Add support to emit debug info for C++ namespaces.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@91440 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Devang Patel 2009-12-15 19:16:48 +00:00
parent ad6b1fdaf9
commit 6404e4e795
5 changed files with 128 additions and 23 deletions

View File

@ -99,6 +99,7 @@ namespace llvm {
bool isGlobalVariable() const; bool isGlobalVariable() const;
bool isScope() const; bool isScope() const;
bool isCompileUnit() const; bool isCompileUnit() const;
bool isNameSpace() const;
bool isLexicalBlock() const; bool isLexicalBlock() const;
bool isSubrange() const; bool isSubrange() const;
bool isEnumerator() const; bool isEnumerator() const;
@ -218,7 +219,7 @@ namespace llvm {
virtual ~DIType() {} virtual ~DIType() {}
DIDescriptor getContext() const { return getDescriptorField(1); } DIDescriptor getContext() const { return getDescriptorField(1); }
StringRef getName() const { return getStringField(2); } StringRef getName() const { return getStringField(2); }
DICompileUnit getCompileUnit() const{ return getFieldAs<DICompileUnit>(3); } DICompileUnit getCompileUnit() const{ return getFieldAs<DICompileUnit>(3); }
unsigned getLineNumber() const { return getUnsignedField(4); } unsigned getLineNumber() const { return getUnsignedField(4); }
uint64_t getSizeInBits() const { return getUInt64Field(5); } uint64_t getSizeInBits() const { return getUInt64Field(5); }
@ -470,6 +471,22 @@ namespace llvm {
StringRef getFilename() const { return getContext().getFilename(); } StringRef getFilename() const { return getContext().getFilename(); }
}; };
/// DINameSpace - A wrapper for a C++ style name space.
class DINameSpace : public DIScope {
public:
explicit DINameSpace(MDNode *N = 0) : DIScope(N) {
if (DbgNode && !isNameSpace())
DbgNode = 0;
}
DIScope getContext() const { return getFieldAs<DIScope>(1); }
StringRef getName() const { return getStringField(2); }
StringRef getDirectory() const { return getContext().getDirectory(); }
StringRef getFilename() const { return getContext().getFilename(); }
DICompileUnit getCompileUnit() const { return getFieldAs<DICompileUnit>(3); }
unsigned getLineNumber() const { return getUnsignedField(4); }
};
/// DILocation - This object holds location information. This object /// DILocation - This object holds location information. This object
/// is not associated with any DWARF tag. /// is not associated with any DWARF tag.
class DILocation : public DIDescriptor { class DILocation : public DIDescriptor {
@ -624,6 +641,11 @@ namespace llvm {
/// with the specified parent context. /// with the specified parent context.
DILexicalBlock CreateLexicalBlock(DIDescriptor Context); DILexicalBlock CreateLexicalBlock(DIDescriptor Context);
/// CreateNameSpace - This creates new descriptor for a namespace
/// with the specified parent context.
DINameSpace CreateNameSpace(DIDescriptor Context, StringRef Name,
DICompileUnit CU, unsigned LineNo);
/// CreateLocation - Creates a debug info location. /// CreateLocation - Creates a debug info location.
DILocation CreateLocation(unsigned LineNo, unsigned ColumnNo, DILocation CreateLocation(unsigned LineNo, unsigned ColumnNo,
DIScope S, DILocation OrigLoc); DIScope S, DILocation OrigLoc);

View File

@ -227,6 +227,7 @@ bool DIDescriptor::isScope() const {
case dwarf::DW_TAG_compile_unit: case dwarf::DW_TAG_compile_unit:
case dwarf::DW_TAG_lexical_block: case dwarf::DW_TAG_lexical_block:
case dwarf::DW_TAG_subprogram: case dwarf::DW_TAG_subprogram:
case dwarf::DW_TAG_namespace:
return true; return true;
default: default:
break; break;
@ -242,6 +243,14 @@ bool DIDescriptor::isCompileUnit() const {
return Tag == dwarf::DW_TAG_compile_unit; return Tag == dwarf::DW_TAG_compile_unit;
} }
/// isNameSpace - Return true if the specified tag is DW_TAG_namespace.
bool DIDescriptor::isNameSpace() const {
assert (!isNull() && "Invalid descriptor!");
unsigned Tag = getTag();
return Tag == dwarf::DW_TAG_namespace;
}
/// isLexicalBlock - Return true if the specified tag is DW_TAG_lexical_block. /// isLexicalBlock - Return true if the specified tag is DW_TAG_lexical_block.
bool DIDescriptor::isLexicalBlock() const { bool DIDescriptor::isLexicalBlock() const {
assert (!isNull() && "Invalid descriptor!"); assert (!isNull() && "Invalid descriptor!");
@ -438,6 +447,8 @@ StringRef DIScope::getFilename() const {
return DISubprogram(DbgNode).getFilename(); return DISubprogram(DbgNode).getFilename();
else if (isCompileUnit()) else if (isCompileUnit())
return DICompileUnit(DbgNode).getFilename(); return DICompileUnit(DbgNode).getFilename();
else if (isNameSpace())
return DINameSpace(DbgNode).getFilename();
else else
assert (0 && "Invalid DIScope!"); assert (0 && "Invalid DIScope!");
return StringRef(); return StringRef();
@ -450,6 +461,8 @@ StringRef DIScope::getDirectory() const {
return DISubprogram(DbgNode).getDirectory(); return DISubprogram(DbgNode).getDirectory();
else if (isCompileUnit()) else if (isCompileUnit())
return DICompileUnit(DbgNode).getDirectory(); return DICompileUnit(DbgNode).getDirectory();
else if (isNameSpace())
return DINameSpace(DbgNode).getDirectory();
else else
assert (0 && "Invalid DIScope!"); assert (0 && "Invalid DIScope!");
return StringRef(); return StringRef();
@ -996,6 +1009,21 @@ DILexicalBlock DIFactory::CreateLexicalBlock(DIDescriptor Context) {
return DILexicalBlock(MDNode::get(VMContext, &Elts[0], 2)); return DILexicalBlock(MDNode::get(VMContext, &Elts[0], 2));
} }
/// CreateNameSpace - This creates new descriptor for a namespace
/// with the specified parent context.
DINameSpace DIFactory::CreateNameSpace(DIDescriptor Context, StringRef Name,
DICompileUnit CompileUnit,
unsigned LineNo) {
Value *Elts[] = {
GetTagConstant(dwarf::DW_TAG_namespace),
Context.getNode(),
MDString::get(VMContext, Name),
CompileUnit.getNode(),
ConstantInt::get(Type::getInt32Ty(VMContext), LineNo)
};
return DINameSpace(MDNode::get(VMContext, &Elts[0], 5));
}
/// CreateLocation - Creates a debug info location. /// CreateLocation - Creates a debug info location.
DILocation DIFactory::CreateLocation(unsigned LineNo, unsigned ColumnNo, DILocation DIFactory::CreateLocation(unsigned LineNo, unsigned ColumnNo,
DIScope S, DILocation OrigLoc) { DIScope S, DILocation OrigLoc) {

View File

@ -68,6 +68,7 @@ namespace llvm {
/// Data - Raw data bytes for abbreviation. /// Data - Raw data bytes for abbreviation.
/// ///
SmallVector<DIEAbbrevData, 8> Data; SmallVector<DIEAbbrevData, 8> Data;
public: public:
DIEAbbrev(unsigned T, unsigned C) : Tag(T), ChildrenFlag(C), Data() {} DIEAbbrev(unsigned T, unsigned C) : Tag(T), ChildrenFlag(C), Data() {}
virtual ~DIEAbbrev() {} virtual ~DIEAbbrev() {}
@ -131,19 +132,18 @@ namespace llvm {
/// ///
std::vector<DIE *> Children; std::vector<DIE *> Children;
DIE *Parent;
/// Attributes values. /// Attributes values.
/// ///
SmallVector<DIEValue*, 32> Values; SmallVector<DIEValue*, 32> Values;
/// Abstract compile unit.
CompileUnit *AbstractCU;
// Private data for print() // Private data for print()
mutable unsigned IndentCount; mutable unsigned IndentCount;
public: public:
explicit DIE(unsigned Tag) explicit DIE(unsigned Tag)
: Abbrev(Tag, dwarf::DW_CHILDREN_no), Offset(0), : Abbrev(Tag, dwarf::DW_CHILDREN_no), Offset(0),
Size(0), IndentCount(0) {} Size(0), Parent (0), IndentCount(0) {}
virtual ~DIE(); virtual ~DIE();
// Accessors. // Accessors.
@ -154,12 +154,11 @@ namespace llvm {
unsigned getSize() const { return Size; } unsigned getSize() const { return Size; }
const std::vector<DIE *> &getChildren() const { return Children; } const std::vector<DIE *> &getChildren() const { return Children; }
SmallVector<DIEValue*, 32> &getValues() { return Values; } SmallVector<DIEValue*, 32> &getValues() { return Values; }
CompileUnit *getAbstractCompileUnit() const { return AbstractCU; } DIE *getParent() const { return Parent; }
void setTag(unsigned Tag) { Abbrev.setTag(Tag); } void setTag(unsigned Tag) { Abbrev.setTag(Tag); }
void setOffset(unsigned O) { Offset = O; } void setOffset(unsigned O) { Offset = O; }
void setSize(unsigned S) { Size = S; } void setSize(unsigned S) { Size = S; }
void setAbstractCompileUnit(CompileUnit *CU) { AbstractCU = CU; } void setParent(DIE *P) { Parent = P; }
/// addValue - Add a value and attributes to a DIE. /// addValue - Add a value and attributes to a DIE.
/// ///
@ -179,8 +178,13 @@ namespace llvm {
/// addChild - Add a child to the DIE. /// addChild - Add a child to the DIE.
/// ///
void addChild(DIE *Child) { void addChild(DIE *Child) {
if (Child->getParent()) {
assert (Child->getParent() == this && "Unexpected DIE Parent!");
return;
}
Abbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes); Abbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes);
Children.push_back(Child); Children.push_back(Child);
Child->setParent(this);
} }
#ifndef NDEBUG #ifndef NDEBUG

View File

@ -112,7 +112,12 @@ public:
/// getDIEEntry - Returns the debug information entry for the speciefied /// getDIEEntry - Returns the debug information entry for the speciefied
/// debug variable. /// debug variable.
DIEEntry *getDIEEntry(MDNode *N) { return GVToDIEEntryMap.lookup(N); } DIEEntry *getDIEEntry(MDNode *N) {
ValueMap<MDNode *, DIEEntry *>::iterator I = GVToDIEEntryMap.find(N);
if (I == GVToDIEEntryMap.end())
return NULL;
return I->second;
}
/// insertDIEEntry - Insert debug information entry into the map. /// insertDIEEntry - Insert debug information entry into the map.
void insertDIEEntry(MDNode *N, DIEEntry *E) { void insertDIEEntry(MDNode *N, DIEEntry *E) {
@ -446,6 +451,23 @@ void DwarfDebug::addSourceLine(DIE *Die, const DIType *Ty) {
addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); addUInt(Die, dwarf::DW_AT_decl_line, 0, Line);
} }
/// addSourceLine - Add location information to specified debug information
/// entry.
void DwarfDebug::addSourceLine(DIE *Die, const DINameSpace *NS) {
// If there is no compile unit specified, don't add a line #.
if (NS->getCompileUnit().isNull())
return;
unsigned Line = NS->getLineNumber();
StringRef FN = NS->getFilename();
StringRef Dir = NS->getDirectory();
unsigned FileID = GetOrCreateSourceID(Dir, FN);
assert(FileID && "Invalid file id");
addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID);
addUInt(Die, dwarf::DW_AT_decl_line, 0, Line);
}
/* Byref variables, in Blocks, are declared by the programmer as /* Byref variables, in Blocks, are declared by the programmer as
"SomeType VarName;", but the compiler creates a "SomeType VarName;", but the compiler creates a
__Block_byref_x_VarName struct, and gives the variable VarName __Block_byref_x_VarName struct, and gives the variable VarName
@ -745,6 +767,9 @@ void DwarfDebug::addToContextOwner(DIE *Die, DIDescriptor Context) {
else if (Context.isType()) { else if (Context.isType()) {
DIE *ContextDIE = getOrCreateTypeDIE(DIType(Context.getNode())); DIE *ContextDIE = getOrCreateTypeDIE(DIType(Context.getNode()));
ContextDIE->addChild(Die); ContextDIE->addChild(Die);
} else if (Context.isNameSpace()) {
DIE *ContextDIE = getOrCreateNameSpace(DINameSpace(Context.getNode()));
ContextDIE->addChild(Die);
} else if (DIE *ContextDIE = ModuleCU->getDIE(Context.getNode())) } else if (DIE *ContextDIE = ModuleCU->getDIE(Context.getNode()))
ContextDIE->addChild(Die); ContextDIE->addChild(Die);
else else
@ -781,7 +806,6 @@ void DwarfDebug::addType(DIE *Entity, DIType Ty) {
// Check for pre-existence. // Check for pre-existence.
DIEEntry *Entry = ModuleCU->getDIEEntry(Ty.getNode()); DIEEntry *Entry = ModuleCU->getDIEEntry(Ty.getNode());
// If it exists then use the existing value. // If it exists then use the existing value.
if (Entry) { if (Entry) {
Entity->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, Entry); Entity->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, Entry);
@ -1030,13 +1054,6 @@ DIE *DwarfDebug::createGlobalVariableDIE(const DIGlobalVariable &GV) {
addUInt(GVDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); addUInt(GVDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1);
addSourceLine(GVDie, &GV); addSourceLine(GVDie, &GV);
// Add address.
DIEBlock *Block = new DIEBlock();
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr);
addObjectLabel(Block, 0, dwarf::DW_FORM_udata,
Asm->Mang->getMangledName(GV.getGlobal()));
addBlock(GVDie, dwarf::DW_AT_location, 0, Block);
return GVDie; return GVDie;
} }
@ -1285,7 +1302,6 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(MDNode *SPNode) {
SPDie = new DIE(dwarf::DW_TAG_subprogram); SPDie = new DIE(dwarf::DW_TAG_subprogram);
addDIEEntry(SPDie, dwarf::DW_AT_specification, dwarf::DW_FORM_ref4, addDIEEntry(SPDie, dwarf::DW_AT_specification, dwarf::DW_FORM_ref4,
SPDeclDie); SPDeclDie);
ModuleCU->addDie(SPDie); ModuleCU->addDie(SPDie);
} }
@ -1559,6 +1575,20 @@ unsigned DwarfDebug::GetOrCreateSourceID(StringRef DirName, StringRef FileName)
return SrcId; return SrcId;
} }
/// getOrCreateNameSpace - Create a DIE for DINameSpace.
DIE *DwarfDebug::getOrCreateNameSpace(DINameSpace NS) {
DIE *NDie = ModuleCU->getDIE(NS.getNode());
if (NDie)
return NDie;
NDie = new DIE(dwarf::DW_TAG_namespace);
ModuleCU->insertDIE(NS.getNode(), NDie);
if (!NS.getName().empty())
addString(NDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, NS.getName());
addSourceLine(NDie, &NS);
addToContextOwner(NDie, NS.getContext());
return NDie;
}
CompileUnit *DwarfDebug::constructCompileUnit(MDNode *N) { CompileUnit *DwarfDebug::constructCompileUnit(MDNode *N) {
DICompileUnit DIUnit(N); DICompileUnit DIUnit(N);
StringRef FN = DIUnit.getFilename(); StringRef FN = DIUnit.getFilename();
@ -1620,6 +1650,25 @@ void DwarfDebug::constructGlobalVariableDIE(MDNode *N) {
ModuleCU->insertDIE(N, VariableDie); ModuleCU->insertDIE(N, VariableDie);
// Add to context owner. // Add to context owner.
if (DI_GV.isDefinition()
&& !DI_GV.getContext().isCompileUnit()) {
// Create specification DIE.
DIE *VariableSpecDIE = new DIE(dwarf::DW_TAG_variable);
addDIEEntry(VariableSpecDIE, dwarf::DW_AT_specification,
dwarf::DW_FORM_ref4, VariableDie);
DIEBlock *Block = new DIEBlock();
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr);
addObjectLabel(Block, 0, dwarf::DW_FORM_udata,
Asm->Mang->getMangledName(DI_GV.getGlobal()));
addBlock(VariableSpecDIE, dwarf::DW_AT_location, 0, Block);
ModuleCU->addDie(VariableSpecDIE);
} else {
DIEBlock *Block = new DIEBlock();
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr);
addObjectLabel(Block, 0, dwarf::DW_FORM_udata,
Asm->Mang->getMangledName(DI_GV.getGlobal()));
addBlock(VariableDie, dwarf::DW_AT_location, 0, Block);
}
addToContextOwner(VariableDie, DI_GV.getContext()); addToContextOwner(VariableDie, DI_GV.getContext());
// Expose as global. FIXME - need to check external flag. // Expose as global. FIXME - need to check external flag.
@ -1652,9 +1701,7 @@ void DwarfDebug::constructSubprogramDIE(MDNode *N) {
ModuleCU->insertDIE(N, SubprogramDie); ModuleCU->insertDIE(N, SubprogramDie);
// Add to context owner. // Add to context owner.
if (SP.getContext().getNode() == SP.getCompileUnit().getNode()) addToContextOwner(SubprogramDie, SP.getContext());
if (TopLevelDIEs.insert(SubprogramDie))
TopLevelDIEsVector.push_back(SubprogramDie);
// Expose as global. // Expose as global.
ModuleCU->addGlobal(SP.getName(), SubprogramDie); ModuleCU->addGlobal(SP.getName(), SubprogramDie);
@ -2365,7 +2412,6 @@ void DwarfDebug::emitDebugInfo() {
EmitLabel("info_end", ModuleCU->getID()); EmitLabel("info_end", ModuleCU->getID());
Asm->EOL(); Asm->EOL();
} }
/// emitAbbreviations - Emit the abbreviation section. /// emitAbbreviations - Emit the abbreviation section.

View File

@ -285,6 +285,7 @@ class DwarfDebug : public Dwarf {
void addSourceLine(DIE *Die, const DIGlobal *G); void addSourceLine(DIE *Die, const DIGlobal *G);
void addSourceLine(DIE *Die, const DISubprogram *SP); void addSourceLine(DIE *Die, const DISubprogram *SP);
void addSourceLine(DIE *Die, const DIType *Ty); void addSourceLine(DIE *Die, const DIType *Ty);
void addSourceLine(DIE *Die, const DINameSpace *NS);
/// addAddress - Add an address attribute to a die based on the location /// addAddress - Add an address attribute to a die based on the location
/// provided. /// provided.
@ -315,6 +316,10 @@ class DwarfDebug : public Dwarf {
/// addType - Add a new type attribute to the specified entity. /// addType - Add a new type attribute to the specified entity.
void addType(DIE *Entity, DIType Ty); void addType(DIE *Entity, DIType Ty);
/// getOrCreateNameSpace - Create a DIE for DINameSpace.
DIE *getOrCreateNameSpace(DINameSpace NS);
/// getOrCreateTypeDIE - Find existing DIE or create new DIE for the /// getOrCreateTypeDIE - Find existing DIE or create new DIE for the
/// given DIType. /// given DIType.
DIE *getOrCreateTypeDIE(DIType Ty); DIE *getOrCreateTypeDIE(DIType Ty);