From 17d6efb543cb064a971bf8b7b7209d9f75df2abb Mon Sep 17 00:00:00 2001 From: slava Date: Fri, 28 Apr 2006 22:38:48 +0000 Subject: [PATCH] Removing linear IR --- TODO.FACTOR.txt | 2 - library/alien/alien-callback.factor | 25 +- library/alien/alien-invoke.factor | 20 +- library/alien/compiler.factor | 12 +- library/bootstrap/boot-stage1.factor | 14 +- library/bootstrap/boot-stage2.factor | 7 +- library/compiler/amd64/architecture.factor | 4 - library/compiler/architecture.factor | 108 ++++++- library/compiler/compiler.factor | 20 +- library/compiler/generator.factor | 222 +++++++++++--- library/compiler/linearizer.factor | 134 -------- library/compiler/ppc/alien.factor | 89 ------ library/compiler/ppc/architecture.factor | 163 +++++++++- library/compiler/ppc/fixnum.factor | 133 -------- library/compiler/ppc/generator.factor | 108 ------- library/compiler/ppc/intrinsics.factor | 225 ++++++++++++++ library/compiler/ppc/slots.factor | 64 ---- library/compiler/ppc/stack.factor | 39 --- library/compiler/stack.factor | 47 --- library/compiler/templates.factor | 8 +- library/compiler/vops.factor | 340 --------------------- library/compiler/x86/architecture.factor | 4 - library/compiler/xt.factor | 8 +- library/test/compiler/ifte.factor | 1 + library/test/compiler/intrinsics.factor | 74 ++--- library/test/compiler/linearizer.factor | 15 - library/test/compiler/simple.factor | 5 + library/test/test.factor | 2 +- 28 files changed, 775 insertions(+), 1118 deletions(-) delete mode 100644 library/compiler/linearizer.factor delete mode 100644 library/compiler/ppc/alien.factor delete mode 100644 library/compiler/ppc/fixnum.factor delete mode 100644 library/compiler/ppc/generator.factor create mode 100644 library/compiler/ppc/intrinsics.factor delete mode 100644 library/compiler/ppc/slots.factor delete mode 100644 library/compiler/ppc/stack.factor delete mode 100644 library/compiler/stack.factor delete mode 100644 library/compiler/vops.factor delete mode 100644 library/test/compiler/linearizer.factor diff --git a/TODO.FACTOR.txt b/TODO.FACTOR.txt index 269f36bf87..6edf8eba78 100644 --- a/TODO.FACTOR.txt +++ b/TODO.FACTOR.txt @@ -9,8 +9,6 @@ should fix in 0.82: - get factor running on mac intel - when generating a 32-bit image on a 64-bit system, large numbers which should be bignums become fixnums -- httpd fep -- SBUF" " i/o bug - clicks sent twice - speed up ideas: - only do clipping for certain gadgets diff --git a/library/alien/alien-callback.factor b/library/alien/alien-callback.factor index fef4d10f6c..633b7a86ec 100644 --- a/library/alien/alien-callback.factor +++ b/library/alien/alien-callback.factor @@ -32,35 +32,34 @@ M: alien-callback-error summary ( error -- ) ] "infer" set-word-prop : box-parameters ( parameters -- ) - [ box-parameter ] map-parameters % ; + [ box-parameter ] each-parameter ; : registers>objects ( parameters -- ) - dup \ %freg>stack move-parameters % - "nest_stacks" f %alien-invoke , box-parameters ; + dup \ %freg>stack move-parameters + "nest_stacks" f %alien-invoke box-parameters ; : unbox-return ( node -- ) alien-callback-return [ - "unnest_stacks" f %alien-invoke , + "unnest_stacks" f %alien-invoke ] [ c-type [ "reg-class" get "unboxer-function" get - %callback-value , + %callback-value ] bind ] if-void ; -: linearize-callback ( node -- ) - dup alien-callback-xt [ - dup stack-reserve* %prologue , +: generate-callback ( node -- ) + [ alien-callback-xt ] keep [ dup alien-callback-parameters registers>objects dup alien-callback-quot \ init-error-handler swons - %alien-callback , + %alien-callback unbox-return - %return , - ] make-linear ; + %return + ] generate-block ; -M: alien-callback linearize* ( node -- ) - end-basic-block compile-gc linearize-callback iterate-next ; +M: alien-callback generate-node ( node -- ) + end-basic-block compile-gc generate-callback iterate-next ; M: alien-callback stack-reserve* alien-callback-parameters stack-space ; diff --git a/library/alien/alien-invoke.factor b/library/alien/alien-invoke.factor index 853939cc47..213ff16c67 100644 --- a/library/alien/alien-invoke.factor +++ b/library/alien/alien-invoke.factor @@ -39,35 +39,35 @@ M: alien-invoke-error summary ( error -- ) node, ] "infer" set-word-prop -: unbox-parameter ( stack# type -- node ) +: unbox-parameter ( stack# type -- ) c-type [ "reg-class" get "unboxer" get call ] bind ; : unbox-parameters ( parameters -- ) - [ unbox-parameter , ] reverse-each-parameter ; + [ unbox-parameter ] reverse-each-parameter ; : objects>registers ( parameters -- ) #! Generate code for boxing a list of C types, then generate #! code for moving these parameters to register on #! architectures where parameters are passed in registers #! (PowerPC, AMD64). - dup unbox-parameters "save_stacks" f %alien-invoke , - \ %stack>freg move-parameters % ; + dup unbox-parameters "save_stacks" f %alien-invoke + \ %stack>freg move-parameters ; : box-return ( node -- ) - alien-invoke-return [ ] [ f swap box-parameter , ] if-void ; + alien-invoke-return [ ] [ f swap box-parameter ] if-void ; -: linearize-cleanup ( node -- ) +: generate-cleanup ( node -- ) dup alien-invoke-library library-abi "stdcall" = [ drop ] [ - alien-invoke-parameters stack-space %cleanup , + alien-invoke-parameters stack-space %cleanup ] if ; -M: alien-invoke linearize* ( node -- ) +M: alien-invoke generate-node ( node -- ) end-basic-block compile-gc dup alien-invoke-parameters objects>registers - dup alien-invoke-dlsym %alien-invoke , - dup linearize-cleanup box-return + dup alien-invoke-dlsym %alien-invoke + dup generate-cleanup box-return iterate-next ; M: alien-invoke stack-reserve* diff --git a/library/alien/compiler.factor b/library/alien/compiler.factor index 9deb4f3a2b..63df3cdd23 100644 --- a/library/alien/compiler.factor +++ b/library/alien/compiler.factor @@ -36,22 +36,22 @@ kernel-internals math namespaces sequences words ; [ c-size cell / "void*" ] [ 1array ] if ] map concat ; +: each-parameter ( parameters quot -- ) + >r [ parameter-sizes ] keep r> 2each ; inline + : reverse-each-parameter ( parameters quot -- ) >r [ parameter-sizes ] keep [ reverse-slice ] 2apply r> 2each ; inline -: map-parameters ( parameters quot -- seq ) - >r [ parameter-sizes ] keep r> 2map ; inline - -: move-parameters ( params vop -- seq ) +: move-parameters ( params vop -- ) #! Moves values from C stack to registers (if vop is #! %stack>freg) and registers to C stack (if vop is #! %freg>stack). swap [ flatten-value-types 0 { int-regs float-regs stack-params } [ set ] each-with - [ pick >r alloc-parameter r> execute ] map-parameters - nip + [ pick >r alloc-parameter r> execute ] each-parameter + drop ] with-scope ; inline : box-parameter ( stack# type -- node ) diff --git a/library/bootstrap/boot-stage1.factor b/library/bootstrap/boot-stage1.factor index e063ee395e..6a928e1e21 100644 --- a/library/bootstrap/boot-stage1.factor +++ b/library/bootstrap/boot-stage1.factor @@ -126,12 +126,8 @@ vectors words ; "/library/inference/print-dataflow.factor" "/library/compiler/assembler.factor" - "/library/compiler/vops.factor" "/library/compiler/templates.factor" - "/library/compiler/linearizer.factor" - "/library/compiler/stack.factor" "/library/compiler/xt.factor" - "/library/compiler/intrinsics.factor" "/library/compiler/generator.factor" "/library/compiler/compiler.factor" @@ -297,11 +293,11 @@ vectors words ; { "/library/compiler/ppc/assembler.factor" "/library/compiler/ppc/architecture.factor" - "/library/compiler/ppc/generator.factor" - "/library/compiler/ppc/slots.factor" - "/library/compiler/ppc/stack.factor" - "/library/compiler/ppc/fixnum.factor" - "/library/compiler/ppc/alien.factor" + ! "/library/compiler/ppc/generator.factor" + ! "/library/compiler/ppc/slots.factor" + ! "/library/compiler/ppc/stack.factor" + ! "/library/compiler/ppc/fixnum.factor" + ! "/library/compiler/ppc/alien.factor" } ] } { diff --git a/library/bootstrap/boot-stage2.factor b/library/bootstrap/boot-stage2.factor index d13befd2b4..ba1de70cb3 100644 --- a/library/bootstrap/boot-stage2.factor +++ b/library/bootstrap/boot-stage2.factor @@ -23,12 +23,7 @@ H{ } clone help-graph set-global xref-articles "Compiling base..." print flush - { - uncons 1+ 1- + <= > >= mod length - nth-unsafe set-nth-unsafe - = string>number number>string scan - kill-values (generate) - } [ compile ] each + { "kernel" "sequences" "assembler" } compile-vocabs "Compiling system..." print flush compile-all diff --git a/library/compiler/amd64/architecture.factor b/library/compiler/amd64/architecture.factor index 6950d4dec3..4922f704d5 100644 --- a/library/compiler/amd64/architecture.factor +++ b/library/compiler/amd64/architecture.factor @@ -10,10 +10,6 @@ kernel-internals math namespaces sequences ; ! R14 datastack ! R15 callstack -: fixnum-imm? ( -- ? ) - #! Can fixnum operations take immediate operands? - f ; inline - : ds-reg R14 ; inline : cs-reg R15 ; inline : remainder-reg RDX ; inline diff --git a/library/compiler/architecture.factor b/library/compiler/architecture.factor index 2325bd7299..acc122ed6a 100644 --- a/library/compiler/architecture.factor +++ b/library/compiler/architecture.factor @@ -1,10 +1,110 @@ IN: compiler +USING: generic kernel kernel-internals math memory namespaces +sequences ; -! A few things the front-end needs to know about the back-end. +! A scratch register for computations +TUPLE: vreg n ; -DEFER: fixnum-imm? ( -- ? ) -#! Can fixnum operations take immediate operands? +! Register classes +TUPLE: int-regs ; +TUPLE: float-regs size ; +! A pseudo-register class for parameters spilled on the stack +TUPLE: stack-params ; + +! Return values of this class go here +GENERIC: return-reg ( register-class -- reg ) + +! Sequence of registers used for parameter passing in class +GENERIC: fastcall-regs ( register-class -- regs ) + +! Sequence mapping vreg-n to native assembler registers DEFER: vregs ( -- regs ) -DEFER: compile-c-call ( library function -- ) +! Load a literal (immediate or indirect) +G: load-literal ( obj vreg -- ) 1 standard-combination ; + +! Set up caller stack frame (PowerPC and AMD64) +DEFER: %prologue ( n -- ) + +! Tail call another word +DEFER: %jump ( label -- ) + +! Call another word +DEFER: %call ( label -- ) + +! Local jump for branches or tail calls in nested #label +DEFER: %jump-label ( label -- ) + +! Test if vreg is 'f' or not +DEFER: %jump-t ( label vreg -- ) + +! Jump table of addresses (one cell each) is right after this +DEFER: %dispatch ( vreg -- ) + +! Return to caller +DEFER: %return ( -- ) + +! Change datastack height +DEFER: %inc-d ( n -- ) + +! Change callstack height +DEFER: %inc-r ( n -- ) + +! Load stack into vreg +DEFER: %peek ( vreg loc -- ) + +! Store vreg to stack +DEFER: %replace ( vreg loc -- ) + +! FFI stuff +DEFER: %unbox ( n reg-class func -- ) + +DEFER: %unbox-struct ( n reg-class size -- ) + +DEFER: %box ( n reg-class func -- ) + +DEFER: %box-struct ( n reg-class size -- ) + +DEFER: %alien-invoke ( library function -- ) + +DEFER: %alien-callback ( quot -- ) + +DEFER: %callback-value ( reg-class func -- ) + +! A few FFI operations have default implementations +: %cleanup ( n -- ) drop ; + +: %stack>freg ( n reg reg-class -- ) 3drop ; + +: %freg>stack ( n reg reg-class -- ) 3drop ; + +! Some stuff probably not worth redefining in other backends +M: stack-params fastcall-regs drop 0 ; + +GENERIC: reg-size ( register-class -- n ) + +GENERIC: inc-reg-class ( register-class -- ) + +M: int-regs reg-size drop cell ; + +: (inc-reg-class) + dup class inc + macosx? [ reg-size stack-params +@ ] [ drop ] if ; + +M: int-regs inc-reg-class + (inc-reg-class) ; + +M: float-regs reg-size float-regs-size ; + +M: float-regs inc-reg-class + dup (inc-reg-class) + macosx? [ reg-size 4 / int-regs +@ ] [ drop ] if ; + +GENERIC: v>operand + +M: integer v>operand tag-bits shift ; + +M: vreg v>operand vreg-n vregs nth ; + +M: f v>operand address ; diff --git a/library/compiler/compiler.factor b/library/compiler/compiler.factor index e3f5d2885a..ec7681d4ef 100644 --- a/library/compiler/compiler.factor +++ b/library/compiler/compiler.factor @@ -5,23 +5,21 @@ USING: errors hashtables inference io kernel lists math namespaces optimizer prettyprint sequences test words ; : (compile) ( word -- ) - #! Should be called inside the with-compiler scope. - dup word-def dataflow optimize linearize - [ generate ] hash-each ; - -: benchmark-compile - [ [ (compile) ] keep ] benchmark nip + [ + [ + dup word-def dataflow optimize generate + ] keep + ] benchmark nip "compile-time" set-word-prop ; : inform-compile ( word -- ) "Compiling " write . flush ; : compile-postponed ( -- ) compile-words get dup empty? [ - dup pop - dup inform-compile - benchmark-compile - compile-postponed - ] unless drop ; + drop + ] [ + pop dup inform-compile (compile) compile-postponed + ] if ; : compile ( word -- ) [ postpone-word compile-postponed ] with-compiler ; diff --git a/library/compiler/generator.factor b/library/compiler/generator.factor index 78c6e40fe1..0d3b2862a9 100644 --- a/library/compiler/generator.factor +++ b/library/compiler/generator.factor @@ -1,18 +1,39 @@ -! Copyright (C) 2004, 2005 Slava Pestov. -! See http://factor.sf.net/license.txt for BSD license. +! Copyright (C) 2004, 2006 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. IN: compiler -USING: alien assembler errors inference kernel -kernel-internals lists math memory namespaces sequences strings -vectors words ; +USING: arrays assembler errors generic hashtables inference +kernel kernel-internals lists math namespaces queues sequences +words ; -! Compile a VOP. -GENERIC: generate-node ( vop -- ) +GENERIC: stack-reserve* -: generate-code ( word linear -- length ) +M: object stack-reserve* drop 0 ; + +: stack-reserve ( node -- n ) + 0 swap [ stack-reserve* max ] each-node ; + +DEFER: #terminal? + +PREDICATE: #merge #terminal-merge node-successor #terminal? ; + +PREDICATE: #call #terminal-call + dup node-successor node-successor #terminal? + swap if-intrinsic and ; + +UNION: #terminal + POSTPONE: f #return #values #terminal-merge ; + +: tail-call? ( -- ? ) + node-stack get [ + dup #terminal-call? swap node-successor #terminal? or + ] all? ; + +: generate-code ( word node quot -- length | quot: node -- ) compiled-offset >r compile-aligned - swap save-xt - [ dup [ generate-node ] with-vop ] each + rot save-xt + over stack-reserve %prologue + call compile-aligned compiled-offset r> - ; @@ -21,46 +42,175 @@ GENERIC: generate-node ( vop -- ) dup [ assemble-cell ] each length cells ; -: (generate) ( word linear -- ) - #! Compile a word definition from linear IR. - V{ } clone relocation-table set - begin-assembly swap >r >r - generate-code - generate-reloc - r> set-compiled-cell - r> set-compiled-cell ; - SYMBOL: previous-offset -: generate ( word linear -- ) +: begin-generating ( -- code-len-fixup reloc-len-fixup ) + compiled-offset previous-offset set + V{ } clone relocation-table set + init-templates begin-assembly swap ; + +: generate-1 ( word node quot -- | quot: node -- ) #! If generation fails, reset compiled offset. [ - compiled-offset previous-offset set - (generate) + begin-generating >r >r + generate-code + generate-reloc + r> set-compiled-cell + r> set-compiled-cell ] [ - previous-offset get set-compiled-offset - rethrow + previous-offset get set-compiled-offset rethrow ] recover ; -! A few VOPs have trivial generators. +SYMBOL: generate-queue -M: %label generate-node ( vop -- ) - vop-label save-xt ; +: generate-loop ( -- ) + generate-queue get dup queue-empty? [ + drop + ] [ + deque first3 generate-1 generate-loop + ] if ; -M: %target-label generate-node ( vop -- ) - drop label 0 assemble-cell absolute-cell ; +: generate-block ( word node quot -- | quot: node -- ) + 3array generate-queue get enque ; -M: %cleanup generate-node ( vop -- ) drop ; +GENERIC: generate-node ( node -- ) -M: %freg>stack generate-node ( vop -- ) drop ; +: generate-nodes ( node -- ) + [ node@ generate-node ] iterate-nodes end-basic-block ; -M: %stack>freg generate-node ( vop -- ) drop ; +: generate-word ( node -- ) + [ [ generate-nodes ] with-node-iterator ] + generate-block ; -M: %alien-invoke generate-node - #! call a C function. - drop 0 input 1 input compile-c-call ; +: generate ( word node -- ) + [ + generate-queue set + generate-word generate-loop + ] with-scope ; -: dest/src ( -- dest src ) 0 output-operand 0 input-operand ; +! node +M: node generate-node ( node -- next ) drop iterate-next ; + +! #label +: generate-call ( label -- next ) + end-basic-block + tail-call? [ %jump f ] [ %call iterate-next ] if ; + +M: #label generate-node ( node -- next ) + #! We remap the IR node's label to a new label object here, + #! to avoid problems with two IR #label nodes having the + #! same label in different lexical scopes. + dup node-param dup generate-call >r + swap node-child generate-word r> ; + +! #if +: generate-if ( node label -- next ) +