diff options
author | Anders Carlsson <andersca@mac.com> | 2010-01-21 16:50:45 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2010-01-21 16:50:45 +0000 |
commit | f768db7775ca33ca8a592f115b0ae06634367f33 (patch) | |
tree | 081aba1bd090764c4edd6ec343d9db48fb3c59ab /clang | |
parent | 93f899509d0c847a3da62b2512df59728124f6bb (diff) | |
download | bcm5719-llvm-f768db7775ca33ca8a592f115b0ae06634367f33.tar.gz bcm5719-llvm-f768db7775ca33ca8a592f115b0ae06634367f33.zip |
Move the VTT related code into its own file, CGVTT.cpp
llvm-svn: 94079
Diffstat (limited to 'clang')
-rw-r--r-- | clang/clang.xcodeproj/project.pbxproj | 4 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGVTT.cpp | 398 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGVtable.cpp | 378 | ||||
-rw-r--r-- | clang/lib/CodeGen/CMakeLists.txt | 1 |
4 files changed, 403 insertions, 378 deletions
diff --git a/clang/clang.xcodeproj/project.pbxproj b/clang/clang.xcodeproj/project.pbxproj index 72d0b45931d..d1cd032ec03 100644 --- a/clang/clang.xcodeproj/project.pbxproj +++ b/clang/clang.xcodeproj/project.pbxproj @@ -43,6 +43,7 @@ 1A81AA19108144F40094E50B /* CGVtable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A81AA18108144F40094E50B /* CGVtable.cpp */; }; 1A869A700BA2164C008DA07A /* LiteralSupport.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1A869A6E0BA2164C008DA07A /* LiteralSupport.h */; }; 1A869AA80BA21ABA008DA07A /* LiteralSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */; }; + 1A97825B1108BA18002B98FC /* CGVTT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A97825A1108BA18002B98FC /* CGVTT.cpp */; }; 1A986AB710D0746D00A8EA9E /* CGDeclCXX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A986AB610D0746D00A8EA9E /* CGDeclCXX.cpp */; }; 1AA1D91810125DE30078DEBC /* RecordLayoutBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AA1D91610125DE30078DEBC /* RecordLayoutBuilder.cpp */; }; 1AA963C410D85A7300786C86 /* FullExpr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AA963C310D85A7300786C86 /* FullExpr.cpp */; }; @@ -404,6 +405,7 @@ 1A81AA5D108278A20094E50B /* CGVtable.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = CGVtable.h; path = lib/CodeGen/CGVtable.h; sourceTree = "<group>"; tabWidth = 2; }; 1A869A6E0BA2164C008DA07A /* LiteralSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LiteralSupport.h; sourceTree = "<group>"; }; 1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LiteralSupport.cpp; sourceTree = "<group>"; }; + 1A97825A1108BA18002B98FC /* CGVTT.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CGVTT.cpp; path = lib/CodeGen/CGVTT.cpp; sourceTree = "<group>"; }; 1A986AB610D0746D00A8EA9E /* CGDeclCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGDeclCXX.cpp; path = lib/CodeGen/CGDeclCXX.cpp; sourceTree = "<group>"; tabWidth = 2; }; 1AA1D91610125DE30078DEBC /* RecordLayoutBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = RecordLayoutBuilder.cpp; path = lib/AST/RecordLayoutBuilder.cpp; sourceTree = "<group>"; tabWidth = 2; }; 1AA1D91710125DE30078DEBC /* RecordLayoutBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = RecordLayoutBuilder.h; path = lib/AST/RecordLayoutBuilder.h; sourceTree = "<group>"; tabWidth = 2; }; @@ -1317,6 +1319,7 @@ 35475B230E7997680000BFE4 /* CGValue.h */, 1A81AA18108144F40094E50B /* CGVtable.cpp */, 1A81AA5D108278A20094E50B /* CGVtable.h */, + 1A97825A1108BA18002B98FC /* CGVTT.cpp */, DE928B800C0A615B00231DA4 /* CodeGenFunction.h */, DE928B820C0A616000231DA4 /* CodeGenFunction.cpp */, DE928B7C0C0A615100231DA4 /* CodeGenModule.h */, @@ -1963,6 +1966,7 @@ 1ACB57EA1105820D0047B991 /* LangStandards.cpp in Sources */, 1ACB57EB1105820D0047B991 /* TypeXML.cpp in Sources */, 1ACB57EC1105820D0047B991 /* VerifyDiagnosticsClient.cpp in Sources */, + 1A97825B1108BA18002B98FC /* CGVTT.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/clang/lib/CodeGen/CGVTT.cpp b/clang/lib/CodeGen/CGVTT.cpp new file mode 100644 index 00000000000..9714bd9d967 --- /dev/null +++ b/clang/lib/CodeGen/CGVTT.cpp @@ -0,0 +1,398 @@ +//===--- CGVTT.cpp - Emit LLVM Code for C++ VTTs --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This contains code dealing with C++ code generation of VTTs (vtable tables). +// +//===----------------------------------------------------------------------===// + +#include "CodeGenModule.h" +#include "clang/AST/RecordLayout.h" +using namespace clang; +using namespace CodeGen; + +#define D1(x) + +namespace { +class VTTBuilder { + /// Inits - The list of values built for the VTT. + std::vector<llvm::Constant *> &Inits; + /// Class - The most derived class that this vtable is being built for. + const CXXRecordDecl *Class; + CodeGenModule &CGM; // Per-module state. + llvm::SmallSet<const CXXRecordDecl *, 32> SeenVBase; + /// BLayout - Layout for the most derived class that this vtable is being + /// built for. + const ASTRecordLayout &BLayout; + CGVtableInfo::AddrMap_t &AddressPoints; + // vtbl - A pointer to the vtable for Class. + llvm::Constant *ClassVtbl; + llvm::LLVMContext &VMContext; + + /// SeenVBasesInSecondary - The seen virtual bases when building the + /// secondary virtual pointers. + llvm::SmallPtrSet<const CXXRecordDecl *, 32> SeenVBasesInSecondary; + + llvm::DenseMap<const CXXRecordDecl *, uint64_t> SubVTTIndicies; + + bool GenerateDefinition; + + llvm::DenseMap<BaseSubobject, llvm::Constant *> CtorVtables; + llvm::DenseMap<std::pair<const CXXRecordDecl *, BaseSubobject>, uint64_t> + CtorVtableAddressPoints; + + llvm::Constant *getCtorVtable(const BaseSubobject &Base) { + if (!GenerateDefinition) + return 0; + + llvm::Constant *&CtorVtable = CtorVtables[Base]; + if (!CtorVtable) { + // Build the vtable. + CGVtableInfo::CtorVtableInfo Info + = CGM.getVtableInfo().getCtorVtable(Class, Base); + + CtorVtable = Info.Vtable; + + // Add the address points for this base. + for (CGVtableInfo::AddressPointsMapTy::const_iterator I = + Info.AddressPoints.begin(), E = Info.AddressPoints.end(); + I != E; ++I) { + uint64_t &AddressPoint = + CtorVtableAddressPoints[std::make_pair(Base.getBase(), I->first)]; + + // Check if we already have the address points for this base. + if (AddressPoint) + break; + + // Otherwise, insert it. + AddressPoint = I->second; + } + } + + return CtorVtable; + } + + + /// BuildVtablePtr - Build up a referene to the given secondary vtable + llvm::Constant *BuildVtablePtr(llvm::Constant *Vtable, + const CXXRecordDecl *VtableClass, + const CXXRecordDecl *RD, + uint64_t Offset) { + if (!GenerateDefinition) + return 0; + + uint64_t AddressPoint; + + if (VtableClass != Class) { + // We have a ctor vtable, look for the address point in the ctor vtable + // address points. + AddressPoint = + CtorVtableAddressPoints[std::make_pair(VtableClass, + BaseSubobject(RD, Offset))]; + } else { + AddressPoint = + (*AddressPoints[VtableClass])[std::make_pair(RD, Offset)]; + } + + // FIXME: We can never have 0 address point. Do this for now so gepping + // retains the same structure. Later we'll just assert. + if (AddressPoint == 0) + AddressPoint = 1; + D1(printf("XXX address point for %s in %s layout %s at offset %d was %d\n", + RD->getNameAsCString(), VtblClass->getNameAsCString(), + Class->getNameAsCString(), (int)Offset, (int)AddressPoint)); + + llvm::Value *Idxs[] = { + llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), 0), + llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), AddressPoint) + }; + + llvm::Constant *Init = + llvm::ConstantExpr::getInBoundsGetElementPtr(Vtable, Idxs, 2); + + const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext); + return llvm::ConstantExpr::getBitCast(Init, Int8PtrTy); + } + + /// Secondary - Add the secondary vtable pointers to Inits. Offset is the + /// current offset in bits to the object we're working on. + void Secondary(const CXXRecordDecl *RD, llvm::Constant *vtbl, + const CXXRecordDecl *VtblClass, uint64_t Offset=0, + bool MorallyVirtual=false) { + if (RD->getNumVBases() == 0 && ! MorallyVirtual) + return; + + for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), + e = RD->bases_end(); i != e; ++i) { + const CXXRecordDecl *Base = + cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); + + // We only want to visit each virtual base once. + if (i->isVirtual() && SeenVBasesInSecondary.count(Base)) + continue; + + // Itanium C++ ABI 2.6.2: + // Secondary virtual pointers are present for all bases with either + // virtual bases or virtual function declarations overridden along a + // virtual path. + // + // If the base class is not dynamic, we don't want to add it, nor any + // of its base classes. + if (!Base->isDynamicClass()) + continue; + + const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); + const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); + const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual(); + bool NonVirtualPrimaryBase; + NonVirtualPrimaryBase = !PrimaryBaseWasVirtual && Base == PrimaryBase; + bool BaseMorallyVirtual = MorallyVirtual | i->isVirtual(); + uint64_t BaseOffset; + if (!i->isVirtual()) { + const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); + BaseOffset = Offset + Layout.getBaseClassOffset(Base); + } else + BaseOffset = BLayout.getVBaseClassOffset(Base); + llvm::Constant *subvtbl = vtbl; + const CXXRecordDecl *subVtblClass = VtblClass; + if ((Base->getNumVBases() || BaseMorallyVirtual) + && !NonVirtualPrimaryBase) { + llvm::Constant *init; + if (BaseMorallyVirtual || VtblClass == Class) + init = BuildVtablePtr(vtbl, VtblClass, Base, BaseOffset); + else { + init = getCtorVtable(BaseSubobject(Base, BaseOffset)); + + subvtbl = init; + subVtblClass = Base; + + init = BuildVtablePtr(init, Class, Base, BaseOffset); + } + + Inits.push_back(init); + } + + if (i->isVirtual()) + SeenVBasesInSecondary.insert(Base); + + Secondary(Base, subvtbl, subVtblClass, BaseOffset, BaseMorallyVirtual); + } + } + + /// BuiltVTT - Add the VTT to Inits. Offset is the offset in bits to the + /// currnet object we're working on. + void BuildVTT(const CXXRecordDecl *RD, uint64_t Offset, bool MorallyVirtual) { + // Itanium C++ ABI 2.6.2: + // An array of virtual table addresses, called the VTT, is declared for + // each class type that has indirect or direct virtual base classes. + if (RD->getNumVBases() == 0) + return; + + // Remember the sub-VTT index. + SubVTTIndicies[RD] = Inits.size(); + + llvm::Constant *Vtable; + const CXXRecordDecl *VtableClass; + + // First comes the primary virtual table pointer... + if (MorallyVirtual) { + Vtable = ClassVtbl; + VtableClass = Class; + } else { + Vtable = getCtorVtable(BaseSubobject(RD, Offset)); + VtableClass = RD; + } + + llvm::Constant *Init = BuildVtablePtr(Vtable, VtableClass, RD, Offset); + Inits.push_back(Init); + + // then the secondary VTTs.... + SecondaryVTTs(RD, Offset, MorallyVirtual); + + // Make sure to clear the set of seen virtual bases. + SeenVBasesInSecondary.clear(); + + // and last the secondary vtable pointers. + Secondary(RD, Vtable, VtableClass, Offset, MorallyVirtual); + } + + /// SecondaryVTTs - Add the secondary VTTs to Inits. The secondary VTTs are + /// built from each direct non-virtual proper base that requires a VTT in + /// declaration order. + void SecondaryVTTs(const CXXRecordDecl *RD, uint64_t Offset=0, + bool MorallyVirtual=false) { + for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), + e = RD->bases_end(); i != e; ++i) { + const CXXRecordDecl *Base = + cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); + if (i->isVirtual()) + continue; + const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); + uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(Base); + + BuildVTT(Base, BaseOffset, MorallyVirtual); + } + } + + /// VirtualVTTs - Add the VTT for each proper virtual base in inheritance + /// graph preorder. + void VirtualVTTs(const CXXRecordDecl *RD) { + for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), + e = RD->bases_end(); i != e; ++i) { + const CXXRecordDecl *Base = + cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); + if (i->isVirtual() && !SeenVBase.count(Base)) { + SeenVBase.insert(Base); + uint64_t BaseOffset = BLayout.getVBaseClassOffset(Base); + BuildVTT(Base, BaseOffset, false); + } + VirtualVTTs(Base); + } + } + +public: + VTTBuilder(std::vector<llvm::Constant *> &inits, const CXXRecordDecl *c, + CodeGenModule &cgm, bool GenerateDefinition) + : Inits(inits), Class(c), CGM(cgm), + BLayout(cgm.getContext().getASTRecordLayout(c)), + AddressPoints(*cgm.getVtableInfo().AddressPoints[c]), + VMContext(cgm.getModule().getContext()), + GenerateDefinition(GenerateDefinition) { + + // First comes the primary virtual table pointer for the complete class... + ClassVtbl = GenerateDefinition ? CGM.getVtableInfo().getVtable(Class) : 0; + + llvm::Constant *Init = BuildVtablePtr(ClassVtbl, Class, Class, 0); + Inits.push_back(Init); + + // then the secondary VTTs... + SecondaryVTTs(Class); + + // Make sure to clear the set of seen virtual bases. + SeenVBasesInSecondary.clear(); + + // then the secondary vtable pointers... + Secondary(Class, ClassVtbl, Class); + + // and last, the virtual VTTs. + VirtualVTTs(Class); + } + + llvm::DenseMap<const CXXRecordDecl *, uint64_t> &getSubVTTIndicies() { + return SubVTTIndicies; + } +}; +} + +llvm::GlobalVariable * +CGVtableInfo::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; + + llvm::SmallString<256> OutName; + CGM.getMangleContext().mangleCXXVTT(RD, OutName); + llvm::StringRef Name = OutName.str(); + + D1(printf("vtt %s\n", RD->getNameAsCString())); + + llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name); + if (GV == 0 || GV->isDeclaration()) { + const llvm::Type *Int8PtrTy = + llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); + + std::vector<llvm::Constant *> inits; + VTTBuilder b(inits, RD, CGM, GenerateDefinition); + + const llvm::ArrayType *Type = llvm::ArrayType::get(Int8PtrTy, inits.size()); + llvm::Constant *Init = 0; + if (GenerateDefinition) + Init = llvm::ConstantArray::get(Type, inits); + + llvm::GlobalVariable *OldGV = GV; + GV = new llvm::GlobalVariable(CGM.getModule(), Type, /*isConstant=*/true, + Linkage, Init, Name); + CGM.setGlobalVisibility(GV, RD); + + if (OldGV) { + GV->takeName(OldGV); + llvm::Constant *NewPtr = + llvm::ConstantExpr::getBitCast(GV, OldGV->getType()); + OldGV->replaceAllUsesWith(NewPtr); + OldGV->eraseFromParent(); + } + } + + return GV; +} + +CGVtableInfo::CtorVtableInfo +CGVtableInfo::getCtorVtable(const CXXRecordDecl *RD, + const BaseSubobject &Base) { + CtorVtableInfo Info; + + Info.Vtable = GenerateVtable(llvm::GlobalValue::InternalLinkage, + /*GenerateDefinition=*/true, + RD, Base.getBase(), Base.getBaseOffset(), + Info.AddressPoints); + return Info; +} + +llvm::GlobalVariable *CGVtableInfo::getVTT(const CXXRecordDecl *RD) { + return GenerateVTT(llvm::GlobalValue::ExternalLinkage, + /*GenerateDefinition=*/false, RD); + +} + + +bool CGVtableInfo::needsVTTParameter(GlobalDecl GD) { + const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); + + // We don't have any virtual bases, just return early. + if (!MD->getParent()->getNumVBases()) + return false; + + // Check if we have a base constructor. + if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base) + return true; + + // Check if we have a base destructor. + if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base) + return true; + + return false; +} + +uint64_t CGVtableInfo::getSubVTTIndex(const CXXRecordDecl *RD, + const CXXRecordDecl *Base) { + ClassPairTy ClassPair(RD, Base); + + SubVTTIndiciesTy::iterator I = + SubVTTIndicies.find(ClassPair); + if (I != SubVTTIndicies.end()) + return I->second; + + std::vector<llvm::Constant *> inits; + VTTBuilder Builder(inits, RD, CGM, /*GenerateDefinition=*/false); + + for (llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I = + Builder.getSubVTTIndicies().begin(), + E = Builder.getSubVTTIndicies().end(); I != E; ++I) { + // Insert all indices. + ClassPairTy ClassPair(RD, I->first); + + SubVTTIndicies.insert(std::make_pair(ClassPair, I->second)); + } + + I = SubVTTIndicies.find(ClassPair); + assert(I != SubVTTIndicies.end() && "Did not find index!"); + + return I->second; +} diff --git a/clang/lib/CodeGen/CGVtable.cpp b/clang/lib/CodeGen/CGVtable.cpp index b2fb8662fe6..1da10010f5d 100644 --- a/clang/lib/CodeGen/CGVtable.cpp +++ b/clang/lib/CodeGen/CGVtable.cpp @@ -1205,321 +1205,6 @@ CGVtableInfo::GenerateVtable(llvm::GlobalVariable::LinkageTypes Linkage, return GV; } -namespace { -class VTTBuilder { - /// Inits - The list of values built for the VTT. - std::vector<llvm::Constant *> &Inits; - /// Class - The most derived class that this vtable is being built for. - const CXXRecordDecl *Class; - CodeGenModule &CGM; // Per-module state. - llvm::SmallSet<const CXXRecordDecl *, 32> SeenVBase; - /// BLayout - Layout for the most derived class that this vtable is being - /// built for. - const ASTRecordLayout &BLayout; - CGVtableInfo::AddrMap_t &AddressPoints; - // vtbl - A pointer to the vtable for Class. - llvm::Constant *ClassVtbl; - llvm::LLVMContext &VMContext; - - /// SeenVBasesInSecondary - The seen virtual bases when building the - /// secondary virtual pointers. - llvm::SmallPtrSet<const CXXRecordDecl *, 32> SeenVBasesInSecondary; - - llvm::DenseMap<const CXXRecordDecl *, uint64_t> SubVTTIndicies; - - bool GenerateDefinition; - - llvm::DenseMap<BaseSubobject, llvm::Constant *> CtorVtables; - llvm::DenseMap<std::pair<const CXXRecordDecl *, BaseSubobject>, uint64_t> - CtorVtableAddressPoints; - - llvm::Constant *getCtorVtable(const BaseSubobject &Base) { - if (!GenerateDefinition) - return 0; - - llvm::Constant *&CtorVtable = CtorVtables[Base]; - if (!CtorVtable) { - // Build the vtable. - CGVtableInfo::CtorVtableInfo Info - = CGM.getVtableInfo().getCtorVtable(Class, Base); - - CtorVtable = Info.Vtable; - - // Add the address points for this base. - for (CGVtableInfo::AddressPointsMapTy::const_iterator I = - Info.AddressPoints.begin(), E = Info.AddressPoints.end(); - I != E; ++I) { - uint64_t &AddressPoint = - CtorVtableAddressPoints[std::make_pair(Base.getBase(), I->first)]; - - // Check if we already have the address points for this base. - if (AddressPoint) - break; - - // Otherwise, insert it. - AddressPoint = I->second; - } - } - - return CtorVtable; - } - - - /// BuildVtablePtr - Build up a referene to the given secondary vtable - llvm::Constant *BuildVtablePtr(llvm::Constant *Vtable, - const CXXRecordDecl *VtableClass, - const CXXRecordDecl *RD, - uint64_t Offset) { - if (!GenerateDefinition) - return 0; - - uint64_t AddressPoint; - - if (VtableClass != Class) { - // We have a ctor vtable, look for the address point in the ctor vtable - // address points. - AddressPoint = - CtorVtableAddressPoints[std::make_pair(VtableClass, - BaseSubobject(RD, Offset))]; - } else { - AddressPoint = - (*AddressPoints[VtableClass])[std::make_pair(RD, Offset)]; - } - - // FIXME: We can never have 0 address point. Do this for now so gepping - // retains the same structure. Later we'll just assert. - if (AddressPoint == 0) - AddressPoint = 1; - D1(printf("XXX address point for %s in %s layout %s at offset %d was %d\n", - RD->getNameAsCString(), VtblClass->getNameAsCString(), - Class->getNameAsCString(), (int)Offset, (int)AddressPoint)); - - llvm::Value *Idxs[] = { - llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), 0), - llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), AddressPoint) - }; - - llvm::Constant *Init = - llvm::ConstantExpr::getInBoundsGetElementPtr(Vtable, Idxs, 2); - - const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext); - return llvm::ConstantExpr::getBitCast(Init, Int8PtrTy); - } - - /// Secondary - Add the secondary vtable pointers to Inits. Offset is the - /// current offset in bits to the object we're working on. - void Secondary(const CXXRecordDecl *RD, llvm::Constant *vtbl, - const CXXRecordDecl *VtblClass, uint64_t Offset=0, - bool MorallyVirtual=false) { - if (RD->getNumVBases() == 0 && ! MorallyVirtual) - return; - - for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), - e = RD->bases_end(); i != e; ++i) { - const CXXRecordDecl *Base = - cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); - - // We only want to visit each virtual base once. - if (i->isVirtual() && SeenVBasesInSecondary.count(Base)) - continue; - - // Itanium C++ ABI 2.6.2: - // Secondary virtual pointers are present for all bases with either - // virtual bases or virtual function declarations overridden along a - // virtual path. - // - // If the base class is not dynamic, we don't want to add it, nor any - // of its base classes. - if (!Base->isDynamicClass()) - continue; - - const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); - const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); - const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual(); - bool NonVirtualPrimaryBase; - NonVirtualPrimaryBase = !PrimaryBaseWasVirtual && Base == PrimaryBase; - bool BaseMorallyVirtual = MorallyVirtual | i->isVirtual(); - uint64_t BaseOffset; - if (!i->isVirtual()) { - const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); - BaseOffset = Offset + Layout.getBaseClassOffset(Base); - } else - BaseOffset = BLayout.getVBaseClassOffset(Base); - llvm::Constant *subvtbl = vtbl; - const CXXRecordDecl *subVtblClass = VtblClass; - if ((Base->getNumVBases() || BaseMorallyVirtual) - && !NonVirtualPrimaryBase) { - llvm::Constant *init; - if (BaseMorallyVirtual || VtblClass == Class) - init = BuildVtablePtr(vtbl, VtblClass, Base, BaseOffset); - else { - init = getCtorVtable(BaseSubobject(Base, BaseOffset)); - - subvtbl = init; - subVtblClass = Base; - - init = BuildVtablePtr(init, Class, Base, BaseOffset); - } - - Inits.push_back(init); - } - - if (i->isVirtual()) - SeenVBasesInSecondary.insert(Base); - - Secondary(Base, subvtbl, subVtblClass, BaseOffset, BaseMorallyVirtual); - } - } - - /// BuiltVTT - Add the VTT to Inits. Offset is the offset in bits to the - /// currnet object we're working on. - void BuildVTT(const CXXRecordDecl *RD, uint64_t Offset, bool MorallyVirtual) { - // Itanium C++ ABI 2.6.2: - // An array of virtual table addresses, called the VTT, is declared for - // each class type that has indirect or direct virtual base classes. - if (RD->getNumVBases() == 0) - return; - - // Remember the sub-VTT index. - SubVTTIndicies[RD] = Inits.size(); - - llvm::Constant *Vtable; - const CXXRecordDecl *VtableClass; - - // First comes the primary virtual table pointer... - if (MorallyVirtual) { - Vtable = ClassVtbl; - VtableClass = Class; - } else { - Vtable = getCtorVtable(BaseSubobject(RD, Offset)); - VtableClass = RD; - } - - llvm::Constant *Init = BuildVtablePtr(Vtable, VtableClass, RD, Offset); - Inits.push_back(Init); - - // then the secondary VTTs.... - SecondaryVTTs(RD, Offset, MorallyVirtual); - - // Make sure to clear the set of seen virtual bases. - SeenVBasesInSecondary.clear(); - - // and last the secondary vtable pointers. - Secondary(RD, Vtable, VtableClass, Offset, MorallyVirtual); - } - - /// SecondaryVTTs - Add the secondary VTTs to Inits. The secondary VTTs are - /// built from each direct non-virtual proper base that requires a VTT in - /// declaration order. - void SecondaryVTTs(const CXXRecordDecl *RD, uint64_t Offset=0, - bool MorallyVirtual=false) { - for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), - e = RD->bases_end(); i != e; ++i) { - const CXXRecordDecl *Base = - cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); - if (i->isVirtual()) - continue; - const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); - uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(Base); - - BuildVTT(Base, BaseOffset, MorallyVirtual); - } - } - - /// VirtualVTTs - Add the VTT for each proper virtual base in inheritance - /// graph preorder. - void VirtualVTTs(const CXXRecordDecl *RD) { - for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), - e = RD->bases_end(); i != e; ++i) { - const CXXRecordDecl *Base = - cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); - if (i->isVirtual() && !SeenVBase.count(Base)) { - SeenVBase.insert(Base); - uint64_t BaseOffset = BLayout.getVBaseClassOffset(Base); - BuildVTT(Base, BaseOffset, false); - } - VirtualVTTs(Base); - } - } - -public: - VTTBuilder(std::vector<llvm::Constant *> &inits, const CXXRecordDecl *c, - CodeGenModule &cgm, bool GenerateDefinition) - : Inits(inits), Class(c), CGM(cgm), - BLayout(cgm.getContext().getASTRecordLayout(c)), - AddressPoints(*cgm.getVtableInfo().AddressPoints[c]), - VMContext(cgm.getModule().getContext()), - GenerateDefinition(GenerateDefinition) { - - // First comes the primary virtual table pointer for the complete class... - ClassVtbl = GenerateDefinition ? CGM.getVtableInfo().getVtable(Class) : 0; - - llvm::Constant *Init = BuildVtablePtr(ClassVtbl, Class, Class, 0); - Inits.push_back(Init); - - // then the secondary VTTs... - SecondaryVTTs(Class); - - // Make sure to clear the set of seen virtual bases. - SeenVBasesInSecondary.clear(); - - // then the secondary vtable pointers... - Secondary(Class, ClassVtbl, Class); - - // and last, the virtual VTTs. - VirtualVTTs(Class); - } - - llvm::DenseMap<const CXXRecordDecl *, uint64_t> &getSubVTTIndicies() { - return SubVTTIndicies; - } -}; -} - -llvm::GlobalVariable * -CGVtableInfo::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; - - llvm::SmallString<256> OutName; - CGM.getMangleContext().mangleCXXVTT(RD, OutName); - llvm::StringRef Name = OutName.str(); - - D1(printf("vtt %s\n", RD->getNameAsCString())); - - llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name); - if (GV == 0 || GV->isDeclaration()) { - const llvm::Type *Int8PtrTy = - llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); - - std::vector<llvm::Constant *> inits; - VTTBuilder b(inits, RD, CGM, GenerateDefinition); - - const llvm::ArrayType *Type = llvm::ArrayType::get(Int8PtrTy, inits.size()); - llvm::Constant *Init = 0; - if (GenerateDefinition) - Init = llvm::ConstantArray::get(Type, inits); - - llvm::GlobalVariable *OldGV = GV; - GV = new llvm::GlobalVariable(CGM.getModule(), Type, /*isConstant=*/true, - Linkage, Init, Name); - CGM.setGlobalVisibility(GV, RD); - - if (OldGV) { - GV->takeName(OldGV); - llvm::Constant *NewPtr = - llvm::ConstantExpr::getBitCast(GV, OldGV->getType()); - OldGV->replaceAllUsesWith(NewPtr); - OldGV->eraseFromParent(); - } - } - - return GV; -} - void CGVtableInfo::GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage, const CXXRecordDecl *RD) { llvm::GlobalVariable *&Vtable = Vtables[RD]; @@ -1547,25 +1232,6 @@ llvm::GlobalVariable *CGVtableInfo::getVtable(const CXXRecordDecl *RD) { return Vtable; } -CGVtableInfo::CtorVtableInfo -CGVtableInfo::getCtorVtable(const CXXRecordDecl *RD, - const BaseSubobject &Base) { - CtorVtableInfo Info; - - Info.Vtable = GenerateVtable(llvm::GlobalValue::InternalLinkage, - /*GenerateDefinition=*/true, - RD, Base.getBase(), Base.getBaseOffset(), - Info.AddressPoints); - return Info; -} - -llvm::GlobalVariable *CGVtableInfo::getVTT(const CXXRecordDecl *RD) { - return GenerateVTT(llvm::GlobalValue::ExternalLinkage, - /*GenerateDefinition=*/false, RD); - -} - - void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) { const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); const CXXRecordDecl *RD = MD->getParent(); @@ -1599,47 +1265,3 @@ void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) { } } -bool CGVtableInfo::needsVTTParameter(GlobalDecl GD) { - const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); - - // We don't have any virtual bases, just return early. - if (!MD->getParent()->getNumVBases()) - return false; - - // Check if we have a base constructor. - if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base) - return true; - - // Check if we have a base destructor. - if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base) - return true; - - return false; -} - -uint64_t CGVtableInfo::getSubVTTIndex(const CXXRecordDecl *RD, - const CXXRecordDecl *Base) { - ClassPairTy ClassPair(RD, Base); - - SubVTTIndiciesTy::iterator I = - SubVTTIndicies.find(ClassPair); - if (I != SubVTTIndicies.end()) - return I->second; - - std::vector<llvm::Constant *> inits; - VTTBuilder Builder(inits, RD, CGM, /*GenerateDefinition=*/false); - - for (llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I = - Builder.getSubVTTIndicies().begin(), - E = Builder.getSubVTTIndicies().end(); I != E; ++I) { - // Insert all indices. - ClassPairTy ClassPair(RD, I->first); - - SubVTTIndicies.insert(std::make_pair(ClassPair, I->second)); - } - - I = SubVTTIndicies.find(ClassPair); - assert(I != SubVTTIndicies.end() && "Did not find index!"); - - return I->second; -} diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt index 45469d39e4a..e72a1d9e094 100644 --- a/clang/lib/CodeGen/CMakeLists.txt +++ b/clang/lib/CodeGen/CMakeLists.txt @@ -24,6 +24,7 @@ add_clang_library(clangCodeGen CGStmt.cpp CGTemporaries.cpp CGVtable.cpp + CGVTT.cpp CodeGenFunction.cpp CodeGenModule.cpp CodeGenTypes.cpp |