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
|
"Cross-referencing..." print flush
|
||||||
H{ } clone crossref set-global xref-words
|
H{ } clone crossref set-global xref-words
|
||||||
|
|
||||||
cpu { "x86" "pentium4" } member? [
|
cpu "x86" = [
|
||||||
macosx?
|
macosx?
|
||||||
"/library/compiler/x86/alien-macosx.factor"
|
"/library/compiler/x86/alien-macosx.factor"
|
||||||
"/library/compiler/x86/alien.factor"
|
"/library/compiler/x86/alien.factor"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
! Copyright (C) 2005, 2006 Slava Pestov.
|
! Copyright (C) 2005, 2006 Slava Pestov.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
IN: compiler
|
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.
|
! 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 the return value on the C stack
|
||||||
store-return-reg ;
|
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 -- )
|
: %box-struct ( n size -- )
|
||||||
>r stack-increment + cell + r>
|
over [
|
||||||
"box_value_struct" struct-ptr/size ;
|
>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@ )
|
: box@ ( n reg-class -- stack@ )
|
||||||
#! Used for callbacks; we want to box the values given to
|
#! 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
|
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
|
[ 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 ,
|
{ "void*" } swap second append ,
|
||||||
] make-alien-invoke ;
|
] 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 )
|
: sender-stub ( method function -- word )
|
||||||
over first c-struct?
|
over first use-stret?
|
||||||
[ make-sender-stret ] [ make-sender ] if
|
[ make-sender-stret ] [ make-sender ] if
|
||||||
define-temp ;
|
define-temp ;
|
||||||
|
|
||||||
|
@ -77,7 +88,7 @@ H{ } clone objc-methods set-global
|
||||||
first [ <c-object> dup ] curry 1 make-dip ;
|
first [ <c-object> dup ] curry 1 make-dip ;
|
||||||
|
|
||||||
: stret-prolog ( type -- )
|
: stret-prolog ( type -- )
|
||||||
dup c-struct?
|
dup use-stret?
|
||||||
[ [ >r ] % , [ <malloc-object> dup r> ] % ] [ drop ] if ;
|
[ [ >r ] % , [ <malloc-object> dup r> ] % ] [ drop ] if ;
|
||||||
|
|
||||||
: make-prepare-send ( selector method super? -- quot )
|
: 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 ;
|
dup <c-object> -rot c-size >r 2dup r> memcpy free ;
|
||||||
|
|
||||||
: stret-epilog ( type -- )
|
: 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 )
|
: 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);
|
memcpy(array + 1,src,size);
|
||||||
dpush(tag_object(array));
|
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 unbox_value_struct(void *dest, CELL size);
|
||||||
DLLEXPORT void box_value_struct(void *src, 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;
|
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))
|
void callback_test_1(void (*callback)(void))
|
||||||
{
|
{
|
||||||
printf("callback_test_1 entry\n");
|
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; };
|
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_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 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_1(void (*callback)(void));
|
||||||
DLLEXPORT void callback_test_2(void (*callback)(int x, int y), int x, int y);
|
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);
|
DLLEXPORT void callback_test_3(void (*callback)(int x, double y, int z), int x, double y, int z);
|
||||||
|
|
Loading…
Reference in New Issue