[LLVMdev] LLVM asserts

Chris Lattner clattner at apple.com
Wed Aug 19 20:26:50 PDT 2009


On Aug 19, 2009, at 7:29 PM, Óscar Fuentes wrote:
Eli Friedman <eli.friedman at gmail.com> writes:
> Besides, in my experience all LLVM asserts I see are Type mismatches  
> for
> instructions and similar cases, i.e., errors about my compiler  
> producing
> wrong LLVM "code" through the API, plus some occasional bug on LLVM,
> sometimes about one layer passing the wrong thing to the next layer,
> sometimes the bug being the existence of the assert check itself.

Failures like this are common in development, but should not occur in  
production quality code.  They mean that your compiler is broken and  
you should fix it.  The Verifier pass is one way to catch some classes  
of malformed IR before you toss it in to poor unsuspecting optimizers.

> And finally, as Aaron points out, a robust library reports failures,  
> but
> shouldn't kill the process.

Again, an assertion failure is no different than dereferencing a  
dangling or garbage pointer.  This is a non-recoverable error.   
llvm_unreachable is the same class of problem.  It is semantically the  
same as assert(0) - an unrecoverable failure.

To say it again:
    an assert is not recoverable
    an assert is not recoverable
    an assert is not recoverable

Remember that assertions happen when an invariant is broken.   
Invariants, by definition, don't vary.  Assertions are also disabled  
in certain build modes, and this is important because the whole idea  
is that they do checking in debug builds that disappear in production  
builds.  It is really not feasible or desirable for them to cause a  
"recoverable error", even ignoring the fact that there is no good  
recovery mechanism.


I want to reiterate what Eli said, it is worth repeating:

"
> So what should we use to validate input, such as constructing an
> APFloat from a string? llvm_report_error? Or should I change my string
> parsing function into a classmethod that returns pointer to an APFloat
> or null on failure?

Nothing in ADT should be using llvm_report_error; if something is
expected to fail, it should return an error code, and otherwise it
should assert."


In other words, we should define APIs that have strict invariants on  
the callers.  If an API naturally has a failure mode, it should report  
it by returning an error code.  Only in situations where it is really  
really really unreasonable to do this should the error be reported  
with llvm_report_error.  The cases that fall into this category are  
things like malformed inline asm constraints etc.  It is very  
difficult for the front-end to fully validate all of these  
constraints, and so the code generator currently has to report some  
errors.

To be fully clear, I'm not a big fan of the current llvm_report_error  
approach (though it is definitely better than what we had before!).   
In my ideal little world, when the backend invokes llvm_report_error,  
it should *guarantee* that it can continue on and return back.  For  
example, in an inline asm error, I think the code generator should  
report the error with llvm_report_error and then discard the invalid  
inline asm and continue code generation.

This approach gives clients flexibility over how to handle the  
problem: if they want to immediately abort they can (and this should  
be the default behavior).  However, if the code generator is embedded  
into a larger app, the app should be able to install a handler, do  
code generation and when it completes, it could check for an error and  
report it however desired.  Right now the only reasonable  
implementation of an error handler ends in exit(1) which is not optimal.

-Chris



More information about the llvm-dev mailing list