Skip to content

Commit

Permalink
Fixed Dwarf debug info emission to skip DILexicalBlockFile entries.
Browse files Browse the repository at this point in the history
Before this fix, DILexicalBlockFile entries were skipped only in some cases and were not in other cases.

Differential Revision: http://reviews.llvm.org/D18724

llvm-svn: 267004
  • Loading branch information
Amjad Aboud committed Apr 21, 2016
1 parent 9d26599 commit a5ba991
Show file tree
Hide file tree
Showing 5 changed files with 187 additions and 8 deletions.
6 changes: 6 additions & 0 deletions llvm/include/llvm/IR/DebugInfoMetadata.h
Expand Up @@ -1163,6 +1163,12 @@ class DILocalScope : public DIScope {
/// chain.
DISubprogram *getSubprogram() const;

/// Get the first non DILexicalBlockFile scope of this scope.
///
/// Return this if it's not a \a DILexicalBlockFIle; otherwise, look up the
/// scope chain.
DILocalScope *getNonLexicalBlockFileScope() const;

static bool classof(const Metadata *MD) {
return MD->getMetadataID() == DISubprogramKind ||
MD->getMetadataID() == DILexicalBlockKind ||
Expand Down
9 changes: 8 additions & 1 deletion llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
Expand Up @@ -118,7 +118,14 @@ class DwarfCompileUnit : public DwarfUnit {
unsigned getOrCreateSourceID(StringRef FileName, StringRef DirName) override;

void addImportedEntity(const DIImportedEntity* IE) {
ImportedEntities[IE->getScope()].push_back(IE);
DIScope *Scope = IE->getScope();
assert(Scope && "Invalid Scope encoding!");
if (!isa<DILocalScope>(Scope))
// No need to add imported enities that are not local declaration.
return;

auto *LocalScope = cast<DILocalScope>(Scope)->getNonLexicalBlockFileScope();
ImportedEntities[LocalScope].push_back(IE);
}

/// addRange - Add an address range to the list of ranges for this unit.
Expand Down
13 changes: 6 additions & 7 deletions llvm/lib/CodeGen/LexicalScopes.cpp
Expand Up @@ -113,8 +113,7 @@ LexicalScope *LexicalScopes::findLexicalScope(const DILocation *DL) {

// The scope that we were created with could have an extra file - which
// isn't what we care about in this case.
if (auto *File = dyn_cast<DILexicalBlockFile>(Scope))
Scope = File->getScope();
Scope = Scope->getNonLexicalBlockFileScope();

if (auto *IA = DL->getInlinedAt()) {
auto I = InlinedLexicalScopeMap.find(std::make_pair(Scope, IA));
Expand All @@ -140,8 +139,8 @@ LexicalScope *LexicalScopes::getOrCreateLexicalScope(const DILocalScope *Scope,
/// getOrCreateRegularScope - Find or create a regular lexical scope.
LexicalScope *
LexicalScopes::getOrCreateRegularScope(const DILocalScope *Scope) {
if (auto *File = dyn_cast<DILexicalBlockFile>(Scope))
Scope = File->getScope();
assert(Scope && "Invalid Scope encoding!");
Scope = Scope->getNonLexicalBlockFileScope();

auto I = LexicalScopeMap.find(Scope);
if (I != LexicalScopeMap.end())
Expand Down Expand Up @@ -169,6 +168,8 @@ LexicalScopes::getOrCreateRegularScope(const DILocalScope *Scope) {
LexicalScope *
LexicalScopes::getOrCreateInlinedScope(const DILocalScope *Scope,
const DILocation *InlinedAt) {
assert(Scope && "Invalid Scope encoding!");
Scope = Scope->getNonLexicalBlockFileScope();
std::pair<const DILocalScope *, const DILocation *> P(Scope, InlinedAt);
auto I = InlinedLexicalScopeMap.find(P);
if (I != InlinedLexicalScopeMap.end())
Expand All @@ -192,9 +193,7 @@ LexicalScopes::getOrCreateInlinedScope(const DILocalScope *Scope,
LexicalScope *
LexicalScopes::getOrCreateAbstractScope(const DILocalScope *Scope) {
assert(Scope && "Invalid Scope encoding!");

if (auto *File = dyn_cast<DILexicalBlockFile>(Scope))
Scope = File->getScope();
Scope = Scope->getNonLexicalBlockFileScope();
auto I = AbstractScopeMap.find(Scope);
if (I != AbstractScopeMap.end())
return &I->second;
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/IR/DebugInfoMetadata.cpp
Expand Up @@ -392,6 +392,12 @@ DISubprogram *DILocalScope::getSubprogram() const {
return const_cast<DISubprogram *>(cast<DISubprogram>(this));
}

DILocalScope *DILocalScope::getNonLexicalBlockFileScope() const {
if (auto *File = dyn_cast<DILexicalBlockFile>(this))
return File->getScope()->getNonLexicalBlockFileScope();
return const_cast<DILocalScope *>(this);
}

DISubprogram *DISubprogram::getImpl(
LLVMContext &Context, Metadata *Scope, MDString *Name,
MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type,
Expand Down
161 changes: 161 additions & 0 deletions llvm/test/DebugInfo/X86/lexical-block-file-inline.ll
@@ -0,0 +1,161 @@
; RUN: llc -mtriple=x86_64-unknown-linux-gnu -filetype=obj -O0 < %s | llvm-dwarfdump -debug-dump=info - | FileCheck %s

;; This test checks that Inlined DILexicalBlockFile with local decl entry
;; is skipped and only one DW_TAG_lexical_block is generated.
;; This test is special because it contains DILexicalBlockFile that has a
;; DILexicalBlockFile as a parent scope.
;;
;; This test was generated by running following command:
;; clang -cc1 -O0 -debug-info-kind=limited -dwarf-version=4 -emit-llvm test.cpp
;; Where test.cpp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;namespace N {}
;; __attribute__((always_inline)) int bar() {
;; {
;; int y;
;;#line 1 "test.h"
;; using namespace N;
;; while (y < 0) return 2;
;; return 0;
;; }
;;}
;;int foo() {
;; return bar();
;;}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; Concrete "bar" function
; CHECK: DW_TAG_subprogram
; CHECK-NOT: {{DW_TAG|NULL}}
; CHECK: DW_AT_abstract_origin {{.*}} {[[Offset_bar:0x[0-9abcdef]+]]}
; CHECK-NOT: {{DW_TAG|NULL}}
; CHECK: DW_TAG_lexical_block
; CHECK-NOT: {{DW_TAG|NULL}}
; CHECK: DW_TAG_variable
; CHECK-NOT: {{DW_TAG|NULL}}
; CHECK: DW_TAG_imported_module

;; Abstract "bar" function
; CHECK: [[Offset_bar]]: DW_TAG_subprogram
; CHECK-NOT: {{DW_TAG|NULL}}
; CHECK: DW_AT_name {{.*}} "bar"
; CHECK-NOT: {{DW_TAG|NULL}}
; CHECK: DW_AT_inline
; CHECK-NOT: {{DW_TAG|NULL}}
; CHECK: DW_TAG_lexical_block
; CHECK-NOT: {{DW_TAG|NULL}}
; CHECK: DW_TAG_variable
; CHECK-NOT: {{DW_TAG|NULL}}
; CHECK: DW_TAG_imported_module

; CHECK: DW_TAG_subprogram
; CHECK-NOT: {{DW_TAG|NULL}}
; CHECK: DW_AT_name {{.*}} "foo"
; CHECK-NOT: {{NULL}}

;; Inlined "bar" function
; CHECK: DW_TAG_inlined_subroutine
; CHECK-NEXT: DW_AT_abstract_origin {{.*}} {[[Offset_bar]]}
; CHECK-NOT: {{DW_TAG|NULL}}
; CHECK: DW_TAG_lexical_block
; CHECK-NOT: {{DW_TAG|NULL}}
; CHECK: DW_TAG_variable
; CHECK-NOT: {{DW_TAG|NULL}}
; CHECK: DW_TAG_imported_module


; Function Attrs: alwaysinline nounwind
define i32 @_Z3barv() #0 !dbg !4 {
entry:
%retval = alloca i32, align 4
%y = alloca i32, align 4
call void @llvm.dbg.declare(metadata i32* %y, metadata !18, metadata !19), !dbg !20
br label %while.cond, !dbg !21

while.cond: ; preds = %entry
%0 = load i32, i32* %y, align 4, !dbg !22
%cmp = icmp slt i32 %0, 0, !dbg !22
br i1 %cmp, label %while.body, label %while.end, !dbg !22

while.body: ; preds = %while.cond
store i32 2, i32* %retval, align 4, !dbg !24
br label %return, !dbg !24

while.end: ; preds = %while.cond
store i32 0, i32* %retval, align 4, !dbg !26
br label %return, !dbg !26

return: ; preds = %while.end, %while.body
%1 = load i32, i32* %retval, align 4, !dbg !27
ret i32 %1, !dbg !27
}

; Function Attrs: nounwind readnone
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1

; Function Attrs: nounwind
define i32 @_Z3foov() #2 !dbg !8 {
entry:
%retval.i = alloca i32, align 4
%y.i = alloca i32, align 4
call void @llvm.dbg.declare(metadata i32* %y.i, metadata !18, metadata !19), !dbg !29
%0 = load i32, i32* %y.i, align 4, !dbg !31
%cmp.i = icmp slt i32 %0, 0, !dbg !31
br i1 %cmp.i, label %while.body.i, label %while.end.i, !dbg !31

while.body.i: ; preds = %entry
store i32 2, i32* %retval.i, align 4, !dbg !32
br label %_Z3barv.exit, !dbg !32

while.end.i: ; preds = %entry
store i32 0, i32* %retval.i, align 4, !dbg !33
br label %_Z3barv.exit, !dbg !33

_Z3barv.exit: ; preds = %while.end.i, %while.body.i
%1 = load i32, i32* %retval.i, align 4, !dbg !34
ret i32 %1, !dbg !35
}

attributes #0 = { alwaysinline nounwind }
attributes #1 = { nounwind readnone }
attributes #2 = { nounwind }

!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!15, !16}
!llvm.ident = !{!17}

!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.9.0 (trunk 264349)", isOptimized: false, runtimeVersion: 0, emissionKind: 1, enums: !2, imports: !10)
!1 = !DIFile(filename: "test.cpp", directory: "/")
!2 = !{}
!4 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !1, file: !1, line: 2, type: !5, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)
!5 = !DISubroutineType(types: !6)
!6 = !{!7}
!7 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
!8 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !9, file: !9, line: 6, type: !5, isLocal: false, isDefinition: true, scopeLine: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)
!9 = !DIFile(filename: "test.h", directory: "/")
!10 = !{!11}
!11 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !12, entity: !14, line: 1)
!12 = !DILexicalBlockFile(scope: !13, file: !9, discriminator: 0)
!13 = distinct !DILexicalBlock(scope: !4, file: !1, line: 3)
!14 = !DINamespace(name: "N", scope: null, file: !1, line: 1)
!15 = !{i32 2, !"Dwarf Version", i32 4}
!16 = !{i32 2, !"Debug Info Version", i32 3}
!17 = !{!"clang version 3.9.0 (trunk 264349)"}
!18 = !DILocalVariable(name: "y", scope: !13, file: !1, line: 4, type: !7)
!19 = !DIExpression()
!20 = !DILocation(line: 4, scope: !13)
!21 = !DILocation(line: 2, scope: !12)
!22 = !DILocation(line: 2, scope: !23)
!23 = !DILexicalBlockFile(scope: !12, file: !9, discriminator: 1)
!24 = !DILocation(line: 2, scope: !25)
!25 = !DILexicalBlockFile(scope: !12, file: !9, discriminator: 2)
!26 = !DILocation(line: 3, scope: !12)
!27 = !DILocation(line: 5, scope: !28)
!28 = !DILexicalBlockFile(scope: !4, file: !9, discriminator: 0)
!29 = !DILocation(line: 4, scope: !13, inlinedAt: !30)
!30 = distinct !DILocation(line: 7, scope: !8)
!31 = !DILocation(line: 2, scope: !23, inlinedAt: !30)
!32 = !DILocation(line: 2, scope: !25, inlinedAt: !30)
!33 = !DILocation(line: 3, scope: !12, inlinedAt: !30)
!34 = !DILocation(line: 5, scope: !28, inlinedAt: !30)
!35 = !DILocation(line: 7, scope: !8)

0 comments on commit a5ba991

Please sign in to comment.