<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<p style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: "Calibri", sans-serif">
> When we have <= 3 arguments (I don't want to call them registers because they may turn into constants or memory locations later on) we can use DW_OP_rot to move the one we need to adjust to the top and the DW_OP_rot the stack back into the original order.
 For 4-255 arguments, we need to add extra operations both to the beginning and the end of the expression, here an example for salvaging the 4th element from the top:</p>
<p style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: "Calibri", sans-serif">
<o:p> </o:p></p>
<p style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: "Calibri", sans-serif">
That example is how I'd imagine DW_OP_pick/DW_OP_LLVM_register to be used. Personally I'm of the opinion that although we can use DW_OP_rot for cases with arguments <= 3, it would be better to use DW_OP_pick in those cases. One reason is consistency; the other
 is that as you mentioned, the expressions can get rather long, and this gets worse if we start by using DW_OP_rot and then switch to DW_OP_pick. For example if we have (assuming the first arg is on top of the stack):</p>
<p style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: "Calibri", sans-serif">
<o:p> </o:p></p>
<p style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: "Calibri", sans-serif">
<span style="font-family: Consolas, Courier, monospace;">%c = add %e, %f</span></p>
<p style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: "Calibri", sans-serif">
<span style="font-family: Consolas, Courier, monospace;">%b = div %d, 7</span></p>
<p style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: "Calibri", sans-serif">
<span style="font-family: Consolas, Courier, monospace;">dv(!DIExpression(DW_OP_plus, DW_OP_mul), %a, %b, %c)</span><span style="font-family: Consolas, Courier, monospace;">                                             
</span><span style="font-family: Consolas, Courier, monospace;">; Short and sweet</span></p>
<p style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: "Calibri", sans-serif">
<span style="font-family: Consolas, Courier, monospace;">dv(!DIExpression(DW_OP_pick, 2, DW_OP_pick, 1, DW_OP_pick, 0, DW_OP_plus, DW_OP_mul), %a, %b, %c) ; Verbose</span></p>
<p style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: "Calibri", sans-serif">
<span style="font-family: Consolas, Courier, monospace;">; Salvage %b</span></p>
<p style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: "Calibri", sans-serif">
<span style="font-family: Consolas, Courier, monospace;">dv(!DIExpression(DW_OP_rot, DW_OP_constu, 7, DW_OP_div, DW_OP_rot, DW_OP_rot, DW_OP_plus, DW_OP_mul), %a, %d, %c)</span><span style="font-family: Consolas, Courier, monospace;">            
</span><span style="font-family: Consolas, Courier, monospace;">; Suddenly a lot longer</span></p>
<p style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: "Calibri", sans-serif">
<span style="font-family: Consolas, Courier, monospace;">dv(!DIExpression(DW_OP_pick, 2, DW_OP_pick, 1, DW_OP_constu, 7, DW_OP_div, DW_OP_pick, 0, DW_OP_plus, DW_OP_mul), %a, %d, %c) ; Still longer, but not by as much</span></p>
<p style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: "Calibri", sans-serif">
<span style="font-family: Consolas, Courier, monospace;">; Salvage %c</span></p>
<p style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: "Calibri", sans-serif">
<span style="font-family: Consolas, Courier, monospace;">dv(!DIExpression(DW_OP_pick, 2, DW_OP_pick, 3, DW_OP_plus, DW_OP_pick, 1, DW_OP_pick, 0, DW_OP_rot, DW_OP_constu, 7, DW_OP_div, DW_OP_rot, DW_OP_rot, DW_OP_plus, DW_OP_mul), %a, %d, %e, %f)</span><span style="font-family: Consolas, Courier, monospace;"> 
</span><span style="font-family: Consolas, Courier, monospace;">; Sudden conversion to use DW_OP_pick; now necessary to pick every argument, while still using DW_OP_rot</span></p>
<p style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: "Calibri", sans-serif">
<span style="font-family: Consolas, Courier, monospace;">dv(!DIExpression(DW_OP_pick, 2, DW_OP_pick, 3, DW_OP_plus, DW_OP_pick, 1, DW_OP_constu, 7, DW_OP_div, DW_OP_pick, 0, DW_OP_plus, DW_OP_mul), %a, %d, %e, %f)</span><span style="font-family: Consolas, Courier, monospace;">                                  
</span><span style="font-family: Consolas, Courier, monospace;">; Now shorter, due to not containing DW_OP_rot</span></p>
<p style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: "Calibri", sans-serif">
<o:p><span style="font-family: Consolas, Courier, monospace;"> </span></o:p></p>
<p style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: "Calibri", sans-serif">
We could avoid this sudden growth in expression length by having salvage debug info attempt to remove the use of DW_OP_rot, but this would make salvaging more complicated as it would need to cover the cases where we:</p>
<p style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: "Calibri", sans-serif">
<o:p> </o:p></p>
<p style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: "Calibri", sans-serif">
1. Salvage a simple expression that doesn't need rotating or picking: prepend salvage instructions.</p>
<p style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: "Calibri", sans-serif">
2. Salvage a simple expression that now needs rotation: insert 3x DW_OP_rot, insert salvage instructions at some point in the middle.</p>
<p style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: "Calibri", sans-serif">
3. Salvage an expression with rotation: determine where salvage instructions need to go and place them.</p>
<p style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: "Calibri", sans-serif">
4. Salvage an expression with rotation that now needs picking: insert DW_OP_pick for each arg, move salvages from the middle of DW_OP_rot to DW_OP_pick, remove DW_OP_rot.</p>
<p style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: "Calibri", sans-serif">
5. Salvage an expression with picking: append salvage instructions to the relevant DW_OP_pick operator.</p>
<p style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: "Calibri", sans-serif">
<o:p> </o:p></p>
<p style="margin: 0cm 0cm 0.0001pt; font-size: 11pt; font-family: "Calibri", sans-serif">
I think the best solution is the one where we keep the "always on the stack" behaviour, so that we can avoid using DW_OP_pick where it doesn't do anything useful (as in the first case in the example), while keeping salvageDebugInfo simple.</p>
<br>
</div>
<div id="appendonsend"></div>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> aprantl@apple.com <aprantl@apple.com> on behalf of Adrian Prantl <aprantl@apple.com><br>
<b>Sent:</b> 25 February 2020 17:06<br>
<b>To:</b> Tozer, Stephen <stephen.tozer@sony.com><br>
<b>Cc:</b> David Blaikie <dblaikie@gmail.com>; Jonas Devlieghere <jdevlieghere@apple.com>; Robinson, Paul <paul.robinson@sony.com>; Eric Christopher <echristo@gmail.com>; llvm-dev@lists.llvm.org <llvm-dev@lists.llvm.org><br>
<b>Subject:</b> Re: [llvm-dev] [RFC] Allowing debug intrinsics to reference multiple SSA Values</font>
<div> </div>
</div>
<div class="BodyFragment"><font size="2"><span style="font-size:11pt;">
<div class="PlainText"><br>
<br>
> On Feb 25, 2020, at 8:39 AM, Tozer, Stephen <stephen.tozer@sony.com> wrote:<br>
> <br>
>> As the person who has advocated for DW_OP_LLVM_arg(N) before, my main motivation was to resolve the ambiguity of constant DIExpressions: As a worst-case example:<br>
>> <br>
>> dbg.value(%undef, !DILocalVariable(x), DIExpression(DW_OP_constu, 42))<br>
>> <br>
>> Is this undefined, or constant 42?<br>
>> <br>
>> But if we make dbg.value fully variadic with all parameters pushed to the stack ahead of time, we can distinguish between<br>
>> <br>
>> dbg.value(!DILocalVariable(x), DIExpression(DW_OP_constu, 42)) ; a constant<br>
>> dbg.value(i32 42, !DILocalVariable(x), DIExpression()) ; the same constant dbg.value(%undef, !DILocalVariable(x), DIExpression(DW_OP_constu, 42)) ; undef + garbage leftover expression<br>
>> <br>
>> If we do it this way and allow 0-n SSA values then I'm in support of the push-first scheme.<br>
> <br>
> This seems like as good a case as any to go with the push-first approach, since it solves a meaningful problem that the alternative does not.
<br>
> <br>
>> As a side note, updating dbg.values in salvageDebugInfo when we allow multiple SSA values per dbg.value will be interesting, but possible. We'll need to put the value we need to update at the top of the stack, prepend the salvage expression and then restore
 the order of arguments on the stack that the rest of the expression expects.<br>
> <br>
> The difficulty here is that in DWARF5, there is no operator that can move an argument up the stack; there are specific operators that rotate the top 2 or 3 elements, but outside of that the only thing you can do is copy an element to the top with DW_OP_pick.
 Of course we don't have to stick to actual DWARF operators by any means, but I don't think there's any way to eventually express an indexed swap/move operator in DWARF either: you can duplicate an element from anywhere on the stack to the top, but you can't
 delete the original element or move the top element back down again. Because of this, it is necessary (I believe) to use DW_OP_pick in the general case even if all the arguments are initially pushed onto the stack, due to the limits on how we can manipulate
 the stack. Of course there are many expressions that don't require DW_OP_pick to evaluate, but for consistency's sake I think it's best to use it instead of the swap or rotate operators whenever any of them is needed.<br>
> <br>
> Regardless of whether we push everything immediately or not, having an operator that pushes the SSA value at a given argument index onto the stack seems necessary - if we push elements initially then DW_OP_pick (or DW_OP_LLVM_pick), otherwise DW_OP_LLVM_register.
 In either of these cases, salvaging is simple: we simply append the salvage expression after the salvaged value's operator. It also translates cleanly to DWARF, since we can directly replace the operator in question with DW_OP_regval_type, using whichever
 register holds the value we're looking for as an argument, without needing to modify or even consider the rest of the expression at all.<br>
> <br>
<br>
When we have <= 3 arguments (I don't want to call them registers because they may turn into constants or memory locations later on) we can use DW_OP_rot to move the one we need to adjust to the top and the DW_OP_rot the stack back into the original order. For
 4-255 arguments, we need to add extra operations both to the beginning and the end of the expression, here an example for salvaging the 4th element from the top:<br>
<br>
r0 r1 r2 r3    ; stack before<br>
DW_OP_pick 0  <br>
<br>
r0 r1 r2 r3 r0 ; stack after pick 0 ...<br>
<adjustments>  ; the salvage operations for r0<br>
<br>
r0 r1 r2 r3 r0'<br>
DW_OP_pick 1<br>
<br>
r0 r1 r2 r3 r0' r1<br>
DW_OP_pick 2<br>
<br>
r0 r1 r2 r3 r0' r1 r2<br>
DW_OP_pick 3<br>
<br>
r0 r1 r2 r3 r0' r1 r2 r3<br>
<rest of expression><br>
<br>
r0 r1 r2 r3 result<br>
DW_OP_swap<br>
<br>
r0 r1 r2 result r3<br>
DW_OP_drop<br>
<br>
r0 r1 r2 result<br>
DW_OP_swap<br>
<br>
r0 r1 result r2<br>
DW_OP_drop<br>
DW_OP_rot<br>
DW_OP_drop<br>
DW_OP_drop<br>
<br>
result<br>
<br>
It's possible to do with just DWARF expressions, but the resulting expression may get a little long. We could also just say we support up to 3 arguments and that would probably be fine.<br>
<br>
-- adrian<br>
<br>
</div>
</span></font></div>
</body>
</html>