mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-28 15:33:16 +00:00
Add support to emit debug info for c++ style namespaces.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@90805 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
80564f761a
commit
4063f6bcc7
@ -99,6 +99,7 @@ namespace llvm {
|
||||
bool isGlobalVariable() const;
|
||||
bool isScope() const;
|
||||
bool isCompileUnit() const;
|
||||
bool isNameSpace() const;
|
||||
bool isLexicalBlock() const;
|
||||
bool isSubrange() const;
|
||||
bool isEnumerator() const;
|
||||
@ -218,7 +219,7 @@ namespace llvm {
|
||||
virtual ~DIType() {}
|
||||
|
||||
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); }
|
||||
unsigned getLineNumber() const { return getUnsignedField(4); }
|
||||
uint64_t getSizeInBits() const { return getUInt64Field(5); }
|
||||
@ -470,6 +471,22 @@ namespace llvm {
|
||||
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
|
||||
/// is not associated with any DWARF tag.
|
||||
class DILocation : public DIDescriptor {
|
||||
@ -624,6 +641,11 @@ namespace llvm {
|
||||
/// with the specified parent 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.
|
||||
DILocation CreateLocation(unsigned LineNo, unsigned ColumnNo,
|
||||
DIScope S, DILocation OrigLoc);
|
||||
|
@ -227,6 +227,7 @@ bool DIDescriptor::isScope() const {
|
||||
case dwarf::DW_TAG_compile_unit:
|
||||
case dwarf::DW_TAG_lexical_block:
|
||||
case dwarf::DW_TAG_subprogram:
|
||||
case dwarf::DW_TAG_namespace:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
@ -242,6 +243,14 @@ bool DIDescriptor::isCompileUnit() const {
|
||||
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.
|
||||
bool DIDescriptor::isLexicalBlock() const {
|
||||
assert (!isNull() && "Invalid descriptor!");
|
||||
@ -438,6 +447,8 @@ StringRef DIScope::getFilename() const {
|
||||
return DISubprogram(DbgNode).getFilename();
|
||||
else if (isCompileUnit())
|
||||
return DICompileUnit(DbgNode).getFilename();
|
||||
else if (isNameSpace())
|
||||
return DINameSpace(DbgNode).getFilename();
|
||||
else
|
||||
assert (0 && "Invalid DIScope!");
|
||||
return StringRef();
|
||||
@ -450,6 +461,8 @@ StringRef DIScope::getDirectory() const {
|
||||
return DISubprogram(DbgNode).getDirectory();
|
||||
else if (isCompileUnit())
|
||||
return DICompileUnit(DbgNode).getDirectory();
|
||||
else if (isNameSpace())
|
||||
return DINameSpace(DbgNode).getDirectory();
|
||||
else
|
||||
assert (0 && "Invalid DIScope!");
|
||||
return StringRef();
|
||||
@ -996,6 +1009,21 @@ DILexicalBlock DIFactory::CreateLexicalBlock(DIDescriptor Context) {
|
||||
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.
|
||||
DILocation DIFactory::CreateLocation(unsigned LineNo, unsigned ColumnNo,
|
||||
DIScope S, DILocation OrigLoc) {
|
||||
|
@ -446,6 +446,23 @@ void DwarfDebug::addSourceLine(DIE *Die, const DIType *Ty) {
|
||||
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
|
||||
"SomeType VarName;", but the compiler creates a
|
||||
__Block_byref_x_VarName struct, and gives the variable VarName
|
||||
@ -771,9 +788,13 @@ void DwarfDebug::addType(CompileUnit *DW_Unit, DIE *Entity, DIType Ty) {
|
||||
// Add debug information entry to entity and appropriate context.
|
||||
DIE *Die = NULL;
|
||||
DIDescriptor Context = Ty.getContext();
|
||||
if (!Context.isNull())
|
||||
Die = DW_Unit->getDIE(Context.getNode());
|
||||
|
||||
if (!Context.isNull()) {
|
||||
if (Context.isNameSpace()) {
|
||||
DINameSpace NS(Context.getNode());
|
||||
Die = getOrCreateNameSpace(NS);
|
||||
} else
|
||||
Die = DW_Unit->getDIE(Context.getNode());
|
||||
}
|
||||
if (Die)
|
||||
Die->addChild(Buffer);
|
||||
else
|
||||
@ -1643,6 +1664,29 @@ unsigned DwarfDebug::GetOrCreateSourceID(StringRef DirName, StringRef FileName)
|
||||
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);
|
||||
DIDescriptor NSContext = NS.getContext();
|
||||
DIE *Context = NULL;
|
||||
if (NSContext.isNameSpace()) {
|
||||
DINameSpace NS2(NSContext.getNode());
|
||||
Context = getOrCreateNameSpace(NS2);
|
||||
}
|
||||
else
|
||||
Context = ModuleCU->getCUDie();
|
||||
Context->addChild(NDie);
|
||||
return NDie;
|
||||
}
|
||||
|
||||
void DwarfDebug::constructCompileUnit(MDNode *N) {
|
||||
DICompileUnit DIUnit(N);
|
||||
StringRef FN = DIUnit.getFilename();
|
||||
@ -1734,10 +1778,17 @@ void DwarfDebug::constructSubprogramDIE(MDNode *N) {
|
||||
ModuleCU->insertDIE(N, SubprogramDie);
|
||||
|
||||
// Add to context owner.
|
||||
if (SP.getContext().getNode() == SP.getCompileUnit().getNode())
|
||||
DIDescriptor SPContext = SP.getContext();
|
||||
if (SPContext.isCompileUnit()
|
||||
&& SPContext.getNode() == SP.getCompileUnit().getNode()) {
|
||||
if (TopLevelDIEs.insert(SubprogramDie))
|
||||
TopLevelDIEsVector.push_back(SubprogramDie);
|
||||
|
||||
} else if (SPContext.isNameSpace()) {
|
||||
DINameSpace NS(SPContext.getNode());
|
||||
DIE *NDie = getOrCreateNameSpace(NS);
|
||||
NDie->addChild(SubprogramDie);
|
||||
}
|
||||
|
||||
// Expose as global.
|
||||
ModuleCU->addGlobal(SP.getName(), SubprogramDie);
|
||||
|
||||
@ -1780,10 +1831,18 @@ void DwarfDebug::beginModule(Module *M, MachineModuleInfo *mmi) {
|
||||
for (DebugInfoFinder::iterator I = DbgFinder.global_variable_begin(),
|
||||
E = DbgFinder.global_variable_end(); I != E; ++I) {
|
||||
DIGlobalVariable GV(*I);
|
||||
if (GV.getContext().getNode() != GV.getCompileUnit().getNode())
|
||||
ScopedGVs.push_back(*I);
|
||||
else
|
||||
DIDescriptor GVContext = GV.getContext();
|
||||
if (GVContext.isCompileUnit()
|
||||
&& GVContext.getNode() == GV.getCompileUnit().getNode())
|
||||
constructGlobalVariableDIE(*I);
|
||||
else if (GVContext.isNameSpace()) {
|
||||
DIE *GVDie = createGlobalVariableDIE(ModuleCU, GV);
|
||||
DINameSpace NS(GVContext.getNode());
|
||||
DIE *NDie = getOrCreateNameSpace(NS);
|
||||
NDie->addChild(GVDie);
|
||||
}
|
||||
else
|
||||
ScopedGVs.push_back(*I);
|
||||
}
|
||||
|
||||
// Create DIEs for each subprogram.
|
||||
|
@ -289,6 +289,7 @@ class DwarfDebug : public Dwarf {
|
||||
void addSourceLine(DIE *Die, const DIGlobal *G);
|
||||
void addSourceLine(DIE *Die, const DISubprogram *SP);
|
||||
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
|
||||
/// provided.
|
||||
@ -340,6 +341,9 @@ class DwarfDebug : public Dwarf {
|
||||
/// constructEnumTypeDIE - Construct enum type DIE from DIEnumerator.
|
||||
DIE *constructEnumTypeDIE(CompileUnit *DW_Unit, DIEnumerator *ETy);
|
||||
|
||||
/// getOrCreateNameSpace - Create a DIE for DINameSpace.
|
||||
DIE *getOrCreateNameSpace(DINameSpace &NS);
|
||||
|
||||
/// createGlobalVariableDIE - Create new DIE using GV.
|
||||
DIE *createGlobalVariableDIE(CompileUnit *DW_Unit,
|
||||
const DIGlobalVariable &GV);
|
||||
|
Loading…
Reference in New Issue
Block a user