Diff for /gforth/cross.fs between versions 1.83 and 1.126

version 1.83, 1999/12/31 21:39:59 version 1.126, 2002/03/21 17:26:00
Line 1 Line 1
 \ CROSS.FS     The Cross-Compiler                      06oct92py  \ CROSS.FS     The Cross-Compiler                      06oct92py
 \ Idea and implementation: Bernd Paysan (py)  \ Idea and implementation: Bernd Paysan (py)
   
 \ Copyright (C) 1995,1996,1997,1998,1999 Free Software Foundation, Inc.  \ Copyright (C) 1995,1996,1997,1998,1999,2000 Free Software Foundation, Inc.
   
 \ This file is part of Gforth.  \ This file is part of Gforth.
   
Line 17 Line 17
   
 \ You should have received a copy of the GNU General Public License  \ You should have received a copy of the GNU General Public License
 \ along with this program; if not, write to the Free Software  \ along with this program; if not, write to the Free Software
 \ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  \ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
   
 0   0 
 [IF]  [IF]
   
 ToDo:  ToDo:
 Crossdoc destination ./doc/crossdoc.fd makes no sense when  - Crossdoc destination ./doc/crossdoc.fd makes no sense when
 cross.fs is uses seperately. jaw    cross.fs is used seperately. jaw
 Do we need this char translation with >address and in branchoffset?   - Do we need this char translation with >address and in branchoffset? 
 (>body also affected) jaw    (>body also affected) jaw
 Clean up mark> and >resolve stuff jaw  
   
 [THEN]  [THEN]
   
Line 62  forth definitions Line 61  forth definitions
 : T  previous Ghosts also Target ; immediate  : T  previous Ghosts also Target ; immediate
 : G  Ghosts ; immediate  : G  Ghosts ; immediate
   
   
 : >cross  also Cross definitions previous ;  : >cross  also Cross definitions previous ;
 : >target also Target definitions previous ;  : >target also Target definitions previous ;
 : >minimal also Minimal definitions previous ;  : >minimal also Minimal definitions previous ;
Line 70  H Line 70  H
   
 >CROSS  >CROSS
   
   \ Test against this definitions to find out whether we are cross-compiling
   \ may be usefull for assemblers
   0 Constant gforth-cross-indicator
   
 \ find out whether we are compiling with gforth  \ find out whether we are compiling with gforth
   
 : defined? bl word find nip ;  : defined? bl word find nip ;
Line 201  Create bases   10 ,   2 ,   A , 100 , Line 205  Create bases   10 ,   2 ,   A , 100 ,
   
 [THEN]  [THEN]
   
   \ this provides assert( and struct stuff
   \GFORTH [IFUNDEF] assert1(
   \GFORTH also forth definitions require assert.fs previous
   \GFORTH [THEN]
   
   >CROSS
   
 hex     \ the defualt base for the cross-compiler is hex !!  hex     \ the defualt base for the cross-compiler is hex !!
 \ Warnings off  \ Warnings off
   
Line 241  hex     \ the defualt base for the cross Line 252  hex     \ the defualt base for the cross
   
 hex  hex
   
   \ FIXME delete`
 \ 1 Constant Cross-Flag \ to check whether assembler compiler plug-ins are  \ 1 Constant Cross-Flag \ to check whether assembler compiler plug-ins are
                         \ for cross-compiling                          \ for cross-compiling
 \ No! we use "[IFUNDEF]" there to find out whether we are target compiling!!!  \ No! we use "[IFUNDEF]" there to find out whether we are target compiling!!!
   
   \ FIXME move down
 : comment? ( c-addr u -- c-addr u )  : comment? ( c-addr u -- c-addr u )
         2dup s" (" compare 0=          2dup s" (" compare 0=
         IF    postpone (          IF    postpone (
         ELSE  2dup s" \" compare 0= IF postpone \ THEN          ELSE  2dup s" \" compare 0= IF postpone \ THEN
         THEN ;          THEN ;
   
   : X ( -- <name> )
   \G The next word in the input is a target word.
   \G Equivalent to T <name> but without permanent
   \G switch to target dictionary. Used as prefix e.g. for @, !, here etc.
     bl word count [ ' target >wordlist ] Literal search-wordlist
     IF state @ IF compile, ELSE execute THEN
     ELSE  -1 ABORT" Cross: access method not supported!"
     THEN ; immediate
   
 \ Begin CROSS COMPILER:  \ Begin CROSS COMPILER:
   
 \ debugging  \ debugging
Line 296  set-order previous Line 318  set-order previous
         \ POSTPONE false           \ POSTPONE false 
   THEN ; immediate    THEN ; immediate
   
   : symentry ( adr len taddr -- )
   \G Produce a symbol table (an optional symbol address
   \G map) if wanted
       [ [IFDEF] fd-symbol-table ]
         base @ swap hex s>d <# 8 0 DO # LOOP #> fd-symbol-table write-file throw base !
         s" :" fd-symbol-table write-file throw
         fd-symbol-table write-line throw
       [ [ELSE] ]
         2drop drop
       [ [THEN] ] ;
   
   
 \ \ --------------------        source file  \ \ --------------------        source file
   
 decimal  decimal
Line 474  Create tfile 0 c, 255 chars allot Line 508  Create tfile 0 c, 255 chars allot
     THEN ;      THEN ;
   
 : compact.. ( adr len -- adr2 len2 )  : compact.. ( adr len -- adr2 len2 )
 \ deletes phrases like "xy/.." out of our directory name 2dec97jaw      \ deletes phrases like "xy/.." out of our directory name 2dec97jaw
   over >r -1 >r      over swap
   BEGIN dup WHILE      BEGIN  dup  WHILE
         over c@ pathsep?           dup >r '/ scan 2dup 4 min s" /../" compare 0=
         IF      r@ -1 =          IF
                 IF      r> drop dup >r              dup r> - >r 4 /string over r> + 4 -
                 ELSE    2dup 1 /string               swap 2dup + >r move dup r> over -
                         3 min s" ../" compare          ELSE
                         0=              rdrop dup 1 min /string
                         IF      r@ over - ( diff )          THEN
                                 2 pick swap - ( dest-adr )      REPEAT  drop over - ;
                                 >r 3 /string r> swap 2dup >r >r  
                                 move r> r>  
                         ELSE    r> drop dup >r  
                         THEN  
                 THEN  
         THEN  
         1 /string  
   REPEAT   
   r> drop   
   drop r> tuck - ;  
   
 : reworkdir ( -- )  : reworkdir ( -- )
   remove~+    remove~+
Line 638  stack-warn [IF] Line 662  stack-warn [IF]
 : defempty? ; immediate  : defempty? ; immediate
 [THEN]  [THEN]
   
 \ \ GhostNames Ghosts                                  9may93jaw  \ \ --------------------        Compiler Plug Ins               01aug97jaw
   
   >CROSS
   
 \ second name source to search trough list  \ Compiler States
   
 VARIABLE GhostNames  Variable comp-state
 0 GhostNames !  0 Constant interpreting
   1 Constant compiling
   2 Constant resolving
   3 Constant assembling
   
 : GhostName ( -- addr )  : compiling? comp-state @ compiling = ;
     align here GhostNames @ , GhostNames ! here 0 ,  
     bl word count  
     \ 2dup type space  
     string, \ !! cfalign ?  
     align ;  
   
 \ Ghost Builder                                        06oct92py  : pi-undefined -1 ABORT" Plugin undefined" ;
   
 \ <T T> new version with temp variable                 10may93jaw  : Plugin ( -- : pluginname )
     Create 
     \ for normal cross-compiling only one action
     \ exists, this fields are identical. For the instant
     \ simulation environment we need, two actions for each plugin
     \ the target one and the one that generates the simulation code
     ['] pi-undefined , \ action
     ['] pi-undefined , \ target plugin action
     8765 ,     \ plugin magic
     DOES> perform ;
   
   Plugin DummyPlugin
   
   : 'PI ( -- addr : pluginname )
     ' >body dup 2 cells + @ 8765 <> ABORT" not a plugin" ;
   
   : plugin-of ( xt -- : pluginname )
     dup 'PI 2! ;
   
   : action-of ( xt -- : plunginname )
     'PI cell+ ! ;
   
   : TPA ( -- : plugin )
   \ target plugin action
   \ executes current target action of plugin
     'PI cell+ POSTPONE literal POSTPONE perform ; immediate
   
   Variable ppi-temp 0 ppi-temp !
   
   : pa:
   \g define plugin action
     ppi-temp @ ABORT" pa: definition not closed"
     'PI ppi-temp ! :noname ;
   
   : ;pa
   \g end a definition for plugin action
     POSTPONE ; ppi-temp @ ! 0 ppi-temp ! ; immediate
   
   
   Plugin dlit, ( d -- )                   \ compile numerical value the target
   Plugin lit, ( n -- )
   Plugin alit, ( n -- )
   
   Plugin branch, ( target-addr -- )       \ compiles a branch
   Plugin ?branch, ( target-addr -- )      \ compiles a ?branch
   Plugin branchmark, ( -- branch-addr )   \ reserves room for a branch
   Plugin ?branchmark, ( -- branch-addr )  \ reserves room for a ?branch
   Plugin ?domark, ( -- branch-addr )      \ reserves room for a ?do branch
   Plugin branchto, ( -- )                 \ actual program position is target of a branch (do e.g. alignment)
   ' NOOP plugin-of branchto, 
   Plugin branchtoresolve, ( branch-addr -- ) \ resolves a forward reference from branchmark
   Plugin branchtomark, ( -- target-addr ) \ marks a branch destination
   
   Plugin colon, ( tcfa -- )               \ compiles call to tcfa at current position
   Plugin prim, ( tcfa -- )                \ compiles primitive invocation
   Plugin colonmark, ( -- addr )           \ marks a colon call
   Plugin colon-resolve ( tcfa addr -- )
   
   Plugin addr-resolve ( target-addr addr -- )
   Plugin doer-resolve ( ghost res-pnt target-addr addr -- ghost res-pnt )
   
   Plugin ncontrols? ( [ xn ... x1 ] n -- ) \ checks wheter n control structures are open
   Plugin if,      ( -- if-token )
   Plugin else,    ( if-token -- if-token )
   Plugin then,    ( if-token -- )
   Plugin ahead,
   Plugin begin,
   Plugin while,
   Plugin until,
   Plugin again,
   Plugin repeat,
   Plugin cs-swap  ( x1 x2 -- x2 x1 )
   
   Plugin case,    ( -- n )
   Plugin of,      ( n -- x1 n )
   Plugin endof,   ( x1 n -- x2 n )
   Plugin endcase, ( x1 .. xn n -- )
   
   Plugin do,      ( -- do-token )
   Plugin ?do,     ( -- ?do-token )
   Plugin for,     ( -- for-token )
   Plugin loop,    ( do-token / ?do-token -- )
   Plugin +loop,   ( do-token / ?do-token -- )
   Plugin next,    ( for-token )
   Plugin leave,   ( -- )
   Plugin ?leave,  ( -- )
   
   Plugin ca>native  \ Convert a code address to the processors
                     \ native address. This is used in doprim, and
                     \ code/code: primitive definitions word to
                     \ convert the addresses.
                     \ The only target where we need this is the misc
                     \ which is a 16 Bit processor with word addresses
                     \ but the forth system we build has a normal byte
                     \ addressed memory model    
   
   Plugin doprim,  \ compiles start of a primitive
   Plugin docol,           \ compiles start of a colon definition
   Plugin doer,            
   Plugin fini,      \ compiles end of definition ;s
   Plugin doeshandler,
   Plugin dodoes,
   
   Plugin colon-start
   ' noop plugin-of colon-start
   Plugin colon-end
   ' noop plugin-of colon-end
   
   Plugin ]comp     \ starts compilation
   ' noop plugin-of ]comp
   Plugin comp[     \ ends compilation
   ' noop plugin-of comp[
   
 VARIABLE VocTemp  Plugin t>body             \ we need the system >body
                           \ and the target >body
   
 : <T  get-current VocTemp ! also Ghosts definitions ;  >TARGET
 : T>  previous VocTemp @ set-current ;  : >body t>body ;
   
   
   \ Ghost Builder                                        06oct92py
   
   >CROSS
 hex  hex
   \ Values for ghost magic
 4711 Constant <fwd>             4712 Constant <res>  4711 Constant <fwd>             4712 Constant <res>
 4713 Constant <imm>             4714 Constant <do:>  4713 Constant <imm>             4714 Constant <do:>
 4715 Constant <skip>  4715 Constant <skip>
   
 \ iForth makes only immediate directly after create  \ Bitmask for ghost flags
 \ make atonce trick! ?  1 Constant <unique>
   2 Constant <primitive>
   
   \ FXIME: move this to general stuff?
   : set-flag ( addr flag -- )
     over @ or swap ! ;
   
   : reset-flag ( addr flag -- )
     invert over @ and swap ! ;
   
   : get-flag ( addr flag -- f )
     swap @ and 0<> ;
     
   
   Struct
   
     \ link to next ghost (always the first element)
     cell% field >next-ghost
   
 Variable atonce atonce off    \ type of ghost
     cell% field >magic
                   
     \ pointer where ghost is in target, or if unresolved
     \ points to the where we have to resolve (linked-list)
     cell% field >link
   
     \ execution semantics (while target compiling) of ghost
     cell% field >exec
   
     \ compilation action of this ghost; this is what is
     \ done to compile a call (or whatever) to this definition.
     \ E.g. >comp contains the semantic of postpone s"
     \ whereas >exec-compile contains the semantic of s"
     cell% field >comp
   
     \ Compilation sematics (while parsing) of this ghost. E.g. 
     \ "\" will skip the rest of line.
     \ These semantics are defined by Cond: and
     \ if a word is made immediate in instant, then the >exec2 field
     \ gets copied to here
     cell% field >exec-compile
   
     \ Additional execution semantics of this ghost. This is used
     \ for code generated by instant and for the doer-xt of created
     \ words
     cell% field >exec2
   
     cell% field >created
   
     \ the xt of the created ghost word itself
     cell% field >ghost-xt
   
     \ pointer to the counted string of the assiciated
     \ assembler label
     cell% field >asm-name
   
     \ mapped primitives have a special address, so
     \ we are able to detect them
     cell% field >asm-dummyaddr
                           
     \ for builder (create, variable...) words
     \ the execution symantics of words built are placed here
     \ this is a doer ghost or a dummy ghost
     cell% field >do:ghost
   
 : NoExec true ABORT" CROSS: Don't execute ghost, or immediate target word" ;    cell% field >ghost-flags
   
 : GhostHeader <fwd> , 0 , ['] NoExec , ;    cell% field >ghost-name
   
 : >magic ;              \ type of ghost  End-Struct ghost-struct
 : >link cell+ ;         \ pointer where ghost is in target, or if unresolved  
                         \ points to the where we have to resolve (linked-list)  Variable ghost-list
 : >exec cell+ cell+ ;   \ execution symantics (while target compiling) of ghost  0 ghost-list !
 : >end 3 cells + ;      \ room for additional tags  
                         \ for builder (create, variable...) words the  
                         \ execution symantics of words built are placed here  
   
 Variable executed-ghost \ last executed ghost, needed in tcreate and gdoes>  Variable executed-ghost \ last executed ghost, needed in tcreate and gdoes>
 Variable last-ghost     \ last ghost that is created  \ Variable last-ghost   \ last ghost that is created
 Variable last-header-ghost \ last ghost definitions with header  Variable last-header-ghost \ last ghost definitions with header
   
   \ space for ghosts resolve structure
   \ we create ghosts in a sepearte space
   \ and not to the current host dp, because this
   \ gives trouble with instant while compiling and creating
   \ a ghost for a forward reference
   \ BTW: we cannot allocate another memory region
   \ because allot will check the overflow!!
   Variable cross-space-dp
   Create cross-space 250000 allot here 100 allot align 
   Constant cross-space-end
   cross-space cross-space-dp !
   Variable cross-space-dp-orig
   
   : cross-space-used cross-space-dp @ cross-space - ;
   
   : >space ( -- )
     dp @ cross-space-dp-orig !
     cross-space-dp @ dp ! ;
   
   : space> ( -- )
     dp @ dup cross-space-dp !
     cross-space-end u> ABORT" CROSS: cross-space overflow"
     cross-space-dp-orig @ dp ! ;
   
   \ this is just for debugging, to see this in the backtrace
   : execute-exec execute ;
   : execute-exec2 execute ;
   : execute-exec-compile execute ;
   
   : NoExec
     executed-ghost @ >exec2 @
     ?dup 
     IF   execute-exec2
     ELSE true ABORT" CROSS: Don't execute ghost, or immediate target word"
     THEN ;
   
   Defer is-forward
   
   : (ghostheader) ( -- )
       ghost-list linked <fwd> , 0 , ['] NoExec , ['] is-forward ,
       0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , ;
   
   : ghostheader ( -- ) (ghostheader) 0 , ;
   
   ' Ghosts >wordlist Constant ghosts-wordlist
   
   \ the current wordlist for ghost definitions in the host
   ghosts-wordlist Value current-ghosts
   
 : Make-Ghost ( "name" -- ghost )  : Make-Ghost ( "name" -- ghost )
   >in @ GhostName swap >in !    >space
   <T Create atonce @ IF immediate atonce off THEN    \ save current and create in ghost vocabulary
   here tuck swap ! ghostheader T>    get-current >r current-ghosts set-current
   dup last-ghost !    >in @ Create >in !
   DOES> dup executed-ghost ! >exec @ execute ;    \ some forth systems like iForth need the immediate directly
     \ after the word is created
     \ restore current
     r> set-current
     here (ghostheader)
     bl word count string, align
     space>
     \ set ghost-xt field by doing a search
     dup >ghost-name count 
     current-ghosts search-wordlist
     0= ABORT" CROSS: Just created, must be there!"
     over >ghost-xt !
     DOES> 
         dup executed-ghost !
         >exec @ execute-exec ;
   
 \ ghost words                                          14oct92py  \ ghost words                                          14oct92py
 \                                          changed:    10may93py/jaw  \                                          changed:    10may93py/jaw
   
 : gfind   ( string -- ghost true/1 / string false )  Defer search-ghosts
   
   : (search-ghosts) ( adr len -- cfa true | 0 )
     current-ghosts search-wordlist ; 
   
     ' (search-ghosts) IS search-ghosts
   
   : gsearch ( addr len -- ghost true | 0 )
     search-ghosts
     dup IF swap >body swap THEN ;
   
   : gfind   ( string -- ghost true / string false )
 \ searches for string in word-list ghosts  \ searches for string in word-list ghosts
   dup count [ ' ghosts >wordlist ] Literal search-wordlist    \ dup count type space
   dup IF >r >body nip r>  THEN ;    dup >r count gsearch
     dup IF rdrop ELSE r> swap THEN ;
   
 : gdiscover ( xt -- ghost true | xt false )  : gdiscover ( xt -- ghost true | xt false )
   GhostNames    >r ghost-list
   BEGIN @ dup    BEGIN @ dup
   WHILE 2dup    WHILE dup >magic @ <fwd> <>
         cell+ @ dup >magic @ <fwd> <>          IF dup >link @ r@ =
         >r >link @ = r> and             IF rdrop true EXIT THEN
         IF cell+ @ nip true EXIT THEN          THEN
   REPEAT    REPEAT
   drop false ;    drop r> false ;
   
 VARIABLE Already  : xt>ghost ( xt -- ghost )
     gdiscover 0= ABORT" CROSS: ghost not found for this xt" ;
   
 : ghost   ( "name" -- ghost )  : Ghost   ( "name" -- ghost )
   Already off    >in @ bl word gfind IF  nip EXIT  THEN
   >in @  bl word gfind   IF  atonce off Already on nip EXIT  THEN  
   drop  >in !  Make-Ghost ;    drop  >in !  Make-Ghost ;
   
 : >ghostname ( ghost -- adr len )  : >ghostname ( ghost -- adr len )
   GhostNames    >ghost-name count ;
   BEGIN @ dup  
   WHILE 2dup cell+ @ =  
   UNTIL nip 2 cells + count  
   ELSE  2drop   
         \ true abort" CROSS: Ghostnames inconsistent"  
         s" ?!?!?!"  
   THEN ;  
   
 : .ghost ( ghost -- ) >ghostname type ;  
   
 \ ' >ghostname ALIAS @name  
   
 : forward? ( ghost -- flag )  : forward? ( ghost -- flag )
   >magic @ <fwd> = ;    >magic @ <fwd> = ;
Line 739  VARIABLE Already Line 1002  VARIABLE Already
 : undefined? ( ghost -- flag )  : undefined? ( ghost -- flag )
   >magic @ dup <fwd> = swap <skip> = or ;    >magic @ dup <fwd> = swap <skip> = or ;
   
   : immediate? ( ghost -- flag )
     >magic @ <imm> = ;
   
   Variable TWarnings
   TWarnings on
   Variable Exists-Warnings
   Exists-Warnings on
   
   : exists-warning ( ghost -- ghost )
     TWarnings @ Exists-Warnings @ and
     IF dup >ghostname warnhead type ."  exists " THEN ;
   
   \ : HeaderGhost Ghost ;
   
   Variable reuse-ghosts reuse-ghosts off
   
   : HeaderGhost ( "name" -- ghost )
     >in @ 
     bl word count 
   \  2dup type space
     current-ghosts search-wordlist
     IF  >body dup undefined? reuse-ghosts @ or
         IF   nip EXIT
         ELSE exists-warning 
         THEN
         drop >in ! 
     ELSE >in ! 
     THEN 
     \ we keep the execution semantics of the prviously
     \ defined words, this is a workaround
     \ for the redefined \ until vocs work
     Make-Ghost ;
    
   : .ghost ( ghost -- ) >ghostname type ;
   
   \ ' >ghostname ALIAS @name
   
   : findghost ( "ghostname" -- ghost ) 
     bl word gfind 0= ABORT" CROSS: Ghost don't exists" ;
   
   : [G'] ( -- ghost : name )
   \G ticks a ghost and returns its address
     findghost
     state @ IF postpone literal THEN ; immediate
   
   : g>xt ( ghost -- xt )
   \G Re