<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Thu, Feb 6, 2014 at 5:29 AM, Renato Golin <span dir="ltr"><<a href="mailto:renato.golin@linaro.org" target="_blank">renato.golin@linaro.org</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr">Folks,<div><br></div><div>We're having some discussions about the behaviour of exception handling and Dwarf sharing unwind logic, tables, etc. and it seems that the code around it wasn't designed with any particular goal in mind, but evolved (like the EHABI) and now we're seeing the results from it. </div>

<div><br></div><div>The problems below are assuming C vs. C++, but it actually apply to any possibly-exceptional vs. never-exceptional cases.</div><div><br></div><div><br></div><div>1. C vs. C++</div><div><br></div><div>
We have two unwind flags: nounwind, which flags functions that can't unwind (leaf, nothrow, etc) and uwtable, which forces generation of the table regardless of nounwind. It seems sensible that C++ code with exceptions enabled should generate the tables for all functions, in case they're called by (or call) external functions. In C we don't want any of that.</div>

<div><br></div><div>GCC seems to never emit tables, and G++ always do, even on C code (.c files, no exception or anything), which is very sensible and in line with my reasoning above. Clang, on the other hand, always generates them. I guess it'll have to figure out what to do based on its impressions on what language is being used to produce similar results.</div>

<div><br></div><div>I believe that emitting the tables on anything that could potentially interact with exceptional code makes sense, but that's clearly a front-end decision. To LLVM, nounwind and uwtables should be absolute:</div>

<div><br></div><div>IF (uwtables)</div><div>  IF (nownwind)</div><div>    CantUnwind</div><div>  ELSE</div><div>    Unwind Table</div><div>ELSE</div><div>  do nothing</div><div>ENDIF</div></div></blockquote><div><br></div>
<div>This looks wrong, based on the LangRef:</div><div><br></div>"uwtable</div><div class="gmail_quote">  This attribute indicates that the ABI being targeted requires that an unwind table entry be produce for this function even if we can show that no exceptions passes by it."</div>
<div class="gmail_quote"><br></div><div class="gmail_quote">I think it's probably:</div><div class="gmail_quote"><br></div><div class="gmail_quote">if (nounwind)</div><div class="gmail_quote">  can't unwind</div><div class="gmail_quote">
<br></div><div class="gmail_quote">if (uwtable || (!nounwind && need uwtable to unwind))</div><div class="gmail_quote">  unwind table<br><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div dir="ltr"><div>
2. .fnstart/.fnend+friends<br></div><div><br></div><div>Another problem is that the emission of unwinding tables (based on .fnstart/.fnend symbols and others) is conditional *only* to the existence (or not) of an exception handling class being loaded (EHABI, Dwarf). Which means that, we can't disable the EH on a per-function basis.</div>

<div><br></div><div>We'll have to change the way these symbols are emitted, at least when using ARMException, so that we can emit the tables and honour the uwtable on a per-function basis.</div><div><br></div><div>Again, this is a requirement for problem 1, but it'd need to be fixed after 3.</div>

<div><br></div><div><br></div><div>3. Unwinding code</div><div><br></div><div>Currently, even when no exception handling are needed, the exception code is used to generate Dwarf unwinding directives (CFI) for the debugger.</div>

<div><br></div><div>Both DwarfCFIException and ARMException inherit from DwarfException, and they are called to do the debug info about the stack unwinding, which is (at least) misplaced. The consensus is that this code should be factored out.</div>

<div><br></div><div>The part that is relevant to this thread is that, today, if -arm-disable-ehabi is requested, ARMException will not be used and we won't have a way of generating debug stack directives, which is wrong.</div>

<div><br></div><div>Factoring out this code is a requirement for the unwinding problem (1), since if we disable EH today, we'll disable Dwarf stack unwinding altogether. But we also need a final solution for problem 4 below before we start.</div>

<div><br></div><div><br></div><div>4. Clang EH control</div><div><br></div><div><div>There are a number of Clang/LLVM options to control exception handling:</div></div><div> * -fno-excetpion (enable/disable EH on C++ mode, off in C mode)</div>

<div> * -fcxx-exception (no idea, is it objC++ specific? does it control tables in any way?)</div><div> * -funwind-tables (forces uwtable attribute?)<br></div><div> * -arm-disable-ehabi (ARM specific bogus flag)</div><div>

<br></div><div>Those options are not always completely exclusive, and they damage different parts of the compilation process (as seen recently on the list), so we need a clear consensus on what each option mean (or should mean), and translate it to the back-end (via function attributes). This would considerably simplify the back-end and help us tackle this refactoring.</div>
</div></blockquote><div><br></div><div>I believe the intent is:</div><div>  -fexceptions/-fno-exceptions controls whether we generate code that copes with exceptions passing through it.</div><div>  -fcxx-exceptions/-fno-cxx-exceptions controls whether we allow exception constructs in C++ code (throw, catch, try) and whether we validate exception specifications (both during compilation and at runtime).</div>
<div>  -fobjc-exceptions/-fno-objc-exceptions controls whether we allow exception constructs in ObjC code (@throw, @try, @catch).</div><div><br></div><div>So:</div><div><br></div><div>  -fno-exceptions implies -fno-cxx-exceptions and -fno-objc-exceptions</div>
<div>  -fcxx-exceptions and -fobjc-exceptions require -fexceptions</div><div><br></div><div>The (-cc1) frontend defaults to -fno-exceptions -fno-cxx-exceptions -fno-objc-exceptions (I'm not sure why).</div><div>The driver defaults to:</div>
<div>  * in ObjC++: -fcxx-exceptions -fobjc-exceptions -fexceptions</div><div>  * in ObjC: -fobjc-exceptions -fexceptions</div><div>  * in C++: -fcxx-exceptions -fexceptions</div><div>  * in C: <nothing></div><div><br>
</div><div>(Users might want to specify -fexceptions in C, when building code like qsort that might have exceptions thrown across it.)</div><div><br></div><div><br></div><div>-funwind-tables appears to be an entirely orthogonal flag, which is by default determined based on the target (with some -f flags to override the default), entirely ignoring the -fexceptions flags and language mode. This does not appear to be a flag that an end-user should touch, under most circumstances, but it's far from clear to me that we're getting the default right here (maybe it should depend on -fexceptions?).</div>
<div><br></div><div><br></div><div>The 'nounwind' attribute is set if -fexceptions is specified, or if we have some other way of knowing the function does not throw. Exception: in -fobjc-exceptions mode, we ask the ObjC runtime whether to set the flag. This looks like a bug to me.</div>
<div><br></div><div>The 'uwtable' attribute is set based on the value we determined for -funwind-tables (either through an explicit flag or from the target).</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div dir="ltr"><div>My main target for this problem is to have the one true option on the front-ends, and rely only on function attributes on the back-end (including tools like llc). For that, I'd love to be left with -fexception only and infer all the rest from the language / conditions of the code.</div>

<div><br></div><div>Ex:</div><div><br></div><div>IF (C++ mode)</div><div>  IF (-fno-exception)</div><div>    no uwtable</div><div>    no nounwind</div><div>  ELSE</div><div>    uwtable</div><div>    IF (leaf / nothrow)</div>

<div>      nounwind</div><div>    ENDIF<br></div><div>  ENDIF</div><div>ELSE</div><div>  no uwtable</div><div>  no nounwind</div></div></blockquote><div><br></div><div>This seems wrong -- in C with -fexceptions we do not want nounwind, and sometimes want uwtable (depending on ABI).</div>
<div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div>ENDIF</div><div><br></div>
<div>My main goal is to get rid of (at least) -arm-disable-ehabi.<br>
</div><div><br></div><div><br></div><div><br></div><div>Finally,</div><div><br></div><div>If you got this far, you're *really* interested in making the exception handling more user/dev friendly in LLVM, so I welcome any critics about the "proposal" above, as well as any explanations of the doubts expressed. I may be wrong about many things, feel free to enlighten me! We may have a lot less work to do, and I'll be happy. ;)</div>

<div><br></div><div>I believe the dependency graph of the solutions are:</div><div><br></div><div>4 -> 3 -> 2 -> 1</div><div><br></div><div>So, we first should solve the flags problem, than refactor the unwinding code out of EH, make the debug generation use them as well, and then we can start with the EH specific changes. The problem is that 4 will change things considerably, so we might need some scaffolding during the whole process.</div>

<div><br></div><div>Makes sense?</div><div><br></div><div>cheers,</div><div>--renato</div><div><br></div></div>
<br>_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:LLVMdev@cs.uiuc.edu">LLVMdev@cs.uiuc.edu</a>         <a href="http://llvm.cs.uiuc.edu" target="_blank">http://llvm.cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev</a><br>
<br></blockquote></div><br></div></div>