BZ #72: CACAO and gcc don't agree on calling conventions

Status fields:

creation_ts:2008-05-23 15:17
After updating to Fedora 9 (and getting rid of the mmap problem I posted to the mailing
list), I noticed that dacapo had stopped working in a very peculiar way - it could not
create files during unzipping because of the non-existent directory "scratch/antlr"
which it should have created with File.mkdir(). But it had not.

After lots of poking around, I found out that gcc 4.3 only uses 8 bits (al) to return a
boolean value. But cacao expects the whole register to be set. The following line
appeared in a +TraceJavaCalls output.>135257088 (0x080fdc00)

It means that the file does not exist (the lower 8 bits are zero). CACAO, however,
interprets it as non-zero and thus doesn't execute the subsequent mkdir, causing the
file extraction to fail.

I don't know what the official ABI says, and I couldn't find an obvious easy way to fix
it, so I'm reporting it here.

On x86_64, in contrast, I didn't have this problem. Maybe the calling convention is
different there, maybe gcc didn't change its behavior or maybe it was just bad luck...

Comment #1 by on 2008-05-23 15:29:00

Is there even such a thing as an official ABI? If there is, it's not easily

Comment #2 by on 2008-05-23 16:21:46

Found it:

Not very helpful though - "A function that returns an integral or pointer value places
its result in register %eax."

This can mean anything, although I would probably interpret it the way CACAO does.

Comment #3 by on 2008-05-31 08:49:57

Stefan, I assign this bug to you.

Comment #4 by on 2008-06-09 18:38:29

Created an attachment (id=41)
hg export of fix

This should fix it (for i386). I cannot commit (thank you Debian), so I'm posting it

I'm not sure about x86_64 anymore. Theoretically, it should be affected too. Maybe I
haven't noticed because I haven't rebuilt classpath yet...

Comment #5 by on 2008-06-09 18:40:04

twisti, what's with that "XXX does not work, because of nibbles" comment?

It works fine for <REG_RESULT, REG_RESULT> at least...

Comment #6 by on 2008-06-10 10:20:37

Yes, it works for register number 0 (EAX == AX == AL), but not for others.  So enabling
this one is not a good idea.

Comment #7 by on 2008-06-11 08:29:30

With what optimization are you compiling?  Have you tried to change that?

Comment #8 by on 2008-06-11 08:41:26

(In reply to comment #7)
> With what optimization are you compiling?  Have you tried to change that?

Yeah, it doesn't make a difference.

The function "exists" compiles to the code shown below (I used -fomit-frame-pointer for

char exists(int a)
        return a > 0;

0000007d <exists>:
  7d:   83 7c 24 04 00          cmpl   $0x0,0x4(%esp)
  82:   0f 9f c0                setg   %al
  85:   c3                      ret

Comment #9 by on 2008-06-11 09:31:51

Yes, you're right.  I just tried it on my Debian box:

$ gcc-4.2 -S -m32 -fomit-frame-pointer -O2 test.c
$ cat test.s
        xorl    %eax, %eax
        cmpl    $0, 4(%esp)
        setg    %al

$ gcc-4.3 -S -m32 -fomit-frame-pointer -O2 test.c
$ cat test.s
        movl    4(%esp), %eax
        testl   %eax, %eax
        setg    %al

See the missing register clear?  Same applies to x86_64:

$ gcc-4.2 -S -m64 -fomit-frame-pointer -O2 test.c
$ cat test.s
        xorl    %eax, %eax
        testl   %edi, %edi
        setg    %al

$ gcc-4.3 -S -m64 -fomit-frame-pointer -O2 test.c
$ cat test.s
        testl   %edi, %edi
        setg    %al

I don't know if this is indented or a bug.

Comment #10 by on 2008-06-11 10:24:16

I cannot imagine this being a bug. I think I remember a somewhat similar change a few
years ago when gcc changed the point in time at which it forced (C++) bools to 0/1.
Before, bools always contained only 0/1, so a cast to char was a nop. They changed it so
that bools can contain any value, and only upon casting to a numeric value is it
interpreted as false/true and set to 0/1 resp. The change might have been the other way
round but I'm sure it happened at some time.

Comment #11 by on 2008-06-11 12:24:22

I just tried Sun Studio compiler and it produces the same code as GCC 4.2.  Should we
ask the GCC list?

Comment #12 by on 2008-06-11 16:52:33

Intel 10.0 does the same (like GCC 4.2).

It happened somewhere between the gcc-4.3-20070707 and gcc-4.3-20070713 snapshots. No
idea which changeset exactly.

It does interoperate well with older code, however, because apparently, compiled code
has never assumed the upper part of the register to contain anything useful.

Comment #13 by on 2008-06-11 19:28:07

See (and followups)

Comment #14 by on 2008-06-11 21:36:09

Hmm, OK.  So it seems we have to add a "workaround".

Comment #15 by on 2008-06-11 22:21:30

Interestingly, Visual C++ 2003 (the only version I tried) produces code like gcc 4.3.

In a way, I like the change. Before, the expansion has always been done twice - once
before returning and once when interpreting the return value. Now that redundancy is
gone. And this is a good thing. It's very similar to that whole cld issue
<>, except that the ABI specification is crystal clear
for the direction flag, something which cannot be said about the return value issue.

Comment #16 by on 2008-06-11 23:21:03

Created an attachment (id=43)

First part (i386). Now I know what you meant with that nibbles comment...

Comment #17 by on 2008-06-11 23:34:54

Created an attachment (id=44)

This should do it for x86_64...

Comment #18 by on 2008-06-11 23:43:48


Comment #19 by on 2008-06-12 10:04:03

Thanks for fixing this one.

Attachment id=41

date:2008-06-09 18:38
desc:hg export of fix

Attachment id=43

date:2008-06-11 23:21

Attachment id=44

date:2008-06-11 23:34