Adding FFI to new front-end

db4
Slava Pestov 2008-08-12 02:41:18 -05:00
parent d42edecffb
commit aededc406f
15 changed files with 181 additions and 16 deletions

View File

@ -2,6 +2,12 @@ IN: alien.c-types.tests
USING: alien alien.syntax alien.c-types kernel tools.test USING: alien alien.syntax alien.c-types kernel tools.test
sequences system libc alien.strings io.encodings.utf8 ; sequences system libc alien.strings io.encodings.utf8 ;
\ expand-constants must-infer
: xyz 123 ;
[ { "blah" 123 } ] [ { "blah" xyz } expand-constants ] unit-test
: foo ( -- n ) "fdafd" f dlsym [ 123 ] unless* ; : foo ( -- n ) "fdafd" f dlsym [ 123 ] unless* ;
[ 123 ] [ foo ] unit-test [ 123 ] [ foo ] unit-test

View File

@ -4,7 +4,7 @@ USING: byte-arrays arrays assocs kernel kernel.private libc math
namespaces parser sequences strings words assocs splitting namespaces parser sequences strings words assocs splitting
math.parser cpu.architecture alien alien.accessors quotations math.parser cpu.architecture alien alien.accessors quotations
layouts system compiler.units io.files io.encodings.binary layouts system compiler.units io.files io.encodings.binary
accessors combinators effects ; accessors combinators effects continuations ;
IN: alien.c-types IN: alien.c-types
DEFER: <int> DEFER: <int>
@ -239,15 +239,20 @@ M: long-long-type box-return ( type -- )
} 2cleave ; } 2cleave ;
: expand-constants ( c-type -- c-type' ) : expand-constants ( c-type -- c-type' )
#! We use def>> call instead of execute to get around
#! staging violations
dup array? [ dup array? [
unclip >r [ dup word? [ def>> call ] when ] map r> prefix unclip >r [
dup word? [
def>> { } swap with-datastack first
] when
] map r> prefix
] when ; ] when ;
: malloc-file-contents ( path -- alien len ) : malloc-file-contents ( path -- alien len )
binary file-contents dup malloc-byte-array swap length ; binary file-contents dup malloc-byte-array swap length ;
: if-void ( type true false -- )
pick "void" = [ drop nip call ] [ nip call ] if ; inline
[ [
<c-type> <c-type>
[ alien-cell ] >>getter [ alien-cell ] >>getter

View File

@ -35,6 +35,12 @@ M: #phi backward
[ [ out-r>> ] [ phi-in-r>> ] bi look-at-corresponding ] [ [ out-r>> ] [ phi-in-r>> ] bi look-at-corresponding ]
2bi ; 2bi ;
M: #alien-invoke backward
nip [ look-at-inputs ] [ look-at-outputs ] bi ;
M: #alien-indirect backward
nip [ look-at-inputs ] [ look-at-outputs ] bi ;
M: node backward 2drop ; M: node backward 2drop ;
: backward-dfa ( node quot -- assoc ) [ backward ] dfa ; inline : backward-dfa ( node quot -- assoc ) [ backward ] dfa ; inline

View File

@ -23,6 +23,12 @@ M: #call mark-live-values
dup word>> "flushable" word-prop dup word>> "flushable" word-prop
[ drop ] [ [ look-at-inputs ] [ look-at-outputs ] bi ] if ; [ drop ] [ [ look-at-inputs ] [ look-at-outputs ] bi ] if ;
M: #alien-invoke mark-live-values
[ look-at-inputs ] [ look-at-outputs ] bi ;
M: #alien-indirect mark-live-values
[ look-at-inputs ] [ look-at-outputs ] bi ;
M: #return mark-live-values M: #return mark-live-values
look-at-inputs ; look-at-inputs ;

View File

@ -1,6 +1,5 @@
IN: compiler.tree.debugger.tests IN: compiler.tree.debugger.tests
USING: compiler.tree.debugger tools.test ; USING: compiler.tree.debugger tools.test ;
\ optimized-quot. must-infer \ optimized. must-infer
\ optimized-word. must-infer
\ optimizer-report. must-infer \ optimizer-report. must-infer

View File

@ -22,7 +22,7 @@ MACRO: match-choose ( alist -- )
MATCH-VARS: ?a ?b ?c ; MATCH-VARS: ?a ?b ?c ;
: pretty-shuffle ( effect -- word/f ) : pretty-shuffle ( effect -- word/f )
[ in>> ] [ out>> ] bi { [ in>> ] [ out>> ] bi 2array {
{ { { } { } } [ ] } { { { } { } } [ ] }
{ { { ?a } { ?a } } [ ] } { { { ?a } { ?a } } [ ] }
{ { { ?a ?b } { ?a ?b } } [ ] } { { { ?a ?b } { ?a ?b } } [ ] }

View File

@ -80,3 +80,13 @@ M: #call escape-analysis*
M: #return escape-analysis* M: #return escape-analysis*
in-d>> add-escaping-values ; in-d>> add-escaping-values ;
M: #alien-invoke escape-analysis*
[ in-d>> add-escaping-values ]
[ out-d>> unknown-allocation ]
bi ;
M: #alien-indirect escape-analysis*
[ in-d>> add-escaping-values ]
[ out-d>> unknown-allocation ]
bi ;

View File

@ -115,3 +115,9 @@ M: #call propagate-before
M: #call propagate-after M: #call propagate-after
dup word>> "input-classes" word-prop dup dup word>> "input-classes" word-prop dup
[ propagate-input-classes ] [ 2drop ] if ; [ propagate-input-classes ] [ 2drop ] if ;
M: #alien-invoke propagate-before
out-d>> [ object-info swap set-value-info ] each ;
M: #alien-indirect propagate-before
out-d>> [ object-info swap set-value-info ] each ;

View File

@ -143,6 +143,30 @@ TUPLE: #copy < #renaming in-d out-d ;
swap >>out-d swap >>out-d
swap >>in-d ; swap >>in-d ;
TUPLE: #alien-node < node params ;
: new-alien-node ( params class -- node )
new
over in-d>> >>in-d
over out-d>> >>out-d
swap >>params ; inline
TUPLE: #alien-invoke < #alien-node in-d out-d ;
: #alien-invoke ( params -- node )
\ #alien-invoke new-alien-node ;
TUPLE: #alien-indirect < #alien-node in-d out-d ;
: #alien-indirect ( params -- node )
\ #alien-indirect new-alien-node ;
TUPLE: #alien-callback < #alien-node ;
: #alien-callback ( params -- node )
\ #alien-callback new
swap >>params ;
: node, ( node -- ) stack-visitor get push ; : node, ( node -- ) stack-visitor get push ;
GENERIC: inputs/outputs ( #renaming -- inputs outputs ) GENERIC: inputs/outputs ( #renaming -- inputs outputs )
@ -177,3 +201,6 @@ M: vector #phi, #phi node, ;
M: vector #declare, #declare node, ; M: vector #declare, #declare node, ;
M: vector #recursive, #recursive node, ; M: vector #recursive, #recursive node, ;
M: vector #copy, #copy node, ; M: vector #copy, #copy node, ;
M: vector #alien-invoke, #alien-invoke node, ;
M: vector #alien-indirect, #alien-indirect node, ;
M: vector #alien-callback, #alien-callback node, ;

View File

@ -128,4 +128,8 @@ M: #return unbox-tuples* dup in-d>> assert-not-unboxed ;
M: #introduce unbox-tuples* dup value>> assert-not-unboxed ; M: #introduce unbox-tuples* dup value>> assert-not-unboxed ;
M: #alien-invoke unbox-tuples* dup in-d>> assert-not-unboxed ;
M: #alien-indirect unbox-tuples* dup in-d>> assert-not-unboxed ;
: unbox-tuples ( nodes -- nodes ) [ unbox-tuples* ] map-nodes ; : unbox-tuples ( nodes -- nodes ) [ unbox-tuples* ] map-nodes ;

View File

@ -0,0 +1,84 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: kernel sequences accessors combinators math namespaces
init sets words
alien alien.c-types
stack-checker.backend stack-checker.errors stack-checker.visitor ;
IN: stack-checker.alien
TUPLE: alien-node-params return parameters abi in-d out-d ;
TUPLE: alien-invoke-params < alien-node-params library function ;
TUPLE: alien-indirect-params < alien-node-params ;
TUPLE: alien-callback-params < alien-node-params quot xt ;
: pop-parameters ( -- seq )
pop-literal nip [ expand-constants ] map ;
: param-prep-quot ( node -- quot )
parameters>> [ c-type c-type-unboxer-quot ] map spread>quot ;
: alien-stack ( params extra -- )
over parameters>> length + consume-d >>in-d
dup return>> "void" = 0 1 ? produce-d >>out-d
drop ;
: return-prep-quot ( node -- quot )
return>> [ [ ] ] [ c-type c-type-boxer-quot ] if-void ;
: infer-alien-invoke ( -- )
alien-invoke-params new
! Compile-time parameters
pop-parameters >>parameters
pop-literal nip >>function
pop-literal nip >>library
pop-literal nip >>return
! Quotation which coerces parameters to required types
dup param-prep-quot recursive-state get infer-quot
! Set ABI
dup library>> library [ abi>> ] [ "cdecl" ] if* >>abi
! Magic #: consume exactly the number of inputs
dup 0 alien-stack
! Add node to IR
dup #alien-invoke,
! Quotation which coerces return value to required type
return-prep-quot recursive-state get infer-quot ;
: infer-alien-indirect ( -- )
alien-indirect-params new
! Compile-time parameters
pop-literal nip >>abi
pop-parameters >>parameters
pop-literal nip >>return
! Quotation which coerces parameters to required types
dup param-prep-quot [ dip ] curry recursive-state get infer-quot
! Magic #: consume the function pointer, too
dup 1 alien-stack
! Add node to IR
dup #alien-indirect,
! Quotation which coerces return value to required type
return-prep-quot recursive-state get infer-quot ;
! Callbacks are registered in a global hashtable. If you clear
! this hashtable, they will all be blown away by code GC, beware
SYMBOL: callbacks
[ H{ } clone callbacks set-global ] "alien.compiler" add-init-hook
: register-callback ( word -- ) callbacks get conjoin ;
: callback-bottom ( params -- )
xt>> [ [ register-callback ] [ word-xt drop <alien> ] bi ] curry
recursive-state get infer-quot ;
: infer-alien-callback ( -- )
alien-callback-params new
pop-literal nip >>quot
pop-literal nip >>abi
pop-parameters >>parameters
pop-literal nip >>return
gensym >>xt
dup callback-bottom
#alien-callback, ;

View File

@ -32,7 +32,7 @@ M: inline-recursive hashcode* id>> hashcode* ;
: <inline-recursive> ( word -- label ) : <inline-recursive> ( word -- label )
inline-recursive new inline-recursive new
gensym t "inlined-block" set-word-prop >>id gensym dup t "inlined-block" set-word-prop >>id
swap >>word ; swap >>word ;
: quotation-param? ( obj -- ? ) : quotation-param? ( obj -- ? )

View File

@ -10,10 +10,14 @@ sequences sequences.private slots.private strings
strings.private system threads.private classes.tuple strings.private system threads.private classes.tuple
classes.tuple.private vectors vectors.private words definitions classes.tuple.private vectors vectors.private words definitions
words.private assocs summary compiler.units system.private words.private assocs summary compiler.units system.private
combinators locals.backend stack-checker.state combinators locals.backend
stack-checker.backend stack-checker.branches stack-checker.state
stack-checker.errors stack-checker.transforms stack-checker.backend
stack-checker.visitor ; stack-checker.branches
stack-checker.errors
stack-checker.transforms
stack-checker.visitor
stack-checker.alien ;
IN: stack-checker.known-words IN: stack-checker.known-words
: infer-primitive ( word -- ) : infer-primitive ( word -- )
@ -153,13 +157,15 @@ M: object infer-call*
{ \ get-local [ infer-get-local ] } { \ get-local [ infer-get-local ] }
{ \ drop-locals [ infer-drop-locals ] } { \ drop-locals [ infer-drop-locals ] }
{ \ do-primitive [ \ do-primitive cannot-infer-effect ] } { \ do-primitive [ \ do-primitive cannot-infer-effect ] }
{ \ alien-invoke [ infer-alien-invoke ] }
{ \ alien-indirect [ infer-alien-indirect ] }
{ \ alien-callback [ infer-alien-callback ] }
} case ; } case ;
{ {
>r r> declare call curry compose >r r> declare call curry compose execute if dispatch
execute if dispatch <tuple-boa> <tuple-boa> (throw) load-locals get-local drop-locals
(throw) load-locals get-local drop-locals do-primitive alien-invoke alien-indirect alien-callback
do-primitive
} [ t +special+ set-word-prop ] each } [ t +special+ set-word-prop ] each
{ call execute dispatch load-locals get-local drop-locals } { call execute dispatch load-locals get-local drop-locals }

View File

@ -22,3 +22,6 @@ M: f #declare, drop ;
M: f #recursive, 2drop 2drop ; M: f #recursive, 2drop 2drop ;
M: f #copy, 2drop ; M: f #copy, 2drop ;
M: f #drop, drop ; M: f #drop, drop ;
M: f #alien-invoke, drop ;
M: f #alien-indirect, drop ;
M: f #alien-callback, drop ;

View File

@ -27,3 +27,6 @@ HOOK: #enter-recursive, stack-visitor ( label inputs outputs -- )
HOOK: #return-recursive, stack-visitor ( label inputs outputs -- ) HOOK: #return-recursive, stack-visitor ( label inputs outputs -- )
HOOK: #recursive, stack-visitor ( word label inputs visitor -- ) HOOK: #recursive, stack-visitor ( word label inputs visitor -- )
HOOK: #copy, stack-visitor ( inputs outputs -- ) HOOK: #copy, stack-visitor ( inputs outputs -- )
HOOK: #alien-invoke, stack-visitor ( params -- )
HOOK: #alien-indirect, stack-visitor ( params -- )
HOOK: #alien-callback, stack-visitor ( params -- )