From 883fc72c3c8273e61d92f43e7b6d9cc6bc7244c7 Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Sat, 29 Jan 2011 19:16:51 +0000 Subject: [PATCH] Make emitting a VTT a two-step process, much like emitting a VTable. You first get the address of the VTT, and then pass it to EmitVTTDefinition. llvm-svn: 124539 --- clang/lib/CodeGen/CGClass.cpp | 2 +- clang/lib/CodeGen/CGRTTI.cpp | 2 +- clang/lib/CodeGen/CGVTT.cpp | 73 +++++++++------------- clang/lib/CodeGen/CGVTables.cpp | 5 +- clang/lib/CodeGen/CGVTables.h | 15 +++-- clang/test/CodeGenCXX/mangle-subst-std.cpp | 6 +- 6 files changed, 49 insertions(+), 54 deletions(-) diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index a7b8f659786f..7efd2bc807fc 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -318,7 +318,7 @@ static llvm::Value *GetVTTParameter(CodeGenFunction &CGF, GlobalDecl GD, VTT = CGF.Builder.CreateConstInBoundsGEP1_64(VTT, SubVTTIndex); } else { // We're the complete constructor, so get the VTT by name. - VTT = CGF.CGM.getVTables().getVTT(RD); + VTT = CGF.CGM.getVTables().GetAddrOfVTT(RD); VTT = CGF.Builder.CreateConstInBoundsGEP2_64(VTT, 0, SubVTTIndex); } diff --git a/clang/lib/CodeGen/CGRTTI.cpp b/clang/lib/CodeGen/CGRTTI.cpp index 4ba58c716399..244bca8095ec 100644 --- a/clang/lib/CodeGen/CGRTTI.cpp +++ b/clang/lib/CodeGen/CGRTTI.cpp @@ -522,7 +522,7 @@ llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) { llvm::SmallString<256> OutName; CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, OutName); llvm::StringRef Name = OutName.str(); - + llvm::GlobalVariable *OldGV = CGM.getModule().getNamedGlobal(Name); if (OldGV && !OldGV->isDeclaration()) return llvm::ConstantExpr::getBitCast(OldGV, Int8PtrTy); diff --git a/clang/lib/CodeGen/CGVTT.cpp b/clang/lib/CodeGen/CGVTT.cpp index 5a99059f1af6..5ebe92b5394a 100644 --- a/clang/lib/CodeGen/CGVTT.cpp +++ b/clang/lib/CodeGen/CGVTT.cpp @@ -366,58 +366,47 @@ void VTTBuilder::LayoutVTT(BaseSubobject Base, bool BaseIsVirtual) { } -llvm::GlobalVariable * -CodeGenVTables::GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage, - bool GenerateDefinition, - const CXXRecordDecl *RD) { - // Only classes that have virtual bases need a VTT. - if (RD->getNumVBases() == 0) - return 0; +void +CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT, + llvm::GlobalVariable::LinkageTypes Linkage, + const CXXRecordDecl *RD) { + VTTBuilder Builder(CGM, RD, /*GenerateDefinition=*/true); + + const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); + const llvm::ArrayType *ArrayType = + llvm::ArrayType::get(Int8PtrTy, Builder.getVTTComponents().size()); + + llvm::Constant *Init = + llvm::ConstantArray::get(ArrayType, Builder.getVTTComponents().data(), + Builder.getVTTComponents().size()); + + VTT->setInitializer(Init); + + // Set the correct linkage. + VTT->setLinkage(Linkage); +} + +llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTT(const CXXRecordDecl *RD) { + assert(RD->getNumVBases() && "Only classes with virtual bases need a VTT"); llvm::SmallString<256> OutName; CGM.getCXXABI().getMangleContext().mangleCXXVTT(RD, OutName); llvm::StringRef Name = OutName.str(); - D1(printf("vtt %s\n", RD->getNameAsCString())); + VTTBuilder Builder(CGM, RD, /*GenerateDefinition=*/false); - llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true); - if (GV == 0 || GV->isDeclaration()) { - const llvm::Type *Int8PtrTy = - llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); + const llvm::Type *Int8PtrTy = + llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); + const llvm::ArrayType *ArrayType = + llvm::ArrayType::get(Int8PtrTy, Builder.getVTTComponents().size()); - VTTBuilder Builder(CGM, RD, GenerateDefinition); - - const llvm::ArrayType *Type = - llvm::ArrayType::get(Int8PtrTy, Builder.getVTTComponents().size()); - - llvm::Constant *Init = 0; - if (GenerateDefinition) - Init = llvm::ConstantArray::get(Type, Builder.getVTTComponents().data(), - Builder.getVTTComponents().size()); - - llvm::GlobalVariable *OldGV = GV; - GV = new llvm::GlobalVariable(CGM.getModule(), Type, /*isConstant=*/true, - Linkage, Init, Name); - CGM.setGlobalVisibility(GV, RD, /*ForDefinition*/ GenerateDefinition); - GV->setUnnamedAddr(true); - - if (OldGV) { - GV->takeName(OldGV); - llvm::Constant *NewPtr = - llvm::ConstantExpr::getBitCast(GV, OldGV->getType()); - OldGV->replaceAllUsesWith(NewPtr); - OldGV->eraseFromParent(); - } - } - + llvm::GlobalVariable *GV = + CGM.CreateOrReplaceCXXRuntimeVariable(Name, ArrayType, + llvm::GlobalValue::ExternalLinkage); + GV->setUnnamedAddr(true); return GV; } -llvm::GlobalVariable *CodeGenVTables::getVTT(const CXXRecordDecl *RD) { - return GenerateVTT(llvm::GlobalValue::ExternalLinkage, - /*GenerateDefinition=*/false, RD); -} - bool CodeGenVTables::needsVTTParameter(GlobalDecl GD) { const CXXMethodDecl *MD = cast(GD.getDecl()); diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index 0ff41bb35423..ad2269418b7f 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -3040,7 +3040,10 @@ CodeGenVTables::GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage, VTable = GetAddrOfVTable(RD); EmitVTableDefinition(VTable, Linkage, RD); - GenerateVTT(Linkage, /*GenerateDefinition=*/true, RD); + if (RD->getNumVBases()) { + llvm::GlobalVariable *VTT = GetAddrOfVTT(RD); + EmitVTTDefinition(VTT, Linkage, RD); + } // If this is the magic class __cxxabiv1::__fundamental_type_info, // we will emit the typeinfo for the fundamental types. This is the diff --git a/clang/lib/CodeGen/CGVTables.h b/clang/lib/CodeGen/CGVTables.h index 3e3cd4b165ab..3aee49372dfd 100644 --- a/clang/lib/CodeGen/CGVTables.h +++ b/clang/lib/CodeGen/CGVTables.h @@ -182,10 +182,6 @@ class CodeGenVTables { void ComputeMethodVTableIndices(const CXXRecordDecl *RD); - llvm::GlobalVariable *GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage, - bool GenerateDefinition, - const CXXRecordDecl *RD); - /// EmitThunk - Emit a single thunk. void EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk); @@ -257,8 +253,15 @@ public: GenerateConstructionVTable(const CXXRecordDecl *RD, const BaseSubobject &Base, bool BaseIsVirtual, VTableAddressPointsMapTy& AddressPoints); - - llvm::GlobalVariable *getVTT(const CXXRecordDecl *RD); + + + /// GetAddrOfVTable - Get the address of the VTT for the given record decl. + llvm::GlobalVariable *GetAddrOfVTT(const CXXRecordDecl *RD); + + /// EmitVTTDefinition - Emit the definition of the given vtable. + void EmitVTTDefinition(llvm::GlobalVariable *VTT, + llvm::GlobalVariable::LinkageTypes Linkage, + const CXXRecordDecl *RD); /// EmitThunks - Emit the associated thunks for the given global decl. void EmitThunks(GlobalDecl GD); diff --git a/clang/test/CodeGenCXX/mangle-subst-std.cpp b/clang/test/CodeGenCXX/mangle-subst-std.cpp index 2b570ed20236..8d79988da8e3 100644 --- a/clang/test/CodeGenCXX/mangle-subst-std.cpp +++ b/clang/test/CodeGenCXX/mangle-subst-std.cpp @@ -3,14 +3,14 @@ // Check mangling of Vtables, VTTs, and construction vtables that // involve standard substitutions. +// CHECK: @_ZTTSd = linkonce_odr unnamed_addr constant // CHECK: @_ZTVSd = linkonce_odr unnamed_addr constant // CHECK: @_ZTCSd0_Si = internal constant // CHECK: @_ZTCSd16_So = internal constant -// CHECK: @_ZTTSd = linkonce_odr unnamed_addr constant -// CHECK: @_ZTVSo = linkonce_odr unnamed_addr constant // CHECK: @_ZTTSo = linkonce_odr unnamed_addr constant -// CHECK: @_ZTVSi = linkonce_odr unnamed_addr constant +// CHECK: @_ZTVSo = linkonce_odr unnamed_addr constant // CHECK: @_ZTTSi = linkonce_odr unnamed_addr constant +// CHECK: @_ZTVSi = linkonce_odr unnamed_addr constant namespace std { struct A { A(); };