Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[DebugInfo][DWARF] Emit a single location instead of a location list
for variables in nested scopes (including inlined functions) if there is a single location which covers the entire scope and the scope is contained in a single block. Based on work by @jmorse. Reviewed By: vsk, aprantl Differential Revision: https://reviews.llvm.org/D79571
- Loading branch information
Showing
4 changed files
with
400 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
114 changes: 114 additions & 0 deletions
114
llvm/test/DebugInfo/X86/single-location-inlined-param.mir
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
# RUN: llc -start-after=livedebugvalues --filetype=obj %s -o - \ | ||
# RUN: | llvm-dwarfdump -v -name=param - | FileCheck %s | ||
# | ||
# Generated with opt -sroa -inline, llc -stop-after=livedebugvalues, with some | ||
# metadata removed by hand. | ||
# | ||
# int glob; | ||
# __attribute__((always_inline)) | ||
# static void inline_me(int param) { | ||
# { | ||
# int local = param; | ||
# glob = local; | ||
# } | ||
# } | ||
# int fun(int number) { | ||
# inline_me(number); | ||
# if (number) | ||
# return 0; | ||
# return 1; | ||
# } | ||
# | ||
# The inlined parameter 'param' is available for the entirety of its enclosing | ||
# scope. We expect to see a single location entry despite the fact that the | ||
# final instruction in that scope belongs to a dominated scope. | ||
# | ||
# Except for 'param', all DILocalVariable metadata has been removed. | ||
# | ||
# Ignore first entry (abstract), we want to look at the concrete instance. | ||
# CHECK: DW_TAG_formal_parameter [ | ||
# CHECK: DW_TAG_formal_parameter [ | ||
# CHECK-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_reg5 RDI) | ||
# CHECK-NEXT: DW_AT_abstract_origin {{.*}} "param" | ||
|
||
--- | | ||
target triple = "x86_64-unknown-linux-gnu" | ||
|
||
@glob = dso_local global i32 0, align 4, !dbg !0 | ||
declare void @llvm.dbg.declare(metadata, metadata, metadata) | ||
declare void @llvm.dbg.value(metadata, metadata, metadata) | ||
define dso_local i32 @fun(i32 %number) !dbg !11 { | ||
entry: | ||
call void @llvm.dbg.value(metadata i32 %number, metadata !17, metadata !DIExpression()), !dbg !24 | ||
store i32 %number, i32* @glob, align 4, !dbg !27 | ||
%tobool = icmp ne i32 %number, 0, !dbg !32 | ||
br i1 %tobool, label %return, label %if.end, !dbg !34 | ||
|
||
if.end: ; preds = %entry | ||
br label %return, !dbg !35 | ||
|
||
return: ; preds = %entry, %if.end | ||
%retval.0 = phi i32 [ 1, %if.end ], [ 0, %entry ], !dbg !16 | ||
ret i32 %retval.0, !dbg !36 | ||
} | ||
|
||
!llvm.dbg.cu = !{!2} | ||
!llvm.module.flags = !{!7, !8, !9} | ||
!llvm.ident = !{!10} | ||
|
||
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) | ||
!1 = distinct !DIGlobalVariable(name: "glob", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) | ||
!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 11.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, splitDebugInlining: false, nameTableKind: None) | ||
!3 = !DIFile(filename: "test.c", directory: "/") | ||
!4 = !{} | ||
!5 = !{!0} | ||
!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) | ||
!7 = !{i32 7, !"Dwarf Version", i32 4} | ||
!8 = !{i32 2, !"Debug Info Version", i32 3} | ||
!9 = !{i32 1, !"wchar_size", i32 4} | ||
!10 = !{!"clang version 11.0.0"} | ||
!11 = distinct !DISubprogram(name: "fun", scope: !3, file: !3, line: 9, type: !12, scopeLine: 9, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !14) | ||
!12 = !DISubroutineType(types: !13) | ||
!13 = !{!6, !6} | ||
!14 = !{} | ||
!16 = !DILocation(line: 0, scope: !11) | ||
!17 = !DILocalVariable(name: "param", arg: 1, scope: !18, file: !3, line: 3, type: !6) | ||
!18 = distinct !DISubprogram(name: "inline_me", scope: !3, file: !3, line: 3, type: !19, scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !21) | ||
!19 = !DISubroutineType(types: !20) | ||
!20 = !{null, !6} | ||
!21 = !{!17} | ||
!23 = distinct !DILexicalBlock(scope: !18, file: !3, line: 4, column: 3) | ||
!24 = !DILocation(line: 0, scope: !18, inlinedAt: !25) | ||
!25 = distinct !DILocation(line: 10, column: 3, scope: !11) | ||
!26 = !DILocation(line: 0, scope: !23, inlinedAt: !25) | ||
!27 = !DILocation(line: 6, column: 10, scope: !23, inlinedAt: !25) | ||
!32 = !DILocation(line: 11, column: 7, scope: !33) | ||
!33 = distinct !DILexicalBlock(scope: !11, file: !3, line: 11, column: 7) | ||
!34 = !DILocation(line: 11, column: 7, scope: !11) | ||
!35 = !DILocation(line: 13, column: 3, scope: !11) | ||
!36 = !DILocation(line: 14, column: 1, scope: !11) | ||
|
||
... | ||
--- | ||
name: fun | ||
body: | | ||
bb.0.entry: | ||
successors: %bb.2(0x50000000), %bb.1(0x30000000) | ||
liveins: $edi | ||
DBG_VALUE $edi, $noreg, !17, !DIExpression(), debug-location !24 | ||
MOV32mr $rip, 1, $noreg, @glob, $noreg, renamable $edi, debug-location !27 :: (store 4 into @glob) | ||
renamable $eax = XOR32rr undef $eax, undef $eax, implicit-def dead $eflags | ||
TEST32rr killed renamable $edi, renamable $edi, implicit-def $eflags, debug-location !32 | ||
JCC_1 %bb.1, 4, implicit $eflags, debug-location !34 | ||
bb.2.return: | ||
liveins: $eax | ||
RETQ $eax, debug-location !36 | ||
bb.1.if.end: | ||
renamable $eax = MOV32ri 1 | ||
RETQ $eax, debug-location !36 | ||
... |
182 changes: 182 additions & 0 deletions
182
llvm/test/DebugInfo/X86/single-location-interrupted-scope.mir
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
# RUN: llc -start-after=livedebugvalues --filetype=obj %s -o - \ | ||
# RUN: | llvm-dwarfdump -v -name=parama - | FileCheck %s | ||
# | ||
# Generated with -O2, llc -stop-after=livedebugvalues, with IR modified from | ||
# this source: | ||
# | ||
# int globa, globb; | ||
# void ext(); | ||
# static void set(int parama, int paramb) { | ||
# globa = parama; | ||
# globb = paramb; | ||
# } | ||
# void funone(int one, int two) { | ||
# two = two + one; | ||
# // 'two = ...' sunk between the inlined assignments to globa and globa. | ||
# set(one, two); | ||
# if (two > 0) | ||
# return ext(); | ||
# } | ||
# void funtwo(int one, int two) { | ||
# two = one + two; | ||
# // 'two = ...' sunk between the inlined assignments to globa and globa, | ||
# // and rdi is clobbered by the sunk 'two = ...'. | ||
# set(one, two); | ||
# if (one < two) | ||
# return ext(); | ||
# } | ||
# | ||
# Check that the 'parama' is available for the entire inlined scope in funone, | ||
# and that it is unavailable in the second DW_AT_ranges segment of the inlined | ||
# scope in funtwo. In both cases the inlined scope 'set' is intrerrupted by an | ||
# instruction from the calling function. | ||
# | ||
# Except for 'parama', all DILocalVariable metadata has been removed. | ||
# | ||
# Ignore first entry (abstract), we want to look at the concrete instances. | ||
# CHECK: DW_TAG_formal_parameter [ | ||
# CHECK: DW_TAG_formal_parameter [ | ||
# CHECK-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_reg5 RDI) | ||
# CHECK-NEXT: DW_AT_abstract_origin {{.*}} "parama" | ||
# CHECK: DW_TAG_formal_parameter [ | ||
# CHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] | ||
# CHECK-NEXT: [0x{{[0-9a-b]+}}, 0x{{[0-9a-b]+}}) | ||
# CHECK-NEXT: DW_AT_abstract_origin {{.*}} "parama" | ||
|
||
--- | | ||
target triple = "x86_64-unknown-linux-gnu" | ||
|
||
@globa = dso_local local_unnamed_addr global i32 0, align 4, !dbg !0 | ||
@globb = dso_local local_unnamed_addr global i32 0, align 4, !dbg !10 | ||
|
||
declare !dbg !6 dso_local void @ext(...) local_unnamed_addr | ||
declare void @llvm.dbg.value(metadata, metadata, metadata) | ||
|
||
define dso_local void @funone(i32 %one, i32 %two) local_unnamed_addr !dbg !17 { | ||
entry: | ||
call void @llvm.dbg.value(metadata i32 %one, metadata !20, metadata !DIExpression()), !dbg !23 | ||
store i32 %one, i32* @globa, align 4, !dbg !25 | ||
%add = add nsw i32 %two, %one, !dbg !30 | ||
store i32 %add, i32* @globb, align 4, !dbg !31 | ||
%cmp = icmp sgt i32 %add, 0, !dbg !32 | ||
br i1 %cmp, label %if.then, label %if.end, !dbg !34 | ||
|
||
if.then: ; preds = %entry | ||
tail call void (...) @ext(), !dbg !35 | ||
ret void, !dbg !36 | ||
|
||
if.end: ; preds = %entry | ||
ret void, !dbg !36 | ||
} | ||
|
||
define dso_local void @funtwo(i32 %one, i32 %two) local_unnamed_addr !dbg !37 { | ||
entry: | ||
call void @llvm.dbg.value(metadata i32 %one, metadata !20, metadata !DIExpression()), !dbg !41 | ||
store i32 %one, i32* @globa, align 4, !dbg !43 | ||
%add = add nsw i32 %two, %one, !dbg !44 | ||
store i32 %add, i32* @globb, align 4, !dbg !45 | ||
%cmp = icmp sgt i32 %two, 0, !dbg !46 | ||
br i1 %cmp, label %if.then, label %if.end, !dbg !48 | ||
|
||
if.then: ; preds = %entry | ||
tail call void (...) @ext(), !dbg !49 | ||
ret void, !dbg !50 | ||
|
||
if.end: ; preds = %entry | ||
ret void, !dbg !50 | ||
} | ||
|
||
!llvm.dbg.cu = !{!2} | ||
!llvm.module.flags = !{!13, !14, !15} | ||
!llvm.ident = !{!16} | ||
|
||
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) | ||
!1 = distinct !DIGlobalVariable(name: "globa", scope: !2, file: !3, line: 16, type: !12, isLocal: false, isDefinition: true) | ||
!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 11.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !5, globals: !9, splitDebugInlining: false, nameTableKind: None) | ||
!3 = !DIFile(filename: "test.c", directory: "/") | ||
!4 = !{} | ||
!5 = !{!6} | ||
!6 = !DISubprogram(name: "ext", scope: !3, file: !3, line: 17, type: !7, spFlags: DISPFlagOptimized, retainedNodes: !4) | ||
!7 = !DISubroutineType(types: !8) | ||
!8 = !{null, null} | ||
!9 = !{!0, !10} | ||
!10 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression()) | ||
!11 = distinct !DIGlobalVariable(name: "globb", scope: !2, file: !3, line: 16, type: !12, isLocal: false, isDefinition: true) | ||
!12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) | ||
!13 = !{i32 7, !"Dwarf Version", i32 4} | ||
!14 = !{i32 2, !"Debug Info Version", i32 3} | ||
!15 = !{i32 1, !"wchar_size", i32 4} | ||
!16 = !{!"clang version 11.0.0"} | ||
!17 = distinct !DISubprogram(name: "funone", scope: !3, file: !3, line: 22, type: !18, scopeLine: 22, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4) | ||
!18 = !DISubroutineType(types: !19) | ||
!19 = !{null, !12, !12} | ||
!20 = !DILocalVariable(name: "parama", arg: 1, scope: !21, file: !3, line: 18, type: !12) | ||
!21 = distinct !DISubprogram(name: "set", scope: !3, file: !3, line: 18, type: !18, scopeLine: 18, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !22) | ||
!22 = !{!20} | ||
!23 = !DILocation(line: 0, scope: !21, inlinedAt: !24) | ||
!24 = distinct !DILocation(line: 24, column: 3, scope: !17) | ||
!25 = !DILocation(line: 19, column: 9, scope: !21, inlinedAt: !24) | ||
!30 = !DILocation(line: 23, column: 13, scope: !17) | ||
!31 = !DILocation(line: 20, column: 9, scope: !21, inlinedAt: !24) | ||
!32 = !DILocation(line: 25, column: 11, scope: !33) | ||
!33 = distinct !DILexicalBlock(scope: !17, file: !3, line: 25, column: 7) | ||
!34 = !DILocation(line: 25, column: 7, scope: !17) | ||
!35 = !DILocation(line: 26, column: 12, scope: !33) | ||
!36 = !DILocation(line: 27, column: 1, scope: !17) | ||
!37 = distinct !DISubprogram(name: "funtwo", scope: !3, file: !3, line: 28, type: !18, scopeLine: 28, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !38) | ||
!38 = !{} | ||
!41 = !DILocation(line: 0, scope: !21, inlinedAt: !42) | ||
!42 = distinct !DILocation(line: 30, column: 3, scope: !37) | ||
!43 = !DILocation(line: 19, column: 9, scope: !21, inlinedAt: !42) | ||
!44 = !DILocation(line: 29, column: 13, scope: !37) | ||
!45 = !DILocation(line: 20, column: 9, scope: !21, inlinedAt: !42) | ||
!46 = !DILocation(line: 31, column: 11, scope: !47) | ||
!47 = distinct !DILexicalBlock(scope: !37, file: !3, line: 31, column: 7) | ||
!48 = !DILocation(line: 31, column: 7, scope: !37) | ||
!49 = !DILocation(line: 32, column: 12, scope: !47) | ||
!50 = !DILocation(line: 33, column: 1, scope: !37) | ||
|
||
... | ||
--- | ||
name: funone | ||
body: | | ||
bb.0.entry: | ||
successors: %bb.2(0x50000000), %bb.1(0x30000000) | ||
liveins: $edi, $esi | ||
DBG_VALUE $edi, $noreg, !20, !DIExpression(), debug-location !23 | ||
MOV32mr $rip, 1, $noreg, @globa, $noreg, renamable $edi, debug-location !25 :: (store 4 into @globa) | ||
renamable $esi = ADD32rr killed renamable $esi, killed renamable $edi, implicit-def $eflags, debug-location !32 | ||
MOV32mr $rip, 1, $noreg, @globb, $noreg, killed renamable $esi, debug-location !31 :: (store 4 into @globb) | ||
JCC_1 %bb.1, 14, implicit $eflags, debug-location !34 | ||
bb.2.if.then: | ||
dead $eax = XOR32rr undef $eax, undef $eax, implicit-def dead $eflags, implicit-def $al, debug-location !35 | ||
TAILJMPd64 @ext, csr_64, implicit $rsp, implicit $ssp, implicit $rsp, implicit $ssp, implicit killed $al, debug-location !35 | ||
bb.1.if.end: | ||
RETQ debug-location !36 | ||
... | ||
--- | ||
name: funtwo | ||
body: | | ||
bb.0.entry: | ||
successors: %bb.2(0x50000000), %bb.1(0x30000000) | ||
liveins: $edi, $esi | ||
DBG_VALUE $edi, $noreg, !20, !DIExpression(), debug-location !41 | ||
MOV32mr $rip, 1, $noreg, @globa, $noreg, renamable $edi, debug-location !43 :: (store 4 into @globa) | ||
renamable $edi = nsw ADD32rr killed renamable $edi, renamable $esi, implicit-def dead $eflags, debug-location !44 | ||
MOV32mr $rip, 1, $noreg, @globb, $noreg, killed renamable $edi, debug-location !45 :: (store 4 into @globb) | ||
TEST32rr killed renamable $esi, renamable $esi, implicit-def $eflags, debug-location !46 | ||
JCC_1 %bb.1, 14, implicit $eflags, debug-location !48 | ||
bb.2.if.then: | ||
dead $eax = XOR32rr undef $eax, undef $eax, implicit-def dead $eflags, implicit-def $al, debug-location !49 | ||
TAILJMPd64 @ext, csr_64, implicit $rsp, implicit $ssp, implicit $rsp, implicit $ssp, implicit killed $al, debug-location !49 | ||
bb.1.if.end: | ||
RETQ debug-location !50 | ||
... |
Oops, something went wrong.