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 §ionVec = 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