[LLVMdev] Does nounwind have semantics?
atrick at apple.com
Mon Jul 22 01:23:08 PDT 2013
On Jul 22, 2013, at 12:56 AM, Duncan Sands <baldrick at free.fr> wrote:
> my understanding is different. I'm pretty sure that what I'm about to say is
> the traditional way these things have been viewed in LLVM. That doesn't mean
> that it's the best way to view these things.
>> - nounwind means no dwarf EH. Absence
> I guess you mean presence.
> of nounwind means absence of dwarf EH. It
>> would be unwise for optimization passes to reason about the semantics beyond
>> that. I was momentarily mislead by the LICM code that handles MayThrow specially.
> nounwind has nothing to do with dwarf, since exceptions themselves need have
> nothing to do with dwarf (which is just one way of implementing exception
> handling). Don't forget setjmp/longjmp exception handling, and also exception
> handling by returning an extra invisible parameter (which I mentioned in
> another email) which IIRC was actually implemented by someone at the codegen
> level at some point as it was faster than dwarf for code that throws exceptions
> a lot. An additional point is that while in C++ you create an exception object,
> not all languages associate an object with an exception, some just want to do
> the equivalent of a non-local goto. Creating an exception object means
> allocating memory, mucking around with global data structures and obviously
> writing memory. A non-local goto doesn't have to do more than unwind the stack
> until it gets to the right frame then do a jump. It's not clear to me that that
> should be considered as writing memory.
> Here's my take: a call to an function marked nounwind either never returns
> (eg infinite loop or exits the program) or returns normally. It doesn't
> "return" by unwinding the stack out of the caller. On the other hand a
> function that is not marked nounwind may "return" by unwinding the stack;
> control in this case doesn't continue in the caller, it continues at least one
> further up the stack. Thus in this case the instructions after the call
> instruction are not executed. Note I'm talking about an ordinary call here,
> not an invoke. In the case of an invoke control may continue in the caller
> function, but only at a well-defined point (the landing pad).
Good explanation. Your definition of nounwind is completely logical. I would prefer not to rely on it though because
- Realistically, the semantics won’t be well tested.
- It doesn’t seem terribly important to treat nonlocal gotos as readonly (though maybe it is to you :)
- When it is important to optimize memory access around nonlocal gotos, I prefer to expose control flow to the optimizer explicitly.
e.g. why not just use invokes for all your may-throw calls, then you’re free to mark them readonly?
>> - Things that throw exceptions or trap in defined ways are not readonly.
> See above for why throwing an exception doesn't have to write memory. Dwarf
> exception handling, and anything which can be used to implement C++ exception
> handling, is clearly writing memory and thus cannot be used inside a readonly
> function. So yes, any function Clang produces that throws an exception is not
> going to be readonly. But as I mentioned above some languages have no
> exception object and just unwind the stack. For these the expression "throwing
> an exception" (which implicitly includes the idea that there is an exception
> object) is not really appropriate; "unwinds the stack" is the basic concept
> here. This is basically orthogonal to readonly.
>> - Runtime checks for overflow, div-by-zero, bounds checks, etc. should be
>> implemented at the IR level as branches to noreturn calls because it can be done
>> that way and I haven’t seen concrete evidence that it’s too expensive. Don’t try
>> to do something fancy with intrinsics and attributes unless absolutely required.
> I agree with this.
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the llvm-dev