factor/library/compiler/intrinsics.factor

284 lines
5.6 KiB
Factor
Raw Normal View History

2005-05-06 18:33:40 -04:00
! Copyright (C) 2005 Slava Pestov.
! See http://factor.sf.net/license.txt for BSD license.
2005-05-09 02:34:15 -04:00
IN: compiler-frontend
USING: assembler compiler-backend generic hashtables inference
kernel kernel-internals lists math math-internals namespaces
sequences words ;
2005-05-06 18:33:40 -04:00
: immediate? ( obj -- ? )
#! fixnums and f have a pointerless representation, and
#! are compiled immediately. Everything else can be moved
#! by GC, and is indexed through a table.
dup fixnum? swap f eq? or ;
#push [
1 %inc-d ,
[ node-param get ] bind dup immediate? [
%immediate-d ,
] [
0 swap %indirect , out-1
] ifte
] "linearizer" set-word-prop
\ drop [
drop
1 %dec-d ,
] "linearizer" set-word-prop
\ dup [
drop
in-1
1 %inc-d ,
out-1
] "linearizer" set-word-prop
\ swap [
drop
in-2
0 0 %replace-d ,
1 1 %replace-d ,
2005-05-06 18:33:40 -04:00
] "linearizer" set-word-prop
\ over [
drop
0 1 %peek-d ,
1 %inc-d ,
out-1
] "linearizer" set-word-prop
\ pick [
drop
0 2 %peek-d ,
1 %inc-d ,
out-1
] "linearizer" set-word-prop
\ >r [
drop
in-1
1 %inc-r ,
1 %dec-d ,
0 0 %replace-r ,
] "linearizer" set-word-prop
\ r> [
drop
0 0 %peek-r ,
1 %inc-d ,
1 %dec-r ,
out-1
] "linearizer" set-word-prop
2005-05-09 22:34:47 -04:00
: node-peek ( node -- obj ) node-consume-d swap hash peek ;
2005-05-06 18:33:40 -04:00
: peek-2 dup length 2 - swap nth ;
2005-05-09 22:34:47 -04:00
: node-peek-2 ( node -- obj ) node-consume-d swap hash peek-2 ;
: typed? ( value -- ? ) value-types length 1 = ;
2005-05-06 18:33:40 -04:00
: self ( word -- )
f swap dup "infer-effect" word-prop (consume/produce) ;
: intrinsic ( word -- )
dup [ literal, \ self , ] make-list "infer" set-word-prop ;
\ slot intrinsic
2005-05-06 18:33:40 -04:00
2005-05-09 22:34:47 -04:00
: slot@ ( node -- n )
2005-05-06 18:33:40 -04:00
#! Compute slot offset.
2005-05-09 22:34:47 -04:00
node-consume-d swap hash
2005-05-06 18:33:40 -04:00
dup peek literal-value cell *
swap peek-2 value-types car type-tag - ;
2005-05-09 22:34:47 -04:00
: typed-literal? ( node -- ? )
#! Output if the node's first input is well-typed, and the
#! second is a literal.
dup node-peek literal? swap node-peek-2 typed? and ;
2005-05-06 18:33:40 -04:00
\ slot [
2005-05-09 22:34:47 -04:00
dup typed-literal? [
2005-05-06 18:33:40 -04:00
1 %dec-d ,
in-1
0 swap slot@ %fast-slot ,
] [
drop
in-2
1 %dec-d ,
0 %untag ,
2005-05-06 18:33:40 -04:00
1 0 %slot ,
] ifte out-1
] "linearizer" set-word-prop
2005-05-13 00:09:49 -04:00
! \ set-slot intrinsic
!
! \ set-slot [
! dup typed-literal? [
! 1 %dec-d ,
! in-2
! 2 %dec-d ,
! slot@ >r 0 1 r> %fast-set-slot ,
! ] [
! drop
! in-3
! 3 %dec-d ,
! 1 %untag ,
! 0 1 2 %set-slot ,
! ] ifte
! ] "linearizer" set-word-prop
2005-05-06 18:33:40 -04:00
\ type intrinsic
\ type [
drop
in-1
0 %type ,
0 %tag-fixnum ,
out-1
] "linearizer" set-word-prop
\ arithmetic-type intrinsic
\ arithmetic-type [
drop
in-1
0 %arithmetic-type ,
0 %tag-fixnum ,
1 %inc-d ,
out-1
] "linearizer" set-word-prop
: binary-op-reg ( op out -- )
>r in-2
1 %dec-d ,
2005-05-08 20:30:38 -04:00
1 <vreg> 0 <vreg> rot execute ,
r> 0 %replace-d , ;
: binary-op ( node op out -- )
#! out is a vreg where the vop stores the result.
2005-05-09 22:34:47 -04:00
>r >r node-peek dup literal? [
1 %dec-d ,
in-1
2005-05-09 22:34:47 -04:00
literal-value 0 <vreg> r> execute ,
r> 0 %replace-d ,
] [
drop
r> r> binary-op-reg
] ifte ;
[
[[ fixnum+ %fixnum+ ]]
[[ fixnum- %fixnum- ]]
[[ fixnum-bitand %fixnum-bitand ]]
[[ fixnum-bitor %fixnum-bitor ]]
[[ fixnum-bitxor %fixnum-bitxor ]]
[[ fixnum<= %fixnum<= ]]
[[ fixnum< %fixnum< ]]
[[ fixnum>= %fixnum>= ]]
[[ fixnum> %fixnum> ]]
2005-05-09 02:34:15 -04:00
[[ eq? %eq? ]]
] [
uncons over intrinsic
[ literal, 0 , \ binary-op , ] make-list
"linearizer" set-word-prop
] each
\ fixnum* intrinsic
2005-05-09 23:25:46 -04:00
: slow-fixnum* \ %fixnum* 0 binary-op-reg ;
\ fixnum* [
2005-05-09 22:34:47 -04:00
! Turn multiplication by a power of two into a left shift.
node-peek dup literal? [
literal-value dup power-of-2? [
1 %dec-d ,
in-1
log2 0 <vreg> %fixnum<< ,
0 0 %replace-d ,
] [
2005-05-09 23:25:46 -04:00
drop slow-fixnum*
2005-05-09 22:34:47 -04:00
] ifte
] [
2005-05-09 23:25:46 -04:00
drop slow-fixnum*
2005-05-09 22:34:47 -04:00
] ifte
] "linearizer" set-word-prop
\ fixnum-mod intrinsic
\ fixnum-mod [
! This is not clever. Because of x86, %fixnum-mod is
! hard-coded to put its output in vreg 2, which happends to
! be EDX there.
drop \ %fixnum-mod 2 binary-op-reg
] "linearizer" set-word-prop
\ fixnum/i intrinsic
\ fixnum/i [
drop \ %fixnum/i 0 binary-op-reg
] "linearizer" set-word-prop
\ fixnum/mod intrinsic
\ fixnum/mod [
! See the remark on fixnum-mod for vreg usage
drop
in-2
0 <vreg> 1 <vreg> %fixnum/mod ,
2 0 %replace-d ,
0 1 %replace-d ,
] "linearizer" set-word-prop
\ fixnum-bitnot intrinsic
\ fixnum-bitnot [
drop
in-1
0 %fixnum-bitnot ,
out-1
] "linearizer" set-word-prop
2005-05-09 22:34:47 -04:00
: slow-shift ( -- ) \ fixnum-shift %call , ;
: negative-shift ( n -- )
1 %dec-d ,
in-1
dup cell -8 * <= [
drop 0 <vreg> 2 <vreg> %fixnum-sgn ,
2 0 %replace-d ,
] [
neg 0 <vreg> %fixnum>> ,
out-1
] ifte ;
: positive-shift ( n -- )
dup cell 8 * tag-bits - <= [
1 %dec-d ,
in-1
0 <vreg> %fixnum<< ,
out-1
] [
drop slow-shift
] ifte ;
: fast-shift ( n -- )
dup 0 = [
1 %dec-d ,
drop
] [
dup 0 < [
negative-shift
] [
positive-shift
] ifte
] ifte ;
\ fixnum-shift intrinsic
\ fixnum-shift [
node-peek dup literal? [
literal-value fast-shift
] [
drop slow-shift
] ifte
] "linearizer" set-word-prop