From cbcd4e5d9d4c6148d47c6c05038b295c1eb037b2 Mon Sep 17 00:00:00 2001 From: Mike Stump Date: Sat, 14 Nov 2009 23:32:21 +0000 Subject: [PATCH] Finisgh off rest of class_type_info rtti generation. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@88823 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGRtti.cpp | 128 ++++++++++++++++++++++++++++++++---- lib/CodeGen/CGVtable.cpp | 3 +- lib/CodeGen/CodeGenModule.h | 3 + 3 files changed, 120 insertions(+), 14 deletions(-) diff --git a/lib/CodeGen/CGRtti.cpp b/lib/CodeGen/CGRtti.cpp index 3d76bcd965..11a8ea7e7c 100644 --- a/lib/CodeGen/CGRtti.cpp +++ b/lib/CodeGen/CGRtti.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "CodeGenModule.h" +#include "clang/AST/RecordLayout.h" using namespace clang; using namespace CodeGen; @@ -24,9 +25,9 @@ public: : CGM(cgm), VMContext(cgm.getModule().getContext()), Int8PtrTy(llvm::Type::getInt8PtrTy(VMContext)) { } - llvm::Constant *Buildclass_type_infoDesc() { - // Build a descriptor for class_type_info. - llvm::StringRef Name = "_ZTVN10__cxxabiv121__vmi_class_type_infoE"; + /// BuildVtableRef - Build a reference to a vtable. + llvm::Constant *BuildVtableRef(const char *Name) { + // Build a descriptor for Name llvm::Constant *GV = CGM.getModule().getGlobalVariable(Name); if (GV) GV = llvm::ConstantExpr::getBitCast(GV, @@ -36,25 +37,25 @@ public: linktype = llvm::GlobalValue::ExternalLinkage; GV = new llvm::GlobalVariable(CGM.getModule(), Int8PtrTy, true, linktype, 0, Name); - } + } llvm::Constant *C; C = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), 2); C = llvm::ConstantExpr::getInBoundsGetElementPtr(GV, &C, 1); return llvm::ConstantExpr::getBitCast(C, Int8PtrTy); } - + llvm::Constant *BuildName(const CXXRecordDecl *RD) { llvm::SmallString<256> OutName; llvm::raw_svector_ostream Out(OutName); mangleCXXRttiName(CGM.getMangleContext(), CGM.getContext().getTagDeclType(RD), Out); - + llvm::GlobalVariable::LinkageTypes linktype; linktype = llvm::GlobalValue::LinkOnceODRLinkage; llvm::Constant *C; C = llvm::ConstantArray::get(VMContext, Out.str().substr(4)); - + llvm::Constant *s = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true, linktype, C, Out.str()); @@ -62,8 +63,44 @@ public: return s; }; + /// - BuildFlags - Build a psABI __flags value for __vmi_class_type_info. + llvm::Constant *BuildFlags(int f) { + return llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), f); + } + + /// BuildBaseCount - Build a psABI __base_count value for + /// __vmi_class_type_info. + llvm::Constant *BuildBaseCount(unsigned c) { + return llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), c); + } + + llvm::Constant *Buildclass_type_infoRef(const CXXRecordDecl *RD) { + const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext); + llvm::Constant *C; + + if (!CGM.getContext().getLangOptions().Rtti) + return llvm::Constant::getNullValue(Int8PtrTy); + + llvm::SmallString<256> OutName; + llvm::raw_svector_ostream Out(OutName); + mangleCXXRtti(CGM.getMangleContext(), CGM.getContext().getTagDeclType(RD), + Out); + + C = CGM.getModule().getGlobalVariable(Out.str()); + if (C) + return llvm::ConstantExpr::getBitCast(C, Int8PtrTy); + + llvm::GlobalVariable::LinkageTypes linktype; + linktype = llvm::GlobalValue::ExternalLinkage;; + + C = new llvm::GlobalVariable(CGM.getModule(), Int8PtrTy, true, linktype, + 0, Out.str()); + return llvm::ConstantExpr::getBitCast(C, Int8PtrTy); + } + llvm::Constant *Buildclass_type_info(const CXXRecordDecl *RD) { const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext); + llvm::Constant *C; if (!CGM.getContext().getLangOptions().Rtti) return llvm::Constant::getNullValue(Int8PtrTy); @@ -72,29 +109,94 @@ public: llvm::raw_svector_ostream Out(OutName); mangleCXXRtti(CGM.getMangleContext(), CGM.getContext().getTagDeclType(RD), Out); - + + llvm::GlobalVariable *GV; + GV = CGM.getModule().getGlobalVariable(Out.str()); + if (GV && !GV->isDeclaration()) + return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy); + llvm::GlobalVariable::LinkageTypes linktype; linktype = llvm::GlobalValue::LinkOnceODRLinkage; std::vector info; - info.push_back(Buildclass_type_infoDesc()); + if (RD->getNumBases() == 0) + C = BuildVtableRef("_ZTVN10__cxxabiv117__class_type_infoE"); + // FIXME: Add si_class_type_info optimization + else + C = BuildVtableRef("_ZTVN10__cxxabiv121__vmi_class_type_infoE"); + info.push_back(C); info.push_back(BuildName(RD)); - // FIXME: rest of rtti bits + // If we have no bases, there are no more fields. + if (RD->getNumBases()) { - llvm::Constant *C; + // FIXME: Calculate is_diamond and non-diamond repeated inheritance, 3 is + // conservative. + info.push_back(BuildFlags(3)); + info.push_back(BuildBaseCount(RD->getNumBases())); + + const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); + for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), + e = RD->bases_end(); i != e; ++i) { + const CXXRecordDecl *Base = + cast(i->getType()->getAs()->getDecl()); + info.push_back(CGM.GenerateRtti(Base)); + int64_t offset; + if (!i->isVirtual()) + offset = Layout.getBaseClassOffset(Base); + else + offset = CGM.getVtableInfo().getVirtualBaseOffsetIndex(RD, Base); + offset <<= 8; + // Now set the flags. + offset += i->isVirtual() ? 1 : 0;; + offset += i->getAccessSpecifier() == AS_public ? 2 : 0; + const llvm::Type *LongTy = + CGM.getTypes().ConvertType(CGM.getContext().LongTy); + C = llvm::ConstantInt::get(LongTy, offset); + info.push_back(C); + } + } + + std::vector Types(info.size()); + for (unsigned i=0; igetType(); + // llvm::StructType *Ty = llvm::StructType::get(VMContext, Types, true); + C = llvm::ConstantStruct::get(VMContext, &info[0], info.size(), false); + + if (GV == 0) + GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true, linktype, + C, Out.str()); + else { + llvm::GlobalVariable *OGV = GV; + GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true, linktype, + C, Out.str()); + GV->takeName(OGV); + llvm::Constant *NewPtr = llvm::ConstantExpr::getBitCast(GV, OGV->getType()); + OGV->replaceAllUsesWith(NewPtr); + OGV->eraseFromParent(); + } + return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy); + +#if 0 llvm::ArrayType *type = llvm::ArrayType::get(Int8PtrTy, info.size()); C = llvm::ConstantArray::get(type, info); - llvm::Constant *Rtti = + llvm::Constant *Rtti = new llvm::GlobalVariable(CGM.getModule(), type, true, linktype, C, Out.str()); Rtti = llvm::ConstantExpr::getBitCast(Rtti, Int8PtrTy); return Rtti; +#endif } }; +llvm::Constant *CodeGenModule::GenerateRttiRef(const CXXRecordDecl *RD) { + RttiBuilder b(*this); + + return b.Buildclass_type_infoRef(RD); +} + llvm::Constant *CodeGenModule::GenerateRtti(const CXXRecordDecl *RD) { RttiBuilder b(*this); - return b.Buildclass_type_info(RD); + return b.Buildclass_type_info(RD); } diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 3c718b5fe3..efca4f2fbe 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -80,7 +80,7 @@ public: const CXXRecordDecl *l, uint64_t lo, CodeGenModule &cgm) : methods(meth), Class(c), LayoutClass(l), LayoutOffset(lo), BLayout(cgm.getContext().getASTRecordLayout(l)), - rtti(cgm.GenerateRtti(c)), VMContext(cgm.getModule().getContext()), + rtti(cgm.GenerateRttiRef(c)), VMContext(cgm.getModule().getContext()), CGM(cgm), AddressPoints(*new llvm::DenseMap), Extern(true), LLVMPointerWidth(cgm.getContext().Target.getPointerWidth(0)) { @@ -1022,6 +1022,7 @@ llvm::Constant *CGVtableInfo::getVtable(const CXXRecordDecl *RD) { if (vtbl) return vtbl; vtbl = CGM.GenerateVtable(RD, RD); + CGM.GenerateRtti(RD); CGM.GenerateVTT(RD); return vtbl; } diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 44d24337df..85e4d3d073 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -226,6 +226,9 @@ public: /// GenerateRtti - Generate the rtti information for the given type. llvm::Constant *GenerateRtti(const CXXRecordDecl *RD); + /// GenerateRttiRef - Generate a reference to the rtti information for the + /// given type. + llvm::Constant *GenerateRttiRef(const CXXRecordDecl *RD); /// BuildThunk - Build a thunk for the given method llvm::Constant *BuildThunk(const CXXMethodDecl *MD, bool Extern, int64_t nv, -- 2.40.0