<html><head><meta http-equiv="Content-Type" content="text/html; charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Sep 16, 2020, at 9:55 AM, Tozer, Stephen <<a href="mailto:stephen.tozer@sony.com" class="">stephen.tozer@sony.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta charset="UTF-8" class=""><div style="font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt;" class="">> That makes sense, and I think for "direct" values in your definition it is true that all direct values are r-values.</div><div style="font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt;" class="">> Why do we need DW_OP_LLVM_direct when we already have DW_OP_LLVM_stack_value? Can you give an example of something that is definitely not a stack value, but direct?<br class=""></div><div style="font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt;" class=""><br class=""></div><div style="font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt;" class="">The difference in definition is the intention: DW_OP_LLVM_direct means "we'd like this to be an l-value if possible", DW_OP_stack_value means "this should never be an l-value". Because of this, an expression ending with DW_OP_LLVM_direct can be emitted as an l-value in any case where the value of the preceding expression is equal to an l-value. So for example:</div><div style="font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt;" class=""><br class=""></div><div style="font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt;" class=""><span style="font-family: Consolas, Courier, monospace;" class="">  DBG_VALUE $rsp, !"x", !DIExpression(DW_OP_LLVM_direct) => DW_OP_reg7 RSP</span><div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt;" class=""><span style="font-family: Consolas, Courier, monospace;" class="">  DBG_VALUE $rsp, !"x", !DIExpression(DW_OP_deref, DW_OP_LLVM_direct) => DW_OP_breg7 RSP+0</span><div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt;" class=""><span style="font-family: Consolas, Courier, monospace;" class="">  DBG_VALUE $rsp, !"x", !DIExpression(DW_OP_plus_uconst, 4, DW_OP_LLVM_direct) => DW_OP_breg7 RSP+4, DW_OP_stack_value</span><br class=""></div></div><br class=""></div><div style="font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt;" class="">Your point about the semantics of variable assignments in the debugger is useful, that clears up my misunderstandings. I believe that even with that in mind, LLVM_direct (or whatever name it takes) would be appropriate. If we recognize that a variable must be read-only to preserve those semantics, then we can use DW_OP_stack_value to ensure that it is always an r-value. If we don't have any reason to make a variable read-only other than that we can't *currently* find an l-value location for it, then we would use DW_OP_LLVM_direct. Right now we use DW_OP_stack_value whenever we make a complex expression, but that doesn't need to be the case.<br class=""></div></div></blockquote><div><br class=""></div><div>Great! It sounds like we reached mutual understanding :-)</div><br class=""><blockquote type="cite" class=""><div class=""><div style="font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt;" class=""><br class=""></div><div style="font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt;" class="">The code below is an example program where we may eventually be able to generate a valid l-value for the variable "a" in foo(), but can't without an alternative to DW_OP_stack_value. At the end of the example, "a" is an r-value, but doesn't need to be: there is a single register that holds its exact value, and an assignment to that register would have the same semantics as an equivalent assignment to "a" in the source. The optimizations taking place in this code are analogous to if we had "a = bar() + 4 - 4;", but because we don't figure out that "a = bar()" in a single pass, we pre-emptively assume that "a" must be an r-value.<br class=""><div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt;" class=""><br class=""></div><div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt;" class="">To be able to emit an l-value we would first need the ability to optimize/simplify DIExpressions so that the expression becomes just (DW_OP_stack_value) - this wouldn't be particularly difficult to implement for simple arithmetic. Even with this improvement, the definition of DW_OP_stack_value explicitly forbids the expression from being a register location. If we instead used DW_OP_LLVM_direct, then we would be free to emit the register location<span class="Apple-converted-space"> </span><span style="font-family: Consolas, Courier, monospace;" class="">(</span><span style="font-family: Consolas, Courier, monospace;" class="">DW_OP_reg0 RAX)</span><span style="font-family: "Segoe UI", "Helvetica Neue", sans-serif;" class="">.</span></div></div><div style="font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt;" class=""><br class=""></div><div style="font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt;" class=""><span style="font-family: Consolas, Courier, monospace;" class="">  // Compile with clang -O2 -g<br class=""></span></div><div style="font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt;" class=""><span style="font-family: Consolas, Courier, monospace;" class="">  int baz();</span><div class=""><span style="font-family: Consolas, Courier, monospace;" class="">  int bar2(int arg) {</span></div><div class=""><span style="font-family: Consolas, Courier, monospace;" class="">    return arg * 4;</span></div><div class=""><span style="font-family: Consolas, Courier, monospace;" class="">  }</span></div><div class=""><span style="font-family: Consolas, Courier, monospace;" class="">  int bar() {</span></div><div class=""><span style="font-family: Consolas, Courier, monospace;" class="">    return bar2(1);</span></div><span style="font-family: Consolas, Courier, monospace;" class="">  }</span><br class=""></div><div style="font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt;" class=""><span style="font-family: Consolas, Courier, monospace;" class="">  int foo() {</span><span style="font-family: Consolas, Courier, monospace;" class=""><div class=""><span style="font-family: Consolas, Courier, monospace;" class="">    int a = baz() + bar() - 4;</span></div><div class="">    return a * 2;</div>  }</span></div><div style="font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt;" class=""><span style="font-family: Consolas, Courier, monospace;" class=""><br class=""></span></div><div style="font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt;" class=""><span style="font-family: Consolas, Courier, monospace;" class="">; Eventually becomes the IR...</span></div><div style="font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt;" class=""><span style="font-family: Consolas, Courier, monospace;" class="">  %call = call i32 @_Z3bazv(), !dbg !25</span><div class=""><span style="font-family: Consolas, Courier, monospace;" class="">  %call1 = call i32 @_Z3barv(), !dbg !26</span></div><div class=""><span style="font-family: Consolas, Courier, monospace;" class="">  %add = add nsw i32 %call, %call1, !dbg !27</span></div><div class=""><span style="font-family: Consolas, Courier, monospace;" class="">  %sub = sub nsw i32 %add, 4, !dbg !28</span></div><span style="font-family: Consolas, Courier, monospace;" class="">  call void @llvm.dbg.value(metadata i32 %sub, metadata !24, metadata !DIExpression()), !dbg !29<br class=""><div class="">  %mul = mul nsw i32 %sub, 2, !dbg !30</div>  ret i32 %mul, !dbg !31</span></div><div style="font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt;" class=""><span style="font-family: Consolas, Courier, monospace;" class=""><br class=""></span></div><div style="font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt;" class=""><span style="font-family: Consolas, Courier, monospace;" class="">; Combine redundant instructions, "a" is salvaged...</span></div><div style="font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt;" class=""><span style="font-family: Consolas, Courier, monospace;" class="">  %call = call i32 @_Z3bazv(), !dbg !25<div class="">  %call1 = call i32 @_Z3barv(), !dbg !26</div><div class="">  %add = add nsw i32 %call, %call1, !dbg !27</div>  call void @llvm.dbg.value(metadata i32 %add, metadata !24, metadata !DIExpression(DW_OP_constu, 4, DW_OP_minus, DW_OP_stack_value)), !dbg !28<br class=""><div class="">  %sub = shl i32 %add, 1, !dbg !29</div><div class="">  %mul = add i32 %sub, -8, !dbg !29</div>  ret i32 %mul, !dbg !30</span></div><div style="font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt;" class=""><span style="font-family: Consolas, Courier, monospace;" class=""> <span class="Apple-converted-space"> </span><br class=""></span></div><div style="font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt;" class=""><span style="font-family: Consolas, Courier, monospace;" class="">; bar() is found to always return 4<br class=""><div class="">  %call = call i32 @_Z3bazv(), !dbg !14</div><div class="">  %add = add nsw i32 %call, 4, !dbg !15</div><div class="">  call void @llvm.dbg.value(metadata i32 %add, metadata !13, metadata !DIExpression(DW_OP_constu, 4, DW_OP_minus, DW_OP_stack_value)), !dbg !16</div><div class="">  %sub = shl i32 %add, 1, !dbg !17</div><div class="">  %mul = add i32 %sub, -8, !dbg !17</div>  ret i32 %mul, !dbg !18<div class=""></div><div class=""><br class=""></div><div class="">; %add is unused, optimize out and salvage...</div><div class=""></div>  %call = call i32 @_Z3bazv(), !dbg !24<div class="">  call void @llvm.dbg.value(metadata i32 %call, metadata !23, metadata !DIExpression(DW_OP_plus_uconst, 4, DW_OP_constu, 4, DW_OP_minus, DW_OP_stack_value)), !dbg !25</div><div class="">  %add = shl i32 %call, 1, !dbg !26</div><div class="">  ret i32 %add, !dbg !27</div><div class=""><br class=""></div><div class="">  ; Final DWARF location for "a":</div><div class="">  DW_AT_location        (0x00000000:<br class=""></div><div class="">      [0x0000000000000029, 0x000000000000002b): DW_OP_breg0 RAX+4, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_lit4, DW_OP_minus, DW_OP_stack_value)</div></span></div></div></blockquote><br class=""></div><div>So in this example, if we had DW_OP_LLVM_direct, we would salvage "a" as</div><div><br class=""></div><div>DIExpression(DW_OP_constu, 4, DW_OP_minus, DW_OP_LLVM_direct) ?</div><div><br class=""></div><div>which would mean: "this is an l-value with some additional DWARF operations. The backend should either emit this as a DW_OP_stack_value, or if the DWARF expression turns out to be a no-op, drop the entire DIExpression and emit this as a register or memory location.".</div><div>I can see how that could potentially be useful. I'm not sure how often we could practically make use of a situation like this, but I understand your motivation.</div><br class=""><div class="">If we had DW_OP_LLVM_direct: what would be the semantics of </div><div class=""><br class=""></div><div class="">DIExpression(DW_OP_constu, 4, DW_OP_minus, DW_OP_LLVM_direct)</div><div class=""><br class=""></div><div class="">versus</div><div class=""><br class=""></div><div class="">DIExpression(DW_OP_constu, 4, DW_OP_minus) ?</div><div class=""><br class=""></div><div class="">thanks,</div><div class="">adrian</div></body></html>