Duncan Sands
2011-Jun-14 09:11 UTC
[LLVMdev] Is LLVM expressive enough to represent asynchronous exceptions?
Hi John, On 13/06/11 23:27, John McCall wrote:> On Jun 13, 2011, at 2:12 PM, Andrew Trick wrote: >> Although I believe asynchronous signals are also best handled by the runtime. They can be converted into cooperative exceptions. I have to say I can't see the value in resuming from an interrupt at literally any instruction address. > > For what it's worth, SEH (which inspires a lot of this) allows blocks of code to be protected from interruption. > > But yes, I am not inclined to support asynchronous exceptions from signals.gcc Ada turns signals into exceptions. As far as I know it does this completely asynchronously, and the fact that LLVM doesn't support this is rather bad as far as Ada is concerned. That said, the Ada front-end doesn't rely on this for things like dividing by zero: it precedes all code that does division by a bunch of checks that test that nothing can go wrong (like dividing by zero) and explicitly raises a "synchronous" exception if one of the checks fail. In particular it does not rely on -ftrapv to catch integer overflow (which must raise an exception); I hear that this is because -ftrapv does not work reliably. I'm assuming that it explicitly checks for division by zero because relying on signals does not work reliably, e.g. Ada semantics are not always preserved by the optimizers if you do this; but I'm not sure. So when does Ada use signals? Essentially never! I.e. an Ada program only gets hit by a signal if something very bad went wrong, that the compiler couldn't catch by inserting explicit checks. This almost always means memory corruption: for example a double free or a use after free can result in the program being hit by a signal, which then gets turned into an exception. Since the Ada language treats these kinds of things as "unbounded errors" (i.e. the nasal demon sort), there are no special semantics to preserve, so relying on signals is presumably fine. Things like dividing by zero are "bounded errors" (i.e. the consequences of this kind of error are carefully circumscribed), which is presumably why the compiler is very careful that Ada semantics are preserved in these cases. Ciao, Duncan.
Chris Lattner
2011-Jun-14 16:18 UTC
[LLVMdev] Is LLVM expressive enough to represent asynchronous exceptions?
On Jun 14, 2011, at 2:11 AM, Duncan Sands wrote:> gcc Ada turns signals into exceptions. As far as I know it does this > completely asynchronously, and the fact that LLVM doesn't support this > is rather bad as far as Ada is concerned. That said, the Ada front-endYou're saying that it turns asynch signals like SIGHUP (which can occur on any machine instruction) into signals? -Chris
Duncan Sands
2011-Jun-14 17:27 UTC
[LLVMdev] Is LLVM expressive enough to represent asynchronous exceptions?
Hi Chris, I've CC'd Eric Botcazou in the hope that he will clear up just what the Ada front-end needs from the rest of the compiler as far as asynchronous exceptions are concerned.>> gcc Ada turns signals into exceptions. As far as I know it does this >> completely asynchronously, and the fact that LLVM doesn't support this >> is rather bad as far as Ada is concerned. That said, the Ada front-end > > You're saying that it turns asynch signals like SIGHUP (which can occur on any machine instruction) into signals?AFAIK, on posix systems only SIGFPE, SIGILL, SIGSEGV and SIGBUS are turned into exceptions. For other signals, if there is no signal handler then the program is terminated; if the user installed a signal handler then it is run, and as far as I know there is no way for a user installed handler to raise an exception at the original point of execution without going deep into nasal demon territory. So SIGFPE, SIGILL, SIGSEGV and SIGBUS are the only ones that need to be thought about. I'm going to ignore the possibility that the user uses "kill" or somesuch to hit an Ada program with one of these signals. I think that falls out of the scope of the language standard, so any behaviour would probably be correct as far as the standard is concerned. For SIGILL, SIGSEGV and SIGBUS, I think the program has to be erroneous [*] to get one of these in the first place (note that null pointer dereferences and other things corresponding to "bounded errors" in Ada parlance [**] do not cause a segfault because the compiler inserts code to check for a null pointer before every dereference and explicitly raises an exception if the pointer is null), so I suspect that the compiler tries to do something (raise an exception) because it is helpful (quality of implementation) rather than because the language requires it. I wouldn't bet my life on this though :) As for SIGFPE, you will also never get this in normal usage (things like dividing INT_MIN by -1 never happen because the compiler inserts code to check for this before every division) and, based on the fact that the runtime doesn't even bother to attach a helpful message to the exception raised on SIGFPE, I'm not sure why the compiler even bothers with this one. In short, I think if LLVM ignores the possibility of signals being turned into exceptions then programs will probably still conform to what the language standard requires, but there might be some users complaining that stack overflow detection and recovery and other neat compiler features don't work when using LLVM as the GCC backend. But I don't know enough about this to be sure. Ciao, Duncan. [*] In C parlance, the program has undefined behaviour. [**] These are errors for which the consequences are carefully circumscribed by the language standard.
Possibly Parallel Threads
- [LLVMdev] Is LLVM expressive enough to represent asynchronous exceptions?
- [LLVMdev] Is LLVM expressive enough to represent asynchronous exceptions?
- [LLVMdev] Is LLVM expressive enough to represent asynchronous exceptions?
- [LLVMdev] Is LLVM expressive enough to represent asynchronous exceptions?
- [LLVMdev] Is LLVM expressive enough to represent asynchronous exceptions?