Remove debug info anchors - llvm.dbg.compile_units, llvm.dbg.subprograms

and llvm.dbg.global_variables.

llvm-svn: 74251
This commit is contained in:
Devang Patel 2009-06-26 01:49:18 +00:00
parent aa311ca000
commit 0751a28888
6 changed files with 95 additions and 238 deletions

View File

@ -24,7 +24,6 @@
<ol>
<li><a href="#debug_info_descriptors">Debug information descriptors</a>
<ul>
<li><a href="#format_anchors">Anchor descriptors</a></li>
<li><a href="#format_compile_units">Compile unit descriptors</a></li>
<li><a href="#format_global_variables">Global variable descriptors</a></li>
<li><a href="#format_subprograms">Subprogram descriptors</a></li>
@ -334,58 +333,6 @@ height="369">
</div>
<!-- ======================================================================= -->
<div class="doc_subsubsection">
<a name="format_anchors">Anchor descriptors</a>
</div>
<div class="doc_text">
<div class="doc_code">
<pre>
%<a href="#format_anchors">llvm.dbg.anchor.type</a> = type {
i32, ;; Tag = 0 + <a href="#LLVMDebugVersion">LLVMDebugVersion</a>
i32 ;; Tag of descriptors grouped by the anchor
}
</pre>
</div>
<p>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.</p>
<p>The following names are recognized as anchors by LLVM:</p>
<div class="doc_code">
<pre>
%<a href="#format_compile_units">llvm.dbg.compile_units</a> = linkonce constant %<a href="#format_anchors">llvm.dbg.anchor.type</a> {
i32 0,
i32 17
} ;; DW_TAG_compile_unit
%<a href="#format_global_variables">llvm.dbg.global_variables</a> = linkonce constant %<a href="#format_anchors">llvm.dbg.anchor.type</a> {
i32 0,
i32 52
} ;; DW_TAG_variable
%<a href="#format_subprograms">llvm.dbg.subprograms</a> = linkonce constant %<a href="#format_anchors">llvm.dbg.anchor.type</a> {
i32 0,
i32 46
} ;; DW_TAG_subprogram
</pre>
</div>
<p>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.</p>
</div>
<!-- ======================================================================= -->
<div class="doc_subsubsection">
<a name="format_compile_units">Compile unit descriptors</a>

View File

@ -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<GlobalVariable *, 2> &CompileUnits,
SmallVector<GlobalVariable *, 4> &GlobalVars,
SmallVector<GlobalVariable *, 4> &Subprograms);
} // end namespace llvm
#endif

View File

@ -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<GlobalVariable>(C) && "Incorrectly typed anchor?");
GlobalVariable *GV = cast<GlobalVariable>(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<GlobalVariable *, 2> &CUs,
SmallVector<GlobalVariable *, 4> &GVs,
SmallVector<GlobalVariable *, 4> &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";
}

View File

@ -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<Constant>(*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<GlobalVariable>(*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<Constant>(*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<GlobalVariable>(*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<Constant>(*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<GlobalVariable>(*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<GlobalVariable *, 2> CUs;
SmallVector<GlobalVariable *, 4> GVs;
SmallVector<GlobalVariable *, 4> SPs;
CollectDebugInfoAnchors(*M, CUs, GVs, SPs);
// Create all the compile unit DIEs.
ConstructCompileUnits();
for (SmallVector<GlobalVariable *, 2>::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<GlobalVariable *, 4>::iterator I = GVs.begin(),
E = GVs.end(); I != E; ++I)
ConstructGlobalVariableDIE(*I);
// Create DIEs for each of the externally visible subprograms.
for (SmallVector<GlobalVariable *, 4>::iterator I = SPs.begin(),
E = SPs.end(); I != E; ++I)
ConstructSubprogram(*I);
MMI = mmi;
shouldEmit = true;
MMI->setDebugInfoAvailability(true);

View File

@ -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.

View File

@ -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<const GlobalValue*, 8> llvmUsedValues;
findUsedValues(M, llvmUsedValues);
// Delete all dbg variables.
SmallVector<GlobalVariable *, 2> CUs;
SmallVector<GlobalVariable *, 4> GVs;
SmallVector<GlobalVariable *, 4> 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<GlobalVariable *, 2>::iterator I = CUs.begin(),
E = CUs.end(); I != E; ++I)
(*I)->setLinkage(GlobalValue::InternalLinkage);
for (SmallVector<GlobalVariable *, 4>::iterator I = GVs.begin(),
E = GVs.end(); I != E; ++I)
(*I)->setLinkage(GlobalValue::InternalLinkage);
for (SmallVector<GlobalVariable *, 4>::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<GlobalVariable>(I);