Skip to content

Commit 8acdcf4

Browse files
committed
[Clang][CodeGen]vtable, typeinfo et al. are globals
All data structures and values associated with handling virtual functions / inheritance, as well as RTTI, are globals and thus can only reside in the global address space. This was not taken fully taken into account because for most targets, global & generic appear to coincide. However, on targets where global & generic ASes differ (e.g. AMDGPU), this was problematic, since it led to the generation of invalid bitcasts (which would trigger asserts in Debug) and less than optimal code. This patch does two things: ensures that vtables, vptrs, vtts, typeinfo are generated in the right AS, and populated accordingly; removes a bunch of bitcasts which look like left-overs from the typed ptr era. Reviewed By: yxsamliu Differential Revision: https://reviews.llvm.org/D153092
1 parent 3055c58 commit 8acdcf4

15 files changed

+1057
-56
lines changed

clang/lib/CodeGen/CGVTT.cpp

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT,
4242
llvm::GlobalVariable::LinkageTypes Linkage,
4343
const CXXRecordDecl *RD) {
4444
VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/true);
45-
llvm::ArrayType *ArrayType =
46-
llvm::ArrayType::get(CGM.Int8PtrTy, Builder.getVTTComponents().size());
45+
llvm::ArrayType *ArrayType = llvm::ArrayType::get(
46+
CGM.GlobalsInt8PtrTy, Builder.getVTTComponents().size());
4747

4848
SmallVector<llvm::GlobalVariable *, 8> VTables;
4949
SmallVector<VTableAddressPointsMapTy, 8> VTableAddressPoints;
@@ -81,9 +81,6 @@ CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT,
8181
VTable->getValueType(), VTable, Idxs, /*InBounds=*/true,
8282
/*InRangeIndex=*/1);
8383

84-
Init = llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(Init,
85-
CGM.Int8PtrTy);
86-
8784
VTTComponents.push_back(Init);
8885
}
8986

@@ -112,9 +109,9 @@ llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTT(const CXXRecordDecl *RD) {
112109

113110
VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false);
114111

115-
llvm::ArrayType *ArrayType =
116-
llvm::ArrayType::get(CGM.Int8PtrTy, Builder.getVTTComponents().size());
117-
llvm::Align Align = CGM.getDataLayout().getABITypeAlign(CGM.Int8PtrTy);
112+
llvm::ArrayType *ArrayType = llvm::ArrayType::get(
113+
CGM.GlobalsInt8PtrTy, Builder.getVTTComponents().size());
114+
llvm::Align Align = CGM.getDataLayout().getABITypeAlign(CGM.GlobalsInt8PtrTy);
118115

119116
llvm::GlobalVariable *GV = CGM.CreateOrReplaceCXXRuntimeVariable(
120117
Name, ArrayType, llvm::GlobalValue::ExternalLinkage, Align);

clang/lib/CodeGen/CGVTables.cpp

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -690,7 +690,7 @@ bool CodeGenVTables::useRelativeLayout() const {
690690
llvm::Type *CodeGenModule::getVTableComponentType() const {
691691
if (UseRelativeLayout(*this))
692692
return Int32Ty;
693-
return Int8PtrTy;
693+
return GlobalsInt8PtrTy;
694694
}
695695

696696
llvm::Type *CodeGenVTables::getVTableComponentType() const {
@@ -702,7 +702,7 @@ static void AddPointerLayoutOffset(const CodeGenModule &CGM,
702702
CharUnits offset) {
703703
builder.add(llvm::ConstantExpr::getIntToPtr(
704704
llvm::ConstantInt::get(CGM.PtrDiffTy, offset.getQuantity()),
705-
CGM.Int8PtrTy));
705+
CGM.GlobalsInt8PtrTy));
706706
}
707707

708708
static void AddRelativeLayoutOffset(const CodeGenModule &CGM,
@@ -739,7 +739,7 @@ void CodeGenVTables::addVTableComponent(ConstantArrayBuilder &builder,
739739
vtableHasLocalLinkage,
740740
/*isCompleteDtor=*/false);
741741
else
742-
return builder.add(llvm::ConstantExpr::getBitCast(rtti, CGM.Int8PtrTy));
742+
return builder.add(rtti);
743743

744744
case VTableComponent::CK_FunctionPointer:
745745
case VTableComponent::CK_CompleteDtorPointer:
@@ -758,7 +758,8 @@ void CodeGenVTables::addVTableComponent(ConstantArrayBuilder &builder,
758758
? MD->hasAttr<CUDADeviceAttr>()
759759
: (MD->hasAttr<CUDAHostAttr>() || !MD->hasAttr<CUDADeviceAttr>());
760760
if (!CanEmitMethod)
761-
return builder.add(llvm::ConstantExpr::getNullValue(CGM.Int8PtrTy));
761+
return builder.add(
762+
llvm::ConstantExpr::getNullValue(CGM.GlobalsInt8PtrTy));
762763
// Method is acceptable, continue processing as usual.
763764
}
764765

@@ -771,20 +772,20 @@ void CodeGenVTables::addVTableComponent(ConstantArrayBuilder &builder,
771772
// with the local symbol. As a temporary solution, fill these components
772773
// with zero. We shouldn't be calling these in the first place anyway.
773774
if (useRelativeLayout())
774-
return llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
775+
return llvm::ConstantPointerNull::get(CGM.GlobalsInt8PtrTy);
775776

776777
// For NVPTX devices in OpenMP emit special functon as null pointers,
777778
// otherwise linking ends up with unresolved references.
778779
if (CGM.getLangOpts().OpenMP && CGM.getLangOpts().OpenMPIsTargetDevice &&
779780
CGM.getTriple().isNVPTX())
780-
return llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
781+
return llvm::ConstantPointerNull::get(CGM.GlobalsInt8PtrTy);
781782
llvm::FunctionType *fnTy =
782783
llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
783784
llvm::Constant *fn = cast<llvm::Constant>(
784785
CGM.CreateRuntimeFunction(fnTy, name).getCallee());
785786
if (auto f = dyn_cast<llvm::Function>(fn))
786787
f->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
787-
return llvm::ConstantExpr::getBitCast(fn, CGM.Int8PtrTy);
788+
return fn;
788789
};
789790

790791
llvm::Constant *fnPtr;
@@ -822,15 +823,26 @@ void CodeGenVTables::addVTableComponent(ConstantArrayBuilder &builder,
822823
return addRelativeComponent(
823824
builder, fnPtr, vtableAddressPoint, vtableHasLocalLinkage,
824825
component.getKind() == VTableComponent::CK_CompleteDtorPointer);
825-
} else
826-
return builder.add(llvm::ConstantExpr::getBitCast(fnPtr, CGM.Int8PtrTy));
826+
} else {
827+
// TODO: this icky and only exists due to functions being in the generic
828+
// address space, rather than the global one, even though they are
829+
// globals; fixing said issue might be intrusive, and will be done
830+
// later.
831+
unsigned FnAS = fnPtr->getType()->getPointerAddressSpace();
832+
unsigned GVAS = CGM.GlobalsInt8PtrTy->getPointerAddressSpace();
833+
834+
if (FnAS != GVAS)
835+
fnPtr =
836+
llvm::ConstantExpr::getAddrSpaceCast(fnPtr, CGM.GlobalsInt8PtrTy);
837+
return builder.add(fnPtr);
838+
}
827839
}
828840

829841
case VTableComponent::CK_UnusedFunctionPointer:
830842
if (useRelativeLayout())
831843
return builder.add(llvm::ConstantExpr::getNullValue(CGM.Int32Ty));
832844
else
833-
return builder.addNullPointer(CGM.Int8PtrTy);
845+
return builder.addNullPointer(CGM.GlobalsInt8PtrTy);
834846
}
835847

836848
llvm_unreachable("Unexpected vtable component kind");

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7155,7 +7155,7 @@ llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty,
71557155
if ((!ForEH && !getLangOpts().RTTI) || getLangOpts().CUDAIsDevice ||
71567156
(getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice &&
71577157
getTriple().isNVPTX()))
7158-
return llvm::Constant::getNullValue(Int8PtrTy);
7158+
return llvm::Constant::getNullValue(GlobalsInt8PtrTy);
71597159

71607160
if (ForEH && Ty->isObjCObjectPointerType() &&
71617161
LangOpts.ObjCRuntime.isGNUFamily())

clang/lib/CodeGen/ItaniumCXXABI.cpp

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -624,7 +624,7 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
624624
CGF.EmitBlock(FnVirtual);
625625

626626
// Cast the adjusted this to a pointer to vtable pointer and load.
627-
llvm::Type *VTableTy = Builder.getInt8PtrTy();
627+
llvm::Type *VTableTy = CGF.CGM.GlobalsInt8PtrTy;
628628
CharUnits VTablePtrAlign =
629629
CGF.CGM.getDynamicOffsetAlignment(ThisAddr.getAlignment(), RD,
630630
CGF.getPointerAlign());
@@ -1821,11 +1821,11 @@ llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructorWithVTT(
18211821
/// Load the VTT.
18221822
llvm::Value *VTT = CGF.LoadCXXVTT();
18231823
if (VirtualPointerIndex)
1824-
VTT = CGF.Builder.CreateConstInBoundsGEP1_64(
1825-
CGF.VoidPtrTy, VTT, VirtualPointerIndex);
1824+
VTT = CGF.Builder.CreateConstInBoundsGEP1_64(CGF.GlobalsVoidPtrTy, VTT,
1825+
VirtualPointerIndex);
18261826

18271827
// And load the address point from the VTT.
1828-
return CGF.Builder.CreateAlignedLoad(CGF.VoidPtrTy, VTT,
1828+
return CGF.Builder.CreateAlignedLoad(CGF.GlobalsVoidPtrTy, VTT,
18291829
CGF.getPointerAlign());
18301830
}
18311831

@@ -1853,12 +1853,13 @@ llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
18531853
CGM.getItaniumVTableContext().getVTableLayout(RD);
18541854
llvm::Type *VTableType = CGM.getVTables().getVTableType(VTLayout);
18551855

1856-
// Use pointer alignment for the vtable. Otherwise we would align them based
1857-
// on the size of the initializer which doesn't make sense as only single
1858-
// values are read.
1856+
// Use pointer to global alignment for the vtable. Otherwise we would align
1857+
// them based on the size of the initializer which doesn't make sense as only
1858+
// single values are read.
1859+
LangAS AS = CGM.GetGlobalVarAddressSpace(nullptr);
18591860
unsigned PAlign = CGM.getItaniumVTableContext().isRelativeLayout()
18601861
? 32
1861-
: CGM.getTarget().getPointerAlign(LangAS::Default);
1862+
: CGM.getTarget().getPointerAlign(AS);
18621863

18631864
VTable = CGM.CreateOrReplaceCXXRuntimeVariable(
18641865
Name, VTableType, llvm::GlobalValue::ExternalLinkage,
@@ -1893,7 +1894,7 @@ CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
18931894
Address This,
18941895
llvm::Type *Ty,
18951896
SourceLocation Loc) {
1896-
llvm::Type *PtrTy = llvm::PointerType::getUnqual(CGF.getLLVMContext());
1897+
llvm::Type *PtrTy = CGM.GlobalsInt8PtrTy;
18971898
auto *MethodDecl = cast<CXXMethodDecl>(GD.getDecl());
18981899
llvm::Value *VTable = CGF.GetVTablePtr(This, PtrTy, MethodDecl->getParent());
18991900

@@ -3157,10 +3158,9 @@ ItaniumRTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) {
31573158
// Note for the future: If we would ever like to do deferred emission of
31583159
// RTTI, check if emitting vtables opportunistically need any adjustment.
31593160

3160-
GV = new llvm::GlobalVariable(CGM.getModule(), CGM.Int8PtrTy,
3161-
/*isConstant=*/true,
3162-
llvm::GlobalValue::ExternalLinkage, nullptr,
3163-
Name);
3161+
GV = new llvm::GlobalVariable(
3162+
CGM.getModule(), CGM.GlobalsInt8PtrTy,
3163+
/*isConstant=*/true, llvm::GlobalValue::ExternalLinkage, nullptr, Name);
31643164
const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
31653165
CGM.setGVProperties(GV, RD);
31663166
// Import the typeinfo symbol when all non-inline virtual methods are
@@ -3173,7 +3173,7 @@ ItaniumRTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) {
31733173
}
31743174
}
31753175

3176-
return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
3176+
return GV;
31773177
}
31783178

31793179
/// TypeInfoIsInStandardLibrary - Given a builtin type, returns whether the type
@@ -3551,7 +3551,8 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) {
35513551
if (CGM.getItaniumVTableContext().isRelativeLayout())
35523552
VTable = CGM.getModule().getNamedAlias(VTableName);
35533553
if (!VTable)
3554-
VTable = CGM.getModule().getOrInsertGlobal(VTableName, CGM.Int8PtrTy);
3554+
VTable =
3555+
CGM.getModule().getOrInsertGlobal(VTableName, CGM.GlobalsInt8PtrTy);
35553556

35563557
CGM.setDSOLocal(cast<llvm::GlobalValue>(VTable->stripPointerCasts()));
35573558

@@ -3563,15 +3564,13 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) {
35633564
// The vtable address point is 8 bytes after its start:
35643565
// 4 for the offset to top + 4 for the relative offset to rtti.
35653566
llvm::Constant *Eight = llvm::ConstantInt::get(CGM.Int32Ty, 8);
3566-
VTable = llvm::ConstantExpr::getBitCast(VTable, CGM.Int8PtrTy);
35673567
VTable =
35683568
llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.Int8Ty, VTable, Eight);
35693569
} else {
35703570
llvm::Constant *Two = llvm::ConstantInt::get(PtrDiffTy, 2);
3571-
VTable = llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.Int8PtrTy, VTable,
3572-
Two);
3571+
VTable = llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.GlobalsInt8PtrTy,
3572+
VTable, Two);
35733573
}
3574-
VTable = llvm::ConstantExpr::getBitCast(VTable, CGM.Int8PtrTy);
35753574

35763575
Fields.push_back(VTable);
35773576
}
@@ -3643,7 +3642,7 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty) {
36433642
assert(!OldGV->hasAvailableExternallyLinkage() &&
36443643
"available_externally typeinfos not yet implemented");
36453644

3646-
return llvm::ConstantExpr::getBitCast(OldGV, CGM.Int8PtrTy);
3645+
return OldGV;
36473646
}
36483647

36493648
// Check if there is already an external RTTI descriptor for this type.
@@ -3703,9 +3702,9 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(
37033702
llvm::ConstantInt::get(CGM.Int64Ty, ((uint64_t)1) << 63);
37043703
TypeNameField = llvm::ConstantExpr::getAdd(TypeNameField, flag);
37053704
TypeNameField =
3706-
llvm::ConstantExpr::getIntToPtr(TypeNameField, CGM.Int8PtrTy);
3705+
llvm::ConstantExpr::getIntToPtr(TypeNameField, CGM.GlobalsInt8PtrTy);
37073706
} else {
3708-
TypeNameField = llvm::ConstantExpr::getBitCast(TypeName, CGM.Int8PtrTy);
3707+
TypeNameField = TypeName;
37093708
}
37103709
Fields.push_back(TypeNameField);
37113710

@@ -3835,7 +3834,7 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(
38353834
GV->setComdat(M.getOrInsertComdat(GV->getName()));
38363835

38373836
CharUnits Align = CGM.getContext().toCharUnitsFromBits(
3838-
CGM.getTarget().getPointerAlign(LangAS::Default));
3837+
CGM.getTarget().getPointerAlign(CGM.GetGlobalVarAddressSpace(nullptr)));
38393838
GV->setAlignment(Align.getAsAlign());
38403839

38413840
// The Itanium ABI specifies that type_info objects must be globally
@@ -3867,7 +3866,7 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(
38673866
TypeName->setPartition(CGM.getCodeGenOpts().SymbolPartition);
38683867
GV->setPartition(CGM.getCodeGenOpts().SymbolPartition);
38693868

3870-
return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
3869+
return GV;
38713870
}
38723871

38733872
/// BuildObjCObjectTypeInfo - Build the appropriate kind of type_info
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %clang_cc1 %s -triple=amdgcn-amd-amdhsa -std=c++11 -emit-llvm -o - | FileCheck %s
2+
3+
struct A {
4+
virtual void f();
5+
virtual void g();
6+
virtual void h();
7+
};
8+
9+
void A::f() {}
10+
11+
// CHECK: @_ZTV1A ={{.*}} unnamed_addr addrspace(1) constant { [5 x ptr addrspace(1)] } { [5 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) @_ZTI1A, ptr addrspace(1) addrspacecast (ptr @_ZN1A1fEv to ptr addrspace(1)), ptr addrspace(1) addrspacecast (ptr @_ZN1A1gEv to ptr addrspace(1)), ptr addrspace(1) addrspacecast (ptr @_ZN1A1hEv to ptr addrspace(1))]
12+
// CHECK: @_ZTS1A ={{.*}} constant [3 x i8] c"1A\00", align 1
13+
// CHECK: @_ZTI1A ={{.*}} addrspace(1) constant { ptr addrspace(1), ptr addrspace(1) } { ptr addrspace(1) getelementptr inbounds (ptr addrspace(1), ptr addrspace(1) @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), ptr addrspace(1) @_ZTS1A }, align 8

0 commit comments

Comments
 (0)