On 07/19/16 19:30, Bernd Edlinger wrote:
> On 07/19/16 18:37, Jakub Jelinek wrote:
>> On Tue, Jul 19, 2016 at 04:20:55PM +0000, Bernd Edlinger wrote:
>>> As discussed at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71876,
>>> we have a _very_ old hack in gcc, that recognizes certain functions by
>>> name, and inserts in some cases unsafe attributes, that don't work for
>>> a freestanding environment.
>>>
>>> It is unsafe to return ECF_MAY_BE_ALLOCA, ECF_LEAF and ECF_NORETURN
>>> from special_function_p, just by the name of the function, especially
>>> for less well known functions, like "getcontext" or "savectx", which
>>> could easily used for something completely different.
>>>
>>> Moreover, from the backend library we cannot check flag_hosted, or if
>>> the function has "C" or "C++" binding.
>>
>> I believe this will regress handling of various functions.
>> E.g. for alloca (as opposed to
>> __builtin_alloca/__builtin_alloca_with_align,
>> this means EFC_MAY_BE_ALLOCA will not be set anymore.
>>
>
> That depends on which options are used: with -ansi and -ffreestanding,
> alloca is just a normal function, which is kind of correct.
>
> If you include glibc's <alloca.h>, alloca is directly defined to
> __builtin_alloca(x), which should work always.
>
> If alloca is declared as void *alloca(size_t); it is also recognized as
> built-in unless -ansi or -ffreestanding is used, so that handling was
> in a way duplicated already.
>
> So I see no regression here.
>
>> _longjmp/siglongjmp will no longer be ECF_NORETURN (glibc
>> doesn't declare them as such), __sigsetjmp will no longer be ECF_LEAF.
>
> Which version of glibc do you refer to?
>
> My 2.19-0ubuntu6.9 has:
>
> extern void _longjmp (struct __jmp_buf_tag __env[1], int __val)
>       __THROWNL __attribute__ ((__noreturn__));
>
> extern int __sigsetjmp (struct __jmp_buf_tag __env[1], int __savemask)
> __THROWNL;
>
> So yes, __THROWNL is "__attribute__ ((__nothrow__))".
>
> But they also have __THROW around which is "__attribute__ ((__nothrow__
> __LEAF))", so that is just a minor bug in the glibc header, the header
> should declare it __THROW if it is no leaf.
>
> If you are concerned about the leaf attribute, it would
> be easy to add a builtin for _longjmp, and __sigsetjmp, as
> the _ is reserved anyway.  However I considered it an implementation
> detail of glibc, that could change, and I did not check newlib on that
> either.
>
> Should I add built-in for _longjmp and __sigsetjmp, and check if
> that works for newlib too?
>
>
> Thanks
> Bernd.


I have tried to find a test case with setjmp/longjmp where the leaf
attribute on the setjmp makes a difference, and the most aggressive
test case I could think of was this:

cat test1.c
static long env0[16], env1[16];
static int x = 0;

int jmp(void*) __attribute__((returns_twice, nothrow, leaf));
void go(void*, void*, int) __attribute__((nothrow));
void doit()
{
   x++;
}

int
test()
{
   static  int xx;
   xx = x;
   jmp (env0);
   xx += x;
   jmp (env1);
   go (env0, env1, xx + x);
   return xx;
}

gcc -O3 -S test.c && inspect assembler code.

Here jmp is marked leaf and returns_twice, but go is not leaf
and can either call doit, or jump to env0 or env1, or simply
return. It would be wrong to expect "x" not to change between
the jmp calls.  gcc-4.8.4 generates invalid code out of this,
and correct code if leaf is not in the function declaration.
However on trunk the code is correct, and the assembler code is
completely identical with or without leaf.

I wondered when that was fixed...

So I googled a bit around "gcc returns_twice leaf", and found
something interesting, where you argumented that it would
be wrong to put the leaf attribute at the setjmp function
in glibc: https://bugzilla.redhat.com/show_bug.cgi?id=752905

"Jakub Jelinek 2011-11-10 14:38:50 EST

setjmp/__sigsetjmp/_setjmp definitely must be __THROWNL rather than __THROW.
Similarly setcontext and swapcontext.  They all have side-effects which 
can modify module static variables that don't have address taken."


I completely agree with you.  But how can it be, that special_function_p
seems to do the completely opposite thing, and add leaf to the setjmp
declaration even if that is not written in the header file?


Thanks
Bernd.

Reply via email to