<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Mar 2, 2016 at 1:59 PM, Lang Hames <span dir="ltr"><<a href="mailto:lhames@gmail.com" target="_blank">lhames@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Hi Owen, Dave,<span class=""><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"><span style="font-size:13px">I want to ask what I feel is an important high-level question here:  how does this approach differ, fundamentally, from exceptions, and why should we go down the route of building our own error handling scheme rather than “just” adopting exceptions?</span> </blockquote></span><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"><br><span style="font-size:13px">To answer my own question, my impression is that your proposed scheme is functionally similar to exceptions, with the major deviation of being opt-in rather than opt-out...</span></blockquote><div><br></div><div>I think that's a good one-line summary of the difference between the two schemes.</div><span class=""><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"><span style="font-size:13px">In particular, an opt-in scheme will require threading the error-handling type system through many layers of generic and/or boilerplate code in order to allow various callbacks in target backends to report errors properly.</span></blockquote><div><span style="font-size:13px"><br></span></div></span><div>Agreed. For the purposes of this discussion I'm going to take it as given that we *should* be handling these errors, and currently can't because we haven't turned on exceptions or threaded anything through.</div><div><br></div><div>If we turned exceptions on we wouldn't need any API changes, but we would pay the overhead for exceptions and RTTI everywhere in LLVM except where we explicitly opt out via noexcept specifiers. To get an upper bound on this I did a Release (non-LTO) build of LLVM with and without exceptions+RTTI turned on. I didn't get past looking at the binary size differences: clang got >9% bigger. Other tools got between 2% and 25% bigger, with most clustered around a 10-15% increase. Those are some scary size regressions.</div><div><br></div><div>If we use TypedError to solve this we would have to thread errors through many layers of the stack to get to ISel (pass managers, passes, etc). However, I believe that only a very small percentage of all LLVM functions would need to change, and I expect the space and performance overhead of TypedError to be correspondingly small. So we end up trading some engineering effort (explicitly threading TypedError) for (I expect) better performance.</div><span class=""><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"><span style="font-size:13px">It may be that other approaches, more like the diagnostic handling options discussed in the original thread (& that we have plumbed through for the "remarks" support). But maybe you need a hard stop on these errors, in which case you do need some implicit or explicit control flow to get you out.</span></blockquote><div><br></div></span><div>As I mentioned in the RFC thread I'm not opposed to diagnostic handlers, but I think they're a solution for a fairly specific problem. Since the primary aim here is to return cleanly (without taking down whatever program called the failing operation), we need some sort of error return.</div></div></blockquote><div><br></div><div>I think Clang is a good example of what "some sort of error return" can look like when it's not something as explicit as TypedError/error_code - erroneous ASTs can be produced that satisfy most of the ASTs invariants, enough for large parts of Clang to be ignorant to the error, which reduces the number of places that need to handle errors as well as providing better chances for error recovery/producing more than one error at a time. This can be useful for many users/use cases (indeed your objdump original motivation could be handy to have stub results and indirect failures in some cases - so that if, say, one table is corrupt, you can still dump other parts instead of stopping immediately).<br><br>& in doing so, you then tend to want to provide all the extra failure info through a side channel (since you're using the primary channel to mock up/pretend/paper over the error for the most part to streamline existing codepaths)<br><br>This is not to suggest that what you're proposing isn't valuable/worth doing/applicable to many cases - but there are other tools in the toolkit & I don't think they're as limited as they might appear.<br><br>Anyway, don't mean to sideline this discussion - I'm not proposing it as a "we should do diagnostic handlers instead of TypedError", just as a <here are some other tools that might be applicable (possibly in concert with TypedError) to some users/might be something Owen would like to consider when figuring out his own APIs>. </div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div> With TypedError, the error value is sufficient to hold the error message and the question becomes: What value would be added by threading a diagnostic handler through as well? Some libraries, particularly those that need to produce non-trivial source diagnostics like in clang and LLVM's IR parser, will actually want a diagnostic handler, whereas something like ISel can probably get away with an error-return alone.</div><span class=""><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"><span style="font-size:13px">I can speak only to my own use case here:  if my frontend provided me with contract-violating IR, I want to propagate an error all the way out to the the client (non-LLVM code) such that (1) they can log/report the error as appropriate for the platform, to aid in future debug, and (2) to give them a chance to recover via higher-order mechanisms such as falling back to a lower tier JIT, to an interpreter, or simply to an unoptimized compilation.  My impression is that #2 tends to get overlooked here, but many online and JIT compilation use cases have reasonable fallbacks options to continue program execution even if LLVM fails in a nominally unrecoverable manner.</span></blockquote><div><span style="font-size:13px"><br></span></div></span><div>Yep. I think this need is satisfied equally well by my scheme or exceptions. </div><span class="HOEnZb"><font color="#888888"><div><br></div><div>- Lang.</div></font></span></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Mar 1, 2016 at 2:02 PM, David Blaikie <span dir="ltr"><<a href="mailto:dblaikie@gmail.com" target="_blank">dblaikie@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote"><span>On Tue, Mar 1, 2016 at 1:55 PM, Owen Anderson <span dir="ltr"><<a href="mailto:resistor@mac.com" target="_blank">resistor@mac.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><span><br><div><blockquote type="cite"><div>On Mar 1, 2016, at 1:43 PM, David Blaikie <<a href="mailto:dblaikie@gmail.com" target="_blank">dblaikie@gmail.com</a>> wrote:</div><br><div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">It may be that other approaches, more like the diagnostic handling options discussed in the original thread (& that we have plumbed through for the "remarks" support). But maybe you need a hard stop on these errors, in which case you do need some implicit or explicit control flow to get you out. There was a bit of discussion about how to do this for lld recently - returning stub results that are "sufficient" maybe with a flag saying "this isn't a real result" - more like Clang's Parser/Sema: we don't have error results everywhere. We return erroneous stubs and the like which allow a lot of Clang to continue on without worrying about whether something failed. Only handling the failures in relatively few places.</div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">This is also useful for providing error recovery/multiple errors (eg: this instruction /and/ thin instruction were both wrong - so the user doesn't have to edit/compile loop again just to find out the two lines they wrote both needed changes). </div></div></blockquote></div><br></span><div>I can speak only to my own use case here:  if my frontend provided me with contract-violating IR, I want to propagate an error all the way out to the the client (non-LLVM code) such that (1) they can log/report the error as appropriate for the platform, to aid in future debug, and (2) to give them a chance to recover via higher-order mechanisms such as falling back to a lower tier JIT, to an interpreter, or simply to an unoptimized compilation.  My impression is that #2 tends to get overlooked here, but many online and JIT compilation use cases have reasonable fallbacks options to continue program execution even if LLVM fails in a nominally unrecoverable manner.</div></div></blockquote><div><br></div></span><div>Fair point - a callback mechanism could still be used to achieve that goal (or hybrid mechanisms involving the kind of "stub result" sort of stuff Clang does - you could register a null diagnostic handler and still expect the system to fail and in (2) I imagine you don't differentiate the specific failures much just "LLVM JIT didn't work, try the other thing"). Possibly not the best tool for the job, but one path that could be considered.<br><br>But yeah, good to keep that scenario in mind to be sure - thanks for articulating/clarifying it (& if my responses aren't making sense in that context, sorry about that - happy to try to clarify/explain differently)<br><br>- Dave </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"><span><font color="#888888"><div><br></div><div>—Owen</div></font></span></div></blockquote></div><br></div></div>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div></div>