
On 04 March 2005 17:32, Kurt Roeckx wrote:
I have no idea what ghc has too do with gcc,
A bit of background: GHC uses gcc as a backend compiler. GHC generates C code that is compiled using gcc (we also have a native code generator for some platforms; but not for x86_64 yet).
or what the problem exactly is.
The problem is that gcc generates incorrect code for C code that uses global register variables. You won't have noticed this, because most programs don't use global register variables. GHC uses global register variables to speed up the generated code.
We have very little problems with gcc for the debian amd64 port. Our default compiler is still 3.3. This builds almost everything without problems, however we build a few mozilla packages with gcc-3.4.
All I can tell is that ghc6 seems to be working on debian amd64. It can build itself and things like that.
That build of ghc6 is what we call "unregisterised": it doesn't make use of register variables to speed up the generated code. IOW, it generates plain ANSI C code, which gcc compiles fine.
Can someone please give a test case (and show what to do) to see what is wrong?
Ok, here's a really simple example: $ 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 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.
Out current default compiler in debian is: gcc version 3.3.5 (Debian 1:3.3.5-8)
The gcc 3.4 version is: gcc version 3.4.4 20050203 (prerelease) (Debian 3.4.3-9)
And ghc6 is at version 6.2.2-3.
I'm going to try with different versions of gcc. I've just submitted this bug report to the gcc guys. Cheers, Simon

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
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.
Hmm. On gcc 3.3.5 that I have, it discards the assignment on x86 as well. Dave

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

On Mon, Mar 07, 2005 at 07:01:16PM +0100, Kurt Roeckx wrote:
Also, it should be a "movq $g, %rax" instead of movl.
The default x86_64 model on gcc is -mcmodel=small, which assumes that all symbols are within the first 2GB. If you compile it with -mcmodel=medium it'll generate: movabsq $g, %r13 Dave
participants (3)
-
David Brown
-
Kurt Roeckx
-
Simon Marlow