This fails for i386 32-bit when using -fpic: void foo() { asm volatile ("movl $0,%%ebx" : : : "ebx"); } The compiler reports foo.c:1:14: error: PIC register clobbered by ‘ebx’ in ‘asm’ This forces people to write their asm statements differently for PIC and non-PIC code. That is not useful. The compiler could save and restore the PIC register around the asm statement. That would be more useful, and that is what we should do.
This was added on purpose. See PR 8340. *** This bug has been marked as a duplicate of bug 8340 ***
No, this is not a duplicate of PR 8340. I am suggesting a different way of handling the situation, which would still produce correct code. I am suggesting that when an asm clobbers the PIC register, that we explicitly save and restore the register around the asm.
(In reply to comment #2) > No, this is not a duplicate of PR 8340. I am suggesting a different way of > handling the situation, which would still produce correct code. I am > suggesting that when an asm clobbers the PIC register, that we explicitly save > and restore the register around the asm. The reason why it is a dup is that we decided we did not want to fix it that way. If you want to reopen the old bug that is a different story.
http://gcc.gnu.org/ml/gcc-patches/2002-11/msg01372.html
What happens on targets like PPC where r2 (the PIC register) is a fixed register should we save and restore it or error out. I say we should error out. Really I think it is a good thing to error out and force people to write their PIC vs no PIC inline-asm differently. As it forces people to think about register pressure and such.
The old bug was about bad code generation, and that was fixed. I don't think it needs to be reopened. I can not find any discussion about fixing this issue in any way other than forbidding it. I have no problem with forbidding clobbering fixed registers. That is a related but distinct issue. I do not think it is helpful to force people to consider pic vs. non-pic issues. They can still consider them if they choose, but I do not think it is helpful to force them.
(In reply to comment #6) > > I can not find any discussion about fixing this issue in any way other than > forbidding it. > EBX is fixed in PIC. If it is changed in asm, it should be saved and restored in asm. Otherwise, non-leaf functions may not work properly even if it is saved/restored in prologue/epilogue.
I'm suggesting saving and restoring it around the asm statement itself, not in the prologue and epilogue.
> I'm suggesting saving and restoring it around the asm statement itself, not in > the prologue and epilogue. Although the error was primarily RTH's idea, I still think it's very reasonable. When you write inline asm, you're expecting a certain degree of control over the generated code; knowing that you're clobbering the PIC register can be useful, especially on a register-starved architecture like the x86. If you stand by your clobbering, then writing the conditional save-and-restore code is trivial.
What advantage do we bring to our users by requiring them to be aware of the details of the PIC register when writing inline asm code? Again, those who *are* aware of the PIC register have complete control. But many people are able to write assembler code but have no idea what the PIC register is. In what way are we helping them by forcing them to know about it? How does that help them write inline assembler which, e.g., uses the cpuid instruction, or makes a kernel system call which passes a parameter in %ebx?
If you are writing assembler code you need to know your ABI in and out.
(In reply to comment #10) > > what way are we helping them by forcing them to know about it? How does that > help them write inline assembler which, e.g., uses the cpuid instruction, or Use <cpuid.h> provided by gcc. > makes a kernel system call which passes a parameter in %ebx? You can use syscall () or take a look at the C library source to see how system call is inlined.
> In what way are we helping them by forcing them to know about it? How does > that help them write inline assembler which, e.g., uses the cpuid instruction, > or makes a kernel system call which passes a parameter in %ebx? In these cases, that won't probably help them indeed. But, in other cases, like someone wanting to write very efficiently a hot loop in asm for a library, making it explicit that the %ebx register is not freely available like the others might help him to find the most efficient approach. Maybe we could just warn though.
In a first try on updating to valgrind 3.7.0 I run into this: make[3]: Entering directory `/home/pcpa/rpm/BUILD/valgrind-3.7.0/coregrind' x86_64-mandriva-linux-gnu-gcc -DHAVE_CONFIG_H -I. -I.. -I.. -I../include -I../VEX/pub -DVGA_x86=1 -DVGO_linux=1 -DVGP_x86_linux=1 -DVGPV_x86_linux_vanilla=1 -I../coregrind -DVG_LIBDIR="\"/usr/lib64/valgrind"\" -DVG_PLATFORM="\"x86-linux\"" -m32 -O2 -g -Wall -Wmissing-prototypes -Wshadow -Wpointer-arith -Wstrict-prototypes -Wmissing-declarations -Wno-format-zero-length -fno-strict-aliasing -fno-builtin -Wno-long-long -O2 -g -frecord-gcc-switches -Wstrict-aliasing=2 -pipe -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fstack-protector --param=ssp-buffer-size=4 -fPIC -Wno-pointer-sign -fno-stack-protector -MT libcoregrind_x86_linux_a-syswrap-linux.o -MD -MP -MF .deps/libcoregrind_x86_linux_a-syswrap-linux.Tpo -c -o libcoregrind_x86_linux_a-syswrap-linux.o `test -f 'm_syswrap/syswrap-linux.c' || echo './'`m_syswrap/syswrap-linux.c m_syswrap/syswrap-linux.c: In function 'run_a_thread_NORETURN': m_syswrap/syswrap-linux.c:202:7: error: PIC register clobbered by 'ebx' in 'asm' make[3]: *** [libcoregrind_x86_linux_a-syswrap-linux.o] Error 1 The code is like this: static void run_a_thread_NORETURN ( Word tidW ) [...] /* We have to use this sequence to terminate the thread to prevent a subtle race. If VG_(exit_thread)() had left the ThreadState as Empty, then it could have been reallocated, reusing the stack while we're doing these last cleanups. Instead, VG_(exit_thread) leaves it as Zombie to prevent reallocation. We need to make sure we don't touch the stack between marking it Empty and exiting. Hence the assembler. */ #if defined(VGP_x86_linux) asm volatile ( "movl %1, %0\n" /* set tst->status = VgTs_Empty */ "movl %2, %%eax\n" /* set %eax = __NR_exit */ "movl %3, %%ebx\n" /* set %ebx = tst->os_state.exitcode */ "int $0x80\n" /* exit(tst->os_state.exitcode) */ : "=m" (tst->status) : "n" (VgTs_Empty), "n" (__NR_exit), "m" (tst->os_state.exitcode) : "eax", "ebx" ); #elif defined(VGP_amd64_linux) In valgrind 3.6.1 it works because it does not tell about the clobbered registers.
As a heavy inline asm user myself, i can understand the pain to handle PIC yourself, but there is no way around that. You can "accidentally" use the PIC register by a memory operand ("m"). Then the compiler can not save it for you. Greetings Jan
Author: kyukhin Date: Mon Oct 13 17:26:49 2014 New Revision: 216154 URL: https://gcc.gnu.org/viewcvs?rev=216154&root=gcc&view=rev Log: gcc/ PR target/8340 PR middle-end/47602 PR rtl-optimization/55458 * config/i386/i386.c (ix86_use_pseudo_pic_reg): New. (ix86_init_pic_reg): New. (ix86_select_alt_pic_regnum): Add check on pseudo register. (ix86_save_reg): Likewise. (ix86_expand_prologue): Remove PIC register initialization now performed in ix86_init_pic_reg. (ix86_output_function_epilogue): Add check on pseudo register. (set_pic_reg_ever_alive): New. (legitimize_pic_address): Replace df_set_regs_ever_live with new set_pic_reg_ever_alive. (legitimize_tls_address): Likewise. (ix86_pic_register_p): New check. (ix86_delegitimize_address): Add check on pseudo register. (ix86_expand_call): Insert move from pseudo PIC register to ABI defined REAL_PIC_OFFSET_TABLE_REGNUM. (TARGET_INIT_PIC_REG): New. (TARGET_USE_PSEUDO_PIC_REG): New. * config/i386/i386.h (PIC_OFFSET_TABLE_REGNUM): Return INVALID_REGNUM if pic_offset_table_rtx exists. * doc/tm.texi.in (TARGET_USE_PSEUDO_PIC_REG, TARGET_INIT_PIC_REG): Document. * doc/tm.texi: Regenerate. * function.c (assign_parms): Generate pseudo register for PIC. * init-regs.c (initialize_uninitialized_regs): Ignor pseudo PIC register. * ira-color.c (color_pass): Add check on pseudo register. * ira-emit.c (change_loop): Don't create copies for PIC pseudo register. * ira.c (split_live_ranges_for_shrink_wrap): Add check on pseudo register. (ira): Add target specific PIC register initialization. (do_reload): Keep PIC pseudo register. * lra-assigns.c (spill_for): Add checks on pseudo register. * lra-constraints.c (contains_symbol_ref_p): New. (lra_constraints): Enable lra risky transformations when PIC is pseudo register. * shrink-wrap.c (try_shrink_wrapping): Add check on pseudo register. * target.def (use_pseudo_pic_reg): New. (init_pic_reg): New. gcc/testsuite/ PR target/8340 PR middle-end/47602 PR rtl-optimization/55458 * gcc.target/i386/pic-1.c: Remove dg-error as test should pass now. * gcc.target/i386/pr55458.c: Likewise. * gcc.target/i386/pr47602.c: New. * gcc.target/i386/pr23098.c: Move to XFAIL. Modified: trunk/gcc/ChangeLog trunk/gcc/config/i386/i386.c trunk/gcc/config/i386/i386.h trunk/gcc/doc/tm.texi trunk/gcc/doc/tm.texi.in trunk/gcc/function.c trunk/gcc/init-regs.c trunk/gcc/ira-color.c trunk/gcc/ira-emit.c trunk/gcc/ira.c trunk/gcc/lra-assigns.c trunk/gcc/lra-constraints.c trunk/gcc/shrink-wrap.c trunk/gcc/target.def trunk/gcc/testsuite/ChangeLog trunk/gcc/testsuite/gcc.target/i386/pic-1.c trunk/gcc/testsuite/gcc.target/i386/pr23098.c trunk/gcc/testsuite/gcc.target/i386/pr55458.c
Now that the PIC register is a pseudo for i686, this "just works".