summaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
authorErik Pilkington <erik.pilkington@gmail.com>2019-01-17 18:18:53 +0000
committerErik Pilkington <erik.pilkington@gmail.com>2019-01-17 18:18:53 +0000
commit4ee4a0f3317d452831081ffb66298ae936ba43ab (patch)
tree3636a7f33ef2425c49625a6c715b4310ef261ad9 /lib/CodeGen
parentf812df94335cccf585168fcda36d6b683b625640 (diff)
downloadclang-4ee4a0f3317d452831081ffb66298ae936ba43ab.tar.gz
[CodeGenObjC] Use a constant value for non-fragile ivar offsets when possible
If a class inherits from NSObject and has an implementation, then we can assume that ivar offsets won't need to be updated by the runtime. This allows us to index into the object using a constant value and avoid loading from the ivar offset variable. This patch was adapted from one written by Pete Cooper. rdar://problem/10132568 Differential revision: https://reviews.llvm.org/D56802 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@351461 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/CGObjCMac.cpp44
1 files changed, 33 insertions, 11 deletions
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index d91eb43ca3..9b3522e8f8 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -1550,6 +1550,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);
@@ -6702,6 +6711,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;
@@ -6990,17 +7005,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