<html>
<head>
<base href="https://bugs.llvm.org/">
</head>
<body><table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Bug ID</th>
<td><a class="bz_bug_link
bz_status_NEW "
title="NEW - Static Local of Inlined Func in Orphaned DWARF DIE"
href="https://bugs.llvm.org/show_bug.cgi?id=51545">51545</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>Static Local of Inlined Func in Orphaned DWARF DIE
</td>
</tr>
<tr>
<th>Product</th>
<td>libraries
</td>
</tr>
<tr>
<th>Version</th>
<td>12.0
</td>
</tr>
<tr>
<th>Hardware</th>
<td>PC
</td>
</tr>
<tr>
<th>OS</th>
<td>Linux
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Severity</th>
<td>enhancement
</td>
</tr>
<tr>
<th>Priority</th>
<td>P
</td>
</tr>
<tr>
<th>Component</th>
<td>DebugInfo
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>ellis.sparky.hoag@gmail.com
</td>
</tr>
<tr>
<th>CC</th>
<td>jdevlieghere@apple.com, keith.walker@arm.com, llvm-bugs@lists.llvm.org, paul_robinson@playstation.sony.com
</td>
</tr></table>
<p>
<div>
<pre><a href="https://bugs.llvm.org/show_bug.cgi">https://bugs.llvm.org/show_bug.cgi</a> shows the same bug but the info seems to be
outdated.
Function-local static variable do not have the correct debug info when their
function is inlined and removed. The root cause is that DIEs for globals are
created before the abstract origin DIEs from inlined subroutines are created.
In this example, the local variable is a child of `foo`'s correct DIE, but the
static global DIE is a child of an orphaned DIE. That orphaned DIE was expected
to be filled in when `foo` is emitted, but that doesn't happen in this example.
```
void mark_used(int *);
__attribute__((always_inline))
static void foo() {
static int global = 0;
int local = 0;
mark_used(&global);
mark_used(&local);
}
int main() {
foo();
return 0;
}
```
```
$ clang -g main.cpp -c -o - | llvm-dwarfdump -
0x0000000b: DW_TAG_compile_unit
DW_AT_producer ("Apple clang version 12.0.5
(clang-1205.0.22.9)")
DW_AT_language (DW_LANG_C_plus_plus)
DW_AT_name ("main.cpp")
DW_AT_APPLE_sdk ("MacOSX.sdk")
DW_AT_stmt_list (0x00000000)
DW_AT_low_pc (0x0000000000000000)
DW_AT_high_pc (0x0000000000000033)
0x00000032: DW_TAG_subprogram
0x00000033: DW_TAG_variable
DW_AT_name ("global")
DW_AT_type (0x00000049 "int")
DW_AT_decl_file ("main.cpp")
DW_AT_decl_line (4)
DW_AT_location (DW_OP_addr 0x408)
0x00000048: NULL
0x00000049: DW_TAG_base_type
DW_AT_name ("int")
DW_AT_encoding (DW_ATE_signed)
DW_AT_byte_size (0x04)
0x00000050: DW_TAG_subprogram
DW_AT_linkage_name ("_ZL3foov")
DW_AT_name ("foo")
DW_AT_decl_file ("main.cpp")
DW_AT_decl_line (3)
DW_AT_inline (DW_INL_inlined)
0x0000005c: DW_TAG_variable
DW_AT_name ("local")
DW_AT_decl_file ("main.cpp")
DW_AT_decl_line (5)
DW_AT_type (0x00000049 "int")
0x00000067: NULL
0x00000068: DW_TAG_subprogram
DW_AT_low_pc (0x0000000000000000)
DW_AT_high_pc (0x0000000000000033)
DW_AT_frame_base (DW_OP_reg6 RBP)
DW_AT_name ("main")
DW_AT_decl_file ("main.cpp")
DW_AT_decl_line (10)
DW_AT_type (0x00000049 "int")
DW_AT_external (true)
0x00000081: DW_TAG_inlined_subroutine
DW_AT_abstract_origin (0x00000050 "_ZL3foov")
DW_AT_low_pc (0x000000000000000f)
DW_AT_high_pc (0x000000000000002d)
DW_AT_call_file ("main.cpp")
DW_AT_call_line (11)
DW_AT_call_column (0x03)
0x00000095: DW_TAG_variable
DW_AT_location (DW_OP_fbreg -4)
DW_AT_abstract_origin (0x0000005c "local")
0x0000009d: NULL
0x0000009e: NULL
0x0000009f: NULL
```
You'll also notice that only the local variable is a child of the inlined
subroutine for `foo` and the static variable is missing.
I made a test case below, but I haven't figured out a good solution without
breaking other test cases.
```
; RUN: %llc_dwarf -O0 -filetype=obj < %s | llvm-dwarfdump -v -debug-info - |
FileCheck --implicit-check-not "{{DW_TAG|NULL}}" %s
; CHECK: DW_TAG_compile_unit
; CHECK: DW_TAG_subprogram
; CHECK: DW_AT_name {{.*}} "foo"
; CHECK: DW_TAG_variable
; CHECK: DW_AT_name {{.*}} "static_var"
; CHECK: DW_TAG_variable
; CHECK: DW_AT_name {{.*}} "local_var"
; CHECK: NULL
; CHECK: DW_TAG_base_type
; CHECK: DW_TAG_subprogram
; CHECK: DW_AT_name {{.*}} "main"
; CHECK: DW_TAG_inlined_subroutine
; CHECK: DW_AT_abstract_origin {{.*}} "foo"
; CHECK; DW_TAG_variable
; CHECK; DW_AT_abstract_origin {{.*}} "static_var"
; CHECK: DW_TAG_variable
; CHECK: DW_AT_abstract_origin {{.*}} "local_var"
; CHECK: NULL
; CHECK: NULL
; CHECK: NULL
@static_var = internal global i32 4, align 4, !dbg !0
define i32 @main() !dbg !7 {
store i32 0, i32* @static_var, align 4, !dbg !15
%local_var = alloca i32, align 4
call void @llvm.dbg.declare(metadata i32* %local_var, metadata !2, metadata
!DIExpression()), !dbg !15
store i32 0, i32* %local_var, align 4, !dbg !15
}
declare void @llvm.dbg.declare(metadata, metadata, metadata)
!llvm.dbg.cu = !{!4}
!llvm.module.flags = !{!11, !12, !13}
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
!1 = !DIGlobalVariable(name: "static_var", scope: !6, file: !5, line: 3, type:
!10, isLocal: true, isDefinition: true)
!2 = !DILocalVariable(name: "local_var", scope: !6, file: !5, line: 4, type:
!10)
!3 = !DISubroutineType(types: !8)
!4 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !5,
emissionKind: FullDebug, globals: !9, splitDebugInlining: false)
!5 = !DIFile(filename: "test.cpp", directory: "/")
!6 = distinct !DISubprogram(name: "foo", scope: !5, file: !5, line: 2, type:
!3, scopeLine: 2, unit: !4)
!7 = distinct !DISubprogram(name: "main", scope: !5, file: !5, line: 7, type:
!3, scopeLine: 7, unit: !4)
!8 = !{}
!9 = !{!0}
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!11 = !{i32 7, !"Dwarf Version", i32 4}
!12 = !{i32 2, !"Debug Info Version", i32 3}
!13 = !{i32 1, !"wchar_size", i32 4}
!15 = !DILocation(line: 4, column: 7, scope: !6, inlinedAt: !16)
!16 = !DILocation(line: 9, column: 3, scope: !7)
```</pre>
</div>
</p>
<hr>
<span>You are receiving this mail because:</span>
<ul>
<li>You are on the CC list for the bug.</li>
</ul>
</body>
</html>