xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/CodeGen/CGObjCGNU.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
17330f729Sjoerg //===------- CGObjCGNU.cpp - Emit LLVM Code from ASTs for a Module --------===//
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 GNU runtime.  The
107330f729Sjoerg // class in this file generates structures used by the GNU Objective-C runtime
117330f729Sjoerg // library.  These structures are defined in objc/objc.h and objc/objc-api.h in
127330f729Sjoerg // the GNU runtime distribution.
137330f729Sjoerg //
147330f729Sjoerg //===----------------------------------------------------------------------===//
157330f729Sjoerg 
16*e038c9c4Sjoerg #include "CGCXXABI.h"
177330f729Sjoerg #include "CGCleanup.h"
18*e038c9c4Sjoerg #include "CGObjCRuntime.h"
197330f729Sjoerg #include "CodeGenFunction.h"
207330f729Sjoerg #include "CodeGenModule.h"
217330f729Sjoerg #include "clang/AST/ASTContext.h"
22*e038c9c4Sjoerg #include "clang/AST/Attr.h"
237330f729Sjoerg #include "clang/AST/Decl.h"
247330f729Sjoerg #include "clang/AST/DeclObjC.h"
257330f729Sjoerg #include "clang/AST/RecordLayout.h"
267330f729Sjoerg #include "clang/AST/StmtObjC.h"
277330f729Sjoerg #include "clang/Basic/FileManager.h"
287330f729Sjoerg #include "clang/Basic/SourceManager.h"
29*e038c9c4Sjoerg #include "clang/CodeGen/ConstantInitBuilder.h"
307330f729Sjoerg #include "llvm/ADT/SmallVector.h"
317330f729Sjoerg #include "llvm/ADT/StringMap.h"
327330f729Sjoerg #include "llvm/IR/DataLayout.h"
337330f729Sjoerg #include "llvm/IR/Intrinsics.h"
347330f729Sjoerg #include "llvm/IR/LLVMContext.h"
357330f729Sjoerg #include "llvm/IR/Module.h"
367330f729Sjoerg #include "llvm/Support/Compiler.h"
377330f729Sjoerg #include "llvm/Support/ConvertUTF.h"
387330f729Sjoerg #include <cctype>
397330f729Sjoerg 
407330f729Sjoerg using namespace clang;
417330f729Sjoerg using namespace CodeGen;
427330f729Sjoerg 
437330f729Sjoerg namespace {
447330f729Sjoerg 
457330f729Sjoerg /// Class that lazily initialises the runtime function.  Avoids inserting the
467330f729Sjoerg /// types and the function declaration into a module if they're not used, and
477330f729Sjoerg /// avoids constructing the type more than once if it's used more than once.
487330f729Sjoerg class LazyRuntimeFunction {
497330f729Sjoerg   CodeGenModule *CGM;
507330f729Sjoerg   llvm::FunctionType *FTy;
517330f729Sjoerg   const char *FunctionName;
527330f729Sjoerg   llvm::FunctionCallee Function;
537330f729Sjoerg 
547330f729Sjoerg public:
557330f729Sjoerg   /// Constructor leaves this class uninitialized, because it is intended to
567330f729Sjoerg   /// be used as a field in another class and not all of the types that are
577330f729Sjoerg   /// used as arguments will necessarily be available at construction time.
LazyRuntimeFunction()587330f729Sjoerg   LazyRuntimeFunction()
597330f729Sjoerg       : CGM(nullptr), FunctionName(nullptr), Function(nullptr) {}
607330f729Sjoerg 
617330f729Sjoerg   /// Initialises the lazy function with the name, return type, and the types
627330f729Sjoerg   /// of the arguments.
637330f729Sjoerg   template <typename... Tys>
init(CodeGenModule * Mod,const char * name,llvm::Type * RetTy,Tys * ...Types)647330f729Sjoerg   void init(CodeGenModule *Mod, const char *name, llvm::Type *RetTy,
657330f729Sjoerg             Tys *... Types) {
667330f729Sjoerg     CGM = Mod;
677330f729Sjoerg     FunctionName = name;
687330f729Sjoerg     Function = nullptr;
697330f729Sjoerg     if(sizeof...(Tys)) {
707330f729Sjoerg       SmallVector<llvm::Type *, 8> ArgTys({Types...});
717330f729Sjoerg       FTy = llvm::FunctionType::get(RetTy, ArgTys, false);
727330f729Sjoerg     }
737330f729Sjoerg     else {
747330f729Sjoerg       FTy = llvm::FunctionType::get(RetTy, None, false);
757330f729Sjoerg     }
767330f729Sjoerg   }
777330f729Sjoerg 
getType()787330f729Sjoerg   llvm::FunctionType *getType() { return FTy; }
797330f729Sjoerg 
807330f729Sjoerg   /// Overloaded cast operator, allows the class to be implicitly cast to an
817330f729Sjoerg   /// LLVM constant.
operator llvm::FunctionCallee()827330f729Sjoerg   operator llvm::FunctionCallee() {
837330f729Sjoerg     if (!Function) {
847330f729Sjoerg       if (!FunctionName)
857330f729Sjoerg         return nullptr;
867330f729Sjoerg       Function = CGM->CreateRuntimeFunction(FTy, FunctionName);
877330f729Sjoerg     }
887330f729Sjoerg     return Function;
897330f729Sjoerg   }
907330f729Sjoerg };
917330f729Sjoerg 
927330f729Sjoerg 
937330f729Sjoerg /// GNU Objective-C runtime code generation.  This class implements the parts of
947330f729Sjoerg /// Objective-C support that are specific to the GNU family of runtimes (GCC,
957330f729Sjoerg /// GNUstep and ObjFW).
967330f729Sjoerg class CGObjCGNU : public CGObjCRuntime {
977330f729Sjoerg protected:
987330f729Sjoerg   /// The LLVM module into which output is inserted
997330f729Sjoerg   llvm::Module &TheModule;
1007330f729Sjoerg   /// strut objc_super.  Used for sending messages to super.  This structure
1017330f729Sjoerg   /// contains the receiver (object) and the expected class.
1027330f729Sjoerg   llvm::StructType *ObjCSuperTy;
1037330f729Sjoerg   /// struct objc_super*.  The type of the argument to the superclass message
1047330f729Sjoerg   /// lookup functions.
1057330f729Sjoerg   llvm::PointerType *PtrToObjCSuperTy;
1067330f729Sjoerg   /// LLVM type for selectors.  Opaque pointer (i8*) unless a header declaring
1077330f729Sjoerg   /// SEL is included in a header somewhere, in which case it will be whatever
1087330f729Sjoerg   /// type is declared in that header, most likely {i8*, i8*}.
1097330f729Sjoerg   llvm::PointerType *SelectorTy;
1107330f729Sjoerg   /// LLVM i8 type.  Cached here to avoid repeatedly getting it in all of the
1117330f729Sjoerg   /// places where it's used
1127330f729Sjoerg   llvm::IntegerType *Int8Ty;
1137330f729Sjoerg   /// Pointer to i8 - LLVM type of char*, for all of the places where the
1147330f729Sjoerg   /// runtime needs to deal with C strings.
1157330f729Sjoerg   llvm::PointerType *PtrToInt8Ty;
1167330f729Sjoerg   /// struct objc_protocol type
1177330f729Sjoerg   llvm::StructType *ProtocolTy;
1187330f729Sjoerg   /// Protocol * type.
1197330f729Sjoerg   llvm::PointerType *ProtocolPtrTy;
1207330f729Sjoerg   /// Instance Method Pointer type.  This is a pointer to a function that takes,
1217330f729Sjoerg   /// at a minimum, an object and a selector, and is the generic type for
1227330f729Sjoerg   /// Objective-C methods.  Due to differences between variadic / non-variadic
1237330f729Sjoerg   /// calling conventions, it must always be cast to the correct type before
1247330f729Sjoerg   /// actually being used.
1257330f729Sjoerg   llvm::PointerType *IMPTy;
1267330f729Sjoerg   /// Type of an untyped Objective-C object.  Clang treats id as a built-in type
1277330f729Sjoerg   /// when compiling Objective-C code, so this may be an opaque pointer (i8*),
1287330f729Sjoerg   /// but if the runtime header declaring it is included then it may be a
1297330f729Sjoerg   /// pointer to a structure.
1307330f729Sjoerg   llvm::PointerType *IdTy;
1317330f729Sjoerg   /// Pointer to a pointer to an Objective-C object.  Used in the new ABI
1327330f729Sjoerg   /// message lookup function and some GC-related functions.
1337330f729Sjoerg   llvm::PointerType *PtrToIdTy;
1347330f729Sjoerg   /// The clang type of id.  Used when using the clang CGCall infrastructure to
1357330f729Sjoerg   /// call Objective-C methods.
1367330f729Sjoerg   CanQualType ASTIdTy;
1377330f729Sjoerg   /// LLVM type for C int type.
1387330f729Sjoerg   llvm::IntegerType *IntTy;
1397330f729Sjoerg   /// LLVM type for an opaque pointer.  This is identical to PtrToInt8Ty, but is
1407330f729Sjoerg   /// used in the code to document the difference between i8* meaning a pointer
1417330f729Sjoerg   /// to a C string and i8* meaning a pointer to some opaque type.
1427330f729Sjoerg   llvm::PointerType *PtrTy;
1437330f729Sjoerg   /// LLVM type for C long type.  The runtime uses this in a lot of places where
1447330f729Sjoerg   /// it should be using intptr_t, but we can't fix this without breaking
1457330f729Sjoerg   /// compatibility with GCC...
1467330f729Sjoerg   llvm::IntegerType *LongTy;
1477330f729Sjoerg   /// LLVM type for C size_t.  Used in various runtime data structures.
1487330f729Sjoerg   llvm::IntegerType *SizeTy;
1497330f729Sjoerg   /// LLVM type for C intptr_t.
1507330f729Sjoerg   llvm::IntegerType *IntPtrTy;
1517330f729Sjoerg   /// LLVM type for C ptrdiff_t.  Mainly used in property accessor functions.
1527330f729Sjoerg   llvm::IntegerType *PtrDiffTy;
1537330f729Sjoerg   /// LLVM type for C int*.  Used for GCC-ABI-compatible non-fragile instance
1547330f729Sjoerg   /// variables.
1557330f729Sjoerg   llvm::PointerType *PtrToIntTy;
1567330f729Sjoerg   /// LLVM type for Objective-C BOOL type.
1577330f729Sjoerg   llvm::Type *BoolTy;
1587330f729Sjoerg   /// 32-bit integer type, to save us needing to look it up every time it's used.
1597330f729Sjoerg   llvm::IntegerType *Int32Ty;
1607330f729Sjoerg   /// 64-bit integer type, to save us needing to look it up every time it's used.
1617330f729Sjoerg   llvm::IntegerType *Int64Ty;
1627330f729Sjoerg   /// The type of struct objc_property.
1637330f729Sjoerg   llvm::StructType *PropertyMetadataTy;
1647330f729Sjoerg   /// Metadata kind used to tie method lookups to message sends.  The GNUstep
1657330f729Sjoerg   /// runtime provides some LLVM passes that can use this to do things like
1667330f729Sjoerg   /// automatic IMP caching and speculative inlining.
1677330f729Sjoerg   unsigned msgSendMDKind;
1687330f729Sjoerg   /// Does the current target use SEH-based exceptions? False implies
1697330f729Sjoerg   /// Itanium-style DWARF unwinding.
1707330f729Sjoerg   bool usesSEHExceptions;
1717330f729Sjoerg 
1727330f729Sjoerg   /// Helper to check if we are targeting a specific runtime version or later.
isRuntime(ObjCRuntime::Kind kind,unsigned major,unsigned minor=0)1737330f729Sjoerg   bool isRuntime(ObjCRuntime::Kind kind, unsigned major, unsigned minor=0) {
1747330f729Sjoerg     const ObjCRuntime &R = CGM.getLangOpts().ObjCRuntime;
1757330f729Sjoerg     return (R.getKind() == kind) &&
1767330f729Sjoerg       (R.getVersion() >= VersionTuple(major, minor));
1777330f729Sjoerg   }
1787330f729Sjoerg 
ManglePublicSymbol(StringRef Name)1797330f729Sjoerg   std::string ManglePublicSymbol(StringRef Name) {
1807330f729Sjoerg     return (StringRef(CGM.getTriple().isOSBinFormatCOFF() ? "$_" : "._") + Name).str();
1817330f729Sjoerg   }
1827330f729Sjoerg 
SymbolForProtocol(Twine Name)1837330f729Sjoerg   std::string SymbolForProtocol(Twine Name) {
1847330f729Sjoerg     return (ManglePublicSymbol("OBJC_PROTOCOL_") + Name).str();
1857330f729Sjoerg   }
1867330f729Sjoerg 
SymbolForProtocolRef(StringRef Name)1877330f729Sjoerg   std::string SymbolForProtocolRef(StringRef Name) {
1887330f729Sjoerg     return (ManglePublicSymbol("OBJC_REF_PROTOCOL_") + Name).str();
1897330f729Sjoerg   }
1907330f729Sjoerg 
1917330f729Sjoerg 
1927330f729Sjoerg   /// Helper function that generates a constant string and returns a pointer to
1937330f729Sjoerg   /// the start of the string.  The result of this function can be used anywhere
1947330f729Sjoerg   /// where the C code specifies const char*.
MakeConstantString(StringRef Str,const char * Name="")1957330f729Sjoerg   llvm::Constant *MakeConstantString(StringRef Str, const char *Name = "") {
196*e038c9c4Sjoerg     ConstantAddress Array =
197*e038c9c4Sjoerg         CGM.GetAddrOfConstantCString(std::string(Str), Name);
1987330f729Sjoerg     return llvm::ConstantExpr::getGetElementPtr(Array.getElementType(),
1997330f729Sjoerg                                                 Array.getPointer(), Zeros);
2007330f729Sjoerg   }
2017330f729Sjoerg 
2027330f729Sjoerg   /// Emits a linkonce_odr string, whose name is the prefix followed by the
2037330f729Sjoerg   /// string value.  This allows the linker to combine the strings between
2047330f729Sjoerg   /// different modules.  Used for EH typeinfo names, selector strings, and a
2057330f729Sjoerg   /// few other things.
ExportUniqueString(const std::string & Str,const std::string & prefix,bool Private=false)2067330f729Sjoerg   llvm::Constant *ExportUniqueString(const std::string &Str,
2077330f729Sjoerg                                      const std::string &prefix,
2087330f729Sjoerg                                      bool Private=false) {
2097330f729Sjoerg     std::string name = prefix + Str;
2107330f729Sjoerg     auto *ConstStr = TheModule.getGlobalVariable(name);
2117330f729Sjoerg     if (!ConstStr) {
2127330f729Sjoerg       llvm::Constant *value = llvm::ConstantDataArray::getString(VMContext,Str);
2137330f729Sjoerg       auto *GV = new llvm::GlobalVariable(TheModule, value->getType(), true,
2147330f729Sjoerg               llvm::GlobalValue::LinkOnceODRLinkage, value, name);
2157330f729Sjoerg       GV->setComdat(TheModule.getOrInsertComdat(name));
2167330f729Sjoerg       if (Private)
2177330f729Sjoerg         GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
2187330f729Sjoerg       ConstStr = GV;
2197330f729Sjoerg     }
2207330f729Sjoerg     return llvm::ConstantExpr::getGetElementPtr(ConstStr->getValueType(),
2217330f729Sjoerg                                                 ConstStr, Zeros);
2227330f729Sjoerg   }
2237330f729Sjoerg 
2247330f729Sjoerg   /// Returns a property name and encoding string.
MakePropertyEncodingString(const ObjCPropertyDecl * PD,const Decl * Container)2257330f729Sjoerg   llvm::Constant *MakePropertyEncodingString(const ObjCPropertyDecl *PD,
2267330f729Sjoerg                                              const Decl *Container) {
2277330f729Sjoerg     assert(!isRuntime(ObjCRuntime::GNUstep, 2));
2287330f729Sjoerg     if (isRuntime(ObjCRuntime::GNUstep, 1, 6)) {
2297330f729Sjoerg       std::string NameAndAttributes;
2307330f729Sjoerg       std::string TypeStr =
2317330f729Sjoerg         CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container);
2327330f729Sjoerg       NameAndAttributes += '\0';
2337330f729Sjoerg       NameAndAttributes += TypeStr.length() + 3;
2347330f729Sjoerg       NameAndAttributes += TypeStr;
2357330f729Sjoerg       NameAndAttributes += '\0';
2367330f729Sjoerg       NameAndAttributes += PD->getNameAsString();
2377330f729Sjoerg       return MakeConstantString(NameAndAttributes);
2387330f729Sjoerg     }
2397330f729Sjoerg     return MakeConstantString(PD->getNameAsString());
2407330f729Sjoerg   }
2417330f729Sjoerg 
2427330f729Sjoerg   /// Push the property attributes into two structure fields.
PushPropertyAttributes(ConstantStructBuilder & Fields,const ObjCPropertyDecl * property,bool isSynthesized=true,bool isDynamic=true)2437330f729Sjoerg   void PushPropertyAttributes(ConstantStructBuilder &Fields,
2447330f729Sjoerg       const ObjCPropertyDecl *property, bool isSynthesized=true, bool
2457330f729Sjoerg       isDynamic=true) {
2467330f729Sjoerg     int attrs = property->getPropertyAttributes();
2477330f729Sjoerg     // For read-only properties, clear the copy and retain flags
248*e038c9c4Sjoerg     if (attrs & ObjCPropertyAttribute::kind_readonly) {
249*e038c9c4Sjoerg       attrs &= ~ObjCPropertyAttribute::kind_copy;
250*e038c9c4Sjoerg       attrs &= ~ObjCPropertyAttribute::kind_retain;
251*e038c9c4Sjoerg       attrs &= ~ObjCPropertyAttribute::kind_weak;
252*e038c9c4Sjoerg       attrs &= ~ObjCPropertyAttribute::kind_strong;
2537330f729Sjoerg     }
2547330f729Sjoerg     // The first flags field has the same attribute values as clang uses internally
2557330f729Sjoerg     Fields.addInt(Int8Ty, attrs & 0xff);
2567330f729Sjoerg     attrs >>= 8;
2577330f729Sjoerg     attrs <<= 2;
2587330f729Sjoerg     // For protocol properties, synthesized and dynamic have no meaning, so we
2597330f729Sjoerg     // reuse these flags to indicate that this is a protocol property (both set
2607330f729Sjoerg     // has no meaning, as a property can't be both synthesized and dynamic)
2617330f729Sjoerg     attrs |= isSynthesized ? (1<<0) : 0;
2627330f729Sjoerg     attrs |= isDynamic ? (1<<1) : 0;
2637330f729Sjoerg     // The second field is the next four fields left shifted by two, with the
2647330f729Sjoerg     // low bit set to indicate whether the field is synthesized or dynamic.
2657330f729Sjoerg     Fields.addInt(Int8Ty, attrs & 0xff);
2667330f729Sjoerg     // Two padding fields
2677330f729Sjoerg     Fields.addInt(Int8Ty, 0);
2687330f729Sjoerg     Fields.addInt(Int8Ty, 0);
2697330f729Sjoerg   }
2707330f729Sjoerg 
2717330f729Sjoerg   virtual llvm::Constant *GenerateCategoryProtocolList(const
2727330f729Sjoerg       ObjCCategoryDecl *OCD);
PushPropertyListHeader(ConstantStructBuilder & Fields,int count)2737330f729Sjoerg   virtual ConstantArrayBuilder PushPropertyListHeader(ConstantStructBuilder &Fields,
2747330f729Sjoerg       int count) {
2757330f729Sjoerg       // int count;
2767330f729Sjoerg       Fields.addInt(IntTy, count);
2777330f729Sjoerg       // int size; (only in GNUstep v2 ABI.
2787330f729Sjoerg       if (isRuntime(ObjCRuntime::GNUstep, 2)) {
2797330f729Sjoerg         llvm::DataLayout td(&TheModule);
2807330f729Sjoerg         Fields.addInt(IntTy, td.getTypeSizeInBits(PropertyMetadataTy) /
2817330f729Sjoerg             CGM.getContext().getCharWidth());
2827330f729Sjoerg       }
2837330f729Sjoerg       // struct objc_property_list *next;
2847330f729Sjoerg       Fields.add(NULLPtr);
2857330f729Sjoerg       // struct objc_property properties[]
2867330f729Sjoerg       return Fields.beginArray(PropertyMetadataTy);
2877330f729Sjoerg   }
PushProperty(ConstantArrayBuilder & PropertiesArray,const ObjCPropertyDecl * property,const Decl * OCD,bool isSynthesized=true,bool isDynamic=true)2887330f729Sjoerg   virtual void PushProperty(ConstantArrayBuilder &PropertiesArray,
2897330f729Sjoerg             const ObjCPropertyDecl *property,
2907330f729Sjoerg             const Decl *OCD,
2917330f729Sjoerg             bool isSynthesized=true, bool
2927330f729Sjoerg             isDynamic=true) {
2937330f729Sjoerg     auto Fields = PropertiesArray.beginStruct(PropertyMetadataTy);
2947330f729Sjoerg     ASTContext &Context = CGM.getContext();
2957330f729Sjoerg     Fields.add(MakePropertyEncodingString(property, OCD));
2967330f729Sjoerg     PushPropertyAttributes(Fields, property, isSynthesized, isDynamic);
2977330f729Sjoerg     auto addPropertyMethod = [&](const ObjCMethodDecl *accessor) {
2987330f729Sjoerg       if (accessor) {
2997330f729Sjoerg         std::string TypeStr = Context.getObjCEncodingForMethodDecl(accessor);
3007330f729Sjoerg         llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
3017330f729Sjoerg         Fields.add(MakeConstantString(accessor->getSelector().getAsString()));
3027330f729Sjoerg         Fields.add(TypeEncoding);
3037330f729Sjoerg       } else {
3047330f729Sjoerg         Fields.add(NULLPtr);
3057330f729Sjoerg         Fields.add(NULLPtr);
3067330f729Sjoerg       }
3077330f729Sjoerg     };
3087330f729Sjoerg     addPropertyMethod(property->getGetterMethodDecl());
3097330f729Sjoerg     addPropertyMethod(property->getSetterMethodDecl());
3107330f729Sjoerg     Fields.finishAndAddTo(PropertiesArray);
3117330f729Sjoerg   }
3127330f729Sjoerg 
3137330f729Sjoerg   /// Ensures that the value has the required type, by inserting a bitcast if
3147330f729Sjoerg   /// required.  This function lets us avoid inserting bitcasts that are
3157330f729Sjoerg   /// redundant.
EnforceType(CGBuilderTy & B,llvm::Value * V,llvm::Type * Ty)3167330f729Sjoerg   llvm::Value* EnforceType(CGBuilderTy &B, llvm::Value *V, llvm::Type *Ty) {
3177330f729Sjoerg     if (V->getType() == Ty) return V;
3187330f729Sjoerg     return B.CreateBitCast(V, Ty);
3197330f729Sjoerg   }
EnforceType(CGBuilderTy & B,Address V,llvm::Type * Ty)3207330f729Sjoerg   Address EnforceType(CGBuilderTy &B, Address V, llvm::Type *Ty) {
3217330f729Sjoerg     if (V.getType() == Ty) return V;
3227330f729Sjoerg     return B.CreateBitCast(V, Ty);
3237330f729Sjoerg   }
3247330f729Sjoerg 
3257330f729Sjoerg   // Some zeros used for GEPs in lots of places.
3267330f729Sjoerg   llvm::Constant *Zeros[2];
3277330f729Sjoerg   /// Null pointer value.  Mainly used as a terminator in various arrays.
3287330f729Sjoerg   llvm::Constant *NULLPtr;
3297330f729Sjoerg   /// LLVM context.
3307330f729Sjoerg   llvm::LLVMContext &VMContext;
3317330f729Sjoerg 
3327330f729Sjoerg protected:
3337330f729Sjoerg 
3347330f729Sjoerg   /// Placeholder for the class.  Lots of things refer to the class before we've
3357330f729Sjoerg   /// actually emitted it.  We use this alias as a placeholder, and then replace
3367330f729Sjoerg   /// it with a pointer to the class structure before finally emitting the
3377330f729Sjoerg   /// module.
3387330f729Sjoerg   llvm::GlobalAlias *ClassPtrAlias;
3397330f729Sjoerg   /// Placeholder for the metaclass.  Lots of things refer to the class before
3407330f729Sjoerg   /// we've / actually emitted it.  We use this alias as a placeholder, and then
3417330f729Sjoerg   /// replace / it with a pointer to the metaclass structure before finally
3427330f729Sjoerg   /// emitting the / module.
3437330f729Sjoerg   llvm::GlobalAlias *MetaClassPtrAlias;
3447330f729Sjoerg   /// All of the classes that have been generated for this compilation units.
3457330f729Sjoerg   std::vector<llvm::Constant*> Classes;
3467330f729Sjoerg   /// All of the categories that have been generated for this compilation units.
3477330f729Sjoerg   std::vector<llvm::Constant*> Categories;
3487330f729Sjoerg   /// All of the Objective-C constant strings that have been generated for this
3497330f729Sjoerg   /// compilation units.
3507330f729Sjoerg   std::vector<llvm::Constant*> ConstantStrings;
3517330f729Sjoerg   /// Map from string values to Objective-C constant strings in the output.
3527330f729Sjoerg   /// Used to prevent emitting Objective-C strings more than once.  This should
3537330f729Sjoerg   /// not be required at all - CodeGenModule should manage this list.
3547330f729Sjoerg   llvm::StringMap<llvm::Constant*> ObjCStrings;
3557330f729Sjoerg   /// All of the protocols that have been declared.
3567330f729Sjoerg   llvm::StringMap<llvm::Constant*> ExistingProtocols;
3577330f729Sjoerg   /// For each variant of a selector, we store the type encoding and a
3587330f729Sjoerg   /// placeholder value.  For an untyped selector, the type will be the empty
3597330f729Sjoerg   /// string.  Selector references are all done via the module's selector table,
3607330f729Sjoerg   /// so we create an alias as a placeholder and then replace it with the real
3617330f729Sjoerg   /// value later.
3627330f729Sjoerg   typedef std::pair<std::string, llvm::GlobalAlias*> TypedSelector;
3637330f729Sjoerg   /// Type of the selector map.  This is roughly equivalent to the structure
3647330f729Sjoerg   /// used in the GNUstep runtime, which maintains a list of all of the valid
3657330f729Sjoerg   /// types for a selector in a table.
3667330f729Sjoerg   typedef llvm::DenseMap<Selector, SmallVector<TypedSelector, 2> >
3677330f729Sjoerg     SelectorMap;
3687330f729Sjoerg   /// A map from selectors to selector types.  This allows us to emit all
3697330f729Sjoerg   /// selectors of the same name and type together.
3707330f729Sjoerg   SelectorMap SelectorTable;
3717330f729Sjoerg 
3727330f729Sjoerg   /// Selectors related to memory management.  When compiling in GC mode, we
3737330f729Sjoerg   /// omit these.
3747330f729Sjoerg   Selector RetainSel, ReleaseSel, AutoreleaseSel;
3757330f729Sjoerg   /// Runtime functions used for memory management in GC mode.  Note that clang
3767330f729Sjoerg   /// supports code generation for calling these functions, but neither GNU
3777330f729Sjoerg   /// runtime actually supports this API properly yet.
3787330f729Sjoerg   LazyRuntimeFunction IvarAssignFn, StrongCastAssignFn, MemMoveFn, WeakReadFn,
3797330f729Sjoerg     WeakAssignFn, GlobalAssignFn;
3807330f729Sjoerg 
3817330f729Sjoerg   typedef std::pair<std::string, std::string> ClassAliasPair;
3827330f729Sjoerg   /// All classes that have aliases set for them.
3837330f729Sjoerg   std::vector<ClassAliasPair> ClassAliases;
3847330f729Sjoerg 
3857330f729Sjoerg protected:
3867330f729Sjoerg   /// Function used for throwing Objective-C exceptions.
3877330f729Sjoerg   LazyRuntimeFunction ExceptionThrowFn;
3887330f729Sjoerg   /// Function used for rethrowing exceptions, used at the end of \@finally or
3897330f729Sjoerg   /// \@synchronize blocks.
3907330f729Sjoerg   LazyRuntimeFunction ExceptionReThrowFn;
3917330f729Sjoerg   /// Function called when entering a catch function.  This is required for
3927330f729Sjoerg   /// differentiating Objective-C exceptions and foreign exceptions.
3937330f729Sjoerg   LazyRuntimeFunction EnterCatchFn;
3947330f729Sjoerg   /// Function called when exiting from a catch block.  Used to do exception
3957330f729Sjoerg   /// cleanup.
3967330f729Sjoerg   LazyRuntimeFunction ExitCatchFn;
3977330f729Sjoerg   /// Function called when entering an \@synchronize block.  Acquires the lock.
3987330f729Sjoerg   LazyRuntimeFunction SyncEnterFn;
3997330f729Sjoerg   /// Function called when exiting an \@synchronize block.  Releases the lock.
4007330f729Sjoerg   LazyRuntimeFunction SyncExitFn;
4017330f729Sjoerg 
4027330f729Sjoerg private:
4037330f729Sjoerg   /// Function called if fast enumeration detects that the collection is
4047330f729Sjoerg   /// modified during the update.
4057330f729Sjoerg   LazyRuntimeFunction EnumerationMutationFn;
4067330f729Sjoerg   /// Function for implementing synthesized property getters that return an
4077330f729Sjoerg   /// object.
4087330f729Sjoerg   LazyRuntimeFunction GetPropertyFn;
4097330f729Sjoerg   /// Function for implementing synthesized property setters that return an
4107330f729Sjoerg   /// object.
4117330f729Sjoerg   LazyRuntimeFunction SetPropertyFn;
4127330f729Sjoerg   /// Function used for non-object declared property getters.
4137330f729Sjoerg   LazyRuntimeFunction GetStructPropertyFn;
4147330f729Sjoerg   /// Function used for non-object declared property setters.
4157330f729Sjoerg   LazyRuntimeFunction SetStructPropertyFn;
4167330f729Sjoerg 
4177330f729Sjoerg protected:
4187330f729Sjoerg   /// The version of the runtime that this class targets.  Must match the
4197330f729Sjoerg   /// version in the runtime.
4207330f729Sjoerg   int RuntimeVersion;
4217330f729Sjoerg   /// The version of the protocol class.  Used to differentiate between ObjC1
4227330f729Sjoerg   /// and ObjC2 protocols.  Objective-C 1 protocols can not contain optional
4237330f729Sjoerg   /// components and can not contain declared properties.  We always emit
4247330f729Sjoerg   /// Objective-C 2 property structures, but we have to pretend that they're
4257330f729Sjoerg   /// Objective-C 1 property structures when targeting the GCC runtime or it
4267330f729Sjoerg   /// will abort.
4277330f729Sjoerg   const int ProtocolVersion;
4287330f729Sjoerg   /// The version of the class ABI.  This value is used in the class structure
4297330f729Sjoerg   /// and indicates how various fields should be interpreted.
4307330f729Sjoerg   const int ClassABIVersion;
4317330f729Sjoerg   /// Generates an instance variable list structure.  This is a structure
4327330f729Sjoerg   /// containing a size and an array of structures containing instance variable
4337330f729Sjoerg   /// metadata.  This is used purely for introspection in the fragile ABI.  In
4347330f729Sjoerg   /// the non-fragile ABI, it's used for instance variable fixup.
4357330f729Sjoerg   virtual llvm::Constant *GenerateIvarList(ArrayRef<llvm::Constant *> IvarNames,
4367330f729Sjoerg                              ArrayRef<llvm::Constant *> IvarTypes,
4377330f729Sjoerg                              ArrayRef<llvm::Constant *> IvarOffsets,
4387330f729Sjoerg                              ArrayRef<llvm::Constant *> IvarAlign,
4397330f729Sjoerg                              ArrayRef<Qualifiers::ObjCLifetime> IvarOwnership);
4407330f729Sjoerg 
4417330f729Sjoerg   /// Generates a method list structure.  This is a structure containing a size
4427330f729Sjoerg   /// and an array of structures containing method metadata.
4437330f729Sjoerg   ///
4447330f729Sjoerg   /// This structure is used by both classes and categories, and contains a next
4457330f729Sjoerg   /// pointer allowing them to be chained together in a linked list.
4467330f729Sjoerg   llvm::Constant *GenerateMethodList(StringRef ClassName,
4477330f729Sjoerg       StringRef CategoryName,
4487330f729Sjoerg       ArrayRef<const ObjCMethodDecl*> Methods,
4497330f729Sjoerg       bool isClassMethodList);
4507330f729Sjoerg 
4517330f729Sjoerg   /// Emits an empty protocol.  This is used for \@protocol() where no protocol
4527330f729Sjoerg   /// is found.  The runtime will (hopefully) fix up the pointer to refer to the
4537330f729Sjoerg   /// real protocol.
4547330f729Sjoerg   virtual llvm::Constant *GenerateEmptyProtocol(StringRef ProtocolName);
4557330f729Sjoerg 
4567330f729Sjoerg   /// Generates a list of property metadata structures.  This follows the same
4577330f729Sjoerg   /// pattern as method and instance variable metadata lists.
4587330f729Sjoerg   llvm::Constant *GeneratePropertyList(const Decl *Container,
4597330f729Sjoerg       const ObjCContainerDecl *OCD,
4607330f729Sjoerg       bool isClassProperty=false,
4617330f729Sjoerg       bool protocolOptionalProperties=false);
4627330f729Sjoerg 
4637330f729Sjoerg   /// Generates a list of referenced protocols.  Classes, categories, and
4647330f729Sjoerg   /// protocols all use this structure.
4657330f729Sjoerg   llvm::Constant *GenerateProtocolList(ArrayRef<std::string> Protocols);
4667330f729Sjoerg 
4677330f729Sjoerg   /// To ensure that all protocols are seen by the runtime, we add a category on
4687330f729Sjoerg   /// a class defined in the runtime, declaring no methods, but adopting the
4697330f729Sjoerg   /// protocols.  This is a horribly ugly hack, but it allows us to collect all
4707330f729Sjoerg   /// of the protocols without changing the ABI.
4717330f729Sjoerg   void GenerateProtocolHolderCategory();
4727330f729Sjoerg 
4737330f729Sjoerg   /// Generates a class structure.
4747330f729Sjoerg   llvm::Constant *GenerateClassStructure(
4757330f729Sjoerg       llvm::Constant *MetaClass,
4767330f729Sjoerg       llvm::Constant *SuperClass,
4777330f729Sjoerg       unsigned info,
4787330f729Sjoerg       const char *Name,
4797330f729Sjoerg       llvm::Constant *Version,
4807330f729Sjoerg       llvm::Constant *InstanceSize,
4817330f729Sjoerg       llvm::Constant *IVars,
4827330f729Sjoerg       llvm::Constant *Methods,
4837330f729Sjoerg       llvm::Constant *Protocols,
4847330f729Sjoerg       llvm::Constant *IvarOffsets,
4857330f729Sjoerg       llvm::Constant *Properties,
4867330f729Sjoerg       llvm::Constant *StrongIvarBitmap,
4877330f729Sjoerg       llvm::Constant *WeakIvarBitmap,
4887330f729Sjoerg       bool isMeta=false);
4897330f729Sjoerg 
4907330f729Sjoerg   /// Generates a method list.  This is used by protocols to define the required
4917330f729Sjoerg   /// and optional methods.
4927330f729Sjoerg   virtual llvm::Constant *GenerateProtocolMethodList(
4937330f729Sjoerg       ArrayRef<const ObjCMethodDecl*> Methods);
4947330f729Sjoerg   /// Emits optional and required method lists.
4957330f729Sjoerg   template<class T>
EmitProtocolMethodList(T && Methods,llvm::Constant * & Required,llvm::Constant * & Optional)4967330f729Sjoerg   void EmitProtocolMethodList(T &&Methods, llvm::Constant *&Required,
4977330f729Sjoerg       llvm::Constant *&Optional) {
4987330f729Sjoerg     SmallVector<const ObjCMethodDecl*, 16> RequiredMethods;
4997330f729Sjoerg     SmallVector<const ObjCMethodDecl*, 16> OptionalMethods;
5007330f729Sjoerg     for (const auto *I : Methods)
5017330f729Sjoerg       if (I->isOptional())
5027330f729Sjoerg         OptionalMethods.push_back(I);
5037330f729Sjoerg       else
5047330f729Sjoerg         RequiredMethods.push_back(I);
5057330f729Sjoerg     Required = GenerateProtocolMethodList(RequiredMethods);
5067330f729Sjoerg     Optional = GenerateProtocolMethodList(OptionalMethods);
5077330f729Sjoerg   }
5087330f729Sjoerg 
5097330f729Sjoerg   /// Returns a selector with the specified type encoding.  An empty string is
5107330f729Sjoerg   /// used to return an untyped selector (with the types field set to NULL).
5117330f729Sjoerg   virtual llvm::Value *GetTypedSelector(CodeGenFunction &CGF, Selector Sel,
5127330f729Sjoerg                                         const std::string &TypeEncoding);
5137330f729Sjoerg 
5147330f729Sjoerg   /// Returns the name of ivar offset variables.  In the GNUstep v1 ABI, this
5157330f729Sjoerg   /// contains the class and ivar names, in the v2 ABI this contains the type
5167330f729Sjoerg   /// encoding as well.
GetIVarOffsetVariableName(const ObjCInterfaceDecl * ID,const ObjCIvarDecl * Ivar)5177330f729Sjoerg   virtual std::string GetIVarOffsetVariableName(const ObjCInterfaceDecl *ID,
5187330f729Sjoerg                                                 const ObjCIvarDecl *Ivar) {
5197330f729Sjoerg     const std::string Name = "__objc_ivar_offset_" + ID->getNameAsString()
5207330f729Sjoerg       + '.' + Ivar->getNameAsString();
5217330f729Sjoerg     return Name;
5227330f729Sjoerg   }
5237330f729Sjoerg   /// Returns the variable used to store the offset of an instance variable.
5247330f729Sjoerg   llvm::GlobalVariable *ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
5257330f729Sjoerg       const ObjCIvarDecl *Ivar);
5267330f729Sjoerg   /// Emits a reference to a class.  This allows the linker to object if there
5277330f729Sjoerg   /// is no class of the matching name.
5287330f729Sjoerg   void EmitClassRef(const std::string &className);
5297330f729Sjoerg 
5307330f729Sjoerg   /// Emits a pointer to the named class
5317330f729Sjoerg   virtual llvm::Value *GetClassNamed(CodeGenFunction &CGF,
5327330f729Sjoerg                                      const std::string &Name, bool isWeak);
5337330f729Sjoerg 
5347330f729Sjoerg   /// Looks up the method for sending a message to the specified object.  This
5357330f729Sjoerg   /// mechanism differs between the GCC and GNU runtimes, so this method must be
5367330f729Sjoerg   /// overridden in subclasses.
5377330f729Sjoerg   virtual llvm::Value *LookupIMP(CodeGenFunction &CGF,
5387330f729Sjoerg                                  llvm::Value *&Receiver,
5397330f729Sjoerg                                  llvm::Value *cmd,
5407330f729Sjoerg                                  llvm::MDNode *node,
5417330f729Sjoerg                                  MessageSendInfo &MSI) = 0;
5427330f729Sjoerg 
5437330f729Sjoerg   /// Looks up the method for sending a message to a superclass.  This
5447330f729Sjoerg   /// mechanism differs between the GCC and GNU runtimes, so this method must
5457330f729Sjoerg   /// be overridden in subclasses.
5467330f729Sjoerg   virtual llvm::Value *LookupIMPSuper(CodeGenFunction &CGF,
5477330f729Sjoerg                                       Address ObjCSuper,
5487330f729Sjoerg                                       llvm::Value *cmd,
5497330f729Sjoerg                                       MessageSendInfo &MSI) = 0;
5507330f729Sjoerg 
5517330f729Sjoerg   /// Libobjc2 uses a bitfield representation where small(ish) bitfields are
5527330f729Sjoerg   /// stored in a 64-bit value with the low bit set to 1 and the remaining 63
5537330f729Sjoerg   /// bits set to their values, LSB first, while larger ones are stored in a
5547330f729Sjoerg   /// structure of this / form:
5557330f729Sjoerg   ///
5567330f729Sjoerg   /// struct { int32_t length; int32_t values[length]; };
5577330f729Sjoerg   ///
5587330f729Sjoerg   /// The values in the array are stored in host-endian format, with the least
5597330f729Sjoerg   /// significant bit being assumed to come first in the bitfield.  Therefore,
5607330f729Sjoerg   /// a bitfield with the 64th bit set will be (int64_t)&{ 2, [0, 1<<31] },
5617330f729Sjoerg   /// while a bitfield / with the 63rd bit set will be 1<<64.
5627330f729Sjoerg   llvm::Constant *MakeBitField(ArrayRef<bool> bits);
5637330f729Sjoerg 
5647330f729Sjoerg public:
5657330f729Sjoerg   CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion,
5667330f729Sjoerg       unsigned protocolClassVersion, unsigned classABI=1);
5677330f729Sjoerg 
5687330f729Sjoerg   ConstantAddress GenerateConstantString(const StringLiteral *) override;
5697330f729Sjoerg 
5707330f729Sjoerg   RValue
5717330f729Sjoerg   GenerateMessageSend(CodeGenFunction &CGF, ReturnValueSlot Return,
5727330f729Sjoerg                       QualType ResultType, Selector Sel,
5737330f729Sjoerg                       llvm::Value *Receiver, const CallArgList &CallArgs,
5747330f729Sjoerg                       const ObjCInterfaceDecl *Class,
5757330f729Sjoerg                       const ObjCMethodDecl *Method) override;
5767330f729Sjoerg   RValue
5777330f729Sjoerg   GenerateMessageSendSuper(CodeGenFunction &CGF, ReturnValueSlot Return,
5787330f729Sjoerg                            QualType ResultType, Selector Sel,
5797330f729Sjoerg                            const ObjCInterfaceDecl *Class,
5807330f729Sjoerg                            bool isCategoryImpl, llvm::Value *Receiver,
5817330f729Sjoerg                            bool IsClassMessage, const CallArgList &CallArgs,
5827330f729Sjoerg                            const ObjCMethodDecl *Method) override;
5837330f729Sjoerg   llvm::Value *GetClass(CodeGenFunction &CGF,
5847330f729Sjoerg                         const ObjCInterfaceDecl *OID) override;
5857330f729Sjoerg   llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) override;
5867330f729Sjoerg   Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override;
5877330f729Sjoerg   llvm::Value *GetSelector(CodeGenFunction &CGF,
5887330f729Sjoerg                            const ObjCMethodDecl *Method) override;
GetConstantSelector(Selector Sel,const std::string & TypeEncoding)5897330f729Sjoerg   virtual llvm::Constant *GetConstantSelector(Selector Sel,
5907330f729Sjoerg                                               const std::string &TypeEncoding) {
5917330f729Sjoerg     llvm_unreachable("Runtime unable to generate constant selector");
5927330f729Sjoerg   }
GetConstantSelector(const ObjCMethodDecl * M)5937330f729Sjoerg   llvm::Constant *GetConstantSelector(const ObjCMethodDecl *M) {
5947330f729Sjoerg     return GetConstantSelector(M->getSelector(),
5957330f729Sjoerg         CGM.getContext().getObjCEncodingForMethodDecl(M));
5967330f729Sjoerg   }
5977330f729Sjoerg   llvm::Constant *GetEHType(QualType T) override;
5987330f729Sjoerg 
5997330f729Sjoerg   llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
6007330f729Sjoerg                                  const ObjCContainerDecl *CD) override;
601*e038c9c4Sjoerg   void GenerateDirectMethodPrologue(CodeGenFunction &CGF, llvm::Function *Fn,
602*e038c9c4Sjoerg                                     const ObjCMethodDecl *OMD,
603*e038c9c4Sjoerg                                     const ObjCContainerDecl *CD) override;
6047330f729Sjoerg   void GenerateCategory(const ObjCCategoryImplDecl *CMD) override;
6057330f729Sjoerg   void GenerateClass(const ObjCImplementationDecl *ClassDecl) override;
6067330f729Sjoerg   void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) override;
6077330f729Sjoerg   llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
6087330f729Sjoerg                                    const ObjCProtocolDecl *PD) override;
6097330f729Sjoerg   void GenerateProtocol(const ObjCProtocolDecl *PD) override;
610*e038c9c4Sjoerg 
611*e038c9c4Sjoerg   virtual llvm::Constant *GenerateProtocolRef(const ObjCProtocolDecl *PD);
612*e038c9c4Sjoerg 
GetOrEmitProtocol(const ObjCProtocolDecl * PD)613*e038c9c4Sjoerg   llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD) override {
614*e038c9c4Sjoerg     return GenerateProtocolRef(PD);
615*e038c9c4Sjoerg   }
616*e038c9c4Sjoerg 
6177330f729Sjoerg   llvm::Function *ModuleInitFunction() override;
6187330f729Sjoerg   llvm::FunctionCallee GetPropertyGetFunction() override;
6197330f729Sjoerg   llvm::FunctionCallee GetPropertySetFunction() override;
6207330f729Sjoerg   llvm::FunctionCallee GetOptimizedPropertySetFunction(bool atomic,
6217330f729Sjoerg                                                        bool copy) override;
6227330f729Sjoerg   llvm::FunctionCallee GetSetStructFunction() override;
6237330f729Sjoerg   llvm::FunctionCallee GetGetStructFunction() override;
6247330f729Sjoerg   llvm::FunctionCallee GetCppAtomicObjectGetFunction() override;
6257330f729Sjoerg   llvm::FunctionCallee GetCppAtomicObjectSetFunction() override;
6267330f729Sjoerg   llvm::FunctionCallee EnumerationMutationFunction() override;
6277330f729Sjoerg 
6287330f729Sjoerg   void EmitTryStmt(CodeGenFunction &CGF,
6297330f729Sjoerg                    const ObjCAtTryStmt &S) override;
6307330f729Sjoerg   void EmitSynchronizedStmt(CodeGenFunction &CGF,
6317330f729Sjoerg                             const ObjCAtSynchronizedStmt &S) override;
6327330f729Sjoerg   void EmitThrowStmt(CodeGenFunction &CGF,
6337330f729Sjoerg                      const ObjCAtThrowStmt &S,
6347330f729Sjoerg                      bool ClearInsertionPoint=true) override;
6357330f729Sjoerg   llvm::Value * EmitObjCWeakRead(CodeGenFunction &CGF,
6367330f729Sjoerg                                  Address AddrWeakObj) override;
6377330f729Sjoerg   void EmitObjCWeakAssign(CodeGenFunction &CGF,
6387330f729Sjoerg                           llvm::Value *src, Address dst) override;
6397330f729Sjoerg   void EmitObjCGlobalAssign(CodeGenFunction &CGF,
6407330f729Sjoerg                             llvm::Value *src, Address dest,
6417330f729Sjoerg                             bool threadlocal=false) override;
6427330f729Sjoerg   void EmitObjCIvarAssign(CodeGenFunction &CGF, llvm::Value *src,
6437330f729Sjoerg                           Address dest, llvm::Value *ivarOffset) override;
6447330f729Sjoerg   void EmitObjCStrongCastAssign(CodeGenFunction &CGF,
6457330f729Sjoerg                                 llvm::Value *src, Address dest) override;
6467330f729Sjoerg   void EmitGCMemmoveCollectable(CodeGenFunction &CGF, Address DestPtr,
6477330f729Sjoerg                                 Address SrcPtr,
6487330f729Sjoerg                                 llvm::Value *Size) override;
6497330f729Sjoerg   LValue EmitObjCValueForIvar(CodeGenFunction &CGF, QualType ObjectTy,
6507330f729Sjoerg                               llvm::Value *BaseValue, const ObjCIvarDecl *Ivar,
6517330f729Sjoerg                               unsigned CVRQualifiers) override;
6527330f729Sjoerg   llvm::Value *EmitIvarOffset(CodeGenFunction &CGF,
6537330f729Sjoerg                               const ObjCInterfaceDecl *Interface,
6547330f729Sjoerg                               const ObjCIvarDecl *Ivar) override;
6557330f729Sjoerg   llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) override;
BuildGCBlockLayout(CodeGenModule & CGM,const CGBlockInfo & blockInfo)6567330f729Sjoerg   llvm::Constant *BuildGCBlockLayout(CodeGenModule &CGM,
6577330f729Sjoerg                                      const CGBlockInfo &blockInfo) override {
6587330f729Sjoerg     return NULLPtr;
6597330f729Sjoerg   }
BuildRCBlockLayout(CodeGenModule & CGM,const CGBlockInfo & blockInfo)6607330f729Sjoerg   llvm::Constant *BuildRCBlockLayout(CodeGenModule &CGM,
6617330f729Sjoerg                                      const CGBlockInfo &blockInfo) override {
6627330f729Sjoerg     return NULLPtr;
6637330f729Sjoerg   }
6647330f729Sjoerg 
BuildByrefLayout(CodeGenModule & CGM,QualType T)6657330f729Sjoerg   llvm::Constant *BuildByrefLayout(CodeGenModule &CGM, QualType T) override {
6667330f729Sjoerg     return NULLPtr;
6677330f729Sjoerg   }
6687330f729Sjoerg };
6697330f729Sjoerg 
6707330f729Sjoerg /// Class representing the legacy GCC Objective-C ABI.  This is the default when
6717330f729Sjoerg /// -fobjc-nonfragile-abi is not specified.
6727330f729Sjoerg ///
6737330f729Sjoerg /// The GCC ABI target actually generates code that is approximately compatible
6747330f729Sjoerg /// with the new GNUstep runtime ABI, but refrains from using any features that
6757330f729Sjoerg /// would not work with the GCC runtime.  For example, clang always generates
6767330f729Sjoerg /// the extended form of the class structure, and the extra fields are simply
6777330f729Sjoerg /// ignored by GCC libobjc.
6787330f729Sjoerg class CGObjCGCC : public CGObjCGNU {
6797330f729Sjoerg   /// The GCC ABI message lookup function.  Returns an IMP pointing to the
6807330f729Sjoerg   /// method implementation for this message.
6817330f729Sjoerg   LazyRuntimeFunction MsgLookupFn;
6827330f729Sjoerg   /// The GCC ABI superclass message lookup function.  Takes a pointer to a
6837330f729Sjoerg   /// structure describing the receiver and the class, and a selector as
6847330f729Sjoerg   /// arguments.  Returns the IMP for the corresponding method.
6857330f729Sjoerg   LazyRuntimeFunction MsgLookupSuperFn;
6867330f729Sjoerg 
6877330f729Sjoerg protected:
LookupIMP(CodeGenFunction & CGF,llvm::Value * & Receiver,llvm::Value * cmd,llvm::MDNode * node,MessageSendInfo & MSI)6887330f729Sjoerg   llvm::Value *LookupIMP(CodeGenFunction &CGF, llvm::Value *&Receiver,
6897330f729Sjoerg                          llvm::Value *cmd, llvm::MDNode *node,
6907330f729Sjoerg                          MessageSendInfo &MSI) override {
6917330f729Sjoerg     CGBuilderTy &Builder = CGF.Builder;
6927330f729Sjoerg     llvm::Value *args[] = {
6937330f729Sjoerg             EnforceType(Builder, Receiver, IdTy),
6947330f729Sjoerg             EnforceType(Builder, cmd, SelectorTy) };
6957330f729Sjoerg     llvm::CallBase *imp = CGF.EmitRuntimeCallOrInvoke(MsgLookupFn, args);
6967330f729Sjoerg     imp->setMetadata(msgSendMDKind, node);
6977330f729Sjoerg     return imp;
6987330f729Sjoerg   }
6997330f729Sjoerg 
LookupIMPSuper(CodeGenFunction & CGF,Address ObjCSuper,llvm::Value * cmd,MessageSendInfo & MSI)7007330f729Sjoerg   llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper,
7017330f729Sjoerg                               llvm::Value *cmd, MessageSendInfo &MSI) override {
7027330f729Sjoerg     CGBuilderTy &Builder = CGF.Builder;
7037330f729Sjoerg     llvm::Value *lookupArgs[] = {EnforceType(Builder, ObjCSuper,
7047330f729Sjoerg         PtrToObjCSuperTy).getPointer(), cmd};
7057330f729Sjoerg     return CGF.EmitNounwindRuntimeCall(MsgLookupSuperFn, lookupArgs);
7067330f729Sjoerg   }
7077330f729Sjoerg 
7087330f729Sjoerg public:
CGObjCGCC(CodeGenModule & Mod)7097330f729Sjoerg   CGObjCGCC(CodeGenModule &Mod) : CGObjCGNU(Mod, 8, 2) {
7107330f729Sjoerg     // IMP objc_msg_lookup(id, SEL);
7117330f729Sjoerg     MsgLookupFn.init(&CGM, "objc_msg_lookup", IMPTy, IdTy, SelectorTy);
7127330f729Sjoerg     // IMP objc_msg_lookup_super(struct objc_super*, SEL);
7137330f729Sjoerg     MsgLookupSuperFn.init(&CGM, "objc_msg_lookup_super", IMPTy,
7147330f729Sjoerg                           PtrToObjCSuperTy, SelectorTy);
7157330f729Sjoerg   }
7167330f729Sjoerg };
7177330f729Sjoerg 
7187330f729Sjoerg /// Class used when targeting the new GNUstep runtime ABI.
7197330f729Sjoerg class CGObjCGNUstep : public CGObjCGNU {
7207330f729Sjoerg     /// The slot lookup function.  Returns a pointer to a cacheable structure
7217330f729Sjoerg     /// that contains (among other things) the IMP.
7227330f729Sjoerg     LazyRuntimeFunction SlotLookupFn;
7237330f729Sjoerg     /// The GNUstep ABI superclass message lookup function.  Takes a pointer to
7247330f729Sjoerg     /// a structure describing the receiver and the class, and a selector as
7257330f729Sjoerg     /// arguments.  Returns the slot for the corresponding method.  Superclass
7267330f729Sjoerg     /// message lookup rarely changes, so this is a good caching opportunity.
7277330f729Sjoerg     LazyRuntimeFunction SlotLookupSuperFn;
7287330f729Sjoerg     /// Specialised function for setting atomic retain properties
7297330f729Sjoerg     LazyRuntimeFunction SetPropertyAtomic;
7307330f729Sjoerg     /// Specialised function for setting atomic copy properties
7317330f729Sjoerg     LazyRuntimeFunction SetPropertyAtomicCopy;
7327330f729Sjoerg     /// Specialised function for setting nonatomic retain properties
7337330f729Sjoerg     LazyRuntimeFunction SetPropertyNonAtomic;
7347330f729Sjoerg     /// Specialised function for setting nonatomic copy properties
7357330f729Sjoerg     LazyRuntimeFunction SetPropertyNonAtomicCopy;
7367330f729Sjoerg     /// Function to perform atomic copies of C++ objects with nontrivial copy
7377330f729Sjoerg     /// constructors from Objective-C ivars.
7387330f729Sjoerg     LazyRuntimeFunction CxxAtomicObjectGetFn;
7397330f729Sjoerg     /// Function to perform atomic copies of C++ objects with nontrivial copy
7407330f729Sjoerg     /// constructors to Objective-C ivars.
7417330f729Sjoerg     LazyRuntimeFunction CxxAtomicObjectSetFn;
7427330f729Sjoerg     /// Type of an slot structure pointer.  This is returned by the various
7437330f729Sjoerg     /// lookup functions.
7447330f729Sjoerg     llvm::Type *SlotTy;
7457330f729Sjoerg 
7467330f729Sjoerg   public:
7477330f729Sjoerg     llvm::Constant *GetEHType(QualType T) override;
7487330f729Sjoerg 
7497330f729Sjoerg   protected:
LookupIMP(CodeGenFunction & CGF,llvm::Value * & Receiver,llvm::Value * cmd,llvm::MDNode * node,MessageSendInfo & MSI)7507330f729Sjoerg     llvm::Value *LookupIMP(CodeGenFunction &CGF, llvm::Value *&Receiver,
7517330f729Sjoerg                            llvm::Value *cmd, llvm::MDNode *node,
7527330f729Sjoerg                            MessageSendInfo &MSI) override {
7537330f729Sjoerg       CGBuilderTy &Builder = CGF.Builder;
7547330f729Sjoerg       llvm::FunctionCallee LookupFn = SlotLookupFn;
7557330f729Sjoerg 
7567330f729Sjoerg       // Store the receiver on the stack so that we can reload it later
7577330f729Sjoerg       Address ReceiverPtr =
7587330f729Sjoerg         CGF.CreateTempAlloca(Receiver->getType(), CGF.getPointerAlign());
7597330f729Sjoerg       Builder.CreateStore(Receiver, ReceiverPtr);
7607330f729Sjoerg 
7617330f729Sjoerg       llvm::Value *self;
7627330f729Sjoerg 
7637330f729Sjoerg       if (isa<ObjCMethodDecl>(CGF.CurCodeDecl)) {
7647330f729Sjoerg         self = CGF.LoadObjCSelf();
7657330f729Sjoerg       } else {
7667330f729Sjoerg         self = llvm::ConstantPointerNull::get(IdTy);
7677330f729Sjoerg       }
7687330f729Sjoerg 
7697330f729Sjoerg       // The lookup function is guaranteed not to capture the receiver pointer.
7707330f729Sjoerg       if (auto *LookupFn2 = dyn_cast<llvm::Function>(LookupFn.getCallee()))
7717330f729Sjoerg         LookupFn2->addParamAttr(0, llvm::Attribute::NoCapture);
7727330f729Sjoerg 
7737330f729Sjoerg       llvm::Value *args[] = {
7747330f729Sjoerg               EnforceType(Builder, ReceiverPtr.getPointer(), PtrToIdTy),
7757330f729Sjoerg               EnforceType(Builder, cmd, SelectorTy),
7767330f729Sjoerg               EnforceType(Builder, self, IdTy) };
7777330f729Sjoerg       llvm::CallBase *slot = CGF.EmitRuntimeCallOrInvoke(LookupFn, args);
7787330f729Sjoerg       slot->setOnlyReadsMemory();
7797330f729Sjoerg       slot->setMetadata(msgSendMDKind, node);
7807330f729Sjoerg 
7817330f729Sjoerg       // Load the imp from the slot
7827330f729Sjoerg       llvm::Value *imp = Builder.CreateAlignedLoad(
783*e038c9c4Sjoerg           IMPTy, Builder.CreateStructGEP(nullptr, slot, 4),
784*e038c9c4Sjoerg           CGF.getPointerAlign());
7857330f729Sjoerg 
7867330f729Sjoerg       // The lookup function may have changed the receiver, so make sure we use
7877330f729Sjoerg       // the new one.
7887330f729Sjoerg       Receiver = Builder.CreateLoad(ReceiverPtr, true);
7897330f729Sjoerg       return imp;
7907330f729Sjoerg     }
7917330f729Sjoerg 
LookupIMPSuper(CodeGenFunction & CGF,Address ObjCSuper,llvm::Value * cmd,MessageSendInfo & MSI)7927330f729Sjoerg     llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper,
7937330f729Sjoerg                                 llvm::Value *cmd,
7947330f729Sjoerg                                 MessageSendInfo &MSI) override {
7957330f729Sjoerg       CGBuilderTy &Builder = CGF.Builder;
7967330f729Sjoerg       llvm::Value *lookupArgs[] = {ObjCSuper.getPointer(), cmd};
7977330f729Sjoerg 
7987330f729Sjoerg       llvm::CallInst *slot =
7997330f729Sjoerg         CGF.EmitNounwindRuntimeCall(SlotLookupSuperFn, lookupArgs);
8007330f729Sjoerg       slot->setOnlyReadsMemory();
8017330f729Sjoerg 
802*e038c9c4Sjoerg       return Builder.CreateAlignedLoad(
803*e038c9c4Sjoerg           IMPTy, Builder.CreateStructGEP(nullptr, slot, 4),
8047330f729Sjoerg           CGF.getPointerAlign());
8057330f729Sjoerg     }
8067330f729Sjoerg 
8077330f729Sjoerg   public:
CGObjCGNUstep(CodeGenModule & Mod)8087330f729Sjoerg     CGObjCGNUstep(CodeGenModule &Mod) : CGObjCGNUstep(Mod, 9, 3, 1) {}
CGObjCGNUstep(CodeGenModule & Mod,unsigned ABI,unsigned ProtocolABI,unsigned ClassABI)8097330f729Sjoerg     CGObjCGNUstep(CodeGenModule &Mod, unsigned ABI, unsigned ProtocolABI,
8107330f729Sjoerg         unsigned ClassABI) :
8117330f729Sjoerg       CGObjCGNU(Mod, ABI, ProtocolABI, ClassABI) {
8127330f729Sjoerg       const ObjCRuntime &R = CGM.getLangOpts().ObjCRuntime;
8137330f729Sjoerg 
8147330f729Sjoerg       llvm::StructType *SlotStructTy =
8157330f729Sjoerg           llvm::StructType::get(PtrTy, PtrTy, PtrTy, IntTy, IMPTy);
8167330f729Sjoerg       SlotTy = llvm::PointerType::getUnqual(SlotStructTy);
8177330f729Sjoerg       // Slot_t objc_msg_lookup_sender(id *receiver, SEL selector, id sender);
8187330f729Sjoerg       SlotLookupFn.init(&CGM, "objc_msg_lookup_sender", SlotTy, PtrToIdTy,
8197330f729Sjoerg                         SelectorTy, IdTy);
8207330f729Sjoerg       // Slot_t objc_slot_lookup_super(struct objc_super*, SEL);
8217330f729Sjoerg       SlotLookupSuperFn.init(&CGM, "objc_slot_lookup_super", SlotTy,
8227330f729Sjoerg                              PtrToObjCSuperTy, SelectorTy);
8237330f729Sjoerg       // If we're in ObjC++ mode, then we want to make
8247330f729Sjoerg       if (usesSEHExceptions) {
8257330f729Sjoerg           llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
8267330f729Sjoerg           // void objc_exception_rethrow(void)
8277330f729Sjoerg           ExceptionReThrowFn.init(&CGM, "objc_exception_rethrow", VoidTy);
8287330f729Sjoerg       } else if (CGM.getLangOpts().CPlusPlus) {
8297330f729Sjoerg         llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
8307330f729Sjoerg         // void *__cxa_begin_catch(void *e)
8317330f729Sjoerg         EnterCatchFn.init(&CGM, "__cxa_begin_catch", PtrTy, PtrTy);
8327330f729Sjoerg         // void __cxa_end_catch(void)
8337330f729Sjoerg         ExitCatchFn.init(&CGM, "__cxa_end_catch", VoidTy);
8347330f729Sjoerg         // void _Unwind_Resume_or_Rethrow(void*)
8357330f729Sjoerg         ExceptionReThrowFn.init(&CGM, "_Unwind_Resume_or_Rethrow", VoidTy,
8367330f729Sjoerg                                 PtrTy);
8377330f729Sjoerg       } else if (R.getVersion() >= VersionTuple(1, 7)) {
8387330f729Sjoerg         llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
8397330f729Sjoerg         // id objc_begin_catch(void *e)
8407330f729Sjoerg         EnterCatchFn.init(&CGM, "objc_begin_catch", IdTy, PtrTy);
8417330f729Sjoerg         // void objc_end_catch(void)
8427330f729Sjoerg         ExitCatchFn.init(&CGM, "objc_end_catch", VoidTy);
8437330f729Sjoerg         // void _Unwind_Resume_or_Rethrow(void*)
8447330f729Sjoerg         ExceptionReThrowFn.init(&CGM, "objc_exception_rethrow", VoidTy, PtrTy);
8457330f729Sjoerg       }
8467330f729Sjoerg       llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
8477330f729Sjoerg       SetPropertyAtomic.init(&CGM, "objc_setProperty_atomic", VoidTy, IdTy,
8487330f729Sjoerg                              SelectorTy, IdTy, PtrDiffTy);
8497330f729Sjoerg       SetPropertyAtomicCopy.init(&CGM, "objc_setProperty_atomic_copy", VoidTy,
8507330f729Sjoerg                                  IdTy, SelectorTy, IdTy, PtrDiffTy);
8517330f729Sjoerg       SetPropertyNonAtomic.init(&CGM, "objc_setProperty_nonatomic", VoidTy,
8527330f729Sjoerg                                 IdTy, SelectorTy, IdTy, PtrDiffTy);
8537330f729Sjoerg       SetPropertyNonAtomicCopy.init(&CGM, "objc_setProperty_nonatomic_copy",
8547330f729Sjoerg                                     VoidTy, IdTy, SelectorTy, IdTy, PtrDiffTy);
8557330f729Sjoerg       // void objc_setCppObjectAtomic(void *dest, const void *src, void
8567330f729Sjoerg       // *helper);
8577330f729Sjoerg       CxxAtomicObjectSetFn.init(&CGM, "objc_setCppObjectAtomic", VoidTy, PtrTy,
8587330f729Sjoerg                                 PtrTy, PtrTy);
8597330f729Sjoerg       // void objc_getCppObjectAtomic(void *dest, const void *src, void
8607330f729Sjoerg       // *helper);
8617330f729Sjoerg       CxxAtomicObjectGetFn.init(&CGM, "objc_getCppObjectAtomic", VoidTy, PtrTy,
8627330f729Sjoerg                                 PtrTy, PtrTy);
8637330f729Sjoerg     }
8647330f729Sjoerg 
GetCppAtomicObjectGetFunction()8657330f729Sjoerg     llvm::FunctionCallee GetCppAtomicObjectGetFunction() override {
8667330f729Sjoerg       // The optimised functions were added in version 1.7 of the GNUstep
8677330f729Sjoerg       // runtime.
8687330f729Sjoerg       assert (CGM.getLangOpts().ObjCRuntime.getVersion() >=
8697330f729Sjoerg           VersionTuple(1, 7));
8707330f729Sjoerg       return CxxAtomicObjectGetFn;
8717330f729Sjoerg     }
8727330f729Sjoerg 
GetCppAtomicObjectSetFunction()8737330f729Sjoerg     llvm::FunctionCallee GetCppAtomicObjectSetFunction() override {
8747330f729Sjoerg       // The optimised functions were added in version 1.7 of the GNUstep
8757330f729Sjoerg       // runtime.
8767330f729Sjoerg       assert (CGM.getLangOpts().ObjCRuntime.getVersion() >=
8777330f729Sjoerg           VersionTuple(1, 7));
8787330f729Sjoerg       return CxxAtomicObjectSetFn;
8797330f729Sjoerg     }
8807330f729Sjoerg 
GetOptimizedPropertySetFunction(bool atomic,bool copy)8817330f729Sjoerg     llvm::FunctionCallee GetOptimizedPropertySetFunction(bool atomic,
8827330f729Sjoerg                                                          bool copy) override {
8837330f729Sjoerg       // The optimised property functions omit the GC check, and so are not
8847330f729Sjoerg       // safe to use in GC mode.  The standard functions are fast in GC mode,
8857330f729Sjoerg       // so there is less advantage in using them.
8867330f729Sjoerg       assert ((CGM.getLangOpts().getGC() == LangOptions::NonGC));
8877330f729Sjoerg       // The optimised functions were added in version 1.7 of the GNUstep
8887330f729Sjoerg       // runtime.
8897330f729Sjoerg       assert (CGM.getLangOpts().ObjCRuntime.getVersion() >=
8907330f729Sjoerg           VersionTuple(1, 7));
8917330f729Sjoerg 
8927330f729Sjoerg       if (atomic) {
8937330f729Sjoerg         if (copy) return SetPropertyAtomicCopy;
8947330f729Sjoerg         return SetPropertyAtomic;
8957330f729Sjoerg       }
8967330f729Sjoerg 
8977330f729Sjoerg       return copy ? SetPropertyNonAtomicCopy : SetPropertyNonAtomic;
8987330f729Sjoerg     }
8997330f729Sjoerg };
9007330f729Sjoerg 
9017330f729Sjoerg /// GNUstep Objective-C ABI version 2 implementation.
9027330f729Sjoerg /// This is the ABI that provides a clean break with the legacy GCC ABI and
9037330f729Sjoerg /// cleans up a number of things that were added to work around 1980s linkers.
9047330f729Sjoerg class CGObjCGNUstep2 : public CGObjCGNUstep {
9057330f729Sjoerg   enum SectionKind
9067330f729Sjoerg   {
9077330f729Sjoerg     SelectorSection = 0,
9087330f729Sjoerg     ClassSection,
9097330f729Sjoerg     ClassReferenceSection,
9107330f729Sjoerg     CategorySection,
9117330f729Sjoerg     ProtocolSection,
9127330f729Sjoerg     ProtocolReferenceSection,
9137330f729Sjoerg     ClassAliasSection,
9147330f729Sjoerg     ConstantStringSection
9157330f729Sjoerg   };
9167330f729Sjoerg   static const char *const SectionsBaseNames[8];
9177330f729Sjoerg   static const char *const PECOFFSectionsBaseNames[8];
9187330f729Sjoerg   template<SectionKind K>
sectionName()9197330f729Sjoerg   std::string sectionName() {
9207330f729Sjoerg     if (CGM.getTriple().isOSBinFormatCOFF()) {
9217330f729Sjoerg       std::string name(PECOFFSectionsBaseNames[K]);
9227330f729Sjoerg       name += "$m";
9237330f729Sjoerg       return name;
9247330f729Sjoerg     }
9257330f729Sjoerg     return SectionsBaseNames[K];
9267330f729Sjoerg   }
9277330f729Sjoerg   /// The GCC ABI superclass message lookup function.  Takes a pointer to a
9287330f729Sjoerg   /// structure describing the receiver and the class, and a selector as
9297330f729Sjoerg   /// arguments.  Returns the IMP for the corresponding method.
9307330f729Sjoerg   LazyRuntimeFunction MsgLookupSuperFn;
9317330f729Sjoerg   /// A flag indicating if we've emitted at least one protocol.
9327330f729Sjoerg   /// If we haven't, then we need to emit an empty protocol, to ensure that the
9337330f729Sjoerg   /// __start__objc_protocols and __stop__objc_protocols sections exist.
9347330f729Sjoerg   bool EmittedProtocol = false;
9357330f729Sjoerg   /// A flag indicating if we've emitted at least one protocol reference.
9367330f729Sjoerg   /// If we haven't, then we need to emit an empty protocol, to ensure that the
9377330f729Sjoerg   /// __start__objc_protocol_refs and __stop__objc_protocol_refs sections
9387330f729Sjoerg   /// exist.
9397330f729Sjoerg   bool EmittedProtocolRef = false;
9407330f729Sjoerg   /// A flag indicating if we've emitted at least one class.
9417330f729Sjoerg   /// If we haven't, then we need to emit an empty protocol, to ensure that the
9427330f729Sjoerg   /// __start__objc_classes and __stop__objc_classes sections / exist.
9437330f729Sjoerg   bool EmittedClass = false;
9447330f729Sjoerg   /// Generate the name of a symbol for a reference to a class.  Accesses to
9457330f729Sjoerg   /// classes should be indirected via this.
9467330f729Sjoerg 
9477330f729Sjoerg   typedef std::pair<std::string, std::pair<llvm::Constant*, int>> EarlyInitPair;
9487330f729Sjoerg   std::vector<EarlyInitPair> EarlyInitList;
9497330f729Sjoerg 
SymbolForClassRef(StringRef Name,bool isWeak)9507330f729Sjoerg   std::string SymbolForClassRef(StringRef Name, bool isWeak) {
9517330f729Sjoerg     if (isWeak)
9527330f729Sjoerg       return (ManglePublicSymbol("OBJC_WEAK_REF_CLASS_") + Name).str();
9537330f729Sjoerg     else
9547330f729Sjoerg       return (ManglePublicSymbol("OBJC_REF_CLASS_") + Name).str();
9557330f729Sjoerg   }
9567330f729Sjoerg   /// Generate the name of a class symbol.
SymbolForClass(StringRef Name)9577330f729Sjoerg   std::string SymbolForClass(StringRef Name) {
9587330f729Sjoerg     return (ManglePublicSymbol("OBJC_CLASS_") + Name).str();
9597330f729Sjoerg   }
CallRuntimeFunction(CGBuilderTy & B,StringRef FunctionName,ArrayRef<llvm::Value * > Args)9607330f729Sjoerg   void CallRuntimeFunction(CGBuilderTy &B, StringRef FunctionName,
9617330f729Sjoerg       ArrayRef<llvm::Value*> Args) {
9627330f729Sjoerg     SmallVector<llvm::Type *,8> Types;
9637330f729Sjoerg     for (auto *Arg : Args)
9647330f729Sjoerg       Types.push_back(Arg->getType());
9657330f729Sjoerg     llvm::FunctionType *FT = llvm::FunctionType::get(B.getVoidTy(), Types,
9667330f729Sjoerg         false);
9677330f729Sjoerg     llvm::FunctionCallee Fn = CGM.CreateRuntimeFunction(FT, FunctionName);
9687330f729Sjoerg     B.CreateCall(Fn, Args);
9697330f729Sjoerg   }
9707330f729Sjoerg 
GenerateConstantString(const StringLiteral * SL)9717330f729Sjoerg   ConstantAddress GenerateConstantString(const StringLiteral *SL) override {
9727330f729Sjoerg 
9737330f729Sjoerg     auto Str = SL->getString();
9747330f729Sjoerg     CharUnits Align = CGM.getPointerAlign();
9757330f729Sjoerg 
9767330f729Sjoerg     // Look for an existing one
9777330f729Sjoerg     llvm::StringMap<llvm::Constant*>::iterator old = ObjCStrings.find(Str);
9787330f729Sjoerg     if (old != ObjCStrings.end())
9797330f729Sjoerg       return ConstantAddress(old->getValue(), Align);
9807330f729Sjoerg 
9817330f729Sjoerg     bool isNonASCII = SL->containsNonAscii();
9827330f729Sjoerg 
9837330f729Sjoerg     auto LiteralLength = SL->getLength();
9847330f729Sjoerg 
9857330f729Sjoerg     if ((CGM.getTarget().getPointerWidth(0) == 64) &&
9867330f729Sjoerg         (LiteralLength < 9) && !isNonASCII) {
9877330f729Sjoerg       // Tiny strings are only used on 64-bit platforms.  They store 8 7-bit
9887330f729Sjoerg       // ASCII characters in the high 56 bits, followed by a 4-bit length and a
9897330f729Sjoerg       // 3-bit tag (which is always 4).
9907330f729Sjoerg       uint64_t str = 0;
9917330f729Sjoerg       // Fill in the characters
9927330f729Sjoerg       for (unsigned i=0 ; i<LiteralLength ; i++)
9937330f729Sjoerg         str |= ((uint64_t)SL->getCodeUnit(i)) << ((64 - 4 - 3) - (i*7));
9947330f729Sjoerg       // Fill in the length
9957330f729Sjoerg       str |= LiteralLength << 3;
9967330f729Sjoerg       // Set the tag
9977330f729Sjoerg       str |= 4;
9987330f729Sjoerg       auto *ObjCStr = llvm::ConstantExpr::getIntToPtr(
9997330f729Sjoerg           llvm::ConstantInt::get(Int64Ty, str), IdTy);
10007330f729Sjoerg       ObjCStrings[Str] = ObjCStr;
10017330f729Sjoerg       return ConstantAddress(ObjCStr, Align);
10027330f729Sjoerg     }
10037330f729Sjoerg 
10047330f729Sjoerg     StringRef StringClass = CGM.getLangOpts().ObjCConstantStringClass;
10057330f729Sjoerg 
10067330f729Sjoerg     if (StringClass.empty()) StringClass = "NSConstantString";
10077330f729Sjoerg 
10087330f729Sjoerg     std::string Sym = SymbolForClass(StringClass);
10097330f729Sjoerg 
10107330f729Sjoerg     llvm::Constant *isa = TheModule.getNamedGlobal(Sym);
10117330f729Sjoerg 
10127330f729Sjoerg     if (!isa) {
10137330f729Sjoerg       isa = new llvm::GlobalVariable(TheModule, IdTy, /* isConstant */false,
10147330f729Sjoerg               llvm::GlobalValue::ExternalLinkage, nullptr, Sym);
10157330f729Sjoerg       if (CGM.getTriple().isOSBinFormatCOFF()) {
10167330f729Sjoerg         cast<llvm::GlobalValue>(isa)->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
10177330f729Sjoerg       }
10187330f729Sjoerg     } else if (isa->getType() != PtrToIdTy)
10197330f729Sjoerg       isa = llvm::ConstantExpr::getBitCast(isa, PtrToIdTy);
10207330f729Sjoerg 
10217330f729Sjoerg     //  struct
10227330f729Sjoerg     //  {
10237330f729Sjoerg     //    Class isa;
10247330f729Sjoerg     //    uint32_t flags;
10257330f729Sjoerg     //    uint32_t length; // Number of codepoints
10267330f729Sjoerg     //    uint32_t size; // Number of bytes
10277330f729Sjoerg     //    uint32_t hash;
10287330f729Sjoerg     //    const char *data;
10297330f729Sjoerg     //  };
10307330f729Sjoerg 
10317330f729Sjoerg     ConstantInitBuilder Builder(CGM);
10327330f729Sjoerg     auto Fields = Builder.beginStruct();
10337330f729Sjoerg     if (!CGM.getTriple().isOSBinFormatCOFF()) {
10347330f729Sjoerg       Fields.add(isa);
10357330f729Sjoerg     } else {
10367330f729Sjoerg       Fields.addNullPointer(PtrTy);
10377330f729Sjoerg     }
10387330f729Sjoerg     // For now, all non-ASCII strings are represented as UTF-16.  As such, the
10397330f729Sjoerg     // number of bytes is simply double the number of UTF-16 codepoints.  In
10407330f729Sjoerg     // ASCII strings, the number of bytes is equal to the number of non-ASCII
10417330f729Sjoerg     // codepoints.
10427330f729Sjoerg     if (isNonASCII) {
10437330f729Sjoerg       unsigned NumU8CodeUnits = Str.size();
10447330f729Sjoerg       // A UTF-16 representation of a unicode string contains at most the same
10457330f729Sjoerg       // number of code units as a UTF-8 representation.  Allocate that much
10467330f729Sjoerg       // space, plus one for the final null character.
10477330f729Sjoerg       SmallVector<llvm::UTF16, 128> ToBuf(NumU8CodeUnits + 1);
10487330f729Sjoerg       const llvm::UTF8 *FromPtr = (const llvm::UTF8 *)Str.data();
10497330f729Sjoerg       llvm::UTF16 *ToPtr = &ToBuf[0];
10507330f729Sjoerg       (void)llvm::ConvertUTF8toUTF16(&FromPtr, FromPtr + NumU8CodeUnits,
10517330f729Sjoerg           &ToPtr, ToPtr + NumU8CodeUnits, llvm::strictConversion);
10527330f729Sjoerg       uint32_t StringLength = ToPtr - &ToBuf[0];
10537330f729Sjoerg       // Add null terminator
10547330f729Sjoerg       *ToPtr = 0;
10557330f729Sjoerg       // Flags: 2 indicates UTF-16 encoding
10567330f729Sjoerg       Fields.addInt(Int32Ty, 2);
10577330f729Sjoerg       // Number of UTF-16 codepoints
10587330f729Sjoerg       Fields.addInt(Int32Ty, StringLength);
10597330f729Sjoerg       // Number of bytes
10607330f729Sjoerg       Fields.addInt(Int32Ty, StringLength * 2);
10617330f729Sjoerg       // Hash.  Not currently initialised by the compiler.
10627330f729Sjoerg       Fields.addInt(Int32Ty, 0);
10637330f729Sjoerg       // pointer to the data string.
10647330f729Sjoerg       auto Arr = llvm::makeArrayRef(&ToBuf[0], ToPtr+1);
10657330f729Sjoerg       auto *C = llvm::ConstantDataArray::get(VMContext, Arr);
10667330f729Sjoerg       auto *Buffer = new llvm::GlobalVariable(TheModule, C->getType(),
10677330f729Sjoerg           /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, C, ".str");
10687330f729Sjoerg       Buffer->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
10697330f729Sjoerg       Fields.add(Buffer);
10707330f729Sjoerg     } else {
10717330f729Sjoerg       // Flags: 0 indicates ASCII encoding
10727330f729Sjoerg       Fields.addInt(Int32Ty, 0);
10737330f729Sjoerg       // Number of UTF-16 codepoints, each ASCII byte is a UTF-16 codepoint
10747330f729Sjoerg       Fields.addInt(Int32Ty, Str.size());
10757330f729Sjoerg       // Number of bytes
10767330f729Sjoerg       Fields.addInt(Int32Ty, Str.size());
10777330f729Sjoerg       // Hash.  Not currently initialised by the compiler.
10787330f729Sjoerg       Fields.addInt(Int32Ty, 0);
10797330f729Sjoerg       // Data pointer
10807330f729Sjoerg       Fields.add(MakeConstantString(Str));
10817330f729Sjoerg     }
10827330f729Sjoerg     std::string StringName;
10837330f729Sjoerg     bool isNamed = !isNonASCII;
10847330f729Sjoerg     if (isNamed) {
10857330f729Sjoerg       StringName = ".objc_str_";
10867330f729Sjoerg       for (int i=0,e=Str.size() ; i<e ; ++i) {
10877330f729Sjoerg         unsigned char c = Str[i];
10887330f729Sjoerg         if (isalnum(c))
10897330f729Sjoerg           StringName += c;
10907330f729Sjoerg         else if (c == ' ')
10917330f729Sjoerg           StringName += '_';
10927330f729Sjoerg         else {
10937330f729Sjoerg           isNamed = false;
10947330f729Sjoerg           break;
10957330f729Sjoerg         }
10967330f729Sjoerg       }
10977330f729Sjoerg     }
10987330f729Sjoerg     auto *ObjCStrGV =
10997330f729Sjoerg       Fields.finishAndCreateGlobal(
11007330f729Sjoerg           isNamed ? StringRef(StringName) : ".objc_string",
11017330f729Sjoerg           Align, false, isNamed ? llvm::GlobalValue::LinkOnceODRLinkage
11027330f729Sjoerg                                 : llvm::GlobalValue::PrivateLinkage);
11037330f729Sjoerg     ObjCStrGV->setSection(sectionName<ConstantStringSection>());
11047330f729Sjoerg     if (isNamed) {
11057330f729Sjoerg       ObjCStrGV->setComdat(TheModule.getOrInsertComdat(StringName));
11067330f729Sjoerg       ObjCStrGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
11077330f729Sjoerg     }
11087330f729Sjoerg     if (CGM.getTriple().isOSBinFormatCOFF()) {
11097330f729Sjoerg       std::pair<llvm::Constant*, int> v{ObjCStrGV, 0};
11107330f729Sjoerg       EarlyInitList.emplace_back(Sym, v);
11117330f729Sjoerg     }
11127330f729Sjoerg     llvm::Constant *ObjCStr = llvm::ConstantExpr::getBitCast(ObjCStrGV, IdTy);
11137330f729Sjoerg     ObjCStrings[Str] = ObjCStr;
11147330f729Sjoerg     ConstantStrings.push_back(ObjCStr);
11157330f729Sjoerg     return ConstantAddress(ObjCStr, Align);
11167330f729Sjoerg   }
11177330f729Sjoerg 
PushProperty(ConstantArrayBuilder & PropertiesArray,const ObjCPropertyDecl * property,const Decl * OCD,bool isSynthesized=true,bool isDynamic=true)11187330f729Sjoerg   void PushProperty(ConstantArrayBuilder &PropertiesArray,
11197330f729Sjoerg             const ObjCPropertyDecl *property,
11207330f729Sjoerg             const Decl *OCD,
11217330f729Sjoerg             bool isSynthesized=true, bool
11227330f729Sjoerg             isDynamic=true) override {
11237330f729Sjoerg     // struct objc_property
11247330f729Sjoerg     // {
11257330f729Sjoerg     //   const char *name;
11267330f729Sjoerg     //   const char *attributes;
11277330f729Sjoerg     //   const char *type;
11287330f729Sjoerg     //   SEL getter;
11297330f729Sjoerg     //   SEL setter;
11307330f729Sjoerg     // };
11317330f729Sjoerg     auto Fields = PropertiesArray.beginStruct(PropertyMetadataTy);
11327330f729Sjoerg     ASTContext &Context = CGM.getContext();
11337330f729Sjoerg     Fields.add(MakeConstantString(property->getNameAsString()));
11347330f729Sjoerg     std::string TypeStr =
11357330f729Sjoerg       CGM.getContext().getObjCEncodingForPropertyDecl(property, OCD);
11367330f729Sjoerg     Fields.add(MakeConstantString(TypeStr));
11377330f729Sjoerg     std::string typeStr;
11387330f729Sjoerg     Context.getObjCEncodingForType(property->getType(), typeStr);
11397330f729Sjoerg     Fields.add(MakeConstantString(typeStr));
11407330f729Sjoerg     auto addPropertyMethod = [&](const ObjCMethodDecl *accessor) {
11417330f729Sjoerg       if (accessor) {
11427330f729Sjoerg         std::string TypeStr = Context.getObjCEncodingForMethodDecl(accessor);
11437330f729Sjoerg         Fields.add(GetConstantSelector(accessor->getSelector(), TypeStr));
11447330f729Sjoerg       } else {
11457330f729Sjoerg         Fields.add(NULLPtr);
11467330f729Sjoerg       }
11477330f729Sjoerg     };
11487330f729Sjoerg     addPropertyMethod(property->getGetterMethodDecl());
11497330f729Sjoerg     addPropertyMethod(property->getSetterMethodDecl());
11507330f729Sjoerg     Fields.finishAndAddTo(PropertiesArray);
11517330f729Sjoerg   }
11527330f729Sjoerg 
11537330f729Sjoerg   llvm::Constant *
GenerateProtocolMethodList(ArrayRef<const ObjCMethodDecl * > Methods)11547330f729Sjoerg   GenerateProtocolMethodList(ArrayRef<const ObjCMethodDecl*> Methods) override {
11557330f729Sjoerg     // struct objc_protocol_method_description
11567330f729Sjoerg     // {
11577330f729Sjoerg     //   SEL selector;
11587330f729Sjoerg     //   const char *types;
11597330f729Sjoerg     // };
11607330f729Sjoerg     llvm::StructType *ObjCMethodDescTy =
11617330f729Sjoerg       llvm::StructType::get(CGM.getLLVMContext(),
11627330f729Sjoerg           { PtrToInt8Ty, PtrToInt8Ty });
11637330f729Sjoerg     ASTContext &Context = CGM.getContext();
11647330f729Sjoerg     ConstantInitBuilder Builder(CGM);
11657330f729Sjoerg     // struct objc_protocol_method_description_list
11667330f729Sjoerg     // {
11677330f729Sjoerg     //   int count;
11687330f729Sjoerg     //   int size;
11697330f729Sjoerg     //   struct objc_protocol_method_description methods[];
11707330f729Sjoerg     // };
11717330f729Sjoerg     auto MethodList = Builder.beginStruct();
11727330f729Sjoerg     // int count;
11737330f729Sjoerg     MethodList.addInt(IntTy, Methods.size());
11747330f729Sjoerg     // int size; // sizeof(struct objc_method_description)
11757330f729Sjoerg     llvm::DataLayout td(&TheModule);
11767330f729Sjoerg     MethodList.addInt(IntTy, td.getTypeSizeInBits(ObjCMethodDescTy) /
11777330f729Sjoerg         CGM.getContext().getCharWidth());
11787330f729Sjoerg     // struct objc_method_description[]
11797330f729Sjoerg     auto MethodArray = MethodList.beginArray(ObjCMethodDescTy);
11807330f729Sjoerg     for (auto *M : Methods) {
11817330f729Sjoerg       auto Method = MethodArray.beginStruct(ObjCMethodDescTy);
11827330f729Sjoerg       Method.add(CGObjCGNU::GetConstantSelector(M));
11837330f729Sjoerg       Method.add(GetTypeString(Context.getObjCEncodingForMethodDecl(M, true)));
11847330f729Sjoerg       Method.finishAndAddTo(MethodArray);
11857330f729Sjoerg     }
11867330f729Sjoerg     MethodArray.finishAndAddTo(MethodList);
11877330f729Sjoerg     return MethodList.finishAndCreateGlobal(".objc_protocol_method_list",
11887330f729Sjoerg                                             CGM.getPointerAlign());
11897330f729Sjoerg   }
GenerateCategoryProtocolList(const ObjCCategoryDecl * OCD)11907330f729Sjoerg   llvm::Constant *GenerateCategoryProtocolList(const ObjCCategoryDecl *OCD)
11917330f729Sjoerg     override {
1192*e038c9c4Sjoerg     const auto &ReferencedProtocols = OCD->getReferencedProtocols();
1193*e038c9c4Sjoerg     auto RuntimeProtocols = GetRuntimeProtocolList(ReferencedProtocols.begin(),
1194*e038c9c4Sjoerg                                                    ReferencedProtocols.end());
11957330f729Sjoerg     SmallVector<llvm::Constant *, 16> Protocols;
1196*e038c9c4Sjoerg     for (const auto *PI : RuntimeProtocols)
11977330f729Sjoerg       Protocols.push_back(
11987330f729Sjoerg           llvm::ConstantExpr::getBitCast(GenerateProtocolRef(PI),
11997330f729Sjoerg             ProtocolPtrTy));
12007330f729Sjoerg     return GenerateProtocolList(Protocols);
12017330f729Sjoerg   }
12027330f729Sjoerg 
LookupIMPSuper(CodeGenFunction & CGF,Address ObjCSuper,llvm::Value * cmd,MessageSendInfo & MSI)12037330f729Sjoerg   llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper,
12047330f729Sjoerg                               llvm::Value *cmd, MessageSendInfo &MSI) override {
12057330f729Sjoerg     // Don't access the slot unless we're trying to cache the result.
12067330f729Sjoerg     CGBuilderTy &Builder = CGF.Builder;
12077330f729Sjoerg     llvm::Value *lookupArgs[] = {CGObjCGNU::EnforceType(Builder, ObjCSuper,
12087330f729Sjoerg         PtrToObjCSuperTy).getPointer(), cmd};
12097330f729Sjoerg     return CGF.EmitNounwindRuntimeCall(MsgLookupSuperFn, lookupArgs);
12107330f729Sjoerg   }
12117330f729Sjoerg 
GetClassVar(StringRef Name,bool isWeak=false)12127330f729Sjoerg   llvm::GlobalVariable *GetClassVar(StringRef Name, bool isWeak=false) {
12137330f729Sjoerg     std::string SymbolName = SymbolForClassRef(Name, isWeak);
12147330f729Sjoerg     auto *ClassSymbol = TheModule.getNamedGlobal(SymbolName);
12157330f729Sjoerg     if (ClassSymbol)
12167330f729Sjoerg       return ClassSymbol;
12177330f729Sjoerg     ClassSymbol = new llvm::GlobalVariable(TheModule,
12187330f729Sjoerg         IdTy, false, llvm::GlobalValue::ExternalLinkage,
12197330f729Sjoerg         nullptr, SymbolName);
12207330f729Sjoerg     // If this is a weak symbol, then we are creating a valid definition for
12217330f729Sjoerg     // the symbol, pointing to a weak definition of the real class pointer.  If
12227330f729Sjoerg     // this is not a weak reference, then we are expecting another compilation
12237330f729Sjoerg     // unit to provide the real indirection symbol.
12247330f729Sjoerg     if (isWeak)
12257330f729Sjoerg       ClassSymbol->setInitializer(new llvm::GlobalVariable(TheModule,
12267330f729Sjoerg           Int8Ty, false, llvm::GlobalValue::ExternalWeakLinkage,
12277330f729Sjoerg           nullptr, SymbolForClass(Name)));
12287330f729Sjoerg     else {
12297330f729Sjoerg       if (CGM.getTriple().isOSBinFormatCOFF()) {
12307330f729Sjoerg         IdentifierInfo &II = CGM.getContext().Idents.get(Name);
12317330f729Sjoerg         TranslationUnitDecl *TUDecl = CGM.getContext().getTranslationUnitDecl();
12327330f729Sjoerg         DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
12337330f729Sjoerg 
12347330f729Sjoerg         const ObjCInterfaceDecl *OID = nullptr;
1235*e038c9c4Sjoerg         for (const auto *Result : DC->lookup(&II))
12367330f729Sjoerg           if ((OID = dyn_cast<ObjCInterfaceDecl>(Result)))
12377330f729Sjoerg             break;
12387330f729Sjoerg 
12397330f729Sjoerg         // The first Interface we find may be a @class,
12407330f729Sjoerg         // which should only be treated as the source of
12417330f729Sjoerg         // truth in the absence of a true declaration.
1242*e038c9c4Sjoerg         assert(OID && "Failed to find ObjCInterfaceDecl");
12437330f729Sjoerg         const ObjCInterfaceDecl *OIDDef = OID->getDefinition();
12447330f729Sjoerg         if (OIDDef != nullptr)
12457330f729Sjoerg           OID = OIDDef;
12467330f729Sjoerg 
12477330f729Sjoerg         auto Storage = llvm::GlobalValue::DefaultStorageClass;
12487330f729Sjoerg         if (OID->hasAttr<DLLImportAttr>())
12497330f729Sjoerg           Storage = llvm::GlobalValue::DLLImportStorageClass;
12507330f729Sjoerg         else if (OID->hasAttr<DLLExportAttr>())
12517330f729Sjoerg           Storage = llvm::GlobalValue::DLLExportStorageClass;
12527330f729Sjoerg 
12537330f729Sjoerg         cast<llvm::GlobalValue>(ClassSymbol)->setDLLStorageClass(Storage);
12547330f729Sjoerg       }
12557330f729Sjoerg     }
12567330f729Sjoerg     assert(ClassSymbol->getName() == SymbolName);
12577330f729Sjoerg     return ClassSymbol;
12587330f729Sjoerg   }
GetClassNamed(CodeGenFunction & CGF,const std::string & Name,bool isWeak)12597330f729Sjoerg   llvm::Value *GetClassNamed(CodeGenFunction &CGF,
12607330f729Sjoerg                              const std::string &Name,
12617330f729Sjoerg                              bool isWeak) override {
12627330f729Sjoerg     return CGF.Builder.CreateLoad(Address(GetClassVar(Name, isWeak),
12637330f729Sjoerg           CGM.getPointerAlign()));
12647330f729Sjoerg   }
FlagsForOwnership(Qualifiers::ObjCLifetime Ownership)12657330f729Sjoerg   int32_t FlagsForOwnership(Qualifiers::ObjCLifetime Ownership) {
12667330f729Sjoerg     // typedef enum {
12677330f729Sjoerg     //   ownership_invalid = 0,
12687330f729Sjoerg     //   ownership_strong  = 1,
12697330f729Sjoerg     //   ownership_weak    = 2,
12707330f729Sjoerg     //   ownership_unsafe  = 3
12717330f729Sjoerg     // } ivar_ownership;
12727330f729Sjoerg     int Flag;
12737330f729Sjoerg     switch (Ownership) {
12747330f729Sjoerg       case Qualifiers::OCL_Strong:
12757330f729Sjoerg           Flag = 1;
12767330f729Sjoerg           break;
12777330f729Sjoerg       case Qualifiers::OCL_Weak:
12787330f729Sjoerg           Flag = 2;
12797330f729Sjoerg           break;
12807330f729Sjoerg       case Qualifiers::OCL_ExplicitNone:
12817330f729Sjoerg           Flag = 3;
12827330f729Sjoerg           break;
12837330f729Sjoerg       case Qualifiers::OCL_None:
12847330f729Sjoerg       case Qualifiers::OCL_Autoreleasing:
12857330f729Sjoerg         assert(Ownership != Qualifiers::OCL_Autoreleasing);
12867330f729Sjoerg         Flag = 0;
12877330f729Sjoerg     }
12887330f729Sjoerg     return Flag;
12897330f729Sjoerg   }
GenerateIvarList(ArrayRef<llvm::Constant * > IvarNames,ArrayRef<llvm::Constant * > IvarTypes,ArrayRef<llvm::Constant * > IvarOffsets,ArrayRef<llvm::Constant * > IvarAlign,ArrayRef<Qualifiers::ObjCLifetime> IvarOwnership)12907330f729Sjoerg   llvm::Constant *GenerateIvarList(ArrayRef<llvm::Constant *> IvarNames,
12917330f729Sjoerg                    ArrayRef<llvm::Constant *> IvarTypes,
12927330f729Sjoerg                    ArrayRef<llvm::Constant *> IvarOffsets,
12937330f729Sjoerg                    ArrayRef<llvm::Constant *> IvarAlign,
12947330f729Sjoerg                    ArrayRef<Qualifiers::ObjCLifetime> IvarOwnership) override {
12957330f729Sjoerg     llvm_unreachable("Method should not be called!");
12967330f729Sjoerg   }
12977330f729Sjoerg 
GenerateEmptyProtocol(StringRef ProtocolName)12987330f729Sjoerg   llvm::Constant *GenerateEmptyProtocol(StringRef ProtocolName) override {
12997330f729Sjoerg     std::string Name = SymbolForProtocol(ProtocolName);
13007330f729Sjoerg     auto *GV = TheModule.getGlobalVariable(Name);
13017330f729Sjoerg     if (!GV) {
13027330f729Sjoerg       // Emit a placeholder symbol.
13037330f729Sjoerg       GV = new llvm::GlobalVariable(TheModule, ProtocolTy, false,
13047330f729Sjoerg           llvm::GlobalValue::ExternalLinkage, nullptr, Name);
13057330f729Sjoerg       GV->setAlignment(CGM.getPointerAlign().getAsAlign());
13067330f729Sjoerg     }
13077330f729Sjoerg     return llvm::ConstantExpr::getBitCast(GV, ProtocolPtrTy);
13087330f729Sjoerg   }
13097330f729Sjoerg 
13107330f729Sjoerg   /// Existing protocol references.
13117330f729Sjoerg   llvm::StringMap<llvm::Constant*> ExistingProtocolRefs;
13127330f729Sjoerg 
GenerateProtocolRef(CodeGenFunction & CGF,const ObjCProtocolDecl * PD)13137330f729Sjoerg   llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
13147330f729Sjoerg                                    const ObjCProtocolDecl *PD) override {
13157330f729Sjoerg     auto Name = PD->getNameAsString();
13167330f729Sjoerg     auto *&Ref = ExistingProtocolRefs[Name];
13177330f729Sjoerg     if (!Ref) {
13187330f729Sjoerg       auto *&Protocol = ExistingProtocols[Name];
13197330f729Sjoerg       if (!Protocol)
13207330f729Sjoerg         Protocol = GenerateProtocolRef(PD);
13217330f729Sjoerg       std::string RefName = SymbolForProtocolRef(Name);
13227330f729Sjoerg       assert(!TheModule.getGlobalVariable(RefName));
13237330f729Sjoerg       // Emit a reference symbol.
13247330f729Sjoerg       auto GV = new llvm::GlobalVariable(TheModule, ProtocolPtrTy,
13257330f729Sjoerg           false, llvm::GlobalValue::LinkOnceODRLinkage,
13267330f729Sjoerg           llvm::ConstantExpr::getBitCast(Protocol, ProtocolPtrTy), RefName);
13277330f729Sjoerg       GV->setComdat(TheModule.getOrInsertComdat(RefName));
13287330f729Sjoerg       GV->setSection(sectionName<ProtocolReferenceSection>());
13297330f729Sjoerg       GV->setAlignment(CGM.getPointerAlign().getAsAlign());
13307330f729Sjoerg       Ref = GV;
13317330f729Sjoerg     }
13327330f729Sjoerg     EmittedProtocolRef = true;
1333*e038c9c4Sjoerg     return CGF.Builder.CreateAlignedLoad(ProtocolPtrTy, Ref,
1334*e038c9c4Sjoerg                                          CGM.getPointerAlign());
13357330f729Sjoerg   }
13367330f729Sjoerg 
GenerateProtocolList(ArrayRef<llvm::Constant * > Protocols)13377330f729Sjoerg   llvm::Constant *GenerateProtocolList(ArrayRef<llvm::Constant*> Protocols) {
13387330f729Sjoerg     llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(ProtocolPtrTy,
13397330f729Sjoerg         Protocols.size());
13407330f729Sjoerg     llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy,
13417330f729Sjoerg         Protocols);
13427330f729Sjoerg     ConstantInitBuilder builder(CGM);
13437330f729Sjoerg     auto ProtocolBuilder = builder.beginStruct();
13447330f729Sjoerg     ProtocolBuilder.addNullPointer(PtrTy);
13457330f729Sjoerg     ProtocolBuilder.addInt(SizeTy, Protocols.size());
13467330f729Sjoerg     ProtocolBuilder.add(ProtocolArray);
13477330f729Sjoerg     return ProtocolBuilder.finishAndCreateGlobal(".objc_protocol_list",
13487330f729Sjoerg         CGM.getPointerAlign(), false, llvm::GlobalValue::InternalLinkage);
13497330f729Sjoerg   }
13507330f729Sjoerg 
GenerateProtocol(const ObjCProtocolDecl * PD)13517330f729Sjoerg   void GenerateProtocol(const ObjCProtocolDecl *PD) override {
13527330f729Sjoerg     // Do nothing - we only emit referenced protocols.
13537330f729Sjoerg   }
GenerateProtocolRef(const ObjCProtocolDecl * PD)1354*e038c9c4Sjoerg   llvm::Constant *GenerateProtocolRef(const ObjCProtocolDecl *PD) override {
13557330f729Sjoerg     std::string ProtocolName = PD->getNameAsString();
13567330f729Sjoerg     auto *&Protocol = ExistingProtocols[ProtocolName];
13577330f729Sjoerg     if (Protocol)
13587330f729Sjoerg       return Protocol;
13597330f729Sjoerg 
13607330f729Sjoerg     EmittedProtocol = true;
13617330f729Sjoerg 
13627330f729Sjoerg     auto SymName = SymbolForProtocol(ProtocolName);
13637330f729Sjoerg     auto *OldGV = TheModule.getGlobalVariable(SymName);
13647330f729Sjoerg 
13657330f729Sjoerg     // Use the protocol definition, if there is one.
13667330f729Sjoerg     if (const ObjCProtocolDecl *Def = PD->getDefinition())
13677330f729Sjoerg       PD = Def;
13687330f729Sjoerg     else {
13697330f729Sjoerg       // If there is no definition, then create an external linkage symbol and
13707330f729Sjoerg       // hope that someone else fills it in for us (and fail to link if they
13717330f729Sjoerg       // don't).
13727330f729Sjoerg       assert(!OldGV);
13737330f729Sjoerg       Protocol = new llvm::GlobalVariable(TheModule, ProtocolTy,
13747330f729Sjoerg         /*isConstant*/false,
13757330f729Sjoerg         llvm::GlobalValue::ExternalLinkage, nullptr, SymName);
13767330f729Sjoerg       return Protocol;
13777330f729Sjoerg     }
13787330f729Sjoerg 
13797330f729Sjoerg     SmallVector<llvm::Constant*, 16> Protocols;
1380*e038c9c4Sjoerg     auto RuntimeProtocols =
1381*e038c9c4Sjoerg         GetRuntimeProtocolList(PD->protocol_begin(), PD->protocol_end());
1382*e038c9c4Sjoerg     for (const auto *PI : RuntimeProtocols)
13837330f729Sjoerg       Protocols.push_back(
13847330f729Sjoerg           llvm::ConstantExpr::getBitCast(GenerateProtocolRef(PI),
13857330f729Sjoerg             ProtocolPtrTy));
13867330f729Sjoerg     llvm::Constant *ProtocolList = GenerateProtocolList(Protocols);
13877330f729Sjoerg 
13887330f729Sjoerg     // Collect information about methods
13897330f729Sjoerg     llvm::Constant *InstanceMethodList, *OptionalInstanceMethodList;
13907330f729Sjoerg     llvm::Constant *ClassMethodList, *OptionalClassMethodList;
13917330f729Sjoerg     EmitProtocolMethodList(PD->instance_methods(), InstanceMethodList,
13927330f729Sjoerg         OptionalInstanceMethodList);
13937330f729Sjoerg     EmitProtocolMethodList(PD->class_methods(), ClassMethodList,
13947330f729Sjoerg         OptionalClassMethodList);
13957330f729Sjoerg 
13967330f729Sjoerg     // The isa pointer must be set to a magic number so the runtime knows it's
13977330f729Sjoerg     // the correct layout.
13987330f729Sjoerg     ConstantInitBuilder builder(CGM);
13997330f729Sjoerg     auto ProtocolBuilder = builder.beginStruct();
14007330f729Sjoerg     ProtocolBuilder.add(llvm::ConstantExpr::getIntToPtr(
14017330f729Sjoerg           llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy));
14027330f729Sjoerg     ProtocolBuilder.add(MakeConstantString(ProtocolName));
14037330f729Sjoerg     ProtocolBuilder.add(ProtocolList);
14047330f729Sjoerg     ProtocolBuilder.add(InstanceMethodList);
14057330f729Sjoerg     ProtocolBuilder.add(ClassMethodList);
14067330f729Sjoerg     ProtocolBuilder.add(OptionalInstanceMethodList);
14077330f729Sjoerg     ProtocolBuilder.add(OptionalClassMethodList);
14087330f729Sjoerg     // Required instance properties
14097330f729Sjoerg     ProtocolBuilder.add(GeneratePropertyList(nullptr, PD, false, false));
14107330f729Sjoerg     // Optional instance properties
14117330f729Sjoerg     ProtocolBuilder.add(GeneratePropertyList(nullptr, PD, false, true));
14127330f729Sjoerg     // Required class properties
14137330f729Sjoerg     ProtocolBuilder.add(GeneratePropertyList(nullptr, PD, true, false));
14147330f729Sjoerg     // Optional class properties
14157330f729Sjoerg     ProtocolBuilder.add(GeneratePropertyList(nullptr, PD, true, true));
14167330f729Sjoerg 
14177330f729Sjoerg     auto *GV = ProtocolBuilder.finishAndCreateGlobal(SymName,
14187330f729Sjoerg         CGM.getPointerAlign(), false, llvm::GlobalValue::ExternalLinkage);
14197330f729Sjoerg     GV->setSection(sectionName<ProtocolSection>());
14207330f729Sjoerg     GV->setComdat(TheModule.getOrInsertComdat(SymName));
14217330f729Sjoerg     if (OldGV) {
14227330f729Sjoerg       OldGV->replaceAllUsesWith(llvm::ConstantExpr::getBitCast(GV,
14237330f729Sjoerg             OldGV->getType()));
14247330f729Sjoerg       OldGV->removeFromParent();
14257330f729Sjoerg       GV->setName(SymName);
14267330f729Sjoerg     }
14277330f729Sjoerg     Protocol = GV;
14287330f729Sjoerg     return GV;
14297330f729Sjoerg   }
EnforceType(llvm::Constant * Val,llvm::Type * Ty)14307330f729Sjoerg   llvm::Constant *EnforceType(llvm::Constant *Val, llvm::Type *Ty) {
14317330f729Sjoerg     if (Val->getType() == Ty)
14327330f729Sjoerg       return Val;
14337330f729Sjoerg     return llvm::ConstantExpr::getBitCast(Val, Ty);
14347330f729Sjoerg   }
GetTypedSelector(CodeGenFunction & CGF,Selector Sel,const std::string & TypeEncoding)14357330f729Sjoerg   llvm::Value *GetTypedSelector(CodeGenFunction &CGF, Selector Sel,
14367330f729Sjoerg                                 const std::string &TypeEncoding) override {
14377330f729Sjoerg     return GetConstantSelector(Sel, TypeEncoding);
14387330f729Sjoerg   }
GetTypeString(llvm::StringRef TypeEncoding)14397330f729Sjoerg   llvm::Constant  *GetTypeString(llvm::StringRef TypeEncoding) {
14407330f729Sjoerg     if (TypeEncoding.empty())
14417330f729Sjoerg       return NULLPtr;
1442*e038c9c4Sjoerg     std::string MangledTypes = std::string(TypeEncoding);
14437330f729Sjoerg     std::replace(MangledTypes.begin(), MangledTypes.end(),
14447330f729Sjoerg       '@', '\1');
14457330f729Sjoerg     std::string TypesVarName = ".objc_sel_types_" + MangledTypes;
14467330f729Sjoerg     auto *TypesGlobal = TheModule.getGlobalVariable(TypesVarName);
14477330f729Sjoerg     if (!TypesGlobal) {
14487330f729Sjoerg       llvm::Constant *Init = llvm::ConstantDataArray::getString(VMContext,
14497330f729Sjoerg           TypeEncoding);
14507330f729Sjoerg       auto *GV = new llvm::GlobalVariable(TheModule, Init->getType(),
14517330f729Sjoerg           true, llvm::GlobalValue::LinkOnceODRLinkage, Init, TypesVarName);
14527330f729Sjoerg       GV->setComdat(TheModule.getOrInsertComdat(TypesVarName));
14537330f729Sjoerg       GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
14547330f729Sjoerg       TypesGlobal = GV;
14557330f729Sjoerg     }
14567330f729Sjoerg     return llvm::ConstantExpr::getGetElementPtr(TypesGlobal->getValueType(),
14577330f729Sjoerg         TypesGlobal, Zeros);
14587330f729Sjoerg   }
GetConstantSelector(Selector Sel,const std::string & TypeEncoding)14597330f729Sjoerg   llvm::Constant *GetConstantSelector(Selector Sel,
14607330f729Sjoerg                                       const std::string &TypeEncoding) override {
14617330f729Sjoerg     // @ is used as a special character in symbol names (used for symbol
14627330f729Sjoerg     // versioning), so mangle the name to not include it.  Replace it with a
14637330f729Sjoerg     // character that is not a valid type encoding character (and, being
14647330f729Sjoerg     // non-printable, never will be!)
14657330f729Sjoerg     std::string MangledTypes = TypeEncoding;
14667330f729Sjoerg     std::replace(MangledTypes.begin(), MangledTypes.end(),
14677330f729Sjoerg       '@', '\1');
14687330f729Sjoerg     auto SelVarName = (StringRef(".objc_selector_") + Sel.getAsString() + "_" +
14697330f729Sjoerg       MangledTypes).str();
14707330f729Sjoerg     if (auto *GV = TheModule.getNamedGlobal(SelVarName))
14717330f729Sjoerg       return EnforceType(GV, SelectorTy);
14727330f729Sjoerg     ConstantInitBuilder builder(CGM);
14737330f729Sjoerg     auto SelBuilder = builder.beginStruct();
14747330f729Sjoerg     SelBuilder.add(ExportUniqueString(Sel.getAsString(), ".objc_sel_name_",
14757330f729Sjoerg           true));
14767330f729Sjoerg     SelBuilder.add(GetTypeString(TypeEncoding));
14777330f729Sjoerg     auto *GV = SelBuilder.finishAndCreateGlobal(SelVarName,
14787330f729Sjoerg         CGM.getPointerAlign(), false, llvm::GlobalValue::LinkOnceODRLinkage);
14797330f729Sjoerg     GV->setComdat(TheModule.getOrInsertComdat(SelVarName));
14807330f729Sjoerg     GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
14817330f729Sjoerg     GV->setSection(sectionName<SelectorSection>());
14827330f729Sjoerg     auto *SelVal = EnforceType(GV, SelectorTy);
14837330f729Sjoerg     return SelVal;
14847330f729Sjoerg   }
14857330f729Sjoerg   llvm::StructType *emptyStruct = nullptr;
14867330f729Sjoerg 
14877330f729Sjoerg   /// Return pointers to the start and end of a section.  On ELF platforms, we
14887330f729Sjoerg   /// use the __start_ and __stop_ symbols that GNU-compatible linkers will set
14897330f729Sjoerg   /// to the start and end of section names, as long as those section names are
14907330f729Sjoerg   /// valid identifiers and the symbols are referenced but not defined.  On
14917330f729Sjoerg   /// Windows, we use the fact that MSVC-compatible linkers will lexically sort
14927330f729Sjoerg   /// by subsections and place everything that we want to reference in a middle
14937330f729Sjoerg   /// subsection and then insert zero-sized symbols in subsections a and z.
14947330f729Sjoerg   std::pair<llvm::Constant*,llvm::Constant*>
GetSectionBounds(StringRef Section)14957330f729Sjoerg   GetSectionBounds(StringRef Section) {
14967330f729Sjoerg     if (CGM.getTriple().isOSBinFormatCOFF()) {
14977330f729Sjoerg       if (emptyStruct == nullptr) {
14987330f729Sjoerg         emptyStruct = llvm::StructType::create(VMContext, ".objc_section_sentinel");
14997330f729Sjoerg         emptyStruct->setBody({}, /*isPacked*/true);
15007330f729Sjoerg       }
15017330f729Sjoerg       auto ZeroInit = llvm::Constant::getNullValue(emptyStruct);
15027330f729Sjoerg       auto Sym = [&](StringRef Prefix, StringRef SecSuffix) {
15037330f729Sjoerg         auto *Sym = new llvm::GlobalVariable(TheModule, emptyStruct,
15047330f729Sjoerg             /*isConstant*/false,
15057330f729Sjoerg             llvm::GlobalValue::LinkOnceODRLinkage, ZeroInit, Prefix +
15067330f729Sjoerg             Section);
15077330f729Sjoerg         Sym->setVisibility(llvm::GlobalValue::HiddenVisibility);
15087330f729Sjoerg         Sym->setSection((Section + SecSuffix).str());
15097330f729Sjoerg         Sym->setComdat(TheModule.getOrInsertComdat((Prefix +
15107330f729Sjoerg             Section).str()));
15117330f729Sjoerg         Sym->setAlignment(CGM.getPointerAlign().getAsAlign());
15127330f729Sjoerg         return Sym;
15137330f729Sjoerg       };
15147330f729Sjoerg       return { Sym("__start_", "$a"), Sym("__stop", "$z") };
15157330f729Sjoerg     }
15167330f729Sjoerg     auto *Start = new llvm::GlobalVariable(TheModule, PtrTy,
15177330f729Sjoerg         /*isConstant*/false,
15187330f729Sjoerg         llvm::GlobalValue::ExternalLinkage, nullptr, StringRef("__start_") +
15197330f729Sjoerg         Section);
15207330f729Sjoerg     Start->setVisibility(llvm::GlobalValue::HiddenVisibility);
15217330f729Sjoerg     auto *Stop = new llvm::GlobalVariable(TheModule, PtrTy,
15227330f729Sjoerg         /*isConstant*/false,
15237330f729Sjoerg         llvm::GlobalValue::ExternalLinkage, nullptr, StringRef("__stop_") +
15247330f729Sjoerg         Section);
15257330f729Sjoerg     Stop->setVisibility(llvm::GlobalValue::HiddenVisibility);
15267330f729Sjoerg     return { Start, Stop };
15277330f729Sjoerg   }
getCatchAllTypeInfo()15287330f729Sjoerg   CatchTypeInfo getCatchAllTypeInfo() override {
15297330f729Sjoerg     return CGM.getCXXABI().getCatchAllTypeInfo();
15307330f729Sjoerg   }
ModuleInitFunction()15317330f729Sjoerg   llvm::Function *ModuleInitFunction() override {
15327330f729Sjoerg     llvm::Function *LoadFunction = llvm::Function::Create(
15337330f729Sjoerg       llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), false),
15347330f729Sjoerg       llvm::GlobalValue::LinkOnceODRLinkage, ".objcv2_load_function",
15357330f729Sjoerg       &TheModule);
15367330f729Sjoerg     LoadFunction->setVisibility(llvm::GlobalValue::HiddenVisibility);
15377330f729Sjoerg     LoadFunction->setComdat(TheModule.getOrInsertComdat(".objcv2_load_function"));
15387330f729Sjoerg 
15397330f729Sjoerg     llvm::BasicBlock *EntryBB =
15407330f729Sjoerg         llvm::BasicBlock::Create(VMContext, "entry", LoadFunction);
15417330f729Sjoerg     CGBuilderTy B(CGM, VMContext);
15427330f729Sjoerg     B.SetInsertPoint(EntryBB);
15437330f729Sjoerg     ConstantInitBuilder builder(CGM);
15447330f729Sjoerg     auto InitStructBuilder = builder.beginStruct();
15457330f729Sjoerg     InitStructBuilder.addInt(Int64Ty, 0);
15467330f729Sjoerg     auto &sectionVec = CGM.getTriple().isOSBinFormatCOFF() ? PECOFFSectionsBaseNames : SectionsBaseNames;
15477330f729Sjoerg     for (auto *s : sectionVec) {
15487330f729Sjoerg       auto bounds = GetSectionBounds(s);
15497330f729Sjoerg       InitStructBuilder.add(bounds.first);
15507330f729Sjoerg       InitStructBuilder.add(bounds.second);
15517330f729Sjoerg     }
15527330f729Sjoerg     auto *InitStruct = InitStructBuilder.finishAndCreateGlobal(".objc_init",
15537330f729Sjoerg         CGM.getPointerAlign(), false, llvm::GlobalValue::LinkOnceODRLinkage);
15547330f729Sjoerg     InitStruct->setVisibility(llvm::GlobalValue::HiddenVisibility);
15557330f729Sjoerg     InitStruct->setComdat(TheModule.getOrInsertComdat(".objc_init"));
15567330f729Sjoerg 
15577330f729Sjoerg     CallRuntimeFunction(B, "__objc_load", {InitStruct});;
15587330f729Sjoerg     B.CreateRetVoid();
15597330f729Sjoerg     // Make sure that the optimisers don't delete this function.
15607330f729Sjoerg     CGM.addCompilerUsedGlobal(LoadFunction);
15617330f729Sjoerg     // FIXME: Currently ELF only!
15627330f729Sjoerg     // We have to do this by hand, rather than with @llvm.ctors, so that the
15637330f729Sjoerg     // linker can remove the duplicate invocations.
15647330f729Sjoerg     auto *InitVar = new llvm::GlobalVariable(TheModule, LoadFunction->getType(),
1565*e038c9c4Sjoerg         /*isConstant*/false, llvm::GlobalValue::LinkOnceAnyLinkage,
15667330f729Sjoerg         LoadFunction, ".objc_ctor");
15677330f729Sjoerg     // Check that this hasn't been renamed.  This shouldn't happen, because
15687330f729Sjoerg     // this function should be called precisely once.
15697330f729Sjoerg     assert(InitVar->getName() == ".objc_ctor");
15707330f729Sjoerg     // In Windows, initialisers are sorted by the suffix.  XCL is for library
15717330f729Sjoerg     // initialisers, which run before user initialisers.  We are running
15727330f729Sjoerg     // Objective-C loads at the end of library load.  This means +load methods
15737330f729Sjoerg     // will run before any other static constructors, but that static
15747330f729Sjoerg     // constructors can see a fully initialised Objective-C state.
15757330f729Sjoerg     if (CGM.getTriple().isOSBinFormatCOFF())
15767330f729Sjoerg         InitVar->setSection(".CRT$XCLz");
15777330f729Sjoerg     else
15787330f729Sjoerg     {
15797330f729Sjoerg       if (CGM.getCodeGenOpts().UseInitArray)
15807330f729Sjoerg         InitVar->setSection(".init_array");
15817330f729Sjoerg       else
15827330f729Sjoerg         InitVar->setSection(".ctors");
15837330f729Sjoerg     }
15847330f729Sjoerg     InitVar->setVisibility(llvm::GlobalValue::HiddenVisibility);
15857330f729Sjoerg     InitVar->setComdat(TheModule.getOrInsertComdat(".objc_ctor"));
15867330f729Sjoerg     CGM.addUsedGlobal(InitVar);
15877330f729Sjoerg     for (auto *C : Categories) {
15887330f729Sjoerg       auto *Cat = cast<llvm::GlobalVariable>(C->stripPointerCasts());
15897330f729Sjoerg       Cat->setSection(sectionName<CategorySection>());
15907330f729Sjoerg       CGM.addUsedGlobal(Cat);
15917330f729Sjoerg     }
15927330f729Sjoerg     auto createNullGlobal = [&](StringRef Name, ArrayRef<llvm::Constant*> Init,
15937330f729Sjoerg         StringRef Section) {
15947330f729Sjoerg       auto nullBuilder = builder.beginStruct();
15957330f729Sjoerg       for (auto *F : Init)
15967330f729Sjoerg         nullBuilder.add(F);
15977330f729Sjoerg       auto GV = nullBuilder.finishAndCreateGlobal(Name, CGM.getPointerAlign(),
15987330f729Sjoerg           false, llvm::GlobalValue::LinkOnceODRLinkage);
15997330f729Sjoerg       GV->setSection(Section);
16007330f729Sjoerg       GV->setComdat(TheModule.getOrInsertComdat(Name));
16017330f729Sjoerg       GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
16027330f729Sjoerg       CGM.addUsedGlobal(GV);
16037330f729Sjoerg       return GV;
16047330f729Sjoerg     };
16057330f729Sjoerg     for (auto clsAlias : ClassAliases)
16067330f729Sjoerg       createNullGlobal(std::string(".objc_class_alias") +
16077330f729Sjoerg           clsAlias.second, { MakeConstantString(clsAlias.second),
16087330f729Sjoerg           GetClassVar(clsAlias.first) }, sectionName<ClassAliasSection>());
16097330f729Sjoerg     // On ELF platforms, add a null value for each special section so that we
16107330f729Sjoerg     // can always guarantee that the _start and _stop symbols will exist and be
16117330f729Sjoerg     // meaningful.  This is not required on COFF platforms, where our start and
16127330f729Sjoerg     // stop symbols will create the section.
16137330f729Sjoerg     if (!CGM.getTriple().isOSBinFormatCOFF()) {
16147330f729Sjoerg       createNullGlobal(".objc_null_selector", {NULLPtr, NULLPtr},
16157330f729Sjoerg           sectionName<SelectorSection>());
16167330f729Sjoerg       if (Categories.empty())
16177330f729Sjoerg         createNullGlobal(".objc_null_category", {NULLPtr, NULLPtr,
16187330f729Sjoerg                       NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr},
16197330f729Sjoerg             sectionName<CategorySection>());
16207330f729Sjoerg       if (!EmittedClass) {
16217330f729Sjoerg         createNullGlobal(".objc_null_cls_init_ref", NULLPtr,
16227330f729Sjoerg             sectionName<ClassSection>());
16237330f729Sjoerg         createNullGlobal(".objc_null_class_ref", { NULLPtr, NULLPtr },
16247330f729Sjoerg             sectionName<ClassReferenceSection>());
16257330f729Sjoerg       }
16267330f729Sjoerg       if (!EmittedProtocol)
16277330f729Sjoerg         createNullGlobal(".objc_null_protocol", {NULLPtr, NULLPtr, NULLPtr,
16287330f729Sjoerg             NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr,
16297330f729Sjoerg             NULLPtr}, sectionName<ProtocolSection>());
16307330f729Sjoerg       if (!EmittedProtocolRef)
16317330f729Sjoerg         createNullGlobal(".objc_null_protocol_ref", {NULLPtr},
16327330f729Sjoerg             sectionName<ProtocolReferenceSection>());
16337330f729Sjoerg       if (ClassAliases.empty())
16347330f729Sjoerg         createNullGlobal(".objc_null_class_alias", { NULLPtr, NULLPtr },
16357330f729Sjoerg             sectionName<ClassAliasSection>());
16367330f729Sjoerg       if (ConstantStrings.empty()) {
16377330f729Sjoerg         auto i32Zero = llvm::ConstantInt::get(Int32Ty, 0);
16387330f729Sjoerg         createNullGlobal(".objc_null_constant_string", { NULLPtr, i32Zero,
16397330f729Sjoerg             i32Zero, i32Zero, i32Zero, NULLPtr },
16407330f729Sjoerg             sectionName<ConstantStringSection>());
16417330f729Sjoerg       }
16427330f729Sjoerg     }
16437330f729Sjoerg     ConstantStrings.clear();
16447330f729Sjoerg     Categories.clear();
16457330f729Sjoerg     Classes.clear();
16467330f729Sjoerg 
16477330f729Sjoerg     if (EarlyInitList.size() > 0) {
16487330f729Sjoerg       auto *Init = llvm::Function::Create(llvm::FunctionType::get(CGM.VoidTy,
16497330f729Sjoerg             {}), llvm::GlobalValue::InternalLinkage, ".objc_early_init",
16507330f729Sjoerg           &CGM.getModule());
16517330f729Sjoerg       llvm::IRBuilder<> b(llvm::BasicBlock::Create(CGM.getLLVMContext(), "entry",
16527330f729Sjoerg             Init));
16537330f729Sjoerg       for (const auto &lateInit : EarlyInitList) {
16547330f729Sjoerg         auto *global = TheModule.getGlobalVariable(lateInit.first);
16557330f729Sjoerg         if (global) {
1656*e038c9c4Sjoerg           b.CreateAlignedStore(
1657*e038c9c4Sjoerg               global,
1658*e038c9c4Sjoerg               b.CreateStructGEP(lateInit.second.first, lateInit.second.second),
1659*e038c9c4Sjoerg               CGM.getPointerAlign().getAsAlign());
16607330f729Sjoerg         }
16617330f729Sjoerg       }
16627330f729Sjoerg       b.CreateRetVoid();
16637330f729Sjoerg       // We can't use the normal LLVM global initialisation array, because we
16647330f729Sjoerg       // need to specify that this runs early in library initialisation.
16657330f729Sjoerg       auto *InitVar = new llvm::GlobalVariable(CGM.getModule(), Init->getType(),
16667330f729Sjoerg           /*isConstant*/true, llvm::GlobalValue::InternalLinkage,
16677330f729Sjoerg           Init, ".objc_early_init_ptr");
16687330f729Sjoerg       InitVar->setSection(".CRT$XCLb");
16697330f729Sjoerg       CGM.addUsedGlobal(InitVar);
16707330f729Sjoerg     }
16717330f729Sjoerg     return nullptr;
16727330f729Sjoerg   }
16737330f729Sjoerg   /// In the v2 ABI, ivar offset variables use the type encoding in their name
16747330f729Sjoerg   /// to trigger linker failures if the types don't match.
GetIVarOffsetVariableName(const ObjCInterfaceDecl * ID,const ObjCIvarDecl * Ivar)16757330f729Sjoerg   std::string GetIVarOffsetVariableName(const ObjCInterfaceDecl *ID,
16767330f729Sjoerg                                         const ObjCIvarDecl *Ivar) override {
16777330f729Sjoerg     std::string TypeEncoding;
16787330f729Sjoerg     CGM.getContext().getObjCEncodingForType(Ivar->getType(), TypeEncoding);
16797330f729Sjoerg     // Prevent the @ from being interpreted as a symbol version.
16807330f729Sjoerg     std::replace(TypeEncoding.begin(), TypeEncoding.end(),
16817330f729Sjoerg       '@', '\1');
16827330f729Sjoerg     const std::string Name = "__objc_ivar_offset_" + ID->getNameAsString()
16837330f729Sjoerg       + '.' + Ivar->getNameAsString() + '.' + TypeEncoding;
16847330f729Sjoerg     return Name;
16857330f729Sjoerg   }
EmitIvarOffset(CodeGenFunction & CGF,const ObjCInterfaceDecl * Interface,const ObjCIvarDecl * Ivar)16867330f729Sjoerg   llvm::Value *EmitIvarOffset(CodeGenFunction &CGF,
16877330f729Sjoerg                               const ObjCInterfaceDecl *Interface,
16887330f729Sjoerg                               const ObjCIvarDecl *Ivar) override {
16897330f729Sjoerg     const std::string Name = GetIVarOffsetVariableName(Ivar->getContainingInterface(), Ivar);
16907330f729Sjoerg     llvm::GlobalVariable *IvarOffsetPointer = TheModule.getNamedGlobal(Name);
16917330f729Sjoerg     if (!IvarOffsetPointer)
16927330f729Sjoerg       IvarOffsetPointer = new llvm::GlobalVariable(TheModule, IntTy, false,
16937330f729Sjoerg               llvm::GlobalValue::ExternalLinkage, nullptr, Name);
16947330f729Sjoerg     CharUnits Align = CGM.getIntAlign();
1695*e038c9c4Sjoerg     llvm::Value *Offset =
1696*e038c9c4Sjoerg         CGF.Builder.CreateAlignedLoad(IntTy, IvarOffsetPointer, Align);
16977330f729Sjoerg     if (Offset->getType() != PtrDiffTy)
16987330f729Sjoerg       Offset = CGF.Builder.CreateZExtOrBitCast(Offset, PtrDiffTy);
16997330f729Sjoerg     return Offset;
17007330f729Sjoerg   }
GenerateClass(const ObjCImplementationDecl * OID)17017330f729Sjoerg   void GenerateClass(const ObjCImplementationDecl *OID) override {
17027330f729Sjoerg     ASTContext &Context = CGM.getContext();
17037330f729Sjoerg     bool IsCOFF = CGM.getTriple().isOSBinFormatCOFF();
17047330f729Sjoerg 
17057330f729Sjoerg     // Get the class name
17067330f729Sjoerg     ObjCInterfaceDecl *classDecl =
17077330f729Sjoerg         const_cast<ObjCInterfaceDecl *>(OID->getClassInterface());
17087330f729Sjoerg     std::string className = classDecl->getNameAsString();
17097330f729Sjoerg     auto *classNameConstant = MakeConstantString(className);
17107330f729Sjoerg 
17117330f729Sjoerg     ConstantInitBuilder builder(CGM);
17127330f729Sjoerg     auto metaclassFields = builder.beginStruct();
17137330f729Sjoerg     // struct objc_class *isa;
17147330f729Sjoerg     metaclassFields.addNullPointer(PtrTy);
17157330f729Sjoerg     // struct objc_class *super_class;
17167330f729Sjoerg     metaclassFields.addNullPointer(PtrTy);
17177330f729Sjoerg     // const char *name;
17187330f729Sjoerg     metaclassFields.add(classNameConstant);
17197330f729Sjoerg     // long version;
17207330f729Sjoerg     metaclassFields.addInt(LongTy, 0);
17217330f729Sjoerg     // unsigned long info;
17227330f729Sjoerg     // objc_class_flag_meta
17237330f729Sjoerg     metaclassFields.addInt(LongTy, 1);
17247330f729Sjoerg     // long instance_size;
17257330f729Sjoerg     // Setting this to zero is consistent with the older ABI, but it might be
17267330f729Sjoerg     // more sensible to set this to sizeof(struct objc_class)
17277330f729Sjoerg     metaclassFields.addInt(LongTy, 0);
17287330f729Sjoerg     // struct objc_ivar_list *ivars;
17297330f729Sjoerg     metaclassFields.addNullPointer(PtrTy);
17307330f729Sjoerg     // struct objc_method_list *methods
17317330f729Sjoerg     // FIXME: Almost identical code is copied and pasted below for the
17327330f729Sjoerg     // class, but refactoring it cleanly requires C++14 generic lambdas.
17337330f729Sjoerg     if (OID->classmeth_begin() == OID->classmeth_end())
17347330f729Sjoerg       metaclassFields.addNullPointer(PtrTy);
17357330f729Sjoerg     else {
17367330f729Sjoerg       SmallVector<ObjCMethodDecl*, 16> ClassMethods;
17377330f729Sjoerg       ClassMethods.insert(ClassMethods.begin(), OID->classmeth_begin(),
17387330f729Sjoerg           OID->classmeth_end());
17397330f729Sjoerg       metaclassFields.addBitCast(
17407330f729Sjoerg               GenerateMethodList(className, "", ClassMethods, true),
17417330f729Sjoerg               PtrTy);
17427330f729Sjoerg     }
17437330f729Sjoerg     // void *dtable;
17447330f729Sjoerg     metaclassFields.addNullPointer(PtrTy);
17457330f729Sjoerg     // IMP cxx_construct;
17467330f729Sjoerg     metaclassFields.addNullPointer(PtrTy);
17477330f729Sjoerg     // IMP cxx_destruct;
17487330f729Sjoerg     metaclassFields.addNullPointer(PtrTy);
17497330f729Sjoerg     // struct objc_class *subclass_list
17507330f729Sjoerg     metaclassFields.addNullPointer(PtrTy);
17517330f729Sjoerg     // struct objc_class *sibling_class
17527330f729Sjoerg     metaclassFields.addNullPointer(PtrTy);
17537330f729Sjoerg     // struct objc_protocol_list *protocols;
17547330f729Sjoerg     metaclassFields.addNullPointer(PtrTy);
17557330f729Sjoerg     // struct reference_list *extra_data;
17567330f729Sjoerg     metaclassFields.addNullPointer(PtrTy);
17577330f729Sjoerg     // long abi_version;
17587330f729Sjoerg     metaclassFields.addInt(LongTy, 0);
17597330f729Sjoerg     // struct objc_property_list *properties
17607330f729Sjoerg     metaclassFields.add(GeneratePropertyList(OID, classDecl, /*isClassProperty*/true));
17617330f729Sjoerg 
17627330f729Sjoerg     auto *metaclass = metaclassFields.finishAndCreateGlobal(
17637330f729Sjoerg         ManglePublicSymbol("OBJC_METACLASS_") + className,
17647330f729Sjoerg         CGM.getPointerAlign());
17657330f729Sjoerg 
17667330f729Sjoerg     auto classFields = builder.beginStruct();
17677330f729Sjoerg     // struct objc_class *isa;
17687330f729Sjoerg     classFields.add(metaclass);
17697330f729Sjoerg     // struct objc_class *super_class;
17707330f729Sjoerg     // Get the superclass name.
17717330f729Sjoerg     const ObjCInterfaceDecl * SuperClassDecl =
17727330f729Sjoerg       OID->getClassInterface()->getSuperClass();
17737330f729Sjoerg     llvm::Constant *SuperClass = nullptr;
17747330f729Sjoerg     if (SuperClassDecl) {
17757330f729Sjoerg       auto SuperClassName = SymbolForClass(SuperClassDecl->getNameAsString());
17767330f729Sjoerg       SuperClass = TheModule.getNamedGlobal(SuperClassName);
17777330f729Sjoerg       if (!SuperClass)
17787330f729Sjoerg       {
17797330f729Sjoerg         SuperClass = new llvm::GlobalVariable(TheModule, PtrTy, false,
17807330f729Sjoerg             llvm::GlobalValue::ExternalLinkage, nullptr, SuperClassName);
17817330f729Sjoerg         if (IsCOFF) {
17827330f729Sjoerg           auto Storage = llvm::GlobalValue::DefaultStorageClass;
17837330f729Sjoerg           if (SuperClassDecl->hasAttr<DLLImportAttr>())
17847330f729Sjoerg             Storage = llvm::GlobalValue::DLLImportStorageClass;
17857330f729Sjoerg           else if (SuperClassDecl->hasAttr<DLLExportAttr>())
17867330f729Sjoerg             Storage = llvm::GlobalValue::DLLExportStorageClass;
17877330f729Sjoerg 
17887330f729Sjoerg           cast<llvm::GlobalValue>(SuperClass)->setDLLStorageClass(Storage);
17897330f729Sjoerg         }
17907330f729Sjoerg       }
17917330f729Sjoerg       if (!IsCOFF)
17927330f729Sjoerg         classFields.add(llvm::ConstantExpr::getBitCast(SuperClass, PtrTy));
17937330f729Sjoerg       else
17947330f729Sjoerg         classFields.addNullPointer(PtrTy);
17957330f729Sjoerg     } else
17967330f729Sjoerg       classFields.addNullPointer(PtrTy);
17977330f729Sjoerg     // const char *name;
17987330f729Sjoerg     classFields.add(classNameConstant);
17997330f729Sjoerg     // long version;
18007330f729Sjoerg     classFields.addInt(LongTy, 0);
18017330f729Sjoerg     // unsigned long info;
18027330f729Sjoerg     // !objc_class_flag_meta
18037330f729Sjoerg     classFields.addInt(LongTy, 0);
18047330f729Sjoerg     // long instance_size;
18057330f729Sjoerg     int superInstanceSize = !SuperClassDecl ? 0 :
18067330f729Sjoerg       Context.getASTObjCInterfaceLayout(SuperClassDecl).getSize().getQuantity();
18077330f729Sjoerg     // Instance size is negative for classes that have not yet had their ivar
18087330f729Sjoerg     // layout calculated.
18097330f729Sjoerg     classFields.addInt(LongTy,
18107330f729Sjoerg       0 - (Context.getASTObjCImplementationLayout(OID).getSize().getQuantity() -
18117330f729Sjoerg       superInstanceSize));
18127330f729Sjoerg 
18137330f729Sjoerg     if (classDecl->all_declared_ivar_begin() == nullptr)
18147330f729Sjoerg       classFields.addNullPointer(PtrTy);
18157330f729Sjoerg     else {
18167330f729Sjoerg       int ivar_count = 0;
18177330f729Sjoerg       for (const ObjCIvarDecl *IVD = classDecl->all_declared_ivar_begin(); IVD;
18187330f729Sjoerg            IVD = IVD->getNextIvar()) ivar_count++;
18197330f729Sjoerg       llvm::DataLayout td(&TheModule);
18207330f729Sjoerg       // struct objc_ivar_list *ivars;
18217330f729Sjoerg       ConstantInitBuilder b(CGM);
18227330f729Sjoerg       auto ivarListBuilder = b.beginStruct();
18237330f729Sjoerg       // int count;
18247330f729Sjoerg       ivarListBuilder.addInt(IntTy, ivar_count);
18257330f729Sjoerg       // size_t size;
18267330f729Sjoerg       llvm::StructType *ObjCIvarTy = llvm::StructType::get(
18277330f729Sjoerg         PtrToInt8Ty,
18287330f729Sjoerg         PtrToInt8Ty,
18297330f729Sjoerg         PtrToInt8Ty,
18307330f729Sjoerg         Int32Ty,
18317330f729Sjoerg         Int32Ty);
18327330f729Sjoerg       ivarListBuilder.addInt(SizeTy, td.getTypeSizeInBits(ObjCIvarTy) /
18337330f729Sjoerg           CGM.getContext().getCharWidth());
18347330f729Sjoerg       // struct objc_ivar ivars[]
18357330f729Sjoerg       auto ivarArrayBuilder = ivarListBuilder.beginArray();
18367330f729Sjoerg       for (const ObjCIvarDecl *IVD = classDecl->all_declared_ivar_begin(); IVD;
18377330f729Sjoerg            IVD = IVD->getNextIvar()) {
18387330f729Sjoerg         auto ivarTy = IVD->getType();
18397330f729Sjoerg         auto ivarBuilder = ivarArrayBuilder.beginStruct();
18407330f729Sjoerg         // const char *name;
18417330f729Sjoerg         ivarBuilder.add(MakeConstantString(IVD->getNameAsString()));
18427330f729Sjoerg         // const char *type;
18437330f729Sjoerg         std::string TypeStr;
18447330f729Sjoerg         //Context.getObjCEncodingForType(ivarTy, TypeStr, IVD, true);
18457330f729Sjoerg         Context.getObjCEncodingForMethodParameter(Decl::OBJC_TQ_None, ivarTy, TypeStr, true);
18467330f729Sjoerg         ivarBuilder.add(MakeConstantString(TypeStr));
18477330f729Sjoerg         // int *offset;
18487330f729Sjoerg         uint64_t BaseOffset = ComputeIvarBaseOffset(CGM, OID, IVD);
18497330f729Sjoerg         uint64_t Offset = BaseOffset - superInstanceSize;
18507330f729Sjoerg         llvm::Constant *OffsetValue = llvm::ConstantInt::get(IntTy, Offset);
18517330f729Sjoerg         std::string OffsetName = GetIVarOffsetVariableName(classDecl, IVD);
18527330f729Sjoerg         llvm::GlobalVariable *OffsetVar = TheModule.getGlobalVariable(OffsetName);
18537330f729Sjoerg         if (OffsetVar)
18547330f729Sjoerg           OffsetVar->setInitializer(OffsetValue);
18557330f729Sjoerg         else
18567330f729Sjoerg           OffsetVar = new llvm::GlobalVariable(TheModule, IntTy,
18577330f729Sjoerg             false, llvm::GlobalValue::ExternalLinkage,
18587330f729Sjoerg             OffsetValue, OffsetName);
18597330f729Sjoerg         auto ivarVisibility =
18607330f729Sjoerg             (IVD->getAccessControl() == ObjCIvarDecl::Private ||
18617330f729Sjoerg              IVD->getAccessControl() == ObjCIvarDecl::Package ||
18627330f729Sjoerg              classDecl->getVisibility() == HiddenVisibility) ?
18637330f729Sjoerg                     llvm::GlobalValue::HiddenVisibility :
18647330f729Sjoerg                     llvm::GlobalValue::DefaultVisibility;
18657330f729Sjoerg         OffsetVar->setVisibility(ivarVisibility);
18667330f729Sjoerg         ivarBuilder.add(OffsetVar);
18677330f729Sjoerg         // Ivar size
18687330f729Sjoerg         ivarBuilder.addInt(Int32Ty,
18697330f729Sjoerg             CGM.getContext().getTypeSizeInChars(ivarTy).getQuantity());
18707330f729Sjoerg         // Alignment will be stored as a base-2 log of the alignment.
18717330f729Sjoerg         unsigned align =
18727330f729Sjoerg             llvm::Log2_32(Context.getTypeAlignInChars(ivarTy).getQuantity());
18737330f729Sjoerg         // Objects that require more than 2^64-byte alignment should be impossible!
18747330f729Sjoerg         assert(align < 64);
18757330f729Sjoerg         // uint32_t flags;
18767330f729Sjoerg         // Bits 0-1 are ownership.
18777330f729Sjoerg         // Bit 2 indicates an extended type encoding
18787330f729Sjoerg         // Bits 3-8 contain log2(aligment)
18797330f729Sjoerg         ivarBuilder.addInt(Int32Ty,
18807330f729Sjoerg             (align << 3) | (1<<2) |
18817330f729Sjoerg             FlagsForOwnership(ivarTy.getQualifiers().getObjCLifetime()));
18827330f729Sjoerg         ivarBuilder.finishAndAddTo(ivarArrayBuilder);
18837330f729Sjoerg       }
18847330f729Sjoerg       ivarArrayBuilder.finishAndAddTo(ivarListBuilder);
18857330f729Sjoerg       auto ivarList = ivarListBuilder.finishAndCreateGlobal(".objc_ivar_list",
18867330f729Sjoerg           CGM.getPointerAlign(), /*constant*/ false,
18877330f729Sjoerg           llvm::GlobalValue::PrivateLinkage);
18887330f729Sjoerg       classFields.add(ivarList);
18897330f729Sjoerg     }
18907330f729Sjoerg     // struct objc_method_list *methods
18917330f729Sjoerg     SmallVector<const ObjCMethodDecl*, 16> InstanceMethods;
18927330f729Sjoerg     InstanceMethods.insert(InstanceMethods.begin(), OID->instmeth_begin(),
18937330f729Sjoerg         OID->instmeth_end());
18947330f729Sjoerg     for (auto *propImpl : OID->property_impls())
18957330f729Sjoerg       if (propImpl->getPropertyImplementation() ==
18967330f729Sjoerg           ObjCPropertyImplDecl::Synthesize) {
18977330f729Sjoerg         auto addIfExists = [&](const ObjCMethodDecl *OMD) {
1898*e038c9c4Sjoerg           if (OMD && OMD->hasBody())
18997330f729Sjoerg             InstanceMethods.push_back(OMD);
19007330f729Sjoerg         };
1901*e038c9c4Sjoerg         addIfExists(propImpl->getGetterMethodDecl());
1902*e038c9c4Sjoerg         addIfExists(propImpl->getSetterMethodDecl());
19037330f729Sjoerg       }
19047330f729Sjoerg 
19057330f729Sjoerg     if (InstanceMethods.size() == 0)
19067330f729Sjoerg       classFields.addNullPointer(PtrTy);
19077330f729Sjoerg     else
19087330f729Sjoerg       classFields.addBitCast(
19097330f729Sjoerg               GenerateMethodList(className, "", InstanceMethods, false),
19107330f729Sjoerg               PtrTy);
19117330f729Sjoerg     // void *dtable;
19127330f729Sjoerg     classFields.addNullPointer(PtrTy);
19137330f729Sjoerg     // IMP cxx_construct;
19147330f729Sjoerg     classFields.addNullPointer(PtrTy);
19157330f729Sjoerg     // IMP cxx_destruct;
19167330f729Sjoerg     classFields.addNullPointer(PtrTy);
19177330f729Sjoerg     // struct objc_class *subclass_list
19187330f729Sjoerg     classFields.addNullPointer(PtrTy);
19197330f729Sjoerg     // struct objc_class *sibling_class
19207330f729Sjoerg     classFields.addNullPointer(PtrTy);
19217330f729Sjoerg     // struct objc_protocol_list *protocols;
1922*e038c9c4Sjoerg     auto RuntimeProtocols = GetRuntimeProtocolList(classDecl->protocol_begin(),
1923*e038c9c4Sjoerg                                                    classDecl->protocol_end());
19247330f729Sjoerg     SmallVector<llvm::Constant *, 16> Protocols;
1925*e038c9c4Sjoerg     for (const auto *I : RuntimeProtocols)
19267330f729Sjoerg       Protocols.push_back(
19277330f729Sjoerg           llvm::ConstantExpr::getBitCast(GenerateProtocolRef(I),
19287330f729Sjoerg             ProtocolPtrTy));
19297330f729Sjoerg     if (Protocols.empty())
19307330f729Sjoerg       classFields.addNullPointer(PtrTy);
19317330f729Sjoerg     else
19327330f729Sjoerg       classFields.add(GenerateProtocolList(Protocols));
19337330f729Sjoerg     // struct reference_list *extra_data;
19347330f729Sjoerg     classFields.addNullPointer(PtrTy);
19357330f729Sjoerg     // long abi_version;
19367330f729Sjoerg     classFields.addInt(LongTy, 0);
19377330f729Sjoerg     // struct objc_property_list *properties
19387330f729Sjoerg     classFields.add(GeneratePropertyList(OID, classDecl));
19397330f729Sjoerg 
19407330f729Sjoerg     auto *classStruct =
19417330f729Sjoerg       classFields.finishAndCreateGlobal(SymbolForClass(className),
19427330f729Sjoerg         CGM.getPointerAlign(), false, llvm::GlobalValue::ExternalLinkage);
19437330f729Sjoerg 
19447330f729Sjoerg     auto *classRefSymbol = GetClassVar(className);
19457330f729Sjoerg     classRefSymbol->setSection(sectionName<ClassReferenceSection>());
19467330f729Sjoerg     classRefSymbol->setInitializer(llvm::ConstantExpr::getBitCast(classStruct, IdTy));
19477330f729Sjoerg 
19487330f729Sjoerg     if (IsCOFF) {
19497330f729Sjoerg       // we can't import a class struct.
19507330f729Sjoerg       if (OID->getClassInterface()->hasAttr<DLLExportAttr>()) {
19517330f729Sjoerg         cast<llvm::GlobalValue>(classStruct)->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
19527330f729Sjoerg         cast<llvm::GlobalValue>(classRefSymbol)->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
19537330f729Sjoerg       }
19547330f729Sjoerg 
19557330f729Sjoerg       if (SuperClass) {
19567330f729Sjoerg         std::pair<llvm::Constant*, int> v{classStruct, 1};
1957*e038c9c4Sjoerg         EarlyInitList.emplace_back(std::string(SuperClass->getName()),
1958*e038c9c4Sjoerg                                    std::move(v));
19597330f729Sjoerg       }
19607330f729Sjoerg 
19617330f729Sjoerg     }
19627330f729Sjoerg 
19637330f729Sjoerg 
19647330f729Sjoerg     // Resolve the class aliases, if they exist.
19657330f729Sjoerg     // FIXME: Class pointer aliases shouldn't exist!
19667330f729Sjoerg     if (ClassPtrAlias) {
19677330f729Sjoerg       ClassPtrAlias->replaceAllUsesWith(
19687330f729Sjoerg           llvm::ConstantExpr::getBitCast(classStruct, IdTy));
19697330f729Sjoerg       ClassPtrAlias->eraseFromParent();
19707330f729Sjoerg       ClassPtrAlias = nullptr;
19717330f729Sjoerg     }
19727330f729Sjoerg     if (auto Placeholder =
19737330f729Sjoerg         TheModule.getNamedGlobal(SymbolForClass(className)))
19747330f729Sjoerg       if (Placeholder != classStruct) {
19757330f729Sjoerg         Placeholder->replaceAllUsesWith(
19767330f729Sjoerg             llvm::ConstantExpr::getBitCast(classStruct, Placeholder->getType()));
19777330f729Sjoerg         Placeholder->eraseFromParent();
19787330f729Sjoerg         classStruct->setName(SymbolForClass(className));
19797330f729Sjoerg       }
19807330f729Sjoerg     if (MetaClassPtrAlias) {
19817330f729Sjoerg       MetaClassPtrAlias->replaceAllUsesWith(
19827330f729Sjoerg           llvm::ConstantExpr::getBitCast(metaclass, IdTy));
19837330f729Sjoerg       MetaClassPtrAlias->eraseFromParent();
19847330f729Sjoerg       MetaClassPtrAlias = nullptr;
19857330f729Sjoerg     }
19867330f729Sjoerg     assert(classStruct->getName() == SymbolForClass(className));
19877330f729Sjoerg 
19887330f729Sjoerg     auto classInitRef = new llvm::GlobalVariable(TheModule,
19897330f729Sjoerg         classStruct->getType(), false, llvm::GlobalValue::ExternalLinkage,
19907330f729Sjoerg         classStruct, ManglePublicSymbol("OBJC_INIT_CLASS_") + className);
19917330f729Sjoerg     classInitRef->setSection(sectionName<ClassSection>());
19927330f729Sjoerg     CGM.addUsedGlobal(classInitRef);
19937330f729Sjoerg 
19947330f729Sjoerg     EmittedClass = true;
19957330f729Sjoerg   }
19967330f729Sjoerg   public:
CGObjCGNUstep2(CodeGenModule & Mod)19977330f729Sjoerg     CGObjCGNUstep2(CodeGenModule &Mod) : CGObjCGNUstep(Mod, 10, 4, 2) {
19987330f729Sjoerg       MsgLookupSuperFn.init(&CGM, "objc_msg_lookup_super", IMPTy,
19997330f729Sjoerg                             PtrToObjCSuperTy, SelectorTy);
20007330f729Sjoerg       // struct objc_property
20017330f729Sjoerg       // {
20027330f729Sjoerg       //   const char *name;
20037330f729Sjoerg       //   const char *attributes;
20047330f729Sjoerg       //   const char *type;
20057330f729Sjoerg       //   SEL getter;
20067330f729Sjoerg       //   SEL setter;
20077330f729Sjoerg       // }
20087330f729Sjoerg       PropertyMetadataTy =
20097330f729Sjoerg         llvm::StructType::get(CGM.getLLVMContext(),
20107330f729Sjoerg             { PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty });
20117330f729Sjoerg     }
20127330f729Sjoerg 
20137330f729Sjoerg };
20147330f729Sjoerg 
20157330f729Sjoerg const char *const CGObjCGNUstep2::SectionsBaseNames[8] =
20167330f729Sjoerg {
20177330f729Sjoerg "__objc_selectors",
20187330f729Sjoerg "__objc_classes",
20197330f729Sjoerg "__objc_class_refs",
20207330f729Sjoerg "__objc_cats",
20217330f729Sjoerg "__objc_protocols",
20227330f729Sjoerg "__objc_protocol_refs",
20237330f729Sjoerg "__objc_class_aliases",
20247330f729Sjoerg "__objc_constant_string"
20257330f729Sjoerg };
20267330f729Sjoerg 
20277330f729Sjoerg const char *const CGObjCGNUstep2::PECOFFSectionsBaseNames[8] =
20287330f729Sjoerg {
20297330f729Sjoerg ".objcrt$SEL",
20307330f729Sjoerg ".objcrt$CLS",
20317330f729Sjoerg ".objcrt$CLR",
20327330f729Sjoerg ".objcrt$CAT",
20337330f729Sjoerg ".objcrt$PCL",
20347330f729Sjoerg ".objcrt$PCR",
20357330f729Sjoerg ".objcrt$CAL",
20367330f729Sjoerg ".objcrt$STR"
20377330f729Sjoerg };
20387330f729Sjoerg 
20397330f729Sjoerg /// Support for the ObjFW runtime.
20407330f729Sjoerg class CGObjCObjFW: public CGObjCGNU {
20417330f729Sjoerg protected:
20427330f729Sjoerg   /// The GCC ABI message lookup function.  Returns an IMP pointing to the
20437330f729Sjoerg   /// method implementation for this message.
20447330f729Sjoerg   LazyRuntimeFunction MsgLookupFn;
20457330f729Sjoerg   /// stret lookup function.  While this does not seem to make sense at the
20467330f729Sjoerg   /// first look, this is required to call the correct forwarding function.
20477330f729Sjoerg   LazyRuntimeFunction MsgLookupFnSRet;
20487330f729Sjoerg   /// The GCC ABI superclass message lookup function.  Takes a pointer to a
20497330f729Sjoerg   /// structure describing the receiver and the class, and a selector as
20507330f729Sjoerg   /// arguments.  Returns the IMP for the corresponding method.
20517330f729Sjoerg   LazyRuntimeFunction MsgLookupSuperFn, MsgLookupSuperFnSRet;
20527330f729Sjoerg 
LookupIMP(CodeGenFunction & CGF,llvm::Value * & Receiver,llvm::Value * cmd,llvm::MDNode * node,MessageSendInfo & MSI)20537330f729Sjoerg   llvm::Value *LookupIMP(CodeGenFunction &CGF, llvm::Value *&Receiver,
20547330f729Sjoerg                          llvm::Value *cmd, llvm::MDNode *node,
20557330f729Sjoerg                          MessageSendInfo &MSI) override {
20567330f729Sjoerg     CGBuilderTy &Builder = CGF.Builder;
20577330f729Sjoerg     llvm::Value *args[] = {
20587330f729Sjoerg             EnforceType(Builder, Receiver, IdTy),
20597330f729Sjoerg             EnforceType(Builder, cmd, SelectorTy) };
20607330f729Sjoerg 
20617330f729Sjoerg     llvm::CallBase *imp;
20627330f729Sjoerg     if (CGM.ReturnTypeUsesSRet(MSI.CallInfo))
20637330f729Sjoerg       imp = CGF.EmitRuntimeCallOrInvoke(MsgLookupFnSRet, args);
20647330f729Sjoerg     else
20657330f729Sjoerg       imp = CGF.EmitRuntimeCallOrInvoke(MsgLookupFn, args);
20667330f729Sjoerg 
20677330f729Sjoerg     imp->setMetadata(msgSendMDKind, node);
20687330f729Sjoerg     return imp;
20697330f729Sjoerg   }
20707330f729Sjoerg 
LookupIMPSuper(CodeGenFunction & CGF,Address ObjCSuper,llvm::Value * cmd,MessageSendInfo & MSI)20717330f729Sjoerg   llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper,
20727330f729Sjoerg                               llvm::Value *cmd, MessageSendInfo &MSI) override {
20737330f729Sjoerg     CGBuilderTy &Builder = CGF.Builder;
20747330f729Sjoerg     llvm::Value *lookupArgs[] = {
20757330f729Sjoerg         EnforceType(Builder, ObjCSuper.getPointer(), PtrToObjCSuperTy), cmd,
20767330f729Sjoerg     };
20777330f729Sjoerg 
20787330f729Sjoerg     if (CGM.ReturnTypeUsesSRet(MSI.CallInfo))
20797330f729Sjoerg       return CGF.EmitNounwindRuntimeCall(MsgLookupSuperFnSRet, lookupArgs);
20807330f729Sjoerg     else
20817330f729Sjoerg       return CGF.EmitNounwindRuntimeCall(MsgLookupSuperFn, lookupArgs);
20827330f729Sjoerg   }
20837330f729Sjoerg 
GetClassNamed(CodeGenFunction & CGF,const std::string & Name,bool isWeak)20847330f729Sjoerg   llvm::Value *GetClassNamed(CodeGenFunction &CGF, const std::string &Name,
20857330f729Sjoerg                              bool isWeak) override {
20867330f729Sjoerg     if (isWeak)
20877330f729Sjoerg       return CGObjCGNU::GetClassNamed(CGF, Name, isWeak);
20887330f729Sjoerg 
20897330f729Sjoerg     EmitClassRef(Name);
20907330f729Sjoerg     std::string SymbolName = "_OBJC_CLASS_" + Name;
20917330f729Sjoerg     llvm::GlobalVariable *ClassSymbol = TheModule.getGlobalVariable(SymbolName);
20927330f729Sjoerg     if (!ClassSymbol)
20937330f729Sjoerg       ClassSymbol = new llvm::GlobalVariable(TheModule, LongTy, false,
20947330f729Sjoerg                                              llvm::GlobalValue::ExternalLinkage,
20957330f729Sjoerg                                              nullptr, SymbolName);
20967330f729Sjoerg     return ClassSymbol;
20977330f729Sjoerg   }
20987330f729Sjoerg 
20997330f729Sjoerg public:
CGObjCObjFW(CodeGenModule & Mod)21007330f729Sjoerg   CGObjCObjFW(CodeGenModule &Mod): CGObjCGNU(Mod, 9, 3) {
21017330f729Sjoerg     // IMP objc_msg_lookup(id, SEL);
21027330f729Sjoerg     MsgLookupFn.init(&CGM, "objc_msg_lookup", IMPTy, IdTy, SelectorTy);
21037330f729Sjoerg     MsgLookupFnSRet.init(&CGM, "objc_msg_lookup_stret", IMPTy, IdTy,
21047330f729Sjoerg                          SelectorTy);
21057330f729Sjoerg     // IMP objc_msg_lookup_super(struct objc_super*, SEL);
21067330f729Sjoerg     MsgLookupSuperFn.init(&CGM, "objc_msg_lookup_super", IMPTy,
21077330f729Sjoerg                           PtrToObjCSuperTy, SelectorTy);
21087330f729Sjoerg     MsgLookupSuperFnSRet.init(&CGM, "objc_msg_lookup_super_stret", IMPTy,
21097330f729Sjoerg                               PtrToObjCSuperTy, SelectorTy);
21107330f729Sjoerg   }
21117330f729Sjoerg };
21127330f729Sjoerg } // end anonymous namespace
21137330f729Sjoerg 
21147330f729Sjoerg /// Emits a reference to a dummy variable which is emitted with each class.
21157330f729Sjoerg /// This ensures that a linker error will be generated when trying to link
21167330f729Sjoerg /// together modules where a referenced class is not defined.
EmitClassRef(const std::string & className)21177330f729Sjoerg void CGObjCGNU::EmitClassRef(const std::string &className) {
21187330f729Sjoerg   std::string symbolRef = "__objc_class_ref_" + className;
21197330f729Sjoerg   // Don't emit two copies of the same symbol
21207330f729Sjoerg   if (TheModule.getGlobalVariable(symbolRef))
21217330f729Sjoerg     return;
21227330f729Sjoerg   std::string symbolName = "__objc_class_name_" + className;
21237330f729Sjoerg   llvm::GlobalVariable *ClassSymbol = TheModule.getGlobalVariable(symbolName);
21247330f729Sjoerg   if (!ClassSymbol) {
21257330f729Sjoerg     ClassSymbol = new llvm::GlobalVariable(TheModule, LongTy, false,
21267330f729Sjoerg                                            llvm::GlobalValue::ExternalLinkage,
21277330f729Sjoerg                                            nullptr, symbolName);
21287330f729Sjoerg   }
21297330f729Sjoerg   new llvm::GlobalVariable(TheModule, ClassSymbol->getType(), true,
21307330f729Sjoerg     llvm::GlobalValue::WeakAnyLinkage, ClassSymbol, symbolRef);
21317330f729Sjoerg }
21327330f729Sjoerg 
CGObjCGNU(CodeGenModule & cgm,unsigned runtimeABIVersion,unsigned protocolClassVersion,unsigned classABI)21337330f729Sjoerg CGObjCGNU::CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion,
21347330f729Sjoerg                      unsigned protocolClassVersion, unsigned classABI)
21357330f729Sjoerg   : CGObjCRuntime(cgm), TheModule(CGM.getModule()),
21367330f729Sjoerg     VMContext(cgm.getLLVMContext()), ClassPtrAlias(nullptr),
21377330f729Sjoerg     MetaClassPtrAlias(nullptr), RuntimeVersion(runtimeABIVersion),
21387330f729Sjoerg     ProtocolVersion(protocolClassVersion), ClassABIVersion(classABI) {
21397330f729Sjoerg 
21407330f729Sjoerg   msgSendMDKind = VMContext.getMDKindID("GNUObjCMessageSend");
21417330f729Sjoerg   usesSEHExceptions =
21427330f729Sjoerg       cgm.getContext().getTargetInfo().getTriple().isWindowsMSVCEnvironment();
21437330f729Sjoerg 
21447330f729Sjoerg   CodeGenTypes &Types = CGM.getTypes();
21457330f729Sjoerg   IntTy = cast<llvm::IntegerType>(
21467330f729Sjoerg       Types.ConvertType(CGM.getContext().IntTy));
21477330f729Sjoerg   LongTy = cast<llvm::IntegerType>(
21487330f729Sjoerg       Types.ConvertType(CGM.getContext().LongTy));
21497330f729Sjoerg   SizeTy = cast<llvm::IntegerType>(
21507330f729Sjoerg       Types.ConvertType(CGM.getContext().getSizeType()));
21517330f729Sjoerg   PtrDiffTy = cast<llvm::IntegerType>(
21527330f729Sjoerg       Types.ConvertType(CGM.getContext().getPointerDiffType()));
21537330f729Sjoerg   BoolTy = CGM.getTypes().ConvertType(CGM.getContext().BoolTy);
21547330f729Sjoerg 
21557330f729Sjoerg   Int8Ty = llvm::Type::getInt8Ty(VMContext);
21567330f729Sjoerg   // C string type.  Used in lots of places.
21577330f729Sjoerg   PtrToInt8Ty = llvm::PointerType::getUnqual(Int8Ty);
21587330f729Sjoerg   ProtocolPtrTy = llvm::PointerType::getUnqual(
21597330f729Sjoerg       Types.ConvertType(CGM.getContext().getObjCProtoType()));
21607330f729Sjoerg 
21617330f729Sjoerg   Zeros[0] = llvm::ConstantInt::get(LongTy, 0);
21627330f729Sjoerg   Zeros[1] = Zeros[0];
21637330f729Sjoerg   NULLPtr = llvm::ConstantPointerNull::get(PtrToInt8Ty);
21647330f729Sjoerg   // Get the selector Type.
21657330f729Sjoerg   QualType selTy = CGM.getContext().getObjCSelType();
21667330f729Sjoerg   if (QualType() == selTy) {
21677330f729Sjoerg     SelectorTy = PtrToInt8Ty;
21687330f729Sjoerg   } else {
21697330f729Sjoerg     SelectorTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(selTy));
21707330f729Sjoerg   }
21717330f729Sjoerg 
21727330f729Sjoerg   PtrToIntTy = llvm::PointerType::getUnqual(IntTy);
21737330f729Sjoerg   PtrTy = PtrToInt8Ty;
21747330f729Sjoerg 
21757330f729Sjoerg   Int32Ty = llvm::Type::getInt32Ty(VMContext);
21767330f729Sjoerg   Int64Ty = llvm::Type::getInt64Ty(VMContext);
21777330f729Sjoerg 
21787330f729Sjoerg   IntPtrTy =
21797330f729Sjoerg       CGM.getDataLayout().getPointerSizeInBits() == 32 ? Int32Ty : Int64Ty;
21807330f729Sjoerg 
21817330f729Sjoerg   // Object type
21827330f729Sjoerg   QualType UnqualIdTy = CGM.getContext().getObjCIdType();
21837330f729Sjoerg   ASTIdTy = CanQualType();
21847330f729Sjoerg   if (UnqualIdTy != QualType()) {
21857330f729Sjoerg     ASTIdTy = CGM.getContext().getCanonicalType(UnqualIdTy);
21867330f729Sjoerg     IdTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(ASTIdTy));
21877330f729Sjoerg   } else {
21887330f729Sjoerg     IdTy = PtrToInt8Ty;
21897330f729Sjoerg   }
21907330f729Sjoerg   PtrToIdTy = llvm::PointerType::getUnqual(IdTy);
21917330f729Sjoerg   ProtocolTy = llvm::StructType::get(IdTy,
21927330f729Sjoerg       PtrToInt8Ty, // name
21937330f729Sjoerg       PtrToInt8Ty, // protocols
21947330f729Sjoerg       PtrToInt8Ty, // instance methods
21957330f729Sjoerg       PtrToInt8Ty, // class methods
21967330f729Sjoerg       PtrToInt8Ty, // optional instance methods
21977330f729Sjoerg       PtrToInt8Ty, // optional class methods
21987330f729Sjoerg       PtrToInt8Ty, // properties
21997330f729Sjoerg       PtrToInt8Ty);// optional properties
22007330f729Sjoerg 
22017330f729Sjoerg   // struct objc_property_gsv1
22027330f729Sjoerg   // {
22037330f729Sjoerg   //   const char *name;
22047330f729Sjoerg   //   char attributes;
22057330f729Sjoerg   //   char attributes2;
22067330f729Sjoerg   //   char unused1;
22077330f729Sjoerg   //   char unused2;
22087330f729Sjoerg   //   const char *getter_name;
22097330f729Sjoerg   //   const char *getter_types;
22107330f729Sjoerg   //   const char *setter_name;
22117330f729Sjoerg   //   const char *setter_types;
22127330f729Sjoerg   // }
22137330f729Sjoerg   PropertyMetadataTy = llvm::StructType::get(CGM.getLLVMContext(), {
22147330f729Sjoerg       PtrToInt8Ty, Int8Ty, Int8Ty, Int8Ty, Int8Ty, PtrToInt8Ty, PtrToInt8Ty,
22157330f729Sjoerg       PtrToInt8Ty, PtrToInt8Ty });
22167330f729Sjoerg 
22177330f729Sjoerg   ObjCSuperTy = llvm::StructType::get(IdTy, IdTy);
22187330f729Sjoerg   PtrToObjCSuperTy = llvm::PointerType::getUnqual(ObjCSuperTy);
22197330f729Sjoerg 
22207330f729Sjoerg   llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
22217330f729Sjoerg 
22227330f729Sjoerg   // void objc_exception_throw(id);
22237330f729Sjoerg   ExceptionThrowFn.init(&CGM, "objc_exception_throw", VoidTy, IdTy);
22247330f729Sjoerg   ExceptionReThrowFn.init(&CGM, "objc_exception_throw", VoidTy, IdTy);
22257330f729Sjoerg   // int objc_sync_enter(id);
22267330f729Sjoerg   SyncEnterFn.init(&CGM, "objc_sync_enter", IntTy, IdTy);
22277330f729Sjoerg   // int objc_sync_exit(id);
22287330f729Sjoerg   SyncExitFn.init(&CGM, "objc_sync_exit", IntTy, IdTy);
22297330f729Sjoerg 
22307330f729Sjoerg   // void objc_enumerationMutation (id)
22317330f729Sjoerg   EnumerationMutationFn.init(&CGM, "objc_enumerationMutation", VoidTy, IdTy);
22327330f729Sjoerg 
22337330f729Sjoerg   // id objc_getProperty(id, SEL, ptrdiff_t, BOOL)
22347330f729Sjoerg   GetPropertyFn.init(&CGM, "objc_getProperty", IdTy, IdTy, SelectorTy,
22357330f729Sjoerg                      PtrDiffTy, BoolTy);
22367330f729Sjoerg   // void objc_setProperty(id, SEL, ptrdiff_t, id, BOOL, BOOL)
22377330f729Sjoerg   SetPropertyFn.init(&CGM, "objc_setProperty", VoidTy, IdTy, SelectorTy,
22387330f729Sjoerg                      PtrDiffTy, IdTy, BoolTy, BoolTy);
22397330f729Sjoerg   // void objc_setPropertyStruct(void*, void*, ptrdiff_t, BOOL, BOOL)
22407330f729Sjoerg   GetStructPropertyFn.init(&CGM, "objc_getPropertyStruct", VoidTy, PtrTy, PtrTy,
22417330f729Sjoerg                            PtrDiffTy, BoolTy, BoolTy);
22427330f729Sjoerg   // void objc_setPropertyStruct(void*, void*, ptrdiff_t, BOOL, BOOL)
22437330f729Sjoerg   SetStructPropertyFn.init(&CGM, "objc_setPropertyStruct", VoidTy, PtrTy, PtrTy,
22447330f729Sjoerg                            PtrDiffTy, BoolTy, BoolTy);
22457330f729Sjoerg 
22467330f729Sjoerg   // IMP type
22477330f729Sjoerg   llvm::Type *IMPArgs[] = { IdTy, SelectorTy };
22487330f729Sjoerg   IMPTy = llvm::PointerType::getUnqual(llvm::FunctionType::get(IdTy, IMPArgs,
22497330f729Sjoerg               true));
22507330f729Sjoerg 
22517330f729Sjoerg   const LangOptions &Opts = CGM.getLangOpts();
22527330f729Sjoerg   if ((Opts.getGC() != LangOptions::NonGC) || Opts.ObjCAutoRefCount)
22537330f729Sjoerg     RuntimeVersion = 10;
22547330f729Sjoerg 
22557330f729Sjoerg   // Don't bother initialising the GC stuff unless we're compiling in GC mode
22567330f729Sjoerg   if (Opts.getGC() != LangOptions::NonGC) {
22577330f729Sjoerg     // This is a bit of an hack.  We should sort this out by having a proper
22587330f729Sjoerg     // CGObjCGNUstep subclass for GC, but we may want to really support the old
22597330f729Sjoerg     // ABI and GC added in ObjectiveC2.framework, so we fudge it a bit for now
22607330f729Sjoerg     // Get selectors needed in GC mode
22617330f729Sjoerg     RetainSel = GetNullarySelector("retain", CGM.getContext());
22627330f729Sjoerg     ReleaseSel = GetNullarySelector("release", CGM.getContext());
22637330f729Sjoerg     AutoreleaseSel = GetNullarySelector("autorelease", CGM.getContext());
22647330f729Sjoerg 
22657330f729Sjoerg     // Get functions needed in GC mode
22667330f729Sjoerg 
22677330f729Sjoerg     // id objc_assign_ivar(id, id, ptrdiff_t);
22687330f729Sjoerg     IvarAssignFn.init(&CGM, "objc_assign_ivar", IdTy, IdTy, IdTy, PtrDiffTy);
22697330f729Sjoerg     // id objc_assign_strongCast (id, id*)
22707330f729Sjoerg     StrongCastAssignFn.init(&CGM, "objc_assign_strongCast", IdTy, IdTy,
22717330f729Sjoerg                             PtrToIdTy);
22727330f729Sjoerg     // id objc_assign_global(id, id*);
22737330f729Sjoerg     GlobalAssignFn.init(&CGM, "objc_assign_global", IdTy, IdTy, PtrToIdTy);
22747330f729Sjoerg     // id objc_assign_weak(id, id*);
22757330f729Sjoerg     WeakAssignFn.init(&CGM, "objc_assign_weak", IdTy, IdTy, PtrToIdTy);
22767330f729Sjoerg     // id objc_read_weak(id*);
22777330f729Sjoerg     WeakReadFn.init(&CGM, "objc_read_weak", IdTy, PtrToIdTy);
22787330f729Sjoerg     // void *objc_memmove_collectable(void*, void *, size_t);
22797330f729Sjoerg     MemMoveFn.init(&CGM, "objc_memmove_collectable", PtrTy, PtrTy, PtrTy,
22807330f729Sjoerg                    SizeTy);
22817330f729Sjoerg   }
22827330f729Sjoerg }
22837330f729Sjoerg 
GetClassNamed(CodeGenFunction & CGF,const std::string & Name,bool isWeak)22847330f729Sjoerg llvm::Value *CGObjCGNU::GetClassNamed(CodeGenFunction &CGF,
22857330f729Sjoerg                                       const std::string &Name, bool isWeak) {
22867330f729Sjoerg   llvm::Constant *ClassName = MakeConstantString(Name);
22877330f729Sjoerg   // With the incompatible ABI, this will need to be replaced with a direct
22887330f729Sjoerg   // reference to the class symbol.  For the compatible nonfragile ABI we are
22897330f729Sjoerg   // still performing this lookup at run time but emitting the symbol for the
22907330f729Sjoerg   // class externally so that we can make the switch later.
22917330f729Sjoerg   //
22927330f729Sjoerg   // Libobjc2 contains an LLVM pass that replaces calls to objc_lookup_class
22937330f729Sjoerg   // with memoized versions or with static references if it's safe to do so.
22947330f729Sjoerg   if (!isWeak)
22957330f729Sjoerg     EmitClassRef(Name);
22967330f729Sjoerg 
22977330f729Sjoerg   llvm::FunctionCallee ClassLookupFn = CGM.CreateRuntimeFunction(
22987330f729Sjoerg       llvm::FunctionType::get(IdTy, PtrToInt8Ty, true), "objc_lookup_class");
22997330f729Sjoerg   return CGF.EmitNounwindRuntimeCall(ClassLookupFn, ClassName);
23007330f729Sjoerg }
23017330f729Sjoerg 
23027330f729Sjoerg // This has to perform the lookup every time, since posing and related
23037330f729Sjoerg // techniques can modify the name -> class mapping.
GetClass(CodeGenFunction & CGF,const ObjCInterfaceDecl * OID)23047330f729Sjoerg llvm::Value *CGObjCGNU::GetClass(CodeGenFunction &CGF,
23057330f729Sjoerg                                  const ObjCInterfaceDecl *OID) {
23067330f729Sjoerg   auto *Value =
23077330f729Sjoerg       GetClassNamed(CGF, OID->getNameAsString(), OID->isWeakImported());
23087330f729Sjoerg   if (auto *ClassSymbol = dyn_cast<llvm::GlobalVariable>(Value))
23097330f729Sjoerg     CGM.setGVProperties(ClassSymbol, OID);
23107330f729Sjoerg   return Value;
23117330f729Sjoerg }
23127330f729Sjoerg 
EmitNSAutoreleasePoolClassRef(CodeGenFunction & CGF)23137330f729Sjoerg llvm::Value *CGObjCGNU::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
23147330f729Sjoerg   auto *Value  = GetClassNamed(CGF, "NSAutoreleasePool", false);
23157330f729Sjoerg   if (CGM.getTriple().isOSBinFormatCOFF()) {
23167330f729Sjoerg     if (auto *ClassSymbol = dyn_cast<llvm::GlobalVariable>(Value)) {
23177330f729Sjoerg       IdentifierInfo &II = CGF.CGM.getContext().Idents.get("NSAutoreleasePool");
23187330f729Sjoerg       TranslationUnitDecl *TUDecl = CGM.getContext().getTranslationUnitDecl();
23197330f729Sjoerg       DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
23207330f729Sjoerg 
23217330f729Sjoerg       const VarDecl *VD = nullptr;
2322*e038c9c4Sjoerg       for (const auto *Result : DC->lookup(&II))
23237330f729Sjoerg         if ((VD = dyn_cast<VarDecl>(Result)))
23247330f729Sjoerg           break;
23257330f729Sjoerg 
23267330f729Sjoerg       CGM.setGVProperties(ClassSymbol, VD);
23277330f729Sjoerg     }
23287330f729Sjoerg   }
23297330f729Sjoerg   return Value;
23307330f729Sjoerg }
23317330f729Sjoerg 
GetTypedSelector(CodeGenFunction & CGF,Selector Sel,const std::string & TypeEncoding)23327330f729Sjoerg llvm::Value *CGObjCGNU::GetTypedSelector(CodeGenFunction &CGF, Selector Sel,
23337330f729Sjoerg                                          const std::string &TypeEncoding) {
23347330f729Sjoerg   SmallVectorImpl<TypedSelector> &Types = SelectorTable[Sel];
23357330f729Sjoerg   llvm::GlobalAlias *SelValue = nullptr;
23367330f729Sjoerg 
23377330f729Sjoerg   for (SmallVectorImpl<TypedSelector>::iterator i = Types.begin(),
23387330f729Sjoerg       e = Types.end() ; i!=e ; i++) {
23397330f729Sjoerg     if (i->first == TypeEncoding) {
23407330f729Sjoerg       SelValue = i->second;
23417330f729Sjoerg       break;
23427330f729Sjoerg     }
23437330f729Sjoerg   }
23447330f729Sjoerg   if (!SelValue) {
23457330f729Sjoerg     SelValue = llvm::GlobalAlias::create(
23467330f729Sjoerg         SelectorTy->getElementType(), 0, llvm::GlobalValue::PrivateLinkage,
23477330f729Sjoerg         ".objc_selector_" + Sel.getAsString(), &TheModule);
23487330f729Sjoerg     Types.emplace_back(TypeEncoding, SelValue);
23497330f729Sjoerg   }
23507330f729Sjoerg 
23517330f729Sjoerg   return SelValue;
23527330f729Sjoerg }
23537330f729Sjoerg 
GetAddrOfSelector(CodeGenFunction & CGF,Selector Sel)23547330f729Sjoerg Address CGObjCGNU::GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) {
23557330f729Sjoerg   llvm::Value *SelValue = GetSelector(CGF, Sel);
23567330f729Sjoerg 
23577330f729Sjoerg   // Store it to a temporary.  Does this satisfy the semantics of
23587330f729Sjoerg   // GetAddrOfSelector?  Hopefully.
23597330f729Sjoerg   Address tmp = CGF.CreateTempAlloca(SelValue->getType(),
23607330f729Sjoerg                                      CGF.getPointerAlign());
23617330f729Sjoerg   CGF.Builder.CreateStore(SelValue, tmp);
23627330f729Sjoerg   return tmp;
23637330f729Sjoerg }
23647330f729Sjoerg 
GetSelector(CodeGenFunction & CGF,Selector Sel)23657330f729Sjoerg llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF, Selector Sel) {
23667330f729Sjoerg   return GetTypedSelector(CGF, Sel, std::string());
23677330f729Sjoerg }
23687330f729Sjoerg 
GetSelector(CodeGenFunction & CGF,const ObjCMethodDecl * Method)23697330f729Sjoerg llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF,
23707330f729Sjoerg                                     const ObjCMethodDecl *Method) {
23717330f729Sjoerg   std::string SelTypes = CGM.getContext().getObjCEncodingForMethodDecl(Method);
23727330f729Sjoerg   return GetTypedSelector(CGF, Method->getSelector(), SelTypes);
23737330f729Sjoerg }
23747330f729Sjoerg 
GetEHType(QualType T)23757330f729Sjoerg llvm::Constant *CGObjCGNU::GetEHType(QualType T) {
23767330f729Sjoerg   if (T->isObjCIdType() || T->isObjCQualifiedIdType()) {
23777330f729Sjoerg     // With the old ABI, there was only one kind of catchall, which broke
23787330f729Sjoerg     // foreign exceptions.  With the new ABI, we use __objc_id_typeinfo as
23797330f729Sjoerg     // a pointer indicating object catchalls, and NULL to indicate real
23807330f729Sjoerg     // catchalls
23817330f729Sjoerg     if (CGM.getLangOpts().ObjCRuntime.isNonFragile()) {
23827330f729Sjoerg       return MakeConstantString("@id");
23837330f729Sjoerg     } else {
23847330f729Sjoerg       return nullptr;
23857330f729Sjoerg     }
23867330f729Sjoerg   }
23877330f729Sjoerg 
23887330f729Sjoerg   // All other types should be Objective-C interface pointer types.
23897330f729Sjoerg   const ObjCObjectPointerType *OPT = T->getAs<ObjCObjectPointerType>();
23907330f729Sjoerg   assert(OPT && "Invalid @catch type.");
23917330f729Sjoerg   const ObjCInterfaceDecl *IDecl = OPT->getObjectType()->getInterface();
23927330f729Sjoerg   assert(IDecl && "Invalid @catch type.");
23937330f729Sjoerg   return MakeConstantString(IDecl->getIdentifier()->getName());
23947330f729Sjoerg }
23957330f729Sjoerg 
GetEHType(QualType T)23967330f729Sjoerg llvm::Constant *CGObjCGNUstep::GetEHType(QualType T) {
23977330f729Sjoerg   if (usesSEHExceptions)
23987330f729Sjoerg     return CGM.getCXXABI().getAddrOfRTTIDescriptor(T);
23997330f729Sjoerg 
24007330f729Sjoerg   if (!CGM.getLangOpts().CPlusPlus)
24017330f729Sjoerg     return CGObjCGNU::GetEHType(T);
24027330f729Sjoerg 
24037330f729Sjoerg   // For Objective-C++, we want to provide the ability to catch both C++ and
24047330f729Sjoerg   // Objective-C objects in the same function.
24057330f729Sjoerg 
24067330f729Sjoerg   // There's a particular fixed type info for 'id'.
24077330f729Sjoerg   if (T->isObjCIdType() ||
24087330f729Sjoerg       T->isObjCQualifiedIdType()) {
24097330f729Sjoerg     llvm::Constant *IDEHType =
24107330f729Sjoerg       CGM.getModule().getGlobalVariable("__objc_id_type_info");
24117330f729Sjoerg     if (!IDEHType)
24127330f729Sjoerg       IDEHType =
24137330f729Sjoerg         new llvm::GlobalVariable(CGM.getModule(), PtrToInt8Ty,
24147330f729Sjoerg                                  false,
24157330f729Sjoerg                                  llvm::GlobalValue::ExternalLinkage,
24167330f729Sjoerg                                  nullptr, "__objc_id_type_info");
24177330f729Sjoerg     return llvm::ConstantExpr::getBitCast(IDEHType, PtrToInt8Ty);
24187330f729Sjoerg   }
24197330f729Sjoerg 
24207330f729Sjoerg   const ObjCObjectPointerType *PT =
24217330f729Sjoerg     T->getAs<ObjCObjectPointerType>();
24227330f729Sjoerg   assert(PT && "Invalid @catch type.");
24237330f729Sjoerg   const ObjCInterfaceType *IT = PT->getInterfaceType();
24247330f729Sjoerg   assert(IT && "Invalid @catch type.");
2425*e038c9c4Sjoerg   std::string className =
2426*e038c9c4Sjoerg       std::string(IT->getDecl()->getIdentifier()->getName());
24277330f729Sjoerg 
24287330f729Sjoerg   std::string typeinfoName = "__objc_eh_typeinfo_" + className;
24297330f729Sjoerg 
24307330f729Sjoerg   // Return the existing typeinfo if it exists
24317330f729Sjoerg   llvm::Constant *typeinfo = TheModule.getGlobalVariable(typeinfoName);
24327330f729Sjoerg   if (typeinfo)
24337330f729Sjoerg     return llvm::ConstantExpr::getBitCast(typeinfo, PtrToInt8Ty);
24347330f729Sjoerg 
24357330f729Sjoerg   // Otherwise create it.
24367330f729Sjoerg 
24377330f729Sjoerg   // vtable for gnustep::libobjc::__objc_class_type_info
24387330f729Sjoerg   // It's quite ugly hard-coding this.  Ideally we'd generate it using the host
24397330f729Sjoerg   // platform's name mangling.
24407330f729Sjoerg   const char *vtableName = "_ZTVN7gnustep7libobjc22__objc_class_type_infoE";
24417330f729Sjoerg   auto *Vtable = TheModule.getGlobalVariable(vtableName);
24427330f729Sjoerg   if (!Vtable) {
24437330f729Sjoerg     Vtable = new llvm::GlobalVariable(TheModule, PtrToInt8Ty, true,
24447330f729Sjoerg                                       llvm::GlobalValue::ExternalLinkage,
24457330f729Sjoerg                                       nullptr, vtableName);
24467330f729Sjoerg   }
24477330f729Sjoerg   llvm::Constant *Two = llvm::ConstantInt::get(IntTy, 2);
24487330f729Sjoerg   auto *BVtable = llvm::ConstantExpr::getBitCast(
24497330f729Sjoerg       llvm::ConstantExpr::getGetElementPtr(Vtable->getValueType(), Vtable, Two),
24507330f729Sjoerg       PtrToInt8Ty);
24517330f729Sjoerg 
24527330f729Sjoerg   llvm::Constant *typeName =
24537330f729Sjoerg     ExportUniqueString(className, "__objc_eh_typename_");
24547330f729Sjoerg 
24557330f729Sjoerg   ConstantInitBuilder builder(CGM);
24567330f729Sjoerg   auto fields = builder.beginStruct();
24577330f729Sjoerg   fields.add(BVtable);
24587330f729Sjoerg   fields.add(typeName);
24597330f729Sjoerg   llvm::Constant *TI =
24607330f729Sjoerg     fields.finishAndCreateGlobal("__objc_eh_typeinfo_" + className,
24617330f729Sjoerg                                  CGM.getPointerAlign(),
24627330f729Sjoerg                                  /*constant*/ false,
24637330f729Sjoerg                                  llvm::GlobalValue::LinkOnceODRLinkage);
24647330f729Sjoerg   return llvm::ConstantExpr::getBitCast(TI, PtrToInt8Ty);
24657330f729Sjoerg }
24667330f729Sjoerg 
24677330f729Sjoerg /// Generate an NSConstantString object.
GenerateConstantString(const StringLiteral * SL)24687330f729Sjoerg ConstantAddress CGObjCGNU::GenerateConstantString(const StringLiteral *SL) {
24697330f729Sjoerg 
24707330f729Sjoerg   std::string Str = SL->getString().str();
24717330f729Sjoerg   CharUnits Align = CGM.getPointerAlign();
24727330f729Sjoerg 
24737330f729Sjoerg   // Look for an existing one
24747330f729Sjoerg   llvm::StringMap<llvm::Constant*>::iterator old = ObjCStrings.find(Str);
24757330f729Sjoerg   if (old != ObjCStrings.end())
24767330f729Sjoerg     return ConstantAddress(old->getValue(), Align);
24777330f729Sjoerg 
24787330f729Sjoerg   StringRef StringClass = CGM.getLangOpts().ObjCConstantStringClass;
24797330f729Sjoerg 
24807330f729Sjoerg   if (StringClass.empty()) StringClass = "NSConstantString";
24817330f729Sjoerg 
24827330f729Sjoerg   std::string Sym = "_OBJC_CLASS_";
24837330f729Sjoerg   Sym += StringClass;
24847330f729Sjoerg 
24857330f729Sjoerg   llvm::Constant *isa = TheModule.getNamedGlobal(Sym);
24867330f729Sjoerg 
24877330f729Sjoerg   if (!isa)
24887330f729Sjoerg     isa = new llvm::GlobalVariable(TheModule, IdTy, /* isConstant */false,
24897330f729Sjoerg             llvm::GlobalValue::ExternalWeakLinkage, nullptr, Sym);
24907330f729Sjoerg   else if (isa->getType() != PtrToIdTy)
24917330f729Sjoerg     isa = llvm::ConstantExpr::getBitCast(isa, PtrToIdTy);
24927330f729Sjoerg 
24937330f729Sjoerg   ConstantInitBuilder Builder(CGM);
24947330f729Sjoerg   auto Fields = Builder.beginStruct();
24957330f729Sjoerg   Fields.add(isa);
24967330f729Sjoerg   Fields.add(MakeConstantString(Str));
24977330f729Sjoerg   Fields.addInt(IntTy, Str.size());
24987330f729Sjoerg   llvm::Constant *ObjCStr =
24997330f729Sjoerg     Fields.finishAndCreateGlobal(".objc_str", Align);
25007330f729Sjoerg   ObjCStr = llvm::ConstantExpr::getBitCast(ObjCStr, PtrToInt8Ty);
25017330f729Sjoerg   ObjCStrings[Str] = ObjCStr;
25027330f729Sjoerg   ConstantStrings.push_back(ObjCStr);
25037330f729Sjoerg   return ConstantAddress(ObjCStr, Align);
25047330f729Sjoerg }
25057330f729Sjoerg 
25067330f729Sjoerg ///Generates a message send where the super is the receiver.  This is a message
25077330f729Sjoerg ///send to self with special delivery semantics indicating which class's method
25087330f729Sjoerg ///should be called.
25097330f729Sjoerg RValue
GenerateMessageSendSuper(CodeGenFunction & CGF,ReturnValueSlot Return,QualType ResultType,Selector Sel,const ObjCInterfaceDecl * Class,bool isCategoryImpl,llvm::Value * Receiver,bool IsClassMessage,const CallArgList & CallArgs,const ObjCMethodDecl * Method)25107330f729Sjoerg CGObjCGNU::GenerateMessageSendSuper(CodeGenFunction &CGF,
25117330f729Sjoerg                                     ReturnValueSlot Return,
25127330f729Sjoerg                                     QualType ResultType,
25137330f729Sjoerg                                     Selector Sel,
25147330f729Sjoerg                                     const ObjCInterfaceDecl *Class,
25157330f729Sjoerg                                     bool isCategoryImpl,
25167330f729Sjoerg                                     llvm::Value *Receiver,
25177330f729Sjoerg                                     bool IsClassMessage,
25187330f729Sjoerg                                     const CallArgList &CallArgs,
25197330f729Sjoerg                                     const ObjCMethodDecl *Method) {
25207330f729Sjoerg   CGBuilderTy &Builder = CGF.Builder;
25217330f729Sjoerg   if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) {
25227330f729Sjoerg     if (Sel == RetainSel || Sel == AutoreleaseSel) {
25237330f729Sjoerg       return RValue::get(EnforceType(Builder, Receiver,
25247330f729Sjoerg                   CGM.getTypes().ConvertType(ResultType)));
25257330f729Sjoerg     }
25267330f729Sjoerg     if (Sel == ReleaseSel) {
25277330f729Sjoerg       return RValue::get(nullptr);
25287330f729Sjoerg     }
25297330f729Sjoerg   }
25307330f729Sjoerg 
25317330f729Sjoerg   llvm::Value *cmd = GetSelector(CGF, Sel);
25327330f729Sjoerg   CallArgList ActualArgs;
25337330f729Sjoerg 
25347330f729Sjoerg   ActualArgs.add(RValue::get(EnforceType(Builder, Receiver, IdTy)), ASTIdTy);
25357330f729Sjoerg   ActualArgs.add(RValue::get(cmd), CGF.getContext().getObjCSelType());
25367330f729Sjoerg   ActualArgs.addFrom(CallArgs);
25377330f729Sjoerg 
25387330f729Sjoerg   MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);
25397330f729Sjoerg 
25407330f729Sjoerg   llvm::Value *ReceiverClass = nullptr;
25417330f729Sjoerg   bool isV2ABI = isRuntime(ObjCRuntime::GNUstep, 2);
25427330f729Sjoerg   if (isV2ABI) {
25437330f729Sjoerg     ReceiverClass = GetClassNamed(CGF,
25447330f729Sjoerg         Class->getSuperClass()->getNameAsString(), /*isWeak*/false);
25457330f729Sjoerg     if (IsClassMessage)  {
25467330f729Sjoerg       // Load the isa pointer of the superclass is this is a class method.
25477330f729Sjoerg       ReceiverClass = Builder.CreateBitCast(ReceiverClass,
25487330f729Sjoerg                                             llvm::PointerType::getUnqual(IdTy));
25497330f729Sjoerg       ReceiverClass =
2550*e038c9c4Sjoerg         Builder.CreateAlignedLoad(IdTy, ReceiverClass, CGF.getPointerAlign());
25517330f729Sjoerg     }
25527330f729Sjoerg     ReceiverClass = EnforceType(Builder, ReceiverClass, IdTy);
25537330f729Sjoerg   } else {
25547330f729Sjoerg     if (isCategoryImpl) {
25557330f729Sjoerg       llvm::FunctionCallee classLookupFunction = nullptr;
25567330f729Sjoerg       if (IsClassMessage)  {
25577330f729Sjoerg         classLookupFunction = CGM.CreateRuntimeFunction(llvm::FunctionType::get(
25587330f729Sjoerg               IdTy, PtrTy, true), "objc_get_meta_class");
25597330f729Sjoerg       } else {
25607330f729Sjoerg         classLookupFunction = CGM.CreateRuntimeFunction(llvm::FunctionType::get(
25617330f729Sjoerg               IdTy, PtrTy, true), "objc_get_class");
25627330f729Sjoerg       }
25637330f729Sjoerg       ReceiverClass = Builder.CreateCall(classLookupFunction,
25647330f729Sjoerg           MakeConstantString(Class->getNameAsString()));
25657330f729Sjoerg     } else {
25667330f729Sjoerg       // Set up global aliases for the metaclass or class pointer if they do not
25677330f729Sjoerg       // already exist.  These will are forward-references which will be set to
25687330f729Sjoerg       // pointers to the class and metaclass structure created for the runtime
25697330f729Sjoerg       // load function.  To send a message to super, we look up the value of the
25707330f729Sjoerg       // super_class pointer from either the class or metaclass structure.
25717330f729Sjoerg       if (IsClassMessage)  {
25727330f729Sjoerg         if (!MetaClassPtrAlias) {
25737330f729Sjoerg           MetaClassPtrAlias = llvm::GlobalAlias::create(
25747330f729Sjoerg               IdTy->getElementType(), 0, llvm::GlobalValue::InternalLinkage,
25757330f729Sjoerg               ".objc_metaclass_ref" + Class->getNameAsString(), &TheModule);
25767330f729Sjoerg         }
25777330f729Sjoerg         ReceiverClass = MetaClassPtrAlias;
25787330f729Sjoerg       } else {
25797330f729Sjoerg         if (!ClassPtrAlias) {
25807330f729Sjoerg           ClassPtrAlias = llvm::GlobalAlias::create(
25817330f729Sjoerg               IdTy->getElementType(), 0, llvm::GlobalValue::InternalLinkage,
25827330f729Sjoerg               ".objc_class_ref" + Class->getNameAsString(), &TheModule);
25837330f729Sjoerg         }
25847330f729Sjoerg         ReceiverClass = ClassPtrAlias;
25857330f729Sjoerg       }
25867330f729Sjoerg     }
25877330f729Sjoerg     // Cast the pointer to a simplified version of the class structure
25887330f729Sjoerg     llvm::Type *CastTy = llvm::StructType::get(IdTy, IdTy);
25897330f729Sjoerg     ReceiverClass = Builder.CreateBitCast(ReceiverClass,
25907330f729Sjoerg                                           llvm::PointerType::getUnqual(CastTy));
25917330f729Sjoerg     // Get the superclass pointer
25927330f729Sjoerg     ReceiverClass = Builder.CreateStructGEP(CastTy, ReceiverClass, 1);
25937330f729Sjoerg     // Load the superclass pointer
25947330f729Sjoerg     ReceiverClass =
2595*e038c9c4Sjoerg       Builder.CreateAlignedLoad(IdTy, ReceiverClass, CGF.getPointerAlign());
25967330f729Sjoerg   }
25977330f729Sjoerg   // Construct the structure used to look up the IMP
25987330f729Sjoerg   llvm::StructType *ObjCSuperTy =
25997330f729Sjoerg       llvm::StructType::get(Receiver->getType(), IdTy);
26007330f729Sjoerg 
26017330f729Sjoerg   Address ObjCSuper = CGF.CreateTempAlloca(ObjCSuperTy,
26027330f729Sjoerg                               CGF.getPointerAlign());
26037330f729Sjoerg 
26047330f729Sjoerg   Builder.CreateStore(Receiver, Builder.CreateStructGEP(ObjCSuper, 0));
26057330f729Sjoerg   Builder.CreateStore(ReceiverClass, Builder.CreateStructGEP(ObjCSuper, 1));
26067330f729Sjoerg 
26077330f729Sjoerg   ObjCSuper = EnforceType(Builder, ObjCSuper, PtrToObjCSuperTy);
26087330f729Sjoerg 
26097330f729Sjoerg   // Get the IMP
26107330f729Sjoerg   llvm::Value *imp = LookupIMPSuper(CGF, ObjCSuper, cmd, MSI);
26117330f729Sjoerg   imp = EnforceType(Builder, imp, MSI.MessengerType);
26127330f729Sjoerg 
26137330f729Sjoerg   llvm::Metadata *impMD[] = {
26147330f729Sjoerg       llvm::MDString::get(VMContext, Sel.getAsString()),
26157330f729Sjoerg       llvm::MDString::get(VMContext, Class->getSuperClass()->getNameAsString()),
26167330f729Sjoerg       llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
26177330f729Sjoerg           llvm::Type::getInt1Ty(VMContext), IsClassMessage))};
26187330f729Sjoerg   llvm::MDNode *node = llvm::MDNode::get(VMContext, impMD);
26197330f729Sjoerg 
26207330f729Sjoerg   CGCallee callee(CGCalleeInfo(), imp);
26217330f729Sjoerg 
26227330f729Sjoerg   llvm::CallBase *call;
26237330f729Sjoerg   RValue msgRet = CGF.EmitCall(MSI.CallInfo, callee, Return, ActualArgs, &call);
26247330f729Sjoerg   call->setMetadata(msgSendMDKind, node);
26257330f729Sjoerg   return msgRet;
26267330f729Sjoerg }
26277330f729Sjoerg 
26287330f729Sjoerg /// Generate code for a message send expression.
26297330f729Sjoerg RValue
GenerateMessageSend(CodeGenFunction & CGF,ReturnValueSlot Return,QualType ResultType,Selector Sel,llvm::Value * Receiver,const CallArgList & CallArgs,const ObjCInterfaceDecl * Class,const ObjCMethodDecl * Method)26307330f729Sjoerg CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF,
26317330f729Sjoerg                                ReturnValueSlot Return,
26327330f729Sjoerg                                QualType ResultType,
26337330f729Sjoerg                                Selector Sel,
26347330f729Sjoerg                                llvm::Value *Receiver,
26357330f729Sjoerg                                const CallArgList &CallArgs,
26367330f729Sjoerg                                const ObjCInterfaceDecl *Class,
26377330f729Sjoerg                                const ObjCMethodDecl *Method) {
26387330f729Sjoerg   CGBuilderTy &Builder = CGF.Builder;
26397330f729Sjoerg 
26407330f729Sjoerg   // Strip out message sends to retain / release in GC mode
26417330f729Sjoerg   if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) {
26427330f729Sjoerg     if (Sel == RetainSel || Sel == AutoreleaseSel) {
26437330f729Sjoerg       return RValue::get(EnforceType(Builder, Receiver,
26447330f729Sjoerg                   CGM.getTypes().ConvertType(ResultType)));
26457330f729Sjoerg     }
26467330f729Sjoerg     if (Sel == ReleaseSel) {
26477330f729Sjoerg       return RValue::get(nullptr);
26487330f729Sjoerg     }
26497330f729Sjoerg   }
26507330f729Sjoerg 
26517330f729Sjoerg   // If the return type is something that goes in an integer register, the
26527330f729Sjoerg   // runtime will handle 0 returns.  For other cases, we fill in the 0 value
26537330f729Sjoerg   // ourselves.
26547330f729Sjoerg   //
26557330f729Sjoerg   // The language spec says the result of this kind of message send is
26567330f729Sjoerg   // undefined, but lots of people seem to have forgotten to read that
26577330f729Sjoerg   // paragraph and insist on sending messages to nil that have structure
26587330f729Sjoerg   // returns.  With GCC, this generates a random return value (whatever happens
26597330f729Sjoerg   // to be on the stack / in those registers at the time) on most platforms,
26607330f729Sjoerg   // and generates an illegal instruction trap on SPARC.  With LLVM it corrupts
26617330f729Sjoerg   // the stack.
26627330f729Sjoerg   bool isPointerSizedReturn = (ResultType->isAnyPointerType() ||
26637330f729Sjoerg       ResultType->isIntegralOrEnumerationType() || ResultType->isVoidType());
26647330f729Sjoerg 
26657330f729Sjoerg   llvm::BasicBlock *startBB = nullptr;
26667330f729Sjoerg   llvm::BasicBlock *messageBB = nullptr;
26677330f729Sjoerg   llvm::BasicBlock *continueBB = nullptr;
26687330f729Sjoerg 
26697330f729Sjoerg   if (!isPointerSizedReturn) {
26707330f729Sjoerg     startBB = Builder.GetInsertBlock();
26717330f729Sjoerg     messageBB = CGF.createBasicBlock("msgSend");
26727330f729Sjoerg     continueBB = CGF.createBasicBlock("continue");
26737330f729Sjoerg 
26747330f729Sjoerg     llvm::Value *isNil = Builder.CreateICmpEQ(Receiver,
26757330f729Sjoerg             llvm::Constant::getNullValue(Receiver->getType()));
26767330f729Sjoerg     Builder.CreateCondBr(isNil, continueBB, messageBB);
26777330f729Sjoerg     CGF.EmitBlock(messageBB);
26787330f729Sjoerg   }
26797330f729Sjoerg 
26807330f729Sjoerg   IdTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(ASTIdTy));
26817330f729Sjoerg   llvm::Value *cmd;
26827330f729Sjoerg   if (Method)
26837330f729Sjoerg     cmd = GetSelector(CGF, Method);
26847330f729Sjoerg   else
26857330f729Sjoerg     cmd = GetSelector(CGF, Sel);
26867330f729Sjoerg   cmd = EnforceType(Builder, cmd, SelectorTy);
26877330f729Sjoerg   Receiver = EnforceType(Builder, Receiver, IdTy);
26887330f729Sjoerg 
26897330f729Sjoerg   llvm::Metadata *impMD[] = {
26907330f729Sjoerg       llvm::MDString::get(VMContext, Sel.getAsString()),
26917330f729Sjoerg       llvm::MDString::get(VMContext, Class ? Class->getNameAsString() : ""),
26927330f729Sjoerg       llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
26937330f729Sjoerg           llvm::Type::getInt1Ty(VMContext), Class != nullptr))};
26947330f729Sjoerg   llvm::MDNode *node = llvm::MDNode::get(VMContext, impMD);
26957330f729Sjoerg 
26967330f729Sjoerg   CallArgList ActualArgs;
26977330f729Sjoerg   ActualArgs.add(RValue::get(Receiver), ASTIdTy);
26987330f729Sjoerg   ActualArgs.add(RValue::get(cmd), CGF.getContext().getObjCSelType());
26997330f729Sjoerg   ActualArgs.addFrom(CallArgs);
27007330f729Sjoerg 
27017330f729Sjoerg   MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);
27027330f729Sjoerg 
27037330f729Sjoerg   // Get the IMP to call
27047330f729Sjoerg   llvm::Value *imp;
27057330f729Sjoerg 
27067330f729Sjoerg   // If we have non-legacy dispatch specified, we try using the objc_msgSend()
27077330f729Sjoerg   // functions.  These are not supported on all platforms (or all runtimes on a
27087330f729Sjoerg   // given platform), so we
27097330f729Sjoerg   switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
27107330f729Sjoerg     case CodeGenOptions::Legacy:
27117330f729Sjoerg       imp = LookupIMP(CGF, Receiver, cmd, node, MSI);
27127330f729Sjoerg       break;
27137330f729Sjoerg     case CodeGenOptions::Mixed:
27147330f729Sjoerg     case CodeGenOptions::NonLegacy:
27157330f729Sjoerg       if (CGM.ReturnTypeUsesFPRet(ResultType)) {
27167330f729Sjoerg         imp =
27177330f729Sjoerg             CGM.CreateRuntimeFunction(llvm::FunctionType::get(IdTy, IdTy, true),
27187330f729Sjoerg                                       "objc_msgSend_fpret")
27197330f729Sjoerg                 .getCallee();
27207330f729Sjoerg       } else if (CGM.ReturnTypeUsesSRet(MSI.CallInfo)) {
27217330f729Sjoerg         // The actual types here don't matter - we're going to bitcast the
27227330f729Sjoerg         // function anyway
27237330f729Sjoerg         imp =
27247330f729Sjoerg             CGM.CreateRuntimeFunction(llvm::FunctionType::get(IdTy, IdTy, true),
27257330f729Sjoerg                                       "objc_msgSend_stret")
27267330f729Sjoerg                 .getCallee();
27277330f729Sjoerg       } else {
27287330f729Sjoerg         imp = CGM.CreateRuntimeFunction(
27297330f729Sjoerg                      llvm::FunctionType::get(IdTy, IdTy, true), "objc_msgSend")
27307330f729Sjoerg                   .getCallee();
27317330f729Sjoerg       }
27327330f729Sjoerg   }
27337330f729Sjoerg 
27347330f729Sjoerg   // Reset the receiver in case the lookup modified it
27357330f729Sjoerg   ActualArgs[0] = CallArg(RValue::get(Receiver), ASTIdTy);
27367330f729Sjoerg 
27377330f729Sjoerg   imp = EnforceType(Builder, imp, MSI.MessengerType);
27387330f729Sjoerg 
27397330f729Sjoerg   llvm::CallBase *call;
27407330f729Sjoerg   CGCallee callee(CGCalleeInfo(), imp);
27417330f729Sjoerg   RValue msgRet = CGF.EmitCall(MSI.CallInfo, callee, Return, ActualArgs, &call);
27427330f729Sjoerg   call->setMetadata(msgSendMDKind, node);
27437330f729Sjoerg 
27447330f729Sjoerg 
27457330f729Sjoerg   if (!isPointerSizedReturn) {
27467330f729Sjoerg     messageBB = CGF.Builder.GetInsertBlock();
27477330f729Sjoerg     CGF.Builder.CreateBr(continueBB);
27487330f729Sjoerg     CGF.EmitBlock(continueBB);
27497330f729Sjoerg     if (msgRet.isScalar()) {
27507330f729Sjoerg       llvm::Value *v = msgRet.getScalarVal();
27517330f729Sjoerg       llvm::PHINode *phi = Builder.CreatePHI(v->getType(), 2);
27527330f729Sjoerg       phi->addIncoming(v, messageBB);
27537330f729Sjoerg       phi->addIncoming(llvm::Constant::getNullValue(v->getType()), startBB);
27547330f729Sjoerg       msgRet = RValue::get(phi);
27557330f729Sjoerg     } else if (msgRet.isAggregate()) {
27567330f729Sjoerg       Address v = msgRet.getAggregateAddress();
27577330f729Sjoerg       llvm::PHINode *phi = Builder.CreatePHI(v.getType(), 2);
27587330f729Sjoerg       llvm::Type *RetTy = v.getElementType();
27597330f729Sjoerg       Address NullVal = CGF.CreateTempAlloca(RetTy, v.getAlignment(), "null");
27607330f729Sjoerg       CGF.InitTempAlloca(NullVal, llvm::Constant::getNullValue(RetTy));
27617330f729Sjoerg       phi->addIncoming(v.getPointer(), messageBB);
27627330f729Sjoerg       phi->addIncoming(NullVal.getPointer(), startBB);
27637330f729Sjoerg       msgRet = RValue::getAggregate(Address(phi, v.getAlignment()));
27647330f729Sjoerg     } else /* isComplex() */ {
27657330f729Sjoerg       std::pair<llvm::Value*,llvm::Value*> v = msgRet.getComplexVal();
27667330f729Sjoerg       llvm::PHINode *phi = Builder.CreatePHI(v.first->getType(), 2);
27677330f729Sjoerg       phi->addIncoming(v.first, messageBB);
27687330f729Sjoerg       phi->addIncoming(llvm::Constant::getNullValue(v.first->getType()),
27697330f729Sjoerg           startBB);
27707330f729Sjoerg       llvm::PHINode *phi2 = Builder.CreatePHI(v.second->getType(), 2);
27717330f729Sjoerg       phi2->addIncoming(v.second, messageBB);
27727330f729Sjoerg       phi2->addIncoming(llvm::Constant::getNullValue(v.second->getType()),
27737330f729Sjoerg           startBB);
27747330f729Sjoerg       msgRet = RValue::getComplex(phi, phi2);
27757330f729Sjoerg     }
27767330f729Sjoerg   }
27777330f729Sjoerg   return msgRet;
27787330f729Sjoerg }
27797330f729Sjoerg 
27807330f729Sjoerg /// Generates a MethodList.  Used in construction of a objc_class and
27817330f729Sjoerg /// objc_category structures.
27827330f729Sjoerg llvm::Constant *CGObjCGNU::
GenerateMethodList(StringRef ClassName,StringRef CategoryName,ArrayRef<const ObjCMethodDecl * > Methods,bool isClassMethodList)27837330f729Sjoerg GenerateMethodList(StringRef ClassName,
27847330f729Sjoerg                    StringRef CategoryName,
27857330f729Sjoerg                    ArrayRef<const ObjCMethodDecl*> Methods,
27867330f729Sjoerg                    bool isClassMethodList) {
27877330f729Sjoerg   if (Methods.empty())
27887330f729Sjoerg     return NULLPtr;
27897330f729Sjoerg 
27907330f729Sjoerg   ConstantInitBuilder Builder(CGM);
27917330f729Sjoerg 
27927330f729Sjoerg   auto MethodList = Builder.beginStruct();
27937330f729Sjoerg   MethodList.addNullPointer(CGM.Int8PtrTy);
27947330f729Sjoerg   MethodList.addInt(Int32Ty, Methods.size());
27957330f729Sjoerg 
27967330f729Sjoerg   // Get the method structure type.
27977330f729Sjoerg   llvm::StructType *ObjCMethodTy =
27987330f729Sjoerg     llvm::StructType::get(CGM.getLLVMContext(), {
27997330f729Sjoerg       PtrToInt8Ty, // Really a selector, but the runtime creates it us.
28007330f729Sjoerg       PtrToInt8Ty, // Method types
28017330f729Sjoerg       IMPTy        // Method pointer
28027330f729Sjoerg     });
28037330f729Sjoerg   bool isV2ABI = isRuntime(ObjCRuntime::GNUstep, 2);
28047330f729Sjoerg   if (isV2ABI) {
28057330f729Sjoerg     // size_t size;
28067330f729Sjoerg     llvm::DataLayout td(&TheModule);
28077330f729Sjoerg     MethodList.addInt(SizeTy, td.getTypeSizeInBits(ObjCMethodTy) /
28087330f729Sjoerg         CGM.getContext().getCharWidth());
28097330f729Sjoerg     ObjCMethodTy =
28107330f729Sjoerg       llvm::StructType::get(CGM.getLLVMContext(), {
28117330f729Sjoerg         IMPTy,       // Method pointer
28127330f729Sjoerg         PtrToInt8Ty, // Selector
28137330f729Sjoerg         PtrToInt8Ty  // Extended type encoding
28147330f729Sjoerg       });
28157330f729Sjoerg   } else {
28167330f729Sjoerg     ObjCMethodTy =
28177330f729Sjoerg       llvm::StructType::get(CGM.getLLVMContext(), {
28187330f729Sjoerg         PtrToInt8Ty, // Really a selector, but the runtime creates it us.
28197330f729Sjoerg         PtrToInt8Ty, // Method types
28207330f729Sjoerg         IMPTy        // Method pointer
28217330f729Sjoerg       });
28227330f729Sjoerg   }
28237330f729Sjoerg   auto MethodArray = MethodList.beginArray();
28247330f729Sjoerg   ASTContext &Context = CGM.getContext();
28257330f729Sjoerg   for (const auto *OMD : Methods) {
28267330f729Sjoerg     llvm::Constant *FnPtr =
2827*e038c9c4Sjoerg       TheModule.getFunction(getSymbolNameForMethod(OMD));
28287330f729Sjoerg     assert(FnPtr && "Can't generate metadata for method that doesn't exist");
28297330f729Sjoerg     auto Method = MethodArray.beginStruct(ObjCMethodTy);
28307330f729Sjoerg     if (isV2ABI) {
28317330f729Sjoerg       Method.addBitCast(FnPtr, IMPTy);
28327330f729Sjoerg       Method.add(GetConstantSelector(OMD->getSelector(),
28337330f729Sjoerg           Context.getObjCEncodingForMethodDecl(OMD)));
28347330f729Sjoerg       Method.add(MakeConstantString(Context.getObjCEncodingForMethodDecl(OMD, true)));
28357330f729Sjoerg     } else {
28367330f729Sjoerg       Method.add(MakeConstantString(OMD->getSelector().getAsString()));
28377330f729Sjoerg       Method.add(MakeConstantString(Context.getObjCEncodingForMethodDecl(OMD)));
28387330f729Sjoerg       Method.addBitCast(FnPtr, IMPTy);
28397330f729Sjoerg     }
28407330f729Sjoerg     Method.finishAndAddTo(MethodArray);
28417330f729Sjoerg   }
28427330f729Sjoerg   MethodArray.finishAndAddTo(MethodList);
28437330f729Sjoerg 
28447330f729Sjoerg   // Create an instance of the structure
28457330f729Sjoerg   return MethodList.finishAndCreateGlobal(".objc_method_list",
28467330f729Sjoerg                                           CGM.getPointerAlign());
28477330f729Sjoerg }
28487330f729Sjoerg 
28497330f729Sjoerg /// Generates an IvarList.  Used in construction of a objc_class.
28507330f729Sjoerg llvm::Constant *CGObjCGNU::
GenerateIvarList(ArrayRef<llvm::Constant * > IvarNames,ArrayRef<llvm::Constant * > IvarTypes,ArrayRef<llvm::Constant * > IvarOffsets,ArrayRef<llvm::Constant * > IvarAlign,ArrayRef<Qualifiers::ObjCLifetime> IvarOwnership)28517330f729Sjoerg GenerateIvarList(ArrayRef<llvm::Constant *> IvarNames,
28527330f729Sjoerg                  ArrayRef<llvm::Constant *> IvarTypes,
28537330f729Sjoerg                  ArrayRef<llvm::Constant *> IvarOffsets,
28547330f729Sjoerg                  ArrayRef<llvm::Constant *> IvarAlign,
28557330f729Sjoerg                  ArrayRef<Qualifiers::ObjCLifetime> IvarOwnership) {
28567330f729Sjoerg   if (IvarNames.empty())
28577330f729Sjoerg     return NULLPtr;
28587330f729Sjoerg 
28597330f729Sjoerg   ConstantInitBuilder Builder(CGM);
28607330f729Sjoerg 
28617330f729Sjoerg   // Structure containing array count followed by array.
28627330f729Sjoerg   auto IvarList = Builder.beginStruct();
28637330f729Sjoerg   IvarList.addInt(IntTy, (int)IvarNames.size());
28647330f729Sjoerg 
28657330f729Sjoerg   // Get the ivar structure type.
28667330f729Sjoerg   llvm::StructType *ObjCIvarTy =
28677330f729Sjoerg       llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, IntTy);
28687330f729Sjoerg 
28697330f729Sjoerg   // Array of ivar structures.
28707330f729Sjoerg   auto Ivars = IvarList.beginArray(ObjCIvarTy);
28717330f729Sjoerg   for (unsigned int i = 0, e = IvarNames.size() ; i < e ; i++) {
28727330f729Sjoerg     auto Ivar = Ivars.beginStruct(ObjCIvarTy);
28737330f729Sjoerg     Ivar.add(IvarNames[i]);
28747330f729Sjoerg     Ivar.add(IvarTypes[i]);
28757330f729Sjoerg     Ivar.add(IvarOffsets[i]);
28767330f729Sjoerg     Ivar.finishAndAddTo(Ivars);
28777330f729Sjoerg   }
28787330f729Sjoerg   Ivars.finishAndAddTo(IvarList);
28797330f729Sjoerg 
28807330f729Sjoerg   // Create an instance of the structure
28817330f729Sjoerg   return IvarList.finishAndCreateGlobal(".objc_ivar_list",
28827330f729Sjoerg                                         CGM.getPointerAlign());
28837330f729Sjoerg }
28847330f729Sjoerg 
28857330f729Sjoerg /// Generate a class structure
GenerateClassStructure(llvm::Constant * MetaClass,llvm::Constant * SuperClass,unsigned info,const char * Name,llvm::Constant * Version,llvm::Constant * InstanceSize,llvm::Constant * IVars,llvm::Constant * Methods,llvm::Constant * Protocols,llvm::Constant * IvarOffsets,llvm::Constant * Properties,llvm::Constant * StrongIvarBitmap,llvm::Constant * WeakIvarBitmap,bool isMeta)28867330f729Sjoerg llvm::Constant *CGObjCGNU::GenerateClassStructure(
28877330f729Sjoerg     llvm::Constant *MetaClass,
28887330f729Sjoerg     llvm::Constant *SuperClass,
28897330f729Sjoerg     unsigned info,
28907330f729Sjoerg     const char *Name,
28917330f729Sjoerg     llvm::Constant *Version,
28927330f729Sjoerg     llvm::Constant *InstanceSize,
28937330f729Sjoerg     llvm::Constant *IVars,
28947330f729Sjoerg     llvm::Constant *Methods,
28957330f729Sjoerg     llvm::Constant *Protocols,
28967330f729Sjoerg     llvm::Constant *IvarOffsets,
28977330f729Sjoerg     llvm::Constant *Properties,
28987330f729Sjoerg     llvm::Constant *StrongIvarBitmap,
28997330f729Sjoerg     llvm::Constant *WeakIvarBitmap,
29007330f729Sjoerg     bool isMeta) {
29017330f729Sjoerg   // Set up the class structure
29027330f729Sjoerg   // Note:  Several of these are char*s when they should be ids.  This is
29037330f729Sjoerg   // because the runtime performs this translation on load.
29047330f729Sjoerg   //
29057330f729Sjoerg   // Fields marked New ABI are part of the GNUstep runtime.  We emit them
29067330f729Sjoerg   // anyway; the classes will still work with the GNU runtime, they will just
29077330f729Sjoerg   // be ignored.
29087330f729Sjoerg   llvm::StructType *ClassTy = llvm::StructType::get(
29097330f729Sjoerg       PtrToInt8Ty,        // isa
29107330f729Sjoerg       PtrToInt8Ty,        // super_class
29117330f729Sjoerg       PtrToInt8Ty,        // name
29127330f729Sjoerg       LongTy,             // version
29137330f729Sjoerg       LongTy,             // info
29147330f729Sjoerg       LongTy,             // instance_size
29157330f729Sjoerg       IVars->getType(),   // ivars
29167330f729Sjoerg       Methods->getType(), // methods
29177330f729Sjoerg       // These are all filled in by the runtime, so we pretend
29187330f729Sjoerg       PtrTy, // dtable
29197330f729Sjoerg       PtrTy, // subclass_list
29207330f729Sjoerg       PtrTy, // sibling_class
29217330f729Sjoerg       PtrTy, // protocols
29227330f729Sjoerg       PtrTy, // gc_object_type
29237330f729Sjoerg       // New ABI:
29247330f729Sjoerg       LongTy,                 // abi_version
29257330f729Sjoerg       IvarOffsets->getType(), // ivar_offsets
29267330f729Sjoerg       Properties->getType(),  // properties
29277330f729Sjoerg       IntPtrTy,               // strong_pointers
29287330f729Sjoerg       IntPtrTy                // weak_pointers
29297330f729Sjoerg       );
29307330f729Sjoerg 
29317330f729Sjoerg   ConstantInitBuilder Builder(CGM);
29327330f729Sjoerg   auto Elements = Builder.beginStruct(ClassTy);
29337330f729Sjoerg 
29347330f729Sjoerg   // Fill in the structure
29357330f729Sjoerg 
29367330f729Sjoerg   // isa
29377330f729Sjoerg   Elements.addBitCast(MetaClass, PtrToInt8Ty);
29387330f729Sjoerg   // super_class
29397330f729Sjoerg   Elements.add(SuperClass);
29407330f729Sjoerg   // name
29417330f729Sjoerg   Elements.add(MakeConstantString(Name, ".class_name"));
29427330f729Sjoerg   // version
29437330f729Sjoerg   Elements.addInt(LongTy, 0);
29447330f729Sjoerg   // info
29457330f729Sjoerg   Elements.addInt(LongTy, info);
29467330f729Sjoerg   // instance_size
29477330f729Sjoerg   if (isMeta) {
29487330f729Sjoerg     llvm::DataLayout td(&TheModule);
29497330f729Sjoerg     Elements.addInt(LongTy,
29507330f729Sjoerg                     td.getTypeSizeInBits(ClassTy) /
29517330f729Sjoerg                       CGM.getContext().getCharWidth());
29527330f729Sjoerg   } else
29537330f729Sjoerg     Elements.add(InstanceSize);
29547330f729Sjoerg   // ivars
29557330f729Sjoerg   Elements.add(IVars);
29567330f729Sjoerg   // methods
29577330f729Sjoerg   Elements.add(Methods);
29587330f729Sjoerg   // These are all filled in by the runtime, so we pretend
29597330f729Sjoerg   // dtable
29607330f729Sjoerg   Elements.add(NULLPtr);
29617330f729Sjoerg   // subclass_list
29627330f729Sjoerg   Elements.add(NULLPtr);
29637330f729Sjoerg   // sibling_class
29647330f729Sjoerg   Elements.add(NULLPtr);
29657330f729Sjoerg   // protocols
29667330f729Sjoerg   Elements.addBitCast(Protocols, PtrTy);
29677330f729Sjoerg   // gc_object_type
29687330f729Sjoerg   Elements.add(NULLPtr);
29697330f729Sjoerg   // abi_version
29707330f729Sjoerg   Elements.addInt(LongTy, ClassABIVersion);
29717330f729Sjoerg   // ivar_offsets
29727330f729Sjoerg   Elements.add(IvarOffsets);
29737330f729Sjoerg   // properties
29747330f729Sjoerg   Elements.add(Properties);
29757330f729Sjoerg   // strong_pointers
29767330f729Sjoerg   Elements.add(StrongIvarBitmap);
29777330f729Sjoerg   // weak_pointers
29787330f729Sjoerg   Elements.add(WeakIvarBitmap);
29797330f729Sjoerg   // Create an instance of the structure
29807330f729Sjoerg   // This is now an externally visible symbol, so that we can speed up class
29817330f729Sjoerg   // messages in the next ABI.  We may already have some weak references to
29827330f729Sjoerg   // this, so check and fix them properly.
29837330f729Sjoerg   std::string ClassSym((isMeta ? "_OBJC_METACLASS_": "_OBJC_CLASS_") +
29847330f729Sjoerg           std::string(Name));
29857330f729Sjoerg   llvm::GlobalVariable *ClassRef = TheModule.getNamedGlobal(ClassSym);
29867330f729Sjoerg   llvm::Constant *Class =
29877330f729Sjoerg     Elements.finishAndCreateGlobal(ClassSym, CGM.getPointerAlign(), false,
29887330f729Sjoerg                                    llvm::GlobalValue::ExternalLinkage);
29897330f729Sjoerg   if (ClassRef) {
29907330f729Sjoerg     ClassRef->replaceAllUsesWith(llvm::ConstantExpr::getBitCast(Class,
29917330f729Sjoerg                   ClassRef->getType()));
29927330f729Sjoerg     ClassRef->removeFromParent();
29937330f729Sjoerg     Class->setName(ClassSym);
29947330f729Sjoerg   }
29957330f729Sjoerg   return Class;
29967330f729Sjoerg }
29977330f729Sjoerg 
29987330f729Sjoerg llvm::Constant *CGObjCGNU::
GenerateProtocolMethodList(ArrayRef<const ObjCMethodDecl * > Methods)29997330f729Sjoerg GenerateProtocolMethodList(ArrayRef<const ObjCMethodDecl*> Methods) {
30007330f729Sjoerg   // Get the method structure type.
30017330f729Sjoerg   llvm::StructType *ObjCMethodDescTy =
30027330f729Sjoerg     llvm::StructType::get(CGM.getLLVMContext(), { PtrToInt8Ty, PtrToInt8Ty });
30037330f729Sjoerg   ASTContext &Context = CGM.getContext();
30047330f729Sjoerg   ConstantInitBuilder Builder(CGM);
30057330f729Sjoerg   auto MethodList = Builder.beginStruct();
30067330f729Sjoerg   MethodList.addInt(IntTy, Methods.size());
30077330f729Sjoerg   auto MethodArray = MethodList.beginArray(ObjCMethodDescTy);
30087330f729Sjoerg   for (auto *M : Methods) {
30097330f729Sjoerg     auto Method = MethodArray.beginStruct(ObjCMethodDescTy);
30107330f729Sjoerg     Method.add(MakeConstantString(M->getSelector().getAsString()));
30117330f729Sjoerg     Method.add(MakeConstantString(Context.getObjCEncodingForMethodDecl(M)));
30127330f729Sjoerg     Method.finishAndAddTo(MethodArray);
30137330f729Sjoerg   }
30147330f729Sjoerg   MethodArray.finishAndAddTo(MethodList);
30157330f729Sjoerg   return MethodList.finishAndCreateGlobal(".objc_method_list",
30167330f729Sjoerg                                           CGM.getPointerAlign());
30177330f729Sjoerg }
30187330f729Sjoerg 
30197330f729Sjoerg // Create the protocol list structure used in classes, categories and so on
30207330f729Sjoerg llvm::Constant *
GenerateProtocolList(ArrayRef<std::string> Protocols)30217330f729Sjoerg CGObjCGNU::GenerateProtocolList(ArrayRef<std::string> Protocols) {
30227330f729Sjoerg 
30237330f729Sjoerg   ConstantInitBuilder Builder(CGM);
30247330f729Sjoerg   auto ProtocolList = Builder.beginStruct();
30257330f729Sjoerg   ProtocolList.add(NULLPtr);
30267330f729Sjoerg   ProtocolList.addInt(LongTy, Protocols.size());
30277330f729Sjoerg 
30287330f729Sjoerg   auto Elements = ProtocolList.beginArray(PtrToInt8Ty);
30297330f729Sjoerg   for (const std::string *iter = Protocols.begin(), *endIter = Protocols.end();
30307330f729Sjoerg       iter != endIter ; iter++) {
30317330f729Sjoerg     llvm::Constant *protocol = nullptr;
30327330f729Sjoerg     llvm::StringMap<llvm::Constant*>::iterator value =
30337330f729Sjoerg       ExistingProtocols.find(*iter);
30347330f729Sjoerg     if (value == ExistingProtocols.end()) {
30357330f729Sjoerg       protocol = GenerateEmptyProtocol(*iter);
30367330f729Sjoerg     } else {
30377330f729Sjoerg       protocol = value->getValue();
30387330f729Sjoerg     }
30397330f729Sjoerg     Elements.addBitCast(protocol, PtrToInt8Ty);
30407330f729Sjoerg   }
30417330f729Sjoerg   Elements.finishAndAddTo(ProtocolList);
30427330f729Sjoerg   return ProtocolList.finishAndCreateGlobal(".objc_protocol_list",
30437330f729Sjoerg                                             CGM.getPointerAlign());
30447330f729Sjoerg }
30457330f729Sjoerg 
GenerateProtocolRef(CodeGenFunction & CGF,const ObjCProtocolDecl * PD)30467330f729Sjoerg llvm::Value *CGObjCGNU::GenerateProtocolRef(CodeGenFunction &CGF,
30477330f729Sjoerg                                             const ObjCProtocolDecl *PD) {
3048*e038c9c4Sjoerg   auto protocol = GenerateProtocolRef(PD);
30497330f729Sjoerg   llvm::Type *T =
30507330f729Sjoerg       CGM.getTypes().ConvertType(CGM.getContext().getObjCProtoType());
30517330f729Sjoerg   return CGF.Builder.CreateBitCast(protocol, llvm::PointerType::getUnqual(T));
30527330f729Sjoerg }
30537330f729Sjoerg 
GenerateProtocolRef(const ObjCProtocolDecl * PD)3054*e038c9c4Sjoerg llvm::Constant *CGObjCGNU::GenerateProtocolRef(const ObjCProtocolDecl *PD) {
3055*e038c9c4Sjoerg   llvm::Constant *&protocol = ExistingProtocols[PD->getNameAsString()];
3056*e038c9c4Sjoerg   if (!protocol)
3057*e038c9c4Sjoerg     GenerateProtocol(PD);
3058*e038c9c4Sjoerg   assert(protocol && "Unknown protocol");
3059*e038c9c4Sjoerg   return protocol;
3060*e038c9c4Sjoerg }
3061*e038c9c4Sjoerg 
30627330f729Sjoerg llvm::Constant *
GenerateEmptyProtocol(StringRef ProtocolName)30637330f729Sjoerg CGObjCGNU::GenerateEmptyProtocol(StringRef ProtocolName) {
30647330f729Sjoerg   llvm::Constant *ProtocolList = GenerateProtocolList({});
30657330f729Sjoerg   llvm::Constant *MethodList = GenerateProtocolMethodList({});
30667330f729Sjoerg   MethodList = llvm::ConstantExpr::getBitCast(MethodList, PtrToInt8Ty);
30677330f729Sjoerg   // Protocols are objects containing lists of the methods implemented and
30687330f729Sjoerg   // protocols adopted.
30697330f729Sjoerg   ConstantInitBuilder Builder(CGM);
30707330f729Sjoerg   auto Elements = Builder.beginStruct();
30717330f729Sjoerg 
30727330f729Sjoerg   // The isa pointer must be set to a magic number so the runtime knows it's
30737330f729Sjoerg   // the correct layout.
30747330f729Sjoerg   Elements.add(llvm::ConstantExpr::getIntToPtr(
30757330f729Sjoerg           llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy));
30767330f729Sjoerg 
30777330f729Sjoerg   Elements.add(MakeConstantString(ProtocolName, ".objc_protocol_name"));
30787330f729Sjoerg   Elements.add(ProtocolList); /* .protocol_list */
30797330f729Sjoerg   Elements.add(MethodList);   /* .instance_methods */
30807330f729Sjoerg   Elements.add(MethodList);   /* .class_methods */
30817330f729Sjoerg   Elements.add(MethodList);   /* .optional_instance_methods */
30827330f729Sjoerg   Elements.add(MethodList);   /* .optional_class_methods */
30837330f729Sjoerg   Elements.add(NULLPtr);      /* .properties */
30847330f729Sjoerg   Elements.add(NULLPtr);      /* .optional_properties */
30857330f729Sjoerg   return Elements.finishAndCreateGlobal(SymbolForProtocol(ProtocolName),
30867330f729Sjoerg                                         CGM.getPointerAlign());
30877330f729Sjoerg }
30887330f729Sjoerg 
GenerateProtocol(const ObjCProtocolDecl * PD)30897330f729Sjoerg void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
3090*e038c9c4Sjoerg   if (PD->isNonRuntimeProtocol())
3091*e038c9c4Sjoerg     return;
3092*e038c9c4Sjoerg 
30937330f729Sjoerg   std::string ProtocolName = PD->getNameAsString();
30947330f729Sjoerg 
30957330f729Sjoerg   // Use the protocol definition, if there is one.
30967330f729Sjoerg   if (const ObjCProtocolDecl *Def = PD->getDefinition())
30977330f729Sjoerg     PD = Def;
30987330f729Sjoerg 
30997330f729Sjoerg   SmallVector<std::string, 16> Protocols;
31007330f729Sjoerg   for (const auto *PI : PD->protocols())
31017330f729Sjoerg     Protocols.push_back(PI->getNameAsString());
31027330f729Sjoerg   SmallVector<const ObjCMethodDecl*, 16> InstanceMethods;
31037330f729Sjoerg   SmallVector<const ObjCMethodDecl*, 16> OptionalInstanceMethods;
31047330f729Sjoerg   for (const auto *I : PD->instance_methods())
31057330f729Sjoerg     if (I->isOptional())
31067330f729Sjoerg       OptionalInstanceMethods.push_back(I);
31077330f729Sjoerg     else
31087330f729Sjoerg       InstanceMethods.push_back(I);
31097330f729Sjoerg   // Collect information about class methods:
31107330f729Sjoerg   SmallVector<const ObjCMethodDecl*, 16> ClassMethods;
31117330f729Sjoerg   SmallVector<const ObjCMethodDecl*, 16> OptionalClassMethods;
31127330f729Sjoerg   for (const auto *I : PD->class_methods())
31137330f729Sjoerg     if (I->isOptional())
31147330f729Sjoerg       OptionalClassMethods.push_back(I);
31157330f729Sjoerg     else
31167330f729Sjoerg       ClassMethods.push_back(I);
31177330f729Sjoerg 
31187330f729Sjoerg   llvm::Constant *ProtocolList = GenerateProtocolList(Protocols);
31197330f729Sjoerg   llvm::Constant *InstanceMethodList =
31207330f729Sjoerg     GenerateProtocolMethodList(InstanceMethods);
31217330f729Sjoerg   llvm::Constant *ClassMethodList =
31227330f729Sjoerg     GenerateProtocolMethodList(ClassMethods);
31237330f729Sjoerg   llvm::Constant *OptionalInstanceMethodList =
31247330f729Sjoerg     GenerateProtocolMethodList(OptionalInstanceMethods);
31257330f729Sjoerg   llvm::Constant *OptionalClassMethodList =
31267330f729Sjoerg     GenerateProtocolMethodList(OptionalClassMethods);
31277330f729Sjoerg 
31287330f729Sjoerg   // Property metadata: name, attributes, isSynthesized, setter name, setter
31297330f729Sjoerg   // types, getter name, getter types.
31307330f729Sjoerg   // The isSynthesized value is always set to 0 in a protocol.  It exists to
31317330f729Sjoerg   // simplify the runtime library by allowing it to use the same data
31327330f729Sjoerg   // structures for protocol metadata everywhere.
31337330f729Sjoerg 
31347330f729Sjoerg   llvm::Constant *PropertyList =
31357330f729Sjoerg     GeneratePropertyList(nullptr, PD, false, false);
31367330f729Sjoerg   llvm::Constant *OptionalPropertyList =
31377330f729Sjoerg     GeneratePropertyList(nullptr, PD, false, true);
31387330f729Sjoerg 
31397330f729Sjoerg   // Protocols are objects containing lists of the methods implemented and
31407330f729Sjoerg   // protocols adopted.
31417330f729Sjoerg   // The isa pointer must be set to a magic number so the runtime knows it's
31427330f729Sjoerg   // the correct layout.
31437330f729Sjoerg   ConstantInitBuilder Builder(CGM);
31447330f729Sjoerg   auto Elements = Builder.beginStruct();
31457330f729Sjoerg   Elements.add(
31467330f729Sjoerg       llvm::ConstantExpr::getIntToPtr(
31477330f729Sjoerg           llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy));
31487330f729Sjoerg   Elements.add(MakeConstantString(ProtocolName));
31497330f729Sjoerg   Elements.add(ProtocolList);
31507330f729Sjoerg   Elements.add(InstanceMethodList);
31517330f729Sjoerg   Elements.add(ClassMethodList);
31527330f729Sjoerg   Elements.add(OptionalInstanceMethodList);
31537330f729Sjoerg   Elements.add(OptionalClassMethodList);
31547330f729Sjoerg   Elements.add(PropertyList);
31557330f729Sjoerg   Elements.add(OptionalPropertyList);
31567330f729Sjoerg   ExistingProtocols[ProtocolName] =
31577330f729Sjoerg     llvm::ConstantExpr::getBitCast(
31587330f729Sjoerg       Elements.finishAndCreateGlobal(".objc_protocol", CGM.getPointerAlign()),
31597330f729Sjoerg       IdTy);
31607330f729Sjoerg }
GenerateProtocolHolderCategory()31617330f729Sjoerg void CGObjCGNU::GenerateProtocolHolderCategory() {
31627330f729Sjoerg   // Collect information about instance methods
31637330f729Sjoerg 
31647330f729Sjoerg   ConstantInitBuilder Builder(CGM);
31657330f729Sjoerg   auto Elements = Builder.beginStruct();
31667330f729Sjoerg 
31677330f729Sjoerg   const std::string ClassName = "__ObjC_Protocol_Holder_Ugly_Hack";
31687330f729Sjoerg   const std::string CategoryName = "AnotherHack";
31697330f729Sjoerg   Elements.add(MakeConstantString(CategoryName));
31707330f729Sjoerg   Elements.add(MakeConstantString(ClassName));
31717330f729Sjoerg   // Instance method list
31727330f729Sjoerg   Elements.addBitCast(GenerateMethodList(
31737330f729Sjoerg           ClassName, CategoryName, {}, false), PtrTy);
31747330f729Sjoerg   // Class method list
31757330f729Sjoerg   Elements.addBitCast(GenerateMethodList(
31767330f729Sjoerg           ClassName, CategoryName, {}, true), PtrTy);
31777330f729Sjoerg 
31787330f729Sjoerg   // Protocol list
31797330f729Sjoerg   ConstantInitBuilder ProtocolListBuilder(CGM);
31807330f729Sjoerg   auto ProtocolList = ProtocolListBuilder.beginStruct();
31817330f729Sjoerg   ProtocolList.add(NULLPtr);
31827330f729Sjoerg   ProtocolList.addInt(LongTy, ExistingProtocols.size());
31837330f729Sjoerg   auto ProtocolElements = ProtocolList.beginArray(PtrTy);
31847330f729Sjoerg   for (auto iter = ExistingProtocols.begin(), endIter = ExistingProtocols.end();
31857330f729Sjoerg        iter != endIter ; iter++) {
31867330f729Sjoerg     ProtocolElements.addBitCast(iter->getValue(), PtrTy);
31877330f729Sjoerg   }
31887330f729Sjoerg   ProtocolElements.finishAndAddTo(ProtocolList);
31897330f729Sjoerg   Elements.addBitCast(
31907330f729Sjoerg                    ProtocolList.finishAndCreateGlobal(".objc_protocol_list",
31917330f729Sjoerg                                                       CGM.getPointerAlign()),
31927330f729Sjoerg                    PtrTy);
31937330f729Sjoerg   Categories.push_back(llvm::ConstantExpr::getBitCast(
31947330f729Sjoerg         Elements.finishAndCreateGlobal("", CGM.getPointerAlign()),
31957330f729Sjoerg         PtrTy));
31967330f729Sjoerg }
31977330f729Sjoerg 
31987330f729Sjoerg /// Libobjc2 uses a bitfield representation where small(ish) bitfields are
31997330f729Sjoerg /// stored in a 64-bit value with the low bit set to 1 and the remaining 63
32007330f729Sjoerg /// bits set to their values, LSB first, while larger ones are stored in a
32017330f729Sjoerg /// structure of this / form:
32027330f729Sjoerg ///
32037330f729Sjoerg /// struct { int32_t length; int32_t values[length]; };
32047330f729Sjoerg ///
32057330f729Sjoerg /// The values in the array are stored in host-endian format, with the least
32067330f729Sjoerg /// significant bit being assumed to come first in the bitfield.  Therefore, a
32077330f729Sjoerg /// bitfield with the 64th bit set will be (int64_t)&{ 2, [0, 1<<31] }, while a
32087330f729Sjoerg /// bitfield / with the 63rd bit set will be 1<<64.
MakeBitField(ArrayRef<bool> bits)32097330f729Sjoerg llvm::Constant *CGObjCGNU::MakeBitField(ArrayRef<bool> bits) {
32107330f729Sjoerg   int bitCount = bits.size();
32117330f729Sjoerg   int ptrBits = CGM.getDataLayout().getPointerSizeInBits();
32127330f729Sjoerg   if (bitCount < ptrBits) {
32137330f729Sjoerg     uint64_t val = 1;
32147330f729Sjoerg     for (int i=0 ; i<bitCount ; ++i) {
32157330f729Sjoerg       if (bits[i]) val |= 1ULL<<(i+1);
32167330f729Sjoerg     }
32177330f729Sjoerg     return llvm::ConstantInt::get(IntPtrTy, val);
32187330f729Sjoerg   }
32197330f729Sjoerg   SmallVector<llvm::Constant *, 8> values;
32207330f729Sjoerg   int v=0;
32217330f729Sjoerg   while (v < bitCount) {
32227330f729Sjoerg     int32_t word = 0;
32237330f729Sjoerg     for (int i=0 ; (i<32) && (v<bitCount)  ; ++i) {
32247330f729Sjoerg       if (bits[v]) word |= 1<<i;
32257330f729Sjoerg       v++;
32267330f729Sjoerg     }
32277330f729Sjoerg     values.push_back(llvm::ConstantInt::get(Int32Ty, word));
32287330f729Sjoerg   }
32297330f729Sjoerg 
32307330f729Sjoerg   ConstantInitBuilder builder(CGM);
32317330f729Sjoerg   auto fields = builder.beginStruct();
32327330f729Sjoerg   fields.addInt(Int32Ty, values.size());
32337330f729Sjoerg   auto array = fields.beginArray();
32347330f729Sjoerg   for (auto v : values) array.add(v);
32357330f729Sjoerg   array.finishAndAddTo(fields);
32367330f729Sjoerg 
32377330f729Sjoerg   llvm::Constant *GS =
32387330f729Sjoerg     fields.finishAndCreateGlobal("", CharUnits::fromQuantity(4));
32397330f729Sjoerg   llvm::Constant *ptr = llvm::ConstantExpr::getPtrToInt(GS, IntPtrTy);
32407330f729Sjoerg   return ptr;
32417330f729Sjoerg }
32427330f729Sjoerg 
GenerateCategoryProtocolList(const ObjCCategoryDecl * OCD)32437330f729Sjoerg llvm::Constant *CGObjCGNU::GenerateCategoryProtocolList(const
32447330f729Sjoerg     ObjCCategoryDecl *OCD) {
3245*e038c9c4Sjoerg   const auto &RefPro = OCD->getReferencedProtocols();
3246*e038c9c4Sjoerg   const auto RuntimeProtos =
3247*e038c9c4Sjoerg       GetRuntimeProtocolList(RefPro.begin(), RefPro.end());
32487330f729Sjoerg   SmallVector<std::string, 16> Protocols;
3249*e038c9c4Sjoerg   for (const auto *PD : RuntimeProtos)
32507330f729Sjoerg     Protocols.push_back(PD->getNameAsString());
32517330f729Sjoerg   return GenerateProtocolList(Protocols);
32527330f729Sjoerg }
32537330f729Sjoerg 
GenerateCategory(const ObjCCategoryImplDecl * OCD)32547330f729Sjoerg void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
32557330f729Sjoerg   const ObjCInterfaceDecl *Class = OCD->getClassInterface();
32567330f729Sjoerg   std::string ClassName = Class->getNameAsString();
32577330f729Sjoerg   std::string CategoryName = OCD->getNameAsString();
32587330f729Sjoerg 
32597330f729Sjoerg   // Collect the names of referenced protocols
32607330f729Sjoerg   const ObjCCategoryDecl *CatDecl = OCD->getCategoryDecl();
32617330f729Sjoerg 
32627330f729Sjoerg   ConstantInitBuilder Builder(CGM);
32637330f729Sjoerg   auto Elements = Builder.beginStruct();
32647330f729Sjoerg   Elements.add(MakeConstantString(CategoryName));
32657330f729Sjoerg   Elements.add(MakeConstantString(ClassName));
32667330f729Sjoerg   // Instance method list
32677330f729Sjoerg   SmallVector<ObjCMethodDecl*, 16> InstanceMethods;
32687330f729Sjoerg   InstanceMethods.insert(InstanceMethods.begin(), OCD->instmeth_begin(),
32697330f729Sjoerg       OCD->instmeth_end());
32707330f729Sjoerg   Elements.addBitCast(
32717330f729Sjoerg           GenerateMethodList(ClassName, CategoryName, InstanceMethods, false),
32727330f729Sjoerg           PtrTy);
32737330f729Sjoerg   // Class method list
32747330f729Sjoerg 
32757330f729Sjoerg   SmallVector<ObjCMethodDecl*, 16> ClassMethods;
32767330f729Sjoerg   ClassMethods.insert(ClassMethods.begin(), OCD->classmeth_begin(),
32777330f729Sjoerg       OCD->classmeth_end());
32787330f729Sjoerg   Elements.addBitCast(
32797330f729Sjoerg           GenerateMethodList(ClassName, CategoryName, ClassMethods, true),
32807330f729Sjoerg           PtrTy);
32817330f729Sjoerg   // Protocol list
32827330f729Sjoerg   Elements.addBitCast(GenerateCategoryProtocolList(CatDecl), PtrTy);
32837330f729Sjoerg   if (isRuntime(ObjCRuntime::GNUstep, 2)) {
32847330f729Sjoerg     const ObjCCategoryDecl *Category =
32857330f729Sjoerg       Class->FindCategoryDeclaration(OCD->getIdentifier());
32867330f729Sjoerg     if (Category) {
32877330f729Sjoerg       // Instance properties
32887330f729Sjoerg       Elements.addBitCast(GeneratePropertyList(OCD, Category, false), PtrTy);
32897330f729Sjoerg       // Class properties
32907330f729Sjoerg       Elements.addBitCast(GeneratePropertyList(OCD, Category, true), PtrTy);
32917330f729Sjoerg     } else {
32927330f729Sjoerg       Elements.addNullPointer(PtrTy);
32937330f729Sjoerg       Elements.addNullPointer(PtrTy);
32947330f729Sjoerg     }
32957330f729Sjoerg   }
32967330f729Sjoerg 
32977330f729Sjoerg   Categories.push_back(llvm::ConstantExpr::getBitCast(
32987330f729Sjoerg         Elements.finishAndCreateGlobal(
32997330f729Sjoerg           std::string(".objc_category_")+ClassName+CategoryName,
33007330f729Sjoerg           CGM.getPointerAlign()),
33017330f729Sjoerg         PtrTy));
33027330f729Sjoerg }
33037330f729Sjoerg 
GeneratePropertyList(const Decl * Container,const ObjCContainerDecl * OCD,bool isClassProperty,bool protocolOptionalProperties)33047330f729Sjoerg llvm::Constant *CGObjCGNU::GeneratePropertyList(const Decl *Container,
33057330f729Sjoerg     const ObjCContainerDecl *OCD,
33067330f729Sjoerg     bool isClassProperty,
33077330f729Sjoerg     bool protocolOptionalProperties) {
33087330f729Sjoerg 
33097330f729Sjoerg   SmallVector<const ObjCPropertyDecl *, 16> Properties;
33107330f729Sjoerg   llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
33117330f729Sjoerg   bool isProtocol = isa<ObjCProtocolDecl>(OCD);
33127330f729Sjoerg   ASTContext &Context = CGM.getContext();
33137330f729Sjoerg 
33147330f729Sjoerg   std::function<void(const ObjCProtocolDecl *Proto)> collectProtocolProperties
33157330f729Sjoerg     = [&](const ObjCProtocolDecl *Proto) {
33167330f729Sjoerg       for (const auto *P : Proto->protocols())
33177330f729Sjoerg         collectProtocolProperties(P);
33187330f729Sjoerg       for (const auto *PD : Proto->properties()) {
33197330f729Sjoerg         if (isClassProperty != PD->isClassProperty())
33207330f729Sjoerg           continue;
33217330f729Sjoerg         // Skip any properties that are declared in protocols that this class
33227330f729Sjoerg         // conforms to but are not actually implemented by this class.
33237330f729Sjoerg         if (!isProtocol && !Context.getObjCPropertyImplDeclForPropertyDecl(PD, Container))
33247330f729Sjoerg           continue;
33257330f729Sjoerg         if (!PropertySet.insert(PD->getIdentifier()).second)
33267330f729Sjoerg           continue;
33277330f729Sjoerg         Properties.push_back(PD);
33287330f729Sjoerg       }
33297330f729Sjoerg     };
33307330f729Sjoerg 
33317330f729Sjoerg   if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
33327330f729Sjoerg     for (const ObjCCategoryDecl *ClassExt : OID->known_extensions())
33337330f729Sjoerg       for (auto *PD : ClassExt->properties()) {
33347330f729Sjoerg         if (isClassProperty != PD->isClassProperty())
33357330f729Sjoerg           continue;
33367330f729Sjoerg         PropertySet.insert(PD->getIdentifier());
33377330f729Sjoerg         Properties.push_back(PD);
33387330f729Sjoerg       }
33397330f729Sjoerg 
33407330f729Sjoerg   for (const auto *PD : OCD->properties()) {
33417330f729Sjoerg     if (isClassProperty != PD->isClassProperty())
33427330f729Sjoerg       continue;
33437330f729Sjoerg     // If we're generating a list for a protocol, skip optional / required ones
33447330f729Sjoerg     // when generating the other list.
33457330f729Sjoerg     if (isProtocol && (protocolOptionalProperties != PD->isOptional()))
33467330f729Sjoerg       continue;
33477330f729Sjoerg     // Don't emit duplicate metadata for properties that were already in a
33487330f729Sjoerg     // class extension.
33497330f729Sjoerg     if (!PropertySet.insert(PD->getIdentifier()).second)
33507330f729Sjoerg       continue;
33517330f729Sjoerg 
33527330f729Sjoerg     Properties.push_back(PD);
33537330f729Sjoerg   }
33547330f729Sjoerg 
33557330f729Sjoerg   if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
33567330f729Sjoerg     for (const auto *P : OID->all_referenced_protocols())
33577330f729Sjoerg       collectProtocolProperties(P);
33587330f729Sjoerg   else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD))
33597330f729Sjoerg     for (const auto *P : CD->protocols())
33607330f729Sjoerg       collectProtocolProperties(P);
33617330f729Sjoerg 
33627330f729Sjoerg   auto numProperties = Properties.size();
33637330f729Sjoerg 
33647330f729Sjoerg   if (numProperties == 0)
33657330f729Sjoerg     return NULLPtr;
33667330f729Sjoerg 
33677330f729Sjoerg   ConstantInitBuilder builder(CGM);
33687330f729Sjoerg   auto propertyList = builder.beginStruct();
33697330f729Sjoerg   auto properties = PushPropertyListHeader(propertyList, numProperties);
33707330f729Sjoerg 
33717330f729Sjoerg   // Add all of the property methods need adding to the method list and to the
33727330f729Sjoerg   // property metadata list.
33737330f729Sjoerg   for (auto *property : Properties) {
33747330f729Sjoerg     bool isSynthesized = false;
33757330f729Sjoerg     bool isDynamic = false;
33767330f729Sjoerg     if (!isProtocol) {
33777330f729Sjoerg       auto *propertyImpl = Context.getObjCPropertyImplDeclForPropertyDecl(property, Container);
33787330f729Sjoerg       if (propertyImpl) {
33797330f729Sjoerg         isSynthesized = (propertyImpl->getPropertyImplementation() ==
33807330f729Sjoerg             ObjCPropertyImplDecl::Synthesize);
33817330f729Sjoerg         isDynamic = (propertyImpl->getPropertyImplementation() ==
33827330f729Sjoerg             ObjCPropertyImplDecl::Dynamic);
33837330f729Sjoerg       }
33847330f729Sjoerg     }
33857330f729Sjoerg     PushProperty(properties, property, Container, isSynthesized, isDynamic);
33867330f729Sjoerg   }
33877330f729Sjoerg   properties.finishAndAddTo(propertyList);
33887330f729Sjoerg 
33897330f729Sjoerg   return propertyList.finishAndCreateGlobal(".objc_property_list",
33907330f729Sjoerg                                             CGM.getPointerAlign());
33917330f729Sjoerg }
33927330f729Sjoerg 
RegisterAlias(const ObjCCompatibleAliasDecl * OAD)33937330f729Sjoerg void CGObjCGNU::RegisterAlias(const ObjCCompatibleAliasDecl *OAD) {
33947330f729Sjoerg   // Get the class declaration for which the alias is specified.
33957330f729Sjoerg   ObjCInterfaceDecl *ClassDecl =
33967330f729Sjoerg     const_cast<ObjCInterfaceDecl *>(OAD->getClassInterface());
33977330f729Sjoerg   ClassAliases.emplace_back(ClassDecl->getNameAsString(),
33987330f729Sjoerg                             OAD->getNameAsString());
33997330f729Sjoerg }
34007330f729Sjoerg 
GenerateClass(const ObjCImplementationDecl * OID)34017330f729Sjoerg void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
34027330f729Sjoerg   ASTContext &Context = CGM.getContext();
34037330f729Sjoerg 
34047330f729Sjoerg   // Get the superclass name.
34057330f729Sjoerg   const ObjCInterfaceDecl * SuperClassDecl =
34067330f729Sjoerg     OID->getClassInterface()->getSuperClass();
34077330f729Sjoerg   std::string SuperClassName;
34087330f729Sjoerg   if (SuperClassDecl) {
34097330f729Sjoerg     SuperClassName = SuperClassDecl->getNameAsString();
34107330f729Sjoerg     EmitClassRef(SuperClassName);
34117330f729Sjoerg   }
34127330f729Sjoerg 
34137330f729Sjoerg   // Get the class name
34147330f729Sjoerg   ObjCInterfaceDecl *ClassDecl =
34157330f729Sjoerg       const_cast<ObjCInterfaceDecl *>(OID->getClassInterface());
34167330f729Sjoerg   std::string ClassName = ClassDecl->getNameAsString();
34177330f729Sjoerg 
34187330f729Sjoerg   // Emit the symbol that is used to generate linker errors if this class is
34197330f729Sjoerg   // referenced in other modules but not declared.
34207330f729Sjoerg   std::string classSymbolName = "__objc_class_name_" + ClassName;
34217330f729Sjoerg   if (auto *symbol = TheModule.getGlobalVariable(classSymbolName)) {
34227330f729Sjoerg     symbol->setInitializer(llvm::ConstantInt::get(LongTy, 0));
34237330f729Sjoerg   } else {
34247330f729Sjoerg     new llvm::GlobalVariable(TheModule, LongTy, false,
34257330f729Sjoerg                              llvm::GlobalValue::ExternalLinkage,
34267330f729Sjoerg                              llvm::ConstantInt::get(LongTy, 0),
34277330f729Sjoerg                              classSymbolName);
34287330f729Sjoerg   }
34297330f729Sjoerg 
34307330f729Sjoerg   // Get the size of instances.
34317330f729Sjoerg   int instanceSize =
34327330f729Sjoerg     Context.getASTObjCImplementationLayout(OID).getSize().getQuantity();
34337330f729Sjoerg 
34347330f729Sjoerg   // Collect information about instance variables.
34357330f729Sjoerg   SmallVector<llvm::Constant*, 16> IvarNames;
34367330f729Sjoerg   SmallVector<llvm::Constant*, 16> IvarTypes;
34377330f729Sjoerg   SmallVector<llvm::Constant*, 16> IvarOffsets;
34387330f729Sjoerg   SmallVector<llvm::Constant*, 16> IvarAligns;
34397330f729Sjoerg   SmallVector<Qualifiers::ObjCLifetime, 16> IvarOwnership;
34407330f729Sjoerg 
34417330f729Sjoerg   ConstantInitBuilder IvarOffsetBuilder(CGM);
34427330f729Sjoerg   auto IvarOffsetValues = IvarOffsetBuilder.beginArray(PtrToIntTy);
34437330f729Sjoerg   SmallVector<bool, 16> WeakIvars;
34447330f729Sjoerg   SmallVector<bool, 16> StrongIvars;
34457330f729Sjoerg 
34467330f729Sjoerg   int superInstanceSize = !SuperClassDecl ? 0 :
34477330f729Sjoerg     Context.getASTObjCInterfaceLayout(SuperClassDecl).getSize().getQuantity();
34487330f729Sjoerg   // For non-fragile ivars, set the instance size to 0 - {the size of just this
34497330f729Sjoerg   // class}.  The runtime will then set this to the correct value on load.
34507330f729Sjoerg   if (CGM.getLangOpts().ObjCRuntime.isNonFragile()) {
34517330f729Sjoerg     instanceSize = 0 - (instanceSize - superInstanceSize);
34527330f729Sjoerg   }
34537330f729Sjoerg 
34547330f729Sjoerg   for (const ObjCIvarDecl *IVD = ClassDecl->all_declared_ivar_begin(); IVD;
34557330f729Sjoerg        IVD = IVD->getNextIvar()) {
34567330f729Sjoerg       // Store the name
34577330f729Sjoerg       IvarNames.push_back(MakeConstantString(IVD->getNameAsString()));
34587330f729Sjoerg       // Get the type encoding for this ivar
34597330f729Sjoerg       std::string TypeStr;
34607330f729Sjoerg       Context.getObjCEncodingForType(IVD->getType(), TypeStr, IVD);
34617330f729Sjoerg       IvarTypes.push_back(MakeConstantString(TypeStr));
34627330f729Sjoerg       IvarAligns.push_back(llvm::ConstantInt::get(IntTy,
34637330f729Sjoerg             Context.getTypeSize(IVD->getType())));
34647330f729Sjoerg       // Get the offset
34657330f729Sjoerg       uint64_t BaseOffset = ComputeIvarBaseOffset(CGM, OID, IVD);
34667330f729Sjoerg       uint64_t Offset = BaseOffset;
34677330f729Sjoerg       if (CGM.getLangOpts().ObjCRuntime.isNonFragile()) {
34687330f729Sjoerg         Offset = BaseOffset - superInstanceSize;
34697330f729Sjoerg       }
34707330f729Sjoerg       llvm::Constant *OffsetValue = llvm::ConstantInt::get(IntTy, Offset);
34717330f729Sjoerg       // Create the direct offset value
34727330f729Sjoerg       std::string OffsetName = "__objc_ivar_offset_value_" + ClassName +"." +
34737330f729Sjoerg           IVD->getNameAsString();
34747330f729Sjoerg 
34757330f729Sjoerg       llvm::GlobalVariable *OffsetVar = TheModule.getGlobalVariable(OffsetName);
34767330f729Sjoerg       if (OffsetVar) {
34777330f729Sjoerg         OffsetVar->setInitializer(OffsetValue);
34787330f729Sjoerg         // If this is the real definition, change its linkage type so that
34797330f729Sjoerg         // different modules will use this one, rather than their private
34807330f729Sjoerg         // copy.
34817330f729Sjoerg         OffsetVar->setLinkage(llvm::GlobalValue::ExternalLinkage);
34827330f729Sjoerg       } else
34837330f729Sjoerg         OffsetVar = new llvm::GlobalVariable(TheModule, Int32Ty,
34847330f729Sjoerg           false, llvm::GlobalValue::ExternalLinkage,
34857330f729Sjoerg           OffsetValue, OffsetName);
34867330f729Sjoerg       IvarOffsets.push_back(OffsetValue);
34877330f729Sjoerg       IvarOffsetValues.add(OffsetVar);
34887330f729Sjoerg       Qualifiers::ObjCLifetime lt = IVD->getType().getQualifiers().getObjCLifetime();
34897330f729Sjoerg       IvarOwnership.push_back(lt);
34907330f729Sjoerg       switch (lt) {
34917330f729Sjoerg         case Qualifiers::OCL_Strong:
34927330f729Sjoerg           StrongIvars.push_back(true);
34937330f729Sjoerg           WeakIvars.push_back(false);
34947330f729Sjoerg           break;
34957330f729Sjoerg         case Qualifiers::OCL_Weak:
34967330f729Sjoerg           StrongIvars.push_back(false);
34977330f729Sjoerg           WeakIvars.push_back(true);
34987330f729Sjoerg           break;
34997330f729Sjoerg         default:
35007330f729Sjoerg           StrongIvars.push_back(false);
35017330f729Sjoerg           WeakIvars.push_back(false);
35027330f729Sjoerg       }
35037330f729Sjoerg   }
35047330f729Sjoerg   llvm::Constant *StrongIvarBitmap = MakeBitField(StrongIvars);
35057330f729Sjoerg   llvm::Constant *WeakIvarBitmap = MakeBitField(WeakIvars);
35067330f729Sjoerg   llvm::GlobalVariable *IvarOffsetArray =
35077330f729Sjoerg     IvarOffsetValues.finishAndCreateGlobal(".ivar.offsets",
35087330f729Sjoerg                                            CGM.getPointerAlign());
35097330f729Sjoerg 
35107330f729Sjoerg   // Collect information about instance methods
35117330f729Sjoerg   SmallVector<const ObjCMethodDecl*, 16> InstanceMethods;
35127330f729Sjoerg   InstanceMethods.insert(InstanceMethods.begin(), OID->instmeth_begin(),
35137330f729Sjoerg       OID->instmeth_end());
35147330f729Sjoerg 
35157330f729Sjoerg   SmallVector<const ObjCMethodDecl*, 16> ClassMethods;
35167330f729Sjoerg   ClassMethods.insert(ClassMethods.begin(), OID->classmeth_begin(),
35177330f729Sjoerg       OID->classmeth_end());
35187330f729Sjoerg 
35197330f729Sjoerg   llvm::Constant *Properties = GeneratePropertyList(OID, ClassDecl);
35207330f729Sjoerg 
35217330f729Sjoerg   // Collect the names of referenced protocols
3522*e038c9c4Sjoerg   auto RefProtocols = ClassDecl->protocols();
3523*e038c9c4Sjoerg   auto RuntimeProtocols =
3524*e038c9c4Sjoerg       GetRuntimeProtocolList(RefProtocols.begin(), RefProtocols.end());
35257330f729Sjoerg   SmallVector<std::string, 16> Protocols;
3526*e038c9c4Sjoerg   for (const auto *I : RuntimeProtocols)
35277330f729Sjoerg     Protocols.push_back(I->getNameAsString());
35287330f729Sjoerg 
35297330f729Sjoerg   // Get the superclass pointer.
35307330f729Sjoerg   llvm::Constant *SuperClass;
35317330f729Sjoerg   if (!SuperClassName.empty()) {
35327330f729Sjoerg     SuperClass = MakeConstantString(SuperClassName, ".super_class_name");
35337330f729Sjoerg   } else {
35347330f729Sjoerg     SuperClass = llvm::ConstantPointerNull::get(PtrToInt8Ty);
35357330f729Sjoerg   }
35367330f729Sjoerg   // Empty vector used to construct empty method lists
35377330f729Sjoerg   SmallVector<llvm::Constant*, 1>  empty;
35387330f729Sjoerg   // Generate the method and instance variable lists
35397330f729Sjoerg   llvm::Constant *MethodList = GenerateMethodList(ClassName, "",
35407330f729Sjoerg       InstanceMethods, false);
35417330f729Sjoerg   llvm::Constant *ClassMethodList = GenerateMethodList(ClassName, "",
35427330f729Sjoerg       ClassMethods, true);
35437330f729Sjoerg   llvm::Constant *IvarList = GenerateIvarList(IvarNames, IvarTypes,
35447330f729Sjoerg       IvarOffsets, IvarAligns, IvarOwnership);
35457330f729Sjoerg   // Irrespective of whether we are compiling for a fragile or non-fragile ABI,
35467330f729Sjoerg   // we emit a symbol containing the offset for each ivar in the class.  This
35477330f729Sjoerg   // allows code compiled for the non-Fragile ABI to inherit from code compiled
35487330f729Sjoerg   // for the legacy ABI, without causing problems.  The converse is also
35497330f729Sjoerg   // possible, but causes all ivar accesses to be fragile.
35507330f729Sjoerg 
35517330f729Sjoerg   // Offset pointer for getting at the correct field in the ivar list when
35527330f729Sjoerg   // setting up the alias.  These are: The base address for the global, the
35537330f729Sjoerg   // ivar array (second field), the ivar in this list (set for each ivar), and
35547330f729Sjoerg   // the offset (third field in ivar structure)
35557330f729Sjoerg   llvm::Type *IndexTy = Int32Ty;
35567330f729Sjoerg   llvm::Constant *offsetPointerIndexes[] = {Zeros[0],
35577330f729Sjoerg       llvm::ConstantInt::get(IndexTy, ClassABIVersion > 1 ? 2 : 1), nullptr,
35587330f729Sjoerg       llvm::ConstantInt::get(IndexTy, ClassABIVersion > 1 ? 3 : 2) };
35597330f729Sjoerg 
35607330f729Sjoerg   unsigned ivarIndex = 0;
35617330f729Sjoerg   for (const ObjCIvarDecl *IVD = ClassDecl->all_declared_ivar_begin(); IVD;
35627330f729Sjoerg        IVD = IVD->getNextIvar()) {
35637330f729Sjoerg       const std::string Name = GetIVarOffsetVariableName(ClassDecl, IVD);
35647330f729Sjoerg       offsetPointerIndexes[2] = llvm::ConstantInt::get(IndexTy, ivarIndex);
35657330f729Sjoerg       // Get the correct ivar field
35667330f729Sjoerg       llvm::Constant *offsetValue = llvm::ConstantExpr::getGetElementPtr(
35677330f729Sjoerg           cast<llvm::GlobalVariable>(IvarList)->getValueType(), IvarList,
35687330f729Sjoerg           offsetPointerIndexes);
35697330f729Sjoerg       // Get the existing variable, if one exists.
35707330f729Sjoerg       llvm::GlobalVariable *offset = TheModule.getNamedGlobal(Name);
35717330f729Sjoerg       if (offset) {
35727330f729Sjoerg         offset->setInitializer(offsetValue);
35737330f729Sjoerg         // If this is the real definition, change its linkage type so that
35747330f729Sjoerg         // different modules will use this one, rather than their private
35757330f729Sjoerg         // copy.
35767330f729Sjoerg         offset->setLinkage(llvm::GlobalValue::ExternalLinkage);
35777330f729Sjoerg       } else
35787330f729Sjoerg         // Add a new alias if there isn't one already.
35797330f729Sjoerg         new llvm::GlobalVariable(TheModule, offsetValue->getType(),
35807330f729Sjoerg                 false, llvm::GlobalValue::ExternalLinkage, offsetValue, Name);
35817330f729Sjoerg       ++ivarIndex;
35827330f729Sjoerg   }
35837330f729Sjoerg   llvm::Constant *ZeroPtr = llvm::ConstantInt::get(IntPtrTy, 0);
35847330f729Sjoerg 
35857330f729Sjoerg   //Generate metaclass for class methods
35867330f729Sjoerg   llvm::Constant *MetaClassStruct = GenerateClassStructure(
35877330f729Sjoerg       NULLPtr, NULLPtr, 0x12L, ClassName.c_str(), nullptr, Zeros[0],
35887330f729Sjoerg       NULLPtr, ClassMethodList, NULLPtr, NULLPtr,
35897330f729Sjoerg       GeneratePropertyList(OID, ClassDecl, true), ZeroPtr, ZeroPtr, true);
35907330f729Sjoerg   CGM.setGVProperties(cast<llvm::GlobalValue>(MetaClassStruct),
35917330f729Sjoerg                       OID->getClassInterface());
35927330f729Sjoerg 
35937330f729Sjoerg   // Generate the class structure
35947330f729Sjoerg   llvm::Constant *ClassStruct = GenerateClassStructure(
35957330f729Sjoerg       MetaClassStruct, SuperClass, 0x11L, ClassName.c_str(), nullptr,
35967330f729Sjoerg       llvm::ConstantInt::get(LongTy, instanceSize), IvarList, MethodList,
35977330f729Sjoerg       GenerateProtocolList(Protocols), IvarOffsetArray, Properties,
35987330f729Sjoerg       StrongIvarBitmap, WeakIvarBitmap);
35997330f729Sjoerg   CGM.setGVProperties(cast<llvm::GlobalValue>(ClassStruct),
36007330f729Sjoerg                       OID->getClassInterface());
36017330f729Sjoerg 
36027330f729Sjoerg   // Resolve the class aliases, if they exist.
36037330f729Sjoerg   if (ClassPtrAlias) {
36047330f729Sjoerg     ClassPtrAlias->replaceAllUsesWith(
36057330f729Sjoerg         llvm::ConstantExpr::getBitCast(ClassStruct, IdTy));
36067330f729Sjoerg     ClassPtrAlias->eraseFromParent();
36077330f729Sjoerg     ClassPtrAlias = nullptr;
36087330f729Sjoerg   }
36097330f729Sjoerg   if (MetaClassPtrAlias) {
36107330f729Sjoerg     MetaClassPtrAlias->replaceAllUsesWith(
36117330f729Sjoerg         llvm::ConstantExpr::getBitCast(MetaClassStruct, IdTy));
36127330f729Sjoerg     MetaClassPtrAlias->eraseFromParent();
36137330f729Sjoerg     MetaClassPtrAlias = nullptr;
36147330f729Sjoerg   }
36157330f729Sjoerg 
36167330f729Sjoerg   // Add class structure to list to be added to the symtab later
36177330f729Sjoerg   ClassStruct = llvm::ConstantExpr::getBitCast(ClassStruct, PtrToInt8Ty);
36187330f729Sjoerg   Classes.push_back(ClassStruct);
36197330f729Sjoerg }
36207330f729Sjoerg 
ModuleInitFunction()36217330f729Sjoerg llvm::Function *CGObjCGNU::ModuleInitFunction() {
36227330f729Sjoerg   // Only emit an ObjC load function if no Objective-C stuff has been called
36237330f729Sjoerg   if (Classes.empty() && Categories.empty() && ConstantStrings.empty() &&
36247330f729Sjoerg       ExistingProtocols.empty() && SelectorTable.empty())
36257330f729Sjoerg     return nullptr;
36267330f729Sjoerg 
36277330f729Sjoerg   // Add all referenced protocols to a category.
36287330f729Sjoerg   GenerateProtocolHolderCategory();
36297330f729Sjoerg 
36307330f729Sjoerg   llvm::StructType *selStructTy =
36317330f729Sjoerg     dyn_cast<llvm::StructType>(SelectorTy->getElementType());
36327330f729Sjoerg   llvm::Type *selStructPtrTy = SelectorTy;
36337330f729Sjoerg   if (!selStructTy) {
36347330f729Sjoerg     selStructTy = llvm::StructType::get(CGM.getLLVMContext(),
36357330f729Sjoerg                                         { PtrToInt8Ty, PtrToInt8Ty });
36367330f729Sjoerg     selStructPtrTy = llvm::PointerType::getUnqual(selStructTy);
36377330f729Sjoerg   }
36387330f729Sjoerg 
36397330f729Sjoerg   // Generate statics list:
36407330f729Sjoerg   llvm::Constant *statics = NULLPtr;
36417330f729Sjoerg   if (!ConstantStrings.empty()) {
36427330f729Sjoerg     llvm::GlobalVariable *fileStatics = [&] {
36437330f729Sjoerg       ConstantInitBuilder builder(CGM);
36447330f729Sjoerg       auto staticsStruct = builder.beginStruct();
36457330f729Sjoerg 
36467330f729Sjoerg       StringRef stringClass = CGM.getLangOpts().ObjCConstantStringClass;
36477330f729Sjoerg       if (stringClass.empty()) stringClass = "NXConstantString";
36487330f729Sjoerg       staticsStruct.add(MakeConstantString(stringClass,
36497330f729Sjoerg                                            ".objc_static_class_name"));
36507330f729Sjoerg 
36517330f729Sjoerg       auto array = staticsStruct.beginArray();
36527330f729Sjoerg       array.addAll(ConstantStrings);
36537330f729Sjoerg       array.add(NULLPtr);
36547330f729Sjoerg       array.finishAndAddTo(staticsStruct);
36557330f729Sjoerg 
36567330f729Sjoerg       return staticsStruct.finishAndCreateGlobal(".objc_statics",
36577330f729Sjoerg                                                  CGM.getPointerAlign());
36587330f729Sjoerg     }();
36597330f729Sjoerg 
36607330f729Sjoerg     ConstantInitBuilder builder(CGM);
36617330f729Sjoerg     auto allStaticsArray = builder.beginArray(fileStatics->getType());
36627330f729Sjoerg     allStaticsArray.add(fileStatics);
36637330f729Sjoerg     allStaticsArray.addNullPointer(fileStatics->getType());
36647330f729Sjoerg 
36657330f729Sjoerg     statics = allStaticsArray.finishAndCreateGlobal(".objc_statics_ptr",
36667330f729Sjoerg                                                     CGM.getPointerAlign());
36677330f729Sjoerg     statics = llvm::ConstantExpr::getBitCast(statics, PtrTy);
36687330f729Sjoerg   }
36697330f729Sjoerg 
36707330f729Sjoerg   // Array of classes, categories, and constant objects.
36717330f729Sjoerg 
36727330f729Sjoerg   SmallVector<llvm::GlobalAlias*, 16> selectorAliases;
36737330f729Sjoerg   unsigned selectorCount;
36747330f729Sjoerg 
36757330f729Sjoerg   // Pointer to an array of selectors used in this module.
36767330f729Sjoerg   llvm::GlobalVariable *selectorList = [&] {
36777330f729Sjoerg     ConstantInitBuilder builder(CGM);
36787330f729Sjoerg     auto selectors = builder.beginArray(selStructTy);
36797330f729Sjoerg     auto &table = SelectorTable; // MSVC workaround
36807330f729Sjoerg     std::vector<Selector> allSelectors;
36817330f729Sjoerg     for (auto &entry : table)
36827330f729Sjoerg       allSelectors.push_back(entry.first);
36837330f729Sjoerg     llvm::sort(allSelectors);
36847330f729Sjoerg 
36857330f729Sjoerg     for (auto &untypedSel : allSelectors) {
36867330f729Sjoerg       std::string selNameStr = untypedSel.getAsString();
36877330f729Sjoerg       llvm::Constant *selName = ExportUniqueString(selNameStr, ".objc_sel_name");
36887330f729Sjoerg 
36897330f729Sjoerg       for (TypedSelector &sel : table[untypedSel]) {
36907330f729Sjoerg         llvm::Constant *selectorTypeEncoding = NULLPtr;
36917330f729Sjoerg         if (!sel.first.empty())
36927330f729Sjoerg           selectorTypeEncoding =
36937330f729Sjoerg             MakeConstantString(sel.first, ".objc_sel_types");
36947330f729Sjoerg 
36957330f729Sjoerg         auto selStruct = selectors.beginStruct(selStructTy);
36967330f729Sjoerg         selStruct.add(selName);
36977330f729Sjoerg         selStruct.add(selectorTypeEncoding);
36987330f729Sjoerg         selStruct.finishAndAddTo(selectors);
36997330f729Sjoerg 
37007330f729Sjoerg         // Store the selector alias for later replacement
37017330f729Sjoerg         selectorAliases.push_back(sel.second);
37027330f729Sjoerg       }
37037330f729Sjoerg     }
37047330f729Sjoerg 
37057330f729Sjoerg     // Remember the number of entries in the selector table.
37067330f729Sjoerg     selectorCount = selectors.size();
37077330f729Sjoerg 
37087330f729Sjoerg     // NULL-terminate the selector list.  This should not actually be required,
37097330f729Sjoerg     // because the selector list has a length field.  Unfortunately, the GCC
37107330f729Sjoerg     // runtime decides to ignore the length field and expects a NULL terminator,
37117330f729Sjoerg     // and GCC cooperates with this by always setting the length to 0.
37127330f729Sjoerg     auto selStruct = selectors.beginStruct(selStructTy);
37137330f729Sjoerg     selStruct.add(NULLPtr);
37147330f729Sjoerg     selStruct.add(NULLPtr);
37157330f729Sjoerg     selStruct.finishAndAddTo(selectors);
37167330f729Sjoerg 
37177330f729Sjoerg     return selectors.finishAndCreateGlobal(".objc_selector_list",
37187330f729Sjoerg                                            CGM.getPointerAlign());
37197330f729Sjoerg   }();
37207330f729Sjoerg 
37217330f729Sjoerg   // Now that all of the static selectors exist, create pointers to them.
37227330f729Sjoerg   for (unsigned i = 0; i < selectorCount; ++i) {
37237330f729Sjoerg     llvm::Constant *idxs[] = {
37247330f729Sjoerg       Zeros[0],
37257330f729Sjoerg       llvm::ConstantInt::get(Int32Ty, i)
37267330f729Sjoerg     };
37277330f729Sjoerg     // FIXME: We're generating redundant loads and stores here!
37287330f729Sjoerg     llvm::Constant *selPtr = llvm::ConstantExpr::getGetElementPtr(
37297330f729Sjoerg         selectorList->getValueType(), selectorList, idxs);
37307330f729Sjoerg     // If selectors are defined as an opaque type, cast the pointer to this
37317330f729Sjoerg     // type.
37327330f729Sjoerg     selPtr = llvm::ConstantExpr::getBitCast(selPtr, SelectorTy);
37337330f729Sjoerg     selectorAliases[i]->replaceAllUsesWith(selPtr);
37347330f729Sjoerg     selectorAliases[i]->eraseFromParent();
37357330f729Sjoerg   }
37367330f729Sjoerg 
37377330f729Sjoerg   llvm::GlobalVariable *symtab = [&] {
37387330f729Sjoerg     ConstantInitBuilder builder(CGM);
37397330f729Sjoerg     auto symtab = builder.beginStruct();
37407330f729Sjoerg 
37417330f729Sjoerg     // Number of static selectors
37427330f729Sjoerg     symtab.addInt(LongTy, selectorCount);
37437330f729Sjoerg 
37447330f729Sjoerg     symtab.addBitCast(selectorList, selStructPtrTy);
37457330f729Sjoerg 
37467330f729Sjoerg     // Number of classes defined.
37477330f729Sjoerg     symtab.addInt(CGM.Int16Ty, Classes.size());
37487330f729Sjoerg     // Number of categories defined
37497330f729Sjoerg     symtab.addInt(CGM.Int16Ty, Categories.size());
37507330f729Sjoerg 
37517330f729Sjoerg     // Create an array of classes, then categories, then static object instances
37527330f729Sjoerg     auto classList = symtab.beginArray(PtrToInt8Ty);
37537330f729Sjoerg     classList.addAll(Classes);
37547330f729Sjoerg     classList.addAll(Categories);
37557330f729Sjoerg     //  NULL-terminated list of static object instances (mainly constant strings)
37567330f729Sjoerg     classList.add(statics);
37577330f729Sjoerg     classList.add(NULLPtr);
37587330f729Sjoerg     classList.finishAndAddTo(symtab);
37597330f729Sjoerg 
37607330f729Sjoerg     // Construct the symbol table.
37617330f729Sjoerg     return symtab.finishAndCreateGlobal("", CGM.getPointerAlign());
37627330f729Sjoerg   }();
37637330f729Sjoerg 
37647330f729Sjoerg   // The symbol table is contained in a module which has some version-checking
37657330f729Sjoerg   // constants
37667330f729Sjoerg   llvm::Constant *module = [&] {
37677330f729Sjoerg     llvm::Type *moduleEltTys[] = {
37687330f729Sjoerg       LongTy, LongTy, PtrToInt8Ty, symtab->getType(), IntTy
37697330f729Sjoerg     };
37707330f729Sjoerg     llvm::StructType *moduleTy =
37717330f729Sjoerg       llvm::StructType::get(CGM.getLLVMContext(),
37727330f729Sjoerg          makeArrayRef(moduleEltTys).drop_back(unsigned(RuntimeVersion < 10)));
37737330f729Sjoerg 
37747330f729Sjoerg     ConstantInitBuilder builder(CGM);
37757330f729Sjoerg     auto module = builder.beginStruct(moduleTy);
37767330f729Sjoerg     // Runtime version, used for ABI compatibility checking.
37777330f729Sjoerg     module.addInt(LongTy, RuntimeVersion);
37787330f729Sjoerg     // sizeof(ModuleTy)
37797330f729Sjoerg     module.addInt(LongTy, CGM.getDataLayout().getTypeStoreSize(moduleTy));
37807330f729Sjoerg 
37817330f729Sjoerg     // The path to the source file where this module was declared
37827330f729Sjoerg     SourceManager &SM = CGM.getContext().getSourceManager();
37837330f729Sjoerg     const FileEntry *mainFile = SM.getFileEntryForID(SM.getMainFileID());
37847330f729Sjoerg     std::string path =
37857330f729Sjoerg       (Twine(mainFile->getDir()->getName()) + "/" + mainFile->getName()).str();
37867330f729Sjoerg     module.add(MakeConstantString(path, ".objc_source_file_name"));
37877330f729Sjoerg     module.add(symtab);
37887330f729Sjoerg 
37897330f729Sjoerg     if (RuntimeVersion >= 10) {
37907330f729Sjoerg       switch (CGM.getLangOpts().getGC()) {
37917330f729Sjoerg       case LangOptions::GCOnly:
37927330f729Sjoerg         module.addInt(IntTy, 2);
37937330f729Sjoerg         break;
37947330f729Sjoerg       case LangOptions::NonGC:
37957330f729Sjoerg         if (CGM.getLangOpts().ObjCAutoRefCount)
37967330f729Sjoerg           module.addInt(IntTy, 1);
37977330f729Sjoerg         else
37987330f729Sjoerg           module.addInt(IntTy, 0);
37997330f729Sjoerg         break;
38007330f729Sjoerg       case LangOptions::HybridGC:
38017330f729Sjoerg         module.addInt(IntTy, 1);
38027330f729Sjoerg         break;
38037330f729Sjoerg       }
38047330f729Sjoerg     }
38057330f729Sjoerg 
38067330f729Sjoerg     return module.finishAndCreateGlobal("", CGM.getPointerAlign());
38077330f729Sjoerg   }();
38087330f729Sjoerg 
38097330f729Sjoerg   // Create the load function calling the runtime entry point with the module
38107330f729Sjoerg   // structure
38117330f729Sjoerg   llvm::Function * LoadFunction = llvm::Function::Create(
38127330f729Sjoerg       llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), false),
38137330f729Sjoerg       llvm::GlobalValue::InternalLinkage, ".objc_load_function",
38147330f729Sjoerg       &TheModule);
38157330f729Sjoerg   llvm::BasicBlock *EntryBB =
38167330f729Sjoerg       llvm::BasicBlock::Create(VMContext, "entry", LoadFunction);
38177330f729Sjoerg   CGBuilderTy Builder(CGM, VMContext);
38187330f729Sjoerg   Builder.SetInsertPoint(EntryBB);
38197330f729Sjoerg 
38207330f729Sjoerg   llvm::FunctionType *FT =
38217330f729Sjoerg     llvm::FunctionType::get(Builder.getVoidTy(), module->getType(), true);
38227330f729Sjoerg   llvm::FunctionCallee Register =
38237330f729Sjoerg       CGM.CreateRuntimeFunction(FT, "__objc_exec_class");
38247330f729Sjoerg   Builder.CreateCall(Register, module);
38257330f729Sjoerg 
38267330f729Sjoerg   if (!ClassAliases.empty()) {
38277330f729Sjoerg     llvm::Type *ArgTypes[2] = {PtrTy, PtrToInt8Ty};
38287330f729Sjoerg     llvm::FunctionType *RegisterAliasTy =
38297330f729Sjoerg       llvm::FunctionType::get(Builder.getVoidTy(),
38307330f729Sjoerg                               ArgTypes, false);
38317330f729Sjoerg     llvm::Function *RegisterAlias = llvm::Function::Create(
38327330f729Sjoerg       RegisterAliasTy,
38337330f729Sjoerg       llvm::GlobalValue::ExternalWeakLinkage, "class_registerAlias_np",
38347330f729Sjoerg       &TheModule);
38357330f729Sjoerg     llvm::BasicBlock *AliasBB =
38367330f729Sjoerg       llvm::BasicBlock::Create(VMContext, "alias", LoadFunction);
38377330f729Sjoerg     llvm::BasicBlock *NoAliasBB =
38387330f729Sjoerg       llvm::BasicBlock::Create(VMContext, "no_alias", LoadFunction);
38397330f729Sjoerg 
38407330f729Sjoerg     // Branch based on whether the runtime provided class_registerAlias_np()
38417330f729Sjoerg     llvm::Value *HasRegisterAlias = Builder.CreateICmpNE(RegisterAlias,
38427330f729Sjoerg             llvm::Constant::getNullValue(RegisterAlias->getType()));
38437330f729Sjoerg     Builder.CreateCondBr(HasRegisterAlias, AliasBB, NoAliasBB);
38447330f729Sjoerg 
38457330f729Sjoerg     // The true branch (has alias registration function):
38467330f729Sjoerg     Builder.SetInsertPoint(AliasBB);
38477330f729Sjoerg     // Emit alias registration calls:
38487330f729Sjoerg     for (std::vector<ClassAliasPair>::iterator iter = ClassAliases.begin();
38497330f729Sjoerg        iter != ClassAliases.end(); ++iter) {
38507330f729Sjoerg        llvm::Constant *TheClass =
38517330f729Sjoerg           TheModule.getGlobalVariable("_OBJC_CLASS_" + iter->first, true);
38527330f729Sjoerg        if (TheClass) {
38537330f729Sjoerg          TheClass = llvm::ConstantExpr::getBitCast(TheClass, PtrTy);
38547330f729Sjoerg          Builder.CreateCall(RegisterAlias,
38557330f729Sjoerg                             {TheClass, MakeConstantString(iter->second)});
38567330f729Sjoerg        }
38577330f729Sjoerg     }
38587330f729Sjoerg     // Jump to end:
38597330f729Sjoerg     Builder.CreateBr(NoAliasBB);
38607330f729Sjoerg 
38617330f729Sjoerg     // Missing alias registration function, just return from the function:
38627330f729Sjoerg     Builder.SetInsertPoint(NoAliasBB);
38637330f729Sjoerg   }
38647330f729Sjoerg   Builder.CreateRetVoid();
38657330f729Sjoerg 
38667330f729Sjoerg   return LoadFunction;
38677330f729Sjoerg }
38687330f729Sjoerg 
GenerateMethod(const ObjCMethodDecl * OMD,const ObjCContainerDecl * CD)38697330f729Sjoerg llvm::Function *CGObjCGNU::GenerateMethod(const ObjCMethodDecl *OMD,
38707330f729Sjoerg                                           const ObjCContainerDecl *CD) {
38717330f729Sjoerg   CodeGenTypes &Types = CGM.getTypes();
38727330f729Sjoerg   llvm::FunctionType *MethodTy =
38737330f729Sjoerg     Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
3874*e038c9c4Sjoerg   std::string FunctionName = getSymbolNameForMethod(OMD);
38757330f729Sjoerg 
38767330f729Sjoerg   llvm::Function *Method
38777330f729Sjoerg     = llvm::Function::Create(MethodTy,
38787330f729Sjoerg                              llvm::GlobalValue::InternalLinkage,
38797330f729Sjoerg                              FunctionName,
38807330f729Sjoerg                              &TheModule);
38817330f729Sjoerg   return Method;
38827330f729Sjoerg }
38837330f729Sjoerg 
GenerateDirectMethodPrologue(CodeGenFunction & CGF,llvm::Function * Fn,const ObjCMethodDecl * OMD,const ObjCContainerDecl * CD)3884*e038c9c4Sjoerg void CGObjCGNU::GenerateDirectMethodPrologue(CodeGenFunction &CGF,
3885*e038c9c4Sjoerg                                              llvm::Function *Fn,
3886*e038c9c4Sjoerg                                              const ObjCMethodDecl *OMD,
3887*e038c9c4Sjoerg                                              const ObjCContainerDecl *CD) {
3888*e038c9c4Sjoerg   // GNU runtime doesn't support direct calls at this time
3889*e038c9c4Sjoerg }
3890*e038c9c4Sjoerg 
GetPropertyGetFunction()38917330f729Sjoerg llvm::FunctionCallee CGObjCGNU::GetPropertyGetFunction() {
38927330f729Sjoerg   return GetPropertyFn;
38937330f729Sjoerg }
38947330f729Sjoerg 
GetPropertySetFunction()38957330f729Sjoerg llvm::FunctionCallee CGObjCGNU::GetPropertySetFunction() {
38967330f729Sjoerg   return SetPropertyFn;
38977330f729Sjoerg }
38987330f729Sjoerg 
GetOptimizedPropertySetFunction(bool atomic,bool copy)38997330f729Sjoerg llvm::FunctionCallee CGObjCGNU::GetOptimizedPropertySetFunction(bool atomic,
39007330f729Sjoerg                                                                 bool copy) {
39017330f729Sjoerg   return nullptr;
39027330f729Sjoerg }
39037330f729Sjoerg 
GetGetStructFunction()39047330f729Sjoerg llvm::FunctionCallee CGObjCGNU::GetGetStructFunction() {
39057330f729Sjoerg   return GetStructPropertyFn;
39067330f729Sjoerg }
39077330f729Sjoerg 
GetSetStructFunction()39087330f729Sjoerg llvm::FunctionCallee CGObjCGNU::GetSetStructFunction() {
39097330f729Sjoerg   return SetStructPropertyFn;
39107330f729Sjoerg }
39117330f729Sjoerg 
GetCppAtomicObjectGetFunction()39127330f729Sjoerg llvm::FunctionCallee CGObjCGNU::GetCppAtomicObjectGetFunction() {
39137330f729Sjoerg   return nullptr;
39147330f729Sjoerg }
39157330f729Sjoerg 
GetCppAtomicObjectSetFunction()39167330f729Sjoerg llvm::FunctionCallee CGObjCGNU::GetCppAtomicObjectSetFunction() {
39177330f729Sjoerg   return nullptr;
39187330f729Sjoerg }
39197330f729Sjoerg 
EnumerationMutationFunction()39207330f729Sjoerg llvm::FunctionCallee CGObjCGNU::EnumerationMutationFunction() {
39217330f729Sjoerg   return EnumerationMutationFn;
39227330f729Sjoerg }
39237330f729Sjoerg 
EmitSynchronizedStmt(CodeGenFunction & CGF,const ObjCAtSynchronizedStmt & S)39247330f729Sjoerg void CGObjCGNU::EmitSynchronizedStmt(CodeGenFunction &CGF,
39257330f729Sjoerg                                      const ObjCAtSynchronizedStmt &S) {
39267330f729Sjoerg   EmitAtSynchronizedStmt(CGF, S, SyncEnterFn, SyncExitFn);
39277330f729Sjoerg }
39287330f729Sjoerg 
39297330f729Sjoerg 
EmitTryStmt(CodeGenFunction & CGF,const ObjCAtTryStmt & S)39307330f729Sjoerg void CGObjCGNU::EmitTryStmt(CodeGenFunction &CGF,
39317330f729Sjoerg                             const ObjCAtTryStmt &S) {
39327330f729Sjoerg   // Unlike the Apple non-fragile runtimes, which also uses
39337330f729Sjoerg   // unwind-based zero cost exceptions, the GNU Objective C runtime's
39347330f729Sjoerg   // EH support isn't a veneer over C++ EH.  Instead, exception
39357330f729Sjoerg   // objects are created by objc_exception_throw and destroyed by
39367330f729Sjoerg   // the personality function; this avoids the need for bracketing
39377330f729Sjoerg   // catch handlers with calls to __blah_begin_catch/__blah_end_catch
39387330f729Sjoerg   // (or even _Unwind_DeleteException), but probably doesn't
39397330f729Sjoerg   // interoperate very well with foreign exceptions.
39407330f729Sjoerg   //
39417330f729Sjoerg   // In Objective-C++ mode, we actually emit something equivalent to the C++
39427330f729Sjoerg   // exception handler.
39437330f729Sjoerg   EmitTryCatchStmt(CGF, S, EnterCatchFn, ExitCatchFn, ExceptionReThrowFn);
39447330f729Sjoerg }
39457330f729Sjoerg 
EmitThrowStmt(CodeGenFunction & CGF,const ObjCAtThrowStmt & S,bool ClearInsertionPoint)39467330f729Sjoerg void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF,
39477330f729Sjoerg                               const ObjCAtThrowStmt &S,
39487330f729Sjoerg                               bool ClearInsertionPoint) {
39497330f729Sjoerg   llvm::Value *ExceptionAsObject;
39507330f729Sjoerg   bool isRethrow = false;
39517330f729Sjoerg 
39527330f729Sjoerg   if (const Expr *ThrowExpr = S.getThrowExpr()) {
39537330f729Sjoerg     llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
39547330f729Sjoerg     ExceptionAsObject = Exception;
39557330f729Sjoerg   } else {
39567330f729Sjoerg     assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
39577330f729Sjoerg            "Unexpected rethrow outside @catch block.");
39587330f729Sjoerg     ExceptionAsObject = CGF.ObjCEHValueStack.back();
39597330f729Sjoerg     isRethrow = true;
39607330f729Sjoerg   }
39617330f729Sjoerg   if (isRethrow && usesSEHExceptions) {
39627330f729Sjoerg     // For SEH, ExceptionAsObject may be undef, because the catch handler is
39637330f729Sjoerg     // not passed it for catchalls and so it is not visible to the catch
39647330f729Sjoerg     // funclet.  The real thrown object will still be live on the stack at this
39657330f729Sjoerg     // point and will be rethrown.  If we are explicitly rethrowing the object
39667330f729Sjoerg     // that was passed into the `@catch` block, then this code path is not
39677330f729Sjoerg     // reached and we will instead call `objc_exception_throw` with an explicit
39687330f729Sjoerg     // argument.
39697330f729Sjoerg     llvm::CallBase *Throw = CGF.EmitRuntimeCallOrInvoke(ExceptionReThrowFn);
39707330f729Sjoerg     Throw->setDoesNotReturn();
39717330f729Sjoerg   }
39727330f729Sjoerg   else {
39737330f729Sjoerg     ExceptionAsObject = CGF.Builder.CreateBitCast(ExceptionAsObject, IdTy);
39747330f729Sjoerg     llvm::CallBase *Throw =
39757330f729Sjoerg         CGF.EmitRuntimeCallOrInvoke(ExceptionThrowFn, ExceptionAsObject);
39767330f729Sjoerg     Throw->setDoesNotReturn();
39777330f729Sjoerg   }
39787330f729Sjoerg   CGF.Builder.CreateUnreachable();
39797330f729Sjoerg   if (ClearInsertionPoint)
39807330f729Sjoerg     CGF.Builder.ClearInsertionPoint();
39817330f729Sjoerg }
39827330f729Sjoerg 
EmitObjCWeakRead(CodeGenFunction & CGF,Address AddrWeakObj)39837330f729Sjoerg llvm::Value * CGObjCGNU::EmitObjCWeakRead(CodeGenFunction &CGF,
39847330f729Sjoerg                                           Address AddrWeakObj) {
39857330f729Sjoerg   CGBuilderTy &B = CGF.Builder;
39867330f729Sjoerg   AddrWeakObj = EnforceType(B, AddrWeakObj, PtrToIdTy);
39877330f729Sjoerg   return B.CreateCall(WeakReadFn, AddrWeakObj.getPointer());
39887330f729Sjoerg }
39897330f729Sjoerg 
EmitObjCWeakAssign(CodeGenFunction & CGF,llvm::Value * src,Address dst)39907330f729Sjoerg void CGObjCGNU::EmitObjCWeakAssign(CodeGenFunction &CGF,
39917330f729Sjoerg                                    llvm::Value *src, Address dst) {
39927330f729Sjoerg   CGBuilderTy &B = CGF.Builder;
39937330f729Sjoerg   src = EnforceType(B, src, IdTy);
39947330f729Sjoerg   dst = EnforceType(B, dst, PtrToIdTy);
39957330f729Sjoerg   B.CreateCall(WeakAssignFn, {src, dst.getPointer()});
39967330f729Sjoerg }
39977330f729Sjoerg 
EmitObjCGlobalAssign(CodeGenFunction & CGF,llvm::Value * src,Address dst,bool threadlocal)39987330f729Sjoerg void CGObjCGNU::EmitObjCGlobalAssign(CodeGenFunction &CGF,
39997330f729Sjoerg                                      llvm::Value *src, Address dst,
40007330f729Sjoerg                                      bool threadlocal) {
40017330f729Sjoerg   CGBuilderTy &B = CGF.Builder;
40027330f729Sjoerg   src = EnforceType(B, src, IdTy);
40037330f729Sjoerg   dst = EnforceType(B, dst, PtrToIdTy);
40047330f729Sjoerg   // FIXME. Add threadloca assign API
40057330f729Sjoerg   assert(!threadlocal && "EmitObjCGlobalAssign - Threal Local API NYI");
40067330f729Sjoerg   B.CreateCall(GlobalAssignFn, {src, dst.getPointer()});
40077330f729Sjoerg }
40087330f729Sjoerg 
EmitObjCIvarAssign(CodeGenFunction & CGF,llvm::Value * src,Address dst,llvm::Value * ivarOffset)40097330f729Sjoerg void CGObjCGNU::EmitObjCIvarAssign(CodeGenFunction &CGF,
40107330f729Sjoerg                                    llvm::Value *src, Address dst,
40117330f729Sjoerg                                    llvm::Value *ivarOffset) {
40127330f729Sjoerg   CGBuilderTy &B = CGF.Builder;
40137330f729Sjoerg   src = EnforceType(B, src, IdTy);
40147330f729Sjoerg   dst = EnforceType(B, dst, IdTy);
40157330f729Sjoerg   B.CreateCall(IvarAssignFn, {src, dst.getPointer(), ivarOffset});
40167330f729Sjoerg }
40177330f729Sjoerg 
EmitObjCStrongCastAssign(CodeGenFunction & CGF,llvm::Value * src,Address dst)40187330f729Sjoerg void CGObjCGNU::EmitObjCStrongCastAssign(CodeGenFunction &CGF,
40197330f729Sjoerg                                          llvm::Value *src, Address dst) {
40207330f729Sjoerg   CGBuilderTy &B = CGF.Builder;
40217330f729Sjoerg   src = EnforceType(B, src, IdTy);
40227330f729Sjoerg   dst = EnforceType(B, dst, PtrToIdTy);
40237330f729Sjoerg   B.CreateCall(StrongCastAssignFn, {src, dst.getPointer()});
40247330f729Sjoerg }
40257330f729Sjoerg 
EmitGCMemmoveCollectable(CodeGenFunction & CGF,Address DestPtr,Address SrcPtr,llvm::Value * Size)40267330f729Sjoerg void CGObjCGNU::EmitGCMemmoveCollectable(CodeGenFunction &CGF,
40277330f729Sjoerg                                          Address DestPtr,
40287330f729Sjoerg                                          Address SrcPtr,
40297330f729Sjoerg                                          llvm::Value *Size) {
40307330f729Sjoerg   CGBuilderTy &B = CGF.Builder;
40317330f729Sjoerg   DestPtr = EnforceType(B, DestPtr, PtrTy);
40327330f729Sjoerg   SrcPtr = EnforceType(B, SrcPtr, PtrTy);
40337330f729Sjoerg 
40347330f729Sjoerg   B.CreateCall(MemMoveFn, {DestPtr.getPointer(), SrcPtr.getPointer(), Size});
40357330f729Sjoerg }
40367330f729Sjoerg 
ObjCIvarOffsetVariable(const ObjCInterfaceDecl * ID,const ObjCIvarDecl * Ivar)40377330f729Sjoerg llvm::GlobalVariable *CGObjCGNU::ObjCIvarOffsetVariable(
40387330f729Sjoerg                               const ObjCInterfaceDecl *ID,
40397330f729Sjoerg                               const ObjCIvarDecl *Ivar) {
40407330f729Sjoerg   const std::string Name = GetIVarOffsetVariableName(ID, Ivar);
40417330f729Sjoerg   // Emit the variable and initialize it with what we think the correct value
40427330f729Sjoerg   // is.  This allows code compiled with non-fragile ivars to work correctly
40437330f729Sjoerg   // when linked against code which isn't (most of the time).
40447330f729Sjoerg   llvm::GlobalVariable *IvarOffsetPointer = TheModule.getNamedGlobal(Name);
40457330f729Sjoerg   if (!IvarOffsetPointer)
40467330f729Sjoerg     IvarOffsetPointer = new llvm::GlobalVariable(TheModule,
40477330f729Sjoerg             llvm::Type::getInt32PtrTy(VMContext), false,
40487330f729Sjoerg             llvm::GlobalValue::ExternalLinkage, nullptr, Name);
40497330f729Sjoerg   return IvarOffsetPointer;
40507330f729Sjoerg }
40517330f729Sjoerg 
EmitObjCValueForIvar(CodeGenFunction & CGF,QualType ObjectTy,llvm::Value * BaseValue,const ObjCIvarDecl * Ivar,unsigned CVRQualifiers)40527330f729Sjoerg LValue CGObjCGNU::EmitObjCValueForIvar(CodeGenFunction &CGF,
40537330f729Sjoerg                                        QualType ObjectTy,
40547330f729Sjoerg                                        llvm::Value *BaseValue,
40557330f729Sjoerg                                        const ObjCIvarDecl *Ivar,
40567330f729Sjoerg                                        unsigned CVRQualifiers) {
40577330f729Sjoerg   const ObjCInterfaceDecl *ID =
40587330f729Sjoerg     ObjectTy->castAs<ObjCObjectType>()->getInterface();
40597330f729Sjoerg   return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
40607330f729Sjoerg                                   EmitIvarOffset(CGF, ID, Ivar));
40617330f729Sjoerg }
40627330f729Sjoerg 
FindIvarInterface(ASTContext & Context,const ObjCInterfaceDecl * OID,const ObjCIvarDecl * OIVD)40637330f729Sjoerg static const ObjCInterfaceDecl *FindIvarInterface(ASTContext &Context,
40647330f729Sjoerg                                                   const ObjCInterfaceDecl *OID,
40657330f729Sjoerg                                                   const ObjCIvarDecl *OIVD) {
40667330f729Sjoerg   for (const ObjCIvarDecl *next = OID->all_declared_ivar_begin(); next;
40677330f729Sjoerg        next = next->getNextIvar()) {
40687330f729Sjoerg     if (OIVD == next)
40697330f729Sjoerg       return OID;
40707330f729Sjoerg   }
40717330f729Sjoerg 
40727330f729Sjoerg   // Otherwise check in the super class.
40737330f729Sjoerg   if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
40747330f729Sjoerg     return FindIvarInterface(Context, Super, OIVD);
40757330f729Sjoerg 
40767330f729Sjoerg   return nullptr;
40777330f729Sjoerg }
40787330f729Sjoerg 
EmitIvarOffset(CodeGenFunction & CGF,const ObjCInterfaceDecl * Interface,const ObjCIvarDecl * Ivar)40797330f729Sjoerg llvm::Value *CGObjCGNU::EmitIvarOffset(CodeGenFunction &CGF,
40807330f729Sjoerg                          const ObjCInterfaceDecl *Interface,
40817330f729Sjoerg                          const ObjCIvarDecl *Ivar) {
40827330f729Sjoerg   if (CGM.getLangOpts().ObjCRuntime.isNonFragile()) {
40837330f729Sjoerg     Interface = FindIvarInterface(CGM.getContext(), Interface, Ivar);
40847330f729Sjoerg 
40857330f729Sjoerg     // The MSVC linker cannot have a single global defined as LinkOnceAnyLinkage
40867330f729Sjoerg     // and ExternalLinkage, so create a reference to the ivar global and rely on
40877330f729Sjoerg     // the definition being created as part of GenerateClass.
40887330f729Sjoerg     if (RuntimeVersion < 10 ||
40897330f729Sjoerg         CGF.CGM.getTarget().getTriple().isKnownWindowsMSVCEnvironment())
40907330f729Sjoerg       return CGF.Builder.CreateZExtOrBitCast(
40917330f729Sjoerg           CGF.Builder.CreateAlignedLoad(
40927330f729Sjoerg               Int32Ty, CGF.Builder.CreateAlignedLoad(
4093*e038c9c4Sjoerg                            llvm::Type::getInt32PtrTy(VMContext),
40947330f729Sjoerg                            ObjCIvarOffsetVariable(Interface, Ivar),
40957330f729Sjoerg                            CGF.getPointerAlign(), "ivar"),
40967330f729Sjoerg               CharUnits::fromQuantity(4)),
40977330f729Sjoerg           PtrDiffTy);
40987330f729Sjoerg     std::string name = "__objc_ivar_offset_value_" +
40997330f729Sjoerg       Interface->getNameAsString() +"." + Ivar->getNameAsString();
41007330f729Sjoerg     CharUnits Align = CGM.getIntAlign();
41017330f729Sjoerg     llvm::Value *Offset = TheModule.getGlobalVariable(name);
41027330f729Sjoerg     if (!Offset) {
41037330f729Sjoerg       auto GV = new llvm::GlobalVariable(TheModule, IntTy,
41047330f729Sjoerg           false, llvm::GlobalValue::LinkOnceAnyLinkage,
41057330f729Sjoerg           llvm::Constant::getNullValue(IntTy), name);
41067330f729Sjoerg       GV->setAlignment(Align.getAsAlign());
41077330f729Sjoerg       Offset = GV;
41087330f729Sjoerg     }
4109*e038c9c4Sjoerg     Offset = CGF.Builder.CreateAlignedLoad(IntTy, Offset, Align);
41107330f729Sjoerg     if (Offset->getType() != PtrDiffTy)
41117330f729Sjoerg       Offset = CGF.Builder.CreateZExtOrBitCast(Offset, PtrDiffTy);
41127330f729Sjoerg     return Offset;
41137330f729Sjoerg   }
41147330f729Sjoerg   uint64_t Offset = ComputeIvarBaseOffset(CGF.CGM, Interface, Ivar);
41157330f729Sjoerg   return llvm::ConstantInt::get(PtrDiffTy, Offset, /*isSigned*/true);
41167330f729Sjoerg }
41177330f729Sjoerg 
41187330f729Sjoerg CGObjCRuntime *
CreateGNUObjCRuntime(CodeGenModule & CGM)41197330f729Sjoerg clang::CodeGen::CreateGNUObjCRuntime(CodeGenModule &CGM) {
41207330f729Sjoerg   auto Runtime = CGM.getLangOpts().ObjCRuntime;
41217330f729Sjoerg   switch (Runtime.getKind()) {
41227330f729Sjoerg   case ObjCRuntime::GNUstep:
41237330f729Sjoerg     if (Runtime.getVersion() >= VersionTuple(2, 0))
41247330f729Sjoerg       return new CGObjCGNUstep2(CGM);
41257330f729Sjoerg     return new CGObjCGNUstep(CGM);
41267330f729Sjoerg 
41277330f729Sjoerg   case ObjCRuntime::GCC:
41287330f729Sjoerg     return new CGObjCGCC(CGM);
41297330f729Sjoerg 
41307330f729Sjoerg   case ObjCRuntime::ObjFW:
41317330f729Sjoerg     return new CGObjCObjFW(CGM);
41327330f729Sjoerg 
41337330f729Sjoerg   case ObjCRuntime::FragileMacOSX:
41347330f729Sjoerg   case ObjCRuntime::MacOSX:
41357330f729Sjoerg   case ObjCRuntime::iOS:
41367330f729Sjoerg   case ObjCRuntime::WatchOS:
41377330f729Sjoerg     llvm_unreachable("these runtimes are not GNU runtimes");
41387330f729Sjoerg   }
41397330f729Sjoerg   llvm_unreachable("bad runtime");
41407330f729Sjoerg }
4141