 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
72.8% |
587 / 806 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
88.8% |
716 / 806 |
| |
|
Line Coverage: |
91.2% |
1931 / 2117 |
| |
 |
|
 |
1 : //===------- CGObjCMac.cpp - Interface to Apple Objective-C Runtime -------===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 : //
10 : // This provides Objective-C code generation targetting the Apple runtime.
11 : //
12 : //===----------------------------------------------------------------------===//
13 :
14 : #include "CGObjCRuntime.h"
15 :
16 : #include "CodeGenModule.h"
17 : #include "CodeGenFunction.h"
18 : #include "clang/AST/ASTContext.h"
19 : #include "clang/AST/Decl.h"
20 : #include "clang/AST/DeclObjC.h"
21 : #include "clang/AST/RecordLayout.h"
22 : #include "clang/AST/StmtObjC.h"
23 : #include "clang/Basic/LangOptions.h"
24 : #include "clang/CodeGen/CodeGenOptions.h"
25 :
26 : #include "llvm/Intrinsics.h"
27 : #include "llvm/LLVMContext.h"
28 : #include "llvm/Module.h"
29 : #include "llvm/ADT/DenseSet.h"
30 : #include "llvm/ADT/SetVector.h"
31 : #include "llvm/ADT/SmallString.h"
32 : #include "llvm/ADT/SmallPtrSet.h"
33 : #include "llvm/Support/raw_ostream.h"
34 : #include "llvm/Target/TargetData.h"
35 : #include <cstdio>
36 :
37 : using namespace clang;
38 : using namespace CodeGen;
39 :
40 : // Common CGObjCRuntime functions, these don't belong here, but they
41 : // don't belong in CGObjCRuntime either so we will live with it for
42 : // now.
43 :
44 : /// FindIvarInterface - Find the interface containing the ivar.
45 : ///
46 : /// FIXME: We shouldn't need to do this, the containing context should
47 : /// be fixed.
48 : static const ObjCInterfaceDecl *FindIvarInterface(ASTContext &Context,
49 : const ObjCInterfaceDecl *OID,
50 : const ObjCIvarDecl *OIVD,
51 843: unsigned &Index) {
52 : // FIXME: The index here is closely tied to how
53 : // ASTContext::getObjCLayout is implemented. This should be fixed to
54 : // get the information from the layout directly.
55 843: Index = 0;
56 843: llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
57 843: Context.ShallowCollectObjCIvars(OID, Ivars);
2906: branch 1 taken
85: branch 2 taken
58 2991: for (unsigned k = 0, e = Ivars.size(); k != e; ++k) {
758: branch 1 taken
2148: branch 2 taken
59 2906: if (OIVD == Ivars[k])
60 758: return OID;
61 2148: ++Index;
62 : }
63 :
64 : // Otherwise check in the super class.
85: branch 1 taken
0: branch 2 not taken
65 85: if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
66 85: return FindIvarInterface(Context, Super, OIVD, Index);
67 :
68 0: return 0;
69 : }
70 :
71 : static uint64_t LookupFieldBitOffset(CodeGen::CodeGenModule &CGM,
72 : const ObjCInterfaceDecl *OID,
73 : const ObjCImplementationDecl *ID,
74 642: const ObjCIvarDecl *Ivar) {
75 : unsigned Index;
76 : const ObjCInterfaceDecl *Container =
77 642: FindIvarInterface(CGM.getContext(), OID, Ivar, Index);
0: branch 0 not taken
642: branch 1 taken
78 642: assert(Container && "Unable to find ivar container");
79 :
80 : // If we know have an implementation (and the ivar is in it) then
81 : // look up in the implementation layout.
82 : const ASTRecordLayout *RL;
176: branch 0 taken
466: branch 1 taken
154: branch 3 taken
22: branch 4 taken
154: branch 5 taken
488: branch 6 taken
83 642: if (ID && ID->getClassInterface() == Container)
84 154: RL = &CGM.getContext().getASTObjCImplementationLayout(ID);
85 : else
86 488: RL = &CGM.getContext().getASTObjCInterfaceLayout(Container);
87 642: return RL->getFieldOffset(Index);
88 : }
89 :
90 : uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,
91 : const ObjCInterfaceDecl *OID,
92 410: const ObjCIvarDecl *Ivar) {
93 410: return LookupFieldBitOffset(CGM, OID, 0, Ivar) / 8;
94 : }
95 :
96 : uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,
97 : const ObjCImplementationDecl *OID,
98 176: const ObjCIvarDecl *Ivar) {
99 176: return LookupFieldBitOffset(CGM, OID->getClassInterface(), OID, Ivar) / 8;
100 : }
101 :
102 : LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
103 : const ObjCInterfaceDecl *OID,
104 : llvm::Value *BaseValue,
105 : const ObjCIvarDecl *Ivar,
106 : unsigned CVRQualifiers,
107 293: llvm::Value *Offset) {
108 : // Compute (type*) ( (char *) BaseValue + Offset)
109 293: const llvm::Type *I8Ptr = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
110 293: QualType IvarTy = Ivar->getType();
111 293: const llvm::Type *LTy = CGF.CGM.getTypes().ConvertTypeForMem(IvarTy);
112 293: llvm::Value *V = CGF.Builder.CreateBitCast(BaseValue, I8Ptr);
113 293: V = CGF.Builder.CreateGEP(V, Offset, "add.ptr");
114 293: V = CGF.Builder.CreateBitCast(V, llvm::PointerType::getUnqual(LTy));
115 :
116 293: Qualifiers Quals = CGF.MakeQualifiers(IvarTy);
117 293: Quals.addCVRQualifiers(CVRQualifiers);
118 :
56: branch 1 taken
237: branch 2 taken
119 293: if (Ivar->isBitField()) {
120 : // We need to compute the bit offset for the bit-field, the offset
121 : // is to the byte. Note, there is a subtle invariant here: we can
122 : // only call this routine on non-sythesized ivars but we may be
123 : // called for synthesized ivars. However, a synthesized ivar can
124 : // never be a bit-field so this is safe.
125 56: uint64_t BitOffset = LookupFieldBitOffset(CGF.CGM, OID, 0, Ivar) % 8;
126 :
127 : uint64_t BitFieldSize =
128 56: Ivar->getBitWidth()->EvaluateAsInt(CGF.getContext()).getZExtValue();
129 : return LValue::MakeBitfield(V, BitOffset, BitFieldSize,
130 : IvarTy->isSignedIntegerType(),
131 56: Quals.getCVRQualifiers());
132 : }
133 :
134 :
135 237: LValue LV = LValue::MakeAddr(V, Quals);
136 237: return LV;
137 : }
138 :
139 : ///
140 :
141 : namespace {
142 :
143 : typedef std::vector<llvm::Constant*> ConstantVector;
144 :
145 : // FIXME: We should find a nicer way to make the labels for metadata, string
146 : // concatenation is lame.
147 :
148 : class ObjCCommonTypesHelper {
149 : protected:
150 : llvm::LLVMContext &VMContext;
151 :
152 : private:
153 167: llvm::Constant *getMessageSendFn() const {
154 : // id objc_msgSend (id, SEL, ...)
155 167: std::vector<const llvm::Type*> Params;
156 167: Params.push_back(ObjectPtrTy);
157 167: Params.push_back(SelectorPtrTy);
158 : return
159 : CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
160 : Params, true),
161 167: "objc_msgSend");
162 : }
163 :
164 6: llvm::Constant *getMessageSendStretFn() const {
165 : // id objc_msgSend_stret (id, SEL, ...)
166 6: std::vector<const llvm::Type*> Params;
167 6: Params.push_back(ObjectPtrTy);
168 6: Params.push_back(SelectorPtrTy);
169 : return
170 : CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
171 : Params, true),
172 6: "objc_msgSend_stret");
173 :
174 : }
175 :
176 9: llvm::Constant *getMessageSendFpretFn() const {
177 : // FIXME: This should be long double on x86_64?
178 : // [double | long double] objc_msgSend_fpret(id self, SEL op, ...)
179 9: std::vector<const llvm::Type*> Params;
180 9: Params.push_back(ObjectPtrTy);
181 9: Params.push_back(SelectorPtrTy);
182 : return
183 : CGM.CreateRuntimeFunction(llvm::FunctionType::get(
184 : llvm::Type::getDoubleTy(VMContext),
185 : Params,
186 : true),
187 9: "objc_msgSend_fpret");
188 :
189 : }
190 :
191 29: llvm::Constant *getMessageSendSuperFn() const {
192 : // id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
193 29: const char *SuperName = "objc_msgSendSuper";
194 29: std::vector<const llvm::Type*> Params;
195 29: Params.push_back(SuperPtrTy);
196 29: Params.push_back(SelectorPtrTy);
197 : return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
198 : Params, true),
199 29: SuperName);
200 : }
201 :
202 2: llvm::Constant *getMessageSendSuperFn2() const {
203 : // id objc_msgSendSuper2(struct objc_super *super, SEL op, ...)
204 2: const char *SuperName = "objc_msgSendSuper2";
205 2: std::vector<const llvm::Type*> Params;
206 2: Params.push_back(SuperPtrTy);
207 2: Params.push_back(SelectorPtrTy);
208 : return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
209 : Params, true),
210 2: SuperName);
211 : }
212 :
213 4: llvm::Constant *getMessageSendSuperStretFn() const {
214 : // void objc_msgSendSuper_stret(void * stretAddr, struct objc_super *super,
215 : // SEL op, ...)
216 4: std::vector<const llvm::Type*> Params;
217 4: Params.push_back(Int8PtrTy);
218 4: Params.push_back(SuperPtrTy);
219 4: Params.push_back(SelectorPtrTy);
220 : return CGM.CreateRuntimeFunction(
221 : llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
222 : Params, true),
223 4: "objc_msgSendSuper_stret");
224 : }
225 :
226 0: llvm::Constant *getMessageSendSuperStretFn2() const {
227 : // void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super,
228 : // SEL op, ...)
229 0: std::vector<const llvm::Type*> Params;
230 0: Params.push_back(Int8PtrTy);
231 0: Params.push_back(SuperPtrTy);
232 0: Params.push_back(SelectorPtrTy);
233 : return CGM.CreateRuntimeFunction(
234 : llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
235 : Params, true),
236 0: "objc_msgSendSuper2_stret");
237 : }
238 :
239 4: llvm::Constant *getMessageSendSuperFpretFn() const {
240 : // There is no objc_msgSendSuper_fpret? How can that work?
241 4: return getMessageSendSuperFn();
242 : }
243 :
244 0: llvm::Constant *getMessageSendSuperFpretFn2() const {
245 : // There is no objc_msgSendSuper_fpret? How can that work?
246 0: return getMessageSendSuperFn2();
247 : }
248 :
249 : protected:
250 : CodeGen::CodeGenModule &CGM;
251 :
252 : public:
253 : const llvm::Type *ShortTy, *IntTy, *LongTy, *LongLongTy;
254 : const llvm::Type *Int8PtrTy;
255 :
256 : /// ObjectPtrTy - LLVM type for object handles (typeof(id))
257 : const llvm::Type *ObjectPtrTy;
258 :
259 : /// PtrObjectPtrTy - LLVM type for id *
260 : const llvm::Type *PtrObjectPtrTy;
261 :
262 : /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
263 : const llvm::Type *SelectorPtrTy;
264 : /// ProtocolPtrTy - LLVM type for external protocol handles
265 : /// (typeof(Protocol))
266 : const llvm::Type *ExternalProtocolPtrTy;
267 :
268 : // SuperCTy - clang type for struct objc_super.
269 : QualType SuperCTy;
270 : // SuperPtrCTy - clang type for struct objc_super *.
271 : QualType SuperPtrCTy;
272 :
273 : /// SuperTy - LLVM type for struct objc_super.
274 : const llvm::StructType *SuperTy;
275 : /// SuperPtrTy - LLVM type for struct objc_super *.
276 : const llvm::Type *SuperPtrTy;
277 :
278 : /// PropertyTy - LLVM type for struct objc_property (struct _prop_t
279 : /// in GCC parlance).
280 : const llvm::StructType *PropertyTy;
281 :
282 : /// PropertyListTy - LLVM type for struct objc_property_list
283 : /// (_prop_list_t in GCC parlance).
284 : const llvm::StructType *PropertyListTy;
285 : /// PropertyListPtrTy - LLVM type for struct objc_property_list*.
286 : const llvm::Type *PropertyListPtrTy;
287 :
288 : // MethodTy - LLVM type for struct objc_method.
289 : const llvm::StructType *MethodTy;
290 :
291 : /// CacheTy - LLVM type for struct objc_cache.
292 : const llvm::Type *CacheTy;
293 : /// CachePtrTy - LLVM type for struct objc_cache *.
294 : const llvm::Type *CachePtrTy;
295 :
296 8: llvm::Constant *getGetPropertyFn() {
297 8: CodeGen::CodeGenTypes &Types = CGM.getTypes();
298 8: ASTContext &Ctx = CGM.getContext();
299 : // id objc_getProperty (id, SEL, ptrdiff_t, bool)
300 8: llvm::SmallVector<QualType,16> Params;
301 8: QualType IdType = Ctx.getObjCIdType();
302 8: QualType SelType = Ctx.getObjCSelType();
303 8: Params.push_back(IdType);
304 8: Params.push_back(SelType);
305 8: Params.push_back(Ctx.LongTy);
306 8: Params.push_back(Ctx.BoolTy);
307 : const llvm::FunctionType *FTy =
308 : Types.GetFunctionType(Types.getFunctionInfo(IdType, Params,
309 8: CC_Default, false), false);
310 8: return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
311 : }
312 :
313 10: llvm::Constant *getSetPropertyFn() {
314 10: CodeGen::CodeGenTypes &Types = CGM.getTypes();
315 10: ASTContext &Ctx = CGM.getContext();
316 : // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
317 10: llvm::SmallVector<QualType,16> Params;
318 10: QualType IdType = Ctx.getObjCIdType();
319 10: QualType SelType = Ctx.getObjCSelType();
320 10: Params.push_back(IdType);
321 10: Params.push_back(SelType);
322 10: Params.push_back(Ctx.LongTy);
323 10: Params.push_back(IdType);
324 10: Params.push_back(Ctx.BoolTy);
325 10: Params.push_back(Ctx.BoolTy);
326 : const llvm::FunctionType *FTy =
327 : Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
328 10: CC_Default, false), false);
329 10: return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
330 : }
331 :
332 4: llvm::Constant *getEnumerationMutationFn() {
333 4: CodeGen::CodeGenTypes &Types = CGM.getTypes();
334 4: ASTContext &Ctx = CGM.getContext();
335 : // void objc_enumerationMutation (id)
336 4: llvm::SmallVector<QualType,16> Params;
337 4: Params.push_back(Ctx.getObjCIdType());
338 : const llvm::FunctionType *FTy =
339 : Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
340 4: CC_Default, false), false);
341 4: return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
342 : }
343 :
344 : /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
345 15: llvm::Constant *getGcReadWeakFn() {
346 : // id objc_read_weak (id *)
347 15: std::vector<const llvm::Type*> Args;
348 15: Args.push_back(ObjectPtrTy->getPointerTo());
349 : llvm::FunctionType *FTy =
350 15: llvm::FunctionType::get(ObjectPtrTy, Args, false);
351 15: return CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
352 : }
353 :
354 : /// GcAssignWeakFn -- LLVM objc_assign_weak function.
355 11: llvm::Constant *getGcAssignWeakFn() {
356 : // id objc_assign_weak (id, id *)
357 11: std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
358 11: Args.push_back(ObjectPtrTy->getPointerTo());
359 : llvm::FunctionType *FTy =
360 11: llvm::FunctionType::get(ObjectPtrTy, Args, false);
361 11: return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
362 : }
363 :
364 : /// GcAssignGlobalFn -- LLVM objc_assign_global function.
365 53: llvm::Constant *getGcAssignGlobalFn() {
366 : // id objc_assign_global(id, id *)
367 53: std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
368 53: Args.push_back(ObjectPtrTy->getPointerTo());
369 : llvm::FunctionType *FTy =
370 53: llvm::FunctionType::get(ObjectPtrTy, Args, false);
371 53: return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
372 : }
373 :
374 : /// GcAssignIvarFn -- LLVM objc_assign_ivar function.
375 36: llvm::Constant *getGcAssignIvarFn() {
376 : // id objc_assign_ivar(id, id *, ptrdiff_t)
377 36: std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
378 36: Args.push_back(ObjectPtrTy->getPointerTo());
379 36: Args.push_back(LongTy);
380 : llvm::FunctionType *FTy =
381 36: llvm::FunctionType::get(ObjectPtrTy, Args, false);
382 36: return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
383 : }
384 :
385 : /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function.
386 5: llvm::Constant *GcMemmoveCollectableFn() {
387 : // void *objc_memmove_collectable(void *dst, const void *src, size_t size)
388 5: std::vector<const llvm::Type*> Args(1, Int8PtrTy);
389 5: Args.push_back(Int8PtrTy);
390 5: Args.push_back(LongTy);
391 5: llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args, false);
392 5: return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable");
393 : }
394 :
395 : /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
396 22: llvm::Constant *getGcAssignStrongCastFn() {
397 : // id objc_assign_global(id, id *)
398 22: std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
399 22: Args.push_back(ObjectPtrTy->getPointerTo());
400 : llvm::FunctionType *FTy =
401 22: llvm::FunctionType::get(ObjectPtrTy, Args, false);
402 22: return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
403 : }
404 :
405 : /// ExceptionThrowFn - LLVM objc_exception_throw function.
406 21: llvm::Constant *getExceptionThrowFn() {
407 : // void objc_exception_throw(id)
408 21: std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
409 : llvm::FunctionType *FTy =
410 21: llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
411 21: return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
412 : }
413 :
414 : /// SyncEnterFn - LLVM object_sync_enter function.
415 7: llvm::Constant *getSyncEnterFn() {
416 : // void objc_sync_enter (id)
417 7: std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
418 : llvm::FunctionType *FTy =
419 7: llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
420 7: return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
421 : }
422 :
423 : /// SyncExitFn - LLVM object_sync_exit function.
424 7: llvm::Constant *getSyncExitFn() {
425 : // void objc_sync_exit (id)
426 7: std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
427 : llvm::FunctionType *FTy =
428 7: llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
429 7: return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
430 : }
431 :
432 177: llvm::Constant *getSendFn(bool IsSuper) const {
25: branch 0 taken
152: branch 1 taken
433 177: return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
434 : }
435 :
436 17: llvm::Constant *getSendFn2(bool IsSuper) const {
2: branch 0 taken
15: branch 1 taken
437 17: return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
438 : }
439 :
440 10: llvm::Constant *getSendStretFn(bool IsSuper) const {
4: branch 0 taken
6: branch 1 taken
441 10: return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
442 : }
443 :
444 0: llvm::Constant *getSendStretFn2(bool IsSuper) const {
0: branch 0 not taken
0: branch 1 not taken
445 0: return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
446 : }
447 :
448 12: llvm::Constant *getSendFpretFn(bool IsSuper) const {
4: branch 0 taken
8: branch 1 taken
449 12: return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
450 : }
451 :
452 1: llvm::Constant *getSendFpretFn2(bool IsSuper) const {
0: branch 0 not taken
1: branch 1 taken
453 1: return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
454 : }
455 :
456 : ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
457 129: ~ObjCCommonTypesHelper(){}
458 : };
459 :
460 : /// ObjCTypesHelper - Helper class that encapsulates lazy
461 : /// construction of varies types used during ObjC generation.
462 : class ObjCTypesHelper : public ObjCCommonTypesHelper {
463 : public:
464 : /// SymtabTy - LLVM type for struct objc_symtab.
465 : const llvm::StructType *SymtabTy;
466 : /// SymtabPtrTy - LLVM type for struct objc_symtab *.
467 : const llvm::Type *SymtabPtrTy;
468 : /// ModuleTy - LLVM type for struct objc_module.
469 : const llvm::StructType *ModuleTy;
470 :
471 : /// ProtocolTy - LLVM type for struct objc_protocol.
472 : const llvm::StructType *ProtocolTy;
473 : /// ProtocolPtrTy - LLVM type for struct objc_protocol *.
474 : const llvm::Type *ProtocolPtrTy;
475 : /// ProtocolExtensionTy - LLVM type for struct
476 : /// objc_protocol_extension.
477 : const llvm::StructType *ProtocolExtensionTy;
478 : /// ProtocolExtensionTy - LLVM type for struct
479 : /// objc_protocol_extension *.
480 : const llvm::Type *ProtocolExtensionPtrTy;
481 : /// MethodDescriptionTy - LLVM type for struct
482 : /// objc_method_description.
483 : const llvm::StructType *MethodDescriptionTy;
484 : /// MethodDescriptionListTy - LLVM type for struct
485 : /// objc_method_description_list.
486 : const llvm::StructType *MethodDescriptionListTy;
487 : /// MethodDescriptionListPtrTy - LLVM type for struct
488 : /// objc_method_description_list *.
489 : const llvm::Type *MethodDescriptionListPtrTy;
490 : /// ProtocolListTy - LLVM type for struct objc_property_list.
491 : const llvm::Type *ProtocolListTy;
492 : /// ProtocolListPtrTy - LLVM type for struct objc_property_list*.
493 : const llvm::Type *ProtocolListPtrTy;
494 : /// CategoryTy - LLVM type for struct objc_category.
495 : const llvm::StructType *CategoryTy;
496 : /// ClassTy - LLVM type for struct objc_class.
497 : const llvm::StructType *ClassTy;
498 : /// ClassPtrTy - LLVM type for struct objc_class *.
499 : const llvm::Type *ClassPtrTy;
500 : /// ClassExtensionTy - LLVM type for struct objc_class_ext.
501 : const llvm::StructType *ClassExtensionTy;
502 : /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *.
503 : const llvm::Type *ClassExtensionPtrTy;
504 : // IvarTy - LLVM type for struct objc_ivar.
505 : const llvm::StructType *IvarTy;
506 : /// IvarListTy - LLVM type for struct objc_ivar_list.
507 : const llvm::Type *IvarListTy;
508 : /// IvarListPtrTy - LLVM type for struct objc_ivar_list *.
509 : const llvm::Type *IvarListPtrTy;
510 : /// MethodListTy - LLVM type for struct objc_method_list.
511 : const llvm::Type *MethodListTy;
512 : /// MethodListPtrTy - LLVM type for struct objc_method_list *.
513 : const llvm::Type *MethodListPtrTy;
514 :
515 : /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
516 : const llvm::Type *ExceptionDataTy;
517 :
518 : /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
519 22: llvm::Constant *getExceptionTryEnterFn() {
520 22: std::vector<const llvm::Type*> Params;
521 22: Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
522 : return CGM.CreateRuntimeFunction(
523 : llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
524 : Params, false),
525 22: "objc_exception_try_enter");
526 : }
527 :
528 : /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
529 15: llvm::Constant *getExceptionTryExitFn() {
530 15: std::vector<const llvm::Type*> Params;
531 15: Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
532 : return CGM.CreateRuntimeFunction(
533 : llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
534 : Params, false),
535 15: "objc_exception_try_exit");
536 : }
537 :
538 : /// ExceptionExtractFn - LLVM objc_exception_extract function.
539 22: llvm::Constant *getExceptionExtractFn() {
540 22: std::vector<const llvm::Type*> Params;
541 22: Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
542 : return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
543 : Params, false),
544 22: "objc_exception_extract");
545 :
546 : }
547 :
548 : /// ExceptionMatchFn - LLVM objc_exception_match function.
549 4: llvm::Constant *getExceptionMatchFn() {
550 4: std::vector<const llvm::Type*> Params;
551 4: Params.push_back(ClassPtrTy);
552 4: Params.push_back(ObjectPtrTy);
553 : return CGM.CreateRuntimeFunction(
554 : llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext),
555 : Params, false),
556 4: "objc_exception_match");
557 :
558 : }
559 :
560 : /// SetJmpFn - LLVM _setjmp function.
561 22: llvm::Constant *getSetJmpFn() {
562 22: std::vector<const llvm::Type*> Params;
563 22: Params.push_back(llvm::Type::getInt32PtrTy(VMContext));
564 : return
565 : CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext),
566 : Params, false),
567 22: "_setjmp");
568 :
569 : }
570 :
571 : public:
572 : ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
573 110: ~ObjCTypesHelper() {}
574 : };
575 :
576 : /// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
577 : /// modern abi
578 : class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
579 : public:
580 :
581 : // MethodListnfABITy - LLVM for struct _method_list_t
582 : const llvm::StructType *MethodListnfABITy;
583 :
584 : // MethodListnfABIPtrTy - LLVM for struct _method_list_t*
585 : const llvm::Type *MethodListnfABIPtrTy;
586 :
587 : // ProtocolnfABITy = LLVM for struct _protocol_t
588 : const llvm::StructType *ProtocolnfABITy;
589 :
590 : // ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
591 : const llvm::Type *ProtocolnfABIPtrTy;
592 :
593 : // ProtocolListnfABITy - LLVM for struct _objc_protocol_list
594 : const llvm::StructType *ProtocolListnfABITy;
595 :
596 : // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
597 : const llvm::Type *ProtocolListnfABIPtrTy;
598 :
599 : // ClassnfABITy - LLVM for struct _class_t
600 : const llvm::StructType *ClassnfABITy;
601 :
602 : // ClassnfABIPtrTy - LLVM for struct _class_t*
603 : const llvm::Type *ClassnfABIPtrTy;
604 :
605 : // IvarnfABITy - LLVM for struct _ivar_t
606 : const llvm::StructType *IvarnfABITy;
607 :
608 : // IvarListnfABITy - LLVM for struct _ivar_list_t
609 : const llvm::StructType *IvarListnfABITy;
610 :
611 : // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
612 : const llvm::Type *IvarListnfABIPtrTy;
613 :
614 : // ClassRonfABITy - LLVM for struct _class_ro_t
615 : const llvm::StructType *ClassRonfABITy;
616 :
617 : // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
618 : const llvm::Type *ImpnfABITy;
619 :
620 : // CategorynfABITy - LLVM for struct _category_t
621 : const llvm::StructType *CategorynfABITy;
622 :
623 : // New types for nonfragile abi messaging.
624 :
625 : // MessageRefTy - LLVM for:
626 : // struct _message_ref_t {
627 : // IMP messenger;
628 : // SEL name;
629 : // };
630 : const llvm::StructType *MessageRefTy;
631 : // MessageRefCTy - clang type for struct _message_ref_t
632 : QualType MessageRefCTy;
633 :
634 : // MessageRefPtrTy - LLVM for struct _message_ref_t*
635 : const llvm::Type *MessageRefPtrTy;
636 : // MessageRefCPtrTy - clang type for struct _message_ref_t*
637 : QualType MessageRefCPtrTy;
638 :
639 : // MessengerTy - Type of the messenger (shown as IMP above)
640 : const llvm::FunctionType *MessengerTy;
641 :
642 : // SuperMessageRefTy - LLVM for:
643 : // struct _super_message_ref_t {
644 : // SUPER_IMP messenger;
645 : // SEL name;
646 : // };
647 : const llvm::StructType *SuperMessageRefTy;
648 :
649 : // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
650 : const llvm::Type *SuperMessageRefPtrTy;
651 :
652 2: llvm::Constant *getMessageSendFixupFn() {
653 : // id objc_msgSend_fixup(id, struct message_ref_t*, ...)
654 2: std::vector<const llvm::Type*> Params;
655 2: Params.push_back(ObjectPtrTy);
656 2: Params.push_back(MessageRefPtrTy);
657 : return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
658 : Params, true),
659 2: "objc_msgSend_fixup");
660 : }
661 :
662 0: llvm::Constant *getMessageSendFpretFixupFn() {
663 : // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...)
664 0: std::vector<const llvm::Type*> Params;
665 0: Params.push_back(ObjectPtrTy);
666 0: Params.push_back(MessageRefPtrTy);
667 : return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
668 : Params, true),
669 0: "objc_msgSend_fpret_fixup");
670 : }
671 :
672 0: llvm::Constant *getMessageSendStretFixupFn() {
673 : // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...)
674 0: std::vector<const llvm::Type*> Params;
675 0: Params.push_back(ObjectPtrTy);
676 0: Params.push_back(MessageRefPtrTy);
677 : return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
678 : Params, true),
679 0: "objc_msgSend_stret_fixup");
680 : }
681 :
682 : llvm::Constant *getMessageSendIdFixupFn() {
683 : // id objc_msgSendId_fixup(id, struct message_ref_t*, ...)
684 : std::vector<const llvm::Type*> Params;
685 : Params.push_back(ObjectPtrTy);
686 : Params.push_back(MessageRefPtrTy);
687 : return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
688 : Params, true),
689 : "objc_msgSendId_fixup");
690 : }
691 :
692 : llvm::Constant *getMessageSendIdStretFixupFn() {
693 : // id objc_msgSendId_stret_fixup(id, struct message_ref_t*, ...)
694 : std::vector<const llvm::Type*> Params;
695 : Params.push_back(ObjectPtrTy);
696 : Params.push_back(MessageRefPtrTy);
697 : return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
698 : Params, true),
699 : "objc_msgSendId_stret_fixup");
700 : }
701 0: llvm::Constant *getMessageSendSuper2FixupFn() {
702 : // id objc_msgSendSuper2_fixup (struct objc_super *,
703 : // struct _super_message_ref_t*, ...)
704 0: std::vector<const llvm::Type*> Params;
705 0: Params.push_back(SuperPtrTy);
706 0: Params.push_back(SuperMessageRefPtrTy);
707 : return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
708 : Params, true),
709 0: "objc_msgSendSuper2_fixup");
710 : }
711 :
712 0: llvm::Constant *getMessageSendSuper2StretFixupFn() {
713 : // id objc_msgSendSuper2_stret_fixup(struct objc_super *,
714 : // struct _super_message_ref_t*, ...)
715 0: std::vector<const llvm::Type*> Params;
716 0: Params.push_back(SuperPtrTy);
717 0: Params.push_back(SuperMessageRefPtrTy);
718 : return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
719 : Params, true),
720 0: "objc_msgSendSuper2_stret_fixup");
721 : }
722 :
723 :
724 :
725 : /// EHPersonalityPtr - LLVM value for an i8* to the Objective-C
726 : /// exception personality function.
727 14: llvm::Value *getEHPersonalityPtr() {
728 : llvm::Constant *Personality =
729 : CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext),
730 : true),
731 14: "__objc_personality_v0");
732 14: return llvm::ConstantExpr::getBitCast(Personality, Int8PtrTy);
733 : }
734 :
735 2: llvm::Constant *getUnwindResumeOrRethrowFn() {
736 2: std::vector<const llvm::Type*> Params;
737 2: Params.push_back(Int8PtrTy);
738 : return CGM.CreateRuntimeFunction(
739 : llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
740 : Params, false),
741 2: "_Unwind_Resume_or_Rethrow");
742 : }
743 :
744 6: llvm::Constant *getObjCEndCatchFn() {
745 : return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
746 : false),
747 6: "objc_end_catch");
748 :
749 : }
750 :
751 6: llvm::Constant *getObjCBeginCatchFn() {
752 6: std::vector<const llvm::Type*> Params;
753 6: Params.push_back(Int8PtrTy);
754 : return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy,
755 : Params, false),
756 6: "objc_begin_catch");
757 : }
758 :
759 : const llvm::StructType *EHTypeTy;
760 : const llvm::Type *EHTypePtrTy;
761 :
762 : ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
763 19: ~ObjCNonFragileABITypesHelper(){}
764 : };
765 :
0: branch 18 not taken
129: branch 19 taken
0: branch 39 not taken
0: branch 40 not taken
0: branch 60 not taken
0: branch 61 not taken
766 129: class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
767 : public:
768 : // FIXME - accessibility
769 152: class GC_IVAR {
770 : public:
771 : unsigned ivar_bytepos;
772 : unsigned ivar_size;
773 152: GC_IVAR(unsigned bytepos = 0, unsigned size = 0)
774 152: : ivar_bytepos(bytepos), ivar_size(size) {}
775 :
776 : // Allow sorting based on byte pos.
777 0: bool operator<(const GC_IVAR &b) const {
778 0: return ivar_bytepos < b.ivar_bytepos;
779 : }
780 : };
781 :
782 32: class SKIP_SCAN {
783 : public:
784 : unsigned skip;
785 : unsigned scan;
786 29: SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0)
787 29: : skip(_skip), scan(_scan) {}
788 : };
789 :
790 : protected:
791 : CodeGen::CodeGenModule &CGM;
792 : llvm::LLVMContext &VMContext;
793 : // FIXME! May not be needing this after all.
794 : unsigned ObjCABI;
795 :
796 : // gc ivar layout bitmap calculation helper caches.
797 : llvm::SmallVector<GC_IVAR, 16> SkipIvars;
798 : llvm::SmallVector<GC_IVAR, 16> IvarsInfo;
799 :
800 : /// LazySymbols - Symbols to generate a lazy reference for. See
801 : /// DefinedSymbols and FinishModule().
802 : llvm::SetVector<IdentifierInfo*> LazySymbols;
803 :
804 : /// DefinedSymbols - External symbols which are defined by this
805 : /// module. The symbols in this list and LazySymbols are used to add
806 : /// special linker symbols which ensure that Objective-C modules are
807 : /// linked properly.
808 : llvm::SetVector<IdentifierInfo*> DefinedSymbols;
809 :
810 : /// ClassNames - uniqued class names.
811 : llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassNames;
812 :
813 : /// MethodVarNames - uniqued method variable names.
814 : llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
815 :
816 : /// MethodVarTypes - uniqued method type signatures. We have to use
817 : /// a StringMap here because have no other unique reference.
818 : llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
819 :
820 : /// MethodDefinitions - map of methods which have been defined in
821 : /// this translation unit.
822 : llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions;
823 :
824 : /// PropertyNames - uniqued method variable names.
825 : llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
826 :
827 : /// ClassReferences - uniqued class references.
828 : llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
829 :
830 : /// SelectorReferences - uniqued selector references.
831 : llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
832 :
833 : /// Protocols - Protocols for which an objc_protocol structure has
834 : /// been emitted. Forward declarations are handled by creating an
835 : /// empty structure whose initializer is filled in when/if defined.
836 : llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
837 :
838 : /// DefinedProtocols - Protocols which have actually been
839 : /// defined. We should not need this, see FIXME in GenerateProtocol.
840 : llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
841 :
842 : /// DefinedClasses - List of defined classes.
843 : std::vector<llvm::GlobalValue*> DefinedClasses;
844 :
845 : /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
846 : std::vector<llvm::GlobalValue*> DefinedNonLazyClasses;
847 :
848 : /// DefinedCategories - List of defined categories.
849 : std::vector<llvm::GlobalValue*> DefinedCategories;
850 :
851 : /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
852 : std::vector<llvm::GlobalValue*> DefinedNonLazyCategories;
853 :
854 : /// GetNameForMethod - Return a name for the given method.
855 : /// \param[out] NameOut - The return value.
856 : void GetNameForMethod(const ObjCMethodDecl *OMD,
857 : const ObjCContainerDecl *CD,
858 : llvm::SmallVectorImpl<char> &NameOut);
859 :
860 : /// GetMethodVarName - Return a unique constant for the given
861 : /// selector's name. The return value has type char *.
862 : llvm::Constant *GetMethodVarName(Selector Sel);
863 : llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
864 : llvm::Constant *GetMethodVarName(const std::string &Name);
865 :
866 : /// GetMethodVarType - Return a unique constant for the given
867 : /// selector's name. The return value has type char *.
868 :
869 : // FIXME: This is a horrible name.
870 : llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D);
871 : llvm::Constant *GetMethodVarType(const FieldDecl *D);
872 :
873 : /// GetPropertyName - Return a unique constant for the given
874 : /// name. The return value has type char *.
875 : llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
876 :
877 : // FIXME: This can be dropped once string functions are unified.
878 : llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
879 : const Decl *Container);
880 :
881 : /// GetClassName - Return a unique constant for the given selector's
882 : /// name. The return value has type char *.
883 : llvm::Constant *GetClassName(IdentifierInfo *Ident);
884 :
885 : /// BuildIvarLayout - Builds ivar layout bitmap for the class
886 : /// implementation for the __strong or __weak case.
887 : ///
888 : llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
889 : bool ForStrongLayout);
890 :
891 : void BuildAggrIvarRecordLayout(const RecordType *RT,
892 : unsigned int BytePos, bool ForStrongLayout,
893 : bool &HasUnion);
894 : void BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
895 : const llvm::StructLayout *Layout,
896 : const RecordDecl *RD,
897 : const llvm::SmallVectorImpl<FieldDecl*> &RecFields,
898 : unsigned int BytePos, bool ForStrongLayout,
899 : bool &HasUnion);
900 :
901 : /// GetIvarLayoutName - Returns a unique constant for the given
902 : /// ivar layout bitmap.
903 : llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
904 : const ObjCCommonTypesHelper &ObjCTypes);
905 :
906 : /// EmitPropertyList - Emit the given property list. The return
907 : /// value has type PropertyListPtrTy.
908 : llvm::Constant *EmitPropertyList(llvm::Twine Name,
909 : const Decl *Container,
910 : const ObjCContainerDecl *OCD,
911 : const ObjCCommonTypesHelper &ObjCTypes);
912 :
913 : /// PushProtocolProperties - Push protocol's property on the input stack.
914 : void PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet,
915 : std::vector<llvm::Constant*> &Properties,
916 : const Decl *Container,
917 : const ObjCProtocolDecl *PROTO,
918 : const ObjCCommonTypesHelper &ObjCTypes);
919 :
920 : /// GetProtocolRef - Return a reference to the internal protocol
921 : /// description, creating an empty one if it has not been
922 : /// defined. The return value has type ProtocolPtrTy.
923 : llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
924 :
925 : /// CreateMetadataVar - Create a global variable with internal
926 : /// linkage for use by the Objective-C runtime.
927 : ///
928 : /// This is a convenience wrapper which not only creates the
929 : /// variable, but also sets the section and alignment and adds the
930 : /// global to the "llvm.used" list.
931 : ///
932 : /// \param Name - The variable name.
933 : /// \param Init - The variable initializer; this is also used to
934 : /// define the type of the variable.
935 : /// \param Section - The section the variable should go into, or 0.
936 : /// \param Align - The alignment for the variable, or 0.
937 : /// \param AddToUsed - Whether the variable should be added to
938 : /// "llvm.used".
939 : llvm::GlobalVariable *CreateMetadataVar(llvm::Twine Name,
940 : llvm::Constant *Init,
941 : const char *Section,
942 : unsigned Align,
943 : bool AddToUsed);
944 :
945 : CodeGen::RValue EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF,
946 : QualType ResultType,
947 : llvm::Value *Sel,
948 : llvm::Value *Arg0,
949 : QualType Arg0Ty,
950 : bool IsSuper,
951 : const CallArgList &CallArgs,
952 : const ObjCMethodDecl *OMD,
953 : const ObjCCommonTypesHelper &ObjCTypes);
954 :
955 : public:
956 130: CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
957 130: CGM(cgm), VMContext(cgm.getLLVMContext()) { }
958 :
959 : virtual llvm::Constant *GenerateConstantString(const StringLiteral *SL);
960 :
961 : virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
962 : const ObjCContainerDecl *CD=0);
963 :
964 : virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
965 :
966 : /// GetOrEmitProtocol - Get the protocol object for the given
967 : /// declaration, emitting it if necessary. The return value has type
968 : /// ProtocolPtrTy.
969 : virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0;
970 :
971 : /// GetOrEmitProtocolRef - Get a forward reference to the protocol
972 : /// object for the given declaration, emitting it if needed. These
973 : /// forward references will be filled in with empty bodies if no
974 : /// definition is seen. The return value has type ProtocolPtrTy.
975 : virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
976 : };
977 :
110: branch 2 taken
0: branch 3 not taken
0: branch 7 not taken
0: branch 8 not taken
978 110: class CGObjCMac : public CGObjCCommonMac {
979 : private:
980 : ObjCTypesHelper ObjCTypes;
981 : /// EmitImageInfo - Emit the image info marker used to encode some module
982 : /// level information.
983 : void EmitImageInfo();
984 :
985 : /// EmitModuleInfo - Another marker encoding module level
986 : /// information.
987 : void EmitModuleInfo();
988 :
989 : /// EmitModuleSymols - Emit module symbols, the list of defined
990 : /// classes and categories. The result has type SymtabPtrTy.
991 : llvm::Constant *EmitModuleSymbols();
992 :
993 : /// FinishModule - Write out global data structures at the end of
994 : /// processing a translation unit.
995 : void FinishModule();
996 :
997 : /// EmitClassExtension - Generate the class extension structure used
998 : /// to store the weak ivar layout and properties. The return value
999 : /// has type ClassExtensionPtrTy.
1000 : llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID);
1001 :
1002 : /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1003 : /// for the given class.
1004 : llvm::Value *EmitClassRef(CGBuilderTy &Builder,
1005 : const ObjCInterfaceDecl *ID);
1006 :
1007 : /// EmitSuperClassRef - Emits reference to class's main metadata class.
1008 : llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
1009 :
1010 : CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
1011 : QualType ResultType,
1012 : Selector Sel,
1013 : llvm::Value *Arg0,
1014 : QualType Arg0Ty,
1015 : bool IsSuper,
1016 : const CallArgList &CallArgs);
1017 :
1018 : /// EmitIvarList - Emit the ivar list for the given
1019 : /// implementation. If ForClass is true the list of class ivars
1020 : /// (i.e. metaclass ivars) is emitted, otherwise the list of
1021 : /// interface ivars will be emitted. The return value has type
1022 : /// IvarListPtrTy.
1023 : llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
1024 : bool ForClass);
1025 :
1026 : /// EmitMetaClass - Emit a forward reference to the class structure
1027 : /// for the metaclass of the given interface. The return value has
1028 : /// type ClassPtrTy.
1029 : llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
1030 :
1031 : /// EmitMetaClass - Emit a class structure for the metaclass of the
1032 : /// given implementation. The return value has type ClassPtrTy.
1033 : llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
1034 : llvm::Constant *Protocols,
1035 : const ConstantVector &Methods);
1036 :
1037 : llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
1038 :
1039 : llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
1040 :
1041 : /// EmitMethodList - Emit the method list for the given
1042 : /// implementation. The return value has type MethodListPtrTy.
1043 : llvm::Constant *EmitMethodList(llvm::Twine Name,
1044 : const char *Section,
1045 : const ConstantVector &Methods);
1046 :
1047 : /// EmitMethodDescList - Emit a method description list for a list of
1048 : /// method declarations.
1049 : /// - TypeName: The name for the type containing the methods.
1050 : /// - IsProtocol: True iff these methods are for a protocol.
1051 : /// - ClassMethds: True iff these are class methods.
1052 : /// - Required: When true, only "required" methods are
1053 : /// listed. Similarly, when false only "optional" methods are
1054 : /// listed. For classes this should always be true.
1055 : /// - begin, end: The method list to output.
1056 : ///
1057 : /// The return value has type MethodDescriptionListPtrTy.
1058 : llvm::Constant *EmitMethodDescList(llvm::Twine Name,
1059 : const char *Section,
1060 : const ConstantVector &Methods);
1061 :
1062 : /// GetOrEmitProtocol - Get the protocol object for the given
1063 : /// declaration, emitting it if necessary. The return value has type
1064 : /// ProtocolPtrTy.
1065 : virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
1066 :
1067 : /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1068 : /// object for the given declaration, emitting it if needed. These
1069 : /// forward references will be filled in with empty bodies if no
1070 : /// definition is seen. The return value has type ProtocolPtrTy.
1071 : virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
1072 :
1073 : /// EmitProtocolExtension - Generate the protocol extension
1074 : /// structure used to store optional instance and class methods, and
1075 : /// protocol properties. The return value has type
1076 : /// ProtocolExtensionPtrTy.
1077 : llvm::Constant *
1078 : EmitProtocolExtension(const ObjCProtocolDecl *PD,
1079 : const ConstantVector &OptInstanceMethods,
1080 : const ConstantVector &OptClassMethods);
1081 :
1082 : /// EmitProtocolList - Generate the list of referenced
1083 : /// protocols. The return value has type ProtocolListPtrTy.
1084 : llvm::Constant *EmitProtocolList(llvm::Twine Name,
1085 : ObjCProtocolDecl::protocol_iterator begin,
1086 : ObjCProtocolDecl::protocol_iterator end);
1087 :
1088 : /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1089 : /// for the given selector.
1090 : llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel);
1091 :
1092 : public:
1093 : CGObjCMac(CodeGen::CodeGenModule &cgm);
1094 :
1095 : virtual llvm::Function *ModuleInitFunction();
1096 :
1097 : virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1098 : QualType ResultType,
1099 : Selector Sel,
1100 : llvm::Value *Receiver,
1101 : bool IsClassMessage,
1102 : const CallArgList &CallArgs,
1103 : const ObjCMethodDecl *Method);
1104 :
1105 : virtual CodeGen::RValue
1106 : GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
1107 : QualType ResultType,
1108 : Selector Sel,
1109 : const ObjCInterfaceDecl *Class,
1110 : bool isCategoryImpl,
1111 : llvm::Value *Receiver,
1112 : bool IsClassMessage,
1113 : const CallArgList &CallArgs,
1114 : const ObjCMethodDecl *Method);
1115 :
1116 : virtual llvm::Value *GetClass(CGBuilderTy &Builder,
1117 : const ObjCInterfaceDecl *ID);
1118 :
1119 : virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel);
1120 :
1121 : /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1122 : /// untyped one.
1123 : virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
1124 : const ObjCMethodDecl *Method);
1125 :
1126 : virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
1127 :
1128 : virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
1129 :
1130 : virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
1131 : const ObjCProtocolDecl *PD);
1132 :
1133 : virtual llvm::Constant *GetPropertyGetFunction();
1134 : virtual llvm::Constant *GetPropertySetFunction();
1135 : virtual llvm::Constant *EnumerationMutationFunction();
1136 :
1137 : virtual void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1138 : const Stmt &S);
1139 : virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
1140 : const ObjCAtThrowStmt &S);
1141 : virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
1142 : llvm::Value *AddrWeakObj);
1143 : virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
1144 : llvm::Value *src, llvm::Value *dst);
1145 : virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
1146 : llvm::Value *src, llvm::Value *dest);
1147 : virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
1148 : llvm::Value *src, llvm::Value *dest,
1149 : llvm::Value *ivarOffset);
1150 : virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
1151 : llvm::Value *src, llvm::Value *dest);
1152 : virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1153 : llvm::Value *dest, llvm::Value *src,
1154 : QualType Ty);
1155 :
1156 : virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1157 : QualType ObjectTy,
1158 : llvm::Value *BaseValue,
1159 : const ObjCIvarDecl *Ivar,
1160 : unsigned CVRQualifiers);
1161 : virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
1162 : const ObjCInterfaceDecl *Interface,
1163 : const ObjCIvarDecl *Ivar);
1164 : };
1165 :
19: branch 7 taken
0: branch 8 not taken
0: branch 17 not taken
0: branch 18 not taken
1166 19: class CGObjCNonFragileABIMac : public CGObjCCommonMac {
1167 : private:
1168 : ObjCNonFragileABITypesHelper ObjCTypes;
1169 : llvm::GlobalVariable* ObjCEmptyCacheVar;
1170 : llvm::GlobalVariable* ObjCEmptyVtableVar;
1171 :
1172 : /// SuperClassReferences - uniqued super class references.
1173 : llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
1174 :
1175 : /// MetaClassReferences - uniqued meta class references.
1176 : llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
1177 :
1178 : /// EHTypeReferences - uniqued class ehtype references.
1179 : llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
1180 :
1181 : /// NonLegacyDispatchMethods - List of methods for which we do *not* generate
1182 : /// legacy messaging dispatch.
1183 : llvm::DenseSet<Selector> NonLegacyDispatchMethods;
1184 :
1185 : /// DefinedMetaClasses - List of defined meta-classes.
1186 : std::vector<llvm::GlobalValue*> DefinedMetaClasses;
1187 :
1188 : /// LegacyDispatchedSelector - Returns true if SEL is not in the list of
1189 : /// NonLegacyDispatchMethods; false otherwise.
1190 : bool LegacyDispatchedSelector(Selector Sel);
1191 :
1192 : /// FinishNonFragileABIModule - Write out global data structures at the end of
1193 : /// processing a translation unit.
1194 : void FinishNonFragileABIModule();
1195 :
1196 : /// AddModuleClassList - Add the given list of class pointers to the
1197 : /// module with the provided symbol and section names.
1198 : void AddModuleClassList(const std::vector<llvm::GlobalValue*> &Container,
1199 : const char *SymbolName,
1200 : const char *SectionName);
1201 :
1202 : llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
1203 : unsigned InstanceStart,
1204 : unsigned InstanceSize,
1205 : const ObjCImplementationDecl *ID);
1206 : llvm::GlobalVariable * BuildClassMetaData(std::string &ClassName,
1207 : llvm::Constant *IsAGV,
1208 : llvm::Constant *SuperClassGV,
1209 : llvm::Constant *ClassRoGV,
1210 : bool HiddenVisibility);
1211 :
1212 : llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
1213 :
1214 : llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
1215 :
1216 : /// EmitMethodList - Emit the method list for the given
1217 : /// implementation. The return value has type MethodListnfABITy.
1218 : llvm::Constant *EmitMethodList(llvm::Twine Name,
1219 : const char *Section,
1220 : const ConstantVector &Methods);
1221 : /// EmitIvarList - Emit the ivar list for the given
1222 : /// implementation. If ForClass is true the list of class ivars
1223 : /// (i.e. metaclass ivars) is emitted, otherwise the list of
1224 : /// interface ivars will be emitted. The return value has type
1225 : /// IvarListnfABIPtrTy.
1226 : llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID);
1227 :
1228 : llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
1229 : const ObjCIvarDecl *Ivar,
1230 : unsigned long int offset);
1231 :
1232 : /// GetOrEmitProtocol - Get the protocol object for the given
1233 : /// declaration, emitting it if necessary. The return value has type
1234 : /// ProtocolPtrTy.
1235 : virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
1236 :
1237 : /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1238 : /// object for the given declaration, emitting it if needed. These
1239 : /// forward references will be filled in with empty bodies if no
1240 : /// definition is seen. The return value has type ProtocolPtrTy.
1241 : virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
1242 :
1243 : /// EmitProtocolList - Generate the list of referenced
1244 : /// protocols. The return value has type ProtocolListPtrTy.
1245 : llvm::Constant *EmitProtocolList(llvm::Twine Name,
1246 : ObjCProtocolDecl::protocol_iterator begin,
1247 : ObjCProtocolDecl::protocol_iterator end);
1248 :
1249 : CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
1250 : QualType ResultType,
1251 : Selector Sel,
1252 : llvm::Value *Receiver,
1253 : QualType Arg0Ty,
1254 : bool IsSuper,
1255 : const CallArgList &CallArgs);
1256 :
1257 : /// GetClassGlobal - Return the global variable for the Objective-C
1258 : /// class of the given name.
1259 : llvm::GlobalVariable *GetClassGlobal(const std::string &Name);
1260 :
1261 : /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1262 : /// for the given class reference.
1263 : llvm::Value *EmitClassRef(CGBuilderTy &Builder,
1264 : const ObjCInterfaceDecl *ID);
1265 :
1266 : /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1267 : /// for the given super class reference.
1268 : llvm::Value *EmitSuperClassRef(CGBuilderTy &Builder,
1269 : const ObjCInterfaceDecl *ID);
1270 :
1271 : /// EmitMetaClassRef - Return a Value * of the address of _class_t
1272 : /// meta-data
1273 : llvm::Value *EmitMetaClassRef(CGBuilderTy &Builder,
1274 : const ObjCInterfaceDecl *ID);
1275 :
1276 : /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
1277 : /// the given ivar.
1278 : ///
1279 : llvm::GlobalVariable * ObjCIvarOffsetVariable(
1280 : const ObjCInterfaceDecl *ID,
1281 : const ObjCIvarDecl *Ivar);
1282 :
1283 : /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1284 : /// for the given selector.
1285 : llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel);
1286 :
1287 : /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
1288 : /// interface. The return value has type EHTypePtrTy.
1289 : llvm::Value *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
1290 : bool ForDefinition);
1291 :
1292 43: const char *getMetaclassSymbolPrefix() const {
1293 43: return "OBJC_METACLASS_$_";
1294 : }
1295 :
1296 63: const char *getClassSymbolPrefix() const {
1297 63: return "OBJC_CLASS_$_";
1298 : }
1299 :
1300 : void GetClassSizeInfo(const ObjCImplementationDecl *OID,
1301 : uint32_t &InstanceStart,
1302 : uint32_t &InstanceSize);
1303 :
1304 : // Shamelessly stolen from Analysis/CFRefCount.cpp
1305 100: Selector GetNullarySelector(const char* name) const {
1306 100: IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1307 100: return CGM.getContext().Selectors.getSelector(0, &II);
1308 : }
1309 :
1310 40: Selector GetUnarySelector(const char* name) const {
1311 40: IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1312 40: return CGM.getContext().Selectors.getSelector(1, &II);
1313 : }
1314 :
1315 : /// ImplementationIsNonLazy - Check whether the given category or
1316 : /// class implementation is "non-lazy".
1317 : bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const;
1318 :
1319 : public:
1320 : CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
1321 : // FIXME. All stubs for now!
1322 : virtual llvm::Function *ModuleInitFunction();
1323 :
1324 : virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1325 : QualType ResultType,
1326 : Selector Sel,
1327 : llvm::Value *Receiver,
1328 : bool IsClassMessage,
1329 : const CallArgList &CallArgs,
1330 : const ObjCMethodDecl *Method);
1331 :
1332 : virtual CodeGen::RValue
1333 : GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
1334 : QualType ResultType,
1335 : Selector Sel,
1336 : const ObjCInterfaceDecl *Class,
1337 : bool isCategoryImpl,
1338 : llvm::Value *Receiver,
1339 : bool IsClassMessage,
1340 : const CallArgList &CallArgs,
1341 : const ObjCMethodDecl *Method);
1342 :
1343 : virtual llvm::Value *GetClass(CGBuilderTy &Builder,
1344 : const ObjCInterfaceDecl *ID);
1345 :
1346 0: virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel)
1347 0: { return EmitSelector(Builder, Sel); }
1348 :
1349 : /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1350 : /// untyped one.
1351 : virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
1352 0: const ObjCMethodDecl *Method)
1353 0: { return EmitSelector(Builder, Method->getSelector()); }
1354 :
1355 : virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
1356 :
1357 : virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
1358 : virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
1359 : const ObjCProtocolDecl *PD);
1360 :
1361 2: virtual llvm::Constant *GetPropertyGetFunction() {
1362 2: return ObjCTypes.getGetPropertyFn();
1363 : }
1364 2: virtual llvm::Constant *GetPropertySetFunction() {
1365 2: return ObjCTypes.getSetPropertyFn();
1366 : }
1367 0: virtual llvm::Constant *EnumerationMutationFunction() {
1368 0: return ObjCTypes.getEnumerationMutationFn();
1369 : }
1370 :
1371 : virtual void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1372 : const Stmt &S);
1373 : virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
1374 : const ObjCAtThrowStmt &S);
1375 : virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
1376 : llvm::Value *AddrWeakObj);
1377 : virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
1378 : llvm::Value *src, llvm::Value *dst);
1379 : virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
1380 : llvm::Value *src, llvm::Value *dest);
1381 : virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
1382 : llvm::Value *src, llvm::Value *dest,
1383 : llvm::Value *ivarOffset);
1384 : virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
1385 : llvm::Value *src, llvm::Value *dest);
1386 : virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1387 : llvm::Value *dest, llvm::Value *src,
1388 : QualType Ty);
1389 : virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1390 : QualType ObjectTy,
1391 : llvm::Value *BaseValue,
1392 : const ObjCIvarDecl *Ivar,
1393 : unsigned CVRQualifiers);
1394 : virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
1395 : const ObjCInterfaceDecl *Interface,
1396 : const ObjCIvarDecl *Ivar);
1397 : };
1398 :
1399 : } // end anonymous namespace
1400 :
1401 : /* *** Helper Functions *** */
1402 :
1403 : /// getConstantGEP() - Help routine to construct simple GEPs.
1404 : static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
1405 : llvm::Constant *C,
1406 : unsigned idx0,
1407 2139: unsigned idx1) {
1408 : llvm::Value *Idxs[] = {
1409 : llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1410 : llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
1411 2139: };
1412 2139: return llvm::ConstantExpr::getGetElementPtr(C, Idxs, 2);
1413 : }
1414 :
1415 : /// hasObjCExceptionAttribute - Return true if this class or any super
1416 : /// class has the __objc_exception__ attribute.
1417 : static bool hasObjCExceptionAttribute(ASTContext &Context,
1418 73: const ObjCInterfaceDecl *OID) {
6: branch 1 taken
67: branch 2 taken
1419 73: if (OID->hasAttr<ObjCExceptionAttr>())
1420 6: return true;
25: branch 1 taken
42: branch 2 taken
1421 67: if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
1422 25: return hasObjCExceptionAttribute(Context, Super);
1423 42: return false;
1424 : }
1425 :
1426 : /* *** CGObjCMac Public Interface *** */
1427 :
1428 110: CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
1429 110: ObjCTypes(cgm) {
1430 110: ObjCABI = 1;
1431 110: EmitImageInfo();
1432 110: }
1433 :
1434 : /// GetClass - Return a reference to the class for the given interface
1435 : /// decl.
1436 : llvm::Value *CGObjCMac::GetClass(CGBuilderTy &Builder,
1437 36: const ObjCInterfaceDecl *ID) {
1438 36: return EmitClassRef(Builder, ID);
1439 : }
1440 :
1441 : /// GetSelector - Return the pointer to the unique'd string for this selector.
1442 1: llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel) {
1443 1: return EmitSelector(Builder, Sel);
1444 : }
1445 : llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
1446 0: *Method) {
1447 0: return EmitSelector(Builder, Method->getSelector());
1448 : }
1449 :
1450 : /// Generate a constant CFString object.
1451 : /*
1452 : struct __builtin_CFString {
1453 : const int *isa; // point to __CFConstantStringClassReference
1454 : int flags;
1455 : const char *str;
1456 : long length;
1457 : };
1458 : */
1459 :
1460 : llvm::Constant *CGObjCCommonMac::GenerateConstantString(
1461 68: const StringLiteral *SL) {
1462 68: return CGM.GetAddrOfConstantCFString(SL);
1463 : }
1464 :
1465 : /// Generates a message send where the super is the receiver. This is
1466 : /// a message send to self with special delivery semantics indicating
1467 : /// which class's method should be called.
1468 : CodeGen::RValue
1469 : CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
1470 : QualType ResultType,
1471 : Selector Sel,
1472 : const ObjCInterfaceDecl *Class,
1473 : bool isCategoryImpl,
1474 : llvm::Value *Receiver,
1475 : bool IsClassMessage,
1476 : const CodeGen::CallArgList &CallArgs,
1477 33: const ObjCMethodDecl *Method) {
1478 : // Create and init a super structure; this is a (receiver, class)
1479 : // pair we will pass to objc_msgSendSuper.
1480 : llvm::Value *ObjCSuper =
1481 33: CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super");
1482 : llvm::Value *ReceiverAsObject =
1483 33: CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
1484 : CGF.Builder.CreateStore(ReceiverAsObject,
1485 33: CGF.Builder.CreateStructGEP(ObjCSuper, 0));
1486 :
1487 : // If this is a class message the metaclass is passed as the target.
1488 : llvm::Value *Target;
12: branch 0 taken
21: branch 1 taken
1489 33: if (IsClassMessage) {
2: branch 0 taken
10: branch 1 taken
1490 12: if (isCategoryImpl) {
1491 : // Message sent to 'super' in a class method defined in a category
1492 : // implementation requires an odd treatment.
1493 : // If we are in a class method, we must retrieve the
1494 : // _metaclass_ for the current class, pointed at by
1495 : // the class's "isa" pointer. The following assumes that
1496 : // isa" is the first ivar in a class (which it must be).
1497 2: Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1498 2: Target = CGF.Builder.CreateStructGEP(Target, 0);
1499 2: Target = CGF.Builder.CreateLoad(Target);
1500 : } else {
1501 10: llvm::Value *MetaClassPtr = EmitMetaClassRef(Class);
1502 10: llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1);
1503 10: llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr);
1504 10: Target = Super;
1505 : }
1506 : }
0: branch 0 not taken
21: branch 1 taken
1507 21: else if (isCategoryImpl)
1508 0: Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1509 : else {
1510 21: llvm::Value *ClassPtr = EmitSuperClassRef(Class);
1511 21: ClassPtr = CGF.Builder.CreateStructGEP(ClassPtr, 1);
1512 21: Target = CGF.Builder.CreateLoad(ClassPtr);
1513 : }
1514 : // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
1515 : // ObjCTypes types.
1516 : const llvm::Type *ClassTy =
1517 33: CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
1518 33: Target = CGF.Builder.CreateBitCast(Target, ClassTy);
1519 : CGF.Builder.CreateStore(Target,
1520 33: CGF.Builder.CreateStructGEP(ObjCSuper, 1));
1521 : return EmitLegacyMessageSend(CGF, ResultType,
1522 : EmitSelector(CGF.Builder, Sel),
1523 : ObjCSuper, ObjCTypes.SuperPtrCTy,
1524 33: true, CallArgs, Method, ObjCTypes);
1525 : }
1526 :
1527 : /// Generate code for a message send expression.
1528 : CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1529 : QualType ResultType,
1530 : Selector Sel,
1531 : llvm::Value *Receiver,
1532 : bool IsClassMessage,
1533 : const CallArgList &CallArgs,
1534 166: const ObjCMethodDecl *Method) {
1535 : return EmitLegacyMessageSend(CGF, ResultType,
1536 : EmitSelector(CGF.Builder, Sel),
1537 : Receiver, CGF.getContext().getObjCIdType(),
1538 166: false, CallArgs, Method, ObjCTypes);
1539 : }
1540 :
1541 : CodeGen::RValue
1542 : CGObjCCommonMac::EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF,
1543 : QualType ResultType,
1544 : llvm::Value *Sel,
1545 : llvm::Value *Arg0,
1546 : QualType Arg0Ty,
1547 : bool IsSuper,
1548 : const CallArgList &CallArgs,
1549 : const ObjCMethodDecl *Method,
1550 217: const ObjCCommonTypesHelper &ObjCTypes) {
1551 217: CallArgList ActualArgs;
182: branch 0 taken
35: branch 1 taken
1552 217: if (!IsSuper)
1553 182: Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp");
1554 217: ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty));
1555 : ActualArgs.push_back(std::make_pair(RValue::get(Sel),
1556 217: CGF.getContext().getObjCSelType()));
1557 217: ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
1558 :
1559 217: CodeGenTypes &Types = CGM.getTypes();
1560 : const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs,
1561 217: CC_Default, false);
1562 : const llvm::FunctionType *FTy =
109: branch 0 taken
108: branch 1 taken
1563 217: Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false);
1564 :
1565 217: llvm::Constant *Fn = NULL;
10: branch 1 taken
207: branch 2 taken
1566 217: if (CGM.ReturnTypeUsesSret(FnInfo)) {
1567 : Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
0: branch 0 not taken
10: branch 1 taken
1568 10: : ObjCTypes.getSendStretFn(IsSuper);
15: branch 2 taken
192: branch 3 taken
1569 207: } else if (ResultType->isFloatingType()) {
3: branch 0 taken
12: branch 1 taken
1570 15: if (ObjCABI == 2) {
3: branch 2 taken
0: branch 3 not taken
1571 3: if (const BuiltinType *BT = ResultType->getAs<BuiltinType>()) {
1572 3: BuiltinType::Kind k = BT->getKind();
1573 : Fn = (k == BuiltinType::LongDouble) ? ObjCTypes.getSendFpretFn2(IsSuper)
1: branch 0 taken
2: branch 1 taken
1574 3: : ObjCTypes.getSendFn2(IsSuper);
1575 : } else {
1576 0: Fn = ObjCTypes.getSendFn2(IsSuper);
1577 : }
1578 : } else
1579 : // FIXME. This currently matches gcc's API for x86-32. May need to change
1580 : // for others if we have their API.
1581 12: Fn = ObjCTypes.getSendFpretFn(IsSuper);
1582 : } else {
1583 : Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
15: branch 0 taken
177: branch 1 taken
1584 192: : ObjCTypes.getSendFn(IsSuper);
1585 : }
0: branch 0 not taken
217: branch 1 taken
1586 217: assert(Fn && "EmitLegacyMessageSend - unknown API");
1587 : Fn = llvm::ConstantExpr::getBitCast(Fn,
1588 217: llvm::PointerType::getUnqual(FTy));
1589 217: return CGF.EmitCall(FnInfo, Fn, ReturnValueSlot(), ActualArgs);
1590 : }
1591 :
1592 : llvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder,
1593 11: const ObjCProtocolDecl *PD) {
1594 : // FIXME: I don't understand why gcc generates this, or where it is
1595 : // resolved. Investigate. Its also wasteful to look this up over and over.
1596 11: LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
1597 :
1598 : return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
1599 11: ObjCTypes.ExternalProtocolPtrTy);
1600 : }
1601 :
1602 31: void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
1603 : // FIXME: We shouldn't need this, the protocol decl should contain enough
1604 : // information to tell us whether this was a declaration or a definition.
1605 31: DefinedProtocols.insert(PD->getIdentifier());
1606 :
1607 : // If we have generated a forward reference to this protocol, emit
1608 : // it now. Otherwise do nothing, the protocol objects are lazily
1609 : // emitted.
1: branch 2 taken
30: branch 3 taken
1610 31: if (Protocols.count(PD->getIdentifier()))
1611 1: GetOrEmitProtocol(PD);
1612 31: }
1613 :
1614 32: llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
27: branch 2 taken
5: branch 3 taken
1615 32: if (DefinedProtocols.count(PD->getIdentifier()))
1616 27: return GetOrEmitProtocol(PD);
1617 5: return GetOrEmitProtocolRef(PD);
1618 : }
1619 :
1620 : /*
1621 : // APPLE LOCAL radar 4585769 - Objective-C 1.0 extensions
1622 : struct _objc_protocol {
1623 : struct _objc_protocol_extension *isa;
1624 : char *protocol_name;
1625 : struct _objc_protocol_list *protocol_list;
1626 : struct _objc__method_prototype_list *instance_methods;
1627 : struct _objc__method_prototype_list *class_methods
1628 : };
1629 :
1630 : See EmitProtocolExtension().
1631 : */
1632 19: llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
1633 19: llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
1634 :
1635 : // Early exit if a defining object has already been generated.
5: branch 0 taken
14: branch 1 taken
4: branch 3 taken
1: branch 4 taken
4: branch 5 taken
15: branch 6 taken
1636 19: if (Entry && Entry->hasInitializer())
1637 4: return Entry;
1638 :
1639 : // FIXME: I don't understand why gcc generates this, or where it is
1640 : // resolved. Investigate. Its also wasteful to look this up over and over.
1641 15: LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
1642 :
1643 : // Construct method lists.
1644 15: std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
1645 15: std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
20: branch 2 taken
15: branch 3 taken
1646 35: for (ObjCProtocolDecl::instmeth_iterator
1647 15: i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
1648 20: ObjCMethodDecl *MD = *i;
1649 20: llvm::Constant *C = GetMethodDescriptionConstant(MD);
1: branch 1 taken
19: branch 2 taken
1650 20: if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
1651 1: OptInstanceMethods.push_back(C);
1652 : } else {
1653 19: InstanceMethods.push_back(C);
1654 : }
1655 : }
1656 :
4: branch 2 taken
15: branch 3 taken
1657 19: for (ObjCProtocolDecl::classmeth_iterator
1658 15: i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
1659 4: ObjCMethodDecl *MD = *i;
1660 4: llvm::Constant *C = GetMethodDescriptionConstant(MD);
1: branch 1 taken
3: branch 2 taken
1661 4: if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
1662 1: OptClassMethods.push_back(C);
1663 : } else {
1664 3: ClassMethods.push_back(C);
1665 : }
1666 : }
1667 :
1668 15: std::vector<llvm::Constant*> Values(5);
1669 15: Values[0] = EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods);
1670 15: Values[1] = GetClassName(PD->getIdentifier());
1671 : Values[2] =
1672 : EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(),
1673 : PD->protocol_begin(),
1674 15: PD->protocol_end());
1675 : Values[3] =
1676 : EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(),
1677 : "__OBJC,__cat_inst_meth,regular,no_dead_strip",
1678 15: InstanceMethods);
1679 : Values[4] =
1680 : EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(),
1681 : "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1682 15: ClassMethods);
1683 : llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
1684 15: Values);
1685 :
1: branch 0 taken
14: branch 1 taken
1686 15: if (Entry) {
1687 : // Already created, fix the linkage and update the initializer.
1688 1: Entry->setLinkage(llvm::GlobalValue::InternalLinkage);
1689 1: Entry->setInitializer(Init);
1690 : } else {
1691 : Entry =
1692 : new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
1693 : llvm::GlobalValue::InternalLinkage,
1694 : Init,
1695 14: "\01L_OBJC_PROTOCOL_" + PD->getName());
1696 14: Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
1697 14: Entry->setAlignment(4);
1698 : // FIXME: Is this necessary? Why only for protocol?
1699 14: Entry->setAlignment(4);
1700 : }
1701 15: CGM.AddUsedGlobal(Entry);
1702 :
1703 15: return Entry;
1704 : }
1705 :
1706 5: llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
1707 5: llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
1708 :
5: branch 0 taken
0: branch 1 not taken
1709 5: if (!Entry) {
1710 : // We use the initializer as a marker of whether this is a forward
1711 : // reference or not. At module finalization we add the empty
1712 : // contents for protocols which were referenced but never defined.
1713 : Entry =
1714 : new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
1715 : llvm::GlobalValue::ExternalLinkage,
1716 : 0,
1717 5: "\01L_OBJC_PROTOCOL_" + PD->getName());
1718 5: Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
1719 5: Entry->setAlignment(4);
1720 : // FIXME: Is this necessary? Why only for protocol?
1721 5: Entry->setAlignment(4);
1722 : }
1723 :
1724 5: return Entry;
1725 : }
1726 :
1727 : /*
1728 : struct _objc_protocol_extension {
1729 : uint32_t size;
1730 : struct objc_method_description_list *optional_instance_methods;
1731 : struct objc_method_description_list *optional_class_methods;
1732 : struct objc_property_list *instance_properties;
1733 : };
1734 : */
1735 : llvm::Constant *
1736 : CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
1737 : const ConstantVector &OptInstanceMethods,
1738 15: const ConstantVector &OptClassMethods) {
1739 : uint64_t Size =
1740 15: CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
1741 15: std::vector<llvm::Constant*> Values(4);
1742 15: Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
1743 : Values[1] =
1744 : EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_"
1745 : + PD->getName(),
1746 : "__OBJC,__cat_inst_meth,regular,no_dead_strip",
1747 15: OptInstanceMethods);
1748 : Values[2] =
1749 : EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(),
1750 : "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1751 15: OptClassMethods);
1752 : Values[3] = EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(),
1753 15: 0, PD, ObjCTypes);
1754 :
1755 : // Return null if no extension bits are used.
14: branch 2 taken
1: branch 3 taken
14: branch 6 taken
0: branch 7 not taken
13: branch 10 taken
1: branch 11 taken
13: branch 12 taken
2: branch 13 taken
1756 15: if (Values[1]->isNullValue() && Values[2]->isNullValue() &&
1757 : Values[3]->isNullValue())
1758 13: return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
1759 :
1760 : llvm::Constant *Init =
1761 2: llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
1762 :
1763 : // No special section, but goes in llvm.used
1764 : return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getName(),
1765 : Init,
1766 2: 0, 0, true);
1767 : }
1768 :
1769 : /*
1770 : struct objc_protocol_list {
1771 : struct objc_protocol_list *next;
1772 : long count;
1773 : Protocol *list[];
1774 : };
1775 : */
1776 : llvm::Constant *
1777 : CGObjCMac::EmitProtocolList(llvm::Twine Name,
1778 : ObjCProtocolDecl::protocol_iterator begin,
1779 140: ObjCProtocolDecl::protocol_iterator end) {
1780 140: std::vector<llvm::Constant*> ProtocolRefs;
1781 :
12: branch 0 taken
140: branch 1 taken
1782 152: for (; begin != end; ++begin)
1783 12: ProtocolRefs.push_back(GetProtocolRef(*begin));
1784 :
1785 : // Just return null for empty protocol lists
130: branch 1 taken
10: branch 2 taken
1786 140: if (ProtocolRefs.empty())
1787 130: return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
1788 :
1789 : // This list is null terminated.
1790 10: ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy));
1791 :
1792 10: std::vector<llvm::Constant*> Values(3);
1793 : // This field is only used by the runtime.
1794 10: Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
1795 : Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy,
1796 10: ProtocolRefs.size() - 1);
1797 : Values[2] =
1798 : llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolPtrTy,
1799 : ProtocolRefs.size()),
1800 10: ProtocolRefs);
1801 :
1802 10: llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
1803 : llvm::GlobalVariable *GV =
1804 : CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1805 10: 4, false);
1806 10: return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
1807 : }
1808 :
1809 : void CGObjCCommonMac::PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet,
1810 : std::vector<llvm::Constant*> &Properties,
1811 : const Decl *Container,
1812 : const ObjCProtocolDecl *PROTO,
1813 19: const ObjCCommonTypesHelper &ObjCTypes) {
1814 19: std::vector<llvm::Constant*> Prop(2);
2: branch 1 taken
19: branch 2 taken
1815 40: for (ObjCProtocolDecl::protocol_iterator P = PROTO->protocol_begin(),
1816 19: E = PROTO->protocol_end(); P != E; ++P)
1817 2: PushProtocolProperties(PropertySet, Properties, Container, (*P), ObjCTypes);
10: branch 3 taken
19: branch 4 taken
1818 48: for (ObjCContainerDecl::prop_iterator I = PROTO->prop_begin(),
1819 19: E = PROTO->prop_end(); I != E; ++I) {
1820 10: const ObjCPropertyDecl *PD = *I;
1: branch 2 taken
9: branch 3 taken
1821 10: if (!PropertySet.insert(PD->getIdentifier()))
1822 1: continue;
1823 9: Prop[0] = GetPropertyName(PD->getIdentifier());
1824 9: Prop[1] = GetPropertyTypeString(PD, Container);
1825 9: Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy, Prop));
1826 19: }
1827 19: }
1828 :
1829 : /*
1830 : struct _objc_property {
1831 : const char * const name;
1832 : const char * const attributes;
1833 : };
1834 :
1835 : struct _objc_property_list {
1836 : uint32_t entsize; // sizeof (struct _objc_property)
1837 : uint32_t prop_count;
1838 : struct _objc_property[prop_count];
1839 : };
1840 : */
1841 : llvm::Constant *CGObjCCommonMac::EmitPropertyList(llvm::Twine Name,
1842 : const Decl *Container,
1843 : const ObjCContainerDecl *OCD,
1844 200: const ObjCCommonTypesHelper &ObjCTypes) {
1845 200: std::vector<llvm::Constant*> Properties, Prop(2);
1846 200: llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
85: branch 3 taken
200: branch 4 taken
1847 485: for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(),
1848 200: E = OCD->prop_end(); I != E; ++I) {
1849 85: const ObjCPropertyDecl *PD = *I;
1850 85: PropertySet.insert(PD->getIdentifier());
1851 85: Prop[0] = GetPropertyName(PD->getIdentifier());
1852 85: Prop[1] = GetPropertyTypeString(PD, Container);
1853 : Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy,
1854 85: Prop));
1855 : }
155: branch 1 taken
45: branch 2 taken
1856 200: if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
17: branch 1 taken
155: branch 2 taken
1857 327: for (ObjCInterfaceDecl::protocol_iterator P = OID->protocol_begin(),
1858 155: E = OID->protocol_end(); P != E; ++P)
1859 17: PushProtocolProperties(PropertySet, Properties, Container, (*P), ObjCTypes);
1860 :
1861 : // Return null for empty list.
155: branch 1 taken
45: branch 2 taken
1862 200: if (Properties.empty())
1863 155: return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
1864 :
1865 : unsigned PropertySize =
1866 45: CGM.getTargetData().getTypeAllocSize(ObjCTypes.PropertyTy);
1867 45: std::vector<llvm::Constant*> Values(3);
1868 45: Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize);
1869 45: Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size());
1870 : llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy,
1871 45: Properties.size());
1872 45: Values[2] = llvm::ConstantArray::get(AT, Properties);
1873 45: llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
1874 :
1875 : llvm::GlobalVariable *GV =
1876 : CreateMetadataVar(Name, Init,
1877 : (ObjCABI == 2) ? "__DATA, __objc_const" :
1878 : "__OBJC,__property,regular,no_dead_strip",
1879 : (ObjCABI == 2) ? 8 : 4,
21: branch 0 taken
24: branch 1 taken
21: branch 2 taken
24: branch 3 taken
1880 45: true);
1881 45: return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
1882 : }
1883 :
1884 : /*
1885 : struct objc_method_description_list {
1886 : int count;
1887 : struct objc_method_description list[];
1888 : };
1889 : */
1890 : llvm::Constant *
1891 24: CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
1892 24: std::vector<llvm::Constant*> Desc(2);
1893 : Desc[0] =
1894 : llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
1895 24: ObjCTypes.SelectorPtrTy);
1896 24: Desc[1] = GetMethodVarType(MD);
1897 : return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy,
1898 24: Desc);
1899 : }
1900 :
1901 : llvm::Constant *CGObjCMac::EmitMethodDescList(llvm::Twine Name,
1902 : const char *Section,
1903 60: const ConstantVector &Methods) {
1904 : // Return null for empty list.
46: branch 1 taken
14: branch 2 taken
1905 60: if (Methods.empty())
1906 46: return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
1907 :
1908 14: std::vector<llvm::Constant*> Values(2);
1909 14: Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
1910 : llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy,
1911 14: Methods.size());
1912 14: Values[1] = llvm::ConstantArray::get(AT, Methods);
1913 14: llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
1914 :
1915 14: llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
1916 : return llvm::ConstantExpr::getBitCast(GV,
1917 14: ObjCTypes.MethodDescriptionListPtrTy);
1918 : }
1919 :
1920 : /*
1921 : struct _objc_category {
1922 : char *category_name;
1923 : char *class_name;
1924 : struct _objc_method_list *instance_methods;
1925 : struct _objc_method_list *class_methods;
1926 : struct _objc_protocol_list *protocols;
1927 : uint32_t size; // <rdar://4585769>
1928 : struct _objc_property_list *instance_properties;
1929 : };
1930 : */
1931 12: void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
1932 12: unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.CategoryTy);
1933 :
1934 : // FIXME: This is poor design, the OCD should have a pointer to the category
1935 : // decl. Additionally, note that Category can be null for the @implementation
1936 : // w/o an @interface case. Sema should just create one for us as it does for
1937 : // @implementation so everyone else can live life under a clear blue sky.
1938 12: const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
1939 : const ObjCCategoryDecl *Category =
1940 12: Interface->FindCategoryDeclaration(OCD->getIdentifier());
1941 :
1942 12: llvm::SmallString<256> ExtName;
1943 : llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
1944 12: << OCD->getName();
1945 :
1946 12: std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
4: branch 2 taken
12: branch 3 taken
1947 16: for (ObjCCategoryImplDecl::instmeth_iterator
1948 12: i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
1949 : // Instance methods should always be defined.
1950 4: InstanceMethods.push_back(GetMethodConstant(*i));
1951 : }
4: branch 2 taken
12: branch 3 taken
1952 16: for (ObjCCategoryImplDecl::classmeth_iterator
1953 12: i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
1954 : // Class methods should always be defined.
1955 4: ClassMethods.push_back(GetMethodConstant(*i));
1956 : }
1957 :
1958 12: std::vector<llvm::Constant*> Values(7);
1959 12: Values[0] = GetClassName(OCD->getIdentifier());
1960 12: Values[1] = GetClassName(Interface->getIdentifier());
1961 12: LazySymbols.insert(Interface->getIdentifier());
1962 : Values[2] =
1963 : EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(),
1964 : "__OBJC,__cat_inst_meth,regular,no_dead_strip",
1965 12: InstanceMethods);
1966 : Values[3] =
1967 : EmitMethodList("\01L_OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(),
1968 : "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1969 12: ClassMethods);
12: branch 0 taken
0: branch 1 not taken
1970 12: if (Category) {
1971 : Values[4] =
1972 : EmitProtocolList("\01L_OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
1973 : Category->protocol_begin(),
1974 12: Category->protocol_end());
1975 : } else {
1976 0: Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
1977 : }
1978 12: Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
1979 :
1980 : // If there is no category @interface then there can be no properties.
12: branch 0 taken
0: branch 1 not taken
1981 12: if (Category) {
1982 : Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
1983 12: OCD, Category, ObjCTypes);
1984 : } else {
1985 0: Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
1986 : }
1987 :
1988 : llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy,
1989 12: Values);
1990 :
1991 : llvm::GlobalVariable *GV =
1992 : CreateMetadataVar("\01L_OBJC_CATEGORY_" + ExtName.str(), Init,
1993 : "__OBJC,__category,regular,no_dead_strip",
1994 12: 4, true);
1995 12: DefinedCategories.push_back(GV);
1996 12: }
1997 :
1998 : // FIXME: Get from somewhere?
1999 : enum ClassFlags {
2000 : eClassFlags_Factory = 0x00001,
2001 : eClassFlags_Meta = 0x00002,
2002 : // <rdr://5142207>
2003 : eClassFlags_HasCXXStructors = 0x02000,
2004 : eClassFlags_Hidden = 0x20000,
2005 : eClassFlags_ABI2_Hidden = 0x00010,
2006 : eClassFlags_ABI2_HasCXXStructors = 0x00004 // <rdr://4923634>
2007 : };
2008 :
2009 : /*
2010 : struct _objc_class {
2011 : Class isa;
2012 : Class super_class;
2013 : const char *name;
2014 : long version;
2015 : long info;
2016 : long instance_size;
2017 : struct _objc_ivar_list *ivars;
2018 : struct _objc_method_list *methods;
2019 : struct _objc_cache *cache;
2020 : struct _objc_protocol_list *protocols;
2021 : // Objective-C 1.0 extensions (<rdr://4585769>)
2022 : const char *ivar_layout;
2023 : struct _objc_class_ext *ext;
2024 : };
2025 :
2026 : See EmitClassExtension();
2027 : */
2028 113: void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
2029 113: DefinedSymbols.insert(ID->getIdentifier());
2030 :
2031 113: std::string ClassName = ID->getNameAsString();
2032 : // FIXME: Gross
2033 : ObjCInterfaceDecl *Interface =
2034 113: const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
2035 : llvm::Constant *Protocols =
2036 : EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(),
2037 : Interface->protocol_begin(),
2038 113: Interface->protocol_end());
2039 113: unsigned Flags = eClassFlags_Factory;
2040 : unsigned Size =
2041 113: CGM.getContext().getASTObjCImplementationLayout(ID).getSize() / 8;
2042 :
2043 : // FIXME: Set CXX-structors flag.
1: branch 2 taken
112: branch 3 taken
2044 113: if (CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden)
2045 1: Flags |= eClassFlags_Hidden;
2046 :
2047 113: std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
113: branch 2 taken
113: branch 3 taken
2048 226: for (ObjCImplementationDecl::instmeth_iterator
2049 113: i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
2050 : // Instance methods should always be defined.
2051 113: InstanceMethods.push_back(GetMethodConstant(*i));
2052 : }
31: branch 2 taken
113: branch 3 taken
2053 144: for (ObjCImplementationDecl::classmeth_iterator
2054 113: i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
2055 : // Class methods should always be defined.
2056 31: ClassMethods.push_back(GetMethodConstant(*i));
2057 : }
2058 :
54: branch 2 taken
113: branch 3 taken
2059 167: for (ObjCImplementationDecl::propimpl_iterator
2060 113: i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
2061 54: ObjCPropertyImplDecl *PID = *i;
2062 :
31: branch 1 taken
23: branch 2 taken
2063 54: if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
2064 31: ObjCPropertyDecl *PD = PID->getPropertyDecl();
2065 :
31: branch 1 taken
0: branch 2 not taken
2066 31: if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
30: branch 1 taken
1: branch 2 taken
2067 31: if (llvm::Constant *C = GetMethodConstant(MD))
2068 30: InstanceMethods.push_back(C);
30: branch 1 taken
1: branch 2 taken
2069 31: if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
28: branch 1 taken
2: branch 2 taken
2070 30: if (llvm::Constant *C = GetMethodConstant(MD))
2071 28: InstanceMethods.push_back(C);
2072 : }
2073 : }
2074 :
2075 113: std::vector<llvm::Constant*> Values(12);
2076 113: Values[ 0] = EmitMetaClass(ID, Protocols, ClassMethods);
50: branch 1 taken
63: branch 2 taken
2077 113: if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
2078 : // Record a reference to the super class.
2079 50: LazySymbols.insert(Super->getIdentifier());
2080 :
2081 : Values[ 1] =
2082 : llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
2083 50: ObjCTypes.ClassPtrTy);
2084 : } else {
2085 63: Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
2086 : }
2087 113: Values[ 2] = GetClassName(ID->getIdentifier());
2088 : // Version is always 0.
2089 113: Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
2090 113: Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
2091 113: Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
2092 113: Values[ 6] = EmitIvarList(ID, false);
2093 : Values[ 7] =
2094 : EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getName(),
2095 : "__OBJC,__inst_meth,regular,no_dead_strip",
2096 113: InstanceMethods);
2097 : // cache is always NULL.
2098 113: Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
2099 113: Values[ 9] = Protocols;
2100 113: Values[10] = BuildIvarLayout(ID, true);
2101 113: Values[11] = EmitClassExtension(ID);
2102 : llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
2103 113: Values);
2104 113: std::string Name("\01L_OBJC_CLASS_");
2105 113: Name += ClassName;
2106 113: const char *Section = "__OBJC,__class,regular,no_dead_strip";
2107 : // Check for a forward reference.
2108 113: llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
9: branch 0 taken
104: branch 1 taken
2109 113: if (GV) {
2110 : assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
9: branch 2 taken
0: branch 3 not taken
2111 9: "Forward metaclass reference has incorrect type.");
2112 9: GV->setLinkage(llvm::GlobalValue::InternalLinkage);
2113 9: GV->setInitializer(Init);
2114 9: GV->setSection(Section);
2115 9: GV->setAlignment(4);
2116 9: CGM.AddUsedGlobal(GV);
2117 : }
2118 : else
2119 104: GV = CreateMetadataVar(Name, Init, Section, 4, true);
2120 113: DefinedClasses.push_back(GV);
2121 113: }
2122 :
2123 : llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
2124 : llvm::Constant *Protocols,
2125 113: const ConstantVector &Methods) {
2126 113: unsigned Flags = eClassFlags_Meta;
2127 113: unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassTy);
2128 :
1: branch 2 taken
112: branch 3 taken
2129 113: if (CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden)
2130 1: Flags |= eClassFlags_Hidden;
2131 :
2132 113: std::vector<llvm::Constant*> Values(12);
2133 : // The isa for the metaclass is the root of the hierarchy.
2134 113: const ObjCInterfaceDecl *Root = ID->getClassInterface();
65: branch 1 taken
113: branch 2 taken
2135 243: while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
2136 65: Root = Super;
2137 : Values[ 0] =
2138 : llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()),
2139 113: ObjCTypes.ClassPtrTy);
2140 : // The super class for the metaclass is emitted as the name of the
2141 : // super class. The runtime fixes this up to point to the
2142 : // *metaclass* for the super class.
50: branch 2 taken
63: branch 3 taken
2143 113: if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
2144 : Values[ 1] =
2145 : llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
2146 50: ObjCTypes.ClassPtrTy);
2147 : } else {
2148 63: Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
2149 : }
2150 113: Values[ 2] = GetClassName(ID->getIdentifier());
2151 : // Version is always 0.
2152 113: Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
2153 113: Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
2154 113: Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
2155 113: Values[ 6] = EmitIvarList(ID, true);
2156 : Values[ 7] =
2157 : EmitMethodList("\01L_OBJC_CLASS_METHODS_" + ID->getNameAsString(),
2158 : "__OBJC,__cls_meth,regular,no_dead_strip",
2159 113: Methods);
2160 : // cache is always NULL.
2161 113: Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
2162 113: Values[ 9] = Protocols;
2163 : // ivar_layout for metaclass is always NULL.
2164 113: Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
2165 : // The class extension is always unused for metaclasses.
2166 113: Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
2167 : llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
2168 113: Values);
2169 :
2170 113: std::string Name("\01L_OBJC_METACLASS_");
2171 113: Name += ID->getNameAsCString();
2172 :
2173 : // Check for a forward reference.
2174 113: llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
4: branch 0 taken
109: branch 1 taken
2175 113: if (GV) {
2176 : assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
4: branch 2 taken
0: branch 3 not taken
2177 4: "Forward metaclass reference has incorrect type.");
2178 4: GV->setLinkage(llvm::GlobalValue::InternalLinkage);
2179 4: GV->setInitializer(Init);
2180 : } else {
2181 : GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
2182 : llvm::GlobalValue::InternalLinkage,
2183 109: Init, Name);
2184 : }
2185 113: GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
2186 113: GV->setAlignment(4);
2187 113: CGM.AddUsedGlobal(GV);
2188 :
2189 113: return GV;
2190 : }
2191 :
2192 10: llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
2193 10: std::string Name = "\01L_OBJC_METACLASS_" + ID->getNameAsString();
2194 :
2195 : // FIXME: Should we look these up somewhere other than the module. Its a bit
2196 : // silly since we only generate these while processing an implementation, so
2197 : // exactly one pointer would work if know when we entered/exitted an
2198 : // implementation block.
2199 :
2200 : // Check for an existing forward reference.
2201 : // Previously, metaclass with internal linkage may have been defined.
2202 : // pass 'true' as 2nd argument so it is returned.
6: branch 0 taken
4: branch 1 taken
2203 10: if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
2204 10: true)) {
2205 : assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
6: branch 2 taken
0: branch 3 not taken
2206 6: "Forward metaclass reference has incorrect type.");
2207 6: return GV;
2208 : } else {
2209 : // Generate as an external reference to keep a consistent
2210 : // module. This will be patched up when we emit the metaclass.
2211 : return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
2212 : llvm::GlobalValue::ExternalLinkage,
2213 : 0,
2214 4: Name);
2215 10: }
2216 : }
2217 :
2218 21: llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
2219 21: std::string Name = "\01L_OBJC_CLASS_" + ID->getNameAsString();
2220 :
12: branch 0 taken
9: branch 1 taken
2221 21: if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
2222 21: true)) {
2223 : assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
12: branch 2 taken
0: branch 3 not taken
2224 12: "Forward class metadata reference has incorrect type.");
2225 12: return GV;
2226 : } else {
2227 : return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
2228 : llvm::GlobalValue::ExternalLinkage,
2229 : 0,
2230 9: Name);
2231 21: }
2232 : }
2233 :
2234 : /*
2235 : struct objc_class_ext {
2236 : uint32_t size;
2237 : const char *weak_ivar_layout;
2238 : struct _objc_property_list *properties;
2239 : };
2240 : */
2241 : llvm::Constant *
2242 113: CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
2243 : uint64_t Size =
2244 113: CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
2245 :
2246 113: std::vector<llvm::Constant*> Values(3);
2247 113: Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
2248 113: Values[1] = BuildIvarLayout(ID, false);
2249 : Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
2250 113: ID, ID->getClassInterface(), ObjCTypes);
2251 :
2252 : // Return null if no extension bits are used.
109: branch 2 taken
4: branch 3 taken
87: branch 6 taken
22: branch 7 taken
87: branch 8 taken
26: branch 9 taken
2253 113: if (Values[1]->isNullValue() && Values[2]->isNullValue())
2254 87: return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
2255 :
2256 : llvm::Constant *Init =
2257 26: llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
2258 : return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getName(),
2259 : Init, "__OBJC,__class_ext,regular,no_dead_strip",
2260 26: 4, true);
2261 : }
2262 :
2263 : /*
2264 : struct objc_ivar {
2265 : char *ivar_name;
2266 : char *ivar_type;
2267 : int ivar_offset;
2268 : };
2269 :
2270 : struct objc_ivar_list {
2271 : int ivar_count;
2272 : struct objc_ivar list[count];
2273 : };
2274 : */
2275 : llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
2276 226: bool ForClass) {
2277 226: std::vector<llvm::Constant*> Ivars, Ivar(3);
2278 :
2279 : // When emitting the root class GCC emits ivar entries for the
2280 : // actual class structure. It is not clear if we need to follow this
2281 : // behavior; for now lets try and get away with not doing it. If so,
2282 : // the cleanest solution would be to make up an ObjCInterfaceDecl
2283 : // for the class.
113: branch 0 taken
113: branch 1 taken
2284 226: if (ForClass)
2285 113: return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
2286 :
2287 : ObjCInterfaceDecl *OID =
2288 113: const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
2289 :
2290 113: llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
2291 113: CGM.getContext().ShallowCollectObjCIvars(OID, OIvars);
2292 :
156: branch 1 taken
113: branch 2 taken
2293 269: for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
2294 156: ObjCIvarDecl *IVD = OIvars[i];
2295 : // Ignore unnamed bit-fields.
2: branch 2 taken
154: branch 3 taken
2296 156: if (!IVD->getDeclName())
2297 2: continue;
2298 154: Ivar[0] = GetMethodVarName(IVD->getIdentifier());
2299 154: Ivar[1] = GetMethodVarType(IVD);
2300 : Ivar[2] = llvm::ConstantInt::get(ObjCTypes.IntTy,
2301 154: ComputeIvarBaseOffset(CGM, OID, IVD));
2302 154: Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar));
2303 : }
2304 :
2305 : // Return null for empty list.
67: branch 1 taken
46: branch 2 taken
2306 113: if (Ivars.empty())
2307 67: return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
2308 :
2309 46: std::vector<llvm::Constant*> Values(2);
2310 46: Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
2311 : llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy,
2312 46: Ivars.size());
2313 46: Values[1] = llvm::ConstantArray::get(AT, Ivars);
2314 46: llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
2315 :
2316 : llvm::GlobalVariable *GV;
0: branch 0 not taken
46: branch 1 taken
2317 46: if (ForClass)
2318 : GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getName(),
2319 : Init, "__OBJC,__class_vars,regular,no_dead_strip",
2320 0: 4, true);
2321 : else
2322 : GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" + ID->getName(),
2323 : Init, "__OBJC,__instance_vars,regular,no_dead_strip",
2324 46: 4, true);
2325 46: return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
2326 : }
2327 :
2328 : /*
2329 : struct objc_method {
2330 : SEL method_name;
2331 : char *method_types;
2332 : void *method;
2333 : };
2334 :
2335 : struct objc_method_list {
2336 : struct objc_method_list *obsolete;
2337 : int count;
2338 : struct objc_method methods_list[count];
2339 : };
2340 : */
2341 :
2342 : /// GetMethodConstant - Return a struct objc_method constant for the
2343 : /// given method if it has been defined. The result is null if the
2344 : /// method has not been defined. The return value has type MethodPtrTy.
2345 213: llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
2346 : // FIXME: Use DenseMap::lookup
2347 213: llvm::Function *Fn = MethodDefinitions[MD];
3: branch 0 taken
210: branch 1 taken
2348 213: if (!Fn)
2349 3: return 0;
2350 :
2351 210: std::vector<llvm::Constant*> Method(3);
2352 : Method[0] =
2353 : llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
2354 210: ObjCTypes.SelectorPtrTy);
2355 210: Method[1] = GetMethodVarType(MD);
2356 210: Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
2357 210: return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
2358 : }
2359 :
2360 : llvm::Constant *CGObjCMac::EmitMethodList(llvm::Twine Name,
2361 : const char *Section,
2362 250: const ConstantVector &Methods) {
2363 : // Return null for empty list.
158: branch 1 taken
92: branch 2 taken
2364 250: if (Methods.empty())
2365 158: return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy);
2366 :
2367 92: std::vector<llvm::Constant*> Values(3);
2368 92: Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
2369 92: Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
2370 : llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
2371 92: Methods.size());
2372 92: Values[2] = llvm::ConstantArray::get(AT, Methods);
2373 92: llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
2374 :
2375 92: llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
2376 : return llvm::ConstantExpr::getBitCast(GV,
2377 92: ObjCTypes.MethodListPtrTy);
2378 : }
2379 :
2380 : llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
2381 284: const ObjCContainerDecl *CD) {
2382 284: llvm::SmallString<256> Name;
2383 284: GetNameForMethod(OMD, CD, Name);
2384 :
2385 284: CodeGenTypes &Types = CGM.getTypes();
2386 : const llvm::FunctionType *MethodTy =
2387 284: Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic());
2388 : llvm::Function *Method =
2389 : llvm::Function::Create(MethodTy,
2390 : llvm::GlobalValue::InternalLinkage,
2391 : Name.str(),
2392 284: &CGM.getModule());
2393 284: MethodDefinitions.insert(std::make_pair(OMD, Method));
2394 :
2395 284: return Method;
2396 : }
2397 :
2398 : llvm::GlobalVariable *
2399 : CGObjCCommonMac::CreateMetadataVar(llvm::Twine Name,
2400 : llvm::Constant *Init,
2401 : const char *Section,
2402 : unsigned Align,
2403 2108: bool AddToUsed) {
2404 2108: const llvm::Type *Ty = Init->getType();
2405 : llvm::GlobalVariable *GV =
2406 : new llvm::GlobalVariable(CGM.getModule(), Ty, false,
2407 2108: llvm::GlobalValue::InternalLinkage, Init, Name);
2106: branch 0 taken
2: branch 1 taken
2408 2108: if (Section)
2409 2106: GV->setSection(Section);
1996: branch 0 taken
112: branch 1 taken
2410 2108: if (Align)
2411 1996: GV->setAlignment(Align);
2098: branch 0 taken
10: branch 1 taken
2412 2108: if (AddToUsed)
2413 2098: CGM.AddUsedGlobal(GV);
2414 2108: return GV;
2415 : }
2416 :
2417 109: llvm::Function *CGObjCMac::ModuleInitFunction() {
2418 : // Abuse this interface function as a place to finalize.
2419 109: FinishModule();
2420 109: return NULL;
2421 : }
2422 :
2423 6: llvm::Constant *CGObjCMac::GetPropertyGetFunction() {
2424 6: return ObjCTypes.getGetPropertyFn();
2425 : }
2426 :
2427 8: llvm::Constant *CGObjCMac::GetPropertySetFunction() {
2428 8: return ObjCTypes.getSetPropertyFn();
2429 : }
2430 :
2431 4: llvm::Constant *CGObjCMac::EnumerationMutationFunction() {
2432 4: return ObjCTypes.getEnumerationMutationFn();
2433 : }
2434 :
2435 : /*
2436 :
2437 : Objective-C setjmp-longjmp (sjlj) Exception Handling
2438 : --
2439 :
2440 : The basic framework for a @try-catch-finally is as follows:
2441 : {
2442 : objc_exception_data d;
2443 : id _rethrow = null;
2444 : bool _call_try_exit = true;
2445 :
2446 : objc_exception_try_enter(&d);
2447 : if (!setjmp(d.jmp_buf)) {
2448 : ... try body ...
2449 : } else {
2450 : // exception path
2451 : id _caught = objc_exception_extract(&d);
2452 :
2453 : // enter new try scope for handlers
2454 : if (!setjmp(d.jmp_buf)) {
2455 : ... match exception and execute catch blocks ...
2456 :
2457 : // fell off end, rethrow.
2458 : _rethrow = _caught;
2459 : ... jump-through-finally to finally_rethrow ...
2460 : } else {
2461 : // exception in catch block
2462 : _rethrow = objc_exception_extract(&d);
2463 : _call_try_exit = false;
2464 : ... jump-through-finally to finally_rethrow ...
2465 : }
2466 : }
2467 : ... jump-through-finally to finally_end ...
2468 :
2469 : finally:
2470 : if (_call_try_exit)
2471 : objc_exception_try_exit(&d);
2472 :
2473 : ... finally block ....
2474 : ... dispatch to finally destination ...
2475 :
2476 : finally_rethrow:
2477 : objc_exception_throw(_rethrow);
2478 :
2479 : finally_end:
2480 : }
2481 :
2482 : This framework differs slightly from the one gcc uses, in that gcc
2483 : uses _rethrow to determine if objc_exception_try_exit should be called
2484 : and if the object should be rethrown. This breaks in the face of
2485 : throwing nil and introduces unnecessary branches.
2486 :
2487 : We specialize this framework for a few particular circumstances:
2488 :
2489 : - If there are no catch blocks, then we avoid emitting the second
2490 : exception handling context.
2491 :
2492 : - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
2493 : e)) we avoid emitting the code to rethrow an uncaught exception.
2494 :
2495 : - FIXME: If there is no @finally block we can do a few more
2496 : simplifications.
2497 :
2498 : Rethrows and Jumps-Through-Finally
2499 : --
2500 :
2501 : Support for implicit rethrows and jumping through the finally block is
2502 : handled by storing the current exception-handling context in
2503 : ObjCEHStack.
2504 :
2505 : In order to implement proper @finally semantics, we support one basic
2506 : mechanism for jumping through the finally block to an arbitrary
2507 : destination. Constructs which generate exits from a @try or @catch
2508 : block use this mechanism to implement the proper semantics by chaining
2509 : jumps, as necessary.
2510 :
2511 : This mechanism works like the one used for indirect goto: we
2512 : arbitrarily assign an ID to each destination and store the ID for the
2513 : destination in a variable prior to entering the finally block. At the
2514 : end of the finally block we simply create a switch to the proper
2515 : destination.
2516 :
2517 : Code gen for @synchronized(expr) stmt;
2518 : Effectively generating code for:
2519 : objc_sync_enter(expr);
2520 : @try stmt @finally { objc_sync_exit(expr); }
2521 : */
2522 :
2523 : void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
2524 15: const Stmt &S) {
2525 15: bool isTry = isa<ObjCAtTryStmt>(S);
2526 : // Create various blocks we refer to for handling @finally.
2527 15: llvm::BasicBlock *FinallyBlock = CGF.createBasicBlock("finally");
2528 15: llvm::BasicBlock *FinallyExit = CGF.createBasicBlock("finally.exit");
2529 15: llvm::BasicBlock *FinallyNoExit = CGF.createBasicBlock("finally.noexit");
2530 15: llvm::BasicBlock *FinallyRethrow = CGF.createBasicBlock("finally.throw");
2531 15: llvm::BasicBlock *FinallyEnd = CGF.createBasicBlock("finally.end");
2532 :
2533 : // For @synchronized, call objc_sync_enter(sync.expr). The
2534 : // evaluation of the expression must occur before we enter the
2535 : // @synchronized. We can safely avoid a temp here because jumps into
2536 : // @synchronized are illegal & this will dominate uses.
2537 15: llvm::Value *SyncArg = 0;
7: branch 0 taken
8: branch 1 taken
2538 15: if (!isTry) {
2539 : SyncArg =
2540 7: CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
2541 7: SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
2542 7: CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg);
2543 : }
2544 :
2545 : // Push an EH context entry, used for handling rethrows and jumps
2546 : // through finally.
2547 15: CGF.PushCleanupBlock(FinallyBlock);
2548 :
13: branch 1 taken
2: branch 2 taken
2549 15: if (CGF.ObjCEHValueStack.empty())
2550 13: CGF.ObjCEHValueStack.push_back(0);
2551 : // If This is a nested @try, caught exception is that of enclosing @try.
2552 : else
2553 2: CGF.ObjCEHValueStack.push_back(CGF.ObjCEHValueStack.back());
2554 : // Allocate memory for the exception data and rethrow pointer.
2555 : llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
2556 15: "exceptiondata.ptr");
2557 : llvm::Value *RethrowPtr = CGF.CreateTempAlloca(ObjCTypes.ObjectPtrTy,
2558 15: "_rethrow");
2559 : llvm::Value *CallTryExitPtr = CGF.CreateTempAlloca(
2560 : llvm::Type::getInt1Ty(VMContext),
2561 15: "_call_try_exit");
2562 : CGF.Builder.CreateStore(llvm::ConstantInt::getTrue(VMContext),
2563 15: CallTryExitPtr);
2564 :
2565 : // Enter a new try block and call setjmp.
2566 15: CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData);
2567 : llvm::Value *JmpBufPtr = CGF.Builder.CreateStructGEP(ExceptionData, 0,
2568 15: "jmpbufarray");
2569 15: JmpBufPtr = CGF.Builder.CreateStructGEP(JmpBufPtr, 0, "tmp");
2570 : llvm::Value *SetJmpResult = CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(),
2571 15: JmpBufPtr, "result");
2572 :
2573 15: llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
2574 15: llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
2575 : CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(SetJmpResult, "threw"),
2576 15: TryHandler, TryBlock);
2577 :
2578 : // Emit the @try block.
2579 15: CGF.EmitBlock(TryBlock);
2580 : CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
8: branch 0 taken
7: branch 1 taken
2581 15: : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
2582 15: CGF.EmitBranchThroughCleanup(FinallyEnd);
2583 :
2584 : // Emit the "exception in @try" block.
2585 15: CGF.EmitBlock(TryHandler);
2586 :
2587 : // Retrieve the exception object. We may emit multiple blocks but
2588 : // nothing can cross this so the value is already in SSA form.
2589 : llvm::Value *Caught =
2590 : CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
2591 15: ExceptionData, "caught");
2592 15: CGF.ObjCEHValueStack.back() = Caught;
7: branch 0 taken
8: branch 1 taken
2593 15: if (!isTry) {
2594 7: CGF.Builder.CreateStore(Caught, RethrowPtr);
2595 : CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext),
2596 7: CallTryExitPtr);
2597 7: CGF.EmitBranchThroughCleanup(FinallyRethrow);
7: branch 0 taken
1: branch 1 taken
2598 8: } else if (const ObjCAtCatchStmt* CatchStmt =
2599 8: cast<ObjCAtTryStmt>(S).getCatchStmts()) {
2600 : // Enter a new exception try block (in case a @catch block throws
2601 : // an exception).
2602 7: CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData);
2603 :
2604 : llvm::Value *SetJmpResult = CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(),
2605 7: JmpBufPtr, "result");
2606 7: llvm::Value *Threw = CGF.Builder.CreateIsNotNull(SetJmpResult, "threw");
2607 :
2608 7: llvm::BasicBlock *CatchBlock = CGF.createBasicBlock("catch");
2609 7: llvm::BasicBlock *CatchHandler = CGF.createBasicBlock("catch.handler");
2610 7: CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
2611 :
2612 7: CGF.EmitBlock(CatchBlock);
2613 :
2614 : // Handle catch list. As a special case we check if everything is
2615 : // matched and avoid generating code for falling off the end if
2616 : // so.
2617 7: bool AllMatched = false;
9: branch 1 taken
2: branch 2 taken
2618 22: for (; CatchStmt; CatchStmt = CatchStmt->getNextCatchStmt()) {
2619 9: llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch");
2620 :
2621 9: const ParmVarDecl *CatchParam = CatchStmt->getCatchParamDecl();
2622 9: const ObjCObjectPointerType *OPT = 0;
2623 :
2624 : // catch(...) always matches.
2: branch 0 taken
7: branch 1 taken
2625 9: if (!CatchParam) {
2626 2: AllMatched = true;
2627 : } else {
2628 7: OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
2629 :
2630 : // catch(id e) always matches.
2631 : // FIXME: For the time being we also match id<X>; this should
2632 : // be rejected by Sema instead.
7: branch 0 taken
0: branch 1 not taken
4: branch 3 taken
3: branch 4 taken
0: branch 6 not taken
4: branch 7 taken
3: branch 8 taken
4: branch 9 taken
2633 7: if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
2634 3: AllMatched = true;
2635 : }
2636 :
5: branch 0 taken
4: branch 1 taken
2637 9: if (AllMatched) {
3: branch 0 taken
2: branch 1 taken
2638 5: if (CatchParam) {
2639 3: CGF.EmitLocalBlockVarDecl(*CatchParam);
3: branch 1 taken
0: branch 2 not taken
2640 3: assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
2641 3: CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam));
2642 : }
2643 :
2644 5: CGF.EmitStmt(CatchStmt->getCatchBody());
2645 5: CGF.EmitBranchThroughCleanup(FinallyEnd);
2646 5: break;
2647 : }
2648 :
0: branch 0 not taken
4: branch 1 taken
2649 4: assert(OPT && "Unexpected non-object pointer type in @catch");
2650 4: QualType T = OPT->getPointeeType();
2651 4: const ObjCInterfaceType *ObjCType = T->getAs<ObjCInterfaceType>();
0: branch 0 not taken
4: branch 1 taken
2652 4: assert(ObjCType && "Catch parameter must have Objective-C type!");
2653 :
2654 : // Check if the @catch block matches the exception object.
2655 4: llvm::Value *Class = EmitClassRef(CGF.Builder, ObjCType->getDecl());
2656 :
2657 : llvm::Value *Match =
2658 : CGF.Builder.CreateCall2(ObjCTypes.getExceptionMatchFn(),
2659 4: Class, Caught, "match");
2660 :
2661 4: llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("matched");
2662 :
2663 : CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
2664 4: MatchedBlock, NextCatchBlock);
2665 :
2666 : // Emit the @catch block.
2667 4: CGF.EmitBlock(MatchedBlock);
2668 4: CGF.EmitLocalBlockVarDecl(*CatchParam);
4: branch 1 taken
0: branch 2 not taken
2669 4: assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
2670 :
2671 : llvm::Value *Tmp =
2672 : CGF.Builder.CreateBitCast(Caught,
2673 : CGF.ConvertType(CatchParam->getType()),
2674 4: "tmp");
2675 4: CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam));
2676 :
2677 4: CGF.EmitStmt(CatchStmt->getCatchBody());
2678 4: CGF.EmitBranchThroughCleanup(FinallyEnd);
2679 :
2680 4: CGF.EmitBlock(NextCatchBlock);
2681 : }
2682 :
2: branch 0 taken
5: branch 1 taken
2683 7: if (!AllMatched) {
2684 : // None of the handlers caught the exception, so store it to be
2685 : // rethrown at the end of the @finally block.
2686 2: CGF.Builder.CreateStore(Caught, RethrowPtr);
2687 2: CGF.EmitBranchThroughCleanup(FinallyRethrow);
2688 : }
2689 :
2690 : // Emit the exception handler for the @catch blocks.
2691 7: CGF.EmitBlock(CatchHandler);
2692 : CGF.Builder.CreateStore(
2693 : CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
2694 : ExceptionData),
2695 7: RethrowPtr);
2696 : CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext),
2697 7: CallTryExitPtr);
2698 7: CGF.EmitBranchThroughCleanup(FinallyRethrow);
2699 : } else {
2700 1: CGF.Builder.CreateStore(Caught, RethrowPtr);
2701 : CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext),
2702 1: CallTryExitPtr);
2703 1: CGF.EmitBranchThroughCleanup(FinallyRethrow);
2704 : }
2705 :
2706 : // Pop the exception-handling stack entry. It is important to do
2707 : // this now, because the code in the @finally block is not in this
2708 : // context.
2709 15: CodeGenFunction::CleanupBlockInfo Info = CGF.PopCleanupBlock();
2710 :
2711 15: CGF.ObjCEHValueStack.pop_back();
2712 :
2713 : // Emit the @finally block.
2714 15: CGF.EmitBlock(FinallyBlock);
2715 15: llvm::Value* CallTryExit = CGF.Builder.CreateLoad(CallTryExitPtr, "tmp");
2716 :
2717 15: CGF.Builder.CreateCondBr(CallTryExit, FinallyExit, FinallyNoExit);
2718 :
2719 15: CGF.EmitBlock(FinallyExit);
2720 15: CGF.Builder.CreateCall(ObjCTypes.getExceptionTryExitFn(), ExceptionData);
2721 :
2722 15: CGF.EmitBlock(FinallyNoExit);
8: branch 0 taken
7: branch 1 taken
2723 15: if (isTry) {
3: branch 0 taken
5: branch 1 taken
2724 8: if (const ObjCAtFinallyStmt* FinallyStmt =
2725 8: cast<ObjCAtTryStmt>(S).getFinallyStmt())
2726 3: CGF.EmitStmt(FinallyStmt->getFinallyBody());
2727 : } else {
2728 : // Emit objc_sync_exit(expr); as finally's sole statement for
2729 : // @synchronized.
2730 7: CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg);
2731 : }
2732 :
2733 : // Emit the switch block
15: branch 0 taken
0: branch 1 not taken
2734 15: if (Info.SwitchBlock)
2735 15: CGF.EmitBlock(Info.SwitchBlock);
15: branch 0 taken
0: branch 1 not taken
2736 15: if (Info.EndBlock)
2737 15: CGF.EmitBlock(Info.EndBlock);
2738 :
2739 15: CGF.EmitBlock(FinallyRethrow);
2740 : CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(),
2741 15: CGF.Builder.CreateLoad(RethrowPtr));
2742 15: CGF.Builder.CreateUnreachable();
2743 :
2744 15: CGF.EmitBlock(FinallyEnd);
2745 15: }
2746 :
2747 : void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
2748 6: const ObjCAtThrowStmt &S) {
2749 : llvm::Value *ExceptionAsObject;
2750 :
3: branch 1 taken
3: branch 2 taken
2751 6: if (const Expr *ThrowExpr = S.getThrowExpr()) {
2752 3: llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
2753 : ExceptionAsObject =
2754 3: CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp");
2755 : } else {
2756 : assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
3: branch 1 taken
0: branch 2 not taken
3: branch 4 taken
0: branch 5 not taken
2757 3: "Unexpected rethrow outside @catch block.");
2758 3: ExceptionAsObject = CGF.ObjCEHValueStack.back();
2759 : }
2760 :
2761 6: CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject);
2762 6: CGF.Builder.CreateUnreachable();
2763 :
2764 : // Clear the insertion point to indicate we are in unreachable code.
2765 6: CGF.Builder.ClearInsertionPoint();
2766 6: }
2767 :
2768 : /// EmitObjCWeakRead - Code gen for loading value of a __weak
2769 : /// object: objc_read_weak (id *src)
2770 : ///
2771 : llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
2772 14: llvm::Value *AddrWeakObj) {
2773 : const llvm::Type* DestTy =
2774 14: cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
2775 : AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
2776 14: ObjCTypes.PtrObjectPtrTy);
2777 : llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
2778 14: AddrWeakObj, "weakread");
2779 14: read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
2780 14: return read_weak;
2781 : }
2782 :
2783 : /// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
2784 : /// objc_assign_weak (id src, id *dst)
2785 : ///
2786 : void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
2787 10: llvm::Value *src, llvm::Value *dst) {
2788 10: const llvm::Type * SrcTy = src->getType();
0: branch 1 not taken
10: branch 2 taken
2789 10: if (!isa<llvm::PointerType>(SrcTy)) {
2790 0: unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
0: branch 0 not taken
0: branch 1 not taken
2791 0: assert(Size <= 8 && "does not support size > 8");
2792 : src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
0: branch 0 not taken
0: branch 1 not taken
2793 0: : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
2794 0: src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
2795 : }
2796 10: src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
2797 10: dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
2798 : CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
2799 10: src, dst, "weakassign");
2800 : return;
2801 : }
2802 :
2803 : /// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
2804 : /// objc_assign_global (id src, id *dst)
2805 : ///
2806 : void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
2807 53: llvm::Value *src, llvm::Value *dst) {
2808 53: const llvm::Type * SrcTy = src->getType();
0: branch 1 not taken
53: branch 2 taken
2809 53: if (!isa<llvm::PointerType>(SrcTy)) {
2810 0: unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
0: branch 0 not taken
0: branch 1 not taken
2811 0: assert(Size <= 8 && "does not support size > 8");
2812 : src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
0: branch 0 not taken
0: branch 1 not taken
2813 0: : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
2814 0: src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
2815 : }
2816 53: src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
2817 53: dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
2818 : CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
2819 53: src, dst, "globalassign");
2820 : return;
2821 : }
2822 :
2823 : /// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
2824 : /// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
2825 : ///
2826 : void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
2827 : llvm::Value *src, llvm::Value *dst,
2828 28: llvm::Value *ivarOffset) {
0: branch 0 not taken
28: branch 1 taken
2829 28: assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
2830 28: const llvm::Type * SrcTy = src->getType();
0: branch 1 not taken
28: branch 2 taken
2831 28: if (!isa<llvm::PointerType>(SrcTy)) {
2832 0: unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
0: branch 0 not taken
0: branch 1 not taken
2833 0: assert(Size <= 8 && "does not support size > 8");
2834 : src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
0: branch 0 not taken
0: branch 1 not taken
2835 0: : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
2836 0: src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
2837 : }
2838 28: src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
2839 28: dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
2840 : CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
2841 28: src, dst, ivarOffset);
2842 : return;
2843 : }
2844 :
2845 : /// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
2846 : /// objc_assign_strongCast (id src, id *dst)
2847 : ///
2848 : void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
2849 17: llvm::Value *src, llvm::Value *dst) {
2850 17: const llvm::Type * SrcTy = src->getType();
0: branch 1 not taken
17: branch 2 taken
2851 17: if (!isa<llvm::PointerType>(SrcTy)) {
2852 0: unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
0: branch 0 not taken
0: branch 1 not taken
2853 0: assert(Size <= 8 && "does not support size > 8");
2854 : src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
0: branch 0 not taken
0: branch 1 not taken
2855 0: : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
2856 0: src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
2857 : }
2858 17: src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
2859 17: dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
2860 : CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
2861 17: src, dst, "weakassign");
2862 : return;
2863 : }
2864 :
2865 : void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
2866 : llvm::Value *DestPtr,
2867 : llvm::Value *SrcPtr,
2868 5: QualType Ty) {
2869 : // Get size info for this aggregate.
2870 5: std::pair<uint64_t, unsigned> TypeInfo = CGM.getContext().getTypeInfo(Ty);
2871 5: unsigned long size = TypeInfo.first/8;
2872 5: SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
2873 5: DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
2874 5: llvm::Value *N = llvm::ConstantInt::get(ObjCTypes.LongTy, size);
2875 : CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
2876 5: DestPtr, SrcPtr, N);
2877 : return;
2878 : }
2879 :
2880 : /// EmitObjCValueForIvar - Code Gen for ivar reference.
2881 : ///
2882 : LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
2883 : QualType ObjectTy,
2884 : llvm::Value *BaseValue,
2885 : const ObjCIvarDecl *Ivar,
2886 235: unsigned CVRQualifiers) {
2887 235: const ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCInterfaceType>()->getDecl();
2888 : return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
2889 235: EmitIvarOffset(CGF, ID, Ivar));
2890 : }
2891 :
2892 : llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
2893 : const ObjCInterfaceDecl *Interface,
2894 249: const ObjCIvarDecl *Ivar) {
2895 249: uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
2896 : return llvm::ConstantInt::get(
2897 : CGM.getTypes().ConvertType(CGM.getContext().LongTy),
2898 249: Offset);
2899 : }
2900 :
2901 : /* *** Private Interface *** */
2902 :
2903 : /// EmitImageInfo - Emit the image info marker used to encode some module
2904 : /// level information.
2905 : ///
2906 : /// See: <rdr://4810609&4810587&4810587>
2907 : /// struct IMAGE_INFO {
2908 : /// unsigned version;
2909 : /// unsigned flags;
2910 : /// };
2911 : enum ImageInfoFlags {
2912 : eImageInfo_FixAndContinue = (1 << 0), // FIXME: Not sure what
2913 : // this implies.
2914 : eImageInfo_GarbageCollected = (1 << 1),
2915 : eImageInfo_GCOnly = (1 << 2),
2916 : eImageInfo_OptimizedByDyld = (1 << 3), // FIXME: When is this set.
2917 :
2918 : // A flag indicating that the module has no instances of an
2919 : // @synthesize of a superclass variable. <rdar://problem/6803242>
2920 : eImageInfo_CorrectedSynthesize = (1 << 4)
2921 : };
2922 :
2923 110: void CGObjCMac::EmitImageInfo() {
2924 110: unsigned version = 0; // Version is unused?
2925 110: unsigned flags = 0;
2926 :
2927 : // FIXME: Fix and continue?
24: branch 2 taken
86: branch 3 taken
2928 110: if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC)
2929 24: flags |= eImageInfo_GarbageCollected;
1: branch 2 taken
109: branch 3 taken
2930 110: if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly)
2931 1: flags |= eImageInfo_GCOnly;
2932 :
2933 : // We never allow @synthesize of a superclass property.
2934 110: flags |= eImageInfo_CorrectedSynthesize;
2935 :
2936 : // Emitted as int[2];
2937 : llvm::Constant *values[2] = {
2938 : llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), version),
2939 : llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), flags)
2940 110: };
2941 110: llvm::ArrayType *AT = llvm::ArrayType::get(llvm::Type::getInt32Ty(VMContext), 2);
2942 :
2943 : const char *Section;
110: branch 0 taken
0: branch 1 not taken
2944 110: if (ObjCABI == 1)
2945 110: Section = "__OBJC, __image_info,regular";
2946 : else
2947 0: Section = "__DATA, __objc_imageinfo, regular, no_dead_strip";
2948 : llvm::GlobalVariable *GV =
2949 : CreateMetadataVar("\01L_OBJC_IMAGE_INFO",
2950 : llvm::ConstantArray::get(AT, values, 2),
2951 : Section,
2952 : 0,
2953 110: true);
2954 110: GV->setConstant(true);
2955 110: }
2956 :
2957 :
2958 : // struct objc_module {
2959 : // unsigned long version;
2960 : // unsigned long size;
2961 : // const char *name;
2962 : // Symtab symtab;
2963 : // };
2964 :
2965 : // FIXME: Get from somewhere
2966 : static const int ModuleVersion = 7;
2967 :
2968 109: void CGObjCMac::EmitModuleInfo() {
2969 109: uint64_t Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ModuleTy);
2970 :
2971 109: std::vector<llvm::Constant*> Values(4);
2972 109: Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion);
2973 109: Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
2974 : // This used to be the filename, now it is unused. <rdr://4327263>
2975 109: Values[2] = GetClassName(&CGM.getContext().Idents.get(""));
2976 109: Values[3] = EmitModuleSymbols();
2977 : CreateMetadataVar("\01L_OBJC_MODULES",
2978 : llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values),
2979 : "__OBJC,__module_info,regular,no_dead_strip",
2980 109: 4, true);
2981 109: }
2982 :
2983 109: llvm::Constant *CGObjCMac::EmitModuleSymbols() {
2984 109: unsigned NumClasses = DefinedClasses.size();
2985 109: unsigned NumCategories = DefinedCategories.size();
2986 :
2987 : // Return null if no symbols were defined.
42: branch 0 taken
67: branch 1 taken
40: branch 2 taken
2: branch 3 taken
2988 109: if (!NumClasses && !NumCategories)
2989 40: return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
2990 :
2991 69: std::vector<llvm::Constant*> Values(5);
2992 69: Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
2993 69: Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy);
2994 69: Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses);
2995 69: Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories);
2996 :
2997 : // The runtime expects exactly the list of defined classes followed
2998 : // by the list of defined categories, in a single array.
2999 69: std::vector<llvm::Constant*> Symbols(NumClasses + NumCategories);
113: branch 0 taken
69: branch 1 taken
3000 182: for (unsigned i=0; i<NumClasses; i++)
3001 : Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i],
3002 113: ObjCTypes.Int8PtrTy);
12: branch 0 taken
69: branch 1 taken
3003 81: for (unsigned i=0; i<NumCategories; i++)
3004 : Symbols[NumClasses + i] =
3005 : llvm::ConstantExpr::getBitCast(DefinedCategories[i],
3006 12: ObjCTypes.Int8PtrTy);
3007 :
3008 : Values[4] =
3009 : llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
3010 : NumClasses + NumCategories),
3011 69: Symbols);
3012 :
3013 69: llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
3014 :
3015 : llvm::GlobalVariable *GV =
3016 : CreateMetadataVar("\01L_OBJC_SYMBOLS", Init,
3017 : "__OBJC,__symbols,regular,no_dead_strip",
3018 69: 4, true);
3019 69: return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
3020 : }
3021 :
3022 : llvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder,
3023 42: const ObjCInterfaceDecl *ID) {
3024 42: LazySymbols.insert(ID->getIdentifier());
3025 :
3026 42: llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
3027 :
33: branch 0 taken
9: branch 1 taken
3028 42: if (!Entry) {
3029 : llvm::Constant *Casted =
3030 : llvm::ConstantExpr::getBitCast(GetClassName(ID->getIdentifier()),
3031 33: ObjCTypes.ClassPtrTy);
3032 : Entry =
3033 : CreateMetadataVar("\01L_OBJC_CLASS_REFERENCES_", Casted,
3034 : "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
3035 33: 4, true);
3036 : }
3037 :
3038 42: return Builder.CreateLoad(Entry, "tmp");
3039 : }
3040 :
3041 200: llvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel) {
3042 200: llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
3043 :
114: branch 0 taken
86: branch 1 taken
3044 200: if (!Entry) {
3045 : llvm::Constant *Casted =
3046 : llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
3047 114: ObjCTypes.SelectorPtrTy);
3048 : Entry =
3049 : CreateMetadataVar("\01L_OBJC_SELECTOR_REFERENCES_", Casted,
3050 : "__OBJC,__message_refs,literal_pointers,no_dead_strip",
3051 114: 4, true);
3052 : }
3053 :
3054 200: return Builder.CreateLoad(Entry, "tmp");
3055 : }
3056 :
3057 730: llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) {
3058 730: llvm::GlobalVariable *&Entry = ClassNames[Ident];
3059 :
351: branch 0 taken
379: branch 1 taken
3060 730: if (!Entry)
3061 : Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
3062 : llvm::ConstantArray::get(VMContext,
3063 : Ident->getNameStart()),
3064 : "__TEXT,__cstring,cstring_literals",
3065 351: 1, true);
3066 :
3067 730: return getConstantGEP(VMContext, Entry, 0, 0);
3068 : }
3069 :
3070 : /// GetIvarLayoutName - Returns a unique constant for the given
3071 : /// ivar layout bitmap.
3072 : llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
3073 84: const ObjCCommonTypesHelper &ObjCTypes) {
3074 84: return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
3075 : }
3076 :
3077 154: static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) {
20: branch 1 taken
134: branch 2 taken
3078 154: if (FQT.isObjCGCStrong())
3079 20: return Qualifiers::Strong;
3080 :
18: branch 1 taken
116: branch 2 taken
3081 134: if (FQT.isObjCGCWeak())
3082 18: return Qualifiers::Weak;
3083 :
64: branch 2 taken
52: branch 3 taken
0: branch 6 not taken
64: branch 7 taken
52: branch 8 taken
64: branch 9 taken
3084 116: if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
3085 52: return Qualifiers::Strong;
3086 :
26: branch 2 taken
38: branch 3 taken
3087 64: if (const PointerType *PT = FQT->getAs<PointerType>())
3088 26: return GetGCAttrTypeForType(Ctx, PT->getPointeeType());
3089 :
3090 38: return Qualifiers::GCNone;
3091 : }
3092 :
3093 : void CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT,
3094 : unsigned int BytePos,
3095 : bool ForStrongLayout,
3096 26: bool &HasUnion) {
3097 26: const RecordDecl *RD = RT->getDecl();
3098 : // FIXME - Use iterator.
3099 26: llvm::SmallVector<FieldDecl*, 16> Fields(RD->field_begin(), RD->field_end());
3100 26: const llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
3101 : const llvm::StructLayout *RecLayout =
3102 26: CGM.getTargetData().getStructLayout(cast<llvm::StructType>(Ty));
3103 :
3104 : BuildAggrIvarLayout(0, RecLayout, RD, Fields, BytePos,
3105 26: ForStrongLayout, HasUnion);
3106 26: }
3107 :
3108 : void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
3109 : const llvm::StructLayout *Layout,
3110 : const RecordDecl *RD,
3111 : const llvm::SmallVectorImpl<FieldDecl*> &RecFields,
3112 : unsigned int BytePos, bool ForStrongLayout,
3113 64: bool &HasUnion) {
26: branch 0 taken
38: branch 1 taken
0: branch 3 not taken
26: branch 4 taken
3114 64: bool IsUnion = (RD && RD->isUnion());
3115 64: uint64_t MaxUnionIvarSize = 0;
3116 64: uint64_t MaxSkippedUnionIvarSize = 0;
3117 64: FieldDecl *MaxField = 0;
3118 64: FieldDecl *MaxSkippedField = 0;
3119 64: FieldDecl *LastFieldBitfield = 0;
3120 64: uint64_t MaxFieldOffset = 0;
3121 64: uint64_t MaxSkippedFieldOffset = 0;
3122 64: uint64_t LastBitfieldOffset = 0;
3123 :
0: branch 1 not taken
64: branch 2 taken
3124 64: if (RecFields.empty())
3125 0: return;
3126 64: unsigned WordSizeInBits = CGM.getContext().Target.getPointerWidth(0);
3127 64: unsigned ByteSizeInBits = CGM.getContext().Target.getCharWidth();
3128 :
192: branch 1 taken
64: branch 2 taken
3129 256: for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
3130 192: FieldDecl *Field = RecFields[i];
3131 : uint64_t FieldOffset;
74: branch 0 taken
118: branch 1 taken
3132 192: if (RD) {
32: branch 1 taken
42: branch 2 taken
3133 74: if (Field->isBitField()) {
3134 32: CodeGenTypes::BitFieldInfo Info = CGM.getTypes().getBitFieldInfo(Field);
3135 :
3136 : const llvm::Type *Ty =
3137 32: CGM.getTypes().ConvertTypeForMemRecursive(Field->getType());
3138 : uint64_t TypeSize =
3139 32: CGM.getTypes().getTargetData().getTypeAllocSize(Ty);
3140 32: FieldOffset = Info.FieldNo * TypeSize;
3141 : } else
3142 : FieldOffset =
3143 42: Layout->getElementOffset(CGM.getTypes().getLLVMFieldNo(Field));
3144 : } else
3145 118: FieldOffset = ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field));
3146 :
3147 : // Skip over unnamed or bitfields
192: branch 1 taken
0: branch 2 not taken
38: branch 4 taken
154: branch 5 taken
38: branch 6 taken
154: branch 7 taken
3148 192: if (!Field->getIdentifier() || Field->isBitField()) {
3149 38: LastFieldBitfield = Field;
3150 38: LastBitfieldOffset = FieldOffset;
3151 38: continue;
3152 : }
3153 :
3154 154: LastFieldBitfield = 0;
3155 154: QualType FQT = Field->getType();
136: branch 2 taken
18: branch 3 taken
0: branch 6 not taken
136: branch 7 taken
18: branch 8 taken
136: branch 9 taken
3156 154: if (FQT->isRecordType() || FQT->isUnionType()) {
0: branch 2 not taken
18: branch 3 taken
3157 18: if (FQT->isUnionType())
3158 0: HasUnion = true;
3159 :
3160 : BuildAggrIvarRecordLayout(FQT->getAs<RecordType>(),
3161 : BytePos + FieldOffset,
3162 18: ForStrongLayout, HasUnion);
3163 18: continue;
3164 : }
3165 :
10: branch 2 taken
126: branch 3 taken
3166 136: if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
3167 : const ConstantArrayType *CArray =
3168 10: dyn_cast_or_null<ConstantArrayType>(Array);
3169 10: uint64_t ElCount = CArray->getSize().getZExtValue();
0: branch 0 not taken
10: branch 1 taken
3170 10: assert(CArray && "only array with known element size is supported");
3171 10: FQT = CArray->getElementType();
6: branch 2 taken
10: branch 3 taken
3172 22: while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
3173 : const ConstantArrayType *CArray =
3174 6: dyn_cast_or_null<ConstantArrayType>(Array);
3175 6: ElCount *= CArray->getSize().getZExtValue();
3176 6: FQT = CArray->getElementType();
3177 : }
3178 :
3179 : assert(!FQT->isUnionType() &&
10: branch 2 taken
0: branch 3 not taken
3180 10: "layout for array of unions not supported");
8: branch 2 taken
2: branch 3 taken
3181 10: if (FQT->isRecordType()) {
3182 8: int OldIndex = IvarsInfo.size() - 1;
3183 8: int OldSkIndex = SkipIvars.size() -1;
3184 :
3185 8: const RecordType *RT = FQT->getAs<RecordType>();
3186 : BuildAggrIvarRecordLayout(RT, BytePos + FieldOffset,
3187 8: ForStrongLayout, HasUnion);
3188 :
3189 : // Replicate layout information for each array element. Note that
3190 : // one element is already done.
3191 8: uint64_t ElIx = 1;
10: branch 1 taken
8: branch 2 taken
3192 26: for (int FirstIndex = IvarsInfo.size() - 1,
3193 8: FirstSkIndex = SkipIvars.size() - 1 ;ElIx < ElCount; ElIx++) {
3194 10: uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits;
4: branch 0 taken
10: branch 1 taken
3195 14: for (int i = OldIndex+1; i <= FirstIndex; ++i)
3196 : IvarsInfo.push_back(GC_IVAR(IvarsInfo[i].ivar_bytepos + Size*ElIx,
3197 4: IvarsInfo[i].ivar_size));
16: branch 0 taken
10: branch 1 taken
3198 26: for (int i = OldSkIndex+1; i <= FirstSkIndex; ++i)
3199 : SkipIvars.push_back(GC_IVAR(SkipIvars[i].ivar_bytepos + Size*ElIx,
3200 16: SkipIvars[i].ivar_size));
3201 : }
3202 8: continue;
3203 : }
3204 : }
3205 : // At this point, we are done with Record/Union and array there of.
3206 : // For other arrays we are down to its element type.
3207 128: Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT);
3208 :
3209 128: unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType());
64: branch 0 taken
64: branch 1 taken
28: branch 2 taken
36: branch 3 taken
64: branch 4 taken
28: branch 5 taken
9: branch 6 taken
55: branch 7 taken
3210 173: if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
3211 : || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
0: branch 0 not taken
45: branch 1 taken
3212 45: if (IsUnion) {
3213 0: uint64_t UnionIvarSize = FieldSize / WordSizeInBits;
0: branch 0 not taken
0: branch 1 not taken
3214 0: if (UnionIvarSize > MaxUnionIvarSize) {
3215 0: MaxUnionIvarSize = UnionIvarSize;
3216 0: MaxField = Field;
3217 0: MaxFieldOffset = FieldOffset;
3218 : }
3219 : } else {
3220 : IvarsInfo.push_back(GC_IVAR(BytePos + FieldOffset,
3221 45: FieldSize / WordSizeInBits));
3222 : }
28: branch 0 taken
55: branch 1 taken
9: branch 2 taken
19: branch 3 taken
0: branch 4 not taken
9: branch 5 taken
55: branch 6 taken
0: branch 7 not taken
55: branch 8 taken
0: branch 9 not taken
3223 83: } else if ((ForStrongLayout &&
3224 : (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak))
3225 : || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) {
0: branch 0 not taken
83: branch 1 taken
3226 83: if (IsUnion) {
3227 : // FIXME: Why the asymmetry? We divide by word size in bits on other
3228 : // side.
3229 0: uint64_t UnionIvarSize = FieldSize;
0: branch 0 not taken
0: branch 1 not taken
3230 0: if (UnionIvarSize > MaxSkippedUnionIvarSize) {
3231 0: MaxSkippedUnionIvarSize = UnionIvarSize;
3232 0: MaxSkippedField = Field;
3233 0: MaxSkippedFieldOffset = FieldOffset;
3234 : }
3235 : } else {
3236 : // FIXME: Why the asymmetry, we divide by byte size in bits here?
3237 : SkipIvars.push_back(GC_IVAR(BytePos + FieldOffset,
3238 83: FieldSize / ByteSizeInBits));
3239 : }
3240 : }
3241 : }
3242 :
4: branch 0 taken
60: branch 1 taken
3243 64: if (LastFieldBitfield) {
3244 : // Last field was a bitfield. Must update skip info.
3245 4: Expr *BitWidth = LastFieldBitfield->getBitWidth();
3246 : uint64_t BitFieldSize =
3247 4: BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue();
3248 4: GC_IVAR skivar;
3249 4: skivar.ivar_bytepos = BytePos + LastBitfieldOffset;
3250 : skivar.ivar_size = (BitFieldSize / ByteSizeInBits)
3251 4: + ((BitFieldSize % ByteSizeInBits) != 0);
3252 4: SkipIvars.push_back(skivar);
3253 : }
3254 :
0: branch 0 not taken
64: branch 1 taken
3255 64: if (MaxField)
3256 : IvarsInfo.push_back(GC_IVAR(BytePos + MaxFieldOffset,
3257 0: MaxUnionIvarSize));
0: branch 0 not taken
64: branch 1 taken
3258 64: if (MaxSkippedField)
3259 : SkipIvars.push_back(GC_IVAR(BytePos + MaxSkippedFieldOffset,
3260 0: MaxSkippedUnionIvarSize));
3261 : }
3262 :
3263 : /// BuildIvarLayout - Builds ivar layout bitmap for the class
3264 : /// implementation for the __strong or __weak case.
3265 : /// The layout map displays which words in ivar list must be skipped
3266 : /// and which must be scanned by GC (see below). String is built of bytes.
3267 : /// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
3268 : /// of words to skip and right nibble is count of words to scan. So, each
3269 : /// nibble represents up to 15 workds to skip or scan. Skipping the rest is
3270 : /// represented by a 0x00 byte which also ends the string.
3271 : /// 1. when ForStrongLayout is true, following ivars are scanned:
3272 : /// - id, Class
3273 : /// - object *
3274 : /// - __strong anything
3275 : ///
3276 : /// 2. When ForStrongLayout is false, following ivars are scanned:
3277 : /// - __weak anything
3278 : ///
3279 : llvm::Constant *CGObjCCommonMac::BuildIvarLayout(
3280 : const ObjCImplementationDecl *OMD,
3281 310: bool ForStrongLayout) {
3282 310: bool hasUnion = false;
3283 :
3284 : unsigned int WordsToScan, WordsToSkip;
3285 310: const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext);
272: branch 2 taken
38: branch 3 taken
3286 310: if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC)
3287 272: return llvm::Constant::getNullValue(PtrTy);
3288 :
3289 38: llvm::SmallVector<FieldDecl*, 32> RecFields;
3290 38: const ObjCInterfaceDecl *OI = OMD->getClassInterface();
3291 38: CGM.getContext().CollectObjCIvars(OI, RecFields);
3292 :
3293 : // Add this implementations synthesized ivars.
3294 38: llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
3295 38: CGM.getContext().CollectSynthesizedIvars(OI, Ivars);
20: branch 1 taken
38: branch 2 taken
3296 58: for (unsigned k = 0, e = Ivars.size(); k != e; ++k)
3297 20: RecFields.push_back(cast<FieldDecl>(Ivars[k]));
3298 :
0: branch 1 not taken
38: branch 2 taken
3299 38: if (RecFields.empty())
3300 0: return llvm::Constant::getNullValue(PtrTy);
3301 :
3302 38: SkipIvars.clear();
3303 38: IvarsInfo.clear();
3304 :
3305 38: BuildAggrIvarLayout(OMD, 0, 0, RecFields, 0, ForStrongLayout, hasUnion);
18: branch 1 taken
20: branch 2 taken
3306 38: if (IvarsInfo.empty())
3307 18: return llvm::Constant::getNullValue(PtrTy);
3308 :
3309 : // Sort on byte position in case we encounterred a union nested in
3310 : // the ivar list.
0: branch 0 not taken
20: branch 1 taken
0: branch 3 not taken
0: branch 4 not taken
0: branch 5 not taken
20: branch 6 taken
3311 20: if (hasUnion && !IvarsInfo.empty())
3312 0: std::sort(IvarsInfo.begin(), IvarsInfo.end());
0: branch 0 not taken
20: branch 1 taken
0: branch 3 not taken
0: branch 4 not taken
0: branch 5 not taken
20: branch 6 taken
3313 20: if (hasUnion && !SkipIvars.empty())
3314 0: std::sort(SkipIvars.begin(), SkipIvars.end());
3315 :
3316 : // Build the string of skip/scan nibbles
3317 20: llvm::SmallVector<SKIP_SCAN, 32> SkipScanIvars;
3318 : unsigned int WordSize =
3319 20: CGM.getTypes().getTargetData().getTypeAllocSize(PtrTy);
12: branch 1 taken
8: branch 2 taken
3320 20: if (IvarsInfo[0].ivar_bytepos == 0) {
3321 12: WordsToSkip = 0;
3322 12: WordsToScan = IvarsInfo[0].ivar_size;
3323 : } else {
3324 8: WordsToSkip = IvarsInfo[0].ivar_bytepos/WordSize;
3325 8: WordsToScan = IvarsInfo[0].ivar_size;
3326 : }
29: branch 1 taken
20: branch 2 taken
3327 49: for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++) {
3328 : unsigned int TailPrevGCObjC =
3329 29: IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize;
26: branch 1 taken
3: branch 2 taken
3330 29: if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC) {
3331 : // consecutive 'scanned' object pointers.
3332 26: WordsToScan += IvarsInfo[i].ivar_size;
3333 : } else {
3334 : // Skip over 'gc'able object pointer which lay over each other.
0: branch 1 not taken
3: branch 2 taken
3335 3: if (TailPrevGCObjC > IvarsInfo[i].ivar_bytepos)
3336 0: continue;
3337 : // Must skip over 1 or more words. We save current skip/scan values
3338 : // and start a new pair.
3339 3: SKIP_SCAN SkScan;
3340 3: SkScan.skip = WordsToSkip;
3341 3: SkScan.scan = WordsToScan;
3342 3: SkipScanIvars.push_back(SkScan);
3343 :
3344 : // Skip the hole.
3345 3: SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize;
3346 3: SkScan.scan = 0;
3347 3: SkipScanIvars.push_back(SkScan);
3348 3: WordsToSkip = 0;
3349 3: WordsToScan = IvarsInfo[i].ivar_size;
3350 : }
3351 : }
20: branch 0 taken
0: branch 1 not taken
3352 20: if (WordsToScan > 0) {
3353 20: SKIP_SCAN SkScan;
3354 20: SkScan.skip = WordsToSkip;
3355 20: SkScan.scan = WordsToScan;
3356 20: SkipScanIvars.push_back(SkScan);
3357 : }
3358 :
10: branch 1 taken
10: branch 2 taken
3359 20: if (!SkipIvars.empty()) {
3360 10: unsigned int LastIndex = SkipIvars.size()-1;
3361 : int LastByteSkipped =
3362 10: SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size;
3363 10: LastIndex = IvarsInfo.size()-1;
3364 : int LastByteScanned =
3365 : IvarsInfo[LastIndex].ivar_bytepos +
3366 10: IvarsInfo[LastIndex].ivar_size * WordSize;
3367 : // Compute number of bytes to skip at the tail end of the last ivar scanned.
6: branch 0 taken
4: branch 1 taken
3368 10: if (LastByteSkipped > LastByteScanned) {
3369 6: unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize;
3370 6: SKIP_SCAN SkScan;
3371 6: SkScan.skip = TotalWords - (LastByteScanned/WordSize);
3372 6: SkScan.scan = 0;
3373 6: SkipScanIvars.push_back(SkScan);
3374 : }
3375 : }
3376 : // Mini optimization of nibbles such that an 0xM0 followed by 0x0N is produced
3377 : // as 0xMN.
3378 20: int SkipScan = SkipScanIvars.size()-1;
29: branch 0 taken
20: branch 1 taken
3379 49: for (int i = 0; i <= SkipScan; i++) {
11: branch 0 taken
18: branch 1 taken
9: branch 3 taken
2: branch 4 taken
3: branch 6 taken
6: branch 7 taken
3: branch 9 taken
0: branch 10 not taken
3: branch 12 taken
0: branch 13 not taken
3: branch 14 taken
26: branch 15 taken
3380 29: if ((i < SkipScan) && SkipScanIvars[i].skip && SkipScanIvars[i].scan == 0
3381 : && SkipScanIvars[i+1].skip == 0 && SkipScanIvars[i+1].scan) {
3382 : // 0xM0 followed by 0x0N detected.
3383 3: SkipScanIvars[i].scan = SkipScanIvars[i+1].scan;
1: branch 0 taken
3: branch 1 taken
3384 4: for (int j = i+1; j < SkipScan; j++)
3385 1: SkipScanIvars[j] = SkipScanIvars[j+1];
3386 3: --SkipScan;
3387 : }
3388 : }
3389 :
3390 : // Generate the string.
3391 20: std::string BitMap;
29: branch 0 taken
20: branch 1 taken
3392 49: for (int i = 0; i <= SkipScan; i++) {
3393 : unsigned char byte;
3394 29: unsigned int skip_small = SkipScanIvars[i].skip % 0xf;
3395 29: unsigned int scan_small = SkipScanIvars[i].scan % 0xf;
3396 29: unsigned int skip_big = SkipScanIvars[i].skip / 0xf;
3397 29: unsigned int scan_big = SkipScanIvars[i].scan / 0xf;
3398 :
3399 : // first skip big.
0: branch 0 not taken
29: branch 1 taken
3400 29: for (unsigned int ix = 0; ix < skip_big; ix++)
3401 0: BitMap += (unsigned char)(0xf0);
3402 :
3403 : // next (skip small, scan)
17: branch 0 taken
12: branch 1 taken
3404 29: if (skip_small) {
3405 17: byte = skip_small << 4;
0: branch 0 not taken
17: branch 1 taken
3406 17: if (scan_big > 0) {
3407 0: byte |= 0xf;
3408 0: --scan_big;
11: branch 0 taken
6: branch 1 taken
3409 17: } else if (scan_small) {
3410 11: byte |= scan_small;
3411 11: scan_small = 0;
3412 : }
3413 17: BitMap += byte;
3414 : }
3415 : // next scan big
1: branch 0 taken
29: branch 1 taken
3416 30: for (unsigned int ix = 0; ix < scan_big; ix++)
3417 1: BitMap += (unsigned char)(0x0f);
3418 : // last scan small
12: branch 0 taken
17: branch 1 taken
3419 29: if (scan_small) {
3420 12: byte = scan_small;
3421 12: BitMap += byte;
3422 : }
3423 : }
3424 : // null terminate string.
3425 20: unsigned char zero = 0;
3426 20: BitMap += zero;
3427 :
0: branch 1 not taken
20: branch 2 taken
3428 20: if (CGM.getLangOptions().ObjCGCBitmapPrint) {
3429 : printf("\n%s ivar layout for class '%s': ",
3430 : ForStrongLayout ? "strong" : "weak",
0: branch 2 not taken
0: branch 3 not taken
3431 0: OMD->getClassInterface()->getNameAsCString());
3432 0: const unsigned char *s = (unsigned char*)BitMap.c_str();
0: branch 1 not taken
0: branch 2 not taken
3433 0: for (unsigned i = 0; i < BitMap.size(); i++)
0: branch 0 not taken
0: branch 1 not taken
3434 0: if (!(s[i] & 0xf0))
0: branch 0 not taken
0: branch 1 not taken
3435 0: printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
3436 : else
0: branch 0 not taken
0: branch 1 not taken
3437 0: printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
3438 0: printf("\n");
3439 : }
3440 : llvm::GlobalVariable * Entry =
3441 : CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
3442 : llvm::ConstantArray::get(VMContext, BitMap.c_str()),
3443 : "__TEXT,__cstring,cstring_literals",
3444 20: 1, true);
3445 20: return getConstantGEP(VMContext, Entry, 0, 0);
3446 : }
3447 :
3448 667: llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
3449 667: llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
3450 :
3451 : // FIXME: Avoid std::string copying.
495: branch 0 taken
172: branch 1 taken
3452 667: if (!Entry)
3453 : Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_NAME_",
3454 : llvm::ConstantArray::get(VMContext, Sel.getAsString()),
3455 : "__TEXT,__cstring,cstring_literals",
3456 495: 1, true);
3457 :
3458 667: return getConstantGEP(VMContext, Entry, 0, 0);
3459 : }
3460 :
3461 : // FIXME: Merge into a single cstring creation function.
3462 212: llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
3463 212: return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
3464 : }
3465 :
3466 : // FIXME: Merge into a single cstring creation function.
3467 0: llvm::Constant *CGObjCCommonMac::GetMethodVarName(const std::string &Name) {
3468 0: return GetMethodVarName(&CGM.getContext().Idents.get(Name));
3469 : }
3470 :
3471 212: llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
3472 212: std::string TypeStr;
3473 212: CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
3474 :
3475 212: llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
3476 :
142: branch 0 taken
70: branch 1 taken
3477 212: if (!Entry)
3478 : Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
3479 : llvm::ConstantArray::get(VMContext, TypeStr),
3480 : "__TEXT,__cstring,cstring_literals",
3481 142: 1, true);
3482 :
3483 212: return getConstantGEP(VMContext, Entry, 0, 0);
3484 : }
3485 :
3486 322: llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D) {
3487 322: std::string TypeStr;
3488 : CGM.getContext().getObjCEncodingForMethodDecl(const_cast<ObjCMethodDecl*>(D),
3489 322: TypeStr);
3490 :
3491 322: llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
3492 :
154: branch 0 taken
168: branch 1 taken
3493 322: if (!Entry)
3494 : Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
3495 : llvm::ConstantArray::get(VMContext, TypeStr),
3496 : "__TEXT,__cstring,cstring_literals",
3497 154: 1, true);
3498 :
3499 322: return getConstantGEP(VMContext, Entry, 0, 0);
3500 : }
3501 :
3502 : // FIXME: Merge into a single cstring creation function.
3503 188: llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
3504 188: llvm::GlobalVariable *&Entry = PropertyNames[Ident];
3505 :
160: branch 0 taken
28: branch 1 taken
3506 188: if (!Entry)
3507 : Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_",
3508 : llvm::ConstantArray::get(VMContext,
3509 : Ident->getNameStart()),
3510 : "__TEXT,__cstring,cstring_literals",
3511 160: 1, true);
3512 :
3513 188: return getConstantGEP(VMContext, Entry, 0, 0);
3514 : }
3515 :
3516 : // FIXME: Merge into a single cstring creation function.
3517 : // FIXME: This Decl should be more precise.
3518 : llvm::Constant *
3519 : CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
3520 94: const Decl *Container) {
3521 94: std::string TypeStr;
3522 94: CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr);
3523 94: return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
3524 : }
3525 :
3526 : void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
3527 : const ObjCContainerDecl *CD,
3528 284: llvm::SmallVectorImpl<char> &Name) {
3529 284: llvm::raw_svector_ostream OS(Name);
0: branch 0 not taken
284: branch 1 taken
3530 284: assert (CD && "Missing container decl in GetNameForMethod");
3531 : OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
243: branch 2 taken
41: branch 3 taken
3532 284: << '[' << CD->getName();
14: branch 0 taken
270: branch 1 taken
3533 284: if (const ObjCCategoryImplDecl *CID =
3534 284: dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
3535 14: OS << '(' << CID->getNameAsString() << ')';
3536 284: OS << ' ' << D->getSelector().getAsString() << ']';
3537 284: }
3538 :
3539 109: void CGObjCMac::FinishModule() {
3540 109: EmitModuleInfo();
3541 :
3542 : // Emit the dummy bodies for any protocols which were referenced but
3543 : // never defined.
19: branch 4 taken
109: branch 5 taken
3544 113: for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator
3545 109: I = Protocols.begin(), e = Protocols.end(); I != e; ++I) {
15: branch 2 taken
4: branch 3 taken
3546 19: if (I->second->hasInitializer())
3547 15: continue;
3548 :
3549 4: std::vector<llvm::Constant*> Values(5);
3550 4: Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
3551 4: Values[1] = GetClassName(I->first);
3552 4: Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
3553 : Values[3] = Values[4] =
3554 4: llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
3555 4: I->second->setLinkage(llvm::GlobalValue::InternalLinkage);
3556 : I->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
3557 4: Values));
3558 4: CGM.AddUsedGlobal(I->second);
3559 : }
3560 :
3561 : // Add assembler directives to add lazy undefined symbol references
3562 : // for classes which are referenced but not defined. This is
3563 : // important for correct linker interaction.
3564 : //
3565 : // FIXME: It would be nice if we had an LLVM construct for this.
65: branch 1 taken
44: branch 2 taken
29: branch 4 taken
36: branch 5 taken
73: branch 6 taken
36: branch 7 taken
3566 109: if (!LazySymbols.empty() || !DefinedSymbols.empty()) {
3567 73: llvm::SmallString<256> Asm;
3568 73: Asm += CGM.getModule().getModuleInlineAsm();
0: branch 1 not taken
73: branch 2 taken
0: branch 4 not taken
0: branch 5 not taken
0: branch 6 not taken
73: branch 7 taken
3569 73: if (!Asm.empty() && Asm.back() != '\n')
3570 0: Asm += '\n';
3571 :
3572 73: llvm::raw_svector_ostream OS(Asm);
93: branch 3 taken
73: branch 4 taken
3573 239: for (llvm::SetVector<IdentifierInfo*>::iterator I = LazySymbols.begin(),
3574 73: e = LazySymbols.end(); I != e; ++I)
3575 93: OS << "\t.lazy_reference .objc_class_name_" << (*I)->getName() << "\n";
113: branch 3 taken
73: branch 4 taken
3576 259: for (llvm::SetVector<IdentifierInfo*>