diff --git a/racket/src/cs/bootstrap/Makefile b/racket/src/cs/bootstrap/Makefile index 78f1bb23f9..f4c7d70557 100644 --- a/racket/src/cs/bootstrap/Makefile +++ b/racket/src/cs/bootstrap/Makefile @@ -1,6 +1,6 @@ RACKET=racket -SCHEME_DIR=../../build/ChezScheme +SCHEME_SRC=../../build/ChezScheme boot: - env SCHEME_DIR="$(SCHEME_DIR)" $(RACKET) make-boot.rkt + env SCHEME_SRC="$(SCHEME_SRC)" $(RACKET) make-boot.rkt diff --git a/racket/src/cs/bootstrap/README.txt b/racket/src/cs/bootstrap/README.txt index e939564a7d..235105857b 100644 --- a/racket/src/cs/bootstrap/README.txt +++ b/racket/src/cs/bootstrap/README.txt @@ -5,9 +5,9 @@ existing Racket build, but without using an existing Chez Scheme build.) The "make-boot.rkt" programs builds Chez Scheme ".boot" and ".h" files -from source. The output is written to "compiled", but copy the files -to "/boot/" in a Chez Scheme source directory before -`configure` to `make` to boostrap the build. +from source. The output is written to "/boot/" in a +Chez Scheme source directory. Build boot files that way before +`configure` and `make` to boostrap the build. The Chez Scheme simulation hasn't been made especially fast, so expect the bootstrap process to take 5-10 times as long as using an existing diff --git a/racket/src/cs/bootstrap/config.rkt b/racket/src/cs/bootstrap/config.rkt index fde88727f7..d479015174 100644 --- a/racket/src/cs/bootstrap/config.rkt +++ b/racket/src/cs/bootstrap/config.rkt @@ -2,15 +2,16 @@ (require ffi/unsafe/global) (provide scheme-dir - target-machine) + target-machine + optimize-level-init) (define ht (get-place-table)) (define scheme-dir (or (hash-ref ht 'make-boot-scheme-dir #f) (simplify-path (path->complete-path - (or (getenv "SCHEME_DIR") - (error "set `SCHEME_DIR` environment variable")))))) + (or (getenv "SCHEME_SRC") + (error "set `SCHEME_SRC` environment variable")))))) (hash-set! ht 'make-boot-scheme-dir scheme-dir) (define target-machine (or (hash-ref ht 'make-boot-targate-machine #f) @@ -26,3 +27,5 @@ (error "set `MACH` environment variable")]))) (hash-set! ht 'make-boot-targate-machine target-machine) + +(define optimize-level-init 3) diff --git a/racket/src/cs/bootstrap/constant.rkt b/racket/src/cs/bootstrap/constant.rkt index da4c814cbb..ee46fc5bde 100644 --- a/racket/src/cs/bootstrap/constant.rkt +++ b/racket/src/cs/bootstrap/constant.rkt @@ -44,7 +44,7 @@ (provide id ...) (define id (hash-ref ht 'id)) ...)) -(hash-set! ht 'ptr-bytes (* 8 (hash-ref ht 'ptr-bits))) +(hash-set! ht 'ptr-bytes (/ (hash-ref ht 'ptr-bits) 8)) (define-constant ptr-bytes @@ -58,4 +58,5 @@ prelex-sticky-mask prelex-is-mask) - +(provide record-ptr-offset) +(define record-ptr-offset 1) diff --git a/racket/src/cs/bootstrap/make-boot.rkt b/racket/src/cs/bootstrap/make-boot.rkt index 2c5fb5617b..5ad15555e2 100644 --- a/racket/src/cs/bootstrap/make-boot.rkt +++ b/racket/src/cs/bootstrap/make-boot.rkt @@ -2,7 +2,8 @@ (require racket/runtime-path racket/match racket/file - (only-in "r6rs-lang.rkt") + (only-in "r6rs-lang.rkt" + optimize-level) (only-in "scheme-lang.rkt" current-expand) (submod "scheme-lang.rkt" callback) @@ -12,24 +13,47 @@ "parse-makefile.rkt" "config.rkt") -;; Writes ".boot" and ".h" files to a "compiled" subdirectory of the -;; current directory. - -;; Set `SCHEME_DIR` and `MACH` to specify the ChezScheme source +;; Set `SCHEME_SRC` and `MACH` to specify the ChezScheme source ;; directory and the target machine. +;; Writes ".boot" and ".h" files to a "boot" subdirectory of +;; `SCHEME_SRC`. + +(define-runtime-path here-dir ".") +(define out-subdir (build-path scheme-dir "boot" target-machine)) (define nano-dir (build-path scheme-dir "nanopass")) +(define (status msg) + (printf "~a\n" msg) + (flush-output)) + +(define sources-date + (for/fold ([d 0]) ([dir (in-list (list here-dir + nano-dir + (build-path scheme-dir "s")))]) + (status (format "Use ~a" dir)) + (for/fold ([d d]) ([f (in-list (directory-list dir))] + #:when (regexp-match? #rx"[.](?:rkt|ss|sls)$" f)) + (max d (file-or-directory-modify-seconds (build-path dir f)))))) + +(status (format "Check ~a" out-subdir)) +(when (for/and ([f (in-list (list "scheme.h" + "equates.h" + "petite.boot" + "scheme.boot"))]) + (define d (file-or-directory-modify-seconds (build-path out-subdir f) #f (lambda () #f))) + (and d (d . >= . sources-date))) + (status "Up-to-date") + (exit)) + +;; ---------------------------------------- + (define-runtime-module-path r6rs-lang-mod "r6rs-lang.rkt") (define-runtime-module-path scheme-lang-mod "scheme-lang.rkt") (define-values (petite-sources scheme-sources) (get-sources-from-makefile scheme-dir)) -(define (status msg) - (printf "~a\n" msg) - (flush-output)) - (define ns (make-base-empty-namespace)) (namespace-attach-module (current-namespace) r6rs-lang-mod ns) (namespace-attach-module (current-namespace) scheme-lang-mod ns) @@ -110,7 +134,6 @@ (set-current-expand-set-callback! (lambda () (start-fully-unwrapping-syntax!) - (status "Load expander") (define $uncprep (orig-eval '$uncprep)) (current-eval (lambda (stx) @@ -260,11 +283,14 @@ (lambda (ty) (filter-foreign-type ty)))) + (make-directory* out-subdir) + (status "Load mkheader") (load-ss (build-path scheme-dir "s/mkheader.ss")) (status "Generate headers") - (eval `(mkscheme.h "compiled/scheme.h" ,target-machine)) - (eval `(mkequates.h "compiled/equates.h")) + (eval `(mkscheme.h ,(path->string (build-path out-subdir "scheme.h")) ,target-machine)) + (eval `(mkequates.h ,(path->string (build-path out-subdir "equates.h")))) + (plumber-flush-all (current-plumber)) (for ([s (in-list '("ftype.ss" "fasl.ss" @@ -281,14 +307,12 @@ (status (format "Load ~a" s)) (load-ss (build-path scheme-dir "s" s))) - (make-directory* "compiled") - (let ([failed? #f]) (for ([src (append petite-sources scheme-sources)]) - (let ([dest (path->string (path->complete-path (build-path "compiled" (path-replace-suffix src #".so"))))]) + (let ([dest (path->string (path->complete-path (build-path out-subdir (path-replace-suffix src #".so"))))]) (parameterize ([current-directory (build-path scheme-dir "s")]) ;; (status (format "Compile ~a" src)) - Chez Scheme prints its own message - (with-handlers ([exn:fail? (lambda (exn) + (with-handlers (#;[exn:fail? (lambda (exn) (eprintf "ERROR: ~s\n" (exn-message exn)) (set! failed? #t))]) ((orig-eval 'compile-file) src dest))))) @@ -296,10 +320,12 @@ (raise-user-error 'make-boot "compilation failure(s)"))) (let ([src->so (lambda (src) - (path->string (build-path "compiled" (path-replace-suffix src #".so"))))]) + (path->string (build-path out-subdir (path-replace-suffix src #".so"))))]) (status "Writing petite.boot") - (eval `($make-boot-file "compiled/petite.boot" ',(string->symbol target-machine) '() + (eval `($make-boot-file ,(path->string (build-path out-subdir "petite.boot")) + ',(string->symbol target-machine) '() ,@(map src->so petite-sources))) (status "Writing scheme.boot") - (eval `($make-boot-file "compiled/scheme.boot" ',(string->symbol target-machine) '("petite") + (eval `($make-boot-file ,(path->string (build-path out-subdir "scheme.boot")) + ',(string->symbol target-machine) '("petite") ,@(map src->so scheme-sources))))) diff --git a/racket/src/cs/bootstrap/nanopass-patch.rkt b/racket/src/cs/bootstrap/nanopass-patch.rkt index ee04ced0c5..4a4074d6e0 100644 --- a/racket/src/cs/bootstrap/nanopass-patch.rkt +++ b/racket/src/cs/bootstrap/nanopass-patch.rkt @@ -19,7 +19,7 @@ body)]))))) (free-identifier=? #'id #'make-in-context-transformer) (begin - (printf "Nanopass patch applied\n") + (printf "Apply nanopass patch\n") #'(... (define id (lambda args diff --git a/racket/src/cs/bootstrap/parse-makefile.rkt b/racket/src/cs/bootstrap/parse-makefile.rkt index f3ae0b54b7..92793fc474 100644 --- a/racket/src/cs/bootstrap/parse-makefile.rkt +++ b/racket/src/cs/bootstrap/parse-makefile.rkt @@ -6,6 +6,7 @@ (define (get-sources-from-makefile scheme-dir) (call-with-input-file* (build-path scheme-dir "s" "Mf-base") + #:mode 'text (lambda (i) (define (extract-files m) (string-split (regexp-replace* #rx"\\\\" (bytes->string/utf-8 (cadr m)) ""))) diff --git a/racket/src/cs/bootstrap/r6rs-lang.rkt b/racket/src/cs/bootstrap/r6rs-lang.rkt index 730b6f44ce..dd047730c1 100644 --- a/racket/src/cs/bootstrap/r6rs-lang.rkt +++ b/racket/src/cs/bootstrap/r6rs-lang.rkt @@ -12,6 +12,7 @@ "format.rkt" "syntax-mode.rkt" "constant.rkt" + "config.rkt" (only-in "record.rkt" do-$make-record-type register-rtd-name! @@ -769,9 +770,8 @@ (define (s:fixnum? x) (and (fixnum? x) - (let ([w (fixnum-width)]) - (<= low-fixnum x high-fixnum)))) + (<= low-fixnum x high-fixnum))) (define (make-compile-time-value v) v) -(define optimize-level (make-parameter 2)) +(define optimize-level (make-parameter optimize-level-init)) diff --git a/racket/src/cs/bootstrap/record.rkt b/racket/src/cs/bootstrap/record.rkt index 7fd0319e05..b5dbf8eea3 100644 --- a/racket/src/cs/bootstrap/record.rkt +++ b/racket/src/cs/bootstrap/record.rkt @@ -5,6 +5,7 @@ racket/list "immediate.rkt" "symbol.rkt" + "gensym.rkt" "constant.rkt") (provide do-$make-record-type @@ -57,8 +58,15 @@ (define (do-$make-record-type in-base-rtd in-super in-name fields sealed? opaque? more - #:uid [uid #f]) - (define name (if (string? in-name) (string->symbol in-name) in-name)) + #:uid [in-uid #f]) + (define name (cond + [(string? in-name) (string->symbol in-name)] + [(gensym? in-name) (string->symbol (gensym->pretty-string in-name))] + [else in-name])) + (define uid (or in-uid + (cond + [(gensym? in-name) in-name] + [else #f]))) (define super (cond [(base-rtd? in-super) struct:base-rtd-subtype] @@ -113,7 +121,7 @@ (define (fld-type fld) (vector-ref fld 3)) (define (fld-byte fld) (vector-ref fld 4)) (define (set-fld-byte! fld v) (vector-set! fld 4 v)) -(define fld-byte-value 0) ; gets replaced +(define fld-byte-value 0) ; doesn't matter; gets replaced in field vectors (define (register-rtd-fields! struct:name fields) (define-values (r-name init-cnt auto-cnt ref set immutables super skipped?) @@ -476,10 +484,10 @@ (void)) (define (fix-offsets flds) - (let loop ([flds flds] [offset (add1 fld-byte-value)]) + (let loop ([flds flds] [offset (+ record-ptr-offset ptr-bytes)]) (unless (null? flds) (set-fld-byte! (car flds) offset) - (loop (cdr flds) (+ offset fld-byte-value)))) + (loop (cdr flds) (+ offset ptr-bytes)))) flds) (define ($object-ref type v offset) @@ -493,7 +501,7 @@ (unless (or (eq? type 'scheme-object) (eq? type 'ptr)) (error '$object-ref "unrecognized type: ~e" type)) - (define i (quotient (- offset (add1 fld-byte-value)) fld-byte-value)) + (define i (quotient (- offset (+ record-ptr-offset ptr-bytes)) ptr-bytes)) (cond [(struct-type? v) (cond diff --git a/racket/src/cs/bootstrap/scheme-lang.rkt b/racket/src/cs/bootstrap/scheme-lang.rkt index d99096479f..d2bcc9c9be 100644 --- a/racket/src/cs/bootstrap/scheme-lang.rkt +++ b/racket/src/cs/bootstrap/scheme-lang.rkt @@ -17,6 +17,7 @@ "scheme-struct.rkt" "symbol.rkt" "record.rkt" + "constant.rkt" (only-in "r6rs-lang.rkt" make-record-constructor-descriptor set-car! @@ -123,7 +124,7 @@ [arithmetic-shift ash] [arithmetic-shift bitwise-arithmetic-shift-left] [arithmetic-shift bitwise-arithmetic-shift] - [fxrshift fxsrl] + [fxrshift fxsra] [bitwise-not lognot] [bitwise-ior logor] [bitwise-xor logxor] @@ -168,6 +169,7 @@ [logbit1 fxlogbit1] [logbit0 fxlogbit0] [logtest fxlogtest]) + fxsrl fxbit-field bitwise-bit-count bitwise-arithmetic-shift-right @@ -554,6 +556,13 @@ (define (logtest a b) (not (eqv? 0 (bitwise-and a b)))) +(define (fxsrl v amt) + (if (and (v . fx< . 0) + (amt . fx> . 0)) + (bitwise-and (fxrshift v amt) + (- (fxlshift 1 (- fixnum-bits amt)) 1)) + (fxrshift v amt))) + (define (fxbit-field fx1 fx2 fx3) (fxand (fxrshift fx1 fx2) (fx- (fxlshift 1 (- fx3 fx2)) 1))) diff --git a/racket/src/cs/c/Makefile.in b/racket/src/cs/c/Makefile.in index eede28b852..731e871c34 100644 --- a/racket/src/cs/c/Makefile.in +++ b/racket/src/cs/c/Makefile.in @@ -137,17 +137,20 @@ SCHEME_CONFIG_VARS = CC="$(CC)" CFLAGS="$(BASE_CFLAGS)" LD="$(LD)" LDFLAGS="$(LD scheme-make: cd $(SCHEME_SRC) && git submodule -q init && git submodule -q update + env SCHEME_SRC="$(SCHEME_SRC)" MACH="$(MACH)" $(BOOTSTRAP_RACKET) $(srcdir)/../bootstrap/make-boot.rkt cd $(SCHEME_SRC) && ./configure @SCHEME_CONFIG_ARGS@ $(SCHEME_CONFIG_VARS) mkdir -p $(SCHEME_SRC)/$(MACH)/boot/$(MACH) $(MAKE) $(SCHEME_SRC)/$(MACH)/boot/$(MACH)/equates.h + $(MAKE) $(SCHEME_SRC)/$(MACH)/boot/$(MACH)/scheme.h $(MAKE) $(SCHEME_SRC)/$(MACH)/boot/$(MACH)/petite.boot $(MAKE) $(SCHEME_SRC)/$(MACH)/boot/$(MACH)/scheme.boot cd $(SCHEME_SRC) && $(MAKE) -# Replace "equates.h", etc., if they seem to be out of date. -# Otherwise, `make` on Chez Scheme can fail. +# If "equates.h", etc., are newly built since previous build, move them into place $(SCHEME_SRC)/$(MACH)/boot/$(MACH)/equates.h: $(SCHEME_SRC)/boot/$(MACH)/equates.h cp $(SCHEME_SRC)/boot/$(MACH)/equates.h $(SCHEME_SRC)/$(MACH)/boot/$(MACH)/equates.h +$(SCHEME_SRC)/$(MACH)/boot/$(MACH)/scheme.h: $(SCHEME_SRC)/boot/$(MACH)/scheme.h + cp $(SCHEME_SRC)/boot/$(MACH)/scheme.h $(SCHEME_SRC)/$(MACH)/boot/$(MACH)/scheme.h $(SCHEME_SRC)/$(MACH)/boot/$(MACH)/petite.boot: $(SCHEME_SRC)/boot/$(MACH)/petite.boot cp $(SCHEME_SRC)/boot/$(MACH)/petite.boot $(SCHEME_SRC)/$(MACH)/boot/$(MACH)/petite.boot $(SCHEME_SRC)/$(MACH)/boot/$(MACH)/scheme.boot: $(SCHEME_SRC)/boot/$(MACH)/scheme.boot diff --git a/racket/src/worksp/cs/prep.rkt b/racket/src/worksp/cs/prep.rkt index f453a5e655..5da3112d97 100644 --- a/racket/src/worksp/cs/prep.rkt +++ b/racket/src/worksp/cs/prep.rkt @@ -42,6 +42,7 @@ (copy-one-dir "s") (copy-one-dir "mats") (copy-one-dir "nanopass") + (copy-one-dir "unicode") (copy-one-dir "zlib") (copy-one-dir "lz4") (copy-one-dir (build-path "boot" machine-name)) diff --git a/racket/src/worksp/cs/recompile.rkt b/racket/src/worksp/cs/recompile.rkt new file mode 100644 index 0000000000..2753f45761 --- /dev/null +++ b/racket/src/worksp/cs/recompile.rkt @@ -0,0 +1,70 @@ +#lang racket/base +(require racket/file + racket/system + "../../cs/bootstrap/parse-makefile.rkt") + +(provide recompile) + +(define optimize-level 3) + +(define (recompile scheme-dir machine #:system* [system* system*]) + (when (or (same-content? (build-path scheme-dir "boot" machine "petite.boot") + (build-path scheme-dir machine "boot" machine "petite.boot")) + (same-content? (build-path scheme-dir "boot" machine "scheme.boot") + (build-path scheme-dir machine "boot" machine "scheme.boot"))) + (define-values (petite-srcs scheme-srcs) (get-sources-from-makefile scheme-dir)) + + (define abs-scheme-dir (path->complete-path scheme-dir)) + + (parameterize ([current-directory (build-path scheme-dir machine "nanopass")]) + (define o (open-output-bytes)) + (write-nanopass-config o) + (write '(compile-library "nanopass.ss" "nanopass.so") o) + (parameterize ([current-input-port (open-input-bytes (get-output-bytes o))]) + (system* (build-path abs-scheme-dir machine "bin" machine "scheme.exe") + "-q" + "--compile-imported-libraries"))) + + (parameterize ([current-directory (build-path scheme-dir machine "s")]) + (copy-file (format "~a.def" machine) "machine.def" #t) + (define o (open-output-bytes)) + (define (src->so src) (regexp-replace #rx"[.]ss$" src ".so")) + (write-system-config o) + (for ([f (in-list '("cmacros.ss" "priminfo.ss"))]) + (write `(load ,f) o)) + (for ([f (in-list (append petite-srcs scheme-srcs))]) + (write `(compile-file ,f) o)) + (write `($make-boot-file ,(format "../boot/~a/petite.boot" machine) + ',(string->symbol machine) '() + ,@(map src->so petite-srcs)) + o) + (write `($make-boot-file ,(format "../boot/~a/scheme.boot" machine) + ',(string->symbol machine) '("petite") + ,@(map src->so scheme-srcs)) + o) + ;;(printf "~a\n" (get-output-string o)) + (parameterize ([current-input-port (open-input-bytes (get-output-bytes o))]) + (system* (build-path abs-scheme-dir machine "bin" machine "scheme.exe") + "-q" + "--libdirs" "../nanopass"))))) + +(define (same-content? f1 f2) + (and (equal? (file-size f1) + (file-size f2)) + (equal? (file->bytes f1) + (file->bytes f2)))) + +(define (write-config o) + (write '(reset-handler abort) o) + (write '(base-exception-handler (lambda (c) (fresh-line) (display-condition c) (newline) (reset))) o) + (write '(keyboard-interrupt-handler (lambda () (display "interrupted---aborting\n") (reset))) o) + (write `(optimize-level ,optimize-level) o) + (write '(debug-level 0) o) + (write '(generate-inspector-information #f) o)) + +(define (write-nanopass-config o) + (write-config o)) + +(define (write-system-config o) + (write-config o) + (write '(subset-mode (quote system)) o)) diff --git a/racket/src/worksp/csbuild.rkt b/racket/src/worksp/csbuild.rkt index 6f2596d812..90a7396e73 100644 --- a/racket/src/worksp/csbuild.rkt +++ b/racket/src/worksp/csbuild.rkt @@ -5,7 +5,8 @@ racket/runtime-path compiler/find-exe racket/system - "cs/prep.rkt") + "cs/prep.rkt" + "cs/recompile.rkt") (define-runtime-path here ".") @@ -67,6 +68,7 @@ ;; ---------------------------------------- +;; Download Chez Scheme source (let ([submodules '("nanopass" "stex" "zlib" "lz4")] [readmes '("ReadMe.md" "ReadMe" "README" "README.md")]) (define (clone from to [git-clone-args '()]) @@ -105,12 +107,30 @@ (system*! "git" "submodule" "init") (system*! "git" "submodule" "update")))])) +;; Bootstrap Chez Scheme boot files +(let/ec esc + (parameterize ([current-environment-variables + (environment-variables-copy (current-environment-variables))] + [exit-handler (let ([orig-exit (exit-handler)]) + (lambda (v) + (if (zero? v) + (esc) + (orig-exit v))))]) + (putenv "SCHEME_SRC" (path->string scheme-dir)) + (putenv "MACH" machine) + (dynamic-require (build-path here 'up "cs" "bootstrap" "make-boot.rkt") #f))) + +;; Prepare to use Chez Scheme makefile (prep-chez-scheme scheme-dir machine) +;; Finish building Chez Scheme (parameterize ([current-directory (build-path scheme-dir machine "c")]) (system*! "nmake" (format "Makefile.~a" machine))) +;; Replace Chez-on-Racket-built bootfiles with Chez-built bootfiles +(recompile scheme-dir machine #:system* system*!) + ;; ---------------------------------------- ;; Run Racket in directories that reach here with "../worksp".