llvm.dbg.value needs the actual loaded value as the first argument, rather than it's address.
Details
Diff Detail
- Repository
- rL LLVM
Event Timeline
Interesting. On a first glance, this almost looks like a cut&paste error from the function above it.
[ I was thinking about whether it wouldn't be better to leave it as is and add an additional DW_OP_deref to the DIExpression. This has both the advantage and disadvantage that the lifetime of the address is indefinite, which could lead to more debuggable code because the variable is available for a longer range. It could also lead to more misleading debug info, if the code is performing calculations on the loaded value and the debug info is pointing the an old version of the variable in memory. ]
In cases where the alloca cannot be elided, the dbg.declare describing the alloca will also survive, so it makes no sense to describe the address twice. We should do the same thing we do for stores and just describe the value.
Can you add a comment to the code that indicates that this is now tracking the loaded value instead of the stack slot and why this is preferable?
thanks,
adrian
Found a similar problem a couple lines down, I think this is the correct fix, but do have a look.
lib/Transforms/Utils/Local.cpp | ||
---|---|---|
1127 ↗ | (On Diff #39028) | Shouldn't the DW_OP_deref be the first instruction in the instruction stream? |
1130 ↗ | (On Diff #39028) | This is definitely the right thing to do here, but I remember adding code to SelectionDAG to recognize the case where a dbg.value describes an alloca and transform the dbg.value to be indirect (this was before we had DIExpression to express this). Found it: SelectionDAGBuilder.cpp:4507 if (N.getNode()) { // A dbg.value for an alloca is always indirect. bool IsIndirect = isa<AllocaInst>(V) || Offset != 0; if (!EmitFuncArgumentDbgValue(V, Variable, Expression, dl, Offset, IsIndirect, N)) { SDV = DAG.getDbgValue(Variable, Expression, N.getNode(), N.getResNo(), IsIndirect, Offset, dl, SDNodeOrder); DAG.AddDbgValue(SDV, N.getNode(), false); } } else if (!V->use_empty() ) { You'll need to update this as well. |
lib/Transforms/Utils/Local.cpp | ||
---|---|---|
1130 ↗ | (On Diff #39028) | Is there any use still for the Offset field of llvm.dbg.value, shouldn't that always be taken care of by DW_OP_bit_piece now? Should I just remove the IsIndirect check completely? |
Sorry, this got buried in my inbox. LGTM with the pending changes mentioned inline.
lib/Transforms/Utils/Local.cpp | ||
---|---|---|
1127 ↗ | (On Diff #39028) | The push_back should happen before the append (probably forgot to update the patch?). |
1130 ↗ | (On Diff #39028) | Yes. I have an open long-term-project to audit all remaining uses of Offset and replace them with DIExpressions and eventually remove the field entirely. Same goes for the IsIndirect flag. |
lib/Transforms/Utils/Local.cpp | ||
---|---|---|
1127 ↗ | (On Diff #39028) | Right, I was waiting to see what to do below. |
1130 ↗ | (On Diff #39028) | No, I think this is the only use. I'll update this patch to remove the AllocaInst case, and we can do the Offset case in a separate commit, making sure that there aren't any test cases which rely on it. |
Ok, this turned out a lot trickier than expected, because some tests were relying on the isIndirect setting for printing correctly (in comments). I updated the comment printing code to account for expressions, which fixed most of that, but there were a few instances in tests where the printed comment disagreed with what was actually in the DWARF (because it wasn't accounting for expressions when printing the comments). I think I fixed most of that, but please take a look at whether everything is still semantically correct. The one test I didn't know what to do with was debug-loc-asan.ll (deleted in this patch to have a full patch that passes tests, but if you let me know how to update it properly, I'll fix it).
Thanks for all the extra work!
there were a few instances in tests where the printed comment disagreed with what was actually in the DWARF
With the recent improvements in llvm-dwarfdump, we can and should just update those testcases to use llc-dwarf | llvm-dwarfdump - --debug-dump=info and check for the expressions.
test/CodeGen/ARM/debug-info-blocks.ll | ||
---|---|---|
2 ↗ | (On Diff #40887) | We should replace this by llc_dwarf | llvm-dwarfdump -debug-dump=info and check for the actual expression there. |
test/DebugInfo/Mips/dsr-fixed-objects.ll | ||
58 ↗ | (On Diff #40887) | where does the extra byte come from? |
58 ↗ | (On Diff #40887) | Where does the extra byte come from? The op_deref? |
test/DebugInfo/X86/reference-argument.ll | ||
6 ↗ | (On Diff #40887) | That comment and the CHECK seem to contradict each other? |
test/DebugInfo/X86/vla.ll | ||
3 ↗ | (On Diff #40887) | Why did you have to remove the check for breg? Ism't the op_deref lowered to one? |
test/DebugInfo/Mips/dsr-fixed-objects.ll | ||
---|---|---|
58 ↗ | (On Diff #40887) | Yeah, the IR was missing an DW_OP_deref. Fixing this, then the DWARF will stay the same. |
test/DebugInfo/X86/reference-argument.ll | ||
6 ↗ | (On Diff #40887) | Not sure what to say about that. Both before and after the change 0x00000101: DW_TAG_formal_parameter [16] DW_AT_location [DW_FORM_block1] (<0x02> 74 00 ) DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000009f] = "v") DW_AT_decl_file [DW_FORM_data1] ("aggregate-indirect-arg.cpp") DW_AT_decl_line [DW_FORM_data1] (22) DW_AT_type [DW_FORM_ref4] (cu + 0x0062 => {0x00000062}) Maybe you can take a look at the radar? |
test/DebugInfo/X86/vla.ll | ||
3 ↗ | (On Diff #40887) | I was mistaken, the DW_OP_breg1 is there. |
The source code that reference-argument.ll was created from is in the debuginfo-tests repository:
class SVal { public: ~SVal() {} const void* Data; unsigned Kind; }; void bar(SVal &v) {} class A { public: void foo(SVal v) { bar(v); } }; int main() { SVal v; v.Data = 0; v.Kind = 2142; A a; a.foo(v); return 0; }
[This IR output is highly questionable, because a function argument is described by an dbg.declare() which is not exactly documented behavior.] Anyway, RSI is carrying the pointer to v, which is a DW_TAG_reference_type, so the comment is correct and it should *not* have an extra DW_OP_deref on it.
It looks like current clang is still generating an DW_OP_deref. I assume the right thing to do here is an dbg.value without the DW_OP_deref? If so I'll update this test case to do that and we should look at clang to change that there as well.
Actually, no, I'm confused !62, has type !9, which is the class, not a reference thereto.
Ah yes. Checking the comments in the assembler output is highly misleading.
I rewrite the test to use llvm-dwarfdump in r255912. Yes, the address should be indirect.
The test still passes if we replace the sketchy dbg.declare with a dbg.value:
call void @llvm.dbg.value(metadata %class.SVal* %v, i64 0, metadata !62, metadata !DIExpression(DW_OP_deref)), !dbg !61
Thanks! Two more inline comments, but otherwise good to go.
lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | ||
---|---|---|
953 ↗ | (On Diff #43217) | This comment is now obsolete. |
lib/Transforms/Utils/Local.cpp | ||
1126 ↗ | (On Diff #43217) | Nitpick: DbgDeclareInst::getExpression() will return an empty DIExpression() and never a nullptr, so the if (DIExpr) should be redundant. |
lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | ||
---|---|---|
4519 ↗ | (On Diff #43217) | Can you remind me why we are ignoring Offset for the indirection flag here but don't on line 957? |
lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | ||
---|---|---|
4519 ↗ | (On Diff #43217) | Because I made a mistake. We should ignore it up there as well. |
Before I commit this, I wanted to point out that this still has the test/DebugInfo/X86/debug-loc-asan.ll test deleted. Thoughts on what to do with that?
Oh right. The correct thing to do would be to recreate the IR from source (assuming that the stuff in Local affects the IR) and update the CHECKs as necessary.
Well, the problem was that running the test case through a recent clang, actually produces very small IR:
; Function Attrs: nounwind sanitize_address uwtable define i32 @_Z3bari(i32 %y) #0 !dbg !4 { entry: %y.addr = alloca i32, align 4 store i32 %y, i32* %y.addr, align 4 call void @llvm.dbg.declare(metadata i32* %y.addr, metadata !11, metadata !12), !dbg !13 %0 = load i32, i32* %y.addr, align 4, !dbg !14 %add = add nsw i32 %0, 2, !dbg !15 ret i32 %add, !dbg !16 }
Ok, I think I figured it out. The first comment in that test case (checking that it comes in a register)
is wrong, because we don't have a dbg.value for that and was based on the incorrect printing of
debug locations in comments (it might be a separate commit to make sure that dbg.value is actually there,
but that's not in the scope for this commit). Then, the CHECK for DEBUG_VALUE was also wrong, because
it's actually a double dereference. Fix that by just removing that check, since we do check the actual
DWARF later down and that's correct.
test/DebugInfo/X86/debug-loc-asan.ll | ||
---|---|---|
12 ↗ | (On Diff #43273) | This comment needs to be updated now. Otherwise this is good! |