From: Devang Patel Date: Fri, 26 Jun 2009 01:49:18 +0000 (+0000) Subject: Remove debug info anchors - llvm.dbg.compile_units, llvm.dbg.subprograms X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=13e16b65ddd679d6edb5f182d683701fdea37b85;p=oota-llvm.git Remove debug info anchors - llvm.dbg.compile_units, llvm.dbg.subprograms and llvm.dbg.global_variables. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74251 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/docs/SourceLevelDebugging.html b/docs/SourceLevelDebugging.html index 0b6ed477e04..11b3600bdbe 100644 --- a/docs/SourceLevelDebugging.html +++ b/docs/SourceLevelDebugging.html @@ -24,7 +24,6 @@
  1. Debug information descriptors
      -
    • Anchor descriptors
    • Compile unit descriptors
    • Global variable descriptors
    • Subprogram descriptors
    • @@ -334,58 +333,6 @@ height="369"> - - - -
      - -
      -
      -%llvm.dbg.anchor.type = type {
      -  i32,   ;; Tag = 0 + LLVMDebugVersion
      -  i32    ;; Tag of descriptors grouped by the anchor
      -}
      -
      -
      - -

      One important aspect of the LLVM debug representation is that it allows the - LLVM debugger to efficiently index all of the global objects without having - to scan the program. To do this, all of the global objects use "anchor" - descriptors with designated names. All of the global objects of a particular - type (e.g., compile units) contain a pointer to the anchor. This pointer - allows a debugger to use def-use chains to find all global objects of that - type.

      - -

      The following names are recognized as anchors by LLVM:

      - -
      -
      -%llvm.dbg.compile_units = linkonce constant %llvm.dbg.anchor.type {
      -  i32 0,
      -  i32 17
      -} ;; DW_TAG_compile_unit
      -%llvm.dbg.global_variables = linkonce constant %llvm.dbg.anchor.type {
      -  i32 0,
      -  i32 52
      -} ;; DW_TAG_variable
      -%llvm.dbg.subprograms = linkonce constant %llvm.dbg.anchor.type {
      -  i32 0,
      -  i32 46
      -} ;; DW_TAG_subprogram
      -
      -
      - -

      Using anchors in this way (where the compile unit descriptor points to the - anchors, as opposed to having a list of compile unit descriptors) allows for - the standard dead global elimination and merging passes to automatically - remove unused debugging information. If the globals were kept track of - through lists, there would always be an object pointing to the descriptors, - thus would never be deleted.

      - -
      -
      Compile unit descriptors diff --git a/include/llvm/Analysis/DebugInfo.h b/include/llvm/Analysis/DebugInfo.h index 42a522500fd..c269eaa3e87 100644 --- a/include/llvm/Analysis/DebugInfo.h +++ b/include/llvm/Analysis/DebugInfo.h @@ -17,9 +17,12 @@ #ifndef LLVM_ANALYSIS_DEBUGINFO_H #define LLVM_ANALYSIS_DEBUGINFO_H +#include "llvm/Module.h" +#include "llvm/GlobalVariable.h" #include "llvm/Target/TargetMachine.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Support/Dwarf.h" namespace llvm { @@ -80,15 +83,6 @@ namespace llvm { void dump() const; }; - /// DIAnchor - A wrapper for various anchor descriptors. - class DIAnchor : public DIDescriptor { - public: - explicit DIAnchor(GlobalVariable *GV = 0) - : DIDescriptor(GV, dwarf::DW_TAG_anchor) {} - - unsigned getAnchorTag() const { return getUnsignedField(1); } - }; - /// DISubrange - This is used to represent ranges, for array bounds. class DISubrange : public DIDescriptor { public: @@ -411,7 +405,6 @@ namespace llvm { class DIFactory { Module &M; // Cached values for uniquing and faster lookups. - DIAnchor CompileUnitAnchor, SubProgramAnchor, GlobalVariableAnchor; const Type *EmptyStructPtr; // "{}*". Function *StopPointFn; // llvm.dbg.stoppoint Function *FuncStartFn; // llvm.dbg.func.start @@ -426,18 +419,6 @@ namespace llvm { public: explicit DIFactory(Module &m); - /// GetOrCreateCompileUnitAnchor - Return the anchor for compile units, - /// creating a new one if there isn't already one in the module. - DIAnchor GetOrCreateCompileUnitAnchor(); - - /// GetOrCreateSubprogramAnchor - Return the anchor for subprograms, - /// creating a new one if there isn't already one in the module. - DIAnchor GetOrCreateSubprogramAnchor(); - - /// GetOrCreateGlobalVariableAnchor - Return the anchor for globals, - /// creating a new one if there isn't already one in the module. - DIAnchor GetOrCreateGlobalVariableAnchor(); - /// GetOrCreateArray - Create an descriptor for an array of descriptors. /// This implicitly uniques the arrays created. DIArray GetOrCreateArray(DIDescriptor *Tys, unsigned NumTys); @@ -540,7 +521,6 @@ namespace llvm { private: Constant *GetTagConstant(unsigned TAG); Constant *GetStringConstant(const std::string &String); - DIAnchor GetOrCreateAnchor(unsigned TAG, const char *Name); /// getCastToEmpty - Return the descriptor as a Constant* with type '{}*'. Constant *getCastToEmpty(DIDescriptor D); @@ -563,6 +543,13 @@ namespace llvm { bool getLocationInfo(const Value *V, std::string &DisplayName, std::string &Type, unsigned &LineNo, std::string &File, std::string &Dir); + + /// CollectDebugInfoAnchors - Collect debugging information anchors. + void CollectDebugInfoAnchors(Module &M, + SmallVector &CompileUnits, + SmallVector &GlobalVars, + SmallVector &Subprograms); + } // end namespace llvm #endif diff --git a/lib/Analysis/DebugInfo.cpp b/lib/Analysis/DebugInfo.cpp index 11a56bdf7d4..6b27cf41624 100644 --- a/lib/Analysis/DebugInfo.cpp +++ b/lib/Analysis/DebugInfo.cpp @@ -367,71 +367,10 @@ Constant *DIFactory::GetStringConstant(const std::string &String) { return Slot = ConstantExpr::getBitCast(StrGV, DestTy); } -/// GetOrCreateAnchor - Look up an anchor for the specified tag and name. If it -/// already exists, return it. If not, create a new one and return it. -DIAnchor DIFactory::GetOrCreateAnchor(unsigned TAG, const char *Name) { - const Type *EltTy = StructType::get(Type::Int32Ty, Type::Int32Ty, NULL); - - // Otherwise, create the global or return it if already in the module. - Constant *C = M.getOrInsertGlobal(Name, EltTy); - assert(isa(C) && "Incorrectly typed anchor?"); - GlobalVariable *GV = cast(C); - - // If it has an initializer, it is already in the module. - if (GV->hasInitializer()) - return SubProgramAnchor = DIAnchor(GV); - - GV->setLinkage(GlobalValue::LinkOnceAnyLinkage); - GV->setSection("llvm.metadata"); - GV->setConstant(true); - M.addTypeName("llvm.dbg.anchor.type", EltTy); - - // Otherwise, set the initializer. - Constant *Elts[] = { - GetTagConstant(dwarf::DW_TAG_anchor), - ConstantInt::get(Type::Int32Ty, TAG) - }; - - GV->setInitializer(ConstantStruct::get(Elts, 2)); - return DIAnchor(GV); -} - - - //===----------------------------------------------------------------------===// // DIFactory: Primary Constructors //===----------------------------------------------------------------------===// -/// GetOrCreateCompileUnitAnchor - Return the anchor for compile units, -/// creating a new one if there isn't already one in the module. -DIAnchor DIFactory::GetOrCreateCompileUnitAnchor() { - // If we already created one, just return it. - if (!CompileUnitAnchor.isNull()) - return CompileUnitAnchor; - return CompileUnitAnchor = GetOrCreateAnchor(dwarf::DW_TAG_compile_unit, - "llvm.dbg.compile_units"); -} - -/// GetOrCreateSubprogramAnchor - Return the anchor for subprograms, -/// creating a new one if there isn't already one in the module. -DIAnchor DIFactory::GetOrCreateSubprogramAnchor() { - // If we already created one, just return it. - if (!SubProgramAnchor.isNull()) - return SubProgramAnchor; - return SubProgramAnchor = GetOrCreateAnchor(dwarf::DW_TAG_subprogram, - "llvm.dbg.subprograms"); -} - -/// GetOrCreateGlobalVariableAnchor - Return the anchor for globals, -/// creating a new one if there isn't already one in the module. -DIAnchor DIFactory::GetOrCreateGlobalVariableAnchor() { - // If we already created one, just return it. - if (!GlobalVariableAnchor.isNull()) - return GlobalVariableAnchor; - return GlobalVariableAnchor = GetOrCreateAnchor(dwarf::DW_TAG_variable, - "llvm.dbg.global_variables"); -} - /// GetOrCreateArray - Create an descriptor for an array of descriptors. /// This implicitly uniques the arrays created. DIArray DIFactory::GetOrCreateArray(DIDescriptor *Tys, unsigned NumTys) { @@ -494,7 +433,7 @@ DICompileUnit DIFactory::CreateCompileUnit(unsigned LangID, unsigned RunTimeVer) { Constant *Elts[] = { GetTagConstant(dwarf::DW_TAG_compile_unit), - getCastToEmpty(GetOrCreateCompileUnitAnchor()), + Constant::getNullValue(EmptyStructPtr), ConstantInt::get(Type::Int32Ty, LangID), GetStringConstant(Filename), GetStringConstant(Directory), @@ -509,7 +448,7 @@ DICompileUnit DIFactory::CreateCompileUnit(unsigned LangID, M.addTypeName("llvm.dbg.compile_unit.type", Init->getType()); GlobalVariable *GV = new GlobalVariable(Init->getType(), true, - GlobalValue::InternalLinkage, + GlobalValue::LinkOnceAnyLinkage, Init, "llvm.dbg.compile_unit", &M); GV->setSection("llvm.metadata"); return DICompileUnit(GV); @@ -655,7 +594,7 @@ DISubprogram DIFactory::CreateSubprogram(DIDescriptor Context, Constant *Elts[] = { GetTagConstant(dwarf::DW_TAG_subprogram), - getCastToEmpty(GetOrCreateSubprogramAnchor()), + Constant::getNullValue(EmptyStructPtr), getCastToEmpty(Context), GetStringConstant(Name), GetStringConstant(DisplayName), @@ -671,7 +610,7 @@ DISubprogram DIFactory::CreateSubprogram(DIDescriptor Context, M.addTypeName("llvm.dbg.subprogram.type", Init->getType()); GlobalVariable *GV = new GlobalVariable(Init->getType(), true, - GlobalValue::InternalLinkage, + GlobalValue::LinkOnceAnyLinkage, Init, "llvm.dbg.subprogram", &M); GV->setSection("llvm.metadata"); return DISubprogram(GV); @@ -687,7 +626,7 @@ DIFactory::CreateGlobalVariable(DIDescriptor Context, const std::string &Name, bool isDefinition, llvm::GlobalVariable *Val) { Constant *Elts[] = { GetTagConstant(dwarf::DW_TAG_variable), - getCastToEmpty(GetOrCreateGlobalVariableAnchor()), + Constant::getNullValue(EmptyStructPtr), getCastToEmpty(Context), GetStringConstant(Name), GetStringConstant(DisplayName), @@ -704,7 +643,7 @@ DIFactory::CreateGlobalVariable(DIDescriptor Context, const std::string &Name, M.addTypeName("llvm.dbg.global_variable.type", Init->getType()); GlobalVariable *GV = new GlobalVariable(Init->getType(), true, - GlobalValue::InternalLinkage, + GlobalValue::LinkOnceAnyLinkage, Init, "llvm.dbg.global_variable", &M); GV->setSection("llvm.metadata"); return DIGlobalVariable(GV); @@ -954,6 +893,36 @@ namespace llvm { Unit.getDirectory(Dir); return true; } + + /// CollectDebugInfoAnchors - Collect debugging information anchors. + void CollectDebugInfoAnchors(Module &M, + SmallVector &CUs, + SmallVector &GVs, + SmallVector &SPs) { + + for (Module::global_iterator GVI = M.global_begin(), E = M.global_end(); + GVI != E; GVI++) { + GlobalVariable *GV = GVI; + if (GV->hasName() && strncmp(GV->getNameStart(), "llvm.dbg", 8) == 0 + && GV->isConstant() && GV->hasInitializer()) { + DICompileUnit C(GV); + if (C.isNull() == false) { + CUs.push_back(GV); + continue; + } + DIGlobalVariable G(GV); + if (G.isNull() == false) { + GVs.push_back(GV); + continue; + } + DISubprogram S(GV); + if (S.isNull() == false) { + SPs.push_back(GV); + continue; + } + } + } + } } /// dump - Print descriptor. @@ -1077,3 +1046,4 @@ void DIVariable::dump() const { getType().dump(); cerr << "\n"; } + diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index e8a42b60759..cbe542ba453 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -1242,27 +1242,7 @@ void DwarfDebug::ConstructCompileUnit(GlobalVariable *GV) { CompileUnits.push_back(Unit); } -/// ConstructCompileUnits - Create a compile unit DIEs. -void DwarfDebug::ConstructCompileUnits() { - GlobalVariable *Root = M->getGlobalVariable("llvm.dbg.compile_units"); - if (!Root) - return; - assert(Root->hasLinkOnceLinkage() && Root->hasOneUse() && - "Malformed compile unit descriptor anchor type"); - Constant *RootC = cast(*Root->use_begin()); - assert(RootC->hasNUsesOrMore(1) && - "Malformed compile unit descriptor anchor type"); - - for (Value::use_iterator UI = RootC->use_begin(), UE = Root->use_end(); - UI != UE; ++UI) - for (Value::use_iterator UUI = UI->use_begin(), UUE = UI->use_end(); - UUI != UUE; ++UUI) { - GlobalVariable *GV = cast(*UUI); - ConstructCompileUnit(GV); - } -} - -bool DwarfDebug::ConstructGlobalVariableDIE(GlobalVariable *GV) { +void DwarfDebug::ConstructGlobalVariableDIE(GlobalVariable *GV) { DIGlobalVariable DI_GV(GV); CompileUnit *DW_Unit = MainCU; if (!DW_Unit) @@ -1271,7 +1251,7 @@ bool DwarfDebug::ConstructGlobalVariableDIE(GlobalVariable *GV) { // Check for pre-existence. DIE *&Slot = DW_Unit->getDieMapSlotFor(DI_GV.getGV()); if (Slot) - return false; + return; DIE *VariableDie = CreateGlobalVariableDIE(DW_Unit, DI_GV); @@ -1292,33 +1272,10 @@ bool DwarfDebug::ConstructGlobalVariableDIE(GlobalVariable *GV) { // Expose as global. FIXME - need to check external flag. std::string Name; DW_Unit->AddGlobal(DI_GV.getName(Name), VariableDie); - return true; + return; } -/// ConstructGlobalVariableDIEs - Create DIEs for each of the externally visible -/// global variables. Return true if at least one global DIE is created. -bool DwarfDebug::ConstructGlobalVariableDIEs() { - GlobalVariable *Root = M->getGlobalVariable("llvm.dbg.global_variables"); - if (!Root) - return false; - - assert(Root->hasLinkOnceLinkage() && Root->hasOneUse() && - "Malformed global variable descriptor anchor type"); - Constant *RootC = cast(*Root->use_begin()); - assert(RootC->hasNUsesOrMore(1) && - "Malformed global variable descriptor anchor type"); - - bool Result = false; - for (Value::use_iterator UI = RootC->use_begin(), UE = Root->use_end(); - UI != UE; ++UI) - for (Value::use_iterator UUI = UI->use_begin(), UUE = UI->use_end(); - UUI != UUE; ++UUI) - Result |= ConstructGlobalVariableDIE(cast(*UUI)); - - return Result; -} - -bool DwarfDebug::ConstructSubprogram(GlobalVariable *GV) { +void DwarfDebug::ConstructSubprogram(GlobalVariable *GV) { DISubprogram SP(GV); CompileUnit *Unit = MainCU; if (!Unit) @@ -1327,12 +1284,12 @@ bool DwarfDebug::ConstructSubprogram(GlobalVariable *GV) { // Check for pre-existence. DIE *&Slot = Unit->getDieMapSlotFor(GV); if (Slot) - return false; + return; if (!SP.isDefinition()) // This is a method declaration which will be handled while constructing // class type. - return false; + return; DIE *SubprogramDie = CreateSubprogramDIE(Unit, SP); @@ -1345,30 +1302,7 @@ bool DwarfDebug::ConstructSubprogram(GlobalVariable *GV) { // Expose as global. std::string Name; Unit->AddGlobal(SP.getName(Name), SubprogramDie); - return true; -} - -/// ConstructSubprograms - Create DIEs for each of the externally visible -/// subprograms. Return true if at least one subprogram DIE is created. -bool DwarfDebug::ConstructSubprograms() { - GlobalVariable *Root = M->getGlobalVariable("llvm.dbg.subprograms"); - if (!Root) - return false; - - assert(Root->hasLinkOnceLinkage() && Root->hasOneUse() && - "Malformed subprogram descriptor anchor type"); - Constant *RootC = cast(*Root->use_begin()); - assert(RootC->hasNUsesOrMore(1) && - "Malformed subprogram descriptor anchor type"); - - bool Result = false; - for (Value::use_iterator UI = RootC->use_begin(), UE = Root->use_end(); - UI != UE; ++UI) - for (Value::use_iterator UUI = UI->use_begin(), UUE = UI->use_end(); - UUI != UUE; ++UUI) - Result |= ConstructSubprogram(cast(*UUI)); - - return Result; + return; } /// BeginModule - Emit all Dwarf sections that should come prior to the @@ -1380,8 +1314,15 @@ void DwarfDebug::BeginModule(Module *M, MachineModuleInfo *mmi) { if (TimePassesIsEnabled) DebugTimer->startTimer(); + SmallVector CUs; + SmallVector GVs; + SmallVector SPs; + CollectDebugInfoAnchors(*M, CUs, GVs, SPs); + // Create all the compile unit DIEs. - ConstructCompileUnits(); + for (SmallVector::iterator I = CUs.begin(), + E = CUs.end(); I != E; ++I) + ConstructCompileUnit(*I); if (CompileUnits.empty()) { if (TimePassesIsEnabled) @@ -1390,21 +1331,25 @@ void DwarfDebug::BeginModule(Module *M, MachineModuleInfo *mmi) { return; } - // Create DIEs for each of the externally visible global variables. - bool globalDIEs = ConstructGlobalVariableDIEs(); - - // Create DIEs for each of the externally visible subprograms. - bool subprogramDIEs = ConstructSubprograms(); - // If there is not any debug info available for any global variables and any // subprograms then there is not any debug info to emit. - if (!globalDIEs && !subprogramDIEs) { + if (GVs.empty() && SPs.empty()) { if (TimePassesIsEnabled) DebugTimer->stopTimer(); return; } + // Create DIEs for each of the externally visible global variables. + for (SmallVector::iterator I = GVs.begin(), + E = GVs.end(); I != E; ++I) + ConstructGlobalVariableDIE(*I); + + // Create DIEs for each of the externally visible subprograms. + for (SmallVector::iterator I = SPs.begin(), + E = SPs.end(); I != E; ++I) + ConstructSubprogram(*I); + MMI = mmi; shouldEmit = true; MMI->setDebugInfoAvailability(true); diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index 5bd666dabd1..111ec33bb84 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -460,21 +460,10 @@ class VISIBILITY_HIDDEN DwarfDebug : public Dwarf { void ConstructCompileUnit(GlobalVariable *GV); - /// ConstructCompileUnits - Create a compile unit DIEs. - void ConstructCompileUnits(); + void ConstructGlobalVariableDIE(GlobalVariable *GV); - bool ConstructGlobalVariableDIE(GlobalVariable *GV); + void ConstructSubprogram(GlobalVariable *GV); - /// ConstructGlobalVariableDIEs - Create DIEs for each of the externally - /// visible global variables. Return true if at least one global DIE is - /// created. - bool ConstructGlobalVariableDIEs(); - - bool ConstructSubprogram(GlobalVariable *GV); - - /// ConstructSubprograms - Create DIEs for each of the externally visible - /// subprograms. Return true if at least one subprogram DIE is created. - bool ConstructSubprograms(); public: //===--------------------------------------------------------------------===// // Main entry points. diff --git a/lib/Transforms/IPO/StripSymbols.cpp b/lib/Transforms/IPO/StripSymbols.cpp index ab8fe5f125e..046e0441b1d 100644 --- a/lib/Transforms/IPO/StripSymbols.cpp +++ b/lib/Transforms/IPO/StripSymbols.cpp @@ -26,6 +26,7 @@ #include "llvm/Instructions.h" #include "llvm/Module.h" #include "llvm/Pass.h" +#include "llvm/Analysis/DebugInfo.h" #include "llvm/ValueSymbolTable.h" #include "llvm/TypeSymbolTable.h" #include "llvm/Transforms/Utils/Local.h" @@ -210,7 +211,25 @@ bool StripDebugInfo(Module &M) { SmallPtrSet llvmUsedValues; findUsedValues(M, llvmUsedValues); - // Delete all dbg variables. + SmallVector CUs; + SmallVector GVs; + SmallVector SPs; + CollectDebugInfoAnchors(M, CUs, GVs, SPs); + // These anchors use LinkOnce linkage so that the optimizer does not + // remove them accidently. Set InternalLinkage for all these debug + // info anchors. + for (SmallVector::iterator I = CUs.begin(), + E = CUs.end(); I != E; ++I) + (*I)->setLinkage(GlobalValue::InternalLinkage); + for (SmallVector::iterator I = GVs.begin(), + E = GVs.end(); I != E; ++I) + (*I)->setLinkage(GlobalValue::InternalLinkage); + for (SmallVector::iterator I = SPs.begin(), + E = SPs.end(); I != E; ++I) + (*I)->setLinkage(GlobalValue::InternalLinkage); + + + // Delete all dbg variables. for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { GlobalVariable *GV = dyn_cast(I);