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