[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;

	TBagel = record
		roundness, tastiness : CFloat;

Procedure PrintBagel(bagel : TBagel); cdecl; external;

	b : TBagel;
	b.roundness := 42.0;
	b.tastiness := 1.0;
(* 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 
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 
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