summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2014-06-16 18:46:51 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2014-06-16 18:46:51 +0000
commit4c2a0425b8b9703a0d113c2ba66b394027d72f20 (patch)
tree5708f01b597a57f3be045a58946e0acf387b97f7 /clang/lib/CodeGen
parenta5360c4cd887413c386ea678784ab08011764191 (diff)
downloadbcm5719-llvm-4c2a0425b8b9703a0d113c2ba66b394027d72f20.tar.gz
bcm5719-llvm-4c2a0425b8b9703a0d113c2ba66b394027d72f20.zip
MS ABI: Implement x86_64 RTTI
Summary: The RTTI scheme for x86_64 is largely the same as the one for i386. Differences are largely limited to avoiding load-time relocations by replacing pointers to RTTI metadata with the difference of that data relative to the load address of the module. Interestingly, this precludes the possibility of successfully using RTTI data from another DLL. The ImageBase reference is always relative to the current DLL. Differential Revision: http://reviews.llvm.org/D4148 llvm-svn: 211041
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/MicrosoftRTTI.cpp99
1 files changed, 81 insertions, 18 deletions
diff --git a/clang/lib/CodeGen/MicrosoftRTTI.cpp b/clang/lib/CodeGen/MicrosoftRTTI.cpp
index bc0c1f6081b..0ce754edfb9 100644
--- a/clang/lib/CodeGen/MicrosoftRTTI.cpp
+++ b/clang/lib/CodeGen/MicrosoftRTTI.cpp
@@ -51,6 +51,43 @@ using namespace CodeGen;
// vbtable. The names of the BaseClassDescriptors have all of their fields
// mangled into them so they can be aggressively deduplicated by the linker.
+static bool isImageRelative(CodeGenModule &CGM) {
+ return CGM.getTarget().getPointerWidth(/*AddressSpace=*/0) == 64;
+}
+
+static llvm::Type *getImageRelativeType(CodeGenModule &CGM,
+ llvm::Type *PtrType) {
+ if (!isImageRelative(CGM))
+ return PtrType;
+ return CGM.IntTy;
+}
+
+static llvm::GlobalVariable *getImageBase(CodeGenModule &CGM) {
+ StringRef Name = "__ImageBase";
+ if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(Name))
+ return GV;
+
+ return new llvm::GlobalVariable(CGM.getModule(), CGM.Int8Ty,
+ /*isConstant=*/true,
+ llvm::GlobalValue::ExternalLinkage,
+ /*Initializer=*/nullptr, Name);
+}
+
+static llvm::Constant *getImageRelativeConstant(CodeGenModule &CGM,
+ llvm::Constant *PtrVal) {
+ if (!isImageRelative(CGM))
+ return PtrVal;
+
+ llvm::Constant *ImageBaseAsInt =
+ llvm::ConstantExpr::getPtrToInt(getImageBase(CGM), CGM.IntPtrTy);
+ llvm::Constant *PtrValAsInt =
+ llvm::ConstantExpr::getPtrToInt(PtrVal, CGM.IntPtrTy);
+ llvm::Constant *Diff =
+ llvm::ConstantExpr::getSub(PtrValAsInt, ImageBaseAsInt,
+ /*HasNUW=*/true, /*HasNSW=*/true);
+ return llvm::ConstantExpr::getTrunc(Diff, CGM.IntTy);
+}
+
// 5 routines for constructing the llvm types for MS RTTI structs.
static llvm::StructType *getClassHierarchyDescriptorType(CodeGenModule &CGM);
@@ -72,13 +109,15 @@ static llvm::StructType *getBaseClassDescriptorType(CodeGenModule &CGM) {
if (auto Type = CGM.getModule().getTypeByName(Name))
return Type;
llvm::Type *FieldTypes[] = {
- CGM.Int8PtrTy,
+ getImageRelativeType(CGM, CGM.Int8PtrTy),
CGM.IntTy,
CGM.IntTy,
CGM.IntTy,
CGM.IntTy,
CGM.IntTy,
- getClassHierarchyDescriptorType(CGM)->getPointerTo()};
+ getImageRelativeType(
+ CGM, getClassHierarchyDescriptorType(CGM)->getPointerTo()),
+ };
return llvm::StructType::create(CGM.getLLVMContext(), FieldTypes, Name);
}
@@ -92,7 +131,10 @@ static llvm::StructType *getClassHierarchyDescriptorType(CodeGenModule &CGM) {
CGM.IntTy,
CGM.IntTy,
CGM.IntTy,
- getBaseClassDescriptorType(CGM)->getPointerTo()->getPointerTo()};
+ getImageRelativeType(
+ CGM,
+ getBaseClassDescriptorType(CGM)->getPointerTo()->getPointerTo()),
+ };
Type->setBody(FieldTypes);
return Type;
}
@@ -101,13 +143,21 @@ static llvm::StructType *getCompleteObjectLocatorType(CodeGenModule &CGM) {
static const char Name[] = "MSRTTICompleteObjectLocator";
if (auto Type = CGM.getModule().getTypeByName(Name))
return Type;
+ llvm::StructType *Type = llvm::StructType::create(CGM.getLLVMContext(), Name);
llvm::Type *FieldTypes[] = {
CGM.IntTy,
CGM.IntTy,
CGM.IntTy,
- CGM.Int8PtrTy,
- getClassHierarchyDescriptorType(CGM)->getPointerTo() };
- return llvm::StructType::create(CGM.getLLVMContext(), FieldTypes, Name);
+ getImageRelativeType(CGM, CGM.Int8PtrTy),
+ getImageRelativeType(
+ CGM, getClassHierarchyDescriptorType(CGM)->getPointerTo()),
+ getImageRelativeType(CGM, Type),
+ };
+ llvm::ArrayRef<llvm::Type *> FieldTypesRef(
+ std::begin(FieldTypes),
+ isImageRelative(CGM) ? std::end(FieldTypes) : std::end(FieldTypes) - 1);
+ Type->setBody(FieldTypesRef);
+ return Type;
}
static llvm::GlobalVariable *getTypeInfoVTable(CodeGenModule &CGM) {
@@ -288,9 +338,11 @@ llvm::GlobalVariable *MSRTTIBuilder::getClassHierarchyDescriptor() {
llvm::ConstantInt::get(CGM.IntTy, 0), // Unknown
llvm::ConstantInt::get(CGM.IntTy, Flags),
llvm::ConstantInt::get(CGM.IntTy, Classes.size()),
- llvm::ConstantExpr::getInBoundsGetElementPtr(
- getBaseClassArray(Classes),
- llvm::ArrayRef<llvm::Value *>(GEPIndices))};
+ getImageRelativeConstant(CGM,
+ llvm::ConstantExpr::getInBoundsGetElementPtr(
+ getBaseClassArray(Classes),
+ llvm::ArrayRef<llvm::Value *>(GEPIndices))),
+ };
CHD->setInitializer(llvm::ConstantStruct::get(Type, Fields));
return CHD;
}
@@ -308,7 +360,8 @@ MSRTTIBuilder::getBaseClassArray(SmallVectorImpl<MSRTTIClass> &Classes) {
// mode) bytes of padding. We provide a pointer sized amount of padding by
// adding +1 to Classes.size(). The sections have pointer alignment and are
// marked pick-any so it shouldn't matter.
- auto PtrType = getBaseClassDescriptorType(CGM)->getPointerTo();
+ auto PtrType = getImageRelativeType(
+ CGM, getBaseClassDescriptorType(CGM)->getPointerTo());
auto ArrayType = llvm::ArrayType::get(PtrType, Classes.size() + 1);
auto BCA = new llvm::GlobalVariable(Module, ArrayType,
/*Constant=*/true, Linkage, /*Initializer=*/nullptr, MangledName.c_str());
@@ -316,8 +369,9 @@ MSRTTIBuilder::getBaseClassArray(SmallVectorImpl<MSRTTIClass> &Classes) {
// Initialize the BaseClassArray.
SmallVector<llvm::Constant *, 8> BaseClassArrayData;
for (MSRTTIClass &Class : Classes)
- BaseClassArrayData.push_back(getBaseClassDescriptor(Class));
- BaseClassArrayData.push_back(llvm::ConstantPointerNull::get(PtrType));
+ BaseClassArrayData.push_back(
+ getImageRelativeConstant(CGM, getBaseClassDescriptor(Class)));
+ BaseClassArrayData.push_back(llvm::Constant::getNullValue(PtrType));
BCA->setInitializer(llvm::ConstantArray::get(ArrayType, BaseClassArrayData));
return BCA;
}
@@ -354,13 +408,16 @@ MSRTTIBuilder::getBaseClassDescriptor(const MSRTTIClass &Class) {
// Initialize the BaseClassDescriptor.
llvm::Constant *Fields[] = {
- CGM.getMSTypeDescriptor(Context.getTypeDeclType(Class.RD)),
+ getImageRelativeConstant(
+ CGM, CGM.getMSTypeDescriptor(Context.getTypeDeclType(Class.RD))),
llvm::ConstantInt::get(CGM.IntTy, Class.NumBases),
llvm::ConstantInt::get(CGM.IntTy, Class.OffsetInVBase),
llvm::ConstantInt::get(CGM.IntTy, VBPtrOffset),
llvm::ConstantInt::get(CGM.IntTy, OffsetInVBTable),
llvm::ConstantInt::get(CGM.IntTy, Class.Flags),
- MSRTTIBuilder(CGM, Class.RD).getClassHierarchyDescriptor()};
+ getImageRelativeConstant(
+ CGM, MSRTTIBuilder(CGM, Class.RD).getClassHierarchyDescriptor()),
+ };
BCD->setInitializer(llvm::ConstantStruct::get(Type, Fields));
return BCD;
}
@@ -395,12 +452,18 @@ MSRTTIBuilder::getCompleteObjectLocator(const VPtrInfo *Info) {
// Initialize the CompleteObjectLocator.
llvm::Constant *Fields[] = {
- llvm::ConstantInt::get(CGM.IntTy, 0), // IsDeltaEncoded
+ llvm::ConstantInt::get(CGM.IntTy, isImageRelative(CGM)),
llvm::ConstantInt::get(CGM.IntTy, OffsetToTop),
llvm::ConstantInt::get(CGM.IntTy, VFPtrOffset),
- CGM.getMSTypeDescriptor(Context.getTypeDeclType(RD)),
- getClassHierarchyDescriptor()};
- COL->setInitializer(llvm::ConstantStruct::get(Type, Fields));
+ getImageRelativeConstant(
+ CGM, CGM.getMSTypeDescriptor(Context.getTypeDeclType(RD))),
+ getImageRelativeConstant(CGM, getClassHierarchyDescriptor()),
+ getImageRelativeConstant(CGM, COL),
+ };
+ llvm::ArrayRef<llvm::Constant *> FieldsRef(Fields);
+ if (!isImageRelative(CGM))
+ FieldsRef = FieldsRef.slice(0, FieldsRef.size() - 1);
+ COL->setInitializer(llvm::ConstantStruct::get(Type, FieldsRef));
return COL;
}
OpenPOWER on IntegriCloud