From 90e5523e4cd2230b86c6921b34affdcd35e0c4c0 Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Mon, 19 Aug 2013 18:46:16 +0000 Subject: [PATCH] Revert "Revert "Revert "DebugInfo: Omit debug info for dynamic classes in TUs that do not have the vtable for that class""" This reverts commit r188642. This change is causing LTO builds to cause our 16 GB machines to swap and OOM all weekend. I am going to work with Dave Blaikie to resolve the issue. Sorry Dave =(. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@188687 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGDebugInfo.cpp | 115 +++++++-------------------- lib/CodeGen/CGDebugInfo.h | 13 ++- lib/CodeGen/CGVTables.cpp | 3 - test/CodeGenCXX/debug-info-class.cpp | 76 +++--------------- 4 files changed, 44 insertions(+), 163 deletions(-) diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 57c35e0aa2..2496970276 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -644,24 +644,8 @@ llvm::DIDescriptor CGDebugInfo::createContextChain(const Decl *Context) { if (const RecordDecl *RD = dyn_cast(Context)) { if (!RD->isDependentType()) { - llvm::DICompositeType T(getTypeOrNull(CGM.getContext().getRecordType(RD))); - llvm::DICompositeType Ty(getOrCreateLimitedType( - CGM.getContext().getRecordType(RD)->castAs(), - getOrCreateMainFile())); - if (!Ty.getTypeArray().getNumElements()) { - if (T) { - llvm::DIArray PrevMem = T.getTypeArray(); - unsigned NumElements = PrevMem.getNumElements(); - if (NumElements == 1 && !PrevMem.getElement(0)) - NumElements = 0; - SmallVector EltTys; - EltTys.reserve(NumElements); - for (unsigned i = 0; i != NumElements; ++i) - EltTys.push_back(PrevMem.getElement(i)); - llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys); - Ty.setTypeArray(Elements); - } - } + llvm::DIType Ty = getOrCreateLimitedType( + CGM.getContext().getRecordType(RD)->castAs(), getOrCreateMainFile()); return llvm::DIDescriptor(Ty); } } @@ -881,7 +865,7 @@ CollectRecordLambdaFields(const CXXRecordDecl *CXXDecl, } } -/// Helper for CollectRecordFields. +/// CollectRecordStaticField - Helper for CollectRecordFields. llvm::DIDerivedType CGDebugInfo::CreateRecordStaticField(const VarDecl *Var, llvm::DIType RecordTy) { @@ -964,7 +948,7 @@ void CGDebugInfo::CollectRecordFields(const RecordDecl *record, for (RecordDecl::decl_iterator I = record->decls_begin(), E = record->decls_end(); I != E; ++I) if (const VarDecl *V = dyn_cast(*I)) - elements.push_back(getOrCreateStaticDataMemberDeclaration(V, RecordTy)); + elements.push_back(CreateRecordStaticField(V, RecordTy)); else if (FieldDecl *field = dyn_cast(*I)) { CollectRecordNormalField(field, layout.getFieldOffset(fieldNo), tunit, elements, RecordTy); @@ -1139,14 +1123,8 @@ CollectCXXMemberFunctions(const CXXRecordDecl *RD, llvm::DIFile Unit, if (D->isImplicit()) continue; - if (const CXXMethodDecl *Method = dyn_cast(D)) { - llvm::DenseMap::iterator MI = - SPCache.find(Method->getCanonicalDecl()); - if (MI == SPCache.end()) - EltTys.push_back(CreateCXXMemberFunction(Method, Unit, RecordTy)); - else - EltTys.push_back(MI->second); - } + if (const CXXMethodDecl *Method = dyn_cast(D)) + EltTys.push_back(CreateCXXMemberFunction(Method, Unit, RecordTy)); } } @@ -1430,18 +1408,10 @@ void CGDebugInfo::completeType(const RecordDecl *RD) { } void CGDebugInfo::completeRequiredType(const RecordDecl *RD) { - if (const CXXRecordDecl *CXXDecl = dyn_cast(RD)) - if (CXXDecl->isDynamicClass()) - return; - QualType Ty = CGM.getContext().getRecordType(RD); llvm::DIType T = getTypeOrNull(Ty); - if (T && T.isForwardDecl()) - completeClassData(RD); -} - -void CGDebugInfo::completeClassData(const RecordDecl *RD) { - QualType Ty = CGM.getContext().getRecordType(RD); + if (!T || !T.isForwardDecl()) + return; void* TyPtr = Ty.getAsOpaquePtr(); if (CompletedTypeCache.count(TyPtr)) return; @@ -1454,23 +1424,14 @@ void CGDebugInfo::completeClassData(const RecordDecl *RD) { /// CreateType - get structure or union type. llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty, bool Declaration) { RecordDecl *RD = Ty->getDecl(); - const CXXRecordDecl *CXXDecl = dyn_cast(RD); // Limited debug info should only remove struct definitions that can // safely be replaced by a forward declaration in the source code. - if ((DebugKind <= CodeGenOptions::LimitedDebugInfo && Declaration && - !RD->isCompleteDefinitionRequired() && CGM.getLangOpts().CPlusPlus) || - (CXXDecl && CXXDecl->hasDefinition() && CXXDecl->isDynamicClass())) { + if (DebugKind <= CodeGenOptions::LimitedDebugInfo && Declaration && + !RD->isCompleteDefinitionRequired() && CGM.getLangOpts().CPlusPlus) { llvm::DIDescriptor FDContext = getContextDescriptor(cast(RD->getDeclContext())); llvm::DIType RetTy = getOrCreateRecordFwdDecl(RD, FDContext); - // FIXME: This is conservatively correct. If we return a non-forward decl - // that's not a full definition (such as those created by - // createContextChain) then getOrCreateType will record is as a complete - // type and we'll never record all its members. But this means we're - // emitting full debug info in TUs where GCC successfully emits a partial - // definition of the type. - if (RetTy.isForwardDecl()) - return RetTy; + return RetTy; } return CreateTypeDefinition(Ty); @@ -1508,7 +1469,6 @@ llvm::DIType CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) { // Convert all the elements. SmallVector EltTys; - // what about nested types? // Note: The split of CXXDecl information here is intentional, the // gdb tests will depend on a certain ordering at printout. The debug @@ -2350,7 +2310,7 @@ llvm::DISubprogram CGDebugInfo::getFunctionDeclaration(const Decl *D) { llvm::DenseMap::iterator MI = SPCache.find(FD->getCanonicalDecl()); if (MI == SPCache.end()) { - if (const CXXMethodDecl *MD = dyn_cast(FD->getCanonicalDecl())) { + if (const CXXMethodDecl *MD = dyn_cast(FD)) { llvm::DICompositeType T(S); llvm::DISubprogram SP = CreateCXXMemberFunction(MD, getOrCreateFile(MD->getLocation()), T); T.addMember(SP); @@ -3065,35 +3025,19 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block, DbgDecl->setDebugLoc(llvm::DebugLoc::get(line, column, scope)); } -/// If D is an out-of-class definition of a static data member of a class, find -/// its corresponding in-class declaration. -llvm::DIDerivedType -CGDebugInfo::getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D) { - if (!D->isStaticDataMember()) - return llvm::DIDerivedType(); - llvm::DenseMap::iterator MI = - StaticDataMemberCache.find(D->getCanonicalDecl()); - if (MI != StaticDataMemberCache.end()) { - assert(MI->second && "Static data member declaration should still exist"); - return llvm::DIDerivedType(cast(MI->second)); - } - llvm::DICompositeType Ctxt( - getContextDescriptor(cast(D->getDeclContext()))); - llvm::DIDerivedType T = CreateRecordStaticField(D, Ctxt); - Ctxt.addMember(T); - return T; -} - -llvm::DIDerivedType -CGDebugInfo::getOrCreateStaticDataMemberDeclaration(const VarDecl *D, - llvm::DICompositeType Ctxt) { - llvm::DenseMap::iterator MI = - StaticDataMemberCache.find(D->getCanonicalDecl()); - if (MI != StaticDataMemberCache.end()) { - assert(MI->second && "Static data member declaration should still exist"); - return llvm::DIDerivedType(cast(MI->second)); +/// getStaticDataMemberDeclaration - If D is an out-of-class definition of +/// a static data member of a class, find its corresponding in-class +/// declaration. +llvm::DIDerivedType CGDebugInfo::getStaticDataMemberDeclaration(const VarDecl *D) { + if (D->isStaticDataMember()) { + llvm::DenseMap::iterator + MI = StaticDataMemberCache.find(D->getCanonicalDecl()); + if (MI != StaticDataMemberCache.end()) + // Verify the info still exists. + if (llvm::Value *V = MI->second) + return llvm::DIDerivedType(cast(V)); } - return CreateRecordStaticField(D, Ctxt); + return llvm::DIDerivedType(); } /// EmitGlobalVariable - Emit information about a global variable. @@ -3125,10 +3069,11 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, LinkageName = StringRef(); llvm::DIDescriptor DContext = getContextDescriptor(dyn_cast(D->getDeclContext())); - llvm::DIGlobalVariable GV = DBuilder.createStaticVariable( - DContext, DeclName, LinkageName, Unit, LineNo, getOrCreateType(T, Unit), - Var->hasInternalLinkage(), Var, - getOrCreateStaticDataMemberDeclarationOrNull(D)); + llvm::DIGlobalVariable GV = + DBuilder.createStaticVariable(DContext, DeclName, LinkageName, Unit, + LineNo, getOrCreateType(T, Unit), + Var->hasInternalLinkage(), Var, + getStaticDataMemberDeclaration(D)); DeclCache.insert(std::make_pair(D->getCanonicalDecl(), llvm::WeakVH(GV))); } @@ -3176,7 +3121,7 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, return; llvm::DIGlobalVariable GV = DBuilder.createStaticVariable( Unit, Name, Name, Unit, getLineNumber(VD->getLocation()), Ty, true, Init, - getOrCreateStaticDataMemberDeclarationOrNull(cast(VD))); + getStaticDataMemberDeclaration(cast(VD))); DeclCache.insert(std::make_pair(VD->getCanonicalDecl(), llvm::WeakVH(GV))); } diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h index d0e16bfe3e..54b9267f8e 100644 --- a/lib/CodeGen/CGDebugInfo.h +++ b/lib/CodeGen/CGDebugInfo.h @@ -291,7 +291,7 @@ public: void completeType(const RecordDecl *RD); void completeRequiredType(const RecordDecl *RD); - void completeClassData(const RecordDecl *RD); + private: /// EmitDeclare - Emit call to llvm.dbg.declare for a variable declaration. @@ -354,13 +354,10 @@ private: /// declaration for the given method definition. llvm::DISubprogram getFunctionDeclaration(const Decl *D); - /// Return debug info descriptor to describe in-class static data member - /// declaration for the given out-of-class definition. - llvm::DIDerivedType - getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D); - llvm::DIDerivedType - getOrCreateStaticDataMemberDeclaration(const VarDecl *D, - llvm::DICompositeType Ctxt); + /// getStaticDataMemberDeclaration - Return debug info descriptor to + /// describe in-class static data member declaration for the given + /// out-of-class definition. + llvm::DIDerivedType getStaticDataMemberDeclaration(const VarDecl *D); /// getFunctionName - Get function name for the given FunctionDecl. If the /// name is constructred on demand (e.g. C++ destructor) then the name diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp index 6649578fc0..c7bb54e069 100644 --- a/lib/CodeGen/CGVTables.cpp +++ b/lib/CodeGen/CGVTables.cpp @@ -828,9 +828,6 @@ CodeGenVTables::GenerateClassData(const CXXRecordDecl *RD) { VFTContext->getVFPtrOffsets(RD); } - if (CGDebugInfo *DI = CGM.getModuleDebugInfo()) - DI->completeClassData(RD); - // First off, check whether we've already emitted the v-table and // associated stuff. llvm::GlobalVariable *VTable = GetAddrOfVTable(RD); diff --git a/test/CodeGenCXX/debug-info-class.cpp b/test/CodeGenCXX/debug-info-class.cpp index e63eeb5eae..0a337dc05d 100644 --- a/test/CodeGenCXX/debug-info-class.cpp +++ b/test/CodeGenCXX/debug-info-class.cpp @@ -13,39 +13,7 @@ public: virtual ~B(); }; -B::~B() { -} - struct C { - static int s; - virtual ~C(); -}; - -C::~C() { -} - -struct D { - D(); - virtual ~D(); - void func() { - } -}; - -struct E { - E(); - virtual ~E(); - virtual void func() { - } -}; - -struct F { - struct inner { - }; - static const int i = 2; - virtual ~F(); -}; - -struct G { virtual void func(); struct inner { int j; @@ -61,17 +29,10 @@ struct A { } }; -void f1() { - D x; - x.func(); - E y; - int i = F::i; - F::inner z; -} int main(int argc, char **argv) { B b; - G::inner c_i; + C::inner c_i; if (argc) { A a; } @@ -88,34 +49,15 @@ int main(int argc, char **argv) { // CHECK: DW_TAG_structure_type ] [foo] // CHECK: DW_TAG_class_type ] [bar] // CHECK: DW_TAG_union_type ] [baz] +// CHECK: DW_TAG_structure_type ] [A] +// CHECK: HdrSize // CHECK: DW_TAG_class_type ] [B] // CHECK: metadata !"_vptr$B", {{.*}}, i32 64, metadata !{{.*}}} ; [ DW_TAG_member ] - -// CHECK: [[C:![0-9]*]] = {{.*}} metadata [[C_MEM:![0-9]*]], i32 0, metadata [[C]], null} ; [ DW_TAG_structure_type ] [C] {{.*}} [def] -// CHECK: [[C_MEM]] = metadata !{metadata [[C_VPTR:![0-9]*]], metadata [[C_S:![0-9]*]], metadata [[C_DTOR:![0-9]*]]} -// CHECK: [[C_VPTR]] = {{.*}} ; [ DW_TAG_member ] [_vptr$C] {{.*}} [artificial] -// CHECK: [[C_S]] = {{.*}} ; [ DW_TAG_member ] [s] {{.*}} [static] [from int] -// CHECK: [[C_DTOR]] = {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [~C] - -// CHECK: ; [ DW_TAG_structure_type ] [A] -// CHECK: HdrSize -// CHECK: metadata [[D_MEM:![0-9]*]], i32 0, null} ; [ DW_TAG_structure_type ] [D] {{.*}} [decl] -// CHECK: [[D_MEM]] = metadata !{metadata [[D_FUNC:![0-9]*]]} -// CHECK: [[D_FUNC]] = {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [func] - -// CHECK: [[F_I_DEF:![0-9]*]] = {{.*}}, metadata [[F_I:![0-9]*]]} ; [ DW_TAG_variable ] [i] -// CHECK: [[F_I]] = {{.*}} ; [ DW_TAG_member ] [i] -// CHECK: [[F:![0-9]*]] = {{.*}} metadata [[F_MEM:![0-9]*]], i32 0, null, null} ; [ DW_TAG_structure_type ] [F] {{.*}} [def] -// CHECK: [[F_MEM]] = metadata !{metadata [[F_I]]} - -// CHECK: null, i32 0, null} ; [ DW_TAG_structure_type ] [E] {{.*}} [decl] - -// CHECK: metadata [[G_INNER_MEM:![0-9]*]], i32 0, null, null} ; [ DW_TAG_structure_type ] [inner] [line 50, {{.*}} [def] +// CHECK: metadata [[C_INNER_MEM:![0-9]*]], i32 0, null, null} ; [ DW_TAG_structure_type ] [inner] {{.*}} [def] // Context chains (in Clang -flimit-debug-info and in GCC generally) contain // definitions without members (& without a vbase 'containing type'): -// CHECK: null, i32 0, null, null} ; [ DW_TAG_structure_type ] [G] {{.*}} [def] -// CHECK: [[G_INNER_MEM]] = metadata !{metadata [[G_INNER_I:![0-9]*]]} -// CHECK: [[G_INNER_I]] = {{.*}} ; [ DW_TAG_member ] [j] {{.*}} [from int] - -// CHECK: ![[EXCEPTLOC]] = metadata !{i32 79, -// CHECK: ![[RETLOC]] = metadata !{i32 78, +// CHECK: null, i32 0, null, null} ; [ DW_TAG_structure_type ] [C] {{.*}} [def] +// CHECK: [[C_INNER_MEM]] = metadata !{metadata [[C_INNER_I:![0-9]*]]} +// CHECK: [[C_INNER_I]] = {{.*}} ; [ DW_TAG_member ] [j] {{.*}} [from int] +// CHECK: ![[EXCEPTLOC]] = metadata !{i32 40, +// CHECK: ![[RETLOC]] = metadata !{i32 39, -- 2.40.0