LLVM now supports setjmp/longjmp!

Thanks to the hard work of Bill Wendling (wendling@isanbard.org), LLVM now
translates setjmp/longjmp calls into the LLVM "exception handling"
instructions invoke & unwind. This means that all of the LLVM optimizers
are now aware of the extra control flow edges made possible by setjmp &
longjmp, so data flow analyses won't make incorrect transformations. A
variety of testcases are available in the
llvm/test/Programs/SingleSource/UnitTests/SetjmpLongjmp/ directory.

Reflecting setjmp/longjmp in terms of the invoke and unwind instructions
also means that the LLVM optimizers are able to optimize the sjlj
operations themselves as well. For example, if you are sick enough to
build a loop out of setjmp/longjmp calls, LLVM translates the longjmp
directly into a simple goto. In a more normal case, if the inliner
inlines the longjmp call into the setjmping function, the longjmp becomes
a direct branch instead of a stack unwinding operation. This happens "for
free" because the optimization was already present for C++ EH, and they
use the same underlying mechanisms.

For now, setjmp/longjmp support only interacts with C++ exception handling
partially correctly. In particular, if there is a "catch block" or
destructors which must be run in a function that longjmps, they will not
be executed correctly (however, catch blocks and dtors higher up in the
stack will). This may be fixed sometime after the 1.0 release, but it is
not super high priority. In particular, this testcase works:

void jmp() { longjmp(...); }
void test() {
  try {
    AClass A; // A's dtor is called due to longjmp
    jmp();
    // not reached
  } catch (...) {} // eat the longjmp "exception"
}

but this does not:

void test() {
  try {
    AClass A; // A's dtor is NOT called due to longjmp
    longjmp(...);
    // not reached
  } catch (...) {} // Does NOT "eat" the longjmp "exception"
}

I'm not aware of any other compilers that do the right thing in either
case, so we're still a step up. :slight_smile:

At this point, we are "feature complete" for our 1.0 release. The only
aspect of C or C++ that we do not support is inline assembly, and that
will have to come after the release.

Thanks again to Bill for the contribution!!

-Chris