Konstantin Vladimirov writes: > Hi, > > Minimal reproduction for x86: > > #include <setjmp.h> > #include <stdio.h> > #include <stdlib.h> > > jmp_buf something_happened; > int key_gdata = 2; > > int store_data; > > void __attribute__((noinline)) > initiate(void) > { > longjmp(something_happened, 1); > } > > int __attribute__ ((noinline)) > foo(int x) > { > return x + 1; > } > > int __attribute__((noinline)) > amibuggy(int x, int y1, int y2, int y3) > { > int nextdata, idx, key_data; > > key_data = key_gdata; > > if (setjmp(something_happened)) > { > if (key_data != key_gdata) > { > fprintf(stderr, "Test failed: data = %d, g_data = %d\n", > key_data, key_gdata); > abort(); > } > else > { > fprintf(stdout, "Test passed\n"); > fprintf(stdout, "data = %d, g_data = %d\n", key_data, key_gdata); > return 0; > } > } > > store_data = key_data; > nextdata = key_gdata; > > idx = foo(nextdata); > > for (;idx != 0; --idx) > { > int tmp = store_data; > nextdata += foo(tmp); > store_data = foo(nextdata); > } > > initiate(); > return 0; > } > > int > main(void) > { > amibuggy(9, 5, 16, 36); > amibuggy(0, 0, 0, 0); > return 0; > } > > > Compile with gcc-4.7.2 with line: > > gcc -O2 repro.c -o repro.x86 > > Now run and you will see test "magically" failed. > > What happens? Compiler on register allocation pass decided to reuse > stack slot 12(%rsp) where key_data persisted. > > movl key_gdata(%rip), %eax > movl %eax, 12(%rsp) > call _setjmp > > ... and later ... > > .L10: > movl 12(%rsp), %edi <--- oops! > call foo > > setjmp stored stack pointer, next frame slot is overwritten by > spill/fill (because compiler thinks that key_data is already dead at > this point. Then everything explodes. > > I am not sure that it is a bug, but situation is rather complicated > for programmer -- I think in this case programmer really may rely on > context restoring after longjmp, and surprise is really great. > > Question to gcc-help: Please comment on should I file this in > bugzilla, or should I live with it. > > Question to gcc: Really I found this problem in private backend and > want to fix it for my users, no matter first answer is yes or no. > Maybe somehow restrict stack slot reusage if function calls setjmp. > But I am not so good in reload internals. Any advices about how to > locally fix it in private backend sources (I haven't still done any > changes to normal gcc-4.7.2, just added new machine description) are > very appreciated. You need to read the C standard and understand the restrictions it places on the values of non-volatile automatic variables when setjmp returns due to a longjmp. Look for "The longjmp function" in WG14/n1124.pdf or n1494.pdf. Then you'll need to use "volatile" or restructure your code slightly.