mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 21:00:29 +00:00
Add a new wrapper node for a DILexicalBlock that encapsulates it and a
file. Since it should only be used when necessary propagate it through the backend code generation and tweak testcases accordingly. This helps with code like in clang's test/CodeGen/debug-info-line.c where we have multiple #line directives within a single lexical block and want to generate only a single block that contains each file change. Part of rdar://10246360 llvm-svn: 141729
This commit is contained in:
parent
22773143e0
commit
57c57a3260
@ -472,10 +472,23 @@ global variables are collected by named metadata <tt>!llvm.dbg.gv</tt>.</p>
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>These descriptors provide debug information about nested blocks within a
|
||||
<p>This descriptor provides debug information about nested blocks within a
|
||||
subprogram. The line number and column numbers are used to dinstinguish
|
||||
two lexical blocks at same depth. </p>
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
!3 = metadata !{
|
||||
i32, ;; Tag = 11 + <a href="#LLVMDebugVersion">LLVMDebugVersion</a> (DW_TAG_lexical_block)
|
||||
metadata ;; Reference to the scope we're annotating with a file change
|
||||
metadata,;; Reference to the file the scope is enclosed in.
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>This descriptor provides a wrapper around a lexical scope to handle file
|
||||
changes in the middle of a lexical block.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
|
@ -37,6 +37,7 @@ namespace llvm {
|
||||
class DINameSpace;
|
||||
class DIVariable;
|
||||
class DISubrange;
|
||||
class DILexicalBlockFile;
|
||||
class DILexicalBlock;
|
||||
class DISubprogram;
|
||||
class DITemplateTypeParameter;
|
||||
@ -463,6 +464,14 @@ namespace llvm {
|
||||
DIFile File, unsigned LineNo);
|
||||
|
||||
|
||||
/// createLexicalBlockFile - This creates a descriptor for a lexical
|
||||
/// block with a new file attached. This merely extends the existing
|
||||
/// lexical block as it crosses a file.
|
||||
/// @param Scope Lexical block.
|
||||
/// @param File Source file.
|
||||
DILexicalBlockFile createLexicalBlockFile(DIDescriptor Scope,
|
||||
DIFile File);
|
||||
|
||||
/// createLexicalBlock - This creates a descriptor for a lexical block
|
||||
/// with the specified parent context.
|
||||
/// @param Scope Parent lexical scope.
|
||||
|
@ -40,6 +40,7 @@ namespace llvm {
|
||||
class DIFile;
|
||||
class DISubprogram;
|
||||
class DILexicalBlock;
|
||||
class DILexicalBlockFile;
|
||||
class DIVariable;
|
||||
class DIType;
|
||||
|
||||
@ -84,6 +85,7 @@ namespace llvm {
|
||||
explicit DIDescriptor(const MDNode *N) : DbgNode(N) {}
|
||||
explicit DIDescriptor(const DIFile F);
|
||||
explicit DIDescriptor(const DISubprogram F);
|
||||
explicit DIDescriptor(const DILexicalBlockFile F);
|
||||
explicit DIDescriptor(const DILexicalBlock F);
|
||||
explicit DIDescriptor(const DIVariable F);
|
||||
explicit DIDescriptor(const DIType F);
|
||||
@ -117,6 +119,7 @@ namespace llvm {
|
||||
bool isFile() const;
|
||||
bool isCompileUnit() const;
|
||||
bool isNameSpace() const;
|
||||
bool isLexicalBlockFile() const;
|
||||
bool isLexicalBlock() const;
|
||||
bool isSubrange() const;
|
||||
bool isEnumerator() const;
|
||||
@ -699,6 +702,26 @@ namespace llvm {
|
||||
}
|
||||
};
|
||||
|
||||
/// DILexicalBlockFile - This is a wrapper for a lexical block with
|
||||
/// a filename change.
|
||||
class DILexicalBlockFile : public DIScope {
|
||||
public:
|
||||
explicit DILexicalBlockFile(const MDNode *N = 0) : DIScope(N) {}
|
||||
DIScope getContext() const { return getScope().getFieldAs<DIScope>(1); }
|
||||
unsigned getLineNumber() const { return getScope().getUnsignedField(2); }
|
||||
unsigned getColumnNumber() const { return getScope().getUnsignedField(3); }
|
||||
StringRef getDirectory() const {
|
||||
StringRef dir = getFieldAs<DIFile>(2).getDirectory();
|
||||
return !dir.empty() ? dir : getContext().getDirectory();
|
||||
}
|
||||
StringRef getFilename() const {
|
||||
StringRef filename = getFieldAs<DIFile>(2).getFilename();
|
||||
assert(!filename.empty() && "Why'd you create this then?");
|
||||
return filename;
|
||||
}
|
||||
DILexicalBlock getScope() const { return getFieldAs<DILexicalBlock>(1); }
|
||||
};
|
||||
|
||||
/// DINameSpace - A wrapper for a C++ style name space.
|
||||
class DINameSpace : public DIScope {
|
||||
public:
|
||||
|
@ -851,6 +851,18 @@ DINameSpace DIBuilder::createNameSpace(DIDescriptor Scope, StringRef Name,
|
||||
return DINameSpace(MDNode::get(VMContext, Elts));
|
||||
}
|
||||
|
||||
/// createLexicalBlockFile - This creates a new MDNode that encapsulates
|
||||
/// an existing scope with a new filename.
|
||||
DILexicalBlockFile DIBuilder::createLexicalBlockFile(DIDescriptor Scope,
|
||||
DIFile File) {
|
||||
Value *Elts[] = {
|
||||
GetTagConstant(VMContext, dwarf::DW_TAG_lexical_block),
|
||||
Scope,
|
||||
File
|
||||
};
|
||||
return DILexicalBlockFile(MDNode::get(VMContext, Elts));
|
||||
}
|
||||
|
||||
DILexicalBlock DIBuilder::createLexicalBlock(DIDescriptor Scope, DIFile File,
|
||||
unsigned Line, unsigned Col) {
|
||||
// Defeat MDNode uniqing for lexical blocks by using unique id.
|
||||
|
@ -39,6 +39,9 @@ DIDescriptor::DIDescriptor(const DIFile F) : DbgNode(F.DbgNode) {
|
||||
DIDescriptor::DIDescriptor(const DISubprogram F) : DbgNode(F.DbgNode) {
|
||||
}
|
||||
|
||||
DIDescriptor::DIDescriptor(const DILexicalBlockFile F) : DbgNode(F.DbgNode) {
|
||||
}
|
||||
|
||||
DIDescriptor::DIDescriptor(const DILexicalBlock F) : DbgNode(F.DbgNode) {
|
||||
}
|
||||
|
||||
@ -263,9 +266,17 @@ bool DIDescriptor::isNameSpace() const {
|
||||
return DbgNode && getTag() == dwarf::DW_TAG_namespace;
|
||||
}
|
||||
|
||||
/// isLexicalBlockFile - Return true if the specified descriptor is a
|
||||
/// lexical block with an extra file.
|
||||
bool DIDescriptor::isLexicalBlockFile() const {
|
||||
return DbgNode && getTag() == dwarf::DW_TAG_lexical_block &&
|
||||
(DbgNode->getNumOperands() == 3);
|
||||
}
|
||||
|
||||
/// isLexicalBlock - Return true if the specified tag is DW_TAG_lexical_block.
|
||||
bool DIDescriptor::isLexicalBlock() const {
|
||||
return DbgNode && getTag() == dwarf::DW_TAG_lexical_block;
|
||||
return DbgNode && getTag() == dwarf::DW_TAG_lexical_block &&
|
||||
(DbgNode->getNumOperands() > 3);
|
||||
}
|
||||
|
||||
/// isSubrange - Return true if the specified tag is DW_TAG_subrange_type.
|
||||
@ -540,6 +551,8 @@ DIArray DISubprogram::getVariables() const {
|
||||
StringRef DIScope::getFilename() const {
|
||||
if (!DbgNode)
|
||||
return StringRef();
|
||||
if (isLexicalBlockFile())
|
||||
return DILexicalBlockFile(DbgNode).getFilename();
|
||||
if (isLexicalBlock())
|
||||
return DILexicalBlock(DbgNode).getFilename();
|
||||
if (isSubprogram())
|
||||
@ -559,6 +572,8 @@ StringRef DIScope::getFilename() const {
|
||||
StringRef DIScope::getDirectory() const {
|
||||
if (!DbgNode)
|
||||
return StringRef();
|
||||
if (isLexicalBlockFile())
|
||||
return DILexicalBlockFile(DbgNode).getDirectory();
|
||||
if (isLexicalBlock())
|
||||
return DILexicalBlock(DbgNode).getDirectory();
|
||||
if (isSubprogram())
|
||||
@ -934,6 +949,10 @@ void DebugInfoFinder::processModule(Module &M) {
|
||||
addCompileUnit(DICompileUnit(Scope));
|
||||
else if (Scope.isSubprogram())
|
||||
processSubprogram(DISubprogram(Scope));
|
||||
else if (Scope.isLexicalBlockFile()) {
|
||||
DILexicalBlockFile DBF = DILexicalBlockFile(Scope);
|
||||
processLexicalBlock(DILexicalBlock(DBF.getScope()));
|
||||
}
|
||||
else if (Scope.isLexicalBlock())
|
||||
processLexicalBlock(DILexicalBlock(Scope));
|
||||
|
||||
@ -967,6 +986,10 @@ void DebugInfoFinder::processLocation(DILocation Loc) {
|
||||
processSubprogram(DISubprogram(S));
|
||||
else if (S.isLexicalBlock())
|
||||
processLexicalBlock(DILexicalBlock(S));
|
||||
else if (S.isLexicalBlockFile()) {
|
||||
DILexicalBlockFile DBF = DILexicalBlockFile(S);
|
||||
processLexicalBlock(DILexicalBlock(DBF.getScope()));
|
||||
}
|
||||
processLocation(Loc.getOrigLocation());
|
||||
}
|
||||
|
||||
@ -998,6 +1021,10 @@ void DebugInfoFinder::processLexicalBlock(DILexicalBlock LB) {
|
||||
DIScope Context = LB.getContext();
|
||||
if (Context.isLexicalBlock())
|
||||
return processLexicalBlock(DILexicalBlock(Context));
|
||||
else if (Context.isLexicalBlockFile()) {
|
||||
DILexicalBlockFile DBF = DILexicalBlockFile(Context);
|
||||
return processLexicalBlock(DILexicalBlock(DBF.getScope()));
|
||||
}
|
||||
else
|
||||
return processSubprogram(DISubprogram(Context));
|
||||
}
|
||||
@ -1081,6 +1108,9 @@ DISubprogram llvm::getDISubprogram(const MDNode *Scope) {
|
||||
if (D.isSubprogram())
|
||||
return DISubprogram(Scope);
|
||||
|
||||
if (D.isLexicalBlockFile())
|
||||
return getDISubprogram(DILexicalBlockFile(Scope).getContext());
|
||||
|
||||
if (D.isLexicalBlock())
|
||||
return getDISubprogram(DILexicalBlock(Scope).getContext());
|
||||
|
||||
|
@ -1371,6 +1371,10 @@ void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S,
|
||||
DISubprogram SP(S);
|
||||
Fn = SP.getFilename();
|
||||
Dir = SP.getDirectory();
|
||||
} else if (Scope.isLexicalBlockFile()) {
|
||||
DILexicalBlockFile DBF(S);
|
||||
Fn = DBF.getFilename();
|
||||
Dir = DBF.getDirectory();
|
||||
} else if (Scope.isLexicalBlock()) {
|
||||
DILexicalBlock DB(S);
|
||||
Fn = DB.getFilename();
|
||||
|
@ -118,9 +118,16 @@ LexicalScope *LexicalScopes::findLexicalScope(DebugLoc DL) {
|
||||
MDNode *IA = NULL;
|
||||
DL.getScopeAndInlinedAt(Scope, IA, MF->getFunction()->getContext());
|
||||
if (!Scope) return NULL;
|
||||
|
||||
// The scope that we were created with could have an extra file - which
|
||||
// isn't what we care about in this case.
|
||||
DIDescriptor D = DIDescriptor(Scope);
|
||||
if (D.isLexicalBlockFile())
|
||||
Scope = DILexicalBlockFile(Scope).getScope();
|
||||
|
||||
if (IA)
|
||||
return InlinedLexicalScopeMap.lookup(DebugLoc::getFromDILocation(IA));
|
||||
return LexicalScopeMap.lookup(DL.getScope(Scope->getContext()));
|
||||
return LexicalScopeMap.lookup(Scope);
|
||||
}
|
||||
|
||||
/// getOrCreateLexicalScope - Find lexical scope for the given DebugLoc. If
|
||||
@ -129,6 +136,7 @@ LexicalScope *LexicalScopes::getOrCreateLexicalScope(DebugLoc DL) {
|
||||
MDNode *Scope = NULL;
|
||||
MDNode *InlinedAt = NULL;
|
||||
DL.getScopeAndInlinedAt(Scope, InlinedAt, MF->getFunction()->getContext());
|
||||
|
||||
if (InlinedAt) {
|
||||
// Create an abstract scope for inlined function.
|
||||
getOrCreateAbstractScope(Scope);
|
||||
@ -141,12 +149,16 @@ LexicalScope *LexicalScopes::getOrCreateLexicalScope(DebugLoc DL) {
|
||||
|
||||
/// getOrCreateRegularScope - Find or create a regular lexical scope.
|
||||
LexicalScope *LexicalScopes::getOrCreateRegularScope(MDNode *Scope) {
|
||||
DIDescriptor D = DIDescriptor(Scope);
|
||||
if (D.isLexicalBlockFile())
|
||||
Scope = DILexicalBlockFile(Scope).getScope();
|
||||
|
||||
LexicalScope *WScope = LexicalScopeMap.lookup(Scope);
|
||||
if (WScope)
|
||||
return WScope;
|
||||
|
||||
LexicalScope *Parent = NULL;
|
||||
if (DIDescriptor(Scope).isLexicalBlock())
|
||||
if (D.isLexicalBlock())
|
||||
Parent = getOrCreateLexicalScope(DebugLoc::getFromDILexicalBlock(Scope));
|
||||
WScope = new LexicalScope(Parent, DIDescriptor(Scope), NULL, false);
|
||||
LexicalScopeMap.insert(std::make_pair(Scope, WScope));
|
||||
@ -176,12 +188,14 @@ LexicalScope *LexicalScopes::getOrCreateInlinedScope(MDNode *Scope,
|
||||
LexicalScope *LexicalScopes::getOrCreateAbstractScope(const MDNode *N) {
|
||||
assert(N && "Invalid Scope encoding!");
|
||||
|
||||
DIDescriptor Scope(N);
|
||||
if (Scope.isLexicalBlockFile())
|
||||
Scope = DILexicalBlockFile(Scope).getScope();
|
||||
LexicalScope *AScope = AbstractScopeMap.lookup(N);
|
||||
if (AScope)
|
||||
return AScope;
|
||||
|
||||
LexicalScope *Parent = NULL;
|
||||
DIDescriptor Scope(N);
|
||||
if (Scope.isLexicalBlock()) {
|
||||
DILexicalBlock DB(N);
|
||||
DIDescriptor ParentDesc = DB.getContext();
|
||||
|
@ -23,10 +23,10 @@ declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone
|
||||
declare i32 @foo(i32) ssp
|
||||
|
||||
!0 = metadata !{i32 5, i32 2, metadata !1, null}
|
||||
!1 = metadata !{i32 458763, metadata !2}; [DW_TAG_lexical_block ]
|
||||
!1 = metadata !{i32 458763, metadata !2, i32 1, i32 1}; [DW_TAG_lexical_block ]
|
||||
!2 = metadata !{i32 458798, i32 0, metadata !3, metadata !"bar", metadata !"bar", metadata !"bar", metadata !3, i32 4, null, i1 false, i1 true}; [DW_TAG_subprogram ]
|
||||
!3 = metadata !{i32 458769, i32 0, i32 12, metadata !"genmodes.i", metadata !"/Users/yash/Downloads", metadata !"clang 1.1", i1 true, i1 false, metadata !"", i32 0}; [DW_TAG_compile_unit ]
|
||||
!4 = metadata !{i32 459008, metadata !5, metadata !"count_", metadata !3, i32 5, metadata !6}; [ DW_TAG_auto_variable ]
|
||||
!5 = metadata !{i32 458763, metadata !1}; [DW_TAG_lexical_block ]
|
||||
!5 = metadata !{i32 458763, metadata !1, i32 1, i32 1}; [DW_TAG_lexical_block ]
|
||||
!6 = metadata !{i32 458788, metadata !3, metadata !"int", metadata !3, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5}; [DW_TAG_base_type ]
|
||||
!7 = metadata !{i32 6, i32 1, metadata !2, null}
|
||||
|
@ -23,10 +23,10 @@ declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone
|
||||
declare i32 @foo(i32) ssp
|
||||
|
||||
!0 = metadata !{i32 5, i32 2, metadata !1, null}
|
||||
!1 = metadata !{i32 458763, metadata !2}; [DW_TAG_lexical_block ]
|
||||
!1 = metadata !{i32 458763, metadata !2, i32 1, i32 1}; [DW_TAG_lexical_block ]
|
||||
!2 = metadata !{i32 458798, i32 0, metadata !3, metadata !"bar", metadata !"bar", metadata !"bar", metadata !3, i32 4, null, i1 false, i1 true}; [DW_TAG_subprogram ]
|
||||
!3 = metadata !{i32 458769, i32 0, i32 12, metadata !"genmodes.i", metadata !"/Users/yash/Downloads", metadata !"clang 1.1", i1 true, i1 false, metadata !"", i32 0}; [DW_TAG_compile_unit ]
|
||||
!4 = metadata !{i32 459008, metadata !5, metadata !"count_", metadata !3, i32 5, metadata !6}; [ DW_TAG_auto_variable ]
|
||||
!5 = metadata !{i32 458763, metadata !1}; [DW_TAG_lexical_block ]
|
||||
!5 = metadata !{i32 458763, metadata !1, i32 1, i32 1}; [DW_TAG_lexical_block ]
|
||||
!6 = metadata !{i32 458788, metadata !3, metadata !"int", metadata !3, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5}; [DW_TAG_base_type ]
|
||||
!7 = metadata !{i32 6, i32 1, metadata !2, null}
|
||||
|
@ -9,7 +9,7 @@ entry:
|
||||
}
|
||||
|
||||
!0 = metadata !{i32 571, i32 3, metadata !1, null}
|
||||
!1 = metadata !{i32 458763, metadata !2}; [DW_TAG_lexical_block ]
|
||||
!1 = metadata !{i32 458763, metadata !2, i32 1, i32 1}; [DW_TAG_lexical_block ]
|
||||
!2 = metadata !{i32 458798, i32 0, metadata !3, metadata !"foo", metadata !"foo", metadata !"foo", metadata !3, i32 561, metadata !4, i1 false, i1 true}; [DW_TAG_subprogram ]
|
||||
!3 = metadata !{i32 458769, i32 0, i32 12, metadata !"hashtab.c", metadata !"/usr/src/gnu/usr.bin/cc/cc_tools/../../../../contrib/gcclibs/libiberty", metadata !"clang 1.1", i1 true, i1 false, metadata !"", i32 0}; [DW_TAG_compile_unit ]
|
||||
!4 = metadata !{i32 458773, metadata !3, metadata !"", null, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !5, i32 0}; [DW_TAG_subroutine_type ]
|
||||
|
Loading…
Reference in New Issue
Block a user