Working on Win64 FFI

db4
unknown 2008-11-08 21:40:47 -06:00
parent 8c29599e97
commit f7fe84e563
9 changed files with 117 additions and 68 deletions

View File

@ -1,6 +1,6 @@
! Copyright (C) 2008 Slava Pestov. ! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: namespaces make math math.parser sequences accessors USING: namespaces make math math.order math.parser sequences accessors
kernel kernel.private layouts assocs words summary arrays kernel kernel.private layouts assocs words summary arrays
combinators classes.algebra alien alien.c-types alien.structs combinators classes.algebra alien alien.c-types alien.structs
alien.strings alien.arrays sets threads libc continuations.private alien.strings alien.arrays sets threads libc continuations.private
@ -234,13 +234,26 @@ M: float-regs reg-class-variable drop float-regs ;
GENERIC: inc-reg-class ( register-class -- ) GENERIC: inc-reg-class ( register-class -- )
M: reg-class inc-reg-class : ?dummy-stack-params ( reg-class -- )
dup reg-class-variable inc dummy-stack-params? [ reg-size stack-params +@ ] [ drop ] if ;
fp-shadows-int? [ reg-size stack-params +@ ] [ drop ] if ;
: ?dummy-int-params ( reg-class -- )
dummy-int-params? [ reg-size cell /i 1 max int-regs +@ ] [ drop ] if ;
: ?dummy-fp-params ( reg-class -- )
drop dummy-fp-params? [ float-regs inc ] when ;
M: int-regs inc-reg-class
[ reg-class-variable inc ]
[ ?dummy-stack-params ]
[ ?dummy-fp-params ]
tri ;
M: float-regs inc-reg-class M: float-regs inc-reg-class
dup call-next-method [ reg-class-variable inc ]
fp-shadows-int? [ reg-size cell /i int-regs +@ ] [ drop ] if ; [ ?dummy-stack-params ]
[ ?dummy-int-params ]
tri ;
GENERIC: reg-class-full? ( class -- ? ) GENERIC: reg-class-full? ( class -- ? )

View File

@ -146,8 +146,14 @@ HOOK: struct-small-enough? cpu ( heap-size -- ? )
! Do we pass value structs by value or hidden reference? ! Do we pass value structs by value or hidden reference?
HOOK: value-structs? cpu ( -- ? ) HOOK: value-structs? cpu ( -- ? )
! If t, fp parameters are shadowed by dummy int parameters ! If t, all parameters are shadowed by dummy stack parameters
HOOK: fp-shadows-int? cpu ( -- ? ) HOOK: dummy-stack-params? cpu ( -- ? )
! If t, all FP parameters are shadowed by dummy int parameters
HOOK: dummy-int-params? cpu ( -- ? )
! If t, all int parameters are shadowed by dummy FP parameters
HOOK: dummy-fp-params? cpu ( -- ? )
HOOK: %prepare-unbox cpu ( -- ) HOOK: %prepare-unbox cpu ( -- )

View File

@ -14,6 +14,10 @@ M: linux lr-save 1 ;
M: float-regs param-regs { 1 2 3 4 5 6 7 8 } ; M: float-regs param-regs { 1 2 3 4 5 6 7 8 } ;
M: ppc value-structs? drop f ; M: ppc value-structs? f ;
M: ppc fp-shadows-int? drop f ; M: ppc dummy-stack-params? f ;
M: ppc dummy-int-params? f ;
M: ppc dummy-fp-params? f ;

View File

@ -15,6 +15,10 @@ M: macosx lr-save 2 ;
M: float-regs param-regs { 1 2 3 4 5 6 7 8 9 10 11 12 13 } ; M: float-regs param-regs { 1 2 3 4 5 6 7 8 9 10 11 12 13 } ;
M: ppc value-structs? drop t ; M: ppc value-structs? t ;
M: ppc fp-shadows-int? drop t ; M: ppc dummy-stack-params? t ;
M: ppc dummy-int-params? t ;
M: ppc dummy-fp-params? f ;

View File

@ -274,6 +274,12 @@ M: x86.32 %callback-return ( n -- )
[ drop 0 ] [ drop 0 ]
} cond RET ; } cond RET ;
M: x86.32 dummy-stack-params? f ;
M: x86.32 dummy-int-params? f ;
M: x86.32 dummy-fp-params? f ;
os windows? [ os windows? [
cell "longlong" c-type (>>align) cell "longlong" c-type (>>align)
cell "ulonglong" c-type (>>align) cell "ulonglong" c-type (>>align)

View File

@ -26,6 +26,7 @@ M: x86.64 temp-reg-2 RCX ;
: param-reg-1 int-regs param-regs first ; inline : param-reg-1 int-regs param-regs first ; inline
: param-reg-2 int-regs param-regs second ; inline : param-reg-2 int-regs param-regs second ; inline
: param-reg-3 int-regs param-regs third ; inline
M: int-regs return-reg drop RAX ; M: int-regs return-reg drop RAX ;
M: float-regs return-reg drop XMM0 ; M: float-regs return-reg drop XMM0 ;
@ -40,13 +41,13 @@ M: x86.64 %prologue ( n -- )
M: stack-params %load-param-reg M: stack-params %load-param-reg
drop drop
>r R11 swap stack@ MOV >r R11 swap param@ MOV
r> stack@ R11 MOV ; r> param@ R11 MOV ;
M: stack-params %save-param-reg M: stack-params %save-param-reg
drop drop
R11 swap next-stack@ MOV R11 swap next-stack@ MOV
stack@ R11 MOV ; param@ R11 MOV ;
: with-return-regs ( quot -- ) : with-return-regs ( quot -- )
[ [
@ -55,37 +56,6 @@ M: stack-params %save-param-reg
call call
] with-scope ; inline ] with-scope ; inline
! The ABI for passing structs by value is pretty messed up
<< "void*" c-type clone "__stack_value" define-primitive-type
stack-params "__stack_value" c-type (>>reg-class) >>
: struct-types&offset ( struct-type -- pairs )
fields>> [
[ type>> ] [ offset>> ] bi 2array
] map ;
: split-struct ( pairs -- seq )
[
[ 8 mod zero? [ t , ] when , ] assoc-each
] { } make { t } split harvest ;
: flatten-small-struct ( c-type -- seq )
struct-types&offset split-struct [
[ c-type c-type-reg-class ] map
int-regs swap member? "void*" "double" ? c-type
] map ;
: flatten-large-struct ( c-type -- seq )
heap-size cell align
cell /i "__stack_value" c-type <repetition> ;
M: struct-type flatten-value-type ( type -- seq )
dup heap-size 16 > [
flatten-large-struct
] [
flatten-small-struct
] if ;
M: x86.64 %prepare-unbox ( -- ) M: x86.64 %prepare-unbox ( -- )
! First parameter is top of stack ! First parameter is top of stack
param-reg-1 R14 [] MOV param-reg-1 R14 [] MOV
@ -102,7 +72,7 @@ M: x86.64 %unbox-long-long ( n func -- )
: %unbox-struct-field ( c-type i -- ) : %unbox-struct-field ( c-type i -- )
! Alien must be in param-reg-1. ! Alien must be in param-reg-1.
param-reg-1 swap cells [+] swap reg-class>> { R11 swap cells [+] swap reg-class>> {
{ int-regs [ int-regs get pop swap MOV ] } { int-regs [ int-regs get pop swap MOV ] }
{ double-float-regs [ float-regs get pop swap MOVSD ] } { double-float-regs [ float-regs get pop swap MOVSD ] }
} case ; } case ;
@ -110,20 +80,20 @@ M: x86.64 %unbox-long-long ( n func -- )
M: x86.64 %unbox-small-struct ( c-type -- ) M: x86.64 %unbox-small-struct ( c-type -- )
! Alien must be in param-reg-1. ! Alien must be in param-reg-1.
"alien_offset" f %alien-invoke "alien_offset" f %alien-invoke
! Move alien_offset() return value to param-reg-1 so that we don't ! Move alien_offset() return value to R11 so that we don't
! clobber it. ! clobber it.
param-reg-1 RAX MOV R11 RAX MOV
[ [
flatten-small-struct [ %unbox-struct-field ] each-index flatten-value-type [ %unbox-struct-field ] each-index
] with-return-regs ; ] with-return-regs ;
M: x86.64 %unbox-large-struct ( n c-type -- ) M: x86.64 %unbox-large-struct ( n c-type -- )
! Source is in param-reg-1 ! Source is in param-reg-1
heap-size heap-size
! Load destination address ! Load destination address
param-reg-2 rot stack@ LEA param-reg-2 rot param@ LEA
! Load structure size ! Load structure size
RDX swap MOV param-reg-3 swap MOV
! Copy the struct to the C stack ! Copy the struct to the C stack
"to_value_struct" f %alien-invoke ; "to_value_struct" f %alien-invoke ;
@ -142,10 +112,7 @@ M: x86.64 %box ( n reg-class func -- )
M: x86.64 %box-long-long ( n func -- ) M: x86.64 %box-long-long ( n func -- )
int-regs swap %box ; int-regs swap %box ;
M: x86.64 struct-small-enough? ( size -- ? ) : box-struct-field@ ( i -- operand ) 1+ cells param@ ;
heap-size 2 cells <= ;
: box-struct-field@ ( i -- operand ) 1+ cells stack@ ;
: %box-struct-field ( c-type i -- ) : %box-struct-field ( c-type i -- )
box-struct-field@ swap reg-class>> { box-struct-field@ swap reg-class>> {
@ -156,15 +123,15 @@ M: x86.64 struct-small-enough? ( size -- ? )
M: x86.64 %box-small-struct ( c-type -- ) M: x86.64 %box-small-struct ( c-type -- )
#! Box a <= 16-byte struct. #! Box a <= 16-byte struct.
[ [
[ flatten-small-struct [ %box-struct-field ] each-index ] [ flatten-value-type [ %box-struct-field ] each-index ]
[ RDX swap heap-size MOV ] bi [ param-reg-3 swap heap-size MOV ] bi
param-reg-1 0 box-struct-field@ MOV param-reg-1 0 box-struct-field@ MOV
param-reg-2 1 box-struct-field@ MOV param-reg-2 1 box-struct-field@ MOV
"box_small_struct" f %alien-invoke "box_small_struct" f %alien-invoke
] with-return-regs ; ] with-return-regs ;
: struct-return@ ( n -- operand ) : struct-return@ ( n -- operand )
[ stack-frame get params>> ] unless* stack@ ; [ stack-frame get params>> ] unless* param@ ;
M: x86.64 %box-large-struct ( n c-type -- ) M: x86.64 %box-large-struct ( n c-type -- )
! Struct size is parameter 2 ! Struct size is parameter 2
@ -178,7 +145,7 @@ M: x86.64 %prepare-box-struct ( -- )
! Compute target address for value struct return ! Compute target address for value struct return
RAX f struct-return@ LEA RAX f struct-return@ LEA
! Store it as the first parameter ! Store it as the first parameter
0 stack@ RAX MOV ; 0 param@ RAX MOV ;
M: x86.64 %prepare-var-args RAX RAX XOR ; M: x86.64 %prepare-var-args RAX RAX XOR ;

View File

@ -10,3 +10,43 @@ M: float-regs param-regs
drop { XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7 } ; drop { XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7 } ;
M: x86.64 reserved-area-size 0 ; M: x86.64 reserved-area-size 0 ;
! The ABI for passing structs by value is pretty messed up
<< "void*" c-type clone "__stack_value" define-primitive-type
stack-params "__stack_value" c-type (>>reg-class) >>
: struct-types&offset ( struct-type -- pairs )
fields>> [
[ type>> ] [ offset>> ] bi 2array
] map ;
: split-struct ( pairs -- seq )
[
[ 8 mod zero? [ t , ] when , ] assoc-each
] { } make { t } split harvest ;
: flatten-small-struct ( c-type -- seq )
struct-types&offset split-struct [
[ c-type c-type-reg-class ] map
int-regs swap member? "void*" "double" ? c-type
] map ;
: flatten-large-struct ( c-type -- seq )
heap-size cell align
cell /i "__stack_value" c-type <repetition> ;
M: struct-type flatten-value-type ( type -- seq )
dup heap-size 16 > [
flatten-large-struct
] [
flatten-small-struct
] if ;
M: x86.64 struct-small-enough? ( size -- ? )
heap-size 2 cells <= ;
M: x86.64 dummy-stack-params? f ;
M: x86.64 dummy-int-params? f ;
M: x86.64 dummy-fp-params? f ;

View File

@ -1,7 +1,7 @@
! Copyright (C) 2008 Slava Pestov. ! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel layouts system alien.c-types compiler.cfg.registers USING: kernel layouts system math alien.c-types
cpu.architecture cpu.x86.assembler cpu.x86 ; compiler.cfg.registers cpu.architecture cpu.x86.assembler cpu.x86 ;
IN: cpu.x86.64.winnt IN: cpu.x86.64.winnt
M: int-regs param-regs drop { RCX RDX R8 R9 } ; M: int-regs param-regs drop { RCX RDX R8 R9 } ;
@ -10,6 +10,15 @@ M: float-regs param-regs drop { XMM0 XMM1 XMM2 XMM3 } ;
M: x86.64 reserved-area-size 4 cells ; M: x86.64 reserved-area-size 4 cells ;
M: x86.64 struct-small-enough? ( size -- ? )
heap-size cell <= ;
M: x86.64 dummy-stack-params? f ;
M: x86.64 dummy-int-params? t ;
M: x86.64 dummy-fp-params? t ;
<< <<
"longlong" "ptrdiff_t" typedef "longlong" "ptrdiff_t" typedef
"int" "long" typedef "int" "long" typedef

View File

@ -467,6 +467,8 @@ M: x86 %compare-float-branch ( label cc src1 src2 -- )
: stack@ ( n -- op ) stack-reg swap [+] ; : stack@ ( n -- op ) stack-reg swap [+] ;
: param@ ( n -- op ) reserved-area-size + stack@ ;
: spill-integer-base ( stack-frame -- n ) : spill-integer-base ( stack-frame -- n )
[ params>> ] [ return>> ] bi + reserved-area-size + ; [ params>> ] [ return>> ] bi + reserved-area-size + ;
@ -493,16 +495,16 @@ M: x86 %reload-float ( dst n -- ) spill-float@ MOVSD ;
M: x86 %loop-entry 16 code-alignment [ NOP ] times ; M: x86 %loop-entry 16 code-alignment [ NOP ] times ;
M: int-regs %save-param-reg drop >r stack@ r> MOV ; M: int-regs %save-param-reg drop >r param@ r> MOV ;
M: int-regs %load-param-reg drop swap stack@ MOV ; M: int-regs %load-param-reg drop swap param@ MOV ;
GENERIC: MOVSS/D ( dst src reg-class -- ) GENERIC: MOVSS/D ( dst src reg-class -- )
M: single-float-regs MOVSS/D drop MOVSS ; M: single-float-regs MOVSS/D drop MOVSS ;
M: double-float-regs MOVSS/D drop MOVSD ; M: double-float-regs MOVSS/D drop MOVSD ;
M: float-regs %save-param-reg >r >r stack@ r> r> MOVSS/D ; M: float-regs %save-param-reg >r >r param@ r> r> MOVSS/D ;
M: float-regs %load-param-reg >r swap stack@ r> MOVSS/D ; M: float-regs %load-param-reg >r swap param@ r> MOVSS/D ;
GENERIC: push-return-reg ( reg-class -- ) GENERIC: push-return-reg ( reg-class -- )
GENERIC: load-return-reg ( n reg-class -- ) GENERIC: load-return-reg ( n reg-class -- )
@ -518,8 +520,6 @@ M: x86 %prepare-alien-invoke
temp-reg-1 2 cells [+] ds-reg MOV temp-reg-1 2 cells [+] ds-reg MOV
temp-reg-1 3 cells [+] rs-reg MOV ; temp-reg-1 3 cells [+] rs-reg MOV ;
M: x86 fp-shadows-int? ( -- ? ) f ;
M: x86 value-structs? t ; M: x86 value-structs? t ;
M: x86 small-enough? ( n -- ? ) M: x86 small-enough? ( n -- ? )