diff options
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGCXX.cpp | 4 | ||||
-rw-r--r-- | lib/CodeGen/CGDecl.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/CGRecordLayoutBuilder.cpp | 5 | ||||
-rw-r--r-- | lib/CodeGen/CGRtti.cpp | 107 | ||||
-rw-r--r-- | lib/CodeGen/CGVtable.cpp | 111 | ||||
-rw-r--r-- | lib/CodeGen/CGVtable.h | 4 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 10 |
7 files changed, 182 insertions, 60 deletions
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 8f5cff4efafe3..b1d30a68bbb71 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -603,8 +603,8 @@ CodeGenFunction::EmitCXXAggrDestructorCall(const CXXDestructorDecl *D, EmitBlock(AfterFor, true); } -/// GenerateCXXAggrDestructorHelper - Generates a helper function which when invoked, -/// calls the default destructor on array elements in reverse order of +/// GenerateCXXAggrDestructorHelper - Generates a helper function which when +/// invoked, calls the default destructor on array elements in reverse order of /// construction. llvm::Constant * CodeGenFunction::GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D, diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 1d2040bae203d..349ede51c63b0 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -611,4 +611,3 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) { DI->EmitDeclareOfArgVariable(&D, DeclPtr, Builder); } } - diff --git a/lib/CodeGen/CGRecordLayoutBuilder.cpp b/lib/CodeGen/CGRecordLayoutBuilder.cpp index 8e0864b8dd83d..a63c8325ffa72 100644 --- a/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -345,6 +345,11 @@ static const CXXMethodDecl *GetKeyFunction(const RecordDecl *D) { if (MD->isPure()) continue; + // FIXME: This doesn't work. If we have an out of line body, that body will + // set the MD to have a body, what we want to know is, was the body present + // inside the declaration of the class. For now, we just avoid the problem + // by pretending there is no key function. + return 0; if (MD->getBody()) continue; diff --git a/lib/CodeGen/CGRtti.cpp b/lib/CodeGen/CGRtti.cpp index e18843d5cf3f1..79d866427f0b8 100644 --- a/lib/CodeGen/CGRtti.cpp +++ b/lib/CodeGen/CGRtti.cpp @@ -47,21 +47,35 @@ public: return llvm::ConstantExpr::getBitCast(C, Int8PtrTy); } - llvm::Constant *BuildName(QualType Ty, bool Hidden) { + llvm::Constant *BuildName(QualType Ty, bool Hidden, bool Extern) { llvm::SmallString<256> OutName; llvm::raw_svector_ostream Out(OutName); mangleCXXRttiName(CGM.getMangleContext(), Ty, Out); + llvm::StringRef Name = Out.str(); llvm::GlobalVariable::LinkageTypes linktype; linktype = llvm::GlobalValue::LinkOnceODRLinkage; + if (!Extern) + linktype = llvm::GlobalValue::InternalLinkage; + + llvm::GlobalVariable *GV; + GV = CGM.getModule().getGlobalVariable(Name); + if (GV && !GV->isDeclaration()) + return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy); llvm::Constant *C; - C = llvm::ConstantArray::get(VMContext, Out.str().substr(4)); + C = llvm::ConstantArray::get(VMContext, Name.substr(4)); - llvm::GlobalVariable * GV = new llvm::GlobalVariable(CGM.getModule(), - C->getType(), - true, linktype, C, - Out.str()); + llvm::GlobalVariable *OGV = GV; + GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true, linktype, + C, Name); + if (OGV) { + GV->takeName(OGV); + llvm::Constant *NewPtr = llvm::ConstantExpr::getBitCast(GV, + OGV->getType()); + OGV->replaceAllUsesWith(NewPtr); + OGV->eraseFromParent(); + } if (Hidden) GV->setVisibility(llvm::GlobalVariable::HiddenVisibility); return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy); @@ -87,8 +101,9 @@ public: llvm::SmallString<256> OutName; llvm::raw_svector_ostream Out(OutName); mangleCXXRtti(CGM.getMangleContext(), Ty, Out); + llvm::StringRef Name = Out.str(); - C = CGM.getModule().getGlobalVariable(Out.str()); + C = CGM.getModule().getGlobalVariable(Name); if (C) return llvm::ConstantExpr::getBitCast(C, Int8PtrTy); @@ -96,7 +111,7 @@ public: linktype = llvm::GlobalValue::ExternalLinkage;; C = new llvm::GlobalVariable(CGM.getModule(), Int8PtrTy, true, linktype, - 0, Out.str()); + 0, Name); return llvm::ConstantExpr::getBitCast(C, Int8PtrTy); } @@ -147,20 +162,19 @@ public: llvm::Constant *finish(std::vector<llvm::Constant *> &info, llvm::GlobalVariable *GV, - llvm::StringRef Name, bool Hidden) { + llvm::StringRef Name, bool Hidden, bool Extern) { llvm::GlobalVariable::LinkageTypes linktype; linktype = llvm::GlobalValue::LinkOnceODRLinkage; + if (!Extern) + linktype = llvm::GlobalValue::InternalLinkage; llvm::Constant *C; C = llvm::ConstantStruct::get(VMContext, &info[0], info.size(), false); - if (GV == 0) - GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true, - linktype, C, Name); - else { - llvm::GlobalVariable *OGV = GV; - GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true, - linktype, C, Name); + llvm::GlobalVariable *OGV = GV; + GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true, linktype, + C, Name); + if (OGV) { GV->takeName(OGV); llvm::Constant *NewPtr = llvm::ConstantExpr::getBitCast(GV, OGV->getType()); @@ -183,15 +197,17 @@ public: llvm::raw_svector_ostream Out(OutName); mangleCXXRtti(CGM.getMangleContext(), CGM.getContext().getTagDeclType(RD), Out); + llvm::StringRef Name = Out.str(); llvm::GlobalVariable *GV; - GV = CGM.getModule().getGlobalVariable(Out.str()); + GV = CGM.getModule().getGlobalVariable(Name); if (GV && !GV->isDeclaration()) return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy); std::vector<llvm::Constant *> info; bool Hidden = CGM.getDeclVisibilityMode(RD) == LangOptions::Hidden; + bool Extern = !RD->isInAnonymousNamespace(); bool simple = false; if (RD->getNumBases() == 0) @@ -202,7 +218,8 @@ public: } else C = BuildVtableRef("_ZTVN10__cxxabiv121__vmi_class_type_infoE"); info.push_back(C); - info.push_back(BuildName(CGM.getContext().getTagDeclType(RD), Hidden)); + info.push_back(BuildName(CGM.getContext().getTagDeclType(RD), Hidden, + Extern)); // If we have no bases, there are no more fields. if (RD->getNumBases()) { @@ -235,7 +252,7 @@ public: } } - return finish(info, GV, Out.str(), Hidden); + return finish(info, GV, Name, Hidden, Extern); } /// - BuildFlags - Build a __flags value for __pbase_type_info. @@ -250,23 +267,49 @@ public: return BuildType(Ty); } + bool DecideExtern(QualType Ty) { + // For this type, see if all components are never in an anonymous namespace. + if (const MemberPointerType *MPT = Ty->getAs<MemberPointerType>()) + return (DecideExtern(MPT->getPointeeType()) + && DecideExtern(QualType(MPT->getClass(), 0))); + if (const PointerType *PT = Ty->getAs<PointerType>()) + return DecideExtern(PT->getPointeeType()); + if (const RecordType *RT = Ty->getAs<RecordType>()) + if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) + return !RD->isInAnonymousNamespace(); + return true; + } + + bool DecideHidden(QualType Ty) { + // For this type, see if all components are never hidden. + if (const MemberPointerType *MPT = Ty->getAs<MemberPointerType>()) + return (DecideHidden(MPT->getPointeeType()) + && DecideHidden(QualType(MPT->getClass(), 0))); + if (const PointerType *PT = Ty->getAs<PointerType>()) + return DecideHidden(PT->getPointeeType()); + if (const RecordType *RT = Ty->getAs<RecordType>()) + if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) + return CGM.getDeclVisibilityMode(RD) == LangOptions::Hidden; + return false; + } + llvm::Constant *BuildPointerType(QualType Ty) { llvm::Constant *C; llvm::SmallString<256> OutName; llvm::raw_svector_ostream Out(OutName); mangleCXXRtti(CGM.getMangleContext(), Ty, Out); + llvm::StringRef Name = Out.str(); llvm::GlobalVariable *GV; - GV = CGM.getModule().getGlobalVariable(Out.str()); + GV = CGM.getModule().getGlobalVariable(Name); if (GV && !GV->isDeclaration()) return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy); std::vector<llvm::Constant *> info; - // FIXME: pointer to hidden should be hidden, we should be able to - // grab a bit off the type for this. - bool Hidden = false; + bool Extern = DecideExtern(Ty); + bool Hidden = DecideHidden(Ty); QualType PTy = Ty->getPointeeType(); QualType BTy; @@ -282,7 +325,7 @@ public: else C = BuildVtableRef("_ZTVN10__cxxabiv119__pointer_type_infoE"); info.push_back(C); - info.push_back(BuildName(Ty, Hidden)); + info.push_back(BuildName(Ty, Hidden, Extern)); Qualifiers Q = PTy.getQualifiers(); PTy = CGM.getContext().getCanonicalType(PTy).getUnqualifiedType(); int flags = 0; @@ -300,7 +343,8 @@ public: if (PtrMem) info.push_back(BuildType2(BTy)); - return finish(info, GV, Out.str(), true); + // We always generate these as hidden, only the name isn't hidden. + return finish(info, GV, Name, true, Extern); } llvm::Constant *BuildSimpleType(QualType Ty, const char *vtbl) { @@ -309,23 +353,24 @@ public: llvm::SmallString<256> OutName; llvm::raw_svector_ostream Out(OutName); mangleCXXRtti(CGM.getMangleContext(), Ty, Out); + llvm::StringRef Name = Out.str(); llvm::GlobalVariable *GV; - GV = CGM.getModule().getGlobalVariable(Out.str()); + GV = CGM.getModule().getGlobalVariable(Name); if (GV && !GV->isDeclaration()) return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy); std::vector<llvm::Constant *> info; - // FIXME: pointer to hidden should be hidden, we should be able to - // grab a bit off the type for this. - bool Hidden = false; + bool Extern = DecideExtern(Ty); + bool Hidden = DecideHidden(Ty); C = BuildVtableRef(vtbl); info.push_back(C); - info.push_back(BuildName(Ty, Hidden)); + info.push_back(BuildName(Ty, Hidden, Extern)); - return finish(info, GV, Out.str(), true); + // We always generate these as hidden, only the name isn't hidden. + return finish(info, GV, Name, true, Extern); } llvm::Constant *BuildType(QualType Ty) { diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 4c97a9bdeebfb..9be1a3b22b337 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -69,7 +69,6 @@ private: llvm::DenseMap<CtorVtable_t, int64_t> &AddressPoints; typedef CXXRecordDecl::method_iterator method_iter; - // FIXME: Linkage should follow vtable const bool Extern; const uint32_t LLVMPointerWidth; Index_t extra; @@ -82,7 +81,7 @@ public: BLayout(cgm.getContext().getASTRecordLayout(l)), rtti(cgm.GenerateRttiRef(c)), VMContext(cgm.getModule().getContext()), CGM(cgm), AddressPoints(*new llvm::DenseMap<CtorVtable_t, int64_t>), - Extern(true), + Extern(!l->isInAnonymousNamespace()), LLVMPointerWidth(cgm.getContext().Target.getPointerWidth(0)) { Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0); @@ -788,37 +787,73 @@ llvm::Constant *CodeGenModule::GenerateVtable(const CXXRecordDecl *LayoutClass, mangleCXXCtorVtable(getMangleContext(), LayoutClass, Offset/8, RD, Out); else mangleCXXVtable(getMangleContext(), RD, Out); + llvm::StringRef Name = Out.str(); - llvm::GlobalVariable::LinkageTypes linktype; - linktype = llvm::GlobalValue::LinkOnceODRLinkage; std::vector<llvm::Constant *> methods; llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0); int64_t AddressPoint; - VtableBuilder b(methods, RD, LayoutClass, Offset, *this); + llvm::GlobalVariable *GV = getModule().getGlobalVariable(Name); + if (GV && AddressPoints[LayoutClass] && !GV->isDeclaration()) + AddressPoint=(*(*(AddressPoints[LayoutClass]))[RD])[std::make_pair(RD, + Offset)]; + else { + VtableBuilder b(methods, RD, LayoutClass, Offset, *this); - D1(printf("vtable %s\n", RD->getNameAsCString())); - // First comes the vtables for all the non-virtual bases... - AddressPoint = b.GenerateVtableForBase(RD, Offset); + D1(printf("vtable %s\n", RD->getNameAsCString())); + // First comes the vtables for all the non-virtual bases... + AddressPoint = b.GenerateVtableForBase(RD, Offset); - // then the vtables for all the virtual bases. - b.GenerateVtableForVBases(RD, Offset); + // then the vtables for all the virtual bases. + b.GenerateVtableForVBases(RD, Offset); - CodeGenModule::AddrMap_t *&ref = AddressPoints[LayoutClass]; - if (ref == 0) - ref = new CodeGenModule::AddrMap_t; + CodeGenModule::AddrMap_t *&ref = AddressPoints[LayoutClass]; + if (ref == 0) + ref = new CodeGenModule::AddrMap_t; - (*ref)[RD] = b.getAddressPoints(); + (*ref)[RD] = b.getAddressPoints(); + + bool CreateDefinition = true; + if (LayoutClass != RD) + CreateDefinition = true; + else { + // We have to convert it to have a record layout. + Types.ConvertTagDeclType(LayoutClass); + const CGRecordLayout &CGLayout = Types.getCGRecordLayout(LayoutClass); + if (const CXXMethodDecl *KeyFunction = CGLayout.getKeyFunction()) { + if (!KeyFunction->getBody()) { + // If there is a KeyFunction, and it isn't defined, just build a + // reference to the vtable. + CreateDefinition = false; + } + } + } - llvm::Constant *C; - llvm::ArrayType *type = llvm::ArrayType::get(Ptr8Ty, methods.size()); - C = llvm::ConstantArray::get(type, methods); - llvm::GlobalVariable *GV = new llvm::GlobalVariable(getModule(), type, - true, linktype, C, - Out.str()); - bool Hidden = getDeclVisibilityMode(RD) == LangOptions::Hidden; - if (Hidden) - GV->setVisibility(llvm::GlobalVariable::HiddenVisibility); + llvm::Constant *C = 0; + llvm::Type *type = Ptr8Ty; + llvm::GlobalVariable::LinkageTypes linktype + = llvm::GlobalValue::ExternalLinkage; + if (CreateDefinition) { + llvm::ArrayType *ntype = llvm::ArrayType::get(Ptr8Ty, methods.size()); + C = llvm::ConstantArray::get(ntype, methods); + linktype = llvm::GlobalValue::LinkOnceODRLinkage; + if (LayoutClass->isInAnonymousNamespace()) + linktype = llvm::GlobalValue::InternalLinkage; + type = ntype; + } + llvm::GlobalVariable *OGV = GV; + GV = new llvm::GlobalVariable(getModule(), type, true, linktype, C, Name); + if (OGV) { + GV->takeName(OGV); + llvm::Constant *NewPtr = llvm::ConstantExpr::getBitCast(GV, + OGV->getType()); + OGV->replaceAllUsesWith(NewPtr); + OGV->eraseFromParent(); + } + bool Hidden = getDeclVisibilityMode(RD) == LangOptions::Hidden; + if (Hidden) + GV->setVisibility(llvm::GlobalVariable::HiddenVisibility); + } llvm::Constant *vtable = llvm::ConstantExpr::getBitCast(GV, Ptr8Ty); llvm::Constant *AddressPointC; uint32_t LLVMPointerWidth = getContext().Target.getPointerWidth(0); @@ -1001,9 +1036,12 @@ llvm::Constant *CodeGenModule::GenerateVTT(const CXXRecordDecl *RD) { llvm::SmallString<256> OutName; llvm::raw_svector_ostream Out(OutName); mangleCXXVTT(getMangleContext(), RD, Out); + llvm::StringRef Name = Out.str(); llvm::GlobalVariable::LinkageTypes linktype; linktype = llvm::GlobalValue::LinkOnceODRLinkage; + if (RD->isInAnonymousNamespace()) + linktype = llvm::GlobalValue::InternalLinkage; std::vector<llvm::Constant *> inits; llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0); @@ -1015,20 +1053,41 @@ llvm::Constant *CodeGenModule::GenerateVTT(const CXXRecordDecl *RD) { llvm::ArrayType *type = llvm::ArrayType::get(Ptr8Ty, inits.size()); C = llvm::ConstantArray::get(type, inits); llvm::GlobalVariable *vtt = new llvm::GlobalVariable(getModule(), type, true, - linktype, C, Out.str()); + linktype, C, Name); bool Hidden = getDeclVisibilityMode(RD) == LangOptions::Hidden; if (Hidden) vtt->setVisibility(llvm::GlobalVariable::HiddenVisibility); return llvm::ConstantExpr::getBitCast(vtt, Ptr8Ty); } +void CGVtableInfo::GenerateClassData(const CXXRecordDecl *RD) { + Vtables[RD] = CGM.GenerateVtable(RD, RD); + CGM.GenerateRtti(RD); + CGM.GenerateVTT(RD); +} + llvm::Constant *CGVtableInfo::getVtable(const CXXRecordDecl *RD) { llvm::Constant *&vtbl = Vtables[RD]; if (vtbl) return vtbl; vtbl = CGM.GenerateVtable(RD, RD); - CGM.GenerateRtti(RD); - CGM.GenerateVTT(RD); + + bool CreateDefinition = true; + // We have to convert it to have a record layout. + CGM.getTypes().ConvertTagDeclType(RD); + const CGRecordLayout &CGLayout = CGM.getTypes().getCGRecordLayout(RD); + if (const CXXMethodDecl *KeyFunction = CGLayout.getKeyFunction()) { + if (!KeyFunction->getBody()) { + // If there is a KeyFunction, and it isn't defined, just build a + // reference to the vtable. + CreateDefinition = false; + } + } + + if (CreateDefinition) { + CGM.GenerateRtti(RD); + CGM.GenerateVTT(RD); + } return vtbl; } diff --git a/lib/CodeGen/CGVtable.h b/lib/CodeGen/CGVtable.h index f9ddf44284b1d..78ae670cf35af 100644 --- a/lib/CodeGen/CGVtable.h +++ b/lib/CodeGen/CGVtable.h @@ -61,6 +61,10 @@ public: llvm::Constant *getVtable(const CXXRecordDecl *RD); llvm::Constant *getCtorVtable(const CXXRecordDecl *RD, const CXXRecordDecl *Class, uint64_t Offset); + /// GenerateClassData - Generate all the class data requires to be generated + /// upon definition of a KeyFunction. This includes the vtable, the + /// rtti data structure and the VTT. + void GenerateClassData(const CXXRecordDecl *RD); }; } diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 0e6f4a63a42ca..195acc5bc1579 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -616,6 +616,16 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD) { Context.getSourceManager(), "Generating code for declaration"); + if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { + const CXXRecordDecl *RD = MD->getParent(); + // We have to convert it to have a record layout. + Types.ConvertTagDeclType(RD); + const CGRecordLayout &CGLayout = Types.getCGRecordLayout(RD); + // A definition of a KeyFunction, generates all the class data, such + // as vtable, rtti and the VTT. + if (CGLayout.getKeyFunction() == MD) + getVtableInfo().GenerateClassData(RD); + } if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(D)) EmitCXXConstructor(CD, GD.getCtorType()); else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(D)) |