<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=""><blockquote type="cite" class="">On Aug 23, 2018, at 1:43 PM, David Blaikie <<a href="mailto:dblaikie@gmail.com" class="">dblaikie@gmail.com</a>> wrote:<br class=""></blockquote><div><blockquote type="cite" class=""><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class=""><br class=""><br class=""><div class="gmail_quote"><div dir="ltr" class="">On Thu, Aug 23, 2018 at 1:00 PM Vedant Kumar <<a href="mailto:vsk@apple.com" class="">vsk@apple.com</a>> wrote:<br class=""></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;line-break:after-white-space" class=""><div class=""><br class=""><blockquote type="cite" class=""><div class="">On Aug 23, 2018, at 12:22 PM, David Blaikie <<a href="mailto:dblaikie@gmail.com" target="_blank" class="">dblaikie@gmail.com</a>> wrote:</div><br class="m_-6594410101962813587Apple-interchange-newline"><div class=""><div dir="ltr" class="">+all the usual debugger folks<font color="#3367d6" class=""><u class=""><br class=""></u></font><br class="">I reckon adding nops would be a pretty unfortunate way to go in terms of code size, etc, if we could help it. One alternative that might work and we've tossed it around a bit - is emitting more accurate "is_stmt" flags. In your first example, the is_stmt flag could be set on the bar() call instruction - and any breakpoint set on an instruction that isn't "is_stmt" could instead set a breakpoint on the statement that covers that instruction (the nearest previous is_stmt instruction*)<br class=""></div></div></blockquote><div class=""><br class=""></div></div></div><div style="word-wrap:break-word;line-break:after-white-space" class=""><div class="">I hadn't considered using "is_stmt" at all, thanks for bringing that up!</div><div class=""><br class=""></div><div class="">Given the rule you've outlined, I'm not sure that the debugger could do a good job in the following scenarios:</div></div></blockquote><div class=""><br class="">Ah, one thing that might've been confusing is when I say "before" I mean "before in the instruction stream/line table" not "before in the source order".<br class=""> </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;line-break:after-white-space" class=""><div class=""><br class=""></div><div class="">  1|  foo =</div><div class="">  2|    bar();</div><div class=""><div class="">  3|  foo =    //< Given a breakpoint on line 3, would the debugger stop on line 2?</div><div class="">  4|    bar();</div></div><div class=""><br class=""></div></div></blockquote><div class=""><br class=""></div><div class="">Given the line table (assuming a sort of simple pseudocode):<br class=""><br class="">  %x1 = call bar(); # line 2<br class="">  store %x1 -> @foo # line 1<br class="">  %x2 = call bar(); # line 4<br class="">  store %x2 -> @foo # line 3<br class=""><br class="">We could group lines 1 and 2 as part of the same statement and lines 3 and 4 as part of the same statement - then when the line table is emitted, the lexically (in the assembly, not in the source code) first instruction that's part of that statement gets the "is_stmt" flag. So in this case line 2 and 4 would have "is_stmt", a debugger, when requested to set a breakpoint on line 3 would look at the line table and say "well, I have this location on line 3, but it's not the start of a statement/not a good place to break, so I'll back up in the instruction stream (within a basic block - so that might get tricky for conditional operators and the like) until I find an instruction marked with "is_stmt" - and it would find the second call instruction and break there. The debugger could make the UI nicer (rather than showing line 4 when the user requested line 3) by highlighting the whole statement (all lines attributed to instructions between this "is_stmt" instruction and the next (Or the end of the basic block)).<br class=""><br class="">Does that make sense?</div></div></div></div></blockquote><div><br class=""></div>Got it, that makes sense.</div><div><br class=""></div><div>vedant</div><div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_quote"><div class=""> </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;line-break:after-white-space" class=""><div class=""></div><div class="">or</div><div class=""><br class=""></div><div class="">  1|  if (...)</div><div class="">  2|    foo();</div><div class="">  3|  else</div><div class="">  4|    bar();</div><div class="">  5|  baz =   //< Given a breakpoint on line 5, would the debugger stop on line 2, 4, or possibly either?</div><div class="">  6|    func();</div><div class=""><br class=""></div><div class="">Is there another way to apply and interpret "is_stmt" flags to resolve these sorts of ambiguities?</div><div class=""><br class=""></div><div class=""></div></div><div style="word-wrap:break-word;line-break:after-white-space" class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class="">The inlining case seems to me like something that could be fixed without changes to the DWARF, purely in the consumer - the consumer has the info that the call occurs on a certain line and when I ask to break on that line it could break on that first instruction in the inlined subroutine (potentially giving me an artificial view that makes it look like I'm at the call site and leting me 'step' (though a no-op) into the inlined function).<br class=""></div></div></blockquote><div class=""><br class=""></div></div></div><div style="word-wrap:break-word;line-break:after-white-space" class=""><div class=""><div class="">Oh, that's a great point. Yes, there is a TAG_inlined_subroutine for "inline_me" which contains AT_call_file and AT_call_line. That's enough information to do the right thing on the debugger side.</div><div class=""><br class=""></div><div class="">thanks,</div><div class="">vedant</div></div></div><div style="word-wrap:break-word;line-break:after-white-space" class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><br class="">* This is a bit problematic when a statement gets interleaved/mixed up with other statements - DWARF has no equivalent of "ranges" for describing a statement. Likely not a problem at -O0 anyway, though (because little interleaving occurs there).<br class=""><br class=""><div class="gmail_quote"><div dir="ltr" class="">On Wed, Aug 22, 2018 at 2:01 PM Vedant Kumar via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org" target="_blank" class="">cfe-dev@lists.llvm.org</a>> wrote:<br class=""></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;line-break:after-white-space" class="">Hello,<div class=""><br class=""></div><div class="">I'd like to improve the situation with setting breakpoints on lines with assignments or inlinable calls. This email outlines problem areas, possible solutions, and why I think emitting extra nops at -O0 might be the best solution.</div><div class=""><br class=""></div><div class=""># Problem 1: Assignments</div><div class=""><br class=""></div><div class="">Counter to user expectation, a breakpoint on a line containing an assignment is reached when the assignment happens, not before the r.h.s is evaluated.</div><div class=""><br class=""></div><div class="">## Example: Can't step into bar()</div><div class=""><br class=""></div><div class="">  1| foo = // Set a breakpoint here. Note that it's not possible to step into bar().</div><div class="">  2|   bar();</div><div class=""><br class=""></div><div class="">One solution is to set the location of the assignment to the location of the r.h.s (line 2). The problem with this approach is that it becomes impossible to set a breakpoint on line 1.</div><div class=""><br class=""></div><div class="">Another solution is to emit a nop (on line 1) prior to emitting the r.h.s, and to emit an artificial location on the assignment's store instruction. This makes it possible to step to line 1 before line 2, and prevents users from stepping back to line 1 after line 2.</div><div class=""><br class=""></div><div class=""># Problem 2: Inlinable calls</div><div class=""><br class=""></div><div class="">Instructions from an inlined function don't have debug locations within the caller. This can make it impossible to set a breakpoint on a line that contains a call to an inlined function.</div><div class=""><br class=""></div><div class="">## Example: Can't set a breakpoint on a call</div><div class=""><br class=""></div><div class="">It's easier to see the bug via Godbolt: <a href="https://godbolt.org/z/scwF20" target="_blank" class="">https://godbolt.org/z/scwF20</a>. Note that it's not possible to set a breakpoint on line 9 (on "inline_me"). At the IR-level, we do emit an unconditional branch with a location that's on line 9, but we have to drop that branch during ISel.</div><div class=""><br class=""></div><div class="">The only solution to this problem (afaik) is to insert a nop before inlinable calls. In this example the nop would be on line 9.</div><div class=""><br class=""></div><div class="">One alternative I've heard is to make the first inlined instruction look like it's located within the caller, but that actually introduces a bug. You wouldn't be able to set a breakpoint on the relevant location in the inlined callee.</div><div class=""><br class=""></div><div class=""># Proposal</div><div class=""><br class=""></div><div class="">As outlined above, I think the best way to address issues with setting breakpoints on assignments and calls is to insert nops with suitable locations at -O0. These nops would lower to a target-specific nop at -O0, and lower to nothing at -O1 or greater (like @llvm.donothing).</div><div class=""><br class=""></div><div class="">The tentative plan is to introduce an intrinsic (say, @llvm.dbg.nop) to accomplish this.</div><div class=""><br class=""></div><div class="">I don't anticipate there being a substantial compile-time impact, but haven't actually measured this yet. I'd like to get some feedback before going forward. Let me know what you think!</div><div class=""><br class=""></div><div class="">thanks,</div><div class="">vedant</div><div class=""><br class=""></div><div class=""><br class=""></div></div>_______________________________________________<br class="">
cfe-dev mailing list<br class="">
<a href="mailto:cfe-dev@lists.llvm.org" target="_blank" class="">cfe-dev@lists.llvm.org</a><br class="">
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank" class="">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br class="">
</blockquote></div></div>
</div></blockquote></div></div></blockquote></div></div>
</div></blockquote></div><br class=""></body></html>