<div dir="ltr"><br><br><div class="gmail_quote"><div dir="ltr">On Fri, Nov 18, 2016 at 10:23 AM Adrian Prantl <<a href="mailto:aprantl@apple.com">aprantl@apple.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg">On Nov 18, 2016, at 10:10 AM, David Blaikie <<a href="mailto:dblaikie@gmail.com" class="gmail_msg" target="_blank">dblaikie@gmail.com</a>> wrote:</div><br class="m_-360619637060269178Apple-interchange-newline gmail_msg"><div class="gmail_msg"><div dir="ltr" class="gmail_msg"><br class="gmail_msg"><br class="gmail_msg"><div class="gmail_quote gmail_msg"><div dir="ltr" class="gmail_msg">On Fri, Nov 18, 2016 at 10:00 AM Adrian Prantl <<a href="mailto:aprantl@apple.com" class="gmail_msg" target="_blank">aprantl@apple.com</a>> wrote:<br class="gmail_msg"></div><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg">On Nov 18, 2016, at 9:51 AM, David Blaikie <<a href="mailto:dblaikie@gmail.com" class="gmail_msg" target="_blank">dblaikie@gmail.com</a>> wrote:</div><br class="m_-360619637060269178m_-1174602213539823603Apple-interchange-newline gmail_msg"><div class="gmail_msg"><div dir="ltr" class="gmail_msg">Would it be reasonable/useful to add another level of indirection while we're here - that would describe which part of the variable is being described by this location:<br class="gmail_msg"><br class="gmail_msg">DIGlobalVariableExpr(value: DW_OP_const 42) -> DIGlobalVariableFragment(offset: 32 bits) -> DIGlobalVariable(name: foo)<br class="gmail_msg"><br class="gmail_msg">(just guessing/pretending there's a DW_OP_const for constant values - I forget how it all works, but purely for demonstration purposes)<br class="gmail_msg"><br class="gmail_msg">That way code manipulating DIGlobalVariableExprs wouldn't need to have explicit knowledge of which part of the variable is being described here. (I suppose that could end up with us creating a bottom-up expression tree in metadata, which probably isn't ideal (too heavyweight))<br class="gmail_msg"></div></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">The nice thing about the Dwarf expressions being a stack-based post-fix-notated programming language is that it you can compose functions by simply concatenating them. The typical kind of manipulations that we do (for example, adding an "add offset", "dereference" operation) can done by simply putting the new expression in front of the old expression. I don't think it can get much simpler than that :-)</div></div></div></blockquote><div class="gmail_msg"><br class="gmail_msg">Wouldn't the piece/bit_piece need to go on top level of the expression tree? I don't think you can simply concatenate things on top of it... <br class="gmail_msg"></div></div></div></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">The expression tree of a stack-based postfix language degenerates to a list. The works in the language can consume a different number of stack arguments, but under the assumption that one well-formed DIExpression takes and produces exactly one value (which is true for all non-constant expressions we support), it is safe to concatenate the expressions.</div></div></div></blockquote><div><br></div><div>But what does this mean to the DWARF consumer? All the examples in the spec seem to show DW_OP_(bit_)piece at the top level of the expression (once the expression stack is evaluated, it may have several DW_OP_(bit_)piece remaining on the stack - and they're all read, oldest to newest (bottom to top of the stack) as descriptions of portions of the variable)</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><div dir="ltr" class="gmail_msg"><div class="gmail_quote gmail_msg"><div class="gmail_msg"><br class="gmail_msg">Oh, also, DW_OP_bit_piece is ordered, judging by the examples in the spec:<br class="gmail_msg"><br class="gmail_msg">DW_OP_reg3 DW_OP_piece 4 DW_OP_reg10 DW_OP_piece 2<br class="gmail_msg"> A variable whose first four bytes reside in register 3 and whose next
two bytes reside in register 10. <br class="gmail_msg"><br class="gmail_msg">So how do we know which DIGlobalVariableExpr goes first? Or if there are holes between exprs?<br class="gmail_msg"><br class="gmail_msg">(am I making sense? not sure - I can try to explain differently, or perhaps just not understanding)<br class="gmail_msg"></div></div></div></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">Please let me know if I'm missing the point. I think there may be some confusion about how multi-piece values are represented in LLVM Metadata.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">One DIExpression only ever represents one DW_OP_piece (with the DW_OP_piece always being the very last element of the expression). To represent a variable with multiple pieces, we use two DIExpression. For example (extracted from the split-global.ll testcase):</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">; struct { int x,y; } Point;</div><div class="gmail_msg"><div class="gmail_msg">@point.x = global i32 1, align 4, !dbg !12</div><div class="gmail_msg">@point.y = global i32 2, align 4, !dbg !13</div><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">!0 = distinct !DIGlobalVariable(name: "point", scope: !1, file: !2, line: 1, type: !5, isLocal: false, isDefinition: true)</div><div class="gmail_msg">!12 = !DIGlobalVariableExpression(var: !0,  expr: !DIExpression(DW_OP_bit_piece,  0, 32))</div><div class="gmail_msg">!13 = !DIGlobalVariableExpression(var: !0,  expr: !DIExpression(DW_OP_bit_piece, 32, 32))</div></div></div></div></div></blockquote><div><br>I think this DWARF is wrong/doesn't make sense. DW_OP_bit_piece's two operands refer to the offset within the previous value on the stack (in this case, the previous/initial value on the stack is implied as the location of the respective globals, @point.x and @point.y). So !13 is invalid DWARF - it says "this piece starts 32 bits into a 32 bit region and is 32 bits long" - which is entirely outside the region.<br><br>"The DW_OP_bit_piece operation takes two operands. The first is an unsigned LEB128
number that gives the size in bits of the piece. The second is an unsigned LEB128 number
that gives the offset in bits from the location defined by the preceding DWARF location
description. "<br><br>The DWARF expression to describe the location of that variable split in two would be:<br><br>DW_OP_addr <addr of @point.x> DW_OP_piece 4 DW_OP_addr <addr of @point.y> DW_OP_piece 4<br><br>Or, if you wanted to use OP_bit_piece, they would each be "DW_OP_bit_piece 32 0".<br><br><br> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">The DWARF backend collects all the DIGlobalVariableExpressions and their respective GlobalVariables and translates this into a single location:</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><div class="gmail_msg">DW_AT_location ([0x0000000000000000], piece 0x00000004, [0x0000000000000004], bit-piece 32 32)</div></div><div class="gmail_msg">                            @point.x, !12, @point.y, !13.</div></div></div></div></blockquote><div><br>I believe this DWARF describes a location consisting of the range ([0x0000, 0x0004), [0x0008, 0x00012)) which is probably not intended.<br><br>The example in <a href="http://2.6.1.3">2.6.1.3</a>:<br><br>DW_OP_reg3 DW_OP_piece 4 DW_OP_reg10 DW_OP_piece 2<br>  A variable whose first four bytes reside in register 3 and whose next
two bytes reside in register 10. <br><br>The pieces are considered to fill the variable left to right.<br><br>& the wording for op_bit_piece says that the offset refers to the location previous in the stack - not about where that fragment goes in the resulting variable.<br><br>"The DW_OP_bit_piece operation takes two operands. The first is an unsigned LEB128
number that gives the size in bits of the piece. The second is an unsigned LEB128 number
that gives the offset in bits from the location defined by the preceding DWARF location
description. "<br> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">does that make sense?</div></div></div></div><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">-- adrian</div></div></div></div><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><div dir="ltr" class="gmail_msg"><div class="gmail_quote gmail_msg"><div class="gmail_msg"> </div></div></div></div></blockquote><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><div dir="ltr" class="gmail_msg"><div class="gmail_quote gmail_msg"><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">--- adrian</div></div></div><div style="word-wrap:break-word" class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><div dir="ltr" class="gmail_msg"><br class="gmail_msg">Perhaps keeping the bit_piece parts out of the DWARF expression bytes and in a separate field of the DIGlobalVariableExpr?<br class="gmail_msg"><br class="gmail_msg">DIGlobalVariableExpr(offset: 32, value: DW_OP_const 42)<br class="gmail_msg"><br class="gmail_msg">Then at least when a variable moves around (does that happen? maybe? - I suppose something like asan, smooshing everything into a single alloca would move something around without splitting it up) the expression can be updated relatively simply without unpacking through a DW_OP_bit_piece, etc?<br class="gmail_msg"><br class="gmail_msg">Maybe this doesn't matter - Ih aven't looked at much of the expression/location handling code.</div><br class="gmail_msg"><div class="gmail_quote gmail_msg"><div dir="ltr" class="gmail_msg">On Fri, Nov 18, 2016 at 9:32 AM Adrian Prantl <<a href="mailto:aprantl@apple.com" class="gmail_msg" target="_blank">aprantl@apple.com</a>> wrote:<br class="gmail_msg"></div><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">aprantl removed rL LLVM as the repository for this revision.<br class="gmail_msg">
aprantl updated this revision to Diff 78544.<br class="gmail_msg">
aprantl added a comment.<br class="gmail_msg">
<br class="gmail_msg">
Improved type-safety by adding a DIGlobalVarExpr pointer union.<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
<a href="https://reviews.llvm.org/D26769" rel="noreferrer" class="gmail_msg" target="_blank">https://reviews.llvm.org/D26769</a><br class="gmail_msg">
<br class="gmail_msg">
Files:<br class="gmail_msg">
  include/llvm/Bitcode/LLVMBitCodes.h<br class="gmail_msg">
  include/llvm/IR/DIBuilder.h<br class="gmail_msg">
  include/llvm/IR/DebugInfo.h<br class="gmail_msg">
  include/llvm/IR/DebugInfoMetadata.h<br class="gmail_msg">
  include/llvm/IR/GlobalVariable.h<br class="gmail_msg">
  include/llvm/IR/Metadata.def<br class="gmail_msg">
  lib/Analysis/ModuleDebugInfoPrinter.cpp<br class="gmail_msg">
  lib/AsmParser/LLParser.cpp<br class="gmail_msg">
  lib/Bitcode/Reader/BitcodeReader.cpp<br class="gmail_msg">
  lib/Bitcode/Writer/BitcodeWriter.cpp<br class="gmail_msg">
  lib/CodeGen/AsmPrinter/CodeViewDebug.cpp<br class="gmail_msg">
  lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp<br class="gmail_msg">
  lib/CodeGen/AsmPrinter/DwarfCompileUnit.h<br class="gmail_msg">
  lib/CodeGen/AsmPrinter/DwarfDebug.cpp<br class="gmail_msg">
  lib/IR/AsmWriter.cpp<br class="gmail_msg">
  lib/IR/DIBuilder.cpp<br class="gmail_msg">
  lib/IR/DebugInfo.cpp<br class="gmail_msg">
  lib/IR/DebugInfoMetadata.cpp<br class="gmail_msg">
  lib/IR/LLVMContextImpl.h<br class="gmail_msg">
  lib/IR/Metadata.cpp<br class="gmail_msg">
  lib/IR/Verifier.cpp<br class="gmail_msg">
  lib/Transforms/IPO/StripSymbols.cpp<br class="gmail_msg">
  lib/Transforms/Instrumentation/AddressSanitizer.cpp<br class="gmail_msg">
  test/Assembler/diglobalvariable.ll<br class="gmail_msg">
  test/Assembler/diglobalvariableexpression.ll<br class="gmail_msg">
  test/Bitcode/DIGlobalVariableExpr.ll<br class="gmail_msg">
  test/Bitcode/DIGlobalVariableExpr.ll.bc<br class="gmail_msg">
  test/Bitcode/diglobalvariable-3.8.ll<br class="gmail_msg">
  test/Bitcode/diglobalvariable-3.8.ll.bc<br class="gmail_msg">
  test/DebugInfo/X86/multiple-at-const-val.ll<br class="gmail_msg">
  test/DebugInfo/X86/pr12831.ll<br class="gmail_msg">
  test/DebugInfo/X86/split-global.ll<br class="gmail_msg">
  test/DebugInfo/X86/stack-value-dwarf4.ll<br class="gmail_msg">
  test/DebugInfo/X86/unattached-global.ll<br class="gmail_msg">
  test/Transforms/GlobalMerge/debug-info.ll<br class="gmail_msg">
  unittests/IR/MetadataTest.cpp<br class="gmail_msg">
<br class="gmail_msg">
</blockquote></div>
</div></blockquote></div></div></blockquote></div></div>
</div></blockquote></div></div></blockquote></div></div>