File: | tools/clang/lib/CodeGen/CGObjCRuntime.cpp |
Warning: | line 111, column 58 Access to field 'StorageSize' results in a dereference of a null pointer (loaded from variable 'Info') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //==- CGObjCRuntime.cpp - Interface to Shared Objective-C Runtime Features ==// | |||
2 | // | |||
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |||
4 | // See https://llvm.org/LICENSE.txt for license information. | |||
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |||
6 | // | |||
7 | //===----------------------------------------------------------------------===// | |||
8 | // | |||
9 | // This abstract class defines the interface for Objective-C runtime-specific | |||
10 | // code generation. It provides some concrete helper methods for functionality | |||
11 | // shared between all (or most) of the Objective-C runtimes supported by clang. | |||
12 | // | |||
13 | //===----------------------------------------------------------------------===// | |||
14 | ||||
15 | #include "CGObjCRuntime.h" | |||
16 | #include "CGCleanup.h" | |||
17 | #include "CGCXXABI.h" | |||
18 | #include "CGRecordLayout.h" | |||
19 | #include "CodeGenFunction.h" | |||
20 | #include "CodeGenModule.h" | |||
21 | #include "clang/AST/RecordLayout.h" | |||
22 | #include "clang/AST/StmtObjC.h" | |||
23 | #include "clang/CodeGen/CGFunctionInfo.h" | |||
24 | #include "llvm/Support/SaveAndRestore.h" | |||
25 | ||||
26 | using namespace clang; | |||
27 | using namespace CodeGen; | |||
28 | ||||
29 | uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM, | |||
30 | const ObjCInterfaceDecl *OID, | |||
31 | const ObjCIvarDecl *Ivar) { | |||
32 | return CGM.getContext().lookupFieldBitOffset(OID, nullptr, Ivar) / | |||
33 | CGM.getContext().getCharWidth(); | |||
34 | } | |||
35 | ||||
36 | uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM, | |||
37 | const ObjCImplementationDecl *OID, | |||
38 | const ObjCIvarDecl *Ivar) { | |||
39 | return CGM.getContext().lookupFieldBitOffset(OID->getClassInterface(), OID, | |||
40 | Ivar) / | |||
41 | CGM.getContext().getCharWidth(); | |||
42 | } | |||
43 | ||||
44 | unsigned CGObjCRuntime::ComputeBitfieldBitOffset( | |||
45 | CodeGen::CodeGenModule &CGM, | |||
46 | const ObjCInterfaceDecl *ID, | |||
47 | const ObjCIvarDecl *Ivar) { | |||
48 | return CGM.getContext().lookupFieldBitOffset(ID, ID->getImplementation(), | |||
49 | Ivar); | |||
50 | } | |||
51 | ||||
52 | LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, | |||
53 | const ObjCInterfaceDecl *OID, | |||
54 | llvm::Value *BaseValue, | |||
55 | const ObjCIvarDecl *Ivar, | |||
56 | unsigned CVRQualifiers, | |||
57 | llvm::Value *Offset) { | |||
58 | // Compute (type*) ( (char *) BaseValue + Offset) | |||
59 | QualType InterfaceTy{OID->getTypeForDecl(), 0}; | |||
60 | QualType ObjectPtrTy = | |||
61 | CGF.CGM.getContext().getObjCObjectPointerType(InterfaceTy); | |||
62 | QualType IvarTy = | |||
63 | Ivar->getUsageType(ObjectPtrTy).withCVRQualifiers(CVRQualifiers); | |||
64 | llvm::Type *LTy = CGF.CGM.getTypes().ConvertTypeForMem(IvarTy); | |||
65 | llvm::Value *V = CGF.Builder.CreateBitCast(BaseValue, CGF.Int8PtrTy); | |||
66 | V = CGF.Builder.CreateInBoundsGEP(V, Offset, "add.ptr"); | |||
67 | ||||
68 | if (!Ivar->isBitField()) { | |||
| ||||
69 | V = CGF.Builder.CreateBitCast(V, llvm::PointerType::getUnqual(LTy)); | |||
70 | LValue LV = CGF.MakeNaturalAlignAddrLValue(V, IvarTy); | |||
71 | return LV; | |||
72 | } | |||
73 | ||||
74 | // We need to compute an access strategy for this bit-field. We are given the | |||
75 | // offset to the first byte in the bit-field, the sub-byte offset is taken | |||
76 | // from the original layout. We reuse the normal bit-field access strategy by | |||
77 | // treating this as an access to a struct where the bit-field is in byte 0, | |||
78 | // and adjust the containing type size as appropriate. | |||
79 | // | |||
80 | // FIXME: Note that currently we make a very conservative estimate of the | |||
81 | // alignment of the bit-field, because (a) it is not clear what guarantees the | |||
82 | // runtime makes us, and (b) we don't have a way to specify that the struct is | |||
83 | // at an alignment plus offset. | |||
84 | // | |||
85 | // Note, there is a subtle invariant here: we can only call this routine on | |||
86 | // non-synthesized ivars but we may be called for synthesized ivars. However, | |||
87 | // a synthesized ivar can never be a bit-field, so this is safe. | |||
88 | uint64_t FieldBitOffset = | |||
89 | CGF.CGM.getContext().lookupFieldBitOffset(OID, nullptr, Ivar); | |||
90 | uint64_t BitOffset = FieldBitOffset % CGF.CGM.getContext().getCharWidth(); | |||
91 | uint64_t AlignmentBits = CGF.CGM.getTarget().getCharAlign(); | |||
92 | uint64_t BitFieldSize = Ivar->getBitWidthValue(CGF.getContext()); | |||
93 | CharUnits StorageSize = CGF.CGM.getContext().toCharUnitsFromBits( | |||
94 | llvm::alignTo(BitOffset + BitFieldSize, AlignmentBits)); | |||
95 | CharUnits Alignment = CGF.CGM.getContext().toCharUnitsFromBits(AlignmentBits); | |||
96 | ||||
97 | // Allocate a new CGBitFieldInfo object to describe this access. | |||
98 | // | |||
99 | // FIXME: This is incredibly wasteful, these should be uniqued or part of some | |||
100 | // layout object. However, this is blocked on other cleanups to the | |||
101 | // Objective-C code, so for now we just live with allocating a bunch of these | |||
102 | // objects. | |||
103 | CGBitFieldInfo *Info = new (CGF.CGM.getContext()) CGBitFieldInfo( | |||
104 | CGBitFieldInfo::MakeInfo(CGF.CGM.getTypes(), Ivar, BitOffset, BitFieldSize, | |||
105 | CGF.CGM.getContext().toBits(StorageSize), | |||
106 | CharUnits::fromQuantity(0))); | |||
107 | ||||
108 | Address Addr(V, Alignment); | |||
109 | Addr = CGF.Builder.CreateElementBitCast(Addr, | |||
110 | llvm::Type::getIntNTy(CGF.getLLVMContext(), | |||
111 | Info->StorageSize)); | |||
| ||||
112 | return LValue::MakeBitfield(Addr, *Info, IvarTy, | |||
113 | LValueBaseInfo(AlignmentSource::Decl), | |||
114 | TBAAAccessInfo()); | |||
115 | } | |||
116 | ||||
117 | namespace { | |||
118 | struct CatchHandler { | |||
119 | const VarDecl *Variable; | |||
120 | const Stmt *Body; | |||
121 | llvm::BasicBlock *Block; | |||
122 | llvm::Constant *TypeInfo; | |||
123 | /// Flags used to differentiate cleanups and catchalls in Windows SEH | |||
124 | unsigned Flags; | |||
125 | }; | |||
126 | ||||
127 | struct CallObjCEndCatch final : EHScopeStack::Cleanup { | |||
128 | CallObjCEndCatch(bool MightThrow, llvm::FunctionCallee Fn) | |||
129 | : MightThrow(MightThrow), Fn(Fn) {} | |||
130 | bool MightThrow; | |||
131 | llvm::FunctionCallee Fn; | |||
132 | ||||
133 | void Emit(CodeGenFunction &CGF, Flags flags) override { | |||
134 | if (MightThrow) | |||
135 | CGF.EmitRuntimeCallOrInvoke(Fn); | |||
136 | else | |||
137 | CGF.EmitNounwindRuntimeCall(Fn); | |||
138 | } | |||
139 | }; | |||
140 | } | |||
141 | ||||
142 | void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF, | |||
143 | const ObjCAtTryStmt &S, | |||
144 | llvm::FunctionCallee beginCatchFn, | |||
145 | llvm::FunctionCallee endCatchFn, | |||
146 | llvm::FunctionCallee exceptionRethrowFn) { | |||
147 | // Jump destination for falling out of catch bodies. | |||
148 | CodeGenFunction::JumpDest Cont; | |||
149 | if (S.getNumCatchStmts()) | |||
150 | Cont = CGF.getJumpDestInCurrentScope("eh.cont"); | |||
151 | ||||
152 | bool useFunclets = EHPersonality::get(CGF).usesFuncletPads(); | |||
153 | ||||
154 | CodeGenFunction::FinallyInfo FinallyInfo; | |||
155 | if (!useFunclets) | |||
156 | if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt()) | |||
157 | FinallyInfo.enter(CGF, Finally->getFinallyBody(), | |||
158 | beginCatchFn, endCatchFn, exceptionRethrowFn); | |||
159 | ||||
160 | SmallVector<CatchHandler, 8> Handlers; | |||
161 | ||||
162 | ||||
163 | // Enter the catch, if there is one. | |||
164 | if (S.getNumCatchStmts()) { | |||
165 | for (unsigned I = 0, N = S.getNumCatchStmts(); I != N; ++I) { | |||
166 | const ObjCAtCatchStmt *CatchStmt = S.getCatchStmt(I); | |||
167 | const VarDecl *CatchDecl = CatchStmt->getCatchParamDecl(); | |||
168 | ||||
169 | Handlers.push_back(CatchHandler()); | |||
170 | CatchHandler &Handler = Handlers.back(); | |||
171 | Handler.Variable = CatchDecl; | |||
172 | Handler.Body = CatchStmt->getCatchBody(); | |||
173 | Handler.Block = CGF.createBasicBlock("catch"); | |||
174 | Handler.Flags = 0; | |||
175 | ||||
176 | // @catch(...) always matches. | |||
177 | if (!CatchDecl) { | |||
178 | auto catchAll = getCatchAllTypeInfo(); | |||
179 | Handler.TypeInfo = catchAll.RTTI; | |||
180 | Handler.Flags = catchAll.Flags; | |||
181 | // Don't consider any other catches. | |||
182 | break; | |||
183 | } | |||
184 | ||||
185 | Handler.TypeInfo = GetEHType(CatchDecl->getType()); | |||
186 | } | |||
187 | ||||
188 | EHCatchScope *Catch = CGF.EHStack.pushCatch(Handlers.size()); | |||
189 | for (unsigned I = 0, E = Handlers.size(); I != E; ++I) | |||
190 | Catch->setHandler(I, { Handlers[I].TypeInfo, Handlers[I].Flags }, Handlers[I].Block); | |||
191 | } | |||
192 | ||||
193 | if (useFunclets) | |||
194 | if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt()) { | |||
195 | CodeGenFunction HelperCGF(CGM, /*suppressNewContext=*/true); | |||
196 | if (!CGF.CurSEHParent) | |||
197 | CGF.CurSEHParent = cast<NamedDecl>(CGF.CurFuncDecl); | |||
198 | // Outline the finally block. | |||
199 | const Stmt *FinallyBlock = Finally->getFinallyBody(); | |||
200 | HelperCGF.startOutlinedSEHHelper(CGF, /*isFilter*/false, FinallyBlock); | |||
201 | ||||
202 | // Emit the original filter expression, convert to i32, and return. | |||
203 | HelperCGF.EmitStmt(FinallyBlock); | |||
204 | ||||
205 | HelperCGF.FinishFunction(FinallyBlock->getEndLoc()); | |||
206 | ||||
207 | llvm::Function *FinallyFunc = HelperCGF.CurFn; | |||
208 | ||||
209 | ||||
210 | // Push a cleanup for __finally blocks. | |||
211 | CGF.pushSEHCleanup(NormalAndEHCleanup, FinallyFunc); | |||
212 | } | |||
213 | ||||
214 | ||||
215 | // Emit the try body. | |||
216 | CGF.EmitStmt(S.getTryBody()); | |||
217 | ||||
218 | // Leave the try. | |||
219 | if (S.getNumCatchStmts()) | |||
220 | CGF.popCatchScope(); | |||
221 | ||||
222 | // Remember where we were. | |||
223 | CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP(); | |||
224 | ||||
225 | // Emit the handlers. | |||
226 | for (unsigned I = 0, E = Handlers.size(); I != E; ++I) { | |||
227 | CatchHandler &Handler = Handlers[I]; | |||
228 | ||||
229 | CGF.EmitBlock(Handler.Block); | |||
230 | llvm::CatchPadInst *CPI = nullptr; | |||
231 | SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad(CGF.CurrentFuncletPad); | |||
232 | if (useFunclets) | |||
233 | if ((CPI = dyn_cast_or_null<llvm::CatchPadInst>(Handler.Block->getFirstNonPHI()))) { | |||
234 | CGF.CurrentFuncletPad = CPI; | |||
235 | CPI->setOperand(2, CGF.getExceptionSlot().getPointer()); | |||
236 | } | |||
237 | llvm::Value *RawExn = CGF.getExceptionFromSlot(); | |||
238 | ||||
239 | // Enter the catch. | |||
240 | llvm::Value *Exn = RawExn; | |||
241 | if (beginCatchFn) | |||
242 | Exn = CGF.EmitNounwindRuntimeCall(beginCatchFn, RawExn, "exn.adjusted"); | |||
243 | ||||
244 | CodeGenFunction::LexicalScope cleanups(CGF, Handler.Body->getSourceRange()); | |||
245 | ||||
246 | if (endCatchFn) { | |||
247 | // Add a cleanup to leave the catch. | |||
248 | bool EndCatchMightThrow = (Handler.Variable == nullptr); | |||
249 | ||||
250 | CGF.EHStack.pushCleanup<CallObjCEndCatch>(NormalAndEHCleanup, | |||
251 | EndCatchMightThrow, | |||
252 | endCatchFn); | |||
253 | } | |||
254 | ||||
255 | // Bind the catch parameter if it exists. | |||
256 | if (const VarDecl *CatchParam = Handler.Variable) { | |||
257 | llvm::Type *CatchType = CGF.ConvertType(CatchParam->getType()); | |||
258 | llvm::Value *CastExn = CGF.Builder.CreateBitCast(Exn, CatchType); | |||
259 | ||||
260 | CGF.EmitAutoVarDecl(*CatchParam); | |||
261 | EmitInitOfCatchParam(CGF, CastExn, CatchParam); | |||
262 | } | |||
263 | if (CPI) | |||
264 | CGF.EHStack.pushCleanup<CatchRetScope>(NormalCleanup, CPI); | |||
265 | ||||
266 | CGF.ObjCEHValueStack.push_back(Exn); | |||
267 | CGF.EmitStmt(Handler.Body); | |||
268 | CGF.ObjCEHValueStack.pop_back(); | |||
269 | ||||
270 | // Leave any cleanups associated with the catch. | |||
271 | cleanups.ForceCleanup(); | |||
272 | ||||
273 | CGF.EmitBranchThroughCleanup(Cont); | |||
274 | } | |||
275 | ||||
276 | // Go back to the try-statement fallthrough. | |||
277 | CGF.Builder.restoreIP(SavedIP); | |||
278 | ||||
279 | // Pop out of the finally. | |||
280 | if (!useFunclets && S.getFinallyStmt()) | |||
281 | FinallyInfo.exit(CGF); | |||
282 | ||||
283 | if (Cont.isValid()) | |||
284 | CGF.EmitBlock(Cont.getBlock()); | |||
285 | } | |||
286 | ||||
287 | void CGObjCRuntime::EmitInitOfCatchParam(CodeGenFunction &CGF, | |||
288 | llvm::Value *exn, | |||
289 | const VarDecl *paramDecl) { | |||
290 | ||||
291 | Address paramAddr = CGF.GetAddrOfLocalVar(paramDecl); | |||
292 | ||||
293 | switch (paramDecl->getType().getQualifiers().getObjCLifetime()) { | |||
294 | case Qualifiers::OCL_Strong: | |||
295 | exn = CGF.EmitARCRetainNonBlock(exn); | |||
296 | LLVM_FALLTHROUGH[[clang::fallthrough]]; | |||
297 | ||||
298 | case Qualifiers::OCL_None: | |||
299 | case Qualifiers::OCL_ExplicitNone: | |||
300 | case Qualifiers::OCL_Autoreleasing: | |||
301 | CGF.Builder.CreateStore(exn, paramAddr); | |||
302 | return; | |||
303 | ||||
304 | case Qualifiers::OCL_Weak: | |||
305 | CGF.EmitARCInitWeak(paramAddr, exn); | |||
306 | return; | |||
307 | } | |||
308 | llvm_unreachable("invalid ownership qualifier")::llvm::llvm_unreachable_internal("invalid ownership qualifier" , "/build/llvm-toolchain-snapshot-9~svn360825/tools/clang/lib/CodeGen/CGObjCRuntime.cpp" , 308); | |||
309 | } | |||
310 | ||||
311 | namespace { | |||
312 | struct CallSyncExit final : EHScopeStack::Cleanup { | |||
313 | llvm::FunctionCallee SyncExitFn; | |||
314 | llvm::Value *SyncArg; | |||
315 | CallSyncExit(llvm::FunctionCallee SyncExitFn, llvm::Value *SyncArg) | |||
316 | : SyncExitFn(SyncExitFn), SyncArg(SyncArg) {} | |||
317 | ||||
318 | void Emit(CodeGenFunction &CGF, Flags flags) override { | |||
319 | CGF.EmitNounwindRuntimeCall(SyncExitFn, SyncArg); | |||
320 | } | |||
321 | }; | |||
322 | } | |||
323 | ||||
324 | void CGObjCRuntime::EmitAtSynchronizedStmt(CodeGenFunction &CGF, | |||
325 | const ObjCAtSynchronizedStmt &S, | |||
326 | llvm::FunctionCallee syncEnterFn, | |||
327 | llvm::FunctionCallee syncExitFn) { | |||
328 | CodeGenFunction::RunCleanupsScope cleanups(CGF); | |||
329 | ||||
330 | // Evaluate the lock operand. This is guaranteed to dominate the | |||
331 | // ARC release and lock-release cleanups. | |||
332 | const Expr *lockExpr = S.getSynchExpr(); | |||
333 | llvm::Value *lock; | |||
334 | if (CGF.getLangOpts().ObjCAutoRefCount) { | |||
335 | lock = CGF.EmitARCRetainScalarExpr(lockExpr); | |||
336 | lock = CGF.EmitObjCConsumeObject(lockExpr->getType(), lock); | |||
337 | } else { | |||
338 | lock = CGF.EmitScalarExpr(lockExpr); | |||
339 | } | |||
340 | lock = CGF.Builder.CreateBitCast(lock, CGF.VoidPtrTy); | |||
341 | ||||
342 | // Acquire the lock. | |||
343 | CGF.Builder.CreateCall(syncEnterFn, lock)->setDoesNotThrow(); | |||
344 | ||||
345 | // Register an all-paths cleanup to release the lock. | |||
346 | CGF.EHStack.pushCleanup<CallSyncExit>(NormalAndEHCleanup, syncExitFn, lock); | |||
347 | ||||
348 | // Emit the body of the statement. | |||
349 | CGF.EmitStmt(S.getSynchBody()); | |||
350 | } | |||
351 | ||||
352 | /// Compute the pointer-to-function type to which a message send | |||
353 | /// should be casted in order to correctly call the given method | |||
354 | /// with the given arguments. | |||
355 | /// | |||
356 | /// \param method - may be null | |||
357 | /// \param resultType - the result type to use if there's no method | |||
358 | /// \param callArgs - the actual arguments, including implicit ones | |||
359 | CGObjCRuntime::MessageSendInfo | |||
360 | CGObjCRuntime::getMessageSendInfo(const ObjCMethodDecl *method, | |||
361 | QualType resultType, | |||
362 | CallArgList &callArgs) { | |||
363 | // If there's a method, use information from that. | |||
364 | if (method) { | |||
365 | const CGFunctionInfo &signature = | |||
366 | CGM.getTypes().arrangeObjCMessageSendSignature(method, callArgs[0].Ty); | |||
367 | ||||
368 | llvm::PointerType *signatureType = | |||
369 | CGM.getTypes().GetFunctionType(signature)->getPointerTo(); | |||
370 | ||||
371 | const CGFunctionInfo &signatureForCall = | |||
372 | CGM.getTypes().arrangeCall(signature, callArgs); | |||
373 | ||||
374 | return MessageSendInfo(signatureForCall, signatureType); | |||
375 | } | |||
376 | ||||
377 | // There's no method; just use a default CC. | |||
378 | const CGFunctionInfo &argsInfo = | |||
379 | CGM.getTypes().arrangeUnprototypedObjCMessageSend(resultType, callArgs); | |||
380 | ||||
381 | // Derive the signature to call from that. | |||
382 | llvm::PointerType *signatureType = | |||
383 | CGM.getTypes().GetFunctionType(argsInfo)->getPointerTo(); | |||
384 | return MessageSendInfo(argsInfo, signatureType); | |||
385 | } |