Add support for 8-byte struct returns, Mac OS X Intel style

slava 2006-07-06 07:04:58 +00:00
parent 200dbc4edd
commit 6a862a9696
8 changed files with 61 additions and 7 deletions

View File

@ -10,7 +10,7 @@ parser sequences sequences-internals words ;
"Cross-referencing..." print flush
H{ } clone crossref set-global xref-words
cpu { "x86" "pentium4" } member? [
cpu "x86" = [
macosx?
"/library/compiler/x86/alien-macosx.factor"
"/library/compiler/x86/alien.factor"

View File

@ -1,7 +1,7 @@
! Copyright (C) 2005, 2006 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
IN: compiler
USING: assembler kernel kernel-internals math namespaces ;
USING: assembler errors kernel kernel-internals math namespaces ;
! OS X uses a different ABI. The stack must be 16-byte aligned.
@ -43,9 +43,26 @@ USING: assembler kernel kernel-internals math namespaces ;
! Store the return value on the C stack
store-return-reg ;
: %box-pair ( -- )
#! Box an 8-byte struct returned in EAX:EDX.
#! Why did Apple have to make things so complex?
#! Just use objc_msgSend_stret for all structs... jesus.
8 [
EDX PUSH
EAX PUSH
"box_value_pair" f %alien-invoke
] with-aligned-stack ;
: %box-struct ( n size -- )
>r stack-increment + cell + r>
"box_value_struct" struct-ptr/size ;
over [
>r stack-increment + cell + r>
"box_value_struct" struct-ptr/size
] [
nip 8 = [
"Cannot %box-struct which is not 8 bytes." throw
] unless
%box-pair
] if ;
: box@ ( n reg-class -- stack@ )
#! Used for callbacks; we want to box the values given to

View File

@ -67,3 +67,10 @@ FUNCTION: int ffi_test_12 int a int b rect c int d int e int f ; compiled
FUNCTION: int ffi_test_13 int a int b int c int d int e int f int g int h int i int j int k ; compiled
[ 66 ] [ 1 2 3 4 5 6 7 8 9 10 11 ffi_test_13 ] unit-test
FUNCTION: foo ffi_test_14 int x int y ;
cpu "x86" = macosx? and [
\ ffi_test_14 compile
[ 11 6 ] [ 11 6 ffi_test_14 dup foo-x swap foo-y ] unit-test
] when

View File

@ -16,8 +16,19 @@ kernel libc math namespaces parser sequences strings words ;
{ "void*" } swap second append ,
] make-alien-invoke ;
: use-stret? ( type -- ? )
#! We use the objc_msgSend_stret form in either of the
#! following two cases:
#! - type is a struct, and we're on PowerPC
#! - type is a struct <= 8 bytes, and we're on x86
{
{ [ dup c-struct? not ] [ drop f ] }
{ [ cpu "ppc" = ] [ drop t ] }
{ [ cpu "x86" = ] [ c-size 8 > ] }
} cond ;
: sender-stub ( method function -- word )
over first c-struct?
over first use-stret?
[ make-sender-stret ] [ make-sender ] if
define-temp ;
@ -77,7 +88,7 @@ H{ } clone objc-methods set-global
first [ <c-object> dup ] curry 1 make-dip ;
: stret-prolog ( type -- )
dup c-struct?
dup use-stret?
[ [ >r ] % , [ <malloc-object> dup r> ] % ] [ drop ] if ;
: make-prepare-send ( selector method super? -- quot )
@ -91,7 +102,7 @@ H{ } clone objc-methods set-global
dup <c-object> -rot c-size >r 2dup r> memcpy free ;
: stret-epilog ( type -- )
dup c-struct? [ , \ block>byte-array , ] [ drop ] if ;
dup use-stret? [ , \ block>byte-array , ] [ drop ] if ;
: make-objc-send ( selector super? -- quot )
[

View File

@ -144,3 +144,13 @@ void box_value_struct(void *src, CELL size)
memcpy(array + 1,src,size);
dpush(tag_object(array));
}
/* for FFI calls returning an 8-byte struct. This only
happends on Intel Mac OS X */
void box_value_pair(CELL x, CELL y)
{
F_ARRAY *array = byte_array(8);
put(AREF(array,0),x);
put(AREF(array,1),y);
dpush(tag_object(array));
}

View File

@ -51,3 +51,4 @@ void primitive_set_alien_double(void);
DLLEXPORT void unbox_value_struct(void *dest, CELL size);
DLLEXPORT void box_value_struct(void *src, CELL size);
DLLEXPORT void box_value_pair(CELL x, CELL y);

View File

@ -87,6 +87,13 @@ int ffi_test_13(int a, int b, int c, int d, int e, int f, int g, int h, int i, i
return a + b + c + d + e + f + g + h + i + j + k;
}
struct foo ffi_test_14(int x, int y)
{
struct foo r;
r.x = x; r.y = y;
return r;
}
void callback_test_1(void (*callback)(void))
{
printf("callback_test_1 entry\n");

View File

@ -14,6 +14,7 @@ DLLEXPORT int ffi_test_11(int a, struct foo b, int c);
struct rect { float x, y, w, h; };
DLLEXPORT int ffi_test_12(int a, int b, struct rect c, int d, int e, int f);
DLLEXPORT int ffi_test_13(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k);
DLLEXPORT struct foo ffi_test_14(int x, int y);
DLLEXPORT void callback_test_1(void (*callback)(void));
DLLEXPORT void callback_test_2(void (*callback)(int x, int y), int x, int y);
DLLEXPORT void callback_test_3(void (*callback)(int x, double y, int z), int x, double y, int z);