Merge branch 'master' into new_optimizer
commit
56d272df9e
|
@ -2,6 +2,12 @@ IN: alien.c-types.tests
|
|||
USING: alien alien.syntax alien.c-types kernel tools.test
|
||||
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* ;
|
||||
|
||||
[ 123 ] [ foo ] unit-test
|
||||
|
|
|
@ -4,7 +4,7 @@ USING: byte-arrays arrays assocs kernel kernel.private libc math
|
|||
namespaces parser sequences strings words assocs splitting
|
||||
math.parser cpu.architecture alien alien.accessors quotations
|
||||
layouts system compiler.units io.files io.encodings.binary
|
||||
accessors combinators effects ;
|
||||
accessors combinators effects continuations ;
|
||||
IN: alien.c-types
|
||||
|
||||
DEFER: <int>
|
||||
|
@ -239,15 +239,20 @@ M: long-long-type box-return ( type -- )
|
|||
} 2cleave ;
|
||||
|
||||
: expand-constants ( c-type -- c-type' )
|
||||
#! We use def>> call instead of execute to get around
|
||||
#! staging violations
|
||||
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 ;
|
||||
|
||||
: malloc-file-contents ( path -- alien len )
|
||||
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>
|
||||
[ alien-cell ] >>getter
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: accessors arrays assocs classes combinators
|
||||
cpu.architecture effects generic hashtables io kernel
|
||||
kernel.private layouts math namespaces prettyprint quotations
|
||||
sequences system threads words vectors sets dequeues cursors
|
||||
kernel.private layouts math math.parser namespaces prettyprint
|
||||
quotations sequences system threads words vectors sets dequeues
|
||||
cursors continuations.private summary alien alien.c-types
|
||||
alien.structs alien.strings alien.arrays libc compiler.errors
|
||||
stack-checker.inlining
|
||||
compiler.tree compiler.tree.builder compiler.tree.combinators
|
||||
compiler.tree.propagation.info compiler.generator.fixup
|
||||
|
@ -48,7 +50,7 @@ SYMBOL: current-label-start
|
|||
: save-machine-code ( literals relocation labels code -- )
|
||||
4array compiling-label get compiled get set-at ;
|
||||
|
||||
: with-generator ( node word label quot -- )
|
||||
: with-generator ( nodes word label quot -- )
|
||||
[
|
||||
>r begin-compiling r>
|
||||
{ } make fixup
|
||||
|
@ -267,3 +269,316 @@ M: #return-recursive generate-node
|
|||
end-basic-block
|
||||
label>> id>> compiling-loops get key?
|
||||
[ %return ] unless f ;
|
||||
|
||||
! #alien-invoke
|
||||
: large-struct? ( ctype -- ? )
|
||||
dup c-struct? [
|
||||
heap-size struct-small-enough? not
|
||||
] [ drop f ] if ;
|
||||
|
||||
: alien-parameters ( params -- seq )
|
||||
dup parameters>>
|
||||
swap return>> large-struct? [ "void*" prefix ] when ;
|
||||
|
||||
: alien-return ( params -- ctype )
|
||||
return>> dup large-struct? [ drop "void" ] when ;
|
||||
|
||||
: c-type-stack-align ( type -- align )
|
||||
dup c-type-stack-align? [ c-type-align ] [ drop cell ] if ;
|
||||
|
||||
: parameter-align ( n type -- n delta )
|
||||
over >r c-type-stack-align align dup r> - ;
|
||||
|
||||
: parameter-sizes ( types -- total offsets )
|
||||
#! Compute stack frame locations.
|
||||
[
|
||||
0 [
|
||||
[ parameter-align drop dup , ] keep stack-size +
|
||||
] reduce cell align
|
||||
] { } make ;
|
||||
|
||||
: return-size ( ctype -- n )
|
||||
#! Amount of space we reserve for a return value.
|
||||
dup large-struct? [ heap-size ] [ drop 0 ] if ;
|
||||
|
||||
: alien-stack-frame ( params -- n )
|
||||
alien-parameters parameter-sizes drop ;
|
||||
|
||||
: alien-invoke-frame ( params -- n )
|
||||
#! One cell is temporary storage, temp@
|
||||
dup return>> return-size
|
||||
swap alien-stack-frame +
|
||||
cell + ;
|
||||
|
||||
: set-stack-frame ( n -- )
|
||||
dup [ frame-required ] when* \ stack-frame set ;
|
||||
|
||||
: with-stack-frame ( n quot -- )
|
||||
swap set-stack-frame
|
||||
call
|
||||
f set-stack-frame ; inline
|
||||
|
||||
GENERIC: reg-size ( register-class -- n )
|
||||
|
||||
M: int-regs reg-size drop cell ;
|
||||
|
||||
M: single-float-regs reg-size drop 4 ;
|
||||
|
||||
M: double-float-regs reg-size drop 8 ;
|
||||
|
||||
GENERIC: reg-class-variable ( register-class -- symbol )
|
||||
|
||||
M: reg-class reg-class-variable ;
|
||||
|
||||
M: float-regs reg-class-variable drop float-regs ;
|
||||
|
||||
GENERIC: inc-reg-class ( register-class -- )
|
||||
|
||||
M: reg-class inc-reg-class
|
||||
dup reg-class-variable inc
|
||||
fp-shadows-int? [ reg-size stack-params +@ ] [ drop ] if ;
|
||||
|
||||
M: float-regs inc-reg-class
|
||||
dup call-next-method
|
||||
fp-shadows-int? [ reg-size cell /i int-regs +@ ] [ drop ] if ;
|
||||
|
||||
: reg-class-full? ( class -- ? )
|
||||
[ reg-class-variable get ] [ param-regs length ] bi >= ;
|
||||
|
||||
: spill-param ( reg-class -- n reg-class )
|
||||
stack-params get
|
||||
>r reg-size stack-params +@ r>
|
||||
stack-params ;
|
||||
|
||||
: fastcall-param ( reg-class -- n reg-class )
|
||||
[ reg-class-variable get ] [ inc-reg-class ] [ ] tri ;
|
||||
|
||||
: alloc-parameter ( parameter -- reg reg-class )
|
||||
c-type-reg-class dup reg-class-full?
|
||||
[ spill-param ] [ fastcall-param ] if
|
||||
[ param-reg ] keep ;
|
||||
|
||||
: (flatten-int-type) ( size -- )
|
||||
cell /i "void*" c-type <repetition> % ;
|
||||
|
||||
GENERIC: flatten-value-type ( type -- )
|
||||
|
||||
M: object flatten-value-type , ;
|
||||
|
||||
M: struct-type flatten-value-type ( type -- )
|
||||
stack-size cell align (flatten-int-type) ;
|
||||
|
||||
M: long-long-type flatten-value-type ( type -- )
|
||||
stack-size cell align (flatten-int-type) ;
|
||||
|
||||
: flatten-value-types ( params -- params )
|
||||
#! Convert value type structs to consecutive void*s.
|
||||
[
|
||||
0 [
|
||||
c-type
|
||||
[ parameter-align (flatten-int-type) ] keep
|
||||
[ stack-size cell align + ] keep
|
||||
flatten-value-type
|
||||
] reduce drop
|
||||
] { } make ;
|
||||
|
||||
: each-parameter ( parameters quot -- )
|
||||
>r [ parameter-sizes nip ] keep r> 2each ; inline
|
||||
|
||||
: reverse-each-parameter ( parameters quot -- )
|
||||
>r [ parameter-sizes nip ] keep r> 2reverse-each ; inline
|
||||
|
||||
: reset-freg-counts ( -- )
|
||||
{ int-regs float-regs stack-params } [ 0 swap set ] each ;
|
||||
|
||||
: with-param-regs ( quot -- )
|
||||
#! In quot you can call alloc-parameter
|
||||
[ reset-freg-counts call ] with-scope ; inline
|
||||
|
||||
: move-parameters ( node word -- )
|
||||
#! Moves values from C stack to registers (if word is
|
||||
#! %load-param-reg) and registers to C stack (if word is
|
||||
#! %save-param-reg).
|
||||
>r
|
||||
alien-parameters
|
||||
flatten-value-types
|
||||
r> [ >r alloc-parameter r> execute ] curry each-parameter ;
|
||||
inline
|
||||
|
||||
: unbox-parameters ( offset node -- )
|
||||
parameters>> [
|
||||
%prepare-unbox >r over + r> unbox-parameter
|
||||
] reverse-each-parameter drop ;
|
||||
|
||||
: prepare-box-struct ( node -- offset )
|
||||
#! Return offset on C stack where to store unboxed
|
||||
#! parameters. If the C function is returning a structure,
|
||||
#! the first parameter is an implicit target area pointer,
|
||||
#! so we need to use a different offset.
|
||||
return>> dup large-struct?
|
||||
[ heap-size %prepare-box-struct cell ] [ drop 0 ] if ;
|
||||
|
||||
: objects>registers ( params -- )
|
||||
#! Generate code for unboxing a list of C types, then
|
||||
#! generate code for moving these parameters to register on
|
||||
#! architectures where parameters are passed in registers.
|
||||
[
|
||||
[ prepare-box-struct ] keep
|
||||
[ unbox-parameters ] keep
|
||||
\ %load-param-reg move-parameters
|
||||
] with-param-regs ;
|
||||
|
||||
: box-return* ( node -- )
|
||||
return>> [ ] [ box-return ] if-void ;
|
||||
|
||||
TUPLE: no-such-library name ;
|
||||
|
||||
M: no-such-library summary
|
||||
drop "Library not found" ;
|
||||
|
||||
M: no-such-library compiler-error-type
|
||||
drop +linkage+ ;
|
||||
|
||||
: no-such-library ( name -- )
|
||||
\ no-such-library boa
|
||||
compiling-word get compiler-error ;
|
||||
|
||||
TUPLE: no-such-symbol name ;
|
||||
|
||||
M: no-such-symbol summary
|
||||
drop "Symbol not found" ;
|
||||
|
||||
M: no-such-symbol compiler-error-type
|
||||
drop +linkage+ ;
|
||||
|
||||
: no-such-symbol ( name -- )
|
||||
\ no-such-symbol boa
|
||||
compiling-word get compiler-error ;
|
||||
|
||||
: check-dlsym ( symbols dll -- )
|
||||
dup dll-valid? [
|
||||
dupd [ dlsym ] curry contains?
|
||||
[ drop ] [ no-such-symbol ] if
|
||||
] [
|
||||
dll-path no-such-library drop
|
||||
] if ;
|
||||
|
||||
: stdcall-mangle ( symbol node -- symbol )
|
||||
"@"
|
||||
swap parameters>> parameter-sizes drop
|
||||
number>string 3append ;
|
||||
|
||||
: alien-invoke-dlsym ( params -- symbols dll )
|
||||
dup function>> dup pick stdcall-mangle 2array
|
||||
swap library>> library dup [ dll>> ] when
|
||||
2dup check-dlsym ;
|
||||
|
||||
M: #alien-invoke generate-node
|
||||
params>>
|
||||
dup alien-invoke-frame [
|
||||
end-basic-block
|
||||
%prepare-alien-invoke
|
||||
dup objects>registers
|
||||
%prepare-var-args
|
||||
dup alien-invoke-dlsym %alien-invoke
|
||||
dup %cleanup
|
||||
box-return*
|
||||
iterate-next
|
||||
] with-stack-frame ;
|
||||
|
||||
! #alien-indirect
|
||||
M: #alien-indirect generate-node
|
||||
params>>
|
||||
dup alien-invoke-frame [
|
||||
! Flush registers
|
||||
end-basic-block
|
||||
! Save registers for GC
|
||||
%prepare-alien-invoke
|
||||
! Save alien at top of stack to temporary storage
|
||||
%prepare-alien-indirect
|
||||
dup objects>registers
|
||||
%prepare-var-args
|
||||
! Call alien in temporary storage
|
||||
%alien-indirect
|
||||
dup %cleanup
|
||||
box-return*
|
||||
iterate-next
|
||||
] with-stack-frame ;
|
||||
|
||||
! #alien-callback
|
||||
: box-parameters ( params -- )
|
||||
alien-parameters [ box-parameter ] each-parameter ;
|
||||
|
||||
: registers>objects ( node -- )
|
||||
[
|
||||
dup \ %save-param-reg move-parameters
|
||||
"nest_stacks" f %alien-invoke
|
||||
box-parameters
|
||||
] with-param-regs ;
|
||||
|
||||
TUPLE: callback-context ;
|
||||
|
||||
: current-callback 2 getenv ;
|
||||
|
||||
: wait-to-return ( token -- )
|
||||
dup current-callback eq? [
|
||||
drop
|
||||
] [
|
||||
yield wait-to-return
|
||||
] if ;
|
||||
|
||||
: do-callback ( quot token -- )
|
||||
init-catchstack
|
||||
dup 2 setenv
|
||||
slip
|
||||
wait-to-return ; inline
|
||||
|
||||
: callback-return-quot ( ctype -- quot )
|
||||
return>> {
|
||||
{ [ dup "void" = ] [ drop [ ] ] }
|
||||
{ [ dup large-struct? ] [ heap-size [ memcpy ] curry ] }
|
||||
[ c-type c-type-unboxer-quot ]
|
||||
} cond ;
|
||||
|
||||
: callback-prep-quot ( params -- quot )
|
||||
parameters>> [ c-type c-type-boxer-quot ] map spread>quot ;
|
||||
|
||||
: wrap-callback-quot ( params -- quot )
|
||||
[
|
||||
[ callback-prep-quot ]
|
||||
[ quot>> ]
|
||||
[ callback-return-quot ] tri 3append ,
|
||||
[ callback-context new do-callback ] %
|
||||
] [ ] make ;
|
||||
|
||||
: %unnest-stacks ( -- ) "unnest_stacks" f %alien-invoke ;
|
||||
|
||||
: callback-unwind ( params -- n )
|
||||
{
|
||||
{ [ dup abi>> "stdcall" = ] [ alien-stack-frame ] }
|
||||
{ [ dup return>> large-struct? ] [ drop 4 ] }
|
||||
[ drop 0 ]
|
||||
} cond ;
|
||||
|
||||
: %callback-return ( params -- )
|
||||
#! All the extra book-keeping for %unwind is only for x86.
|
||||
#! On other platforms its an alias for %return.
|
||||
dup alien-return
|
||||
[ %unnest-stacks ] [ %callback-value ] if-void
|
||||
callback-unwind %unwind ;
|
||||
|
||||
: generate-callback ( params -- )
|
||||
dup xt>> dup [
|
||||
init-templates
|
||||
%prologue-later
|
||||
dup alien-stack-frame [
|
||||
[ registers>objects ]
|
||||
[ wrap-callback-quot %alien-callback ]
|
||||
[ %callback-return ]
|
||||
tri
|
||||
] with-stack-frame
|
||||
] with-generator ;
|
||||
|
||||
M: #alien-callback generate-node
|
||||
end-basic-block
|
||||
params>> generate-callback iterate-next ;
|
||||
|
|
|
@ -35,6 +35,12 @@ M: #phi backward
|
|||
[ [ out-r>> ] [ phi-in-r>> ] bi look-at-corresponding ]
|
||||
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 ;
|
||||
|
||||
: backward-dfa ( node quot -- assoc ) [ backward ] dfa ; inline
|
||||
|
|
|
@ -23,6 +23,12 @@ M: #call mark-live-values
|
|||
dup word>> "flushable" word-prop
|
||||
[ 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
|
||||
look-at-inputs ;
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
IN: compiler.tree.debugger.tests
|
||||
USING: compiler.tree.debugger tools.test ;
|
||||
|
||||
\ optimized-quot. must-infer
|
||||
\ optimized-word. must-infer
|
||||
\ optimized. must-infer
|
||||
\ optimizer-report. must-infer
|
||||
|
|
|
@ -22,7 +22,7 @@ MACRO: match-choose ( alist -- )
|
|||
MATCH-VARS: ?a ?b ?c ;
|
||||
|
||||
: pretty-shuffle ( effect -- word/f )
|
||||
[ in>> ] [ out>> ] bi {
|
||||
[ in>> ] [ out>> ] bi 2array {
|
||||
{ { { } { } } [ ] }
|
||||
{ { { ?a } { ?a } } [ ] }
|
||||
{ { { ?a ?b } { ?a ?b } } [ ] }
|
||||
|
|
|
@ -80,3 +80,13 @@ M: #call escape-analysis*
|
|||
|
||||
M: #return escape-analysis*
|
||||
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 ;
|
||||
|
|
|
@ -115,3 +115,9 @@ M: #call propagate-before
|
|||
M: #call propagate-after
|
||||
dup word>> "input-classes" word-prop dup
|
||||
[ 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 ;
|
||||
|
|
|
@ -143,6 +143,30 @@ TUPLE: #copy < #renaming in-d out-d ;
|
|||
swap >>out-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 ;
|
||||
|
||||
GENERIC: inputs/outputs ( #renaming -- inputs outputs )
|
||||
|
@ -177,3 +201,6 @@ M: vector #phi, #phi node, ;
|
|||
M: vector #declare, #declare node, ;
|
||||
M: vector #recursive, #recursive 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, ;
|
||||
|
|
|
@ -128,4 +128,8 @@ M: #return unbox-tuples* dup in-d>> 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 ;
|
||||
|
|
|
@ -32,7 +32,7 @@ M: inline-recursive hashcode* id>> hashcode* ;
|
|||
|
||||
: <inline-recursive> ( word -- label )
|
||||
inline-recursive new
|
||||
gensym t "inlined-block" set-word-prop >>id
|
||||
gensym dup t "inlined-block" set-word-prop >>id
|
||||
swap >>word ;
|
||||
|
||||
: quotation-param? ( obj -- ? )
|
||||
|
|
|
@ -10,10 +10,14 @@ sequences sequences.private slots.private strings
|
|||
strings.private system threads.private classes.tuple
|
||||
classes.tuple.private vectors vectors.private words definitions
|
||||
words.private assocs summary compiler.units system.private
|
||||
combinators locals.backend stack-checker.state
|
||||
stack-checker.backend stack-checker.branches
|
||||
stack-checker.errors stack-checker.transforms
|
||||
stack-checker.visitor ;
|
||||
combinators locals.backend
|
||||
stack-checker.state
|
||||
stack-checker.backend
|
||||
stack-checker.branches
|
||||
stack-checker.errors
|
||||
stack-checker.transforms
|
||||
stack-checker.visitor
|
||||
stack-checker.alien ;
|
||||
IN: stack-checker.known-words
|
||||
|
||||
: infer-primitive ( word -- )
|
||||
|
@ -153,13 +157,15 @@ M: object infer-call*
|
|||
{ \ get-local [ infer-get-local ] }
|
||||
{ \ drop-locals [ infer-drop-locals ] }
|
||||
{ \ do-primitive [ \ do-primitive cannot-infer-effect ] }
|
||||
{ \ alien-invoke [ infer-alien-invoke ] }
|
||||
{ \ alien-indirect [ infer-alien-indirect ] }
|
||||
{ \ alien-callback [ infer-alien-callback ] }
|
||||
} case ;
|
||||
|
||||
{
|
||||
>r r> declare call curry compose
|
||||
execute if dispatch <tuple-boa>
|
||||
(throw) load-locals get-local drop-locals
|
||||
do-primitive
|
||||
>r r> declare call curry compose execute if dispatch
|
||||
<tuple-boa> (throw) load-locals get-local drop-locals
|
||||
do-primitive alien-invoke alien-indirect alien-callback
|
||||
} [ t +special+ set-word-prop ] each
|
||||
|
||||
{ call execute dispatch load-locals get-local drop-locals }
|
||||
|
@ -173,10 +179,10 @@ SYMBOL: +primitive+
|
|||
{ [ dup +shuffle+ word-prop ] [ infer-shuffle-word ] }
|
||||
{ [ dup +special+ word-prop ] [ infer-special ] }
|
||||
{ [ dup +primitive+ word-prop ] [ infer-primitive ] }
|
||||
{ [ dup +cannot-infer+ word-prop ] [ cannot-infer-effect ] }
|
||||
{ [ dup +transform-quot+ word-prop ] [ apply-transform ] }
|
||||
{ [ dup +inferred-effect+ word-prop ] [ cached-infer ] }
|
||||
{ [ dup "macro" word-prop ] [ apply-macro ] }
|
||||
{ [ dup +cannot-infer+ word-prop ] [ cannot-infer-effect ] }
|
||||
{ [ dup +inferred-effect+ word-prop ] [ cached-infer ] }
|
||||
{ [ dup recursive-label ] [ call-recursive-word ] }
|
||||
[ dup infer-word apply-word/effect ]
|
||||
} cond ;
|
||||
|
|
|
@ -23,10 +23,11 @@ SYMBOL: +transform-n+
|
|||
inline
|
||||
|
||||
: (apply-transform) ( word quot n -- )
|
||||
consume-d dup [ known literal? ] all? [
|
||||
dup ensure-d [ known literal? ] all? [
|
||||
dup empty? [
|
||||
drop recursive-state get 1array
|
||||
] [
|
||||
consume-d
|
||||
[ #drop, ]
|
||||
[ [ literal value>> ] map ]
|
||||
[ first literal recursion>> ] tri prefix
|
||||
|
@ -123,7 +124,6 @@ SYMBOL: +transform-n+
|
|||
|
||||
: bit-member-quot ( seq -- newquot )
|
||||
[
|
||||
[ drop ] % ! drop the sequence itself; we don't use it at run time
|
||||
bit-member-seq ,
|
||||
[
|
||||
{
|
||||
|
@ -140,7 +140,7 @@ SYMBOL: +transform-n+
|
|||
bit-member-quot
|
||||
] [
|
||||
[ literalize [ t ] ] { } map>assoc
|
||||
[ drop f ] suffix [ nip case ] curry
|
||||
[ drop f ] suffix [ case ] curry
|
||||
] if ;
|
||||
|
||||
\ member? [
|
||||
|
|
|
@ -22,3 +22,6 @@ M: f #declare, drop ;
|
|||
M: f #recursive, 2drop 2drop ;
|
||||
M: f #copy, 2drop ;
|
||||
M: f #drop, drop ;
|
||||
M: f #alien-invoke, drop ;
|
||||
M: f #alien-indirect, drop ;
|
||||
M: f #alien-callback, drop ;
|
||||
|
|
|
@ -27,3 +27,6 @@ HOOK: #enter-recursive, stack-visitor ( label inputs outputs -- )
|
|||
HOOK: #return-recursive, stack-visitor ( label inputs outputs -- )
|
||||
HOOK: #recursive, stack-visitor ( word label inputs visitor -- )
|
||||
HOOK: #copy, stack-visitor ( inputs outputs -- )
|
||||
HOOK: #alien-invoke, stack-visitor ( params -- )
|
||||
HOOK: #alien-indirect, stack-visitor ( params -- )
|
||||
HOOK: #alien-callback, stack-visitor ( params -- )
|
||||
|
|
|
@ -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, ;
|
Loading…
Reference in New Issue