From 6a862a96962e35adc5c84ae070b1fe00ba9750cc Mon Sep 17 00:00:00 2001 From: slava Date: Thu, 6 Jul 2006 07:04:58 +0000 Subject: [PATCH] Add support for 8-byte struct returns, Mac OS X Intel style --- library/bootstrap/boot-stage2.factor | 2 +- library/compiler/x86/alien-macosx.factor | 23 ++++++++++++++++++++--- library/test/compiler/alien.factor | 7 +++++++ library/ui/cocoa/utilities.factor | 17 ++++++++++++++--- vm/alien.c | 10 ++++++++++ vm/alien.h | 1 + vm/ffi_test.c | 7 +++++++ vm/ffi_test.h | 1 + 8 files changed, 61 insertions(+), 7 deletions(-) diff --git a/library/bootstrap/boot-stage2.factor b/library/bootstrap/boot-stage2.factor index d409c32a23..5e64d44ead 100644 --- a/library/bootstrap/boot-stage2.factor +++ b/library/bootstrap/boot-stage2.factor @@ -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" diff --git a/library/compiler/x86/alien-macosx.factor b/library/compiler/x86/alien-macosx.factor index e93380c019..23f8937a57 100644 --- a/library/compiler/x86/alien-macosx.factor +++ b/library/compiler/x86/alien-macosx.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 diff --git a/library/test/compiler/alien.factor b/library/test/compiler/alien.factor index e40120fa15..f162806231 100644 --- a/library/test/compiler/alien.factor +++ b/library/test/compiler/alien.factor @@ -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 diff --git a/library/ui/cocoa/utilities.factor b/library/ui/cocoa/utilities.factor index 746b942699..a593d15a71 100644 --- a/library/ui/cocoa/utilities.factor +++ b/library/ui/cocoa/utilities.factor @@ -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 [ dup ] curry 1 make-dip ; : stret-prolog ( type -- ) - dup c-struct? + dup use-stret? [ [ >r ] % , [ dup r> ] % ] [ drop ] if ; : make-prepare-send ( selector method super? -- quot ) @@ -91,7 +102,7 @@ H{ } clone objc-methods set-global dup -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 ) [ diff --git a/vm/alien.c b/vm/alien.c index 44166ec86e..cd8baf2276 100644 --- a/vm/alien.c +++ b/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)); +} diff --git a/vm/alien.h b/vm/alien.h index d693815d21..f4051d3795 100644 --- a/vm/alien.h +++ b/vm/alien.h @@ -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); diff --git a/vm/ffi_test.c b/vm/ffi_test.c index ea84058baa..99b6fb5833 100644 --- a/vm/ffi_test.c +++ b/vm/ffi_test.c @@ -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"); diff --git a/vm/ffi_test.h b/vm/ffi_test.h index 46ff6f1bf5..9d47ef416e 100644 --- a/vm/ffi_test.h +++ b/vm/ffi_test.h @@ -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);