<div dir="ltr"><font face="monospace">On Sat, 20 Nov 2021 at 08:26, Fāng-ruì Sòng <<a href="mailto:maskray@google.com" target="_blank">maskray@google.com</a>> wrote:<br>> > Asynchronous unwind tables could also restrict code generation to<br>> > having only a finite number of frame pointer adjustments (an example<br>> > of *not* having a finite number of `SP` adjustments is on AArch64 when<br>> > untagging the stack (MTE) in some cases the compiler can modify `SP`<br>> > in a loop).<br>><br>> The restriction on MTE is new to me as I don't know much about MTE yet.<span class="gmail_default"></span><br><br>It has nothing to do with MTE per se, <span class="gmail_default">I just noticed it in an MTE test</span></font><div><font face="monospace"><span class="gmail_default">(`llvm/test/CodeGen/AArch64/settag.ll:stg_alloca17()`).</span><br>I've got a patch for this, that just uses an extra scratch register (that's in</font><div><font face="monospace">the epilogue before popping CSRs and we have plenty of registers) and a constant</font></div><div><font face="monospace">number (usually one) of SP adjustments by a constant.<br><br>> > We could, for example, extend the `uwtable` attribute with an optional<br>> > value, e.g.<br>> >   -  `uwtable` (default to 2)<br>> >   -  `uwtable(1)`, sync unwind tables<br>> >   -  `uwtable(2)`, async unwind tables<br>> >   -  `uwtable(3)`, async unwind tables, but tracking only a subset of<br>> > registers (e.g. CFA and return address)<br>> ><br>> > Or add a new attribute `async_uwtable`.<br>> ><br>> > Other suggestions? Comments?<br>><br>> I have thought about extending uwtable as well. In spirit the idea<br>> looks great to me.<br>> The mode removing most callee-saved registers is useful.<br>> For example, I think linux-perf just uses pc/sp/fp (as how its ORC<br>> unwinder is designed).<br>><br>> My slight concern with uwtable(3) is that the amount of unwind<br>> information is not monotonic.<br>> Since sync->async and the number of registers are two dimensions,<br>> perhaps we should use two function attributes?<br><br>I reckon this matters when combining (for whatever reasons) multiple `uwtable` attributes?<br>Indeed, in my first version, I dropped the encoding 3 and then I was able to synthesize</font></div><div><font face="monospace">the attribute for an outlined function by simply taking the max of the attribute</font></div><div><font face="monospace">in the outlined-from functions<span class="gmail_default"> - it was just simpler.</span></font><div><font face="monospace"><br>How about instead we exchange the meaning of 2 and 3 so we get<br>  - 1, sync unwind tables<br>  - 2, "minimal" async unwind tables<br>  - 3, full async unwind tables<br>Then on the principle that we should always emit CFI information that the `uwtable` requested</font></div><div><font face="monospace">(as it may be an ABI mandate), possibly optimised, depending on the `nounwind` attribute, we would get:<br><br>          | nounwind 0           |  nounwind 1<br>----------+----------------------+--------------<br>uwtable 0 | sync, full           |  no CFI<br>----------+----------------------+--------------<span class="gmail_default"></span><br>uwtable 1 | sync, full           |  sync, full<br>----------+----------------------+--------------<br>uwtable 2 | async, full prologue,| <br>          | mininal epilogue     |  async, min<br>----------+----------------------+--------------<br>uwtable 3 | async, full          |  async, full<br><br><span class="gmail_default">as a starting point, and then backends may choose any of the entries</span></font></div><div><span class="gmail_default"><font face="monospace">in the following rows of the same column, as a QOI decision.</font></span></div><div><font face="monospace"><br></font></div><div><div class="gmail_default"><font face="monospace">All that said, I'm not even entirely convinced we need it as a separate `uwtable` option.</font></div><div class="gmail_default"><font face="monospace">The decision to skip some of the CFI instructions can be made during final object encoding.</font></div><div class="gmail_default"><font face="monospace">It probably has to be made during the final encoding, e.g. no point including epilogue CFI instructions</font></div><div class="gmail_default"><font face="monospace">in `.eh_frame`, or an ORC generator would naturally ignore most CFI instructions anyway.</font></div><font face="monospace"><br></font></div><div><font face="monospace">> BTW, are you working on improving the general CFI problems for aarch64?</font></div><div><span class="gmail_default"><font face="monospace">Yeah, I'm implementing support for `-fasynchronous-unwind-tables`. A slightly outdated</font></span></div><div><font face="monospace"><span class="gmail_default">series of patches start from </span><a href="https://reviews.llvm.org/D112330" target="_blank">https://reviews.llvm.org/D112330</a></font></div><div><font face="monospace"><br></font></div><div><span class="gmail_default"><font face="monospace">The full list I have right now is:</font></span></div><span style="color:rgb(32,31,30)"><font face="monospace">*<span class="gmail_default"> </span>[AArch64] Async unwind - Fix MTE codegen emitting frame adjustments in a loop</font></span><div><font face="monospace"><span class="gmail_default">  - this fixes the issue described above</span><br style="color:rgb(32,31,30)"><span style="color:rgb(32,31,30)">*<span class="gmail_default"> </span>[AArch64] Async unwind - Adjust unwind info in AArch64LoadStoreOptimizer</span></font></div><div><font face="monospace"><span class="gmail_default">  - this fixes some case(s) where load/store optimiser moves an SP inc/dec after the matching CFI instruction</span><br style="color:rgb(32,31,30)"><span style="color:rgb(32,31,30)">* [CodeGen] Async unwind - add a pass to fix CFI information</span></font></div><div><span class="gmail_default"><font face="monospace">  - this is a pass that inserts `.cfi_remember_state`/`.cfi_restore_state`, ideally should work</font></span></div><div><font face="monospace"><span class="gmail_default">    for all targets and replace `CFIInstrInserter`</span><br style="color:rgb(32,31,30)"><span style="color:rgb(32,31,30)">* [AArch64] Async unwind - function epilogues</span></font></div><div><font face="monospace"><span class="gmail_default"></span><span style="color:rgb(32,31,30)">* [AArch64] Async unwind - function prologues</span></font></div><div><font face="monospace"><span class="gmail_default">  - these are the core functionality</span><br style="color:rgb(32,31,30)"><span style="color:rgb(32,31,30)">* [AArch64] Async unwind - Refactor generation of shadow call stack prologue/epilogue</span><br style="color:rgb(32,31,30)"><span style="color:rgb(32,31,30)">* [AArch64] Async unwind - Always place the first LDP at the end when ReverseCSRRestoreSeq is true</span><br style="color:rgb(32,31,30)"><span style="color:rgb(32,31,30)">* [AArch64] Async unwind - helper functions to decide on CFI emission</span></font></div><div><font face="monospace"><span class="gmail_default">  - the three above: preparation/refactoring/simplification, `emitEpilogue` especially is a big mess</span><br style="color:rgb(32,31,30)"><span style="color:rgb(32,31,30)">* [AArch64] Async unwind - do not schedule frame setup/destroy</span><br style="color:rgb(32,31,30)"></font><div><span style="color:rgb(32,31,30)"><font face="monospace">* Extend the `uwtable` attribute with unwind table kind</font></span></div><div><font face="monospace"><span class="gmail_default"></span></font></div><div><span class="gmail_default"><font face="monospace">(I was meaning to update it for a few days now, only always something else pops up ...)</font></span></div><div><font face="monospace"><br></font></div><div><font face="monospace">> Since we are discussing asynchronous unwind tables, may I ask two<br>> slightly off-topic things?<br>><br>> (1) What's your opinion on ld --no-ld-generated-unwind-info?<br><span class="gmail_default"></span></font></div><div><font face="monospace"><br></font></div><div><font face="monospace"><span class="gmail_default">I would say, from a design point of view, an unwinder of any kind should not analyse </span>and interpret machine</font></div><div><font face="monospace">instructions as it's, in the general case, fragile - that's been my experience from developing and maintaining</font></div><div><font face="monospace">an unwinder that analysed prologues/epilogues, over a period of 10+ years, each new compiler version required adjustments.</font></div><div><span class="gmail_default"><font face="monospace"><br></font></span></div><div><span class="gmail_default"><font face="monospace">Then, PLT entries are likely to be a special case as they are both tiny and extremely unlikely to change between</font></span></div><div><span class="gmail_default"><font face="monospace">different compilers or different compiler versions. In a sense, one can treat them as having implicit identical unwind</font></span></div><div><span class="gmail_default"><font face="monospace">table entries (of any unwind table kind) associated with their address range, therefore explicit entries in the regular</font></span></div><div><span class="gmail_default"><font face="monospace">unwind tables are superfluous.</font></span></div><div><font face="monospace"><span class="gmail_default"></span></font></div><div><div class="gmail_default"><span class="gmail_default"><font face="monospace"><br></font></span></div><div class="gmail_default"><font face="monospace"><span class="gmail_default">> </span>(2) How should future stack unwinding strategy evolve?</font></div><div class="gmail_default"><font face="monospace">Well, that's a good question ... :D</font></div><div class="gmail_default"><font face="monospace"><br></font></div><div class="gmail_default"><font face="monospace">~chill</font></div><font face="monospace"><br>-- <br>Compiler scrub, Arm</font></div></div></div></div></div>