factor/library/bootstrap/image.factor

379 lines
9.4 KiB
Factor
Raw Normal View History

! :folding=none:collapseFolds=1:
2004-07-16 02:26:21 -04:00
! $Id$
!
! Copyright (C) 2004 Slava Pestov.
!
! Redistribution and use in source and binary forms, with or without
! modification, are permitted provided that the following conditions are met:
!
! 1. Redistributions of source code must retain the above copyright notice,
! this list of conditions and the following disclaimer.
!
! 2. Redistributions in binary form must reproduce the above copyright notice,
! this list of conditions and the following disclaimer in the documentation
! and/or other materials provided with the distribution.
!
! THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
! INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
! FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
! DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
! SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
! PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
! OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
! WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2004-10-27 23:13:00 -04:00
! This library allows one to generate a new set of bootstrap
! images (boot.image.{le32,le64,be32,be64}.
!
! It does this by parsing the set of source files needed to
! generate the minimal image, and writing the cons cells, words,
! strings etc to the image file in the CFactor object memory
! format.
!
! What is a bootstrap image? It basically contains enough code
! to parse a source file. See platform/native/boot.factor --
! It initializes the core interpreter services, and proceeds to
! run platform/native/boot-stage2.factor.
2004-09-11 15:26:24 -04:00
IN: image
2004-07-16 02:26:21 -04:00
USE: errors
USE: hashtables
USE: kernel
2004-12-10 21:39:27 -05:00
USE: kernel-internals
2004-07-16 02:26:21 -04:00
USE: lists
2004-08-26 22:21:17 -04:00
USE: math
2004-07-16 02:26:21 -04:00
USE: namespaces
USE: prettyprint
2004-08-29 04:03:16 -04:00
USE: random
2004-07-16 02:26:21 -04:00
USE: stdio
USE: streams
USE: strings
USE: test
USE: vectors
USE: unparser
USE: words
USE: stack
USE: combinators
USE: logic
2004-11-26 22:23:57 -05:00
! The image being constructed; a vector of word-size integers
SYMBOL: image
! Boot quotation, set by boot.factor
SYMBOL: boot-quot
2004-08-06 02:51:32 -04:00
2004-11-26 22:23:57 -05:00
: emit ( cell -- ) image get vector-push ;
: fixup ( value offset -- ) image get set-vector-nth ;
2004-07-16 02:26:21 -04:00
2004-07-24 15:11:55 -04:00
( Object memory )
2004-07-16 02:26:21 -04:00
: image-magic HEX: 0f0e0d0c ;
: image-version 0 ;
: cell "64-bits" get 8 4 ? ;
: char "64-bits" get 4 2 ? ;
2004-07-16 02:26:21 -04:00
2004-12-10 21:39:27 -05:00
: tag-mask BIN: 111 ; inline
: tag-bits 3 ; inline
2004-07-16 02:26:21 -04:00
: untag ( cell tag -- ) tag-mask bitnot bitand ;
: tag ( cell -- tag ) tag-mask bitand ;
2004-08-26 19:37:22 -04:00
: immediate ( x tag -- tagged ) swap tag-bits shift bitor ;
2004-07-16 02:26:21 -04:00
: >header ( id -- tagged ) header-tag immediate ;
2004-07-24 15:11:55 -04:00
( Image header )
2004-07-16 02:26:21 -04:00
2004-09-08 02:31:03 -04:00
: base
#! We relocate the image to after the header, and leaving
#! two empty cells. This lets us differentiate an F pointer
#! (0/tag 3) from a pointer to the first object in the
#! image.
2 cell * ;
2004-07-16 02:26:21 -04:00
: header ( -- )
image-magic emit
image-version emit
2004-09-08 02:31:03 -04:00
( relocation base at end of header ) base emit
2004-07-16 02:26:21 -04:00
( bootstrap quotation set later ) 0 emit
( global namespace set later ) 0 emit
( size of heap set later ) 0 emit ;
: boot-quot-offset 3 ;
: global-offset 4 ;
: heap-size-offset 5 ;
: header-size 6 ;
2004-09-08 02:31:03 -04:00
( Allocator )
: here ( -- size )
2004-11-26 22:23:57 -05:00
image get vector-length header-size - cell * base + ;
2004-09-08 02:31:03 -04:00
: here-as ( tag -- pointer )
here swap bitor ;
2004-07-16 02:26:21 -04:00
2004-09-08 02:31:03 -04:00
: pad ( -- )
here 8 mod 4 = [ 0 emit ] when ;
2004-07-16 02:26:21 -04:00
2004-07-24 15:11:55 -04:00
( Remember what objects we've compiled )
2004-07-16 02:26:21 -04:00
: pooled-object ( object -- pointer )
"objects" get hash ;
: pool-object ( object pointer -- )
swap "objects" get set-hash ;
2004-07-24 15:11:55 -04:00
( Fixnums )
2004-07-16 02:26:21 -04:00
: emit-fixnum ( n -- tagged ) fixnum-tag immediate ;
2004-07-16 02:26:21 -04:00
2004-08-06 02:51:32 -04:00
( Bignums )
: emit-bignum ( bignum -- tagged )
2004-08-29 01:04:42 -04:00
object-tag here-as >r
bignum-type >header emit
dup 0 = 1 2 ? emit ( capacity )
[
[ 0 = ] [ emit pad ]
[ 0 < ] [ 1 emit neg emit ]
[ 0 > ] [ 0 emit emit ]
] cond r> ;
2004-08-06 02:51:32 -04:00
2004-07-24 15:11:55 -04:00
( Special objects )
2004-07-16 02:26:21 -04:00
! Padded with fixnums for 8-byte alignment
2004-09-08 02:31:03 -04:00
: t,
object-tag here-as "t" set
t-type >header emit
0 emit-fixnum emit ;
2004-07-16 02:26:21 -04:00
: 0, 0 emit-bignum drop ;
: 1, 1 emit-bignum drop ;
: -1, -1 emit-bignum drop ;
2004-08-29 01:04:42 -04:00
2004-07-24 15:11:55 -04:00
( Beginning of the image )
2004-09-08 02:31:03 -04:00
! The image proper begins with the header, then T,
2004-08-29 01:04:42 -04:00
! and the bignums 0, 1, and -1.
2004-07-16 02:26:21 -04:00
2004-09-08 02:31:03 -04:00
: begin ( -- ) header t, 0, 1, -1, ;
2004-07-16 02:26:21 -04:00
2004-07-24 15:11:55 -04:00
( Words )
2004-07-16 02:26:21 -04:00
2004-11-28 21:56:58 -05:00
: word, ( word -- pointer )
word-tag here-as >r word-tag >header emit
hashcode emit ( hashcode )
0 emit r> ;
2004-07-16 02:26:21 -04:00
! This is to handle mutually recursive words
2004-09-30 21:49:49 -04:00
: fixup-word ( word -- offset )
2004-07-16 02:26:21 -04:00
dup pooled-object dup [
2004-09-30 21:49:49 -04:00
nip
2004-07-16 02:26:21 -04:00
] [
drop
[
"Not in image: " ,
dup word-vocabulary ,
" " ,
word-name ,
] make-string throw
2004-07-16 02:26:21 -04:00
] ifte ;
: fixup-words ( -- )
2004-11-26 22:23:57 -05:00
image get [
2004-09-30 21:49:49 -04:00
dup word? [ fixup-word ] when
2004-11-26 22:23:57 -05:00
] vector-map image set ;
2004-07-16 02:26:21 -04:00
: emit-word ( word -- pointer )
2004-09-30 21:49:49 -04:00
dup pooled-object dup [ nip ] [ drop ] ifte ;
2004-07-16 02:26:21 -04:00
2004-07-24 15:11:55 -04:00
( Conses )
2004-07-16 02:26:21 -04:00
DEFER: '
: emit-cons ( c -- tagged )
uncons ' swap '
cons-tag here-as
-rot emit emit ;
2004-07-16 02:26:21 -04:00
2004-07-24 15:11:55 -04:00
( Strings )
2004-07-16 02:26:21 -04:00
2004-09-04 22:29:07 -04:00
: align-string ( n str -- )
tuck str-length - CHAR: \0 fill cat2 ;
2004-07-16 02:26:21 -04:00
: emit-chars ( str -- )
"big-endian" get [ str-reverse ] unless
0 swap [ swap 16 shift + ] str-each emit ;
2004-07-16 02:26:21 -04:00
: (pack-string) ( n list -- )
#! Emit bytes for a string, with n characters per word.
[
2dup str-length > [ dupd align-string ] when emit-chars
] each drop ;
2004-07-16 02:26:21 -04:00
: pack-string ( string -- )
char tuck swap split-n (pack-string) ;
2004-07-16 02:26:21 -04:00
: (emit-string) ( string -- )
2004-07-16 02:26:21 -04:00
object-tag here-as swap
2004-08-06 02:51:32 -04:00
string-type >header emit
2004-07-16 02:26:21 -04:00
dup str-length emit
2004-07-31 14:58:16 -04:00
dup hashcode emit
2004-07-16 02:26:21 -04:00
pack-string
pad ;
: emit-string ( string -- pointer )
2004-07-16 02:26:21 -04:00
#! We pool strings so that each string is only written once
#! to the image
dup pooled-object dup [
nip
] [
drop dup (emit-string) dup >r pool-object r>
2004-07-16 02:26:21 -04:00
] ifte ;
2004-07-24 15:11:55 -04:00
( Word definitions )
2004-07-16 02:26:21 -04:00
: (vocabulary) ( name -- vocab )
#! Vocabulary for target image.
dup "vocabularies" get hash dup [
nip
] [
drop >r namespace-buckets <hashtable> dup r>
"vocabularies" get set-hash
] ifte ;
: (word+) ( word -- )
#! Add the word to a vocabulary in the target image.
dup word-name over word-vocabulary
(vocabulary) set-hash ;
: emit-plist ( word -- plist )
[
dup word-name "name" swons ,
dup word-vocabulary "vocabulary" swons ,
"parsing" word-property [ t "parsing" swons , ] when
] make-list ' ;
2004-07-16 02:26:21 -04:00
: define, ( word primitive parameter -- )
#! Write a word definition to the image.
' >r >r dup (word+) dup emit-plist >r
2004-11-28 21:56:58 -05:00
dup word, pool-object
2004-07-16 02:26:21 -04:00
r> ( -- plist )
r> ( primitive -- ) emit
r> ( parameter -- ) emit
2004-07-27 23:29:37 -04:00
( plist -- ) emit
2004-08-29 03:20:19 -04:00
0 emit ( padding )
0 emit ;
2004-07-16 02:26:21 -04:00
2004-07-24 15:11:55 -04:00
( Arrays and vectors )
2004-07-16 02:26:21 -04:00
: emit-array ( list -- pointer )
2004-08-22 19:06:51 -04:00
[ ' ] map
object-tag here-as >r
2004-08-06 02:51:32 -04:00
array-type >header emit
2004-07-16 02:26:21 -04:00
dup length emit
( elements -- ) [ emit ] each
pad r> ;
: emit-vector ( vector -- pointer )
dup vector>list emit-array swap vector-length
2004-07-16 02:26:21 -04:00
object-tag here-as >r
2004-08-06 02:51:32 -04:00
vector-type >header emit
2004-07-16 02:26:21 -04:00
emit ( length )
emit ( array ptr )
pad r> ;
2004-07-24 15:11:55 -04:00
( Cross-compile a reference to an object )
2004-07-16 02:26:21 -04:00
: ' ( obj -- pointer )
[
[ fixnum? ] [ emit-fixnum ]
[ bignum? ] [ emit-bignum ]
[ word? ] [ emit-word ]
[ cons? ] [ emit-cons ]
[ string? ] [ emit-string ]
[ vector? ] [ emit-vector ]
[ t = ] [ drop "t" get ]
2004-09-08 02:31:03 -04:00
! f is #define F RETAG(0,OBJECT_TYPE)
[ f = ] [ drop object-tag ]
[ drop t ] [ "Cannot cross-compile: " swap cat2 throw ]
2004-07-16 02:26:21 -04:00
] cond ;
2004-07-24 15:11:55 -04:00
( End of the image )
2004-07-16 02:26:21 -04:00
2004-11-26 22:23:57 -05:00
: vocabularies, ( -- )
#! Produces code with stack effect ( -- vocabularies ).
#! This code sets up vocabulary hash tables.
\ <namespace> ,
[
"vocabularies" get [
uncons hash>alist , \ alist>hash , , \ set ,
] hash-each
] make-list ,
\ extend , ;
2004-07-16 02:26:21 -04:00
: global, ( -- )
2004-11-26 22:23:57 -05:00
#! Produces code with stack effect ( vocabularies -- ).
<namespace> ' global-offset fixup
"vocabularies" ,
\ global ,
\ set-hash , ;
: hash-quot ( -- quot )
#! Generate a quotation to generate vocabulary and global
#! namespace hashtables.
[ vocabularies, global, ] make-list ;
: boot, ( quot -- )
boot-quot get append ' boot-quot-offset fixup ;
2004-07-16 02:26:21 -04:00
2004-09-08 02:31:03 -04:00
: end ( -- )
2004-11-26 22:23:57 -05:00
hash-quot
boot,
2004-09-08 02:31:03 -04:00
fixup-words
here base - heap-size-offset fixup ;
2004-07-16 02:26:21 -04:00
2004-07-24 15:11:55 -04:00
( Image output )
2004-07-16 02:26:21 -04:00
2004-07-17 18:35:09 -04:00
: write-word ( word -- )
"64-bits" get [
"big-endian" get [
write-big-endian-64
] [
write-little-endian-64
] ifte
2004-07-17 18:35:09 -04:00
] [
"big-endian" get [
write-big-endian-32
] [
write-little-endian-32
] ifte
2004-07-17 18:35:09 -04:00
] ifte ;
2004-07-16 02:26:21 -04:00
: write-image ( image file -- )
2004-07-17 18:35:09 -04:00
<filebw> [ [ write-word ] vector-each ] with-stream ;
2004-07-16 02:26:21 -04:00
: with-minimal-image ( quot -- image )
[
2004-11-26 22:23:57 -05:00
300000 <vector> image set
2004-07-16 02:26:21 -04:00
521 <hashtable> "objects" set
namespace-buckets <hashtable> "vocabularies" set
2004-07-31 16:11:30 -04:00
! Note that this is a vector that we can side-effect,
! since ; ends up using this variable from nested
! parser namespaces.
1000 <vector> "word-fixups" set
call
2004-11-26 22:23:57 -05:00
image get
] with-scope ;
2004-07-16 02:26:21 -04:00
: with-image ( quot -- image )
[ begin call end ] with-minimal-image ;
2004-07-16 02:26:21 -04:00
: test-image ( quot -- ) with-image vector>list . ;