diff options
author | Anders Carlsson <andersca@mac.com> | 2010-03-25 15:26:28 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2010-03-25 15:26:28 +0000 |
commit | 0d1407e8784844397e0f754a2212161c563f25fa (patch) | |
tree | 4909374b13a7abcf8e9cdb063d055a66137c9816 /lib/CodeGen/CGVtable.cpp | |
parent | d9ab76bbce7b8a563aa847cfcdcd39d8280f11bd (diff) |
When -fdump-vtable-layouts is specified, construction vtable initializers will be generated using the new vtable layout code. (The code is still not completely in place but this is a huge step forward).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@99508 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGVtable.cpp')
-rw-r--r-- | lib/CodeGen/CGVtable.cpp | 145 |
1 files changed, 127 insertions, 18 deletions
diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 50b2ac8759..85ab80bfc7 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -1328,6 +1328,14 @@ public: return AddressPoints.end(); } + VtableThunksMapTy::const_iterator vtable_thunks_begin() const { + return VTableThunks.begin(); + } + + VtableThunksMapTy::const_iterator vtable_thunks_end() const { + return VTableThunks.end(); + } + /// dumpLayout - Dump the vtable layout. void dumpLayout(llvm::raw_ostream&); }; @@ -3995,6 +4003,72 @@ CodeGenVTables::GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage, GenerateVTT(Linkage, /*GenerateDefinition=*/true, RD); } +llvm::Constant * +CodeGenVTables::CreateVTableInitializer(const CXXRecordDecl *RD, + const uint64_t *Components, + unsigned NumComponents, + const VTableThunksTy &VTableThunks) { + llvm::SmallVector<llvm::Constant *, 64> Inits; + + const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); + + for (unsigned I = 0; I != NumComponents; ++I) { + // FIXME: Better value. + llvm::Constant *Init = llvm::Constant::getNullValue(Int8PtrTy); + + Inits.push_back(Init); + } + + llvm::ArrayType *ArrayType = llvm::ArrayType::get(Int8PtrTy, NumComponents); + return llvm::ConstantArray::get(ArrayType, Inits.data(), Inits.size()); +} + +/// GetGlobalVariable - Will return a global variable of the given type. +/// If a variable with a different type already exists then a new variable +/// with the right type will be created. +/// FIXME: We should move this to CodeGenModule and rename it to something +/// better and then use it in CGVTT and CGRTTI. +static llvm::GlobalVariable * +GetGlobalVariable(llvm::Module &Module, llvm::StringRef Name, + const llvm::Type *Ty, + llvm::GlobalValue::LinkageTypes Linkage) { + + llvm::GlobalVariable *GV = Module.getNamedGlobal(Name); + llvm::GlobalVariable *OldGV = 0; + + if (GV) { + // Check if the variable has the right type. + if (GV->getType()->getElementType() == Ty) { + // Set the correct linkage. + GV->setLinkage(Linkage); + return GV; + } + + assert(GV->isDeclaration() && "Declaration has wrong type!"); + + OldGV = GV; + } + + // Create a new variable. + GV = new llvm::GlobalVariable(Module, Ty, /*isConstant=*/true, + Linkage, 0, Name); + + if (OldGV) { + // Replace occurrences of the old variable if needed. + GV->takeName(OldGV); + + if (!OldGV->use_empty()) { + llvm::Constant *NewPtrForOldDecl = + llvm::ConstantExpr::getBitCast(GV, OldGV->getType()); + OldGV->replaceAllUsesWith(NewPtrForOldDecl); + } + + OldGV->eraseFromParent(); + } + + return GV; +} + llvm::Constant *CodeGenVTables::GetAddrOfVTable(const CXXRecordDecl *RD) { llvm::SmallString<256> OutName; CGM.getMangleContext().mangleCXXVtable(RD, OutName); @@ -4025,29 +4099,64 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD, const BaseSubobject &Base, bool BaseIsVirtual, AddressPointsMapTy& AddressPoints) { - - llvm::DenseMap<BaseSubobject, uint64_t> VTableAddressPoints; - - llvm::GlobalVariable *VTable = - GenerateVtable(llvm::GlobalValue::InternalLinkage, - /*GenerateDefinition=*/true, - RD, Base.getBase(), Base.getBaseOffset(), - BaseIsVirtual, VTableAddressPoints); - - // Add the address points for this base. - for (llvm::DenseMap<BaseSubobject, uint64_t>::const_iterator I = - VTableAddressPoints.begin(), E = VTableAddressPoints.end(); - I != E; ++I) { + if (!CGM.getLangOptions().DumpVtableLayouts) { + llvm::DenseMap<BaseSubobject, uint64_t> VTableAddressPoints; + + llvm::GlobalVariable *VTable = + GenerateVtable(llvm::GlobalValue::InternalLinkage, + /*GenerateDefinition=*/true, + RD, Base.getBase(), Base.getBaseOffset(), + BaseIsVirtual, VTableAddressPoints); + + // Add the address points for this base. + for (llvm::DenseMap<BaseSubobject, uint64_t>::const_iterator I = + VTableAddressPoints.begin(), E = VTableAddressPoints.end(); + I != E; ++I) { - uint64_t &AddressPoint = - AddressPoints[std::make_pair(Base.getBase(), I->first)]; + uint64_t &AddressPoint = + AddressPoints[std::make_pair(Base.getBase(), I->first)]; - // Check if we already have the address points for this base. - assert(!AddressPoint && "Address point already exists for this base!"); + // Check if we already have the address points for this base. + assert(!AddressPoint && "Address point already exists for this base!"); - AddressPoint = I->second; + AddressPoint = I->second; + } + + return VTable; } + VtableBuilder Builder(*this, Base.getBase(), Base.getBaseOffset(), + /*MostDerivedClassIsVirtual=*/BaseIsVirtual, RD); + + Builder.dumpLayout(llvm::errs()); + + // Get the mangled construction vtable name. + llvm::SmallString<256> OutName; + CGM.getMangleContext().mangleCXXCtorVtable(RD, Base.getBaseOffset() / 8, + Base.getBase(), OutName); + llvm::StringRef Name = OutName.str(); + + const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); + llvm::ArrayType *ArrayType = + llvm::ArrayType::get(Int8PtrTy, Builder.getNumVTableComponents()); + + // Create the variable that will hold the construction vtable. + llvm::GlobalVariable *VTable = + GetGlobalVariable(CGM.getModule(), Name, ArrayType, + llvm::GlobalValue::InternalLinkage); + + // Add the thunks. + VTableThunksTy VTableThunks; + VTableThunks.append(Builder.vtable_thunks_begin(), + Builder.vtable_thunks_end()); + + // Create and set the initializer. + llvm::Constant *Init = + CreateVTableInitializer(Base.getBase(), + Builder.vtable_components_data_begin(), + Builder.getNumVTableComponents(), VTableThunks); + VTable->setInitializer(Init); + return VTable; } |