<div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Jun 12, 2020 at 1:05 AM Jerome Forissier via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org">llvm-dev@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><br>
<br>
On 6/11/20 11:25 PM, James Y Knight wrote:<br>
> The global constructor was removed by setting the initial value of "val" to<br>
> 1 instead of 0. So, the behavior of this program is preserved. Doesn't look<br>
> like erroneous behavior.<br>
<br>
OK, my example is too simplified indeed. Please consider the following<br>
instead:<br>
<br>
int val;<br>
<br>
static void __attribute__((constructor)) init_fn(void)<br>
{<br>
        val++;<br>
}<br>
<br>
int main(int argc, char *argv[])<br>
{<br>
        return val;<br>
}<br>
<br>
With this, clang -Os -fno-common generates a global variable initialized<br>
to 1 and discards init_fn().<br>
<br>
Now, what happens if the executable is later linked against a shared<br>
library which has its own constructor and sets "val" to some non-zero<br>
value? I mean this for instance:<br>
<br>
extern int val;<br>
<br>
static void __attribute__((constructor)) so_init_fn(void)<br>
{<br>
        val = 1;<br>
}<br>
<br>
I would expect the main program to return 2, not 1.<br></blockquote><div><br></div><div>It seems to me that there is no ordering guarantee that your so_init_fn() would run before init_fn(), isn't this a case of "static initialization order fiasco"?<a href="https://www.google.com/search?client=safari&rls=en&q=static+initialization+order+fiasco&ie=UTF-8&oe=UTF-8"></a></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">
<br>
Last thing, if I define "val" as volatile, the programs behaves as expected.<br>
<br>
Are we in "unspecified, just don't do this" territory here?<br>
<br>
Thanks,<br>
-- <br>
Jerome<br>
<br>
> <br>
> On Thu, Jun 11, 2020 at 10:12 AM Jerome Forissier via llvm-dev <<br>
> <a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>> wrote:<br>
> <br>
>> Hi,<br>
>><br>
>> I think that Clang erroneously discards a function annotated with<br>
>> __attribute__((constructor)) when flags -Os -fno-common are given. Test<br>
>> case below.<br>
>><br>
>> What do you think?<br>
>><br>
>> Thanks.<br>
>><br>
>> ----8<--------8<--------8<--------8<--------8<--------8<--------<br>
>> $ cat ctor.c<br>
>> int val;<br>
>><br>
>> static void __attribute__((constructor)) init_fn(void)<br>
>> {<br>
>>         val = 1;<br>
>> }<br>
>><br>
>> int main(int argc, char *argv[])<br>
>> {<br>
>>         return val;<br>
>> }<br>
>> ----8<--------8<--------8<--------8<--------8<--------8<--------<br>
>><br>
>> Here is what I observed:<br>
>><br>
>> - Clang (10.0.0-4ubuntu1) with -Os -fno-common: function init_fn() is<br>
>> NOT emitted,<br>
>> - Clang (10.0.0-4ubuntu1) with no flag, or only -Os or -fno-common:<br>
>> init_fn() is present as expected,<br>
>> - GCC (Ubuntu 9.3.0-10ubuntu1) with the same flags: init_fn() is present<br>
>> too,<br>
>> - Since <a href="https://reviews.llvm.org/D75056" rel="noreferrer" target="_blank">https://reviews.llvm.org/D75056</a>, -fno-common is the default and<br>
>> therefore -Os is enough to cause the issue.<br>
>><br>
>> ----8<--------8<--------8<--------8<--------8<--------8<--------<br>
>> $ clang --target=arm-linux-gnueabihf -Os -fno-common -S ctor.c \<br>
>>   -o /dev/stdout | grep init_fn<br>
>> $ clang --target=arm-linux-gnueabihf -Os -S ctor.c \<br>
>>   -o /dev/stdout | grep init_fn<br>
>>         .p2align        2               @ -- Begin function init_fn<br>
>>         .type   init_fn,%function<br>
>>         .code   32                      @ @init_fn<br>
>> init_fn:<br>
>>         .size   init_fn, .Lfunc_end0-init_fn<br>
>>         .long   init_fn(target1)<br>
>>         .addrsig_sym init_fn<br>
>> $ clang --target=arm-linux-gnueabihf -fno-common -S ctor.c \<br>
>>   -o /dev/stdout | grep init_fn<br>
>>         .p2align        2               @ -- Begin function init_fn<br>
>>         .type   init_fn,%function<br>
>>         .code   32                      @ @init_fn<br>
>> init_fn:<br>
>>         .size   init_fn, .Lfunc_end0-init_fn<br>
>>         .long   init_fn(target1)<br>
>>         .addrsig_sym init_fn<br>
>> $ arm-linux-gnueabihf-gcc -Os -fno-common -S ctor.c \<br>
>>   -o /dev/stdout | grep init_fn<br>
>>         .type   init_fn, %function<br>
>> init_fn:<br>
>>         .size   init_fn, .-init_fn<br>
>>         .word   init_fn(target1)<br>
>> ----8<--------8<--------8<--------8<--------8<--------8<--------<br>
>><br>
>> --<br>
>> Jerome<br>
>> _______________________________________________<br>
>> LLVM Developers mailing list<br>
>> <a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><br>
>> <a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
>><br>
> <br>
_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
</blockquote></div></div></div></div>