xref: /minix3/external/bsd/llvm/dist/clang/lib/CodeGen/CGObjCMac.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //===------- CGObjCMac.cpp - Interface to Apple Objective-C Runtime -------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This provides Objective-C code generation targeting the Apple runtime.
11f4a2713aSLionel Sambuc //
12f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
13f4a2713aSLionel Sambuc 
14f4a2713aSLionel Sambuc #include "CGObjCRuntime.h"
15f4a2713aSLionel Sambuc #include "CGBlocks.h"
16f4a2713aSLionel Sambuc #include "CGCleanup.h"
17f4a2713aSLionel Sambuc #include "CGRecordLayout.h"
18f4a2713aSLionel Sambuc #include "CodeGenFunction.h"
19f4a2713aSLionel Sambuc #include "CodeGenModule.h"
20f4a2713aSLionel Sambuc #include "clang/AST/ASTContext.h"
21f4a2713aSLionel Sambuc #include "clang/AST/Decl.h"
22f4a2713aSLionel Sambuc #include "clang/AST/DeclObjC.h"
23f4a2713aSLionel Sambuc #include "clang/AST/RecordLayout.h"
24f4a2713aSLionel Sambuc #include "clang/AST/StmtObjC.h"
25f4a2713aSLionel Sambuc #include "clang/Basic/LangOptions.h"
26f4a2713aSLionel Sambuc #include "clang/CodeGen/CGFunctionInfo.h"
27f4a2713aSLionel Sambuc #include "clang/Frontend/CodeGenOptions.h"
28f4a2713aSLionel Sambuc #include "llvm/ADT/DenseSet.h"
29f4a2713aSLionel Sambuc #include "llvm/ADT/SetVector.h"
30f4a2713aSLionel Sambuc #include "llvm/ADT/SmallPtrSet.h"
31f4a2713aSLionel Sambuc #include "llvm/ADT/SmallString.h"
32*0a6a1f1dSLionel Sambuc #include "llvm/IR/CallSite.h"
33f4a2713aSLionel Sambuc #include "llvm/IR/DataLayout.h"
34f4a2713aSLionel Sambuc #include "llvm/IR/InlineAsm.h"
35f4a2713aSLionel Sambuc #include "llvm/IR/IntrinsicInst.h"
36f4a2713aSLionel Sambuc #include "llvm/IR/LLVMContext.h"
37f4a2713aSLionel Sambuc #include "llvm/IR/Module.h"
38f4a2713aSLionel Sambuc #include "llvm/Support/raw_ostream.h"
39f4a2713aSLionel Sambuc #include <cstdio>
40f4a2713aSLionel Sambuc 
41f4a2713aSLionel Sambuc using namespace clang;
42f4a2713aSLionel Sambuc using namespace CodeGen;
43f4a2713aSLionel Sambuc 
44f4a2713aSLionel Sambuc namespace {
45f4a2713aSLionel Sambuc 
46f4a2713aSLionel Sambuc // FIXME: We should find a nicer way to make the labels for metadata, string
47f4a2713aSLionel Sambuc // concatenation is lame.
48f4a2713aSLionel Sambuc 
49f4a2713aSLionel Sambuc class ObjCCommonTypesHelper {
50f4a2713aSLionel Sambuc protected:
51f4a2713aSLionel Sambuc   llvm::LLVMContext &VMContext;
52f4a2713aSLionel Sambuc 
53f4a2713aSLionel Sambuc private:
54f4a2713aSLionel Sambuc   // The types of these functions don't really matter because we
55f4a2713aSLionel Sambuc   // should always bitcast before calling them.
56f4a2713aSLionel Sambuc 
57f4a2713aSLionel Sambuc   /// id objc_msgSend (id, SEL, ...)
58f4a2713aSLionel Sambuc   ///
59f4a2713aSLionel Sambuc   /// The default messenger, used for sends whose ABI is unchanged from
60f4a2713aSLionel Sambuc   /// the all-integer/pointer case.
getMessageSendFn() const61f4a2713aSLionel Sambuc   llvm::Constant *getMessageSendFn() const {
62f4a2713aSLionel Sambuc     // Add the non-lazy-bind attribute, since objc_msgSend is likely to
63f4a2713aSLionel Sambuc     // be called a lot.
64f4a2713aSLionel Sambuc     llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
65f4a2713aSLionel Sambuc     return
66f4a2713aSLionel Sambuc       CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
67f4a2713aSLionel Sambuc                                                         params, true),
68f4a2713aSLionel Sambuc                                 "objc_msgSend",
69f4a2713aSLionel Sambuc                                 llvm::AttributeSet::get(CGM.getLLVMContext(),
70f4a2713aSLionel Sambuc                                               llvm::AttributeSet::FunctionIndex,
71f4a2713aSLionel Sambuc                                                  llvm::Attribute::NonLazyBind));
72f4a2713aSLionel Sambuc   }
73f4a2713aSLionel Sambuc 
74f4a2713aSLionel Sambuc   /// void objc_msgSend_stret (id, SEL, ...)
75f4a2713aSLionel Sambuc   ///
76f4a2713aSLionel Sambuc   /// The messenger used when the return value is an aggregate returned
77f4a2713aSLionel Sambuc   /// by indirect reference in the first argument, and therefore the
78f4a2713aSLionel Sambuc   /// self and selector parameters are shifted over by one.
getMessageSendStretFn() const79f4a2713aSLionel Sambuc   llvm::Constant *getMessageSendStretFn() const {
80f4a2713aSLionel Sambuc     llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
81f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy,
82f4a2713aSLionel Sambuc                                                              params, true),
83f4a2713aSLionel Sambuc                                      "objc_msgSend_stret");
84f4a2713aSLionel Sambuc 
85f4a2713aSLionel Sambuc   }
86f4a2713aSLionel Sambuc 
87f4a2713aSLionel Sambuc   /// [double | long double] objc_msgSend_fpret(id self, SEL op, ...)
88f4a2713aSLionel Sambuc   ///
89f4a2713aSLionel Sambuc   /// The messenger used when the return value is returned on the x87
90f4a2713aSLionel Sambuc   /// floating-point stack; without a special entrypoint, the nil case
91f4a2713aSLionel Sambuc   /// would be unbalanced.
getMessageSendFpretFn() const92f4a2713aSLionel Sambuc   llvm::Constant *getMessageSendFpretFn() const {
93f4a2713aSLionel Sambuc     llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
94f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.DoubleTy,
95f4a2713aSLionel Sambuc                                                              params, true),
96f4a2713aSLionel Sambuc                                      "objc_msgSend_fpret");
97f4a2713aSLionel Sambuc 
98f4a2713aSLionel Sambuc   }
99f4a2713aSLionel Sambuc 
100f4a2713aSLionel Sambuc   /// _Complex long double objc_msgSend_fp2ret(id self, SEL op, ...)
101f4a2713aSLionel Sambuc   ///
102f4a2713aSLionel Sambuc   /// The messenger used when the return value is returned in two values on the
103f4a2713aSLionel Sambuc   /// x87 floating point stack; without a special entrypoint, the nil case
104f4a2713aSLionel Sambuc   /// would be unbalanced. Only used on 64-bit X86.
getMessageSendFp2retFn() const105f4a2713aSLionel Sambuc   llvm::Constant *getMessageSendFp2retFn() const {
106f4a2713aSLionel Sambuc     llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
107f4a2713aSLionel Sambuc     llvm::Type *longDoubleType = llvm::Type::getX86_FP80Ty(VMContext);
108f4a2713aSLionel Sambuc     llvm::Type *resultType =
109*0a6a1f1dSLionel Sambuc       llvm::StructType::get(longDoubleType, longDoubleType, nullptr);
110f4a2713aSLionel Sambuc 
111f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(llvm::FunctionType::get(resultType,
112f4a2713aSLionel Sambuc                                                              params, true),
113f4a2713aSLionel Sambuc                                      "objc_msgSend_fp2ret");
114f4a2713aSLionel Sambuc   }
115f4a2713aSLionel Sambuc 
116f4a2713aSLionel Sambuc   /// id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
117f4a2713aSLionel Sambuc   ///
118f4a2713aSLionel Sambuc   /// The messenger used for super calls, which have different dispatch
119f4a2713aSLionel Sambuc   /// semantics.  The class passed is the superclass of the current
120f4a2713aSLionel Sambuc   /// class.
getMessageSendSuperFn() const121f4a2713aSLionel Sambuc   llvm::Constant *getMessageSendSuperFn() const {
122f4a2713aSLionel Sambuc     llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
123f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
124f4a2713aSLionel Sambuc                                                              params, true),
125f4a2713aSLionel Sambuc                                      "objc_msgSendSuper");
126f4a2713aSLionel Sambuc   }
127f4a2713aSLionel Sambuc 
128f4a2713aSLionel Sambuc   /// id objc_msgSendSuper2(struct objc_super *super, SEL op, ...)
129f4a2713aSLionel Sambuc   ///
130f4a2713aSLionel Sambuc   /// A slightly different messenger used for super calls.  The class
131f4a2713aSLionel Sambuc   /// passed is the current class.
getMessageSendSuperFn2() const132f4a2713aSLionel Sambuc   llvm::Constant *getMessageSendSuperFn2() const {
133f4a2713aSLionel Sambuc     llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
134f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
135f4a2713aSLionel Sambuc                                                              params, true),
136f4a2713aSLionel Sambuc                                      "objc_msgSendSuper2");
137f4a2713aSLionel Sambuc   }
138f4a2713aSLionel Sambuc 
139f4a2713aSLionel Sambuc   /// void objc_msgSendSuper_stret(void *stretAddr, struct objc_super *super,
140f4a2713aSLionel Sambuc   ///                              SEL op, ...)
141f4a2713aSLionel Sambuc   ///
142f4a2713aSLionel Sambuc   /// The messenger used for super calls which return an aggregate indirectly.
getMessageSendSuperStretFn() const143f4a2713aSLionel Sambuc   llvm::Constant *getMessageSendSuperStretFn() const {
144f4a2713aSLionel Sambuc     llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
145f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(
146f4a2713aSLionel Sambuc       llvm::FunctionType::get(CGM.VoidTy, params, true),
147f4a2713aSLionel Sambuc       "objc_msgSendSuper_stret");
148f4a2713aSLionel Sambuc   }
149f4a2713aSLionel Sambuc 
150f4a2713aSLionel Sambuc   /// void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super,
151f4a2713aSLionel Sambuc   ///                               SEL op, ...)
152f4a2713aSLionel Sambuc   ///
153f4a2713aSLionel Sambuc   /// objc_msgSendSuper_stret with the super2 semantics.
getMessageSendSuperStretFn2() const154f4a2713aSLionel Sambuc   llvm::Constant *getMessageSendSuperStretFn2() const {
155f4a2713aSLionel Sambuc     llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
156f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(
157f4a2713aSLionel Sambuc       llvm::FunctionType::get(CGM.VoidTy, params, true),
158f4a2713aSLionel Sambuc       "objc_msgSendSuper2_stret");
159f4a2713aSLionel Sambuc   }
160f4a2713aSLionel Sambuc 
getMessageSendSuperFpretFn() const161f4a2713aSLionel Sambuc   llvm::Constant *getMessageSendSuperFpretFn() const {
162f4a2713aSLionel Sambuc     // There is no objc_msgSendSuper_fpret? How can that work?
163f4a2713aSLionel Sambuc     return getMessageSendSuperFn();
164f4a2713aSLionel Sambuc   }
165f4a2713aSLionel Sambuc 
getMessageSendSuperFpretFn2() const166f4a2713aSLionel Sambuc   llvm::Constant *getMessageSendSuperFpretFn2() const {
167f4a2713aSLionel Sambuc     // There is no objc_msgSendSuper_fpret? How can that work?
168f4a2713aSLionel Sambuc     return getMessageSendSuperFn2();
169f4a2713aSLionel Sambuc   }
170f4a2713aSLionel Sambuc 
171f4a2713aSLionel Sambuc protected:
172f4a2713aSLionel Sambuc   CodeGen::CodeGenModule &CGM;
173f4a2713aSLionel Sambuc 
174f4a2713aSLionel Sambuc public:
175f4a2713aSLionel Sambuc   llvm::Type *ShortTy, *IntTy, *LongTy, *LongLongTy;
176f4a2713aSLionel Sambuc   llvm::Type *Int8PtrTy, *Int8PtrPtrTy;
177*0a6a1f1dSLionel Sambuc   llvm::Type *IvarOffsetVarTy;
178f4a2713aSLionel Sambuc 
179f4a2713aSLionel Sambuc   /// ObjectPtrTy - LLVM type for object handles (typeof(id))
180f4a2713aSLionel Sambuc   llvm::Type *ObjectPtrTy;
181f4a2713aSLionel Sambuc 
182f4a2713aSLionel Sambuc   /// PtrObjectPtrTy - LLVM type for id *
183f4a2713aSLionel Sambuc   llvm::Type *PtrObjectPtrTy;
184f4a2713aSLionel Sambuc 
185f4a2713aSLionel Sambuc   /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
186f4a2713aSLionel Sambuc   llvm::Type *SelectorPtrTy;
187f4a2713aSLionel Sambuc 
188f4a2713aSLionel Sambuc private:
189f4a2713aSLionel Sambuc   /// ProtocolPtrTy - LLVM type for external protocol handles
190f4a2713aSLionel Sambuc   /// (typeof(Protocol))
191f4a2713aSLionel Sambuc   llvm::Type *ExternalProtocolPtrTy;
192f4a2713aSLionel Sambuc 
193f4a2713aSLionel Sambuc public:
getExternalProtocolPtrTy()194f4a2713aSLionel Sambuc   llvm::Type *getExternalProtocolPtrTy() {
195f4a2713aSLionel Sambuc     if (!ExternalProtocolPtrTy) {
196f4a2713aSLionel Sambuc       // FIXME: It would be nice to unify this with the opaque type, so that the
197f4a2713aSLionel Sambuc       // IR comes out a bit cleaner.
198f4a2713aSLionel Sambuc       CodeGen::CodeGenTypes &Types = CGM.getTypes();
199f4a2713aSLionel Sambuc       ASTContext &Ctx = CGM.getContext();
200f4a2713aSLionel Sambuc       llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
201f4a2713aSLionel Sambuc       ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
202f4a2713aSLionel Sambuc     }
203f4a2713aSLionel Sambuc 
204f4a2713aSLionel Sambuc     return ExternalProtocolPtrTy;
205f4a2713aSLionel Sambuc   }
206f4a2713aSLionel Sambuc 
207f4a2713aSLionel Sambuc   // SuperCTy - clang type for struct objc_super.
208f4a2713aSLionel Sambuc   QualType SuperCTy;
209f4a2713aSLionel Sambuc   // SuperPtrCTy - clang type for struct objc_super *.
210f4a2713aSLionel Sambuc   QualType SuperPtrCTy;
211f4a2713aSLionel Sambuc 
212f4a2713aSLionel Sambuc   /// SuperTy - LLVM type for struct objc_super.
213f4a2713aSLionel Sambuc   llvm::StructType *SuperTy;
214f4a2713aSLionel Sambuc   /// SuperPtrTy - LLVM type for struct objc_super *.
215f4a2713aSLionel Sambuc   llvm::Type *SuperPtrTy;
216f4a2713aSLionel Sambuc 
217f4a2713aSLionel Sambuc   /// PropertyTy - LLVM type for struct objc_property (struct _prop_t
218f4a2713aSLionel Sambuc   /// in GCC parlance).
219f4a2713aSLionel Sambuc   llvm::StructType *PropertyTy;
220f4a2713aSLionel Sambuc 
221f4a2713aSLionel Sambuc   /// PropertyListTy - LLVM type for struct objc_property_list
222f4a2713aSLionel Sambuc   /// (_prop_list_t in GCC parlance).
223f4a2713aSLionel Sambuc   llvm::StructType *PropertyListTy;
224f4a2713aSLionel Sambuc   /// PropertyListPtrTy - LLVM type for struct objc_property_list*.
225f4a2713aSLionel Sambuc   llvm::Type *PropertyListPtrTy;
226f4a2713aSLionel Sambuc 
227f4a2713aSLionel Sambuc   // MethodTy - LLVM type for struct objc_method.
228f4a2713aSLionel Sambuc   llvm::StructType *MethodTy;
229f4a2713aSLionel Sambuc 
230f4a2713aSLionel Sambuc   /// CacheTy - LLVM type for struct objc_cache.
231f4a2713aSLionel Sambuc   llvm::Type *CacheTy;
232f4a2713aSLionel Sambuc   /// CachePtrTy - LLVM type for struct objc_cache *.
233f4a2713aSLionel Sambuc   llvm::Type *CachePtrTy;
234f4a2713aSLionel Sambuc 
getGetPropertyFn()235f4a2713aSLionel Sambuc   llvm::Constant *getGetPropertyFn() {
236f4a2713aSLionel Sambuc     CodeGen::CodeGenTypes &Types = CGM.getTypes();
237f4a2713aSLionel Sambuc     ASTContext &Ctx = CGM.getContext();
238f4a2713aSLionel Sambuc     // id objc_getProperty (id, SEL, ptrdiff_t, bool)
239f4a2713aSLionel Sambuc     SmallVector<CanQualType,4> Params;
240f4a2713aSLionel Sambuc     CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
241f4a2713aSLionel Sambuc     CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
242f4a2713aSLionel Sambuc     Params.push_back(IdType);
243f4a2713aSLionel Sambuc     Params.push_back(SelType);
244f4a2713aSLionel Sambuc     Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
245f4a2713aSLionel Sambuc     Params.push_back(Ctx.BoolTy);
246f4a2713aSLionel Sambuc     llvm::FunctionType *FTy =
247*0a6a1f1dSLionel Sambuc         Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(
248*0a6a1f1dSLionel Sambuc             IdType, false, false, Params, FunctionType::ExtInfo(),
249f4a2713aSLionel Sambuc             RequiredArgs::All));
250f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
251f4a2713aSLionel Sambuc   }
252f4a2713aSLionel Sambuc 
getSetPropertyFn()253f4a2713aSLionel Sambuc   llvm::Constant *getSetPropertyFn() {
254f4a2713aSLionel Sambuc     CodeGen::CodeGenTypes &Types = CGM.getTypes();
255f4a2713aSLionel Sambuc     ASTContext &Ctx = CGM.getContext();
256f4a2713aSLionel Sambuc     // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
257f4a2713aSLionel Sambuc     SmallVector<CanQualType,6> Params;
258f4a2713aSLionel Sambuc     CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
259f4a2713aSLionel Sambuc     CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
260f4a2713aSLionel Sambuc     Params.push_back(IdType);
261f4a2713aSLionel Sambuc     Params.push_back(SelType);
262f4a2713aSLionel Sambuc     Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
263f4a2713aSLionel Sambuc     Params.push_back(IdType);
264f4a2713aSLionel Sambuc     Params.push_back(Ctx.BoolTy);
265f4a2713aSLionel Sambuc     Params.push_back(Ctx.BoolTy);
266f4a2713aSLionel Sambuc     llvm::FunctionType *FTy =
267*0a6a1f1dSLionel Sambuc         Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(
268*0a6a1f1dSLionel Sambuc             Ctx.VoidTy, false, false, Params, FunctionType::ExtInfo(),
269f4a2713aSLionel Sambuc             RequiredArgs::All));
270f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
271f4a2713aSLionel Sambuc   }
272f4a2713aSLionel Sambuc 
getOptimizedSetPropertyFn(bool atomic,bool copy)273f4a2713aSLionel Sambuc   llvm::Constant *getOptimizedSetPropertyFn(bool atomic, bool copy) {
274f4a2713aSLionel Sambuc     CodeGen::CodeGenTypes &Types = CGM.getTypes();
275f4a2713aSLionel Sambuc     ASTContext &Ctx = CGM.getContext();
276f4a2713aSLionel Sambuc     // void objc_setProperty_atomic(id self, SEL _cmd,
277f4a2713aSLionel Sambuc     //                              id newValue, ptrdiff_t offset);
278f4a2713aSLionel Sambuc     // void objc_setProperty_nonatomic(id self, SEL _cmd,
279f4a2713aSLionel Sambuc     //                                 id newValue, ptrdiff_t offset);
280f4a2713aSLionel Sambuc     // void objc_setProperty_atomic_copy(id self, SEL _cmd,
281f4a2713aSLionel Sambuc     //                                   id newValue, ptrdiff_t offset);
282f4a2713aSLionel Sambuc     // void objc_setProperty_nonatomic_copy(id self, SEL _cmd,
283f4a2713aSLionel Sambuc     //                                      id newValue, ptrdiff_t offset);
284f4a2713aSLionel Sambuc 
285f4a2713aSLionel Sambuc     SmallVector<CanQualType,4> Params;
286f4a2713aSLionel Sambuc     CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
287f4a2713aSLionel Sambuc     CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
288f4a2713aSLionel Sambuc     Params.push_back(IdType);
289f4a2713aSLionel Sambuc     Params.push_back(SelType);
290f4a2713aSLionel Sambuc     Params.push_back(IdType);
291f4a2713aSLionel Sambuc     Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
292f4a2713aSLionel Sambuc     llvm::FunctionType *FTy =
293*0a6a1f1dSLionel Sambuc         Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(
294*0a6a1f1dSLionel Sambuc             Ctx.VoidTy, false, false, Params, FunctionType::ExtInfo(),
295f4a2713aSLionel Sambuc             RequiredArgs::All));
296f4a2713aSLionel Sambuc     const char *name;
297f4a2713aSLionel Sambuc     if (atomic && copy)
298f4a2713aSLionel Sambuc       name = "objc_setProperty_atomic_copy";
299f4a2713aSLionel Sambuc     else if (atomic && !copy)
300f4a2713aSLionel Sambuc       name = "objc_setProperty_atomic";
301f4a2713aSLionel Sambuc     else if (!atomic && copy)
302f4a2713aSLionel Sambuc       name = "objc_setProperty_nonatomic_copy";
303f4a2713aSLionel Sambuc     else
304f4a2713aSLionel Sambuc       name = "objc_setProperty_nonatomic";
305f4a2713aSLionel Sambuc 
306f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(FTy, name);
307f4a2713aSLionel Sambuc   }
308f4a2713aSLionel Sambuc 
getCopyStructFn()309f4a2713aSLionel Sambuc   llvm::Constant *getCopyStructFn() {
310f4a2713aSLionel Sambuc     CodeGen::CodeGenTypes &Types = CGM.getTypes();
311f4a2713aSLionel Sambuc     ASTContext &Ctx = CGM.getContext();
312f4a2713aSLionel Sambuc     // void objc_copyStruct (void *, const void *, size_t, bool, bool)
313f4a2713aSLionel Sambuc     SmallVector<CanQualType,5> Params;
314f4a2713aSLionel Sambuc     Params.push_back(Ctx.VoidPtrTy);
315f4a2713aSLionel Sambuc     Params.push_back(Ctx.VoidPtrTy);
316f4a2713aSLionel Sambuc     Params.push_back(Ctx.LongTy);
317f4a2713aSLionel Sambuc     Params.push_back(Ctx.BoolTy);
318f4a2713aSLionel Sambuc     Params.push_back(Ctx.BoolTy);
319f4a2713aSLionel Sambuc     llvm::FunctionType *FTy =
320*0a6a1f1dSLionel Sambuc         Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(
321*0a6a1f1dSLionel Sambuc             Ctx.VoidTy, false, false, Params, FunctionType::ExtInfo(),
322f4a2713aSLionel Sambuc             RequiredArgs::All));
323f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(FTy, "objc_copyStruct");
324f4a2713aSLionel Sambuc   }
325f4a2713aSLionel Sambuc 
326f4a2713aSLionel Sambuc   /// This routine declares and returns address of:
327f4a2713aSLionel Sambuc   /// void objc_copyCppObjectAtomic(
328f4a2713aSLionel Sambuc   ///         void *dest, const void *src,
329f4a2713aSLionel Sambuc   ///         void (*copyHelper) (void *dest, const void *source));
getCppAtomicObjectFunction()330f4a2713aSLionel Sambuc   llvm::Constant *getCppAtomicObjectFunction() {
331f4a2713aSLionel Sambuc     CodeGen::CodeGenTypes &Types = CGM.getTypes();
332f4a2713aSLionel Sambuc     ASTContext &Ctx = CGM.getContext();
333f4a2713aSLionel Sambuc     /// void objc_copyCppObjectAtomic(void *dest, const void *src, void *helper);
334f4a2713aSLionel Sambuc     SmallVector<CanQualType,3> Params;
335f4a2713aSLionel Sambuc     Params.push_back(Ctx.VoidPtrTy);
336f4a2713aSLionel Sambuc     Params.push_back(Ctx.VoidPtrTy);
337f4a2713aSLionel Sambuc     Params.push_back(Ctx.VoidPtrTy);
338f4a2713aSLionel Sambuc     llvm::FunctionType *FTy =
339*0a6a1f1dSLionel Sambuc       Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, false, false,
340*0a6a1f1dSLionel Sambuc                                                           Params,
341f4a2713aSLionel Sambuc                                                           FunctionType::ExtInfo(),
342f4a2713aSLionel Sambuc                                                           RequiredArgs::All));
343f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(FTy, "objc_copyCppObjectAtomic");
344f4a2713aSLionel Sambuc   }
345f4a2713aSLionel Sambuc 
getEnumerationMutationFn()346f4a2713aSLionel Sambuc   llvm::Constant *getEnumerationMutationFn() {
347f4a2713aSLionel Sambuc     CodeGen::CodeGenTypes &Types = CGM.getTypes();
348f4a2713aSLionel Sambuc     ASTContext &Ctx = CGM.getContext();
349f4a2713aSLionel Sambuc     // void objc_enumerationMutation (id)
350f4a2713aSLionel Sambuc     SmallVector<CanQualType,1> Params;
351f4a2713aSLionel Sambuc     Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType()));
352f4a2713aSLionel Sambuc     llvm::FunctionType *FTy =
353*0a6a1f1dSLionel Sambuc         Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(
354*0a6a1f1dSLionel Sambuc             Ctx.VoidTy, false, false, Params, FunctionType::ExtInfo(),
355f4a2713aSLionel Sambuc             RequiredArgs::All));
356f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
357f4a2713aSLionel Sambuc   }
358f4a2713aSLionel Sambuc 
359f4a2713aSLionel Sambuc   /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
getGcReadWeakFn()360f4a2713aSLionel Sambuc   llvm::Constant *getGcReadWeakFn() {
361f4a2713aSLionel Sambuc     // id objc_read_weak (id *)
362f4a2713aSLionel Sambuc     llvm::Type *args[] = { ObjectPtrTy->getPointerTo() };
363f4a2713aSLionel Sambuc     llvm::FunctionType *FTy =
364f4a2713aSLionel Sambuc       llvm::FunctionType::get(ObjectPtrTy, args, false);
365f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
366f4a2713aSLionel Sambuc   }
367f4a2713aSLionel Sambuc 
368f4a2713aSLionel Sambuc   /// GcAssignWeakFn -- LLVM objc_assign_weak function.
getGcAssignWeakFn()369f4a2713aSLionel Sambuc   llvm::Constant *getGcAssignWeakFn() {
370f4a2713aSLionel Sambuc     // id objc_assign_weak (id, id *)
371f4a2713aSLionel Sambuc     llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
372f4a2713aSLionel Sambuc     llvm::FunctionType *FTy =
373f4a2713aSLionel Sambuc       llvm::FunctionType::get(ObjectPtrTy, args, false);
374f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
375f4a2713aSLionel Sambuc   }
376f4a2713aSLionel Sambuc 
377f4a2713aSLionel Sambuc   /// GcAssignGlobalFn -- LLVM objc_assign_global function.
getGcAssignGlobalFn()378f4a2713aSLionel Sambuc   llvm::Constant *getGcAssignGlobalFn() {
379f4a2713aSLionel Sambuc     // id objc_assign_global(id, id *)
380f4a2713aSLionel Sambuc     llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
381f4a2713aSLionel Sambuc     llvm::FunctionType *FTy =
382f4a2713aSLionel Sambuc       llvm::FunctionType::get(ObjectPtrTy, args, false);
383f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
384f4a2713aSLionel Sambuc   }
385f4a2713aSLionel Sambuc 
386f4a2713aSLionel Sambuc   /// GcAssignThreadLocalFn -- LLVM objc_assign_threadlocal function.
getGcAssignThreadLocalFn()387f4a2713aSLionel Sambuc   llvm::Constant *getGcAssignThreadLocalFn() {
388f4a2713aSLionel Sambuc     // id objc_assign_threadlocal(id src, id * dest)
389f4a2713aSLionel Sambuc     llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
390f4a2713aSLionel Sambuc     llvm::FunctionType *FTy =
391f4a2713aSLionel Sambuc       llvm::FunctionType::get(ObjectPtrTy, args, false);
392f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal");
393f4a2713aSLionel Sambuc   }
394f4a2713aSLionel Sambuc 
395f4a2713aSLionel Sambuc   /// GcAssignIvarFn -- LLVM objc_assign_ivar function.
getGcAssignIvarFn()396f4a2713aSLionel Sambuc   llvm::Constant *getGcAssignIvarFn() {
397f4a2713aSLionel Sambuc     // id objc_assign_ivar(id, id *, ptrdiff_t)
398f4a2713aSLionel Sambuc     llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo(),
399f4a2713aSLionel Sambuc                            CGM.PtrDiffTy };
400f4a2713aSLionel Sambuc     llvm::FunctionType *FTy =
401f4a2713aSLionel Sambuc       llvm::FunctionType::get(ObjectPtrTy, args, false);
402f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
403f4a2713aSLionel Sambuc   }
404f4a2713aSLionel Sambuc 
405f4a2713aSLionel Sambuc   /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function.
GcMemmoveCollectableFn()406f4a2713aSLionel Sambuc   llvm::Constant *GcMemmoveCollectableFn() {
407f4a2713aSLionel Sambuc     // void *objc_memmove_collectable(void *dst, const void *src, size_t size)
408f4a2713aSLionel Sambuc     llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, LongTy };
409f4a2713aSLionel Sambuc     llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, args, false);
410f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable");
411f4a2713aSLionel Sambuc   }
412f4a2713aSLionel Sambuc 
413f4a2713aSLionel Sambuc   /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
getGcAssignStrongCastFn()414f4a2713aSLionel Sambuc   llvm::Constant *getGcAssignStrongCastFn() {
415f4a2713aSLionel Sambuc     // id objc_assign_strongCast(id, id *)
416f4a2713aSLionel Sambuc     llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
417f4a2713aSLionel Sambuc     llvm::FunctionType *FTy =
418f4a2713aSLionel Sambuc       llvm::FunctionType::get(ObjectPtrTy, args, false);
419f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
420f4a2713aSLionel Sambuc   }
421f4a2713aSLionel Sambuc 
422f4a2713aSLionel Sambuc   /// ExceptionThrowFn - LLVM objc_exception_throw function.
getExceptionThrowFn()423f4a2713aSLionel Sambuc   llvm::Constant *getExceptionThrowFn() {
424f4a2713aSLionel Sambuc     // void objc_exception_throw(id)
425f4a2713aSLionel Sambuc     llvm::Type *args[] = { ObjectPtrTy };
426f4a2713aSLionel Sambuc     llvm::FunctionType *FTy =
427f4a2713aSLionel Sambuc       llvm::FunctionType::get(CGM.VoidTy, args, false);
428f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
429f4a2713aSLionel Sambuc   }
430f4a2713aSLionel Sambuc 
431f4a2713aSLionel Sambuc   /// ExceptionRethrowFn - LLVM objc_exception_rethrow function.
getExceptionRethrowFn()432f4a2713aSLionel Sambuc   llvm::Constant *getExceptionRethrowFn() {
433f4a2713aSLionel Sambuc     // void objc_exception_rethrow(void)
434f4a2713aSLionel Sambuc     llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false);
435f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(FTy, "objc_exception_rethrow");
436f4a2713aSLionel Sambuc   }
437f4a2713aSLionel Sambuc 
438f4a2713aSLionel Sambuc   /// SyncEnterFn - LLVM object_sync_enter function.
getSyncEnterFn()439f4a2713aSLionel Sambuc   llvm::Constant *getSyncEnterFn() {
440f4a2713aSLionel Sambuc     // int objc_sync_enter (id)
441f4a2713aSLionel Sambuc     llvm::Type *args[] = { ObjectPtrTy };
442f4a2713aSLionel Sambuc     llvm::FunctionType *FTy =
443f4a2713aSLionel Sambuc       llvm::FunctionType::get(CGM.IntTy, args, false);
444f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
445f4a2713aSLionel Sambuc   }
446f4a2713aSLionel Sambuc 
447f4a2713aSLionel Sambuc   /// SyncExitFn - LLVM object_sync_exit function.
getSyncExitFn()448f4a2713aSLionel Sambuc   llvm::Constant *getSyncExitFn() {
449f4a2713aSLionel Sambuc     // int objc_sync_exit (id)
450f4a2713aSLionel Sambuc     llvm::Type *args[] = { ObjectPtrTy };
451f4a2713aSLionel Sambuc     llvm::FunctionType *FTy =
452f4a2713aSLionel Sambuc       llvm::FunctionType::get(CGM.IntTy, args, false);
453f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
454f4a2713aSLionel Sambuc   }
455f4a2713aSLionel Sambuc 
getSendFn(bool IsSuper) const456f4a2713aSLionel Sambuc   llvm::Constant *getSendFn(bool IsSuper) const {
457f4a2713aSLionel Sambuc     return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
458f4a2713aSLionel Sambuc   }
459f4a2713aSLionel Sambuc 
getSendFn2(bool IsSuper) const460f4a2713aSLionel Sambuc   llvm::Constant *getSendFn2(bool IsSuper) const {
461f4a2713aSLionel Sambuc     return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
462f4a2713aSLionel Sambuc   }
463f4a2713aSLionel Sambuc 
getSendStretFn(bool IsSuper) const464f4a2713aSLionel Sambuc   llvm::Constant *getSendStretFn(bool IsSuper) const {
465f4a2713aSLionel Sambuc     return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
466f4a2713aSLionel Sambuc   }
467f4a2713aSLionel Sambuc 
getSendStretFn2(bool IsSuper) const468f4a2713aSLionel Sambuc   llvm::Constant *getSendStretFn2(bool IsSuper) const {
469f4a2713aSLionel Sambuc     return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
470f4a2713aSLionel Sambuc   }
471f4a2713aSLionel Sambuc 
getSendFpretFn(bool IsSuper) const472f4a2713aSLionel Sambuc   llvm::Constant *getSendFpretFn(bool IsSuper) const {
473f4a2713aSLionel Sambuc     return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
474f4a2713aSLionel Sambuc   }
475f4a2713aSLionel Sambuc 
getSendFpretFn2(bool IsSuper) const476f4a2713aSLionel Sambuc   llvm::Constant *getSendFpretFn2(bool IsSuper) const {
477f4a2713aSLionel Sambuc     return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
478f4a2713aSLionel Sambuc   }
479f4a2713aSLionel Sambuc 
getSendFp2retFn(bool IsSuper) const480f4a2713aSLionel Sambuc   llvm::Constant *getSendFp2retFn(bool IsSuper) const {
481f4a2713aSLionel Sambuc     return IsSuper ? getMessageSendSuperFn() : getMessageSendFp2retFn();
482f4a2713aSLionel Sambuc   }
483f4a2713aSLionel Sambuc 
getSendFp2RetFn2(bool IsSuper) const484f4a2713aSLionel Sambuc   llvm::Constant *getSendFp2RetFn2(bool IsSuper) const {
485f4a2713aSLionel Sambuc     return IsSuper ? getMessageSendSuperFn2() : getMessageSendFp2retFn();
486f4a2713aSLionel Sambuc   }
487f4a2713aSLionel Sambuc 
488f4a2713aSLionel Sambuc   ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
~ObjCCommonTypesHelper()489f4a2713aSLionel Sambuc   ~ObjCCommonTypesHelper(){}
490f4a2713aSLionel Sambuc };
491f4a2713aSLionel Sambuc 
492f4a2713aSLionel Sambuc /// ObjCTypesHelper - Helper class that encapsulates lazy
493f4a2713aSLionel Sambuc /// construction of varies types used during ObjC generation.
494f4a2713aSLionel Sambuc class ObjCTypesHelper : public ObjCCommonTypesHelper {
495f4a2713aSLionel Sambuc public:
496f4a2713aSLionel Sambuc   /// SymtabTy - LLVM type for struct objc_symtab.
497f4a2713aSLionel Sambuc   llvm::StructType *SymtabTy;
498f4a2713aSLionel Sambuc   /// SymtabPtrTy - LLVM type for struct objc_symtab *.
499f4a2713aSLionel Sambuc   llvm::Type *SymtabPtrTy;
500f4a2713aSLionel Sambuc   /// ModuleTy - LLVM type for struct objc_module.
501f4a2713aSLionel Sambuc   llvm::StructType *ModuleTy;
502f4a2713aSLionel Sambuc 
503f4a2713aSLionel Sambuc   /// ProtocolTy - LLVM type for struct objc_protocol.
504f4a2713aSLionel Sambuc   llvm::StructType *ProtocolTy;
505f4a2713aSLionel Sambuc   /// ProtocolPtrTy - LLVM type for struct objc_protocol *.
506f4a2713aSLionel Sambuc   llvm::Type *ProtocolPtrTy;
507f4a2713aSLionel Sambuc   /// ProtocolExtensionTy - LLVM type for struct
508f4a2713aSLionel Sambuc   /// objc_protocol_extension.
509f4a2713aSLionel Sambuc   llvm::StructType *ProtocolExtensionTy;
510f4a2713aSLionel Sambuc   /// ProtocolExtensionTy - LLVM type for struct
511f4a2713aSLionel Sambuc   /// objc_protocol_extension *.
512f4a2713aSLionel Sambuc   llvm::Type *ProtocolExtensionPtrTy;
513f4a2713aSLionel Sambuc   /// MethodDescriptionTy - LLVM type for struct
514f4a2713aSLionel Sambuc   /// objc_method_description.
515f4a2713aSLionel Sambuc   llvm::StructType *MethodDescriptionTy;
516f4a2713aSLionel Sambuc   /// MethodDescriptionListTy - LLVM type for struct
517f4a2713aSLionel Sambuc   /// objc_method_description_list.
518f4a2713aSLionel Sambuc   llvm::StructType *MethodDescriptionListTy;
519f4a2713aSLionel Sambuc   /// MethodDescriptionListPtrTy - LLVM type for struct
520f4a2713aSLionel Sambuc   /// objc_method_description_list *.
521f4a2713aSLionel Sambuc   llvm::Type *MethodDescriptionListPtrTy;
522f4a2713aSLionel Sambuc   /// ProtocolListTy - LLVM type for struct objc_property_list.
523f4a2713aSLionel Sambuc   llvm::StructType *ProtocolListTy;
524f4a2713aSLionel Sambuc   /// ProtocolListPtrTy - LLVM type for struct objc_property_list*.
525f4a2713aSLionel Sambuc   llvm::Type *ProtocolListPtrTy;
526f4a2713aSLionel Sambuc   /// CategoryTy - LLVM type for struct objc_category.
527f4a2713aSLionel Sambuc   llvm::StructType *CategoryTy;
528f4a2713aSLionel Sambuc   /// ClassTy - LLVM type for struct objc_class.
529f4a2713aSLionel Sambuc   llvm::StructType *ClassTy;
530f4a2713aSLionel Sambuc   /// ClassPtrTy - LLVM type for struct objc_class *.
531f4a2713aSLionel Sambuc   llvm::Type *ClassPtrTy;
532f4a2713aSLionel Sambuc   /// ClassExtensionTy - LLVM type for struct objc_class_ext.
533f4a2713aSLionel Sambuc   llvm::StructType *ClassExtensionTy;
534f4a2713aSLionel Sambuc   /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *.
535f4a2713aSLionel Sambuc   llvm::Type *ClassExtensionPtrTy;
536f4a2713aSLionel Sambuc   // IvarTy - LLVM type for struct objc_ivar.
537f4a2713aSLionel Sambuc   llvm::StructType *IvarTy;
538f4a2713aSLionel Sambuc   /// IvarListTy - LLVM type for struct objc_ivar_list.
539f4a2713aSLionel Sambuc   llvm::Type *IvarListTy;
540f4a2713aSLionel Sambuc   /// IvarListPtrTy - LLVM type for struct objc_ivar_list *.
541f4a2713aSLionel Sambuc   llvm::Type *IvarListPtrTy;
542f4a2713aSLionel Sambuc   /// MethodListTy - LLVM type for struct objc_method_list.
543f4a2713aSLionel Sambuc   llvm::Type *MethodListTy;
544f4a2713aSLionel Sambuc   /// MethodListPtrTy - LLVM type for struct objc_method_list *.
545f4a2713aSLionel Sambuc   llvm::Type *MethodListPtrTy;
546f4a2713aSLionel Sambuc 
547f4a2713aSLionel Sambuc   /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
548f4a2713aSLionel Sambuc   llvm::Type *ExceptionDataTy;
549f4a2713aSLionel Sambuc 
550f4a2713aSLionel Sambuc   /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
getExceptionTryEnterFn()551f4a2713aSLionel Sambuc   llvm::Constant *getExceptionTryEnterFn() {
552f4a2713aSLionel Sambuc     llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
553f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(
554f4a2713aSLionel Sambuc       llvm::FunctionType::get(CGM.VoidTy, params, false),
555f4a2713aSLionel Sambuc       "objc_exception_try_enter");
556f4a2713aSLionel Sambuc   }
557f4a2713aSLionel Sambuc 
558f4a2713aSLionel Sambuc   /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
getExceptionTryExitFn()559f4a2713aSLionel Sambuc   llvm::Constant *getExceptionTryExitFn() {
560f4a2713aSLionel Sambuc     llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
561f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(
562f4a2713aSLionel Sambuc       llvm::FunctionType::get(CGM.VoidTy, params, false),
563f4a2713aSLionel Sambuc       "objc_exception_try_exit");
564f4a2713aSLionel Sambuc   }
565f4a2713aSLionel Sambuc 
566f4a2713aSLionel Sambuc   /// ExceptionExtractFn - LLVM objc_exception_extract function.
getExceptionExtractFn()567f4a2713aSLionel Sambuc   llvm::Constant *getExceptionExtractFn() {
568f4a2713aSLionel Sambuc     llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
569f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
570f4a2713aSLionel Sambuc                                                              params, false),
571f4a2713aSLionel Sambuc                                      "objc_exception_extract");
572f4a2713aSLionel Sambuc   }
573f4a2713aSLionel Sambuc 
574f4a2713aSLionel Sambuc   /// ExceptionMatchFn - LLVM objc_exception_match function.
getExceptionMatchFn()575f4a2713aSLionel Sambuc   llvm::Constant *getExceptionMatchFn() {
576f4a2713aSLionel Sambuc     llvm::Type *params[] = { ClassPtrTy, ObjectPtrTy };
577f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(
578f4a2713aSLionel Sambuc       llvm::FunctionType::get(CGM.Int32Ty, params, false),
579f4a2713aSLionel Sambuc       "objc_exception_match");
580f4a2713aSLionel Sambuc 
581f4a2713aSLionel Sambuc   }
582f4a2713aSLionel Sambuc 
583f4a2713aSLionel Sambuc   /// SetJmpFn - LLVM _setjmp function.
getSetJmpFn()584f4a2713aSLionel Sambuc   llvm::Constant *getSetJmpFn() {
585f4a2713aSLionel Sambuc     // This is specifically the prototype for x86.
586f4a2713aSLionel Sambuc     llvm::Type *params[] = { CGM.Int32Ty->getPointerTo() };
587f4a2713aSLionel Sambuc     return
588f4a2713aSLionel Sambuc       CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.Int32Ty,
589f4a2713aSLionel Sambuc                                                         params, false),
590f4a2713aSLionel Sambuc                                 "_setjmp",
591f4a2713aSLionel Sambuc                                 llvm::AttributeSet::get(CGM.getLLVMContext(),
592f4a2713aSLionel Sambuc                                               llvm::AttributeSet::FunctionIndex,
593f4a2713aSLionel Sambuc                                                  llvm::Attribute::NonLazyBind));
594f4a2713aSLionel Sambuc   }
595f4a2713aSLionel Sambuc 
596f4a2713aSLionel Sambuc public:
597f4a2713aSLionel Sambuc   ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
~ObjCTypesHelper()598f4a2713aSLionel Sambuc   ~ObjCTypesHelper() {}
599f4a2713aSLionel Sambuc };
600f4a2713aSLionel Sambuc 
601f4a2713aSLionel Sambuc /// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
602f4a2713aSLionel Sambuc /// modern abi
603f4a2713aSLionel Sambuc class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
604f4a2713aSLionel Sambuc public:
605f4a2713aSLionel Sambuc 
606f4a2713aSLionel Sambuc   // MethodListnfABITy - LLVM for struct _method_list_t
607f4a2713aSLionel Sambuc   llvm::StructType *MethodListnfABITy;
608f4a2713aSLionel Sambuc 
609f4a2713aSLionel Sambuc   // MethodListnfABIPtrTy - LLVM for struct _method_list_t*
610f4a2713aSLionel Sambuc   llvm::Type *MethodListnfABIPtrTy;
611f4a2713aSLionel Sambuc 
612f4a2713aSLionel Sambuc   // ProtocolnfABITy = LLVM for struct _protocol_t
613f4a2713aSLionel Sambuc   llvm::StructType *ProtocolnfABITy;
614f4a2713aSLionel Sambuc 
615f4a2713aSLionel Sambuc   // ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
616f4a2713aSLionel Sambuc   llvm::Type *ProtocolnfABIPtrTy;
617f4a2713aSLionel Sambuc 
618f4a2713aSLionel Sambuc   // ProtocolListnfABITy - LLVM for struct _objc_protocol_list
619f4a2713aSLionel Sambuc   llvm::StructType *ProtocolListnfABITy;
620f4a2713aSLionel Sambuc 
621f4a2713aSLionel Sambuc   // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
622f4a2713aSLionel Sambuc   llvm::Type *ProtocolListnfABIPtrTy;
623f4a2713aSLionel Sambuc 
624f4a2713aSLionel Sambuc   // ClassnfABITy - LLVM for struct _class_t
625f4a2713aSLionel Sambuc   llvm::StructType *ClassnfABITy;
626f4a2713aSLionel Sambuc 
627f4a2713aSLionel Sambuc   // ClassnfABIPtrTy - LLVM for struct _class_t*
628f4a2713aSLionel Sambuc   llvm::Type *ClassnfABIPtrTy;
629f4a2713aSLionel Sambuc 
630f4a2713aSLionel Sambuc   // IvarnfABITy - LLVM for struct _ivar_t
631f4a2713aSLionel Sambuc   llvm::StructType *IvarnfABITy;
632f4a2713aSLionel Sambuc 
633f4a2713aSLionel Sambuc   // IvarListnfABITy - LLVM for struct _ivar_list_t
634f4a2713aSLionel Sambuc   llvm::StructType *IvarListnfABITy;
635f4a2713aSLionel Sambuc 
636f4a2713aSLionel Sambuc   // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
637f4a2713aSLionel Sambuc   llvm::Type *IvarListnfABIPtrTy;
638f4a2713aSLionel Sambuc 
639f4a2713aSLionel Sambuc   // ClassRonfABITy - LLVM for struct _class_ro_t
640f4a2713aSLionel Sambuc   llvm::StructType *ClassRonfABITy;
641f4a2713aSLionel Sambuc 
642f4a2713aSLionel Sambuc   // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
643f4a2713aSLionel Sambuc   llvm::Type *ImpnfABITy;
644f4a2713aSLionel Sambuc 
645f4a2713aSLionel Sambuc   // CategorynfABITy - LLVM for struct _category_t
646f4a2713aSLionel Sambuc   llvm::StructType *CategorynfABITy;
647f4a2713aSLionel Sambuc 
648f4a2713aSLionel Sambuc   // New types for nonfragile abi messaging.
649f4a2713aSLionel Sambuc 
650f4a2713aSLionel Sambuc   // MessageRefTy - LLVM for:
651f4a2713aSLionel Sambuc   // struct _message_ref_t {
652f4a2713aSLionel Sambuc   //   IMP messenger;
653f4a2713aSLionel Sambuc   //   SEL name;
654f4a2713aSLionel Sambuc   // };
655f4a2713aSLionel Sambuc   llvm::StructType *MessageRefTy;
656f4a2713aSLionel Sambuc   // MessageRefCTy - clang type for struct _message_ref_t
657f4a2713aSLionel Sambuc   QualType MessageRefCTy;
658f4a2713aSLionel Sambuc 
659f4a2713aSLionel Sambuc   // MessageRefPtrTy - LLVM for struct _message_ref_t*
660f4a2713aSLionel Sambuc   llvm::Type *MessageRefPtrTy;
661f4a2713aSLionel Sambuc   // MessageRefCPtrTy - clang type for struct _message_ref_t*
662f4a2713aSLionel Sambuc   QualType MessageRefCPtrTy;
663f4a2713aSLionel Sambuc 
664f4a2713aSLionel Sambuc   // MessengerTy - Type of the messenger (shown as IMP above)
665f4a2713aSLionel Sambuc   llvm::FunctionType *MessengerTy;
666f4a2713aSLionel Sambuc 
667f4a2713aSLionel Sambuc   // SuperMessageRefTy - LLVM for:
668f4a2713aSLionel Sambuc   // struct _super_message_ref_t {
669f4a2713aSLionel Sambuc   //   SUPER_IMP messenger;
670f4a2713aSLionel Sambuc   //   SEL name;
671f4a2713aSLionel Sambuc   // };
672f4a2713aSLionel Sambuc   llvm::StructType *SuperMessageRefTy;
673f4a2713aSLionel Sambuc 
674f4a2713aSLionel Sambuc   // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
675f4a2713aSLionel Sambuc   llvm::Type *SuperMessageRefPtrTy;
676f4a2713aSLionel Sambuc 
getMessageSendFixupFn()677f4a2713aSLionel Sambuc   llvm::Constant *getMessageSendFixupFn() {
678f4a2713aSLionel Sambuc     // id objc_msgSend_fixup(id, struct message_ref_t*, ...)
679f4a2713aSLionel Sambuc     llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
680f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
681f4a2713aSLionel Sambuc                                                              params, true),
682f4a2713aSLionel Sambuc                                      "objc_msgSend_fixup");
683f4a2713aSLionel Sambuc   }
684f4a2713aSLionel Sambuc 
getMessageSendFpretFixupFn()685f4a2713aSLionel Sambuc   llvm::Constant *getMessageSendFpretFixupFn() {
686f4a2713aSLionel Sambuc     // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...)
687f4a2713aSLionel Sambuc     llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
688f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
689f4a2713aSLionel Sambuc                                                              params, true),
690f4a2713aSLionel Sambuc                                      "objc_msgSend_fpret_fixup");
691f4a2713aSLionel Sambuc   }
692f4a2713aSLionel Sambuc 
getMessageSendStretFixupFn()693f4a2713aSLionel Sambuc   llvm::Constant *getMessageSendStretFixupFn() {
694f4a2713aSLionel Sambuc     // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...)
695f4a2713aSLionel Sambuc     llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
696f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
697f4a2713aSLionel Sambuc                                                              params, true),
698f4a2713aSLionel Sambuc                                      "objc_msgSend_stret_fixup");
699f4a2713aSLionel Sambuc   }
700f4a2713aSLionel Sambuc 
getMessageSendSuper2FixupFn()701f4a2713aSLionel Sambuc   llvm::Constant *getMessageSendSuper2FixupFn() {
702f4a2713aSLionel Sambuc     // id objc_msgSendSuper2_fixup (struct objc_super *,
703f4a2713aSLionel Sambuc     //                              struct _super_message_ref_t*, ...)
704f4a2713aSLionel Sambuc     llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
705f4a2713aSLionel Sambuc     return  CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
706f4a2713aSLionel Sambuc                                                               params, true),
707f4a2713aSLionel Sambuc                                       "objc_msgSendSuper2_fixup");
708f4a2713aSLionel Sambuc   }
709f4a2713aSLionel Sambuc 
getMessageSendSuper2StretFixupFn()710f4a2713aSLionel Sambuc   llvm::Constant *getMessageSendSuper2StretFixupFn() {
711f4a2713aSLionel Sambuc     // id objc_msgSendSuper2_stret_fixup(struct objc_super *,
712f4a2713aSLionel Sambuc     //                                   struct _super_message_ref_t*, ...)
713f4a2713aSLionel Sambuc     llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
714f4a2713aSLionel Sambuc     return  CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
715f4a2713aSLionel Sambuc                                                               params, true),
716f4a2713aSLionel Sambuc                                       "objc_msgSendSuper2_stret_fixup");
717f4a2713aSLionel Sambuc   }
718f4a2713aSLionel Sambuc 
getObjCEndCatchFn()719f4a2713aSLionel Sambuc   llvm::Constant *getObjCEndCatchFn() {
720f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy, false),
721f4a2713aSLionel Sambuc                                      "objc_end_catch");
722f4a2713aSLionel Sambuc 
723f4a2713aSLionel Sambuc   }
724f4a2713aSLionel Sambuc 
getObjCBeginCatchFn()725f4a2713aSLionel Sambuc   llvm::Constant *getObjCBeginCatchFn() {
726f4a2713aSLionel Sambuc     llvm::Type *params[] = { Int8PtrTy };
727f4a2713aSLionel Sambuc     return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy,
728f4a2713aSLionel Sambuc                                                              params, false),
729f4a2713aSLionel Sambuc                                      "objc_begin_catch");
730f4a2713aSLionel Sambuc   }
731f4a2713aSLionel Sambuc 
732f4a2713aSLionel Sambuc   llvm::StructType *EHTypeTy;
733f4a2713aSLionel Sambuc   llvm::Type *EHTypePtrTy;
734f4a2713aSLionel Sambuc 
735f4a2713aSLionel Sambuc   ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
~ObjCNonFragileABITypesHelper()736f4a2713aSLionel Sambuc   ~ObjCNonFragileABITypesHelper(){}
737f4a2713aSLionel Sambuc };
738f4a2713aSLionel Sambuc 
739f4a2713aSLionel Sambuc class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
740f4a2713aSLionel Sambuc public:
741f4a2713aSLionel Sambuc   // FIXME - accessibility
742f4a2713aSLionel Sambuc   class GC_IVAR {
743f4a2713aSLionel Sambuc   public:
744f4a2713aSLionel Sambuc     unsigned ivar_bytepos;
745f4a2713aSLionel Sambuc     unsigned ivar_size;
GC_IVAR(unsigned bytepos=0,unsigned size=0)746f4a2713aSLionel Sambuc     GC_IVAR(unsigned bytepos = 0, unsigned size = 0)
747f4a2713aSLionel Sambuc       : ivar_bytepos(bytepos), ivar_size(size) {}
748f4a2713aSLionel Sambuc 
749f4a2713aSLionel Sambuc     // Allow sorting based on byte pos.
operator <(const GC_IVAR & b) const750f4a2713aSLionel Sambuc     bool operator<(const GC_IVAR &b) const {
751f4a2713aSLionel Sambuc       return ivar_bytepos < b.ivar_bytepos;
752f4a2713aSLionel Sambuc     }
753f4a2713aSLionel Sambuc   };
754f4a2713aSLionel Sambuc 
755f4a2713aSLionel Sambuc   class SKIP_SCAN {
756f4a2713aSLionel Sambuc   public:
757f4a2713aSLionel Sambuc     unsigned skip;
758f4a2713aSLionel Sambuc     unsigned scan;
SKIP_SCAN(unsigned _skip=0,unsigned _scan=0)759f4a2713aSLionel Sambuc     SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0)
760f4a2713aSLionel Sambuc       : skip(_skip), scan(_scan) {}
761f4a2713aSLionel Sambuc   };
762f4a2713aSLionel Sambuc 
763f4a2713aSLionel Sambuc   /// opcode for captured block variables layout 'instructions'.
764f4a2713aSLionel Sambuc   /// In the following descriptions, 'I' is the value of the immediate field.
765f4a2713aSLionel Sambuc   /// (field following the opcode).
766f4a2713aSLionel Sambuc   ///
767f4a2713aSLionel Sambuc   enum BLOCK_LAYOUT_OPCODE {
768f4a2713aSLionel Sambuc     /// An operator which affects how the following layout should be
769f4a2713aSLionel Sambuc     /// interpreted.
770f4a2713aSLionel Sambuc     ///   I == 0: Halt interpretation and treat everything else as
771f4a2713aSLionel Sambuc     ///           a non-pointer.  Note that this instruction is equal
772f4a2713aSLionel Sambuc     ///           to '\0'.
773f4a2713aSLionel Sambuc     ///   I != 0: Currently unused.
774f4a2713aSLionel Sambuc     BLOCK_LAYOUT_OPERATOR            = 0,
775f4a2713aSLionel Sambuc 
776f4a2713aSLionel Sambuc     /// The next I+1 bytes do not contain a value of object pointer type.
777f4a2713aSLionel Sambuc     /// Note that this can leave the stream unaligned, meaning that
778f4a2713aSLionel Sambuc     /// subsequent word-size instructions do not begin at a multiple of
779f4a2713aSLionel Sambuc     /// the pointer size.
780f4a2713aSLionel Sambuc     BLOCK_LAYOUT_NON_OBJECT_BYTES    = 1,
781f4a2713aSLionel Sambuc 
782f4a2713aSLionel Sambuc     /// The next I+1 words do not contain a value of object pointer type.
783f4a2713aSLionel Sambuc     /// This is simply an optimized version of BLOCK_LAYOUT_BYTES for
784f4a2713aSLionel Sambuc     /// when the required skip quantity is a multiple of the pointer size.
785f4a2713aSLionel Sambuc     BLOCK_LAYOUT_NON_OBJECT_WORDS    = 2,
786f4a2713aSLionel Sambuc 
787f4a2713aSLionel Sambuc     /// The next I+1 words are __strong pointers to Objective-C
788f4a2713aSLionel Sambuc     /// objects or blocks.
789f4a2713aSLionel Sambuc     BLOCK_LAYOUT_STRONG              = 3,
790f4a2713aSLionel Sambuc 
791f4a2713aSLionel Sambuc     /// The next I+1 words are pointers to __block variables.
792f4a2713aSLionel Sambuc     BLOCK_LAYOUT_BYREF               = 4,
793f4a2713aSLionel Sambuc 
794f4a2713aSLionel Sambuc     /// The next I+1 words are __weak pointers to Objective-C
795f4a2713aSLionel Sambuc     /// objects or blocks.
796f4a2713aSLionel Sambuc     BLOCK_LAYOUT_WEAK                = 5,
797f4a2713aSLionel Sambuc 
798f4a2713aSLionel Sambuc     /// The next I+1 words are __unsafe_unretained pointers to
799f4a2713aSLionel Sambuc     /// Objective-C objects or blocks.
800f4a2713aSLionel Sambuc     BLOCK_LAYOUT_UNRETAINED          = 6
801f4a2713aSLionel Sambuc 
802f4a2713aSLionel Sambuc     /// The next I+1 words are block or object pointers with some
803f4a2713aSLionel Sambuc     /// as-yet-unspecified ownership semantics.  If we add more
804f4a2713aSLionel Sambuc     /// flavors of ownership semantics, values will be taken from
805f4a2713aSLionel Sambuc     /// this range.
806f4a2713aSLionel Sambuc     ///
807f4a2713aSLionel Sambuc     /// This is included so that older tools can at least continue
808f4a2713aSLionel Sambuc     /// processing the layout past such things.
809f4a2713aSLionel Sambuc     //BLOCK_LAYOUT_OWNERSHIP_UNKNOWN = 7..10,
810f4a2713aSLionel Sambuc 
811f4a2713aSLionel Sambuc     /// All other opcodes are reserved.  Halt interpretation and
812f4a2713aSLionel Sambuc     /// treat everything else as opaque.
813f4a2713aSLionel Sambuc   };
814f4a2713aSLionel Sambuc 
815f4a2713aSLionel Sambuc   class RUN_SKIP {
816f4a2713aSLionel Sambuc   public:
817f4a2713aSLionel Sambuc     enum BLOCK_LAYOUT_OPCODE opcode;
818f4a2713aSLionel Sambuc     CharUnits block_var_bytepos;
819f4a2713aSLionel Sambuc     CharUnits block_var_size;
RUN_SKIP(enum BLOCK_LAYOUT_OPCODE Opcode=BLOCK_LAYOUT_OPERATOR,CharUnits BytePos=CharUnits::Zero (),CharUnits Size=CharUnits::Zero ())820f4a2713aSLionel Sambuc     RUN_SKIP(enum BLOCK_LAYOUT_OPCODE Opcode = BLOCK_LAYOUT_OPERATOR,
821f4a2713aSLionel Sambuc              CharUnits BytePos = CharUnits::Zero(),
822f4a2713aSLionel Sambuc              CharUnits Size = CharUnits::Zero())
823f4a2713aSLionel Sambuc     : opcode(Opcode), block_var_bytepos(BytePos),  block_var_size(Size) {}
824f4a2713aSLionel Sambuc 
825f4a2713aSLionel Sambuc     // Allow sorting based on byte pos.
operator <(const RUN_SKIP & b) const826f4a2713aSLionel Sambuc     bool operator<(const RUN_SKIP &b) const {
827f4a2713aSLionel Sambuc       return block_var_bytepos < b.block_var_bytepos;
828f4a2713aSLionel Sambuc     }
829f4a2713aSLionel Sambuc   };
830f4a2713aSLionel Sambuc 
831f4a2713aSLionel Sambuc protected:
832f4a2713aSLionel Sambuc   llvm::LLVMContext &VMContext;
833f4a2713aSLionel Sambuc   // FIXME! May not be needing this after all.
834f4a2713aSLionel Sambuc   unsigned ObjCABI;
835f4a2713aSLionel Sambuc 
836f4a2713aSLionel Sambuc   // gc ivar layout bitmap calculation helper caches.
837f4a2713aSLionel Sambuc   SmallVector<GC_IVAR, 16> SkipIvars;
838f4a2713aSLionel Sambuc   SmallVector<GC_IVAR, 16> IvarsInfo;
839f4a2713aSLionel Sambuc 
840f4a2713aSLionel Sambuc   // arc/mrr layout of captured block literal variables.
841f4a2713aSLionel Sambuc   SmallVector<RUN_SKIP, 16> RunSkipBlockVars;
842f4a2713aSLionel Sambuc 
843f4a2713aSLionel Sambuc   /// LazySymbols - Symbols to generate a lazy reference for. See
844f4a2713aSLionel Sambuc   /// DefinedSymbols and FinishModule().
845f4a2713aSLionel Sambuc   llvm::SetVector<IdentifierInfo*> LazySymbols;
846f4a2713aSLionel Sambuc 
847f4a2713aSLionel Sambuc   /// DefinedSymbols - External symbols which are defined by this
848f4a2713aSLionel Sambuc   /// module. The symbols in this list and LazySymbols are used to add
849f4a2713aSLionel Sambuc   /// special linker symbols which ensure that Objective-C modules are
850f4a2713aSLionel Sambuc   /// linked properly.
851f4a2713aSLionel Sambuc   llvm::SetVector<IdentifierInfo*> DefinedSymbols;
852f4a2713aSLionel Sambuc 
853f4a2713aSLionel Sambuc   /// ClassNames - uniqued class names.
854*0a6a1f1dSLionel Sambuc   llvm::StringMap<llvm::GlobalVariable*> ClassNames;
855f4a2713aSLionel Sambuc 
856f4a2713aSLionel Sambuc   /// MethodVarNames - uniqued method variable names.
857f4a2713aSLionel Sambuc   llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
858f4a2713aSLionel Sambuc 
859f4a2713aSLionel Sambuc   /// DefinedCategoryNames - list of category names in form Class_Category.
860f4a2713aSLionel Sambuc   llvm::SetVector<std::string> DefinedCategoryNames;
861f4a2713aSLionel Sambuc 
862f4a2713aSLionel Sambuc   /// MethodVarTypes - uniqued method type signatures. We have to use
863f4a2713aSLionel Sambuc   /// a StringMap here because have no other unique reference.
864f4a2713aSLionel Sambuc   llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
865f4a2713aSLionel Sambuc 
866f4a2713aSLionel Sambuc   /// MethodDefinitions - map of methods which have been defined in
867f4a2713aSLionel Sambuc   /// this translation unit.
868f4a2713aSLionel Sambuc   llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions;
869f4a2713aSLionel Sambuc 
870f4a2713aSLionel Sambuc   /// PropertyNames - uniqued method variable names.
871f4a2713aSLionel Sambuc   llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
872f4a2713aSLionel Sambuc 
873f4a2713aSLionel Sambuc   /// ClassReferences - uniqued class references.
874f4a2713aSLionel Sambuc   llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
875f4a2713aSLionel Sambuc 
876f4a2713aSLionel Sambuc   /// SelectorReferences - uniqued selector references.
877f4a2713aSLionel Sambuc   llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
878f4a2713aSLionel Sambuc 
879f4a2713aSLionel Sambuc   /// Protocols - Protocols for which an objc_protocol structure has
880f4a2713aSLionel Sambuc   /// been emitted. Forward declarations are handled by creating an
881f4a2713aSLionel Sambuc   /// empty structure whose initializer is filled in when/if defined.
882f4a2713aSLionel Sambuc   llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
883f4a2713aSLionel Sambuc 
884f4a2713aSLionel Sambuc   /// DefinedProtocols - Protocols which have actually been
885f4a2713aSLionel Sambuc   /// defined. We should not need this, see FIXME in GenerateProtocol.
886f4a2713aSLionel Sambuc   llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
887f4a2713aSLionel Sambuc 
888f4a2713aSLionel Sambuc   /// DefinedClasses - List of defined classes.
889f4a2713aSLionel Sambuc   SmallVector<llvm::GlobalValue*, 16> DefinedClasses;
890f4a2713aSLionel Sambuc 
891*0a6a1f1dSLionel Sambuc   /// ImplementedClasses - List of @implemented classes.
892*0a6a1f1dSLionel Sambuc   SmallVector<const ObjCInterfaceDecl*, 16> ImplementedClasses;
893*0a6a1f1dSLionel Sambuc 
894f4a2713aSLionel Sambuc   /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
895f4a2713aSLionel Sambuc   SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyClasses;
896f4a2713aSLionel Sambuc 
897f4a2713aSLionel Sambuc   /// DefinedCategories - List of defined categories.
898f4a2713aSLionel Sambuc   SmallVector<llvm::GlobalValue*, 16> DefinedCategories;
899f4a2713aSLionel Sambuc 
900f4a2713aSLionel Sambuc   /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
901f4a2713aSLionel Sambuc   SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyCategories;
902f4a2713aSLionel Sambuc 
903f4a2713aSLionel Sambuc   /// GetNameForMethod - Return a name for the given method.
904f4a2713aSLionel Sambuc   /// \param[out] NameOut - The return value.
905f4a2713aSLionel Sambuc   void GetNameForMethod(const ObjCMethodDecl *OMD,
906f4a2713aSLionel Sambuc                         const ObjCContainerDecl *CD,
907f4a2713aSLionel Sambuc                         SmallVectorImpl<char> &NameOut);
908f4a2713aSLionel Sambuc 
909f4a2713aSLionel Sambuc   /// GetMethodVarName - Return a unique constant for the given
910f4a2713aSLionel Sambuc   /// selector's name. The return value has type char *.
911f4a2713aSLionel Sambuc   llvm::Constant *GetMethodVarName(Selector Sel);
912f4a2713aSLionel Sambuc   llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
913f4a2713aSLionel Sambuc 
914f4a2713aSLionel Sambuc   /// GetMethodVarType - Return a unique constant for the given
915f4a2713aSLionel Sambuc   /// method's type encoding string. The return value has type char *.
916f4a2713aSLionel Sambuc 
917f4a2713aSLionel Sambuc   // FIXME: This is a horrible name.
918f4a2713aSLionel Sambuc   llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D,
919f4a2713aSLionel Sambuc                                    bool Extended = false);
920f4a2713aSLionel Sambuc   llvm::Constant *GetMethodVarType(const FieldDecl *D);
921f4a2713aSLionel Sambuc 
922f4a2713aSLionel Sambuc   /// GetPropertyName - Return a unique constant for the given
923f4a2713aSLionel Sambuc   /// name. The return value has type char *.
924f4a2713aSLionel Sambuc   llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
925f4a2713aSLionel Sambuc 
926f4a2713aSLionel Sambuc   // FIXME: This can be dropped once string functions are unified.
927f4a2713aSLionel Sambuc   llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
928f4a2713aSLionel Sambuc                                         const Decl *Container);
929f4a2713aSLionel Sambuc 
930f4a2713aSLionel Sambuc   /// GetClassName - Return a unique constant for the given selector's
931*0a6a1f1dSLionel Sambuc   /// runtime name (which may change via use of objc_runtime_name attribute on
932*0a6a1f1dSLionel Sambuc   /// class or protocol definition. The return value has type char *.
933*0a6a1f1dSLionel Sambuc   llvm::Constant *GetClassName(StringRef RuntimeName);
934f4a2713aSLionel Sambuc 
935f4a2713aSLionel Sambuc   llvm::Function *GetMethodDefinition(const ObjCMethodDecl *MD);
936f4a2713aSLionel Sambuc 
937f4a2713aSLionel Sambuc   /// BuildIvarLayout - Builds ivar layout bitmap for the class
938f4a2713aSLionel Sambuc   /// implementation for the __strong or __weak case.
939f4a2713aSLionel Sambuc   ///
940f4a2713aSLionel Sambuc   llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
941f4a2713aSLionel Sambuc                                   bool ForStrongLayout);
942f4a2713aSLionel Sambuc 
943f4a2713aSLionel Sambuc   llvm::Constant *BuildIvarLayoutBitmap(std::string &BitMap);
944f4a2713aSLionel Sambuc 
945f4a2713aSLionel Sambuc   void BuildAggrIvarRecordLayout(const RecordType *RT,
946f4a2713aSLionel Sambuc                                  unsigned int BytePos, bool ForStrongLayout,
947f4a2713aSLionel Sambuc                                  bool &HasUnion);
948f4a2713aSLionel Sambuc   void BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
949f4a2713aSLionel Sambuc                            const llvm::StructLayout *Layout,
950f4a2713aSLionel Sambuc                            const RecordDecl *RD,
951f4a2713aSLionel Sambuc                            ArrayRef<const FieldDecl*> RecFields,
952f4a2713aSLionel Sambuc                            unsigned int BytePos, bool ForStrongLayout,
953f4a2713aSLionel Sambuc                            bool &HasUnion);
954f4a2713aSLionel Sambuc 
955f4a2713aSLionel Sambuc   Qualifiers::ObjCLifetime getBlockCaptureLifetime(QualType QT, bool ByrefLayout);
956f4a2713aSLionel Sambuc 
957f4a2713aSLionel Sambuc   void UpdateRunSkipBlockVars(bool IsByref,
958f4a2713aSLionel Sambuc                               Qualifiers::ObjCLifetime LifeTime,
959f4a2713aSLionel Sambuc                               CharUnits FieldOffset,
960f4a2713aSLionel Sambuc                               CharUnits FieldSize);
961f4a2713aSLionel Sambuc 
962f4a2713aSLionel Sambuc   void BuildRCBlockVarRecordLayout(const RecordType *RT,
963f4a2713aSLionel Sambuc                                    CharUnits BytePos, bool &HasUnion,
964f4a2713aSLionel Sambuc                                    bool ByrefLayout=false);
965f4a2713aSLionel Sambuc 
966f4a2713aSLionel Sambuc   void BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
967f4a2713aSLionel Sambuc                            const RecordDecl *RD,
968f4a2713aSLionel Sambuc                            ArrayRef<const FieldDecl*> RecFields,
969f4a2713aSLionel Sambuc                            CharUnits BytePos, bool &HasUnion,
970f4a2713aSLionel Sambuc                            bool ByrefLayout);
971f4a2713aSLionel Sambuc 
972f4a2713aSLionel Sambuc   uint64_t InlineLayoutInstruction(SmallVectorImpl<unsigned char> &Layout);
973f4a2713aSLionel Sambuc 
974f4a2713aSLionel Sambuc   llvm::Constant *getBitmapBlockLayout(bool ComputeByrefLayout);
975f4a2713aSLionel Sambuc 
976f4a2713aSLionel Sambuc 
977f4a2713aSLionel Sambuc   /// GetIvarLayoutName - Returns a unique constant for the given
978f4a2713aSLionel Sambuc   /// ivar layout bitmap.
979f4a2713aSLionel Sambuc   llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
980f4a2713aSLionel Sambuc                                     const ObjCCommonTypesHelper &ObjCTypes);
981f4a2713aSLionel Sambuc 
982f4a2713aSLionel Sambuc   /// EmitPropertyList - Emit the given property list. The return
983f4a2713aSLionel Sambuc   /// value has type PropertyListPtrTy.
984f4a2713aSLionel Sambuc   llvm::Constant *EmitPropertyList(Twine Name,
985f4a2713aSLionel Sambuc                                    const Decl *Container,
986f4a2713aSLionel Sambuc                                    const ObjCContainerDecl *OCD,
987f4a2713aSLionel Sambuc                                    const ObjCCommonTypesHelper &ObjCTypes);
988f4a2713aSLionel Sambuc 
989f4a2713aSLionel Sambuc   /// EmitProtocolMethodTypes - Generate the array of extended method type
990f4a2713aSLionel Sambuc   /// strings. The return value has type Int8PtrPtrTy.
991f4a2713aSLionel Sambuc   llvm::Constant *EmitProtocolMethodTypes(Twine Name,
992f4a2713aSLionel Sambuc                                           ArrayRef<llvm::Constant*> MethodTypes,
993f4a2713aSLionel Sambuc                                        const ObjCCommonTypesHelper &ObjCTypes);
994f4a2713aSLionel Sambuc 
995f4a2713aSLionel Sambuc   /// PushProtocolProperties - Push protocol's property on the input stack.
996f4a2713aSLionel Sambuc   void PushProtocolProperties(
997f4a2713aSLionel Sambuc     llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet,
998f4a2713aSLionel Sambuc     SmallVectorImpl<llvm::Constant*> &Properties,
999f4a2713aSLionel Sambuc     const Decl *Container,
1000*0a6a1f1dSLionel Sambuc     const ObjCProtocolDecl *Proto,
1001f4a2713aSLionel Sambuc     const ObjCCommonTypesHelper &ObjCTypes);
1002f4a2713aSLionel Sambuc 
1003f4a2713aSLionel Sambuc   /// GetProtocolRef - Return a reference to the internal protocol
1004f4a2713aSLionel Sambuc   /// description, creating an empty one if it has not been
1005f4a2713aSLionel Sambuc   /// defined. The return value has type ProtocolPtrTy.
1006f4a2713aSLionel Sambuc   llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
1007f4a2713aSLionel Sambuc 
1008f4a2713aSLionel Sambuc   /// CreateMetadataVar - Create a global variable with internal
1009f4a2713aSLionel Sambuc   /// linkage for use by the Objective-C runtime.
1010f4a2713aSLionel Sambuc   ///
1011f4a2713aSLionel Sambuc   /// This is a convenience wrapper which not only creates the
1012f4a2713aSLionel Sambuc   /// variable, but also sets the section and alignment and adds the
1013f4a2713aSLionel Sambuc   /// global to the "llvm.used" list.
1014f4a2713aSLionel Sambuc   ///
1015f4a2713aSLionel Sambuc   /// \param Name - The variable name.
1016f4a2713aSLionel Sambuc   /// \param Init - The variable initializer; this is also used to
1017f4a2713aSLionel Sambuc   /// define the type of the variable.
1018*0a6a1f1dSLionel Sambuc   /// \param Section - The section the variable should go into, or empty.
1019f4a2713aSLionel Sambuc   /// \param Align - The alignment for the variable, or 0.
1020f4a2713aSLionel Sambuc   /// \param AddToUsed - Whether the variable should be added to
1021f4a2713aSLionel Sambuc   /// "llvm.used".
1022*0a6a1f1dSLionel Sambuc   llvm::GlobalVariable *CreateMetadataVar(Twine Name, llvm::Constant *Init,
1023*0a6a1f1dSLionel Sambuc                                           StringRef Section, unsigned Align,
1024f4a2713aSLionel Sambuc                                           bool AddToUsed);
1025f4a2713aSLionel Sambuc 
1026f4a2713aSLionel Sambuc   CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
1027f4a2713aSLionel Sambuc                                   ReturnValueSlot Return,
1028f4a2713aSLionel Sambuc                                   QualType ResultType,
1029f4a2713aSLionel Sambuc                                   llvm::Value *Sel,
1030f4a2713aSLionel Sambuc                                   llvm::Value *Arg0,
1031f4a2713aSLionel Sambuc                                   QualType Arg0Ty,
1032f4a2713aSLionel Sambuc                                   bool IsSuper,
1033f4a2713aSLionel Sambuc                                   const CallArgList &CallArgs,
1034f4a2713aSLionel Sambuc                                   const ObjCMethodDecl *OMD,
1035f4a2713aSLionel Sambuc                                   const ObjCCommonTypesHelper &ObjCTypes);
1036f4a2713aSLionel Sambuc 
1037f4a2713aSLionel Sambuc   /// EmitImageInfo - Emit the image info marker used to encode some module
1038f4a2713aSLionel Sambuc   /// level information.
1039f4a2713aSLionel Sambuc   void EmitImageInfo();
1040f4a2713aSLionel Sambuc 
1041f4a2713aSLionel Sambuc public:
CGObjCCommonMac(CodeGen::CodeGenModule & cgm)1042f4a2713aSLionel Sambuc   CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
1043f4a2713aSLionel Sambuc     CGObjCRuntime(cgm), VMContext(cgm.getLLVMContext()) { }
1044f4a2713aSLionel Sambuc 
1045*0a6a1f1dSLionel Sambuc   llvm::Constant *GenerateConstantString(const StringLiteral *SL) override;
1046f4a2713aSLionel Sambuc 
1047*0a6a1f1dSLionel Sambuc   llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
1048*0a6a1f1dSLionel Sambuc                                  const ObjCContainerDecl *CD=nullptr) override;
1049f4a2713aSLionel Sambuc 
1050*0a6a1f1dSLionel Sambuc   void GenerateProtocol(const ObjCProtocolDecl *PD) override;
1051f4a2713aSLionel Sambuc 
1052f4a2713aSLionel Sambuc   /// GetOrEmitProtocol - Get the protocol object for the given
1053f4a2713aSLionel Sambuc   /// declaration, emitting it if necessary. The return value has type
1054f4a2713aSLionel Sambuc   /// ProtocolPtrTy.
1055f4a2713aSLionel Sambuc   virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0;
1056f4a2713aSLionel Sambuc 
1057f4a2713aSLionel Sambuc   /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1058f4a2713aSLionel Sambuc   /// object for the given declaration, emitting it if needed. These
1059f4a2713aSLionel Sambuc   /// forward references will be filled in with empty bodies if no
1060f4a2713aSLionel Sambuc   /// definition is seen. The return value has type ProtocolPtrTy.
1061f4a2713aSLionel Sambuc   virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
1062*0a6a1f1dSLionel Sambuc   llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
1063*0a6a1f1dSLionel Sambuc                                      const CGBlockInfo &blockInfo) override;
1064*0a6a1f1dSLionel Sambuc   llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM,
1065*0a6a1f1dSLionel Sambuc                                      const CGBlockInfo &blockInfo) override;
1066f4a2713aSLionel Sambuc 
1067*0a6a1f1dSLionel Sambuc   llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM,
1068*0a6a1f1dSLionel Sambuc                                    QualType T) override;
1069f4a2713aSLionel Sambuc };
1070f4a2713aSLionel Sambuc 
1071f4a2713aSLionel Sambuc class CGObjCMac : public CGObjCCommonMac {
1072f4a2713aSLionel Sambuc private:
1073f4a2713aSLionel Sambuc   ObjCTypesHelper ObjCTypes;
1074f4a2713aSLionel Sambuc 
1075f4a2713aSLionel Sambuc   /// EmitModuleInfo - Another marker encoding module level
1076f4a2713aSLionel Sambuc   /// information.
1077f4a2713aSLionel Sambuc   void EmitModuleInfo();
1078f4a2713aSLionel Sambuc 
1079f4a2713aSLionel Sambuc   /// EmitModuleSymols - Emit module symbols, the list of defined
1080f4a2713aSLionel Sambuc   /// classes and categories. The result has type SymtabPtrTy.
1081f4a2713aSLionel Sambuc   llvm::Constant *EmitModuleSymbols();
1082f4a2713aSLionel Sambuc 
1083f4a2713aSLionel Sambuc   /// FinishModule - Write out global data structures at the end of
1084f4a2713aSLionel Sambuc   /// processing a translation unit.
1085f4a2713aSLionel Sambuc   void FinishModule();
1086f4a2713aSLionel Sambuc 
1087f4a2713aSLionel Sambuc   /// EmitClassExtension - Generate the class extension structure used
1088f4a2713aSLionel Sambuc   /// to store the weak ivar layout and properties. The return value
1089f4a2713aSLionel Sambuc   /// has type ClassExtensionPtrTy.
1090f4a2713aSLionel Sambuc   llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID);
1091f4a2713aSLionel Sambuc 
1092f4a2713aSLionel Sambuc   /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1093f4a2713aSLionel Sambuc   /// for the given class.
1094f4a2713aSLionel Sambuc   llvm::Value *EmitClassRef(CodeGenFunction &CGF,
1095f4a2713aSLionel Sambuc                             const ObjCInterfaceDecl *ID);
1096f4a2713aSLionel Sambuc 
1097f4a2713aSLionel Sambuc   llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF,
1098f4a2713aSLionel Sambuc                                   IdentifierInfo *II);
1099f4a2713aSLionel Sambuc 
1100*0a6a1f1dSLionel Sambuc   llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) override;
1101f4a2713aSLionel Sambuc 
1102f4a2713aSLionel Sambuc   /// EmitSuperClassRef - Emits reference to class's main metadata class.
1103f4a2713aSLionel Sambuc   llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
1104f4a2713aSLionel Sambuc 
1105f4a2713aSLionel Sambuc   /// EmitIvarList - Emit the ivar list for the given
1106f4a2713aSLionel Sambuc   /// implementation. If ForClass is true the list of class ivars
1107f4a2713aSLionel Sambuc   /// (i.e. metaclass ivars) is emitted, otherwise the list of
1108f4a2713aSLionel Sambuc   /// interface ivars will be emitted. The return value has type
1109f4a2713aSLionel Sambuc   /// IvarListPtrTy.
1110f4a2713aSLionel Sambuc   llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
1111f4a2713aSLionel Sambuc                                bool ForClass);
1112f4a2713aSLionel Sambuc 
1113f4a2713aSLionel Sambuc   /// EmitMetaClass - Emit a forward reference to the class structure
1114f4a2713aSLionel Sambuc   /// for the metaclass of the given interface. The return value has
1115f4a2713aSLionel Sambuc   /// type ClassPtrTy.
1116f4a2713aSLionel Sambuc   llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
1117f4a2713aSLionel Sambuc 
1118f4a2713aSLionel Sambuc   /// EmitMetaClass - Emit a class structure for the metaclass of the
1119f4a2713aSLionel Sambuc   /// given implementation. The return value has type ClassPtrTy.
1120f4a2713aSLionel Sambuc   llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
1121f4a2713aSLionel Sambuc                                 llvm::Constant *Protocols,
1122f4a2713aSLionel Sambuc                                 ArrayRef<llvm::Constant*> Methods);
1123f4a2713aSLionel Sambuc 
1124f4a2713aSLionel Sambuc   llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
1125f4a2713aSLionel Sambuc 
1126f4a2713aSLionel Sambuc   llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
1127f4a2713aSLionel Sambuc 
1128f4a2713aSLionel Sambuc   /// EmitMethodList - Emit the method list for the given
1129f4a2713aSLionel Sambuc   /// implementation. The return value has type MethodListPtrTy.
1130f4a2713aSLionel Sambuc   llvm::Constant *EmitMethodList(Twine Name,
1131f4a2713aSLionel Sambuc                                  const char *Section,
1132f4a2713aSLionel Sambuc                                  ArrayRef<llvm::Constant*> Methods);
1133f4a2713aSLionel Sambuc 
1134f4a2713aSLionel Sambuc   /// EmitMethodDescList - Emit a method description list for a list of
1135f4a2713aSLionel Sambuc   /// method declarations.
1136f4a2713aSLionel Sambuc   ///  - TypeName: The name for the type containing the methods.
1137f4a2713aSLionel Sambuc   ///  - IsProtocol: True iff these methods are for a protocol.
1138f4a2713aSLionel Sambuc   ///  - ClassMethds: True iff these are class methods.
1139f4a2713aSLionel Sambuc   ///  - Required: When true, only "required" methods are
1140f4a2713aSLionel Sambuc   ///    listed. Similarly, when false only "optional" methods are
1141f4a2713aSLionel Sambuc   ///    listed. For classes this should always be true.
1142f4a2713aSLionel Sambuc   ///  - begin, end: The method list to output.
1143f4a2713aSLionel Sambuc   ///
1144f4a2713aSLionel Sambuc   /// The return value has type MethodDescriptionListPtrTy.
1145f4a2713aSLionel Sambuc   llvm::Constant *EmitMethodDescList(Twine Name,
1146f4a2713aSLionel Sambuc                                      const char *Section,
1147f4a2713aSLionel Sambuc                                      ArrayRef<llvm::Constant*> Methods);
1148f4a2713aSLionel Sambuc 
1149f4a2713aSLionel Sambuc   /// GetOrEmitProtocol - Get the protocol object for the given
1150f4a2713aSLionel Sambuc   /// declaration, emitting it if necessary. The return value has type
1151f4a2713aSLionel Sambuc   /// ProtocolPtrTy.
1152*0a6a1f1dSLionel Sambuc   llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD) override;
1153f4a2713aSLionel Sambuc 
1154f4a2713aSLionel Sambuc   /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1155f4a2713aSLionel Sambuc   /// object for the given declaration, emitting it if needed. These
1156f4a2713aSLionel Sambuc   /// forward references will be filled in with empty bodies if no
1157f4a2713aSLionel Sambuc   /// definition is seen. The return value has type ProtocolPtrTy.
1158*0a6a1f1dSLionel Sambuc   llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) override;
1159f4a2713aSLionel Sambuc 
1160f4a2713aSLionel Sambuc   /// EmitProtocolExtension - Generate the protocol extension
1161f4a2713aSLionel Sambuc   /// structure used to store optional instance and class methods, and
1162f4a2713aSLionel Sambuc   /// protocol properties. The return value has type
1163f4a2713aSLionel Sambuc   /// ProtocolExtensionPtrTy.
1164f4a2713aSLionel Sambuc   llvm::Constant *
1165f4a2713aSLionel Sambuc   EmitProtocolExtension(const ObjCProtocolDecl *PD,
1166f4a2713aSLionel Sambuc                         ArrayRef<llvm::Constant*> OptInstanceMethods,
1167f4a2713aSLionel Sambuc                         ArrayRef<llvm::Constant*> OptClassMethods,
1168f4a2713aSLionel Sambuc                         ArrayRef<llvm::Constant*> MethodTypesExt);
1169f4a2713aSLionel Sambuc 
1170f4a2713aSLionel Sambuc   /// EmitProtocolList - Generate the list of referenced
1171f4a2713aSLionel Sambuc   /// protocols. The return value has type ProtocolListPtrTy.
1172f4a2713aSLionel Sambuc   llvm::Constant *EmitProtocolList(Twine Name,
1173f4a2713aSLionel Sambuc                                    ObjCProtocolDecl::protocol_iterator begin,
1174f4a2713aSLionel Sambuc                                    ObjCProtocolDecl::protocol_iterator end);
1175f4a2713aSLionel Sambuc 
1176f4a2713aSLionel Sambuc   /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1177f4a2713aSLionel Sambuc   /// for the given selector.
1178f4a2713aSLionel Sambuc   llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel,
1179f4a2713aSLionel Sambuc                             bool lval=false);
1180f4a2713aSLionel Sambuc 
1181f4a2713aSLionel Sambuc public:
1182f4a2713aSLionel Sambuc   CGObjCMac(CodeGen::CodeGenModule &cgm);
1183f4a2713aSLionel Sambuc 
1184*0a6a1f1dSLionel Sambuc   llvm::Function *ModuleInitFunction() override;
1185f4a2713aSLionel Sambuc 
1186*0a6a1f1dSLionel Sambuc   CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1187f4a2713aSLionel Sambuc                                       ReturnValueSlot Return,
1188f4a2713aSLionel Sambuc                                       QualType ResultType,
1189*0a6a1f1dSLionel Sambuc                                       Selector Sel, llvm::Value *Receiver,
1190f4a2713aSLionel Sambuc                                       const CallArgList &CallArgs,
1191f4a2713aSLionel Sambuc                                       const ObjCInterfaceDecl *Class,
1192*0a6a1f1dSLionel Sambuc                                       const ObjCMethodDecl *Method) override;
1193f4a2713aSLionel Sambuc 
1194*0a6a1f1dSLionel Sambuc   CodeGen::RValue
1195f4a2713aSLionel Sambuc   GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
1196*0a6a1f1dSLionel Sambuc                            ReturnValueSlot Return, QualType ResultType,
1197*0a6a1f1dSLionel Sambuc                            Selector Sel, const ObjCInterfaceDecl *Class,
1198*0a6a1f1dSLionel Sambuc                            bool isCategoryImpl, llvm::Value *Receiver,
1199*0a6a1f1dSLionel Sambuc                            bool IsClassMessage, const CallArgList &CallArgs,
1200*0a6a1f1dSLionel Sambuc                            const ObjCMethodDecl *Method) override;
1201f4a2713aSLionel Sambuc 
1202*0a6a1f1dSLionel Sambuc   llvm::Value *GetClass(CodeGenFunction &CGF,
1203*0a6a1f1dSLionel Sambuc                         const ObjCInterfaceDecl *ID) override;
1204f4a2713aSLionel Sambuc 
1205*0a6a1f1dSLionel Sambuc   llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel,
1206*0a6a1f1dSLionel Sambuc                            bool lval = false) override;
1207f4a2713aSLionel Sambuc 
1208f4a2713aSLionel Sambuc   /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1209f4a2713aSLionel Sambuc   /// untyped one.
1210*0a6a1f1dSLionel Sambuc   llvm::Value *GetSelector(CodeGenFunction &CGF,
1211*0a6a1f1dSLionel Sambuc                            const ObjCMethodDecl *Method) override;
1212f4a2713aSLionel Sambuc 
1213*0a6a1f1dSLionel Sambuc   llvm::Constant *GetEHType(QualType T) override;
1214f4a2713aSLionel Sambuc 
1215*0a6a1f1dSLionel Sambuc   void GenerateCategory(const ObjCCategoryImplDecl *CMD) override;
1216f4a2713aSLionel Sambuc 
1217*0a6a1f1dSLionel Sambuc   void GenerateClass(const ObjCImplementationDecl *ClassDecl) override;
1218f4a2713aSLionel Sambuc 
RegisterAlias(const ObjCCompatibleAliasDecl * OAD)1219*0a6a1f1dSLionel Sambuc   void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) override {}
1220f4a2713aSLionel Sambuc 
1221*0a6a1f1dSLionel Sambuc   llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
1222*0a6a1f1dSLionel Sambuc                                    const ObjCProtocolDecl *PD) override;
1223f4a2713aSLionel Sambuc 
1224*0a6a1f1dSLionel Sambuc   llvm::Constant *GetPropertyGetFunction() override;
1225*0a6a1f1dSLionel Sambuc   llvm::Constant *GetPropertySetFunction() override;
1226*0a6a1f1dSLionel Sambuc   llvm::Constant *GetOptimizedPropertySetFunction(bool atomic,
1227*0a6a1f1dSLionel Sambuc                                                   bool copy) override;
1228*0a6a1f1dSLionel Sambuc   llvm::Constant *GetGetStructFunction() override;
1229*0a6a1f1dSLionel Sambuc   llvm::Constant *GetSetStructFunction() override;
1230*0a6a1f1dSLionel Sambuc   llvm::Constant *GetCppAtomicObjectGetFunction() override;
1231*0a6a1f1dSLionel Sambuc   llvm::Constant *GetCppAtomicObjectSetFunction() override;
1232*0a6a1f1dSLionel Sambuc   llvm::Constant *EnumerationMutationFunction() override;
1233f4a2713aSLionel Sambuc 
1234*0a6a1f1dSLionel Sambuc   void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1235*0a6a1f1dSLionel Sambuc                    const ObjCAtTryStmt &S) override;
1236*0a6a1f1dSLionel Sambuc   void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1237*0a6a1f1dSLionel Sambuc                             const ObjCAtSynchronizedStmt &S) override;
1238f4a2713aSLionel Sambuc   void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S);
1239*0a6a1f1dSLionel Sambuc   void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S,
1240*0a6a1f1dSLionel Sambuc                      bool ClearInsertionPoint=true) override;
1241*0a6a1f1dSLionel Sambuc   llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
1242*0a6a1f1dSLionel Sambuc                                  llvm::Value *AddrWeakObj) override;
1243*0a6a1f1dSLionel Sambuc   void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
1244*0a6a1f1dSLionel Sambuc                           llvm::Value *src, llvm::Value *dst) override;
1245*0a6a1f1dSLionel Sambuc   void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
1246f4a2713aSLionel Sambuc                             llvm::Value *src, llvm::Value *dest,
1247*0a6a1f1dSLionel Sambuc                             bool threadlocal = false) override;
1248*0a6a1f1dSLionel Sambuc   void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
1249f4a2713aSLionel Sambuc                           llvm::Value *src, llvm::Value *dest,
1250*0a6a1f1dSLionel Sambuc                           llvm::Value *ivarOffset) override;
1251*0a6a1f1dSLionel Sambuc   void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
1252*0a6a1f1dSLionel Sambuc                                 llvm::Value *src, llvm::Value *dest) override;
1253*0a6a1f1dSLionel Sambuc   void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1254f4a2713aSLionel Sambuc                                 llvm::Value *dest, llvm::Value *src,
1255*0a6a1f1dSLionel Sambuc                                 llvm::Value *size) override;
1256f4a2713aSLionel Sambuc 
1257*0a6a1f1dSLionel Sambuc   LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy,
1258*0a6a1f1dSLionel Sambuc                               llvm::Value *BaseValue, const ObjCIvarDecl *Ivar,
1259*0a6a1f1dSLionel Sambuc                               unsigned CVRQualifiers) override;
1260*0a6a1f1dSLionel Sambuc   llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
1261f4a2713aSLionel Sambuc                               const ObjCInterfaceDecl *Interface,
1262*0a6a1f1dSLionel Sambuc                               const ObjCIvarDecl *Ivar) override;
1263f4a2713aSLionel Sambuc 
1264f4a2713aSLionel Sambuc   /// GetClassGlobal - Return the global variable for the Objective-C
1265f4a2713aSLionel Sambuc   /// class of the given name.
GetClassGlobal(const std::string & Name,bool Weak=false)1266*0a6a1f1dSLionel Sambuc   llvm::GlobalVariable *GetClassGlobal(const std::string &Name,
1267*0a6a1f1dSLionel Sambuc                                        bool Weak = false) override {
1268f4a2713aSLionel Sambuc     llvm_unreachable("CGObjCMac::GetClassGlobal");
1269f4a2713aSLionel Sambuc   }
1270f4a2713aSLionel Sambuc };
1271f4a2713aSLionel Sambuc 
1272f4a2713aSLionel Sambuc class CGObjCNonFragileABIMac : public CGObjCCommonMac {
1273f4a2713aSLionel Sambuc private:
1274f4a2713aSLionel Sambuc   ObjCNonFragileABITypesHelper ObjCTypes;
1275f4a2713aSLionel Sambuc   llvm::GlobalVariable* ObjCEmptyCacheVar;
1276f4a2713aSLionel Sambuc   llvm::GlobalVariable* ObjCEmptyVtableVar;
1277f4a2713aSLionel Sambuc 
1278f4a2713aSLionel Sambuc   /// SuperClassReferences - uniqued super class references.
1279f4a2713aSLionel Sambuc   llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
1280f4a2713aSLionel Sambuc 
1281f4a2713aSLionel Sambuc   /// MetaClassReferences - uniqued meta class references.
1282f4a2713aSLionel Sambuc   llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
1283f4a2713aSLionel Sambuc 
1284f4a2713aSLionel Sambuc   /// EHTypeReferences - uniqued class ehtype references.
1285f4a2713aSLionel Sambuc   llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
1286f4a2713aSLionel Sambuc 
1287f4a2713aSLionel Sambuc   /// VTableDispatchMethods - List of methods for which we generate
1288f4a2713aSLionel Sambuc   /// vtable-based message dispatch.
1289f4a2713aSLionel Sambuc   llvm::DenseSet<Selector> VTableDispatchMethods;
1290f4a2713aSLionel Sambuc 
1291f4a2713aSLionel Sambuc   /// DefinedMetaClasses - List of defined meta-classes.
1292f4a2713aSLionel Sambuc   std::vector<llvm::GlobalValue*> DefinedMetaClasses;
1293f4a2713aSLionel Sambuc 
1294f4a2713aSLionel Sambuc   /// isVTableDispatchedSelector - Returns true if SEL is a
1295f4a2713aSLionel Sambuc   /// vtable-based selector.
1296f4a2713aSLionel Sambuc   bool isVTableDispatchedSelector(Selector Sel);
1297f4a2713aSLionel Sambuc 
1298f4a2713aSLionel Sambuc   /// FinishNonFragileABIModule - Write out global data structures at the end of
1299f4a2713aSLionel Sambuc   /// processing a translation unit.
1300f4a2713aSLionel Sambuc   void FinishNonFragileABIModule();
1301f4a2713aSLionel Sambuc 
1302f4a2713aSLionel Sambuc   /// AddModuleClassList - Add the given list of class pointers to the
1303f4a2713aSLionel Sambuc   /// module with the provided symbol and section names.
1304f4a2713aSLionel Sambuc   void AddModuleClassList(ArrayRef<llvm::GlobalValue*> Container,
1305f4a2713aSLionel Sambuc                           const char *SymbolName,
1306f4a2713aSLionel Sambuc                           const char *SectionName);
1307f4a2713aSLionel Sambuc 
1308f4a2713aSLionel Sambuc   llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
1309f4a2713aSLionel Sambuc                                               unsigned InstanceStart,
1310f4a2713aSLionel Sambuc                                               unsigned InstanceSize,
1311f4a2713aSLionel Sambuc                                               const ObjCImplementationDecl *ID);
1312*0a6a1f1dSLionel Sambuc   llvm::GlobalVariable * BuildClassMetaData(const std::string &ClassName,
1313f4a2713aSLionel Sambuc                                             llvm::Constant *IsAGV,
1314f4a2713aSLionel Sambuc                                             llvm::Constant *SuperClassGV,
1315f4a2713aSLionel Sambuc                                             llvm::Constant *ClassRoGV,
1316*0a6a1f1dSLionel Sambuc                                             bool HiddenVisibility,
1317*0a6a1f1dSLionel Sambuc                                             bool Weak);
1318f4a2713aSLionel Sambuc 
1319f4a2713aSLionel Sambuc   llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
1320f4a2713aSLionel Sambuc 
1321f4a2713aSLionel Sambuc   llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
1322f4a2713aSLionel Sambuc 
1323f4a2713aSLionel Sambuc   /// EmitMethodList - Emit the method list for the given
1324f4a2713aSLionel Sambuc   /// implementation. The return value has type MethodListnfABITy.
1325f4a2713aSLionel Sambuc   llvm::Constant *EmitMethodList(Twine Name,
1326f4a2713aSLionel Sambuc                                  const char *Section,
1327f4a2713aSLionel Sambuc                                  ArrayRef<llvm::Constant*> Methods);
1328f4a2713aSLionel Sambuc   /// EmitIvarList - Emit the ivar list for the given
1329f4a2713aSLionel Sambuc   /// implementation. If ForClass is true the list of class ivars
1330f4a2713aSLionel Sambuc   /// (i.e. metaclass ivars) is emitted, otherwise the list of
1331f4a2713aSLionel Sambuc   /// interface ivars will be emitted. The return value has type
1332f4a2713aSLionel Sambuc   /// IvarListnfABIPtrTy.
1333f4a2713aSLionel Sambuc   llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID);
1334f4a2713aSLionel Sambuc 
1335f4a2713aSLionel Sambuc   llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
1336f4a2713aSLionel Sambuc                                     const ObjCIvarDecl *Ivar,
1337f4a2713aSLionel Sambuc                                     unsigned long int offset);
1338f4a2713aSLionel Sambuc 
1339f4a2713aSLionel Sambuc   /// GetOrEmitProtocol - Get the protocol object for the given
1340f4a2713aSLionel Sambuc   /// declaration, emitting it if necessary. The return value has type
1341f4a2713aSLionel Sambuc   /// ProtocolPtrTy.
1342*0a6a1f1dSLionel Sambuc   llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD) override;
1343f4a2713aSLionel Sambuc 
1344f4a2713aSLionel Sambuc   /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1345f4a2713aSLionel Sambuc   /// object for the given declaration, emitting it if needed. These
1346f4a2713aSLionel Sambuc   /// forward references will be filled in with empty bodies if no
1347f4a2713aSLionel Sambuc   /// definition is seen. The return value has type ProtocolPtrTy.
1348*0a6a1f1dSLionel Sambuc   llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) override;
1349f4a2713aSLionel Sambuc 
1350f4a2713aSLionel Sambuc   /// EmitProtocolList - Generate the list of referenced
1351f4a2713aSLionel Sambuc   /// protocols. The return value has type ProtocolListPtrTy.
1352f4a2713aSLionel Sambuc   llvm::Constant *EmitProtocolList(Twine Name,
1353f4a2713aSLionel Sambuc                                    ObjCProtocolDecl::protocol_iterator begin,
1354f4a2713aSLionel Sambuc                                    ObjCProtocolDecl::protocol_iterator end);
1355f4a2713aSLionel Sambuc 
1356f4a2713aSLionel Sambuc   CodeGen::RValue EmitVTableMessageSend(CodeGen::CodeGenFunction &CGF,
1357f4a2713aSLionel Sambuc                                         ReturnValueSlot Return,
1358f4a2713aSLionel Sambuc                                         QualType ResultType,
1359f4a2713aSLionel Sambuc                                         Selector Sel,
1360f4a2713aSLionel Sambuc                                         llvm::Value *Receiver,
1361f4a2713aSLionel Sambuc                                         QualType Arg0Ty,
1362f4a2713aSLionel Sambuc                                         bool IsSuper,
1363f4a2713aSLionel Sambuc                                         const CallArgList &CallArgs,
1364f4a2713aSLionel Sambuc                                         const ObjCMethodDecl *Method);
1365f4a2713aSLionel Sambuc 
1366f4a2713aSLionel Sambuc   /// GetClassGlobal - Return the global variable for the Objective-C
1367f4a2713aSLionel Sambuc   /// class of the given name.
1368*0a6a1f1dSLionel Sambuc   llvm::GlobalVariable *GetClassGlobal(const std::string &Name,
1369*0a6a1f1dSLionel Sambuc                                        bool Weak = false) override;
1370f4a2713aSLionel Sambuc 
1371f4a2713aSLionel Sambuc   /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1372f4a2713aSLionel Sambuc   /// for the given class reference.
1373f4a2713aSLionel Sambuc   llvm::Value *EmitClassRef(CodeGenFunction &CGF,
1374f4a2713aSLionel Sambuc                             const ObjCInterfaceDecl *ID);
1375f4a2713aSLionel Sambuc 
1376f4a2713aSLionel Sambuc   llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF,
1377*0a6a1f1dSLionel Sambuc                                   IdentifierInfo *II, bool Weak,
1378*0a6a1f1dSLionel Sambuc                                   const ObjCInterfaceDecl *ID);
1379f4a2713aSLionel Sambuc 
1380*0a6a1f1dSLionel Sambuc   llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) override;
1381f4a2713aSLionel Sambuc 
1382f4a2713aSLionel Sambuc   /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1383f4a2713aSLionel Sambuc   /// for the given super class reference.
1384f4a2713aSLionel Sambuc   llvm::Value *EmitSuperClassRef(CodeGenFunction &CGF,
1385f4a2713aSLionel Sambuc                                  const ObjCInterfaceDecl *ID);
1386f4a2713aSLionel Sambuc 
1387f4a2713aSLionel Sambuc   /// EmitMetaClassRef - Return a Value * of the address of _class_t
1388f4a2713aSLionel Sambuc   /// meta-data
1389f4a2713aSLionel Sambuc   llvm::Value *EmitMetaClassRef(CodeGenFunction &CGF,
1390*0a6a1f1dSLionel Sambuc                                 const ObjCInterfaceDecl *ID, bool Weak);
1391f4a2713aSLionel Sambuc 
1392f4a2713aSLionel Sambuc   /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
1393f4a2713aSLionel Sambuc   /// the given ivar.
1394f4a2713aSLionel Sambuc   ///
1395f4a2713aSLionel Sambuc   llvm::GlobalVariable * ObjCIvarOffsetVariable(
1396f4a2713aSLionel Sambuc     const ObjCInterfaceDecl *ID,
1397f4a2713aSLionel Sambuc     const ObjCIvarDecl *Ivar);
1398f4a2713aSLionel Sambuc 
1399f4a2713aSLionel Sambuc   /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1400f4a2713aSLionel Sambuc   /// for the given selector.
1401f4a2713aSLionel Sambuc   llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel,
1402f4a2713aSLionel Sambuc                             bool lval=false);
1403f4a2713aSLionel Sambuc 
1404f4a2713aSLionel Sambuc   /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
1405f4a2713aSLionel Sambuc   /// interface. The return value has type EHTypePtrTy.
1406f4a2713aSLionel Sambuc   llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
1407f4a2713aSLionel Sambuc                                   bool ForDefinition);
1408f4a2713aSLionel Sambuc 
getMetaclassSymbolPrefix() const1409f4a2713aSLionel Sambuc   const char *getMetaclassSymbolPrefix() const {
1410f4a2713aSLionel Sambuc     return "OBJC_METACLASS_$_";
1411f4a2713aSLionel Sambuc   }
1412f4a2713aSLionel Sambuc 
getClassSymbolPrefix() const1413f4a2713aSLionel Sambuc   const char *getClassSymbolPrefix() const {
1414f4a2713aSLionel Sambuc     return "OBJC_CLASS_$_";
1415f4a2713aSLionel Sambuc   }
1416f4a2713aSLionel Sambuc 
1417f4a2713aSLionel Sambuc   void GetClassSizeInfo(const ObjCImplementationDecl *OID,
1418f4a2713aSLionel Sambuc                         uint32_t &InstanceStart,
1419f4a2713aSLionel Sambuc                         uint32_t &InstanceSize);
1420f4a2713aSLionel Sambuc 
1421f4a2713aSLionel Sambuc   // Shamelessly stolen from Analysis/CFRefCount.cpp
GetNullarySelector(const char * name) const1422f4a2713aSLionel Sambuc   Selector GetNullarySelector(const char* name) const {
1423f4a2713aSLionel Sambuc     IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1424f4a2713aSLionel Sambuc     return CGM.getContext().Selectors.getSelector(0, &II);
1425f4a2713aSLionel Sambuc   }
1426f4a2713aSLionel Sambuc 
GetUnarySelector(const char * name) const1427f4a2713aSLionel Sambuc   Selector GetUnarySelector(const char* name) const {
1428f4a2713aSLionel Sambuc     IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1429f4a2713aSLionel Sambuc     return CGM.getContext().Selectors.getSelector(1, &II);
1430f4a2713aSLionel Sambuc   }
1431f4a2713aSLionel Sambuc 
1432f4a2713aSLionel Sambuc   /// ImplementationIsNonLazy - Check whether the given category or
1433f4a2713aSLionel Sambuc   /// class implementation is "non-lazy".
1434f4a2713aSLionel Sambuc   bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const;
1435f4a2713aSLionel Sambuc 
IsIvarOffsetKnownIdempotent(const CodeGen::CodeGenFunction & CGF,const ObjCIvarDecl * IV)1436f4a2713aSLionel Sambuc   bool IsIvarOffsetKnownIdempotent(const CodeGen::CodeGenFunction &CGF,
1437f4a2713aSLionel Sambuc                                    const ObjCIvarDecl *IV) {
1438*0a6a1f1dSLionel Sambuc     // Annotate the load as an invariant load iff inside an instance method
1439*0a6a1f1dSLionel Sambuc     // and ivar belongs to instance method's class and one of its super class.
1440*0a6a1f1dSLionel Sambuc     // This check is needed because the ivar offset is a lazily
1441f4a2713aSLionel Sambuc     // initialised value that may depend on objc_msgSend to perform a fixup on
1442f4a2713aSLionel Sambuc     // the first message dispatch.
1443f4a2713aSLionel Sambuc     //
1444f4a2713aSLionel Sambuc     // An additional opportunity to mark the load as invariant arises when the
1445f4a2713aSLionel Sambuc     // base of the ivar access is a parameter to an Objective C method.
1446f4a2713aSLionel Sambuc     // However, because the parameters are not available in the current
1447f4a2713aSLionel Sambuc     // interface, we cannot perform this check.
1448*0a6a1f1dSLionel Sambuc     if (const ObjCMethodDecl *MD =
1449*0a6a1f1dSLionel Sambuc           dyn_cast_or_null<ObjCMethodDecl>(CGF.CurFuncDecl))
1450*0a6a1f1dSLionel Sambuc       if (MD->isInstanceMethod())
1451*0a6a1f1dSLionel Sambuc         if (const ObjCInterfaceDecl *ID = MD->getClassInterface())
1452*0a6a1f1dSLionel Sambuc           return IV->getContainingInterface()->isSuperClassOf(ID);
1453f4a2713aSLionel Sambuc     return false;
1454f4a2713aSLionel Sambuc   }
1455f4a2713aSLionel Sambuc 
1456f4a2713aSLionel Sambuc public:
1457f4a2713aSLionel Sambuc   CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
1458f4a2713aSLionel Sambuc   // FIXME. All stubs for now!
1459*0a6a1f1dSLionel Sambuc   llvm::Function *ModuleInitFunction() override;
1460f4a2713aSLionel Sambuc 
1461*0a6a1f1dSLionel Sambuc   CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1462f4a2713aSLionel Sambuc                                       ReturnValueSlot Return,
1463*0a6a1f1dSLionel Sambuc                                       QualType ResultType, Selector Sel,
1464f4a2713aSLionel Sambuc                                       llvm::Value *Receiver,
1465f4a2713aSLionel Sambuc                                       const CallArgList &CallArgs,
1466f4a2713aSLionel Sambuc                                       const ObjCInterfaceDecl *Class,
1467*0a6a1f1dSLionel Sambuc                                       const ObjCMethodDecl *Method) override;
1468f4a2713aSLionel Sambuc 
1469*0a6a1f1dSLionel Sambuc   CodeGen::RValue
1470f4a2713aSLionel Sambuc   GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
1471*0a6a1f1dSLionel Sambuc                            ReturnValueSlot Return, QualType ResultType,
1472*0a6a1f1dSLionel Sambuc                            Selector Sel, const ObjCInterfaceDecl *Class,
1473*0a6a1f1dSLionel Sambuc                            bool isCategoryImpl, llvm::Value *Receiver,
1474*0a6a1f1dSLionel Sambuc                            bool IsClassMessage, const CallArgList &CallArgs,
1475*0a6a1f1dSLionel Sambuc                            const ObjCMethodDecl *Method) override;
1476f4a2713aSLionel Sambuc 
1477*0a6a1f1dSLionel Sambuc   llvm::Value *GetClass(CodeGenFunction &CGF,
1478*0a6a1f1dSLionel Sambuc                         const ObjCInterfaceDecl *ID) override;
1479f4a2713aSLionel Sambuc 
GetSelector(CodeGenFunction & CGF,Selector Sel,bool lvalue=false)1480*0a6a1f1dSLionel Sambuc   llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel,
1481*0a6a1f1dSLionel Sambuc                            bool lvalue = false) override
1482f4a2713aSLionel Sambuc     { return EmitSelector(CGF, Sel, lvalue); }
1483f4a2713aSLionel Sambuc 
1484f4a2713aSLionel Sambuc   /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1485f4a2713aSLionel Sambuc   /// untyped one.
GetSelector(CodeGenFunction & CGF,const ObjCMethodDecl * Method)1486*0a6a1f1dSLionel Sambuc   llvm::Value *GetSelector(CodeGenFunction &CGF,
1487*0a6a1f1dSLionel Sambuc                            const ObjCMethodDecl *Method) override
1488f4a2713aSLionel Sambuc     { return EmitSelector(CGF, Method->getSelector()); }
1489f4a2713aSLionel Sambuc 
1490*0a6a1f1dSLionel Sambuc   void GenerateCategory(const ObjCCategoryImplDecl *CMD) override;
1491f4a2713aSLionel Sambuc 
1492*0a6a1f1dSLionel Sambuc   void GenerateClass(const ObjCImplementationDecl *ClassDecl) override;
1493f4a2713aSLionel Sambuc 
RegisterAlias(const ObjCCompatibleAliasDecl * OAD)1494*0a6a1f1dSLionel Sambuc   void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) override {}
1495f4a2713aSLionel Sambuc 
1496*0a6a1f1dSLionel Sambuc   llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
1497*0a6a1f1dSLionel Sambuc                                    const ObjCProtocolDecl *PD) override;
1498f4a2713aSLionel Sambuc 
1499*0a6a1f1dSLionel Sambuc   llvm::Constant *GetEHType(QualType T) override;
1500f4a2713aSLionel Sambuc 
GetPropertyGetFunction()1501*0a6a1f1dSLionel Sambuc   llvm::Constant *GetPropertyGetFunction() override {
1502f4a2713aSLionel Sambuc     return ObjCTypes.getGetPropertyFn();
1503f4a2713aSLionel Sambuc   }
GetPropertySetFunction()1504*0a6a1f1dSLionel Sambuc   llvm::Constant *GetPropertySetFunction() override {
1505f4a2713aSLionel Sambuc     return ObjCTypes.getSetPropertyFn();
1506f4a2713aSLionel Sambuc   }
1507f4a2713aSLionel Sambuc 
GetOptimizedPropertySetFunction(bool atomic,bool copy)1508*0a6a1f1dSLionel Sambuc   llvm::Constant *GetOptimizedPropertySetFunction(bool atomic,
1509*0a6a1f1dSLionel Sambuc                                                   bool copy) override {
1510f4a2713aSLionel Sambuc     return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
1511f4a2713aSLionel Sambuc   }
1512f4a2713aSLionel Sambuc 
GetSetStructFunction()1513*0a6a1f1dSLionel Sambuc   llvm::Constant *GetSetStructFunction() override {
1514f4a2713aSLionel Sambuc     return ObjCTypes.getCopyStructFn();
1515f4a2713aSLionel Sambuc   }
GetGetStructFunction()1516*0a6a1f1dSLionel Sambuc   llvm::Constant *GetGetStructFunction() override {
1517f4a2713aSLionel Sambuc     return ObjCTypes.getCopyStructFn();
1518f4a2713aSLionel Sambuc   }
GetCppAtomicObjectSetFunction()1519*0a6a1f1dSLionel Sambuc   llvm::Constant *GetCppAtomicObjectSetFunction() override {
1520f4a2713aSLionel Sambuc     return ObjCTypes.getCppAtomicObjectFunction();
1521f4a2713aSLionel Sambuc   }
GetCppAtomicObjectGetFunction()1522*0a6a1f1dSLionel Sambuc   llvm::Constant *GetCppAtomicObjectGetFunction() override {
1523f4a2713aSLionel Sambuc     return ObjCTypes.getCppAtomicObjectFunction();
1524f4a2713aSLionel Sambuc   }
1525f4a2713aSLionel Sambuc 
EnumerationMutationFunction()1526*0a6a1f1dSLionel Sambuc   llvm::Constant *EnumerationMutationFunction() override {
1527f4a2713aSLionel Sambuc     return ObjCTypes.getEnumerationMutationFn();
1528f4a2713aSLionel Sambuc   }
1529f4a2713aSLionel Sambuc 
1530*0a6a1f1dSLionel Sambuc   void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1531*0a6a1f1dSLionel Sambuc                    const ObjCAtTryStmt &S) override;
1532*0a6a1f1dSLionel Sambuc   void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1533*0a6a1f1dSLionel Sambuc                             const ObjCAtSynchronizedStmt &S) override;
1534*0a6a1f1dSLionel Sambuc   void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S,
1535*0a6a1f1dSLionel Sambuc                      bool ClearInsertionPoint=true) override;
1536*0a6a1f1dSLionel Sambuc   llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
1537*0a6a1f1dSLionel Sambuc                                  llvm::Value *AddrWeakObj) override;
1538*0a6a1f1dSLionel Sambuc   void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
1539*0a6a1f1dSLionel Sambuc                           llvm::Value *src, llvm::Value *dst) override;
1540*0a6a1f1dSLionel Sambuc   void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
1541f4a2713aSLionel Sambuc                             llvm::Value *src, llvm::Value *dest,
1542*0a6a1f1dSLionel Sambuc                             bool threadlocal = false) override;
1543*0a6a1f1dSLionel Sambuc   void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
1544f4a2713aSLionel Sambuc                           llvm::Value *src, llvm::Value *dest,
1545*0a6a1f1dSLionel Sambuc                           llvm::Value *ivarOffset) override;
1546*0a6a1f1dSLionel Sambuc   void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
1547*0a6a1f1dSLionel Sambuc                                 llvm::Value *src, llvm::Value *dest) override;
1548*0a6a1f1dSLionel Sambuc   void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1549f4a2713aSLionel Sambuc                                 llvm::Value *dest, llvm::Value *src,
1550*0a6a1f1dSLionel Sambuc                                 llvm::Value *size) override;
1551*0a6a1f1dSLionel Sambuc   LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy,
1552*0a6a1f1dSLionel Sambuc                               llvm::Value *BaseValue, const ObjCIvarDecl *Ivar,
1553*0a6a1f1dSLionel Sambuc                               unsigned CVRQualifiers) override;
1554*0a6a1f1dSLionel Sambuc   llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
1555f4a2713aSLionel Sambuc                               const ObjCInterfaceDecl *Interface,
1556*0a6a1f1dSLionel Sambuc                               const ObjCIvarDecl *Ivar) override;
1557f4a2713aSLionel Sambuc };
1558f4a2713aSLionel Sambuc 
1559f4a2713aSLionel Sambuc /// A helper class for performing the null-initialization of a return
1560f4a2713aSLionel Sambuc /// value.
1561f4a2713aSLionel Sambuc struct NullReturnState {
1562f4a2713aSLionel Sambuc   llvm::BasicBlock *NullBB;
NullReturnState__anon9749cc0a0111::NullReturnState1563*0a6a1f1dSLionel Sambuc   NullReturnState() : NullBB(nullptr) {}
1564f4a2713aSLionel Sambuc 
1565f4a2713aSLionel Sambuc   /// Perform a null-check of the given receiver.
init__anon9749cc0a0111::NullReturnState1566f4a2713aSLionel Sambuc   void init(CodeGenFunction &CGF, llvm::Value *receiver) {
1567f4a2713aSLionel Sambuc     // Make blocks for the null-receiver and call edges.
1568f4a2713aSLionel Sambuc     NullBB = CGF.createBasicBlock("msgSend.null-receiver");
1569f4a2713aSLionel Sambuc     llvm::BasicBlock *callBB = CGF.createBasicBlock("msgSend.call");
1570f4a2713aSLionel Sambuc 
1571f4a2713aSLionel Sambuc     // Check for a null receiver and, if there is one, jump to the
1572f4a2713aSLionel Sambuc     // null-receiver block.  There's no point in trying to avoid it:
1573f4a2713aSLionel Sambuc     // we're always going to put *something* there, because otherwise
1574f4a2713aSLionel Sambuc     // we shouldn't have done this null-check in the first place.
1575f4a2713aSLionel Sambuc     llvm::Value *isNull = CGF.Builder.CreateIsNull(receiver);
1576f4a2713aSLionel Sambuc     CGF.Builder.CreateCondBr(isNull, NullBB, callBB);
1577f4a2713aSLionel Sambuc 
1578f4a2713aSLionel Sambuc     // Otherwise, start performing the call.
1579f4a2713aSLionel Sambuc     CGF.EmitBlock(callBB);
1580f4a2713aSLionel Sambuc   }
1581f4a2713aSLionel Sambuc 
1582f4a2713aSLionel Sambuc   /// Complete the null-return operation.  It is valid to call this
1583f4a2713aSLionel Sambuc   /// regardless of whether 'init' has been called.
complete__anon9749cc0a0111::NullReturnState1584f4a2713aSLionel Sambuc   RValue complete(CodeGenFunction &CGF, RValue result, QualType resultType,
1585f4a2713aSLionel Sambuc                   const CallArgList &CallArgs,
1586f4a2713aSLionel Sambuc                   const ObjCMethodDecl *Method) {
1587f4a2713aSLionel Sambuc     // If we never had to do a null-check, just use the raw result.
1588f4a2713aSLionel Sambuc     if (!NullBB) return result;
1589f4a2713aSLionel Sambuc 
1590f4a2713aSLionel Sambuc     // The continuation block.  This will be left null if we don't have an
1591f4a2713aSLionel Sambuc     // IP, which can happen if the method we're calling is marked noreturn.
1592*0a6a1f1dSLionel Sambuc     llvm::BasicBlock *contBB = nullptr;
1593f4a2713aSLionel Sambuc 
1594f4a2713aSLionel Sambuc     // Finish the call path.
1595f4a2713aSLionel Sambuc     llvm::BasicBlock *callBB = CGF.Builder.GetInsertBlock();
1596f4a2713aSLionel Sambuc     if (callBB) {
1597f4a2713aSLionel Sambuc       contBB = CGF.createBasicBlock("msgSend.cont");
1598f4a2713aSLionel Sambuc       CGF.Builder.CreateBr(contBB);
1599f4a2713aSLionel Sambuc     }
1600f4a2713aSLionel Sambuc 
1601f4a2713aSLionel Sambuc     // Okay, start emitting the null-receiver block.
1602f4a2713aSLionel Sambuc     CGF.EmitBlock(NullBB);
1603f4a2713aSLionel Sambuc 
1604f4a2713aSLionel Sambuc     // Release any consumed arguments we've got.
1605f4a2713aSLionel Sambuc     if (Method) {
1606f4a2713aSLionel Sambuc       CallArgList::const_iterator I = CallArgs.begin();
1607f4a2713aSLionel Sambuc       for (ObjCMethodDecl::param_const_iterator i = Method->param_begin(),
1608f4a2713aSLionel Sambuc            e = Method->param_end(); i != e; ++i, ++I) {
1609f4a2713aSLionel Sambuc         const ParmVarDecl *ParamDecl = (*i);
1610f4a2713aSLionel Sambuc         if (ParamDecl->hasAttr<NSConsumedAttr>()) {
1611f4a2713aSLionel Sambuc           RValue RV = I->RV;
1612f4a2713aSLionel Sambuc           assert(RV.isScalar() &&
1613f4a2713aSLionel Sambuc                  "NullReturnState::complete - arg not on object");
1614f4a2713aSLionel Sambuc           CGF.EmitARCRelease(RV.getScalarVal(), ARCImpreciseLifetime);
1615f4a2713aSLionel Sambuc         }
1616f4a2713aSLionel Sambuc       }
1617f4a2713aSLionel Sambuc     }
1618f4a2713aSLionel Sambuc 
1619f4a2713aSLionel Sambuc     // The phi code below assumes that we haven't needed any control flow yet.
1620f4a2713aSLionel Sambuc     assert(CGF.Builder.GetInsertBlock() == NullBB);
1621f4a2713aSLionel Sambuc 
1622f4a2713aSLionel Sambuc     // If we've got a void return, just jump to the continuation block.
1623f4a2713aSLionel Sambuc     if (result.isScalar() && resultType->isVoidType()) {
1624f4a2713aSLionel Sambuc       // No jumps required if the message-send was noreturn.
1625f4a2713aSLionel Sambuc       if (contBB) CGF.EmitBlock(contBB);
1626f4a2713aSLionel Sambuc       return result;
1627f4a2713aSLionel Sambuc     }
1628f4a2713aSLionel Sambuc 
1629f4a2713aSLionel Sambuc     // If we've got a scalar return, build a phi.
1630f4a2713aSLionel Sambuc     if (result.isScalar()) {
1631f4a2713aSLionel Sambuc       // Derive the null-initialization value.
1632f4a2713aSLionel Sambuc       llvm::Constant *null = CGF.CGM.EmitNullConstant(resultType);
1633f4a2713aSLionel Sambuc 
1634f4a2713aSLionel Sambuc       // If no join is necessary, just flow out.
1635f4a2713aSLionel Sambuc       if (!contBB) return RValue::get(null);
1636f4a2713aSLionel Sambuc 
1637f4a2713aSLionel Sambuc       // Otherwise, build a phi.
1638f4a2713aSLionel Sambuc       CGF.EmitBlock(contBB);
1639f4a2713aSLionel Sambuc       llvm::PHINode *phi = CGF.Builder.CreatePHI(null->getType(), 2);
1640f4a2713aSLionel Sambuc       phi->addIncoming(result.getScalarVal(), callBB);
1641f4a2713aSLionel Sambuc       phi->addIncoming(null, NullBB);
1642f4a2713aSLionel Sambuc       return RValue::get(phi);
1643f4a2713aSLionel Sambuc     }
1644f4a2713aSLionel Sambuc 
1645f4a2713aSLionel Sambuc     // If we've got an aggregate return, null the buffer out.
1646f4a2713aSLionel Sambuc     // FIXME: maybe we should be doing things differently for all the
1647f4a2713aSLionel Sambuc     // cases where the ABI has us returning (1) non-agg values in
1648f4a2713aSLionel Sambuc     // memory or (2) agg values in registers.
1649f4a2713aSLionel Sambuc     if (result.isAggregate()) {
1650f4a2713aSLionel Sambuc       assert(result.isAggregate() && "null init of non-aggregate result?");
1651f4a2713aSLionel Sambuc       CGF.EmitNullInitialization(result.getAggregateAddr(), resultType);
1652f4a2713aSLionel Sambuc       if (contBB) CGF.EmitBlock(contBB);
1653f4a2713aSLionel Sambuc       return result;
1654f4a2713aSLionel Sambuc     }
1655f4a2713aSLionel Sambuc 
1656f4a2713aSLionel Sambuc     // Complex types.
1657f4a2713aSLionel Sambuc     CGF.EmitBlock(contBB);
1658f4a2713aSLionel Sambuc     CodeGenFunction::ComplexPairTy callResult = result.getComplexVal();
1659f4a2713aSLionel Sambuc 
1660f4a2713aSLionel Sambuc     // Find the scalar type and its zero value.
1661f4a2713aSLionel Sambuc     llvm::Type *scalarTy = callResult.first->getType();
1662f4a2713aSLionel Sambuc     llvm::Constant *scalarZero = llvm::Constant::getNullValue(scalarTy);
1663f4a2713aSLionel Sambuc 
1664f4a2713aSLionel Sambuc     // Build phis for both coordinates.
1665f4a2713aSLionel Sambuc     llvm::PHINode *real = CGF.Builder.CreatePHI(scalarTy, 2);
1666f4a2713aSLionel Sambuc     real->addIncoming(callResult.first, callBB);
1667f4a2713aSLionel Sambuc     real->addIncoming(scalarZero, NullBB);
1668f4a2713aSLionel Sambuc     llvm::PHINode *imag = CGF.Builder.CreatePHI(scalarTy, 2);
1669f4a2713aSLionel Sambuc     imag->addIncoming(callResult.second, callBB);
1670f4a2713aSLionel Sambuc     imag->addIncoming(scalarZero, NullBB);
1671f4a2713aSLionel Sambuc     return RValue::getComplex(real, imag);
1672f4a2713aSLionel Sambuc   }
1673f4a2713aSLionel Sambuc };
1674f4a2713aSLionel Sambuc 
1675f4a2713aSLionel Sambuc } // end anonymous namespace
1676f4a2713aSLionel Sambuc 
1677f4a2713aSLionel Sambuc /* *** Helper Functions *** */
1678f4a2713aSLionel Sambuc 
1679f4a2713aSLionel Sambuc /// getConstantGEP() - Help routine to construct simple GEPs.
getConstantGEP(llvm::LLVMContext & VMContext,llvm::Constant * C,unsigned idx0,unsigned idx1)1680f4a2713aSLionel Sambuc static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
1681f4a2713aSLionel Sambuc                                       llvm::Constant *C,
1682f4a2713aSLionel Sambuc                                       unsigned idx0,
1683f4a2713aSLionel Sambuc                                       unsigned idx1) {
1684f4a2713aSLionel Sambuc   llvm::Value *Idxs[] = {
1685f4a2713aSLionel Sambuc     llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1686f4a2713aSLionel Sambuc     llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
1687f4a2713aSLionel Sambuc   };
1688f4a2713aSLionel Sambuc   return llvm::ConstantExpr::getGetElementPtr(C, Idxs);
1689f4a2713aSLionel Sambuc }
1690f4a2713aSLionel Sambuc 
1691f4a2713aSLionel Sambuc /// hasObjCExceptionAttribute - Return true if this class or any super
1692f4a2713aSLionel Sambuc /// class has the __objc_exception__ attribute.
hasObjCExceptionAttribute(ASTContext & Context,const ObjCInterfaceDecl * OID)1693f4a2713aSLionel Sambuc static bool hasObjCExceptionAttribute(ASTContext &Context,
1694f4a2713aSLionel Sambuc                                       const ObjCInterfaceDecl *OID) {
1695f4a2713aSLionel Sambuc   if (OID->hasAttr<ObjCExceptionAttr>())
1696f4a2713aSLionel Sambuc     return true;
1697f4a2713aSLionel Sambuc   if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
1698f4a2713aSLionel Sambuc     return hasObjCExceptionAttribute(Context, Super);
1699f4a2713aSLionel Sambuc   return false;
1700f4a2713aSLionel Sambuc }
1701f4a2713aSLionel Sambuc 
1702f4a2713aSLionel Sambuc /* *** CGObjCMac Public Interface *** */
1703f4a2713aSLionel Sambuc 
CGObjCMac(CodeGen::CodeGenModule & cgm)1704f4a2713aSLionel Sambuc CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
1705f4a2713aSLionel Sambuc                                                     ObjCTypes(cgm) {
1706f4a2713aSLionel Sambuc   ObjCABI = 1;
1707f4a2713aSLionel Sambuc   EmitImageInfo();
1708f4a2713aSLionel Sambuc }
1709f4a2713aSLionel Sambuc 
1710f4a2713aSLionel Sambuc /// GetClass - Return a reference to the class for the given interface
1711f4a2713aSLionel Sambuc /// decl.
GetClass(CodeGenFunction & CGF,const ObjCInterfaceDecl * ID)1712f4a2713aSLionel Sambuc llvm::Value *CGObjCMac::GetClass(CodeGenFunction &CGF,
1713f4a2713aSLionel Sambuc                                  const ObjCInterfaceDecl *ID) {
1714f4a2713aSLionel Sambuc   return EmitClassRef(CGF, ID);
1715f4a2713aSLionel Sambuc }
1716f4a2713aSLionel Sambuc 
1717f4a2713aSLionel Sambuc /// GetSelector - Return the pointer to the unique'd string for this selector.
GetSelector(CodeGenFunction & CGF,Selector Sel,bool lval)1718f4a2713aSLionel Sambuc llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, Selector Sel,
1719f4a2713aSLionel Sambuc                                     bool lval) {
1720f4a2713aSLionel Sambuc   return EmitSelector(CGF, Sel, lval);
1721f4a2713aSLionel Sambuc }
GetSelector(CodeGenFunction & CGF,const ObjCMethodDecl * Method)1722f4a2713aSLionel Sambuc llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, const ObjCMethodDecl
1723f4a2713aSLionel Sambuc                                     *Method) {
1724f4a2713aSLionel Sambuc   return EmitSelector(CGF, Method->getSelector());
1725f4a2713aSLionel Sambuc }
1726f4a2713aSLionel Sambuc 
GetEHType(QualType T)1727f4a2713aSLionel Sambuc llvm::Constant *CGObjCMac::GetEHType(QualType T) {
1728f4a2713aSLionel Sambuc   if (T->isObjCIdType() ||
1729f4a2713aSLionel Sambuc       T->isObjCQualifiedIdType()) {
1730f4a2713aSLionel Sambuc     return CGM.GetAddrOfRTTIDescriptor(
1731f4a2713aSLionel Sambuc               CGM.getContext().getObjCIdRedefinitionType(), /*ForEH=*/true);
1732f4a2713aSLionel Sambuc   }
1733f4a2713aSLionel Sambuc   if (T->isObjCClassType() ||
1734f4a2713aSLionel Sambuc       T->isObjCQualifiedClassType()) {
1735f4a2713aSLionel Sambuc     return CGM.GetAddrOfRTTIDescriptor(
1736f4a2713aSLionel Sambuc              CGM.getContext().getObjCClassRedefinitionType(), /*ForEH=*/true);
1737f4a2713aSLionel Sambuc   }
1738f4a2713aSLionel Sambuc   if (T->isObjCObjectPointerType())
1739f4a2713aSLionel Sambuc     return CGM.GetAddrOfRTTIDescriptor(T,  /*ForEH=*/true);
1740f4a2713aSLionel Sambuc 
1741f4a2713aSLionel Sambuc   llvm_unreachable("asking for catch type for ObjC type in fragile runtime");
1742f4a2713aSLionel Sambuc }
1743f4a2713aSLionel Sambuc 
1744f4a2713aSLionel Sambuc /// Generate a constant CFString object.
1745f4a2713aSLionel Sambuc /*
1746f4a2713aSLionel Sambuc   struct __builtin_CFString {
1747f4a2713aSLionel Sambuc   const int *isa; // point to __CFConstantStringClassReference
1748f4a2713aSLionel Sambuc   int flags;
1749f4a2713aSLionel Sambuc   const char *str;
1750f4a2713aSLionel Sambuc   long length;
1751f4a2713aSLionel Sambuc   };
1752f4a2713aSLionel Sambuc */
1753f4a2713aSLionel Sambuc 
1754f4a2713aSLionel Sambuc /// or Generate a constant NSString object.
1755f4a2713aSLionel Sambuc /*
1756f4a2713aSLionel Sambuc    struct __builtin_NSString {
1757f4a2713aSLionel Sambuc      const int *isa; // point to __NSConstantStringClassReference
1758f4a2713aSLionel Sambuc      const char *str;
1759f4a2713aSLionel Sambuc      unsigned int length;
1760f4a2713aSLionel Sambuc    };
1761f4a2713aSLionel Sambuc */
1762f4a2713aSLionel Sambuc 
GenerateConstantString(const StringLiteral * SL)1763f4a2713aSLionel Sambuc llvm::Constant *CGObjCCommonMac::GenerateConstantString(
1764f4a2713aSLionel Sambuc   const StringLiteral *SL) {
1765f4a2713aSLionel Sambuc   return (CGM.getLangOpts().NoConstantCFStrings == 0 ?
1766f4a2713aSLionel Sambuc           CGM.GetAddrOfConstantCFString(SL) :
1767f4a2713aSLionel Sambuc           CGM.GetAddrOfConstantString(SL));
1768f4a2713aSLionel Sambuc }
1769f4a2713aSLionel Sambuc 
1770f4a2713aSLionel Sambuc enum {
1771f4a2713aSLionel Sambuc   kCFTaggedObjectID_Integer = (1 << 1) + 1
1772f4a2713aSLionel Sambuc };
1773f4a2713aSLionel Sambuc 
1774f4a2713aSLionel Sambuc /// Generates a message send where the super is the receiver.  This is
1775f4a2713aSLionel Sambuc /// a message send to self with special delivery semantics indicating
1776f4a2713aSLionel Sambuc /// which class's method should be called.
1777f4a2713aSLionel Sambuc CodeGen::RValue
GenerateMessageSendSuper(CodeGen::CodeGenFunction & CGF,ReturnValueSlot Return,QualType ResultType,Selector Sel,const ObjCInterfaceDecl * Class,bool isCategoryImpl,llvm::Value * Receiver,bool IsClassMessage,const CodeGen::CallArgList & CallArgs,const ObjCMethodDecl * Method)1778f4a2713aSLionel Sambuc CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
1779f4a2713aSLionel Sambuc                                     ReturnValueSlot Return,
1780f4a2713aSLionel Sambuc                                     QualType ResultType,
1781f4a2713aSLionel Sambuc                                     Selector Sel,
1782f4a2713aSLionel Sambuc                                     const ObjCInterfaceDecl *Class,
1783f4a2713aSLionel Sambuc                                     bool isCategoryImpl,
1784f4a2713aSLionel Sambuc                                     llvm::Value *Receiver,
1785f4a2713aSLionel Sambuc                                     bool IsClassMessage,
1786f4a2713aSLionel Sambuc                                     const CodeGen::CallArgList &CallArgs,
1787f4a2713aSLionel Sambuc                                     const ObjCMethodDecl *Method) {
1788f4a2713aSLionel Sambuc   // Create and init a super structure; this is a (receiver, class)
1789f4a2713aSLionel Sambuc   // pair we will pass to objc_msgSendSuper.
1790f4a2713aSLionel Sambuc   llvm::Value *ObjCSuper =
1791f4a2713aSLionel Sambuc     CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
1792f4a2713aSLionel Sambuc   llvm::Value *ReceiverAsObject =
1793f4a2713aSLionel Sambuc     CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
1794f4a2713aSLionel Sambuc   CGF.Builder.CreateStore(ReceiverAsObject,
1795f4a2713aSLionel Sambuc                           CGF.Builder.CreateStructGEP(ObjCSuper, 0));
1796f4a2713aSLionel Sambuc 
1797f4a2713aSLionel Sambuc   // If this is a class message the metaclass is passed as the target.
1798f4a2713aSLionel Sambuc   llvm::Value *Target;
1799f4a2713aSLionel Sambuc   if (IsClassMessage) {
1800f4a2713aSLionel Sambuc     if (isCategoryImpl) {
1801f4a2713aSLionel Sambuc       // Message sent to 'super' in a class method defined in a category
1802f4a2713aSLionel Sambuc       // implementation requires an odd treatment.
1803f4a2713aSLionel Sambuc       // If we are in a class method, we must retrieve the
1804f4a2713aSLionel Sambuc       // _metaclass_ for the current class, pointed at by
1805f4a2713aSLionel Sambuc       // the class's "isa" pointer.  The following assumes that
1806f4a2713aSLionel Sambuc       // isa" is the first ivar in a class (which it must be).
1807f4a2713aSLionel Sambuc       Target = EmitClassRef(CGF, Class->getSuperClass());
1808f4a2713aSLionel Sambuc       Target = CGF.Builder.CreateStructGEP(Target, 0);
1809f4a2713aSLionel Sambuc       Target = CGF.Builder.CreateLoad(Target);
1810f4a2713aSLionel Sambuc     } else {
1811f4a2713aSLionel Sambuc       llvm::Value *MetaClassPtr = EmitMetaClassRef(Class);
1812f4a2713aSLionel Sambuc       llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1);
1813f4a2713aSLionel Sambuc       llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr);
1814f4a2713aSLionel Sambuc       Target = Super;
1815f4a2713aSLionel Sambuc     }
1816f4a2713aSLionel Sambuc   }
1817f4a2713aSLionel Sambuc   else if (isCategoryImpl)
1818f4a2713aSLionel Sambuc     Target = EmitClassRef(CGF, Class->getSuperClass());
1819f4a2713aSLionel Sambuc   else {
1820f4a2713aSLionel Sambuc     llvm::Value *ClassPtr = EmitSuperClassRef(Class);
1821f4a2713aSLionel Sambuc     ClassPtr = CGF.Builder.CreateStructGEP(ClassPtr, 1);
1822f4a2713aSLionel Sambuc     Target = CGF.Builder.CreateLoad(ClassPtr);
1823f4a2713aSLionel Sambuc   }
1824f4a2713aSLionel Sambuc   // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
1825f4a2713aSLionel Sambuc   // ObjCTypes types.
1826f4a2713aSLionel Sambuc   llvm::Type *ClassTy =
1827f4a2713aSLionel Sambuc     CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
1828f4a2713aSLionel Sambuc   Target = CGF.Builder.CreateBitCast(Target, ClassTy);
1829f4a2713aSLionel Sambuc   CGF.Builder.CreateStore(Target,
1830f4a2713aSLionel Sambuc                           CGF.Builder.CreateStructGEP(ObjCSuper, 1));
1831f4a2713aSLionel Sambuc   return EmitMessageSend(CGF, Return, ResultType,
1832f4a2713aSLionel Sambuc                          EmitSelector(CGF, Sel),
1833f4a2713aSLionel Sambuc                          ObjCSuper, ObjCTypes.SuperPtrCTy,
1834f4a2713aSLionel Sambuc                          true, CallArgs, Method, ObjCTypes);
1835f4a2713aSLionel Sambuc }
1836f4a2713aSLionel Sambuc 
1837f4a2713aSLionel Sambuc /// Generate code for a message send expression.
GenerateMessageSend(CodeGen::CodeGenFunction & CGF,ReturnValueSlot Return,QualType ResultType,Selector Sel,llvm::Value * Receiver,const CallArgList & CallArgs,const ObjCInterfaceDecl * Class,const ObjCMethodDecl * Method)1838f4a2713aSLionel Sambuc CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1839f4a2713aSLionel Sambuc                                                ReturnValueSlot Return,
1840f4a2713aSLionel Sambuc                                                QualType ResultType,
1841f4a2713aSLionel Sambuc                                                Selector Sel,
1842f4a2713aSLionel Sambuc                                                llvm::Value *Receiver,
1843f4a2713aSLionel Sambuc                                                const CallArgList &CallArgs,
1844f4a2713aSLionel Sambuc                                                const ObjCInterfaceDecl *Class,
1845f4a2713aSLionel Sambuc                                                const ObjCMethodDecl *Method) {
1846f4a2713aSLionel Sambuc   return EmitMessageSend(CGF, Return, ResultType,
1847f4a2713aSLionel Sambuc                          EmitSelector(CGF, Sel),
1848f4a2713aSLionel Sambuc                          Receiver, CGF.getContext().getObjCIdType(),
1849f4a2713aSLionel Sambuc                          false, CallArgs, Method, ObjCTypes);
1850f4a2713aSLionel Sambuc }
1851f4a2713aSLionel Sambuc 
1852f4a2713aSLionel Sambuc CodeGen::RValue
EmitMessageSend(CodeGen::CodeGenFunction & CGF,ReturnValueSlot Return,QualType ResultType,llvm::Value * Sel,llvm::Value * Arg0,QualType Arg0Ty,bool IsSuper,const CallArgList & CallArgs,const ObjCMethodDecl * Method,const ObjCCommonTypesHelper & ObjCTypes)1853f4a2713aSLionel Sambuc CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
1854f4a2713aSLionel Sambuc                                  ReturnValueSlot Return,
1855f4a2713aSLionel Sambuc                                  QualType ResultType,
1856f4a2713aSLionel Sambuc                                  llvm::Value *Sel,
1857f4a2713aSLionel Sambuc                                  llvm::Value *Arg0,
1858f4a2713aSLionel Sambuc                                  QualType Arg0Ty,
1859f4a2713aSLionel Sambuc                                  bool IsSuper,
1860f4a2713aSLionel Sambuc                                  const CallArgList &CallArgs,
1861f4a2713aSLionel Sambuc                                  const ObjCMethodDecl *Method,
1862f4a2713aSLionel Sambuc                                  const ObjCCommonTypesHelper &ObjCTypes) {
1863f4a2713aSLionel Sambuc   CallArgList ActualArgs;
1864f4a2713aSLionel Sambuc   if (!IsSuper)
1865f4a2713aSLionel Sambuc     Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy);
1866f4a2713aSLionel Sambuc   ActualArgs.add(RValue::get(Arg0), Arg0Ty);
1867f4a2713aSLionel Sambuc   ActualArgs.add(RValue::get(Sel), CGF.getContext().getObjCSelType());
1868f4a2713aSLionel Sambuc   ActualArgs.addFrom(CallArgs);
1869f4a2713aSLionel Sambuc 
1870f4a2713aSLionel Sambuc   // If we're calling a method, use the formal signature.
1871f4a2713aSLionel Sambuc   MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);
1872f4a2713aSLionel Sambuc 
1873f4a2713aSLionel Sambuc   if (Method)
1874*0a6a1f1dSLionel Sambuc     assert(CGM.getContext().getCanonicalType(Method->getReturnType()) ==
1875f4a2713aSLionel Sambuc                CGM.getContext().getCanonicalType(ResultType) &&
1876f4a2713aSLionel Sambuc            "Result type mismatch!");
1877f4a2713aSLionel Sambuc 
1878f4a2713aSLionel Sambuc   NullReturnState nullReturn;
1879f4a2713aSLionel Sambuc 
1880*0a6a1f1dSLionel Sambuc   llvm::Constant *Fn = nullptr;
1881*0a6a1f1dSLionel Sambuc   if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) {
1882f4a2713aSLionel Sambuc     if (!IsSuper) nullReturn.init(CGF, Arg0);
1883f4a2713aSLionel Sambuc     Fn = (ObjCABI == 2) ?  ObjCTypes.getSendStretFn2(IsSuper)
1884f4a2713aSLionel Sambuc       : ObjCTypes.getSendStretFn(IsSuper);
1885f4a2713aSLionel Sambuc   } else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
1886f4a2713aSLionel Sambuc     Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
1887f4a2713aSLionel Sambuc       : ObjCTypes.getSendFpretFn(IsSuper);
1888f4a2713aSLionel Sambuc   } else if (CGM.ReturnTypeUsesFP2Ret(ResultType)) {
1889f4a2713aSLionel Sambuc     Fn = (ObjCABI == 2) ? ObjCTypes.getSendFp2RetFn2(IsSuper)
1890f4a2713aSLionel Sambuc       : ObjCTypes.getSendFp2retFn(IsSuper);
1891f4a2713aSLionel Sambuc   } else {
1892*0a6a1f1dSLionel Sambuc     // arm64 uses objc_msgSend for stret methods and yet null receiver check
1893*0a6a1f1dSLionel Sambuc     // must be made for it.
1894*0a6a1f1dSLionel Sambuc     if (!IsSuper && CGM.ReturnTypeUsesSRet(MSI.CallInfo))
1895*0a6a1f1dSLionel Sambuc       nullReturn.init(CGF, Arg0);
1896f4a2713aSLionel Sambuc     Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
1897f4a2713aSLionel Sambuc       : ObjCTypes.getSendFn(IsSuper);
1898f4a2713aSLionel Sambuc   }
1899f4a2713aSLionel Sambuc 
1900f4a2713aSLionel Sambuc   bool requiresnullCheck = false;
1901f4a2713aSLionel Sambuc   if (CGM.getLangOpts().ObjCAutoRefCount && Method)
1902*0a6a1f1dSLionel Sambuc     for (const auto *ParamDecl : Method->params()) {
1903f4a2713aSLionel Sambuc       if (ParamDecl->hasAttr<NSConsumedAttr>()) {
1904f4a2713aSLionel Sambuc         if (!nullReturn.NullBB)
1905f4a2713aSLionel Sambuc           nullReturn.init(CGF, Arg0);
1906f4a2713aSLionel Sambuc         requiresnullCheck = true;
1907f4a2713aSLionel Sambuc         break;
1908f4a2713aSLionel Sambuc       }
1909f4a2713aSLionel Sambuc     }
1910f4a2713aSLionel Sambuc 
1911f4a2713aSLionel Sambuc   Fn = llvm::ConstantExpr::getBitCast(Fn, MSI.MessengerType);
1912f4a2713aSLionel Sambuc   RValue rvalue = CGF.EmitCall(MSI.CallInfo, Fn, Return, ActualArgs);
1913f4a2713aSLionel Sambuc   return nullReturn.complete(CGF, rvalue, ResultType, CallArgs,
1914*0a6a1f1dSLionel Sambuc                              requiresnullCheck ? Method : nullptr);
1915f4a2713aSLionel Sambuc }
1916f4a2713aSLionel Sambuc 
GetGCAttrTypeForType(ASTContext & Ctx,QualType FQT)1917f4a2713aSLionel Sambuc static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) {
1918f4a2713aSLionel Sambuc   if (FQT.isObjCGCStrong())
1919f4a2713aSLionel Sambuc     return Qualifiers::Strong;
1920f4a2713aSLionel Sambuc 
1921f4a2713aSLionel Sambuc   if (FQT.isObjCGCWeak() || FQT.getObjCLifetime() == Qualifiers::OCL_Weak)
1922f4a2713aSLionel Sambuc     return Qualifiers::Weak;
1923f4a2713aSLionel Sambuc 
1924f4a2713aSLionel Sambuc   // check for __unsafe_unretained
1925f4a2713aSLionel Sambuc   if (FQT.getObjCLifetime() == Qualifiers::OCL_ExplicitNone)
1926f4a2713aSLionel Sambuc     return Qualifiers::GCNone;
1927f4a2713aSLionel Sambuc 
1928f4a2713aSLionel Sambuc   if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
1929f4a2713aSLionel Sambuc     return Qualifiers::Strong;
1930f4a2713aSLionel Sambuc 
1931f4a2713aSLionel Sambuc   if (const PointerType *PT = FQT->getAs<PointerType>())
1932f4a2713aSLionel Sambuc     return GetGCAttrTypeForType(Ctx, PT->getPointeeType());
1933f4a2713aSLionel Sambuc 
1934f4a2713aSLionel Sambuc   return Qualifiers::GCNone;
1935f4a2713aSLionel Sambuc }
1936f4a2713aSLionel Sambuc 
BuildGCBlockLayout(CodeGenModule & CGM,const CGBlockInfo & blockInfo)1937f4a2713aSLionel Sambuc llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
1938f4a2713aSLionel Sambuc                                                 const CGBlockInfo &blockInfo) {
1939f4a2713aSLionel Sambuc 
1940f4a2713aSLionel Sambuc   llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
1941f4a2713aSLionel Sambuc   if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
1942f4a2713aSLionel Sambuc       !CGM.getLangOpts().ObjCAutoRefCount)
1943f4a2713aSLionel Sambuc     return nullPtr;
1944f4a2713aSLionel Sambuc 
1945f4a2713aSLionel Sambuc   bool hasUnion = false;
1946f4a2713aSLionel Sambuc   SkipIvars.clear();
1947f4a2713aSLionel Sambuc   IvarsInfo.clear();
1948f4a2713aSLionel Sambuc   unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0);
1949f4a2713aSLionel Sambuc   unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
1950f4a2713aSLionel Sambuc 
1951f4a2713aSLionel Sambuc   // __isa is the first field in block descriptor and must assume by runtime's
1952f4a2713aSLionel Sambuc   // convention that it is GC'able.
1953f4a2713aSLionel Sambuc   IvarsInfo.push_back(GC_IVAR(0, 1));
1954f4a2713aSLionel Sambuc 
1955f4a2713aSLionel Sambuc   const BlockDecl *blockDecl = blockInfo.getBlockDecl();
1956f4a2713aSLionel Sambuc 
1957f4a2713aSLionel Sambuc   // Calculate the basic layout of the block structure.
1958f4a2713aSLionel Sambuc   const llvm::StructLayout *layout =
1959f4a2713aSLionel Sambuc     CGM.getDataLayout().getStructLayout(blockInfo.StructureType);
1960f4a2713aSLionel Sambuc 
1961f4a2713aSLionel Sambuc   // Ignore the optional 'this' capture: C++ objects are not assumed
1962f4a2713aSLionel Sambuc   // to be GC'ed.
1963f4a2713aSLionel Sambuc 
1964f4a2713aSLionel Sambuc   // Walk the captured variables.
1965*0a6a1f1dSLionel Sambuc   for (const auto &CI : blockDecl->captures()) {
1966*0a6a1f1dSLionel Sambuc     const VarDecl *variable = CI.getVariable();
1967f4a2713aSLionel Sambuc     QualType type = variable->getType();
1968f4a2713aSLionel Sambuc 
1969f4a2713aSLionel Sambuc     const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
1970f4a2713aSLionel Sambuc 
1971f4a2713aSLionel Sambuc     // Ignore constant captures.
1972f4a2713aSLionel Sambuc     if (capture.isConstant()) continue;
1973f4a2713aSLionel Sambuc 
1974f4a2713aSLionel Sambuc     uint64_t fieldOffset = layout->getElementOffset(capture.getIndex());
1975f4a2713aSLionel Sambuc 
1976f4a2713aSLionel Sambuc     // __block variables are passed by their descriptor address.
1977*0a6a1f1dSLionel Sambuc     if (CI.isByRef()) {
1978f4a2713aSLionel Sambuc       IvarsInfo.push_back(GC_IVAR(fieldOffset, /*size in words*/ 1));
1979f4a2713aSLionel Sambuc       continue;
1980f4a2713aSLionel Sambuc     }
1981f4a2713aSLionel Sambuc 
1982f4a2713aSLionel Sambuc     assert(!type->isArrayType() && "array variable should not be caught");
1983f4a2713aSLionel Sambuc     if (const RecordType *record = type->getAs<RecordType>()) {
1984f4a2713aSLionel Sambuc       BuildAggrIvarRecordLayout(record, fieldOffset, true, hasUnion);
1985f4a2713aSLionel Sambuc       continue;
1986f4a2713aSLionel Sambuc     }
1987f4a2713aSLionel Sambuc 
1988f4a2713aSLionel Sambuc     Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), type);
1989f4a2713aSLionel Sambuc     unsigned fieldSize = CGM.getContext().getTypeSize(type);
1990f4a2713aSLionel Sambuc 
1991f4a2713aSLionel Sambuc     if (GCAttr == Qualifiers::Strong)
1992f4a2713aSLionel Sambuc       IvarsInfo.push_back(GC_IVAR(fieldOffset,
1993f4a2713aSLionel Sambuc                                   fieldSize / WordSizeInBits));
1994f4a2713aSLionel Sambuc     else if (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak)
1995f4a2713aSLionel Sambuc       SkipIvars.push_back(GC_IVAR(fieldOffset,
1996f4a2713aSLionel Sambuc                                   fieldSize / ByteSizeInBits));
1997f4a2713aSLionel Sambuc   }
1998f4a2713aSLionel Sambuc 
1999f4a2713aSLionel Sambuc   if (IvarsInfo.empty())
2000f4a2713aSLionel Sambuc     return nullPtr;
2001f4a2713aSLionel Sambuc 
2002f4a2713aSLionel Sambuc   // Sort on byte position; captures might not be allocated in order,
2003f4a2713aSLionel Sambuc   // and unions can do funny things.
2004f4a2713aSLionel Sambuc   llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
2005f4a2713aSLionel Sambuc   llvm::array_pod_sort(SkipIvars.begin(), SkipIvars.end());
2006f4a2713aSLionel Sambuc 
2007f4a2713aSLionel Sambuc   std::string BitMap;
2008f4a2713aSLionel Sambuc   llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
2009f4a2713aSLionel Sambuc   if (CGM.getLangOpts().ObjCGCBitmapPrint) {
2010f4a2713aSLionel Sambuc     printf("\n block variable layout for block: ");
2011f4a2713aSLionel Sambuc     const unsigned char *s = (const unsigned char*)BitMap.c_str();
2012f4a2713aSLionel Sambuc     for (unsigned i = 0, e = BitMap.size(); i < e; i++)
2013f4a2713aSLionel Sambuc       if (!(s[i] & 0xf0))
2014f4a2713aSLionel Sambuc         printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
2015f4a2713aSLionel Sambuc       else
2016f4a2713aSLionel Sambuc         printf("0x%x%s",  s[i], s[i] != 0 ? ", " : "");
2017f4a2713aSLionel Sambuc     printf("\n");
2018f4a2713aSLionel Sambuc   }
2019f4a2713aSLionel Sambuc 
2020f4a2713aSLionel Sambuc   return C;
2021f4a2713aSLionel Sambuc }
2022f4a2713aSLionel Sambuc 
2023f4a2713aSLionel Sambuc /// getBlockCaptureLifetime - This routine returns life time of the captured
2024f4a2713aSLionel Sambuc /// block variable for the purpose of block layout meta-data generation. FQT is
2025f4a2713aSLionel Sambuc /// the type of the variable captured in the block.
getBlockCaptureLifetime(QualType FQT,bool ByrefLayout)2026f4a2713aSLionel Sambuc Qualifiers::ObjCLifetime CGObjCCommonMac::getBlockCaptureLifetime(QualType FQT,
2027f4a2713aSLionel Sambuc                                                                   bool ByrefLayout) {
2028f4a2713aSLionel Sambuc   if (CGM.getLangOpts().ObjCAutoRefCount)
2029f4a2713aSLionel Sambuc     return FQT.getObjCLifetime();
2030f4a2713aSLionel Sambuc 
2031f4a2713aSLionel Sambuc   // MRR.
2032f4a2713aSLionel Sambuc   if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
2033f4a2713aSLionel Sambuc     return ByrefLayout ? Qualifiers::OCL_ExplicitNone : Qualifiers::OCL_Strong;
2034f4a2713aSLionel Sambuc 
2035f4a2713aSLionel Sambuc   return Qualifiers::OCL_None;
2036f4a2713aSLionel Sambuc }
2037f4a2713aSLionel Sambuc 
UpdateRunSkipBlockVars(bool IsByref,Qualifiers::ObjCLifetime LifeTime,CharUnits FieldOffset,CharUnits FieldSize)2038f4a2713aSLionel Sambuc void CGObjCCommonMac::UpdateRunSkipBlockVars(bool IsByref,
2039f4a2713aSLionel Sambuc                                              Qualifiers::ObjCLifetime LifeTime,
2040f4a2713aSLionel Sambuc                                              CharUnits FieldOffset,
2041f4a2713aSLionel Sambuc                                              CharUnits FieldSize) {
2042f4a2713aSLionel Sambuc   // __block variables are passed by their descriptor address.
2043f4a2713aSLionel Sambuc   if (IsByref)
2044f4a2713aSLionel Sambuc     RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_BYREF, FieldOffset,
2045f4a2713aSLionel Sambuc                                         FieldSize));
2046f4a2713aSLionel Sambuc   else if (LifeTime == Qualifiers::OCL_Strong)
2047f4a2713aSLionel Sambuc     RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset,
2048f4a2713aSLionel Sambuc                                         FieldSize));
2049f4a2713aSLionel Sambuc   else if (LifeTime == Qualifiers::OCL_Weak)
2050f4a2713aSLionel Sambuc     RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset,
2051f4a2713aSLionel Sambuc                                         FieldSize));
2052f4a2713aSLionel Sambuc   else if (LifeTime == Qualifiers::OCL_ExplicitNone)
2053f4a2713aSLionel Sambuc     RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset,
2054f4a2713aSLionel Sambuc                                         FieldSize));
2055f4a2713aSLionel Sambuc   else
2056f4a2713aSLionel Sambuc     RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES,
2057f4a2713aSLionel Sambuc                                         FieldOffset,
2058f4a2713aSLionel Sambuc                                         FieldSize));
2059f4a2713aSLionel Sambuc }
2060f4a2713aSLionel Sambuc 
BuildRCRecordLayout(const llvm::StructLayout * RecLayout,const RecordDecl * RD,ArrayRef<const FieldDecl * > RecFields,CharUnits BytePos,bool & HasUnion,bool ByrefLayout)2061f4a2713aSLionel Sambuc void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
2062f4a2713aSLionel Sambuc                                           const RecordDecl *RD,
2063f4a2713aSLionel Sambuc                                           ArrayRef<const FieldDecl*> RecFields,
2064f4a2713aSLionel Sambuc                                           CharUnits BytePos, bool &HasUnion,
2065f4a2713aSLionel Sambuc                                           bool ByrefLayout) {
2066f4a2713aSLionel Sambuc   bool IsUnion = (RD && RD->isUnion());
2067f4a2713aSLionel Sambuc   CharUnits MaxUnionSize = CharUnits::Zero();
2068*0a6a1f1dSLionel Sambuc   const FieldDecl *MaxField = nullptr;
2069*0a6a1f1dSLionel Sambuc   const FieldDecl *LastFieldBitfieldOrUnnamed = nullptr;
2070f4a2713aSLionel Sambuc   CharUnits MaxFieldOffset = CharUnits::Zero();
2071f4a2713aSLionel Sambuc   CharUnits LastBitfieldOrUnnamedOffset = CharUnits::Zero();
2072f4a2713aSLionel Sambuc 
2073f4a2713aSLionel Sambuc   if (RecFields.empty())
2074f4a2713aSLionel Sambuc     return;
2075f4a2713aSLionel Sambuc   unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
2076f4a2713aSLionel Sambuc 
2077f4a2713aSLionel Sambuc   for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
2078f4a2713aSLionel Sambuc     const FieldDecl *Field = RecFields[i];
2079f4a2713aSLionel Sambuc     // Note that 'i' here is actually the field index inside RD of Field,
2080f4a2713aSLionel Sambuc     // although this dependency is hidden.
2081f4a2713aSLionel Sambuc     const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
2082f4a2713aSLionel Sambuc     CharUnits FieldOffset =
2083f4a2713aSLionel Sambuc       CGM.getContext().toCharUnitsFromBits(RL.getFieldOffset(i));
2084f4a2713aSLionel Sambuc 
2085f4a2713aSLionel Sambuc     // Skip over unnamed or bitfields
2086f4a2713aSLionel Sambuc     if (!Field->getIdentifier() || Field->isBitField()) {
2087f4a2713aSLionel Sambuc       LastFieldBitfieldOrUnnamed = Field;
2088f4a2713aSLionel Sambuc       LastBitfieldOrUnnamedOffset = FieldOffset;
2089f4a2713aSLionel Sambuc       continue;
2090f4a2713aSLionel Sambuc     }
2091f4a2713aSLionel Sambuc 
2092*0a6a1f1dSLionel Sambuc     LastFieldBitfieldOrUnnamed = nullptr;
2093f4a2713aSLionel Sambuc     QualType FQT = Field->getType();
2094f4a2713aSLionel Sambuc     if (FQT->isRecordType() || FQT->isUnionType()) {
2095f4a2713aSLionel Sambuc       if (FQT->isUnionType())
2096f4a2713aSLionel Sambuc         HasUnion = true;
2097f4a2713aSLionel Sambuc 
2098f4a2713aSLionel Sambuc       BuildRCBlockVarRecordLayout(FQT->getAs<RecordType>(),
2099f4a2713aSLionel Sambuc                                   BytePos + FieldOffset, HasUnion);
2100f4a2713aSLionel Sambuc       continue;
2101f4a2713aSLionel Sambuc     }
2102f4a2713aSLionel Sambuc 
2103f4a2713aSLionel Sambuc     if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
2104f4a2713aSLionel Sambuc       const ConstantArrayType *CArray =
2105f4a2713aSLionel Sambuc         dyn_cast_or_null<ConstantArrayType>(Array);
2106f4a2713aSLionel Sambuc       uint64_t ElCount = CArray->getSize().getZExtValue();
2107f4a2713aSLionel Sambuc       assert(CArray && "only array with known element size is supported");
2108f4a2713aSLionel Sambuc       FQT = CArray->getElementType();
2109f4a2713aSLionel Sambuc       while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
2110f4a2713aSLionel Sambuc         const ConstantArrayType *CArray =
2111f4a2713aSLionel Sambuc           dyn_cast_or_null<ConstantArrayType>(Array);
2112f4a2713aSLionel Sambuc         ElCount *= CArray->getSize().getZExtValue();
2113f4a2713aSLionel Sambuc         FQT = CArray->getElementType();
2114f4a2713aSLionel Sambuc       }
2115f4a2713aSLionel Sambuc       if (FQT->isRecordType() && ElCount) {
2116f4a2713aSLionel Sambuc         int OldIndex = RunSkipBlockVars.size() - 1;
2117f4a2713aSLionel Sambuc         const RecordType *RT = FQT->getAs<RecordType>();
2118f4a2713aSLionel Sambuc         BuildRCBlockVarRecordLayout(RT, BytePos + FieldOffset,
2119f4a2713aSLionel Sambuc                                     HasUnion);
2120f4a2713aSLionel Sambuc 
2121f4a2713aSLionel Sambuc         // Replicate layout information for each array element. Note that
2122f4a2713aSLionel Sambuc         // one element is already done.
2123f4a2713aSLionel Sambuc         uint64_t ElIx = 1;
2124f4a2713aSLionel Sambuc         for (int FirstIndex = RunSkipBlockVars.size() - 1 ;ElIx < ElCount; ElIx++) {
2125f4a2713aSLionel Sambuc           CharUnits Size = CGM.getContext().getTypeSizeInChars(RT);
2126f4a2713aSLionel Sambuc           for (int i = OldIndex+1; i <= FirstIndex; ++i)
2127f4a2713aSLionel Sambuc             RunSkipBlockVars.push_back(
2128f4a2713aSLionel Sambuc               RUN_SKIP(RunSkipBlockVars[i].opcode,
2129f4a2713aSLionel Sambuc               RunSkipBlockVars[i].block_var_bytepos + Size*ElIx,
2130f4a2713aSLionel Sambuc               RunSkipBlockVars[i].block_var_size));
2131f4a2713aSLionel Sambuc         }
2132f4a2713aSLionel Sambuc         continue;
2133f4a2713aSLionel Sambuc       }
2134f4a2713aSLionel Sambuc     }
2135f4a2713aSLionel Sambuc     CharUnits FieldSize = CGM.getContext().getTypeSizeInChars(Field->getType());
2136f4a2713aSLionel Sambuc     if (IsUnion) {
2137f4a2713aSLionel Sambuc       CharUnits UnionIvarSize = FieldSize;
2138f4a2713aSLionel Sambuc       if (UnionIvarSize > MaxUnionSize) {
2139f4a2713aSLionel Sambuc         MaxUnionSize = UnionIvarSize;
2140f4a2713aSLionel Sambuc         MaxField = Field;
2141f4a2713aSLionel Sambuc         MaxFieldOffset = FieldOffset;
2142f4a2713aSLionel Sambuc       }
2143f4a2713aSLionel Sambuc     } else {
2144f4a2713aSLionel Sambuc       UpdateRunSkipBlockVars(false,
2145f4a2713aSLionel Sambuc                              getBlockCaptureLifetime(FQT, ByrefLayout),
2146f4a2713aSLionel Sambuc                              BytePos + FieldOffset,
2147f4a2713aSLionel Sambuc                              FieldSize);
2148f4a2713aSLionel Sambuc     }
2149f4a2713aSLionel Sambuc   }
2150f4a2713aSLionel Sambuc 
2151f4a2713aSLionel Sambuc   if (LastFieldBitfieldOrUnnamed) {
2152f4a2713aSLionel Sambuc     if (LastFieldBitfieldOrUnnamed->isBitField()) {
2153f4a2713aSLionel Sambuc       // Last field was a bitfield. Must update the info.
2154f4a2713aSLionel Sambuc       uint64_t BitFieldSize
2155f4a2713aSLionel Sambuc         = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext());
2156f4a2713aSLionel Sambuc       unsigned UnsSize = (BitFieldSize / ByteSizeInBits) +
2157f4a2713aSLionel Sambuc                         ((BitFieldSize % ByteSizeInBits) != 0);
2158f4a2713aSLionel Sambuc       CharUnits Size = CharUnits::fromQuantity(UnsSize);
2159f4a2713aSLionel Sambuc       Size += LastBitfieldOrUnnamedOffset;
2160f4a2713aSLionel Sambuc       UpdateRunSkipBlockVars(false,
2161f4a2713aSLionel Sambuc                              getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(),
2162f4a2713aSLionel Sambuc                                                      ByrefLayout),
2163f4a2713aSLionel Sambuc                              BytePos + LastBitfieldOrUnnamedOffset,
2164f4a2713aSLionel Sambuc                              Size);
2165f4a2713aSLionel Sambuc     } else {
2166f4a2713aSLionel Sambuc       assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
2167f4a2713aSLionel Sambuc       // Last field was unnamed. Must update skip info.
2168f4a2713aSLionel Sambuc       CharUnits FieldSize
2169f4a2713aSLionel Sambuc         = CGM.getContext().getTypeSizeInChars(LastFieldBitfieldOrUnnamed->getType());
2170f4a2713aSLionel Sambuc       UpdateRunSkipBlockVars(false,
2171f4a2713aSLionel Sambuc                              getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(),
2172f4a2713aSLionel Sambuc                                                      ByrefLayout),
2173f4a2713aSLionel Sambuc                              BytePos + LastBitfieldOrUnnamedOffset,
2174f4a2713aSLionel Sambuc                              FieldSize);
2175f4a2713aSLionel Sambuc     }
2176f4a2713aSLionel Sambuc   }
2177f4a2713aSLionel Sambuc 
2178f4a2713aSLionel Sambuc   if (MaxField)
2179f4a2713aSLionel Sambuc     UpdateRunSkipBlockVars(false,
2180f4a2713aSLionel Sambuc                            getBlockCaptureLifetime(MaxField->getType(), ByrefLayout),
2181f4a2713aSLionel Sambuc                            BytePos + MaxFieldOffset,
2182f4a2713aSLionel Sambuc                            MaxUnionSize);
2183f4a2713aSLionel Sambuc }
2184f4a2713aSLionel Sambuc 
BuildRCBlockVarRecordLayout(const RecordType * RT,CharUnits BytePos,bool & HasUnion,bool ByrefLayout)2185f4a2713aSLionel Sambuc void CGObjCCommonMac::BuildRCBlockVarRecordLayout(const RecordType *RT,
2186f4a2713aSLionel Sambuc                                                   CharUnits BytePos,
2187f4a2713aSLionel Sambuc                                                   bool &HasUnion,
2188f4a2713aSLionel Sambuc                                                   bool ByrefLayout) {
2189f4a2713aSLionel Sambuc   const RecordDecl *RD = RT->getDecl();
2190*0a6a1f1dSLionel Sambuc   SmallVector<const FieldDecl*, 16> Fields(RD->fields());
2191f4a2713aSLionel Sambuc   llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
2192f4a2713aSLionel Sambuc   const llvm::StructLayout *RecLayout =
2193f4a2713aSLionel Sambuc     CGM.getDataLayout().getStructLayout(cast<llvm::StructType>(Ty));
2194f4a2713aSLionel Sambuc 
2195f4a2713aSLionel Sambuc   BuildRCRecordLayout(RecLayout, RD, Fields, BytePos, HasUnion, ByrefLayout);
2196f4a2713aSLionel Sambuc }
2197f4a2713aSLionel Sambuc 
2198f4a2713aSLionel Sambuc /// InlineLayoutInstruction - This routine produce an inline instruction for the
2199f4a2713aSLionel Sambuc /// block variable layout if it can. If not, it returns 0. Rules are as follow:
2200f4a2713aSLionel Sambuc /// If ((uintptr_t) layout) < (1 << 12), the layout is inline. In the 64bit world,
2201f4a2713aSLionel Sambuc /// an inline layout of value 0x0000000000000xyz is interpreted as follows:
2202f4a2713aSLionel Sambuc /// x captured object pointers of BLOCK_LAYOUT_STRONG. Followed by
2203f4a2713aSLionel Sambuc /// y captured object of BLOCK_LAYOUT_BYREF. Followed by
2204f4a2713aSLionel Sambuc /// z captured object of BLOCK_LAYOUT_WEAK. If any of the above is missing, zero
2205f4a2713aSLionel Sambuc /// replaces it. For example, 0x00000x00 means x BLOCK_LAYOUT_STRONG and no
2206f4a2713aSLionel Sambuc /// BLOCK_LAYOUT_BYREF and no BLOCK_LAYOUT_WEAK objects are captured.
InlineLayoutInstruction(SmallVectorImpl<unsigned char> & Layout)2207f4a2713aSLionel Sambuc uint64_t CGObjCCommonMac::InlineLayoutInstruction(
2208f4a2713aSLionel Sambuc                                     SmallVectorImpl<unsigned char> &Layout) {
2209f4a2713aSLionel Sambuc   uint64_t Result = 0;
2210f4a2713aSLionel Sambuc   if (Layout.size() <= 3) {
2211f4a2713aSLionel Sambuc     unsigned size = Layout.size();
2212f4a2713aSLionel Sambuc     unsigned strong_word_count = 0, byref_word_count=0, weak_word_count=0;
2213f4a2713aSLionel Sambuc     unsigned char inst;
2214f4a2713aSLionel Sambuc     enum BLOCK_LAYOUT_OPCODE opcode ;
2215f4a2713aSLionel Sambuc     switch (size) {
2216f4a2713aSLionel Sambuc       case 3:
2217f4a2713aSLionel Sambuc         inst = Layout[0];
2218f4a2713aSLionel Sambuc         opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2219f4a2713aSLionel Sambuc         if (opcode == BLOCK_LAYOUT_STRONG)
2220f4a2713aSLionel Sambuc           strong_word_count = (inst & 0xF)+1;
2221f4a2713aSLionel Sambuc         else
2222f4a2713aSLionel Sambuc           return 0;
2223f4a2713aSLionel Sambuc         inst = Layout[1];
2224f4a2713aSLionel Sambuc         opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2225f4a2713aSLionel Sambuc         if (opcode == BLOCK_LAYOUT_BYREF)
2226f4a2713aSLionel Sambuc           byref_word_count = (inst & 0xF)+1;
2227f4a2713aSLionel Sambuc         else
2228f4a2713aSLionel Sambuc           return 0;
2229f4a2713aSLionel Sambuc         inst = Layout[2];
2230f4a2713aSLionel Sambuc         opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2231f4a2713aSLionel Sambuc         if (opcode == BLOCK_LAYOUT_WEAK)
2232f4a2713aSLionel Sambuc           weak_word_count = (inst & 0xF)+1;
2233f4a2713aSLionel Sambuc         else
2234f4a2713aSLionel Sambuc           return 0;
2235f4a2713aSLionel Sambuc         break;
2236f4a2713aSLionel Sambuc 
2237f4a2713aSLionel Sambuc       case 2:
2238f4a2713aSLionel Sambuc         inst = Layout[0];
2239f4a2713aSLionel Sambuc         opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2240f4a2713aSLionel Sambuc         if (opcode == BLOCK_LAYOUT_STRONG) {
2241f4a2713aSLionel Sambuc           strong_word_count = (inst & 0xF)+1;
2242f4a2713aSLionel Sambuc           inst = Layout[1];
2243f4a2713aSLionel Sambuc           opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2244f4a2713aSLionel Sambuc           if (opcode == BLOCK_LAYOUT_BYREF)
2245f4a2713aSLionel Sambuc             byref_word_count = (inst & 0xF)+1;
2246f4a2713aSLionel Sambuc           else if (opcode == BLOCK_LAYOUT_WEAK)
2247f4a2713aSLionel Sambuc             weak_word_count = (inst & 0xF)+1;
2248f4a2713aSLionel Sambuc           else
2249f4a2713aSLionel Sambuc             return 0;
2250f4a2713aSLionel Sambuc         }
2251f4a2713aSLionel Sambuc         else if (opcode == BLOCK_LAYOUT_BYREF) {
2252f4a2713aSLionel Sambuc           byref_word_count = (inst & 0xF)+1;
2253f4a2713aSLionel Sambuc           inst = Layout[1];
2254f4a2713aSLionel Sambuc           opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2255f4a2713aSLionel Sambuc           if (opcode == BLOCK_LAYOUT_WEAK)
2256f4a2713aSLionel Sambuc             weak_word_count = (inst & 0xF)+1;
2257f4a2713aSLionel Sambuc           else
2258f4a2713aSLionel Sambuc             return 0;
2259f4a2713aSLionel Sambuc         }
2260f4a2713aSLionel Sambuc         else
2261f4a2713aSLionel Sambuc           return 0;
2262f4a2713aSLionel Sambuc         break;
2263f4a2713aSLionel Sambuc 
2264f4a2713aSLionel Sambuc       case 1:
2265f4a2713aSLionel Sambuc         inst = Layout[0];
2266f4a2713aSLionel Sambuc         opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2267f4a2713aSLionel Sambuc         if (opcode == BLOCK_LAYOUT_STRONG)
2268f4a2713aSLionel Sambuc           strong_word_count = (inst & 0xF)+1;
2269f4a2713aSLionel Sambuc         else if (opcode == BLOCK_LAYOUT_BYREF)
2270f4a2713aSLionel Sambuc           byref_word_count = (inst & 0xF)+1;
2271f4a2713aSLionel Sambuc         else if (opcode == BLOCK_LAYOUT_WEAK)
2272f4a2713aSLionel Sambuc           weak_word_count = (inst & 0xF)+1;
2273f4a2713aSLionel Sambuc         else
2274f4a2713aSLionel Sambuc           return 0;
2275f4a2713aSLionel Sambuc         break;
2276f4a2713aSLionel Sambuc 
2277f4a2713aSLionel Sambuc       default:
2278f4a2713aSLionel Sambuc         return 0;
2279f4a2713aSLionel Sambuc     }
2280f4a2713aSLionel Sambuc 
2281f4a2713aSLionel Sambuc     // Cannot inline when any of the word counts is 15. Because this is one less
2282f4a2713aSLionel Sambuc     // than the actual work count (so 15 means 16 actual word counts),
2283f4a2713aSLionel Sambuc     // and we can only display 0 thru 15 word counts.
2284f4a2713aSLionel Sambuc     if (strong_word_count == 16 || byref_word_count == 16 || weak_word_count == 16)
2285f4a2713aSLionel Sambuc       return 0;
2286f4a2713aSLionel Sambuc 
2287f4a2713aSLionel Sambuc     unsigned count =
2288f4a2713aSLionel Sambuc       (strong_word_count != 0) + (byref_word_count != 0) + (weak_word_count != 0);
2289f4a2713aSLionel Sambuc 
2290f4a2713aSLionel Sambuc     if (size == count) {
2291f4a2713aSLionel Sambuc       if (strong_word_count)
2292f4a2713aSLionel Sambuc         Result = strong_word_count;
2293f4a2713aSLionel Sambuc       Result <<= 4;
2294f4a2713aSLionel Sambuc       if (byref_word_count)
2295f4a2713aSLionel Sambuc         Result += byref_word_count;
2296f4a2713aSLionel Sambuc       Result <<= 4;
2297f4a2713aSLionel Sambuc       if (weak_word_count)
2298f4a2713aSLionel Sambuc         Result += weak_word_count;
2299f4a2713aSLionel Sambuc     }
2300f4a2713aSLionel Sambuc   }
2301f4a2713aSLionel Sambuc   return Result;
2302f4a2713aSLionel Sambuc }
2303f4a2713aSLionel Sambuc 
getBitmapBlockLayout(bool ComputeByrefLayout)2304f4a2713aSLionel Sambuc llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) {
2305f4a2713aSLionel Sambuc   llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
2306f4a2713aSLionel Sambuc   if (RunSkipBlockVars.empty())
2307f4a2713aSLionel Sambuc     return nullPtr;
2308f4a2713aSLionel Sambuc   unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0);
2309f4a2713aSLionel Sambuc   unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
2310f4a2713aSLionel Sambuc   unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
2311f4a2713aSLionel Sambuc 
2312f4a2713aSLionel Sambuc   // Sort on byte position; captures might not be allocated in order,
2313f4a2713aSLionel Sambuc   // and unions can do funny things.
2314f4a2713aSLionel Sambuc   llvm::array_pod_sort(RunSkipBlockVars.begin(), RunSkipBlockVars.end());
2315f4a2713aSLionel Sambuc   SmallVector<unsigned char, 16> Layout;
2316f4a2713aSLionel Sambuc 
2317f4a2713aSLionel Sambuc   unsigned size = RunSkipBlockVars.size();
2318f4a2713aSLionel Sambuc   for (unsigned i = 0; i < size; i++) {
2319f4a2713aSLionel Sambuc     enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode;
2320f4a2713aSLionel Sambuc     CharUnits start_byte_pos = RunSkipBlockVars[i].block_var_bytepos;
2321f4a2713aSLionel Sambuc     CharUnits end_byte_pos = start_byte_pos;
2322f4a2713aSLionel Sambuc     unsigned j = i+1;
2323f4a2713aSLionel Sambuc     while (j < size) {
2324f4a2713aSLionel Sambuc       if (opcode == RunSkipBlockVars[j].opcode) {
2325f4a2713aSLionel Sambuc         end_byte_pos = RunSkipBlockVars[j++].block_var_bytepos;
2326f4a2713aSLionel Sambuc         i++;
2327f4a2713aSLionel Sambuc       }
2328f4a2713aSLionel Sambuc       else
2329f4a2713aSLionel Sambuc         break;
2330f4a2713aSLionel Sambuc     }
2331f4a2713aSLionel Sambuc     CharUnits size_in_bytes =
2332f4a2713aSLionel Sambuc     end_byte_pos - start_byte_pos + RunSkipBlockVars[j-1].block_var_size;
2333f4a2713aSLionel Sambuc     if (j < size) {
2334f4a2713aSLionel Sambuc       CharUnits gap =
2335f4a2713aSLionel Sambuc       RunSkipBlockVars[j].block_var_bytepos -
2336f4a2713aSLionel Sambuc       RunSkipBlockVars[j-1].block_var_bytepos - RunSkipBlockVars[j-1].block_var_size;
2337f4a2713aSLionel Sambuc       size_in_bytes += gap;
2338f4a2713aSLionel Sambuc     }
2339f4a2713aSLionel Sambuc     CharUnits residue_in_bytes = CharUnits::Zero();
2340f4a2713aSLionel Sambuc     if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES) {
2341f4a2713aSLionel Sambuc       residue_in_bytes = size_in_bytes % WordSizeInBytes;
2342f4a2713aSLionel Sambuc       size_in_bytes -= residue_in_bytes;
2343f4a2713aSLionel Sambuc       opcode = BLOCK_LAYOUT_NON_OBJECT_WORDS;
2344f4a2713aSLionel Sambuc     }
2345f4a2713aSLionel Sambuc 
2346f4a2713aSLionel Sambuc     unsigned size_in_words = size_in_bytes.getQuantity() / WordSizeInBytes;
2347f4a2713aSLionel Sambuc     while (size_in_words >= 16) {
2348f4a2713aSLionel Sambuc       // Note that value in imm. is one less that the actual
2349f4a2713aSLionel Sambuc       // value. So, 0xf means 16 words follow!
2350f4a2713aSLionel Sambuc       unsigned char inst = (opcode << 4) | 0xf;
2351f4a2713aSLionel Sambuc       Layout.push_back(inst);
2352f4a2713aSLionel Sambuc       size_in_words -= 16;
2353f4a2713aSLionel Sambuc     }
2354f4a2713aSLionel Sambuc     if (size_in_words > 0) {
2355f4a2713aSLionel Sambuc       // Note that value in imm. is one less that the actual
2356f4a2713aSLionel Sambuc       // value. So, we subtract 1 away!
2357f4a2713aSLionel Sambuc       unsigned char inst = (opcode << 4) | (size_in_words-1);
2358f4a2713aSLionel Sambuc       Layout.push_back(inst);
2359f4a2713aSLionel Sambuc     }
2360f4a2713aSLionel Sambuc     if (residue_in_bytes > CharUnits::Zero()) {
2361f4a2713aSLionel Sambuc       unsigned char inst =
2362f4a2713aSLionel Sambuc       (BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) | (residue_in_bytes.getQuantity()-1);
2363f4a2713aSLionel Sambuc       Layout.push_back(inst);
2364f4a2713aSLionel Sambuc     }
2365f4a2713aSLionel Sambuc   }
2366f4a2713aSLionel Sambuc 
2367f4a2713aSLionel Sambuc   int e = Layout.size()-1;
2368f4a2713aSLionel Sambuc   while (e >= 0) {
2369f4a2713aSLionel Sambuc     unsigned char inst = Layout[e--];
2370f4a2713aSLionel Sambuc     enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2371f4a2713aSLionel Sambuc     if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES || opcode == BLOCK_LAYOUT_NON_OBJECT_WORDS)
2372f4a2713aSLionel Sambuc       Layout.pop_back();
2373f4a2713aSLionel Sambuc     else
2374f4a2713aSLionel Sambuc       break;
2375f4a2713aSLionel Sambuc   }
2376f4a2713aSLionel Sambuc 
2377f4a2713aSLionel Sambuc   uint64_t Result = InlineLayoutInstruction(Layout);
2378f4a2713aSLionel Sambuc   if (Result != 0) {
2379f4a2713aSLionel Sambuc     // Block variable layout instruction has been inlined.
2380f4a2713aSLionel Sambuc     if (CGM.getLangOpts().ObjCGCBitmapPrint) {
2381f4a2713aSLionel Sambuc       if (ComputeByrefLayout)
2382f4a2713aSLionel Sambuc         printf("\n Inline instruction for BYREF variable layout: ");
2383f4a2713aSLionel Sambuc       else
2384f4a2713aSLionel Sambuc         printf("\n Inline instruction for block variable layout: ");
2385f4a2713aSLionel Sambuc       printf("0x0%" PRIx64 "\n", Result);
2386f4a2713aSLionel Sambuc     }
2387f4a2713aSLionel Sambuc     if (WordSizeInBytes == 8) {
2388f4a2713aSLionel Sambuc       const llvm::APInt Instruction(64, Result);
2389f4a2713aSLionel Sambuc       return llvm::Constant::getIntegerValue(CGM.Int64Ty, Instruction);
2390f4a2713aSLionel Sambuc     }
2391f4a2713aSLionel Sambuc     else {
2392f4a2713aSLionel Sambuc       const llvm::APInt Instruction(32, Result);
2393f4a2713aSLionel Sambuc       return llvm::Constant::getIntegerValue(CGM.Int32Ty, Instruction);
2394f4a2713aSLionel Sambuc     }
2395f4a2713aSLionel Sambuc   }
2396f4a2713aSLionel Sambuc 
2397f4a2713aSLionel Sambuc   unsigned char inst = (BLOCK_LAYOUT_OPERATOR << 4) | 0;
2398f4a2713aSLionel Sambuc   Layout.push_back(inst);
2399f4a2713aSLionel Sambuc   std::string BitMap;
2400f4a2713aSLionel Sambuc   for (unsigned i = 0, e = Layout.size(); i != e; i++)
2401f4a2713aSLionel Sambuc     BitMap += Layout[i];
2402f4a2713aSLionel Sambuc 
2403f4a2713aSLionel Sambuc   if (CGM.getLangOpts().ObjCGCBitmapPrint) {
2404f4a2713aSLionel Sambuc     if (ComputeByrefLayout)
2405f4a2713aSLionel Sambuc       printf("\n BYREF variable layout: ");
2406f4a2713aSLionel Sambuc     else
2407f4a2713aSLionel Sambuc       printf("\n block variable layout: ");
2408f4a2713aSLionel Sambuc     for (unsigned i = 0, e = BitMap.size(); i != e; i++) {
2409f4a2713aSLionel Sambuc       unsigned char inst = BitMap[i];
2410f4a2713aSLionel Sambuc       enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2411f4a2713aSLionel Sambuc       unsigned delta = 1;
2412f4a2713aSLionel Sambuc       switch (opcode) {
2413f4a2713aSLionel Sambuc         case BLOCK_LAYOUT_OPERATOR:
2414f4a2713aSLionel Sambuc           printf("BL_OPERATOR:");
2415f4a2713aSLionel Sambuc           delta = 0;
2416f4a2713aSLionel Sambuc           break;
2417f4a2713aSLionel Sambuc         case BLOCK_LAYOUT_NON_OBJECT_BYTES:
2418f4a2713aSLionel Sambuc           printf("BL_NON_OBJECT_BYTES:");
2419f4a2713aSLionel Sambuc           break;
2420f4a2713aSLionel Sambuc         case BLOCK_LAYOUT_NON_OBJECT_WORDS:
2421f4a2713aSLionel Sambuc           printf("BL_NON_OBJECT_WORD:");
2422f4a2713aSLionel Sambuc           break;
2423f4a2713aSLionel Sambuc         case BLOCK_LAYOUT_STRONG:
2424f4a2713aSLionel Sambuc           printf("BL_STRONG:");
2425f4a2713aSLionel Sambuc           break;
2426f4a2713aSLionel Sambuc         case BLOCK_LAYOUT_BYREF:
2427f4a2713aSLionel Sambuc           printf("BL_BYREF:");
2428f4a2713aSLionel Sambuc           break;
2429f4a2713aSLionel Sambuc         case BLOCK_LAYOUT_WEAK:
2430f4a2713aSLionel Sambuc           printf("BL_WEAK:");
2431f4a2713aSLionel Sambuc           break;
2432f4a2713aSLionel Sambuc         case BLOCK_LAYOUT_UNRETAINED:
2433f4a2713aSLionel Sambuc           printf("BL_UNRETAINED:");
2434f4a2713aSLionel Sambuc           break;
2435f4a2713aSLionel Sambuc       }
2436f4a2713aSLionel Sambuc       // Actual value of word count is one more that what is in the imm.
2437f4a2713aSLionel Sambuc       // field of the instruction
2438f4a2713aSLionel Sambuc       printf("%d", (inst & 0xf) + delta);
2439f4a2713aSLionel Sambuc       if (i < e-1)
2440f4a2713aSLionel Sambuc         printf(", ");
2441f4a2713aSLionel Sambuc       else
2442f4a2713aSLionel Sambuc         printf("\n");
2443f4a2713aSLionel Sambuc     }
2444f4a2713aSLionel Sambuc   }
2445f4a2713aSLionel Sambuc 
2446*0a6a1f1dSLionel Sambuc   llvm::GlobalVariable *Entry = CreateMetadataVar(
2447*0a6a1f1dSLionel Sambuc       "OBJC_CLASS_NAME_",
2448f4a2713aSLionel Sambuc       llvm::ConstantDataArray::getString(VMContext, BitMap, false),
2449f4a2713aSLionel Sambuc       "__TEXT,__objc_classname,cstring_literals", 1, true);
2450f4a2713aSLionel Sambuc   return getConstantGEP(VMContext, Entry, 0, 0);
2451f4a2713aSLionel Sambuc }
2452f4a2713aSLionel Sambuc 
BuildRCBlockLayout(CodeGenModule & CGM,const CGBlockInfo & blockInfo)2453f4a2713aSLionel Sambuc llvm::Constant *CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM,
2454f4a2713aSLionel Sambuc                                                     const CGBlockInfo &blockInfo) {
2455f4a2713aSLionel Sambuc   assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
2456f4a2713aSLionel Sambuc 
2457f4a2713aSLionel Sambuc   RunSkipBlockVars.clear();
2458f4a2713aSLionel Sambuc   bool hasUnion = false;
2459f4a2713aSLionel Sambuc 
2460f4a2713aSLionel Sambuc   unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0);
2461f4a2713aSLionel Sambuc   unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
2462f4a2713aSLionel Sambuc   unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
2463f4a2713aSLionel Sambuc 
2464f4a2713aSLionel Sambuc   const BlockDecl *blockDecl = blockInfo.getBlockDecl();
2465f4a2713aSLionel Sambuc 
2466f4a2713aSLionel Sambuc   // Calculate the basic layout of the block structure.
2467f4a2713aSLionel Sambuc   const llvm::StructLayout *layout =
2468f4a2713aSLionel Sambuc   CGM.getDataLayout().getStructLayout(blockInfo.StructureType);
2469f4a2713aSLionel Sambuc 
2470f4a2713aSLionel Sambuc   // Ignore the optional 'this' capture: C++ objects are not assumed
2471f4a2713aSLionel Sambuc   // to be GC'ed.
2472f4a2713aSLionel Sambuc   if (blockInfo.BlockHeaderForcedGapSize != CharUnits::Zero())
2473f4a2713aSLionel Sambuc     UpdateRunSkipBlockVars(false, Qualifiers::OCL_None,
2474f4a2713aSLionel Sambuc                            blockInfo.BlockHeaderForcedGapOffset,
2475f4a2713aSLionel Sambuc                            blockInfo.BlockHeaderForcedGapSize);
2476f4a2713aSLionel Sambuc   // Walk the captured variables.
2477*0a6a1f1dSLionel Sambuc   for (const auto &CI : blockDecl->captures()) {
2478*0a6a1f1dSLionel Sambuc     const VarDecl *variable = CI.getVariable();
2479f4a2713aSLionel Sambuc     QualType type = variable->getType();
2480f4a2713aSLionel Sambuc 
2481f4a2713aSLionel Sambuc     const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
2482f4a2713aSLionel Sambuc 
2483f4a2713aSLionel Sambuc     // Ignore constant captures.
2484f4a2713aSLionel Sambuc     if (capture.isConstant()) continue;
2485f4a2713aSLionel Sambuc 
2486f4a2713aSLionel Sambuc     CharUnits fieldOffset =
2487f4a2713aSLionel Sambuc        CharUnits::fromQuantity(layout->getElementOffset(capture.getIndex()));
2488f4a2713aSLionel Sambuc 
2489f4a2713aSLionel Sambuc     assert(!type->isArrayType() && "array variable should not be caught");
2490*0a6a1f1dSLionel Sambuc     if (!CI.isByRef())
2491f4a2713aSLionel Sambuc       if (const RecordType *record = type->getAs<RecordType>()) {
2492f4a2713aSLionel Sambuc         BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion);
2493f4a2713aSLionel Sambuc         continue;
2494f4a2713aSLionel Sambuc       }
2495f4a2713aSLionel Sambuc     CharUnits fieldSize;
2496*0a6a1f1dSLionel Sambuc     if (CI.isByRef())
2497f4a2713aSLionel Sambuc       fieldSize = CharUnits::fromQuantity(WordSizeInBytes);
2498f4a2713aSLionel Sambuc     else
2499f4a2713aSLionel Sambuc       fieldSize = CGM.getContext().getTypeSizeInChars(type);
2500*0a6a1f1dSLionel Sambuc     UpdateRunSkipBlockVars(CI.isByRef(), getBlockCaptureLifetime(type, false),
2501f4a2713aSLionel Sambuc                            fieldOffset, fieldSize);
2502f4a2713aSLionel Sambuc   }
2503f4a2713aSLionel Sambuc   return getBitmapBlockLayout(false);
2504f4a2713aSLionel Sambuc }
2505f4a2713aSLionel Sambuc 
2506f4a2713aSLionel Sambuc 
BuildByrefLayout(CodeGen::CodeGenModule & CGM,QualType T)2507f4a2713aSLionel Sambuc llvm::Constant *CGObjCCommonMac::BuildByrefLayout(CodeGen::CodeGenModule &CGM,
2508f4a2713aSLionel Sambuc                                                   QualType T) {
2509f4a2713aSLionel Sambuc   assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
2510f4a2713aSLionel Sambuc   assert(!T->isArrayType() && "__block array variable should not be caught");
2511f4a2713aSLionel Sambuc   CharUnits fieldOffset;
2512f4a2713aSLionel Sambuc   RunSkipBlockVars.clear();
2513f4a2713aSLionel Sambuc   bool hasUnion = false;
2514f4a2713aSLionel Sambuc   if (const RecordType *record = T->getAs<RecordType>()) {
2515f4a2713aSLionel Sambuc     BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion, true /*ByrefLayout */);
2516f4a2713aSLionel Sambuc     llvm::Constant *Result = getBitmapBlockLayout(true);
2517f4a2713aSLionel Sambuc     return Result;
2518f4a2713aSLionel Sambuc   }
2519f4a2713aSLionel Sambuc   llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
2520f4a2713aSLionel Sambuc   return nullPtr;
2521f4a2713aSLionel Sambuc }
2522f4a2713aSLionel Sambuc 
GenerateProtocolRef(CodeGenFunction & CGF,const ObjCProtocolDecl * PD)2523f4a2713aSLionel Sambuc llvm::Value *CGObjCMac::GenerateProtocolRef(CodeGenFunction &CGF,
2524f4a2713aSLionel Sambuc                                             const ObjCProtocolDecl *PD) {
2525f4a2713aSLionel Sambuc   // FIXME: I don't understand why gcc generates this, or where it is
2526f4a2713aSLionel Sambuc   // resolved. Investigate. Its also wasteful to look this up over and over.
2527f4a2713aSLionel Sambuc   LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
2528f4a2713aSLionel Sambuc 
2529f4a2713aSLionel Sambuc   return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
2530f4a2713aSLionel Sambuc                                         ObjCTypes.getExternalProtocolPtrTy());
2531f4a2713aSLionel Sambuc }
2532f4a2713aSLionel Sambuc 
GenerateProtocol(const ObjCProtocolDecl * PD)2533f4a2713aSLionel Sambuc void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
2534f4a2713aSLionel Sambuc   // FIXME: We shouldn't need this, the protocol decl should contain enough
2535f4a2713aSLionel Sambuc   // information to tell us whether this was a declaration or a definition.
2536f4a2713aSLionel Sambuc   DefinedProtocols.insert(PD->getIdentifier());
2537f4a2713aSLionel Sambuc 
2538f4a2713aSLionel Sambuc   // If we have generated a forward reference to this protocol, emit
2539f4a2713aSLionel Sambuc   // it now. Otherwise do nothing, the protocol objects are lazily
2540f4a2713aSLionel Sambuc   // emitted.
2541f4a2713aSLionel Sambuc   if (Protocols.count(PD->getIdentifier()))
2542f4a2713aSLionel Sambuc     GetOrEmitProtocol(PD);
2543f4a2713aSLionel Sambuc }
2544f4a2713aSLionel Sambuc 
GetProtocolRef(const ObjCProtocolDecl * PD)2545f4a2713aSLionel Sambuc llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
2546f4a2713aSLionel Sambuc   if (DefinedProtocols.count(PD->getIdentifier()))
2547f4a2713aSLionel Sambuc     return GetOrEmitProtocol(PD);
2548f4a2713aSLionel Sambuc 
2549f4a2713aSLionel Sambuc   return GetOrEmitProtocolRef(PD);
2550f4a2713aSLionel Sambuc }
2551f4a2713aSLionel Sambuc 
2552f4a2713aSLionel Sambuc /*
2553*0a6a1f1dSLionel Sambuc // Objective-C 1.0 extensions
2554f4a2713aSLionel Sambuc struct _objc_protocol {
2555f4a2713aSLionel Sambuc struct _objc_protocol_extension *isa;
2556f4a2713aSLionel Sambuc char *protocol_name;
2557f4a2713aSLionel Sambuc struct _objc_protocol_list *protocol_list;
2558f4a2713aSLionel Sambuc struct _objc__method_prototype_list *instance_methods;
2559f4a2713aSLionel Sambuc struct _objc__method_prototype_list *class_methods
2560f4a2713aSLionel Sambuc };
2561f4a2713aSLionel Sambuc 
2562f4a2713aSLionel Sambuc See EmitProtocolExtension().
2563f4a2713aSLionel Sambuc */
GetOrEmitProtocol(const ObjCProtocolDecl * PD)2564f4a2713aSLionel Sambuc llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
2565f4a2713aSLionel Sambuc   llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
2566f4a2713aSLionel Sambuc 
2567f4a2713aSLionel Sambuc   // Early exit if a defining object has already been generated.
2568f4a2713aSLionel Sambuc   if (Entry && Entry->hasInitializer())
2569f4a2713aSLionel Sambuc     return Entry;
2570f4a2713aSLionel Sambuc 
2571f4a2713aSLionel Sambuc   // Use the protocol definition, if there is one.
2572f4a2713aSLionel Sambuc   if (const ObjCProtocolDecl *Def = PD->getDefinition())
2573f4a2713aSLionel Sambuc     PD = Def;
2574f4a2713aSLionel Sambuc 
2575f4a2713aSLionel Sambuc   // FIXME: I don't understand why gcc generates this, or where it is
2576f4a2713aSLionel Sambuc   // resolved. Investigate. Its also wasteful to look this up over and over.
2577f4a2713aSLionel Sambuc   LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
2578f4a2713aSLionel Sambuc 
2579f4a2713aSLionel Sambuc   // Construct method lists.
2580f4a2713aSLionel Sambuc   std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
2581f4a2713aSLionel Sambuc   std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
2582f4a2713aSLionel Sambuc   std::vector<llvm::Constant*> MethodTypesExt, OptMethodTypesExt;
2583*0a6a1f1dSLionel Sambuc   for (const auto *MD : PD->instance_methods()) {
2584f4a2713aSLionel Sambuc     llvm::Constant *C = GetMethodDescriptionConstant(MD);
2585f4a2713aSLionel Sambuc     if (!C)
2586f4a2713aSLionel Sambuc       return GetOrEmitProtocolRef(PD);
2587f4a2713aSLionel Sambuc 
2588f4a2713aSLionel Sambuc     if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
2589f4a2713aSLionel Sambuc       OptInstanceMethods.push_back(C);
2590f4a2713aSLionel Sambuc       OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
2591f4a2713aSLionel Sambuc     } else {
2592f4a2713aSLionel Sambuc       InstanceMethods.push_back(C);
2593f4a2713aSLionel Sambuc       MethodTypesExt.push_back(GetMethodVarType(MD, true));
2594f4a2713aSLionel Sambuc     }
2595f4a2713aSLionel Sambuc   }
2596f4a2713aSLionel Sambuc 
2597*0a6a1f1dSLionel Sambuc   for (const auto *MD : PD->class_methods()) {
2598f4a2713aSLionel Sambuc     llvm::Constant *C = GetMethodDescriptionConstant(MD);
2599f4a2713aSLionel Sambuc     if (!C)
2600f4a2713aSLionel Sambuc       return GetOrEmitProtocolRef(PD);
2601f4a2713aSLionel Sambuc 
2602f4a2713aSLionel Sambuc     if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
2603f4a2713aSLionel Sambuc       OptClassMethods.push_back(C);
2604f4a2713aSLionel Sambuc       OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
2605f4a2713aSLionel Sambuc     } else {
2606f4a2713aSLionel Sambuc       ClassMethods.push_back(C);
2607f4a2713aSLionel Sambuc       MethodTypesExt.push_back(GetMethodVarType(MD, true));
2608f4a2713aSLionel Sambuc     }
2609f4a2713aSLionel Sambuc   }
2610f4a2713aSLionel Sambuc 
2611f4a2713aSLionel Sambuc   MethodTypesExt.insert(MethodTypesExt.end(),
2612f4a2713aSLionel Sambuc                         OptMethodTypesExt.begin(), OptMethodTypesExt.end());
2613f4a2713aSLionel Sambuc 
2614f4a2713aSLionel Sambuc   llvm::Constant *Values[] = {
2615f4a2713aSLionel Sambuc       EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods,
2616f4a2713aSLionel Sambuc                             MethodTypesExt),
2617*0a6a1f1dSLionel Sambuc       GetClassName(PD->getObjCRuntimeNameAsString()),
2618*0a6a1f1dSLionel Sambuc       EmitProtocolList("OBJC_PROTOCOL_REFS_" + PD->getName(),
2619*0a6a1f1dSLionel Sambuc                        PD->protocol_begin(), PD->protocol_end()),
2620*0a6a1f1dSLionel Sambuc       EmitMethodDescList("OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(),
2621f4a2713aSLionel Sambuc                          "__OBJC,__cat_inst_meth,regular,no_dead_strip",
2622f4a2713aSLionel Sambuc                          InstanceMethods),
2623*0a6a1f1dSLionel Sambuc       EmitMethodDescList("OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(),
2624f4a2713aSLionel Sambuc                          "__OBJC,__cat_cls_meth,regular,no_dead_strip",
2625*0a6a1f1dSLionel Sambuc                          ClassMethods)};
2626f4a2713aSLionel Sambuc   llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
2627f4a2713aSLionel Sambuc                                                    Values);
2628f4a2713aSLionel Sambuc 
2629f4a2713aSLionel Sambuc   if (Entry) {
2630*0a6a1f1dSLionel Sambuc     // Already created, update the initializer.
2631*0a6a1f1dSLionel Sambuc     assert(Entry->hasPrivateLinkage());
2632f4a2713aSLionel Sambuc     Entry->setInitializer(Init);
2633f4a2713aSLionel Sambuc   } else {
2634*0a6a1f1dSLionel Sambuc     Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy,
2635*0a6a1f1dSLionel Sambuc                                      false, llvm::GlobalValue::PrivateLinkage,
2636*0a6a1f1dSLionel Sambuc                                      Init, "OBJC_PROTOCOL_" + PD->getName());
2637f4a2713aSLionel Sambuc     Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
2638f4a2713aSLionel Sambuc     // FIXME: Is this necessary? Why only for protocol?
2639f4a2713aSLionel Sambuc     Entry->setAlignment(4);
2640f4a2713aSLionel Sambuc 
2641f4a2713aSLionel Sambuc     Protocols[PD->getIdentifier()] = Entry;
2642f4a2713aSLionel Sambuc   }
2643*0a6a1f1dSLionel Sambuc   CGM.addCompilerUsedGlobal(Entry);
2644f4a2713aSLionel Sambuc 
2645f4a2713aSLionel Sambuc   return Entry;
2646f4a2713aSLionel Sambuc }
2647f4a2713aSLionel Sambuc 
GetOrEmitProtocolRef(const ObjCProtocolDecl * PD)2648f4a2713aSLionel Sambuc llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
2649f4a2713aSLionel Sambuc   llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
2650f4a2713aSLionel Sambuc 
2651f4a2713aSLionel Sambuc   if (!Entry) {
2652f4a2713aSLionel Sambuc     // We use the initializer as a marker of whether this is a forward
2653f4a2713aSLionel Sambuc     // reference or not. At module finalization we add the empty
2654f4a2713aSLionel Sambuc     // contents for protocols which were referenced but never defined.
2655*0a6a1f1dSLionel Sambuc     Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy,
2656*0a6a1f1dSLionel Sambuc                                      false, llvm::GlobalValue::PrivateLinkage,
2657*0a6a1f1dSLionel Sambuc                                      nullptr, "OBJC_PROTOCOL_" + PD->getName());
2658f4a2713aSLionel Sambuc     Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
2659f4a2713aSLionel Sambuc     // FIXME: Is this necessary? Why only for protocol?
2660f4a2713aSLionel Sambuc     Entry->setAlignment(4);
2661f4a2713aSLionel Sambuc   }
2662f4a2713aSLionel Sambuc 
2663f4a2713aSLionel Sambuc   return Entry;
2664f4a2713aSLionel Sambuc }
2665f4a2713aSLionel Sambuc 
2666f4a2713aSLionel Sambuc /*
2667f4a2713aSLionel Sambuc   struct _objc_protocol_extension {
2668f4a2713aSLionel Sambuc   uint32_t size;
2669f4a2713aSLionel Sambuc   struct objc_method_description_list *optional_instance_methods;
2670f4a2713aSLionel Sambuc   struct objc_method_description_list *optional_class_methods;
2671f4a2713aSLionel Sambuc   struct objc_property_list *instance_properties;
2672f4a2713aSLionel Sambuc   const char ** extendedMethodTypes;
2673f4a2713aSLionel Sambuc   };
2674f4a2713aSLionel Sambuc */
2675f4a2713aSLionel Sambuc llvm::Constant *
EmitProtocolExtension(const ObjCProtocolDecl * PD,ArrayRef<llvm::Constant * > OptInstanceMethods,ArrayRef<llvm::Constant * > OptClassMethods,ArrayRef<llvm::Constant * > MethodTypesExt)2676f4a2713aSLionel Sambuc CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
2677f4a2713aSLionel Sambuc                                  ArrayRef<llvm::Constant*> OptInstanceMethods,
2678f4a2713aSLionel Sambuc                                  ArrayRef<llvm::Constant*> OptClassMethods,
2679f4a2713aSLionel Sambuc                                  ArrayRef<llvm::Constant*> MethodTypesExt) {
2680f4a2713aSLionel Sambuc   uint64_t Size =
2681f4a2713aSLionel Sambuc     CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
2682f4a2713aSLionel Sambuc   llvm::Constant *Values[] = {
2683f4a2713aSLionel Sambuc       llvm::ConstantInt::get(ObjCTypes.IntTy, Size),
2684*0a6a1f1dSLionel Sambuc       EmitMethodDescList("OBJC_PROTOCOL_INSTANCE_METHODS_OPT_" + PD->getName(),
2685f4a2713aSLionel Sambuc                          "__OBJC,__cat_inst_meth,regular,no_dead_strip",
2686f4a2713aSLionel Sambuc                          OptInstanceMethods),
2687*0a6a1f1dSLionel Sambuc       EmitMethodDescList("OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(),
2688f4a2713aSLionel Sambuc                          "__OBJC,__cat_cls_meth,regular,no_dead_strip",
2689f4a2713aSLionel Sambuc                          OptClassMethods),
2690*0a6a1f1dSLionel Sambuc       EmitPropertyList("OBJC_$_PROP_PROTO_LIST_" + PD->getName(), nullptr, PD,
2691f4a2713aSLionel Sambuc                        ObjCTypes),
2692*0a6a1f1dSLionel Sambuc       EmitProtocolMethodTypes("OBJC_PROTOCOL_METHOD_TYPES_" + PD->getName(),
2693*0a6a1f1dSLionel Sambuc                               MethodTypesExt, ObjCTypes)};
2694f4a2713aSLionel Sambuc 
2695f4a2713aSLionel Sambuc   // Return null if no extension bits are used.
2696f4a2713aSLionel Sambuc   if (Values[1]->isNullValue() && Values[2]->isNullValue() &&
2697f4a2713aSLionel Sambuc       Values[3]->isNullValue() && Values[4]->isNullValue())
2698f4a2713aSLionel Sambuc     return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
2699f4a2713aSLionel Sambuc 
2700f4a2713aSLionel Sambuc   llvm::Constant *Init =
2701f4a2713aSLionel Sambuc     llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
2702f4a2713aSLionel Sambuc 
2703f4a2713aSLionel Sambuc   // No special section, but goes in llvm.used
2704*0a6a1f1dSLionel Sambuc   return CreateMetadataVar("\01l_OBJC_PROTOCOLEXT_" + PD->getName(), Init,
2705*0a6a1f1dSLionel Sambuc                            StringRef(), 0, true);
2706f4a2713aSLionel Sambuc }
2707f4a2713aSLionel Sambuc 
2708f4a2713aSLionel Sambuc /*
2709f4a2713aSLionel Sambuc   struct objc_protocol_list {
2710f4a2713aSLionel Sambuc     struct objc_protocol_list *next;
2711f4a2713aSLionel Sambuc     long count;
2712f4a2713aSLionel Sambuc     Protocol *list[];
2713f4a2713aSLionel Sambuc   };
2714f4a2713aSLionel Sambuc */
2715f4a2713aSLionel Sambuc llvm::Constant *
EmitProtocolList(Twine Name,ObjCProtocolDecl::protocol_iterator begin,ObjCProtocolDecl::protocol_iterator end)2716f4a2713aSLionel Sambuc CGObjCMac::EmitProtocolList(Twine Name,
2717f4a2713aSLionel Sambuc                             ObjCProtocolDecl::protocol_iterator begin,
2718f4a2713aSLionel Sambuc                             ObjCProtocolDecl::protocol_iterator end) {
2719f4a2713aSLionel Sambuc   SmallVector<llvm::Constant *, 16> ProtocolRefs;
2720f4a2713aSLionel Sambuc 
2721f4a2713aSLionel Sambuc   for (; begin != end; ++begin)
2722f4a2713aSLionel Sambuc     ProtocolRefs.push_back(GetProtocolRef(*begin));
2723f4a2713aSLionel Sambuc 
2724f4a2713aSLionel Sambuc   // Just return null for empty protocol lists
2725f4a2713aSLionel Sambuc   if (ProtocolRefs.empty())
2726f4a2713aSLionel Sambuc     return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
2727f4a2713aSLionel Sambuc 
2728f4a2713aSLionel Sambuc   // This list is null terminated.
2729f4a2713aSLionel Sambuc   ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy));
2730f4a2713aSLionel Sambuc 
2731f4a2713aSLionel Sambuc   llvm::Constant *Values[3];
2732f4a2713aSLionel Sambuc   // This field is only used by the runtime.
2733f4a2713aSLionel Sambuc   Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
2734f4a2713aSLionel Sambuc   Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy,
2735f4a2713aSLionel Sambuc                                      ProtocolRefs.size() - 1);
2736f4a2713aSLionel Sambuc   Values[2] =
2737f4a2713aSLionel Sambuc     llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolPtrTy,
2738f4a2713aSLionel Sambuc                                                   ProtocolRefs.size()),
2739f4a2713aSLionel Sambuc                              ProtocolRefs);
2740f4a2713aSLionel Sambuc 
2741f4a2713aSLionel Sambuc   llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
2742f4a2713aSLionel Sambuc   llvm::GlobalVariable *GV =
2743f4a2713aSLionel Sambuc     CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip",
2744f4a2713aSLionel Sambuc                       4, false);
2745f4a2713aSLionel Sambuc   return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
2746f4a2713aSLionel Sambuc }
2747f4a2713aSLionel Sambuc 
2748f4a2713aSLionel Sambuc void CGObjCCommonMac::
PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo *,16> & PropertySet,SmallVectorImpl<llvm::Constant * > & Properties,const Decl * Container,const ObjCProtocolDecl * Proto,const ObjCCommonTypesHelper & ObjCTypes)2749f4a2713aSLionel Sambuc PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*,16> &PropertySet,
2750f4a2713aSLionel Sambuc                        SmallVectorImpl<llvm::Constant *> &Properties,
2751f4a2713aSLionel Sambuc                        const Decl *Container,
2752*0a6a1f1dSLionel Sambuc                        const ObjCProtocolDecl *Proto,
2753f4a2713aSLionel Sambuc                        const ObjCCommonTypesHelper &ObjCTypes) {
2754*0a6a1f1dSLionel Sambuc   for (const auto *P : Proto->protocols())
2755*0a6a1f1dSLionel Sambuc     PushProtocolProperties(PropertySet, Properties, Container, P, ObjCTypes);
2756*0a6a1f1dSLionel Sambuc   for (const auto *PD : Proto->properties()) {
2757*0a6a1f1dSLionel Sambuc     if (!PropertySet.insert(PD->getIdentifier()).second)
2758f4a2713aSLionel Sambuc       continue;
2759f4a2713aSLionel Sambuc     llvm::Constant *Prop[] = {
2760f4a2713aSLionel Sambuc       GetPropertyName(PD->getIdentifier()),
2761f4a2713aSLionel Sambuc       GetPropertyTypeString(PD, Container)
2762f4a2713aSLionel Sambuc     };
2763f4a2713aSLionel Sambuc     Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy, Prop));
2764f4a2713aSLionel Sambuc   }
2765f4a2713aSLionel Sambuc }
2766f4a2713aSLionel Sambuc 
2767f4a2713aSLionel Sambuc /*
2768f4a2713aSLionel Sambuc   struct _objc_property {
2769f4a2713aSLionel Sambuc     const char * const name;
2770f4a2713aSLionel Sambuc     const char * const attributes;
2771f4a2713aSLionel Sambuc   };
2772f4a2713aSLionel Sambuc 
2773f4a2713aSLionel Sambuc   struct _objc_property_list {
2774f4a2713aSLionel Sambuc     uint32_t entsize; // sizeof (struct _objc_property)
2775f4a2713aSLionel Sambuc     uint32_t prop_count;
2776f4a2713aSLionel Sambuc     struct _objc_property[prop_count];
2777f4a2713aSLionel Sambuc   };
2778f4a2713aSLionel Sambuc */
EmitPropertyList(Twine Name,const Decl * Container,const ObjCContainerDecl * OCD,const ObjCCommonTypesHelper & ObjCTypes)2779f4a2713aSLionel Sambuc llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name,
2780f4a2713aSLionel Sambuc                                        const Decl *Container,
2781f4a2713aSLionel Sambuc                                        const ObjCContainerDecl *OCD,
2782f4a2713aSLionel Sambuc                                        const ObjCCommonTypesHelper &ObjCTypes) {
2783f4a2713aSLionel Sambuc   SmallVector<llvm::Constant *, 16> Properties;
2784f4a2713aSLionel Sambuc   llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
2785*0a6a1f1dSLionel Sambuc   for (const auto *PD : OCD->properties()) {
2786f4a2713aSLionel Sambuc     PropertySet.insert(PD->getIdentifier());
2787f4a2713aSLionel Sambuc     llvm::Constant *Prop[] = {
2788f4a2713aSLionel Sambuc       GetPropertyName(PD->getIdentifier()),
2789f4a2713aSLionel Sambuc       GetPropertyTypeString(PD, Container)
2790f4a2713aSLionel Sambuc     };
2791f4a2713aSLionel Sambuc     Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy,
2792f4a2713aSLionel Sambuc                                                    Prop));
2793f4a2713aSLionel Sambuc   }
2794f4a2713aSLionel Sambuc   if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
2795*0a6a1f1dSLionel Sambuc     for (const auto *P : OID->all_referenced_protocols())
2796*0a6a1f1dSLionel Sambuc       PushProtocolProperties(PropertySet, Properties, Container, P, ObjCTypes);
2797f4a2713aSLionel Sambuc   }
2798f4a2713aSLionel Sambuc   else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) {
2799*0a6a1f1dSLionel Sambuc     for (const auto *P : CD->protocols())
2800*0a6a1f1dSLionel Sambuc       PushProtocolProperties(PropertySet, Properties, Container, P, ObjCTypes);
2801f4a2713aSLionel Sambuc   }
2802f4a2713aSLionel Sambuc 
2803f4a2713aSLionel Sambuc   // Return null for empty list.
2804f4a2713aSLionel Sambuc   if (Properties.empty())
2805f4a2713aSLionel Sambuc     return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
2806f4a2713aSLionel Sambuc 
2807f4a2713aSLionel Sambuc   unsigned PropertySize =
2808f4a2713aSLionel Sambuc     CGM.getDataLayout().getTypeAllocSize(ObjCTypes.PropertyTy);
2809f4a2713aSLionel Sambuc   llvm::Constant *Values[3];
2810f4a2713aSLionel Sambuc   Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize);
2811f4a2713aSLionel Sambuc   Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size());
2812f4a2713aSLionel Sambuc   llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy,
2813f4a2713aSLionel Sambuc                                              Properties.size());
2814f4a2713aSLionel Sambuc   Values[2] = llvm::ConstantArray::get(AT, Properties);
2815f4a2713aSLionel Sambuc   llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
2816f4a2713aSLionel Sambuc 
2817f4a2713aSLionel Sambuc   llvm::GlobalVariable *GV =
2818f4a2713aSLionel Sambuc     CreateMetadataVar(Name, Init,
2819f4a2713aSLionel Sambuc                       (ObjCABI == 2) ? "__DATA, __objc_const" :
2820f4a2713aSLionel Sambuc                       "__OBJC,__property,regular,no_dead_strip",
2821f4a2713aSLionel Sambuc                       (ObjCABI == 2) ? 8 : 4,
2822f4a2713aSLionel Sambuc                       true);
2823f4a2713aSLionel Sambuc   return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
2824f4a2713aSLionel Sambuc }
2825f4a2713aSLionel Sambuc 
2826f4a2713aSLionel Sambuc llvm::Constant *
EmitProtocolMethodTypes(Twine Name,ArrayRef<llvm::Constant * > MethodTypes,const ObjCCommonTypesHelper & ObjCTypes)2827f4a2713aSLionel Sambuc CGObjCCommonMac::EmitProtocolMethodTypes(Twine Name,
2828f4a2713aSLionel Sambuc                                          ArrayRef<llvm::Constant*> MethodTypes,
2829f4a2713aSLionel Sambuc                                          const ObjCCommonTypesHelper &ObjCTypes) {
2830f4a2713aSLionel Sambuc   // Return null for empty list.
2831f4a2713aSLionel Sambuc   if (MethodTypes.empty())
2832f4a2713aSLionel Sambuc     return llvm::Constant::getNullValue(ObjCTypes.Int8PtrPtrTy);
2833f4a2713aSLionel Sambuc 
2834f4a2713aSLionel Sambuc   llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
2835f4a2713aSLionel Sambuc                                              MethodTypes.size());
2836f4a2713aSLionel Sambuc   llvm::Constant *Init = llvm::ConstantArray::get(AT, MethodTypes);
2837f4a2713aSLionel Sambuc 
2838*0a6a1f1dSLionel Sambuc   llvm::GlobalVariable *GV = CreateMetadataVar(
2839*0a6a1f1dSLionel Sambuc       Name, Init, (ObjCABI == 2) ? "__DATA, __objc_const" : StringRef(),
2840*0a6a1f1dSLionel Sambuc       (ObjCABI == 2) ? 8 : 4, true);
2841f4a2713aSLionel Sambuc   return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.Int8PtrPtrTy);
2842f4a2713aSLionel Sambuc }
2843f4a2713aSLionel Sambuc 
2844f4a2713aSLionel Sambuc /*
2845f4a2713aSLionel Sambuc   struct objc_method_description_list {
2846f4a2713aSLionel Sambuc   int count;
2847f4a2713aSLionel Sambuc   struct objc_method_description list[];
2848f4a2713aSLionel Sambuc   };
2849f4a2713aSLionel Sambuc */
2850f4a2713aSLionel Sambuc llvm::Constant *
GetMethodDescriptionConstant(const ObjCMethodDecl * MD)2851f4a2713aSLionel Sambuc CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
2852f4a2713aSLionel Sambuc   llvm::Constant *Desc[] = {
2853f4a2713aSLionel Sambuc     llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
2854f4a2713aSLionel Sambuc                                    ObjCTypes.SelectorPtrTy),
2855f4a2713aSLionel Sambuc     GetMethodVarType(MD)
2856f4a2713aSLionel Sambuc   };
2857f4a2713aSLionel Sambuc   if (!Desc[1])
2858*0a6a1f1dSLionel Sambuc     return nullptr;
2859f4a2713aSLionel Sambuc 
2860f4a2713aSLionel Sambuc   return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy,
2861f4a2713aSLionel Sambuc                                    Desc);
2862f4a2713aSLionel Sambuc }
2863f4a2713aSLionel Sambuc 
2864f4a2713aSLionel Sambuc llvm::Constant *
EmitMethodDescList(Twine Name,const char * Section,ArrayRef<llvm::Constant * > Methods)2865f4a2713aSLionel Sambuc CGObjCMac::EmitMethodDescList(Twine Name, const char *Section,
2866f4a2713aSLionel Sambuc                               ArrayRef<llvm::Constant*> Methods) {
2867f4a2713aSLionel Sambuc   // Return null for empty list.
2868f4a2713aSLionel Sambuc   if (Methods.empty())
2869f4a2713aSLionel Sambuc     return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
2870f4a2713aSLionel Sambuc 
2871f4a2713aSLionel Sambuc   llvm::Constant *Values[2];
2872f4a2713aSLionel Sambuc   Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
2873f4a2713aSLionel Sambuc   llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy,
2874f4a2713aSLionel Sambuc                                              Methods.size());
2875f4a2713aSLionel Sambuc   Values[1] = llvm::ConstantArray::get(AT, Methods);
2876f4a2713aSLionel Sambuc   llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
2877f4a2713aSLionel Sambuc 
2878f4a2713aSLionel Sambuc   llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
2879f4a2713aSLionel Sambuc   return llvm::ConstantExpr::getBitCast(GV,
2880f4a2713aSLionel Sambuc                                         ObjCTypes.MethodDescriptionListPtrTy);
2881f4a2713aSLionel Sambuc }
2882f4a2713aSLionel Sambuc 
2883f4a2713aSLionel Sambuc /*
2884f4a2713aSLionel Sambuc   struct _objc_category {
2885f4a2713aSLionel Sambuc   char *category_name;
2886f4a2713aSLionel Sambuc   char *class_name;
2887f4a2713aSLionel Sambuc   struct _objc_method_list *instance_methods;
2888f4a2713aSLionel Sambuc   struct _objc_method_list *class_methods;
2889f4a2713aSLionel Sambuc   struct _objc_protocol_list *protocols;
2890f4a2713aSLionel Sambuc   uint32_t size; // <rdar://4585769>
2891f4a2713aSLionel Sambuc   struct _objc_property_list *instance_properties;
2892f4a2713aSLionel Sambuc   };
2893f4a2713aSLionel Sambuc */
GenerateCategory(const ObjCCategoryImplDecl * OCD)2894f4a2713aSLionel Sambuc void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
2895f4a2713aSLionel Sambuc   unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategoryTy);
2896f4a2713aSLionel Sambuc 
2897f4a2713aSLionel Sambuc   // FIXME: This is poor design, the OCD should have a pointer to the category
2898f4a2713aSLionel Sambuc   // decl. Additionally, note that Category can be null for the @implementation
2899f4a2713aSLionel Sambuc   // w/o an @interface case. Sema should just create one for us as it does for
2900f4a2713aSLionel Sambuc   // @implementation so everyone else can live life under a clear blue sky.
2901f4a2713aSLionel Sambuc   const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
2902f4a2713aSLionel Sambuc   const ObjCCategoryDecl *Category =
2903f4a2713aSLionel Sambuc     Interface->FindCategoryDeclaration(OCD->getIdentifier());
2904f4a2713aSLionel Sambuc 
2905f4a2713aSLionel Sambuc   SmallString<256> ExtName;
2906f4a2713aSLionel Sambuc   llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
2907f4a2713aSLionel Sambuc                                      << OCD->getName();
2908f4a2713aSLionel Sambuc 
2909f4a2713aSLionel Sambuc   SmallVector<llvm::Constant *, 16> InstanceMethods, ClassMethods;
2910*0a6a1f1dSLionel Sambuc   for (const auto *I : OCD->instance_methods())
2911f4a2713aSLionel Sambuc     // Instance methods should always be defined.
2912*0a6a1f1dSLionel Sambuc     InstanceMethods.push_back(GetMethodConstant(I));
2913*0a6a1f1dSLionel Sambuc 
2914*0a6a1f1dSLionel Sambuc   for (const auto *I : OCD->class_methods())
2915f4a2713aSLionel Sambuc     // Class methods should always be defined.
2916*0a6a1f1dSLionel Sambuc     ClassMethods.push_back(GetMethodConstant(I));
2917f4a2713aSLionel Sambuc 
2918f4a2713aSLionel Sambuc   llvm::Constant *Values[7];
2919*0a6a1f1dSLionel Sambuc   Values[0] = GetClassName(OCD->getName());
2920*0a6a1f1dSLionel Sambuc   Values[1] = GetClassName(Interface->getObjCRuntimeNameAsString());
2921f4a2713aSLionel Sambuc   LazySymbols.insert(Interface->getIdentifier());
2922*0a6a1f1dSLionel Sambuc   Values[2] = EmitMethodList("OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(),
2923f4a2713aSLionel Sambuc                              "__OBJC,__cat_inst_meth,regular,no_dead_strip",
2924f4a2713aSLionel Sambuc                              InstanceMethods);
2925*0a6a1f1dSLionel Sambuc   Values[3] = EmitMethodList("OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(),
2926f4a2713aSLionel Sambuc                              "__OBJC,__cat_cls_meth,regular,no_dead_strip",
2927f4a2713aSLionel Sambuc                              ClassMethods);
2928f4a2713aSLionel Sambuc   if (Category) {
2929f4a2713aSLionel Sambuc     Values[4] =
2930*0a6a1f1dSLionel Sambuc         EmitProtocolList("OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
2931*0a6a1f1dSLionel Sambuc                          Category->protocol_begin(), Category->protocol_end());
2932f4a2713aSLionel Sambuc   } else {
2933f4a2713aSLionel Sambuc     Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
2934f4a2713aSLionel Sambuc   }
2935f4a2713aSLionel Sambuc   Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
2936f4a2713aSLionel Sambuc 
2937f4a2713aSLionel Sambuc   // If there is no category @interface then there can be no properties.
2938f4a2713aSLionel Sambuc   if (Category) {
2939f4a2713aSLionel Sambuc     Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
2940f4a2713aSLionel Sambuc                                  OCD, Category, ObjCTypes);
2941f4a2713aSLionel Sambuc   } else {
2942f4a2713aSLionel Sambuc     Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
2943f4a2713aSLionel Sambuc   }
2944f4a2713aSLionel Sambuc 
2945f4a2713aSLionel Sambuc   llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy,
2946f4a2713aSLionel Sambuc                                                    Values);
2947f4a2713aSLionel Sambuc 
2948f4a2713aSLionel Sambuc   llvm::GlobalVariable *GV =
2949*0a6a1f1dSLionel Sambuc       CreateMetadataVar("OBJC_CATEGORY_" + ExtName.str(), Init,
2950*0a6a1f1dSLionel Sambuc                         "__OBJC,__category,regular,no_dead_strip", 4, true);
2951f4a2713aSLionel Sambuc   DefinedCategories.push_back(GV);
2952f4a2713aSLionel Sambuc   DefinedCategoryNames.insert(ExtName.str());
2953f4a2713aSLionel Sambuc   // method definition entries must be clear for next implementation.
2954f4a2713aSLionel Sambuc   MethodDefinitions.clear();
2955f4a2713aSLionel Sambuc }
2956f4a2713aSLionel Sambuc 
2957f4a2713aSLionel Sambuc enum FragileClassFlags {
2958f4a2713aSLionel Sambuc   FragileABI_Class_Factory                 = 0x00001,
2959f4a2713aSLionel Sambuc   FragileABI_Class_Meta                    = 0x00002,
2960f4a2713aSLionel Sambuc   FragileABI_Class_HasCXXStructors         = 0x02000,
2961f4a2713aSLionel Sambuc   FragileABI_Class_Hidden                  = 0x20000
2962f4a2713aSLionel Sambuc };
2963f4a2713aSLionel Sambuc 
2964f4a2713aSLionel Sambuc enum NonFragileClassFlags {
2965f4a2713aSLionel Sambuc   /// Is a meta-class.
2966f4a2713aSLionel Sambuc   NonFragileABI_Class_Meta                 = 0x00001,
2967f4a2713aSLionel Sambuc 
2968f4a2713aSLionel Sambuc   /// Is a root class.
2969f4a2713aSLionel Sambuc   NonFragileABI_Class_Root                 = 0x00002,
2970f4a2713aSLionel Sambuc 
2971f4a2713aSLionel Sambuc   /// Has a C++ constructor and destructor.
2972f4a2713aSLionel Sambuc   NonFragileABI_Class_HasCXXStructors      = 0x00004,
2973f4a2713aSLionel Sambuc 
2974f4a2713aSLionel Sambuc   /// Has hidden visibility.
2975f4a2713aSLionel Sambuc   NonFragileABI_Class_Hidden               = 0x00010,
2976f4a2713aSLionel Sambuc 
2977f4a2713aSLionel Sambuc   /// Has the exception attribute.
2978f4a2713aSLionel Sambuc   NonFragileABI_Class_Exception            = 0x00020,
2979f4a2713aSLionel Sambuc 
2980f4a2713aSLionel Sambuc   /// (Obsolete) ARC-specific: this class has a .release_ivars method
2981f4a2713aSLionel Sambuc   NonFragileABI_Class_HasIvarReleaser      = 0x00040,
2982f4a2713aSLionel Sambuc 
2983f4a2713aSLionel Sambuc   /// Class implementation was compiled under ARC.
2984f4a2713aSLionel Sambuc   NonFragileABI_Class_CompiledByARC        = 0x00080,
2985f4a2713aSLionel Sambuc 
2986f4a2713aSLionel Sambuc   /// Class has non-trivial destructors, but zero-initialization is okay.
2987f4a2713aSLionel Sambuc   NonFragileABI_Class_HasCXXDestructorOnly = 0x00100
2988f4a2713aSLionel Sambuc };
2989f4a2713aSLionel Sambuc 
2990f4a2713aSLionel Sambuc /*
2991f4a2713aSLionel Sambuc   struct _objc_class {
2992f4a2713aSLionel Sambuc   Class isa;
2993f4a2713aSLionel Sambuc   Class super_class;
2994f4a2713aSLionel Sambuc   const char *name;
2995f4a2713aSLionel Sambuc   long version;
2996f4a2713aSLionel Sambuc   long info;
2997f4a2713aSLionel Sambuc   long instance_size;
2998f4a2713aSLionel Sambuc   struct _objc_ivar_list *ivars;
2999f4a2713aSLionel Sambuc   struct _objc_method_list *methods;
3000f4a2713aSLionel Sambuc   struct _objc_cache *cache;
3001f4a2713aSLionel Sambuc   struct _objc_protocol_list *protocols;
3002f4a2713aSLionel Sambuc   // Objective-C 1.0 extensions (<rdr://4585769>)
3003f4a2713aSLionel Sambuc   const char *ivar_layout;
3004f4a2713aSLionel Sambuc   struct _objc_class_ext *ext;
3005f4a2713aSLionel Sambuc   };
3006f4a2713aSLionel Sambuc 
3007f4a2713aSLionel Sambuc   See EmitClassExtension();
3008f4a2713aSLionel Sambuc */
GenerateClass(const ObjCImplementationDecl * ID)3009f4a2713aSLionel Sambuc void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
3010f4a2713aSLionel Sambuc   DefinedSymbols.insert(ID->getIdentifier());
3011f4a2713aSLionel Sambuc 
3012f4a2713aSLionel Sambuc   std::string ClassName = ID->getNameAsString();
3013f4a2713aSLionel Sambuc   // FIXME: Gross
3014f4a2713aSLionel Sambuc   ObjCInterfaceDecl *Interface =
3015f4a2713aSLionel Sambuc     const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
3016f4a2713aSLionel Sambuc   llvm::Constant *Protocols =
3017*0a6a1f1dSLionel Sambuc       EmitProtocolList("OBJC_CLASS_PROTOCOLS_" + ID->getName(),
3018f4a2713aSLionel Sambuc                        Interface->all_referenced_protocol_begin(),
3019f4a2713aSLionel Sambuc                        Interface->all_referenced_protocol_end());
3020f4a2713aSLionel Sambuc   unsigned Flags = FragileABI_Class_Factory;
3021f4a2713aSLionel Sambuc   if (ID->hasNonZeroConstructors() || ID->hasDestructors())
3022f4a2713aSLionel Sambuc     Flags |= FragileABI_Class_HasCXXStructors;
3023f4a2713aSLionel Sambuc   unsigned Size =
3024f4a2713aSLionel Sambuc     CGM.getContext().getASTObjCImplementationLayout(ID).getSize().getQuantity();
3025f4a2713aSLionel Sambuc 
3026f4a2713aSLionel Sambuc   // FIXME: Set CXX-structors flag.
3027f4a2713aSLionel Sambuc   if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
3028f4a2713aSLionel Sambuc     Flags |= FragileABI_Class_Hidden;
3029f4a2713aSLionel Sambuc 
3030f4a2713aSLionel Sambuc   SmallVector<llvm::Constant *, 16> InstanceMethods, ClassMethods;
3031*0a6a1f1dSLionel Sambuc   for (const auto *I : ID->instance_methods())
3032f4a2713aSLionel Sambuc     // Instance methods should always be defined.
3033*0a6a1f1dSLionel Sambuc     InstanceMethods.push_back(GetMethodConstant(I));
3034*0a6a1f1dSLionel Sambuc 
3035*0a6a1f1dSLionel Sambuc   for (const auto *I : ID->class_methods())
3036f4a2713aSLionel Sambuc     // Class methods should always be defined.
3037*0a6a1f1dSLionel Sambuc     ClassMethods.push_back(GetMethodConstant(I));
3038f4a2713aSLionel Sambuc 
3039*0a6a1f1dSLionel Sambuc   for (const auto *PID : ID->property_impls()) {
3040f4a2713aSLionel Sambuc     if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
3041f4a2713aSLionel Sambuc       ObjCPropertyDecl *PD = PID->getPropertyDecl();
3042f4a2713aSLionel Sambuc 
3043f4a2713aSLionel Sambuc       if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
3044f4a2713aSLionel Sambuc         if (llvm::Constant *C = GetMethodConstant(MD))
3045f4a2713aSLionel Sambuc           InstanceMethods.push_back(C);
3046f4a2713aSLionel Sambuc       if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
3047f4a2713aSLionel Sambuc         if (llvm::Constant *C = GetMethodConstant(MD))
3048f4a2713aSLionel Sambuc           InstanceMethods.push_back(C);
3049f4a2713aSLionel Sambuc     }
3050f4a2713aSLionel Sambuc   }
3051f4a2713aSLionel Sambuc 
3052f4a2713aSLionel Sambuc   llvm::Constant *Values[12];
3053f4a2713aSLionel Sambuc   Values[ 0] = EmitMetaClass(ID, Protocols, ClassMethods);
3054f4a2713aSLionel Sambuc   if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
3055f4a2713aSLionel Sambuc     // Record a reference to the super class.
3056f4a2713aSLionel Sambuc     LazySymbols.insert(Super->getIdentifier());
3057f4a2713aSLionel Sambuc 
3058f4a2713aSLionel Sambuc     Values[ 1] =
3059*0a6a1f1dSLionel Sambuc       llvm::ConstantExpr::getBitCast(GetClassName(Super->getObjCRuntimeNameAsString()),
3060f4a2713aSLionel Sambuc                                      ObjCTypes.ClassPtrTy);
3061f4a2713aSLionel Sambuc   } else {
3062f4a2713aSLionel Sambuc     Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
3063f4a2713aSLionel Sambuc   }
3064*0a6a1f1dSLionel Sambuc   Values[ 2] = GetClassName(ID->getObjCRuntimeNameAsString());
3065f4a2713aSLionel Sambuc   // Version is always 0.
3066f4a2713aSLionel Sambuc   Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
3067f4a2713aSLionel Sambuc   Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
3068f4a2713aSLionel Sambuc   Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
3069f4a2713aSLionel Sambuc   Values[ 6] = EmitIvarList(ID, false);
3070*0a6a1f1dSLionel Sambuc   Values[7] = EmitMethodList("OBJC_INSTANCE_METHODS_" + ID->getName(),
3071f4a2713aSLionel Sambuc                              "__OBJC,__inst_meth,regular,no_dead_strip",
3072f4a2713aSLionel Sambuc                              InstanceMethods);
3073f4a2713aSLionel Sambuc   // cache is always NULL.
3074f4a2713aSLionel Sambuc   Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
3075f4a2713aSLionel Sambuc   Values[ 9] = Protocols;
3076f4a2713aSLionel Sambuc   Values[10] = BuildIvarLayout(ID, true);
3077f4a2713aSLionel Sambuc   Values[11] = EmitClassExtension(ID);
3078f4a2713aSLionel Sambuc   llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
3079f4a2713aSLionel Sambuc                                                    Values);
3080*0a6a1f1dSLionel Sambuc   std::string Name("OBJC_CLASS_");
3081f4a2713aSLionel Sambuc   Name += ClassName;
3082f4a2713aSLionel Sambuc   const char *Section = "__OBJC,__class,regular,no_dead_strip";
3083f4a2713aSLionel Sambuc   // Check for a forward reference.
3084*0a6a1f1dSLionel Sambuc   llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
3085f4a2713aSLionel Sambuc   if (GV) {
3086f4a2713aSLionel Sambuc     assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3087f4a2713aSLionel Sambuc            "Forward metaclass reference has incorrect type.");
3088f4a2713aSLionel Sambuc     GV->setInitializer(Init);
3089f4a2713aSLionel Sambuc     GV->setSection(Section);
3090f4a2713aSLionel Sambuc     GV->setAlignment(4);
3091*0a6a1f1dSLionel Sambuc     CGM.addCompilerUsedGlobal(GV);
3092*0a6a1f1dSLionel Sambuc   } else
3093f4a2713aSLionel Sambuc     GV = CreateMetadataVar(Name, Init, Section, 4, true);
3094f4a2713aSLionel Sambuc   DefinedClasses.push_back(GV);
3095*0a6a1f1dSLionel Sambuc   ImplementedClasses.push_back(Interface);
3096f4a2713aSLionel Sambuc   // method definition entries must be clear for next implementation.
3097f4a2713aSLionel Sambuc   MethodDefinitions.clear();
3098f4a2713aSLionel Sambuc }
3099f4a2713aSLionel Sambuc 
EmitMetaClass(const ObjCImplementationDecl * ID,llvm::Constant * Protocols,ArrayRef<llvm::Constant * > Methods)3100f4a2713aSLionel Sambuc llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
3101f4a2713aSLionel Sambuc                                          llvm::Constant *Protocols,
3102f4a2713aSLionel Sambuc                                          ArrayRef<llvm::Constant*> Methods) {
3103f4a2713aSLionel Sambuc   unsigned Flags = FragileABI_Class_Meta;
3104f4a2713aSLionel Sambuc   unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassTy);
3105f4a2713aSLionel Sambuc 
3106f4a2713aSLionel Sambuc   if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
3107f4a2713aSLionel Sambuc     Flags |= FragileABI_Class_Hidden;
3108f4a2713aSLionel Sambuc 
3109f4a2713aSLionel Sambuc   llvm::Constant *Values[12];
3110f4a2713aSLionel Sambuc   // The isa for the metaclass is the root of the hierarchy.
3111f4a2713aSLionel Sambuc   const ObjCInterfaceDecl *Root = ID->getClassInterface();
3112f4a2713aSLionel Sambuc   while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
3113f4a2713aSLionel Sambuc     Root = Super;
3114f4a2713aSLionel Sambuc   Values[ 0] =
3115*0a6a1f1dSLionel Sambuc     llvm::ConstantExpr::getBitCast(GetClassName(Root->getObjCRuntimeNameAsString()),
3116f4a2713aSLionel Sambuc                                    ObjCTypes.ClassPtrTy);
3117f4a2713aSLionel Sambuc   // The super class for the metaclass is emitted as the name of the
3118f4a2713aSLionel Sambuc   // super class. The runtime fixes this up to point to the
3119f4a2713aSLionel Sambuc   // *metaclass* for the super class.
3120f4a2713aSLionel Sambuc   if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
3121f4a2713aSLionel Sambuc     Values[ 1] =
3122*0a6a1f1dSLionel Sambuc       llvm::ConstantExpr::getBitCast(GetClassName(Super->getObjCRuntimeNameAsString()),
3123f4a2713aSLionel Sambuc                                      ObjCTypes.ClassPtrTy);
3124f4a2713aSLionel Sambuc   } else {
3125f4a2713aSLionel Sambuc     Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
3126f4a2713aSLionel Sambuc   }
3127*0a6a1f1dSLionel Sambuc   Values[ 2] = GetClassName(ID->getObjCRuntimeNameAsString());
3128f4a2713aSLionel Sambuc   // Version is always 0.
3129f4a2713aSLionel Sambuc   Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
3130f4a2713aSLionel Sambuc   Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
3131f4a2713aSLionel Sambuc   Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
3132f4a2713aSLionel Sambuc   Values[ 6] = EmitIvarList(ID, true);
3133f4a2713aSLionel Sambuc   Values[7] =
3134*0a6a1f1dSLionel Sambuc       EmitMethodList("OBJC_CLASS_METHODS_" + ID->getNameAsString(),
3135*0a6a1f1dSLionel Sambuc                      "__OBJC,__cls_meth,regular,no_dead_strip", Methods);
3136f4a2713aSLionel Sambuc   // cache is always NULL.
3137f4a2713aSLionel Sambuc   Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
3138f4a2713aSLionel Sambuc   Values[ 9] = Protocols;
3139f4a2713aSLionel Sambuc   // ivar_layout for metaclass is always NULL.
3140f4a2713aSLionel Sambuc   Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
3141f4a2713aSLionel Sambuc   // The class extension is always unused for metaclasses.
3142f4a2713aSLionel Sambuc   Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
3143f4a2713aSLionel Sambuc   llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
3144f4a2713aSLionel Sambuc                                                    Values);
3145f4a2713aSLionel Sambuc 
3146*0a6a1f1dSLionel Sambuc   std::string Name("OBJC_METACLASS_");
3147f4a2713aSLionel Sambuc   Name += ID->getName();
3148f4a2713aSLionel Sambuc 
3149f4a2713aSLionel Sambuc   // Check for a forward reference.
3150*0a6a1f1dSLionel Sambuc   llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
3151f4a2713aSLionel Sambuc   if (GV) {
3152f4a2713aSLionel Sambuc     assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3153f4a2713aSLionel Sambuc            "Forward metaclass reference has incorrect type.");
3154f4a2713aSLionel Sambuc     GV->setInitializer(Init);
3155f4a2713aSLionel Sambuc   } else {
3156f4a2713aSLionel Sambuc     GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
3157*0a6a1f1dSLionel Sambuc                                   llvm::GlobalValue::PrivateLinkage,
3158f4a2713aSLionel Sambuc                                   Init, Name);
3159f4a2713aSLionel Sambuc   }
3160f4a2713aSLionel Sambuc   GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
3161f4a2713aSLionel Sambuc   GV->setAlignment(4);
3162*0a6a1f1dSLionel Sambuc   CGM.addCompilerUsedGlobal(GV);
3163f4a2713aSLionel Sambuc 
3164f4a2713aSLionel Sambuc   return GV;
3165f4a2713aSLionel Sambuc }
3166f4a2713aSLionel Sambuc 
EmitMetaClassRef(const ObjCInterfaceDecl * ID)3167f4a2713aSLionel Sambuc llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
3168*0a6a1f1dSLionel Sambuc   std::string Name = "OBJC_METACLASS_" + ID->getNameAsString();
3169f4a2713aSLionel Sambuc 
3170f4a2713aSLionel Sambuc   // FIXME: Should we look these up somewhere other than the module. Its a bit
3171f4a2713aSLionel Sambuc   // silly since we only generate these while processing an implementation, so
3172f4a2713aSLionel Sambuc   // exactly one pointer would work if know when we entered/exitted an
3173f4a2713aSLionel Sambuc   // implementation block.
3174f4a2713aSLionel Sambuc 
3175f4a2713aSLionel Sambuc   // Check for an existing forward reference.
3176f4a2713aSLionel Sambuc   // Previously, metaclass with internal linkage may have been defined.
3177f4a2713aSLionel Sambuc   // pass 'true' as 2nd argument so it is returned.
3178*0a6a1f1dSLionel Sambuc   llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
3179*0a6a1f1dSLionel Sambuc   if (!GV)
3180*0a6a1f1dSLionel Sambuc     GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
3181*0a6a1f1dSLionel Sambuc                                   llvm::GlobalValue::PrivateLinkage, nullptr,
3182*0a6a1f1dSLionel Sambuc                                   Name);
3183*0a6a1f1dSLionel Sambuc 
3184f4a2713aSLionel Sambuc   assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3185f4a2713aSLionel Sambuc          "Forward metaclass reference has incorrect type.");
3186f4a2713aSLionel Sambuc   return GV;
3187f4a2713aSLionel Sambuc }
3188f4a2713aSLionel Sambuc 
EmitSuperClassRef(const ObjCInterfaceDecl * ID)3189f4a2713aSLionel Sambuc llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
3190*0a6a1f1dSLionel Sambuc   std::string Name = "OBJC_CLASS_" + ID->getNameAsString();
3191*0a6a1f1dSLionel Sambuc   llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
3192f4a2713aSLionel Sambuc 
3193*0a6a1f1dSLionel Sambuc   if (!GV)
3194*0a6a1f1dSLionel Sambuc     GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
3195*0a6a1f1dSLionel Sambuc                                   llvm::GlobalValue::PrivateLinkage, nullptr,
3196*0a6a1f1dSLionel Sambuc                                   Name);
3197*0a6a1f1dSLionel Sambuc 
3198f4a2713aSLionel Sambuc   assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3199f4a2713aSLionel Sambuc          "Forward class metadata reference has incorrect type.");
3200f4a2713aSLionel Sambuc   return GV;
3201f4a2713aSLionel Sambuc }
3202f4a2713aSLionel Sambuc 
3203f4a2713aSLionel Sambuc /*
3204f4a2713aSLionel Sambuc   struct objc_class_ext {
3205f4a2713aSLionel Sambuc   uint32_t size;
3206f4a2713aSLionel Sambuc   const char *weak_ivar_layout;
3207f4a2713aSLionel Sambuc   struct _objc_property_list *properties;
3208f4a2713aSLionel Sambuc   };
3209f4a2713aSLionel Sambuc */
3210f4a2713aSLionel Sambuc llvm::Constant *
EmitClassExtension(const ObjCImplementationDecl * ID)3211f4a2713aSLionel Sambuc CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
3212f4a2713aSLionel Sambuc   uint64_t Size =
3213f4a2713aSLionel Sambuc     CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
3214f4a2713aSLionel Sambuc 
3215f4a2713aSLionel Sambuc   llvm::Constant *Values[3];
3216f4a2713aSLionel Sambuc   Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
3217f4a2713aSLionel Sambuc   Values[1] = BuildIvarLayout(ID, false);
3218f4a2713aSLionel Sambuc   Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
3219f4a2713aSLionel Sambuc                                ID, ID->getClassInterface(), ObjCTypes);
3220f4a2713aSLionel Sambuc 
3221f4a2713aSLionel Sambuc   // Return null if no extension bits are used.
3222f4a2713aSLionel Sambuc   if (Values[1]->isNullValue() && Values[2]->isNullValue())
3223f4a2713aSLionel Sambuc     return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
3224f4a2713aSLionel Sambuc 
3225f4a2713aSLionel Sambuc   llvm::Constant *Init =
3226f4a2713aSLionel Sambuc     llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
3227*0a6a1f1dSLionel Sambuc   return CreateMetadataVar("OBJC_CLASSEXT_" + ID->getName(), Init,
3228*0a6a1f1dSLionel Sambuc                            "__OBJC,__class_ext,regular,no_dead_strip", 4, true);
3229f4a2713aSLionel Sambuc }
3230f4a2713aSLionel Sambuc 
3231f4a2713aSLionel Sambuc /*
3232f4a2713aSLionel Sambuc   struct objc_ivar {
3233f4a2713aSLionel Sambuc     char *ivar_name;
3234f4a2713aSLionel Sambuc     char *ivar_type;
3235f4a2713aSLionel Sambuc     int ivar_offset;
3236f4a2713aSLionel Sambuc   };
3237f4a2713aSLionel Sambuc 
3238f4a2713aSLionel Sambuc   struct objc_ivar_list {
3239f4a2713aSLionel Sambuc     int ivar_count;
3240f4a2713aSLionel Sambuc     struct objc_ivar list[count];
3241f4a2713aSLionel Sambuc   };
3242f4a2713aSLionel Sambuc */
EmitIvarList(const ObjCImplementationDecl * ID,bool ForClass)3243f4a2713aSLionel Sambuc llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
3244f4a2713aSLionel Sambuc                                         bool ForClass) {
3245f4a2713aSLionel Sambuc   std::vector<llvm::Constant*> Ivars;
3246f4a2713aSLionel Sambuc 
3247f4a2713aSLionel Sambuc   // When emitting the root class GCC emits ivar entries for the
3248f4a2713aSLionel Sambuc   // actual class structure. It is not clear if we need to follow this
3249f4a2713aSLionel Sambuc   // behavior; for now lets try and get away with not doing it. If so,
3250f4a2713aSLionel Sambuc   // the cleanest solution would be to make up an ObjCInterfaceDecl
3251f4a2713aSLionel Sambuc   // for the class.
3252f4a2713aSLionel Sambuc   if (ForClass)
3253f4a2713aSLionel Sambuc     return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
3254f4a2713aSLionel Sambuc 
3255f4a2713aSLionel Sambuc   const ObjCInterfaceDecl *OID = ID->getClassInterface();
3256f4a2713aSLionel Sambuc 
3257f4a2713aSLionel Sambuc   for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
3258f4a2713aSLionel Sambuc        IVD; IVD = IVD->getNextIvar()) {
3259f4a2713aSLionel Sambuc     // Ignore unnamed bit-fields.
3260f4a2713aSLionel Sambuc     if (!IVD->getDeclName())
3261f4a2713aSLionel Sambuc       continue;
3262f4a2713aSLionel Sambuc     llvm::Constant *Ivar[] = {
3263f4a2713aSLionel Sambuc       GetMethodVarName(IVD->getIdentifier()),
3264f4a2713aSLionel Sambuc       GetMethodVarType(IVD),
3265f4a2713aSLionel Sambuc       llvm::ConstantInt::get(ObjCTypes.IntTy,
3266f4a2713aSLionel Sambuc                              ComputeIvarBaseOffset(CGM, OID, IVD))
3267f4a2713aSLionel Sambuc     };
3268f4a2713aSLionel Sambuc     Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar));
3269f4a2713aSLionel Sambuc   }
3270f4a2713aSLionel Sambuc 
3271f4a2713aSLionel Sambuc   // Return null for empty list.
3272f4a2713aSLionel Sambuc   if (Ivars.empty())
3273f4a2713aSLionel Sambuc     return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
3274f4a2713aSLionel Sambuc 
3275f4a2713aSLionel Sambuc   llvm::Constant *Values[2];
3276f4a2713aSLionel Sambuc   Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
3277f4a2713aSLionel Sambuc   llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy,
3278f4a2713aSLionel Sambuc                                              Ivars.size());
3279f4a2713aSLionel Sambuc   Values[1] = llvm::ConstantArray::get(AT, Ivars);
3280f4a2713aSLionel Sambuc   llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
3281f4a2713aSLionel Sambuc 
3282f4a2713aSLionel Sambuc   llvm::GlobalVariable *GV;
3283f4a2713aSLionel Sambuc   if (ForClass)
3284*0a6a1f1dSLionel Sambuc     GV =
3285*0a6a1f1dSLionel Sambuc         CreateMetadataVar("OBJC_CLASS_VARIABLES_" + ID->getName(), Init,
3286*0a6a1f1dSLionel Sambuc                           "__OBJC,__class_vars,regular,no_dead_strip", 4, true);
3287f4a2713aSLionel Sambuc   else
3288*0a6a1f1dSLionel Sambuc     GV = CreateMetadataVar("OBJC_INSTANCE_VARIABLES_" + ID->getName(), Init,
3289*0a6a1f1dSLionel Sambuc                            "__OBJC,__instance_vars,regular,no_dead_strip", 4,
3290*0a6a1f1dSLionel Sambuc                            true);
3291f4a2713aSLionel Sambuc   return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
3292f4a2713aSLionel Sambuc }
3293f4a2713aSLionel Sambuc 
3294f4a2713aSLionel Sambuc /*
3295f4a2713aSLionel Sambuc   struct objc_method {
3296f4a2713aSLionel Sambuc   SEL method_name;
3297f4a2713aSLionel Sambuc   char *method_types;
3298f4a2713aSLionel Sambuc   void *method;
3299f4a2713aSLionel Sambuc   };
3300f4a2713aSLionel Sambuc 
3301f4a2713aSLionel Sambuc   struct objc_method_list {
3302f4a2713aSLionel Sambuc   struct objc_method_list *obsolete;
3303f4a2713aSLionel Sambuc   int count;
3304f4a2713aSLionel Sambuc   struct objc_method methods_list[count];
3305f4a2713aSLionel Sambuc   };
3306f4a2713aSLionel Sambuc */
3307f4a2713aSLionel Sambuc 
3308f4a2713aSLionel Sambuc /// GetMethodConstant - Return a struct objc_method constant for the
3309f4a2713aSLionel Sambuc /// given method if it has been defined. The result is null if the
3310f4a2713aSLionel Sambuc /// method has not been defined. The return value has type MethodPtrTy.
GetMethodConstant(const ObjCMethodDecl * MD)3311f4a2713aSLionel Sambuc llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
3312f4a2713aSLionel Sambuc   llvm::Function *Fn = GetMethodDefinition(MD);
3313f4a2713aSLionel Sambuc   if (!Fn)
3314*0a6a1f1dSLionel Sambuc     return nullptr;
3315f4a2713aSLionel Sambuc 
3316f4a2713aSLionel Sambuc   llvm::Constant *Method[] = {
3317f4a2713aSLionel Sambuc     llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
3318f4a2713aSLionel Sambuc                                    ObjCTypes.SelectorPtrTy),
3319f4a2713aSLionel Sambuc     GetMethodVarType(MD),
3320f4a2713aSLionel Sambuc     llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy)
3321f4a2713aSLionel Sambuc   };
3322f4a2713aSLionel Sambuc   return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
3323f4a2713aSLionel Sambuc }
3324f4a2713aSLionel Sambuc 
EmitMethodList(Twine Name,const char * Section,ArrayRef<llvm::Constant * > Methods)3325f4a2713aSLionel Sambuc llvm::Constant *CGObjCMac::EmitMethodList(Twine Name,
3326f4a2713aSLionel Sambuc                                           const char *Section,
3327f4a2713aSLionel Sambuc                                           ArrayRef<llvm::Constant*> Methods) {
3328f4a2713aSLionel Sambuc   // Return null for empty list.
3329f4a2713aSLionel Sambuc   if (Methods.empty())
3330f4a2713aSLionel Sambuc     return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy);
3331f4a2713aSLionel Sambuc 
3332f4a2713aSLionel Sambuc   llvm::Constant *Values[3];
3333f4a2713aSLionel Sambuc   Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
3334f4a2713aSLionel Sambuc   Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
3335f4a2713aSLionel Sambuc   llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
3336f4a2713aSLionel Sambuc                                              Methods.size());
3337f4a2713aSLionel Sambuc   Values[2] = llvm::ConstantArray::get(AT, Methods);
3338f4a2713aSLionel Sambuc   llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
3339f4a2713aSLionel Sambuc 
3340f4a2713aSLionel Sambuc   llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
3341f4a2713aSLionel Sambuc   return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListPtrTy);
3342f4a2713aSLionel Sambuc }
3343f4a2713aSLionel Sambuc 
GenerateMethod(const ObjCMethodDecl * OMD,const ObjCContainerDecl * CD)3344f4a2713aSLionel Sambuc llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
3345f4a2713aSLionel Sambuc                                                 const ObjCContainerDecl *CD) {
3346f4a2713aSLionel Sambuc   SmallString<256> Name;
3347f4a2713aSLionel Sambuc   GetNameForMethod(OMD, CD, Name);
3348f4a2713aSLionel Sambuc 
3349f4a2713aSLionel Sambuc   CodeGenTypes &Types = CGM.getTypes();
3350f4a2713aSLionel Sambuc   llvm::FunctionType *MethodTy =
3351f4a2713aSLionel Sambuc     Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
3352f4a2713aSLionel Sambuc   llvm::Function *Method =
3353f4a2713aSLionel Sambuc     llvm::Function::Create(MethodTy,
3354f4a2713aSLionel Sambuc                            llvm::GlobalValue::InternalLinkage,
3355f4a2713aSLionel Sambuc                            Name.str(),
3356f4a2713aSLionel Sambuc                            &CGM.getModule());
3357f4a2713aSLionel Sambuc   MethodDefinitions.insert(std::make_pair(OMD, Method));
3358f4a2713aSLionel Sambuc 
3359f4a2713aSLionel Sambuc   return Method;
3360f4a2713aSLionel Sambuc }
3361f4a2713aSLionel Sambuc 
CreateMetadataVar(Twine Name,llvm::Constant * Init,StringRef Section,unsigned Align,bool AddToUsed)3362*0a6a1f1dSLionel Sambuc llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
3363f4a2713aSLionel Sambuc                                                          llvm::Constant *Init,
3364*0a6a1f1dSLionel Sambuc                                                          StringRef Section,
3365f4a2713aSLionel Sambuc                                                          unsigned Align,
3366f4a2713aSLionel Sambuc                                                          bool AddToUsed) {
3367f4a2713aSLionel Sambuc   llvm::Type *Ty = Init->getType();
3368f4a2713aSLionel Sambuc   llvm::GlobalVariable *GV =
3369f4a2713aSLionel Sambuc     new llvm::GlobalVariable(CGM.getModule(), Ty, false,
3370*0a6a1f1dSLionel Sambuc                              llvm::GlobalValue::PrivateLinkage, Init, Name);
3371*0a6a1f1dSLionel Sambuc   if (!Section.empty())
3372f4a2713aSLionel Sambuc     GV->setSection(Section);
3373f4a2713aSLionel Sambuc   if (Align)
3374f4a2713aSLionel Sambuc     GV->setAlignment(Align);
3375f4a2713aSLionel Sambuc   if (AddToUsed)
3376*0a6a1f1dSLionel Sambuc     CGM.addCompilerUsedGlobal(GV);
3377f4a2713aSLionel Sambuc   return GV;
3378f4a2713aSLionel Sambuc }
3379f4a2713aSLionel Sambuc 
ModuleInitFunction()3380f4a2713aSLionel Sambuc llvm::Function *CGObjCMac::ModuleInitFunction() {
3381f4a2713aSLionel Sambuc   // Abuse this interface function as a place to finalize.
3382f4a2713aSLionel Sambuc   FinishModule();
3383*0a6a1f1dSLionel Sambuc   return nullptr;
3384f4a2713aSLionel Sambuc }
3385f4a2713aSLionel Sambuc 
GetPropertyGetFunction()3386f4a2713aSLionel Sambuc llvm::Constant *CGObjCMac::GetPropertyGetFunction() {
3387f4a2713aSLionel Sambuc   return ObjCTypes.getGetPropertyFn();
3388f4a2713aSLionel Sambuc }
3389f4a2713aSLionel Sambuc 
GetPropertySetFunction()3390f4a2713aSLionel Sambuc llvm::Constant *CGObjCMac::GetPropertySetFunction() {
3391f4a2713aSLionel Sambuc   return ObjCTypes.getSetPropertyFn();
3392f4a2713aSLionel Sambuc }
3393f4a2713aSLionel Sambuc 
GetOptimizedPropertySetFunction(bool atomic,bool copy)3394f4a2713aSLionel Sambuc llvm::Constant *CGObjCMac::GetOptimizedPropertySetFunction(bool atomic,
3395f4a2713aSLionel Sambuc                                                            bool copy) {
3396f4a2713aSLionel Sambuc   return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
3397f4a2713aSLionel Sambuc }
3398f4a2713aSLionel Sambuc 
GetGetStructFunction()3399f4a2713aSLionel Sambuc llvm::Constant *CGObjCMac::GetGetStructFunction() {
3400f4a2713aSLionel Sambuc   return ObjCTypes.getCopyStructFn();
3401f4a2713aSLionel Sambuc }
GetSetStructFunction()3402f4a2713aSLionel Sambuc llvm::Constant *CGObjCMac::GetSetStructFunction() {
3403f4a2713aSLionel Sambuc   return ObjCTypes.getCopyStructFn();
3404f4a2713aSLionel Sambuc }
3405f4a2713aSLionel Sambuc 
GetCppAtomicObjectGetFunction()3406f4a2713aSLionel Sambuc llvm::Constant *CGObjCMac::GetCppAtomicObjectGetFunction() {
3407f4a2713aSLionel Sambuc   return ObjCTypes.getCppAtomicObjectFunction();
3408f4a2713aSLionel Sambuc }
GetCppAtomicObjectSetFunction()3409f4a2713aSLionel Sambuc llvm::Constant *CGObjCMac::GetCppAtomicObjectSetFunction() {
3410f4a2713aSLionel Sambuc   return ObjCTypes.getCppAtomicObjectFunction();
3411f4a2713aSLionel Sambuc }
3412f4a2713aSLionel Sambuc 
EnumerationMutationFunction()3413f4a2713aSLionel Sambuc llvm::Constant *CGObjCMac::EnumerationMutationFunction() {
3414f4a2713aSLionel Sambuc   return ObjCTypes.getEnumerationMutationFn();
3415f4a2713aSLionel Sambuc }
3416f4a2713aSLionel Sambuc 
EmitTryStmt(CodeGenFunction & CGF,const ObjCAtTryStmt & S)3417f4a2713aSLionel Sambuc void CGObjCMac::EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S) {
3418f4a2713aSLionel Sambuc   return EmitTryOrSynchronizedStmt(CGF, S);
3419f4a2713aSLionel Sambuc }
3420f4a2713aSLionel Sambuc 
EmitSynchronizedStmt(CodeGenFunction & CGF,const ObjCAtSynchronizedStmt & S)3421f4a2713aSLionel Sambuc void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF,
3422f4a2713aSLionel Sambuc                                      const ObjCAtSynchronizedStmt &S) {
3423f4a2713aSLionel Sambuc   return EmitTryOrSynchronizedStmt(CGF, S);
3424f4a2713aSLionel Sambuc }
3425f4a2713aSLionel Sambuc 
3426f4a2713aSLionel Sambuc namespace {
3427f4a2713aSLionel Sambuc   struct PerformFragileFinally : EHScopeStack::Cleanup {
3428f4a2713aSLionel Sambuc     const Stmt &S;
3429f4a2713aSLionel Sambuc     llvm::Value *SyncArgSlot;
3430f4a2713aSLionel Sambuc     llvm::Value *CallTryExitVar;
3431f4a2713aSLionel Sambuc     llvm::Value *ExceptionData;
3432f4a2713aSLionel Sambuc     ObjCTypesHelper &ObjCTypes;
PerformFragileFinally__anon9749cc0a0311::PerformFragileFinally3433f4a2713aSLionel Sambuc     PerformFragileFinally(const Stmt *S,
3434f4a2713aSLionel Sambuc                           llvm::Value *SyncArgSlot,
3435f4a2713aSLionel Sambuc                           llvm::Value *CallTryExitVar,
3436f4a2713aSLionel Sambuc                           llvm::Value *ExceptionData,
3437f4a2713aSLionel Sambuc                           ObjCTypesHelper *ObjCTypes)
3438f4a2713aSLionel Sambuc       : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
3439f4a2713aSLionel Sambuc         ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
3440f4a2713aSLionel Sambuc 
Emit__anon9749cc0a0311::PerformFragileFinally3441*0a6a1f1dSLionel Sambuc     void Emit(CodeGenFunction &CGF, Flags flags) override {
3442f4a2713aSLionel Sambuc       // Check whether we need to call objc_exception_try_exit.
3443f4a2713aSLionel Sambuc       // In optimized code, this branch will always be folded.
3444f4a2713aSLionel Sambuc       llvm::BasicBlock *FinallyCallExit =
3445f4a2713aSLionel Sambuc         CGF.createBasicBlock("finally.call_exit");
3446f4a2713aSLionel Sambuc       llvm::BasicBlock *FinallyNoCallExit =
3447f4a2713aSLionel Sambuc         CGF.createBasicBlock("finally.no_call_exit");
3448f4a2713aSLionel Sambuc       CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar),
3449f4a2713aSLionel Sambuc                                FinallyCallExit, FinallyNoCallExit);
3450f4a2713aSLionel Sambuc 
3451f4a2713aSLionel Sambuc       CGF.EmitBlock(FinallyCallExit);
3452f4a2713aSLionel Sambuc       CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryExitFn(),
3453f4a2713aSLionel Sambuc                                   ExceptionData);
3454f4a2713aSLionel Sambuc 
3455f4a2713aSLionel Sambuc       CGF.EmitBlock(FinallyNoCallExit);
3456f4a2713aSLionel Sambuc 
3457f4a2713aSLionel Sambuc       if (isa<ObjCAtTryStmt>(S)) {
3458f4a2713aSLionel Sambuc         if (const ObjCAtFinallyStmt* FinallyStmt =
3459f4a2713aSLionel Sambuc               cast<ObjCAtTryStmt>(S).getFinallyStmt()) {
3460f4a2713aSLionel Sambuc           // Don't try to do the @finally if this is an EH cleanup.
3461f4a2713aSLionel Sambuc           if (flags.isForEHCleanup()) return;
3462f4a2713aSLionel Sambuc 
3463f4a2713aSLionel Sambuc           // Save the current cleanup destination in case there's
3464f4a2713aSLionel Sambuc           // control flow inside the finally statement.
3465f4a2713aSLionel Sambuc           llvm::Value *CurCleanupDest =
3466f4a2713aSLionel Sambuc             CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot());
3467f4a2713aSLionel Sambuc 
3468f4a2713aSLionel Sambuc           CGF.EmitStmt(FinallyStmt->getFinallyBody());
3469f4a2713aSLionel Sambuc 
3470f4a2713aSLionel Sambuc           if (CGF.HaveInsertPoint()) {
3471f4a2713aSLionel Sambuc             CGF.Builder.CreateStore(CurCleanupDest,
3472f4a2713aSLionel Sambuc                                     CGF.getNormalCleanupDestSlot());
3473f4a2713aSLionel Sambuc           } else {
3474f4a2713aSLionel Sambuc             // Currently, the end of the cleanup must always exist.
3475f4a2713aSLionel Sambuc             CGF.EnsureInsertPoint();
3476f4a2713aSLionel Sambuc           }
3477f4a2713aSLionel Sambuc         }
3478f4a2713aSLionel Sambuc       } else {
3479f4a2713aSLionel Sambuc         // Emit objc_sync_exit(expr); as finally's sole statement for
3480f4a2713aSLionel Sambuc         // @synchronized.
3481f4a2713aSLionel Sambuc         llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot);
3482f4a2713aSLionel Sambuc         CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncExitFn(), SyncArg);
3483f4a2713aSLionel Sambuc       }
3484f4a2713aSLionel Sambuc     }
3485f4a2713aSLionel Sambuc   };
3486f4a2713aSLionel Sambuc 
3487f4a2713aSLionel Sambuc   class FragileHazards {
3488f4a2713aSLionel Sambuc     CodeGenFunction &CGF;
3489f4a2713aSLionel Sambuc     SmallVector<llvm::Value*, 20> Locals;
3490f4a2713aSLionel Sambuc     llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry;
3491f4a2713aSLionel Sambuc 
3492f4a2713aSLionel Sambuc     llvm::InlineAsm *ReadHazard;
3493f4a2713aSLionel Sambuc     llvm::InlineAsm *WriteHazard;
3494f4a2713aSLionel Sambuc 
3495f4a2713aSLionel Sambuc     llvm::FunctionType *GetAsmFnType();
3496f4a2713aSLionel Sambuc 
3497f4a2713aSLionel Sambuc     void collectLocals();
3498f4a2713aSLionel Sambuc     void emitReadHazard(CGBuilderTy &Builder);
3499f4a2713aSLionel Sambuc 
3500f4a2713aSLionel Sambuc   public:
3501f4a2713aSLionel Sambuc     FragileHazards(CodeGenFunction &CGF);
3502f4a2713aSLionel Sambuc 
3503f4a2713aSLionel Sambuc     void emitWriteHazard();
3504f4a2713aSLionel Sambuc     void emitHazardsInNewBlocks();
3505f4a2713aSLionel Sambuc   };
3506f4a2713aSLionel Sambuc }
3507f4a2713aSLionel Sambuc 
3508f4a2713aSLionel Sambuc /// Create the fragile-ABI read and write hazards based on the current
3509f4a2713aSLionel Sambuc /// state of the function, which is presumed to be immediately prior
3510f4a2713aSLionel Sambuc /// to a @try block.  These hazards are used to maintain correct
3511f4a2713aSLionel Sambuc /// semantics in the face of optimization and the fragile ABI's
3512f4a2713aSLionel Sambuc /// cavalier use of setjmp/longjmp.
FragileHazards(CodeGenFunction & CGF)3513f4a2713aSLionel Sambuc FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) {
3514f4a2713aSLionel Sambuc   collectLocals();
3515f4a2713aSLionel Sambuc 
3516f4a2713aSLionel Sambuc   if (Locals.empty()) return;
3517f4a2713aSLionel Sambuc 
3518f4a2713aSLionel Sambuc   // Collect all the blocks in the function.
3519f4a2713aSLionel Sambuc   for (llvm::Function::iterator
3520f4a2713aSLionel Sambuc          I = CGF.CurFn->begin(), E = CGF.CurFn->end(); I != E; ++I)
3521f4a2713aSLionel Sambuc     BlocksBeforeTry.insert(&*I);
3522f4a2713aSLionel Sambuc 
3523f4a2713aSLionel Sambuc   llvm::FunctionType *AsmFnTy = GetAsmFnType();
3524f4a2713aSLionel Sambuc 
3525f4a2713aSLionel Sambuc   // Create a read hazard for the allocas.  This inhibits dead-store
3526f4a2713aSLionel Sambuc   // optimizations and forces the values to memory.  This hazard is
3527f4a2713aSLionel Sambuc   // inserted before any 'throwing' calls in the protected scope to
3528f4a2713aSLionel Sambuc   // reflect the possibility that the variables might be read from the
3529f4a2713aSLionel Sambuc   // catch block if the call throws.
3530f4a2713aSLionel Sambuc   {
3531f4a2713aSLionel Sambuc     std::string Constraint;
3532f4a2713aSLionel Sambuc     for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
3533f4a2713aSLionel Sambuc       if (I) Constraint += ',';
3534f4a2713aSLionel Sambuc       Constraint += "*m";
3535f4a2713aSLionel Sambuc     }
3536f4a2713aSLionel Sambuc 
3537f4a2713aSLionel Sambuc     ReadHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
3538f4a2713aSLionel Sambuc   }
3539f4a2713aSLionel Sambuc 
3540f4a2713aSLionel Sambuc   // Create a write hazard for the allocas.  This inhibits folding
3541f4a2713aSLionel Sambuc   // loads across the hazard.  This hazard is inserted at the
3542f4a2713aSLionel Sambuc   // beginning of the catch path to reflect the possibility that the
3543f4a2713aSLionel Sambuc   // variables might have been written within the protected scope.
3544f4a2713aSLionel Sambuc   {
3545f4a2713aSLionel Sambuc     std::string Constraint;
3546f4a2713aSLionel Sambuc     for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
3547f4a2713aSLionel Sambuc       if (I) Constraint += ',';
3548f4a2713aSLionel Sambuc       Constraint += "=*m";
3549f4a2713aSLionel Sambuc     }
3550f4a2713aSLionel Sambuc 
3551f4a2713aSLionel Sambuc     WriteHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
3552f4a2713aSLionel Sambuc   }
3553f4a2713aSLionel Sambuc }
3554f4a2713aSLionel Sambuc 
3555f4a2713aSLionel Sambuc /// Emit a write hazard at the current location.
emitWriteHazard()3556f4a2713aSLionel Sambuc void FragileHazards::emitWriteHazard() {
3557f4a2713aSLionel Sambuc   if (Locals.empty()) return;
3558f4a2713aSLionel Sambuc 
3559f4a2713aSLionel Sambuc   CGF.EmitNounwindRuntimeCall(WriteHazard, Locals);
3560f4a2713aSLionel Sambuc }
3561f4a2713aSLionel Sambuc 
emitReadHazard(CGBuilderTy & Builder)3562f4a2713aSLionel Sambuc void FragileHazards::emitReadHazard(CGBuilderTy &Builder) {
3563f4a2713aSLionel Sambuc   assert(!Locals.empty());
3564f4a2713aSLionel Sambuc   llvm::CallInst *call = Builder.CreateCall(ReadHazard, Locals);
3565f4a2713aSLionel Sambuc   call->setDoesNotThrow();
3566f4a2713aSLionel Sambuc   call->setCallingConv(CGF.getRuntimeCC());
3567f4a2713aSLionel Sambuc }
3568f4a2713aSLionel Sambuc 
3569f4a2713aSLionel Sambuc /// Emit read hazards in all the protected blocks, i.e. all the blocks
3570f4a2713aSLionel Sambuc /// which have been inserted since the beginning of the try.
emitHazardsInNewBlocks()3571f4a2713aSLionel Sambuc void FragileHazards::emitHazardsInNewBlocks() {
3572f4a2713aSLionel Sambuc   if (Locals.empty()) return;
3573f4a2713aSLionel Sambuc 
3574f4a2713aSLionel Sambuc   CGBuilderTy Builder(CGF.getLLVMContext());
3575f4a2713aSLionel Sambuc 
3576f4a2713aSLionel Sambuc   // Iterate through all blocks, skipping those prior to the try.
3577f4a2713aSLionel Sambuc   for (llvm::Function::iterator
3578f4a2713aSLionel Sambuc          FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); FI != FE; ++FI) {
3579f4a2713aSLionel Sambuc     llvm::BasicBlock &BB = *FI;
3580f4a2713aSLionel Sambuc     if (BlocksBeforeTry.count(&BB)) continue;
3581f4a2713aSLionel Sambuc 
3582f4a2713aSLionel Sambuc     // Walk through all the calls in the block.
3583f4a2713aSLionel Sambuc     for (llvm::BasicBlock::iterator
3584f4a2713aSLionel Sambuc            BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) {
3585f4a2713aSLionel Sambuc       llvm::Instruction &I = *BI;
3586f4a2713aSLionel Sambuc 
3587f4a2713aSLionel Sambuc       // Ignore instructions that aren't non-intrinsic calls.
3588f4a2713aSLionel Sambuc       // These are the only calls that can possibly call longjmp.
3589f4a2713aSLionel Sambuc       if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I)) continue;
3590f4a2713aSLionel Sambuc       if (isa<llvm::IntrinsicInst>(I))
3591f4a2713aSLionel Sambuc         continue;
3592f4a2713aSLionel Sambuc 
3593f4a2713aSLionel Sambuc       // Ignore call sites marked nounwind.  This may be questionable,
3594f4a2713aSLionel Sambuc       // since 'nounwind' doesn't necessarily mean 'does not call longjmp'.
3595f4a2713aSLionel Sambuc       llvm::CallSite CS(&I);
3596f4a2713aSLionel Sambuc       if (CS.doesNotThrow()) continue;
3597f4a2713aSLionel Sambuc 
3598f4a2713aSLionel Sambuc       // Insert a read hazard before the call.  This will ensure that
3599f4a2713aSLionel Sambuc       // any writes to the locals are performed before making the
3600f4a2713aSLionel Sambuc       // call.  If the call throws, then this is sufficient to
3601f4a2713aSLionel Sambuc       // guarantee correctness as long as it doesn't also write to any
3602f4a2713aSLionel Sambuc       // locals.
3603f4a2713aSLionel Sambuc       Builder.SetInsertPoint(&BB, BI);
3604f4a2713aSLionel Sambuc       emitReadHazard(Builder);
3605f4a2713aSLionel Sambuc     }
3606f4a2713aSLionel Sambuc   }
3607f4a2713aSLionel Sambuc }
3608f4a2713aSLionel Sambuc 
addIfPresent(llvm::DenseSet<llvm::Value * > & S,llvm::Value * V)3609f4a2713aSLionel Sambuc static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, llvm::Value *V) {
3610f4a2713aSLionel Sambuc   if (V) S.insert(V);
3611f4a2713aSLionel Sambuc }
3612f4a2713aSLionel Sambuc 
collectLocals()3613f4a2713aSLionel Sambuc void FragileHazards::collectLocals() {
3614f4a2713aSLionel Sambuc   // Compute a set of allocas to ignore.
3615f4a2713aSLionel Sambuc   llvm::DenseSet<llvm::Value*> AllocasToIgnore;
3616f4a2713aSLionel Sambuc   addIfPresent(AllocasToIgnore, CGF.ReturnValue);
3617f4a2713aSLionel Sambuc   addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest);
3618f4a2713aSLionel Sambuc 
3619f4a2713aSLionel Sambuc   // Collect all the allocas currently in the function.  This is
3620f4a2713aSLionel Sambuc   // probably way too aggressive.
3621f4a2713aSLionel Sambuc   llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock();
3622f4a2713aSLionel Sambuc   for (llvm::BasicBlock::iterator
3623f4a2713aSLionel Sambuc          I = Entry.begin(), E = Entry.end(); I != E; ++I)
3624f4a2713aSLionel Sambuc     if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I))
3625f4a2713aSLionel Sambuc       Locals.push_back(&*I);
3626f4a2713aSLionel Sambuc }
3627f4a2713aSLionel Sambuc 
GetAsmFnType()3628f4a2713aSLionel Sambuc llvm::FunctionType *FragileHazards::GetAsmFnType() {
3629f4a2713aSLionel Sambuc   SmallVector<llvm::Type *, 16> tys(Locals.size());
3630f4a2713aSLionel Sambuc   for (unsigned i = 0, e = Locals.size(); i != e; ++i)
3631f4a2713aSLionel Sambuc     tys[i] = Locals[i]->getType();
3632f4a2713aSLionel Sambuc   return llvm::FunctionType::get(CGF.VoidTy, tys, false);
3633f4a2713aSLionel Sambuc }
3634f4a2713aSLionel Sambuc 
3635f4a2713aSLionel Sambuc /*
3636f4a2713aSLionel Sambuc 
3637f4a2713aSLionel Sambuc   Objective-C setjmp-longjmp (sjlj) Exception Handling
3638f4a2713aSLionel Sambuc   --
3639f4a2713aSLionel Sambuc 
3640f4a2713aSLionel Sambuc   A catch buffer is a setjmp buffer plus:
3641f4a2713aSLionel Sambuc     - a pointer to the exception that was caught
3642f4a2713aSLionel Sambuc     - a pointer to the previous exception data buffer
3643f4a2713aSLionel Sambuc     - two pointers of reserved storage
3644f4a2713aSLionel Sambuc   Therefore catch buffers form a stack, with a pointer to the top
3645f4a2713aSLionel Sambuc   of the stack kept in thread-local storage.
3646f4a2713aSLionel Sambuc 
3647f4a2713aSLionel Sambuc   objc_exception_try_enter pushes a catch buffer onto the EH stack.
3648f4a2713aSLionel Sambuc   objc_exception_try_exit pops the given catch buffer, which is
3649f4a2713aSLionel Sambuc     required to be the top of the EH stack.
3650f4a2713aSLionel Sambuc   objc_exception_throw pops the top of the EH stack, writes the
3651f4a2713aSLionel Sambuc     thrown exception into the appropriate field, and longjmps
3652f4a2713aSLionel Sambuc     to the setjmp buffer.  It crashes the process (with a printf
3653f4a2713aSLionel Sambuc     and an abort()) if there are no catch buffers on the stack.
3654f4a2713aSLionel Sambuc   objc_exception_extract just reads the exception pointer out of the
3655f4a2713aSLionel Sambuc     catch buffer.
3656f4a2713aSLionel Sambuc 
3657f4a2713aSLionel Sambuc   There's no reason an implementation couldn't use a light-weight
3658f4a2713aSLionel Sambuc   setjmp here --- something like __builtin_setjmp, but API-compatible
3659f4a2713aSLionel Sambuc   with the heavyweight setjmp.  This will be more important if we ever
3660f4a2713aSLionel Sambuc   want to implement correct ObjC/C++ exception interactions for the
3661f4a2713aSLionel Sambuc   fragile ABI.
3662f4a2713aSLionel Sambuc 
3663f4a2713aSLionel Sambuc   Note that for this use of setjmp/longjmp to be correct, we may need
3664f4a2713aSLionel Sambuc   to mark some local variables volatile: if a non-volatile local
3665f4a2713aSLionel Sambuc   variable is modified between the setjmp and the longjmp, it has
3666f4a2713aSLionel Sambuc   indeterminate value.  For the purposes of LLVM IR, it may be
3667f4a2713aSLionel Sambuc   sufficient to make loads and stores within the @try (to variables
3668f4a2713aSLionel Sambuc   declared outside the @try) volatile.  This is necessary for
3669f4a2713aSLionel Sambuc   optimized correctness, but is not currently being done; this is
3670f4a2713aSLionel Sambuc   being tracked as rdar://problem/8160285
3671f4a2713aSLionel Sambuc 
3672f4a2713aSLionel Sambuc   The basic framework for a @try-catch-finally is as follows:
3673f4a2713aSLionel Sambuc   {
3674f4a2713aSLionel Sambuc   objc_exception_data d;
3675f4a2713aSLionel Sambuc   id _rethrow = null;
3676f4a2713aSLionel Sambuc   bool _call_try_exit = true;
3677f4a2713aSLionel Sambuc 
3678f4a2713aSLionel Sambuc   objc_exception_try_enter(&d);
3679f4a2713aSLionel Sambuc   if (!setjmp(d.jmp_buf)) {
3680f4a2713aSLionel Sambuc   ... try body ...
3681f4a2713aSLionel Sambuc   } else {
3682f4a2713aSLionel Sambuc   // exception path
3683f4a2713aSLionel Sambuc   id _caught = objc_exception_extract(&d);
3684f4a2713aSLionel Sambuc 
3685f4a2713aSLionel Sambuc   // enter new try scope for handlers
3686f4a2713aSLionel Sambuc   if (!setjmp(d.jmp_buf)) {
3687f4a2713aSLionel Sambuc   ... match exception and execute catch blocks ...
3688f4a2713aSLionel Sambuc 
3689f4a2713aSLionel Sambuc   // fell off end, rethrow.
3690f4a2713aSLionel Sambuc   _rethrow = _caught;
3691f4a2713aSLionel Sambuc   ... jump-through-finally to finally_rethrow ...
3692f4a2713aSLionel Sambuc   } else {
3693f4a2713aSLionel Sambuc   // exception in catch block
3694f4a2713aSLionel Sambuc   _rethrow = objc_exception_extract(&d);
3695f4a2713aSLionel Sambuc   _call_try_exit = false;
3696f4a2713aSLionel Sambuc   ... jump-through-finally to finally_rethrow ...
3697f4a2713aSLionel Sambuc   }
3698f4a2713aSLionel Sambuc   }
3699f4a2713aSLionel Sambuc   ... jump-through-finally to finally_end ...
3700f4a2713aSLionel Sambuc 
3701f4a2713aSLionel Sambuc   finally:
3702f4a2713aSLionel Sambuc   if (_call_try_exit)
3703f4a2713aSLionel Sambuc   objc_exception_try_exit(&d);
3704f4a2713aSLionel Sambuc 
3705f4a2713aSLionel Sambuc   ... finally block ....
3706f4a2713aSLionel Sambuc   ... dispatch to finally destination ...
3707f4a2713aSLionel Sambuc 
3708f4a2713aSLionel Sambuc   finally_rethrow:
3709f4a2713aSLionel Sambuc   objc_exception_throw(_rethrow);
3710f4a2713aSLionel Sambuc 
3711f4a2713aSLionel Sambuc   finally_end:
3712f4a2713aSLionel Sambuc   }
3713f4a2713aSLionel Sambuc 
3714f4a2713aSLionel Sambuc   This framework differs slightly from the one gcc uses, in that gcc
3715f4a2713aSLionel Sambuc   uses _rethrow to determine if objc_exception_try_exit should be called
3716f4a2713aSLionel Sambuc   and if the object should be rethrown. This breaks in the face of
3717f4a2713aSLionel Sambuc   throwing nil and introduces unnecessary branches.
3718f4a2713aSLionel Sambuc 
3719f4a2713aSLionel Sambuc   We specialize this framework for a few particular circumstances:
3720f4a2713aSLionel Sambuc 
3721f4a2713aSLionel Sambuc   - If there are no catch blocks, then we avoid emitting the second
3722f4a2713aSLionel Sambuc   exception handling context.
3723f4a2713aSLionel Sambuc 
3724f4a2713aSLionel Sambuc   - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
3725f4a2713aSLionel Sambuc   e)) we avoid emitting the code to rethrow an uncaught exception.
3726f4a2713aSLionel Sambuc 
3727f4a2713aSLionel Sambuc   - FIXME: If there is no @finally block we can do a few more
3728f4a2713aSLionel Sambuc   simplifications.
3729f4a2713aSLionel Sambuc 
3730f4a2713aSLionel Sambuc   Rethrows and Jumps-Through-Finally
3731f4a2713aSLionel Sambuc   --
3732f4a2713aSLionel Sambuc 
3733f4a2713aSLionel Sambuc   '@throw;' is supported by pushing the currently-caught exception
3734f4a2713aSLionel Sambuc   onto ObjCEHStack while the @catch blocks are emitted.
3735f4a2713aSLionel Sambuc 
3736f4a2713aSLionel Sambuc   Branches through the @finally block are handled with an ordinary
3737f4a2713aSLionel Sambuc   normal cleanup.  We do not register an EH cleanup; fragile-ABI ObjC
3738f4a2713aSLionel Sambuc   exceptions are not compatible with C++ exceptions, and this is
3739f4a2713aSLionel Sambuc   hardly the only place where this will go wrong.
3740f4a2713aSLionel Sambuc 
3741f4a2713aSLionel Sambuc   @synchronized(expr) { stmt; } is emitted as if it were:
3742f4a2713aSLionel Sambuc     id synch_value = expr;
3743f4a2713aSLionel Sambuc     objc_sync_enter(synch_value);
3744f4a2713aSLionel Sambuc     @try { stmt; } @finally { objc_sync_exit(synch_value); }
3745f4a2713aSLionel Sambuc */
3746f4a2713aSLionel Sambuc 
EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction & CGF,const Stmt & S)3747f4a2713aSLionel Sambuc void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
3748f4a2713aSLionel Sambuc                                           const Stmt &S) {
3749f4a2713aSLionel Sambuc   bool isTry = isa<ObjCAtTryStmt>(S);
3750f4a2713aSLionel Sambuc 
3751f4a2713aSLionel Sambuc   // A destination for the fall-through edges of the catch handlers to
3752f4a2713aSLionel Sambuc   // jump to.
3753f4a2713aSLionel Sambuc   CodeGenFunction::JumpDest FinallyEnd =
3754f4a2713aSLionel Sambuc     CGF.getJumpDestInCurrentScope("finally.end");
3755f4a2713aSLionel Sambuc 
3756f4a2713aSLionel Sambuc   // A destination for the rethrow edge of the catch handlers to jump
3757f4a2713aSLionel Sambuc   // to.
3758f4a2713aSLionel Sambuc   CodeGenFunction::JumpDest FinallyRethrow =
3759f4a2713aSLionel Sambuc     CGF.getJumpDestInCurrentScope("finally.rethrow");
3760f4a2713aSLionel Sambuc 
3761f4a2713aSLionel Sambuc   // For @synchronized, call objc_sync_enter(sync.expr). The
3762f4a2713aSLionel Sambuc   // evaluation of the expression must occur before we enter the
3763f4a2713aSLionel Sambuc   // @synchronized.  We can't avoid a temp here because we need the
3764f4a2713aSLionel Sambuc   // value to be preserved.  If the backend ever does liveness
3765f4a2713aSLionel Sambuc   // correctly after setjmp, this will be unnecessary.
3766*0a6a1f1dSLionel Sambuc   llvm::Value *SyncArgSlot = nullptr;
3767f4a2713aSLionel Sambuc   if (!isTry) {
3768f4a2713aSLionel Sambuc     llvm::Value *SyncArg =
3769f4a2713aSLionel Sambuc       CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
3770f4a2713aSLionel Sambuc     SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
3771f4a2713aSLionel Sambuc     CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncEnterFn(), SyncArg);
3772f4a2713aSLionel Sambuc 
3773f4a2713aSLionel Sambuc     SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(), "sync.arg");
3774f4a2713aSLionel Sambuc     CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
3775f4a2713aSLionel Sambuc   }
3776f4a2713aSLionel Sambuc 
3777f4a2713aSLionel Sambuc   // Allocate memory for the setjmp buffer.  This needs to be kept
3778f4a2713aSLionel Sambuc   // live throughout the try and catch blocks.
3779f4a2713aSLionel Sambuc   llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
3780f4a2713aSLionel Sambuc                                                     "exceptiondata.ptr");
3781f4a2713aSLionel Sambuc 
3782f4a2713aSLionel Sambuc   // Create the fragile hazards.  Note that this will not capture any
3783f4a2713aSLionel Sambuc   // of the allocas required for exception processing, but will
3784f4a2713aSLionel Sambuc   // capture the current basic block (which extends all the way to the
3785f4a2713aSLionel Sambuc   // setjmp call) as "before the @try".
3786f4a2713aSLionel Sambuc   FragileHazards Hazards(CGF);
3787f4a2713aSLionel Sambuc 
3788f4a2713aSLionel Sambuc   // Create a flag indicating whether the cleanup needs to call
3789f4a2713aSLionel Sambuc   // objc_exception_try_exit.  This is true except when
3790f4a2713aSLionel Sambuc   //   - no catches match and we're branching through the cleanup
3791f4a2713aSLionel Sambuc   //     just to rethrow the exception, or
3792f4a2713aSLionel Sambuc   //   - a catch matched and we're falling out of the catch handler.
3793f4a2713aSLionel Sambuc   // The setjmp-safety rule here is that we should always store to this
3794f4a2713aSLionel Sambuc   // variable in a place that dominates the branch through the cleanup
3795f4a2713aSLionel Sambuc   // without passing through any setjmps.
3796f4a2713aSLionel Sambuc   llvm::Value *CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
3797f4a2713aSLionel Sambuc                                                      "_call_try_exit");
3798f4a2713aSLionel Sambuc 
3799f4a2713aSLionel Sambuc   // A slot containing the exception to rethrow.  Only needed when we
3800f4a2713aSLionel Sambuc   // have both a @catch and a @finally.
3801*0a6a1f1dSLionel Sambuc   llvm::Value *PropagatingExnVar = nullptr;
3802f4a2713aSLionel Sambuc 
3803f4a2713aSLionel Sambuc   // Push a normal cleanup to leave the try scope.
3804f4a2713aSLionel Sambuc   CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalAndEHCleanup, &S,
3805f4a2713aSLionel Sambuc                                                  SyncArgSlot,
3806f4a2713aSLionel Sambuc                                                  CallTryExitVar,
3807f4a2713aSLionel Sambuc                                                  ExceptionData,
3808f4a2713aSLionel Sambuc                                                  &ObjCTypes);
3809f4a2713aSLionel Sambuc 
3810f4a2713aSLionel Sambuc   // Enter a try block:
3811f4a2713aSLionel Sambuc   //  - Call objc_exception_try_enter to push ExceptionData on top of
3812f4a2713aSLionel Sambuc   //    the EH stack.
3813f4a2713aSLionel Sambuc   CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData);
3814f4a2713aSLionel Sambuc 
3815f4a2713aSLionel Sambuc   //  - Call setjmp on the exception data buffer.
3816f4a2713aSLionel Sambuc   llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
3817f4a2713aSLionel Sambuc   llvm::Value *GEPIndexes[] = { Zero, Zero, Zero };
3818f4a2713aSLionel Sambuc   llvm::Value *SetJmpBuffer =
3819f4a2713aSLionel Sambuc     CGF.Builder.CreateGEP(ExceptionData, GEPIndexes, "setjmp_buffer");
3820f4a2713aSLionel Sambuc   llvm::CallInst *SetJmpResult =
3821f4a2713aSLionel Sambuc     CGF.EmitNounwindRuntimeCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result");
3822f4a2713aSLionel Sambuc   SetJmpResult->setCanReturnTwice();
3823f4a2713aSLionel Sambuc 
3824f4a2713aSLionel Sambuc   // If setjmp returned 0, enter the protected block; otherwise,
3825f4a2713aSLionel Sambuc   // branch to the handler.
3826f4a2713aSLionel Sambuc   llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
3827f4a2713aSLionel Sambuc   llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
3828f4a2713aSLionel Sambuc   llvm::Value *DidCatch =
3829f4a2713aSLionel Sambuc     CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
3830f4a2713aSLionel Sambuc   CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
3831f4a2713aSLionel Sambuc 
3832f4a2713aSLionel Sambuc   // Emit the protected block.
3833f4a2713aSLionel Sambuc   CGF.EmitBlock(TryBlock);
3834f4a2713aSLionel Sambuc   CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
3835f4a2713aSLionel Sambuc   CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
3836f4a2713aSLionel Sambuc                      : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
3837f4a2713aSLionel Sambuc 
3838f4a2713aSLionel Sambuc   CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP();
3839f4a2713aSLionel Sambuc 
3840f4a2713aSLionel Sambuc   // Emit the exception handler block.
3841f4a2713aSLionel Sambuc   CGF.EmitBlock(TryHandler);
3842f4a2713aSLionel Sambuc 
3843f4a2713aSLionel Sambuc   // Don't optimize loads of the in-scope locals across this point.
3844f4a2713aSLionel Sambuc   Hazards.emitWriteHazard();
3845f4a2713aSLionel Sambuc 
3846f4a2713aSLionel Sambuc   // For a @synchronized (or a @try with no catches), just branch
3847f4a2713aSLionel Sambuc   // through the cleanup to the rethrow block.
3848f4a2713aSLionel Sambuc   if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
3849f4a2713aSLionel Sambuc     // Tell the cleanup not to re-pop the exit.
3850f4a2713aSLionel Sambuc     CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
3851f4a2713aSLionel Sambuc     CGF.EmitBranchThroughCleanup(FinallyRethrow);
3852f4a2713aSLionel Sambuc 
3853f4a2713aSLionel Sambuc   // Otherwise, we have to match against the caught exceptions.
3854f4a2713aSLionel Sambuc   } else {
3855f4a2713aSLionel Sambuc     // Retrieve the exception object.  We may emit multiple blocks but
3856f4a2713aSLionel Sambuc     // nothing can cross this so the value is already in SSA form.
3857f4a2713aSLionel Sambuc     llvm::CallInst *Caught =
3858f4a2713aSLionel Sambuc       CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(),
3859f4a2713aSLionel Sambuc                                   ExceptionData, "caught");
3860f4a2713aSLionel Sambuc 
3861f4a2713aSLionel Sambuc     // Push the exception to rethrow onto the EH value stack for the
3862f4a2713aSLionel Sambuc     // benefit of any @throws in the handlers.
3863f4a2713aSLionel Sambuc     CGF.ObjCEHValueStack.push_back(Caught);
3864f4a2713aSLionel Sambuc 
3865f4a2713aSLionel Sambuc     const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S);
3866f4a2713aSLionel Sambuc 
3867*0a6a1f1dSLionel Sambuc     bool HasFinally = (AtTryStmt->getFinallyStmt() != nullptr);
3868f4a2713aSLionel Sambuc 
3869*0a6a1f1dSLionel Sambuc     llvm::BasicBlock *CatchBlock = nullptr;
3870*0a6a1f1dSLionel Sambuc     llvm::BasicBlock *CatchHandler = nullptr;
3871f4a2713aSLionel Sambuc     if (HasFinally) {
3872f4a2713aSLionel Sambuc       // Save the currently-propagating exception before
3873f4a2713aSLionel Sambuc       // objc_exception_try_enter clears the exception slot.
3874f4a2713aSLionel Sambuc       PropagatingExnVar = CGF.CreateTempAlloca(Caught->getType(),
3875f4a2713aSLionel Sambuc                                                "propagating_exception");
3876f4a2713aSLionel Sambuc       CGF.Builder.CreateStore(Caught, PropagatingExnVar);
3877f4a2713aSLionel Sambuc 
3878f4a2713aSLionel Sambuc       // Enter a new exception try block (in case a @catch block
3879f4a2713aSLionel Sambuc       // throws an exception).
3880f4a2713aSLionel Sambuc       CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(),
3881f4a2713aSLionel Sambuc                                   ExceptionData);
3882f4a2713aSLionel Sambuc 
3883f4a2713aSLionel Sambuc       llvm::CallInst *SetJmpResult =
3884f4a2713aSLionel Sambuc         CGF.EmitNounwindRuntimeCall(ObjCTypes.getSetJmpFn(),
3885f4a2713aSLionel Sambuc                                     SetJmpBuffer, "setjmp.result");
3886f4a2713aSLionel Sambuc       SetJmpResult->setCanReturnTwice();
3887f4a2713aSLionel Sambuc 
3888f4a2713aSLionel Sambuc       llvm::Value *Threw =
3889f4a2713aSLionel Sambuc         CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
3890f4a2713aSLionel Sambuc 
3891f4a2713aSLionel Sambuc       CatchBlock = CGF.createBasicBlock("catch");
3892f4a2713aSLionel Sambuc       CatchHandler = CGF.createBasicBlock("catch_for_catch");
3893f4a2713aSLionel Sambuc       CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
3894f4a2713aSLionel Sambuc 
3895f4a2713aSLionel Sambuc       CGF.EmitBlock(CatchBlock);
3896f4a2713aSLionel Sambuc     }
3897f4a2713aSLionel Sambuc 
3898f4a2713aSLionel Sambuc     CGF.Builder.CreateStore(CGF.Builder.getInt1(HasFinally), CallTryExitVar);
3899f4a2713aSLionel Sambuc 
3900f4a2713aSLionel Sambuc     // Handle catch list. As a special case we check if everything is
3901f4a2713aSLionel Sambuc     // matched and avoid generating code for falling off the end if
3902f4a2713aSLionel Sambuc     // so.
3903f4a2713aSLionel Sambuc     bool AllMatched = false;
3904f4a2713aSLionel Sambuc     for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) {
3905f4a2713aSLionel Sambuc       const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I);
3906f4a2713aSLionel Sambuc 
3907f4a2713aSLionel Sambuc       const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
3908*0a6a1f1dSLionel Sambuc       const ObjCObjectPointerType *OPT = nullptr;
3909f4a2713aSLionel Sambuc 
3910f4a2713aSLionel Sambuc       // catch(...) always matches.
3911f4a2713aSLionel Sambuc       if (!CatchParam) {
3912f4a2713aSLionel Sambuc         AllMatched = true;
3913f4a2713aSLionel Sambuc       } else {
3914f4a2713aSLionel Sambuc         OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
3915f4a2713aSLionel Sambuc 
3916f4a2713aSLionel Sambuc         // catch(id e) always matches under this ABI, since only
3917f4a2713aSLionel Sambuc         // ObjC exceptions end up here in the first place.
3918f4a2713aSLionel Sambuc         // FIXME: For the time being we also match id<X>; this should
3919f4a2713aSLionel Sambuc         // be rejected by Sema instead.
3920f4a2713aSLionel Sambuc         if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
3921f4a2713aSLionel Sambuc           AllMatched = true;
3922f4a2713aSLionel Sambuc       }
3923f4a2713aSLionel Sambuc 
3924f4a2713aSLionel Sambuc       // If this is a catch-all, we don't need to test anything.
3925f4a2713aSLionel Sambuc       if (AllMatched) {
3926f4a2713aSLionel Sambuc         CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
3927f4a2713aSLionel Sambuc 
3928f4a2713aSLionel Sambuc         if (CatchParam) {
3929f4a2713aSLionel Sambuc           CGF.EmitAutoVarDecl(*CatchParam);
3930f4a2713aSLionel Sambuc           assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
3931f4a2713aSLionel Sambuc 
3932f4a2713aSLionel Sambuc           // These types work out because ConvertType(id) == i8*.
3933f4a2713aSLionel Sambuc           CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam));
3934f4a2713aSLionel Sambuc         }
3935f4a2713aSLionel Sambuc 
3936f4a2713aSLionel Sambuc         CGF.EmitStmt(CatchStmt->getCatchBody());
3937f4a2713aSLionel Sambuc 
3938f4a2713aSLionel Sambuc         // The scope of the catch variable ends right here.
3939f4a2713aSLionel Sambuc         CatchVarCleanups.ForceCleanup();
3940f4a2713aSLionel Sambuc 
3941f4a2713aSLionel Sambuc         CGF.EmitBranchThroughCleanup(FinallyEnd);
3942f4a2713aSLionel Sambuc         break;
3943f4a2713aSLionel Sambuc       }
3944f4a2713aSLionel Sambuc 
3945f4a2713aSLionel Sambuc       assert(OPT && "Unexpected non-object pointer type in @catch");
3946f4a2713aSLionel Sambuc       const ObjCObjectType *ObjTy = OPT->getObjectType();
3947f4a2713aSLionel Sambuc 
3948f4a2713aSLionel Sambuc       // FIXME: @catch (Class c) ?
3949f4a2713aSLionel Sambuc       ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
3950f4a2713aSLionel Sambuc       assert(IDecl && "Catch parameter must have Objective-C type!");
3951f4a2713aSLionel Sambuc 
3952f4a2713aSLionel Sambuc       // Check if the @catch block matches the exception object.
3953f4a2713aSLionel Sambuc       llvm::Value *Class = EmitClassRef(CGF, IDecl);
3954f4a2713aSLionel Sambuc 
3955f4a2713aSLionel Sambuc       llvm::Value *matchArgs[] = { Class, Caught };
3956f4a2713aSLionel Sambuc       llvm::CallInst *Match =
3957f4a2713aSLionel Sambuc         CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionMatchFn(),
3958f4a2713aSLionel Sambuc                                     matchArgs, "match");
3959f4a2713aSLionel Sambuc 
3960f4a2713aSLionel Sambuc       llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match");
3961f4a2713aSLionel Sambuc       llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next");
3962f4a2713aSLionel Sambuc 
3963f4a2713aSLionel Sambuc       CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
3964f4a2713aSLionel Sambuc                                MatchedBlock, NextCatchBlock);
3965f4a2713aSLionel Sambuc 
3966f4a2713aSLionel Sambuc       // Emit the @catch block.
3967f4a2713aSLionel Sambuc       CGF.EmitBlock(MatchedBlock);
3968f4a2713aSLionel Sambuc 
3969f4a2713aSLionel Sambuc       // Collect any cleanups for the catch variable.  The scope lasts until
3970f4a2713aSLionel Sambuc       // the end of the catch body.
3971f4a2713aSLionel Sambuc       CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
3972f4a2713aSLionel Sambuc 
3973f4a2713aSLionel Sambuc       CGF.EmitAutoVarDecl(*CatchParam);
3974f4a2713aSLionel Sambuc       assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
3975f4a2713aSLionel Sambuc 
3976f4a2713aSLionel Sambuc       // Initialize the catch variable.
3977f4a2713aSLionel Sambuc       llvm::Value *Tmp =
3978f4a2713aSLionel Sambuc         CGF.Builder.CreateBitCast(Caught,
3979f4a2713aSLionel Sambuc                                   CGF.ConvertType(CatchParam->getType()));
3980f4a2713aSLionel Sambuc       CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam));
3981f4a2713aSLionel Sambuc 
3982f4a2713aSLionel Sambuc       CGF.EmitStmt(CatchStmt->getCatchBody());
3983f4a2713aSLionel Sambuc 
3984f4a2713aSLionel Sambuc       // We're done with the catch variable.
3985f4a2713aSLionel Sambuc       CatchVarCleanups.ForceCleanup();
3986f4a2713aSLionel Sambuc 
3987f4a2713aSLionel Sambuc       CGF.EmitBranchThroughCleanup(FinallyEnd);
3988f4a2713aSLionel Sambuc 
3989f4a2713aSLionel Sambuc       CGF.EmitBlock(NextCatchBlock);
3990f4a2713aSLionel Sambuc     }
3991f4a2713aSLionel Sambuc 
3992f4a2713aSLionel Sambuc     CGF.ObjCEHValueStack.pop_back();
3993f4a2713aSLionel Sambuc 
3994f4a2713aSLionel Sambuc     // If nothing wanted anything to do with the caught exception,
3995f4a2713aSLionel Sambuc     // kill the extract call.
3996f4a2713aSLionel Sambuc     if (Caught->use_empty())
3997f4a2713aSLionel Sambuc       Caught->eraseFromParent();
3998f4a2713aSLionel Sambuc 
3999f4a2713aSLionel Sambuc     if (!AllMatched)
4000f4a2713aSLionel Sambuc       CGF.EmitBranchThroughCleanup(FinallyRethrow);
4001f4a2713aSLionel Sambuc 
4002f4a2713aSLionel Sambuc     if (HasFinally) {
4003f4a2713aSLionel Sambuc       // Emit the exception handler for the @catch blocks.
4004f4a2713aSLionel Sambuc       CGF.EmitBlock(CatchHandler);
4005f4a2713aSLionel Sambuc 
4006f4a2713aSLionel Sambuc       // In theory we might now need a write hazard, but actually it's
4007f4a2713aSLionel Sambuc       // unnecessary because there's no local-accessing code between
4008f4a2713aSLionel Sambuc       // the try's write hazard and here.
4009f4a2713aSLionel Sambuc       //Hazards.emitWriteHazard();
4010f4a2713aSLionel Sambuc 
4011f4a2713aSLionel Sambuc       // Extract the new exception and save it to the
4012f4a2713aSLionel Sambuc       // propagating-exception slot.
4013f4a2713aSLionel Sambuc       assert(PropagatingExnVar);
4014f4a2713aSLionel Sambuc       llvm::CallInst *NewCaught =
4015f4a2713aSLionel Sambuc         CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(),
4016f4a2713aSLionel Sambuc                                     ExceptionData, "caught");
4017f4a2713aSLionel Sambuc       CGF.Builder.CreateStore(NewCaught, PropagatingExnVar);
4018f4a2713aSLionel Sambuc 
4019f4a2713aSLionel Sambuc       // Don't pop the catch handler; the throw already did.
4020f4a2713aSLionel Sambuc       CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
4021f4a2713aSLionel Sambuc       CGF.EmitBranchThroughCleanup(FinallyRethrow);
4022f4a2713aSLionel Sambuc     }
4023f4a2713aSLionel Sambuc   }
4024f4a2713aSLionel Sambuc 
4025f4a2713aSLionel Sambuc   // Insert read hazards as required in the new blocks.
4026f4a2713aSLionel Sambuc   Hazards.emitHazardsInNewBlocks();
4027f4a2713aSLionel Sambuc 
4028f4a2713aSLionel Sambuc   // Pop the cleanup.
4029f4a2713aSLionel Sambuc   CGF.Builder.restoreIP(TryFallthroughIP);
4030f4a2713aSLionel Sambuc   if (CGF.HaveInsertPoint())
4031f4a2713aSLionel Sambuc     CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
4032f4a2713aSLionel Sambuc   CGF.PopCleanupBlock();
4033f4a2713aSLionel Sambuc   CGF.EmitBlock(FinallyEnd.getBlock(), true);
4034f4a2713aSLionel Sambuc 
4035f4a2713aSLionel Sambuc   // Emit the rethrow block.
4036f4a2713aSLionel Sambuc   CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
4037f4a2713aSLionel Sambuc   CGF.EmitBlock(FinallyRethrow.getBlock(), true);
4038f4a2713aSLionel Sambuc   if (CGF.HaveInsertPoint()) {
4039f4a2713aSLionel Sambuc     // If we have a propagating-exception variable, check it.
4040f4a2713aSLionel Sambuc     llvm::Value *PropagatingExn;
4041f4a2713aSLionel Sambuc     if (PropagatingExnVar) {
4042f4a2713aSLionel Sambuc       PropagatingExn = CGF.Builder.CreateLoad(PropagatingExnVar);
4043f4a2713aSLionel Sambuc 
4044f4a2713aSLionel Sambuc     // Otherwise, just look in the buffer for the exception to throw.
4045f4a2713aSLionel Sambuc     } else {
4046f4a2713aSLionel Sambuc       llvm::CallInst *Caught =
4047f4a2713aSLionel Sambuc         CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(),
4048f4a2713aSLionel Sambuc                                     ExceptionData);
4049f4a2713aSLionel Sambuc       PropagatingExn = Caught;
4050f4a2713aSLionel Sambuc     }
4051f4a2713aSLionel Sambuc 
4052f4a2713aSLionel Sambuc     CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionThrowFn(),
4053f4a2713aSLionel Sambuc                                 PropagatingExn);
4054f4a2713aSLionel Sambuc     CGF.Builder.CreateUnreachable();
4055f4a2713aSLionel Sambuc   }
4056f4a2713aSLionel Sambuc 
4057f4a2713aSLionel Sambuc   CGF.Builder.restoreIP(SavedIP);
4058f4a2713aSLionel Sambuc }
4059f4a2713aSLionel Sambuc 
EmitThrowStmt(CodeGen::CodeGenFunction & CGF,const ObjCAtThrowStmt & S,bool ClearInsertionPoint)4060f4a2713aSLionel Sambuc void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
4061f4a2713aSLionel Sambuc                               const ObjCAtThrowStmt &S,
4062f4a2713aSLionel Sambuc                               bool ClearInsertionPoint) {
4063f4a2713aSLionel Sambuc   llvm::Value *ExceptionAsObject;
4064f4a2713aSLionel Sambuc 
4065f4a2713aSLionel Sambuc   if (const Expr *ThrowExpr = S.getThrowExpr()) {
4066f4a2713aSLionel Sambuc     llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
4067f4a2713aSLionel Sambuc     ExceptionAsObject =
4068f4a2713aSLionel Sambuc       CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
4069f4a2713aSLionel Sambuc   } else {
4070f4a2713aSLionel Sambuc     assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
4071f4a2713aSLionel Sambuc            "Unexpected rethrow outside @catch block.");
4072f4a2713aSLionel Sambuc     ExceptionAsObject = CGF.ObjCEHValueStack.back();
4073f4a2713aSLionel Sambuc   }
4074f4a2713aSLionel Sambuc 
4075f4a2713aSLionel Sambuc   CGF.EmitRuntimeCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
4076f4a2713aSLionel Sambuc     ->setDoesNotReturn();
4077f4a2713aSLionel Sambuc   CGF.Builder.CreateUnreachable();
4078f4a2713aSLionel Sambuc 
4079f4a2713aSLionel Sambuc   // Clear the insertion point to indicate we are in unreachable code.
4080f4a2713aSLionel Sambuc   if (ClearInsertionPoint)
4081f4a2713aSLionel Sambuc     CGF.Builder.ClearInsertionPoint();
4082f4a2713aSLionel Sambuc }
4083f4a2713aSLionel Sambuc 
4084f4a2713aSLionel Sambuc /// EmitObjCWeakRead - Code gen for loading value of a __weak
4085f4a2713aSLionel Sambuc /// object: objc_read_weak (id *src)
4086f4a2713aSLionel Sambuc ///
EmitObjCWeakRead(CodeGen::CodeGenFunction & CGF,llvm::Value * AddrWeakObj)4087f4a2713aSLionel Sambuc llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
4088f4a2713aSLionel Sambuc                                           llvm::Value *AddrWeakObj) {
4089f4a2713aSLionel Sambuc   llvm::Type* DestTy =
4090f4a2713aSLionel Sambuc     cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
4091f4a2713aSLionel Sambuc   AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
4092f4a2713aSLionel Sambuc                                           ObjCTypes.PtrObjectPtrTy);
4093f4a2713aSLionel Sambuc   llvm::Value *read_weak =
4094f4a2713aSLionel Sambuc     CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(),
4095f4a2713aSLionel Sambuc                                 AddrWeakObj, "weakread");
4096f4a2713aSLionel Sambuc   read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
4097f4a2713aSLionel Sambuc   return read_weak;
4098f4a2713aSLionel Sambuc }
4099f4a2713aSLionel Sambuc 
4100f4a2713aSLionel Sambuc /// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
4101f4a2713aSLionel Sambuc /// objc_assign_weak (id src, id *dst)
4102f4a2713aSLionel Sambuc ///
EmitObjCWeakAssign(CodeGen::CodeGenFunction & CGF,llvm::Value * src,llvm::Value * dst)4103f4a2713aSLionel Sambuc void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
4104f4a2713aSLionel Sambuc                                    llvm::Value *src, llvm::Value *dst) {
4105f4a2713aSLionel Sambuc   llvm::Type * SrcTy = src->getType();
4106f4a2713aSLionel Sambuc   if (!isa<llvm::PointerType>(SrcTy)) {
4107f4a2713aSLionel Sambuc     unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
4108f4a2713aSLionel Sambuc     assert(Size <= 8 && "does not support size > 8");
4109f4a2713aSLionel Sambuc     src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
4110f4a2713aSLionel Sambuc       : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
4111f4a2713aSLionel Sambuc     src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4112f4a2713aSLionel Sambuc   }
4113f4a2713aSLionel Sambuc   src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4114f4a2713aSLionel Sambuc   dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
4115f4a2713aSLionel Sambuc   llvm::Value *args[] = { src, dst };
4116f4a2713aSLionel Sambuc   CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(),
4117f4a2713aSLionel Sambuc                               args, "weakassign");
4118f4a2713aSLionel Sambuc   return;
4119f4a2713aSLionel Sambuc }
4120f4a2713aSLionel Sambuc 
4121f4a2713aSLionel Sambuc /// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
4122f4a2713aSLionel Sambuc /// objc_assign_global (id src, id *dst)
4123f4a2713aSLionel Sambuc ///
EmitObjCGlobalAssign(CodeGen::CodeGenFunction & CGF,llvm::Value * src,llvm::Value * dst,bool threadlocal)4124f4a2713aSLionel Sambuc void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
4125f4a2713aSLionel Sambuc                                      llvm::Value *src, llvm::Value *dst,
4126f4a2713aSLionel Sambuc                                      bool threadlocal) {
4127f4a2713aSLionel Sambuc   llvm::Type * SrcTy = src->getType();
4128f4a2713aSLionel Sambuc   if (!isa<llvm::PointerType>(SrcTy)) {
4129f4a2713aSLionel Sambuc     unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
4130f4a2713aSLionel Sambuc     assert(Size <= 8 && "does not support size > 8");
4131f4a2713aSLionel Sambuc     src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
4132f4a2713aSLionel Sambuc       : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
4133f4a2713aSLionel Sambuc     src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4134f4a2713aSLionel Sambuc   }
4135f4a2713aSLionel Sambuc   src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4136f4a2713aSLionel Sambuc   dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
4137f4a2713aSLionel Sambuc   llvm::Value *args[] = { src, dst };
4138f4a2713aSLionel Sambuc   if (!threadlocal)
4139f4a2713aSLionel Sambuc     CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(),
4140f4a2713aSLionel Sambuc                                 args, "globalassign");
4141f4a2713aSLionel Sambuc   else
4142f4a2713aSLionel Sambuc     CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(),
4143f4a2713aSLionel Sambuc                                 args, "threadlocalassign");
4144f4a2713aSLionel Sambuc   return;
4145f4a2713aSLionel Sambuc }
4146f4a2713aSLionel Sambuc 
4147f4a2713aSLionel Sambuc /// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
4148f4a2713aSLionel Sambuc /// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
4149f4a2713aSLionel Sambuc ///
EmitObjCIvarAssign(CodeGen::CodeGenFunction & CGF,llvm::Value * src,llvm::Value * dst,llvm::Value * ivarOffset)4150f4a2713aSLionel Sambuc void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
4151f4a2713aSLionel Sambuc                                    llvm::Value *src, llvm::Value *dst,
4152f4a2713aSLionel Sambuc                                    llvm::Value *ivarOffset) {
4153f4a2713aSLionel Sambuc   assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
4154f4a2713aSLionel Sambuc   llvm::Type * SrcTy = src->getType();
4155f4a2713aSLionel Sambuc   if (!isa<llvm::PointerType>(SrcTy)) {
4156f4a2713aSLionel Sambuc     unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
4157f4a2713aSLionel Sambuc     assert(Size <= 8 && "does not support size > 8");
4158f4a2713aSLionel Sambuc     src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
4159f4a2713aSLionel Sambuc       : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
4160f4a2713aSLionel Sambuc     src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4161f4a2713aSLionel Sambuc   }
4162f4a2713aSLionel Sambuc   src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4163f4a2713aSLionel Sambuc   dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
4164f4a2713aSLionel Sambuc   llvm::Value *args[] = { src, dst, ivarOffset };
4165f4a2713aSLionel Sambuc   CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
4166f4a2713aSLionel Sambuc   return;
4167f4a2713aSLionel Sambuc }
4168f4a2713aSLionel Sambuc 
4169f4a2713aSLionel Sambuc /// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
4170f4a2713aSLionel Sambuc /// objc_assign_strongCast (id src, id *dst)
4171f4a2713aSLionel Sambuc ///
EmitObjCStrongCastAssign(CodeGen::CodeGenFunction & CGF,llvm::Value * src,llvm::Value * dst)4172f4a2713aSLionel Sambuc void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
4173f4a2713aSLionel Sambuc                                          llvm::Value *src, llvm::Value *dst) {
4174f4a2713aSLionel Sambuc   llvm::Type * SrcTy = src->getType();
4175f4a2713aSLionel Sambuc   if (!isa<llvm::PointerType>(SrcTy)) {
4176f4a2713aSLionel Sambuc     unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
4177f4a2713aSLionel Sambuc     assert(Size <= 8 && "does not support size > 8");
4178f4a2713aSLionel Sambuc     src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
4179f4a2713aSLionel Sambuc       : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
4180f4a2713aSLionel Sambuc     src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4181f4a2713aSLionel Sambuc   }
4182f4a2713aSLionel Sambuc   src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4183f4a2713aSLionel Sambuc   dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
4184f4a2713aSLionel Sambuc   llvm::Value *args[] = { src, dst };
4185f4a2713aSLionel Sambuc   CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(),
4186f4a2713aSLionel Sambuc                               args, "weakassign");
4187f4a2713aSLionel Sambuc   return;
4188f4a2713aSLionel Sambuc }
4189f4a2713aSLionel Sambuc 
EmitGCMemmoveCollectable(CodeGen::CodeGenFunction & CGF,llvm::Value * DestPtr,llvm::Value * SrcPtr,llvm::Value * size)4190f4a2713aSLionel Sambuc void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
4191f4a2713aSLionel Sambuc                                          llvm::Value *DestPtr,
4192f4a2713aSLionel Sambuc                                          llvm::Value *SrcPtr,
4193f4a2713aSLionel Sambuc                                          llvm::Value *size) {
4194f4a2713aSLionel Sambuc   SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
4195f4a2713aSLionel Sambuc   DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
4196f4a2713aSLionel Sambuc   llvm::Value *args[] = { DestPtr, SrcPtr, size };
4197f4a2713aSLionel Sambuc   CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
4198f4a2713aSLionel Sambuc }
4199f4a2713aSLionel Sambuc 
4200f4a2713aSLionel Sambuc /// EmitObjCValueForIvar - Code Gen for ivar reference.
4201f4a2713aSLionel Sambuc ///
EmitObjCValueForIvar(CodeGen::CodeGenFunction & CGF,QualType ObjectTy,llvm::Value * BaseValue,const ObjCIvarDecl * Ivar,unsigned CVRQualifiers)4202f4a2713aSLionel Sambuc LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
4203f4a2713aSLionel Sambuc                                        QualType ObjectTy,
4204f4a2713aSLionel Sambuc                                        llvm::Value *BaseValue,
4205f4a2713aSLionel Sambuc                                        const ObjCIvarDecl *Ivar,
4206f4a2713aSLionel Sambuc                                        unsigned CVRQualifiers) {
4207f4a2713aSLionel Sambuc   const ObjCInterfaceDecl *ID =
4208f4a2713aSLionel Sambuc     ObjectTy->getAs<ObjCObjectType>()->getInterface();
4209f4a2713aSLionel Sambuc   return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
4210f4a2713aSLionel Sambuc                                   EmitIvarOffset(CGF, ID, Ivar));
4211f4a2713aSLionel Sambuc }
4212f4a2713aSLionel Sambuc 
EmitIvarOffset(CodeGen::CodeGenFunction & CGF,const ObjCInterfaceDecl * Interface,const ObjCIvarDecl * Ivar)4213f4a2713aSLionel Sambuc llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
4214f4a2713aSLionel Sambuc                                        const ObjCInterfaceDecl *Interface,
4215f4a2713aSLionel Sambuc                                        const ObjCIvarDecl *Ivar) {
4216f4a2713aSLionel Sambuc   uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
4217f4a2713aSLionel Sambuc   return llvm::ConstantInt::get(
4218f4a2713aSLionel Sambuc     CGM.getTypes().ConvertType(CGM.getContext().LongTy),
4219f4a2713aSLionel Sambuc     Offset);
4220f4a2713aSLionel Sambuc }
4221f4a2713aSLionel Sambuc 
4222f4a2713aSLionel Sambuc /* *** Private Interface *** */
4223f4a2713aSLionel Sambuc 
4224f4a2713aSLionel Sambuc /// EmitImageInfo - Emit the image info marker used to encode some module
4225f4a2713aSLionel Sambuc /// level information.
4226f4a2713aSLionel Sambuc ///
4227f4a2713aSLionel Sambuc /// See: <rdr://4810609&4810587&4810587>
4228f4a2713aSLionel Sambuc /// struct IMAGE_INFO {
4229f4a2713aSLionel Sambuc ///   unsigned version;
4230f4a2713aSLionel Sambuc ///   unsigned flags;
4231f4a2713aSLionel Sambuc /// };
4232f4a2713aSLionel Sambuc enum ImageInfoFlags {
4233*0a6a1f1dSLionel Sambuc   eImageInfo_FixAndContinue      = (1 << 0), // This flag is no longer set by clang.
4234f4a2713aSLionel Sambuc   eImageInfo_GarbageCollected    = (1 << 1),
4235f4a2713aSLionel Sambuc   eImageInfo_GCOnly              = (1 << 2),
4236*0a6a1f1dSLionel Sambuc   eImageInfo_OptimizedByDyld     = (1 << 3), // This flag is set by the dyld shared cache.
4237f4a2713aSLionel Sambuc 
4238f4a2713aSLionel Sambuc   // A flag indicating that the module has no instances of a @synthesize of a
4239f4a2713aSLionel Sambuc   // superclass variable. <rdar://problem/6803242>
4240*0a6a1f1dSLionel Sambuc   eImageInfo_CorrectedSynthesize = (1 << 4), // This flag is no longer set by clang.
4241f4a2713aSLionel Sambuc   eImageInfo_ImageIsSimulated    = (1 << 5)
4242f4a2713aSLionel Sambuc };
4243f4a2713aSLionel Sambuc 
EmitImageInfo()4244f4a2713aSLionel Sambuc void CGObjCCommonMac::EmitImageInfo() {
4245f4a2713aSLionel Sambuc   unsigned version = 0; // Version is unused?
4246f4a2713aSLionel Sambuc   const char *Section = (ObjCABI == 1) ?
4247f4a2713aSLionel Sambuc     "__OBJC, __image_info,regular" :
4248f4a2713aSLionel Sambuc     "__DATA, __objc_imageinfo, regular, no_dead_strip";
4249f4a2713aSLionel Sambuc 
4250f4a2713aSLionel Sambuc   // Generate module-level named metadata to convey this information to the
4251f4a2713aSLionel Sambuc   // linker and code-gen.
4252f4a2713aSLionel Sambuc   llvm::Module &Mod = CGM.getModule();
4253f4a2713aSLionel Sambuc 
4254f4a2713aSLionel Sambuc   // Add the ObjC ABI version to the module flags.
4255f4a2713aSLionel Sambuc   Mod.addModuleFlag(llvm::Module::Error, "Objective-C Version", ObjCABI);
4256f4a2713aSLionel Sambuc   Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Version",
4257f4a2713aSLionel Sambuc                     version);
4258f4a2713aSLionel Sambuc   Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Section",
4259f4a2713aSLionel Sambuc                     llvm::MDString::get(VMContext,Section));
4260f4a2713aSLionel Sambuc 
4261f4a2713aSLionel Sambuc   if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
4262f4a2713aSLionel Sambuc     // Non-GC overrides those files which specify GC.
4263f4a2713aSLionel Sambuc     Mod.addModuleFlag(llvm::Module::Override,
4264f4a2713aSLionel Sambuc                       "Objective-C Garbage Collection", (uint32_t)0);
4265f4a2713aSLionel Sambuc   } else {
4266f4a2713aSLionel Sambuc     // Add the ObjC garbage collection value.
4267f4a2713aSLionel Sambuc     Mod.addModuleFlag(llvm::Module::Error,
4268f4a2713aSLionel Sambuc                       "Objective-C Garbage Collection",
4269f4a2713aSLionel Sambuc                       eImageInfo_GarbageCollected);
4270f4a2713aSLionel Sambuc 
4271f4a2713aSLionel Sambuc     if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) {
4272f4a2713aSLionel Sambuc       // Add the ObjC GC Only value.
4273f4a2713aSLionel Sambuc       Mod.addModuleFlag(llvm::Module::Error, "Objective-C GC Only",
4274f4a2713aSLionel Sambuc                         eImageInfo_GCOnly);
4275f4a2713aSLionel Sambuc 
4276f4a2713aSLionel Sambuc       // Require that GC be specified and set to eImageInfo_GarbageCollected.
4277*0a6a1f1dSLionel Sambuc       llvm::Metadata *Ops[2] = {
4278f4a2713aSLionel Sambuc           llvm::MDString::get(VMContext, "Objective-C Garbage Collection"),
4279*0a6a1f1dSLionel Sambuc           llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
4280*0a6a1f1dSLionel Sambuc               llvm::Type::getInt32Ty(VMContext), eImageInfo_GarbageCollected))};
4281f4a2713aSLionel Sambuc       Mod.addModuleFlag(llvm::Module::Require, "Objective-C GC Only",
4282f4a2713aSLionel Sambuc                         llvm::MDNode::get(VMContext, Ops));
4283f4a2713aSLionel Sambuc     }
4284f4a2713aSLionel Sambuc   }
4285f4a2713aSLionel Sambuc 
4286f4a2713aSLionel Sambuc   // Indicate whether we're compiling this to run on a simulator.
4287f4a2713aSLionel Sambuc   const llvm::Triple &Triple = CGM.getTarget().getTriple();
4288f4a2713aSLionel Sambuc   if (Triple.isiOS() &&
4289f4a2713aSLionel Sambuc       (Triple.getArch() == llvm::Triple::x86 ||
4290f4a2713aSLionel Sambuc        Triple.getArch() == llvm::Triple::x86_64))
4291f4a2713aSLionel Sambuc     Mod.addModuleFlag(llvm::Module::Error, "Objective-C Is Simulated",
4292f4a2713aSLionel Sambuc                       eImageInfo_ImageIsSimulated);
4293f4a2713aSLionel Sambuc }
4294f4a2713aSLionel Sambuc 
4295f4a2713aSLionel Sambuc // struct objc_module {
4296f4a2713aSLionel Sambuc //   unsigned long version;
4297f4a2713aSLionel Sambuc //   unsigned long size;
4298f4a2713aSLionel Sambuc //   const char *name;
4299f4a2713aSLionel Sambuc //   Symtab symtab;
4300f4a2713aSLionel Sambuc // };
4301f4a2713aSLionel Sambuc 
4302f4a2713aSLionel Sambuc // FIXME: Get from somewhere
4303f4a2713aSLionel Sambuc static const int ModuleVersion = 7;
4304f4a2713aSLionel Sambuc 
EmitModuleInfo()4305f4a2713aSLionel Sambuc void CGObjCMac::EmitModuleInfo() {
4306f4a2713aSLionel Sambuc   uint64_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ModuleTy);
4307f4a2713aSLionel Sambuc 
4308f4a2713aSLionel Sambuc   llvm::Constant *Values[] = {
4309f4a2713aSLionel Sambuc     llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion),
4310f4a2713aSLionel Sambuc     llvm::ConstantInt::get(ObjCTypes.LongTy, Size),
4311f4a2713aSLionel Sambuc     // This used to be the filename, now it is unused. <rdr://4327263>
4312*0a6a1f1dSLionel Sambuc     GetClassName(StringRef("")),
4313f4a2713aSLionel Sambuc     EmitModuleSymbols()
4314f4a2713aSLionel Sambuc   };
4315*0a6a1f1dSLionel Sambuc   CreateMetadataVar("OBJC_MODULES",
4316f4a2713aSLionel Sambuc                     llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values),
4317*0a6a1f1dSLionel Sambuc                     "__OBJC,__module_info,regular,no_dead_strip", 4, true);
4318f4a2713aSLionel Sambuc }
4319f4a2713aSLionel Sambuc 
EmitModuleSymbols()4320f4a2713aSLionel Sambuc llvm::Constant *CGObjCMac::EmitModuleSymbols() {
4321f4a2713aSLionel Sambuc   unsigned NumClasses = DefinedClasses.size();
4322f4a2713aSLionel Sambuc   unsigned NumCategories = DefinedCategories.size();
4323f4a2713aSLionel Sambuc 
4324f4a2713aSLionel Sambuc   // Return null if no symbols were defined.
4325f4a2713aSLionel Sambuc   if (!NumClasses && !NumCategories)
4326f4a2713aSLionel Sambuc     return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
4327f4a2713aSLionel Sambuc 
4328f4a2713aSLionel Sambuc   llvm::Constant *Values[5];
4329f4a2713aSLionel Sambuc   Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
4330f4a2713aSLionel Sambuc   Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy);
4331f4a2713aSLionel Sambuc   Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses);
4332f4a2713aSLionel Sambuc   Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories);
4333f4a2713aSLionel Sambuc 
4334f4a2713aSLionel Sambuc   // The runtime expects exactly the list of defined classes followed
4335f4a2713aSLionel Sambuc   // by the list of defined categories, in a single array.
4336f4a2713aSLionel Sambuc   SmallVector<llvm::Constant*, 8> Symbols(NumClasses + NumCategories);
4337*0a6a1f1dSLionel Sambuc   for (unsigned i=0; i<NumClasses; i++) {
4338*0a6a1f1dSLionel Sambuc     const ObjCInterfaceDecl *ID = ImplementedClasses[i];
4339*0a6a1f1dSLionel Sambuc     assert(ID);
4340*0a6a1f1dSLionel Sambuc     if (ObjCImplementationDecl *IMP = ID->getImplementation())
4341*0a6a1f1dSLionel Sambuc       // We are implementing a weak imported interface. Give it external linkage
4342*0a6a1f1dSLionel Sambuc       if (ID->isWeakImported() && !IMP->isWeakImported())
4343*0a6a1f1dSLionel Sambuc         DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
4344*0a6a1f1dSLionel Sambuc 
4345f4a2713aSLionel Sambuc     Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i],
4346f4a2713aSLionel Sambuc                                                 ObjCTypes.Int8PtrTy);
4347*0a6a1f1dSLionel Sambuc   }
4348f4a2713aSLionel Sambuc   for (unsigned i=0; i<NumCategories; i++)
4349f4a2713aSLionel Sambuc     Symbols[NumClasses + i] =
4350f4a2713aSLionel Sambuc       llvm::ConstantExpr::getBitCast(DefinedCategories[i],
4351f4a2713aSLionel Sambuc                                      ObjCTypes.Int8PtrTy);
4352f4a2713aSLionel Sambuc 
4353f4a2713aSLionel Sambuc   Values[4] =
4354f4a2713aSLionel Sambuc     llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
4355f4a2713aSLionel Sambuc                                                   Symbols.size()),
4356f4a2713aSLionel Sambuc                              Symbols);
4357f4a2713aSLionel Sambuc 
4358f4a2713aSLionel Sambuc   llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
4359f4a2713aSLionel Sambuc 
4360*0a6a1f1dSLionel Sambuc   llvm::GlobalVariable *GV = CreateMetadataVar(
4361*0a6a1f1dSLionel Sambuc       "OBJC_SYMBOLS", Init, "__OBJC,__symbols,regular,no_dead_strip", 4, true);
4362f4a2713aSLionel Sambuc   return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
4363f4a2713aSLionel Sambuc }
4364f4a2713aSLionel Sambuc 
EmitClassRefFromId(CodeGenFunction & CGF,IdentifierInfo * II)4365f4a2713aSLionel Sambuc llvm::Value *CGObjCMac::EmitClassRefFromId(CodeGenFunction &CGF,
4366f4a2713aSLionel Sambuc                                            IdentifierInfo *II) {
4367f4a2713aSLionel Sambuc   LazySymbols.insert(II);
4368f4a2713aSLionel Sambuc 
4369f4a2713aSLionel Sambuc   llvm::GlobalVariable *&Entry = ClassReferences[II];
4370f4a2713aSLionel Sambuc 
4371f4a2713aSLionel Sambuc   if (!Entry) {
4372f4a2713aSLionel Sambuc     llvm::Constant *Casted =
4373*0a6a1f1dSLionel Sambuc     llvm::ConstantExpr::getBitCast(GetClassName(II->getName()),
4374f4a2713aSLionel Sambuc                                    ObjCTypes.ClassPtrTy);
4375*0a6a1f1dSLionel Sambuc     Entry = CreateMetadataVar(
4376*0a6a1f1dSLionel Sambuc         "OBJC_CLASS_REFERENCES_", Casted,
4377*0a6a1f1dSLionel Sambuc         "__OBJC,__cls_refs,literal_pointers,no_dead_strip", 4, true);
4378f4a2713aSLionel Sambuc   }
4379f4a2713aSLionel Sambuc 
4380f4a2713aSLionel Sambuc   return CGF.Builder.CreateLoad(Entry);
4381f4a2713aSLionel Sambuc }
4382f4a2713aSLionel Sambuc 
EmitClassRef(CodeGenFunction & CGF,const ObjCInterfaceDecl * ID)4383f4a2713aSLionel Sambuc llvm::Value *CGObjCMac::EmitClassRef(CodeGenFunction &CGF,
4384f4a2713aSLionel Sambuc                                      const ObjCInterfaceDecl *ID) {
4385f4a2713aSLionel Sambuc   return EmitClassRefFromId(CGF, ID->getIdentifier());
4386f4a2713aSLionel Sambuc }
4387f4a2713aSLionel Sambuc 
EmitNSAutoreleasePoolClassRef(CodeGenFunction & CGF)4388f4a2713aSLionel Sambuc llvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
4389f4a2713aSLionel Sambuc   IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
4390f4a2713aSLionel Sambuc   return EmitClassRefFromId(CGF, II);
4391f4a2713aSLionel Sambuc }
4392f4a2713aSLionel Sambuc 
EmitSelector(CodeGenFunction & CGF,Selector Sel,bool lvalue)4393f4a2713aSLionel Sambuc llvm::Value *CGObjCMac::EmitSelector(CodeGenFunction &CGF, Selector Sel,
4394f4a2713aSLionel Sambuc                                      bool lvalue) {
4395f4a2713aSLionel Sambuc   llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
4396f4a2713aSLionel Sambuc 
4397f4a2713aSLionel Sambuc   if (!Entry) {
4398f4a2713aSLionel Sambuc     llvm::Constant *Casted =
4399f4a2713aSLionel Sambuc       llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
4400f4a2713aSLionel Sambuc                                      ObjCTypes.SelectorPtrTy);
4401*0a6a1f1dSLionel Sambuc     Entry = CreateMetadataVar(
4402*0a6a1f1dSLionel Sambuc         "OBJC_SELECTOR_REFERENCES_", Casted,
4403*0a6a1f1dSLionel Sambuc         "__OBJC,__message_refs,literal_pointers,no_dead_strip", 4, true);
4404f4a2713aSLionel Sambuc     Entry->setExternallyInitialized(true);
4405f4a2713aSLionel Sambuc   }
4406f4a2713aSLionel Sambuc 
4407f4a2713aSLionel Sambuc   if (lvalue)
4408f4a2713aSLionel Sambuc     return Entry;
4409f4a2713aSLionel Sambuc   return CGF.Builder.CreateLoad(Entry);
4410f4a2713aSLionel Sambuc }
4411f4a2713aSLionel Sambuc 
GetClassName(StringRef RuntimeName)4412*0a6a1f1dSLionel Sambuc llvm::Constant *CGObjCCommonMac::GetClassName(StringRef RuntimeName) {
4413*0a6a1f1dSLionel Sambuc     llvm::GlobalVariable *&Entry = ClassNames[RuntimeName];
4414f4a2713aSLionel Sambuc     if (!Entry)
4415*0a6a1f1dSLionel Sambuc       Entry = CreateMetadataVar(
4416*0a6a1f1dSLionel Sambuc           "OBJC_CLASS_NAME_",
4417*0a6a1f1dSLionel Sambuc           llvm::ConstantDataArray::getString(VMContext, RuntimeName),
4418*0a6a1f1dSLionel Sambuc           ((ObjCABI == 2) ? "__TEXT,__objc_classname,cstring_literals"
4419*0a6a1f1dSLionel Sambuc                           : "__TEXT,__cstring,cstring_literals"),
4420f4a2713aSLionel Sambuc           1, true);
4421f4a2713aSLionel Sambuc     return getConstantGEP(VMContext, Entry, 0, 0);
4422f4a2713aSLionel Sambuc }
4423f4a2713aSLionel Sambuc 
GetMethodDefinition(const ObjCMethodDecl * MD)4424f4a2713aSLionel Sambuc llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
4425f4a2713aSLionel Sambuc   llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*>::iterator
4426f4a2713aSLionel Sambuc       I = MethodDefinitions.find(MD);
4427f4a2713aSLionel Sambuc   if (I != MethodDefinitions.end())
4428f4a2713aSLionel Sambuc     return I->second;
4429f4a2713aSLionel Sambuc 
4430*0a6a1f1dSLionel Sambuc   return nullptr;
4431f4a2713aSLionel Sambuc }
4432f4a2713aSLionel Sambuc 
4433f4a2713aSLionel Sambuc /// GetIvarLayoutName - Returns a unique constant for the given
4434f4a2713aSLionel Sambuc /// ivar layout bitmap.
GetIvarLayoutName(IdentifierInfo * Ident,const ObjCCommonTypesHelper & ObjCTypes)4435f4a2713aSLionel Sambuc llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
4436f4a2713aSLionel Sambuc                                        const ObjCCommonTypesHelper &ObjCTypes) {
4437f4a2713aSLionel Sambuc   return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
4438f4a2713aSLionel Sambuc }
4439f4a2713aSLionel Sambuc 
BuildAggrIvarRecordLayout(const RecordType * RT,unsigned int BytePos,bool ForStrongLayout,bool & HasUnion)4440f4a2713aSLionel Sambuc void CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT,
4441f4a2713aSLionel Sambuc                                                 unsigned int BytePos,
4442f4a2713aSLionel Sambuc                                                 bool ForStrongLayout,
4443f4a2713aSLionel Sambuc                                                 bool &HasUnion) {
4444f4a2713aSLionel Sambuc   const RecordDecl *RD = RT->getDecl();
4445f4a2713aSLionel Sambuc   // FIXME - Use iterator.
4446*0a6a1f1dSLionel Sambuc   SmallVector<const FieldDecl*, 16> Fields(RD->fields());
4447f4a2713aSLionel Sambuc   llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
4448f4a2713aSLionel Sambuc   const llvm::StructLayout *RecLayout =
4449f4a2713aSLionel Sambuc     CGM.getDataLayout().getStructLayout(cast<llvm::StructType>(Ty));
4450f4a2713aSLionel Sambuc 
4451*0a6a1f1dSLionel Sambuc   BuildAggrIvarLayout(nullptr, RecLayout, RD, Fields, BytePos, ForStrongLayout,
4452*0a6a1f1dSLionel Sambuc                       HasUnion);
4453f4a2713aSLionel Sambuc }
4454f4a2713aSLionel Sambuc 
BuildAggrIvarLayout(const ObjCImplementationDecl * OI,const llvm::StructLayout * Layout,const RecordDecl * RD,ArrayRef<const FieldDecl * > RecFields,unsigned int BytePos,bool ForStrongLayout,bool & HasUnion)4455f4a2713aSLionel Sambuc void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
4456f4a2713aSLionel Sambuc                              const llvm::StructLayout *Layout,
4457f4a2713aSLionel Sambuc                              const RecordDecl *RD,
4458f4a2713aSLionel Sambuc                              ArrayRef<const FieldDecl*> RecFields,
4459f4a2713aSLionel Sambuc                              unsigned int BytePos, bool ForStrongLayout,
4460f4a2713aSLionel Sambuc                              bool &HasUnion) {
4461f4a2713aSLionel Sambuc   bool IsUnion = (RD && RD->isUnion());
4462f4a2713aSLionel Sambuc   uint64_t MaxUnionIvarSize = 0;
4463f4a2713aSLionel Sambuc   uint64_t MaxSkippedUnionIvarSize = 0;
4464*0a6a1f1dSLionel Sambuc   const FieldDecl *MaxField = nullptr;
4465*0a6a1f1dSLionel Sambuc   const FieldDecl *MaxSkippedField = nullptr;
4466*0a6a1f1dSLionel Sambuc   const FieldDecl *LastFieldBitfieldOrUnnamed = nullptr;
4467f4a2713aSLionel Sambuc   uint64_t MaxFieldOffset = 0;
4468f4a2713aSLionel Sambuc   uint64_t MaxSkippedFieldOffset = 0;
4469f4a2713aSLionel Sambuc   uint64_t LastBitfieldOrUnnamedOffset = 0;
4470f4a2713aSLionel Sambuc   uint64_t FirstFieldDelta = 0;
4471f4a2713aSLionel Sambuc 
4472f4a2713aSLionel Sambuc   if (RecFields.empty())
4473f4a2713aSLionel Sambuc     return;
4474f4a2713aSLionel Sambuc   unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0);
4475f4a2713aSLionel Sambuc   unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
4476f4a2713aSLionel Sambuc   if (!RD && CGM.getLangOpts().ObjCAutoRefCount) {
4477f4a2713aSLionel Sambuc     const FieldDecl *FirstField = RecFields[0];
4478f4a2713aSLionel Sambuc     FirstFieldDelta =
4479f4a2713aSLionel Sambuc       ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(FirstField));
4480f4a2713aSLionel Sambuc   }
4481f4a2713aSLionel Sambuc 
4482f4a2713aSLionel Sambuc   for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
4483f4a2713aSLionel Sambuc     const FieldDecl *Field = RecFields[i];
4484f4a2713aSLionel Sambuc     uint64_t FieldOffset;
4485f4a2713aSLionel Sambuc     if (RD) {
4486f4a2713aSLionel Sambuc       // Note that 'i' here is actually the field index inside RD of Field,
4487f4a2713aSLionel Sambuc       // although this dependency is hidden.
4488f4a2713aSLionel Sambuc       const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
4489f4a2713aSLionel Sambuc       FieldOffset = (RL.getFieldOffset(i) / ByteSizeInBits) - FirstFieldDelta;
4490f4a2713aSLionel Sambuc     } else
4491f4a2713aSLionel Sambuc       FieldOffset =
4492f4a2713aSLionel Sambuc         ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field)) - FirstFieldDelta;
4493f4a2713aSLionel Sambuc 
4494f4a2713aSLionel Sambuc     // Skip over unnamed or bitfields
4495f4a2713aSLionel Sambuc     if (!Field->getIdentifier() || Field->isBitField()) {
4496f4a2713aSLionel Sambuc       LastFieldBitfieldOrUnnamed = Field;
4497f4a2713aSLionel Sambuc       LastBitfieldOrUnnamedOffset = FieldOffset;
4498f4a2713aSLionel Sambuc       continue;
4499f4a2713aSLionel Sambuc     }
4500f4a2713aSLionel Sambuc 
4501*0a6a1f1dSLionel Sambuc     LastFieldBitfieldOrUnnamed = nullptr;
4502f4a2713aSLionel Sambuc     QualType FQT = Field->getType();
4503f4a2713aSLionel Sambuc     if (FQT->isRecordType() || FQT->isUnionType()) {
4504f4a2713aSLionel Sambuc       if (FQT->isUnionType())
4505f4a2713aSLionel Sambuc         HasUnion = true;
4506f4a2713aSLionel Sambuc 
4507f4a2713aSLionel Sambuc       BuildAggrIvarRecordLayout(FQT->getAs<RecordType>(),
4508f4a2713aSLionel Sambuc                                 BytePos + FieldOffset,
4509f4a2713aSLionel Sambuc                                 ForStrongLayout, HasUnion);
4510f4a2713aSLionel Sambuc       continue;
4511f4a2713aSLionel Sambuc     }
4512f4a2713aSLionel Sambuc 
4513f4a2713aSLionel Sambuc     if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
4514f4a2713aSLionel Sambuc       const ConstantArrayType *CArray =
4515f4a2713aSLionel Sambuc         dyn_cast_or_null<ConstantArrayType>(Array);
4516f4a2713aSLionel Sambuc       uint64_t ElCount = CArray->getSize().getZExtValue();
4517f4a2713aSLionel Sambuc       assert(CArray && "only array with known element size is supported");
4518f4a2713aSLionel Sambuc       FQT = CArray->getElementType();
4519f4a2713aSLionel Sambuc       while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
4520f4a2713aSLionel Sambuc         const ConstantArrayType *CArray =
4521f4a2713aSLionel Sambuc           dyn_cast_or_null<ConstantArrayType>(Array);
4522f4a2713aSLionel Sambuc         ElCount *= CArray->getSize().getZExtValue();
4523f4a2713aSLionel Sambuc         FQT = CArray->getElementType();
4524f4a2713aSLionel Sambuc       }
4525f4a2713aSLionel Sambuc       if (FQT->isRecordType() && ElCount) {
4526f4a2713aSLionel Sambuc         int OldIndex = IvarsInfo.size() - 1;
4527f4a2713aSLionel Sambuc         int OldSkIndex = SkipIvars.size() -1;
4528f4a2713aSLionel Sambuc 
4529f4a2713aSLionel Sambuc         const RecordType *RT = FQT->getAs<RecordType>();
4530f4a2713aSLionel Sambuc         BuildAggrIvarRecordLayout(RT, BytePos + FieldOffset,
4531f4a2713aSLionel Sambuc                                   ForStrongLayout, HasUnion);
4532f4a2713aSLionel Sambuc 
4533f4a2713aSLionel Sambuc         // Replicate layout information for each array element. Note that
4534f4a2713aSLionel Sambuc         // one element is already done.
4535f4a2713aSLionel Sambuc         uint64_t ElIx = 1;
4536f4a2713aSLionel Sambuc         for (int FirstIndex = IvarsInfo.size() - 1,
4537f4a2713aSLionel Sambuc                FirstSkIndex = SkipIvars.size() - 1 ;ElIx < ElCount; ElIx++) {
4538f4a2713aSLionel Sambuc           uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits;
4539f4a2713aSLionel Sambuc           for (int i = OldIndex+1; i <= FirstIndex; ++i)
4540f4a2713aSLionel Sambuc             IvarsInfo.push_back(GC_IVAR(IvarsInfo[i].ivar_bytepos + Size*ElIx,
4541f4a2713aSLionel Sambuc                                         IvarsInfo[i].ivar_size));
4542f4a2713aSLionel Sambuc           for (int i = OldSkIndex+1; i <= FirstSkIndex; ++i)
4543f4a2713aSLionel Sambuc             SkipIvars.push_back(GC_IVAR(SkipIvars[i].ivar_bytepos + Size*ElIx,
4544f4a2713aSLionel Sambuc                                         SkipIvars[i].ivar_size));
4545f4a2713aSLionel Sambuc         }
4546f4a2713aSLionel Sambuc         continue;
4547f4a2713aSLionel Sambuc       }
4548f4a2713aSLionel Sambuc     }
4549f4a2713aSLionel Sambuc     // At this point, we are done with Record/Union and array there of.
4550f4a2713aSLionel Sambuc     // For other arrays we are down to its element type.
4551f4a2713aSLionel Sambuc     Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT);
4552f4a2713aSLionel Sambuc 
4553f4a2713aSLionel Sambuc     unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType());
4554f4a2713aSLionel Sambuc     if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
4555f4a2713aSLionel Sambuc         || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
4556f4a2713aSLionel Sambuc       if (IsUnion) {
4557f4a2713aSLionel Sambuc         uint64_t UnionIvarSize = FieldSize / WordSizeInBits;
4558f4a2713aSLionel Sambuc         if (UnionIvarSize > MaxUnionIvarSize) {
4559f4a2713aSLionel Sambuc           MaxUnionIvarSize = UnionIvarSize;
4560f4a2713aSLionel Sambuc           MaxField = Field;
4561f4a2713aSLionel Sambuc           MaxFieldOffset = FieldOffset;
4562f4a2713aSLionel Sambuc         }
4563f4a2713aSLionel Sambuc       } else {
4564f4a2713aSLionel Sambuc         IvarsInfo.push_back(GC_IVAR(BytePos + FieldOffset,
4565f4a2713aSLionel Sambuc                                     FieldSize / WordSizeInBits));
4566f4a2713aSLionel Sambuc       }
4567f4a2713aSLionel Sambuc     } else if ((ForStrongLayout &&
4568f4a2713aSLionel Sambuc                 (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak))
4569f4a2713aSLionel Sambuc                || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) {
4570f4a2713aSLionel Sambuc       if (IsUnion) {
4571f4a2713aSLionel Sambuc         // FIXME: Why the asymmetry? We divide by word size in bits on other
4572f4a2713aSLionel Sambuc         // side.
4573f4a2713aSLionel Sambuc         uint64_t UnionIvarSize = FieldSize / ByteSizeInBits;
4574f4a2713aSLionel Sambuc         if (UnionIvarSize > MaxSkippedUnionIvarSize) {
4575f4a2713aSLionel Sambuc           MaxSkippedUnionIvarSize = UnionIvarSize;
4576f4a2713aSLionel Sambuc           MaxSkippedField = Field;
4577f4a2713aSLionel Sambuc           MaxSkippedFieldOffset = FieldOffset;
4578f4a2713aSLionel Sambuc         }
4579f4a2713aSLionel Sambuc       } else {
4580f4a2713aSLionel Sambuc         // FIXME: Why the asymmetry, we divide by byte size in bits here?
4581f4a2713aSLionel Sambuc         SkipIvars.push_back(GC_IVAR(BytePos + FieldOffset,
4582f4a2713aSLionel Sambuc                                     FieldSize / ByteSizeInBits));
4583f4a2713aSLionel Sambuc       }
4584f4a2713aSLionel Sambuc     }
4585f4a2713aSLionel Sambuc   }
4586f4a2713aSLionel Sambuc 
4587f4a2713aSLionel Sambuc   if (LastFieldBitfieldOrUnnamed) {
4588f4a2713aSLionel Sambuc     if (LastFieldBitfieldOrUnnamed->isBitField()) {
4589f4a2713aSLionel Sambuc       // Last field was a bitfield. Must update skip info.
4590f4a2713aSLionel Sambuc       uint64_t BitFieldSize
4591f4a2713aSLionel Sambuc           = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext());
4592f4a2713aSLionel Sambuc       GC_IVAR skivar;
4593f4a2713aSLionel Sambuc       skivar.ivar_bytepos = BytePos + LastBitfieldOrUnnamedOffset;
4594f4a2713aSLionel Sambuc       skivar.ivar_size = (BitFieldSize / ByteSizeInBits)
4595f4a2713aSLionel Sambuc         + ((BitFieldSize % ByteSizeInBits) != 0);
4596f4a2713aSLionel Sambuc       SkipIvars.push_back(skivar);
4597f4a2713aSLionel Sambuc     } else {
4598f4a2713aSLionel Sambuc       assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
4599f4a2713aSLionel Sambuc       // Last field was unnamed. Must update skip info.
4600f4a2713aSLionel Sambuc       unsigned FieldSize
4601f4a2713aSLionel Sambuc           = CGM.getContext().getTypeSize(LastFieldBitfieldOrUnnamed->getType());
4602f4a2713aSLionel Sambuc       SkipIvars.push_back(GC_IVAR(BytePos + LastBitfieldOrUnnamedOffset,
4603f4a2713aSLionel Sambuc                                   FieldSize / ByteSizeInBits));
4604f4a2713aSLionel Sambuc     }
4605f4a2713aSLionel Sambuc   }
4606f4a2713aSLionel Sambuc 
4607f4a2713aSLionel Sambuc   if (MaxField)
4608f4a2713aSLionel Sambuc     IvarsInfo.push_back(GC_IVAR(BytePos + MaxFieldOffset,
4609f4a2713aSLionel Sambuc                                 MaxUnionIvarSize));
4610f4a2713aSLionel Sambuc   if (MaxSkippedField)
4611f4a2713aSLionel Sambuc     SkipIvars.push_back(GC_IVAR(BytePos + MaxSkippedFieldOffset,
4612f4a2713aSLionel Sambuc                                 MaxSkippedUnionIvarSize));
4613f4a2713aSLionel Sambuc }
4614f4a2713aSLionel Sambuc 
4615f4a2713aSLionel Sambuc /// BuildIvarLayoutBitmap - This routine is the horsework for doing all
4616f4a2713aSLionel Sambuc /// the computations and returning the layout bitmap (for ivar or blocks) in
4617f4a2713aSLionel Sambuc /// the given argument BitMap string container. Routine reads
4618f4a2713aSLionel Sambuc /// two containers, IvarsInfo and SkipIvars which are assumed to be
4619f4a2713aSLionel Sambuc /// filled already by the caller.
BuildIvarLayoutBitmap(std::string & BitMap)4620f4a2713aSLionel Sambuc llvm::Constant *CGObjCCommonMac::BuildIvarLayoutBitmap(std::string &BitMap) {
4621f4a2713aSLionel Sambuc   unsigned int WordsToScan, WordsToSkip;
4622f4a2713aSLionel Sambuc   llvm::Type *PtrTy = CGM.Int8PtrTy;
4623f4a2713aSLionel Sambuc 
4624f4a2713aSLionel Sambuc   // Build the string of skip/scan nibbles
4625f4a2713aSLionel Sambuc   SmallVector<SKIP_SCAN, 32> SkipScanIvars;
4626f4a2713aSLionel Sambuc   unsigned int WordSize =
4627f4a2713aSLionel Sambuc   CGM.getTypes().getDataLayout().getTypeAllocSize(PtrTy);
4628f4a2713aSLionel Sambuc   if (IvarsInfo[0].ivar_bytepos == 0) {
4629f4a2713aSLionel Sambuc     WordsToSkip = 0;
4630f4a2713aSLionel Sambuc     WordsToScan = IvarsInfo[0].ivar_size;
4631f4a2713aSLionel Sambuc   } else {
4632f4a2713aSLionel Sambuc     WordsToSkip = IvarsInfo[0].ivar_bytepos/WordSize;
4633f4a2713aSLionel Sambuc     WordsToScan = IvarsInfo[0].ivar_size;
4634f4a2713aSLionel Sambuc   }
4635f4a2713aSLionel Sambuc   for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++) {
4636f4a2713aSLionel Sambuc     unsigned int TailPrevGCObjC =
4637f4a2713aSLionel Sambuc     IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize;
4638f4a2713aSLionel Sambuc     if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC) {
4639f4a2713aSLionel Sambuc       // consecutive 'scanned' object pointers.
4640f4a2713aSLionel Sambuc       WordsToScan += IvarsInfo[i].ivar_size;
4641f4a2713aSLionel Sambuc     } else {
4642f4a2713aSLionel Sambuc       // Skip over 'gc'able object pointer which lay over each other.
4643f4a2713aSLionel Sambuc       if (TailPrevGCObjC > IvarsInfo[i].ivar_bytepos)
4644f4a2713aSLionel Sambuc         continue;
4645f4a2713aSLionel Sambuc       // Must skip over 1 or more words. We save current skip/scan values
4646f4a2713aSLionel Sambuc       //  and start a new pair.
4647f4a2713aSLionel Sambuc       SKIP_SCAN SkScan;
4648f4a2713aSLionel Sambuc       SkScan.skip = WordsToSkip;
4649f4a2713aSLionel Sambuc       SkScan.scan = WordsToScan;
4650f4a2713aSLionel Sambuc       SkipScanIvars.push_back(SkScan);
4651f4a2713aSLionel Sambuc 
4652f4a2713aSLionel Sambuc       // Skip the hole.
4653f4a2713aSLionel Sambuc       SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize;
4654f4a2713aSLionel Sambuc       SkScan.scan = 0;
4655f4a2713aSLionel Sambuc       SkipScanIvars.push_back(SkScan);
4656f4a2713aSLionel Sambuc       WordsToSkip = 0;
4657f4a2713aSLionel Sambuc       WordsToScan = IvarsInfo[i].ivar_size;
4658f4a2713aSLionel Sambuc     }
4659f4a2713aSLionel Sambuc   }
4660f4a2713aSLionel Sambuc   if (WordsToScan > 0) {
4661f4a2713aSLionel Sambuc     SKIP_SCAN SkScan;
4662f4a2713aSLionel Sambuc     SkScan.skip = WordsToSkip;
4663f4a2713aSLionel Sambuc     SkScan.scan = WordsToScan;
4664f4a2713aSLionel Sambuc     SkipScanIvars.push_back(SkScan);
4665f4a2713aSLionel Sambuc   }
4666f4a2713aSLionel Sambuc 
4667f4a2713aSLionel Sambuc   if (!SkipIvars.empty()) {
4668f4a2713aSLionel Sambuc     unsigned int LastIndex = SkipIvars.size()-1;
4669f4a2713aSLionel Sambuc     int LastByteSkipped =
4670f4a2713aSLionel Sambuc     SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size;
4671f4a2713aSLionel Sambuc     LastIndex = IvarsInfo.size()-1;
4672f4a2713aSLionel Sambuc     int LastByteScanned =
4673f4a2713aSLionel Sambuc     IvarsInfo[LastIndex].ivar_bytepos +
4674f4a2713aSLionel Sambuc     IvarsInfo[LastIndex].ivar_size * WordSize;
4675f4a2713aSLionel Sambuc     // Compute number of bytes to skip at the tail end of the last ivar scanned.
4676f4a2713aSLionel Sambuc     if (LastByteSkipped > LastByteScanned) {
4677f4a2713aSLionel Sambuc       unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize;
4678f4a2713aSLionel Sambuc       SKIP_SCAN SkScan;
4679f4a2713aSLionel Sambuc       SkScan.skip = TotalWords - (LastByteScanned/WordSize);
4680f4a2713aSLionel Sambuc       SkScan.scan = 0;
4681f4a2713aSLionel Sambuc       SkipScanIvars.push_back(SkScan);
4682f4a2713aSLionel Sambuc     }
4683f4a2713aSLionel Sambuc   }
4684f4a2713aSLionel Sambuc   // Mini optimization of nibbles such that an 0xM0 followed by 0x0N is produced
4685f4a2713aSLionel Sambuc   // as 0xMN.
4686f4a2713aSLionel Sambuc   int SkipScan = SkipScanIvars.size()-1;
4687f4a2713aSLionel Sambuc   for (int i = 0; i <= SkipScan; i++) {
4688f4a2713aSLionel Sambuc     if ((i < SkipScan) && SkipScanIvars[i].skip && SkipScanIvars[i].scan == 0
4689f4a2713aSLionel Sambuc         && SkipScanIvars[i+1].skip == 0 && SkipScanIvars[i+1].scan) {
4690f4a2713aSLionel Sambuc       // 0xM0 followed by 0x0N detected.
4691f4a2713aSLionel Sambuc       SkipScanIvars[i].scan = SkipScanIvars[i+1].scan;
4692f4a2713aSLionel Sambuc       for (int j = i+1; j < SkipScan; j++)
4693f4a2713aSLionel Sambuc         SkipScanIvars[j] = SkipScanIvars[j+1];
4694f4a2713aSLionel Sambuc       --SkipScan;
4695f4a2713aSLionel Sambuc     }
4696f4a2713aSLionel Sambuc   }
4697f4a2713aSLionel Sambuc 
4698f4a2713aSLionel Sambuc   // Generate the string.
4699f4a2713aSLionel Sambuc   for (int i = 0; i <= SkipScan; i++) {
4700f4a2713aSLionel Sambuc     unsigned char byte;
4701f4a2713aSLionel Sambuc     unsigned int skip_small = SkipScanIvars[i].skip % 0xf;
4702f4a2713aSLionel Sambuc     unsigned int scan_small = SkipScanIvars[i].scan % 0xf;
4703f4a2713aSLionel Sambuc     unsigned int skip_big  = SkipScanIvars[i].skip / 0xf;
4704f4a2713aSLionel Sambuc     unsigned int scan_big  = SkipScanIvars[i].scan / 0xf;
4705f4a2713aSLionel Sambuc 
4706f4a2713aSLionel Sambuc     // first skip big.
4707f4a2713aSLionel Sambuc     for (unsigned int ix = 0; ix < skip_big; ix++)
4708f4a2713aSLionel Sambuc       BitMap += (unsigned char)(0xf0);
4709f4a2713aSLionel Sambuc 
4710f4a2713aSLionel Sambuc     // next (skip small, scan)
4711f4a2713aSLionel Sambuc     if (skip_small) {
4712f4a2713aSLionel Sambuc       byte = skip_small << 4;
4713f4a2713aSLionel Sambuc       if (scan_big > 0) {
4714f4a2713aSLionel Sambuc         byte |= 0xf;
4715f4a2713aSLionel Sambuc         --scan_big;
4716f4a2713aSLionel Sambuc       } else if (scan_small) {
4717f4a2713aSLionel Sambuc         byte |= scan_small;
4718f4a2713aSLionel Sambuc         scan_small = 0;
4719f4a2713aSLionel Sambuc       }
4720f4a2713aSLionel Sambuc       BitMap += byte;
4721f4a2713aSLionel Sambuc     }
4722f4a2713aSLionel Sambuc     // next scan big
4723f4a2713aSLionel Sambuc     for (unsigned int ix = 0; ix < scan_big; ix++)
4724f4a2713aSLionel Sambuc       BitMap += (unsigned char)(0x0f);
4725f4a2713aSLionel Sambuc     // last scan small
4726f4a2713aSLionel Sambuc     if (scan_small) {
4727f4a2713aSLionel Sambuc       byte = scan_small;
4728f4a2713aSLionel Sambuc       BitMap += byte;
4729f4a2713aSLionel Sambuc     }
4730f4a2713aSLionel Sambuc   }
4731f4a2713aSLionel Sambuc   // null terminate string.
4732f4a2713aSLionel Sambuc   unsigned char zero = 0;
4733f4a2713aSLionel Sambuc   BitMap += zero;
4734f4a2713aSLionel Sambuc 
4735*0a6a1f1dSLionel Sambuc   llvm::GlobalVariable *Entry = CreateMetadataVar(
4736*0a6a1f1dSLionel Sambuc       "OBJC_CLASS_NAME_",
4737f4a2713aSLionel Sambuc       llvm::ConstantDataArray::getString(VMContext, BitMap, false),
4738*0a6a1f1dSLionel Sambuc       ((ObjCABI == 2) ? "__TEXT,__objc_classname,cstring_literals"
4739*0a6a1f1dSLionel Sambuc                       : "__TEXT,__cstring,cstring_literals"),
4740f4a2713aSLionel Sambuc       1, true);
4741f4a2713aSLionel Sambuc   return getConstantGEP(VMContext, Entry, 0, 0);
4742f4a2713aSLionel Sambuc }
4743f4a2713aSLionel Sambuc 
4744f4a2713aSLionel Sambuc /// BuildIvarLayout - Builds ivar layout bitmap for the class
4745f4a2713aSLionel Sambuc /// implementation for the __strong or __weak case.
4746f4a2713aSLionel Sambuc /// The layout map displays which words in ivar list must be skipped
4747f4a2713aSLionel Sambuc /// and which must be scanned by GC (see below). String is built of bytes.
4748f4a2713aSLionel Sambuc /// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
4749f4a2713aSLionel Sambuc /// of words to skip and right nibble is count of words to scan. So, each
4750f4a2713aSLionel Sambuc /// nibble represents up to 15 workds to skip or scan. Skipping the rest is
4751f4a2713aSLionel Sambuc /// represented by a 0x00 byte which also ends the string.
4752f4a2713aSLionel Sambuc /// 1. when ForStrongLayout is true, following ivars are scanned:
4753f4a2713aSLionel Sambuc /// - id, Class
4754f4a2713aSLionel Sambuc /// - object *
4755f4a2713aSLionel Sambuc /// - __strong anything
4756f4a2713aSLionel Sambuc ///
4757f4a2713aSLionel Sambuc /// 2. When ForStrongLayout is false, following ivars are scanned:
4758f4a2713aSLionel Sambuc /// - __weak anything
4759f4a2713aSLionel Sambuc ///
BuildIvarLayout(const ObjCImplementationDecl * OMD,bool ForStrongLayout)4760f4a2713aSLionel Sambuc llvm::Constant *CGObjCCommonMac::BuildIvarLayout(
4761f4a2713aSLionel Sambuc   const ObjCImplementationDecl *OMD,
4762f4a2713aSLionel Sambuc   bool ForStrongLayout) {
4763f4a2713aSLionel Sambuc   bool hasUnion = false;
4764f4a2713aSLionel Sambuc 
4765f4a2713aSLionel Sambuc   llvm::Type *PtrTy = CGM.Int8PtrTy;
4766f4a2713aSLionel Sambuc   if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
4767f4a2713aSLionel Sambuc       !CGM.getLangOpts().ObjCAutoRefCount)
4768f4a2713aSLionel Sambuc     return llvm::Constant::getNullValue(PtrTy);
4769f4a2713aSLionel Sambuc 
4770f4a2713aSLionel Sambuc   const ObjCInterfaceDecl *OI = OMD->getClassInterface();
4771f4a2713aSLionel Sambuc   SmallVector<const FieldDecl*, 32> RecFields;
4772f4a2713aSLionel Sambuc   if (CGM.getLangOpts().ObjCAutoRefCount) {
4773f4a2713aSLionel Sambuc     for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin();
4774f4a2713aSLionel Sambuc          IVD; IVD = IVD->getNextIvar())
4775f4a2713aSLionel Sambuc       RecFields.push_back(cast<FieldDecl>(IVD));
4776f4a2713aSLionel Sambuc   }
4777f4a2713aSLionel Sambuc   else {
4778f4a2713aSLionel Sambuc     SmallVector<const ObjCIvarDecl*, 32> Ivars;
4779f4a2713aSLionel Sambuc     CGM.getContext().DeepCollectObjCIvars(OI, true, Ivars);
4780f4a2713aSLionel Sambuc 
4781f4a2713aSLionel Sambuc     // FIXME: This is not ideal; we shouldn't have to do this copy.
4782f4a2713aSLionel Sambuc     RecFields.append(Ivars.begin(), Ivars.end());
4783f4a2713aSLionel Sambuc   }
4784f4a2713aSLionel Sambuc 
4785f4a2713aSLionel Sambuc   if (RecFields.empty())
4786f4a2713aSLionel Sambuc     return llvm::Constant::getNullValue(PtrTy);
4787f4a2713aSLionel Sambuc 
4788f4a2713aSLionel Sambuc   SkipIvars.clear();
4789f4a2713aSLionel Sambuc   IvarsInfo.clear();
4790f4a2713aSLionel Sambuc 
4791*0a6a1f1dSLionel Sambuc   BuildAggrIvarLayout(OMD, nullptr, nullptr, RecFields, 0, ForStrongLayout,
4792*0a6a1f1dSLionel Sambuc                       hasUnion);
4793f4a2713aSLionel Sambuc   if (IvarsInfo.empty())
4794f4a2713aSLionel Sambuc     return llvm::Constant::getNullValue(PtrTy);
4795f4a2713aSLionel Sambuc   // Sort on byte position in case we encounterred a union nested in
4796f4a2713aSLionel Sambuc   // the ivar list.
4797f4a2713aSLionel Sambuc   if (hasUnion && !IvarsInfo.empty())
4798f4a2713aSLionel Sambuc     std::sort(IvarsInfo.begin(), IvarsInfo.end());
4799f4a2713aSLionel Sambuc   if (hasUnion && !SkipIvars.empty())
4800f4a2713aSLionel Sambuc     std::sort(SkipIvars.begin(), SkipIvars.end());
4801f4a2713aSLionel Sambuc 
4802f4a2713aSLionel Sambuc   std::string BitMap;
4803f4a2713aSLionel Sambuc   llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
4804f4a2713aSLionel Sambuc 
4805f4a2713aSLionel Sambuc    if (CGM.getLangOpts().ObjCGCBitmapPrint) {
4806f4a2713aSLionel Sambuc     printf("\n%s ivar layout for class '%s': ",
4807f4a2713aSLionel Sambuc            ForStrongLayout ? "strong" : "weak",
4808*0a6a1f1dSLionel Sambuc            OMD->getClassInterface()->getName().str().c_str());
4809f4a2713aSLionel Sambuc     const unsigned char *s = (const unsigned char*)BitMap.c_str();
4810f4a2713aSLionel Sambuc     for (unsigned i = 0, e = BitMap.size(); i < e; i++)
4811f4a2713aSLionel Sambuc       if (!(s[i] & 0xf0))
4812f4a2713aSLionel Sambuc         printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
4813f4a2713aSLionel Sambuc       else
4814f4a2713aSLionel Sambuc         printf("0x%x%s",  s[i], s[i] != 0 ? ", " : "");
4815f4a2713aSLionel Sambuc     printf("\n");
4816f4a2713aSLionel Sambuc   }
4817f4a2713aSLionel Sambuc   return C;
4818f4a2713aSLionel Sambuc }
4819f4a2713aSLionel Sambuc 
GetMethodVarName(Selector Sel)4820f4a2713aSLionel Sambuc llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
4821f4a2713aSLionel Sambuc   llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
4822f4a2713aSLionel Sambuc 
4823f4a2713aSLionel Sambuc   // FIXME: Avoid std::string in "Sel.getAsString()"
4824f4a2713aSLionel Sambuc   if (!Entry)
4825*0a6a1f1dSLionel Sambuc     Entry = CreateMetadataVar(
4826*0a6a1f1dSLionel Sambuc         "OBJC_METH_VAR_NAME_",
4827f4a2713aSLionel Sambuc         llvm::ConstantDataArray::getString(VMContext, Sel.getAsString()),
4828*0a6a1f1dSLionel Sambuc         ((ObjCABI == 2) ? "__TEXT,__objc_methname,cstring_literals"
4829*0a6a1f1dSLionel Sambuc                         : "__TEXT,__cstring,cstring_literals"),
4830f4a2713aSLionel Sambuc         1, true);
4831f4a2713aSLionel Sambuc 
4832f4a2713aSLionel Sambuc   return getConstantGEP(VMContext, Entry, 0, 0);
4833f4a2713aSLionel Sambuc }
4834f4a2713aSLionel Sambuc 
4835f4a2713aSLionel Sambuc // FIXME: Merge into a single cstring creation function.
GetMethodVarName(IdentifierInfo * ID)4836f4a2713aSLionel Sambuc llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
4837f4a2713aSLionel Sambuc   return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
4838f4a2713aSLionel Sambuc }
4839f4a2713aSLionel Sambuc 
GetMethodVarType(const FieldDecl * Field)4840f4a2713aSLionel Sambuc llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
4841f4a2713aSLionel Sambuc   std::string TypeStr;
4842f4a2713aSLionel Sambuc   CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
4843f4a2713aSLionel Sambuc 
4844f4a2713aSLionel Sambuc   llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
4845f4a2713aSLionel Sambuc 
4846f4a2713aSLionel Sambuc   if (!Entry)
4847*0a6a1f1dSLionel Sambuc     Entry = CreateMetadataVar(
4848*0a6a1f1dSLionel Sambuc         "OBJC_METH_VAR_TYPE_",
4849f4a2713aSLionel Sambuc         llvm::ConstantDataArray::getString(VMContext, TypeStr),
4850*0a6a1f1dSLionel Sambuc         ((ObjCABI == 2) ? "__TEXT,__objc_methtype,cstring_literals"
4851*0a6a1f1dSLionel Sambuc                         : "__TEXT,__cstring,cstring_literals"),
4852f4a2713aSLionel Sambuc         1, true);
4853f4a2713aSLionel Sambuc 
4854f4a2713aSLionel Sambuc   return getConstantGEP(VMContext, Entry, 0, 0);
4855f4a2713aSLionel Sambuc }
4856f4a2713aSLionel Sambuc 
GetMethodVarType(const ObjCMethodDecl * D,bool Extended)4857f4a2713aSLionel Sambuc llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D,
4858f4a2713aSLionel Sambuc                                                   bool Extended) {
4859f4a2713aSLionel Sambuc   std::string TypeStr;
4860f4a2713aSLionel Sambuc   if (CGM.getContext().getObjCEncodingForMethodDecl(D, TypeStr, Extended))
4861*0a6a1f1dSLionel Sambuc     return nullptr;
4862f4a2713aSLionel Sambuc 
4863f4a2713aSLionel Sambuc   llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
4864f4a2713aSLionel Sambuc 
4865f4a2713aSLionel Sambuc   if (!Entry)
4866*0a6a1f1dSLionel Sambuc     Entry = CreateMetadataVar(
4867*0a6a1f1dSLionel Sambuc         "OBJC_METH_VAR_TYPE_",
4868f4a2713aSLionel Sambuc         llvm::ConstantDataArray::getString(VMContext, TypeStr),
4869*0a6a1f1dSLionel Sambuc         ((ObjCABI == 2) ? "__TEXT,__objc_methtype,cstring_literals"
4870*0a6a1f1dSLionel Sambuc                         : "__TEXT,__cstring,cstring_literals"),
4871f4a2713aSLionel Sambuc         1, true);
4872f4a2713aSLionel Sambuc 
4873f4a2713aSLionel Sambuc   return getConstantGEP(VMContext, Entry, 0, 0);
4874f4a2713aSLionel Sambuc }
4875f4a2713aSLionel Sambuc 
4876f4a2713aSLionel Sambuc // FIXME: Merge into a single cstring creation function.
GetPropertyName(IdentifierInfo * Ident)4877f4a2713aSLionel Sambuc llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
4878f4a2713aSLionel Sambuc   llvm::GlobalVariable *&Entry = PropertyNames[Ident];
4879f4a2713aSLionel Sambuc 
4880f4a2713aSLionel Sambuc   if (!Entry)
4881*0a6a1f1dSLionel Sambuc     Entry = CreateMetadataVar(
4882*0a6a1f1dSLionel Sambuc         "OBJC_PROP_NAME_ATTR_",
4883*0a6a1f1dSLionel Sambuc         llvm::ConstantDataArray::getString(VMContext, Ident->getName()),
4884*0a6a1f1dSLionel Sambuc         "__TEXT,__cstring,cstring_literals", 1, true);
4885f4a2713aSLionel Sambuc 
4886f4a2713aSLionel Sambuc   return getConstantGEP(VMContext, Entry, 0, 0);
4887f4a2713aSLionel Sambuc }
4888f4a2713aSLionel Sambuc 
4889f4a2713aSLionel Sambuc // FIXME: Merge into a single cstring creation function.
4890f4a2713aSLionel Sambuc // FIXME: This Decl should be more precise.
4891f4a2713aSLionel Sambuc llvm::Constant *
GetPropertyTypeString(const ObjCPropertyDecl * PD,const Decl * Container)4892f4a2713aSLionel Sambuc CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
4893f4a2713aSLionel Sambuc                                        const Decl *Container) {
4894f4a2713aSLionel Sambuc   std::string TypeStr;
4895f4a2713aSLionel Sambuc   CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr);
4896f4a2713aSLionel Sambuc   return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
4897f4a2713aSLionel Sambuc }
4898f4a2713aSLionel Sambuc 
GetNameForMethod(const ObjCMethodDecl * D,const ObjCContainerDecl * CD,SmallVectorImpl<char> & Name)4899f4a2713aSLionel Sambuc void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
4900f4a2713aSLionel Sambuc                                        const ObjCContainerDecl *CD,
4901f4a2713aSLionel Sambuc                                        SmallVectorImpl<char> &Name) {
4902f4a2713aSLionel Sambuc   llvm::raw_svector_ostream OS(Name);
4903f4a2713aSLionel Sambuc   assert (CD && "Missing container decl in GetNameForMethod");
4904f4a2713aSLionel Sambuc   OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
4905f4a2713aSLionel Sambuc      << '[' << CD->getName();
4906f4a2713aSLionel Sambuc   if (const ObjCCategoryImplDecl *CID =
4907f4a2713aSLionel Sambuc       dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
4908f4a2713aSLionel Sambuc     OS << '(' << *CID << ')';
4909f4a2713aSLionel Sambuc   OS << ' ' << D->getSelector().getAsString() << ']';
4910f4a2713aSLionel Sambuc }
4911f4a2713aSLionel Sambuc 
FinishModule()4912f4a2713aSLionel Sambuc void CGObjCMac::FinishModule() {
4913f4a2713aSLionel Sambuc   EmitModuleInfo();
4914f4a2713aSLionel Sambuc 
4915f4a2713aSLionel Sambuc   // Emit the dummy bodies for any protocols which were referenced but
4916f4a2713aSLionel Sambuc   // never defined.
4917f4a2713aSLionel Sambuc   for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator
4918f4a2713aSLionel Sambuc          I = Protocols.begin(), e = Protocols.end(); I != e; ++I) {
4919f4a2713aSLionel Sambuc     if (I->second->hasInitializer())
4920f4a2713aSLionel Sambuc       continue;
4921f4a2713aSLionel Sambuc 
4922f4a2713aSLionel Sambuc     llvm::Constant *Values[5];
4923f4a2713aSLionel Sambuc     Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
4924*0a6a1f1dSLionel Sambuc     Values[1] = GetClassName(I->first->getName());
4925f4a2713aSLionel Sambuc     Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
4926f4a2713aSLionel Sambuc     Values[3] = Values[4] =
4927f4a2713aSLionel Sambuc       llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
4928f4a2713aSLionel Sambuc     I->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
4929f4a2713aSLionel Sambuc                                                         Values));
4930*0a6a1f1dSLionel Sambuc     CGM.addCompilerUsedGlobal(I->second);
4931f4a2713aSLionel Sambuc   }
4932f4a2713aSLionel Sambuc 
4933f4a2713aSLionel Sambuc   // Add assembler directives to add lazy undefined symbol references
4934f4a2713aSLionel Sambuc   // for classes which are referenced but not defined. This is
4935f4a2713aSLionel Sambuc   // important for correct linker interaction.
4936f4a2713aSLionel Sambuc   //
4937f4a2713aSLionel Sambuc   // FIXME: It would be nice if we had an LLVM construct for this.
4938f4a2713aSLionel Sambuc   if (!LazySymbols.empty() || !DefinedSymbols.empty()) {
4939f4a2713aSLionel Sambuc     SmallString<256> Asm;
4940f4a2713aSLionel Sambuc     Asm += CGM.getModule().getModuleInlineAsm();
4941f4a2713aSLionel Sambuc     if (!Asm.empty() && Asm.back() != '\n')
4942f4a2713aSLionel Sambuc       Asm += '\n';
4943f4a2713aSLionel Sambuc 
4944f4a2713aSLionel Sambuc     llvm::raw_svector_ostream OS(Asm);
4945f4a2713aSLionel Sambuc     for (llvm::SetVector<IdentifierInfo*>::iterator I = DefinedSymbols.begin(),
4946f4a2713aSLionel Sambuc            e = DefinedSymbols.end(); I != e; ++I)
4947f4a2713aSLionel Sambuc       OS << "\t.objc_class_name_" << (*I)->getName() << "=0\n"
4948f4a2713aSLionel Sambuc          << "\t.globl .objc_class_name_" << (*I)->getName() << "\n";
4949f4a2713aSLionel Sambuc     for (llvm::SetVector<IdentifierInfo*>::iterator I = LazySymbols.begin(),
4950f4a2713aSLionel Sambuc          e = LazySymbols.end(); I != e; ++I) {
4951f4a2713aSLionel Sambuc       OS << "\t.lazy_reference .objc_class_name_" << (*I)->getName() << "\n";
4952f4a2713aSLionel Sambuc     }
4953f4a2713aSLionel Sambuc 
4954f4a2713aSLionel Sambuc     for (size_t i = 0, e = DefinedCategoryNames.size(); i < e; ++i) {
4955f4a2713aSLionel Sambuc       OS << "\t.objc_category_name_" << DefinedCategoryNames[i] << "=0\n"
4956f4a2713aSLionel Sambuc          << "\t.globl .objc_category_name_" << DefinedCategoryNames[i] << "\n";
4957f4a2713aSLionel Sambuc     }
4958f4a2713aSLionel Sambuc 
4959f4a2713aSLionel Sambuc     CGM.getModule().setModuleInlineAsm(OS.str());
4960f4a2713aSLionel Sambuc   }
4961f4a2713aSLionel Sambuc }
4962f4a2713aSLionel Sambuc 
CGObjCNonFragileABIMac(CodeGen::CodeGenModule & cgm)4963f4a2713aSLionel Sambuc CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
4964f4a2713aSLionel Sambuc   : CGObjCCommonMac(cgm),
4965f4a2713aSLionel Sambuc     ObjCTypes(cgm) {
4966*0a6a1f1dSLionel Sambuc   ObjCEmptyCacheVar = ObjCEmptyVtableVar = nullptr;
4967f4a2713aSLionel Sambuc   ObjCABI = 2;
4968f4a2713aSLionel Sambuc }
4969f4a2713aSLionel Sambuc 
4970f4a2713aSLionel Sambuc /* *** */
4971f4a2713aSLionel Sambuc 
ObjCCommonTypesHelper(CodeGen::CodeGenModule & cgm)4972f4a2713aSLionel Sambuc ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
4973*0a6a1f1dSLionel Sambuc   : VMContext(cgm.getLLVMContext()), CGM(cgm), ExternalProtocolPtrTy(nullptr)
4974f4a2713aSLionel Sambuc {
4975f4a2713aSLionel Sambuc   CodeGen::CodeGenTypes &Types = CGM.getTypes();
4976f4a2713aSLionel Sambuc   ASTContext &Ctx = CGM.getContext();
4977f4a2713aSLionel Sambuc 
4978f4a2713aSLionel Sambuc   ShortTy = Types.ConvertType(Ctx.ShortTy);
4979f4a2713aSLionel Sambuc   IntTy = Types.ConvertType(Ctx.IntTy);
4980f4a2713aSLionel Sambuc   LongTy = Types.ConvertType(Ctx.LongTy);
4981f4a2713aSLionel Sambuc   LongLongTy = Types.ConvertType(Ctx.LongLongTy);
4982f4a2713aSLionel Sambuc   Int8PtrTy = CGM.Int8PtrTy;
4983f4a2713aSLionel Sambuc   Int8PtrPtrTy = CGM.Int8PtrPtrTy;
4984f4a2713aSLionel Sambuc 
4985*0a6a1f1dSLionel Sambuc   // arm64 targets use "int" ivar offset variables. All others,
4986*0a6a1f1dSLionel Sambuc   // including OS X x86_64 and Windows x86_64, use "long" ivar offsets.
4987*0a6a1f1dSLionel Sambuc   if (CGM.getTarget().getTriple().getArch() == llvm::Triple::aarch64)
4988*0a6a1f1dSLionel Sambuc     IvarOffsetVarTy = IntTy;
4989*0a6a1f1dSLionel Sambuc   else
4990*0a6a1f1dSLionel Sambuc     IvarOffsetVarTy = LongTy;
4991*0a6a1f1dSLionel Sambuc 
4992f4a2713aSLionel Sambuc   ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType());
4993f4a2713aSLionel Sambuc   PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy);
4994f4a2713aSLionel Sambuc   SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType());
4995f4a2713aSLionel Sambuc 
4996f4a2713aSLionel Sambuc   // I'm not sure I like this. The implicit coordination is a bit
4997f4a2713aSLionel Sambuc   // gross. We should solve this in a reasonable fashion because this
4998f4a2713aSLionel Sambuc   // is a pretty common task (match some runtime data structure with
4999f4a2713aSLionel Sambuc   // an LLVM data structure).
5000f4a2713aSLionel Sambuc 
5001f4a2713aSLionel Sambuc   // FIXME: This is leaked.
5002f4a2713aSLionel Sambuc   // FIXME: Merge with rewriter code?
5003f4a2713aSLionel Sambuc 
5004f4a2713aSLionel Sambuc   // struct _objc_super {
5005f4a2713aSLionel Sambuc   //   id self;
5006f4a2713aSLionel Sambuc   //   Class cls;
5007f4a2713aSLionel Sambuc   // }
5008f4a2713aSLionel Sambuc   RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
5009f4a2713aSLionel Sambuc                                       Ctx.getTranslationUnitDecl(),
5010f4a2713aSLionel Sambuc                                       SourceLocation(), SourceLocation(),
5011f4a2713aSLionel Sambuc                                       &Ctx.Idents.get("_objc_super"));
5012*0a6a1f1dSLionel Sambuc   RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5013*0a6a1f1dSLionel Sambuc                                 nullptr, Ctx.getObjCIdType(), nullptr, nullptr,
5014*0a6a1f1dSLionel Sambuc                                 false, ICIS_NoInit));
5015*0a6a1f1dSLionel Sambuc   RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5016*0a6a1f1dSLionel Sambuc                                 nullptr, Ctx.getObjCClassType(), nullptr,
5017*0a6a1f1dSLionel Sambuc                                 nullptr, false, ICIS_NoInit));
5018f4a2713aSLionel Sambuc   RD->completeDefinition();
5019f4a2713aSLionel Sambuc 
5020f4a2713aSLionel Sambuc   SuperCTy = Ctx.getTagDeclType(RD);
5021f4a2713aSLionel Sambuc   SuperPtrCTy = Ctx.getPointerType(SuperCTy);
5022f4a2713aSLionel Sambuc 
5023f4a2713aSLionel Sambuc   SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
5024f4a2713aSLionel Sambuc   SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
5025f4a2713aSLionel Sambuc 
5026f4a2713aSLionel Sambuc   // struct _prop_t {
5027f4a2713aSLionel Sambuc   //   char *name;
5028f4a2713aSLionel Sambuc   //   char *attributes;
5029f4a2713aSLionel Sambuc   // }
5030f4a2713aSLionel Sambuc   PropertyTy = llvm::StructType::create("struct._prop_t",
5031*0a6a1f1dSLionel Sambuc                                         Int8PtrTy, Int8PtrTy, nullptr);
5032f4a2713aSLionel Sambuc 
5033f4a2713aSLionel Sambuc   // struct _prop_list_t {
5034f4a2713aSLionel Sambuc   //   uint32_t entsize;      // sizeof(struct _prop_t)
5035f4a2713aSLionel Sambuc   //   uint32_t count_of_properties;
5036f4a2713aSLionel Sambuc   //   struct _prop_t prop_list[count_of_properties];
5037f4a2713aSLionel Sambuc   // }
5038f4a2713aSLionel Sambuc   PropertyListTy =
5039f4a2713aSLionel Sambuc     llvm::StructType::create("struct._prop_list_t", IntTy, IntTy,
5040*0a6a1f1dSLionel Sambuc                              llvm::ArrayType::get(PropertyTy, 0), nullptr);
5041f4a2713aSLionel Sambuc   // struct _prop_list_t *
5042f4a2713aSLionel Sambuc   PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
5043f4a2713aSLionel Sambuc 
5044f4a2713aSLionel Sambuc   // struct _objc_method {
5045f4a2713aSLionel Sambuc   //   SEL _cmd;
5046f4a2713aSLionel Sambuc   //   char *method_type;
5047f4a2713aSLionel Sambuc   //   char *_imp;
5048f4a2713aSLionel Sambuc   // }
5049f4a2713aSLionel Sambuc   MethodTy = llvm::StructType::create("struct._objc_method",
5050f4a2713aSLionel Sambuc                                       SelectorPtrTy, Int8PtrTy, Int8PtrTy,
5051*0a6a1f1dSLionel Sambuc                                       nullptr);
5052f4a2713aSLionel Sambuc 
5053f4a2713aSLionel Sambuc   // struct _objc_cache *
5054f4a2713aSLionel Sambuc   CacheTy = llvm::StructType::create(VMContext, "struct._objc_cache");
5055f4a2713aSLionel Sambuc   CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
5056f4a2713aSLionel Sambuc 
5057f4a2713aSLionel Sambuc }
5058f4a2713aSLionel Sambuc 
ObjCTypesHelper(CodeGen::CodeGenModule & cgm)5059f4a2713aSLionel Sambuc ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
5060f4a2713aSLionel Sambuc   : ObjCCommonTypesHelper(cgm) {
5061f4a2713aSLionel Sambuc   // struct _objc_method_description {
5062f4a2713aSLionel Sambuc   //   SEL name;
5063f4a2713aSLionel Sambuc   //   char *types;
5064f4a2713aSLionel Sambuc   // }
5065f4a2713aSLionel Sambuc   MethodDescriptionTy =
5066f4a2713aSLionel Sambuc     llvm::StructType::create("struct._objc_method_description",
5067*0a6a1f1dSLionel Sambuc                              SelectorPtrTy, Int8PtrTy, nullptr);
5068f4a2713aSLionel Sambuc 
5069f4a2713aSLionel Sambuc   // struct _objc_method_description_list {
5070f4a2713aSLionel Sambuc   //   int count;
5071f4a2713aSLionel Sambuc   //   struct _objc_method_description[1];
5072f4a2713aSLionel Sambuc   // }
5073*0a6a1f1dSLionel Sambuc   MethodDescriptionListTy = llvm::StructType::create(
5074*0a6a1f1dSLionel Sambuc       "struct._objc_method_description_list", IntTy,
5075*0a6a1f1dSLionel Sambuc       llvm::ArrayType::get(MethodDescriptionTy, 0), nullptr);
5076f4a2713aSLionel Sambuc 
5077f4a2713aSLionel Sambuc   // struct _objc_method_description_list *
5078f4a2713aSLionel Sambuc   MethodDescriptionListPtrTy =
5079f4a2713aSLionel Sambuc     llvm::PointerType::getUnqual(MethodDescriptionListTy);
5080f4a2713aSLionel Sambuc 
5081f4a2713aSLionel Sambuc   // Protocol description structures
5082f4a2713aSLionel Sambuc 
5083f4a2713aSLionel Sambuc   // struct _objc_protocol_extension {
5084f4a2713aSLionel Sambuc   //   uint32_t size;  // sizeof(struct _objc_protocol_extension)
5085f4a2713aSLionel Sambuc   //   struct _objc_method_description_list *optional_instance_methods;
5086f4a2713aSLionel Sambuc   //   struct _objc_method_description_list *optional_class_methods;
5087f4a2713aSLionel Sambuc   //   struct _objc_property_list *instance_properties;
5088f4a2713aSLionel Sambuc   //   const char ** extendedMethodTypes;
5089f4a2713aSLionel Sambuc   // }
5090f4a2713aSLionel Sambuc   ProtocolExtensionTy =
5091f4a2713aSLionel Sambuc     llvm::StructType::create("struct._objc_protocol_extension",
5092f4a2713aSLionel Sambuc                              IntTy, MethodDescriptionListPtrTy,
5093f4a2713aSLionel Sambuc                              MethodDescriptionListPtrTy, PropertyListPtrTy,
5094*0a6a1f1dSLionel Sambuc                              Int8PtrPtrTy, nullptr);
5095f4a2713aSLionel Sambuc 
5096f4a2713aSLionel Sambuc   // struct _objc_protocol_extension *
5097f4a2713aSLionel Sambuc   ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
5098f4a2713aSLionel Sambuc 
5099f4a2713aSLionel Sambuc   // Handle recursive construction of Protocol and ProtocolList types
5100f4a2713aSLionel Sambuc 
5101f4a2713aSLionel Sambuc   ProtocolTy =
5102f4a2713aSLionel Sambuc     llvm::StructType::create(VMContext, "struct._objc_protocol");
5103f4a2713aSLionel Sambuc 
5104f4a2713aSLionel Sambuc   ProtocolListTy =
5105f4a2713aSLionel Sambuc     llvm::StructType::create(VMContext, "struct._objc_protocol_list");
5106f4a2713aSLionel Sambuc   ProtocolListTy->setBody(llvm::PointerType::getUnqual(ProtocolListTy),
5107f4a2713aSLionel Sambuc                           LongTy,
5108f4a2713aSLionel Sambuc                           llvm::ArrayType::get(ProtocolTy, 0),
5109*0a6a1f1dSLionel Sambuc                           nullptr);
5110f4a2713aSLionel Sambuc 
5111f4a2713aSLionel Sambuc   // struct _objc_protocol {
5112f4a2713aSLionel Sambuc   //   struct _objc_protocol_extension *isa;
5113f4a2713aSLionel Sambuc   //   char *protocol_name;
5114f4a2713aSLionel Sambuc   //   struct _objc_protocol **_objc_protocol_list;
5115f4a2713aSLionel Sambuc   //   struct _objc_method_description_list *instance_methods;
5116f4a2713aSLionel Sambuc   //   struct _objc_method_description_list *class_methods;
5117f4a2713aSLionel Sambuc   // }
5118f4a2713aSLionel Sambuc   ProtocolTy->setBody(ProtocolExtensionPtrTy, Int8PtrTy,
5119f4a2713aSLionel Sambuc                       llvm::PointerType::getUnqual(ProtocolListTy),
5120f4a2713aSLionel Sambuc                       MethodDescriptionListPtrTy,
5121f4a2713aSLionel Sambuc                       MethodDescriptionListPtrTy,
5122*0a6a1f1dSLionel Sambuc                       nullptr);
5123f4a2713aSLionel Sambuc 
5124f4a2713aSLionel Sambuc   // struct _objc_protocol_list *
5125f4a2713aSLionel Sambuc   ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
5126f4a2713aSLionel Sambuc 
5127f4a2713aSLionel Sambuc   ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
5128f4a2713aSLionel Sambuc 
5129f4a2713aSLionel Sambuc   // Class description structures
5130f4a2713aSLionel Sambuc 
5131f4a2713aSLionel Sambuc   // struct _objc_ivar {
5132f4a2713aSLionel Sambuc   //   char *ivar_name;
5133f4a2713aSLionel Sambuc   //   char *ivar_type;
5134f4a2713aSLionel Sambuc   //   int  ivar_offset;
5135f4a2713aSLionel Sambuc   // }
5136f4a2713aSLionel Sambuc   IvarTy = llvm::StructType::create("struct._objc_ivar",
5137*0a6a1f1dSLionel Sambuc                                     Int8PtrTy, Int8PtrTy, IntTy, nullptr);
5138f4a2713aSLionel Sambuc 
5139f4a2713aSLionel Sambuc   // struct _objc_ivar_list *
5140f4a2713aSLionel Sambuc   IvarListTy =
5141f4a2713aSLionel Sambuc     llvm::StructType::create(VMContext, "struct._objc_ivar_list");
5142f4a2713aSLionel Sambuc   IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
5143f4a2713aSLionel Sambuc 
5144f4a2713aSLionel Sambuc   // struct _objc_method_list *
5145f4a2713aSLionel Sambuc   MethodListTy =
5146f4a2713aSLionel Sambuc     llvm::StructType::create(VMContext, "struct._objc_method_list");
5147f4a2713aSLionel Sambuc   MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
5148f4a2713aSLionel Sambuc 
5149f4a2713aSLionel Sambuc   // struct _objc_class_extension *
5150f4a2713aSLionel Sambuc   ClassExtensionTy =
5151f4a2713aSLionel Sambuc     llvm::StructType::create("struct._objc_class_extension",
5152*0a6a1f1dSLionel Sambuc                              IntTy, Int8PtrTy, PropertyListPtrTy, nullptr);
5153f4a2713aSLionel Sambuc   ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
5154f4a2713aSLionel Sambuc 
5155f4a2713aSLionel Sambuc   ClassTy = llvm::StructType::create(VMContext, "struct._objc_class");
5156f4a2713aSLionel Sambuc 
5157f4a2713aSLionel Sambuc   // struct _objc_class {
5158f4a2713aSLionel Sambuc   //   Class isa;
5159f4a2713aSLionel Sambuc   //   Class super_class;
5160f4a2713aSLionel Sambuc   //   char *name;
5161f4a2713aSLionel Sambuc   //   long version;
5162f4a2713aSLionel Sambuc   //   long info;
5163f4a2713aSLionel Sambuc   //   long instance_size;
5164f4a2713aSLionel Sambuc   //   struct _objc_ivar_list *ivars;
5165f4a2713aSLionel Sambuc   //   struct _objc_method_list *methods;
5166f4a2713aSLionel Sambuc   //   struct _objc_cache *cache;
5167f4a2713aSLionel Sambuc   //   struct _objc_protocol_list *protocols;
5168f4a2713aSLionel Sambuc   //   char *ivar_layout;
5169f4a2713aSLionel Sambuc   //   struct _objc_class_ext *ext;
5170f4a2713aSLionel Sambuc   // };
5171f4a2713aSLionel Sambuc   ClassTy->setBody(llvm::PointerType::getUnqual(ClassTy),
5172f4a2713aSLionel Sambuc                    llvm::PointerType::getUnqual(ClassTy),
5173f4a2713aSLionel Sambuc                    Int8PtrTy,
5174f4a2713aSLionel Sambuc                    LongTy,
5175f4a2713aSLionel Sambuc                    LongTy,
5176f4a2713aSLionel Sambuc                    LongTy,
5177f4a2713aSLionel Sambuc                    IvarListPtrTy,
5178f4a2713aSLionel Sambuc                    MethodListPtrTy,
5179f4a2713aSLionel Sambuc                    CachePtrTy,
5180f4a2713aSLionel Sambuc                    ProtocolListPtrTy,
5181f4a2713aSLionel Sambuc                    Int8PtrTy,
5182f4a2713aSLionel Sambuc                    ClassExtensionPtrTy,
5183*0a6a1f1dSLionel Sambuc                    nullptr);
5184f4a2713aSLionel Sambuc 
5185f4a2713aSLionel Sambuc   ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
5186f4a2713aSLionel Sambuc 
5187f4a2713aSLionel Sambuc   // struct _objc_category {
5188f4a2713aSLionel Sambuc   //   char *category_name;
5189f4a2713aSLionel Sambuc   //   char *class_name;
5190f4a2713aSLionel Sambuc   //   struct _objc_method_list *instance_method;
5191f4a2713aSLionel Sambuc   //   struct _objc_method_list *class_method;
5192f4a2713aSLionel Sambuc   //   uint32_t size;  // sizeof(struct _objc_category)
5193f4a2713aSLionel Sambuc   //   struct _objc_property_list *instance_properties;// category's @property
5194f4a2713aSLionel Sambuc   // }
5195f4a2713aSLionel Sambuc   CategoryTy =
5196f4a2713aSLionel Sambuc     llvm::StructType::create("struct._objc_category",
5197f4a2713aSLionel Sambuc                              Int8PtrTy, Int8PtrTy, MethodListPtrTy,
5198f4a2713aSLionel Sambuc                              MethodListPtrTy, ProtocolListPtrTy,
5199*0a6a1f1dSLionel Sambuc                              IntTy, PropertyListPtrTy, nullptr);
5200f4a2713aSLionel Sambuc 
5201f4a2713aSLionel Sambuc   // Global metadata structures
5202f4a2713aSLionel Sambuc 
5203f4a2713aSLionel Sambuc   // struct _objc_symtab {
5204f4a2713aSLionel Sambuc   //   long sel_ref_cnt;
5205f4a2713aSLionel Sambuc   //   SEL *refs;
5206f4a2713aSLionel Sambuc   //   short cls_def_cnt;
5207f4a2713aSLionel Sambuc   //   short cat_def_cnt;
5208f4a2713aSLionel Sambuc   //   char *defs[cls_def_cnt + cat_def_cnt];
5209f4a2713aSLionel Sambuc   // }
5210f4a2713aSLionel Sambuc   SymtabTy =
5211f4a2713aSLionel Sambuc     llvm::StructType::create("struct._objc_symtab",
5212f4a2713aSLionel Sambuc                              LongTy, SelectorPtrTy, ShortTy, ShortTy,
5213*0a6a1f1dSLionel Sambuc                              llvm::ArrayType::get(Int8PtrTy, 0), nullptr);
5214f4a2713aSLionel Sambuc   SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
5215f4a2713aSLionel Sambuc 
5216f4a2713aSLionel Sambuc   // struct _objc_module {
5217f4a2713aSLionel Sambuc   //   long version;
5218f4a2713aSLionel Sambuc   //   long size;   // sizeof(struct _objc_module)
5219f4a2713aSLionel Sambuc   //   char *name;
5220f4a2713aSLionel Sambuc   //   struct _objc_symtab* symtab;
5221f4a2713aSLionel Sambuc   //  }
5222f4a2713aSLionel Sambuc   ModuleTy =
5223f4a2713aSLionel Sambuc     llvm::StructType::create("struct._objc_module",
5224*0a6a1f1dSLionel Sambuc                              LongTy, LongTy, Int8PtrTy, SymtabPtrTy, nullptr);
5225f4a2713aSLionel Sambuc 
5226f4a2713aSLionel Sambuc 
5227f4a2713aSLionel Sambuc   // FIXME: This is the size of the setjmp buffer and should be target
5228f4a2713aSLionel Sambuc   // specific. 18 is what's used on 32-bit X86.
5229f4a2713aSLionel Sambuc   uint64_t SetJmpBufferSize = 18;
5230f4a2713aSLionel Sambuc 
5231f4a2713aSLionel Sambuc   // Exceptions
5232f4a2713aSLionel Sambuc   llvm::Type *StackPtrTy = llvm::ArrayType::get(CGM.Int8PtrTy, 4);
5233f4a2713aSLionel Sambuc 
5234f4a2713aSLionel Sambuc   ExceptionDataTy =
5235f4a2713aSLionel Sambuc     llvm::StructType::create("struct._objc_exception_data",
5236f4a2713aSLionel Sambuc                              llvm::ArrayType::get(CGM.Int32Ty,SetJmpBufferSize),
5237*0a6a1f1dSLionel Sambuc                              StackPtrTy, nullptr);
5238f4a2713aSLionel Sambuc 
5239f4a2713aSLionel Sambuc }
5240f4a2713aSLionel Sambuc 
ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule & cgm)5241f4a2713aSLionel Sambuc ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
5242f4a2713aSLionel Sambuc   : ObjCCommonTypesHelper(cgm) {
5243f4a2713aSLionel Sambuc   // struct _method_list_t {
5244f4a2713aSLionel Sambuc   //   uint32_t entsize;  // sizeof(struct _objc_method)
5245f4a2713aSLionel Sambuc   //   uint32_t method_count;
5246f4a2713aSLionel Sambuc   //   struct _objc_method method_list[method_count];
5247f4a2713aSLionel Sambuc   // }
5248f4a2713aSLionel Sambuc   MethodListnfABITy =
5249f4a2713aSLionel Sambuc     llvm::StructType::create("struct.__method_list_t", IntTy, IntTy,
5250*0a6a1f1dSLionel Sambuc                              llvm::ArrayType::get(MethodTy, 0), nullptr);
5251f4a2713aSLionel Sambuc   // struct method_list_t *
5252f4a2713aSLionel Sambuc   MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
5253f4a2713aSLionel Sambuc 
5254f4a2713aSLionel Sambuc   // struct _protocol_t {
5255f4a2713aSLionel Sambuc   //   id isa;  // NULL
5256f4a2713aSLionel Sambuc   //   const char * const protocol_name;
5257f4a2713aSLionel Sambuc   //   const struct _protocol_list_t * protocol_list; // super protocols
5258f4a2713aSLionel Sambuc   //   const struct method_list_t * const instance_methods;
5259f4a2713aSLionel Sambuc   //   const struct method_list_t * const class_methods;
5260f4a2713aSLionel Sambuc   //   const struct method_list_t *optionalInstanceMethods;
5261f4a2713aSLionel Sambuc   //   const struct method_list_t *optionalClassMethods;
5262f4a2713aSLionel Sambuc   //   const struct _prop_list_t * properties;
5263f4a2713aSLionel Sambuc   //   const uint32_t size;  // sizeof(struct _protocol_t)
5264f4a2713aSLionel Sambuc   //   const uint32_t flags;  // = 0
5265f4a2713aSLionel Sambuc   //   const char ** extendedMethodTypes;
5266f4a2713aSLionel Sambuc   // }
5267f4a2713aSLionel Sambuc 
5268f4a2713aSLionel Sambuc   // Holder for struct _protocol_list_t *
5269f4a2713aSLionel Sambuc   ProtocolListnfABITy =
5270f4a2713aSLionel Sambuc     llvm::StructType::create(VMContext, "struct._objc_protocol_list");
5271f4a2713aSLionel Sambuc 
5272f4a2713aSLionel Sambuc   ProtocolnfABITy =
5273f4a2713aSLionel Sambuc     llvm::StructType::create("struct._protocol_t", ObjectPtrTy, Int8PtrTy,
5274f4a2713aSLionel Sambuc                              llvm::PointerType::getUnqual(ProtocolListnfABITy),
5275f4a2713aSLionel Sambuc                              MethodListnfABIPtrTy, MethodListnfABIPtrTy,
5276f4a2713aSLionel Sambuc                              MethodListnfABIPtrTy, MethodListnfABIPtrTy,
5277f4a2713aSLionel Sambuc                              PropertyListPtrTy, IntTy, IntTy, Int8PtrPtrTy,
5278*0a6a1f1dSLionel Sambuc                              nullptr);
5279f4a2713aSLionel Sambuc 
5280f4a2713aSLionel Sambuc   // struct _protocol_t*
5281f4a2713aSLionel Sambuc   ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
5282f4a2713aSLionel Sambuc 
5283f4a2713aSLionel Sambuc   // struct _protocol_list_t {
5284f4a2713aSLionel Sambuc   //   long protocol_count;   // Note, this is 32/64 bit
5285f4a2713aSLionel Sambuc   //   struct _protocol_t *[protocol_count];
5286f4a2713aSLionel Sambuc   // }
5287f4a2713aSLionel Sambuc   ProtocolListnfABITy->setBody(LongTy,
5288f4a2713aSLionel Sambuc                                llvm::ArrayType::get(ProtocolnfABIPtrTy, 0),
5289*0a6a1f1dSLionel Sambuc                                nullptr);
5290f4a2713aSLionel Sambuc 
5291f4a2713aSLionel Sambuc   // struct _objc_protocol_list*
5292f4a2713aSLionel Sambuc   ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
5293f4a2713aSLionel Sambuc 
5294f4a2713aSLionel Sambuc   // struct _ivar_t {
5295*0a6a1f1dSLionel Sambuc   //   unsigned [long] int *offset;  // pointer to ivar offset location
5296f4a2713aSLionel Sambuc   //   char *name;
5297f4a2713aSLionel Sambuc   //   char *type;
5298f4a2713aSLionel Sambuc   //   uint32_t alignment;
5299f4a2713aSLionel Sambuc   //   uint32_t size;
5300f4a2713aSLionel Sambuc   // }
5301*0a6a1f1dSLionel Sambuc   IvarnfABITy = llvm::StructType::create(
5302*0a6a1f1dSLionel Sambuc       "struct._ivar_t", llvm::PointerType::getUnqual(IvarOffsetVarTy),
5303*0a6a1f1dSLionel Sambuc       Int8PtrTy, Int8PtrTy, IntTy, IntTy, nullptr);
5304f4a2713aSLionel Sambuc 
5305f4a2713aSLionel Sambuc   // struct _ivar_list_t {
5306f4a2713aSLionel Sambuc   //   uint32 entsize;  // sizeof(struct _ivar_t)
5307f4a2713aSLionel Sambuc   //   uint32 count;
5308f4a2713aSLionel Sambuc   //   struct _iver_t list[count];
5309f4a2713aSLionel Sambuc   // }
5310f4a2713aSLionel Sambuc   IvarListnfABITy =
5311f4a2713aSLionel Sambuc     llvm::StructType::create("struct._ivar_list_t", IntTy, IntTy,
5312*0a6a1f1dSLionel Sambuc                              llvm::ArrayType::get(IvarnfABITy, 0), nullptr);
5313f4a2713aSLionel Sambuc 
5314f4a2713aSLionel Sambuc   IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
5315f4a2713aSLionel Sambuc 
5316f4a2713aSLionel Sambuc   // struct _class_ro_t {
5317f4a2713aSLionel Sambuc   //   uint32_t const flags;
5318f4a2713aSLionel Sambuc   //   uint32_t const instanceStart;
5319f4a2713aSLionel Sambuc   //   uint32_t const instanceSize;
5320f4a2713aSLionel Sambuc   //   uint32_t const reserved;  // only when building for 64bit targets
5321f4a2713aSLionel Sambuc   //   const uint8_t * const ivarLayout;
5322f4a2713aSLionel Sambuc   //   const char *const name;
5323f4a2713aSLionel Sambuc   //   const struct _method_list_t * const baseMethods;
5324f4a2713aSLionel Sambuc   //   const struct _objc_protocol_list *const baseProtocols;
5325f4a2713aSLionel Sambuc   //   const struct _ivar_list_t *const ivars;
5326f4a2713aSLionel Sambuc   //   const uint8_t * const weakIvarLayout;
5327f4a2713aSLionel Sambuc   //   const struct _prop_list_t * const properties;
5328f4a2713aSLionel Sambuc   // }
5329f4a2713aSLionel Sambuc 
5330f4a2713aSLionel Sambuc   // FIXME. Add 'reserved' field in 64bit abi mode!
5331f4a2713aSLionel Sambuc   ClassRonfABITy = llvm::StructType::create("struct._class_ro_t",
5332f4a2713aSLionel Sambuc                                             IntTy, IntTy, IntTy, Int8PtrTy,
5333f4a2713aSLionel Sambuc                                             Int8PtrTy, MethodListnfABIPtrTy,
5334f4a2713aSLionel Sambuc                                             ProtocolListnfABIPtrTy,
5335f4a2713aSLionel Sambuc                                             IvarListnfABIPtrTy,
5336*0a6a1f1dSLionel Sambuc                                             Int8PtrTy, PropertyListPtrTy,
5337*0a6a1f1dSLionel Sambuc                                             nullptr);
5338f4a2713aSLionel Sambuc 
5339f4a2713aSLionel Sambuc   // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
5340f4a2713aSLionel Sambuc   llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
5341f4a2713aSLionel Sambuc   ImpnfABITy = llvm::FunctionType::get(ObjectPtrTy, params, false)
5342f4a2713aSLionel Sambuc                  ->getPointerTo();
5343f4a2713aSLionel Sambuc 
5344f4a2713aSLionel Sambuc   // struct _class_t {
5345f4a2713aSLionel Sambuc   //   struct _class_t *isa;
5346f4a2713aSLionel Sambuc   //   struct _class_t * const superclass;
5347f4a2713aSLionel Sambuc   //   void *cache;
5348f4a2713aSLionel Sambuc   //   IMP *vtable;
5349f4a2713aSLionel Sambuc   //   struct class_ro_t *ro;
5350f4a2713aSLionel Sambuc   // }
5351f4a2713aSLionel Sambuc 
5352f4a2713aSLionel Sambuc   ClassnfABITy = llvm::StructType::create(VMContext, "struct._class_t");
5353f4a2713aSLionel Sambuc   ClassnfABITy->setBody(llvm::PointerType::getUnqual(ClassnfABITy),
5354f4a2713aSLionel Sambuc                         llvm::PointerType::getUnqual(ClassnfABITy),
5355f4a2713aSLionel Sambuc                         CachePtrTy,
5356f4a2713aSLionel Sambuc                         llvm::PointerType::getUnqual(ImpnfABITy),
5357f4a2713aSLionel Sambuc                         llvm::PointerType::getUnqual(ClassRonfABITy),
5358*0a6a1f1dSLionel Sambuc                         nullptr);
5359f4a2713aSLionel Sambuc 
5360f4a2713aSLionel Sambuc   // LLVM for struct _class_t *
5361f4a2713aSLionel Sambuc   ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
5362f4a2713aSLionel Sambuc 
5363f4a2713aSLionel Sambuc   // struct _category_t {
5364f4a2713aSLionel Sambuc   //   const char * const name;
5365f4a2713aSLionel Sambuc   //   struct _class_t *const cls;
5366f4a2713aSLionel Sambuc   //   const struct _method_list_t * const instance_methods;
5367f4a2713aSLionel Sambuc   //   const struct _method_list_t * const class_methods;
5368f4a2713aSLionel Sambuc   //   const struct _protocol_list_t * const protocols;
5369f4a2713aSLionel Sambuc   //   const struct _prop_list_t * const properties;
5370f4a2713aSLionel Sambuc   // }
5371f4a2713aSLionel Sambuc   CategorynfABITy = llvm::StructType::create("struct._category_t",
5372f4a2713aSLionel Sambuc                                              Int8PtrTy, ClassnfABIPtrTy,
5373f4a2713aSLionel Sambuc                                              MethodListnfABIPtrTy,
5374f4a2713aSLionel Sambuc                                              MethodListnfABIPtrTy,
5375f4a2713aSLionel Sambuc                                              ProtocolListnfABIPtrTy,
5376f4a2713aSLionel Sambuc                                              PropertyListPtrTy,
5377*0a6a1f1dSLionel Sambuc                                              nullptr);
5378f4a2713aSLionel Sambuc 
5379f4a2713aSLionel Sambuc   // New types for nonfragile abi messaging.
5380f4a2713aSLionel Sambuc   CodeGen::CodeGenTypes &Types = CGM.getTypes();
5381f4a2713aSLionel Sambuc   ASTContext &Ctx = CGM.getContext();
5382f4a2713aSLionel Sambuc 
5383f4a2713aSLionel Sambuc   // MessageRefTy - LLVM for:
5384f4a2713aSLionel Sambuc   // struct _message_ref_t {
5385f4a2713aSLionel Sambuc   //   IMP messenger;
5386f4a2713aSLionel Sambuc   //   SEL name;
5387f4a2713aSLionel Sambuc   // };
5388f4a2713aSLionel Sambuc 
5389f4a2713aSLionel Sambuc   // First the clang type for struct _message_ref_t
5390f4a2713aSLionel Sambuc   RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
5391f4a2713aSLionel Sambuc                                       Ctx.getTranslationUnitDecl(),
5392f4a2713aSLionel Sambuc                                       SourceLocation(), SourceLocation(),
5393f4a2713aSLionel Sambuc                                       &Ctx.Idents.get("_message_ref_t"));
5394*0a6a1f1dSLionel Sambuc   RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5395*0a6a1f1dSLionel Sambuc                                 nullptr, Ctx.VoidPtrTy, nullptr, nullptr, false,
5396f4a2713aSLionel Sambuc                                 ICIS_NoInit));
5397*0a6a1f1dSLionel Sambuc   RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5398*0a6a1f1dSLionel Sambuc                                 nullptr, Ctx.getObjCSelType(), nullptr, nullptr,
5399*0a6a1f1dSLionel Sambuc                                 false, ICIS_NoInit));
5400f4a2713aSLionel Sambuc   RD->completeDefinition();
5401f4a2713aSLionel Sambuc 
5402f4a2713aSLionel Sambuc   MessageRefCTy = Ctx.getTagDeclType(RD);
5403f4a2713aSLionel Sambuc   MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
5404f4a2713aSLionel Sambuc   MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
5405f4a2713aSLionel Sambuc 
5406f4a2713aSLionel Sambuc   // MessageRefPtrTy - LLVM for struct _message_ref_t*
5407f4a2713aSLionel Sambuc   MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
5408f4a2713aSLionel Sambuc 
5409f4a2713aSLionel Sambuc   // SuperMessageRefTy - LLVM for:
5410f4a2713aSLionel Sambuc   // struct _super_message_ref_t {
5411f4a2713aSLionel Sambuc   //   SUPER_IMP messenger;
5412f4a2713aSLionel Sambuc   //   SEL name;
5413f4a2713aSLionel Sambuc   // };
5414f4a2713aSLionel Sambuc   SuperMessageRefTy =
5415f4a2713aSLionel Sambuc     llvm::StructType::create("struct._super_message_ref_t",
5416*0a6a1f1dSLionel Sambuc                              ImpnfABITy, SelectorPtrTy, nullptr);
5417f4a2713aSLionel Sambuc 
5418f4a2713aSLionel Sambuc   // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
5419f4a2713aSLionel Sambuc   SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
5420f4a2713aSLionel Sambuc 
5421f4a2713aSLionel Sambuc 
5422f4a2713aSLionel Sambuc   // struct objc_typeinfo {
5423f4a2713aSLionel Sambuc   //   const void** vtable; // objc_ehtype_vtable + 2
5424f4a2713aSLionel Sambuc   //   const char*  name;    // c++ typeinfo string
5425f4a2713aSLionel Sambuc   //   Class        cls;
5426f4a2713aSLionel Sambuc   // };
5427f4a2713aSLionel Sambuc   EHTypeTy =
5428f4a2713aSLionel Sambuc     llvm::StructType::create("struct._objc_typeinfo",
5429f4a2713aSLionel Sambuc                              llvm::PointerType::getUnqual(Int8PtrTy),
5430*0a6a1f1dSLionel Sambuc                              Int8PtrTy, ClassnfABIPtrTy, nullptr);
5431f4a2713aSLionel Sambuc   EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
5432f4a2713aSLionel Sambuc }
5433f4a2713aSLionel Sambuc 
ModuleInitFunction()5434f4a2713aSLionel Sambuc llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
5435f4a2713aSLionel Sambuc   FinishNonFragileABIModule();
5436f4a2713aSLionel Sambuc 
5437*0a6a1f1dSLionel Sambuc   return nullptr;
5438f4a2713aSLionel Sambuc }
5439f4a2713aSLionel Sambuc 
5440f4a2713aSLionel Sambuc void CGObjCNonFragileABIMac::
AddModuleClassList(ArrayRef<llvm::GlobalValue * > Container,const char * SymbolName,const char * SectionName)5441f4a2713aSLionel Sambuc AddModuleClassList(ArrayRef<llvm::GlobalValue*> Container,
5442f4a2713aSLionel Sambuc                    const char *SymbolName,
5443f4a2713aSLionel Sambuc                    const char *SectionName) {
5444f4a2713aSLionel Sambuc   unsigned NumClasses = Container.size();
5445f4a2713aSLionel Sambuc 
5446f4a2713aSLionel Sambuc   if (!NumClasses)
5447f4a2713aSLionel Sambuc     return;
5448f4a2713aSLionel Sambuc 
5449f4a2713aSLionel Sambuc   SmallVector<llvm::Constant*, 8> Symbols(NumClasses);
5450f4a2713aSLionel Sambuc   for (unsigned i=0; i<NumClasses; i++)
5451f4a2713aSLionel Sambuc     Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i],
5452f4a2713aSLionel Sambuc                                                 ObjCTypes.Int8PtrTy);
5453f4a2713aSLionel Sambuc   llvm::Constant *Init =
5454f4a2713aSLionel Sambuc     llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
5455f4a2713aSLionel Sambuc                                                   Symbols.size()),
5456f4a2713aSLionel Sambuc                              Symbols);
5457f4a2713aSLionel Sambuc 
5458f4a2713aSLionel Sambuc   llvm::GlobalVariable *GV =
5459f4a2713aSLionel Sambuc     new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
5460*0a6a1f1dSLionel Sambuc                              llvm::GlobalValue::PrivateLinkage,
5461f4a2713aSLionel Sambuc                              Init,
5462f4a2713aSLionel Sambuc                              SymbolName);
5463f4a2713aSLionel Sambuc   GV->setAlignment(CGM.getDataLayout().getABITypeAlignment(Init->getType()));
5464f4a2713aSLionel Sambuc   GV->setSection(SectionName);
5465*0a6a1f1dSLionel Sambuc   CGM.addCompilerUsedGlobal(GV);
5466f4a2713aSLionel Sambuc }
5467f4a2713aSLionel Sambuc 
FinishNonFragileABIModule()5468f4a2713aSLionel Sambuc void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
5469f4a2713aSLionel Sambuc   // nonfragile abi has no module definition.
5470f4a2713aSLionel Sambuc 
5471f4a2713aSLionel Sambuc   // Build list of all implemented class addresses in array
5472f4a2713aSLionel Sambuc   // L_OBJC_LABEL_CLASS_$.
5473*0a6a1f1dSLionel Sambuc 
5474*0a6a1f1dSLionel Sambuc   for (unsigned i=0, NumClasses=ImplementedClasses.size(); i<NumClasses; i++) {
5475*0a6a1f1dSLionel Sambuc     const ObjCInterfaceDecl *ID = ImplementedClasses[i];
5476*0a6a1f1dSLionel Sambuc     assert(ID);
5477*0a6a1f1dSLionel Sambuc     if (ObjCImplementationDecl *IMP = ID->getImplementation())
5478*0a6a1f1dSLionel Sambuc       // We are implementing a weak imported interface. Give it external linkage
5479*0a6a1f1dSLionel Sambuc       if (ID->isWeakImported() && !IMP->isWeakImported()) {
5480*0a6a1f1dSLionel Sambuc         DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
5481*0a6a1f1dSLionel Sambuc         DefinedMetaClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
5482*0a6a1f1dSLionel Sambuc       }
5483*0a6a1f1dSLionel Sambuc   }
5484*0a6a1f1dSLionel Sambuc 
5485*0a6a1f1dSLionel Sambuc   AddModuleClassList(DefinedClasses, "OBJC_LABEL_CLASS_$",
5486f4a2713aSLionel Sambuc                      "__DATA, __objc_classlist, regular, no_dead_strip");
5487f4a2713aSLionel Sambuc 
5488*0a6a1f1dSLionel Sambuc   AddModuleClassList(DefinedNonLazyClasses, "OBJC_LABEL_NONLAZY_CLASS_$",
5489f4a2713aSLionel Sambuc                      "__DATA, __objc_nlclslist, regular, no_dead_strip");
5490f4a2713aSLionel Sambuc 
5491f4a2713aSLionel Sambuc   // Build list of all implemented category addresses in array
5492f4a2713aSLionel Sambuc   // L_OBJC_LABEL_CATEGORY_$.
5493*0a6a1f1dSLionel Sambuc   AddModuleClassList(DefinedCategories, "OBJC_LABEL_CATEGORY_$",
5494f4a2713aSLionel Sambuc                      "__DATA, __objc_catlist, regular, no_dead_strip");
5495*0a6a1f1dSLionel Sambuc   AddModuleClassList(DefinedNonLazyCategories, "OBJC_LABEL_NONLAZY_CATEGORY_$",
5496f4a2713aSLionel Sambuc                      "__DATA, __objc_nlcatlist, regular, no_dead_strip");
5497f4a2713aSLionel Sambuc 
5498f4a2713aSLionel Sambuc   EmitImageInfo();
5499f4a2713aSLionel Sambuc }
5500f4a2713aSLionel Sambuc 
5501f4a2713aSLionel Sambuc /// isVTableDispatchedSelector - Returns true if SEL is not in the list of
5502f4a2713aSLionel Sambuc /// VTableDispatchMethods; false otherwise. What this means is that
5503f4a2713aSLionel Sambuc /// except for the 19 selectors in the list, we generate 32bit-style
5504f4a2713aSLionel Sambuc /// message dispatch call for all the rest.
isVTableDispatchedSelector(Selector Sel)5505f4a2713aSLionel Sambuc bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) {
5506f4a2713aSLionel Sambuc   // At various points we've experimented with using vtable-based
5507f4a2713aSLionel Sambuc   // dispatch for all methods.
5508f4a2713aSLionel Sambuc   switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
5509f4a2713aSLionel Sambuc   case CodeGenOptions::Legacy:
5510f4a2713aSLionel Sambuc     return false;
5511f4a2713aSLionel Sambuc   case CodeGenOptions::NonLegacy:
5512f4a2713aSLionel Sambuc     return true;
5513f4a2713aSLionel Sambuc   case CodeGenOptions::Mixed:
5514f4a2713aSLionel Sambuc     break;
5515f4a2713aSLionel Sambuc   }
5516f4a2713aSLionel Sambuc 
5517f4a2713aSLionel Sambuc   // If so, see whether this selector is in the white-list of things which must
5518f4a2713aSLionel Sambuc   // use the new dispatch convention. We lazily build a dense set for this.
5519f4a2713aSLionel Sambuc   if (VTableDispatchMethods.empty()) {
5520f4a2713aSLionel Sambuc     VTableDispatchMethods.insert(GetNullarySelector("alloc"));
5521f4a2713aSLionel Sambuc     VTableDispatchMethods.insert(GetNullarySelector("class"));
5522f4a2713aSLionel Sambuc     VTableDispatchMethods.insert(GetNullarySelector("self"));
5523f4a2713aSLionel Sambuc     VTableDispatchMethods.insert(GetNullarySelector("isFlipped"));
5524f4a2713aSLionel Sambuc     VTableDispatchMethods.insert(GetNullarySelector("length"));
5525f4a2713aSLionel Sambuc     VTableDispatchMethods.insert(GetNullarySelector("count"));
5526f4a2713aSLionel Sambuc 
5527f4a2713aSLionel Sambuc     // These are vtable-based if GC is disabled.
5528f4a2713aSLionel Sambuc     // Optimistically use vtable dispatch for hybrid compiles.
5529f4a2713aSLionel Sambuc     if (CGM.getLangOpts().getGC() != LangOptions::GCOnly) {
5530f4a2713aSLionel Sambuc       VTableDispatchMethods.insert(GetNullarySelector("retain"));
5531f4a2713aSLionel Sambuc       VTableDispatchMethods.insert(GetNullarySelector("release"));
5532f4a2713aSLionel Sambuc       VTableDispatchMethods.insert(GetNullarySelector("autorelease"));
5533f4a2713aSLionel Sambuc     }
5534f4a2713aSLionel Sambuc 
5535f4a2713aSLionel Sambuc     VTableDispatchMethods.insert(GetUnarySelector("allocWithZone"));
5536f4a2713aSLionel Sambuc     VTableDispatchMethods.insert(GetUnarySelector("isKindOfClass"));
5537f4a2713aSLionel Sambuc     VTableDispatchMethods.insert(GetUnarySelector("respondsToSelector"));
5538f4a2713aSLionel Sambuc     VTableDispatchMethods.insert(GetUnarySelector("objectForKey"));
5539f4a2713aSLionel Sambuc     VTableDispatchMethods.insert(GetUnarySelector("objectAtIndex"));
5540f4a2713aSLionel Sambuc     VTableDispatchMethods.insert(GetUnarySelector("isEqualToString"));
5541f4a2713aSLionel Sambuc     VTableDispatchMethods.insert(GetUnarySelector("isEqual"));
5542f4a2713aSLionel Sambuc 
5543f4a2713aSLionel Sambuc     // These are vtable-based if GC is enabled.
5544f4a2713aSLionel Sambuc     // Optimistically use vtable dispatch for hybrid compiles.
5545f4a2713aSLionel Sambuc     if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
5546f4a2713aSLionel Sambuc       VTableDispatchMethods.insert(GetNullarySelector("hash"));
5547f4a2713aSLionel Sambuc       VTableDispatchMethods.insert(GetUnarySelector("addObject"));
5548f4a2713aSLionel Sambuc 
5549f4a2713aSLionel Sambuc       // "countByEnumeratingWithState:objects:count"
5550f4a2713aSLionel Sambuc       IdentifierInfo *KeyIdents[] = {
5551f4a2713aSLionel Sambuc         &CGM.getContext().Idents.get("countByEnumeratingWithState"),
5552f4a2713aSLionel Sambuc         &CGM.getContext().Idents.get("objects"),
5553f4a2713aSLionel Sambuc         &CGM.getContext().Idents.get("count")
5554f4a2713aSLionel Sambuc       };
5555f4a2713aSLionel Sambuc       VTableDispatchMethods.insert(
5556f4a2713aSLionel Sambuc         CGM.getContext().Selectors.getSelector(3, KeyIdents));
5557f4a2713aSLionel Sambuc     }
5558f4a2713aSLionel Sambuc   }
5559f4a2713aSLionel Sambuc 
5560f4a2713aSLionel Sambuc   return VTableDispatchMethods.count(Sel);
5561f4a2713aSLionel Sambuc }
5562f4a2713aSLionel Sambuc 
5563f4a2713aSLionel Sambuc /// BuildClassRoTInitializer - generate meta-data for:
5564f4a2713aSLionel Sambuc /// struct _class_ro_t {
5565f4a2713aSLionel Sambuc ///   uint32_t const flags;
5566f4a2713aSLionel Sambuc ///   uint32_t const instanceStart;
5567f4a2713aSLionel Sambuc ///   uint32_t const instanceSize;
5568f4a2713aSLionel Sambuc ///   uint32_t const reserved;  // only when building for 64bit targets
5569f4a2713aSLionel Sambuc ///   const uint8_t * const ivarLayout;
5570f4a2713aSLionel Sambuc ///   const char *const name;
5571f4a2713aSLionel Sambuc ///   const struct _method_list_t * const baseMethods;
5572f4a2713aSLionel Sambuc ///   const struct _protocol_list_t *const baseProtocols;
5573f4a2713aSLionel Sambuc ///   const struct _ivar_list_t *const ivars;
5574f4a2713aSLionel Sambuc ///   const uint8_t * const weakIvarLayout;
5575f4a2713aSLionel Sambuc ///   const struct _prop_list_t * const properties;
5576f4a2713aSLionel Sambuc /// }
5577f4a2713aSLionel Sambuc ///
BuildClassRoTInitializer(unsigned flags,unsigned InstanceStart,unsigned InstanceSize,const ObjCImplementationDecl * ID)5578f4a2713aSLionel Sambuc llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
5579f4a2713aSLionel Sambuc   unsigned flags,
5580f4a2713aSLionel Sambuc   unsigned InstanceStart,
5581f4a2713aSLionel Sambuc   unsigned InstanceSize,
5582f4a2713aSLionel Sambuc   const ObjCImplementationDecl *ID) {
5583*0a6a1f1dSLionel Sambuc   std::string ClassName = ID->getObjCRuntimeNameAsString();
5584f4a2713aSLionel Sambuc   llvm::Constant *Values[10]; // 11 for 64bit targets!
5585f4a2713aSLionel Sambuc 
5586f4a2713aSLionel Sambuc   if (CGM.getLangOpts().ObjCAutoRefCount)
5587f4a2713aSLionel Sambuc     flags |= NonFragileABI_Class_CompiledByARC;
5588f4a2713aSLionel Sambuc 
5589f4a2713aSLionel Sambuc   Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags);
5590f4a2713aSLionel Sambuc   Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart);
5591f4a2713aSLionel Sambuc   Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize);
5592f4a2713aSLionel Sambuc   // FIXME. For 64bit targets add 0 here.
5593f4a2713aSLionel Sambuc   Values[ 3] = (flags & NonFragileABI_Class_Meta)
5594*0a6a1f1dSLionel Sambuc     ? GetIvarLayoutName(nullptr, ObjCTypes)
5595f4a2713aSLionel Sambuc     : BuildIvarLayout(ID, true);
5596*0a6a1f1dSLionel Sambuc   Values[ 4] = GetClassName(ID->getObjCRuntimeNameAsString());
5597f4a2713aSLionel Sambuc   // const struct _method_list_t * const baseMethods;
5598f4a2713aSLionel Sambuc   std::vector<llvm::Constant*> Methods;
5599f4a2713aSLionel Sambuc   std::string MethodListName("\01l_OBJC_$_");
5600f4a2713aSLionel Sambuc   if (flags & NonFragileABI_Class_Meta) {
5601*0a6a1f1dSLionel Sambuc     MethodListName += "CLASS_METHODS_";
5602*0a6a1f1dSLionel Sambuc     MethodListName += ID->getObjCRuntimeNameAsString();
5603*0a6a1f1dSLionel Sambuc     for (const auto *I : ID->class_methods())
5604f4a2713aSLionel Sambuc       // Class methods should always be defined.
5605*0a6a1f1dSLionel Sambuc       Methods.push_back(GetMethodConstant(I));
5606f4a2713aSLionel Sambuc   } else {
5607*0a6a1f1dSLionel Sambuc     MethodListName += "INSTANCE_METHODS_";
5608*0a6a1f1dSLionel Sambuc     MethodListName += ID->getObjCRuntimeNameAsString();
5609*0a6a1f1dSLionel Sambuc     for (const auto *I : ID->instance_methods())
5610f4a2713aSLionel Sambuc       // Instance methods should always be defined.
5611*0a6a1f1dSLionel Sambuc       Methods.push_back(GetMethodConstant(I));
5612f4a2713aSLionel Sambuc 
5613*0a6a1f1dSLionel Sambuc     for (const auto *PID : ID->property_impls()) {
5614f4a2713aSLionel Sambuc       if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
5615f4a2713aSLionel Sambuc         ObjCPropertyDecl *PD = PID->getPropertyDecl();
5616f4a2713aSLionel Sambuc 
5617f4a2713aSLionel Sambuc         if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
5618f4a2713aSLionel Sambuc           if (llvm::Constant *C = GetMethodConstant(MD))
5619f4a2713aSLionel Sambuc             Methods.push_back(C);
5620f4a2713aSLionel Sambuc         if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
5621f4a2713aSLionel Sambuc           if (llvm::Constant *C = GetMethodConstant(MD))
5622f4a2713aSLionel Sambuc             Methods.push_back(C);
5623f4a2713aSLionel Sambuc       }
5624f4a2713aSLionel Sambuc     }
5625f4a2713aSLionel Sambuc   }
5626f4a2713aSLionel Sambuc   Values[ 5] = EmitMethodList(MethodListName,
5627f4a2713aSLionel Sambuc                               "__DATA, __objc_const", Methods);
5628f4a2713aSLionel Sambuc 
5629f4a2713aSLionel Sambuc   const ObjCInterfaceDecl *OID = ID->getClassInterface();
5630f4a2713aSLionel Sambuc   assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
5631f4a2713aSLionel Sambuc   Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
5632*0a6a1f1dSLionel Sambuc                                 + OID->getObjCRuntimeNameAsString(),
5633f4a2713aSLionel Sambuc                                 OID->all_referenced_protocol_begin(),
5634f4a2713aSLionel Sambuc                                 OID->all_referenced_protocol_end());
5635f4a2713aSLionel Sambuc 
5636f4a2713aSLionel Sambuc   if (flags & NonFragileABI_Class_Meta) {
5637f4a2713aSLionel Sambuc     Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
5638*0a6a1f1dSLionel Sambuc     Values[ 8] = GetIvarLayoutName(nullptr, ObjCTypes);
5639f4a2713aSLionel Sambuc     Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
5640f4a2713aSLionel Sambuc   } else {
5641f4a2713aSLionel Sambuc     Values[ 7] = EmitIvarList(ID);
5642f4a2713aSLionel Sambuc     Values[ 8] = BuildIvarLayout(ID, false);
5643*0a6a1f1dSLionel Sambuc     Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getObjCRuntimeNameAsString(),
5644f4a2713aSLionel Sambuc                                   ID, ID->getClassInterface(), ObjCTypes);
5645f4a2713aSLionel Sambuc   }
5646f4a2713aSLionel Sambuc   llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,
5647f4a2713aSLionel Sambuc                                                    Values);
5648f4a2713aSLionel Sambuc   llvm::GlobalVariable *CLASS_RO_GV =
5649f4a2713aSLionel Sambuc     new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassRonfABITy, false,
5650*0a6a1f1dSLionel Sambuc                              llvm::GlobalValue::PrivateLinkage,
5651f4a2713aSLionel Sambuc                              Init,
5652f4a2713aSLionel Sambuc                              (flags & NonFragileABI_Class_Meta) ?
5653f4a2713aSLionel Sambuc                              std::string("\01l_OBJC_METACLASS_RO_$_")+ClassName :
5654f4a2713aSLionel Sambuc                              std::string("\01l_OBJC_CLASS_RO_$_")+ClassName);
5655f4a2713aSLionel Sambuc   CLASS_RO_GV->setAlignment(
5656f4a2713aSLionel Sambuc     CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassRonfABITy));
5657f4a2713aSLionel Sambuc   CLASS_RO_GV->setSection("__DATA, __objc_const");
5658f4a2713aSLionel Sambuc   return CLASS_RO_GV;
5659f4a2713aSLionel Sambuc 
5660f4a2713aSLionel Sambuc }
5661f4a2713aSLionel Sambuc 
5662f4a2713aSLionel Sambuc /// BuildClassMetaData - This routine defines that to-level meta-data
5663f4a2713aSLionel Sambuc /// for the given ClassName for:
5664f4a2713aSLionel Sambuc /// struct _class_t {
5665f4a2713aSLionel Sambuc ///   struct _class_t *isa;
5666f4a2713aSLionel Sambuc ///   struct _class_t * const superclass;
5667f4a2713aSLionel Sambuc ///   void *cache;
5668f4a2713aSLionel Sambuc ///   IMP *vtable;
5669f4a2713aSLionel Sambuc ///   struct class_ro_t *ro;
5670f4a2713aSLionel Sambuc /// }
5671f4a2713aSLionel Sambuc ///
BuildClassMetaData(const std::string & ClassName,llvm::Constant * IsAGV,llvm::Constant * SuperClassGV,llvm::Constant * ClassRoGV,bool HiddenVisibility,bool Weak)5672f4a2713aSLionel Sambuc llvm::GlobalVariable *CGObjCNonFragileABIMac::BuildClassMetaData(
5673*0a6a1f1dSLionel Sambuc     const std::string &ClassName, llvm::Constant *IsAGV, llvm::Constant *SuperClassGV,
5674*0a6a1f1dSLionel Sambuc     llvm::Constant *ClassRoGV, bool HiddenVisibility, bool Weak) {
5675f4a2713aSLionel Sambuc   llvm::Constant *Values[] = {
5676f4a2713aSLionel Sambuc     IsAGV,
5677f4a2713aSLionel Sambuc     SuperClassGV,
5678f4a2713aSLionel Sambuc     ObjCEmptyCacheVar,  // &ObjCEmptyCacheVar
5679f4a2713aSLionel Sambuc     ObjCEmptyVtableVar, // &ObjCEmptyVtableVar
5680f4a2713aSLionel Sambuc     ClassRoGV           // &CLASS_RO_GV
5681f4a2713aSLionel Sambuc   };
5682f4a2713aSLionel Sambuc   if (!Values[1])
5683f4a2713aSLionel Sambuc     Values[1] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy);
5684f4a2713aSLionel Sambuc   if (!Values[3])
5685f4a2713aSLionel Sambuc     Values[3] = llvm::Constant::getNullValue(
5686f4a2713aSLionel Sambuc                   llvm::PointerType::getUnqual(ObjCTypes.ImpnfABITy));
5687f4a2713aSLionel Sambuc   llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy,
5688f4a2713aSLionel Sambuc                                                    Values);
5689*0a6a1f1dSLionel Sambuc   llvm::GlobalVariable *GV = GetClassGlobal(ClassName, Weak);
5690f4a2713aSLionel Sambuc   GV->setInitializer(Init);
5691f4a2713aSLionel Sambuc   GV->setSection("__DATA, __objc_data");
5692f4a2713aSLionel Sambuc   GV->setAlignment(
5693f4a2713aSLionel Sambuc     CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassnfABITy));
5694f4a2713aSLionel Sambuc   if (HiddenVisibility)
5695f4a2713aSLionel Sambuc     GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
5696f4a2713aSLionel Sambuc   return GV;
5697f4a2713aSLionel Sambuc }
5698f4a2713aSLionel Sambuc 
5699f4a2713aSLionel Sambuc bool
ImplementationIsNonLazy(const ObjCImplDecl * OD) const5700f4a2713aSLionel Sambuc CGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
5701*0a6a1f1dSLionel Sambuc   return OD->getClassMethod(GetNullarySelector("load")) != nullptr;
5702f4a2713aSLionel Sambuc }
5703f4a2713aSLionel Sambuc 
GetClassSizeInfo(const ObjCImplementationDecl * OID,uint32_t & InstanceStart,uint32_t & InstanceSize)5704f4a2713aSLionel Sambuc void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
5705f4a2713aSLionel Sambuc                                               uint32_t &InstanceStart,
5706f4a2713aSLionel Sambuc                                               uint32_t &InstanceSize) {
5707f4a2713aSLionel Sambuc   const ASTRecordLayout &RL =
5708f4a2713aSLionel Sambuc     CGM.getContext().getASTObjCImplementationLayout(OID);
5709f4a2713aSLionel Sambuc 
5710f4a2713aSLionel Sambuc   // InstanceSize is really instance end.
5711f4a2713aSLionel Sambuc   InstanceSize = RL.getDataSize().getQuantity();
5712f4a2713aSLionel Sambuc 
5713f4a2713aSLionel Sambuc   // If there are no fields, the start is the same as the end.
5714f4a2713aSLionel Sambuc   if (!RL.getFieldCount())
5715f4a2713aSLionel Sambuc     InstanceStart = InstanceSize;
5716f4a2713aSLionel Sambuc   else
5717f4a2713aSLionel Sambuc     InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth();
5718f4a2713aSLionel Sambuc }
5719f4a2713aSLionel Sambuc 
GenerateClass(const ObjCImplementationDecl * ID)5720f4a2713aSLionel Sambuc void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
5721*0a6a1f1dSLionel Sambuc   std::string ClassName = ID->getObjCRuntimeNameAsString();
5722f4a2713aSLionel Sambuc   if (!ObjCEmptyCacheVar) {
5723f4a2713aSLionel Sambuc     ObjCEmptyCacheVar = new llvm::GlobalVariable(
5724f4a2713aSLionel Sambuc       CGM.getModule(),
5725f4a2713aSLionel Sambuc       ObjCTypes.CacheTy,
5726f4a2713aSLionel Sambuc       false,
5727f4a2713aSLionel Sambuc       llvm::GlobalValue::ExternalLinkage,
5728*0a6a1f1dSLionel Sambuc       nullptr,
5729f4a2713aSLionel Sambuc       "_objc_empty_cache");
5730f4a2713aSLionel Sambuc 
5731f4a2713aSLionel Sambuc     // Make this entry NULL for any iOS device target, any iOS simulator target,
5732f4a2713aSLionel Sambuc     // OS X with deployment target 10.9 or later.
5733f4a2713aSLionel Sambuc     const llvm::Triple &Triple = CGM.getTarget().getTriple();
5734f4a2713aSLionel Sambuc     if (Triple.isiOS() || (Triple.isMacOSX() && !Triple.isMacOSXVersionLT(10, 9)))
5735f4a2713aSLionel Sambuc       // This entry will be null.
5736*0a6a1f1dSLionel Sambuc       ObjCEmptyVtableVar = nullptr;
5737f4a2713aSLionel Sambuc     else
5738f4a2713aSLionel Sambuc       ObjCEmptyVtableVar = new llvm::GlobalVariable(
5739f4a2713aSLionel Sambuc                                                     CGM.getModule(),
5740f4a2713aSLionel Sambuc                                                     ObjCTypes.ImpnfABITy,
5741f4a2713aSLionel Sambuc                                                     false,
5742f4a2713aSLionel Sambuc                                                     llvm::GlobalValue::ExternalLinkage,
5743*0a6a1f1dSLionel Sambuc                                                     nullptr,
5744f4a2713aSLionel Sambuc                                                     "_objc_empty_vtable");
5745f4a2713aSLionel Sambuc   }
5746f4a2713aSLionel Sambuc   assert(ID->getClassInterface() &&
5747f4a2713aSLionel Sambuc          "CGObjCNonFragileABIMac::GenerateClass - class is 0");
5748f4a2713aSLionel Sambuc   // FIXME: Is this correct (that meta class size is never computed)?
5749f4a2713aSLionel Sambuc   uint32_t InstanceStart =
5750f4a2713aSLionel Sambuc     CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassnfABITy);
5751f4a2713aSLionel Sambuc   uint32_t InstanceSize = InstanceStart;
5752f4a2713aSLionel Sambuc   uint32_t flags = NonFragileABI_Class_Meta;
5753*0a6a1f1dSLionel Sambuc   llvm::SmallString<64> ObjCMetaClassName(getMetaclassSymbolPrefix());
5754*0a6a1f1dSLionel Sambuc   llvm::SmallString<64> ObjCClassName(getClassSymbolPrefix());
5755*0a6a1f1dSLionel Sambuc   llvm::SmallString<64> TClassName;
5756f4a2713aSLionel Sambuc 
5757f4a2713aSLionel Sambuc   llvm::GlobalVariable *SuperClassGV, *IsAGV;
5758f4a2713aSLionel Sambuc 
5759f4a2713aSLionel Sambuc   // Build the flags for the metaclass.
5760f4a2713aSLionel Sambuc   bool classIsHidden =
5761f4a2713aSLionel Sambuc     ID->getClassInterface()->getVisibility() == HiddenVisibility;
5762f4a2713aSLionel Sambuc   if (classIsHidden)
5763f4a2713aSLionel Sambuc     flags |= NonFragileABI_Class_Hidden;
5764f4a2713aSLionel Sambuc 
5765f4a2713aSLionel Sambuc   // FIXME: why is this flag set on the metaclass?
5766f4a2713aSLionel Sambuc   // ObjC metaclasses have no fields and don't really get constructed.
5767f4a2713aSLionel Sambuc   if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
5768f4a2713aSLionel Sambuc     flags |= NonFragileABI_Class_HasCXXStructors;
5769f4a2713aSLionel Sambuc     if (!ID->hasNonZeroConstructors())
5770f4a2713aSLionel Sambuc       flags |= NonFragileABI_Class_HasCXXDestructorOnly;
5771f4a2713aSLionel Sambuc   }
5772f4a2713aSLionel Sambuc 
5773f4a2713aSLionel Sambuc   if (!ID->getClassInterface()->getSuperClass()) {
5774f4a2713aSLionel Sambuc     // class is root
5775f4a2713aSLionel Sambuc     flags |= NonFragileABI_Class_Root;
5776*0a6a1f1dSLionel Sambuc     TClassName = ObjCClassName;
5777*0a6a1f1dSLionel Sambuc     TClassName += ClassName;
5778*0a6a1f1dSLionel Sambuc     SuperClassGV = GetClassGlobal(TClassName.str(),
5779*0a6a1f1dSLionel Sambuc                                   ID->getClassInterface()->isWeakImported());
5780*0a6a1f1dSLionel Sambuc     TClassName = ObjCMetaClassName;
5781*0a6a1f1dSLionel Sambuc     TClassName += ClassName;
5782*0a6a1f1dSLionel Sambuc     IsAGV = GetClassGlobal(TClassName.str(),
5783*0a6a1f1dSLionel Sambuc                            ID->getClassInterface()->isWeakImported());
5784f4a2713aSLionel Sambuc   } else {
5785f4a2713aSLionel Sambuc     // Has a root. Current class is not a root.
5786f4a2713aSLionel Sambuc     const ObjCInterfaceDecl *Root = ID->getClassInterface();
5787f4a2713aSLionel Sambuc     while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
5788f4a2713aSLionel Sambuc       Root = Super;
5789*0a6a1f1dSLionel Sambuc     TClassName = ObjCMetaClassName ;
5790*0a6a1f1dSLionel Sambuc     TClassName += Root->getObjCRuntimeNameAsString();
5791*0a6a1f1dSLionel Sambuc     IsAGV = GetClassGlobal(TClassName.str(),
5792*0a6a1f1dSLionel Sambuc                            Root->isWeakImported());
5793*0a6a1f1dSLionel Sambuc 
5794f4a2713aSLionel Sambuc     // work on super class metadata symbol.
5795*0a6a1f1dSLionel Sambuc     TClassName = ObjCMetaClassName;
5796*0a6a1f1dSLionel Sambuc     TClassName += ID->getClassInterface()->getSuperClass()->getObjCRuntimeNameAsString();
5797*0a6a1f1dSLionel Sambuc     SuperClassGV = GetClassGlobal(
5798*0a6a1f1dSLionel Sambuc                                   TClassName.str(),
5799*0a6a1f1dSLionel Sambuc                                   ID->getClassInterface()->getSuperClass()->isWeakImported());
5800f4a2713aSLionel Sambuc   }
5801f4a2713aSLionel Sambuc   llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags,
5802f4a2713aSLionel Sambuc                                                                InstanceStart,
5803f4a2713aSLionel Sambuc                                                                InstanceSize,ID);
5804*0a6a1f1dSLionel Sambuc   TClassName = ObjCMetaClassName;
5805*0a6a1f1dSLionel Sambuc   TClassName += ClassName;
5806*0a6a1f1dSLionel Sambuc   llvm::GlobalVariable *MetaTClass = BuildClassMetaData(
5807*0a6a1f1dSLionel Sambuc       TClassName.str(), IsAGV, SuperClassGV, CLASS_RO_GV, classIsHidden,
5808*0a6a1f1dSLionel Sambuc       ID->getClassInterface()->isWeakImported());
5809f4a2713aSLionel Sambuc   DefinedMetaClasses.push_back(MetaTClass);
5810f4a2713aSLionel Sambuc 
5811f4a2713aSLionel Sambuc   // Metadata for the class
5812f4a2713aSLionel Sambuc   flags = 0;
5813f4a2713aSLionel Sambuc   if (classIsHidden)
5814f4a2713aSLionel Sambuc     flags |= NonFragileABI_Class_Hidden;
5815f4a2713aSLionel Sambuc 
5816f4a2713aSLionel Sambuc   if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
5817f4a2713aSLionel Sambuc     flags |= NonFragileABI_Class_HasCXXStructors;
5818f4a2713aSLionel Sambuc 
5819f4a2713aSLionel Sambuc     // Set a flag to enable a runtime optimization when a class has
5820f4a2713aSLionel Sambuc     // fields that require destruction but which don't require
5821f4a2713aSLionel Sambuc     // anything except zero-initialization during construction.  This
5822f4a2713aSLionel Sambuc     // is most notably true of __strong and __weak types, but you can
5823f4a2713aSLionel Sambuc     // also imagine there being C++ types with non-trivial default
5824f4a2713aSLionel Sambuc     // constructors that merely set all fields to null.
5825f4a2713aSLionel Sambuc     if (!ID->hasNonZeroConstructors())
5826f4a2713aSLionel Sambuc       flags |= NonFragileABI_Class_HasCXXDestructorOnly;
5827f4a2713aSLionel Sambuc   }
5828f4a2713aSLionel Sambuc 
5829f4a2713aSLionel Sambuc   if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface()))
5830f4a2713aSLionel Sambuc     flags |= NonFragileABI_Class_Exception;
5831f4a2713aSLionel Sambuc 
5832f4a2713aSLionel Sambuc   if (!ID->getClassInterface()->getSuperClass()) {
5833f4a2713aSLionel Sambuc     flags |= NonFragileABI_Class_Root;
5834*0a6a1f1dSLionel Sambuc     SuperClassGV = nullptr;
5835f4a2713aSLionel Sambuc   } else {
5836f4a2713aSLionel Sambuc     // Has a root. Current class is not a root.
5837*0a6a1f1dSLionel Sambuc     TClassName = ObjCClassName;
5838*0a6a1f1dSLionel Sambuc     TClassName += ID->getClassInterface()->getSuperClass()->getObjCRuntimeNameAsString();
5839*0a6a1f1dSLionel Sambuc     SuperClassGV = GetClassGlobal(
5840*0a6a1f1dSLionel Sambuc                                   TClassName.str(),
5841*0a6a1f1dSLionel Sambuc                                   ID->getClassInterface()->getSuperClass()->isWeakImported());
5842f4a2713aSLionel Sambuc   }
5843f4a2713aSLionel Sambuc   GetClassSizeInfo(ID, InstanceStart, InstanceSize);
5844f4a2713aSLionel Sambuc   CLASS_RO_GV = BuildClassRoTInitializer(flags,
5845f4a2713aSLionel Sambuc                                          InstanceStart,
5846f4a2713aSLionel Sambuc                                          InstanceSize,
5847f4a2713aSLionel Sambuc                                          ID);
5848f4a2713aSLionel Sambuc 
5849*0a6a1f1dSLionel Sambuc   TClassName = ObjCClassName;
5850*0a6a1f1dSLionel Sambuc   TClassName += ClassName;
5851f4a2713aSLionel Sambuc   llvm::GlobalVariable *ClassMD =
5852*0a6a1f1dSLionel Sambuc     BuildClassMetaData(TClassName.str(), MetaTClass, SuperClassGV, CLASS_RO_GV,
5853*0a6a1f1dSLionel Sambuc                        classIsHidden,
5854*0a6a1f1dSLionel Sambuc                        ID->getClassInterface()->isWeakImported());
5855f4a2713aSLionel Sambuc   DefinedClasses.push_back(ClassMD);
5856*0a6a1f1dSLionel Sambuc   ImplementedClasses.push_back(ID->getClassInterface());
5857f4a2713aSLionel Sambuc 
5858f4a2713aSLionel Sambuc   // Determine if this class is also "non-lazy".
5859f4a2713aSLionel Sambuc   if (ImplementationIsNonLazy(ID))
5860f4a2713aSLionel Sambuc     DefinedNonLazyClasses.push_back(ClassMD);
5861f4a2713aSLionel Sambuc 
5862f4a2713aSLionel Sambuc   // Force the definition of the EHType if necessary.
5863f4a2713aSLionel Sambuc   if (flags & NonFragileABI_Class_Exception)
5864f4a2713aSLionel Sambuc     GetInterfaceEHType(ID->getClassInterface(), true);
5865f4a2713aSLionel Sambuc   // Make sure method definition entries are all clear for next implementation.
5866f4a2713aSLionel Sambuc   MethodDefinitions.clear();
5867f4a2713aSLionel Sambuc }
5868f4a2713aSLionel Sambuc 
5869f4a2713aSLionel Sambuc /// GenerateProtocolRef - This routine is called to generate code for
5870f4a2713aSLionel Sambuc /// a protocol reference expression; as in:
5871f4a2713aSLionel Sambuc /// @code
5872f4a2713aSLionel Sambuc ///   @protocol(Proto1);
5873f4a2713aSLionel Sambuc /// @endcode
5874f4a2713aSLionel Sambuc /// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1
5875f4a2713aSLionel Sambuc /// which will hold address of the protocol meta-data.
5876f4a2713aSLionel Sambuc ///
GenerateProtocolRef(CodeGenFunction & CGF,const ObjCProtocolDecl * PD)5877f4a2713aSLionel Sambuc llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF,
5878f4a2713aSLionel Sambuc                                                          const ObjCProtocolDecl *PD) {
5879f4a2713aSLionel Sambuc 
5880f4a2713aSLionel Sambuc   // This routine is called for @protocol only. So, we must build definition
5881f4a2713aSLionel Sambuc   // of protocol's meta-data (not a reference to it!)
5882f4a2713aSLionel Sambuc   //
5883f4a2713aSLionel Sambuc   llvm::Constant *Init =
5884f4a2713aSLionel Sambuc     llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
5885f4a2713aSLionel Sambuc                                    ObjCTypes.getExternalProtocolPtrTy());
5886f4a2713aSLionel Sambuc 
5887f4a2713aSLionel Sambuc   std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_");
5888*0a6a1f1dSLionel Sambuc   ProtocolName += PD->getObjCRuntimeNameAsString();
5889f4a2713aSLionel Sambuc 
5890f4a2713aSLionel Sambuc   llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
5891f4a2713aSLionel Sambuc   if (PTGV)
5892f4a2713aSLionel Sambuc     return CGF.Builder.CreateLoad(PTGV);
5893f4a2713aSLionel Sambuc   PTGV = new llvm::GlobalVariable(
5894f4a2713aSLionel Sambuc     CGM.getModule(),
5895f4a2713aSLionel Sambuc     Init->getType(), false,
5896f4a2713aSLionel Sambuc     llvm::GlobalValue::WeakAnyLinkage,
5897f4a2713aSLionel Sambuc     Init,
5898f4a2713aSLionel Sambuc     ProtocolName);
5899f4a2713aSLionel Sambuc   PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip");
5900f4a2713aSLionel Sambuc   PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
5901*0a6a1f1dSLionel Sambuc   CGM.addCompilerUsedGlobal(PTGV);
5902f4a2713aSLionel Sambuc   return CGF.Builder.CreateLoad(PTGV);
5903f4a2713aSLionel Sambuc }
5904f4a2713aSLionel Sambuc 
5905f4a2713aSLionel Sambuc /// GenerateCategory - Build metadata for a category implementation.
5906f4a2713aSLionel Sambuc /// struct _category_t {
5907f4a2713aSLionel Sambuc ///   const char * const name;
5908f4a2713aSLionel Sambuc ///   struct _class_t *const cls;
5909f4a2713aSLionel Sambuc ///   const struct _method_list_t * const instance_methods;
5910f4a2713aSLionel Sambuc ///   const struct _method_list_t * const class_methods;
5911f4a2713aSLionel Sambuc ///   const struct _protocol_list_t * const protocols;
5912f4a2713aSLionel Sambuc ///   const struct _prop_list_t * const properties;
5913f4a2713aSLionel Sambuc /// }
5914f4a2713aSLionel Sambuc ///
GenerateCategory(const ObjCCategoryImplDecl * OCD)5915f4a2713aSLionel Sambuc void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
5916f4a2713aSLionel Sambuc   const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
5917f4a2713aSLionel Sambuc   const char *Prefix = "\01l_OBJC_$_CATEGORY_";
5918*0a6a1f1dSLionel Sambuc 
5919*0a6a1f1dSLionel Sambuc   llvm::SmallString<64> ExtCatName(Prefix);
5920*0a6a1f1dSLionel Sambuc   ExtCatName += Interface->getObjCRuntimeNameAsString();
5921*0a6a1f1dSLionel Sambuc   ExtCatName += "_$_";
5922*0a6a1f1dSLionel Sambuc   ExtCatName += OCD->getNameAsString();
5923*0a6a1f1dSLionel Sambuc 
5924*0a6a1f1dSLionel Sambuc   llvm::SmallString<64> ExtClassName(getClassSymbolPrefix());
5925*0a6a1f1dSLionel Sambuc   ExtClassName += Interface->getObjCRuntimeNameAsString();
5926f4a2713aSLionel Sambuc 
5927f4a2713aSLionel Sambuc   llvm::Constant *Values[6];
5928*0a6a1f1dSLionel Sambuc   Values[0] = GetClassName(OCD->getIdentifier()->getName());
5929f4a2713aSLionel Sambuc   // meta-class entry symbol
5930*0a6a1f1dSLionel Sambuc   llvm::GlobalVariable *ClassGV =
5931*0a6a1f1dSLionel Sambuc       GetClassGlobal(ExtClassName.str(), Interface->isWeakImported());
5932f4a2713aSLionel Sambuc 
5933f4a2713aSLionel Sambuc   Values[1] = ClassGV;
5934f4a2713aSLionel Sambuc   std::vector<llvm::Constant*> Methods;
5935*0a6a1f1dSLionel Sambuc   llvm::SmallString<64> MethodListName(Prefix);
5936f4a2713aSLionel Sambuc 
5937*0a6a1f1dSLionel Sambuc   MethodListName += "INSTANCE_METHODS_";
5938*0a6a1f1dSLionel Sambuc   MethodListName += Interface->getObjCRuntimeNameAsString();
5939*0a6a1f1dSLionel Sambuc   MethodListName += "_$_";
5940*0a6a1f1dSLionel Sambuc   MethodListName += OCD->getName();
5941*0a6a1f1dSLionel Sambuc 
5942*0a6a1f1dSLionel Sambuc   for (const auto *I : OCD->instance_methods())
5943f4a2713aSLionel Sambuc     // Instance methods should always be defined.
5944*0a6a1f1dSLionel Sambuc     Methods.push_back(GetMethodConstant(I));
5945f4a2713aSLionel Sambuc 
5946*0a6a1f1dSLionel Sambuc   Values[2] = EmitMethodList(MethodListName.str(),
5947f4a2713aSLionel Sambuc                              "__DATA, __objc_const",
5948f4a2713aSLionel Sambuc                              Methods);
5949f4a2713aSLionel Sambuc 
5950f4a2713aSLionel Sambuc   MethodListName = Prefix;
5951*0a6a1f1dSLionel Sambuc   MethodListName += "CLASS_METHODS_";
5952*0a6a1f1dSLionel Sambuc   MethodListName += Interface->getObjCRuntimeNameAsString();
5953*0a6a1f1dSLionel Sambuc   MethodListName += "_$_";
5954*0a6a1f1dSLionel Sambuc   MethodListName += OCD->getNameAsString();
5955f4a2713aSLionel Sambuc 
5956*0a6a1f1dSLionel Sambuc   Methods.clear();
5957*0a6a1f1dSLionel Sambuc   for (const auto *I : OCD->class_methods())
5958*0a6a1f1dSLionel Sambuc     // Class methods should always be defined.
5959*0a6a1f1dSLionel Sambuc     Methods.push_back(GetMethodConstant(I));
5960*0a6a1f1dSLionel Sambuc 
5961*0a6a1f1dSLionel Sambuc   Values[3] = EmitMethodList(MethodListName.str(),
5962f4a2713aSLionel Sambuc                              "__DATA, __objc_const",
5963f4a2713aSLionel Sambuc                              Methods);
5964f4a2713aSLionel Sambuc   const ObjCCategoryDecl *Category =
5965f4a2713aSLionel Sambuc     Interface->FindCategoryDeclaration(OCD->getIdentifier());
5966f4a2713aSLionel Sambuc   if (Category) {
5967f4a2713aSLionel Sambuc     SmallString<256> ExtName;
5968*0a6a1f1dSLionel Sambuc     llvm::raw_svector_ostream(ExtName) << Interface->getObjCRuntimeNameAsString() << "_$_"
5969f4a2713aSLionel Sambuc                                        << OCD->getName();
5970f4a2713aSLionel Sambuc     Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
5971*0a6a1f1dSLionel Sambuc                                    + Interface->getObjCRuntimeNameAsString() + "_$_"
5972f4a2713aSLionel Sambuc                                    + Category->getName(),
5973f4a2713aSLionel Sambuc                                    Category->protocol_begin(),
5974f4a2713aSLionel Sambuc                                    Category->protocol_end());
5975f4a2713aSLionel Sambuc     Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
5976f4a2713aSLionel Sambuc                                  OCD, Category, ObjCTypes);
5977f4a2713aSLionel Sambuc   } else {
5978f4a2713aSLionel Sambuc     Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
5979f4a2713aSLionel Sambuc     Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
5980f4a2713aSLionel Sambuc   }
5981f4a2713aSLionel Sambuc 
5982f4a2713aSLionel Sambuc   llvm::Constant *Init =
5983f4a2713aSLionel Sambuc     llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy,
5984f4a2713aSLionel Sambuc                               Values);
5985f4a2713aSLionel Sambuc   llvm::GlobalVariable *GCATV
5986f4a2713aSLionel Sambuc     = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CategorynfABITy,
5987f4a2713aSLionel Sambuc                                false,
5988*0a6a1f1dSLionel Sambuc                                llvm::GlobalValue::PrivateLinkage,
5989f4a2713aSLionel Sambuc                                Init,
5990*0a6a1f1dSLionel Sambuc                                ExtCatName.str());
5991f4a2713aSLionel Sambuc   GCATV->setAlignment(
5992f4a2713aSLionel Sambuc     CGM.getDataLayout().getABITypeAlignment(ObjCTypes.CategorynfABITy));
5993f4a2713aSLionel Sambuc   GCATV->setSection("__DATA, __objc_const");
5994*0a6a1f1dSLionel Sambuc   CGM.addCompilerUsedGlobal(GCATV);
5995f4a2713aSLionel Sambuc   DefinedCategories.push_back(GCATV);
5996f4a2713aSLionel Sambuc 
5997f4a2713aSLionel Sambuc   // Determine if this category is also "non-lazy".
5998f4a2713aSLionel Sambuc   if (ImplementationIsNonLazy(OCD))
5999f4a2713aSLionel Sambuc     DefinedNonLazyCategories.push_back(GCATV);
6000f4a2713aSLionel Sambuc   // method definition entries must be clear for next implementation.
6001f4a2713aSLionel Sambuc   MethodDefinitions.clear();
6002f4a2713aSLionel Sambuc }
6003f4a2713aSLionel Sambuc 
6004f4a2713aSLionel Sambuc /// GetMethodConstant - Return a struct objc_method constant for the
6005f4a2713aSLionel Sambuc /// given method if it has been defined. The result is null if the
6006f4a2713aSLionel Sambuc /// method has not been defined. The return value has type MethodPtrTy.
GetMethodConstant(const ObjCMethodDecl * MD)6007f4a2713aSLionel Sambuc llvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant(
6008f4a2713aSLionel Sambuc   const ObjCMethodDecl *MD) {
6009f4a2713aSLionel Sambuc   llvm::Function *Fn = GetMethodDefinition(MD);
6010f4a2713aSLionel Sambuc   if (!Fn)
6011*0a6a1f1dSLionel Sambuc     return nullptr;
6012f4a2713aSLionel Sambuc 
6013f4a2713aSLionel Sambuc   llvm::Constant *Method[] = {
6014f4a2713aSLionel Sambuc     llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
6015f4a2713aSLionel Sambuc                                    ObjCTypes.SelectorPtrTy),
6016f4a2713aSLionel Sambuc     GetMethodVarType(MD),
6017f4a2713aSLionel Sambuc     llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy)
6018f4a2713aSLionel Sambuc   };
6019f4a2713aSLionel Sambuc   return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
6020f4a2713aSLionel Sambuc }
6021f4a2713aSLionel Sambuc 
6022f4a2713aSLionel Sambuc /// EmitMethodList - Build meta-data for method declarations
6023f4a2713aSLionel Sambuc /// struct _method_list_t {
6024f4a2713aSLionel Sambuc ///   uint32_t entsize;  // sizeof(struct _objc_method)
6025f4a2713aSLionel Sambuc ///   uint32_t method_count;
6026f4a2713aSLionel Sambuc ///   struct _objc_method method_list[method_count];
6027f4a2713aSLionel Sambuc /// }
6028f4a2713aSLionel Sambuc ///
6029f4a2713aSLionel Sambuc llvm::Constant *
EmitMethodList(Twine Name,const char * Section,ArrayRef<llvm::Constant * > Methods)6030f4a2713aSLionel Sambuc CGObjCNonFragileABIMac::EmitMethodList(Twine Name,
6031f4a2713aSLionel Sambuc                                        const char *Section,
6032f4a2713aSLionel Sambuc                                        ArrayRef<llvm::Constant*> Methods) {
6033f4a2713aSLionel Sambuc   // Return null for empty list.
6034f4a2713aSLionel Sambuc   if (Methods.empty())
6035f4a2713aSLionel Sambuc     return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
6036f4a2713aSLionel Sambuc 
6037f4a2713aSLionel Sambuc   llvm::Constant *Values[3];
6038f4a2713aSLionel Sambuc   // sizeof(struct _objc_method)
6039f4a2713aSLionel Sambuc   unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.MethodTy);
6040f4a2713aSLionel Sambuc   Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
6041f4a2713aSLionel Sambuc   // method_count
6042f4a2713aSLionel Sambuc   Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
6043f4a2713aSLionel Sambuc   llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
6044f4a2713aSLionel Sambuc                                              Methods.size());
6045f4a2713aSLionel Sambuc   Values[2] = llvm::ConstantArray::get(AT, Methods);
6046f4a2713aSLionel Sambuc   llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
6047f4a2713aSLionel Sambuc 
6048f4a2713aSLionel Sambuc   llvm::GlobalVariable *GV =
6049f4a2713aSLionel Sambuc     new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
6050*0a6a1f1dSLionel Sambuc                              llvm::GlobalValue::PrivateLinkage, Init, Name);
6051f4a2713aSLionel Sambuc   GV->setAlignment(CGM.getDataLayout().getABITypeAlignment(Init->getType()));
6052f4a2713aSLionel Sambuc   GV->setSection(Section);
6053*0a6a1f1dSLionel Sambuc   CGM.addCompilerUsedGlobal(GV);
6054f4a2713aSLionel Sambuc   return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListnfABIPtrTy);
6055f4a2713aSLionel Sambuc }
6056f4a2713aSLionel Sambuc 
6057f4a2713aSLionel Sambuc /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
6058f4a2713aSLionel Sambuc /// the given ivar.
6059f4a2713aSLionel Sambuc llvm::GlobalVariable *
ObjCIvarOffsetVariable(const ObjCInterfaceDecl * ID,const ObjCIvarDecl * Ivar)6060f4a2713aSLionel Sambuc CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
6061f4a2713aSLionel Sambuc                                                const ObjCIvarDecl *Ivar) {
6062*0a6a1f1dSLionel Sambuc 
6063f4a2713aSLionel Sambuc   const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
6064*0a6a1f1dSLionel Sambuc   llvm::SmallString<64> Name("OBJC_IVAR_$_");
6065*0a6a1f1dSLionel Sambuc   Name += Container->getObjCRuntimeNameAsString();
6066*0a6a1f1dSLionel Sambuc   Name += ".";
6067*0a6a1f1dSLionel Sambuc   Name += Ivar->getName();
6068f4a2713aSLionel Sambuc   llvm::GlobalVariable *IvarOffsetGV =
6069f4a2713aSLionel Sambuc     CGM.getModule().getGlobalVariable(Name);
6070f4a2713aSLionel Sambuc   if (!IvarOffsetGV)
6071*0a6a1f1dSLionel Sambuc     IvarOffsetGV = new llvm::GlobalVariable(
6072*0a6a1f1dSLionel Sambuc       CGM.getModule(), ObjCTypes.IvarOffsetVarTy, false,
6073*0a6a1f1dSLionel Sambuc       llvm::GlobalValue::ExternalLinkage, nullptr, Name.str());
6074f4a2713aSLionel Sambuc   return IvarOffsetGV;
6075f4a2713aSLionel Sambuc }
6076f4a2713aSLionel Sambuc 
6077f4a2713aSLionel Sambuc llvm::Constant *
EmitIvarOffsetVar(const ObjCInterfaceDecl * ID,const ObjCIvarDecl * Ivar,unsigned long int Offset)6078f4a2713aSLionel Sambuc CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
6079f4a2713aSLionel Sambuc                                           const ObjCIvarDecl *Ivar,
6080f4a2713aSLionel Sambuc                                           unsigned long int Offset) {
6081f4a2713aSLionel Sambuc   llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
6082*0a6a1f1dSLionel Sambuc   IvarOffsetGV->setInitializer(
6083*0a6a1f1dSLionel Sambuc       llvm::ConstantInt::get(ObjCTypes.IvarOffsetVarTy, Offset));
6084f4a2713aSLionel Sambuc   IvarOffsetGV->setAlignment(
6085*0a6a1f1dSLionel Sambuc       CGM.getDataLayout().getABITypeAlignment(ObjCTypes.IvarOffsetVarTy));
6086f4a2713aSLionel Sambuc 
6087f4a2713aSLionel Sambuc   // FIXME: This matches gcc, but shouldn't the visibility be set on the use as
6088f4a2713aSLionel Sambuc   // well (i.e., in ObjCIvarOffsetVariable).
6089f4a2713aSLionel Sambuc   if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
6090f4a2713aSLionel Sambuc       Ivar->getAccessControl() == ObjCIvarDecl::Package ||
6091f4a2713aSLionel Sambuc       ID->getVisibility() == HiddenVisibility)
6092f4a2713aSLionel Sambuc     IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
6093f4a2713aSLionel Sambuc   else
6094f4a2713aSLionel Sambuc     IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
6095f4a2713aSLionel Sambuc   IvarOffsetGV->setSection("__DATA, __objc_ivar");
6096f4a2713aSLionel Sambuc   return IvarOffsetGV;
6097f4a2713aSLionel Sambuc }
6098f4a2713aSLionel Sambuc 
6099f4a2713aSLionel Sambuc /// EmitIvarList - Emit the ivar list for the given
6100f4a2713aSLionel Sambuc /// implementation. The return value has type
6101f4a2713aSLionel Sambuc /// IvarListnfABIPtrTy.
6102f4a2713aSLionel Sambuc ///  struct _ivar_t {
6103*0a6a1f1dSLionel Sambuc ///   unsigned [long] int *offset;  // pointer to ivar offset location
6104f4a2713aSLionel Sambuc ///   char *name;
6105f4a2713aSLionel Sambuc ///   char *type;
6106f4a2713aSLionel Sambuc ///   uint32_t alignment;
6107f4a2713aSLionel Sambuc ///   uint32_t size;
6108f4a2713aSLionel Sambuc /// }
6109f4a2713aSLionel Sambuc /// struct _ivar_list_t {
6110f4a2713aSLionel Sambuc ///   uint32 entsize;  // sizeof(struct _ivar_t)
6111f4a2713aSLionel Sambuc ///   uint32 count;
6112f4a2713aSLionel Sambuc ///   struct _iver_t list[count];
6113f4a2713aSLionel Sambuc /// }
6114f4a2713aSLionel Sambuc ///
6115f4a2713aSLionel Sambuc 
EmitIvarList(const ObjCImplementationDecl * ID)6116f4a2713aSLionel Sambuc llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
6117f4a2713aSLionel Sambuc   const ObjCImplementationDecl *ID) {
6118f4a2713aSLionel Sambuc 
6119f4a2713aSLionel Sambuc   std::vector<llvm::Constant*> Ivars;
6120f4a2713aSLionel Sambuc 
6121f4a2713aSLionel Sambuc   const ObjCInterfaceDecl *OID = ID->getClassInterface();
6122f4a2713aSLionel Sambuc   assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
6123f4a2713aSLionel Sambuc 
6124f4a2713aSLionel Sambuc   // FIXME. Consolidate this with similar code in GenerateClass.
6125f4a2713aSLionel Sambuc 
6126f4a2713aSLionel Sambuc   for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
6127f4a2713aSLionel Sambuc        IVD; IVD = IVD->getNextIvar()) {
6128f4a2713aSLionel Sambuc     // Ignore unnamed bit-fields.
6129f4a2713aSLionel Sambuc     if (!IVD->getDeclName())
6130f4a2713aSLionel Sambuc       continue;
6131f4a2713aSLionel Sambuc     llvm::Constant *Ivar[5];
6132f4a2713aSLionel Sambuc     Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD,
6133f4a2713aSLionel Sambuc                                 ComputeIvarBaseOffset(CGM, ID, IVD));
6134f4a2713aSLionel Sambuc     Ivar[1] = GetMethodVarName(IVD->getIdentifier());
6135f4a2713aSLionel Sambuc     Ivar[2] = GetMethodVarType(IVD);
6136f4a2713aSLionel Sambuc     llvm::Type *FieldTy =
6137f4a2713aSLionel Sambuc       CGM.getTypes().ConvertTypeForMem(IVD->getType());
6138f4a2713aSLionel Sambuc     unsigned Size = CGM.getDataLayout().getTypeAllocSize(FieldTy);
6139f4a2713aSLionel Sambuc     unsigned Align = CGM.getContext().getPreferredTypeAlign(
6140f4a2713aSLionel Sambuc       IVD->getType().getTypePtr()) >> 3;
6141f4a2713aSLionel Sambuc     Align = llvm::Log2_32(Align);
6142f4a2713aSLionel Sambuc     Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align);
6143f4a2713aSLionel Sambuc     // NOTE. Size of a bitfield does not match gcc's, because of the
6144f4a2713aSLionel Sambuc     // way bitfields are treated special in each. But I am told that
6145f4a2713aSLionel Sambuc     // 'size' for bitfield ivars is ignored by the runtime so it does
6146f4a2713aSLionel Sambuc     // not matter.  If it matters, there is enough info to get the
6147f4a2713aSLionel Sambuc     // bitfield right!
6148f4a2713aSLionel Sambuc     Ivar[4] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
6149f4a2713aSLionel Sambuc     Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarnfABITy, Ivar));
6150f4a2713aSLionel Sambuc   }
6151f4a2713aSLionel Sambuc   // Return null for empty list.
6152f4a2713aSLionel Sambuc   if (Ivars.empty())
6153f4a2713aSLionel Sambuc     return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
6154f4a2713aSLionel Sambuc 
6155f4a2713aSLionel Sambuc   llvm::Constant *Values[3];
6156f4a2713aSLionel Sambuc   unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.IvarnfABITy);
6157f4a2713aSLionel Sambuc   Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
6158f4a2713aSLionel Sambuc   Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
6159f4a2713aSLionel Sambuc   llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy,
6160f4a2713aSLionel Sambuc                                              Ivars.size());
6161f4a2713aSLionel Sambuc   Values[2] = llvm::ConstantArray::get(AT, Ivars);
6162f4a2713aSLionel Sambuc   llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
6163f4a2713aSLionel Sambuc   const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_";
6164f4a2713aSLionel Sambuc   llvm::GlobalVariable *GV =
6165f4a2713aSLionel Sambuc     new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
6166*0a6a1f1dSLionel Sambuc                              llvm::GlobalValue::PrivateLinkage,
6167f4a2713aSLionel Sambuc                              Init,
6168*0a6a1f1dSLionel Sambuc                              Prefix + OID->getObjCRuntimeNameAsString());
6169f4a2713aSLionel Sambuc   GV->setAlignment(
6170f4a2713aSLionel Sambuc     CGM.getDataLayout().getABITypeAlignment(Init->getType()));
6171f4a2713aSLionel Sambuc   GV->setSection("__DATA, __objc_const");
6172f4a2713aSLionel Sambuc 
6173*0a6a1f1dSLionel Sambuc   CGM.addCompilerUsedGlobal(GV);
6174f4a2713aSLionel Sambuc   return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy);
6175f4a2713aSLionel Sambuc }
6176f4a2713aSLionel Sambuc 
GetOrEmitProtocolRef(const ObjCProtocolDecl * PD)6177f4a2713aSLionel Sambuc llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
6178f4a2713aSLionel Sambuc   const ObjCProtocolDecl *PD) {
6179f4a2713aSLionel Sambuc   llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
6180f4a2713aSLionel Sambuc 
6181f4a2713aSLionel Sambuc   if (!Entry) {
6182f4a2713aSLionel Sambuc     // We use the initializer as a marker of whether this is a forward
6183f4a2713aSLionel Sambuc     // reference or not. At module finalization we add the empty
6184f4a2713aSLionel Sambuc     // contents for protocols which were referenced but never defined.
6185f4a2713aSLionel Sambuc     Entry =
6186*0a6a1f1dSLionel Sambuc         new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
6187*0a6a1f1dSLionel Sambuc                                  false, llvm::GlobalValue::ExternalLinkage,
6188*0a6a1f1dSLionel Sambuc                                  nullptr,
6189*0a6a1f1dSLionel Sambuc                                  "\01l_OBJC_PROTOCOL_$_" + PD->getObjCRuntimeNameAsString());
6190f4a2713aSLionel Sambuc     Entry->setSection("__DATA,__datacoal_nt,coalesced");
6191f4a2713aSLionel Sambuc   }
6192f4a2713aSLionel Sambuc 
6193f4a2713aSLionel Sambuc   return Entry;
6194f4a2713aSLionel Sambuc }
6195f4a2713aSLionel Sambuc 
6196f4a2713aSLionel Sambuc /// GetOrEmitProtocol - Generate the protocol meta-data:
6197f4a2713aSLionel Sambuc /// @code
6198f4a2713aSLionel Sambuc /// struct _protocol_t {
6199f4a2713aSLionel Sambuc ///   id isa;  // NULL
6200f4a2713aSLionel Sambuc ///   const char * const protocol_name;
6201f4a2713aSLionel Sambuc ///   const struct _protocol_list_t * protocol_list; // super protocols
6202f4a2713aSLionel Sambuc ///   const struct method_list_t * const instance_methods;
6203f4a2713aSLionel Sambuc ///   const struct method_list_t * const class_methods;
6204f4a2713aSLionel Sambuc ///   const struct method_list_t *optionalInstanceMethods;
6205f4a2713aSLionel Sambuc ///   const struct method_list_t *optionalClassMethods;
6206f4a2713aSLionel Sambuc ///   const struct _prop_list_t * properties;
6207f4a2713aSLionel Sambuc ///   const uint32_t size;  // sizeof(struct _protocol_t)
6208f4a2713aSLionel Sambuc ///   const uint32_t flags;  // = 0
6209f4a2713aSLionel Sambuc ///   const char ** extendedMethodTypes;
6210f4a2713aSLionel Sambuc /// }
6211f4a2713aSLionel Sambuc /// @endcode
6212f4a2713aSLionel Sambuc ///
6213f4a2713aSLionel Sambuc 
GetOrEmitProtocol(const ObjCProtocolDecl * PD)6214f4a2713aSLionel Sambuc llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
6215f4a2713aSLionel Sambuc   const ObjCProtocolDecl *PD) {
6216f4a2713aSLionel Sambuc   llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
6217f4a2713aSLionel Sambuc 
6218f4a2713aSLionel Sambuc   // Early exit if a defining object has already been generated.
6219f4a2713aSLionel Sambuc   if (Entry && Entry->hasInitializer())
6220f4a2713aSLionel Sambuc     return Entry;
6221f4a2713aSLionel Sambuc 
6222f4a2713aSLionel Sambuc   // Use the protocol definition, if there is one.
6223f4a2713aSLionel Sambuc   if (const ObjCProtocolDecl *Def = PD->getDefinition())
6224f4a2713aSLionel Sambuc     PD = Def;
6225f4a2713aSLionel Sambuc 
6226f4a2713aSLionel Sambuc   // Construct method lists.
6227f4a2713aSLionel Sambuc   std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
6228f4a2713aSLionel Sambuc   std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
6229f4a2713aSLionel Sambuc   std::vector<llvm::Constant*> MethodTypesExt, OptMethodTypesExt;
6230*0a6a1f1dSLionel Sambuc   for (const auto *MD : PD->instance_methods()) {
6231f4a2713aSLionel Sambuc     llvm::Constant *C = GetMethodDescriptionConstant(MD);
6232f4a2713aSLionel Sambuc     if (!C)
6233f4a2713aSLionel Sambuc       return GetOrEmitProtocolRef(PD);
6234f4a2713aSLionel Sambuc 
6235f4a2713aSLionel Sambuc     if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
6236f4a2713aSLionel Sambuc       OptInstanceMethods.push_back(C);
6237f4a2713aSLionel Sambuc       OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
6238f4a2713aSLionel Sambuc     } else {
6239f4a2713aSLionel Sambuc       InstanceMethods.push_back(C);
6240f4a2713aSLionel Sambuc       MethodTypesExt.push_back(GetMethodVarType(MD, true));
6241f4a2713aSLionel Sambuc     }
6242f4a2713aSLionel Sambuc   }
6243f4a2713aSLionel Sambuc 
6244*0a6a1f1dSLionel Sambuc   for (const auto *MD : PD->class_methods()) {
6245f4a2713aSLionel Sambuc     llvm::Constant *C = GetMethodDescriptionConstant(MD);
6246f4a2713aSLionel Sambuc     if (!C)
6247f4a2713aSLionel Sambuc       return GetOrEmitProtocolRef(PD);
6248f4a2713aSLionel Sambuc 
6249f4a2713aSLionel Sambuc     if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
6250f4a2713aSLionel Sambuc       OptClassMethods.push_back(C);
6251f4a2713aSLionel Sambuc       OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
6252f4a2713aSLionel Sambuc     } else {
6253f4a2713aSLionel Sambuc       ClassMethods.push_back(C);
6254f4a2713aSLionel Sambuc       MethodTypesExt.push_back(GetMethodVarType(MD, true));
6255f4a2713aSLionel Sambuc     }
6256f4a2713aSLionel Sambuc   }
6257f4a2713aSLionel Sambuc 
6258f4a2713aSLionel Sambuc   MethodTypesExt.insert(MethodTypesExt.end(),
6259f4a2713aSLionel Sambuc                         OptMethodTypesExt.begin(), OptMethodTypesExt.end());
6260f4a2713aSLionel Sambuc 
6261f4a2713aSLionel Sambuc   llvm::Constant *Values[11];
6262f4a2713aSLionel Sambuc   // isa is NULL
6263f4a2713aSLionel Sambuc   Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
6264*0a6a1f1dSLionel Sambuc   Values[1] = GetClassName(PD->getObjCRuntimeNameAsString());
6265*0a6a1f1dSLionel Sambuc   Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getObjCRuntimeNameAsString(),
6266f4a2713aSLionel Sambuc                                PD->protocol_begin(),
6267f4a2713aSLionel Sambuc                                PD->protocol_end());
6268f4a2713aSLionel Sambuc 
6269f4a2713aSLionel Sambuc   Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_"
6270*0a6a1f1dSLionel Sambuc                              + PD->getObjCRuntimeNameAsString(),
6271f4a2713aSLionel Sambuc                              "__DATA, __objc_const",
6272f4a2713aSLionel Sambuc                              InstanceMethods);
6273f4a2713aSLionel Sambuc   Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_"
6274*0a6a1f1dSLionel Sambuc                              + PD->getObjCRuntimeNameAsString(),
6275f4a2713aSLionel Sambuc                              "__DATA, __objc_const",
6276f4a2713aSLionel Sambuc                              ClassMethods);
6277f4a2713aSLionel Sambuc   Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"
6278*0a6a1f1dSLionel Sambuc                              + PD->getObjCRuntimeNameAsString(),
6279f4a2713aSLionel Sambuc                              "__DATA, __objc_const",
6280f4a2713aSLionel Sambuc                              OptInstanceMethods);
6281f4a2713aSLionel Sambuc   Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"
6282*0a6a1f1dSLionel Sambuc                              + PD->getObjCRuntimeNameAsString(),
6283f4a2713aSLionel Sambuc                              "__DATA, __objc_const",
6284f4a2713aSLionel Sambuc                              OptClassMethods);
6285*0a6a1f1dSLionel Sambuc   Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getObjCRuntimeNameAsString(),
6286*0a6a1f1dSLionel Sambuc                                nullptr, PD, ObjCTypes);
6287f4a2713aSLionel Sambuc   uint32_t Size =
6288f4a2713aSLionel Sambuc     CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
6289f4a2713aSLionel Sambuc   Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
6290f4a2713aSLionel Sambuc   Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy);
6291f4a2713aSLionel Sambuc   Values[10] = EmitProtocolMethodTypes("\01l_OBJC_$_PROTOCOL_METHOD_TYPES_"
6292*0a6a1f1dSLionel Sambuc                                        + PD->getObjCRuntimeNameAsString(),
6293f4a2713aSLionel Sambuc                                        MethodTypesExt, ObjCTypes);
6294f4a2713aSLionel Sambuc   llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy,
6295f4a2713aSLionel Sambuc                                                    Values);
6296f4a2713aSLionel Sambuc 
6297f4a2713aSLionel Sambuc   if (Entry) {
6298f4a2713aSLionel Sambuc     // Already created, fix the linkage and update the initializer.
6299f4a2713aSLionel Sambuc     Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
6300f4a2713aSLionel Sambuc     Entry->setInitializer(Init);
6301f4a2713aSLionel Sambuc   } else {
6302f4a2713aSLionel Sambuc     Entry =
6303f4a2713aSLionel Sambuc       new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
6304f4a2713aSLionel Sambuc                                false, llvm::GlobalValue::WeakAnyLinkage, Init,
6305*0a6a1f1dSLionel Sambuc                                "\01l_OBJC_PROTOCOL_$_" + PD->getObjCRuntimeNameAsString());
6306f4a2713aSLionel Sambuc     Entry->setAlignment(
6307f4a2713aSLionel Sambuc       CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABITy));
6308f4a2713aSLionel Sambuc     Entry->setSection("__DATA,__datacoal_nt,coalesced");
6309f4a2713aSLionel Sambuc 
6310f4a2713aSLionel Sambuc     Protocols[PD->getIdentifier()] = Entry;
6311f4a2713aSLionel Sambuc   }
6312f4a2713aSLionel Sambuc   Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
6313*0a6a1f1dSLionel Sambuc   CGM.addCompilerUsedGlobal(Entry);
6314f4a2713aSLionel Sambuc 
6315f4a2713aSLionel Sambuc   // Use this protocol meta-data to build protocol list table in section
6316f4a2713aSLionel Sambuc   // __DATA, __objc_protolist
6317f4a2713aSLionel Sambuc   llvm::GlobalVariable *PTGV =
6318f4a2713aSLionel Sambuc     new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
6319f4a2713aSLionel Sambuc                              false, llvm::GlobalValue::WeakAnyLinkage, Entry,
6320*0a6a1f1dSLionel Sambuc                              "\01l_OBJC_LABEL_PROTOCOL_$_" + PD->getObjCRuntimeNameAsString());
6321f4a2713aSLionel Sambuc   PTGV->setAlignment(
6322f4a2713aSLionel Sambuc     CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
6323f4a2713aSLionel Sambuc   PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
6324f4a2713aSLionel Sambuc   PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
6325*0a6a1f1dSLionel Sambuc   CGM.addCompilerUsedGlobal(PTGV);
6326f4a2713aSLionel Sambuc   return Entry;
6327f4a2713aSLionel Sambuc }
6328f4a2713aSLionel Sambuc 
6329f4a2713aSLionel Sambuc /// EmitProtocolList - Generate protocol list meta-data:
6330f4a2713aSLionel Sambuc /// @code
6331f4a2713aSLionel Sambuc /// struct _protocol_list_t {
6332f4a2713aSLionel Sambuc ///   long protocol_count;   // Note, this is 32/64 bit
6333f4a2713aSLionel Sambuc ///   struct _protocol_t[protocol_count];
6334f4a2713aSLionel Sambuc /// }
6335f4a2713aSLionel Sambuc /// @endcode
6336f4a2713aSLionel Sambuc ///
6337f4a2713aSLionel Sambuc llvm::Constant *
EmitProtocolList(Twine Name,ObjCProtocolDecl::protocol_iterator begin,ObjCProtocolDecl::protocol_iterator end)6338f4a2713aSLionel Sambuc CGObjCNonFragileABIMac::EmitProtocolList(Twine Name,
6339f4a2713aSLionel Sambuc                                       ObjCProtocolDecl::protocol_iterator begin,
6340f4a2713aSLionel Sambuc                                       ObjCProtocolDecl::protocol_iterator end) {
6341f4a2713aSLionel Sambuc   SmallVector<llvm::Constant *, 16> ProtocolRefs;
6342f4a2713aSLionel Sambuc 
6343f4a2713aSLionel Sambuc   // Just return null for empty protocol lists
6344f4a2713aSLionel Sambuc   if (begin == end)
6345f4a2713aSLionel Sambuc     return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
6346f4a2713aSLionel Sambuc 
6347f4a2713aSLionel Sambuc   // FIXME: We shouldn't need to do this lookup here, should we?
6348f4a2713aSLionel Sambuc   SmallString<256> TmpName;
6349f4a2713aSLionel Sambuc   Name.toVector(TmpName);
6350f4a2713aSLionel Sambuc   llvm::GlobalVariable *GV =
6351f4a2713aSLionel Sambuc     CGM.getModule().getGlobalVariable(TmpName.str(), true);
6352f4a2713aSLionel Sambuc   if (GV)
6353f4a2713aSLionel Sambuc     return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
6354f4a2713aSLionel Sambuc 
6355f4a2713aSLionel Sambuc   for (; begin != end; ++begin)
6356f4a2713aSLionel Sambuc     ProtocolRefs.push_back(GetProtocolRef(*begin));  // Implemented???
6357f4a2713aSLionel Sambuc 
6358f4a2713aSLionel Sambuc   // This list is null terminated.
6359f4a2713aSLionel Sambuc   ProtocolRefs.push_back(llvm::Constant::getNullValue(
6360f4a2713aSLionel Sambuc                            ObjCTypes.ProtocolnfABIPtrTy));
6361f4a2713aSLionel Sambuc 
6362f4a2713aSLionel Sambuc   llvm::Constant *Values[2];
6363f4a2713aSLionel Sambuc   Values[0] =
6364f4a2713aSLionel Sambuc     llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1);
6365f4a2713aSLionel Sambuc   Values[1] =
6366f4a2713aSLionel Sambuc     llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy,
6367f4a2713aSLionel Sambuc                                                   ProtocolRefs.size()),
6368f4a2713aSLionel Sambuc                              ProtocolRefs);
6369f4a2713aSLionel Sambuc 
6370f4a2713aSLionel Sambuc   llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
6371f4a2713aSLionel Sambuc   GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
6372*0a6a1f1dSLionel Sambuc                                 llvm::GlobalValue::PrivateLinkage,
6373f4a2713aSLionel Sambuc                                 Init, Name);
6374f4a2713aSLionel Sambuc   GV->setSection("__DATA, __objc_const");
6375f4a2713aSLionel Sambuc   GV->setAlignment(
6376f4a2713aSLionel Sambuc     CGM.getDataLayout().getABITypeAlignment(Init->getType()));
6377*0a6a1f1dSLionel Sambuc   CGM.addCompilerUsedGlobal(GV);
6378f4a2713aSLionel Sambuc   return llvm::ConstantExpr::getBitCast(GV,
6379f4a2713aSLionel Sambuc                                         ObjCTypes.ProtocolListnfABIPtrTy);
6380f4a2713aSLionel Sambuc }
6381f4a2713aSLionel Sambuc 
6382f4a2713aSLionel Sambuc /// GetMethodDescriptionConstant - This routine build following meta-data:
6383f4a2713aSLionel Sambuc /// struct _objc_method {
6384f4a2713aSLionel Sambuc ///   SEL _cmd;
6385f4a2713aSLionel Sambuc ///   char *method_type;
6386f4a2713aSLionel Sambuc ///   char *_imp;
6387f4a2713aSLionel Sambuc /// }
6388f4a2713aSLionel Sambuc 
6389f4a2713aSLionel Sambuc llvm::Constant *
GetMethodDescriptionConstant(const ObjCMethodDecl * MD)6390f4a2713aSLionel Sambuc CGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
6391f4a2713aSLionel Sambuc   llvm::Constant *Desc[3];
6392f4a2713aSLionel Sambuc   Desc[0] =
6393f4a2713aSLionel Sambuc     llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
6394f4a2713aSLionel Sambuc                                    ObjCTypes.SelectorPtrTy);
6395f4a2713aSLionel Sambuc   Desc[1] = GetMethodVarType(MD);
6396f4a2713aSLionel Sambuc   if (!Desc[1])
6397*0a6a1f1dSLionel Sambuc     return nullptr;
6398f4a2713aSLionel Sambuc 
6399f4a2713aSLionel Sambuc   // Protocol methods have no implementation. So, this entry is always NULL.
6400f4a2713aSLionel Sambuc   Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
6401f4a2713aSLionel Sambuc   return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc);
6402f4a2713aSLionel Sambuc }
6403f4a2713aSLionel Sambuc 
6404f4a2713aSLionel Sambuc /// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
6405f4a2713aSLionel Sambuc /// This code gen. amounts to generating code for:
6406f4a2713aSLionel Sambuc /// @code
6407f4a2713aSLionel Sambuc /// (type *)((char *)base + _OBJC_IVAR_$_.ivar;
6408f4a2713aSLionel Sambuc /// @encode
6409f4a2713aSLionel Sambuc ///
EmitObjCValueForIvar(CodeGen::CodeGenFunction & CGF,QualType ObjectTy,llvm::Value * BaseValue,const ObjCIvarDecl * Ivar,unsigned CVRQualifiers)6410f4a2713aSLionel Sambuc LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
6411f4a2713aSLionel Sambuc                                                CodeGen::CodeGenFunction &CGF,
6412f4a2713aSLionel Sambuc                                                QualType ObjectTy,
6413f4a2713aSLionel Sambuc                                                llvm::Value *BaseValue,
6414f4a2713aSLionel Sambuc                                                const ObjCIvarDecl *Ivar,
6415f4a2713aSLionel Sambuc                                                unsigned CVRQualifiers) {
6416f4a2713aSLionel Sambuc   ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCObjectType>()->getInterface();
6417f4a2713aSLionel Sambuc   llvm::Value *Offset = EmitIvarOffset(CGF, ID, Ivar);
6418f4a2713aSLionel Sambuc   return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
6419f4a2713aSLionel Sambuc                                   Offset);
6420f4a2713aSLionel Sambuc }
6421f4a2713aSLionel Sambuc 
EmitIvarOffset(CodeGen::CodeGenFunction & CGF,const ObjCInterfaceDecl * Interface,const ObjCIvarDecl * Ivar)6422f4a2713aSLionel Sambuc llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset(
6423f4a2713aSLionel Sambuc   CodeGen::CodeGenFunction &CGF,
6424f4a2713aSLionel Sambuc   const ObjCInterfaceDecl *Interface,
6425f4a2713aSLionel Sambuc   const ObjCIvarDecl *Ivar) {
6426*0a6a1f1dSLionel Sambuc   llvm::Value *IvarOffsetValue = ObjCIvarOffsetVariable(Interface, Ivar);
6427*0a6a1f1dSLionel Sambuc   IvarOffsetValue = CGF.Builder.CreateLoad(IvarOffsetValue, "ivar");
6428*0a6a1f1dSLionel Sambuc   if (IsIvarOffsetKnownIdempotent(CGF, Ivar))
6429*0a6a1f1dSLionel Sambuc     cast<llvm::LoadInst>(IvarOffsetValue)
6430*0a6a1f1dSLionel Sambuc         ->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
6431*0a6a1f1dSLionel Sambuc                       llvm::MDNode::get(VMContext, None));
6432*0a6a1f1dSLionel Sambuc 
6433*0a6a1f1dSLionel Sambuc   // This could be 32bit int or 64bit integer depending on the architecture.
6434*0a6a1f1dSLionel Sambuc   // Cast it to 64bit integer value, if it is a 32bit integer ivar offset value
6435*0a6a1f1dSLionel Sambuc   //  as this is what caller always expectes.
6436*0a6a1f1dSLionel Sambuc   if (ObjCTypes.IvarOffsetVarTy == ObjCTypes.IntTy)
6437*0a6a1f1dSLionel Sambuc     IvarOffsetValue = CGF.Builder.CreateIntCast(
6438*0a6a1f1dSLionel Sambuc         IvarOffsetValue, ObjCTypes.LongTy, true, "ivar.conv");
6439*0a6a1f1dSLionel Sambuc   return IvarOffsetValue;
6440f4a2713aSLionel Sambuc }
6441f4a2713aSLionel Sambuc 
appendSelectorForMessageRefTable(std::string & buffer,Selector selector)6442f4a2713aSLionel Sambuc static void appendSelectorForMessageRefTable(std::string &buffer,
6443f4a2713aSLionel Sambuc                                              Selector selector) {
6444f4a2713aSLionel Sambuc   if (selector.isUnarySelector()) {
6445f4a2713aSLionel Sambuc     buffer += selector.getNameForSlot(0);
6446f4a2713aSLionel Sambuc     return;
6447f4a2713aSLionel Sambuc   }
6448f4a2713aSLionel Sambuc 
6449f4a2713aSLionel Sambuc   for (unsigned i = 0, e = selector.getNumArgs(); i != e; ++i) {
6450f4a2713aSLionel Sambuc     buffer += selector.getNameForSlot(i);
6451f4a2713aSLionel Sambuc     buffer += '_';
6452f4a2713aSLionel Sambuc   }
6453f4a2713aSLionel Sambuc }
6454f4a2713aSLionel Sambuc 
6455f4a2713aSLionel Sambuc /// Emit a "v-table" message send.  We emit a weak hidden-visibility
6456f4a2713aSLionel Sambuc /// struct, initially containing the selector pointer and a pointer to
6457f4a2713aSLionel Sambuc /// a "fixup" variant of the appropriate objc_msgSend.  To call, we
6458f4a2713aSLionel Sambuc /// load and call the function pointer, passing the address of the
6459f4a2713aSLionel Sambuc /// struct as the second parameter.  The runtime determines whether
6460f4a2713aSLionel Sambuc /// the selector is currently emitted using vtable dispatch; if so, it
6461f4a2713aSLionel Sambuc /// substitutes a stub function which simply tail-calls through the
6462f4a2713aSLionel Sambuc /// appropriate vtable slot, and if not, it substitues a stub function
6463f4a2713aSLionel Sambuc /// which tail-calls objc_msgSend.  Both stubs adjust the selector
6464f4a2713aSLionel Sambuc /// argument to correctly point to the selector.
6465f4a2713aSLionel Sambuc RValue
EmitVTableMessageSend(CodeGenFunction & CGF,ReturnValueSlot returnSlot,QualType resultType,Selector selector,llvm::Value * arg0,QualType arg0Type,bool isSuper,const CallArgList & formalArgs,const ObjCMethodDecl * method)6466f4a2713aSLionel Sambuc CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
6467f4a2713aSLionel Sambuc                                               ReturnValueSlot returnSlot,
6468f4a2713aSLionel Sambuc                                               QualType resultType,
6469f4a2713aSLionel Sambuc                                               Selector selector,
6470f4a2713aSLionel Sambuc                                               llvm::Value *arg0,
6471f4a2713aSLionel Sambuc                                               QualType arg0Type,
6472f4a2713aSLionel Sambuc                                               bool isSuper,
6473f4a2713aSLionel Sambuc                                               const CallArgList &formalArgs,
6474f4a2713aSLionel Sambuc                                               const ObjCMethodDecl *method) {
6475f4a2713aSLionel Sambuc   // Compute the actual arguments.
6476f4a2713aSLionel Sambuc   CallArgList args;
6477f4a2713aSLionel Sambuc 
6478f4a2713aSLionel Sambuc   // First argument: the receiver / super-call structure.
6479f4a2713aSLionel Sambuc   if (!isSuper)
6480f4a2713aSLionel Sambuc     arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy);
6481f4a2713aSLionel Sambuc   args.add(RValue::get(arg0), arg0Type);
6482f4a2713aSLionel Sambuc 
6483f4a2713aSLionel Sambuc   // Second argument: a pointer to the message ref structure.  Leave
6484f4a2713aSLionel Sambuc   // the actual argument value blank for now.
6485*0a6a1f1dSLionel Sambuc   args.add(RValue::get(nullptr), ObjCTypes.MessageRefCPtrTy);
6486f4a2713aSLionel Sambuc 
6487f4a2713aSLionel Sambuc   args.insert(args.end(), formalArgs.begin(), formalArgs.end());
6488f4a2713aSLionel Sambuc 
6489f4a2713aSLionel Sambuc   MessageSendInfo MSI = getMessageSendInfo(method, resultType, args);
6490f4a2713aSLionel Sambuc 
6491f4a2713aSLionel Sambuc   NullReturnState nullReturn;
6492f4a2713aSLionel Sambuc 
6493f4a2713aSLionel Sambuc   // Find the function to call and the mangled name for the message
6494f4a2713aSLionel Sambuc   // ref structure.  Using a different mangled name wouldn't actually
6495f4a2713aSLionel Sambuc   // be a problem; it would just be a waste.
6496f4a2713aSLionel Sambuc   //
6497f4a2713aSLionel Sambuc   // The runtime currently never uses vtable dispatch for anything
6498f4a2713aSLionel Sambuc   // except normal, non-super message-sends.
6499f4a2713aSLionel Sambuc   // FIXME: don't use this for that.
6500*0a6a1f1dSLionel Sambuc   llvm::Constant *fn = nullptr;
6501f4a2713aSLionel Sambuc   std::string messageRefName("\01l_");
6502*0a6a1f1dSLionel Sambuc   if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) {
6503f4a2713aSLionel Sambuc     if (isSuper) {
6504f4a2713aSLionel Sambuc       fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
6505f4a2713aSLionel Sambuc       messageRefName += "objc_msgSendSuper2_stret_fixup";
6506f4a2713aSLionel Sambuc     } else {
6507f4a2713aSLionel Sambuc       nullReturn.init(CGF, arg0);
6508f4a2713aSLionel Sambuc       fn = ObjCTypes.getMessageSendStretFixupFn();
6509f4a2713aSLionel Sambuc       messageRefName += "objc_msgSend_stret_fixup";
6510f4a2713aSLionel Sambuc     }
6511f4a2713aSLionel Sambuc   } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) {
6512f4a2713aSLionel Sambuc     fn = ObjCTypes.getMessageSendFpretFixupFn();
6513f4a2713aSLionel Sambuc     messageRefName += "objc_msgSend_fpret_fixup";
6514f4a2713aSLionel Sambuc   } else {
6515f4a2713aSLionel Sambuc     if (isSuper) {
6516f4a2713aSLionel Sambuc       fn = ObjCTypes.getMessageSendSuper2FixupFn();
6517f4a2713aSLionel Sambuc       messageRefName += "objc_msgSendSuper2_fixup";
6518f4a2713aSLionel Sambuc     } else {
6519f4a2713aSLionel Sambuc       fn = ObjCTypes.getMessageSendFixupFn();
6520f4a2713aSLionel Sambuc       messageRefName += "objc_msgSend_fixup";
6521f4a2713aSLionel Sambuc     }
6522f4a2713aSLionel Sambuc   }
6523f4a2713aSLionel Sambuc   assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend");
6524f4a2713aSLionel Sambuc   messageRefName += '_';
6525f4a2713aSLionel Sambuc 
6526f4a2713aSLionel Sambuc   // Append the selector name, except use underscores anywhere we
6527f4a2713aSLionel Sambuc   // would have used colons.
6528f4a2713aSLionel Sambuc   appendSelectorForMessageRefTable(messageRefName, selector);
6529f4a2713aSLionel Sambuc 
6530f4a2713aSLionel Sambuc   llvm::GlobalVariable *messageRef
6531f4a2713aSLionel Sambuc     = CGM.getModule().getGlobalVariable(messageRefName);
6532f4a2713aSLionel Sambuc   if (!messageRef) {
6533f4a2713aSLionel Sambuc     // Build the message ref structure.
6534f4a2713aSLionel Sambuc     llvm::Constant *values[] = { fn, GetMethodVarName(selector) };
6535f4a2713aSLionel Sambuc     llvm::Constant *init = llvm::ConstantStruct::getAnon(values);
6536f4a2713aSLionel Sambuc     messageRef = new llvm::GlobalVariable(CGM.getModule(),
6537f4a2713aSLionel Sambuc                                           init->getType(),
6538f4a2713aSLionel Sambuc                                           /*constant*/ false,
6539f4a2713aSLionel Sambuc                                           llvm::GlobalValue::WeakAnyLinkage,
6540f4a2713aSLionel Sambuc                                           init,
6541f4a2713aSLionel Sambuc                                           messageRefName);
6542f4a2713aSLionel Sambuc     messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
6543f4a2713aSLionel Sambuc     messageRef->setAlignment(16);
6544f4a2713aSLionel Sambuc     messageRef->setSection("__DATA, __objc_msgrefs, coalesced");
6545f4a2713aSLionel Sambuc   }
6546f4a2713aSLionel Sambuc 
6547f4a2713aSLionel Sambuc   bool requiresnullCheck = false;
6548f4a2713aSLionel Sambuc   if (CGM.getLangOpts().ObjCAutoRefCount && method)
6549*0a6a1f1dSLionel Sambuc     for (const auto *ParamDecl : method->params()) {
6550f4a2713aSLionel Sambuc       if (ParamDecl->hasAttr<NSConsumedAttr>()) {
6551f4a2713aSLionel Sambuc         if (!nullReturn.NullBB)
6552f4a2713aSLionel Sambuc           nullReturn.init(CGF, arg0);
6553f4a2713aSLionel Sambuc         requiresnullCheck = true;
6554f4a2713aSLionel Sambuc         break;
6555f4a2713aSLionel Sambuc       }
6556f4a2713aSLionel Sambuc     }
6557f4a2713aSLionel Sambuc 
6558f4a2713aSLionel Sambuc   llvm::Value *mref =
6559f4a2713aSLionel Sambuc     CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy);
6560f4a2713aSLionel Sambuc 
6561f4a2713aSLionel Sambuc   // Update the message ref argument.
6562f4a2713aSLionel Sambuc   args[1].RV = RValue::get(mref);
6563f4a2713aSLionel Sambuc 
6564f4a2713aSLionel Sambuc   // Load the function to call from the message ref table.
6565f4a2713aSLionel Sambuc   llvm::Value *callee = CGF.Builder.CreateStructGEP(mref, 0);
6566f4a2713aSLionel Sambuc   callee = CGF.Builder.CreateLoad(callee, "msgSend_fn");
6567f4a2713aSLionel Sambuc 
6568f4a2713aSLionel Sambuc   callee = CGF.Builder.CreateBitCast(callee, MSI.MessengerType);
6569f4a2713aSLionel Sambuc 
6570f4a2713aSLionel Sambuc   RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args);
6571f4a2713aSLionel Sambuc   return nullReturn.complete(CGF, result, resultType, formalArgs,
6572*0a6a1f1dSLionel Sambuc                              requiresnullCheck ? method : nullptr);
6573f4a2713aSLionel Sambuc }
6574f4a2713aSLionel Sambuc 
6575f4a2713aSLionel Sambuc /// Generate code for a message send expression in the nonfragile abi.
6576f4a2713aSLionel Sambuc CodeGen::RValue
GenerateMessageSend(CodeGen::CodeGenFunction & CGF,ReturnValueSlot Return,QualType ResultType,Selector Sel,llvm::Value * Receiver,const CallArgList & CallArgs,const ObjCInterfaceDecl * Class,const ObjCMethodDecl * Method)6577f4a2713aSLionel Sambuc CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
6578f4a2713aSLionel Sambuc                                             ReturnValueSlot Return,
6579f4a2713aSLionel Sambuc                                             QualType ResultType,
6580f4a2713aSLionel Sambuc                                             Selector Sel,
6581f4a2713aSLionel Sambuc                                             llvm::Value *Receiver,
6582f4a2713aSLionel Sambuc                                             const CallArgList &CallArgs,
6583f4a2713aSLionel Sambuc                                             const ObjCInterfaceDecl *Class,
6584f4a2713aSLionel Sambuc                                             const ObjCMethodDecl *Method) {
6585f4a2713aSLionel Sambuc   return isVTableDispatchedSelector(Sel)
6586f4a2713aSLionel Sambuc     ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
6587f4a2713aSLionel Sambuc                             Receiver, CGF.getContext().getObjCIdType(),
6588f4a2713aSLionel Sambuc                             false, CallArgs, Method)
6589f4a2713aSLionel Sambuc     : EmitMessageSend(CGF, Return, ResultType,
6590f4a2713aSLionel Sambuc                       EmitSelector(CGF, Sel),
6591f4a2713aSLionel Sambuc                       Receiver, CGF.getContext().getObjCIdType(),
6592f4a2713aSLionel Sambuc                       false, CallArgs, Method, ObjCTypes);
6593f4a2713aSLionel Sambuc }
6594f4a2713aSLionel Sambuc 
6595f4a2713aSLionel Sambuc llvm::GlobalVariable *
GetClassGlobal(const std::string & Name,bool Weak)6596*0a6a1f1dSLionel Sambuc CGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name, bool Weak) {
6597*0a6a1f1dSLionel Sambuc   llvm::GlobalValue::LinkageTypes L =
6598*0a6a1f1dSLionel Sambuc       Weak ? llvm::GlobalValue::ExternalWeakLinkage
6599*0a6a1f1dSLionel Sambuc            : llvm::GlobalValue::ExternalLinkage;
6600*0a6a1f1dSLionel Sambuc 
6601f4a2713aSLionel Sambuc   llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
6602f4a2713aSLionel Sambuc 
6603*0a6a1f1dSLionel Sambuc   if (!GV)
6604f4a2713aSLionel Sambuc     GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy,
6605*0a6a1f1dSLionel Sambuc                                   false, L, nullptr, Name);
6606f4a2713aSLionel Sambuc 
6607*0a6a1f1dSLionel Sambuc   assert(GV->getLinkage() == L);
6608f4a2713aSLionel Sambuc   return GV;
6609f4a2713aSLionel Sambuc }
6610f4a2713aSLionel Sambuc 
EmitClassRefFromId(CodeGenFunction & CGF,IdentifierInfo * II,bool Weak,const ObjCInterfaceDecl * ID)6611f4a2713aSLionel Sambuc llvm::Value *CGObjCNonFragileABIMac::EmitClassRefFromId(CodeGenFunction &CGF,
6612*0a6a1f1dSLionel Sambuc                                                         IdentifierInfo *II,
6613*0a6a1f1dSLionel Sambuc                                                         bool Weak,
6614*0a6a1f1dSLionel Sambuc                                                         const ObjCInterfaceDecl *ID) {
6615f4a2713aSLionel Sambuc   llvm::GlobalVariable *&Entry = ClassReferences[II];
6616f4a2713aSLionel Sambuc 
6617f4a2713aSLionel Sambuc   if (!Entry) {
6618*0a6a1f1dSLionel Sambuc     std::string ClassName(
6619*0a6a1f1dSLionel Sambuc       getClassSymbolPrefix() +
6620*0a6a1f1dSLionel Sambuc       (ID ? ID->getObjCRuntimeNameAsString() : II->getName()).str());
6621*0a6a1f1dSLionel Sambuc     llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName, Weak);
6622*0a6a1f1dSLionel Sambuc     Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
6623*0a6a1f1dSLionel Sambuc                                      false, llvm::GlobalValue::PrivateLinkage,
6624*0a6a1f1dSLionel Sambuc                                      ClassGV, "OBJC_CLASSLIST_REFERENCES_$_");
6625f4a2713aSLionel Sambuc     Entry->setAlignment(
6626f4a2713aSLionel Sambuc                         CGM.getDataLayout().getABITypeAlignment(
6627f4a2713aSLionel Sambuc                                                                 ObjCTypes.ClassnfABIPtrTy));
6628f4a2713aSLionel Sambuc     Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip");
6629*0a6a1f1dSLionel Sambuc     CGM.addCompilerUsedGlobal(Entry);
6630f4a2713aSLionel Sambuc   }
6631f4a2713aSLionel Sambuc   return CGF.Builder.CreateLoad(Entry);
6632f4a2713aSLionel Sambuc }
6633f4a2713aSLionel Sambuc 
EmitClassRef(CodeGenFunction & CGF,const ObjCInterfaceDecl * ID)6634f4a2713aSLionel Sambuc llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CodeGenFunction &CGF,
6635f4a2713aSLionel Sambuc                                                   const ObjCInterfaceDecl *ID) {
6636*0a6a1f1dSLionel Sambuc   return EmitClassRefFromId(CGF, ID->getIdentifier(), ID->isWeakImported(), ID);
6637f4a2713aSLionel Sambuc }
6638f4a2713aSLionel Sambuc 
EmitNSAutoreleasePoolClassRef(CodeGenFunction & CGF)6639f4a2713aSLionel Sambuc llvm::Value *CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef(
6640f4a2713aSLionel Sambuc                                                     CodeGenFunction &CGF) {
6641f4a2713aSLionel Sambuc   IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
6642*0a6a1f1dSLionel Sambuc   return EmitClassRefFromId(CGF, II, false, 0);
6643f4a2713aSLionel Sambuc }
6644f4a2713aSLionel Sambuc 
6645f4a2713aSLionel Sambuc llvm::Value *
EmitSuperClassRef(CodeGenFunction & CGF,const ObjCInterfaceDecl * ID)6646f4a2713aSLionel Sambuc CGObjCNonFragileABIMac::EmitSuperClassRef(CodeGenFunction &CGF,
6647f4a2713aSLionel Sambuc                                           const ObjCInterfaceDecl *ID) {
6648f4a2713aSLionel Sambuc   llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
6649f4a2713aSLionel Sambuc 
6650f4a2713aSLionel Sambuc   if (!Entry) {
6651*0a6a1f1dSLionel Sambuc     llvm::SmallString<64> ClassName(getClassSymbolPrefix());
6652*0a6a1f1dSLionel Sambuc     ClassName += ID->getObjCRuntimeNameAsString();
6653*0a6a1f1dSLionel Sambuc     llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName.str(),
6654*0a6a1f1dSLionel Sambuc                                                    ID->isWeakImported());
6655*0a6a1f1dSLionel Sambuc     Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
6656*0a6a1f1dSLionel Sambuc                                      false, llvm::GlobalValue::PrivateLinkage,
6657*0a6a1f1dSLionel Sambuc                                      ClassGV, "OBJC_CLASSLIST_SUP_REFS_$_");
6658f4a2713aSLionel Sambuc     Entry->setAlignment(
6659f4a2713aSLionel Sambuc       CGM.getDataLayout().getABITypeAlignment(
6660f4a2713aSLionel Sambuc         ObjCTypes.ClassnfABIPtrTy));
6661f4a2713aSLionel Sambuc     Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
6662*0a6a1f1dSLionel Sambuc     CGM.addCompilerUsedGlobal(Entry);
6663f4a2713aSLionel Sambuc   }
6664f4a2713aSLionel Sambuc   return CGF.Builder.CreateLoad(Entry);
6665f4a2713aSLionel Sambuc }
6666f4a2713aSLionel Sambuc 
6667f4a2713aSLionel Sambuc /// EmitMetaClassRef - Return a Value * of the address of _class_t
6668f4a2713aSLionel Sambuc /// meta-data
6669f4a2713aSLionel Sambuc ///
EmitMetaClassRef(CodeGenFunction & CGF,const ObjCInterfaceDecl * ID,bool Weak)6670f4a2713aSLionel Sambuc llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CodeGenFunction &CGF,
6671*0a6a1f1dSLionel Sambuc                                                       const ObjCInterfaceDecl *ID,
6672*0a6a1f1dSLionel Sambuc                                                       bool Weak) {
6673f4a2713aSLionel Sambuc   llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
6674*0a6a1f1dSLionel Sambuc   if (!Entry) {
6675*0a6a1f1dSLionel Sambuc     llvm::SmallString<64> MetaClassName(getMetaclassSymbolPrefix());
6676*0a6a1f1dSLionel Sambuc     MetaClassName += ID->getObjCRuntimeNameAsString();
6677*0a6a1f1dSLionel Sambuc     llvm::GlobalVariable *MetaClassGV =
6678*0a6a1f1dSLionel Sambuc       GetClassGlobal(MetaClassName.str(), Weak);
6679f4a2713aSLionel Sambuc 
6680*0a6a1f1dSLionel Sambuc     Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
6681*0a6a1f1dSLionel Sambuc                                      false, llvm::GlobalValue::PrivateLinkage,
6682*0a6a1f1dSLionel Sambuc                                      MetaClassGV, "OBJC_CLASSLIST_SUP_REFS_$_");
6683f4a2713aSLionel Sambuc     Entry->setAlignment(
6684*0a6a1f1dSLionel Sambuc         CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassnfABIPtrTy));
6685f4a2713aSLionel Sambuc 
6686f4a2713aSLionel Sambuc     Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
6687*0a6a1f1dSLionel Sambuc     CGM.addCompilerUsedGlobal(Entry);
6688*0a6a1f1dSLionel Sambuc   }
6689f4a2713aSLionel Sambuc 
6690f4a2713aSLionel Sambuc   return CGF.Builder.CreateLoad(Entry);
6691f4a2713aSLionel Sambuc }
6692f4a2713aSLionel Sambuc 
6693f4a2713aSLionel Sambuc /// GetClass - Return a reference to the class for the given interface
6694f4a2713aSLionel Sambuc /// decl.
GetClass(CodeGenFunction & CGF,const ObjCInterfaceDecl * ID)6695f4a2713aSLionel Sambuc llvm::Value *CGObjCNonFragileABIMac::GetClass(CodeGenFunction &CGF,
6696f4a2713aSLionel Sambuc                                               const ObjCInterfaceDecl *ID) {
6697f4a2713aSLionel Sambuc   if (ID->isWeakImported()) {
6698*0a6a1f1dSLionel Sambuc     llvm::SmallString<64> ClassName(getClassSymbolPrefix());
6699*0a6a1f1dSLionel Sambuc     ClassName += ID->getObjCRuntimeNameAsString();
6700*0a6a1f1dSLionel Sambuc     llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName.str(), true);
6701*0a6a1f1dSLionel Sambuc     (void)ClassGV;
6702*0a6a1f1dSLionel Sambuc     assert(ClassGV->hasExternalWeakLinkage());
6703f4a2713aSLionel Sambuc   }
6704f4a2713aSLionel Sambuc 
6705f4a2713aSLionel Sambuc   return EmitClassRef(CGF, ID);
6706f4a2713aSLionel Sambuc }
6707f4a2713aSLionel Sambuc 
6708f4a2713aSLionel Sambuc /// Generates a message send where the super is the receiver.  This is
6709f4a2713aSLionel Sambuc /// a message send to self with special delivery semantics indicating
6710f4a2713aSLionel Sambuc /// which class's method should be called.
6711f4a2713aSLionel Sambuc CodeGen::RValue
GenerateMessageSendSuper(CodeGen::CodeGenFunction & CGF,ReturnValueSlot Return,QualType ResultType,Selector Sel,const ObjCInterfaceDecl * Class,bool isCategoryImpl,llvm::Value * Receiver,bool IsClassMessage,const CodeGen::CallArgList & CallArgs,const ObjCMethodDecl * Method)6712f4a2713aSLionel Sambuc CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
6713f4a2713aSLionel Sambuc                                                  ReturnValueSlot Return,
6714f4a2713aSLionel Sambuc                                                  QualType ResultType,
6715f4a2713aSLionel Sambuc                                                  Selector Sel,
6716f4a2713aSLionel Sambuc                                                  const ObjCInterfaceDecl *Class,
6717f4a2713aSLionel Sambuc                                                  bool isCategoryImpl,
6718f4a2713aSLionel Sambuc                                                  llvm::Value *Receiver,
6719f4a2713aSLionel Sambuc                                                  bool IsClassMessage,
6720f4a2713aSLionel Sambuc                                                  const CodeGen::CallArgList &CallArgs,
6721f4a2713aSLionel Sambuc                                                  const ObjCMethodDecl *Method) {
6722f4a2713aSLionel Sambuc   // ...
6723f4a2713aSLionel Sambuc   // Create and init a super structure; this is a (receiver, class)
6724f4a2713aSLionel Sambuc   // pair we will pass to objc_msgSendSuper.
6725f4a2713aSLionel Sambuc   llvm::Value *ObjCSuper =
6726f4a2713aSLionel Sambuc     CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
6727f4a2713aSLionel Sambuc 
6728f4a2713aSLionel Sambuc   llvm::Value *ReceiverAsObject =
6729f4a2713aSLionel Sambuc     CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
6730f4a2713aSLionel Sambuc   CGF.Builder.CreateStore(ReceiverAsObject,
6731f4a2713aSLionel Sambuc                           CGF.Builder.CreateStructGEP(ObjCSuper, 0));
6732f4a2713aSLionel Sambuc 
6733f4a2713aSLionel Sambuc   // If this is a class message the metaclass is passed as the target.
6734f4a2713aSLionel Sambuc   llvm::Value *Target;
6735f4a2713aSLionel Sambuc   if (IsClassMessage)
6736*0a6a1f1dSLionel Sambuc       Target = EmitMetaClassRef(CGF, Class, Class->isWeakImported());
6737f4a2713aSLionel Sambuc   else
6738f4a2713aSLionel Sambuc     Target = EmitSuperClassRef(CGF, Class);
6739f4a2713aSLionel Sambuc 
6740f4a2713aSLionel Sambuc   // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
6741f4a2713aSLionel Sambuc   // ObjCTypes types.
6742f4a2713aSLionel Sambuc   llvm::Type *ClassTy =
6743f4a2713aSLionel Sambuc     CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
6744f4a2713aSLionel Sambuc   Target = CGF.Builder.CreateBitCast(Target, ClassTy);
6745f4a2713aSLionel Sambuc   CGF.Builder.CreateStore(Target,
6746f4a2713aSLionel Sambuc                           CGF.Builder.CreateStructGEP(ObjCSuper, 1));
6747f4a2713aSLionel Sambuc 
6748f4a2713aSLionel Sambuc   return (isVTableDispatchedSelector(Sel))
6749f4a2713aSLionel Sambuc     ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
6750f4a2713aSLionel Sambuc                             ObjCSuper, ObjCTypes.SuperPtrCTy,
6751f4a2713aSLionel Sambuc                             true, CallArgs, Method)
6752f4a2713aSLionel Sambuc     : EmitMessageSend(CGF, Return, ResultType,
6753f4a2713aSLionel Sambuc                       EmitSelector(CGF, Sel),
6754f4a2713aSLionel Sambuc                       ObjCSuper, ObjCTypes.SuperPtrCTy,
6755f4a2713aSLionel Sambuc                       true, CallArgs, Method, ObjCTypes);
6756f4a2713aSLionel Sambuc }
6757f4a2713aSLionel Sambuc 
EmitSelector(CodeGenFunction & CGF,Selector Sel,bool lval)6758f4a2713aSLionel Sambuc llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CodeGenFunction &CGF,
6759f4a2713aSLionel Sambuc                                                   Selector Sel, bool lval) {
6760f4a2713aSLionel Sambuc   llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
6761f4a2713aSLionel Sambuc 
6762f4a2713aSLionel Sambuc   if (!Entry) {
6763f4a2713aSLionel Sambuc     llvm::Constant *Casted =
6764f4a2713aSLionel Sambuc       llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
6765f4a2713aSLionel Sambuc                                      ObjCTypes.SelectorPtrTy);
6766*0a6a1f1dSLionel Sambuc     Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.SelectorPtrTy,
6767*0a6a1f1dSLionel Sambuc                                      false, llvm::GlobalValue::PrivateLinkage,
6768*0a6a1f1dSLionel Sambuc                                      Casted, "OBJC_SELECTOR_REFERENCES_");
6769f4a2713aSLionel Sambuc     Entry->setExternallyInitialized(true);
6770f4a2713aSLionel Sambuc     Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
6771*0a6a1f1dSLionel Sambuc     CGM.addCompilerUsedGlobal(Entry);
6772f4a2713aSLionel Sambuc   }
6773f4a2713aSLionel Sambuc 
6774f4a2713aSLionel Sambuc   if (lval)
6775f4a2713aSLionel Sambuc     return Entry;
6776f4a2713aSLionel Sambuc   llvm::LoadInst* LI = CGF.Builder.CreateLoad(Entry);
6777f4a2713aSLionel Sambuc 
6778f4a2713aSLionel Sambuc   LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
6779*0a6a1f1dSLionel Sambuc                   llvm::MDNode::get(VMContext, None));
6780f4a2713aSLionel Sambuc   return LI;
6781f4a2713aSLionel Sambuc }
6782f4a2713aSLionel Sambuc /// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
6783f4a2713aSLionel Sambuc /// objc_assign_ivar (id src, id *dst, ptrdiff_t)
6784f4a2713aSLionel Sambuc ///
EmitObjCIvarAssign(CodeGen::CodeGenFunction & CGF,llvm::Value * src,llvm::Value * dst,llvm::Value * ivarOffset)6785f4a2713aSLionel Sambuc void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
6786f4a2713aSLionel Sambuc                                                 llvm::Value *src,
6787f4a2713aSLionel Sambuc                                                 llvm::Value *dst,
6788f4a2713aSLionel Sambuc                                                 llvm::Value *ivarOffset) {
6789f4a2713aSLionel Sambuc   llvm::Type * SrcTy = src->getType();
6790f4a2713aSLionel Sambuc   if (!isa<llvm::PointerType>(SrcTy)) {
6791f4a2713aSLionel Sambuc     unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
6792f4a2713aSLionel Sambuc     assert(Size <= 8 && "does not support size > 8");
6793f4a2713aSLionel Sambuc     src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
6794f4a2713aSLionel Sambuc            : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
6795f4a2713aSLionel Sambuc     src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6796f4a2713aSLionel Sambuc   }
6797f4a2713aSLionel Sambuc   src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6798f4a2713aSLionel Sambuc   dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
6799f4a2713aSLionel Sambuc   llvm::Value *args[] = { src, dst, ivarOffset };
6800f4a2713aSLionel Sambuc   CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
6801f4a2713aSLionel Sambuc }
6802f4a2713aSLionel Sambuc 
6803f4a2713aSLionel Sambuc /// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
6804f4a2713aSLionel Sambuc /// objc_assign_strongCast (id src, id *dst)
6805f4a2713aSLionel Sambuc ///
EmitObjCStrongCastAssign(CodeGen::CodeGenFunction & CGF,llvm::Value * src,llvm::Value * dst)6806f4a2713aSLionel Sambuc void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
6807f4a2713aSLionel Sambuc   CodeGen::CodeGenFunction &CGF,
6808f4a2713aSLionel Sambuc   llvm::Value *src, llvm::Value *dst) {
6809f4a2713aSLionel Sambuc   llvm::Type * SrcTy = src->getType();
6810f4a2713aSLionel Sambuc   if (!isa<llvm::PointerType>(SrcTy)) {
6811f4a2713aSLionel Sambuc     unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
6812f4a2713aSLionel Sambuc     assert(Size <= 8 && "does not support size > 8");
6813f4a2713aSLionel Sambuc     src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
6814f4a2713aSLionel Sambuc            : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
6815f4a2713aSLionel Sambuc     src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6816f4a2713aSLionel Sambuc   }
6817f4a2713aSLionel Sambuc   src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6818f4a2713aSLionel Sambuc   dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
6819f4a2713aSLionel Sambuc   llvm::Value *args[] = { src, dst };
6820f4a2713aSLionel Sambuc   CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(),
6821f4a2713aSLionel Sambuc                               args, "weakassign");
6822f4a2713aSLionel Sambuc }
6823f4a2713aSLionel Sambuc 
EmitGCMemmoveCollectable(CodeGen::CodeGenFunction & CGF,llvm::Value * DestPtr,llvm::Value * SrcPtr,llvm::Value * Size)6824f4a2713aSLionel Sambuc void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
6825f4a2713aSLionel Sambuc   CodeGen::CodeGenFunction &CGF,
6826f4a2713aSLionel Sambuc   llvm::Value *DestPtr,
6827f4a2713aSLionel Sambuc   llvm::Value *SrcPtr,
6828f4a2713aSLionel Sambuc   llvm::Value *Size) {
6829f4a2713aSLionel Sambuc   SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
6830f4a2713aSLionel Sambuc   DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
6831f4a2713aSLionel Sambuc   llvm::Value *args[] = { DestPtr, SrcPtr, Size };
6832f4a2713aSLionel Sambuc   CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
6833f4a2713aSLionel Sambuc }
6834f4a2713aSLionel Sambuc 
6835f4a2713aSLionel Sambuc /// EmitObjCWeakRead - Code gen for loading value of a __weak
6836f4a2713aSLionel Sambuc /// object: objc_read_weak (id *src)
6837f4a2713aSLionel Sambuc ///
EmitObjCWeakRead(CodeGen::CodeGenFunction & CGF,llvm::Value * AddrWeakObj)6838f4a2713aSLionel Sambuc llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
6839f4a2713aSLionel Sambuc   CodeGen::CodeGenFunction &CGF,
6840f4a2713aSLionel Sambuc   llvm::Value *AddrWeakObj) {
6841f4a2713aSLionel Sambuc   llvm::Type* DestTy =
6842f4a2713aSLionel Sambuc     cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
6843f4a2713aSLionel Sambuc   AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
6844f4a2713aSLionel Sambuc   llvm::Value *read_weak =
6845f4a2713aSLionel Sambuc     CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(),
6846f4a2713aSLionel Sambuc                                 AddrWeakObj, "weakread");
6847f4a2713aSLionel Sambuc   read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
6848f4a2713aSLionel Sambuc   return read_weak;
6849f4a2713aSLionel Sambuc }
6850f4a2713aSLionel Sambuc 
6851f4a2713aSLionel Sambuc /// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
6852f4a2713aSLionel Sambuc /// objc_assign_weak (id src, id *dst)
6853f4a2713aSLionel Sambuc ///
EmitObjCWeakAssign(CodeGen::CodeGenFunction & CGF,llvm::Value * src,llvm::Value * dst)6854f4a2713aSLionel Sambuc void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
6855f4a2713aSLionel Sambuc                                                 llvm::Value *src, llvm::Value *dst) {
6856f4a2713aSLionel Sambuc   llvm::Type * SrcTy = src->getType();
6857f4a2713aSLionel Sambuc   if (!isa<llvm::PointerType>(SrcTy)) {
6858f4a2713aSLionel Sambuc     unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
6859f4a2713aSLionel Sambuc     assert(Size <= 8 && "does not support size > 8");
6860f4a2713aSLionel Sambuc     src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
6861f4a2713aSLionel Sambuc            : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
6862f4a2713aSLionel Sambuc     src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6863f4a2713aSLionel Sambuc   }
6864f4a2713aSLionel Sambuc   src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6865f4a2713aSLionel Sambuc   dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
6866f4a2713aSLionel Sambuc   llvm::Value *args[] = { src, dst };
6867f4a2713aSLionel Sambuc   CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(),
6868f4a2713aSLionel Sambuc                               args, "weakassign");
6869f4a2713aSLionel Sambuc }
6870f4a2713aSLionel Sambuc 
6871f4a2713aSLionel Sambuc /// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
6872f4a2713aSLionel Sambuc /// objc_assign_global (id src, id *dst)
6873f4a2713aSLionel Sambuc ///
EmitObjCGlobalAssign(CodeGen::CodeGenFunction & CGF,llvm::Value * src,llvm::Value * dst,bool threadlocal)6874f4a2713aSLionel Sambuc void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
6875f4a2713aSLionel Sambuc                                           llvm::Value *src, llvm::Value *dst,
6876f4a2713aSLionel Sambuc                                           bool threadlocal) {
6877f4a2713aSLionel Sambuc   llvm::Type * SrcTy = src->getType();
6878f4a2713aSLionel Sambuc   if (!isa<llvm::PointerType>(SrcTy)) {
6879f4a2713aSLionel Sambuc     unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
6880f4a2713aSLionel Sambuc     assert(Size <= 8 && "does not support size > 8");
6881f4a2713aSLionel Sambuc     src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
6882f4a2713aSLionel Sambuc            : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
6883f4a2713aSLionel Sambuc     src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6884f4a2713aSLionel Sambuc   }
6885f4a2713aSLionel Sambuc   src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6886f4a2713aSLionel Sambuc   dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
6887f4a2713aSLionel Sambuc   llvm::Value *args[] = { src, dst };
6888f4a2713aSLionel Sambuc   if (!threadlocal)
6889f4a2713aSLionel Sambuc     CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(),
6890f4a2713aSLionel Sambuc                                 args, "globalassign");
6891f4a2713aSLionel Sambuc   else
6892f4a2713aSLionel Sambuc     CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(),
6893f4a2713aSLionel Sambuc                                 args, "threadlocalassign");
6894f4a2713aSLionel Sambuc }
6895f4a2713aSLionel Sambuc 
6896f4a2713aSLionel Sambuc void
EmitSynchronizedStmt(CodeGen::CodeGenFunction & CGF,const ObjCAtSynchronizedStmt & S)6897f4a2713aSLionel Sambuc CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
6898f4a2713aSLionel Sambuc                                              const ObjCAtSynchronizedStmt &S) {
6899f4a2713aSLionel Sambuc   EmitAtSynchronizedStmt(CGF, S,
6900f4a2713aSLionel Sambuc       cast<llvm::Function>(ObjCTypes.getSyncEnterFn()),
6901f4a2713aSLionel Sambuc       cast<llvm::Function>(ObjCTypes.getSyncExitFn()));
6902f4a2713aSLionel Sambuc }
6903f4a2713aSLionel Sambuc 
6904f4a2713aSLionel Sambuc llvm::Constant *
GetEHType(QualType T)6905f4a2713aSLionel Sambuc CGObjCNonFragileABIMac::GetEHType(QualType T) {
6906f4a2713aSLionel Sambuc   // There's a particular fixed type info for 'id'.
6907f4a2713aSLionel Sambuc   if (T->isObjCIdType() ||
6908f4a2713aSLionel Sambuc       T->isObjCQualifiedIdType()) {
6909f4a2713aSLionel Sambuc     llvm::Constant *IDEHType =
6910f4a2713aSLionel Sambuc       CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
6911f4a2713aSLionel Sambuc     if (!IDEHType)
6912f4a2713aSLionel Sambuc       IDEHType =
6913f4a2713aSLionel Sambuc         new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
6914f4a2713aSLionel Sambuc                                  false,
6915f4a2713aSLionel Sambuc                                  llvm::GlobalValue::ExternalLinkage,
6916*0a6a1f1dSLionel Sambuc                                  nullptr, "OBJC_EHTYPE_id");
6917f4a2713aSLionel Sambuc     return IDEHType;
6918f4a2713aSLionel Sambuc   }
6919f4a2713aSLionel Sambuc 
6920f4a2713aSLionel Sambuc   // All other types should be Objective-C interface pointer types.
6921f4a2713aSLionel Sambuc   const ObjCObjectPointerType *PT =
6922f4a2713aSLionel Sambuc     T->getAs<ObjCObjectPointerType>();
6923f4a2713aSLionel Sambuc   assert(PT && "Invalid @catch type.");
6924f4a2713aSLionel Sambuc   const ObjCInterfaceType *IT = PT->getInterfaceType();
6925f4a2713aSLionel Sambuc   assert(IT && "Invalid @catch type.");
6926f4a2713aSLionel Sambuc   return GetInterfaceEHType(IT->getDecl(), false);
6927f4a2713aSLionel Sambuc }
6928f4a2713aSLionel Sambuc 
EmitTryStmt(CodeGen::CodeGenFunction & CGF,const ObjCAtTryStmt & S)6929f4a2713aSLionel Sambuc void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
6930f4a2713aSLionel Sambuc                                          const ObjCAtTryStmt &S) {
6931f4a2713aSLionel Sambuc   EmitTryCatchStmt(CGF, S,
6932f4a2713aSLionel Sambuc       cast<llvm::Function>(ObjCTypes.getObjCBeginCatchFn()),
6933f4a2713aSLionel Sambuc       cast<llvm::Function>(ObjCTypes.getObjCEndCatchFn()),
6934f4a2713aSLionel Sambuc       cast<llvm::Function>(ObjCTypes.getExceptionRethrowFn()));
6935f4a2713aSLionel Sambuc }
6936f4a2713aSLionel Sambuc 
6937f4a2713aSLionel Sambuc /// EmitThrowStmt - Generate code for a throw statement.
EmitThrowStmt(CodeGen::CodeGenFunction & CGF,const ObjCAtThrowStmt & S,bool ClearInsertionPoint)6938f4a2713aSLionel Sambuc void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
6939f4a2713aSLionel Sambuc                                            const ObjCAtThrowStmt &S,
6940f4a2713aSLionel Sambuc                                            bool ClearInsertionPoint) {
6941f4a2713aSLionel Sambuc   if (const Expr *ThrowExpr = S.getThrowExpr()) {
6942f4a2713aSLionel Sambuc     llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
6943f4a2713aSLionel Sambuc     Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
6944f4a2713aSLionel Sambuc     CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionThrowFn(), Exception)
6945f4a2713aSLionel Sambuc       .setDoesNotReturn();
6946f4a2713aSLionel Sambuc   } else {
6947f4a2713aSLionel Sambuc     CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionRethrowFn())
6948f4a2713aSLionel Sambuc       .setDoesNotReturn();
6949f4a2713aSLionel Sambuc   }
6950f4a2713aSLionel Sambuc 
6951f4a2713aSLionel Sambuc   CGF.Builder.CreateUnreachable();
6952f4a2713aSLionel Sambuc   if (ClearInsertionPoint)
6953f4a2713aSLionel Sambuc     CGF.Builder.ClearInsertionPoint();
6954f4a2713aSLionel Sambuc }
6955f4a2713aSLionel Sambuc 
6956f4a2713aSLionel Sambuc llvm::Constant *
GetInterfaceEHType(const ObjCInterfaceDecl * ID,bool ForDefinition)6957f4a2713aSLionel Sambuc CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
6958f4a2713aSLionel Sambuc                                            bool ForDefinition) {
6959f4a2713aSLionel Sambuc   llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
6960f4a2713aSLionel Sambuc 
6961f4a2713aSLionel Sambuc   // If we don't need a definition, return the entry if found or check
6962f4a2713aSLionel Sambuc   // if we use an external reference.
6963f4a2713aSLionel Sambuc   if (!ForDefinition) {
6964f4a2713aSLionel Sambuc     if (Entry)
6965f4a2713aSLionel Sambuc       return Entry;
6966f4a2713aSLionel Sambuc 
6967f4a2713aSLionel Sambuc     // If this type (or a super class) has the __objc_exception__
6968f4a2713aSLionel Sambuc     // attribute, emit an external reference.
6969f4a2713aSLionel Sambuc     if (hasObjCExceptionAttribute(CGM.getContext(), ID))
6970f4a2713aSLionel Sambuc       return Entry =
6971f4a2713aSLionel Sambuc           new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
6972f4a2713aSLionel Sambuc                                    llvm::GlobalValue::ExternalLinkage,
6973*0a6a1f1dSLionel Sambuc                                    nullptr,
6974f4a2713aSLionel Sambuc                                    ("OBJC_EHTYPE_$_" +
6975*0a6a1f1dSLionel Sambuc                                     ID->getObjCRuntimeNameAsString()));
6976f4a2713aSLionel Sambuc   }
6977f4a2713aSLionel Sambuc 
6978f4a2713aSLionel Sambuc   // Otherwise we need to either make a new entry or fill in the
6979f4a2713aSLionel Sambuc   // initializer.
6980f4a2713aSLionel Sambuc   assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition");
6981*0a6a1f1dSLionel Sambuc   llvm::SmallString<64> ClassName(getClassSymbolPrefix());
6982*0a6a1f1dSLionel Sambuc   ClassName += ID->getObjCRuntimeNameAsString();
6983f4a2713aSLionel Sambuc   std::string VTableName = "objc_ehtype_vtable";
6984f4a2713aSLionel Sambuc   llvm::GlobalVariable *VTableGV =
6985f4a2713aSLionel Sambuc     CGM.getModule().getGlobalVariable(VTableName);
6986f4a2713aSLionel Sambuc   if (!VTableGV)
6987f4a2713aSLionel Sambuc     VTableGV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy,
6988f4a2713aSLionel Sambuc                                         false,
6989f4a2713aSLionel Sambuc                                         llvm::GlobalValue::ExternalLinkage,
6990*0a6a1f1dSLionel Sambuc                                         nullptr, VTableName);
6991f4a2713aSLionel Sambuc 
6992f4a2713aSLionel Sambuc   llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2);
6993f4a2713aSLionel Sambuc 
6994f4a2713aSLionel Sambuc   llvm::Constant *Values[] = {
6995f4a2713aSLionel Sambuc     llvm::ConstantExpr::getGetElementPtr(VTableGV, VTableIdx),
6996*0a6a1f1dSLionel Sambuc     GetClassName(ID->getObjCRuntimeNameAsString()),
6997*0a6a1f1dSLionel Sambuc     GetClassGlobal(ClassName.str())
6998f4a2713aSLionel Sambuc   };
6999f4a2713aSLionel Sambuc   llvm::Constant *Init =
7000f4a2713aSLionel Sambuc     llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values);
7001f4a2713aSLionel Sambuc 
7002*0a6a1f1dSLionel Sambuc   llvm::GlobalValue::LinkageTypes L = ForDefinition
7003*0a6a1f1dSLionel Sambuc                                           ? llvm::GlobalValue::ExternalLinkage
7004*0a6a1f1dSLionel Sambuc                                           : llvm::GlobalValue::WeakAnyLinkage;
7005f4a2713aSLionel Sambuc   if (Entry) {
7006f4a2713aSLionel Sambuc     Entry->setInitializer(Init);
7007f4a2713aSLionel Sambuc   } else {
7008*0a6a1f1dSLionel Sambuc     llvm::SmallString<64> EHTYPEName("OBJC_EHTYPE_$_");
7009*0a6a1f1dSLionel Sambuc     EHTYPEName += ID->getObjCRuntimeNameAsString();
7010f4a2713aSLionel Sambuc     Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
7011*0a6a1f1dSLionel Sambuc                                      L,
7012f4a2713aSLionel Sambuc                                      Init,
7013*0a6a1f1dSLionel Sambuc                                      EHTYPEName.str());
7014f4a2713aSLionel Sambuc   }
7015*0a6a1f1dSLionel Sambuc   assert(Entry->getLinkage() == L);
7016f4a2713aSLionel Sambuc 
7017f4a2713aSLionel Sambuc   if (ID->getVisibility() == HiddenVisibility)
7018f4a2713aSLionel Sambuc     Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
7019f4a2713aSLionel Sambuc   Entry->setAlignment(CGM.getDataLayout().getABITypeAlignment(
7020f4a2713aSLionel Sambuc       ObjCTypes.EHTypeTy));
7021f4a2713aSLionel Sambuc 
7022*0a6a1f1dSLionel Sambuc   if (ForDefinition)
7023f4a2713aSLionel Sambuc     Entry->setSection("__DATA,__objc_const");
7024*0a6a1f1dSLionel Sambuc   else
7025f4a2713aSLionel Sambuc     Entry->setSection("__DATA,__datacoal_nt,coalesced");
7026f4a2713aSLionel Sambuc 
7027f4a2713aSLionel Sambuc   return Entry;
7028f4a2713aSLionel Sambuc }
7029f4a2713aSLionel Sambuc 
7030f4a2713aSLionel Sambuc /* *** */
7031f4a2713aSLionel Sambuc 
7032f4a2713aSLionel Sambuc CodeGen::CGObjCRuntime *
CreateMacObjCRuntime(CodeGen::CodeGenModule & CGM)7033f4a2713aSLionel Sambuc CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
7034f4a2713aSLionel Sambuc   switch (CGM.getLangOpts().ObjCRuntime.getKind()) {
7035f4a2713aSLionel Sambuc   case ObjCRuntime::FragileMacOSX:
7036f4a2713aSLionel Sambuc   return new CGObjCMac(CGM);
7037f4a2713aSLionel Sambuc 
7038f4a2713aSLionel Sambuc   case ObjCRuntime::MacOSX:
7039f4a2713aSLionel Sambuc   case ObjCRuntime::iOS:
7040f4a2713aSLionel Sambuc     return new CGObjCNonFragileABIMac(CGM);
7041f4a2713aSLionel Sambuc 
7042f4a2713aSLionel Sambuc   case ObjCRuntime::GNUstep:
7043f4a2713aSLionel Sambuc   case ObjCRuntime::GCC:
7044f4a2713aSLionel Sambuc   case ObjCRuntime::ObjFW:
7045f4a2713aSLionel Sambuc     llvm_unreachable("these runtimes are not Mac runtimes");
7046f4a2713aSLionel Sambuc   }
7047f4a2713aSLionel Sambuc   llvm_unreachable("bad runtime");
7048f4a2713aSLionel Sambuc }
7049