C calling convention broken when passing structures larger than two integers.
Original Reporter info from Mantis: Flawless
-
Reporter name: Christian Iversen
Original Reporter info from Mantis: Flawless
- Reporter name: Christian Iversen
Description:
If a structure is passed by value rather than reference, and is larger than 2 integers, and the calling convention is cdecl, the call will fail.
On page 13 and 16 in this pdf file:
http://www.agner.org/optimize/calling_conventions.pdf
it's quite clearly shown that objects larger than two registers should always be passed on the stack for cdecl (at least on linux, I think the rules are different for windows).
fpc currently tries to pass all 5 arguments in the example program in registers, which causes it to fail.
Steps to reproduce:
compile gcc program with: gcc -masm=intel -fverbose-asm -save-temps -c test.c
compile fpc program with: fpc -al testp.pas
testp.pas:
program testp;
uses
ctypes, vorbis;
{$LINKLIB 'c'}
{$LINK 'test'}
function ov_open_callbacks_foo(datasource: pointer; var vf: OggVorbis_File; initial: pointer; ibytes: clong; callbacks: ov_callbacks): cint; cdecl; external;
var
vf: OggVorbis_File;
cb: ov_callbacks;
begin
cb.read := read_func(pointer(10));
cb.seek := seek_func(pointer(20));
cb.close := close_func(pointer(30));
cb.tell := tell_func(pointer(40));
ov_open_callbacks_foo(pointer(1), vf, pointer(3), 4, cb);
end.
#include &LtPos;stdio.h>
#include &LtPos;vorbis/vorbisfile.h>
int ov_open_callbacks_foo(void *datasource, OggVorbis_File *vf, char *initial, long ibytes, ov_callbacks callbacks) {
printf("%p:%p:%p:%d:%p\n", datasource, vf, initial, ibytes, callbacks);
}
Mantis conversion info:
- Mantis ID: 7453
- OS: Linux
- OS Build: 2.6.15
- Build: [2006/09/21] for x86_64
- Platform: Amd64
- Version: 2.2.0
- Fixed in version: 2.2.0
- Fixed in revision: 4688 (#360cbe1d)