<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 - [DebugInfo] Location list for variable is missing due to mix of dbg.declare and dbg.value"
href="https://bugs.llvm.org/show_bug.cgi?id=39314">39314</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>[DebugInfo] Location list for variable is missing due to mix of dbg.declare and dbg.value
</td>
</tr>
<tr>
<th>Product</th>
<td>new-bugs
</td>
</tr>
<tr>
<th>Version</th>
<td>trunk
</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>new bugs
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>david.stenberg@ericsson.com
</td>
</tr>
<tr>
<th>CC</th>
<td>llvm-bugs@lists.llvm.org
</td>
</tr></table>
<p>
<div>
<pre>Reproduced on trunk (r344484).
When compiling the following file, foo.c:
int i = 0;
int main() {
long arr[2] = {0, 0};
long volatile *ptr = arr;
for (; i < 1; i++)
arr[1] = *ptr + 13;
}
using:
$ clang -O3 -g -S foo.c -o foo.s
$ clang foo.s -o foo.out
we do not emit a location list for arr (but instead only a location description
for the first element):
$ readelf --debug-dump=info -W foo.out | grep -B2 -A3 ': arr'
<2><5f>: Abbrev Number: 5 (DW_TAG_variable)
<60> DW_AT_location : 4 byte block: 91 78 93 8 (DW_OP_fbreg:
-8; DW_OP_piece: 8)
<65> DW_AT_name : (indirect string, offset: 0x124): arr
<69> DW_AT_decl_file : 1
<6a> DW_AT_decl_line : 3
<6b> DW_AT_type : <0x7b>
even though we have DBG_VALUEs for the second element available:
$ grep "DEBUG_VALUE: main:arr" foo.s
#DEBUG_VALUE: main:arr <- [DW_OP_LLVM_fragment 64 64] 0
#DEBUG_VALUE: main:arr <- [DW_OP_plus_uconst 13, DW_OP_stack_value,
DW_OP_LLVM_fragment 64 64] $rcx
Some internal analysis:
In SelectionDAGISel.cpp, in processDbgDeclares(), the dbg.declare is taken
care of, and dbg info for the arr variable is inserted in MF using
MF->setVariableDbgInfo.
Later, in DwarfDebug::collectVariableInfo, the dbg info from MF is handled
first. The code looks like this:
void DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU,
const DISubprogram *SP,
DenseSet<InlinedVariable> &Processed)
{
// Grab the variable info that was squirreled away in the MMI side-table.
collectVariableInfoFromMFTable(TheCU, Processed);
for (const auto &I : DbgValues) {
InlinedVariable IV = I.first;
if (Processed.count(IV))
continue;
...
So "arr" is added to Processed already inside
collectVariableInfoFromMFTable, and when iterating over the DbgValues (the map
with dbg.value "history") we bail out early.
It is SROA that splits arr, resulting in a dbg.declare, and some dbg.values:
*** IR Dump Before SROA ***
; Function Attrs: nounwind uwtable
define dso_local i32 @main() #0 !dbg !11 {
entry:
%retval = alloca i32, align 4
%arr = alloca [2 x i64], align 16
%ptr = alloca i64*, align 8
store i32 0, i32* %retval, align 4
%0 = bitcast [2 x i64]* %arr to i8*, !dbg !23
call void @llvm.lifetime.start.p0i8(i64 16, i8* %0) #3, !dbg !23
call void @llvm.dbg.declare(metadata [2 x i64]* %arr, metadata !15,
metadata !DIExpression()), !dbg !24
%1 = bitcast [2 x i64]* %arr to i8*, !dbg !24
call void @llvm.memset.p0i8.i64(i8* align 16 %1, i8 0, i64 16, i1 false),
!dbg !24
%2 = bitcast i64** %ptr to i8*, !dbg !25
call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) #3, !dbg !25
call void @llvm.dbg.declare(metadata i64** %ptr, metadata !20, metadata
!DIExpression()), !dbg !26
%arraydecay = getelementptr inbounds [2 x i64], [2 x i64]* %arr, i32 0,
i32 0, !dbg !27
store i64* %arraydecay, i64** %ptr, align 8, !dbg !26, !tbaa !28
br label %for.cond, !dbg !32
for.cond: ; preds = %for.body,
%entry
%3 = load i32, i32* @i, align 4, !dbg !33, !tbaa !36
%cmp = icmp slt i32 %3, 1, !dbg !38
br i1 %cmp, label %for.body, label %for.end, !dbg !39
for.body: ; preds = %for.cond
%4 = load i64*, i64** %ptr, align 8, !dbg !40, !tbaa !28
%5 = load volatile i64, i64* %4, align 8, !dbg !41, !tbaa !42
%add = add nsw i64 %5, 13, !dbg !44
%arrayidx = getelementptr inbounds [2 x i64], [2 x i64]* %arr, i64 0, i64
1, !dbg !45
store i64 %add, i64* %arrayidx, align 8, !dbg !46, !tbaa !42
%6 = load i32, i32* @i, align 4, !dbg !47, !tbaa !36
%inc = add nsw i32 %6, 1, !dbg !47
store i32 %inc, i32* @i, align 4, !dbg !47, !tbaa !36
br label %for.cond, !dbg !48, !llvm.loop !49
for.end: ; preds = %for.cond
%7 = bitcast i64** %ptr to i8*, !dbg !51
call void @llvm.lifetime.end.p0i8(i64 8, i8* %7) #3, !dbg !51
%8 = bitcast [2 x i64]* %arr to i8*, !dbg !51
call void @llvm.lifetime.end.p0i8(i64 16, i8* %8) #3, !dbg !51
%9 = load i32, i32* %retval, align 4, !dbg !51
ret i32 %9, !dbg !51
}
*** IR Dump After SROA ***
; Function Attrs: nounwind uwtable
define dso_local i32 @main() #0 !dbg !11 {
entry:
%arr.sroa.0 = alloca i64, align 16
call void @llvm.dbg.declare(metadata i64* %arr.sroa.0, metadata !15,
metadata !DIExpression(DW_OP_LLVM_fragment, 0, 64)), !dbg !23
%arr.sroa.0.0..sroa_cast4 = bitcast i64* %arr.sroa.0 to i8*, !dbg !24
call void @llvm.lifetime.start.p0i8(i64 8, i8*
%arr.sroa.0.0..sroa_cast4), !dbg !24
store i64 0, i64* %arr.sroa.0, align 16, !dbg !23
call void @llvm.dbg.value(metadata i64 0, metadata !15, metadata
!DIExpression(DW_OP_LLVM_fragment, 64, 64)), !dbg !23
call void @llvm.dbg.value(metadata i64* undef, metadata !20, metadata
!DIExpression()), !dbg !25
br label %for.cond, !dbg !26
for.cond: ; preds = %for.body,
%entry
%0 = load i32, i32* @i, align 4, !dbg !27, !tbaa !30
%cmp = icmp slt i32 %0, 1, !dbg !34
br i1 %cmp, label %for.body, label %for.end, !dbg !35
for.body: ; preds = %for.cond
%arr.sroa.0.0.arr.sroa.0.0. = load volatile i64, i64* %arr.sroa.0, align
16, !dbg !36, !tbaa !37
%add = add nsw i64 %arr.sroa.0.0.arr.sroa.0.0., 13, !dbg !39
call void @llvm.dbg.value(metadata i64 %add, metadata !15, metadata
!DIExpression(DW_OP_LLVM_fragment, 64, 64)), !dbg !23
%1 = load i32, i32* @i, align 4, !dbg !40, !tbaa !30
%inc = add nsw i32 %1, 1, !dbg !40
store i32 %inc, i32* @i, align 4, !dbg !40, !tbaa !30
br label %for.cond, !dbg !41, !llvm.loop !42
for.end: ; preds = %for.cond
%arr.sroa.0.0..sroa_cast5 = bitcast i64* %arr.sroa.0 to i8*, !dbg !44
call void @llvm.lifetime.end.p0i8(i64 8, i8* %arr.sroa.0.0..sroa_cast5),
!dbg !44
ret i32 0, !dbg !44
}
Should the DWARF emission be able to handle these cases, or is the input bad
somehow?</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>