summaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGObjCMac.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/CGObjCMac.cpp')
-rw-r--r--lib/CodeGen/CGObjCMac.cpp576
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();