
On Mon, Mar 07, 2005 at 11:47:31AM -0000, Simon Marlow wrote:
$ cat bug.c register void * R1 __asm__("%r13");
extern void g(void); static void f(void) { R1 = g; goto *R1; } $ gcc -S -O bug.c $
And take a look at the generated assembly for the function f:
f: .LFB2: movl $g, %eax jmp *%rax
I get the same with both gcc-3.3 and gcc-3.4. They generate identical code.
Note that the assignment to the global variable R1 has been lost. It works fine on x86 though: change the register variable to %esi and try it.
It looks to me like it's using eax/rax instead of r13 to me. It's probably doing some optimizing it shouldn't, but on the other hand isn't "wrong". Also, it should be a "movq $g, %rax" instead of movl. Without -O I get: f: pushq %rbp movq %rsp, %rbp movl $g, %r13d movq %r13, %rax jmp *%rax (Note that the first 2 instructions are now a stack frame, disabled with -O) It still is using an movl instead of a movq, which is wrong. esi (or rsi) give the following warning: bug.c:1: warning: call-clobbered register used for global register variable And doesn't change a thing. It's still the same code. Using %ebp or %rbp with -O gives: movl $g, %ebp jmp *%rbp Which gives the same movl/movq problem, but now got the right register. Doing the same on i386 generates this: f: pushl %ebp movl %esp, %ebp movl $g, %eax jmp *%eax Using -fomit-frame-pointer you get: f: movl $g, %eax jmp *%eax Which seems to be exactly the same thing, except it got the size right now. The weird thing is that r13 doesn't exist on i386, and it didn't complain about it. Anyway, as summary: - It's using a movl where it should use a movq - It's probably doing some optimizations it shouldn't, but they're not "wrong" in this testcase and probably can't be avoided because of the way gcc works. Those happen on both i386 and amd64. Kurt