[fpc-devel] Bug (Severe): Floating point values completely break GCC Struct compatability with records in 64-bit
Joshua Cearley
joshua.cearley at gmail.com
Wed Dec 16 12:26:27 CET 2009
While working on a binding for the development branch for the Allegro
game library I ran in to a bit of a problem in that one of the methods
takes a structure of four floating point values (which is how it stores
colors) and this is not done through a pointer to a color struct but by
passing the structure directly to the method; this never actually works
and exploring with GCC shows that the should-be C compatible record
built by FPC 2.5 was fine but the version C had was corrupted. I went to
FPC 2.4rc1 and tried again, and the same issue remains. 32-bit builds
seem to work properly, so I conclude that only the 64-bit version of FPC
is emitting broken code.
The following was generated with 2.4rc1;
Recreating this problem is fairly simple; first you have a source file
written in C code `cpart.c`:
/* Start */
#include <stdio.h>
struct Bagel
{
float roundness, tastiness;
};
void PrintBagel(struct Bagel b)
{
printf("[Bagel Round:%f Tasty:%f]\n", b.roundness, b.tastiness);
}
/* End */
Then you have the trivial Pascal application `ppart.pp`:
(* Start *)
program ppart;
{$LINK cpart}
uses ctypes;
type
{$PACKRECORDS C}
TBagel = record
roundness, tastiness : CFloat;
end;
Procedure PrintBagel(bagel : TBagel); cdecl; external;
var
b : TBagel;
begin
b.roundness := 42.0;
b.tastiness := 1.0;
PrintBagel(b);
end.
(* End *)
Then we compile these:
skrylar)fpc-bug % gcc -c cpart.c && ppcx64 ppart
Free Pascal Compiler version 2.4.0rc1 [2009/10/24] for x86_64
Copyright (c) 1993-2009 by Florian Klaempfl
Target OS: Darwin for x86_64
Compiling ppart.pp
Assembling ppart
Linking ppart
22 lines compiled, 0.1 sec
skrylar)fpc-bug %
Run it:
skrylar)fpc-bug % ./ppart
[Bagel Round:0.000000 Tasty:-170141183460469231731687303715884105728.000000]
skrylar)fpc-bug %
Disassembling through GDB (AT&T Syntax ahead):
Dump of assembler code for function PASCALMAIN:
0x00000001000009f0 <PASCALMAIN+0>: push %rbp
0x00000001000009f1 <PASCALMAIN+1>: mov %rsp,%rbp
0x00000001000009f4 <PASCALMAIN+4>: callq 0x100013970
<fpc_initializeunits>
0x00000001000009f9 <PASCALMAIN+9>: lea 0x1d218(%rip),%rax
# 0x10001dc18 <$PPART$_Ld1>
0x0000000100000a00 <PASCALMAIN+16>: mov (%rax),%eax
0x0000000100000a02 <PASCALMAIN+18>: lea 0x2329f(%rip),%rdx
# 0x100023ca8 <U_P$PPART_B>
0x0000000100000a09 <PASCALMAIN+25>: mov %eax,(%rdx)
0x0000000100000a0b <PASCALMAIN+27>: lea 0x1d20a(%rip),%rax
# 0x10001dc1c <$PPART$_Ld2>
0x0000000100000a12 <PASCALMAIN+34>: mov (%rax),%eax
0x0000000100000a14 <PASCALMAIN+36>: lea 0x2328d(%rip),%rdx
# 0x100023ca8 <U_P$PPART_B>
0x0000000100000a1b <PASCALMAIN+43>: mov %eax,0x4(%rdx)
0x0000000100000a1e <PASCALMAIN+46>: lea 0x23283(%rip),%rax
# 0x100023ca8 <U_P$PPART_B>
0x0000000100000a25 <PASCALMAIN+53>: mov (%rax),%rdi
0x0000000100000a28 <PASCALMAIN+56>: callq 0x100000a3c <PrintBagel>
0x0000000100000a2d <PASCALMAIN+61>: callq 0x100013d70 <SYSTEM_DO_EXIT>
0x0000000100000a32 <PASCALMAIN+66>: leaveq
0x0000000100000a33 <PASCALMAIN+67>: retq
End of assembler dump.
Dump of assembler code for function PrintBagel:
0x0000000100000a3c <PrintBagel+0>: push %rbp
0x0000000100000a3d <PrintBagel+1>: mov %rsp,%rbp
0x0000000100000a40 <PrintBagel+4>: sub $0x10,%rsp
0x0000000100000a44 <PrintBagel+8>: movq %xmm0,-0x8(%rbp)
0x0000000100000a49 <PrintBagel+13>: movss -0x4(%rbp),%xmm0
0x0000000100000a4e <PrintBagel+18>: cvtss2sd %xmm0,%xmm1
0x0000000100000a52 <PrintBagel+22>: movss -0x8(%rbp),%xmm0
0x0000000100000a57 <PrintBagel+27>: cvtss2sd %xmm0,%xmm0
0x0000000100000a5b <PrintBagel+31>: lea 0x1d164(%rip),%rdi
# 0x10001dbc6
0x0000000100000a62 <PrintBagel+38>: mov $0x2,%eax
0x0000000100000a67 <PrintBagel+43>: callq 0x10001d976
<dyld_stub_printf>
0x0000000100000a6c <PrintBagel+48>: leaveq
0x0000000100000a6d <PrintBagel+49>: retq
0x0000000100000a6e <PrintBagel+50>: nop
0x0000000100000a6f <PrintBagel+51>: nop
End of assembler dump.
I asked in IRC and was referred to here; unfortunately with Snow Leopard
GCC compiles in 64-bit by default and so falling back to 32-bit is
exceptionally painful.
More information about the fpc-devel
mailing list