[llvm-commits] [llvm-gcc-4.2] r49171 - in /llvm-gcc-4.2/trunk/gcc: llvm-convert.cpp llvm-types.cpp
Dale Johannesen
dalej at apple.com
Fri Apr 4 10:22:45 PDT 2008
On Apr 4, 2008, at 1:50 AM, Duncan Sands wrote:
> Hi Dale,
>
>> - if (!tree_could_throw_p(exp))
>> + if (!tree_could_throw_p(exp) || !flag_exceptions)
>
> this bit is not needed because
>
> bool
> tree_could_throw_p (tree t)
> {
> if (!flag_exceptions)
> return false;
OK.
>> // Compute whether the result needs to be zext or sext'd.
>> ParameterAttributes RAttributes =
>> HandleArgumentExtension(ReturnType);
>> + // Make sure all functions are marked nounwind if we aren't
>> using exceptions.
>> + if (!flag_exceptions)
>> + RAttributes |= ParamAttr::NoUnwind;
>> +
>> if (RAttributes != ParamAttr::None)
>> Attrs.push_back(ParamAttrsWithIndex::get(0, RAttributes));
>>
>> @@ -1112,7 +1116,9 @@
>> RAttributes |= ParamAttr::NoReturn;
>>
>> // Check for 'nounwind' function attribute.
>> - if (flags & ECF_NOTHROW)
>> + // When flag_exceptions is not set (it is set by default in C++/
>> ObjC++),
>> + // don't unwind anything.
>> + if ((flags & ECF_NOTHROW) || !flag_exceptions)
>
> I think this is wrong, because it means that declarations of
> external functions
> will always be marked nounwind. Consider compiling the following
> without -fexceptions:
>
> extern void g(bool Allowed_To_Throw);
> void f(void) {
> g(false);
> }
>
> and compiling the following with -fexceptions:
>
> void g(bool Allowed_To_Throw) {
> ...
> if (Allowed_To_Throw)
> throw something;
> else
> abort();
> ...
> }
>
> then linking the two modules together. Here g is a function that
> doesn't throw exceptions
> unless Allowed_To_Throw is true. With your patch g will be declared
> nounwind in the first
> module but not in the second. When you link them g may be marked
> nounwind in the linked
> module which would be wrong (I don't know if this happens or not
> currently, but it doesn't
> matter - we shouldn't rely on this kind of linker detail for
> correctness).
I disagree; this is exactly the sort of detail where the linker
behavior should be specified. In fact, if g throws and its caller f
does not expect it to, that is probably a mistake, and one the linker
could usefully tell the user about. (I see that it is not a mistake
in your example but I think a mistake is much more likely.)
Consider also that llvm-gcc cannot guarantee that all declarations and
definitions match. If we do as you suggest, they will mismatch when
the definition is nounwind.
As for the linker behavior, I would expect the definition to win.
Right now running your example through llvm-ld does appear to mark g
as nounwind, even though it throws. I believe the appropriate thing
to do is change the linker to take the nounwind bit from the
definition, and perhaps emit a warning.
> What I think should happen is:
>
> (1) *calls* to g from the first module should be marked nounwind.
> In fact all calls in
> the first module should be marked nounwind. This is already the
> case thanks to tree_could_throw_p.
> (2) external declarations should not be marked nounwind.
> (3) functions like f with a body compiled without -fexceptions
> should be marked nounwind.
>
> So I think you should undo these changes, and instead add some code
> to StartFunctionBody
> to add the nounwind attribute if !flag_exceptions.
>
> Best wishes,
>
> Duncan.
>
> PS: I was wrong to think that llvm-gcc was already marking functions
> nounwind when compiled
> with !flag_exceptions - it was prune_eh that was adding the
> marking. Nice catch!
It was sometimes, but not in all cases.
More information about the llvm-commits
mailing list