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