aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/ItaniumCXXABI.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen/ItaniumCXXABI.cpp')
-rw-r--r--clang/lib/CodeGen/ItaniumCXXABI.cpp367
1 files changed, 282 insertions, 85 deletions
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index b5b8702c551e..80de2a6e3950 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -203,7 +203,7 @@ public:
void EmitCXXConstructors(const CXXConstructorDecl *D) override;
- AddedStructorArgs
+ AddedStructorArgCounts
buildStructorSignature(GlobalDecl GD,
SmallVectorImpl<CanQualType> &ArgTys) override;
@@ -222,10 +222,17 @@ public:
void EmitInstanceFunctionProlog(CodeGenFunction &CGF) override;
- AddedStructorArgs
- addImplicitConstructorArgs(CodeGenFunction &CGF, const CXXConstructorDecl *D,
- CXXCtorType Type, bool ForVirtualBase,
- bool Delegating, CallArgList &Args) override;
+ AddedStructorArgs getImplicitConstructorArgs(CodeGenFunction &CGF,
+ const CXXConstructorDecl *D,
+ CXXCtorType Type,
+ bool ForVirtualBase,
+ bool Delegating) override;
+
+ llvm::Value *getCXXDestructorImplicitParam(CodeGenFunction &CGF,
+ const CXXDestructorDecl *DD,
+ CXXDtorType Type,
+ bool ForVirtualBase,
+ bool Delegating) override;
void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD,
CXXDtorType Type, bool ForVirtualBase,
@@ -516,6 +523,22 @@ private:
}
bool canCallMismatchedFunctionType() const override { return false; }
};
+
+class XLCXXABI final : public ItaniumCXXABI {
+public:
+ explicit XLCXXABI(CodeGen::CodeGenModule &CGM)
+ : ItaniumCXXABI(CGM) {}
+
+ void registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,
+ llvm::FunctionCallee dtor,
+ llvm::Constant *addr) override;
+
+ bool useSinitAndSterm() const override { return true; }
+
+private:
+ void emitCXXStermFinalizer(const VarDecl &D, llvm::Function *dtorStub,
+ llvm::Constant *addr);
+};
}
CodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) {
@@ -546,6 +569,9 @@ CodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) {
case TargetCXXABI::WebAssembly:
return new WebAssemblyCXXABI(CGM);
+ case TargetCXXABI::XL:
+ return new XLCXXABI(CGM);
+
case TargetCXXABI::GenericItanium:
if (CGM.getContext().getTargetInfo().getTriple().getArch()
== llvm::Triple::le32) {
@@ -670,6 +696,10 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
CGM.HasHiddenLTOVisibility(RD);
bool ShouldEmitVFEInfo = CGM.getCodeGenOpts().VirtualFunctionElimination &&
CGM.HasHiddenLTOVisibility(RD);
+ bool ShouldEmitWPDInfo =
+ CGM.getCodeGenOpts().WholeProgramVTables &&
+ // Don't insert type tests if we are forcing public std visibility.
+ !CGM.HasLTOVisibilityPublicStd(RD);
llvm::Value *VirtualFn = nullptr;
{
@@ -677,16 +707,17 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
llvm::Value *TypeId = nullptr;
llvm::Value *CheckResult = nullptr;
- if (ShouldEmitCFICheck || ShouldEmitVFEInfo) {
- // If doing CFI or VFE, we will need the metadata node to check against.
+ if (ShouldEmitCFICheck || ShouldEmitVFEInfo || ShouldEmitWPDInfo) {
+ // If doing CFI, VFE or WPD, we will need the metadata node to check
+ // against.
llvm::Metadata *MD =
CGM.CreateMetadataIdentifierForVirtualMemPtrType(QualType(MPT, 0));
TypeId = llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD);
}
- llvm::Value *VFPAddr = Builder.CreateGEP(VTable, VTableOffset);
-
if (ShouldEmitVFEInfo) {
+ llvm::Value *VFPAddr = Builder.CreateGEP(VTable, VTableOffset);
+
// If doing VFE, load from the vtable with a type.checked.load intrinsic
// call. Note that we use the GEP to calculate the address to load from
// and pass 0 as the offset to the intrinsic. This is because every
@@ -702,18 +733,30 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
} else {
// When not doing VFE, emit a normal load, as it allows more
// optimisations than type.checked.load.
- if (ShouldEmitCFICheck) {
+ if (ShouldEmitCFICheck || ShouldEmitWPDInfo) {
+ llvm::Value *VFPAddr = Builder.CreateGEP(VTable, VTableOffset);
CheckResult = Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::type_test),
{Builder.CreateBitCast(VFPAddr, CGF.Int8PtrTy), TypeId});
}
- VFPAddr =
- Builder.CreateBitCast(VFPAddr, FTy->getPointerTo()->getPointerTo());
- VirtualFn = Builder.CreateAlignedLoad(VFPAddr, CGF.getPointerAlign(),
- "memptr.virtualfn");
+
+ if (CGM.getItaniumVTableContext().isRelativeLayout()) {
+ VirtualFn = CGF.Builder.CreateCall(
+ CGM.getIntrinsic(llvm::Intrinsic::load_relative,
+ {VTableOffset->getType()}),
+ {VTable, VTableOffset});
+ VirtualFn = CGF.Builder.CreateBitCast(VirtualFn, FTy->getPointerTo());
+ } else {
+ llvm::Value *VFPAddr = CGF.Builder.CreateGEP(VTable, VTableOffset);
+ VFPAddr = CGF.Builder.CreateBitCast(
+ VFPAddr, FTy->getPointerTo()->getPointerTo());
+ VirtualFn = CGF.Builder.CreateAlignedLoad(
+ VFPAddr, CGF.getPointerAlign(), "memptr.virtualfn");
+ }
}
assert(VirtualFn && "Virtual fuction pointer not created!");
- assert((!ShouldEmitCFICheck || !ShouldEmitVFEInfo || CheckResult) &&
+ assert((!ShouldEmitCFICheck || !ShouldEmitVFEInfo || !ShouldEmitWPDInfo ||
+ CheckResult) &&
"Check result required but not created!");
if (ShouldEmitCFICheck) {
@@ -984,11 +1027,16 @@ llvm::Constant *ItaniumCXXABI::BuildMemberPointer(const CXXMethodDecl *MD,
llvm::Constant *MemPtr[2];
if (MD->isVirtual()) {
uint64_t Index = CGM.getItaniumVTableContext().getMethodVTableIndex(MD);
-
- const ASTContext &Context = getContext();
- CharUnits PointerWidth =
- Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
- uint64_t VTableOffset = (Index * PointerWidth.getQuantity());
+ uint64_t VTableOffset;
+ if (CGM.getItaniumVTableContext().isRelativeLayout()) {
+ // Multiply by 4-byte relative offsets.
+ VTableOffset = Index * 4;
+ } else {
+ const ASTContext &Context = getContext();
+ CharUnits PointerWidth = Context.toCharUnitsFromBits(
+ Context.getTargetInfo().getPointerWidth(0));
+ VTableOffset = Index * PointerWidth.getQuantity();
+ }
if (UseARMMethodPtrABI) {
// ARM C++ ABI 3.2.1:
@@ -1402,8 +1450,19 @@ llvm::Value *ItaniumCXXABI::EmitTypeid(CodeGenFunction &CGF,
llvm::Value *Value =
CGF.GetVTablePtr(ThisPtr, StdTypeInfoPtrTy->getPointerTo(), ClassDecl);
- // Load the type info.
- Value = CGF.Builder.CreateConstInBoundsGEP1_64(Value, -1ULL);
+ if (CGM.getItaniumVTableContext().isRelativeLayout()) {
+ // Load the type info.
+ Value = CGF.Builder.CreateBitCast(Value, CGM.Int8PtrTy);
+ Value = CGF.Builder.CreateCall(
+ CGM.getIntrinsic(llvm::Intrinsic::load_relative, {CGM.Int32Ty}),
+ {Value, llvm::ConstantInt::get(CGM.Int32Ty, -4)});
+
+ // Setup to dereference again since this is a proxy we accessed.
+ Value = CGF.Builder.CreateBitCast(Value, StdTypeInfoPtrTy->getPointerTo());
+ } else {
+ // Load the type info.
+ Value = CGF.Builder.CreateConstInBoundsGEP1_64(Value, -1ULL);
+ }
return CGF.Builder.CreateAlignedLoad(Value, CGF.getPointerAlign());
}
@@ -1459,28 +1518,37 @@ llvm::Value *ItaniumCXXABI::EmitDynamicCastToVoid(CodeGenFunction &CGF,
Address ThisAddr,
QualType SrcRecordTy,
QualType DestTy) {
- llvm::Type *PtrDiffLTy =
- CGF.ConvertType(CGF.getContext().getPointerDiffType());
llvm::Type *DestLTy = CGF.ConvertType(DestTy);
-
auto *ClassDecl =
cast<CXXRecordDecl>(SrcRecordTy->castAs<RecordType>()->getDecl());
- // Get the vtable pointer.
- llvm::Value *VTable = CGF.GetVTablePtr(ThisAddr, PtrDiffLTy->getPointerTo(),
- ClassDecl);
+ llvm::Value *OffsetToTop;
+ if (CGM.getItaniumVTableContext().isRelativeLayout()) {
+ // Get the vtable pointer.
+ llvm::Value *VTable =
+ CGF.GetVTablePtr(ThisAddr, CGM.Int32Ty->getPointerTo(), ClassDecl);
- // Get the offset-to-top from the vtable.
- llvm::Value *OffsetToTop =
- CGF.Builder.CreateConstInBoundsGEP1_64(VTable, -2ULL);
- OffsetToTop =
- CGF.Builder.CreateAlignedLoad(OffsetToTop, CGF.getPointerAlign(),
- "offset.to.top");
+ // Get the offset-to-top from the vtable.
+ OffsetToTop =
+ CGF.Builder.CreateConstInBoundsGEP1_32(/*Type=*/nullptr, VTable, -2U);
+ OffsetToTop = CGF.Builder.CreateAlignedLoad(
+ OffsetToTop, CharUnits::fromQuantity(4), "offset.to.top");
+ } else {
+ llvm::Type *PtrDiffLTy =
+ CGF.ConvertType(CGF.getContext().getPointerDiffType());
+ // Get the vtable pointer.
+ llvm::Value *VTable =
+ CGF.GetVTablePtr(ThisAddr, PtrDiffLTy->getPointerTo(), ClassDecl);
+
+ // Get the offset-to-top from the vtable.
+ OffsetToTop = CGF.Builder.CreateConstInBoundsGEP1_64(VTable, -2ULL);
+ OffsetToTop = CGF.Builder.CreateAlignedLoad(
+ OffsetToTop, CGF.getPointerAlign(), "offset.to.top");
+ }
// Finally, add the offset to the pointer.
llvm::Value *Value = ThisAddr.getPointer();
Value = CGF.EmitCastToVoidPtr(Value);
Value = CGF.Builder.CreateInBoundsGEP(Value, OffsetToTop);
-
return CGF.Builder.CreateBitCast(Value, DestLTy);
}
@@ -1501,17 +1569,22 @@ ItaniumCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF,
CharUnits VBaseOffsetOffset =
CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(ClassDecl,
BaseClassDecl);
-
llvm::Value *VBaseOffsetPtr =
CGF.Builder.CreateConstGEP1_64(VTablePtr, VBaseOffsetOffset.getQuantity(),
"vbase.offset.ptr");
- VBaseOffsetPtr = CGF.Builder.CreateBitCast(VBaseOffsetPtr,
- CGM.PtrDiffTy->getPointerTo());
-
- llvm::Value *VBaseOffset =
- CGF.Builder.CreateAlignedLoad(VBaseOffsetPtr, CGF.getPointerAlign(),
- "vbase.offset");
+ llvm::Value *VBaseOffset;
+ if (CGM.getItaniumVTableContext().isRelativeLayout()) {
+ VBaseOffsetPtr =
+ CGF.Builder.CreateBitCast(VBaseOffsetPtr, CGF.Int32Ty->getPointerTo());
+ VBaseOffset = CGF.Builder.CreateAlignedLoad(
+ VBaseOffsetPtr, CharUnits::fromQuantity(4), "vbase.offset");
+ } else {
+ VBaseOffsetPtr = CGF.Builder.CreateBitCast(VBaseOffsetPtr,
+ CGM.PtrDiffTy->getPointerTo());
+ VBaseOffset = CGF.Builder.CreateAlignedLoad(
+ VBaseOffsetPtr, CGF.getPointerAlign(), "vbase.offset");
+ }
return VBaseOffset;
}
@@ -1531,7 +1604,7 @@ void ItaniumCXXABI::EmitCXXConstructors(const CXXConstructorDecl *D) {
}
}
-CGCXXABI::AddedStructorArgs
+CGCXXABI::AddedStructorArgCounts
ItaniumCXXABI::buildStructorSignature(GlobalDecl GD,
SmallVectorImpl<CanQualType> &ArgTys) {
ASTContext &Context = getContext();
@@ -1545,9 +1618,9 @@ ItaniumCXXABI::buildStructorSignature(GlobalDecl GD,
cast<CXXMethodDecl>(GD.getDecl())->getParent()->getNumVBases() != 0) {
ArgTys.insert(ArgTys.begin() + 1,
Context.getPointerType(Context.VoidPtrTy));
- return AddedStructorArgs::prefix(1);
+ return AddedStructorArgCounts::prefix(1);
}
- return AddedStructorArgs{};
+ return AddedStructorArgCounts{};
}
void ItaniumCXXABI::EmitCXXDestructors(const CXXDestructorDecl *D) {
@@ -1613,9 +1686,9 @@ void ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue);
}
-CGCXXABI::AddedStructorArgs ItaniumCXXABI::addImplicitConstructorArgs(
+CGCXXABI::AddedStructorArgs ItaniumCXXABI::getImplicitConstructorArgs(
CodeGenFunction &CGF, const CXXConstructorDecl *D, CXXCtorType Type,
- bool ForVirtualBase, bool Delegating, CallArgList &Args) {
+ bool ForVirtualBase, bool Delegating) {
if (!NeedsVTTParameter(GlobalDecl(D, Type)))
return AddedStructorArgs{};
@@ -1623,8 +1696,14 @@ CGCXXABI::AddedStructorArgs ItaniumCXXABI::addImplicitConstructorArgs(
llvm::Value *VTT =
CGF.GetVTTParameter(GlobalDecl(D, Type), ForVirtualBase, Delegating);
QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy);
- Args.insert(Args.begin() + 1, CallArg(RValue::get(VTT), VTTTy));
- return AddedStructorArgs::prefix(1); // Added one arg.
+ return AddedStructorArgs::prefix({{VTT, VTTTy}});
+}
+
+llvm::Value *ItaniumCXXABI::getCXXDestructorImplicitParam(
+ CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type,
+ bool ForVirtualBase, bool Delegating) {
+ GlobalDecl GD(DD, Type);
+ return CGF.GetVTTParameter(GD, ForVirtualBase, Delegating);
}
void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
@@ -1633,7 +1712,8 @@ void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
bool Delegating, Address This,
QualType ThisTy) {
GlobalDecl GD(DD, Type);
- llvm::Value *VTT = CGF.GetVTTParameter(GD, ForVirtualBase, Delegating);
+ llvm::Value *VTT =
+ getCXXDestructorImplicitParam(CGF, DD, Type, ForVirtualBase, Delegating);
QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy);
CGCallee Callee;
@@ -1660,10 +1740,11 @@ void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
CGM.GetAddrOfRTTIDescriptor(CGM.getContext().getTagDeclType(RD));
// Create and set the initializer.
- ConstantInitBuilder Builder(CGM);
- auto Components = Builder.beginStruct();
- CGVT.createVTableInitializer(Components, VTLayout, RTTI);
- Components.finishAndSetAsInitializer(VTable);
+ ConstantInitBuilder builder(CGM);
+ auto components = builder.beginStruct();
+ CGVT.createVTableInitializer(components, VTLayout, RTTI,
+ llvm::GlobalValue::isLocalLinkage(Linkage));
+ components.finishAndSetAsInitializer(VTable);
// Set the correct linkage.
VTable->setLinkage(Linkage);
@@ -1687,6 +1768,9 @@ void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
if (!VTable->isDeclarationForLinker())
CGM.EmitVTableTypeMetadata(RD, VTable, VTLayout);
+
+ if (VTContext.isRelativeLayout() && !VTable->isDSOLocal())
+ CGVT.GenerateRelativeVTableAlias(VTable, VTable->getName());
}
bool ItaniumCXXABI::isVirtualOffsetNeededForVTableField(
@@ -1776,7 +1860,9 @@ llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
// Use pointer alignment for the vtable. Otherwise we would align them based
// on the size of the initializer which doesn't make sense as only single
// values are read.
- unsigned PAlign = CGM.getTarget().getPointerAlign(0);
+ unsigned PAlign = CGM.getItaniumVTableContext().isRelativeLayout()
+ ? 32
+ : CGM.getTarget().getPointerAlign(0);
VTable = CGM.CreateOrReplaceCXXRuntimeVariable(
Name, VTableType, llvm::GlobalValue::ExternalLinkage,
@@ -1793,9 +1879,9 @@ CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
Address This,
llvm::Type *Ty,
SourceLocation Loc) {
- Ty = Ty->getPointerTo()->getPointerTo();
auto *MethodDecl = cast<CXXMethodDecl>(GD.getDecl());
- llvm::Value *VTable = CGF.GetVTablePtr(This, Ty, MethodDecl->getParent());
+ llvm::Value *VTable = CGF.GetVTablePtr(
+ This, Ty->getPointerTo()->getPointerTo(), MethodDecl->getParent());
uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD);
llvm::Value *VFunc;
@@ -1806,10 +1892,21 @@ CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
} else {
CGF.EmitTypeMetadataCodeForVCall(MethodDecl->getParent(), VTable, Loc);
- llvm::Value *VFuncPtr =
- CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfn");
- auto *VFuncLoad =
- CGF.Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign());
+ llvm::Value *VFuncLoad;
+ if (CGM.getItaniumVTableContext().isRelativeLayout()) {
+ VTable = CGF.Builder.CreateBitCast(VTable, CGM.Int8PtrTy);
+ llvm::Value *Load = CGF.Builder.CreateCall(
+ CGM.getIntrinsic(llvm::Intrinsic::load_relative, {CGM.Int32Ty}),
+ {VTable, llvm::ConstantInt::get(CGM.Int32Ty, 4 * VTableIndex)});
+ VFuncLoad = CGF.Builder.CreateBitCast(Load, Ty->getPointerTo());
+ } else {
+ VTable =
+ CGF.Builder.CreateBitCast(VTable, Ty->getPointerTo()->getPointerTo());
+ llvm::Value *VTableSlotPtr =
+ CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfn");
+ VFuncLoad =
+ CGF.Builder.CreateAlignedLoad(VTableSlotPtr, CGF.getPointerAlign());
+ }
// Add !invariant.load md to virtual function load to indicate that
// function didn't change inside vtable.
@@ -1818,11 +1915,14 @@ CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
// the same virtual function loads from the same vtable load, which won't
// happen without enabled devirtualization with -fstrict-vtable-pointers.
if (CGM.getCodeGenOpts().OptimizationLevel > 0 &&
- CGM.getCodeGenOpts().StrictVTablePointers)
- VFuncLoad->setMetadata(
- llvm::LLVMContext::MD_invariant_load,
- llvm::MDNode::get(CGM.getLLVMContext(),
- llvm::ArrayRef<llvm::Metadata *>()));
+ CGM.getCodeGenOpts().StrictVTablePointers) {
+ if (auto *VFuncLoadInstr = dyn_cast<llvm::Instruction>(VFuncLoad)) {
+ VFuncLoadInstr->setMetadata(
+ llvm::LLVMContext::MD_invariant_load,
+ llvm::MDNode::get(CGM.getLLVMContext(),
+ llvm::ArrayRef<llvm::Metadata *>()));
+ }
+ }
VFunc = VFuncLoad;
}
@@ -1939,21 +2039,28 @@ static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF,
// Perform the virtual adjustment if we have one.
llvm::Value *ResultPtr;
if (VirtualAdjustment) {
- llvm::Type *PtrDiffTy =
- CGF.ConvertType(CGF.getContext().getPointerDiffType());
-
Address VTablePtrPtr = CGF.Builder.CreateElementBitCast(V, CGF.Int8PtrTy);
llvm::Value *VTablePtr = CGF.Builder.CreateLoad(VTablePtrPtr);
+ llvm::Value *Offset;
llvm::Value *OffsetPtr =
CGF.Builder.CreateConstInBoundsGEP1_64(VTablePtr, VirtualAdjustment);
+ if (CGF.CGM.getItaniumVTableContext().isRelativeLayout()) {
+ // Load the adjustment offset from the vtable as a 32-bit int.
+ OffsetPtr =
+ CGF.Builder.CreateBitCast(OffsetPtr, CGF.Int32Ty->getPointerTo());
+ Offset =
+ CGF.Builder.CreateAlignedLoad(OffsetPtr, CharUnits::fromQuantity(4));
+ } else {
+ llvm::Type *PtrDiffTy =
+ CGF.ConvertType(CGF.getContext().getPointerDiffType());
- OffsetPtr = CGF.Builder.CreateBitCast(OffsetPtr, PtrDiffTy->getPointerTo());
-
- // Load the adjustment offset from the vtable.
- llvm::Value *Offset =
- CGF.Builder.CreateAlignedLoad(OffsetPtr, CGF.getPointerAlign());
+ OffsetPtr =
+ CGF.Builder.CreateBitCast(OffsetPtr, PtrDiffTy->getPointerTo());
+ // Load the adjustment offset from the vtable.
+ Offset = CGF.Builder.CreateAlignedLoad(OffsetPtr, CGF.getPointerAlign());
+ }
// Adjust our pointer.
ResultPtr = CGF.Builder.CreateInBoundsGEP(V.getPointer(), Offset);
} else {
@@ -2438,7 +2545,7 @@ void CodeGenModule::registerGlobalDtorsWithAtExit() {
std::string GlobalInitFnName =
std::string("__GLOBAL_init_") + llvm::to_string(Priority);
llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
- llvm::Function *GlobalInitFn = CreateGlobalInitOrDestructFunction(
+ llvm::Function *GlobalInitFn = CreateGlobalInitOrCleanUpFunction(
FTy, GlobalInitFnName, getTypes().arrangeNullaryFunction(),
SourceLocation());
ASTContext &Ctx = getContext();
@@ -2592,14 +2699,15 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs(
llvm::FunctionType *FTy =
llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
- InitFunc = CGM.CreateGlobalInitOrDestructFunction(FTy, "__tls_init", FI,
- SourceLocation(),
- /*TLS=*/true);
+ InitFunc = CGM.CreateGlobalInitOrCleanUpFunction(FTy, "__tls_init", FI,
+ SourceLocation(),
+ /*TLS=*/true);
llvm::GlobalVariable *Guard = new llvm::GlobalVariable(
CGM.getModule(), CGM.Int8Ty, /*isConstant=*/false,
llvm::GlobalVariable::InternalLinkage,
llvm::ConstantInt::get(CGM.Int8Ty, 0), "__tls_guard");
Guard->setThreadLocal(true);
+ Guard->setThreadLocalMode(CGM.GetDefaultLLVMTLSModel());
CharUnits GuardAlign = CharUnits::One();
Guard->setAlignment(GuardAlign.getAsAlign());
@@ -3008,6 +3116,7 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
case BuiltinType::SatUShortFract:
case BuiltinType::SatUFract:
case BuiltinType::SatULongFract:
+ case BuiltinType::BFloat16:
return false;
case BuiltinType::Dependent:
@@ -3200,9 +3309,11 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) {
llvm_unreachable("Pipe types shouldn't get here");
case Type::Builtin:
+ case Type::ExtInt:
// GCC treats vector and complex types as fundamental types.
case Type::Vector:
case Type::ExtVector:
+ case Type::ConstantMatrix:
case Type::Complex:
case Type::Atomic:
// FIXME: GCC treats block pointers as fundamental types?!
@@ -3277,17 +3388,32 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) {
break;
}
- llvm::Constant *VTable =
- CGM.getModule().getOrInsertGlobal(VTableName, CGM.Int8PtrTy);
+ llvm::Constant *VTable = nullptr;
+
+ // Check if the alias exists. If it doesn't, then get or create the global.
+ if (CGM.getItaniumVTableContext().isRelativeLayout())
+ VTable = CGM.getModule().getNamedAlias(VTableName);
+ if (!VTable)
+ VTable = CGM.getModule().getOrInsertGlobal(VTableName, CGM.Int8PtrTy);
+
CGM.setDSOLocal(cast<llvm::GlobalValue>(VTable->stripPointerCasts()));
llvm::Type *PtrDiffTy =
- CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
+ CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
// The vtable address point is 2.
- llvm::Constant *Two = llvm::ConstantInt::get(PtrDiffTy, 2);
- VTable =
- llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.Int8PtrTy, VTable, Two);
+ if (CGM.getItaniumVTableContext().isRelativeLayout()) {
+ // The vtable address point is 8 bytes after its start:
+ // 4 for the offset to top + 4 for the relative offset to rtti.
+ llvm::Constant *Eight = llvm::ConstantInt::get(CGM.Int32Ty, 8);
+ VTable = llvm::ConstantExpr::getBitCast(VTable, CGM.Int8PtrTy);
+ VTable =
+ llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.Int8Ty, VTable, Eight);
+ } else {
+ llvm::Constant *Two = llvm::ConstantInt::get(PtrDiffTy, 2);
+ VTable = llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.Int8PtrTy, VTable,
+ Two);
+ }
VTable = llvm::ConstantExpr::getBitCast(VTable, CGM.Int8PtrTy);
Fields.push_back(VTable);
@@ -3438,6 +3564,7 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(
case Type::Builtin:
case Type::Vector:
case Type::ExtVector:
+ case Type::ConstantMatrix:
case Type::Complex:
case Type::BlockPointer:
// Itanium C++ ABI 2.9.5p4:
@@ -3453,7 +3580,10 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(
llvm_unreachable("Undeduced type shouldn't get here");
case Type::Pipe:
- llvm_unreachable("Pipe type shouldn't get here");
+ break;
+
+ case Type::ExtInt:
+ break;
case Type::ConstantArray:
case Type::IncompleteArray:
@@ -4401,3 +4531,70 @@ void WebAssemblyCXXABI::emitBeginCatch(CodeGenFunction &CGF,
NormalCleanup, cast<llvm::CatchPadInst>(CGF.CurrentFuncletPad));
ItaniumCXXABI::emitBeginCatch(CGF, C);
}
+
+/// Register a global destructor as best as we know how.
+void XLCXXABI::registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,
+ llvm::FunctionCallee dtor,
+ llvm::Constant *addr) {
+ if (D.getTLSKind() != VarDecl::TLS_None)
+ llvm::report_fatal_error("thread local storage not yet implemented on AIX");
+
+ // Create __dtor function for the var decl.
+ llvm::Function *dtorStub = CGF.createAtExitStub(D, dtor, addr);
+
+ // Register above __dtor with atexit().
+ CGF.registerGlobalDtorWithAtExit(dtorStub);
+
+ // Emit __finalize function to unregister __dtor and (as appropriate) call
+ // __dtor.
+ emitCXXStermFinalizer(D, dtorStub, addr);
+}
+
+void XLCXXABI::emitCXXStermFinalizer(const VarDecl &D, llvm::Function *dtorStub,
+ llvm::Constant *addr) {
+ llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false);
+ SmallString<256> FnName;
+ {
+ llvm::raw_svector_ostream Out(FnName);
+ getMangleContext().mangleDynamicStermFinalizer(&D, Out);
+ }
+
+ // Create the finalization action associated with a variable.
+ const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
+ llvm::Function *StermFinalizer = CGM.CreateGlobalInitOrCleanUpFunction(
+ FTy, FnName.str(), FI, D.getLocation());
+
+ CodeGenFunction CGF(CGM);
+
+ CGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, StermFinalizer, FI,
+ FunctionArgList());
+
+ // The unatexit subroutine unregisters __dtor functions that were previously
+ // registered by the atexit subroutine. If the referenced function is found,
+ // the unatexit returns a value of 0, meaning that the cleanup is still
+ // pending (and we should call the __dtor function).
+ llvm::Value *V = CGF.unregisterGlobalDtorWithUnAtExit(dtorStub);
+
+ llvm::Value *NeedsDestruct = CGF.Builder.CreateIsNull(V, "needs_destruct");
+
+ llvm::BasicBlock *DestructCallBlock = CGF.createBasicBlock("destruct.call");
+ llvm::BasicBlock *EndBlock = CGF.createBasicBlock("destruct.end");
+
+ // Check if unatexit returns a value of 0. If it does, jump to
+ // DestructCallBlock, otherwise jump to EndBlock directly.
+ CGF.Builder.CreateCondBr(NeedsDestruct, DestructCallBlock, EndBlock);
+
+ CGF.EmitBlock(DestructCallBlock);
+
+ // Emit the call to dtorStub.
+ llvm::CallInst *CI = CGF.Builder.CreateCall(dtorStub);
+
+ // Make sure the call and the callee agree on calling convention.
+ CI->setCallingConv(dtorStub->getCallingConv());
+
+ CGF.EmitBlock(EndBlock);
+
+ CGF.FinishFunction();
+
+ CGM.AddCXXStermFinalizerEntry(StermFinalizer);
+}