Thank you for the reply!
The WebAssembly example I’m not as familiar with, but I believe it is handling a specific case, making assumptions that do not hold for the general case.
To be clear, WebAssemblyDebugValueManager
is something we wrote, and I’d like to fix it if that’s not correct. The reason I asked about it was I was not sure if that was the correct way to gather DBG_VALUE
s associated with an instruction. You said it was an ‘exception’, then what would be a non-exceptional, or more conventional, way to do it? What assumptions does it have that do not hold for the general case?
The general problem you refer to of tracking the registers/stack slots referred to by a debug value is relatively complicated, but the general approach is that after instruction selection, the values produced by instructions will be in virtual registers, which will not be overwritten or killed. Immediately after register allocation converts these to physical registers and stack slots, LiveDebugValues steps in and performs an analysis to track values moving through machine locations and/or being dropped, producing new debug values as needed after each move. In short, most passes prior to regalloc should generally be able to just follow the rules above, though as mentioned there are exceptions.
Even in the virtual register + SSA mode, once a def is separated from its DBG_VALUE
s, I’m not sure how to reconnect them or reflect the def’s changes to those DBG_VALUE
s. Even if a register is only set once, I don’t think I can guarantee that in the BB that DBG_VALUE
s exist, that register has been set on all paths leading up to that BB. I’ll give an example below.
Hopefully this helps, but if you can give a more specific example of what you’re trying to do, then I’d be happy to answer/explain more specifically what’s happening and what should happen with debug values.
For example, if there’s a BB like this,
bb.1:
…
%5 = SOME INST
DBG_VALUE %5, …
DBG_VALUE %5, …
And after some optimization, the %5
’s defining instruction is hoisted to another BB:
pre:
…
%5 = SOME INST
…
bb.1:
…
DBG_VALUE %5, …
DBG_VALUE %5, …
…
As we talked about, those DBG_VALUE
s are not supposed to be hoisted with SOME INST
. Now %5
’s definition and its DBG_VALUE
s are separated across BBs. Then in a later pass, if we want to change %5 = SOME INST
’s register to %8
, I don’t think we can change its DBG_VALUE %5
s, which are now in bb.1
, to DBG_VALUE %8
, because there can be a path to bb.1
that doesn’t encounter pre
BB and we can’t guarantee %8
’s value always contains the same thing in all paths leading up to bb.1
.
This is what an optimization can cause, but this kind of “separated” def and DBG_VALUE
happen even right after instruction selection, because the bitcode is already that way. One example I found from a small program is, before instruction selection, this llvm.dbg.value
is not in the same BB as its def in the first place, and it’s hard to even pinpoint which instruction is its corresponding def:
if.end19: ; preds = %if.then17, %for.body
%conv.i36 = and i32 %c.044, 255, !dbg !118
call void @llvm.dbg.value(metadata i32 %c.044, metadata !88, metadata !DIExpression()), !dbg !121
…
After instruction selection, this becomes DBG_VALUE %6
, and we don’t know where that %6
’s def is:
bb.12.if.end19:
; predecessors: %bb.10, %bb.11
successors: %bb.14(0x04000000), %bb.13(0x7c000000); %bb.14(3.12%), %bb.13(96.88%)
%48:i32 = CONST_I32 255, implicit-def dead $arguments
%49:i32 = AND_I32 %6:i32, killed %48:i32, implicit-def dead $arguments, debug-location !120; wc.c:67:19 @[ wc.c:100:10 ]
DBG_VALUE %6:i32, $noreg, !"c", !DIExpression(), debug-location !123; wc.c:0 @[ wc.c:100:10 ] line no:65
…
So in these cases, once DBG_VALUE
s are separated (sometimes rightfully, as in case of hoisting) from its def, I’m not sure how to reflect changes to the def to those DBG_VALUE
s.