Add support for 8-byte struct returns, Mac OS X Intel style
parent
200dbc4edd
commit
6a862a9696
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 )
|
||||
[
|
||||
|
|
10
vm/alien.c
10
vm/alien.c
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue