xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/CodeGen/CGObjCMac.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
17330f729Sjoerg //===------- CGObjCMac.cpp - Interface to Apple Objective-C Runtime -------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // This provides Objective-C code generation targeting the Apple runtime.
107330f729Sjoerg //
117330f729Sjoerg //===----------------------------------------------------------------------===//
127330f729Sjoerg 
137330f729Sjoerg #include "CGBlocks.h"
147330f729Sjoerg #include "CGCleanup.h"
157330f729Sjoerg #include "CGObjCRuntime.h"
167330f729Sjoerg #include "CGRecordLayout.h"
177330f729Sjoerg #include "CodeGenFunction.h"
187330f729Sjoerg #include "CodeGenModule.h"
197330f729Sjoerg #include "clang/AST/ASTContext.h"
20*e038c9c4Sjoerg #include "clang/AST/Attr.h"
217330f729Sjoerg #include "clang/AST/Decl.h"
227330f729Sjoerg #include "clang/AST/DeclObjC.h"
23*e038c9c4Sjoerg #include "clang/AST/Mangle.h"
247330f729Sjoerg #include "clang/AST/RecordLayout.h"
257330f729Sjoerg #include "clang/AST/StmtObjC.h"
267330f729Sjoerg #include "clang/Basic/CodeGenOptions.h"
277330f729Sjoerg #include "clang/Basic/LangOptions.h"
287330f729Sjoerg #include "clang/CodeGen/CGFunctionInfo.h"
29*e038c9c4Sjoerg #include "clang/CodeGen/ConstantInitBuilder.h"
307330f729Sjoerg #include "llvm/ADT/CachedHashString.h"
317330f729Sjoerg #include "llvm/ADT/DenseSet.h"
327330f729Sjoerg #include "llvm/ADT/SetVector.h"
337330f729Sjoerg #include "llvm/ADT/SmallPtrSet.h"
347330f729Sjoerg #include "llvm/ADT/SmallString.h"
35*e038c9c4Sjoerg #include "llvm/ADT/UniqueVector.h"
367330f729Sjoerg #include "llvm/IR/DataLayout.h"
377330f729Sjoerg #include "llvm/IR/InlineAsm.h"
387330f729Sjoerg #include "llvm/IR/IntrinsicInst.h"
397330f729Sjoerg #include "llvm/IR/LLVMContext.h"
407330f729Sjoerg #include "llvm/IR/Module.h"
417330f729Sjoerg #include "llvm/Support/ScopedPrinter.h"
427330f729Sjoerg #include "llvm/Support/raw_ostream.h"
437330f729Sjoerg #include <cstdio>
447330f729Sjoerg 
457330f729Sjoerg using namespace clang;
467330f729Sjoerg using namespace CodeGen;
477330f729Sjoerg 
487330f729Sjoerg namespace {
497330f729Sjoerg 
507330f729Sjoerg // FIXME: We should find a nicer way to make the labels for metadata, string
517330f729Sjoerg // concatenation is lame.
527330f729Sjoerg 
537330f729Sjoerg class ObjCCommonTypesHelper {
547330f729Sjoerg protected:
557330f729Sjoerg   llvm::LLVMContext &VMContext;
567330f729Sjoerg 
577330f729Sjoerg private:
587330f729Sjoerg   // The types of these functions don't really matter because we
597330f729Sjoerg   // should always bitcast before calling them.
607330f729Sjoerg 
617330f729Sjoerg   /// id objc_msgSend (id, SEL, ...)
627330f729Sjoerg   ///
637330f729Sjoerg   /// The default messenger, used for sends whose ABI is unchanged from
647330f729Sjoerg   /// the all-integer/pointer case.
getMessageSendFn() const657330f729Sjoerg   llvm::FunctionCallee getMessageSendFn() const {
667330f729Sjoerg     // Add the non-lazy-bind attribute, since objc_msgSend is likely to
677330f729Sjoerg     // be called a lot.
687330f729Sjoerg     llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
697330f729Sjoerg     return CGM.CreateRuntimeFunction(
707330f729Sjoerg         llvm::FunctionType::get(ObjectPtrTy, params, true), "objc_msgSend",
717330f729Sjoerg         llvm::AttributeList::get(CGM.getLLVMContext(),
727330f729Sjoerg                                  llvm::AttributeList::FunctionIndex,
737330f729Sjoerg                                  llvm::Attribute::NonLazyBind));
747330f729Sjoerg   }
757330f729Sjoerg 
767330f729Sjoerg   /// void objc_msgSend_stret (id, SEL, ...)
777330f729Sjoerg   ///
787330f729Sjoerg   /// The messenger used when the return value is an aggregate returned
797330f729Sjoerg   /// by indirect reference in the first argument, and therefore the
807330f729Sjoerg   /// self and selector parameters are shifted over by one.
getMessageSendStretFn() const817330f729Sjoerg   llvm::FunctionCallee getMessageSendStretFn() const {
827330f729Sjoerg     llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
837330f729Sjoerg     return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy,
847330f729Sjoerg                                                              params, true),
857330f729Sjoerg                                      "objc_msgSend_stret");
867330f729Sjoerg   }
877330f729Sjoerg 
887330f729Sjoerg   /// [double | long double] objc_msgSend_fpret(id self, SEL op, ...)
897330f729Sjoerg   ///
907330f729Sjoerg   /// The messenger used when the return value is returned on the x87
917330f729Sjoerg   /// floating-point stack; without a special entrypoint, the nil case
927330f729Sjoerg   /// would be unbalanced.
getMessageSendFpretFn() const937330f729Sjoerg   llvm::FunctionCallee getMessageSendFpretFn() const {
947330f729Sjoerg     llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
957330f729Sjoerg     return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.DoubleTy,
967330f729Sjoerg                                                              params, true),
977330f729Sjoerg                                      "objc_msgSend_fpret");
987330f729Sjoerg   }
997330f729Sjoerg 
1007330f729Sjoerg   /// _Complex long double objc_msgSend_fp2ret(id self, SEL op, ...)
1017330f729Sjoerg   ///
1027330f729Sjoerg   /// The messenger used when the return value is returned in two values on the
1037330f729Sjoerg   /// x87 floating point stack; without a special entrypoint, the nil case
1047330f729Sjoerg   /// would be unbalanced. Only used on 64-bit X86.
getMessageSendFp2retFn() const1057330f729Sjoerg   llvm::FunctionCallee getMessageSendFp2retFn() const {
1067330f729Sjoerg     llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
1077330f729Sjoerg     llvm::Type *longDoubleType = llvm::Type::getX86_FP80Ty(VMContext);
1087330f729Sjoerg     llvm::Type *resultType =
1097330f729Sjoerg         llvm::StructType::get(longDoubleType, longDoubleType);
1107330f729Sjoerg 
1117330f729Sjoerg     return CGM.CreateRuntimeFunction(llvm::FunctionType::get(resultType,
1127330f729Sjoerg                                                              params, true),
1137330f729Sjoerg                                      "objc_msgSend_fp2ret");
1147330f729Sjoerg   }
1157330f729Sjoerg 
1167330f729Sjoerg   /// id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
1177330f729Sjoerg   ///
1187330f729Sjoerg   /// The messenger used for super calls, which have different dispatch
1197330f729Sjoerg   /// semantics.  The class passed is the superclass of the current
1207330f729Sjoerg   /// class.
getMessageSendSuperFn() const1217330f729Sjoerg   llvm::FunctionCallee getMessageSendSuperFn() const {
1227330f729Sjoerg     llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
1237330f729Sjoerg     return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
1247330f729Sjoerg                                                              params, true),
1257330f729Sjoerg                                      "objc_msgSendSuper");
1267330f729Sjoerg   }
1277330f729Sjoerg 
1287330f729Sjoerg   /// id objc_msgSendSuper2(struct objc_super *super, SEL op, ...)
1297330f729Sjoerg   ///
1307330f729Sjoerg   /// A slightly different messenger used for super calls.  The class
1317330f729Sjoerg   /// passed is the current class.
getMessageSendSuperFn2() const1327330f729Sjoerg   llvm::FunctionCallee getMessageSendSuperFn2() const {
1337330f729Sjoerg     llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
1347330f729Sjoerg     return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
1357330f729Sjoerg                                                              params, true),
1367330f729Sjoerg                                      "objc_msgSendSuper2");
1377330f729Sjoerg   }
1387330f729Sjoerg 
1397330f729Sjoerg   /// void objc_msgSendSuper_stret(void *stretAddr, struct objc_super *super,
1407330f729Sjoerg   ///                              SEL op, ...)
1417330f729Sjoerg   ///
1427330f729Sjoerg   /// The messenger used for super calls which return an aggregate indirectly.
getMessageSendSuperStretFn() const1437330f729Sjoerg   llvm::FunctionCallee getMessageSendSuperStretFn() const {
1447330f729Sjoerg     llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
1457330f729Sjoerg     return CGM.CreateRuntimeFunction(
1467330f729Sjoerg       llvm::FunctionType::get(CGM.VoidTy, params, true),
1477330f729Sjoerg       "objc_msgSendSuper_stret");
1487330f729Sjoerg   }
1497330f729Sjoerg 
1507330f729Sjoerg   /// void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super,
1517330f729Sjoerg   ///                               SEL op, ...)
1527330f729Sjoerg   ///
1537330f729Sjoerg   /// objc_msgSendSuper_stret with the super2 semantics.
getMessageSendSuperStretFn2() const1547330f729Sjoerg   llvm::FunctionCallee getMessageSendSuperStretFn2() const {
1557330f729Sjoerg     llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
1567330f729Sjoerg     return CGM.CreateRuntimeFunction(
1577330f729Sjoerg       llvm::FunctionType::get(CGM.VoidTy, params, true),
1587330f729Sjoerg       "objc_msgSendSuper2_stret");
1597330f729Sjoerg   }
1607330f729Sjoerg 
getMessageSendSuperFpretFn() const1617330f729Sjoerg   llvm::FunctionCallee getMessageSendSuperFpretFn() const {
1627330f729Sjoerg     // There is no objc_msgSendSuper_fpret? How can that work?
1637330f729Sjoerg     return getMessageSendSuperFn();
1647330f729Sjoerg   }
1657330f729Sjoerg 
getMessageSendSuperFpretFn2() const1667330f729Sjoerg   llvm::FunctionCallee getMessageSendSuperFpretFn2() const {
1677330f729Sjoerg     // There is no objc_msgSendSuper_fpret? How can that work?
1687330f729Sjoerg     return getMessageSendSuperFn2();
1697330f729Sjoerg   }
1707330f729Sjoerg 
1717330f729Sjoerg protected:
1727330f729Sjoerg   CodeGen::CodeGenModule &CGM;
1737330f729Sjoerg 
1747330f729Sjoerg public:
1757330f729Sjoerg   llvm::IntegerType *ShortTy, *IntTy, *LongTy;
1767330f729Sjoerg   llvm::PointerType *Int8PtrTy, *Int8PtrPtrTy;
1777330f729Sjoerg   llvm::Type *IvarOffsetVarTy;
1787330f729Sjoerg 
1797330f729Sjoerg   /// ObjectPtrTy - LLVM type for object handles (typeof(id))
1807330f729Sjoerg   llvm::PointerType *ObjectPtrTy;
1817330f729Sjoerg 
1827330f729Sjoerg   /// PtrObjectPtrTy - LLVM type for id *
1837330f729Sjoerg   llvm::PointerType *PtrObjectPtrTy;
1847330f729Sjoerg 
1857330f729Sjoerg   /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
1867330f729Sjoerg   llvm::PointerType *SelectorPtrTy;
1877330f729Sjoerg 
1887330f729Sjoerg private:
1897330f729Sjoerg   /// ProtocolPtrTy - LLVM type for external protocol handles
1907330f729Sjoerg   /// (typeof(Protocol))
1917330f729Sjoerg   llvm::Type *ExternalProtocolPtrTy;
1927330f729Sjoerg 
1937330f729Sjoerg public:
getExternalProtocolPtrTy()1947330f729Sjoerg   llvm::Type *getExternalProtocolPtrTy() {
1957330f729Sjoerg     if (!ExternalProtocolPtrTy) {
1967330f729Sjoerg       // FIXME: It would be nice to unify this with the opaque type, so that the
1977330f729Sjoerg       // IR comes out a bit cleaner.
1987330f729Sjoerg       CodeGen::CodeGenTypes &Types = CGM.getTypes();
1997330f729Sjoerg       ASTContext &Ctx = CGM.getContext();
2007330f729Sjoerg       llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
2017330f729Sjoerg       ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
2027330f729Sjoerg     }
2037330f729Sjoerg 
2047330f729Sjoerg     return ExternalProtocolPtrTy;
2057330f729Sjoerg   }
2067330f729Sjoerg 
2077330f729Sjoerg   // SuperCTy - clang type for struct objc_super.
2087330f729Sjoerg   QualType SuperCTy;
2097330f729Sjoerg   // SuperPtrCTy - clang type for struct objc_super *.
2107330f729Sjoerg   QualType SuperPtrCTy;
2117330f729Sjoerg 
2127330f729Sjoerg   /// SuperTy - LLVM type for struct objc_super.
2137330f729Sjoerg   llvm::StructType *SuperTy;
2147330f729Sjoerg   /// SuperPtrTy - LLVM type for struct objc_super *.
2157330f729Sjoerg   llvm::PointerType *SuperPtrTy;
2167330f729Sjoerg 
2177330f729Sjoerg   /// PropertyTy - LLVM type for struct objc_property (struct _prop_t
2187330f729Sjoerg   /// in GCC parlance).
2197330f729Sjoerg   llvm::StructType *PropertyTy;
2207330f729Sjoerg 
2217330f729Sjoerg   /// PropertyListTy - LLVM type for struct objc_property_list
2227330f729Sjoerg   /// (_prop_list_t in GCC parlance).
2237330f729Sjoerg   llvm::StructType *PropertyListTy;
2247330f729Sjoerg   /// PropertyListPtrTy - LLVM type for struct objc_property_list*.
2257330f729Sjoerg   llvm::PointerType *PropertyListPtrTy;
2267330f729Sjoerg 
2277330f729Sjoerg   // MethodTy - LLVM type for struct objc_method.
2287330f729Sjoerg   llvm::StructType *MethodTy;
2297330f729Sjoerg 
2307330f729Sjoerg   /// CacheTy - LLVM type for struct objc_cache.
2317330f729Sjoerg   llvm::Type *CacheTy;
2327330f729Sjoerg   /// CachePtrTy - LLVM type for struct objc_cache *.
2337330f729Sjoerg   llvm::PointerType *CachePtrTy;
2347330f729Sjoerg 
getGetPropertyFn()2357330f729Sjoerg   llvm::FunctionCallee getGetPropertyFn() {
2367330f729Sjoerg     CodeGen::CodeGenTypes &Types = CGM.getTypes();
2377330f729Sjoerg     ASTContext &Ctx = CGM.getContext();
2387330f729Sjoerg     // id objc_getProperty (id, SEL, ptrdiff_t, bool)
2397330f729Sjoerg     CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
2407330f729Sjoerg     CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
2417330f729Sjoerg     CanQualType Params[] = {
2427330f729Sjoerg         IdType, SelType,
2437330f729Sjoerg         Ctx.getPointerDiffType()->getCanonicalTypeUnqualified(), Ctx.BoolTy};
2447330f729Sjoerg     llvm::FunctionType *FTy =
2457330f729Sjoerg         Types.GetFunctionType(
2467330f729Sjoerg           Types.arrangeBuiltinFunctionDeclaration(IdType, Params));
2477330f729Sjoerg     return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
2487330f729Sjoerg   }
2497330f729Sjoerg 
getSetPropertyFn()2507330f729Sjoerg   llvm::FunctionCallee getSetPropertyFn() {
2517330f729Sjoerg     CodeGen::CodeGenTypes &Types = CGM.getTypes();
2527330f729Sjoerg     ASTContext &Ctx = CGM.getContext();
2537330f729Sjoerg     // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
2547330f729Sjoerg     CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
2557330f729Sjoerg     CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
2567330f729Sjoerg     CanQualType Params[] = {
2577330f729Sjoerg         IdType,
2587330f729Sjoerg         SelType,
2597330f729Sjoerg         Ctx.getPointerDiffType()->getCanonicalTypeUnqualified(),
2607330f729Sjoerg         IdType,
2617330f729Sjoerg         Ctx.BoolTy,
2627330f729Sjoerg         Ctx.BoolTy};
2637330f729Sjoerg     llvm::FunctionType *FTy =
2647330f729Sjoerg         Types.GetFunctionType(
2657330f729Sjoerg           Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
2667330f729Sjoerg     return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
2677330f729Sjoerg   }
2687330f729Sjoerg 
getOptimizedSetPropertyFn(bool atomic,bool copy)2697330f729Sjoerg   llvm::FunctionCallee getOptimizedSetPropertyFn(bool atomic, bool copy) {
2707330f729Sjoerg     CodeGen::CodeGenTypes &Types = CGM.getTypes();
2717330f729Sjoerg     ASTContext &Ctx = CGM.getContext();
2727330f729Sjoerg     // void objc_setProperty_atomic(id self, SEL _cmd,
2737330f729Sjoerg     //                              id newValue, ptrdiff_t offset);
2747330f729Sjoerg     // void objc_setProperty_nonatomic(id self, SEL _cmd,
2757330f729Sjoerg     //                                 id newValue, ptrdiff_t offset);
2767330f729Sjoerg     // void objc_setProperty_atomic_copy(id self, SEL _cmd,
2777330f729Sjoerg     //                                   id newValue, ptrdiff_t offset);
2787330f729Sjoerg     // void objc_setProperty_nonatomic_copy(id self, SEL _cmd,
2797330f729Sjoerg     //                                      id newValue, ptrdiff_t offset);
2807330f729Sjoerg 
2817330f729Sjoerg     SmallVector<CanQualType,4> Params;
2827330f729Sjoerg     CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
2837330f729Sjoerg     CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
2847330f729Sjoerg     Params.push_back(IdType);
2857330f729Sjoerg     Params.push_back(SelType);
2867330f729Sjoerg     Params.push_back(IdType);
2877330f729Sjoerg     Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
2887330f729Sjoerg     llvm::FunctionType *FTy =
2897330f729Sjoerg         Types.GetFunctionType(
2907330f729Sjoerg           Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
2917330f729Sjoerg     const char *name;
2927330f729Sjoerg     if (atomic && copy)
2937330f729Sjoerg       name = "objc_setProperty_atomic_copy";
2947330f729Sjoerg     else if (atomic && !copy)
2957330f729Sjoerg       name = "objc_setProperty_atomic";
2967330f729Sjoerg     else if (!atomic && copy)
2977330f729Sjoerg       name = "objc_setProperty_nonatomic_copy";
2987330f729Sjoerg     else
2997330f729Sjoerg       name = "objc_setProperty_nonatomic";
3007330f729Sjoerg 
3017330f729Sjoerg     return CGM.CreateRuntimeFunction(FTy, name);
3027330f729Sjoerg   }
3037330f729Sjoerg 
getCopyStructFn()3047330f729Sjoerg   llvm::FunctionCallee getCopyStructFn() {
3057330f729Sjoerg     CodeGen::CodeGenTypes &Types = CGM.getTypes();
3067330f729Sjoerg     ASTContext &Ctx = CGM.getContext();
3077330f729Sjoerg     // void objc_copyStruct (void *, const void *, size_t, bool, bool)
3087330f729Sjoerg     SmallVector<CanQualType,5> Params;
3097330f729Sjoerg     Params.push_back(Ctx.VoidPtrTy);
3107330f729Sjoerg     Params.push_back(Ctx.VoidPtrTy);
3117330f729Sjoerg     Params.push_back(Ctx.getSizeType());
3127330f729Sjoerg     Params.push_back(Ctx.BoolTy);
3137330f729Sjoerg     Params.push_back(Ctx.BoolTy);
3147330f729Sjoerg     llvm::FunctionType *FTy =
3157330f729Sjoerg         Types.GetFunctionType(
3167330f729Sjoerg           Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
3177330f729Sjoerg     return CGM.CreateRuntimeFunction(FTy, "objc_copyStruct");
3187330f729Sjoerg   }
3197330f729Sjoerg 
3207330f729Sjoerg   /// This routine declares and returns address of:
3217330f729Sjoerg   /// void objc_copyCppObjectAtomic(
3227330f729Sjoerg   ///         void *dest, const void *src,
3237330f729Sjoerg   ///         void (*copyHelper) (void *dest, const void *source));
getCppAtomicObjectFunction()3247330f729Sjoerg   llvm::FunctionCallee getCppAtomicObjectFunction() {
3257330f729Sjoerg     CodeGen::CodeGenTypes &Types = CGM.getTypes();
3267330f729Sjoerg     ASTContext &Ctx = CGM.getContext();
3277330f729Sjoerg     /// void objc_copyCppObjectAtomic(void *dest, const void *src, void *helper);
3287330f729Sjoerg     SmallVector<CanQualType,3> Params;
3297330f729Sjoerg     Params.push_back(Ctx.VoidPtrTy);
3307330f729Sjoerg     Params.push_back(Ctx.VoidPtrTy);
3317330f729Sjoerg     Params.push_back(Ctx.VoidPtrTy);
3327330f729Sjoerg     llvm::FunctionType *FTy =
3337330f729Sjoerg         Types.GetFunctionType(
3347330f729Sjoerg           Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
3357330f729Sjoerg     return CGM.CreateRuntimeFunction(FTy, "objc_copyCppObjectAtomic");
3367330f729Sjoerg   }
3377330f729Sjoerg 
getEnumerationMutationFn()3387330f729Sjoerg   llvm::FunctionCallee getEnumerationMutationFn() {
3397330f729Sjoerg     CodeGen::CodeGenTypes &Types = CGM.getTypes();
3407330f729Sjoerg     ASTContext &Ctx = CGM.getContext();
3417330f729Sjoerg     // void objc_enumerationMutation (id)
3427330f729Sjoerg     SmallVector<CanQualType,1> Params;
3437330f729Sjoerg     Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType()));
3447330f729Sjoerg     llvm::FunctionType *FTy =
3457330f729Sjoerg         Types.GetFunctionType(
3467330f729Sjoerg           Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
3477330f729Sjoerg     return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
3487330f729Sjoerg   }
3497330f729Sjoerg 
getLookUpClassFn()3507330f729Sjoerg   llvm::FunctionCallee getLookUpClassFn() {
3517330f729Sjoerg     CodeGen::CodeGenTypes &Types = CGM.getTypes();
3527330f729Sjoerg     ASTContext &Ctx = CGM.getContext();
3537330f729Sjoerg     // Class objc_lookUpClass (const char *)
3547330f729Sjoerg     SmallVector<CanQualType,1> Params;
3557330f729Sjoerg     Params.push_back(
3567330f729Sjoerg       Ctx.getCanonicalType(Ctx.getPointerType(Ctx.CharTy.withConst())));
3577330f729Sjoerg     llvm::FunctionType *FTy =
3587330f729Sjoerg         Types.GetFunctionType(Types.arrangeBuiltinFunctionDeclaration(
3597330f729Sjoerg                                 Ctx.getCanonicalType(Ctx.getObjCClassType()),
3607330f729Sjoerg                                 Params));
3617330f729Sjoerg     return CGM.CreateRuntimeFunction(FTy, "objc_lookUpClass");
3627330f729Sjoerg   }
3637330f729Sjoerg 
3647330f729Sjoerg   /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
getGcReadWeakFn()3657330f729Sjoerg   llvm::FunctionCallee getGcReadWeakFn() {
3667330f729Sjoerg     // id objc_read_weak (id *)
3677330f729Sjoerg     llvm::Type *args[] = { ObjectPtrTy->getPointerTo() };
3687330f729Sjoerg     llvm::FunctionType *FTy =
3697330f729Sjoerg       llvm::FunctionType::get(ObjectPtrTy, args, false);
3707330f729Sjoerg     return CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
3717330f729Sjoerg   }
3727330f729Sjoerg 
3737330f729Sjoerg   /// GcAssignWeakFn -- LLVM objc_assign_weak function.
getGcAssignWeakFn()3747330f729Sjoerg   llvm::FunctionCallee getGcAssignWeakFn() {
3757330f729Sjoerg     // id objc_assign_weak (id, id *)
3767330f729Sjoerg     llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
3777330f729Sjoerg     llvm::FunctionType *FTy =
3787330f729Sjoerg       llvm::FunctionType::get(ObjectPtrTy, args, false);
3797330f729Sjoerg     return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
3807330f729Sjoerg   }
3817330f729Sjoerg 
3827330f729Sjoerg   /// GcAssignGlobalFn -- LLVM objc_assign_global function.
getGcAssignGlobalFn()3837330f729Sjoerg   llvm::FunctionCallee getGcAssignGlobalFn() {
3847330f729Sjoerg     // id objc_assign_global(id, id *)
3857330f729Sjoerg     llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
3867330f729Sjoerg     llvm::FunctionType *FTy =
3877330f729Sjoerg       llvm::FunctionType::get(ObjectPtrTy, args, false);
3887330f729Sjoerg     return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
3897330f729Sjoerg   }
3907330f729Sjoerg 
3917330f729Sjoerg   /// GcAssignThreadLocalFn -- LLVM objc_assign_threadlocal function.
getGcAssignThreadLocalFn()3927330f729Sjoerg   llvm::FunctionCallee getGcAssignThreadLocalFn() {
3937330f729Sjoerg     // id objc_assign_threadlocal(id src, id * dest)
3947330f729Sjoerg     llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
3957330f729Sjoerg     llvm::FunctionType *FTy =
3967330f729Sjoerg       llvm::FunctionType::get(ObjectPtrTy, args, false);
3977330f729Sjoerg     return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal");
3987330f729Sjoerg   }
3997330f729Sjoerg 
4007330f729Sjoerg   /// GcAssignIvarFn -- LLVM objc_assign_ivar function.
getGcAssignIvarFn()4017330f729Sjoerg   llvm::FunctionCallee getGcAssignIvarFn() {
4027330f729Sjoerg     // id objc_assign_ivar(id, id *, ptrdiff_t)
4037330f729Sjoerg     llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo(),
4047330f729Sjoerg                            CGM.PtrDiffTy };
4057330f729Sjoerg     llvm::FunctionType *FTy =
4067330f729Sjoerg       llvm::FunctionType::get(ObjectPtrTy, args, false);
4077330f729Sjoerg     return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
4087330f729Sjoerg   }
4097330f729Sjoerg 
4107330f729Sjoerg   /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function.
GcMemmoveCollectableFn()4117330f729Sjoerg   llvm::FunctionCallee GcMemmoveCollectableFn() {
4127330f729Sjoerg     // void *objc_memmove_collectable(void *dst, const void *src, size_t size)
4137330f729Sjoerg     llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, LongTy };
4147330f729Sjoerg     llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, args, false);
4157330f729Sjoerg     return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable");
4167330f729Sjoerg   }
4177330f729Sjoerg 
4187330f729Sjoerg   /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
getGcAssignStrongCastFn()4197330f729Sjoerg   llvm::FunctionCallee getGcAssignStrongCastFn() {
4207330f729Sjoerg     // id objc_assign_strongCast(id, id *)
4217330f729Sjoerg     llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
4227330f729Sjoerg     llvm::FunctionType *FTy =
4237330f729Sjoerg       llvm::FunctionType::get(ObjectPtrTy, args, false);
4247330f729Sjoerg     return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
4257330f729Sjoerg   }
4267330f729Sjoerg 
4277330f729Sjoerg   /// ExceptionThrowFn - LLVM objc_exception_throw function.
getExceptionThrowFn()4287330f729Sjoerg   llvm::FunctionCallee getExceptionThrowFn() {
4297330f729Sjoerg     // void objc_exception_throw(id)
4307330f729Sjoerg     llvm::Type *args[] = { ObjectPtrTy };
4317330f729Sjoerg     llvm::FunctionType *FTy =
4327330f729Sjoerg       llvm::FunctionType::get(CGM.VoidTy, args, false);
4337330f729Sjoerg     return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
4347330f729Sjoerg   }
4357330f729Sjoerg 
4367330f729Sjoerg   /// ExceptionRethrowFn - LLVM objc_exception_rethrow function.
getExceptionRethrowFn()4377330f729Sjoerg   llvm::FunctionCallee getExceptionRethrowFn() {
4387330f729Sjoerg     // void objc_exception_rethrow(void)
4397330f729Sjoerg     llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false);
4407330f729Sjoerg     return CGM.CreateRuntimeFunction(FTy, "objc_exception_rethrow");
4417330f729Sjoerg   }
4427330f729Sjoerg 
4437330f729Sjoerg   /// SyncEnterFn - LLVM object_sync_enter function.
getSyncEnterFn()4447330f729Sjoerg   llvm::FunctionCallee getSyncEnterFn() {
4457330f729Sjoerg     // int objc_sync_enter (id)
4467330f729Sjoerg     llvm::Type *args[] = { ObjectPtrTy };
4477330f729Sjoerg     llvm::FunctionType *FTy =
4487330f729Sjoerg       llvm::FunctionType::get(CGM.IntTy, args, false);
4497330f729Sjoerg     return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
4507330f729Sjoerg   }
4517330f729Sjoerg 
4527330f729Sjoerg   /// SyncExitFn - LLVM object_sync_exit function.
getSyncExitFn()4537330f729Sjoerg   llvm::FunctionCallee getSyncExitFn() {
4547330f729Sjoerg     // int objc_sync_exit (id)
4557330f729Sjoerg     llvm::Type *args[] = { ObjectPtrTy };
4567330f729Sjoerg     llvm::FunctionType *FTy =
4577330f729Sjoerg       llvm::FunctionType::get(CGM.IntTy, args, false);
4587330f729Sjoerg     return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
4597330f729Sjoerg   }
4607330f729Sjoerg 
getSendFn(bool IsSuper) const4617330f729Sjoerg   llvm::FunctionCallee getSendFn(bool IsSuper) const {
4627330f729Sjoerg     return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
4637330f729Sjoerg   }
4647330f729Sjoerg 
getSendFn2(bool IsSuper) const4657330f729Sjoerg   llvm::FunctionCallee getSendFn2(bool IsSuper) const {
4667330f729Sjoerg     return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
4677330f729Sjoerg   }
4687330f729Sjoerg 
getSendStretFn(bool IsSuper) const4697330f729Sjoerg   llvm::FunctionCallee getSendStretFn(bool IsSuper) const {
4707330f729Sjoerg     return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
4717330f729Sjoerg   }
4727330f729Sjoerg 
getSendStretFn2(bool IsSuper) const4737330f729Sjoerg   llvm::FunctionCallee getSendStretFn2(bool IsSuper) const {
4747330f729Sjoerg     return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
4757330f729Sjoerg   }
4767330f729Sjoerg 
getSendFpretFn(bool IsSuper) const4777330f729Sjoerg   llvm::FunctionCallee getSendFpretFn(bool IsSuper) const {
4787330f729Sjoerg     return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
4797330f729Sjoerg   }
4807330f729Sjoerg 
getSendFpretFn2(bool IsSuper) const4817330f729Sjoerg   llvm::FunctionCallee getSendFpretFn2(bool IsSuper) const {
4827330f729Sjoerg     return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
4837330f729Sjoerg   }
4847330f729Sjoerg 
getSendFp2retFn(bool IsSuper) const4857330f729Sjoerg   llvm::FunctionCallee getSendFp2retFn(bool IsSuper) const {
4867330f729Sjoerg     return IsSuper ? getMessageSendSuperFn() : getMessageSendFp2retFn();
4877330f729Sjoerg   }
4887330f729Sjoerg 
getSendFp2RetFn2(bool IsSuper) const4897330f729Sjoerg   llvm::FunctionCallee getSendFp2RetFn2(bool IsSuper) const {
4907330f729Sjoerg     return IsSuper ? getMessageSendSuperFn2() : getMessageSendFp2retFn();
4917330f729Sjoerg   }
4927330f729Sjoerg 
4937330f729Sjoerg   ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
4947330f729Sjoerg };
4957330f729Sjoerg 
4967330f729Sjoerg /// ObjCTypesHelper - Helper class that encapsulates lazy
4977330f729Sjoerg /// construction of varies types used during ObjC generation.
4987330f729Sjoerg class ObjCTypesHelper : public ObjCCommonTypesHelper {
4997330f729Sjoerg public:
5007330f729Sjoerg   /// SymtabTy - LLVM type for struct objc_symtab.
5017330f729Sjoerg   llvm::StructType *SymtabTy;
5027330f729Sjoerg   /// SymtabPtrTy - LLVM type for struct objc_symtab *.
5037330f729Sjoerg   llvm::PointerType *SymtabPtrTy;
5047330f729Sjoerg   /// ModuleTy - LLVM type for struct objc_module.
5057330f729Sjoerg   llvm::StructType *ModuleTy;
5067330f729Sjoerg 
5077330f729Sjoerg   /// ProtocolTy - LLVM type for struct objc_protocol.
5087330f729Sjoerg   llvm::StructType *ProtocolTy;
5097330f729Sjoerg   /// ProtocolPtrTy - LLVM type for struct objc_protocol *.
5107330f729Sjoerg   llvm::PointerType *ProtocolPtrTy;
5117330f729Sjoerg   /// ProtocolExtensionTy - LLVM type for struct
5127330f729Sjoerg   /// objc_protocol_extension.
5137330f729Sjoerg   llvm::StructType *ProtocolExtensionTy;
5147330f729Sjoerg   /// ProtocolExtensionTy - LLVM type for struct
5157330f729Sjoerg   /// objc_protocol_extension *.
5167330f729Sjoerg   llvm::PointerType *ProtocolExtensionPtrTy;
5177330f729Sjoerg   /// MethodDescriptionTy - LLVM type for struct
5187330f729Sjoerg   /// objc_method_description.
5197330f729Sjoerg   llvm::StructType *MethodDescriptionTy;
5207330f729Sjoerg   /// MethodDescriptionListTy - LLVM type for struct
5217330f729Sjoerg   /// objc_method_description_list.
5227330f729Sjoerg   llvm::StructType *MethodDescriptionListTy;
5237330f729Sjoerg   /// MethodDescriptionListPtrTy - LLVM type for struct
5247330f729Sjoerg   /// objc_method_description_list *.
5257330f729Sjoerg   llvm::PointerType *MethodDescriptionListPtrTy;
5267330f729Sjoerg   /// ProtocolListTy - LLVM type for struct objc_property_list.
5277330f729Sjoerg   llvm::StructType *ProtocolListTy;
5287330f729Sjoerg   /// ProtocolListPtrTy - LLVM type for struct objc_property_list*.
5297330f729Sjoerg   llvm::PointerType *ProtocolListPtrTy;
5307330f729Sjoerg   /// CategoryTy - LLVM type for struct objc_category.
5317330f729Sjoerg   llvm::StructType *CategoryTy;
5327330f729Sjoerg   /// ClassTy - LLVM type for struct objc_class.
5337330f729Sjoerg   llvm::StructType *ClassTy;
5347330f729Sjoerg   /// ClassPtrTy - LLVM type for struct objc_class *.
5357330f729Sjoerg   llvm::PointerType *ClassPtrTy;
5367330f729Sjoerg   /// ClassExtensionTy - LLVM type for struct objc_class_ext.
5377330f729Sjoerg   llvm::StructType *ClassExtensionTy;
5387330f729Sjoerg   /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *.
5397330f729Sjoerg   llvm::PointerType *ClassExtensionPtrTy;
5407330f729Sjoerg   // IvarTy - LLVM type for struct objc_ivar.
5417330f729Sjoerg   llvm::StructType *IvarTy;
5427330f729Sjoerg   /// IvarListTy - LLVM type for struct objc_ivar_list.
5437330f729Sjoerg   llvm::StructType *IvarListTy;
5447330f729Sjoerg   /// IvarListPtrTy - LLVM type for struct objc_ivar_list *.
5457330f729Sjoerg   llvm::PointerType *IvarListPtrTy;
5467330f729Sjoerg   /// MethodListTy - LLVM type for struct objc_method_list.
5477330f729Sjoerg   llvm::StructType *MethodListTy;
5487330f729Sjoerg   /// MethodListPtrTy - LLVM type for struct objc_method_list *.
5497330f729Sjoerg   llvm::PointerType *MethodListPtrTy;
5507330f729Sjoerg 
5517330f729Sjoerg   /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
5527330f729Sjoerg   llvm::StructType *ExceptionDataTy;
5537330f729Sjoerg 
5547330f729Sjoerg   /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
getExceptionTryEnterFn()5557330f729Sjoerg   llvm::FunctionCallee getExceptionTryEnterFn() {
5567330f729Sjoerg     llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
5577330f729Sjoerg     return CGM.CreateRuntimeFunction(
5587330f729Sjoerg       llvm::FunctionType::get(CGM.VoidTy, params, false),
5597330f729Sjoerg       "objc_exception_try_enter");
5607330f729Sjoerg   }
5617330f729Sjoerg 
5627330f729Sjoerg   /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
getExceptionTryExitFn()5637330f729Sjoerg   llvm::FunctionCallee getExceptionTryExitFn() {
5647330f729Sjoerg     llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
5657330f729Sjoerg     return CGM.CreateRuntimeFunction(
5667330f729Sjoerg       llvm::FunctionType::get(CGM.VoidTy, params, false),
5677330f729Sjoerg       "objc_exception_try_exit");
5687330f729Sjoerg   }
5697330f729Sjoerg 
5707330f729Sjoerg   /// ExceptionExtractFn - LLVM objc_exception_extract function.
getExceptionExtractFn()5717330f729Sjoerg   llvm::FunctionCallee getExceptionExtractFn() {
5727330f729Sjoerg     llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
5737330f729Sjoerg     return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
5747330f729Sjoerg                                                              params, false),
5757330f729Sjoerg                                      "objc_exception_extract");
5767330f729Sjoerg   }
5777330f729Sjoerg 
5787330f729Sjoerg   /// ExceptionMatchFn - LLVM objc_exception_match function.
getExceptionMatchFn()5797330f729Sjoerg   llvm::FunctionCallee getExceptionMatchFn() {
5807330f729Sjoerg     llvm::Type *params[] = { ClassPtrTy, ObjectPtrTy };
5817330f729Sjoerg     return CGM.CreateRuntimeFunction(
5827330f729Sjoerg       llvm::FunctionType::get(CGM.Int32Ty, params, false),
5837330f729Sjoerg       "objc_exception_match");
5847330f729Sjoerg   }
5857330f729Sjoerg 
5867330f729Sjoerg   /// SetJmpFn - LLVM _setjmp function.
getSetJmpFn()5877330f729Sjoerg   llvm::FunctionCallee getSetJmpFn() {
5887330f729Sjoerg     // This is specifically the prototype for x86.
5897330f729Sjoerg     llvm::Type *params[] = { CGM.Int32Ty->getPointerTo() };
5907330f729Sjoerg     return CGM.CreateRuntimeFunction(
5917330f729Sjoerg         llvm::FunctionType::get(CGM.Int32Ty, params, false), "_setjmp",
5927330f729Sjoerg         llvm::AttributeList::get(CGM.getLLVMContext(),
5937330f729Sjoerg                                  llvm::AttributeList::FunctionIndex,
5947330f729Sjoerg                                  llvm::Attribute::NonLazyBind));
5957330f729Sjoerg   }
5967330f729Sjoerg 
5977330f729Sjoerg public:
5987330f729Sjoerg   ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
5997330f729Sjoerg };
6007330f729Sjoerg 
6017330f729Sjoerg /// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
6027330f729Sjoerg /// modern abi
6037330f729Sjoerg class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
6047330f729Sjoerg public:
6057330f729Sjoerg   // MethodListnfABITy - LLVM for struct _method_list_t
6067330f729Sjoerg   llvm::StructType *MethodListnfABITy;
6077330f729Sjoerg 
6087330f729Sjoerg   // MethodListnfABIPtrTy - LLVM for struct _method_list_t*
6097330f729Sjoerg   llvm::PointerType *MethodListnfABIPtrTy;
6107330f729Sjoerg 
6117330f729Sjoerg   // ProtocolnfABITy = LLVM for struct _protocol_t
6127330f729Sjoerg   llvm::StructType *ProtocolnfABITy;
6137330f729Sjoerg 
6147330f729Sjoerg   // ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
6157330f729Sjoerg   llvm::PointerType *ProtocolnfABIPtrTy;
6167330f729Sjoerg 
6177330f729Sjoerg   // ProtocolListnfABITy - LLVM for struct _objc_protocol_list
6187330f729Sjoerg   llvm::StructType *ProtocolListnfABITy;
6197330f729Sjoerg 
6207330f729Sjoerg   // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
6217330f729Sjoerg   llvm::PointerType *ProtocolListnfABIPtrTy;
6227330f729Sjoerg 
6237330f729Sjoerg   // ClassnfABITy - LLVM for struct _class_t
6247330f729Sjoerg   llvm::StructType *ClassnfABITy;
6257330f729Sjoerg 
6267330f729Sjoerg   // ClassnfABIPtrTy - LLVM for struct _class_t*
6277330f729Sjoerg   llvm::PointerType *ClassnfABIPtrTy;
6287330f729Sjoerg 
6297330f729Sjoerg   // IvarnfABITy - LLVM for struct _ivar_t
6307330f729Sjoerg   llvm::StructType *IvarnfABITy;
6317330f729Sjoerg 
6327330f729Sjoerg   // IvarListnfABITy - LLVM for struct _ivar_list_t
6337330f729Sjoerg   llvm::StructType *IvarListnfABITy;
6347330f729Sjoerg 
6357330f729Sjoerg   // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
6367330f729Sjoerg   llvm::PointerType *IvarListnfABIPtrTy;
6377330f729Sjoerg 
6387330f729Sjoerg   // ClassRonfABITy - LLVM for struct _class_ro_t
6397330f729Sjoerg   llvm::StructType *ClassRonfABITy;
6407330f729Sjoerg 
6417330f729Sjoerg   // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
6427330f729Sjoerg   llvm::PointerType *ImpnfABITy;
6437330f729Sjoerg 
6447330f729Sjoerg   // CategorynfABITy - LLVM for struct _category_t
6457330f729Sjoerg   llvm::StructType *CategorynfABITy;
6467330f729Sjoerg 
6477330f729Sjoerg   // New types for nonfragile abi messaging.
6487330f729Sjoerg 
6497330f729Sjoerg   // MessageRefTy - LLVM for:
6507330f729Sjoerg   // struct _message_ref_t {
6517330f729Sjoerg   //   IMP messenger;
6527330f729Sjoerg   //   SEL name;
6537330f729Sjoerg   // };
6547330f729Sjoerg   llvm::StructType *MessageRefTy;
6557330f729Sjoerg   // MessageRefCTy - clang type for struct _message_ref_t
6567330f729Sjoerg   QualType MessageRefCTy;
6577330f729Sjoerg 
6587330f729Sjoerg   // MessageRefPtrTy - LLVM for struct _message_ref_t*
6597330f729Sjoerg   llvm::Type *MessageRefPtrTy;
6607330f729Sjoerg   // MessageRefCPtrTy - clang type for struct _message_ref_t*
6617330f729Sjoerg   QualType MessageRefCPtrTy;
6627330f729Sjoerg 
6637330f729Sjoerg   // SuperMessageRefTy - LLVM for:
6647330f729Sjoerg   // struct _super_message_ref_t {
6657330f729Sjoerg   //   SUPER_IMP messenger;
6667330f729Sjoerg   //   SEL name;
6677330f729Sjoerg   // };
6687330f729Sjoerg   llvm::StructType *SuperMessageRefTy;
6697330f729Sjoerg 
6707330f729Sjoerg   // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
6717330f729Sjoerg   llvm::PointerType *SuperMessageRefPtrTy;
6727330f729Sjoerg 
getMessageSendFixupFn()6737330f729Sjoerg   llvm::FunctionCallee getMessageSendFixupFn() {
6747330f729Sjoerg     // id objc_msgSend_fixup(id, struct message_ref_t*, ...)
6757330f729Sjoerg     llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
6767330f729Sjoerg     return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
6777330f729Sjoerg                                                              params, true),
6787330f729Sjoerg                                      "objc_msgSend_fixup");
6797330f729Sjoerg   }
6807330f729Sjoerg 
getMessageSendFpretFixupFn()6817330f729Sjoerg   llvm::FunctionCallee getMessageSendFpretFixupFn() {
6827330f729Sjoerg     // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...)
6837330f729Sjoerg     llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
6847330f729Sjoerg     return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
6857330f729Sjoerg                                                              params, true),
6867330f729Sjoerg                                      "objc_msgSend_fpret_fixup");
6877330f729Sjoerg   }
6887330f729Sjoerg 
getMessageSendStretFixupFn()6897330f729Sjoerg   llvm::FunctionCallee getMessageSendStretFixupFn() {
6907330f729Sjoerg     // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...)
6917330f729Sjoerg     llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
6927330f729Sjoerg     return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
6937330f729Sjoerg                                                              params, true),
6947330f729Sjoerg                                      "objc_msgSend_stret_fixup");
6957330f729Sjoerg   }
6967330f729Sjoerg 
getMessageSendSuper2FixupFn()6977330f729Sjoerg   llvm::FunctionCallee getMessageSendSuper2FixupFn() {
6987330f729Sjoerg     // id objc_msgSendSuper2_fixup (struct objc_super *,
6997330f729Sjoerg     //                              struct _super_message_ref_t*, ...)
7007330f729Sjoerg     llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
7017330f729Sjoerg     return  CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
7027330f729Sjoerg                                                               params, true),
7037330f729Sjoerg                                       "objc_msgSendSuper2_fixup");
7047330f729Sjoerg   }
7057330f729Sjoerg 
getMessageSendSuper2StretFixupFn()7067330f729Sjoerg   llvm::FunctionCallee getMessageSendSuper2StretFixupFn() {
7077330f729Sjoerg     // id objc_msgSendSuper2_stret_fixup(struct objc_super *,
7087330f729Sjoerg     //                                   struct _super_message_ref_t*, ...)
7097330f729Sjoerg     llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
7107330f729Sjoerg     return  CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
7117330f729Sjoerg                                                               params, true),
7127330f729Sjoerg                                       "objc_msgSendSuper2_stret_fixup");
7137330f729Sjoerg   }
7147330f729Sjoerg 
getObjCEndCatchFn()7157330f729Sjoerg   llvm::FunctionCallee getObjCEndCatchFn() {
7167330f729Sjoerg     return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy, false),
7177330f729Sjoerg                                      "objc_end_catch");
7187330f729Sjoerg   }
7197330f729Sjoerg 
getObjCBeginCatchFn()7207330f729Sjoerg   llvm::FunctionCallee getObjCBeginCatchFn() {
7217330f729Sjoerg     llvm::Type *params[] = { Int8PtrTy };
7227330f729Sjoerg     return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy,
7237330f729Sjoerg                                                              params, false),
7247330f729Sjoerg                                      "objc_begin_catch");
7257330f729Sjoerg   }
7267330f729Sjoerg 
7277330f729Sjoerg   /// Class objc_loadClassref (void *)
7287330f729Sjoerg   ///
7297330f729Sjoerg   /// Loads from a classref. For Objective-C stub classes, this invokes the
7307330f729Sjoerg   /// initialization callback stored inside the stub. For all other classes
7317330f729Sjoerg   /// this simply dereferences the pointer.
getLoadClassrefFn() const7327330f729Sjoerg   llvm::FunctionCallee getLoadClassrefFn() const {
7337330f729Sjoerg     // Add the non-lazy-bind attribute, since objc_loadClassref is likely to
7347330f729Sjoerg     // be called a lot.
7357330f729Sjoerg     //
7367330f729Sjoerg     // Also it is safe to make it readnone, since we never load or store the
7377330f729Sjoerg     // classref except by calling this function.
7387330f729Sjoerg     llvm::Type *params[] = { Int8PtrPtrTy };
7397330f729Sjoerg     llvm::FunctionCallee F = CGM.CreateRuntimeFunction(
7407330f729Sjoerg         llvm::FunctionType::get(ClassnfABIPtrTy, params, false),
7417330f729Sjoerg         "objc_loadClassref",
7427330f729Sjoerg         llvm::AttributeList::get(CGM.getLLVMContext(),
7437330f729Sjoerg                                  llvm::AttributeList::FunctionIndex,
7447330f729Sjoerg                                  {llvm::Attribute::NonLazyBind,
7457330f729Sjoerg                                   llvm::Attribute::ReadNone,
7467330f729Sjoerg                                   llvm::Attribute::NoUnwind}));
7477330f729Sjoerg     if (!CGM.getTriple().isOSBinFormatCOFF())
7487330f729Sjoerg       cast<llvm::Function>(F.getCallee())->setLinkage(
7497330f729Sjoerg         llvm::Function::ExternalWeakLinkage);
7507330f729Sjoerg 
7517330f729Sjoerg     return F;
7527330f729Sjoerg   }
7537330f729Sjoerg 
7547330f729Sjoerg   llvm::StructType *EHTypeTy;
7557330f729Sjoerg   llvm::Type *EHTypePtrTy;
7567330f729Sjoerg 
7577330f729Sjoerg   ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
7587330f729Sjoerg };
7597330f729Sjoerg 
7607330f729Sjoerg enum class ObjCLabelType {
7617330f729Sjoerg   ClassName,
7627330f729Sjoerg   MethodVarName,
7637330f729Sjoerg   MethodVarType,
7647330f729Sjoerg   PropertyName,
7657330f729Sjoerg };
7667330f729Sjoerg 
7677330f729Sjoerg class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
7687330f729Sjoerg public:
7697330f729Sjoerg   class SKIP_SCAN {
7707330f729Sjoerg   public:
7717330f729Sjoerg     unsigned skip;
7727330f729Sjoerg     unsigned scan;
SKIP_SCAN(unsigned _skip=0,unsigned _scan=0)7737330f729Sjoerg     SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0)
7747330f729Sjoerg       : skip(_skip), scan(_scan) {}
7757330f729Sjoerg   };
7767330f729Sjoerg 
7777330f729Sjoerg   /// opcode for captured block variables layout 'instructions'.
7787330f729Sjoerg   /// In the following descriptions, 'I' is the value of the immediate field.
7797330f729Sjoerg   /// (field following the opcode).
7807330f729Sjoerg   ///
7817330f729Sjoerg   enum BLOCK_LAYOUT_OPCODE {
7827330f729Sjoerg     /// An operator which affects how the following layout should be
7837330f729Sjoerg     /// interpreted.
7847330f729Sjoerg     ///   I == 0: Halt interpretation and treat everything else as
7857330f729Sjoerg     ///           a non-pointer.  Note that this instruction is equal
7867330f729Sjoerg     ///           to '\0'.
7877330f729Sjoerg     ///   I != 0: Currently unused.
7887330f729Sjoerg     BLOCK_LAYOUT_OPERATOR            = 0,
7897330f729Sjoerg 
7907330f729Sjoerg     /// The next I+1 bytes do not contain a value of object pointer type.
7917330f729Sjoerg     /// Note that this can leave the stream unaligned, meaning that
7927330f729Sjoerg     /// subsequent word-size instructions do not begin at a multiple of
7937330f729Sjoerg     /// the pointer size.
7947330f729Sjoerg     BLOCK_LAYOUT_NON_OBJECT_BYTES    = 1,
7957330f729Sjoerg 
7967330f729Sjoerg     /// The next I+1 words do not contain a value of object pointer type.
7977330f729Sjoerg     /// This is simply an optimized version of BLOCK_LAYOUT_BYTES for
7987330f729Sjoerg     /// when the required skip quantity is a multiple of the pointer size.
7997330f729Sjoerg     BLOCK_LAYOUT_NON_OBJECT_WORDS    = 2,
8007330f729Sjoerg 
8017330f729Sjoerg     /// The next I+1 words are __strong pointers to Objective-C
8027330f729Sjoerg     /// objects or blocks.
8037330f729Sjoerg     BLOCK_LAYOUT_STRONG              = 3,
8047330f729Sjoerg 
8057330f729Sjoerg     /// The next I+1 words are pointers to __block variables.
8067330f729Sjoerg     BLOCK_LAYOUT_BYREF               = 4,
8077330f729Sjoerg 
8087330f729Sjoerg     /// The next I+1 words are __weak pointers to Objective-C
8097330f729Sjoerg     /// objects or blocks.
8107330f729Sjoerg     BLOCK_LAYOUT_WEAK                = 5,
8117330f729Sjoerg 
8127330f729Sjoerg     /// The next I+1 words are __unsafe_unretained pointers to
8137330f729Sjoerg     /// Objective-C objects or blocks.
8147330f729Sjoerg     BLOCK_LAYOUT_UNRETAINED          = 6
8157330f729Sjoerg 
8167330f729Sjoerg     /// The next I+1 words are block or object pointers with some
8177330f729Sjoerg     /// as-yet-unspecified ownership semantics.  If we add more
8187330f729Sjoerg     /// flavors of ownership semantics, values will be taken from
8197330f729Sjoerg     /// this range.
8207330f729Sjoerg     ///
8217330f729Sjoerg     /// This is included so that older tools can at least continue
8227330f729Sjoerg     /// processing the layout past such things.
8237330f729Sjoerg     //BLOCK_LAYOUT_OWNERSHIP_UNKNOWN = 7..10,
8247330f729Sjoerg 
8257330f729Sjoerg     /// All other opcodes are reserved.  Halt interpretation and
8267330f729Sjoerg     /// treat everything else as opaque.
8277330f729Sjoerg   };
8287330f729Sjoerg 
8297330f729Sjoerg   class RUN_SKIP {
8307330f729Sjoerg   public:
8317330f729Sjoerg     enum BLOCK_LAYOUT_OPCODE opcode;
8327330f729Sjoerg     CharUnits block_var_bytepos;
8337330f729Sjoerg     CharUnits block_var_size;
RUN_SKIP(enum BLOCK_LAYOUT_OPCODE Opcode=BLOCK_LAYOUT_OPERATOR,CharUnits BytePos=CharUnits::Zero (),CharUnits Size=CharUnits::Zero ())8347330f729Sjoerg     RUN_SKIP(enum BLOCK_LAYOUT_OPCODE Opcode = BLOCK_LAYOUT_OPERATOR,
8357330f729Sjoerg              CharUnits BytePos = CharUnits::Zero(),
8367330f729Sjoerg              CharUnits Size = CharUnits::Zero())
8377330f729Sjoerg     : opcode(Opcode), block_var_bytepos(BytePos),  block_var_size(Size) {}
8387330f729Sjoerg 
8397330f729Sjoerg     // Allow sorting based on byte pos.
operator <(const RUN_SKIP & b) const8407330f729Sjoerg     bool operator<(const RUN_SKIP &b) const {
8417330f729Sjoerg       return block_var_bytepos < b.block_var_bytepos;
8427330f729Sjoerg     }
8437330f729Sjoerg   };
8447330f729Sjoerg 
8457330f729Sjoerg protected:
8467330f729Sjoerg   llvm::LLVMContext &VMContext;
8477330f729Sjoerg   // FIXME! May not be needing this after all.
8487330f729Sjoerg   unsigned ObjCABI;
8497330f729Sjoerg 
8507330f729Sjoerg   // arc/mrr layout of captured block literal variables.
8517330f729Sjoerg   SmallVector<RUN_SKIP, 16> RunSkipBlockVars;
8527330f729Sjoerg 
8537330f729Sjoerg   /// LazySymbols - Symbols to generate a lazy reference for. See
8547330f729Sjoerg   /// DefinedSymbols and FinishModule().
8557330f729Sjoerg   llvm::SetVector<IdentifierInfo*> LazySymbols;
8567330f729Sjoerg 
8577330f729Sjoerg   /// DefinedSymbols - External symbols which are defined by this
8587330f729Sjoerg   /// module. The symbols in this list and LazySymbols are used to add
8597330f729Sjoerg   /// special linker symbols which ensure that Objective-C modules are
8607330f729Sjoerg   /// linked properly.
8617330f729Sjoerg   llvm::SetVector<IdentifierInfo*> DefinedSymbols;
8627330f729Sjoerg 
8637330f729Sjoerg   /// ClassNames - uniqued class names.
8647330f729Sjoerg   llvm::StringMap<llvm::GlobalVariable*> ClassNames;
8657330f729Sjoerg 
8667330f729Sjoerg   /// MethodVarNames - uniqued method variable names.
8677330f729Sjoerg   llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
8687330f729Sjoerg 
8697330f729Sjoerg   /// DefinedCategoryNames - list of category names in form Class_Category.
8707330f729Sjoerg   llvm::SmallSetVector<llvm::CachedHashString, 16> DefinedCategoryNames;
8717330f729Sjoerg 
8727330f729Sjoerg   /// MethodVarTypes - uniqued method type signatures. We have to use
8737330f729Sjoerg   /// a StringMap here because have no other unique reference.
8747330f729Sjoerg   llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
8757330f729Sjoerg 
8767330f729Sjoerg   /// MethodDefinitions - map of methods which have been defined in
8777330f729Sjoerg   /// this translation unit.
8787330f729Sjoerg   llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions;
8797330f729Sjoerg 
880*e038c9c4Sjoerg   /// DirectMethodDefinitions - map of direct methods which have been defined in
881*e038c9c4Sjoerg   /// this translation unit.
882*e038c9c4Sjoerg   llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> DirectMethodDefinitions;
883*e038c9c4Sjoerg 
8847330f729Sjoerg   /// PropertyNames - uniqued method variable names.
8857330f729Sjoerg   llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
8867330f729Sjoerg 
8877330f729Sjoerg   /// ClassReferences - uniqued class references.
8887330f729Sjoerg   llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
8897330f729Sjoerg 
8907330f729Sjoerg   /// SelectorReferences - uniqued selector references.
8917330f729Sjoerg   llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
8927330f729Sjoerg 
8937330f729Sjoerg   /// Protocols - Protocols for which an objc_protocol structure has
8947330f729Sjoerg   /// been emitted. Forward declarations are handled by creating an
8957330f729Sjoerg   /// empty structure whose initializer is filled in when/if defined.
8967330f729Sjoerg   llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
8977330f729Sjoerg 
8987330f729Sjoerg   /// DefinedProtocols - Protocols which have actually been
8997330f729Sjoerg   /// defined. We should not need this, see FIXME in GenerateProtocol.
9007330f729Sjoerg   llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
9017330f729Sjoerg 
9027330f729Sjoerg   /// DefinedClasses - List of defined classes.
9037330f729Sjoerg   SmallVector<llvm::GlobalValue*, 16> DefinedClasses;
9047330f729Sjoerg 
9057330f729Sjoerg   /// ImplementedClasses - List of @implemented classes.
9067330f729Sjoerg   SmallVector<const ObjCInterfaceDecl*, 16> ImplementedClasses;
9077330f729Sjoerg 
9087330f729Sjoerg   /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
9097330f729Sjoerg   SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyClasses;
9107330f729Sjoerg 
9117330f729Sjoerg   /// DefinedCategories - List of defined categories.
9127330f729Sjoerg   SmallVector<llvm::GlobalValue*, 16> DefinedCategories;
9137330f729Sjoerg 
9147330f729Sjoerg   /// DefinedStubCategories - List of defined categories on class stubs.
9157330f729Sjoerg   SmallVector<llvm::GlobalValue*, 16> DefinedStubCategories;
9167330f729Sjoerg 
9177330f729Sjoerg   /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
9187330f729Sjoerg   SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyCategories;
9197330f729Sjoerg 
9207330f729Sjoerg   /// Cached reference to the class for constant strings. This value has type
9217330f729Sjoerg   /// int * but is actually an Obj-C class pointer.
9227330f729Sjoerg   llvm::WeakTrackingVH ConstantStringClassRef;
9237330f729Sjoerg 
9247330f729Sjoerg   /// The LLVM type corresponding to NSConstantString.
9257330f729Sjoerg   llvm::StructType *NSConstantStringType = nullptr;
9267330f729Sjoerg 
9277330f729Sjoerg   llvm::StringMap<llvm::GlobalVariable *> NSConstantStringMap;
9287330f729Sjoerg 
9297330f729Sjoerg   /// GetMethodVarName - Return a unique constant for the given
9307330f729Sjoerg   /// selector's name. The return value has type char *.
9317330f729Sjoerg   llvm::Constant *GetMethodVarName(Selector Sel);
9327330f729Sjoerg   llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
9337330f729Sjoerg 
9347330f729Sjoerg   /// GetMethodVarType - Return a unique constant for the given
9357330f729Sjoerg   /// method's type encoding string. The return value has type char *.
9367330f729Sjoerg 
9377330f729Sjoerg   // FIXME: This is a horrible name.
9387330f729Sjoerg   llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D,
9397330f729Sjoerg                                    bool Extended = false);
9407330f729Sjoerg   llvm::Constant *GetMethodVarType(const FieldDecl *D);
9417330f729Sjoerg 
9427330f729Sjoerg   /// GetPropertyName - Return a unique constant for the given
9437330f729Sjoerg   /// name. The return value has type char *.
9447330f729Sjoerg   llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
9457330f729Sjoerg 
9467330f729Sjoerg   // FIXME: This can be dropped once string functions are unified.
9477330f729Sjoerg   llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
9487330f729Sjoerg                                         const Decl *Container);
9497330f729Sjoerg 
9507330f729Sjoerg   /// GetClassName - Return a unique constant for the given selector's
9517330f729Sjoerg   /// runtime name (which may change via use of objc_runtime_name attribute on
9527330f729Sjoerg   /// class or protocol definition. The return value has type char *.
9537330f729Sjoerg   llvm::Constant *GetClassName(StringRef RuntimeName);
9547330f729Sjoerg 
9557330f729Sjoerg   llvm::Function *GetMethodDefinition(const ObjCMethodDecl *MD);
9567330f729Sjoerg 
9577330f729Sjoerg   /// BuildIvarLayout - Builds ivar layout bitmap for the class
9587330f729Sjoerg   /// implementation for the __strong or __weak case.
9597330f729Sjoerg   ///
9607330f729Sjoerg   /// \param hasMRCWeakIvars - Whether we are compiling in MRC and there
9617330f729Sjoerg   ///   are any weak ivars defined directly in the class.  Meaningless unless
9627330f729Sjoerg   ///   building a weak layout.  Does not guarantee that the layout will
9637330f729Sjoerg   ///   actually have any entries, because the ivar might be under-aligned.
9647330f729Sjoerg   llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
9657330f729Sjoerg                                   CharUnits beginOffset,
9667330f729Sjoerg                                   CharUnits endOffset,
9677330f729Sjoerg                                   bool forStrongLayout,
9687330f729Sjoerg                                   bool hasMRCWeakIvars);
9697330f729Sjoerg 
BuildStrongIvarLayout(const ObjCImplementationDecl * OI,CharUnits beginOffset,CharUnits endOffset)9707330f729Sjoerg   llvm::Constant *BuildStrongIvarLayout(const ObjCImplementationDecl *OI,
9717330f729Sjoerg                                         CharUnits beginOffset,
9727330f729Sjoerg                                         CharUnits endOffset) {
9737330f729Sjoerg     return BuildIvarLayout(OI, beginOffset, endOffset, true, false);
9747330f729Sjoerg   }
9757330f729Sjoerg 
BuildWeakIvarLayout(const ObjCImplementationDecl * OI,CharUnits beginOffset,CharUnits endOffset,bool hasMRCWeakIvars)9767330f729Sjoerg   llvm::Constant *BuildWeakIvarLayout(const ObjCImplementationDecl *OI,
9777330f729Sjoerg                                       CharUnits beginOffset,
9787330f729Sjoerg                                       CharUnits endOffset,
9797330f729Sjoerg                                       bool hasMRCWeakIvars) {
9807330f729Sjoerg     return BuildIvarLayout(OI, beginOffset, endOffset, false, hasMRCWeakIvars);
9817330f729Sjoerg   }
9827330f729Sjoerg 
9837330f729Sjoerg   Qualifiers::ObjCLifetime getBlockCaptureLifetime(QualType QT, bool ByrefLayout);
9847330f729Sjoerg 
9857330f729Sjoerg   void UpdateRunSkipBlockVars(bool IsByref,
9867330f729Sjoerg                               Qualifiers::ObjCLifetime LifeTime,
9877330f729Sjoerg                               CharUnits FieldOffset,
9887330f729Sjoerg                               CharUnits FieldSize);
9897330f729Sjoerg 
9907330f729Sjoerg   void BuildRCBlockVarRecordLayout(const RecordType *RT,
9917330f729Sjoerg                                    CharUnits BytePos, bool &HasUnion,
9927330f729Sjoerg                                    bool ByrefLayout=false);
9937330f729Sjoerg 
9947330f729Sjoerg   void BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
9957330f729Sjoerg                            const RecordDecl *RD,
9967330f729Sjoerg                            ArrayRef<const FieldDecl*> RecFields,
9977330f729Sjoerg                            CharUnits BytePos, bool &HasUnion,
9987330f729Sjoerg                            bool ByrefLayout);
9997330f729Sjoerg 
10007330f729Sjoerg   uint64_t InlineLayoutInstruction(SmallVectorImpl<unsigned char> &Layout);
10017330f729Sjoerg 
10027330f729Sjoerg   llvm::Constant *getBitmapBlockLayout(bool ComputeByrefLayout);
10037330f729Sjoerg 
10047330f729Sjoerg   /// GetIvarLayoutName - Returns a unique constant for the given
10057330f729Sjoerg   /// ivar layout bitmap.
10067330f729Sjoerg   llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
10077330f729Sjoerg                                     const ObjCCommonTypesHelper &ObjCTypes);
10087330f729Sjoerg 
10097330f729Sjoerg   /// EmitPropertyList - Emit the given property list. The return
10107330f729Sjoerg   /// value has type PropertyListPtrTy.
10117330f729Sjoerg   llvm::Constant *EmitPropertyList(Twine Name,
10127330f729Sjoerg                                    const Decl *Container,
10137330f729Sjoerg                                    const ObjCContainerDecl *OCD,
10147330f729Sjoerg                                    const ObjCCommonTypesHelper &ObjCTypes,
10157330f729Sjoerg                                    bool IsClassProperty);
10167330f729Sjoerg 
10177330f729Sjoerg   /// EmitProtocolMethodTypes - Generate the array of extended method type
10187330f729Sjoerg   /// strings. The return value has type Int8PtrPtrTy.
10197330f729Sjoerg   llvm::Constant *EmitProtocolMethodTypes(Twine Name,
10207330f729Sjoerg                                           ArrayRef<llvm::Constant*> MethodTypes,
10217330f729Sjoerg                                        const ObjCCommonTypesHelper &ObjCTypes);
10227330f729Sjoerg 
10237330f729Sjoerg   /// GetProtocolRef - Return a reference to the internal protocol
10247330f729Sjoerg   /// description, creating an empty one if it has not been
10257330f729Sjoerg   /// defined. The return value has type ProtocolPtrTy.
10267330f729Sjoerg   llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
10277330f729Sjoerg 
10287330f729Sjoerg   /// Return a reference to the given Class using runtime calls rather than
10297330f729Sjoerg   /// by a symbol reference.
10307330f729Sjoerg   llvm::Value *EmitClassRefViaRuntime(CodeGenFunction &CGF,
10317330f729Sjoerg                                       const ObjCInterfaceDecl *ID,
10327330f729Sjoerg                                       ObjCCommonTypesHelper &ObjCTypes);
10337330f729Sjoerg 
10347330f729Sjoerg   std::string GetSectionName(StringRef Section, StringRef MachOAttributes);
10357330f729Sjoerg 
10367330f729Sjoerg public:
10377330f729Sjoerg   /// CreateMetadataVar - Create a global variable with internal
10387330f729Sjoerg   /// linkage for use by the Objective-C runtime.
10397330f729Sjoerg   ///
10407330f729Sjoerg   /// This is a convenience wrapper which not only creates the
10417330f729Sjoerg   /// variable, but also sets the section and alignment and adds the
10427330f729Sjoerg   /// global to the "llvm.used" list.
10437330f729Sjoerg   ///
10447330f729Sjoerg   /// \param Name - The variable name.
10457330f729Sjoerg   /// \param Init - The variable initializer; this is also used to
10467330f729Sjoerg   ///   define the type of the variable.
10477330f729Sjoerg   /// \param Section - The section the variable should go into, or empty.
10487330f729Sjoerg   /// \param Align - The alignment for the variable, or 0.
10497330f729Sjoerg   /// \param AddToUsed - Whether the variable should be added to
10507330f729Sjoerg   ///   "llvm.used".
10517330f729Sjoerg   llvm::GlobalVariable *CreateMetadataVar(Twine Name,
10527330f729Sjoerg                                           ConstantStructBuilder &Init,
10537330f729Sjoerg                                           StringRef Section, CharUnits Align,
10547330f729Sjoerg                                           bool AddToUsed);
10557330f729Sjoerg   llvm::GlobalVariable *CreateMetadataVar(Twine Name,
10567330f729Sjoerg                                           llvm::Constant *Init,
10577330f729Sjoerg                                           StringRef Section, CharUnits Align,
10587330f729Sjoerg                                           bool AddToUsed);
10597330f729Sjoerg 
10607330f729Sjoerg   llvm::GlobalVariable *CreateCStringLiteral(StringRef Name,
10617330f729Sjoerg                                              ObjCLabelType LabelType,
10627330f729Sjoerg                                              bool ForceNonFragileABI = false,
10637330f729Sjoerg                                              bool NullTerminate = true);
10647330f729Sjoerg 
10657330f729Sjoerg protected:
10667330f729Sjoerg   CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
10677330f729Sjoerg                                   ReturnValueSlot Return,
10687330f729Sjoerg                                   QualType ResultType,
1069*e038c9c4Sjoerg                                   Selector Sel,
10707330f729Sjoerg                                   llvm::Value *Arg0,
10717330f729Sjoerg                                   QualType Arg0Ty,
10727330f729Sjoerg                                   bool IsSuper,
10737330f729Sjoerg                                   const CallArgList &CallArgs,
10747330f729Sjoerg                                   const ObjCMethodDecl *OMD,
10757330f729Sjoerg                                   const ObjCInterfaceDecl *ClassReceiver,
10767330f729Sjoerg                                   const ObjCCommonTypesHelper &ObjCTypes);
10777330f729Sjoerg 
10787330f729Sjoerg   /// EmitImageInfo - Emit the image info marker used to encode some module
10797330f729Sjoerg   /// level information.
10807330f729Sjoerg   void EmitImageInfo();
10817330f729Sjoerg 
10827330f729Sjoerg public:
CGObjCCommonMac(CodeGen::CodeGenModule & cgm)1083*e038c9c4Sjoerg   CGObjCCommonMac(CodeGen::CodeGenModule &cgm)
1084*e038c9c4Sjoerg       : CGObjCRuntime(cgm), VMContext(cgm.getLLVMContext()) {}
10857330f729Sjoerg 
isNonFragileABI() const10867330f729Sjoerg   bool isNonFragileABI() const {
10877330f729Sjoerg     return ObjCABI == 2;
10887330f729Sjoerg   }
10897330f729Sjoerg 
10907330f729Sjoerg   ConstantAddress GenerateConstantString(const StringLiteral *SL) override;
10917330f729Sjoerg   ConstantAddress GenerateConstantNSString(const StringLiteral *SL);
10927330f729Sjoerg 
10937330f729Sjoerg   llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
10947330f729Sjoerg                                  const ObjCContainerDecl *CD=nullptr) override;
10957330f729Sjoerg 
1096*e038c9c4Sjoerg   llvm::Function *GenerateDirectMethod(const ObjCMethodDecl *OMD,
1097*e038c9c4Sjoerg                                        const ObjCContainerDecl *CD);
10987330f729Sjoerg 
1099*e038c9c4Sjoerg   void GenerateDirectMethodPrologue(CodeGenFunction &CGF, llvm::Function *Fn,
1100*e038c9c4Sjoerg                                     const ObjCMethodDecl *OMD,
1101*e038c9c4Sjoerg                                     const ObjCContainerDecl *CD) override;
1102*e038c9c4Sjoerg 
1103*e038c9c4Sjoerg   void GenerateProtocol(const ObjCProtocolDecl *PD) override;
11047330f729Sjoerg 
11057330f729Sjoerg   /// GetOrEmitProtocolRef - Get a forward reference to the protocol
11067330f729Sjoerg   /// object for the given declaration, emitting it if needed. These
11077330f729Sjoerg   /// forward references will be filled in with empty bodies if no
11087330f729Sjoerg   /// definition is seen. The return value has type ProtocolPtrTy.
11097330f729Sjoerg   virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
11107330f729Sjoerg 
11117330f729Sjoerg   virtual llvm::Constant *getNSConstantStringClassRef() = 0;
11127330f729Sjoerg 
11137330f729Sjoerg   llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
11147330f729Sjoerg                                      const CGBlockInfo &blockInfo) override;
11157330f729Sjoerg   llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM,
11167330f729Sjoerg                                      const CGBlockInfo &blockInfo) override;
11177330f729Sjoerg   std::string getRCBlockLayoutStr(CodeGen::CodeGenModule &CGM,
11187330f729Sjoerg                                   const CGBlockInfo &blockInfo) override;
11197330f729Sjoerg 
11207330f729Sjoerg   llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM,
11217330f729Sjoerg                                    QualType T) override;
11227330f729Sjoerg 
11237330f729Sjoerg private:
11247330f729Sjoerg   void fillRunSkipBlockVars(CodeGenModule &CGM, const CGBlockInfo &blockInfo);
11257330f729Sjoerg };
11267330f729Sjoerg 
11277330f729Sjoerg namespace {
11287330f729Sjoerg 
11297330f729Sjoerg enum class MethodListType {
11307330f729Sjoerg   CategoryInstanceMethods,
11317330f729Sjoerg   CategoryClassMethods,
11327330f729Sjoerg   InstanceMethods,
11337330f729Sjoerg   ClassMethods,
11347330f729Sjoerg   ProtocolInstanceMethods,
11357330f729Sjoerg   ProtocolClassMethods,
11367330f729Sjoerg   OptionalProtocolInstanceMethods,
11377330f729Sjoerg   OptionalProtocolClassMethods,
11387330f729Sjoerg };
11397330f729Sjoerg 
11407330f729Sjoerg /// A convenience class for splitting the methods of a protocol into
11417330f729Sjoerg /// the four interesting groups.
11427330f729Sjoerg class ProtocolMethodLists {
11437330f729Sjoerg public:
11447330f729Sjoerg   enum Kind {
11457330f729Sjoerg     RequiredInstanceMethods,
11467330f729Sjoerg     RequiredClassMethods,
11477330f729Sjoerg     OptionalInstanceMethods,
11487330f729Sjoerg     OptionalClassMethods
11497330f729Sjoerg   };
11507330f729Sjoerg   enum {
11517330f729Sjoerg     NumProtocolMethodLists = 4
11527330f729Sjoerg   };
11537330f729Sjoerg 
getMethodListKind(Kind kind)11547330f729Sjoerg   static MethodListType getMethodListKind(Kind kind) {
11557330f729Sjoerg     switch (kind) {
11567330f729Sjoerg     case RequiredInstanceMethods:
11577330f729Sjoerg       return MethodListType::ProtocolInstanceMethods;
11587330f729Sjoerg     case RequiredClassMethods:
11597330f729Sjoerg       return MethodListType::ProtocolClassMethods;
11607330f729Sjoerg     case OptionalInstanceMethods:
11617330f729Sjoerg       return MethodListType::OptionalProtocolInstanceMethods;
11627330f729Sjoerg     case OptionalClassMethods:
11637330f729Sjoerg       return MethodListType::OptionalProtocolClassMethods;
11647330f729Sjoerg     }
11657330f729Sjoerg     llvm_unreachable("bad kind");
11667330f729Sjoerg   }
11677330f729Sjoerg 
11687330f729Sjoerg   SmallVector<const ObjCMethodDecl *, 4> Methods[NumProtocolMethodLists];
11697330f729Sjoerg 
get(const ObjCProtocolDecl * PD)11707330f729Sjoerg   static ProtocolMethodLists get(const ObjCProtocolDecl *PD) {
11717330f729Sjoerg     ProtocolMethodLists result;
11727330f729Sjoerg 
11737330f729Sjoerg     for (auto MD : PD->methods()) {
11747330f729Sjoerg       size_t index = (2 * size_t(MD->isOptional()))
11757330f729Sjoerg                    + (size_t(MD->isClassMethod()));
11767330f729Sjoerg       result.Methods[index].push_back(MD);
11777330f729Sjoerg     }
11787330f729Sjoerg 
11797330f729Sjoerg     return result;
11807330f729Sjoerg   }
11817330f729Sjoerg 
11827330f729Sjoerg   template <class Self>
emitExtendedTypesArray(Self * self) const11837330f729Sjoerg   SmallVector<llvm::Constant*, 8> emitExtendedTypesArray(Self *self) const {
11847330f729Sjoerg     // In both ABIs, the method types list is parallel with the
11857330f729Sjoerg     // concatenation of the methods arrays in the following order:
11867330f729Sjoerg     //   instance methods
11877330f729Sjoerg     //   class methods
11887330f729Sjoerg     //   optional instance methods
11897330f729Sjoerg     //   optional class methods
11907330f729Sjoerg     SmallVector<llvm::Constant*, 8> result;
11917330f729Sjoerg 
11927330f729Sjoerg     // Methods is already in the correct order for both ABIs.
11937330f729Sjoerg     for (auto &list : Methods) {
11947330f729Sjoerg       for (auto MD : list) {
11957330f729Sjoerg         result.push_back(self->GetMethodVarType(MD, true));
11967330f729Sjoerg       }
11977330f729Sjoerg     }
11987330f729Sjoerg 
11997330f729Sjoerg     return result;
12007330f729Sjoerg   }
12017330f729Sjoerg 
12027330f729Sjoerg   template <class Self>
emitMethodList(Self * self,const ObjCProtocolDecl * PD,Kind kind) const12037330f729Sjoerg   llvm::Constant *emitMethodList(Self *self, const ObjCProtocolDecl *PD,
12047330f729Sjoerg                                  Kind kind) const {
12057330f729Sjoerg     return self->emitMethodList(PD->getObjCRuntimeNameAsString(),
12067330f729Sjoerg                                 getMethodListKind(kind), Methods[kind]);
12077330f729Sjoerg   }
12087330f729Sjoerg };
12097330f729Sjoerg 
12107330f729Sjoerg } // end anonymous namespace
12117330f729Sjoerg 
12127330f729Sjoerg class CGObjCMac : public CGObjCCommonMac {
12137330f729Sjoerg private:
12147330f729Sjoerg   friend ProtocolMethodLists;
12157330f729Sjoerg 
12167330f729Sjoerg   ObjCTypesHelper ObjCTypes;
12177330f729Sjoerg 
12187330f729Sjoerg   /// EmitModuleInfo - Another marker encoding module level
12197330f729Sjoerg   /// information.
12207330f729Sjoerg   void EmitModuleInfo();
12217330f729Sjoerg 
12227330f729Sjoerg   /// EmitModuleSymols - Emit module symbols, the list of defined
12237330f729Sjoerg   /// classes and categories. The result has type SymtabPtrTy.
12247330f729Sjoerg   llvm::Constant *EmitModuleSymbols();
12257330f729Sjoerg 
12267330f729Sjoerg   /// FinishModule - Write out global data structures at the end of
12277330f729Sjoerg   /// processing a translation unit.
12287330f729Sjoerg   void FinishModule();
12297330f729Sjoerg 
12307330f729Sjoerg   /// EmitClassExtension - Generate the class extension structure used
12317330f729Sjoerg   /// to store the weak ivar layout and properties. The return value
12327330f729Sjoerg   /// has type ClassExtensionPtrTy.
12337330f729Sjoerg   llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID,
12347330f729Sjoerg                                      CharUnits instanceSize,
12357330f729Sjoerg                                      bool hasMRCWeakIvars,
12367330f729Sjoerg                                      bool isMetaclass);
12377330f729Sjoerg 
12387330f729Sjoerg   /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
12397330f729Sjoerg   /// for the given class.
12407330f729Sjoerg   llvm::Value *EmitClassRef(CodeGenFunction &CGF,
12417330f729Sjoerg                             const ObjCInterfaceDecl *ID);
12427330f729Sjoerg 
12437330f729Sjoerg   llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF,
12447330f729Sjoerg                                   IdentifierInfo *II);
12457330f729Sjoerg 
12467330f729Sjoerg   llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) override;
12477330f729Sjoerg 
12487330f729Sjoerg   /// EmitSuperClassRef - Emits reference to class's main metadata class.
12497330f729Sjoerg   llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
12507330f729Sjoerg 
12517330f729Sjoerg   /// EmitIvarList - Emit the ivar list for the given
12527330f729Sjoerg   /// implementation. If ForClass is true the list of class ivars
12537330f729Sjoerg   /// (i.e. metaclass ivars) is emitted, otherwise the list of
12547330f729Sjoerg   /// interface ivars will be emitted. The return value has type
12557330f729Sjoerg   /// IvarListPtrTy.
12567330f729Sjoerg   llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
12577330f729Sjoerg                                bool ForClass);
12587330f729Sjoerg 
12597330f729Sjoerg   /// EmitMetaClass - Emit a forward reference to the class structure
12607330f729Sjoerg   /// for the metaclass of the given interface. The return value has
12617330f729Sjoerg   /// type ClassPtrTy.
12627330f729Sjoerg   llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
12637330f729Sjoerg 
12647330f729Sjoerg   /// EmitMetaClass - Emit a class structure for the metaclass of the
12657330f729Sjoerg   /// given implementation. The return value has type ClassPtrTy.
12667330f729Sjoerg   llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
12677330f729Sjoerg                                 llvm::Constant *Protocols,
12687330f729Sjoerg                                 ArrayRef<const ObjCMethodDecl *> Methods);
12697330f729Sjoerg 
12707330f729Sjoerg   void emitMethodConstant(ConstantArrayBuilder &builder,
12717330f729Sjoerg                           const ObjCMethodDecl *MD);
12727330f729Sjoerg 
12737330f729Sjoerg   void emitMethodDescriptionConstant(ConstantArrayBuilder &builder,
12747330f729Sjoerg                                      const ObjCMethodDecl *MD);
12757330f729Sjoerg 
12767330f729Sjoerg   /// EmitMethodList - Emit the method list for the given
12777330f729Sjoerg   /// implementation. The return value has type MethodListPtrTy.
12787330f729Sjoerg   llvm::Constant *emitMethodList(Twine Name, MethodListType MLT,
12797330f729Sjoerg                                  ArrayRef<const ObjCMethodDecl *> Methods);
12807330f729Sjoerg 
12817330f729Sjoerg   /// GetOrEmitProtocol - Get the protocol object for the given
12827330f729Sjoerg   /// declaration, emitting it if necessary. The return value has type
12837330f729Sjoerg   /// ProtocolPtrTy.
12847330f729Sjoerg   llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD) override;
12857330f729Sjoerg 
12867330f729Sjoerg   /// GetOrEmitProtocolRef - Get a forward reference to the protocol
12877330f729Sjoerg   /// object for the given declaration, emitting it if needed. These
12887330f729Sjoerg   /// forward references will be filled in with empty bodies if no
12897330f729Sjoerg   /// definition is seen. The return value has type ProtocolPtrTy.
12907330f729Sjoerg   llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) override;
12917330f729Sjoerg 
12927330f729Sjoerg   /// EmitProtocolExtension - Generate the protocol extension
12937330f729Sjoerg   /// structure used to store optional instance and class methods, and
12947330f729Sjoerg   /// protocol properties. The return value has type
12957330f729Sjoerg   /// ProtocolExtensionPtrTy.
12967330f729Sjoerg   llvm::Constant *
12977330f729Sjoerg   EmitProtocolExtension(const ObjCProtocolDecl *PD,
12987330f729Sjoerg                         const ProtocolMethodLists &methodLists);
12997330f729Sjoerg 
13007330f729Sjoerg   /// EmitProtocolList - Generate the list of referenced
13017330f729Sjoerg   /// protocols. The return value has type ProtocolListPtrTy.
13027330f729Sjoerg   llvm::Constant *EmitProtocolList(Twine Name,
13037330f729Sjoerg                                    ObjCProtocolDecl::protocol_iterator begin,
13047330f729Sjoerg                                    ObjCProtocolDecl::protocol_iterator end);
13057330f729Sjoerg 
13067330f729Sjoerg   /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
13077330f729Sjoerg   /// for the given selector.
13087330f729Sjoerg   llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel);
1309*e038c9c4Sjoerg   Address EmitSelectorAddr(Selector Sel);
13107330f729Sjoerg 
13117330f729Sjoerg public:
13127330f729Sjoerg   CGObjCMac(CodeGen::CodeGenModule &cgm);
13137330f729Sjoerg 
13147330f729Sjoerg   llvm::Constant *getNSConstantStringClassRef() override;
13157330f729Sjoerg 
13167330f729Sjoerg   llvm::Function *ModuleInitFunction() override;
13177330f729Sjoerg 
13187330f729Sjoerg   CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
13197330f729Sjoerg                                       ReturnValueSlot Return,
13207330f729Sjoerg                                       QualType ResultType,
13217330f729Sjoerg                                       Selector Sel, llvm::Value *Receiver,
13227330f729Sjoerg                                       const CallArgList &CallArgs,
13237330f729Sjoerg                                       const ObjCInterfaceDecl *Class,
13247330f729Sjoerg                                       const ObjCMethodDecl *Method) override;
13257330f729Sjoerg 
13267330f729Sjoerg   CodeGen::RValue
13277330f729Sjoerg   GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
13287330f729Sjoerg                            ReturnValueSlot Return, QualType ResultType,
13297330f729Sjoerg                            Selector Sel, const ObjCInterfaceDecl *Class,
13307330f729Sjoerg                            bool isCategoryImpl, llvm::Value *Receiver,
13317330f729Sjoerg                            bool IsClassMessage, const CallArgList &CallArgs,
13327330f729Sjoerg                            const ObjCMethodDecl *Method) override;
13337330f729Sjoerg 
13347330f729Sjoerg   llvm::Value *GetClass(CodeGenFunction &CGF,
13357330f729Sjoerg                         const ObjCInterfaceDecl *ID) override;
13367330f729Sjoerg 
13377330f729Sjoerg   llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) override;
13387330f729Sjoerg   Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override;
13397330f729Sjoerg 
13407330f729Sjoerg   /// The NeXT/Apple runtimes do not support typed selectors; just emit an
13417330f729Sjoerg   /// untyped one.
13427330f729Sjoerg   llvm::Value *GetSelector(CodeGenFunction &CGF,
13437330f729Sjoerg                            const ObjCMethodDecl *Method) override;
13447330f729Sjoerg 
13457330f729Sjoerg   llvm::Constant *GetEHType(QualType T) override;
13467330f729Sjoerg 
13477330f729Sjoerg   void GenerateCategory(const ObjCCategoryImplDecl *CMD) override;
13487330f729Sjoerg 
13497330f729Sjoerg   void GenerateClass(const ObjCImplementationDecl *ClassDecl) override;
13507330f729Sjoerg 
RegisterAlias(const ObjCCompatibleAliasDecl * OAD)13517330f729Sjoerg   void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) override {}
13527330f729Sjoerg 
13537330f729Sjoerg   llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
13547330f729Sjoerg                                    const ObjCProtocolDecl *PD) override;
13557330f729Sjoerg 
13567330f729Sjoerg   llvm::FunctionCallee GetPropertyGetFunction() override;
13577330f729Sjoerg   llvm::FunctionCallee GetPropertySetFunction() override;
13587330f729Sjoerg   llvm::FunctionCallee GetOptimizedPropertySetFunction(bool atomic,
13597330f729Sjoerg                                                        bool copy) override;
13607330f729Sjoerg   llvm::FunctionCallee GetGetStructFunction() override;
13617330f729Sjoerg   llvm::FunctionCallee GetSetStructFunction() override;
13627330f729Sjoerg   llvm::FunctionCallee GetCppAtomicObjectGetFunction() override;
13637330f729Sjoerg   llvm::FunctionCallee GetCppAtomicObjectSetFunction() override;
13647330f729Sjoerg   llvm::FunctionCallee EnumerationMutationFunction() override;
13657330f729Sjoerg 
13667330f729Sjoerg   void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
13677330f729Sjoerg                    const ObjCAtTryStmt &S) override;
13687330f729Sjoerg   void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
13697330f729Sjoerg                             const ObjCAtSynchronizedStmt &S) override;
13707330f729Sjoerg   void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S);
13717330f729Sjoerg   void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S,
13727330f729Sjoerg                      bool ClearInsertionPoint=true) override;
13737330f729Sjoerg   llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
13747330f729Sjoerg                                  Address AddrWeakObj) override;
13757330f729Sjoerg   void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
13767330f729Sjoerg                           llvm::Value *src, Address dst) override;
13777330f729Sjoerg   void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
13787330f729Sjoerg                             llvm::Value *src, Address dest,
13797330f729Sjoerg                             bool threadlocal = false) override;
13807330f729Sjoerg   void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
13817330f729Sjoerg                           llvm::Value *src, Address dest,
13827330f729Sjoerg                           llvm::Value *ivarOffset) override;
13837330f729Sjoerg   void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
13847330f729Sjoerg                                 llvm::Value *src, Address dest) override;
13857330f729Sjoerg   void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
13867330f729Sjoerg                                 Address dest, Address src,
13877330f729Sjoerg                                 llvm::Value *size) override;
13887330f729Sjoerg 
13897330f729Sjoerg   LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy,
13907330f729Sjoerg                               llvm::Value *BaseValue, const ObjCIvarDecl *Ivar,
13917330f729Sjoerg                               unsigned CVRQualifiers) override;
13927330f729Sjoerg   llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
13937330f729Sjoerg                               const ObjCInterfaceDecl *Interface,
13947330f729Sjoerg                               const ObjCIvarDecl *Ivar) override;
13957330f729Sjoerg };
13967330f729Sjoerg 
13977330f729Sjoerg class CGObjCNonFragileABIMac : public CGObjCCommonMac {
13987330f729Sjoerg private:
13997330f729Sjoerg   friend ProtocolMethodLists;
14007330f729Sjoerg   ObjCNonFragileABITypesHelper ObjCTypes;
14017330f729Sjoerg   llvm::GlobalVariable* ObjCEmptyCacheVar;
14027330f729Sjoerg   llvm::Constant* ObjCEmptyVtableVar;
14037330f729Sjoerg 
14047330f729Sjoerg   /// SuperClassReferences - uniqued super class references.
14057330f729Sjoerg   llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
14067330f729Sjoerg 
14077330f729Sjoerg   /// MetaClassReferences - uniqued meta class references.
14087330f729Sjoerg   llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
14097330f729Sjoerg 
14107330f729Sjoerg   /// EHTypeReferences - uniqued class ehtype references.
14117330f729Sjoerg   llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
14127330f729Sjoerg 
14137330f729Sjoerg   /// VTableDispatchMethods - List of methods for which we generate
14147330f729Sjoerg   /// vtable-based message dispatch.
14157330f729Sjoerg   llvm::DenseSet<Selector> VTableDispatchMethods;
14167330f729Sjoerg 
14177330f729Sjoerg   /// DefinedMetaClasses - List of defined meta-classes.
14187330f729Sjoerg   std::vector<llvm::GlobalValue*> DefinedMetaClasses;
14197330f729Sjoerg 
14207330f729Sjoerg   /// isVTableDispatchedSelector - Returns true if SEL is a
14217330f729Sjoerg   /// vtable-based selector.
14227330f729Sjoerg   bool isVTableDispatchedSelector(Selector Sel);
14237330f729Sjoerg 
14247330f729Sjoerg   /// FinishNonFragileABIModule - Write out global data structures at the end of
14257330f729Sjoerg   /// processing a translation unit.
14267330f729Sjoerg   void FinishNonFragileABIModule();
14277330f729Sjoerg 
14287330f729Sjoerg   /// AddModuleClassList - Add the given list of class pointers to the
14297330f729Sjoerg   /// module with the provided symbol and section names.
14307330f729Sjoerg   void AddModuleClassList(ArrayRef<llvm::GlobalValue *> Container,
14317330f729Sjoerg                           StringRef SymbolName, StringRef SectionName);
14327330f729Sjoerg 
14337330f729Sjoerg   llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
14347330f729Sjoerg                                               unsigned InstanceStart,
14357330f729Sjoerg                                               unsigned InstanceSize,
14367330f729Sjoerg                                               const ObjCImplementationDecl *ID);
14377330f729Sjoerg   llvm::GlobalVariable *BuildClassObject(const ObjCInterfaceDecl *CI,
14387330f729Sjoerg                                          bool isMetaclass,
14397330f729Sjoerg                                          llvm::Constant *IsAGV,
14407330f729Sjoerg                                          llvm::Constant *SuperClassGV,
14417330f729Sjoerg                                          llvm::Constant *ClassRoGV,
14427330f729Sjoerg                                          bool HiddenVisibility);
14437330f729Sjoerg 
14447330f729Sjoerg   void emitMethodConstant(ConstantArrayBuilder &builder,
14457330f729Sjoerg                             const ObjCMethodDecl *MD,
14467330f729Sjoerg                             bool forProtocol);
14477330f729Sjoerg 
14487330f729Sjoerg   /// Emit the method list for the given implementation. The return value
14497330f729Sjoerg   /// has type MethodListnfABITy.
14507330f729Sjoerg   llvm::Constant *emitMethodList(Twine Name, MethodListType MLT,
14517330f729Sjoerg                                  ArrayRef<const ObjCMethodDecl *> Methods);
14527330f729Sjoerg 
14537330f729Sjoerg   /// EmitIvarList - Emit the ivar list for the given
14547330f729Sjoerg   /// implementation. If ForClass is true the list of class ivars
14557330f729Sjoerg   /// (i.e. metaclass ivars) is emitted, otherwise the list of
14567330f729Sjoerg   /// interface ivars will be emitted. The return value has type
14577330f729Sjoerg   /// IvarListnfABIPtrTy.
14587330f729Sjoerg   llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID);
14597330f729Sjoerg 
14607330f729Sjoerg   llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
14617330f729Sjoerg                                     const ObjCIvarDecl *Ivar,
14627330f729Sjoerg                                     unsigned long int offset);
14637330f729Sjoerg 
14647330f729Sjoerg   /// GetOrEmitProtocol - Get the protocol object for the given
14657330f729Sjoerg   /// declaration, emitting it if necessary. The return value has type
14667330f729Sjoerg   /// ProtocolPtrTy.
14677330f729Sjoerg   llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD) override;
14687330f729Sjoerg 
14697330f729Sjoerg   /// GetOrEmitProtocolRef - Get a forward reference to the protocol
14707330f729Sjoerg   /// object for the given declaration, emitting it if needed. These
14717330f729Sjoerg   /// forward references will be filled in with empty bodies if no
14727330f729Sjoerg   /// definition is seen. The return value has type ProtocolPtrTy.
14737330f729Sjoerg   llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) override;
14747330f729Sjoerg 
14757330f729Sjoerg   /// EmitProtocolList - Generate the list of referenced
14767330f729Sjoerg   /// protocols. The return value has type ProtocolListPtrTy.
14777330f729Sjoerg   llvm::Constant *EmitProtocolList(Twine Name,
14787330f729Sjoerg                                    ObjCProtocolDecl::protocol_iterator begin,
14797330f729Sjoerg                                    ObjCProtocolDecl::protocol_iterator end);
14807330f729Sjoerg 
14817330f729Sjoerg   CodeGen::RValue EmitVTableMessageSend(CodeGen::CodeGenFunction &CGF,
14827330f729Sjoerg                                         ReturnValueSlot Return,
14837330f729Sjoerg                                         QualType ResultType,
14847330f729Sjoerg                                         Selector Sel,
14857330f729Sjoerg                                         llvm::Value *Receiver,
14867330f729Sjoerg                                         QualType Arg0Ty,
14877330f729Sjoerg                                         bool IsSuper,
14887330f729Sjoerg                                         const CallArgList &CallArgs,
14897330f729Sjoerg                                         const ObjCMethodDecl *Method);
14907330f729Sjoerg 
14917330f729Sjoerg   /// GetClassGlobal - Return the global variable for the Objective-C
14927330f729Sjoerg   /// class of the given name.
14937330f729Sjoerg   llvm::Constant *GetClassGlobal(StringRef Name,
14947330f729Sjoerg                                  ForDefinition_t IsForDefinition,
14957330f729Sjoerg                                  bool Weak = false, bool DLLImport = false);
14967330f729Sjoerg   llvm::Constant *GetClassGlobal(const ObjCInterfaceDecl *ID,
14977330f729Sjoerg                                  bool isMetaclass,
14987330f729Sjoerg                                  ForDefinition_t isForDefinition);
14997330f729Sjoerg 
15007330f729Sjoerg   llvm::Constant *GetClassGlobalForClassRef(const ObjCInterfaceDecl *ID);
15017330f729Sjoerg 
15027330f729Sjoerg   llvm::Value *EmitLoadOfClassRef(CodeGenFunction &CGF,
15037330f729Sjoerg                                   const ObjCInterfaceDecl *ID,
15047330f729Sjoerg                                   llvm::GlobalVariable *Entry);
15057330f729Sjoerg 
15067330f729Sjoerg   /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
15077330f729Sjoerg   /// for the given class reference.
15087330f729Sjoerg   llvm::Value *EmitClassRef(CodeGenFunction &CGF,
15097330f729Sjoerg                             const ObjCInterfaceDecl *ID);
15107330f729Sjoerg 
15117330f729Sjoerg   llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF,
15127330f729Sjoerg                                   IdentifierInfo *II,
15137330f729Sjoerg                                   const ObjCInterfaceDecl *ID);
15147330f729Sjoerg 
15157330f729Sjoerg   llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) override;
15167330f729Sjoerg 
15177330f729Sjoerg   /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
15187330f729Sjoerg   /// for the given super class reference.
15197330f729Sjoerg   llvm::Value *EmitSuperClassRef(CodeGenFunction &CGF,
15207330f729Sjoerg                                  const ObjCInterfaceDecl *ID);
15217330f729Sjoerg 
15227330f729Sjoerg   /// EmitMetaClassRef - Return a Value * of the address of _class_t
15237330f729Sjoerg   /// meta-data
15247330f729Sjoerg   llvm::Value *EmitMetaClassRef(CodeGenFunction &CGF,
15257330f729Sjoerg                                 const ObjCInterfaceDecl *ID, bool Weak);
15267330f729Sjoerg 
15277330f729Sjoerg   /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
15287330f729Sjoerg   /// the given ivar.
15297330f729Sjoerg   ///
15307330f729Sjoerg   llvm::GlobalVariable * ObjCIvarOffsetVariable(
15317330f729Sjoerg     const ObjCInterfaceDecl *ID,
15327330f729Sjoerg     const ObjCIvarDecl *Ivar);
15337330f729Sjoerg 
15347330f729Sjoerg   /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
15357330f729Sjoerg   /// for the given selector.
15367330f729Sjoerg   llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel);
1537*e038c9c4Sjoerg   Address EmitSelectorAddr(Selector Sel);
15387330f729Sjoerg 
15397330f729Sjoerg   /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
15407330f729Sjoerg   /// interface. The return value has type EHTypePtrTy.
15417330f729Sjoerg   llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
15427330f729Sjoerg                                      ForDefinition_t IsForDefinition);
15437330f729Sjoerg 
getMetaclassSymbolPrefix() const15447330f729Sjoerg   StringRef getMetaclassSymbolPrefix() const { return "OBJC_METACLASS_$_"; }
15457330f729Sjoerg 
getClassSymbolPrefix() const15467330f729Sjoerg   StringRef getClassSymbolPrefix() const { return "OBJC_CLASS_$_"; }
15477330f729Sjoerg 
15487330f729Sjoerg   void GetClassSizeInfo(const ObjCImplementationDecl *OID,
15497330f729Sjoerg                         uint32_t &InstanceStart,
15507330f729Sjoerg                         uint32_t &InstanceSize);
15517330f729Sjoerg 
15527330f729Sjoerg   // Shamelessly stolen from Analysis/CFRefCount.cpp
GetNullarySelector(const char * name) const15537330f729Sjoerg   Selector GetNullarySelector(const char* name) const {
15547330f729Sjoerg     IdentifierInfo* II = &CGM.getContext().Idents.get(name);
15557330f729Sjoerg     return CGM.getContext().Selectors.getSelector(0, &II);
15567330f729Sjoerg   }
15577330f729Sjoerg 
GetUnarySelector(const char * name) const15587330f729Sjoerg   Selector GetUnarySelector(const char* name) const {
15597330f729Sjoerg     IdentifierInfo* II = &CGM.getContext().Idents.get(name);
15607330f729Sjoerg     return CGM.getContext().Selectors.getSelector(1, &II);
15617330f729Sjoerg   }
15627330f729Sjoerg 
15637330f729Sjoerg   /// ImplementationIsNonLazy - Check whether the given category or
15647330f729Sjoerg   /// class implementation is "non-lazy".
15657330f729Sjoerg   bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const;
15667330f729Sjoerg 
IsIvarOffsetKnownIdempotent(const CodeGen::CodeGenFunction & CGF,const ObjCIvarDecl * IV)15677330f729Sjoerg   bool IsIvarOffsetKnownIdempotent(const CodeGen::CodeGenFunction &CGF,
15687330f729Sjoerg                                    const ObjCIvarDecl *IV) {
15697330f729Sjoerg     // Annotate the load as an invariant load iff inside an instance method
15707330f729Sjoerg     // and ivar belongs to instance method's class and one of its super class.
15717330f729Sjoerg     // This check is needed because the ivar offset is a lazily
15727330f729Sjoerg     // initialised value that may depend on objc_msgSend to perform a fixup on
15737330f729Sjoerg     // the first message dispatch.
15747330f729Sjoerg     //
15757330f729Sjoerg     // An additional opportunity to mark the load as invariant arises when the
15767330f729Sjoerg     // base of the ivar access is a parameter to an Objective C method.
15777330f729Sjoerg     // However, because the parameters are not available in the current
15787330f729Sjoerg     // interface, we cannot perform this check.
1579*e038c9c4Sjoerg     //
1580*e038c9c4Sjoerg     // Note that for direct methods, because objc_msgSend is skipped,
1581*e038c9c4Sjoerg     // and that the method may be inlined, this optimization actually
1582*e038c9c4Sjoerg     // can't be performed.
15837330f729Sjoerg     if (const ObjCMethodDecl *MD =
15847330f729Sjoerg           dyn_cast_or_null<ObjCMethodDecl>(CGF.CurFuncDecl))
1585*e038c9c4Sjoerg       if (MD->isInstanceMethod() && !MD->isDirectMethod())
15867330f729Sjoerg         if (const ObjCInterfaceDecl *ID = MD->getClassInterface())
15877330f729Sjoerg           return IV->getContainingInterface()->isSuperClassOf(ID);
15887330f729Sjoerg     return false;
15897330f729Sjoerg   }
15907330f729Sjoerg 
isClassLayoutKnownStatically(const ObjCInterfaceDecl * ID)15917330f729Sjoerg   bool isClassLayoutKnownStatically(const ObjCInterfaceDecl *ID) {
15927330f729Sjoerg     // NSObject is a fixed size. If we can see the @implementation of a class
15937330f729Sjoerg     // which inherits from NSObject then we know that all it's offsets also must
15947330f729Sjoerg     // be fixed. FIXME: Can we do this if see a chain of super classes with
15957330f729Sjoerg     // implementations leading to NSObject?
15967330f729Sjoerg     return ID->getImplementation() && ID->getSuperClass() &&
15977330f729Sjoerg            ID->getSuperClass()->getName() == "NSObject";
15987330f729Sjoerg   }
15997330f729Sjoerg 
16007330f729Sjoerg public:
16017330f729Sjoerg   CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
16027330f729Sjoerg 
16037330f729Sjoerg   llvm::Constant *getNSConstantStringClassRef() override;
16047330f729Sjoerg 
16057330f729Sjoerg   llvm::Function *ModuleInitFunction() override;
16067330f729Sjoerg 
16077330f729Sjoerg   CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
16087330f729Sjoerg                                       ReturnValueSlot Return,
16097330f729Sjoerg                                       QualType ResultType, Selector Sel,
16107330f729Sjoerg                                       llvm::Value *Receiver,
16117330f729Sjoerg                                       const CallArgList &CallArgs,
16127330f729Sjoerg                                       const ObjCInterfaceDecl *Class,
16137330f729Sjoerg                                       const ObjCMethodDecl *Method) override;
16147330f729Sjoerg 
16157330f729Sjoerg   CodeGen::RValue
16167330f729Sjoerg   GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
16177330f729Sjoerg                            ReturnValueSlot Return, QualType ResultType,
16187330f729Sjoerg                            Selector Sel, const ObjCInterfaceDecl *Class,
16197330f729Sjoerg                            bool isCategoryImpl, llvm::Value *Receiver,
16207330f729Sjoerg                            bool IsClassMessage, const CallArgList &CallArgs,
16217330f729Sjoerg                            const ObjCMethodDecl *Method) override;
16227330f729Sjoerg 
16237330f729Sjoerg   llvm::Value *GetClass(CodeGenFunction &CGF,
16247330f729Sjoerg                         const ObjCInterfaceDecl *ID) override;
16257330f729Sjoerg 
GetSelector(CodeGenFunction & CGF,Selector Sel)16267330f729Sjoerg   llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) override
16277330f729Sjoerg     { return EmitSelector(CGF, Sel); }
GetAddrOfSelector(CodeGenFunction & CGF,Selector Sel)16287330f729Sjoerg   Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override
1629*e038c9c4Sjoerg     { return EmitSelectorAddr(Sel); }
16307330f729Sjoerg 
16317330f729Sjoerg   /// The NeXT/Apple runtimes do not support typed selectors; just emit an
16327330f729Sjoerg   /// untyped one.
GetSelector(CodeGenFunction & CGF,const ObjCMethodDecl * Method)16337330f729Sjoerg   llvm::Value *GetSelector(CodeGenFunction &CGF,
16347330f729Sjoerg                            const ObjCMethodDecl *Method) override
16357330f729Sjoerg     { return EmitSelector(CGF, Method->getSelector()); }
16367330f729Sjoerg 
16377330f729Sjoerg   void GenerateCategory(const ObjCCategoryImplDecl *CMD) override;
16387330f729Sjoerg 
16397330f729Sjoerg   void GenerateClass(const ObjCImplementationDecl *ClassDecl) override;
16407330f729Sjoerg 
RegisterAlias(const ObjCCompatibleAliasDecl * OAD)16417330f729Sjoerg   void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) override {}
16427330f729Sjoerg 
16437330f729Sjoerg   llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
16447330f729Sjoerg                                    const ObjCProtocolDecl *PD) override;
16457330f729Sjoerg 
16467330f729Sjoerg   llvm::Constant *GetEHType(QualType T) override;
16477330f729Sjoerg 
GetPropertyGetFunction()16487330f729Sjoerg   llvm::FunctionCallee GetPropertyGetFunction() override {
16497330f729Sjoerg     return ObjCTypes.getGetPropertyFn();
16507330f729Sjoerg   }
GetPropertySetFunction()16517330f729Sjoerg   llvm::FunctionCallee GetPropertySetFunction() override {
16527330f729Sjoerg     return ObjCTypes.getSetPropertyFn();
16537330f729Sjoerg   }
16547330f729Sjoerg 
GetOptimizedPropertySetFunction(bool atomic,bool copy)16557330f729Sjoerg   llvm::FunctionCallee GetOptimizedPropertySetFunction(bool atomic,
16567330f729Sjoerg                                                        bool copy) override {
16577330f729Sjoerg     return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
16587330f729Sjoerg   }
16597330f729Sjoerg 
GetSetStructFunction()16607330f729Sjoerg   llvm::FunctionCallee GetSetStructFunction() override {
16617330f729Sjoerg     return ObjCTypes.getCopyStructFn();
16627330f729Sjoerg   }
16637330f729Sjoerg 
GetGetStructFunction()16647330f729Sjoerg   llvm::FunctionCallee GetGetStructFunction() override {
16657330f729Sjoerg     return ObjCTypes.getCopyStructFn();
16667330f729Sjoerg   }
16677330f729Sjoerg 
GetCppAtomicObjectSetFunction()16687330f729Sjoerg   llvm::FunctionCallee GetCppAtomicObjectSetFunction() override {
16697330f729Sjoerg     return ObjCTypes.getCppAtomicObjectFunction();
16707330f729Sjoerg   }
16717330f729Sjoerg 
GetCppAtomicObjectGetFunction()16727330f729Sjoerg   llvm::FunctionCallee GetCppAtomicObjectGetFunction() override {
16737330f729Sjoerg     return ObjCTypes.getCppAtomicObjectFunction();
16747330f729Sjoerg   }
16757330f729Sjoerg 
EnumerationMutationFunction()16767330f729Sjoerg   llvm::FunctionCallee EnumerationMutationFunction() override {
16777330f729Sjoerg     return ObjCTypes.getEnumerationMutationFn();
16787330f729Sjoerg   }
16797330f729Sjoerg 
16807330f729Sjoerg   void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
16817330f729Sjoerg                    const ObjCAtTryStmt &S) override;
16827330f729Sjoerg   void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
16837330f729Sjoerg                             const ObjCAtSynchronizedStmt &S) override;
16847330f729Sjoerg   void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S,
16857330f729Sjoerg                      bool ClearInsertionPoint=true) override;
16867330f729Sjoerg   llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
16877330f729Sjoerg                                  Address AddrWeakObj) override;
16887330f729Sjoerg   void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
16897330f729Sjoerg                           llvm::Value *src, Address edst) override;
16907330f729Sjoerg   void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
16917330f729Sjoerg                             llvm::Value *src, Address dest,
16927330f729Sjoerg                             bool threadlocal = false) override;
16937330f729Sjoerg   void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
16947330f729Sjoerg                           llvm::Value *src, Address dest,
16957330f729Sjoerg                           llvm::Value *ivarOffset) override;
16967330f729Sjoerg   void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
16977330f729Sjoerg                                 llvm::Value *src, Address dest) override;
16987330f729Sjoerg   void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
16997330f729Sjoerg                                 Address dest, Address src,
17007330f729Sjoerg                                 llvm::Value *size) override;
17017330f729Sjoerg   LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy,
17027330f729Sjoerg                               llvm::Value *BaseValue, const ObjCIvarDecl *Ivar,
17037330f729Sjoerg                               unsigned CVRQualifiers) override;
17047330f729Sjoerg   llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
17057330f729Sjoerg                               const ObjCInterfaceDecl *Interface,
17067330f729Sjoerg                               const ObjCIvarDecl *Ivar) override;
17077330f729Sjoerg };
17087330f729Sjoerg 
17097330f729Sjoerg /// A helper class for performing the null-initialization of a return
17107330f729Sjoerg /// value.
17117330f729Sjoerg struct NullReturnState {
17127330f729Sjoerg   llvm::BasicBlock *NullBB;
NullReturnState__anon0cc8f9a20111::NullReturnState17137330f729Sjoerg   NullReturnState() : NullBB(nullptr) {}
17147330f729Sjoerg 
17157330f729Sjoerg   /// Perform a null-check of the given receiver.
init__anon0cc8f9a20111::NullReturnState17167330f729Sjoerg   void init(CodeGenFunction &CGF, llvm::Value *receiver) {
17177330f729Sjoerg     // Make blocks for the null-receiver and call edges.
17187330f729Sjoerg     NullBB = CGF.createBasicBlock("msgSend.null-receiver");
17197330f729Sjoerg     llvm::BasicBlock *callBB = CGF.createBasicBlock("msgSend.call");
17207330f729Sjoerg 
17217330f729Sjoerg     // Check for a null receiver and, if there is one, jump to the
17227330f729Sjoerg     // null-receiver block.  There's no point in trying to avoid it:
17237330f729Sjoerg     // we're always going to put *something* there, because otherwise
17247330f729Sjoerg     // we shouldn't have done this null-check in the first place.
17257330f729Sjoerg     llvm::Value *isNull = CGF.Builder.CreateIsNull(receiver);
17267330f729Sjoerg     CGF.Builder.CreateCondBr(isNull, NullBB, callBB);
17277330f729Sjoerg 
17287330f729Sjoerg     // Otherwise, start performing the call.
17297330f729Sjoerg     CGF.EmitBlock(callBB);
17307330f729Sjoerg   }
17317330f729Sjoerg 
17327330f729Sjoerg   /// Complete the null-return operation.  It is valid to call this
17337330f729Sjoerg   /// regardless of whether 'init' has been called.
complete__anon0cc8f9a20111::NullReturnState17347330f729Sjoerg   RValue complete(CodeGenFunction &CGF,
17357330f729Sjoerg                   ReturnValueSlot returnSlot,
17367330f729Sjoerg                   RValue result,
17377330f729Sjoerg                   QualType resultType,
17387330f729Sjoerg                   const CallArgList &CallArgs,
17397330f729Sjoerg                   const ObjCMethodDecl *Method) {
17407330f729Sjoerg     // If we never had to do a null-check, just use the raw result.
17417330f729Sjoerg     if (!NullBB) return result;
17427330f729Sjoerg 
17437330f729Sjoerg     // The continuation block.  This will be left null if we don't have an
17447330f729Sjoerg     // IP, which can happen if the method we're calling is marked noreturn.
17457330f729Sjoerg     llvm::BasicBlock *contBB = nullptr;
17467330f729Sjoerg 
17477330f729Sjoerg     // Finish the call path.
17487330f729Sjoerg     llvm::BasicBlock *callBB = CGF.Builder.GetInsertBlock();
17497330f729Sjoerg     if (callBB) {
17507330f729Sjoerg       contBB = CGF.createBasicBlock("msgSend.cont");
17517330f729Sjoerg       CGF.Builder.CreateBr(contBB);
17527330f729Sjoerg     }
17537330f729Sjoerg 
17547330f729Sjoerg     // Okay, start emitting the null-receiver block.
17557330f729Sjoerg     CGF.EmitBlock(NullBB);
17567330f729Sjoerg 
17577330f729Sjoerg     // Release any consumed arguments we've got.
17587330f729Sjoerg     if (Method) {
17597330f729Sjoerg       CallArgList::const_iterator I = CallArgs.begin();
17607330f729Sjoerg       for (ObjCMethodDecl::param_const_iterator i = Method->param_begin(),
17617330f729Sjoerg            e = Method->param_end(); i != e; ++i, ++I) {
17627330f729Sjoerg         const ParmVarDecl *ParamDecl = (*i);
17637330f729Sjoerg         if (ParamDecl->hasAttr<NSConsumedAttr>()) {
17647330f729Sjoerg           RValue RV = I->getRValue(CGF);
17657330f729Sjoerg           assert(RV.isScalar() &&
17667330f729Sjoerg                  "NullReturnState::complete - arg not on object");
17677330f729Sjoerg           CGF.EmitARCRelease(RV.getScalarVal(), ARCImpreciseLifetime);
1768*e038c9c4Sjoerg         } else {
1769*e038c9c4Sjoerg           QualType QT = ParamDecl->getType();
1770*e038c9c4Sjoerg           auto *RT = QT->getAs<RecordType>();
1771*e038c9c4Sjoerg           if (RT && RT->getDecl()->isParamDestroyedInCallee()) {
1772*e038c9c4Sjoerg             RValue RV = I->getRValue(CGF);
1773*e038c9c4Sjoerg             QualType::DestructionKind DtorKind = QT.isDestructedType();
1774*e038c9c4Sjoerg             switch (DtorKind) {
1775*e038c9c4Sjoerg             case QualType::DK_cxx_destructor:
1776*e038c9c4Sjoerg               CGF.destroyCXXObject(CGF, RV.getAggregateAddress(), QT);
1777*e038c9c4Sjoerg               break;
1778*e038c9c4Sjoerg             case QualType::DK_nontrivial_c_struct:
1779*e038c9c4Sjoerg               CGF.destroyNonTrivialCStruct(CGF, RV.getAggregateAddress(), QT);
1780*e038c9c4Sjoerg               break;
1781*e038c9c4Sjoerg             default:
1782*e038c9c4Sjoerg               llvm_unreachable("unexpected dtor kind");
1783*e038c9c4Sjoerg               break;
1784*e038c9c4Sjoerg             }
1785*e038c9c4Sjoerg           }
17867330f729Sjoerg         }
17877330f729Sjoerg       }
17887330f729Sjoerg     }
17897330f729Sjoerg 
17907330f729Sjoerg     // The phi code below assumes that we haven't needed any control flow yet.
17917330f729Sjoerg     assert(CGF.Builder.GetInsertBlock() == NullBB);
17927330f729Sjoerg 
17937330f729Sjoerg     // If we've got a void return, just jump to the continuation block.
17947330f729Sjoerg     if (result.isScalar() && resultType->isVoidType()) {
17957330f729Sjoerg       // No jumps required if the message-send was noreturn.
17967330f729Sjoerg       if (contBB) CGF.EmitBlock(contBB);
17977330f729Sjoerg       return result;
17987330f729Sjoerg     }
17997330f729Sjoerg 
18007330f729Sjoerg     // If we've got a scalar return, build a phi.
18017330f729Sjoerg     if (result.isScalar()) {
18027330f729Sjoerg       // Derive the null-initialization value.
1803*e038c9c4Sjoerg       llvm::Value *null =
1804*e038c9c4Sjoerg           CGF.EmitFromMemory(CGF.CGM.EmitNullConstant(resultType), resultType);
18057330f729Sjoerg 
18067330f729Sjoerg       // If no join is necessary, just flow out.
18077330f729Sjoerg       if (!contBB) return RValue::get(null);
18087330f729Sjoerg 
18097330f729Sjoerg       // Otherwise, build a phi.
18107330f729Sjoerg       CGF.EmitBlock(contBB);
18117330f729Sjoerg       llvm::PHINode *phi = CGF.Builder.CreatePHI(null->getType(), 2);
18127330f729Sjoerg       phi->addIncoming(result.getScalarVal(), callBB);
18137330f729Sjoerg       phi->addIncoming(null, NullBB);
18147330f729Sjoerg       return RValue::get(phi);
18157330f729Sjoerg     }
18167330f729Sjoerg 
18177330f729Sjoerg     // If we've got an aggregate return, null the buffer out.
18187330f729Sjoerg     // FIXME: maybe we should be doing things differently for all the
18197330f729Sjoerg     // cases where the ABI has us returning (1) non-agg values in
18207330f729Sjoerg     // memory or (2) agg values in registers.
18217330f729Sjoerg     if (result.isAggregate()) {
18227330f729Sjoerg       assert(result.isAggregate() && "null init of non-aggregate result?");
18237330f729Sjoerg       if (!returnSlot.isUnused())
18247330f729Sjoerg         CGF.EmitNullInitialization(result.getAggregateAddress(), resultType);
18257330f729Sjoerg       if (contBB) CGF.EmitBlock(contBB);
18267330f729Sjoerg       return result;
18277330f729Sjoerg     }
18287330f729Sjoerg 
18297330f729Sjoerg     // Complex types.
18307330f729Sjoerg     CGF.EmitBlock(contBB);
18317330f729Sjoerg     CodeGenFunction::ComplexPairTy callResult = result.getComplexVal();
18327330f729Sjoerg 
18337330f729Sjoerg     // Find the scalar type and its zero value.
18347330f729Sjoerg     llvm::Type *scalarTy = callResult.first->getType();
18357330f729Sjoerg     llvm::Constant *scalarZero = llvm::Constant::getNullValue(scalarTy);
18367330f729Sjoerg 
18377330f729Sjoerg     // Build phis for both coordinates.
18387330f729Sjoerg     llvm::PHINode *real = CGF.Builder.CreatePHI(scalarTy, 2);
18397330f729Sjoerg     real->addIncoming(callResult.first, callBB);
18407330f729Sjoerg     real->addIncoming(scalarZero, NullBB);
18417330f729Sjoerg     llvm::PHINode *imag = CGF.Builder.CreatePHI(scalarTy, 2);
18427330f729Sjoerg     imag->addIncoming(callResult.second, callBB);
18437330f729Sjoerg     imag->addIncoming(scalarZero, NullBB);
18447330f729Sjoerg     return RValue::getComplex(real, imag);
18457330f729Sjoerg   }
18467330f729Sjoerg };
18477330f729Sjoerg 
18487330f729Sjoerg } // end anonymous namespace
18497330f729Sjoerg 
18507330f729Sjoerg /* *** Helper Functions *** */
18517330f729Sjoerg 
18527330f729Sjoerg /// getConstantGEP() - Help routine to construct simple GEPs.
getConstantGEP(llvm::LLVMContext & VMContext,llvm::GlobalVariable * C,unsigned idx0,unsigned idx1)18537330f729Sjoerg static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
18547330f729Sjoerg                                       llvm::GlobalVariable *C, unsigned idx0,
18557330f729Sjoerg                                       unsigned idx1) {
18567330f729Sjoerg   llvm::Value *Idxs[] = {
18577330f729Sjoerg     llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
18587330f729Sjoerg     llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
18597330f729Sjoerg   };
18607330f729Sjoerg   return llvm::ConstantExpr::getGetElementPtr(C->getValueType(), C, Idxs);
18617330f729Sjoerg }
18627330f729Sjoerg 
18637330f729Sjoerg /// hasObjCExceptionAttribute - Return true if this class or any super
18647330f729Sjoerg /// class has the __objc_exception__ attribute.
hasObjCExceptionAttribute(ASTContext & Context,const ObjCInterfaceDecl * OID)18657330f729Sjoerg static bool hasObjCExceptionAttribute(ASTContext &Context,
18667330f729Sjoerg                                       const ObjCInterfaceDecl *OID) {
18677330f729Sjoerg   if (OID->hasAttr<ObjCExceptionAttr>())
18687330f729Sjoerg     return true;
18697330f729Sjoerg   if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
18707330f729Sjoerg     return hasObjCExceptionAttribute(Context, Super);
18717330f729Sjoerg   return false;
18727330f729Sjoerg }
18737330f729Sjoerg 
18747330f729Sjoerg static llvm::GlobalValue::LinkageTypes
getLinkageTypeForObjCMetadata(CodeGenModule & CGM,StringRef Section)18757330f729Sjoerg getLinkageTypeForObjCMetadata(CodeGenModule &CGM, StringRef Section) {
18767330f729Sjoerg   if (CGM.getTriple().isOSBinFormatMachO() &&
18777330f729Sjoerg       (Section.empty() || Section.startswith("__DATA")))
18787330f729Sjoerg     return llvm::GlobalValue::InternalLinkage;
18797330f729Sjoerg   return llvm::GlobalValue::PrivateLinkage;
18807330f729Sjoerg }
18817330f729Sjoerg 
18827330f729Sjoerg /// A helper function to create an internal or private global variable.
18837330f729Sjoerg static llvm::GlobalVariable *
finishAndCreateGlobal(ConstantInitBuilder::StructBuilder & Builder,const llvm::Twine & Name,CodeGenModule & CGM)18847330f729Sjoerg finishAndCreateGlobal(ConstantInitBuilder::StructBuilder &Builder,
18857330f729Sjoerg                      const llvm::Twine &Name, CodeGenModule &CGM) {
18867330f729Sjoerg   std::string SectionName;
18877330f729Sjoerg   if (CGM.getTriple().isOSBinFormatMachO())
18887330f729Sjoerg     SectionName = "__DATA, __objc_const";
18897330f729Sjoerg   auto *GV = Builder.finishAndCreateGlobal(
18907330f729Sjoerg       Name, CGM.getPointerAlign(), /*constant*/ false,
18917330f729Sjoerg       getLinkageTypeForObjCMetadata(CGM, SectionName));
18927330f729Sjoerg   GV->setSection(SectionName);
18937330f729Sjoerg   return GV;
18947330f729Sjoerg }
18957330f729Sjoerg 
18967330f729Sjoerg /* *** CGObjCMac Public Interface *** */
18977330f729Sjoerg 
CGObjCMac(CodeGen::CodeGenModule & cgm)18987330f729Sjoerg CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
18997330f729Sjoerg                                                     ObjCTypes(cgm) {
19007330f729Sjoerg   ObjCABI = 1;
19017330f729Sjoerg   EmitImageInfo();
19027330f729Sjoerg }
19037330f729Sjoerg 
19047330f729Sjoerg /// GetClass - Return a reference to the class for the given interface
19057330f729Sjoerg /// decl.
GetClass(CodeGenFunction & CGF,const ObjCInterfaceDecl * ID)19067330f729Sjoerg llvm::Value *CGObjCMac::GetClass(CodeGenFunction &CGF,
19077330f729Sjoerg                                  const ObjCInterfaceDecl *ID) {
19087330f729Sjoerg   return EmitClassRef(CGF, ID);
19097330f729Sjoerg }
19107330f729Sjoerg 
19117330f729Sjoerg /// GetSelector - Return the pointer to the unique'd string for this selector.
GetSelector(CodeGenFunction & CGF,Selector Sel)19127330f729Sjoerg llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, Selector Sel) {
19137330f729Sjoerg   return EmitSelector(CGF, Sel);
19147330f729Sjoerg }
GetAddrOfSelector(CodeGenFunction & CGF,Selector Sel)19157330f729Sjoerg Address CGObjCMac::GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) {
1916*e038c9c4Sjoerg   return EmitSelectorAddr(Sel);
19177330f729Sjoerg }
GetSelector(CodeGenFunction & CGF,const ObjCMethodDecl * Method)19187330f729Sjoerg llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, const ObjCMethodDecl
19197330f729Sjoerg                                     *Method) {
19207330f729Sjoerg   return EmitSelector(CGF, Method->getSelector());
19217330f729Sjoerg }
19227330f729Sjoerg 
GetEHType(QualType T)19237330f729Sjoerg llvm::Constant *CGObjCMac::GetEHType(QualType T) {
19247330f729Sjoerg   if (T->isObjCIdType() ||
19257330f729Sjoerg       T->isObjCQualifiedIdType()) {
19267330f729Sjoerg     return CGM.GetAddrOfRTTIDescriptor(
19277330f729Sjoerg               CGM.getContext().getObjCIdRedefinitionType(), /*ForEH=*/true);
19287330f729Sjoerg   }
19297330f729Sjoerg   if (T->isObjCClassType() ||
19307330f729Sjoerg       T->isObjCQualifiedClassType()) {
19317330f729Sjoerg     return CGM.GetAddrOfRTTIDescriptor(
19327330f729Sjoerg              CGM.getContext().getObjCClassRedefinitionType(), /*ForEH=*/true);
19337330f729Sjoerg   }
19347330f729Sjoerg   if (T->isObjCObjectPointerType())
19357330f729Sjoerg     return CGM.GetAddrOfRTTIDescriptor(T,  /*ForEH=*/true);
19367330f729Sjoerg 
19377330f729Sjoerg   llvm_unreachable("asking for catch type for ObjC type in fragile runtime");
19387330f729Sjoerg }
19397330f729Sjoerg 
19407330f729Sjoerg /// Generate a constant CFString object.
19417330f729Sjoerg /*
19427330f729Sjoerg   struct __builtin_CFString {
19437330f729Sjoerg   const int *isa; // point to __CFConstantStringClassReference
19447330f729Sjoerg   int flags;
19457330f729Sjoerg   const char *str;
19467330f729Sjoerg   long length;
19477330f729Sjoerg   };
19487330f729Sjoerg */
19497330f729Sjoerg 
19507330f729Sjoerg /// or Generate a constant NSString object.
19517330f729Sjoerg /*
19527330f729Sjoerg    struct __builtin_NSString {
19537330f729Sjoerg      const int *isa; // point to __NSConstantStringClassReference
19547330f729Sjoerg      const char *str;
19557330f729Sjoerg      unsigned int length;
19567330f729Sjoerg    };
19577330f729Sjoerg */
19587330f729Sjoerg 
19597330f729Sjoerg ConstantAddress
GenerateConstantString(const StringLiteral * SL)19607330f729Sjoerg CGObjCCommonMac::GenerateConstantString(const StringLiteral *SL) {
19617330f729Sjoerg   return (!CGM.getLangOpts().NoConstantCFStrings
19627330f729Sjoerg             ? CGM.GetAddrOfConstantCFString(SL)
19637330f729Sjoerg             : GenerateConstantNSString(SL));
19647330f729Sjoerg }
19657330f729Sjoerg 
19667330f729Sjoerg static llvm::StringMapEntry<llvm::GlobalVariable *> &
GetConstantStringEntry(llvm::StringMap<llvm::GlobalVariable * > & Map,const StringLiteral * Literal,unsigned & StringLength)19677330f729Sjoerg GetConstantStringEntry(llvm::StringMap<llvm::GlobalVariable *> &Map,
19687330f729Sjoerg                        const StringLiteral *Literal, unsigned &StringLength) {
19697330f729Sjoerg   StringRef String = Literal->getString();
19707330f729Sjoerg   StringLength = String.size();
19717330f729Sjoerg   return *Map.insert(std::make_pair(String, nullptr)).first;
19727330f729Sjoerg }
19737330f729Sjoerg 
getNSConstantStringClassRef()19747330f729Sjoerg llvm::Constant *CGObjCMac::getNSConstantStringClassRef() {
19757330f729Sjoerg   if (llvm::Value *V = ConstantStringClassRef)
19767330f729Sjoerg     return cast<llvm::Constant>(V);
19777330f729Sjoerg 
19787330f729Sjoerg   auto &StringClass = CGM.getLangOpts().ObjCConstantStringClass;
19797330f729Sjoerg   std::string str =
19807330f729Sjoerg     StringClass.empty() ? "_NSConstantStringClassReference"
19817330f729Sjoerg                         : "_" + StringClass + "ClassReference";
19827330f729Sjoerg 
19837330f729Sjoerg   llvm::Type *PTy = llvm::ArrayType::get(CGM.IntTy, 0);
19847330f729Sjoerg   auto GV = CGM.CreateRuntimeVariable(PTy, str);
19857330f729Sjoerg   auto V = llvm::ConstantExpr::getBitCast(GV, CGM.IntTy->getPointerTo());
19867330f729Sjoerg   ConstantStringClassRef = V;
19877330f729Sjoerg   return V;
19887330f729Sjoerg }
19897330f729Sjoerg 
getNSConstantStringClassRef()19907330f729Sjoerg llvm::Constant *CGObjCNonFragileABIMac::getNSConstantStringClassRef() {
19917330f729Sjoerg   if (llvm::Value *V = ConstantStringClassRef)
19927330f729Sjoerg     return cast<llvm::Constant>(V);
19937330f729Sjoerg 
19947330f729Sjoerg   auto &StringClass = CGM.getLangOpts().ObjCConstantStringClass;
19957330f729Sjoerg   std::string str =
19967330f729Sjoerg     StringClass.empty() ? "OBJC_CLASS_$_NSConstantString"
19977330f729Sjoerg                         : "OBJC_CLASS_$_" + StringClass;
19987330f729Sjoerg   llvm::Constant *GV = GetClassGlobal(str, NotForDefinition);
19997330f729Sjoerg 
20007330f729Sjoerg   // Make sure the result is of the correct type.
20017330f729Sjoerg   auto V = llvm::ConstantExpr::getBitCast(GV, CGM.IntTy->getPointerTo());
20027330f729Sjoerg 
20037330f729Sjoerg   ConstantStringClassRef = V;
20047330f729Sjoerg   return V;
20057330f729Sjoerg }
20067330f729Sjoerg 
20077330f729Sjoerg ConstantAddress
GenerateConstantNSString(const StringLiteral * Literal)20087330f729Sjoerg CGObjCCommonMac::GenerateConstantNSString(const StringLiteral *Literal) {
20097330f729Sjoerg   unsigned StringLength = 0;
20107330f729Sjoerg   llvm::StringMapEntry<llvm::GlobalVariable *> &Entry =
20117330f729Sjoerg     GetConstantStringEntry(NSConstantStringMap, Literal, StringLength);
20127330f729Sjoerg 
20137330f729Sjoerg   if (auto *C = Entry.second)
20147330f729Sjoerg     return ConstantAddress(C, CharUnits::fromQuantity(C->getAlignment()));
20157330f729Sjoerg 
20167330f729Sjoerg   // If we don't already have it, get _NSConstantStringClassReference.
20177330f729Sjoerg   llvm::Constant *Class = getNSConstantStringClassRef();
20187330f729Sjoerg 
20197330f729Sjoerg   // If we don't already have it, construct the type for a constant NSString.
20207330f729Sjoerg   if (!NSConstantStringType) {
20217330f729Sjoerg     NSConstantStringType =
20227330f729Sjoerg       llvm::StructType::create({
20237330f729Sjoerg         CGM.Int32Ty->getPointerTo(),
20247330f729Sjoerg         CGM.Int8PtrTy,
20257330f729Sjoerg         CGM.IntTy
20267330f729Sjoerg       }, "struct.__builtin_NSString");
20277330f729Sjoerg   }
20287330f729Sjoerg 
20297330f729Sjoerg   ConstantInitBuilder Builder(CGM);
20307330f729Sjoerg   auto Fields = Builder.beginStruct(NSConstantStringType);
20317330f729Sjoerg 
20327330f729Sjoerg   // Class pointer.
20337330f729Sjoerg   Fields.add(Class);
20347330f729Sjoerg 
20357330f729Sjoerg   // String pointer.
20367330f729Sjoerg   llvm::Constant *C =
20377330f729Sjoerg     llvm::ConstantDataArray::getString(VMContext, Entry.first());
20387330f729Sjoerg 
20397330f729Sjoerg   llvm::GlobalValue::LinkageTypes Linkage = llvm::GlobalValue::PrivateLinkage;
20407330f729Sjoerg   bool isConstant = !CGM.getLangOpts().WritableStrings;
20417330f729Sjoerg 
20427330f729Sjoerg   auto *GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), isConstant,
20437330f729Sjoerg                                       Linkage, C, ".str");
20447330f729Sjoerg   GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
20457330f729Sjoerg   // Don't enforce the target's minimum global alignment, since the only use
20467330f729Sjoerg   // of the string is via this class initializer.
2047*e038c9c4Sjoerg   GV->setAlignment(llvm::Align(1));
20487330f729Sjoerg   Fields.addBitCast(GV, CGM.Int8PtrTy);
20497330f729Sjoerg 
20507330f729Sjoerg   // String length.
20517330f729Sjoerg   Fields.addInt(CGM.IntTy, StringLength);
20527330f729Sjoerg 
20537330f729Sjoerg   // The struct.
20547330f729Sjoerg   CharUnits Alignment = CGM.getPointerAlign();
20557330f729Sjoerg   GV = Fields.finishAndCreateGlobal("_unnamed_nsstring_", Alignment,
20567330f729Sjoerg                                     /*constant*/ true,
20577330f729Sjoerg                                     llvm::GlobalVariable::PrivateLinkage);
20587330f729Sjoerg   const char *NSStringSection = "__OBJC,__cstring_object,regular,no_dead_strip";
20597330f729Sjoerg   const char *NSStringNonFragileABISection =
20607330f729Sjoerg       "__DATA,__objc_stringobj,regular,no_dead_strip";
20617330f729Sjoerg   // FIXME. Fix section.
20627330f729Sjoerg   GV->setSection(CGM.getLangOpts().ObjCRuntime.isNonFragile()
20637330f729Sjoerg                      ? NSStringNonFragileABISection
20647330f729Sjoerg                      : NSStringSection);
20657330f729Sjoerg   Entry.second = GV;
20667330f729Sjoerg 
20677330f729Sjoerg   return ConstantAddress(GV, Alignment);
20687330f729Sjoerg }
20697330f729Sjoerg 
20707330f729Sjoerg enum {
20717330f729Sjoerg   kCFTaggedObjectID_Integer = (1 << 1) + 1
20727330f729Sjoerg };
20737330f729Sjoerg 
20747330f729Sjoerg /// Generates a message send where the super is the receiver.  This is
20757330f729Sjoerg /// a message send to self with special delivery semantics indicating
20767330f729Sjoerg /// which class's method should be called.
20777330f729Sjoerg 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)20787330f729Sjoerg CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
20797330f729Sjoerg                                     ReturnValueSlot Return,
20807330f729Sjoerg                                     QualType ResultType,
20817330f729Sjoerg                                     Selector Sel,
20827330f729Sjoerg                                     const ObjCInterfaceDecl *Class,
20837330f729Sjoerg                                     bool isCategoryImpl,
20847330f729Sjoerg                                     llvm::Value *Receiver,
20857330f729Sjoerg                                     bool IsClassMessage,
20867330f729Sjoerg                                     const CodeGen::CallArgList &CallArgs,
20877330f729Sjoerg                                     const ObjCMethodDecl *Method) {
20887330f729Sjoerg   // Create and init a super structure; this is a (receiver, class)
20897330f729Sjoerg   // pair we will pass to objc_msgSendSuper.
20907330f729Sjoerg   Address ObjCSuper =
20917330f729Sjoerg     CGF.CreateTempAlloca(ObjCTypes.SuperTy, CGF.getPointerAlign(),
20927330f729Sjoerg                          "objc_super");
20937330f729Sjoerg   llvm::Value *ReceiverAsObject =
20947330f729Sjoerg     CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
20957330f729Sjoerg   CGF.Builder.CreateStore(ReceiverAsObject,
20967330f729Sjoerg                           CGF.Builder.CreateStructGEP(ObjCSuper, 0));
20977330f729Sjoerg 
20987330f729Sjoerg   // If this is a class message the metaclass is passed as the target.
2099*e038c9c4Sjoerg   llvm::Type *ClassTyPtr = llvm::PointerType::getUnqual(ObjCTypes.ClassTy);
21007330f729Sjoerg   llvm::Value *Target;
21017330f729Sjoerg   if (IsClassMessage) {
21027330f729Sjoerg     if (isCategoryImpl) {
21037330f729Sjoerg       // Message sent to 'super' in a class method defined in a category
21047330f729Sjoerg       // implementation requires an odd treatment.
21057330f729Sjoerg       // If we are in a class method, we must retrieve the
21067330f729Sjoerg       // _metaclass_ for the current class, pointed at by
21077330f729Sjoerg       // the class's "isa" pointer.  The following assumes that
21087330f729Sjoerg       // isa" is the first ivar in a class (which it must be).
21097330f729Sjoerg       Target = EmitClassRef(CGF, Class->getSuperClass());
21107330f729Sjoerg       Target = CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, Target, 0);
2111*e038c9c4Sjoerg       Target = CGF.Builder.CreateAlignedLoad(ClassTyPtr, Target,
2112*e038c9c4Sjoerg                                              CGF.getPointerAlign());
21137330f729Sjoerg     } else {
21147330f729Sjoerg       llvm::Constant *MetaClassPtr = EmitMetaClassRef(Class);
21157330f729Sjoerg       llvm::Value *SuperPtr =
21167330f729Sjoerg           CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, MetaClassPtr, 1);
2117*e038c9c4Sjoerg       llvm::Value *Super = CGF.Builder.CreateAlignedLoad(ClassTyPtr, SuperPtr,
2118*e038c9c4Sjoerg                                                          CGF.getPointerAlign());
21197330f729Sjoerg       Target = Super;
21207330f729Sjoerg     }
21217330f729Sjoerg   } else if (isCategoryImpl)
21227330f729Sjoerg     Target = EmitClassRef(CGF, Class->getSuperClass());
21237330f729Sjoerg   else {
21247330f729Sjoerg     llvm::Value *ClassPtr = EmitSuperClassRef(Class);
21257330f729Sjoerg     ClassPtr = CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, ClassPtr, 1);
2126*e038c9c4Sjoerg     Target = CGF.Builder.CreateAlignedLoad(ClassTyPtr, ClassPtr,
2127*e038c9c4Sjoerg                                            CGF.getPointerAlign());
21287330f729Sjoerg   }
21297330f729Sjoerg   // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
21307330f729Sjoerg   // ObjCTypes types.
21317330f729Sjoerg   llvm::Type *ClassTy =
21327330f729Sjoerg     CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
21337330f729Sjoerg   Target = CGF.Builder.CreateBitCast(Target, ClassTy);
21347330f729Sjoerg   CGF.Builder.CreateStore(Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1));
2135*e038c9c4Sjoerg   return EmitMessageSend(CGF, Return, ResultType, Sel, ObjCSuper.getPointer(),
2136*e038c9c4Sjoerg                          ObjCTypes.SuperPtrCTy, true, CallArgs, Method, Class,
2137*e038c9c4Sjoerg                          ObjCTypes);
21387330f729Sjoerg }
21397330f729Sjoerg 
21407330f729Sjoerg /// 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)21417330f729Sjoerg CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
21427330f729Sjoerg                                                ReturnValueSlot Return,
21437330f729Sjoerg                                                QualType ResultType,
21447330f729Sjoerg                                                Selector Sel,
21457330f729Sjoerg                                                llvm::Value *Receiver,
21467330f729Sjoerg                                                const CallArgList &CallArgs,
21477330f729Sjoerg                                                const ObjCInterfaceDecl *Class,
21487330f729Sjoerg                                                const ObjCMethodDecl *Method) {
2149*e038c9c4Sjoerg   return EmitMessageSend(CGF, Return, ResultType, Sel, Receiver,
2150*e038c9c4Sjoerg                          CGF.getContext().getObjCIdType(), false, CallArgs,
2151*e038c9c4Sjoerg                          Method, Class, ObjCTypes);
21527330f729Sjoerg }
21537330f729Sjoerg 
isWeakLinkedClass(const ObjCInterfaceDecl * ID)21547330f729Sjoerg static bool isWeakLinkedClass(const ObjCInterfaceDecl *ID) {
21557330f729Sjoerg   do {
21567330f729Sjoerg     if (ID->isWeakImported())
21577330f729Sjoerg       return true;
21587330f729Sjoerg   } while ((ID = ID->getSuperClass()));
21597330f729Sjoerg 
21607330f729Sjoerg   return false;
21617330f729Sjoerg }
21627330f729Sjoerg 
21637330f729Sjoerg 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)21647330f729Sjoerg CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
21657330f729Sjoerg                                  ReturnValueSlot Return,
21667330f729Sjoerg                                  QualType ResultType,
2167*e038c9c4Sjoerg                                  Selector Sel,
21687330f729Sjoerg                                  llvm::Value *Arg0,
21697330f729Sjoerg                                  QualType Arg0Ty,
21707330f729Sjoerg                                  bool IsSuper,
21717330f729Sjoerg                                  const CallArgList &CallArgs,
21727330f729Sjoerg                                  const ObjCMethodDecl *Method,
21737330f729Sjoerg                                  const ObjCInterfaceDecl *ClassReceiver,
21747330f729Sjoerg                                  const ObjCCommonTypesHelper &ObjCTypes) {
2175*e038c9c4Sjoerg   CodeGenTypes &Types = CGM.getTypes();
2176*e038c9c4Sjoerg   auto selTy = CGF.getContext().getObjCSelType();
2177*e038c9c4Sjoerg   llvm::Value *SelValue;
2178*e038c9c4Sjoerg 
2179*e038c9c4Sjoerg   if (Method && Method->isDirectMethod()) {
2180*e038c9c4Sjoerg     // Direct methods will synthesize the proper `_cmd` internally,
2181*e038c9c4Sjoerg     // so just don't bother with setting the `_cmd` argument.
2182*e038c9c4Sjoerg     assert(!IsSuper);
2183*e038c9c4Sjoerg     SelValue = llvm::UndefValue::get(Types.ConvertType(selTy));
2184*e038c9c4Sjoerg   } else {
2185*e038c9c4Sjoerg     SelValue = GetSelector(CGF, Sel);
2186*e038c9c4Sjoerg   }
2187*e038c9c4Sjoerg 
21887330f729Sjoerg   CallArgList ActualArgs;
21897330f729Sjoerg   if (!IsSuper)
21907330f729Sjoerg     Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy);
21917330f729Sjoerg   ActualArgs.add(RValue::get(Arg0), Arg0Ty);
2192*e038c9c4Sjoerg   ActualArgs.add(RValue::get(SelValue), selTy);
21937330f729Sjoerg   ActualArgs.addFrom(CallArgs);
21947330f729Sjoerg 
21957330f729Sjoerg   // If we're calling a method, use the formal signature.
21967330f729Sjoerg   MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);
21977330f729Sjoerg 
21987330f729Sjoerg   if (Method)
21997330f729Sjoerg     assert(CGM.getContext().getCanonicalType(Method->getReturnType()) ==
22007330f729Sjoerg                CGM.getContext().getCanonicalType(ResultType) &&
22017330f729Sjoerg            "Result type mismatch!");
22027330f729Sjoerg 
22037330f729Sjoerg   bool ReceiverCanBeNull = true;
22047330f729Sjoerg 
22057330f729Sjoerg   // Super dispatch assumes that self is non-null; even the messenger
22067330f729Sjoerg   // doesn't have a null check internally.
22077330f729Sjoerg   if (IsSuper) {
22087330f729Sjoerg     ReceiverCanBeNull = false;
22097330f729Sjoerg 
22107330f729Sjoerg   // If this is a direct dispatch of a class method, check whether the class,
22117330f729Sjoerg   // or anything in its hierarchy, was weak-linked.
22127330f729Sjoerg   } else if (ClassReceiver && Method && Method->isClassMethod()) {
22137330f729Sjoerg     ReceiverCanBeNull = isWeakLinkedClass(ClassReceiver);
22147330f729Sjoerg 
22157330f729Sjoerg   // If we're emitting a method, and self is const (meaning just ARC, for now),
22167330f729Sjoerg   // and the receiver is a load of self, then self is a valid object.
22177330f729Sjoerg   } else if (auto CurMethod =
22187330f729Sjoerg                dyn_cast_or_null<ObjCMethodDecl>(CGF.CurCodeDecl)) {
22197330f729Sjoerg     auto Self = CurMethod->getSelfDecl();
22207330f729Sjoerg     if (Self->getType().isConstQualified()) {
22217330f729Sjoerg       if (auto LI = dyn_cast<llvm::LoadInst>(Arg0->stripPointerCasts())) {
22227330f729Sjoerg         llvm::Value *SelfAddr = CGF.GetAddrOfLocalVar(Self).getPointer();
22237330f729Sjoerg         if (SelfAddr == LI->getPointerOperand()) {
22247330f729Sjoerg           ReceiverCanBeNull = false;
22257330f729Sjoerg         }
22267330f729Sjoerg       }
22277330f729Sjoerg     }
22287330f729Sjoerg   }
22297330f729Sjoerg 
22307330f729Sjoerg   bool RequiresNullCheck = false;
22317330f729Sjoerg 
22327330f729Sjoerg   llvm::FunctionCallee Fn = nullptr;
2233*e038c9c4Sjoerg   if (Method && Method->isDirectMethod()) {
2234*e038c9c4Sjoerg     Fn = GenerateDirectMethod(Method, Method->getClassInterface());
2235*e038c9c4Sjoerg   } else if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) {
22367330f729Sjoerg     if (ReceiverCanBeNull) RequiresNullCheck = true;
22377330f729Sjoerg     Fn = (ObjCABI == 2) ?  ObjCTypes.getSendStretFn2(IsSuper)
22387330f729Sjoerg       : ObjCTypes.getSendStretFn(IsSuper);
22397330f729Sjoerg   } else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
22407330f729Sjoerg     Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
22417330f729Sjoerg       : ObjCTypes.getSendFpretFn(IsSuper);
22427330f729Sjoerg   } else if (CGM.ReturnTypeUsesFP2Ret(ResultType)) {
22437330f729Sjoerg     Fn = (ObjCABI == 2) ? ObjCTypes.getSendFp2RetFn2(IsSuper)
22447330f729Sjoerg       : ObjCTypes.getSendFp2retFn(IsSuper);
22457330f729Sjoerg   } else {
22467330f729Sjoerg     // arm64 uses objc_msgSend for stret methods and yet null receiver check
22477330f729Sjoerg     // must be made for it.
22487330f729Sjoerg     if (ReceiverCanBeNull && CGM.ReturnTypeUsesSRet(MSI.CallInfo))
22497330f729Sjoerg       RequiresNullCheck = true;
22507330f729Sjoerg     Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
22517330f729Sjoerg       : ObjCTypes.getSendFn(IsSuper);
22527330f729Sjoerg   }
22537330f729Sjoerg 
22547330f729Sjoerg   // Cast function to proper signature
22557330f729Sjoerg   llvm::Constant *BitcastFn = cast<llvm::Constant>(
22567330f729Sjoerg       CGF.Builder.CreateBitCast(Fn.getCallee(), MSI.MessengerType));
22577330f729Sjoerg 
22587330f729Sjoerg   // We don't need to emit a null check to zero out an indirect result if the
22597330f729Sjoerg   // result is ignored.
22607330f729Sjoerg   if (Return.isUnused())
22617330f729Sjoerg     RequiresNullCheck = false;
22627330f729Sjoerg 
22637330f729Sjoerg   // Emit a null-check if there's a consumed argument other than the receiver.
22647330f729Sjoerg   if (!RequiresNullCheck && CGM.getLangOpts().ObjCAutoRefCount && Method) {
22657330f729Sjoerg     for (const auto *ParamDecl : Method->parameters()) {
2266*e038c9c4Sjoerg       if (ParamDecl->isDestroyedInCallee()) {
22677330f729Sjoerg         RequiresNullCheck = true;
22687330f729Sjoerg         break;
22697330f729Sjoerg       }
22707330f729Sjoerg     }
22717330f729Sjoerg   }
22727330f729Sjoerg 
22737330f729Sjoerg   NullReturnState nullReturn;
22747330f729Sjoerg   if (RequiresNullCheck) {
22757330f729Sjoerg     nullReturn.init(CGF, Arg0);
22767330f729Sjoerg   }
22777330f729Sjoerg 
22787330f729Sjoerg   llvm::CallBase *CallSite;
22797330f729Sjoerg   CGCallee Callee = CGCallee::forDirect(BitcastFn);
22807330f729Sjoerg   RValue rvalue = CGF.EmitCall(MSI.CallInfo, Callee, Return, ActualArgs,
22817330f729Sjoerg                                &CallSite);
22827330f729Sjoerg 
22837330f729Sjoerg   // Mark the call as noreturn if the method is marked noreturn and the
22847330f729Sjoerg   // receiver cannot be null.
22857330f729Sjoerg   if (Method && Method->hasAttr<NoReturnAttr>() && !ReceiverCanBeNull) {
22867330f729Sjoerg     CallSite->setDoesNotReturn();
22877330f729Sjoerg   }
22887330f729Sjoerg 
22897330f729Sjoerg   return nullReturn.complete(CGF, Return, rvalue, ResultType, CallArgs,
22907330f729Sjoerg                              RequiresNullCheck ? Method : nullptr);
22917330f729Sjoerg }
22927330f729Sjoerg 
GetGCAttrTypeForType(ASTContext & Ctx,QualType FQT,bool pointee=false)22937330f729Sjoerg static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT,
22947330f729Sjoerg                                            bool pointee = false) {
22957330f729Sjoerg   // Note that GC qualification applies recursively to C pointer types
22967330f729Sjoerg   // that aren't otherwise decorated.  This is weird, but it's probably
22977330f729Sjoerg   // an intentional workaround to the unreliable placement of GC qualifiers.
22987330f729Sjoerg   if (FQT.isObjCGCStrong())
22997330f729Sjoerg     return Qualifiers::Strong;
23007330f729Sjoerg 
23017330f729Sjoerg   if (FQT.isObjCGCWeak())
23027330f729Sjoerg     return Qualifiers::Weak;
23037330f729Sjoerg 
23047330f729Sjoerg   if (auto ownership = FQT.getObjCLifetime()) {
23057330f729Sjoerg     // Ownership does not apply recursively to C pointer types.
23067330f729Sjoerg     if (pointee) return Qualifiers::GCNone;
23077330f729Sjoerg     switch (ownership) {
23087330f729Sjoerg     case Qualifiers::OCL_Weak: return Qualifiers::Weak;
23097330f729Sjoerg     case Qualifiers::OCL_Strong: return Qualifiers::Strong;
23107330f729Sjoerg     case Qualifiers::OCL_ExplicitNone: return Qualifiers::GCNone;
23117330f729Sjoerg     case Qualifiers::OCL_Autoreleasing: llvm_unreachable("autoreleasing ivar?");
23127330f729Sjoerg     case Qualifiers::OCL_None: llvm_unreachable("known nonzero");
23137330f729Sjoerg     }
23147330f729Sjoerg     llvm_unreachable("bad objc ownership");
23157330f729Sjoerg   }
23167330f729Sjoerg 
23177330f729Sjoerg   // Treat unqualified retainable pointers as strong.
23187330f729Sjoerg   if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
23197330f729Sjoerg     return Qualifiers::Strong;
23207330f729Sjoerg 
23217330f729Sjoerg   // Walk into C pointer types, but only in GC.
23227330f729Sjoerg   if (Ctx.getLangOpts().getGC() != LangOptions::NonGC) {
23237330f729Sjoerg     if (const PointerType *PT = FQT->getAs<PointerType>())
23247330f729Sjoerg       return GetGCAttrTypeForType(Ctx, PT->getPointeeType(), /*pointee*/ true);
23257330f729Sjoerg   }
23267330f729Sjoerg 
23277330f729Sjoerg   return Qualifiers::GCNone;
23287330f729Sjoerg }
23297330f729Sjoerg 
23307330f729Sjoerg namespace {
23317330f729Sjoerg   struct IvarInfo {
23327330f729Sjoerg     CharUnits Offset;
23337330f729Sjoerg     uint64_t SizeInWords;
IvarInfo__anon0cc8f9a20511::IvarInfo23347330f729Sjoerg     IvarInfo(CharUnits offset, uint64_t sizeInWords)
23357330f729Sjoerg       : Offset(offset), SizeInWords(sizeInWords) {}
23367330f729Sjoerg 
23377330f729Sjoerg     // Allow sorting based on byte pos.
operator <__anon0cc8f9a20511::IvarInfo23387330f729Sjoerg     bool operator<(const IvarInfo &other) const {
23397330f729Sjoerg       return Offset < other.Offset;
23407330f729Sjoerg     }
23417330f729Sjoerg   };
23427330f729Sjoerg 
23437330f729Sjoerg   /// A helper class for building GC layout strings.
23447330f729Sjoerg   class IvarLayoutBuilder {
23457330f729Sjoerg     CodeGenModule &CGM;
23467330f729Sjoerg 
23477330f729Sjoerg     /// The start of the layout.  Offsets will be relative to this value,
23487330f729Sjoerg     /// and entries less than this value will be silently discarded.
23497330f729Sjoerg     CharUnits InstanceBegin;
23507330f729Sjoerg 
23517330f729Sjoerg     /// The end of the layout.  Offsets will never exceed this value.
23527330f729Sjoerg     CharUnits InstanceEnd;
23537330f729Sjoerg 
23547330f729Sjoerg     /// Whether we're generating the strong layout or the weak layout.
23557330f729Sjoerg     bool ForStrongLayout;
23567330f729Sjoerg 
23577330f729Sjoerg     /// Whether the offsets in IvarsInfo might be out-of-order.
23587330f729Sjoerg     bool IsDisordered = false;
23597330f729Sjoerg 
23607330f729Sjoerg     llvm::SmallVector<IvarInfo, 8> IvarsInfo;
23617330f729Sjoerg 
23627330f729Sjoerg   public:
IvarLayoutBuilder(CodeGenModule & CGM,CharUnits instanceBegin,CharUnits instanceEnd,bool forStrongLayout)23637330f729Sjoerg     IvarLayoutBuilder(CodeGenModule &CGM, CharUnits instanceBegin,
23647330f729Sjoerg                       CharUnits instanceEnd, bool forStrongLayout)
23657330f729Sjoerg       : CGM(CGM), InstanceBegin(instanceBegin), InstanceEnd(instanceEnd),
23667330f729Sjoerg         ForStrongLayout(forStrongLayout) {
23677330f729Sjoerg     }
23687330f729Sjoerg 
23697330f729Sjoerg     void visitRecord(const RecordType *RT, CharUnits offset);
23707330f729Sjoerg 
23717330f729Sjoerg     template <class Iterator, class GetOffsetFn>
23727330f729Sjoerg     void visitAggregate(Iterator begin, Iterator end,
23737330f729Sjoerg                         CharUnits aggrOffset,
23747330f729Sjoerg                         const GetOffsetFn &getOffset);
23757330f729Sjoerg 
23767330f729Sjoerg     void visitField(const FieldDecl *field, CharUnits offset);
23777330f729Sjoerg 
23787330f729Sjoerg     /// Add the layout of a block implementation.
23797330f729Sjoerg     void visitBlock(const CGBlockInfo &blockInfo);
23807330f729Sjoerg 
23817330f729Sjoerg     /// Is there any information for an interesting bitmap?
hasBitmapData() const23827330f729Sjoerg     bool hasBitmapData() const { return !IvarsInfo.empty(); }
23837330f729Sjoerg 
23847330f729Sjoerg     llvm::Constant *buildBitmap(CGObjCCommonMac &CGObjC,
23857330f729Sjoerg                                 llvm::SmallVectorImpl<unsigned char> &buffer);
23867330f729Sjoerg 
dump(ArrayRef<unsigned char> buffer)23877330f729Sjoerg     static void dump(ArrayRef<unsigned char> buffer) {
23887330f729Sjoerg       const unsigned char *s = buffer.data();
23897330f729Sjoerg       for (unsigned i = 0, e = buffer.size(); i < e; i++)
23907330f729Sjoerg         if (!(s[i] & 0xf0))
23917330f729Sjoerg           printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
23927330f729Sjoerg         else
23937330f729Sjoerg           printf("0x%x%s",  s[i], s[i] != 0 ? ", " : "");
23947330f729Sjoerg       printf("\n");
23957330f729Sjoerg     }
23967330f729Sjoerg   };
23977330f729Sjoerg } // end anonymous namespace
23987330f729Sjoerg 
BuildGCBlockLayout(CodeGenModule & CGM,const CGBlockInfo & blockInfo)23997330f729Sjoerg llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
24007330f729Sjoerg                                                 const CGBlockInfo &blockInfo) {
24017330f729Sjoerg 
24027330f729Sjoerg   llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
24037330f729Sjoerg   if (CGM.getLangOpts().getGC() == LangOptions::NonGC)
24047330f729Sjoerg     return nullPtr;
24057330f729Sjoerg 
24067330f729Sjoerg   IvarLayoutBuilder builder(CGM, CharUnits::Zero(), blockInfo.BlockSize,
24077330f729Sjoerg                             /*for strong layout*/ true);
24087330f729Sjoerg 
24097330f729Sjoerg   builder.visitBlock(blockInfo);
24107330f729Sjoerg 
24117330f729Sjoerg   if (!builder.hasBitmapData())
24127330f729Sjoerg     return nullPtr;
24137330f729Sjoerg 
24147330f729Sjoerg   llvm::SmallVector<unsigned char, 32> buffer;
24157330f729Sjoerg   llvm::Constant *C = builder.buildBitmap(*this, buffer);
24167330f729Sjoerg   if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
24177330f729Sjoerg     printf("\n block variable layout for block: ");
24187330f729Sjoerg     builder.dump(buffer);
24197330f729Sjoerg   }
24207330f729Sjoerg 
24217330f729Sjoerg   return C;
24227330f729Sjoerg }
24237330f729Sjoerg 
visitBlock(const CGBlockInfo & blockInfo)24247330f729Sjoerg void IvarLayoutBuilder::visitBlock(const CGBlockInfo &blockInfo) {
24257330f729Sjoerg   // __isa is the first field in block descriptor and must assume by runtime's
24267330f729Sjoerg   // convention that it is GC'able.
24277330f729Sjoerg   IvarsInfo.push_back(IvarInfo(CharUnits::Zero(), 1));
24287330f729Sjoerg 
24297330f729Sjoerg   const BlockDecl *blockDecl = blockInfo.getBlockDecl();
24307330f729Sjoerg 
24317330f729Sjoerg   // Ignore the optional 'this' capture: C++ objects are not assumed
24327330f729Sjoerg   // to be GC'ed.
24337330f729Sjoerg 
24347330f729Sjoerg   CharUnits lastFieldOffset;
24357330f729Sjoerg 
24367330f729Sjoerg   // Walk the captured variables.
24377330f729Sjoerg   for (const auto &CI : blockDecl->captures()) {
24387330f729Sjoerg     const VarDecl *variable = CI.getVariable();
24397330f729Sjoerg     QualType type = variable->getType();
24407330f729Sjoerg 
24417330f729Sjoerg     const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
24427330f729Sjoerg 
24437330f729Sjoerg     // Ignore constant captures.
24447330f729Sjoerg     if (capture.isConstant()) continue;
24457330f729Sjoerg 
24467330f729Sjoerg     CharUnits fieldOffset = capture.getOffset();
24477330f729Sjoerg 
24487330f729Sjoerg     // Block fields are not necessarily ordered; if we detect that we're
24497330f729Sjoerg     // adding them out-of-order, make sure we sort later.
24507330f729Sjoerg     if (fieldOffset < lastFieldOffset)
24517330f729Sjoerg       IsDisordered = true;
24527330f729Sjoerg     lastFieldOffset = fieldOffset;
24537330f729Sjoerg 
24547330f729Sjoerg     // __block variables are passed by their descriptor address.
24557330f729Sjoerg     if (CI.isByRef()) {
24567330f729Sjoerg       IvarsInfo.push_back(IvarInfo(fieldOffset, /*size in words*/ 1));
24577330f729Sjoerg       continue;
24587330f729Sjoerg     }
24597330f729Sjoerg 
24607330f729Sjoerg     assert(!type->isArrayType() && "array variable should not be caught");
24617330f729Sjoerg     if (const RecordType *record = type->getAs<RecordType>()) {
24627330f729Sjoerg       visitRecord(record, fieldOffset);
24637330f729Sjoerg       continue;
24647330f729Sjoerg     }
24657330f729Sjoerg 
24667330f729Sjoerg     Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), type);
24677330f729Sjoerg 
24687330f729Sjoerg     if (GCAttr == Qualifiers::Strong) {
24697330f729Sjoerg       assert(CGM.getContext().getTypeSize(type)
24707330f729Sjoerg                 == CGM.getTarget().getPointerWidth(0));
24717330f729Sjoerg       IvarsInfo.push_back(IvarInfo(fieldOffset, /*size in words*/ 1));
24727330f729Sjoerg     }
24737330f729Sjoerg   }
24747330f729Sjoerg }
24757330f729Sjoerg 
24767330f729Sjoerg /// getBlockCaptureLifetime - This routine returns life time of the captured
24777330f729Sjoerg /// block variable for the purpose of block layout meta-data generation. FQT is
24787330f729Sjoerg /// the type of the variable captured in the block.
getBlockCaptureLifetime(QualType FQT,bool ByrefLayout)24797330f729Sjoerg Qualifiers::ObjCLifetime CGObjCCommonMac::getBlockCaptureLifetime(QualType FQT,
24807330f729Sjoerg                                                                   bool ByrefLayout) {
24817330f729Sjoerg   // If it has an ownership qualifier, we're done.
24827330f729Sjoerg   if (auto lifetime = FQT.getObjCLifetime())
24837330f729Sjoerg     return lifetime;
24847330f729Sjoerg 
24857330f729Sjoerg   // If it doesn't, and this is ARC, it has no ownership.
24867330f729Sjoerg   if (CGM.getLangOpts().ObjCAutoRefCount)
24877330f729Sjoerg     return Qualifiers::OCL_None;
24887330f729Sjoerg 
24897330f729Sjoerg   // In MRC, retainable pointers are owned by non-__block variables.
24907330f729Sjoerg   if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
24917330f729Sjoerg     return ByrefLayout ? Qualifiers::OCL_ExplicitNone : Qualifiers::OCL_Strong;
24927330f729Sjoerg 
24937330f729Sjoerg   return Qualifiers::OCL_None;
24947330f729Sjoerg }
24957330f729Sjoerg 
UpdateRunSkipBlockVars(bool IsByref,Qualifiers::ObjCLifetime LifeTime,CharUnits FieldOffset,CharUnits FieldSize)24967330f729Sjoerg void CGObjCCommonMac::UpdateRunSkipBlockVars(bool IsByref,
24977330f729Sjoerg                                              Qualifiers::ObjCLifetime LifeTime,
24987330f729Sjoerg                                              CharUnits FieldOffset,
24997330f729Sjoerg                                              CharUnits FieldSize) {
25007330f729Sjoerg   // __block variables are passed by their descriptor address.
25017330f729Sjoerg   if (IsByref)
25027330f729Sjoerg     RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_BYREF, FieldOffset,
25037330f729Sjoerg                                         FieldSize));
25047330f729Sjoerg   else if (LifeTime == Qualifiers::OCL_Strong)
25057330f729Sjoerg     RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset,
25067330f729Sjoerg                                         FieldSize));
25077330f729Sjoerg   else if (LifeTime == Qualifiers::OCL_Weak)
25087330f729Sjoerg     RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset,
25097330f729Sjoerg                                         FieldSize));
25107330f729Sjoerg   else if (LifeTime == Qualifiers::OCL_ExplicitNone)
25117330f729Sjoerg     RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset,
25127330f729Sjoerg                                         FieldSize));
25137330f729Sjoerg   else
25147330f729Sjoerg     RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES,
25157330f729Sjoerg                                         FieldOffset,
25167330f729Sjoerg                                         FieldSize));
25177330f729Sjoerg }
25187330f729Sjoerg 
BuildRCRecordLayout(const llvm::StructLayout * RecLayout,const RecordDecl * RD,ArrayRef<const FieldDecl * > RecFields,CharUnits BytePos,bool & HasUnion,bool ByrefLayout)25197330f729Sjoerg void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
25207330f729Sjoerg                                           const RecordDecl *RD,
25217330f729Sjoerg                                           ArrayRef<const FieldDecl*> RecFields,
25227330f729Sjoerg                                           CharUnits BytePos, bool &HasUnion,
25237330f729Sjoerg                                           bool ByrefLayout) {
25247330f729Sjoerg   bool IsUnion = (RD && RD->isUnion());
25257330f729Sjoerg   CharUnits MaxUnionSize = CharUnits::Zero();
25267330f729Sjoerg   const FieldDecl *MaxField = nullptr;
25277330f729Sjoerg   const FieldDecl *LastFieldBitfieldOrUnnamed = nullptr;
25287330f729Sjoerg   CharUnits MaxFieldOffset = CharUnits::Zero();
25297330f729Sjoerg   CharUnits LastBitfieldOrUnnamedOffset = CharUnits::Zero();
25307330f729Sjoerg 
25317330f729Sjoerg   if (RecFields.empty())
25327330f729Sjoerg     return;
25337330f729Sjoerg   unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
25347330f729Sjoerg 
25357330f729Sjoerg   for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
25367330f729Sjoerg     const FieldDecl *Field = RecFields[i];
25377330f729Sjoerg     // Note that 'i' here is actually the field index inside RD of Field,
25387330f729Sjoerg     // although this dependency is hidden.
25397330f729Sjoerg     const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
25407330f729Sjoerg     CharUnits FieldOffset =
25417330f729Sjoerg       CGM.getContext().toCharUnitsFromBits(RL.getFieldOffset(i));
25427330f729Sjoerg 
25437330f729Sjoerg     // Skip over unnamed or bitfields
25447330f729Sjoerg     if (!Field->getIdentifier() || Field->isBitField()) {
25457330f729Sjoerg       LastFieldBitfieldOrUnnamed = Field;
25467330f729Sjoerg       LastBitfieldOrUnnamedOffset = FieldOffset;
25477330f729Sjoerg       continue;
25487330f729Sjoerg     }
25497330f729Sjoerg 
25507330f729Sjoerg     LastFieldBitfieldOrUnnamed = nullptr;
25517330f729Sjoerg     QualType FQT = Field->getType();
25527330f729Sjoerg     if (FQT->isRecordType() || FQT->isUnionType()) {
25537330f729Sjoerg       if (FQT->isUnionType())
25547330f729Sjoerg         HasUnion = true;
25557330f729Sjoerg 
25567330f729Sjoerg       BuildRCBlockVarRecordLayout(FQT->getAs<RecordType>(),
25577330f729Sjoerg                                   BytePos + FieldOffset, HasUnion);
25587330f729Sjoerg       continue;
25597330f729Sjoerg     }
25607330f729Sjoerg 
25617330f729Sjoerg     if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
25627330f729Sjoerg       auto *CArray = cast<ConstantArrayType>(Array);
25637330f729Sjoerg       uint64_t ElCount = CArray->getSize().getZExtValue();
25647330f729Sjoerg       assert(CArray && "only array with known element size is supported");
25657330f729Sjoerg       FQT = CArray->getElementType();
25667330f729Sjoerg       while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
25677330f729Sjoerg         auto *CArray = cast<ConstantArrayType>(Array);
25687330f729Sjoerg         ElCount *= CArray->getSize().getZExtValue();
25697330f729Sjoerg         FQT = CArray->getElementType();
25707330f729Sjoerg       }
25717330f729Sjoerg       if (FQT->isRecordType() && ElCount) {
25727330f729Sjoerg         int OldIndex = RunSkipBlockVars.size() - 1;
2573*e038c9c4Sjoerg         auto *RT = FQT->castAs<RecordType>();
2574*e038c9c4Sjoerg         BuildRCBlockVarRecordLayout(RT, BytePos + FieldOffset, HasUnion);
25757330f729Sjoerg 
25767330f729Sjoerg         // Replicate layout information for each array element. Note that
25777330f729Sjoerg         // one element is already done.
25787330f729Sjoerg         uint64_t ElIx = 1;
25797330f729Sjoerg         for (int FirstIndex = RunSkipBlockVars.size() - 1 ;ElIx < ElCount; ElIx++) {
25807330f729Sjoerg           CharUnits Size = CGM.getContext().getTypeSizeInChars(RT);
25817330f729Sjoerg           for (int i = OldIndex+1; i <= FirstIndex; ++i)
25827330f729Sjoerg             RunSkipBlockVars.push_back(
25837330f729Sjoerg               RUN_SKIP(RunSkipBlockVars[i].opcode,
25847330f729Sjoerg               RunSkipBlockVars[i].block_var_bytepos + Size*ElIx,
25857330f729Sjoerg               RunSkipBlockVars[i].block_var_size));
25867330f729Sjoerg         }
25877330f729Sjoerg         continue;
25887330f729Sjoerg       }
25897330f729Sjoerg     }
25907330f729Sjoerg     CharUnits FieldSize = CGM.getContext().getTypeSizeInChars(Field->getType());
25917330f729Sjoerg     if (IsUnion) {
25927330f729Sjoerg       CharUnits UnionIvarSize = FieldSize;
25937330f729Sjoerg       if (UnionIvarSize > MaxUnionSize) {
25947330f729Sjoerg         MaxUnionSize = UnionIvarSize;
25957330f729Sjoerg         MaxField = Field;
25967330f729Sjoerg         MaxFieldOffset = FieldOffset;
25977330f729Sjoerg       }
25987330f729Sjoerg     } else {
25997330f729Sjoerg       UpdateRunSkipBlockVars(false,
26007330f729Sjoerg                              getBlockCaptureLifetime(FQT, ByrefLayout),
26017330f729Sjoerg                              BytePos + FieldOffset,
26027330f729Sjoerg                              FieldSize);
26037330f729Sjoerg     }
26047330f729Sjoerg   }
26057330f729Sjoerg 
26067330f729Sjoerg   if (LastFieldBitfieldOrUnnamed) {
26077330f729Sjoerg     if (LastFieldBitfieldOrUnnamed->isBitField()) {
26087330f729Sjoerg       // Last field was a bitfield. Must update the info.
26097330f729Sjoerg       uint64_t BitFieldSize
26107330f729Sjoerg         = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext());
26117330f729Sjoerg       unsigned UnsSize = (BitFieldSize / ByteSizeInBits) +
26127330f729Sjoerg                         ((BitFieldSize % ByteSizeInBits) != 0);
26137330f729Sjoerg       CharUnits Size = CharUnits::fromQuantity(UnsSize);
26147330f729Sjoerg       Size += LastBitfieldOrUnnamedOffset;
26157330f729Sjoerg       UpdateRunSkipBlockVars(false,
26167330f729Sjoerg                              getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(),
26177330f729Sjoerg                                                      ByrefLayout),
26187330f729Sjoerg                              BytePos + LastBitfieldOrUnnamedOffset,
26197330f729Sjoerg                              Size);
26207330f729Sjoerg     } else {
26217330f729Sjoerg       assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
26227330f729Sjoerg       // Last field was unnamed. Must update skip info.
26237330f729Sjoerg       CharUnits FieldSize
26247330f729Sjoerg         = CGM.getContext().getTypeSizeInChars(LastFieldBitfieldOrUnnamed->getType());
26257330f729Sjoerg       UpdateRunSkipBlockVars(false,
26267330f729Sjoerg                              getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(),
26277330f729Sjoerg                                                      ByrefLayout),
26287330f729Sjoerg                              BytePos + LastBitfieldOrUnnamedOffset,
26297330f729Sjoerg                              FieldSize);
26307330f729Sjoerg     }
26317330f729Sjoerg   }
26327330f729Sjoerg 
26337330f729Sjoerg   if (MaxField)
26347330f729Sjoerg     UpdateRunSkipBlockVars(false,
26357330f729Sjoerg                            getBlockCaptureLifetime(MaxField->getType(), ByrefLayout),
26367330f729Sjoerg                            BytePos + MaxFieldOffset,
26377330f729Sjoerg                            MaxUnionSize);
26387330f729Sjoerg }
26397330f729Sjoerg 
BuildRCBlockVarRecordLayout(const RecordType * RT,CharUnits BytePos,bool & HasUnion,bool ByrefLayout)26407330f729Sjoerg void CGObjCCommonMac::BuildRCBlockVarRecordLayout(const RecordType *RT,
26417330f729Sjoerg                                                   CharUnits BytePos,
26427330f729Sjoerg                                                   bool &HasUnion,
26437330f729Sjoerg                                                   bool ByrefLayout) {
26447330f729Sjoerg   const RecordDecl *RD = RT->getDecl();
26457330f729Sjoerg   SmallVector<const FieldDecl*, 16> Fields(RD->fields());
26467330f729Sjoerg   llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
26477330f729Sjoerg   const llvm::StructLayout *RecLayout =
26487330f729Sjoerg     CGM.getDataLayout().getStructLayout(cast<llvm::StructType>(Ty));
26497330f729Sjoerg 
26507330f729Sjoerg   BuildRCRecordLayout(RecLayout, RD, Fields, BytePos, HasUnion, ByrefLayout);
26517330f729Sjoerg }
26527330f729Sjoerg 
26537330f729Sjoerg /// InlineLayoutInstruction - This routine produce an inline instruction for the
26547330f729Sjoerg /// block variable layout if it can. If not, it returns 0. Rules are as follow:
26557330f729Sjoerg /// If ((uintptr_t) layout) < (1 << 12), the layout is inline. In the 64bit world,
26567330f729Sjoerg /// an inline layout of value 0x0000000000000xyz is interpreted as follows:
26577330f729Sjoerg /// x captured object pointers of BLOCK_LAYOUT_STRONG. Followed by
26587330f729Sjoerg /// y captured object of BLOCK_LAYOUT_BYREF. Followed by
26597330f729Sjoerg /// z captured object of BLOCK_LAYOUT_WEAK. If any of the above is missing, zero
26607330f729Sjoerg /// replaces it. For example, 0x00000x00 means x BLOCK_LAYOUT_STRONG and no
26617330f729Sjoerg /// BLOCK_LAYOUT_BYREF and no BLOCK_LAYOUT_WEAK objects are captured.
InlineLayoutInstruction(SmallVectorImpl<unsigned char> & Layout)26627330f729Sjoerg uint64_t CGObjCCommonMac::InlineLayoutInstruction(
26637330f729Sjoerg                                     SmallVectorImpl<unsigned char> &Layout) {
26647330f729Sjoerg   uint64_t Result = 0;
26657330f729Sjoerg   if (Layout.size() <= 3) {
26667330f729Sjoerg     unsigned size = Layout.size();
26677330f729Sjoerg     unsigned strong_word_count = 0, byref_word_count=0, weak_word_count=0;
26687330f729Sjoerg     unsigned char inst;
26697330f729Sjoerg     enum BLOCK_LAYOUT_OPCODE opcode ;
26707330f729Sjoerg     switch (size) {
26717330f729Sjoerg       case 3:
26727330f729Sjoerg         inst = Layout[0];
26737330f729Sjoerg         opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
26747330f729Sjoerg         if (opcode == BLOCK_LAYOUT_STRONG)
26757330f729Sjoerg           strong_word_count = (inst & 0xF)+1;
26767330f729Sjoerg         else
26777330f729Sjoerg           return 0;
26787330f729Sjoerg         inst = Layout[1];
26797330f729Sjoerg         opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
26807330f729Sjoerg         if (opcode == BLOCK_LAYOUT_BYREF)
26817330f729Sjoerg           byref_word_count = (inst & 0xF)+1;
26827330f729Sjoerg         else
26837330f729Sjoerg           return 0;
26847330f729Sjoerg         inst = Layout[2];
26857330f729Sjoerg         opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
26867330f729Sjoerg         if (opcode == BLOCK_LAYOUT_WEAK)
26877330f729Sjoerg           weak_word_count = (inst & 0xF)+1;
26887330f729Sjoerg         else
26897330f729Sjoerg           return 0;
26907330f729Sjoerg         break;
26917330f729Sjoerg 
26927330f729Sjoerg       case 2:
26937330f729Sjoerg         inst = Layout[0];
26947330f729Sjoerg         opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
26957330f729Sjoerg         if (opcode == BLOCK_LAYOUT_STRONG) {
26967330f729Sjoerg           strong_word_count = (inst & 0xF)+1;
26977330f729Sjoerg           inst = Layout[1];
26987330f729Sjoerg           opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
26997330f729Sjoerg           if (opcode == BLOCK_LAYOUT_BYREF)
27007330f729Sjoerg             byref_word_count = (inst & 0xF)+1;
27017330f729Sjoerg           else if (opcode == BLOCK_LAYOUT_WEAK)
27027330f729Sjoerg             weak_word_count = (inst & 0xF)+1;
27037330f729Sjoerg           else
27047330f729Sjoerg             return 0;
27057330f729Sjoerg         }
27067330f729Sjoerg         else if (opcode == BLOCK_LAYOUT_BYREF) {
27077330f729Sjoerg           byref_word_count = (inst & 0xF)+1;
27087330f729Sjoerg           inst = Layout[1];
27097330f729Sjoerg           opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
27107330f729Sjoerg           if (opcode == BLOCK_LAYOUT_WEAK)
27117330f729Sjoerg             weak_word_count = (inst & 0xF)+1;
27127330f729Sjoerg           else
27137330f729Sjoerg             return 0;
27147330f729Sjoerg         }
27157330f729Sjoerg         else
27167330f729Sjoerg           return 0;
27177330f729Sjoerg         break;
27187330f729Sjoerg 
27197330f729Sjoerg       case 1:
27207330f729Sjoerg         inst = Layout[0];
27217330f729Sjoerg         opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
27227330f729Sjoerg         if (opcode == BLOCK_LAYOUT_STRONG)
27237330f729Sjoerg           strong_word_count = (inst & 0xF)+1;
27247330f729Sjoerg         else if (opcode == BLOCK_LAYOUT_BYREF)
27257330f729Sjoerg           byref_word_count = (inst & 0xF)+1;
27267330f729Sjoerg         else if (opcode == BLOCK_LAYOUT_WEAK)
27277330f729Sjoerg           weak_word_count = (inst & 0xF)+1;
27287330f729Sjoerg         else
27297330f729Sjoerg           return 0;
27307330f729Sjoerg         break;
27317330f729Sjoerg 
27327330f729Sjoerg       default:
27337330f729Sjoerg         return 0;
27347330f729Sjoerg     }
27357330f729Sjoerg 
27367330f729Sjoerg     // Cannot inline when any of the word counts is 15. Because this is one less
27377330f729Sjoerg     // than the actual work count (so 15 means 16 actual word counts),
27387330f729Sjoerg     // and we can only display 0 thru 15 word counts.
27397330f729Sjoerg     if (strong_word_count == 16 || byref_word_count == 16 || weak_word_count == 16)
27407330f729Sjoerg       return 0;
27417330f729Sjoerg 
27427330f729Sjoerg     unsigned count =
27437330f729Sjoerg       (strong_word_count != 0) + (byref_word_count != 0) + (weak_word_count != 0);
27447330f729Sjoerg 
27457330f729Sjoerg     if (size == count) {
27467330f729Sjoerg       if (strong_word_count)
27477330f729Sjoerg         Result = strong_word_count;
27487330f729Sjoerg       Result <<= 4;
27497330f729Sjoerg       if (byref_word_count)
27507330f729Sjoerg         Result += byref_word_count;
27517330f729Sjoerg       Result <<= 4;
27527330f729Sjoerg       if (weak_word_count)
27537330f729Sjoerg         Result += weak_word_count;
27547330f729Sjoerg     }
27557330f729Sjoerg   }
27567330f729Sjoerg   return Result;
27577330f729Sjoerg }
27587330f729Sjoerg 
getBitmapBlockLayout(bool ComputeByrefLayout)27597330f729Sjoerg llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) {
27607330f729Sjoerg   llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
27617330f729Sjoerg   if (RunSkipBlockVars.empty())
27627330f729Sjoerg     return nullPtr;
27637330f729Sjoerg   unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0);
27647330f729Sjoerg   unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
27657330f729Sjoerg   unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
27667330f729Sjoerg 
27677330f729Sjoerg   // Sort on byte position; captures might not be allocated in order,
27687330f729Sjoerg   // and unions can do funny things.
27697330f729Sjoerg   llvm::array_pod_sort(RunSkipBlockVars.begin(), RunSkipBlockVars.end());
27707330f729Sjoerg   SmallVector<unsigned char, 16> Layout;
27717330f729Sjoerg 
27727330f729Sjoerg   unsigned size = RunSkipBlockVars.size();
27737330f729Sjoerg   for (unsigned i = 0; i < size; i++) {
27747330f729Sjoerg     enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode;
27757330f729Sjoerg     CharUnits start_byte_pos = RunSkipBlockVars[i].block_var_bytepos;
27767330f729Sjoerg     CharUnits end_byte_pos = start_byte_pos;
27777330f729Sjoerg     unsigned j = i+1;
27787330f729Sjoerg     while (j < size) {
27797330f729Sjoerg       if (opcode == RunSkipBlockVars[j].opcode) {
27807330f729Sjoerg         end_byte_pos = RunSkipBlockVars[j++].block_var_bytepos;
27817330f729Sjoerg         i++;
27827330f729Sjoerg       }
27837330f729Sjoerg       else
27847330f729Sjoerg         break;
27857330f729Sjoerg     }
27867330f729Sjoerg     CharUnits size_in_bytes =
27877330f729Sjoerg     end_byte_pos - start_byte_pos + RunSkipBlockVars[j-1].block_var_size;
27887330f729Sjoerg     if (j < size) {
27897330f729Sjoerg       CharUnits gap =
27907330f729Sjoerg       RunSkipBlockVars[j].block_var_bytepos -
27917330f729Sjoerg       RunSkipBlockVars[j-1].block_var_bytepos - RunSkipBlockVars[j-1].block_var_size;
27927330f729Sjoerg       size_in_bytes += gap;
27937330f729Sjoerg     }
27947330f729Sjoerg     CharUnits residue_in_bytes = CharUnits::Zero();
27957330f729Sjoerg     if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES) {
27967330f729Sjoerg       residue_in_bytes = size_in_bytes % WordSizeInBytes;
27977330f729Sjoerg       size_in_bytes -= residue_in_bytes;
27987330f729Sjoerg       opcode = BLOCK_LAYOUT_NON_OBJECT_WORDS;
27997330f729Sjoerg     }
28007330f729Sjoerg 
28017330f729Sjoerg     unsigned size_in_words = size_in_bytes.getQuantity() / WordSizeInBytes;
28027330f729Sjoerg     while (size_in_words >= 16) {
28037330f729Sjoerg       // Note that value in imm. is one less that the actual
28047330f729Sjoerg       // value. So, 0xf means 16 words follow!
28057330f729Sjoerg       unsigned char inst = (opcode << 4) | 0xf;
28067330f729Sjoerg       Layout.push_back(inst);
28077330f729Sjoerg       size_in_words -= 16;
28087330f729Sjoerg     }
28097330f729Sjoerg     if (size_in_words > 0) {
28107330f729Sjoerg       // Note that value in imm. is one less that the actual
28117330f729Sjoerg       // value. So, we subtract 1 away!
28127330f729Sjoerg       unsigned char inst = (opcode << 4) | (size_in_words-1);
28137330f729Sjoerg       Layout.push_back(inst);
28147330f729Sjoerg     }
28157330f729Sjoerg     if (residue_in_bytes > CharUnits::Zero()) {
28167330f729Sjoerg       unsigned char inst =
28177330f729Sjoerg       (BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) | (residue_in_bytes.getQuantity()-1);
28187330f729Sjoerg       Layout.push_back(inst);
28197330f729Sjoerg     }
28207330f729Sjoerg   }
28217330f729Sjoerg 
28227330f729Sjoerg   while (!Layout.empty()) {
28237330f729Sjoerg     unsigned char inst = Layout.back();
28247330f729Sjoerg     enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
28257330f729Sjoerg     if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES || opcode == BLOCK_LAYOUT_NON_OBJECT_WORDS)
28267330f729Sjoerg       Layout.pop_back();
28277330f729Sjoerg     else
28287330f729Sjoerg       break;
28297330f729Sjoerg   }
28307330f729Sjoerg 
28317330f729Sjoerg   uint64_t Result = InlineLayoutInstruction(Layout);
28327330f729Sjoerg   if (Result != 0) {
28337330f729Sjoerg     // Block variable layout instruction has been inlined.
28347330f729Sjoerg     if (CGM.getLangOpts().ObjCGCBitmapPrint) {
28357330f729Sjoerg       if (ComputeByrefLayout)
28367330f729Sjoerg         printf("\n Inline BYREF variable layout: ");
28377330f729Sjoerg       else
28387330f729Sjoerg         printf("\n Inline block variable layout: ");
28397330f729Sjoerg       printf("0x0%" PRIx64 "", Result);
28407330f729Sjoerg       if (auto numStrong = (Result & 0xF00) >> 8)
28417330f729Sjoerg         printf(", BL_STRONG:%d", (int) numStrong);
28427330f729Sjoerg       if (auto numByref = (Result & 0x0F0) >> 4)
28437330f729Sjoerg         printf(", BL_BYREF:%d", (int) numByref);
28447330f729Sjoerg       if (auto numWeak = (Result & 0x00F) >> 0)
28457330f729Sjoerg         printf(", BL_WEAK:%d", (int) numWeak);
28467330f729Sjoerg       printf(", BL_OPERATOR:0\n");
28477330f729Sjoerg     }
28487330f729Sjoerg     return llvm::ConstantInt::get(CGM.IntPtrTy, Result);
28497330f729Sjoerg   }
28507330f729Sjoerg 
28517330f729Sjoerg   unsigned char inst = (BLOCK_LAYOUT_OPERATOR << 4) | 0;
28527330f729Sjoerg   Layout.push_back(inst);
28537330f729Sjoerg   std::string BitMap;
28547330f729Sjoerg   for (unsigned i = 0, e = Layout.size(); i != e; i++)
28557330f729Sjoerg     BitMap += Layout[i];
28567330f729Sjoerg 
28577330f729Sjoerg   if (CGM.getLangOpts().ObjCGCBitmapPrint) {
28587330f729Sjoerg     if (ComputeByrefLayout)
28597330f729Sjoerg       printf("\n Byref variable layout: ");
28607330f729Sjoerg     else
28617330f729Sjoerg       printf("\n Block variable layout: ");
28627330f729Sjoerg     for (unsigned i = 0, e = BitMap.size(); i != e; i++) {
28637330f729Sjoerg       unsigned char inst = BitMap[i];
28647330f729Sjoerg       enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
28657330f729Sjoerg       unsigned delta = 1;
28667330f729Sjoerg       switch (opcode) {
28677330f729Sjoerg         case BLOCK_LAYOUT_OPERATOR:
28687330f729Sjoerg           printf("BL_OPERATOR:");
28697330f729Sjoerg           delta = 0;
28707330f729Sjoerg           break;
28717330f729Sjoerg         case BLOCK_LAYOUT_NON_OBJECT_BYTES:
28727330f729Sjoerg           printf("BL_NON_OBJECT_BYTES:");
28737330f729Sjoerg           break;
28747330f729Sjoerg         case BLOCK_LAYOUT_NON_OBJECT_WORDS:
28757330f729Sjoerg           printf("BL_NON_OBJECT_WORD:");
28767330f729Sjoerg           break;
28777330f729Sjoerg         case BLOCK_LAYOUT_STRONG:
28787330f729Sjoerg           printf("BL_STRONG:");
28797330f729Sjoerg           break;
28807330f729Sjoerg         case BLOCK_LAYOUT_BYREF:
28817330f729Sjoerg           printf("BL_BYREF:");
28827330f729Sjoerg           break;
28837330f729Sjoerg         case BLOCK_LAYOUT_WEAK:
28847330f729Sjoerg           printf("BL_WEAK:");
28857330f729Sjoerg           break;
28867330f729Sjoerg         case BLOCK_LAYOUT_UNRETAINED:
28877330f729Sjoerg           printf("BL_UNRETAINED:");
28887330f729Sjoerg           break;
28897330f729Sjoerg       }
28907330f729Sjoerg       // Actual value of word count is one more that what is in the imm.
28917330f729Sjoerg       // field of the instruction
28927330f729Sjoerg       printf("%d", (inst & 0xf) + delta);
28937330f729Sjoerg       if (i < e-1)
28947330f729Sjoerg         printf(", ");
28957330f729Sjoerg       else
28967330f729Sjoerg         printf("\n");
28977330f729Sjoerg     }
28987330f729Sjoerg   }
28997330f729Sjoerg 
29007330f729Sjoerg   auto *Entry = CreateCStringLiteral(BitMap, ObjCLabelType::ClassName,
29017330f729Sjoerg                                      /*ForceNonFragileABI=*/true,
29027330f729Sjoerg                                      /*NullTerminate=*/false);
29037330f729Sjoerg   return getConstantGEP(VMContext, Entry, 0, 0);
29047330f729Sjoerg }
29057330f729Sjoerg 
getBlockLayoutInfoString(const SmallVectorImpl<CGObjCCommonMac::RUN_SKIP> & RunSkipBlockVars,bool HasCopyDisposeHelpers)29067330f729Sjoerg static std::string getBlockLayoutInfoString(
29077330f729Sjoerg     const SmallVectorImpl<CGObjCCommonMac::RUN_SKIP> &RunSkipBlockVars,
29087330f729Sjoerg     bool HasCopyDisposeHelpers) {
29097330f729Sjoerg   std::string Str;
29107330f729Sjoerg   for (const CGObjCCommonMac::RUN_SKIP &R : RunSkipBlockVars) {
29117330f729Sjoerg     if (R.opcode == CGObjCCommonMac::BLOCK_LAYOUT_UNRETAINED) {
29127330f729Sjoerg       // Copy/dispose helpers don't have any information about
29137330f729Sjoerg       // __unsafe_unretained captures, so unconditionally concatenate a string.
29147330f729Sjoerg       Str += "u";
29157330f729Sjoerg     } else if (HasCopyDisposeHelpers) {
29167330f729Sjoerg       // Information about __strong, __weak, or byref captures has already been
29177330f729Sjoerg       // encoded into the names of the copy/dispose helpers. We have to add a
29187330f729Sjoerg       // string here only when the copy/dispose helpers aren't generated (which
29197330f729Sjoerg       // happens when the block is non-escaping).
29207330f729Sjoerg       continue;
29217330f729Sjoerg     } else {
29227330f729Sjoerg       switch (R.opcode) {
29237330f729Sjoerg       case CGObjCCommonMac::BLOCK_LAYOUT_STRONG:
29247330f729Sjoerg         Str += "s";
29257330f729Sjoerg         break;
29267330f729Sjoerg       case CGObjCCommonMac::BLOCK_LAYOUT_BYREF:
29277330f729Sjoerg         Str += "r";
29287330f729Sjoerg         break;
29297330f729Sjoerg       case CGObjCCommonMac::BLOCK_LAYOUT_WEAK:
29307330f729Sjoerg         Str += "w";
29317330f729Sjoerg         break;
29327330f729Sjoerg       default:
29337330f729Sjoerg         continue;
29347330f729Sjoerg       }
29357330f729Sjoerg     }
29367330f729Sjoerg     Str += llvm::to_string(R.block_var_bytepos.getQuantity());
29377330f729Sjoerg     Str += "l" + llvm::to_string(R.block_var_size.getQuantity());
29387330f729Sjoerg   }
29397330f729Sjoerg   return Str;
29407330f729Sjoerg }
29417330f729Sjoerg 
fillRunSkipBlockVars(CodeGenModule & CGM,const CGBlockInfo & blockInfo)29427330f729Sjoerg void CGObjCCommonMac::fillRunSkipBlockVars(CodeGenModule &CGM,
29437330f729Sjoerg                                            const CGBlockInfo &blockInfo) {
29447330f729Sjoerg   assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
29457330f729Sjoerg 
29467330f729Sjoerg   RunSkipBlockVars.clear();
29477330f729Sjoerg   bool hasUnion = false;
29487330f729Sjoerg 
29497330f729Sjoerg   unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0);
29507330f729Sjoerg   unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
29517330f729Sjoerg   unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
29527330f729Sjoerg 
29537330f729Sjoerg   const BlockDecl *blockDecl = blockInfo.getBlockDecl();
29547330f729Sjoerg 
29557330f729Sjoerg   // Calculate the basic layout of the block structure.
29567330f729Sjoerg   const llvm::StructLayout *layout =
29577330f729Sjoerg   CGM.getDataLayout().getStructLayout(blockInfo.StructureType);
29587330f729Sjoerg 
29597330f729Sjoerg   // Ignore the optional 'this' capture: C++ objects are not assumed
29607330f729Sjoerg   // to be GC'ed.
29617330f729Sjoerg   if (blockInfo.BlockHeaderForcedGapSize != CharUnits::Zero())
29627330f729Sjoerg     UpdateRunSkipBlockVars(false, Qualifiers::OCL_None,
29637330f729Sjoerg                            blockInfo.BlockHeaderForcedGapOffset,
29647330f729Sjoerg                            blockInfo.BlockHeaderForcedGapSize);
29657330f729Sjoerg   // Walk the captured variables.
29667330f729Sjoerg   for (const auto &CI : blockDecl->captures()) {
29677330f729Sjoerg     const VarDecl *variable = CI.getVariable();
29687330f729Sjoerg     QualType type = variable->getType();
29697330f729Sjoerg 
29707330f729Sjoerg     const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
29717330f729Sjoerg 
29727330f729Sjoerg     // Ignore constant captures.
29737330f729Sjoerg     if (capture.isConstant()) continue;
29747330f729Sjoerg 
29757330f729Sjoerg     CharUnits fieldOffset =
29767330f729Sjoerg        CharUnits::fromQuantity(layout->getElementOffset(capture.getIndex()));
29777330f729Sjoerg 
29787330f729Sjoerg     assert(!type->isArrayType() && "array variable should not be caught");
29797330f729Sjoerg     if (!CI.isByRef())
29807330f729Sjoerg       if (const RecordType *record = type->getAs<RecordType>()) {
29817330f729Sjoerg         BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion);
29827330f729Sjoerg         continue;
29837330f729Sjoerg       }
29847330f729Sjoerg     CharUnits fieldSize;
29857330f729Sjoerg     if (CI.isByRef())
29867330f729Sjoerg       fieldSize = CharUnits::fromQuantity(WordSizeInBytes);
29877330f729Sjoerg     else
29887330f729Sjoerg       fieldSize = CGM.getContext().getTypeSizeInChars(type);
29897330f729Sjoerg     UpdateRunSkipBlockVars(CI.isByRef(), getBlockCaptureLifetime(type, false),
29907330f729Sjoerg                            fieldOffset, fieldSize);
29917330f729Sjoerg   }
29927330f729Sjoerg }
29937330f729Sjoerg 
29947330f729Sjoerg llvm::Constant *
BuildRCBlockLayout(CodeGenModule & CGM,const CGBlockInfo & blockInfo)29957330f729Sjoerg CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM,
29967330f729Sjoerg                                     const CGBlockInfo &blockInfo) {
29977330f729Sjoerg   fillRunSkipBlockVars(CGM, blockInfo);
29987330f729Sjoerg   return getBitmapBlockLayout(false);
29997330f729Sjoerg }
30007330f729Sjoerg 
getRCBlockLayoutStr(CodeGenModule & CGM,const CGBlockInfo & blockInfo)30017330f729Sjoerg std::string CGObjCCommonMac::getRCBlockLayoutStr(CodeGenModule &CGM,
30027330f729Sjoerg                                                  const CGBlockInfo &blockInfo) {
30037330f729Sjoerg   fillRunSkipBlockVars(CGM, blockInfo);
30047330f729Sjoerg   return getBlockLayoutInfoString(RunSkipBlockVars,
30057330f729Sjoerg                                   blockInfo.needsCopyDisposeHelpers());
30067330f729Sjoerg }
30077330f729Sjoerg 
BuildByrefLayout(CodeGen::CodeGenModule & CGM,QualType T)30087330f729Sjoerg llvm::Constant *CGObjCCommonMac::BuildByrefLayout(CodeGen::CodeGenModule &CGM,
30097330f729Sjoerg                                                   QualType T) {
30107330f729Sjoerg   assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
30117330f729Sjoerg   assert(!T->isArrayType() && "__block array variable should not be caught");
30127330f729Sjoerg   CharUnits fieldOffset;
30137330f729Sjoerg   RunSkipBlockVars.clear();
30147330f729Sjoerg   bool hasUnion = false;
30157330f729Sjoerg   if (const RecordType *record = T->getAs<RecordType>()) {
30167330f729Sjoerg     BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion, true /*ByrefLayout */);
30177330f729Sjoerg     llvm::Constant *Result = getBitmapBlockLayout(true);
30187330f729Sjoerg     if (isa<llvm::ConstantInt>(Result))
30197330f729Sjoerg       Result = llvm::ConstantExpr::getIntToPtr(Result, CGM.Int8PtrTy);
30207330f729Sjoerg     return Result;
30217330f729Sjoerg   }
30227330f729Sjoerg   llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
30237330f729Sjoerg   return nullPtr;
30247330f729Sjoerg }
30257330f729Sjoerg 
GenerateProtocolRef(CodeGenFunction & CGF,const ObjCProtocolDecl * PD)30267330f729Sjoerg llvm::Value *CGObjCMac::GenerateProtocolRef(CodeGenFunction &CGF,
30277330f729Sjoerg                                             const ObjCProtocolDecl *PD) {
30287330f729Sjoerg   // FIXME: I don't understand why gcc generates this, or where it is
30297330f729Sjoerg   // resolved. Investigate. Its also wasteful to look this up over and over.
30307330f729Sjoerg   LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
30317330f729Sjoerg 
30327330f729Sjoerg   return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
30337330f729Sjoerg                                         ObjCTypes.getExternalProtocolPtrTy());
30347330f729Sjoerg }
30357330f729Sjoerg 
GenerateProtocol(const ObjCProtocolDecl * PD)30367330f729Sjoerg void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
30377330f729Sjoerg   // FIXME: We shouldn't need this, the protocol decl should contain enough
30387330f729Sjoerg   // information to tell us whether this was a declaration or a definition.
30397330f729Sjoerg   DefinedProtocols.insert(PD->getIdentifier());
30407330f729Sjoerg 
30417330f729Sjoerg   // If we have generated a forward reference to this protocol, emit
30427330f729Sjoerg   // it now. Otherwise do nothing, the protocol objects are lazily
30437330f729Sjoerg   // emitted.
30447330f729Sjoerg   if (Protocols.count(PD->getIdentifier()))
30457330f729Sjoerg     GetOrEmitProtocol(PD);
30467330f729Sjoerg }
30477330f729Sjoerg 
GetProtocolRef(const ObjCProtocolDecl * PD)30487330f729Sjoerg llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
30497330f729Sjoerg   if (DefinedProtocols.count(PD->getIdentifier()))
30507330f729Sjoerg     return GetOrEmitProtocol(PD);
30517330f729Sjoerg 
30527330f729Sjoerg   return GetOrEmitProtocolRef(PD);
30537330f729Sjoerg }
30547330f729Sjoerg 
EmitClassRefViaRuntime(CodeGenFunction & CGF,const ObjCInterfaceDecl * ID,ObjCCommonTypesHelper & ObjCTypes)30557330f729Sjoerg llvm::Value *CGObjCCommonMac::EmitClassRefViaRuntime(
30567330f729Sjoerg                CodeGenFunction &CGF,
30577330f729Sjoerg                const ObjCInterfaceDecl *ID,
30587330f729Sjoerg                ObjCCommonTypesHelper &ObjCTypes) {
30597330f729Sjoerg   llvm::FunctionCallee lookUpClassFn = ObjCTypes.getLookUpClassFn();
30607330f729Sjoerg 
3061*e038c9c4Sjoerg   llvm::Value *className = CGF.CGM
3062*e038c9c4Sjoerg                                .GetAddrOfConstantCString(std::string(
3063*e038c9c4Sjoerg                                    ID->getObjCRuntimeNameAsString()))
30647330f729Sjoerg                                .getPointer();
30657330f729Sjoerg   ASTContext &ctx = CGF.CGM.getContext();
30667330f729Sjoerg   className =
30677330f729Sjoerg       CGF.Builder.CreateBitCast(className,
30687330f729Sjoerg                                 CGF.ConvertType(
30697330f729Sjoerg                                   ctx.getPointerType(ctx.CharTy.withConst())));
30707330f729Sjoerg   llvm::CallInst *call = CGF.Builder.CreateCall(lookUpClassFn, className);
30717330f729Sjoerg   call->setDoesNotThrow();
30727330f729Sjoerg   return call;
30737330f729Sjoerg }
30747330f729Sjoerg 
30757330f729Sjoerg /*
30767330f729Sjoerg // Objective-C 1.0 extensions
30777330f729Sjoerg struct _objc_protocol {
30787330f729Sjoerg struct _objc_protocol_extension *isa;
30797330f729Sjoerg char *protocol_name;
30807330f729Sjoerg struct _objc_protocol_list *protocol_list;
30817330f729Sjoerg struct _objc__method_prototype_list *instance_methods;
30827330f729Sjoerg struct _objc__method_prototype_list *class_methods
30837330f729Sjoerg };
30847330f729Sjoerg 
30857330f729Sjoerg See EmitProtocolExtension().
30867330f729Sjoerg */
GetOrEmitProtocol(const ObjCProtocolDecl * PD)30877330f729Sjoerg llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
30887330f729Sjoerg   llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
30897330f729Sjoerg 
30907330f729Sjoerg   // Early exit if a defining object has already been generated.
30917330f729Sjoerg   if (Entry && Entry->hasInitializer())
30927330f729Sjoerg     return Entry;
30937330f729Sjoerg 
30947330f729Sjoerg   // Use the protocol definition, if there is one.
30957330f729Sjoerg   if (const ObjCProtocolDecl *Def = PD->getDefinition())
30967330f729Sjoerg     PD = Def;
30977330f729Sjoerg 
30987330f729Sjoerg   // FIXME: I don't understand why gcc generates this, or where it is
30997330f729Sjoerg   // resolved. Investigate. Its also wasteful to look this up over and over.
31007330f729Sjoerg   LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
31017330f729Sjoerg 
31027330f729Sjoerg   // Construct method lists.
31037330f729Sjoerg   auto methodLists = ProtocolMethodLists::get(PD);
31047330f729Sjoerg 
31057330f729Sjoerg   ConstantInitBuilder builder(CGM);
31067330f729Sjoerg   auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
31077330f729Sjoerg   values.add(EmitProtocolExtension(PD, methodLists));
31087330f729Sjoerg   values.add(GetClassName(PD->getObjCRuntimeNameAsString()));
31097330f729Sjoerg   values.add(EmitProtocolList("OBJC_PROTOCOL_REFS_" + PD->getName(),
31107330f729Sjoerg                               PD->protocol_begin(), PD->protocol_end()));
31117330f729Sjoerg   values.add(methodLists.emitMethodList(this, PD,
31127330f729Sjoerg                               ProtocolMethodLists::RequiredInstanceMethods));
31137330f729Sjoerg   values.add(methodLists.emitMethodList(this, PD,
31147330f729Sjoerg                               ProtocolMethodLists::RequiredClassMethods));
31157330f729Sjoerg 
31167330f729Sjoerg   if (Entry) {
31177330f729Sjoerg     // Already created, update the initializer.
31187330f729Sjoerg     assert(Entry->hasPrivateLinkage());
31197330f729Sjoerg     values.finishAndSetAsInitializer(Entry);
31207330f729Sjoerg   } else {
31217330f729Sjoerg     Entry = values.finishAndCreateGlobal("OBJC_PROTOCOL_" + PD->getName(),
31227330f729Sjoerg                                          CGM.getPointerAlign(),
31237330f729Sjoerg                                          /*constant*/ false,
31247330f729Sjoerg                                          llvm::GlobalValue::PrivateLinkage);
31257330f729Sjoerg     Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
31267330f729Sjoerg 
31277330f729Sjoerg     Protocols[PD->getIdentifier()] = Entry;
31287330f729Sjoerg   }
31297330f729Sjoerg   CGM.addCompilerUsedGlobal(Entry);
31307330f729Sjoerg 
31317330f729Sjoerg   return Entry;
31327330f729Sjoerg }
31337330f729Sjoerg 
GetOrEmitProtocolRef(const ObjCProtocolDecl * PD)31347330f729Sjoerg llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
31357330f729Sjoerg   llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
31367330f729Sjoerg 
31377330f729Sjoerg   if (!Entry) {
31387330f729Sjoerg     // We use the initializer as a marker of whether this is a forward
31397330f729Sjoerg     // reference or not. At module finalization we add the empty
31407330f729Sjoerg     // contents for protocols which were referenced but never defined.
31417330f729Sjoerg     Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy,
31427330f729Sjoerg                                      false, llvm::GlobalValue::PrivateLinkage,
31437330f729Sjoerg                                      nullptr, "OBJC_PROTOCOL_" + PD->getName());
31447330f729Sjoerg     Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
31457330f729Sjoerg     // FIXME: Is this necessary? Why only for protocol?
31467330f729Sjoerg     Entry->setAlignment(llvm::Align(4));
31477330f729Sjoerg   }
31487330f729Sjoerg 
31497330f729Sjoerg   return Entry;
31507330f729Sjoerg }
31517330f729Sjoerg 
31527330f729Sjoerg /*
31537330f729Sjoerg   struct _objc_protocol_extension {
31547330f729Sjoerg   uint32_t size;
31557330f729Sjoerg   struct objc_method_description_list *optional_instance_methods;
31567330f729Sjoerg   struct objc_method_description_list *optional_class_methods;
31577330f729Sjoerg   struct objc_property_list *instance_properties;
31587330f729Sjoerg   const char ** extendedMethodTypes;
31597330f729Sjoerg   struct objc_property_list *class_properties;
31607330f729Sjoerg   };
31617330f729Sjoerg */
31627330f729Sjoerg llvm::Constant *
EmitProtocolExtension(const ObjCProtocolDecl * PD,const ProtocolMethodLists & methodLists)31637330f729Sjoerg CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
31647330f729Sjoerg                                  const ProtocolMethodLists &methodLists) {
31657330f729Sjoerg   auto optInstanceMethods =
31667330f729Sjoerg     methodLists.emitMethodList(this, PD,
31677330f729Sjoerg                                ProtocolMethodLists::OptionalInstanceMethods);
31687330f729Sjoerg   auto optClassMethods =
31697330f729Sjoerg     methodLists.emitMethodList(this, PD,
31707330f729Sjoerg                                ProtocolMethodLists::OptionalClassMethods);
31717330f729Sjoerg 
31727330f729Sjoerg   auto extendedMethodTypes =
31737330f729Sjoerg     EmitProtocolMethodTypes("OBJC_PROTOCOL_METHOD_TYPES_" + PD->getName(),
31747330f729Sjoerg                             methodLists.emitExtendedTypesArray(this),
31757330f729Sjoerg                             ObjCTypes);
31767330f729Sjoerg 
31777330f729Sjoerg   auto instanceProperties =
31787330f729Sjoerg     EmitPropertyList("OBJC_$_PROP_PROTO_LIST_" + PD->getName(), nullptr, PD,
31797330f729Sjoerg                      ObjCTypes, false);
31807330f729Sjoerg   auto classProperties =
31817330f729Sjoerg     EmitPropertyList("OBJC_$_CLASS_PROP_PROTO_LIST_" + PD->getName(), nullptr,
31827330f729Sjoerg                      PD, ObjCTypes, true);
31837330f729Sjoerg 
31847330f729Sjoerg   // Return null if no extension bits are used.
31857330f729Sjoerg   if (optInstanceMethods->isNullValue() &&
31867330f729Sjoerg       optClassMethods->isNullValue() &&
31877330f729Sjoerg       extendedMethodTypes->isNullValue() &&
31887330f729Sjoerg       instanceProperties->isNullValue() &&
31897330f729Sjoerg       classProperties->isNullValue()) {
31907330f729Sjoerg     return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
31917330f729Sjoerg   }
31927330f729Sjoerg 
31937330f729Sjoerg   uint64_t size =
31947330f729Sjoerg     CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
31957330f729Sjoerg 
31967330f729Sjoerg   ConstantInitBuilder builder(CGM);
31977330f729Sjoerg   auto values = builder.beginStruct(ObjCTypes.ProtocolExtensionTy);
31987330f729Sjoerg   values.addInt(ObjCTypes.IntTy, size);
31997330f729Sjoerg   values.add(optInstanceMethods);
32007330f729Sjoerg   values.add(optClassMethods);
32017330f729Sjoerg   values.add(instanceProperties);
32027330f729Sjoerg   values.add(extendedMethodTypes);
32037330f729Sjoerg   values.add(classProperties);
32047330f729Sjoerg 
32057330f729Sjoerg   // No special section, but goes in llvm.used
32067330f729Sjoerg   return CreateMetadataVar("_OBJC_PROTOCOLEXT_" + PD->getName(), values,
32077330f729Sjoerg                            StringRef(), CGM.getPointerAlign(), true);
32087330f729Sjoerg }
32097330f729Sjoerg 
32107330f729Sjoerg /*
32117330f729Sjoerg   struct objc_protocol_list {
32127330f729Sjoerg     struct objc_protocol_list *next;
32137330f729Sjoerg     long count;
32147330f729Sjoerg     Protocol *list[];
32157330f729Sjoerg   };
32167330f729Sjoerg */
32177330f729Sjoerg llvm::Constant *
EmitProtocolList(Twine name,ObjCProtocolDecl::protocol_iterator begin,ObjCProtocolDecl::protocol_iterator end)32187330f729Sjoerg CGObjCMac::EmitProtocolList(Twine name,
32197330f729Sjoerg                             ObjCProtocolDecl::protocol_iterator begin,
32207330f729Sjoerg                             ObjCProtocolDecl::protocol_iterator end) {
32217330f729Sjoerg   // Just return null for empty protocol lists
3222*e038c9c4Sjoerg   auto PDs = GetRuntimeProtocolList(begin, end);
3223*e038c9c4Sjoerg   if (PDs.empty())
32247330f729Sjoerg     return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
32257330f729Sjoerg 
32267330f729Sjoerg   ConstantInitBuilder builder(CGM);
32277330f729Sjoerg   auto values = builder.beginStruct();
32287330f729Sjoerg 
32297330f729Sjoerg   // This field is only used by the runtime.
32307330f729Sjoerg   values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
32317330f729Sjoerg 
32327330f729Sjoerg   // Reserve a slot for the count.
32337330f729Sjoerg   auto countSlot = values.addPlaceholder();
32347330f729Sjoerg 
32357330f729Sjoerg   auto refsArray = values.beginArray(ObjCTypes.ProtocolPtrTy);
3236*e038c9c4Sjoerg   for (const auto *Proto : PDs)
3237*e038c9c4Sjoerg     refsArray.add(GetProtocolRef(Proto));
3238*e038c9c4Sjoerg 
32397330f729Sjoerg   auto count = refsArray.size();
32407330f729Sjoerg 
32417330f729Sjoerg   // This list is null terminated.
32427330f729Sjoerg   refsArray.addNullPointer(ObjCTypes.ProtocolPtrTy);
32437330f729Sjoerg 
32447330f729Sjoerg   refsArray.finishAndAddTo(values);
32457330f729Sjoerg   values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);
32467330f729Sjoerg 
32477330f729Sjoerg   StringRef section;
32487330f729Sjoerg   if (CGM.getTriple().isOSBinFormatMachO())
32497330f729Sjoerg     section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
32507330f729Sjoerg 
32517330f729Sjoerg   llvm::GlobalVariable *GV =
32527330f729Sjoerg       CreateMetadataVar(name, values, section, CGM.getPointerAlign(), false);
32537330f729Sjoerg   return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
32547330f729Sjoerg }
32557330f729Sjoerg 
32567330f729Sjoerg static void
PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo *,16> & PropertySet,SmallVectorImpl<const ObjCPropertyDecl * > & Properties,const ObjCProtocolDecl * Proto,bool IsClassProperty)32577330f729Sjoerg PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*,16> &PropertySet,
32587330f729Sjoerg                        SmallVectorImpl<const ObjCPropertyDecl *> &Properties,
32597330f729Sjoerg                        const ObjCProtocolDecl *Proto,
32607330f729Sjoerg                        bool IsClassProperty) {
32617330f729Sjoerg   for (const auto *PD : Proto->properties()) {
32627330f729Sjoerg     if (IsClassProperty != PD->isClassProperty())
32637330f729Sjoerg       continue;
32647330f729Sjoerg     if (!PropertySet.insert(PD->getIdentifier()).second)
32657330f729Sjoerg       continue;
32667330f729Sjoerg     Properties.push_back(PD);
32677330f729Sjoerg   }
3268*e038c9c4Sjoerg 
3269*e038c9c4Sjoerg   for (const auto *P : Proto->protocols())
3270*e038c9c4Sjoerg     PushProtocolProperties(PropertySet, Properties, P, IsClassProperty);
32717330f729Sjoerg }
32727330f729Sjoerg 
32737330f729Sjoerg /*
32747330f729Sjoerg   struct _objc_property {
32757330f729Sjoerg     const char * const name;
32767330f729Sjoerg     const char * const attributes;
32777330f729Sjoerg   };
32787330f729Sjoerg 
32797330f729Sjoerg   struct _objc_property_list {
32807330f729Sjoerg     uint32_t entsize; // sizeof (struct _objc_property)
32817330f729Sjoerg     uint32_t prop_count;
32827330f729Sjoerg     struct _objc_property[prop_count];
32837330f729Sjoerg   };
32847330f729Sjoerg */
EmitPropertyList(Twine Name,const Decl * Container,const ObjCContainerDecl * OCD,const ObjCCommonTypesHelper & ObjCTypes,bool IsClassProperty)32857330f729Sjoerg llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name,
32867330f729Sjoerg                                        const Decl *Container,
32877330f729Sjoerg                                        const ObjCContainerDecl *OCD,
32887330f729Sjoerg                                        const ObjCCommonTypesHelper &ObjCTypes,
32897330f729Sjoerg                                        bool IsClassProperty) {
32907330f729Sjoerg   if (IsClassProperty) {
32917330f729Sjoerg     // Make this entry NULL for OS X with deployment target < 10.11, for iOS
32927330f729Sjoerg     // with deployment target < 9.0.
32937330f729Sjoerg     const llvm::Triple &Triple = CGM.getTarget().getTriple();
32947330f729Sjoerg     if ((Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 11)) ||
32957330f729Sjoerg         (Triple.isiOS() && Triple.isOSVersionLT(9)))
32967330f729Sjoerg       return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
32977330f729Sjoerg   }
32987330f729Sjoerg 
32997330f729Sjoerg   SmallVector<const ObjCPropertyDecl *, 16> Properties;
33007330f729Sjoerg   llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
33017330f729Sjoerg 
33027330f729Sjoerg   if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
33037330f729Sjoerg     for (const ObjCCategoryDecl *ClassExt : OID->known_extensions())
33047330f729Sjoerg       for (auto *PD : ClassExt->properties()) {
33057330f729Sjoerg         if (IsClassProperty != PD->isClassProperty())
33067330f729Sjoerg           continue;
3307*e038c9c4Sjoerg         if (PD->isDirectProperty())
3308*e038c9c4Sjoerg           continue;
33097330f729Sjoerg         PropertySet.insert(PD->getIdentifier());
33107330f729Sjoerg         Properties.push_back(PD);
33117330f729Sjoerg       }
33127330f729Sjoerg 
33137330f729Sjoerg   for (const auto *PD : OCD->properties()) {
33147330f729Sjoerg     if (IsClassProperty != PD->isClassProperty())
33157330f729Sjoerg       continue;
33167330f729Sjoerg     // Don't emit duplicate metadata for properties that were already in a
33177330f729Sjoerg     // class extension.
33187330f729Sjoerg     if (!PropertySet.insert(PD->getIdentifier()).second)
33197330f729Sjoerg       continue;
3320*e038c9c4Sjoerg     if (PD->isDirectProperty())
3321*e038c9c4Sjoerg       continue;
33227330f729Sjoerg     Properties.push_back(PD);
33237330f729Sjoerg   }
33247330f729Sjoerg 
33257330f729Sjoerg   if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
33267330f729Sjoerg     for (const auto *P : OID->all_referenced_protocols())
33277330f729Sjoerg       PushProtocolProperties(PropertySet, Properties, P, IsClassProperty);
33287330f729Sjoerg   }
33297330f729Sjoerg   else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) {
33307330f729Sjoerg     for (const auto *P : CD->protocols())
33317330f729Sjoerg       PushProtocolProperties(PropertySet, Properties, P, IsClassProperty);
33327330f729Sjoerg   }
33337330f729Sjoerg 
33347330f729Sjoerg   // Return null for empty list.
33357330f729Sjoerg   if (Properties.empty())
33367330f729Sjoerg     return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
33377330f729Sjoerg 
33387330f729Sjoerg   unsigned propertySize =
33397330f729Sjoerg     CGM.getDataLayout().getTypeAllocSize(ObjCTypes.PropertyTy);
33407330f729Sjoerg 
33417330f729Sjoerg   ConstantInitBuilder builder(CGM);
33427330f729Sjoerg   auto values = builder.beginStruct();
33437330f729Sjoerg   values.addInt(ObjCTypes.IntTy, propertySize);
33447330f729Sjoerg   values.addInt(ObjCTypes.IntTy, Properties.size());
33457330f729Sjoerg   auto propertiesArray = values.beginArray(ObjCTypes.PropertyTy);
33467330f729Sjoerg   for (auto PD : Properties) {
33477330f729Sjoerg     auto property = propertiesArray.beginStruct(ObjCTypes.PropertyTy);
33487330f729Sjoerg     property.add(GetPropertyName(PD->getIdentifier()));
33497330f729Sjoerg     property.add(GetPropertyTypeString(PD, Container));
33507330f729Sjoerg     property.finishAndAddTo(propertiesArray);
33517330f729Sjoerg   }
33527330f729Sjoerg   propertiesArray.finishAndAddTo(values);
33537330f729Sjoerg 
33547330f729Sjoerg   StringRef Section;
33557330f729Sjoerg   if (CGM.getTriple().isOSBinFormatMachO())
33567330f729Sjoerg     Section = (ObjCABI == 2) ? "__DATA, __objc_const"
33577330f729Sjoerg                              : "__OBJC,__property,regular,no_dead_strip";
33587330f729Sjoerg 
33597330f729Sjoerg   llvm::GlobalVariable *GV =
33607330f729Sjoerg       CreateMetadataVar(Name, values, Section, CGM.getPointerAlign(), true);
33617330f729Sjoerg   return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
33627330f729Sjoerg }
33637330f729Sjoerg 
33647330f729Sjoerg llvm::Constant *
EmitProtocolMethodTypes(Twine Name,ArrayRef<llvm::Constant * > MethodTypes,const ObjCCommonTypesHelper & ObjCTypes)33657330f729Sjoerg CGObjCCommonMac::EmitProtocolMethodTypes(Twine Name,
33667330f729Sjoerg                                          ArrayRef<llvm::Constant*> MethodTypes,
33677330f729Sjoerg                                          const ObjCCommonTypesHelper &ObjCTypes) {
33687330f729Sjoerg   // Return null for empty list.
33697330f729Sjoerg   if (MethodTypes.empty())
33707330f729Sjoerg     return llvm::Constant::getNullValue(ObjCTypes.Int8PtrPtrTy);
33717330f729Sjoerg 
33727330f729Sjoerg   llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
33737330f729Sjoerg                                              MethodTypes.size());
33747330f729Sjoerg   llvm::Constant *Init = llvm::ConstantArray::get(AT, MethodTypes);
33757330f729Sjoerg 
33767330f729Sjoerg   StringRef Section;
33777330f729Sjoerg   if (CGM.getTriple().isOSBinFormatMachO() && ObjCABI == 2)
33787330f729Sjoerg     Section = "__DATA, __objc_const";
33797330f729Sjoerg 
33807330f729Sjoerg   llvm::GlobalVariable *GV =
33817330f729Sjoerg       CreateMetadataVar(Name, Init, Section, CGM.getPointerAlign(), true);
33827330f729Sjoerg   return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.Int8PtrPtrTy);
33837330f729Sjoerg }
33847330f729Sjoerg 
33857330f729Sjoerg /*
33867330f729Sjoerg   struct _objc_category {
33877330f729Sjoerg   char *category_name;
33887330f729Sjoerg   char *class_name;
33897330f729Sjoerg   struct _objc_method_list *instance_methods;
33907330f729Sjoerg   struct _objc_method_list *class_methods;
33917330f729Sjoerg   struct _objc_protocol_list *protocols;
33927330f729Sjoerg   uint32_t size; // <rdar://4585769>
33937330f729Sjoerg   struct _objc_property_list *instance_properties;
33947330f729Sjoerg   struct _objc_property_list *class_properties;
33957330f729Sjoerg   };
33967330f729Sjoerg */
GenerateCategory(const ObjCCategoryImplDecl * OCD)33977330f729Sjoerg void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
33987330f729Sjoerg   unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategoryTy);
33997330f729Sjoerg 
34007330f729Sjoerg   // FIXME: This is poor design, the OCD should have a pointer to the category
34017330f729Sjoerg   // decl. Additionally, note that Category can be null for the @implementation
34027330f729Sjoerg   // w/o an @interface case. Sema should just create one for us as it does for
34037330f729Sjoerg   // @implementation so everyone else can live life under a clear blue sky.
34047330f729Sjoerg   const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
34057330f729Sjoerg   const ObjCCategoryDecl *Category =
34067330f729Sjoerg     Interface->FindCategoryDeclaration(OCD->getIdentifier());
34077330f729Sjoerg 
34087330f729Sjoerg   SmallString<256> ExtName;
34097330f729Sjoerg   llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
34107330f729Sjoerg                                      << OCD->getName();
34117330f729Sjoerg 
34127330f729Sjoerg   ConstantInitBuilder Builder(CGM);
34137330f729Sjoerg   auto Values = Builder.beginStruct(ObjCTypes.CategoryTy);
34147330f729Sjoerg 
34157330f729Sjoerg   enum {
34167330f729Sjoerg     InstanceMethods,
34177330f729Sjoerg     ClassMethods,
34187330f729Sjoerg     NumMethodLists
34197330f729Sjoerg   };
34207330f729Sjoerg   SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists];
34217330f729Sjoerg   for (const auto *MD : OCD->methods()) {
3422*e038c9c4Sjoerg     if (!MD->isDirectMethod())
34237330f729Sjoerg       Methods[unsigned(MD->isClassMethod())].push_back(MD);
34247330f729Sjoerg   }
34257330f729Sjoerg 
34267330f729Sjoerg   Values.add(GetClassName(OCD->getName()));
34277330f729Sjoerg   Values.add(GetClassName(Interface->getObjCRuntimeNameAsString()));
34287330f729Sjoerg   LazySymbols.insert(Interface->getIdentifier());
34297330f729Sjoerg 
34307330f729Sjoerg   Values.add(emitMethodList(ExtName, MethodListType::CategoryInstanceMethods,
34317330f729Sjoerg                             Methods[InstanceMethods]));
34327330f729Sjoerg   Values.add(emitMethodList(ExtName, MethodListType::CategoryClassMethods,
34337330f729Sjoerg                             Methods[ClassMethods]));
34347330f729Sjoerg   if (Category) {
34357330f729Sjoerg     Values.add(
34367330f729Sjoerg         EmitProtocolList("OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
34377330f729Sjoerg                          Category->protocol_begin(), Category->protocol_end()));
34387330f729Sjoerg   } else {
34397330f729Sjoerg     Values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
34407330f729Sjoerg   }
34417330f729Sjoerg   Values.addInt(ObjCTypes.IntTy, Size);
34427330f729Sjoerg 
34437330f729Sjoerg   // If there is no category @interface then there can be no properties.
34447330f729Sjoerg   if (Category) {
34457330f729Sjoerg     Values.add(EmitPropertyList("_OBJC_$_PROP_LIST_" + ExtName.str(),
34467330f729Sjoerg                                 OCD, Category, ObjCTypes, false));
34477330f729Sjoerg     Values.add(EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(),
34487330f729Sjoerg                                 OCD, Category, ObjCTypes, true));
34497330f729Sjoerg   } else {
34507330f729Sjoerg     Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
34517330f729Sjoerg     Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
34527330f729Sjoerg   }
34537330f729Sjoerg 
34547330f729Sjoerg   llvm::GlobalVariable *GV =
34557330f729Sjoerg       CreateMetadataVar("OBJC_CATEGORY_" + ExtName.str(), Values,
34567330f729Sjoerg                         "__OBJC,__category,regular,no_dead_strip",
34577330f729Sjoerg                         CGM.getPointerAlign(), true);
34587330f729Sjoerg   DefinedCategories.push_back(GV);
34597330f729Sjoerg   DefinedCategoryNames.insert(llvm::CachedHashString(ExtName));
34607330f729Sjoerg   // method definition entries must be clear for next implementation.
34617330f729Sjoerg   MethodDefinitions.clear();
34627330f729Sjoerg }
34637330f729Sjoerg 
34647330f729Sjoerg enum FragileClassFlags {
34657330f729Sjoerg   /// Apparently: is not a meta-class.
34667330f729Sjoerg   FragileABI_Class_Factory                 = 0x00001,
34677330f729Sjoerg 
34687330f729Sjoerg   /// Is a meta-class.
34697330f729Sjoerg   FragileABI_Class_Meta                    = 0x00002,
34707330f729Sjoerg 
34717330f729Sjoerg   /// Has a non-trivial constructor or destructor.
34727330f729Sjoerg   FragileABI_Class_HasCXXStructors         = 0x02000,
34737330f729Sjoerg 
34747330f729Sjoerg   /// Has hidden visibility.
34757330f729Sjoerg   FragileABI_Class_Hidden                  = 0x20000,
34767330f729Sjoerg 
34777330f729Sjoerg   /// Class implementation was compiled under ARC.
34787330f729Sjoerg   FragileABI_Class_CompiledByARC           = 0x04000000,
34797330f729Sjoerg 
34807330f729Sjoerg   /// Class implementation was compiled under MRC and has MRC weak ivars.
34817330f729Sjoerg   /// Exclusive with CompiledByARC.
34827330f729Sjoerg   FragileABI_Class_HasMRCWeakIvars         = 0x08000000,
34837330f729Sjoerg };
34847330f729Sjoerg 
34857330f729Sjoerg enum NonFragileClassFlags {
34867330f729Sjoerg   /// Is a meta-class.
34877330f729Sjoerg   NonFragileABI_Class_Meta                 = 0x00001,
34887330f729Sjoerg 
34897330f729Sjoerg   /// Is a root class.
34907330f729Sjoerg   NonFragileABI_Class_Root                 = 0x00002,
34917330f729Sjoerg 
34927330f729Sjoerg   /// Has a non-trivial constructor or destructor.
34937330f729Sjoerg   NonFragileABI_Class_HasCXXStructors      = 0x00004,
34947330f729Sjoerg 
34957330f729Sjoerg   /// Has hidden visibility.
34967330f729Sjoerg   NonFragileABI_Class_Hidden               = 0x00010,
34977330f729Sjoerg 
34987330f729Sjoerg   /// Has the exception attribute.
34997330f729Sjoerg   NonFragileABI_Class_Exception            = 0x00020,
35007330f729Sjoerg 
35017330f729Sjoerg   /// (Obsolete) ARC-specific: this class has a .release_ivars method
35027330f729Sjoerg   NonFragileABI_Class_HasIvarReleaser      = 0x00040,
35037330f729Sjoerg 
35047330f729Sjoerg   /// Class implementation was compiled under ARC.
35057330f729Sjoerg   NonFragileABI_Class_CompiledByARC        = 0x00080,
35067330f729Sjoerg 
35077330f729Sjoerg   /// Class has non-trivial destructors, but zero-initialization is okay.
35087330f729Sjoerg   NonFragileABI_Class_HasCXXDestructorOnly = 0x00100,
35097330f729Sjoerg 
35107330f729Sjoerg   /// Class implementation was compiled under MRC and has MRC weak ivars.
35117330f729Sjoerg   /// Exclusive with CompiledByARC.
35127330f729Sjoerg   NonFragileABI_Class_HasMRCWeakIvars      = 0x00200,
35137330f729Sjoerg };
35147330f729Sjoerg 
hasWeakMember(QualType type)35157330f729Sjoerg static bool hasWeakMember(QualType type) {
35167330f729Sjoerg   if (type.getObjCLifetime() == Qualifiers::OCL_Weak) {
35177330f729Sjoerg     return true;
35187330f729Sjoerg   }
35197330f729Sjoerg 
35207330f729Sjoerg   if (auto recType = type->getAs<RecordType>()) {
35217330f729Sjoerg     for (auto field : recType->getDecl()->fields()) {
35227330f729Sjoerg       if (hasWeakMember(field->getType()))
35237330f729Sjoerg         return true;
35247330f729Sjoerg     }
35257330f729Sjoerg   }
35267330f729Sjoerg 
35277330f729Sjoerg   return false;
35287330f729Sjoerg }
35297330f729Sjoerg 
35307330f729Sjoerg /// For compatibility, we only want to set the "HasMRCWeakIvars" flag
35317330f729Sjoerg /// (and actually fill in a layout string) if we really do have any
35327330f729Sjoerg /// __weak ivars.
hasMRCWeakIvars(CodeGenModule & CGM,const ObjCImplementationDecl * ID)35337330f729Sjoerg static bool hasMRCWeakIvars(CodeGenModule &CGM,
35347330f729Sjoerg                             const ObjCImplementationDecl *ID) {
35357330f729Sjoerg   if (!CGM.getLangOpts().ObjCWeak) return false;
35367330f729Sjoerg   assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
35377330f729Sjoerg 
35387330f729Sjoerg   for (const ObjCIvarDecl *ivar =
35397330f729Sjoerg          ID->getClassInterface()->all_declared_ivar_begin();
35407330f729Sjoerg        ivar; ivar = ivar->getNextIvar()) {
35417330f729Sjoerg     if (hasWeakMember(ivar->getType()))
35427330f729Sjoerg       return true;
35437330f729Sjoerg   }
35447330f729Sjoerg 
35457330f729Sjoerg   return false;
35467330f729Sjoerg }
35477330f729Sjoerg 
35487330f729Sjoerg /*
35497330f729Sjoerg   struct _objc_class {
35507330f729Sjoerg   Class isa;
35517330f729Sjoerg   Class super_class;
35527330f729Sjoerg   const char *name;
35537330f729Sjoerg   long version;
35547330f729Sjoerg   long info;
35557330f729Sjoerg   long instance_size;
35567330f729Sjoerg   struct _objc_ivar_list *ivars;
35577330f729Sjoerg   struct _objc_method_list *methods;
35587330f729Sjoerg   struct _objc_cache *cache;
35597330f729Sjoerg   struct _objc_protocol_list *protocols;
35607330f729Sjoerg   // Objective-C 1.0 extensions (<rdr://4585769>)
35617330f729Sjoerg   const char *ivar_layout;
35627330f729Sjoerg   struct _objc_class_ext *ext;
35637330f729Sjoerg   };
35647330f729Sjoerg 
35657330f729Sjoerg   See EmitClassExtension();
35667330f729Sjoerg */
GenerateClass(const ObjCImplementationDecl * ID)35677330f729Sjoerg void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
35687330f729Sjoerg   IdentifierInfo *RuntimeName =
35697330f729Sjoerg       &CGM.getContext().Idents.get(ID->getObjCRuntimeNameAsString());
35707330f729Sjoerg   DefinedSymbols.insert(RuntimeName);
35717330f729Sjoerg 
35727330f729Sjoerg   std::string ClassName = ID->getNameAsString();
35737330f729Sjoerg   // FIXME: Gross
35747330f729Sjoerg   ObjCInterfaceDecl *Interface =
35757330f729Sjoerg     const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
35767330f729Sjoerg   llvm::Constant *Protocols =
35777330f729Sjoerg       EmitProtocolList("OBJC_CLASS_PROTOCOLS_" + ID->getName(),
35787330f729Sjoerg                        Interface->all_referenced_protocol_begin(),
35797330f729Sjoerg                        Interface->all_referenced_protocol_end());
35807330f729Sjoerg   unsigned Flags = FragileABI_Class_Factory;
35817330f729Sjoerg   if (ID->hasNonZeroConstructors() || ID->hasDestructors())
35827330f729Sjoerg     Flags |= FragileABI_Class_HasCXXStructors;
35837330f729Sjoerg 
35847330f729Sjoerg   bool hasMRCWeak = false;
35857330f729Sjoerg 
35867330f729Sjoerg   if (CGM.getLangOpts().ObjCAutoRefCount)
35877330f729Sjoerg     Flags |= FragileABI_Class_CompiledByARC;
35887330f729Sjoerg   else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID)))
35897330f729Sjoerg     Flags |= FragileABI_Class_HasMRCWeakIvars;
35907330f729Sjoerg 
35917330f729Sjoerg   CharUnits Size =
35927330f729Sjoerg     CGM.getContext().getASTObjCImplementationLayout(ID).getSize();
35937330f729Sjoerg 
35947330f729Sjoerg   // FIXME: Set CXX-structors flag.
35957330f729Sjoerg   if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
35967330f729Sjoerg     Flags |= FragileABI_Class_Hidden;
35977330f729Sjoerg 
35987330f729Sjoerg   enum {
35997330f729Sjoerg     InstanceMethods,
36007330f729Sjoerg     ClassMethods,
36017330f729Sjoerg     NumMethodLists
36027330f729Sjoerg   };
36037330f729Sjoerg   SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists];
36047330f729Sjoerg   for (const auto *MD : ID->methods()) {
3605*e038c9c4Sjoerg     if (!MD->isDirectMethod())
36067330f729Sjoerg       Methods[unsigned(MD->isClassMethod())].push_back(MD);
36077330f729Sjoerg   }
36087330f729Sjoerg 
36097330f729Sjoerg   for (const auto *PID : ID->property_impls()) {
36107330f729Sjoerg     if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
3611*e038c9c4Sjoerg       if (PID->getPropertyDecl()->isDirectProperty())
3612*e038c9c4Sjoerg         continue;
3613*e038c9c4Sjoerg       if (ObjCMethodDecl *MD = PID->getGetterMethodDecl())
36147330f729Sjoerg         if (GetMethodDefinition(MD))
36157330f729Sjoerg           Methods[InstanceMethods].push_back(MD);
3616*e038c9c4Sjoerg       if (ObjCMethodDecl *MD = PID->getSetterMethodDecl())
36177330f729Sjoerg         if (GetMethodDefinition(MD))
36187330f729Sjoerg           Methods[InstanceMethods].push_back(MD);
36197330f729Sjoerg     }
36207330f729Sjoerg   }
36217330f729Sjoerg 
36227330f729Sjoerg   ConstantInitBuilder builder(CGM);
36237330f729Sjoerg   auto values = builder.beginStruct(ObjCTypes.ClassTy);
36247330f729Sjoerg   values.add(EmitMetaClass(ID, Protocols, Methods[ClassMethods]));
36257330f729Sjoerg   if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
36267330f729Sjoerg     // Record a reference to the super class.
36277330f729Sjoerg     LazySymbols.insert(Super->getIdentifier());
36287330f729Sjoerg 
36297330f729Sjoerg     values.addBitCast(GetClassName(Super->getObjCRuntimeNameAsString()),
36307330f729Sjoerg                       ObjCTypes.ClassPtrTy);
36317330f729Sjoerg   } else {
36327330f729Sjoerg     values.addNullPointer(ObjCTypes.ClassPtrTy);
36337330f729Sjoerg   }
36347330f729Sjoerg   values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
36357330f729Sjoerg   // Version is always 0.
36367330f729Sjoerg   values.addInt(ObjCTypes.LongTy, 0);
36377330f729Sjoerg   values.addInt(ObjCTypes.LongTy, Flags);
36387330f729Sjoerg   values.addInt(ObjCTypes.LongTy, Size.getQuantity());
36397330f729Sjoerg   values.add(EmitIvarList(ID, false));
36407330f729Sjoerg   values.add(emitMethodList(ID->getName(), MethodListType::InstanceMethods,
36417330f729Sjoerg                             Methods[InstanceMethods]));
36427330f729Sjoerg   // cache is always NULL.
36437330f729Sjoerg   values.addNullPointer(ObjCTypes.CachePtrTy);
36447330f729Sjoerg   values.add(Protocols);
36457330f729Sjoerg   values.add(BuildStrongIvarLayout(ID, CharUnits::Zero(), Size));
36467330f729Sjoerg   values.add(EmitClassExtension(ID, Size, hasMRCWeak,
36477330f729Sjoerg                                 /*isMetaclass*/ false));
36487330f729Sjoerg 
36497330f729Sjoerg   std::string Name("OBJC_CLASS_");
36507330f729Sjoerg   Name += ClassName;
36517330f729Sjoerg   const char *Section = "__OBJC,__class,regular,no_dead_strip";
36527330f729Sjoerg   // Check for a forward reference.
36537330f729Sjoerg   llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
36547330f729Sjoerg   if (GV) {
3655*e038c9c4Sjoerg     assert(GV->getValueType() == ObjCTypes.ClassTy &&
36567330f729Sjoerg            "Forward metaclass reference has incorrect type.");
36577330f729Sjoerg     values.finishAndSetAsInitializer(GV);
36587330f729Sjoerg     GV->setSection(Section);
36597330f729Sjoerg     GV->setAlignment(CGM.getPointerAlign().getAsAlign());
36607330f729Sjoerg     CGM.addCompilerUsedGlobal(GV);
36617330f729Sjoerg   } else
36627330f729Sjoerg     GV = CreateMetadataVar(Name, values, Section, CGM.getPointerAlign(), true);
36637330f729Sjoerg   DefinedClasses.push_back(GV);
36647330f729Sjoerg   ImplementedClasses.push_back(Interface);
36657330f729Sjoerg   // method definition entries must be clear for next implementation.
36667330f729Sjoerg   MethodDefinitions.clear();
36677330f729Sjoerg }
36687330f729Sjoerg 
EmitMetaClass(const ObjCImplementationDecl * ID,llvm::Constant * Protocols,ArrayRef<const ObjCMethodDecl * > Methods)36697330f729Sjoerg llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
36707330f729Sjoerg                                          llvm::Constant *Protocols,
36717330f729Sjoerg                                 ArrayRef<const ObjCMethodDecl*> Methods) {
36727330f729Sjoerg   unsigned Flags = FragileABI_Class_Meta;
36737330f729Sjoerg   unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassTy);
36747330f729Sjoerg 
36757330f729Sjoerg   if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
36767330f729Sjoerg     Flags |= FragileABI_Class_Hidden;
36777330f729Sjoerg 
36787330f729Sjoerg   ConstantInitBuilder builder(CGM);
36797330f729Sjoerg   auto values = builder.beginStruct(ObjCTypes.ClassTy);
36807330f729Sjoerg   // The isa for the metaclass is the root of the hierarchy.
36817330f729Sjoerg   const ObjCInterfaceDecl *Root = ID->getClassInterface();
36827330f729Sjoerg   while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
36837330f729Sjoerg     Root = Super;
36847330f729Sjoerg   values.addBitCast(GetClassName(Root->getObjCRuntimeNameAsString()),
36857330f729Sjoerg                     ObjCTypes.ClassPtrTy);
36867330f729Sjoerg   // The super class for the metaclass is emitted as the name of the
36877330f729Sjoerg   // super class. The runtime fixes this up to point to the
36887330f729Sjoerg   // *metaclass* for the super class.
36897330f729Sjoerg   if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
36907330f729Sjoerg     values.addBitCast(GetClassName(Super->getObjCRuntimeNameAsString()),
36917330f729Sjoerg                       ObjCTypes.ClassPtrTy);
36927330f729Sjoerg   } else {
36937330f729Sjoerg     values.addNullPointer(ObjCTypes.ClassPtrTy);
36947330f729Sjoerg   }
36957330f729Sjoerg   values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
36967330f729Sjoerg   // Version is always 0.
36977330f729Sjoerg   values.addInt(ObjCTypes.LongTy, 0);
36987330f729Sjoerg   values.addInt(ObjCTypes.LongTy, Flags);
36997330f729Sjoerg   values.addInt(ObjCTypes.LongTy, Size);
37007330f729Sjoerg   values.add(EmitIvarList(ID, true));
37017330f729Sjoerg   values.add(emitMethodList(ID->getName(), MethodListType::ClassMethods,
37027330f729Sjoerg                             Methods));
37037330f729Sjoerg   // cache is always NULL.
37047330f729Sjoerg   values.addNullPointer(ObjCTypes.CachePtrTy);
37057330f729Sjoerg   values.add(Protocols);
37067330f729Sjoerg   // ivar_layout for metaclass is always NULL.
37077330f729Sjoerg   values.addNullPointer(ObjCTypes.Int8PtrTy);
37087330f729Sjoerg   // The class extension is used to store class properties for metaclasses.
37097330f729Sjoerg   values.add(EmitClassExtension(ID, CharUnits::Zero(), false/*hasMRCWeak*/,
37107330f729Sjoerg                                 /*isMetaclass*/true));
37117330f729Sjoerg 
37127330f729Sjoerg   std::string Name("OBJC_METACLASS_");
37137330f729Sjoerg   Name += ID->getName();
37147330f729Sjoerg 
37157330f729Sjoerg   // Check for a forward reference.
37167330f729Sjoerg   llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
37177330f729Sjoerg   if (GV) {
3718*e038c9c4Sjoerg     assert(GV->getValueType() == ObjCTypes.ClassTy &&
37197330f729Sjoerg            "Forward metaclass reference has incorrect type.");
37207330f729Sjoerg     values.finishAndSetAsInitializer(GV);
37217330f729Sjoerg   } else {
37227330f729Sjoerg     GV = values.finishAndCreateGlobal(Name, CGM.getPointerAlign(),
37237330f729Sjoerg                                       /*constant*/ false,
37247330f729Sjoerg                                       llvm::GlobalValue::PrivateLinkage);
37257330f729Sjoerg   }
37267330f729Sjoerg   GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
37277330f729Sjoerg   CGM.addCompilerUsedGlobal(GV);
37287330f729Sjoerg 
37297330f729Sjoerg   return GV;
37307330f729Sjoerg }
37317330f729Sjoerg 
EmitMetaClassRef(const ObjCInterfaceDecl * ID)37327330f729Sjoerg llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
37337330f729Sjoerg   std::string Name = "OBJC_METACLASS_" + ID->getNameAsString();
37347330f729Sjoerg 
37357330f729Sjoerg   // FIXME: Should we look these up somewhere other than the module. Its a bit
37367330f729Sjoerg   // silly since we only generate these while processing an implementation, so
37377330f729Sjoerg   // exactly one pointer would work if know when we entered/exitted an
37387330f729Sjoerg   // implementation block.
37397330f729Sjoerg 
37407330f729Sjoerg   // Check for an existing forward reference.
37417330f729Sjoerg   // Previously, metaclass with internal linkage may have been defined.
37427330f729Sjoerg   // pass 'true' as 2nd argument so it is returned.
37437330f729Sjoerg   llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
37447330f729Sjoerg   if (!GV)
37457330f729Sjoerg     GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
37467330f729Sjoerg                                   llvm::GlobalValue::PrivateLinkage, nullptr,
37477330f729Sjoerg                                   Name);
37487330f729Sjoerg 
3749*e038c9c4Sjoerg   assert(GV->getValueType() == ObjCTypes.ClassTy &&
37507330f729Sjoerg          "Forward metaclass reference has incorrect type.");
37517330f729Sjoerg   return GV;
37527330f729Sjoerg }
37537330f729Sjoerg 
EmitSuperClassRef(const ObjCInterfaceDecl * ID)37547330f729Sjoerg llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
37557330f729Sjoerg   std::string Name = "OBJC_CLASS_" + ID->getNameAsString();
37567330f729Sjoerg   llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
37577330f729Sjoerg 
37587330f729Sjoerg   if (!GV)
37597330f729Sjoerg     GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
37607330f729Sjoerg                                   llvm::GlobalValue::PrivateLinkage, nullptr,
37617330f729Sjoerg                                   Name);
37627330f729Sjoerg 
3763*e038c9c4Sjoerg   assert(GV->getValueType() == ObjCTypes.ClassTy &&
37647330f729Sjoerg          "Forward class metadata reference has incorrect type.");
37657330f729Sjoerg   return GV;
37667330f729Sjoerg }
37677330f729Sjoerg 
37687330f729Sjoerg /*
37697330f729Sjoerg   Emit a "class extension", which in this specific context means extra
37707330f729Sjoerg   data that doesn't fit in the normal fragile-ABI class structure, and
37717330f729Sjoerg   has nothing to do with the language concept of a class extension.
37727330f729Sjoerg 
37737330f729Sjoerg   struct objc_class_ext {
37747330f729Sjoerg   uint32_t size;
37757330f729Sjoerg   const char *weak_ivar_layout;
37767330f729Sjoerg   struct _objc_property_list *properties;
37777330f729Sjoerg   };
37787330f729Sjoerg */
37797330f729Sjoerg llvm::Constant *
EmitClassExtension(const ObjCImplementationDecl * ID,CharUnits InstanceSize,bool hasMRCWeakIvars,bool isMetaclass)37807330f729Sjoerg CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID,
37817330f729Sjoerg                               CharUnits InstanceSize, bool hasMRCWeakIvars,
37827330f729Sjoerg                               bool isMetaclass) {
37837330f729Sjoerg   // Weak ivar layout.
37847330f729Sjoerg   llvm::Constant *layout;
37857330f729Sjoerg   if (isMetaclass) {
37867330f729Sjoerg     layout = llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
37877330f729Sjoerg   } else {
37887330f729Sjoerg     layout = BuildWeakIvarLayout(ID, CharUnits::Zero(), InstanceSize,
37897330f729Sjoerg                                  hasMRCWeakIvars);
37907330f729Sjoerg   }
37917330f729Sjoerg 
37927330f729Sjoerg   // Properties.
37937330f729Sjoerg   llvm::Constant *propertyList =
37947330f729Sjoerg     EmitPropertyList((isMetaclass ? Twine("_OBJC_$_CLASS_PROP_LIST_")
37957330f729Sjoerg                                   : Twine("_OBJC_$_PROP_LIST_"))
37967330f729Sjoerg                         + ID->getName(),
37977330f729Sjoerg                      ID, ID->getClassInterface(), ObjCTypes, isMetaclass);
37987330f729Sjoerg 
37997330f729Sjoerg   // Return null if no extension bits are used.
38007330f729Sjoerg   if (layout->isNullValue() && propertyList->isNullValue()) {
38017330f729Sjoerg     return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
38027330f729Sjoerg   }
38037330f729Sjoerg 
38047330f729Sjoerg   uint64_t size =
38057330f729Sjoerg     CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
38067330f729Sjoerg 
38077330f729Sjoerg   ConstantInitBuilder builder(CGM);
38087330f729Sjoerg   auto values = builder.beginStruct(ObjCTypes.ClassExtensionTy);
38097330f729Sjoerg   values.addInt(ObjCTypes.IntTy, size);
38107330f729Sjoerg   values.add(layout);
38117330f729Sjoerg   values.add(propertyList);
38127330f729Sjoerg 
38137330f729Sjoerg   return CreateMetadataVar("OBJC_CLASSEXT_" + ID->getName(), values,
38147330f729Sjoerg                            "__OBJC,__class_ext,regular,no_dead_strip",
38157330f729Sjoerg                            CGM.getPointerAlign(), true);
38167330f729Sjoerg }
38177330f729Sjoerg 
38187330f729Sjoerg /*
38197330f729Sjoerg   struct objc_ivar {
38207330f729Sjoerg     char *ivar_name;
38217330f729Sjoerg     char *ivar_type;
38227330f729Sjoerg     int ivar_offset;
38237330f729Sjoerg   };
38247330f729Sjoerg 
38257330f729Sjoerg   struct objc_ivar_list {
38267330f729Sjoerg     int ivar_count;
38277330f729Sjoerg     struct objc_ivar list[count];
38287330f729Sjoerg   };
38297330f729Sjoerg */
EmitIvarList(const ObjCImplementationDecl * ID,bool ForClass)38307330f729Sjoerg llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
38317330f729Sjoerg                                         bool ForClass) {
38327330f729Sjoerg   // When emitting the root class GCC emits ivar entries for the
38337330f729Sjoerg   // actual class structure. It is not clear if we need to follow this
38347330f729Sjoerg   // behavior; for now lets try and get away with not doing it. If so,
38357330f729Sjoerg   // the cleanest solution would be to make up an ObjCInterfaceDecl
38367330f729Sjoerg   // for the class.
38377330f729Sjoerg   if (ForClass)
38387330f729Sjoerg     return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
38397330f729Sjoerg 
38407330f729Sjoerg   const ObjCInterfaceDecl *OID = ID->getClassInterface();
38417330f729Sjoerg 
38427330f729Sjoerg   ConstantInitBuilder builder(CGM);
38437330f729Sjoerg   auto ivarList = builder.beginStruct();
38447330f729Sjoerg   auto countSlot = ivarList.addPlaceholder();
38457330f729Sjoerg   auto ivars = ivarList.beginArray(ObjCTypes.IvarTy);
38467330f729Sjoerg 
38477330f729Sjoerg   for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
38487330f729Sjoerg        IVD; IVD = IVD->getNextIvar()) {
38497330f729Sjoerg     // Ignore unnamed bit-fields.
38507330f729Sjoerg     if (!IVD->getDeclName())
38517330f729Sjoerg       continue;
38527330f729Sjoerg 
38537330f729Sjoerg     auto ivar = ivars.beginStruct(ObjCTypes.IvarTy);
38547330f729Sjoerg     ivar.add(GetMethodVarName(IVD->getIdentifier()));
38557330f729Sjoerg     ivar.add(GetMethodVarType(IVD));
38567330f729Sjoerg     ivar.addInt(ObjCTypes.IntTy, ComputeIvarBaseOffset(CGM, OID, IVD));
38577330f729Sjoerg     ivar.finishAndAddTo(ivars);
38587330f729Sjoerg   }
38597330f729Sjoerg 
38607330f729Sjoerg   // Return null for empty list.
38617330f729Sjoerg   auto count = ivars.size();
38627330f729Sjoerg   if (count == 0) {
38637330f729Sjoerg     ivars.abandon();
38647330f729Sjoerg     ivarList.abandon();
38657330f729Sjoerg     return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
38667330f729Sjoerg   }
38677330f729Sjoerg 
38687330f729Sjoerg   ivars.finishAndAddTo(ivarList);
38697330f729Sjoerg   ivarList.fillPlaceholderWithInt(countSlot, ObjCTypes.IntTy, count);
38707330f729Sjoerg 
38717330f729Sjoerg   llvm::GlobalVariable *GV;
38727330f729Sjoerg   if (ForClass)
38737330f729Sjoerg     GV =
38747330f729Sjoerg         CreateMetadataVar("OBJC_CLASS_VARIABLES_" + ID->getName(), ivarList,
38757330f729Sjoerg                           "__OBJC,__class_vars,regular,no_dead_strip",
38767330f729Sjoerg                           CGM.getPointerAlign(), true);
38777330f729Sjoerg   else
38787330f729Sjoerg     GV = CreateMetadataVar("OBJC_INSTANCE_VARIABLES_" + ID->getName(), ivarList,
38797330f729Sjoerg                            "__OBJC,__instance_vars,regular,no_dead_strip",
38807330f729Sjoerg                            CGM.getPointerAlign(), true);
38817330f729Sjoerg   return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
38827330f729Sjoerg }
38837330f729Sjoerg 
38847330f729Sjoerg /// Build a struct objc_method_description constant for the given method.
38857330f729Sjoerg ///
38867330f729Sjoerg /// struct objc_method_description {
38877330f729Sjoerg ///   SEL method_name;
38887330f729Sjoerg ///   char *method_types;
38897330f729Sjoerg /// };
emitMethodDescriptionConstant(ConstantArrayBuilder & builder,const ObjCMethodDecl * MD)38907330f729Sjoerg void CGObjCMac::emitMethodDescriptionConstant(ConstantArrayBuilder &builder,
38917330f729Sjoerg                                               const ObjCMethodDecl *MD) {
38927330f729Sjoerg   auto description = builder.beginStruct(ObjCTypes.MethodDescriptionTy);
38937330f729Sjoerg   description.addBitCast(GetMethodVarName(MD->getSelector()),
38947330f729Sjoerg                          ObjCTypes.SelectorPtrTy);
38957330f729Sjoerg   description.add(GetMethodVarType(MD));
38967330f729Sjoerg   description.finishAndAddTo(builder);
38977330f729Sjoerg }
38987330f729Sjoerg 
38997330f729Sjoerg /// Build a struct objc_method constant for the given method.
39007330f729Sjoerg ///
39017330f729Sjoerg /// struct objc_method {
39027330f729Sjoerg ///   SEL method_name;
39037330f729Sjoerg ///   char *method_types;
39047330f729Sjoerg ///   void *method;
39057330f729Sjoerg /// };
emitMethodConstant(ConstantArrayBuilder & builder,const ObjCMethodDecl * MD)39067330f729Sjoerg void CGObjCMac::emitMethodConstant(ConstantArrayBuilder &builder,
39077330f729Sjoerg                                    const ObjCMethodDecl *MD) {
39087330f729Sjoerg   llvm::Function *fn = GetMethodDefinition(MD);
39097330f729Sjoerg   assert(fn && "no definition registered for method");
39107330f729Sjoerg 
39117330f729Sjoerg   auto method = builder.beginStruct(ObjCTypes.MethodTy);
39127330f729Sjoerg   method.addBitCast(GetMethodVarName(MD->getSelector()),
39137330f729Sjoerg                     ObjCTypes.SelectorPtrTy);
39147330f729Sjoerg   method.add(GetMethodVarType(MD));
39157330f729Sjoerg   method.addBitCast(fn, ObjCTypes.Int8PtrTy);
39167330f729Sjoerg   method.finishAndAddTo(builder);
39177330f729Sjoerg }
39187330f729Sjoerg 
39197330f729Sjoerg /// Build a struct objc_method_list or struct objc_method_description_list,
39207330f729Sjoerg /// as appropriate.
39217330f729Sjoerg ///
39227330f729Sjoerg /// struct objc_method_list {
39237330f729Sjoerg ///   struct objc_method_list *obsolete;
39247330f729Sjoerg ///   int count;
39257330f729Sjoerg ///   struct objc_method methods_list[count];
39267330f729Sjoerg /// };
39277330f729Sjoerg ///
39287330f729Sjoerg /// struct objc_method_description_list {
39297330f729Sjoerg ///   int count;
39307330f729Sjoerg ///   struct objc_method_description list[count];
39317330f729Sjoerg /// };
emitMethodList(Twine name,MethodListType MLT,ArrayRef<const ObjCMethodDecl * > methods)39327330f729Sjoerg llvm::Constant *CGObjCMac::emitMethodList(Twine name, MethodListType MLT,
39337330f729Sjoerg                                  ArrayRef<const ObjCMethodDecl *> methods) {
39347330f729Sjoerg   StringRef prefix;
39357330f729Sjoerg   StringRef section;
39367330f729Sjoerg   bool forProtocol = false;
39377330f729Sjoerg   switch (MLT) {
39387330f729Sjoerg   case MethodListType::CategoryInstanceMethods:
39397330f729Sjoerg     prefix = "OBJC_CATEGORY_INSTANCE_METHODS_";
39407330f729Sjoerg     section = "__OBJC,__cat_inst_meth,regular,no_dead_strip";
39417330f729Sjoerg     forProtocol = false;
39427330f729Sjoerg     break;
39437330f729Sjoerg   case MethodListType::CategoryClassMethods:
39447330f729Sjoerg     prefix = "OBJC_CATEGORY_CLASS_METHODS_";
39457330f729Sjoerg     section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
39467330f729Sjoerg     forProtocol = false;
39477330f729Sjoerg     break;
39487330f729Sjoerg   case MethodListType::InstanceMethods:
39497330f729Sjoerg     prefix = "OBJC_INSTANCE_METHODS_";
39507330f729Sjoerg     section = "__OBJC,__inst_meth,regular,no_dead_strip";
39517330f729Sjoerg     forProtocol = false;
39527330f729Sjoerg     break;
39537330f729Sjoerg   case MethodListType::ClassMethods:
39547330f729Sjoerg     prefix = "OBJC_CLASS_METHODS_";
39557330f729Sjoerg     section = "__OBJC,__cls_meth,regular,no_dead_strip";
39567330f729Sjoerg     forProtocol = false;
39577330f729Sjoerg     break;
39587330f729Sjoerg   case MethodListType::ProtocolInstanceMethods:
39597330f729Sjoerg     prefix = "OBJC_PROTOCOL_INSTANCE_METHODS_";
39607330f729Sjoerg     section = "__OBJC,__cat_inst_meth,regular,no_dead_strip";
39617330f729Sjoerg     forProtocol = true;
39627330f729Sjoerg     break;
39637330f729Sjoerg   case MethodListType::ProtocolClassMethods:
39647330f729Sjoerg     prefix = "OBJC_PROTOCOL_CLASS_METHODS_";
39657330f729Sjoerg     section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
39667330f729Sjoerg     forProtocol = true;
39677330f729Sjoerg     break;
39687330f729Sjoerg   case MethodListType::OptionalProtocolInstanceMethods:
39697330f729Sjoerg     prefix = "OBJC_PROTOCOL_INSTANCE_METHODS_OPT_";
39707330f729Sjoerg     section = "__OBJC,__cat_inst_meth,regular,no_dead_strip";
39717330f729Sjoerg     forProtocol = true;
39727330f729Sjoerg     break;
39737330f729Sjoerg   case MethodListType::OptionalProtocolClassMethods:
39747330f729Sjoerg     prefix = "OBJC_PROTOCOL_CLASS_METHODS_OPT_";
39757330f729Sjoerg     section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
39767330f729Sjoerg     forProtocol = true;
39777330f729Sjoerg     break;
39787330f729Sjoerg   }
39797330f729Sjoerg 
39807330f729Sjoerg   // Return null for empty list.
39817330f729Sjoerg   if (methods.empty())
39827330f729Sjoerg     return llvm::Constant::getNullValue(forProtocol
39837330f729Sjoerg                                         ? ObjCTypes.MethodDescriptionListPtrTy
39847330f729Sjoerg                                         : ObjCTypes.MethodListPtrTy);
39857330f729Sjoerg 
39867330f729Sjoerg   // For protocols, this is an objc_method_description_list, which has
39877330f729Sjoerg   // a slightly different structure.
39887330f729Sjoerg   if (forProtocol) {
39897330f729Sjoerg     ConstantInitBuilder builder(CGM);
39907330f729Sjoerg     auto values = builder.beginStruct();
39917330f729Sjoerg     values.addInt(ObjCTypes.IntTy, methods.size());
39927330f729Sjoerg     auto methodArray = values.beginArray(ObjCTypes.MethodDescriptionTy);
39937330f729Sjoerg     for (auto MD : methods) {
39947330f729Sjoerg       emitMethodDescriptionConstant(methodArray, MD);
39957330f729Sjoerg     }
39967330f729Sjoerg     methodArray.finishAndAddTo(values);
39977330f729Sjoerg 
39987330f729Sjoerg     llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
39997330f729Sjoerg                                                  CGM.getPointerAlign(), true);
40007330f729Sjoerg     return llvm::ConstantExpr::getBitCast(GV,
40017330f729Sjoerg                                           ObjCTypes.MethodDescriptionListPtrTy);
40027330f729Sjoerg   }
40037330f729Sjoerg 
40047330f729Sjoerg   // Otherwise, it's an objc_method_list.
40057330f729Sjoerg   ConstantInitBuilder builder(CGM);
40067330f729Sjoerg   auto values = builder.beginStruct();
40077330f729Sjoerg   values.addNullPointer(ObjCTypes.Int8PtrTy);
40087330f729Sjoerg   values.addInt(ObjCTypes.IntTy, methods.size());
40097330f729Sjoerg   auto methodArray = values.beginArray(ObjCTypes.MethodTy);
40107330f729Sjoerg   for (auto MD : methods) {
4011*e038c9c4Sjoerg     if (!MD->isDirectMethod())
40127330f729Sjoerg       emitMethodConstant(methodArray, MD);
40137330f729Sjoerg   }
40147330f729Sjoerg   methodArray.finishAndAddTo(values);
40157330f729Sjoerg 
40167330f729Sjoerg   llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
40177330f729Sjoerg                                                CGM.getPointerAlign(), true);
40187330f729Sjoerg   return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListPtrTy);
40197330f729Sjoerg }
40207330f729Sjoerg 
GenerateMethod(const ObjCMethodDecl * OMD,const ObjCContainerDecl * CD)40217330f729Sjoerg llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
40227330f729Sjoerg                                                 const ObjCContainerDecl *CD) {
4023*e038c9c4Sjoerg   llvm::Function *Method;
4024*e038c9c4Sjoerg 
4025*e038c9c4Sjoerg   if (OMD->isDirectMethod()) {
4026*e038c9c4Sjoerg     Method = GenerateDirectMethod(OMD, CD);
4027*e038c9c4Sjoerg   } else {
4028*e038c9c4Sjoerg     auto Name = getSymbolNameForMethod(OMD);
40297330f729Sjoerg 
40307330f729Sjoerg     CodeGenTypes &Types = CGM.getTypes();
40317330f729Sjoerg     llvm::FunctionType *MethodTy =
40327330f729Sjoerg         Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
4033*e038c9c4Sjoerg     Method =
4034*e038c9c4Sjoerg         llvm::Function::Create(MethodTy, llvm::GlobalValue::InternalLinkage,
4035*e038c9c4Sjoerg                                Name, &CGM.getModule());
4036*e038c9c4Sjoerg   }
4037*e038c9c4Sjoerg 
40387330f729Sjoerg   MethodDefinitions.insert(std::make_pair(OMD, Method));
40397330f729Sjoerg 
40407330f729Sjoerg   return Method;
40417330f729Sjoerg }
40427330f729Sjoerg 
4043*e038c9c4Sjoerg llvm::Function *
GenerateDirectMethod(const ObjCMethodDecl * OMD,const ObjCContainerDecl * CD)4044*e038c9c4Sjoerg CGObjCCommonMac::GenerateDirectMethod(const ObjCMethodDecl *OMD,
4045*e038c9c4Sjoerg                                       const ObjCContainerDecl *CD) {
4046*e038c9c4Sjoerg   auto *COMD = OMD->getCanonicalDecl();
4047*e038c9c4Sjoerg   auto I = DirectMethodDefinitions.find(COMD);
4048*e038c9c4Sjoerg   llvm::Function *OldFn = nullptr, *Fn = nullptr;
4049*e038c9c4Sjoerg 
4050*e038c9c4Sjoerg   if (I != DirectMethodDefinitions.end()) {
4051*e038c9c4Sjoerg     // Objective-C allows for the declaration and implementation types
4052*e038c9c4Sjoerg     // to differ slightly.
4053*e038c9c4Sjoerg     //
4054*e038c9c4Sjoerg     // If we're being asked for the Function associated for a method
4055*e038c9c4Sjoerg     // implementation, a previous value might have been cached
4056*e038c9c4Sjoerg     // based on the type of the canonical declaration.
4057*e038c9c4Sjoerg     //
4058*e038c9c4Sjoerg     // If these do not match, then we'll replace this function with
4059*e038c9c4Sjoerg     // a new one that has the proper type below.
4060*e038c9c4Sjoerg     if (!OMD->getBody() || COMD->getReturnType() == OMD->getReturnType())
4061*e038c9c4Sjoerg       return I->second;
4062*e038c9c4Sjoerg     OldFn = I->second;
4063*e038c9c4Sjoerg   }
4064*e038c9c4Sjoerg 
4065*e038c9c4Sjoerg   CodeGenTypes &Types = CGM.getTypes();
4066*e038c9c4Sjoerg   llvm::FunctionType *MethodTy =
4067*e038c9c4Sjoerg     Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
4068*e038c9c4Sjoerg 
4069*e038c9c4Sjoerg   if (OldFn) {
4070*e038c9c4Sjoerg     Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
4071*e038c9c4Sjoerg                                 "", &CGM.getModule());
4072*e038c9c4Sjoerg     Fn->takeName(OldFn);
4073*e038c9c4Sjoerg     OldFn->replaceAllUsesWith(
4074*e038c9c4Sjoerg         llvm::ConstantExpr::getBitCast(Fn, OldFn->getType()));
4075*e038c9c4Sjoerg     OldFn->eraseFromParent();
4076*e038c9c4Sjoerg 
4077*e038c9c4Sjoerg     // Replace the cached function in the map.
4078*e038c9c4Sjoerg     I->second = Fn;
4079*e038c9c4Sjoerg   } else {
4080*e038c9c4Sjoerg     auto Name = getSymbolNameForMethod(OMD, /*include category*/ false);
4081*e038c9c4Sjoerg 
4082*e038c9c4Sjoerg     Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
4083*e038c9c4Sjoerg                                 Name, &CGM.getModule());
4084*e038c9c4Sjoerg     DirectMethodDefinitions.insert(std::make_pair(COMD, Fn));
4085*e038c9c4Sjoerg   }
4086*e038c9c4Sjoerg 
4087*e038c9c4Sjoerg   return Fn;
4088*e038c9c4Sjoerg }
4089*e038c9c4Sjoerg 
GenerateDirectMethodPrologue(CodeGenFunction & CGF,llvm::Function * Fn,const ObjCMethodDecl * OMD,const ObjCContainerDecl * CD)4090*e038c9c4Sjoerg void CGObjCCommonMac::GenerateDirectMethodPrologue(
4091*e038c9c4Sjoerg     CodeGenFunction &CGF, llvm::Function *Fn, const ObjCMethodDecl *OMD,
4092*e038c9c4Sjoerg     const ObjCContainerDecl *CD) {
4093*e038c9c4Sjoerg   auto &Builder = CGF.Builder;
4094*e038c9c4Sjoerg   bool ReceiverCanBeNull = true;
4095*e038c9c4Sjoerg   auto selfAddr = CGF.GetAddrOfLocalVar(OMD->getSelfDecl());
4096*e038c9c4Sjoerg   auto selfValue = Builder.CreateLoad(selfAddr);
4097*e038c9c4Sjoerg 
4098*e038c9c4Sjoerg   // Generate:
4099*e038c9c4Sjoerg   //
4100*e038c9c4Sjoerg   // /* for class methods only to force class lazy initialization */
4101*e038c9c4Sjoerg   // self = [self self];
4102*e038c9c4Sjoerg   //
4103*e038c9c4Sjoerg   // /* unless the receiver is never NULL */
4104*e038c9c4Sjoerg   // if (self == nil) {
4105*e038c9c4Sjoerg   //     return (ReturnType){ };
4106*e038c9c4Sjoerg   // }
4107*e038c9c4Sjoerg   //
4108*e038c9c4Sjoerg   // _cmd = @selector(...)
4109*e038c9c4Sjoerg   // ...
4110*e038c9c4Sjoerg 
4111*e038c9c4Sjoerg   if (OMD->isClassMethod()) {
4112*e038c9c4Sjoerg     const ObjCInterfaceDecl *OID = cast<ObjCInterfaceDecl>(CD);
4113*e038c9c4Sjoerg     assert(OID &&
4114*e038c9c4Sjoerg            "GenerateDirectMethod() should be called with the Class Interface");
4115*e038c9c4Sjoerg     Selector SelfSel = GetNullarySelector("self", CGM.getContext());
4116*e038c9c4Sjoerg     auto ResultType = CGF.getContext().getObjCIdType();
4117*e038c9c4Sjoerg     RValue result;
4118*e038c9c4Sjoerg     CallArgList Args;
4119*e038c9c4Sjoerg 
4120*e038c9c4Sjoerg     // TODO: If this method is inlined, the caller might know that `self` is
4121*e038c9c4Sjoerg     // already initialized; for example, it might be an ordinary Objective-C
4122*e038c9c4Sjoerg     // method which always receives an initialized `self`, or it might have just
4123*e038c9c4Sjoerg     // forced initialization on its own.
4124*e038c9c4Sjoerg     //
4125*e038c9c4Sjoerg     // We should find a way to eliminate this unnecessary initialization in such
4126*e038c9c4Sjoerg     // cases in LLVM.
4127*e038c9c4Sjoerg     result = GeneratePossiblySpecializedMessageSend(
4128*e038c9c4Sjoerg         CGF, ReturnValueSlot(), ResultType, SelfSel, selfValue, Args, OID,
4129*e038c9c4Sjoerg         nullptr, true);
4130*e038c9c4Sjoerg     Builder.CreateStore(result.getScalarVal(), selfAddr);
4131*e038c9c4Sjoerg 
4132*e038c9c4Sjoerg     // Nullable `Class` expressions cannot be messaged with a direct method
4133*e038c9c4Sjoerg     // so the only reason why the receive can be null would be because
4134*e038c9c4Sjoerg     // of weak linking.
4135*e038c9c4Sjoerg     ReceiverCanBeNull = isWeakLinkedClass(OID);
4136*e038c9c4Sjoerg   }
4137*e038c9c4Sjoerg 
4138*e038c9c4Sjoerg   if (ReceiverCanBeNull) {
4139*e038c9c4Sjoerg     llvm::BasicBlock *SelfIsNilBlock =
4140*e038c9c4Sjoerg         CGF.createBasicBlock("objc_direct_method.self_is_nil");
4141*e038c9c4Sjoerg     llvm::BasicBlock *ContBlock =
4142*e038c9c4Sjoerg         CGF.createBasicBlock("objc_direct_method.cont");
4143*e038c9c4Sjoerg 
4144*e038c9c4Sjoerg     // if (self == nil) {
4145*e038c9c4Sjoerg     auto selfTy = cast<llvm::PointerType>(selfValue->getType());
4146*e038c9c4Sjoerg     auto Zero = llvm::ConstantPointerNull::get(selfTy);
4147*e038c9c4Sjoerg 
4148*e038c9c4Sjoerg     llvm::MDBuilder MDHelper(CGM.getLLVMContext());
4149*e038c9c4Sjoerg     Builder.CreateCondBr(Builder.CreateICmpEQ(selfValue, Zero), SelfIsNilBlock,
4150*e038c9c4Sjoerg                          ContBlock, MDHelper.createBranchWeights(1, 1 << 20));
4151*e038c9c4Sjoerg 
4152*e038c9c4Sjoerg     CGF.EmitBlock(SelfIsNilBlock);
4153*e038c9c4Sjoerg 
4154*e038c9c4Sjoerg     //   return (ReturnType){ };
4155*e038c9c4Sjoerg     auto retTy = OMD->getReturnType();
4156*e038c9c4Sjoerg     Builder.SetInsertPoint(SelfIsNilBlock);
4157*e038c9c4Sjoerg     if (!retTy->isVoidType()) {
4158*e038c9c4Sjoerg       CGF.EmitNullInitialization(CGF.ReturnValue, retTy);
4159*e038c9c4Sjoerg     }
4160*e038c9c4Sjoerg     CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
4161*e038c9c4Sjoerg     // }
4162*e038c9c4Sjoerg 
4163*e038c9c4Sjoerg     // rest of the body
4164*e038c9c4Sjoerg     CGF.EmitBlock(ContBlock);
4165*e038c9c4Sjoerg     Builder.SetInsertPoint(ContBlock);
4166*e038c9c4Sjoerg   }
4167*e038c9c4Sjoerg 
4168*e038c9c4Sjoerg   // only synthesize _cmd if it's referenced
4169*e038c9c4Sjoerg   if (OMD->getCmdDecl()->isUsed()) {
4170*e038c9c4Sjoerg     Builder.CreateStore(GetSelector(CGF, OMD),
4171*e038c9c4Sjoerg                         CGF.GetAddrOfLocalVar(OMD->getCmdDecl()));
4172*e038c9c4Sjoerg   }
4173*e038c9c4Sjoerg }
4174*e038c9c4Sjoerg 
CreateMetadataVar(Twine Name,ConstantStructBuilder & Init,StringRef Section,CharUnits Align,bool AddToUsed)41757330f729Sjoerg llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
41767330f729Sjoerg                                                ConstantStructBuilder &Init,
41777330f729Sjoerg                                                          StringRef Section,
41787330f729Sjoerg                                                          CharUnits Align,
41797330f729Sjoerg                                                          bool AddToUsed) {
41807330f729Sjoerg   llvm::GlobalValue::LinkageTypes LT =
41817330f729Sjoerg       getLinkageTypeForObjCMetadata(CGM, Section);
41827330f729Sjoerg   llvm::GlobalVariable *GV =
41837330f729Sjoerg       Init.finishAndCreateGlobal(Name, Align, /*constant*/ false, LT);
41847330f729Sjoerg   if (!Section.empty())
41857330f729Sjoerg     GV->setSection(Section);
41867330f729Sjoerg   if (AddToUsed)
41877330f729Sjoerg     CGM.addCompilerUsedGlobal(GV);
41887330f729Sjoerg   return GV;
41897330f729Sjoerg }
41907330f729Sjoerg 
CreateMetadataVar(Twine Name,llvm::Constant * Init,StringRef Section,CharUnits Align,bool AddToUsed)41917330f729Sjoerg llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
41927330f729Sjoerg                                                          llvm::Constant *Init,
41937330f729Sjoerg                                                          StringRef Section,
41947330f729Sjoerg                                                          CharUnits Align,
41957330f729Sjoerg                                                          bool AddToUsed) {
41967330f729Sjoerg   llvm::Type *Ty = Init->getType();
41977330f729Sjoerg   llvm::GlobalValue::LinkageTypes LT =
41987330f729Sjoerg       getLinkageTypeForObjCMetadata(CGM, Section);
41997330f729Sjoerg   llvm::GlobalVariable *GV =
42007330f729Sjoerg       new llvm::GlobalVariable(CGM.getModule(), Ty, false, LT, Init, Name);
42017330f729Sjoerg   if (!Section.empty())
42027330f729Sjoerg     GV->setSection(Section);
42037330f729Sjoerg   GV->setAlignment(Align.getAsAlign());
42047330f729Sjoerg   if (AddToUsed)
42057330f729Sjoerg     CGM.addCompilerUsedGlobal(GV);
42067330f729Sjoerg   return GV;
42077330f729Sjoerg }
42087330f729Sjoerg 
42097330f729Sjoerg llvm::GlobalVariable *
CreateCStringLiteral(StringRef Name,ObjCLabelType Type,bool ForceNonFragileABI,bool NullTerminate)42107330f729Sjoerg CGObjCCommonMac::CreateCStringLiteral(StringRef Name, ObjCLabelType Type,
42117330f729Sjoerg                                       bool ForceNonFragileABI,
42127330f729Sjoerg                                       bool NullTerminate) {
42137330f729Sjoerg   StringRef Label;
42147330f729Sjoerg   switch (Type) {
42157330f729Sjoerg   case ObjCLabelType::ClassName:     Label = "OBJC_CLASS_NAME_"; break;
42167330f729Sjoerg   case ObjCLabelType::MethodVarName: Label = "OBJC_METH_VAR_NAME_"; break;
42177330f729Sjoerg   case ObjCLabelType::MethodVarType: Label = "OBJC_METH_VAR_TYPE_"; break;
42187330f729Sjoerg   case ObjCLabelType::PropertyName:  Label = "OBJC_PROP_NAME_ATTR_"; break;
42197330f729Sjoerg   }
42207330f729Sjoerg 
42217330f729Sjoerg   bool NonFragile = ForceNonFragileABI || isNonFragileABI();
42227330f729Sjoerg 
42237330f729Sjoerg   StringRef Section;
42247330f729Sjoerg   switch (Type) {
42257330f729Sjoerg   case ObjCLabelType::ClassName:
42267330f729Sjoerg     Section = NonFragile ? "__TEXT,__objc_classname,cstring_literals"
42277330f729Sjoerg                          : "__TEXT,__cstring,cstring_literals";
42287330f729Sjoerg     break;
42297330f729Sjoerg   case ObjCLabelType::MethodVarName:
42307330f729Sjoerg     Section = NonFragile ? "__TEXT,__objc_methname,cstring_literals"
42317330f729Sjoerg                          : "__TEXT,__cstring,cstring_literals";
42327330f729Sjoerg     break;
42337330f729Sjoerg   case ObjCLabelType::MethodVarType:
42347330f729Sjoerg     Section = NonFragile ? "__TEXT,__objc_methtype,cstring_literals"
42357330f729Sjoerg                          : "__TEXT,__cstring,cstring_literals";
42367330f729Sjoerg     break;
42377330f729Sjoerg   case ObjCLabelType::PropertyName:
4238*e038c9c4Sjoerg     Section = NonFragile ? "__TEXT,__objc_methname,cstring_literals"
4239*e038c9c4Sjoerg                          : "__TEXT,__cstring,cstring_literals";
42407330f729Sjoerg     break;
42417330f729Sjoerg   }
42427330f729Sjoerg 
42437330f729Sjoerg   llvm::Constant *Value =
42447330f729Sjoerg       llvm::ConstantDataArray::getString(VMContext, Name, NullTerminate);
42457330f729Sjoerg   llvm::GlobalVariable *GV =
42467330f729Sjoerg       new llvm::GlobalVariable(CGM.getModule(), Value->getType(),
42477330f729Sjoerg                                /*isConstant=*/true,
42487330f729Sjoerg                                llvm::GlobalValue::PrivateLinkage, Value, Label);
42497330f729Sjoerg   if (CGM.getTriple().isOSBinFormatMachO())
42507330f729Sjoerg     GV->setSection(Section);
42517330f729Sjoerg   GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
42527330f729Sjoerg   GV->setAlignment(CharUnits::One().getAsAlign());
42537330f729Sjoerg   CGM.addCompilerUsedGlobal(GV);
42547330f729Sjoerg 
42557330f729Sjoerg   return GV;
42567330f729Sjoerg }
42577330f729Sjoerg 
ModuleInitFunction()42587330f729Sjoerg llvm::Function *CGObjCMac::ModuleInitFunction() {
42597330f729Sjoerg   // Abuse this interface function as a place to finalize.
42607330f729Sjoerg   FinishModule();
42617330f729Sjoerg   return nullptr;
42627330f729Sjoerg }
42637330f729Sjoerg 
GetPropertyGetFunction()42647330f729Sjoerg llvm::FunctionCallee CGObjCMac::GetPropertyGetFunction() {
42657330f729Sjoerg   return ObjCTypes.getGetPropertyFn();
42667330f729Sjoerg }
42677330f729Sjoerg 
GetPropertySetFunction()42687330f729Sjoerg llvm::FunctionCallee CGObjCMac::GetPropertySetFunction() {
42697330f729Sjoerg   return ObjCTypes.getSetPropertyFn();
42707330f729Sjoerg }
42717330f729Sjoerg 
GetOptimizedPropertySetFunction(bool atomic,bool copy)42727330f729Sjoerg llvm::FunctionCallee CGObjCMac::GetOptimizedPropertySetFunction(bool atomic,
42737330f729Sjoerg                                                                 bool copy) {
42747330f729Sjoerg   return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
42757330f729Sjoerg }
42767330f729Sjoerg 
GetGetStructFunction()42777330f729Sjoerg llvm::FunctionCallee CGObjCMac::GetGetStructFunction() {
42787330f729Sjoerg   return ObjCTypes.getCopyStructFn();
42797330f729Sjoerg }
42807330f729Sjoerg 
GetSetStructFunction()42817330f729Sjoerg llvm::FunctionCallee CGObjCMac::GetSetStructFunction() {
42827330f729Sjoerg   return ObjCTypes.getCopyStructFn();
42837330f729Sjoerg }
42847330f729Sjoerg 
GetCppAtomicObjectGetFunction()42857330f729Sjoerg llvm::FunctionCallee CGObjCMac::GetCppAtomicObjectGetFunction() {
42867330f729Sjoerg   return ObjCTypes.getCppAtomicObjectFunction();
42877330f729Sjoerg }
42887330f729Sjoerg 
GetCppAtomicObjectSetFunction()42897330f729Sjoerg llvm::FunctionCallee CGObjCMac::GetCppAtomicObjectSetFunction() {
42907330f729Sjoerg   return ObjCTypes.getCppAtomicObjectFunction();
42917330f729Sjoerg }
42927330f729Sjoerg 
EnumerationMutationFunction()42937330f729Sjoerg llvm::FunctionCallee CGObjCMac::EnumerationMutationFunction() {
42947330f729Sjoerg   return ObjCTypes.getEnumerationMutationFn();
42957330f729Sjoerg }
42967330f729Sjoerg 
EmitTryStmt(CodeGenFunction & CGF,const ObjCAtTryStmt & S)42977330f729Sjoerg void CGObjCMac::EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S) {
42987330f729Sjoerg   return EmitTryOrSynchronizedStmt(CGF, S);
42997330f729Sjoerg }
43007330f729Sjoerg 
EmitSynchronizedStmt(CodeGenFunction & CGF,const ObjCAtSynchronizedStmt & S)43017330f729Sjoerg void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF,
43027330f729Sjoerg                                      const ObjCAtSynchronizedStmt &S) {
43037330f729Sjoerg   return EmitTryOrSynchronizedStmt(CGF, S);
43047330f729Sjoerg }
43057330f729Sjoerg 
43067330f729Sjoerg namespace {
43077330f729Sjoerg   struct PerformFragileFinally final : EHScopeStack::Cleanup {
43087330f729Sjoerg     const Stmt &S;
43097330f729Sjoerg     Address SyncArgSlot;
43107330f729Sjoerg     Address CallTryExitVar;
43117330f729Sjoerg     Address ExceptionData;
43127330f729Sjoerg     ObjCTypesHelper &ObjCTypes;
PerformFragileFinally__anon0cc8f9a20811::PerformFragileFinally43137330f729Sjoerg     PerformFragileFinally(const Stmt *S,
43147330f729Sjoerg                           Address SyncArgSlot,
43157330f729Sjoerg                           Address CallTryExitVar,
43167330f729Sjoerg                           Address ExceptionData,
43177330f729Sjoerg                           ObjCTypesHelper *ObjCTypes)
43187330f729Sjoerg       : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
43197330f729Sjoerg         ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
43207330f729Sjoerg 
Emit__anon0cc8f9a20811::PerformFragileFinally43217330f729Sjoerg     void Emit(CodeGenFunction &CGF, Flags flags) override {
43227330f729Sjoerg       // Check whether we need to call objc_exception_try_exit.
43237330f729Sjoerg       // In optimized code, this branch will always be folded.
43247330f729Sjoerg       llvm::BasicBlock *FinallyCallExit =
43257330f729Sjoerg         CGF.createBasicBlock("finally.call_exit");
43267330f729Sjoerg       llvm::BasicBlock *FinallyNoCallExit =
43277330f729Sjoerg         CGF.createBasicBlock("finally.no_call_exit");
43287330f729Sjoerg       CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar),
43297330f729Sjoerg                                FinallyCallExit, FinallyNoCallExit);
43307330f729Sjoerg 
43317330f729Sjoerg       CGF.EmitBlock(FinallyCallExit);
43327330f729Sjoerg       CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryExitFn(),
43337330f729Sjoerg                                   ExceptionData.getPointer());
43347330f729Sjoerg 
43357330f729Sjoerg       CGF.EmitBlock(FinallyNoCallExit);
43367330f729Sjoerg 
43377330f729Sjoerg       if (isa<ObjCAtTryStmt>(S)) {
43387330f729Sjoerg         if (const ObjCAtFinallyStmt* FinallyStmt =
43397330f729Sjoerg               cast<ObjCAtTryStmt>(S).getFinallyStmt()) {
43407330f729Sjoerg           // Don't try to do the @finally if this is an EH cleanup.
43417330f729Sjoerg           if (flags.isForEHCleanup()) return;
43427330f729Sjoerg 
43437330f729Sjoerg           // Save the current cleanup destination in case there's
43447330f729Sjoerg           // control flow inside the finally statement.
43457330f729Sjoerg           llvm::Value *CurCleanupDest =
43467330f729Sjoerg             CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot());
43477330f729Sjoerg 
43487330f729Sjoerg           CGF.EmitStmt(FinallyStmt->getFinallyBody());
43497330f729Sjoerg 
43507330f729Sjoerg           if (CGF.HaveInsertPoint()) {
43517330f729Sjoerg             CGF.Builder.CreateStore(CurCleanupDest,
43527330f729Sjoerg                                     CGF.getNormalCleanupDestSlot());
43537330f729Sjoerg           } else {
43547330f729Sjoerg             // Currently, the end of the cleanup must always exist.
43557330f729Sjoerg             CGF.EnsureInsertPoint();
43567330f729Sjoerg           }
43577330f729Sjoerg         }
43587330f729Sjoerg       } else {
43597330f729Sjoerg         // Emit objc_sync_exit(expr); as finally's sole statement for
43607330f729Sjoerg         // @synchronized.
43617330f729Sjoerg         llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot);
43627330f729Sjoerg         CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncExitFn(), SyncArg);
43637330f729Sjoerg       }
43647330f729Sjoerg     }
43657330f729Sjoerg   };
43667330f729Sjoerg 
43677330f729Sjoerg   class FragileHazards {
43687330f729Sjoerg     CodeGenFunction &CGF;
43697330f729Sjoerg     SmallVector<llvm::Value*, 20> Locals;
43707330f729Sjoerg     llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry;
43717330f729Sjoerg 
43727330f729Sjoerg     llvm::InlineAsm *ReadHazard;
43737330f729Sjoerg     llvm::InlineAsm *WriteHazard;
43747330f729Sjoerg 
43757330f729Sjoerg     llvm::FunctionType *GetAsmFnType();
43767330f729Sjoerg 
43777330f729Sjoerg     void collectLocals();
43787330f729Sjoerg     void emitReadHazard(CGBuilderTy &Builder);
43797330f729Sjoerg 
43807330f729Sjoerg   public:
43817330f729Sjoerg     FragileHazards(CodeGenFunction &CGF);
43827330f729Sjoerg 
43837330f729Sjoerg     void emitWriteHazard();
43847330f729Sjoerg     void emitHazardsInNewBlocks();
43857330f729Sjoerg   };
43867330f729Sjoerg } // end anonymous namespace
43877330f729Sjoerg 
43887330f729Sjoerg /// Create the fragile-ABI read and write hazards based on the current
43897330f729Sjoerg /// state of the function, which is presumed to be immediately prior
43907330f729Sjoerg /// to a @try block.  These hazards are used to maintain correct
43917330f729Sjoerg /// semantics in the face of optimization and the fragile ABI's
43927330f729Sjoerg /// cavalier use of setjmp/longjmp.
FragileHazards(CodeGenFunction & CGF)43937330f729Sjoerg FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) {
43947330f729Sjoerg   collectLocals();
43957330f729Sjoerg 
43967330f729Sjoerg   if (Locals.empty()) return;
43977330f729Sjoerg 
43987330f729Sjoerg   // Collect all the blocks in the function.
43997330f729Sjoerg   for (llvm::Function::iterator
44007330f729Sjoerg          I = CGF.CurFn->begin(), E = CGF.CurFn->end(); I != E; ++I)
44017330f729Sjoerg     BlocksBeforeTry.insert(&*I);
44027330f729Sjoerg 
44037330f729Sjoerg   llvm::FunctionType *AsmFnTy = GetAsmFnType();
44047330f729Sjoerg 
44057330f729Sjoerg   // Create a read hazard for the allocas.  This inhibits dead-store
44067330f729Sjoerg   // optimizations and forces the values to memory.  This hazard is
44077330f729Sjoerg   // inserted before any 'throwing' calls in the protected scope to
44087330f729Sjoerg   // reflect the possibility that the variables might be read from the
44097330f729Sjoerg   // catch block if the call throws.
44107330f729Sjoerg   {
44117330f729Sjoerg     std::string Constraint;
44127330f729Sjoerg     for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
44137330f729Sjoerg       if (I) Constraint += ',';
44147330f729Sjoerg       Constraint += "*m";
44157330f729Sjoerg     }
44167330f729Sjoerg 
44177330f729Sjoerg     ReadHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
44187330f729Sjoerg   }
44197330f729Sjoerg 
44207330f729Sjoerg   // Create a write hazard for the allocas.  This inhibits folding
44217330f729Sjoerg   // loads across the hazard.  This hazard is inserted at the
44227330f729Sjoerg   // beginning of the catch path to reflect the possibility that the
44237330f729Sjoerg   // variables might have been written within the protected scope.
44247330f729Sjoerg   {
44257330f729Sjoerg     std::string Constraint;
44267330f729Sjoerg     for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
44277330f729Sjoerg       if (I) Constraint += ',';
44287330f729Sjoerg       Constraint += "=*m";
44297330f729Sjoerg     }
44307330f729Sjoerg 
44317330f729Sjoerg     WriteHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
44327330f729Sjoerg   }
44337330f729Sjoerg }
44347330f729Sjoerg 
44357330f729Sjoerg /// Emit a write hazard at the current location.
emitWriteHazard()44367330f729Sjoerg void FragileHazards::emitWriteHazard() {
44377330f729Sjoerg   if (Locals.empty()) return;
44387330f729Sjoerg 
44397330f729Sjoerg   CGF.EmitNounwindRuntimeCall(WriteHazard, Locals);
44407330f729Sjoerg }
44417330f729Sjoerg 
emitReadHazard(CGBuilderTy & Builder)44427330f729Sjoerg void FragileHazards::emitReadHazard(CGBuilderTy &Builder) {
44437330f729Sjoerg   assert(!Locals.empty());
44447330f729Sjoerg   llvm::CallInst *call = Builder.CreateCall(ReadHazard, Locals);
44457330f729Sjoerg   call->setDoesNotThrow();
44467330f729Sjoerg   call->setCallingConv(CGF.getRuntimeCC());
44477330f729Sjoerg }
44487330f729Sjoerg 
44497330f729Sjoerg /// Emit read hazards in all the protected blocks, i.e. all the blocks
44507330f729Sjoerg /// which have been inserted since the beginning of the try.
emitHazardsInNewBlocks()44517330f729Sjoerg void FragileHazards::emitHazardsInNewBlocks() {
44527330f729Sjoerg   if (Locals.empty()) return;
44537330f729Sjoerg 
44547330f729Sjoerg   CGBuilderTy Builder(CGF, CGF.getLLVMContext());
44557330f729Sjoerg 
44567330f729Sjoerg   // Iterate through all blocks, skipping those prior to the try.
44577330f729Sjoerg   for (llvm::Function::iterator
44587330f729Sjoerg          FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); FI != FE; ++FI) {
44597330f729Sjoerg     llvm::BasicBlock &BB = *FI;
44607330f729Sjoerg     if (BlocksBeforeTry.count(&BB)) continue;
44617330f729Sjoerg 
44627330f729Sjoerg     // Walk through all the calls in the block.
44637330f729Sjoerg     for (llvm::BasicBlock::iterator
44647330f729Sjoerg            BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) {
44657330f729Sjoerg       llvm::Instruction &I = *BI;
44667330f729Sjoerg 
44677330f729Sjoerg       // Ignore instructions that aren't non-intrinsic calls.
44687330f729Sjoerg       // These are the only calls that can possibly call longjmp.
44697330f729Sjoerg       if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I))
44707330f729Sjoerg         continue;
44717330f729Sjoerg       if (isa<llvm::IntrinsicInst>(I))
44727330f729Sjoerg         continue;
44737330f729Sjoerg 
44747330f729Sjoerg       // Ignore call sites marked nounwind.  This may be questionable,
44757330f729Sjoerg       // since 'nounwind' doesn't necessarily mean 'does not call longjmp'.
44767330f729Sjoerg       if (cast<llvm::CallBase>(I).doesNotThrow())
44777330f729Sjoerg         continue;
44787330f729Sjoerg 
44797330f729Sjoerg       // Insert a read hazard before the call.  This will ensure that
44807330f729Sjoerg       // any writes to the locals are performed before making the
44817330f729Sjoerg       // call.  If the call throws, then this is sufficient to
44827330f729Sjoerg       // guarantee correctness as long as it doesn't also write to any
44837330f729Sjoerg       // locals.
44847330f729Sjoerg       Builder.SetInsertPoint(&BB, BI);
44857330f729Sjoerg       emitReadHazard(Builder);
44867330f729Sjoerg     }
44877330f729Sjoerg   }
44887330f729Sjoerg }
44897330f729Sjoerg 
addIfPresent(llvm::DenseSet<llvm::Value * > & S,Address V)44907330f729Sjoerg static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, Address V) {
44917330f729Sjoerg   if (V.isValid()) S.insert(V.getPointer());
44927330f729Sjoerg }
44937330f729Sjoerg 
collectLocals()44947330f729Sjoerg void FragileHazards::collectLocals() {
44957330f729Sjoerg   // Compute a set of allocas to ignore.
44967330f729Sjoerg   llvm::DenseSet<llvm::Value*> AllocasToIgnore;
44977330f729Sjoerg   addIfPresent(AllocasToIgnore, CGF.ReturnValue);
44987330f729Sjoerg   addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest);
44997330f729Sjoerg 
45007330f729Sjoerg   // Collect all the allocas currently in the function.  This is
45017330f729Sjoerg   // probably way too aggressive.
45027330f729Sjoerg   llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock();
45037330f729Sjoerg   for (llvm::BasicBlock::iterator
45047330f729Sjoerg          I = Entry.begin(), E = Entry.end(); I != E; ++I)
45057330f729Sjoerg     if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I))
45067330f729Sjoerg       Locals.push_back(&*I);
45077330f729Sjoerg }
45087330f729Sjoerg 
GetAsmFnType()45097330f729Sjoerg llvm::FunctionType *FragileHazards::GetAsmFnType() {
45107330f729Sjoerg   SmallVector<llvm::Type *, 16> tys(Locals.size());
45117330f729Sjoerg   for (unsigned i = 0, e = Locals.size(); i != e; ++i)
45127330f729Sjoerg     tys[i] = Locals[i]->getType();
45137330f729Sjoerg   return llvm::FunctionType::get(CGF.VoidTy, tys, false);
45147330f729Sjoerg }
45157330f729Sjoerg 
45167330f729Sjoerg /*
45177330f729Sjoerg 
45187330f729Sjoerg   Objective-C setjmp-longjmp (sjlj) Exception Handling
45197330f729Sjoerg   --
45207330f729Sjoerg 
45217330f729Sjoerg   A catch buffer is a setjmp buffer plus:
45227330f729Sjoerg     - a pointer to the exception that was caught
45237330f729Sjoerg     - a pointer to the previous exception data buffer
45247330f729Sjoerg     - two pointers of reserved storage
45257330f729Sjoerg   Therefore catch buffers form a stack, with a pointer to the top
45267330f729Sjoerg   of the stack kept in thread-local storage.
45277330f729Sjoerg 
45287330f729Sjoerg   objc_exception_try_enter pushes a catch buffer onto the EH stack.
45297330f729Sjoerg   objc_exception_try_exit pops the given catch buffer, which is
45307330f729Sjoerg     required to be the top of the EH stack.
45317330f729Sjoerg   objc_exception_throw pops the top of the EH stack, writes the
45327330f729Sjoerg     thrown exception into the appropriate field, and longjmps
45337330f729Sjoerg     to the setjmp buffer.  It crashes the process (with a printf
45347330f729Sjoerg     and an abort()) if there are no catch buffers on the stack.
45357330f729Sjoerg   objc_exception_extract just reads the exception pointer out of the
45367330f729Sjoerg     catch buffer.
45377330f729Sjoerg 
45387330f729Sjoerg   There's no reason an implementation couldn't use a light-weight
45397330f729Sjoerg   setjmp here --- something like __builtin_setjmp, but API-compatible
45407330f729Sjoerg   with the heavyweight setjmp.  This will be more important if we ever
45417330f729Sjoerg   want to implement correct ObjC/C++ exception interactions for the
45427330f729Sjoerg   fragile ABI.
45437330f729Sjoerg 
45447330f729Sjoerg   Note that for this use of setjmp/longjmp to be correct, we may need
45457330f729Sjoerg   to mark some local variables volatile: if a non-volatile local
45467330f729Sjoerg   variable is modified between the setjmp and the longjmp, it has
45477330f729Sjoerg   indeterminate value.  For the purposes of LLVM IR, it may be
45487330f729Sjoerg   sufficient to make loads and stores within the @try (to variables
45497330f729Sjoerg   declared outside the @try) volatile.  This is necessary for
45507330f729Sjoerg   optimized correctness, but is not currently being done; this is
45517330f729Sjoerg   being tracked as rdar://problem/8160285
45527330f729Sjoerg 
45537330f729Sjoerg   The basic framework for a @try-catch-finally is as follows:
45547330f729Sjoerg   {
45557330f729Sjoerg   objc_exception_data d;
45567330f729Sjoerg   id _rethrow = null;
45577330f729Sjoerg   bool _call_try_exit = true;
45587330f729Sjoerg 
45597330f729Sjoerg   objc_exception_try_enter(&d);
45607330f729Sjoerg   if (!setjmp(d.jmp_buf)) {
45617330f729Sjoerg   ... try body ...
45627330f729Sjoerg   } else {
45637330f729Sjoerg   // exception path
45647330f729Sjoerg   id _caught = objc_exception_extract(&d);
45657330f729Sjoerg 
45667330f729Sjoerg   // enter new try scope for handlers
45677330f729Sjoerg   if (!setjmp(d.jmp_buf)) {
45687330f729Sjoerg   ... match exception and execute catch blocks ...
45697330f729Sjoerg 
45707330f729Sjoerg   // fell off end, rethrow.
45717330f729Sjoerg   _rethrow = _caught;
45727330f729Sjoerg   ... jump-through-finally to finally_rethrow ...
45737330f729Sjoerg   } else {
45747330f729Sjoerg   // exception in catch block
45757330f729Sjoerg   _rethrow = objc_exception_extract(&d);
45767330f729Sjoerg   _call_try_exit = false;
45777330f729Sjoerg   ... jump-through-finally to finally_rethrow ...
45787330f729Sjoerg   }
45797330f729Sjoerg   }
45807330f729Sjoerg   ... jump-through-finally to finally_end ...
45817330f729Sjoerg 
45827330f729Sjoerg   finally:
45837330f729Sjoerg   if (_call_try_exit)
45847330f729Sjoerg   objc_exception_try_exit(&d);
45857330f729Sjoerg 
45867330f729Sjoerg   ... finally block ....
45877330f729Sjoerg   ... dispatch to finally destination ...
45887330f729Sjoerg 
45897330f729Sjoerg   finally_rethrow:
45907330f729Sjoerg   objc_exception_throw(_rethrow);
45917330f729Sjoerg 
45927330f729Sjoerg   finally_end:
45937330f729Sjoerg   }
45947330f729Sjoerg 
45957330f729Sjoerg   This framework differs slightly from the one gcc uses, in that gcc
45967330f729Sjoerg   uses _rethrow to determine if objc_exception_try_exit should be called
45977330f729Sjoerg   and if the object should be rethrown. This breaks in the face of
45987330f729Sjoerg   throwing nil and introduces unnecessary branches.
45997330f729Sjoerg 
46007330f729Sjoerg   We specialize this framework for a few particular circumstances:
46017330f729Sjoerg 
46027330f729Sjoerg   - If there are no catch blocks, then we avoid emitting the second
46037330f729Sjoerg   exception handling context.
46047330f729Sjoerg 
46057330f729Sjoerg   - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
46067330f729Sjoerg   e)) we avoid emitting the code to rethrow an uncaught exception.
46077330f729Sjoerg 
46087330f729Sjoerg   - FIXME: If there is no @finally block we can do a few more
46097330f729Sjoerg   simplifications.
46107330f729Sjoerg 
46117330f729Sjoerg   Rethrows and Jumps-Through-Finally
46127330f729Sjoerg   --
46137330f729Sjoerg 
46147330f729Sjoerg   '@throw;' is supported by pushing the currently-caught exception
46157330f729Sjoerg   onto ObjCEHStack while the @catch blocks are emitted.
46167330f729Sjoerg 
46177330f729Sjoerg   Branches through the @finally block are handled with an ordinary
46187330f729Sjoerg   normal cleanup.  We do not register an EH cleanup; fragile-ABI ObjC
46197330f729Sjoerg   exceptions are not compatible with C++ exceptions, and this is
46207330f729Sjoerg   hardly the only place where this will go wrong.
46217330f729Sjoerg 
46227330f729Sjoerg   @synchronized(expr) { stmt; } is emitted as if it were:
46237330f729Sjoerg     id synch_value = expr;
46247330f729Sjoerg     objc_sync_enter(synch_value);
46257330f729Sjoerg     @try { stmt; } @finally { objc_sync_exit(synch_value); }
46267330f729Sjoerg */
46277330f729Sjoerg 
EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction & CGF,const Stmt & S)46287330f729Sjoerg void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
46297330f729Sjoerg                                           const Stmt &S) {
46307330f729Sjoerg   bool isTry = isa<ObjCAtTryStmt>(S);
46317330f729Sjoerg 
46327330f729Sjoerg   // A destination for the fall-through edges of the catch handlers to
46337330f729Sjoerg   // jump to.
46347330f729Sjoerg   CodeGenFunction::JumpDest FinallyEnd =
46357330f729Sjoerg     CGF.getJumpDestInCurrentScope("finally.end");
46367330f729Sjoerg 
46377330f729Sjoerg   // A destination for the rethrow edge of the catch handlers to jump
46387330f729Sjoerg   // to.
46397330f729Sjoerg   CodeGenFunction::JumpDest FinallyRethrow =
46407330f729Sjoerg     CGF.getJumpDestInCurrentScope("finally.rethrow");
46417330f729Sjoerg 
46427330f729Sjoerg   // For @synchronized, call objc_sync_enter(sync.expr). The
46437330f729Sjoerg   // evaluation of the expression must occur before we enter the
46447330f729Sjoerg   // @synchronized.  We can't avoid a temp here because we need the
46457330f729Sjoerg   // value to be preserved.  If the backend ever does liveness
46467330f729Sjoerg   // correctly after setjmp, this will be unnecessary.
46477330f729Sjoerg   Address SyncArgSlot = Address::invalid();
46487330f729Sjoerg   if (!isTry) {
46497330f729Sjoerg     llvm::Value *SyncArg =
46507330f729Sjoerg       CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
46517330f729Sjoerg     SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
46527330f729Sjoerg     CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncEnterFn(), SyncArg);
46537330f729Sjoerg 
46547330f729Sjoerg     SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(),
46557330f729Sjoerg                                        CGF.getPointerAlign(), "sync.arg");
46567330f729Sjoerg     CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
46577330f729Sjoerg   }
46587330f729Sjoerg 
46597330f729Sjoerg   // Allocate memory for the setjmp buffer.  This needs to be kept
46607330f729Sjoerg   // live throughout the try and catch blocks.
46617330f729Sjoerg   Address ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
46627330f729Sjoerg                                                CGF.getPointerAlign(),
46637330f729Sjoerg                                                "exceptiondata.ptr");
46647330f729Sjoerg 
46657330f729Sjoerg   // Create the fragile hazards.  Note that this will not capture any
46667330f729Sjoerg   // of the allocas required for exception processing, but will
46677330f729Sjoerg   // capture the current basic block (which extends all the way to the
46687330f729Sjoerg   // setjmp call) as "before the @try".
46697330f729Sjoerg   FragileHazards Hazards(CGF);
46707330f729Sjoerg 
46717330f729Sjoerg   // Create a flag indicating whether the cleanup needs to call
46727330f729Sjoerg   // objc_exception_try_exit.  This is true except when
46737330f729Sjoerg   //   - no catches match and we're branching through the cleanup
46747330f729Sjoerg   //     just to rethrow the exception, or
46757330f729Sjoerg   //   - a catch matched and we're falling out of the catch handler.
46767330f729Sjoerg   // The setjmp-safety rule here is that we should always store to this
46777330f729Sjoerg   // variable in a place that dominates the branch through the cleanup
46787330f729Sjoerg   // without passing through any setjmps.
46797330f729Sjoerg   Address CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
46807330f729Sjoerg                                                 CharUnits::One(),
46817330f729Sjoerg                                                 "_call_try_exit");
46827330f729Sjoerg 
46837330f729Sjoerg   // A slot containing the exception to rethrow.  Only needed when we
46847330f729Sjoerg   // have both a @catch and a @finally.
46857330f729Sjoerg   Address PropagatingExnVar = Address::invalid();
46867330f729Sjoerg 
46877330f729Sjoerg   // Push a normal cleanup to leave the try scope.
46887330f729Sjoerg   CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalAndEHCleanup, &S,
46897330f729Sjoerg                                                  SyncArgSlot,
46907330f729Sjoerg                                                  CallTryExitVar,
46917330f729Sjoerg                                                  ExceptionData,
46927330f729Sjoerg                                                  &ObjCTypes);
46937330f729Sjoerg 
46947330f729Sjoerg   // Enter a try block:
46957330f729Sjoerg   //  - Call objc_exception_try_enter to push ExceptionData on top of
46967330f729Sjoerg   //    the EH stack.
46977330f729Sjoerg   CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(),
46987330f729Sjoerg                               ExceptionData.getPointer());
46997330f729Sjoerg 
47007330f729Sjoerg   //  - Call setjmp on the exception data buffer.
47017330f729Sjoerg   llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
47027330f729Sjoerg   llvm::Value *GEPIndexes[] = { Zero, Zero, Zero };
47037330f729Sjoerg   llvm::Value *SetJmpBuffer = CGF.Builder.CreateGEP(
47047330f729Sjoerg       ObjCTypes.ExceptionDataTy, ExceptionData.getPointer(), GEPIndexes,
47057330f729Sjoerg       "setjmp_buffer");
47067330f729Sjoerg   llvm::CallInst *SetJmpResult = CGF.EmitNounwindRuntimeCall(
47077330f729Sjoerg       ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result");
47087330f729Sjoerg   SetJmpResult->setCanReturnTwice();
47097330f729Sjoerg 
47107330f729Sjoerg   // If setjmp returned 0, enter the protected block; otherwise,
47117330f729Sjoerg   // branch to the handler.
47127330f729Sjoerg   llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
47137330f729Sjoerg   llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
47147330f729Sjoerg   llvm::Value *DidCatch =
47157330f729Sjoerg     CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
47167330f729Sjoerg   CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
47177330f729Sjoerg 
47187330f729Sjoerg   // Emit the protected block.
47197330f729Sjoerg   CGF.EmitBlock(TryBlock);
47207330f729Sjoerg   CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
47217330f729Sjoerg   CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
47227330f729Sjoerg                      : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
47237330f729Sjoerg 
47247330f729Sjoerg   CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP();
47257330f729Sjoerg 
47267330f729Sjoerg   // Emit the exception handler block.
47277330f729Sjoerg   CGF.EmitBlock(TryHandler);
47287330f729Sjoerg 
47297330f729Sjoerg   // Don't optimize loads of the in-scope locals across this point.
47307330f729Sjoerg   Hazards.emitWriteHazard();
47317330f729Sjoerg 
47327330f729Sjoerg   // For a @synchronized (or a @try with no catches), just branch
47337330f729Sjoerg   // through the cleanup to the rethrow block.
47347330f729Sjoerg   if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
47357330f729Sjoerg     // Tell the cleanup not to re-pop the exit.
47367330f729Sjoerg     CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
47377330f729Sjoerg     CGF.EmitBranchThroughCleanup(FinallyRethrow);
47387330f729Sjoerg 
47397330f729Sjoerg   // Otherwise, we have to match against the caught exceptions.
47407330f729Sjoerg   } else {
47417330f729Sjoerg     // Retrieve the exception object.  We may emit multiple blocks but
47427330f729Sjoerg     // nothing can cross this so the value is already in SSA form.
47437330f729Sjoerg     llvm::CallInst *Caught =
47447330f729Sjoerg       CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(),
47457330f729Sjoerg                                   ExceptionData.getPointer(), "caught");
47467330f729Sjoerg 
47477330f729Sjoerg     // Push the exception to rethrow onto the EH value stack for the
47487330f729Sjoerg     // benefit of any @throws in the handlers.
47497330f729Sjoerg     CGF.ObjCEHValueStack.push_back(Caught);
47507330f729Sjoerg 
47517330f729Sjoerg     const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S);
47527330f729Sjoerg 
47537330f729Sjoerg     bool HasFinally = (AtTryStmt->getFinallyStmt() != nullptr);
47547330f729Sjoerg 
47557330f729Sjoerg     llvm::BasicBlock *CatchBlock = nullptr;
47567330f729Sjoerg     llvm::BasicBlock *CatchHandler = nullptr;
47577330f729Sjoerg     if (HasFinally) {
47587330f729Sjoerg       // Save the currently-propagating exception before
47597330f729Sjoerg       // objc_exception_try_enter clears the exception slot.
47607330f729Sjoerg       PropagatingExnVar = CGF.CreateTempAlloca(Caught->getType(),
47617330f729Sjoerg                                                CGF.getPointerAlign(),
47627330f729Sjoerg                                                "propagating_exception");
47637330f729Sjoerg       CGF.Builder.CreateStore(Caught, PropagatingExnVar);
47647330f729Sjoerg 
47657330f729Sjoerg       // Enter a new exception try block (in case a @catch block
47667330f729Sjoerg       // throws an exception).
47677330f729Sjoerg       CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(),
47687330f729Sjoerg                                   ExceptionData.getPointer());
47697330f729Sjoerg 
47707330f729Sjoerg       llvm::CallInst *SetJmpResult =
47717330f729Sjoerg         CGF.EmitNounwindRuntimeCall(ObjCTypes.getSetJmpFn(),
47727330f729Sjoerg                                     SetJmpBuffer, "setjmp.result");
47737330f729Sjoerg       SetJmpResult->setCanReturnTwice();
47747330f729Sjoerg 
47757330f729Sjoerg       llvm::Value *Threw =
47767330f729Sjoerg         CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
47777330f729Sjoerg 
47787330f729Sjoerg       CatchBlock = CGF.createBasicBlock("catch");
47797330f729Sjoerg       CatchHandler = CGF.createBasicBlock("catch_for_catch");
47807330f729Sjoerg       CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
47817330f729Sjoerg 
47827330f729Sjoerg       CGF.EmitBlock(CatchBlock);
47837330f729Sjoerg     }
47847330f729Sjoerg 
47857330f729Sjoerg     CGF.Builder.CreateStore(CGF.Builder.getInt1(HasFinally), CallTryExitVar);
47867330f729Sjoerg 
47877330f729Sjoerg     // Handle catch list. As a special case we check if everything is
47887330f729Sjoerg     // matched and avoid generating code for falling off the end if
47897330f729Sjoerg     // so.
47907330f729Sjoerg     bool AllMatched = false;
47917330f729Sjoerg     for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) {
47927330f729Sjoerg       const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I);
47937330f729Sjoerg 
47947330f729Sjoerg       const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
47957330f729Sjoerg       const ObjCObjectPointerType *OPT = nullptr;
47967330f729Sjoerg 
47977330f729Sjoerg       // catch(...) always matches.
47987330f729Sjoerg       if (!CatchParam) {
47997330f729Sjoerg         AllMatched = true;
48007330f729Sjoerg       } else {
48017330f729Sjoerg         OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
48027330f729Sjoerg 
48037330f729Sjoerg         // catch(id e) always matches under this ABI, since only
48047330f729Sjoerg         // ObjC exceptions end up here in the first place.
48057330f729Sjoerg         // FIXME: For the time being we also match id<X>; this should
48067330f729Sjoerg         // be rejected by Sema instead.
48077330f729Sjoerg         if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
48087330f729Sjoerg           AllMatched = true;
48097330f729Sjoerg       }
48107330f729Sjoerg 
48117330f729Sjoerg       // If this is a catch-all, we don't need to test anything.
48127330f729Sjoerg       if (AllMatched) {
48137330f729Sjoerg         CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
48147330f729Sjoerg 
48157330f729Sjoerg         if (CatchParam) {
48167330f729Sjoerg           CGF.EmitAutoVarDecl(*CatchParam);
48177330f729Sjoerg           assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
48187330f729Sjoerg 
48197330f729Sjoerg           // These types work out because ConvertType(id) == i8*.
48207330f729Sjoerg           EmitInitOfCatchParam(CGF, Caught, CatchParam);
48217330f729Sjoerg         }
48227330f729Sjoerg 
48237330f729Sjoerg         CGF.EmitStmt(CatchStmt->getCatchBody());
48247330f729Sjoerg 
48257330f729Sjoerg         // The scope of the catch variable ends right here.
48267330f729Sjoerg         CatchVarCleanups.ForceCleanup();
48277330f729Sjoerg 
48287330f729Sjoerg         CGF.EmitBranchThroughCleanup(FinallyEnd);
48297330f729Sjoerg         break;
48307330f729Sjoerg       }
48317330f729Sjoerg 
48327330f729Sjoerg       assert(OPT && "Unexpected non-object pointer type in @catch");
48337330f729Sjoerg       const ObjCObjectType *ObjTy = OPT->getObjectType();
48347330f729Sjoerg 
48357330f729Sjoerg       // FIXME: @catch (Class c) ?
48367330f729Sjoerg       ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
48377330f729Sjoerg       assert(IDecl && "Catch parameter must have Objective-C type!");
48387330f729Sjoerg 
48397330f729Sjoerg       // Check if the @catch block matches the exception object.
48407330f729Sjoerg       llvm::Value *Class = EmitClassRef(CGF, IDecl);
48417330f729Sjoerg 
48427330f729Sjoerg       llvm::Value *matchArgs[] = { Class, Caught };
48437330f729Sjoerg       llvm::CallInst *Match =
48447330f729Sjoerg         CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionMatchFn(),
48457330f729Sjoerg                                     matchArgs, "match");
48467330f729Sjoerg 
48477330f729Sjoerg       llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match");
48487330f729Sjoerg       llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next");
48497330f729Sjoerg 
48507330f729Sjoerg       CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
48517330f729Sjoerg                                MatchedBlock, NextCatchBlock);
48527330f729Sjoerg 
48537330f729Sjoerg       // Emit the @catch block.
48547330f729Sjoerg       CGF.EmitBlock(MatchedBlock);
48557330f729Sjoerg 
48567330f729Sjoerg       // Collect any cleanups for the catch variable.  The scope lasts until
48577330f729Sjoerg       // the end of the catch body.
48587330f729Sjoerg       CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
48597330f729Sjoerg 
48607330f729Sjoerg       CGF.EmitAutoVarDecl(*CatchParam);
48617330f729Sjoerg       assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
48627330f729Sjoerg 
48637330f729Sjoerg       // Initialize the catch variable.
48647330f729Sjoerg       llvm::Value *Tmp =
48657330f729Sjoerg         CGF.Builder.CreateBitCast(Caught,
48667330f729Sjoerg                                   CGF.ConvertType(CatchParam->getType()));
48677330f729Sjoerg       EmitInitOfCatchParam(CGF, Tmp, CatchParam);
48687330f729Sjoerg 
48697330f729Sjoerg       CGF.EmitStmt(CatchStmt->getCatchBody());
48707330f729Sjoerg 
48717330f729Sjoerg       // We're done with the catch variable.
48727330f729Sjoerg       CatchVarCleanups.ForceCleanup();
48737330f729Sjoerg 
48747330f729Sjoerg       CGF.EmitBranchThroughCleanup(FinallyEnd);
48757330f729Sjoerg 
48767330f729Sjoerg       CGF.EmitBlock(NextCatchBlock);
48777330f729Sjoerg     }
48787330f729Sjoerg 
48797330f729Sjoerg     CGF.ObjCEHValueStack.pop_back();
48807330f729Sjoerg 
48817330f729Sjoerg     // If nothing wanted anything to do with the caught exception,
48827330f729Sjoerg     // kill the extract call.
48837330f729Sjoerg     if (Caught->use_empty())
48847330f729Sjoerg       Caught->eraseFromParent();
48857330f729Sjoerg 
48867330f729Sjoerg     if (!AllMatched)
48877330f729Sjoerg       CGF.EmitBranchThroughCleanup(FinallyRethrow);
48887330f729Sjoerg 
48897330f729Sjoerg     if (HasFinally) {
48907330f729Sjoerg       // Emit the exception handler for the @catch blocks.
48917330f729Sjoerg       CGF.EmitBlock(CatchHandler);
48927330f729Sjoerg 
48937330f729Sjoerg       // In theory we might now need a write hazard, but actually it's
48947330f729Sjoerg       // unnecessary because there's no local-accessing code between
48957330f729Sjoerg       // the try's write hazard and here.
48967330f729Sjoerg       //Hazards.emitWriteHazard();
48977330f729Sjoerg 
48987330f729Sjoerg       // Extract the new exception and save it to the
48997330f729Sjoerg       // propagating-exception slot.
49007330f729Sjoerg       assert(PropagatingExnVar.isValid());
49017330f729Sjoerg       llvm::CallInst *NewCaught =
49027330f729Sjoerg         CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(),
49037330f729Sjoerg                                     ExceptionData.getPointer(), "caught");
49047330f729Sjoerg       CGF.Builder.CreateStore(NewCaught, PropagatingExnVar);
49057330f729Sjoerg 
49067330f729Sjoerg       // Don't pop the catch handler; the throw already did.
49077330f729Sjoerg       CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
49087330f729Sjoerg       CGF.EmitBranchThroughCleanup(FinallyRethrow);
49097330f729Sjoerg     }
49107330f729Sjoerg   }
49117330f729Sjoerg 
49127330f729Sjoerg   // Insert read hazards as required in the new blocks.
49137330f729Sjoerg   Hazards.emitHazardsInNewBlocks();
49147330f729Sjoerg 
49157330f729Sjoerg   // Pop the cleanup.
49167330f729Sjoerg   CGF.Builder.restoreIP(TryFallthroughIP);
49177330f729Sjoerg   if (CGF.HaveInsertPoint())
49187330f729Sjoerg     CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
49197330f729Sjoerg   CGF.PopCleanupBlock();
49207330f729Sjoerg   CGF.EmitBlock(FinallyEnd.getBlock(), true);
49217330f729Sjoerg 
49227330f729Sjoerg   // Emit the rethrow block.
49237330f729Sjoerg   CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
49247330f729Sjoerg   CGF.EmitBlock(FinallyRethrow.getBlock(), true);
49257330f729Sjoerg   if (CGF.HaveInsertPoint()) {
49267330f729Sjoerg     // If we have a propagating-exception variable, check it.
49277330f729Sjoerg     llvm::Value *PropagatingExn;
49287330f729Sjoerg     if (PropagatingExnVar.isValid()) {
49297330f729Sjoerg       PropagatingExn = CGF.Builder.CreateLoad(PropagatingExnVar);
49307330f729Sjoerg 
49317330f729Sjoerg     // Otherwise, just look in the buffer for the exception to throw.
49327330f729Sjoerg     } else {
49337330f729Sjoerg       llvm::CallInst *Caught =
49347330f729Sjoerg         CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(),
49357330f729Sjoerg                                     ExceptionData.getPointer());
49367330f729Sjoerg       PropagatingExn = Caught;
49377330f729Sjoerg     }
49387330f729Sjoerg 
49397330f729Sjoerg     CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionThrowFn(),
49407330f729Sjoerg                                 PropagatingExn);
49417330f729Sjoerg     CGF.Builder.CreateUnreachable();
49427330f729Sjoerg   }
49437330f729Sjoerg 
49447330f729Sjoerg   CGF.Builder.restoreIP(SavedIP);
49457330f729Sjoerg }
49467330f729Sjoerg 
EmitThrowStmt(CodeGen::CodeGenFunction & CGF,const ObjCAtThrowStmt & S,bool ClearInsertionPoint)49477330f729Sjoerg void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
49487330f729Sjoerg                               const ObjCAtThrowStmt &S,
49497330f729Sjoerg                               bool ClearInsertionPoint) {
49507330f729Sjoerg   llvm::Value *ExceptionAsObject;
49517330f729Sjoerg 
49527330f729Sjoerg   if (const Expr *ThrowExpr = S.getThrowExpr()) {
49537330f729Sjoerg     llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
49547330f729Sjoerg     ExceptionAsObject =
49557330f729Sjoerg       CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
49567330f729Sjoerg   } else {
49577330f729Sjoerg     assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
49587330f729Sjoerg            "Unexpected rethrow outside @catch block.");
49597330f729Sjoerg     ExceptionAsObject = CGF.ObjCEHValueStack.back();
49607330f729Sjoerg   }
49617330f729Sjoerg 
49627330f729Sjoerg   CGF.EmitRuntimeCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
49637330f729Sjoerg     ->setDoesNotReturn();
49647330f729Sjoerg   CGF.Builder.CreateUnreachable();
49657330f729Sjoerg 
49667330f729Sjoerg   // Clear the insertion point to indicate we are in unreachable code.
49677330f729Sjoerg   if (ClearInsertionPoint)
49687330f729Sjoerg     CGF.Builder.ClearInsertionPoint();
49697330f729Sjoerg }
49707330f729Sjoerg 
49717330f729Sjoerg /// EmitObjCWeakRead - Code gen for loading value of a __weak
49727330f729Sjoerg /// object: objc_read_weak (id *src)
49737330f729Sjoerg ///
EmitObjCWeakRead(CodeGen::CodeGenFunction & CGF,Address AddrWeakObj)49747330f729Sjoerg llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
49757330f729Sjoerg                                           Address AddrWeakObj) {
49767330f729Sjoerg   llvm::Type* DestTy = AddrWeakObj.getElementType();
49777330f729Sjoerg   AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
49787330f729Sjoerg                                           ObjCTypes.PtrObjectPtrTy);
49797330f729Sjoerg   llvm::Value *read_weak =
49807330f729Sjoerg     CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(),
49817330f729Sjoerg                                 AddrWeakObj.getPointer(), "weakread");
49827330f729Sjoerg   read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
49837330f729Sjoerg   return read_weak;
49847330f729Sjoerg }
49857330f729Sjoerg 
49867330f729Sjoerg /// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
49877330f729Sjoerg /// objc_assign_weak (id src, id *dst)
49887330f729Sjoerg ///
EmitObjCWeakAssign(CodeGen::CodeGenFunction & CGF,llvm::Value * src,Address dst)49897330f729Sjoerg void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
49907330f729Sjoerg                                    llvm::Value *src, Address dst) {
49917330f729Sjoerg   llvm::Type * SrcTy = src->getType();
49927330f729Sjoerg   if (!isa<llvm::PointerType>(SrcTy)) {
49937330f729Sjoerg     unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
49947330f729Sjoerg     assert(Size <= 8 && "does not support size > 8");
49957330f729Sjoerg     src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
49967330f729Sjoerg                       : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
49977330f729Sjoerg     src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
49987330f729Sjoerg   }
49997330f729Sjoerg   src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
50007330f729Sjoerg   dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
50017330f729Sjoerg   llvm::Value *args[] = { src, dst.getPointer() };
50027330f729Sjoerg   CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(),
50037330f729Sjoerg                               args, "weakassign");
50047330f729Sjoerg }
50057330f729Sjoerg 
50067330f729Sjoerg /// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
50077330f729Sjoerg /// objc_assign_global (id src, id *dst)
50087330f729Sjoerg ///
EmitObjCGlobalAssign(CodeGen::CodeGenFunction & CGF,llvm::Value * src,Address dst,bool threadlocal)50097330f729Sjoerg void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
50107330f729Sjoerg                                      llvm::Value *src, Address dst,
50117330f729Sjoerg                                      bool threadlocal) {
50127330f729Sjoerg   llvm::Type * SrcTy = src->getType();
50137330f729Sjoerg   if (!isa<llvm::PointerType>(SrcTy)) {
50147330f729Sjoerg     unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
50157330f729Sjoerg     assert(Size <= 8 && "does not support size > 8");
50167330f729Sjoerg     src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
50177330f729Sjoerg                       : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
50187330f729Sjoerg     src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
50197330f729Sjoerg   }
50207330f729Sjoerg   src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
50217330f729Sjoerg   dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
50227330f729Sjoerg   llvm::Value *args[] = { src, dst.getPointer() };
50237330f729Sjoerg   if (!threadlocal)
50247330f729Sjoerg     CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(),
50257330f729Sjoerg                                 args, "globalassign");
50267330f729Sjoerg   else
50277330f729Sjoerg     CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(),
50287330f729Sjoerg                                 args, "threadlocalassign");
50297330f729Sjoerg }
50307330f729Sjoerg 
50317330f729Sjoerg /// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
50327330f729Sjoerg /// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
50337330f729Sjoerg ///
EmitObjCIvarAssign(CodeGen::CodeGenFunction & CGF,llvm::Value * src,Address dst,llvm::Value * ivarOffset)50347330f729Sjoerg void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
50357330f729Sjoerg                                    llvm::Value *src, Address dst,
50367330f729Sjoerg                                    llvm::Value *ivarOffset) {
50377330f729Sjoerg   assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
50387330f729Sjoerg   llvm::Type * SrcTy = src->getType();
50397330f729Sjoerg   if (!isa<llvm::PointerType>(SrcTy)) {
50407330f729Sjoerg     unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
50417330f729Sjoerg     assert(Size <= 8 && "does not support size > 8");
50427330f729Sjoerg     src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
50437330f729Sjoerg                       : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
50447330f729Sjoerg     src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
50457330f729Sjoerg   }
50467330f729Sjoerg   src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
50477330f729Sjoerg   dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
50487330f729Sjoerg   llvm::Value *args[] = { src, dst.getPointer(), ivarOffset };
50497330f729Sjoerg   CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
50507330f729Sjoerg }
50517330f729Sjoerg 
50527330f729Sjoerg /// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
50537330f729Sjoerg /// objc_assign_strongCast (id src, id *dst)
50547330f729Sjoerg ///
EmitObjCStrongCastAssign(CodeGen::CodeGenFunction & CGF,llvm::Value * src,Address dst)50557330f729Sjoerg void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
50567330f729Sjoerg                                          llvm::Value *src, Address dst) {
50577330f729Sjoerg   llvm::Type * SrcTy = src->getType();
50587330f729Sjoerg   if (!isa<llvm::PointerType>(SrcTy)) {
50597330f729Sjoerg     unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
50607330f729Sjoerg     assert(Size <= 8 && "does not support size > 8");
50617330f729Sjoerg     src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
50627330f729Sjoerg                       : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
50637330f729Sjoerg     src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
50647330f729Sjoerg   }
50657330f729Sjoerg   src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
50667330f729Sjoerg   dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
50677330f729Sjoerg   llvm::Value *args[] = { src, dst.getPointer() };
50687330f729Sjoerg   CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(),
50697330f729Sjoerg                               args, "strongassign");
50707330f729Sjoerg }
50717330f729Sjoerg 
EmitGCMemmoveCollectable(CodeGen::CodeGenFunction & CGF,Address DestPtr,Address SrcPtr,llvm::Value * size)50727330f729Sjoerg void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
50737330f729Sjoerg                                          Address DestPtr,
50747330f729Sjoerg                                          Address SrcPtr,
50757330f729Sjoerg                                          llvm::Value *size) {
50767330f729Sjoerg   SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
50777330f729Sjoerg   DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
50787330f729Sjoerg   llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), size };
50797330f729Sjoerg   CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
50807330f729Sjoerg }
50817330f729Sjoerg 
50827330f729Sjoerg /// EmitObjCValueForIvar - Code Gen for ivar reference.
50837330f729Sjoerg ///
EmitObjCValueForIvar(CodeGen::CodeGenFunction & CGF,QualType ObjectTy,llvm::Value * BaseValue,const ObjCIvarDecl * Ivar,unsigned CVRQualifiers)50847330f729Sjoerg LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
50857330f729Sjoerg                                        QualType ObjectTy,
50867330f729Sjoerg                                        llvm::Value *BaseValue,
50877330f729Sjoerg                                        const ObjCIvarDecl *Ivar,
50887330f729Sjoerg                                        unsigned CVRQualifiers) {
50897330f729Sjoerg   const ObjCInterfaceDecl *ID =
50907330f729Sjoerg     ObjectTy->castAs<ObjCObjectType>()->getInterface();
50917330f729Sjoerg   return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
50927330f729Sjoerg                                   EmitIvarOffset(CGF, ID, Ivar));
50937330f729Sjoerg }
50947330f729Sjoerg 
EmitIvarOffset(CodeGen::CodeGenFunction & CGF,const ObjCInterfaceDecl * Interface,const ObjCIvarDecl * Ivar)50957330f729Sjoerg llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
50967330f729Sjoerg                                        const ObjCInterfaceDecl *Interface,
50977330f729Sjoerg                                        const ObjCIvarDecl *Ivar) {
50987330f729Sjoerg   uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
50997330f729Sjoerg   return llvm::ConstantInt::get(
51007330f729Sjoerg     CGM.getTypes().ConvertType(CGM.getContext().LongTy),
51017330f729Sjoerg     Offset);
51027330f729Sjoerg }
51037330f729Sjoerg 
51047330f729Sjoerg /* *** Private Interface *** */
51057330f729Sjoerg 
GetSectionName(StringRef Section,StringRef MachOAttributes)51067330f729Sjoerg std::string CGObjCCommonMac::GetSectionName(StringRef Section,
51077330f729Sjoerg                                             StringRef MachOAttributes) {
51087330f729Sjoerg   switch (CGM.getTriple().getObjectFormat()) {
51097330f729Sjoerg   case llvm::Triple::UnknownObjectFormat:
51107330f729Sjoerg     llvm_unreachable("unexpected object file format");
51117330f729Sjoerg   case llvm::Triple::MachO: {
51127330f729Sjoerg     if (MachOAttributes.empty())
51137330f729Sjoerg       return ("__DATA," + Section).str();
51147330f729Sjoerg     return ("__DATA," + Section + "," + MachOAttributes).str();
51157330f729Sjoerg   }
51167330f729Sjoerg   case llvm::Triple::ELF:
51177330f729Sjoerg     assert(Section.substr(0, 2) == "__" &&
51187330f729Sjoerg            "expected the name to begin with __");
51197330f729Sjoerg     return Section.substr(2).str();
51207330f729Sjoerg   case llvm::Triple::COFF:
51217330f729Sjoerg     assert(Section.substr(0, 2) == "__" &&
51227330f729Sjoerg            "expected the name to begin with __");
51237330f729Sjoerg     return ("." + Section.substr(2) + "$B").str();
51247330f729Sjoerg   case llvm::Triple::Wasm:
5125*e038c9c4Sjoerg   case llvm::Triple::GOFF:
51267330f729Sjoerg   case llvm::Triple::XCOFF:
51277330f729Sjoerg     llvm::report_fatal_error(
5128*e038c9c4Sjoerg         "Objective-C support is unimplemented for object file format");
51297330f729Sjoerg   }
51307330f729Sjoerg 
51317330f729Sjoerg   llvm_unreachable("Unhandled llvm::Triple::ObjectFormatType enum");
51327330f729Sjoerg }
51337330f729Sjoerg 
51347330f729Sjoerg /// EmitImageInfo - Emit the image info marker used to encode some module
51357330f729Sjoerg /// level information.
51367330f729Sjoerg ///
51377330f729Sjoerg /// See: <rdr://4810609&4810587&4810587>
51387330f729Sjoerg /// struct IMAGE_INFO {
51397330f729Sjoerg ///   unsigned version;
51407330f729Sjoerg ///   unsigned flags;
51417330f729Sjoerg /// };
51427330f729Sjoerg enum ImageInfoFlags {
51437330f729Sjoerg   eImageInfo_FixAndContinue      = (1 << 0), // This flag is no longer set by clang.
51447330f729Sjoerg   eImageInfo_GarbageCollected    = (1 << 1),
51457330f729Sjoerg   eImageInfo_GCOnly              = (1 << 2),
51467330f729Sjoerg   eImageInfo_OptimizedByDyld     = (1 << 3), // This flag is set by the dyld shared cache.
51477330f729Sjoerg 
51487330f729Sjoerg   // A flag indicating that the module has no instances of a @synthesize of a
51497330f729Sjoerg   // superclass variable. <rdar://problem/6803242>
51507330f729Sjoerg   eImageInfo_CorrectedSynthesize = (1 << 4), // This flag is no longer set by clang.
51517330f729Sjoerg   eImageInfo_ImageIsSimulated    = (1 << 5),
51527330f729Sjoerg   eImageInfo_ClassProperties     = (1 << 6)
51537330f729Sjoerg };
51547330f729Sjoerg 
EmitImageInfo()51557330f729Sjoerg void CGObjCCommonMac::EmitImageInfo() {
51567330f729Sjoerg   unsigned version = 0; // Version is unused?
51577330f729Sjoerg   std::string Section =
51587330f729Sjoerg       (ObjCABI == 1)
51597330f729Sjoerg           ? "__OBJC,__image_info,regular"
51607330f729Sjoerg           : GetSectionName("__objc_imageinfo", "regular,no_dead_strip");
51617330f729Sjoerg 
51627330f729Sjoerg   // Generate module-level named metadata to convey this information to the
51637330f729Sjoerg   // linker and code-gen.
51647330f729Sjoerg   llvm::Module &Mod = CGM.getModule();
51657330f729Sjoerg 
51667330f729Sjoerg   // Add the ObjC ABI version to the module flags.
51677330f729Sjoerg   Mod.addModuleFlag(llvm::Module::Error, "Objective-C Version", ObjCABI);
51687330f729Sjoerg   Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Version",
51697330f729Sjoerg                     version);
51707330f729Sjoerg   Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Section",
51717330f729Sjoerg                     llvm::MDString::get(VMContext, Section));
51727330f729Sjoerg 
5173*e038c9c4Sjoerg   auto Int8Ty = llvm::Type::getInt8Ty(VMContext);
51747330f729Sjoerg   if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
51757330f729Sjoerg     // Non-GC overrides those files which specify GC.
5176*e038c9c4Sjoerg     Mod.addModuleFlag(llvm::Module::Error,
5177*e038c9c4Sjoerg                       "Objective-C Garbage Collection",
5178*e038c9c4Sjoerg                       llvm::ConstantInt::get(Int8Ty,0));
51797330f729Sjoerg   } else {
51807330f729Sjoerg     // Add the ObjC garbage collection value.
51817330f729Sjoerg     Mod.addModuleFlag(llvm::Module::Error,
51827330f729Sjoerg                       "Objective-C Garbage Collection",
5183*e038c9c4Sjoerg                       llvm::ConstantInt::get(Int8Ty,
5184*e038c9c4Sjoerg                         (uint8_t)eImageInfo_GarbageCollected));
51857330f729Sjoerg 
51867330f729Sjoerg     if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) {
51877330f729Sjoerg       // Add the ObjC GC Only value.
51887330f729Sjoerg       Mod.addModuleFlag(llvm::Module::Error, "Objective-C GC Only",
51897330f729Sjoerg                         eImageInfo_GCOnly);
51907330f729Sjoerg 
51917330f729Sjoerg       // Require that GC be specified and set to eImageInfo_GarbageCollected.
51927330f729Sjoerg       llvm::Metadata *Ops[2] = {
51937330f729Sjoerg           llvm::MDString::get(VMContext, "Objective-C Garbage Collection"),
51947330f729Sjoerg           llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
5195*e038c9c4Sjoerg               Int8Ty, eImageInfo_GarbageCollected))};
51967330f729Sjoerg       Mod.addModuleFlag(llvm::Module::Require, "Objective-C GC Only",
51977330f729Sjoerg                         llvm::MDNode::get(VMContext, Ops));
51987330f729Sjoerg     }
51997330f729Sjoerg   }
52007330f729Sjoerg 
52017330f729Sjoerg   // Indicate whether we're compiling this to run on a simulator.
52027330f729Sjoerg   if (CGM.getTarget().getTriple().isSimulatorEnvironment())
52037330f729Sjoerg     Mod.addModuleFlag(llvm::Module::Error, "Objective-C Is Simulated",
52047330f729Sjoerg                       eImageInfo_ImageIsSimulated);
52057330f729Sjoerg 
52067330f729Sjoerg   // Indicate whether we are generating class properties.
52077330f729Sjoerg   Mod.addModuleFlag(llvm::Module::Error, "Objective-C Class Properties",
52087330f729Sjoerg                     eImageInfo_ClassProperties);
52097330f729Sjoerg }
52107330f729Sjoerg 
52117330f729Sjoerg // struct objc_module {
52127330f729Sjoerg //   unsigned long version;
52137330f729Sjoerg //   unsigned long size;
52147330f729Sjoerg //   const char *name;
52157330f729Sjoerg //   Symtab symtab;
52167330f729Sjoerg // };
52177330f729Sjoerg 
52187330f729Sjoerg // FIXME: Get from somewhere
52197330f729Sjoerg static const int ModuleVersion = 7;
52207330f729Sjoerg 
EmitModuleInfo()52217330f729Sjoerg void CGObjCMac::EmitModuleInfo() {
52227330f729Sjoerg   uint64_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ModuleTy);
52237330f729Sjoerg 
52247330f729Sjoerg   ConstantInitBuilder builder(CGM);
52257330f729Sjoerg   auto values = builder.beginStruct(ObjCTypes.ModuleTy);
52267330f729Sjoerg   values.addInt(ObjCTypes.LongTy, ModuleVersion);
52277330f729Sjoerg   values.addInt(ObjCTypes.LongTy, Size);
52287330f729Sjoerg   // This used to be the filename, now it is unused. <rdr://4327263>
52297330f729Sjoerg   values.add(GetClassName(StringRef("")));
52307330f729Sjoerg   values.add(EmitModuleSymbols());
52317330f729Sjoerg   CreateMetadataVar("OBJC_MODULES", values,
52327330f729Sjoerg                     "__OBJC,__module_info,regular,no_dead_strip",
52337330f729Sjoerg                     CGM.getPointerAlign(), true);
52347330f729Sjoerg }
52357330f729Sjoerg 
EmitModuleSymbols()52367330f729Sjoerg llvm::Constant *CGObjCMac::EmitModuleSymbols() {
52377330f729Sjoerg   unsigned NumClasses = DefinedClasses.size();
52387330f729Sjoerg   unsigned NumCategories = DefinedCategories.size();
52397330f729Sjoerg 
52407330f729Sjoerg   // Return null if no symbols were defined.
52417330f729Sjoerg   if (!NumClasses && !NumCategories)
52427330f729Sjoerg     return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
52437330f729Sjoerg 
52447330f729Sjoerg   ConstantInitBuilder builder(CGM);
52457330f729Sjoerg   auto values = builder.beginStruct();
52467330f729Sjoerg   values.addInt(ObjCTypes.LongTy, 0);
52477330f729Sjoerg   values.addNullPointer(ObjCTypes.SelectorPtrTy);
52487330f729Sjoerg   values.addInt(ObjCTypes.ShortTy, NumClasses);
52497330f729Sjoerg   values.addInt(ObjCTypes.ShortTy, NumCategories);
52507330f729Sjoerg 
52517330f729Sjoerg   // The runtime expects exactly the list of defined classes followed
52527330f729Sjoerg   // by the list of defined categories, in a single array.
52537330f729Sjoerg   auto array = values.beginArray(ObjCTypes.Int8PtrTy);
52547330f729Sjoerg   for (unsigned i=0; i<NumClasses; i++) {
52557330f729Sjoerg     const ObjCInterfaceDecl *ID = ImplementedClasses[i];
52567330f729Sjoerg     assert(ID);
52577330f729Sjoerg     if (ObjCImplementationDecl *IMP = ID->getImplementation())
52587330f729Sjoerg       // We are implementing a weak imported interface. Give it external linkage
52597330f729Sjoerg       if (ID->isWeakImported() && !IMP->isWeakImported())
52607330f729Sjoerg         DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
52617330f729Sjoerg 
52627330f729Sjoerg     array.addBitCast(DefinedClasses[i], ObjCTypes.Int8PtrTy);
52637330f729Sjoerg   }
52647330f729Sjoerg   for (unsigned i=0; i<NumCategories; i++)
52657330f729Sjoerg     array.addBitCast(DefinedCategories[i], ObjCTypes.Int8PtrTy);
52667330f729Sjoerg 
52677330f729Sjoerg   array.finishAndAddTo(values);
52687330f729Sjoerg 
52697330f729Sjoerg   llvm::GlobalVariable *GV = CreateMetadataVar(
52707330f729Sjoerg       "OBJC_SYMBOLS", values, "__OBJC,__symbols,regular,no_dead_strip",
52717330f729Sjoerg       CGM.getPointerAlign(), true);
52727330f729Sjoerg   return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
52737330f729Sjoerg }
52747330f729Sjoerg 
EmitClassRefFromId(CodeGenFunction & CGF,IdentifierInfo * II)52757330f729Sjoerg llvm::Value *CGObjCMac::EmitClassRefFromId(CodeGenFunction &CGF,
52767330f729Sjoerg                                            IdentifierInfo *II) {
52777330f729Sjoerg   LazySymbols.insert(II);
52787330f729Sjoerg 
52797330f729Sjoerg   llvm::GlobalVariable *&Entry = ClassReferences[II];
52807330f729Sjoerg 
52817330f729Sjoerg   if (!Entry) {
52827330f729Sjoerg     llvm::Constant *Casted =
52837330f729Sjoerg     llvm::ConstantExpr::getBitCast(GetClassName(II->getName()),
52847330f729Sjoerg                                    ObjCTypes.ClassPtrTy);
52857330f729Sjoerg     Entry = CreateMetadataVar(
52867330f729Sjoerg         "OBJC_CLASS_REFERENCES_", Casted,
52877330f729Sjoerg         "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
52887330f729Sjoerg         CGM.getPointerAlign(), true);
52897330f729Sjoerg   }
52907330f729Sjoerg 
5291*e038c9c4Sjoerg   return CGF.Builder.CreateAlignedLoad(Entry->getValueType(), Entry,
5292*e038c9c4Sjoerg                                        CGF.getPointerAlign());
52937330f729Sjoerg }
52947330f729Sjoerg 
EmitClassRef(CodeGenFunction & CGF,const ObjCInterfaceDecl * ID)52957330f729Sjoerg llvm::Value *CGObjCMac::EmitClassRef(CodeGenFunction &CGF,
52967330f729Sjoerg                                      const ObjCInterfaceDecl *ID) {
52977330f729Sjoerg   // If the class has the objc_runtime_visible attribute, we need to
52987330f729Sjoerg   // use the Objective-C runtime to get the class.
52997330f729Sjoerg   if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
53007330f729Sjoerg     return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
53017330f729Sjoerg 
53027330f729Sjoerg   IdentifierInfo *RuntimeName =
53037330f729Sjoerg       &CGM.getContext().Idents.get(ID->getObjCRuntimeNameAsString());
53047330f729Sjoerg   return EmitClassRefFromId(CGF, RuntimeName);
53057330f729Sjoerg }
53067330f729Sjoerg 
EmitNSAutoreleasePoolClassRef(CodeGenFunction & CGF)53077330f729Sjoerg llvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
53087330f729Sjoerg   IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
53097330f729Sjoerg   return EmitClassRefFromId(CGF, II);
53107330f729Sjoerg }
53117330f729Sjoerg 
EmitSelector(CodeGenFunction & CGF,Selector Sel)53127330f729Sjoerg llvm::Value *CGObjCMac::EmitSelector(CodeGenFunction &CGF, Selector Sel) {
5313*e038c9c4Sjoerg   return CGF.Builder.CreateLoad(EmitSelectorAddr(Sel));
53147330f729Sjoerg }
53157330f729Sjoerg 
EmitSelectorAddr(Selector Sel)5316*e038c9c4Sjoerg Address CGObjCMac::EmitSelectorAddr(Selector Sel) {
5317*e038c9c4Sjoerg   CharUnits Align = CGM.getPointerAlign();
53187330f729Sjoerg 
53197330f729Sjoerg   llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
53207330f729Sjoerg   if (!Entry) {
53217330f729Sjoerg     llvm::Constant *Casted =
53227330f729Sjoerg       llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
53237330f729Sjoerg                                      ObjCTypes.SelectorPtrTy);
53247330f729Sjoerg     Entry = CreateMetadataVar(
53257330f729Sjoerg         "OBJC_SELECTOR_REFERENCES_", Casted,
53267330f729Sjoerg         "__OBJC,__message_refs,literal_pointers,no_dead_strip", Align, true);
53277330f729Sjoerg     Entry->setExternallyInitialized(true);
53287330f729Sjoerg   }
53297330f729Sjoerg 
53307330f729Sjoerg   return Address(Entry, Align);
53317330f729Sjoerg }
53327330f729Sjoerg 
GetClassName(StringRef RuntimeName)53337330f729Sjoerg llvm::Constant *CGObjCCommonMac::GetClassName(StringRef RuntimeName) {
53347330f729Sjoerg     llvm::GlobalVariable *&Entry = ClassNames[RuntimeName];
53357330f729Sjoerg     if (!Entry)
53367330f729Sjoerg       Entry = CreateCStringLiteral(RuntimeName, ObjCLabelType::ClassName);
53377330f729Sjoerg     return getConstantGEP(VMContext, Entry, 0, 0);
53387330f729Sjoerg }
53397330f729Sjoerg 
GetMethodDefinition(const ObjCMethodDecl * MD)53407330f729Sjoerg llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
53417330f729Sjoerg   llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*>::iterator
53427330f729Sjoerg       I = MethodDefinitions.find(MD);
53437330f729Sjoerg   if (I != MethodDefinitions.end())
53447330f729Sjoerg     return I->second;
53457330f729Sjoerg 
53467330f729Sjoerg   return nullptr;
53477330f729Sjoerg }
53487330f729Sjoerg 
53497330f729Sjoerg /// GetIvarLayoutName - Returns a unique constant for the given
53507330f729Sjoerg /// ivar layout bitmap.
GetIvarLayoutName(IdentifierInfo * Ident,const ObjCCommonTypesHelper & ObjCTypes)53517330f729Sjoerg llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
53527330f729Sjoerg                                        const ObjCCommonTypesHelper &ObjCTypes) {
53537330f729Sjoerg   return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
53547330f729Sjoerg }
53557330f729Sjoerg 
visitRecord(const RecordType * RT,CharUnits offset)53567330f729Sjoerg void IvarLayoutBuilder::visitRecord(const RecordType *RT,
53577330f729Sjoerg                                     CharUnits offset) {
53587330f729Sjoerg   const RecordDecl *RD = RT->getDecl();
53597330f729Sjoerg 
53607330f729Sjoerg   // If this is a union, remember that we had one, because it might mess
53617330f729Sjoerg   // up the ordering of layout entries.
53627330f729Sjoerg   if (RD->isUnion())
53637330f729Sjoerg     IsDisordered = true;
53647330f729Sjoerg 
53657330f729Sjoerg   const ASTRecordLayout *recLayout = nullptr;
53667330f729Sjoerg   visitAggregate(RD->field_begin(), RD->field_end(), offset,
53677330f729Sjoerg                  [&](const FieldDecl *field) -> CharUnits {
53687330f729Sjoerg     if (!recLayout)
53697330f729Sjoerg       recLayout = &CGM.getContext().getASTRecordLayout(RD);
53707330f729Sjoerg     auto offsetInBits = recLayout->getFieldOffset(field->getFieldIndex());
53717330f729Sjoerg     return CGM.getContext().toCharUnitsFromBits(offsetInBits);
53727330f729Sjoerg   });
53737330f729Sjoerg }
53747330f729Sjoerg 
53757330f729Sjoerg template <class Iterator, class GetOffsetFn>
visitAggregate(Iterator begin,Iterator end,CharUnits aggregateOffset,const GetOffsetFn & getOffset)53767330f729Sjoerg void IvarLayoutBuilder::visitAggregate(Iterator begin, Iterator end,
53777330f729Sjoerg                                        CharUnits aggregateOffset,
53787330f729Sjoerg                                        const GetOffsetFn &getOffset) {
53797330f729Sjoerg   for (; begin != end; ++begin) {
53807330f729Sjoerg     auto field = *begin;
53817330f729Sjoerg 
53827330f729Sjoerg     // Skip over bitfields.
53837330f729Sjoerg     if (field->isBitField()) {
53847330f729Sjoerg       continue;
53857330f729Sjoerg     }
53867330f729Sjoerg 
53877330f729Sjoerg     // Compute the offset of the field within the aggregate.
53887330f729Sjoerg     CharUnits fieldOffset = aggregateOffset + getOffset(field);
53897330f729Sjoerg 
53907330f729Sjoerg     visitField(field, fieldOffset);
53917330f729Sjoerg   }
53927330f729Sjoerg }
53937330f729Sjoerg 
53947330f729Sjoerg /// Collect layout information for the given fields into IvarsInfo.
visitField(const FieldDecl * field,CharUnits fieldOffset)53957330f729Sjoerg void IvarLayoutBuilder::visitField(const FieldDecl *field,
53967330f729Sjoerg                                    CharUnits fieldOffset) {
53977330f729Sjoerg   QualType fieldType = field->getType();
53987330f729Sjoerg 
53997330f729Sjoerg   // Drill down into arrays.
54007330f729Sjoerg   uint64_t numElts = 1;
54017330f729Sjoerg   if (auto arrayType = CGM.getContext().getAsIncompleteArrayType(fieldType)) {
54027330f729Sjoerg     numElts = 0;
54037330f729Sjoerg     fieldType = arrayType->getElementType();
54047330f729Sjoerg   }
54057330f729Sjoerg   // Unlike incomplete arrays, constant arrays can be nested.
54067330f729Sjoerg   while (auto arrayType = CGM.getContext().getAsConstantArrayType(fieldType)) {
54077330f729Sjoerg     numElts *= arrayType->getSize().getZExtValue();
54087330f729Sjoerg     fieldType = arrayType->getElementType();
54097330f729Sjoerg   }
54107330f729Sjoerg 
54117330f729Sjoerg   assert(!fieldType->isArrayType() && "ivar of non-constant array type?");
54127330f729Sjoerg 
54137330f729Sjoerg   // If we ended up with a zero-sized array, we've done what we can do within
54147330f729Sjoerg   // the limits of this layout encoding.
54157330f729Sjoerg   if (numElts == 0) return;
54167330f729Sjoerg 
54177330f729Sjoerg   // Recurse if the base element type is a record type.
54187330f729Sjoerg   if (auto recType = fieldType->getAs<RecordType>()) {
54197330f729Sjoerg     size_t oldEnd = IvarsInfo.size();
54207330f729Sjoerg 
54217330f729Sjoerg     visitRecord(recType, fieldOffset);
54227330f729Sjoerg 
54237330f729Sjoerg     // If we have an array, replicate the first entry's layout information.
54247330f729Sjoerg     auto numEltEntries = IvarsInfo.size() - oldEnd;
54257330f729Sjoerg     if (numElts != 1 && numEltEntries != 0) {
54267330f729Sjoerg       CharUnits eltSize = CGM.getContext().getTypeSizeInChars(recType);
54277330f729Sjoerg       for (uint64_t eltIndex = 1; eltIndex != numElts; ++eltIndex) {
54287330f729Sjoerg         // Copy the last numEltEntries onto the end of the array, adjusting
54297330f729Sjoerg         // each for the element size.
54307330f729Sjoerg         for (size_t i = 0; i != numEltEntries; ++i) {
54317330f729Sjoerg           auto firstEntry = IvarsInfo[oldEnd + i];
54327330f729Sjoerg           IvarsInfo.push_back(IvarInfo(firstEntry.Offset + eltIndex * eltSize,
54337330f729Sjoerg                                        firstEntry.SizeInWords));
54347330f729Sjoerg         }
54357330f729Sjoerg       }
54367330f729Sjoerg     }
54377330f729Sjoerg 
54387330f729Sjoerg     return;
54397330f729Sjoerg   }
54407330f729Sjoerg 
54417330f729Sjoerg   // Classify the element type.
54427330f729Sjoerg   Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), fieldType);
54437330f729Sjoerg 
54447330f729Sjoerg   // If it matches what we're looking for, add an entry.
54457330f729Sjoerg   if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
54467330f729Sjoerg       || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
54477330f729Sjoerg     assert(CGM.getContext().getTypeSizeInChars(fieldType)
54487330f729Sjoerg              == CGM.getPointerSize());
54497330f729Sjoerg     IvarsInfo.push_back(IvarInfo(fieldOffset, numElts));
54507330f729Sjoerg   }
54517330f729Sjoerg }
54527330f729Sjoerg 
54537330f729Sjoerg /// buildBitmap - This routine does the horsework of taking the offsets of
54547330f729Sjoerg /// strong/weak references and creating a bitmap.  The bitmap is also
54557330f729Sjoerg /// returned in the given buffer, suitable for being passed to \c dump().
buildBitmap(CGObjCCommonMac & CGObjC,llvm::SmallVectorImpl<unsigned char> & buffer)54567330f729Sjoerg llvm::Constant *IvarLayoutBuilder::buildBitmap(CGObjCCommonMac &CGObjC,
54577330f729Sjoerg                                 llvm::SmallVectorImpl<unsigned char> &buffer) {
54587330f729Sjoerg   // The bitmap is a series of skip/scan instructions, aligned to word
54597330f729Sjoerg   // boundaries.  The skip is performed first.
54607330f729Sjoerg   const unsigned char MaxNibble = 0xF;
54617330f729Sjoerg   const unsigned char SkipMask = 0xF0, SkipShift = 4;
54627330f729Sjoerg   const unsigned char ScanMask = 0x0F, ScanShift = 0;
54637330f729Sjoerg 
54647330f729Sjoerg   assert(!IvarsInfo.empty() && "generating bitmap for no data");
54657330f729Sjoerg 
54667330f729Sjoerg   // Sort the ivar info on byte position in case we encounterred a
54677330f729Sjoerg   // union nested in the ivar list.
54687330f729Sjoerg   if (IsDisordered) {
54697330f729Sjoerg     // This isn't a stable sort, but our algorithm should handle it fine.
54707330f729Sjoerg     llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
54717330f729Sjoerg   } else {
5472*e038c9c4Sjoerg     assert(llvm::is_sorted(IvarsInfo));
54737330f729Sjoerg   }
54747330f729Sjoerg   assert(IvarsInfo.back().Offset < InstanceEnd);
54757330f729Sjoerg 
54767330f729Sjoerg   assert(buffer.empty());
54777330f729Sjoerg 
54787330f729Sjoerg   // Skip the next N words.
54797330f729Sjoerg   auto skip = [&](unsigned numWords) {
54807330f729Sjoerg     assert(numWords > 0);
54817330f729Sjoerg 
54827330f729Sjoerg     // Try to merge into the previous byte.  Since scans happen second, we
54837330f729Sjoerg     // can't do this if it includes a scan.
54847330f729Sjoerg     if (!buffer.empty() && !(buffer.back() & ScanMask)) {
54857330f729Sjoerg       unsigned lastSkip = buffer.back() >> SkipShift;
54867330f729Sjoerg       if (lastSkip < MaxNibble) {
54877330f729Sjoerg         unsigned claimed = std::min(MaxNibble - lastSkip, numWords);
54887330f729Sjoerg         numWords -= claimed;
54897330f729Sjoerg         lastSkip += claimed;
54907330f729Sjoerg         buffer.back() = (lastSkip << SkipShift);
54917330f729Sjoerg       }
54927330f729Sjoerg     }
54937330f729Sjoerg 
54947330f729Sjoerg     while (numWords >= MaxNibble) {
54957330f729Sjoerg       buffer.push_back(MaxNibble << SkipShift);
54967330f729Sjoerg       numWords -= MaxNibble;
54977330f729Sjoerg     }
54987330f729Sjoerg     if (numWords) {
54997330f729Sjoerg       buffer.push_back(numWords << SkipShift);
55007330f729Sjoerg     }
55017330f729Sjoerg   };
55027330f729Sjoerg 
55037330f729Sjoerg   // Scan the next N words.
55047330f729Sjoerg   auto scan = [&](unsigned numWords) {
55057330f729Sjoerg     assert(numWords > 0);
55067330f729Sjoerg 
55077330f729Sjoerg     // Try to merge into the previous byte.  Since scans happen second, we can
55087330f729Sjoerg     // do this even if it includes a skip.
55097330f729Sjoerg     if (!buffer.empty()) {
55107330f729Sjoerg       unsigned lastScan = (buffer.back() & ScanMask) >> ScanShift;
55117330f729Sjoerg       if (lastScan < MaxNibble) {
55127330f729Sjoerg         unsigned claimed = std::min(MaxNibble - lastScan, numWords);
55137330f729Sjoerg         numWords -= claimed;
55147330f729Sjoerg         lastScan += claimed;
55157330f729Sjoerg         buffer.back() = (buffer.back() & SkipMask) | (lastScan << ScanShift);
55167330f729Sjoerg       }
55177330f729Sjoerg     }
55187330f729Sjoerg 
55197330f729Sjoerg     while (numWords >= MaxNibble) {
55207330f729Sjoerg       buffer.push_back(MaxNibble << ScanShift);
55217330f729Sjoerg       numWords -= MaxNibble;
55227330f729Sjoerg     }
55237330f729Sjoerg     if (numWords) {
55247330f729Sjoerg       buffer.push_back(numWords << ScanShift);
55257330f729Sjoerg     }
55267330f729Sjoerg   };
55277330f729Sjoerg 
55287330f729Sjoerg   // One past the end of the last scan.
55297330f729Sjoerg   unsigned endOfLastScanInWords = 0;
55307330f729Sjoerg   const CharUnits WordSize = CGM.getPointerSize();
55317330f729Sjoerg 
55327330f729Sjoerg   // Consider all the scan requests.
55337330f729Sjoerg   for (auto &request : IvarsInfo) {
55347330f729Sjoerg     CharUnits beginOfScan = request.Offset - InstanceBegin;
55357330f729Sjoerg 
55367330f729Sjoerg     // Ignore scan requests that don't start at an even multiple of the
55377330f729Sjoerg     // word size.  We can't encode them.
55387330f729Sjoerg     if ((beginOfScan % WordSize) != 0) continue;
55397330f729Sjoerg 
55407330f729Sjoerg     // Ignore scan requests that start before the instance start.
55417330f729Sjoerg     // This assumes that scans never span that boundary.  The boundary
55427330f729Sjoerg     // isn't the true start of the ivars, because in the fragile-ARC case
55437330f729Sjoerg     // it's rounded up to word alignment, but the test above should leave
55447330f729Sjoerg     // us ignoring that possibility.
55457330f729Sjoerg     if (beginOfScan.isNegative()) {
55467330f729Sjoerg       assert(request.Offset + request.SizeInWords * WordSize <= InstanceBegin);
55477330f729Sjoerg       continue;
55487330f729Sjoerg     }
55497330f729Sjoerg 
55507330f729Sjoerg     unsigned beginOfScanInWords = beginOfScan / WordSize;
55517330f729Sjoerg     unsigned endOfScanInWords = beginOfScanInWords + request.SizeInWords;
55527330f729Sjoerg 
55537330f729Sjoerg     // If the scan starts some number of words after the last one ended,
55547330f729Sjoerg     // skip forward.
55557330f729Sjoerg     if (beginOfScanInWords > endOfLastScanInWords) {
55567330f729Sjoerg       skip(beginOfScanInWords - endOfLastScanInWords);
55577330f729Sjoerg 
55587330f729Sjoerg     // Otherwise, start scanning where the last left off.
55597330f729Sjoerg     } else {
55607330f729Sjoerg       beginOfScanInWords = endOfLastScanInWords;
55617330f729Sjoerg 
55627330f729Sjoerg       // If that leaves us with nothing to scan, ignore this request.
55637330f729Sjoerg       if (beginOfScanInWords >= endOfScanInWords) continue;
55647330f729Sjoerg     }
55657330f729Sjoerg 
55667330f729Sjoerg     // Scan to the end of the request.
55677330f729Sjoerg     assert(beginOfScanInWords < endOfScanInWords);
55687330f729Sjoerg     scan(endOfScanInWords - beginOfScanInWords);
55697330f729Sjoerg     endOfLastScanInWords = endOfScanInWords;
55707330f729Sjoerg   }
55717330f729Sjoerg 
55727330f729Sjoerg   if (buffer.empty())
55737330f729Sjoerg     return llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
55747330f729Sjoerg 
55757330f729Sjoerg   // For GC layouts, emit a skip to the end of the allocation so that we
55767330f729Sjoerg   // have precise information about the entire thing.  This isn't useful
55777330f729Sjoerg   // or necessary for the ARC-style layout strings.
55787330f729Sjoerg   if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
55797330f729Sjoerg     unsigned lastOffsetInWords =
55807330f729Sjoerg       (InstanceEnd - InstanceBegin + WordSize - CharUnits::One()) / WordSize;
55817330f729Sjoerg     if (lastOffsetInWords > endOfLastScanInWords) {
55827330f729Sjoerg       skip(lastOffsetInWords - endOfLastScanInWords);
55837330f729Sjoerg     }
55847330f729Sjoerg   }
55857330f729Sjoerg 
55867330f729Sjoerg   // Null terminate the string.
55877330f729Sjoerg   buffer.push_back(0);
55887330f729Sjoerg 
55897330f729Sjoerg   auto *Entry = CGObjC.CreateCStringLiteral(
55907330f729Sjoerg       reinterpret_cast<char *>(buffer.data()), ObjCLabelType::ClassName);
55917330f729Sjoerg   return getConstantGEP(CGM.getLLVMContext(), Entry, 0, 0);
55927330f729Sjoerg }
55937330f729Sjoerg 
55947330f729Sjoerg /// BuildIvarLayout - Builds ivar layout bitmap for the class
55957330f729Sjoerg /// implementation for the __strong or __weak case.
55967330f729Sjoerg /// The layout map displays which words in ivar list must be skipped
55977330f729Sjoerg /// and which must be scanned by GC (see below). String is built of bytes.
55987330f729Sjoerg /// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
55997330f729Sjoerg /// of words to skip and right nibble is count of words to scan. So, each
56007330f729Sjoerg /// nibble represents up to 15 workds to skip or scan. Skipping the rest is
56017330f729Sjoerg /// represented by a 0x00 byte which also ends the string.
56027330f729Sjoerg /// 1. when ForStrongLayout is true, following ivars are scanned:
56037330f729Sjoerg /// - id, Class
56047330f729Sjoerg /// - object *
56057330f729Sjoerg /// - __strong anything
56067330f729Sjoerg ///
56077330f729Sjoerg /// 2. When ForStrongLayout is false, following ivars are scanned:
56087330f729Sjoerg /// - __weak anything
56097330f729Sjoerg ///
56107330f729Sjoerg llvm::Constant *
BuildIvarLayout(const ObjCImplementationDecl * OMD,CharUnits beginOffset,CharUnits endOffset,bool ForStrongLayout,bool HasMRCWeakIvars)56117330f729Sjoerg CGObjCCommonMac::BuildIvarLayout(const ObjCImplementationDecl *OMD,
56127330f729Sjoerg                                  CharUnits beginOffset, CharUnits endOffset,
56137330f729Sjoerg                                  bool ForStrongLayout, bool HasMRCWeakIvars) {
56147330f729Sjoerg   // If this is MRC, and we're either building a strong layout or there
56157330f729Sjoerg   // are no weak ivars, bail out early.
56167330f729Sjoerg   llvm::Type *PtrTy = CGM.Int8PtrTy;
56177330f729Sjoerg   if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
56187330f729Sjoerg       !CGM.getLangOpts().ObjCAutoRefCount &&
56197330f729Sjoerg       (ForStrongLayout || !HasMRCWeakIvars))
56207330f729Sjoerg     return llvm::Constant::getNullValue(PtrTy);
56217330f729Sjoerg 
56227330f729Sjoerg   const ObjCInterfaceDecl *OI = OMD->getClassInterface();
56237330f729Sjoerg   SmallVector<const ObjCIvarDecl*, 32> ivars;
56247330f729Sjoerg 
56257330f729Sjoerg   // GC layout strings include the complete object layout, possibly
56267330f729Sjoerg   // inaccurately in the non-fragile ABI; the runtime knows how to fix this
56277330f729Sjoerg   // up.
56287330f729Sjoerg   //
56297330f729Sjoerg   // ARC layout strings only include the class's ivars.  In non-fragile
56307330f729Sjoerg   // runtimes, that means starting at InstanceStart, rounded up to word
56317330f729Sjoerg   // alignment.  In fragile runtimes, there's no InstanceStart, so it means
56327330f729Sjoerg   // starting at the offset of the first ivar, rounded up to word alignment.
56337330f729Sjoerg   //
56347330f729Sjoerg   // MRC weak layout strings follow the ARC style.
56357330f729Sjoerg   CharUnits baseOffset;
56367330f729Sjoerg   if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
56377330f729Sjoerg     for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin();
56387330f729Sjoerg          IVD; IVD = IVD->getNextIvar())
56397330f729Sjoerg       ivars.push_back(IVD);
56407330f729Sjoerg 
56417330f729Sjoerg     if (isNonFragileABI()) {
56427330f729Sjoerg       baseOffset = beginOffset; // InstanceStart
56437330f729Sjoerg     } else if (!ivars.empty()) {
56447330f729Sjoerg       baseOffset =
56457330f729Sjoerg         CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivars[0]));
56467330f729Sjoerg     } else {
56477330f729Sjoerg       baseOffset = CharUnits::Zero();
56487330f729Sjoerg     }
56497330f729Sjoerg 
56507330f729Sjoerg     baseOffset = baseOffset.alignTo(CGM.getPointerAlign());
56517330f729Sjoerg   }
56527330f729Sjoerg   else {
56537330f729Sjoerg     CGM.getContext().DeepCollectObjCIvars(OI, true, ivars);
56547330f729Sjoerg 
56557330f729Sjoerg     baseOffset = CharUnits::Zero();
56567330f729Sjoerg   }
56577330f729Sjoerg 
56587330f729Sjoerg   if (ivars.empty())
56597330f729Sjoerg     return llvm::Constant::getNullValue(PtrTy);
56607330f729Sjoerg 
56617330f729Sjoerg   IvarLayoutBuilder builder(CGM, baseOffset, endOffset, ForStrongLayout);
56627330f729Sjoerg 
56637330f729Sjoerg   builder.visitAggregate(ivars.begin(), ivars.end(), CharUnits::Zero(),
56647330f729Sjoerg                          [&](const ObjCIvarDecl *ivar) -> CharUnits {
56657330f729Sjoerg       return CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivar));
56667330f729Sjoerg   });
56677330f729Sjoerg 
56687330f729Sjoerg   if (!builder.hasBitmapData())
56697330f729Sjoerg     return llvm::Constant::getNullValue(PtrTy);
56707330f729Sjoerg 
56717330f729Sjoerg   llvm::SmallVector<unsigned char, 4> buffer;
56727330f729Sjoerg   llvm::Constant *C = builder.buildBitmap(*this, buffer);
56737330f729Sjoerg 
56747330f729Sjoerg    if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
56757330f729Sjoerg     printf("\n%s ivar layout for class '%s': ",
56767330f729Sjoerg            ForStrongLayout ? "strong" : "weak",
56777330f729Sjoerg            OMD->getClassInterface()->getName().str().c_str());
56787330f729Sjoerg     builder.dump(buffer);
56797330f729Sjoerg   }
56807330f729Sjoerg   return C;
56817330f729Sjoerg }
56827330f729Sjoerg 
GetMethodVarName(Selector Sel)56837330f729Sjoerg llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
56847330f729Sjoerg   llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
56857330f729Sjoerg   // FIXME: Avoid std::string in "Sel.getAsString()"
56867330f729Sjoerg   if (!Entry)
56877330f729Sjoerg     Entry = CreateCStringLiteral(Sel.getAsString(), ObjCLabelType::MethodVarName);
56887330f729Sjoerg   return getConstantGEP(VMContext, Entry, 0, 0);
56897330f729Sjoerg }
56907330f729Sjoerg 
56917330f729Sjoerg // FIXME: Merge into a single cstring creation function.
GetMethodVarName(IdentifierInfo * ID)56927330f729Sjoerg llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
56937330f729Sjoerg   return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
56947330f729Sjoerg }
56957330f729Sjoerg 
GetMethodVarType(const FieldDecl * Field)56967330f729Sjoerg llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
56977330f729Sjoerg   std::string TypeStr;
56987330f729Sjoerg   CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
56997330f729Sjoerg 
57007330f729Sjoerg   llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
57017330f729Sjoerg   if (!Entry)
57027330f729Sjoerg     Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
57037330f729Sjoerg   return getConstantGEP(VMContext, Entry, 0, 0);
57047330f729Sjoerg }
57057330f729Sjoerg 
GetMethodVarType(const ObjCMethodDecl * D,bool Extended)57067330f729Sjoerg llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D,
57077330f729Sjoerg                                                   bool Extended) {
57087330f729Sjoerg   std::string TypeStr =
57097330f729Sjoerg     CGM.getContext().getObjCEncodingForMethodDecl(D, Extended);
57107330f729Sjoerg 
57117330f729Sjoerg   llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
57127330f729Sjoerg   if (!Entry)
57137330f729Sjoerg     Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
57147330f729Sjoerg   return getConstantGEP(VMContext, Entry, 0, 0);
57157330f729Sjoerg }
57167330f729Sjoerg 
57177330f729Sjoerg // FIXME: Merge into a single cstring creation function.
GetPropertyName(IdentifierInfo * Ident)57187330f729Sjoerg llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
57197330f729Sjoerg   llvm::GlobalVariable *&Entry = PropertyNames[Ident];
57207330f729Sjoerg   if (!Entry)
57217330f729Sjoerg     Entry = CreateCStringLiteral(Ident->getName(), ObjCLabelType::PropertyName);
57227330f729Sjoerg   return getConstantGEP(VMContext, Entry, 0, 0);
57237330f729Sjoerg }
57247330f729Sjoerg 
57257330f729Sjoerg // FIXME: Merge into a single cstring creation function.
57267330f729Sjoerg // FIXME: This Decl should be more precise.
57277330f729Sjoerg llvm::Constant *
GetPropertyTypeString(const ObjCPropertyDecl * PD,const Decl * Container)57287330f729Sjoerg CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
57297330f729Sjoerg                                        const Decl *Container) {
57307330f729Sjoerg   std::string TypeStr =
57317330f729Sjoerg     CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container);
57327330f729Sjoerg   return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
57337330f729Sjoerg }
57347330f729Sjoerg 
FinishModule()57357330f729Sjoerg void CGObjCMac::FinishModule() {
57367330f729Sjoerg   EmitModuleInfo();
57377330f729Sjoerg 
57387330f729Sjoerg   // Emit the dummy bodies for any protocols which were referenced but
57397330f729Sjoerg   // never defined.
57407330f729Sjoerg   for (auto &entry : Protocols) {
57417330f729Sjoerg     llvm::GlobalVariable *global = entry.second;
57427330f729Sjoerg     if (global->hasInitializer())
57437330f729Sjoerg       continue;
57447330f729Sjoerg 
57457330f729Sjoerg     ConstantInitBuilder builder(CGM);
57467330f729Sjoerg     auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
57477330f729Sjoerg     values.addNullPointer(ObjCTypes.ProtocolExtensionPtrTy);
57487330f729Sjoerg     values.add(GetClassName(entry.first->getName()));
57497330f729Sjoerg     values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
57507330f729Sjoerg     values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
57517330f729Sjoerg     values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
57527330f729Sjoerg     values.finishAndSetAsInitializer(global);
57537330f729Sjoerg     CGM.addCompilerUsedGlobal(global);
57547330f729Sjoerg   }
57557330f729Sjoerg 
57567330f729Sjoerg   // Add assembler directives to add lazy undefined symbol references
57577330f729Sjoerg   // for classes which are referenced but not defined. This is
57587330f729Sjoerg   // important for correct linker interaction.
57597330f729Sjoerg   //
57607330f729Sjoerg   // FIXME: It would be nice if we had an LLVM construct for this.
57617330f729Sjoerg   if ((!LazySymbols.empty() || !DefinedSymbols.empty()) &&
57627330f729Sjoerg       CGM.getTriple().isOSBinFormatMachO()) {
57637330f729Sjoerg     SmallString<256> Asm;
57647330f729Sjoerg     Asm += CGM.getModule().getModuleInlineAsm();
57657330f729Sjoerg     if (!Asm.empty() && Asm.back() != '\n')
57667330f729Sjoerg       Asm += '\n';
57677330f729Sjoerg 
57687330f729Sjoerg     llvm::raw_svector_ostream OS(Asm);
57697330f729Sjoerg     for (const auto *Sym : DefinedSymbols)
57707330f729Sjoerg       OS << "\t.objc_class_name_" << Sym->getName() << "=0\n"
57717330f729Sjoerg          << "\t.globl .objc_class_name_" << Sym->getName() << "\n";
57727330f729Sjoerg     for (const auto *Sym : LazySymbols)
57737330f729Sjoerg       OS << "\t.lazy_reference .objc_class_name_" << Sym->getName() << "\n";
57747330f729Sjoerg     for (const auto &Category : DefinedCategoryNames)
57757330f729Sjoerg       OS << "\t.objc_category_name_" << Category << "=0\n"
57767330f729Sjoerg          << "\t.globl .objc_category_name_" << Category << "\n";
57777330f729Sjoerg 
57787330f729Sjoerg     CGM.getModule().setModuleInlineAsm(OS.str());
57797330f729Sjoerg   }
57807330f729Sjoerg }
57817330f729Sjoerg 
CGObjCNonFragileABIMac(CodeGen::CodeGenModule & cgm)57827330f729Sjoerg CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
57837330f729Sjoerg     : CGObjCCommonMac(cgm), ObjCTypes(cgm), ObjCEmptyCacheVar(nullptr),
57847330f729Sjoerg       ObjCEmptyVtableVar(nullptr) {
57857330f729Sjoerg   ObjCABI = 2;
57867330f729Sjoerg }
57877330f729Sjoerg 
57887330f729Sjoerg /* *** */
57897330f729Sjoerg 
ObjCCommonTypesHelper(CodeGen::CodeGenModule & cgm)57907330f729Sjoerg ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
57917330f729Sjoerg   : VMContext(cgm.getLLVMContext()), CGM(cgm), ExternalProtocolPtrTy(nullptr)
57927330f729Sjoerg {
57937330f729Sjoerg   CodeGen::CodeGenTypes &Types = CGM.getTypes();
57947330f729Sjoerg   ASTContext &Ctx = CGM.getContext();
57957330f729Sjoerg 
57967330f729Sjoerg   ShortTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.ShortTy));
57977330f729Sjoerg   IntTy = CGM.IntTy;
57987330f729Sjoerg   LongTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.LongTy));
57997330f729Sjoerg   Int8PtrTy = CGM.Int8PtrTy;
58007330f729Sjoerg   Int8PtrPtrTy = CGM.Int8PtrPtrTy;
58017330f729Sjoerg 
58027330f729Sjoerg   // arm64 targets use "int" ivar offset variables. All others,
58037330f729Sjoerg   // including OS X x86_64 and Windows x86_64, use "long" ivar offsets.
58047330f729Sjoerg   if (CGM.getTarget().getTriple().getArch() == llvm::Triple::aarch64)
58057330f729Sjoerg     IvarOffsetVarTy = IntTy;
58067330f729Sjoerg   else
58077330f729Sjoerg     IvarOffsetVarTy = LongTy;
58087330f729Sjoerg 
58097330f729Sjoerg   ObjectPtrTy =
58107330f729Sjoerg     cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCIdType()));
58117330f729Sjoerg   PtrObjectPtrTy =
58127330f729Sjoerg     llvm::PointerType::getUnqual(ObjectPtrTy);
58137330f729Sjoerg   SelectorPtrTy =
58147330f729Sjoerg     cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCSelType()));
58157330f729Sjoerg 
58167330f729Sjoerg   // I'm not sure I like this. The implicit coordination is a bit
58177330f729Sjoerg   // gross. We should solve this in a reasonable fashion because this
58187330f729Sjoerg   // is a pretty common task (match some runtime data structure with
58197330f729Sjoerg   // an LLVM data structure).
58207330f729Sjoerg 
58217330f729Sjoerg   // FIXME: This is leaked.
58227330f729Sjoerg   // FIXME: Merge with rewriter code?
58237330f729Sjoerg 
58247330f729Sjoerg   // struct _objc_super {
58257330f729Sjoerg   //   id self;
58267330f729Sjoerg   //   Class cls;
58277330f729Sjoerg   // }
58287330f729Sjoerg   RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
58297330f729Sjoerg                                       Ctx.getTranslationUnitDecl(),
58307330f729Sjoerg                                       SourceLocation(), SourceLocation(),
58317330f729Sjoerg                                       &Ctx.Idents.get("_objc_super"));
58327330f729Sjoerg   RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
58337330f729Sjoerg                                 nullptr, Ctx.getObjCIdType(), nullptr, nullptr,
58347330f729Sjoerg                                 false, ICIS_NoInit));
58357330f729Sjoerg   RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
58367330f729Sjoerg                                 nullptr, Ctx.getObjCClassType(), nullptr,
58377330f729Sjoerg                                 nullptr, false, ICIS_NoInit));
58387330f729Sjoerg   RD->completeDefinition();
58397330f729Sjoerg 
58407330f729Sjoerg   SuperCTy = Ctx.getTagDeclType(RD);
58417330f729Sjoerg   SuperPtrCTy = Ctx.getPointerType(SuperCTy);
58427330f729Sjoerg 
58437330f729Sjoerg   SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
58447330f729Sjoerg   SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
58457330f729Sjoerg 
58467330f729Sjoerg   // struct _prop_t {
58477330f729Sjoerg   //   char *name;
58487330f729Sjoerg   //   char *attributes;
58497330f729Sjoerg   // }
58507330f729Sjoerg   PropertyTy = llvm::StructType::create("struct._prop_t", Int8PtrTy, Int8PtrTy);
58517330f729Sjoerg 
58527330f729Sjoerg   // struct _prop_list_t {
58537330f729Sjoerg   //   uint32_t entsize;      // sizeof(struct _prop_t)
58547330f729Sjoerg   //   uint32_t count_of_properties;
58557330f729Sjoerg   //   struct _prop_t prop_list[count_of_properties];
58567330f729Sjoerg   // }
58577330f729Sjoerg   PropertyListTy = llvm::StructType::create(
58587330f729Sjoerg       "struct._prop_list_t", IntTy, IntTy, llvm::ArrayType::get(PropertyTy, 0));
58597330f729Sjoerg   // struct _prop_list_t *
58607330f729Sjoerg   PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
58617330f729Sjoerg 
58627330f729Sjoerg   // struct _objc_method {
58637330f729Sjoerg   //   SEL _cmd;
58647330f729Sjoerg   //   char *method_type;
58657330f729Sjoerg   //   char *_imp;
58667330f729Sjoerg   // }
58677330f729Sjoerg   MethodTy = llvm::StructType::create("struct._objc_method", SelectorPtrTy,
58687330f729Sjoerg                                       Int8PtrTy, Int8PtrTy);
58697330f729Sjoerg 
58707330f729Sjoerg   // struct _objc_cache *
58717330f729Sjoerg   CacheTy = llvm::StructType::create(VMContext, "struct._objc_cache");
58727330f729Sjoerg   CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
58737330f729Sjoerg }
58747330f729Sjoerg 
ObjCTypesHelper(CodeGen::CodeGenModule & cgm)58757330f729Sjoerg ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
58767330f729Sjoerg   : ObjCCommonTypesHelper(cgm) {
58777330f729Sjoerg   // struct _objc_method_description {
58787330f729Sjoerg   //   SEL name;
58797330f729Sjoerg   //   char *types;
58807330f729Sjoerg   // }
58817330f729Sjoerg   MethodDescriptionTy = llvm::StructType::create(
58827330f729Sjoerg       "struct._objc_method_description", SelectorPtrTy, Int8PtrTy);
58837330f729Sjoerg 
58847330f729Sjoerg   // struct _objc_method_description_list {
58857330f729Sjoerg   //   int count;
58867330f729Sjoerg   //   struct _objc_method_description[1];
58877330f729Sjoerg   // }
58887330f729Sjoerg   MethodDescriptionListTy =
58897330f729Sjoerg       llvm::StructType::create("struct._objc_method_description_list", IntTy,
58907330f729Sjoerg                                llvm::ArrayType::get(MethodDescriptionTy, 0));
58917330f729Sjoerg 
58927330f729Sjoerg   // struct _objc_method_description_list *
58937330f729Sjoerg   MethodDescriptionListPtrTy =
58947330f729Sjoerg     llvm::PointerType::getUnqual(MethodDescriptionListTy);
58957330f729Sjoerg 
58967330f729Sjoerg   // Protocol description structures
58977330f729Sjoerg 
58987330f729Sjoerg   // struct _objc_protocol_extension {
58997330f729Sjoerg   //   uint32_t size;  // sizeof(struct _objc_protocol_extension)
59007330f729Sjoerg   //   struct _objc_method_description_list *optional_instance_methods;
59017330f729Sjoerg   //   struct _objc_method_description_list *optional_class_methods;
59027330f729Sjoerg   //   struct _objc_property_list *instance_properties;
59037330f729Sjoerg   //   const char ** extendedMethodTypes;
59047330f729Sjoerg   //   struct _objc_property_list *class_properties;
59057330f729Sjoerg   // }
59067330f729Sjoerg   ProtocolExtensionTy = llvm::StructType::create(
59077330f729Sjoerg       "struct._objc_protocol_extension", IntTy, MethodDescriptionListPtrTy,
59087330f729Sjoerg       MethodDescriptionListPtrTy, PropertyListPtrTy, Int8PtrPtrTy,
59097330f729Sjoerg       PropertyListPtrTy);
59107330f729Sjoerg 
59117330f729Sjoerg   // struct _objc_protocol_extension *
59127330f729Sjoerg   ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
59137330f729Sjoerg 
59147330f729Sjoerg   // Handle recursive construction of Protocol and ProtocolList types
59157330f729Sjoerg 
59167330f729Sjoerg   ProtocolTy =
59177330f729Sjoerg     llvm::StructType::create(VMContext, "struct._objc_protocol");
59187330f729Sjoerg 
59197330f729Sjoerg   ProtocolListTy =
59207330f729Sjoerg     llvm::StructType::create(VMContext, "struct._objc_protocol_list");
59217330f729Sjoerg   ProtocolListTy->setBody(llvm::PointerType::getUnqual(ProtocolListTy), LongTy,
59227330f729Sjoerg                           llvm::ArrayType::get(ProtocolTy, 0));
59237330f729Sjoerg 
59247330f729Sjoerg   // struct _objc_protocol {
59257330f729Sjoerg   //   struct _objc_protocol_extension *isa;
59267330f729Sjoerg   //   char *protocol_name;
59277330f729Sjoerg   //   struct _objc_protocol **_objc_protocol_list;
59287330f729Sjoerg   //   struct _objc_method_description_list *instance_methods;
59297330f729Sjoerg   //   struct _objc_method_description_list *class_methods;
59307330f729Sjoerg   // }
59317330f729Sjoerg   ProtocolTy->setBody(ProtocolExtensionPtrTy, Int8PtrTy,
59327330f729Sjoerg                       llvm::PointerType::getUnqual(ProtocolListTy),
59337330f729Sjoerg                       MethodDescriptionListPtrTy, MethodDescriptionListPtrTy);
59347330f729Sjoerg 
59357330f729Sjoerg   // struct _objc_protocol_list *
59367330f729Sjoerg   ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
59377330f729Sjoerg 
59387330f729Sjoerg   ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
59397330f729Sjoerg 
59407330f729Sjoerg   // Class description structures
59417330f729Sjoerg 
59427330f729Sjoerg   // struct _objc_ivar {
59437330f729Sjoerg   //   char *ivar_name;
59447330f729Sjoerg   //   char *ivar_type;
59457330f729Sjoerg   //   int  ivar_offset;
59467330f729Sjoerg   // }
59477330f729Sjoerg   IvarTy = llvm::StructType::create("struct._objc_ivar", Int8PtrTy, Int8PtrTy,
59487330f729Sjoerg                                     IntTy);
59497330f729Sjoerg 
59507330f729Sjoerg   // struct _objc_ivar_list *
59517330f729Sjoerg   IvarListTy =
59527330f729Sjoerg     llvm::StructType::create(VMContext, "struct._objc_ivar_list");
59537330f729Sjoerg   IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
59547330f729Sjoerg 
59557330f729Sjoerg   // struct _objc_method_list *
59567330f729Sjoerg   MethodListTy =
59577330f729Sjoerg     llvm::StructType::create(VMContext, "struct._objc_method_list");
59587330f729Sjoerg   MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
59597330f729Sjoerg 
59607330f729Sjoerg   // struct _objc_class_extension *
59617330f729Sjoerg   ClassExtensionTy = llvm::StructType::create(
59627330f729Sjoerg       "struct._objc_class_extension", IntTy, Int8PtrTy, PropertyListPtrTy);
59637330f729Sjoerg   ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
59647330f729Sjoerg 
59657330f729Sjoerg   ClassTy = llvm::StructType::create(VMContext, "struct._objc_class");
59667330f729Sjoerg 
59677330f729Sjoerg   // struct _objc_class {
59687330f729Sjoerg   //   Class isa;
59697330f729Sjoerg   //   Class super_class;
59707330f729Sjoerg   //   char *name;
59717330f729Sjoerg   //   long version;
59727330f729Sjoerg   //   long info;
59737330f729Sjoerg   //   long instance_size;
59747330f729Sjoerg   //   struct _objc_ivar_list *ivars;
59757330f729Sjoerg   //   struct _objc_method_list *methods;
59767330f729Sjoerg   //   struct _objc_cache *cache;
59777330f729Sjoerg   //   struct _objc_protocol_list *protocols;
59787330f729Sjoerg   //   char *ivar_layout;
59797330f729Sjoerg   //   struct _objc_class_ext *ext;
59807330f729Sjoerg   // };
59817330f729Sjoerg   ClassTy->setBody(llvm::PointerType::getUnqual(ClassTy),
59827330f729Sjoerg                    llvm::PointerType::getUnqual(ClassTy), Int8PtrTy, LongTy,
59837330f729Sjoerg                    LongTy, LongTy, IvarListPtrTy, MethodListPtrTy, CachePtrTy,
59847330f729Sjoerg                    ProtocolListPtrTy, Int8PtrTy, ClassExtensionPtrTy);
59857330f729Sjoerg 
59867330f729Sjoerg   ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
59877330f729Sjoerg 
59887330f729Sjoerg   // struct _objc_category {
59897330f729Sjoerg   //   char *category_name;
59907330f729Sjoerg   //   char *class_name;
59917330f729Sjoerg   //   struct _objc_method_list *instance_method;
59927330f729Sjoerg   //   struct _objc_method_list *class_method;
59937330f729Sjoerg   //   struct _objc_protocol_list *protocols;
59947330f729Sjoerg   //   uint32_t size;  // sizeof(struct _objc_category)
59957330f729Sjoerg   //   struct _objc_property_list *instance_properties;// category's @property
59967330f729Sjoerg   //   struct _objc_property_list *class_properties;
59977330f729Sjoerg   // }
59987330f729Sjoerg   CategoryTy = llvm::StructType::create(
59997330f729Sjoerg       "struct._objc_category", Int8PtrTy, Int8PtrTy, MethodListPtrTy,
60007330f729Sjoerg       MethodListPtrTy, ProtocolListPtrTy, IntTy, PropertyListPtrTy,
60017330f729Sjoerg       PropertyListPtrTy);
60027330f729Sjoerg 
60037330f729Sjoerg   // Global metadata structures
60047330f729Sjoerg 
60057330f729Sjoerg   // struct _objc_symtab {
60067330f729Sjoerg   //   long sel_ref_cnt;
60077330f729Sjoerg   //   SEL *refs;
60087330f729Sjoerg   //   short cls_def_cnt;
60097330f729Sjoerg   //   short cat_def_cnt;
60107330f729Sjoerg   //   char *defs[cls_def_cnt + cat_def_cnt];
60117330f729Sjoerg   // }
60127330f729Sjoerg   SymtabTy = llvm::StructType::create("struct._objc_symtab", LongTy,
60137330f729Sjoerg                                       SelectorPtrTy, ShortTy, ShortTy,
60147330f729Sjoerg                                       llvm::ArrayType::get(Int8PtrTy, 0));
60157330f729Sjoerg   SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
60167330f729Sjoerg 
60177330f729Sjoerg   // struct _objc_module {
60187330f729Sjoerg   //   long version;
60197330f729Sjoerg   //   long size;   // sizeof(struct _objc_module)
60207330f729Sjoerg   //   char *name;
60217330f729Sjoerg   //   struct _objc_symtab* symtab;
60227330f729Sjoerg   //  }
60237330f729Sjoerg   ModuleTy = llvm::StructType::create("struct._objc_module", LongTy, LongTy,
60247330f729Sjoerg                                       Int8PtrTy, SymtabPtrTy);
60257330f729Sjoerg 
60267330f729Sjoerg   // FIXME: This is the size of the setjmp buffer and should be target
60277330f729Sjoerg   // specific. 18 is what's used on 32-bit X86.
60287330f729Sjoerg   uint64_t SetJmpBufferSize = 18;
60297330f729Sjoerg 
60307330f729Sjoerg   // Exceptions
60317330f729Sjoerg   llvm::Type *StackPtrTy = llvm::ArrayType::get(CGM.Int8PtrTy, 4);
60327330f729Sjoerg 
60337330f729Sjoerg   ExceptionDataTy = llvm::StructType::create(
60347330f729Sjoerg       "struct._objc_exception_data",
60357330f729Sjoerg       llvm::ArrayType::get(CGM.Int32Ty, SetJmpBufferSize), StackPtrTy);
60367330f729Sjoerg }
60377330f729Sjoerg 
ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule & cgm)60387330f729Sjoerg ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
60397330f729Sjoerg   : ObjCCommonTypesHelper(cgm) {
60407330f729Sjoerg   // struct _method_list_t {
60417330f729Sjoerg   //   uint32_t entsize;  // sizeof(struct _objc_method)
60427330f729Sjoerg   //   uint32_t method_count;
60437330f729Sjoerg   //   struct _objc_method method_list[method_count];
60447330f729Sjoerg   // }
60457330f729Sjoerg   MethodListnfABITy =
60467330f729Sjoerg       llvm::StructType::create("struct.__method_list_t", IntTy, IntTy,
60477330f729Sjoerg                                llvm::ArrayType::get(MethodTy, 0));
60487330f729Sjoerg   // struct method_list_t *
60497330f729Sjoerg   MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
60507330f729Sjoerg 
60517330f729Sjoerg   // struct _protocol_t {
60527330f729Sjoerg   //   id isa;  // NULL
60537330f729Sjoerg   //   const char * const protocol_name;
60547330f729Sjoerg   //   const struct _protocol_list_t * protocol_list; // super protocols
60557330f729Sjoerg   //   const struct method_list_t * const instance_methods;
60567330f729Sjoerg   //   const struct method_list_t * const class_methods;
60577330f729Sjoerg   //   const struct method_list_t *optionalInstanceMethods;
60587330f729Sjoerg   //   const struct method_list_t *optionalClassMethods;
60597330f729Sjoerg   //   const struct _prop_list_t * properties;
60607330f729Sjoerg   //   const uint32_t size;  // sizeof(struct _protocol_t)
60617330f729Sjoerg   //   const uint32_t flags;  // = 0
60627330f729Sjoerg   //   const char ** extendedMethodTypes;
60637330f729Sjoerg   //   const char *demangledName;
60647330f729Sjoerg   //   const struct _prop_list_t * class_properties;
60657330f729Sjoerg   // }
60667330f729Sjoerg 
60677330f729Sjoerg   // Holder for struct _protocol_list_t *
60687330f729Sjoerg   ProtocolListnfABITy =
60697330f729Sjoerg     llvm::StructType::create(VMContext, "struct._objc_protocol_list");
60707330f729Sjoerg 
60717330f729Sjoerg   ProtocolnfABITy = llvm::StructType::create(
60727330f729Sjoerg       "struct._protocol_t", ObjectPtrTy, Int8PtrTy,
60737330f729Sjoerg       llvm::PointerType::getUnqual(ProtocolListnfABITy), MethodListnfABIPtrTy,
60747330f729Sjoerg       MethodListnfABIPtrTy, MethodListnfABIPtrTy, MethodListnfABIPtrTy,
60757330f729Sjoerg       PropertyListPtrTy, IntTy, IntTy, Int8PtrPtrTy, Int8PtrTy,
60767330f729Sjoerg       PropertyListPtrTy);
60777330f729Sjoerg 
60787330f729Sjoerg   // struct _protocol_t*
60797330f729Sjoerg   ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
60807330f729Sjoerg 
60817330f729Sjoerg   // struct _protocol_list_t {
60827330f729Sjoerg   //   long protocol_count;   // Note, this is 32/64 bit
60837330f729Sjoerg   //   struct _protocol_t *[protocol_count];
60847330f729Sjoerg   // }
60857330f729Sjoerg   ProtocolListnfABITy->setBody(LongTy,
60867330f729Sjoerg                                llvm::ArrayType::get(ProtocolnfABIPtrTy, 0));
60877330f729Sjoerg 
60887330f729Sjoerg   // struct _objc_protocol_list*
60897330f729Sjoerg   ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
60907330f729Sjoerg 
60917330f729Sjoerg   // struct _ivar_t {
60927330f729Sjoerg   //   unsigned [long] int *offset;  // pointer to ivar offset location
60937330f729Sjoerg   //   char *name;
60947330f729Sjoerg   //   char *type;
60957330f729Sjoerg   //   uint32_t alignment;
60967330f729Sjoerg   //   uint32_t size;
60977330f729Sjoerg   // }
60987330f729Sjoerg   IvarnfABITy = llvm::StructType::create(
60997330f729Sjoerg       "struct._ivar_t", llvm::PointerType::getUnqual(IvarOffsetVarTy),
61007330f729Sjoerg       Int8PtrTy, Int8PtrTy, IntTy, IntTy);
61017330f729Sjoerg 
61027330f729Sjoerg   // struct _ivar_list_t {
61037330f729Sjoerg   //   uint32 entsize;  // sizeof(struct _ivar_t)
61047330f729Sjoerg   //   uint32 count;
61057330f729Sjoerg   //   struct _iver_t list[count];
61067330f729Sjoerg   // }
61077330f729Sjoerg   IvarListnfABITy =
61087330f729Sjoerg       llvm::StructType::create("struct._ivar_list_t", IntTy, IntTy,
61097330f729Sjoerg                                llvm::ArrayType::get(IvarnfABITy, 0));
61107330f729Sjoerg 
61117330f729Sjoerg   IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
61127330f729Sjoerg 
61137330f729Sjoerg   // struct _class_ro_t {
61147330f729Sjoerg   //   uint32_t const flags;
61157330f729Sjoerg   //   uint32_t const instanceStart;
61167330f729Sjoerg   //   uint32_t const instanceSize;
61177330f729Sjoerg   //   uint32_t const reserved;  // only when building for 64bit targets
61187330f729Sjoerg   //   const uint8_t * const ivarLayout;
61197330f729Sjoerg   //   const char *const name;
61207330f729Sjoerg   //   const struct _method_list_t * const baseMethods;
61217330f729Sjoerg   //   const struct _objc_protocol_list *const baseProtocols;
61227330f729Sjoerg   //   const struct _ivar_list_t *const ivars;
61237330f729Sjoerg   //   const uint8_t * const weakIvarLayout;
61247330f729Sjoerg   //   const struct _prop_list_t * const properties;
61257330f729Sjoerg   // }
61267330f729Sjoerg 
61277330f729Sjoerg   // FIXME. Add 'reserved' field in 64bit abi mode!
61287330f729Sjoerg   ClassRonfABITy = llvm::StructType::create(
61297330f729Sjoerg       "struct._class_ro_t", IntTy, IntTy, IntTy, Int8PtrTy, Int8PtrTy,
61307330f729Sjoerg       MethodListnfABIPtrTy, ProtocolListnfABIPtrTy, IvarListnfABIPtrTy,
61317330f729Sjoerg       Int8PtrTy, PropertyListPtrTy);
61327330f729Sjoerg 
61337330f729Sjoerg   // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
61347330f729Sjoerg   llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
61357330f729Sjoerg   ImpnfABITy = llvm::FunctionType::get(ObjectPtrTy, params, false)
61367330f729Sjoerg                  ->getPointerTo();
61377330f729Sjoerg 
61387330f729Sjoerg   // struct _class_t {
61397330f729Sjoerg   //   struct _class_t *isa;
61407330f729Sjoerg   //   struct _class_t * const superclass;
61417330f729Sjoerg   //   void *cache;
61427330f729Sjoerg   //   IMP *vtable;
61437330f729Sjoerg   //   struct class_ro_t *ro;
61447330f729Sjoerg   // }
61457330f729Sjoerg 
61467330f729Sjoerg   ClassnfABITy = llvm::StructType::create(VMContext, "struct._class_t");
61477330f729Sjoerg   ClassnfABITy->setBody(llvm::PointerType::getUnqual(ClassnfABITy),
61487330f729Sjoerg                         llvm::PointerType::getUnqual(ClassnfABITy), CachePtrTy,
61497330f729Sjoerg                         llvm::PointerType::getUnqual(ImpnfABITy),
61507330f729Sjoerg                         llvm::PointerType::getUnqual(ClassRonfABITy));
61517330f729Sjoerg 
61527330f729Sjoerg   // LLVM for struct _class_t *
61537330f729Sjoerg   ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
61547330f729Sjoerg 
61557330f729Sjoerg   // struct _category_t {
61567330f729Sjoerg   //   const char * const name;
61577330f729Sjoerg   //   struct _class_t *const cls;
61587330f729Sjoerg   //   const struct _method_list_t * const instance_methods;
61597330f729Sjoerg   //   const struct _method_list_t * const class_methods;
61607330f729Sjoerg   //   const struct _protocol_list_t * const protocols;
61617330f729Sjoerg   //   const struct _prop_list_t * const properties;
61627330f729Sjoerg   //   const struct _prop_list_t * const class_properties;
61637330f729Sjoerg   //   const uint32_t size;
61647330f729Sjoerg   // }
61657330f729Sjoerg   CategorynfABITy = llvm::StructType::create(
61667330f729Sjoerg       "struct._category_t", Int8PtrTy, ClassnfABIPtrTy, MethodListnfABIPtrTy,
61677330f729Sjoerg       MethodListnfABIPtrTy, ProtocolListnfABIPtrTy, PropertyListPtrTy,
61687330f729Sjoerg       PropertyListPtrTy, IntTy);
61697330f729Sjoerg 
61707330f729Sjoerg   // New types for nonfragile abi messaging.
61717330f729Sjoerg   CodeGen::CodeGenTypes &Types = CGM.getTypes();
61727330f729Sjoerg   ASTContext &Ctx = CGM.getContext();
61737330f729Sjoerg 
61747330f729Sjoerg   // MessageRefTy - LLVM for:
61757330f729Sjoerg   // struct _message_ref_t {
61767330f729Sjoerg   //   IMP messenger;
61777330f729Sjoerg   //   SEL name;
61787330f729Sjoerg   // };
61797330f729Sjoerg 
61807330f729Sjoerg   // First the clang type for struct _message_ref_t
61817330f729Sjoerg   RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
61827330f729Sjoerg                                       Ctx.getTranslationUnitDecl(),
61837330f729Sjoerg                                       SourceLocation(), SourceLocation(),
61847330f729Sjoerg                                       &Ctx.Idents.get("_message_ref_t"));
61857330f729Sjoerg   RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
61867330f729Sjoerg                                 nullptr, Ctx.VoidPtrTy, nullptr, nullptr, false,
61877330f729Sjoerg                                 ICIS_NoInit));
61887330f729Sjoerg   RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
61897330f729Sjoerg                                 nullptr, Ctx.getObjCSelType(), nullptr, nullptr,
61907330f729Sjoerg                                 false, ICIS_NoInit));
61917330f729Sjoerg   RD->completeDefinition();
61927330f729Sjoerg 
61937330f729Sjoerg   MessageRefCTy = Ctx.getTagDeclType(RD);
61947330f729Sjoerg   MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
61957330f729Sjoerg   MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
61967330f729Sjoerg 
61977330f729Sjoerg   // MessageRefPtrTy - LLVM for struct _message_ref_t*
61987330f729Sjoerg   MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
61997330f729Sjoerg 
62007330f729Sjoerg   // SuperMessageRefTy - LLVM for:
62017330f729Sjoerg   // struct _super_message_ref_t {
62027330f729Sjoerg   //   SUPER_IMP messenger;
62037330f729Sjoerg   //   SEL name;
62047330f729Sjoerg   // };
62057330f729Sjoerg   SuperMessageRefTy = llvm::StructType::create("struct._super_message_ref_t",
62067330f729Sjoerg                                                ImpnfABITy, SelectorPtrTy);
62077330f729Sjoerg 
62087330f729Sjoerg   // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
62097330f729Sjoerg   SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
62107330f729Sjoerg 
62117330f729Sjoerg 
62127330f729Sjoerg   // struct objc_typeinfo {
62137330f729Sjoerg   //   const void** vtable; // objc_ehtype_vtable + 2
62147330f729Sjoerg   //   const char*  name;    // c++ typeinfo string
62157330f729Sjoerg   //   Class        cls;
62167330f729Sjoerg   // };
62177330f729Sjoerg   EHTypeTy = llvm::StructType::create("struct._objc_typeinfo",
62187330f729Sjoerg                                       llvm::PointerType::getUnqual(Int8PtrTy),
62197330f729Sjoerg                                       Int8PtrTy, ClassnfABIPtrTy);
62207330f729Sjoerg   EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
62217330f729Sjoerg }
62227330f729Sjoerg 
ModuleInitFunction()62237330f729Sjoerg llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
62247330f729Sjoerg   FinishNonFragileABIModule();
62257330f729Sjoerg 
62267330f729Sjoerg   return nullptr;
62277330f729Sjoerg }
62287330f729Sjoerg 
AddModuleClassList(ArrayRef<llvm::GlobalValue * > Container,StringRef SymbolName,StringRef SectionName)62297330f729Sjoerg void CGObjCNonFragileABIMac::AddModuleClassList(
62307330f729Sjoerg     ArrayRef<llvm::GlobalValue *> Container, StringRef SymbolName,
62317330f729Sjoerg     StringRef SectionName) {
62327330f729Sjoerg   unsigned NumClasses = Container.size();
62337330f729Sjoerg 
62347330f729Sjoerg   if (!NumClasses)
62357330f729Sjoerg     return;
62367330f729Sjoerg 
62377330f729Sjoerg   SmallVector<llvm::Constant*, 8> Symbols(NumClasses);
62387330f729Sjoerg   for (unsigned i=0; i<NumClasses; i++)
62397330f729Sjoerg     Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i],
62407330f729Sjoerg                                                 ObjCTypes.Int8PtrTy);
62417330f729Sjoerg   llvm::Constant *Init =
62427330f729Sjoerg     llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
62437330f729Sjoerg                                                   Symbols.size()),
62447330f729Sjoerg                              Symbols);
62457330f729Sjoerg 
62467330f729Sjoerg   // Section name is obtained by calling GetSectionName, which returns
62477330f729Sjoerg   // sections in the __DATA segment on MachO.
62487330f729Sjoerg   assert((!CGM.getTriple().isOSBinFormatMachO() ||
62497330f729Sjoerg           SectionName.startswith("__DATA")) &&
62507330f729Sjoerg          "SectionName expected to start with __DATA on MachO");
6251*e038c9c4Sjoerg   llvm::GlobalVariable *GV = new llvm::GlobalVariable(
6252*e038c9c4Sjoerg       CGM.getModule(), Init->getType(), false,
6253*e038c9c4Sjoerg       llvm::GlobalValue::PrivateLinkage, Init, SymbolName);
62547330f729Sjoerg   GV->setAlignment(
62557330f729Sjoerg       llvm::Align(CGM.getDataLayout().getABITypeAlignment(Init->getType())));
62567330f729Sjoerg   GV->setSection(SectionName);
62577330f729Sjoerg   CGM.addCompilerUsedGlobal(GV);
62587330f729Sjoerg }
62597330f729Sjoerg 
FinishNonFragileABIModule()62607330f729Sjoerg void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
62617330f729Sjoerg   // nonfragile abi has no module definition.
62627330f729Sjoerg 
62637330f729Sjoerg   // Build list of all implemented class addresses in array
62647330f729Sjoerg   // L_OBJC_LABEL_CLASS_$.
62657330f729Sjoerg 
62667330f729Sjoerg   for (unsigned i=0, NumClasses=ImplementedClasses.size(); i<NumClasses; i++) {
62677330f729Sjoerg     const ObjCInterfaceDecl *ID = ImplementedClasses[i];
62687330f729Sjoerg     assert(ID);
62697330f729Sjoerg     if (ObjCImplementationDecl *IMP = ID->getImplementation())
62707330f729Sjoerg       // We are implementing a weak imported interface. Give it external linkage
62717330f729Sjoerg       if (ID->isWeakImported() && !IMP->isWeakImported()) {
62727330f729Sjoerg         DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
62737330f729Sjoerg         DefinedMetaClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
62747330f729Sjoerg       }
62757330f729Sjoerg   }
62767330f729Sjoerg 
62777330f729Sjoerg   AddModuleClassList(DefinedClasses, "OBJC_LABEL_CLASS_$",
62787330f729Sjoerg                      GetSectionName("__objc_classlist",
62797330f729Sjoerg                                     "regular,no_dead_strip"));
62807330f729Sjoerg 
62817330f729Sjoerg   AddModuleClassList(DefinedNonLazyClasses, "OBJC_LABEL_NONLAZY_CLASS_$",
62827330f729Sjoerg                      GetSectionName("__objc_nlclslist",
62837330f729Sjoerg                                     "regular,no_dead_strip"));
62847330f729Sjoerg 
62857330f729Sjoerg   // Build list of all implemented category addresses in array
62867330f729Sjoerg   // L_OBJC_LABEL_CATEGORY_$.
62877330f729Sjoerg   AddModuleClassList(DefinedCategories, "OBJC_LABEL_CATEGORY_$",
62887330f729Sjoerg                      GetSectionName("__objc_catlist",
62897330f729Sjoerg                                     "regular,no_dead_strip"));
62907330f729Sjoerg   AddModuleClassList(DefinedStubCategories, "OBJC_LABEL_STUB_CATEGORY_$",
62917330f729Sjoerg                      GetSectionName("__objc_catlist2",
62927330f729Sjoerg                                     "regular,no_dead_strip"));
62937330f729Sjoerg   AddModuleClassList(DefinedNonLazyCategories, "OBJC_LABEL_NONLAZY_CATEGORY_$",
62947330f729Sjoerg                      GetSectionName("__objc_nlcatlist",
62957330f729Sjoerg                                     "regular,no_dead_strip"));
62967330f729Sjoerg 
62977330f729Sjoerg   EmitImageInfo();
62987330f729Sjoerg }
62997330f729Sjoerg 
63007330f729Sjoerg /// isVTableDispatchedSelector - Returns true if SEL is not in the list of
63017330f729Sjoerg /// VTableDispatchMethods; false otherwise. What this means is that
63027330f729Sjoerg /// except for the 19 selectors in the list, we generate 32bit-style
63037330f729Sjoerg /// message dispatch call for all the rest.
isVTableDispatchedSelector(Selector Sel)63047330f729Sjoerg bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) {
63057330f729Sjoerg   // At various points we've experimented with using vtable-based
63067330f729Sjoerg   // dispatch for all methods.
63077330f729Sjoerg   switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
63087330f729Sjoerg   case CodeGenOptions::Legacy:
63097330f729Sjoerg     return false;
63107330f729Sjoerg   case CodeGenOptions::NonLegacy:
63117330f729Sjoerg     return true;
63127330f729Sjoerg   case CodeGenOptions::Mixed:
63137330f729Sjoerg     break;
63147330f729Sjoerg   }
63157330f729Sjoerg 
63167330f729Sjoerg   // If so, see whether this selector is in the white-list of things which must
63177330f729Sjoerg   // use the new dispatch convention. We lazily build a dense set for this.
63187330f729Sjoerg   if (VTableDispatchMethods.empty()) {
63197330f729Sjoerg     VTableDispatchMethods.insert(GetNullarySelector("alloc"));
63207330f729Sjoerg     VTableDispatchMethods.insert(GetNullarySelector("class"));
63217330f729Sjoerg     VTableDispatchMethods.insert(GetNullarySelector("self"));
63227330f729Sjoerg     VTableDispatchMethods.insert(GetNullarySelector("isFlipped"));
63237330f729Sjoerg     VTableDispatchMethods.insert(GetNullarySelector("length"));
63247330f729Sjoerg     VTableDispatchMethods.insert(GetNullarySelector("count"));
63257330f729Sjoerg 
63267330f729Sjoerg     // These are vtable-based if GC is disabled.
63277330f729Sjoerg     // Optimistically use vtable dispatch for hybrid compiles.
63287330f729Sjoerg     if (CGM.getLangOpts().getGC() != LangOptions::GCOnly) {
63297330f729Sjoerg       VTableDispatchMethods.insert(GetNullarySelector("retain"));
63307330f729Sjoerg       VTableDispatchMethods.insert(GetNullarySelector("release"));
63317330f729Sjoerg       VTableDispatchMethods.insert(GetNullarySelector("autorelease"));
63327330f729Sjoerg     }
63337330f729Sjoerg 
63347330f729Sjoerg     VTableDispatchMethods.insert(GetUnarySelector("allocWithZone"));
63357330f729Sjoerg     VTableDispatchMethods.insert(GetUnarySelector("isKindOfClass"));
63367330f729Sjoerg     VTableDispatchMethods.insert(GetUnarySelector("respondsToSelector"));
63377330f729Sjoerg     VTableDispatchMethods.insert(GetUnarySelector("objectForKey"));
63387330f729Sjoerg     VTableDispatchMethods.insert(GetUnarySelector("objectAtIndex"));
63397330f729Sjoerg     VTableDispatchMethods.insert(GetUnarySelector("isEqualToString"));
63407330f729Sjoerg     VTableDispatchMethods.insert(GetUnarySelector("isEqual"));
63417330f729Sjoerg 
63427330f729Sjoerg     // These are vtable-based if GC is enabled.
63437330f729Sjoerg     // Optimistically use vtable dispatch for hybrid compiles.
63447330f729Sjoerg     if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
63457330f729Sjoerg       VTableDispatchMethods.insert(GetNullarySelector("hash"));
63467330f729Sjoerg       VTableDispatchMethods.insert(GetUnarySelector("addObject"));
63477330f729Sjoerg 
63487330f729Sjoerg       // "countByEnumeratingWithState:objects:count"
63497330f729Sjoerg       IdentifierInfo *KeyIdents[] = {
63507330f729Sjoerg         &CGM.getContext().Idents.get("countByEnumeratingWithState"),
63517330f729Sjoerg         &CGM.getContext().Idents.get("objects"),
63527330f729Sjoerg         &CGM.getContext().Idents.get("count")
63537330f729Sjoerg       };
63547330f729Sjoerg       VTableDispatchMethods.insert(
63557330f729Sjoerg         CGM.getContext().Selectors.getSelector(3, KeyIdents));
63567330f729Sjoerg     }
63577330f729Sjoerg   }
63587330f729Sjoerg 
63597330f729Sjoerg   return VTableDispatchMethods.count(Sel);
63607330f729Sjoerg }
63617330f729Sjoerg 
63627330f729Sjoerg /// BuildClassRoTInitializer - generate meta-data for:
63637330f729Sjoerg /// struct _class_ro_t {
63647330f729Sjoerg ///   uint32_t const flags;
63657330f729Sjoerg ///   uint32_t const instanceStart;
63667330f729Sjoerg ///   uint32_t const instanceSize;
63677330f729Sjoerg ///   uint32_t const reserved;  // only when building for 64bit targets
63687330f729Sjoerg ///   const uint8_t * const ivarLayout;
63697330f729Sjoerg ///   const char *const name;
63707330f729Sjoerg ///   const struct _method_list_t * const baseMethods;
63717330f729Sjoerg ///   const struct _protocol_list_t *const baseProtocols;
63727330f729Sjoerg ///   const struct _ivar_list_t *const ivars;
63737330f729Sjoerg ///   const uint8_t * const weakIvarLayout;
63747330f729Sjoerg ///   const struct _prop_list_t * const properties;
63757330f729Sjoerg /// }
63767330f729Sjoerg ///
BuildClassRoTInitializer(unsigned flags,unsigned InstanceStart,unsigned InstanceSize,const ObjCImplementationDecl * ID)63777330f729Sjoerg llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
63787330f729Sjoerg   unsigned flags,
63797330f729Sjoerg   unsigned InstanceStart,
63807330f729Sjoerg   unsigned InstanceSize,
63817330f729Sjoerg   const ObjCImplementationDecl *ID) {
6382*e038c9c4Sjoerg   std::string ClassName = std::string(ID->getObjCRuntimeNameAsString());
63837330f729Sjoerg 
63847330f729Sjoerg   CharUnits beginInstance = CharUnits::fromQuantity(InstanceStart);
63857330f729Sjoerg   CharUnits endInstance = CharUnits::fromQuantity(InstanceSize);
63867330f729Sjoerg 
63877330f729Sjoerg   bool hasMRCWeak = false;
63887330f729Sjoerg   if (CGM.getLangOpts().ObjCAutoRefCount)
63897330f729Sjoerg     flags |= NonFragileABI_Class_CompiledByARC;
63907330f729Sjoerg   else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID)))
63917330f729Sjoerg     flags |= NonFragileABI_Class_HasMRCWeakIvars;
63927330f729Sjoerg 
63937330f729Sjoerg   ConstantInitBuilder builder(CGM);
63947330f729Sjoerg   auto values = builder.beginStruct(ObjCTypes.ClassRonfABITy);
63957330f729Sjoerg 
63967330f729Sjoerg   values.addInt(ObjCTypes.IntTy, flags);
63977330f729Sjoerg   values.addInt(ObjCTypes.IntTy, InstanceStart);
63987330f729Sjoerg   values.addInt(ObjCTypes.IntTy, InstanceSize);
63997330f729Sjoerg   values.add((flags & NonFragileABI_Class_Meta)
64007330f729Sjoerg                 ? GetIvarLayoutName(nullptr, ObjCTypes)
64017330f729Sjoerg                 : BuildStrongIvarLayout(ID, beginInstance, endInstance));
64027330f729Sjoerg   values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
64037330f729Sjoerg 
64047330f729Sjoerg   // const struct _method_list_t * const baseMethods;
64057330f729Sjoerg   SmallVector<const ObjCMethodDecl*, 16> methods;
64067330f729Sjoerg   if (flags & NonFragileABI_Class_Meta) {
64077330f729Sjoerg     for (const auto *MD : ID->class_methods())
6408*e038c9c4Sjoerg       if (!MD->isDirectMethod())
64097330f729Sjoerg         methods.push_back(MD);
64107330f729Sjoerg   } else {
64117330f729Sjoerg     for (const auto *MD : ID->instance_methods())
6412*e038c9c4Sjoerg       if (!MD->isDirectMethod())
64137330f729Sjoerg         methods.push_back(MD);
64147330f729Sjoerg   }
64157330f729Sjoerg 
64167330f729Sjoerg   values.add(emitMethodList(ID->getObjCRuntimeNameAsString(),
64177330f729Sjoerg                             (flags & NonFragileABI_Class_Meta)
64187330f729Sjoerg                                ? MethodListType::ClassMethods
64197330f729Sjoerg                                : MethodListType::InstanceMethods,
64207330f729Sjoerg                             methods));
64217330f729Sjoerg 
64227330f729Sjoerg   const ObjCInterfaceDecl *OID = ID->getClassInterface();
64237330f729Sjoerg   assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
64247330f729Sjoerg   values.add(EmitProtocolList("_OBJC_CLASS_PROTOCOLS_$_"
64257330f729Sjoerg                                 + OID->getObjCRuntimeNameAsString(),
64267330f729Sjoerg                               OID->all_referenced_protocol_begin(),
64277330f729Sjoerg                               OID->all_referenced_protocol_end()));
64287330f729Sjoerg 
64297330f729Sjoerg   if (flags & NonFragileABI_Class_Meta) {
64307330f729Sjoerg     values.addNullPointer(ObjCTypes.IvarListnfABIPtrTy);
64317330f729Sjoerg     values.add(GetIvarLayoutName(nullptr, ObjCTypes));
64327330f729Sjoerg     values.add(EmitPropertyList(
64337330f729Sjoerg         "_OBJC_$_CLASS_PROP_LIST_" + ID->getObjCRuntimeNameAsString(),
64347330f729Sjoerg         ID, ID->getClassInterface(), ObjCTypes, true));
64357330f729Sjoerg   } else {
64367330f729Sjoerg     values.add(EmitIvarList(ID));
64377330f729Sjoerg     values.add(BuildWeakIvarLayout(ID, beginInstance, endInstance, hasMRCWeak));
64387330f729Sjoerg     values.add(EmitPropertyList(
64397330f729Sjoerg         "_OBJC_$_PROP_LIST_" + ID->getObjCRuntimeNameAsString(),
64407330f729Sjoerg         ID, ID->getClassInterface(), ObjCTypes, false));
64417330f729Sjoerg   }
64427330f729Sjoerg 
64437330f729Sjoerg   llvm::SmallString<64> roLabel;
64447330f729Sjoerg   llvm::raw_svector_ostream(roLabel)
64457330f729Sjoerg       << ((flags & NonFragileABI_Class_Meta) ? "_OBJC_METACLASS_RO_$_"
64467330f729Sjoerg                                              : "_OBJC_CLASS_RO_$_")
64477330f729Sjoerg       << ClassName;
64487330f729Sjoerg 
64497330f729Sjoerg   return finishAndCreateGlobal(values, roLabel, CGM);
64507330f729Sjoerg }
64517330f729Sjoerg 
64527330f729Sjoerg /// Build the metaclass object for a class.
64537330f729Sjoerg ///
64547330f729Sjoerg /// struct _class_t {
64557330f729Sjoerg ///   struct _class_t *isa;
64567330f729Sjoerg ///   struct _class_t * const superclass;
64577330f729Sjoerg ///   void *cache;
64587330f729Sjoerg ///   IMP *vtable;
64597330f729Sjoerg ///   struct class_ro_t *ro;
64607330f729Sjoerg /// }
64617330f729Sjoerg ///
64627330f729Sjoerg llvm::GlobalVariable *
BuildClassObject(const ObjCInterfaceDecl * CI,bool isMetaclass,llvm::Constant * IsAGV,llvm::Constant * SuperClassGV,llvm::Constant * ClassRoGV,bool HiddenVisibility)64637330f729Sjoerg CGObjCNonFragileABIMac::BuildClassObject(const ObjCInterfaceDecl *CI,
64647330f729Sjoerg                                          bool isMetaclass,
64657330f729Sjoerg                                          llvm::Constant *IsAGV,
64667330f729Sjoerg                                          llvm::Constant *SuperClassGV,
64677330f729Sjoerg                                          llvm::Constant *ClassRoGV,
64687330f729Sjoerg                                          bool HiddenVisibility) {
64697330f729Sjoerg   ConstantInitBuilder builder(CGM);
64707330f729Sjoerg   auto values = builder.beginStruct(ObjCTypes.ClassnfABITy);
64717330f729Sjoerg   values.add(IsAGV);
64727330f729Sjoerg   if (SuperClassGV) {
64737330f729Sjoerg     values.add(SuperClassGV);
64747330f729Sjoerg   } else {
64757330f729Sjoerg     values.addNullPointer(ObjCTypes.ClassnfABIPtrTy);
64767330f729Sjoerg   }
64777330f729Sjoerg   values.add(ObjCEmptyCacheVar);
64787330f729Sjoerg   values.add(ObjCEmptyVtableVar);
64797330f729Sjoerg   values.add(ClassRoGV);
64807330f729Sjoerg 
64817330f729Sjoerg   llvm::GlobalVariable *GV =
64827330f729Sjoerg     cast<llvm::GlobalVariable>(GetClassGlobal(CI, isMetaclass, ForDefinition));
64837330f729Sjoerg   values.finishAndSetAsInitializer(GV);
64847330f729Sjoerg 
64857330f729Sjoerg   if (CGM.getTriple().isOSBinFormatMachO())
64867330f729Sjoerg     GV->setSection("__DATA, __objc_data");
64877330f729Sjoerg   GV->setAlignment(llvm::Align(
64887330f729Sjoerg       CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassnfABITy)));
64897330f729Sjoerg   if (!CGM.getTriple().isOSBinFormatCOFF())
64907330f729Sjoerg     if (HiddenVisibility)
64917330f729Sjoerg       GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
64927330f729Sjoerg   return GV;
64937330f729Sjoerg }
64947330f729Sjoerg 
ImplementationIsNonLazy(const ObjCImplDecl * OD) const64957330f729Sjoerg bool CGObjCNonFragileABIMac::ImplementationIsNonLazy(
64967330f729Sjoerg     const ObjCImplDecl *OD) const {
64977330f729Sjoerg   return OD->getClassMethod(GetNullarySelector("load")) != nullptr ||
64987330f729Sjoerg          OD->getClassInterface()->hasAttr<ObjCNonLazyClassAttr>() ||
64997330f729Sjoerg          OD->hasAttr<ObjCNonLazyClassAttr>();
65007330f729Sjoerg }
65017330f729Sjoerg 
GetClassSizeInfo(const ObjCImplementationDecl * OID,uint32_t & InstanceStart,uint32_t & InstanceSize)65027330f729Sjoerg void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
65037330f729Sjoerg                                               uint32_t &InstanceStart,
65047330f729Sjoerg                                               uint32_t &InstanceSize) {
65057330f729Sjoerg   const ASTRecordLayout &RL =
65067330f729Sjoerg     CGM.getContext().getASTObjCImplementationLayout(OID);
65077330f729Sjoerg 
65087330f729Sjoerg   // InstanceSize is really instance end.
65097330f729Sjoerg   InstanceSize = RL.getDataSize().getQuantity();
65107330f729Sjoerg 
65117330f729Sjoerg   // If there are no fields, the start is the same as the end.
65127330f729Sjoerg   if (!RL.getFieldCount())
65137330f729Sjoerg     InstanceStart = InstanceSize;
65147330f729Sjoerg   else
65157330f729Sjoerg     InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth();
65167330f729Sjoerg }
65177330f729Sjoerg 
getStorage(CodeGenModule & CGM,StringRef Name)65187330f729Sjoerg static llvm::GlobalValue::DLLStorageClassTypes getStorage(CodeGenModule &CGM,
65197330f729Sjoerg                                                           StringRef Name) {
65207330f729Sjoerg   IdentifierInfo &II = CGM.getContext().Idents.get(Name);
65217330f729Sjoerg   TranslationUnitDecl *TUDecl = CGM.getContext().getTranslationUnitDecl();
65227330f729Sjoerg   DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
65237330f729Sjoerg 
65247330f729Sjoerg   const VarDecl *VD = nullptr;
6525*e038c9c4Sjoerg   for (const auto *Result : DC->lookup(&II))
65267330f729Sjoerg     if ((VD = dyn_cast<VarDecl>(Result)))
65277330f729Sjoerg       break;
65287330f729Sjoerg 
65297330f729Sjoerg   if (!VD)
65307330f729Sjoerg     return llvm::GlobalValue::DLLImportStorageClass;
65317330f729Sjoerg   if (VD->hasAttr<DLLExportAttr>())
65327330f729Sjoerg     return llvm::GlobalValue::DLLExportStorageClass;
65337330f729Sjoerg   if (VD->hasAttr<DLLImportAttr>())
65347330f729Sjoerg     return llvm::GlobalValue::DLLImportStorageClass;
65357330f729Sjoerg   return llvm::GlobalValue::DefaultStorageClass;
65367330f729Sjoerg }
65377330f729Sjoerg 
GenerateClass(const ObjCImplementationDecl * ID)65387330f729Sjoerg void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
65397330f729Sjoerg   if (!ObjCEmptyCacheVar) {
65407330f729Sjoerg     ObjCEmptyCacheVar =
65417330f729Sjoerg         new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CacheTy, false,
65427330f729Sjoerg                                  llvm::GlobalValue::ExternalLinkage, nullptr,
65437330f729Sjoerg                                  "_objc_empty_cache");
65447330f729Sjoerg     if (CGM.getTriple().isOSBinFormatCOFF())
65457330f729Sjoerg       ObjCEmptyCacheVar->setDLLStorageClass(getStorage(CGM, "_objc_empty_cache"));
65467330f729Sjoerg 
65477330f729Sjoerg     // Only OS X with deployment version <10.9 use the empty vtable symbol
65487330f729Sjoerg     const llvm::Triple &Triple = CGM.getTarget().getTriple();
65497330f729Sjoerg     if (Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 9))
65507330f729Sjoerg       ObjCEmptyVtableVar =
65517330f729Sjoerg           new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ImpnfABITy, false,
65527330f729Sjoerg                                    llvm::GlobalValue::ExternalLinkage, nullptr,
65537330f729Sjoerg                                    "_objc_empty_vtable");
65547330f729Sjoerg     else
65557330f729Sjoerg       ObjCEmptyVtableVar =
65567330f729Sjoerg         llvm::ConstantPointerNull::get(ObjCTypes.ImpnfABITy->getPointerTo());
65577330f729Sjoerg   }
65587330f729Sjoerg 
65597330f729Sjoerg   // FIXME: Is this correct (that meta class size is never computed)?
65607330f729Sjoerg   uint32_t InstanceStart =
65617330f729Sjoerg     CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassnfABITy);
65627330f729Sjoerg   uint32_t InstanceSize = InstanceStart;
65637330f729Sjoerg   uint32_t flags = NonFragileABI_Class_Meta;
65647330f729Sjoerg 
65657330f729Sjoerg   llvm::Constant *SuperClassGV, *IsAGV;
65667330f729Sjoerg 
65677330f729Sjoerg   const auto *CI = ID->getClassInterface();
65687330f729Sjoerg   assert(CI && "CGObjCNonFragileABIMac::GenerateClass - class is 0");
65697330f729Sjoerg 
65707330f729Sjoerg   // Build the flags for the metaclass.
65717330f729Sjoerg   bool classIsHidden = (CGM.getTriple().isOSBinFormatCOFF())
65727330f729Sjoerg                            ? !CI->hasAttr<DLLExportAttr>()
65737330f729Sjoerg                            : CI->getVisibility() == HiddenVisibility;
65747330f729Sjoerg   if (classIsHidden)
65757330f729Sjoerg     flags |= NonFragileABI_Class_Hidden;
65767330f729Sjoerg 
65777330f729Sjoerg   // FIXME: why is this flag set on the metaclass?
65787330f729Sjoerg   // ObjC metaclasses have no fields and don't really get constructed.
65797330f729Sjoerg   if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
65807330f729Sjoerg     flags |= NonFragileABI_Class_HasCXXStructors;
65817330f729Sjoerg     if (!ID->hasNonZeroConstructors())
65827330f729Sjoerg       flags |= NonFragileABI_Class_HasCXXDestructorOnly;
65837330f729Sjoerg   }
65847330f729Sjoerg 
65857330f729Sjoerg   if (!CI->getSuperClass()) {
65867330f729Sjoerg     // class is root
65877330f729Sjoerg     flags |= NonFragileABI_Class_Root;
65887330f729Sjoerg 
65897330f729Sjoerg     SuperClassGV = GetClassGlobal(CI, /*metaclass*/ false, NotForDefinition);
65907330f729Sjoerg     IsAGV = GetClassGlobal(CI, /*metaclass*/ true, NotForDefinition);
65917330f729Sjoerg   } else {
65927330f729Sjoerg     // Has a root. Current class is not a root.
65937330f729Sjoerg     const ObjCInterfaceDecl *Root = ID->getClassInterface();
65947330f729Sjoerg     while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
65957330f729Sjoerg       Root = Super;
65967330f729Sjoerg 
65977330f729Sjoerg     const auto *Super = CI->getSuperClass();
65987330f729Sjoerg     IsAGV = GetClassGlobal(Root, /*metaclass*/ true, NotForDefinition);
65997330f729Sjoerg     SuperClassGV = GetClassGlobal(Super, /*metaclass*/ true, NotForDefinition);
66007330f729Sjoerg   }
66017330f729Sjoerg 
66027330f729Sjoerg   llvm::GlobalVariable *CLASS_RO_GV =
66037330f729Sjoerg       BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID);
66047330f729Sjoerg 
66057330f729Sjoerg   llvm::GlobalVariable *MetaTClass =
66067330f729Sjoerg     BuildClassObject(CI, /*metaclass*/ true,
66077330f729Sjoerg                      IsAGV, SuperClassGV, CLASS_RO_GV, classIsHidden);
66087330f729Sjoerg   CGM.setGVProperties(MetaTClass, CI);
66097330f729Sjoerg   DefinedMetaClasses.push_back(MetaTClass);
66107330f729Sjoerg 
66117330f729Sjoerg   // Metadata for the class
66127330f729Sjoerg   flags = 0;
66137330f729Sjoerg   if (classIsHidden)
66147330f729Sjoerg     flags |= NonFragileABI_Class_Hidden;
66157330f729Sjoerg 
66167330f729Sjoerg   if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
66177330f729Sjoerg     flags |= NonFragileABI_Class_HasCXXStructors;
66187330f729Sjoerg 
66197330f729Sjoerg     // Set a flag to enable a runtime optimization when a class has
66207330f729Sjoerg     // fields that require destruction but which don't require
66217330f729Sjoerg     // anything except zero-initialization during construction.  This
66227330f729Sjoerg     // is most notably true of __strong and __weak types, but you can
66237330f729Sjoerg     // also imagine there being C++ types with non-trivial default
66247330f729Sjoerg     // constructors that merely set all fields to null.
66257330f729Sjoerg     if (!ID->hasNonZeroConstructors())
66267330f729Sjoerg       flags |= NonFragileABI_Class_HasCXXDestructorOnly;
66277330f729Sjoerg   }
66287330f729Sjoerg 
66297330f729Sjoerg   if (hasObjCExceptionAttribute(CGM.getContext(), CI))
66307330f729Sjoerg     flags |= NonFragileABI_Class_Exception;
66317330f729Sjoerg 
66327330f729Sjoerg   if (!CI->getSuperClass()) {
66337330f729Sjoerg     flags |= NonFragileABI_Class_Root;
66347330f729Sjoerg     SuperClassGV = nullptr;
66357330f729Sjoerg   } else {
66367330f729Sjoerg     // Has a root. Current class is not a root.
66377330f729Sjoerg     const auto *Super = CI->getSuperClass();
66387330f729Sjoerg     SuperClassGV = GetClassGlobal(Super, /*metaclass*/ false, NotForDefinition);
66397330f729Sjoerg   }
66407330f729Sjoerg 
66417330f729Sjoerg   GetClassSizeInfo(ID, InstanceStart, InstanceSize);
66427330f729Sjoerg   CLASS_RO_GV =
66437330f729Sjoerg       BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID);
66447330f729Sjoerg 
66457330f729Sjoerg   llvm::GlobalVariable *ClassMD =
66467330f729Sjoerg     BuildClassObject(CI, /*metaclass*/ false,
66477330f729Sjoerg                      MetaTClass, SuperClassGV, CLASS_RO_GV, classIsHidden);
66487330f729Sjoerg   CGM.setGVProperties(ClassMD, CI);
66497330f729Sjoerg   DefinedClasses.push_back(ClassMD);
66507330f729Sjoerg   ImplementedClasses.push_back(CI);
66517330f729Sjoerg 
66527330f729Sjoerg   // Determine if this class is also "non-lazy".
66537330f729Sjoerg   if (ImplementationIsNonLazy(ID))
66547330f729Sjoerg     DefinedNonLazyClasses.push_back(ClassMD);
66557330f729Sjoerg 
66567330f729Sjoerg   // Force the definition of the EHType if necessary.
66577330f729Sjoerg   if (flags & NonFragileABI_Class_Exception)
66587330f729Sjoerg     (void) GetInterfaceEHType(CI, ForDefinition);
66597330f729Sjoerg   // Make sure method definition entries are all clear for next implementation.
66607330f729Sjoerg   MethodDefinitions.clear();
66617330f729Sjoerg }
66627330f729Sjoerg 
66637330f729Sjoerg /// GenerateProtocolRef - This routine is called to generate code for
66647330f729Sjoerg /// a protocol reference expression; as in:
66657330f729Sjoerg /// @code
66667330f729Sjoerg ///   @protocol(Proto1);
66677330f729Sjoerg /// @endcode
66687330f729Sjoerg /// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1
66697330f729Sjoerg /// which will hold address of the protocol meta-data.
66707330f729Sjoerg ///
GenerateProtocolRef(CodeGenFunction & CGF,const ObjCProtocolDecl * PD)66717330f729Sjoerg llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF,
66727330f729Sjoerg                                                          const ObjCProtocolDecl *PD) {
66737330f729Sjoerg 
66747330f729Sjoerg   // This routine is called for @protocol only. So, we must build definition
66757330f729Sjoerg   // of protocol's meta-data (not a reference to it!)
6676*e038c9c4Sjoerg   assert(!PD->isNonRuntimeProtocol() &&
6677*e038c9c4Sjoerg          "attempting to get a protocol ref to a static protocol.");
66787330f729Sjoerg   llvm::Constant *Init =
66797330f729Sjoerg     llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
66807330f729Sjoerg                                    ObjCTypes.getExternalProtocolPtrTy());
66817330f729Sjoerg 
66827330f729Sjoerg   std::string ProtocolName("_OBJC_PROTOCOL_REFERENCE_$_");
66837330f729Sjoerg   ProtocolName += PD->getObjCRuntimeNameAsString();
66847330f729Sjoerg 
66857330f729Sjoerg   CharUnits Align = CGF.getPointerAlign();
66867330f729Sjoerg 
66877330f729Sjoerg   llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
66887330f729Sjoerg   if (PTGV)
6689*e038c9c4Sjoerg     return CGF.Builder.CreateAlignedLoad(PTGV->getValueType(), PTGV, Align);
66907330f729Sjoerg   PTGV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
66917330f729Sjoerg                                   llvm::GlobalValue::WeakAnyLinkage, Init,
66927330f729Sjoerg                                   ProtocolName);
66937330f729Sjoerg   PTGV->setSection(GetSectionName("__objc_protorefs",
66947330f729Sjoerg                                   "coalesced,no_dead_strip"));
66957330f729Sjoerg   PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
66967330f729Sjoerg   PTGV->setAlignment(Align.getAsAlign());
66977330f729Sjoerg   if (!CGM.getTriple().isOSBinFormatMachO())
66987330f729Sjoerg     PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolName));
66997330f729Sjoerg   CGM.addUsedGlobal(PTGV);
6700*e038c9c4Sjoerg   return CGF.Builder.CreateAlignedLoad(PTGV->getValueType(), PTGV, Align);
67017330f729Sjoerg }
67027330f729Sjoerg 
67037330f729Sjoerg /// GenerateCategory - Build metadata for a category implementation.
67047330f729Sjoerg /// struct _category_t {
67057330f729Sjoerg ///   const char * const name;
67067330f729Sjoerg ///   struct _class_t *const cls;
67077330f729Sjoerg ///   const struct _method_list_t * const instance_methods;
67087330f729Sjoerg ///   const struct _method_list_t * const class_methods;
67097330f729Sjoerg ///   const struct _protocol_list_t * const protocols;
67107330f729Sjoerg ///   const struct _prop_list_t * const properties;
67117330f729Sjoerg ///   const struct _prop_list_t * const class_properties;
67127330f729Sjoerg ///   const uint32_t size;
67137330f729Sjoerg /// }
67147330f729Sjoerg ///
GenerateCategory(const ObjCCategoryImplDecl * OCD)67157330f729Sjoerg void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
67167330f729Sjoerg   const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
67177330f729Sjoerg   const char *Prefix = "_OBJC_$_CATEGORY_";
67187330f729Sjoerg 
67197330f729Sjoerg   llvm::SmallString<64> ExtCatName(Prefix);
67207330f729Sjoerg   ExtCatName += Interface->getObjCRuntimeNameAsString();
67217330f729Sjoerg   ExtCatName += "_$_";
67227330f729Sjoerg   ExtCatName += OCD->getNameAsString();
67237330f729Sjoerg 
67247330f729Sjoerg   ConstantInitBuilder builder(CGM);
67257330f729Sjoerg   auto values = builder.beginStruct(ObjCTypes.CategorynfABITy);
67267330f729Sjoerg   values.add(GetClassName(OCD->getIdentifier()->getName()));
67277330f729Sjoerg   // meta-class entry symbol
67287330f729Sjoerg   values.add(GetClassGlobal(Interface, /*metaclass*/ false, NotForDefinition));
67297330f729Sjoerg   std::string listName =
67307330f729Sjoerg       (Interface->getObjCRuntimeNameAsString() + "_$_" + OCD->getName()).str();
67317330f729Sjoerg 
67327330f729Sjoerg   SmallVector<const ObjCMethodDecl *, 16> instanceMethods;
67337330f729Sjoerg   SmallVector<const ObjCMethodDecl *, 8> classMethods;
67347330f729Sjoerg   for (const auto *MD : OCD->methods()) {
6735*e038c9c4Sjoerg     if (MD->isDirectMethod())
6736*e038c9c4Sjoerg       continue;
67377330f729Sjoerg     if (MD->isInstanceMethod()) {
67387330f729Sjoerg       instanceMethods.push_back(MD);
67397330f729Sjoerg     } else {
67407330f729Sjoerg       classMethods.push_back(MD);
67417330f729Sjoerg     }
67427330f729Sjoerg   }
67437330f729Sjoerg 
67447330f729Sjoerg   values.add(emitMethodList(listName, MethodListType::CategoryInstanceMethods,
67457330f729Sjoerg                             instanceMethods));
67467330f729Sjoerg   values.add(emitMethodList(listName, MethodListType::CategoryClassMethods,
67477330f729Sjoerg                             classMethods));
67487330f729Sjoerg 
67497330f729Sjoerg   const ObjCCategoryDecl *Category =
67507330f729Sjoerg     Interface->FindCategoryDeclaration(OCD->getIdentifier());
67517330f729Sjoerg   if (Category) {
67527330f729Sjoerg     SmallString<256> ExtName;
67537330f729Sjoerg     llvm::raw_svector_ostream(ExtName) << Interface->getObjCRuntimeNameAsString() << "_$_"
67547330f729Sjoerg                                        << OCD->getName();
67557330f729Sjoerg     values.add(EmitProtocolList("_OBJC_CATEGORY_PROTOCOLS_$_"
67567330f729Sjoerg                                    + Interface->getObjCRuntimeNameAsString() + "_$_"
67577330f729Sjoerg                                    + Category->getName(),
67587330f729Sjoerg                                 Category->protocol_begin(),
67597330f729Sjoerg                                 Category->protocol_end()));
67607330f729Sjoerg     values.add(EmitPropertyList("_OBJC_$_PROP_LIST_" + ExtName.str(),
67617330f729Sjoerg                                 OCD, Category, ObjCTypes, false));
67627330f729Sjoerg     values.add(EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(),
67637330f729Sjoerg                                 OCD, Category, ObjCTypes, true));
67647330f729Sjoerg   } else {
67657330f729Sjoerg     values.addNullPointer(ObjCTypes.ProtocolListnfABIPtrTy);
67667330f729Sjoerg     values.addNullPointer(ObjCTypes.PropertyListPtrTy);
67677330f729Sjoerg     values.addNullPointer(ObjCTypes.PropertyListPtrTy);
67687330f729Sjoerg   }
67697330f729Sjoerg 
67707330f729Sjoerg   unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategorynfABITy);
67717330f729Sjoerg   values.addInt(ObjCTypes.IntTy, Size);
67727330f729Sjoerg 
67737330f729Sjoerg   llvm::GlobalVariable *GCATV =
67747330f729Sjoerg       finishAndCreateGlobal(values, ExtCatName.str(), CGM);
67757330f729Sjoerg   CGM.addCompilerUsedGlobal(GCATV);
67767330f729Sjoerg   if (Interface->hasAttr<ObjCClassStubAttr>())
67777330f729Sjoerg     DefinedStubCategories.push_back(GCATV);
67787330f729Sjoerg   else
67797330f729Sjoerg     DefinedCategories.push_back(GCATV);
67807330f729Sjoerg 
67817330f729Sjoerg   // Determine if this category is also "non-lazy".
67827330f729Sjoerg   if (ImplementationIsNonLazy(OCD))
67837330f729Sjoerg     DefinedNonLazyCategories.push_back(GCATV);
67847330f729Sjoerg   // method definition entries must be clear for next implementation.
67857330f729Sjoerg   MethodDefinitions.clear();
67867330f729Sjoerg }
67877330f729Sjoerg 
67887330f729Sjoerg /// emitMethodConstant - Return a struct objc_method constant.  If
67897330f729Sjoerg /// forProtocol is true, the implementation will be null; otherwise,
67907330f729Sjoerg /// the method must have a definition registered with the runtime.
67917330f729Sjoerg ///
67927330f729Sjoerg /// struct _objc_method {
67937330f729Sjoerg ///   SEL _cmd;
67947330f729Sjoerg ///   char *method_type;
67957330f729Sjoerg ///   char *_imp;
67967330f729Sjoerg /// }
emitMethodConstant(ConstantArrayBuilder & builder,const ObjCMethodDecl * MD,bool forProtocol)67977330f729Sjoerg void CGObjCNonFragileABIMac::emitMethodConstant(ConstantArrayBuilder &builder,
67987330f729Sjoerg                                                 const ObjCMethodDecl *MD,
67997330f729Sjoerg                                                 bool forProtocol) {
68007330f729Sjoerg   auto method = builder.beginStruct(ObjCTypes.MethodTy);
68017330f729Sjoerg   method.addBitCast(GetMethodVarName(MD->getSelector()),
68027330f729Sjoerg                     ObjCTypes.SelectorPtrTy);
68037330f729Sjoerg   method.add(GetMethodVarType(MD));
68047330f729Sjoerg 
68057330f729Sjoerg   if (forProtocol) {
68067330f729Sjoerg     // Protocol methods have no implementation. So, this entry is always NULL.
68077330f729Sjoerg     method.addNullPointer(ObjCTypes.Int8PtrTy);
68087330f729Sjoerg   } else {
68097330f729Sjoerg     llvm::Function *fn = GetMethodDefinition(MD);
68107330f729Sjoerg     assert(fn && "no definition for method?");
68117330f729Sjoerg     method.addBitCast(fn, ObjCTypes.Int8PtrTy);
68127330f729Sjoerg   }
68137330f729Sjoerg 
68147330f729Sjoerg   method.finishAndAddTo(builder);
68157330f729Sjoerg }
68167330f729Sjoerg 
68177330f729Sjoerg /// Build meta-data for method declarations.
68187330f729Sjoerg ///
68197330f729Sjoerg /// struct _method_list_t {
68207330f729Sjoerg ///   uint32_t entsize;  // sizeof(struct _objc_method)
68217330f729Sjoerg ///   uint32_t method_count;
68227330f729Sjoerg ///   struct _objc_method method_list[method_count];
68237330f729Sjoerg /// }
68247330f729Sjoerg ///
68257330f729Sjoerg llvm::Constant *
emitMethodList(Twine name,MethodListType kind,ArrayRef<const ObjCMethodDecl * > methods)68267330f729Sjoerg CGObjCNonFragileABIMac::emitMethodList(Twine name, MethodListType kind,
68277330f729Sjoerg                               ArrayRef<const ObjCMethodDecl *> methods) {
68287330f729Sjoerg   // Return null for empty list.
68297330f729Sjoerg   if (methods.empty())
68307330f729Sjoerg     return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
68317330f729Sjoerg 
68327330f729Sjoerg   StringRef prefix;
68337330f729Sjoerg   bool forProtocol;
68347330f729Sjoerg   switch (kind) {
68357330f729Sjoerg   case MethodListType::CategoryInstanceMethods:
68367330f729Sjoerg     prefix = "_OBJC_$_CATEGORY_INSTANCE_METHODS_";
68377330f729Sjoerg     forProtocol = false;
68387330f729Sjoerg     break;
68397330f729Sjoerg   case MethodListType::CategoryClassMethods:
68407330f729Sjoerg     prefix = "_OBJC_$_CATEGORY_CLASS_METHODS_";
68417330f729Sjoerg     forProtocol = false;
68427330f729Sjoerg     break;
68437330f729Sjoerg   case MethodListType::InstanceMethods:
68447330f729Sjoerg     prefix = "_OBJC_$_INSTANCE_METHODS_";
68457330f729Sjoerg     forProtocol = false;
68467330f729Sjoerg     break;
68477330f729Sjoerg   case MethodListType::ClassMethods:
68487330f729Sjoerg     prefix = "_OBJC_$_CLASS_METHODS_";
68497330f729Sjoerg     forProtocol = false;
68507330f729Sjoerg     break;
68517330f729Sjoerg 
68527330f729Sjoerg   case MethodListType::ProtocolInstanceMethods:
68537330f729Sjoerg     prefix = "_OBJC_$_PROTOCOL_INSTANCE_METHODS_";
68547330f729Sjoerg     forProtocol = true;
68557330f729Sjoerg     break;
68567330f729Sjoerg   case MethodListType::ProtocolClassMethods:
68577330f729Sjoerg     prefix = "_OBJC_$_PROTOCOL_CLASS_METHODS_";
68587330f729Sjoerg     forProtocol = true;
68597330f729Sjoerg     break;
68607330f729Sjoerg   case MethodListType::OptionalProtocolInstanceMethods:
68617330f729Sjoerg     prefix = "_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_";
68627330f729Sjoerg     forProtocol = true;
68637330f729Sjoerg     break;
68647330f729Sjoerg   case MethodListType::OptionalProtocolClassMethods:
68657330f729Sjoerg     prefix = "_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_";
68667330f729Sjoerg     forProtocol = true;
68677330f729Sjoerg     break;
68687330f729Sjoerg   }
68697330f729Sjoerg 
68707330f729Sjoerg   ConstantInitBuilder builder(CGM);
68717330f729Sjoerg   auto values = builder.beginStruct();
68727330f729Sjoerg 
68737330f729Sjoerg   // sizeof(struct _objc_method)
68747330f729Sjoerg   unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.MethodTy);
68757330f729Sjoerg   values.addInt(ObjCTypes.IntTy, Size);
68767330f729Sjoerg   // method_count
68777330f729Sjoerg   values.addInt(ObjCTypes.IntTy, methods.size());
68787330f729Sjoerg   auto methodArray = values.beginArray(ObjCTypes.MethodTy);
6879*e038c9c4Sjoerg   for (auto MD : methods)
68807330f729Sjoerg     emitMethodConstant(methodArray, MD, forProtocol);
68817330f729Sjoerg   methodArray.finishAndAddTo(values);
68827330f729Sjoerg 
68837330f729Sjoerg   llvm::GlobalVariable *GV = finishAndCreateGlobal(values, prefix + name, CGM);
68847330f729Sjoerg   CGM.addCompilerUsedGlobal(GV);
68857330f729Sjoerg   return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListnfABIPtrTy);
68867330f729Sjoerg }
68877330f729Sjoerg 
68887330f729Sjoerg /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
68897330f729Sjoerg /// the given ivar.
68907330f729Sjoerg llvm::GlobalVariable *
ObjCIvarOffsetVariable(const ObjCInterfaceDecl * ID,const ObjCIvarDecl * Ivar)68917330f729Sjoerg CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
68927330f729Sjoerg                                                const ObjCIvarDecl *Ivar) {
68937330f729Sjoerg   const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
68947330f729Sjoerg   llvm::SmallString<64> Name("OBJC_IVAR_$_");
68957330f729Sjoerg   Name += Container->getObjCRuntimeNameAsString();
68967330f729Sjoerg   Name += ".";
68977330f729Sjoerg   Name += Ivar->getName();
68987330f729Sjoerg   llvm::GlobalVariable *IvarOffsetGV = CGM.getModule().getGlobalVariable(Name);
68997330f729Sjoerg   if (!IvarOffsetGV) {
69007330f729Sjoerg     IvarOffsetGV =
69017330f729Sjoerg         new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.IvarOffsetVarTy,
69027330f729Sjoerg                                  false, llvm::GlobalValue::ExternalLinkage,
69037330f729Sjoerg                                  nullptr, Name.str());
69047330f729Sjoerg     if (CGM.getTriple().isOSBinFormatCOFF()) {
69057330f729Sjoerg       bool IsPrivateOrPackage =
69067330f729Sjoerg           Ivar->getAccessControl() == ObjCIvarDecl::Private ||
69077330f729Sjoerg           Ivar->getAccessControl() == ObjCIvarDecl::Package;
69087330f729Sjoerg 
69097330f729Sjoerg       const ObjCInterfaceDecl *ContainingID = Ivar->getContainingInterface();
69107330f729Sjoerg 
69117330f729Sjoerg       if (ContainingID->hasAttr<DLLImportAttr>())
69127330f729Sjoerg         IvarOffsetGV
69137330f729Sjoerg             ->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
69147330f729Sjoerg       else if (ContainingID->hasAttr<DLLExportAttr>() && !IsPrivateOrPackage)
69157330f729Sjoerg         IvarOffsetGV
69167330f729Sjoerg             ->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
69177330f729Sjoerg     }
69187330f729Sjoerg   }
69197330f729Sjoerg   return IvarOffsetGV;
69207330f729Sjoerg }
69217330f729Sjoerg 
69227330f729Sjoerg llvm::Constant *
EmitIvarOffsetVar(const ObjCInterfaceDecl * ID,const ObjCIvarDecl * Ivar,unsigned long int Offset)69237330f729Sjoerg CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
69247330f729Sjoerg                                           const ObjCIvarDecl *Ivar,
69257330f729Sjoerg                                           unsigned long int Offset) {
69267330f729Sjoerg   llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
69277330f729Sjoerg   IvarOffsetGV->setInitializer(
69287330f729Sjoerg       llvm::ConstantInt::get(ObjCTypes.IvarOffsetVarTy, Offset));
69297330f729Sjoerg   IvarOffsetGV->setAlignment(llvm::Align(
69307330f729Sjoerg       CGM.getDataLayout().getABITypeAlignment(ObjCTypes.IvarOffsetVarTy)));
69317330f729Sjoerg 
69327330f729Sjoerg   if (!CGM.getTriple().isOSBinFormatCOFF()) {
69337330f729Sjoerg     // FIXME: This matches gcc, but shouldn't the visibility be set on the use
69347330f729Sjoerg     // as well (i.e., in ObjCIvarOffsetVariable).
69357330f729Sjoerg     if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
69367330f729Sjoerg         Ivar->getAccessControl() == ObjCIvarDecl::Package ||
69377330f729Sjoerg         ID->getVisibility() == HiddenVisibility)
69387330f729Sjoerg       IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
69397330f729Sjoerg     else
69407330f729Sjoerg       IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
69417330f729Sjoerg   }
69427330f729Sjoerg 
69437330f729Sjoerg   // If ID's layout is known, then make the global constant. This serves as a
69447330f729Sjoerg   // useful assertion: we'll never use this variable to calculate ivar offsets,
69457330f729Sjoerg   // so if the runtime tries to patch it then we should crash.
69467330f729Sjoerg   if (isClassLayoutKnownStatically(ID))
69477330f729Sjoerg     IvarOffsetGV->setConstant(true);
69487330f729Sjoerg 
69497330f729Sjoerg   if (CGM.getTriple().isOSBinFormatMachO())
69507330f729Sjoerg     IvarOffsetGV->setSection("__DATA, __objc_ivar");
69517330f729Sjoerg   return IvarOffsetGV;
69527330f729Sjoerg }
69537330f729Sjoerg 
69547330f729Sjoerg /// EmitIvarList - Emit the ivar list for the given
69557330f729Sjoerg /// implementation. The return value has type
69567330f729Sjoerg /// IvarListnfABIPtrTy.
69577330f729Sjoerg ///  struct _ivar_t {
69587330f729Sjoerg ///   unsigned [long] int *offset;  // pointer to ivar offset location
69597330f729Sjoerg ///   char *name;
69607330f729Sjoerg ///   char *type;
69617330f729Sjoerg ///   uint32_t alignment;
69627330f729Sjoerg ///   uint32_t size;
69637330f729Sjoerg /// }
69647330f729Sjoerg /// struct _ivar_list_t {
69657330f729Sjoerg ///   uint32 entsize;  // sizeof(struct _ivar_t)
69667330f729Sjoerg ///   uint32 count;
69677330f729Sjoerg ///   struct _iver_t list[count];
69687330f729Sjoerg /// }
69697330f729Sjoerg ///
69707330f729Sjoerg 
EmitIvarList(const ObjCImplementationDecl * ID)69717330f729Sjoerg llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
69727330f729Sjoerg   const ObjCImplementationDecl *ID) {
69737330f729Sjoerg 
69747330f729Sjoerg   ConstantInitBuilder builder(CGM);
69757330f729Sjoerg   auto ivarList = builder.beginStruct();
69767330f729Sjoerg   ivarList.addInt(ObjCTypes.IntTy,
69777330f729Sjoerg                   CGM.getDataLayout().getTypeAllocSize(ObjCTypes.IvarnfABITy));
69787330f729Sjoerg   auto ivarCountSlot = ivarList.addPlaceholder();
69797330f729Sjoerg   auto ivars = ivarList.beginArray(ObjCTypes.IvarnfABITy);
69807330f729Sjoerg 
69817330f729Sjoerg   const ObjCInterfaceDecl *OID = ID->getClassInterface();
69827330f729Sjoerg   assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
69837330f729Sjoerg 
69847330f729Sjoerg   // FIXME. Consolidate this with similar code in GenerateClass.
69857330f729Sjoerg 
69867330f729Sjoerg   for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
69877330f729Sjoerg        IVD; IVD = IVD->getNextIvar()) {
69887330f729Sjoerg     // Ignore unnamed bit-fields.
69897330f729Sjoerg     if (!IVD->getDeclName())
69907330f729Sjoerg       continue;
69917330f729Sjoerg 
69927330f729Sjoerg     auto ivar = ivars.beginStruct(ObjCTypes.IvarnfABITy);
69937330f729Sjoerg     ivar.add(EmitIvarOffsetVar(ID->getClassInterface(), IVD,
69947330f729Sjoerg                                ComputeIvarBaseOffset(CGM, ID, IVD)));
69957330f729Sjoerg     ivar.add(GetMethodVarName(IVD->getIdentifier()));
69967330f729Sjoerg     ivar.add(GetMethodVarType(IVD));
69977330f729Sjoerg     llvm::Type *FieldTy =
69987330f729Sjoerg       CGM.getTypes().ConvertTypeForMem(IVD->getType());
69997330f729Sjoerg     unsigned Size = CGM.getDataLayout().getTypeAllocSize(FieldTy);
70007330f729Sjoerg     unsigned Align = CGM.getContext().getPreferredTypeAlign(
70017330f729Sjoerg       IVD->getType().getTypePtr()) >> 3;
70027330f729Sjoerg     Align = llvm::Log2_32(Align);
70037330f729Sjoerg     ivar.addInt(ObjCTypes.IntTy, Align);
70047330f729Sjoerg     // NOTE. Size of a bitfield does not match gcc's, because of the
70057330f729Sjoerg     // way bitfields are treated special in each. But I am told that
70067330f729Sjoerg     // 'size' for bitfield ivars is ignored by the runtime so it does
70077330f729Sjoerg     // not matter.  If it matters, there is enough info to get the
70087330f729Sjoerg     // bitfield right!
70097330f729Sjoerg     ivar.addInt(ObjCTypes.IntTy, Size);
70107330f729Sjoerg     ivar.finishAndAddTo(ivars);
70117330f729Sjoerg   }
70127330f729Sjoerg   // Return null for empty list.
70137330f729Sjoerg   if (ivars.empty()) {
70147330f729Sjoerg     ivars.abandon();
70157330f729Sjoerg     ivarList.abandon();
70167330f729Sjoerg     return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
70177330f729Sjoerg   }
70187330f729Sjoerg 
70197330f729Sjoerg   auto ivarCount = ivars.size();
70207330f729Sjoerg   ivars.finishAndAddTo(ivarList);
70217330f729Sjoerg   ivarList.fillPlaceholderWithInt(ivarCountSlot, ObjCTypes.IntTy, ivarCount);
70227330f729Sjoerg 
70237330f729Sjoerg   const char *Prefix = "_OBJC_$_INSTANCE_VARIABLES_";
70247330f729Sjoerg   llvm::GlobalVariable *GV = finishAndCreateGlobal(
70257330f729Sjoerg       ivarList, Prefix + OID->getObjCRuntimeNameAsString(), CGM);
70267330f729Sjoerg   CGM.addCompilerUsedGlobal(GV);
70277330f729Sjoerg   return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy);
70287330f729Sjoerg }
70297330f729Sjoerg 
GetOrEmitProtocolRef(const ObjCProtocolDecl * PD)70307330f729Sjoerg llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
70317330f729Sjoerg   const ObjCProtocolDecl *PD) {
70327330f729Sjoerg   llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
70337330f729Sjoerg 
7034*e038c9c4Sjoerg   assert(!PD->isNonRuntimeProtocol() &&
7035*e038c9c4Sjoerg          "attempting to GetOrEmit a non-runtime protocol");
70367330f729Sjoerg   if (!Entry) {
70377330f729Sjoerg     // We use the initializer as a marker of whether this is a forward
70387330f729Sjoerg     // reference or not. At module finalization we add the empty
70397330f729Sjoerg     // contents for protocols which were referenced but never defined.
70407330f729Sjoerg     llvm::SmallString<64> Protocol;
70417330f729Sjoerg     llvm::raw_svector_ostream(Protocol) << "_OBJC_PROTOCOL_$_"
70427330f729Sjoerg                                         << PD->getObjCRuntimeNameAsString();
70437330f729Sjoerg 
70447330f729Sjoerg     Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
70457330f729Sjoerg                                      false, llvm::GlobalValue::ExternalLinkage,
70467330f729Sjoerg                                      nullptr, Protocol);
70477330f729Sjoerg     if (!CGM.getTriple().isOSBinFormatMachO())
70487330f729Sjoerg       Entry->setComdat(CGM.getModule().getOrInsertComdat(Protocol));
70497330f729Sjoerg   }
70507330f729Sjoerg 
70517330f729Sjoerg   return Entry;
70527330f729Sjoerg }
70537330f729Sjoerg 
70547330f729Sjoerg /// GetOrEmitProtocol - Generate the protocol meta-data:
70557330f729Sjoerg /// @code
70567330f729Sjoerg /// struct _protocol_t {
70577330f729Sjoerg ///   id isa;  // NULL
70587330f729Sjoerg ///   const char * const protocol_name;
70597330f729Sjoerg ///   const struct _protocol_list_t * protocol_list; // super protocols
70607330f729Sjoerg ///   const struct method_list_t * const instance_methods;
70617330f729Sjoerg ///   const struct method_list_t * const class_methods;
70627330f729Sjoerg ///   const struct method_list_t *optionalInstanceMethods;
70637330f729Sjoerg ///   const struct method_list_t *optionalClassMethods;
70647330f729Sjoerg ///   const struct _prop_list_t * properties;
70657330f729Sjoerg ///   const uint32_t size;  // sizeof(struct _protocol_t)
70667330f729Sjoerg ///   const uint32_t flags;  // = 0
70677330f729Sjoerg ///   const char ** extendedMethodTypes;
70687330f729Sjoerg ///   const char *demangledName;
70697330f729Sjoerg ///   const struct _prop_list_t * class_properties;
70707330f729Sjoerg /// }
70717330f729Sjoerg /// @endcode
70727330f729Sjoerg ///
70737330f729Sjoerg 
GetOrEmitProtocol(const ObjCProtocolDecl * PD)70747330f729Sjoerg llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
70757330f729Sjoerg   const ObjCProtocolDecl *PD) {
70767330f729Sjoerg   llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
70777330f729Sjoerg 
70787330f729Sjoerg   // Early exit if a defining object has already been generated.
70797330f729Sjoerg   if (Entry && Entry->hasInitializer())
70807330f729Sjoerg     return Entry;
70817330f729Sjoerg 
70827330f729Sjoerg   // Use the protocol definition, if there is one.
70837330f729Sjoerg   assert(PD->hasDefinition() &&
70847330f729Sjoerg          "emitting protocol metadata without definition");
70857330f729Sjoerg   PD = PD->getDefinition();
70867330f729Sjoerg 
70877330f729Sjoerg   auto methodLists = ProtocolMethodLists::get(PD);
70887330f729Sjoerg 
70897330f729Sjoerg   ConstantInitBuilder builder(CGM);
70907330f729Sjoerg   auto values = builder.beginStruct(ObjCTypes.ProtocolnfABITy);
70917330f729Sjoerg 
70927330f729Sjoerg   // isa is NULL
70937330f729Sjoerg   values.addNullPointer(ObjCTypes.ObjectPtrTy);
70947330f729Sjoerg   values.add(GetClassName(PD->getObjCRuntimeNameAsString()));
70957330f729Sjoerg   values.add(EmitProtocolList("_OBJC_$_PROTOCOL_REFS_"
70967330f729Sjoerg                                 + PD->getObjCRuntimeNameAsString(),
70977330f729Sjoerg                                PD->protocol_begin(),
70987330f729Sjoerg                                PD->protocol_end()));
70997330f729Sjoerg   values.add(methodLists.emitMethodList(this, PD,
71007330f729Sjoerg                                  ProtocolMethodLists::RequiredInstanceMethods));
71017330f729Sjoerg   values.add(methodLists.emitMethodList(this, PD,
71027330f729Sjoerg                                  ProtocolMethodLists::RequiredClassMethods));
71037330f729Sjoerg   values.add(methodLists.emitMethodList(this, PD,
71047330f729Sjoerg                                  ProtocolMethodLists::OptionalInstanceMethods));
71057330f729Sjoerg   values.add(methodLists.emitMethodList(this, PD,
71067330f729Sjoerg                                  ProtocolMethodLists::OptionalClassMethods));
71077330f729Sjoerg   values.add(EmitPropertyList(
71087330f729Sjoerg                "_OBJC_$_PROP_LIST_" + PD->getObjCRuntimeNameAsString(),
71097330f729Sjoerg                nullptr, PD, ObjCTypes, false));
71107330f729Sjoerg   uint32_t Size =
71117330f729Sjoerg     CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
71127330f729Sjoerg   values.addInt(ObjCTypes.IntTy, Size);
71137330f729Sjoerg   values.addInt(ObjCTypes.IntTy, 0);
71147330f729Sjoerg   values.add(EmitProtocolMethodTypes("_OBJC_$_PROTOCOL_METHOD_TYPES_"
71157330f729Sjoerg                                        + PD->getObjCRuntimeNameAsString(),
71167330f729Sjoerg                                      methodLists.emitExtendedTypesArray(this),
71177330f729Sjoerg                                      ObjCTypes));
71187330f729Sjoerg 
71197330f729Sjoerg   // const char *demangledName;
71207330f729Sjoerg   values.addNullPointer(ObjCTypes.Int8PtrTy);
71217330f729Sjoerg 
71227330f729Sjoerg   values.add(EmitPropertyList(
71237330f729Sjoerg       "_OBJC_$_CLASS_PROP_LIST_" + PD->getObjCRuntimeNameAsString(),
71247330f729Sjoerg       nullptr, PD, ObjCTypes, true));
71257330f729Sjoerg 
71267330f729Sjoerg   if (Entry) {
71277330f729Sjoerg     // Already created, fix the linkage and update the initializer.
71287330f729Sjoerg     Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
71297330f729Sjoerg     values.finishAndSetAsInitializer(Entry);
71307330f729Sjoerg   } else {
71317330f729Sjoerg     llvm::SmallString<64> symbolName;
71327330f729Sjoerg     llvm::raw_svector_ostream(symbolName)
71337330f729Sjoerg       << "_OBJC_PROTOCOL_$_" << PD->getObjCRuntimeNameAsString();
71347330f729Sjoerg 
71357330f729Sjoerg     Entry = values.finishAndCreateGlobal(symbolName, CGM.getPointerAlign(),
71367330f729Sjoerg                                          /*constant*/ false,
71377330f729Sjoerg                                          llvm::GlobalValue::WeakAnyLinkage);
71387330f729Sjoerg     if (!CGM.getTriple().isOSBinFormatMachO())
71397330f729Sjoerg       Entry->setComdat(CGM.getModule().getOrInsertComdat(symbolName));
71407330f729Sjoerg 
71417330f729Sjoerg     Protocols[PD->getIdentifier()] = Entry;
71427330f729Sjoerg   }
71437330f729Sjoerg   Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
71447330f729Sjoerg   CGM.addUsedGlobal(Entry);
71457330f729Sjoerg 
71467330f729Sjoerg   // Use this protocol meta-data to build protocol list table in section
71477330f729Sjoerg   // __DATA, __objc_protolist
71487330f729Sjoerg   llvm::SmallString<64> ProtocolRef;
71497330f729Sjoerg   llvm::raw_svector_ostream(ProtocolRef) << "_OBJC_LABEL_PROTOCOL_$_"
71507330f729Sjoerg                                          << PD->getObjCRuntimeNameAsString();
71517330f729Sjoerg 
71527330f729Sjoerg   llvm::GlobalVariable *PTGV =
71537330f729Sjoerg     new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
71547330f729Sjoerg                              false, llvm::GlobalValue::WeakAnyLinkage, Entry,
71557330f729Sjoerg                              ProtocolRef);
71567330f729Sjoerg   if (!CGM.getTriple().isOSBinFormatMachO())
71577330f729Sjoerg     PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolRef));
71587330f729Sjoerg   PTGV->setAlignment(llvm::Align(
71597330f729Sjoerg       CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy)));
71607330f729Sjoerg   PTGV->setSection(GetSectionName("__objc_protolist",
71617330f729Sjoerg                                   "coalesced,no_dead_strip"));
71627330f729Sjoerg   PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
71637330f729Sjoerg   CGM.addUsedGlobal(PTGV);
71647330f729Sjoerg   return Entry;
71657330f729Sjoerg }
71667330f729Sjoerg 
71677330f729Sjoerg /// EmitProtocolList - Generate protocol list meta-data:
71687330f729Sjoerg /// @code
71697330f729Sjoerg /// struct _protocol_list_t {
71707330f729Sjoerg ///   long protocol_count;   // Note, this is 32/64 bit
71717330f729Sjoerg ///   struct _protocol_t[protocol_count];
71727330f729Sjoerg /// }
71737330f729Sjoerg /// @endcode
71747330f729Sjoerg ///
71757330f729Sjoerg llvm::Constant *
EmitProtocolList(Twine Name,ObjCProtocolDecl::protocol_iterator begin,ObjCProtocolDecl::protocol_iterator end)71767330f729Sjoerg CGObjCNonFragileABIMac::EmitProtocolList(Twine Name,
71777330f729Sjoerg                                       ObjCProtocolDecl::protocol_iterator begin,
71787330f729Sjoerg                                       ObjCProtocolDecl::protocol_iterator end) {
71797330f729Sjoerg   // Just return null for empty protocol lists
7180*e038c9c4Sjoerg   auto Protocols = GetRuntimeProtocolList(begin, end);
7181*e038c9c4Sjoerg   if (Protocols.empty())
7182*e038c9c4Sjoerg     return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
7183*e038c9c4Sjoerg 
7184*e038c9c4Sjoerg   SmallVector<llvm::Constant *, 16> ProtocolRefs;
7185*e038c9c4Sjoerg   ProtocolRefs.reserve(Protocols.size());
7186*e038c9c4Sjoerg 
7187*e038c9c4Sjoerg   for (const auto *PD : Protocols)
7188*e038c9c4Sjoerg     ProtocolRefs.push_back(GetProtocolRef(PD));
7189*e038c9c4Sjoerg 
7190*e038c9c4Sjoerg   // If all of the protocols in the protocol list are objc_non_runtime_protocol
7191*e038c9c4Sjoerg   // just return null
7192*e038c9c4Sjoerg   if (ProtocolRefs.size() == 0)
71937330f729Sjoerg     return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
71947330f729Sjoerg 
71957330f729Sjoerg   // FIXME: We shouldn't need to do this lookup here, should we?
71967330f729Sjoerg   SmallString<256> TmpName;
71977330f729Sjoerg   Name.toVector(TmpName);
71987330f729Sjoerg   llvm::GlobalVariable *GV =
71997330f729Sjoerg     CGM.getModule().getGlobalVariable(TmpName.str(), true);
72007330f729Sjoerg   if (GV)
72017330f729Sjoerg     return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
72027330f729Sjoerg 
72037330f729Sjoerg   ConstantInitBuilder builder(CGM);
72047330f729Sjoerg   auto values = builder.beginStruct();
72057330f729Sjoerg   auto countSlot = values.addPlaceholder();
72067330f729Sjoerg 
72077330f729Sjoerg   // A null-terminated array of protocols.
72087330f729Sjoerg   auto array = values.beginArray(ObjCTypes.ProtocolnfABIPtrTy);
7209*e038c9c4Sjoerg   for (auto const &proto : ProtocolRefs)
7210*e038c9c4Sjoerg     array.add(proto);
72117330f729Sjoerg   auto count = array.size();
72127330f729Sjoerg   array.addNullPointer(ObjCTypes.ProtocolnfABIPtrTy);
72137330f729Sjoerg 
72147330f729Sjoerg   array.finishAndAddTo(values);
72157330f729Sjoerg   values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);
72167330f729Sjoerg 
72177330f729Sjoerg   GV = finishAndCreateGlobal(values, Name, CGM);
72187330f729Sjoerg   CGM.addCompilerUsedGlobal(GV);
72197330f729Sjoerg   return llvm::ConstantExpr::getBitCast(GV,
72207330f729Sjoerg                                         ObjCTypes.ProtocolListnfABIPtrTy);
72217330f729Sjoerg }
72227330f729Sjoerg 
72237330f729Sjoerg /// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
72247330f729Sjoerg /// This code gen. amounts to generating code for:
72257330f729Sjoerg /// @code
72267330f729Sjoerg /// (type *)((char *)base + _OBJC_IVAR_$_.ivar;
72277330f729Sjoerg /// @encode
72287330f729Sjoerg ///
EmitObjCValueForIvar(CodeGen::CodeGenFunction & CGF,QualType ObjectTy,llvm::Value * BaseValue,const ObjCIvarDecl * Ivar,unsigned CVRQualifiers)72297330f729Sjoerg LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
72307330f729Sjoerg                                                CodeGen::CodeGenFunction &CGF,
72317330f729Sjoerg                                                QualType ObjectTy,
72327330f729Sjoerg                                                llvm::Value *BaseValue,
72337330f729Sjoerg                                                const ObjCIvarDecl *Ivar,
72347330f729Sjoerg                                                unsigned CVRQualifiers) {
72357330f729Sjoerg   ObjCInterfaceDecl *ID = ObjectTy->castAs<ObjCObjectType>()->getInterface();
72367330f729Sjoerg   llvm::Value *Offset = EmitIvarOffset(CGF, ID, Ivar);
72377330f729Sjoerg   return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
72387330f729Sjoerg                                   Offset);
72397330f729Sjoerg }
72407330f729Sjoerg 
72417330f729Sjoerg llvm::Value *
EmitIvarOffset(CodeGen::CodeGenFunction & CGF,const ObjCInterfaceDecl * Interface,const ObjCIvarDecl * Ivar)72427330f729Sjoerg CGObjCNonFragileABIMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
72437330f729Sjoerg                                        const ObjCInterfaceDecl *Interface,
72447330f729Sjoerg                                        const ObjCIvarDecl *Ivar) {
72457330f729Sjoerg   llvm::Value *IvarOffsetValue;
72467330f729Sjoerg   if (isClassLayoutKnownStatically(Interface)) {
72477330f729Sjoerg     IvarOffsetValue = llvm::ConstantInt::get(
72487330f729Sjoerg         ObjCTypes.IvarOffsetVarTy,
72497330f729Sjoerg         ComputeIvarBaseOffset(CGM, Interface->getImplementation(), Ivar));
72507330f729Sjoerg   } else {
72517330f729Sjoerg     llvm::GlobalVariable *GV = ObjCIvarOffsetVariable(Interface, Ivar);
72527330f729Sjoerg     IvarOffsetValue =
7253*e038c9c4Sjoerg         CGF.Builder.CreateAlignedLoad(GV->getValueType(), GV,
7254*e038c9c4Sjoerg                                       CGF.getSizeAlign(), "ivar");
72557330f729Sjoerg     if (IsIvarOffsetKnownIdempotent(CGF, Ivar))
72567330f729Sjoerg       cast<llvm::LoadInst>(IvarOffsetValue)
72577330f729Sjoerg           ->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
72587330f729Sjoerg                         llvm::MDNode::get(VMContext, None));
72597330f729Sjoerg   }
72607330f729Sjoerg 
72617330f729Sjoerg   // This could be 32bit int or 64bit integer depending on the architecture.
72627330f729Sjoerg   // Cast it to 64bit integer value, if it is a 32bit integer ivar offset value
72637330f729Sjoerg   //  as this is what caller always expects.
72647330f729Sjoerg   if (ObjCTypes.IvarOffsetVarTy == ObjCTypes.IntTy)
72657330f729Sjoerg     IvarOffsetValue = CGF.Builder.CreateIntCast(
72667330f729Sjoerg         IvarOffsetValue, ObjCTypes.LongTy, true, "ivar.conv");
72677330f729Sjoerg   return IvarOffsetValue;
72687330f729Sjoerg }
72697330f729Sjoerg 
appendSelectorForMessageRefTable(std::string & buffer,Selector selector)72707330f729Sjoerg static void appendSelectorForMessageRefTable(std::string &buffer,
72717330f729Sjoerg                                              Selector selector) {
72727330f729Sjoerg   if (selector.isUnarySelector()) {
72737330f729Sjoerg     buffer += selector.getNameForSlot(0);
72747330f729Sjoerg     return;
72757330f729Sjoerg   }
72767330f729Sjoerg 
72777330f729Sjoerg   for (unsigned i = 0, e = selector.getNumArgs(); i != e; ++i) {
72787330f729Sjoerg     buffer += selector.getNameForSlot(i);
72797330f729Sjoerg     buffer += '_';
72807330f729Sjoerg   }
72817330f729Sjoerg }
72827330f729Sjoerg 
72837330f729Sjoerg /// Emit a "vtable" message send.  We emit a weak hidden-visibility
72847330f729Sjoerg /// struct, initially containing the selector pointer and a pointer to
72857330f729Sjoerg /// a "fixup" variant of the appropriate objc_msgSend.  To call, we
72867330f729Sjoerg /// load and call the function pointer, passing the address of the
72877330f729Sjoerg /// struct as the second parameter.  The runtime determines whether
72887330f729Sjoerg /// the selector is currently emitted using vtable dispatch; if so, it
72897330f729Sjoerg /// substitutes a stub function which simply tail-calls through the
72907330f729Sjoerg /// appropriate vtable slot, and if not, it substitues a stub function
72917330f729Sjoerg /// which tail-calls objc_msgSend.  Both stubs adjust the selector
72927330f729Sjoerg /// argument to correctly point to the selector.
72937330f729Sjoerg RValue
EmitVTableMessageSend(CodeGenFunction & CGF,ReturnValueSlot returnSlot,QualType resultType,Selector selector,llvm::Value * arg0,QualType arg0Type,bool isSuper,const CallArgList & formalArgs,const ObjCMethodDecl * method)72947330f729Sjoerg CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
72957330f729Sjoerg                                               ReturnValueSlot returnSlot,
72967330f729Sjoerg                                               QualType resultType,
72977330f729Sjoerg                                               Selector selector,
72987330f729Sjoerg                                               llvm::Value *arg0,
72997330f729Sjoerg                                               QualType arg0Type,
73007330f729Sjoerg                                               bool isSuper,
73017330f729Sjoerg                                               const CallArgList &formalArgs,
73027330f729Sjoerg                                               const ObjCMethodDecl *method) {
73037330f729Sjoerg   // Compute the actual arguments.
73047330f729Sjoerg   CallArgList args;
73057330f729Sjoerg 
73067330f729Sjoerg   // First argument: the receiver / super-call structure.
73077330f729Sjoerg   if (!isSuper)
73087330f729Sjoerg     arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy);
73097330f729Sjoerg   args.add(RValue::get(arg0), arg0Type);
73107330f729Sjoerg 
73117330f729Sjoerg   // Second argument: a pointer to the message ref structure.  Leave
73127330f729Sjoerg   // the actual argument value blank for now.
73137330f729Sjoerg   args.add(RValue::get(nullptr), ObjCTypes.MessageRefCPtrTy);
73147330f729Sjoerg 
73157330f729Sjoerg   args.insert(args.end(), formalArgs.begin(), formalArgs.end());
73167330f729Sjoerg 
73177330f729Sjoerg   MessageSendInfo MSI = getMessageSendInfo(method, resultType, args);
73187330f729Sjoerg 
73197330f729Sjoerg   NullReturnState nullReturn;
73207330f729Sjoerg 
73217330f729Sjoerg   // Find the function to call and the mangled name for the message
73227330f729Sjoerg   // ref structure.  Using a different mangled name wouldn't actually
73237330f729Sjoerg   // be a problem; it would just be a waste.
73247330f729Sjoerg   //
73257330f729Sjoerg   // The runtime currently never uses vtable dispatch for anything
73267330f729Sjoerg   // except normal, non-super message-sends.
73277330f729Sjoerg   // FIXME: don't use this for that.
73287330f729Sjoerg   llvm::FunctionCallee fn = nullptr;
73297330f729Sjoerg   std::string messageRefName("_");
73307330f729Sjoerg   if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) {
73317330f729Sjoerg     if (isSuper) {
73327330f729Sjoerg       fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
73337330f729Sjoerg       messageRefName += "objc_msgSendSuper2_stret_fixup";
73347330f729Sjoerg     } else {
73357330f729Sjoerg       nullReturn.init(CGF, arg0);
73367330f729Sjoerg       fn = ObjCTypes.getMessageSendStretFixupFn();
73377330f729Sjoerg       messageRefName += "objc_msgSend_stret_fixup";
73387330f729Sjoerg     }
73397330f729Sjoerg   } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) {
73407330f729Sjoerg     fn = ObjCTypes.getMessageSendFpretFixupFn();
73417330f729Sjoerg     messageRefName += "objc_msgSend_fpret_fixup";
73427330f729Sjoerg   } else {
73437330f729Sjoerg     if (isSuper) {
73447330f729Sjoerg       fn = ObjCTypes.getMessageSendSuper2FixupFn();
73457330f729Sjoerg       messageRefName += "objc_msgSendSuper2_fixup";
73467330f729Sjoerg     } else {
73477330f729Sjoerg       fn = ObjCTypes.getMessageSendFixupFn();
73487330f729Sjoerg       messageRefName += "objc_msgSend_fixup";
73497330f729Sjoerg     }
73507330f729Sjoerg   }
73517330f729Sjoerg   assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend");
73527330f729Sjoerg   messageRefName += '_';
73537330f729Sjoerg 
73547330f729Sjoerg   // Append the selector name, except use underscores anywhere we
73557330f729Sjoerg   // would have used colons.
73567330f729Sjoerg   appendSelectorForMessageRefTable(messageRefName, selector);
73577330f729Sjoerg 
73587330f729Sjoerg   llvm::GlobalVariable *messageRef
73597330f729Sjoerg     = CGM.getModule().getGlobalVariable(messageRefName);
73607330f729Sjoerg   if (!messageRef) {
73617330f729Sjoerg     // Build the message ref structure.
73627330f729Sjoerg     ConstantInitBuilder builder(CGM);
73637330f729Sjoerg     auto values = builder.beginStruct();
73647330f729Sjoerg     values.add(cast<llvm::Constant>(fn.getCallee()));
73657330f729Sjoerg     values.add(GetMethodVarName(selector));
73667330f729Sjoerg     messageRef = values.finishAndCreateGlobal(messageRefName,
73677330f729Sjoerg                                               CharUnits::fromQuantity(16),
73687330f729Sjoerg                                               /*constant*/ false,
73697330f729Sjoerg                                         llvm::GlobalValue::WeakAnyLinkage);
73707330f729Sjoerg     messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
73717330f729Sjoerg     messageRef->setSection(GetSectionName("__objc_msgrefs", "coalesced"));
73727330f729Sjoerg   }
73737330f729Sjoerg 
73747330f729Sjoerg   bool requiresnullCheck = false;
73757330f729Sjoerg   if (CGM.getLangOpts().ObjCAutoRefCount && method)
73767330f729Sjoerg     for (const auto *ParamDecl : method->parameters()) {
7377*e038c9c4Sjoerg       if (ParamDecl->isDestroyedInCallee()) {
73787330f729Sjoerg         if (!nullReturn.NullBB)
73797330f729Sjoerg           nullReturn.init(CGF, arg0);
73807330f729Sjoerg         requiresnullCheck = true;
73817330f729Sjoerg         break;
73827330f729Sjoerg       }
73837330f729Sjoerg     }
73847330f729Sjoerg 
73857330f729Sjoerg   Address mref =
73867330f729Sjoerg     Address(CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy),
73877330f729Sjoerg             CGF.getPointerAlign());
73887330f729Sjoerg 
73897330f729Sjoerg   // Update the message ref argument.
73907330f729Sjoerg   args[1].setRValue(RValue::get(mref.getPointer()));
73917330f729Sjoerg 
73927330f729Sjoerg   // Load the function to call from the message ref table.
73937330f729Sjoerg   Address calleeAddr = CGF.Builder.CreateStructGEP(mref, 0);
73947330f729Sjoerg   llvm::Value *calleePtr = CGF.Builder.CreateLoad(calleeAddr, "msgSend_fn");
73957330f729Sjoerg 
73967330f729Sjoerg   calleePtr = CGF.Builder.CreateBitCast(calleePtr, MSI.MessengerType);
73977330f729Sjoerg   CGCallee callee(CGCalleeInfo(), calleePtr);
73987330f729Sjoerg 
73997330f729Sjoerg   RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args);
74007330f729Sjoerg   return nullReturn.complete(CGF, returnSlot, result, resultType, formalArgs,
74017330f729Sjoerg                              requiresnullCheck ? method : nullptr);
74027330f729Sjoerg }
74037330f729Sjoerg 
74047330f729Sjoerg /// Generate code for a message send expression in the nonfragile abi.
74057330f729Sjoerg CodeGen::RValue
GenerateMessageSend(CodeGen::CodeGenFunction & CGF,ReturnValueSlot Return,QualType ResultType,Selector Sel,llvm::Value * Receiver,const CallArgList & CallArgs,const ObjCInterfaceDecl * Class,const ObjCMethodDecl * Method)74067330f729Sjoerg CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
74077330f729Sjoerg                                             ReturnValueSlot Return,
74087330f729Sjoerg                                             QualType ResultType,
74097330f729Sjoerg                                             Selector Sel,
74107330f729Sjoerg                                             llvm::Value *Receiver,
74117330f729Sjoerg                                             const CallArgList &CallArgs,
74127330f729Sjoerg                                             const ObjCInterfaceDecl *Class,
74137330f729Sjoerg                                             const ObjCMethodDecl *Method) {
74147330f729Sjoerg   return isVTableDispatchedSelector(Sel)
74157330f729Sjoerg     ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
74167330f729Sjoerg                             Receiver, CGF.getContext().getObjCIdType(),
74177330f729Sjoerg                             false, CallArgs, Method)
7418*e038c9c4Sjoerg     : EmitMessageSend(CGF, Return, ResultType, Sel,
74197330f729Sjoerg                       Receiver, CGF.getContext().getObjCIdType(),
74207330f729Sjoerg                       false, CallArgs, Method, Class, ObjCTypes);
74217330f729Sjoerg }
74227330f729Sjoerg 
74237330f729Sjoerg llvm::Constant *
GetClassGlobal(const ObjCInterfaceDecl * ID,bool metaclass,ForDefinition_t isForDefinition)74247330f729Sjoerg CGObjCNonFragileABIMac::GetClassGlobal(const ObjCInterfaceDecl *ID,
74257330f729Sjoerg                                        bool metaclass,
74267330f729Sjoerg                                        ForDefinition_t isForDefinition) {
74277330f729Sjoerg   auto prefix =
74287330f729Sjoerg     (metaclass ? getMetaclassSymbolPrefix() : getClassSymbolPrefix());
74297330f729Sjoerg   return GetClassGlobal((prefix + ID->getObjCRuntimeNameAsString()).str(),
74307330f729Sjoerg                         isForDefinition,
74317330f729Sjoerg                         ID->isWeakImported(),
74327330f729Sjoerg                         !isForDefinition
74337330f729Sjoerg                           && CGM.getTriple().isOSBinFormatCOFF()
74347330f729Sjoerg                           && ID->hasAttr<DLLImportAttr>());
74357330f729Sjoerg }
74367330f729Sjoerg 
74377330f729Sjoerg llvm::Constant *
GetClassGlobal(StringRef Name,ForDefinition_t IsForDefinition,bool Weak,bool DLLImport)74387330f729Sjoerg CGObjCNonFragileABIMac::GetClassGlobal(StringRef Name,
74397330f729Sjoerg                                        ForDefinition_t IsForDefinition,
74407330f729Sjoerg                                        bool Weak, bool DLLImport) {
74417330f729Sjoerg   llvm::GlobalValue::LinkageTypes L =
74427330f729Sjoerg       Weak ? llvm::GlobalValue::ExternalWeakLinkage
74437330f729Sjoerg            : llvm::GlobalValue::ExternalLinkage;
74447330f729Sjoerg 
74457330f729Sjoerg   llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
74467330f729Sjoerg   if (!GV || GV->getType() != ObjCTypes.ClassnfABITy->getPointerTo()) {
74477330f729Sjoerg     auto *NewGV = new llvm::GlobalVariable(ObjCTypes.ClassnfABITy, false, L,
74487330f729Sjoerg                                            nullptr, Name);
74497330f729Sjoerg 
74507330f729Sjoerg     if (DLLImport)
74517330f729Sjoerg       NewGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
74527330f729Sjoerg 
74537330f729Sjoerg     if (GV) {
74547330f729Sjoerg       GV->replaceAllUsesWith(
74557330f729Sjoerg           llvm::ConstantExpr::getBitCast(NewGV, GV->getType()));
74567330f729Sjoerg       GV->eraseFromParent();
74577330f729Sjoerg     }
74587330f729Sjoerg     GV = NewGV;
74597330f729Sjoerg     CGM.getModule().getGlobalList().push_back(GV);
74607330f729Sjoerg   }
74617330f729Sjoerg 
74627330f729Sjoerg   assert(GV->getLinkage() == L);
74637330f729Sjoerg   return GV;
74647330f729Sjoerg }
74657330f729Sjoerg 
74667330f729Sjoerg llvm::Constant *
GetClassGlobalForClassRef(const ObjCInterfaceDecl * ID)74677330f729Sjoerg CGObjCNonFragileABIMac::GetClassGlobalForClassRef(const ObjCInterfaceDecl *ID) {
74687330f729Sjoerg   llvm::Constant *ClassGV = GetClassGlobal(ID, /*metaclass*/ false,
74697330f729Sjoerg                                            NotForDefinition);
74707330f729Sjoerg 
74717330f729Sjoerg   if (!ID->hasAttr<ObjCClassStubAttr>())
74727330f729Sjoerg     return ClassGV;
74737330f729Sjoerg 
74747330f729Sjoerg   ClassGV = llvm::ConstantExpr::getPointerCast(ClassGV, ObjCTypes.Int8PtrTy);
74757330f729Sjoerg 
74767330f729Sjoerg   // Stub classes are pointer-aligned. Classrefs pointing at stub classes
74777330f729Sjoerg   // must set the least significant bit set to 1.
74787330f729Sjoerg   auto *Idx = llvm::ConstantInt::get(CGM.Int32Ty, 1);
74797330f729Sjoerg   return llvm::ConstantExpr::getGetElementPtr(CGM.Int8Ty, ClassGV, Idx);
74807330f729Sjoerg }
74817330f729Sjoerg 
74827330f729Sjoerg llvm::Value *
EmitLoadOfClassRef(CodeGenFunction & CGF,const ObjCInterfaceDecl * ID,llvm::GlobalVariable * Entry)74837330f729Sjoerg CGObjCNonFragileABIMac::EmitLoadOfClassRef(CodeGenFunction &CGF,
74847330f729Sjoerg                                            const ObjCInterfaceDecl *ID,
74857330f729Sjoerg                                            llvm::GlobalVariable *Entry) {
74867330f729Sjoerg   if (ID && ID->hasAttr<ObjCClassStubAttr>()) {
74877330f729Sjoerg     // Classrefs pointing at Objective-C stub classes must be loaded by calling
74887330f729Sjoerg     // a special runtime function.
74897330f729Sjoerg     return CGF.EmitRuntimeCall(
74907330f729Sjoerg       ObjCTypes.getLoadClassrefFn(), Entry, "load_classref_result");
74917330f729Sjoerg   }
74927330f729Sjoerg 
74937330f729Sjoerg   CharUnits Align = CGF.getPointerAlign();
7494*e038c9c4Sjoerg   return CGF.Builder.CreateAlignedLoad(Entry->getValueType(), Entry, Align);
74957330f729Sjoerg }
74967330f729Sjoerg 
74977330f729Sjoerg llvm::Value *
EmitClassRefFromId(CodeGenFunction & CGF,IdentifierInfo * II,const ObjCInterfaceDecl * ID)74987330f729Sjoerg CGObjCNonFragileABIMac::EmitClassRefFromId(CodeGenFunction &CGF,
74997330f729Sjoerg                                            IdentifierInfo *II,
75007330f729Sjoerg                                            const ObjCInterfaceDecl *ID) {
75017330f729Sjoerg   llvm::GlobalVariable *&Entry = ClassReferences[II];
75027330f729Sjoerg 
75037330f729Sjoerg   if (!Entry) {
75047330f729Sjoerg     llvm::Constant *ClassGV;
75057330f729Sjoerg     if (ID) {
75067330f729Sjoerg       ClassGV = GetClassGlobalForClassRef(ID);
75077330f729Sjoerg     } else {
75087330f729Sjoerg       ClassGV = GetClassGlobal((getClassSymbolPrefix() + II->getName()).str(),
75097330f729Sjoerg                                NotForDefinition);
75107330f729Sjoerg       assert(ClassGV->getType() == ObjCTypes.ClassnfABIPtrTy &&
75117330f729Sjoerg              "classref was emitted with the wrong type?");
75127330f729Sjoerg     }
75137330f729Sjoerg 
75147330f729Sjoerg     std::string SectionName =
75157330f729Sjoerg         GetSectionName("__objc_classrefs", "regular,no_dead_strip");
75167330f729Sjoerg     Entry = new llvm::GlobalVariable(
75177330f729Sjoerg         CGM.getModule(), ClassGV->getType(), false,
75187330f729Sjoerg         getLinkageTypeForObjCMetadata(CGM, SectionName), ClassGV,
75197330f729Sjoerg         "OBJC_CLASSLIST_REFERENCES_$_");
75207330f729Sjoerg     Entry->setAlignment(CGF.getPointerAlign().getAsAlign());
75217330f729Sjoerg     if (!ID || !ID->hasAttr<ObjCClassStubAttr>())
75227330f729Sjoerg       Entry->setSection(SectionName);
75237330f729Sjoerg 
75247330f729Sjoerg     CGM.addCompilerUsedGlobal(Entry);
75257330f729Sjoerg   }
75267330f729Sjoerg 
75277330f729Sjoerg   return EmitLoadOfClassRef(CGF, ID, Entry);
75287330f729Sjoerg }
75297330f729Sjoerg 
EmitClassRef(CodeGenFunction & CGF,const ObjCInterfaceDecl * ID)75307330f729Sjoerg llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CodeGenFunction &CGF,
75317330f729Sjoerg                                                   const ObjCInterfaceDecl *ID) {
75327330f729Sjoerg   // If the class has the objc_runtime_visible attribute, we need to
75337330f729Sjoerg   // use the Objective-C runtime to get the class.
75347330f729Sjoerg   if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
75357330f729Sjoerg     return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
75367330f729Sjoerg 
75377330f729Sjoerg   return EmitClassRefFromId(CGF, ID->getIdentifier(), ID);
75387330f729Sjoerg }
75397330f729Sjoerg 
EmitNSAutoreleasePoolClassRef(CodeGenFunction & CGF)75407330f729Sjoerg llvm::Value *CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef(
75417330f729Sjoerg                                                     CodeGenFunction &CGF) {
75427330f729Sjoerg   IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
75437330f729Sjoerg   return EmitClassRefFromId(CGF, II, nullptr);
75447330f729Sjoerg }
75457330f729Sjoerg 
75467330f729Sjoerg llvm::Value *
EmitSuperClassRef(CodeGenFunction & CGF,const ObjCInterfaceDecl * ID)75477330f729Sjoerg CGObjCNonFragileABIMac::EmitSuperClassRef(CodeGenFunction &CGF,
75487330f729Sjoerg                                           const ObjCInterfaceDecl *ID) {
75497330f729Sjoerg   llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
75507330f729Sjoerg 
75517330f729Sjoerg   if (!Entry) {
75527330f729Sjoerg     llvm::Constant *ClassGV = GetClassGlobalForClassRef(ID);
75537330f729Sjoerg     std::string SectionName =
75547330f729Sjoerg         GetSectionName("__objc_superrefs", "regular,no_dead_strip");
7555*e038c9c4Sjoerg     Entry = new llvm::GlobalVariable(CGM.getModule(), ClassGV->getType(), false,
7556*e038c9c4Sjoerg                                      llvm::GlobalValue::PrivateLinkage, ClassGV,
75577330f729Sjoerg                                      "OBJC_CLASSLIST_SUP_REFS_$_");
75587330f729Sjoerg     Entry->setAlignment(CGF.getPointerAlign().getAsAlign());
75597330f729Sjoerg     Entry->setSection(SectionName);
75607330f729Sjoerg     CGM.addCompilerUsedGlobal(Entry);
75617330f729Sjoerg   }
75627330f729Sjoerg 
75637330f729Sjoerg   return EmitLoadOfClassRef(CGF, ID, Entry);
75647330f729Sjoerg }
75657330f729Sjoerg 
75667330f729Sjoerg /// EmitMetaClassRef - Return a Value * of the address of _class_t
75677330f729Sjoerg /// meta-data
75687330f729Sjoerg ///
EmitMetaClassRef(CodeGenFunction & CGF,const ObjCInterfaceDecl * ID,bool Weak)75697330f729Sjoerg llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CodeGenFunction &CGF,
75707330f729Sjoerg                                                       const ObjCInterfaceDecl *ID,
75717330f729Sjoerg                                                       bool Weak) {
75727330f729Sjoerg   CharUnits Align = CGF.getPointerAlign();
75737330f729Sjoerg   llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
75747330f729Sjoerg   if (!Entry) {
75757330f729Sjoerg     auto MetaClassGV = GetClassGlobal(ID, /*metaclass*/ true, NotForDefinition);
75767330f729Sjoerg     std::string SectionName =
75777330f729Sjoerg         GetSectionName("__objc_superrefs", "regular,no_dead_strip");
7578*e038c9c4Sjoerg     Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
7579*e038c9c4Sjoerg                                      false, llvm::GlobalValue::PrivateLinkage,
7580*e038c9c4Sjoerg                                      MetaClassGV, "OBJC_CLASSLIST_SUP_REFS_$_");
75817330f729Sjoerg     Entry->setAlignment(Align.getAsAlign());
75827330f729Sjoerg     Entry->setSection(SectionName);
75837330f729Sjoerg     CGM.addCompilerUsedGlobal(Entry);
75847330f729Sjoerg   }
75857330f729Sjoerg 
7586*e038c9c4Sjoerg   return CGF.Builder.CreateAlignedLoad(ObjCTypes.ClassnfABIPtrTy, Entry, Align);
75877330f729Sjoerg }
75887330f729Sjoerg 
75897330f729Sjoerg /// GetClass - Return a reference to the class for the given interface
75907330f729Sjoerg /// decl.
GetClass(CodeGenFunction & CGF,const ObjCInterfaceDecl * ID)75917330f729Sjoerg llvm::Value *CGObjCNonFragileABIMac::GetClass(CodeGenFunction &CGF,
75927330f729Sjoerg                                               const ObjCInterfaceDecl *ID) {
75937330f729Sjoerg   if (ID->isWeakImported()) {
75947330f729Sjoerg     auto ClassGV = GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition);
75957330f729Sjoerg     (void)ClassGV;
75967330f729Sjoerg     assert(!isa<llvm::GlobalVariable>(ClassGV) ||
75977330f729Sjoerg            cast<llvm::GlobalVariable>(ClassGV)->hasExternalWeakLinkage());
75987330f729Sjoerg   }
75997330f729Sjoerg 
76007330f729Sjoerg   return EmitClassRef(CGF, ID);
76017330f729Sjoerg }
76027330f729Sjoerg 
76037330f729Sjoerg /// Generates a message send where the super is the receiver.  This is
76047330f729Sjoerg /// a message send to self with special delivery semantics indicating
76057330f729Sjoerg /// which class's method should be called.
76067330f729Sjoerg 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)76077330f729Sjoerg CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
76087330f729Sjoerg                                                  ReturnValueSlot Return,
76097330f729Sjoerg                                                  QualType ResultType,
76107330f729Sjoerg                                                  Selector Sel,
76117330f729Sjoerg                                                  const ObjCInterfaceDecl *Class,
76127330f729Sjoerg                                                  bool isCategoryImpl,
76137330f729Sjoerg                                                  llvm::Value *Receiver,
76147330f729Sjoerg                                                  bool IsClassMessage,
76157330f729Sjoerg                                                  const CodeGen::CallArgList &CallArgs,
76167330f729Sjoerg                                                  const ObjCMethodDecl *Method) {
76177330f729Sjoerg   // ...
76187330f729Sjoerg   // Create and init a super structure; this is a (receiver, class)
76197330f729Sjoerg   // pair we will pass to objc_msgSendSuper.
76207330f729Sjoerg   Address ObjCSuper =
76217330f729Sjoerg     CGF.CreateTempAlloca(ObjCTypes.SuperTy, CGF.getPointerAlign(),
76227330f729Sjoerg                          "objc_super");
76237330f729Sjoerg 
76247330f729Sjoerg   llvm::Value *ReceiverAsObject =
76257330f729Sjoerg     CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
76267330f729Sjoerg   CGF.Builder.CreateStore(ReceiverAsObject,
76277330f729Sjoerg                           CGF.Builder.CreateStructGEP(ObjCSuper, 0));
76287330f729Sjoerg 
76297330f729Sjoerg   // If this is a class message the metaclass is passed as the target.
76307330f729Sjoerg   llvm::Value *Target;
76317330f729Sjoerg   if (IsClassMessage)
76327330f729Sjoerg       Target = EmitMetaClassRef(CGF, Class, Class->isWeakImported());
76337330f729Sjoerg   else
76347330f729Sjoerg     Target = EmitSuperClassRef(CGF, Class);
76357330f729Sjoerg 
76367330f729Sjoerg   // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
76377330f729Sjoerg   // ObjCTypes types.
76387330f729Sjoerg   llvm::Type *ClassTy =
76397330f729Sjoerg     CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
76407330f729Sjoerg   Target = CGF.Builder.CreateBitCast(Target, ClassTy);
76417330f729Sjoerg   CGF.Builder.CreateStore(Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1));
76427330f729Sjoerg 
76437330f729Sjoerg   return (isVTableDispatchedSelector(Sel))
76447330f729Sjoerg     ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
76457330f729Sjoerg                             ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy,
76467330f729Sjoerg                             true, CallArgs, Method)
7647*e038c9c4Sjoerg     : EmitMessageSend(CGF, Return, ResultType, Sel,
76487330f729Sjoerg                       ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy,
76497330f729Sjoerg                       true, CallArgs, Method, Class, ObjCTypes);
76507330f729Sjoerg }
76517330f729Sjoerg 
EmitSelector(CodeGenFunction & CGF,Selector Sel)76527330f729Sjoerg llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CodeGenFunction &CGF,
76537330f729Sjoerg                                                   Selector Sel) {
7654*e038c9c4Sjoerg   Address Addr = EmitSelectorAddr(Sel);
76557330f729Sjoerg 
76567330f729Sjoerg   llvm::LoadInst* LI = CGF.Builder.CreateLoad(Addr);
76577330f729Sjoerg   LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
76587330f729Sjoerg                   llvm::MDNode::get(VMContext, None));
76597330f729Sjoerg   return LI;
76607330f729Sjoerg }
76617330f729Sjoerg 
EmitSelectorAddr(Selector Sel)7662*e038c9c4Sjoerg Address CGObjCNonFragileABIMac::EmitSelectorAddr(Selector Sel) {
76637330f729Sjoerg   llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
7664*e038c9c4Sjoerg   CharUnits Align = CGM.getPointerAlign();
76657330f729Sjoerg   if (!Entry) {
76667330f729Sjoerg     llvm::Constant *Casted =
76677330f729Sjoerg       llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
76687330f729Sjoerg                                      ObjCTypes.SelectorPtrTy);
76697330f729Sjoerg     std::string SectionName =
76707330f729Sjoerg         GetSectionName("__objc_selrefs", "literal_pointers,no_dead_strip");
76717330f729Sjoerg     Entry = new llvm::GlobalVariable(
76727330f729Sjoerg         CGM.getModule(), ObjCTypes.SelectorPtrTy, false,
76737330f729Sjoerg         getLinkageTypeForObjCMetadata(CGM, SectionName), Casted,
76747330f729Sjoerg         "OBJC_SELECTOR_REFERENCES_");
76757330f729Sjoerg     Entry->setExternallyInitialized(true);
76767330f729Sjoerg     Entry->setSection(SectionName);
76777330f729Sjoerg     Entry->setAlignment(Align.getAsAlign());
76787330f729Sjoerg     CGM.addCompilerUsedGlobal(Entry);
76797330f729Sjoerg   }
76807330f729Sjoerg 
76817330f729Sjoerg   return Address(Entry, Align);
76827330f729Sjoerg }
76837330f729Sjoerg 
76847330f729Sjoerg /// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
76857330f729Sjoerg /// objc_assign_ivar (id src, id *dst, ptrdiff_t)
76867330f729Sjoerg ///
EmitObjCIvarAssign(CodeGen::CodeGenFunction & CGF,llvm::Value * src,Address dst,llvm::Value * ivarOffset)76877330f729Sjoerg void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
76887330f729Sjoerg                                                 llvm::Value *src,
76897330f729Sjoerg                                                 Address dst,
76907330f729Sjoerg                                                 llvm::Value *ivarOffset) {
76917330f729Sjoerg   llvm::Type * SrcTy = src->getType();
76927330f729Sjoerg   if (!isa<llvm::PointerType>(SrcTy)) {
76937330f729Sjoerg     unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
76947330f729Sjoerg     assert(Size <= 8 && "does not support size > 8");
76957330f729Sjoerg     src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
76967330f729Sjoerg            : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
76977330f729Sjoerg     src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
76987330f729Sjoerg   }
76997330f729Sjoerg   src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
77007330f729Sjoerg   dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
77017330f729Sjoerg   llvm::Value *args[] = { src, dst.getPointer(), ivarOffset };
77027330f729Sjoerg   CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
77037330f729Sjoerg }
77047330f729Sjoerg 
77057330f729Sjoerg /// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
77067330f729Sjoerg /// objc_assign_strongCast (id src, id *dst)
77077330f729Sjoerg ///
EmitObjCStrongCastAssign(CodeGen::CodeGenFunction & CGF,llvm::Value * src,Address dst)77087330f729Sjoerg void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
77097330f729Sjoerg   CodeGen::CodeGenFunction &CGF,
77107330f729Sjoerg   llvm::Value *src, Address dst) {
77117330f729Sjoerg   llvm::Type * SrcTy = src->getType();
77127330f729Sjoerg   if (!isa<llvm::PointerType>(SrcTy)) {
77137330f729Sjoerg     unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
77147330f729Sjoerg     assert(Size <= 8 && "does not support size > 8");
77157330f729Sjoerg     src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
77167330f729Sjoerg            : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
77177330f729Sjoerg     src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
77187330f729Sjoerg   }
77197330f729Sjoerg   src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
77207330f729Sjoerg   dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
77217330f729Sjoerg   llvm::Value *args[] = { src, dst.getPointer() };
77227330f729Sjoerg   CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(),
77237330f729Sjoerg                               args, "weakassign");
77247330f729Sjoerg }
77257330f729Sjoerg 
EmitGCMemmoveCollectable(CodeGen::CodeGenFunction & CGF,Address DestPtr,Address SrcPtr,llvm::Value * Size)77267330f729Sjoerg void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
77277330f729Sjoerg   CodeGen::CodeGenFunction &CGF,
77287330f729Sjoerg   Address DestPtr,
77297330f729Sjoerg   Address SrcPtr,
77307330f729Sjoerg   llvm::Value *Size) {
77317330f729Sjoerg   SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
77327330f729Sjoerg   DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
77337330f729Sjoerg   llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), Size };
77347330f729Sjoerg   CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
77357330f729Sjoerg }
77367330f729Sjoerg 
77377330f729Sjoerg /// EmitObjCWeakRead - Code gen for loading value of a __weak
77387330f729Sjoerg /// object: objc_read_weak (id *src)
77397330f729Sjoerg ///
EmitObjCWeakRead(CodeGen::CodeGenFunction & CGF,Address AddrWeakObj)77407330f729Sjoerg llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
77417330f729Sjoerg   CodeGen::CodeGenFunction &CGF,
77427330f729Sjoerg   Address AddrWeakObj) {
77437330f729Sjoerg   llvm::Type *DestTy = AddrWeakObj.getElementType();
77447330f729Sjoerg   AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
77457330f729Sjoerg   llvm::Value *read_weak =
77467330f729Sjoerg     CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(),
77477330f729Sjoerg                                 AddrWeakObj.getPointer(), "weakread");
77487330f729Sjoerg   read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
77497330f729Sjoerg   return read_weak;
77507330f729Sjoerg }
77517330f729Sjoerg 
77527330f729Sjoerg /// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
77537330f729Sjoerg /// objc_assign_weak (id src, id *dst)
77547330f729Sjoerg ///
EmitObjCWeakAssign(CodeGen::CodeGenFunction & CGF,llvm::Value * src,Address dst)77557330f729Sjoerg void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
77567330f729Sjoerg                                                 llvm::Value *src, Address dst) {
77577330f729Sjoerg   llvm::Type * SrcTy = src->getType();
77587330f729Sjoerg   if (!isa<llvm::PointerType>(SrcTy)) {
77597330f729Sjoerg     unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
77607330f729Sjoerg     assert(Size <= 8 && "does not support size > 8");
77617330f729Sjoerg     src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
77627330f729Sjoerg            : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
77637330f729Sjoerg     src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
77647330f729Sjoerg   }
77657330f729Sjoerg   src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
77667330f729Sjoerg   dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
77677330f729Sjoerg   llvm::Value *args[] = { src, dst.getPointer() };
77687330f729Sjoerg   CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(),
77697330f729Sjoerg                               args, "weakassign");
77707330f729Sjoerg }
77717330f729Sjoerg 
77727330f729Sjoerg /// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
77737330f729Sjoerg /// objc_assign_global (id src, id *dst)
77747330f729Sjoerg ///
EmitObjCGlobalAssign(CodeGen::CodeGenFunction & CGF,llvm::Value * src,Address dst,bool threadlocal)77757330f729Sjoerg void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
77767330f729Sjoerg                                           llvm::Value *src, Address dst,
77777330f729Sjoerg                                           bool threadlocal) {
77787330f729Sjoerg   llvm::Type * SrcTy = src->getType();
77797330f729Sjoerg   if (!isa<llvm::PointerType>(SrcTy)) {
77807330f729Sjoerg     unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
77817330f729Sjoerg     assert(Size <= 8 && "does not support size > 8");
77827330f729Sjoerg     src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
77837330f729Sjoerg            : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
77847330f729Sjoerg     src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
77857330f729Sjoerg   }
77867330f729Sjoerg   src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
77877330f729Sjoerg   dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
77887330f729Sjoerg   llvm::Value *args[] = { src, dst.getPointer() };
77897330f729Sjoerg   if (!threadlocal)
77907330f729Sjoerg     CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(),
77917330f729Sjoerg                                 args, "globalassign");
77927330f729Sjoerg   else
77937330f729Sjoerg     CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(),
77947330f729Sjoerg                                 args, "threadlocalassign");
77957330f729Sjoerg }
77967330f729Sjoerg 
77977330f729Sjoerg void
EmitSynchronizedStmt(CodeGen::CodeGenFunction & CGF,const ObjCAtSynchronizedStmt & S)77987330f729Sjoerg CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
77997330f729Sjoerg                                              const ObjCAtSynchronizedStmt &S) {
78007330f729Sjoerg   EmitAtSynchronizedStmt(CGF, S, ObjCTypes.getSyncEnterFn(),
78017330f729Sjoerg                          ObjCTypes.getSyncExitFn());
78027330f729Sjoerg }
78037330f729Sjoerg 
78047330f729Sjoerg llvm::Constant *
GetEHType(QualType T)78057330f729Sjoerg CGObjCNonFragileABIMac::GetEHType(QualType T) {
78067330f729Sjoerg   // There's a particular fixed type info for 'id'.
78077330f729Sjoerg   if (T->isObjCIdType() || T->isObjCQualifiedIdType()) {
78087330f729Sjoerg     auto *IDEHType = CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
78097330f729Sjoerg     if (!IDEHType) {
78107330f729Sjoerg       IDEHType =
78117330f729Sjoerg           new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
78127330f729Sjoerg                                    llvm::GlobalValue::ExternalLinkage, nullptr,
78137330f729Sjoerg                                    "OBJC_EHTYPE_id");
78147330f729Sjoerg       if (CGM.getTriple().isOSBinFormatCOFF())
78157330f729Sjoerg         IDEHType->setDLLStorageClass(getStorage(CGM, "OBJC_EHTYPE_id"));
78167330f729Sjoerg     }
78177330f729Sjoerg     return IDEHType;
78187330f729Sjoerg   }
78197330f729Sjoerg 
78207330f729Sjoerg   // All other types should be Objective-C interface pointer types.
78217330f729Sjoerg   const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>();
78227330f729Sjoerg   assert(PT && "Invalid @catch type.");
78237330f729Sjoerg 
78247330f729Sjoerg   const ObjCInterfaceType *IT = PT->getInterfaceType();
78257330f729Sjoerg   assert(IT && "Invalid @catch type.");
78267330f729Sjoerg 
78277330f729Sjoerg   return GetInterfaceEHType(IT->getDecl(), NotForDefinition);
78287330f729Sjoerg }
78297330f729Sjoerg 
EmitTryStmt(CodeGen::CodeGenFunction & CGF,const ObjCAtTryStmt & S)78307330f729Sjoerg void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
78317330f729Sjoerg                                          const ObjCAtTryStmt &S) {
78327330f729Sjoerg   EmitTryCatchStmt(CGF, S, ObjCTypes.getObjCBeginCatchFn(),
78337330f729Sjoerg                    ObjCTypes.getObjCEndCatchFn(),
78347330f729Sjoerg                    ObjCTypes.getExceptionRethrowFn());
78357330f729Sjoerg }
78367330f729Sjoerg 
78377330f729Sjoerg /// EmitThrowStmt - Generate code for a throw statement.
EmitThrowStmt(CodeGen::CodeGenFunction & CGF,const ObjCAtThrowStmt & S,bool ClearInsertionPoint)78387330f729Sjoerg void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
78397330f729Sjoerg                                            const ObjCAtThrowStmt &S,
78407330f729Sjoerg                                            bool ClearInsertionPoint) {
78417330f729Sjoerg   if (const Expr *ThrowExpr = S.getThrowExpr()) {
78427330f729Sjoerg     llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
78437330f729Sjoerg     Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
78447330f729Sjoerg     llvm::CallBase *Call =
78457330f729Sjoerg         CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionThrowFn(), Exception);
78467330f729Sjoerg     Call->setDoesNotReturn();
78477330f729Sjoerg   } else {
78487330f729Sjoerg     llvm::CallBase *Call =
78497330f729Sjoerg         CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionRethrowFn());
78507330f729Sjoerg     Call->setDoesNotReturn();
78517330f729Sjoerg   }
78527330f729Sjoerg 
78537330f729Sjoerg   CGF.Builder.CreateUnreachable();
78547330f729Sjoerg   if (ClearInsertionPoint)
78557330f729Sjoerg     CGF.Builder.ClearInsertionPoint();
78567330f729Sjoerg }
78577330f729Sjoerg 
78587330f729Sjoerg llvm::Constant *
GetInterfaceEHType(const ObjCInterfaceDecl * ID,ForDefinition_t IsForDefinition)78597330f729Sjoerg CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
78607330f729Sjoerg                                            ForDefinition_t IsForDefinition) {
78617330f729Sjoerg   llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
78627330f729Sjoerg   StringRef ClassName = ID->getObjCRuntimeNameAsString();
78637330f729Sjoerg 
78647330f729Sjoerg   // If we don't need a definition, return the entry if found or check
78657330f729Sjoerg   // if we use an external reference.
78667330f729Sjoerg   if (!IsForDefinition) {
78677330f729Sjoerg     if (Entry)
78687330f729Sjoerg       return Entry;
78697330f729Sjoerg 
78707330f729Sjoerg     // If this type (or a super class) has the __objc_exception__
78717330f729Sjoerg     // attribute, emit an external reference.
78727330f729Sjoerg     if (hasObjCExceptionAttribute(CGM.getContext(), ID)) {
78737330f729Sjoerg       std::string EHTypeName = ("OBJC_EHTYPE_$_" + ClassName).str();
78747330f729Sjoerg       Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
78757330f729Sjoerg                                        false, llvm::GlobalValue::ExternalLinkage,
78767330f729Sjoerg                                        nullptr, EHTypeName);
78777330f729Sjoerg       CGM.setGVProperties(Entry, ID);
78787330f729Sjoerg       return Entry;
78797330f729Sjoerg     }
78807330f729Sjoerg   }
78817330f729Sjoerg 
78827330f729Sjoerg   // Otherwise we need to either make a new entry or fill in the initializer.
78837330f729Sjoerg   assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition");
78847330f729Sjoerg 
78857330f729Sjoerg   std::string VTableName = "objc_ehtype_vtable";
78867330f729Sjoerg   auto *VTableGV = CGM.getModule().getGlobalVariable(VTableName);
78877330f729Sjoerg   if (!VTableGV) {
78887330f729Sjoerg     VTableGV =
78897330f729Sjoerg         new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy, false,
78907330f729Sjoerg                                  llvm::GlobalValue::ExternalLinkage, nullptr,
78917330f729Sjoerg                                  VTableName);
78927330f729Sjoerg     if (CGM.getTriple().isOSBinFormatCOFF())
78937330f729Sjoerg       VTableGV->setDLLStorageClass(getStorage(CGM, VTableName));
78947330f729Sjoerg   }
78957330f729Sjoerg 
78967330f729Sjoerg   llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2);
78977330f729Sjoerg   ConstantInitBuilder builder(CGM);
78987330f729Sjoerg   auto values = builder.beginStruct(ObjCTypes.EHTypeTy);
78997330f729Sjoerg   values.add(
79007330f729Sjoerg     llvm::ConstantExpr::getInBoundsGetElementPtr(VTableGV->getValueType(),
79017330f729Sjoerg                                                  VTableGV, VTableIdx));
79027330f729Sjoerg   values.add(GetClassName(ClassName));
79037330f729Sjoerg   values.add(GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition));
79047330f729Sjoerg 
79057330f729Sjoerg   llvm::GlobalValue::LinkageTypes L = IsForDefinition
79067330f729Sjoerg                                           ? llvm::GlobalValue::ExternalLinkage
79077330f729Sjoerg                                           : llvm::GlobalValue::WeakAnyLinkage;
79087330f729Sjoerg   if (Entry) {
79097330f729Sjoerg     values.finishAndSetAsInitializer(Entry);
79107330f729Sjoerg     Entry->setAlignment(CGM.getPointerAlign().getAsAlign());
79117330f729Sjoerg   } else {
79127330f729Sjoerg     Entry = values.finishAndCreateGlobal("OBJC_EHTYPE_$_" + ClassName,
79137330f729Sjoerg                                          CGM.getPointerAlign(),
79147330f729Sjoerg                                          /*constant*/ false,
79157330f729Sjoerg                                          L);
79167330f729Sjoerg     if (hasObjCExceptionAttribute(CGM.getContext(), ID))
79177330f729Sjoerg       CGM.setGVProperties(Entry, ID);
79187330f729Sjoerg   }
79197330f729Sjoerg   assert(Entry->getLinkage() == L);
79207330f729Sjoerg 
79217330f729Sjoerg   if (!CGM.getTriple().isOSBinFormatCOFF())
79227330f729Sjoerg     if (ID->getVisibility() == HiddenVisibility)
79237330f729Sjoerg       Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
79247330f729Sjoerg 
79257330f729Sjoerg   if (IsForDefinition)
79267330f729Sjoerg     if (CGM.getTriple().isOSBinFormatMachO())
79277330f729Sjoerg       Entry->setSection("__DATA,__objc_const");
79287330f729Sjoerg 
79297330f729Sjoerg   return Entry;
79307330f729Sjoerg }
79317330f729Sjoerg 
79327330f729Sjoerg /* *** */
79337330f729Sjoerg 
79347330f729Sjoerg CodeGen::CGObjCRuntime *
CreateMacObjCRuntime(CodeGen::CodeGenModule & CGM)79357330f729Sjoerg CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
79367330f729Sjoerg   switch (CGM.getLangOpts().ObjCRuntime.getKind()) {
79377330f729Sjoerg   case ObjCRuntime::FragileMacOSX:
79387330f729Sjoerg   return new CGObjCMac(CGM);
79397330f729Sjoerg 
79407330f729Sjoerg   case ObjCRuntime::MacOSX:
79417330f729Sjoerg   case ObjCRuntime::iOS:
79427330f729Sjoerg   case ObjCRuntime::WatchOS:
79437330f729Sjoerg     return new CGObjCNonFragileABIMac(CGM);
79447330f729Sjoerg 
79457330f729Sjoerg   case ObjCRuntime::GNUstep:
79467330f729Sjoerg   case ObjCRuntime::GCC:
79477330f729Sjoerg   case ObjCRuntime::ObjFW:
79487330f729Sjoerg     llvm_unreachable("these runtimes are not Mac runtimes");
79497330f729Sjoerg   }
79507330f729Sjoerg   llvm_unreachable("bad runtime");
79517330f729Sjoerg }
7952