diff --git a/basis/compiler/cfg/builder/builder.factor b/basis/compiler/cfg/builder/builder.factor index 93daa601fe..17a5942af2 100755 --- a/basis/compiler/cfg/builder/builder.factor +++ b/basis/compiler/cfg/builder/builder.factor @@ -171,6 +171,7 @@ M: #if emit-node [ V{ } clone node-stack set ##prologue + begin-basic-block emit-nodes basic-block get [ ##epilogue diff --git a/basis/compiler/tests/templates.factor b/basis/compiler/tests/templates.factor index de87ad8c00..0a109a15eb 100644 --- a/basis/compiler/tests/templates.factor +++ b/basis/compiler/tests/templates.factor @@ -219,3 +219,14 @@ TUPLE: my-tuple ; : bad-value-bug ( a -- b ) [ 3 ] [ 3 ] if f ; [ { f f f } ] [ t bad-value-bug ] unit-test + +! PowerPC regression +TUPLE: id obj ; + +: (gc-check-bug) ( a b -- c ) + { [ id boa ] [ id boa ] } dispatch ; + +: gc-check-bug ( -- ) + 10000000 [ "hi" 0 (gc-check-bug) drop ] times ; + +[ ] [ gc-check-bug ] unit-test diff --git a/basis/cpu/ppc/ppc.factor b/basis/cpu/ppc/ppc.factor index 2be46d15ee..49caae4bb8 100644 --- a/basis/cpu/ppc/ppc.factor +++ b/basis/cpu/ppc/ppc.factor @@ -4,7 +4,8 @@ USING: accessors assocs sequences kernel combinators make math math.order math.ranges system namespaces locals layouts words alien alien.c-types cpu.architecture cpu.ppc.assembler compiler.cfg.registers compiler.cfg.instructions -compiler.constants compiler.codegen compiler.codegen.fixup ; +compiler.constants compiler.codegen compiler.codegen.fixup +compiler.cfg.intrinsics compiler.cfg.stack-frame ; IN: cpu.ppc ! PowerPC register assignments: @@ -15,15 +16,19 @@ IN: cpu.ppc ! f0-f29: float vregs ! f30, f31: float scratch +enable-float-intrinsics + +<< \ ##integer>float t frame-required? set-word-prop +\ ##float>integer t frame-required? set-word-prop >> + M: ppc machine-registers { { int-regs T{ range f 2 26 1 } } - { double-float-regs T{ range f 0 28 1 } } + { double-float-regs T{ range f 0 29 1 } } } ; : scratch-reg 28 ; inline -: fp-scratch-reg-1 29 ; inline -: fp-scratch-reg-2 30 ; inline +: fp-scratch-reg 30 ; inline M: ppc two-operand? f ; @@ -54,8 +59,16 @@ M: ppc %inc-d ( n -- ) ds-reg (%inc) ; M: ppc %inc-r ( n -- ) rs-reg (%inc) ; HOOK: reserved-area-size os ( -- n ) -HOOK: lr-save os ( -- n ) +! The start of the stack frame contains the size of this frame +! as well as the currently executing XT +: factor-area-size ( -- n ) 2 cells ; foldable +: next-save ( n -- i ) cell - ; +: xt-save ( n -- i ) 2 cells - ; + +! Next, we have the spill area as well as the FFI parameter area. +! They overlap, since basic blocks with FFI calls will never +! spill. : param@ ( n -- x ) reserved-area-size + ; inline : param-save-size ( -- n ) 8 cells ; foldable @@ -63,19 +76,34 @@ HOOK: lr-save os ( -- n ) : local@ ( n -- x ) reserved-area-size param-save-size + + ; inline -: factor-area-size ( -- n ) 2 cells ; foldable +: spill-integer-base ( -- n ) + stack-frame get spill-counts>> double-float-regs swap at + double-float-regs reg-size * ; -: next-save ( n -- i ) cell - ; +: spill-integer@ ( n -- offset ) + cells spill-integer-base + param@ ; -: xt-save ( n -- i ) 2 cells - ; +: spill-float@ ( n -- offset ) + double-float-regs reg-size * param@ ; + +! Some FP intrinsics need a temporary scratch area in the stack +! frame, 8 bytes in size +: scratch@ ( n -- offset ) + stack-frame get total-size>> + factor-area-size - + param-save-size - + + ; + +! Finally we have the linkage area +HOOK: lr-save os ( -- n ) M: ppc stack-frame-size ( stack-frame -- i ) [ spill-counts>> [ swap reg-size * ] { } assoc>map sum ] [ params>> ] [ return>> ] tri + + - reserved-area-size + param-save-size + + reserved-area-size + factor-area-size + 4 cells align ; @@ -198,19 +226,19 @@ M: ppc %div-float FDIV ; M:: ppc %integer>float ( dst src -- ) HEX: 4330 scratch-reg LIS - scratch-reg 1 0 param@ STW + scratch-reg 1 0 scratch@ STW scratch-reg src MR scratch-reg dup HEX: 8000 XORIS - scratch-reg 1 cell param@ STW - fp-scratch-reg-2 1 0 param@ LFD + scratch-reg 1 4 scratch@ STW + dst 1 0 scratch@ LFD scratch-reg 4503601774854144.0 %load-indirect - fp-scratch-reg-2 scratch-reg float-offset LFD - fp-scratch-reg-2 fp-scratch-reg-2 fp-scratch-reg-2 FSUB ; + fp-scratch-reg scratch-reg float-offset LFD + dst dst fp-scratch-reg FSUB ; M:: ppc %float>integer ( dst src -- ) - fp-scratch-reg-1 src FCTIWZ - fp-scratch-reg-2 1 0 param@ STFD - dst 1 4 param@ LWZ ; + fp-scratch-reg src FCTIWZ + fp-scratch-reg 1 0 scratch@ STFD + dst 1 4 scratch@ LWZ ; M: ppc %copy ( dst src -- ) MR ; @@ -218,6 +246,10 @@ M: ppc %copy-float ( dst src -- ) FMR ; M: ppc %unbox-float ( dst src -- ) float-offset LFD ; +M:: ppc %box-float ( dst src temp -- ) + dst 16 float temp %allot + src dst float-offset STFD ; + M:: ppc %unbox-any-c-ptr ( dst src temp -- ) [ { "is-byte-array" "end" "start" } [ define-label ] each @@ -349,11 +381,6 @@ M: ppc %gc "end" resolve-label ; M: ppc %prologue ( n -- ) - #! We use a volatile register (r11) here for scratch. Because - #! callback bodies have a prologue too, we cannot assume - #! that c_to_factor saved all non-volatile registers, so - #! we have to respect the C calling convention. Also, we - #! cannot touch any param-regs either. 0 11 LOAD32 rc-absolute-ppc-2/2 rel-this 0 MFLR 1 1 pick neg ADDI @@ -410,32 +437,11 @@ M: ppc %compare-branch (%compare) %branch ; M: ppc %compare-imm-branch (%compare-imm) %branch ; M: ppc %compare-float-branch (%compare-float) %branch ; -: spill-integer-base ( stack-frame -- n ) - [ params>> ] [ return>> ] bi + ; +M: ppc %spill-integer ( src n -- ) spill-integer@ 1 swap STW ; +M: ppc %reload-integer ( dst n -- ) spill-integer@ 1 swap LWZ ; -: stack@ 1 swap ; inline - -: spill-integer@ ( n -- reg offset ) - cells - stack-frame get spill-integer-base - + stack@ ; - -: spill-float-base ( stack-frame -- n ) - [ spill-counts>> int-regs swap at int-regs reg-size * ] - [ params>> ] - [ return>> ] - tri + + ; - -: spill-float@ ( n -- reg offset ) - double-float-regs reg-size * - stack-frame get spill-float-base - + stack@ ; - -M: ppc %spill-integer ( src n -- ) spill-integer@ STW ; -M: ppc %reload-integer ( dst n -- ) spill-integer@ LWZ ; - -M: ppc %spill-float ( src n -- ) spill-float@ STFD ; -M: ppc %reload-float ( dst n -- ) spill-float@ LFD ; +M: ppc %spill-float ( src n -- ) spill-float@ 1 swap STFD ; +M: ppc %reload-float ( dst n -- ) spill-float@ 1 swap LFD ; M: ppc %loop-entry ; diff --git a/basis/io/unix/launcher/parser/parser.factor b/basis/io/unix/launcher/parser/parser.factor index e5e83ab4e9..276ed45f27 100644 --- a/basis/io/unix/launcher/parser/parser.factor +++ b/basis/io/unix/launcher/parser/parser.factor @@ -29,5 +29,5 @@ IN: io.unix.launcher.parser PEG: tokenize-command ( command -- ast/f ) 'argument' " " token repeat1 list-of - " " token repeat0 swap over pack + " " token repeat0 tuck pack just ; diff --git a/basis/peg/ebnf/ebnf.factor b/basis/peg/ebnf/ebnf.factor index 776450ccd9..ccae0fec93 100644 --- a/basis/peg/ebnf/ebnf.factor +++ b/basis/peg/ebnf/ebnf.factor @@ -487,7 +487,7 @@ M: ebnf-terminal (transform) ( ast -- parser ) M: ebnf-foreign (transform) ( ast -- parser ) dup word>> search [ "Foreign word '" swap word>> append "' not found" append throw ] unless* - swap rule>> [ main ] unless* dupd swap rule [ + swap rule>> [ main ] unless* over rule [ nip ] [ execute diff --git a/core/generic/standard/standard-docs.factor b/core/generic/standard/standard-docs.factor index 1d98dec87c..15913b46be 100644 --- a/core/generic/standard/standard-docs.factor +++ b/core/generic/standard/standard-docs.factor @@ -16,7 +16,7 @@ HELP: standard-combination { $examples "A generic word for append strings and characters to a sequence, dispatching on the object underneath the top of the stack:" { $code - "G: build-string 1 standard-combination ;" + "GENERIC# build-string 1 ( elt str -- )" "M: string build-string swap push-all ;" "M: integer build-string push ;" } diff --git a/extra/project-euler/215/215-tests.factor b/extra/project-euler/215/215-tests.factor new file mode 100644 index 0000000000..ddd87cc2ff --- /dev/null +++ b/extra/project-euler/215/215-tests.factor @@ -0,0 +1,5 @@ +USING: project-euler.215 tools.test ; +IN: project-euler.215.tests + +[ 8 ] [ 9 3 solve ] unit-test +[ 806844323190414 ] [ euler215 ] unit-test diff --git a/extra/project-euler/215/215.factor b/extra/project-euler/215/215.factor new file mode 100644 index 0000000000..056de72e50 --- /dev/null +++ b/extra/project-euler/215/215.factor @@ -0,0 +1,56 @@ +USING: accessors kernel locals math ; +IN: project-euler.215 + +TUPLE: block two three ; +TUPLE: end { ways integer } ; + +C: block +C: end +: 0 ; inline +: 1 ; inline + +: failure? ( t -- ? ) ways>> 0 = ; inline + +: choice ( t p q -- t t ) [ [ two>> ] [ three>> ] bi ] 2dip bi* ; inline + +GENERIC: merge ( t t -- t ) +GENERIC# block-merge 1 ( t t -- t ) +GENERIC# end-merge 1 ( t t -- t ) +M: block merge block-merge ; +M: end merge end-merge ; +M: block block-merge [ [ two>> ] bi@ merge ] + [ [ three>> ] bi@ merge ] 2bi ; +M: end block-merge nip ; +M: block end-merge drop ; +M: end end-merge [ ways>> ] bi@ + ; + +GENERIC: h-1 ( t -- t ) +GENERIC: h0 ( t -- t ) +GENERIC: h1 ( t -- t ) +GENERIC: h2 ( t -- t ) + +M: block h-1 [ h1 ] [ h2 ] choice merge ; +M: block h0 drop ; +M: block h1 [ [ h1 ] [ h2 ] choice merge ] + [ [ h0 ] [ h1 ] choice merge ] bi ; +M: block h2 [ h1 ] [ h2 ] choice merge swap ; + +M: end h-1 drop ; +M: end h0 ; +M: end h1 drop ; +M: end h2 dup failure? [ ] unless ; + +: next-row ( t -- t ) [ h-1 ] [ h1 ] choice swap ; + +: first-row ( n -- t ) + [ ] dip + 1- [| a b c | b c a b ] times 2drop ; + +GENERIC: total ( t -- n ) +M: block total [ total ] dup choice + ; +M: end total ways>> ; + +: solve ( width height -- ways ) + [ first-row ] dip 1- [ next-row ] times total ; + +: euler215 ( -- ways ) 32 10 solve ;