| \ converts primitives to, e.g., C code |
\ converts primitives to, e.g., C code |
| |
|
| \ Copyright (C) 1995,1996,1997,1998,2000 Free Software Foundation, Inc. |
\ Copyright (C) 1995,1996,1997,1998,2000,2003 Free Software Foundation, Inc. |
| |
|
| \ This file is part of Gforth. |
\ This file is part of Gforth. |
| |
|
| \ (stack-in-index-xt and a test for stack==instruction-stream); there |
\ (stack-in-index-xt and a test for stack==instruction-stream); there |
| \ should be only one. |
\ should be only one. |
| |
|
| |
\ for backwards compatibility, jaw |
| |
require compat/strcomp.fs |
| |
|
| warnings off |
warnings off |
| |
|
| |
\ redefinitions of kernel words not present in gforth-0.6.1 |
| |
: latestxt lastcfa @ ; |
| |
: latest last @ ; |
| |
|
| [IFUNDEF] try |
[IFUNDEF] try |
| include startup.fs |
include startup.fs |
| [THEN] |
[THEN] |
| \ warnings on |
\ warnings on |
| |
|
| include ./gray.fs |
include ./gray.fs |
| 32 constant max-effect \ number of things on one side of a stack effect |
128 constant max-effect \ number of things on one side of a stack effect |
| 4 constant max-stacks \ the max. number of stacks (including inst-stream). |
4 constant max-stacks \ the max. number of stacks (including inst-stream). |
| 255 constant maxchar |
255 constant maxchar |
| maxchar 1+ constant eof-char |
maxchar 1+ constant eof-char |
| cell% 2* field stack-pointer \ stackpointer name |
cell% 2* field stack-pointer \ stackpointer name |
| cell% field stack-type \ name for default type of stack items |
cell% field stack-type \ name for default type of stack items |
| cell% field stack-in-index-xt \ ( in-size item -- in-index ) |
cell% field stack-in-index-xt \ ( in-size item -- in-index ) |
| |
cell% field stack-access-transform \ ( nitem -- index ) |
| end-struct stack% |
end-struct stack% |
| |
|
| struct% |
struct% |
| 1 next-stack-number +! |
1 next-stack-number +! |
| r@ stack-type ! |
r@ stack-type ! |
| save-mem r@ stack-pointer 2! |
save-mem r@ stack-pointer 2! |
| ['] stack-in-index r> stack-in-index-xt ! ; |
['] stack-in-index r@ stack-in-index-xt ! |
| |
['] noop r@ stack-access-transform ! |
| |
rdrop ; |
| |
|
| : map-stacks { xt -- } |
: map-stacks { xt -- } |
| \ perform xt for all stacks |
\ perform xt for all stacks |
| 2variable name-filename |
2variable name-filename |
| 2variable last-name-filename |
2variable last-name-filename |
| Variable function-number 0 function-number ! |
Variable function-number 0 function-number ! |
| |
Variable function-old 0 function-old ! |
| |
: function-diff ( n -- ) |
| |
." GROUPADD(" function-number @ function-old @ - 0 .r ." )" cr |
| |
function-number @ function-old ! ; |
| |
: forth-fdiff ( -- ) |
| |
function-number @ function-old @ - 0 .r ." groupadd" cr |
| |
function-number @ function-old ! ; |
| |
|
| \ a few more set ops |
\ a few more set ops |
| |
|
| |
|
| \ stack access stuff |
\ stack access stuff |
| |
|
| : normal-stack-access1 ( n stack -- ) |
: normal-stack-access0 { n stack -- } |
| stack-pointer 2@ type |
n stack stack-access-transform @ execute ." [" 0 .r ." ]" ; |
| dup |
|
| if |
: normal-stack-access1 { n stack -- } |
| ." [" 0 .r ." ]" |
stack stack-pointer 2@ type |
| |
n if |
| |
n stack normal-stack-access0 |
| else |
else |
| drop ." TOS" |
." TOS" |
| endif ; |
endif ; |
| |
|
| : normal-stack-access ( n stack -- ) |
: normal-stack-access ( n stack -- ) |
| get-current type-names set-current |
get-current type-names set-current |
| stack-type 2dup nextname stack-type-name |
stack-type 2dup nextname stack-type-name |
| set-current |
set-current |
| stack-pointer lastxt >body stack-name nextname make-stack ; |
stack-pointer latestxt >body stack-name nextname make-stack ; |
| |
|
| stack inst-stream IP Cell |
stack inst-stream IP Cell |
| ' inst-in-index inst-stream stack-in-index-xt ! |
' inst-in-index inst-stream stack-in-index-xt ! |
| : compute-offset-out ( addr1 addr2 -- ) |
: compute-offset-out ( addr1 addr2 -- ) |
| ['] stack-out compute-offset ; |
['] stack-out compute-offset ; |
| |
|
| : clear-stack ( stack -- ) |
|
| dup stack-in off stack-out off ; |
|
| |
|
| : compute-offsets ( -- ) |
: compute-offsets ( -- ) |
| ['] clear-stack map-stacks |
prim prim-stacks-in max-stacks cells erase |
| |
prim prim-stacks-out max-stacks cells erase |
| prim prim-effect-in prim prim-effect-in-end @ ['] compute-offset-in map-items |
prim prim-effect-in prim prim-effect-in-end @ ['] compute-offset-in map-items |
| prim prim-effect-out prim prim-effect-out-end @ ['] compute-offset-out map-items |
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 ; |
inst-stream stack-out @ 0= s" # can only be on the input side" ?print-error ; |
| stack stack-out @ 0<> stack stack-in @ 0= and |
stack stack-out @ 0<> stack stack-in @ 0= and |
| if |
if |
| ." IF_" stack stack-pointer 2@ 2dup type ." TOS(" |
." IF_" stack stack-pointer 2@ 2dup type ." TOS(" |
| 2dup type ." [0] = " type ." TOS);" cr |
2dup type 0 stack normal-stack-access0 ." = " type ." TOS);" cr |
| endif ; |
endif ; |
| |
|
| : flush-tos ( -- ) |
: flush-tos ( -- ) |
| stack stack-out @ 0= stack stack-in @ 0<> and |
stack stack-out @ 0= stack stack-in @ 0<> and |
| if |
if |
| ." IF_" stack stack-pointer 2@ 2dup type ." TOS(" |
." IF_" stack stack-pointer 2@ 2dup type ." TOS(" |
| 2dup type ." TOS = " type ." [0]);" cr |
2dup type ." TOS = " type 0 stack normal-stack-access0 ." );" cr |
| endif ; |
endif ; |
| |
|
| : fill-tos ( -- ) |
: fill-tos ( -- ) |
| : fetches ( -- ) |
: fetches ( -- ) |
| prim prim-effect-in prim prim-effect-in-end @ ['] fetch map-items ; |
prim prim-effect-in prim prim-effect-in-end @ ['] fetch map-items ; |
| |
|
| |
: stack-update-transform ( n1 stack -- n2 ) |
| |
\ n2 is the number by which the stack pointer should be |
| |
\ incremented to pop n1 items |
| |
stack-access-transform @ dup >r execute |
| |
0 r> execute - ; |
| |
|
| : stack-pointer-update { stack -- } |
: stack-pointer-update { stack -- } |
| \ stacks grow downwards |
\ stacks grow downwards |
| stack stack-diff |
stack stack-diff |
| stack inst-stream = if |
stack inst-stream = if |
| ." INC_IP(" 0 .r ." );" cr |
." INC_IP(" 0 .r ." );" cr |
| else |
else |
| stack stack-pointer 2@ type ." += " 0 .r ." ;" cr |
stack stack-pointer 2@ type ." += " |
| |
stack stack-update-transform 0 .r ." ;" cr |
| endif |
endif |
| endif ; |
endif ; |
| |
|
| endif |
endif |
| 2drop ; |
2drop ; |
| |
|
| |
: output-nextp2 ( -- ) |
| |
." NEXT_P2;" cr ; |
| |
|
| |
variable tail-nextp2 \ xt to execute for printing NEXT_P2 in INST_TAIL |
| |
' output-nextp2 tail-nextp2 ! |
| |
|
| : output-label2 ( -- ) |
: output-label2 ( -- ) |
| ." LABEL2(" prim prim-c-name 2@ type ." )" cr |
." LABEL2(" prim prim-c-name 2@ type ." )" cr |
| ." NEXT_P2;" cr ; |
." NEXT_P2;" cr ; |
| xt execute ; |
xt execute ; |
| |
|
| : output-c-tail ( -- ) |
: output-c-tail ( -- ) |
| ['] noop output-c-tail1 ; |
tail-nextp2 @ output-c-tail1 ; |
| |
|
| : output-c-tail2 ( -- ) |
: output-c-tail2 ( -- ) |
| ['] output-label2 output-c-tail1 ; |
['] output-label2 output-c-tail1 ; |
| |
|
| : output-c-tail-no-stores ( -- ) |
: output-c-tail-no-stores ( -- ) |
| ['] noop output-c-tail1-no-stores ; |
tail-nextp2 @ output-c-tail1-no-stores ; |
| |
|
| : output-c-tail2-no-stores ( -- ) |
: output-c-tail2-no-stores ( -- ) |
| ['] output-label2 output-c-tail1-no-stores ; |
['] output-label2 output-c-tail1-no-stores ; |
| ( primitive-number @ . ." alias " ) ." Primitive " prim prim-name 2@ type cr ; |
( primitive-number @ . ." alias " ) ." Primitive " prim prim-name 2@ type cr ; |
| |
|
| : output-c-prim-num ( -- ) |
: output-c-prim-num ( -- ) |
| ." #define N_" prim prim-c-name 2@ type prim prim-num @ 8 + 4 .r cr ; |
." N_" prim prim-c-name 2@ type ." ," cr ; |
| |
|
| : output-forth ( -- ) |
: output-forth ( -- ) |
| prim prim-forth-code @ 0= |
prim prim-forth-code @ 0= |
| : print-item { n stack -- } |
: print-item { n stack -- } |
| \ print nth stack item name |
\ print nth stack item name |
| stack stack-type @ type-c-name 2@ type space |
stack stack-type @ type-c-name 2@ type space |
| ." _" stack stack-pointer 2@ type n 0 .r ; |
." MAYBE_UNUSED _" stack stack-pointer 2@ type n 0 .r ; |
| |
|
| : print-declarations-combined ( -- ) |
: print-declarations-combined ( -- ) |
| max-stacks 0 ?do |
max-stacks 0 ?do |
| \ int loads; /* number of stack loads */ |
\ int loads; /* number of stack loads */ |
| \ int stores; /* number of stack stores */ |
\ int stores; /* number of stack stores */ |
| \ int updates; /* number of stack pointer updates */ |
\ int updates; /* number of stack pointer updates */ |
| |
\ int offset; /* offset into super2 table */ |
| \ int length; /* number of components */ |
\ int length; /* number of components */ |
| \ int *components; /* array of vm_prim indexes of components */ |
|
| \ }; |
\ }; |
| |
|
| \ How do you know which primitive or combined instruction this |
\ How do you know which primitive or combined instruction this |
| \ structure refers to? By the order of cost structures, as in most |
\ structure refers to? By the order of cost structures, as in most |
| \ other cases. |
\ other cases. |
| |
|
| |
: super2-length ( -- n ) |
| |
combined if |
| |
num-combined @ |
| |
else |
| |
1 |
| |
endif ; |
| |
|
| : compute-costs { p -- nloads nstores nupdates } |
: compute-costs { p -- nloads nstores nupdates } |
| \ compute the number of loads, stores, and stack pointer updates |
\ compute the number of loads, stores, and stack pointer updates |
| \ of a primitive or combined instruction; does not take TOS |
\ of a primitive or combined instruction; does not take TOS |
| \ caching into account, nor that IP updates are combined with |
\ caching into account |
| \ other stuff |
|
| 0 max-stacks 0 +do |
0 max-stacks 0 +do |
| p prim-stacks-in i th @ + |
p prim-stacks-in i th @ + |
| loop |
loop |
| |
super2-length 1- - \ don't count instruction fetches of subsumed insts |
| 0 max-stacks 0 +do |
0 max-stacks 0 +do |
| p prim-stacks-out i th @ + |
p prim-stacks-out i th @ + |
| loop |
loop |
| 0 max-stacks 0 +do |
0 max-stacks 1 +do \ don't count ip updates, therefore "1 +do" |
| p prim-stacks-in i th @ p prim-stacks-out i th @ <> - |
p prim-stacks-in i th @ p prim-stacks-out i th @ <> - |
| loop ; |
loop ; |
| |
|
| : output-num-part ( p -- ) |
: output-num-part ( p -- ) |
| prim-num @ 4 .r ." ," ; |
." N_" prim-c-name 2@ type ." ," ; |
| |
\ prim-num @ 4 .r ." ," ; |
| |
|
| |
: output-name-comment ( -- ) |
| |
." /* " prim prim-name 2@ type ." */" ; |
| |
|
| |
variable offset-super2 0 offset-super2 ! \ offset into the super2 table |
| |
|
| |
: output-costs-gforth-simple ( -- ) |
| |
." {" prim compute-costs |
| |
rot 2 .r ." ," swap 2 .r ." ," 2 .r ." , " |
| |
prim output-num-part |
| |
1 2 .r ." }," |
| |
output-name-comment |
| |
cr ; |
| |
|
| |
: output-costs-gforth-combined ( -- ) |
| |
." {" prim compute-costs |
| |
rot 2 .r ." ," swap 2 .r ." ," 2 .r ." , " |
| |
." N_START_SUPER+" offset-super2 @ 5 .r ." ," |
| |
super2-length dup 2 .r ." }," offset-super2 +! |
| |
output-name-comment |
| |
cr ; |
| |
|
| : output-costs ( -- ) |
: output-costs ( -- ) |
| |
\ description of superinstructions and simple instructions |
| ." {" prim compute-costs |
." {" prim compute-costs |
| rot 2 .r ." ," swap 2 .r ." ," 2 .r ." ," |
rot 2 .r ." ," swap 2 .r ." ," 2 .r ." ," |
| |
offset-super2 @ 5 .r ." ," |
| |
super2-length dup 2 .r ." }," offset-super2 +! |
| |
output-name-comment |
| |
cr ; |
| |
|
| |
: output-super2 ( -- ) |
| |
\ table of superinstructions without requirement for existing prefixes |
| combined if |
combined if |
| num-combined @ 2 .r |
['] output-num-part map-combined |
| ." , ((int []){" ['] output-num-part map-combined ." })}, /* " |
|
| else |
else |
| ." 1, ((int []){" prim prim-num @ 4 .r ." })}, /* " |
prim output-num-part |
| endif |
endif |
| prim prim-name 2@ type ." */" |
output-name-comment |
| cr ; |
cr ; |
| |
|
| \ the parser |
\ the parser |
| getinput member? ; |
getinput member? ; |
| ' testchar? test-vector ! |
' testchar? test-vector ! |
| |
|
| : checksyncline ( -- ) |
: checksynclines ( -- ) |
| \ when input points to a newline, check if the next line is a |
\ when input points to a newline, check if the next line is a |
| \ sync line. If it is, perform the appropriate actions. |
\ sync line. If it is, perform the appropriate actions. |
| rawinput @ >r |
rawinput @ begin >r |
| s" #line " r@ over compare if |
s" #line " r@ over compare if |
| rdrop 1 line +! EXIT |
rdrop 1 line +! EXIT |
| endif |
endif |
| endif |
endif |
| dup c@ nl-char <> 0= s" sync line syntax" ?print-error |
dup c@ nl-char <> 0= s" sync line syntax" ?print-error |
| skipsynclines @ if |
skipsynclines @ if |
| dup char+ rawinput ! |
char+ dup rawinput ! |
| rawinput @ c@ cookedinput @ c! |
rawinput @ c@ cookedinput @ c! |
| endif |
endif |
| drop ; |
again ; |
| |
|
| : ?nextchar ( f -- ) |
: ?nextchar ( f -- ) |
| s" syntax error, wrong char" ?print-error |
s" syntax error, wrong char" ?print-error |
| 1 chars rawinput +! |
1 chars rawinput +! |
| 1 chars cookedinput +! |
1 chars cookedinput +! |
| nl-char = if |
nl-char = if |
| checksyncline |
checksynclines |
| rawinput @ line-start ! |
rawinput @ line-start ! |
| endif |
endif |
| rawinput @ c@ cookedinput @ c! |
rawinput @ c@ |
| |
cookedinput @ c! |
| endif ; |
endif ; |
| |
|
| : charclass ( set "name" -- ) |
: charclass ( set "name" -- ) |
| )) <- c-comment ( -- ) |
)) <- c-comment ( -- ) |
| |
|
| (( ` - nonl ** {{ |
(( ` - nonl ** {{ |
| forth-flag @ IF ." [ELSE]" cr THEN |
forth-flag @ IF forth-fdiff ." [ELSE]" cr THEN |
| c-flag @ IF ." #else" cr THEN }} |
c-flag @ IF |
| |
function-diff |
| |
." #else /* " function-number @ 0 .r ." */" cr THEN }} |
| )) <- else-comment |
)) <- else-comment |
| |
|
| (( ` + {{ start }} nonl ** {{ end |
(( ` + {{ start }} nonl ** {{ end |
| dup |
dup |
| IF c-flag @ |
IF c-flag @ |
| IF ." #ifdef HAS_" bounds ?DO I c@ toupper emit LOOP cr |
IF |
| |
function-diff |
| |
." #ifdef HAS_" bounds ?DO I c@ toupper emit LOOP cr |
| THEN |
THEN |
| forth-flag @ |
forth-flag @ |
| IF ." has? " type ." [IF]" cr THEN |
IF forth-fdiff ." has? " type ." [IF]" cr THEN |
| ELSE 2drop |
ELSE 2drop |
| c-flag @ IF ." #endif" cr THEN |
c-flag @ IF |
| forth-flag @ IF ." [THEN]" cr THEN |
function-diff ." #endif" cr THEN |
| |
forth-flag @ IF forth-fdiff ." [THEN]" cr THEN |
| THEN }} |
THEN }} |
| )) <- if-comment |
)) <- if-comment |
| |
|
| (( (( ` g || ` G )) {{ start }} nonl ** |
(( (( ` g || ` G )) {{ start }} nonl ** |
| {{ end |
{{ end |
| forth-flag @ IF ." group " type cr THEN |
forth-flag @ IF forth-fdiff ." group " type cr THEN |
| c-flag @ IF ." GROUP(" type ." )" cr THEN }} |
c-flag @ IF function-diff |
| |
." GROUP(" type ." , " function-number @ 0 .r ." )" cr THEN }} |
| )) <- group-comment |
)) <- group-comment |
| |
|
| (( (( eval-comment || forth-comment || c-comment || else-comment || if-comment || group-comment )) ?? nonl ** )) <- comment-body |
(( (( eval-comment || forth-comment || c-comment || else-comment || if-comment || group-comment )) ?? nonl ** )) <- comment-body |
| start }} [ifdef] vmgen c-ident [else] forth-ident [then] {{ end |
start }} [ifdef] vmgen c-ident [else] forth-ident [then] {{ end |
| 2dup prim prim-name 2! prim prim-c-name 2! }} white ** |
2dup prim prim-name 2! prim prim-c-name 2! }} white ** |
| (( ` / white ** {{ start }} c-ident {{ end prim prim-c-name 2! }} white ** )) ?? |
(( ` / white ** {{ start }} c-ident {{ end prim prim-c-name 2! }} white ** )) ?? |
| (( simple-primitive || combined-primitive )) {{ 1 function-number +! }} |
(( simple-primitive || combined-primitive )) |
| |
{{ 1 function-number +! }} |
| )) <- primitive ( -- ) |
)) <- primitive ( -- ) |
| |
|
| (( (( comment || primitive || nl white ** )) ** eof )) |
(( (( comment || primitive || nl white ** )) ** eof )) |
| \ process the string at addr u |
\ process the string at addr u |
| over dup rawinput ! dup line-start ! cookedinput ! |
over dup rawinput ! dup line-start ! cookedinput ! |
| + endrawinput ! |
+ endrawinput ! |
| checksyncline |
checksynclines |
| primitives2something ; |
primitives2something ; |
| |
|
| |
: unixify ( c-addr u1 -- c-addr u2 ) |
| |
\ delete crs from the string |
| |
bounds tuck tuck ?do ( c-addr1 ) |
| |
i c@ dup #cr <> if |
| |
over c! char+ |
| |
else |
| |
drop |
| |
endif |
| |
loop |
| |
over - ; |
| |
|
| : process-file ( addr u xt-simple x-combined -- ) |
: process-file ( addr u xt-simple x-combined -- ) |
| output-combined ! output ! |
output-combined ! output ! |
| save-mem 2dup filename 2! |
save-mem 2dup filename 2! |
| slurp-file |
slurp-file unixify |
| warnings @ if |
warnings @ if |
| ." ------------ CUT HERE -------------" cr endif |
." ------------ CUT HERE -------------" cr endif |
| primfilter ; |
primfilter ; |