diff options
author | Eric Christopher <echristo@apple.com> | 2011-10-11 22:59:11 +0000 |
---|---|---|
committer | Eric Christopher <echristo@apple.com> | 2011-10-11 22:59:11 +0000 |
commit | 6618a241f7ba2571a1a55b3733c4441d467baf42 (patch) | |
tree | ca10b111fbb600e6de43d2ece7b9b1550b2d0d8d | |
parent | 5ba7b501fd4b88e3fea590499e9464b4b2c153a4 (diff) | |
download | external_llvm-6618a241f7ba2571a1a55b3733c4441d467baf42.zip external_llvm-6618a241f7ba2571a1a55b3733c4441d467baf42.tar.gz external_llvm-6618a241f7ba2571a1a55b3733c4441d467baf42.tar.bz2 |
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
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141729 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | docs/SourceLevelDebugging.html | 15 | ||||
-rw-r--r-- | include/llvm/Analysis/DIBuilder.h | 9 | ||||
-rw-r--r-- | include/llvm/Analysis/DebugInfo.h | 23 | ||||
-rw-r--r-- | lib/Analysis/DIBuilder.cpp | 12 | ||||
-rw-r--r-- | lib/Analysis/DebugInfo.cpp | 32 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 4 | ||||
-rw-r--r-- | lib/CodeGen/LexicalScopes.cpp | 20 | ||||
-rw-r--r-- | test/CodeGen/ARM/2009-10-16-Scope.ll | 4 | ||||
-rw-r--r-- | test/CodeGen/X86/2009-10-16-Scope.ll | 4 | ||||
-rw-r--r-- | test/DebugInfo/2010-01-05-DbgScope.ll | 2 |
10 files changed, 115 insertions, 10 deletions
diff --git a/docs/SourceLevelDebugging.html b/docs/SourceLevelDebugging.html index 98dfc9a..6eaaa24 100644 --- a/docs/SourceLevelDebugging.html +++ b/docs/SourceLevelDebugging.html @@ -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> <!-- ======================================================================= --> diff --git a/include/llvm/Analysis/DIBuilder.h b/include/llvm/Analysis/DIBuilder.h index a29d762..ee24226 100644 --- a/include/llvm/Analysis/DIBuilder.h +++ b/include/llvm/Analysis/DIBuilder.h @@ -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. diff --git a/include/llvm/Analysis/DebugInfo.h b/include/llvm/Analysis/DebugInfo.h index 1022302..d2bb29b 100644 --- a/include/llvm/Analysis/DebugInfo.h +++ b/include/llvm/Analysis/DebugInfo.h @@ -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: diff --git a/lib/Analysis/DIBuilder.cpp b/lib/Analysis/DIBuilder.cpp index fd56d36..bfa429d 100644 --- a/lib/Analysis/DIBuilder.cpp +++ b/lib/Analysis/DIBuilder.cpp @@ -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. diff --git a/lib/Analysis/DebugInfo.cpp b/lib/Analysis/DebugInfo.cpp index aeb039c..44457d3 100644 --- a/lib/Analysis/DebugInfo.cpp +++ b/lib/Analysis/DebugInfo.cpp @@ -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()); diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index d7c702a..1b7e370 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -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(); diff --git a/lib/CodeGen/LexicalScopes.cpp b/lib/CodeGen/LexicalScopes.cpp index ae06a40..02fa525 100644 --- a/lib/CodeGen/LexicalScopes.cpp +++ b/lib/CodeGen/LexicalScopes.cpp @@ -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(); diff --git a/test/CodeGen/ARM/2009-10-16-Scope.ll b/test/CodeGen/ARM/2009-10-16-Scope.ll index ce440e9..a2e7ff7 100644 --- a/test/CodeGen/ARM/2009-10-16-Scope.ll +++ b/test/CodeGen/ARM/2009-10-16-Scope.ll @@ -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} diff --git a/test/CodeGen/X86/2009-10-16-Scope.ll b/test/CodeGen/X86/2009-10-16-Scope.ll index 86c2024..e41038d 100644 --- a/test/CodeGen/X86/2009-10-16-Scope.ll +++ b/test/CodeGen/X86/2009-10-16-Scope.ll @@ -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} diff --git a/test/DebugInfo/2010-01-05-DbgScope.ll b/test/DebugInfo/2010-01-05-DbgScope.ll index 8cf20e3..ad4c8d7 100644 --- a/test/DebugInfo/2010-01-05-DbgScope.ll +++ b/test/DebugInfo/2010-01-05-DbgScope.ll @@ -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 ] |