Catching Signals While JIT'ing Code

I’m trying to figure out the best way to handle signals raised during the execution of LLVM’s optimization passes or the JIT’ing of code prior to running it.

In particular, LLVM throws unix signals instead of C++ exceptions while the header ErrorHandling.h contains the following warning (the last paragraph in particular):

/// llvm_instal_error_handler - Installs a new error handler to be used
/// whenever a serious (non-recoverable) error is encountered by LLVM.
///
/// (snip)
///
/// It is dangerous to naively use an error handler which throws an exception.
/// Even though some applications desire to gracefully recover from arbitrary
/// faults, blindly throwing exceptions through unfamiliar code isn’t a way to
/// achieve this.

I must be naive because what I’d really like to do is throw an exception. I realize there are good reasons that this might not work so I understand the comment, however, I’m curious why LLVM didn’t use C++ exceptions for error recovery rather than unix signals like SIGABRT?

I figured this must have come up a few times so I did the usual Google search but didn’t find any definitive relevant discussions, though I found plenty of references to the fact that LLVM uses signals and other people who wondered why. I never found a good answer nor a definitive statement of the best approach for this particular case.

So, given the fact of the current design choice, which I’m in no real position to argue was a good one or a bad one since I don’t know the criteria, I want to know the best way to handle signals generated while I’m JIT’ing LLVM IR that I generated from a scripting language that I parse and output to LLVM IR within my C++ engine (which also happens to reside within a Cocoa Objective-C application world).

Ideally, I’d like to catch the signal inside a single C++ function that calls the JIT’ing code and handles the error if something goes wrong. I don’t want to have to take my process down in that event. This code will be running in the same process as the user GUI, some of the time, so I can’t just kill the process when that is the case.

I know others must have faced the same issue when using LLVM for embedded scripting language JIT compilation. What’s the best way to encapsulate and recover from errors that occur within the LLVM JIT framework whether because of my unintentional misuse of the IR or a bug in LLVM itself?

Thanks in advance,

Curtis

Right, this gets into the whole error-handling philosophy of LLVM, or
lack thereof. The idea is that so long as your frontend generating IR
gives correct IR and is well-behaved, LLVM will not assert, abort, or
crash. Once you've successfully debugged your frontend, you should
never see this kind of error from LLVM and need to recover from it.
In practice, this is true enough that it is acceptable to simply crash
the process when it fails.

One problem with installing a SIGABRT handler and raising an exception
is that code in LLVM is written with these assumptions about error
handling. It isn't expecting a failing assert to raise a C++
exception, so it doesn't do any work to clean up if that were to
happen. Memory is left in an unknown state, and attempting to perform
another compilation might just lead to a crash later.

Also, most people deploy LLVM with the asserts disabled because they
make the code ~10x slower. For unladen swallow, I tend to run our
regression tests with asserts off so they finish faster, and if it
crashes, I might go back and turn them on.

Reid

Hi all,

I have the following C code.

static int addp(int *c, int a,int b)
{
int x = *c + a + b;
return(x);
}

I want to replace *c with a scalar. So I tried the -argpromotion pass.
However, it fails to do anything to the resulting llvm file.

List of commands:
clang add.c -c -o add.bc
clang add.c -S -o add.ll
opt -argpromotion -stats add.bc -o add_a.bc
llvm-dis < add_a.bc > add_a.ll

Also, when I try to print the stats I get a message
"Maximum CGSCCPassMgr iterations on one SCC"

Can anyone please let me know what I am missing here?

Thanks for all the help.

Regards
Arvind

Hi all,

I have the following C code.

static int addp(int *c, int a,int b)
{
int x = *c + a + b;
return(x);
}

I want to replace *c with a scalar. So I tried the -argpromotion pass.
However, it fails to do anything to the resulting llvm file.

I assume this isn't the complete file.

List of commands:
clang add.c -c -o add.bc
clang add.c -S -o add.ll
opt -argpromotion -stats add.bc -o add_a.bc
llvm-dis < add_a.bc > add_a.ll

argpromotion won't work without running mem2reg first for normal clang output.

-Eli