From ac34c06c0cfe982c022f7f93d9a932163d160d8b Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 17 May 2005 20:13:08 +0000 Subject: [PATCH] new dataflow IR --- TODO.FACTOR.txt | 3 +- library/alien/compiler.factor | 100 +++---- library/combinators.factor | 3 + library/compiler/intrinsics.factor | 91 ++---- library/compiler/linearizer.factor | 95 +++--- library/compiler/optimizer.factor | 408 +++++++++++++------------- library/inference/branches.factor | 35 ++- library/inference/dataflow.factor | 174 ++++++----- library/inference/inference.factor | 21 +- library/inference/partial-eval.factor | 4 +- library/inference/stack.factor | 21 +- library/inference/words.factor | 76 ++--- library/test/tuple.factor | 2 + 13 files changed, 478 insertions(+), 555 deletions(-) diff --git a/TODO.FACTOR.txt b/TODO.FACTOR.txt index f404851bd1..e3aed42f91 100644 --- a/TODO.FACTOR.txt +++ b/TODO.FACTOR.txt @@ -6,8 +6,9 @@ http://www.caddr.com/macho/archives/sbcl-devel/2005-3/4764.html http://clozure.com/cgi-bin/viewcvs.cgi/ccl/lisp-kernel/lisp-exceptions.c?rev=1.9&content-type=text/vnd.viewcvs-markup +- single-stepper and variable access: wrong namespace? +- [ over ] generics no-method - investigate if COPYING_GEN needs a fix -- alien-global type wrong - simplifier: - dead loads not optimized out - kill tag-fixnum/untag-fixnum diff --git a/library/alien/compiler.factor b/library/alien/compiler.factor index 8e58366f21..467bcf51ed 100644 --- a/library/alien/compiler.factor +++ b/library/alien/compiler.factor @@ -1,9 +1,9 @@ ! Copyright (C) 2004, 2005 Slava Pestov. ! See http://factor.sf.net/license.txt for BSD license. IN: alien -USING: assembler compiler compiler-backend errors generic -inference kernel lists math namespaces sequences stdio strings -unparser words ; +USING: assembler compiler compiler-frontend compiler-backend +errors generic inference kernel lists math namespaces sequences +stdio strings unparser words ; ! ! ! WARNING ! ! ! ! Reloading this file into a running Factor instance on Win32 @@ -42,48 +42,42 @@ M: alien-error error. ( error -- ) " symbol." % ] make-string print ; -: alien-invoke ( ... returns library function parameters -- ... ) +: alien-invoke ( ... return library function parameters -- ... ) #! Call a C library function. - #! 'returns' is a type spec, and 'parameters' is a list of + #! 'return' is a type spec, and 'parameters' is a list of #! type specs. 'library' is an entry in the "libraries" #! namespace. drop throw ; -! These are set in the alien-invoke dataflow IR node. -SYMBOL: alien-returns -SYMBOL: alien-parameters +TUPLE: alien-node return parameters ; +C: alien-node make-node ; -: set-alien-returns ( returns node -- ) - [ dup alien-returns set ] bind - "void" = [ - [ object ] produce-d 1 0 node-outputs - ] unless ; +: set-alien-return ( return node -- ) + 2dup set-alien-node-return + swap "void" = [ + drop + ] [ + [ object ] produce-d 1 0 rot node-outputs + ] ifte ; : set-alien-parameters ( parameters node -- ) - [ dup alien-parameters set ] bind - [ drop object ] map dup dup ensure-d - length 0 node-inputs consume-d ; + 2dup set-alien-node-parameters + >r [ drop object ] map dup dup ensure-d + length 0 r> node-inputs consume-d ; : ensure-dlsym ( symbol library -- ) load-library dlsym drop ; -: alien-invoke-node ( returns params function library -- ) +: alien-node ( return params function library -- ) #! We should fail if the library does not exist, so that #! compilation does not keep trying to compile FFI words #! over and over again if the library is not loaded. 2dup ensure-dlsym - cons \ alien-invoke dataflow, + cons param-node [ set-alien-parameters ] keep - set-alien-returns ; + [ set-alien-return ] keep + node, ; -: infer-alien-invoke ( -- ) - \ alien-invoke "infer-effect" word-prop car ensure-d - pop-literal nip - pop-literal nip >r - pop-literal nip - pop-literal nip -rot - r> swap alien-invoke-node ; - -: parameters [ alien-parameters get reverse ] bind ; +: parameters alien-node-parameters reverse ; : stack-space ( parameters -- n ) 0 swap [ c-size cell align + ] each ; @@ -101,57 +95,35 @@ SYMBOL: alien-parameters parameters dup stack-space dup %parameters , >r - dup dup length swap [ >r 1 - dup r> unbox-parameter ] each drop + dup dup length swap [ + >r 1 - dup r> unbox-parameter + ] each drop length [ %parameter ] project % r> ; -: linearize-returns ( returns -- ) - [ alien-returns get ] bind dup "void" = [ +: linearize-return ( return -- ) + alien-node-return dup "void" = [ drop ] [ c-type [ "boxer" get "box-op" get ] bind execute , ] ifte ; -: linearize-alien-invoke ( node -- ) +M: alien-node linearize-node* ( node -- ) dup linearize-parameters >r - dup [ node-param get ] bind %alien-invoke , - dup [ node-param get cdr library-abi "stdcall" = ] bind + dup node-param %alien-invoke , + dup node-param cdr library-abi "stdcall" = r> swap [ drop ] [ %cleanup , ] ifte - linearize-returns ; + linearize-return ; -\ alien-invoke [ linearize-alien-invoke ] "linearizer" set-word-prop - -\ alien-invoke [ [ string string string general-list ] [ ] ] +\ alien-invoke [ [ string object string general-list ] [ ] ] "infer-effect" set-word-prop -\ alien-invoke [ infer-alien-invoke ] "infer" set-word-prop - -: alien-global ( type library name -- value ) - #! Fetch the value of C global variable. - #! 'type' is a type spec. 'library' is an entry in the - #! "libraries" namespace. - throw ; - -: alien-global-node ( type name library -- ) - 2dup ensure-dlsym - cons \ alien-global dataflow, - set-alien-returns ; - -: infer-alien-global ( -- ) - \ alien-global "infer-effect" word-prop car ensure-d +\ alien-invoke [ pop-literal nip + pop-literal nip >r pop-literal nip pop-literal nip -rot - alien-global-node ; - -: linearize-alien-global ( node -- ) - dup [ node-param get ] bind %alien-global , - linearize-returns ; - -\ alien-global [ linearize-alien-global ] "linearizer" set-word-prop - -\ alien-global [ [ string string string ] [ object ] ] "infer-effect" set-word-prop - -\ alien-global [ infer-alien-global ] "infer" set-word-prop + r> swap alien-node +] "infer" set-word-prop global [ "libraries" get [ "libraries" set ] unless diff --git a/library/combinators.factor b/library/combinators.factor index afd71e8a71..a030dee844 100644 --- a/library/combinators.factor +++ b/library/combinators.factor @@ -5,6 +5,9 @@ IN: kernel : slip ( quot x -- x | quot: -- ) >r call r> ; inline +: 2slip ( quot x y -- x y | quot: -- ) + >r >r call r> r> ; inline + : keep ( x quot -- x | quot: x -- ) over >r call r> ; inline diff --git a/library/compiler/intrinsics.factor b/library/compiler/intrinsics.factor index b93d5aabd7..a6083273bc 100644 --- a/library/compiler/intrinsics.factor +++ b/library/compiler/intrinsics.factor @@ -5,55 +5,33 @@ USING: assembler compiler-backend generic hashtables inference kernel kernel-internals lists math math-internals namespaces sequences words ; -: 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 ( obj -- ) - 0 swap literal-value dup - immediate? [ %immediate ] [ %indirect ] ifte , ; - -#push [ - [ node-produce-d get ] bind - dup length dup %inc-d , - 1 - swap [ - push-1 0 over %replace-d , - ] each drop -] "linearizer" set-word-prop - -#drop [ - [ node-consume-d get length ] bind %dec-d , -] "linearizer" set-word-prop - \ dup [ drop in-1 1 %inc-d , out-1 -] "linearizer" set-word-prop +] "intrinsic" set-word-prop \ swap [ drop in-2 0 0 %replace-d , 1 1 %replace-d , -] "linearizer" set-word-prop +] "intrinsic" set-word-prop \ over [ drop 0 1 %peek-d , 1 %inc-d , out-1 -] "linearizer" set-word-prop +] "intrinsic" set-word-prop \ pick [ drop 0 2 %peek-d , 1 %inc-d , out-1 -] "linearizer" set-word-prop +] "intrinsic" set-word-prop \ >r [ drop @@ -61,7 +39,7 @@ sequences words ; 1 %inc-r , 1 %dec-d , 0 0 %replace-r , -] "linearizer" set-word-prop +] "intrinsic" set-word-prop \ r> [ drop @@ -69,20 +47,18 @@ sequences words ; 1 %inc-d , 1 %dec-r , out-1 -] "linearizer" set-word-prop +] "intrinsic" set-word-prop -: node-peek ( node -- obj ) node-consume-d swap hash peek ; +: node-peek ( node -- obj ) node-in-d peek ; : peek-2 dup length 2 - swap nth ; -: node-peek-2 ( node -- obj ) node-consume-d swap hash peek-2 ; +: node-peek-2 ( node -- obj ) node-in-d peek-2 ; : typed? ( value -- ? ) value-types length 1 = ; -\ slot t "intrinsic" set-word-prop - : slot@ ( node -- n ) #! Compute slot offset. - node-consume-d swap hash + node-in-d dup peek literal-value cell * swap peek-2 value-types car type-tag - ; @@ -103,9 +79,7 @@ sequences words ; 0 %untag , 1 0 %slot , ] ifte out-1 -] "linearizer" set-word-prop - -\ set-slot t "intrinsic" set-word-prop +] "intrinsic" set-word-prop \ set-slot [ dup typed-literal? [ @@ -120,9 +94,7 @@ sequences words ; 1 %untag , 0 1 2 %set-slot , ] ifte -] "linearizer" set-word-prop - -\ type t "intrinsic" set-word-prop +] "intrinsic" set-word-prop \ type [ drop @@ -130,9 +102,7 @@ sequences words ; 0 %type , 0 %tag-fixnum , out-1 -] "linearizer" set-word-prop - -\ arithmetic-type t "intrinsic" set-word-prop +] "intrinsic" set-word-prop \ arithmetic-type [ drop @@ -141,25 +111,21 @@ sequences words ; 0 %tag-fixnum , 1 %inc-d , out-1 -] "linearizer" set-word-prop - -\ getenv t "intrinsic" set-word-prop +] "intrinsic" set-word-prop \ getenv [ 1 %dec-d , node-peek literal-value 0 swap %getenv , 1 %inc-d , out-1 -] "linearizer" set-word-prop - -\ setenv t "intrinsic" set-word-prop +] "intrinsic" set-word-prop \ setenv [ 1 %dec-d , in-1 node-peek literal-value 0 swap %setenv , 1 %dec-d , -] "linearizer" set-word-prop +] "intrinsic" set-word-prop : binary-op-reg ( op out -- ) >r in-2 @@ -194,13 +160,10 @@ sequences words ; [[ fixnum> %fixnum> ]] [[ eq? %eq? ]] ] [ - uncons over t "intrinsic" set-word-prop - [ literal, 0 , \ binary-op , ] make-list - "linearizer" set-word-prop + uncons [ literal, 0 , \ binary-op , ] make-list + "intrinsic" set-word-prop ] each -\ fixnum* t "intrinsic" set-word-prop - : slow-fixnum* \ %fixnum* 0 binary-op-reg ; \ fixnum* [ @@ -217,24 +180,20 @@ sequences words ; ] [ drop slow-fixnum* ] ifte -] "linearizer" set-word-prop - -\ fixnum-mod t "intrinsic" set-word-prop +] "intrinsic" set-word-prop \ 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 +] "intrinsic" set-word-prop \ fixnum/i t "intrinsic" set-word-prop \ fixnum/i [ drop \ %fixnum/i 0 binary-op-reg -] "linearizer" set-word-prop - -\ fixnum/mod t "intrinsic" set-word-prop +] "intrinsic" set-word-prop \ fixnum/mod [ ! See the remark on fixnum-mod for vreg usage @@ -243,16 +202,14 @@ sequences words ; 0 1 %fixnum/mod , 2 0 %replace-d , 0 1 %replace-d , -] "linearizer" set-word-prop - -\ fixnum-bitnot t "intrinsic" set-word-prop +] "intrinsic" set-word-prop \ fixnum-bitnot [ drop in-1 0 %fixnum-bitnot , out-1 -] "linearizer" set-word-prop +] "intrinsic" set-word-prop : slow-shift ( -- ) \ fixnum-shift %call , ; @@ -289,12 +246,10 @@ sequences words ; ] ifte ] ifte ; -\ fixnum-shift t "intrinsic" set-word-prop - \ fixnum-shift [ node-peek dup literal? [ literal-value fast-shift ] [ drop slow-shift ] ifte -] "linearizer" set-word-prop +] "intrinsic" set-word-prop diff --git a/library/compiler/linearizer.factor b/library/compiler/linearizer.factor index 97853d2fa9..a4e1d9aaee 100644 --- a/library/compiler/linearizer.factor +++ b/library/compiler/linearizer.factor @@ -4,66 +4,69 @@ IN: compiler-frontend USING: compiler-backend inference kernel kernel-internals lists math namespaces words strings errors prettyprint sequences ; -: >linear ( node -- ) - #! Dataflow OPs have a linearizer word property. This - #! quotation is executed to convert the node into linear - #! form. - "linearizer" [ "No linearizer" throw ] apply-dataflow ; +GENERIC: linearize-node* ( node -- ) +M: f linearize-node* ( f -- ) drop ; -: (linearize) ( dataflow -- ) - [ >linear ] each ; +: linearize-node ( node -- ) + [ + dup linearize-node* node-successor linearize-node + ] when* ; : linearize ( dataflow -- linear ) #! Transform dataflow IR into linear IR. This strips out - #! stack flow information, flattens conditionals into - #! jumps and labels, and turns dataflow IR nodes into - #! lists where the first element is an operation, and the - #! rest is arguments. - [ %prologue , (linearize) ] make-list ; + #! stack flow information, and flattens conditionals into + #! jumps and labels. + [ %prologue , linearize-node ] make-list ; -: linearize-label ( node -- ) - #! Labels are tricky, because they might contain non-tail - #! calls. So we push the address of the location right after - #! the #label , then linearize the #label , then add a #return - #! node to the linear IR. The simplifier will take care of - #! this in the common case where the labelled block does - #! not contain non-tail recursive calls to itself. +M: #label linearize-node* ( node -- )