--- gforth/prims2x.fs 2003/10/09 14:15:19 1.144 +++ gforth/prims2x.fs 2005/07/28 14:12:33 1.157 @@ -1,6 +1,6 @@ \ converts primitives to, e.g., C code -\ Copyright (C) 1995,1996,1997,1998,2000,2003 Free Software Foundation, Inc. +\ Copyright (C) 1995,1996,1997,1998,2000,2003,2004 Free Software Foundation, Inc. \ This file is part of Gforth. @@ -231,13 +231,13 @@ variable next-state-number 0 next-state- rdrop ; : map-stacks { xt -- } - \ perform xt for all stacks + \ perform xt ( stack -- ) for all stacks next-stack-number @ 0 +do stacks i th @ xt execute loop ; : map-stacks1 { xt -- } - \ perform xt for all stacks except inst-stream + \ perform xt ( stack -- ) for all stacks except inst-stream next-stack-number @ 1 +do stacks i th @ xt execute loop ; @@ -246,7 +246,7 @@ variable next-state-number 0 next-state- : init-item ( addr u addr1 -- ) \ initialize item at addr1 with name addr u - \ !! remove stack prefix + \ the stack prefix is removed by the stack-prefix dup item% %size erase item-name 2! ; @@ -267,6 +267,7 @@ struct% cell% 2* field prim-name cell% 2* field prim-wordset cell% 2* field prim-c-name + cell% 2* field prim-c-name-orig \ for reprocessed prims, the original name cell% 2* field prim-doc cell% 2* field prim-c-code cell% 2* field prim-forth-code @@ -279,6 +280,7 @@ struct% cell% field prim-effect-out-end cell% max-stacks * field prim-stacks-in \ number of in items per stack cell% max-stacks * field prim-stacks-out \ number of out items per stack + cell% max-stacks * field prim-stacks-sync \ sync flag per stack end-struct prim% : make-prim ( -- prim ) @@ -302,6 +304,9 @@ variable in-part \ true if processing a r> to prim throw ; +: prim-c-name-2! ( c-addr u -- ) + 2dup prim prim-c-name 2! prim prim-c-name-orig 2! ; + 1000 constant max-combined create combined-prims max-combined cells allot variable num-combined @@ -531,8 +536,8 @@ defer inst-stream-f ( -- stack ) : store-single { item -- } item item-stack @ { stack } store-optimization @ in-part @ 0= and item same-as-in? and - item item-in-index stack state-in stack-reg 0= and \ in in memory? - item item-out-index stack state-out stack-reg 0= and \ out in memory? + item item-in-index stack state-in stack-reg \ in reg/mem + item item-out-index stack state-out stack-reg = and \ out reg/mem 0= if item really-store-single cr endif ; @@ -645,6 +650,41 @@ does> ( item -- ) stack item item-stack ! item declaration ; +: stack-prim-stacks-sync ( stack -- addr ) + prim prim-stacks-sync swap stack-number @ th ; + +: set-prim-stacks-sync ( stack -- ) + stack-prim-stacks-sync on ; + +: clear-prim-stacks-sync ( stack -- ) + stack-prim-stacks-sync off ; + + +get-current prefixes set-current +: ... ( item -- ) + \ this "prefix" ensures that the appropriate stack is synced with memory + dup item-name 2@ s" ..." str= 0= abort" '...' must end the item name" + item-stack @ dup if + set-prim-stacks-sync + else \ prefixless "..." syncs all stacks + ['] set-prim-stacks-sync map-stacks1 + endif ; +set-current + +create ...-item ( -- addr ) \ just used for letting stack-prefixes work on it +item% %allot \ stores the stack temporarily until used by ... + +: init-item1 ( addr1 addr u -- addr2 ) + \ initialize item at addr1 with name addr u, next item is at addr2 + \ !! make sure that any mention of "..." is only stack-prefixed + 2dup s" ..." search nip nip if ( addr1 addr u ) + 0 ...-item item-stack ! \ initialize to prefixless + 2dup ...-item item-name 2! + ...-item rot rot execute-prefix ( addr1 ) + else + 2 pick init-item item% %size + + endif ; + \ types pointed to by stacks for use in combined prims \ !! output-c-combined shouldn't use these names! : stack-type-name ( addr u "name" -- ) @@ -712,6 +752,9 @@ stack inst-stream IP Cell default-ss s state-sss i th ! loop ; +: .state ( state -- ) + 0 >body - >name .name ; + : set-ss ( ss stack state -- ) state-sss swap stack-number @ th ! ; @@ -738,6 +781,10 @@ stack inst-stream IP Cell prim prim-effect-out prim prim-effect-out-end @ ['] compute-offset-out map-items inst-stream stack-out @ 0= s" # can only be on the input side" ?print-error ; +: init-simple { prim -- } + \ much of the initialization is elsewhere + ['] clear-prim-stacks-sync map-stacks ; + : process-simple ( -- ) prim prim { W^ key } key cell combinations ['] constant insert-wordlist @@ -753,11 +800,19 @@ stack inst-stream IP Cell stack state-in stack-state-items stack stack-in @ - 0 max stack state-out stack-state-items stack stack-out @ - 0 max ; +: spill-stack-items { stack -- u } + \ there are u items to spill in stack + stack unused-stack-items + stack stack-prim-stacks-sync @ if + drop 0 + endif + swap - ; + : spill-stack { stack -- } \ spill regs of state-in that are not used by prim and are not in state-out stack state-in stack-offset { offset } stack state-in stack-state-items ( items ) - dup stack unused-stack-items - - +do + dup stack spill-stack-items + +do \ loop through the bottom items stack stack-pointer 2@ type i offset - stack normal-stack-access0 ." = " @@ -767,10 +822,18 @@ stack inst-stream IP Cell : spill-state ( -- ) ['] spill-stack map-stacks1 ; +: fill-stack-items { stack -- u } + \ there are u items to fill in stack + stack unused-stack-items + stack stack-prim-stacks-sync @ if + swap drop 0 swap + endif + - ; + : fill-stack { stack -- } stack state-out stack-offset { offset } stack state-out stack-state-items ( items ) - dup stack unused-stack-items - + +do + dup stack fill-stack-items + +do \ loop through the bottom items i stack state-out normal-stack-access1 ." = " stack stack-pointer 2@ type @@ -826,25 +889,45 @@ stack inst-stream IP Cell stack-access-transform @ dup >r execute 0 r> execute - ; -: stack-pointer-update { stack -- } - \ and moves - \ stacks grow downwards - stack stack-diff ( in-out ) - stack state-in stack-offset - - stack state-out stack-offset + ( [in-in_offset]-[out-out_offset] ) - ?dup-if \ this check is not necessary, gcc would do this for us +: update-stack-pointer { stack n -- } + n if \ this check is not necessary, gcc would do this for us stack inst-stream = if - ." INC_IP(" 0 .r ." );" cr + ." INC_IP(" n 0 .r ." );" cr else stack stack-pointer 2@ type ." += " - stack stack-update-transform 0 .r ." ;" cr + n stack stack-update-transform 0 .r ." ;" cr endif - endif - stack stack-moves ; + endif ; + +: stack-pointer-update { stack -- } + \ and moves + \ stacks grow downwards + stack stack-prim-stacks-sync @ if + stack stack-in @ + stack state-in stack-offset - + stack swap update-stack-pointer + else + stack stack-diff ( in-out ) + stack state-in stack-offset - + stack state-out stack-offset + ( [in-in_offset]-[out-out_offset] ) + stack swap update-stack-pointer + stack stack-moves + endif ; : stack-pointer-updates ( -- ) ['] stack-pointer-update map-stacks ; +: stack-pointer-update2 { stack -- } + stack stack-prim-stacks-sync @ if + stack state-out stack-offset + stack stack-out @ - + stack swap update-stack-pointer + endif ; + +: stack-pointer-updates2 ( -- ) + \ update stack pointers after C code, where necessary + ['] stack-pointer-update2 map-stacks ; + : store ( item -- ) \ f is true if the item should be stored \ f is false if the store is probably not necessary @@ -887,6 +970,17 @@ stack inst-stream IP Cell endif 2drop ; + +defer output-nextp0 +:noname ( -- ) + ." NEXT_P0;" cr ; +is output-nextp0 + +defer output-nextp1 +:noname ( -- ) + ." NEXT_P1;" cr ; +is output-nextp1 + : output-nextp2 ( -- ) ." NEXT_P2;" cr ; @@ -895,21 +989,34 @@ variable tail-nextp2 \ xt to execute for : output-label2 ( -- ) ." LABEL2(" prim prim-c-name 2@ type ." )" cr - ." NEXT_P2;" cr ; + ." NEXT_P1_5;" cr + ." LABEL3(" prim prim-c-name 2@ type ." )" cr + ." DO_GOTO;" cr ; : output-c-tail1 { xt -- } \ the final part of the generated C code, with xt printing LABEL2 or not. output-super-end print-debug-results - ." NEXT_P1;" cr + output-nextp1 + stack-pointer-updates2 stores fill-state xt execute ; +: output-c-vm-jump-tail ( -- ) + \ !! this functionality not yet implemented for superinstructions + output-super-end + print-debug-results + stores + fill-state + ." LABEL2(" prim prim-c-name 2@ type ." )" cr + ." LABEL3(" prim prim-c-name 2@ type ." )" cr + ." DO_GOTO;" cr ; + : output-c-tail1-no-stores { xt -- } \ the final part of the generated C code for combinations output-super-end - ." NEXT_P1;" cr + output-nextp1 fill-state xt execute ; @@ -917,7 +1024,11 @@ variable tail-nextp2 \ xt to execute for tail-nextp2 @ output-c-tail1 ; : output-c-tail2 ( -- ) - ['] output-label2 output-c-tail1 ; + prim prim-c-code 2@ s" VM_JUMP(" search nip nip if + output-c-vm-jump-tail + else + ['] output-label2 output-c-tail1 + endif ; : output-c-tail-no-stores ( -- ) tail-nextp2 @ output-c-tail1-no-stores ; @@ -944,15 +1055,23 @@ variable tail-nextp2 \ xt to execute for : print-entry ( -- ) ." LABEL(" prim prim-c-name 2@ type ." )" ; - -: output-c ( -- ) - print-entry ." /* " prim prim-name 2@ type ." ( " prim prim-stack-string 2@ type ." ) */" cr + +: prim-type ( addr u -- ) + \ print out a primitive, but avoid "*/" + 2dup s" */" search nip nip IF + bounds ?DO I c@ dup '* = IF drop 'x THEN emit LOOP + ELSE type THEN ; + +: output-c ( -- ) + print-entry ." /* " prim prim-name 2@ prim-type + ." ( " prim prim-stack-string 2@ type ." ) " + state-in .state ." -- " state-out .state ." */" cr ." /* " prim prim-doc 2@ type ." */" cr ." NAME(" quote prim prim-name 2@ type quote ." )" cr \ debugging ." {" cr ." DEF_CA" cr print-declarations - ." NEXT_P0;" cr + output-nextp0 spill-state fetches print-debug-args @@ -1024,7 +1143,7 @@ variable tail-nextp2 \ xt to execute for prim prim-branch? prim prim-c-code 2@ s" SUPER_END" search nip nip 0<> or prim prim-c-code 2@ s" SUPER_CONTINUE" search nip nip 0= and - negate 0 .r ." , /* " prim prim-name 2@ type ." */" cr ; + negate 0 .r ." , /* " prim prim-name 2@ prim-type ." */" cr ; : gen-arg-parm { item -- } item item-stack @ inst-stream = if @@ -1095,8 +1214,11 @@ variable tail-nextp2 \ xt to execute for : output-alias ( -- ) ( primitive-number @ . ." alias " ) ." Primitive " prim prim-name 2@ type cr ; -: output-c-prim-num ( -- ) +defer output-c-prim-num ( -- ) + +:noname ( -- ) ." N_" prim prim-c-name 2@ type ." ," cr ; +is output-c-prim-num : output-forth ( -- ) prim prim-forth-code @ 0= @@ -1349,6 +1471,9 @@ variable reprocessed-num 0 reprocessed-n : compute-default-state-out ( n-in -- n-out ) \ for the current prim cache-stack stack-in @ - 0 max + cache-stack stack-prim-stacks-sync @ if + drop 0 + endif cache-stack stack-out @ + cache-states 2@ nip 1- min ; : gen-prim-states ( prim -- ) @@ -1427,7 +1552,7 @@ variable reprocessed-num 0 reprocessed-n : output-part ( p -- ) to prim - ." /* " prim prim-name 2@ type ." ( " prim prim-stack-string 2@ type ." ) */" cr + ." /* " prim prim-name 2@ prim-type ." ( " prim prim-stack-string 2@ type ." ) */" cr ." NAME(" quote prim prim-name 2@ type quote ." )" cr \ debugging ." {" cr print-declarations @@ -1454,7 +1579,7 @@ variable reprocessed-num 0 reprocessed-n ." {" cr ." DEF_CA" cr print-declarations-combined - ." NEXT_P0;" cr + output-nextp0 spill-state \ fetches \ now in parts \ print-debug-args @@ -1494,11 +1619,14 @@ variable reprocessed-num 0 reprocessed-n \ This is intended as initializer for a structure like this \ struct cost { -\ int loads; /* number of stack loads */ -\ int stores; /* number of stack stores */ -\ int updates; /* number of stack pointer updates */ -\ int offset; /* offset into super2 table */ -\ int length; /* number of components */ +\ char loads; /* number of stack loads */ +\ char stores; /* number of stack stores */ +\ char updates; /* number of stack pointer updates */ +\ char branch; /* is it a branch (SET_IP) */ +\ char state_in; /* state on entry */ +\ char state_out; /* state on exit */ +\ short offset; /* offset into super2 table */ +\ char length; /* number of components */ \ }; \ How do you know which primitive or combined instruction this @@ -1528,11 +1656,11 @@ variable reprocessed-num 0 reprocessed-n loop ; : output-num-part ( p -- ) - ." N_" prim-c-name 2@ type ." ," ; + ." N_" prim-c-name-orig 2@ type ." ," ; \ prim-num @ 4 .r ." ," ; : output-name-comment ( -- ) - ." /* " prim prim-name 2@ type ." */" ; + ." /* " prim prim-name 2@ prim-type ." */" ; variable offset-super2 0 offset-super2 ! \ offset into the super2 table @@ -1541,7 +1669,9 @@ variable offset-super2 0 offset-super2 rot 2 .r ." ," swap 2 .r ." ," 2 .r ." , " prim prim-branch? negate . ." ," state-in state-number @ 2 .r ." ," - state-out state-number @ 2 .r ." ," ; + state-out state-number @ 2 .r ." ," + inst-stream stack-in @ 1 .r ." ," +; : output-costs-gforth-simple ( -- ) output-costs-prefix @@ -1557,22 +1687,25 @@ variable offset-super2 0 offset-super2 output-name-comment cr ; -: output-costs ( -- ) - \ description of superinstructions and simple instructions - ." {" prim compute-costs - rot 2 .r ." ," swap 2 .r ." ," 2 .r ." ," - offset-super2 @ 5 .r ." ," - super2-length dup 2 .r ." }," offset-super2 +! - output-name-comment - cr ; +\ : output-costs ( -- ) +\ \ description of superinstructions and simple instructions +\ ." {" prim compute-costs +\ rot 2 .r ." ," swap 2 .r ." ," 2 .r ." ," +\ offset-super2 @ 5 .r ." ," +\ super2-length dup 2 .r ." ," offset-super2 +! +\ inst-stream stack-in @ 1 .r ." }," +\ output-name-comment +\ cr ; -: output-super2 ( -- ) - \ table of superinstructions without requirement for existing prefixes - combined if - ['] output-num-part map-combined - else +: output-super2-simple ( -- ) + prim prim-c-name 2@ prim prim-c-name-orig 2@ d= if prim output-num-part - endif + output-name-comment + cr + endif ; + +: output-super2-combined ( -- ) + ['] output-num-part map-combined output-name-comment cr ; @@ -1667,7 +1800,7 @@ nl-char singleton eof-char over add-memb (( letter (( letter || digit )) ** )) <- c-ident ( -- ) -(( ` # ?? (( letter || digit || ` : )) ++ +(( ` # ?? (( letter || digit || ` : )) ++ (( ` . ` . ` . )) ?? )) <- stack-ident ( -- ) (( nowhitebq nowhite ** )) @@ -1722,18 +1855,18 @@ Variable c-flag (( ` \ comment-body nleof )) <- comment ( -- ) -(( {{ start }} stack-ident {{ end 2 pick init-item item% %size + }} white ** )) ** -<- stack-items +(( {{ start }} stack-ident {{ end init-item1 }} white ** )) ** +<- stack-items ( addr1 -- addr2 ) (( {{ prim prim-effect-in }} stack-items {{ prim prim-effect-in-end ! }} ` - ` - white ** {{ prim prim-effect-out }} stack-items {{ prim prim-effect-out-end ! }} )) <- stack-effect ( -- ) -(( {{ prim create-prim }} +(( {{ prim create-prim prim init-simple }} ` ( white ** {{ start }} stack-effect {{ end prim prim-stack-string 2! }} ` ) white ** (( {{ start }} forth-ident {{ end prim prim-wordset 2! }} white ** - (( {{ start }} c-ident {{ end prim prim-c-name 2! }} )) ?? + (( {{ start }} c-ident {{ end 2dup prim-c-name-2! }} )) ?? )) ?? nleof (( ` " ` " {{ start }} (( noquote ++ ` " )) ++ {{ end 1- prim prim-doc 2! }} ` " white ** nleof )) ?? {{ skipsynclines off line @ c-line ! filename 2@ c-filename 2! start }} @@ -1755,8 +1888,8 @@ Variable c-flag line @ name-line ! filename 2@ name-filename 2! function-number @ prim prim-num ! start }} [ifdef] vmgen c-ident [else] forth-ident [then] {{ end - 2dup prim prim-name 2! prim prim-c-name 2! }} white ** - (( ` / white ** {{ start }} c-ident {{ end prim prim-c-name 2! }} white ** )) ?? + 2dup prim prim-name 2! prim-c-name-2! }} white ** + (( ` / white ** {{ start }} c-ident {{ end prim-c-name-2! }} white ** )) ?? (( simple-primitive || combined-primitive )) {{ 1 function-number +! }} )) <- primitive ( -- )