diff options
Diffstat (limited to 'lib/CodeGen/CGObjCMac.cpp')
-rw-r--r-- | lib/CodeGen/CGObjCMac.cpp | 576 |
1 files changed, 345 insertions, 231 deletions
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index d91eb43ca322..12880fecbadf 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -1,9 +1,8 @@ //===------- CGObjCMac.cpp - Interface to Apple Objective-C Runtime -------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -31,7 +30,6 @@ #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" -#include "llvm/IR/CallSite.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/IntrinsicInst.h" @@ -61,7 +59,7 @@ private: /// /// The default messenger, used for sends whose ABI is unchanged from /// the all-integer/pointer case. - llvm::Constant *getMessageSendFn() const { + llvm::FunctionCallee getMessageSendFn() const { // Add the non-lazy-bind attribute, since objc_msgSend is likely to // be called a lot. llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy }; @@ -77,12 +75,11 @@ private: /// The messenger used when the return value is an aggregate returned /// by indirect reference in the first argument, and therefore the /// self and selector parameters are shifted over by one. - llvm::Constant *getMessageSendStretFn() const { + llvm::FunctionCallee getMessageSendStretFn() const { llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy }; return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy, params, true), "objc_msgSend_stret"); - } /// [double | long double] objc_msgSend_fpret(id self, SEL op, ...) @@ -90,12 +87,11 @@ private: /// The messenger used when the return value is returned on the x87 /// floating-point stack; without a special entrypoint, the nil case /// would be unbalanced. - llvm::Constant *getMessageSendFpretFn() const { + llvm::FunctionCallee getMessageSendFpretFn() const { llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy }; return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.DoubleTy, params, true), "objc_msgSend_fpret"); - } /// _Complex long double objc_msgSend_fp2ret(id self, SEL op, ...) @@ -103,7 +99,7 @@ private: /// The messenger used when the return value is returned in two values on the /// x87 floating point stack; without a special entrypoint, the nil case /// would be unbalanced. Only used on 64-bit X86. - llvm::Constant *getMessageSendFp2retFn() const { + llvm::FunctionCallee getMessageSendFp2retFn() const { llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy }; llvm::Type *longDoubleType = llvm::Type::getX86_FP80Ty(VMContext); llvm::Type *resultType = @@ -119,7 +115,7 @@ private: /// The messenger used for super calls, which have different dispatch /// semantics. The class passed is the superclass of the current /// class. - llvm::Constant *getMessageSendSuperFn() const { + llvm::FunctionCallee getMessageSendSuperFn() const { llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy }; return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, params, true), @@ -130,7 +126,7 @@ private: /// /// A slightly different messenger used for super calls. The class /// passed is the current class. - llvm::Constant *getMessageSendSuperFn2() const { + llvm::FunctionCallee getMessageSendSuperFn2() const { llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy }; return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, params, true), @@ -141,7 +137,7 @@ private: /// SEL op, ...) /// /// The messenger used for super calls which return an aggregate indirectly. - llvm::Constant *getMessageSendSuperStretFn() const { + llvm::FunctionCallee getMessageSendSuperStretFn() const { llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy }; return CGM.CreateRuntimeFunction( llvm::FunctionType::get(CGM.VoidTy, params, true), @@ -152,19 +148,19 @@ private: /// SEL op, ...) /// /// objc_msgSendSuper_stret with the super2 semantics. - llvm::Constant *getMessageSendSuperStretFn2() const { + llvm::FunctionCallee getMessageSendSuperStretFn2() const { llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy }; return CGM.CreateRuntimeFunction( llvm::FunctionType::get(CGM.VoidTy, params, true), "objc_msgSendSuper2_stret"); } - llvm::Constant *getMessageSendSuperFpretFn() const { + llvm::FunctionCallee getMessageSendSuperFpretFn() const { // There is no objc_msgSendSuper_fpret? How can that work? return getMessageSendSuperFn(); } - llvm::Constant *getMessageSendSuperFpretFn2() const { + llvm::FunctionCallee getMessageSendSuperFpretFn2() const { // There is no objc_msgSendSuper_fpret? How can that work? return getMessageSendSuperFn2(); } @@ -233,7 +229,7 @@ public: /// CachePtrTy - LLVM type for struct objc_cache *. llvm::PointerType *CachePtrTy; - llvm::Constant *getGetPropertyFn() { + llvm::FunctionCallee getGetPropertyFn() { CodeGen::CodeGenTypes &Types = CGM.getTypes(); ASTContext &Ctx = CGM.getContext(); // id objc_getProperty (id, SEL, ptrdiff_t, bool) @@ -248,7 +244,7 @@ public: return CGM.CreateRuntimeFunction(FTy, "objc_getProperty"); } - llvm::Constant *getSetPropertyFn() { + llvm::FunctionCallee getSetPropertyFn() { CodeGen::CodeGenTypes &Types = CGM.getTypes(); ASTContext &Ctx = CGM.getContext(); // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool) @@ -267,7 +263,7 @@ public: return CGM.CreateRuntimeFunction(FTy, "objc_setProperty"); } - llvm::Constant *getOptimizedSetPropertyFn(bool atomic, bool copy) { + llvm::FunctionCallee getOptimizedSetPropertyFn(bool atomic, bool copy) { CodeGen::CodeGenTypes &Types = CGM.getTypes(); ASTContext &Ctx = CGM.getContext(); // void objc_setProperty_atomic(id self, SEL _cmd, @@ -302,7 +298,7 @@ public: return CGM.CreateRuntimeFunction(FTy, name); } - llvm::Constant *getCopyStructFn() { + llvm::FunctionCallee getCopyStructFn() { CodeGen::CodeGenTypes &Types = CGM.getTypes(); ASTContext &Ctx = CGM.getContext(); // void objc_copyStruct (void *, const void *, size_t, bool, bool) @@ -322,7 +318,7 @@ public: /// void objc_copyCppObjectAtomic( /// void *dest, const void *src, /// void (*copyHelper) (void *dest, const void *source)); - llvm::Constant *getCppAtomicObjectFunction() { + llvm::FunctionCallee getCppAtomicObjectFunction() { CodeGen::CodeGenTypes &Types = CGM.getTypes(); ASTContext &Ctx = CGM.getContext(); /// void objc_copyCppObjectAtomic(void *dest, const void *src, void *helper); @@ -336,7 +332,7 @@ public: return CGM.CreateRuntimeFunction(FTy, "objc_copyCppObjectAtomic"); } - llvm::Constant *getEnumerationMutationFn() { + llvm::FunctionCallee getEnumerationMutationFn() { CodeGen::CodeGenTypes &Types = CGM.getTypes(); ASTContext &Ctx = CGM.getContext(); // void objc_enumerationMutation (id) @@ -348,7 +344,7 @@ public: return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation"); } - llvm::Constant *getLookUpClassFn() { + llvm::FunctionCallee getLookUpClassFn() { CodeGen::CodeGenTypes &Types = CGM.getTypes(); ASTContext &Ctx = CGM.getContext(); // Class objc_lookUpClass (const char *) @@ -363,7 +359,7 @@ public: } /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function. - llvm::Constant *getGcReadWeakFn() { + llvm::FunctionCallee getGcReadWeakFn() { // id objc_read_weak (id *) llvm::Type *args[] = { ObjectPtrTy->getPointerTo() }; llvm::FunctionType *FTy = @@ -372,7 +368,7 @@ public: } /// GcAssignWeakFn -- LLVM objc_assign_weak function. - llvm::Constant *getGcAssignWeakFn() { + llvm::FunctionCallee getGcAssignWeakFn() { // id objc_assign_weak (id, id *) llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() }; llvm::FunctionType *FTy = @@ -381,7 +377,7 @@ public: } /// GcAssignGlobalFn -- LLVM objc_assign_global function. - llvm::Constant *getGcAssignGlobalFn() { + llvm::FunctionCallee getGcAssignGlobalFn() { // id objc_assign_global(id, id *) llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() }; llvm::FunctionType *FTy = @@ -390,7 +386,7 @@ public: } /// GcAssignThreadLocalFn -- LLVM objc_assign_threadlocal function. - llvm::Constant *getGcAssignThreadLocalFn() { + llvm::FunctionCallee getGcAssignThreadLocalFn() { // id objc_assign_threadlocal(id src, id * dest) llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() }; llvm::FunctionType *FTy = @@ -399,7 +395,7 @@ public: } /// GcAssignIvarFn -- LLVM objc_assign_ivar function. - llvm::Constant *getGcAssignIvarFn() { + llvm::FunctionCallee getGcAssignIvarFn() { // id objc_assign_ivar(id, id *, ptrdiff_t) llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo(), CGM.PtrDiffTy }; @@ -409,7 +405,7 @@ public: } /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function. - llvm::Constant *GcMemmoveCollectableFn() { + llvm::FunctionCallee GcMemmoveCollectableFn() { // void *objc_memmove_collectable(void *dst, const void *src, size_t size) llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, LongTy }; llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, args, false); @@ -417,7 +413,7 @@ public: } /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function. - llvm::Constant *getGcAssignStrongCastFn() { + llvm::FunctionCallee getGcAssignStrongCastFn() { // id objc_assign_strongCast(id, id *) llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() }; llvm::FunctionType *FTy = @@ -426,7 +422,7 @@ public: } /// ExceptionThrowFn - LLVM objc_exception_throw function. - llvm::Constant *getExceptionThrowFn() { + llvm::FunctionCallee getExceptionThrowFn() { // void objc_exception_throw(id) llvm::Type *args[] = { ObjectPtrTy }; llvm::FunctionType *FTy = @@ -435,14 +431,14 @@ public: } /// ExceptionRethrowFn - LLVM objc_exception_rethrow function. - llvm::Constant *getExceptionRethrowFn() { + llvm::FunctionCallee getExceptionRethrowFn() { // void objc_exception_rethrow(void) llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false); return CGM.CreateRuntimeFunction(FTy, "objc_exception_rethrow"); } /// SyncEnterFn - LLVM object_sync_enter function. - llvm::Constant *getSyncEnterFn() { + llvm::FunctionCallee getSyncEnterFn() { // int objc_sync_enter (id) llvm::Type *args[] = { ObjectPtrTy }; llvm::FunctionType *FTy = @@ -451,7 +447,7 @@ public: } /// SyncExitFn - LLVM object_sync_exit function. - llvm::Constant *getSyncExitFn() { + llvm::FunctionCallee getSyncExitFn() { // int objc_sync_exit (id) llvm::Type *args[] = { ObjectPtrTy }; llvm::FunctionType *FTy = @@ -459,35 +455,35 @@ public: return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit"); } - llvm::Constant *getSendFn(bool IsSuper) const { + llvm::FunctionCallee getSendFn(bool IsSuper) const { return IsSuper ? getMessageSendSuperFn() : getMessageSendFn(); } - llvm::Constant *getSendFn2(bool IsSuper) const { + llvm::FunctionCallee getSendFn2(bool IsSuper) const { return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn(); } - llvm::Constant *getSendStretFn(bool IsSuper) const { + llvm::FunctionCallee getSendStretFn(bool IsSuper) const { return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn(); } - llvm::Constant *getSendStretFn2(bool IsSuper) const { + llvm::FunctionCallee getSendStretFn2(bool IsSuper) const { return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn(); } - llvm::Constant *getSendFpretFn(bool IsSuper) const { + llvm::FunctionCallee getSendFpretFn(bool IsSuper) const { return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn(); } - llvm::Constant *getSendFpretFn2(bool IsSuper) const { + llvm::FunctionCallee getSendFpretFn2(bool IsSuper) const { return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn(); } - llvm::Constant *getSendFp2retFn(bool IsSuper) const { + llvm::FunctionCallee getSendFp2retFn(bool IsSuper) const { return IsSuper ? getMessageSendSuperFn() : getMessageSendFp2retFn(); } - llvm::Constant *getSendFp2RetFn2(bool IsSuper) const { + llvm::FunctionCallee getSendFp2RetFn2(bool IsSuper) const { return IsSuper ? getMessageSendSuperFn2() : getMessageSendFp2retFn(); } @@ -553,7 +549,7 @@ public: llvm::StructType *ExceptionDataTy; /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function. - llvm::Constant *getExceptionTryEnterFn() { + llvm::FunctionCallee getExceptionTryEnterFn() { llvm::Type *params[] = { ExceptionDataTy->getPointerTo() }; return CGM.CreateRuntimeFunction( llvm::FunctionType::get(CGM.VoidTy, params, false), @@ -561,7 +557,7 @@ public: } /// ExceptionTryExitFn - LLVM objc_exception_try_exit function. - llvm::Constant *getExceptionTryExitFn() { + llvm::FunctionCallee getExceptionTryExitFn() { llvm::Type *params[] = { ExceptionDataTy->getPointerTo() }; return CGM.CreateRuntimeFunction( llvm::FunctionType::get(CGM.VoidTy, params, false), @@ -569,7 +565,7 @@ public: } /// ExceptionExtractFn - LLVM objc_exception_extract function. - llvm::Constant *getExceptionExtractFn() { + llvm::FunctionCallee getExceptionExtractFn() { llvm::Type *params[] = { ExceptionDataTy->getPointerTo() }; return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, params, false), @@ -577,7 +573,7 @@ public: } /// ExceptionMatchFn - LLVM objc_exception_match function. - llvm::Constant *getExceptionMatchFn() { + llvm::FunctionCallee getExceptionMatchFn() { llvm::Type *params[] = { ClassPtrTy, ObjectPtrTy }; return CGM.CreateRuntimeFunction( llvm::FunctionType::get(CGM.Int32Ty, params, false), @@ -585,7 +581,7 @@ public: } /// SetJmpFn - LLVM _setjmp function. - llvm::Constant *getSetJmpFn() { + llvm::FunctionCallee getSetJmpFn() { // This is specifically the prototype for x86. llvm::Type *params[] = { CGM.Int32Ty->getPointerTo() }; return CGM.CreateRuntimeFunction( @@ -671,7 +667,7 @@ public: // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t* llvm::PointerType *SuperMessageRefPtrTy; - llvm::Constant *getMessageSendFixupFn() { + llvm::FunctionCallee getMessageSendFixupFn() { // id objc_msgSend_fixup(id, struct message_ref_t*, ...) llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy }; return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, @@ -679,7 +675,7 @@ public: "objc_msgSend_fixup"); } - llvm::Constant *getMessageSendFpretFixupFn() { + llvm::FunctionCallee getMessageSendFpretFixupFn() { // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...) llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy }; return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, @@ -687,7 +683,7 @@ public: "objc_msgSend_fpret_fixup"); } - llvm::Constant *getMessageSendStretFixupFn() { + llvm::FunctionCallee getMessageSendStretFixupFn() { // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...) llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy }; return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, @@ -695,7 +691,7 @@ public: "objc_msgSend_stret_fixup"); } - llvm::Constant *getMessageSendSuper2FixupFn() { + llvm::FunctionCallee getMessageSendSuper2FixupFn() { // id objc_msgSendSuper2_fixup (struct objc_super *, // struct _super_message_ref_t*, ...) llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy }; @@ -704,7 +700,7 @@ public: "objc_msgSendSuper2_fixup"); } - llvm::Constant *getMessageSendSuper2StretFixupFn() { + llvm::FunctionCallee getMessageSendSuper2StretFixupFn() { // id objc_msgSendSuper2_stret_fixup(struct objc_super *, // struct _super_message_ref_t*, ...) llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy }; @@ -713,19 +709,45 @@ public: "objc_msgSendSuper2_stret_fixup"); } - llvm::Constant *getObjCEndCatchFn() { + llvm::FunctionCallee getObjCEndCatchFn() { return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy, false), "objc_end_catch"); - } - llvm::Constant *getObjCBeginCatchFn() { + llvm::FunctionCallee getObjCBeginCatchFn() { llvm::Type *params[] = { Int8PtrTy }; return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy, params, false), "objc_begin_catch"); } + /// Class objc_loadClassref (void *) + /// + /// Loads from a classref. For Objective-C stub classes, this invokes the + /// initialization callback stored inside the stub. For all other classes + /// this simply dereferences the pointer. + llvm::FunctionCallee getLoadClassrefFn() const { + // Add the non-lazy-bind attribute, since objc_loadClassref is likely to + // be called a lot. + // + // Also it is safe to make it readnone, since we never load or store the + // classref except by calling this function. + llvm::Type *params[] = { Int8PtrPtrTy }; + llvm::FunctionCallee F = CGM.CreateRuntimeFunction( + llvm::FunctionType::get(ClassnfABIPtrTy, params, false), + "objc_loadClassref", + llvm::AttributeList::get(CGM.getLLVMContext(), + llvm::AttributeList::FunctionIndex, + {llvm::Attribute::NonLazyBind, + llvm::Attribute::ReadNone, + llvm::Attribute::NoUnwind})); + if (!CGM.getTriple().isOSBinFormatCOFF()) + cast<llvm::Function>(F.getCallee())->setLinkage( + llvm::Function::ExternalWeakLinkage); + + return F; + } + llvm::StructType *EHTypeTy; llvm::Type *EHTypePtrTy; @@ -882,6 +904,9 @@ protected: /// DefinedCategories - List of defined categories. SmallVector<llvm::GlobalValue*, 16> DefinedCategories; + /// DefinedStubCategories - List of defined categories on class stubs. + SmallVector<llvm::GlobalValue*, 16> DefinedStubCategories; + /// DefinedNonLazyCategories - List of defined "non-lazy" categories. SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyCategories; @@ -1325,15 +1350,15 @@ public: llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF, const ObjCProtocolDecl *PD) override; - llvm::Constant *GetPropertyGetFunction() override; - llvm::Constant *GetPropertySetFunction() override; - llvm::Constant *GetOptimizedPropertySetFunction(bool atomic, - bool copy) override; - llvm::Constant *GetGetStructFunction() override; - llvm::Constant *GetSetStructFunction() override; - llvm::Constant *GetCppAtomicObjectGetFunction() override; - llvm::Constant *GetCppAtomicObjectSetFunction() override; - llvm::Constant *EnumerationMutationFunction() override; + llvm::FunctionCallee GetPropertyGetFunction() override; + llvm::FunctionCallee GetPropertySetFunction() override; + llvm::FunctionCallee GetOptimizedPropertySetFunction(bool atomic, + bool copy) override; + llvm::FunctionCallee GetGetStructFunction() override; + llvm::FunctionCallee GetSetStructFunction() override; + llvm::FunctionCallee GetCppAtomicObjectGetFunction() override; + llvm::FunctionCallee GetCppAtomicObjectSetFunction() override; + llvm::FunctionCallee EnumerationMutationFunction() override; void EmitTryStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtTryStmt &S) override; @@ -1469,6 +1494,12 @@ private: bool isMetaclass, ForDefinition_t isForDefinition); + llvm::Constant *GetClassGlobalForClassRef(const ObjCInterfaceDecl *ID); + + llvm::Value *EmitLoadOfClassRef(CodeGenFunction &CGF, + const ObjCInterfaceDecl *ID, + llvm::GlobalVariable *Entry); + /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy, /// for the given class reference. llvm::Value *EmitClassRef(CodeGenFunction &CGF, @@ -1550,6 +1581,15 @@ private: return false; } + bool isClassLayoutKnownStatically(const ObjCInterfaceDecl *ID) { + // NSObject is a fixed size. If we can see the @implementation of a class + // which inherits from NSObject then we know that all it's offsets also must + // be fixed. FIXME: Can we do this if see a chain of super classes with + // implementations leading to NSObject? + return ID->getImplementation() && ID->getSuperClass() && + ID->getSuperClass()->getName() == "NSObject"; + } + public: CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm); @@ -1598,35 +1638,35 @@ public: llvm::Constant *GetEHType(QualType T) override; - llvm::Constant *GetPropertyGetFunction() override { + llvm::FunctionCallee GetPropertyGetFunction() override { return ObjCTypes.getGetPropertyFn(); } - llvm::Constant *GetPropertySetFunction() override { + llvm::FunctionCallee GetPropertySetFunction() override { return ObjCTypes.getSetPropertyFn(); } - llvm::Constant *GetOptimizedPropertySetFunction(bool atomic, - bool copy) override { + llvm::FunctionCallee GetOptimizedPropertySetFunction(bool atomic, + bool copy) override { return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy); } - llvm::Constant *GetSetStructFunction() override { + llvm::FunctionCallee GetSetStructFunction() override { return ObjCTypes.getCopyStructFn(); } - llvm::Constant *GetGetStructFunction() override { + llvm::FunctionCallee GetGetStructFunction() override { return ObjCTypes.getCopyStructFn(); } - llvm::Constant *GetCppAtomicObjectSetFunction() override { + llvm::FunctionCallee GetCppAtomicObjectSetFunction() override { return ObjCTypes.getCppAtomicObjectFunction(); } - llvm::Constant *GetCppAtomicObjectGetFunction() override { + llvm::FunctionCallee GetCppAtomicObjectGetFunction() override { return ObjCTypes.getCppAtomicObjectFunction(); } - llvm::Constant *EnumerationMutationFunction() override { + llvm::FunctionCallee EnumerationMutationFunction() override { return ObjCTypes.getEnumerationMutationFn(); } @@ -1805,6 +1845,28 @@ static bool hasObjCExceptionAttribute(ASTContext &Context, return false; } +static llvm::GlobalValue::LinkageTypes +getLinkageTypeForObjCMetadata(CodeGenModule &CGM, StringRef Section) { + if (CGM.getTriple().isOSBinFormatMachO() && + (Section.empty() || Section.startswith("__DATA"))) + return llvm::GlobalValue::InternalLinkage; + return llvm::GlobalValue::PrivateLinkage; +} + +/// A helper function to create an internal or private global variable. +static llvm::GlobalVariable * +finishAndCreateGlobal(ConstantInitBuilder::StructBuilder &Builder, + const llvm::Twine &Name, CodeGenModule &CGM) { + std::string SectionName; + if (CGM.getTriple().isOSBinFormatMachO()) + SectionName = "__DATA, __objc_const"; + auto *GV = Builder.finishAndCreateGlobal( + Name, CGM.getPointerAlign(), /*constant*/ false, + getLinkageTypeForObjCMetadata(CGM, SectionName)); + GV->setSection(SectionName); + return GV; +} + /* *** CGObjCMac Public Interface *** */ CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm), @@ -1907,7 +1969,7 @@ llvm::Constant *CGObjCNonFragileABIMac::getNSConstantStringClassRef() { std::string str = StringClass.empty() ? "OBJC_CLASS_$_NSConstantString" : "OBJC_CLASS_$_" + StringClass; - auto GV = GetClassGlobal(str, NotForDefinition); + llvm::Constant *GV = GetClassGlobal(str, NotForDefinition); // Make sure the result is of the correct type. auto V = llvm::ConstantExpr::getBitCast(GV, CGM.IntTy->getPointerTo()); @@ -2004,9 +2066,8 @@ CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, "objc_super"); llvm::Value *ReceiverAsObject = CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); - CGF.Builder.CreateStore( - ReceiverAsObject, - CGF.Builder.CreateStructGEP(ObjCSuper, 0, CharUnits::Zero())); + CGF.Builder.CreateStore(ReceiverAsObject, + CGF.Builder.CreateStructGEP(ObjCSuper, 0)); // If this is a class message the metaclass is passed as the target. llvm::Value *Target; @@ -2041,8 +2102,7 @@ CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, llvm::Type *ClassTy = CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType()); Target = CGF.Builder.CreateBitCast(Target, ClassTy); - CGF.Builder.CreateStore(Target, - CGF.Builder.CreateStructGEP(ObjCSuper, 1, CGF.getPointerSize())); + CGF.Builder.CreateStore(Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1)); return EmitMessageSend(CGF, Return, ResultType, EmitSelector(CGF, Sel), ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy, @@ -2129,7 +2189,7 @@ CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF, bool RequiresNullCheck = false; - llvm::Constant *Fn = nullptr; + llvm::FunctionCallee Fn = nullptr; if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) { if (ReceiverCanBeNull) RequiresNullCheck = true; Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper) @@ -2149,6 +2209,10 @@ CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF, : ObjCTypes.getSendFn(IsSuper); } + // Cast function to proper signature + llvm::Constant *BitcastFn = cast<llvm::Constant>( + CGF.Builder.CreateBitCast(Fn.getCallee(), MSI.MessengerType)); + // We don't need to emit a null check to zero out an indirect result if the // result is ignored. if (Return.isUnused()) @@ -2169,16 +2233,15 @@ CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF, nullReturn.init(CGF, Arg0); } - llvm::Instruction *CallSite; - Fn = llvm::ConstantExpr::getBitCast(Fn, MSI.MessengerType); - CGCallee Callee = CGCallee::forDirect(Fn); + llvm::CallBase *CallSite; + CGCallee Callee = CGCallee::forDirect(BitcastFn); RValue rvalue = CGF.EmitCall(MSI.CallInfo, Callee, Return, ActualArgs, &CallSite); // Mark the call as noreturn if the method is marked noreturn and the // receiver cannot be null. if (Method && Method->hasAttr<NoReturnAttr>() && !ReceiverCanBeNull) { - llvm::CallSite(CallSite).setDoesNotReturn(); + CallSite->setDoesNotReturn(); } return nullReturn.complete(CGF, Return, rvalue, ResultType, CallArgs, @@ -2954,7 +3017,7 @@ llvm::Value *CGObjCCommonMac::EmitClassRefViaRuntime( CodeGenFunction &CGF, const ObjCInterfaceDecl *ID, ObjCCommonTypesHelper &ObjCTypes) { - llvm::Constant *lookUpClassFn = ObjCTypes.getLookUpClassFn(); + llvm::FunctionCallee lookUpClassFn = ObjCTypes.getLookUpClassFn(); llvm::Value *className = CGF.CGM.GetAddrOfConstantCString(ID->getObjCRuntimeNameAsString()) @@ -3100,7 +3163,7 @@ CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD, values.add(classProperties); // No special section, but goes in llvm.used - return CreateMetadataVar("\01l_OBJC_PROTOCOLEXT_" + PD->getName(), values, + return CreateMetadataVar("_OBJC_PROTOCOLEXT_" + PD->getName(), values, StringRef(), CGM.getPointerAlign(), true); } @@ -3333,9 +3396,9 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { // If there is no category @interface then there can be no properties. if (Category) { - Values.add(EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(), + Values.add(EmitPropertyList("_OBJC_$_PROP_LIST_" + ExtName.str(), OCD, Category, ObjCTypes, false)); - Values.add(EmitPropertyList("\01l_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(), + Values.add(EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(), OCD, Category, ObjCTypes, true)); } else { Values.addNullPointer(ObjCTypes.PropertyListPtrTy); @@ -3681,8 +3744,8 @@ CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID, // Properties. llvm::Constant *propertyList = - EmitPropertyList((isMetaclass ? Twine("\01l_OBJC_$_CLASS_PROP_LIST_") - : Twine("\01l_OBJC_$_PROP_LIST_")) + EmitPropertyList((isMetaclass ? Twine("_OBJC_$_CLASS_PROP_LIST_") + : Twine("_OBJC_$_PROP_LIST_")) + ID->getName(), ID, ID->getClassInterface(), ObjCTypes, isMetaclass); @@ -3930,9 +3993,10 @@ llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name, StringRef Section, CharUnits Align, bool AddToUsed) { + llvm::GlobalValue::LinkageTypes LT = + getLinkageTypeForObjCMetadata(CGM, Section); llvm::GlobalVariable *GV = - Init.finishAndCreateGlobal(Name, Align, /*constant*/ false, - llvm::GlobalValue::PrivateLinkage); + Init.finishAndCreateGlobal(Name, Align, /*constant*/ false, LT); if (!Section.empty()) GV->setSection(Section); if (AddToUsed) @@ -3946,9 +4010,10 @@ llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name, CharUnits Align, bool AddToUsed) { llvm::Type *Ty = Init->getType(); + llvm::GlobalValue::LinkageTypes LT = + getLinkageTypeForObjCMetadata(CGM, Section); llvm::GlobalVariable *GV = - new llvm::GlobalVariable(CGM.getModule(), Ty, false, - llvm::GlobalValue::PrivateLinkage, Init, Name); + new llvm::GlobalVariable(CGM.getModule(), Ty, false, LT, Init, Name); if (!Section.empty()) GV->setSection(Section); GV->setAlignment(Align.getQuantity()); @@ -4011,36 +4076,36 @@ llvm::Function *CGObjCMac::ModuleInitFunction() { return nullptr; } -llvm::Constant *CGObjCMac::GetPropertyGetFunction() { +llvm::FunctionCallee CGObjCMac::GetPropertyGetFunction() { return ObjCTypes.getGetPropertyFn(); } -llvm::Constant *CGObjCMac::GetPropertySetFunction() { +llvm::FunctionCallee CGObjCMac::GetPropertySetFunction() { return ObjCTypes.getSetPropertyFn(); } -llvm::Constant *CGObjCMac::GetOptimizedPropertySetFunction(bool atomic, - bool copy) { +llvm::FunctionCallee CGObjCMac::GetOptimizedPropertySetFunction(bool atomic, + bool copy) { return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy); } -llvm::Constant *CGObjCMac::GetGetStructFunction() { +llvm::FunctionCallee CGObjCMac::GetGetStructFunction() { return ObjCTypes.getCopyStructFn(); } -llvm::Constant *CGObjCMac::GetSetStructFunction() { +llvm::FunctionCallee CGObjCMac::GetSetStructFunction() { return ObjCTypes.getCopyStructFn(); } -llvm::Constant *CGObjCMac::GetCppAtomicObjectGetFunction() { +llvm::FunctionCallee CGObjCMac::GetCppAtomicObjectGetFunction() { return ObjCTypes.getCppAtomicObjectFunction(); } -llvm::Constant *CGObjCMac::GetCppAtomicObjectSetFunction() { +llvm::FunctionCallee CGObjCMac::GetCppAtomicObjectSetFunction() { return ObjCTypes.getCppAtomicObjectFunction(); } -llvm::Constant *CGObjCMac::EnumerationMutationFunction() { +llvm::FunctionCallee CGObjCMac::EnumerationMutationFunction() { return ObjCTypes.getEnumerationMutationFn(); } @@ -4216,14 +4281,15 @@ void FragileHazards::emitHazardsInNewBlocks() { // Ignore instructions that aren't non-intrinsic calls. // These are the only calls that can possibly call longjmp. - if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I)) continue; + if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I)) + continue; if (isa<llvm::IntrinsicInst>(I)) continue; // Ignore call sites marked nounwind. This may be questionable, // since 'nounwind' doesn't necessarily mean 'does not call longjmp'. - llvm::CallSite CS(&I); - if (CS.doesNotThrow()) continue; + if (cast<llvm::CallBase>(I).doesNotThrow()) + continue; // Insert a read hazard before the call. This will ensure that // any writes to the locals are performed before making the @@ -4855,7 +4921,7 @@ llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF, std::string CGObjCCommonMac::GetSectionName(StringRef Section, StringRef MachOAttributes) { switch (CGM.getTriple().getObjectFormat()) { - default: + case llvm::Triple::UnknownObjectFormat: llvm_unreachable("unexpected object file format"); case llvm::Triple::MachO: { if (MachOAttributes.empty()) @@ -4870,7 +4936,13 @@ std::string CGObjCCommonMac::GetSectionName(StringRef Section, assert(Section.substr(0, 2) == "__" && "expected the name to begin with __"); return ("." + Section.substr(2) + "$B").str(); + case llvm::Triple::Wasm: + case llvm::Triple::XCOFF: + llvm::report_fatal_error( + "Objective-C support is unimplemented for object file format."); } + + llvm_unreachable("Unhandled llvm::Triple::ObjectFormatType enum"); } /// EmitImageInfo - Emit the image info marker used to encode some module @@ -5994,10 +6066,15 @@ void CGObjCNonFragileABIMac::AddModuleClassList( Symbols.size()), Symbols); + // Section name is obtained by calling GetSectionName, which returns + // sections in the __DATA segment on MachO. + assert((!CGM.getTriple().isOSBinFormatMachO() || + SectionName.startswith("__DATA")) && + "SectionName expected to start with __DATA on MachO"); + llvm::GlobalValue::LinkageTypes LT = + getLinkageTypeForObjCMetadata(CGM, SectionName); llvm::GlobalVariable *GV = - new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, - llvm::GlobalValue::PrivateLinkage, - Init, + new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, LT, Init, SymbolName); GV->setAlignment(CGM.getDataLayout().getABITypeAlignment(Init->getType())); GV->setSection(SectionName); @@ -6034,6 +6111,9 @@ void CGObjCNonFragileABIMac::FinishNonFragileABIModule() { AddModuleClassList(DefinedCategories, "OBJC_LABEL_CATEGORY_$", GetSectionName("__objc_catlist", "regular,no_dead_strip")); + AddModuleClassList(DefinedStubCategories, "OBJC_LABEL_STUB_CATEGORY_$", + GetSectionName("__objc_catlist2", + "regular,no_dead_strip")); AddModuleClassList(DefinedNonLazyCategories, "OBJC_LABEL_NONLAZY_CATEGORY_$", GetSectionName("__objc_nlcatlist", "regular,no_dead_strip")); @@ -6176,7 +6256,7 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer( const ObjCInterfaceDecl *OID = ID->getClassInterface(); assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer"); - values.add(EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_" + values.add(EmitProtocolList("_OBJC_CLASS_PROTOCOLS_$_" + OID->getObjCRuntimeNameAsString(), OID->all_referenced_protocol_begin(), OID->all_referenced_protocol_end())); @@ -6185,29 +6265,23 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer( values.addNullPointer(ObjCTypes.IvarListnfABIPtrTy); values.add(GetIvarLayoutName(nullptr, ObjCTypes)); values.add(EmitPropertyList( - "\01l_OBJC_$_CLASS_PROP_LIST_" + ID->getObjCRuntimeNameAsString(), + "_OBJC_$_CLASS_PROP_LIST_" + ID->getObjCRuntimeNameAsString(), ID, ID->getClassInterface(), ObjCTypes, true)); } else { values.add(EmitIvarList(ID)); values.add(BuildWeakIvarLayout(ID, beginInstance, endInstance, hasMRCWeak)); values.add(EmitPropertyList( - "\01l_OBJC_$_PROP_LIST_" + ID->getObjCRuntimeNameAsString(), + "_OBJC_$_PROP_LIST_" + ID->getObjCRuntimeNameAsString(), ID, ID->getClassInterface(), ObjCTypes, false)); } llvm::SmallString<64> roLabel; llvm::raw_svector_ostream(roLabel) - << ((flags & NonFragileABI_Class_Meta) ? "\01l_OBJC_METACLASS_RO_$_" - : "\01l_OBJC_CLASS_RO_$_") + << ((flags & NonFragileABI_Class_Meta) ? "_OBJC_METACLASS_RO_$_" + : "_OBJC_CLASS_RO_$_") << ClassName; - llvm::GlobalVariable *CLASS_RO_GV = - values.finishAndCreateGlobal(roLabel, CGM.getPointerAlign(), - /*constant*/ false, - llvm::GlobalValue::PrivateLinkage); - if (CGM.getTriple().isOSBinFormatMachO()) - CLASS_RO_GV->setSection("__DATA, __objc_const"); - return CLASS_RO_GV; + return finishAndCreateGlobal(values, roLabel, CGM); } /// Build the metaclass object for a class. @@ -6253,9 +6327,11 @@ CGObjCNonFragileABIMac::BuildClassObject(const ObjCInterfaceDecl *CI, return GV; } -bool -CGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const { - return OD->getClassMethod(GetNullarySelector("load")) != nullptr; +bool CGObjCNonFragileABIMac::ImplementationIsNonLazy( + const ObjCImplDecl *OD) const { + return OD->getClassMethod(GetNullarySelector("load")) != nullptr || + OD->getClassInterface()->hasAttr<ObjCNonLazyClassAttr>() || + OD->hasAttr<ObjCNonLazyClassAttr>(); } void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID, @@ -6437,7 +6513,7 @@ llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF, llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD), ObjCTypes.getExternalProtocolPtrTy()); - std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_"); + std::string ProtocolName("_OBJC_PROTOCOL_REFERENCE_$_"); ProtocolName += PD->getObjCRuntimeNameAsString(); CharUnits Align = CGF.getPointerAlign(); @@ -6472,7 +6548,7 @@ llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF, /// void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { const ObjCInterfaceDecl *Interface = OCD->getClassInterface(); - const char *Prefix = "\01l_OBJC_$_CATEGORY_"; + const char *Prefix = "_OBJC_$_CATEGORY_"; llvm::SmallString<64> ExtCatName(Prefix); ExtCatName += Interface->getObjCRuntimeNameAsString(); @@ -6508,14 +6584,14 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { SmallString<256> ExtName; llvm::raw_svector_ostream(ExtName) << Interface->getObjCRuntimeNameAsString() << "_$_" << OCD->getName(); - values.add(EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_" + values.add(EmitProtocolList("_OBJC_CATEGORY_PROTOCOLS_$_" + Interface->getObjCRuntimeNameAsString() + "_$_" + Category->getName(), Category->protocol_begin(), Category->protocol_end())); - values.add(EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(), + values.add(EmitPropertyList("_OBJC_$_PROP_LIST_" + ExtName.str(), OCD, Category, ObjCTypes, false)); - values.add(EmitPropertyList("\01l_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(), + values.add(EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(), OCD, Category, ObjCTypes, true)); } else { values.addNullPointer(ObjCTypes.ProtocolListnfABIPtrTy); @@ -6527,13 +6603,12 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { values.addInt(ObjCTypes.IntTy, Size); llvm::GlobalVariable *GCATV = - values.finishAndCreateGlobal(ExtCatName.str(), CGM.getPointerAlign(), - /*constant*/ false, - llvm::GlobalValue::PrivateLinkage); - if (CGM.getTriple().isOSBinFormatMachO()) - GCATV->setSection("__DATA, __objc_const"); + finishAndCreateGlobal(values, ExtCatName.str(), CGM); CGM.addCompilerUsedGlobal(GCATV); - DefinedCategories.push_back(GCATV); + if (Interface->hasAttr<ObjCClassStubAttr>()) + DefinedStubCategories.push_back(GCATV); + else + DefinedCategories.push_back(GCATV); // Determine if this category is also "non-lazy". if (ImplementationIsNonLazy(OCD)) @@ -6590,36 +6665,36 @@ CGObjCNonFragileABIMac::emitMethodList(Twine name, MethodListType kind, bool forProtocol; switch (kind) { case MethodListType::CategoryInstanceMethods: - prefix = "\01l_OBJC_$_CATEGORY_INSTANCE_METHODS_"; + prefix = "_OBJC_$_CATEGORY_INSTANCE_METHODS_"; forProtocol = false; break; case MethodListType::CategoryClassMethods: - prefix = "\01l_OBJC_$_CATEGORY_CLASS_METHODS_"; + prefix = "_OBJC_$_CATEGORY_CLASS_METHODS_"; forProtocol = false; break; case MethodListType::InstanceMethods: - prefix = "\01l_OBJC_$_INSTANCE_METHODS_"; + prefix = "_OBJC_$_INSTANCE_METHODS_"; forProtocol = false; break; case MethodListType::ClassMethods: - prefix = "\01l_OBJC_$_CLASS_METHODS_"; + prefix = "_OBJC_$_CLASS_METHODS_"; forProtocol = false; break; case MethodListType::ProtocolInstanceMethods: - prefix = "\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_"; + prefix = "_OBJC_$_PROTOCOL_INSTANCE_METHODS_"; forProtocol = true; break; case MethodListType::ProtocolClassMethods: - prefix = "\01l_OBJC_$_PROTOCOL_CLASS_METHODS_"; + prefix = "_OBJC_$_PROTOCOL_CLASS_METHODS_"; forProtocol = true; break; case MethodListType::OptionalProtocolInstanceMethods: - prefix = "\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"; + prefix = "_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"; forProtocol = true; break; case MethodListType::OptionalProtocolClassMethods: - prefix = "\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"; + prefix = "_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"; forProtocol = true; break; } @@ -6638,11 +6713,7 @@ CGObjCNonFragileABIMac::emitMethodList(Twine name, MethodListType kind, } methodArray.finishAndAddTo(values); - auto *GV = values.finishAndCreateGlobal(prefix + name, CGM.getPointerAlign(), - /*constant*/ false, - llvm::GlobalValue::PrivateLinkage); - if (CGM.getTriple().isOSBinFormatMachO()) - GV->setSection("__DATA, __objc_const"); + llvm::GlobalVariable *GV = finishAndCreateGlobal(values, prefix + name, CGM); CGM.addCompilerUsedGlobal(GV); return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListnfABIPtrTy); } @@ -6702,6 +6773,12 @@ CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID, IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility); } + // If ID's layout is known, then make the global constant. This serves as a + // useful assertion: we'll never use this variable to calculate ivar offsets, + // so if the runtime tries to patch it then we should crash. + if (isClassLayoutKnownStatically(ID)) + IvarOffsetGV->setConstant(true); + if (CGM.getTriple().isOSBinFormatMachO()) IvarOffsetGV->setSection("__DATA, __objc_ivar"); return IvarOffsetGV; @@ -6776,13 +6853,9 @@ llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList( ivars.finishAndAddTo(ivarList); ivarList.fillPlaceholderWithInt(ivarCountSlot, ObjCTypes.IntTy, ivarCount); - const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_"; - llvm::GlobalVariable *GV = - ivarList.finishAndCreateGlobal(Prefix + OID->getObjCRuntimeNameAsString(), - CGM.getPointerAlign(), /*constant*/ false, - llvm::GlobalValue::PrivateLinkage); - if (CGM.getTriple().isOSBinFormatMachO()) - GV->setSection("__DATA, __objc_const"); + const char *Prefix = "_OBJC_$_INSTANCE_VARIABLES_"; + llvm::GlobalVariable *GV = finishAndCreateGlobal( + ivarList, Prefix + OID->getObjCRuntimeNameAsString(), CGM); CGM.addCompilerUsedGlobal(GV); return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy); } @@ -6796,7 +6869,7 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef( // reference or not. At module finalization we add the empty // contents for protocols which were referenced but never defined. llvm::SmallString<64> Protocol; - llvm::raw_svector_ostream(Protocol) << "\01l_OBJC_PROTOCOL_$_" + llvm::raw_svector_ostream(Protocol) << "_OBJC_PROTOCOL_$_" << PD->getObjCRuntimeNameAsString(); Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, @@ -6850,7 +6923,7 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( // isa is NULL values.addNullPointer(ObjCTypes.ObjectPtrTy); values.add(GetClassName(PD->getObjCRuntimeNameAsString())); - values.add(EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + values.add(EmitProtocolList("_OBJC_$_PROTOCOL_REFS_" + PD->getObjCRuntimeNameAsString(), PD->protocol_begin(), PD->protocol_end())); @@ -6863,13 +6936,13 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( values.add(methodLists.emitMethodList(this, PD, ProtocolMethodLists::OptionalClassMethods)); values.add(EmitPropertyList( - "\01l_OBJC_$_PROP_LIST_" + PD->getObjCRuntimeNameAsString(), + "_OBJC_$_PROP_LIST_" + PD->getObjCRuntimeNameAsString(), nullptr, PD, ObjCTypes, false)); uint32_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy); values.addInt(ObjCTypes.IntTy, Size); values.addInt(ObjCTypes.IntTy, 0); - values.add(EmitProtocolMethodTypes("\01l_OBJC_$_PROTOCOL_METHOD_TYPES_" + values.add(EmitProtocolMethodTypes("_OBJC_$_PROTOCOL_METHOD_TYPES_" + PD->getObjCRuntimeNameAsString(), methodLists.emitExtendedTypesArray(this), ObjCTypes)); @@ -6878,7 +6951,7 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( values.addNullPointer(ObjCTypes.Int8PtrTy); values.add(EmitPropertyList( - "\01l_OBJC_$_CLASS_PROP_LIST_" + PD->getObjCRuntimeNameAsString(), + "_OBJC_$_CLASS_PROP_LIST_" + PD->getObjCRuntimeNameAsString(), nullptr, PD, ObjCTypes, true)); if (Entry) { @@ -6888,7 +6961,7 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( } else { llvm::SmallString<64> symbolName; llvm::raw_svector_ostream(symbolName) - << "\01l_OBJC_PROTOCOL_$_" << PD->getObjCRuntimeNameAsString(); + << "_OBJC_PROTOCOL_$_" << PD->getObjCRuntimeNameAsString(); Entry = values.finishAndCreateGlobal(symbolName, CGM.getPointerAlign(), /*constant*/ false, @@ -6904,7 +6977,7 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( // Use this protocol meta-data to build protocol list table in section // __DATA, __objc_protolist llvm::SmallString<64> ProtocolRef; - llvm::raw_svector_ostream(ProtocolRef) << "\01l_OBJC_LABEL_PROTOCOL_$_" + llvm::raw_svector_ostream(ProtocolRef) << "_OBJC_LABEL_PROTOCOL_$_" << PD->getObjCRuntimeNameAsString(); llvm::GlobalVariable *PTGV = @@ -6962,11 +7035,7 @@ CGObjCNonFragileABIMac::EmitProtocolList(Twine Name, array.finishAndAddTo(values); values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count); - GV = values.finishAndCreateGlobal(Name, CGM.getPointerAlign(), - /*constant*/ false, - llvm::GlobalValue::PrivateLinkage); - if (CGM.getTriple().isOSBinFormatMachO()) - GV->setSection("__DATA, __objc_const"); + GV = finishAndCreateGlobal(values, Name, CGM); CGM.addCompilerUsedGlobal(GV); return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy); @@ -6990,17 +7059,24 @@ LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar( Offset); } -llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset( - CodeGen::CodeGenFunction &CGF, - const ObjCInterfaceDecl *Interface, - const ObjCIvarDecl *Ivar) { - llvm::Value *IvarOffsetValue = ObjCIvarOffsetVariable(Interface, Ivar); - IvarOffsetValue = CGF.Builder.CreateAlignedLoad(IvarOffsetValue, - CGF.getSizeAlign(), "ivar"); - if (IsIvarOffsetKnownIdempotent(CGF, Ivar)) - cast<llvm::LoadInst>(IvarOffsetValue) - ->setMetadata(CGM.getModule().getMDKindID("invariant.load"), - llvm::MDNode::get(VMContext, None)); +llvm::Value * +CGObjCNonFragileABIMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF, + const ObjCInterfaceDecl *Interface, + const ObjCIvarDecl *Ivar) { + llvm::Value *IvarOffsetValue; + if (isClassLayoutKnownStatically(Interface)) { + IvarOffsetValue = llvm::ConstantInt::get( + ObjCTypes.IvarOffsetVarTy, + ComputeIvarBaseOffset(CGM, Interface->getImplementation(), Ivar)); + } else { + llvm::GlobalVariable *GV = ObjCIvarOffsetVariable(Interface, Ivar); + IvarOffsetValue = + CGF.Builder.CreateAlignedLoad(GV, CGF.getSizeAlign(), "ivar"); + if (IsIvarOffsetKnownIdempotent(CGF, Ivar)) + cast<llvm::LoadInst>(IvarOffsetValue) + ->setMetadata(CGM.getModule().getMDKindID("invariant.load"), + llvm::MDNode::get(VMContext, None)); + } // This could be 32bit int or 64bit integer depending on the architecture. // Cast it to 64bit integer value, if it is a 32bit integer ivar offset value @@ -7069,8 +7145,8 @@ CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF, // The runtime currently never uses vtable dispatch for anything // except normal, non-super message-sends. // FIXME: don't use this for that. - llvm::Constant *fn = nullptr; - std::string messageRefName("\01l_"); + llvm::FunctionCallee fn = nullptr; + std::string messageRefName("_"); if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) { if (isSuper) { fn = ObjCTypes.getMessageSendSuper2StretFixupFn(); @@ -7105,7 +7181,7 @@ CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF, // Build the message ref structure. ConstantInitBuilder builder(CGM); auto values = builder.beginStruct(); - values.add(fn); + values.add(cast<llvm::Constant>(fn.getCallee())); values.add(GetMethodVarName(selector)); messageRef = values.finishAndCreateGlobal(messageRefName, CharUnits::fromQuantity(16), @@ -7134,8 +7210,7 @@ CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF, args[1].setRValue(RValue::get(mref.getPointer())); // Load the function to call from the message ref table. - Address calleeAddr = - CGF.Builder.CreateStructGEP(mref, 0, CharUnits::Zero()); + Address calleeAddr = CGF.Builder.CreateStructGEP(mref, 0); llvm::Value *calleePtr = CGF.Builder.CreateLoad(calleeAddr, "msgSend_fn"); calleePtr = CGF.Builder.CreateBitCast(calleePtr, MSI.MessengerType); @@ -7209,31 +7284,68 @@ CGObjCNonFragileABIMac::GetClassGlobal(StringRef Name, return GV; } +llvm::Constant * +CGObjCNonFragileABIMac::GetClassGlobalForClassRef(const ObjCInterfaceDecl *ID) { + llvm::Constant *ClassGV = GetClassGlobal(ID, /*metaclass*/ false, + NotForDefinition); + + if (!ID->hasAttr<ObjCClassStubAttr>()) + return ClassGV; + + ClassGV = llvm::ConstantExpr::getPointerCast(ClassGV, ObjCTypes.Int8PtrTy); + + // Stub classes are pointer-aligned. Classrefs pointing at stub classes + // must set the least significant bit set to 1. + auto *Idx = llvm::ConstantInt::get(CGM.Int32Ty, 1); + return llvm::ConstantExpr::getGetElementPtr(CGM.Int8Ty, ClassGV, Idx); +} + +llvm::Value * +CGObjCNonFragileABIMac::EmitLoadOfClassRef(CodeGenFunction &CGF, + const ObjCInterfaceDecl *ID, + llvm::GlobalVariable *Entry) { + if (ID && ID->hasAttr<ObjCClassStubAttr>()) { + // Classrefs pointing at Objective-C stub classes must be loaded by calling + // a special runtime function. + return CGF.EmitRuntimeCall( + ObjCTypes.getLoadClassrefFn(), Entry, "load_classref_result"); + } + + CharUnits Align = CGF.getPointerAlign(); + return CGF.Builder.CreateAlignedLoad(Entry, Align); +} + llvm::Value * CGObjCNonFragileABIMac::EmitClassRefFromId(CodeGenFunction &CGF, IdentifierInfo *II, const ObjCInterfaceDecl *ID) { - CharUnits Align = CGF.getPointerAlign(); llvm::GlobalVariable *&Entry = ClassReferences[II]; if (!Entry) { llvm::Constant *ClassGV; if (ID) { - ClassGV = GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition); + ClassGV = GetClassGlobalForClassRef(ID); } else { ClassGV = GetClassGlobal((getClassSymbolPrefix() + II->getName()).str(), NotForDefinition); + assert(ClassGV->getType() == ObjCTypes.ClassnfABIPtrTy && + "classref was emitted with the wrong type?"); } - Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, - false, llvm::GlobalValue::PrivateLinkage, - ClassGV, "OBJC_CLASSLIST_REFERENCES_$_"); - Entry->setAlignment(Align.getQuantity()); - Entry->setSection(GetSectionName("__objc_classrefs", - "regular,no_dead_strip")); + std::string SectionName = + GetSectionName("__objc_classrefs", "regular,no_dead_strip"); + Entry = new llvm::GlobalVariable( + CGM.getModule(), ClassGV->getType(), false, + getLinkageTypeForObjCMetadata(CGM, SectionName), ClassGV, + "OBJC_CLASSLIST_REFERENCES_$_"); + Entry->setAlignment(CGF.getPointerAlign().getQuantity()); + if (!ID || !ID->hasAttr<ObjCClassStubAttr>()) + Entry->setSection(SectionName); + CGM.addCompilerUsedGlobal(Entry); } - return CGF.Builder.CreateAlignedLoad(Entry, Align); + + return EmitLoadOfClassRef(CGF, ID, Entry); } llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CodeGenFunction &CGF, @@ -7255,20 +7367,22 @@ llvm::Value *CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef( llvm::Value * CGObjCNonFragileABIMac::EmitSuperClassRef(CodeGenFunction &CGF, const ObjCInterfaceDecl *ID) { - CharUnits Align = CGF.getPointerAlign(); llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()]; if (!Entry) { - auto ClassGV = GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition); - Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, - false, llvm::GlobalValue::PrivateLinkage, - ClassGV, "OBJC_CLASSLIST_SUP_REFS_$_"); - Entry->setAlignment(Align.getQuantity()); - Entry->setSection(GetSectionName("__objc_superrefs", - "regular,no_dead_strip")); + llvm::Constant *ClassGV = GetClassGlobalForClassRef(ID); + std::string SectionName = + GetSectionName("__objc_superrefs", "regular,no_dead_strip"); + Entry = new llvm::GlobalVariable( + CGM.getModule(), ClassGV->getType(), false, + getLinkageTypeForObjCMetadata(CGM, SectionName), ClassGV, + "OBJC_CLASSLIST_SUP_REFS_$_"); + Entry->setAlignment(CGF.getPointerAlign().getQuantity()); + Entry->setSection(SectionName); CGM.addCompilerUsedGlobal(Entry); } - return CGF.Builder.CreateAlignedLoad(Entry, Align); + + return EmitLoadOfClassRef(CGF, ID, Entry); } /// EmitMetaClassRef - Return a Value * of the address of _class_t @@ -7281,14 +7395,14 @@ llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CodeGenFunction &CGF, llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()]; if (!Entry) { auto MetaClassGV = GetClassGlobal(ID, /*metaclass*/ true, NotForDefinition); - - Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, - false, llvm::GlobalValue::PrivateLinkage, - MetaClassGV, "OBJC_CLASSLIST_SUP_REFS_$_"); + std::string SectionName = + GetSectionName("__objc_superrefs", "regular,no_dead_strip"); + Entry = new llvm::GlobalVariable( + CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false, + getLinkageTypeForObjCMetadata(CGM, SectionName), MetaClassGV, + "OBJC_CLASSLIST_SUP_REFS_$_"); Entry->setAlignment(Align.getQuantity()); - - Entry->setSection(GetSectionName("__objc_superrefs", - "regular,no_dead_strip")); + Entry->setSection(SectionName); CGM.addCompilerUsedGlobal(Entry); } @@ -7332,9 +7446,8 @@ CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, llvm::Value *ReceiverAsObject = CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); - CGF.Builder.CreateStore( - ReceiverAsObject, - CGF.Builder.CreateStructGEP(ObjCSuper, 0, CharUnits::Zero())); + CGF.Builder.CreateStore(ReceiverAsObject, + CGF.Builder.CreateStructGEP(ObjCSuper, 0)); // If this is a class message the metaclass is passed as the target. llvm::Value *Target; @@ -7348,8 +7461,7 @@ CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, llvm::Type *ClassTy = CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType()); Target = CGF.Builder.CreateBitCast(Target, ClassTy); - CGF.Builder.CreateStore( - Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1, CGF.getPointerSize())); + CGF.Builder.CreateStore(Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1)); return (isVTableDispatchedSelector(Sel)) ? EmitVTableMessageSend(CGF, Return, ResultType, Sel, @@ -7380,12 +7492,14 @@ Address CGObjCNonFragileABIMac::EmitSelectorAddr(CodeGenFunction &CGF, llvm::Constant *Casted = llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel), ObjCTypes.SelectorPtrTy); - Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.SelectorPtrTy, - false, llvm::GlobalValue::PrivateLinkage, - Casted, "OBJC_SELECTOR_REFERENCES_"); + std::string SectionName = + GetSectionName("__objc_selrefs", "literal_pointers,no_dead_strip"); + Entry = new llvm::GlobalVariable( + CGM.getModule(), ObjCTypes.SelectorPtrTy, false, + getLinkageTypeForObjCMetadata(CGM, SectionName), Casted, + "OBJC_SELECTOR_REFERENCES_"); Entry->setExternallyInitialized(true); - Entry->setSection(GetSectionName("__objc_selrefs", - "literal_pointers,no_dead_strip")); + Entry->setSection(SectionName); Entry->setAlignment(Align.getQuantity()); CGM.addCompilerUsedGlobal(Entry); } @@ -7509,9 +7623,8 @@ void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, void CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtSynchronizedStmt &S) { - EmitAtSynchronizedStmt(CGF, S, - cast<llvm::Function>(ObjCTypes.getSyncEnterFn()), - cast<llvm::Function>(ObjCTypes.getSyncExitFn())); + EmitAtSynchronizedStmt(CGF, S, ObjCTypes.getSyncEnterFn(), + ObjCTypes.getSyncExitFn()); } llvm::Constant * @@ -7542,10 +7655,9 @@ CGObjCNonFragileABIMac::GetEHType(QualType T) { void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtTryStmt &S) { - EmitTryCatchStmt(CGF, S, - cast<llvm::Function>(ObjCTypes.getObjCBeginCatchFn()), - cast<llvm::Function>(ObjCTypes.getObjCEndCatchFn()), - cast<llvm::Function>(ObjCTypes.getExceptionRethrowFn())); + EmitTryCatchStmt(CGF, S, ObjCTypes.getObjCBeginCatchFn(), + ObjCTypes.getObjCEndCatchFn(), + ObjCTypes.getExceptionRethrowFn()); } /// EmitThrowStmt - Generate code for a throw statement. @@ -7555,11 +7667,13 @@ void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, if (const Expr *ThrowExpr = S.getThrowExpr()) { llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr); Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy); - CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionThrowFn(), Exception) - .setDoesNotReturn(); + llvm::CallBase *Call = + CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionThrowFn(), Exception); + Call->setDoesNotReturn(); } else { - CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionRethrowFn()) - .setDoesNotReturn(); + llvm::CallBase *Call = + CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionRethrowFn()); + Call->setDoesNotReturn(); } CGF.Builder.CreateUnreachable(); |