[Bug target/83368] alloca after setjmp breaks PIC base reg
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83368 --- Comment #20 from Eric Botcazou --- > Thanks for the fix; is this a candidate for backporting to the gcc-7 branch? > If not we can just carry it in Debian, but it would be nicer to have it > upstream. Sorry, it looks like I missed this message too... In any case, the change was not really appropriate for a backport.
[Bug target/83368] alloca after setjmp breaks PIC base reg
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83368 --- Comment #19 from James Clarke --- Thanks for the fix; is this a candidate for backporting to the gcc-7 branch? If not we can just carry it in Debian, but it would be nicer to have it upstream.
[Bug target/83368] alloca after setjmp breaks PIC base reg
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83368 Eric Botcazou changed: What|Removed |Added Status|ASSIGNED|RESOLVED Resolution|--- |FIXED Target Milestone|--- |8.0 --- Comment #18 from Eric Botcazou --- Fixed on the mainline.
[Bug target/83368] alloca after setjmp breaks PIC base reg
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83368 --- Comment #17 from Eric Botcazou --- Author: ebotcazou Date: Fri Jan 12 11:29:30 2018 New Revision: 256575 URL: https://gcc.gnu.org/viewcvs?rev=256575=gcc=rev Log: PR target/83368 * config/sparc/sparc.h (PIC_OFFSET_TABLE_REGNUM): Set to INVALID_REGNUM in PIC mode except for TARGET_VXWORKS_RTP. * config/sparc/sparc.c: Include cfgrtl.h. (TARGET_INIT_PIC_REG): Define. (TARGET_USE_PSEUDO_PIC_REG): Likewise. (sparc_pic_register_p): New predicate. (sparc_legitimate_address_p): Use it. (sparc_legitimize_pic_address): Likewise. (sparc_delegitimize_address): Likewise. (sparc_mode_dependent_address_p): Likewise. (gen_load_pcrel_sym): Remove 4th parameter. (load_got_register): Adjust call to above. Remove obsolete stuff. (sparc_expand_prologue): Do not call load_got_register here. (sparc_flat_expand_prologue): Likewise. (sparc_output_mi_thunk): Set the pic_offset_table_rtx object. (sparc_use_pseudo_pic_reg): New function. (sparc_init_pic_reg): Likewise. * config/sparc/sparc.md (vxworks_load_got): Set the GOT register. (builtin_setjmp_receiver): Enable only for TARGET_VXWORKS_RTP. Added: trunk/gcc/testsuite/gcc.target/sparc/setjmp-1.c Modified: trunk/gcc/ChangeLog trunk/gcc/config/sparc/sparc.c trunk/gcc/config/sparc/sparc.h trunk/gcc/config/sparc/sparc.md
[Bug target/83368] alloca after setjmp breaks PIC base reg
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83368 Eric Botcazou changed: What|Removed |Added Status|NEW |ASSIGNED Assignee|unassigned at gcc dot gnu.org |ebotcazou at gcc dot gnu.org --- Comment #16 from Eric Botcazou --- Investigating.
[Bug target/83368] alloca after setjmp breaks PIC base reg
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83368 Eric Botcazou changed: What|Removed |Added Status|RESOLVED|NEW Resolution|WONTFIX |--- --- Comment #15 from Eric Botcazou --- > It's true that, as far as I'm aware, no other architecture has this issue, > as either the PIC register is caller-saved, or it gets saved by setjmp. OK, that was my understanding too. > However the original SPARC library authors clearly thought of this and > decided it was the responsibility of the compiler to not rely on input or > local registers being preserved given their explicit note in SCD, so whether > or not you believe that this was a good idea, that's what they chose and > what we currently have, and GCC is not adhering to that. Sure, it would be > nice if the registers were saved by setjmp, but it's documented behaviour > and thus not a bug as such in glibc nor Solaris's libc. Fair enough, let's bow to SCD's wisdom then. ;-)
[Bug target/83368] alloca after setjmp breaks PIC base reg
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83368 --- Comment #14 from James Clarke --- (In reply to Eric Botcazou from comment #12) > > Can't be done without an ABI break. But it is just the PIC register, and I'm > > still of the view this is a GCC bug. You seem to not be listening to my > > arguments and just reciting that "setjmp must save call-saved registers", > > which would be nice if it were true, but that's not what actually happens, > > and GCC already tries to handle this; it just misses a case on SPARC. > > OK, let's see it the other way around: how does it work on other > architectures? Does GCC save and restore the PIC register or it is > preserved through the call to setjmp? It's true that, as far as I'm aware, no other architecture has this issue, as either the PIC register is caller-saved, or it gets saved by setjmp. However the original SPARC library authors clearly thought of this and decided it was the responsibility of the compiler to not rely on input or local registers being preserved given their explicit note in SCD, so whether or not you believe that this was a good idea, that's what they chose and what we currently have, and GCC is not adhering to that. Sure, it would be nice if the registers were saved by setjmp, but it's documented behaviour and thus not a bug as such in glibc nor Solaris's libc.
[Bug target/83368] alloca after setjmp breaks PIC base reg
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83368 --- Comment #13 from James Clarke --- (In reply to Eric Botcazou from comment #11) > > > Again you're wrong, the call-saved registers are properly preserved if you > > > don't clobber the stack pointer, just write a small test or simply tweak > > > yours. > > > > Yes, I know that. > > OK, at least something we agree on. :-) > > > But GCC doesn't rely on that for *any other use* of the input and local > > registers; they are spilled to the stack and reloaded after the setjmp when > > needed. > > No, that's also wrong, try: > > int main(void) > { > register int i asm ("l0") = 1; > setjmp(jb); > printf("%d\n", i); > > if (c < 10) > bar(); > > return 0; > } > > main: > save%sp, -176, %sp > mov 1, %l0 > sethi %hi(jb), %g1 > or %g1, %lo(jb), %o0 > call_setjmp, 0 > nop > mov %l0, %g1 > sra %g1, 0, %g1 > mov %g1, %o1 > sethi %hi(.LC0), %g1 > or %g1, %lo(.LC0), %o0 > callprintf, 0 > nop > > GCC really expects all call-saved registers to be preserved. That's a bad example; if you change "l0" to "o5", GCC will still let you do it, and doesn't spill the value anywhere either. GCC assumes if you give a register, you know that the register really won't be clobbered by any function calls in between. Yes you might not be aware of the issue with setjmp in this instance, but that's your problem if you write this code. > > Also the fact that alloca clobbers the stack pointer > > is an implementation detail; for example, LLVM allocates all the space up > > front in the function prologue in this case, which means it would not run > > into this issue (and in fact it also spills its PIC base register). > > This should also work with libc's alloca and it clobbers the stack pointer. Ok, true.
[Bug target/83368] alloca after setjmp breaks PIC base reg
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83368 --- Comment #12 from Eric Botcazou --- > Can't be done without an ABI break. But it is just the PIC register, and I'm > still of the view this is a GCC bug. You seem to not be listening to my > arguments and just reciting that "setjmp must save call-saved registers", > which would be nice if it were true, but that's not what actually happens, > and GCC already tries to handle this; it just misses a case on SPARC. OK, let's see it the other way around: how does it work on other architectures? Does GCC save and restore the PIC register or it is preserved through the call to setjmp?
[Bug target/83368] alloca after setjmp breaks PIC base reg
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83368 --- Comment #11 from Eric Botcazou --- > > Again you're wrong, the call-saved registers are properly preserved if you > > don't clobber the stack pointer, just write a small test or simply tweak > > yours. > > Yes, I know that. OK, at least something we agree on. :-) > But GCC doesn't rely on that for *any other use* of the input and local > registers; they are spilled to the stack and reloaded after the setjmp when > needed. No, that's also wrong, try: int main(void) { register int i asm ("l0") = 1; setjmp(jb); printf("%d\n", i); if (c < 10) bar(); return 0; } main: save%sp, -176, %sp mov 1, %l0 sethi %hi(jb), %g1 or %g1, %lo(jb), %o0 call_setjmp, 0 nop mov %l0, %g1 sra %g1, 0, %g1 mov %g1, %o1 sethi %hi(.LC0), %g1 or %g1, %lo(.LC0), %o0 callprintf, 0 nop GCC really expects all call-saved registers to be preserved. > Also the fact that alloca clobbers the stack pointer > is an implementation detail; for example, LLVM allocates all the space up > front in the function prologue in this case, which means it would not run > into this issue (and in fact it also spills its PIC base register). This should also work with libc's alloca and it clobbers the stack pointer.
[Bug target/83368] alloca after setjmp breaks PIC base reg
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83368 --- Comment #10 from James Clarke --- (In reply to James Clarke from comment #9) > (In reply to Eric Botcazou from comment #7) > > > And for what it's worth, 32-bit Solaris/SPARC's setjmp isn't saving any of > > > the caller's input or local registers either, so it's not glibc-specific. > > > > Again you're wrong, the call-saved registers are properly preserved if you > > don't clobber the stack pointer, just write a small test or simply tweak > > yours. > > Yes, I know that. But GCC doesn't rely on that for *any other use* of the > input and local registers; they are spilled to the stack and reloaded after > the setjmp when needed. Also the fact that alloca clobbers the stack pointer > is an implementation detail; for example, LLVM allocates all the space up > front in the function prologue in this case, which means it would not run > into this issue (and in fact it also spills its PIC base register). (In reply to Eric Botcazou from comment #8) > > You already have code in sched-deps.c to deal with setjmp potentially not > > saving registers it should across all architectures: > > > > if (find_reg_note (insn, REG_SETJMP, NULL)) > > { > > /* This is setjmp. Assume that all registers, not just > > hard registers, may be clobbered by this call. */ > > reg_pending_barrier = MOVE_BARRIER; > > } > > GCC expects all call-saved registers to be preserved by setjmp/longjmp > though and I think that's what is implemented in glibc for other > architectures. No, it doesn't. Try it yourself. Make a local variable live across a setjmp call, and even under -O3 you will see it spilled to the stack and reloaded after setjmp returns. > > Why is it so hard to fix this bug? It's a very simple problem that only > > affects %l7; all it needs is for it to be spilled and reloaded. > > Because it's a call-saved register. Not for setjmp, but this is where we disagree. > > This is breaking real-world code that works on every other architecture I > > have > > tried it on, and telling people to use non-portable built-in functions > > isn't > > going to necessarily be well-received. > > Then you need to convince someone to fix glibc and make setjmp/longjmp > preserve call-saved registers even if the stack pointer is subsequently > clobbered. Or maybe just the PIC register, but I think it's only the tip of > the iceberg. Can't be done without an ABI break. But it is just the PIC register, and I'm still of the view this is a GCC bug. You seem to not be listening to my arguments and just reciting that "setjmp must save call-saved registers", which would be nice if it were true, but that's not what actually happens, and GCC already tries to handle this; it just misses a case on SPARC.
[Bug target/83368] alloca after setjmp breaks PIC base reg
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83368 --- Comment #9 from James Clarke --- (In reply to Eric Botcazou from comment #7) > > And for what it's worth, 32-bit Solaris/SPARC's setjmp isn't saving any of > > the caller's input or local registers either, so it's not glibc-specific. > > Again you're wrong, the call-saved registers are properly preserved if you > don't clobber the stack pointer, just write a small test or simply tweak > yours. Yes, I know that. But GCC doesn't rely on that for *any other use* of the input and local registers; they are spilled to the stack and reloaded after the setjmp when needed. Also the fact that alloca clobbers the stack pointer is an implementation detail; for example, LLVM allocates all the space up front in the function prologue in this case, which means it would not run into this issue (and in fact it also spills its PIC base register).
[Bug target/83368] alloca after setjmp breaks PIC base reg
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83368 --- Comment #8 from Eric Botcazou --- > You already have code in sched-deps.c to deal with setjmp potentially not > saving registers it should across all architectures: > > if (find_reg_note (insn, REG_SETJMP, NULL)) > { > /* This is setjmp. Assume that all registers, not just > hard registers, may be clobbered by this call. */ > reg_pending_barrier = MOVE_BARRIER; > } GCC expects all call-saved registers to be preserved by setjmp/longjmp though and I think that's what is implemented in glibc for other architectures. > Why is it so hard to fix this bug? It's a very simple problem that only > affects %l7; all it needs is for it to be spilled and reloaded. Because it's a call-saved register. > This is breaking real-world code that works on every other architecture I have > tried it on, and telling people to use non-portable built-in functions isn't > going to necessarily be well-received. Then you need to convince someone to fix glibc and make setjmp/longjmp preserve call-saved registers even if the stack pointer is subsequently clobbered. Or maybe just the PIC register, but I think it's only the tip of the iceberg.
[Bug target/83368] alloca after setjmp breaks PIC base reg
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83368 Eric Botcazou changed: What|Removed |Added Status|REOPENED|RESOLVED Resolution|--- |WONTFIX --- Comment #7 from Eric Botcazou --- > And for what it's worth, 32-bit Solaris/SPARC's setjmp isn't saving any of > the caller's input or local registers either, so it's not glibc-specific. Again you're wrong, the call-saved registers are properly preserved if you don't clobber the stack pointer, just write a small test or simply tweak yours.
[Bug target/83368] alloca after setjmp breaks PIC base reg
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83368 --- Comment #6 from James Clarke --- And for what it's worth, 32-bit Solaris/SPARC's setjmp isn't saving any of the caller's input or local registers either, so it's not glibc-specific.
[Bug target/83368] alloca after setjmp breaks PIC base reg
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83368 James Clarke changed: What|Removed |Added Status|RESOLVED|REOPENED Resolution|WONTFIX |--- --- Comment #5 from James Clarke --- (In reply to Eric Botcazou from comment #4) > > Therefore, I am of the view that this should be reopened as a bug in GCC. > > GCC already spills local variables live across a setjmp to the stack (as it > > can't use input or local registers due to the above note); it should be > > doing the same for %l7. > > No, setjmp/longjmp must preserve the call-saved registers and it does in > almost all cases, both on Linux and Solaris. You already have code in sched-deps.c to deal with setjmp potentially not saving registers it should across all architectures: if (find_reg_note (insn, REG_SETJMP, NULL)) { /* This is setjmp. Assume that all registers, not just hard registers, may be clobbered by this call. */ reg_pending_barrier = MOVE_BARRIER; } Why is it so hard to fix this bug? It's a very simple problem that only affects %l7; all it needs is for it to be spilled and reloaded. This is breaking real-world code that works on every other architecture I have tried it on, and telling people to use non-portable built-in functions isn't going to necessarily be well-received.
[Bug target/83368] alloca after setjmp breaks PIC base reg
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83368 Eric Botcazou changed: What|Removed |Added Status|REOPENED|RESOLVED Resolution|--- |WONTFIX --- Comment #4 from Eric Botcazou --- > Therefore, I am of the view that this should be reopened as a bug in GCC. > GCC already spills local variables live across a setjmp to the stack (as it > can't use input or local registers due to the above note); it should be > doing the same for %l7. No, setjmp/longjmp must preserve the call-saved registers and it does in almost all cases, both on Linux and Solaris. But you're clobbering the stack pointer after calling setjmp and this cannot reasonably work on SPARC because of the way setjmp/longjmp is implemented for this architecture. Let's declare this as WONTFIX; you can use __builtin_setjmp/longjmp instead.
[Bug target/83368] alloca after setjmp breaks PIC base reg
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83368 James Clarke changed: What|Removed |Added Status|RESOLVED|REOPENED Resolution|INVALID |--- --- Comment #3 from James Clarke --- (In reply to Eric Botcazou from comment #2) > It's a glibc bug, setjmp doesn't preserve %l7. I filed [1], but having gone away and thought about this, I don't think it is. SPARC Compliance Definition 2.4.1 specifically calls this out (page 47 or 3P-11 in my PDF), with: "There are some routines, like setjmp(), sigsetjmp(), and vfork(), that require the caller assume the registers %l0 through %l7, and %i0 through %i5 are volatile across the call." Therefore, I am of the view that this should be reopened as a bug in GCC. GCC already spills local variables live across a setjmp to the stack (as it can't use input or local registers due to the above note); it should be doing the same for %l7. [1] https://sourceware.org/bugzilla/show_bug.cgi?id=22604
[Bug target/83368] alloca after setjmp breaks PIC base reg
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83368 Eric Botcazou changed: What|Removed |Added Status|NEW |RESOLVED Resolution|--- |INVALID --- Comment #2 from Eric Botcazou --- It's a glibc bug, setjmp doesn't preserve %l7.
[Bug target/83368] alloca after setjmp breaks PIC base reg
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83368 Eric Botcazou changed: What|Removed |Added Status|UNCONFIRMED |NEW Last reconfirmed||2017-12-12 CC||ebotcazou at gcc dot gnu.org Ever confirmed|0 |1 --- Comment #1 from Eric Botcazou --- builtin_setjmp_receiver has simply nothing to do with setjmp/longjmp.