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