diff --git a/src/Makefile b/src/Makefile index aa9bfa2..d42d9ed 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2,7 +2,7 @@ all: ikarus.fasl ikarus.fasl: - echo '(load "compiler-6.2.ss")' | petite + echo '(load "compiler-6.9.ss")' | petite clean: rm -f *.fasl diff --git a/src/build-date.tmp b/src/build-date.tmp index 597f7df..a33701c 100644 --- a/src/build-date.tmp +++ b/src/build-date.tmp @@ -1 +1 @@ -2006-08-02 +2006-08-22 diff --git a/src/chez-compat.ss b/src/chez-compat.ss index 9de1539..9ef66bf 100644 --- a/src/chez-compat.ss +++ b/src/chez-compat.ss @@ -31,5 +31,27 @@ (define char= char=?) +(set! $base-rtd #%$base-rtd) +(define-syntax |#primitive| + (syntax-rules () + [(_ n prim) prim] + [(_ prim) prim])) +(define (date-string) + (system "date +\"%F\" > build-date.tmp") + (let ([ip (open-input-file "build-date.tmp")]) + (list->string + (let f () + (let ([x (read-char ip)]) + (if (char=? x #\newline) + '() + (cons x (f)))))))) +(define ($record rtd . args) + (apply (record-constructor rtd) args)) +(define ($record/rtd? x rtd) + (and (record? x) (eq? (record-type-descriptor x) rtd))) +(define ($record-ref x i) + ((record-field-accessor (record-type-descriptor x) i) x)) +(define ($record-set! x i v) + ((record-field-mutator (record-type-descriptor x) i) x v)) diff --git a/src/compiler-6.3.ss b/src/compiler-6.3.ss new file mode 100644 index 0000000..88e1083 --- /dev/null +++ b/src/compiler-6.3.ss @@ -0,0 +1,3199 @@ + + +;;; 6.2: * side-effects now modify the dirty-vector +;;; * added bwp-object? +;;; * added pointer-value +;;; * added tcbuckets +;;; 6.1: * added case-lambda, dropped lambda +;;; 6.0: * basic compiler + +(when (eq? "" "") + (load "chez-compat.ss") + (set! primitive-ref top-level-value) + (set! primitive-set! set-top-level-value!) + (set! chez-expand sc-expand) + (printf "loading psyntax.pp ...\n") + (load "psyntax-7.1.pp") + (current-expand + (lambda (x . args) + (apply chez-expand (sc-expand x) args))) + (printf "loading psyntax.ss ...\n") + (load "psyntax-7.1.ss") + (current-expand + (lambda (x . args) + (apply chez-expand (sc-expand x) args))) + (printf "ok\n")) + +(define primitive-set! set-top-level-value!) +(load "record-case.ss") + +(load "libassembler-compat-6.0.ss") ; defines make-code etc. +(load "libintelasm-6.0.ss") ; uses make-code, etc. +(load "libfasl-6.0.ss") ; uses code? etc. + + + +(load "tests-driver.ss") +(print-gensym #f) +(gensym-prefix "L_") + + +(define assembler-output (make-parameter #t)) + +(load "set-operations.ss") +;(load "tests-5.6-req.scm") +;(load "tests-5.3-req.scm") +;(load "tests-5.2-req.scm") +;(load "tests-5.1-req.scm") +;(load "tests-4.3-req.scm") +;(load "tests-4.2-req.scm") + +;(load "tests-4.1-req.scm") +;(load "tests-3.4-req.scm") + +;(load "tests-3.3-req.scm") +;(load "tests-3.2-req.scm") +;(load "tests-3.1-req.scm") +;(load "tests-2.9-req.scm") +;(load "tests-2.8-req.scm") +;(load "tests-2.6-req.scm") +;(load "tests-2.4-req.scm") +;(load "tests-2.3-req.scm") +;(load "tests-2.2-req.scm") +;(load "tests-2.1-req.scm") +;(load "tests-1.9-req.scm") +;(load "tests-1.8-req.scm") +;(load "tests-1.7-req.scm") +;(load "tests-1.6-req.scm") +;(load "tests-1.5-req.scm") +;(load "tests-1.4-req.scm") +;(load "tests-1.3-req.scm") +;(load "tests-1.2-req.scm") +;(load "tests-1.1-req.scm") + + +(define scheme-library-files + '(["libhandlers-6.0.ss" "libhandlers.fasl"] + ["libcontrol-6.1.ss" "libcontrol.fasl"] + ["libcollect-6.1.ss" "libcollect.fasl"] + ["librecord-6.1.ss" "librecord.fasl"] + ["libcxr-6.0.ss" "libcxr.fasl"] + ["libcore-6.2.ss" "libcore.fasl"] + ["libio-6.1.ss" "libio.fasl"] + ["libwriter-6.2.ss" "libwriter.fasl"] + ["libtokenizer-6.1.ss" "libtokenizer.fasl"] + ;["libexpand-6.2.ss" "libexpand.fasl"] + ;["libcompile-6.4.ss" "libcompile.fasl"] + ["psyntax-7.1.ss" "psyntax.fasl"] + ["libinterpret-6.1.ss" "libinterpret.fasl"] + ;["libintelasm-6.0.ss" "libintelasm.fasl"] + ["libcafe-6.1.ss" "libcafe.fasl"] +; ["libtrace-5.3.ss" "libtrace-5.3.s" "libtrace" ] + ["libposix-6.0.ss" "libposix.fasl"] + ["libhash-6.2.ss" "libhash.fasl"] + ["libtoplevel-6.0.ss" "libtoplevel.fasl"] + )) + +(define primitive? + (lambda (x) + (or (assq x open-coded-primitives) + (memq x public-primitives)))) + +(define open-coded-primitives +;;; these primitives, when found in operator position with the correct +;;; number of arguments, will be open-coded by the generator. If an +;;; incorrect number of args is detected, or if they appear in non-operator +;;; position, then they cannot be open-coded, and the pcb-primitives table +;;; is consulted for a reference of the pcb slot containing the primitive. +;;; If it's not found there, an error is signalled. +;;; +;;; prim-name args + '([$constant-ref 1 value] + [$constant-set! 2 effect] + [$pcb-ref 1 value] + [$pcb-set! 2 effect] + ;;; type predicates + [fixnum? 1 pred] + [immediate? 1 pred] + [boolean? 1 pred] + [char? 1 pred] + [pair? 1 pred] + [symbol? 1 pred] + [vector? 1 pred] + [string? 1 pred] + [procedure? 1 pred] + [null? 1 pred] + [eof-object? 1 pred] + [bwp-object? 1 pred] + [$unbound-object? 1 pred] + [$forward-ptr? 1 pred] + [not 1 pred] + [pointer-value 1 value] + [eq? 2 pred] + ;;; fixnum primitives + [$fxadd1 1 value] + [$fxsub1 1 value] + [$fx+ 2 value] + [$fx- 2 value] + [$fx* 2 value] + [$fxsll 2 value] + [$fxsra 2 value] + [$fxlogand 2 value] + [$fxlogor 2 value] + [$fxlogxor 2 value] + [$fxlognot 1 value] + [$fxquotient 2 value] + [$fxmodulo 2 value] + ;;; fixnum predicates + [$fxzero? 1 pred] + [$fx= 2 pred] + [$fx< 2 pred] + [$fx<= 2 pred] + [$fx> 2 pred] + [$fx>= 2 pred] + ;;; character predicates + [$char= 2 pred] + [$char< 2 pred] + [$char<= 2 pred] + [$char> 2 pred] + [$char>= 2 pred] + ;;; character conversion + [$fixnum->char 1 value] + [$char->fixnum 1 value] + ;;; lists/pairs + [cons 2 value] + [$car 1 value] + [$cdr 1 value] + [$set-car! 2 effect] + [$set-cdr! 2 effect] + ;;; vectors + [$make-vector 1 value] + [vector any value] + [$vector-length 1 value] + [$vector-ref 2 value] + [$vector-set! 3 effect] + ;;; strings + [$make-string 1 value] + [$string any value] + [$string-length 1 value] + [$string-ref 2 value] + [$string-set! 3 effect] + ;;; symbols + [$make-symbol 1 value] + [$symbol-value 1 value] + [$symbol-string 1 value] + [$symbol-unique-string 1 value] + [$set-symbol-value! 2 effect] + [$set-symbol-string! 2 effect] + [$set-symbol-unique-string! 2 effect] + [$symbol-plist 1 value] + [$set-symbol-plist! 2 effect] + [primitive-ref 1 value] + [primitive-set! 2 effect] + ;;; tcbuckets + [$make-tcbucket 4 value] + [$tcbucket-key 1 value] + [$tcbucket-val 1 value] + [$tcbucket-next 1 value] + [$set-tcbucket-val! 2 effect] + [$set-tcbucket-next! 2 effect] + [$set-tcbucket-tconc! 2 effect] + ;;; misc + [eof-object 0 value] + [void 0 value] + [$exit 1 effect] + [$fp-at-base 0 pred] + [$current-frame 0 value] + [$seal-frame-and-call 1 tail] + [$frame->continuation 1 value] + ;;; + ;;; records + ;;; + [$make-record 2 value] + [$record? 1 pred] + [$record-rtd 1 value] + [$record-ref 2 value] + [$record-set! 3 effect] + ;;; + ;;; asm + ;;; + ;[code? 1 pred] + ;[$code-instr-size 1 value] + ;[$code-reloc-size 1 value] + ;[$code-closure-size 1 value] + ;[$code->closure 1 value] + ;[$set-code-byte! 3 effect] + ;[$set-code-word! 3 effect] + ;[$set-code-object! 4 effect] + ;[$set-code-object+offset! 5 effect] + ;[$set-code-object+offset/rel! 5 effect] + ;;; + [$make-call-with-values-procedure 0 value] + [$make-values-procedure 0 value] + [$install-underflow-handler 0 effect] + )) + +(define (primitive-context x) + (cond + [(assq x open-coded-primitives) => caddr] + [else (error 'primitive-context "unknown prim ~s" x)])) + + +;;; primitives table section +(define primitives-table + '(;;; system locations used by the C/Scheme interface + [$apply-nonprocedure-error-handler library] + [$incorrect-args-error-handler library] + [$multiple-values-error library] + [$intern library] + [do-overflow library] + [do-vararg-overflow library] + [do-stack-overflow library] + ;;; type predicates + [fixnum? public] + [immediate? public] + [boolean? public] + [char? public] + [null? public] + [pair? public] + [symbol? public] + [vector? public] + [string? public] + [procedure? public] + [eof-object? public] + [not public] + [eq? public] + [equal? public] + ;;; fixnum primitives + [fxadd1 public] + [fxsub1 public] + [fx+ public] + [fx- public] + [fx* public] + [fxsll public] + [fxsra public] + [fxlogor public] + [fxlogand public] + [fxlogxor public] + [fxlognot public] + [fxquotient public] + [fxremainder public] + [fxmodulo public] + ;;; fixnum predicates + [fxzero? public] + [fx= public] + [fx< public] + [fx<= public] + [fx> public] + [fx>= public] + ;;; characters + [char=? public] + [char? public] + [char>=? public] + [integer->char public] + [char->integer public] + ;;; lists + [cons public] + [car public] + [cdr public] + [caar public] + [cadr public] + [cdar public] + [cddr public] + [caaar public] + [caadr public] + [cadar public] + [caddr public] + [cdaar public] + [cdadr public] + [cddar public] + [cdddr public] + [caaaar public] + [caaadr public] + [caadar public] + [caaddr public] + [cadaar public] + [cadadr public] + [caddar public] + [cadddr public] + [cdaaar public] + [cdaadr public] + [cdadar public] + [cdaddr public] + [cddaar public] + [cddadr public] + [cdddar public] + [cddddr public] + [set-car! public] + [set-cdr! public] + [list public] + [list* ADDME] + [list? public] + [list-ref public] + [length public] + [make-list public] + [reverse public] + [append public] + [list-ref public] + [memq public] + [memv public] + [assq public] + [map public] + [for-each public] + [andmap public] + [ormap public] + ;;; vectors + [make-vector public] + [vector public] + [vector-length public] + [vector-ref public] + [vector-set! public] + [list->vector public] + [vector->list public] + ;;; strings + [make-string public] + [string public] + [string-length public] + [string-ref public] + [string-set! public] + [list->string public] + [string->list public] + [string-append public] + [substring public] + [string=? public] + [fixnum->string public] + ;;; symbols + [gensym public] + [gensym? public] + [symbol->string public] + [gensym->unique-string public] + [gensym-prefix public] + [gensym-count public] + [print-gensym public] + [string->symbol public] + [top-level-value public] + [top-level-bound? public] + [set-top-level-value! public] + [primitive-set! public] + [getprop public] + [putprop public] + [remprop public] + [property-list public] + [oblist public] + [uuid public] + ;;; eof + [eof-object public] + [void public] + ;;; control/debugging + [print-error public] + [error public] + [current-error-handler public] + [exit public] + [apply public] + [make-parameter public] + ;;; output + [output-port? public] + [console-output-port public] + [current-output-port public] + [standard-output-port public] + [standard-error-port public] + [open-output-file public] + [open-output-string public] + [with-output-to-file public] + [call-with-output-file public] + [with-input-from-file public] + [call-with-input-file public] + [get-output-string public] + [close-output-port public] + [flush-output-port public] + [write-char public] + [output-port-name public] + [newline public] + ;;; input + [input-port? public] + [standard-input-port public] + [console-input-port public] + [current-input-port public] + [open-input-file public] + [close-input-port public] + [reset-input-port! public] + [read-char public] + [peek-char public] + [unread-char public] + [input-port-name public] + ;;; writing/printing + [write public] + [display public] + [printf public] + [fprintf public] + [format public] + [read-token public] + [read public] + ;;; evaluation + [primitive? public] + [expand public] + [syntax-error public] + [current-expand public] + [expand-mode public] + [compile-file public] + [fasl-write public] + + [$sc-put-cte public] + [sc-expand public] + [$make-environment public] + [environment? public] + [interaction-environment public] + [identifier? public] + [syntax->list public] + [syntax-object->datum public] + [datum->syntax-object public] + [generate-temporaries public] + [free-identifier=? public] + [bound-identifier=? public] + [literal-identifier=? public] + [syntax-error public] + [$syntax-dispatch public] + + + + [interpret public] + [eval public] + [current-eval public] + [load public] + [new-cafe public] + [collect public] + [call/cc public] + [call/cf library] + [dynamic-wind public] + [values public] + [call-with-values public] + [make-traced-procedure library] + [trace-symbol! library] + [untrace-symbol! library] + ;;; record + [$base-rtd library] + [record? public] + [record-rtd public] + [record-name public] + [record-printer public] + [record-length public] + [record-ref public] + [record-set! public] + ;;; record rtds + [make-record-type public] + [record-constructor public] + [record-predicate public] + [record-field-accessor public] + [record-field-mutator public] + ;;; hash tables + [make-hash-table public] + [hash-table? public] + [get-hash-table public] + [put-hash-table! public] + ;;; asm + [make-code public] + [code? public] + [make-code-executable! public] + [code-instr-size public] + [code-reloc-size public] + [code-closure-size public] + [set-code-byte! public] + [set-code-word! public] + [set-code-object! public] + [set-code-foreign-object! public] + [set-code-object+offset! public] + [set-code-object+offset/rel! public] + [set-code-object/reloc/relative! public] + [code->closure public] + [list*->code* library] + ;;; + ;;; POSIX + ;;; + [fork public] + [posix-fork public] + [system public] + [$debug public] + [$underflow-misaligned-error public] + )) + +(define (primitive? x) + (cond + [(assq x primitives-table) #t] + [(assq x open-coded-primitives) #t] + [else #f])) + +(define (open-codeable? x) + (cond + [(assq x open-coded-primitives) #t] + [(assq x primitives-table) #f] + [else (error 'open-codeable "invalid primitive ~s" x)])) + +(define (open-coded-primitive-args x) + (cond + [(assq x open-coded-primitives) => cadr] + [else (error 'open-coded-primitive-args "invalid ~s" x)])) + +;;; end of primitives table section + + +(define-record constant (value)) +(define-record code-loc (label)) +(define-record foreign-label (label)) +(define-record var (name)) +(define-record cp-var (idx)) +(define-record frame-var (idx)) +(define-record new-frame (base-idx size body)) +(define-record save-cp (loc)) +(define-record eval-cp (check body)) +(define-record return (value)) +(define-record call-cp + (call-convention rp-convention base-idx arg-count live-mask)) +(define-record primcall (op arg*)) +(define-record primref (name)) +(define-record conditional (test conseq altern)) +(define-record bind (lhs* rhs* body)) +(define-record seq (e0 e1)) +(define-record function (arg* proper body)) +(define-record clambda-case (arg* proper body)) +(define-record clambda (cases)) +(define-record clambda-code (label cases free)) + +(define-record closure (code free*)) +(define-record funcall (op rand*)) +(define-record appcall (op rand*)) +(define-record forcall (op rand*)) +(define-record code-rec (arg* proper free* body)) + +(define-record codes (list body)) +(define-record assign (lhs rhs)) + +(define unique-var + (let ([counter 0]) + (lambda (x) + (let ([g (gensym (format "~a:~a" x counter))]) + (set! counter (fxadd1 counter)) + (make-var g))))) + +(define (make-bind^ lhs* rhs* body) + (if (null? lhs*) + body + (make-bind lhs* rhs* body))) + +(define (recordize x) + (define (gen-fml* fml*) + (cond + [(pair? fml*) + (cons (unique-var (car fml*)) + (gen-fml* (cdr fml*)))] + [(symbol? fml*) + (unique-var fml*)] + [else '()])) + (define (properize fml*) + (cond + [(pair? fml*) + (cons (car fml*) (properize (cdr fml*)))] + [(null? fml*) '()] + [else (list fml*)])) + (define (extend-env fml* nfml* env) + (cons (cons fml* nfml*) env)) + (define (quoted-sym x) + (if (and (list? x) + (fx= (length x) 2) + (eq? 'quote (car x)) + (symbol? (cadr x))) + (cadr x) + (error 'quoted-sym "not a quoted symbol ~s" x))) + (define (quoted-string x) + (if (and (list? x) + (fx= (length x) 2) + (eq? 'quote (car x)) + (string? (cadr x))) + (cadr x) + (error 'quoted-string "not a quoted string ~s" x))) + (define (lookup^ x lhs* rhs*) + (cond + [(pair? lhs*) + (if (eq? x (car lhs*)) + (car rhs*) + (lookup^ x (cdr lhs*) (cdr rhs*)))] + [(eq? x lhs*) rhs*] + [else #f])) + (define (lookup x env) + (cond + [(pair? env) + (or (lookup^ x (caar env) (cdar env)) + (lookup x (cdr env)))] + [else #f])) + (define (E x env) + (cond + [(pair? x) + (case (car x) + [(quote) (make-constant (cadr x))] + [(if) + (make-conditional + (E (cadr x) env) + (E (caddr x) env) + (E (cadddr x) env))] + [(set!) + (let ([lhs (cadr x)] [rhs (caddr x)]) + (make-assign + (or (lookup lhs env) + (error 'recordize "invalid assignment ~s" x)) + (E rhs env)))] + [(begin) + (let f ([a (cadr x)] [d (cddr x)]) + (cond + [(null? d) (E a env)] + [else + (make-seq + (E a env) + (f (car d) (cdr d)))]))] + [(case-lambda) + (let ([cls* + (map + (lambda (cls) + (let ([fml* (car cls)] [body (cadr cls)]) + (let ([nfml* (gen-fml* fml*)]) + (let ([body (E body (extend-env fml* nfml* env))]) + (make-clambda-case + (properize nfml*) + (list? fml*) + body))))) + (cdr x))]) + (make-clambda cls*))] + [(foreign-call) + (let ([name (quoted-string (cadr x))] [arg* (cddr x)]) + (make-forcall name + (map (lambda (x) (E x env)) arg*)))] + [(|#primitive|) + (let ([var (cadr x)]) + (if (primitive? var) + (make-primref var) + (error 'recordize "invalid primitive ~s" var)))] + [(top-level-value) + (let ([var (quoted-sym (cadr x))]) + (cond + [(primitive? var) (make-primref var)] + [else (error 'recordize "invalid top-level var ~s" var)]))] + [(memv) + (make-funcall + (make-primref 'memq) + (map (lambda (x) (E x env)) (cdr x)))] + [($apply) + (let ([proc (cadr x)] [arg* (cddr x)]) + (make-appcall + (E proc env) + (map (lambda (x) (E x env)) arg*)))] + [(void) + (make-constant (void))] + [else + (make-funcall + (E (car x) env) + (map (lambda (x) (E x env)) (cdr x)))])] + [(symbol? x) + (or (lookup x env) + (error 'recordize "invalid reference in ~s" x))] + [else (error 'recordize "invalid expression ~s" x)])) + (E x '())) + + +(define (unparse x) + (define (E-args proper x) + (if proper + (map E x) + (let f ([a (car x)] [d (cdr x)]) + (cond + [(null? d) (E a)] + [else (cons (E a) (f (car d) (cdr d)))])))) + (define (E x) + (record-case x + [(constant c) `(quote ,c)] + [(code-loc x) `(code-loc ,x)] + [(var x) (string->symbol (format "v:~a" x))] + [(primref x) x] + [(conditional test conseq altern) + `(if ,(E test) ,(E conseq) ,(E altern))] + [(primcall op arg*) `(,op . ,(map E arg*))] + [(bind lhs* rhs* body) + `(let ,(map (lambda (lhs rhs) (list (E lhs) (E rhs))) lhs* rhs*) + ,(E body))] + [(seq e0 e1) `(begin ,(E e0) ,(E e1))] + [(function args proper body) + `(lambda ,(E-args proper args) ,(E body))] + [(clambda-case args proper body) + `(clambda-case ,(E-args proper args) ,(E body))] + [(clambda cls*) + `(case-lambda . ,(map E cls*))] + [(clambda-code label clauses free) + `(code ,label . ,(map E clauses))] + [(closure code free*) + `(closure ,(E code) ,(map E free*))] + [(code-rec arg* proper free* body) + `(code-rec [arg: ,(E-args proper arg*)] + [free: ,(map E free*)] + ,(E body))] + [(codes list body) + `(codes ,(map E list) + ,(E body))] + [(funcall rator rand*) `(funcall ,(E rator) . ,(map E rand*))] + [(appcall rator rand*) `(appcall ,(E rator) . ,(map E rand*))] + [(forcall rator rand*) `(foreign-call ,rator . ,(map E rand*))] + [(assign lhs rhs) `(set! ,(E lhs) ,(E rhs))] + [(return x) `(return ,(E x))] + [(new-frame base-idx size body) + `(new-frame [base: ,base-idx] + [size: ,size] + ,(E body))] + [(frame-var idx) + (string->symbol (format "fv.~a" idx))] + [(cp-var idx) + (string->symbol (format "cp.~a" idx))] + [(save-cp expr) + `(save-cp ,(E expr))] + [(eval-cp check body) + `(eval-cp ,check ,(E body))] + [(call-cp call-convention rp-convention base-idx arg-count live-mask) + `(call-cp [conv: ,call-convention] + [rpconv: ,rp-convention] + [base-idx: ,base-idx] + [arg-count: ,arg-count] + [live-mask: ,live-mask])] + [(foreign-label x) `(foreign-label ,x)] + [else (error 'unparse "invalid record ~s" x)])) + (E x)) + +(define (optimize-direct-calls x) + (define who 'optimize-direct-calls) + (define (make-conses ls) + (cond + [(null? ls) (make-constant '())] + [else + (make-primcall 'cons + (list (car ls) (make-conses (cdr ls))))])) + (define (properize lhs* rhs*) + (cond + [(null? lhs*) (error who "improper improper")] + [(null? (cdr lhs*)) + (list (make-conses rhs*))] + [else (cons (car rhs*) (properize (cdr lhs*) (cdr rhs*)))])) + (define (inline-case cls rand*) + (record-case cls + [(clambda-case fml* proper body) + (if proper + (and (fx= (length fml*) (length rand*)) + (make-bind fml* rand* body)) + (and (fx<= (length fml*) (length rand*)) + (make-bind fml* (properize fml* rand*) body)))])) + (define (try-inline cls* rand* default) + (cond + [(null? cls*) default] + [(inline-case (car cls*) rand*)] + [else (try-inline (cdr cls*) rand* default)])) + (define (inline rator rand*) + (record-case rator + [(clambda cls*) + (try-inline cls* rand* + (make-funcall rator rand*))] +; [(function fml* proper body) +; (cond +; [proper +; (if (fx= (length fml*) (length rand*)) +; (make-bind fml* rand* body) +; (begin +; (warning 'compile "possible application error in ~s" +; (unparse (make-funcall rator rand*))) +; (make-funcall rator rand*)))] +; [else +; (if (fx<= (length fml*) (length rand*)) +; (make-bind fml* (properize fml* rand*) body) +; (begin +; (warning 'compile "possible application error in ~s" +; (unparse (make-funcall rator rand*))) +; (make-funcall rator rand*)))])] + [else (make-funcall rator rand*)])) + (define (Expr x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional + (Expr test) + (Expr conseq) + (Expr altern))] + [(seq e0 e1) + (make-seq (Expr e0) (Expr e1))] + [(function fml* proper body) + (make-function fml* proper (Expr body))] + [(clambda cls*) + (make-clambda + (map (lambda (x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (Expr body))])) + cls*))] + [(primcall rator rand*) + (make-primcall rator (map Expr rand*))] + [(funcall rator rand*) + (inline (Expr rator) (map Expr rand*))] + [(appcall rator rand*) + (make-appcall (Expr rator) (map Expr rand*))] + [(forcall rator rand*) + (make-forcall rator (map Expr rand*))] + [(assign lhs rhs) + (make-assign lhs (Expr rhs))] + [else (error who "invalid expression ~s" (unparse x))])) + (Expr x)) + + + +(define (uncover-assigned x) + (define who 'uncover-assigned) + (define (Expr* x*) + (cond + [(null? x*) '()] + [else (union (Expr (car x*)) (Expr* (cdr x*)))])) + (define (Expr x) + (record-case x + [(constant) '()] + [(var) '()] + [(primref) '()] + [(bind lhs* rhs* body) + (union (Expr body) (Expr* rhs*))] + [(conditional test conseq altern) + (union (Expr test) (union (Expr conseq) (Expr altern)))] + [(seq e0 e1) (union (Expr e0) (Expr e1))] + [(clambda cls*) + (Expr* (map clambda-case-body cls*))] + [(function fml* proper body) (Expr body)] + [(primcall rator rand*) (Expr* rand*)] + [(funcall rator rand*) + (union (Expr rator) (Expr* rand*))] + [(appcall rator rand*) + (union (Expr rator) (Expr* rand*))] + [(forcall rator rand*) (Expr* rand*)] + [(assign lhs rhs) + (union (singleton lhs) (Expr rhs))] + [else (error who "invalid expression ~s" (unparse x))])) + (Expr x)) + +(define (rewrite-assignments assigned x) + (define who 'rewrite-assignments) + (define (fix lhs*) + (cond + [(null? lhs*) (values '() '() '())] + [else + (let ([x (car lhs*)]) + (let-values ([(lhs* a-lhs* a-rhs*) (fix (cdr lhs*))]) + (cond + [(memq x assigned) + (let ([t (make-var 'assignment-tmp)]) + (values (cons t lhs*) (cons x a-lhs*) (cons t a-rhs*)))] + [else + (values (cons x lhs*) a-lhs* a-rhs*)])))])) + (define (bind-assigned lhs* rhs* body) + (cond + [(null? lhs*) body] + [else + (make-bind lhs* + (map (lambda (rhs) (make-primcall 'vector (list rhs))) rhs*) + body)])) + (define (Expr x) + (record-case x + [(constant) x] + [(var) + (cond + [(memq x assigned) + (make-primcall '$vector-ref (list x (make-constant 0)))] + [else x])] + [(primref) x] + [(bind lhs* rhs* body) + (let-values ([(lhs* a-lhs* a-rhs*) (fix lhs*)]) + (make-bind lhs* (map Expr rhs*) + (bind-assigned a-lhs* a-rhs* (Expr body))))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (make-seq (Expr e0) (Expr e1))] + [(function fml* proper body) + (let-values ([(fml* a-lhs* a-rhs*) (fix fml*)]) + (make-function fml* proper + (bind-assigned a-lhs* a-rhs* (Expr body))))] + [(clambda cls*) + (make-clambda + (map (lambda (cls) + (record-case cls + [(clambda-case fml* proper body) + (let-values ([(fml* a-lhs* a-rhs*) (fix fml*)]) + (make-clambda-case fml* proper + (bind-assigned a-lhs* a-rhs* (Expr body))))])) + cls*))] + [(primcall op rand*) + (make-primcall op (map Expr rand*))] + [(forcall op rand*) + (make-forcall op (map Expr rand*))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall rator rand*) + (make-appcall (Expr rator) (map Expr rand*))] + [(assign lhs rhs) + (unless (memq lhs assigned) + (error 'rewrite-assignments "not assigned ~s in ~s" lhs x)) + (make-primcall '$vector-set! (list lhs (make-constant 0) (Expr rhs)))] + [else (error who "invalid expression ~s" (unparse x))])) + (Expr x)) + + +(define (remove-assignments x) + (let ([assigned (uncover-assigned x)]) + (rewrite-assignments assigned x))) + + +(define (convert-closures prog) + (define who 'convert-closures) + (define (Expr* x*) + (cond + [(null? x*) (values '() '())] + [else + (let-values ([(a a-free) (Expr (car x*))] + [(d d-free) (Expr* (cdr x*))]) + (values (cons a d) (union a-free d-free)))])) + (define (Expr ex) + (record-case ex + [(constant) (values ex '())] + [(var) (values ex (singleton ex))] + [(primref) (values ex '())] + [(bind lhs* rhs* body) + (let-values ([(rhs* rhs-free) (Expr* rhs*)] + [(body body-free) (Expr body)]) + (values (make-bind lhs* rhs* body) + (union rhs-free (difference body-free lhs*))))] + [(conditional test conseq altern) + (let-values ([(test test-free) (Expr test)] + [(conseq conseq-free) (Expr conseq)] + [(altern altern-free) (Expr altern)]) + (values (make-conditional test conseq altern) + (union test-free (union conseq-free altern-free))))] + [(seq e0 e1) + (let-values ([(e0 e0-free) (Expr e0)] + [(e1 e1-free) (Expr e1)]) + (values (make-seq e0 e1) (union e0-free e1-free)))] + [(function fml* proper body) + (let-values ([(body body-free) (Expr body)]) + (let ([free (difference body-free fml*)]) + (values (make-closure (make-code-rec fml* proper free body) free) + free)))] + [(clambda cls*) + (let-values ([(cls* free) + (let f ([cls* cls*]) + (cond + [(null? cls*) (values '() '())] + [else + (record-case (car cls*) + [(clambda-case fml* proper body) + (let-values ([(body body-free) (Expr body)] + [(cls* cls*-free) (f (cdr cls*))]) + (values + (cons (make-clambda-case fml* proper body) + cls*) + (union (difference body-free fml*) + cls*-free)))])]))]) + (values (make-closure (make-clambda-code (gensym) cls* free) free) + free))] + [(primcall op rand*) + (let-values ([(rand* rand*-free) (Expr* rand*)]) + (values (make-primcall op rand*) rand*-free))] + [(forcall op rand*) + (let-values ([(rand* rand*-free) (Expr* rand*)]) + (values (make-forcall op rand*) rand*-free))] + [(funcall rator rand*) + (let-values ([(rator rat-free) (Expr rator)] + [(rand* rand*-free) (Expr* rand*)]) + (values (make-funcall rator rand*) + (union rat-free rand*-free)))] + [(appcall rator rand*) + (let-values ([(rator rat-free) (Expr rator)] + [(rand* rand*-free) (Expr* rand*)]) + (values (make-appcall rator rand*) + (union rat-free rand*-free)))] + [else (error who "invalid expression ~s" (unparse ex))])) + (let-values ([(prog free) (Expr prog)]) + (unless (null? free) + (error 'convert-closures "free vars ~s encountered in ~a" + free (unparse prog))) + prog)) + + +(define (lift-codes x) + (define who 'lift-codes) + (define all-codes '()) + (define (do-code x) + (record-case x + [(clambda-code label cls* free) + (let ([cls* (map + (lambda (x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (E body))])) + cls*)]) + (let ([g (make-code-loc label)]) + (set! all-codes + (cons (make-clambda-code label cls* free) all-codes)) + g))])) + (define (E x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(bind lhs* rhs* body) + (make-bind lhs* (map E rhs*) (E body))] + [(conditional test conseq altern) + (make-conditional (E test) (E conseq) (E altern))] + [(seq e0 e1) (make-seq (E e0) (E e1))] + [(closure c free) (make-closure (do-code c) free)] + [(primcall op rand*) (make-primcall op (map E rand*))] + [(forcall op rand*) (make-forcall op (map E rand*))] + [(funcall rator rand*) (make-funcall (E rator) (map E rand*))] + [(appcall rator rand*) (make-appcall (E rator) (map E rand*))] + [else (error who "invalid expression ~s" (unparse x))])) + (let ([x (E x)]) + (make-codes all-codes x))) + + + + +(define (syntactically-valid? op rand*) + (define (valid-arg-count? op rand*) + (let ([n (open-coded-primitive-args op)] [m (length rand*)]) + (cond + [(eq? n 'any) #t] + [(eq? n 'no-code) + (error 'syntactically-valid + "should not primcall non codable prim ~s" op)] + [(fixnum? n) + (cond + [(fx= n m) #t] + [else + (error 'compile + "Possible incorrect number of args in ~s" + (cons op (map unparse rand*))) + #f])] + [else (error 'do-primcall "BUG: what ~s" n)]))) + (define (check op pred?) + (lambda (arg) + (record-case arg + [(constant c) + (cond + [(pred? c) #t] + [else + (error 'compile "Possible argument error to primitive ~s" op) + #f])] + [(primref) + (cond + [(pred? (lambda (x) x)) #t] + [else + (error 'compile "Possible argument error to primitive ~s" op) + #f])] + [else #t]))) + (define (nonnegative-fixnum? n) + (and (fixnum? n) (fx>= n 0))) + (define (byte? n) + (and (fixnum? n) (fx<= 0 n) (fx<= n 127))) + (define (valid-arg-types? op rand*) + (case op + [(fixnum? immediate? boolean? char? vector? string? procedure? + null? pair? not cons eq? vector symbol? error eof-object eof-object? + void $unbound-object? code? $forward-ptr? bwp-object? + pointer-value) + '#t] + [($fxadd1 $fxsub1 $fxzero? $fxlognot $fxlogor $fxlogand $fx+ $fx- $fx* + $fx= $fx< $fx<= $fx> $fx>= $fxquotient $fxmodulo $fxsll $fxsra $fxlogxor $exit) + (andmap (check op fixnum?) rand*)] + [($fixnum->char) + (andmap (check op byte?) rand*)] + [($char->fixnum $char= $char< $char<= $char> $char>= $string) + (andmap (check op char?) rand*)] + [($make-vector $make-string) + (andmap (check op nonnegative-fixnum?) rand*)] + [($car $cdr) + (andmap (check op pair?) rand*)] + [($vector-length) + (andmap (check op vector?) rand*)] + [($string-length) + (andmap (check op string?) rand*)] + [($set-car! $set-cdr!) + ((check op pair?) (car rand*))] + [($vector-ref $vector-set!) + (and ((check op vector?) (car rand*)) + ((check op nonnegative-fixnum?) (cadr rand*)))] + [($string-ref $string-set! + $string-ref-16+0 $string-ref-16+1 $string-ref-8+0 $string-ref-8+2) + (and ((check op string?) (car rand*)) + ((check op nonnegative-fixnum?) (cadr rand*)))] + [($symbol-string $symbol-unique-string) + (andmap (check op symbol?) rand*)] + [($constant-ref $set-constant! $intern $pcb-set! $pcb-ref $make-symbol + $symbol-value $set-symbol-value! $symbol-plist $set-symbol-plist! + $set-symbol-system-value! $set-symbol-system-value! + $set-symbol-unique-string! + $set-symbol-string! + $seal-frame-and-call $frame->continuation $code->closure + $code-instr-size $code-reloc-size $code-closure-size + $set-code-byte! $set-code-word! + $set-code-object! $set-code-object+offset! $set-code-object+offset/rel! + $make-record $record? $record-rtd $record-ref $record-set! + primitive-set! primitive-ref + $make-tcbucket $tcbucket-key $tcbucket-val $tcbucket-next + $set-tcbucket-val! $set-tcbucket-next! $set-tcbucket-tconc!) + #t] + [else (error 'valid-arg-types? "unhandled op ~s" op)])) + (and (valid-arg-count? op rand*) + (or (null? rand*) + (valid-arg-types? op rand*)))) + + +;;; the output of simplify-operands differs from the input in that the +;;; operands to primcalls are all simple (variables, primrefs, or constants). +;;; funcalls to open-codable primrefs whos arguments are "ok" are converted to +;;; primcalls. + +(define (introduce-primcalls x) + (define who 'introduce-primcalls) + (define (simple? x) + (or (constant? x) (var? x) (primref? x))) + (define (Expr x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(closure) x] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (make-seq (Expr e0) (Expr e1))] + [(primcall op arg*) + (case op + ;[(values) + ; (if (fx= (length arg*) 1) + ; (Expr (car arg*)) + ; (begin + ; (warning 'compile "possible incorrect number of values") + ; (make-funcall (make-primref 'values) (map Expr arg*))))] + [else + (make-primcall op (map Expr arg*))])] + [(forcall op arg*) + (make-forcall op (map Expr arg*))] + [(funcall rator rand*) + (cond + [(and (primref? rator) + (open-codeable? (primref-name rator)) + (syntactically-valid? (primref-name rator) rand*)) + (Expr (make-primcall (primref-name rator) rand*))] + [else + (make-funcall (Expr rator) (map Expr rand*))])] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (Tail x) + (record-case x + [(constant) (make-return x)] + [(var) (make-return x)] + [(primref) (make-return x)] + [(closure) (make-return x)] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Tail body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Tail conseq) (Tail altern))] + [(seq e0 e1) (make-seq (Expr e0) (Tail e1))] + [(primcall op arg*) + (case op + ;[(values) + ; (if (fx= (length arg*) 1) + ; (make-return (Expr (car arg*))) + ; (make-return* (map Expr arg*)))] + [else + (make-return (make-primcall op (map Expr arg*)))])] + [(forcall op arg*) + (make-return (make-forcall op (map Expr arg*)))] + [(funcall rator rand*) + (cond + [(and (primref? rator) + (open-codeable? (primref-name rator)) + (syntactically-valid? (primref-name rator) rand*)) + (Tail (make-primcall (primref-name rator) rand*))] + [else + (make-funcall (Expr rator) (map Expr rand*))])] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (CaseExpr x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (Tail body))])) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (make-clambda-code L (map CaseExpr cases) free)])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) (Tail body))])) + (CodesExpr x)) + + +(define (simplify-operands x) + (define who 'simplify-operands) + (define (simple? x) + (or (constant? x) (var? x) (primref? x))) + (define (simplify arg lhs* rhs* k) + (if (simple? arg) + (k arg lhs* rhs*) + (let ([v (unique-var 'tmp)]) + (k v (cons v lhs*) (cons (Expr arg) rhs*))))) + (define (simplify* arg* lhs* rhs* k) + (cond + [(null? arg*) (k '() lhs* rhs*)] + [else + (simplify (car arg*) lhs* rhs* + (lambda (a lhs* rhs*) + (simplify* (cdr arg*) lhs* rhs* + (lambda (d lhs* rhs*) + (k (cons a d) lhs* rhs*)))))])) + (define (Expr x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(closure) x] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (make-seq (Expr e0) (Expr e1))] + [(primcall op arg*) + (simplify* arg* '() '() + (lambda (arg* lhs* rhs*) + (make-bind^ lhs* rhs* + (make-primcall op arg*))))] + [(forcall op arg*) + (make-forcall op (map Expr arg*))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (Tail x) + (record-case x + [(return v) (make-return (Expr v))] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Tail body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Tail conseq) (Tail altern))] + [(seq e0 e1) (make-seq (Expr e0) (Tail e1))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (CaseExpr x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (Tail body))])) + (define (CodeExpr x) + (record-case x + [(clambda-code L clauses free) + (make-clambda-code L (map CaseExpr clauses) free)])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) (Tail body))])) + (CodesExpr x)) + + +(define (insert-stack-overflow-checks x) + (define who 'insert-stack-overflow-checks) + (define (insert-check body) + (make-seq + (make-conditional + (make-primcall '$fp-overflow '()) + (make-funcall (make-primref 'do-stack-overflow) '()) + (make-primcall 'void '())) + body)) + (define (Expr x) + (record-case x + [(constant) #f] + [(var) #f] + [(primref) #f] + [(closure code free*) #f] + [(bind lhs* rhs* body) + (or (ormap Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (or (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (or (Expr e0) (Expr e1))] + [(primcall op arg*) (ormap Expr arg*)] + [(forcall op arg*) (ormap Expr arg*)] + [(funcall rator arg*) #t] + [(appcall rator arg*) #t] + [else (error who "invalid expression ~s" (unparse x))])) + (define (Tail x) + (record-case x + [(return v) (Expr v)] + [(bind lhs* rhs* body) + (or (ormap Expr rhs*) (Tail body))] + [(conditional test conseq altern) + (or (Expr test) (Tail conseq) (Tail altern))] + [(seq e0 e1) (or (Expr e0) (Tail e1))] + [(funcall rator arg*) (or (Expr rator) (ormap Expr arg*))] + [(appcall rator arg*) (or (Expr rator) (ormap Expr arg*))] + [else (error who "invalid tail expression ~s" (unparse x))])) + (define (CaseExpr x) + (record-case x + [(clambda-case fml* proper body) + (if (Tail body) + (make-clambda-case fml* proper (insert-check body)) + x)])) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (make-clambda-code L (map CaseExpr cases) free)])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) + (if (Tail body) + (insert-check body) + body))])) + (CodesExpr x)) + + +(define (insert-allocation-checks x) + (define who 'insert-allocation-checks) + (define (check-bytes n var body) + (make-seq + (make-conditional + (make-primcall '$ap-check-bytes + (list (make-constant n) var)) + (make-funcall (make-primref 'do-overflow) + (list + (make-primcall '$fx+ + (list (make-constant n) var)))) + (make-primcall 'void '())) + body)) + (define (check-words n var body) + (make-seq + (make-conditional + (make-primcall '$ap-check-words + (list (make-constant n) var)) + (make-funcall (make-primref 'do-overflow-words) + (list + (make-primcall '$fx+ + (list (make-constant n) var)))) + (make-primcall 'void '())) + body)) + (define (check-const n body) + (make-seq + (make-conditional + (make-primcall '$ap-check-const + (list (make-constant n))) + (make-funcall (make-primref 'do-overflow) + (list (make-constant n))) + (make-primcall 'void '())) + body)) + (define (Expr x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(closure code free*) + (check-const (fx+ disp-closure-data (fx* (length free*) wordsize)) x)] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (make-seq (Expr e0) (Expr e1))] + [(primcall op arg*) + (let ([x (make-primcall op (map Expr arg*))]) + (case op + [(cons) (check-const pair-size x)] + [($make-symbol) (check-const symbol-size x)] + [($make-tcbucket) (check-const tcbucket-size x)] + [($frame->continuation $code->closure) + (check-const (fx+ disp-closure-data (fx* (length arg*) wordsize)) x)] + [($make-string) + (record-case (car arg*) + [(constant i) + (check-const (fx+ i (fx+ disp-string-data 1)) x)] + [else + (check-bytes (fxadd1 disp-string-data) (car arg*) x)])] + [($string) + (check-const (fx+ (length arg*) (fx+ disp-string-data 1)) x)] + [($make-vector) + (record-case (car arg*) + [(constant i) + (check-const (fx+ (fx* i wordsize) disp-vector-data) x)] + [else + (check-words (fxadd1 disp-vector-data) (car arg*) x)])] + [($make-record) + (record-case (cadr arg*) + [(constant i) + (check-const (fx+ (fx* i wordsize) disp-record-data) x)] + [else + (check-words (fxadd1 disp-record-data) (cadr arg*) x)])] + [(vector) + (check-const (fx+ (fx* (length arg*) wordsize) disp-vector-data) x)] + [else x]))] + [(forcall op arg*) + (make-forcall op (map Expr arg*))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (Tail x) + (record-case x + [(return v) (make-return (Expr v))] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Tail body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Tail conseq) (Tail altern))] + [(seq e0 e1) (make-seq (Expr e0) (Tail e1))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (CaseExpr x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (Tail body))])) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (make-clambda-code L (map CaseExpr cases) free)])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) (Tail body))])) + (CodesExpr x)) + + +(define (remove-local-variables x) + (define who 'remove-local-variables) + (define (simple* x* r) + (map (lambda (x) + (cond + [(assq x r) => cdr] + [else + (when (var? x) (error who "unbound var ~s" x)) + x])) + x*)) + (define (env->mask r sz) + (let ([s (make-vector (fxsra (fx+ sz 7) 3) 0)]) + (for-each + (lambda (idx) + (let ([q (fxsra idx 3)] + [r (fxlogand idx 7)]) + (vector-set! s q + (fxlogor (vector-ref s q) (fxsll 1 r))))) + r) + s)) + (define (do-new-frame op rand* si r call-convention rp-convention orig-live) + (make-new-frame (fxadd1 si) (fx+ (length rand*) 2) + (let f ([r* rand*] [nsi (fx+ si 2)] [live orig-live]) + (cond + [(null? r*) + (make-seq + (make-seq + (make-save-cp (make-frame-var si)) + (case call-convention + [(normal apply) + (make-eval-cp #t (Expr op nsi r (cons si live)))] + [(foreign) + (make-eval-cp #f (make-foreign-label op))] + [else (error who "invalid convention ~s" convention)])) + (make-call-cp call-convention + rp-convention + (fxadd1 si) ; frame size + (length rand*) ; argc + (env->mask (cons si orig-live) ; cp and everything before it + (fxadd1 si))))] ; mask-size ~~ frame size + [else + (make-seq + (make-assign (make-frame-var nsi) + (Expr (car r*) nsi r live)) + (f (cdr r*) (fxadd1 nsi) (cons nsi live)))])))) + (define (nop) (make-primcall 'void '())) + (define (do-bind lhs* rhs* body si r live k) + (let f ([lhs* lhs*] [rhs* rhs*] [si si] [nr r] [live live]) + (cond + [(null? lhs*) (k body si nr live)] + [else + (let ([v (make-frame-var si)]) + (make-seq + (make-assign v (Expr (car rhs*) si r live)) + (f (cdr lhs*) (cdr rhs*) (fxadd1 si) + (cons (cons (car lhs*) v) nr) + (cons si live))))]))) + (define (Tail x si r live) + (record-case x + [(return v) (make-return (Expr v si r live))] + [(bind lhs* rhs* body) + (do-bind lhs* rhs* body si r live Tail)] + [(conditional test conseq altern) + (make-conditional + (Expr test si r live) + (Tail conseq si r live) + (Tail altern si r live))] + [(seq e0 e1) (make-seq (Effect e0 si r live) (Tail e1 si r live))] + [(primcall op arg*) + (case op +; [(values) (make-primcall op (simple* arg* r))] + [else (make-return (make-primcall op (simple* arg* r)))])] + [(funcall op rand*) + (do-new-frame op rand* si r 'normal 'tail live)] + [(appcall op rand*) + (do-new-frame op rand* si r 'apply 'tail live)] + [else (error who "invalid expression ~s" (unparse x))])) + (define (Effect x si r live) + (record-case x + [(constant) (nop)] + [(var) (nop)] + [(primref) (nop)] + [(closure code free*) (nop)] + [(bind lhs* rhs* body) + (do-bind lhs* rhs* body si r live Effect)] + [(conditional test conseq altern) + (make-conditional + (Expr test si r live) + (Effect conseq si r live) + (Effect altern si r live))] + [(seq e0 e1) (make-seq (Effect e0 si r live) (Effect e1 si r live))] + [(primcall op arg*) + (make-primcall op (simple* arg* r))] + [(forcall op rand*) + (do-new-frame op rand* si r 'foreign 'effect live)] + [(funcall op rand*) + (do-new-frame op rand* si r 'normal 'effect live)] + [(appcall op rand*) + (do-new-frame op rand* si r 'apply 'effect live)] + [else (error who "invalid effect expression ~s" (unparse x))])) + (define (Expr x si r live) + (record-case x + [(constant) x] + [(var) + (cond + [(assq x r) => cdr] + [else (error who "unbound var ~s" x)])] + [(primref) x] + [(closure code free*) + (make-closure code (simple* free* r))] + [(bind lhs* rhs* body) + (do-bind lhs* rhs* body si r live Expr)] + [(conditional test conseq altern) + (make-conditional + (Expr test si r live) + (Expr conseq si r live) + (Expr altern si r live))] + [(seq e0 e1) (make-seq (Effect e0 si r live) (Expr e1 si r live))] + [(primcall op arg*) + (make-primcall op (simple* arg* r))] + [(forcall op rand*) + (do-new-frame op rand* si r 'foreign 'value live)] + [(funcall op rand*) + (do-new-frame op rand* si r 'normal 'value live)] + [(appcall op rand*) + (do-new-frame op rand* si r 'apply 'value live)] + [else (error who "invalid expression ~s" (unparse x))])) + (define (bind-fml* fml* r) + (let f ([si 1] [fml* fml*]) + (cond + [(null? fml*) (values '() si r '())] + [else + (let-values ([(nfml* nsi r live) (f (fxadd1 si) (cdr fml*))]) + (let ([v (make-frame-var si)]) + (values (cons v nfml*) + nsi + (cons (cons (car fml*) v) r) + (cons si live))))]))) + (define (bind-free* free*) + (let f ([free* free*] [idx 0] [r '()]) + (cond + [(null? free*) r] + [else + (f (cdr free*) (fxadd1 idx) + (cons (cons (car free*) (make-cp-var idx)) r))]))) + (define CaseExpr + (lambda (r) + (lambda (x) + (record-case x + [(clambda-case fml* proper body) + (let-values ([(fml* si r live) (bind-fml* fml* r)]) + (make-clambda-case fml* proper (Tail body si r live)))])))) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (let ([r (bind-free* free)]) + (make-clambda-code L (map (CaseExpr r) cases) free))])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) + (Tail body 1 '() '()))])) + (CodesExpr x)) + + +(begin + (define fx-shift 2) + (define fx-mask #x03) + (define fx-tag 0) + (define bool-f #x2F) + (define bool-t #x3F) + (define bool-mask #xEF) + (define bool-tag bool-f) + (define bool-shift 4) + (define nil #x4F) + (define eof #x5F) ; double check + (define unbound #x6F) ; double check + (define void-object #x7F) ; double check + (define bwp-object #x8F) ; double check + (define char-shift 8) + (define char-tag #x0F) + (define char-mask #xFF) + (define pair-mask 7) + (define pair-tag 1) + (define disp-car 0) + (define disp-cdr 4) + (define pair-size 8) + (define pagesize 4096) + (define pageshift 12) + (define wordsize 4) + (define wordshift 2) + + (define symbol-mask 7) + (define symbol-tag 2) + (define disp-symbol-string 0) + (define disp-symbol-unique-string 4) + (define disp-symbol-value 8) + (define disp-symbol-plist 12) + (define disp-symbol-system-value 16) + (define disp-symbol-system-plist 20) + (define symbol-size 24) + (define vector-tag 5) + (define vector-mask 7) + (define disp-vector-length 0) + (define disp-vector-data 4) + (define string-mask 7) + (define string-tag 6) + (define disp-string-length 0) + (define disp-string-data 4) + (define closure-mask 7) + (define closure-tag 3) + (define disp-closure-data 4) + (define disp-closure-code 0) + (define continuation-size 16) + (define continuation-tag #x1F) + (define disp-continuation-top 4) + (define disp-continuation-size 8) + (define disp-continuation-next 12) + (define code-tag #x2F) + (define disp-code-instrsize 4) + (define disp-code-relocsize 8) + (define disp-code-closuresize 12) + (define disp-code-data 16) + (define disp-tcbucket-tconc 0) + (define disp-tcbucket-key 4) + (define disp-tcbucket-val 8) + (define disp-tcbucket-next 12) + (define tcbucket-size 16) + + (define record-ptag vector-tag) + (define record-pmask vector-mask) + (define disp-record-rtd 0) + (define disp-record-data 4) + (define disp-frame-size -17) + (define disp-frame-offset -13) + (define disp-multivalue-rp -9) + (define object-alignment 8) + (define align-shift 3) + (define pagesize 4096) + (define dirty-word -1)) + +(begin + (define (mem off val) + (cond + [(fixnum? off) (list 'disp (int off) val)] + [(register? off) (list 'disp off val)] + [else (error 'mem "invalid disp ~s" off)])) + (define (int x) (list 'int x)) + (define (obj x) (list 'obj x)) + (define (byte x) (list 'byte x)) + (define (byte-vector x) (list 'byte-vector x)) + (define (movzbl src targ) (list 'movzbl src targ)) + (define (sall src targ) (list 'sall src targ)) + (define (sarl src targ) (list 'sarl src targ)) + (define (shrl src targ) (list 'shrl src targ)) + (define (notl src) (list 'notl src)) + (define (pushl src) (list 'pushl src)) + (define (popl src) (list 'popl src)) + (define (orl src targ) (list 'orl src targ)) + (define (xorl src targ) (list 'xorl src targ)) + (define (andl src targ) (list 'andl src targ)) + (define (movl src targ) (list 'movl src targ)) + (define (movb src targ) (list 'movb src targ)) + (define (addl src targ) (list 'addl src targ)) + (define (imull src targ) (list 'imull src targ)) + (define (idivl src) (list 'idivl src)) + (define (subl src targ) (list 'subl src targ)) + (define (push src) (list 'push src)) + (define (pop targ) (list 'pop targ)) + (define (sete targ) (list 'sete targ)) + (define (call targ) (list 'call targ)) + (define (tail-indirect-cpr-call) + (jmp (mem (fx- disp-closure-code closure-tag) cpr))) + (define (indirect-cpr-call) + (call (mem (fx- disp-closure-code closure-tag) cpr))) + (define (negl targ) (list 'negl targ)) + (define (label x) (list 'label x)) + (define (label-address x) (list 'label-address x)) + (define (ret) '(ret)) + (define (cltd) '(cltd)) + (define (cmpl arg1 arg2) (list 'cmpl arg1 arg2)) + (define (je label) (list 'je label)) + (define (jne label) (list 'jne label)) + (define (jle label) (list 'jle label)) + (define (jge label) (list 'jge label)) + (define (jg label) (list 'jg label)) + (define (jl label) (list 'jl label)) + (define (jb label) (list 'jb label)) + (define (ja label) (list 'ja label)) + (define (jmp label) (list 'jmp label)) + (define edi '%edx) ; closure pointer + (define esi '%esi) ; pcb + (define ebp '%ebp) ; allocation pointer + (define esp '%esp) ; stack base pointer + (define al '%al) + (define ah '%ah) + (define bh '%bh) + (define cl '%cl) + (define eax '%eax) + (define ebx '%ebx) + (define ecx '%ecx) + (define edx '%edx) + (define apr '%ebp) + (define fpr '%esp) + (define cpr '%edi) + (define pcr '%esi) + (define register? symbol?) + (define (argc-convention n) + (fx- 0 (fxsll n fx-shift)))) + + +(define pcb-ref + (lambda (x) + (case x + [(allocation-pointer) (mem 0 pcr)] + [(allocation-redline) (mem 4 pcr)] + [(frame-pointer) (mem 8 pcr)] + [(frame-base) (mem 12 pcr)] + [(frame-redline) (mem 16 pcr)] + [(next-continuation) (mem 20 pcr)] + [(system-stack) (mem 24 pcr)] + [(dirty-vector) (mem 28 pcr)] + [else (error 'pcb-ref "invalid arg ~s" x)]))) + +(define (primref-loc op) + (unless (symbol? op) (error 'primref-loc "not a symbol ~s" op)) + (mem (fx- disp-symbol-system-value symbol-tag) + (obj op))) + +(define (generate-code x) + (define who 'generate-code) + (define (rp-label x) + (case x + [(value) (label-address SL_multiple_values_error_rp)] + [(effect) (label-address SL_multiple_values_ignore_rp)] + [else (error who "invalid rp-convention ~s" x)])) + (define (align n) + (fxsll (fxsra (fx+ n (fxsub1 object-alignment)) align-shift) align-shift)) + (define unique-label + (lambda () + (label (gensym)))) + (define (constant-val x) + (cond + [(fixnum? x) (obj x)] + [(boolean? x) (int (if x bool-t bool-f))] + [(null? x) (int nil)] + [(char? x) (int (fx+ (fxsll (char->integer x) char-shift) char-tag))] + [(eq? x (void)) (int void-object)] + [else (obj x)])) + (define (cond-branch op Lt Lf ac) + (define (opposite x) + (cadr (assq x '([je jne] [jl jge] [jle jg] [jg jle] [jge jl])))) + (unless (or Lt Lf) + (error 'cond-branch "no labels")) + (cond + [(not Lf) (cons (list op Lt) ac)] + [(not Lt) (cons (list (opposite op) Lf) ac)] + [else (list* (list op Lt) (jmp Lf) ac)])) + (define (indirect-type-pred pri-mask pri-tag sec-mask sec-tag rand* Lt Lf ac) + (cond + [(and Lt Lf) + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int pri-mask) ebx) + (cmpl (int pri-tag) ebx) + (jne Lf) + (movl (mem (fx- 0 pri-tag) eax) ebx) + (if sec-mask + (andl (int sec-mask) ebx) + '(nop)) + (cmpl (int sec-tag) ebx) + (jne Lf) + (jmp Lt) + ac)] + [Lf + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int pri-mask) ebx) + (cmpl (int pri-tag) ebx) + (jne Lf) + (movl (mem (fx- 0 pri-tag) eax) ebx) + (if sec-mask + (andl (int sec-mask) ebx) + '(nop)) + (cmpl (int sec-tag) ebx) + (jne Lf) + ac)] + [Lt + (let ([L_END (unique-label)]) + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int pri-mask) ebx) + (cmpl (int pri-tag) ebx) + (jne L_END) + (movl (mem (fx- 0 pri-tag) eax) ebx) + (if sec-mask + (andl (int sec-mask) ebx) + '(nop)) + (cmpl (int sec-tag) ebx) + (je Lt) + L_END + ac))] + [else ac])) + (define (type-pred mask tag rand* Lt Lf ac) + (cond + [mask + (list* + (movl (Simple (car rand*)) eax) + (andl (int mask) eax) + (cmpl (int tag) eax) + (cond-branch 'je Lt Lf ac))] + [else + (let ([v (Simple (car rand*))]) + (cond + [(memq (car v) '(mem register)) + (list* + (cmpl (int tag) (Simple (car rand*))) + (cond-branch 'je Lt Lf ac))] + [else + (list* + (movl (Simple (car rand*)) eax) + (cmpl (int tag) eax) + (cond-branch 'je Lt Lf ac))]))])) + (define (compare-and-branch op rand* Lt Lf ac) + (define (opposite x) + (cadr (assq x '([je je] [jl jg] [jle jge] [jg jl] [jge jle])))) + (cond + [(and (constant? (car rand*)) (constant? (cadr rand*))) + (list* + (movl (Simple (car rand*)) eax) + (cmpl (Simple (cadr rand*)) eax) + (cond-branch op Lt Lf ac))] + [(constant? (cadr rand*)) + (list* + (cmpl (Simple (cadr rand*)) (Simple (car rand*))) + (cond-branch op Lt Lf ac))] + [(constant? (car rand*)) + (list* + (cmpl (Simple (car rand*)) (Simple (cadr rand*))) + (cond-branch (opposite op) Lt Lf ac))] + [else + (list* + (movl (Simple (car rand*)) eax) + (cmpl (Simple (cadr rand*)) eax) + (cond-branch op Lt Lf ac))])) + (define (do-pred-prim op rand* Lt Lf ac) + (case op + [(fixnum?) (type-pred fx-mask fx-tag rand* Lt Lf ac)] + [(pair?) (type-pred pair-mask pair-tag rand* Lt Lf ac)] + [(char?) (type-pred char-mask char-tag rand* Lt Lf ac)] + [(string?) (type-pred string-mask string-tag rand* Lt Lf ac)] + [(symbol?) (type-pred symbol-mask symbol-tag rand* Lt Lf ac)] + [(procedure?) (type-pred closure-mask closure-tag rand* Lt Lf ac)] + [(boolean?) (type-pred bool-mask bool-tag rand* Lt Lf ac)] + [(null?) (type-pred #f nil rand* Lt Lf ac)] + [($unbound-object?) (type-pred #f unbound rand* Lt Lf ac)] + [($forward-ptr?) (type-pred #f -1 rand* Lt Lf ac)] + [(not) (type-pred #f bool-f rand* Lt Lf ac)] + [(eof-object?) (type-pred #f eof rand* Lt Lf ac)] + [(bwp-object?) (type-pred #f bwp-object rand* Lt Lf ac)] + [($fxzero?) (type-pred #f 0 rand* Lt Lf ac)] + [($fx= $char= eq?) (compare-and-branch 'je rand* Lt Lf ac)] + [($fx< $char<) (compare-and-branch 'jl rand* Lt Lf ac)] + [($fx<= $char<=) (compare-and-branch 'jle rand* Lt Lf ac)] + [($fx> $char>) (compare-and-branch 'jg rand* Lt Lf ac)] + [($fx>= $char>=) (compare-and-branch 'jge rand* Lt Lf ac)] + [(vector?) + (indirect-type-pred vector-mask vector-tag fx-mask fx-tag + rand* Lt Lf ac)] + [($record?) + (indirect-type-pred record-pmask record-ptag record-pmask record-ptag + rand* Lt Lf ac)] + [(code?) + (indirect-type-pred vector-mask vector-tag #f code-tag + rand* Lt Lf ac)] + [(immediate?) + (cond + [(and Lt Lf) + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int fx-mask) ebx) + (cmpl (int 0) ebx) + (je Lt) + (andl (int 7) eax) + (cmpl (int 7) eax) + (je Lt) + (jmp Lf) + ac)] + [Lt + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int fx-mask) ebx) + (cmpl (int 0) ebx) + (je Lt) + (andl (int 7) eax) + (cmpl (int 7) eax) + (je Lt) + ac)] + [Lf + (let ([Ljoin (unique-label)]) + (list* + (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int fx-mask) ebx) + (cmpl (int 0) ebx) + (je Ljoin) + (andl (int 7) eax) + (cmpl (int 7) eax) + (jne Lf) + Ljoin + ac))] + [else ac])] + [($ap-check-words) + (record-case (car rand*) + [(constant i) + (list* (movl (pcb-ref 'allocation-redline) eax) + (subl (Simple (cadr rand*)) eax) + (subl (int i) eax) + (cmpl eax apr) + (cond-branch 'jge Lt Lf ac))] + [else (error who "ap-check-words")])] + [($ap-check-bytes) + (record-case (car rand*) + [(constant i) + (list* (movl (Simple (cadr rand*)) eax) + (negl eax) + (addl (pcb-ref 'allocation-redline) eax) + (subl (int i) eax) + (cmpl eax apr) + (cond-branch 'jge Lt Lf ac))] + [else (error who "ap-check-bytes")])] + [($ap-check-const) + (record-case (car rand*) + [(constant i) + (if (fx< i pagesize) + (list* + (cmpl (pcb-ref 'allocation-redline) apr) + (cond-branch 'jge Lt Lf ac)) + (list* + (movl (pcb-ref 'allocation-redline) eax) + (subl (int i) eax) + (cmpl eax apr) + (cond-branch 'jge Lt Lf ac)))] + [else (error who "ap-check-const")])] + [($fp-at-base) + (list* + (movl (pcb-ref 'frame-base) eax) + (subl (int wordsize) eax) + (cmpl eax fpr) + (cond-branch 'je Lt Lf ac))] + [($fp-overflow) + (list* (cmpl (pcb-ref 'frame-redline) fpr) + (cond-branch 'jle Lt Lf ac))] + [($vector-ref) + (do-value-prim op rand* + (do-simple-test eax Lt Lf ac))] + [(cons void $fxadd1 $fxsub1) + ;;; always true + (do-effect-prim op rand* + (cond + [(not Lt) ac] + [else (cons (jmp Lt) ac)]))] + [else + (error 'pred-prim "HERE unhandled ~s" op)])) + (define (do-pred->value-prim op rand* ac) + (case op + [else + (let ([Lf (unique-label)] [Lj (unique-label)]) + (do-pred-prim op rand* #f Lf + (list* (movl (constant-val #t) eax) + (jmp Lj) + Lf + (movl (constant-val #f) eax) + Lj + ac)))])) + (define (indirect-ref arg* off ac) + (list* + (movl (Simple (car arg*)) eax) + (movl (mem off eax) eax) + ac)) + (define (do-value-prim op arg* ac) + (case op + [(eof-object) (cons (movl (int eof) eax) ac)] + [(void) (cons (movl (int void-object) eax) ac)] + [($fxadd1) + (list* (movl (Simple (car arg*)) eax) + (addl (constant-val 1) eax) + ac)] + [($fxsub1) + (list* (movl (Simple (car arg*)) eax) + (addl (constant-val -1) eax) + ac)] + [($fx+) + (list* (movl (Simple (car arg*)) eax) + (addl (Simple (cadr arg*)) eax) + ac)] + [($fx-) + (list* (movl (Simple (car arg*)) eax) + (subl (Simple (cadr arg*)) eax) + ac)] + [($fx*) + (cond + [(constant? (car arg*)) + (record-case (car arg*) + [(constant c) + (unless (fixnum? c) + (error who "invalid arg ~s to fx*" c)) + (list* (movl (Simple (cadr arg*)) eax) + (imull (int c) eax) + ac)])] + [(constant? (cadr arg*)) + (record-case (cadr arg*) + [(constant c) + (unless (fixnum? c) + (error who "invalid arg ~s to fx*" c)) + (list* (movl (Simple (car arg*)) eax) + (imull (int c) eax) + ac)])] + [else + (list* (movl (Simple (car arg*)) eax) + (sarl (int fx-shift) eax) + (imull (Simple (cadr arg*)) eax) + ac)])] + [($fxquotient) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ecx) + (cltd) + (idivl ecx) + (sall (int fx-shift) eax) + ac)] + [($fxmodulo) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl eax ecx) + (xorl ebx ecx) + (sarl (int (fxsub1 (fx* wordsize 8))) ecx) + (andl ebx ecx) + (cltd) + (idivl ebx) + (movl edx eax) + (addl ecx eax) + ac)] + [($fxlogor) + (list* (movl (Simple (car arg*)) eax) + (orl (Simple (cadr arg*)) eax) + ac)] + [($fxlogand) + (list* (movl (Simple (car arg*)) eax) + (andl (Simple (cadr arg*)) eax) + ac)] + [($fxlogxor) + (list* (movl (Simple (car arg*)) eax) + (xorl (Simple (cadr arg*)) eax) + ac)] + [($fxsra) + (record-case (cadr arg*) + [(constant i) + (unless (fixnum? i) (error who "invalid arg to fxsra")) + (list* (movl (Simple (car arg*)) eax) + (sarl (int (fx+ i fx-shift)) eax) + (sall (int fx-shift) eax) + ac)] + [else + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ecx) + (sarl (int fx-shift) ecx) + (sarl (int fx-shift) eax) + (sarl cl eax) + (sall (int fx-shift) eax) + ac)])] + [($fxsll) + (record-case (cadr arg*) + [(constant i) + (unless (fixnum? i) (error who "invalid arg to fxsll")) + (list* (movl (Simple (car arg*)) eax) + (sall (int i) eax) + ac)] + [else + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ecx) + (sarl (int fx-shift) ecx) + (sall cl eax) + ac)])] + [($fixnum->char) + (list* (movl (Simple (car arg*)) eax) + (sall (int (fx- char-shift fx-shift)) eax) + (orl (int char-tag) eax) + ac)] + [($char->fixnum) + (list* (movl (Simple (car arg*)) eax) + (sarl (int (fx- char-shift fx-shift)) eax) + ac)] + [($fxlognot) + (list* (movl (Simple (car arg*)) eax) + (orl (int fx-mask) eax) + (notl eax) + ac)] + [($car) (indirect-ref arg* (fx- disp-car pair-tag) ac)] + [($cdr) (indirect-ref arg* (fx- disp-cdr pair-tag) ac)] + [($vector-length) + (indirect-ref arg* (fx- disp-vector-length vector-tag) ac)] + [($string-length) + (indirect-ref arg* (fx- disp-string-length string-tag) ac)] + [($symbol-string) + (indirect-ref arg* (fx- disp-symbol-string symbol-tag) ac)] + [($symbol-unique-string) + (indirect-ref arg* (fx- disp-symbol-unique-string symbol-tag) ac)] + [($symbol-value) + (indirect-ref arg* (fx- disp-symbol-value symbol-tag) ac)] + [(primitive-ref) + (indirect-ref arg* (fx- disp-symbol-system-value symbol-tag) ac)] + [($tcbucket-key) + (indirect-ref arg* (fx- disp-tcbucket-key vector-tag) ac)] + [($tcbucket-val) + (indirect-ref arg* (fx- disp-tcbucket-val vector-tag) ac)] + [($tcbucket-next) + (indirect-ref arg* (fx- disp-tcbucket-next vector-tag) ac)] + [(pointer-value) + (list* + (movl (Simple (car arg*)) eax) + (sarl (int fx-shift) eax) + (sall (int fx-shift) eax) + ac)] + [($symbol-plist) + (indirect-ref arg* (fx- disp-symbol-plist symbol-tag) ac)] + [($record-rtd) + (indirect-ref arg* (fx- disp-record-rtd record-ptag) ac)] + [($constant-ref) + (list* (movl (Simple (car arg*)) eax) ac)] + [($vector-ref) + (list* (movl (Simple (car arg*)) ebx) + (addl (Simple (cadr arg*)) ebx) + (movl (mem (fx- disp-vector-data vector-tag) ebx) eax) + ac)] + [($record-ref) + (list* (movl (Simple (car arg*)) ebx) + (addl (Simple (cadr arg*)) ebx) + (movl (mem (fx- disp-record-data record-ptag) ebx) eax) + ac)] + [($string-ref) + (list* (movl (Simple (cadr arg*)) ebx) + (sarl (int fx-shift) ebx) + (addl (Simple (car arg*)) ebx) + (movl (int char-tag) eax) + (movb (mem (fx- disp-string-data string-tag) ebx) ah) + ac)] + [($make-string) + (list* (movl (Simple (car arg*)) ebx) + (movl ebx (mem disp-string-length apr)) + (movl apr eax) + (addl (int string-tag) eax) + (sarl (int fx-shift) ebx) + (addl ebx apr) + (movb (int 0) (mem disp-string-data apr)) + (addl (int (fx+ disp-string-data object-alignment)) apr) + (sarl (int align-shift) apr) + (sall (int align-shift) apr) + ac)] + [($make-vector) + (list* (movl (Simple (car arg*)) ebx) + (movl ebx (mem disp-vector-length apr)) + (movl apr eax) + (addl (int vector-tag) eax) + (addl ebx apr) + (addl (int (fx+ disp-vector-data (fxsub1 object-alignment))) apr) + (sarl (int align-shift) apr) + (sall (int align-shift) apr) + ac)] + [($make-record) + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem disp-record-rtd apr)) + (movl apr eax) + (addl (int record-ptag) eax) + (addl (Simple (cadr arg*)) apr) + (addl (int (fx+ disp-record-data (fxsub1 object-alignment))) apr) + (sarl (int align-shift) apr) + (sall (int align-shift) apr) + ac)] + [(cons) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl eax (mem disp-car apr)) + (movl apr eax) + (movl ebx (mem disp-cdr apr)) + (addl (int pair-tag) eax) + (addl (int (align pair-size)) apr) + ac)] + [($make-symbol) + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem disp-symbol-string apr)) + (movl (int 0) (mem disp-symbol-unique-string apr)) + (movl (int unbound) (mem disp-symbol-value apr)) + (movl (int nil) (mem disp-symbol-plist apr)) + (movl (int unbound) (mem disp-symbol-system-value apr)) + (movl (int nil) (mem disp-symbol-system-plist apr)) + (movl apr eax) + (addl (int symbol-tag) eax) + (addl (int (align symbol-size)) apr) + ac)] + [($make-tcbucket) + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem disp-tcbucket-tconc apr)) + (movl (Simple (cadr arg*)) eax) + (movl eax (mem disp-tcbucket-key apr)) + (movl (Simple (caddr arg*)) eax) + (movl eax (mem disp-tcbucket-val apr)) + (movl (Simple (cadddr arg*)) eax) + (movl eax (mem disp-tcbucket-next apr)) + (movl apr eax) + (addl (int vector-tag) eax) + (addl (int (align tcbucket-size)) apr) + ac)] + [(vector) + (let f ([arg* arg*] [idx disp-vector-data]) + (cond + [(null? arg*) + (list* (movl apr eax) + (addl (int vector-tag) eax) + (movl (int (fx- idx disp-vector-data)) + (mem disp-vector-length apr)) + (addl (int (align idx)) apr) + ac)] + [else + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem idx apr)) + (f (cdr arg*) (fx+ idx wordsize)))]))] + [($string) + (let f ([arg* arg*] [idx disp-string-data]) + (cond + [(null? arg*) + (list* (movb (int 0) (mem idx apr)) + (movl apr eax) + (addl (int string-tag) eax) + (movl (int (fx* (fx- idx disp-string-data) wordsize)) + (mem disp-string-length apr)) + (addl (int (align (fxadd1 idx))) apr) + ac)] + [else + (record-case (car arg*) + [(constant c) + (unless (char? c) (error who "invalid arg to string ~s" x)) + (list* (movb (int (char->integer c)) (mem idx apr)) + (f (cdr arg*) (fxadd1 idx)))] + [else + (list* (movl (Simple (car arg*)) ebx) + (movb bh (mem idx apr)) + (f (cdr arg*) (fxadd1 idx)))])]))] + [($current-frame) + (list* (movl (pcb-ref 'next-continuation) eax) + ac)] + [($seal-frame-and-call) + (list* (movl (Simple (car arg*)) cpr) ; proc + (movl (pcb-ref 'frame-base) eax) + ; eax=baseofstack + (movl (mem (fx- 0 wordsize) eax) ebx) ; underflow handler + (movl ebx (mem (fx- 0 wordsize) fpr)) ; set + ; create a new cont record + (movl (int continuation-tag) (mem 0 apr)) + (movl fpr (mem disp-continuation-top apr)) + ; compute the size of the captured frame + (movl eax ebx) + (subl fpr ebx) + (subl (int wordsize) ebx) + ; and store it + (movl ebx (mem disp-continuation-size apr)) + ; load next cont + (movl (pcb-ref 'next-continuation) ebx) + ; and store it + (movl ebx (mem disp-continuation-next apr)) + ; adjust ap + (movl apr eax) + (addl (int vector-tag) eax) + (addl (int continuation-size) apr) + ; store new cont in current-cont + (movl eax (pcb-ref 'next-continuation)) + ; adjust fp + (movl fpr (pcb-ref 'frame-base)) + (subl (int wordsize) fpr) + ; tail-call f + (movl eax (mem (fx- 0 wordsize) fpr)) + (movl (int (argc-convention 1)) eax) + (tail-indirect-cpr-call) + ac)] + [($code-instr-size) + (indirect-ref arg* (fx- disp-code-instrsize vector-tag) + (cons (sall (int fx-shift) eax) ac))] + [($code-reloc-size) + (indirect-ref arg* (fx- disp-code-relocsize vector-tag) ac)] + [($code-closure-size) + (indirect-ref arg* (fx- disp-code-closuresize vector-tag) ac)] + [($set-car! $set-cdr! $vector-set! $string-set! $exit + $set-symbol-value! $set-symbol-plist! + $set-code-byte! $set-code-word! primitive-set! + $set-code-object! $set-code-object+offset! $set-code-object+offset/rel! + $record-set!) + (do-effect-prim op arg* + (cons (movl (int void-object) eax) ac))] + [(fixnum? immediate? $fxzero? boolean? char? pair? vector? string? symbol? + procedure? null? not eof-object? $fx= $fx< $fx<= $fx> $fx>= eq? + $char= $char< $char<= $char> $char>= $unbound-object? code? + $record? bwp-object?) + (do-pred->value-prim op arg* ac)] + [($code->closure) + (list* + (movl (Simple (car arg*)) eax) + (addl (int (fx- disp-code-data vector-tag)) eax) + (movl eax (mem 0 apr)) + (movl apr eax) + (addl (int closure-tag) eax) + (addl (int (align disp-closure-data)) apr) + ac)] + [($frame->continuation) + (NonTail + (make-closure (make-code-loc SL_continuation_code) arg*) + ac)] + [($make-call-with-values-procedure) + (NonTail + (make-closure (make-code-loc SL_call_with_values) arg*) + ac)] + [($make-values-procedure) + (NonTail + (make-closure (make-code-loc SL_values) arg*) + ac)] + [else + (error 'value-prim "unhandled ~s" op)])) + (define (indirect-assignment arg* offset ac) + (list* + (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem offset eax)) + ;;; record side effect + (addl (int offset) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)) + (define (do-effect-prim op arg* ac) + (case op + [($vector-set!) + (list* (movl (Simple (car arg*)) ebx) + (addl (Simple (cadr arg*)) ebx) + (addl (int (fx- disp-vector-data vector-tag)) ebx) + (movl (Simple (caddr arg*)) eax) + (movl eax (mem 0 ebx)) + ;;; record side effect + (shrl (int pageshift) ebx) + (sall (int wordshift) ebx) + (addl (pcb-ref 'dirty-vector) ebx) + (movl (int dirty-word) (mem 0 ebx)) + ac)] + [($string-set!) + (list* (movl (Simple (cadr arg*)) eax) + (sarl (int fx-shift) eax) + (addl (Simple (car arg*)) eax) + (movl (Simple (caddr arg*)) ebx) + (movb bh (mem (fx- disp-string-data string-tag) eax)) + ac)] + [($set-car!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-car pair-tag) eax)) + ;;; record side effect + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($set-cdr!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-cdr pair-tag) eax)) + ;;; record side effect + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($set-tcbucket-key!) + (indirect-assignment arg* (fx- disp-tcbucket-key vector-tag) ac)] + [($set-tcbucket-val!) + (indirect-assignment arg* (fx- disp-tcbucket-val vector-tag) ac)] + [($set-tcbucket-next!) + (indirect-assignment arg* (fx- disp-tcbucket-next vector-tag) ac)] + [($set-tcbucket-tconc!) + (indirect-assignment arg* (fx- disp-tcbucket-tconc vector-tag) ac)] + + [($set-symbol-value!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-symbol-value symbol-tag) eax)) + ;;; record side effect + (addl (int (fx- disp-symbol-value symbol-tag)) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [(primitive-set!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-symbol-system-value symbol-tag) eax)) + ;;; record side effect + (addl (int (fx- disp-symbol-system-value symbol-tag)) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($set-symbol-plist!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-symbol-plist symbol-tag) eax)) + ;;; record side effect + (addl (int (fx- disp-symbol-plist symbol-tag)) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($set-symbol-unique-string!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-symbol-unique-string symbol-tag) eax)) + ;;; record side effect + (addl (int (fx- disp-symbol-unique-string symbol-tag)) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($set-symbol-string!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-symbol-string symbol-tag) eax)) + ;;; record side effect + (addl (int (fx- disp-symbol-string symbol-tag)) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($record-set!) + (list* (movl (Simple (car arg*)) ebx) + (addl (Simple (cadr arg*)) ebx) + (movl (Simple (caddr arg*)) eax) + (addl (int (fx- disp-record-data record-ptag)) ebx) + (movl eax (mem 0 ebx)) + ;;; record side effect + (shrl (int pageshift) ebx) + (sall (int wordshift) ebx) + (addl (pcb-ref 'dirty-vector) ebx) + (movl (int dirty-word) (mem 0 ebx)) + ac)] + [(cons void $fxadd1 $fxsub1) + (let f ([arg* arg*]) + (cond + [(null? arg*) ac] + [else + (Effect (car arg*) (f (cdr arg*)))]))] + [else + (error 'do-effect-prim "unhandled op ~s" op)])) + (define (do-simple-test x Lt Lf ac) + (unless (or Lt Lf) + (error 'Pred "no labels")) + (cond + [(not Lt) + (list* (cmpl (int bool-f) x) (je Lf) ac)] + [(not Lf) + (list* (cmpl (int bool-f) x) (jne Lt) ac)] + [else + (list* (cmpl (int bool-f) x) (je Lf) (jmp Lt) ac)])) + (define (Simple x) + (record-case x + [(cp-var i) + (mem (fx+ (fx* i wordsize) (fx- disp-closure-data closure-tag)) cpr)] + [(frame-var i) (mem (fx* i (fx- 0 wordsize)) fpr)] + [(constant c) (constant-val c)] + [(code-loc label) (label-address label)] + [(primref op) (primref-loc op)] + [else (error 'Simple "what ~s" x)])) + (define (frame-adjustment offset) + (fx* (fxsub1 offset) (fx- 0 wordsize))) + (define (NonTail x ac) + (record-case x + [(constant c) + (cons (movl (constant-val c) eax) ac)] + [(frame-var) + (cons (movl (Simple x) eax) ac)] + [(cp-var) + (cons (movl (Simple x) eax) ac)] + [(foreign-label L) + (cons (movl (list 'foreign-label L) eax) ac)] + [(primref c) + (cons (movl (primref-loc c) eax) ac)] + [(closure label arg*) + (let f ([arg* arg*] [off disp-closure-data]) + (cond + [(null? arg*) + (list* (movl (Simple label) (mem 0 apr)) + (movl apr eax) + (addl (int (align off)) apr) + (addl (int closure-tag) eax) + ac)] + [else + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem off apr)) + (f (cdr arg*) (fx+ off wordsize)))]))] + [(conditional test conseq altern) + (let ([Lj (unique-label)] [Lf (unique-label)]) + (Pred test #f Lf + (NonTail conseq + (list* (jmp Lj) Lf (NonTail altern (cons Lj ac))))))] + [(seq e0 e1) + (Effect e0 (NonTail e1 ac))] + [(primcall op rand*) + (do-value-prim op rand* ac)] + [(new-frame base-idx size body) + (NonTail body ac)] + [(call-cp call-convention rp-convention offset size mask) + (let ([L_CALL (unique-label)]) + (case call-convention + [(normal) + (list* (addl (int (frame-adjustment offset)) fpr) + (movl (int (argc-convention size)) eax) + (jmp L_CALL) + ; NEW FRAME + `(byte-vector ,mask) + `(int ,(fx* offset wordsize)) + `(current-frame-offset) + (rp-label rp-convention) + `(byte 0) ; padding for indirect calls only + `(byte 0) ; direct calls are ok + L_CALL + (indirect-cpr-call) + (movl (mem 0 fpr) cpr) + (subl (int (frame-adjustment offset)) fpr) + ac)] + [(apply) are-we-ever-here? + (list* (addl (int (frame-adjustment offset)) fpr) + (movl (int (argc-convention size)) eax) + (jmp L_CALL) + ; NEW FRAME + (byte-vector mask) + `(int ,(fx* offset wordsize)) + `(current-frame-offset) + (rp-label rp-convention) + L_CALL + (call (label SL_apply)) + (movl (mem 0 fpr) cpr) + (subl (int (frame-adjustment offset)) fpr) + ac)] + [(foreign) + (list* (addl (int (frame-adjustment offset)) fpr) + (movl (int (argc-convention size)) eax) + (movl '(foreign-label "ik_foreign_call") ebx) + (jmp L_CALL) + ; NEW FRAME + (byte-vector mask) + `(int ,(fx* offset wordsize)) + `(current-frame-offset) + (rp-label rp-convention) ; should be 0, since C has 1 rv + '(byte 0) + '(byte 0) + '(byte 0) + L_CALL + (call ebx) + (movl (mem 0 fpr) cpr) + (subl (int (frame-adjustment offset)) fpr) + ac)] + [else (error who "invalid convention ~s for call-cp" convention)]))] + [else (error 'NonTail "invalid expression ~s" x)])) + (define (Pred x Lt Lf ac) + (record-case x + [(frame-var i) + (do-simple-test (idx->frame-loc i) Lt Lf ac)] + [(cp-var i) + (do-simple-test (Simple x) Lt Lf ac)] + [(constant c) + (if c + (if Lt (cons (jmp Lt) ac) ac) + (if Lf (cons (jmp Lf) ac) ac))] + [(primcall op rand*) + (do-pred-prim op rand* Lt Lf ac)] + [(conditional test conseq altern) + (cond + [(not Lt) + (let ([Lj^ (unique-label)] [Lf^ (unique-label)]) + (Pred test #f Lf^ + (Pred conseq Lj^ Lf + (cons Lf^ + (Pred altern #f Lf + (cons Lj^ ac))))))] + [(not Lf) + (let ([Lj^ (unique-label)] [Lf^ (unique-label)]) + (Pred test #f Lf^ + (Pred conseq Lt Lj^ + (cons Lf^ + (Pred altern Lt #f + (cons Lj^ ac))))))] + [else + (let ([Lf^ (unique-label)]) + (Pred test #f Lf^ + (Pred conseq Lt Lf + (cons Lf^ + (Pred altern Lt Lf ac)))))])] + [(seq e0 e1) + (Effect e0 (Pred e1 Lt Lf ac))] + [(new-frame) + (NonTail x (do-simple-test eax Lt Lf ac))] + [else (error 'Pred "invalid expression ~s" x)])) + (define (idx->frame-loc i) + (mem (fx* i (fx- 0 wordsize)) fpr)) + (define (Effect x ac) + (record-case x + [(constant) ac] + [(primcall op rand*) + (do-effect-prim op rand* ac)] + [(conditional test conseq altern) + (let ([Lf (unique-label)] [Ljoin (unique-label)]) + (Pred test #f Lf + (Effect conseq + (list* (jmp Ljoin) Lf (Effect altern (cons Ljoin ac))))))] + [(seq e0 e1) + (Effect e0 (Effect e1 ac))] + [(assign loc val) + (record-case loc + [(frame-var i) + (NonTail val + (cons (movl eax (idx->frame-loc i)) ac))] + [else (error who "invalid assign loc ~s" loc)])] + [(eval-cp check body) + (NonTail body + (cond + [check + (list* + (movl eax cpr) + (andl (int closure-mask) eax) + (cmpl (int closure-tag) eax) + (jne (label SL_nonprocedure)) + ac)] + [else + (list* + (movl eax cpr) + ac)]))] + [(save-cp loc) + (record-case loc + [(frame-var i) + (cons (movl cpr (idx->frame-loc i)) ac)] + [else (error who "invalid cpr loc ~s" x)])] + [(new-frame) (NonTail x ac)] + [(frame-var) ac] + [else (error 'Effect "invalid expression ~s" x)])) + (define (Tail x ac) + (record-case x + [(return x) + (NonTail x (cons (ret) ac))] + [(conditional test conseq altern) + (let ([L (unique-label)]) + (Pred test #f L + (Tail conseq + (cons L (Tail altern ac)))))] + [(seq e0 e1) + (Effect e0 (Tail e1 ac))] + [(new-frame idx size body) + (Tail body ac)] + [(call-cp call-convention rp-convention idx argc mask) + (unless (eq? rp-convention 'tail) + (error who "nontail rp (~s) in tail context" rp-convention)) + (let f ([i 0]) + (cond + [(fx= i argc) + (case call-convention + [(normal) + (list* + (movl (int (argc-convention argc)) eax) + (tail-indirect-cpr-call) + ac)] + [(apply) + (list* + (movl (int (argc-convention argc)) eax) + (jmp (label SL_apply)) + ac)] + [else (error who "invalid conv ~s in tail call-cpr" convention)])] + [else + (list* (movl (mem (fx* (fx+ idx (fxadd1 i)) + (fx- 0 wordsize)) fpr) + eax) + (movl eax (mem (fx* (fx+ i 1) (fx- 0 wordsize)) fpr)) + (f (fxadd1 i)))]))] + [else (error 'Tail "invalid expression ~s" x)])) + (define (handle-vararg fml-count ac) + (define CONTINUE_LABEL (unique-label)) + (define DONE_LABEL (unique-label)) + (define CONS_LABEL (unique-label)) + (define LOOP_HEAD (unique-label)) + (define L_CALL (unique-label)) + (list* (cmpl (int (argc-convention (fxsub1 fml-count))) eax) + (jg (label SL_invalid_args)) + (jl CONS_LABEL) + (movl (int nil) ebx) + (jmp DONE_LABEL) + CONS_LABEL + (movl (pcb-ref 'allocation-redline) ebx) + (addl eax ebx) + (addl eax ebx) + (cmpl ebx apr) + (jle LOOP_HEAD) + ; overflow + (addl eax esp) ; advance esp to cover args + (pushl cpr) ; push current cp + (pushl eax) ; push argc + (negl eax) ; make argc positive + (addl (int (fx* 4 wordsize)) eax) ; add 4 words to adjust frame size + (pushl eax) ; push frame size + (addl eax eax) ; double the number of args + (movl eax (mem (fx* -2 wordsize) fpr)) ; pass it as first arg + (movl (int (argc-convention 1)) eax) ; setup argc + (movl (primref-loc 'do-vararg-overflow) cpr) ; load handler + (jmp L_CALL) ; go to overflow handler + ; NEW FRAME + (int 0) ; if the framesize=0, then the framesize is dynamic + '(current-frame-offset) + (int 0) ; multiarg rp + (byte 0) + (byte 0) + L_CALL + (indirect-cpr-call) + (popl eax) ; pop framesize and drop it + (popl eax) ; reload argc + (popl cpr) ; reload cp + (subl eax fpr) ; readjust fp + LOOP_HEAD + (movl (int nil) ebx) + CONTINUE_LABEL + (movl ebx (mem disp-cdr apr)) + (movl (mem fpr eax) ebx) + (movl ebx (mem disp-car apr)) + (movl apr ebx) + (addl (int pair-tag) ebx) + (addl (int pair-size) apr) + (addl (int (fxsll 1 fx-shift)) eax) + (cmpl (int (fx- 0 (fxsll fml-count fx-shift))) eax) + (jle CONTINUE_LABEL) + DONE_LABEL + (movl ebx (mem (fx- 0 (fxsll fml-count fx-shift)) fpr)) + ac)) + (define (Entry check? x ac) + (record-case x + [(clambda-case fml* proper body) + (let ([ac (Tail body ac)]) + (cond + [(and proper check?) + (list* (cmpl (int (argc-convention (length fml*))) eax) + (jne (label SL_invalid_args)) + ac)] + [proper ac] + [else + (handle-vararg (length fml*) ac)]))])) + (define make-dispatcher + (lambda (j? L L* x x* ac) + (cond + [(null? L*) (if j? (cons (jmp (label L)) ac) ac)] + [else + (record-case x + [(clambda-case fml* proper _) + (cond + [proper + (list* (cmpl (int (argc-convention (length fml*))) eax) + (je (label L)) + (make-dispatcher #t + (car L*) (cdr L*) (car x*) (cdr x*) ac))] + [else + (list* (cmpl (int (argc-convention (fxsub1 (length fml*)))) eax) + (jle (label L)) + (make-dispatcher #t + (car L*) (cdr L*) (car x*) (cdr x*) ac))])])]))) + (define (handle-cases x x*) + (let ([L* (map (lambda (_) (gensym)) x*)] + [L (gensym)]) + (make-dispatcher #f L L* x x* + (let f ([x x] [x* x*] [L L] [L* L*]) + (cond + [(null? x*) + (cons (label L) (Entry 'check x '()))] + [else + (cons (label L) + (Entry #f x + (f (car x*) (cdr x*) (car L*) (cdr L*))))]))))) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (list* + (fx+ disp-closure-data (fx* wordsize (length free))) + (label L) + (handle-cases (car cases) (cdr cases)))])) + (record-case x + [(codes list body) + (cons (cons 0 (Tail body '())) + (map CodeExpr list))])) + + +(define SL_nonprocedure (gensym "SL_nonprocedure")) +(define SL_invalid_args (gensym "SL_invalid_args")) +(define SL_foreign_call (gensym "SL_foreign_call")) +(define SL_continuation_code (gensym "SL_continuation_code")) +(define SL_multiple_values_error_rp (gensym "SL_multiple_values_error_rp")) +(define SL_multiple_values_ignore_rp (gensym "SL_multiple_ignore_error_rp")) +(define SL_underflow_multiple_values (gensym "SL_underflow_multiple_values")) +(define SL_underflow_handler (gensym "SL_underflow_handler")) +(define SL_scheme_exit (gensym "SL_scheme_exit")) +(define SL_apply (gensym "SL_apply")) +(define SL_values (gensym "SL_values")) +(define SL_call_with_values (gensym "SL_call_with_values")) + +(list*->code* + (list + (let ([L_cwv_done (gensym)] + [L_cwv_loop (gensym)] + [L_cwv_multi_rp (gensym)] + [L_cwv_call (gensym)]) + (list disp-closure-data + (label SL_call_with_values) + (cmpl (int (argc-convention 2)) eax) + (jne (label SL_invalid_args)) + (movl (mem (fx- 0 wordsize) fpr) ebx) ; producer + (movl ebx cpr) + (andl (int closure-mask) ebx) + (cmpl (int closure-tag) ebx) + (jne (label SL_nonprocedure)) + (movl (int (argc-convention 0)) eax) + (subl (int (fx* wordsize 2)) fpr) + (jmp (label L_cwv_call)) + ; MV NEW FRAME + (byte-vector '#(#b110)) + (int (fx* wordsize 3)) + '(current-frame-offset) + (label-address L_cwv_multi_rp) + (byte 0) + (byte 0) + (label L_cwv_call) + (indirect-cpr-call) + ;;; one value returned + (addl (int (fx* wordsize 2)) fpr) + (movl (mem (fx* -2 wordsize) fpr) ebx) ; consumer + (movl ebx cpr) + (movl eax (mem (fx- 0 wordsize) fpr)) + (movl (int (argc-convention 1)) eax) + (andl (int closure-mask) ebx) + (cmpl (int closure-tag) ebx) + (jne (label SL_nonprocedure)) + (tail-indirect-cpr-call) + ;;; multiple values returned + (label L_cwv_multi_rp) + ; because values does not pop the return point + ; we have to adjust fp one more word here + (addl (int (fx* wordsize 3)) fpr) + (movl (mem (fx* -2 wordsize) fpr) cpr) ; consumer + (cmpl (int (argc-convention 0)) eax) + (je (label L_cwv_done)) + (movl (int (fx* -4 wordsize)) ebx) + (addl fpr ebx) ; ebx points to first value + (movl ebx ecx) + (addl eax ecx) ; ecx points to the last value + (label L_cwv_loop) + (movl (mem 0 ebx) edx) + (movl edx (mem (fx* 3 wordsize) ebx)) + (subl (int wordsize) ebx) + (cmpl ecx ebx) + (jge (label L_cwv_loop)) + (label L_cwv_done) + (movl cpr ebx) + (andl (int closure-mask) ebx) + (cmpl (int closure-tag) ebx) + (jne (label SL_nonprocedure)) + (tail-indirect-cpr-call))) + + (let ([L_values_one_value (gensym)] + [L_values_many_values (gensym)]) + (list disp-closure-data + (label SL_values) + (cmpl (int (argc-convention 1)) eax) + (je (label L_values_one_value)) + (label L_values_many_values) + (movl (mem 0 fpr) ebx) ; return point + (jmp (mem disp-multivalue-rp ebx)) ; go + (label L_values_one_value) + (movl (mem (fx- 0 wordsize) fpr) eax) + (ret))) + + (let ([L_apply_done (gensym)] + [L_apply_loop (gensym)]) + (list 0 + (label SL_apply) + (movl (mem fpr eax) ebx) + (cmpl (int nil) ebx) + (je (label L_apply_done)) + (label L_apply_loop) + (movl (mem (fx- disp-car pair-tag) ebx) ecx) + (movl (mem (fx- disp-cdr pair-tag) ebx) ebx) + (movl ecx (mem fpr eax)) + (subl (int wordsize) eax) + (cmpl (int nil) ebx) + (jne (label L_apply_loop)) + (label L_apply_done) + (addl (int wordsize) eax) + (tail-indirect-cpr-call))) + + (list 0 + (label SL_nonprocedure) + (movl cpr (mem (fx- 0 wordsize) fpr)) ; first arg + (movl (primref-loc '$apply-nonprocedure-error-handler) cpr) + (movl (int (argc-convention 1)) eax) + (tail-indirect-cpr-call)) + + (list 0 + (label SL_multiple_values_error_rp) + (movl (primref-loc '$multiple-values-error) cpr) + (tail-indirect-cpr-call)) + + (list 0 + (label SL_multiple_values_ignore_rp) + (ret)) + + (list 0 + (label SL_invalid_args) + ;;; + (movl cpr (mem (fx- 0 wordsize) fpr)) ; first arg + (negl eax) + (movl eax (mem (fx- 0 (fx* 2 wordsize)) fpr)) + (movl (primref-loc '$incorrect-args-error-handler) cpr) + (movl (int (argc-convention 2)) eax) + (tail-indirect-cpr-call)) + + (let ([Lset (gensym)] [Lloop (gensym)]) + (list 0 + (label SL_foreign_call) + (movl fpr (pcb-ref 'frame-pointer)) + (movl apr (pcb-ref 'allocation-pointer)) + (movl fpr ebx) + (movl (pcb-ref 'system-stack) esp) + (pushl pcr) + (cmpl (int 0) eax) + (je (label Lset)) + (label Lloop) + (movl (mem ebx eax) ecx) + (pushl ecx) + (addl (int 4) eax) + (cmpl (int 0) eax) + (jne (label Lloop)) + (label Lset) + ; FOREIGN NEW FRAME + (call cpr) + (movl (pcb-ref 'frame-pointer) fpr) + (movl (pcb-ref 'allocation-pointer) apr) + (ret))) + + (let ([L_cont_zero_args (gensym)] + [L_cont_mult_args (gensym)] + [L_cont_one_arg (gensym)] + [L_cont_mult_move_args (gensym)] + [L_cont_mult_copy_loop (gensym)]) + (list + (fx+ disp-closure-data wordsize) + (label SL_continuation_code) + (movl (mem (fx- disp-closure-data closure-tag) cpr) ebx) ; captured-k + (movl ebx (pcb-ref 'next-continuation)) ; set + (movl (pcb-ref 'frame-base) ebx) + (cmpl (int (argc-convention 1)) eax) + (jg (label L_cont_zero_args)) + (jl (label L_cont_mult_args)) + (label L_cont_one_arg) + (movl (mem (fx- 0 wordsize) fpr) eax) + (movl ebx fpr) + (subl (int wordsize) fpr) + (ret) + (label L_cont_zero_args) + (subl (int wordsize) ebx) + (movl ebx fpr) + (movl (mem 0 ebx) ebx) ; return point + (jmp (mem disp-multivalue-rp ebx)) ; go + (label L_cont_mult_args) + (subl (int wordsize) ebx) + (cmpl ebx fpr) + (jne (label L_cont_mult_move_args)) + (movl (mem 0 ebx) ebx) + (jmp (mem disp-multivalue-rp ebx)) + (label L_cont_mult_move_args) + ; move args from fpr to ebx + (movl (int 0) ecx) + (label L_cont_mult_copy_loop) + (subl (int wordsize) ecx) + (movl (mem fpr ecx) edx) + (movl edx (mem ebx ecx)) + (cmpl ecx eax) + (jne (label L_cont_mult_copy_loop)) + (movl ebx fpr) + (movl (mem 0 ebx) ebx) + (jmp (mem disp-multivalue-rp ebx)) + )) + )) + + + +(define (compile-program original-program) + (let* (;;; + [p (sc-expand original-program)] + [p (recordize p)] + ;[f (pretty-print (unparse p))] + [p (optimize-direct-calls p)] + [p (remove-assignments p)] + [p (convert-closures p)] + [p (lift-codes p)] + ;[p (lift-complex-constants p)] + [p (introduce-primcalls p)] + [p (simplify-operands p)] + ;[f (pretty-print (unparse p))] + [p (insert-stack-overflow-checks p)] + [p (insert-allocation-checks p)] + [p (remove-local-variables p)] + ;[f (pretty-print (unparse p))] + [ls* (generate-code p)] + [f (when (assembler-output) + (for-each + (lambda (ls) + (for-each (lambda (x) (printf " ~s\n" x)) ls)) + ls*))] + [code* (list*->code* ls*)]) + (fasl-write (car code*) (compile-port)))) + + +(define compile-expr + (lambda (expr output-file) + (let ([op (open-output-file output-file 'replace)]) + (parameterize ([compile-port op]) + (compile-program expr)) + (close-output-port op)))) + +(define compile-file + (lambda (input-file output-file) + (let ([ip (open-input-file input-file)] + [op (open-output-file output-file 'replace)]) + (parameterize ([compile-port op] + [expand-mode 'bootstrap]) + (let f () + (let ([x (read ip)]) + (unless (eof-object? x) + (compile-program x) + (f))))) + (close-input-port ip) + (close-output-port op)))) + + +(parameterize ([assembler-output #f]) + (for-each + (lambda (x) + (printf "compiling ~a ...\n" x) + (compile-file (car x) (cadr x))) + scheme-library-files)) + +(system "rm -f ikarus.fasl") + +(for-each + (lambda (x) + (system (format "cat ~a >> ikarus.fasl" (cadr x)))) + scheme-library-files) + + + +(define replace-safe-prims-with-unsafe + (lambda (x) + (define prims + '([fx+ $fx+] [fx- $fx-] [fx* $fx*] [fxadd1 $fxadd1] [fxsub1 $fxsub1] + [fxlogand $fxlogand] [fxlogor $fxlogor] [fxlognot $fxlognot] + [fx= $fx=] [fx< $fx<] [fx<= $fx<=] [fx> $fx>] [fx>= $fx>=] + [fxzero? $fxzero?] + [fixnum->char $fixnum->char] [char->fixnum $char->fixnum] + [char= $char=] + [char< $char<] [char> $char>] [char<= $char<=] [char>= $char>=] + [car $car] [cdr $cdr] [set-car! $set-car!] [set-cdr! $set-cdr!] + [vector-length $vector-length] [vector-ref $vector-ref] + [vector-set! $vector-set!] [make-vector $make-vector] + [string-length $string-length] [string-ref $string-ref] + [string-set! $string-set!] [make-string $make-string] + )) + (define (E x) + (cond + [(pair? x) (cons (E (car x)) (E (cdr x)))] + [(symbol? x) + (cond + [(assq x prims) => cadr] + [else x])] + [else x])) + (E x))) + +(parameterize ([input-filter + (lambda (x) + `(begin (write (eval ',x)) (newline) (exit 0)))]) + (test-all)) + +(define (get-date) + (system "date +\"%F\" > build-date.tmp") + (let ([ip (open-input-file "build-date.tmp")]) + (list->string + (let f () + (let ([x (read-char ip)]) + (if (char=? x #\newline) + '() + (cons x (f)))))))) + +(compile-expr + `(begin + (display ,(format "Petite Ikarus Scheme (Build ~a)\n" (get-date))) + (display "Copyright (c) 2006 Abdulaziz Ghuloum\n\n") + (new-cafe)) + "petite-ikarus.fasl") diff --git a/src/compiler-6.4.ss b/src/compiler-6.4.ss new file mode 100644 index 0000000..da0089c --- /dev/null +++ b/src/compiler-6.4.ss @@ -0,0 +1,98 @@ + + +;;; 6.2: * side-effects now modify the dirty-vector +;;; * added bwp-object? +;;; * added pointer-value +;;; * added tcbuckets +;;; 6.1: * added case-lambda, dropped lambda +;;; 6.0: * basic compiler + +(when (eq? "" "") + (load "chez-compat.ss") + (set! primitive-ref top-level-value) + (set! primitive-set! set-top-level-value!) + (set! chez-expand sc-expand) + (set! chez-current-expand current-expand) + (set! $base-rtd (eval '#%$base-rtd)) +; (set! $base-rtd #%$base-rtd) + (printf "loading psyntax.pp ...\n") + (load "psyntax-7.1.pp") + (chez-current-expand + (lambda (x . args) + (apply chez-expand (sc-expand x) args))) + (printf "loading psyntax.ss ...\n") + (load "psyntax-7.1.ss") + (chez-current-expand + (lambda (x . args) + (apply chez-expand (sc-expand x) args))) + (printf "ok\n") + (load "libassembler-compat-6.0.ss") ; defines make-code etc. + (load "libintelasm-6.0.ss") ; uses make-code, etc. + (load "libfasl-6.0.ss") ; uses code? etc. + (load "libcompile-6.4.ss") ; uses fasl-write +) + + +(define scheme-library-files + '(["libhandlers-6.0.ss" "libhandlers.fasl"] + ["libcontrol-6.1.ss" "libcontrol.fasl"] + ["libcollect-6.1.ss" "libcollect.fasl"] + ["librecord-6.4.ss" "librecord.fasl"] + ["libcxr-6.0.ss" "libcxr.fasl"] + ["libcore-6.2.ss" "libcore.fasl"] + ["libio-6.1.ss" "libio.fasl"] + ["libwriter-6.2.ss" "libwriter.fasl"] + ["libtokenizer-6.1.ss" "libtokenizer.fasl"] + ["libassembler-compat-6.0.ss" "libassembler-compat.ss"] + ["libintelasm-6.4.ss" "libintelasm.fasl"] + ["libfasl-6.0.ss" "libfasl.fasl"] + ["libcompile-6.4.ss" "libcompile.fasl"] + ["psyntax-7.1.ss" "psyntax.fasl"] + ["libinterpret-6.1.ss" "libinterpret.fasl"] + ["libcafe-6.1.ss" "libcafe.fasl"] +; ["libtrace-5.3.ss" "libtrace-5.3.s" "libtrace" ] + ["libposix-6.0.ss" "libposix.fasl"] + ["libhash-6.2.ss" "libhash.fasl"] + ["libtoplevel-6.0.ss" "libtoplevel.fasl"] + )) + + + +(define (compile-library ifile ofile) + (parameterize ([assembler-output #f] [expand-mode 'bootstrap]) + (printf "compiling ~a ...\n" ifile) + (compile-file ifile ofile 'replace))) + +(for-each + (lambda (x) + (compile-library (car x) (cadr x))) + scheme-library-files) + +(system "rm -f ikarus.fasl") + +(for-each + (lambda (x) + (system (format "cat ~a >> ikarus.fasl" (cadr x)))) + scheme-library-files) + + +(define (get-date) + (system "date +\"%F\" > build-date.tmp") + (let ([ip (open-input-file "build-date.tmp")]) + (list->string + (let f () + (let ([x (read-char ip)]) + (if (char=? x #\newline) + '() + (cons x (f)))))))) + +(with-output-to-file "petite-ikarus.ss" + (lambda () + (write + `(begin + (display ,(format "Petite Ikarus Scheme (Build ~a)\n" (get-date))) + (display "Copyright (c) 2006 Abdulaziz Ghuloum\n\n") + (new-cafe)))) + 'replace) + +(compile-library "petite-ikarus.ss" "petite-ikarus.fasl") diff --git a/src/compiler-6.5.ss b/src/compiler-6.5.ss new file mode 100644 index 0000000..f4dc5e2 --- /dev/null +++ b/src/compiler-6.5.ss @@ -0,0 +1,96 @@ + + +;;; 6.2: * side-effects now modify the dirty-vector +;;; * added bwp-object? +;;; * added pointer-value +;;; * added tcbuckets +;;; 6.1: * added case-lambda, dropped lambda +;;; 6.0: * basic compiler + +(when (eq? "" "") + (load "chez-compat.ss") + (set! primitive-ref top-level-value) + (set! primitive-set! set-top-level-value!) + (set! chez-expand sc-expand) + (set! chez-current-expand current-expand) + (printf "loading psyntax.pp ...\n") + (load "psyntax-7.1.pp") + (chez-current-expand + (lambda (x . args) + (apply chez-expand (sc-expand x) args))) + (printf "loading psyntax.ss ...\n") + (load "psyntax-7.1-6.5.ss") + (chez-current-expand + (lambda (x . args) + (apply chez-expand (sc-expand x) args))) + (printf "ok\n") + (load "libassembler-compat-6.0.ss") ; defines make-code etc. + (load "libintelasm-6.0.ss") ; uses make-code, etc. + (load "libfasl-6.0.ss") ; uses code? etc. + (load "libcompile-6.5.ss") ; uses fasl-write +) + + +(define scheme-library-files + '(["libhandlers-6.0.ss" "libhandlers.fasl"] + ["libcontrol-6.1.ss" "libcontrol.fasl"] + ["libcollect-6.1.ss" "libcollect.fasl"] + ["librecord-6.4.ss" "librecord.fasl"] + ["libcxr-6.0.ss" "libcxr.fasl"] + ["libcore-6.2.ss" "libcore.fasl"] + ["libio-6.1.ss" "libio.fasl"] + ["libwriter-6.2.ss" "libwriter.fasl"] + ["libtokenizer-6.1.ss" "libtokenizer.fasl"] + ["libassembler-compat-6.0.ss" "libassembler-compat.ss"] + ["libintelasm-6.4.ss" "libintelasm.fasl"] + ["libfasl-6.0.ss" "libfasl.fasl"] + ["libcompile-6.5.ss" "libcompile.fasl"] + ["psyntax-7.1-6.5.ss" "psyntax.fasl"] + ["libinterpret-6.5.ss" "libinterpret.fasl"] + ["libcafe-6.1.ss" "libcafe.fasl"] +; ["libtrace-5.3.ss" "libtrace-5.3.s" "libtrace" ] + ["libposix-6.0.ss" "libposix.fasl"] + ["libhash-6.2.ss" "libhash.fasl"] + ["libtoplevel-6.0.ss" "libtoplevel.fasl"] + )) + + + +(define (compile-library ifile ofile) + (parameterize ([assembler-output #f] [expand-mode 'bootstrap]) + (printf "compiling ~a ...\n" ifile) + (compile-file ifile ofile 'replace))) + +(for-each + (lambda (x) + (compile-library (car x) (cadr x))) + scheme-library-files) + +(system "rm -f ikarus.fasl") + +(for-each + (lambda (x) + (system (format "cat ~a >> ikarus.fasl" (cadr x)))) + scheme-library-files) + + +(define (get-date) + (system "date +\"%F\" > build-date.tmp") + (let ([ip (open-input-file "build-date.tmp")]) + (list->string + (let f () + (let ([x (read-char ip)]) + (if (char=? x #\newline) + '() + (cons x (f)))))))) + +(with-output-to-file "petite-ikarus.ss" + (lambda () + (write + `(begin + (display ,(format "Petite Ikarus Scheme (Build ~a)\n" (get-date))) + (display "Copyright (c) 2006 Abdulaziz Ghuloum\n\n") + (new-cafe)))) + 'replace) + +(compile-library "petite-ikarus.ss" "petite-ikarus.fasl") diff --git a/src/compiler-6.6.ss b/src/compiler-6.6.ss new file mode 100644 index 0000000..b83900e --- /dev/null +++ b/src/compiler-6.6.ss @@ -0,0 +1,97 @@ + + +;;; 6.2: * side-effects now modify the dirty-vector +;;; * added bwp-object? +;;; * added pointer-value +;;; * added tcbuckets +;;; 6.1: * added case-lambda, dropped lambda +;;; 6.0: * basic compiler + +(when (eq? "" "") + (load "chez-compat.ss") + (set! primitive-ref top-level-value) + (set! primitive-set! set-top-level-value!) + (set! chez-expand sc-expand) + (set! chez-current-expand current-expand) + (printf "loading psyntax.pp ...\n") + (load "psyntax-7.1.pp") + (chez-current-expand + (lambda (x . args) + (apply chez-expand (sc-expand x) args))) + (printf "loading psyntax.ss ...\n") + (load "psyntax-7.1-6.5.ss") + (chez-current-expand + (lambda (x . args) + (apply chez-expand (sc-expand x) args))) + (printf "ok\n") + (load "libassembler-compat-6.6.ss") ; defines make-code etc. + (load "libintelasm-6.6.ss") ; uses make-code, etc. + (load "libfasl-6.6.ss") ; uses code? etc. + (load "libcompile-6.6.ss") ; uses fasl-write +) + + + +(define scheme-library-files + '(["libhandlers-6.0.ss" "libhandlers.fasl"] + ["libcontrol-6.1.ss" "libcontrol.fasl"] + ["libcollect-6.1.ss" "libcollect.fasl"] + ["librecord-6.4.ss" "librecord.fasl"] + ["libcxr-6.0.ss" "libcxr.fasl"] + ["libcore-6.2.ss" "libcore.fasl"] + ["libio-6.1.ss" "libio.fasl"] + ["libwriter-6.2.ss" "libwriter.fasl"] + ["libtokenizer-6.1.ss" "libtokenizer.fasl"] + ["libassembler-compat-6.6.ss" "libassembler-compat.ss"] + ["libintelasm-6.6.ss" "libintelasm.fasl"] + ["libfasl-6.6.ss" "libfasl.fasl"] + ["libcompile-6.6.ss" "libcompile.fasl"] + ["psyntax-7.1-6.5.ss" "psyntax.fasl"] + ["libinterpret-6.5.ss" "libinterpret.fasl"] + ["libcafe-6.1.ss" "libcafe.fasl"] +; ["libtrace-5.3.ss" "libtrace-5.3.s" "libtrace" ] + ["libposix-6.0.ss" "libposix.fasl"] + ["libhash-6.2.ss" "libhash.fasl"] + ["libtoplevel-6.0.ss" "libtoplevel.fasl"] + )) + + + +(define (compile-library ifile ofile) + (parameterize ([assembler-output #f] [expand-mode 'bootstrap]) + (printf "compiling ~a ...\n" ifile) + (compile-file ifile ofile 'replace))) + +(for-each + (lambda (x) + (compile-library (car x) (cadr x))) + scheme-library-files) + +(system "rm -f ikarus.fasl") + +(for-each + (lambda (x) + (system (format "cat ~a >> ikarus.fasl" (cadr x)))) + scheme-library-files) + + +(define (get-date) + (system "date +\"%F\" > build-date.tmp") + (let ([ip (open-input-file "build-date.tmp")]) + (list->string + (let f () + (let ([x (read-char ip)]) + (if (char=? x #\newline) + '() + (cons x (f)))))))) + +(with-output-to-file "petite-ikarus.ss" + (lambda () + (write + `(begin + (display ,(format "Petite Ikarus Scheme (Build ~a)\n" (get-date))) + (display "Copyright (c) 2006 Abdulaziz Ghuloum\n\n") + (new-cafe)))) + 'replace) + +(compile-library "petite-ikarus.ss" "petite-ikarus.fasl") diff --git a/src/compiler-6.7.ss b/src/compiler-6.7.ss new file mode 100644 index 0000000..b19d43f --- /dev/null +++ b/src/compiler-6.7.ss @@ -0,0 +1,98 @@ + + +;;; 6.2: * side-effects now modify the dirty-vector +;;; * added bwp-object? +;;; * added pointer-value +;;; * added tcbuckets +;;; 6.1: * added case-lambda, dropped lambda +;;; 6.0: * basic compiler + +(when (eq? "" "") + (load "chez-compat.ss") + (set! primitive-ref top-level-value) + (set! primitive-set! set-top-level-value!) + (set! chez-expand sc-expand) + (set! chez-current-expand current-expand) + (printf "loading psyntax.pp ...\n") + (load "psyntax-7.1.pp") + (chez-current-expand + (lambda (x . args) + (apply chez-expand (sc-expand x) args))) + (printf "loading psyntax.ss ...\n") + (load "psyntax-7.1-6.5.ss") + (chez-current-expand + (lambda (x . args) + (apply chez-expand (sc-expand x) args))) + (printf "ok\n") + (load "libassembler-compat-6.7.ss") ; defines make-code etc. + (load "libintelasm-6.6.ss") ; uses make-code, etc. + (load "libfasl-6.7.ss") ; uses code? etc. + (load "libcompile-6.7.ss") ; uses fasl-write +) + + + +(define scheme-library-files + '(["libhandlers-6.0.ss" "libhandlers.fasl"] + ["libcontrol-6.1.ss" "libcontrol.fasl"] + ["libcollect-6.1.ss" "libcollect.fasl"] + ["librecord-6.4.ss" "librecord.fasl"] + ["libcxr-6.0.ss" "libcxr.fasl"] + ["libcore-6.2.ss" "libcore.fasl"] + ["libio-6.1.ss" "libio.fasl"] + ["libwriter-6.2.ss" "libwriter.fasl"] + ["libtokenizer-6.1.ss" "libtokenizer.fasl"] + ["libassembler-6.7.ss" "libassembler.ss"] + ["libintelasm-6.6.ss" "libintelasm.fasl"] + ["libfasl-6.7.ss" "libfasl.fasl"] + ["libcompile-6.7.ss" "libcompile.fasl"] + ["psyntax-7.1-6.5.ss" "psyntax.fasl"] + ["libinterpret-6.5.ss" "libinterpret.fasl"] + ["libcafe-6.1.ss" "libcafe.fasl"] +; ["libtrace-5.3.ss" "libtrace-5.3.s" "libtrace" ] + ["libposix-6.0.ss" "libposix.fasl"] + ["libhash-6.2.ss" "libhash.fasl"] + ["libtoplevel-6.0.ss" "libtoplevel.fasl"] + )) + + + +(define (compile-library ifile ofile) + (parameterize ([assembler-output #f] + [expand-mode 'bootstrap]) + (printf "compiling ~a ...\n" ifile) + (compile-file ifile ofile 'replace))) + +(for-each + (lambda (x) + (compile-library (car x) (cadr x))) + scheme-library-files) + +(system "rm -f ikarus.fasl") + +(for-each + (lambda (x) + (system (format "cat ~a >> ikarus.fasl" (cadr x)))) + scheme-library-files) + + +(define (get-date) + (system "date +\"%F\" > build-date.tmp") + (let ([ip (open-input-file "build-date.tmp")]) + (list->string + (let f () + (let ([x (read-char ip)]) + (if (char=? x #\newline) + '() + (cons x (f)))))))) + +(with-output-to-file "petite-ikarus.ss" + (lambda () + (write + `(begin + (display ,(format "Petite Ikarus Scheme (Build ~a)\n" (get-date))) + (display "Copyright (c) 2006 Abdulaziz Ghuloum\n\n") + (new-cafe)))) + 'replace) + +(compile-library "petite-ikarus.ss" "petite-ikarus.fasl") diff --git a/src/compiler-6.8.ss b/src/compiler-6.8.ss new file mode 100644 index 0000000..e12cfaa --- /dev/null +++ b/src/compiler-6.8.ss @@ -0,0 +1,98 @@ + + +;;; 6.2: * side-effects now modify the dirty-vector +;;; * added bwp-object? +;;; * added pointer-value +;;; * added tcbuckets +;;; 6.1: * added case-lambda, dropped lambda +;;; 6.0: * basic compiler + +(when (eq? "" "") + (load "chez-compat.ss") + (set! primitive-ref top-level-value) + (set! primitive-set! set-top-level-value!) + (set! chez-expand sc-expand) + (set! chez-current-expand current-expand) + (printf "loading psyntax.pp ...\n") + (load "psyntax-7.1.pp") + (chez-current-expand + (lambda (x . args) + (apply chez-expand (sc-expand x) args))) + (printf "loading psyntax.ss ...\n") + (load "psyntax-7.1-6.5.ss") + (chez-current-expand + (lambda (x . args) + (apply chez-expand (sc-expand x) args))) + (printf "ok\n") + (load "libassembler-compat-6.7.ss") ; defines make-code etc. + (load "libintelasm-6.6.ss") ; uses make-code, etc. + (load "libfasl-6.7.ss") ; uses code? etc. + (load "libcompile-6.7.ss") ; uses fasl-write +) + + + +(define scheme-library-files + '(["libhandlers-6.0.ss" "libhandlers.fasl"] + ["libcontrol-6.1.ss" "libcontrol.fasl"] + ["libcollect-6.1.ss" "libcollect.fasl"] + ["librecord-6.4.ss" "librecord.fasl"] + ["libcxr-6.0.ss" "libcxr.fasl"] + ["libcore-6.2.ss" "libcore.fasl"] + ["libio-6.1.ss" "libio.fasl"] + ["libwriter-6.2.ss" "libwriter.fasl"] + ["libtokenizer-6.1.ss" "libtokenizer.fasl"] + ["libassembler-6.7.ss" "libassembler.ss"] + ["libintelasm-6.6.ss" "libintelasm.fasl"] + ["libfasl-6.7.ss" "libfasl.fasl"] + ["libcompile-6.7.ss" "libcompile.fasl"] + ["psyntax-7.1-6.8.ss" "psyntax.fasl"] + ["libinterpret-6.5.ss" "libinterpret.fasl"] + ["libcafe-6.1.ss" "libcafe.fasl"] +; ["libtrace-5.3.ss" "libtrace-5.3.s" "libtrace" ] + ["libposix-6.0.ss" "libposix.fasl"] + ["libhash-6.2.ss" "libhash.fasl"] + ["libtoplevel-6.0.ss" "libtoplevel.fasl"] + )) + + + +(define (compile-library ifile ofile) + (parameterize ([assembler-output #f] + [expand-mode 'bootstrap]) + (printf "compiling ~a ...\n" ifile) + (compile-file ifile ofile 'replace))) + +(for-each + (lambda (x) + (compile-library (car x) (cadr x))) + scheme-library-files) + +(system "rm -f ikarus.fasl") + +(for-each + (lambda (x) + (system (format "cat ~a >> ikarus.fasl" (cadr x)))) + scheme-library-files) + + +(define (get-date) + (system "date +\"%F\" > build-date.tmp") + (let ([ip (open-input-file "build-date.tmp")]) + (list->string + (let f () + (let ([x (read-char ip)]) + (if (char=? x #\newline) + '() + (cons x (f)))))))) + +(with-output-to-file "petite-ikarus.ss" + (lambda () + (write + `(begin + (display ,(format "Petite Ikarus Scheme (Build ~a)\n" (get-date))) + (display "Copyright (c) 2006 Abdulaziz Ghuloum\n\n") + (new-cafe)))) + 'replace) + +(compile-library "petite-ikarus.ss" "petite-ikarus.fasl") diff --git a/src/compiler-6.9.ss b/src/compiler-6.9.ss new file mode 100644 index 0000000..2a10256 --- /dev/null +++ b/src/compiler-6.9.ss @@ -0,0 +1,256 @@ + + +;;; +;;; 6.9: * creating a *system* environment +;;; 6.8: * creating a core-primitive form in the expander +;;; 6.2: * side-effects now modify the dirty-vector +;;; * added bwp-object? +;;; * added pointer-value +;;; * added tcbuckets +;;; 6.1: * added case-lambda, dropped lambda +;;; 6.0: * basic compiler + + + + +(define macros + '(|#primitive| lambda case-lambda set! quote begin define if letrec + foreign-call $apply + quasiquote unquote unquote-splicing + define-syntax identifier-syntax let-syntax letrec-syntax + fluid-let-syntax alias meta eval-when with-implicit with-syntax + type-descriptor + syntax-case syntax-rules module $module import $import import-only + syntax quasisyntax unsyntax unsyntax-splicing datum + let let* let-values cond case define-record or and when unless do + include parameterize trace untrace trace-lambda)) + + + +(define public-primitives + '(null? pair? char? fixnum? symbol? gensym? string? vector? list? + boolean? procedure? + not + eof-object eof-object? bwp-object? + void + fx= fx< fx<= fx> fx>= fxzero? + fx+ fx- fx* fxadd1 fxsub1 fxquotient fxremainder fxmodulo + fxsll fxsra fxlognot fxlogor fxlogand fxlogxor + integer->char char->integer + char=? char? char>=? + cons car cdr set-car! set-cdr! + caar cadr cdar cddr + caaar caadr cadar caddr cdaar cdadr cddar cdddr + caaaar caaadr caadar caaddr cadaar cadadr caddar cadddr + cdaaar cdaadr cdadar cdaddr cddaar cddadr cdddar cddddr + list list* make-list length list-ref + append + make-vector vector-ref vector-set! vector-length vector + vector->list list->vector + make-string string-ref string-set! string-length string list->string + uuid + string-append substring + string=? string? string>=? + remprop putprop getprop property-list + apply + map for-each andmap ormap + memq memv assq + eq? equal? + reverse + string->symbol symbol->string oblist + top-level-value set-top-level-value! top-level-bound? + gensym gensym-count gensym-prefix print-gensym + gensym->unique-string + call-with-values values + make-parameter dynamic-wind + output-port? current-output-port standard-output-port console-output-port + open-output-file close-output-port flush-output-port output-port-name + with-output-to-file with-input-from-file + input-port? current-input-port standard-input-port console-input-port + reset-input-port! + open-input-file close-input-port input-port-name + standard-error-port + open-output-string get-output-string + newline write-char peek-char read-char unread-char + display write fasl-write printf format print-error + read-token read + error exit call/cc + current-error-handler + eval current-eval interpret compile compile-file new-cafe load + system + expand sc-expand current-expand expand-mode + environment? interaction-environment + identifier? free-identifier=? bound-identifier=? literal-identifier=? + datum->syntax-object syntax-object->datum syntax-error + syntax->list + generate-temporaries + record? record-set! record-ref record-length + record-type-descriptor make-record-type + record-printer record-name record-field-accessor + record-field-mutator record-predicate record-constructor + record-type-name record-type-symbol record-type-field-names + hash-table? make-hash-table get-hash-table put-hash-table! + assembler-output + $make-environment + features + )) + +(define system-primitives + '(immediate? $unbound-object? $forward-ptr? + pointer-value + primitive-ref primitive-set! + $fx= $fx< $fx<= $fx> $fx>= $fxzero? + $fx+ $fx- $fx* $fxadd1 $fxsub1 $fxquotient $fxremainder $fxmodulo + $fxsll $fxsra $fxlognot $fxlogor $fxlogand $fxlogxor + $fixnum->char $char->fixnum + $char= $char< $char<= $char> $char>= + $car $cdr $set-car! $set-cdr! + $make-vector $vector-ref $vector-set! $vector-length + $make-string $string-ref $string-set! $string-length $string + $symbol-string $symbol-unique-string $symbol-value + $set-symbol-string! $set-symbol-unique-string! $set-symbol-value! + $make-symbol $set-symbol-plist! $symbol-plist + $sc-put-cte + $record? $record/rtd? $record-set! $record-ref $record-rtd + $make-record $record + $base-rtd + $code? $code-reloc-vector $code-freevars $code-size $code-ref $code-set! + $code->closure list*->code* + make-code code? set-code-reloc-vector! code-reloc-vector code-freevars + code-size code-ref code-set! + $frame->continuation $fp-at-base $current-frame $seal-frame-and-call + $make-call-with-values-procedure $make-values-procedure + do-overflow collect + $make-tcbucket $tcbucket-next $tcbucket-key $tcbucket-val + $set-tcbucket-next! $set-tcbucket-val! $set-tcbucket-tconc! + call/cf trace-symbol! untrace-symbol! make-traced-procedure + fixnum->string date-string + vector-memq vector-memv + )) + + + +(define (whack-system-env setenv?) + (define add-prim + (lambda (x) + (let ([g (gensym (symbol->string x))]) + (putprop x '|#system| g) + (putprop g '*sc-expander* (cons 'core-primitive x))))) + (define add-macro + (lambda (x) + (let ([g (gensym (symbol->string x))] + [e (getprop x '*sc-expander*)]) + (when e + (putprop x '|#system| g) + (putprop g '*sc-expander* e))))) + (define (foo) + (eval + `(begin + (define-syntax compile-time-date-string + (lambda (x) + #'(quote ,(#%date-string)))) + (define-syntax public-primitives + (lambda (x) + #'(quote ,public-primitives))) + (define-syntax system-primitives + (lambda (x) + #'(quote ,system-primitives))) + (define-syntax macros + (lambda (x) + #'(quote ,macros)))))) + (set! system-env ($make-environment '|#system| #t)) + (for-each add-macro macros) + (for-each add-prim public-primitives) + (for-each add-prim system-primitives) + (if setenv? + (parameterize ([interaction-environment system-env]) + (foo)) + (foo))) + + + +(when (eq? "" "") + (load "chez-compat.ss") + (set! primitive-ref top-level-value) + (set! primitive-set! set-top-level-value!) + (set! chez-expand sc-expand) + (set! chez-current-expand current-expand) + (printf "loading psyntax.pp ...\n") + (load "psyntax-7.1.pp") + (chez-current-expand + (lambda (x . args) + (apply chez-expand (sc-expand x) args))) + (whack-system-env #f) + (printf "loading psyntax.ss ...\n") + (load "psyntax-7.1-6.9.ss") + (chez-current-expand + (lambda (x . args) + (apply chez-expand (sc-expand x) args))) + (whack-system-env #t) + (printf "ok\n") + (load "libassembler-compat-6.7.ss") ; defines make-code etc. + (load "libintelasm-6.6.ss") ; uses make-code, etc. + (load "libfasl-6.7.ss") ; uses code? etc. + (load "libcompile-6.7.ss") ; uses fasl-write +) + + +(whack-system-env #t) + +(define scheme-library-files + '(["libhandlers-6.9.ss" "libhandlers.fasl"] + ["libcontrol-6.1.ss" "libcontrol.fasl"] + ["libcollect-6.1.ss" "libcollect.fasl"] + ["librecord-6.4.ss" "librecord.fasl"] + ["libcxr-6.0.ss" "libcxr.fasl"] + ["libcore-6.9.ss" "libcore.fasl"] + ["libio-6.9.ss" "libio.fasl"] + ["libwriter-6.2.ss" "libwriter.fasl"] + ["libtokenizer-6.1.ss" "libtokenizer.fasl"] + ["libassembler-6.7.ss" "libassembler.ss"] + ["libintelasm-6.9.ss" "libintelasm.fasl"] + ["libfasl-6.7.ss" "libfasl.fasl"] + ["libcompile-6.7.ss" "libcompile.fasl"] + ["psyntax-7.1-6.9.ss" "psyntax.fasl"] + ["libinterpret-6.5.ss" "libinterpret.fasl"] + ["libcafe-6.1.ss" "libcafe.fasl"] + ["libtrace-6.9.ss" "libtrace.fasl"] + ["libposix-6.0.ss" "libposix.fasl"] + ["libhash-6.2.ss" "libhash.fasl"] + ["libtoplevel-6.9.ss" "libtoplevel.fasl"] + )) + + + +(define (compile-library ifile ofile) + (parameterize ([assembler-output #f] + [expand-mode 'bootstrap] + [interaction-environment system-env]) + (printf "compiling ~a ...\n" ifile) + (compile-file ifile ofile 'replace))) + +(for-each + (lambda (x) + (compile-library (car x) (cadr x))) + scheme-library-files) + + +(define (join s ls) + (cond + [(null? ls) ""] + [else + (let ([str (open-output-string)]) + (let f ([a (car ls)] [d (cdr ls)]) + (cond + [(null? d) + (display a str) + (get-output-string str)] + [else + (display a str) + (display s str) + (f (car d) (cdr d))])))])) + + +(system + (format "cat ~a > ikarus.fasl" + (join " " (map cadr scheme-library-files)))) diff --git a/src/compiler-8.0.ss b/src/compiler-8.0.ss new file mode 100644 index 0000000..bb1a651 --- /dev/null +++ b/src/compiler-8.0.ss @@ -0,0 +1,261 @@ + + +;;; +;;; 6.9: * creating a *system* environment +;;; 6.8: * creating a core-primitive form in the expander +;;; 6.2: * side-effects now modify the dirty-vector +;;; * added bwp-object? +;;; * added pointer-value +;;; * added tcbuckets +;;; 6.1: * added case-lambda, dropped lambda +;;; 6.0: * basic compiler + + + + +(define macros + '(|#primitive| lambda case-lambda set! quote begin define if letrec + foreign-call $apply + quasiquote unquote unquote-splicing + define-syntax identifier-syntax let-syntax letrec-syntax + fluid-let-syntax alias meta eval-when with-implicit with-syntax + type-descriptor + syntax-case syntax-rules module $module import $import import-only + syntax quasisyntax unsyntax unsyntax-splicing datum + let let* let-values cond case define-record or and when unless do + include parameterize trace untrace trace-lambda)) + + + +(define public-primitives + '(null? pair? char? fixnum? symbol? gensym? string? vector? list? + boolean? procedure? + not + eof-object eof-object? bwp-object? + void + fx= fx< fx<= fx> fx>= fxzero? + fx+ fx- fx* fxadd1 fxsub1 fxquotient fxremainder fxmodulo + fxsll fxsra fxlognot fxlogor fxlogand fxlogxor + integer->char char->integer + char=? char? char>=? + cons car cdr set-car! set-cdr! + caar cadr cdar cddr + caaar caadr cadar caddr cdaar cdadr cddar cdddr + caaaar caaadr caadar caaddr cadaar cadadr caddar cadddr + cdaaar cdaadr cdadar cdaddr cddaar cddadr cdddar cddddr + list list* make-list length list-ref + append + make-vector vector-ref vector-set! vector-length vector + vector->list list->vector + make-string string-ref string-set! string-length string list->string + uuid + string-append substring + string=? string? string>=? + remprop putprop getprop property-list + apply + map for-each andmap ormap + memq memv assq + eq? equal? + reverse + string->symbol symbol->string oblist + top-level-value set-top-level-value! top-level-bound? + gensym gensym-count gensym-prefix print-gensym + gensym->unique-string + call-with-values values + make-parameter dynamic-wind + output-port? current-output-port standard-output-port console-output-port + open-output-file close-output-port flush-output-port output-port-name + with-output-to-file with-input-from-file + input-port? current-input-port standard-input-port console-input-port + reset-input-port! + open-input-file close-input-port input-port-name + standard-error-port + open-output-string get-output-string + newline write-char peek-char read-char unread-char + display write fasl-write printf format print-error + read-token read + error exit call/cc + current-error-handler + eval current-eval interpret compile compile-file new-cafe load + system + expand sc-expand current-expand expand-mode + environment? interaction-environment + identifier? free-identifier=? bound-identifier=? literal-identifier=? + datum->syntax-object syntax-object->datum syntax-error + syntax->list + generate-temporaries + record? record-set! record-ref record-length + record-type-descriptor make-record-type + record-printer record-name record-field-accessor + record-field-mutator record-predicate record-constructor + record-type-name record-type-symbol record-type-field-names + hash-table? make-hash-table get-hash-table put-hash-table! + assembler-output + $make-environment + features + )) + +(define system-primitives + '(immediate? $unbound-object? $forward-ptr? + pointer-value + primitive-ref primitive-set! + $fx= $fx< $fx<= $fx> $fx>= $fxzero? + $fx+ $fx- $fx* $fxadd1 $fxsub1 $fxquotient $fxremainder $fxmodulo + $fxsll $fxsra $fxlognot $fxlogor $fxlogand $fxlogxor + $fixnum->char $char->fixnum + $char= $char< $char<= $char> $char>= + $car $cdr $set-car! $set-cdr! + $make-vector $vector-ref $vector-set! $vector-length + $make-string $string-ref $string-set! $string-length $string + $symbol-string $symbol-unique-string $symbol-value + $set-symbol-string! $set-symbol-unique-string! $set-symbol-value! + $make-symbol $set-symbol-plist! $symbol-plist + $sc-put-cte + $record? $record/rtd? $record-set! $record-ref $record-rtd + $make-record $record + $base-rtd + $code? $code-reloc-vector $code-freevars $code-size $code-ref $code-set! + $code->closure list*->code* + make-code code? set-code-reloc-vector! code-reloc-vector code-freevars + code-size code-ref code-set! + $frame->continuation $fp-at-base $current-frame $seal-frame-and-call + $make-call-with-values-procedure $make-values-procedure + do-overflow collect + $make-tcbucket $tcbucket-next $tcbucket-key $tcbucket-val + $set-tcbucket-next! $set-tcbucket-val! $set-tcbucket-tconc! + call/cf trace-symbol! untrace-symbol! make-traced-procedure + fixnum->string date-string + vector-memq vector-memv + + + +port? input-port? output-port? $make-input-port make-input-port $make-output-port make-output-port $make-input/output-port make-input/output-port $port-handler port-handler $port-input-buffer port-input-buffer $port-input-index port-input-index $port-input-size port-input-size $port-output-buffer port-output-buffer $port-output-index port-output-index $port-output-size port-output-size $set-port-input-index! set-port-input-index! $set-port-input-size! set-port-input-size! $set-port-output-index! set-port-output-index! $set-port-output-size! set-port-output-size! $write-char write-char newline port-name input-port-name output-port-name $read-char read-char $unread-char unread-char $peek-char peek-char $unread-char $reset-input-port! reset-input-port! $close-input-port close-input-port $close-output-port close-output-port $flush-output-port flush-output-port *standard-input-port* console-input-port *current-input-port* current-input-port *standard-output-port* *current-output-port* *standard-error-port* standard-output-port standard-error-port console-output-port current-output-port *current-output-port* open-output-file open-output-string get-output-string with-output-to-file call-with-output-file with-input-from-file call-with-input-file + + )) + + + +(define (whack-system-env setenv?) + (define add-prim + (lambda (x) + (let ([g (gensym (symbol->string x))]) + (putprop x '|#system| g) + (putprop g '*sc-expander* (cons 'core-primitive x))))) + (define add-macro + (lambda (x) + (let ([g (gensym (symbol->string x))] + [e (getprop x '*sc-expander*)]) + (when e + (putprop x '|#system| g) + (putprop g '*sc-expander* e))))) + (define (foo) + (eval + `(begin + (define-syntax compile-time-date-string + (lambda (x) + #'(quote ,(#%date-string)))) + (define-syntax public-primitives + (lambda (x) + #'(quote ,public-primitives))) + (define-syntax system-primitives + (lambda (x) + #'(quote ,system-primitives))) + (define-syntax macros + (lambda (x) + #'(quote ,macros)))))) + (set! system-env ($make-environment '|#system| #t)) + (for-each add-macro macros) + (for-each add-prim public-primitives) + (for-each add-prim system-primitives) + (if setenv? + (parameterize ([interaction-environment system-env]) + (foo)) + (foo))) + + + +(when (eq? "" "") + (load "chez-compat.ss") + (set! primitive-ref top-level-value) + (set! primitive-set! set-top-level-value!) + (set! chez-expand sc-expand) + (set! chez-current-expand current-expand) + (printf "loading psyntax.pp ...\n") + (load "psyntax-7.1.pp") + (chez-current-expand + (lambda (x . args) + (apply chez-expand (sc-expand x) args))) + (whack-system-env #f) + (printf "loading psyntax.ss ...\n") + (load "psyntax-7.1-6.9.ss") + (chez-current-expand + (lambda (x . args) + (apply chez-expand (sc-expand x) args))) + (whack-system-env #t) + (printf "ok\n") + (load "libassembler-compat-6.7.ss") ; defines make-code etc. + (load "libintelasm-6.6.ss") ; uses make-code, etc. + (load "libfasl-6.7.ss") ; uses code? etc. + (load "libcompile-6.7.ss") ; uses fasl-write +) + + +(whack-system-env #t) + +(define scheme-library-files + '(["libhandlers-6.9.ss" "libhandlers.fasl"] + ["libcontrol-6.1.ss" "libcontrol.fasl"] + ["libcollect-6.1.ss" "libcollect.fasl"] + ["librecord-6.4.ss" "librecord.fasl"] + ["libcxr-6.0.ss" "libcxr.fasl"] + ["libcore-6.9.ss" "libcore.fasl"] + ["libio-6.9.ss" "libio.fasl"] + ["libwriter-6.2.ss" "libwriter.fasl"] + ["libtokenizer-6.1.ss" "libtokenizer.fasl"] + ["libassembler-6.7.ss" "libassembler.ss"] + ["libintelasm-6.9.ss" "libintelasm.fasl"] + ["libfasl-6.7.ss" "libfasl.fasl"] + ["libcompile-6.7.ss" "libcompile.fasl"] + ["psyntax-7.1-6.9.ss" "psyntax.fasl"] + ["libinterpret-6.5.ss" "libinterpret.fasl"] + ["libcafe-6.1.ss" "libcafe.fasl"] + ["libtrace-6.9.ss" "libtrace.fasl"] + ["libposix-6.0.ss" "libposix.fasl"] + ["libhash-6.2.ss" "libhash.fasl"] + ["libtoplevel-6.9.ss" "libtoplevel.fasl"] + )) + + + +(define (compile-library ifile ofile) + (parameterize ([assembler-output #f] + [expand-mode 'bootstrap] + [interaction-environment system-env]) + (printf "compiling ~a ...\n" ifile) + (compile-file ifile ofile 'replace))) + +(for-each + (lambda (x) + (compile-library (car x) (cadr x))) + scheme-library-files) + + +(define (join s ls) + (cond + [(null? ls) ""] + [else + (let ([str (open-output-string)]) + (let f ([a (car ls)] [d (cdr ls)]) + (cond + [(null? d) + (display a str) + (get-output-string str)] + [else + (display a str) + (display s str) + (f (car d) (cdr d))])))])) + + +(system + (format "cat ~a > ikarus.fasl" + (join " " (map cadr scheme-library-files)))) diff --git a/src/compiler-8.1.ss b/src/compiler-8.1.ss new file mode 100644 index 0000000..9480512 --- /dev/null +++ b/src/compiler-8.1.ss @@ -0,0 +1,289 @@ + + +;;; 8.1: * using chez-style io ports +;;; 6.9: * creating a *system* environment +;;; 6.8: * creating a core-primitive form in the expander +;;; 6.2: * side-effects now modify the dirty-vector +;;; * added bwp-object? +;;; * added pointer-value +;;; * added tcbuckets +;;; 6.1: * added case-lambda, dropped lambda +;;; 6.0: * basic compiler + + + + +(define macros + '(|#primitive| lambda case-lambda set! quote begin define if letrec + foreign-call $apply + quasiquote unquote unquote-splicing + define-syntax identifier-syntax let-syntax letrec-syntax + fluid-let-syntax alias meta eval-when with-implicit with-syntax + type-descriptor + syntax-case syntax-rules module $module import $import import-only + syntax quasisyntax unsyntax unsyntax-splicing datum + let let* let-values cond case define-record or and when unless do + include parameterize trace untrace trace-lambda)) + + + +(define public-primitives + '(null? pair? char? fixnum? symbol? gensym? string? vector? list? + boolean? procedure? + not + eof-object eof-object? bwp-object? + void + fx= fx< fx<= fx> fx>= fxzero? + fx+ fx- fx* fxadd1 fxsub1 fxquotient fxremainder fxmodulo + fxsll fxsra fxlognot fxlogor fxlogand fxlogxor + integer->char char->integer + char=? char? char>=? + cons car cdr set-car! set-cdr! + caar cadr cdar cddr + caaar caadr cadar caddr cdaar cdadr cddar cdddr + caaaar caaadr caadar caaddr cadaar cadadr caddar cadddr + cdaaar cdaadr cdadar cdaddr cddaar cddadr cdddar cddddr + list list* make-list length list-ref + append + make-vector vector-ref vector-set! vector-length vector + vector->list list->vector + make-string string-ref string-set! string-length string list->string + uuid + string-append substring + string=? string? string>=? + remprop putprop getprop property-list + apply + map for-each andmap ormap + memq memv assq + eq? equal? + reverse + string->symbol symbol->string oblist + top-level-value set-top-level-value! top-level-bound? + gensym gensym-count gensym-prefix print-gensym + gensym->unique-string + call-with-values values + make-parameter dynamic-wind + display write fasl-write printf format print-error + read-token read + error exit call/cc + current-error-handler + eval current-eval interpret compile compile-file new-cafe load + system + expand sc-expand current-expand expand-mode + environment? interaction-environment + identifier? free-identifier=? bound-identifier=? literal-identifier=? + datum->syntax-object syntax-object->datum syntax-error + syntax->list + generate-temporaries + record? record-set! record-ref record-length + record-type-descriptor make-record-type + record-printer record-name record-field-accessor + record-field-mutator record-predicate record-constructor + record-type-name record-type-symbol record-type-field-names + hash-table? make-hash-table get-hash-table put-hash-table! + assembler-output + $make-environment + features + + port? input-port? output-port? + make-input-port make-output-port make-input/output-port + port-handler + port-input-buffer port-input-index port-input-size + port-output-buffer port-output-index port-output-size + set-port-input-index! set-port-input-size! + set-port-output-index! set-port-output-size! + port-name input-port-name output-port-name + write-char read-char unread-char peek-char + newline + reset-input-port! flush-output-port + close-input-port close-output-port + console-input-port current-input-port + standard-output-port standard-error-port + console-output-port current-output-port + open-output-file + open-output-string get-output-string + with-output-to-file call-with-output-file + with-input-from-file call-with-input-file + + + )) + +(define system-primitives + '(immediate? $unbound-object? $forward-ptr? + pointer-value + primitive-ref primitive-set! + $fx= $fx< $fx<= $fx> $fx>= $fxzero? + $fx+ $fx- $fx* $fxadd1 $fxsub1 $fxquotient $fxremainder $fxmodulo + $fxsll $fxsra $fxlognot $fxlogor $fxlogand $fxlogxor + $fixnum->char $char->fixnum + $char= $char< $char<= $char> $char>= + $car $cdr $set-car! $set-cdr! + $make-vector $vector-ref $vector-set! $vector-length + $make-string $string-ref $string-set! $string-length $string + $symbol-string $symbol-unique-string $symbol-value + $set-symbol-string! $set-symbol-unique-string! $set-symbol-value! + $make-symbol $set-symbol-plist! $symbol-plist + $sc-put-cte + $record? $record/rtd? $record-set! $record-ref $record-rtd + $make-record $record + $base-rtd + $code? $code-reloc-vector $code-freevars $code-size $code-ref $code-set! + $code->closure list*->code* + make-code code? set-code-reloc-vector! code-reloc-vector code-freevars + code-size code-ref code-set! + $frame->continuation $fp-at-base $current-frame $seal-frame-and-call + $make-call-with-values-procedure $make-values-procedure + do-overflow collect + $make-tcbucket $tcbucket-next $tcbucket-key $tcbucket-val + $set-tcbucket-next! $set-tcbucket-val! $set-tcbucket-tconc! + call/cf trace-symbol! untrace-symbol! make-traced-procedure + fixnum->string date-string + vector-memq vector-memv + + ;;; must open-code + $make-port + $make-input-port $make-output-port $make-input/output-port + $port-handler + $port-input-buffer $port-input-index $port-input-size + $port-output-buffer $port-output-index $port-output-size + $set-port-input-index! $set-port-input-size! + $set-port-output-index! $set-port-output-size! + + ;;; better open-code + $write-char $read-char $peek-char $unread-char + + ;;; never open-code + $reset-input-port! $close-input-port + $close-output-port $flush-output-port + *standard-output-port* *standard-error-port* *current-output-port* + *standard-input-port* *current-input-port* + )) + + + +(define (whack-system-env setenv?) + (define add-prim + (lambda (x) + (let ([g (gensym (symbol->string x))]) + (putprop x '|#system| g) + (putprop g '*sc-expander* (cons 'core-primitive x))))) + (define add-macro + (lambda (x) + (let ([g (gensym (symbol->string x))] + [e (getprop x '*sc-expander*)]) + (when e + (putprop x '|#system| g) + (putprop g '*sc-expander* e))))) + (define (foo) + (eval + `(begin + (define-syntax compile-time-date-string + (lambda (x) + #'(quote ,(#%date-string)))) + (define-syntax public-primitives + (lambda (x) + #'(quote ,public-primitives))) + (define-syntax system-primitives + (lambda (x) + #'(quote ,system-primitives))) + (define-syntax macros + (lambda (x) + #'(quote ,macros)))))) + (set! system-env ($make-environment '|#system| #t)) + (for-each add-macro macros) + (for-each add-prim public-primitives) + (for-each add-prim system-primitives) + (if setenv? + (parameterize ([interaction-environment system-env]) + (foo)) + (foo))) + + + +(when (eq? "" "") + (load "chez-compat.ss") + (set! primitive-ref top-level-value) + (set! primitive-set! set-top-level-value!) + (set! chez-expand sc-expand) + (set! chez-current-expand current-expand) + (printf "loading psyntax.pp ...\n") + (load "psyntax-7.1.pp") + (chez-current-expand + (lambda (x . args) + (apply chez-expand (sc-expand x) args))) + (whack-system-env #f) + (printf "loading psyntax.ss ...\n") + (load "psyntax-7.1-6.9.ss") + (chez-current-expand + (lambda (x . args) + (apply chez-expand (sc-expand x) args))) + (whack-system-env #t) + (printf "ok\n") + (load "libassembler-compat-6.7.ss") ; defines make-code etc. + (load "libintelasm-6.6.ss") ; uses make-code, etc. + (load "libfasl-6.7.ss") ; uses code? etc. + (load "libcompile-8.1.ss") ; uses fasl-write +) + + +(whack-system-env #t) + +(define scheme-library-files + '(["libhandlers-6.9.ss" #t "libhandlers.fasl"] + ["libcontrol-6.1.ss" #t "libcontrol.fasl"] + ["libcollect-6.1.ss" #t "libcollect.fasl"] + ["librecord-6.4.ss" #t "librecord.fasl"] + ["libcxr-6.0.ss" #t "libcxr.fasl"] + ["libcore-6.9.ss" #t "libcore.fasl"] + ["libchezio-8.1.ss" #t "libchezio.fasl"] + ["libwriter-6.2.ss" #t "libwriter.fasl"] + ["libtokenizer-6.1.ss" #t "libtokenizer.fasl"] + ["libassembler-6.7.ss" #t "libassembler.ss"] + ["libintelasm-6.9.ss" #t "libintelasm.fasl"] + ["libfasl-6.7.ss" #t "libfasl.fasl"] + ["libcompile-8.1.ss" #t "libcompile.fasl"] + ["psyntax-7.1-6.9.ss" #t "psyntax.fasl"] + ["libinterpret-6.5.ss" #t "libinterpret.fasl"] + ["libcafe-6.1.ss" #t "libcafe.fasl"] + ["libtrace-6.9.ss" #t "libtrace.fasl"] + ["libposix-6.0.ss" #t "libposix.fasl"] + ["libhash-6.2.ss" #t "libhash.fasl"] + ["libtoplevel-6.9.ss" #t "libtoplevel.fasl"] + )) + + + +(define (compile-library ifile ofile) + (parameterize ([assembler-output #f] + [expand-mode 'bootstrap] + [interaction-environment system-env]) + (printf "compiling ~a ...\n" ifile) + (compile-file ifile ofile 'replace) + (printf "done\n"))) + +(for-each + (lambda (x) + (when (cadr x) + (compile-library (car x) (caddr x)))) + scheme-library-files) + + +(define (join s ls) + (cond + [(null? ls) ""] + [else + (let ([str (open-output-string)]) + (let f ([a (car ls)] [d (cdr ls)]) + (cond + [(null? d) + (display a str) + (get-output-string str)] + [else + (display a str) + (display s str) + (f (car d) (cdr d))])))])) + + +(system + (format "cat ~a > ikarus.fasl" + (join " " (map caddr scheme-library-files)))) diff --git a/src/geninstr/gen.pl b/src/geninstr/gen.pl index eeea6cf..188e773 100755 --- a/src/geninstr/gen.pl +++ b/src/geninstr/gen.pl @@ -48,7 +48,12 @@ sub gen3{ } } -gen1 "movb \$0, 4(r1)\n"; +gen1 "movl \$0x1234, r1\n"; + +#gen1 "movl \$27, 4(r1)\n"; +#gen1 "movl \$27, 4000(r1)\n"; + +#gen1 "movb \$0, 4(r1)\n"; #gen1 "movb -2(r1), %ah\n"; #gen2 "xorl r1,r2\n"; diff --git a/src/geninstr/tmp.dump b/src/geninstr/tmp.dump index 7b18d91..d0c65b1 100644 --- a/src/geninstr/tmp.dump +++ b/src/geninstr/tmp.dump @@ -4,11 +4,11 @@ tmp.o: file format elf32-i386 Disassembly of section .text: 00000000 <.text>: - 0: c6 40 04 00 movb $0x0,0x4(%eax) - 4: c6 41 04 00 movb $0x0,0x4(%ecx) - 8: c6 42 04 00 movb $0x0,0x4(%edx) - c: c6 43 04 00 movb $0x0,0x4(%ebx) - 10: c6 44 24 04 00 movb $0x0,0x4(%esp) - 15: c6 45 04 00 movb $0x0,0x4(%ebp) - 19: c6 46 04 00 movb $0x0,0x4(%esi) - 1d: c6 47 04 00 movb $0x0,0x4(%edi) + 0: b8 34 12 00 00 mov $0x1234,%eax + 5: b9 34 12 00 00 mov $0x1234,%ecx + a: ba 34 12 00 00 mov $0x1234,%edx + f: bb 34 12 00 00 mov $0x1234,%ebx + 14: bc 34 12 00 00 mov $0x1234,%esp + 19: bd 34 12 00 00 mov $0x1234,%ebp + 1e: be 34 12 00 00 mov $0x1234,%esi + 23: bf 34 12 00 00 mov $0x1234,%edi diff --git a/src/geninstr/tmp.s b/src/geninstr/tmp.s index 7d5ea4f..2bc8fb8 100644 --- a/src/geninstr/tmp.s +++ b/src/geninstr/tmp.s @@ -1,9 +1,9 @@ .text -movb $0, 4(%eax) -movb $0, 4(%ecx) -movb $0, 4(%edx) -movb $0, 4(%ebx) -movb $0, 4(%esp) -movb $0, 4(%ebp) -movb $0, 4(%esi) -movb $0, 4(%edi) +movl $0x1234, %eax +movl $0x1234, %ecx +movl $0x1234, %edx +movl $0x1234, %ebx +movl $0x1234, %esp +movl $0x1234, %ebp +movl $0x1234, %esi +movl $0x1234, %edi diff --git a/src/ikarus.fasl b/src/ikarus.fasl index 047aad2..4fad35e 100644 Binary files a/src/ikarus.fasl and b/src/ikarus.fasl differ diff --git a/src/libassembler-6.7.ss b/src/libassembler-6.7.ss new file mode 100644 index 0000000..1b734b7 --- /dev/null +++ b/src/libassembler-6.7.ss @@ -0,0 +1,56 @@ + +(primitive-set! 'make-code + (lambda (code-size freevars) + (unless (and (fixnum? code-size) ($fx>= code-size 0)) + (error 'make-code "~s is not a valid code size" code-size)) + (unless (and (fixnum? freevars) ($fx>= freevars 0)) + (error 'make-code "~s is not a valid number of free vars" freevars)) + (foreign-call "ikrt_make_code" code-size freevars '#()))) + +(primitive-set! 'code? + (lambda (x) ($code? x))) + +(primitive-set! 'code-reloc-vector + (lambda (x) + (unless ($code? x) (error 'code-reloc-vector "~s is not a code" x)) + ($code-reloc-vector x))) + +(primitive-set! 'code-freevars + (lambda (x) + (unless ($code? x) (error 'code-closure-size "~s is not a code" x)) + ($code-freevars x))) + +(primitive-set! 'code-size + (lambda (x) + (unless ($code? x) (error 'code-size "~s is not a code" x)) + ($code-size x))) + +(primitive-set! 'code-set! + (lambda (x i v) + (unless ($code? x) (error 'code-set! "~s is not a code" x)) + (unless (and (fixnum? i) + ($fx>= i 0) + ($fx< i ($code-size x))) + (error 'code-set! "~s is not a valid index" i)) + (unless (and (fixnum? v) + ($fx>= v 0) + ($fx< v 256)) + (error 'code-set! "~s is not a valid byte" v)) + ($code-set! x i v))) + +(primitive-set! 'code-ref + (lambda (x i) + (unless ($code? x) (error 'code-ref "~s is not a code" x)) + (unless (and (fixnum? i) + ($fx>= i 0) + ($fx< i ($code-size x))) + (error 'code-ref "~s is not a valid index" i)) + ($code-ref x i))) + +(primitive-set! 'set-code-reloc-vector! + (lambda (x v) + (unless ($code? x) + (error 'set-code-reloc-vector! "~s is not a code" x)) + (unless (vector? v) + (error 'set-code-reloc-vector! "~s is not a vector" v)) + (foreign-call "ikrt_set_code_reloc_vector" x v))) diff --git a/src/libassembler-compat-6.0.ss b/src/libassembler-compat-6.0.ss index 01782f9..2056db0 100644 --- a/src/libassembler-compat-6.0.ss +++ b/src/libassembler-compat-6.0.ss @@ -1,56 +1,67 @@ -(define-record code (closure-size code-vec reloc-vec)) - -(define make-code - (let ([make-code make-code]) +(let () + (define-record code (closure-size code-vec reloc-vec)) + + (define make-code^ (lambda (code-size reloc-size closure-size) (let ([code-size (fxsll (fxsra (fx+ code-size 3) 2) 2)]) (make-code closure-size (make-string code-size (integer->char 0)) - (make-vector (fxsra reloc-size 2))))))) + (make-vector (fxsra reloc-size 2)))))) + + (define set-code-byte! + (lambda (code idx byte) + (string-set! (code-code-vec code) idx (integer->char byte)))) + + (define set-code-word! + (lambda (code idx x) + (cond + [(fixnum? x) + (set-code-byte! code (fx+ idx 0) (fxsll (fxlogand x #x3F) 2)) + (set-code-byte! code (fx+ idx 1) (fxlogand (fxsra x 6) #xFF)) + (set-code-byte! code (fx+ idx 2) (fxlogand (fxsra x 14) #xFF)) + (set-code-byte! code (fx+ idx 3) (fxlogand (fxsra x 22) #xFF))] + [else (error 'set-code-word! "unhandled ~s" x)]))) + + (define set-code-object! + (lambda (code obj code-idx reloc-idx) + (let ([v (code-reloc-vec code)]) + (vector-set! v reloc-idx (list 'object code-idx obj))))) + + (define set-code-foreign-object! + (lambda (code obj code-idx reloc-idx) + (let ([v (code-reloc-vec code)]) + (vector-set! v reloc-idx (list 'foreign code-idx obj)) + (vector-set! v (fxadd1 reloc-idx) '(skip))))) + + (define set-code-object+offset/rel! + (lambda (code obj code-idx obj-idx reloc-idx) + (let ([v (code-reloc-vec code)]) + (vector-set! v reloc-idx + (list 'object+off/rel code-idx obj obj-idx)) + (vector-set! v (fxadd1 reloc-idx) '(skip))))) + + (define set-code-object+offset! + (lambda (code obj code-idx obj-idx reloc-idx) + (let ([v (code-reloc-vec code)]) + (vector-set! v reloc-idx + (list 'object+off code-idx obj obj-idx)) + (vector-set! v (fxadd1 reloc-idx) '(skip))))) + + (define make-code-executable! + (lambda (x) (void))) -(define set-code-byte! - (lambda (code idx byte) - (string-set! (code-code-vec code) idx (integer->char byte)))) - - -(define set-code-word! - (lambda (code idx x) - (cond - [(fixnum? x) - (set-code-byte! code (fx+ idx 0) (fxsll (fxlogand x #x3F) 2)) - (set-code-byte! code (fx+ idx 1) (fxlogand (fxsra x 6) #xFF)) - (set-code-byte! code (fx+ idx 2) (fxlogand (fxsra x 14) #xFF)) - (set-code-byte! code (fx+ idx 3) (fxlogand (fxsra x 22) #xFF))] - [else (error 'set-code-word! "unhandled ~s" x)]))) - -(define set-code-object! - (lambda (code obj code-idx reloc-idx) - (let ([v (code-reloc-vec code)]) - (vector-set! v reloc-idx (list 'object code-idx obj))))) - -(define set-code-foreign-object! - (lambda (code obj code-idx reloc-idx) - (let ([v (code-reloc-vec code)]) - (vector-set! v reloc-idx (list 'foreign code-idx obj)) - (vector-set! v (fxadd1 reloc-idx) '(skip))))) - - -(define set-code-object+offset/rel! - (lambda (code obj code-idx obj-idx reloc-idx) - (let ([v (code-reloc-vec code)]) - (vector-set! v reloc-idx - (list 'object+off/rel code-idx obj obj-idx)) - (vector-set! v (fxadd1 reloc-idx) '(skip))))) - -(define set-code-object+offset! - (lambda (code obj code-idx obj-idx reloc-idx) - (let ([v (code-reloc-vec code)]) - (vector-set! v reloc-idx - (list 'object+off code-idx obj obj-idx)) - (vector-set! v (fxadd1 reloc-idx) '(skip))))) - -(define make-code-executable! - (lambda (x) (void))) + (primitive-set! 'make-code make-code^) + (primitive-set! 'code? code?) + (primitive-set! 'code-code-vec code-code-vec) + (primitive-set! 'code-reloc-vec code-reloc-vec) + (primitive-set! 'code-closure-size code-closure-size) + (primitive-set! 'set-code-byte! set-code-byte!) + (primitive-set! 'set-code-word! set-code-word!) + (primitive-set! 'set-code-object! set-code-object!) + (primitive-set! 'set-code-foreign-object! set-code-foreign-object!) + (primitive-set! 'set-code-object+offset/rel! set-code-object+offset/rel!) + (primitive-set! 'set-code-object+offset! set-code-object+offset!) + (primitive-set! 'make-code-executable! make-code-executable!)) diff --git a/src/libassembler-compat-6.6.ss b/src/libassembler-compat-6.6.ss new file mode 100644 index 0000000..3dfffec --- /dev/null +++ b/src/libassembler-compat-6.6.ss @@ -0,0 +1,32 @@ + +(let () + (define-record code (closure-size code-string reloc-vector)) + + (define make-code^ + (lambda (code-size closure-size) + (let ([code-size (fxsll (fxsra (fx+ code-size 3) 2) 2)]) + (make-code + closure-size + (make-string code-size) + #f)))) + + (define code-set! + (lambda (code idx byte) + (string-set! (code-code-string code) idx (integer->char byte)))) + + (define code-ref + (lambda (code idx) + (char->integer (string-ref (code-code-string code) idx)))) + + (define (code-size code) + (string-length (code-code-string code))) + + (primitive-set! 'make-code make-code^) + (primitive-set! 'code? code?) + (primitive-set! 'code-reloc-vector code-reloc-vector) + (primitive-set! 'code-closure-size code-closure-size) + (primitive-set! 'code-size code-size) + (primitive-set! 'code-set! code-set!) + (primitive-set! 'code-ref code-ref) + (primitive-set! 'set-code-reloc-vector! set-code-reloc-vector!)) + diff --git a/src/libassembler-compat-6.7.ss b/src/libassembler-compat-6.7.ss new file mode 100644 index 0000000..dd34e27 --- /dev/null +++ b/src/libassembler-compat-6.7.ss @@ -0,0 +1,32 @@ + +(let () + (define-record code (freevars code-string reloc-vector)) + + (define make-code^ + (lambda (code-size freevars) + (let ([code-size (fxsll (fxsra (fx+ code-size 3) 2) 2)]) + (make-code + freevars + (make-string code-size) + #f)))) + + (define code-set! + (lambda (code idx byte) + (string-set! (code-code-string code) idx (integer->char byte)))) + + (define code-ref + (lambda (code idx) + (char->integer (string-ref (code-code-string code) idx)))) + + (define (code-size code) + (string-length (code-code-string code))) + + (primitive-set! 'make-code make-code^) + (primitive-set! 'code? code?) + (primitive-set! 'code-reloc-vector code-reloc-vector) + (primitive-set! 'code-freevars code-freevars) + (primitive-set! 'code-size code-size) + (primitive-set! 'code-set! code-set!) + (primitive-set! 'code-ref code-ref) + (primitive-set! 'set-code-reloc-vector! set-code-reloc-vector!)) + diff --git a/src/libassembler-compat.ss b/src/libassembler-compat.ss new file mode 100644 index 0000000..12406b2 Binary files /dev/null and b/src/libassembler-compat.ss differ diff --git a/src/libassembler.ss b/src/libassembler.ss new file mode 100644 index 0000000..b748820 Binary files /dev/null and b/src/libassembler.ss differ diff --git a/src/libcafe-6.1.ss b/src/libcafe-6.1.ss index 25eedff..34cae3c 100644 --- a/src/libcafe-6.1.ss +++ b/src/libcafe-6.1.ss @@ -30,7 +30,6 @@ (with-error-handler (lambda args (reset-input-port! (console-input-port)) - (display "repl catch\n" (console-output-port)) (apply print-error args) (k (void))) (lambda () @@ -64,7 +63,7 @@ (primitive-set! 'new-cafe (case-lambda - [() (new-cafe (current-eval))] + [() (new-cafe eval)] [(p) (unless (procedure? p) (error 'new-cafe "~s is not a procedure" p)) diff --git a/src/libcafe.fasl b/src/libcafe.fasl index c4b3966..b36efff 100644 Binary files a/src/libcafe.fasl and b/src/libcafe.fasl differ diff --git a/src/libchezio-8.1.ss b/src/libchezio-8.1.ss new file mode 100644 index 0000000..3f577c7 --- /dev/null +++ b/src/libchezio-8.1.ss @@ -0,0 +1,750 @@ + + +(let () + (include "unsafe-record.ss") + ;;; + ;;; GENERIC PORTS: BASIC PRIMITIVES + ;;; + ;;; Exports: + ;;; * Constructors: + ;;; (make-input-port handler input-buffer) + ;;; (make-output-port handler output-buffer) + ;;; (make-input/output-port handler input-buffer output-buffer) + ;;; + ;;; * Predicates: + ;;; (port? x) + ;;; (input-port? x) + ;;; (output-port? x) + ;;; + ;;; * Accessors: + ;;; (port-handler port) + ;;; (port-input-buffer port) + ;;; (port-input-index port) + ;;; (port-input-size port) + ;;; (port-output-buffer port) + ;;; (port-output-index port) + ;;; (port-output-size port) + ;;; + ;;; * Mutators: + ;;; (set-port-input-index! port fixnum) + ;;; (set-port-input-size! port fixnum) + ;;; (set-port-output-index! port fixnum) + ;;; (set-port-output-size! port fixnum) + ;;; + ;;; (begin + ;;; ;;; uncomment this form to use the compiler's definition + ;;; ;;; of ports; otherwise, ports are represented as vanilla + ;;; ;;; records. + ;;; ($define-record-syntax port + ;;; (handler input-buffer input-index input-size + ;;; output-buffer output-index output-size)) + ;;; (define-syntax port? (identifier-syntax $port?)) + ;;; (define-syntax input-port? + ;;; (syntax-rules () + ;;; [(_ x) (identifier? #'x) + ;;; (and ($port? x) (string? ($port-input-buffer x)))])) + ;;; (define-syntax output-port? + ;;; (syntax-rules () + ;;; [(_ x) (identifier? #'x) + ;;; (and ($port? x) (string? ($port-output-buffer x)))]))) + ;;; + (primitive-set! 'port? + (lambda (x) (port? x))) + ;;; + (primitive-set! 'input-port? + (lambda (x) (input-port? x))) + ;;; + (primitive-set! 'output-port? + (lambda (x) (output-port? x))) + ;;; + (primitive-set! '$make-input-port + (lambda (handler buffer) + ($make-port handler buffer 0 ($string-length buffer) #f 0 0))) + ;;; + (primitive-set! 'make-input-port + (lambda (handler buffer) + (if (procedure? handler) + (if (string? buffer) + ($make-input-port handler buffer) + (error 'make-input-port "~s is not a string" buffer)) + (error 'make-input-port "~s is not a procedure" handler)))) + ;;; + (primitive-set! '$make-output-port + (lambda (handler buffer) + ($make-port handler #f 0 0 buffer 0 ($string-length buffer)))) + ;;; + (primitive-set! 'make-output-port + (lambda (handler buffer) + (if (procedure? handler) + (if (string? buffer) + ($make-output-port handler buffer) + (error 'make-output-port "~s is not a string" buffer)) + (error 'make-output-port "~s is not a procedure" handler)))) + ;;; + (primitive-set! '$make-input/output-port + (lambda (handler input-buffer output-buffer) + ($make-port handler + input-buffer 0 ($string-length input-buffer) + output-buffer 0 ($string-length output-buffer)))) + (primitive-set! 'make-input/output-port + (lambda (handler input-buffer output-buffer) + (if (procedure? handler) + (if (string? input-buffer) + (if (string? output-buffer) + ($make-input/output-port handler input-buffer output-buffer) + (error 'make-input/output-port + "~s is not a string" + output-buffer)) + (error 'make-input/output-port "~s is not a string" input-buffer)) + (error 'make-input/output-port "~s is not a procedure" handler)))) + ;;; + (primitive-set! '$port-handler + (lambda (x) ($port-handler x))) + ;;; + (primitive-set! 'port-handler + (lambda (x) + (if (port? x) + ($port-handler x) + (error 'port-handler "~s is not a port" x)))) + ;;; + (primitive-set! '$port-input-buffer + (lambda (x) ($port-input-buffer x))) + ;;; + (primitive-set! 'port-input-buffer + (lambda (x) + (if (input-port? x) + ($port-input-buffer x) + (error 'port-input-buffer "~s is not an input-port" x)))) + ;;; + (primitive-set! '$port-input-index + (lambda (x) ($port-input-index x))) + ;;; + (primitive-set! 'port-input-index + (lambda (x) + (if (input-port? x) + ($port-input-index x) + (error 'port-input-index "~s is not an input-port" x)))) + ;;; + (primitive-set! '$port-input-size + (lambda (x) ($port-input-size x))) + ;;; + (primitive-set! 'port-input-size + (lambda (x) + (if (input-port? x) + ($port-input-size x) + (error 'port-input-size "~s is not an input-port" x)))) + ;;; + (primitive-set! '$port-output-buffer + (lambda (x) ($port-output-buffer x))) + ;;; + (primitive-set! 'port-output-buffer + (lambda (x) + (if (output-port? x) + ($port-output-buffer x) + (error 'port-output-buffer "~s is not an output-port" x)))) + ;;; + (primitive-set! '$port-output-index + (lambda (x) ($port-output-index x))) + ;;; + (primitive-set! 'port-output-index + (lambda (x) + (if (output-port? x) + ($port-output-index x) + (error 'port-output-index "~s is not an output-port" x)))) + ;;; + (primitive-set! '$port-output-size + (lambda (x) ($port-output-size x))) + ;;; + (primitive-set! 'port-output-size + (lambda (x) + (if (output-port? x) + ($port-output-size x) + (error 'port-output-size "~s is not an output-port" x)))) + ;;; + (primitive-set! '$set-port-input-index! + (lambda (p i) ($set-port-input-index! p i))) + ;;; + (primitive-set! 'set-port-input-index! + (lambda (p i) + (if (input-port? p) + (if (fixnum? i) + (if ($fx>= i 0) + (if ($fx<= i ($port-input-size p)) + ($set-port-input-index! p i) + (error 'set-port-input-index! "index ~s is too big" i)) + (error 'set-port-input-index! "index ~s is negative" i)) + (error 'set-port-input-index! "~s is not a valid index" i)) + (error 'set-port-input-index! "~s is not an input-port" p)))) + ;;; + (primitive-set! '$set-port-input-size! + (lambda (p i) + ($set-port-input-index! p 0) + ($set-port-input-size! p i))) + ;;; + (primitive-set! 'set-port-input-size! + (lambda (p i) + (if (input-port? p) + (if (fixnum? i) + (if ($fx>= i 0) + (if ($fx<= i ($string-length ($port-input-buffer p))) + (begin + ($set-port-input-index! p 0) + ($set-port-input-size! p i)) + (error 'set-port-input-size! "size ~s is too big" i)) + (error 'set-port-input-size! "size ~s is negative" i)) + (error 'set-port-input-size! "~s is not a valid size" i)) + (error 'set-port-input-size! "~s is not an input-port" p)))) + ;;; + (primitive-set! '$set-port-output-index! + (lambda (p i) ($set-port-output-index! p i))) + ;;; + (primitive-set! 'set-port-output-index! + (lambda (p i) + (if (output-port? p) + (if (fixnum? i) + (if ($fx>= i 0) + (if ($fx<= i ($port-output-size p)) + ($set-port-output-index! p i) + (error 'set-port-output-index! "index ~s is too big" i)) + (error 'set-port-output-index! "index ~s is negative" i)) + (error 'set-port-output-index! "~s is not a valid index" i)) + (error 'set-port-output-index! "~s is not an output-port" p)))) + ;;; + (primitive-set! '$set-port-output-size! + (lambda (p i) + ($set-port-output-index! p 0) + ($set-port-output-size! p i))) + ;;; + (primitive-set! 'set-port-output-size! + (lambda (p i) + (if (output-port? p) + (if (fixnum? i) + (if ($fx>= i 0) + (if ($fx<= i ($string-length ($port-output-buffer p))) + (begin + ($set-port-output-index! p 0) + ($set-port-output-size! p i)) + (error 'set-port-output-size! "size ~s is too big" i)) + (error 'set-port-output-size! "size ~s is negative" i)) + (error 'set-port-output-size! "~s is not a valid size" i)) + (error 'set-port-output-size! "~s is not an output-port" p))))) + + +(let () + ;;; IO PRIMITIVES + ;;; + (primitive-set! '$write-char + (lambda (c p) + (let ([idx ($port-output-index p)]) + (if ($fx< idx ($port-output-size p)) + (begin + ($string-set! ($port-output-buffer p) idx c) + ($set-port-output-index! p ($fxadd1 idx))) + (($port-handler p) 'write-char c p))))) + ;;; + (primitive-set! 'write-char + (case-lambda + [(c) + (if (char? c) + ($write-char c (current-output-port)) + (error 'write-char "~s is not a character" c))] + [(c p) + (if (char? c) + (if (output-port? p) + ($write-char c p) + (error 'write-char "~s is not an output-port" p)) + (error 'write-char "~s is not a character" c))])) + ;;; + (primitive-set! 'newline + (case-lambda + [() + ($write-char #\newline (current-output-port)) + ($flush-output-port (current-output-port))] + [(p) + (if (output-port? p) + (begin + ($write-char #\newline p) + ($flush-output-port p)) + (error 'newline "~s is not an output port" p))])) + ;;; + (primitive-set! 'port-name + (lambda (p) + (if (port? p) + (($port-handler p) 'port-name p) + (error 'port-name "~s is not a port" p)))) + (primitive-set! 'input-port-name port-name) + (primitive-set! 'output-port-name port-name) + (primitive-set! '$read-char + (lambda (p) + (let ([idx ($port-input-index p)]) + (if ($fx< idx ($port-input-size p)) + (begin + ($set-port-input-index! p ($fxadd1 idx)) + ($string-ref ($port-input-buffer p) idx)) + (begin + (($port-handler p) 'read-char p)))))) + ;;; + (primitive-set! 'read-char + (case-lambda + [() ($read-char (current-input-port))] + [(p) + (if (input-port? p) + ($read-char p) + (error 'read-char "~s is not an input-port" p))])) + ;;; + (primitive-set! '$unread-char + (lambda (c p) + (let ([idx ($fxsub1 ($port-input-index p))]) + (if (and ($fx>= idx 0) + ($fx< idx ($port-input-size p))) + (begin + ($set-port-input-index! p idx) + ($string-set! ($port-input-buffer p) idx c)) + (($port-handler p) 'unread-char c p))))) + ;;; + (primitive-set! 'unread-char + (case-lambda + [(c) (if (char? c) + ($unread-char c (current-input-port)) + (error 'unread-char "~s is not a character" c))] + [(c p) + (if (input-port? p) + (if (char? c) + ($unread-char c p) + (error 'unread-char "~s is not a character" c)) + (error 'unread-char "~s is not an input-port" p))])) + ;;; + (primitive-set! '$peek-char + (lambda (p) + (let ([idx ($port-input-index p)]) + (if ($fx< idx ($port-input-size p)) + ($string-ref ($port-input-buffer p) idx) + (($port-handler p) 'peek-char p))))) + ;;; + (primitive-set! 'peek-char + (case-lambda + [() ($peek-char (current-input-port))] + [(p) + (if (input-port? p) + ($peek-char p) + (error 'peek-char "~s is not an input-port" p))])) + ;;; + (primitive-set! '$unread-char + (lambda (c p) + (let ([idx ($fxsub1 ($port-input-index p))]) + (if (and ($fx>= idx 0) + ($fx< idx ($port-input-size p))) + (begin + ($set-port-input-index! p idx) + ($string-set! ($port-input-buffer p) idx c)) + (($port-handler p) 'unread-char c p))))) + ;;; + (primitive-set! '$reset-input-port! + (lambda (p) + ($set-port-input-size! p 0))) + ;;; + (primitive-set! 'reset-input-port! + (case-lambda + [() ($reset-input-port! (current-input-port))] + [(p) + (if (input-port? p) + ($reset-input-port! p) + (error 'reset-input-port! "~s is not an input-port" p))])) + ;;; + (primitive-set! '$close-input-port + (lambda (p) + (($port-handler p) 'close-port p))) + ;;; + (primitive-set! 'close-input-port + (case-lambda + [() ($close-input-port (current-input-port))] + [(p) + (if (input-port? p) + ($close-input-port p) + (error 'close-input-port! "~s is not an input-port" p))])) + ;;; + (primitive-set! '$close-output-port + (lambda (p) + (($port-handler p) 'close-port p))) + ;;; + (primitive-set! 'close-output-port + (case-lambda + [() ($close-output-port (current-output-port))] + [(p) + (if (output-port? p) + ($close-output-port p) + (error 'close-output-port "~s is not an output-port" p))])) + ;;; + (primitive-set! '$flush-output-port + (lambda (p) + (($port-handler p) 'flush-output-port p))) + ;;; + (primitive-set! 'flush-output-port + (case-lambda + [() ($flush-output-port (current-output-port))] + [(p) + (if (output-port? p) + ($flush-output-port p) + (error 'flush-output-port "~s is not an output-port" p))]))) + + + +(let () + ;;; INPUT FILES + (include "message-case.ss") + (define make-input-file-handler + (lambda (fd port-name) + (let ((open? #t)) + (lambda (msg . args) + (message-case msg args + [(read-char p) + (unless (input-port? p) + (error 'read-char "~s is not an input port" p)) + (let ([idx ($port-input-index p)]) + (if ($fx< idx ($port-input-size p)) + (begin + ($set-port-input-index! p ($fxadd1 idx)) + ($string-ref ($port-input-buffer p) idx)) + (if open? + (let ([bytes + (foreign-call "ikrt_read" fd + ($port-input-buffer p))]) + (cond + [(not bytes) + (error 'read-char "Cannot read from ~s" port-name)] + [($fx= bytes 0) + (eof-object)] + [else + ($set-port-input-size! p bytes) + ($read-char p)])) + (error 'read-char "port ~s is closed" p))))] + [(peek-char p) + (unless (input-port? p) + (error 'peek-char "~s is not an input port" p)) + (let ([idx ($port-input-index p)]) + (if ($fx< idx ($port-input-size p)) + ($string-ref ($port-input-buffer p) idx) + (if open? + (let ([bytes + (foreign-call "ikrt_read" fd + (port-input-buffer p))]) + (cond + [(not bytes) + (error 'peek-char + "Cannot read from ~s" port-name)] + [($fx= bytes 0) + (eof-object)] + [else + ($set-port-input-size! p bytes) + ($peek-char p)])) + (error 'peek-char "port ~s is closed" p))))] + [(unread-char c p) + (unless (input-port? p) + (error 'unread-char "~s is not an input port" p)) + (let ([idx ($fxsub1 ($port-input-index p))]) + (if (and ($fx>= idx 0) + ($fx< idx ($port-input-size p))) + (begin + ($set-port-input-index! p idx) + ($string-set! ($port-input-buffer p) idx c)) + (if open? + (error 'unread-char "port ~s is closed" p) + (error 'unread-char "too many unread-chars"))))] + [(port-name p) port-name] + [(close-port p) + (unless (input-port? p) + (error 'close-input-port "~s is not an input port" p)) + (when open? + ($set-port-input-size! p 0) + (set! open? #f) + (unless (foreign-call "ikrt_close_file" fd) + (error 'close-input-port "cannot close ~s" port-name)))] + [else + (error 'input-file-handler + "message not handled ~s" (cons msg args))]))))) + (define open-input-file + (lambda (filename) + (let ([fd/error (foreign-call "ikrt_open_input_file" filename)]) + (if (fixnum? fd/error) + (let ([port (make-input-port + (make-input-file-handler fd/error filename) + (make-string 4096))]) + (set-port-input-size! port 0) + port) + (error 'open-input-file "cannot open ~s: ~a" filename fd/error))))) + (primitive-set! '*standard-input-port* + (let ([p (make-input-port + (make-input-file-handler 0 '*stdin*) + (make-string 4096))]) + (set-port-input-size! p 0) + p)) + (primitive-set! 'console-input-port (lambda () *standard-input-port*)) + (primitive-set! '*current-input-port* *standard-input-port*) + (primitive-set! 'current-input-port + (case-lambda + [() *current-input-port*] + [(p) + (if (input-port? p) + (primitive-set! '*current-input-port* p) + (error 'current-input-port "~s is not an input-port" p))])) + (primitive-set! 'open-input-file + (lambda (filename) + (if (string? filename) + (open-input-file filename) + (error 'open-input-file "~s is not a string" filename))))) + + +(let () + ;;; OUTPUT FILES + (include "message-case.ss") + (define do-write-buffer + (lambda (fd port-name p caller) + (let ([bytes (foreign-call "ikrt_write_file" + fd + (port-output-buffer p) + (port-output-index p))]) + (if (fixnum? bytes) + (set-port-output-index! p 0) + (error caller "cannot write to file ~s: ~a" port-name bytes))))) + (define make-output-file-handler + (lambda (fd port-name) + (define open? #t) + (define output-file-handler + (lambda (msg . args) + (message-case msg args + [(write-char c p) + (if (char? c) + (if (output-port? p) + (let ([idx ($port-output-index p)]) + (if ($fx< idx ($port-output-size p)) + (begin + ($string-set! ($port-output-buffer p) idx c) + ($set-port-output-index! p ($fxadd1 idx))) + (if open? + (begin + (do-write-buffer fd port-name p 'write-char) + ($write-char c p)) + (error 'write-char "port ~s is closed" p)))) + (error 'write-char "~s is not an output-port" p)) + (error 'write-char "~s is not a character" c))] + [(flush-output-port p) + (if (output-port? p) + (if open? + (do-write-buffer fd port-name p 'flush-output-port) + (error 'flush-output-port "port ~s is closed" p)) + (error 'flush-output-port "~s is not an output-port" p))] + [(close-port p) + (when open? + (flush-output-port p) + ($set-port-output-size! p 0) + (set! open? #f) + (unless (foreign-call "ikrt_close_file" fd) + (error 'close-output-port "cannot close ~s" port-name)))] + [(port-name p) port-name] + [else (error 'output-file-handler + "unhandled message ~s" (cons msg args))]))) + output-file-handler)) + (define (option-id x) + (case x + [(error) 0] + [(replace) 1] + [(truncate) 2] + [(append) 3] + [else (error 'open-output-file "~s is not a valid mode" x)])) + (define open-output-file + (lambda (filename options) + (let ([fd/error + (foreign-call "ikrt_open_output_file" + filename + (option-id options))]) + (if (fixnum? fd/error) + (make-output-port + (make-output-file-handler fd/error filename) + (make-string 4096)) + (error 'open-output-file "cannot open ~s: ~a" filename fd/error))))) + (primitive-set! '*standard-output-port* + (make-output-port + (make-output-file-handler 1 '*stdout*) + (make-string 4096))) + (primitive-set! '*current-output-port* *standard-output-port*) + (primitive-set! '*standard-error-port* + (make-output-port + (make-output-file-handler 2 '*stderr*) + (make-string 4096))) + (primitive-set! 'standard-output-port + (lambda () *standard-output-port*)) + (primitive-set! 'standard-error-port + (lambda () *standard-error-port*)) + (primitive-set! 'console-output-port + (lambda () *standard-output-port*)) + (primitive-set! 'current-output-port + (case-lambda + [() *current-output-port*] + [(p) + (if (output-port? p) + (primitive-set! '*current-output-port* p) + (error 'current-output-port "~s is not an output port" p))])) + (primitive-set! 'open-output-file + (case-lambda + [(filename) + (if (string? filename) + (open-output-file filename 'error) + (error 'open-output-file "~s is not a string" filename))] + [(filename options) + (if (string? filename) + (open-output-file filename options) + (error 'open-output-file "~s is not a string" filename))]))) + + +(let () + (include "message-case.ss") + ;;; OUTPUT STRINGS + (define string-copy + (lambda (s) + (substring s 0 (string-length s)))) + (define concat + (lambda (str i ls) + (let ([n (sum i ls)]) + (let ([outstr ($make-string n)]) + (let f ([n (copy outstr str i n)] [ls ls]) + (if (null? ls) + outstr + (let ([a ($car ls)]) + (f (copy outstr a ($string-length a) n) ($cdr ls))))))))) + (define sum + (lambda (ac ls) + (cond + [(null? ls) ac] + [else (sum ($fx+ ac ($string-length ($car ls))) ($cdr ls))]))) + (define copy + (lambda (dst src n end) + (let f ([di end] + [si n]) + (cond + [($fx= si 0) di] + [else + (let ([di ($fxsub1 di)] [si ($fxsub1 si)]) + ($string-set! dst di ($string-ref src si)) + (f di si))])))) + (define make-output-string-handler + (lambda () + (define buffer-list '()) + (define open? #t) + (define output-handler + (lambda (msg . args) + (message-case msg args + [(write-char c p) + (if (char? c) + (if (output-port? p) + (let ([idx ($port-output-index p)]) + (if ($fx< idx ($port-output-size p)) + (begin + ($string-set! ($port-output-buffer p) idx c) + ($set-port-output-index! p ($fxadd1 idx))) + (if open? + (begin + (set! buffer-list + (cons (string-copy (port-output-buffer p)) + buffer-list)) + ($set-port-output-size! p + ($string-length ($port-output-buffer p))) + ($write-char c p)) + (error 'write-char "port ~s is closed" p)))) + (error 'write-char "~s is not an output-port" p)) + (error 'write-char "~s is not a character" c))] + [(flush-output-port p) + (void)] + [(close-port p) + (set! open? #f)] + [(port-name p) 'string-port] + [(get-output-string p) + (concat ($port-output-buffer p) + ($port-output-index p) + buffer-list)] + [else (error 'output-handler + "unhandled message ~s" (cons msg args))]))) + output-handler)) + (primitive-set! 'open-output-string + (lambda () + (make-output-port + (make-output-string-handler) + (make-string 10)))) + (primitive-set! 'get-output-string + (lambda (p) + (if (output-port? p) + (($port-handler p) 'get-output-string p) + (error 'get-output-string "~s is not an output port" p)))) +) + +(primitive-set! 'with-output-to-file + (lambda (name proc . args) + (unless (string? name) + (error 'with-output-to-file "~s is not a string" name)) + (unless (procedure? proc) + (error 'with-output-to-file "~s is not a procedure" proc)) + (let ([p (apply open-output-file name args)] + [shot #f]) + (parameterize ([current-output-port p]) + (dynamic-wind + (lambda () + (when shot + (error 'with-output-to-file + "cannot reenter"))) + proc + (lambda () + (close-output-port p) + (set! shot #t))))))) + +(primitive-set! 'call-with-output-file + (lambda (name proc . args) + (unless (string? name) + (error 'call-with-output-file "~s is not a string" name)) + (unless (procedure? proc) + (error 'call-with-output-file "~s is not a procedure" proc)) + (let ([p (apply open-output-file name args)] + [shot #f]) + (dynamic-wind + (lambda () + (when shot + (error 'call-with-output-file "cannot reenter"))) + (lambda () (proc p)) + (lambda () + (close-output-port p) + (set! shot #t)))))) + +(primitive-set! 'with-input-from-file + (lambda (name proc) + (unless (string? name) + (error 'with-input-from-file "~s is not a string" name)) + (unless (procedure? proc) + (error 'with-input-from-file "~s is not a procedure" proc)) + (let ([p (open-input-file name)] + [shot #f]) + (parameterize ([current-input-port p]) + (dynamic-wind + (lambda () + (when shot + (error 'with-input-from-file + "cannot reenter"))) + proc + (lambda () + (close-input-port p) + (set! shot #t))))))) + +(primitive-set! 'call-with-input-file + (lambda (name proc) + (unless (string? name) + (error 'call-with-input-file "~s is not a string" name)) + (unless (procedure? proc) + (error 'call-with-input-file "~s is not a procedure" proc)) + (let ([p (open-input-file name)] + [shot #f]) + (dynamic-wind + (lambda () + (when shot + (error 'call-with-input-file "cannot reenter"))) + (lambda () (proc p)) + (lambda () + (close-input-port p) + (set! shot #t)))))) + diff --git a/src/libcollect.fasl b/src/libcollect.fasl index 195ddc3..3491553 100644 Binary files a/src/libcollect.fasl and b/src/libcollect.fasl differ diff --git a/src/libcompile-6.4.ss b/src/libcompile-6.4.ss new file mode 100644 index 0000000..2bb199a --- /dev/null +++ b/src/libcompile-6.4.ss @@ -0,0 +1,3035 @@ + + +;;; 6.2: * side-effects now modify the dirty-vector +;;; * added bwp-object? +;;; * added pointer-value +;;; * added tcbuckets +;;; 6.1: * added case-lambda, dropped lambda +;;; 6.0: * basic compiler + +(let () + +(include "record-case.ss") + + +(include "set-operations.ss") + + +(define open-coded-primitives +;;; these primitives, when found in operator position with the correct +;;; number of arguments, will be open-coded by the generator. If an +;;; incorrect number of args is detected, or if they appear in non-operator +;;; position, then they cannot be open-coded, and the pcb-primitives table +;;; is consulted for a reference of the pcb slot containing the primitive. +;;; If it's not found there, an error is signalled. +;;; +;;; prim-name args + '([$constant-ref 1 value] + [$constant-set! 2 effect] + [$pcb-ref 1 value] + [$pcb-set! 2 effect] + ;;; type predicates + [fixnum? 1 pred] + [immediate? 1 pred] + [boolean? 1 pred] + [char? 1 pred] + [pair? 1 pred] + [symbol? 1 pred] + [vector? 1 pred] + [string? 1 pred] + [procedure? 1 pred] + [null? 1 pred] + [eof-object? 1 pred] + [bwp-object? 1 pred] + [$unbound-object? 1 pred] + [$forward-ptr? 1 pred] + [not 1 pred] + [pointer-value 1 value] + [eq? 2 pred] + ;;; fixnum primitives + [$fxadd1 1 value] + [$fxsub1 1 value] + [$fx+ 2 value] + [$fx- 2 value] + [$fx* 2 value] + [$fxsll 2 value] + [$fxsra 2 value] + [$fxlogand 2 value] + [$fxlogor 2 value] + [$fxlogxor 2 value] + [$fxlognot 1 value] + [$fxquotient 2 value] + [$fxmodulo 2 value] + ;;; fixnum predicates + [$fxzero? 1 pred] + [$fx= 2 pred] + [$fx< 2 pred] + [$fx<= 2 pred] + [$fx> 2 pred] + [$fx>= 2 pred] + ;;; character predicates + [$char= 2 pred] + [$char< 2 pred] + [$char<= 2 pred] + [$char> 2 pred] + [$char>= 2 pred] + ;;; character conversion + [$fixnum->char 1 value] + [$char->fixnum 1 value] + ;;; lists/pairs + [cons 2 value] + [$car 1 value] + [$cdr 1 value] + [$set-car! 2 effect] + [$set-cdr! 2 effect] + ;;; vectors + [$make-vector 1 value] + [vector any value] + [$vector-length 1 value] + [$vector-ref 2 value] + [$vector-set! 3 effect] + ;;; strings + [$make-string 1 value] + [$string any value] + [$string-length 1 value] + [$string-ref 2 value] + [$string-set! 3 effect] + ;;; symbols + [$make-symbol 1 value] + [$symbol-value 1 value] + [$symbol-string 1 value] + [$symbol-unique-string 1 value] + [$set-symbol-value! 2 effect] + [$set-symbol-string! 2 effect] + [$set-symbol-unique-string! 2 effect] + [$symbol-plist 1 value] + [$set-symbol-plist! 2 effect] + [primitive-ref 1 value] + [primitive-set! 2 effect] + ;;; tcbuckets + [$make-tcbucket 4 value] + [$tcbucket-key 1 value] + [$tcbucket-val 1 value] + [$tcbucket-next 1 value] + [$set-tcbucket-val! 2 effect] + [$set-tcbucket-next! 2 effect] + [$set-tcbucket-tconc! 2 effect] + ;;; misc + [eof-object 0 value] + [void 0 value] + [$exit 1 effect] + [$fp-at-base 0 pred] + [$current-frame 0 value] + [$seal-frame-and-call 1 tail] + [$frame->continuation 1 value] + ;;; + ;;; records + ;;; + [$make-record 2 value] + [$record? 1 pred] + [$record-rtd 1 value] + [$record-ref 2 value] + [$record-set! 3 effect] + ;;; + ;;; asm + ;;; + ;[code? 1 pred] + ;[$code-instr-size 1 value] + ;[$code-reloc-size 1 value] + ;[$code-closure-size 1 value] + ;[$code->closure 1 value] + ;[$set-code-byte! 3 effect] + ;[$set-code-word! 3 effect] + ;[$set-code-object! 4 effect] + ;[$set-code-object+offset! 5 effect] + ;[$set-code-object+offset/rel! 5 effect] + ;;; + [$make-call-with-values-procedure 0 value] + [$make-values-procedure 0 value] + [$install-underflow-handler 0 effect] + )) + +(define (primitive-context x) + (cond + [(assq x open-coded-primitives) => caddr] + [else (error 'primitive-context "unknown prim ~s" x)])) + + +;;; primitives table section +(define primitives-table + '(;;; system locations used by the C/Scheme interface + [$apply-nonprocedure-error-handler library] + [$incorrect-args-error-handler library] + [$multiple-values-error library] + [$intern library] + [do-overflow library] + [do-vararg-overflow library] + [do-stack-overflow library] + ;;; type predicates + [fixnum? public] + [immediate? public] + [boolean? public] + [char? public] + [null? public] + [pair? public] + [symbol? public] + [vector? public] + [string? public] + [procedure? public] + [eof-object? public] + [not public] + [eq? public] + [equal? public] + ;;; fixnum primitives + [fxadd1 public] + [fxsub1 public] + [fx+ public] + [fx- public] + [fx* public] + [fxsll public] + [fxsra public] + [fxlogor public] + [fxlogand public] + [fxlogxor public] + [fxlognot public] + [fxquotient public] + [fxremainder public] + [fxmodulo public] + ;;; fixnum predicates + [fxzero? public] + [fx= public] + [fx< public] + [fx<= public] + [fx> public] + [fx>= public] + ;;; characters + [char=? public] + [char? public] + [char>=? public] + [integer->char public] + [char->integer public] + ;;; lists + [cons public] + [car public] + [cdr public] + [caar public] + [cadr public] + [cdar public] + [cddr public] + [caaar public] + [caadr public] + [cadar public] + [caddr public] + [cdaar public] + [cdadr public] + [cddar public] + [cdddr public] + [caaaar public] + [caaadr public] + [caadar public] + [caaddr public] + [cadaar public] + [cadadr public] + [caddar public] + [cadddr public] + [cdaaar public] + [cdaadr public] + [cdadar public] + [cdaddr public] + [cddaar public] + [cddadr public] + [cdddar public] + [cddddr public] + [set-car! public] + [set-cdr! public] + [list public] + [list* ADDME] + [list? public] + [list-ref public] + [length public] + [make-list public] + [reverse public] + [append public] + [list-ref public] + [memq public] + [memv public] + [assq public] + [map public] + [for-each public] + [andmap public] + [ormap public] + ;;; vectors + [make-vector public] + [vector public] + [vector-length public] + [vector-ref public] + [vector-set! public] + [list->vector public] + [vector->list public] + ;;; strings + [make-string public] + [string public] + [string-length public] + [string-ref public] + [string-set! public] + [list->string public] + [string->list public] + [string-append public] + [substring public] + [string=? public] + [fixnum->string public] + ;;; symbols + [gensym public] + [gensym? public] + [symbol->string public] + [gensym->unique-string public] + [gensym-prefix public] + [gensym-count public] + [print-gensym public] + [string->symbol public] + [top-level-value public] + [top-level-bound? public] + [set-top-level-value! public] + [primitive-set! public] + [getprop public] + [putprop public] + [remprop public] + [property-list public] + [oblist public] + [uuid public] + ;;; eof + [eof-object public] + [void public] + ;;; control/debugging + [print-error public] + [error public] + [current-error-handler public] + [exit public] + [apply public] + [make-parameter public] + ;;; output + [output-port? public] + [console-output-port public] + [current-output-port public] + [standard-output-port public] + [standard-error-port public] + [open-output-file public] + [open-output-string public] + [with-output-to-file public] + [call-with-output-file public] + [with-input-from-file public] + [call-with-input-file public] + [get-output-string public] + [close-output-port public] + [flush-output-port public] + [write-char public] + [output-port-name public] + [newline public] + ;;; input + [input-port? public] + [standard-input-port public] + [console-input-port public] + [current-input-port public] + [open-input-file public] + [close-input-port public] + [reset-input-port! public] + [read-char public] + [peek-char public] + [unread-char public] + [input-port-name public] + ;;; writing/printing + [write public] + [display public] + [printf public] + [fprintf public] + [format public] + [read-token public] + [read public] + ;;; evaluation + [primitive? public] + [expand public] + [syntax-error public] + [current-expand public] + [expand-mode public] + [assembler-output public] + [compile-file public] + [fasl-write public] + + [$sc-put-cte public] + [sc-expand public] + [$make-environment public] + [environment? public] + [interaction-environment public] + [identifier? public] + [syntax->list public] + [syntax-object->datum public] + [datum->syntax-object public] + [generate-temporaries public] + [free-identifier=? public] + [bound-identifier=? public] + [literal-identifier=? public] + [syntax-error public] + [$syntax-dispatch public] + + + + [interpret public] + [eval public] + [current-eval public] + [load public] + [new-cafe public] + [collect public] + [call/cc public] + [call/cf library] + [dynamic-wind public] + [values public] + [call-with-values public] + [make-traced-procedure library] + [trace-symbol! library] + [untrace-symbol! library] + ;;; record + [$base-rtd library] + [record? public] + [record-rtd public] + [record-name public] + [record-printer public] + [record-length public] + [record-ref public] + [record-set! public] + ;;; record rtds + [make-record-type public] + [record-type-name public] + [record-type-descriptor public] + [record-type-symbol public] + [record-type-field-names public] + [record-constructor public] + [record-predicate public] + [record-field-accessor public] + [record-field-mutator public] + ;;; hash tables + [make-hash-table public] + [hash-table? public] + [get-hash-table public] + [put-hash-table! public] + ;;; asm + [make-code public] + [code? public] + [make-code-executable! public] + [code-instr-size public] + [code-reloc-size public] + [code-closure-size public] + [set-code-byte! public] + [set-code-word! public] + [set-code-object! public] + [set-code-foreign-object! public] + [set-code-object+offset! public] + [set-code-object+offset/rel! public] + [set-code-object/reloc/relative! public] + [code-reloc-vec public] + [code-code-vec public] + [code->closure public] + [list*->code* library] + ;;; + ;;; POSIX + ;;; + [fork public] + [posix-fork public] + [system public] + [$debug public] + [$underflow-misaligned-error public] + )) + + +(define (primitive? x) + (cond + [(assq x primitives-table) #t] + [(assq x open-coded-primitives) #t] + [else #f])) + +(define (open-codeable? x) + (cond + [(assq x open-coded-primitives) #t] + [(assq x primitives-table) #f] + [else (error 'open-codeable "invalid primitive ~s" x)])) + +(define (open-coded-primitive-args x) + (cond + [(assq x open-coded-primitives) => cadr] + [else (error 'open-coded-primitive-args "invalid ~s" x)])) + +;;; end of primitives table section + + +(define-record constant (value)) +(define-record code-loc (label)) +(define-record foreign-label (label)) +(define-record var (name)) +(define-record cp-var (idx)) +(define-record frame-var (idx)) +(define-record new-frame (base-idx size body)) +(define-record save-cp (loc)) +(define-record eval-cp (check body)) +(define-record return (value)) +(define-record call-cp + (call-convention rp-convention base-idx arg-count live-mask)) +(define-record primcall (op arg*)) +(define-record primref (name)) +(define-record conditional (test conseq altern)) +(define-record bind (lhs* rhs* body)) +(define-record seq (e0 e1)) +(define-record function (arg* proper body)) +(define-record clambda-case (arg* proper body)) +(define-record clambda (cases)) +(define-record clambda-code (label cases free)) + +(define-record closure (code free*)) +(define-record funcall (op rand*)) +(define-record appcall (op rand*)) +(define-record forcall (op rand*)) +(define-record code-rec (arg* proper free* body)) + +(define-record codes (list body)) +(define-record assign (lhs rhs)) + +(define unique-var + (let ([counter 0]) + (lambda (x) + (let ([g (gensym (format "~a:~a" x counter))]) + (set! counter (fxadd1 counter)) + (make-var g))))) + +(define (make-bind^ lhs* rhs* body) + (if (null? lhs*) + body + (make-bind lhs* rhs* body))) + +(define (recordize x) + (define (gen-fml* fml*) + (cond + [(pair? fml*) + (cons (unique-var (car fml*)) + (gen-fml* (cdr fml*)))] + [(symbol? fml*) + (unique-var fml*)] + [else '()])) + (define (properize fml*) + (cond + [(pair? fml*) + (cons (car fml*) (properize (cdr fml*)))] + [(null? fml*) '()] + [else (list fml*)])) + (define (extend-env fml* nfml* env) + (cons (cons fml* nfml*) env)) + (define (quoted-sym x) + (if (and (list? x) + (fx= (length x) 2) + (eq? 'quote (car x)) + (symbol? (cadr x))) + (cadr x) + (error 'quoted-sym "not a quoted symbol ~s" x))) + (define (quoted-string x) + (if (and (list? x) + (fx= (length x) 2) + (eq? 'quote (car x)) + (string? (cadr x))) + (cadr x) + (error 'quoted-string "not a quoted string ~s" x))) + (define (lookup^ x lhs* rhs*) + (cond + [(pair? lhs*) + (if (eq? x (car lhs*)) + (car rhs*) + (lookup^ x (cdr lhs*) (cdr rhs*)))] + [(eq? x lhs*) rhs*] + [else #f])) + (define (lookup x env) + (cond + [(pair? env) + (or (lookup^ x (caar env) (cdar env)) + (lookup x (cdr env)))] + [else #f])) + (define (E x env) + (cond + [(pair? x) + (case (car x) + [(quote) (make-constant (cadr x))] + [(if) + (make-conditional + (E (cadr x) env) + (E (caddr x) env) + (E (cadddr x) env))] + [(set!) + (let ([lhs (cadr x)] [rhs (caddr x)]) + (make-assign + (or (lookup lhs env) + (error 'recordize "invalid assignment ~s" x)) + (E rhs env)))] + [(begin) + (let f ([a (cadr x)] [d (cddr x)]) + (cond + [(null? d) (E a env)] + [else + (make-seq + (E a env) + (f (car d) (cdr d)))]))] + [(case-lambda) + (let ([cls* + (map + (lambda (cls) + (let ([fml* (car cls)] [body (cadr cls)]) + (let ([nfml* (gen-fml* fml*)]) + (let ([body (E body (extend-env fml* nfml* env))]) + (make-clambda-case + (properize nfml*) + (list? fml*) + body))))) + (cdr x))]) + (make-clambda cls*))] + [(foreign-call) + (let ([name (quoted-string (cadr x))] [arg* (cddr x)]) + (make-forcall name + (map (lambda (x) (E x env)) arg*)))] + [(|#primitive|) + (let ([var (cadr x)]) + (if (primitive? var) + (make-primref var) + (error 'recordize "invalid primitive ~s" var)))] + [(top-level-value) + (let ([var (quoted-sym (cadr x))]) + (cond + [(primitive? var) (make-primref var)] + [else (error 'recordize "invalid top-level var ~s" var)]))] + [(memv) + (make-funcall + (make-primref 'memq) + (map (lambda (x) (E x env)) (cdr x)))] + [($apply) + (let ([proc (cadr x)] [arg* (cddr x)]) + (make-appcall + (E proc env) + (map (lambda (x) (E x env)) arg*)))] + [(void) + (make-constant (void))] + [else + (make-funcall + (E (car x) env) + (map (lambda (x) (E x env)) (cdr x)))])] + [(symbol? x) + (or (lookup x env) + (error 'recordize "invalid reference in ~s" x))] + [else (error 'recordize "invalid expression ~s" x)])) + (E x '())) + + +(define (unparse x) + (define (E-args proper x) + (if proper + (map E x) + (let f ([a (car x)] [d (cdr x)]) + (cond + [(null? d) (E a)] + [else (cons (E a) (f (car d) (cdr d)))])))) + (define (E x) + (record-case x + [(constant c) `(quote ,c)] + [(code-loc x) `(code-loc ,x)] + [(var x) (string->symbol (format "v:~a" x))] + [(primref x) x] + [(conditional test conseq altern) + `(if ,(E test) ,(E conseq) ,(E altern))] + [(primcall op arg*) `(,op . ,(map E arg*))] + [(bind lhs* rhs* body) + `(let ,(map (lambda (lhs rhs) (list (E lhs) (E rhs))) lhs* rhs*) + ,(E body))] + [(seq e0 e1) `(begin ,(E e0) ,(E e1))] + [(function args proper body) + `(lambda ,(E-args proper args) ,(E body))] + [(clambda-case args proper body) + `(clambda-case ,(E-args proper args) ,(E body))] + [(clambda cls*) + `(case-lambda . ,(map E cls*))] + [(clambda-code label clauses free) + `(code ,label . ,(map E clauses))] + [(closure code free*) + `(closure ,(E code) ,(map E free*))] + [(code-rec arg* proper free* body) + `(code-rec [arg: ,(E-args proper arg*)] + [free: ,(map E free*)] + ,(E body))] + [(codes list body) + `(codes ,(map E list) + ,(E body))] + [(funcall rator rand*) `(funcall ,(E rator) . ,(map E rand*))] + [(appcall rator rand*) `(appcall ,(E rator) . ,(map E rand*))] + [(forcall rator rand*) `(foreign-call ,rator . ,(map E rand*))] + [(assign lhs rhs) `(set! ,(E lhs) ,(E rhs))] + [(return x) `(return ,(E x))] + [(new-frame base-idx size body) + `(new-frame [base: ,base-idx] + [size: ,size] + ,(E body))] + [(frame-var idx) + (string->symbol (format "fv.~a" idx))] + [(cp-var idx) + (string->symbol (format "cp.~a" idx))] + [(save-cp expr) + `(save-cp ,(E expr))] + [(eval-cp check body) + `(eval-cp ,check ,(E body))] + [(call-cp call-convention rp-convention base-idx arg-count live-mask) + `(call-cp [conv: ,call-convention] + [rpconv: ,rp-convention] + [base-idx: ,base-idx] + [arg-count: ,arg-count] + [live-mask: ,live-mask])] + [(foreign-label x) `(foreign-label ,x)] + [else (error 'unparse "invalid record ~s" x)])) + (E x)) + +(define (optimize-direct-calls x) + (define who 'optimize-direct-calls) + (define (make-conses ls) + (cond + [(null? ls) (make-constant '())] + [else + (make-primcall 'cons + (list (car ls) (make-conses (cdr ls))))])) + (define (properize lhs* rhs*) + (cond + [(null? lhs*) (error who "improper improper")] + [(null? (cdr lhs*)) + (list (make-conses rhs*))] + [else (cons (car rhs*) (properize (cdr lhs*) (cdr rhs*)))])) + (define (inline-case cls rand*) + (record-case cls + [(clambda-case fml* proper body) + (if proper + (and (fx= (length fml*) (length rand*)) + (make-bind fml* rand* body)) + (and (fx<= (length fml*) (length rand*)) + (make-bind fml* (properize fml* rand*) body)))])) + (define (try-inline cls* rand* default) + (cond + [(null? cls*) default] + [(inline-case (car cls*) rand*)] + [else (try-inline (cdr cls*) rand* default)])) + (define (inline rator rand*) + (record-case rator + [(clambda cls*) + (try-inline cls* rand* + (make-funcall rator rand*))] +; [(function fml* proper body) +; (cond +; [proper +; (if (fx= (length fml*) (length rand*)) +; (make-bind fml* rand* body) +; (begin +; (warning 'compile "possible application error in ~s" +; (unparse (make-funcall rator rand*))) +; (make-funcall rator rand*)))] +; [else +; (if (fx<= (length fml*) (length rand*)) +; (make-bind fml* (properize fml* rand*) body) +; (begin +; (warning 'compile "possible application error in ~s" +; (unparse (make-funcall rator rand*))) +; (make-funcall rator rand*)))])] + [else (make-funcall rator rand*)])) + (define (Expr x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional + (Expr test) + (Expr conseq) + (Expr altern))] + [(seq e0 e1) + (make-seq (Expr e0) (Expr e1))] + [(function fml* proper body) + (make-function fml* proper (Expr body))] + [(clambda cls*) + (make-clambda + (map (lambda (x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (Expr body))])) + cls*))] + [(primcall rator rand*) + (make-primcall rator (map Expr rand*))] + [(funcall rator rand*) + (inline (Expr rator) (map Expr rand*))] + [(appcall rator rand*) + (make-appcall (Expr rator) (map Expr rand*))] + [(forcall rator rand*) + (make-forcall rator (map Expr rand*))] + [(assign lhs rhs) + (make-assign lhs (Expr rhs))] + [else (error who "invalid expression ~s" (unparse x))])) + (Expr x)) + + + +(define (uncover-assigned x) + (define who 'uncover-assigned) + (define (Expr* x*) + (cond + [(null? x*) '()] + [else (union (Expr (car x*)) (Expr* (cdr x*)))])) + (define (Expr x) + (record-case x + [(constant) '()] + [(var) '()] + [(primref) '()] + [(bind lhs* rhs* body) + (union (Expr body) (Expr* rhs*))] + [(conditional test conseq altern) + (union (Expr test) (union (Expr conseq) (Expr altern)))] + [(seq e0 e1) (union (Expr e0) (Expr e1))] + [(clambda cls*) + (Expr* (map clambda-case-body cls*))] + [(function fml* proper body) (Expr body)] + [(primcall rator rand*) (Expr* rand*)] + [(funcall rator rand*) + (union (Expr rator) (Expr* rand*))] + [(appcall rator rand*) + (union (Expr rator) (Expr* rand*))] + [(forcall rator rand*) (Expr* rand*)] + [(assign lhs rhs) + (union (singleton lhs) (Expr rhs))] + [else (error who "invalid expression ~s" (unparse x))])) + (Expr x)) + +(define (rewrite-assignments assigned x) + (define who 'rewrite-assignments) + (define (fix lhs*) + (cond + [(null? lhs*) (values '() '() '())] + [else + (let ([x (car lhs*)]) + (let-values ([(lhs* a-lhs* a-rhs*) (fix (cdr lhs*))]) + (cond + [(memq x assigned) + (let ([t (make-var 'assignment-tmp)]) + (values (cons t lhs*) (cons x a-lhs*) (cons t a-rhs*)))] + [else + (values (cons x lhs*) a-lhs* a-rhs*)])))])) + (define (bind-assigned lhs* rhs* body) + (cond + [(null? lhs*) body] + [else + (make-bind lhs* + (map (lambda (rhs) (make-primcall 'vector (list rhs))) rhs*) + body)])) + (define (Expr x) + (record-case x + [(constant) x] + [(var) + (cond + [(memq x assigned) + (make-primcall '$vector-ref (list x (make-constant 0)))] + [else x])] + [(primref) x] + [(bind lhs* rhs* body) + (let-values ([(lhs* a-lhs* a-rhs*) (fix lhs*)]) + (make-bind lhs* (map Expr rhs*) + (bind-assigned a-lhs* a-rhs* (Expr body))))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (make-seq (Expr e0) (Expr e1))] + [(function fml* proper body) + (let-values ([(fml* a-lhs* a-rhs*) (fix fml*)]) + (make-function fml* proper + (bind-assigned a-lhs* a-rhs* (Expr body))))] + [(clambda cls*) + (make-clambda + (map (lambda (cls) + (record-case cls + [(clambda-case fml* proper body) + (let-values ([(fml* a-lhs* a-rhs*) (fix fml*)]) + (make-clambda-case fml* proper + (bind-assigned a-lhs* a-rhs* (Expr body))))])) + cls*))] + [(primcall op rand*) + (make-primcall op (map Expr rand*))] + [(forcall op rand*) + (make-forcall op (map Expr rand*))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall rator rand*) + (make-appcall (Expr rator) (map Expr rand*))] + [(assign lhs rhs) + (unless (memq lhs assigned) + (error 'rewrite-assignments "not assigned ~s in ~s" lhs x)) + (make-primcall '$vector-set! (list lhs (make-constant 0) (Expr rhs)))] + [else (error who "invalid expression ~s" (unparse x))])) + (Expr x)) + + +(define (remove-assignments x) + (let ([assigned (uncover-assigned x)]) + (rewrite-assignments assigned x))) + + +(define (convert-closures prog) + (define who 'convert-closures) + (define (Expr* x*) + (cond + [(null? x*) (values '() '())] + [else + (let-values ([(a a-free) (Expr (car x*))] + [(d d-free) (Expr* (cdr x*))]) + (values (cons a d) (union a-free d-free)))])) + (define (Expr ex) + (record-case ex + [(constant) (values ex '())] + [(var) (values ex (singleton ex))] + [(primref) (values ex '())] + [(bind lhs* rhs* body) + (let-values ([(rhs* rhs-free) (Expr* rhs*)] + [(body body-free) (Expr body)]) + (values (make-bind lhs* rhs* body) + (union rhs-free (difference body-free lhs*))))] + [(conditional test conseq altern) + (let-values ([(test test-free) (Expr test)] + [(conseq conseq-free) (Expr conseq)] + [(altern altern-free) (Expr altern)]) + (values (make-conditional test conseq altern) + (union test-free (union conseq-free altern-free))))] + [(seq e0 e1) + (let-values ([(e0 e0-free) (Expr e0)] + [(e1 e1-free) (Expr e1)]) + (values (make-seq e0 e1) (union e0-free e1-free)))] + [(function fml* proper body) + (let-values ([(body body-free) (Expr body)]) + (let ([free (difference body-free fml*)]) + (values (make-closure (make-code-rec fml* proper free body) free) + free)))] + [(clambda cls*) + (let-values ([(cls* free) + (let f ([cls* cls*]) + (cond + [(null? cls*) (values '() '())] + [else + (record-case (car cls*) + [(clambda-case fml* proper body) + (let-values ([(body body-free) (Expr body)] + [(cls* cls*-free) (f (cdr cls*))]) + (values + (cons (make-clambda-case fml* proper body) + cls*) + (union (difference body-free fml*) + cls*-free)))])]))]) + (values (make-closure (make-clambda-code (gensym) cls* free) free) + free))] + [(primcall op rand*) + (let-values ([(rand* rand*-free) (Expr* rand*)]) + (values (make-primcall op rand*) rand*-free))] + [(forcall op rand*) + (let-values ([(rand* rand*-free) (Expr* rand*)]) + (values (make-forcall op rand*) rand*-free))] + [(funcall rator rand*) + (let-values ([(rator rat-free) (Expr rator)] + [(rand* rand*-free) (Expr* rand*)]) + (values (make-funcall rator rand*) + (union rat-free rand*-free)))] + [(appcall rator rand*) + (let-values ([(rator rat-free) (Expr rator)] + [(rand* rand*-free) (Expr* rand*)]) + (values (make-appcall rator rand*) + (union rat-free rand*-free)))] + [else (error who "invalid expression ~s" (unparse ex))])) + (let-values ([(prog free) (Expr prog)]) + (unless (null? free) + (error 'convert-closures "free vars ~s encountered in ~a" + free (unparse prog))) + prog)) + + +(define (lift-codes x) + (define who 'lift-codes) + (define all-codes '()) + (define (do-code x) + (record-case x + [(clambda-code label cls* free) + (let ([cls* (map + (lambda (x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (E body))])) + cls*)]) + (let ([g (make-code-loc label)]) + (set! all-codes + (cons (make-clambda-code label cls* free) all-codes)) + g))])) + (define (E x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(bind lhs* rhs* body) + (make-bind lhs* (map E rhs*) (E body))] + [(conditional test conseq altern) + (make-conditional (E test) (E conseq) (E altern))] + [(seq e0 e1) (make-seq (E e0) (E e1))] + [(closure c free) (make-closure (do-code c) free)] + [(primcall op rand*) (make-primcall op (map E rand*))] + [(forcall op rand*) (make-forcall op (map E rand*))] + [(funcall rator rand*) (make-funcall (E rator) (map E rand*))] + [(appcall rator rand*) (make-appcall (E rator) (map E rand*))] + [else (error who "invalid expression ~s" (unparse x))])) + (let ([x (E x)]) + (make-codes all-codes x))) + + + + +(define (syntactically-valid? op rand*) + (define (valid-arg-count? op rand*) + (let ([n (open-coded-primitive-args op)] [m (length rand*)]) + (cond + [(eq? n 'any) #t] + [(eq? n 'no-code) + (error 'syntactically-valid + "should not primcall non codable prim ~s" op)] + [(fixnum? n) + (cond + [(fx= n m) #t] + [else + (error 'compile + "Possible incorrect number of args in ~s" + (cons op (map unparse rand*))) + #f])] + [else (error 'do-primcall "BUG: what ~s" n)]))) + (define (check op pred?) + (lambda (arg) + (record-case arg + [(constant c) + (cond + [(pred? c) #t] + [else + (error 'compile "Possible argument error to primitive ~s" op) + #f])] + [(primref) + (cond + [(pred? (lambda (x) x)) #t] + [else + (error 'compile "Possible argument error to primitive ~s" op) + #f])] + [else #t]))) + (define (nonnegative-fixnum? n) + (and (fixnum? n) (fx>= n 0))) + (define (byte? n) + (and (fixnum? n) (fx<= 0 n) (fx<= n 127))) + (define (valid-arg-types? op rand*) + (case op + [(fixnum? immediate? boolean? char? vector? string? procedure? + null? pair? not cons eq? vector symbol? error eof-object eof-object? + void $unbound-object? code? $forward-ptr? bwp-object? + pointer-value) + '#t] + [($fxadd1 $fxsub1 $fxzero? $fxlognot $fxlogor $fxlogand $fx+ $fx- $fx* + $fx= $fx< $fx<= $fx> $fx>= $fxquotient $fxmodulo $fxsll $fxsra $fxlogxor $exit) + (andmap (check op fixnum?) rand*)] + [($fixnum->char) + (andmap (check op byte?) rand*)] + [($char->fixnum $char= $char< $char<= $char> $char>= $string) + (andmap (check op char?) rand*)] + [($make-vector $make-string) + (andmap (check op nonnegative-fixnum?) rand*)] + [($car $cdr) + (andmap (check op pair?) rand*)] + [($vector-length) + (andmap (check op vector?) rand*)] + [($string-length) + (andmap (check op string?) rand*)] + [($set-car! $set-cdr!) + ((check op pair?) (car rand*))] + [($vector-ref $vector-set!) + (and ((check op vector?) (car rand*)) + ((check op nonnegative-fixnum?) (cadr rand*)))] + [($string-ref $string-set! + $string-ref-16+0 $string-ref-16+1 $string-ref-8+0 $string-ref-8+2) + (and ((check op string?) (car rand*)) + ((check op nonnegative-fixnum?) (cadr rand*)))] + [($symbol-string $symbol-unique-string) + (andmap (check op symbol?) rand*)] + [($constant-ref $set-constant! $intern $pcb-set! $pcb-ref $make-symbol + $symbol-value $set-symbol-value! $symbol-plist $set-symbol-plist! + $set-symbol-system-value! $set-symbol-system-value! + $set-symbol-unique-string! + $set-symbol-string! + $seal-frame-and-call $frame->continuation $code->closure + $code-instr-size $code-reloc-size $code-closure-size + $set-code-byte! $set-code-word! + $set-code-object! $set-code-object+offset! $set-code-object+offset/rel! + $make-record $record? $record-rtd $record-ref $record-set! + primitive-set! primitive-ref + $make-tcbucket $tcbucket-key $tcbucket-val $tcbucket-next + $set-tcbucket-val! $set-tcbucket-next! $set-tcbucket-tconc!) + #t] + [else (error 'valid-arg-types? "unhandled op ~s" op)])) + (and (valid-arg-count? op rand*) + (or (null? rand*) + (valid-arg-types? op rand*)))) + + +;;; the output of simplify-operands differs from the input in that the +;;; operands to primcalls are all simple (variables, primrefs, or constants). +;;; funcalls to open-codable primrefs whos arguments are "ok" are converted to +;;; primcalls. + +(define (introduce-primcalls x) + (define who 'introduce-primcalls) + (define (simple? x) + (or (constant? x) (var? x) (primref? x))) + (define (Expr x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(closure) x] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (make-seq (Expr e0) (Expr e1))] + [(primcall op arg*) + (case op + ;[(values) + ; (if (fx= (length arg*) 1) + ; (Expr (car arg*)) + ; (begin + ; (warning 'compile "possible incorrect number of values") + ; (make-funcall (make-primref 'values) (map Expr arg*))))] + [else + (make-primcall op (map Expr arg*))])] + [(forcall op arg*) + (make-forcall op (map Expr arg*))] + [(funcall rator rand*) + (cond + [(and (primref? rator) + (open-codeable? (primref-name rator)) + (syntactically-valid? (primref-name rator) rand*)) + (Expr (make-primcall (primref-name rator) rand*))] + [else + (make-funcall (Expr rator) (map Expr rand*))])] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (Tail x) + (record-case x + [(constant) (make-return x)] + [(var) (make-return x)] + [(primref) (make-return x)] + [(closure) (make-return x)] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Tail body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Tail conseq) (Tail altern))] + [(seq e0 e1) (make-seq (Expr e0) (Tail e1))] + [(primcall op arg*) + (case op + ;[(values) + ; (if (fx= (length arg*) 1) + ; (make-return (Expr (car arg*))) + ; (make-return* (map Expr arg*)))] + [else + (make-return (make-primcall op (map Expr arg*)))])] + [(forcall op arg*) + (make-return (make-forcall op (map Expr arg*)))] + [(funcall rator rand*) + (cond + [(and (primref? rator) + (open-codeable? (primref-name rator)) + (syntactically-valid? (primref-name rator) rand*)) + (Tail (make-primcall (primref-name rator) rand*))] + [else + (make-funcall (Expr rator) (map Expr rand*))])] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (CaseExpr x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (Tail body))])) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (make-clambda-code L (map CaseExpr cases) free)])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) (Tail body))])) + (CodesExpr x)) + + +(define (simplify-operands x) + (define who 'simplify-operands) + (define (simple? x) + (or (constant? x) (var? x) (primref? x))) + (define (simplify arg lhs* rhs* k) + (if (simple? arg) + (k arg lhs* rhs*) + (let ([v (unique-var 'tmp)]) + (k v (cons v lhs*) (cons (Expr arg) rhs*))))) + (define (simplify* arg* lhs* rhs* k) + (cond + [(null? arg*) (k '() lhs* rhs*)] + [else + (simplify (car arg*) lhs* rhs* + (lambda (a lhs* rhs*) + (simplify* (cdr arg*) lhs* rhs* + (lambda (d lhs* rhs*) + (k (cons a d) lhs* rhs*)))))])) + (define (Expr x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(closure) x] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (make-seq (Expr e0) (Expr e1))] + [(primcall op arg*) + (simplify* arg* '() '() + (lambda (arg* lhs* rhs*) + (make-bind^ lhs* rhs* + (make-primcall op arg*))))] + [(forcall op arg*) + (make-forcall op (map Expr arg*))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (Tail x) + (record-case x + [(return v) (make-return (Expr v))] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Tail body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Tail conseq) (Tail altern))] + [(seq e0 e1) (make-seq (Expr e0) (Tail e1))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (CaseExpr x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (Tail body))])) + (define (CodeExpr x) + (record-case x + [(clambda-code L clauses free) + (make-clambda-code L (map CaseExpr clauses) free)])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) (Tail body))])) + (CodesExpr x)) + + +(define (insert-stack-overflow-checks x) + (define who 'insert-stack-overflow-checks) + (define (insert-check body) + (make-seq + (make-conditional + (make-primcall '$fp-overflow '()) + (make-funcall (make-primref 'do-stack-overflow) '()) + (make-primcall 'void '())) + body)) + (define (Expr x) + (record-case x + [(constant) #f] + [(var) #f] + [(primref) #f] + [(closure code free*) #f] + [(bind lhs* rhs* body) + (or (ormap Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (or (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (or (Expr e0) (Expr e1))] + [(primcall op arg*) (ormap Expr arg*)] + [(forcall op arg*) (ormap Expr arg*)] + [(funcall rator arg*) #t] + [(appcall rator arg*) #t] + [else (error who "invalid expression ~s" (unparse x))])) + (define (Tail x) + (record-case x + [(return v) (Expr v)] + [(bind lhs* rhs* body) + (or (ormap Expr rhs*) (Tail body))] + [(conditional test conseq altern) + (or (Expr test) (Tail conseq) (Tail altern))] + [(seq e0 e1) (or (Expr e0) (Tail e1))] + [(funcall rator arg*) (or (Expr rator) (ormap Expr arg*))] + [(appcall rator arg*) (or (Expr rator) (ormap Expr arg*))] + [else (error who "invalid tail expression ~s" (unparse x))])) + (define (CaseExpr x) + (record-case x + [(clambda-case fml* proper body) + (if (Tail body) + (make-clambda-case fml* proper (insert-check body)) + x)])) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (make-clambda-code L (map CaseExpr cases) free)])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) + (if (Tail body) + (insert-check body) + body))])) + (CodesExpr x)) + + +(define (insert-allocation-checks x) + (define who 'insert-allocation-checks) + (define (check-bytes n var body) + (make-seq + (make-conditional + (make-primcall '$ap-check-bytes + (list (make-constant n) var)) + (make-funcall (make-primref 'do-overflow) + (list + (make-primcall '$fx+ + (list (make-constant n) var)))) + (make-primcall 'void '())) + body)) + (define (check-words n var body) + (make-seq + (make-conditional + (make-primcall '$ap-check-words + (list (make-constant n) var)) + (make-funcall (make-primref 'do-overflow-words) + (list + (make-primcall '$fx+ + (list (make-constant n) var)))) + (make-primcall 'void '())) + body)) + (define (check-const n body) + (make-seq + (make-conditional + (make-primcall '$ap-check-const + (list (make-constant n))) + (make-funcall (make-primref 'do-overflow) + (list (make-constant n))) + (make-primcall 'void '())) + body)) + (define (Expr x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(closure code free*) + (check-const (fx+ disp-closure-data (fx* (length free*) wordsize)) x)] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (make-seq (Expr e0) (Expr e1))] + [(primcall op arg*) + (let ([x (make-primcall op (map Expr arg*))]) + (case op + [(cons) (check-const pair-size x)] + [($make-symbol) (check-const symbol-size x)] + [($make-tcbucket) (check-const tcbucket-size x)] + [($frame->continuation $code->closure) + (check-const (fx+ disp-closure-data (fx* (length arg*) wordsize)) x)] + [($make-string) + (record-case (car arg*) + [(constant i) + (check-const (fx+ i (fx+ disp-string-data 1)) x)] + [else + (check-bytes (fxadd1 disp-string-data) (car arg*) x)])] + [($string) + (check-const (fx+ (length arg*) (fx+ disp-string-data 1)) x)] + [($make-vector) + (record-case (car arg*) + [(constant i) + (check-const (fx+ (fx* i wordsize) disp-vector-data) x)] + [else + (check-words (fxadd1 disp-vector-data) (car arg*) x)])] + [($make-record) + (record-case (cadr arg*) + [(constant i) + (check-const (fx+ (fx* i wordsize) disp-record-data) x)] + [else + (check-words (fxadd1 disp-record-data) (cadr arg*) x)])] + [(vector) + (check-const (fx+ (fx* (length arg*) wordsize) disp-vector-data) x)] + [else x]))] + [(forcall op arg*) + (make-forcall op (map Expr arg*))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (Tail x) + (record-case x + [(return v) (make-return (Expr v))] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Tail body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Tail conseq) (Tail altern))] + [(seq e0 e1) (make-seq (Expr e0) (Tail e1))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (CaseExpr x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (Tail body))])) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (make-clambda-code L (map CaseExpr cases) free)])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) (Tail body))])) + (CodesExpr x)) + + +(define (remove-local-variables x) + (define who 'remove-local-variables) + (define (simple* x* r) + (map (lambda (x) + (cond + [(assq x r) => cdr] + [else + (when (var? x) (error who "unbound var ~s" x)) + x])) + x*)) + (define (env->mask r sz) + (let ([s (make-vector (fxsra (fx+ sz 7) 3) 0)]) + (for-each + (lambda (idx) + (let ([q (fxsra idx 3)] + [r (fxlogand idx 7)]) + (vector-set! s q + (fxlogor (vector-ref s q) (fxsll 1 r))))) + r) + s)) + (define (do-new-frame op rand* si r call-convention rp-convention orig-live) + (make-new-frame (fxadd1 si) (fx+ (length rand*) 2) + (let f ([r* rand*] [nsi (fx+ si 2)] [live orig-live]) + (cond + [(null? r*) + (make-seq + (make-seq + (make-save-cp (make-frame-var si)) + (case call-convention + [(normal apply) + (make-eval-cp #t (Expr op nsi r (cons si live)))] + [(foreign) + (make-eval-cp #f (make-foreign-label op))] + [else (error who "invalid convention ~s" call-convention)])) + (make-call-cp call-convention + rp-convention + (fxadd1 si) ; frame size + (length rand*) ; argc + (env->mask (cons si orig-live) ; cp and everything before it + (fxadd1 si))))] ; mask-size ~~ frame size + [else + (make-seq + (make-assign (make-frame-var nsi) + (Expr (car r*) nsi r live)) + (f (cdr r*) (fxadd1 nsi) (cons nsi live)))])))) + (define (nop) (make-primcall 'void '())) + (define (do-bind lhs* rhs* body si r live k) + (let f ([lhs* lhs*] [rhs* rhs*] [si si] [nr r] [live live]) + (cond + [(null? lhs*) (k body si nr live)] + [else + (let ([v (make-frame-var si)]) + (make-seq + (make-assign v (Expr (car rhs*) si r live)) + (f (cdr lhs*) (cdr rhs*) (fxadd1 si) + (cons (cons (car lhs*) v) nr) + (cons si live))))]))) + (define (Tail x si r live) + (record-case x + [(return v) (make-return (Expr v si r live))] + [(bind lhs* rhs* body) + (do-bind lhs* rhs* body si r live Tail)] + [(conditional test conseq altern) + (make-conditional + (Expr test si r live) + (Tail conseq si r live) + (Tail altern si r live))] + [(seq e0 e1) (make-seq (Effect e0 si r live) (Tail e1 si r live))] + [(primcall op arg*) + (case op +; [(values) (make-primcall op (simple* arg* r))] + [else (make-return (make-primcall op (simple* arg* r)))])] + [(funcall op rand*) + (do-new-frame op rand* si r 'normal 'tail live)] + [(appcall op rand*) + (do-new-frame op rand* si r 'apply 'tail live)] + [else (error who "invalid expression ~s" (unparse x))])) + (define (Effect x si r live) + (record-case x + [(constant) (nop)] + [(var) (nop)] + [(primref) (nop)] + [(closure code free*) (nop)] + [(bind lhs* rhs* body) + (do-bind lhs* rhs* body si r live Effect)] + [(conditional test conseq altern) + (make-conditional + (Expr test si r live) + (Effect conseq si r live) + (Effect altern si r live))] + [(seq e0 e1) (make-seq (Effect e0 si r live) (Effect e1 si r live))] + [(primcall op arg*) + (make-primcall op (simple* arg* r))] + [(forcall op rand*) + (do-new-frame op rand* si r 'foreign 'effect live)] + [(funcall op rand*) + (do-new-frame op rand* si r 'normal 'effect live)] + [(appcall op rand*) + (do-new-frame op rand* si r 'apply 'effect live)] + [else (error who "invalid effect expression ~s" (unparse x))])) + (define (Expr x si r live) + (record-case x + [(constant) x] + [(var) + (cond + [(assq x r) => cdr] + [else (error who "unbound var ~s" x)])] + [(primref) x] + [(closure code free*) + (make-closure code (simple* free* r))] + [(bind lhs* rhs* body) + (do-bind lhs* rhs* body si r live Expr)] + [(conditional test conseq altern) + (make-conditional + (Expr test si r live) + (Expr conseq si r live) + (Expr altern si r live))] + [(seq e0 e1) (make-seq (Effect e0 si r live) (Expr e1 si r live))] + [(primcall op arg*) + (make-primcall op (simple* arg* r))] + [(forcall op rand*) + (do-new-frame op rand* si r 'foreign 'value live)] + [(funcall op rand*) + (do-new-frame op rand* si r 'normal 'value live)] + [(appcall op rand*) + (do-new-frame op rand* si r 'apply 'value live)] + [else (error who "invalid expression ~s" (unparse x))])) + (define (bind-fml* fml* r) + (let f ([si 1] [fml* fml*]) + (cond + [(null? fml*) (values '() si r '())] + [else + (let-values ([(nfml* nsi r live) (f (fxadd1 si) (cdr fml*))]) + (let ([v (make-frame-var si)]) + (values (cons v nfml*) + nsi + (cons (cons (car fml*) v) r) + (cons si live))))]))) + (define (bind-free* free*) + (let f ([free* free*] [idx 0] [r '()]) + (cond + [(null? free*) r] + [else + (f (cdr free*) (fxadd1 idx) + (cons (cons (car free*) (make-cp-var idx)) r))]))) + (define CaseExpr + (lambda (r) + (lambda (x) + (record-case x + [(clambda-case fml* proper body) + (let-values ([(fml* si r live) (bind-fml* fml* r)]) + (make-clambda-case fml* proper (Tail body si r live)))])))) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (let ([r (bind-free* free)]) + (make-clambda-code L (map (CaseExpr r) cases) free))])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) + (Tail body 1 '() '()))])) + (CodesExpr x)) + + +(begin + (define fx-shift 2) + (define fx-mask #x03) + (define fx-tag 0) + (define bool-f #x2F) + (define bool-t #x3F) + (define bool-mask #xEF) + (define bool-tag #x2F) + (define bool-shift 4) + (define nil #x4F) + (define eof #x5F) ; double check + (define unbound #x6F) ; double check + (define void-object #x7F) ; double check + (define bwp-object #x8F) ; double check + (define char-shift 8) + (define char-tag #x0F) + (define char-mask #xFF) + (define pair-mask 7) + (define pair-tag 1) + (define disp-car 0) + (define disp-cdr 4) + (define pair-size 8) + (define pagesize 4096) + (define pageshift 12) + (define wordsize 4) + (define wordshift 2) + + (define symbol-mask 7) + (define symbol-tag 2) + (define disp-symbol-string 0) + (define disp-symbol-unique-string 4) + (define disp-symbol-value 8) + (define disp-symbol-plist 12) + (define disp-symbol-system-value 16) + (define disp-symbol-system-plist 20) + (define symbol-size 24) + (define vector-tag 5) + (define vector-mask 7) + (define disp-vector-length 0) + (define disp-vector-data 4) + (define string-mask 7) + (define string-tag 6) + (define disp-string-length 0) + (define disp-string-data 4) + (define closure-mask 7) + (define closure-tag 3) + (define disp-closure-data 4) + (define disp-closure-code 0) + (define continuation-size 16) + (define continuation-tag #x1F) + (define disp-continuation-top 4) + (define disp-continuation-size 8) + (define disp-continuation-next 12) + (define code-tag #x2F) + (define disp-code-instrsize 4) + (define disp-code-relocsize 8) + (define disp-code-closuresize 12) + (define disp-code-data 16) + (define disp-tcbucket-tconc 0) + (define disp-tcbucket-key 4) + (define disp-tcbucket-val 8) + (define disp-tcbucket-next 12) + (define tcbucket-size 16) + + (define record-ptag 5) + (define record-pmask 7) + (define disp-record-rtd 0) + (define disp-record-data 4) + (define disp-frame-size -17) + (define disp-frame-offset -13) + (define disp-multivalue-rp -9) + (define object-alignment 8) + (define align-shift 3) + (define dirty-word -1)) + +(begin + (define (mem off val) + (cond + [(fixnum? off) (list 'disp (int off) val)] + [(register? off) (list 'disp off val)] + [else (error 'mem "invalid disp ~s" off)])) + (define (int x) (list 'int x)) + (define (obj x) (list 'obj x)) + (define (byte x) (list 'byte x)) + (define (byte-vector x) (list 'byte-vector x)) + (define (movzbl src targ) (list 'movzbl src targ)) + (define (sall src targ) (list 'sall src targ)) + (define (sarl src targ) (list 'sarl src targ)) + (define (shrl src targ) (list 'shrl src targ)) + (define (notl src) (list 'notl src)) + (define (pushl src) (list 'pushl src)) + (define (popl src) (list 'popl src)) + (define (orl src targ) (list 'orl src targ)) + (define (xorl src targ) (list 'xorl src targ)) + (define (andl src targ) (list 'andl src targ)) + (define (movl src targ) (list 'movl src targ)) + (define (movb src targ) (list 'movb src targ)) + (define (addl src targ) (list 'addl src targ)) + (define (imull src targ) (list 'imull src targ)) + (define (idivl src) (list 'idivl src)) + (define (subl src targ) (list 'subl src targ)) + (define (push src) (list 'push src)) + (define (pop targ) (list 'pop targ)) + (define (sete targ) (list 'sete targ)) + (define (call targ) (list 'call targ)) + (define (tail-indirect-cpr-call) + (jmp (mem (fx- disp-closure-code closure-tag) cpr))) + (define (indirect-cpr-call) + (call (mem (fx- disp-closure-code closure-tag) cpr))) + (define (negl targ) (list 'negl targ)) + (define (label x) (list 'label x)) + (define (label-address x) (list 'label-address x)) + (define (ret) '(ret)) + (define (cltd) '(cltd)) + (define (cmpl arg1 arg2) (list 'cmpl arg1 arg2)) + (define (je label) (list 'je label)) + (define (jne label) (list 'jne label)) + (define (jle label) (list 'jle label)) + (define (jge label) (list 'jge label)) + (define (jg label) (list 'jg label)) + (define (jl label) (list 'jl label)) + (define (jb label) (list 'jb label)) + (define (ja label) (list 'ja label)) + (define (jmp label) (list 'jmp label)) + (define edi '%edx) ; closure pointer + (define esi '%esi) ; pcb + (define ebp '%ebp) ; allocation pointer + (define esp '%esp) ; stack base pointer + (define al '%al) + (define ah '%ah) + (define bh '%bh) + (define cl '%cl) + (define eax '%eax) + (define ebx '%ebx) + (define ecx '%ecx) + (define edx '%edx) + (define apr '%ebp) + (define fpr '%esp) + (define cpr '%edi) + (define pcr '%esi) + (define register? symbol?) + (define (argc-convention n) + (fx- 0 (fxsll n fx-shift)))) + + +(define pcb-ref + (lambda (x) + (case x + [(allocation-pointer) (mem 0 pcr)] + [(allocation-redline) (mem 4 pcr)] + [(frame-pointer) (mem 8 pcr)] + [(frame-base) (mem 12 pcr)] + [(frame-redline) (mem 16 pcr)] + [(next-continuation) (mem 20 pcr)] + [(system-stack) (mem 24 pcr)] + [(dirty-vector) (mem 28 pcr)] + [else (error 'pcb-ref "invalid arg ~s" x)]))) + +(define (primref-loc op) + (unless (symbol? op) (error 'primref-loc "not a symbol ~s" op)) + (mem (fx- disp-symbol-system-value symbol-tag) + (obj op))) + +(define (generate-code x) + (define who 'generate-code) + (define (rp-label x) + (case x + [(value) (label-address SL_multiple_values_error_rp)] + [(effect) (label-address SL_multiple_values_ignore_rp)] + [else (error who "invalid rp-convention ~s" x)])) + (define (align n) + (fxsll (fxsra (fx+ n (fxsub1 object-alignment)) align-shift) align-shift)) + (define unique-label + (lambda () + (label (gensym)))) + (define (constant-val x) + (cond + [(fixnum? x) (obj x)] + [(boolean? x) (int (if x bool-t bool-f))] + [(null? x) (int nil)] + [(char? x) (int (fx+ (fxsll (char->integer x) char-shift) char-tag))] + [(eq? x (void)) (int void-object)] + [else (obj x)])) + (define (cond-branch op Lt Lf ac) + (define (opposite x) + (cadr (assq x '([je jne] [jl jge] [jle jg] [jg jle] [jge jl])))) + (unless (or Lt Lf) + (error 'cond-branch "no labels")) + (cond + [(not Lf) (cons (list op Lt) ac)] + [(not Lt) (cons (list (opposite op) Lf) ac)] + [else (list* (list op Lt) (jmp Lf) ac)])) + (define (indirect-type-pred pri-mask pri-tag sec-mask sec-tag rand* Lt Lf ac) + (cond + [(and Lt Lf) + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int pri-mask) ebx) + (cmpl (int pri-tag) ebx) + (jne Lf) + (movl (mem (fx- 0 pri-tag) eax) ebx) + (if sec-mask + (andl (int sec-mask) ebx) + '(nop)) + (cmpl (int sec-tag) ebx) + (jne Lf) + (jmp Lt) + ac)] + [Lf + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int pri-mask) ebx) + (cmpl (int pri-tag) ebx) + (jne Lf) + (movl (mem (fx- 0 pri-tag) eax) ebx) + (if sec-mask + (andl (int sec-mask) ebx) + '(nop)) + (cmpl (int sec-tag) ebx) + (jne Lf) + ac)] + [Lt + (let ([L_END (unique-label)]) + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int pri-mask) ebx) + (cmpl (int pri-tag) ebx) + (jne L_END) + (movl (mem (fx- 0 pri-tag) eax) ebx) + (if sec-mask + (andl (int sec-mask) ebx) + '(nop)) + (cmpl (int sec-tag) ebx) + (je Lt) + L_END + ac))] + [else ac])) + (define (type-pred mask tag rand* Lt Lf ac) + (cond + [mask + (list* + (movl (Simple (car rand*)) eax) + (andl (int mask) eax) + (cmpl (int tag) eax) + (cond-branch 'je Lt Lf ac))] + [else + (let ([v (Simple (car rand*))]) + (cond + [(memq (car v) '(mem register)) + (list* + (cmpl (int tag) (Simple (car rand*))) + (cond-branch 'je Lt Lf ac))] + [else + (list* + (movl (Simple (car rand*)) eax) + (cmpl (int tag) eax) + (cond-branch 'je Lt Lf ac))]))])) + (define (compare-and-branch op rand* Lt Lf ac) + (define (opposite x) + (cadr (assq x '([je je] [jl jg] [jle jge] [jg jl] [jge jle])))) + (cond + [(and (constant? (car rand*)) (constant? (cadr rand*))) + (list* + (movl (Simple (car rand*)) eax) + (cmpl (Simple (cadr rand*)) eax) + (cond-branch op Lt Lf ac))] + [(constant? (cadr rand*)) + (list* + (cmpl (Simple (cadr rand*)) (Simple (car rand*))) + (cond-branch op Lt Lf ac))] + [(constant? (car rand*)) + (list* + (cmpl (Simple (car rand*)) (Simple (cadr rand*))) + (cond-branch (opposite op) Lt Lf ac))] + [else + (list* + (movl (Simple (car rand*)) eax) + (cmpl (Simple (cadr rand*)) eax) + (cond-branch op Lt Lf ac))])) + (define (do-pred-prim op rand* Lt Lf ac) + (case op + [(fixnum?) (type-pred fx-mask fx-tag rand* Lt Lf ac)] + [(pair?) (type-pred pair-mask pair-tag rand* Lt Lf ac)] + [(char?) (type-pred char-mask char-tag rand* Lt Lf ac)] + [(string?) (type-pred string-mask string-tag rand* Lt Lf ac)] + [(symbol?) (type-pred symbol-mask symbol-tag rand* Lt Lf ac)] + [(procedure?) (type-pred closure-mask closure-tag rand* Lt Lf ac)] + [(boolean?) (type-pred bool-mask bool-tag rand* Lt Lf ac)] + [(null?) (type-pred #f nil rand* Lt Lf ac)] + [($unbound-object?) (type-pred #f unbound rand* Lt Lf ac)] + [($forward-ptr?) (type-pred #f -1 rand* Lt Lf ac)] + [(not) (type-pred #f bool-f rand* Lt Lf ac)] + [(eof-object?) (type-pred #f eof rand* Lt Lf ac)] + [(bwp-object?) (type-pred #f bwp-object rand* Lt Lf ac)] + [($fxzero?) (type-pred #f 0 rand* Lt Lf ac)] + [($fx= $char= eq?) (compare-and-branch 'je rand* Lt Lf ac)] + [($fx< $char<) (compare-and-branch 'jl rand* Lt Lf ac)] + [($fx<= $char<=) (compare-and-branch 'jle rand* Lt Lf ac)] + [($fx> $char>) (compare-and-branch 'jg rand* Lt Lf ac)] + [($fx>= $char>=) (compare-and-branch 'jge rand* Lt Lf ac)] + [(vector?) + (indirect-type-pred vector-mask vector-tag fx-mask fx-tag + rand* Lt Lf ac)] + [($record?) + (indirect-type-pred record-pmask record-ptag record-pmask record-ptag + rand* Lt Lf ac)] + [(code?) + (indirect-type-pred vector-mask vector-tag #f code-tag + rand* Lt Lf ac)] + [(immediate?) + (cond + [(and Lt Lf) + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int fx-mask) ebx) + (cmpl (int 0) ebx) + (je Lt) + (andl (int 7) eax) + (cmpl (int 7) eax) + (je Lt) + (jmp Lf) + ac)] + [Lt + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int fx-mask) ebx) + (cmpl (int 0) ebx) + (je Lt) + (andl (int 7) eax) + (cmpl (int 7) eax) + (je Lt) + ac)] + [Lf + (let ([Ljoin (unique-label)]) + (list* + (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int fx-mask) ebx) + (cmpl (int 0) ebx) + (je Ljoin) + (andl (int 7) eax) + (cmpl (int 7) eax) + (jne Lf) + Ljoin + ac))] + [else ac])] + [($ap-check-words) + (record-case (car rand*) + [(constant i) + (list* (movl (pcb-ref 'allocation-redline) eax) + (subl (Simple (cadr rand*)) eax) + (subl (int i) eax) + (cmpl eax apr) + (cond-branch 'jge Lt Lf ac))] + [else (error who "ap-check-words")])] + [($ap-check-bytes) + (record-case (car rand*) + [(constant i) + (list* (movl (Simple (cadr rand*)) eax) + (negl eax) + (addl (pcb-ref 'allocation-redline) eax) + (subl (int i) eax) + (cmpl eax apr) + (cond-branch 'jge Lt Lf ac))] + [else (error who "ap-check-bytes")])] + [($ap-check-const) + (record-case (car rand*) + [(constant i) + (if (fx< i pagesize) + (list* + (cmpl (pcb-ref 'allocation-redline) apr) + (cond-branch 'jge Lt Lf ac)) + (list* + (movl (pcb-ref 'allocation-redline) eax) + (subl (int i) eax) + (cmpl eax apr) + (cond-branch 'jge Lt Lf ac)))] + [else (error who "ap-check-const")])] + [($fp-at-base) + (list* + (movl (pcb-ref 'frame-base) eax) + (subl (int wordsize) eax) + (cmpl eax fpr) + (cond-branch 'je Lt Lf ac))] + [($fp-overflow) + (list* (cmpl (pcb-ref 'frame-redline) fpr) + (cond-branch 'jle Lt Lf ac))] + [($vector-ref) + (do-value-prim op rand* + (do-simple-test eax Lt Lf ac))] + [(cons void $fxadd1 $fxsub1) + ;;; always true + (do-effect-prim op rand* + (cond + [(not Lt) ac] + [else (cons (jmp Lt) ac)]))] + [else + (error 'pred-prim "HERE unhandled ~s" op)])) + (define (do-pred->value-prim op rand* ac) + (case op + [else + (let ([Lf (unique-label)] [Lj (unique-label)]) + (do-pred-prim op rand* #f Lf + (list* (movl (constant-val #t) eax) + (jmp Lj) + Lf + (movl (constant-val #f) eax) + Lj + ac)))])) + (define (indirect-ref arg* off ac) + (list* + (movl (Simple (car arg*)) eax) + (movl (mem off eax) eax) + ac)) + (define (do-value-prim op arg* ac) + (case op + [(eof-object) (cons (movl (int eof) eax) ac)] + [(void) (cons (movl (int void-object) eax) ac)] + [($fxadd1) + (list* (movl (Simple (car arg*)) eax) + (addl (constant-val 1) eax) + ac)] + [($fxsub1) + (list* (movl (Simple (car arg*)) eax) + (addl (constant-val -1) eax) + ac)] + [($fx+) + (list* (movl (Simple (car arg*)) eax) + (addl (Simple (cadr arg*)) eax) + ac)] + [($fx-) + (list* (movl (Simple (car arg*)) eax) + (subl (Simple (cadr arg*)) eax) + ac)] + [($fx*) + (cond + [(constant? (car arg*)) + (record-case (car arg*) + [(constant c) + (unless (fixnum? c) + (error who "invalid arg ~s to fx*" c)) + (list* (movl (Simple (cadr arg*)) eax) + (imull (int c) eax) + ac)])] + [(constant? (cadr arg*)) + (record-case (cadr arg*) + [(constant c) + (unless (fixnum? c) + (error who "invalid arg ~s to fx*" c)) + (list* (movl (Simple (car arg*)) eax) + (imull (int c) eax) + ac)])] + [else + (list* (movl (Simple (car arg*)) eax) + (sarl (int fx-shift) eax) + (imull (Simple (cadr arg*)) eax) + ac)])] + [($fxquotient) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ecx) + (cltd) + (idivl ecx) + (sall (int fx-shift) eax) + ac)] + [($fxmodulo) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl eax ecx) + (xorl ebx ecx) + (sarl (int (fxsub1 (fx* wordsize 8))) ecx) + (andl ebx ecx) + (cltd) + (idivl ebx) + (movl edx eax) + (addl ecx eax) + ac)] + [($fxlogor) + (list* (movl (Simple (car arg*)) eax) + (orl (Simple (cadr arg*)) eax) + ac)] + [($fxlogand) + (list* (movl (Simple (car arg*)) eax) + (andl (Simple (cadr arg*)) eax) + ac)] + [($fxlogxor) + (list* (movl (Simple (car arg*)) eax) + (xorl (Simple (cadr arg*)) eax) + ac)] + [($fxsra) + (record-case (cadr arg*) + [(constant i) + (unless (fixnum? i) (error who "invalid arg to fxsra")) + (list* (movl (Simple (car arg*)) eax) + (sarl (int (fx+ i fx-shift)) eax) + (sall (int fx-shift) eax) + ac)] + [else + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ecx) + (sarl (int fx-shift) ecx) + (sarl (int fx-shift) eax) + (sarl cl eax) + (sall (int fx-shift) eax) + ac)])] + [($fxsll) + (record-case (cadr arg*) + [(constant i) + (unless (fixnum? i) (error who "invalid arg to fxsll")) + (list* (movl (Simple (car arg*)) eax) + (sall (int i) eax) + ac)] + [else + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ecx) + (sarl (int fx-shift) ecx) + (sall cl eax) + ac)])] + [($fixnum->char) + (list* (movl (Simple (car arg*)) eax) + (sall (int (fx- char-shift fx-shift)) eax) + (orl (int char-tag) eax) + ac)] + [($char->fixnum) + (list* (movl (Simple (car arg*)) eax) + (sarl (int (fx- char-shift fx-shift)) eax) + ac)] + [($fxlognot) + (list* (movl (Simple (car arg*)) eax) + (orl (int fx-mask) eax) + (notl eax) + ac)] + [($car) (indirect-ref arg* (fx- disp-car pair-tag) ac)] + [($cdr) (indirect-ref arg* (fx- disp-cdr pair-tag) ac)] + [($vector-length) + (indirect-ref arg* (fx- disp-vector-length vector-tag) ac)] + [($string-length) + (indirect-ref arg* (fx- disp-string-length string-tag) ac)] + [($symbol-string) + (indirect-ref arg* (fx- disp-symbol-string symbol-tag) ac)] + [($symbol-unique-string) + (indirect-ref arg* (fx- disp-symbol-unique-string symbol-tag) ac)] + [($symbol-value) + (indirect-ref arg* (fx- disp-symbol-value symbol-tag) ac)] + [(primitive-ref) + (indirect-ref arg* (fx- disp-symbol-system-value symbol-tag) ac)] + [($tcbucket-key) + (indirect-ref arg* (fx- disp-tcbucket-key vector-tag) ac)] + [($tcbucket-val) + (indirect-ref arg* (fx- disp-tcbucket-val vector-tag) ac)] + [($tcbucket-next) + (indirect-ref arg* (fx- disp-tcbucket-next vector-tag) ac)] + [(pointer-value) + (list* + (movl (Simple (car arg*)) eax) + (sarl (int fx-shift) eax) + (sall (int fx-shift) eax) + ac)] + [($symbol-plist) + (indirect-ref arg* (fx- disp-symbol-plist symbol-tag) ac)] + [($record-rtd) + (indirect-ref arg* (fx- disp-record-rtd record-ptag) ac)] + [($constant-ref) + (list* (movl (Simple (car arg*)) eax) ac)] + [($vector-ref) + (list* (movl (Simple (car arg*)) ebx) + (addl (Simple (cadr arg*)) ebx) + (movl (mem (fx- disp-vector-data vector-tag) ebx) eax) + ac)] + [($record-ref) + (list* (movl (Simple (car arg*)) ebx) + (addl (Simple (cadr arg*)) ebx) + (movl (mem (fx- disp-record-data record-ptag) ebx) eax) + ac)] + [($string-ref) + (list* (movl (Simple (cadr arg*)) ebx) + (sarl (int fx-shift) ebx) + (addl (Simple (car arg*)) ebx) + (movl (int char-tag) eax) + (movb (mem (fx- disp-string-data string-tag) ebx) ah) + ac)] + [($make-string) + (list* (movl (Simple (car arg*)) ebx) + (movl ebx (mem disp-string-length apr)) + (movl apr eax) + (addl (int string-tag) eax) + (sarl (int fx-shift) ebx) + (addl ebx apr) + (movb (int 0) (mem disp-string-data apr)) + (addl (int (fx+ disp-string-data object-alignment)) apr) + (sarl (int align-shift) apr) + (sall (int align-shift) apr) + ac)] + [($make-vector) + (list* (movl (Simple (car arg*)) ebx) + (movl ebx (mem disp-vector-length apr)) + (movl apr eax) + (addl (int vector-tag) eax) + (addl ebx apr) + (addl (int (fx+ disp-vector-data (fxsub1 object-alignment))) apr) + (sarl (int align-shift) apr) + (sall (int align-shift) apr) + ac)] + [($make-record) + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem disp-record-rtd apr)) + (movl apr eax) + (addl (int record-ptag) eax) + (addl (Simple (cadr arg*)) apr) + (addl (int (fx+ disp-record-data (fxsub1 object-alignment))) apr) + (sarl (int align-shift) apr) + (sall (int align-shift) apr) + ac)] + [(cons) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl eax (mem disp-car apr)) + (movl apr eax) + (movl ebx (mem disp-cdr apr)) + (addl (int pair-tag) eax) + (addl (int (align pair-size)) apr) + ac)] + [($make-symbol) + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem disp-symbol-string apr)) + (movl (int 0) (mem disp-symbol-unique-string apr)) + (movl (int unbound) (mem disp-symbol-value apr)) + (movl (int nil) (mem disp-symbol-plist apr)) + (movl (int unbound) (mem disp-symbol-system-value apr)) + (movl (int nil) (mem disp-symbol-system-plist apr)) + (movl apr eax) + (addl (int symbol-tag) eax) + (addl (int (align symbol-size)) apr) + ac)] + [($make-tcbucket) + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem disp-tcbucket-tconc apr)) + (movl (Simple (cadr arg*)) eax) + (movl eax (mem disp-tcbucket-key apr)) + (movl (Simple (caddr arg*)) eax) + (movl eax (mem disp-tcbucket-val apr)) + (movl (Simple (cadddr arg*)) eax) + (movl eax (mem disp-tcbucket-next apr)) + (movl apr eax) + (addl (int vector-tag) eax) + (addl (int (align tcbucket-size)) apr) + ac)] + [(vector) + (let f ([arg* arg*] [idx disp-vector-data]) + (cond + [(null? arg*) + (list* (movl apr eax) + (addl (int vector-tag) eax) + (movl (int (fx- idx disp-vector-data)) + (mem disp-vector-length apr)) + (addl (int (align idx)) apr) + ac)] + [else + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem idx apr)) + (f (cdr arg*) (fx+ idx wordsize)))]))] + [($string) + (let f ([arg* arg*] [idx disp-string-data]) + (cond + [(null? arg*) + (list* (movb (int 0) (mem idx apr)) + (movl apr eax) + (addl (int string-tag) eax) + (movl (int (fx* (fx- idx disp-string-data) wordsize)) + (mem disp-string-length apr)) + (addl (int (align (fxadd1 idx))) apr) + ac)] + [else + (record-case (car arg*) + [(constant c) + (unless (char? c) (error who "invalid arg to string ~s" x)) + (list* (movb (int (char->integer c)) (mem idx apr)) + (f (cdr arg*) (fxadd1 idx)))] + [else + (list* (movl (Simple (car arg*)) ebx) + (movb bh (mem idx apr)) + (f (cdr arg*) (fxadd1 idx)))])]))] + [($current-frame) + (list* (movl (pcb-ref 'next-continuation) eax) + ac)] + [($seal-frame-and-call) + (list* (movl (Simple (car arg*)) cpr) ; proc + (movl (pcb-ref 'frame-base) eax) + ; eax=baseofstack + (movl (mem (fx- 0 wordsize) eax) ebx) ; underflow handler + (movl ebx (mem (fx- 0 wordsize) fpr)) ; set + ; create a new cont record + (movl (int continuation-tag) (mem 0 apr)) + (movl fpr (mem disp-continuation-top apr)) + ; compute the size of the captured frame + (movl eax ebx) + (subl fpr ebx) + (subl (int wordsize) ebx) + ; and store it + (movl ebx (mem disp-continuation-size apr)) + ; load next cont + (movl (pcb-ref 'next-continuation) ebx) + ; and store it + (movl ebx (mem disp-continuation-next apr)) + ; adjust ap + (movl apr eax) + (addl (int vector-tag) eax) + (addl (int continuation-size) apr) + ; store new cont in current-cont + (movl eax (pcb-ref 'next-continuation)) + ; adjust fp + (movl fpr (pcb-ref 'frame-base)) + (subl (int wordsize) fpr) + ; tail-call f + (movl eax (mem (fx- 0 wordsize) fpr)) + (movl (int (argc-convention 1)) eax) + (tail-indirect-cpr-call) + ac)] + [($code-instr-size) + (indirect-ref arg* (fx- disp-code-instrsize vector-tag) + (cons (sall (int fx-shift) eax) ac))] + [($code-reloc-size) + (indirect-ref arg* (fx- disp-code-relocsize vector-tag) ac)] + [($code-closure-size) + (indirect-ref arg* (fx- disp-code-closuresize vector-tag) ac)] + [($set-car! $set-cdr! $vector-set! $string-set! $exit + $set-symbol-value! $set-symbol-plist! + $set-code-byte! $set-code-word! primitive-set! + $set-code-object! $set-code-object+offset! $set-code-object+offset/rel! + $record-set!) + (do-effect-prim op arg* + (cons (movl (int void-object) eax) ac))] + [(fixnum? immediate? $fxzero? boolean? char? pair? vector? string? symbol? + procedure? null? not eof-object? $fx= $fx< $fx<= $fx> $fx>= eq? + $char= $char< $char<= $char> $char>= $unbound-object? code? + $record? bwp-object?) + (do-pred->value-prim op arg* ac)] + [($code->closure) + (list* + (movl (Simple (car arg*)) eax) + (addl (int (fx- disp-code-data vector-tag)) eax) + (movl eax (mem 0 apr)) + (movl apr eax) + (addl (int closure-tag) eax) + (addl (int (align disp-closure-data)) apr) + ac)] + [($frame->continuation) + (NonTail + (make-closure (make-code-loc SL_continuation_code) arg*) + ac)] + [($make-call-with-values-procedure) + (NonTail + (make-closure (make-code-loc SL_call_with_values) arg*) + ac)] + [($make-values-procedure) + (NonTail + (make-closure (make-code-loc SL_values) arg*) + ac)] + [else + (error 'value-prim "unhandled ~s" op)])) + (define (indirect-assignment arg* offset ac) + (list* + (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem offset eax)) + ;;; record side effect + (addl (int offset) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)) + (define (do-effect-prim op arg* ac) + (case op + [($vector-set!) + (list* (movl (Simple (car arg*)) ebx) + (addl (Simple (cadr arg*)) ebx) + (addl (int (fx- disp-vector-data vector-tag)) ebx) + (movl (Simple (caddr arg*)) eax) + (movl eax (mem 0 ebx)) + ;;; record side effect + (shrl (int pageshift) ebx) + (sall (int wordshift) ebx) + (addl (pcb-ref 'dirty-vector) ebx) + (movl (int dirty-word) (mem 0 ebx)) + ac)] + [($string-set!) + (list* (movl (Simple (cadr arg*)) eax) + (sarl (int fx-shift) eax) + (addl (Simple (car arg*)) eax) + (movl (Simple (caddr arg*)) ebx) + (movb bh (mem (fx- disp-string-data string-tag) eax)) + ac)] + [($set-car!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-car pair-tag) eax)) + ;;; record side effect + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($set-cdr!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-cdr pair-tag) eax)) + ;;; record side effect + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($set-tcbucket-key!) + (indirect-assignment arg* (fx- disp-tcbucket-key vector-tag) ac)] + [($set-tcbucket-val!) + (indirect-assignment arg* (fx- disp-tcbucket-val vector-tag) ac)] + [($set-tcbucket-next!) + (indirect-assignment arg* (fx- disp-tcbucket-next vector-tag) ac)] + [($set-tcbucket-tconc!) + (indirect-assignment arg* (fx- disp-tcbucket-tconc vector-tag) ac)] + + [($set-symbol-value!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-symbol-value symbol-tag) eax)) + ;;; record side effect + (addl (int (fx- disp-symbol-value symbol-tag)) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [(primitive-set!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-symbol-system-value symbol-tag) eax)) + ;;; record side effect + (addl (int (fx- disp-symbol-system-value symbol-tag)) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($set-symbol-plist!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-symbol-plist symbol-tag) eax)) + ;;; record side effect + (addl (int (fx- disp-symbol-plist symbol-tag)) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($set-symbol-unique-string!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-symbol-unique-string symbol-tag) eax)) + ;;; record side effect + (addl (int (fx- disp-symbol-unique-string symbol-tag)) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($set-symbol-string!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-symbol-string symbol-tag) eax)) + ;;; record side effect + (addl (int (fx- disp-symbol-string symbol-tag)) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($record-set!) + (list* (movl (Simple (car arg*)) ebx) + (addl (Simple (cadr arg*)) ebx) + (movl (Simple (caddr arg*)) eax) + (addl (int (fx- disp-record-data record-ptag)) ebx) + (movl eax (mem 0 ebx)) + ;;; record side effect + (shrl (int pageshift) ebx) + (sall (int wordshift) ebx) + (addl (pcb-ref 'dirty-vector) ebx) + (movl (int dirty-word) (mem 0 ebx)) + ac)] + [(cons void $fxadd1 $fxsub1) + (let f ([arg* arg*]) + (cond + [(null? arg*) ac] + [else + (Effect (car arg*) (f (cdr arg*)))]))] + [else + (error 'do-effect-prim "unhandled op ~s" op)])) + (define (do-simple-test x Lt Lf ac) + (unless (or Lt Lf) + (error 'Pred "no labels")) + (cond + [(not Lt) + (list* (cmpl (int bool-f) x) (je Lf) ac)] + [(not Lf) + (list* (cmpl (int bool-f) x) (jne Lt) ac)] + [else + (list* (cmpl (int bool-f) x) (je Lf) (jmp Lt) ac)])) + (define (Simple x) + (record-case x + [(cp-var i) + (mem (fx+ (fx* i wordsize) (fx- disp-closure-data closure-tag)) cpr)] + [(frame-var i) (mem (fx* i (fx- 0 wordsize)) fpr)] + [(constant c) (constant-val c)] + [(code-loc label) (label-address label)] + [(primref op) (primref-loc op)] + [else (error 'Simple "what ~s" x)])) + (define (frame-adjustment offset) + (fx* (fxsub1 offset) (fx- 0 wordsize))) + (define (NonTail x ac) + (record-case x + [(constant c) + (cons (movl (constant-val c) eax) ac)] + [(frame-var) + (cons (movl (Simple x) eax) ac)] + [(cp-var) + (cons (movl (Simple x) eax) ac)] + [(foreign-label L) + (cons (movl (list 'foreign-label L) eax) ac)] + [(primref c) + (cons (movl (primref-loc c) eax) ac)] + [(closure label arg*) + (let f ([arg* arg*] [off disp-closure-data]) + (cond + [(null? arg*) + (list* (movl (Simple label) (mem 0 apr)) + (movl apr eax) + (addl (int (align off)) apr) + (addl (int closure-tag) eax) + ac)] + [else + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem off apr)) + (f (cdr arg*) (fx+ off wordsize)))]))] + [(conditional test conseq altern) + (let ([Lj (unique-label)] [Lf (unique-label)]) + (Pred test #f Lf + (NonTail conseq + (list* (jmp Lj) Lf (NonTail altern (cons Lj ac))))))] + [(seq e0 e1) + (Effect e0 (NonTail e1 ac))] + [(primcall op rand*) + (do-value-prim op rand* ac)] + [(new-frame base-idx size body) + (NonTail body ac)] + [(call-cp call-convention rp-convention offset size mask) + (let ([L_CALL (unique-label)]) + (case call-convention + [(normal) + (list* (addl (int (frame-adjustment offset)) fpr) + (movl (int (argc-convention size)) eax) + (jmp L_CALL) + ; NEW FRAME + `(byte-vector ,mask) + `(int ,(fx* offset wordsize)) + `(current-frame-offset) + (rp-label rp-convention) + `(byte 0) ; padding for indirect calls only + `(byte 0) ; direct calls are ok + L_CALL + (indirect-cpr-call) + (movl (mem 0 fpr) cpr) + (subl (int (frame-adjustment offset)) fpr) + ac)] + [(foreign) + (list* (addl (int (frame-adjustment offset)) fpr) + (movl (int (argc-convention size)) eax) + (movl '(foreign-label "ik_foreign_call") ebx) + (jmp L_CALL) + ; NEW FRAME + (byte-vector mask) + `(int ,(fx* offset wordsize)) + `(current-frame-offset) + (rp-label rp-convention) ; should be 0, since C has 1 rv + '(byte 0) + '(byte 0) + '(byte 0) + L_CALL + (call ebx) + (movl (mem 0 fpr) cpr) + (subl (int (frame-adjustment offset)) fpr) + ac)] + [else + (error who "invalid convention ~s for call-cp" call-convention)]))] + [else (error 'NonTail "invalid expression ~s" x)])) + (define (Pred x Lt Lf ac) + (record-case x + [(frame-var i) + (do-simple-test (idx->frame-loc i) Lt Lf ac)] + [(cp-var i) + (do-simple-test (Simple x) Lt Lf ac)] + [(constant c) + (if c + (if Lt (cons (jmp Lt) ac) ac) + (if Lf (cons (jmp Lf) ac) ac))] + [(primcall op rand*) + (do-pred-prim op rand* Lt Lf ac)] + [(conditional test conseq altern) + (cond + [(not Lt) + (let ([Lj^ (unique-label)] [Lf^ (unique-label)]) + (Pred test #f Lf^ + (Pred conseq Lj^ Lf + (cons Lf^ + (Pred altern #f Lf + (cons Lj^ ac))))))] + [(not Lf) + (let ([Lj^ (unique-label)] [Lf^ (unique-label)]) + (Pred test #f Lf^ + (Pred conseq Lt Lj^ + (cons Lf^ + (Pred altern Lt #f + (cons Lj^ ac))))))] + [else + (let ([Lf^ (unique-label)]) + (Pred test #f Lf^ + (Pred conseq Lt Lf + (cons Lf^ + (Pred altern Lt Lf ac)))))])] + [(seq e0 e1) + (Effect e0 (Pred e1 Lt Lf ac))] + [(new-frame) + (NonTail x (do-simple-test eax Lt Lf ac))] + [else (error 'Pred "invalid expression ~s" x)])) + (define (idx->frame-loc i) + (mem (fx* i (fx- 0 wordsize)) fpr)) + (define (Effect x ac) + (record-case x + [(constant) ac] + [(primcall op rand*) + (do-effect-prim op rand* ac)] + [(conditional test conseq altern) + (let ([Lf (unique-label)] [Ljoin (unique-label)]) + (Pred test #f Lf + (Effect conseq + (list* (jmp Ljoin) Lf (Effect altern (cons Ljoin ac))))))] + [(seq e0 e1) + (Effect e0 (Effect e1 ac))] + [(assign loc val) + (record-case loc + [(frame-var i) + (NonTail val + (cons (movl eax (idx->frame-loc i)) ac))] + [else (error who "invalid assign loc ~s" loc)])] + [(eval-cp check body) + (NonTail body + (cond + [check + (list* + (movl eax cpr) + (andl (int closure-mask) eax) + (cmpl (int closure-tag) eax) + (jne (label SL_nonprocedure)) + ac)] + [else + (list* + (movl eax cpr) + ac)]))] + [(save-cp loc) + (record-case loc + [(frame-var i) + (cons (movl cpr (idx->frame-loc i)) ac)] + [else (error who "invalid cpr loc ~s" x)])] + [(new-frame) (NonTail x ac)] + [(frame-var) ac] + [else (error 'Effect "invalid expression ~s" x)])) + (define (Tail x ac) + (record-case x + [(return x) + (NonTail x (cons (ret) ac))] + [(conditional test conseq altern) + (let ([L (unique-label)]) + (Pred test #f L + (Tail conseq + (cons L (Tail altern ac)))))] + [(seq e0 e1) + (Effect e0 (Tail e1 ac))] + [(new-frame idx size body) + (Tail body ac)] + [(call-cp call-convention rp-convention idx argc mask) + (unless (eq? rp-convention 'tail) + (error who "nontail rp (~s) in tail context" rp-convention)) + (let f ([i 0]) + (cond + [(fx= i argc) + (case call-convention + [(normal) + (list* + (movl (int (argc-convention argc)) eax) + (tail-indirect-cpr-call) + ac)] + [(apply) + (list* + (movl (int (argc-convention argc)) eax) + (jmp (label SL_apply)) + ac)] + [else + (error who "invalid conv ~s in tail call-cpr" call-convention)])] + [else + (list* (movl (mem (fx* (fx+ idx (fxadd1 i)) + (fx- 0 wordsize)) fpr) + eax) + (movl eax (mem (fx* (fx+ i 1) (fx- 0 wordsize)) fpr)) + (f (fxadd1 i)))]))] + [else (error 'Tail "invalid expression ~s" x)])) + (define (handle-vararg fml-count ac) + (define CONTINUE_LABEL (unique-label)) + (define DONE_LABEL (unique-label)) + (define CONS_LABEL (unique-label)) + (define LOOP_HEAD (unique-label)) + (define L_CALL (unique-label)) + (list* (cmpl (int (argc-convention (fxsub1 fml-count))) eax) + (jg (label SL_invalid_args)) + (jl CONS_LABEL) + (movl (int nil) ebx) + (jmp DONE_LABEL) + CONS_LABEL + (movl (pcb-ref 'allocation-redline) ebx) + (addl eax ebx) + (addl eax ebx) + (cmpl ebx apr) + (jle LOOP_HEAD) + ; overflow + (addl eax esp) ; advance esp to cover args + (pushl cpr) ; push current cp + (pushl eax) ; push argc + (negl eax) ; make argc positive + (addl (int (fx* 4 wordsize)) eax) ; add 4 words to adjust frame size + (pushl eax) ; push frame size + (addl eax eax) ; double the number of args + (movl eax (mem (fx* -2 wordsize) fpr)) ; pass it as first arg + (movl (int (argc-convention 1)) eax) ; setup argc + (movl (primref-loc 'do-vararg-overflow) cpr) ; load handler + (jmp L_CALL) ; go to overflow handler + ; NEW FRAME + (int 0) ; if the framesize=0, then the framesize is dynamic + '(current-frame-offset) + (int 0) ; multiarg rp + (byte 0) + (byte 0) + L_CALL + (indirect-cpr-call) + (popl eax) ; pop framesize and drop it + (popl eax) ; reload argc + (popl cpr) ; reload cp + (subl eax fpr) ; readjust fp + LOOP_HEAD + (movl (int nil) ebx) + CONTINUE_LABEL + (movl ebx (mem disp-cdr apr)) + (movl (mem fpr eax) ebx) + (movl ebx (mem disp-car apr)) + (movl apr ebx) + (addl (int pair-tag) ebx) + (addl (int pair-size) apr) + (addl (int (fxsll 1 fx-shift)) eax) + (cmpl (int (fx- 0 (fxsll fml-count fx-shift))) eax) + (jle CONTINUE_LABEL) + DONE_LABEL + (movl ebx (mem (fx- 0 (fxsll fml-count fx-shift)) fpr)) + ac)) + (define (Entry check? x ac) + (record-case x + [(clambda-case fml* proper body) + (let ([ac (Tail body ac)]) + (cond + [(and proper check?) + (list* (cmpl (int (argc-convention (length fml*))) eax) + (jne (label SL_invalid_args)) + ac)] + [proper ac] + [else + (handle-vararg (length fml*) ac)]))])) + (define make-dispatcher + (lambda (j? L L* x x* ac) + (cond + [(null? L*) (if j? (cons (jmp (label L)) ac) ac)] + [else + (record-case x + [(clambda-case fml* proper _) + (cond + [proper + (list* (cmpl (int (argc-convention (length fml*))) eax) + (je (label L)) + (make-dispatcher #t + (car L*) (cdr L*) (car x*) (cdr x*) ac))] + [else + (list* (cmpl (int (argc-convention (fxsub1 (length fml*)))) eax) + (jle (label L)) + (make-dispatcher #t + (car L*) (cdr L*) (car x*) (cdr x*) ac))])])]))) + (define (handle-cases x x*) + (let ([L* (map (lambda (_) (gensym)) x*)] + [L (gensym)]) + (make-dispatcher #f L L* x x* + (let f ([x x] [x* x*] [L L] [L* L*]) + (cond + [(null? x*) + (cons (label L) (Entry 'check x '()))] + [else + (cons (label L) + (Entry #f x + (f (car x*) (cdr x*) (car L*) (cdr L*))))]))))) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (list* + (fx+ disp-closure-data (fx* wordsize (length free))) + (label L) + (handle-cases (car cases) (cdr cases)))])) + (record-case x + [(codes list body) + (cons (cons 0 (Tail body '())) + (map CodeExpr list))])) + + +(define SL_nonprocedure (gensym "SL_nonprocedure")) +(define SL_invalid_args (gensym "SL_invalid_args")) +(define SL_foreign_call (gensym "SL_foreign_call")) +(define SL_continuation_code (gensym "SL_continuation_code")) +(define SL_multiple_values_error_rp (gensym "SL_multiple_values_error_rp")) +(define SL_multiple_values_ignore_rp (gensym "SL_multiple_ignore_error_rp")) +(define SL_underflow_multiple_values (gensym "SL_underflow_multiple_values")) +(define SL_underflow_handler (gensym "SL_underflow_handler")) +(define SL_scheme_exit (gensym "SL_scheme_exit")) +(define SL_apply (gensym "SL_apply")) +(define SL_values (gensym "SL_values")) +(define SL_call_with_values (gensym "SL_call_with_values")) + +(module () +(list*->code* + (list + (let ([L_cwv_done (gensym)] + [L_cwv_loop (gensym)] + [L_cwv_multi_rp (gensym)] + [L_cwv_call (gensym)]) + (list disp-closure-data + (label SL_call_with_values) + (cmpl (int (argc-convention 2)) eax) + (jne (label SL_invalid_args)) + (movl (mem (fx- 0 wordsize) fpr) ebx) ; producer + (movl ebx cpr) + (andl (int closure-mask) ebx) + (cmpl (int closure-tag) ebx) + (jne (label SL_nonprocedure)) + (movl (int (argc-convention 0)) eax) + (subl (int (fx* wordsize 2)) fpr) + (jmp (label L_cwv_call)) + ; MV NEW FRAME + (byte-vector '#(#b110)) + (int (fx* wordsize 3)) + '(current-frame-offset) + (label-address L_cwv_multi_rp) + (byte 0) + (byte 0) + (label L_cwv_call) + (indirect-cpr-call) + ;;; one value returned + (addl (int (fx* wordsize 2)) fpr) + (movl (mem (fx* -2 wordsize) fpr) ebx) ; consumer + (movl ebx cpr) + (movl eax (mem (fx- 0 wordsize) fpr)) + (movl (int (argc-convention 1)) eax) + (andl (int closure-mask) ebx) + (cmpl (int closure-tag) ebx) + (jne (label SL_nonprocedure)) + (tail-indirect-cpr-call) + ;;; multiple values returned + (label L_cwv_multi_rp) + ; because values does not pop the return point + ; we have to adjust fp one more word here + (addl (int (fx* wordsize 3)) fpr) + (movl (mem (fx* -2 wordsize) fpr) cpr) ; consumer + (cmpl (int (argc-convention 0)) eax) + (je (label L_cwv_done)) + (movl (int (fx* -4 wordsize)) ebx) + (addl fpr ebx) ; ebx points to first value + (movl ebx ecx) + (addl eax ecx) ; ecx points to the last value + (label L_cwv_loop) + (movl (mem 0 ebx) edx) + (movl edx (mem (fx* 3 wordsize) ebx)) + (subl (int wordsize) ebx) + (cmpl ecx ebx) + (jge (label L_cwv_loop)) + (label L_cwv_done) + (movl cpr ebx) + (andl (int closure-mask) ebx) + (cmpl (int closure-tag) ebx) + (jne (label SL_nonprocedure)) + (tail-indirect-cpr-call))) + + (let ([L_values_one_value (gensym)] + [L_values_many_values (gensym)]) + (list disp-closure-data + (label SL_values) + (cmpl (int (argc-convention 1)) eax) + (je (label L_values_one_value)) + (label L_values_many_values) + (movl (mem 0 fpr) ebx) ; return point + (jmp (mem disp-multivalue-rp ebx)) ; go + (label L_values_one_value) + (movl (mem (fx- 0 wordsize) fpr) eax) + (ret))) + + (let ([L_apply_done (gensym)] + [L_apply_loop (gensym)]) + (list 0 + (label SL_apply) + (movl (mem fpr eax) ebx) + (cmpl (int nil) ebx) + (je (label L_apply_done)) + (label L_apply_loop) + (movl (mem (fx- disp-car pair-tag) ebx) ecx) + (movl (mem (fx- disp-cdr pair-tag) ebx) ebx) + (movl ecx (mem fpr eax)) + (subl (int wordsize) eax) + (cmpl (int nil) ebx) + (jne (label L_apply_loop)) + (label L_apply_done) + (addl (int wordsize) eax) + (tail-indirect-cpr-call))) + + (list 0 + (label SL_nonprocedure) + (movl cpr (mem (fx- 0 wordsize) fpr)) ; first arg + (movl (primref-loc '$apply-nonprocedure-error-handler) cpr) + (movl (int (argc-convention 1)) eax) + (tail-indirect-cpr-call)) + + (list 0 + (label SL_multiple_values_error_rp) + (movl (primref-loc '$multiple-values-error) cpr) + (tail-indirect-cpr-call)) + + (list 0 + (label SL_multiple_values_ignore_rp) + (ret)) + + (list 0 + (label SL_invalid_args) + ;;; + (movl cpr (mem (fx- 0 wordsize) fpr)) ; first arg + (negl eax) + (movl eax (mem (fx- 0 (fx* 2 wordsize)) fpr)) + (movl (primref-loc '$incorrect-args-error-handler) cpr) + (movl (int (argc-convention 2)) eax) + (tail-indirect-cpr-call)) + + (let ([Lset (gensym)] [Lloop (gensym)]) + (list 0 + (label SL_foreign_call) + (movl fpr (pcb-ref 'frame-pointer)) + (movl apr (pcb-ref 'allocation-pointer)) + (movl fpr ebx) + (movl (pcb-ref 'system-stack) esp) + (pushl pcr) + (cmpl (int 0) eax) + (je (label Lset)) + (label Lloop) + (movl (mem ebx eax) ecx) + (pushl ecx) + (addl (int 4) eax) + (cmpl (int 0) eax) + (jne (label Lloop)) + (label Lset) + ; FOREIGN NEW FRAME + (call cpr) + (movl (pcb-ref 'frame-pointer) fpr) + (movl (pcb-ref 'allocation-pointer) apr) + (ret))) + + (let ([L_cont_zero_args (gensym)] + [L_cont_mult_args (gensym)] + [L_cont_one_arg (gensym)] + [L_cont_mult_move_args (gensym)] + [L_cont_mult_copy_loop (gensym)]) + (list + (fx+ disp-closure-data wordsize) + (label SL_continuation_code) + (movl (mem (fx- disp-closure-data closure-tag) cpr) ebx) ; captured-k + (movl ebx (pcb-ref 'next-continuation)) ; set + (movl (pcb-ref 'frame-base) ebx) + (cmpl (int (argc-convention 1)) eax) + (jg (label L_cont_zero_args)) + (jl (label L_cont_mult_args)) + (label L_cont_one_arg) + (movl (mem (fx- 0 wordsize) fpr) eax) + (movl ebx fpr) + (subl (int wordsize) fpr) + (ret) + (label L_cont_zero_args) + (subl (int wordsize) ebx) + (movl ebx fpr) + (movl (mem 0 ebx) ebx) ; return point + (jmp (mem disp-multivalue-rp ebx)) ; go + (label L_cont_mult_args) + (subl (int wordsize) ebx) + (cmpl ebx fpr) + (jne (label L_cont_mult_move_args)) + (movl (mem 0 ebx) ebx) + (jmp (mem disp-multivalue-rp ebx)) + (label L_cont_mult_move_args) + ; move args from fpr to ebx + (movl (int 0) ecx) + (label L_cont_mult_copy_loop) + (subl (int wordsize) ecx) + (movl (mem fpr ecx) edx) + (movl edx (mem ebx ecx)) + (cmpl ecx eax) + (jne (label L_cont_mult_copy_loop)) + (movl ebx fpr) + (movl (mem 0 ebx) ebx) + (jmp (mem disp-multivalue-rp ebx)) + )) + ))) + + + +(define (compile-expr expr) + (let* ([p (recordize expr)] + [p (optimize-direct-calls p)] + [p (remove-assignments p)] + [p (convert-closures p)] + [p (lift-codes p)] + [p (introduce-primcalls p)] + [p (simplify-operands p)] + [p (insert-stack-overflow-checks p)] + [p (insert-allocation-checks p)] + [p (remove-local-variables p)] + [ls* (generate-code p)] + [f (when (assembler-output) + (for-each + (lambda (ls) + (for-each (lambda (x) (printf " ~s\n" x)) ls)) + ls*))] + [code* (list*->code* ls*)]) + (car code*))) + +(define compile-file + (lambda (input-file output-file . rest) + (let ([ip (open-input-file input-file)] + [op (apply open-output-file output-file rest)]) + (let f () + (let ([x (read ip)]) + (unless (eof-object? x) + (fasl-write (compile-expr (expand x)) op) + (f)))) + (close-input-port ip) + (close-output-port op)))) + +(primitive-set! 'compile-file compile-file) +(primitive-set! 'assembler-output (make-parameter #f)) +) + diff --git a/src/libcompile-6.5.ss b/src/libcompile-6.5.ss new file mode 100644 index 0000000..51dd525 --- /dev/null +++ b/src/libcompile-6.5.ss @@ -0,0 +1,3435 @@ + + +;;; 6.2: * side-effects now modify the dirty-vector +;;; * added bwp-object? +;;; * added pointer-value +;;; * added tcbuckets +;;; 6.1: * added case-lambda, dropped lambda +;;; 6.0: * basic compiler + +(let () + +(define-syntax cond-expand + (lambda (x) + (syntax-case x () + [(_ test conseq altern) + (if (eval (syntax-object->datum #'test)) + #'conseq + #'altern)]))) + +(cond-expand (eq? "" "") + (include "record-case.chez.ss") + (include "record-case.ss")) + + +(include "set-operations.ss") + + +(define open-coded-primitives +;;; these primitives, when found in operator position with the correct +;;; number of arguments, will be open-coded by the generator. If an +;;; incorrect number of args is detected, or if they appear in non-operator +;;; position, then they cannot be open-coded, and the pcb-primitives table +;;; is consulted for a reference of the pcb slot containing the primitive. +;;; If it's not found there, an error is signalled. +;;; +;;; prim-name args + '([$constant-ref 1 value] + [$constant-set! 2 effect] + [$pcb-ref 1 value] + [$pcb-set! 2 effect] + ;;; type predicates + [fixnum? 1 pred] + [immediate? 1 pred] + [boolean? 1 pred] + [char? 1 pred] + [pair? 1 pred] + [symbol? 1 pred] + [vector? 1 pred] + [string? 1 pred] + [procedure? 1 pred] + [null? 1 pred] + [eof-object? 1 pred] + [bwp-object? 1 pred] + [$unbound-object? 1 pred] + [$forward-ptr? 1 pred] + [not 1 pred] + [pointer-value 1 value] + [eq? 2 pred] + ;;; fixnum primitives + [$fxadd1 1 value] + [$fxsub1 1 value] + [$fx+ 2 value] + [$fx- 2 value] + [$fx* 2 value] + [$fxsll 2 value] + [$fxsra 2 value] + [$fxlogand 2 value] + [$fxlogor 2 value] + [$fxlogxor 2 value] + [$fxlognot 1 value] + [$fxquotient 2 value] + [$fxmodulo 2 value] + ;;; fixnum predicates + [$fxzero? 1 pred] + [$fx= 2 pred] + [$fx< 2 pred] + [$fx<= 2 pred] + [$fx> 2 pred] + [$fx>= 2 pred] + ;;; character predicates + [$char= 2 pred] + [$char< 2 pred] + [$char<= 2 pred] + [$char> 2 pred] + [$char>= 2 pred] + ;;; character conversion + [$fixnum->char 1 value] + [$char->fixnum 1 value] + ;;; lists/pairs + [cons 2 value] + [$car 1 value] + [$cdr 1 value] + [$set-car! 2 effect] + [$set-cdr! 2 effect] + ;;; vectors + [$make-vector 1 value] + [vector any value] + [$vector-length 1 value] + [$vector-ref 2 value] + [$vector-set! 3 effect] + ;;; strings + [$make-string 1 value] + [$string any value] + [$string-length 1 value] + [$string-ref 2 value] + [$string-set! 3 effect] + ;;; symbols + [$make-symbol 1 value] + [$symbol-value 1 value] + [$symbol-string 1 value] + [$symbol-unique-string 1 value] + [$set-symbol-value! 2 effect] + [$set-symbol-string! 2 effect] + [$set-symbol-unique-string! 2 effect] + [$symbol-plist 1 value] + [$set-symbol-plist! 2 effect] + [primitive-ref 1 value] + [primitive-set! 2 effect] + ;;; tcbuckets + [$make-tcbucket 4 value] + [$tcbucket-key 1 value] + [$tcbucket-val 1 value] + [$tcbucket-next 1 value] + [$set-tcbucket-val! 2 effect] + [$set-tcbucket-next! 2 effect] + [$set-tcbucket-tconc! 2 effect] + ;;; misc + [eof-object 0 value] + [void 0 value] + [$exit 1 effect] + [$fp-at-base 0 pred] + [$current-frame 0 value] + [$seal-frame-and-call 1 tail] + [$frame->continuation 1 value] + ;;; + ;;; records + ;;; + [$make-record 2 value] + [$record? 1 pred] + [$record/rtd? 2 pred] + [$record-rtd 1 value] + [$record-ref 2 value] + [$record-set! 3 effect] + ;;; + ;;; asm + ;;; + ;[code? 1 pred] + ;[$code-instr-size 1 value] + ;[$code-reloc-size 1 value] + ;[$code-closure-size 1 value] + ;[$code->closure 1 value] + ;[$set-code-byte! 3 effect] + ;[$set-code-word! 3 effect] + ;[$set-code-object! 4 effect] + ;[$set-code-object+offset! 5 effect] + ;[$set-code-object+offset/rel! 5 effect] + ;;; + [$make-call-with-values-procedure 0 value] + [$make-values-procedure 0 value] + [$install-underflow-handler 0 effect] + )) + +(define (primitive-context x) + (cond + [(assq x open-coded-primitives) => caddr] + [else (error 'primitive-context "unknown prim ~s" x)])) + + +;;; primitives table section +(define primitives-table + '(;;; system locations used by the C/Scheme interface + [$apply-nonprocedure-error-handler library] + [$incorrect-args-error-handler library] + [$multiple-values-error library] + [$intern library] + [do-overflow library] + [do-vararg-overflow library] + [do-stack-overflow library] + ;;; type predicates + [fixnum? public] + [immediate? public] + [boolean? public] + [char? public] + [null? public] + [pair? public] + [symbol? public] + [vector? public] + [string? public] + [procedure? public] + [eof-object? public] + [not public] + [eq? public] + [equal? public] + ;;; fixnum primitives + [fxadd1 public] + [fxsub1 public] + [fx+ public] + [fx- public] + [fx* public] + [fxsll public] + [fxsra public] + [fxlogor public] + [fxlogand public] + [fxlogxor public] + [fxlognot public] + [fxquotient public] + [fxremainder public] + [fxmodulo public] + ;;; fixnum predicates + [fxzero? public] + [fx= public] + [fx< public] + [fx<= public] + [fx> public] + [fx>= public] + ;;; characters + [char=? public] + [char? public] + [char>=? public] + [integer->char public] + [char->integer public] + ;;; lists + [cons public] + [car public] + [cdr public] + [caar public] + [cadr public] + [cdar public] + [cddr public] + [caaar public] + [caadr public] + [cadar public] + [caddr public] + [cdaar public] + [cdadr public] + [cddar public] + [cdddr public] + [caaaar public] + [caaadr public] + [caadar public] + [caaddr public] + [cadaar public] + [cadadr public] + [caddar public] + [cadddr public] + [cdaaar public] + [cdaadr public] + [cdadar public] + [cdaddr public] + [cddaar public] + [cddadr public] + [cdddar public] + [cddddr public] + [set-car! public] + [set-cdr! public] + [list public] + [list* ADDME] + [list? public] + [list-ref public] + [length public] + [make-list public] + [reverse public] + [append public] + [list-ref public] + [memq public] + [memv public] + [assq public] + [map public] + [for-each public] + [andmap public] + [ormap public] + ;;; vectors + [make-vector public] + [vector public] + [vector-length public] + [vector-ref public] + [vector-set! public] + [list->vector public] + [vector->list public] + ;;; strings + [make-string public] + [string public] + [string-length public] + [string-ref public] + [string-set! public] + [list->string public] + [string->list public] + [string-append public] + [substring public] + [string=? public] + [fixnum->string public] + ;;; symbols + [gensym public] + [gensym? public] + [symbol->string public] + [gensym->unique-string public] + [gensym-prefix public] + [gensym-count public] + [print-gensym public] + [string->symbol public] + [top-level-value public] + [top-level-bound? public] + [set-top-level-value! public] + [primitive-set! public] + [getprop public] + [putprop public] + [remprop public] + [property-list public] + [oblist public] + [uuid public] + ;;; eof + [eof-object public] + [void public] + ;;; control/debugging + [print-error public] + [error public] + [current-error-handler public] + [exit public] + [apply public] + [make-parameter public] + ;;; output + [output-port? public] + [console-output-port public] + [current-output-port public] + [standard-output-port public] + [standard-error-port public] + [open-output-file public] + [open-output-string public] + [with-output-to-file public] + [call-with-output-file public] + [with-input-from-file public] + [call-with-input-file public] + [get-output-string public] + [close-output-port public] + [flush-output-port public] + [write-char public] + [output-port-name public] + [newline public] + ;;; input + [input-port? public] + [standard-input-port public] + [console-input-port public] + [current-input-port public] + [open-input-file public] + [close-input-port public] + [reset-input-port! public] + [read-char public] + [peek-char public] + [unread-char public] + [input-port-name public] + ;;; writing/printing + [write public] + [display public] + [printf public] + [fprintf public] + [format public] + [read-token public] + [read public] + ;;; evaluation + [primitive? public] + [expand public] + [syntax-error public] + [current-expand public] + [expand-mode public] + [assembler-output public] + [compile-file public] + [fasl-write public] + + [$sc-put-cte public] + [sc-expand public] + [$make-environment public] + [environment? public] + [interaction-environment public] + [identifier? public] + [syntax->list public] + [syntax-object->datum public] + [datum->syntax-object public] + [generate-temporaries public] + [free-identifier=? public] + [bound-identifier=? public] + [literal-identifier=? public] + [syntax-error public] + [$syntax-dispatch public] + + + + [interpret public] + [eval public] + [current-eval public] + [load public] + [new-cafe public] + [collect public] + [call/cc public] + [call/cf library] + [dynamic-wind public] + [values public] + [call-with-values public] + [make-traced-procedure library] + [trace-symbol! library] + [untrace-symbol! library] + ;;; record + [$base-rtd library] + [record? public] + [record-rtd public] + [record-name public] + [record-printer public] + [record-length public] + [record-ref public] + [record-set! public] + ;;; record rtds + [make-record-type public] + [record-type-name public] + [record-type-descriptor public] + [record-type-symbol public] + [record-type-field-names public] + [record-constructor public] + [record-predicate public] + [record-field-accessor public] + [record-field-mutator public] + ;;; hash tables + [make-hash-table public] + [hash-table? public] + [get-hash-table public] + [put-hash-table! public] + ;;; asm + [make-code public] + [code? public] + [make-code-executable! public] + [code-instr-size public] + [code-reloc-size public] + [code-closure-size public] + [set-code-byte! public] + [set-code-word! public] + [set-code-object! public] + [set-code-foreign-object! public] + [set-code-object+offset! public] + [set-code-object+offset/rel! public] + [set-code-object/reloc/relative! public] + [code-reloc-vec public] + [code-code-vec public] + [code->closure public] + [list*->code* library] + ;;; + ;;; POSIX + ;;; + [fork public] + [posix-fork public] + [system public] + [$debug public] + [$underflow-misaligned-error public] + )) + + +(define (primitive? x) + (cond + [(assq x primitives-table) #t] + [(assq x open-coded-primitives) #t] + [else #f])) + +(define (open-codeable? x) + (cond + [(assq x open-coded-primitives) #t] + [(assq x primitives-table) #f] + [else (error 'open-codeable "invalid primitive ~s" x)])) + +(define (open-coded-primitive-args x) + (cond + [(assq x open-coded-primitives) => cadr] + [else (error 'open-coded-primitive-args "invalid ~s" x)])) + +;;; end of primitives table section + + +(define-record constant (value)) +(define-record code-loc (label)) +(define-record foreign-label (label)) +(define-record var (name assigned)) +(define-record cp-var (idx)) +(define-record frame-var (idx)) +(define-record new-frame (base-idx size body)) +(define-record save-cp (loc)) +(define-record eval-cp (check body)) +(define-record return (value)) +(define-record call-cp + (call-convention rp-convention base-idx arg-count live-mask)) +(define-record primcall (op arg*)) +(define-record primref (name)) +(define-record conditional (test conseq altern)) +(define-record bind (lhs* rhs* body)) +(define-record recbind (lhs* rhs* body)) +(define-record fix (lhs* rhs* body)) + +(define-record seq (e0 e1)) +(define-record clambda-case (arg* proper body)) +(define-record clambda (cases)) +(define-record clambda-code (label cases free)) + +(define-record closure (code free*)) +(define-record funcall (op rand*)) +(define-record appcall (op rand*)) +(define-record forcall (op rand*)) +(define-record code-rec (arg* proper free* body)) + +(define-record codes (list body)) +(define-record assign (lhs rhs)) + +(define unique-var + (let ([counter 0]) + (lambda (x) + (let ([g (gensym (format "~a:~a" x counter))]) + (set! counter (fxadd1 counter)) + (make-var g #f))))) + +(define (make-bind^ lhs* rhs* body) + (if (null? lhs*) + body + (make-bind lhs* rhs* body))) + +(define (recordize x) + (define (gen-fml* fml*) + (cond + [(pair? fml*) + (cons (unique-var (car fml*)) + (gen-fml* (cdr fml*)))] + [(symbol? fml*) + (unique-var fml*)] + [else '()])) + (define (properize fml*) + (cond + [(pair? fml*) + (cons (car fml*) (properize (cdr fml*)))] + [(null? fml*) '()] + [else (list fml*)])) + (define (extend-env fml* nfml* env) + (cons (cons fml* nfml*) env)) + (define (quoted-sym x) + (if (and (list? x) + (fx= (length x) 2) + (eq? 'quote (car x)) + (symbol? (cadr x))) + (cadr x) + (error 'quoted-sym "not a quoted symbol ~s" x))) + (define (quoted-string x) + (if (and (list? x) + (fx= (length x) 2) + (eq? 'quote (car x)) + (string? (cadr x))) + (cadr x) + (error 'quoted-string "not a quoted string ~s" x))) + (define (lookup^ x lhs* rhs*) + (cond + [(pair? lhs*) + (if (eq? x (car lhs*)) + (car rhs*) + (lookup^ x (cdr lhs*) (cdr rhs*)))] + [(eq? x lhs*) rhs*] + [else #f])) + (define (lookup x env) + (cond + [(pair? env) + (or (lookup^ x (caar env) (cdar env)) + (lookup x (cdr env)))] + [else #f])) + (define (E x env) + (cond + [(pair? x) + (case (car x) + [(quote) (make-constant (cadr x))] + [(if) + (make-conditional + (E (cadr x) env) + (E (caddr x) env) + (E (cadddr x) env))] + [(set!) + (let ([lhs (cadr x)] [rhs (caddr x)]) + (make-assign + (or (lookup lhs env) + (error 'recordize "invalid assignment ~s" x)) + (E rhs env)))] + [(begin) + (let f ([a (cadr x)] [d (cddr x)]) + (cond + [(null? d) (E a env)] + [else + (make-seq + (E a env) + (f (car d) (cdr d)))]))] + [(letrec) + (unless (fx= (length x) 3) (syntax-error x)) + (let ([bind* (cadr x)] [body (caddr x)]) + (let ([lhs* (map car bind*)] + [rhs* (map cadr bind*)]) + (let ([nlhs* (gen-fml* lhs*)]) + (let ([env (extend-env lhs* nlhs* env)]) + (make-recbind nlhs* + (map (lambda (rhs) (E rhs env)) rhs*) + (E body env))))))] + [(letrec) + (unless (fx= (length x) 3) (syntax-error x)) + (let ([bind* (cadr x)] [body (caddr x)]) + (let ([lhs* (map car bind*)] + [rhs* (map cadr bind*)] + [v* (map (lambda (x) '(void)) bind*)] + [t* (map (lambda (x) (gensym)) bind*)]) + (E `((case-lambda + [,lhs* + ((case-lambda + [,t* + (begin ,@(map (lambda (x v) `(set! ,x ,v)) lhs* t*) + ,body)]) + ,@rhs*)]) + ,@v*) + env)))] + [(case-lambda) + (let ([cls* + (map + (lambda (cls) + (let ([fml* (car cls)] [body (cadr cls)]) + (let ([nfml* (gen-fml* fml*)]) + (let ([body (E body (extend-env fml* nfml* env))]) + (make-clambda-case + (properize nfml*) + (list? fml*) + body))))) + (cdr x))]) + (make-clambda cls*))] + [(foreign-call) + (let ([name (quoted-string (cadr x))] [arg* (cddr x)]) + (make-forcall name + (map (lambda (x) (E x env)) arg*)))] + [(|#primitive|) + (let ([var (cadr x)]) + (if (primitive? var) + (make-primref var) + (error 'recordize "invalid primitive ~s" var)))] + [(top-level-value) + (let ([var (quoted-sym (cadr x))]) + (cond + [(primitive? var) (make-primref var)] + [else (error 'recordize "invalid top-level var ~s" var)]))] + [(memv) + (make-funcall + (make-primref 'memq) + (map (lambda (x) (E x env)) (cdr x)))] + [($apply) + (let ([proc (cadr x)] [arg* (cddr x)]) + (make-appcall + (E proc env) + (map (lambda (x) (E x env)) arg*)))] + [(void) + (make-constant (void))] + [else + (make-funcall + (E (car x) env) + (map (lambda (x) (E x env)) (cdr x)))])] + [(symbol? x) + (or (lookup x env) + (error 'recordize "invalid reference in ~s" x))] + [else (error 'recordize "invalid expression ~s" x)])) + (E x '())) + + +(define (unparse x) + (define (E-args proper x) + (if proper + (map E x) + (let f ([a (car x)] [d (cdr x)]) + (cond + [(null? d) (E a)] + [else (cons (E a) (f (car d) (cdr d)))])))) + (define (E x) + (record-case x + [(constant c) `(quote ,c)] + [(code-loc x) `(code-loc ,x)] + [(var x) (string->symbol (format "v:~a" x))] + [(primref x) x] + [(conditional test conseq altern) + `(if ,(E test) ,(E conseq) ,(E altern))] + [(primcall op arg*) `(,op . ,(map E arg*))] + [(bind lhs* rhs* body) + `(let ,(map (lambda (lhs rhs) (list (E lhs) (E rhs))) lhs* rhs*) + ,(E body))] + [(recbind lhs* rhs* body) + `(letrec ,(map (lambda (lhs rhs) (list (E lhs) (E rhs))) lhs* rhs*) + ,(E body))] + [(fix lhs* rhs* body) + `(fix ,(map (lambda (lhs rhs) (list (E lhs) (E rhs))) lhs* rhs*) + ,(E body))] + [(seq e0 e1) `(begin ,(E e0) ,(E e1))] + [(clambda-case args proper body) + `(clambda-case ,(E-args proper args) ,(E body))] + [(clambda cls*) + `(case-lambda . ,(map E cls*))] + [(clambda-code label clauses free) + `(code ,label . ,(map E clauses))] + [(closure code free*) + `(closure ,(E code) ,(map E free*))] + [(code-rec arg* proper free* body) + `(code-rec [arg: ,(E-args proper arg*)] + [free: ,(map E free*)] + ,(E body))] + [(codes list body) + `(codes ,(map E list) + ,(E body))] + [(funcall rator rand*) `(funcall ,(E rator) . ,(map E rand*))] + [(appcall rator rand*) `(appcall ,(E rator) . ,(map E rand*))] + [(forcall rator rand*) `(foreign-call ,rator . ,(map E rand*))] + [(assign lhs rhs) `(set! ,(E lhs) ,(E rhs))] + [(return x) `(return ,(E x))] + [(new-frame base-idx size body) + `(new-frame [base: ,base-idx] + [size: ,size] + ,(E body))] + [(frame-var idx) + (string->symbol (format "fv.~a" idx))] + [(cp-var idx) + (string->symbol (format "cp.~a" idx))] + [(save-cp expr) + `(save-cp ,(E expr))] + [(eval-cp check body) + `(eval-cp ,check ,(E body))] + [(call-cp call-convention rp-convention base-idx arg-count live-mask) + `(call-cp [conv: ,call-convention] + [rpconv: ,rp-convention] + [base-idx: ,base-idx] + [arg-count: ,arg-count] + [live-mask: ,live-mask])] + [(foreign-label x) `(foreign-label ,x)] + [else (error 'unparse "invalid record ~s" x)])) + (E x)) + +(define (optimize-direct-calls x) + (define who 'optimize-direct-calls) + (define (make-conses ls) + (cond + [(null? ls) (make-constant '())] + [else + (make-primcall 'cons + (list (car ls) (make-conses (cdr ls))))])) + (define (properize lhs* rhs*) + (cond + [(null? lhs*) (error who "improper improper")] + [(null? (cdr lhs*)) + (list (make-conses rhs*))] + [else (cons (car rhs*) (properize (cdr lhs*) (cdr rhs*)))])) + (define (inline-case cls rand*) + (record-case cls + [(clambda-case fml* proper body) + (if proper + (and (fx= (length fml*) (length rand*)) + (make-bind fml* rand* body)) + (and (fx<= (length fml*) (length rand*)) + (make-bind fml* (properize fml* rand*) body)))])) + (define (try-inline cls* rand* default) + (cond + [(null? cls*) default] + [(inline-case (car cls*) rand*)] + [else (try-inline (cdr cls*) rand* default)])) + (define (inline rator rand*) + (record-case rator + [(clambda cls*) + (try-inline cls* rand* + (make-funcall rator rand*))] + [else (make-funcall rator rand*)])) + (define (Expr x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Expr body))] + [(recbind lhs* rhs* body) + (make-recbind lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional + (Expr test) + (Expr conseq) + (Expr altern))] + [(seq e0 e1) + (make-seq (Expr e0) (Expr e1))] + [(clambda cls*) + (make-clambda + (map (lambda (x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (Expr body))])) + cls*))] + [(primcall rator rand*) + (make-primcall rator (map Expr rand*))] + [(funcall rator rand*) + (inline (Expr rator) (map Expr rand*))] + [(appcall rator rand*) + (make-appcall (Expr rator) (map Expr rand*))] + [(forcall rator rand*) + (make-forcall rator (map Expr rand*))] + [(assign lhs rhs) + (make-assign lhs (Expr rhs))] + [else (error who "invalid expression ~s" (unparse x))])) + (Expr x)) + + +(define (optimize-letrec x) + (define who 'optimize-letrec) + (define (extend-hash lhs* h ref) + (for-each (lambda (lhs) (put-hash-table! h lhs #t)) lhs*) + (lambda (x) + (unless (get-hash-table h x #f) + (put-hash-table! h x #t) + (ref x)))) + (define (E* x* ref comp) + (cond + [(null? x*) '()] + [else + (cons (E (car x*) ref comp) + (E* (cdr x*) ref comp))])) + (define (do-rhs* i lhs* rhs* ref comp vref vcomp) + (cond + [(null? rhs*) '()] + [else + (let ([h (make-hash-table)]) + (let ([ref + (lambda (x) + (unless (get-hash-table h x #f) + (put-hash-table! h x #t) + (ref x) + (when (memq x lhs*) + (vector-set! vref i #t))))] + [comp + (lambda () + (vector-set! vcomp i #t) + (comp))]) + (cons (E (car rhs*) ref comp) + (do-rhs* (fxadd1 i) lhs* (cdr rhs*) ref comp vref vcomp))))])) + (define (partition-rhs* i lhs* rhs* vref vcomp) + (cond + [(null? lhs*) (values '() '() '() '() '() '())] + [else + (let-values + ([(slhs* srhs* llhs* lrhs* clhs* crhs*) + (partition-rhs* (fxadd1 i) (cdr lhs*) (cdr rhs*) vref vcomp)] + [(lhs rhs) (values (car lhs*) (car rhs*))]) + (cond + [(var-assigned lhs) + (values slhs* srhs* llhs* lrhs* (cons lhs clhs*) (cons rhs crhs*))] + [(clambda? rhs) + (values slhs* srhs* (cons lhs llhs*) (cons rhs lrhs*) clhs* crhs*)] + [(or (vector-ref vref i) (vector-ref vcomp i)) + (values slhs* srhs* llhs* lrhs* (cons lhs clhs*) (cons rhs crhs*))] + [else + (values (cons lhs slhs*) (cons rhs srhs*) llhs* lrhs* clhs* crhs*)] + ))])) + (define (do-recbind lhs* rhs* body ref comp) + (let ([h (make-hash-table)] + [vref (make-vector (length lhs*) #f)] + [vcomp (make-vector (length lhs*) #f)]) + (let* ([ref (extend-hash lhs* h ref)] + [body (E body ref comp)]) + (let ([rhs* (do-rhs* 0 lhs* rhs* ref comp vref vcomp)]) + (let-values ([(slhs* srhs* llhs* lrhs* clhs* crhs*) + (partition-rhs* 0 lhs* rhs* vref vcomp)]) + (let ([v* (map (lambda (x) (make-primcall 'void '())) clhs*)] + [t* (map (lambda (x) (unique-var 'tmp)) clhs*)]) + (make-bind slhs* srhs* + (make-bind clhs* v* + (make-fix llhs* lrhs* + (make-bind t* crhs* + (build-assign* clhs* t* body))))))))))) + (define (build-assign* lhs* rhs* body) + (cond + [(null? lhs*) body] + [else + (make-seq + (make-assign (car lhs*) (car rhs*)) + (build-assign* (cdr lhs*) (cdr rhs*) body))])) + (define (E x ref comp) + (record-case x + [(constant) x] + [(var) (ref x) x] + [(assign lhs rhs) + (set-var-assigned! lhs #t) + (ref lhs) + (make-assign lhs (E rhs ref comp))] + [(primref) x] + [(bind lhs* rhs* body) + (let ([rhs* (E* rhs* ref comp)]) + (let ([h (make-hash-table)]) + (let ([body (E body (extend-hash lhs* h ref) comp)]) + (make-bind lhs* rhs* body))))] + [(recbind lhs* rhs* body) + (if (null? lhs*) + (E body ref comp) + (do-recbind lhs* rhs* body ref comp))] + [(conditional e0 e1 e2) + (make-conditional (E e0 ref comp) (E e1 ref comp) (E e2 ref comp))] + [(seq e0 e1) (make-seq (E e0 ref comp) (E e1 ref comp))] + [(clambda cls*) + (make-clambda + (map (lambda (x) + (record-case x + [(clambda-case fml* proper body) + (let ([h (make-hash-table)]) + (let ([body (E body (extend-hash fml* h ref) void)]) + (make-clambda-case fml* proper body)))])) + cls*))] + [(primcall rator rand*) + (when (memq rator '(call/cc call/cf)) + (comp)) + (make-primcall rator (E* rand* ref comp))] + [(funcall rator rand*) + (let ([rator (E rator ref comp)] [rand* (E* rand* ref comp)]) + (record-case rator + [(primref op) + (when (memq op '(call/cc call/cf)) + (comp))] + [else + (comp)]) + (make-funcall rator rand*))] + [(appcall rator rand*) + (let ([rator (E rator ref comp)] [rand* (E* rand* ref comp)]) + (record-case rator + [(primref op) + (when (memq op '(call/cc call/cf)) + (comp))] + [else + (comp)]) + (make-appcall rator rand*))] + [(forcall rator rand*) + (make-forcall rator (E* rand* ref comp))] + [else (error who "invalid expression ~s" (unparse x))])) + (E x (lambda (x) (error who "free var ~s found" x)) + void)) + + +(define (remove-letrec x) + (define who 'remove-letrec) + (define (Expr x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Expr body))] + [(recbind lhs* rhs* body) + (let ([t* (map (lambda (lhs) (unique-var 'tmp)) lhs*)] + [v* (map (lambda (lhs) (make-primcall 'void '())) lhs*)]) + (make-bind lhs* v* + (make-bind t* (map Expr rhs*) + (let f ([lhs* lhs*] [t* t*]) + (cond + [(null? lhs*) (Expr body)] + [else + (make-seq + (make-assign (car lhs*) (car t*)) + (f (cdr lhs*) (cdr t*)))])))))] + ;[(fix lhs* rhs* body) + ; (Expr (make-recbind lhs* rhs* body))] + [(fix lhs* rhs* body) + (make-fix lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional + (Expr test) + (Expr conseq) + (Expr altern))] + [(seq e0 e1) + (make-seq (Expr e0) (Expr e1))] + [(clambda cls*) + (make-clambda + (map (lambda (x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (Expr body))])) + cls*))] + [(primcall rator rand*) + (make-primcall rator (map Expr rand*))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall rator rand*) + (make-appcall (Expr rator) (map Expr rand*))] + [(forcall rator rand*) + (make-forcall rator (map Expr rand*))] + [(assign lhs rhs) + (make-assign lhs (Expr rhs))] + [else (error who "invalid expression ~s" (unparse x))])) + (Expr x)) + + + +(define (uncover-assigned x) + (define who 'uncover-assigned) + (define (Expr* x*) + (for-each Expr x*)) + (define (Expr x) + (record-case x + [(constant) (void)] + [(var) (void)] + [(primref) (void)] + [(bind lhs* rhs* body) + (begin (Expr body) (Expr* rhs*))] + [(recbind lhs* rhs* body) + (begin (Expr body) (Expr* rhs*))] + [(fix lhs* rhs* body) + (Expr* rhs*) + (Expr body) + (when (ormap var-assigned lhs*) + (error 'uncover-assigned "a fix lhs is assigned"))] + [(conditional test conseq altern) + (begin (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (begin (Expr e0) (Expr e1))] + [(clambda cls*) + (for-each + (lambda (cls) + (Expr (clambda-case-body cls))) + cls*)] + [(primcall rator rand*) (Expr* rand*)] + [(funcall rator rand*) + (begin (Expr rator) (Expr* rand*))] + [(appcall rator rand*) + (begin (Expr rator) (Expr* rand*))] + [(forcall rator rand*) (Expr* rand*)] + [(assign lhs rhs) + (set-var-assigned! lhs #t) + (Expr rhs)] + [else (error who "invalid expression ~s" (unparse x))])) + (Expr x)) + + + +(define (rewrite-assignments x) + (define who 'rewrite-assignments) + (define (fix-lhs* lhs*) + (cond + [(null? lhs*) (values '() '() '())] + [else + (let ([x (car lhs*)]) + (let-values ([(lhs* a-lhs* a-rhs*) (fix-lhs* (cdr lhs*))]) + (cond + [(var-assigned x) + (let ([t (unique-var 'assignment-tmp)]) + (values (cons t lhs*) (cons x a-lhs*) (cons t a-rhs*)))] + [else + (values (cons x lhs*) a-lhs* a-rhs*)])))])) + (define (bind-assigned lhs* rhs* body) + (cond + [(null? lhs*) body] + [else + (make-bind lhs* + (map (lambda (rhs) (make-primcall 'vector (list rhs))) rhs*) + body)])) + (define (Expr x) + (record-case x + [(constant) x] + [(var) + (cond + [(var-assigned x) + (make-primcall '$vector-ref (list x (make-constant 0)))] + [else x])] + [(primref) x] + [(bind lhs* rhs* body) + (let-values ([(lhs* a-lhs* a-rhs*) (fix-lhs* lhs*)]) + (make-bind lhs* (map Expr rhs*) + (bind-assigned a-lhs* a-rhs* (Expr body))))] + [(fix lhs* rhs* body) + (make-fix lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (make-seq (Expr e0) (Expr e1))] + [(clambda cls*) + (make-clambda + (map (lambda (cls) + (record-case cls + [(clambda-case fml* proper body) + (let-values ([(fml* a-lhs* a-rhs*) (fix-lhs* fml*)]) + (make-clambda-case fml* proper + (bind-assigned a-lhs* a-rhs* (Expr body))))])) + cls*))] + [(primcall op rand*) + (make-primcall op (map Expr rand*))] + [(forcall op rand*) + (make-forcall op (map Expr rand*))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall rator rand*) + (make-appcall (Expr rator) (map Expr rand*))] + [(assign lhs rhs) + (unless (var-assigned lhs) + (error 'rewrite-assignments "not assigned ~s in ~s" lhs x)) + (make-primcall '$vector-set! (list lhs (make-constant 0) (Expr rhs)))] + [else (error who "invalid expression ~s" (unparse x))])) + (Expr x)) + + +(define (remove-assignments x) + (uncover-assigned x) + (rewrite-assignments x)) + + + + +(define (convert-closures prog) + (define who 'convert-closures) + (define (Expr* x*) + (cond + [(null? x*) (values '() '())] + [else + (let-values ([(a a-free) (Expr (car x*))] + [(d d-free) (Expr* (cdr x*))]) + (values (cons a d) (union a-free d-free)))])) + (define (do-clambda* x*) + (cond + [(null? x*) (values '() '())] + [else + (let-values ([(a a-free) (do-clambda (car x*))] + [(d d-free) (do-clambda* (cdr x*))]) + (values (cons a d) (union a-free d-free)))])) + (define (do-clambda x) + (record-case x + [(clambda cls*) + (let-values ([(cls* free) + (let f ([cls* cls*]) + (cond + [(null? cls*) (values '() '())] + [else + (record-case (car cls*) + [(clambda-case fml* proper body) + (let-values ([(body body-free) (Expr body)] + [(cls* cls*-free) (f (cdr cls*))]) + (values + (cons (make-clambda-case fml* proper body) + cls*) + (union (difference body-free fml*) + cls*-free)))])]))]) + (values (make-closure (make-clambda-code (gensym) cls* free) free) + free))])) + (define (Expr ex) + (record-case ex + [(constant) (values ex '())] + [(var) (values ex (singleton ex))] + [(primref) (values ex '())] + [(bind lhs* rhs* body) + (let-values ([(rhs* rhs-free) (Expr* rhs*)] + [(body body-free) (Expr body)]) + (values (make-bind lhs* rhs* body) + (union rhs-free (difference body-free lhs*))))] + [(fix lhs* rhs* body) + (let-values ([(rhs* rfree) (do-clambda* rhs*)] + [(body bfree) (Expr body)]) + (values (make-fix lhs* rhs* body) + (difference (union bfree rfree) lhs*)))] + [(conditional test conseq altern) + (let-values ([(test test-free) (Expr test)] + [(conseq conseq-free) (Expr conseq)] + [(altern altern-free) (Expr altern)]) + (values (make-conditional test conseq altern) + (union test-free (union conseq-free altern-free))))] + [(seq e0 e1) + (let-values ([(e0 e0-free) (Expr e0)] + [(e1 e1-free) (Expr e1)]) + (values (make-seq e0 e1) (union e0-free e1-free)))] + [(clambda) + (do-clambda ex)] + [(primcall op rand*) + (let-values ([(rand* rand*-free) (Expr* rand*)]) + (values (make-primcall op rand*) rand*-free))] + [(forcall op rand*) + (let-values ([(rand* rand*-free) (Expr* rand*)]) + (values (make-forcall op rand*) rand*-free))] + [(funcall rator rand*) + (let-values ([(rator rat-free) (Expr rator)] + [(rand* rand*-free) (Expr* rand*)]) + (values (make-funcall rator rand*) + (union rat-free rand*-free)))] + [(appcall rator rand*) + (let-values ([(rator rat-free) (Expr rator)] + [(rand* rand*-free) (Expr* rand*)]) + (values (make-appcall rator rand*) + (union rat-free rand*-free)))] + [else (error who "invalid expression ~s" (unparse ex))])) + (let-values ([(prog free) (Expr prog)]) + (unless (null? free) + (error 'convert-closures "free vars ~s encountered in ~a" + free (unparse prog))) + prog)) + + +(define (lift-codes x) + (define who 'lift-codes) + (define all-codes '()) + (define (do-code x) + (record-case x + [(clambda-code label cls* free) + (let ([cls* (map + (lambda (x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (E body))])) + cls*)]) + (let ([g (make-code-loc label)]) + (set! all-codes + (cons (make-clambda-code label cls* free) all-codes)) + g))])) + (define (E x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(bind lhs* rhs* body) + (make-bind lhs* (map E rhs*) (E body))] + [(fix lhs* rhs* body) + (make-fix lhs* (map E rhs*) (E body))] + [(conditional test conseq altern) + (make-conditional (E test) (E conseq) (E altern))] + [(seq e0 e1) (make-seq (E e0) (E e1))] + [(closure c free) (make-closure (do-code c) free)] + [(primcall op rand*) (make-primcall op (map E rand*))] + [(forcall op rand*) (make-forcall op (map E rand*))] + [(funcall rator rand*) (make-funcall (E rator) (map E rand*))] + [(appcall rator rand*) (make-appcall (E rator) (map E rand*))] + [else (error who "invalid expression ~s" (unparse x))])) + (let ([x (E x)]) + (make-codes all-codes x))) + + + + +(define (syntactically-valid? op rand*) + (define (valid-arg-count? op rand*) + (let ([n (open-coded-primitive-args op)] [m (length rand*)]) + (cond + [(eq? n 'any) #t] + [(eq? n 'no-code) + (error 'syntactically-valid + "should not primcall non codable prim ~s" op)] + [(fixnum? n) + (cond + [(fx= n m) #t] + [else + (error 'compile + "Possible incorrect number of args in ~s" + (cons op (map unparse rand*))) + #f])] + [else (error 'do-primcall "BUG: what ~s" n)]))) + (define (check op pred?) + (lambda (arg) + (record-case arg + [(constant c) + (cond + [(pred? c) #t] + [else + (error 'compile "Possible argument error to primitive ~s" op) + #f])] + [(primref) + (cond + [(pred? (lambda (x) x)) #t] + [else + (error 'compile "Possible argument error to primitive ~s" op) + #f])] + [else #t]))) + (define (nonnegative-fixnum? n) + (and (fixnum? n) (fx>= n 0))) + (define (byte? n) + (and (fixnum? n) (fx<= 0 n) (fx<= n 127))) + (define (valid-arg-types? op rand*) + (case op + [(fixnum? immediate? boolean? char? vector? string? procedure? + null? pair? not cons eq? vector symbol? error eof-object eof-object? + void $unbound-object? code? $forward-ptr? bwp-object? + pointer-value) + '#t] + [($fxadd1 $fxsub1 $fxzero? $fxlognot $fxlogor $fxlogand $fx+ $fx- $fx* + $fx= $fx< $fx<= $fx> $fx>= $fxquotient $fxmodulo $fxsll $fxsra $fxlogxor $exit) + (andmap (check op fixnum?) rand*)] + [($fixnum->char) + (andmap (check op byte?) rand*)] + [($char->fixnum $char= $char< $char<= $char> $char>= $string) + (andmap (check op char?) rand*)] + [($make-vector $make-string) + (andmap (check op nonnegative-fixnum?) rand*)] + [($car $cdr) + (andmap (check op pair?) rand*)] + [($vector-length) + (andmap (check op vector?) rand*)] + [($string-length) + (andmap (check op string?) rand*)] + [($set-car! $set-cdr!) + ((check op pair?) (car rand*))] + [($vector-ref $vector-set!) + (and ((check op vector?) (car rand*)) + ((check op nonnegative-fixnum?) (cadr rand*)))] + [($string-ref $string-set! + $string-ref-16+0 $string-ref-16+1 $string-ref-8+0 $string-ref-8+2) + (and ((check op string?) (car rand*)) + ((check op nonnegative-fixnum?) (cadr rand*)))] + [($symbol-string $symbol-unique-string) + (andmap (check op symbol?) rand*)] + [($constant-ref $set-constant! $intern $pcb-set! $pcb-ref $make-symbol + $symbol-value $set-symbol-value! $symbol-plist $set-symbol-plist! + $set-symbol-system-value! $set-symbol-system-value! + $set-symbol-unique-string! + $set-symbol-string! + $seal-frame-and-call $frame->continuation $code->closure + $code-instr-size $code-reloc-size $code-closure-size + $set-code-byte! $set-code-word! + $set-code-object! $set-code-object+offset! $set-code-object+offset/rel! + $make-record $record? $record/rtd? $record-rtd $record-ref $record-set! + primitive-set! primitive-ref + $make-tcbucket $tcbucket-key $tcbucket-val $tcbucket-next + $set-tcbucket-val! $set-tcbucket-next! $set-tcbucket-tconc!) + #t] + [else (error 'valid-arg-types? "unhandled op ~s" op)])) + (and (valid-arg-count? op rand*) + (or (null? rand*) + (valid-arg-types? op rand*)))) + + +;;; the output of simplify-operands differs from the input in that the +;;; operands to primcalls are all simple (variables, primrefs, or constants). +;;; funcalls to open-codable primrefs whos arguments are "ok" are converted to +;;; primcalls. + +(define (introduce-primcalls x) + (define who 'introduce-primcalls) + (define (simple? x) + (or (constant? x) (var? x) (primref? x))) + (define (Expr x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(closure) x] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Expr body))] + [(fix lhs* rhs* body) + (make-fix lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (make-seq (Expr e0) (Expr e1))] + [(primcall op arg*) + (case op + ;[(values) + ; (if (fx= (length arg*) 1) + ; (Expr (car arg*)) + ; (begin + ; (warning 'compile "possible incorrect number of values") + ; (make-funcall (make-primref 'values) (map Expr arg*))))] + [else + (make-primcall op (map Expr arg*))])] + [(forcall op arg*) + (make-forcall op (map Expr arg*))] + [(funcall rator rand*) + (cond + [(and (primref? rator) + (open-codeable? (primref-name rator)) + (syntactically-valid? (primref-name rator) rand*)) + (Expr (make-primcall (primref-name rator) rand*))] + [else + (make-funcall (Expr rator) (map Expr rand*))])] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (Tail x) + (record-case x + [(constant) (make-return x)] + [(var) (make-return x)] + [(primref) (make-return x)] + [(closure) (make-return x)] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Tail body))] + [(fix lhs* rhs* body) + (make-fix lhs* (map Expr rhs*) (Tail body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Tail conseq) (Tail altern))] + [(seq e0 e1) (make-seq (Expr e0) (Tail e1))] + [(primcall op arg*) + (case op + ;[(values) + ; (if (fx= (length arg*) 1) + ; (make-return (Expr (car arg*))) + ; (make-return* (map Expr arg*)))] + [else + (make-return (make-primcall op (map Expr arg*)))])] + [(forcall op arg*) + (make-return (make-forcall op (map Expr arg*)))] + [(funcall rator rand*) + (cond + [(and (primref? rator) + (open-codeable? (primref-name rator)) + (syntactically-valid? (primref-name rator) rand*)) + (Tail (make-primcall (primref-name rator) rand*))] + [else + (make-funcall (Expr rator) (map Expr rand*))])] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (CaseExpr x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (Tail body))])) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (make-clambda-code L (map CaseExpr cases) free)])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) (Tail body))])) + (CodesExpr x)) + + +(define (simplify-operands x) + (define who 'simplify-operands) + (define (simple? x) + (or (constant? x) (var? x) (primref? x))) + (define (simplify arg lhs* rhs* k) + (if (simple? arg) + (k arg lhs* rhs*) + (let ([v (unique-var 'tmp)]) + (k v (cons v lhs*) (cons (Expr arg) rhs*))))) + (define (simplify* arg* lhs* rhs* k) + (cond + [(null? arg*) (k '() lhs* rhs*)] + [else + (simplify (car arg*) lhs* rhs* + (lambda (a lhs* rhs*) + (simplify* (cdr arg*) lhs* rhs* + (lambda (d lhs* rhs*) + (k (cons a d) lhs* rhs*)))))])) + (define (Expr x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(closure) x] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Expr body))] + [(fix lhs* rhs* body) + (make-fix lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (make-seq (Expr e0) (Expr e1))] + [(primcall op arg*) + (simplify* arg* '() '() + (lambda (arg* lhs* rhs*) + (make-bind^ lhs* rhs* + (make-primcall op arg*))))] + [(forcall op arg*) + (make-forcall op (map Expr arg*))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (Tail x) + (record-case x + [(return v) (make-return (Expr v))] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Tail body))] + [(fix lhs* rhs* body) + (make-fix lhs* (map Expr rhs*) (Tail body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Tail conseq) (Tail altern))] + [(seq e0 e1) (make-seq (Expr e0) (Tail e1))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (CaseExpr x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (Tail body))])) + (define (CodeExpr x) + (record-case x + [(clambda-code L clauses free) + (make-clambda-code L (map CaseExpr clauses) free)])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) (Tail body))])) + (CodesExpr x)) + + +(define (insert-stack-overflow-checks x) + (define who 'insert-stack-overflow-checks) + (define (insert-check body) + (make-seq + (make-conditional + (make-primcall '$fp-overflow '()) + (make-funcall (make-primref 'do-stack-overflow) '()) + (make-primcall 'void '())) + body)) + (define (Expr x) + (record-case x + [(constant) #f] + [(var) #f] + [(primref) #f] + [(closure code free*) #f] + [(bind lhs* rhs* body) + (or (ormap Expr rhs*) (Expr body))] + [(fix lhs* rhs* body) (Expr body)] + [(conditional test conseq altern) + (or (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (or (Expr e0) (Expr e1))] + [(primcall op arg*) (ormap Expr arg*)] + [(forcall op arg*) (ormap Expr arg*)] + [(funcall rator arg*) #t] + [(appcall rator arg*) #t] + [else (error who "invalid expression ~s" (unparse x))])) + (define (Tail x) + (record-case x + [(return v) (Expr v)] + [(bind lhs* rhs* body) + (or (ormap Expr rhs*) (Tail body))] + [(fix lhs* rhs* body) (Tail body)] + [(conditional test conseq altern) + (or (Expr test) (Tail conseq) (Tail altern))] + [(seq e0 e1) (or (Expr e0) (Tail e1))] + [(funcall rator arg*) (or (Expr rator) (ormap Expr arg*))] + [(appcall rator arg*) (or (Expr rator) (ormap Expr arg*))] + [else (error who "invalid tail expression ~s" (unparse x))])) + (define (CaseExpr x) + (record-case x + [(clambda-case fml* proper body) + (if (Tail body) + (make-clambda-case fml* proper (insert-check body)) + x)])) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (make-clambda-code L (map CaseExpr cases) free)])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) + (if (Tail body) + (insert-check body) + body))])) + (CodesExpr x)) + + +(define (insert-allocation-checks x) + (define who 'insert-allocation-checks) + (define (check-bytes n var body) + (make-seq + (make-conditional + (make-primcall '$ap-check-bytes + (list (make-constant n) var)) + (make-funcall (make-primref 'do-overflow) + (list + (make-primcall '$fx+ + (list (make-constant n) var)))) + (make-primcall 'void '())) + body)) + (define (check-words n var body) + (make-seq + (make-conditional + (make-primcall '$ap-check-words + (list (make-constant n) var)) + (make-funcall (make-primref 'do-overflow-words) + (list + (make-primcall '$fx+ + (list (make-constant n) var)))) + (make-primcall 'void '())) + body)) + (define (check-const n body) + (make-seq + (make-conditional + (make-primcall '$ap-check-const + (list (make-constant n))) + (make-funcall (make-primref 'do-overflow) + (list (make-constant n))) + (make-primcall 'void '())) + body)) + (define (closure-size x) + (record-case x + [(closure code free*) + (align (fx+ disp-closure-data (fx* (length free*) wordsize)))] + [else (error 'closure-size "~s is not a closure" x)])) + (define (sum ac ls) + (cond + [(null? ls) ac] + [else (sum (fx+ ac (car ls)) (cdr ls))])) + (define (Expr x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(closure) + (check-const (closure-size x) x)] + [(fix lhs* rhs* body) + (if (null? lhs*) + (Expr body) + (check-const (sum 0 (map closure-size rhs*)) + (make-fix lhs* rhs* + (Expr body))))] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (make-seq (Expr e0) (Expr e1))] + [(primcall op arg*) + (let ([x (make-primcall op (map Expr arg*))]) + (case op + [(cons) (check-const pair-size x)] + [($make-symbol) (check-const symbol-size x)] + [($make-tcbucket) (check-const tcbucket-size x)] + [($frame->continuation $code->closure) + (check-const (fx+ disp-closure-data (fx* (length arg*) wordsize)) x)] + [($make-string) + (record-case (car arg*) + [(constant i) + (check-const (fx+ i (fx+ disp-string-data 1)) x)] + [else + (check-bytes (fxadd1 disp-string-data) (car arg*) x)])] + [($string) + (check-const (fx+ (length arg*) (fx+ disp-string-data 1)) x)] + [($make-vector) + (record-case (car arg*) + [(constant i) + (check-const (fx+ (fx* i wordsize) disp-vector-data) x)] + [else + (check-words (fxadd1 disp-vector-data) (car arg*) x)])] + [($make-record) + (record-case (cadr arg*) + [(constant i) + (check-const (fx+ (fx* i wordsize) disp-record-data) x)] + [else + (check-words (fxadd1 disp-record-data) (cadr arg*) x)])] + [(vector) + (check-const (fx+ (fx* (length arg*) wordsize) disp-vector-data) x)] + [else x]))] + [(forcall op arg*) + (make-forcall op (map Expr arg*))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (Tail x) + (record-case x + [(return v) (make-return (Expr v))] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Tail body))] + [(fix lhs* rhs* body) + (if (null? lhs*) + (Tail body) + (check-const (sum 0 (map closure-size rhs*)) + (make-fix lhs* rhs* + (Tail body))))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Tail conseq) (Tail altern))] + [(seq e0 e1) (make-seq (Expr e0) (Tail e1))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (CaseExpr x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (Tail body))])) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (make-clambda-code L (map CaseExpr cases) free)])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) (Tail body))])) + (CodesExpr x)) + + +(define (remove-local-variables x) + (define who 'remove-local-variables) + (define (simple* x* r) + (map (lambda (x) + (cond + [(assq x r) => cdr] + [else + (when (var? x) (error who "unbound var ~s" x)) + x])) + x*)) + (define (env->mask r sz) + (let ([s (make-vector (fxsra (fx+ sz 7) 3) 0)]) + (for-each + (lambda (idx) + (let ([q (fxsra idx 3)] + [r (fxlogand idx 7)]) + (vector-set! s q + (fxlogor (vector-ref s q) (fxsll 1 r))))) + r) + s)) + (define (do-new-frame op rand* si r call-convention rp-convention orig-live) + (make-new-frame (fxadd1 si) (fx+ (length rand*) 2) + (let f ([r* rand*] [nsi (fx+ si 2)] [live orig-live]) + (cond + [(null? r*) + (make-seq + (make-seq + (make-save-cp (make-frame-var si)) + (case call-convention + [(normal apply) + (make-eval-cp #t (Expr op nsi r (cons si live)))] + [(foreign) + (make-eval-cp #f (make-foreign-label op))] + [else (error who "invalid convention ~s" call-convention)])) + (make-call-cp call-convention + rp-convention + (fxadd1 si) ; frame size + (length rand*) ; argc + (env->mask (cons si orig-live) ; cp and everything before it + (fxadd1 si))))] ; mask-size ~~ frame size + [else + (make-seq + (make-assign (make-frame-var nsi) + (Expr (car r*) nsi r live)) + (f (cdr r*) (fxadd1 nsi) (cons nsi live)))])))) + (define (nop) (make-primcall 'void '())) + (define (do-bind lhs* rhs* body si r live k) + (let f ([lhs* lhs*] [rhs* rhs*] [si si] [nr r] [live live]) + (cond + [(null? lhs*) (k body si nr live)] + [else + (let ([v (make-frame-var si)]) + (make-seq + (make-assign v (Expr (car rhs*) si r live)) + (f (cdr lhs*) (cdr rhs*) (fxadd1 si) + (cons (cons (car lhs*) v) nr) + (cons si live))))]))) + (define (do-closure r) + (lambda (x) + (record-case x + [(closure code free*) + (make-closure code (simple* free* r))]))) + (define (do-fix lhs* rhs* body si r live k) + (let f ([l* lhs*] [nlhs* '()] [si si] [r r] [live live]) + (cond + [(null? l*) + (make-fix (reverse nlhs*) + (map (do-closure r) rhs*) + (k body si r live))] + [else + (let ([v (make-frame-var si)]) + (f (cdr l*) (cons v nlhs*) (fxadd1 si) + (cons (cons (car l*) v) r) + (cons si live)))]))) + (define (Tail x si r live) + (record-case x + [(return v) (make-return (Expr v si r live))] + [(bind lhs* rhs* body) + (do-bind lhs* rhs* body si r live Tail)] + [(fix lhs* rhs* body) + (do-fix lhs* rhs* body si r live Tail)] + [(conditional test conseq altern) + (make-conditional + (Expr test si r live) + (Tail conseq si r live) + (Tail altern si r live))] + [(seq e0 e1) (make-seq (Effect e0 si r live) (Tail e1 si r live))] + [(primcall op arg*) + (case op +; [(values) (make-primcall op (simple* arg* r))] + [else (make-return (make-primcall op (simple* arg* r)))])] + [(funcall op rand*) + (do-new-frame op rand* si r 'normal 'tail live)] + [(appcall op rand*) + (do-new-frame op rand* si r 'apply 'tail live)] + [else (error who "invalid expression ~s" (unparse x))])) + (define (Effect x si r live) + (record-case x + [(constant) (nop)] + [(var) (nop)] + [(primref) (nop)] + [(closure code free*) (nop)] + [(bind lhs* rhs* body) + (do-bind lhs* rhs* body si r live Effect)] + [(fix lhs* rhs* body) + (do-fix lhs* rhs* body si r live Effect)] + [(conditional test conseq altern) + (make-conditional + (Expr test si r live) + (Effect conseq si r live) + (Effect altern si r live))] + [(seq e0 e1) (make-seq (Effect e0 si r live) (Effect e1 si r live))] + [(primcall op arg*) + (make-primcall op (simple* arg* r))] + [(forcall op rand*) + (do-new-frame op rand* si r 'foreign 'effect live)] + [(funcall op rand*) + (do-new-frame op rand* si r 'normal 'effect live)] + [(appcall op rand*) + (do-new-frame op rand* si r 'apply 'effect live)] + [else (error who "invalid effect expression ~s" (unparse x))])) + (define (Expr x si r live) + (record-case x + [(constant) x] + [(var) + (cond + [(assq x r) => cdr] + [else (error who "unbound var ~s" x)])] + [(primref) x] + [(closure code free*) + (make-closure code (simple* free* r))] + [(bind lhs* rhs* body) + (do-bind lhs* rhs* body si r live Expr)] + [(fix lhs* rhs* body) + (do-fix lhs* rhs* body si r live Expr)] + [(conditional test conseq altern) + (make-conditional + (Expr test si r live) + (Expr conseq si r live) + (Expr altern si r live))] + [(seq e0 e1) (make-seq (Effect e0 si r live) (Expr e1 si r live))] + [(primcall op arg*) + (make-primcall op (simple* arg* r))] + [(forcall op rand*) + (do-new-frame op rand* si r 'foreign 'value live)] + [(funcall op rand*) + (do-new-frame op rand* si r 'normal 'value live)] + [(appcall op rand*) + (do-new-frame op rand* si r 'apply 'value live)] + [else (error who "invalid expression ~s" (unparse x))])) + (define (bind-fml* fml* r) + (let f ([si 1] [fml* fml*]) + (cond + [(null? fml*) (values '() si r '())] + [else + (let-values ([(nfml* nsi r live) (f (fxadd1 si) (cdr fml*))]) + (let ([v (make-frame-var si)]) + (values (cons v nfml*) + nsi + (cons (cons (car fml*) v) r) + (cons si live))))]))) + (define (bind-free* free*) + (let f ([free* free*] [idx 0] [r '()]) + (cond + [(null? free*) r] + [else + (f (cdr free*) (fxadd1 idx) + (cons (cons (car free*) (make-cp-var idx)) r))]))) + (define CaseExpr + (lambda (r) + (lambda (x) + (record-case x + [(clambda-case fml* proper body) + (let-values ([(fml* si r live) (bind-fml* fml* r)]) + (make-clambda-case fml* proper (Tail body si r live)))])))) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (let ([r (bind-free* free)]) + (make-clambda-code L (map (CaseExpr r) cases) free))])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) + (Tail body 1 '() '()))])) + (CodesExpr x)) + + +(begin + (define fx-shift 2) + (define fx-mask #x03) + (define fx-tag 0) + (define bool-f #x2F) + (define bool-t #x3F) + (define bool-mask #xEF) + (define bool-tag #x2F) + (define bool-shift 4) + (define nil #x4F) + (define eof #x5F) ; double check + (define unbound #x6F) ; double check + (define void-object #x7F) ; double check + (define bwp-object #x8F) ; double check + (define char-shift 8) + (define char-tag #x0F) + (define char-mask #xFF) + (define pair-mask 7) + (define pair-tag 1) + (define disp-car 0) + (define disp-cdr 4) + (define pair-size 8) + (define pagesize 4096) + (define pageshift 12) + (define wordsize 4) + (define wordshift 2) + + (define symbol-mask 7) + (define symbol-tag 2) + (define disp-symbol-string 0) + (define disp-symbol-unique-string 4) + (define disp-symbol-value 8) + (define disp-symbol-plist 12) + (define disp-symbol-system-value 16) + (define disp-symbol-system-plist 20) + (define symbol-size 24) + (define vector-tag 5) + (define vector-mask 7) + (define disp-vector-length 0) + (define disp-vector-data 4) + (define string-mask 7) + (define string-tag 6) + (define disp-string-length 0) + (define disp-string-data 4) + (define closure-mask 7) + (define closure-tag 3) + (define disp-closure-data 4) + (define disp-closure-code 0) + (define continuation-size 16) + (define continuation-tag #x1F) + (define disp-continuation-top 4) + (define disp-continuation-size 8) + (define disp-continuation-next 12) + (define code-tag #x2F) + (define disp-code-instrsize 4) + (define disp-code-relocsize 8) + (define disp-code-closuresize 12) + (define disp-code-data 16) + (define disp-tcbucket-tconc 0) + (define disp-tcbucket-key 4) + (define disp-tcbucket-val 8) + (define disp-tcbucket-next 12) + (define tcbucket-size 16) + + (define record-ptag 5) + (define record-pmask 7) + (define disp-record-rtd 0) + (define disp-record-data 4) + (define disp-frame-size -17) + (define disp-frame-offset -13) + (define disp-multivalue-rp -9) + (define object-alignment 8) + (define align-shift 3) + (define dirty-word -1)) + +(define (align n) + (fxsll (fxsra (fx+ n (fxsub1 object-alignment)) align-shift) align-shift)) + +(begin + (define (mem off val) + (cond + [(fixnum? off) (list 'disp (int off) val)] + [(register? off) (list 'disp off val)] + [else (error 'mem "invalid disp ~s" off)])) + (define (int x) (list 'int x)) + (define (obj x) (list 'obj x)) + (define (byte x) (list 'byte x)) + (define (byte-vector x) (list 'byte-vector x)) + (define (movzbl src targ) (list 'movzbl src targ)) + (define (sall src targ) (list 'sall src targ)) + (define (sarl src targ) (list 'sarl src targ)) + (define (shrl src targ) (list 'shrl src targ)) + (define (notl src) (list 'notl src)) + (define (pushl src) (list 'pushl src)) + (define (popl src) (list 'popl src)) + (define (orl src targ) (list 'orl src targ)) + (define (xorl src targ) (list 'xorl src targ)) + (define (andl src targ) (list 'andl src targ)) + (define (movl src targ) (list 'movl src targ)) + (define (movb src targ) (list 'movb src targ)) + (define (addl src targ) (list 'addl src targ)) + (define (imull src targ) (list 'imull src targ)) + (define (idivl src) (list 'idivl src)) + (define (subl src targ) (list 'subl src targ)) + (define (push src) (list 'push src)) + (define (pop targ) (list 'pop targ)) + (define (sete targ) (list 'sete targ)) + (define (call targ) (list 'call targ)) + (define (tail-indirect-cpr-call) + (jmp (mem (fx- disp-closure-code closure-tag) cpr))) + (define (indirect-cpr-call) + (call (mem (fx- disp-closure-code closure-tag) cpr))) + (define (negl targ) (list 'negl targ)) + (define (label x) (list 'label x)) + (define (label-address x) (list 'label-address x)) + (define (ret) '(ret)) + (define (cltd) '(cltd)) + (define (cmpl arg1 arg2) (list 'cmpl arg1 arg2)) + (define (je label) (list 'je label)) + (define (jne label) (list 'jne label)) + (define (jle label) (list 'jle label)) + (define (jge label) (list 'jge label)) + (define (jg label) (list 'jg label)) + (define (jl label) (list 'jl label)) + (define (jb label) (list 'jb label)) + (define (ja label) (list 'ja label)) + (define (jmp label) (list 'jmp label)) + (define edi '%edx) ; closure pointer + (define esi '%esi) ; pcb + (define ebp '%ebp) ; allocation pointer + (define esp '%esp) ; stack base pointer + (define al '%al) + (define ah '%ah) + (define bh '%bh) + (define cl '%cl) + (define eax '%eax) + (define ebx '%ebx) + (define ecx '%ecx) + (define edx '%edx) + (define apr '%ebp) + (define fpr '%esp) + (define cpr '%edi) + (define pcr '%esi) + (define register? symbol?) + (define (argc-convention n) + (fx- 0 (fxsll n fx-shift)))) + + +(define pcb-ref + (lambda (x) + (case x + [(allocation-pointer) (mem 0 pcr)] + [(allocation-redline) (mem 4 pcr)] + [(frame-pointer) (mem 8 pcr)] + [(frame-base) (mem 12 pcr)] + [(frame-redline) (mem 16 pcr)] + [(next-continuation) (mem 20 pcr)] + [(system-stack) (mem 24 pcr)] + [(dirty-vector) (mem 28 pcr)] + [else (error 'pcb-ref "invalid arg ~s" x)]))) + +(define (primref-loc op) + (unless (symbol? op) (error 'primref-loc "not a symbol ~s" op)) + (mem (fx- disp-symbol-system-value symbol-tag) + (obj op))) + +(define (generate-code x) + (define who 'generate-code) + (define (rp-label x) + (case x + [(value) (label-address SL_multiple_values_error_rp)] + [(effect) (label-address SL_multiple_values_ignore_rp)] + [else (error who "invalid rp-convention ~s" x)])) + (define unique-label + (lambda () + (label (gensym)))) + (define (constant-val x) + (cond + [(fixnum? x) (obj x)] + [(boolean? x) (int (if x bool-t bool-f))] + [(null? x) (int nil)] + [(char? x) (int (fx+ (fxsll (char->integer x) char-shift) char-tag))] + [(eq? x (void)) (int void-object)] + [else (obj x)])) + (define (cond-branch op Lt Lf ac) + (define (opposite x) + (cadr (assq x '([je jne] [jl jge] [jle jg] [jg jle] [jge jl])))) + (unless (or Lt Lf) + (error 'cond-branch "no labels")) + (cond + [(not Lf) (cons (list op Lt) ac)] + [(not Lt) (cons (list (opposite op) Lf) ac)] + [else (list* (list op Lt) (jmp Lf) ac)])) + (define (indirect-type-pred pri-mask pri-tag sec-mask sec-tag rand* Lt Lf ac) + (cond + [(and Lt Lf) + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int pri-mask) ebx) + (cmpl (int pri-tag) ebx) + (jne Lf) + (movl (mem (fx- 0 pri-tag) eax) ebx) + (if sec-mask + (andl (int sec-mask) ebx) + '(nop)) + (cmpl (int sec-tag) ebx) + (jne Lf) + (jmp Lt) + ac)] + [Lf + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int pri-mask) ebx) + (cmpl (int pri-tag) ebx) + (jne Lf) + (movl (mem (fx- 0 pri-tag) eax) ebx) + (if sec-mask + (andl (int sec-mask) ebx) + '(nop)) + (cmpl (int sec-tag) ebx) + (jne Lf) + ac)] + [Lt + (let ([L_END (unique-label)]) + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int pri-mask) ebx) + (cmpl (int pri-tag) ebx) + (jne L_END) + (movl (mem (fx- 0 pri-tag) eax) ebx) + (if sec-mask + (andl (int sec-mask) ebx) + '(nop)) + (cmpl (int sec-tag) ebx) + (je Lt) + L_END + ac))] + [else ac])) + (define (type-pred mask tag rand* Lt Lf ac) + (cond + [mask + (list* + (movl (Simple (car rand*)) eax) + (andl (int mask) eax) + (cmpl (int tag) eax) + (cond-branch 'je Lt Lf ac))] + [else + (let ([v (Simple (car rand*))]) + (cond + [(memq (car v) '(mem register)) + (list* + (cmpl (int tag) (Simple (car rand*))) + (cond-branch 'je Lt Lf ac))] + [else + (list* + (movl (Simple (car rand*)) eax) + (cmpl (int tag) eax) + (cond-branch 'je Lt Lf ac))]))])) + (define (compare-and-branch op rand* Lt Lf ac) + (define (opposite x) + (cadr (assq x '([je je] [jl jg] [jle jge] [jg jl] [jge jle])))) + (cond + [(and (constant? (car rand*)) (constant? (cadr rand*))) + (list* + (movl (Simple (car rand*)) eax) + (cmpl (Simple (cadr rand*)) eax) + (cond-branch op Lt Lf ac))] + [(constant? (cadr rand*)) + (list* + (cmpl (Simple (cadr rand*)) (Simple (car rand*))) + (cond-branch op Lt Lf ac))] + [(constant? (car rand*)) + (list* + (cmpl (Simple (car rand*)) (Simple (cadr rand*))) + (cond-branch (opposite op) Lt Lf ac))] + [else + (list* + (movl (Simple (car rand*)) eax) + (cmpl (Simple (cadr rand*)) eax) + (cond-branch op Lt Lf ac))])) + (define (do-pred-prim op rand* Lt Lf ac) + (case op + [(fixnum?) (type-pred fx-mask fx-tag rand* Lt Lf ac)] + [(pair?) (type-pred pair-mask pair-tag rand* Lt Lf ac)] + [(char?) (type-pred char-mask char-tag rand* Lt Lf ac)] + [(string?) (type-pred string-mask string-tag rand* Lt Lf ac)] + [(symbol?) (type-pred symbol-mask symbol-tag rand* Lt Lf ac)] + [(procedure?) (type-pred closure-mask closure-tag rand* Lt Lf ac)] + [(boolean?) (type-pred bool-mask bool-tag rand* Lt Lf ac)] + [(null?) (type-pred #f nil rand* Lt Lf ac)] + [($unbound-object?) (type-pred #f unbound rand* Lt Lf ac)] + [($forward-ptr?) (type-pred #f -1 rand* Lt Lf ac)] + [(not) (type-pred #f bool-f rand* Lt Lf ac)] + [(eof-object?) (type-pred #f eof rand* Lt Lf ac)] + [(bwp-object?) (type-pred #f bwp-object rand* Lt Lf ac)] + [($fxzero?) (type-pred #f 0 rand* Lt Lf ac)] + [($fx= $char= eq?) (compare-and-branch 'je rand* Lt Lf ac)] + [($fx< $char<) (compare-and-branch 'jl rand* Lt Lf ac)] + [($fx<= $char<=) (compare-and-branch 'jle rand* Lt Lf ac)] + [($fx> $char>) (compare-and-branch 'jg rand* Lt Lf ac)] + [($fx>= $char>=) (compare-and-branch 'jge rand* Lt Lf ac)] + [(vector?) + (indirect-type-pred vector-mask vector-tag fx-mask fx-tag + rand* Lt Lf ac)] + [($record?) + (indirect-type-pred record-pmask record-ptag record-pmask record-ptag + rand* Lt Lf ac)] + [($record/rtd?) + (cond + [Lf + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int vector-mask) eax) + (cmpl (int vector-tag) eax) + (jne Lf) + (movl (Simple (cadr rand*)) eax) + (cmpl (mem (fx- disp-record-rtd vector-tag) ebx) eax) + (jne Lf) + (if Lt + (cons (jmp Lt) ac) + ac))] + [Lt + (let ([Ljoin (unique-label)]) + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int vector-mask) eax) + (cmpl (int vector-tag) eax) + (jne Ljoin) + (movl (Simple (cadr rand*)) eax) + (cmpl (mem (fx- disp-record-rtd vector-tag) ebx) eax) + (je Lt) + (label Ljoin) + ac))] + [else ac])] + [(code?) + (indirect-type-pred vector-mask vector-tag #f code-tag + rand* Lt Lf ac)] + [(immediate?) + (cond + [(and Lt Lf) + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int fx-mask) ebx) + (cmpl (int 0) ebx) + (je Lt) + (andl (int 7) eax) + (cmpl (int 7) eax) + (je Lt) + (jmp Lf) + ac)] + [Lt + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int fx-mask) ebx) + (cmpl (int 0) ebx) + (je Lt) + (andl (int 7) eax) + (cmpl (int 7) eax) + (je Lt) + ac)] + [Lf + (let ([Ljoin (unique-label)]) + (list* + (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int fx-mask) ebx) + (cmpl (int 0) ebx) + (je Ljoin) + (andl (int 7) eax) + (cmpl (int 7) eax) + (jne Lf) + Ljoin + ac))] + [else ac])] + [($ap-check-words) + (record-case (car rand*) + [(constant i) + (list* (movl (pcb-ref 'allocation-redline) eax) + (subl (Simple (cadr rand*)) eax) + (subl (int i) eax) + (cmpl eax apr) + (cond-branch 'jge Lt Lf ac))] + [else (error who "ap-check-words")])] + [($ap-check-bytes) + (record-case (car rand*) + [(constant i) + (list* (movl (Simple (cadr rand*)) eax) + (negl eax) + (addl (pcb-ref 'allocation-redline) eax) + (subl (int i) eax) + (cmpl eax apr) + (cond-branch 'jge Lt Lf ac))] + [else (error who "ap-check-bytes")])] + [($ap-check-const) + (record-case (car rand*) + [(constant i) + (if (fx< i pagesize) + (list* + (cmpl (pcb-ref 'allocation-redline) apr) + (cond-branch 'jge Lt Lf ac)) + (list* + (movl (pcb-ref 'allocation-redline) eax) + (subl (int i) eax) + (cmpl eax apr) + (cond-branch 'jge Lt Lf ac)))] + [else (error who "ap-check-const")])] + [($fp-at-base) + (list* + (movl (pcb-ref 'frame-base) eax) + (subl (int wordsize) eax) + (cmpl eax fpr) + (cond-branch 'je Lt Lf ac))] + [($fp-overflow) + (list* (cmpl (pcb-ref 'frame-redline) fpr) + (cond-branch 'jle Lt Lf ac))] + [($vector-ref) + (do-value-prim op rand* + (do-simple-test eax Lt Lf ac))] + [(cons void $fxadd1 $fxsub1) + ;;; always true + (do-effect-prim op rand* + (cond + [(not Lt) ac] + [else (cons (jmp Lt) ac)]))] + [else + (error 'pred-prim "HERE unhandled ~s" op)])) + (define (do-pred->value-prim op rand* ac) + (case op + [else + (let ([Lf (unique-label)] [Lj (unique-label)]) + (do-pred-prim op rand* #f Lf + (list* (movl (constant-val #t) eax) + (jmp Lj) + Lf + (movl (constant-val #f) eax) + Lj + ac)))])) + (define (indirect-ref arg* off ac) + (list* + (movl (Simple (car arg*)) eax) + (movl (mem off eax) eax) + ac)) + (define (do-value-prim op arg* ac) + (case op + [(eof-object) (cons (movl (int eof) eax) ac)] + [(void) (cons (movl (int void-object) eax) ac)] + [($fxadd1) + (list* (movl (Simple (car arg*)) eax) + (addl (constant-val 1) eax) + ac)] + [($fxsub1) + (list* (movl (Simple (car arg*)) eax) + (addl (constant-val -1) eax) + ac)] + [($fx+) + (list* (movl (Simple (car arg*)) eax) + (addl (Simple (cadr arg*)) eax) + ac)] + [($fx-) + (list* (movl (Simple (car arg*)) eax) + (subl (Simple (cadr arg*)) eax) + ac)] + [($fx*) + (cond + [(constant? (car arg*)) + (record-case (car arg*) + [(constant c) + (unless (fixnum? c) + (error who "invalid arg ~s to fx*" c)) + (list* (movl (Simple (cadr arg*)) eax) + (imull (int c) eax) + ac)])] + [(constant? (cadr arg*)) + (record-case (cadr arg*) + [(constant c) + (unless (fixnum? c) + (error who "invalid arg ~s to fx*" c)) + (list* (movl (Simple (car arg*)) eax) + (imull (int c) eax) + ac)])] + [else + (list* (movl (Simple (car arg*)) eax) + (sarl (int fx-shift) eax) + (imull (Simple (cadr arg*)) eax) + ac)])] + [($fxquotient) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ecx) + (cltd) + (idivl ecx) + (sall (int fx-shift) eax) + ac)] + [($fxmodulo) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl eax ecx) + (xorl ebx ecx) + (sarl (int (fxsub1 (fx* wordsize 8))) ecx) + (andl ebx ecx) + (cltd) + (idivl ebx) + (movl edx eax) + (addl ecx eax) + ac)] + [($fxlogor) + (list* (movl (Simple (car arg*)) eax) + (orl (Simple (cadr arg*)) eax) + ac)] + [($fxlogand) + (list* (movl (Simple (car arg*)) eax) + (andl (Simple (cadr arg*)) eax) + ac)] + [($fxlogxor) + (list* (movl (Simple (car arg*)) eax) + (xorl (Simple (cadr arg*)) eax) + ac)] + [($fxsra) + (record-case (cadr arg*) + [(constant i) + (unless (fixnum? i) (error who "invalid arg to fxsra")) + (list* (movl (Simple (car arg*)) eax) + (sarl (int (fx+ i fx-shift)) eax) + (sall (int fx-shift) eax) + ac)] + [else + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ecx) + (sarl (int fx-shift) ecx) + (sarl (int fx-shift) eax) + (sarl cl eax) + (sall (int fx-shift) eax) + ac)])] + [($fxsll) + (record-case (cadr arg*) + [(constant i) + (unless (fixnum? i) (error who "invalid arg to fxsll")) + (list* (movl (Simple (car arg*)) eax) + (sall (int i) eax) + ac)] + [else + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ecx) + (sarl (int fx-shift) ecx) + (sall cl eax) + ac)])] + [($fixnum->char) + (list* (movl (Simple (car arg*)) eax) + (sall (int (fx- char-shift fx-shift)) eax) + (orl (int char-tag) eax) + ac)] + [($char->fixnum) + (list* (movl (Simple (car arg*)) eax) + (sarl (int (fx- char-shift fx-shift)) eax) + ac)] + [($fxlognot) + (list* (movl (Simple (car arg*)) eax) + (orl (int fx-mask) eax) + (notl eax) + ac)] + [($car) (indirect-ref arg* (fx- disp-car pair-tag) ac)] + [($cdr) (indirect-ref arg* (fx- disp-cdr pair-tag) ac)] + [($vector-length) + (indirect-ref arg* (fx- disp-vector-length vector-tag) ac)] + [($string-length) + (indirect-ref arg* (fx- disp-string-length string-tag) ac)] + [($symbol-string) + (indirect-ref arg* (fx- disp-symbol-string symbol-tag) ac)] + [($symbol-unique-string) + (indirect-ref arg* (fx- disp-symbol-unique-string symbol-tag) ac)] + [($symbol-value) + (indirect-ref arg* (fx- disp-symbol-value symbol-tag) ac)] + [(primitive-ref) + (indirect-ref arg* (fx- disp-symbol-system-value symbol-tag) ac)] + [($tcbucket-key) + (indirect-ref arg* (fx- disp-tcbucket-key vector-tag) ac)] + [($tcbucket-val) + (indirect-ref arg* (fx- disp-tcbucket-val vector-tag) ac)] + [($tcbucket-next) + (indirect-ref arg* (fx- disp-tcbucket-next vector-tag) ac)] + [(pointer-value) + (list* + (movl (Simple (car arg*)) eax) + (sarl (int fx-shift) eax) + (sall (int fx-shift) eax) + ac)] + [($symbol-plist) + (indirect-ref arg* (fx- disp-symbol-plist symbol-tag) ac)] + [($record-rtd) + (indirect-ref arg* (fx- disp-record-rtd record-ptag) ac)] + [($constant-ref) + (list* (movl (Simple (car arg*)) eax) ac)] + [($vector-ref) + (list* (movl (Simple (car arg*)) ebx) + (addl (Simple (cadr arg*)) ebx) + (movl (mem (fx- disp-vector-data vector-tag) ebx) eax) + ac)] + [($record-ref) + (list* (movl (Simple (car arg*)) ebx) + (addl (Simple (cadr arg*)) ebx) + (movl (mem (fx- disp-record-data record-ptag) ebx) eax) + ac)] + [($string-ref) + (list* (movl (Simple (cadr arg*)) ebx) + (sarl (int fx-shift) ebx) + (addl (Simple (car arg*)) ebx) + (movl (int char-tag) eax) + (movb (mem (fx- disp-string-data string-tag) ebx) ah) + ac)] + [($make-string) + (list* (movl (Simple (car arg*)) ebx) + (movl ebx (mem disp-string-length apr)) + (movl apr eax) + (addl (int string-tag) eax) + (sarl (int fx-shift) ebx) + (addl ebx apr) + (movb (int 0) (mem disp-string-data apr)) + (addl (int (fx+ disp-string-data object-alignment)) apr) + (sarl (int align-shift) apr) + (sall (int align-shift) apr) + ac)] + [($make-vector) + (list* (movl (Simple (car arg*)) ebx) + (movl ebx (mem disp-vector-length apr)) + (movl apr eax) + (addl (int vector-tag) eax) + (addl ebx apr) + (addl (int (fx+ disp-vector-data (fxsub1 object-alignment))) apr) + (sarl (int align-shift) apr) + (sall (int align-shift) apr) + ac)] + [($make-record) + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem disp-record-rtd apr)) + (movl apr eax) + (addl (int record-ptag) eax) + (addl (Simple (cadr arg*)) apr) + (addl (int (fx+ disp-record-data (fxsub1 object-alignment))) apr) + (sarl (int align-shift) apr) + (sall (int align-shift) apr) + ac)] + [(cons) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl eax (mem disp-car apr)) + (movl apr eax) + (movl ebx (mem disp-cdr apr)) + (addl (int pair-tag) eax) + (addl (int (align pair-size)) apr) + ac)] + [($make-symbol) + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem disp-symbol-string apr)) + (movl (int 0) (mem disp-symbol-unique-string apr)) + (movl (int unbound) (mem disp-symbol-value apr)) + (movl (int nil) (mem disp-symbol-plist apr)) + (movl (int unbound) (mem disp-symbol-system-value apr)) + (movl (int nil) (mem disp-symbol-system-plist apr)) + (movl apr eax) + (addl (int symbol-tag) eax) + (addl (int (align symbol-size)) apr) + ac)] + [($make-tcbucket) + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem disp-tcbucket-tconc apr)) + (movl (Simple (cadr arg*)) eax) + (movl eax (mem disp-tcbucket-key apr)) + (movl (Simple (caddr arg*)) eax) + (movl eax (mem disp-tcbucket-val apr)) + (movl (Simple (cadddr arg*)) eax) + (movl eax (mem disp-tcbucket-next apr)) + (movl apr eax) + (addl (int vector-tag) eax) + (addl (int (align tcbucket-size)) apr) + ac)] + [(vector) + (let f ([arg* arg*] [idx disp-vector-data]) + (cond + [(null? arg*) + (list* (movl apr eax) + (addl (int vector-tag) eax) + (movl (int (fx- idx disp-vector-data)) + (mem disp-vector-length apr)) + (addl (int (align idx)) apr) + ac)] + [else + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem idx apr)) + (f (cdr arg*) (fx+ idx wordsize)))]))] + [($string) + (let f ([arg* arg*] [idx disp-string-data]) + (cond + [(null? arg*) + (list* (movb (int 0) (mem idx apr)) + (movl apr eax) + (addl (int string-tag) eax) + (movl (int (fx* (fx- idx disp-string-data) wordsize)) + (mem disp-string-length apr)) + (addl (int (align (fxadd1 idx))) apr) + ac)] + [else + (record-case (car arg*) + [(constant c) + (unless (char? c) (error who "invalid arg to string ~s" x)) + (list* (movb (int (char->integer c)) (mem idx apr)) + (f (cdr arg*) (fxadd1 idx)))] + [else + (list* (movl (Simple (car arg*)) ebx) + (movb bh (mem idx apr)) + (f (cdr arg*) (fxadd1 idx)))])]))] + [($current-frame) + (list* (movl (pcb-ref 'next-continuation) eax) + ac)] + [($seal-frame-and-call) + (list* (movl (Simple (car arg*)) cpr) ; proc + (movl (pcb-ref 'frame-base) eax) + ; eax=baseofstack + (movl (mem (fx- 0 wordsize) eax) ebx) ; underflow handler + (movl ebx (mem (fx- 0 wordsize) fpr)) ; set + ; create a new cont record + (movl (int continuation-tag) (mem 0 apr)) + (movl fpr (mem disp-continuation-top apr)) + ; compute the size of the captured frame + (movl eax ebx) + (subl fpr ebx) + (subl (int wordsize) ebx) + ; and store it + (movl ebx (mem disp-continuation-size apr)) + ; load next cont + (movl (pcb-ref 'next-continuation) ebx) + ; and store it + (movl ebx (mem disp-continuation-next apr)) + ; adjust ap + (movl apr eax) + (addl (int vector-tag) eax) + (addl (int continuation-size) apr) + ; store new cont in current-cont + (movl eax (pcb-ref 'next-continuation)) + ; adjust fp + (movl fpr (pcb-ref 'frame-base)) + (subl (int wordsize) fpr) + ; tail-call f + (movl eax (mem (fx- 0 wordsize) fpr)) + (movl (int (argc-convention 1)) eax) + (tail-indirect-cpr-call) + ac)] + [($code-instr-size) + (indirect-ref arg* (fx- disp-code-instrsize vector-tag) + (cons (sall (int fx-shift) eax) ac))] + [($code-reloc-size) + (indirect-ref arg* (fx- disp-code-relocsize vector-tag) ac)] + [($code-closure-size) + (indirect-ref arg* (fx- disp-code-closuresize vector-tag) ac)] + [($set-car! $set-cdr! $vector-set! $string-set! $exit + $set-symbol-value! $set-symbol-plist! + $set-code-byte! $set-code-word! primitive-set! + $set-code-object! $set-code-object+offset! $set-code-object+offset/rel! + $record-set!) + (do-effect-prim op arg* + (cons (movl (int void-object) eax) ac))] + [(fixnum? immediate? $fxzero? boolean? char? pair? vector? string? symbol? + procedure? null? not eof-object? $fx= $fx< $fx<= $fx> $fx>= eq? + $char= $char< $char<= $char> $char>= $unbound-object? code? + $record? bwp-object?) + (do-pred->value-prim op arg* ac)] + [($code->closure) + (list* + (movl (Simple (car arg*)) eax) + (addl (int (fx- disp-code-data vector-tag)) eax) + (movl eax (mem 0 apr)) + (movl apr eax) + (addl (int closure-tag) eax) + (addl (int (align disp-closure-data)) apr) + ac)] + [($frame->continuation) + (NonTail + (make-closure (make-code-loc SL_continuation_code) arg*) + ac)] + [($make-call-with-values-procedure) + (NonTail + (make-closure (make-code-loc SL_call_with_values) arg*) + ac)] + [($make-values-procedure) + (NonTail + (make-closure (make-code-loc SL_values) arg*) + ac)] + [else + (error 'value-prim "unhandled ~s" op)])) + (define (indirect-assignment arg* offset ac) + (list* + (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem offset eax)) + ;;; record side effect + (addl (int offset) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)) + (define (do-effect-prim op arg* ac) + (case op + [($vector-set!) + (list* (movl (Simple (car arg*)) ebx) + (addl (Simple (cadr arg*)) ebx) + (addl (int (fx- disp-vector-data vector-tag)) ebx) + (movl (Simple (caddr arg*)) eax) + (movl eax (mem 0 ebx)) + ;;; record side effect + (shrl (int pageshift) ebx) + (sall (int wordshift) ebx) + (addl (pcb-ref 'dirty-vector) ebx) + (movl (int dirty-word) (mem 0 ebx)) + ac)] + [($string-set!) + (list* (movl (Simple (cadr arg*)) eax) + (sarl (int fx-shift) eax) + (addl (Simple (car arg*)) eax) + (movl (Simple (caddr arg*)) ebx) + (movb bh (mem (fx- disp-string-data string-tag) eax)) + ac)] + [($set-car!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-car pair-tag) eax)) + ;;; record side effect + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($set-cdr!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-cdr pair-tag) eax)) + ;;; record side effect + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($set-tcbucket-key!) + (indirect-assignment arg* (fx- disp-tcbucket-key vector-tag) ac)] + [($set-tcbucket-val!) + (indirect-assignment arg* (fx- disp-tcbucket-val vector-tag) ac)] + [($set-tcbucket-next!) + (indirect-assignment arg* (fx- disp-tcbucket-next vector-tag) ac)] + [($set-tcbucket-tconc!) + (indirect-assignment arg* (fx- disp-tcbucket-tconc vector-tag) ac)] + + [($set-symbol-value!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-symbol-value symbol-tag) eax)) + ;;; record side effect + (addl (int (fx- disp-symbol-value symbol-tag)) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [(primitive-set!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-symbol-system-value symbol-tag) eax)) + ;;; record side effect + (addl (int (fx- disp-symbol-system-value symbol-tag)) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($set-symbol-plist!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-symbol-plist symbol-tag) eax)) + ;;; record side effect + (addl (int (fx- disp-symbol-plist symbol-tag)) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($set-symbol-unique-string!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-symbol-unique-string symbol-tag) eax)) + ;;; record side effect + (addl (int (fx- disp-symbol-unique-string symbol-tag)) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($set-symbol-string!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-symbol-string symbol-tag) eax)) + ;;; record side effect + (addl (int (fx- disp-symbol-string symbol-tag)) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($record-set!) + (list* (movl (Simple (car arg*)) ebx) + (addl (Simple (cadr arg*)) ebx) + (movl (Simple (caddr arg*)) eax) + (addl (int (fx- disp-record-data record-ptag)) ebx) + (movl eax (mem 0 ebx)) + ;;; record side effect + (shrl (int pageshift) ebx) + (sall (int wordshift) ebx) + (addl (pcb-ref 'dirty-vector) ebx) + (movl (int dirty-word) (mem 0 ebx)) + ac)] + [(cons void $fxadd1 $fxsub1) + (let f ([arg* arg*]) + (cond + [(null? arg*) ac] + [else + (Effect (car arg*) (f (cdr arg*)))]))] + [else + (error 'do-effect-prim "unhandled op ~s" op)])) + (define (do-simple-test x Lt Lf ac) + (unless (or Lt Lf) + (error 'Pred "no labels")) + (cond + [(not Lt) + (list* (cmpl (int bool-f) x) (je Lf) ac)] + [(not Lf) + (list* (cmpl (int bool-f) x) (jne Lt) ac)] + [else + (list* (cmpl (int bool-f) x) (je Lf) (jmp Lt) ac)])) + (define (Simple x) + (record-case x + [(cp-var i) + (mem (fx+ (fx* i wordsize) (fx- disp-closure-data closure-tag)) cpr)] + [(frame-var i) (mem (fx* i (fx- 0 wordsize)) fpr)] + [(constant c) (constant-val c)] + [(code-loc label) (label-address label)] + [(primref op) (primref-loc op)] + [else (error 'Simple "what ~s" x)])) + (define (closure-size x) + (align (fx+ disp-closure-data + (fx* wordsize (length (closure-free* x)))))) + (define (assign-codes rhs* n* i ac) + (cond + [(null? rhs*) ac] + [else + (record-case (car rhs*) + [(closure label free*) + (cons (movl (Simple label) (mem i apr)) + (assign-codes + (cdr rhs*) (cdr n*) (fx+ i (car n*)) ac))])])) + (define (whack-free x i n* rhs* ac) + (cond + [(null? rhs*) ac] + [else + (let ([free (closure-free* (car rhs*))]) + (let f ([free free] [j (fx+ i disp-closure-data)]) + (cond + [(null? free) + (whack-free x (fx+ i (car n*)) (cdr n*) (cdr rhs*) ac)] + [(eq? (car free) x) + (cons + (movl eax (mem j apr)) + (f (cdr free) (fx+ j wordsize)))] + [else (f (cdr free) (fx+ j wordsize))])))])) + (define (assign-nonrec-free* rhs* all-rhs* n* seen ac) + (cond + [(null? rhs*) ac] + [else + (let f ([ls (closure-free* (car rhs*))] [seen seen]) + (cond + [(null? ls) + (assign-nonrec-free* (cdr rhs*) all-rhs* n* seen ac)] + [(memq (car ls) seen) (f (cdr ls) seen)] + [else + (cons + (movl (Simple (car ls)) eax) + (whack-free (car ls) 0 n* all-rhs* + (f (cdr ls) (cons (car ls) seen))))]))])) + (define (assign-rec-free* lhs* rhs* all-n* ac) + (list* (movl apr eax) + (addl (int closure-tag) eax) + (let f ([lhs* lhs*] [n* all-n*]) + (cond + [(null? (cdr lhs*)) + (cons + (movl eax (Simple (car lhs*))) + (whack-free (car lhs*) 0 all-n* rhs* ac))] + [else + (cons + (movl eax (Simple (car lhs*))) + (whack-free (car lhs*) 0 all-n* rhs* + (cons + (addl (int (car n*)) eax) + (f (cdr lhs*) (cdr n*)))))])))) + (define (sum ac ls) + (cond + [(null? ls) ac] + [else (sum (fx+ ac (car ls)) (cdr ls))])) + (define (do-fix lhs* rhs* ac) + ;;; 1. first, set the code pointers in the right places + ;;; 2. next, for every variable appearing in the rhs* but is not in + ;;; the lhs*, load it once and set it everywhere it occurs. + ;;; 3. next, compute the values of the lhs*, and for every computed + ;;; value, store it on the stack, and set it everywhere it occurs + ;;; in the rhs* + ;;; 4. that's it. + (let* ([n* (map closure-size rhs*)]) + (assign-codes rhs* n* 0 + (assign-nonrec-free* rhs* rhs* n* lhs* + (assign-rec-free* lhs* rhs* n* + (cons (addl (int (sum 0 n*)) apr) ac)))))) + (define (frame-adjustment offset) + (fx* (fxsub1 offset) (fx- 0 wordsize))) + (define (NonTail x ac) + (record-case x + [(constant c) + (cons (movl (constant-val c) eax) ac)] + [(frame-var) + (cons (movl (Simple x) eax) ac)] + [(cp-var) + (cons (movl (Simple x) eax) ac)] + [(foreign-label L) + (cons (movl (list 'foreign-label L) eax) ac)] + [(primref c) + (cons (movl (primref-loc c) eax) ac)] + [(closure label arg*) + (let f ([arg* arg*] [off disp-closure-data]) + (cond + [(null? arg*) + (list* (movl (Simple label) (mem 0 apr)) + (movl apr eax) + (addl (int (align off)) apr) + (addl (int closure-tag) eax) + ac)] + [else + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem off apr)) + (f (cdr arg*) (fx+ off wordsize)))]))] + [(conditional test conseq altern) + (let ([Lj (unique-label)] [Lf (unique-label)]) + (Pred test #f Lf + (NonTail conseq + (list* (jmp Lj) Lf (NonTail altern (cons Lj ac))))))] + [(seq e0 e1) + (Effect e0 (NonTail e1 ac))] + [(fix lhs* rhs* body) + (do-fix lhs* rhs* (NonTail body ac))] + [(primcall op rand*) + (do-value-prim op rand* ac)] + [(new-frame base-idx size body) + (NonTail body ac)] + [(call-cp call-convention rp-convention offset size mask) + (let ([L_CALL (unique-label)]) + (case call-convention + [(normal) + (list* (addl (int (frame-adjustment offset)) fpr) + (movl (int (argc-convention size)) eax) + (jmp L_CALL) + ; NEW FRAME + `(byte-vector ,mask) + `(int ,(fx* offset wordsize)) + `(current-frame-offset) + (rp-label rp-convention) + `(byte 0) ; padding for indirect calls only + `(byte 0) ; direct calls are ok + L_CALL + (indirect-cpr-call) + (movl (mem 0 fpr) cpr) + (subl (int (frame-adjustment offset)) fpr) + ac)] + [(foreign) + (list* (addl (int (frame-adjustment offset)) fpr) + (movl (int (argc-convention size)) eax) + (movl '(foreign-label "ik_foreign_call") ebx) + (jmp L_CALL) + ; NEW FRAME + (byte-vector mask) + `(int ,(fx* offset wordsize)) + `(current-frame-offset) + (rp-label rp-convention) ; should be 0, since C has 1 rv + '(byte 0) + '(byte 0) + '(byte 0) + L_CALL + (call ebx) + (movl (mem 0 fpr) cpr) + (subl (int (frame-adjustment offset)) fpr) + ac)] + [else + (error who "invalid convention ~s for call-cp" call-convention)]))] + [else (error 'NonTail "invalid expression ~s" x)])) + (define (Pred x Lt Lf ac) + (record-case x + [(frame-var i) + (do-simple-test (idx->frame-loc i) Lt Lf ac)] + [(cp-var i) + (do-simple-test (Simple x) Lt Lf ac)] + [(constant c) + (if c + (if Lt (cons (jmp Lt) ac) ac) + (if Lf (cons (jmp Lf) ac) ac))] + [(fix lhs* rhs* body) + (do-fix lhs* rhs* (Pred body Lt Lf ac))] + [(primcall op rand*) + (do-pred-prim op rand* Lt Lf ac)] + [(conditional test conseq altern) + (cond + [(not Lt) + (let ([Lj^ (unique-label)] [Lf^ (unique-label)]) + (Pred test #f Lf^ + (Pred conseq Lj^ Lf + (cons Lf^ + (Pred altern #f Lf + (cons Lj^ ac))))))] + [(not Lf) + (let ([Lj^ (unique-label)] [Lf^ (unique-label)]) + (Pred test #f Lf^ + (Pred conseq Lt Lj^ + (cons Lf^ + (Pred altern Lt #f + (cons Lj^ ac))))))] + [else + (let ([Lf^ (unique-label)]) + (Pred test #f Lf^ + (Pred conseq Lt Lf + (cons Lf^ + (Pred altern Lt Lf ac)))))])] + [(seq e0 e1) + (Effect e0 (Pred e1 Lt Lf ac))] + [(new-frame) + (NonTail x (do-simple-test eax Lt Lf ac))] + [else (error 'Pred "invalid expression ~s" x)])) + (define (idx->frame-loc i) + (mem (fx* i (fx- 0 wordsize)) fpr)) + (define (Effect x ac) + (record-case x + [(constant) ac] + [(primcall op rand*) + (do-effect-prim op rand* ac)] + [(conditional test conseq altern) + (let ([Lf (unique-label)] [Ljoin (unique-label)]) + (Pred test #f Lf + (Effect conseq + (list* (jmp Ljoin) Lf (Effect altern (cons Ljoin ac))))))] + [(seq e0 e1) + (Effect e0 (Effect e1 ac))] + [(fix lhs* rhs* body) + (do-fix lhs* rhs* (Effect body ac))] + [(assign loc val) + (record-case loc + [(frame-var i) + (NonTail val + (cons (movl eax (idx->frame-loc i)) ac))] + [else (error who "invalid assign loc ~s" loc)])] + [(eval-cp check body) + (NonTail body + (cond + [check + (list* + (movl eax cpr) + (andl (int closure-mask) eax) + (cmpl (int closure-tag) eax) + (jne (label SL_nonprocedure)) + ac)] + [else + (list* + (movl eax cpr) + ac)]))] + [(save-cp loc) + (record-case loc + [(frame-var i) + (cons (movl cpr (idx->frame-loc i)) ac)] + [else (error who "invalid cpr loc ~s" x)])] + [(new-frame) (NonTail x ac)] + [(frame-var) ac] + [else (error 'Effect "invalid expression ~s" x)])) + (define (Tail x ac) + (record-case x + [(return x) + (NonTail x (cons (ret) ac))] + [(conditional test conseq altern) + (let ([L (unique-label)]) + (Pred test #f L + (Tail conseq + (cons L (Tail altern ac)))))] + [(seq e0 e1) + (Effect e0 (Tail e1 ac))] + [(fix lhs* rhs* body) + (do-fix lhs* rhs* (Tail body ac))] + [(new-frame idx size body) + (Tail body ac)] + [(call-cp call-convention rp-convention idx argc mask) + (unless (eq? rp-convention 'tail) + (error who "nontail rp (~s) in tail context" rp-convention)) + (let f ([i 0]) + (cond + [(fx= i argc) + (case call-convention + [(normal) + (list* + (movl (int (argc-convention argc)) eax) + (tail-indirect-cpr-call) + ac)] + [(apply) + (list* + (movl (int (argc-convention argc)) eax) + (jmp (label SL_apply)) + ac)] + [else + (error who "invalid conv ~s in tail call-cpr" call-convention)])] + [else + (list* (movl (mem (fx* (fx+ idx (fxadd1 i)) + (fx- 0 wordsize)) fpr) + eax) + (movl eax (mem (fx* (fx+ i 1) (fx- 0 wordsize)) fpr)) + (f (fxadd1 i)))]))] + [else (error 'Tail "invalid expression ~s" x)])) + (define (handle-vararg fml-count ac) + (define CONTINUE_LABEL (unique-label)) + (define DONE_LABEL (unique-label)) + (define CONS_LABEL (unique-label)) + (define LOOP_HEAD (unique-label)) + (define L_CALL (unique-label)) + (list* (cmpl (int (argc-convention (fxsub1 fml-count))) eax) + (jg (label SL_invalid_args)) + (jl CONS_LABEL) + (movl (int nil) ebx) + (jmp DONE_LABEL) + CONS_LABEL + (movl (pcb-ref 'allocation-redline) ebx) + (addl eax ebx) + (addl eax ebx) + (cmpl ebx apr) + (jle LOOP_HEAD) + ; overflow + (addl eax esp) ; advance esp to cover args + (pushl cpr) ; push current cp + (pushl eax) ; push argc + (negl eax) ; make argc positive + (addl (int (fx* 4 wordsize)) eax) ; add 4 words to adjust frame size + (pushl eax) ; push frame size + (addl eax eax) ; double the number of args + (movl eax (mem (fx* -2 wordsize) fpr)) ; pass it as first arg + (movl (int (argc-convention 1)) eax) ; setup argc + (movl (primref-loc 'do-vararg-overflow) cpr) ; load handler + (jmp L_CALL) ; go to overflow handler + ; NEW FRAME + (int 0) ; if the framesize=0, then the framesize is dynamic + '(current-frame-offset) + (int 0) ; multiarg rp + (byte 0) + (byte 0) + L_CALL + (indirect-cpr-call) + (popl eax) ; pop framesize and drop it + (popl eax) ; reload argc + (popl cpr) ; reload cp + (subl eax fpr) ; readjust fp + LOOP_HEAD + (movl (int nil) ebx) + CONTINUE_LABEL + (movl ebx (mem disp-cdr apr)) + (movl (mem fpr eax) ebx) + (movl ebx (mem disp-car apr)) + (movl apr ebx) + (addl (int pair-tag) ebx) + (addl (int pair-size) apr) + (addl (int (fxsll 1 fx-shift)) eax) + (cmpl (int (fx- 0 (fxsll fml-count fx-shift))) eax) + (jle CONTINUE_LABEL) + DONE_LABEL + (movl ebx (mem (fx- 0 (fxsll fml-count fx-shift)) fpr)) + ac)) + (define (Entry check? x ac) + (record-case x + [(clambda-case fml* proper body) + (let ([ac (Tail body ac)]) + (cond + [(and proper check?) + (list* (cmpl (int (argc-convention (length fml*))) eax) + (jne (label SL_invalid_args)) + ac)] + [proper ac] + [else + (handle-vararg (length fml*) ac)]))])) + (define make-dispatcher + (lambda (j? L L* x x* ac) + (cond + [(null? L*) (if j? (cons (jmp (label L)) ac) ac)] + [else + (record-case x + [(clambda-case fml* proper _) + (cond + [proper + (list* (cmpl (int (argc-convention (length fml*))) eax) + (je (label L)) + (make-dispatcher #t + (car L*) (cdr L*) (car x*) (cdr x*) ac))] + [else + (list* (cmpl (int (argc-convention (fxsub1 (length fml*)))) eax) + (jle (label L)) + (make-dispatcher #t + (car L*) (cdr L*) (car x*) (cdr x*) ac))])])]))) + (define (handle-cases x x*) + (let ([L* (map (lambda (_) (gensym)) x*)] + [L (gensym)]) + (make-dispatcher #f L L* x x* + (let f ([x x] [x* x*] [L L] [L* L*]) + (cond + [(null? x*) + (cons (label L) (Entry 'check x '()))] + [else + (cons (label L) + (Entry #f x + (f (car x*) (cdr x*) (car L*) (cdr L*))))]))))) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (list* + (fx+ disp-closure-data (fx* wordsize (length free))) + (label L) + (handle-cases (car cases) (cdr cases)))])) + (record-case x + [(codes list body) + (cons (cons 0 (Tail body '())) + (map CodeExpr list))])) + + +(define SL_nonprocedure (gensym "SL_nonprocedure")) +(define SL_invalid_args (gensym "SL_invalid_args")) +(define SL_foreign_call (gensym "SL_foreign_call")) +(define SL_continuation_code (gensym "SL_continuation_code")) +(define SL_multiple_values_error_rp (gensym "SL_multiple_values_error_rp")) +(define SL_multiple_values_ignore_rp (gensym "SL_multiple_ignore_error_rp")) +(define SL_underflow_multiple_values (gensym "SL_underflow_multiple_values")) +(define SL_underflow_handler (gensym "SL_underflow_handler")) +(define SL_scheme_exit (gensym "SL_scheme_exit")) +(define SL_apply (gensym "SL_apply")) +(define SL_values (gensym "SL_values")) +(define SL_call_with_values (gensym "SL_call_with_values")) + +(module () +(list*->code* + (list + (let ([L_cwv_done (gensym)] + [L_cwv_loop (gensym)] + [L_cwv_multi_rp (gensym)] + [L_cwv_call (gensym)]) + (list disp-closure-data + (label SL_call_with_values) + (cmpl (int (argc-convention 2)) eax) + (jne (label SL_invalid_args)) + (movl (mem (fx- 0 wordsize) fpr) ebx) ; producer + (movl ebx cpr) + (andl (int closure-mask) ebx) + (cmpl (int closure-tag) ebx) + (jne (label SL_nonprocedure)) + (movl (int (argc-convention 0)) eax) + (subl (int (fx* wordsize 2)) fpr) + (jmp (label L_cwv_call)) + ; MV NEW FRAME + (byte-vector '#(#b110)) + (int (fx* wordsize 3)) + '(current-frame-offset) + (label-address L_cwv_multi_rp) + (byte 0) + (byte 0) + (label L_cwv_call) + (indirect-cpr-call) + ;;; one value returned + (addl (int (fx* wordsize 2)) fpr) + (movl (mem (fx* -2 wordsize) fpr) ebx) ; consumer + (movl ebx cpr) + (movl eax (mem (fx- 0 wordsize) fpr)) + (movl (int (argc-convention 1)) eax) + (andl (int closure-mask) ebx) + (cmpl (int closure-tag) ebx) + (jne (label SL_nonprocedure)) + (tail-indirect-cpr-call) + ;;; multiple values returned + (label L_cwv_multi_rp) + ; because values does not pop the return point + ; we have to adjust fp one more word here + (addl (int (fx* wordsize 3)) fpr) + (movl (mem (fx* -2 wordsize) fpr) cpr) ; consumer + (cmpl (int (argc-convention 0)) eax) + (je (label L_cwv_done)) + (movl (int (fx* -4 wordsize)) ebx) + (addl fpr ebx) ; ebx points to first value + (movl ebx ecx) + (addl eax ecx) ; ecx points to the last value + (label L_cwv_loop) + (movl (mem 0 ebx) edx) + (movl edx (mem (fx* 3 wordsize) ebx)) + (subl (int wordsize) ebx) + (cmpl ecx ebx) + (jge (label L_cwv_loop)) + (label L_cwv_done) + (movl cpr ebx) + (andl (int closure-mask) ebx) + (cmpl (int closure-tag) ebx) + (jne (label SL_nonprocedure)) + (tail-indirect-cpr-call))) + + (let ([L_values_one_value (gensym)] + [L_values_many_values (gensym)]) + (list disp-closure-data + (label SL_values) + (cmpl (int (argc-convention 1)) eax) + (je (label L_values_one_value)) + (label L_values_many_values) + (movl (mem 0 fpr) ebx) ; return point + (jmp (mem disp-multivalue-rp ebx)) ; go + (label L_values_one_value) + (movl (mem (fx- 0 wordsize) fpr) eax) + (ret))) + + (let ([L_apply_done (gensym)] + [L_apply_loop (gensym)]) + (list 0 + (label SL_apply) + (movl (mem fpr eax) ebx) + (cmpl (int nil) ebx) + (je (label L_apply_done)) + (label L_apply_loop) + (movl (mem (fx- disp-car pair-tag) ebx) ecx) + (movl (mem (fx- disp-cdr pair-tag) ebx) ebx) + (movl ecx (mem fpr eax)) + (subl (int wordsize) eax) + (cmpl (int nil) ebx) + (jne (label L_apply_loop)) + (label L_apply_done) + (addl (int wordsize) eax) + (tail-indirect-cpr-call))) + + (list 0 + (label SL_nonprocedure) + (movl cpr (mem (fx- 0 wordsize) fpr)) ; first arg + (movl (primref-loc '$apply-nonprocedure-error-handler) cpr) + (movl (int (argc-convention 1)) eax) + (tail-indirect-cpr-call)) + + (list 0 + (label SL_multiple_values_error_rp) + (movl (primref-loc '$multiple-values-error) cpr) + (tail-indirect-cpr-call)) + + (list 0 + (label SL_multiple_values_ignore_rp) + (ret)) + + (list 0 + (label SL_invalid_args) + ;;; + (movl cpr (mem (fx- 0 wordsize) fpr)) ; first arg + (negl eax) + (movl eax (mem (fx- 0 (fx* 2 wordsize)) fpr)) + (movl (primref-loc '$incorrect-args-error-handler) cpr) + (movl (int (argc-convention 2)) eax) + (tail-indirect-cpr-call)) + + (let ([Lset (gensym)] [Lloop (gensym)]) + (list 0 + (label SL_foreign_call) + (movl fpr (pcb-ref 'frame-pointer)) + (movl apr (pcb-ref 'allocation-pointer)) + (movl fpr ebx) + (movl (pcb-ref 'system-stack) esp) + (pushl pcr) + (cmpl (int 0) eax) + (je (label Lset)) + (label Lloop) + (movl (mem ebx eax) ecx) + (pushl ecx) + (addl (int 4) eax) + (cmpl (int 0) eax) + (jne (label Lloop)) + (label Lset) + ; FOREIGN NEW FRAME + (call cpr) + (movl (pcb-ref 'frame-pointer) fpr) + (movl (pcb-ref 'allocation-pointer) apr) + (ret))) + + (let ([L_cont_zero_args (gensym)] + [L_cont_mult_args (gensym)] + [L_cont_one_arg (gensym)] + [L_cont_mult_move_args (gensym)] + [L_cont_mult_copy_loop (gensym)]) + (list + (fx+ disp-closure-data wordsize) + (label SL_continuation_code) + (movl (mem (fx- disp-closure-data closure-tag) cpr) ebx) ; captured-k + (movl ebx (pcb-ref 'next-continuation)) ; set + (movl (pcb-ref 'frame-base) ebx) + (cmpl (int (argc-convention 1)) eax) + (jg (label L_cont_zero_args)) + (jl (label L_cont_mult_args)) + (label L_cont_one_arg) + (movl (mem (fx- 0 wordsize) fpr) eax) + (movl ebx fpr) + (subl (int wordsize) fpr) + (ret) + (label L_cont_zero_args) + (subl (int wordsize) ebx) + (movl ebx fpr) + (movl (mem 0 ebx) ebx) ; return point + (jmp (mem disp-multivalue-rp ebx)) ; go + (label L_cont_mult_args) + (subl (int wordsize) ebx) + (cmpl ebx fpr) + (jne (label L_cont_mult_move_args)) + (movl (mem 0 ebx) ebx) + (jmp (mem disp-multivalue-rp ebx)) + (label L_cont_mult_move_args) + ; move args from fpr to ebx + (movl (int 0) ecx) + (label L_cont_mult_copy_loop) + (subl (int wordsize) ecx) + (movl (mem fpr ecx) edx) + (movl edx (mem ebx ecx)) + (cmpl ecx eax) + (jne (label L_cont_mult_copy_loop)) + (movl ebx fpr) + (movl (mem 0 ebx) ebx) + (jmp (mem disp-multivalue-rp ebx)) + )) + ))) + + + +(define (compile-expr expr) + (let* ([p (recordize expr)] + [p (optimize-direct-calls p)] + [p (optimize-letrec p)] + [p (remove-letrec p)] + [p (remove-assignments p)] + [p (convert-closures p)] + [p (lift-codes p)] + [p (introduce-primcalls p)] + [p (simplify-operands p)] + [p (insert-stack-overflow-checks p)] + [p (insert-allocation-checks p)] + [p (remove-local-variables p)] + [ls* (generate-code p)] + [f (when (assembler-output) + (for-each + (lambda (ls) + (for-each (lambda (x) (printf " ~s\n" x)) ls)) + ls*))] + [code* (list*->code* ls*)]) + (car code*))) + +(define compile-file + (lambda (input-file output-file . rest) + (let ([ip (open-input-file input-file)] + [op (apply open-output-file output-file rest)]) + (let f () + (let ([x (read ip)]) + (unless (eof-object? x) + (fasl-write (compile-expr (expand x)) op) + (f)))) + (close-input-port ip) + (close-output-port op)))) + +(primitive-set! 'compile-file compile-file) +(primitive-set! 'assembler-output (make-parameter #f)) +) + diff --git a/src/libcompile-6.6.ss b/src/libcompile-6.6.ss new file mode 100644 index 0000000..6e2ba57 --- /dev/null +++ b/src/libcompile-6.6.ss @@ -0,0 +1,3446 @@ + + +;;; 6.2: * side-effects now modify the dirty-vector +;;; * added bwp-object? +;;; * added pointer-value +;;; * added tcbuckets +;;; 6.1: * added case-lambda, dropped lambda +;;; 6.0: * basic compiler + +(let () + +(define-syntax cond-expand + (lambda (x) + (syntax-case x () + [(_ test conseq altern) + (if (eval (syntax-object->datum #'test)) + #'conseq + #'altern)]))) + +(cond-expand (eq? "" "") + (include "record-case.chez.ss") + (include "record-case.ss")) + + +(include "set-operations.ss") + + +(define open-coded-primitives +;;; these primitives, when found in operator position with the correct +;;; number of arguments, will be open-coded by the generator. If an +;;; incorrect number of args is detected, or if they appear in non-operator +;;; position, then they cannot be open-coded, and the pcb-primitives table +;;; is consulted for a reference of the pcb slot containing the primitive. +;;; If it's not found there, an error is signalled. +;;; +;;; prim-name args + '([$constant-ref 1 value] + [$constant-set! 2 effect] + [$pcb-ref 1 value] + [$pcb-set! 2 effect] + ;;; type predicates + [fixnum? 1 pred] + [immediate? 1 pred] + [boolean? 1 pred] + [char? 1 pred] + [pair? 1 pred] + [symbol? 1 pred] + [vector? 1 pred] + [string? 1 pred] + [procedure? 1 pred] + [null? 1 pred] + [eof-object? 1 pred] + [bwp-object? 1 pred] + [$unbound-object? 1 pred] + [$forward-ptr? 1 pred] + [not 1 pred] + [pointer-value 1 value] + [eq? 2 pred] + ;;; fixnum primitives + [$fxadd1 1 value] + [$fxsub1 1 value] + [$fx+ 2 value] + [$fx- 2 value] + [$fx* 2 value] + [$fxsll 2 value] + [$fxsra 2 value] + [$fxlogand 2 value] + [$fxlogor 2 value] + [$fxlogxor 2 value] + [$fxlognot 1 value] + [$fxquotient 2 value] + [$fxmodulo 2 value] + ;;; fixnum predicates + [$fxzero? 1 pred] + [$fx= 2 pred] + [$fx< 2 pred] + [$fx<= 2 pred] + [$fx> 2 pred] + [$fx>= 2 pred] + ;;; character predicates + [$char= 2 pred] + [$char< 2 pred] + [$char<= 2 pred] + [$char> 2 pred] + [$char>= 2 pred] + ;;; character conversion + [$fixnum->char 1 value] + [$char->fixnum 1 value] + ;;; lists/pairs + [cons 2 value] + [$car 1 value] + [$cdr 1 value] + [$set-car! 2 effect] + [$set-cdr! 2 effect] + ;;; vectors + [$make-vector 1 value] + [vector any value] + [$vector-length 1 value] + [$vector-ref 2 value] + [$vector-set! 3 effect] + ;;; strings + [$make-string 1 value] + [$string any value] + [$string-length 1 value] + [$string-ref 2 value] + [$string-set! 3 effect] + ;;; symbols + [$make-symbol 1 value] + [$symbol-value 1 value] + [$symbol-string 1 value] + [$symbol-unique-string 1 value] + [$set-symbol-value! 2 effect] + [$set-symbol-string! 2 effect] + [$set-symbol-unique-string! 2 effect] + [$symbol-plist 1 value] + [$set-symbol-plist! 2 effect] + [primitive-ref 1 value] + [primitive-set! 2 effect] + ;;; tcbuckets + [$make-tcbucket 4 value] + [$tcbucket-key 1 value] + [$tcbucket-val 1 value] + [$tcbucket-next 1 value] + [$set-tcbucket-val! 2 effect] + [$set-tcbucket-next! 2 effect] + [$set-tcbucket-tconc! 2 effect] + ;;; misc + [eof-object 0 value] + [void 0 value] + [$exit 1 effect] + [$fp-at-base 0 pred] + [$current-frame 0 value] + [$seal-frame-and-call 1 tail] + [$frame->continuation 1 value] + ;;; + ;;; records + ;;; + [$make-record 2 value] + [$record? 1 pred] + [$record/rtd? 2 pred] + [$record-rtd 1 value] + [$record-ref 2 value] + [$record-set! 3 effect] + ;;; + ;;; asm + ;;; + [$code? 1 pred] + [$code-size 1 value] + [$code-reloc-vector 1 value] + [$code-closure-size 1 value] + [$code-ref 2 value] + [$code-set! 3 value] + [$code->closure 1 value] + ;;; + [$make-call-with-values-procedure 0 value] + [$make-values-procedure 0 value] + [$install-underflow-handler 0 effect] + )) + +(define (primitive-context x) + (cond + [(assq x open-coded-primitives) => caddr] + [else (error 'primitive-context "unknown prim ~s" x)])) + + +;;; primitives table section +(define primitives-table + '(;;; system locations used by the C/Scheme interface + [$apply-nonprocedure-error-handler library] + [$incorrect-args-error-handler library] + [$multiple-values-error library] + [$intern library] + [do-overflow library] + [do-vararg-overflow library] + [do-stack-overflow library] + ;;; type predicates + [fixnum? public] + [immediate? public] + [boolean? public] + [char? public] + [null? public] + [pair? public] + [symbol? public] + [vector? public] + [string? public] + [procedure? public] + [eof-object? public] + [not public] + [eq? public] + [equal? public] + ;;; fixnum primitives + [fxadd1 public] + [fxsub1 public] + [fx+ public] + [fx- public] + [fx* public] + [fxsll public] + [fxsra public] + [fxlogor public] + [fxlogand public] + [fxlogxor public] + [fxlognot public] + [fxquotient public] + [fxremainder public] + [fxmodulo public] + ;;; fixnum predicates + [fxzero? public] + [fx= public] + [fx< public] + [fx<= public] + [fx> public] + [fx>= public] + ;;; characters + [char=? public] + [char? public] + [char>=? public] + [integer->char public] + [char->integer public] + ;;; lists + [cons public] + [car public] + [cdr public] + [caar public] + [cadr public] + [cdar public] + [cddr public] + [caaar public] + [caadr public] + [cadar public] + [caddr public] + [cdaar public] + [cdadr public] + [cddar public] + [cdddr public] + [caaaar public] + [caaadr public] + [caadar public] + [caaddr public] + [cadaar public] + [cadadr public] + [caddar public] + [cadddr public] + [cdaaar public] + [cdaadr public] + [cdadar public] + [cdaddr public] + [cddaar public] + [cddadr public] + [cdddar public] + [cddddr public] + [set-car! public] + [set-cdr! public] + [list public] + [list* ADDME] + [list? public] + [list-ref public] + [length public] + [make-list public] + [reverse public] + [append public] + [list-ref public] + [memq public] + [memv public] + [assq public] + [map public] + [for-each public] + [andmap public] + [ormap public] + ;;; vectors + [make-vector public] + [vector public] + [vector-length public] + [vector-ref public] + [vector-set! public] + [list->vector public] + [vector->list public] + ;;; strings + [make-string public] + [string public] + [string-length public] + [string-ref public] + [string-set! public] + [list->string public] + [string->list public] + [string-append public] + [substring public] + [string=? public] + [fixnum->string public] + ;;; symbols + [gensym public] + [gensym? public] + [symbol->string public] + [gensym->unique-string public] + [gensym-prefix public] + [gensym-count public] + [print-gensym public] + [string->symbol public] + [top-level-value public] + [top-level-bound? public] + [set-top-level-value! public] + [primitive-set! public] + [getprop public] + [putprop public] + [remprop public] + [property-list public] + [oblist public] + [uuid public] + ;;; eof + [eof-object public] + [void public] + ;;; control/debugging + [print-error public] + [error public] + [current-error-handler public] + [exit public] + [apply public] + [make-parameter public] + ;;; output + [output-port? public] + [console-output-port public] + [current-output-port public] + [standard-output-port public] + [standard-error-port public] + [open-output-file public] + [open-output-string public] + [with-output-to-file public] + [call-with-output-file public] + [with-input-from-file public] + [call-with-input-file public] + [get-output-string public] + [close-output-port public] + [flush-output-port public] + [write-char public] + [output-port-name public] + [newline public] + ;;; input + [input-port? public] + [standard-input-port public] + [console-input-port public] + [current-input-port public] + [open-input-file public] + [close-input-port public] + [reset-input-port! public] + [read-char public] + [peek-char public] + [unread-char public] + [input-port-name public] + ;;; writing/printing + [write public] + [display public] + [printf public] + [fprintf public] + [format public] + [read-token public] + [read public] + ;;; evaluation + [primitive? public] + [expand public] + [syntax-error public] + [current-expand public] + [expand-mode public] + [assembler-output public] + [compile-file public] + [fasl-write public] + + [$sc-put-cte public] + [sc-expand public] + [$make-environment public] + [environment? public] + [interaction-environment public] + [identifier? public] + [syntax->list public] + [syntax-object->datum public] + [datum->syntax-object public] + [generate-temporaries public] + [free-identifier=? public] + [bound-identifier=? public] + [literal-identifier=? public] + [syntax-error public] + [$syntax-dispatch public] + + + + [interpret public] + [compile public] + [eval public] + [current-eval public] + [load public] + [new-cafe public] + [collect public] + [call/cc public] + [call/cf library] + [dynamic-wind public] + [values public] + [call-with-values public] + [make-traced-procedure library] + [trace-symbol! library] + [untrace-symbol! library] + ;;; record + [$base-rtd library] + [record? public] + [record-rtd public] + [record-name public] + [record-printer public] + [record-length public] + [record-ref public] + [record-set! public] + ;;; record rtds + [make-record-type public] + [record-type-name public] + [record-type-descriptor public] + [record-type-symbol public] + [record-type-field-names public] + [record-constructor public] + [record-predicate public] + [record-field-accessor public] + [record-field-mutator public] + ;;; hash tables + [make-hash-table public] + [hash-table? public] + [get-hash-table public] + [put-hash-table! public] + ;;; asm + [make-code public] + [code? public] + [code-size public] + [code-closure-size public] + [code-ref public] + [code-set! public] + [code-reloc-vector public] + [set-code-reloc-vector! public] + [code->closure public] + [list*->code* library] + ;;; + ;;; POSIX + ;;; + [fork public] + [posix-fork public] + [system public] + [$debug public] + [$underflow-misaligned-error public] + )) + + +(define (primitive? x) + (cond + [(assq x primitives-table) #t] + [(assq x open-coded-primitives) #t] + [else #f])) + +(define (open-codeable? x) + (cond + [(assq x open-coded-primitives) #t] + [(assq x primitives-table) #f] + [else (error 'open-codeable "invalid primitive ~s" x)])) + +(define (open-coded-primitive-args x) + (cond + [(assq x open-coded-primitives) => cadr] + [else (error 'open-coded-primitive-args "invalid ~s" x)])) + +;;; end of primitives table section + + +(define-record constant (value)) +(define-record code-loc (label)) +(define-record foreign-label (label)) +(define-record var (name assigned)) +(define-record cp-var (idx)) +(define-record frame-var (idx)) +(define-record new-frame (base-idx size body)) +(define-record save-cp (loc)) +(define-record eval-cp (check body)) +(define-record return (value)) +(define-record call-cp + (call-convention rp-convention base-idx arg-count live-mask)) +(define-record primcall (op arg*)) +(define-record primref (name)) +(define-record conditional (test conseq altern)) +(define-record bind (lhs* rhs* body)) +(define-record recbind (lhs* rhs* body)) +(define-record fix (lhs* rhs* body)) + +(define-record seq (e0 e1)) +(define-record clambda-case (arg* proper body)) +(define-record clambda (cases)) +(define-record clambda-code (label cases free)) + +(define-record closure (code free*)) +(define-record funcall (op rand*)) +(define-record appcall (op rand*)) +(define-record forcall (op rand*)) +(define-record code-rec (arg* proper free* body)) + +(define-record codes (list body)) +(define-record assign (lhs rhs)) + +(define unique-var + (let ([counter 0]) + (lambda (x) + (let ([g (gensym (format "~a:~a" x counter))]) + (set! counter (fxadd1 counter)) + (make-var g #f))))) + +(define (make-bind^ lhs* rhs* body) + (if (null? lhs*) + body + (make-bind lhs* rhs* body))) + +(define (recordize x) + (define (gen-fml* fml*) + (cond + [(pair? fml*) + (cons (unique-var (car fml*)) + (gen-fml* (cdr fml*)))] + [(symbol? fml*) + (unique-var fml*)] + [else '()])) + (define (properize fml*) + (cond + [(pair? fml*) + (cons (car fml*) (properize (cdr fml*)))] + [(null? fml*) '()] + [else (list fml*)])) + (define (extend-env fml* nfml* env) + (cons (cons fml* nfml*) env)) + (define (quoted-sym x) + (if (and (list? x) + (fx= (length x) 2) + (eq? 'quote (car x)) + (symbol? (cadr x))) + (cadr x) + (error 'quoted-sym "not a quoted symbol ~s" x))) + (define (quoted-string x) + (if (and (list? x) + (fx= (length x) 2) + (eq? 'quote (car x)) + (string? (cadr x))) + (cadr x) + (error 'quoted-string "not a quoted string ~s" x))) + (define (lookup^ x lhs* rhs*) + (cond + [(pair? lhs*) + (if (eq? x (car lhs*)) + (car rhs*) + (lookup^ x (cdr lhs*) (cdr rhs*)))] + [(eq? x lhs*) rhs*] + [else #f])) + (define (lookup x env) + (cond + [(pair? env) + (or (lookup^ x (caar env) (cdar env)) + (lookup x (cdr env)))] + [else #f])) + (define (E x env) + (cond + [(pair? x) + (case (car x) + [(quote) (make-constant (cadr x))] + [(if) + (make-conditional + (E (cadr x) env) + (E (caddr x) env) + (E (cadddr x) env))] + [(set!) + (let ([lhs (cadr x)] [rhs (caddr x)]) + (make-assign + (or (lookup lhs env) + (error 'recordize "invalid assignment ~s" x)) + (E rhs env)))] + [(begin) + (let f ([a (cadr x)] [d (cddr x)]) + (cond + [(null? d) (E a env)] + [else + (make-seq + (E a env) + (f (car d) (cdr d)))]))] + [(letrec) + (unless (fx= (length x) 3) (syntax-error x)) + (let ([bind* (cadr x)] [body (caddr x)]) + (let ([lhs* (map car bind*)] + [rhs* (map cadr bind*)]) + (let ([nlhs* (gen-fml* lhs*)]) + (let ([env (extend-env lhs* nlhs* env)]) + (make-recbind nlhs* + (map (lambda (rhs) (E rhs env)) rhs*) + (E body env))))))] + [(letrec) + (unless (fx= (length x) 3) (syntax-error x)) + (let ([bind* (cadr x)] [body (caddr x)]) + (let ([lhs* (map car bind*)] + [rhs* (map cadr bind*)] + [v* (map (lambda (x) '(void)) bind*)] + [t* (map (lambda (x) (gensym)) bind*)]) + (E `((case-lambda + [,lhs* + ((case-lambda + [,t* + (begin ,@(map (lambda (x v) `(set! ,x ,v)) lhs* t*) + ,body)]) + ,@rhs*)]) + ,@v*) + env)))] + [(case-lambda) + (let ([cls* + (map + (lambda (cls) + (let ([fml* (car cls)] [body (cadr cls)]) + (let ([nfml* (gen-fml* fml*)]) + (let ([body (E body (extend-env fml* nfml* env))]) + (make-clambda-case + (properize nfml*) + (list? fml*) + body))))) + (cdr x))]) + (make-clambda cls*))] + [(foreign-call) + (let ([name (quoted-string (cadr x))] [arg* (cddr x)]) + (make-forcall name + (map (lambda (x) (E x env)) arg*)))] + [(|#primitive|) + (let ([var (cadr x)]) + (if (primitive? var) + (make-primref var) + (error 'recordize "invalid primitive ~s" var)))] + [(top-level-value) + (let ([var (quoted-sym (cadr x))]) + (cond + [(primitive? var) (make-primref var)] + [else (error 'recordize "invalid top-level var ~s" var)]))] + [(memv) + (make-funcall + (make-primref 'memq) + (map (lambda (x) (E x env)) (cdr x)))] + [($apply) + (let ([proc (cadr x)] [arg* (cddr x)]) + (make-appcall + (E proc env) + (map (lambda (x) (E x env)) arg*)))] + [(void) + (make-constant (void))] + [else + (make-funcall + (E (car x) env) + (map (lambda (x) (E x env)) (cdr x)))])] + [(symbol? x) + (or (lookup x env) + (error 'recordize "invalid reference in ~s" x))] + [else (error 'recordize "invalid expression ~s" x)])) + (E x '())) + + +(define (unparse x) + (define (E-args proper x) + (if proper + (map E x) + (let f ([a (car x)] [d (cdr x)]) + (cond + [(null? d) (E a)] + [else (cons (E a) (f (car d) (cdr d)))])))) + (define (E x) + (record-case x + [(constant c) `(quote ,c)] + [(code-loc x) `(code-loc ,x)] + [(var x) (string->symbol (format "v:~a" x))] + [(primref x) x] + [(conditional test conseq altern) + `(if ,(E test) ,(E conseq) ,(E altern))] + [(primcall op arg*) `(,op . ,(map E arg*))] + [(bind lhs* rhs* body) + `(let ,(map (lambda (lhs rhs) (list (E lhs) (E rhs))) lhs* rhs*) + ,(E body))] + [(recbind lhs* rhs* body) + `(letrec ,(map (lambda (lhs rhs) (list (E lhs) (E rhs))) lhs* rhs*) + ,(E body))] + [(fix lhs* rhs* body) + `(fix ,(map (lambda (lhs rhs) (list (E lhs) (E rhs))) lhs* rhs*) + ,(E body))] + [(seq e0 e1) `(begin ,(E e0) ,(E e1))] + [(clambda-case args proper body) + `(clambda-case ,(E-args proper args) ,(E body))] + [(clambda cls*) + `(case-lambda . ,(map E cls*))] + [(clambda-code label clauses free) + `(code ,label . ,(map E clauses))] + [(closure code free*) + `(closure ,(E code) ,(map E free*))] + [(code-rec arg* proper free* body) + `(code-rec [arg: ,(E-args proper arg*)] + [free: ,(map E free*)] + ,(E body))] + [(codes list body) + `(codes ,(map E list) + ,(E body))] + [(funcall rator rand*) `(funcall ,(E rator) . ,(map E rand*))] + [(appcall rator rand*) `(appcall ,(E rator) . ,(map E rand*))] + [(forcall rator rand*) `(foreign-call ,rator . ,(map E rand*))] + [(assign lhs rhs) `(set! ,(E lhs) ,(E rhs))] + [(return x) `(return ,(E x))] + [(new-frame base-idx size body) + `(new-frame [base: ,base-idx] + [size: ,size] + ,(E body))] + [(frame-var idx) + (string->symbol (format "fv.~a" idx))] + [(cp-var idx) + (string->symbol (format "cp.~a" idx))] + [(save-cp expr) + `(save-cp ,(E expr))] + [(eval-cp check body) + `(eval-cp ,check ,(E body))] + [(call-cp call-convention rp-convention base-idx arg-count live-mask) + `(call-cp [conv: ,call-convention] + [rpconv: ,rp-convention] + [base-idx: ,base-idx] + [arg-count: ,arg-count] + [live-mask: ,live-mask])] + [(foreign-label x) `(foreign-label ,x)] + [else (error 'unparse "invalid record ~s" x)])) + (E x)) + +(define (optimize-direct-calls x) + (define who 'optimize-direct-calls) + (define (make-conses ls) + (cond + [(null? ls) (make-constant '())] + [else + (make-primcall 'cons + (list (car ls) (make-conses (cdr ls))))])) + (define (properize lhs* rhs*) + (cond + [(null? lhs*) (error who "improper improper")] + [(null? (cdr lhs*)) + (list (make-conses rhs*))] + [else (cons (car rhs*) (properize (cdr lhs*) (cdr rhs*)))])) + (define (inline-case cls rand*) + (record-case cls + [(clambda-case fml* proper body) + (if proper + (and (fx= (length fml*) (length rand*)) + (make-bind fml* rand* body)) + (and (fx<= (length fml*) (length rand*)) + (make-bind fml* (properize fml* rand*) body)))])) + (define (try-inline cls* rand* default) + (cond + [(null? cls*) default] + [(inline-case (car cls*) rand*)] + [else (try-inline (cdr cls*) rand* default)])) + (define (inline rator rand*) + (record-case rator + [(clambda cls*) + (try-inline cls* rand* + (make-funcall rator rand*))] + [else (make-funcall rator rand*)])) + (define (Expr x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Expr body))] + [(recbind lhs* rhs* body) + (make-recbind lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional + (Expr test) + (Expr conseq) + (Expr altern))] + [(seq e0 e1) + (make-seq (Expr e0) (Expr e1))] + [(clambda cls*) + (make-clambda + (map (lambda (x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (Expr body))])) + cls*))] + [(primcall rator rand*) + (make-primcall rator (map Expr rand*))] + [(funcall rator rand*) + (inline (Expr rator) (map Expr rand*))] + [(appcall rator rand*) + (make-appcall (Expr rator) (map Expr rand*))] + [(forcall rator rand*) + (make-forcall rator (map Expr rand*))] + [(assign lhs rhs) + (make-assign lhs (Expr rhs))] + [else (error who "invalid expression ~s" (unparse x))])) + (Expr x)) + + +(define (optimize-letrec x) + (define who 'optimize-letrec) + (define (extend-hash lhs* h ref) + (for-each (lambda (lhs) (put-hash-table! h lhs #t)) lhs*) + (lambda (x) + (unless (get-hash-table h x #f) + (put-hash-table! h x #t) + (ref x)))) + (define (E* x* ref comp) + (cond + [(null? x*) '()] + [else + (cons (E (car x*) ref comp) + (E* (cdr x*) ref comp))])) + (define (do-rhs* i lhs* rhs* ref comp vref vcomp) + (cond + [(null? rhs*) '()] + [else + (let ([h (make-hash-table)]) + (let ([ref + (lambda (x) + (unless (get-hash-table h x #f) + (put-hash-table! h x #t) + (ref x) + (when (memq x lhs*) + (vector-set! vref i #t))))] + [comp + (lambda () + (vector-set! vcomp i #t) + (comp))]) + (cons (E (car rhs*) ref comp) + (do-rhs* (fxadd1 i) lhs* (cdr rhs*) ref comp vref vcomp))))])) + (define (partition-rhs* i lhs* rhs* vref vcomp) + (cond + [(null? lhs*) (values '() '() '() '() '() '())] + [else + (let-values + ([(slhs* srhs* llhs* lrhs* clhs* crhs*) + (partition-rhs* (fxadd1 i) (cdr lhs*) (cdr rhs*) vref vcomp)] + [(lhs rhs) (values (car lhs*) (car rhs*))]) + (cond + [(var-assigned lhs) + (values slhs* srhs* llhs* lrhs* (cons lhs clhs*) (cons rhs crhs*))] + [(clambda? rhs) + (values slhs* srhs* (cons lhs llhs*) (cons rhs lrhs*) clhs* crhs*)] + [(or (vector-ref vref i) (vector-ref vcomp i)) + (values slhs* srhs* llhs* lrhs* (cons lhs clhs*) (cons rhs crhs*))] + [else + (values (cons lhs slhs*) (cons rhs srhs*) llhs* lrhs* clhs* crhs*)] + ))])) + (define (do-recbind lhs* rhs* body ref comp) + (let ([h (make-hash-table)] + [vref (make-vector (length lhs*) #f)] + [vcomp (make-vector (length lhs*) #f)]) + (let* ([ref (extend-hash lhs* h ref)] + [body (E body ref comp)]) + (let ([rhs* (do-rhs* 0 lhs* rhs* ref comp vref vcomp)]) + (let-values ([(slhs* srhs* llhs* lrhs* clhs* crhs*) + (partition-rhs* 0 lhs* rhs* vref vcomp)]) + (let ([v* (map (lambda (x) (make-primcall 'void '())) clhs*)] + [t* (map (lambda (x) (unique-var 'tmp)) clhs*)]) + (make-bind slhs* srhs* + (make-bind clhs* v* + (make-fix llhs* lrhs* + (make-bind t* crhs* + (build-assign* clhs* t* body))))))))))) + (define (build-assign* lhs* rhs* body) + (cond + [(null? lhs*) body] + [else + (make-seq + (make-assign (car lhs*) (car rhs*)) + (build-assign* (cdr lhs*) (cdr rhs*) body))])) + (define (E x ref comp) + (record-case x + [(constant) x] + [(var) (ref x) x] + [(assign lhs rhs) + (set-var-assigned! lhs #t) + (ref lhs) + (make-assign lhs (E rhs ref comp))] + [(primref) x] + [(bind lhs* rhs* body) + (let ([rhs* (E* rhs* ref comp)]) + (let ([h (make-hash-table)]) + (let ([body (E body (extend-hash lhs* h ref) comp)]) + (make-bind lhs* rhs* body))))] + [(recbind lhs* rhs* body) + (if (null? lhs*) + (E body ref comp) + (do-recbind lhs* rhs* body ref comp))] + [(conditional e0 e1 e2) + (make-conditional (E e0 ref comp) (E e1 ref comp) (E e2 ref comp))] + [(seq e0 e1) (make-seq (E e0 ref comp) (E e1 ref comp))] + [(clambda cls*) + (make-clambda + (map (lambda (x) + (record-case x + [(clambda-case fml* proper body) + (let ([h (make-hash-table)]) + (let ([body (E body (extend-hash fml* h ref) void)]) + (make-clambda-case fml* proper body)))])) + cls*))] + [(primcall rator rand*) + (when (memq rator '(call/cc call/cf)) + (comp)) + (make-primcall rator (E* rand* ref comp))] + [(funcall rator rand*) + (let ([rator (E rator ref comp)] [rand* (E* rand* ref comp)]) + (record-case rator + [(primref op) + (when (memq op '(call/cc call/cf)) + (comp))] + [else + (comp)]) + (make-funcall rator rand*))] + [(appcall rator rand*) + (let ([rator (E rator ref comp)] [rand* (E* rand* ref comp)]) + (record-case rator + [(primref op) + (when (memq op '(call/cc call/cf)) + (comp))] + [else + (comp)]) + (make-appcall rator rand*))] + [(forcall rator rand*) + (make-forcall rator (E* rand* ref comp))] + [else (error who "invalid expression ~s" (unparse x))])) + (E x (lambda (x) (error who "free var ~s found" x)) + void)) + + +(define (remove-letrec x) + (define who 'remove-letrec) + (define (Expr x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Expr body))] + [(recbind lhs* rhs* body) + (let ([t* (map (lambda (lhs) (unique-var 'tmp)) lhs*)] + [v* (map (lambda (lhs) (make-primcall 'void '())) lhs*)]) + (make-bind lhs* v* + (make-bind t* (map Expr rhs*) + (let f ([lhs* lhs*] [t* t*]) + (cond + [(null? lhs*) (Expr body)] + [else + (make-seq + (make-assign (car lhs*) (car t*)) + (f (cdr lhs*) (cdr t*)))])))))] + ;[(fix lhs* rhs* body) + ; (Expr (make-recbind lhs* rhs* body))] + [(fix lhs* rhs* body) + (make-fix lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional + (Expr test) + (Expr conseq) + (Expr altern))] + [(seq e0 e1) + (make-seq (Expr e0) (Expr e1))] + [(clambda cls*) + (make-clambda + (map (lambda (x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (Expr body))])) + cls*))] + [(primcall rator rand*) + (make-primcall rator (map Expr rand*))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall rator rand*) + (make-appcall (Expr rator) (map Expr rand*))] + [(forcall rator rand*) + (make-forcall rator (map Expr rand*))] + [(assign lhs rhs) + (make-assign lhs (Expr rhs))] + [else (error who "invalid expression ~s" (unparse x))])) + (Expr x)) + + + +(define (uncover-assigned x) + (define who 'uncover-assigned) + (define (Expr* x*) + (for-each Expr x*)) + (define (Expr x) + (record-case x + [(constant) (void)] + [(var) (void)] + [(primref) (void)] + [(bind lhs* rhs* body) + (begin (Expr body) (Expr* rhs*))] + [(recbind lhs* rhs* body) + (begin (Expr body) (Expr* rhs*))] + [(fix lhs* rhs* body) + (Expr* rhs*) + (Expr body) + (when (ormap var-assigned lhs*) + (error 'uncover-assigned "a fix lhs is assigned"))] + [(conditional test conseq altern) + (begin (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (begin (Expr e0) (Expr e1))] + [(clambda cls*) + (for-each + (lambda (cls) + (Expr (clambda-case-body cls))) + cls*)] + [(primcall rator rand*) (Expr* rand*)] + [(funcall rator rand*) + (begin (Expr rator) (Expr* rand*))] + [(appcall rator rand*) + (begin (Expr rator) (Expr* rand*))] + [(forcall rator rand*) (Expr* rand*)] + [(assign lhs rhs) + (set-var-assigned! lhs #t) + (Expr rhs)] + [else (error who "invalid expression ~s" (unparse x))])) + (Expr x)) + + + +(define (rewrite-assignments x) + (define who 'rewrite-assignments) + (define (fix-lhs* lhs*) + (cond + [(null? lhs*) (values '() '() '())] + [else + (let ([x (car lhs*)]) + (let-values ([(lhs* a-lhs* a-rhs*) (fix-lhs* (cdr lhs*))]) + (cond + [(var-assigned x) + (let ([t (unique-var 'assignment-tmp)]) + (values (cons t lhs*) (cons x a-lhs*) (cons t a-rhs*)))] + [else + (values (cons x lhs*) a-lhs* a-rhs*)])))])) + (define (bind-assigned lhs* rhs* body) + (cond + [(null? lhs*) body] + [else + (make-bind lhs* + (map (lambda (rhs) (make-primcall 'vector (list rhs))) rhs*) + body)])) + (define (Expr x) + (record-case x + [(constant) x] + [(var) + (cond + [(var-assigned x) + (make-primcall '$vector-ref (list x (make-constant 0)))] + [else x])] + [(primref) x] + [(bind lhs* rhs* body) + (let-values ([(lhs* a-lhs* a-rhs*) (fix-lhs* lhs*)]) + (make-bind lhs* (map Expr rhs*) + (bind-assigned a-lhs* a-rhs* (Expr body))))] + [(fix lhs* rhs* body) + (make-fix lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (make-seq (Expr e0) (Expr e1))] + [(clambda cls*) + (make-clambda + (map (lambda (cls) + (record-case cls + [(clambda-case fml* proper body) + (let-values ([(fml* a-lhs* a-rhs*) (fix-lhs* fml*)]) + (make-clambda-case fml* proper + (bind-assigned a-lhs* a-rhs* (Expr body))))])) + cls*))] + [(primcall op rand*) + (make-primcall op (map Expr rand*))] + [(forcall op rand*) + (make-forcall op (map Expr rand*))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall rator rand*) + (make-appcall (Expr rator) (map Expr rand*))] + [(assign lhs rhs) + (unless (var-assigned lhs) + (error 'rewrite-assignments "not assigned ~s in ~s" lhs x)) + (make-primcall '$vector-set! (list lhs (make-constant 0) (Expr rhs)))] + [else (error who "invalid expression ~s" (unparse x))])) + (Expr x)) + + +(define (remove-assignments x) + (uncover-assigned x) + (rewrite-assignments x)) + + + + +(define (convert-closures prog) + (define who 'convert-closures) + (define (Expr* x*) + (cond + [(null? x*) (values '() '())] + [else + (let-values ([(a a-free) (Expr (car x*))] + [(d d-free) (Expr* (cdr x*))]) + (values (cons a d) (union a-free d-free)))])) + (define (do-clambda* x*) + (cond + [(null? x*) (values '() '())] + [else + (let-values ([(a a-free) (do-clambda (car x*))] + [(d d-free) (do-clambda* (cdr x*))]) + (values (cons a d) (union a-free d-free)))])) + (define (do-clambda x) + (record-case x + [(clambda cls*) + (let-values ([(cls* free) + (let f ([cls* cls*]) + (cond + [(null? cls*) (values '() '())] + [else + (record-case (car cls*) + [(clambda-case fml* proper body) + (let-values ([(body body-free) (Expr body)] + [(cls* cls*-free) (f (cdr cls*))]) + (values + (cons (make-clambda-case fml* proper body) + cls*) + (union (difference body-free fml*) + cls*-free)))])]))]) + (values (make-closure (make-clambda-code (gensym) cls* free) free) + free))])) + (define (Expr ex) + (record-case ex + [(constant) (values ex '())] + [(var) (values ex (singleton ex))] + [(primref) (values ex '())] + [(bind lhs* rhs* body) + (let-values ([(rhs* rhs-free) (Expr* rhs*)] + [(body body-free) (Expr body)]) + (values (make-bind lhs* rhs* body) + (union rhs-free (difference body-free lhs*))))] + [(fix lhs* rhs* body) + (let-values ([(rhs* rfree) (do-clambda* rhs*)] + [(body bfree) (Expr body)]) + (values (make-fix lhs* rhs* body) + (difference (union bfree rfree) lhs*)))] + [(conditional test conseq altern) + (let-values ([(test test-free) (Expr test)] + [(conseq conseq-free) (Expr conseq)] + [(altern altern-free) (Expr altern)]) + (values (make-conditional test conseq altern) + (union test-free (union conseq-free altern-free))))] + [(seq e0 e1) + (let-values ([(e0 e0-free) (Expr e0)] + [(e1 e1-free) (Expr e1)]) + (values (make-seq e0 e1) (union e0-free e1-free)))] + [(clambda) + (do-clambda ex)] + [(primcall op rand*) + (let-values ([(rand* rand*-free) (Expr* rand*)]) + (values (make-primcall op rand*) rand*-free))] + [(forcall op rand*) + (let-values ([(rand* rand*-free) (Expr* rand*)]) + (values (make-forcall op rand*) rand*-free))] + [(funcall rator rand*) + (let-values ([(rator rat-free) (Expr rator)] + [(rand* rand*-free) (Expr* rand*)]) + (values (make-funcall rator rand*) + (union rat-free rand*-free)))] + [(appcall rator rand*) + (let-values ([(rator rat-free) (Expr rator)] + [(rand* rand*-free) (Expr* rand*)]) + (values (make-appcall rator rand*) + (union rat-free rand*-free)))] + [else (error who "invalid expression ~s" (unparse ex))])) + (let-values ([(prog free) (Expr prog)]) + (unless (null? free) + (error 'convert-closures "free vars ~s encountered in ~a" + free (unparse prog))) + prog)) + + +(define (lift-codes x) + (define who 'lift-codes) + (define all-codes '()) + (define (do-code x) + (record-case x + [(clambda-code label cls* free) + (let ([cls* (map + (lambda (x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (E body))])) + cls*)]) + (let ([g (make-code-loc label)]) + (set! all-codes + (cons (make-clambda-code label cls* free) all-codes)) + g))])) + (define (E x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(bind lhs* rhs* body) + (make-bind lhs* (map E rhs*) (E body))] + [(fix lhs* rhs* body) + (make-fix lhs* (map E rhs*) (E body))] + [(conditional test conseq altern) + (make-conditional (E test) (E conseq) (E altern))] + [(seq e0 e1) (make-seq (E e0) (E e1))] + [(closure c free) (make-closure (do-code c) free)] + [(primcall op rand*) (make-primcall op (map E rand*))] + [(forcall op rand*) (make-forcall op (map E rand*))] + [(funcall rator rand*) (make-funcall (E rator) (map E rand*))] + [(appcall rator rand*) (make-appcall (E rator) (map E rand*))] + [else (error who "invalid expression ~s" (unparse x))])) + (let ([x (E x)]) + (make-codes all-codes x))) + + + + +(define (syntactically-valid? op rand*) + (define (valid-arg-count? op rand*) + (let ([n (open-coded-primitive-args op)] [m (length rand*)]) + (cond + [(eq? n 'any) #t] + [(eq? n 'no-code) + (error 'syntactically-valid + "should not primcall non codable prim ~s" op)] + [(fixnum? n) + (cond + [(fx= n m) #t] + [else + (error 'compile + "Possible incorrect number of args in ~s" + (cons op (map unparse rand*))) + #f])] + [else (error 'do-primcall "BUG: what ~s" n)]))) + (define (check op pred?) + (lambda (arg) + (record-case arg + [(constant c) + (cond + [(pred? c) #t] + [else + (error 'compile "Possible argument error to primitive ~s" op) + #f])] + [(primref) + (cond + [(pred? (lambda (x) x)) #t] + [else + (error 'compile "Possible argument error to primitive ~s" op) + #f])] + [else #t]))) + (define (nonnegative-fixnum? n) + (and (fixnum? n) (fx>= n 0))) + (define (byte? n) + (and (fixnum? n) (fx<= 0 n) (fx<= n 127))) + (define (valid-arg-types? op rand*) + (case op + [(fixnum? immediate? boolean? char? vector? string? procedure? + null? pair? not cons eq? vector symbol? error eof-object eof-object? + void $unbound-object? $code? $forward-ptr? bwp-object? + pointer-value) + '#t] + [($fxadd1 $fxsub1 $fxzero? $fxlognot $fxlogor $fxlogand $fx+ $fx- $fx* + $fx= $fx< $fx<= $fx> $fx>= $fxquotient $fxmodulo $fxsll $fxsra $fxlogxor $exit) + (andmap (check op fixnum?) rand*)] + [($fixnum->char) + (andmap (check op byte?) rand*)] + [($char->fixnum $char= $char< $char<= $char> $char>= $string) + (andmap (check op char?) rand*)] + [($make-vector $make-string) + (andmap (check op nonnegative-fixnum?) rand*)] + [($car $cdr) + (andmap (check op pair?) rand*)] + [($vector-length) + (andmap (check op vector?) rand*)] + [($string-length) + (andmap (check op string?) rand*)] + [($set-car! $set-cdr!) + ((check op pair?) (car rand*))] + [($vector-ref $vector-set!) + (and ((check op vector?) (car rand*)) + ((check op nonnegative-fixnum?) (cadr rand*)))] + [($string-ref $string-set! + $string-ref-16+0 $string-ref-16+1 $string-ref-8+0 $string-ref-8+2) + (and ((check op string?) (car rand*)) + ((check op nonnegative-fixnum?) (cadr rand*)))] + [($symbol-string $symbol-unique-string) + (andmap (check op symbol?) rand*)] + [($constant-ref $set-constant! $intern $pcb-set! $pcb-ref $make-symbol + $symbol-value $set-symbol-value! $symbol-plist $set-symbol-plist! + $set-symbol-system-value! $set-symbol-system-value! + $set-symbol-unique-string! + $set-symbol-string! + $seal-frame-and-call $frame->continuation $code->closure + $code-size $code-reloc-vector $code-closure-size + $code-ref $code-set! + $make-record $record? $record/rtd? $record-rtd $record-ref $record-set! + primitive-set! primitive-ref + $make-tcbucket $tcbucket-key $tcbucket-val $tcbucket-next + $set-tcbucket-val! $set-tcbucket-next! $set-tcbucket-tconc!) + #t] + [else (error 'valid-arg-types? "unhandled op ~s" op)])) + (and (valid-arg-count? op rand*) + (or (null? rand*) + (valid-arg-types? op rand*)))) + + +;;; the output of simplify-operands differs from the input in that the +;;; operands to primcalls are all simple (variables, primrefs, or constants). +;;; funcalls to open-codable primrefs whos arguments are "ok" are converted to +;;; primcalls. + +(define (introduce-primcalls x) + (define who 'introduce-primcalls) + (define (simple? x) + (or (constant? x) (var? x) (primref? x))) + (define (Expr x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(closure) x] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Expr body))] + [(fix lhs* rhs* body) + (make-fix lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (make-seq (Expr e0) (Expr e1))] + [(primcall op arg*) + (case op + ;[(values) + ; (if (fx= (length arg*) 1) + ; (Expr (car arg*)) + ; (begin + ; (warning 'compile "possible incorrect number of values") + ; (make-funcall (make-primref 'values) (map Expr arg*))))] + [else + (make-primcall op (map Expr arg*))])] + [(forcall op arg*) + (make-forcall op (map Expr arg*))] + [(funcall rator rand*) + (cond + [(and (primref? rator) + (open-codeable? (primref-name rator)) + (syntactically-valid? (primref-name rator) rand*)) + (Expr (make-primcall (primref-name rator) rand*))] + [else + (make-funcall (Expr rator) (map Expr rand*))])] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (Tail x) + (record-case x + [(constant) (make-return x)] + [(var) (make-return x)] + [(primref) (make-return x)] + [(closure) (make-return x)] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Tail body))] + [(fix lhs* rhs* body) + (make-fix lhs* (map Expr rhs*) (Tail body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Tail conseq) (Tail altern))] + [(seq e0 e1) (make-seq (Expr e0) (Tail e1))] + [(primcall op arg*) + (case op + ;[(values) + ; (if (fx= (length arg*) 1) + ; (make-return (Expr (car arg*))) + ; (make-return* (map Expr arg*)))] + [else + (make-return (make-primcall op (map Expr arg*)))])] + [(forcall op arg*) + (make-return (make-forcall op (map Expr arg*)))] + [(funcall rator rand*) + (cond + [(and (primref? rator) + (open-codeable? (primref-name rator)) + (syntactically-valid? (primref-name rator) rand*)) + (Tail (make-primcall (primref-name rator) rand*))] + [else + (make-funcall (Expr rator) (map Expr rand*))])] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (CaseExpr x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (Tail body))])) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (make-clambda-code L (map CaseExpr cases) free)])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) (Tail body))])) + (CodesExpr x)) + + +(define (simplify-operands x) + (define who 'simplify-operands) + (define (simple? x) + (or (constant? x) (var? x) (primref? x))) + (define (simplify arg lhs* rhs* k) + (if (simple? arg) + (k arg lhs* rhs*) + (let ([v (unique-var 'tmp)]) + (k v (cons v lhs*) (cons (Expr arg) rhs*))))) + (define (simplify* arg* lhs* rhs* k) + (cond + [(null? arg*) (k '() lhs* rhs*)] + [else + (simplify (car arg*) lhs* rhs* + (lambda (a lhs* rhs*) + (simplify* (cdr arg*) lhs* rhs* + (lambda (d lhs* rhs*) + (k (cons a d) lhs* rhs*)))))])) + (define (Expr x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(closure) x] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Expr body))] + [(fix lhs* rhs* body) + (make-fix lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (make-seq (Expr e0) (Expr e1))] + [(primcall op arg*) + (simplify* arg* '() '() + (lambda (arg* lhs* rhs*) + (make-bind^ lhs* rhs* + (make-primcall op arg*))))] + [(forcall op arg*) + (make-forcall op (map Expr arg*))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (Tail x) + (record-case x + [(return v) (make-return (Expr v))] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Tail body))] + [(fix lhs* rhs* body) + (make-fix lhs* (map Expr rhs*) (Tail body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Tail conseq) (Tail altern))] + [(seq e0 e1) (make-seq (Expr e0) (Tail e1))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (CaseExpr x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (Tail body))])) + (define (CodeExpr x) + (record-case x + [(clambda-code L clauses free) + (make-clambda-code L (map CaseExpr clauses) free)])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) (Tail body))])) + (CodesExpr x)) + + +(define (insert-stack-overflow-checks x) + (define who 'insert-stack-overflow-checks) + (define (insert-check body) + (make-seq + (make-conditional + (make-primcall '$fp-overflow '()) + (make-funcall (make-primref 'do-stack-overflow) '()) + (make-primcall 'void '())) + body)) + (define (Expr x) + (record-case x + [(constant) #f] + [(var) #f] + [(primref) #f] + [(closure code free*) #f] + [(bind lhs* rhs* body) + (or (ormap Expr rhs*) (Expr body))] + [(fix lhs* rhs* body) (Expr body)] + [(conditional test conseq altern) + (or (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (or (Expr e0) (Expr e1))] + [(primcall op arg*) (ormap Expr arg*)] + [(forcall op arg*) (ormap Expr arg*)] + [(funcall rator arg*) #t] + [(appcall rator arg*) #t] + [else (error who "invalid expression ~s" (unparse x))])) + (define (Tail x) + (record-case x + [(return v) (Expr v)] + [(bind lhs* rhs* body) + (or (ormap Expr rhs*) (Tail body))] + [(fix lhs* rhs* body) (Tail body)] + [(conditional test conseq altern) + (or (Expr test) (Tail conseq) (Tail altern))] + [(seq e0 e1) (or (Expr e0) (Tail e1))] + [(funcall rator arg*) (or (Expr rator) (ormap Expr arg*))] + [(appcall rator arg*) (or (Expr rator) (ormap Expr arg*))] + [else (error who "invalid tail expression ~s" (unparse x))])) + (define (CaseExpr x) + (record-case x + [(clambda-case fml* proper body) + (if (Tail body) + (make-clambda-case fml* proper (insert-check body)) + x)])) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (make-clambda-code L (map CaseExpr cases) free)])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) + (if (Tail body) + (insert-check body) + body))])) + (CodesExpr x)) + + +(define (insert-allocation-checks x) + (define who 'insert-allocation-checks) + (define (check-bytes n var body) + (make-seq + (make-conditional + (make-primcall '$ap-check-bytes + (list (make-constant n) var)) + (make-funcall (make-primref 'do-overflow) + (list + (make-primcall '$fx+ + (list (make-constant n) var)))) + (make-primcall 'void '())) + body)) + (define (check-words n var body) + (make-seq + (make-conditional + (make-primcall '$ap-check-words + (list (make-constant n) var)) + (make-funcall (make-primref 'do-overflow-words) + (list + (make-primcall '$fx+ + (list (make-constant n) var)))) + (make-primcall 'void '())) + body)) + (define (check-const n body) + (make-seq + (make-conditional + (make-primcall '$ap-check-const + (list (make-constant n))) + (make-funcall (make-primref 'do-overflow) + (list (make-constant n))) + (make-primcall 'void '())) + body)) + (define (closure-size x) + (record-case x + [(closure code free*) + (align (fx+ disp-closure-data (fx* (length free*) wordsize)))] + [else (error 'closure-size "~s is not a closure" x)])) + (define (sum ac ls) + (cond + [(null? ls) ac] + [else (sum (fx+ ac (car ls)) (cdr ls))])) + (define (Expr x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(closure) + (check-const (closure-size x) x)] + [(fix lhs* rhs* body) + (if (null? lhs*) + (Expr body) + (check-const (sum 0 (map closure-size rhs*)) + (make-fix lhs* rhs* + (Expr body))))] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (make-seq (Expr e0) (Expr e1))] + [(primcall op arg*) + (let ([x (make-primcall op (map Expr arg*))]) + (case op + [(cons) (check-const pair-size x)] + [($make-symbol) (check-const symbol-size x)] + [($make-tcbucket) (check-const tcbucket-size x)] + [($frame->continuation $code->closure) + (check-const (fx+ disp-closure-data (fx* (length arg*) wordsize)) x)] + [($make-string) + (record-case (car arg*) + [(constant i) + (check-const (fx+ i (fx+ disp-string-data 1)) x)] + [else + (check-bytes (fxadd1 disp-string-data) (car arg*) x)])] + [($string) + (check-const (fx+ (length arg*) (fx+ disp-string-data 1)) x)] + [($make-vector) + (record-case (car arg*) + [(constant i) + (check-const (fx+ (fx* i wordsize) disp-vector-data) x)] + [else + (check-words (fxadd1 disp-vector-data) (car arg*) x)])] + [($make-record) + (record-case (cadr arg*) + [(constant i) + (check-const (fx+ (fx* i wordsize) disp-record-data) x)] + [else + (check-words (fxadd1 disp-record-data) (cadr arg*) x)])] + [(vector) + (check-const (fx+ (fx* (length arg*) wordsize) disp-vector-data) x)] + [else x]))] + [(forcall op arg*) + (make-forcall op (map Expr arg*))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (Tail x) + (record-case x + [(return v) (make-return (Expr v))] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Tail body))] + [(fix lhs* rhs* body) + (if (null? lhs*) + (Tail body) + (check-const (sum 0 (map closure-size rhs*)) + (make-fix lhs* rhs* + (Tail body))))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Tail conseq) (Tail altern))] + [(seq e0 e1) (make-seq (Expr e0) (Tail e1))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (CaseExpr x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (Tail body))])) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (make-clambda-code L (map CaseExpr cases) free)])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) (Tail body))])) + (CodesExpr x)) + + +(define (remove-local-variables x) + (define who 'remove-local-variables) + (define (simple* x* r) + (map (lambda (x) + (cond + [(assq x r) => cdr] + [else + (when (var? x) (error who "unbound var ~s" x)) + x])) + x*)) + (define (env->mask r sz) + (let ([s (make-vector (fxsra (fx+ sz 7) 3) 0)]) + (for-each + (lambda (idx) + (let ([q (fxsra idx 3)] + [r (fxlogand idx 7)]) + (vector-set! s q + (fxlogor (vector-ref s q) (fxsll 1 r))))) + r) + s)) + (define (do-new-frame op rand* si r call-convention rp-convention orig-live) + (make-new-frame (fxadd1 si) (fx+ (length rand*) 2) + (let f ([r* rand*] [nsi (fx+ si 2)] [live orig-live]) + (cond + [(null? r*) + (make-seq + (make-seq + (make-save-cp (make-frame-var si)) + (case call-convention + [(normal apply) + (make-eval-cp #t (Expr op nsi r (cons si live)))] + [(foreign) + (make-eval-cp #f (make-foreign-label op))] + [else (error who "invalid convention ~s" call-convention)])) + (make-call-cp call-convention + rp-convention + (fxadd1 si) ; frame size + (length rand*) ; argc + (env->mask (cons si orig-live) ; cp and everything before it + (fxadd1 si))))] ; mask-size ~~ frame size + [else + (make-seq + (make-assign (make-frame-var nsi) + (Expr (car r*) nsi r live)) + (f (cdr r*) (fxadd1 nsi) (cons nsi live)))])))) + (define (nop) (make-primcall 'void '())) + (define (do-bind lhs* rhs* body si r live k) + (let f ([lhs* lhs*] [rhs* rhs*] [si si] [nr r] [live live]) + (cond + [(null? lhs*) (k body si nr live)] + [else + (let ([v (make-frame-var si)]) + (make-seq + (make-assign v (Expr (car rhs*) si r live)) + (f (cdr lhs*) (cdr rhs*) (fxadd1 si) + (cons (cons (car lhs*) v) nr) + (cons si live))))]))) + (define (do-closure r) + (lambda (x) + (record-case x + [(closure code free*) + (make-closure code (simple* free* r))]))) + (define (do-fix lhs* rhs* body si r live k) + (let f ([l* lhs*] [nlhs* '()] [si si] [r r] [live live]) + (cond + [(null? l*) + (make-fix (reverse nlhs*) + (map (do-closure r) rhs*) + (k body si r live))] + [else + (let ([v (make-frame-var si)]) + (f (cdr l*) (cons v nlhs*) (fxadd1 si) + (cons (cons (car l*) v) r) + (cons si live)))]))) + (define (Tail x si r live) + (record-case x + [(return v) (make-return (Expr v si r live))] + [(bind lhs* rhs* body) + (do-bind lhs* rhs* body si r live Tail)] + [(fix lhs* rhs* body) + (do-fix lhs* rhs* body si r live Tail)] + [(conditional test conseq altern) + (make-conditional + (Expr test si r live) + (Tail conseq si r live) + (Tail altern si r live))] + [(seq e0 e1) (make-seq (Effect e0 si r live) (Tail e1 si r live))] + [(primcall op arg*) + (case op +; [(values) (make-primcall op (simple* arg* r))] + [else (make-return (make-primcall op (simple* arg* r)))])] + [(funcall op rand*) + (do-new-frame op rand* si r 'normal 'tail live)] + [(appcall op rand*) + (do-new-frame op rand* si r 'apply 'tail live)] + [else (error who "invalid expression ~s" (unparse x))])) + (define (Effect x si r live) + (record-case x + [(constant) (nop)] + [(var) (nop)] + [(primref) (nop)] + [(closure code free*) (nop)] + [(bind lhs* rhs* body) + (do-bind lhs* rhs* body si r live Effect)] + [(fix lhs* rhs* body) + (do-fix lhs* rhs* body si r live Effect)] + [(conditional test conseq altern) + (make-conditional + (Expr test si r live) + (Effect conseq si r live) + (Effect altern si r live))] + [(seq e0 e1) (make-seq (Effect e0 si r live) (Effect e1 si r live))] + [(primcall op arg*) + (make-primcall op (simple* arg* r))] + [(forcall op rand*) + (do-new-frame op rand* si r 'foreign 'effect live)] + [(funcall op rand*) + (do-new-frame op rand* si r 'normal 'effect live)] + [(appcall op rand*) + (do-new-frame op rand* si r 'apply 'effect live)] + [else (error who "invalid effect expression ~s" (unparse x))])) + (define (Expr x si r live) + (record-case x + [(constant) x] + [(var) + (cond + [(assq x r) => cdr] + [else (error who "unbound var ~s" x)])] + [(primref) x] + [(closure code free*) + (make-closure code (simple* free* r))] + [(bind lhs* rhs* body) + (do-bind lhs* rhs* body si r live Expr)] + [(fix lhs* rhs* body) + (do-fix lhs* rhs* body si r live Expr)] + [(conditional test conseq altern) + (make-conditional + (Expr test si r live) + (Expr conseq si r live) + (Expr altern si r live))] + [(seq e0 e1) (make-seq (Effect e0 si r live) (Expr e1 si r live))] + [(primcall op arg*) + (make-primcall op (simple* arg* r))] + [(forcall op rand*) + (do-new-frame op rand* si r 'foreign 'value live)] + [(funcall op rand*) + (do-new-frame op rand* si r 'normal 'value live)] + [(appcall op rand*) + (do-new-frame op rand* si r 'apply 'value live)] + [else (error who "invalid expression ~s" (unparse x))])) + (define (bind-fml* fml* r) + (let f ([si 1] [fml* fml*]) + (cond + [(null? fml*) (values '() si r '())] + [else + (let-values ([(nfml* nsi r live) (f (fxadd1 si) (cdr fml*))]) + (let ([v (make-frame-var si)]) + (values (cons v nfml*) + nsi + (cons (cons (car fml*) v) r) + (cons si live))))]))) + (define (bind-free* free*) + (let f ([free* free*] [idx 0] [r '()]) + (cond + [(null? free*) r] + [else + (f (cdr free*) (fxadd1 idx) + (cons (cons (car free*) (make-cp-var idx)) r))]))) + (define CaseExpr + (lambda (r) + (lambda (x) + (record-case x + [(clambda-case fml* proper body) + (let-values ([(fml* si r live) (bind-fml* fml* r)]) + (make-clambda-case fml* proper (Tail body si r live)))])))) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (let ([r (bind-free* free)]) + (make-clambda-code L (map (CaseExpr r) cases) free))])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) + (Tail body 1 '() '()))])) + (CodesExpr x)) + + +(begin + (define fx-shift 2) + (define fx-mask #x03) + (define fx-tag 0) + (define bool-f #x2F) + (define bool-t #x3F) + (define bool-mask #xEF) + (define bool-tag #x2F) + (define bool-shift 4) + (define nil #x4F) + (define eof #x5F) ; double check + (define unbound #x6F) ; double check + (define void-object #x7F) ; double check + (define bwp-object #x8F) ; double check + (define char-shift 8) + (define char-tag #x0F) + (define char-mask #xFF) + (define pair-mask 7) + (define pair-tag 1) + (define disp-car 0) + (define disp-cdr 4) + (define pair-size 8) + (define pagesize 4096) + (define pageshift 12) + (define wordsize 4) + (define wordshift 2) + + (define symbol-mask 7) + (define symbol-tag 2) + (define disp-symbol-string 0) + (define disp-symbol-unique-string 4) + (define disp-symbol-value 8) + (define disp-symbol-plist 12) + (define disp-symbol-system-value 16) + (define disp-symbol-system-plist 20) + (define symbol-size 24) + (define vector-tag 5) + (define vector-mask 7) + (define disp-vector-length 0) + (define disp-vector-data 4) + (define string-mask 7) + (define string-tag 6) + (define disp-string-length 0) + (define disp-string-data 4) + (define closure-mask 7) + (define closure-tag 3) + (define disp-closure-data 4) + (define disp-closure-code 0) + (define continuation-size 16) + (define continuation-tag #x1F) + (define disp-continuation-top 4) + (define disp-continuation-size 8) + (define disp-continuation-next 12) + (define code-tag #x2F) + (define disp-code-instrsize 4) + (define disp-code-relocsize 8) + (define disp-code-closuresize 12) + (define disp-code-data 16) + (define disp-tcbucket-tconc 0) + (define disp-tcbucket-key 4) + (define disp-tcbucket-val 8) + (define disp-tcbucket-next 12) + (define tcbucket-size 16) + + (define record-ptag 5) + (define record-pmask 7) + (define disp-record-rtd 0) + (define disp-record-data 4) + (define disp-frame-size -17) + (define disp-frame-offset -13) + (define disp-multivalue-rp -9) + (define object-alignment 8) + (define align-shift 3) + (define dirty-word -1)) + +(define (align n) + (fxsll (fxsra (fx+ n (fxsub1 object-alignment)) align-shift) align-shift)) + +(begin + (define (mem off val) + (cond + [(fixnum? off) (list 'disp (int off) val)] + [(register? off) (list 'disp off val)] + [else (error 'mem "invalid disp ~s" off)])) + (define (int x) (list 'int x)) + (define (obj x) (list 'obj x)) + (define (byte x) (list 'byte x)) + (define (byte-vector x) (list 'byte-vector x)) + (define (movzbl src targ) (list 'movzbl src targ)) + (define (sall src targ) (list 'sall src targ)) + (define (sarl src targ) (list 'sarl src targ)) + (define (shrl src targ) (list 'shrl src targ)) + (define (notl src) (list 'notl src)) + (define (pushl src) (list 'pushl src)) + (define (popl src) (list 'popl src)) + (define (orl src targ) (list 'orl src targ)) + (define (xorl src targ) (list 'xorl src targ)) + (define (andl src targ) (list 'andl src targ)) + (define (movl src targ) (list 'movl src targ)) + (define (movb src targ) (list 'movb src targ)) + (define (addl src targ) (list 'addl src targ)) + (define (imull src targ) (list 'imull src targ)) + (define (idivl src) (list 'idivl src)) + (define (subl src targ) (list 'subl src targ)) + (define (push src) (list 'push src)) + (define (pop targ) (list 'pop targ)) + (define (sete targ) (list 'sete targ)) + (define (call targ) (list 'call targ)) + (define (tail-indirect-cpr-call) + (jmp (mem (fx- disp-closure-code closure-tag) cpr))) + (define (indirect-cpr-call) + (call (mem (fx- disp-closure-code closure-tag) cpr))) + (define (negl targ) (list 'negl targ)) + (define (label x) (list 'label x)) + (define (label-address x) (list 'label-address x)) + (define (ret) '(ret)) + (define (cltd) '(cltd)) + (define (cmpl arg1 arg2) (list 'cmpl arg1 arg2)) + (define (je label) (list 'je label)) + (define (jne label) (list 'jne label)) + (define (jle label) (list 'jle label)) + (define (jge label) (list 'jge label)) + (define (jg label) (list 'jg label)) + (define (jl label) (list 'jl label)) + (define (jb label) (list 'jb label)) + (define (ja label) (list 'ja label)) + (define (jmp label) (list 'jmp label)) + (define edi '%edx) ; closure pointer + (define esi '%esi) ; pcb + (define ebp '%ebp) ; allocation pointer + (define esp '%esp) ; stack base pointer + (define al '%al) + (define ah '%ah) + (define bh '%bh) + (define cl '%cl) + (define eax '%eax) + (define ebx '%ebx) + (define ecx '%ecx) + (define edx '%edx) + (define apr '%ebp) + (define fpr '%esp) + (define cpr '%edi) + (define pcr '%esi) + (define register? symbol?) + (define (argc-convention n) + (fx- 0 (fxsll n fx-shift)))) + + +(define pcb-ref + (lambda (x) + (case x + [(allocation-pointer) (mem 0 pcr)] + [(allocation-redline) (mem 4 pcr)] + [(frame-pointer) (mem 8 pcr)] + [(frame-base) (mem 12 pcr)] + [(frame-redline) (mem 16 pcr)] + [(next-continuation) (mem 20 pcr)] + [(system-stack) (mem 24 pcr)] + [(dirty-vector) (mem 28 pcr)] + [else (error 'pcb-ref "invalid arg ~s" x)]))) + +(define (primref-loc op) + (unless (symbol? op) (error 'primref-loc "not a symbol ~s" op)) + (mem (fx- disp-symbol-system-value symbol-tag) + (obj op))) + +(define (generate-code x) + (define who 'generate-code) + (define (rp-label x) + (case x + [(value) (label-address SL_multiple_values_error_rp)] + [(effect) (label-address SL_multiple_values_ignore_rp)] + [else (error who "invalid rp-convention ~s" x)])) + (define unique-label + (lambda () + (label (gensym)))) + (define (constant-val x) + (cond + [(fixnum? x) (obj x)] + [(boolean? x) (int (if x bool-t bool-f))] + [(null? x) (int nil)] + [(char? x) (int (fx+ (fxsll (char->integer x) char-shift) char-tag))] + [(eq? x (void)) (int void-object)] + [else (obj x)])) + (define (cond-branch op Lt Lf ac) + (define (opposite x) + (cadr (assq x '([je jne] [jl jge] [jle jg] [jg jle] [jge jl])))) + (unless (or Lt Lf) + (error 'cond-branch "no labels")) + (cond + [(not Lf) (cons (list op Lt) ac)] + [(not Lt) (cons (list (opposite op) Lf) ac)] + [else (list* (list op Lt) (jmp Lf) ac)])) + (define (indirect-type-pred pri-mask pri-tag sec-mask sec-tag rand* Lt Lf ac) + (cond + [(and Lt Lf) + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int pri-mask) ebx) + (cmpl (int pri-tag) ebx) + (jne Lf) + (movl (mem (fx- 0 pri-tag) eax) ebx) + (if sec-mask + (andl (int sec-mask) ebx) + '(nop)) + (cmpl (int sec-tag) ebx) + (jne Lf) + (jmp Lt) + ac)] + [Lf + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int pri-mask) ebx) + (cmpl (int pri-tag) ebx) + (jne Lf) + (movl (mem (fx- 0 pri-tag) eax) ebx) + (if sec-mask + (andl (int sec-mask) ebx) + '(nop)) + (cmpl (int sec-tag) ebx) + (jne Lf) + ac)] + [Lt + (let ([L_END (unique-label)]) + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int pri-mask) ebx) + (cmpl (int pri-tag) ebx) + (jne L_END) + (movl (mem (fx- 0 pri-tag) eax) ebx) + (if sec-mask + (andl (int sec-mask) ebx) + '(nop)) + (cmpl (int sec-tag) ebx) + (je Lt) + L_END + ac))] + [else ac])) + (define (type-pred mask tag rand* Lt Lf ac) + (cond + [mask + (list* + (movl (Simple (car rand*)) eax) + (andl (int mask) eax) + (cmpl (int tag) eax) + (cond-branch 'je Lt Lf ac))] + [else + (let ([v (Simple (car rand*))]) + (cond + [(memq (car v) '(mem register)) + (list* + (cmpl (int tag) (Simple (car rand*))) + (cond-branch 'je Lt Lf ac))] + [else + (list* + (movl (Simple (car rand*)) eax) + (cmpl (int tag) eax) + (cond-branch 'je Lt Lf ac))]))])) + (define (compare-and-branch op rand* Lt Lf ac) + (define (opposite x) + (cadr (assq x '([je je] [jl jg] [jle jge] [jg jl] [jge jle])))) + (cond + [(and (constant? (car rand*)) (constant? (cadr rand*))) + (list* + (movl (Simple (car rand*)) eax) + (cmpl (Simple (cadr rand*)) eax) + (cond-branch op Lt Lf ac))] + [(constant? (cadr rand*)) + (list* + (cmpl (Simple (cadr rand*)) (Simple (car rand*))) + (cond-branch op Lt Lf ac))] + [(constant? (car rand*)) + (list* + (cmpl (Simple (car rand*)) (Simple (cadr rand*))) + (cond-branch (opposite op) Lt Lf ac))] + [else + (list* + (movl (Simple (car rand*)) eax) + (cmpl (Simple (cadr rand*)) eax) + (cond-branch op Lt Lf ac))])) + (define (do-pred-prim op rand* Lt Lf ac) + (case op + [(fixnum?) (type-pred fx-mask fx-tag rand* Lt Lf ac)] + [(pair?) (type-pred pair-mask pair-tag rand* Lt Lf ac)] + [(char?) (type-pred char-mask char-tag rand* Lt Lf ac)] + [(string?) (type-pred string-mask string-tag rand* Lt Lf ac)] + [(symbol?) (type-pred symbol-mask symbol-tag rand* Lt Lf ac)] + [(procedure?) (type-pred closure-mask closure-tag rand* Lt Lf ac)] + [(boolean?) (type-pred bool-mask bool-tag rand* Lt Lf ac)] + [(null?) (type-pred #f nil rand* Lt Lf ac)] + [($unbound-object?) (type-pred #f unbound rand* Lt Lf ac)] + [($forward-ptr?) (type-pred #f -1 rand* Lt Lf ac)] + [(not) (type-pred #f bool-f rand* Lt Lf ac)] + [(eof-object?) (type-pred #f eof rand* Lt Lf ac)] + [(bwp-object?) (type-pred #f bwp-object rand* Lt Lf ac)] + [($code?) + (indirect-type-pred vector-mask vector-tag #f code-tag + rand* Lt Lf ac)] + [($fxzero?) (type-pred #f 0 rand* Lt Lf ac)] + [($fx= $char= eq?) (compare-and-branch 'je rand* Lt Lf ac)] + [($fx< $char<) (compare-and-branch 'jl rand* Lt Lf ac)] + [($fx<= $char<=) (compare-and-branch 'jle rand* Lt Lf ac)] + [($fx> $char>) (compare-and-branch 'jg rand* Lt Lf ac)] + [($fx>= $char>=) (compare-and-branch 'jge rand* Lt Lf ac)] + [(vector?) + (indirect-type-pred vector-mask vector-tag fx-mask fx-tag + rand* Lt Lf ac)] + [($record?) + (indirect-type-pred record-pmask record-ptag record-pmask record-ptag + rand* Lt Lf ac)] + [($record/rtd?) + (cond + [Lf + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int vector-mask) eax) + (cmpl (int vector-tag) eax) + (jne Lf) + (movl (Simple (cadr rand*)) eax) + (cmpl (mem (fx- disp-record-rtd vector-tag) ebx) eax) + (jne Lf) + (if Lt + (cons (jmp Lt) ac) + ac))] + [Lt + (let ([Ljoin (unique-label)]) + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int vector-mask) eax) + (cmpl (int vector-tag) eax) + (jne Ljoin) + (movl (Simple (cadr rand*)) eax) + (cmpl (mem (fx- disp-record-rtd vector-tag) ebx) eax) + (je Lt) + (label Ljoin) + ac))] + [else ac])] + [(immediate?) + (cond + [(and Lt Lf) + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int fx-mask) ebx) + (cmpl (int 0) ebx) + (je Lt) + (andl (int 7) eax) + (cmpl (int 7) eax) + (je Lt) + (jmp Lf) + ac)] + [Lt + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int fx-mask) ebx) + (cmpl (int 0) ebx) + (je Lt) + (andl (int 7) eax) + (cmpl (int 7) eax) + (je Lt) + ac)] + [Lf + (let ([Ljoin (unique-label)]) + (list* + (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int fx-mask) ebx) + (cmpl (int 0) ebx) + (je Ljoin) + (andl (int 7) eax) + (cmpl (int 7) eax) + (jne Lf) + Ljoin + ac))] + [else ac])] + [($ap-check-words) + (record-case (car rand*) + [(constant i) + (list* (movl (pcb-ref 'allocation-redline) eax) + (subl (Simple (cadr rand*)) eax) + (subl (int i) eax) + (cmpl eax apr) + (cond-branch 'jge Lt Lf ac))] + [else (error who "ap-check-words")])] + [($ap-check-bytes) + (record-case (car rand*) + [(constant i) + (list* (movl (Simple (cadr rand*)) eax) + (negl eax) + (addl (pcb-ref 'allocation-redline) eax) + (subl (int i) eax) + (cmpl eax apr) + (cond-branch 'jge Lt Lf ac))] + [else (error who "ap-check-bytes")])] + [($ap-check-const) + (record-case (car rand*) + [(constant i) + (if (fx< i pagesize) + (list* + (cmpl (pcb-ref 'allocation-redline) apr) + (cond-branch 'jge Lt Lf ac)) + (list* + (movl (pcb-ref 'allocation-redline) eax) + (subl (int i) eax) + (cmpl eax apr) + (cond-branch 'jge Lt Lf ac)))] + [else (error who "ap-check-const")])] + [($fp-at-base) + (list* + (movl (pcb-ref 'frame-base) eax) + (subl (int wordsize) eax) + (cmpl eax fpr) + (cond-branch 'je Lt Lf ac))] + [($fp-overflow) + (list* (cmpl (pcb-ref 'frame-redline) fpr) + (cond-branch 'jle Lt Lf ac))] + [($vector-ref) + (do-value-prim op rand* + (do-simple-test eax Lt Lf ac))] + [(cons void $fxadd1 $fxsub1) + ;;; always true + (do-effect-prim op rand* + (cond + [(not Lt) ac] + [else (cons (jmp Lt) ac)]))] + [else + (error 'pred-prim "HERE unhandled ~s" op)])) + (define (do-pred->value-prim op rand* ac) + (case op + [else + (let ([Lf (unique-label)] [Lj (unique-label)]) + (do-pred-prim op rand* #f Lf + (list* (movl (constant-val #t) eax) + (jmp Lj) + Lf + (movl (constant-val #f) eax) + Lj + ac)))])) + (define (indirect-ref arg* off ac) + (list* + (movl (Simple (car arg*)) eax) + (movl (mem off eax) eax) + ac)) + (define (do-value-prim op arg* ac) + (case op + [(eof-object) (cons (movl (int eof) eax) ac)] + [(void) (cons (movl (int void-object) eax) ac)] + [($fxadd1) + (list* (movl (Simple (car arg*)) eax) + (addl (constant-val 1) eax) + ac)] + [($fxsub1) + (list* (movl (Simple (car arg*)) eax) + (addl (constant-val -1) eax) + ac)] + [($fx+) + (list* (movl (Simple (car arg*)) eax) + (addl (Simple (cadr arg*)) eax) + ac)] + [($fx-) + (list* (movl (Simple (car arg*)) eax) + (subl (Simple (cadr arg*)) eax) + ac)] + [($fx*) + (cond + [(constant? (car arg*)) + (record-case (car arg*) + [(constant c) + (unless (fixnum? c) + (error who "invalid arg ~s to fx*" c)) + (list* (movl (Simple (cadr arg*)) eax) + (imull (int c) eax) + ac)])] + [(constant? (cadr arg*)) + (record-case (cadr arg*) + [(constant c) + (unless (fixnum? c) + (error who "invalid arg ~s to fx*" c)) + (list* (movl (Simple (car arg*)) eax) + (imull (int c) eax) + ac)])] + [else + (list* (movl (Simple (car arg*)) eax) + (sarl (int fx-shift) eax) + (imull (Simple (cadr arg*)) eax) + ac)])] + [($fxquotient) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ecx) + (cltd) + (idivl ecx) + (sall (int fx-shift) eax) + ac)] + [($fxmodulo) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl eax ecx) + (xorl ebx ecx) + (sarl (int (fxsub1 (fx* wordsize 8))) ecx) + (andl ebx ecx) + (cltd) + (idivl ebx) + (movl edx eax) + (addl ecx eax) + ac)] + [($fxlogor) + (list* (movl (Simple (car arg*)) eax) + (orl (Simple (cadr arg*)) eax) + ac)] + [($fxlogand) + (list* (movl (Simple (car arg*)) eax) + (andl (Simple (cadr arg*)) eax) + ac)] + [($fxlogxor) + (list* (movl (Simple (car arg*)) eax) + (xorl (Simple (cadr arg*)) eax) + ac)] + [($fxsra) + (record-case (cadr arg*) + [(constant i) + (unless (fixnum? i) (error who "invalid arg to fxsra")) + (list* (movl (Simple (car arg*)) eax) + (sarl (int (fx+ i fx-shift)) eax) + (sall (int fx-shift) eax) + ac)] + [else + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ecx) + (sarl (int fx-shift) ecx) + (sarl (int fx-shift) eax) + (sarl cl eax) + (sall (int fx-shift) eax) + ac)])] + [($fxsll) + (record-case (cadr arg*) + [(constant i) + (unless (fixnum? i) (error who "invalid arg to fxsll")) + (list* (movl (Simple (car arg*)) eax) + (sall (int i) eax) + ac)] + [else + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ecx) + (sarl (int fx-shift) ecx) + (sall cl eax) + ac)])] + [($fixnum->char) + (list* (movl (Simple (car arg*)) eax) + (sall (int (fx- char-shift fx-shift)) eax) + (orl (int char-tag) eax) + ac)] + [($char->fixnum) + (list* (movl (Simple (car arg*)) eax) + (sarl (int (fx- char-shift fx-shift)) eax) + ac)] + [($fxlognot) + (list* (movl (Simple (car arg*)) eax) + (orl (int fx-mask) eax) + (notl eax) + ac)] + [($car) (indirect-ref arg* (fx- disp-car pair-tag) ac)] + [($cdr) (indirect-ref arg* (fx- disp-cdr pair-tag) ac)] + [($vector-length) + (indirect-ref arg* (fx- disp-vector-length vector-tag) ac)] + [($string-length) + (indirect-ref arg* (fx- disp-string-length string-tag) ac)] + [($symbol-string) + (indirect-ref arg* (fx- disp-symbol-string symbol-tag) ac)] + [($symbol-unique-string) + (indirect-ref arg* (fx- disp-symbol-unique-string symbol-tag) ac)] + [($symbol-value) + (indirect-ref arg* (fx- disp-symbol-value symbol-tag) ac)] + [(primitive-ref) + (indirect-ref arg* (fx- disp-symbol-system-value symbol-tag) ac)] + [($tcbucket-key) + (indirect-ref arg* (fx- disp-tcbucket-key vector-tag) ac)] + [($tcbucket-val) + (indirect-ref arg* (fx- disp-tcbucket-val vector-tag) ac)] + [($tcbucket-next) + (indirect-ref arg* (fx- disp-tcbucket-next vector-tag) ac)] + [(pointer-value) + (list* + (movl (Simple (car arg*)) eax) + (sarl (int fx-shift) eax) + (sall (int fx-shift) eax) + ac)] + [($symbol-plist) + (indirect-ref arg* (fx- disp-symbol-plist symbol-tag) ac)] + [($record-rtd) + (indirect-ref arg* (fx- disp-record-rtd record-ptag) ac)] + [($constant-ref) + (list* (movl (Simple (car arg*)) eax) ac)] + [($vector-ref) + (list* (movl (Simple (car arg*)) ebx) + (addl (Simple (cadr arg*)) ebx) + (movl (mem (fx- disp-vector-data vector-tag) ebx) eax) + ac)] + [($record-ref) + (list* (movl (Simple (car arg*)) ebx) + (addl (Simple (cadr arg*)) ebx) + (movl (mem (fx- disp-record-data record-ptag) ebx) eax) + ac)] + [($code-ref) + (list* (movl (Simple (cadr arg*)) ebx) + (sarl (int fx-shift) ebx) + (addl (Simple (car arg*)) ebx) + (movl (int 0) eax) + (movb (mem (fx- disp-code-data vector-tag) ebx) ah) + (sarl (int (fx- 8 fx-shift)) eax) + ac)] + [($string-ref) + (list* (movl (Simple (cadr arg*)) ebx) + (sarl (int fx-shift) ebx) + (addl (Simple (car arg*)) ebx) + (movl (int char-tag) eax) + (movb (mem (fx- disp-string-data string-tag) ebx) ah) + ac)] + [($make-string) + (list* (movl (Simple (car arg*)) ebx) + (movl ebx (mem disp-string-length apr)) + (movl apr eax) + (addl (int string-tag) eax) + (sarl (int fx-shift) ebx) + (addl ebx apr) + (movb (int 0) (mem disp-string-data apr)) + (addl (int (fx+ disp-string-data object-alignment)) apr) + (sarl (int align-shift) apr) + (sall (int align-shift) apr) + ac)] + [($make-vector) + (list* (movl (Simple (car arg*)) ebx) + (movl ebx (mem disp-vector-length apr)) + (movl apr eax) + (addl (int vector-tag) eax) + (addl ebx apr) + (addl (int (fx+ disp-vector-data (fxsub1 object-alignment))) apr) + (sarl (int align-shift) apr) + (sall (int align-shift) apr) + ac)] + [($make-record) + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem disp-record-rtd apr)) + (movl apr eax) + (addl (int record-ptag) eax) + (addl (Simple (cadr arg*)) apr) + (addl (int (fx+ disp-record-data (fxsub1 object-alignment))) apr) + (sarl (int align-shift) apr) + (sall (int align-shift) apr) + ac)] + [(cons) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl eax (mem disp-car apr)) + (movl apr eax) + (movl ebx (mem disp-cdr apr)) + (addl (int pair-tag) eax) + (addl (int (align pair-size)) apr) + ac)] + [($make-symbol) + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem disp-symbol-string apr)) + (movl (int 0) (mem disp-symbol-unique-string apr)) + (movl (int unbound) (mem disp-symbol-value apr)) + (movl (int nil) (mem disp-symbol-plist apr)) + (movl (int unbound) (mem disp-symbol-system-value apr)) + (movl (int nil) (mem disp-symbol-system-plist apr)) + (movl apr eax) + (addl (int symbol-tag) eax) + (addl (int (align symbol-size)) apr) + ac)] + [($make-tcbucket) + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem disp-tcbucket-tconc apr)) + (movl (Simple (cadr arg*)) eax) + (movl eax (mem disp-tcbucket-key apr)) + (movl (Simple (caddr arg*)) eax) + (movl eax (mem disp-tcbucket-val apr)) + (movl (Simple (cadddr arg*)) eax) + (movl eax (mem disp-tcbucket-next apr)) + (movl apr eax) + (addl (int vector-tag) eax) + (addl (int (align tcbucket-size)) apr) + ac)] + [(vector) + (let f ([arg* arg*] [idx disp-vector-data]) + (cond + [(null? arg*) + (list* (movl apr eax) + (addl (int vector-tag) eax) + (movl (int (fx- idx disp-vector-data)) + (mem disp-vector-length apr)) + (addl (int (align idx)) apr) + ac)] + [else + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem idx apr)) + (f (cdr arg*) (fx+ idx wordsize)))]))] + [($string) + (let f ([arg* arg*] [idx disp-string-data]) + (cond + [(null? arg*) + (list* (movb (int 0) (mem idx apr)) + (movl apr eax) + (addl (int string-tag) eax) + (movl (int (fx* (fx- idx disp-string-data) wordsize)) + (mem disp-string-length apr)) + (addl (int (align (fxadd1 idx))) apr) + ac)] + [else + (record-case (car arg*) + [(constant c) + (unless (char? c) (error who "invalid arg to string ~s" x)) + (list* (movb (int (char->integer c)) (mem idx apr)) + (f (cdr arg*) (fxadd1 idx)))] + [else + (list* (movl (Simple (car arg*)) ebx) + (movb bh (mem idx apr)) + (f (cdr arg*) (fxadd1 idx)))])]))] + [($current-frame) + (list* (movl (pcb-ref 'next-continuation) eax) + ac)] + [($seal-frame-and-call) + (list* (movl (Simple (car arg*)) cpr) ; proc + (movl (pcb-ref 'frame-base) eax) + ; eax=baseofstack + (movl (mem (fx- 0 wordsize) eax) ebx) ; underflow handler + (movl ebx (mem (fx- 0 wordsize) fpr)) ; set + ; create a new cont record + (movl (int continuation-tag) (mem 0 apr)) + (movl fpr (mem disp-continuation-top apr)) + ; compute the size of the captured frame + (movl eax ebx) + (subl fpr ebx) + (subl (int wordsize) ebx) + ; and store it + (movl ebx (mem disp-continuation-size apr)) + ; load next cont + (movl (pcb-ref 'next-continuation) ebx) + ; and store it + (movl ebx (mem disp-continuation-next apr)) + ; adjust ap + (movl apr eax) + (addl (int vector-tag) eax) + (addl (int continuation-size) apr) + ; store new cont in current-cont + (movl eax (pcb-ref 'next-continuation)) + ; adjust fp + (movl fpr (pcb-ref 'frame-base)) + (subl (int wordsize) fpr) + ; tail-call f + (movl eax (mem (fx- 0 wordsize) fpr)) + (movl (int (argc-convention 1)) eax) + (tail-indirect-cpr-call) + ac)] + [($code-size) + (indirect-ref arg* (fx- disp-code-instrsize vector-tag) ac)] + [($code-reloc-vector) + (indirect-ref arg* (fx- disp-code-relocsize vector-tag) ac)] + [($code-closure-size) + (indirect-ref arg* (fx- disp-code-closuresize vector-tag) ac)] + [($set-car! $set-cdr! $vector-set! $string-set! $exit + $set-symbol-value! $set-symbol-plist! + $code-set! primitive-set! + $set-code-object! $set-code-object+offset! $set-code-object+offset/rel! + $record-set!) + (do-effect-prim op arg* + (cons (movl (int void-object) eax) ac))] + [(fixnum? immediate? $fxzero? boolean? char? pair? vector? string? symbol? + procedure? null? not eof-object? $fx= $fx< $fx<= $fx> $fx>= eq? + $char= $char< $char<= $char> $char>= $unbound-object? $code? + $record? bwp-object?) + (do-pred->value-prim op arg* ac)] + [($code->closure) + (list* + (movl (Simple (car arg*)) eax) + (addl (int (fx- disp-code-data vector-tag)) eax) + (movl eax (mem 0 apr)) + (movl apr eax) + (addl (int closure-tag) eax) + (addl (int (align disp-closure-data)) apr) + ac)] + [($frame->continuation) + (NonTail + (make-closure (make-code-loc SL_continuation_code) arg*) + ac)] + [($make-call-with-values-procedure) + (NonTail + (make-closure (make-code-loc SL_call_with_values) arg*) + ac)] + [($make-values-procedure) + (NonTail + (make-closure (make-code-loc SL_values) arg*) + ac)] + [else + (error 'value-prim "unhandled ~s" op)])) + (define (indirect-assignment arg* offset ac) + (list* + (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem offset eax)) + ;;; record side effect + (addl (int offset) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)) + (define (do-effect-prim op arg* ac) + (case op + [($vector-set!) + (list* (movl (Simple (car arg*)) ebx) + (addl (Simple (cadr arg*)) ebx) + (addl (int (fx- disp-vector-data vector-tag)) ebx) + (movl (Simple (caddr arg*)) eax) + (movl eax (mem 0 ebx)) + ;;; record side effect + (shrl (int pageshift) ebx) + (sall (int wordshift) ebx) + (addl (pcb-ref 'dirty-vector) ebx) + (movl (int dirty-word) (mem 0 ebx)) + ac)] + [($code-set!) + (list* (movl (Simple (cadr arg*)) eax) + (sarl (int fx-shift) eax) + (addl (Simple (car arg*)) eax) + (movl (Simple (caddr arg*)) ebx) + (sall (int (fx- 8 fx-shift)) ebx) + (movb bh (mem (fx- disp-code-data vector-tag) eax)) + ac)] + [($string-set!) + (list* (movl (Simple (cadr arg*)) eax) + (sarl (int fx-shift) eax) + (addl (Simple (car arg*)) eax) + (movl (Simple (caddr arg*)) ebx) + (movb bh (mem (fx- disp-string-data string-tag) eax)) + ac)] + [($set-car!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-car pair-tag) eax)) + ;;; record side effect + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($set-cdr!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-cdr pair-tag) eax)) + ;;; record side effect + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($set-tcbucket-key!) + (indirect-assignment arg* (fx- disp-tcbucket-key vector-tag) ac)] + [($set-tcbucket-val!) + (indirect-assignment arg* (fx- disp-tcbucket-val vector-tag) ac)] + [($set-tcbucket-next!) + (indirect-assignment arg* (fx- disp-tcbucket-next vector-tag) ac)] + [($set-tcbucket-tconc!) + (indirect-assignment arg* (fx- disp-tcbucket-tconc vector-tag) ac)] + + [($set-symbol-value!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-symbol-value symbol-tag) eax)) + ;;; record side effect + (addl (int (fx- disp-symbol-value symbol-tag)) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [(primitive-set!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-symbol-system-value symbol-tag) eax)) + ;;; record side effect + (addl (int (fx- disp-symbol-system-value symbol-tag)) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($set-symbol-plist!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-symbol-plist symbol-tag) eax)) + ;;; record side effect + (addl (int (fx- disp-symbol-plist symbol-tag)) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($set-symbol-unique-string!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-symbol-unique-string symbol-tag) eax)) + ;;; record side effect + (addl (int (fx- disp-symbol-unique-string symbol-tag)) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($set-symbol-string!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-symbol-string symbol-tag) eax)) + ;;; record side effect + (addl (int (fx- disp-symbol-string symbol-tag)) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($record-set!) + (list* (movl (Simple (car arg*)) ebx) + (addl (Simple (cadr arg*)) ebx) + (movl (Simple (caddr arg*)) eax) + (addl (int (fx- disp-record-data record-ptag)) ebx) + (movl eax (mem 0 ebx)) + ;;; record side effect + (shrl (int pageshift) ebx) + (sall (int wordshift) ebx) + (addl (pcb-ref 'dirty-vector) ebx) + (movl (int dirty-word) (mem 0 ebx)) + ac)] + [(cons void $fxadd1 $fxsub1) + (let f ([arg* arg*]) + (cond + [(null? arg*) ac] + [else + (Effect (car arg*) (f (cdr arg*)))]))] + [else + (error 'do-effect-prim "unhandled op ~s" op)])) + (define (do-simple-test x Lt Lf ac) + (unless (or Lt Lf) + (error 'Pred "no labels")) + (cond + [(not Lt) + (list* (cmpl (int bool-f) x) (je Lf) ac)] + [(not Lf) + (list* (cmpl (int bool-f) x) (jne Lt) ac)] + [else + (list* (cmpl (int bool-f) x) (je Lf) (jmp Lt) ac)])) + (define (Simple x) + (record-case x + [(cp-var i) + (mem (fx+ (fx* i wordsize) (fx- disp-closure-data closure-tag)) cpr)] + [(frame-var i) (mem (fx* i (fx- 0 wordsize)) fpr)] + [(constant c) (constant-val c)] + [(code-loc label) (label-address label)] + [(primref op) (primref-loc op)] + [else (error 'Simple "what ~s" x)])) + (define (closure-size x) + (align (fx+ disp-closure-data + (fx* wordsize (length (closure-free* x)))))) + (define (assign-codes rhs* n* i ac) + (cond + [(null? rhs*) ac] + [else + (record-case (car rhs*) + [(closure label free*) + (cons (movl (Simple label) (mem i apr)) + (assign-codes + (cdr rhs*) (cdr n*) (fx+ i (car n*)) ac))])])) + (define (whack-free x i n* rhs* ac) + (cond + [(null? rhs*) ac] + [else + (let ([free (closure-free* (car rhs*))]) + (let f ([free free] [j (fx+ i disp-closure-data)]) + (cond + [(null? free) + (whack-free x (fx+ i (car n*)) (cdr n*) (cdr rhs*) ac)] + [(eq? (car free) x) + (cons + (movl eax (mem j apr)) + (f (cdr free) (fx+ j wordsize)))] + [else (f (cdr free) (fx+ j wordsize))])))])) + (define (assign-nonrec-free* rhs* all-rhs* n* seen ac) + (cond + [(null? rhs*) ac] + [else + (let f ([ls (closure-free* (car rhs*))] [seen seen]) + (cond + [(null? ls) + (assign-nonrec-free* (cdr rhs*) all-rhs* n* seen ac)] + [(memq (car ls) seen) (f (cdr ls) seen)] + [else + (cons + (movl (Simple (car ls)) eax) + (whack-free (car ls) 0 n* all-rhs* + (f (cdr ls) (cons (car ls) seen))))]))])) + (define (assign-rec-free* lhs* rhs* all-n* ac) + (list* (movl apr eax) + (addl (int closure-tag) eax) + (let f ([lhs* lhs*] [n* all-n*]) + (cond + [(null? (cdr lhs*)) + (cons + (movl eax (Simple (car lhs*))) + (whack-free (car lhs*) 0 all-n* rhs* ac))] + [else + (cons + (movl eax (Simple (car lhs*))) + (whack-free (car lhs*) 0 all-n* rhs* + (cons + (addl (int (car n*)) eax) + (f (cdr lhs*) (cdr n*)))))])))) + (define (sum ac ls) + (cond + [(null? ls) ac] + [else (sum (fx+ ac (car ls)) (cdr ls))])) + (define (do-fix lhs* rhs* ac) + ;;; 1. first, set the code pointers in the right places + ;;; 2. next, for every variable appearing in the rhs* but is not in + ;;; the lhs*, load it once and set it everywhere it occurs. + ;;; 3. next, compute the values of the lhs*, and for every computed + ;;; value, store it on the stack, and set it everywhere it occurs + ;;; in the rhs* + ;;; 4. that's it. + (let* ([n* (map closure-size rhs*)]) + (assign-codes rhs* n* 0 + (assign-nonrec-free* rhs* rhs* n* lhs* + (assign-rec-free* lhs* rhs* n* + (cons (addl (int (sum 0 n*)) apr) ac)))))) + (define (frame-adjustment offset) + (fx* (fxsub1 offset) (fx- 0 wordsize))) + (define (NonTail x ac) + (record-case x + [(constant c) + (cons (movl (constant-val c) eax) ac)] + [(frame-var) + (cons (movl (Simple x) eax) ac)] + [(cp-var) + (cons (movl (Simple x) eax) ac)] + [(foreign-label L) + (cons (movl (list 'foreign-label L) eax) ac)] + [(primref c) + (cons (movl (primref-loc c) eax) ac)] + [(closure label arg*) + (let f ([arg* arg*] [off disp-closure-data]) + (cond + [(null? arg*) + (list* (movl (Simple label) (mem 0 apr)) + (movl apr eax) + (addl (int (align off)) apr) + (addl (int closure-tag) eax) + ac)] + [else + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem off apr)) + (f (cdr arg*) (fx+ off wordsize)))]))] + [(conditional test conseq altern) + (let ([Lj (unique-label)] [Lf (unique-label)]) + (Pred test #f Lf + (NonTail conseq + (list* (jmp Lj) Lf (NonTail altern (cons Lj ac))))))] + [(seq e0 e1) + (Effect e0 (NonTail e1 ac))] + [(fix lhs* rhs* body) + (do-fix lhs* rhs* (NonTail body ac))] + [(primcall op rand*) + (do-value-prim op rand* ac)] + [(new-frame base-idx size body) + (NonTail body ac)] + [(call-cp call-convention rp-convention offset size mask) + (let ([L_CALL (unique-label)]) + (case call-convention + [(normal) + (list* (addl (int (frame-adjustment offset)) fpr) + (movl (int (argc-convention size)) eax) + (jmp L_CALL) + ; NEW FRAME + `(byte-vector ,mask) + `(int ,(fx* offset wordsize)) + `(current-frame-offset) + (rp-label rp-convention) + `(byte 0) ; padding for indirect calls only + `(byte 0) ; direct calls are ok + L_CALL + (indirect-cpr-call) + (movl (mem 0 fpr) cpr) + (subl (int (frame-adjustment offset)) fpr) + ac)] + [(foreign) + (list* (addl (int (frame-adjustment offset)) fpr) + (movl (int (argc-convention size)) eax) + (movl '(foreign-label "ik_foreign_call") ebx) + (jmp L_CALL) + ; NEW FRAME + (byte-vector mask) + `(int ,(fx* offset wordsize)) + `(current-frame-offset) + (rp-label rp-convention) ; should be 0, since C has 1 rv + '(byte 0) + '(byte 0) + '(byte 0) + L_CALL + (call ebx) + (movl (mem 0 fpr) cpr) + (subl (int (frame-adjustment offset)) fpr) + ac)] + [else + (error who "invalid convention ~s for call-cp" call-convention)]))] + [else (error 'NonTail "invalid expression ~s" x)])) + (define (Pred x Lt Lf ac) + (record-case x + [(frame-var i) + (do-simple-test (idx->frame-loc i) Lt Lf ac)] + [(cp-var i) + (do-simple-test (Simple x) Lt Lf ac)] + [(constant c) + (if c + (if Lt (cons (jmp Lt) ac) ac) + (if Lf (cons (jmp Lf) ac) ac))] + [(fix lhs* rhs* body) + (do-fix lhs* rhs* (Pred body Lt Lf ac))] + [(primcall op rand*) + (do-pred-prim op rand* Lt Lf ac)] + [(conditional test conseq altern) + (cond + [(not Lt) + (let ([Lj^ (unique-label)] [Lf^ (unique-label)]) + (Pred test #f Lf^ + (Pred conseq Lj^ Lf + (cons Lf^ + (Pred altern #f Lf + (cons Lj^ ac))))))] + [(not Lf) + (let ([Lj^ (unique-label)] [Lf^ (unique-label)]) + (Pred test #f Lf^ + (Pred conseq Lt Lj^ + (cons Lf^ + (Pred altern Lt #f + (cons Lj^ ac))))))] + [else + (let ([Lf^ (unique-label)]) + (Pred test #f Lf^ + (Pred conseq Lt Lf + (cons Lf^ + (Pred altern Lt Lf ac)))))])] + [(seq e0 e1) + (Effect e0 (Pred e1 Lt Lf ac))] + [(new-frame) + (NonTail x (do-simple-test eax Lt Lf ac))] + [else (error 'Pred "invalid expression ~s" x)])) + (define (idx->frame-loc i) + (mem (fx* i (fx- 0 wordsize)) fpr)) + (define (Effect x ac) + (record-case x + [(constant) ac] + [(primcall op rand*) + (do-effect-prim op rand* ac)] + [(conditional test conseq altern) + (let ([Lf (unique-label)] [Ljoin (unique-label)]) + (Pred test #f Lf + (Effect conseq + (list* (jmp Ljoin) Lf (Effect altern (cons Ljoin ac))))))] + [(seq e0 e1) + (Effect e0 (Effect e1 ac))] + [(fix lhs* rhs* body) + (do-fix lhs* rhs* (Effect body ac))] + [(assign loc val) + (record-case loc + [(frame-var i) + (NonTail val + (cons (movl eax (idx->frame-loc i)) ac))] + [else (error who "invalid assign loc ~s" loc)])] + [(eval-cp check body) + (NonTail body + (cond + [check + (list* + (movl eax cpr) + (andl (int closure-mask) eax) + (cmpl (int closure-tag) eax) + (jne (label SL_nonprocedure)) + ac)] + [else + (list* + (movl eax cpr) + ac)]))] + [(save-cp loc) + (record-case loc + [(frame-var i) + (cons (movl cpr (idx->frame-loc i)) ac)] + [else (error who "invalid cpr loc ~s" x)])] + [(new-frame) (NonTail x ac)] + [(frame-var) ac] + [else (error 'Effect "invalid expression ~s" x)])) + (define (Tail x ac) + (record-case x + [(return x) + (NonTail x (cons (ret) ac))] + [(conditional test conseq altern) + (let ([L (unique-label)]) + (Pred test #f L + (Tail conseq + (cons L (Tail altern ac)))))] + [(seq e0 e1) + (Effect e0 (Tail e1 ac))] + [(fix lhs* rhs* body) + (do-fix lhs* rhs* (Tail body ac))] + [(new-frame idx size body) + (Tail body ac)] + [(call-cp call-convention rp-convention idx argc mask) + (unless (eq? rp-convention 'tail) + (error who "nontail rp (~s) in tail context" rp-convention)) + (let f ([i 0]) + (cond + [(fx= i argc) + (case call-convention + [(normal) + (list* + (movl (int (argc-convention argc)) eax) + (tail-indirect-cpr-call) + ac)] + [(apply) + (list* + (movl (int (argc-convention argc)) eax) + (jmp (label SL_apply)) + ac)] + [else + (error who "invalid conv ~s in tail call-cpr" call-convention)])] + [else + (list* (movl (mem (fx* (fx+ idx (fxadd1 i)) + (fx- 0 wordsize)) fpr) + eax) + (movl eax (mem (fx* (fx+ i 1) (fx- 0 wordsize)) fpr)) + (f (fxadd1 i)))]))] + [else (error 'Tail "invalid expression ~s" x)])) + (define (handle-vararg fml-count ac) + (define CONTINUE_LABEL (unique-label)) + (define DONE_LABEL (unique-label)) + (define CONS_LABEL (unique-label)) + (define LOOP_HEAD (unique-label)) + (define L_CALL (unique-label)) + (list* (cmpl (int (argc-convention (fxsub1 fml-count))) eax) + (jg (label SL_invalid_args)) + (jl CONS_LABEL) + (movl (int nil) ebx) + (jmp DONE_LABEL) + CONS_LABEL + (movl (pcb-ref 'allocation-redline) ebx) + (addl eax ebx) + (addl eax ebx) + (cmpl ebx apr) + (jle LOOP_HEAD) + ; overflow + (addl eax esp) ; advance esp to cover args + (pushl cpr) ; push current cp + (pushl eax) ; push argc + (negl eax) ; make argc positive + (addl (int (fx* 4 wordsize)) eax) ; add 4 words to adjust frame size + (pushl eax) ; push frame size + (addl eax eax) ; double the number of args + (movl eax (mem (fx* -2 wordsize) fpr)) ; pass it as first arg + (movl (int (argc-convention 1)) eax) ; setup argc + (movl (primref-loc 'do-vararg-overflow) cpr) ; load handler + (jmp L_CALL) ; go to overflow handler + ; NEW FRAME + (int 0) ; if the framesize=0, then the framesize is dynamic + '(current-frame-offset) + (int 0) ; multiarg rp + (byte 0) + (byte 0) + L_CALL + (indirect-cpr-call) + (popl eax) ; pop framesize and drop it + (popl eax) ; reload argc + (popl cpr) ; reload cp + (subl eax fpr) ; readjust fp + LOOP_HEAD + (movl (int nil) ebx) + CONTINUE_LABEL + (movl ebx (mem disp-cdr apr)) + (movl (mem fpr eax) ebx) + (movl ebx (mem disp-car apr)) + (movl apr ebx) + (addl (int pair-tag) ebx) + (addl (int pair-size) apr) + (addl (int (fxsll 1 fx-shift)) eax) + (cmpl (int (fx- 0 (fxsll fml-count fx-shift))) eax) + (jle CONTINUE_LABEL) + DONE_LABEL + (movl ebx (mem (fx- 0 (fxsll fml-count fx-shift)) fpr)) + ac)) + (define (Entry check? x ac) + (record-case x + [(clambda-case fml* proper body) + (let ([ac (Tail body ac)]) + (cond + [(and proper check?) + (list* (cmpl (int (argc-convention (length fml*))) eax) + (jne (label SL_invalid_args)) + ac)] + [proper ac] + [else + (handle-vararg (length fml*) ac)]))])) + (define make-dispatcher + (lambda (j? L L* x x* ac) + (cond + [(null? L*) (if j? (cons (jmp (label L)) ac) ac)] + [else + (record-case x + [(clambda-case fml* proper _) + (cond + [proper + (list* (cmpl (int (argc-convention (length fml*))) eax) + (je (label L)) + (make-dispatcher #t + (car L*) (cdr L*) (car x*) (cdr x*) ac))] + [else + (list* (cmpl (int (argc-convention (fxsub1 (length fml*)))) eax) + (jle (label L)) + (make-dispatcher #t + (car L*) (cdr L*) (car x*) (cdr x*) ac))])])]))) + (define (handle-cases x x*) + (let ([L* (map (lambda (_) (gensym)) x*)] + [L (gensym)]) + (make-dispatcher #f L L* x x* + (let f ([x x] [x* x*] [L L] [L* L*]) + (cond + [(null? x*) + (cons (label L) (Entry 'check x '()))] + [else + (cons (label L) + (Entry #f x + (f (car x*) (cdr x*) (car L*) (cdr L*))))]))))) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (list* + (fx+ disp-closure-data (fx* wordsize (length free))) + (label L) + (handle-cases (car cases) (cdr cases)))])) + (record-case x + [(codes list body) + (cons (cons 0 (Tail body '())) + (map CodeExpr list))])) + + +(define SL_nonprocedure (gensym "SL_nonprocedure")) +(define SL_invalid_args (gensym "SL_invalid_args")) +(define SL_foreign_call (gensym "SL_foreign_call")) +(define SL_continuation_code (gensym "SL_continuation_code")) +(define SL_multiple_values_error_rp (gensym "SL_multiple_values_error_rp")) +(define SL_multiple_values_ignore_rp (gensym "SL_multiple_ignore_error_rp")) +(define SL_underflow_multiple_values (gensym "SL_underflow_multiple_values")) +(define SL_underflow_handler (gensym "SL_underflow_handler")) +(define SL_scheme_exit (gensym "SL_scheme_exit")) +(define SL_apply (gensym "SL_apply")) +(define SL_values (gensym "SL_values")) +(define SL_call_with_values (gensym "SL_call_with_values")) + +(module () +(list*->code* + (list + (let ([L_cwv_done (gensym)] + [L_cwv_loop (gensym)] + [L_cwv_multi_rp (gensym)] + [L_cwv_call (gensym)]) + (list disp-closure-data + (label SL_call_with_values) + (cmpl (int (argc-convention 2)) eax) + (jne (label SL_invalid_args)) + (movl (mem (fx- 0 wordsize) fpr) ebx) ; producer + (movl ebx cpr) + (andl (int closure-mask) ebx) + (cmpl (int closure-tag) ebx) + (jne (label SL_nonprocedure)) + (movl (int (argc-convention 0)) eax) + (subl (int (fx* wordsize 2)) fpr) + (jmp (label L_cwv_call)) + ; MV NEW FRAME + (byte-vector '#(#b110)) + (int (fx* wordsize 3)) + '(current-frame-offset) + (label-address L_cwv_multi_rp) + (byte 0) + (byte 0) + (label L_cwv_call) + (indirect-cpr-call) + ;;; one value returned + (addl (int (fx* wordsize 2)) fpr) + (movl (mem (fx* -2 wordsize) fpr) ebx) ; consumer + (movl ebx cpr) + (movl eax (mem (fx- 0 wordsize) fpr)) + (movl (int (argc-convention 1)) eax) + (andl (int closure-mask) ebx) + (cmpl (int closure-tag) ebx) + (jne (label SL_nonprocedure)) + (tail-indirect-cpr-call) + ;;; multiple values returned + (label L_cwv_multi_rp) + ; because values does not pop the return point + ; we have to adjust fp one more word here + (addl (int (fx* wordsize 3)) fpr) + (movl (mem (fx* -2 wordsize) fpr) cpr) ; consumer + (cmpl (int (argc-convention 0)) eax) + (je (label L_cwv_done)) + (movl (int (fx* -4 wordsize)) ebx) + (addl fpr ebx) ; ebx points to first value + (movl ebx ecx) + (addl eax ecx) ; ecx points to the last value + (label L_cwv_loop) + (movl (mem 0 ebx) edx) + (movl edx (mem (fx* 3 wordsize) ebx)) + (subl (int wordsize) ebx) + (cmpl ecx ebx) + (jge (label L_cwv_loop)) + (label L_cwv_done) + (movl cpr ebx) + (andl (int closure-mask) ebx) + (cmpl (int closure-tag) ebx) + (jne (label SL_nonprocedure)) + (tail-indirect-cpr-call))) + + (let ([L_values_one_value (gensym)] + [L_values_many_values (gensym)]) + (list disp-closure-data + (label SL_values) + (cmpl (int (argc-convention 1)) eax) + (je (label L_values_one_value)) + (label L_values_many_values) + (movl (mem 0 fpr) ebx) ; return point + (jmp (mem disp-multivalue-rp ebx)) ; go + (label L_values_one_value) + (movl (mem (fx- 0 wordsize) fpr) eax) + (ret))) + + (let ([L_apply_done (gensym)] + [L_apply_loop (gensym)]) + (list 0 + (label SL_apply) + (movl (mem fpr eax) ebx) + (cmpl (int nil) ebx) + (je (label L_apply_done)) + (label L_apply_loop) + (movl (mem (fx- disp-car pair-tag) ebx) ecx) + (movl (mem (fx- disp-cdr pair-tag) ebx) ebx) + (movl ecx (mem fpr eax)) + (subl (int wordsize) eax) + (cmpl (int nil) ebx) + (jne (label L_apply_loop)) + (label L_apply_done) + (addl (int wordsize) eax) + (tail-indirect-cpr-call))) + + (list 0 + (label SL_nonprocedure) + (movl cpr (mem (fx- 0 wordsize) fpr)) ; first arg + (movl (primref-loc '$apply-nonprocedure-error-handler) cpr) + (movl (int (argc-convention 1)) eax) + (tail-indirect-cpr-call)) + + (list 0 + (label SL_multiple_values_error_rp) + (movl (primref-loc '$multiple-values-error) cpr) + (tail-indirect-cpr-call)) + + (list 0 + (label SL_multiple_values_ignore_rp) + (ret)) + + (list 0 + (label SL_invalid_args) + ;;; + (movl cpr (mem (fx- 0 wordsize) fpr)) ; first arg + (negl eax) + (movl eax (mem (fx- 0 (fx* 2 wordsize)) fpr)) + (movl (primref-loc '$incorrect-args-error-handler) cpr) + (movl (int (argc-convention 2)) eax) + (tail-indirect-cpr-call)) + + (let ([Lset (gensym)] [Lloop (gensym)]) + (list 0 + (label SL_foreign_call) + (movl fpr (pcb-ref 'frame-pointer)) + (movl apr (pcb-ref 'allocation-pointer)) + (movl fpr ebx) + (movl (pcb-ref 'system-stack) esp) + (pushl pcr) + (cmpl (int 0) eax) + (je (label Lset)) + (label Lloop) + (movl (mem ebx eax) ecx) + (pushl ecx) + (addl (int 4) eax) + (cmpl (int 0) eax) + (jne (label Lloop)) + (label Lset) + ; FOREIGN NEW FRAME + (call cpr) + (movl (pcb-ref 'frame-pointer) fpr) + (movl (pcb-ref 'allocation-pointer) apr) + (ret))) + + (let ([L_cont_zero_args (gensym)] + [L_cont_mult_args (gensym)] + [L_cont_one_arg (gensym)] + [L_cont_mult_move_args (gensym)] + [L_cont_mult_copy_loop (gensym)]) + (list + (fx+ disp-closure-data wordsize) + (label SL_continuation_code) + (movl (mem (fx- disp-closure-data closure-tag) cpr) ebx) ; captured-k + (movl ebx (pcb-ref 'next-continuation)) ; set + (movl (pcb-ref 'frame-base) ebx) + (cmpl (int (argc-convention 1)) eax) + (jg (label L_cont_zero_args)) + (jl (label L_cont_mult_args)) + (label L_cont_one_arg) + (movl (mem (fx- 0 wordsize) fpr) eax) + (movl ebx fpr) + (subl (int wordsize) fpr) + (ret) + (label L_cont_zero_args) + (subl (int wordsize) ebx) + (movl ebx fpr) + (movl (mem 0 ebx) ebx) ; return point + (jmp (mem disp-multivalue-rp ebx)) ; go + (label L_cont_mult_args) + (subl (int wordsize) ebx) + (cmpl ebx fpr) + (jne (label L_cont_mult_move_args)) + (movl (mem 0 ebx) ebx) + (jmp (mem disp-multivalue-rp ebx)) + (label L_cont_mult_move_args) + ; move args from fpr to ebx + (movl (int 0) ecx) + (label L_cont_mult_copy_loop) + (subl (int wordsize) ecx) + (movl (mem fpr ecx) edx) + (movl edx (mem ebx ecx)) + (cmpl ecx eax) + (jne (label L_cont_mult_copy_loop)) + (movl ebx fpr) + (movl (mem 0 ebx) ebx) + (jmp (mem disp-multivalue-rp ebx)) + )) + ))) + + + +(define (compile-expr expr) + (let* ([p (recordize expr)] + [p (optimize-direct-calls p)] + [p (optimize-letrec p)] + ;[p (remove-letrec p)] + [p (remove-assignments p)] + [p (convert-closures p)] + [p (lift-codes p)] + [p (introduce-primcalls p)] + [p (simplify-operands p)] + [p (insert-stack-overflow-checks p)] + [p (insert-allocation-checks p)] + [p (remove-local-variables p)] + [ls* (generate-code p)] + [f (when (assembler-output) + (for-each + (lambda (ls) + (for-each (lambda (x) (printf " ~s\n" x)) ls)) + ls*))] + [code* (list*->code* ls*)]) + (car code*))) + +(define compile-file + (lambda (input-file output-file . rest) + (let ([ip (open-input-file input-file)] + [op (apply open-output-file output-file rest)]) + (let f () + (let ([x (read ip)]) + (unless (eof-object? x) + (fasl-write (compile-expr (expand x)) op) + (f)))) + (close-input-port ip) + (close-output-port op)))) + +(primitive-set! 'compile-file compile-file) +(primitive-set! 'assembler-output (make-parameter #f)) +(primitive-set! 'compile + (lambda (x) + (let ([code (compile-expr (expand x))]) + (let ([proc ($code->closure code)]) + (proc))))) + +) + diff --git a/src/libcompile-6.7.ss b/src/libcompile-6.7.ss new file mode 100644 index 0000000..8e21502 --- /dev/null +++ b/src/libcompile-6.7.ss @@ -0,0 +1,3660 @@ + +;;; 6.7: * open-coded top-level-value, car, cdr +;;; 6.2: * side-effects now modify the dirty-vector +;;; * added bwp-object? +;;; * added pointer-value +;;; * added tcbuckets +;;; 6.1: * added case-lambda, dropped lambda +;;; 6.0: * basic compiler + +(let () + +(define-syntax cond-expand + (lambda (x) + (syntax-case x () + [(_ test conseq altern) + (if (eval (syntax-object->datum #'test)) + #'conseq + #'altern)]))) + +(cond-expand (eq? "" "") + (include "record-case.chez.ss") + (include "record-case.ss")) + + +(include "set-operations.ss") + + +(define open-coded-primitives +;;; these primitives, when found in operator position with the correct +;;; number of arguments, will be open-coded by the generator. If an +;;; incorrect number of args is detected, or if they appear in non-operator +;;; position, then they cannot be open-coded, and the pcb-primitives table +;;; is consulted for a reference of the pcb slot containing the primitive. +;;; If it's not found there, an error is signalled. +;;; +;;; prim-name args + '([$constant-ref 1 value] + [$constant-set! 2 effect] + [$pcb-ref 1 value] + [$pcb-set! 2 effect] + ;;; type predicates + [fixnum? 1 pred] + [immediate? 1 pred] + [boolean? 1 pred] + [char? 1 pred] + [pair? 1 pred] + [symbol? 1 pred] + [vector? 1 pred] + [string? 1 pred] + [procedure? 1 pred] + [null? 1 pred] + [eof-object? 1 pred] + [bwp-object? 1 pred] + [$unbound-object? 1 pred] + [$forward-ptr? 1 pred] + [not 1 pred] + [pointer-value 1 value] + [eq? 2 pred] + ;;; fixnum primitives + [$fxadd1 1 value] + [$fxsub1 1 value] + [$fx+ 2 value] + [$fx- 2 value] + [$fx* 2 value] + [$fxsll 2 value] + [$fxsra 2 value] + [$fxlogand 2 value] + [$fxlogor 2 value] + [$fxlogxor 2 value] + [$fxlognot 1 value] + [$fxquotient 2 value] + [$fxmodulo 2 value] + ;;; fixnum predicates + [$fxzero? 1 pred] + [$fx= 2 pred] + [$fx< 2 pred] + [$fx<= 2 pred] + [$fx> 2 pred] + [$fx>= 2 pred] + ;;; character predicates + [$char= 2 pred] + [$char< 2 pred] + [$char<= 2 pred] + [$char> 2 pred] + [$char>= 2 pred] + ;;; character conversion + [$fixnum->char 1 value] + [$char->fixnum 1 value] + ;;; lists/pairs + [cons 2 value] + [list* positive value] + [list any value] + [car 1 value] + [cdr 1 value] + [$car 1 value] + [$cdr 1 value] + [$set-car! 2 effect] + [$set-cdr! 2 effect] + ;;; vectors + [$make-vector 1 value] + [vector any value] + [$vector-length 1 value] + [$vector-ref 2 value] + [$vector-set! 3 effect] + [$vector-memq 2 value] + ;;; strings + [$make-string 1 value] + [$string any value] + [$string-length 1 value] + [$string-ref 2 value] + [$string-set! 3 effect] + ;;; symbols + [$make-symbol 1 value] + [$symbol-value 1 value] + [$symbol-string 1 value] + [$symbol-unique-string 1 value] + [$set-symbol-value! 2 effect] + [$set-symbol-string! 2 effect] + [$set-symbol-unique-string! 2 effect] + [$symbol-plist 1 value] + [$set-symbol-plist! 2 effect] + [primitive-ref 1 value] + [primitive-set! 2 effect] + [top-level-value 1 value] + ;;; tcbuckets + [$make-tcbucket 4 value] + [$tcbucket-key 1 value] + [$tcbucket-val 1 value] + [$tcbucket-next 1 value] + [$set-tcbucket-val! 2 effect] + [$set-tcbucket-next! 2 effect] + [$set-tcbucket-tconc! 2 effect] + ;;; misc + [eof-object 0 value] + [void 0 value] + [$exit 1 effect] + [$fp-at-base 0 pred] + [$current-frame 0 value] + [$seal-frame-and-call 1 tail] + [$frame->continuation 1 value] + ;;; + ;;; records + ;;; + [$make-record 2 value] + [$record? 1 pred] + [$record/rtd? 2 pred] + [$record-rtd 1 value] + [$record-ref 2 value] + [$record-set! 3 effect] + [$record any value] + ;;; + ;;; asm + ;;; + [$code? 1 pred] + [$code-size 1 value] + [$code-reloc-vector 1 value] + [$code-freevars 1 value] + [$code-ref 2 value] + [$code-set! 3 value] + [$code->closure 1 value] + ;;; + [$make-call-with-values-procedure 0 value] + [$make-values-procedure 0 value] + [$install-underflow-handler 0 effect] + )) + +(define (primitive-context x) + (cond + [(assq x open-coded-primitives) => caddr] + [else (error 'primitive-context "unknown prim ~s" x)])) + +(define (open-codeable? x) + (cond + [(assq x open-coded-primitives) #t] + [else #f])) + +(define (open-coded-primitive-args x) + (cond + [(assq x open-coded-primitives) => cadr] + [else (error 'open-coded-primitive-args "invalid ~s" x)])) + +;;; end of primitives table section + + +(define-record constant (value)) +(define-record code-loc (label)) +(define-record foreign-label (label)) +(define-record var (name assigned)) +(define-record cp-var (idx)) +(define-record frame-var (idx)) +(define-record new-frame (base-idx size body)) +(define-record save-cp (loc)) +(define-record eval-cp (check body)) +(define-record return (value)) +(define-record call-cp + (call-convention rp-convention base-idx arg-count live-mask)) +(define-record tailcall-cp (convention arg-count)) +(define-record primcall (op arg*)) +(define-record primref (name)) +(define-record conditional (test conseq altern)) +(define-record bind (lhs* rhs* body)) +(define-record recbind (lhs* rhs* body)) +(define-record fix (lhs* rhs* body)) + +(define-record seq (e0 e1)) +(define-record clambda-case (arg* proper body)) +(define-record clambda (cases)) +(define-record clambda-code (label cases free)) +(define-record closure (code free*)) +(define-record funcall (op rand*)) +(define-record appcall (op rand*)) +(define-record forcall (op rand*)) +(define-record code-rec (arg* proper free* body)) +(define-record codes (list body)) +(define-record assign (lhs rhs)) + +(define (unique-var x) + (make-var (gensym (symbol->string x)) #f)) + + +(define (make-bind^ lhs* rhs* body) + (if (null? lhs*) + body + (make-bind lhs* rhs* body))) + +(define (recordize x) + (define (gen-fml* fml*) + (cond + [(pair? fml*) + (cons (unique-var (car fml*)) + (gen-fml* (cdr fml*)))] + [(symbol? fml*) + (unique-var fml*)] + [else '()])) + (define (properize fml*) + (cond + [(pair? fml*) + (cons (car fml*) (properize (cdr fml*)))] + [(null? fml*) '()] + [else (list fml*)])) + (define (extend-env fml* nfml* env) + (cons (cons fml* nfml*) env)) + (define (quoted-sym x) + (if (and (list? x) + (fx= (length x) 2) + (eq? 'quote (car x)) + (symbol? (cadr x))) + (cadr x) + (error 'quoted-sym "not a quoted symbol ~s" x))) + (define (quoted-string x) + (if (and (list? x) + (fx= (length x) 2) + (eq? 'quote (car x)) + (string? (cadr x))) + (cadr x) + (error 'quoted-string "not a quoted string ~s" x))) + (define (lookup^ x lhs* rhs*) + (cond + [(pair? lhs*) + (if (eq? x (car lhs*)) + (car rhs*) + (lookup^ x (cdr lhs*) (cdr rhs*)))] + [(eq? x lhs*) rhs*] + [else #f])) + (define (lookup x env) + (cond + [(pair? env) + (or (lookup^ x (caar env) (cdar env)) + (lookup x (cdr env)))] + [else #f])) + (define (E x env) + (cond + [(pair? x) + (case (car x) + [(quote) (make-constant (cadr x))] + [(if) + (make-conditional + (E (cadr x) env) + (E (caddr x) env) + (E (cadddr x) env))] + [(set!) + (let ([lhs (cadr x)] [rhs (caddr x)]) + (make-assign + (or (lookup lhs env) + (error 'recordize "invalid assignment ~s" x)) + (E rhs env)))] + [(begin) + (let f ([a (cadr x)] [d (cddr x)]) + (cond + [(null? d) (E a env)] + [else + (make-seq + (E a env) + (f (car d) (cdr d)))]))] + [(letrec) + (unless (fx= (length x) 3) (syntax-error x)) + (let ([bind* (cadr x)] [body (caddr x)]) + (let ([lhs* (map car bind*)] + [rhs* (map cadr bind*)]) + (let ([nlhs* (gen-fml* lhs*)]) + (let ([env (extend-env lhs* nlhs* env)]) + (make-recbind nlhs* + (map (lambda (rhs) (E rhs env)) rhs*) + (E body env))))))] + [(letrec) + (unless (fx= (length x) 3) (syntax-error x)) + (let ([bind* (cadr x)] [body (caddr x)]) + (let ([lhs* (map car bind*)] + [rhs* (map cadr bind*)] + [v* (map (lambda (x) '(void)) bind*)] + [t* (map (lambda (x) (gensym)) bind*)]) + (E `((case-lambda + [,lhs* + ((case-lambda + [,t* + (begin ,@(map (lambda (x v) `(set! ,x ,v)) lhs* t*) + ,body)]) + ,@rhs*)]) + ,@v*) + env)))] + [(case-lambda) + (let ([cls* + (map + (lambda (cls) + (let ([fml* (car cls)] [body (cadr cls)]) + (let ([nfml* (gen-fml* fml*)]) + (let ([body (E body (extend-env fml* nfml* env))]) + (make-clambda-case + (properize nfml*) + (list? fml*) + body))))) + (cdr x))]) + (make-clambda cls*))] + [(foreign-call) + (let ([name (quoted-string (cadr x))] [arg* (cddr x)]) + (make-forcall name + (map (lambda (x) (E x env)) arg*)))] + [(|#primitive|) + (let ([var (cadr x)]) + (make-primref var))] + ;;; [(|#primitive|) + ;;; (let ([var (cadr x)]) + ;;; (if (primitive? var) + ;;; (make-primref var) + ;;; (error 'recordize "invalid primitive ~s" var)))] + [(top-level-value) + (let ([var (quoted-sym (cadr x))]) + (if (eq? (expand-mode) 'bootstrap) + (error 'compile "reference to ~s in bootstrap mode" var) + (make-funcall + (make-primref 'top-level-value) + (list (make-constant var)))))] + ;;; [(top-level-value) + ;;; (let ([var (quoted-sym (cadr x))]) + ;;; (if (eq? (expand-mode) 'bootstrap) + ;;; (if (primitive? var) + ;;; (make-primref var) + ;;; (error 'compile "invalid primitive ~s" var)) + ;;; (make-funcall + ;;; (make-primref 'top-level-value) + ;;; (list (make-constant var)))))] + [(set-top-level-value!) + (make-funcall (make-primref 'set-top-level-value!) + (map (lambda (x) (E x env)) (cdr x)))] + [(memv) + (make-funcall + (make-primref 'memq) + (map (lambda (x) (E x env)) (cdr x)))] + [($apply) + (let ([proc (cadr x)] [arg* (cddr x)]) + (make-appcall + (E proc env) + (map (lambda (x) (E x env)) arg*)))] + [(void) + (make-constant (void))] + [else + (make-funcall + (E (car x) env) + (map (lambda (x) (E x env)) (cdr x)))])] + [(symbol? x) + (or (lookup x env) + (error 'recordize "invalid reference in ~s" x))] + [else (error 'recordize "invalid expression ~s" x)])) + (E x '())) + + +(define (unparse x) + (define (E-args proper x) + (if proper + (map E x) + (let f ([a (car x)] [d (cdr x)]) + (cond + [(null? d) (E a)] + [else (cons (E a) (f (car d) (cdr d)))])))) + (define (E x) + (record-case x + [(constant c) `(quote ,c)] + [(code-loc x) `(code-loc ,x)] + [(var x) (string->symbol (format "v:~a" x))] + [(primref x) x] + [(conditional test conseq altern) + `(if ,(E test) ,(E conseq) ,(E altern))] + [(primcall op arg*) `(,op . ,(map E arg*))] + [(bind lhs* rhs* body) + `(let ,(map (lambda (lhs rhs) (list (E lhs) (E rhs))) lhs* rhs*) + ,(E body))] + [(recbind lhs* rhs* body) + `(letrec ,(map (lambda (lhs rhs) (list (E lhs) (E rhs))) lhs* rhs*) + ,(E body))] + [(fix lhs* rhs* body) + `(fix ,(map (lambda (lhs rhs) (list (E lhs) (E rhs))) lhs* rhs*) + ,(E body))] + [(seq e0 e1) `(begin ,(E e0) ,(E e1))] + [(clambda-case args proper body) + `(clambda-case ,(E-args proper args) ,(E body))] + [(clambda cls*) + `(case-lambda . ,(map E cls*))] + [(clambda-code label clauses free) + `(code ,label . ,(map E clauses))] + [(closure code free*) + `(closure ,(E code) ,(map E free*))] + [(code-rec arg* proper free* body) + `(code-rec [arg: ,(E-args proper arg*)] + [free: ,(map E free*)] + ,(E body))] + [(codes list body) + `(codes ,(map E list) + ,(E body))] + [(funcall rator rand*) `(funcall ,(E rator) . ,(map E rand*))] + [(appcall rator rand*) `(appcall ,(E rator) . ,(map E rand*))] + [(forcall rator rand*) `(foreign-call ,rator . ,(map E rand*))] + [(assign lhs rhs) `(set! ,(E lhs) ,(E rhs))] + [(return x) `(return ,(E x))] + [(new-frame base-idx size body) + `(new-frame [base: ,base-idx] + [size: ,size] + ,(E body))] + [(frame-var idx) + (string->symbol (format "fv.~a" idx))] + [(cp-var idx) + (string->symbol (format "cp.~a" idx))] + [(save-cp expr) + `(save-cp ,(E expr))] + [(eval-cp check body) + `(eval-cp ,check ,(E body))] + [(call-cp call-convention rp-convention base-idx arg-count live-mask) + `(call-cp [conv: ,call-convention] + [rpconv: ,rp-convention] + [base-idx: ,base-idx] + [arg-count: ,arg-count] + [live-mask: ,live-mask])] + [(foreign-label x) `(foreign-label ,x)] + [else (error 'unparse "invalid record ~s" x)])) + (E x)) + +(define (optimize-direct-calls x) + (define who 'optimize-direct-calls) + (define (make-conses ls) + (cond + [(null? ls) (make-constant '())] + [else + (make-primcall 'cons + (list (car ls) (make-conses (cdr ls))))])) + (define (properize lhs* rhs*) + (cond + [(null? lhs*) (error who "improper improper")] + [(null? (cdr lhs*)) + (list (make-conses rhs*))] + [else (cons (car rhs*) (properize (cdr lhs*) (cdr rhs*)))])) + (define (inline-case cls rand*) + (record-case cls + [(clambda-case fml* proper body) + (if proper + (and (fx= (length fml*) (length rand*)) + (make-bind fml* rand* body)) + (and (fx<= (length fml*) (length rand*)) + (make-bind fml* (properize fml* rand*) body)))])) + (define (try-inline cls* rand* default) + (cond + [(null? cls*) default] + [(inline-case (car cls*) rand*)] + [else (try-inline (cdr cls*) rand* default)])) + (define (inline rator rand*) + (record-case rator + [(clambda cls*) + (try-inline cls* rand* + (make-funcall rator rand*))] + [else (make-funcall rator rand*)])) + (define (Expr x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Expr body))] + [(recbind lhs* rhs* body) + (make-recbind lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional + (Expr test) + (Expr conseq) + (Expr altern))] + [(seq e0 e1) + (make-seq (Expr e0) (Expr e1))] + [(clambda cls*) + (make-clambda + (map (lambda (x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (Expr body))])) + cls*))] + [(primcall rator rand*) + (make-primcall rator (map Expr rand*))] + [(funcall rator rand*) + (inline (Expr rator) (map Expr rand*))] + [(appcall rator rand*) + (make-appcall (Expr rator) (map Expr rand*))] + [(forcall rator rand*) + (make-forcall rator (map Expr rand*))] + [(assign lhs rhs) + (make-assign lhs (Expr rhs))] + [else (error who "invalid expression ~s" (unparse x))])) + (Expr x)) + + + + +(define lambda-both 0) +(define lambda-producer 0) +(define lambda-consumer 0) +(define lambda-none 0) +(define branching-producer 0) + + +(define (analyze-cwv x) + (define who 'analyze-cwv) + (define (lambda? x) + (record-case x + [(clambda) #t] + [else #f])) + (define (branching-producer? x) + (define (bt? x) + (record-case x + [(bind lhs* rhs* body) (bt? body)] + [(recbind lhs* rhs* body) (bt? body)] + [(conditional test conseq altern) #t] + [(seq e0 e1) (bt? e1)] + [else #f])) + (define (branching-clause? x) + (record-case x + [(clambda-case fml* proper body) + (bt? body)])) + (record-case x + [(clambda cls*) + (ormap branching-clause? cls*)] + [else #f])) + (define (analyze producer consumer) + (cond + [(and (lambda? producer) (lambda? consumer)) + (set! lambda-both (fxadd1 lambda-both))] + [(lambda? producer) + (set! lambda-producer (fxadd1 lambda-producer))] + [(lambda? consumer) + (set! lambda-consumer (fxadd1 lambda-consumer))] + [else + (set! lambda-none (fxadd1 lambda-none))]) + (when (branching-producer? producer) + (set! branching-producer (fxadd1 branching-producer))) + (printf "both=~s p=~s c=~s none=~s branching-prod=~s\n" + lambda-both lambda-producer lambda-consumer lambda-none + branching-producer)) + (define (E x) + (record-case x + [(constant) (void)] + [(var) (void)] + [(primref) (void)] + [(bind lhs* rhs* body) + (for-each E rhs*) (E body)] + [(recbind lhs* rhs* body) + (for-each E rhs*) (E body)] + [(conditional test conseq altern) + (E test) + (E conseq) + (E altern)] + [(seq e0 e1) (E e0) (E e1)] + [(clambda cls*) + (for-each + (lambda (x) + (record-case x + [(clambda-case fml* proper body) (E body)])) + cls*)] + [(primcall rator rand*) + (for-each E rand*) + (when (and (eq? rator 'call-with-values) (fx= (length rand*) 2)) + (analyze (car rand*) (cadr rand*)))] + [(funcall rator rand*) + (E rator) (for-each E rand*) + (when (and (record-case rator + [(primref op) (eq? op 'call-with-values)] + [else #f]) + (fx= (length rand*) 2)) + (analyze (car rand*) (cadr rand*)))] + [(appcall rator rand*) + (E rator) (for-each E rand*)] + [(forcall rator rand*) + (for-each E rand*)] + [(assign lhs rhs) + (E rhs)] + [else (error who "invalid expression ~s" (unparse x))])) + (E x)) + + + + +(define (optimize-letrec x) + (define who 'optimize-letrec) + (define (extend-hash lhs* h ref) + (for-each (lambda (lhs) (put-hash-table! h lhs #t)) lhs*) + (lambda (x) + (unless (get-hash-table h x #f) + (put-hash-table! h x #t) + (ref x)))) + (define (E* x* ref comp) + (cond + [(null? x*) '()] + [else + (cons (E (car x*) ref comp) + (E* (cdr x*) ref comp))])) + (define (do-rhs* i lhs* rhs* ref comp vref vcomp) + (cond + [(null? rhs*) '()] + [else + (let ([h (make-hash-table)]) + (let ([ref + (lambda (x) + (unless (get-hash-table h x #f) + (put-hash-table! h x #t) + (ref x) + (when (memq x lhs*) + (vector-set! vref i #t))))] + [comp + (lambda () + (vector-set! vcomp i #t) + (comp))]) + (cons (E (car rhs*) ref comp) + (do-rhs* (fxadd1 i) lhs* (cdr rhs*) ref comp vref vcomp))))])) + (define (partition-rhs* i lhs* rhs* vref vcomp) + (cond + [(null? lhs*) (values '() '() '() '() '() '())] + [else + (let-values + ([(slhs* srhs* llhs* lrhs* clhs* crhs*) + (partition-rhs* (fxadd1 i) (cdr lhs*) (cdr rhs*) vref vcomp)] + [(lhs rhs) (values (car lhs*) (car rhs*))]) + (cond + [(var-assigned lhs) + (values slhs* srhs* llhs* lrhs* (cons lhs clhs*) (cons rhs crhs*))] + [(clambda? rhs) + (values slhs* srhs* (cons lhs llhs*) (cons rhs lrhs*) clhs* crhs*)] + [(or (vector-ref vref i) (vector-ref vcomp i)) + (values slhs* srhs* llhs* lrhs* (cons lhs clhs*) (cons rhs crhs*))] + [else + (values (cons lhs slhs*) (cons rhs srhs*) llhs* lrhs* clhs* crhs*)] + ))])) + (define (do-recbind lhs* rhs* body ref comp) + (let ([h (make-hash-table)] + [vref (make-vector (length lhs*) #f)] + [vcomp (make-vector (length lhs*) #f)]) + (let* ([ref (extend-hash lhs* h ref)] + [body (E body ref comp)]) + (let ([rhs* (do-rhs* 0 lhs* rhs* ref comp vref vcomp)]) + (let-values ([(slhs* srhs* llhs* lrhs* clhs* crhs*) + (partition-rhs* 0 lhs* rhs* vref vcomp)]) + (let ([v* (map (lambda (x) (make-primcall 'void '())) clhs*)] + [t* (map (lambda (x) (unique-var 'tmp)) clhs*)]) + (make-bind slhs* srhs* + (make-bind clhs* v* + (make-fix llhs* lrhs* + (make-bind t* crhs* + (build-assign* clhs* t* body))))))))))) + (define (build-assign* lhs* rhs* body) + (cond + [(null? lhs*) body] + [else + (make-seq + (make-assign (car lhs*) (car rhs*)) + (build-assign* (cdr lhs*) (cdr rhs*) body))])) + (define (E x ref comp) + (record-case x + [(constant) x] + [(var) (ref x) x] + [(assign lhs rhs) + (set-var-assigned! lhs #t) + (ref lhs) + (make-assign lhs (E rhs ref comp))] + [(primref) x] + [(bind lhs* rhs* body) + (let ([rhs* (E* rhs* ref comp)]) + (let ([h (make-hash-table)]) + (let ([body (E body (extend-hash lhs* h ref) comp)]) + (make-bind lhs* rhs* body))))] + [(recbind lhs* rhs* body) + (if (null? lhs*) + (E body ref comp) + (do-recbind lhs* rhs* body ref comp))] + [(conditional e0 e1 e2) + (make-conditional (E e0 ref comp) (E e1 ref comp) (E e2 ref comp))] + [(seq e0 e1) (make-seq (E e0 ref comp) (E e1 ref comp))] + [(clambda cls*) + (make-clambda + (map (lambda (x) + (record-case x + [(clambda-case fml* proper body) + (let ([h (make-hash-table)]) + (let ([body (E body (extend-hash fml* h ref) void)]) + (make-clambda-case fml* proper body)))])) + cls*))] + [(primcall rator rand*) + (when (memq rator '(call/cc call/cf)) + (comp)) + (make-primcall rator (E* rand* ref comp))] + [(funcall rator rand*) + (let ([rator (E rator ref comp)] [rand* (E* rand* ref comp)]) + (record-case rator + [(primref op) + (when (memq op '(call/cc call/cf)) + (comp))] + [else + (comp)]) + (make-funcall rator rand*))] + [(appcall rator rand*) + (let ([rator (E rator ref comp)] [rand* (E* rand* ref comp)]) + (record-case rator + [(primref op) + (when (memq op '(call/cc call/cf)) + (comp))] + [else + (comp)]) + (make-appcall rator rand*))] + [(forcall rator rand*) + (make-forcall rator (E* rand* ref comp))] + [else (error who "invalid expression ~s" (unparse x))])) + (E x (lambda (x) (error who "free var ~s found" x)) + void)) + + +(define (remove-letrec x) + (define who 'remove-letrec) + (define (Expr x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Expr body))] + [(recbind lhs* rhs* body) + (let ([t* (map (lambda (lhs) (unique-var 'tmp)) lhs*)] + [v* (map (lambda (lhs) (make-primcall 'void '())) lhs*)]) + (make-bind lhs* v* + (make-bind t* (map Expr rhs*) + (let f ([lhs* lhs*] [t* t*]) + (cond + [(null? lhs*) (Expr body)] + [else + (make-seq + (make-assign (car lhs*) (car t*)) + (f (cdr lhs*) (cdr t*)))])))))] + ;[(fix lhs* rhs* body) + ; (Expr (make-recbind lhs* rhs* body))] + [(fix lhs* rhs* body) + (make-fix lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional + (Expr test) + (Expr conseq) + (Expr altern))] + [(seq e0 e1) + (make-seq (Expr e0) (Expr e1))] + [(clambda cls*) + (make-clambda + (map (lambda (x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (Expr body))])) + cls*))] + [(primcall rator rand*) + (make-primcall rator (map Expr rand*))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall rator rand*) + (make-appcall (Expr rator) (map Expr rand*))] + [(forcall rator rand*) + (make-forcall rator (map Expr rand*))] + [(assign lhs rhs) + (make-assign lhs (Expr rhs))] + [else (error who "invalid expression ~s" (unparse x))])) + (Expr x)) + + + +(define (uncover-assigned x) + (define who 'uncover-assigned) + (define (Expr* x*) + (for-each Expr x*)) + (define (Expr x) + (record-case x + [(constant) (void)] + [(var) (void)] + [(primref) (void)] + [(bind lhs* rhs* body) + (begin (Expr body) (Expr* rhs*))] + [(recbind lhs* rhs* body) + (begin (Expr body) (Expr* rhs*))] + [(fix lhs* rhs* body) + (Expr* rhs*) + (Expr body) + (when (ormap var-assigned lhs*) + (error 'uncover-assigned "a fix lhs is assigned"))] + [(conditional test conseq altern) + (begin (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (begin (Expr e0) (Expr e1))] + [(clambda cls*) + (for-each + (lambda (cls) + (Expr (clambda-case-body cls))) + cls*)] + [(primcall rator rand*) (Expr* rand*)] + [(funcall rator rand*) + (begin (Expr rator) (Expr* rand*))] + [(appcall rator rand*) + (begin (Expr rator) (Expr* rand*))] + [(forcall rator rand*) (Expr* rand*)] + [(assign lhs rhs) + (set-var-assigned! lhs #t) + (Expr rhs)] + [else (error who "invalid expression ~s" (unparse x))])) + (Expr x)) + + + +(define (rewrite-assignments x) + (define who 'rewrite-assignments) + (define (fix-lhs* lhs*) + (cond + [(null? lhs*) (values '() '() '())] + [else + (let ([x (car lhs*)]) + (let-values ([(lhs* a-lhs* a-rhs*) (fix-lhs* (cdr lhs*))]) + (cond + [(var-assigned x) + (let ([t (unique-var 'assignment-tmp)]) + (values (cons t lhs*) (cons x a-lhs*) (cons t a-rhs*)))] + [else + (values (cons x lhs*) a-lhs* a-rhs*)])))])) + (define (bind-assigned lhs* rhs* body) + (cond + [(null? lhs*) body] + [else + (make-bind lhs* + (map (lambda (rhs) (make-primcall 'vector (list rhs))) rhs*) + body)])) + (define (Expr x) + (record-case x + [(constant) x] + [(var) + (cond + [(var-assigned x) + (make-primcall '$vector-ref (list x (make-constant 0)))] + [else x])] + [(primref) x] + [(bind lhs* rhs* body) + (let-values ([(lhs* a-lhs* a-rhs*) (fix-lhs* lhs*)]) + (make-bind lhs* (map Expr rhs*) + (bind-assigned a-lhs* a-rhs* (Expr body))))] + [(fix lhs* rhs* body) + (make-fix lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (make-seq (Expr e0) (Expr e1))] + [(clambda cls*) + (make-clambda + (map (lambda (cls) + (record-case cls + [(clambda-case fml* proper body) + (let-values ([(fml* a-lhs* a-rhs*) (fix-lhs* fml*)]) + (make-clambda-case fml* proper + (bind-assigned a-lhs* a-rhs* (Expr body))))])) + cls*))] + [(primcall op rand*) + (make-primcall op (map Expr rand*))] + [(forcall op rand*) + (make-forcall op (map Expr rand*))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall rator rand*) + (make-appcall (Expr rator) (map Expr rand*))] + [(assign lhs rhs) + (unless (var-assigned lhs) + (error 'rewrite-assignments "not assigned ~s in ~s" lhs x)) + (make-primcall '$vector-set! (list lhs (make-constant 0) (Expr rhs)))] + [else (error who "invalid expression ~s" (unparse x))])) + (Expr x)) + + +(define (remove-assignments x) + (uncover-assigned x) + (rewrite-assignments x)) + + + + + +(define (convert-closures prog) + (define who 'convert-closures) + (define (Expr* x*) + (cond + [(null? x*) (values '() '())] + [else + (let-values ([(a a-free) (Expr (car x*))] + [(d d-free) (Expr* (cdr x*))]) + (values (cons a d) (union a-free d-free)))])) + (define (do-clambda* x*) + (cond + [(null? x*) (values '() '())] + [else + (let-values ([(a a-free) (do-clambda (car x*))] + [(d d-free) (do-clambda* (cdr x*))]) + (values (cons a d) (union a-free d-free)))])) + (define (do-clambda x) + (record-case x + [(clambda cls*) + (let-values ([(cls* free) + (let f ([cls* cls*]) + (cond + [(null? cls*) (values '() '())] + [else + (record-case (car cls*) + [(clambda-case fml* proper body) + (let-values ([(body body-free) (Expr body)] + [(cls* cls*-free) (f (cdr cls*))]) + (values + (cons (make-clambda-case fml* proper body) + cls*) + (union (difference body-free fml*) + cls*-free)))])]))]) + (values (make-closure (make-clambda-code (gensym) cls* free) free) + free))])) + (define (Expr ex) + (record-case ex + [(constant) (values ex '())] + [(var) (values ex (singleton ex))] + [(primref) (values ex '())] + [(bind lhs* rhs* body) + (let-values ([(rhs* rhs-free) (Expr* rhs*)] + [(body body-free) (Expr body)]) + (values (make-bind lhs* rhs* body) + (union rhs-free (difference body-free lhs*))))] + [(fix lhs* rhs* body) + (let-values ([(rhs* rfree) (do-clambda* rhs*)] + [(body bfree) (Expr body)]) + (values (make-fix lhs* rhs* body) + (difference (union bfree rfree) lhs*)))] + [(conditional test conseq altern) + (let-values ([(test test-free) (Expr test)] + [(conseq conseq-free) (Expr conseq)] + [(altern altern-free) (Expr altern)]) + (values (make-conditional test conseq altern) + (union test-free (union conseq-free altern-free))))] + [(seq e0 e1) + (let-values ([(e0 e0-free) (Expr e0)] + [(e1 e1-free) (Expr e1)]) + (values (make-seq e0 e1) (union e0-free e1-free)))] + [(clambda) + (do-clambda ex)] + [(primcall op rand*) + (let-values ([(rand* rand*-free) (Expr* rand*)]) + (values (make-primcall op rand*) rand*-free))] + [(forcall op rand*) + (let-values ([(rand* rand*-free) (Expr* rand*)]) + (values (make-forcall op rand*) rand*-free))] + [(funcall rator rand*) + (let-values ([(rator rat-free) (Expr rator)] + [(rand* rand*-free) (Expr* rand*)]) + (values (make-funcall rator rand*) + (union rat-free rand*-free)))] + [(appcall rator rand*) + (let-values ([(rator rat-free) (Expr rator)] + [(rand* rand*-free) (Expr* rand*)]) + (values (make-appcall rator rand*) + (union rat-free rand*-free)))] + [else (error who "invalid expression ~s" (unparse ex))])) + (let-values ([(prog free) (Expr prog)]) + (unless (null? free) + (error 'convert-closures "free vars ~s encountered in ~a" + free (unparse prog))) + prog)) + + +(define (lift-codes x) + (define who 'lift-codes) + (define all-codes '()) + (define (do-code x) + (record-case x + [(clambda-code label cls* free) + (let ([cls* (map + (lambda (x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (E body))])) + cls*)]) + (let ([g (make-code-loc label)]) + (set! all-codes + (cons (make-clambda-code label cls* free) all-codes)) + g))])) + (define (E x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(bind lhs* rhs* body) + (make-bind lhs* (map E rhs*) (E body))] + [(fix lhs* rhs* body) + (make-fix lhs* (map E rhs*) (E body))] + [(conditional test conseq altern) + (make-conditional (E test) (E conseq) (E altern))] + [(seq e0 e1) (make-seq (E e0) (E e1))] + [(closure c free) (make-closure (do-code c) free)] + [(primcall op rand*) (make-primcall op (map E rand*))] + [(forcall op rand*) (make-forcall op (map E rand*))] + [(funcall rator rand*) (make-funcall (E rator) (map E rand*))] + [(appcall rator rand*) (make-appcall (E rator) (map E rand*))] + [else (error who "invalid expression ~s" (unparse x))])) + (let ([x (E x)]) + (make-codes all-codes x))) + + + + +(define (syntactically-valid? op rand*) + (define (valid-arg-count? op rand*) + (let ([n (open-coded-primitive-args op)] [m (length rand*)]) + (cond + [(eq? n 'any) #t] + [(eq? n 'positive) (fx> m 1)] + [(eq? n 'no-code) + (error 'syntactically-valid + "should not primcall non codable prim ~s" op)] + [(fixnum? n) + (cond + [(fx= n m) #t] + [else + (error 'compile + "Possible incorrect number of args in ~s" + (cons op (map unparse rand*))) + #f])] + [else (error 'do-primcall "BUG: what ~s" n)]))) + (define (check op pred?) + (lambda (arg) + (record-case arg + [(constant c) + (cond + [(pred? c) #t] + [else + (error 'compile "Possible argument error to primitive ~s" op) + #f])] + [(primref) + (cond + [(pred? (lambda (x) x)) #t] + [else + (error 'compile "Possible argument error to primitive ~s" op) + #f])] + [else #t]))) + (define (nonnegative-fixnum? n) + (and (fixnum? n) (fx>= n 0))) + (define (byte? n) + (and (fixnum? n) (fx<= 0 n) (fx<= n 127))) + (define (valid-arg-types? op rand*) + (case op + [(fixnum? immediate? boolean? char? vector? string? procedure? + null? pair? not cons eq? vector symbol? error eof-object eof-object? + void $unbound-object? $code? $forward-ptr? bwp-object? + pointer-value top-level-value car cdr list* list $record) + '#t] + [($fxadd1 $fxsub1 $fxzero? $fxlognot $fxlogor $fxlogand $fx+ $fx- $fx* + $fx= $fx< $fx<= $fx> $fx>= $fxquotient $fxmodulo $fxsll $fxsra $fxlogxor $exit) + (andmap (check op fixnum?) rand*)] + [($fixnum->char) + (andmap (check op byte?) rand*)] + [($char->fixnum $char= $char< $char<= $char> $char>= $string) + (andmap (check op char?) rand*)] + [($make-vector $make-string) + (andmap (check op nonnegative-fixnum?) rand*)] + [($car $cdr) + (andmap (check op pair?) rand*)] + [($vector-length) + (andmap (check op vector?) rand*)] + [($string-length) + (andmap (check op string?) rand*)] + [($set-car! $set-cdr!) + ((check op pair?) (car rand*))] + [($vector-ref $vector-set!) + (and ((check op vector?) (car rand*)) + ((check op nonnegative-fixnum?) (cadr rand*)))] + [($string-ref $string-set! + $string-ref-16+0 $string-ref-16+1 $string-ref-8+0 $string-ref-8+2) + (and ((check op string?) (car rand*)) + ((check op nonnegative-fixnum?) (cadr rand*)))] + [($symbol-string $symbol-unique-string) + (andmap (check op symbol?) rand*)] + [($constant-ref $set-constant! $intern $pcb-set! $pcb-ref $make-symbol + $symbol-value $set-symbol-value! $symbol-plist $set-symbol-plist! + $set-symbol-system-value! $set-symbol-system-value! + $set-symbol-unique-string! + $set-symbol-string! + $seal-frame-and-call $frame->continuation $code->closure + $code-size $code-reloc-vector $code-freevars + $code-ref $code-set! + $make-record $record? $record/rtd? $record-rtd $record-ref $record-set! + primitive-set! primitive-ref + $make-tcbucket $tcbucket-key $tcbucket-val $tcbucket-next + $set-tcbucket-val! $set-tcbucket-next! $set-tcbucket-tconc!) + #t] + [else (error 'valid-arg-types? "unhandled op ~s" op)])) + (and (valid-arg-count? op rand*) + (or (null? rand*) + (valid-arg-types? op rand*)))) + + +;;; the output of simplify-operands differs from the input in that the +;;; operands to primcalls are all simple (variables, primrefs, or constants). +;;; funcalls to open-codable primrefs whos arguments are "ok" are converted to +;;; primcalls. + + +(define uninlined '()) +(define (mark-uninlined x) + (cond + [(assq x uninlined) => + (lambda (p) (set-cdr! p (fxadd1 (cdr p))))] + [else (set! uninlined (cons (cons x 1) uninlined))])) + +(module () + (primitive-set! 'uninlined-stats + (lambda () + (let f ([ls uninlined] [ac '()]) + (cond + [(null? ls) ac] + [(fx> (cdar ls) 15) + (f (cdr ls) (cons (car ls) ac))] + [else (f (cdr ls) ac)]))))) + +(define (introduce-primcalls x) + (define who 'introduce-primcalls) + (define (simple? x) + (or (constant? x) (var? x) (primref? x))) + (define (Expr x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(closure) x] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Expr body))] + [(fix lhs* rhs* body) + (make-fix lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (make-seq (Expr e0) (Expr e1))] + [(primcall op arg*) + (case op + ;[(values) + ; (if (fx= (length arg*) 1) + ; (Expr (car arg*)) + ; (begin + ; (warning 'compile "possible incorrect number of values") + ; (make-funcall (make-primref 'values) (map Expr arg*))))] + [else + (make-primcall op (map Expr arg*))])] + [(forcall op arg*) + (make-forcall op (map Expr arg*))] + [(funcall rator rand*) + (cond + [(and (primref? rator) + (open-codeable? (primref-name rator)) + (syntactically-valid? (primref-name rator) rand*)) + (Expr (make-primcall (primref-name rator) rand*))] + [else + (when (primref? rator) + (mark-uninlined (primref-name rator))) + (make-funcall (Expr rator) (map Expr rand*))])] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (Tail x) + (record-case x + [(constant) (make-return x)] + [(var) (make-return x)] + [(primref) (make-return x)] + [(closure) (make-return x)] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Tail body))] + [(fix lhs* rhs* body) + (make-fix lhs* (map Expr rhs*) (Tail body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Tail conseq) (Tail altern))] + [(seq e0 e1) (make-seq (Expr e0) (Tail e1))] + [(primcall op arg*) + (case op + ;[(values) + ; (if (fx= (length arg*) 1) + ; (make-return (Expr (car arg*))) + ; (make-return* (map Expr arg*)))] + [else + (make-return (make-primcall op (map Expr arg*)))])] + [(forcall op arg*) + (make-return (make-forcall op (map Expr arg*)))] + [(funcall rator rand*) + (cond + [(and (primref? rator) + (open-codeable? (primref-name rator)) + (syntactically-valid? (primref-name rator) rand*)) + (Tail (make-primcall (primref-name rator) rand*))] + [else + (make-funcall (Expr rator) (map Expr rand*))])] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (CaseExpr x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (Tail body))])) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (make-clambda-code L (map CaseExpr cases) free)])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) (Tail body))])) + (CodesExpr x)) + + +(define (simplify-operands x) + (define who 'simplify-operands) + (define (simple? x) + (or (constant? x) (var? x) (primref? x))) + (define (simplify arg lhs* rhs* k) + (if (simple? arg) + (k arg lhs* rhs*) + (let ([v (unique-var 'tmp)]) + (k v (cons v lhs*) (cons (Expr arg) rhs*))))) + (define (simplify* arg* lhs* rhs* k) + (cond + [(null? arg*) (k '() lhs* rhs*)] + [else + (simplify (car arg*) lhs* rhs* + (lambda (a lhs* rhs*) + (simplify* (cdr arg*) lhs* rhs* + (lambda (d lhs* rhs*) + (k (cons a d) lhs* rhs*)))))])) + (define (Expr x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(closure) x] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Expr body))] + [(fix lhs* rhs* body) + (make-fix lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (make-seq (Expr e0) (Expr e1))] + [(primcall op arg*) + (cond + [(memq op '(not car cdr)) + (make-primcall op (map Expr arg*))] + [else + (simplify* arg* '() '() + (lambda (arg* lhs* rhs*) + (make-bind^ lhs* rhs* + (make-primcall op arg*))))])] + [(forcall op arg*) + (make-forcall op (map Expr arg*))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (Tail x) + (record-case x + [(return v) (make-return (Expr v))] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Tail body))] + [(fix lhs* rhs* body) + (make-fix lhs* (map Expr rhs*) (Tail body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Tail conseq) (Tail altern))] + [(seq e0 e1) (make-seq (Expr e0) (Tail e1))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (CaseExpr x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (Tail body))])) + (define (CodeExpr x) + (record-case x + [(clambda-code L clauses free) + (make-clambda-code L (map CaseExpr clauses) free)])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) (Tail body))])) + (CodesExpr x)) + + +(define (insert-stack-overflow-checks x) + (define who 'insert-stack-overflow-checks) + (define (insert-check body) + (make-seq + (make-conditional + (make-primcall '$fp-overflow '()) + (make-funcall (make-primref 'do-stack-overflow) '()) + (make-primcall 'void '())) + body)) + (define (Expr x) + (record-case x + [(constant) #f] + [(var) #f] + [(primref) #f] + [(closure code free*) #f] + [(bind lhs* rhs* body) + (or (ormap Expr rhs*) (Expr body))] + [(fix lhs* rhs* body) (Expr body)] + [(conditional test conseq altern) + (or (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (or (Expr e0) (Expr e1))] + [(primcall op arg*) (ormap Expr arg*)] + [(forcall op arg*) (ormap Expr arg*)] + [(funcall rator arg*) #t] + [(appcall rator arg*) #t] + [else (error who "invalid expression ~s" (unparse x))])) + (define (Tail x) + (record-case x + [(return v) (Expr v)] + [(bind lhs* rhs* body) + (or (ormap Expr rhs*) (Tail body))] + [(fix lhs* rhs* body) (Tail body)] + [(conditional test conseq altern) + (or (Expr test) (Tail conseq) (Tail altern))] + [(seq e0 e1) (or (Expr e0) (Tail e1))] + [(funcall rator arg*) (or (Expr rator) (ormap Expr arg*))] + [(appcall rator arg*) (or (Expr rator) (ormap Expr arg*))] + [else (error who "invalid tail expression ~s" (unparse x))])) + (define (CaseExpr x) + (record-case x + [(clambda-case fml* proper body) + (if (Tail body) + (make-clambda-case fml* proper (insert-check body)) + x)])) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (make-clambda-code L (map CaseExpr cases) free)])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) + (if (Tail body) + (insert-check body) + body))])) + (CodesExpr x)) + + +(define (insert-allocation-checks x) + (define who 'insert-allocation-checks) + (define (check-bytes n var body) + (make-seq + (make-conditional + (make-primcall '$ap-check-bytes + (list (make-constant n) var)) + (make-forcall "ik_collect" ;(make-primref 'do-overflow) + (list + (make-primcall '$fx+ + (list (make-constant (fx+ n 4096)) var)))) + (make-primcall 'void '())) + body)) + (define (check-words n var body) + (make-seq + (make-conditional + (make-primcall '$ap-check-words + (list (make-constant n) var)) + (make-forcall "ik_collect" ; (make-primref 'do-overflow-words) + (list + (make-primcall '$fx+ + (list (make-constant (fx+ n 4096)) var)))) + (make-primcall 'void '())) + body)) + (define (check-const n body) + (make-seq + (make-conditional + (make-primcall '$ap-check-const + (list (make-constant n))) + (make-forcall "ik_collect" ;(make-primref 'do-overflow) + (list (make-constant (fx+ n 4096)))) + (make-primcall 'void '())) + body)) + (define (closure-size x) + (record-case x + [(closure code free*) + (align (fx+ disp-closure-data (fx* (length free*) wordsize)))] + [else (error 'closure-size "~s is not a closure" x)])) + (define (sum ac ls) + (cond + [(null? ls) ac] + [else (sum (fx+ ac (car ls)) (cdr ls))])) + (define (Expr x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(closure) + (check-const (closure-size x) x)] + [(fix lhs* rhs* body) + (if (null? lhs*) + (Expr body) + (check-const (sum 0 (map closure-size rhs*)) + (make-fix lhs* rhs* + (Expr body))))] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (make-seq (Expr e0) (Expr e1))] + [(primcall op arg*) + (let ([x (make-primcall op (map Expr arg*))]) + (case op + [(cons) (check-const pair-size x)] + [($make-symbol) (check-const symbol-size x)] + [($make-tcbucket) (check-const tcbucket-size x)] + [($frame->continuation $code->closure) + (check-const (fx+ disp-closure-data (fx* (length arg*) wordsize)) x)] + [($make-string) + (record-case (car arg*) + [(constant i) + (check-const (fx+ i (fx+ disp-string-data 1)) x)] + [else + (check-bytes (fxadd1 disp-string-data) (car arg*) x)])] + [($string) + (check-const (fx+ (length arg*) (fx+ disp-string-data 1)) x)] + [($make-vector) + (record-case (car arg*) + [(constant i) + (check-const (fx+ (fx* i wordsize) disp-vector-data) x)] + [else + (check-words (fxadd1 disp-vector-data) (car arg*) x)])] + [($make-record) + (record-case (cadr arg*) + [(constant i) + (check-const (fx+ (fx* i wordsize) disp-record-data) x)] + [else + (check-words (fxadd1 disp-record-data) (cadr arg*) x)])] + [(list*) + (check-const (fx* (fxsub1 (length arg*)) pair-size) x)] + [(list) + (check-const (fx* (length arg*) pair-size) x)] + [(vector $record) + (check-const (fx+ (fx* (length arg*) wordsize) disp-vector-data) x)] + [else x]))] + [(forcall op arg*) + (make-forcall op (map Expr arg*))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (Tail x) + (record-case x + [(return v) (make-return (Expr v))] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Tail body))] + [(fix lhs* rhs* body) + (if (null? lhs*) + (Tail body) + (check-const (sum 0 (map closure-size rhs*)) + (make-fix lhs* rhs* + (Tail body))))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Tail conseq) (Tail altern))] + [(seq e0 e1) (make-seq (Expr e0) (Tail e1))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (CaseExpr x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (Tail body))])) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (make-clambda-code L (map CaseExpr cases) free)])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) (Tail body))])) + (CodesExpr x)) + + + +(define (remove-local-variables x) + (define who 'remove-local-variables) + (define (simple* x* r) + (map (lambda (x) + (cond + [(assq x r) => cdr] + [else + (when (var? x) (error who "unbound var ~s" x)) + x])) + x*)) + (define (env->mask r sz) + (let ([s (make-vector (fxsra (fx+ sz 7) 3) 0)]) + (for-each + (lambda (idx) + (let ([q (fxsra idx 3)] + [r (fxlogand idx 7)]) + (vector-set! s q + (fxlogor (vector-ref s q) (fxsll 1 r))))) + r) + s)) + (define (check? x) + (cond + [(primref? x) #f] ;;;; PRIMREF CHECK + [else #t])) + (define (do-new-frame op rand* si r call-convention rp-convention orig-live) + (make-new-frame (fxadd1 si) (fx+ (length rand*) 2) + (let f ([r* rand*] [nsi (fx+ si 2)] [live orig-live]) + (cond + [(null? r*) + (make-seq + (make-seq + (make-save-cp (make-frame-var si)) + (case call-convention + [(normal apply) + (make-eval-cp (check? op) (Expr op nsi r (cons si live)))] + [(foreign) + (make-eval-cp #f (make-foreign-label op))] + [else (error who "invalid convention ~s" call-convention)])) + (make-call-cp call-convention + rp-convention + (fxadd1 si) ; frame size + (length rand*) ; argc + (env->mask (cons si orig-live) ; cp and everything before it + (fxadd1 si))))] ; mask-size ~~ frame size + [else + (make-seq + (make-assign (make-frame-var nsi) + (Expr (car r*) nsi r live)) + (f (cdr r*) (fxadd1 nsi) (cons nsi live)))])))) + (define (nop) (make-primcall 'void '())) + (define (do-bind lhs* rhs* body si r live k) + (let f ([lhs* lhs*] [rhs* rhs*] [si si] [nr r] [live live]) + (cond + [(null? lhs*) (k body si nr live)] + [else + (let ([v (make-frame-var si)]) + (make-seq + (make-assign v (Expr (car rhs*) si r live)) + (f (cdr lhs*) (cdr rhs*) (fxadd1 si) + (cons (cons (car lhs*) v) nr) + (cons si live))))]))) + (define (do-closure r) + (lambda (x) + (record-case x + [(closure code free*) + (make-closure code (simple* free* r))]))) + (define (do-fix lhs* rhs* body si r live k) + (let f ([l* lhs*] [nlhs* '()] [si si] [r r] [live live]) + (cond + [(null? l*) + (make-fix (reverse nlhs*) + (map (do-closure r) rhs*) + (k body si r live))] + [else + (let ([v (make-frame-var si)]) + (f (cdr l*) (cons v nlhs*) (fxadd1 si) + (cons (cons (car l*) v) r) + (cons si live)))]))) + (define (do-tail-frame-old op rand* si r call-conv live) + (define (const? x) + (record-case x + [(constant) #t] + [(primref) #t] + [else #f])) + (define (evalrand* rand* i si r live) + (cond + [(null? rand*) + (make-eval-cp (check? op) (Expr op si r live))] + [(const? (car rand*)) + (evalrand* (cdr rand*) (fxadd1 i) (fxadd1 si) r live)] + [else + (let ([v (make-frame-var si)] + [rhs (Expr (car rand*) si r live)]) + (cond + [(and (frame-var? rhs) + (fx= (frame-var-idx rhs) i)) + (evalrand* (cdr rand*) (fx+ i 1) (fx+ si 1) r (cons si live))] + [else + (make-seq + (make-assign v rhs) + (evalrand* (cdr rand*) (fx+ 1 i) (fx+ 1 si) r + (cons si live)))]))])) + (define (moverand* rand* i si ac) + (cond + [(null? rand*) ac] + [(const? (car rand*)) + (make-seq + (make-assign (make-frame-var i) (car rand*)) + (moverand* (cdr rand*) (fxadd1 i) (fxadd1 si) ac))] + [else + (make-seq + (make-assign (make-frame-var i) (make-frame-var si)) + (moverand* (cdr rand*) (fxadd1 i) (fxadd1 si) ac))])) + (make-seq + (evalrand* rand* 1 si r live) + (moverand* rand* 1 si + (make-tailcall-cp call-conv (length rand*))))) + (define (do-tail-frame op rand* si r call-conv live) + (define (const? x) + (record-case x + [(constant) #t] + [(primref) #t] + [else #f])) + (define (evalrand* rand* i si r live ac) + (cond + [(null? rand*) + (make-seq + (make-eval-cp (check? op) (Expr op si r live)) + ac)] + [(const? (car rand*)) + (evalrand* (cdr rand*) (fxadd1 i) (fxadd1 si) r live + (make-seq ac + (make-assign (make-frame-var i) (car rand*))))] + [else + (let ([vsi (make-frame-var si)] + [rhs (Expr (car rand*) si r live)]) + (cond + [(and (frame-var? rhs) + (fx= (frame-var-idx rhs) i)) + (evalrand* (cdr rand*) (fx+ i 1) (fx+ si 1) r (cons si live) ac)] + [(fx= i si) + (make-seq + (make-assign vsi rhs) + (evalrand* (cdr rand*) (fx+ i 1) (fx+ si 1) r + (cons si live) ac))] + [else + (make-seq + (make-assign vsi rhs) + (evalrand* (cdr rand*) (fxadd1 i) (fxadd1 si) r (cons si live) + (make-seq ac + (make-assign (make-frame-var i) vsi))))]))])) + (make-seq + (evalrand* rand* 1 si r live (make-primcall 'void '())) + (make-tailcall-cp call-conv (length rand*)))) + (define (Tail x si r live) + (record-case x + [(return v) (make-return (Expr v si r live))] + [(bind lhs* rhs* body) + (do-bind lhs* rhs* body si r live Tail)] + [(fix lhs* rhs* body) + (do-fix lhs* rhs* body si r live Tail)] + [(conditional test conseq altern) + (make-conditional + (Expr test si r live) + (Tail conseq si r live) + (Tail altern si r live))] + [(seq e0 e1) (make-seq (Effect e0 si r live) (Tail e1 si r live))] + [(primcall op arg*) + (make-return + (make-primcall op + (map (lambda (x) (Expr x si r live)) arg*)))] + + [(funcall op rand*) + (do-tail-frame op rand* si r 'normal live)] + [(appcall op rand*) + (do-tail-frame op rand* si r 'apply live)] +;;; [(funcall op rand*) +;;; (do-new-frame op rand* si r 'normal 'tail live)] +;;; [(appcall op rand*) +;;; (do-new-frame op rand* si r 'apply 'tail live)] + [else (error who "invalid expression ~s" (unparse x))])) + (define (Effect x si r live) + (record-case x + [(constant) (nop)] + [(var) (nop)] + [(primref) (nop)] + [(closure code free*) (nop)] + [(bind lhs* rhs* body) + (do-bind lhs* rhs* body si r live Effect)] + [(fix lhs* rhs* body) + (do-fix lhs* rhs* body si r live Effect)] + [(conditional test conseq altern) + (make-conditional + (Expr test si r live) + (Effect conseq si r live) + (Effect altern si r live))] + [(seq e0 e1) (make-seq (Effect e0 si r live) (Effect e1 si r live))] + [(primcall op arg*) + (make-primcall op + (map (lambda (x) (Expr x si r live)) arg*))] + [(forcall op rand*) + (do-new-frame op rand* si r 'foreign 'effect live)] + [(funcall op rand*) + (do-new-frame op rand* si r 'normal 'effect live)] + [(appcall op rand*) + (do-new-frame op rand* si r 'apply 'effect live)] + [else (error who "invalid effect expression ~s" (unparse x))])) + (define (Expr x si r live) + (record-case x + [(constant) x] + [(var) + (cond + [(assq x r) => cdr] + [else (error who "unbound var ~s" x)])] + [(primref) x] + [(closure code free*) + (make-closure code (simple* free* r))] + [(bind lhs* rhs* body) + (do-bind lhs* rhs* body si r live Expr)] + [(fix lhs* rhs* body) + (do-fix lhs* rhs* body si r live Expr)] + [(conditional test conseq altern) + (make-conditional + (Expr test si r live) + (Expr conseq si r live) + (Expr altern si r live))] + [(seq e0 e1) (make-seq (Effect e0 si r live) (Expr e1 si r live))] + [(primcall op arg*) + (make-primcall op + (map (lambda (x) (Expr x si r live)) arg*))] + [(forcall op rand*) + (do-new-frame op rand* si r 'foreign 'value live)] + [(funcall op rand*) + (do-new-frame op rand* si r 'normal 'value live)] + [(appcall op rand*) + (do-new-frame op rand* si r 'apply 'value live)] + [else (error who "invalid expression ~s" (unparse x))])) + (define (bind-fml* fml* r) + (let f ([si 1] [fml* fml*]) + (cond + [(null? fml*) (values '() si r '())] + [else + (let-values ([(nfml* nsi r live) (f (fxadd1 si) (cdr fml*))]) + (let ([v (make-frame-var si)]) + (values (cons v nfml*) + nsi + (cons (cons (car fml*) v) r) + (cons si live))))]))) + (define (bind-free* free*) + (let f ([free* free*] [idx 0] [r '()]) + (cond + [(null? free*) r] + [else + (f (cdr free*) (fxadd1 idx) + (cons (cons (car free*) (make-cp-var idx)) r))]))) + (define CaseExpr + (lambda (r) + (lambda (x) + (record-case x + [(clambda-case fml* proper body) + (let-values ([(fml* si r live) (bind-fml* fml* r)]) + (make-clambda-case fml* proper (Tail body si r live)))])))) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (let ([r (bind-free* free)]) + (make-clambda-code L (map (CaseExpr r) cases) free))])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) + (Tail body 1 '() '()))])) + (CodesExpr x)) + + + +(define checks-elim-count 0) +(define (optimize-ap-check x) + (define who 'optimize-ap-check) + (define (min x y) + (if (fx< x y) x y)) + (define (Tail x f) + (record-case x + [(return v) + (let-values ([(v f) (NonTail v f)]) + (make-return v))] + [(fix lhs* rhs* body) + (make-fix lhs* rhs* (Tail body f))] + [(conditional test conseq altern) + (let-values ([(test f) (NonTail test f)]) + (make-conditional + test + (Tail conseq f) + (Tail altern f)))] + [(seq e0 e1) + (let-values ([(e0 f) (NonTail e0 f)]) + (make-seq e0 (Tail e1 f)))] + [(tailcall-cp) x] + [else (error who "invalid tail expression ~s" (unparse x))])) + (define (do-primcall op arg* f) + (case op + [($ap-check-const) + (let ([n (constant-value (car arg*))]) + (cond + [(fx< n f) + ;(set! checks-elim-count (fxadd1 checks-elim-count)) + ;(printf "~s checks eliminated\n" checks-elim-count) + (values (make-constant #f) (fx- f n))] + [(fx<= n 4096) + (values (make-primcall '$ap-check-const + (list (make-constant 4096))) + (fx- 4096 n))] + [else + (values (make-primcall '$ap-check-const + (list (make-constant (fx+ n 4096)))) + 4096)]))] + [($ap-check-bytes $ap-check-words) + (values (make-primcall op + (list (make-constant (fx+ (constant-value (car arg*)) + 4096)) + (cadr arg*))) + 4096)] + [else (values (make-primcall op arg*) f)])) + (define (NonTail x f) + (record-case x + [(constant) (values x f)] + [(frame-var) (values x f)] + [(cp-var) (values x f)] + [(save-cp) (values x f)] + [(foreign-label) (values x f)] + [(primref) (values x f)] + [(closure) (values x f)] + [(call-cp call-conv) + (if (eq? call-conv 'foreign) + (values x f) + (values x 0))] + [(primcall op arg*) (do-primcall op arg* f)] + [(fix lhs* rhs* body) + (let-values ([(body f) (NonTail body f)]) + (values (make-fix lhs* rhs* body) f))] + [(conditional test conseq altern) + (let-values ([(test f) (NonTail test f)]) + (if (constant? test) + (if (constant-value test) + (NonTail conseq f) + (NonTail altern f)) + (let-values ([(conseq f0) (NonTail conseq f)] + [(altern f1) (NonTail altern f)]) + (values (make-conditional test conseq altern) + (min f0 f1)))))] + [(seq e0 e1) + (let-values ([(e0 f) (NonTail e0 f)]) + (let-values ([(e1 f) (NonTail e1 f)]) + (values (make-seq e0 e1) f)))] + [(assign lhs rhs) + (let-values ([(rhs f) (NonTail rhs f)]) + (values (make-assign lhs rhs) f))] + [(eval-cp check body) + (let-values ([(body f) (NonTail body f)]) + (values (make-eval-cp check body) f))] + [(new-frame base-idx size body) + (let-values ([(body f) (NonTail body f)]) + (values (make-new-frame base-idx size body) f))] + [else (error who "invalid nontail expression ~s" (unparse x))])) + (define CaseExpr + (lambda (x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (Tail body 0))]))) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (make-clambda-code L (map CaseExpr cases) free)])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) + (Tail body 0))])) + (CodesExpr x)) + +(begin + (define fx-shift 2) + (define fx-mask #x03) + (define fx-tag 0) + (define bool-f #x2F) + (define bool-t #x3F) + (define bool-mask #xEF) + (define bool-tag #x2F) + (define bool-shift 4) + (define nil #x4F) + (define eof #x5F) ; double check + (define unbound #x6F) ; double check + (define void-object #x7F) ; double check + (define bwp-object #x8F) ; double check + (define char-shift 8) + (define char-tag #x0F) + (define char-mask #xFF) + (define pair-mask 7) + (define pair-tag 1) + (define disp-car 0) + (define disp-cdr 4) + (define pair-size 8) + (define pagesize 4096) + (define pageshift 12) + (define wordsize 4) + (define wordshift 2) + + (define symbol-mask 7) + (define symbol-tag 2) + (define disp-symbol-string 0) + (define disp-symbol-unique-string 4) + (define disp-symbol-value 8) + (define disp-symbol-plist 12) + (define disp-symbol-system-value 16) + (define disp-symbol-system-plist 20) + (define symbol-size 24) + (define vector-tag 5) + (define vector-mask 7) + (define disp-vector-length 0) + (define disp-vector-data 4) + (define string-mask 7) + (define string-tag 6) + (define disp-string-length 0) + (define disp-string-data 4) + (define closure-mask 7) + (define closure-tag 3) + (define disp-closure-data 4) + (define disp-closure-code 0) + (define continuation-size 16) + (define continuation-tag #x1F) + (define disp-continuation-top 4) + (define disp-continuation-size 8) + (define disp-continuation-next 12) + (define code-tag #x2F) + (define disp-code-instrsize 4) + (define disp-code-relocsize 8) + (define disp-code-freevars 12) + (define disp-code-data 16) + (define disp-tcbucket-tconc 0) + (define disp-tcbucket-key 4) + (define disp-tcbucket-val 8) + (define disp-tcbucket-next 12) + (define tcbucket-size 16) + (define record-ptag 5) + (define record-pmask 7) + (define disp-record-rtd 0) + (define disp-record-data 4) + (define disp-frame-size -17) + (define disp-frame-offset -13) + (define disp-multivalue-rp -9) + (define object-alignment 8) + (define align-shift 3) + (define dirty-word -1)) + +(define (align n) + (fxsll (fxsra (fx+ n (fxsub1 object-alignment)) align-shift) align-shift)) + +(begin + (define (mem off val) + (cond + [(fixnum? off) (list 'disp (int off) val)] + [(register? off) (list 'disp off val)] + [else (error 'mem "invalid disp ~s" off)])) + (define (int x) (list 'int x)) + (define (obj x) (list 'obj x)) + (define (byte x) (list 'byte x)) + (define (byte-vector x) (list 'byte-vector x)) + (define (movzbl src targ) (list 'movzbl src targ)) + (define (sall src targ) (list 'sall src targ)) + (define (sarl src targ) (list 'sarl src targ)) + (define (shrl src targ) (list 'shrl src targ)) + (define (notl src) (list 'notl src)) + (define (pushl src) (list 'pushl src)) + (define (popl src) (list 'popl src)) + (define (orl src targ) (list 'orl src targ)) + (define (xorl src targ) (list 'xorl src targ)) + (define (andl src targ) (list 'andl src targ)) + (define (movl src targ) (list 'movl src targ)) + (define (movb src targ) (list 'movb src targ)) + (define (addl src targ) (list 'addl src targ)) + (define (imull src targ) (list 'imull src targ)) + (define (idivl src) (list 'idivl src)) + (define (subl src targ) (list 'subl src targ)) + (define (push src) (list 'push src)) + (define (pop targ) (list 'pop targ)) + (define (sete targ) (list 'sete targ)) + (define (call targ) (list 'call targ)) + (define (tail-indirect-cpr-call) + (jmp (mem (fx- disp-closure-code closure-tag) cpr))) + (define (indirect-cpr-call) + (call (mem (fx- disp-closure-code closure-tag) cpr))) + (define (negl targ) (list 'negl targ)) + (define (label x) (list 'label x)) + (define (label-address x) (list 'label-address x)) + (define (ret) '(ret)) + (define (cltd) '(cltd)) + (define (cmpl arg1 arg2) (list 'cmpl arg1 arg2)) + (define (je label) (list 'je label)) + (define (jne label) (list 'jne label)) + (define (jle label) (list 'jle label)) + (define (jge label) (list 'jge label)) + (define (jg label) (list 'jg label)) + (define (jl label) (list 'jl label)) + (define (jb label) (list 'jb label)) + (define (ja label) (list 'ja label)) + (define (jmp label) (list 'jmp label)) + (define edi '%edx) ; closure pointer + (define esi '%esi) ; pcb + (define ebp '%ebp) ; allocation pointer + (define esp '%esp) ; stack base pointer + (define al '%al) + (define ah '%ah) + (define bh '%bh) + (define cl '%cl) + (define eax '%eax) + (define ebx '%ebx) + (define ecx '%ecx) + (define edx '%edx) + (define apr '%ebp) + (define fpr '%esp) + (define cpr '%edi) + (define pcr '%esi) + (define register? symbol?) + (define (argc-convention n) + (fx- 0 (fxsll n fx-shift)))) + + +(define pcb-ref + (lambda (x) + (case x + [(allocation-pointer) (mem 0 pcr)] + [(allocation-redline) (mem 4 pcr)] + [(frame-pointer) (mem 8 pcr)] + [(frame-base) (mem 12 pcr)] + [(frame-redline) (mem 16 pcr)] + [(next-continuation) (mem 20 pcr)] + [(system-stack) (mem 24 pcr)] + [(dirty-vector) (mem 28 pcr)] + [else (error 'pcb-ref "invalid arg ~s" x)]))) + +(define (primref-loc op) + (unless (symbol? op) (error 'primref-loc "not a symbol ~s" op)) + (mem (fx- disp-symbol-system-value symbol-tag) + (obj op))) + + +(define (generate-code x) + (define who 'generate-code) + (define (rp-label x) + (case x + [(value) (label-address SL_multiple_values_error_rp)] + [(effect) (label-address SL_multiple_values_ignore_rp)] + [else (error who "invalid rp-convention ~s" x)])) + (define unique-label + (lambda () + (label (gensym)))) + (define (constant-val x) + (cond + [(fixnum? x) (obj x)] + [(boolean? x) (int (if x bool-t bool-f))] + [(null? x) (int nil)] + [(char? x) (int (fx+ (fxsll (char->integer x) char-shift) char-tag))] + [(eq? x (void)) (int void-object)] + [else (obj x)])) + (define (cond-branch op Lt Lf ac) + (define (opposite x) + (cadr (assq x '([je jne] [jl jge] [jle jg] [jg jle] [jge jl])))) + (unless (or Lt Lf) + (error 'cond-branch "no labels")) + (cond + [(not Lf) (cons (list op Lt) ac)] + [(not Lt) (cons (list (opposite op) Lf) ac)] + [else (list* (list op Lt) (jmp Lf) ac)])) + (define (indirect-type-pred pri-mask pri-tag sec-mask sec-tag rand* Lt Lf ac) + (cond + [(and Lt Lf) + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int pri-mask) ebx) + (cmpl (int pri-tag) ebx) + (jne Lf) + (movl (mem (fx- 0 pri-tag) eax) ebx) + (if sec-mask + (andl (int sec-mask) ebx) + '(nop)) + (cmpl (int sec-tag) ebx) + (jne Lf) + (jmp Lt) + ac)] + [Lf + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int pri-mask) ebx) + (cmpl (int pri-tag) ebx) + (jne Lf) + (movl (mem (fx- 0 pri-tag) eax) ebx) + (if sec-mask + (andl (int sec-mask) ebx) + '(nop)) + (cmpl (int sec-tag) ebx) + (jne Lf) + ac)] + [Lt + (let ([L_END (unique-label)]) + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int pri-mask) ebx) + (cmpl (int pri-tag) ebx) + (jne L_END) + (movl (mem (fx- 0 pri-tag) eax) ebx) + (if sec-mask + (andl (int sec-mask) ebx) + '(nop)) + (cmpl (int sec-tag) ebx) + (je Lt) + L_END + ac))] + [else ac])) + (define (type-pred mask tag rand* Lt Lf ac) + (cond + [mask + (list* + (movl (Simple (car rand*)) eax) + (andl (int mask) eax) + (cmpl (int tag) eax) + (cond-branch 'je Lt Lf ac))] + [else + (let ([v (Simple (car rand*))]) + (cond + [(memq (car v) '(mem register)) + (list* + (cmpl (int tag) (Simple (car rand*))) + (cond-branch 'je Lt Lf ac))] + [else + (list* + (movl (Simple (car rand*)) eax) + (cmpl (int tag) eax) + (cond-branch 'je Lt Lf ac))]))])) + (define (compare-and-branch op rand* Lt Lf ac) + (define (opposite x) + (cadr (assq x '([je je] [jl jg] [jle jge] [jg jl] [jge jle])))) + (cond + [(and (constant? (car rand*)) (constant? (cadr rand*))) + (list* + (movl (Simple (car rand*)) eax) + (cmpl (Simple (cadr rand*)) eax) + (cond-branch op Lt Lf ac))] + [(constant? (cadr rand*)) + (list* + (cmpl (Simple (cadr rand*)) (Simple (car rand*))) + (cond-branch op Lt Lf ac))] + [(constant? (car rand*)) + (list* + (cmpl (Simple (car rand*)) (Simple (cadr rand*))) + (cond-branch (opposite op) Lt Lf ac))] + [else + (list* + (movl (Simple (car rand*)) eax) + (cmpl (Simple (cadr rand*)) eax) + (cond-branch op Lt Lf ac))])) + (define (do-pred-prim op rand* Lt Lf ac) + (case op + [(fixnum?) (type-pred fx-mask fx-tag rand* Lt Lf ac)] + [(pair?) (type-pred pair-mask pair-tag rand* Lt Lf ac)] + [(char?) (type-pred char-mask char-tag rand* Lt Lf ac)] + [(string?) (type-pred string-mask string-tag rand* Lt Lf ac)] + [(symbol?) (type-pred symbol-mask symbol-tag rand* Lt Lf ac)] + [(procedure?) (type-pred closure-mask closure-tag rand* Lt Lf ac)] + [(boolean?) (type-pred bool-mask bool-tag rand* Lt Lf ac)] + [(null?) (type-pred #f nil rand* Lt Lf ac)] + [($unbound-object?) (type-pred #f unbound rand* Lt Lf ac)] + [($forward-ptr?) (type-pred #f -1 rand* Lt Lf ac)] + [(not) (Pred (car rand*) Lf Lt ac)] + ;[(not) (type-pred #f bool-f rand* Lt Lf ac)] + [(eof-object?) (type-pred #f eof rand* Lt Lf ac)] + [(bwp-object?) (type-pred #f bwp-object rand* Lt Lf ac)] + [($code?) + (indirect-type-pred vector-mask vector-tag #f code-tag + rand* Lt Lf ac)] + [($fxzero?) (type-pred #f 0 rand* Lt Lf ac)] + [($fx= $char= eq?) (compare-and-branch 'je rand* Lt Lf ac)] + [($fx< $char<) (compare-and-branch 'jl rand* Lt Lf ac)] + [($fx<= $char<=) (compare-and-branch 'jle rand* Lt Lf ac)] + [($fx> $char>) (compare-and-branch 'jg rand* Lt Lf ac)] + [($fx>= $char>=) (compare-and-branch 'jge rand* Lt Lf ac)] + [(vector?) + (indirect-type-pred vector-mask vector-tag fx-mask fx-tag + rand* Lt Lf ac)] + [($record?) + (indirect-type-pred record-pmask record-ptag record-pmask record-ptag + rand* Lt Lf ac)] + [($record/rtd?) + (cond + [Lf + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int vector-mask) eax) + (cmpl (int vector-tag) eax) + (jne Lf) + (movl (Simple (cadr rand*)) eax) + (cmpl (mem (fx- disp-record-rtd vector-tag) ebx) eax) + (jne Lf) + (if Lt + (cons (jmp Lt) ac) + ac))] + [Lt + (let ([Ljoin (unique-label)]) + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int vector-mask) eax) + (cmpl (int vector-tag) eax) + (jne Ljoin) + (movl (Simple (cadr rand*)) eax) + (cmpl (mem (fx- disp-record-rtd vector-tag) ebx) eax) + (je Lt) + Ljoin + ac))] + [else ac])] + [(immediate?) + (cond + [(and Lt Lf) + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int fx-mask) ebx) + (cmpl (int 0) ebx) + (je Lt) + (andl (int 7) eax) + (cmpl (int 7) eax) + (je Lt) + (jmp Lf) + ac)] + [Lt + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int fx-mask) ebx) + (cmpl (int 0) ebx) + (je Lt) + (andl (int 7) eax) + (cmpl (int 7) eax) + (je Lt) + ac)] + [Lf + (let ([Ljoin (unique-label)]) + (list* + (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int fx-mask) ebx) + (cmpl (int 0) ebx) + (je Ljoin) + (andl (int 7) eax) + (cmpl (int 7) eax) + (jne Lf) + Ljoin + ac))] + [else ac])] + [($ap-check-words) + (record-case (car rand*) + [(constant i) + (list* (movl (pcb-ref 'allocation-redline) eax) + (subl (Simple (cadr rand*)) eax) + (subl (int i) eax) + (cmpl eax apr) + (cond-branch 'jge Lt Lf ac))] + [else (error who "ap-check-words")])] + [($ap-check-bytes) + (record-case (car rand*) + [(constant i) + (list* (movl (Simple (cadr rand*)) eax) + (negl eax) + (addl (pcb-ref 'allocation-redline) eax) + (subl (int i) eax) + (cmpl eax apr) + (cond-branch 'jge Lt Lf ac))] + [else (error who "ap-check-bytes")])] + [($ap-check-const) + (record-case (car rand*) + [(constant i) + (if (fx<= i pagesize) + (list* + (cmpl (pcb-ref 'allocation-redline) apr) + (cond-branch 'jge Lt Lf ac)) + (list* + (movl (pcb-ref 'allocation-redline) eax) + (subl (int i) eax) + (cmpl eax apr) + (cond-branch 'jge Lt Lf ac)))] + [else (error who "ap-check-const")])] + [($fp-at-base) + (list* + (movl (pcb-ref 'frame-base) eax) + (subl (int wordsize) eax) + (cmpl eax fpr) + (cond-branch 'je Lt Lf ac))] + [($fp-overflow) + (list* (cmpl (pcb-ref 'frame-redline) fpr) + (cond-branch 'jle Lt Lf ac))] + [($vector-ref top-level-value car cdr $record-ref) + (do-value-prim op rand* + (do-simple-test eax Lt Lf ac))] + [(cons void $fxadd1 $fxsub1) + ;;; always true + (do-effect-prim op rand* + (cond + [(not Lt) ac] + [else (cons (jmp Lt) ac)]))] + [else + (error 'pred-prim "HERE unhandled ~s" op)])) + (define (do-pred->value-prim op rand* ac) + (case op + [else + (let ([Lf (unique-label)] [Lj (unique-label)]) + (do-pred-prim op rand* #f Lf + (list* (movl (constant-val #t) eax) + (jmp Lj) + Lf + (movl (constant-val #f) eax) + Lj + ac)))])) + (define (indirect-ref arg* off ac) + (list* + (movl (Simple (car arg*)) eax) + (movl (mem off eax) eax) + ac)) + (define (do-value-prim op arg* ac) + (case op + [(eof-object) (cons (movl (int eof) eax) ac)] + [(void) (cons (movl (int void-object) eax) ac)] + [($fxadd1) + (list* (movl (Simple (car arg*)) eax) + (addl (constant-val 1) eax) + ac)] + [($fxsub1) + (list* (movl (Simple (car arg*)) eax) + (addl (constant-val -1) eax) + ac)] + [($fx+) + (list* (movl (Simple (car arg*)) eax) + (addl (Simple (cadr arg*)) eax) + ac)] + [($fx-) + (list* (movl (Simple (car arg*)) eax) + (subl (Simple (cadr arg*)) eax) + ac)] + [($fx*) + (cond + [(constant? (car arg*)) + (record-case (car arg*) + [(constant c) + (unless (fixnum? c) + (error who "invalid arg ~s to fx*" c)) + (list* (movl (Simple (cadr arg*)) eax) + (imull (int c) eax) + ac)])] + [(constant? (cadr arg*)) + (record-case (cadr arg*) + [(constant c) + (unless (fixnum? c) + (error who "invalid arg ~s to fx*" c)) + (list* (movl (Simple (car arg*)) eax) + (imull (int c) eax) + ac)])] + [else + (list* (movl (Simple (car arg*)) eax) + (sarl (int fx-shift) eax) + (imull (Simple (cadr arg*)) eax) + ac)])] + [($fxquotient) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ecx) + (cltd) + (idivl ecx) + (sall (int fx-shift) eax) + ac)] + [($fxmodulo) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl eax ecx) + (xorl ebx ecx) + (sarl (int (fxsub1 (fx* wordsize 8))) ecx) + (andl ebx ecx) + (cltd) + (idivl ebx) + (movl edx eax) + (addl ecx eax) + ac)] + [($fxlogor) + (list* (movl (Simple (car arg*)) eax) + (orl (Simple (cadr arg*)) eax) + ac)] + [($fxlogand) + (list* (movl (Simple (car arg*)) eax) + (andl (Simple (cadr arg*)) eax) + ac)] + [($fxlogxor) + (list* (movl (Simple (car arg*)) eax) + (xorl (Simple (cadr arg*)) eax) + ac)] + [($fxsra) + (record-case (cadr arg*) + [(constant i) + (unless (fixnum? i) (error who "invalid arg to fxsra")) + (list* (movl (Simple (car arg*)) eax) + (sarl (int (fx+ i fx-shift)) eax) + (sall (int fx-shift) eax) + ac)] + [else + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ecx) + (sarl (int fx-shift) ecx) + (sarl (int fx-shift) eax) + (sarl cl eax) + (sall (int fx-shift) eax) + ac)])] + [($fxsll) + (record-case (cadr arg*) + [(constant i) + (unless (fixnum? i) (error who "invalid arg to fxsll")) + (list* (movl (Simple (car arg*)) eax) + (sall (int i) eax) + ac)] + [else + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ecx) + (sarl (int fx-shift) ecx) + (sall cl eax) + ac)])] + [($fixnum->char) + (list* (movl (Simple (car arg*)) eax) + (sall (int (fx- char-shift fx-shift)) eax) + (orl (int char-tag) eax) + ac)] + [($char->fixnum) + (list* (movl (Simple (car arg*)) eax) + (sarl (int (fx- char-shift fx-shift)) eax) + ac)] + [($fxlognot) + (list* (movl (Simple (car arg*)) eax) + (orl (int fx-mask) eax) + (notl eax) + ac)] + [($car) (indirect-ref arg* (fx- disp-car pair-tag) ac)] + [($cdr) (indirect-ref arg* (fx- disp-cdr pair-tag) ac)] + [($vector-length) + (indirect-ref arg* (fx- disp-vector-length vector-tag) ac)] + [($string-length) + (indirect-ref arg* (fx- disp-string-length string-tag) ac)] + [($symbol-string) + (indirect-ref arg* (fx- disp-symbol-string symbol-tag) ac)] + [($symbol-unique-string) + (indirect-ref arg* (fx- disp-symbol-unique-string symbol-tag) ac)] + [($symbol-value) + (indirect-ref arg* (fx- disp-symbol-value symbol-tag) ac)] + [(primitive-ref) + (indirect-ref arg* (fx- disp-symbol-system-value symbol-tag) ac)] + [($tcbucket-key) + (indirect-ref arg* (fx- disp-tcbucket-key vector-tag) ac)] + [($tcbucket-val) + (indirect-ref arg* (fx- disp-tcbucket-val vector-tag) ac)] + [($tcbucket-next) + (indirect-ref arg* (fx- disp-tcbucket-next vector-tag) ac)] + [(pointer-value) + (list* + (movl (Simple (car arg*)) eax) + (sarl (int fx-shift) eax) + (sall (int fx-shift) eax) + ac)] + [($symbol-plist) + (indirect-ref arg* (fx- disp-symbol-plist symbol-tag) ac)] + [($record-rtd) + (indirect-ref arg* (fx- disp-record-rtd record-ptag) ac)] + [($constant-ref) + (list* (movl (Simple (car arg*)) eax) ac)] + [(car cdr) + (let ([x (car arg*)]) + (NonTail x + (list* + (movl eax ebx) + (andl (int pair-mask) eax) + (cmpl (int pair-tag) eax) + (if (eq? op 'car) + (list* + (jne (label SL_car_error)) + (movl (mem (fx- disp-car pair-tag) ebx) eax) + ac) + (list* + (jne (label SL_cdr_error)) + (movl (mem (fx- disp-cdr pair-tag) ebx) eax) + ac)))))] + [(top-level-value) + (let ([x (car arg*)]) + (cond + [(constant? x) + (let ([v (constant-value x)]) + (cond + [(symbol? v) + (list* + (movl (mem (fx- disp-symbol-value symbol-tag) (obj v)) eax) + (movl (obj v) ebx) + (cmpl (int unbound) eax) + (je (label SL_top_level_value_error)) + ac)] + [else + (list* + (movl (obj v) ebx) + (jmp (label SL_top_level_value_error)) + ac)]))] + [else + (NonTail x + (list* + (movl eax ebx) + (andl (int symbol-mask) eax) + (cmpl (int symbol-tag) eax) + (jne (label SL_top_level_value_error)) + (movl (mem (fx- disp-symbol-value symbol-tag) ebx) eax) + (cmpl (int unbound) eax) + (je (label SL_top_level_value_error)) + ac))]))] + [($vector-ref) + (list* (movl (Simple (car arg*)) ebx) + (addl (Simple (cadr arg*)) ebx) + (movl (mem (fx- disp-vector-data vector-tag) ebx) eax) + ac)] + [($record-ref) + (list* (movl (Simple (car arg*)) ebx) + (addl (Simple (cadr arg*)) ebx) + (movl (mem (fx- disp-record-data record-ptag) ebx) eax) + ac)] + [($code-ref) + (list* (movl (Simple (cadr arg*)) ebx) + (sarl (int fx-shift) ebx) + (addl (Simple (car arg*)) ebx) + (movl (int 0) eax) + (movb (mem (fx- disp-code-data vector-tag) ebx) ah) + (sarl (int (fx- 8 fx-shift)) eax) + ac)] + [($string-ref) + (list* (movl (Simple (cadr arg*)) ebx) + (sarl (int fx-shift) ebx) + (addl (Simple (car arg*)) ebx) + (movl (int char-tag) eax) + (movb (mem (fx- disp-string-data string-tag) ebx) ah) + ac)] + [($make-string) + (list* (movl (Simple (car arg*)) ebx) + (movl ebx (mem disp-string-length apr)) + (movl apr eax) + (addl (int string-tag) eax) + (sarl (int fx-shift) ebx) + (addl ebx apr) + (movb (int 0) (mem disp-string-data apr)) + (addl (int (fx+ disp-string-data object-alignment)) apr) + (sarl (int align-shift) apr) + (sall (int align-shift) apr) + ac)] + [($make-vector) + (list* (movl (Simple (car arg*)) ebx) + (movl ebx (mem disp-vector-length apr)) + (movl apr eax) + (addl (int vector-tag) eax) + (addl ebx apr) + (addl (int (fx+ disp-vector-data (fxsub1 object-alignment))) apr) + (sarl (int align-shift) apr) + (sall (int align-shift) apr) + ac)] + [($make-record) + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem disp-record-rtd apr)) + (movl apr eax) + (addl (int record-ptag) eax) + (addl (Simple (cadr arg*)) apr) + (addl (int (fx+ disp-record-data (fxsub1 object-alignment))) apr) + (sarl (int align-shift) apr) + (sall (int align-shift) apr) + ac)] + [(cons) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl eax (mem disp-car apr)) + (movl apr eax) + (movl ebx (mem disp-cdr apr)) + (addl (int pair-tag) eax) + (addl (int (align pair-size)) apr) + ac)] + [(list) + (cond + [(null? arg*) (NonTail (make-constant '()) ac)] + [else + (list* + (addl (int pair-tag) apr) + (movl apr eax) + (let f ([a (car arg*)] [d (cdr arg*)]) + (list* + (movl (Simple a) ebx) + (movl ebx (mem (fx- disp-car pair-tag) apr)) + (if (null? d) + (list* + (movl (int nil) (mem (fx- disp-cdr pair-tag) apr)) + (addl (int (fx- pair-size pair-tag)) apr) + ac) + (list* + (addl (int pair-size) apr) + (movl apr + (mem (fx- disp-cdr (fx+ pair-tag pair-size)) apr)) + (f (car d) (cdr d)))))))])] + [(list*) + (cond + [(fx= (length arg*) 1) (NonTail (car arg*) ac)] + [(fx= (length arg*) 2) (NonTail (make-primcall 'cons arg*) ac)] + [else + (list* + (addl (int pair-tag) apr) + (movl apr eax) + (let f ([a (car arg*)] [b (cadr arg*)] [d (cddr arg*)]) + (list* + (movl (Simple a) ebx) + (movl ebx (mem (fx- disp-car pair-tag) apr)) + (if (null? d) + (list* + (movl (Simple b) ebx) + (movl ebx (mem (fx- disp-cdr pair-tag) apr)) + (addl (int (fx- pair-size pair-tag)) apr) + ac) + (list* + (addl (int pair-size) apr) + (movl apr + (mem (fx- disp-cdr (fx+ pair-tag pair-size)) apr)) + (f b (car d) (cdr d)))))))])] + [($make-symbol) + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem disp-symbol-string apr)) + (movl (int 0) (mem disp-symbol-unique-string apr)) + (movl (int unbound) (mem disp-symbol-value apr)) + (movl (int nil) (mem disp-symbol-plist apr)) + (movl (int unbound) (mem disp-symbol-system-value apr)) + (movl (int nil) (mem disp-symbol-system-plist apr)) + (movl apr eax) + (addl (int symbol-tag) eax) + (addl (int (align symbol-size)) apr) + ac)] + [($make-tcbucket) + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem disp-tcbucket-tconc apr)) + (movl (Simple (cadr arg*)) eax) + (movl eax (mem disp-tcbucket-key apr)) + (movl (Simple (caddr arg*)) eax) + (movl eax (mem disp-tcbucket-val apr)) + (movl (Simple (cadddr arg*)) eax) + (movl eax (mem disp-tcbucket-next apr)) + (movl apr eax) + (addl (int vector-tag) eax) + (addl (int (align tcbucket-size)) apr) + ac)] + [($record) + (let ([rtd (car arg*)] + [ac + (let f ([arg* (cdr arg*)] [idx disp-record-data]) + (cond + [(null? arg*) + (list* (movl apr eax) + (addl (int vector-tag) eax) + (addl (int (align idx)) apr) + ac)] + [else + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem idx apr)) + (f (cdr arg*) (fx+ idx wordsize)))]))]) + (cond + [(constant? rtd) + (list* (movl (Simple rtd) (mem 0 apr)) ac)] + [else + (list* (movl (Simple rtd) eax) (movl eax (mem 0 apr)) ac)]))] + [(vector) + (let f ([arg* arg*] [idx disp-vector-data]) + (cond + [(null? arg*) + (list* (movl apr eax) + (addl (int vector-tag) eax) + (movl (int (fx- idx disp-vector-data)) + (mem disp-vector-length apr)) + (addl (int (align idx)) apr) + ac)] + [else + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem idx apr)) + (f (cdr arg*) (fx+ idx wordsize)))]))] + [($string) + (let f ([arg* arg*] [idx disp-string-data]) + (cond + [(null? arg*) + (list* (movb (int 0) (mem idx apr)) + (movl apr eax) + (addl (int string-tag) eax) + (movl (int (fx* (fx- idx disp-string-data) wordsize)) + (mem disp-string-length apr)) + (addl (int (align (fxadd1 idx))) apr) + ac)] + [else + (record-case (car arg*) + [(constant c) + (unless (char? c) (error who "invalid arg to string ~s" x)) + (list* (movb (int (char->integer c)) (mem idx apr)) + (f (cdr arg*) (fxadd1 idx)))] + [else + (list* (movl (Simple (car arg*)) ebx) + (movb bh (mem idx apr)) + (f (cdr arg*) (fxadd1 idx)))])]))] + [($current-frame) + (list* (movl (pcb-ref 'next-continuation) eax) + ac)] + [($seal-frame-and-call) + (list* (movl (Simple (car arg*)) cpr) ; proc + (movl (pcb-ref 'frame-base) eax) + ; eax=baseofstack + (movl (mem (fx- 0 wordsize) eax) ebx) ; underflow handler + (movl ebx (mem (fx- 0 wordsize) fpr)) ; set + ; create a new cont record + (movl (int continuation-tag) (mem 0 apr)) + (movl fpr (mem disp-continuation-top apr)) + ; compute the size of the captured frame + (movl eax ebx) + (subl fpr ebx) + (subl (int wordsize) ebx) + ; and store it + (movl ebx (mem disp-continuation-size apr)) + ; load next cont + (movl (pcb-ref 'next-continuation) ebx) + ; and store it + (movl ebx (mem disp-continuation-next apr)) + ; adjust ap + (movl apr eax) + (addl (int vector-tag) eax) + (addl (int continuation-size) apr) + ; store new cont in current-cont + (movl eax (pcb-ref 'next-continuation)) + ; adjust fp + (movl fpr (pcb-ref 'frame-base)) + (subl (int wordsize) fpr) + ; tail-call f + (movl eax (mem (fx- 0 wordsize) fpr)) + (movl (int (argc-convention 1)) eax) + (tail-indirect-cpr-call) + ac)] + [($code-size) + (indirect-ref arg* (fx- disp-code-instrsize vector-tag) ac)] + [($code-reloc-vector) + (indirect-ref arg* (fx- disp-code-relocsize vector-tag) ac)] + [($code-freevars) + (indirect-ref arg* (fx- disp-code-freevars vector-tag) ac)] + [($set-car! $set-cdr! $vector-set! $string-set! $exit + $set-symbol-value! $set-symbol-plist! + $code-set! primitive-set! + $set-code-object! $set-code-object+offset! $set-code-object+offset/rel! + $record-set!) + (do-effect-prim op arg* + (cons (movl (int void-object) eax) ac))] + [(fixnum? immediate? $fxzero? boolean? char? pair? vector? string? symbol? + procedure? null? not eof-object? $fx= $fx< $fx<= $fx> $fx>= eq? + $char= $char< $char<= $char> $char>= $unbound-object? $code? + $record? $record/rtd? bwp-object?) + (do-pred->value-prim op arg* ac)] + [($code->closure) + (list* + (movl (Simple (car arg*)) eax) + (addl (int (fx- disp-code-data vector-tag)) eax) + (movl eax (mem 0 apr)) + (movl apr eax) + (addl (int closure-tag) eax) + (addl (int (align disp-closure-data)) apr) + ac)] + [($frame->continuation) + (NonTail + (make-closure (make-code-loc SL_continuation_code) arg*) + ac)] + [($make-call-with-values-procedure) + (NonTail + (make-closure (make-code-loc SL_call_with_values) arg*) + ac)] + [($make-values-procedure) + (NonTail + (make-closure (make-code-loc SL_values) arg*) + ac)] + [else + (error 'value-prim "unhandled ~s" op)])) + (define (indirect-assignment arg* offset ac) + (list* + (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem offset eax)) + ;;; record side effect + (addl (int offset) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)) + (define (do-effect-prim op arg* ac) + (case op + [($vector-set!) + (list* (movl (Simple (car arg*)) ebx) + (addl (Simple (cadr arg*)) ebx) + (addl (int (fx- disp-vector-data vector-tag)) ebx) + (movl (Simple (caddr arg*)) eax) + (movl eax (mem 0 ebx)) + ;;; record side effect + (shrl (int pageshift) ebx) + (sall (int wordshift) ebx) + (addl (pcb-ref 'dirty-vector) ebx) + (movl (int dirty-word) (mem 0 ebx)) + ac)] + [($code-set!) + (list* (movl (Simple (cadr arg*)) eax) + (sarl (int fx-shift) eax) + (addl (Simple (car arg*)) eax) + (movl (Simple (caddr arg*)) ebx) + (sall (int (fx- 8 fx-shift)) ebx) + (movb bh (mem (fx- disp-code-data vector-tag) eax)) + ac)] + [($string-set!) + (list* (movl (Simple (cadr arg*)) eax) + (sarl (int fx-shift) eax) + (addl (Simple (car arg*)) eax) + (movl (Simple (caddr arg*)) ebx) + (movb bh (mem (fx- disp-string-data string-tag) eax)) + ac)] + [($set-car!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-car pair-tag) eax)) + ;;; record side effect + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($set-cdr!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-cdr pair-tag) eax)) + ;;; record side effect + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($set-tcbucket-key!) + (indirect-assignment arg* (fx- disp-tcbucket-key vector-tag) ac)] + [($set-tcbucket-val!) + (indirect-assignment arg* (fx- disp-tcbucket-val vector-tag) ac)] + [($set-tcbucket-next!) + (indirect-assignment arg* (fx- disp-tcbucket-next vector-tag) ac)] + [($set-tcbucket-tconc!) + (indirect-assignment arg* (fx- disp-tcbucket-tconc vector-tag) ac)] + + [($set-symbol-value!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-symbol-value symbol-tag) eax)) + ;;; record side effect + (addl (int (fx- disp-symbol-value symbol-tag)) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [(primitive-set!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-symbol-system-value symbol-tag) eax)) + ;;; record side effect + (addl (int (fx- disp-symbol-system-value symbol-tag)) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($set-symbol-plist!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-symbol-plist symbol-tag) eax)) + ;;; record side effect + (addl (int (fx- disp-symbol-plist symbol-tag)) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($set-symbol-unique-string!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-symbol-unique-string symbol-tag) eax)) + ;;; record side effect + (addl (int (fx- disp-symbol-unique-string symbol-tag)) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($set-symbol-string!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-symbol-string symbol-tag) eax)) + ;;; record side effect + (addl (int (fx- disp-symbol-string symbol-tag)) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($record-set!) + (list* (movl (Simple (car arg*)) ebx) + (addl (Simple (cadr arg*)) ebx) + (movl (Simple (caddr arg*)) eax) + (addl (int (fx- disp-record-data record-ptag)) ebx) + (movl eax (mem 0 ebx)) + ;;; record side effect + (shrl (int pageshift) ebx) + (sall (int wordshift) ebx) + (addl (pcb-ref 'dirty-vector) ebx) + (movl (int dirty-word) (mem 0 ebx)) + ac)] + [(cons void $fxadd1 $fxsub1 $record-ref) + (let f ([arg* arg*]) + (cond + [(null? arg*) ac] + [else + (Effect (car arg*) (f (cdr arg*)))]))] + [else + (error 'do-effect-prim "unhandled op ~s" op)])) + (define (do-simple-test x Lt Lf ac) + (unless (or Lt Lf) + (error 'Pred "no labels")) + (cond + [(not Lt) + (list* (cmpl (int bool-f) x) (je Lf) ac)] + [(not Lf) + (list* (cmpl (int bool-f) x) (jne Lt) ac)] + [else + (list* (cmpl (int bool-f) x) (je Lf) (jmp Lt) ac)])) + (define (Simple x) + (record-case x + [(cp-var i) + (mem (fx+ (fx* i wordsize) (fx- disp-closure-data closure-tag)) cpr)] + [(frame-var i) (mem (fx* i (fx- 0 wordsize)) fpr)] + [(constant c) (constant-val c)] + [(code-loc label) (label-address label)] + [(primref op) (primref-loc op)] + [else (error 'Simple "what ~s" x)])) + (define (closure-size x) + (align (fx+ disp-closure-data + (fx* wordsize (length (closure-free* x)))))) + (define (assign-codes rhs* n* i ac) + (cond + [(null? rhs*) ac] + [else + (record-case (car rhs*) + [(closure label free*) + (cons (movl (Simple label) (mem i apr)) + (assign-codes + (cdr rhs*) (cdr n*) (fx+ i (car n*)) ac))])])) + (define (whack-free x i n* rhs* ac) + (cond + [(null? rhs*) ac] + [else + (let ([free (closure-free* (car rhs*))]) + (let f ([free free] [j (fx+ i disp-closure-data)]) + (cond + [(null? free) + (whack-free x (fx+ i (car n*)) (cdr n*) (cdr rhs*) ac)] + [(eq? (car free) x) + (cons + (movl eax (mem j apr)) + (f (cdr free) (fx+ j wordsize)))] + [else (f (cdr free) (fx+ j wordsize))])))])) + (define (assign-nonrec-free* rhs* all-rhs* n* seen ac) + (cond + [(null? rhs*) ac] + [else + (let f ([ls (closure-free* (car rhs*))] [seen seen]) + (cond + [(null? ls) + (assign-nonrec-free* (cdr rhs*) all-rhs* n* seen ac)] + [(memq (car ls) seen) (f (cdr ls) seen)] + [else + (cons + (movl (Simple (car ls)) eax) + (whack-free (car ls) 0 n* all-rhs* + (f (cdr ls) (cons (car ls) seen))))]))])) + (define (assign-rec-free* lhs* rhs* all-n* ac) + (list* (movl apr eax) + (addl (int closure-tag) eax) + (let f ([lhs* lhs*] [n* all-n*]) + (cond + [(null? (cdr lhs*)) + (cons + (movl eax (Simple (car lhs*))) + (whack-free (car lhs*) 0 all-n* rhs* ac))] + [else + (cons + (movl eax (Simple (car lhs*))) + (whack-free (car lhs*) 0 all-n* rhs* + (cons + (addl (int (car n*)) eax) + (f (cdr lhs*) (cdr n*)))))])))) + (define (sum ac ls) + (cond + [(null? ls) ac] + [else (sum (fx+ ac (car ls)) (cdr ls))])) + (define (do-fix lhs* rhs* ac) + ;;; 1. first, set the code pointers in the right places + ;;; 2. next, for every variable appearing in the rhs* but is not in + ;;; the lhs*, load it once and set it everywhere it occurs. + ;;; 3. next, compute the values of the lhs*, and for every computed + ;;; value, store it on the stack, and set it everywhere it occurs + ;;; in the rhs* + ;;; 4. that's it. + (let* ([n* (map closure-size rhs*)]) + (assign-codes rhs* n* 0 + (assign-nonrec-free* rhs* rhs* n* lhs* + (assign-rec-free* lhs* rhs* n* + (cons (addl (int (sum 0 n*)) apr) ac)))))) + (define (frame-adjustment offset) + (fx* (fxsub1 offset) (fx- 0 wordsize))) + (define (NonTail x ac) + (record-case x + [(constant c) + (cons (movl (constant-val c) eax) ac)] + [(frame-var) + (cons (movl (Simple x) eax) ac)] + [(cp-var) + (cons (movl (Simple x) eax) ac)] + [(foreign-label L) + (cons (movl (list 'foreign-label L) eax) ac)] + [(primref c) + (cons (movl (primref-loc c) eax) ac)] + [(closure label arg*) + (let f ([arg* arg*] [off disp-closure-data]) + (cond + [(null? arg*) + (list* (movl (Simple label) (mem 0 apr)) + (movl apr eax) + (addl (int (align off)) apr) + (addl (int closure-tag) eax) + ac)] + [else + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem off apr)) + (f (cdr arg*) (fx+ off wordsize)))]))] + [(conditional test conseq altern) + (let ([Lj (unique-label)] [Lf (unique-label)]) + (Pred test #f Lf + (NonTail conseq + (list* (jmp Lj) Lf (NonTail altern (cons Lj ac))))))] + [(seq e0 e1) + (Effect e0 (NonTail e1 ac))] + [(fix lhs* rhs* body) + (do-fix lhs* rhs* (NonTail body ac))] + [(primcall op rand*) + (do-value-prim op rand* ac)] + [(new-frame base-idx size body) + (NonTail body ac)] + [(call-cp call-convention rp-convention offset size mask) + (let ([L_CALL (unique-label)]) + (case call-convention + [(normal) + (list* (addl (int (frame-adjustment offset)) fpr) + (movl (int (argc-convention size)) eax) + (jmp L_CALL) + ; NEW FRAME + `(byte-vector ,mask) + `(int ,(fx* offset wordsize)) + `(current-frame-offset) + (rp-label rp-convention) + `(byte 0) ; padding for indirect calls only + `(byte 0) ; direct calls are ok + L_CALL + (indirect-cpr-call) + (movl (mem 0 fpr) cpr) + (subl (int (frame-adjustment offset)) fpr) + ac)] + [(foreign) + (list* (addl (int (frame-adjustment offset)) fpr) + (movl (int (argc-convention size)) eax) + (movl '(foreign-label "ik_foreign_call") ebx) + (jmp L_CALL) + ; NEW FRAME + (byte-vector mask) + `(int ,(fx* offset wordsize)) + `(current-frame-offset) + (rp-label rp-convention) ; should be 0, since C has 1 rv + '(byte 0) + '(byte 0) + '(byte 0) + L_CALL + (call ebx) + (movl (mem 0 fpr) cpr) + (subl (int (frame-adjustment offset)) fpr) + ac)] + [else + (error who "invalid convention ~s for call-cp" call-convention)]))] + [else (error 'NonTail "invalid expression ~s" x)])) + (define (Pred x Lt Lf ac) + (record-case x + [(frame-var i) + (do-simple-test (idx->frame-loc i) Lt Lf ac)] + [(cp-var i) + (do-simple-test (Simple x) Lt Lf ac)] + [(constant c) + (if c + (if Lt (cons (jmp Lt) ac) ac) + (if Lf (cons (jmp Lf) ac) ac))] + [(fix lhs* rhs* body) + (do-fix lhs* rhs* (Pred body Lt Lf ac))] + [(primcall op rand*) + (do-pred-prim op rand* Lt Lf ac)] + [(conditional test conseq altern) + (cond + [(not Lt) + (let ([Lj^ (unique-label)] [Lf^ (unique-label)]) + (Pred test #f Lf^ + (Pred conseq Lj^ Lf + (cons Lf^ + (Pred altern #f Lf + (cons Lj^ ac))))))] + [(not Lf) + (let ([Lj^ (unique-label)] [Lf^ (unique-label)]) + (Pred test #f Lf^ + (Pred conseq Lt Lj^ + (cons Lf^ + (Pred altern Lt #f + (cons Lj^ ac))))))] + [else + (let ([Lf^ (unique-label)]) + (Pred test #f Lf^ + (Pred conseq Lt Lf + (cons Lf^ + (Pred altern Lt Lf ac)))))])] + [(seq e0 e1) + (Effect e0 (Pred e1 Lt Lf ac))] + [(new-frame) + (NonTail x (do-simple-test eax Lt Lf ac))] + [else (error 'Pred "invalid expression ~s" x)])) + (define (idx->frame-loc i) + (mem (fx* i (fx- 0 wordsize)) fpr)) + (define (Effect x ac) + (record-case x + [(constant) ac] + [(primcall op rand*) + (do-effect-prim op rand* ac)] + [(conditional test conseq altern) + (let* ([Ljoin (unique-label)] + [ac (cons Ljoin ac)] + [altern-ac (Effect altern ac)]) + (cond + [(eq? altern-ac ac) ;; altern is nop + (let* ([conseq-ac (Effect conseq ac)]) + (cond + [(eq? conseq-ac ac) ;; conseq is nop too! + (Effect test ac)] + [else ; "when" pattern + (Pred test #f Ljoin conseq-ac)]))] + [else + (let* ([Lf (unique-label)] + [nac (list* (jmp Ljoin) Lf altern-ac)] + [conseq-ac (Effect conseq nac)]) + (cond + [(eq? conseq-ac nac) ;; "unless" pattern" + (Pred test Ljoin #f altern-ac)] + [else + (Pred test #f Lf conseq-ac)]))]))] +;;; [(conditional test conseq altern) +;;; (let ([Lf (unique-label)] [Ljoin (unique-label)]) +;;; (Pred test #f Lf +;;; (Effect conseq +;;; (list* (jmp Ljoin) Lf (Effect altern (cons Ljoin ac))))))] + [(seq e0 e1) + (Effect e0 (Effect e1 ac))] + [(fix lhs* rhs* body) + (do-fix lhs* rhs* (Effect body ac))] + [(assign loc val) + (record-case loc + [(frame-var i) + (record-case val + [(constant c) + (cons (movl (constant-val c) (idx->frame-loc i)) ac)] + [else + (NonTail val + (cons (movl eax (idx->frame-loc i)) ac))])] + [else (error who "invalid assign loc ~s" loc)])] + [(eval-cp check body) + (cond + [check + (NonTail body + (list* + (movl eax cpr) + (andl (int closure-mask) eax) + (cmpl (int closure-tag) eax) + (jne (label SL_nonprocedure)) + ac))] + [(primref? body) + (list* (movl (primref-loc (primref-name body)) cpr) ac)] + [else + (NonTail body (list* (movl eax cpr) ac))])] + [(save-cp loc) + (record-case loc + [(frame-var i) + (cons (movl cpr (idx->frame-loc i)) ac)] + [else (error who "invalid cpr loc ~s" x)])] + [(new-frame) (NonTail x ac)] + [(frame-var) ac] + [else (error 'Effect "invalid expression ~s" x)])) + (define (Tail x ac) + (record-case x + [(return x) + (NonTail x (cons (ret) ac))] + [(conditional test conseq altern) + (let ([L (unique-label)]) + (Pred test #f L + (Tail conseq + (cons L (Tail altern ac)))))] + [(seq e0 e1) + (Effect e0 (Tail e1 ac))] + [(fix lhs* rhs* body) + (do-fix lhs* rhs* (Tail body ac))] + [(new-frame idx size body) + (Tail body ac)] + [(tailcall-cp call-convention argc) + (list* + (movl (int (argc-convention argc)) eax) + (case call-convention + [(normal) (tail-indirect-cpr-call)] + [(apply) (jmp (label SL_apply))] + [else + (error who "invalid tail-call convention ~s" call-convention)]) + ac)] +;;; [(call-cp call-convention rp-convention idx argc mask) +;;; (unless (eq? rp-convention 'tail) +;;; (error who "nontail rp (~s) in tail context" rp-convention)) +;;; (let f ([i 0]) +;;; (cond +;;; [(fx= i argc) +;;; (case call-convention +;;; [(normal) +;;; (list* +;;; (movl (int (argc-convention argc)) eax) +;;; (tail-indirect-cpr-call) +;;; ac)] +;;; [(apply) +;;; (list* +;;; (movl (int (argc-convention argc)) eax) +;;; (jmp (label SL_apply)) +;;; ac)] +;;; [else +;;; (error who "invalid conv ~s in tail call-cpr" call-convention)])] +;;; [else +;;; (list* (movl (mem (fx* (fx+ idx (fxadd1 i)) +;;; (fx- 0 wordsize)) fpr) +;;; eax) +;;; (movl eax (mem (fx* (fx+ i 1) (fx- 0 wordsize)) fpr)) +;;; (f (fxadd1 i)))]))] + [else (error 'Tail "invalid expression ~s" x)])) + (define (handle-vararg fml-count ac) + (define CONTINUE_LABEL (unique-label)) + (define DONE_LABEL (unique-label)) + (define CONS_LABEL (unique-label)) + (define LOOP_HEAD (unique-label)) + (define L_CALL (unique-label)) + (list* (cmpl (int (argc-convention (fxsub1 fml-count))) eax) + (jg (label SL_invalid_args)) + (jl CONS_LABEL) + (movl (int nil) ebx) + (jmp DONE_LABEL) + CONS_LABEL + (movl (pcb-ref 'allocation-redline) ebx) + (addl eax ebx) + (addl eax ebx) + (cmpl ebx apr) + (jle LOOP_HEAD) + ; overflow + (addl eax esp) ; advance esp to cover args + (pushl cpr) ; push current cp + (pushl eax) ; push argc + (negl eax) ; make argc positive + (addl (int (fx* 4 wordsize)) eax) ; add 4 words to adjust frame size + (pushl eax) ; push frame size + (addl eax eax) ; double the number of args + (movl eax (mem (fx* -2 wordsize) fpr)) ; pass it as first arg + (movl (int (argc-convention 1)) eax) ; setup argc + (movl (primref-loc 'do-vararg-overflow) cpr) ; load handler + (jmp L_CALL) ; go to overflow handler + ; NEW FRAME + (int 0) ; if the framesize=0, then the framesize is dynamic + '(current-frame-offset) + (int 0) ; multiarg rp + (byte 0) + (byte 0) + L_CALL + (indirect-cpr-call) + (popl eax) ; pop framesize and drop it + (popl eax) ; reload argc + (popl cpr) ; reload cp + (subl eax fpr) ; readjust fp + LOOP_HEAD + (movl (int nil) ebx) + CONTINUE_LABEL + (movl ebx (mem disp-cdr apr)) + (movl (mem fpr eax) ebx) + (movl ebx (mem disp-car apr)) + (movl apr ebx) + (addl (int pair-tag) ebx) + (addl (int pair-size) apr) + (addl (int (fxsll 1 fx-shift)) eax) + (cmpl (int (fx- 0 (fxsll fml-count fx-shift))) eax) + (jle CONTINUE_LABEL) + DONE_LABEL + (movl ebx (mem (fx- 0 (fxsll fml-count fx-shift)) fpr)) + ac)) + (define (Entry check? x ac) + (record-case x + [(clambda-case fml* proper body) + (let ([ac (Tail body ac)]) + (cond + [(and proper check?) + (list* (cmpl (int (argc-convention (length fml*))) eax) + (jne (label SL_invalid_args)) + ac)] + [proper ac] + [else + (handle-vararg (length fml*) ac)]))])) + (define make-dispatcher + (lambda (j? L L* x x* ac) + (cond + [(null? L*) (if j? (cons (jmp (label L)) ac) ac)] + [else + (record-case x + [(clambda-case fml* proper _) + (cond + [proper + (list* (cmpl (int (argc-convention (length fml*))) eax) + (je (label L)) + (make-dispatcher #t + (car L*) (cdr L*) (car x*) (cdr x*) ac))] + [else + (list* (cmpl (int (argc-convention (fxsub1 (length fml*)))) eax) + (jle (label L)) + (make-dispatcher #t + (car L*) (cdr L*) (car x*) (cdr x*) ac))])])]))) + (define (handle-cases x x*) + (let ([L* (map (lambda (_) (gensym)) x*)] + [L (gensym)]) + (make-dispatcher #f L L* x x* + (let f ([x x] [x* x*] [L L] [L* L*]) + (cond + [(null? x*) + (cons (label L) (Entry 'check x '()))] + [else + (cons (label L) + (Entry #f x + (f (car x*) (cdr x*) (car L*) (cdr L*))))]))))) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (list* + (length free) + (label L) + (handle-cases (car cases) (cdr cases)))])) + (record-case x + [(codes list body) + (cons (cons 0 (Tail body '())) + (map CodeExpr list))])) + + +(define SL_nonprocedure (gensym "SL_nonprocedure")) + +(define SL_top_level_value_error (gensym "SL_top_level_value_error")) +(define SL_car_error (gensym "SL_car_error")) +(define SL_cdr_error (gensym "SL_cdr_error")) + +(define SL_invalid_args (gensym "SL_invalid_args")) +(define SL_foreign_call (gensym "SL_foreign_call")) +(define SL_continuation_code (gensym "SL_continuation_code")) +(define SL_multiple_values_error_rp (gensym "SL_multiple_values_error_rp")) +(define SL_multiple_values_ignore_rp (gensym "SL_multiple_ignore_error_rp")) +(define SL_underflow_multiple_values (gensym "SL_underflow_multiple_values")) +(define SL_underflow_handler (gensym "SL_underflow_handler")) +(define SL_scheme_exit (gensym "SL_scheme_exit")) +(define SL_apply (gensym "SL_apply")) +(define SL_values (gensym "SL_values")) +(define SL_call_with_values (gensym "SL_call_with_values")) + +(module () +(list*->code* + (list + (list 0 + (label SL_car_error) + (movl ebx (mem (fx- 0 wordsize) fpr)) + (movl (primref-loc 'car-error) cpr) + (movl (int (argc-convention 1)) eax) + (tail-indirect-cpr-call)) + + (list 0 + (label SL_cdr_error) + (movl ebx (mem (fx- 0 wordsize) fpr)) + (movl (primref-loc 'cdr-error) cpr) + (movl (int (argc-convention 1)) eax) + (tail-indirect-cpr-call)) + + (list 0 + (label SL_top_level_value_error) + (movl ebx (mem (fx- 0 wordsize) fpr)) + (movl (primref-loc 'top-level-value-error) cpr) + (movl (int (argc-convention 1)) eax) + (tail-indirect-cpr-call)) + + (let ([L_cwv_done (gensym)] + [L_cwv_loop (gensym)] + [L_cwv_multi_rp (gensym)] + [L_cwv_call (gensym)]) + (list + 0 ; no free vars + (label SL_call_with_values) + (cmpl (int (argc-convention 2)) eax) + (jne (label SL_invalid_args)) + (movl (mem (fx- 0 wordsize) fpr) ebx) ; producer + (movl ebx cpr) + (andl (int closure-mask) ebx) + (cmpl (int closure-tag) ebx) + (jne (label SL_nonprocedure)) + (movl (int (argc-convention 0)) eax) + (subl (int (fx* wordsize 2)) fpr) + (jmp (label L_cwv_call)) + ; MV NEW FRAME + (byte-vector '#(#b110)) + (int (fx* wordsize 3)) + '(current-frame-offset) + (label-address L_cwv_multi_rp) + (byte 0) + (byte 0) + (label L_cwv_call) + (indirect-cpr-call) + ;;; one value returned + (addl (int (fx* wordsize 2)) fpr) + (movl (mem (fx* -2 wordsize) fpr) ebx) ; consumer + (movl ebx cpr) + (movl eax (mem (fx- 0 wordsize) fpr)) + (movl (int (argc-convention 1)) eax) + (andl (int closure-mask) ebx) + (cmpl (int closure-tag) ebx) + (jne (label SL_nonprocedure)) + (tail-indirect-cpr-call) + ;;; multiple values returned + (label L_cwv_multi_rp) + ; because values does not pop the return point + ; we have to adjust fp one more word here + (addl (int (fx* wordsize 3)) fpr) + (movl (mem (fx* -2 wordsize) fpr) cpr) ; consumer + (cmpl (int (argc-convention 0)) eax) + (je (label L_cwv_done)) + (movl (int (fx* -4 wordsize)) ebx) + (addl fpr ebx) ; ebx points to first value + (movl ebx ecx) + (addl eax ecx) ; ecx points to the last value + (label L_cwv_loop) + (movl (mem 0 ebx) edx) + (movl edx (mem (fx* 3 wordsize) ebx)) + (subl (int wordsize) ebx) + (cmpl ecx ebx) + (jge (label L_cwv_loop)) + (label L_cwv_done) + (movl cpr ebx) + (andl (int closure-mask) ebx) + (cmpl (int closure-tag) ebx) + (jne (label SL_nonprocedure)) + (tail-indirect-cpr-call))) + + (let ([L_values_one_value (gensym)] + [L_values_many_values (gensym)]) + (list 0 ; no freevars + (label SL_values) + (cmpl (int (argc-convention 1)) eax) + (je (label L_values_one_value)) + (label L_values_many_values) + (movl (mem 0 fpr) ebx) ; return point + (jmp (mem disp-multivalue-rp ebx)) ; go + (label L_values_one_value) + (movl (mem (fx- 0 wordsize) fpr) eax) + (ret))) + + (let ([L_apply_done (gensym)] + [L_apply_loop (gensym)]) + (list 0 + (label SL_apply) + (movl (mem fpr eax) ebx) + (cmpl (int nil) ebx) + (je (label L_apply_done)) + (label L_apply_loop) + (movl (mem (fx- disp-car pair-tag) ebx) ecx) + (movl (mem (fx- disp-cdr pair-tag) ebx) ebx) + (movl ecx (mem fpr eax)) + (subl (int wordsize) eax) + (cmpl (int nil) ebx) + (jne (label L_apply_loop)) + (label L_apply_done) + (addl (int wordsize) eax) + (tail-indirect-cpr-call))) + + (list 0 + (label SL_nonprocedure) + (movl cpr (mem (fx- 0 wordsize) fpr)) ; first arg + (movl (primref-loc '$apply-nonprocedure-error-handler) cpr) + (movl (int (argc-convention 1)) eax) + (tail-indirect-cpr-call)) + + (list 0 + (label SL_multiple_values_error_rp) + (movl (primref-loc '$multiple-values-error) cpr) + (tail-indirect-cpr-call)) + + (list 0 + (label SL_multiple_values_ignore_rp) + (ret)) + + (list 0 + (label SL_invalid_args) + ;;; + (movl cpr (mem (fx- 0 wordsize) fpr)) ; first arg + (negl eax) + (movl eax (mem (fx- 0 (fx* 2 wordsize)) fpr)) + (movl (primref-loc '$incorrect-args-error-handler) cpr) + (movl (int (argc-convention 2)) eax) + (tail-indirect-cpr-call)) + + (let ([Lset (gensym)] [Lloop (gensym)]) + (list 0 + (label SL_foreign_call) + (movl fpr (pcb-ref 'frame-pointer)) + (movl apr (pcb-ref 'allocation-pointer)) + (movl fpr ebx) + (movl (pcb-ref 'system-stack) esp) + (pushl pcr) + (cmpl (int 0) eax) + (je (label Lset)) + (label Lloop) + (movl (mem ebx eax) ecx) + (pushl ecx) + (addl (int 4) eax) + (cmpl (int 0) eax) + (jne (label Lloop)) + (label Lset) + ; FOREIGN NEW FRAME + (call cpr) + (movl (pcb-ref 'frame-pointer) fpr) + (movl (pcb-ref 'allocation-pointer) apr) + (ret))) + + (let ([L_cont_zero_args (gensym)] + [L_cont_mult_args (gensym)] + [L_cont_one_arg (gensym)] + [L_cont_mult_move_args (gensym)] + [L_cont_mult_copy_loop (gensym)]) + (list 1 ; freevars + (label SL_continuation_code) + (movl (mem (fx- disp-closure-data closure-tag) cpr) ebx) ; captured-k + (movl ebx (pcb-ref 'next-continuation)) ; set + (movl (pcb-ref 'frame-base) ebx) + (cmpl (int (argc-convention 1)) eax) + (jg (label L_cont_zero_args)) + (jl (label L_cont_mult_args)) + (label L_cont_one_arg) + (movl (mem (fx- 0 wordsize) fpr) eax) + (movl ebx fpr) + (subl (int wordsize) fpr) + (ret) + (label L_cont_zero_args) + (subl (int wordsize) ebx) + (movl ebx fpr) + (movl (mem 0 ebx) ebx) ; return point + (jmp (mem disp-multivalue-rp ebx)) ; go + (label L_cont_mult_args) + (subl (int wordsize) ebx) + (cmpl ebx fpr) + (jne (label L_cont_mult_move_args)) + (movl (mem 0 ebx) ebx) + (jmp (mem disp-multivalue-rp ebx)) + (label L_cont_mult_move_args) + ; move args from fpr to ebx + (movl (int 0) ecx) + (label L_cont_mult_copy_loop) + (subl (int wordsize) ecx) + (movl (mem fpr ecx) edx) + (movl edx (mem ebx ecx)) + (cmpl ecx eax) + (jne (label L_cont_mult_copy_loop)) + (movl ebx fpr) + (movl (mem 0 ebx) ebx) + (jmp (mem disp-multivalue-rp ebx)) + )) + ))) + + + +(define (compile-expr expr) + (let* ([p (recordize expr)] + [p (optimize-direct-calls p)] +;;; [foo (analyze-cwv p)] + [p (optimize-letrec p)] + ;[p (remove-letrec p)] + [p (remove-assignments p)] + [p (convert-closures p)] + [p (lift-codes p)] + [p (introduce-primcalls p)] + [p (simplify-operands p)] + [p (insert-stack-overflow-checks p)] + [p (insert-allocation-checks p)] + [p (remove-local-variables p)] + [p (optimize-ap-check p)] + [ls* (generate-code p)] + [f (when (assembler-output) + (for-each + (lambda (ls) + (for-each (lambda (x) (printf " ~s\n" x)) ls)) + ls*))] + [code* (list*->code* ls*)]) + (car code*))) + +(define compile-file + (lambda (input-file output-file . rest) + (let ([ip (open-input-file input-file)] + [op (apply open-output-file output-file rest)]) + (let f () + (let ([x (read ip)]) + (unless (eof-object? x) + (fasl-write (compile-expr (expand x)) op) + (f)))) + (close-input-port ip) + (close-output-port op)))) + +(primitive-set! 'compile-file compile-file) +(primitive-set! 'assembler-output (make-parameter #f)) +(primitive-set! 'compile + (lambda (x) + (let ([code (compile-expr (expand x))]) + (let ([proc ($code->closure code)]) + (proc))))) + +) + diff --git a/src/libcompile-8.1.ss b/src/libcompile-8.1.ss new file mode 100644 index 0000000..b25dcf3 --- /dev/null +++ b/src/libcompile-8.1.ss @@ -0,0 +1,3677 @@ + +;;; 6.7: * open-coded top-level-value, car, cdr +;;; 6.2: * side-effects now modify the dirty-vector +;;; * added bwp-object? +;;; * added pointer-value +;;; * added tcbuckets +;;; 6.1: * added case-lambda, dropped lambda +;;; 6.0: * basic compiler + +(let () + +(define-syntax cond-expand + (lambda (x) + (syntax-case x () + [(_ test conseq altern) + (if (eval (syntax-object->datum #'test)) + #'conseq + #'altern)]))) + +(cond-expand (eq? "" "") + (include "record-case.chez.ss") + (include "record-case.ss")) + + +(include "set-operations.ss") + + +(define open-coded-primitives +;;; these primitives, when found in operator position with the correct +;;; number of arguments, will be open-coded by the generator. If an +;;; incorrect number of args is detected, or if they appear in non-operator +;;; position, then they cannot be open-coded, and the pcb-primitives table +;;; is consulted for a reference of the pcb slot containing the primitive. +;;; If it's not found there, an error is signalled. +;;; +;;; prim-name args + '([$constant-ref 1 value] + [$constant-set! 2 effect] + [$pcb-ref 1 value] + [$pcb-set! 2 effect] + ;;; type predicates + [fixnum? 1 pred] + [immediate? 1 pred] + [boolean? 1 pred] + [char? 1 pred] + [pair? 1 pred] + [symbol? 1 pred] + [vector? 1 pred] + [string? 1 pred] + [procedure? 1 pred] + [null? 1 pred] + [eof-object? 1 pred] + [bwp-object? 1 pred] + [$unbound-object? 1 pred] + [$forward-ptr? 1 pred] + [not 1 pred] + [pointer-value 1 value] + [eq? 2 pred] + ;;; fixnum primitives + [$fxadd1 1 value] + [$fxsub1 1 value] + [$fx+ 2 value] + [$fx- 2 value] + [$fx* 2 value] + [$fxsll 2 value] + [$fxsra 2 value] + [$fxlogand 2 value] + [$fxlogor 2 value] + [$fxlogxor 2 value] + [$fxlognot 1 value] + [$fxquotient 2 value] + [$fxmodulo 2 value] + ;;; fixnum predicates + [$fxzero? 1 pred] + [$fx= 2 pred] + [$fx< 2 pred] + [$fx<= 2 pred] + [$fx> 2 pred] + [$fx>= 2 pred] + ;;; character predicates + [$char= 2 pred] + [$char< 2 pred] + [$char<= 2 pred] + [$char> 2 pred] + [$char>= 2 pred] + ;;; character conversion + [$fixnum->char 1 value] + [$char->fixnum 1 value] + ;;; lists/pairs + [cons 2 value] + [list* positive value] + [list any value] + [car 1 value] + [cdr 1 value] + [$car 1 value] + [$cdr 1 value] + [$set-car! 2 effect] + [$set-cdr! 2 effect] + ;;; vectors + [$make-vector 1 value] + [vector any value] + [$vector-length 1 value] + [$vector-ref 2 value] + [$vector-set! 3 effect] + [$vector-memq 2 value] + ;;; strings + [$make-string 1 value] + [$string any value] + [$string-length 1 value] + [$string-ref 2 value] + [$string-set! 3 effect] + ;;; symbols + [$make-symbol 1 value] + [$symbol-value 1 value] + [$symbol-string 1 value] + [$symbol-unique-string 1 value] + [$set-symbol-value! 2 effect] + [$set-symbol-string! 2 effect] + [$set-symbol-unique-string! 2 effect] + [$symbol-plist 1 value] + [$set-symbol-plist! 2 effect] + [primitive-ref 1 value] + [primitive-set! 2 effect] + [top-level-value 1 value] + ;;; ports + [port? 1 pred] + [input-port? 1 pred] + [output-port? 1 pred] + [$make-port 7 value] + [$port-handler 1 value] + [$port-input-buffer 1 value] + [$port-input-index 1 value] + [$port-input-size 1 value] + [$port-output-buffer 1 value] + [$port-output-index 1 value] + [$port-output-size 1 value] + [$set-port-input-index! 2 effect] + [$set-port-input-size! 2 effect] + [$set-port-output-index! 2 effect] + [$set-port-output-size! 2 effect] + ;;; tcbuckets + [$make-tcbucket 4 value] + [$tcbucket-key 1 value] + [$tcbucket-val 1 value] + [$tcbucket-next 1 value] + [$set-tcbucket-val! 2 effect] + [$set-tcbucket-next! 2 effect] + [$set-tcbucket-tconc! 2 effect] + ;;; misc + [eof-object 0 value] + [void 0 value] + [$exit 1 effect] + [$fp-at-base 0 pred] + [$current-frame 0 value] + [$seal-frame-and-call 1 tail] + [$frame->continuation 1 value] + ;;; + ;;; records + ;;; + [$make-record 2 value] + [$record? 1 pred] + [$record/rtd? 2 pred] + [$record-rtd 1 value] + [$record-ref 2 value] + [$record-set! 3 effect] + [$record any value] + ;;; + ;;; asm + ;;; + [$code? 1 pred] + [$code-size 1 value] + [$code-reloc-vector 1 value] + [$code-freevars 1 value] + [$code-ref 2 value] + [$code-set! 3 value] + [$code->closure 1 value] + ;;; + [$make-call-with-values-procedure 0 value] + [$make-values-procedure 0 value] + [$install-underflow-handler 0 effect] + )) + +(define (primitive-context x) + (cond + [(assq x open-coded-primitives) => caddr] + [else (error 'primitive-context "unknown prim ~s" x)])) + +(define (open-codeable? x) + (cond + [(assq x open-coded-primitives) #t] + [else #f])) + +(define (open-coded-primitive-args x) + (cond + [(assq x open-coded-primitives) => cadr] + [else (error 'open-coded-primitive-args "invalid ~s" x)])) + +;;; end of primitives table section + + +(define-record constant (value)) +(define-record code-loc (label)) +(define-record foreign-label (label)) +(define-record var (name assigned)) +(define-record cp-var (idx)) +(define-record frame-var (idx)) +(define-record new-frame (base-idx size body)) +(define-record save-cp (loc)) +(define-record eval-cp (check body)) +(define-record return (value)) +(define-record call-cp + (call-convention rp-convention base-idx arg-count live-mask)) +(define-record tailcall-cp (convention arg-count)) +(define-record primcall (op arg*)) +(define-record primref (name)) +(define-record conditional (test conseq altern)) +(define-record bind (lhs* rhs* body)) +(define-record recbind (lhs* rhs* body)) +(define-record fix (lhs* rhs* body)) + +(define-record seq (e0 e1)) +(define-record clambda-case (arg* proper body)) +(define-record clambda (cases)) +(define-record clambda-code (label cases free)) +(define-record closure (code free*)) +(define-record funcall (op rand*)) +(define-record appcall (op rand*)) +(define-record forcall (op rand*)) +(define-record code-rec (arg* proper free* body)) +(define-record codes (list body)) +(define-record assign (lhs rhs)) + +(define (unique-var x) + (make-var (gensym (symbol->string x)) #f)) + + +(define (make-bind^ lhs* rhs* body) + (if (null? lhs*) + body + (make-bind lhs* rhs* body))) + +(define (recordize x) + (define (gen-fml* fml*) + (cond + [(pair? fml*) + (cons (unique-var (car fml*)) + (gen-fml* (cdr fml*)))] + [(symbol? fml*) + (unique-var fml*)] + [else '()])) + (define (properize fml*) + (cond + [(pair? fml*) + (cons (car fml*) (properize (cdr fml*)))] + [(null? fml*) '()] + [else (list fml*)])) + (define (extend-env fml* nfml* env) + (cons (cons fml* nfml*) env)) + (define (quoted-sym x) + (if (and (list? x) + (fx= (length x) 2) + (eq? 'quote (car x)) + (symbol? (cadr x))) + (cadr x) + (error 'quoted-sym "not a quoted symbol ~s" x))) + (define (quoted-string x) + (if (and (list? x) + (fx= (length x) 2) + (eq? 'quote (car x)) + (string? (cadr x))) + (cadr x) + (error 'quoted-string "not a quoted string ~s" x))) + (define (lookup^ x lhs* rhs*) + (cond + [(pair? lhs*) + (if (eq? x (car lhs*)) + (car rhs*) + (lookup^ x (cdr lhs*) (cdr rhs*)))] + [(eq? x lhs*) rhs*] + [else #f])) + (define (lookup x env) + (cond + [(pair? env) + (or (lookup^ x (caar env) (cdar env)) + (lookup x (cdr env)))] + [else #f])) + (define (E x env) + (cond + [(pair? x) + (case (car x) + [(quote) (make-constant (cadr x))] + [(if) + (make-conditional + (E (cadr x) env) + (E (caddr x) env) + (E (cadddr x) env))] + [(set!) + (let ([lhs (cadr x)] [rhs (caddr x)]) + (make-assign + (or (lookup lhs env) + (error 'recordize "invalid assignment ~s" x)) + (E rhs env)))] + [(begin) + (let f ([a (cadr x)] [d (cddr x)]) + (cond + [(null? d) (E a env)] + [else + (make-seq + (E a env) + (f (car d) (cdr d)))]))] + [(letrec) + (unless (fx= (length x) 3) (syntax-error x)) + (let ([bind* (cadr x)] [body (caddr x)]) + (let ([lhs* (map car bind*)] + [rhs* (map cadr bind*)]) + (let ([nlhs* (gen-fml* lhs*)]) + (let ([env (extend-env lhs* nlhs* env)]) + (make-recbind nlhs* + (map (lambda (rhs) (E rhs env)) rhs*) + (E body env))))))] + [(letrec) + (unless (fx= (length x) 3) (syntax-error x)) + (let ([bind* (cadr x)] [body (caddr x)]) + (let ([lhs* (map car bind*)] + [rhs* (map cadr bind*)] + [v* (map (lambda (x) '(void)) bind*)] + [t* (map (lambda (x) (gensym)) bind*)]) + (E `((case-lambda + [,lhs* + ((case-lambda + [,t* + (begin ,@(map (lambda (x v) `(set! ,x ,v)) lhs* t*) + ,body)]) + ,@rhs*)]) + ,@v*) + env)))] + [(case-lambda) + (let ([cls* + (map + (lambda (cls) + (let ([fml* (car cls)] [body (cadr cls)]) + (let ([nfml* (gen-fml* fml*)]) + (let ([body (E body (extend-env fml* nfml* env))]) + (make-clambda-case + (properize nfml*) + (list? fml*) + body))))) + (cdr x))]) + (make-clambda cls*))] + [(foreign-call) + (let ([name (quoted-string (cadr x))] [arg* (cddr x)]) + (make-forcall name + (map (lambda (x) (E x env)) arg*)))] + [(|#primitive|) + (let ([var (cadr x)]) + (make-primref var))] + ;;; [(|#primitive|) + ;;; (let ([var (cadr x)]) + ;;; (if (primitive? var) + ;;; (make-primref var) + ;;; (error 'recordize "invalid primitive ~s" var)))] + [(top-level-value) + (let ([var (quoted-sym (cadr x))]) + (if (eq? (expand-mode) 'bootstrap) + ;(error 'compile "reference to ~s in bootstrap mode" var) + (make-primref var) + (make-funcall + (make-primref 'top-level-value) + (list (make-constant var)))))] + ;;; [(top-level-value) + ;;; (let ([var (quoted-sym (cadr x))]) + ;;; (if (eq? (expand-mode) 'bootstrap) + ;;; (if (primitive? var) + ;;; (make-primref var) + ;;; (error 'compile "invalid primitive ~s" var)) + ;;; (make-funcall + ;;; (make-primref 'top-level-value) + ;;; (list (make-constant var)))))] + [(set-top-level-value!) + (make-funcall (make-primref 'set-top-level-value!) + (map (lambda (x) (E x env)) (cdr x)))] + [(memv) + (make-funcall + (make-primref 'memq) + (map (lambda (x) (E x env)) (cdr x)))] + [($apply) + (let ([proc (cadr x)] [arg* (cddr x)]) + (make-appcall + (E proc env) + (map (lambda (x) (E x env)) arg*)))] + [(void) + (make-constant (void))] + [else + (make-funcall + (E (car x) env) + (map (lambda (x) (E x env)) (cdr x)))])] + [(symbol? x) + (or (lookup x env) + (error 'recordize "invalid reference in ~s" x))] + [else (error 'recordize "invalid expression ~s" x)])) + (E x '())) + + +(define (unparse x) + (define (E-args proper x) + (if proper + (map E x) + (let f ([a (car x)] [d (cdr x)]) + (cond + [(null? d) (E a)] + [else (cons (E a) (f (car d) (cdr d)))])))) + (define (E x) + (record-case x + [(constant c) `(quote ,c)] + [(code-loc x) `(code-loc ,x)] + [(var x) (string->symbol (format "v:~a" x))] + [(primref x) x] + [(conditional test conseq altern) + `(if ,(E test) ,(E conseq) ,(E altern))] + [(primcall op arg*) `(,op . ,(map E arg*))] + [(bind lhs* rhs* body) + `(let ,(map (lambda (lhs rhs) (list (E lhs) (E rhs))) lhs* rhs*) + ,(E body))] + [(recbind lhs* rhs* body) + `(letrec ,(map (lambda (lhs rhs) (list (E lhs) (E rhs))) lhs* rhs*) + ,(E body))] + [(fix lhs* rhs* body) + `(fix ,(map (lambda (lhs rhs) (list (E lhs) (E rhs))) lhs* rhs*) + ,(E body))] + [(seq e0 e1) `(begin ,(E e0) ,(E e1))] + [(clambda-case args proper body) + `(clambda-case ,(E-args proper args) ,(E body))] + [(clambda cls*) + `(case-lambda . ,(map E cls*))] + [(clambda-code label clauses free) + `(code ,label . ,(map E clauses))] + [(closure code free*) + `(closure ,(E code) ,(map E free*))] + [(code-rec arg* proper free* body) + `(code-rec [arg: ,(E-args proper arg*)] + [free: ,(map E free*)] + ,(E body))] + [(codes list body) + `(codes ,(map E list) + ,(E body))] + [(funcall rator rand*) `(funcall ,(E rator) . ,(map E rand*))] + [(appcall rator rand*) `(appcall ,(E rator) . ,(map E rand*))] + [(forcall rator rand*) `(foreign-call ,rator . ,(map E rand*))] + [(assign lhs rhs) `(set! ,(E lhs) ,(E rhs))] + [(return x) `(return ,(E x))] + [(new-frame base-idx size body) + `(new-frame [base: ,base-idx] + [size: ,size] + ,(E body))] + [(frame-var idx) + (string->symbol (format "fv.~a" idx))] + [(cp-var idx) + (string->symbol (format "cp.~a" idx))] + [(save-cp expr) + `(save-cp ,(E expr))] + [(eval-cp check body) + `(eval-cp ,check ,(E body))] + [(call-cp call-convention rp-convention base-idx arg-count live-mask) + `(call-cp [conv: ,call-convention] + [rpconv: ,rp-convention] + [base-idx: ,base-idx] + [arg-count: ,arg-count] + [live-mask: ,live-mask])] + [(foreign-label x) `(foreign-label ,x)] + [else (error 'unparse "invalid record ~s" x)])) + (E x)) + +(define (optimize-direct-calls x) + (define who 'optimize-direct-calls) + (define (make-conses ls) + (cond + [(null? ls) (make-constant '())] + [else + (make-primcall 'cons + (list (car ls) (make-conses (cdr ls))))])) + (define (properize lhs* rhs*) + (cond + [(null? lhs*) (error who "improper improper")] + [(null? (cdr lhs*)) + (list (make-conses rhs*))] + [else (cons (car rhs*) (properize (cdr lhs*) (cdr rhs*)))])) + (define (inline-case cls rand*) + (record-case cls + [(clambda-case fml* proper body) + (if proper + (and (fx= (length fml*) (length rand*)) + (make-bind fml* rand* body)) + (and (fx<= (length fml*) (length rand*)) + (make-bind fml* (properize fml* rand*) body)))])) + (define (try-inline cls* rand* default) + (cond + [(null? cls*) default] + [(inline-case (car cls*) rand*)] + [else (try-inline (cdr cls*) rand* default)])) + (define (inline rator rand*) + (record-case rator + [(clambda cls*) + (try-inline cls* rand* + (make-funcall rator rand*))] + [else (make-funcall rator rand*)])) + (define (Expr x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Expr body))] + [(recbind lhs* rhs* body) + (make-recbind lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional + (Expr test) + (Expr conseq) + (Expr altern))] + [(seq e0 e1) + (make-seq (Expr e0) (Expr e1))] + [(clambda cls*) + (make-clambda + (map (lambda (x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (Expr body))])) + cls*))] + [(primcall rator rand*) + (make-primcall rator (map Expr rand*))] + [(funcall rator rand*) + (inline (Expr rator) (map Expr rand*))] + [(appcall rator rand*) + (make-appcall (Expr rator) (map Expr rand*))] + [(forcall rator rand*) + (make-forcall rator (map Expr rand*))] + [(assign lhs rhs) + (make-assign lhs (Expr rhs))] + [else (error who "invalid expression ~s" (unparse x))])) + (Expr x)) + + + + +(define lambda-both 0) +(define lambda-producer 0) +(define lambda-consumer 0) +(define lambda-none 0) +(define branching-producer 0) + + +(define (analyze-cwv x) + (define who 'analyze-cwv) + (define (lambda? x) + (record-case x + [(clambda) #t] + [else #f])) + (define (branching-producer? x) + (define (bt? x) + (record-case x + [(bind lhs* rhs* body) (bt? body)] + [(recbind lhs* rhs* body) (bt? body)] + [(conditional test conseq altern) #t] + [(seq e0 e1) (bt? e1)] + [else #f])) + (define (branching-clause? x) + (record-case x + [(clambda-case fml* proper body) + (bt? body)])) + (record-case x + [(clambda cls*) + (ormap branching-clause? cls*)] + [else #f])) + (define (analyze producer consumer) + (cond + [(and (lambda? producer) (lambda? consumer)) + (set! lambda-both (fxadd1 lambda-both))] + [(lambda? producer) + (set! lambda-producer (fxadd1 lambda-producer))] + [(lambda? consumer) + (set! lambda-consumer (fxadd1 lambda-consumer))] + [else + (set! lambda-none (fxadd1 lambda-none))]) + (when (branching-producer? producer) + (set! branching-producer (fxadd1 branching-producer))) + (printf "both=~s p=~s c=~s none=~s branching-prod=~s\n" + lambda-both lambda-producer lambda-consumer lambda-none + branching-producer)) + (define (E x) + (record-case x + [(constant) (void)] + [(var) (void)] + [(primref) (void)] + [(bind lhs* rhs* body) + (for-each E rhs*) (E body)] + [(recbind lhs* rhs* body) + (for-each E rhs*) (E body)] + [(conditional test conseq altern) + (E test) + (E conseq) + (E altern)] + [(seq e0 e1) (E e0) (E e1)] + [(clambda cls*) + (for-each + (lambda (x) + (record-case x + [(clambda-case fml* proper body) (E body)])) + cls*)] + [(primcall rator rand*) + (for-each E rand*) + (when (and (eq? rator 'call-with-values) (fx= (length rand*) 2)) + (analyze (car rand*) (cadr rand*)))] + [(funcall rator rand*) + (E rator) (for-each E rand*) + (when (and (record-case rator + [(primref op) (eq? op 'call-with-values)] + [else #f]) + (fx= (length rand*) 2)) + (analyze (car rand*) (cadr rand*)))] + [(appcall rator rand*) + (E rator) (for-each E rand*)] + [(forcall rator rand*) + (for-each E rand*)] + [(assign lhs rhs) + (E rhs)] + [else (error who "invalid expression ~s" (unparse x))])) + (E x)) + + + + +(define (optimize-letrec x) + (define who 'optimize-letrec) + (define (extend-hash lhs* h ref) + (for-each (lambda (lhs) (put-hash-table! h lhs #t)) lhs*) + (lambda (x) + (unless (get-hash-table h x #f) + (put-hash-table! h x #t) + (ref x)))) + (define (E* x* ref comp) + (cond + [(null? x*) '()] + [else + (cons (E (car x*) ref comp) + (E* (cdr x*) ref comp))])) + (define (do-rhs* i lhs* rhs* ref comp vref vcomp) + (cond + [(null? rhs*) '()] + [else + (let ([h (make-hash-table)]) + (let ([ref + (lambda (x) + (unless (get-hash-table h x #f) + (put-hash-table! h x #t) + (ref x) + (when (memq x lhs*) + (vector-set! vref i #t))))] + [comp + (lambda () + (vector-set! vcomp i #t) + (comp))]) + (cons (E (car rhs*) ref comp) + (do-rhs* (fxadd1 i) lhs* (cdr rhs*) ref comp vref vcomp))))])) + (define (partition-rhs* i lhs* rhs* vref vcomp) + (cond + [(null? lhs*) (values '() '() '() '() '() '())] + [else + (let-values + ([(slhs* srhs* llhs* lrhs* clhs* crhs*) + (partition-rhs* (fxadd1 i) (cdr lhs*) (cdr rhs*) vref vcomp)] + [(lhs rhs) (values (car lhs*) (car rhs*))]) + (cond + [(var-assigned lhs) + (values slhs* srhs* llhs* lrhs* (cons lhs clhs*) (cons rhs crhs*))] + [(clambda? rhs) + (values slhs* srhs* (cons lhs llhs*) (cons rhs lrhs*) clhs* crhs*)] + [(or (vector-ref vref i) (vector-ref vcomp i)) + (values slhs* srhs* llhs* lrhs* (cons lhs clhs*) (cons rhs crhs*))] + [else + (values (cons lhs slhs*) (cons rhs srhs*) llhs* lrhs* clhs* crhs*)] + ))])) + (define (do-recbind lhs* rhs* body ref comp) + (let ([h (make-hash-table)] + [vref (make-vector (length lhs*) #f)] + [vcomp (make-vector (length lhs*) #f)]) + (let* ([ref (extend-hash lhs* h ref)] + [body (E body ref comp)]) + (let ([rhs* (do-rhs* 0 lhs* rhs* ref comp vref vcomp)]) + (let-values ([(slhs* srhs* llhs* lrhs* clhs* crhs*) + (partition-rhs* 0 lhs* rhs* vref vcomp)]) + (let ([v* (map (lambda (x) (make-primcall 'void '())) clhs*)] + [t* (map (lambda (x) (unique-var 'tmp)) clhs*)]) + (make-bind slhs* srhs* + (make-bind clhs* v* + (make-fix llhs* lrhs* + (make-bind t* crhs* + (build-assign* clhs* t* body))))))))))) + (define (build-assign* lhs* rhs* body) + (cond + [(null? lhs*) body] + [else + (make-seq + (make-assign (car lhs*) (car rhs*)) + (build-assign* (cdr lhs*) (cdr rhs*) body))])) + (define (E x ref comp) + (record-case x + [(constant) x] + [(var) (ref x) x] + [(assign lhs rhs) + (set-var-assigned! lhs #t) + (ref lhs) + (make-assign lhs (E rhs ref comp))] + [(primref) x] + [(bind lhs* rhs* body) + (let ([rhs* (E* rhs* ref comp)]) + (let ([h (make-hash-table)]) + (let ([body (E body (extend-hash lhs* h ref) comp)]) + (make-bind lhs* rhs* body))))] + [(recbind lhs* rhs* body) + (if (null? lhs*) + (E body ref comp) + (do-recbind lhs* rhs* body ref comp))] + [(conditional e0 e1 e2) + (make-conditional (E e0 ref comp) (E e1 ref comp) (E e2 ref comp))] + [(seq e0 e1) (make-seq (E e0 ref comp) (E e1 ref comp))] + [(clambda cls*) + (make-clambda + (map (lambda (x) + (record-case x + [(clambda-case fml* proper body) + (let ([h (make-hash-table)]) + (let ([body (E body (extend-hash fml* h ref) void)]) + (make-clambda-case fml* proper body)))])) + cls*))] + [(primcall rator rand*) + (when (memq rator '(call/cc call/cf)) + (comp)) + (make-primcall rator (E* rand* ref comp))] + [(funcall rator rand*) + (let ([rator (E rator ref comp)] [rand* (E* rand* ref comp)]) + (record-case rator + [(primref op) + (when (memq op '(call/cc call/cf)) + (comp))] + [else + (comp)]) + (make-funcall rator rand*))] + [(appcall rator rand*) + (let ([rator (E rator ref comp)] [rand* (E* rand* ref comp)]) + (record-case rator + [(primref op) + (when (memq op '(call/cc call/cf)) + (comp))] + [else + (comp)]) + (make-appcall rator rand*))] + [(forcall rator rand*) + (make-forcall rator (E* rand* ref comp))] + [else (error who "invalid expression ~s" (unparse x))])) + (E x (lambda (x) (error who "free var ~s found" x)) + void)) + + +(define (remove-letrec x) + (define who 'remove-letrec) + (define (Expr x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Expr body))] + [(recbind lhs* rhs* body) + (let ([t* (map (lambda (lhs) (unique-var 'tmp)) lhs*)] + [v* (map (lambda (lhs) (make-primcall 'void '())) lhs*)]) + (make-bind lhs* v* + (make-bind t* (map Expr rhs*) + (let f ([lhs* lhs*] [t* t*]) + (cond + [(null? lhs*) (Expr body)] + [else + (make-seq + (make-assign (car lhs*) (car t*)) + (f (cdr lhs*) (cdr t*)))])))))] + ;[(fix lhs* rhs* body) + ; (Expr (make-recbind lhs* rhs* body))] + [(fix lhs* rhs* body) + (make-fix lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional + (Expr test) + (Expr conseq) + (Expr altern))] + [(seq e0 e1) + (make-seq (Expr e0) (Expr e1))] + [(clambda cls*) + (make-clambda + (map (lambda (x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (Expr body))])) + cls*))] + [(primcall rator rand*) + (make-primcall rator (map Expr rand*))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall rator rand*) + (make-appcall (Expr rator) (map Expr rand*))] + [(forcall rator rand*) + (make-forcall rator (map Expr rand*))] + [(assign lhs rhs) + (make-assign lhs (Expr rhs))] + [else (error who "invalid expression ~s" (unparse x))])) + (Expr x)) + + + +(define (uncover-assigned x) + (define who 'uncover-assigned) + (define (Expr* x*) + (for-each Expr x*)) + (define (Expr x) + (record-case x + [(constant) (void)] + [(var) (void)] + [(primref) (void)] + [(bind lhs* rhs* body) + (begin (Expr body) (Expr* rhs*))] + [(recbind lhs* rhs* body) + (begin (Expr body) (Expr* rhs*))] + [(fix lhs* rhs* body) + (Expr* rhs*) + (Expr body) + (when (ormap var-assigned lhs*) + (error 'uncover-assigned "a fix lhs is assigned"))] + [(conditional test conseq altern) + (begin (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (begin (Expr e0) (Expr e1))] + [(clambda cls*) + (for-each + (lambda (cls) + (Expr (clambda-case-body cls))) + cls*)] + [(primcall rator rand*) (Expr* rand*)] + [(funcall rator rand*) + (begin (Expr rator) (Expr* rand*))] + [(appcall rator rand*) + (begin (Expr rator) (Expr* rand*))] + [(forcall rator rand*) (Expr* rand*)] + [(assign lhs rhs) + (set-var-assigned! lhs #t) + (Expr rhs)] + [else (error who "invalid expression ~s" (unparse x))])) + (Expr x)) + + + +(define (rewrite-assignments x) + (define who 'rewrite-assignments) + (define (fix-lhs* lhs*) + (cond + [(null? lhs*) (values '() '() '())] + [else + (let ([x (car lhs*)]) + (let-values ([(lhs* a-lhs* a-rhs*) (fix-lhs* (cdr lhs*))]) + (cond + [(var-assigned x) + (let ([t (unique-var 'assignment-tmp)]) + (values (cons t lhs*) (cons x a-lhs*) (cons t a-rhs*)))] + [else + (values (cons x lhs*) a-lhs* a-rhs*)])))])) + (define (bind-assigned lhs* rhs* body) + (cond + [(null? lhs*) body] + [else + (make-bind lhs* + (map (lambda (rhs) (make-primcall 'vector (list rhs))) rhs*) + body)])) + (define (Expr x) + (record-case x + [(constant) x] + [(var) + (cond + [(var-assigned x) + (make-primcall '$vector-ref (list x (make-constant 0)))] + [else x])] + [(primref) x] + [(bind lhs* rhs* body) + (let-values ([(lhs* a-lhs* a-rhs*) (fix-lhs* lhs*)]) + (make-bind lhs* (map Expr rhs*) + (bind-assigned a-lhs* a-rhs* (Expr body))))] + [(fix lhs* rhs* body) + (make-fix lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (make-seq (Expr e0) (Expr e1))] + [(clambda cls*) + (make-clambda + (map (lambda (cls) + (record-case cls + [(clambda-case fml* proper body) + (let-values ([(fml* a-lhs* a-rhs*) (fix-lhs* fml*)]) + (make-clambda-case fml* proper + (bind-assigned a-lhs* a-rhs* (Expr body))))])) + cls*))] + [(primcall op rand*) + (make-primcall op (map Expr rand*))] + [(forcall op rand*) + (make-forcall op (map Expr rand*))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall rator rand*) + (make-appcall (Expr rator) (map Expr rand*))] + [(assign lhs rhs) + (unless (var-assigned lhs) + (error 'rewrite-assignments "not assigned ~s in ~s" lhs x)) + (make-primcall '$vector-set! (list lhs (make-constant 0) (Expr rhs)))] + [else (error who "invalid expression ~s" (unparse x))])) + (Expr x)) + + +(define (remove-assignments x) + (uncover-assigned x) + (rewrite-assignments x)) + + + + + +(define (convert-closures prog) + (define who 'convert-closures) + (define (Expr* x*) + (cond + [(null? x*) (values '() '())] + [else + (let-values ([(a a-free) (Expr (car x*))] + [(d d-free) (Expr* (cdr x*))]) + (values (cons a d) (union a-free d-free)))])) + (define (do-clambda* x*) + (cond + [(null? x*) (values '() '())] + [else + (let-values ([(a a-free) (do-clambda (car x*))] + [(d d-free) (do-clambda* (cdr x*))]) + (values (cons a d) (union a-free d-free)))])) + (define (do-clambda x) + (record-case x + [(clambda cls*) + (let-values ([(cls* free) + (let f ([cls* cls*]) + (cond + [(null? cls*) (values '() '())] + [else + (record-case (car cls*) + [(clambda-case fml* proper body) + (let-values ([(body body-free) (Expr body)] + [(cls* cls*-free) (f (cdr cls*))]) + (values + (cons (make-clambda-case fml* proper body) + cls*) + (union (difference body-free fml*) + cls*-free)))])]))]) + (values (make-closure (make-clambda-code (gensym) cls* free) free) + free))])) + (define (Expr ex) + (record-case ex + [(constant) (values ex '())] + [(var) (values ex (singleton ex))] + [(primref) (values ex '())] + [(bind lhs* rhs* body) + (let-values ([(rhs* rhs-free) (Expr* rhs*)] + [(body body-free) (Expr body)]) + (values (make-bind lhs* rhs* body) + (union rhs-free (difference body-free lhs*))))] + [(fix lhs* rhs* body) + (let-values ([(rhs* rfree) (do-clambda* rhs*)] + [(body bfree) (Expr body)]) + (values (make-fix lhs* rhs* body) + (difference (union bfree rfree) lhs*)))] + [(conditional test conseq altern) + (let-values ([(test test-free) (Expr test)] + [(conseq conseq-free) (Expr conseq)] + [(altern altern-free) (Expr altern)]) + (values (make-conditional test conseq altern) + (union test-free (union conseq-free altern-free))))] + [(seq e0 e1) + (let-values ([(e0 e0-free) (Expr e0)] + [(e1 e1-free) (Expr e1)]) + (values (make-seq e0 e1) (union e0-free e1-free)))] + [(clambda) + (do-clambda ex)] + [(primcall op rand*) + (let-values ([(rand* rand*-free) (Expr* rand*)]) + (values (make-primcall op rand*) rand*-free))] + [(forcall op rand*) + (let-values ([(rand* rand*-free) (Expr* rand*)]) + (values (make-forcall op rand*) rand*-free))] + [(funcall rator rand*) + (let-values ([(rator rat-free) (Expr rator)] + [(rand* rand*-free) (Expr* rand*)]) + (values (make-funcall rator rand*) + (union rat-free rand*-free)))] + [(appcall rator rand*) + (let-values ([(rator rat-free) (Expr rator)] + [(rand* rand*-free) (Expr* rand*)]) + (values (make-appcall rator rand*) + (union rat-free rand*-free)))] + [else (error who "invalid expression ~s" (unparse ex))])) + (let-values ([(prog free) (Expr prog)]) + (unless (null? free) + (error 'convert-closures "free vars ~s encountered in ~a" + free (unparse prog))) + prog)) + + +(define (lift-codes x) + (define who 'lift-codes) + (define all-codes '()) + (define (do-code x) + (record-case x + [(clambda-code label cls* free) + (let ([cls* (map + (lambda (x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (E body))])) + cls*)]) + (let ([g (make-code-loc label)]) + (set! all-codes + (cons (make-clambda-code label cls* free) all-codes)) + g))])) + (define (E x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(bind lhs* rhs* body) + (make-bind lhs* (map E rhs*) (E body))] + [(fix lhs* rhs* body) + (make-fix lhs* (map E rhs*) (E body))] + [(conditional test conseq altern) + (make-conditional (E test) (E conseq) (E altern))] + [(seq e0 e1) (make-seq (E e0) (E e1))] + [(closure c free) (make-closure (do-code c) free)] + [(primcall op rand*) (make-primcall op (map E rand*))] + [(forcall op rand*) (make-forcall op (map E rand*))] + [(funcall rator rand*) (make-funcall (E rator) (map E rand*))] + [(appcall rator rand*) (make-appcall (E rator) (map E rand*))] + [else (error who "invalid expression ~s" (unparse x))])) + (let ([x (E x)]) + (make-codes all-codes x))) + + + + +(define (syntactically-valid? op rand*) + (define (valid-arg-count? op rand*) + (let ([n (open-coded-primitive-args op)] [m (length rand*)]) + (cond + [(eq? n 'any) #t] + [(eq? n 'positive) (fx> m 1)] + [(eq? n 'no-code) + (error 'syntactically-valid + "should not primcall non codable prim ~s" op)] + [(fixnum? n) + (cond + [(fx= n m) #t] + [else + (error 'compile + "Possible incorrect number of args in ~s" + (cons op (map unparse rand*))) + #f])] + [else (error 'do-primcall "BUG: what ~s" n)]))) + (define (check op pred?) + (lambda (arg) + (record-case arg + [(constant c) + (cond + [(pred? c) #t] + [else + (error 'compile "Possible argument error to primitive ~s" op) + #f])] + [(primref) + (cond + [(pred? (lambda (x) x)) #t] + [else + (error 'compile "Possible argument error to primitive ~s" op) + #f])] + [else #t]))) + (define (nonnegative-fixnum? n) + (and (fixnum? n) (fx>= n 0))) + (define (byte? n) + (and (fixnum? n) (fx<= 0 n) (fx<= n 127))) + (define (valid-arg-types? op rand*) + (case op + [(fixnum? immediate? boolean? char? vector? string? procedure? + null? pair? not cons eq? vector symbol? error eof-object eof-object? + void $unbound-object? $code? $forward-ptr? bwp-object? + pointer-value top-level-value car cdr list* list $record) + '#t] + [($fxadd1 $fxsub1 $fxzero? $fxlognot $fxlogor $fxlogand $fx+ $fx- $fx* + $fx= $fx< $fx<= $fx> $fx>= $fxquotient $fxmodulo $fxsll $fxsra $fxlogxor $exit) + (andmap (check op fixnum?) rand*)] + [($fixnum->char) + (andmap (check op byte?) rand*)] + [($char->fixnum $char= $char< $char<= $char> $char>= $string) + (andmap (check op char?) rand*)] + [($make-vector $make-string) + (andmap (check op nonnegative-fixnum?) rand*)] + [($car $cdr) + (andmap (check op pair?) rand*)] + [($vector-length) + (andmap (check op vector?) rand*)] + [($string-length) + (andmap (check op string?) rand*)] + [($set-car! $set-cdr!) + ((check op pair?) (car rand*))] + [($vector-ref $vector-set!) + (and ((check op vector?) (car rand*)) + ((check op nonnegative-fixnum?) (cadr rand*)))] + [($string-ref $string-set! + $string-ref-16+0 $string-ref-16+1 $string-ref-8+0 $string-ref-8+2) + (and ((check op string?) (car rand*)) + ((check op nonnegative-fixnum?) (cadr rand*)))] + [($symbol-string $symbol-unique-string) + (andmap (check op symbol?) rand*)] + [($constant-ref $set-constant! $intern $pcb-set! $pcb-ref $make-symbol + $symbol-value $set-symbol-value! $symbol-plist $set-symbol-plist! + $set-symbol-system-value! $set-symbol-system-value! + $set-symbol-unique-string! + $set-symbol-string! + $seal-frame-and-call $frame->continuation $code->closure + $code-size $code-reloc-vector $code-freevars + $code-ref $code-set! + $make-record $record? $record/rtd? $record-rtd $record-ref $record-set! + primitive-set! primitive-ref + $make-tcbucket $tcbucket-key $tcbucket-val $tcbucket-next + $set-tcbucket-val! $set-tcbucket-next! $set-tcbucket-tconc!) + #t] + [else (error 'valid-arg-types? "unhandled op ~s" op)])) + (and (valid-arg-count? op rand*) + (or (null? rand*) + (valid-arg-types? op rand*)))) + + +;;; the output of simplify-operands differs from the input in that the +;;; operands to primcalls are all simple (variables, primrefs, or constants). +;;; funcalls to open-codable primrefs whos arguments are "ok" are converted to +;;; primcalls. + + +(define uninlined '()) +(define (mark-uninlined x) + (cond + [(assq x uninlined) => + (lambda (p) (set-cdr! p (fxadd1 (cdr p))))] + [else (set! uninlined (cons (cons x 1) uninlined))])) + +(module () + (primitive-set! 'uninlined-stats + (lambda () + (let f ([ls uninlined] [ac '()]) + (cond + [(null? ls) ac] + [(fx> (cdar ls) 15) + (f (cdr ls) (cons (car ls) ac))] + [else (f (cdr ls) ac)]))))) + +(define (introduce-primcalls x) + (define who 'introduce-primcalls) + (define (simple? x) + (or (constant? x) (var? x) (primref? x))) + (define (Expr x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(closure) x] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Expr body))] + [(fix lhs* rhs* body) + (make-fix lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (make-seq (Expr e0) (Expr e1))] + [(primcall op arg*) + (case op + ;[(values) + ; (if (fx= (length arg*) 1) + ; (Expr (car arg*)) + ; (begin + ; (warning 'compile "possible incorrect number of values") + ; (make-funcall (make-primref 'values) (map Expr arg*))))] + [else + (make-primcall op (map Expr arg*))])] + [(forcall op arg*) + (make-forcall op (map Expr arg*))] + [(funcall rator rand*) + (cond + [(and (primref? rator) + (open-codeable? (primref-name rator)) + (syntactically-valid? (primref-name rator) rand*)) + (Expr (make-primcall (primref-name rator) rand*))] + [else + (when (primref? rator) + (mark-uninlined (primref-name rator))) + (make-funcall (Expr rator) (map Expr rand*))])] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (Tail x) + (record-case x + [(constant) (make-return x)] + [(var) (make-return x)] + [(primref) (make-return x)] + [(closure) (make-return x)] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Tail body))] + [(fix lhs* rhs* body) + (make-fix lhs* (map Expr rhs*) (Tail body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Tail conseq) (Tail altern))] + [(seq e0 e1) (make-seq (Expr e0) (Tail e1))] + [(primcall op arg*) + (case op + ;[(values) + ; (if (fx= (length arg*) 1) + ; (make-return (Expr (car arg*))) + ; (make-return* (map Expr arg*)))] + [else + (make-return (make-primcall op (map Expr arg*)))])] + [(forcall op arg*) + (make-return (make-forcall op (map Expr arg*)))] + [(funcall rator rand*) + (cond + [(and (primref? rator) + (open-codeable? (primref-name rator)) + (syntactically-valid? (primref-name rator) rand*)) + (Tail (make-primcall (primref-name rator) rand*))] + [else + (make-funcall (Expr rator) (map Expr rand*))])] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (CaseExpr x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (Tail body))])) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (make-clambda-code L (map CaseExpr cases) free)])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) (Tail body))])) + (CodesExpr x)) + + +(define (simplify-operands x) + (define who 'simplify-operands) + (define (simple? x) + (or (constant? x) (var? x) (primref? x))) + (define (simplify arg lhs* rhs* k) + (if (simple? arg) + (k arg lhs* rhs*) + (let ([v (unique-var 'tmp)]) + (k v (cons v lhs*) (cons (Expr arg) rhs*))))) + (define (simplify* arg* lhs* rhs* k) + (cond + [(null? arg*) (k '() lhs* rhs*)] + [else + (simplify (car arg*) lhs* rhs* + (lambda (a lhs* rhs*) + (simplify* (cdr arg*) lhs* rhs* + (lambda (d lhs* rhs*) + (k (cons a d) lhs* rhs*)))))])) + (define (Expr x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(closure) x] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Expr body))] + [(fix lhs* rhs* body) + (make-fix lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (make-seq (Expr e0) (Expr e1))] + [(primcall op arg*) + (cond + [(memq op '(not car cdr)) + (make-primcall op (map Expr arg*))] + [else + (simplify* arg* '() '() + (lambda (arg* lhs* rhs*) + (make-bind^ lhs* rhs* + (make-primcall op arg*))))])] + [(forcall op arg*) + (make-forcall op (map Expr arg*))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (Tail x) + (record-case x + [(return v) (make-return (Expr v))] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Tail body))] + [(fix lhs* rhs* body) + (make-fix lhs* (map Expr rhs*) (Tail body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Tail conseq) (Tail altern))] + [(seq e0 e1) (make-seq (Expr e0) (Tail e1))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (CaseExpr x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (Tail body))])) + (define (CodeExpr x) + (record-case x + [(clambda-code L clauses free) + (make-clambda-code L (map CaseExpr clauses) free)])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) (Tail body))])) + (CodesExpr x)) + + +(define (insert-stack-overflow-checks x) + (define who 'insert-stack-overflow-checks) + (define (insert-check body) + (make-seq + (make-conditional + (make-primcall '$fp-overflow '()) + (make-funcall (make-primref 'do-stack-overflow) '()) + (make-primcall 'void '())) + body)) + (define (Expr x) + (record-case x + [(constant) #f] + [(var) #f] + [(primref) #f] + [(closure code free*) #f] + [(bind lhs* rhs* body) + (or (ormap Expr rhs*) (Expr body))] + [(fix lhs* rhs* body) (Expr body)] + [(conditional test conseq altern) + (or (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (or (Expr e0) (Expr e1))] + [(primcall op arg*) (ormap Expr arg*)] + [(forcall op arg*) (ormap Expr arg*)] + [(funcall rator arg*) #t] + [(appcall rator arg*) #t] + [else (error who "invalid expression ~s" (unparse x))])) + (define (Tail x) + (record-case x + [(return v) (Expr v)] + [(bind lhs* rhs* body) + (or (ormap Expr rhs*) (Tail body))] + [(fix lhs* rhs* body) (Tail body)] + [(conditional test conseq altern) + (or (Expr test) (Tail conseq) (Tail altern))] + [(seq e0 e1) (or (Expr e0) (Tail e1))] + [(funcall rator arg*) (or (Expr rator) (ormap Expr arg*))] + [(appcall rator arg*) (or (Expr rator) (ormap Expr arg*))] + [else (error who "invalid tail expression ~s" (unparse x))])) + (define (CaseExpr x) + (record-case x + [(clambda-case fml* proper body) + (if (Tail body) + (make-clambda-case fml* proper (insert-check body)) + x)])) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (make-clambda-code L (map CaseExpr cases) free)])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) + (if (Tail body) + (insert-check body) + body))])) + (CodesExpr x)) + + +(define (insert-allocation-checks x) + (define who 'insert-allocation-checks) + (define (check-bytes n var body) + (make-seq + (make-conditional + (make-primcall '$ap-check-bytes + (list (make-constant n) var)) + (make-forcall "ik_collect" ;(make-primref 'do-overflow) + (list + (make-primcall '$fx+ + (list (make-constant (fx+ n 4096)) var)))) + (make-primcall 'void '())) + body)) + (define (check-words n var body) + (make-seq + (make-conditional + (make-primcall '$ap-check-words + (list (make-constant n) var)) + (make-forcall "ik_collect" ; (make-primref 'do-overflow-words) + (list + (make-primcall '$fx+ + (list (make-constant (fx+ n 4096)) var)))) + (make-primcall 'void '())) + body)) + (define (check-const n body) + (make-seq + (make-conditional + (make-primcall '$ap-check-const + (list (make-constant n))) + (make-forcall "ik_collect" ;(make-primref 'do-overflow) + (list (make-constant (fx+ n 4096)))) + (make-primcall 'void '())) + body)) + (define (closure-size x) + (record-case x + [(closure code free*) + (align (fx+ disp-closure-data (fx* (length free*) wordsize)))] + [else (error 'closure-size "~s is not a closure" x)])) + (define (sum ac ls) + (cond + [(null? ls) ac] + [else (sum (fx+ ac (car ls)) (cdr ls))])) + (define (Expr x) + (record-case x + [(constant) x] + [(var) x] + [(primref) x] + [(closure) + (check-const (closure-size x) x)] + [(fix lhs* rhs* body) + (if (null? lhs*) + (Expr body) + (check-const (sum 0 (map closure-size rhs*)) + (make-fix lhs* rhs* + (Expr body))))] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Expr body))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Expr conseq) (Expr altern))] + [(seq e0 e1) (make-seq (Expr e0) (Expr e1))] + [(primcall op arg*) + (let ([x (make-primcall op (map Expr arg*))]) + (case op + [(cons) (check-const pair-size x)] + [($make-symbol) (check-const symbol-size x)] + [($make-tcbucket) (check-const tcbucket-size x)] + [($frame->continuation $code->closure) + (check-const (fx+ disp-closure-data (fx* (length arg*) wordsize)) x)] + [($make-string) + (record-case (car arg*) + [(constant i) + (check-const (fx+ i (fx+ disp-string-data 1)) x)] + [else + (check-bytes (fxadd1 disp-string-data) (car arg*) x)])] + [($string) + (check-const (fx+ (length arg*) (fx+ disp-string-data 1)) x)] + [($make-vector) + (record-case (car arg*) + [(constant i) + (check-const (fx+ (fx* i wordsize) disp-vector-data) x)] + [else + (check-words (fxadd1 disp-vector-data) (car arg*) x)])] + [($make-record) + (record-case (cadr arg*) + [(constant i) + (check-const (fx+ (fx* i wordsize) disp-record-data) x)] + [else + (check-words (fxadd1 disp-record-data) (cadr arg*) x)])] + [(list*) + (check-const (fx* (fxsub1 (length arg*)) pair-size) x)] + [(list) + (check-const (fx* (length arg*) pair-size) x)] + [(vector $record) + (check-const (fx+ (fx* (length arg*) wordsize) disp-vector-data) x)] + [else x]))] + [(forcall op arg*) + (make-forcall op (map Expr arg*))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (Tail x) + (record-case x + [(return v) (make-return (Expr v))] + [(bind lhs* rhs* body) + (make-bind lhs* (map Expr rhs*) (Tail body))] + [(fix lhs* rhs* body) + (if (null? lhs*) + (Tail body) + (check-const (sum 0 (map closure-size rhs*)) + (make-fix lhs* rhs* + (Tail body))))] + [(conditional test conseq altern) + (make-conditional (Expr test) (Tail conseq) (Tail altern))] + [(seq e0 e1) (make-seq (Expr e0) (Tail e1))] + [(funcall rator rand*) + (make-funcall (Expr rator) (map Expr rand*))] + [(appcall op arg*) + (make-appcall (Expr op) (map Expr arg*))] + [else (error who "invalid expression ~s" (unparse x))])) + (define (CaseExpr x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (Tail body))])) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (make-clambda-code L (map CaseExpr cases) free)])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) (Tail body))])) + (CodesExpr x)) + + + +(define (remove-local-variables x) + (define who 'remove-local-variables) + (define (simple* x* r) + (map (lambda (x) + (cond + [(assq x r) => cdr] + [else + (when (var? x) (error who "unbound var ~s" x)) + x])) + x*)) + (define (env->mask r sz) + (let ([s (make-vector (fxsra (fx+ sz 7) 3) 0)]) + (for-each + (lambda (idx) + (let ([q (fxsra idx 3)] + [r (fxlogand idx 7)]) + (vector-set! s q + (fxlogor (vector-ref s q) (fxsll 1 r))))) + r) + s)) + (define (check? x) + (cond + [(primref? x) #t] ;;;; PRIMREF CHECK + [else #t])) + (define (do-new-frame op rand* si r call-convention rp-convention orig-live) + (make-new-frame (fxadd1 si) (fx+ (length rand*) 2) + (let f ([r* rand*] [nsi (fx+ si 2)] [live orig-live]) + (cond + [(null? r*) + (make-seq + (make-seq + (make-save-cp (make-frame-var si)) + (case call-convention + [(normal apply) + (make-eval-cp (check? op) (Expr op nsi r (cons si live)))] + [(foreign) + (make-eval-cp #f (make-foreign-label op))] + [else (error who "invalid convention ~s" call-convention)])) + (make-call-cp call-convention + rp-convention + (fxadd1 si) ; frame size + (length rand*) ; argc + (env->mask (cons si orig-live) ; cp and everything before it + (fxadd1 si))))] ; mask-size ~~ frame size + [else + (make-seq + (make-assign (make-frame-var nsi) + (Expr (car r*) nsi r live)) + (f (cdr r*) (fxadd1 nsi) (cons nsi live)))])))) + (define (nop) (make-primcall 'void '())) + (define (do-bind lhs* rhs* body si r live k) + (let f ([lhs* lhs*] [rhs* rhs*] [si si] [nr r] [live live]) + (cond + [(null? lhs*) (k body si nr live)] + [else + (let ([v (make-frame-var si)]) + (make-seq + (make-assign v (Expr (car rhs*) si r live)) + (f (cdr lhs*) (cdr rhs*) (fxadd1 si) + (cons (cons (car lhs*) v) nr) + (cons si live))))]))) + (define (do-closure r) + (lambda (x) + (record-case x + [(closure code free*) + (make-closure code (simple* free* r))]))) + (define (do-fix lhs* rhs* body si r live k) + (let f ([l* lhs*] [nlhs* '()] [si si] [r r] [live live]) + (cond + [(null? l*) + (make-fix (reverse nlhs*) + (map (do-closure r) rhs*) + (k body si r live))] + [else + (let ([v (make-frame-var si)]) + (f (cdr l*) (cons v nlhs*) (fxadd1 si) + (cons (cons (car l*) v) r) + (cons si live)))]))) + (define (do-tail-frame-old op rand* si r call-conv live) + (define (const? x) + (record-case x + [(constant) #t] + [(primref) #t] + [else #f])) + (define (evalrand* rand* i si r live) + (cond + [(null? rand*) + (make-eval-cp (check? op) (Expr op si r live))] + [(const? (car rand*)) + (evalrand* (cdr rand*) (fxadd1 i) (fxadd1 si) r live)] + [else + (let ([v (make-frame-var si)] + [rhs (Expr (car rand*) si r live)]) + (cond + [(and (frame-var? rhs) + (fx= (frame-var-idx rhs) i)) + (evalrand* (cdr rand*) (fx+ i 1) (fx+ si 1) r (cons si live))] + [else + (make-seq + (make-assign v rhs) + (evalrand* (cdr rand*) (fx+ 1 i) (fx+ 1 si) r + (cons si live)))]))])) + (define (moverand* rand* i si ac) + (cond + [(null? rand*) ac] + [(const? (car rand*)) + (make-seq + (make-assign (make-frame-var i) (car rand*)) + (moverand* (cdr rand*) (fxadd1 i) (fxadd1 si) ac))] + [else + (make-seq + (make-assign (make-frame-var i) (make-frame-var si)) + (moverand* (cdr rand*) (fxadd1 i) (fxadd1 si) ac))])) + (make-seq + (evalrand* rand* 1 si r live) + (moverand* rand* 1 si + (make-tailcall-cp call-conv (length rand*))))) + (define (do-tail-frame op rand* si r call-conv live) + (define (const? x) + (record-case x + [(constant) #t] + [(primref) #t] + [else #f])) + (define (evalrand* rand* i si r live ac) + (cond + [(null? rand*) + (make-seq + (make-eval-cp (check? op) (Expr op si r live)) + ac)] + [(const? (car rand*)) + (evalrand* (cdr rand*) (fxadd1 i) (fxadd1 si) r live + (make-seq ac + (make-assign (make-frame-var i) (car rand*))))] + [else + (let ([vsi (make-frame-var si)] + [rhs (Expr (car rand*) si r live)]) + (cond + [(and (frame-var? rhs) + (fx= (frame-var-idx rhs) i)) + (evalrand* (cdr rand*) (fx+ i 1) (fx+ si 1) r (cons si live) ac)] + [(fx= i si) + (make-seq + (make-assign vsi rhs) + (evalrand* (cdr rand*) (fx+ i 1) (fx+ si 1) r + (cons si live) ac))] + [else + (make-seq + (make-assign vsi rhs) + (evalrand* (cdr rand*) (fxadd1 i) (fxadd1 si) r (cons si live) + (make-seq ac + (make-assign (make-frame-var i) vsi))))]))])) + (make-seq + (evalrand* rand* 1 si r live (make-primcall 'void '())) + (make-tailcall-cp call-conv (length rand*)))) + (define (Tail x si r live) + (record-case x + [(return v) (make-return (Expr v si r live))] + [(bind lhs* rhs* body) + (do-bind lhs* rhs* body si r live Tail)] + [(fix lhs* rhs* body) + (do-fix lhs* rhs* body si r live Tail)] + [(conditional test conseq altern) + (make-conditional + (Expr test si r live) + (Tail conseq si r live) + (Tail altern si r live))] + [(seq e0 e1) (make-seq (Effect e0 si r live) (Tail e1 si r live))] + [(primcall op arg*) + (make-return + (make-primcall op + (map (lambda (x) (Expr x si r live)) arg*)))] + + [(funcall op rand*) + (do-tail-frame op rand* si r 'normal live)] + [(appcall op rand*) + (do-tail-frame op rand* si r 'apply live)] +;;; [(funcall op rand*) +;;; (do-new-frame op rand* si r 'normal 'tail live)] +;;; [(appcall op rand*) +;;; (do-new-frame op rand* si r 'apply 'tail live)] + [else (error who "invalid expression ~s" (unparse x))])) + (define (Effect x si r live) + (record-case x + [(constant) (nop)] + [(var) (nop)] + [(primref) (nop)] + [(closure code free*) (nop)] + [(bind lhs* rhs* body) + (do-bind lhs* rhs* body si r live Effect)] + [(fix lhs* rhs* body) + (do-fix lhs* rhs* body si r live Effect)] + [(conditional test conseq altern) + (make-conditional + (Expr test si r live) + (Effect conseq si r live) + (Effect altern si r live))] + [(seq e0 e1) (make-seq (Effect e0 si r live) (Effect e1 si r live))] + [(primcall op arg*) + (make-primcall op + (map (lambda (x) (Expr x si r live)) arg*))] + [(forcall op rand*) + (do-new-frame op rand* si r 'foreign 'effect live)] + [(funcall op rand*) + (do-new-frame op rand* si r 'normal 'effect live)] + [(appcall op rand*) + (do-new-frame op rand* si r 'apply 'effect live)] + [else (error who "invalid effect expression ~s" (unparse x))])) + (define (Expr x si r live) + (record-case x + [(constant) x] + [(var) + (cond + [(assq x r) => cdr] + [else (error who "unbound var ~s" x)])] + [(primref) x] + [(closure code free*) + (make-closure code (simple* free* r))] + [(bind lhs* rhs* body) + (do-bind lhs* rhs* body si r live Expr)] + [(fix lhs* rhs* body) + (do-fix lhs* rhs* body si r live Expr)] + [(conditional test conseq altern) + (make-conditional + (Expr test si r live) + (Expr conseq si r live) + (Expr altern si r live))] + [(seq e0 e1) (make-seq (Effect e0 si r live) (Expr e1 si r live))] + [(primcall op arg*) + (make-primcall op + (map (lambda (x) (Expr x si r live)) arg*))] + [(forcall op rand*) + (do-new-frame op rand* si r 'foreign 'value live)] + [(funcall op rand*) + (do-new-frame op rand* si r 'normal 'value live)] + [(appcall op rand*) + (do-new-frame op rand* si r 'apply 'value live)] + [else (error who "invalid expression ~s" (unparse x))])) + (define (bind-fml* fml* r) + (let f ([si 1] [fml* fml*]) + (cond + [(null? fml*) (values '() si r '())] + [else + (let-values ([(nfml* nsi r live) (f (fxadd1 si) (cdr fml*))]) + (let ([v (make-frame-var si)]) + (values (cons v nfml*) + nsi + (cons (cons (car fml*) v) r) + (cons si live))))]))) + (define (bind-free* free*) + (let f ([free* free*] [idx 0] [r '()]) + (cond + [(null? free*) r] + [else + (f (cdr free*) (fxadd1 idx) + (cons (cons (car free*) (make-cp-var idx)) r))]))) + (define CaseExpr + (lambda (r) + (lambda (x) + (record-case x + [(clambda-case fml* proper body) + (let-values ([(fml* si r live) (bind-fml* fml* r)]) + (make-clambda-case fml* proper (Tail body si r live)))])))) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (let ([r (bind-free* free)]) + (make-clambda-code L (map (CaseExpr r) cases) free))])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) + (Tail body 1 '() '()))])) + (CodesExpr x)) + + + +(define checks-elim-count 0) +(define (optimize-ap-check x) + (define who 'optimize-ap-check) + (define (min x y) + (if (fx< x y) x y)) + (define (Tail x f) + (record-case x + [(return v) + (let-values ([(v f) (NonTail v f)]) + (make-return v))] + [(fix lhs* rhs* body) + (make-fix lhs* rhs* (Tail body f))] + [(conditional test conseq altern) + (let-values ([(test f) (NonTail test f)]) + (make-conditional + test + (Tail conseq f) + (Tail altern f)))] + [(seq e0 e1) + (let-values ([(e0 f) (NonTail e0 f)]) + (make-seq e0 (Tail e1 f)))] + [(tailcall-cp) x] + [else (error who "invalid tail expression ~s" (unparse x))])) + (define (do-primcall op arg* f) + (case op + [($ap-check-const) + (let ([n (constant-value (car arg*))]) + (cond + [(fx< n f) + ;(set! checks-elim-count (fxadd1 checks-elim-count)) + ;(printf "~s checks eliminated\n" checks-elim-count) + (values (make-constant #f) (fx- f n))] + [(fx<= n 4096) + (values (make-primcall '$ap-check-const + (list (make-constant 4096))) + (fx- 4096 n))] + [else + (values (make-primcall '$ap-check-const + (list (make-constant (fx+ n 4096)))) + 4096)]))] + [($ap-check-bytes $ap-check-words) + (values (make-primcall op + (list (make-constant (fx+ (constant-value (car arg*)) + 4096)) + (cadr arg*))) + 4096)] + [else (values (make-primcall op arg*) f)])) + (define (NonTail x f) + (record-case x + [(constant) (values x f)] + [(frame-var) (values x f)] + [(cp-var) (values x f)] + [(save-cp) (values x f)] + [(foreign-label) (values x f)] + [(primref) (values x f)] + [(closure) (values x f)] + [(call-cp call-conv) + (if (eq? call-conv 'foreign) + (values x f) + (values x 0))] + [(primcall op arg*) (do-primcall op arg* f)] + [(fix lhs* rhs* body) + (let-values ([(body f) (NonTail body f)]) + (values (make-fix lhs* rhs* body) f))] + [(conditional test conseq altern) + (let-values ([(test f) (NonTail test f)]) + (if (constant? test) + (if (constant-value test) + (NonTail conseq f) + (NonTail altern f)) + (let-values ([(conseq f0) (NonTail conseq f)] + [(altern f1) (NonTail altern f)]) + (values (make-conditional test conseq altern) + (min f0 f1)))))] + [(seq e0 e1) + (let-values ([(e0 f) (NonTail e0 f)]) + (let-values ([(e1 f) (NonTail e1 f)]) + (values (make-seq e0 e1) f)))] + [(assign lhs rhs) + (let-values ([(rhs f) (NonTail rhs f)]) + (values (make-assign lhs rhs) f))] + [(eval-cp check body) + (let-values ([(body f) (NonTail body f)]) + (values (make-eval-cp check body) f))] + [(new-frame base-idx size body) + (let-values ([(body f) (NonTail body f)]) + (values (make-new-frame base-idx size body) f))] + [else (error who "invalid nontail expression ~s" (unparse x))])) + (define CaseExpr + (lambda (x) + (record-case x + [(clambda-case fml* proper body) + (make-clambda-case fml* proper (Tail body 0))]))) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (make-clambda-code L (map CaseExpr cases) free)])) + (define (CodesExpr x) + (record-case x + [(codes list body) + (make-codes (map CodeExpr list) + (Tail body 0))])) + (CodesExpr x)) + +(begin + (define fx-shift 2) + (define fx-mask #x03) + (define fx-tag 0) + (define bool-f #x2F) + (define bool-t #x3F) + (define bool-mask #xEF) + (define bool-tag #x2F) + (define bool-shift 4) + (define nil #x4F) + (define eof #x5F) ; double check + (define unbound #x6F) ; double check + (define void-object #x7F) ; double check + (define bwp-object #x8F) ; double check + (define char-shift 8) + (define char-tag #x0F) + (define char-mask #xFF) + (define pair-mask 7) + (define pair-tag 1) + (define disp-car 0) + (define disp-cdr 4) + (define pair-size 8) + (define pagesize 4096) + (define pageshift 12) + (define wordsize 4) + (define wordshift 2) + + (define symbol-mask 7) + (define symbol-tag 2) + (define disp-symbol-string 0) + (define disp-symbol-unique-string 4) + (define disp-symbol-value 8) + (define disp-symbol-plist 12) + (define disp-symbol-system-value 16) + (define disp-symbol-system-plist 20) + (define symbol-size 24) + (define vector-tag 5) + (define vector-mask 7) + (define disp-vector-length 0) + (define disp-vector-data 4) + (define string-mask 7) + (define string-tag 6) + (define disp-string-length 0) + (define disp-string-data 4) + (define closure-mask 7) + (define closure-tag 3) + (define disp-closure-data 4) + (define disp-closure-code 0) + (define continuation-size 16) + (define continuation-tag #x1F) + (define disp-continuation-top 4) + (define disp-continuation-size 8) + (define disp-continuation-next 12) + (define code-tag #x2F) + (define disp-code-instrsize 4) + (define disp-code-relocsize 8) + (define disp-code-freevars 12) + (define disp-code-data 16) + (define disp-tcbucket-tconc 0) + (define disp-tcbucket-key 4) + (define disp-tcbucket-val 8) + (define disp-tcbucket-next 12) + (define tcbucket-size 16) + (define record-ptag 5) + (define record-pmask 7) + (define disp-record-rtd 0) + (define disp-record-data 4) + (define disp-frame-size -17) + (define disp-frame-offset -13) + (define disp-multivalue-rp -9) + (define object-alignment 8) + (define align-shift 3) + (define dirty-word -1)) + +(define (align n) + (fxsll (fxsra (fx+ n (fxsub1 object-alignment)) align-shift) align-shift)) + +(begin + (define (mem off val) + (cond + [(fixnum? off) (list 'disp (int off) val)] + [(register? off) (list 'disp off val)] + [else (error 'mem "invalid disp ~s" off)])) + (define (int x) (list 'int x)) + (define (obj x) (list 'obj x)) + (define (byte x) (list 'byte x)) + (define (byte-vector x) (list 'byte-vector x)) + (define (movzbl src targ) (list 'movzbl src targ)) + (define (sall src targ) (list 'sall src targ)) + (define (sarl src targ) (list 'sarl src targ)) + (define (shrl src targ) (list 'shrl src targ)) + (define (notl src) (list 'notl src)) + (define (pushl src) (list 'pushl src)) + (define (popl src) (list 'popl src)) + (define (orl src targ) (list 'orl src targ)) + (define (xorl src targ) (list 'xorl src targ)) + (define (andl src targ) (list 'andl src targ)) + (define (movl src targ) (list 'movl src targ)) + (define (movb src targ) (list 'movb src targ)) + (define (addl src targ) (list 'addl src targ)) + (define (imull src targ) (list 'imull src targ)) + (define (idivl src) (list 'idivl src)) + (define (subl src targ) (list 'subl src targ)) + (define (push src) (list 'push src)) + (define (pop targ) (list 'pop targ)) + (define (sete targ) (list 'sete targ)) + (define (call targ) (list 'call targ)) + (define (tail-indirect-cpr-call) + (jmp (mem (fx- disp-closure-code closure-tag) cpr))) + (define (indirect-cpr-call) + (call (mem (fx- disp-closure-code closure-tag) cpr))) + (define (negl targ) (list 'negl targ)) + (define (label x) (list 'label x)) + (define (label-address x) (list 'label-address x)) + (define (ret) '(ret)) + (define (cltd) '(cltd)) + (define (cmpl arg1 arg2) (list 'cmpl arg1 arg2)) + (define (je label) (list 'je label)) + (define (jne label) (list 'jne label)) + (define (jle label) (list 'jle label)) + (define (jge label) (list 'jge label)) + (define (jg label) (list 'jg label)) + (define (jl label) (list 'jl label)) + (define (jb label) (list 'jb label)) + (define (ja label) (list 'ja label)) + (define (jmp label) (list 'jmp label)) + (define edi '%edx) ; closure pointer + (define esi '%esi) ; pcb + (define ebp '%ebp) ; allocation pointer + (define esp '%esp) ; stack base pointer + (define al '%al) + (define ah '%ah) + (define bh '%bh) + (define cl '%cl) + (define eax '%eax) + (define ebx '%ebx) + (define ecx '%ecx) + (define edx '%edx) + (define apr '%ebp) + (define fpr '%esp) + (define cpr '%edi) + (define pcr '%esi) + (define register? symbol?) + (define (argc-convention n) + (fx- 0 (fxsll n fx-shift)))) + + +(define pcb-ref + (lambda (x) + (case x + [(allocation-pointer) (mem 0 pcr)] + [(allocation-redline) (mem 4 pcr)] + [(frame-pointer) (mem 8 pcr)] + [(frame-base) (mem 12 pcr)] + [(frame-redline) (mem 16 pcr)] + [(next-continuation) (mem 20 pcr)] + [(system-stack) (mem 24 pcr)] + [(dirty-vector) (mem 28 pcr)] + [else (error 'pcb-ref "invalid arg ~s" x)]))) + +(define (primref-loc op) + (unless (symbol? op) (error 'primref-loc "not a symbol ~s" op)) + (mem (fx- disp-symbol-system-value symbol-tag) + (obj op))) + + +(define (generate-code x) + (define who 'generate-code) + (define (rp-label x) + (case x + [(value) (label-address SL_multiple_values_error_rp)] + [(effect) (label-address SL_multiple_values_ignore_rp)] + [else (error who "invalid rp-convention ~s" x)])) + (define unique-label + (lambda () + (label (gensym)))) + (define (constant-val x) + (cond + [(fixnum? x) (obj x)] + [(boolean? x) (int (if x bool-t bool-f))] + [(null? x) (int nil)] + [(char? x) (int (fx+ (fxsll (char->integer x) char-shift) char-tag))] + [(eq? x (void)) (int void-object)] + [else (obj x)])) + (define (cond-branch op Lt Lf ac) + (define (opposite x) + (cadr (assq x '([je jne] [jl jge] [jle jg] [jg jle] [jge jl])))) + (unless (or Lt Lf) + (error 'cond-branch "no labels")) + (cond + [(not Lf) (cons (list op Lt) ac)] + [(not Lt) (cons (list (opposite op) Lf) ac)] + [else (list* (list op Lt) (jmp Lf) ac)])) + (define (indirect-type-pred pri-mask pri-tag sec-mask sec-tag rand* Lt Lf ac) + (cond + [(and Lt Lf) + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int pri-mask) ebx) + (cmpl (int pri-tag) ebx) + (jne Lf) + (movl (mem (fx- 0 pri-tag) eax) ebx) + (if sec-mask + (andl (int sec-mask) ebx) + '(nop)) + (cmpl (int sec-tag) ebx) + (jne Lf) + (jmp Lt) + ac)] + [Lf + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int pri-mask) ebx) + (cmpl (int pri-tag) ebx) + (jne Lf) + (movl (mem (fx- 0 pri-tag) eax) ebx) + (if sec-mask + (andl (int sec-mask) ebx) + '(nop)) + (cmpl (int sec-tag) ebx) + (jne Lf) + ac)] + [Lt + (let ([L_END (unique-label)]) + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int pri-mask) ebx) + (cmpl (int pri-tag) ebx) + (jne L_END) + (movl (mem (fx- 0 pri-tag) eax) ebx) + (if sec-mask + (andl (int sec-mask) ebx) + '(nop)) + (cmpl (int sec-tag) ebx) + (je Lt) + L_END + ac))] + [else ac])) + (define (type-pred mask tag rand* Lt Lf ac) + (cond + [mask + (list* + (movl (Simple (car rand*)) eax) + (andl (int mask) eax) + (cmpl (int tag) eax) + (cond-branch 'je Lt Lf ac))] + [else + (let ([v (Simple (car rand*))]) + (cond + [(memq (car v) '(mem register)) + (list* + (cmpl (int tag) (Simple (car rand*))) + (cond-branch 'je Lt Lf ac))] + [else + (list* + (movl (Simple (car rand*)) eax) + (cmpl (int tag) eax) + (cond-branch 'je Lt Lf ac))]))])) + (define (compare-and-branch op rand* Lt Lf ac) + (define (opposite x) + (cadr (assq x '([je je] [jl jg] [jle jge] [jg jl] [jge jle])))) + (cond + [(and (constant? (car rand*)) (constant? (cadr rand*))) + (list* + (movl (Simple (car rand*)) eax) + (cmpl (Simple (cadr rand*)) eax) + (cond-branch op Lt Lf ac))] + [(constant? (cadr rand*)) + (list* + (cmpl (Simple (cadr rand*)) (Simple (car rand*))) + (cond-branch op Lt Lf ac))] + [(constant? (car rand*)) + (list* + (cmpl (Simple (car rand*)) (Simple (cadr rand*))) + (cond-branch (opposite op) Lt Lf ac))] + [else + (list* + (movl (Simple (car rand*)) eax) + (cmpl (Simple (cadr rand*)) eax) + (cond-branch op Lt Lf ac))])) + (define (do-pred-prim op rand* Lt Lf ac) + (case op + [(fixnum?) (type-pred fx-mask fx-tag rand* Lt Lf ac)] + [(pair?) (type-pred pair-mask pair-tag rand* Lt Lf ac)] + [(char?) (type-pred char-mask char-tag rand* Lt Lf ac)] + [(string?) (type-pred string-mask string-tag rand* Lt Lf ac)] + [(symbol?) (type-pred symbol-mask symbol-tag rand* Lt Lf ac)] + [(procedure?) (type-pred closure-mask closure-tag rand* Lt Lf ac)] + [(boolean?) (type-pred bool-mask bool-tag rand* Lt Lf ac)] + [(null?) (type-pred #f nil rand* Lt Lf ac)] + [($unbound-object?) (type-pred #f unbound rand* Lt Lf ac)] + [($forward-ptr?) (type-pred #f -1 rand* Lt Lf ac)] + [(not) (Pred (car rand*) Lf Lt ac)] + ;[(not) (type-pred #f bool-f rand* Lt Lf ac)] + [(eof-object?) (type-pred #f eof rand* Lt Lf ac)] + [(bwp-object?) (type-pred #f bwp-object rand* Lt Lf ac)] + [($code?) + (indirect-type-pred vector-mask vector-tag #f code-tag + rand* Lt Lf ac)] + [($fxzero?) (type-pred #f 0 rand* Lt Lf ac)] + [($fx= $char= eq?) (compare-and-branch 'je rand* Lt Lf ac)] + [($fx< $char<) (compare-and-branch 'jl rand* Lt Lf ac)] + [($fx<= $char<=) (compare-and-branch 'jle rand* Lt Lf ac)] + [($fx> $char>) (compare-and-branch 'jg rand* Lt Lf ac)] + [($fx>= $char>=) (compare-and-branch 'jge rand* Lt Lf ac)] + [(vector?) + (indirect-type-pred vector-mask vector-tag fx-mask fx-tag + rand* Lt Lf ac)] + [($record?) + (indirect-type-pred record-pmask record-ptag record-pmask record-ptag + rand* Lt Lf ac)] + [($record/rtd?) + (cond + [Lf + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int vector-mask) eax) + (cmpl (int vector-tag) eax) + (jne Lf) + (movl (Simple (cadr rand*)) eax) + (cmpl (mem (fx- disp-record-rtd vector-tag) ebx) eax) + (jne Lf) + (if Lt + (cons (jmp Lt) ac) + ac))] + [Lt + (let ([Ljoin (unique-label)]) + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int vector-mask) eax) + (cmpl (int vector-tag) eax) + (jne Ljoin) + (movl (Simple (cadr rand*)) eax) + (cmpl (mem (fx- disp-record-rtd vector-tag) ebx) eax) + (je Lt) + Ljoin + ac))] + [else ac])] + [(immediate?) + (cond + [(and Lt Lf) + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int fx-mask) ebx) + (cmpl (int 0) ebx) + (je Lt) + (andl (int 7) eax) + (cmpl (int 7) eax) + (je Lt) + (jmp Lf) + ac)] + [Lt + (list* (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int fx-mask) ebx) + (cmpl (int 0) ebx) + (je Lt) + (andl (int 7) eax) + (cmpl (int 7) eax) + (je Lt) + ac)] + [Lf + (let ([Ljoin (unique-label)]) + (list* + (movl (Simple (car rand*)) eax) + (movl eax ebx) + (andl (int fx-mask) ebx) + (cmpl (int 0) ebx) + (je Ljoin) + (andl (int 7) eax) + (cmpl (int 7) eax) + (jne Lf) + Ljoin + ac))] + [else ac])] + [($ap-check-words) + (record-case (car rand*) + [(constant i) + (list* (movl (pcb-ref 'allocation-redline) eax) + (subl (Simple (cadr rand*)) eax) + (subl (int i) eax) + (cmpl eax apr) + (cond-branch 'jge Lt Lf ac))] + [else (error who "ap-check-words")])] + [($ap-check-bytes) + (record-case (car rand*) + [(constant i) + (list* (movl (Simple (cadr rand*)) eax) + (negl eax) + (addl (pcb-ref 'allocation-redline) eax) + (subl (int i) eax) + (cmpl eax apr) + (cond-branch 'jge Lt Lf ac))] + [else (error who "ap-check-bytes")])] + [($ap-check-const) + (record-case (car rand*) + [(constant i) + (if (fx<= i pagesize) + (list* + (cmpl (pcb-ref 'allocation-redline) apr) + (cond-branch 'jge Lt Lf ac)) + (list* + (movl (pcb-ref 'allocation-redline) eax) + (subl (int i) eax) + (cmpl eax apr) + (cond-branch 'jge Lt Lf ac)))] + [else (error who "ap-check-const")])] + [($fp-at-base) + (list* + (movl (pcb-ref 'frame-base) eax) + (subl (int wordsize) eax) + (cmpl eax fpr) + (cond-branch 'je Lt Lf ac))] + [($fp-overflow) + (list* (cmpl (pcb-ref 'frame-redline) fpr) + (cond-branch 'jle Lt Lf ac))] + [($vector-ref top-level-value car cdr $record-ref) + (do-value-prim op rand* + (do-simple-test eax Lt Lf ac))] + [(cons void $fxadd1 $fxsub1) + ;;; always true + (do-effect-prim op rand* + (cond + [(not Lt) ac] + [else (cons (jmp Lt) ac)]))] + [else + (error 'pred-prim "HERE unhandled ~s" op)])) + (define (do-pred->value-prim op rand* ac) + (case op + [else + (let ([Lf (unique-label)] [Lj (unique-label)]) + (do-pred-prim op rand* #f Lf + (list* (movl (constant-val #t) eax) + (jmp Lj) + Lf + (movl (constant-val #f) eax) + Lj + ac)))])) + (define (indirect-ref arg* off ac) + (list* + (movl (Simple (car arg*)) eax) + (movl (mem off eax) eax) + ac)) + (define (do-value-prim op arg* ac) + (case op + [(eof-object) (cons (movl (int eof) eax) ac)] + [(void) (cons (movl (int void-object) eax) ac)] + [($fxadd1) + (list* (movl (Simple (car arg*)) eax) + (addl (constant-val 1) eax) + ac)] + [($fxsub1) + (list* (movl (Simple (car arg*)) eax) + (addl (constant-val -1) eax) + ac)] + [($fx+) + (list* (movl (Simple (car arg*)) eax) + (addl (Simple (cadr arg*)) eax) + ac)] + [($fx-) + (list* (movl (Simple (car arg*)) eax) + (subl (Simple (cadr arg*)) eax) + ac)] + [($fx*) + (cond + [(constant? (car arg*)) + (record-case (car arg*) + [(constant c) + (unless (fixnum? c) + (error who "invalid arg ~s to fx*" c)) + (list* (movl (Simple (cadr arg*)) eax) + (imull (int c) eax) + ac)])] + [(constant? (cadr arg*)) + (record-case (cadr arg*) + [(constant c) + (unless (fixnum? c) + (error who "invalid arg ~s to fx*" c)) + (list* (movl (Simple (car arg*)) eax) + (imull (int c) eax) + ac)])] + [else + (list* (movl (Simple (car arg*)) eax) + (sarl (int fx-shift) eax) + (imull (Simple (cadr arg*)) eax) + ac)])] + [($fxquotient) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ecx) + (cltd) + (idivl ecx) + (sall (int fx-shift) eax) + ac)] + [($fxmodulo) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl eax ecx) + (xorl ebx ecx) + (sarl (int (fxsub1 (fx* wordsize 8))) ecx) + (andl ebx ecx) + (cltd) + (idivl ebx) + (movl edx eax) + (addl ecx eax) + ac)] + [($fxlogor) + (list* (movl (Simple (car arg*)) eax) + (orl (Simple (cadr arg*)) eax) + ac)] + [($fxlogand) + (list* (movl (Simple (car arg*)) eax) + (andl (Simple (cadr arg*)) eax) + ac)] + [($fxlogxor) + (list* (movl (Simple (car arg*)) eax) + (xorl (Simple (cadr arg*)) eax) + ac)] + [($fxsra) + (record-case (cadr arg*) + [(constant i) + (unless (fixnum? i) (error who "invalid arg to fxsra")) + (list* (movl (Simple (car arg*)) eax) + (sarl (int (fx+ i fx-shift)) eax) + (sall (int fx-shift) eax) + ac)] + [else + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ecx) + (sarl (int fx-shift) ecx) + (sarl (int fx-shift) eax) + (sarl cl eax) + (sall (int fx-shift) eax) + ac)])] + [($fxsll) + (record-case (cadr arg*) + [(constant i) + (unless (fixnum? i) (error who "invalid arg to fxsll")) + (list* (movl (Simple (car arg*)) eax) + (sall (int i) eax) + ac)] + [else + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ecx) + (sarl (int fx-shift) ecx) + (sall cl eax) + ac)])] + [($fixnum->char) + (list* (movl (Simple (car arg*)) eax) + (sall (int (fx- char-shift fx-shift)) eax) + (orl (int char-tag) eax) + ac)] + [($char->fixnum) + (list* (movl (Simple (car arg*)) eax) + (sarl (int (fx- char-shift fx-shift)) eax) + ac)] + [($fxlognot) + (list* (movl (Simple (car arg*)) eax) + (orl (int fx-mask) eax) + (notl eax) + ac)] + [($car) (indirect-ref arg* (fx- disp-car pair-tag) ac)] + [($cdr) (indirect-ref arg* (fx- disp-cdr pair-tag) ac)] + [($vector-length) + (indirect-ref arg* (fx- disp-vector-length vector-tag) ac)] + [($string-length) + (indirect-ref arg* (fx- disp-string-length string-tag) ac)] + [($symbol-string) + (indirect-ref arg* (fx- disp-symbol-string symbol-tag) ac)] + [($symbol-unique-string) + (indirect-ref arg* (fx- disp-symbol-unique-string symbol-tag) ac)] + [($symbol-value) + (indirect-ref arg* (fx- disp-symbol-value symbol-tag) ac)] + [(primitive-ref) + (indirect-ref arg* (fx- disp-symbol-system-value symbol-tag) ac)] + [($tcbucket-key) + (indirect-ref arg* (fx- disp-tcbucket-key vector-tag) ac)] + [($tcbucket-val) + (indirect-ref arg* (fx- disp-tcbucket-val vector-tag) ac)] + [($tcbucket-next) + (indirect-ref arg* (fx- disp-tcbucket-next vector-tag) ac)] + [(pointer-value) + (list* + (movl (Simple (car arg*)) eax) + (sarl (int fx-shift) eax) + (sall (int fx-shift) eax) + ac)] + [($symbol-plist) + (indirect-ref arg* (fx- disp-symbol-plist symbol-tag) ac)] + [($record-rtd) + (indirect-ref arg* (fx- disp-record-rtd record-ptag) ac)] + [($constant-ref) + (list* (movl (Simple (car arg*)) eax) ac)] + [(car cdr) + (let ([x (car arg*)]) + (NonTail x + (list* + (movl eax ebx) + (andl (int pair-mask) eax) + (cmpl (int pair-tag) eax) + (if (eq? op 'car) + (list* + (jne (label SL_car_error)) + (movl (mem (fx- disp-car pair-tag) ebx) eax) + ac) + (list* + (jne (label SL_cdr_error)) + (movl (mem (fx- disp-cdr pair-tag) ebx) eax) + ac)))))] + [(top-level-value) + (let ([x (car arg*)]) + (cond + [(constant? x) + (let ([v (constant-value x)]) + (cond + [(symbol? v) + (list* + (movl (mem (fx- disp-symbol-value symbol-tag) (obj v)) eax) + (movl (obj v) ebx) + (cmpl (int unbound) eax) + (je (label SL_top_level_value_error)) + ac)] + [else + (list* + (movl (obj v) ebx) + (jmp (label SL_top_level_value_error)) + ac)]))] + [else + (NonTail x + (list* + (movl eax ebx) + (andl (int symbol-mask) eax) + (cmpl (int symbol-tag) eax) + (jne (label SL_top_level_value_error)) + (movl (mem (fx- disp-symbol-value symbol-tag) ebx) eax) + (cmpl (int unbound) eax) + (je (label SL_top_level_value_error)) + ac))]))] + [($vector-ref) + (list* (movl (Simple (car arg*)) ebx) + (addl (Simple (cadr arg*)) ebx) + (movl (mem (fx- disp-vector-data vector-tag) ebx) eax) + ac)] + [($record-ref) + (list* (movl (Simple (car arg*)) ebx) + (addl (Simple (cadr arg*)) ebx) + (movl (mem (fx- disp-record-data record-ptag) ebx) eax) + ac)] + [($code-ref) + (list* (movl (Simple (cadr arg*)) ebx) + (sarl (int fx-shift) ebx) + (addl (Simple (car arg*)) ebx) + (movl (int 0) eax) + (movb (mem (fx- disp-code-data vector-tag) ebx) ah) + (sarl (int (fx- 8 fx-shift)) eax) + ac)] + [($string-ref) + (list* (movl (Simple (cadr arg*)) ebx) + (sarl (int fx-shift) ebx) + (addl (Simple (car arg*)) ebx) + (movl (int char-tag) eax) + (movb (mem (fx- disp-string-data string-tag) ebx) ah) + ac)] + [($make-string) + (list* (movl (Simple (car arg*)) ebx) + (movl ebx (mem disp-string-length apr)) + (movl apr eax) + (addl (int string-tag) eax) + (sarl (int fx-shift) ebx) + (addl ebx apr) + (movb (int 0) (mem disp-string-data apr)) + (addl (int (fx+ disp-string-data object-alignment)) apr) + (sarl (int align-shift) apr) + (sall (int align-shift) apr) + ac)] + [($make-vector) + (list* (movl (Simple (car arg*)) ebx) + (movl ebx (mem disp-vector-length apr)) + (movl apr eax) + (addl (int vector-tag) eax) + (addl ebx apr) + (addl (int (fx+ disp-vector-data (fxsub1 object-alignment))) apr) + (sarl (int align-shift) apr) + (sall (int align-shift) apr) + ac)] + [($make-record) + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem disp-record-rtd apr)) + (movl apr eax) + (addl (int record-ptag) eax) + (addl (Simple (cadr arg*)) apr) + (addl (int (fx+ disp-record-data (fxsub1 object-alignment))) apr) + (sarl (int align-shift) apr) + (sall (int align-shift) apr) + ac)] + [(cons) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl eax (mem disp-car apr)) + (movl apr eax) + (movl ebx (mem disp-cdr apr)) + (addl (int pair-tag) eax) + (addl (int (align pair-size)) apr) + ac)] + [(list) + (cond + [(null? arg*) (NonTail (make-constant '()) ac)] + [else + (list* + (addl (int pair-tag) apr) + (movl apr eax) + (let f ([a (car arg*)] [d (cdr arg*)]) + (list* + (movl (Simple a) ebx) + (movl ebx (mem (fx- disp-car pair-tag) apr)) + (if (null? d) + (list* + (movl (int nil) (mem (fx- disp-cdr pair-tag) apr)) + (addl (int (fx- pair-size pair-tag)) apr) + ac) + (list* + (addl (int pair-size) apr) + (movl apr + (mem (fx- disp-cdr (fx+ pair-tag pair-size)) apr)) + (f (car d) (cdr d)))))))])] + [(list*) + (cond + [(fx= (length arg*) 1) (NonTail (car arg*) ac)] + [(fx= (length arg*) 2) (NonTail (make-primcall 'cons arg*) ac)] + [else + (list* + (addl (int pair-tag) apr) + (movl apr eax) + (let f ([a (car arg*)] [b (cadr arg*)] [d (cddr arg*)]) + (list* + (movl (Simple a) ebx) + (movl ebx (mem (fx- disp-car pair-tag) apr)) + (if (null? d) + (list* + (movl (Simple b) ebx) + (movl ebx (mem (fx- disp-cdr pair-tag) apr)) + (addl (int (fx- pair-size pair-tag)) apr) + ac) + (list* + (addl (int pair-size) apr) + (movl apr + (mem (fx- disp-cdr (fx+ pair-tag pair-size)) apr)) + (f b (car d) (cdr d)))))))])] + [($make-symbol) + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem disp-symbol-string apr)) + (movl (int 0) (mem disp-symbol-unique-string apr)) + (movl (int unbound) (mem disp-symbol-value apr)) + (movl (int nil) (mem disp-symbol-plist apr)) + (movl (int unbound) (mem disp-symbol-system-value apr)) + (movl (int nil) (mem disp-symbol-system-plist apr)) + (movl apr eax) + (addl (int symbol-tag) eax) + (addl (int (align symbol-size)) apr) + ac)] + [($make-tcbucket) + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem disp-tcbucket-tconc apr)) + (movl (Simple (cadr arg*)) eax) + (movl eax (mem disp-tcbucket-key apr)) + (movl (Simple (caddr arg*)) eax) + (movl eax (mem disp-tcbucket-val apr)) + (movl (Simple (cadddr arg*)) eax) + (movl eax (mem disp-tcbucket-next apr)) + (movl apr eax) + (addl (int vector-tag) eax) + (addl (int (align tcbucket-size)) apr) + ac)] + [($record) + (let ([rtd (car arg*)] + [ac + (let f ([arg* (cdr arg*)] [idx disp-record-data]) + (cond + [(null? arg*) + (list* (movl apr eax) + (addl (int vector-tag) eax) + (addl (int (align idx)) apr) + ac)] + [else + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem idx apr)) + (f (cdr arg*) (fx+ idx wordsize)))]))]) + (cond + [(constant? rtd) + (list* (movl (Simple rtd) (mem 0 apr)) ac)] + [else + (list* (movl (Simple rtd) eax) (movl eax (mem 0 apr)) ac)]))] + [(vector) + (let f ([arg* arg*] [idx disp-vector-data]) + (cond + [(null? arg*) + (list* (movl apr eax) + (addl (int vector-tag) eax) + (movl (int (fx- idx disp-vector-data)) + (mem disp-vector-length apr)) + (addl (int (align idx)) apr) + ac)] + [else + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem idx apr)) + (f (cdr arg*) (fx+ idx wordsize)))]))] + [($string) + (let f ([arg* arg*] [idx disp-string-data]) + (cond + [(null? arg*) + (list* (movb (int 0) (mem idx apr)) + (movl apr eax) + (addl (int string-tag) eax) + (movl (int (fx* (fx- idx disp-string-data) wordsize)) + (mem disp-string-length apr)) + (addl (int (align (fxadd1 idx))) apr) + ac)] + [else + (record-case (car arg*) + [(constant c) + (unless (char? c) (error who "invalid arg to string ~s" x)) + (list* (movb (int (char->integer c)) (mem idx apr)) + (f (cdr arg*) (fxadd1 idx)))] + [else + (list* (movl (Simple (car arg*)) ebx) + (movb bh (mem idx apr)) + (f (cdr arg*) (fxadd1 idx)))])]))] + [($current-frame) + (list* (movl (pcb-ref 'next-continuation) eax) + ac)] + [($seal-frame-and-call) + (list* (movl (Simple (car arg*)) cpr) ; proc + (movl (pcb-ref 'frame-base) eax) + ; eax=baseofstack + (movl (mem (fx- 0 wordsize) eax) ebx) ; underflow handler + (movl ebx (mem (fx- 0 wordsize) fpr)) ; set + ; create a new cont record + (movl (int continuation-tag) (mem 0 apr)) + (movl fpr (mem disp-continuation-top apr)) + ; compute the size of the captured frame + (movl eax ebx) + (subl fpr ebx) + (subl (int wordsize) ebx) + ; and store it + (movl ebx (mem disp-continuation-size apr)) + ; load next cont + (movl (pcb-ref 'next-continuation) ebx) + ; and store it + (movl ebx (mem disp-continuation-next apr)) + ; adjust ap + (movl apr eax) + (addl (int vector-tag) eax) + (addl (int continuation-size) apr) + ; store new cont in current-cont + (movl eax (pcb-ref 'next-continuation)) + ; adjust fp + (movl fpr (pcb-ref 'frame-base)) + (subl (int wordsize) fpr) + ; tail-call f + (movl eax (mem (fx- 0 wordsize) fpr)) + (movl (int (argc-convention 1)) eax) + (tail-indirect-cpr-call) + ac)] + [($code-size) + (indirect-ref arg* (fx- disp-code-instrsize vector-tag) ac)] + [($code-reloc-vector) + (indirect-ref arg* (fx- disp-code-relocsize vector-tag) ac)] + [($code-freevars) + (indirect-ref arg* (fx- disp-code-freevars vector-tag) ac)] + [($set-car! $set-cdr! $vector-set! $string-set! $exit + $set-symbol-value! $set-symbol-plist! + $code-set! primitive-set! + $set-code-object! $set-code-object+offset! $set-code-object+offset/rel! + $record-set!) + (do-effect-prim op arg* + (cons (movl (int void-object) eax) ac))] + [(fixnum? immediate? $fxzero? boolean? char? pair? vector? string? symbol? + procedure? null? not eof-object? $fx= $fx< $fx<= $fx> $fx>= eq? + $char= $char< $char<= $char> $char>= $unbound-object? $code? + $record? $record/rtd? bwp-object?) + (do-pred->value-prim op arg* ac)] + [($code->closure) + (list* + (movl (Simple (car arg*)) eax) + (addl (int (fx- disp-code-data vector-tag)) eax) + (movl eax (mem 0 apr)) + (movl apr eax) + (addl (int closure-tag) eax) + (addl (int (align disp-closure-data)) apr) + ac)] + [($frame->continuation) + (NonTail + (make-closure (make-code-loc SL_continuation_code) arg*) + ac)] + [($make-call-with-values-procedure) + (NonTail + (make-closure (make-code-loc SL_call_with_values) arg*) + ac)] + [($make-values-procedure) + (NonTail + (make-closure (make-code-loc SL_values) arg*) + ac)] + [else + (error 'value-prim "unhandled ~s" op)])) + (define (indirect-assignment arg* offset ac) + (list* + (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem offset eax)) + ;;; record side effect + (addl (int offset) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)) + (define (do-effect-prim op arg* ac) + (case op + [($vector-set!) + (list* (movl (Simple (car arg*)) ebx) + (addl (Simple (cadr arg*)) ebx) + (addl (int (fx- disp-vector-data vector-tag)) ebx) + (movl (Simple (caddr arg*)) eax) + (movl eax (mem 0 ebx)) + ;;; record side effect + (shrl (int pageshift) ebx) + (sall (int wordshift) ebx) + (addl (pcb-ref 'dirty-vector) ebx) + (movl (int dirty-word) (mem 0 ebx)) + ac)] + [($code-set!) + (list* (movl (Simple (cadr arg*)) eax) + (sarl (int fx-shift) eax) + (addl (Simple (car arg*)) eax) + (movl (Simple (caddr arg*)) ebx) + (sall (int (fx- 8 fx-shift)) ebx) + (movb bh (mem (fx- disp-code-data vector-tag) eax)) + ac)] + [($string-set!) + (list* (movl (Simple (cadr arg*)) eax) + (sarl (int fx-shift) eax) + (addl (Simple (car arg*)) eax) + (movl (Simple (caddr arg*)) ebx) + (movb bh (mem (fx- disp-string-data string-tag) eax)) + ac)] + [($set-car!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-car pair-tag) eax)) + ;;; record side effect + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($set-cdr!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-cdr pair-tag) eax)) + ;;; record side effect + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($set-tcbucket-key!) + (indirect-assignment arg* (fx- disp-tcbucket-key vector-tag) ac)] + [($set-tcbucket-val!) + (indirect-assignment arg* (fx- disp-tcbucket-val vector-tag) ac)] + [($set-tcbucket-next!) + (indirect-assignment arg* (fx- disp-tcbucket-next vector-tag) ac)] + [($set-tcbucket-tconc!) + (indirect-assignment arg* (fx- disp-tcbucket-tconc vector-tag) ac)] + + [($set-symbol-value!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-symbol-value symbol-tag) eax)) + ;;; record side effect + (addl (int (fx- disp-symbol-value symbol-tag)) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [(primitive-set!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-symbol-system-value symbol-tag) eax)) + ;;; record side effect + (addl (int (fx- disp-symbol-system-value symbol-tag)) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($set-symbol-plist!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-symbol-plist symbol-tag) eax)) + ;;; record side effect + (addl (int (fx- disp-symbol-plist symbol-tag)) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($set-symbol-unique-string!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-symbol-unique-string symbol-tag) eax)) + ;;; record side effect + (addl (int (fx- disp-symbol-unique-string symbol-tag)) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($set-symbol-string!) + (list* (movl (Simple (car arg*)) eax) + (movl (Simple (cadr arg*)) ebx) + (movl ebx (mem (fx- disp-symbol-string symbol-tag) eax)) + ;;; record side effect + (addl (int (fx- disp-symbol-string symbol-tag)) eax) + (shrl (int pageshift) eax) + (sall (int wordshift) eax) + (addl (pcb-ref 'dirty-vector) eax) + (movl (int dirty-word) (mem 0 eax)) + ac)] + [($record-set!) + (list* (movl (Simple (car arg*)) ebx) + (addl (Simple (cadr arg*)) ebx) + (movl (Simple (caddr arg*)) eax) + (addl (int (fx- disp-record-data record-ptag)) ebx) + (movl eax (mem 0 ebx)) + ;;; record side effect + (shrl (int pageshift) ebx) + (sall (int wordshift) ebx) + (addl (pcb-ref 'dirty-vector) ebx) + (movl (int dirty-word) (mem 0 ebx)) + ac)] + [(cons void $fxadd1 $fxsub1 $record-ref) + (let f ([arg* arg*]) + (cond + [(null? arg*) ac] + [else + (Effect (car arg*) (f (cdr arg*)))]))] + [else + (error 'do-effect-prim "unhandled op ~s" op)])) + (define (do-simple-test x Lt Lf ac) + (unless (or Lt Lf) + (error 'Pred "no labels")) + (cond + [(not Lt) + (list* (cmpl (int bool-f) x) (je Lf) ac)] + [(not Lf) + (list* (cmpl (int bool-f) x) (jne Lt) ac)] + [else + (list* (cmpl (int bool-f) x) (je Lf) (jmp Lt) ac)])) + (define (Simple x) + (record-case x + [(cp-var i) + (mem (fx+ (fx* i wordsize) (fx- disp-closure-data closure-tag)) cpr)] + [(frame-var i) (mem (fx* i (fx- 0 wordsize)) fpr)] + [(constant c) (constant-val c)] + [(code-loc label) (label-address label)] + [(primref op) (primref-loc op)] + [else (error 'Simple "what ~s" x)])) + (define (closure-size x) + (align (fx+ disp-closure-data + (fx* wordsize (length (closure-free* x)))))) + (define (assign-codes rhs* n* i ac) + (cond + [(null? rhs*) ac] + [else + (record-case (car rhs*) + [(closure label free*) + (cons (movl (Simple label) (mem i apr)) + (assign-codes + (cdr rhs*) (cdr n*) (fx+ i (car n*)) ac))])])) + (define (whack-free x i n* rhs* ac) + (cond + [(null? rhs*) ac] + [else + (let ([free (closure-free* (car rhs*))]) + (let f ([free free] [j (fx+ i disp-closure-data)]) + (cond + [(null? free) + (whack-free x (fx+ i (car n*)) (cdr n*) (cdr rhs*) ac)] + [(eq? (car free) x) + (cons + (movl eax (mem j apr)) + (f (cdr free) (fx+ j wordsize)))] + [else (f (cdr free) (fx+ j wordsize))])))])) + (define (assign-nonrec-free* rhs* all-rhs* n* seen ac) + (cond + [(null? rhs*) ac] + [else + (let f ([ls (closure-free* (car rhs*))] [seen seen]) + (cond + [(null? ls) + (assign-nonrec-free* (cdr rhs*) all-rhs* n* seen ac)] + [(memq (car ls) seen) (f (cdr ls) seen)] + [else + (cons + (movl (Simple (car ls)) eax) + (whack-free (car ls) 0 n* all-rhs* + (f (cdr ls) (cons (car ls) seen))))]))])) + (define (assign-rec-free* lhs* rhs* all-n* ac) + (list* (movl apr eax) + (addl (int closure-tag) eax) + (let f ([lhs* lhs*] [n* all-n*]) + (cond + [(null? (cdr lhs*)) + (cons + (movl eax (Simple (car lhs*))) + (whack-free (car lhs*) 0 all-n* rhs* ac))] + [else + (cons + (movl eax (Simple (car lhs*))) + (whack-free (car lhs*) 0 all-n* rhs* + (cons + (addl (int (car n*)) eax) + (f (cdr lhs*) (cdr n*)))))])))) + (define (sum ac ls) + (cond + [(null? ls) ac] + [else (sum (fx+ ac (car ls)) (cdr ls))])) + (define (do-fix lhs* rhs* ac) + ;;; 1. first, set the code pointers in the right places + ;;; 2. next, for every variable appearing in the rhs* but is not in + ;;; the lhs*, load it once and set it everywhere it occurs. + ;;; 3. next, compute the values of the lhs*, and for every computed + ;;; value, store it on the stack, and set it everywhere it occurs + ;;; in the rhs* + ;;; 4. that's it. + (let* ([n* (map closure-size rhs*)]) + (assign-codes rhs* n* 0 + (assign-nonrec-free* rhs* rhs* n* lhs* + (assign-rec-free* lhs* rhs* n* + (cons (addl (int (sum 0 n*)) apr) ac)))))) + (define (frame-adjustment offset) + (fx* (fxsub1 offset) (fx- 0 wordsize))) + (define (NonTail x ac) + (record-case x + [(constant c) + (cons (movl (constant-val c) eax) ac)] + [(frame-var) + (cons (movl (Simple x) eax) ac)] + [(cp-var) + (cons (movl (Simple x) eax) ac)] + [(foreign-label L) + (cons (movl (list 'foreign-label L) eax) ac)] + [(primref c) + (cons (movl (primref-loc c) eax) ac)] + [(closure label arg*) + (let f ([arg* arg*] [off disp-closure-data]) + (cond + [(null? arg*) + (list* (movl (Simple label) (mem 0 apr)) + (movl apr eax) + (addl (int (align off)) apr) + (addl (int closure-tag) eax) + ac)] + [else + (list* (movl (Simple (car arg*)) eax) + (movl eax (mem off apr)) + (f (cdr arg*) (fx+ off wordsize)))]))] + [(conditional test conseq altern) + (let ([Lj (unique-label)] [Lf (unique-label)]) + (Pred test #f Lf + (NonTail conseq + (list* (jmp Lj) Lf (NonTail altern (cons Lj ac))))))] + [(seq e0 e1) + (Effect e0 (NonTail e1 ac))] + [(fix lhs* rhs* body) + (do-fix lhs* rhs* (NonTail body ac))] + [(primcall op rand*) + (do-value-prim op rand* ac)] + [(new-frame base-idx size body) + (NonTail body ac)] + [(call-cp call-convention rp-convention offset size mask) + (let ([L_CALL (unique-label)]) + (case call-convention + [(normal) + (list* (addl (int (frame-adjustment offset)) fpr) + (movl (int (argc-convention size)) eax) + (jmp L_CALL) + ; NEW FRAME + `(byte-vector ,mask) + `(int ,(fx* offset wordsize)) + `(current-frame-offset) + (rp-label rp-convention) + `(byte 0) ; padding for indirect calls only + `(byte 0) ; direct calls are ok + L_CALL + (indirect-cpr-call) + (movl (mem 0 fpr) cpr) + (subl (int (frame-adjustment offset)) fpr) + ac)] + [(foreign) + (list* (addl (int (frame-adjustment offset)) fpr) + (movl (int (argc-convention size)) eax) + (movl '(foreign-label "ik_foreign_call") ebx) + (jmp L_CALL) + ; NEW FRAME + (byte-vector mask) + `(int ,(fx* offset wordsize)) + `(current-frame-offset) + (rp-label rp-convention) ; should be 0, since C has 1 rv + '(byte 0) + '(byte 0) + '(byte 0) + L_CALL + (call ebx) + (movl (mem 0 fpr) cpr) + (subl (int (frame-adjustment offset)) fpr) + ac)] + [else + (error who "invalid convention ~s for call-cp" call-convention)]))] + [else (error 'NonTail "invalid expression ~s" x)])) + (define (Pred x Lt Lf ac) + (record-case x + [(frame-var i) + (do-simple-test (idx->frame-loc i) Lt Lf ac)] + [(cp-var i) + (do-simple-test (Simple x) Lt Lf ac)] + [(constant c) + (if c + (if Lt (cons (jmp Lt) ac) ac) + (if Lf (cons (jmp Lf) ac) ac))] + [(fix lhs* rhs* body) + (do-fix lhs* rhs* (Pred body Lt Lf ac))] + [(primcall op rand*) + (do-pred-prim op rand* Lt Lf ac)] + [(conditional test conseq altern) + (cond + [(not Lt) + (let ([Lj^ (unique-label)] [Lf^ (unique-label)]) + (Pred test #f Lf^ + (Pred conseq Lj^ Lf + (cons Lf^ + (Pred altern #f Lf + (cons Lj^ ac))))))] + [(not Lf) + (let ([Lj^ (unique-label)] [Lf^ (unique-label)]) + (Pred test #f Lf^ + (Pred conseq Lt Lj^ + (cons Lf^ + (Pred altern Lt #f + (cons Lj^ ac))))))] + [else + (let ([Lf^ (unique-label)]) + (Pred test #f Lf^ + (Pred conseq Lt Lf + (cons Lf^ + (Pred altern Lt Lf ac)))))])] + [(seq e0 e1) + (Effect e0 (Pred e1 Lt Lf ac))] + [(new-frame) + (NonTail x (do-simple-test eax Lt Lf ac))] + [else (error 'Pred "invalid expression ~s" x)])) + (define (idx->frame-loc i) + (mem (fx* i (fx- 0 wordsize)) fpr)) + (define (Effect x ac) + (record-case x + [(constant) ac] + [(primcall op rand*) + (do-effect-prim op rand* ac)] + [(conditional test conseq altern) + (let* ([Ljoin (unique-label)] + [ac (cons Ljoin ac)] + [altern-ac (Effect altern ac)]) + (cond + [(eq? altern-ac ac) ;; altern is nop + (let* ([conseq-ac (Effect conseq ac)]) + (cond + [(eq? conseq-ac ac) ;; conseq is nop too! + (Effect test ac)] + [else ; "when" pattern + (Pred test #f Ljoin conseq-ac)]))] + [else + (let* ([Lf (unique-label)] + [nac (list* (jmp Ljoin) Lf altern-ac)] + [conseq-ac (Effect conseq nac)]) + (cond + [(eq? conseq-ac nac) ;; "unless" pattern" + (Pred test Ljoin #f altern-ac)] + [else + (Pred test #f Lf conseq-ac)]))]))] +;;; [(conditional test conseq altern) +;;; (let ([Lf (unique-label)] [Ljoin (unique-label)]) +;;; (Pred test #f Lf +;;; (Effect conseq +;;; (list* (jmp Ljoin) Lf (Effect altern (cons Ljoin ac))))))] + [(seq e0 e1) + (Effect e0 (Effect e1 ac))] + [(fix lhs* rhs* body) + (do-fix lhs* rhs* (Effect body ac))] + [(assign loc val) + (record-case loc + [(frame-var i) + (record-case val + [(constant c) + (cons (movl (constant-val c) (idx->frame-loc i)) ac)] + [else + (NonTail val + (cons (movl eax (idx->frame-loc i)) ac))])] + [else (error who "invalid assign loc ~s" loc)])] + [(eval-cp check body) + (cond + [check + (NonTail body + (list* + (movl eax cpr) + (andl (int closure-mask) eax) + (cmpl (int closure-tag) eax) + (jne (label SL_nonprocedure)) + ac))] + [(primref? body) + (list* (movl (primref-loc (primref-name body)) cpr) ac)] + [else + (NonTail body (list* (movl eax cpr) ac))])] + [(save-cp loc) + (record-case loc + [(frame-var i) + (cons (movl cpr (idx->frame-loc i)) ac)] + [else (error who "invalid cpr loc ~s" x)])] + [(new-frame) (NonTail x ac)] + [(frame-var) ac] + [else (error 'Effect "invalid expression ~s" x)])) + (define (Tail x ac) + (record-case x + [(return x) + (NonTail x (cons (ret) ac))] + [(conditional test conseq altern) + (let ([L (unique-label)]) + (Pred test #f L + (Tail conseq + (cons L (Tail altern ac)))))] + [(seq e0 e1) + (Effect e0 (Tail e1 ac))] + [(fix lhs* rhs* body) + (do-fix lhs* rhs* (Tail body ac))] + [(new-frame idx size body) + (Tail body ac)] + [(tailcall-cp call-convention argc) + (list* + (movl (int (argc-convention argc)) eax) + (case call-convention + [(normal) (tail-indirect-cpr-call)] + [(apply) (jmp (label SL_apply))] + [else + (error who "invalid tail-call convention ~s" call-convention)]) + ac)] +;;; [(call-cp call-convention rp-convention idx argc mask) +;;; (unless (eq? rp-convention 'tail) +;;; (error who "nontail rp (~s) in tail context" rp-convention)) +;;; (let f ([i 0]) +;;; (cond +;;; [(fx= i argc) +;;; (case call-convention +;;; [(normal) +;;; (list* +;;; (movl (int (argc-convention argc)) eax) +;;; (tail-indirect-cpr-call) +;;; ac)] +;;; [(apply) +;;; (list* +;;; (movl (int (argc-convention argc)) eax) +;;; (jmp (label SL_apply)) +;;; ac)] +;;; [else +;;; (error who "invalid conv ~s in tail call-cpr" call-convention)])] +;;; [else +;;; (list* (movl (mem (fx* (fx+ idx (fxadd1 i)) +;;; (fx- 0 wordsize)) fpr) +;;; eax) +;;; (movl eax (mem (fx* (fx+ i 1) (fx- 0 wordsize)) fpr)) +;;; (f (fxadd1 i)))]))] + [else (error 'Tail "invalid expression ~s" x)])) + (define (handle-vararg fml-count ac) + (define CONTINUE_LABEL (unique-label)) + (define DONE_LABEL (unique-label)) + (define CONS_LABEL (unique-label)) + (define LOOP_HEAD (unique-label)) + (define L_CALL (unique-label)) + (list* (cmpl (int (argc-convention (fxsub1 fml-count))) eax) + (jg (label SL_invalid_args)) + (jl CONS_LABEL) + (movl (int nil) ebx) + (jmp DONE_LABEL) + CONS_LABEL + (movl (pcb-ref 'allocation-redline) ebx) + (addl eax ebx) + (addl eax ebx) + (cmpl ebx apr) + (jle LOOP_HEAD) + ; overflow + (addl eax esp) ; advance esp to cover args + (pushl cpr) ; push current cp + (pushl eax) ; push argc + (negl eax) ; make argc positive + (addl (int (fx* 4 wordsize)) eax) ; add 4 words to adjust frame size + (pushl eax) ; push frame size + (addl eax eax) ; double the number of args + (movl eax (mem (fx* -2 wordsize) fpr)) ; pass it as first arg + (movl (int (argc-convention 1)) eax) ; setup argc + (movl (primref-loc 'do-vararg-overflow) cpr) ; load handler + (jmp L_CALL) ; go to overflow handler + ; NEW FRAME + (int 0) ; if the framesize=0, then the framesize is dynamic + '(current-frame-offset) + (int 0) ; multiarg rp + (byte 0) + (byte 0) + L_CALL + (indirect-cpr-call) + (popl eax) ; pop framesize and drop it + (popl eax) ; reload argc + (popl cpr) ; reload cp + (subl eax fpr) ; readjust fp + LOOP_HEAD + (movl (int nil) ebx) + CONTINUE_LABEL + (movl ebx (mem disp-cdr apr)) + (movl (mem fpr eax) ebx) + (movl ebx (mem disp-car apr)) + (movl apr ebx) + (addl (int pair-tag) ebx) + (addl (int pair-size) apr) + (addl (int (fxsll 1 fx-shift)) eax) + (cmpl (int (fx- 0 (fxsll fml-count fx-shift))) eax) + (jle CONTINUE_LABEL) + DONE_LABEL + (movl ebx (mem (fx- 0 (fxsll fml-count fx-shift)) fpr)) + ac)) + (define (Entry check? x ac) + (record-case x + [(clambda-case fml* proper body) + (let ([ac (Tail body ac)]) + (cond + [(and proper check?) + (list* (cmpl (int (argc-convention (length fml*))) eax) + (jne (label SL_invalid_args)) + ac)] + [proper ac] + [else + (handle-vararg (length fml*) ac)]))])) + (define make-dispatcher + (lambda (j? L L* x x* ac) + (cond + [(null? L*) (if j? (cons (jmp (label L)) ac) ac)] + [else + (record-case x + [(clambda-case fml* proper _) + (cond + [proper + (list* (cmpl (int (argc-convention (length fml*))) eax) + (je (label L)) + (make-dispatcher #t + (car L*) (cdr L*) (car x*) (cdr x*) ac))] + [else + (list* (cmpl (int (argc-convention (fxsub1 (length fml*)))) eax) + (jle (label L)) + (make-dispatcher #t + (car L*) (cdr L*) (car x*) (cdr x*) ac))])])]))) + (define (handle-cases x x*) + (let ([L* (map (lambda (_) (gensym)) x*)] + [L (gensym)]) + (make-dispatcher #f L L* x x* + (let f ([x x] [x* x*] [L L] [L* L*]) + (cond + [(null? x*) + (cons (label L) (Entry 'check x '()))] + [else + (cons (label L) + (Entry #f x + (f (car x*) (cdr x*) (car L*) (cdr L*))))]))))) + (define (CodeExpr x) + (record-case x + [(clambda-code L cases free) + (list* + (length free) + (label L) + (handle-cases (car cases) (cdr cases)))])) + (record-case x + [(codes list body) + (cons (cons 0 (Tail body '())) + (map CodeExpr list))])) + + +(define SL_nonprocedure (gensym "SL_nonprocedure")) + +(define SL_top_level_value_error (gensym "SL_top_level_value_error")) +(define SL_car_error (gensym "SL_car_error")) +(define SL_cdr_error (gensym "SL_cdr_error")) + +(define SL_invalid_args (gensym "SL_invalid_args")) +(define SL_foreign_call (gensym "SL_foreign_call")) +(define SL_continuation_code (gensym "SL_continuation_code")) +(define SL_multiple_values_error_rp (gensym "SL_multiple_values_error_rp")) +(define SL_multiple_values_ignore_rp (gensym "SL_multiple_ignore_error_rp")) +(define SL_underflow_multiple_values (gensym "SL_underflow_multiple_values")) +(define SL_underflow_handler (gensym "SL_underflow_handler")) +(define SL_scheme_exit (gensym "SL_scheme_exit")) +(define SL_apply (gensym "SL_apply")) +(define SL_values (gensym "SL_values")) +(define SL_call_with_values (gensym "SL_call_with_values")) + +(module () +(list*->code* + (list + (list 0 + (label SL_car_error) + (movl ebx (mem (fx- 0 wordsize) fpr)) + (movl (primref-loc 'car-error) cpr) + (movl (int (argc-convention 1)) eax) + (tail-indirect-cpr-call)) + + (list 0 + (label SL_cdr_error) + (movl ebx (mem (fx- 0 wordsize) fpr)) + (movl (primref-loc 'cdr-error) cpr) + (movl (int (argc-convention 1)) eax) + (tail-indirect-cpr-call)) + + (list 0 + (label SL_top_level_value_error) + (movl ebx (mem (fx- 0 wordsize) fpr)) + (movl (primref-loc 'top-level-value-error) cpr) + (movl (int (argc-convention 1)) eax) + (tail-indirect-cpr-call)) + + (let ([L_cwv_done (gensym)] + [L_cwv_loop (gensym)] + [L_cwv_multi_rp (gensym)] + [L_cwv_call (gensym)]) + (list + 0 ; no free vars + (label SL_call_with_values) + (cmpl (int (argc-convention 2)) eax) + (jne (label SL_invalid_args)) + (movl (mem (fx- 0 wordsize) fpr) ebx) ; producer + (movl ebx cpr) + (andl (int closure-mask) ebx) + (cmpl (int closure-tag) ebx) + (jne (label SL_nonprocedure)) + (movl (int (argc-convention 0)) eax) + (subl (int (fx* wordsize 2)) fpr) + (jmp (label L_cwv_call)) + ; MV NEW FRAME + (byte-vector '#(#b110)) + (int (fx* wordsize 3)) + '(current-frame-offset) + (label-address L_cwv_multi_rp) + (byte 0) + (byte 0) + (label L_cwv_call) + (indirect-cpr-call) + ;;; one value returned + (addl (int (fx* wordsize 2)) fpr) + (movl (mem (fx* -2 wordsize) fpr) ebx) ; consumer + (movl ebx cpr) + (movl eax (mem (fx- 0 wordsize) fpr)) + (movl (int (argc-convention 1)) eax) + (andl (int closure-mask) ebx) + (cmpl (int closure-tag) ebx) + (jne (label SL_nonprocedure)) + (tail-indirect-cpr-call) + ;;; multiple values returned + (label L_cwv_multi_rp) + ; because values does not pop the return point + ; we have to adjust fp one more word here + (addl (int (fx* wordsize 3)) fpr) + (movl (mem (fx* -2 wordsize) fpr) cpr) ; consumer + (cmpl (int (argc-convention 0)) eax) + (je (label L_cwv_done)) + (movl (int (fx* -4 wordsize)) ebx) + (addl fpr ebx) ; ebx points to first value + (movl ebx ecx) + (addl eax ecx) ; ecx points to the last value + (label L_cwv_loop) + (movl (mem 0 ebx) edx) + (movl edx (mem (fx* 3 wordsize) ebx)) + (subl (int wordsize) ebx) + (cmpl ecx ebx) + (jge (label L_cwv_loop)) + (label L_cwv_done) + (movl cpr ebx) + (andl (int closure-mask) ebx) + (cmpl (int closure-tag) ebx) + (jne (label SL_nonprocedure)) + (tail-indirect-cpr-call))) + + (let ([L_values_one_value (gensym)] + [L_values_many_values (gensym)]) + (list 0 ; no freevars + (label SL_values) + (cmpl (int (argc-convention 1)) eax) + (je (label L_values_one_value)) + (label L_values_many_values) + (movl (mem 0 fpr) ebx) ; return point + (jmp (mem disp-multivalue-rp ebx)) ; go + (label L_values_one_value) + (movl (mem (fx- 0 wordsize) fpr) eax) + (ret))) + + (let ([L_apply_done (gensym)] + [L_apply_loop (gensym)]) + (list 0 + (label SL_apply) + (movl (mem fpr eax) ebx) + (cmpl (int nil) ebx) + (je (label L_apply_done)) + (label L_apply_loop) + (movl (mem (fx- disp-car pair-tag) ebx) ecx) + (movl (mem (fx- disp-cdr pair-tag) ebx) ebx) + (movl ecx (mem fpr eax)) + (subl (int wordsize) eax) + (cmpl (int nil) ebx) + (jne (label L_apply_loop)) + (label L_apply_done) + (addl (int wordsize) eax) + (tail-indirect-cpr-call))) + + (list 0 + (label SL_nonprocedure) + (movl cpr (mem (fx- 0 wordsize) fpr)) ; first arg + (movl (primref-loc '$apply-nonprocedure-error-handler) cpr) + (movl (int (argc-convention 1)) eax) + (tail-indirect-cpr-call)) + + (list 0 + (label SL_multiple_values_error_rp) + (movl (primref-loc '$multiple-values-error) cpr) + (tail-indirect-cpr-call)) + + (list 0 + (label SL_multiple_values_ignore_rp) + (ret)) + + (list 0 + (label SL_invalid_args) + ;;; + (movl cpr (mem (fx- 0 wordsize) fpr)) ; first arg + (negl eax) + (movl eax (mem (fx- 0 (fx* 2 wordsize)) fpr)) + (movl (primref-loc '$incorrect-args-error-handler) cpr) + (movl (int (argc-convention 2)) eax) + (tail-indirect-cpr-call)) + + (let ([Lset (gensym)] [Lloop (gensym)]) + (list 0 + (label SL_foreign_call) + (movl fpr (pcb-ref 'frame-pointer)) + (movl apr (pcb-ref 'allocation-pointer)) + (movl fpr ebx) + (movl (pcb-ref 'system-stack) esp) + (pushl pcr) + (cmpl (int 0) eax) + (je (label Lset)) + (label Lloop) + (movl (mem ebx eax) ecx) + (pushl ecx) + (addl (int 4) eax) + (cmpl (int 0) eax) + (jne (label Lloop)) + (label Lset) + ; FOREIGN NEW FRAME + (call cpr) + (movl (pcb-ref 'frame-pointer) fpr) + (movl (pcb-ref 'allocation-pointer) apr) + (ret))) + + (let ([L_cont_zero_args (gensym)] + [L_cont_mult_args (gensym)] + [L_cont_one_arg (gensym)] + [L_cont_mult_move_args (gensym)] + [L_cont_mult_copy_loop (gensym)]) + (list 1 ; freevars + (label SL_continuation_code) + (movl (mem (fx- disp-closure-data closure-tag) cpr) ebx) ; captured-k + (movl ebx (pcb-ref 'next-continuation)) ; set + (movl (pcb-ref 'frame-base) ebx) + (cmpl (int (argc-convention 1)) eax) + (jg (label L_cont_zero_args)) + (jl (label L_cont_mult_args)) + (label L_cont_one_arg) + (movl (mem (fx- 0 wordsize) fpr) eax) + (movl ebx fpr) + (subl (int wordsize) fpr) + (ret) + (label L_cont_zero_args) + (subl (int wordsize) ebx) + (movl ebx fpr) + (movl (mem 0 ebx) ebx) ; return point + (jmp (mem disp-multivalue-rp ebx)) ; go + (label L_cont_mult_args) + (subl (int wordsize) ebx) + (cmpl ebx fpr) + (jne (label L_cont_mult_move_args)) + (movl (mem 0 ebx) ebx) + (jmp (mem disp-multivalue-rp ebx)) + (label L_cont_mult_move_args) + ; move args from fpr to ebx + (movl (int 0) ecx) + (label L_cont_mult_copy_loop) + (subl (int wordsize) ecx) + (movl (mem fpr ecx) edx) + (movl edx (mem ebx ecx)) + (cmpl ecx eax) + (jne (label L_cont_mult_copy_loop)) + (movl ebx fpr) + (movl (mem 0 ebx) ebx) + (jmp (mem disp-multivalue-rp ebx)) + )) + ))) + + + +(define (compile-expr expr) + (let* ([p (recordize expr)] + [p (optimize-direct-calls p)] +;;; [foo (analyze-cwv p)] + [p (optimize-letrec p)] + ;[p (remove-letrec p)] + [p (remove-assignments p)] + [p (convert-closures p)] + [p (lift-codes p)] + [p (introduce-primcalls p)] + [p (simplify-operands p)] + [p (insert-stack-overflow-checks p)] + [p (insert-allocation-checks p)] + [p (remove-local-variables p)] + [p (optimize-ap-check p)] + [ls* (generate-code p)] + [f (when (assembler-output) + (for-each + (lambda (ls) + (for-each (lambda (x) (printf " ~s\n" x)) ls)) + ls*))] + [code* (list*->code* ls*)]) + (car code*))) + +(define compile-file + (lambda (input-file output-file . rest) + (let ([ip (open-input-file input-file)] + [op (apply open-output-file output-file rest)]) + (let f () + (let ([x (read ip)]) + (unless (eof-object? x) + (fasl-write (compile-expr (expand x)) op) + (f)))) + (close-input-port ip) + (close-output-port op)))) + +(primitive-set! 'compile-file compile-file) +(primitive-set! 'assembler-output (make-parameter #f)) +(primitive-set! 'compile + (lambda (x) + (let ([code (compile-expr (expand x))]) + (let ([proc ($code->closure code)]) + (proc))))) + +) + diff --git a/src/libcontrol.fasl b/src/libcontrol.fasl index d86b21b..aabf1e3 100644 Binary files a/src/libcontrol.fasl and b/src/libcontrol.fasl differ diff --git a/src/libcore-6.9.ss b/src/libcore-6.9.ss new file mode 100644 index 0000000..680b691 --- /dev/null +++ b/src/libcore-6.9.ss @@ -0,0 +1,1664 @@ + +;;; 6.9: * removed uuid +;;; * top-level-value is now open-coded. +;;; +;;; 6.2: * added bwp-object?, weak-cons, weak-pair? +;;; * pointer-value +;;; 6.1: * added uses of case-lambda to replace the ugly code +;;; 6.0: * basic version working + + +(primitive-set! 'call-with-values + ($make-call-with-values-procedure)) + +(primitive-set! 'values + ($make-values-procedure)) + +(primitive-set! 'exit + (case-lambda + [() (exit 0)] + [(status) (foreign-call "exit" status)])) + +(primitive-set! 'eof-object + (lambda () (eof-object))) + +(primitive-set! 'void + (lambda () (void))) + +(primitive-set! 'eof-object? + (lambda (x) (eof-object? x))) + +(primitive-set! 'fxadd1 + (lambda (n) + (unless (fixnum? n) + (error 'fxadd1 "~s is not a fixnum" n)) + ($fxadd1 n))) + +(primitive-set! 'fxsub1 + (lambda (n) + (unless (fixnum? n) + (error 'fxsub1 "~s is not a fixnum" n)) + ($fxsub1 n))) + +(primitive-set! 'integer->char + (lambda (n) + (unless (fixnum? n) + (error 'integer->char "~s is not a fixnum" n)) + (unless (and ($fx>= n 0) + ($fx<= n 255)) + (error 'integer->char "~s is out of range[0..255]" n)) + ($fixnum->char n))) + +(primitive-set! 'char->integer + (lambda (x) + (unless (char? x) + (error 'char->integer "~s is not a character" x)) + ($char->fixnum x))) + +(primitive-set! 'fxlognot + (lambda (x) + (unless (fixnum? x) + (error 'fxlognot "~s is not a fixnum" x)) + ($fxlognot x))) + +(primitive-set! 'fixnum? (lambda (x) (fixnum? x))) +(primitive-set! 'immediate? (lambda (x) (immediate? x))) + +(primitive-set! 'fxzero? + (lambda (x) + (unless (fixnum? x) + (error 'fxzero? "~s is not a fixnum" x)) + ($fxzero? x))) + +(primitive-set! 'boolean? (lambda (x) (boolean? x))) + +(primitive-set! 'char? (lambda (x) (char? x))) + +(primitive-set! 'vector? (lambda (x) (vector? x))) + +(primitive-set! 'string? (lambda (x) (string? x))) + +(primitive-set! 'procedure? (lambda (x) (procedure? x))) + +(primitive-set! 'null? (lambda (x) (null? x))) + +(primitive-set! 'pair? (lambda (x) (pair? x))) + +(let () + (define fill! + (lambda (v i n fill) + (cond + [($fx= i n) v] + [else + ($vector-set! v i fill) + (fill! v ($fx+ i 1) n fill)]))) + (define make-vector + (case-lambda + [(n) (make-vector n (void))] + [(n fill) + (unless (and (fixnum? n) (fx>= n 0)) + (error 'make-vector "~s is not a valid length" n)) + (fill! ($make-vector n) 0 n fill)])) + (primitive-set! 'make-vector make-vector)) + +(primitive-set! 'vector-length + (lambda (x) + (unless (vector? x) + (error 'vector-length "~s is not a vector" x)) + ($vector-length x))) + +(let () + (define fill! + (lambda (s i n c) + (cond + [($fx= i n) s] + [else + ($string-set! s i c) + (fill! s ($fx+ i 1) n c)]))) + (define make-string + (case-lambda + [(n) + (unless (and (fixnum? n) (fx>= n 0)) + (error 'make-string "~s is not a valid length" n)) + ($make-string n)] + [(n c) + (unless (and (fixnum? n) (fx>= n 0)) + (error 'make-string "~s is not a valid length" n)) + (unless (char? c) + (error 'make-string "~s is not a character" c)) + (fill! ($make-string n) 0 n c)])) + (primitive-set! 'make-string make-string)) + + +(primitive-set! 'string-length + (lambda (x) + (unless (string? x) + (error 'string-length "~s is not a string" x)) + ($string-length x))) + +(primitive-set! 'string->list + (lambda (x) + (unless (string? x) + (error 'string->list "~s is not a string" x)) + (let f ([x x] [i ($string-length x)] [ac '()]) + (cond + [($fxzero? i) ac] + [else + (let ([i ($fxsub1 i)]) + (f x i (cons ($string-ref x i) ac)))])))) + + +(let () + (define bstring=? + (lambda (s1 s2 i j) + (or ($fx= i j) + (and ($char= ($string-ref s1 i) ($string-ref s2 i)) + (bstring=? s1 s2 ($fxadd1 i) j))))) + (define check-strings-and-return-false + (lambda (s*) + (cond + [(null? s*) #f] + [(string? ($car s*)) + (check-strings-and-return-false ($cdr s*))] + [else (err ($car s*))]))) + (define strings=? + (lambda (s s* n) + (or (null? s*) + (let ([a ($car s*)]) + (unless (string? a) + (error 'string=? "~s is not a string" a)) + (if ($fx= n ($string-length a)) + (and (strings=? s ($cdr s*) n) + (bstring=? s a 0 n)) + (check-strings-and-return-false ($cdr s*))))))) + (define (err x) + (error 'string=? "~s is not a string" x)) + (primitive-set! 'string=? + (case-lambda + [(s s1) + (if (string? s) + (if (string? s1) + (let ([n ($string-length s)]) + (and ($fx= n ($string-length s1)) + (bstring=? s s1 0 n))) + (err s1)) + (err s))] + [(s . s*) + (if (string? s) + (strings=? s s* ($string-length s)) + (err s))]))) + + + +(let () + ;; FIXME: make nonconsing on 0,1,2, and 3 args + (define length* + (lambda (s* n) + (cond + [(null? s*) n] + [else + (let ([a ($car s*)]) + (unless (string? a) + (error 'string-append "~s is not a string" a)) + (length* ($cdr s*) ($fx+ n ($string-length a))))]))) + (define fill-string + (lambda (s a si sj ai) + (unless ($fx= si sj) + ($string-set! s si ($string-ref a ai)) + (fill-string s a ($fxadd1 si) sj ($fxadd1 ai))))) + (define fill-strings + (lambda (s s* i) + (cond + [(null? s*) s] + [else + (let ([a ($car s*)]) + (let ([n ($string-length a)]) + (let ([j ($fx+ i n)]) + (fill-string s a i j 0) + (fill-strings s ($cdr s*) j))))]))) + (primitive-set! 'string-append + (lambda s* + (let ([n (length* s* 0)]) + (let ([s ($make-string n)]) + (fill-strings s s* 0)))))) + + +(let () + (define fill + (lambda (s d si sj di) + (cond + [($fx= si sj) d] + [else + ($string-set! d di ($string-ref s si)) + (fill s d ($fxadd1 si) sj ($fxadd1 di))]))) + (primitive-set! 'substring + (lambda (s n m) + (unless (string? s) + (error 'substring "~s is not a string" s)) + (let ([len ($string-length s)]) + (unless (and (fixnum? n) + ($fx>= n 0) + ($fx< n len)) + (error 'substring "~s is not a valid start index for ~s" n s)) + (unless (and (fixnum? m) + ($fx>= m 0) + ($fx<= m len)) + (error 'substring "~s is not a valid end index for ~s" m s)) + (let ([len ($fx- m n)]) + (if ($fx<= len 0) + "" + (fill s ($make-string len) n m 0))))))) + +(primitive-set! 'not (lambda (x) (not x))) + +(primitive-set! 'symbol->string + (lambda (x) + (unless (symbol? x) + (error 'symbol->string "~s is not a symbol" x)) + (let ([str ($symbol-string x)]) + (or str + (let ([ct (gensym-count)]) + (let ([str (string-append (gensym-prefix) (fixnum->string ct))]) + ($set-symbol-string! x str) + (gensym-count ($fxadd1 ct)) + str)))))) + +(primitive-set! 'gensym? + (lambda (x) + (and (symbol? x) + (let ([s ($symbol-unique-string x)]) + (and s #t))))) + +(let () + (define f + (lambda (n i j) + (cond + [($fxzero? n) + (values (make-string i) j)] + [else + (let ([q ($fxquotient n 10)]) + (call-with-values + (lambda () (f q ($fxadd1 i) j)) + (lambda (str j) + (let ([r ($fx- n ($fx* q 10))]) + (string-set! str j + ($fixnum->char ($fx+ r ($char->fixnum #\0)))) + (values str ($fxadd1 j))))))]))) + (primitive-set! 'fixnum->string + (lambda (x) + (unless (fixnum? x) (error 'fixnum->string "~s is not a fixnum" x)) + (cond + [($fxzero? x) "0"] + [($fx> x 0) + (call-with-values + (lambda () (f x 0 0)) + (lambda (str j) str))] + [($fx= x -536870912) "-536870912"] + [else + (call-with-values + (lambda () (f ($fx- 0 x) 1 1)) + (lambda (str j) + ($string-set! str 0 #\-) + str))])))) + +;;; OLD (primitive-set! 'top-level-value +;;; OLD (lambda (x) +;;; OLD (unless (symbol? x) +;;; OLD (error 'top-level-value "~s is not a symbol" x)) +;;; OLD (let ([v ($symbol-value x)]) +;;; OLD (when ($unbound-object? v) +;;; OLD (error 'top-level-value "unbound variable ~s" x)) +;;; OLD v))) + +(primitive-set! 'top-level-value + (lambda (x) + (top-level-value x))) + +(primitive-set! 'top-level-bound? + (lambda (x) + (unless (symbol? x) + (error 'top-level-bound? "~s is not a symbol" x)) + (not ($unbound-object? ($symbol-value x))))) + +(primitive-set! 'set-top-level-value! + (lambda (x v) + (unless (symbol? x) + (error 'set-top-level-value! "~s is not a symbol" x)) + ($set-symbol-value! x v))) + +(primitive-set! 'symbol? (lambda (x) (symbol? x))) + +(primitive-set! 'primitive? + (lambda (x) + (unless (symbol? x) + (error 'primitive? "~s is not a symbol" x)) + (procedure? (primitive-ref x)))) + +(primitive-set! 'primitive-ref + (lambda (x) + (unless (symbol? x) + (error 'primitive-ref "~s is not a symbol" x)) + (let ([v (primitive-ref x)]) + (unless (procedure? v) + (error 'primitive-ref "~s is not a primitive" x)) + v))) + +(primitive-set! 'primitive-set! + (lambda (x v) + (unless (symbol? x) + (error 'primitive-set! "~s is not a symbol" x)) + (primitive-set! x v) + (set-top-level-value! x v))) + + + + + +(primitive-set! 'fx+ + (lambda (x y) + (unless (fixnum? x) + (error 'fx+ "~s is not a fixnum" x)) + (unless (fixnum? y) + (error 'fx+ "~s is not a fixnum" y)) + ($fx+ x y))) + +(primitive-set! 'fx- + (lambda (x y) + (unless (fixnum? x) + (error 'fx- "~s is not a fixnum" x)) + (unless (fixnum? y) + (error 'fx- "~s is not a fixnum" y)) + ($fx- x y))) + +(primitive-set! 'fx* + (lambda (x y) + (unless (fixnum? x) + (error 'fx* "~s is not a fixnum" x)) + (unless (fixnum? y) + (error 'fx* "~s is not a fixnum" y)) + ($fx* x y))) + + + +(primitive-set! 'fxquotient + (lambda (x y) + (unless (fixnum? x) + (error 'fxquotient "~s is not a fixnum" x)) + (unless (fixnum? y) + (error 'fxquotient "~s is not a fixnum" y)) + (when ($fxzero? y) + (error 'fxquotient "zero dividend ~s" y)) + ($fxquotient x y))) + + +(primitive-set! 'fxremainder + (lambda (x y) + (unless (fixnum? x) + (error 'fxremainder "~s is not a fixnum" x)) + (unless (fixnum? y) + (error 'fxremainder "~s is not a fixnum" y)) + (when ($fxzero? y) + (error 'fxremainder "zero dividend ~s" y)) + (let ([q ($fxquotient x y)]) + ($fx- x ($fx* q y))))) + + +(primitive-set! 'fxmodulo + (lambda (x y) + (unless (fixnum? x) + (error 'fxmodulo "~s is not a fixnum" x)) + (unless (fixnum? y) + (error 'fxmodulo "~s is not a fixnum" y)) + (when ($fxzero? y) + (error 'fxmodulo "zero dividend ~s" y)) + ($fxmodulo x y))) + + +(primitive-set! 'fxlogor + (lambda (x y) + (unless (fixnum? x) + (error 'fxlogor "~s is not a fixnum" x)) + (unless (fixnum? y) + (error 'fxlogor "~s is not a fixnum" y)) + ($fxlogor x y))) + +(primitive-set! 'fxlogxor + (lambda (x y) + (unless (fixnum? x) + (error 'fxlogxor "~s is not a fixnum" x)) + (unless (fixnum? y) + (error 'fxlogxor "~s is not a fixnum" y)) + ($fxlogxor x y))) + +(primitive-set! 'fxlogand + (lambda (x y) + (unless (fixnum? x) + (error 'fxlogand "~s is not a fixnum" x)) + (unless (fixnum? y) + (error 'fxlogand "~s is not a fixnum" y)) + ($fxlogand x y))) + +(primitive-set! 'fxsra + (lambda (x y) + (unless (fixnum? x) + (error 'fxsra "~s is not a fixnum" x)) + (unless (fixnum? y) + (error 'fxsra "~s is not a fixnum" y)) + (unless ($fx>= y 0) + (error 'fxsra "negative shift not allowed, got ~s" y)) + ($fxsra x y))) + +(primitive-set! 'fxsll + (lambda (x y) + (unless (fixnum? x) + (error 'fxsll "~s is not a fixnum" x)) + (unless (fixnum? y) + (error 'fxsll "~s is not a fixnum" y)) + (unless ($fx>= y 0) + (error 'fxsll "negative shift not allowed, got ~s" y)) + ($fxsll x y))) + +(primitive-set! 'fx= + (lambda (x y) + (unless (fixnum? x) + (error 'fx= "~s is not a fixnum" x)) + (unless (fixnum? y) + (error 'fx= "~s is not a fixnum" y)) + ($fx= x y))) + +(primitive-set! 'fx< + (lambda (x y) + (unless (fixnum? x) + (error 'fx< "~s is not a fixnum" x)) + (unless (fixnum? y) + (error 'fx< "~s is not a fixnum" y)) + ($fx< x y))) + +(primitive-set! 'fx<= + (lambda (x y) + (unless (fixnum? x) + (error 'fx<= "~s is not a fixnum" x)) + (unless (fixnum? y) + (error 'fx<= "~s is not a fixnum" y)) + ($fx<= x y))) + +(primitive-set! 'fx> + (lambda (x y) + (unless (fixnum? x) + (error 'fx> "~s is not a fixnum" x)) + (unless (fixnum? y) + (error 'fx> "~s is not a fixnum" y)) + ($fx> x y))) + +(primitive-set! 'fx>= + (lambda (x y) + (unless (fixnum? x) + (error 'fx>= "~s is not a fixnum" x)) + (unless (fixnum? y) + (error 'fx>= "~s is not a fixnum" y)) + ($fx>= x y))) + + +(primitive-set! 'char=? + (let () + (define (err x) + (error 'char=? "~s is not a character" x)) + (case-lambda + [(c1 c2) + (if (char? c1) + (if (char? c2) + ($char= c1 c2) + (err c2)) + (err c1))] + [(c1 c2 c3) + (if (char? c1) + (if (char? c2) + (if (char? c3) + (and ($char= c1 c2) + ($char= c2 c3)) + (err c3)) + (err c2)) + (err c1))] + [(c1 . c*) + (if (char? c1) + (let f ([c* c*]) + (or (null? c*) + (let ([c2 ($car c*)]) + (if (char? c2) + (if ($char= c1 c2) + (f ($cdr c*)) + (let g ([c* ($cdr c*)]) + (if (null? c*) + #f + (if (char? ($car c*)) + (g ($cdr c*)) + (err ($car c*)))))) + (err c2))))) + (err c1))]))) + + +(primitive-set! 'char? + (let () + (define (err x) + (error 'char>? "~s is not a character" x)) + (case-lambda + [(c1 c2) + (if (char? c1) + (if (char? c2) + ($char> c1 c2) + (err c2)) + (err c1))] + [(c1 c2 c3) + (if (char? c1) + (if (char? c2) + (if (char? c3) + (and ($char> c1 c2) + ($char> c2 c3)) + (err c3)) + (err c2)) + (err c1))] + [(c1 . c*) + (if (char? c1) + (let f ([c1 c1] [c* c*]) + (or (null? c*) + (let ([c2 ($car c*)]) + (if (char? c2) + (if ($char> c1 c2) + (f c2 ($cdr c*)) + (let g ([c* ($cdr c*)]) + (if (null? c*) + #f + (if (char? ($car c*)) + (g ($cdr c*)) + (err ($car c*)))))) + (err c2))))) + (err c1))]))) + +(primitive-set! 'char>=? + (let () + (define (err x) + (error 'char>=? "~s is not a character" x)) + (case-lambda + [(c1 c2) + (if (char? c1) + (if (char? c2) + ($char>= c1 c2) + (err c2)) + (err c1))] + [(c1 c2 c3) + (if (char? c1) + (if (char? c2) + (if (char? c3) + (and ($char>= c1 c2) + ($char>= c2 c3)) + (err c3)) + (err c2)) + (err c1))] + [(c1 . c*) + (if (char? c1) + (let f ([c1 c1] [c* c*]) + (or (null? c*) + (let ([c2 ($car c*)]) + (if (char? c2) + (if ($char>= c1 c2) + (f c2 ($cdr c*)) + (let g ([c* ($cdr c*)]) + (if (null? c*) + #f + (if (char? ($car c*)) + (g ($cdr c*)) + (err ($car c*)))))) + (err c2))))) + (err c1))]))) + + +(primitive-set! 'cons (lambda (x y) (cons x y))) + +(primitive-set! 'eq? (lambda (x y) (eq? x y))) + +(primitive-set! 'set-car! + (lambda (x y) + (unless (pair? x) + (error 'set-car! "~s is not a pair" x)) + ($set-car! x y))) + +(primitive-set! 'set-cdr! + (lambda (x y) + (unless (pair? x) + (error 'set-cdr! "~s is not a pair" x)) + ($set-cdr! x y))) + +(primitive-set! 'vector-ref + (lambda (v i) + (unless (vector? v) + (error 'vector-ref "~s is not a vector" v)) + (unless (fixnum? i) + (error 'vector-ref "~s is not a valid index" i)) + (unless (and ($fx< i ($vector-length v)) + ($fx<= 0 i)) + (error 'vector-ref "index ~s is out of range for ~s" i v)) + ($vector-ref v i))) + +(primitive-set! 'string-ref + (lambda (s i) + (unless (string? s) + (error 'string-ref "~s is not a string" s)) + (unless (fixnum? i) + (error 'string-ref "~s is not a valid index" i)) + (unless (and ($fx< i ($string-length s)) + ($fx<= 0 i)) + (error 'string-ref "index ~s is out of range for ~s" i s)) + ($string-ref s i))) + +(primitive-set! 'vector-set! + (lambda (v i c) + (unless (vector? v) + (error 'vector-set! "~s is not a vector" v)) + (unless (fixnum? i) + (error 'vector-set! "~s is not a valid index" i)) + (unless (and ($fx< i ($vector-length v)) + ($fx<= 0 i)) + (error 'vector-set! "index ~s is out of range for ~s" i v)) + ($vector-set! v i c))) + + +(primitive-set! 'string-set! + (lambda (s i c) + (unless (string? s) + (error 'string-set! "~s is not a string" s)) + (unless (fixnum? i) + (error 'string-set! "~s is not a valid index" i)) + (unless (and ($fx< i ($string-length s)) + ($fx>= i 0)) + (error 'string-set! "index ~s is out of range for ~s" i s)) + (unless (char? c) + (error 'string-set! "~s is not a character" c)) + ($string-set! s i c))) + +(primitive-set! 'vector + ;;; FIXME: add case-lambda + (letrec ([length + (lambda (ls n) + (cond + [(null? ls) n] + [else (length ($cdr ls) ($fx+ n 1))]))] + [loop + (lambda (v ls i n) + (cond + [($fx= i n) v] + [else + ($vector-set! v i ($car ls)) + (loop v ($cdr ls) ($fx+ i 1) n)]))]) + (lambda ls + (let ([n (length ls 0)]) + (let ([v (make-vector n)]) + (loop v ls 0 n)))))) + +(primitive-set! 'string + ;;; FIXME: add case-lambda + (letrec ([length + (lambda (ls n) + (cond + [(null? ls) n] + [(char? ($car ls)) (length ($cdr ls) ($fx+ n 1))] + [else (error 'string "~s is not a character" ($car ls))]))] + [loop + (lambda (s ls i n) + (cond + [($fx= i n) s] + [else + ($string-set! s i ($car ls)) + (loop s ($cdr ls) ($fx+ i 1) n)]))]) + (lambda ls + (let ([n (length ls 0)]) + (let ([s (make-string n)]) + (loop s ls 0 n)))))) + +(primitive-set! 'list? + (letrec ([race + (lambda (h t) + (if (pair? h) + (let ([h ($cdr h)]) + (if (pair? h) + (and (not (eq? h t)) + (race ($cdr h) ($cdr t))) + (null? h))) + (null? h)))]) + (lambda (x) (race x x)))) + + + +(primitive-set! 'reverse + (letrec ([race + (lambda (h t ls ac) + (if (pair? h) + (let ([h ($cdr h)] [ac (cons ($car h) ac)]) + (if (pair? h) + (if (not (eq? h t)) + (race ($cdr h) ($cdr t) ls (cons ($car h) ac)) + (error 'reverse "~s is a circular list" ls)) + (if (null? h) + ac + (error 'reverse "~s is not a proper list" ls)))) + (if (null? h) + ac + (error 'reverse "~s is not a proper list" ls))))]) + (lambda (x) + (race x x x '())))) + +(primitive-set! 'memq + (letrec ([race + (lambda (h t ls x) + (if (pair? h) + (if (eq? ($car h) x) + h + (let ([h ($cdr h)]) + (if (pair? h) + (if (eq? ($car h) x) + h + (if (not (eq? h t)) + (race ($cdr h) ($cdr t) ls x) + (error 'memq "circular list ~s" ls))) + (if (null? h) + '#f + (error 'memq "~s is not a proper list" ls))))) + (if (null? h) + '#f + (error 'memq "~s is not a proper list" ls))))]) + (lambda (x ls) + (race ls ls ls x)))) + +(primitive-set! 'vector-memq + (lambda (x v) + (if (vector? v) + (let f ([x x] [v v] [n ($vector-length v)] [i 0]) + (and ($fx< i n) + (or (eq? x ($vector-ref v i)) + (f x v n ($fxadd1 i))))) + (error 'vector-memq "~s is not a vector" v)))) + +(primitive-set! 'memv memq) +(primitive-set! 'vector-memv vector-memq) + +(primitive-set! 'list->string + (letrec ([race + (lambda (h t ls n) + (if (pair? h) + (let ([h ($cdr h)]) + (if (pair? h) + (if (not (eq? h t)) + (race ($cdr h) ($cdr t) ls ($fx+ n 2)) + (error 'reverse "circular list ~s" ls)) + (if (null? h) + ($fx+ n 1) + (error 'reverse "~s is not a proper list" ls)))) + (if (null? h) + n + (error 'reverse "~s is not a proper list" ls))))] + [fill + (lambda (s i ls) + (cond + [(null? ls) s] + [else + (let ([c ($car ls)]) + (unless (char? c) + (error 'list->string "~s is not a character" c)) + ($string-set! s i c) + (fill s ($fxadd1 i) (cdr ls)))]))]) + (lambda (ls) + (let ([n (race ls ls ls 0)]) + (let ([s ($make-string n)]) + (fill s 0 ls)))))) + +(primitive-set! 'length + (letrec ([race + (lambda (h t ls n) + (if (pair? h) + (let ([h ($cdr h)]) + (if (pair? h) + (if (not (eq? h t)) + (race ($cdr h) ($cdr t) ls ($fx+ n 2)) + (error 'length "circular list ~s" ls)) + (if (null? h) + ($fx+ n 1) + (error 'length "~s is not a proper list" ls)))) + (if (null? h) + n + (error 'length "~s is not a proper list" ls))))]) + (lambda (ls) + (race ls ls ls 0)))) + + +(primitive-set! 'list-ref + (lambda (list index) + (define f + (lambda (ls i) + (cond + [($fxzero? i) + (if (pair? ls) + ($car ls) + (error 'list-ref "index ~s is out of range for ~s" index list))] + [(pair? ls) + (f ($cdr ls) ($fxsub1 i))] + [(null? ls) + (error 'list-rec "index ~s is out of range for ~s" index list)] + [else (error 'list-ref "~s is not a list" list)]))) + (unless (and (fixnum? index) ($fx>= index 0)) + (error 'list-ref "~s is not a valid index" index)) + (f list index))) + + + +;(primitive-set! 'apply +; (letrec ([fix +; (lambda (arg arg*) +; (cond +; [(null? arg*) +; (if (list? arg) +; arg +; (error 'apply "last arg is not a list"))] +; [else +; (cons arg (fix ($car arg*) ($cdr arg*)))]))]) +; (lambda (f arg . arg*) +; (unless (procedure? f) +; (error 'apply "APPLY ~s ~s ~s" f arg arg*)) +; ($apply f (fix arg arg*))))) +; + +;(primitive-set! 'apply +; (letrec ([fix +; (lambda (arg arg*) +; (cond +; [(null? arg*) +; (if (list? arg) +; arg +; (error 'apply "last arg is not a list"))] +; [else +; (cons arg (fix ($car arg*) ($cdr arg*)))]))]) +; (lambda (f arg . arg*) +; (unless (procedure? f) +; (error 'apply "APPLY ~s ~s ~s" f arg arg*)) +; (let ([args (fix arg arg*)]) +; ($apply f args))))) + +(primitive-set! 'apply + (let () + (define (err f ls) + (if (procedure? f) + (error 'apply "not a list") + (error 'apply "~s is not a procedure" f))) + (define (fixandgo f a0 a1 ls p d) + (cond + [(null? ($cdr d)) + (let ([last ($car d)]) + ($set-cdr! p last) + (if (and (procedure? f) (list? last)) + ($apply f a0 a1 ls) + (err f last)))] + [else (fixandgo f a0 a1 ls d ($cdr d))])) + (define apply + (case-lambda + [(f ls) + (if (and (procedure? f) (list? ls)) + ($apply f ls) + (err f ls))] + [(f a0 ls) + (if (and (procedure? f) (list? ls)) + ($apply f a0 ls) + (err f ls))] + [(f a0 a1 ls) + (if (and (procedure? f) (list? ls)) + ($apply f a0 a1 ls) + (err f ls))] + [(f a0 a1 . ls) + (fixandgo f a0 a1 ls ls ($cdr ls))])) + apply)) + + + + + +(primitive-set! 'assq + (letrec ([race + (lambda (x h t ls) + (if (pair? h) + (let ([a ($car h)] [h ($cdr h)]) + (if (pair? a) + (if (eq? ($car a) x) + a + (if (pair? h) + (if (not (eq? h t)) + (let ([a ($car h)]) + (if (pair? a) + (if (eq? ($car a) x) + a + (race x ($cdr h) ($cdr t) ls)) + (error 'assq "malformed alist ~s" + ls))) + (error 'assq "circular list ~s" ls)) + (if (null? h) + #f + (error 'assq "~s is not a proper list" ls)))) + (error 'assq "malformed alist ~s" ls))) + (if (null? h) + #f + (error 'assq "~s is not a proper list" ls))))]) + (lambda (x ls) + (race x ls ls ls)))) + +(primitive-set! 'string->symbol + (lambda (x) + (unless (string? x) + (error 'string->symbol "~s is not a string" x)) + (foreign-call "ik_intern_string" x))) + +(primitive-set! 'oblist + (lambda () + (foreign-call "ik_oblist"))) + +(primitive-set! 'gensym + (case-lambda + [() ($make-symbol #f)] + [(s) + (if (string? s) + ($make-symbol s) + (error 'gensym "~s is not a string" s))])) + +(primitive-set! 'putprop + (lambda (x k v) + (unless (symbol? x) (error 'putprop "~s is not a symbol" x)) + (unless (symbol? k) (error 'putprop "~s is not a symbol" k)) + (let ([p ($symbol-plist x)]) + (cond + [(assq k p) => (lambda (x) (set-cdr! x v))] + [else + ($set-symbol-plist! x (cons (cons k v) p))])))) + +(primitive-set! 'getprop + (lambda (x k) + (unless (symbol? x) (error 'getprop "~s is not a symbol" x)) + (unless (symbol? k) (error 'getprop "~s is not a symbol" k)) + (let ([p ($symbol-plist x)]) + (cond + [(assq k p) => cdr] + [else #f])))) + +(primitive-set! 'remprop + (lambda (x k) + (unless (symbol? x) (error 'remprop "~s is not a symbol" x)) + (unless (symbol? k) (error 'remprop "~s is not a symbol" k)) + (let ([p ($symbol-plist x)]) + (unless (null? p) + (let ([a ($car p)]) + (cond + [(eq? ($car a) k) ($set-symbol-plist! x ($cdr p))] + [else + (let f ([q p] [p ($cdr p)]) + (unless (null? p) + (let ([a ($car p)]) + (cond + [(eq? ($car a) k) + ($set-cdr! q ($cdr p))] + [else + (f p ($cdr p))]))))])))))) + +(primitive-set! 'property-list + (lambda (x) + (unless (symbol? x) + (error 'property-list "~s is not a symbol" x)) + (letrec ([f + (lambda (ls ac) + (cond + [(null? ls) ac] + [else + (let ([a ($car ls)]) + (f ($cdr ls) + (cons ($car a) (cons ($cdr a) ac))))]))]) + (f ($symbol-plist x) '())))) + + +;;X (primitive-set! 'make-parameter +;;X (letrec ([make-param-no-guard +;;X (lambda (x) +;;X (lambda args +;;X (if (null? args) +;;X x +;;X (if (null? ($cdr args)) +;;X (set! x ($car args)) +;;X (error #f "too many arguments to parameter")))))] +;;X [make-param-with-guard +;;X (lambda (x g) +;;X (let ([f +;;X (lambda args +;;X (if (null? args) +;;X x +;;X (if (null? ($cdr args)) +;;X (set! x (g ($car args))) +;;X (error #f "too many arguments to parameter"))))]) +;;X (if (procedure? g) +;;X (begin (set! x (g x)) f) +;;X (error 'make-parameter "not a procedure ~s" g))))]) +;;X (lambda args +;;X (if (pair? args) +;;X (let ([x ($car args)] [args ($cdr args)]) +;;X (if (null? args) +;;X (make-param-no-guard x) +;;X (let ([g ($car args)]) +;;X (if (null? ($cdr args)) +;;X (make-param-with-guard x g) +;;X (error 'make-parameter "too many arguments"))))) +;;X (error 'make-parameter "insufficient arguments"))))) +;;X + +(primitive-set! 'make-parameter + (case-lambda + [(x) + (case-lambda + [() x] + [(v) (set! x v)])] + [(x guard) + (unless (procedure? guard) + (error 'make-parameter "~s is not a procedure" guard)) + (set! x (guard x)) + (case-lambda + [() x] + [(v) (set! x (guard v))])])) + +(let () + (define vector-loop + (lambda (x y i n) + (or ($fx= i n) + (and (equal? ($vector-ref x i) ($vector-ref y i)) + (vector-loop x y ($fxadd1 i) n))))) + (define string-loop + (lambda (x y i n) + (or ($fx= i n) + (and ($char= ($string-ref x i) ($string-ref y i)) + (string-loop x y ($fxadd1 i) n))))) + (define equal? + (lambda (x y) + (cond + [(eq? x y) #t] + [(pair? x) + (and (pair? y) + (equal? ($car x) ($car y)) + (equal? ($cdr x) ($cdr y)))] + [(vector? x) + (and (vector? y) + (let ([n ($vector-length x)]) + (and ($fx= n ($vector-length y)) + (vector-loop x y 0 n))))] + [(string? x) + (and (string? y) + (let ([n ($string-length x)]) + (and ($fx= n ($string-length y)) + (string-loop x y 0 n))))] + [else #f]))) + (primitive-set! 'equal? equal?)) + + +(let () + (define who 'map) + (define len + (lambda (h t n) + (if (pair? h) + (let ([h ($cdr h)]) + (if (pair? h) + (if (eq? h t) + (error who "circular list") + (len ($cdr h) ($cdr t) ($fx+ n 2))) + (if (null? h) + ($fxadd1 n) + (error who "improper list")))) + (if (null? h) + n + (error who "improper list"))))) + (define map1 + (lambda (f a d n) + (cond + [(pair? d) + (if ($fxzero? n) + (error who "list was altered!") + (cons (f a) + (map1 f ($car d) ($cdr d) ($fxsub1 n))))] + [(null? d) + (if ($fxzero? n) + (cons (f a) '()) + (error who "list was altered"))] + [else (error who "list was altered")]))) + (define map2 + (lambda (f a1 a2 d1 d2 n) + (cond + [(pair? d1) + (cond + [(pair? d2) + (if ($fxzero? n) + (error who "list was altered") + (cons (f a1 a2) + (map2 f + ($car d1) ($car d2) + ($cdr d1) ($cdr d2) + ($fxsub1 n))))] + [else (error who "length mismatch")])] + [(null? d1) + (cond + [(null? d2) + (if ($fxzero? n) + (cons (f a1 a2) '()) + (error who "list was altered"))] + [else (error who "length mismatch")])] + [else (error who "list was altered")]))) + (define cars + (lambda (ls*) + (cond + [(null? ls*) '()] + [else + (let ([a (car ls*)]) + (cond + [(pair? a) + (cons (car a) (cars (cdr ls*)))] + [else + (error 'map "length mismatch")]))]))) + (define cdrs + (lambda (ls*) + (cond + [(null? ls*) '()] + [else + (let ([a (car ls*)]) + (cond + [(pair? a) + (cons (cdr a) (cdrs (cdr ls*)))] + [else + (error 'map "length mismatch")]))]))) + (define mapm + (lambda (f ls ls* n) + (cond + [(null? ls) + (if (andmap null? ls*) + (if (fxzero? n) + '() + (error 'map "lists were mutated during operation")) + (error 'map "length mismatch"))] + [(fxzero? n) + (error 'map "lists were mutated during operation")] + [else + (cons + (apply f (car ls) (cars ls*)) + (mapm f (cdr ls) (cdrs ls*) (fxsub1 n)))]))) + (primitive-set! 'map + (case-lambda + [(f ls) + (unless (procedure? f) + (error who "~s is not a procedure" f)) + (cond + [(pair? ls) + (let ([d ($cdr ls)]) + (map1 f ($car ls) d (len d d 0)))] + [(null? ls) '()] + [else (error who "improper list")])] + [(f ls ls2) + (unless (procedure? f) + (error who "~s is not a procedure" f)) + (cond + [(pair? ls) + (if (pair? ls2) + (let ([d ($cdr ls)]) + (map2 f ($car ls) ($car ls2) d ($cdr ls2) (len d d 0))) + (error who "length mismatch"))] + [(null? ls) + (if (null? ls2) + '() + (error who "length mismatch"))] + [else (error who "not a list")])] + [(f ls . ls*) + (unless (procedure? f) + (error who "~s is not a procedure" f)) + (cond + [(pair? ls) + (let ([n (len ls ls 0)]) + (mapm f ls ls* n))] + [(null? ls) + (if (andmap null? ls*) + '() + (error who "length mismatch"))])]))) + + +(let () + (define who 'for-each) + (define len + (lambda (h t n) + (if (pair? h) + (let ([h ($cdr h)]) + (if (pair? h) + (if (eq? h t) + (error who "circular list") + (len ($cdr h) ($cdr t) ($fx+ n 2))) + (if (null? h) + ($fxadd1 n) + (error who "improper list")))) + (if (null? h) + n + (error who "improper list"))))) + (define for-each1 + (lambda (f a d n) + (cond + [(pair? d) + (if ($fxzero? n) + (error who "list was altered!") + (begin + (f a) + (for-each1 f ($car d) ($cdr d) ($fxsub1 n))))] + [(null? d) + (if ($fxzero? n) + (f a) + (error who "list was altered"))] + [else (error who "list was altered")]))) + (define for-each2 + (lambda (f a1 a2 d1 d2 n) + (cond + [(pair? d1) + (cond + [(pair? d2) + (if ($fxzero? n) + (error who "list was altered") + (begin + (f a1 a2) + (for-each2 f + ($car d1) ($car d2) + ($cdr d1) ($cdr d2) + ($fxsub1 n))))] + [else (error who "length mismatch")])] + [(null? d1) + (cond + [(null? d2) + (if ($fxzero? n) + (f a1 a2) + (error who "list was altered"))] + [else (error who "length mismatch")])] + [else (error who "list was altered")]))) + (primitive-set! 'for-each + (case-lambda + [(f ls) + (unless (procedure? f) + (error who "~s is not a procedure" f)) + (cond + [(pair? ls) + (let ([d ($cdr ls)]) + (for-each1 f ($car ls) d (len d d 0)))] + [(null? ls) (void)] + [else (error who "improper list")])] + [(f ls ls2) + (unless (procedure? f) + (error who "~s is not a procedure" f)) + (cond + [(pair? ls) + (if (pair? ls2) + (let ([d ($cdr ls)]) + (for-each2 f + ($car ls) ($car ls2) d ($cdr ls2) (len d d 0))) + (error who "length mismatch"))] + [(null? ls) + (if (null? ls2) + (void) + (error who "length mismatch"))] + [else (error who "not a list")])] + [_ (error who "vararg not supported yet")]))) + + + +(let () + (define who 'andmap) + (define len + (lambda (h t n) + (if (pair? h) + (let ([h ($cdr h)]) + (if (pair? h) + (if (eq? h t) + (error who "circular list") + (len ($cdr h) ($cdr t) ($fx+ n 2))) + (if (null? h) + ($fxadd1 n) + (error who "improper list")))) + (if (null? h) + n + (error who "improper list"))))) + (define andmap1 + (lambda (f a d n) + (cond + [(pair? d) + (if ($fxzero? n) + (error who "list was altered!") + (and (f a) + (andmap1 f ($car d) ($cdr d) ($fxsub1 n))))] + [(null? d) + (if ($fxzero? n) + (f a) + (error who "list was altered"))] + [else (error who "list was altered")]))) + (primitive-set! 'andmap + (case-lambda + [(f ls) + (unless (procedure? f) + (error who "~s is not a procedure" f)) + (cond + [(pair? ls) + (let ([d ($cdr ls)]) + (andmap1 f ($car ls) d (len d d 0)))] + [(null? ls) #t] + [else (error who "improper list")])] + [_ (error who "vararg not supported yet")]))) + + +(let () + (define who 'ormap) + (define len + (lambda (h t n) + (if (pair? h) + (let ([h ($cdr h)]) + (if (pair? h) + (if (eq? h t) + (error who "circular list") + (len ($cdr h) ($cdr t) ($fx+ n 2))) + (if (null? h) + ($fxadd1 n) + (error who "improper list")))) + (if (null? h) + n + (error who "improper list"))))) + (define ormap1 + (lambda (f a d n) + (cond + [(pair? d) + (if ($fxzero? n) + (error who "list was altered!") + (or (f a) + (ormap1 f ($car d) ($cdr d) ($fxsub1 n))))] + [(null? d) + (if ($fxzero? n) + (f a) + (error who "list was altered"))] + [else (error who "list was altered")]))) + (primitive-set! 'ormap + (case-lambda + [(f ls) + (unless (procedure? f) + (error who "~s is not a procedure" f)) + (cond + [(pair? ls) + (let ([d ($cdr ls)]) + (ormap1 f ($car ls) d (len d d 0)))] + [(null? ls) #f] + [else (error who "improper list")])] + [_ (error who "vararg not supported yet")]))) + + + + +(let () + (define reverse + (lambda (h t ls ac) + (if (pair? h) + (let ([h ($cdr h)] [a1 ($car h)]) + (if (pair? h) + (if (not (eq? h t)) + (let ([a2 ($car h)]) + (reverse ($cdr h) ($cdr t) ls (cons a2 (cons a1 ac)))) + (error 'append "circular list ~s" ls)) + (if (null? h) + (cons a1 ac) + (error 'append "~s is not a proper list" ls)))) + (if (null? h) + ac + (error 'append "~s is not a proper list" ls))))) + (define revcons + (lambda (ls ac) + (cond + [(null? ls) ac] + [else + (revcons ($cdr ls) (cons ($car ls) ac))]))) + (define append + (lambda (ls ls*) + (cond + [(null? ls*) ls] + [else + (revcons (reverse ls ls ls '()) + (append ($car ls*) ($cdr ls*)))]))) + (primitive-set! 'append + (lambda (ls . ls*) + (append ls ls*)))) + + +(primitive-set! 'list->vector + (letrec ([race + (lambda (h t ls n) + (if (pair? h) + (let ([h ($cdr h)]) + (if (pair? h) + (if (not (eq? h t)) + (race ($cdr h) ($cdr t) ls ($fx+ n 2)) + (error 'list->vector "circular list ~s" ls)) + (if (null? h) + ($fx+ n 1) + (error 'list->vector "~s is not a proper list" ls)))) + (if (null? h) + n + (error 'list->vector "~s is not a proper list" ls))))] + [fill + (lambda (v i ls) + (cond + [(null? ls) v] + [else + (let ([c ($car ls)]) + ($vector-set! v i c) + (fill v ($fxadd1 i) (cdr ls)))]))]) + (lambda (ls) + (let ([n (race ls ls ls 0)]) + (let ([v (make-vector n)]) + (fill v 0 ls)))))) + + +(let () + (define f + (lambda (v i ls) + (cond + [($fx< i 0) ls] + [else + (f v ($fxsub1 i) (cons ($vector-ref v i) ls))]))) + (primitive-set! 'vector->list + (lambda (v) + (if (vector? v) + (let ([n ($vector-length v)]) + (if ($fxzero? n) + '() + (f v ($fxsub1 n) '()))) + (error 'vector->list "~s is not a vector" v))))) + +(let () + (define f + (lambda (n fill ls) + (cond + [($fxzero? n) ls] + [else + (f ($fxsub1 n) fill (cons fill ls))]))) + (primitive-set! 'make-list + (case-lambda + [(n) + (if (and (fixnum? n) ($fx>= n 0)) + (f n (void) '()) + (error 'make-list "~s is not a valid length" n))] + [(n fill) + (if (and (fixnum? n) ($fx>= n 0)) + (f n fill '()) + (error 'make-list "~s is not a valid length" n))]))) + +(primitive-set! 'list (lambda x x)) + +(primitive-set! 'uuid + (lambda () + (let ([s (make-string 16)]) + (or (foreign-call "ik_uuid" s) + (error 'uuid "failed!"))))) + +(primitive-set! 'gensym->unique-string + (lambda (x) + (unless (symbol? x) + (error 'gensym->unique-string "~s is not a gensym" x)) + (let ([us ($symbol-unique-string x)]) + (cond + [(string? us) us] + [(eq? us #t) + (error 'gensym->unique-string "~s is not a gensym" x)] + [else + (let ([id (uuid)]) + ($set-symbol-unique-string! x id) + id)])))) + +(primitive-set! 'gensym-prefix + (make-parameter + "g" + (lambda (x) + (unless (string? x) + (error 'gensym-prefix "~s is not a string" x)) + x))) + +(primitive-set! 'gensym-count + (make-parameter + 0 + (lambda (x) + (unless (and (fixnum? x) ($fx>= x 0)) + (error 'gensym-count "~s is not a valid count" x)) + x))) + +(primitive-set! 'print-gensym + (make-parameter + #t + (lambda (x) + (unless (boolean? x) + (error 'print-gensym "~s is not a boolean" x)) + x))) + +;; X (primitive-set! 'make-hash-table +;; X (lambda () +;; X (make-hash-table))) +;; X +;; X (primitive-set! 'hash-table? +;; X (lambda (x) +;; X (hash-table? x))) +;; X +;; X (primitive-set! 'get-hash-table +;; X (lambda (h k v) +;; X (foreign-call "ik_get_hash_table" h k v))) +;; X +;; X (primitive-set! 'put-hash-table! +;; X (lambda (h k v) +;; X (foreign-call "ik_put_hash_table" h k v))) + +(primitive-set! 'bwp-object? + (lambda (x) + (bwp-object? x))) + +(primitive-set! 'weak-cons + (lambda (a d) + (foreign-call "ikrt_weak_cons" a d))) + +(primitive-set! 'weak-pair? + (lambda (x) + (and (pair? x) + (foreign-call "ikrt_is_weak_pair" x)))) + +(primitive-set! 'pointer-value + (lambda (x) + (pointer-value x))) + +(primitive-set! 'date-string + (lambda () + (let ([s (make-string 10)]) + (foreign-call "ikrt_strftime" s "%F") + s))) + +(primitive-set! 'features + (lambda () + (append (macros) (public-primitives) '()))) + +(primitive-set! 'list* + (lambda (fst . rest) + (let f ([fst fst] [rest rest]) + (cond + [(null? rest) fst] + [else + (cons fst (f ($car rest) ($cdr rest)))])))) + diff --git a/src/libcore.fasl b/src/libcore.fasl index b76f633..13bff9c 100644 Binary files a/src/libcore.fasl and b/src/libcore.fasl differ diff --git a/src/libcxr.fasl b/src/libcxr.fasl index d086bce..0405654 100644 Binary files a/src/libcxr.fasl and b/src/libcxr.fasl differ diff --git a/src/libexpand.fasl b/src/libexpand.fasl deleted file mode 100644 index dac116e..0000000 Binary files a/src/libexpand.fasl and /dev/null differ diff --git a/src/libfasl-6.0.ss b/src/libfasl-6.0.ss index 6e61fc5..3ed6c7d 100644 --- a/src/libfasl-6.0.ss +++ b/src/libfasl-6.0.ss @@ -1,4 +1,3 @@ -;;; not finished yet ;;; FASL ;;; @@ -20,7 +19,10 @@ ;;; "V" + 4-bytes(n) + object ... : a vector of length n followed by n ;;; objects ;;; "S" + 4-bytes(n) + char ... : a string -;;; "M" + object + object : a symbol with name field and a unique-name field +;;; "M" + symbol-name : a symbol +;;; "G" + pretty-name + unique-name : a gensym +;;; "R" + rtd-name + rtd-symbol + field-count + field-names +;;; "{" + field-count + rtd + fields ;;; ">" + 4-bytes(i) : mark the next object with index i ;;; "<" + 4-bytes(i) : dereference the object marked with index i ;;; @@ -41,7 +43,6 @@ (write-char (integer->char (fxlogand (fxsra x 8) #xFF)) p) (write-char (integer->char (fxlogand (fxsra x 16) #xFF)) p) (write-char (integer->char (fxlogand (fxsra x 24) #xFF)) p))) - (define fasl-write-immediate (lambda (x p) @@ -86,11 +87,11 @@ (f x (fxadd1 i) n)]))] [(gensym? x) (write-char #\G p) - (do-write (gensym->unique-name x) p h - (do-write (symbol->string x) p h m))] + (fasl-write (gensym->unique-string x) p h + (fasl-write (symbol->string x) p h m))] [(symbol? x) (write-char #\M p) - (do-write (symbol->string x) p h m)] + (fasl-write (symbol->string x) p h m)] [(code? x) (write-char #\X p) (let ([code-vec (code-code-vec x)] @@ -132,6 +133,36 @@ (let ([m (fasl-write object p h m)]) (f (fx+ i 2) n m)))] [else (error 'fasl-write "invalid reloc byte ~s" b)])))))] + [(record? x) + (let ([rtd (record-type-descriptor x)]) + (cond + [(eq? rtd #%$base-rtd) + ;;; rtd record + (write-char #\R p) + (let ([names (record-type-field-names x)] + [m + (fasl-write (record-type-symbol x) p h + (fasl-write (record-type-name x) p h m))]) + (write-int (length names) p) + (let f ([names names] [m m]) + (cond + [(null? names) m] + [else + (f (cdr names) + (fasl-write (car names) p h m))])))] + [else + ;;; non-rtd record + (write-char #\{ p) + (write-int (length (record-type-field-names rtd)) p) + (let f ([names (record-type-field-names rtd)] + [m (fasl-write rtd p h m)]) + (cond + [(null? names) m] + [else + (f (cdr names) + (fasl-write + ((record-field-accessor rtd (car names)) x) + p h m))]))]))] [else (error 'fasl-write "~s is not fasl-writable" x)]))) (define fasl-write (lambda (x p h m) @@ -153,7 +184,7 @@ (write-char #\< p) (write-int (fx- 0 mark) p) m]))] - [else (error 'fasl-write "BUG: not in hash table")]))) + [else (error 'fasl-write "BUG: not in hash table ~s" x)]))) (define make-graph (lambda (x h) (unless (immediate? x) @@ -172,7 +203,9 @@ (unless (fx= i n) (make-graph (vector-ref x i) h) (f x (fxadd1 i) n)))] - [(symbol? x) (void)] + [(symbol? x) + (make-graph (symbol->string x) h) + (when (gensym? x) (make-graph (gensym->unique-string x) h))] [(string? x) (void)] [(code? x) (let ([x (code-reloc-vec x)]) @@ -188,6 +221,24 @@ (f (fx+ i 2) n)] [else (error 'fasl-write "unrecognized reloc ~s" b)] )))))] + [(record? x) + (when (eq? x #%$base-rtd) + (error 'fasl-write "$base-rtd is not writable")) + (let ([rtd (record-type-descriptor x)]) + (cond + [(eq? rtd #%$base-rtd) + ;;; this is an rtd + (make-graph (record-type-name x) h) + (make-graph (record-type-symbol x) h) + (for-each (lambda (x) (make-graph x h)) + (record-type-field-names x))] + [else + ;;; this is a record + (make-graph rtd h) + (for-each + (lambda (name) + (make-graph ((record-field-accessor rtd name) x) h)) + (record-type-field-names rtd))]))] [else (error 'fasl-write "~s is not fasl-writable" x)])])))) (define do-fasl-write (lambda (x port) diff --git a/src/libfasl-6.6.ss b/src/libfasl-6.6.ss new file mode 100644 index 0000000..2cab6ef --- /dev/null +++ b/src/libfasl-6.6.ss @@ -0,0 +1,217 @@ + +;;; FASL +;;; +;;; A fasl object is a header followed by one or more objects followed by an +;;; end-of-fasl marker +;;; +;;; The header is the string "#@IK01" +;;; The end of fasl marker is "@" +;;; +;;; An object is either: +;;; "N" : denoting the empty list +;;; "T" : denoting #t +;;; "F" : denoting #f +;;; "E" : denoting the end of file object +;;; "U" : denoting the unspecified value +;;; "I" + 4-bytes : denoting a fixnum (in host byte order) +;;; "C" + 1-byte : denoting a character +;;; "P" + object1 + object2 : a pair +;;; "V" + 4-bytes(n) + object ... : a vector of length n followed by n +;;; objects +;;; "S" + 4-bytes(n) + char ... : a string +;;; "M" + symbol-name : a symbol +;;; "G" + pretty-name + unique-name : a gensym +;;; "R" + rtd-name + rtd-symbol + field-count + field-names +;;; "{" + field-count + rtd + fields +;;; ">" + 4-bytes(i) : mark the next object with index i +;;; "<" + 4-bytes(i) : dereference the object marked with index i +;;; + + +(let () + (define write-fixnum + (lambda (x p) + (unless (fixnum? x) (error 'write-fixnum "not a fixnum ~s" x)) + (write-char (integer->char (fxsll (fxlogand x #x3F) 2)) p) + (write-char (integer->char (fxlogand (fxsra x 6) #xFF)) p) + (write-char (integer->char (fxlogand (fxsra x 14) #xFF)) p) + (write-char (integer->char (fxlogand (fxsra x 22) #xFF)) p))) + (define write-int + (lambda (x p) + (unless (fixnum? x) (error 'write-int "not a fixnum ~s" x)) + (write-char (integer->char (fxlogand x #xFF)) p) + (write-char (integer->char (fxlogand (fxsra x 8) #xFF)) p) + (write-char (integer->char (fxlogand (fxsra x 16) #xFF)) p) + (write-char (integer->char (fxlogand (fxsra x 24) #xFF)) p))) + + (define fasl-write-immediate + (lambda (x p) + (cond + [(null? x) (write-char #\N p)] + [(fixnum? x) + (write-char #\I p) + (write-fixnum x p)] + [(char? x) + (write-char #\C p) + (write-char x p)] + [(boolean? x) + (write-char (if x #\T #\F) p)] + [(eof-object? x) (write-char #\E p)] + [(eq? x (void)) (write-char #\U p)] + [else (error 'fasl-write "~s is not a fasl-writable immediate" x)]))) + + (define do-write + (lambda (x p h m) + (cond + [(pair? x) + (write-char #\P p) + (fasl-write (cdr x) p h + (fasl-write (car x) p h m))] + [(vector? x) + (write-char #\V p) + (write-int (vector-length x) p) + (let f ([x x] [i 0] [n (vector-length x)] [m m]) + (cond + [(fx= i n) m] + [else + (f x (fxadd1 i) n + (fasl-write (vector-ref x i) p h m))]))] + [(string? x) + (write-char #\S p) + (write-int (string-length x) p) + (let f ([x x] [i 0] [n (string-length x)]) + (cond + [(fx= i n) m] + [else + (write-char (string-ref x i) p) + (f x (fxadd1 i) n)]))] + [(gensym? x) + (write-char #\G p) + (fasl-write (gensym->unique-string x) p h + (fasl-write (symbol->string x) p h m))] + [(symbol? x) + (write-char #\M p) + (fasl-write (symbol->string x) p h m)] + [(code? x) + (write-char #\x p) + (write-int (code-size x) p) + (write-int (code-closure-size x) p) + (let f ([i 0] [n (code-size x)]) + (unless (fx= i n) + (write-char (integer->char (code-ref x i)) p) + (f (fxadd1 i) n))) + (fasl-write (code-reloc-vector x) p h m)] + [(record? x) + (let ([rtd (record-type-descriptor x)]) + (cond + [(eq? rtd #%$base-rtd) + ;;; rtd record + (write-char #\R p) + (let ([names (record-type-field-names x)] + [m + (fasl-write (record-type-symbol x) p h + (fasl-write (record-type-name x) p h m))]) + (write-int (length names) p) + (let f ([names names] [m m]) + (cond + [(null? names) m] + [else + (f (cdr names) + (fasl-write (car names) p h m))])))] + [else + ;;; non-rtd record + (write-char #\{ p) + (write-int (length (record-type-field-names rtd)) p) + (let f ([names (record-type-field-names rtd)] + [m (fasl-write rtd p h m)]) + (cond + [(null? names) m] + [else + (f (cdr names) + (fasl-write + ((record-field-accessor rtd (car names)) x) + p h m))]))]))] + [else (error 'fasl-write "~s is not fasl-writable" x)]))) + (define fasl-write + (lambda (x p h m) + (cond + [(immediate? x) (fasl-write-immediate x p) m] + [(get-hash-table h x #f) => + (lambda (mark) + (unless (fixnum? mark) + (error 'fasl-write "BUG: invalid mark ~s" mark)) + (cond + [(fx= mark 0) ; singly referenced + (do-write x p h m)] + [(fx> mark 0) ; marked but not written + (put-hash-table! h x (fx- 0 m)) + (write-char #\> p) + (write-int m p) + (do-write x p h (fxadd1 m))] + [else + (write-char #\< p) + (write-int (fx- 0 mark) p) + m]))] + [else (error 'fasl-write "BUG: not in hash table ~s" x)]))) + (define make-graph + (lambda (x h) + (unless (immediate? x) + (cond + [(get-hash-table h x #f) => + (lambda (i) + (put-hash-table! h x (fxadd1 i)))] + [else + (put-hash-table! h x 0) + (cond + [(pair? x) + (make-graph (car x) h) + (make-graph (cdr x) h)] + [(vector? x) + (let f ([x x] [i 0] [n (vector-length x)]) + (unless (fx= i n) + (make-graph (vector-ref x i) h) + (f x (fxadd1 i) n)))] + [(symbol? x) + (make-graph (symbol->string x) h) + (when (gensym? x) (make-graph (gensym->unique-string x) h))] + [(string? x) (void)] + [(code? x) + (make-graph (code-reloc-vector x) h)] + [(record? x) + (when (eq? x #%$base-rtd) + (error 'fasl-write "$base-rtd is not writable")) + (let ([rtd (record-type-descriptor x)]) + (cond + [(eq? rtd #%$base-rtd) + ;;; this is an rtd + (make-graph (record-type-name x) h) + (make-graph (record-type-symbol x) h) + (for-each (lambda (x) (make-graph x h)) + (record-type-field-names x))] + [else + ;;; this is a record + (make-graph rtd h) + (for-each + (lambda (name) + (make-graph ((record-field-accessor rtd name) x) h)) + (record-type-field-names rtd))]))] + [else (error 'fasl-write "~s is not fasl-writable" x)])])))) + (define do-fasl-write + (lambda (x port) + (let ([h (make-hash-table)]) + (make-graph x h) + (write-char #\# port) + (write-char #\@ port) + (write-char #\I port) + (write-char #\K port) + (write-char #\0 port) + (write-char #\1 port) + (fasl-write x port h 1)))) + (primitive-set! 'fasl-write + (case-lambda + [(x) (do-fasl-write x (current-output-port))] + [(x port) + (unless (output-port? port) + (error 'fasl-write "~s is not an output port" port)) + (do-fasl-write x port)]))) + diff --git a/src/libfasl-6.7.ss b/src/libfasl-6.7.ss new file mode 100644 index 0000000..6f1fe90 --- /dev/null +++ b/src/libfasl-6.7.ss @@ -0,0 +1,217 @@ + +;;; FASL +;;; +;;; A fasl object is a header followed by one or more objects followed by an +;;; end-of-fasl marker +;;; +;;; The header is the string "#@IK01" +;;; The end of fasl marker is "@" +;;; +;;; An object is either: +;;; "N" : denoting the empty list +;;; "T" : denoting #t +;;; "F" : denoting #f +;;; "E" : denoting the end of file object +;;; "U" : denoting the unspecified value +;;; "I" + 4-bytes : denoting a fixnum (in host byte order) +;;; "C" + 1-byte : denoting a character +;;; "P" + object1 + object2 : a pair +;;; "V" + 4-bytes(n) + object ... : a vector of length n followed by n +;;; objects +;;; "S" + 4-bytes(n) + char ... : a string +;;; "M" + symbol-name : a symbol +;;; "G" + pretty-name + unique-name : a gensym +;;; "R" + rtd-name + rtd-symbol + field-count + field-names +;;; "{" + field-count + rtd + fields +;;; ">" + 4-bytes(i) : mark the next object with index i +;;; "<" + 4-bytes(i) : dereference the object marked with index i +;;; + + +(let () + (define write-fixnum + (lambda (x p) + (unless (fixnum? x) (error 'write-fixnum "not a fixnum ~s" x)) + (write-char (integer->char (fxsll (fxlogand x #x3F) 2)) p) + (write-char (integer->char (fxlogand (fxsra x 6) #xFF)) p) + (write-char (integer->char (fxlogand (fxsra x 14) #xFF)) p) + (write-char (integer->char (fxlogand (fxsra x 22) #xFF)) p))) + (define write-int + (lambda (x p) + (unless (fixnum? x) (error 'write-int "not a fixnum ~s" x)) + (write-char (integer->char (fxlogand x #xFF)) p) + (write-char (integer->char (fxlogand (fxsra x 8) #xFF)) p) + (write-char (integer->char (fxlogand (fxsra x 16) #xFF)) p) + (write-char (integer->char (fxlogand (fxsra x 24) #xFF)) p))) + + (define fasl-write-immediate + (lambda (x p) + (cond + [(null? x) (write-char #\N p)] + [(fixnum? x) + (write-char #\I p) + (write-fixnum x p)] + [(char? x) + (write-char #\C p) + (write-char x p)] + [(boolean? x) + (write-char (if x #\T #\F) p)] + [(eof-object? x) (write-char #\E p)] + [(eq? x (void)) (write-char #\U p)] + [else (error 'fasl-write "~s is not a fasl-writable immediate" x)]))) + + (define do-write + (lambda (x p h m) + (cond + [(pair? x) + (write-char #\P p) + (fasl-write (cdr x) p h + (fasl-write (car x) p h m))] + [(vector? x) + (write-char #\V p) + (write-int (vector-length x) p) + (let f ([x x] [i 0] [n (vector-length x)] [m m]) + (cond + [(fx= i n) m] + [else + (f x (fxadd1 i) n + (fasl-write (vector-ref x i) p h m))]))] + [(string? x) + (write-char #\S p) + (write-int (string-length x) p) + (let f ([x x] [i 0] [n (string-length x)]) + (cond + [(fx= i n) m] + [else + (write-char (string-ref x i) p) + (f x (fxadd1 i) n)]))] + [(gensym? x) + (write-char #\G p) + (fasl-write (gensym->unique-string x) p h + (fasl-write (symbol->string x) p h m))] + [(symbol? x) + (write-char #\M p) + (fasl-write (symbol->string x) p h m)] + [(code? x) + (write-char #\x p) + (write-int (code-size x) p) + (write-fixnum (code-freevars x) p) + (let f ([i 0] [n (code-size x)]) + (unless (fx= i n) + (write-char (integer->char (code-ref x i)) p) + (f (fxadd1 i) n))) + (fasl-write (code-reloc-vector x) p h m)] + [(record? x) + (let ([rtd (record-type-descriptor x)]) + (cond + [(eq? rtd #%$base-rtd) + ;;; rtd record + (write-char #\R p) + (let ([names (record-type-field-names x)] + [m + (fasl-write (record-type-symbol x) p h + (fasl-write (record-type-name x) p h m))]) + (write-int (length names) p) + (let f ([names names] [m m]) + (cond + [(null? names) m] + [else + (f (cdr names) + (fasl-write (car names) p h m))])))] + [else + ;;; non-rtd record + (write-char #\{ p) + (write-int (length (record-type-field-names rtd)) p) + (let f ([names (record-type-field-names rtd)] + [m (fasl-write rtd p h m)]) + (cond + [(null? names) m] + [else + (f (cdr names) + (fasl-write + ((record-field-accessor rtd (car names)) x) + p h m))]))]))] + [else (error 'fasl-write "~s is not fasl-writable" x)]))) + (define fasl-write + (lambda (x p h m) + (cond + [(immediate? x) (fasl-write-immediate x p) m] + [(get-hash-table h x #f) => + (lambda (mark) + (unless (fixnum? mark) + (error 'fasl-write "BUG: invalid mark ~s" mark)) + (cond + [(fx= mark 0) ; singly referenced + (do-write x p h m)] + [(fx> mark 0) ; marked but not written + (put-hash-table! h x (fx- 0 m)) + (write-char #\> p) + (write-int m p) + (do-write x p h (fxadd1 m))] + [else + (write-char #\< p) + (write-int (fx- 0 mark) p) + m]))] + [else (error 'fasl-write "BUG: not in hash table ~s" x)]))) + (define make-graph + (lambda (x h) + (unless (immediate? x) + (cond + [(get-hash-table h x #f) => + (lambda (i) + (put-hash-table! h x (fxadd1 i)))] + [else + (put-hash-table! h x 0) + (cond + [(pair? x) + (make-graph (car x) h) + (make-graph (cdr x) h)] + [(vector? x) + (let f ([x x] [i 0] [n (vector-length x)]) + (unless (fx= i n) + (make-graph (vector-ref x i) h) + (f x (fxadd1 i) n)))] + [(symbol? x) + (make-graph (symbol->string x) h) + (when (gensym? x) (make-graph (gensym->unique-string x) h))] + [(string? x) (void)] + [(code? x) + (make-graph (code-reloc-vector x) h)] + [(record? x) + (when (eq? x #%$base-rtd) + (error 'fasl-write "$base-rtd is not writable")) + (let ([rtd (record-type-descriptor x)]) + (cond + [(eq? rtd #%$base-rtd) + ;;; this is an rtd + (make-graph (record-type-name x) h) + (make-graph (record-type-symbol x) h) + (for-each (lambda (x) (make-graph x h)) + (record-type-field-names x))] + [else + ;;; this is a record + (make-graph rtd h) + (for-each + (lambda (name) + (make-graph ((record-field-accessor rtd name) x) h)) + (record-type-field-names rtd))]))] + [else (error 'fasl-write "~s is not fasl-writable" x)])])))) + (define do-fasl-write + (lambda (x port) + (let ([h (make-hash-table)]) + (make-graph x h) + (write-char #\# port) + (write-char #\@ port) + (write-char #\I port) + (write-char #\K port) + (write-char #\0 port) + (write-char #\1 port) + (fasl-write x port h 1)))) + (primitive-set! 'fasl-write + (case-lambda + [(x) (do-fasl-write x (current-output-port))] + [(x port) + (unless (output-port? port) + (error 'fasl-write "~s is not an output port" port)) + (do-fasl-write x port)]))) + diff --git a/src/libhandlers-6.9.ss b/src/libhandlers-6.9.ss new file mode 100644 index 0000000..1af9a2c --- /dev/null +++ b/src/libhandlers-6.9.ss @@ -0,0 +1,45 @@ + +(primitive-set! 'error + (lambda args + (foreign-call "ik_error" args))) + +(primitive-set! '$apply-nonprocedure-error-handler + (lambda (x) + (error 'apply "~s is not a procedure" x))) + +(primitive-set! '$incorrect-args-error-handler + (lambda (p n) + (error 'apply "incorrect number of argument (~s) to ~s" n p))) + +(primitive-set! '$multiple-values-error + (lambda args + (error 'apply + "incorrect number of values ~s returned to single value context" + args))) + +(primitive-set! '$debug + (lambda (x) + (foreign-call "ik_error" (cons "DEBUG" x)))) + +(primitive-set! '$underflow-misaligned-error + (lambda () + (foreign-call "ik_error" "misaligned"))) + +(primitive-set! 'top-level-value-error + (lambda (x) + (cond + [(symbol? x) + (if (top-level-bound? x) + (error 'top-level-value "BUG in ~s" x) + (error 'top-level-value "~s is unbound" x))] + [else + (error 'top-level-value "~s is not a symbol" x)]))) + +(primitive-set! 'car-error + (lambda (x) + (error 'car "~s is not a pair" x))) + +(primitive-set! 'cdr-error + (lambda (x) + (error 'cdr "~s is not a pair" x))) + diff --git a/src/libhandlers.fasl b/src/libhandlers.fasl index 972862e..768f16c 100644 Binary files a/src/libhandlers.fasl and b/src/libhandlers.fasl differ diff --git a/src/libhash-6.2.ss b/src/libhash-6.2.ss index 09861b8..282203f 100644 --- a/src/libhash-6.2.ss +++ b/src/libhash-6.2.ss @@ -91,6 +91,8 @@ ($vector-set! vec idx next)] [else (replace! fst b next)]))) + ;;; reset the tcbucket-tconc FIRST + ($set-tcbucket-tconc! b (get-tc h)) ;;; then add it to the new place (let ([k ($tcbucket-key b)]) (let ([ih (inthash (pointer-value k))]) @@ -98,7 +100,6 @@ (let ([n ($vector-ref vec idx)]) ($set-tcbucket-next! b n) ($vector-set! vec idx b) - ($set-tcbucket-tconc! b (get-tc h)) (void)))))))) (define get-hash @@ -129,9 +130,15 @@ ($set-tcbucket-val! b v) (void))] [else - ($vector-set! vec idx - ($make-tcbucket (get-tc h) x v - ($vector-ref vec idx))) + (let ([bucket + ($make-tcbucket (get-tc h) x v ($vector-ref vec idx))]) + (if ($fx= (pointer-value x) pv) + ($vector-set! vec idx bucket) + (let* ([ih (inthash (pointer-value x))] + [idx + ($fxlogand ih ($fx- ($vector-length vec) 1))]) + ($set-tcbucket-next! bucket ($vector-ref vec idx)) + ($vector-set! vec idx bucket)))) (let ([ct (get-count h)]) (set-count! h ($fxadd1 ct)) (when ($fx> ct ($vector-length vec)) diff --git a/src/libintelasm-6.0.ss b/src/libintelasm-6.0.ss index e86a3c9..38900da 100644 --- a/src/libintelasm-6.0.ss +++ b/src/libintelasm-6.0.ss @@ -375,13 +375,13 @@ ac)]))) -#;(define CODErd - (lambda (c r1 disp ac) - (with-args disp - (lambda (i/r r2) - (if (reg? i/r) - (CODE c (RegReg r1 i/r r2 ac)) - (CODErri c r1 r2 i/r ac)))))) +;;(define CODErd +;; (lambda (c r1 disp ac) +;; (with-args disp +;; (lambda (i/r r2) +;; (if (reg? i/r) +;; (CODE c (RegReg r1 i/r r2 ac)) +;; (CODErri c r1 r2 i/r ac)))))) (define IMM32*2 diff --git a/src/libintelasm-6.4.ss b/src/libintelasm-6.4.ss new file mode 100644 index 0000000..e1094b5 --- /dev/null +++ b/src/libintelasm-6.4.ss @@ -0,0 +1,920 @@ + +;;; +;;; assuming the existence of a code manager, this file defines an assember +;;; that takes lists of assembly code and produces a list of code objects +;;; + + ;;; add + ;;; and + ;;; cmp + ;;; call + ;;; cltd + ;;; idiv + ;;; imull + ;;; ja + ;;; jae + ;;; jb + ;;; jbe + ;;; je + ;;; jg + ;;; jge + ;;; jl + ;;; jle + ;;; jne + ;;; jmp + ;;; movb + ;;; movl + ;;; negl + ;;; notl + ;;; orl + ;;; popl + ;;; pushl + ;;; ret + ;;; sall + ;;; sarl + ;;; shrl + ;;; sete + ;;; setg + + +(let () + +(define fold + (lambda (f init ls) + (cond + [(null? ls) init] + [else + (f (car ls) (fold f init (cdr ls)))]))) + +(define convert-instructions + (lambda (ls) + (fold convert-instruction '() ls))) + +(define register-mapping + '([%eax 32 0] + [%ecx 32 1] + [%edx 32 2] + [%ebx 32 3] + [%esp 32 4] + [%ebp 32 5] + [%esi 32 6] + [%edi 32 7] + [%al 8 0] + [%cl 8 1] + [%dl 8 2] + [%bl 8 3] + [%ah 8 4] + [%ch 8 5] + [%dh 8 6] + [%bh 8 7] + [/0 0 0] + [/1 0 1] + [/2 0 2] + [/3 0 3] + [/4 0 4] + [/5 0 5] + [/6 0 6] + [/7 0 7] + )) + +(define register-index + (lambda (x) + (cond + [(assq x register-mapping) => caddr] + [else (error 'register-index "not a register ~s" x)]))) + +(define reg32? + (lambda (x) + (cond + [(assq x register-mapping) => + (lambda (x) (fx= (cadr x) 32))] + [else #f]))) + +(define reg8? + (lambda (x) + (cond + [(assq x register-mapping) => + (lambda (x) (fx= (cadr x) 8))] + [else #f]))) + +(define reg? + (lambda (x) + (assq x register-mapping))) + +(define check-len + (lambda (x) + (define instr-len + '([ret] + [movl s d] + [movb s d] + [addl s d] + [subl s d] + [sall s d] + [sarl s d] + [shrl s d] + [andl s d] + [xorl s d] + [orl s d] + [cmpl s d] + [imull s d] + [notl d] + [negl d] + [idivl d] + [pushl d] + [popl d] + [jmp d] + [call d] + [ja d] + [jae d] + [jb d] + [jbe d] + [je d] + [jg d] + [jge d] + [jl d] + [jle d] + [jna d] + [jnae d] + [jnb d] + [jnbe d] + [jne d] + [jng d] + [jnge d] + [jnl d] + [jnle d] + [seta d] + [setae d] + [setb d] + [setbe d] + [sete d] + [setg d] + [setge d] + [setl d] + [setle d] + [setna d] + [setnae d] + [setnb d] + [setnbe d] + [setne d] + [setng d] + [setnge d] + [setnl d] + [setnle d] + [cltd] + [nop] + [byte x] + [byte-vector x] + [int x] + [label x] + [label-address x] + [current-frame-offset] + )) + (cond + [(assq (car x) instr-len) => + (lambda (p) + (unless (fx= (length x) (length p)) + (error 'assembler "invalid instruction format ~s" x)))] + [else (error 'assembler "unknown instruction ~s" x)]))) + +(define with-args + (lambda (ls f) + (apply f (cdr ls)))) + +(define byte + (lambda (x) + (cons 'byte (fxlogand x 255)))) + + +(define word + (lambda (x) + (cons 'word x))) + +(define reloc-word + (lambda (x) + (cons 'reloc-word x))) + +(define reloc-word+ + (lambda (x d) + (list* 'reloc-word+ x d))) + +(define list*-aux + (lambda (ls ls*) + (cond + [(null? ls*) ls] + [else (cons ls (list*-aux (car ls*) (cdr ls*)))]))) + +(define list* + (lambda (ls . ls*) + (list*-aux ls ls*))) + +(define byte? + (lambda (x) + (and (fixnum? x) + (fx<= x 127) + (fx<= -128 x)))) + +(define mem? + (lambda (x) + (and (list? x) + (fx= (length x) 3) + (eq? (car x) 'disp) + (or (imm? (cadr x)) + (reg? (cadr x))) + (or (imm? (caddr x)) + (reg? (caddr x)))))) + +(define small-disp? + (lambda (x) + (and (mem? x) + (byte? (cadr x))))) + + +(define CODE + (lambda (n ac) + (cons (byte n) ac))) + +(define CODE+r + (lambda (n r ac) + (cons (byte (fxlogor n (register-index r))) ac))) + +(define ModRM + (lambda (mod reg r/m ac) + (cons (byte (fxlogor + (register-index r/m) + (fxlogor + (fxsll (register-index reg) 3) + (fxsll mod 6)))) + (if (and (not (fx= mod 3)) (eq? r/m '%esp)) + (cons (byte #x24) ac) + ac)))) + +(define IMM32 + (lambda (n ac) + (cond + [(int? n) + (let ([n (cadr n)]) + (list* (byte n) + (byte (fxsra n 8)) + (byte (fxsra n 16)) + (byte (fxsra n 24)) + ac))] + [(obj? n) + (let ([v (cadr n)]) + (if (immediate? v) + (cons (word v) ac) + (cons (reloc-word v) ac)))] + [(obj+? n) + (let ([v (cadr n)] [d (caddr n)]) + (cons (reloc-word+ v d) ac))] + [(label-address? n) + (cons (cons 'label-addr (label-name n)) ac)] + [(foreign? n) + (cons (cons 'foreign-label (label-name n)) ac)] + [else (error 'IMM32 "invalid ~s" n)]))) + + +(define IMM8 + (lambda (n ac) + (cond + [(int? n) + (let ([n (cadr n)]) + (list* (byte n) ac))] + [else (error 'IMM8 "invalid ~s" n)]))) + + +(define imm? + (lambda (x) + (or (int? x) + (obj? x) + (obj+? x) + (label-address? x) + (foreign? x)))) + +(define foreign? + (lambda (x) + (and (pair? x) (eq? (car x) 'foreign-label)))) + + +(define imm8? + (lambda (x) + (and (int? x) (byte? (cadr x))))) + +(define label? + (lambda (x) + (cond + [(and (pair? x) (eq? (car x) 'label)) + (let ([d (cdr x)]) + (unless (and (null? (cdr d)) + (symbol? (car d))) + (error 'assemble "invalid label ~s" x))) + #t] + [else #f]))) + +(define label-address? + (lambda (x) + (cond + [(and (pair? x) (eq? (car x) 'label-address)) + (let ([d (cdr x)]) + (unless (and (null? (cdr d)) + (or (symbol? (car d)) + (string? (car d)))) + (error 'assemble "invalid label-address ~s" x))) + #t] + [else #f]))) + +(define label-name + (lambda (x) (cadr x))) + +(define int? + (lambda (x) + (and (pair? x) (eq? (car x) 'int)))) + +(define obj? + (lambda (x) + (and (pair? x) (eq? (car x) 'obj)))) + +(define obj+? + (lambda (x) + (and (pair? x) (eq? (car x) 'obj+)))) + +(define CODErri + (lambda (c d s i ac) + (cond + [(imm8? i) + (CODE c (ModRM 1 d s (IMM8 i ac)))] + [(reg? i) + (CODE c (ModRM i d s ac))] + [else + (CODE c (ModRM 2 d s (IMM32 i ac)))]))) + +(define CODErr + (lambda (c d s ac) + (CODE c (ModRM 3 d s ac)))) + +(define CODEri + (lambda (c d i ac) + (CODE+r c d (IMM32 i ac)))) + + +(define RegReg + (lambda (r1 r2 r3 ac) + (cond + [(eq? r3 '%esp) (error 'assembler "BUG: invalid src %esp")] + [(eq? r1 '%ebp) (error 'assembler "BUG: invalid src %ebp")] + [else +;;; (parameterize ([print-radix 16]) +;;; (printf "REGREG ~s ~s ~s\n" r1 r2 r3) +;;; (printf "REGREG ~s ~s\n" +;;; (byte (fxlogor 4 (fxsll (register-index r1) 3))) +;;; (byte (fxlogor (register-index r2) +;;; (fxsll (register-index r3) 3))))) + (list* + (byte (fxlogor 4 (fxsll (register-index r1) 3))) + (byte (fxlogor (register-index r2) + (fxsll (register-index r3) 3))) + ac)]))) + + +;;(define CODErd +;; (lambda (c r1 disp ac) +;; (with-args disp +;; (lambda (i/r r2) +;; (if (reg? i/r) +;; (CODE c (RegReg r1 i/r r2 ac)) +;; (CODErri c r1 r2 i/r ac)))))) + + +(define IMM32*2 + (lambda (i1 i2 ac) + (cond + [(and (int? i1) (obj? i2)) + (let ([d (cadr i1)] [v (cadr i2)]) + (cons (reloc-word+ v d) ac))] + [else (error 'assemble "IMM32*2 ~s ~s" i1 i2)]))) + + +(define CODErd + (lambda (c r1 disp ac) + (with-args disp + (lambda (a1 a2) + (cond + [(and (reg? a1) (reg? a2)) + (CODE c (RegReg r1 a1 a2 ac))] + [(and (imm? a1) (reg? a2)) + (CODErri c r1 a2 a1 ac)] + [(and (imm? a1) (imm? a2)) + (CODE c + (ModRM 0 r1 '/5 + (IMM32*2 a1 a2 ac)))] + [else (error 'CODErd "unhandled ~s" disp)]))))) + +(define CODEdi + (lambda (c disp n ac) + (with-args disp + (lambda (i r) + (CODErri c '/0 r i (IMM32 n ac)))))) + +(define CODEdi8 + (lambda (c disp n ac) + (with-args disp + (lambda (i r) + (CODErri c '/0 r i (IMM8 n ac)))))) + +(define *cogen* (gensym "*cogen*")) + +(define-syntax add-instruction + (syntax-rules () + [(_ (name instr ac args ...) b b* ...) + (putprop 'name *cogen* + (cons (length '(args ...)) + (lambda (instr ac args ...) b b* ...)))])) + +(define-syntax add-instructions + (syntax-rules () + [(_ instr ac [(name* arg** ...) b* b** ...] ...) + (begin + (add-instruction (name* instr ac arg** ...) b* b** ...) ...)])) + +(define (convert-instruction a ac) + (cond + [(getprop (car a) *cogen*) => + (lambda (p) + (let ([n (car p)] [proc (cdr p)] [args (cdr a)]) + (cond + [(fx= n (length args)) + (apply proc a ac args)] + [else + (error 'convert-instruction "incorrect args in ~s" a)])))] + [else (old-convert-instruction a ac)] + ;[else (error 'convert-instruction "unknown instruction in ~s" a)] + )) + +(module () +(define who 'assembler) +(add-instructions instr ac + [(ret) (CODE #xC3 ac)] + [(cltd) (CODE #x99 ac)] + [(movl src dst) + (cond + [(and (imm? src) (reg? dst)) (CODEri #xB8 dst src ac)] + [(and (imm? src) (mem? dst)) (CODEdi #xC7 dst src ac)] + [(and (reg? src) (reg? dst)) (CODErr #x89 src dst ac)] + [(and (reg? src) (mem? dst)) (CODErd #x89 src dst ac)] + [(and (mem? src) (reg? dst)) (CODErd #x8B dst src ac)] + [else (error who "invalid ~s" instr)])] + [(movb src dst) + (cond + ;[(and (imm8? src) (reg8? dst)) (CODEri #xB0 dst src ac)] + [(and (imm8? src) (mem? dst)) (CODEdi8 #xC6 dst src ac)] + ;[(and (reg8? src) (reg8? dst)) (CODErr #x88 src dst ac)] + [(and (reg8? src) (mem? dst)) (CODErd #x88 src dst ac)] + [(and (mem? src) (reg8? dst)) (CODErd #x8A dst src ac)] + [else (error who "invalid ~s" instr)])] + [(addl src dst) + (cond + ;;; add imm -> reg + [(and (imm8? src) (reg? dst)) + (CODE #x83 (ModRM 3 '/0 dst (IMM8 src ac)))] + [(and (imm? src) (eq? dst '%eax)) + (CODE #x05 (IMM32 src ac))] + [(and (imm? src) (reg? dst)) + (CODE #x81 (ModRM 3 '/0 dst (IMM32 src ac)))] + ;;; add reg -> reg + [(and (reg? src) (reg? dst)) + (CODE #x01 (ModRM 3 src dst ac))] + ;;; add mem -> reg + [(and (mem? src) (reg? dst)) + (CODErd #x03 dst src ac)] + ;;; add imm -> mem (not needed) + ;;; add reg -> mem (not needed) + [else (error who "invalid ~s" instr)])] + [(subl src dst) + (cond + ;;; imm -> reg + [(and (imm8? src) (reg? dst)) + (CODE #x83 (ModRM 3 '/5 dst (IMM8 src ac)))] + [(and (imm? src) (eq? dst '%eax)) + (CODE #x2D (IMM32 src ac))] + [(and (imm? src) (reg? dst)) + (CODE #x81 (ModRM 3 '/5 dst (IMM32 src ac)))] + ;;; reg -> reg + [(and (reg? src) (reg? dst)) + (CODE #x29 (ModRM 3 src dst ac))] + ;;; mem -> reg + [(and (mem? src) (reg? dst)) + (CODErd #x2B dst src ac)] + ;;; imm -> mem (not needed) + ;;; reg -> mem (not needed) + [else (error who "invalid ~s" instr)])] + [(sall src dst) + (cond + [(and (equal? '(int 1) src) (reg? dst)) + (CODE #xD1 (ModRM 3 '/4 dst ac))] + [(and (imm8? src) (reg? dst)) + (CODE #xC1 (ModRM 3 '/4 dst (IMM8 src ac)))] + [(and (eq? src '%cl) (reg? dst)) + (CODE #xD3 (ModRM 3 '/4 dst ac))] + [else (error who "invalid ~s" instr)])] + [(shrl src dst) + (cond + [(and (equal? '(int 1) src) (reg? dst)) + (CODE #xD1 (ModRM 3 '/5 dst ac))] + [(and (imm8? src) (reg? dst)) + (CODE #xC1 (ModRM 3 '/5 dst (IMM8 src ac)))] + [(and (eq? src '%cl) (reg? dst)) + (CODE #xD3 (ModRM 3 '/5 dst ac))] + [else (error who "invalid ~s" instr)])] + [(sarl src dst) + (cond + [(and (equal? '(int 1) src) (reg? dst)) + (CODE #xD1 (ModRM 3 '/7 dst ac))] + [(and (imm8? src) (reg? dst)) + (CODE #xC1 (ModRM 3 '/7 dst (IMM8 src ac)))] + [(and (eq? src '%cl) (reg? dst)) + (CODE #xD3 (ModRM 3 '/7 dst ac))] + [else (error who "invalid ~s" instr)])] + [(andl src dst) + (cond + ;;; and imm -> reg + [(and (imm8? src) (reg? dst)) + (CODE #x83 (ModRM 3 '/4 dst (IMM8 src ac)))] + [(and (imm? src) (eq? dst '%eax)) + (CODE #x25 (IMM32 src ac))] + [(and (imm? src) (reg? dst)) + (CODE #x81 (ModRM 3 '/4 dst (IMM32 src ac)))] + ;;; and reg -> reg + [(and (reg? src) (reg? dst)) + (CODE #x21 (ModRM 3 src dst ac))] + ;;; and mem -> reg + [(and (mem? src) (reg? dst)) + (CODErd #x23 dst src ac)] + [else (error who "invalid ~s" instr)])] + [(orl src dst) + (cond + ;;; or imm -> reg + [(and (imm8? src) (reg? dst)) + (CODE #x83 (ModRM 3 '/1 dst (IMM8 src ac)))] + [(and (imm? src) (eq? dst '%eax)) + (CODE #x0D (IMM32 src ac))] + [(and (imm? src) (reg? dst)) + (CODE #x81 (ModRM 3 '/1 dst (IMM32 src ac)))] + ;;; or reg -> reg + [(and (reg? src) (reg? dst)) + (CODE #x09 (ModRM 3 src dst ac))] + ;;; or mem -> reg + [(and (mem? src) (reg? dst)) + (CODErd #x0B dst src ac)] + [else (error who "invalid ~s" instr)])] + [(xorl src dst) + (cond + ;;; or imm -> reg + ;[(and (imm8? src) (reg? dst)) + ; (CODE #x83 (ModRM 3 '/1 dst (IMM8 src ac)))] + ;[(and (imm? src) (eq? dst '%eax)) + ; (CODE #x0D (IMM32 src ac))] + ;[(and (imm? src) (reg? dst)) + ; (CODE #x81 (ModRM 3 '/1 dst (IMM32 src ac)))] + ;;; or reg -> reg + [(and (reg? src) (reg? dst)) + (CODE #x31 (ModRM 3 src dst ac))] + ;;; or mem -> reg + [(and (mem? src) (reg? dst)) + (CODErd #x33 dst src ac)] + [else (error who "invalid ~s" instr)])] + [(cmpl src dst) + (cond + [(and (imm8? src) (reg? dst)) + (CODE #x83 (ModRM 3 '/7 dst (IMM8 src ac)))] + [(and (imm? src) (eq? dst '%eax)) + (CODE #x3D (IMM32 src ac))] + [(and (reg? src) (reg? dst)) + (CODE #x39 (ModRM 3 src dst ac))] + [(and (mem? src) (reg? dst)) + (CODErd #x3B dst src ac)] + [(and (imm8? src) (mem? dst)) + (CODErd #x83 '/7 dst (IMM8 src ac))] + [(and (imm? src) (mem? dst)) + (CODErd #x81 '/7 dst (IMM32 src ac))] + [else (error who "invalid ~s" instr)])] + [(imull src dst) + (cond + [(and (imm8? src) (reg? dst)) + (CODE #x6B (ModRM 3 dst dst (IMM8 src ac)))] + [(and (imm? src) (reg? dst)) + (CODE #x69 (ModRM 3 dst dst (IMM32 src ac)))] + [(and (reg? src) (reg? dst)) + (CODE #x0F (CODE #xAF (ModRM 3 dst src ac)))] + [(and (mem? src) (reg? dst)) + (CODE #x0F (CODErd #xAF dst src ac))] + [else (error who "invalid ~s" instr)])] + [(idivl dst) + (cond + [(reg? dst) + (CODErr #xF7 '/7 dst ac)] + [(mem? dst) + (CODErd #xF7 '/7 dst ac)] + [else (error who "invalid ~s" instr)])] + [(pushl dst) + (cond + [(imm8? dst) + (CODE #x6A (IMM8 dst ac))] + [(imm? dst) + (CODE #x68 (IMM32 dst ac))] + [(reg? dst) + (CODE+r #x50 dst ac)] + [(mem? dst) + (CODErd #xFF '/6 dst ac)] + [else (error who "invalid ~s" instr)])] + [(popl dst) + (cond + [(reg? dst) + (CODE+r #x58 dst ac)] + [(mem? dst) + (CODErd #x8F '/0 dst ac)] + [else (error who "invalid ~s" instr)])] + [(notl dst) + (cond + [(reg? dst) + (CODE #xF7 (ModRM 3 '/2 dst ac))] + [(mem? dst) + (CODErd #xF7 '/7 dst ac)] + [else (error who "invalid ~s" instr)])] + [(negl dst) + (cond + [(reg? dst) + (CODE #xF7 (ModRM 3 '/3 dst ac))] + [else (error who "invalid ~s" instr)])] + +)) + +(define old-convert-instruction + (lambda (a ac) + (define who 'assemble) + (check-len a) + (case (car a) + + [(jmp) + (with-args a + (lambda (dst) + (cond + [(label? dst) + (CODE #xE9 (cons (cons 'relative (label-name dst)) ac))] + [(imm? dst) + (CODE #xE9 (IMM32 dst ac))] + [(mem? dst) + (CODErd #xFF '/4 dst ac)] + [else (error who "invalid jmp in ~s" a)])))] + [(call) + (with-args a + (lambda (dst) + (cond + [(imm? dst) + (CODE #xE8 (IMM32 dst ac))] + [(label? dst) + (CODE #xE8 (cons (cons 'relative (label-name dst)) ac))] + [(mem? dst) + (CODErd #xFF '/2 dst ac)] + [(reg? dst) + (CODE #xFF (ModRM 3 '/2 dst ac))] + [else (error who "invalid jmp in ~s" a)])))] + [(seta setae setb setbe sete setg setge setl setle + setna setnae setnb setnbe setne setng setnge setnl setnle) + (let* ([table + '([seta #x97] [setna #x96] + [setae #x93] [setnae #x92] + [setb #x92] [setnb #x93] + [setbe #x96] [setnbe #x97] + [setg #x9F] [setng #x9E] + [setge #x9D] [setnge #x9C] + [setl #x9C] [setnl #x9D] + [setle #x9E] [setnle #x9F] + [sete #x94] [setne #x95])] + [lookup + (lambda (x) + (cond + [(assq x table) => cadr] + [else (error who "invalid cset ~s" x)]))]) + (with-args a + (lambda (dst) + (cond + [(reg8? dst) + (CODE #x0F + (CODE (lookup (car a)) + (ModRM 3 '/0 dst ac)))] + [else (error who "invalid ~s" a)]))))] + [(ja jae jb jbe je jg jge jl jle + jna jnae jnb jnbe jne jng jnge jnl jnle) + (let* ([table + '([je #x84] [jne #x85] + [ja #x87] [jna #x86] + [jae #x83] [jnae #x82] + [jb #x82] [jnb #x83] + [jbe #x86] [jnbe #x87] + [jg #x8F] [jng #x8E] + [jge #x8D] [jnge #x8C] + [jl #x8C] [jnl #x8D] + [jle #x8E] [jnle #x8F])] + [lookup + (lambda (x) + (cond + [(assq x table) => cadr] + [else (error who "invalid cmp ~s" x)]))]) + (with-args a + (lambda (dst) + (cond + [(imm? dst) + (CODE #x0F (CODE (lookup (car a)) (IMM32 dst ac)))] + [(label? dst) + (CODE #x0F + (CODE (lookup (car a)) + (cons (cons 'relative (label-name dst)) ac)))] + [else (error who "invalid ~s" a)]))))] + [(byte) + (with-args a + (lambda (x) + (unless (byte? x) (error who "invalid instruction ~s" a)) + (cons (byte x) ac)))] + [(byte-vector) + (with-args a + (lambda (x) (append (map byte (vector->list x)) ac)))] + [(int) (IMM32 a ac)] + [(label) + (with-args a + (lambda (L) + (unless (symbol? L) (error who "invalid instruction ~s" a)) + (cons (cons 'label L) ac)))] + [(label-address) + (with-args a + (lambda (L) + (unless (symbol? L) (error who "invalid instruction ~s" a)) + (cons (cons 'label-addr L) ac)))] + [(current-frame-offset) + (cons '(current-frame-offset) ac)] + [(nop) ac] + [else + (error who "unknown instruction ~s" a)]))) + +(define diff + (lambda (ls x) + (cond + [(eq? ls x) '()] + [else (cons (car ls) (diff (cdr ls) x))]))) + +(define hex-table + '#(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 + #\8 #\9 #\A #\B #\C #\D #\E #\F)) + +(define write/x + (lambda (x) + (case (car x) + [(byte) + (display "0x") + (display (vector-ref hex-table (fxsra (cdr x) 4))) + (display (vector-ref hex-table (fxlogand (cdr x) 15))) + (display " ")] + [else (write x)]))) + + +(define compute-code-size + (lambda (ls) + (fold (lambda (x ac) + (case (car x) + [(byte) (fx+ ac 1)] + [(word reloc-word reloc-word+ label-addr foreign-label + relative current-frame-offset) + (fx+ ac 4)] + [(label) ac] + [else (error 'compute-code-size "unknown instr ~s" x)])) + 0 + ls))) + + +(define compute-reloc-size + (lambda (ls) + (fold (lambda (x ac) + (case (car x) + [(reloc-word ) (fx+ ac 4)] + [(reloc-word+) (fx+ ac 8)] + [(relative label-addr foreign-label) (fx+ ac 8)] + [(word byte label current-frame-offset) ac] + [else (error 'compute-reloc-size "unknown instr ~s" x)])) + 0 + ls))) + +(define set-label-loc! + (lambda (x loc) + (when (getprop x '*label-loc*) + (error 'compile "label ~s is already defined" x)) + (putprop x '*label-loc* loc))) + +(define label-loc + (lambda (x) + (or (getprop x '*label-loc*) + (error 'compile "undefined label ~s" x)))) + + +(define unset-label-loc! + (lambda (x) + (remprop x '*label-loc*))) + + +(define whack-instructions + (lambda (x ls) + (define f + (lambda (ls idx reloc) + (cond + [(null? ls) reloc] + [else + (let ([a (car ls)]) + (case (car a) + [(byte) + (set-code-byte! x idx (cdr a)) + (f (cdr ls) (fx+ idx 1) reloc)] + [(reloc-word reloc-word+) + (f (cdr ls) (fx+ idx 4) (cons (cons idx a) reloc))] + [(relative label-addr foreign-label) + (f (cdr ls) (fx+ idx 4) (cons (cons idx a) reloc))] + [(word) + (let ([v (cdr a)]) + (set-code-word! x idx v) + (f (cdr ls) (fx+ idx 4) reloc))] + [(current-frame-offset) + (set-code-word! x idx idx) + (f (cdr ls) (fx+ idx 4) reloc)] + [(label) + (set-label-loc! (cdr a) (cons x idx)) + (f (cdr ls) idx reloc)] + [else + (error 'whack-instructions "unknown instr ~s" a)]))]))) + (f ls 0 '()))) + +(define wordsize 4) + +(define whack-reloc + (lambda (code) + (define reloc-idx 0) + (lambda (r) + (let ([idx (car r)] [type (cadr r)] [v (cddr r)]) + (case type + [(reloc-word) + (set-code-object! code v idx reloc-idx) + (set! reloc-idx (fxadd1 reloc-idx))] + [(foreign-label) + (set-code-foreign-object! code v idx reloc-idx) + (set! reloc-idx (fx+ reloc-idx 2))] + [(reloc-word+) + (let ([obj (car v)] [disp (cdr v)]) + (set-code-object+offset! code obj idx disp reloc-idx) + (set! reloc-idx (fx+ reloc-idx 2)))] + [(label-addr) + (let ([loc (label-loc v)]) + (let ([obj (car loc)] [off (cdr loc)]) + (set-code-object+offset! + code obj idx (fx+ off 11) reloc-idx))) + (set! reloc-idx (fx+ reloc-idx 2))] + [(relative) + (let ([loc (label-loc v)]) + (let ([obj (car loc)] [off (cdr loc)]) + (set-code-object+offset/rel! + code obj idx (fx+ off 11) reloc-idx))) + (set! reloc-idx (fx+ reloc-idx 2))] + [else (error 'whack-reloc "invalid reloc type ~s" type)])) + ))) + + +;;; (define list->code +;;; (lambda (ls) +;;; (let ([ls (convert-instructions ls)]) +;;; (let ([n (compute-code-size ls)] +;;; [m (compute-reloc-size ls)]) +;;; (let ([x (make-code n m 1)]) +;;; (let ([reloc* (whack-instructions x ls)]) +;;; (for-each (whack-reloc x) reloc*)) +;;; (make-code-executable! x) +;;; x))))) + +(define list*->code* + (lambda (ls*) + (let ([closure-size* (map car ls*)] + [ls* (map cdr ls*)]) + (let ([ls* (map convert-instructions ls*)]) + (let ([n* (map compute-code-size ls*)] + [m* (map compute-reloc-size ls*)]) + (let ([code* (map (lambda (n m c) (make-code n m c)) + n* + m* + closure-size*)]) + (let ([reloc** (map whack-instructions code* ls*)]) + (for-each + (lambda (code reloc*) + (for-each (whack-reloc code) reloc*)) + code* reloc**) + (for-each make-code-executable! code*) + code*))))))) + +(define list->code + (lambda (ls) + (car (list*->code* (list ls))))) + +(primitive-set! 'list*->code* list*->code*) +) diff --git a/src/libintelasm-6.6.ss b/src/libintelasm-6.6.ss new file mode 100644 index 0000000..7254753 --- /dev/null +++ b/src/libintelasm-6.6.ss @@ -0,0 +1,932 @@ + +;;; +;;; assuming the existence of a code manager, this file defines an assember +;;; that takes lists of assembly code and produces a list of code objects +;;; + + ;;; add + ;;; and + ;;; cmp + ;;; call + ;;; cltd + ;;; idiv + ;;; imull + ;;; ja + ;;; jae + ;;; jb + ;;; jbe + ;;; je + ;;; jg + ;;; jge + ;;; jl + ;;; jle + ;;; jne + ;;; jmp + ;;; movb + ;;; movl + ;;; negl + ;;; notl + ;;; orl + ;;; popl + ;;; pushl + ;;; ret + ;;; sall + ;;; sarl + ;;; shrl + ;;; sete + ;;; setg + + +(let () + +(define fold + (lambda (f init ls) + (cond + [(null? ls) init] + [else + (f (car ls) (fold f init (cdr ls)))]))) + +(define convert-instructions + (lambda (ls) + (fold convert-instruction '() ls))) + +(define register-mapping + '([%eax 32 0] + [%ecx 32 1] + [%edx 32 2] + [%ebx 32 3] + [%esp 32 4] + [%ebp 32 5] + [%esi 32 6] + [%edi 32 7] + [%al 8 0] + [%cl 8 1] + [%dl 8 2] + [%bl 8 3] + [%ah 8 4] + [%ch 8 5] + [%dh 8 6] + [%bh 8 7] + [/0 0 0] + [/1 0 1] + [/2 0 2] + [/3 0 3] + [/4 0 4] + [/5 0 5] + [/6 0 6] + [/7 0 7] + )) + +(define register-index + (lambda (x) + (cond + [(assq x register-mapping) => caddr] + [else (error 'register-index "not a register ~s" x)]))) + +(define reg32? + (lambda (x) + (cond + [(assq x register-mapping) => + (lambda (x) (fx= (cadr x) 32))] + [else #f]))) + +(define reg8? + (lambda (x) + (cond + [(assq x register-mapping) => + (lambda (x) (fx= (cadr x) 8))] + [else #f]))) + +(define reg? + (lambda (x) + (assq x register-mapping))) + +(define check-len + (lambda (x) + (define instr-len + '([ret] + [movl s d] + [movb s d] + [addl s d] + [subl s d] + [sall s d] + [sarl s d] + [shrl s d] + [andl s d] + [xorl s d] + [orl s d] + [cmpl s d] + [imull s d] + [notl d] + [negl d] + [idivl d] + [pushl d] + [popl d] + [jmp d] + [call d] + [ja d] + [jae d] + [jb d] + [jbe d] + [je d] + [jg d] + [jge d] + [jl d] + [jle d] + [jna d] + [jnae d] + [jnb d] + [jnbe d] + [jne d] + [jng d] + [jnge d] + [jnl d] + [jnle d] + [seta d] + [setae d] + [setb d] + [setbe d] + [sete d] + [setg d] + [setge d] + [setl d] + [setle d] + [setna d] + [setnae d] + [setnb d] + [setnbe d] + [setne d] + [setng d] + [setnge d] + [setnl d] + [setnle d] + [cltd] + [nop] + [byte x] + [byte-vector x] + [int x] + [label x] + [label-address x] + [current-frame-offset] + )) + (cond + [(assq (car x) instr-len) => + (lambda (p) + (unless (fx= (length x) (length p)) + (error 'assembler "invalid instruction format ~s" x)))] + [else (error 'assembler "unknown instruction ~s" x)]))) + +(define with-args + (lambda (ls f) + (apply f (cdr ls)))) + +(define byte + (lambda (x) + (cons 'byte (fxlogand x 255)))) + + +(define word + (lambda (x) + (cons 'word x))) + +(define reloc-word + (lambda (x) + (cons 'reloc-word x))) + +(define reloc-word+ + (lambda (x d) + (list* 'reloc-word+ x d))) + +(define list*-aux + (lambda (ls ls*) + (cond + [(null? ls*) ls] + [else (cons ls (list*-aux (car ls*) (cdr ls*)))]))) + +(define list* + (lambda (ls . ls*) + (list*-aux ls ls*))) + +(define byte? + (lambda (x) + (and (fixnum? x) + (fx<= x 127) + (fx<= -128 x)))) + +(define mem? + (lambda (x) + (and (list? x) + (fx= (length x) 3) + (eq? (car x) 'disp) + (or (imm? (cadr x)) + (reg? (cadr x))) + (or (imm? (caddr x)) + (reg? (caddr x)))))) + +(define small-disp? + (lambda (x) + (and (mem? x) + (byte? (cadr x))))) + + +(define CODE + (lambda (n ac) + (cons (byte n) ac))) + +(define CODE+r + (lambda (n r ac) + (cons (byte (fxlogor n (register-index r))) ac))) + +(define ModRM + (lambda (mod reg r/m ac) + (cons (byte (fxlogor + (register-index r/m) + (fxlogor + (fxsll (register-index reg) 3) + (fxsll mod 6)))) + (if (and (not (fx= mod 3)) (eq? r/m '%esp)) + (cons (byte #x24) ac) + ac)))) + +(define IMM32 + (lambda (n ac) + (cond + [(int? n) + (let ([n (cadr n)]) + (list* (byte n) + (byte (fxsra n 8)) + (byte (fxsra n 16)) + (byte (fxsra n 24)) + ac))] + [(obj? n) + (let ([v (cadr n)]) + (if (immediate? v) + (cons (word v) ac) + (cons (reloc-word v) ac)))] + [(obj+? n) + (let ([v (cadr n)] [d (caddr n)]) + (cons (reloc-word+ v d) ac))] + [(label-address? n) + (cons (cons 'label-addr (label-name n)) ac)] + [(foreign? n) + (cons (cons 'foreign-label (label-name n)) ac)] + [else (error 'IMM32 "invalid ~s" n)]))) + + +(define IMM8 + (lambda (n ac) + (cond + [(int? n) + (let ([n (cadr n)]) + (list* (byte n) ac))] + [else (error 'IMM8 "invalid ~s" n)]))) + + +(define imm? + (lambda (x) + (or (int? x) + (obj? x) + (obj+? x) + (label-address? x) + (foreign? x)))) + +(define foreign? + (lambda (x) + (and (pair? x) (eq? (car x) 'foreign-label)))) + + +(define imm8? + (lambda (x) + (and (int? x) (byte? (cadr x))))) + +(define label? + (lambda (x) + (cond + [(and (pair? x) (eq? (car x) 'label)) + (let ([d (cdr x)]) + (unless (and (null? (cdr d)) + (symbol? (car d))) + (error 'assemble "invalid label ~s" x))) + #t] + [else #f]))) + +(define label-address? + (lambda (x) + (cond + [(and (pair? x) (eq? (car x) 'label-address)) + (let ([d (cdr x)]) + (unless (and (null? (cdr d)) + (or (symbol? (car d)) + (string? (car d)))) + (error 'assemble "invalid label-address ~s" x))) + #t] + [else #f]))) + +(define label-name + (lambda (x) (cadr x))) + +(define int? + (lambda (x) + (and (pair? x) (eq? (car x) 'int)))) + +(define obj? + (lambda (x) + (and (pair? x) (eq? (car x) 'obj)))) + +(define obj+? + (lambda (x) + (and (pair? x) (eq? (car x) 'obj+)))) + +(define CODErri + (lambda (c d s i ac) + (cond + [(imm8? i) + (CODE c (ModRM 1 d s (IMM8 i ac)))] + [(reg? i) + (CODE c (ModRM i d s ac))] + [else + (CODE c (ModRM 2 d s (IMM32 i ac)))]))) + +(define CODErr + (lambda (c d s ac) + (CODE c (ModRM 3 d s ac)))) + +(define CODEri + (lambda (c d i ac) + (CODE+r c d (IMM32 i ac)))) + + +(define RegReg + (lambda (r1 r2 r3 ac) + (cond + [(eq? r3 '%esp) (error 'assembler "BUG: invalid src %esp")] + [(eq? r1 '%ebp) (error 'assembler "BUG: invalid src %ebp")] + [else +;;; (parameterize ([print-radix 16]) +;;; (printf "REGREG ~s ~s ~s\n" r1 r2 r3) +;;; (printf "REGREG ~s ~s\n" +;;; (byte (fxlogor 4 (fxsll (register-index r1) 3))) +;;; (byte (fxlogor (register-index r2) +;;; (fxsll (register-index r3) 3))))) + (list* + (byte (fxlogor 4 (fxsll (register-index r1) 3))) + (byte (fxlogor (register-index r2) + (fxsll (register-index r3) 3))) + ac)]))) + + +;;(define CODErd +;; (lambda (c r1 disp ac) +;; (with-args disp +;; (lambda (i/r r2) +;; (if (reg? i/r) +;; (CODE c (RegReg r1 i/r r2 ac)) +;; (CODErri c r1 r2 i/r ac)))))) + + +(define IMM32*2 + (lambda (i1 i2 ac) + (cond + [(and (int? i1) (obj? i2)) + (let ([d (cadr i1)] [v (cadr i2)]) + (cons (reloc-word+ v d) ac))] + [else (error 'assemble "IMM32*2 ~s ~s" i1 i2)]))) + + +(define CODErd + (lambda (c r1 disp ac) + (with-args disp + (lambda (a1 a2) + (cond + [(and (reg? a1) (reg? a2)) + (CODE c (RegReg r1 a1 a2 ac))] + [(and (imm? a1) (reg? a2)) + (CODErri c r1 a2 a1 ac)] + [(and (imm? a1) (imm? a2)) + (CODE c + (ModRM 0 r1 '/5 + (IMM32*2 a1 a2 ac)))] + [else (error 'CODErd "unhandled ~s" disp)]))))) + +(define CODEdi + (lambda (c disp n ac) + (with-args disp + (lambda (i r) + (CODErri c '/0 r i (IMM32 n ac)))))) + +(define CODEdi8 + (lambda (c disp n ac) + (with-args disp + (lambda (i r) + (CODErri c '/0 r i (IMM8 n ac)))))) + +(define *cogen* (gensym "*cogen*")) + +(define-syntax add-instruction + (syntax-rules () + [(_ (name instr ac args ...) b b* ...) + (putprop 'name *cogen* + (cons (length '(args ...)) + (lambda (instr ac args ...) b b* ...)))])) + +(define-syntax add-instructions + (syntax-rules () + [(_ instr ac [(name* arg** ...) b* b** ...] ...) + (begin + (add-instruction (name* instr ac arg** ...) b* b** ...) ...)])) + +(define (convert-instruction a ac) + (cond + [(getprop (car a) *cogen*) => + (lambda (p) + (let ([n (car p)] [proc (cdr p)] [args (cdr a)]) + (cond + [(fx= n (length args)) + (apply proc a ac args)] + [else + (error 'convert-instruction "incorrect args in ~s" a)])))] + [else (old-convert-instruction a ac)] + ;[else (error 'convert-instruction "unknown instruction in ~s" a)] + )) + +(module () +(define who 'assembler) +(add-instructions instr ac + [(ret) (CODE #xC3 ac)] + [(cltd) (CODE #x99 ac)] + [(movl src dst) + (cond + [(and (imm? src) (reg? dst)) (CODEri #xB8 dst src ac)] + [(and (imm? src) (mem? dst)) (CODEdi #xC7 dst src ac)] + [(and (reg? src) (reg? dst)) (CODErr #x89 src dst ac)] + [(and (reg? src) (mem? dst)) (CODErd #x89 src dst ac)] + [(and (mem? src) (reg? dst)) (CODErd #x8B dst src ac)] + [else (error who "invalid ~s" instr)])] + [(movb src dst) + (cond + ;[(and (imm8? src) (reg8? dst)) (CODEri #xB0 dst src ac)] + [(and (imm8? src) (mem? dst)) (CODEdi8 #xC6 dst src ac)] + ;[(and (reg8? src) (reg8? dst)) (CODErr #x88 src dst ac)] + [(and (reg8? src) (mem? dst)) (CODErd #x88 src dst ac)] + [(and (mem? src) (reg8? dst)) (CODErd #x8A dst src ac)] + [else (error who "invalid ~s" instr)])] + [(addl src dst) + (cond + ;;; add imm -> reg + [(and (imm8? src) (reg? dst)) + (CODE #x83 (ModRM 3 '/0 dst (IMM8 src ac)))] + [(and (imm? src) (eq? dst '%eax)) + (CODE #x05 (IMM32 src ac))] + [(and (imm? src) (reg? dst)) + (CODE #x81 (ModRM 3 '/0 dst (IMM32 src ac)))] + ;;; add reg -> reg + [(and (reg? src) (reg? dst)) + (CODE #x01 (ModRM 3 src dst ac))] + ;;; add mem -> reg + [(and (mem? src) (reg? dst)) + (CODErd #x03 dst src ac)] + ;;; add imm -> mem (not needed) + ;;; add reg -> mem (not needed) + [else (error who "invalid ~s" instr)])] + [(subl src dst) + (cond + ;;; imm -> reg + [(and (imm8? src) (reg? dst)) + (CODE #x83 (ModRM 3 '/5 dst (IMM8 src ac)))] + [(and (imm? src) (eq? dst '%eax)) + (CODE #x2D (IMM32 src ac))] + [(and (imm? src) (reg? dst)) + (CODE #x81 (ModRM 3 '/5 dst (IMM32 src ac)))] + ;;; reg -> reg + [(and (reg? src) (reg? dst)) + (CODE #x29 (ModRM 3 src dst ac))] + ;;; mem -> reg + [(and (mem? src) (reg? dst)) + (CODErd #x2B dst src ac)] + ;;; imm -> mem (not needed) + ;;; reg -> mem (not needed) + [else (error who "invalid ~s" instr)])] + [(sall src dst) + (cond + [(and (equal? '(int 1) src) (reg? dst)) + (CODE #xD1 (ModRM 3 '/4 dst ac))] + [(and (imm8? src) (reg? dst)) + (CODE #xC1 (ModRM 3 '/4 dst (IMM8 src ac)))] + [(and (eq? src '%cl) (reg? dst)) + (CODE #xD3 (ModRM 3 '/4 dst ac))] + [else (error who "invalid ~s" instr)])] + [(shrl src dst) + (cond + [(and (equal? '(int 1) src) (reg? dst)) + (CODE #xD1 (ModRM 3 '/5 dst ac))] + [(and (imm8? src) (reg? dst)) + (CODE #xC1 (ModRM 3 '/5 dst (IMM8 src ac)))] + [(and (eq? src '%cl) (reg? dst)) + (CODE #xD3 (ModRM 3 '/5 dst ac))] + [else (error who "invalid ~s" instr)])] + [(sarl src dst) + (cond + [(and (equal? '(int 1) src) (reg? dst)) + (CODE #xD1 (ModRM 3 '/7 dst ac))] + [(and (imm8? src) (reg? dst)) + (CODE #xC1 (ModRM 3 '/7 dst (IMM8 src ac)))] + [(and (eq? src '%cl) (reg? dst)) + (CODE #xD3 (ModRM 3 '/7 dst ac))] + [else (error who "invalid ~s" instr)])] + [(andl src dst) + (cond + ;;; and imm -> reg + [(and (imm8? src) (reg? dst)) + (CODE #x83 (ModRM 3 '/4 dst (IMM8 src ac)))] + [(and (imm? src) (eq? dst '%eax)) + (CODE #x25 (IMM32 src ac))] + [(and (imm? src) (reg? dst)) + (CODE #x81 (ModRM 3 '/4 dst (IMM32 src ac)))] + ;;; and reg -> reg + [(and (reg? src) (reg? dst)) + (CODE #x21 (ModRM 3 src dst ac))] + ;;; and mem -> reg + [(and (mem? src) (reg? dst)) + (CODErd #x23 dst src ac)] + [else (error who "invalid ~s" instr)])] + [(orl src dst) + (cond + ;;; or imm -> reg + [(and (imm8? src) (reg? dst)) + (CODE #x83 (ModRM 3 '/1 dst (IMM8 src ac)))] + [(and (imm? src) (eq? dst '%eax)) + (CODE #x0D (IMM32 src ac))] + [(and (imm? src) (reg? dst)) + (CODE #x81 (ModRM 3 '/1 dst (IMM32 src ac)))] + ;;; or reg -> reg + [(and (reg? src) (reg? dst)) + (CODE #x09 (ModRM 3 src dst ac))] + ;;; or mem -> reg + [(and (mem? src) (reg? dst)) + (CODErd #x0B dst src ac)] + [else (error who "invalid ~s" instr)])] + [(xorl src dst) + (cond + ;;; or imm -> reg + ;[(and (imm8? src) (reg? dst)) + ; (CODE #x83 (ModRM 3 '/1 dst (IMM8 src ac)))] + ;[(and (imm? src) (eq? dst '%eax)) + ; (CODE #x0D (IMM32 src ac))] + ;[(and (imm? src) (reg? dst)) + ; (CODE #x81 (ModRM 3 '/1 dst (IMM32 src ac)))] + ;;; or reg -> reg + [(and (reg? src) (reg? dst)) + (CODE #x31 (ModRM 3 src dst ac))] + ;;; or mem -> reg + [(and (mem? src) (reg? dst)) + (CODErd #x33 dst src ac)] + [else (error who "invalid ~s" instr)])] + [(cmpl src dst) + (cond + [(and (imm8? src) (reg? dst)) + (CODE #x83 (ModRM 3 '/7 dst (IMM8 src ac)))] + [(and (imm? src) (eq? dst '%eax)) + (CODE #x3D (IMM32 src ac))] + [(and (reg? src) (reg? dst)) + (CODE #x39 (ModRM 3 src dst ac))] + [(and (mem? src) (reg? dst)) + (CODErd #x3B dst src ac)] + [(and (imm8? src) (mem? dst)) + (CODErd #x83 '/7 dst (IMM8 src ac))] + [(and (imm? src) (mem? dst)) + (CODErd #x81 '/7 dst (IMM32 src ac))] + [else (error who "invalid ~s" instr)])] + [(imull src dst) + (cond + [(and (imm8? src) (reg? dst)) + (CODE #x6B (ModRM 3 dst dst (IMM8 src ac)))] + [(and (imm? src) (reg? dst)) + (CODE #x69 (ModRM 3 dst dst (IMM32 src ac)))] + [(and (reg? src) (reg? dst)) + (CODE #x0F (CODE #xAF (ModRM 3 dst src ac)))] + [(and (mem? src) (reg? dst)) + (CODE #x0F (CODErd #xAF dst src ac))] + [else (error who "invalid ~s" instr)])] + [(idivl dst) + (cond + [(reg? dst) + (CODErr #xF7 '/7 dst ac)] + [(mem? dst) + (CODErd #xF7 '/7 dst ac)] + [else (error who "invalid ~s" instr)])] + [(pushl dst) + (cond + [(imm8? dst) + (CODE #x6A (IMM8 dst ac))] + [(imm? dst) + (CODE #x68 (IMM32 dst ac))] + [(reg? dst) + (CODE+r #x50 dst ac)] + [(mem? dst) + (CODErd #xFF '/6 dst ac)] + [else (error who "invalid ~s" instr)])] + [(popl dst) + (cond + [(reg? dst) + (CODE+r #x58 dst ac)] + [(mem? dst) + (CODErd #x8F '/0 dst ac)] + [else (error who "invalid ~s" instr)])] + [(notl dst) + (cond + [(reg? dst) + (CODE #xF7 (ModRM 3 '/2 dst ac))] + [(mem? dst) + (CODErd #xF7 '/7 dst ac)] + [else (error who "invalid ~s" instr)])] + [(negl dst) + (cond + [(reg? dst) + (CODE #xF7 (ModRM 3 '/3 dst ac))] + [else (error who "invalid ~s" instr)])] +)) + +(define old-convert-instruction + (lambda (a ac) + (define who 'assemble) + (check-len a) + (case (car a) + [(jmp) + (with-args a + (lambda (dst) + (cond + [(label? dst) + (CODE #xE9 (cons (cons 'relative (label-name dst)) ac))] + [(imm? dst) + (CODE #xE9 (IMM32 dst ac))] + [(mem? dst) + (CODErd #xFF '/4 dst ac)] + [else (error who "invalid jmp in ~s" a)])))] + [(call) + (with-args a + (lambda (dst) + (cond + [(imm? dst) + (CODE #xE8 (IMM32 dst ac))] + [(label? dst) + (CODE #xE8 (cons (cons 'relative (label-name dst)) ac))] + [(mem? dst) + (CODErd #xFF '/2 dst ac)] + [(reg? dst) + (CODE #xFF (ModRM 3 '/2 dst ac))] + [else (error who "invalid jmp in ~s" a)])))] + [(seta setae setb setbe sete setg setge setl setle + setna setnae setnb setnbe setne setng setnge setnl setnle) + (let* ([table + '([seta #x97] [setna #x96] + [setae #x93] [setnae #x92] + [setb #x92] [setnb #x93] + [setbe #x96] [setnbe #x97] + [setg #x9F] [setng #x9E] + [setge #x9D] [setnge #x9C] + [setl #x9C] [setnl #x9D] + [setle #x9E] [setnle #x9F] + [sete #x94] [setne #x95])] + [lookup + (lambda (x) + (cond + [(assq x table) => cadr] + [else (error who "invalid cset ~s" x)]))]) + (with-args a + (lambda (dst) + (cond + [(reg8? dst) + (CODE #x0F + (CODE (lookup (car a)) + (ModRM 3 '/0 dst ac)))] + [else (error who "invalid ~s" a)]))))] + [(ja jae jb jbe je jg jge jl jle + jna jnae jnb jnbe jne jng jnge jnl jnle) + (let* ([table + '([je #x84] [jne #x85] + [ja #x87] [jna #x86] + [jae #x83] [jnae #x82] + [jb #x82] [jnb #x83] + [jbe #x86] [jnbe #x87] + [jg #x8F] [jng #x8E] + [jge #x8D] [jnge #x8C] + [jl #x8C] [jnl #x8D] + [jle #x8E] [jnle #x8F])] + [lookup + (lambda (x) + (cond + [(assq x table) => cadr] + [else (error who "invalid cmp ~s" x)]))]) + (with-args a + (lambda (dst) + (cond + [(imm? dst) + (CODE #x0F (CODE (lookup (car a)) (IMM32 dst ac)))] + [(label? dst) + (CODE #x0F + (CODE (lookup (car a)) + (cons (cons 'relative (label-name dst)) ac)))] + [else (error who "invalid ~s" a)]))))] + [(byte) + (with-args a + (lambda (x) + (unless (byte? x) (error who "invalid instruction ~s" a)) + (cons (byte x) ac)))] + [(byte-vector) + (with-args a + (lambda (x) (append (map byte (vector->list x)) ac)))] + [(int) (IMM32 a ac)] + [(label) + (with-args a + (lambda (L) + (unless (symbol? L) (error who "invalid instruction ~s" a)) + (cons (cons 'label L) ac)))] + [(label-address) + (with-args a + (lambda (L) + (unless (symbol? L) (error who "invalid instruction ~s" a)) + (cons (cons 'label-addr L) ac)))] + [(current-frame-offset) + (cons '(current-frame-offset) ac)] + [(nop) ac] + [else + (error who "unknown instruction ~s" a)]))) + +(define diff + (lambda (ls x) + (cond + [(eq? ls x) '()] + [else (cons (car ls) (diff (cdr ls) x))]))) + +(define hex-table + '#(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 + #\8 #\9 #\A #\B #\C #\D #\E #\F)) + +(define write/x + (lambda (x) + (case (car x) + [(byte) + (display "0x") + (display (vector-ref hex-table (fxsra (cdr x) 4))) + (display (vector-ref hex-table (fxlogand (cdr x) 15))) + (display " ")] + [else (write x)]))) + + +(define compute-code-size + (lambda (ls) + (fold (lambda (x ac) + (case (car x) + [(byte) (fx+ ac 1)] + [(word reloc-word reloc-word+ label-addr foreign-label + relative current-frame-offset) + (fx+ ac 4)] + [(label) ac] + [else (error 'compute-code-size "unknown instr ~s" x)])) + 0 + ls))) + + +(define set-label-loc! + (lambda (x loc) + (when (getprop x '*label-loc*) + (error 'compile "label ~s is already defined" x)) + (putprop x '*label-loc* loc))) + +(define label-loc + (lambda (x) + (or (getprop x '*label-loc*) + (error 'compile "undefined label ~s" x)))) + + +(define unset-label-loc! + (lambda (x) + (remprop x '*label-loc*))) + + +(define set-code-word! + (lambda (code idx x) + (cond + [(fixnum? x) + (code-set! code (fx+ idx 0) (fxsll (fxlogand x #x3F) 2)) + (code-set! code (fx+ idx 1) (fxlogand (fxsra x 6) #xFF)) + (code-set! code (fx+ idx 2) (fxlogand (fxsra x 14) #xFF)) + (code-set! code (fx+ idx 3) (fxlogand (fxsra x 22) #xFF))] + [else (error 'set-code-word! "unhandled ~s" x)]))) + +(define whack-instructions + (lambda (x ls) + (define f + (lambda (ls idx reloc) + (cond + [(null? ls) reloc] + [else + (let ([a (car ls)]) + (case (car a) + [(byte) + (code-set! x idx (cdr a)) + (f (cdr ls) (fx+ idx 1) reloc)] + [(reloc-word reloc-word+) + (f (cdr ls) (fx+ idx 4) (cons (cons idx a) reloc))] + [(relative label-addr foreign-label) + (f (cdr ls) (fx+ idx 4) (cons (cons idx a) reloc))] + [(word) + (let ([v (cdr a)]) + (set-code-word! x idx v) + (f (cdr ls) (fx+ idx 4) reloc))] + [(current-frame-offset) + (set-code-word! x idx idx) + (f (cdr ls) (fx+ idx 4) reloc)] + [(label) + (set-label-loc! (cdr a) (cons x idx)) + (f (cdr ls) idx reloc)] + [else + (error 'whack-instructions "unknown instr ~s" a)]))]))) + (f ls 0 '()))) + +(define wordsize 4) + + +(define compute-reloc-size + (lambda (ls) + (fold (lambda (x ac) + (case (car x) + [(reloc-word foreign-label) (fx+ ac 2)] + [(relative reloc-word+ label-addr) (fx+ ac 3)] + [(word byte label current-frame-offset) ac] + [else (error 'compute-reloc-size "unknown instr ~s" x)])) + 0 + ls))) + +(define whack-reloc + (lambda (vec) + (define reloc-idx 0) + (lambda (r) + (let ([idx (car r)] [type (cadr r)] [v (cddr r)]) + (case type + [(reloc-word) + (vector-set! vec reloc-idx (fxsll idx 2)) + (vector-set! vec (fx+ reloc-idx 1) v) + (set! reloc-idx (fx+ reloc-idx 2))] + [(foreign-label) + (vector-set! vec reloc-idx (fxlogor 1 (fxsll idx 2))) + (vector-set! vec (fx+ reloc-idx 1) v) + (set! reloc-idx (fx+ reloc-idx 2))] + [(reloc-word+) + (let ([obj (car v)] [disp (cdr v)]) + (vector-set! vec reloc-idx (fxlogor 2 (fxsll idx 2))) + (vector-set! vec (fx+ reloc-idx 1) disp) + (vector-set! vec (fx+ reloc-idx 2) obj) + (set! reloc-idx (fx+ reloc-idx 3)))] + [(label-addr) + (let ([loc (label-loc v)]) + (let ([obj (car loc)] [disp (cdr loc)]) + (vector-set! vec reloc-idx (fxlogor 2 (fxsll idx 2))) + (vector-set! vec (fx+ reloc-idx 1) (fx+ disp 11)) + (vector-set! vec (fx+ reloc-idx 2) obj))) + (set! reloc-idx (fx+ reloc-idx 3))] + [(relative) + (let ([loc (label-loc v)]) + (let ([obj (car loc)] [disp (cdr loc)]) + (vector-set! vec reloc-idx (fxlogor 3 (fxsll idx 2))) + (vector-set! vec (fx+ reloc-idx 1) (fx+ disp 11)) + (vector-set! vec (fx+ reloc-idx 2) obj))) + (set! reloc-idx (fx+ reloc-idx 3))] + [else (error 'whack-reloc "invalid reloc type ~s" type)])) + ))) + + +;;; (define list->code +;;; (lambda (ls) +;;; (let ([ls (convert-instructions ls)]) +;;; (let ([n (compute-code-size ls)] +;;; [m (compute-reloc-size ls)]) +;;; (let ([x (make-code n m 1)]) +;;; (let ([reloc* (whack-instructions x ls)]) +;;; (for-each (whack-reloc x) reloc*)) +;;; (make-code-executable! x) +;;; x))))) + +(define list*->code* + (lambda (ls*) + (let ([closure-size* (map car ls*)] + [ls* (map cdr ls*)]) + (let ([ls* (map convert-instructions ls*)]) + (let ([n* (map compute-code-size ls*)] + [m* (map compute-reloc-size ls*)]) + (let ([code* (map make-code n* closure-size*)] + [relv* (map make-vector m*)]) + (let ([reloc** (map whack-instructions code* ls*)]) + (for-each + (lambda (relv reloc*) + (for-each (whack-reloc relv) reloc*)) + relv* reloc**) + (for-each set-code-reloc-vector! code* relv*) + code*))))))) + +(define list->code + (lambda (ls) + (car (list*->code* (list ls))))) + +(primitive-set! 'list*->code* list*->code*) +) diff --git a/src/libintelasm-6.9.ss b/src/libintelasm-6.9.ss new file mode 100644 index 0000000..74ccc3c --- /dev/null +++ b/src/libintelasm-6.9.ss @@ -0,0 +1,887 @@ + +;;; +;;; assuming the existence of a code manager, this file defines an assember +;;; that takes lists of assembly code and produces a list of code objects +;;; + + ;;; add + ;;; and + ;;; cmp + ;;; call + ;;; cltd + ;;; idiv + ;;; imull + ;;; ja + ;;; jae + ;;; jb + ;;; jbe + ;;; je + ;;; jg + ;;; jge + ;;; jl + ;;; jle + ;;; jne + ;;; jmp + ;;; movb + ;;; movl + ;;; negl + ;;; notl + ;;; orl + ;;; popl + ;;; pushl + ;;; ret + ;;; sall + ;;; sarl + ;;; shrl + ;;; sete + ;;; setg + + +(let () + +(define fold + (lambda (f init ls) + (cond + [(null? ls) init] + [else + (f (car ls) (fold f init (cdr ls)))]))) + +(define convert-instructions + (lambda (ls) + (fold convert-instruction '() ls))) + +(define register-mapping + '([%eax 32 0] + [%ecx 32 1] + [%edx 32 2] + [%ebx 32 3] + [%esp 32 4] + [%ebp 32 5] + [%esi 32 6] + [%edi 32 7] + [%al 8 0] + [%cl 8 1] + [%dl 8 2] + [%bl 8 3] + [%ah 8 4] + [%ch 8 5] + [%dh 8 6] + [%bh 8 7] + [/0 0 0] + [/1 0 1] + [/2 0 2] + [/3 0 3] + [/4 0 4] + [/5 0 5] + [/6 0 6] + [/7 0 7] + )) + +(define register-index + (lambda (x) + (cond + [(assq x register-mapping) => caddr] + [else (error 'register-index "not a register ~s" x)]))) + +(define reg32? + (lambda (x) + (cond + [(assq x register-mapping) => + (lambda (x) (fx= (cadr x) 32))] + [else #f]))) + +(define reg8? + (lambda (x) + (cond + [(assq x register-mapping) => + (lambda (x) (fx= (cadr x) 8))] + [else #f]))) + +(define reg? + (lambda (x) + (assq x register-mapping))) + + +;(define with-args +; (lambda (ls f) +; (apply f (cdr ls)))) + +(define-syntax with-args + (syntax-rules (lambda) + [(_ x (lambda (a0 a1) b b* ...)) + (let ([t x]) + (if (pair? t) + (let ([t ($cdr t)]) + (if (pair? t) + (let ([a0 ($car t)] [t ($cdr t)]) + (if (pair? t) + (let ([a1 ($car t)]) + (if (null? ($cdr t)) + (let () b b* ...) + (error 'with-args "too many args"))) + (error 'with-args "too few args"))) + (error 'with-args "too few args"))) + (error 'with-args "too few args")))])) + + +;(define byte +; (lambda (x) +; (cons 'byte (fxlogand x 255)))) + +(define-syntax byte + (syntax-rules () + [(_ x) (fxlogand x 255)])) + + +(define word + (lambda (x) + (cons 'word x))) + +(define reloc-word + (lambda (x) + (cons 'reloc-word x))) + +(define reloc-word+ + (lambda (x d) + (list* 'reloc-word+ x d))) + +(define byte? + (lambda (x) + (and (fixnum? x) + (fx<= x 127) + (fx<= -128 x)))) + +(define mem? + (lambda (x) + (and (list? x) + (fx= (length x) 3) + (eq? (car x) 'disp) + (or (imm? (cadr x)) + (reg? (cadr x))) + (or (imm? (caddr x)) + (reg? (caddr x)))))) + +(define small-disp? + (lambda (x) + (and (mem? x) + (byte? (cadr x))))) + + +(define CODE + (lambda (n ac) + (cons (byte n) ac))) + +(define CODE+r + (lambda (n r ac) + (cons (byte (fxlogor n (register-index r))) ac))) + +(define ModRM + (lambda (mod reg r/m ac) + (cons (byte (fxlogor + (register-index r/m) + (fxlogor + (fxsll (register-index reg) 3) + (fxsll mod 6)))) + (if (and (not (fx= mod 3)) (eq? r/m '%esp)) + (cons (byte #x24) ac) + ac)))) + +(define IMM32 + (lambda (n ac) + (cond + [(int? n) + (let ([n (cadr n)]) + (list* (byte n) + (byte (fxsra n 8)) + (byte (fxsra n 16)) + (byte (fxsra n 24)) + ac))] + [(obj? n) + (let ([v (cadr n)]) + (if (immediate? v) + (cons (word v) ac) + (cons (reloc-word v) ac)))] + [(obj+? n) + (let ([v (cadr n)] [d (caddr n)]) + (cons (reloc-word+ v d) ac))] + [(label-address? n) + (cons (cons 'label-addr (label-name n)) ac)] + [(foreign? n) + (cons (cons 'foreign-label (label-name n)) ac)] + [else (error 'IMM32 "invalid ~s" n)]))) + + +(define IMM8 + (lambda (n ac) + (cond + [(int? n) + (let ([n (cadr n)]) + (list* (byte n) ac))] + [else (error 'IMM8 "invalid ~s" n)]))) + + +(define imm? + (lambda (x) + (or (int? x) + (obj? x) + (obj+? x) + (label-address? x) + (foreign? x)))) + +(define foreign? + (lambda (x) + (and (pair? x) (eq? (car x) 'foreign-label)))) + + +(define imm8? + (lambda (x) + (and (int? x) (byte? (cadr x))))) + +(define label? + (lambda (x) + (cond + [(and (pair? x) (eq? (car x) 'label)) + (let ([d (cdr x)]) + (unless (and (null? (cdr d)) + (symbol? (car d))) + (error 'assemble "invalid label ~s" x))) + #t] + [else #f]))) + +(define label-address? + (lambda (x) + (cond + [(and (pair? x) (eq? (car x) 'label-address)) + (let ([d (cdr x)]) + (unless (and (null? (cdr d)) + (or (symbol? (car d)) + (string? (car d)))) + (error 'assemble "invalid label-address ~s" x))) + #t] + [else #f]))) + +(define label-name + (lambda (x) (cadr x))) + +(define int? + (lambda (x) + (and (pair? x) (eq? (car x) 'int)))) + +(define obj? + (lambda (x) + (and (pair? x) (eq? (car x) 'obj)))) + +(define obj+? + (lambda (x) + (and (pair? x) (eq? (car x) 'obj+)))) + +(define CODErri + (lambda (c d s i ac) + (cond + [(imm8? i) + (CODE c (ModRM 1 d s (IMM8 i ac)))] + [(imm? i) + (CODE c (ModRM 2 d s (IMM32 i ac)))] + [else (error 'CODErri "invalid i=~s" i)]))) + +(define CODErr + (lambda (c d s ac) + (CODE c (ModRM 3 d s ac)))) + +(define CODEri + (lambda (c d i ac) + (CODE+r c d (IMM32 i ac)))) + + +(define RegReg + (lambda (r1 r2 r3 ac) + (cond + [(eq? r3 '%esp) (error 'assembler "BUG: invalid src %esp")] + [(eq? r1 '%ebp) (error 'assembler "BUG: invalid src %ebp")] + [else + (list* + (byte (fxlogor 4 (fxsll (register-index r1) 3))) + (byte (fxlogor (register-index r2) + (fxsll (register-index r3) 3))) + ac)]))) + + +;;(define CODErd +;; (lambda (c r1 disp ac) +;; (with-args disp +;; (lambda (i/r r2) +;; (if (reg? i/r) +;; (CODE c (RegReg r1 i/r r2 ac)) +;; (CODErri c r1 r2 i/r ac)))))) + + +(define IMM32*2 + (lambda (i1 i2 ac) + (cond + [(and (int? i1) (obj? i2)) + (let ([d (cadr i1)] [v (cadr i2)]) + (cons (reloc-word+ v d) ac))] + [else (error 'assemble "IMM32*2 ~s ~s" i1 i2)]))) + + +(define CODErd + (lambda (c r1 disp ac) + (with-args disp + (lambda (a1 a2) + (cond + [(and (reg? a1) (reg? a2)) + (CODE c (RegReg r1 a1 a2 ac))] + [(and (imm? a1) (reg? a2)) + (CODErri c r1 a2 a1 ac)] + [(and (imm? a1) (imm? a2)) + (CODE c + (ModRM 0 r1 '/5 + (IMM32*2 a1 a2 ac)))] + [else (error 'CODErd "unhandled ~s" disp)]))))) + +;;; (define CODEdi +;;; (lambda (c disp n ac) +;;; (with-args disp +;;; (lambda (i r) +;;; (CODErri c '/0 r i (IMM32 n ac)))))) + +(define CODEdi + (lambda (c disp n ac) + (with-args disp + (lambda (a1 a2) + (cond + [(and (reg? a1) (reg? a2)) + (error 'CODEdi "unsupported1")] + [(and (imm? a1) (reg? a2)) + (CODErri c '/0 a2 a1 (IMM32 n ac))] + [(and (imm? a1) (imm? a2)) + (error 'CODEdi "unsupported2")] + [else (error 'CODEdi "unhandled ~s" disp)]))))) + + +(define CODEdi8 + (lambda (c disp n ac) + (with-args disp + (lambda (i r) + (CODErri c '/0 r i (IMM8 n ac)))))) + +(define *cogen* (gensym "*cogen*")) + +(define-syntax add-instruction + (syntax-rules () + [(_ (name instr ac args ...) b b* ...) + (putprop 'name *cogen* + (cons (length '(args ...)) + (lambda (instr ac args ...) b b* ...)))])) + +(define-syntax add-instructions + (syntax-rules () + [(_ instr ac [(name* arg** ...) b* b** ...] ...) + (begin + (add-instruction (name* instr ac arg** ...) b* b** ...) ...)])) + +(define (convert-instruction a ac) + (cond + [(getprop (car a) *cogen*) => + (lambda (p) + (let ([n (car p)] [proc (cdr p)] [args (cdr a)]) + (cond + [(fx= n 2) + (if (fx= (length args) 2) + (proc a ac (car args) (cadr args)) + (error 'convert-instruction "incorrect args in ~s" a))] + [(fx= n 1) + (if (fx= (length args) 1) + (proc a ac (car args)) + (error 'convert-instruction "incorrect args in ~s" a))] + [(fx= n 0) + (if (fx= (length args) 0) + (proc a ac) + (error 'convert-instruction "incorrect args in ~s" a))] + [else + (if (fx= (length args) n) + (apply proc a ac args) + (error 'convert-instruction "incorrect args in ~s" a))])))] + [else (error 'convert-instruction "unknown instruction in ~s" a)])) + +;;; instr/null is for 1-byte instructions that take no arguments +;(define (instr/null code ac) +; (cons code ac)) + +;(define (instr/ir arg1 arg2 ac ircode) +; (CODE+r ircode arg2 (IMM32 arg1 ac))) +; +;(define (instr/im arg1 arg2 ac imcode) +; (error 'instr/im "not implemented")) +; +;(define (instr/rr arg1 arg2 ac rrcode) +; (CODErr rrcode arg1 arg2 ac)) +; +;(define (instr/rm arg1 arg2 ac rmcode) +; (CODErd rmcode arg1 arg2 ac)) + + +(define (instr/2 arg1 arg2 ac ircode imcode rrcode rmcode mrcode) + (cond + [(imm? arg1) + (cond + [(reg? arg2) (CODEri ircode arg2 arg1 ac)] + [(mem? arg2) (CODEdi imcode arg2 arg1 ac)] + [else (error 'instr/2 "invalid args ~s ~s" arg1 arg2)])] + [(reg? arg1) + (cond + [(reg? arg2) (CODErr rrcode arg1 arg2 ac)] + [(mem? arg2) (CODErd rmcode arg1 arg2 ac)] + [else (error 'instr/2 "invalid args ~s ~s" arg1 arg2)])] + [(mem? arg1) + (cond + [(reg? arg2) (CODErd mrcode arg2 arg1 ac)] + [else (error 'instr/2 "invalid args ~s ~s" arg1 arg2)])] + [else (error 'instr/2 "invalid args ~s ~s" arg1 arg2)])) + +(module () +(define who 'assembler) + +(define (conditional-set c dst ac) + (cond + [(reg8? dst) + (CODE #x0F (CODE c (ModRM 3 '/0 dst ac)))] + [else (error who "invalid condition-set to ~s" dst)])) + +(define (conditional-jump c dst ac) + (cond + [(imm? dst) + (CODE #x0F (CODE c (IMM32 dst ac)))] + [(label? dst) + (CODE #x0F (CODE c (cons (cons 'relative (label-name dst)) ac)))] + [else (error who "invalid conditional jump target ~s" dst)])) + +(add-instructions instr ac + [(ret) (CODE #xC3 ac)] + [(cltd) (CODE #x99 ac)] + [(movl src dst) (instr/2 src dst ac #xB8 #xC7 #x89 #x89 #x8B)] + [(movb src dst) + (cond + [(and (imm8? src) (mem? dst)) (CODEdi8 #xC6 dst src ac)] + [(and (reg8? src) (mem? dst)) (CODErd #x88 src dst ac)] + [(and (mem? src) (reg8? dst)) (CODErd #x8A dst src ac)] + [else (error who "invalid ~s" instr)])] + [(addl src dst) + (cond + [(and (imm8? src) (reg? dst)) + (CODE #x83 (ModRM 3 '/0 dst (IMM8 src ac)))] + [(and (imm? src) (eq? dst '%eax)) + (CODE #x05 (IMM32 src ac))] + [(and (imm? src) (reg? dst)) + (CODE #x81 (ModRM 3 '/0 dst (IMM32 src ac)))] + [(and (reg? src) (reg? dst)) + (CODE #x01 (ModRM 3 src dst ac))] + [(and (mem? src) (reg? dst)) + (CODErd #x03 dst src ac)] + [else (error who "invalid ~s" instr)])] + [(subl src dst) + (cond + [(and (imm8? src) (reg? dst)) + (CODE #x83 (ModRM 3 '/5 dst (IMM8 src ac)))] + [(and (imm? src) (eq? dst '%eax)) + (CODE #x2D (IMM32 src ac))] + [(and (imm? src) (reg? dst)) + (CODE #x81 (ModRM 3 '/5 dst (IMM32 src ac)))] + [(and (reg? src) (reg? dst)) + (CODE #x29 (ModRM 3 src dst ac))] + [(and (mem? src) (reg? dst)) + (CODErd #x2B dst src ac)] + [else (error who "invalid ~s" instr)])] + [(sall src dst) + (cond + [(and (equal? '(int 1) src) (reg? dst)) + (CODE #xD1 (ModRM 3 '/4 dst ac))] + [(and (imm8? src) (reg? dst)) + (CODE #xC1 (ModRM 3 '/4 dst (IMM8 src ac)))] + [(and (eq? src '%cl) (reg? dst)) + (CODE #xD3 (ModRM 3 '/4 dst ac))] + [else (error who "invalid ~s" instr)])] + [(shrl src dst) + (cond + [(and (equal? '(int 1) src) (reg? dst)) + (CODE #xD1 (ModRM 3 '/5 dst ac))] + [(and (imm8? src) (reg? dst)) + (CODE #xC1 (ModRM 3 '/5 dst (IMM8 src ac)))] + [(and (eq? src '%cl) (reg? dst)) + (CODE #xD3 (ModRM 3 '/5 dst ac))] + [else (error who "invalid ~s" instr)])] + [(sarl src dst) + (cond + [(and (equal? '(int 1) src) (reg? dst)) + (CODE #xD1 (ModRM 3 '/7 dst ac))] + [(and (imm8? src) (reg? dst)) + (CODE #xC1 (ModRM 3 '/7 dst (IMM8 src ac)))] + [(and (eq? src '%cl) (reg? dst)) + (CODE #xD3 (ModRM 3 '/7 dst ac))] + [else (error who "invalid ~s" instr)])] + [(andl src dst) + (cond + [(and (imm8? src) (reg? dst)) + (CODE #x83 (ModRM 3 '/4 dst (IMM8 src ac)))] + [(and (imm? src) (eq? dst '%eax)) + (CODE #x25 (IMM32 src ac))] + [(and (imm? src) (reg? dst)) + (CODE #x81 (ModRM 3 '/4 dst (IMM32 src ac)))] + [(and (reg? src) (reg? dst)) + (CODE #x21 (ModRM 3 src dst ac))] + [(and (mem? src) (reg? dst)) + (CODErd #x23 dst src ac)] + [else (error who "invalid ~s" instr)])] + [(orl src dst) + (cond + [(and (imm8? src) (reg? dst)) + (CODE #x83 (ModRM 3 '/1 dst (IMM8 src ac)))] + [(and (imm? src) (eq? dst '%eax)) + (CODE #x0D (IMM32 src ac))] + [(and (imm? src) (reg? dst)) + (CODE #x81 (ModRM 3 '/1 dst (IMM32 src ac)))] + [(and (reg? src) (reg? dst)) + (CODE #x09 (ModRM 3 src dst ac))] + [(and (mem? src) (reg? dst)) + (CODErd #x0B dst src ac)] + [else (error who "invalid ~s" instr)])] + [(xorl src dst) + (cond + [(and (reg? src) (reg? dst)) + (CODE #x31 (ModRM 3 src dst ac))] + [(and (mem? src) (reg? dst)) + (CODErd #x33 dst src ac)] + [else (error who "invalid ~s" instr)])] + [(cmpl src dst) + (cond + [(and (imm8? src) (reg? dst)) + (CODE #x83 (ModRM 3 '/7 dst (IMM8 src ac)))] + [(and (imm? src) (eq? dst '%eax)) + (CODE #x3D (IMM32 src ac))] + [(and (reg? src) (reg? dst)) + (CODE #x39 (ModRM 3 src dst ac))] + [(and (mem? src) (reg? dst)) + (CODErd #x3B dst src ac)] + [(and (imm8? src) (mem? dst)) + (CODErd #x83 '/7 dst (IMM8 src ac))] + [(and (imm? src) (mem? dst)) + (CODErd #x81 '/7 dst (IMM32 src ac))] + [else (error who "invalid ~s" instr)])] + [(imull src dst) + (cond + [(and (imm8? src) (reg? dst)) + (CODE #x6B (ModRM 3 dst dst (IMM8 src ac)))] + [(and (imm? src) (reg? dst)) + (CODE #x69 (ModRM 3 dst dst (IMM32 src ac)))] + [(and (reg? src) (reg? dst)) + (CODE #x0F (CODE #xAF (ModRM 3 dst src ac)))] + [(and (mem? src) (reg? dst)) + (CODE #x0F (CODErd #xAF dst src ac))] + [else (error who "invalid ~s" instr)])] + [(idivl dst) + (cond + [(reg? dst) + (CODErr #xF7 '/7 dst ac)] + [(mem? dst) + (CODErd #xF7 '/7 dst ac)] + [else (error who "invalid ~s" instr)])] + [(pushl dst) + (cond + [(imm8? dst) + (CODE #x6A (IMM8 dst ac))] + [(imm? dst) + (CODE #x68 (IMM32 dst ac))] + [(reg? dst) + (CODE+r #x50 dst ac)] + [(mem? dst) + (CODErd #xFF '/6 dst ac)] + [else (error who "invalid ~s" instr)])] + [(popl dst) + (cond + [(reg? dst) + (CODE+r #x58 dst ac)] + [(mem? dst) + (CODErd #x8F '/0 dst ac)] + [else (error who "invalid ~s" instr)])] + [(notl dst) + (cond + [(reg? dst) + (CODE #xF7 (ModRM 3 '/2 dst ac))] + [(mem? dst) + (CODErd #xF7 '/7 dst ac)] + [else (error who "invalid ~s" instr)])] + [(negl dst) + (cond + [(reg? dst) + (CODE #xF7 (ModRM 3 '/3 dst ac))] + [else (error who "invalid ~s" instr)])] + [(jmp dst) + (cond + [(label? dst) + (CODE #xE9 (cons (cons 'relative (label-name dst)) ac))] + [(imm? dst) + (CODE #xE9 (IMM32 dst ac))] + [(mem? dst) + (CODErd #xFF '/4 dst ac)] + [else (error who "invalid jmp target ~s" dst)])] + [(call dst) + (cond + [(imm? dst) + (CODE #xE8 (IMM32 dst ac))] + [(label? dst) + (CODE #xE8 (cons (cons 'relative (label-name dst)) ac))] + [(mem? dst) + (CODErd #xFF '/2 dst ac)] + [(reg? dst) + (CODE #xFF (ModRM 3 '/2 dst ac))] + [else (error who "invalid jmp target ~s" dst)])] + [(seta dst) (conditional-set #x97 dst ac)] + [(setae dst) (conditional-set #x93 dst ac)] + [(setb dst) (conditional-set #x92 dst ac)] + [(setbe dst) (conditional-set #x96 dst ac)] + [(setg dst) (conditional-set #x9F dst ac)] + [(setge dst) (conditional-set #x9D dst ac)] + [(setl dst) (conditional-set #x9C dst ac)] + [(setle dst) (conditional-set #x9E dst ac)] + [(sete dst) (conditional-set #x94 dst ac)] + [(setna dst) (conditional-set #x96 dst ac)] + [(setnae dst) (conditional-set #x92 dst ac)] + [(setnb dst) (conditional-set #x93 dst ac)] + [(setnbe dst) (conditional-set #x97 dst ac)] + [(setng dst) (conditional-set #x9E dst ac)] + [(setnge dst) (conditional-set #x9C dst ac)] + [(setnl dst) (conditional-set #x9D dst ac)] + [(setnle dst) (conditional-set #x9F dst ac)] + [(setne dst) (conditional-set #x95 dst ac)] + [(ja dst) (conditional-jump #x87 dst ac)] + [(jae dst) (conditional-jump #x83 dst ac)] + [(jb dst) (conditional-jump #x82 dst ac)] + [(jbe dst) (conditional-jump #x86 dst ac)] + [(jg dst) (conditional-jump #x8F dst ac)] + [(jge dst) (conditional-jump #x8D dst ac)] + [(jl dst) (conditional-jump #x8C dst ac)] + [(jle dst) (conditional-jump #x8E dst ac)] + [(je dst) (conditional-jump #x84 dst ac)] + [(jna dst) (conditional-jump #x86 dst ac)] + [(jnae dst) (conditional-jump #x82 dst ac)] + [(jnb dst) (conditional-jump #x83 dst ac)] + [(jnbe dst) (conditional-jump #x87 dst ac)] + [(jng dst) (conditional-jump #x8E dst ac)] + [(jnge dst) (conditional-jump #x8C dst ac)] + [(jnl dst) (conditional-jump #x8D dst ac)] + [(jnle dst) (conditional-jump #x8F dst ac)] + [(jne dst) (conditional-jump #x85 dst ac)] + [(byte x) + (unless (byte? x) (error who "~s is not a byte" x)) + (cons (byte x) ac)] + [(byte-vector x) (append (map (lambda (x) (byte x)) (vector->list x)) ac)] + [(int a) (IMM32 instr ac)] + [(label L) + (unless (symbol? L) (error who "label ~s is not a symbol" L)) + (cons (cons 'label L) ac)] + [(label-address L) + (unless (symbol? L) (error who "label-address ~s is not a symbol" L)) + (cons (cons 'label-addr L) ac)] + [(current-frame-offset) + (cons '(current-frame-offset) ac)] + [(nop) ac] +)) + + +(define compute-code-size + (lambda (ls) + (fold (lambda (x ac) + (if (fixnum? x) + (fx+ ac 1) + (case (car x) + [(byte) (fx+ ac 1)] + [(word reloc-word reloc-word+ label-addr foreign-label + relative local-relative current-frame-offset) + (fx+ ac 4)] + [(label) ac] + [else (error 'compute-code-size "unknown instr ~s" x)]))) + 0 + ls))) + + +(define set-label-loc! + (lambda (x loc) + (when (getprop x '*label-loc*) + (error 'compile "label ~s is already defined" x)) + (putprop x '*label-loc* loc))) + +(define label-loc + (lambda (x) + (or (getprop x '*label-loc*) + (error 'compile "undefined label ~s" x)))) + + +(define unset-label-loc! + (lambda (x) + (remprop x '*label-loc*))) + + +(define set-code-word! + (lambda (code idx x) + (cond + [(fixnum? x) + (code-set! code (fx+ idx 0) (fxsll (fxlogand x #x3F) 2)) + (code-set! code (fx+ idx 1) (fxlogand (fxsra x 6) #xFF)) + (code-set! code (fx+ idx 2) (fxlogand (fxsra x 14) #xFF)) + (code-set! code (fx+ idx 3) (fxlogand (fxsra x 22) #xFF))] + [else (error 'set-code-word! "unhandled ~s" x)]))) + +(define (optimize-local-jumps ls) + (define locals '()) + (define g (gensym)) + (for-each + (lambda (x) + (when (and (pair? x) (eq? (car x) 'label)) + (putprop (cdr x) g 'local) + (set! locals (cons (cdr x) locals)))) + ls) + (for-each + (lambda (x) + (when (and (pair? x) + (eq? (car x) 'relative) + (eq? (getprop (cdr x) g) 'local)) + (set-car! x 'local-relative))) + ls) + (for-each (lambda (x) (remprop x g)) locals) + ls) + + + +(define whack-instructions + (lambda (x ls) + (define f + (lambda (ls idx reloc) + (cond + [(null? ls) reloc] + [else + (let ([a (car ls)]) + (if (fixnum? a) + (begin + (code-set! x idx a) + (f (cdr ls) (fxadd1 idx) reloc)) + (case (car a) + [(byte) + (code-set! x idx (cdr a)) + (f (cdr ls) (fx+ idx 1) reloc)] + [(reloc-word reloc-word+) + (f (cdr ls) (fx+ idx 4) (cons (cons idx a) reloc))] + [(local-relative relative label-addr foreign-label) + (f (cdr ls) (fx+ idx 4) (cons (cons idx a) reloc))] + [(word) + (let ([v (cdr a)]) + (set-code-word! x idx v) + (f (cdr ls) (fx+ idx 4) reloc))] + [(current-frame-offset) + (set-code-word! x idx idx) + (f (cdr ls) (fx+ idx 4) reloc)] + [(label) + (set-label-loc! (cdr a) (cons x idx)) + (f (cdr ls) idx reloc)] + [else + (error 'whack-instructions "unknown instr ~s" a)])))]))) + (f ls 0 '()))) + +(define wordsize 4) + + +(define compute-reloc-size + (lambda (ls) + (fold (lambda (x ac) + (if (fixnum? x) + ac + (case (car x) + [(reloc-word foreign-label) (fx+ ac 2)] + [(relative reloc-word+ label-addr) (fx+ ac 3)] + [(word byte label current-frame-offset local-relative) ac] + [else (error 'compute-reloc-size "unknown instr ~s" x)]))) + 0 + ls))) + +(define whack-reloc + (lambda (code vec) + (define reloc-idx 0) + (lambda (r) + (let ([idx (car r)] [type (cadr r)] [v (cddr r)]) + (case type + [(reloc-word) + (vector-set! vec reloc-idx (fxsll idx 2)) + (vector-set! vec (fx+ reloc-idx 1) v) + (set! reloc-idx (fx+ reloc-idx 2))] + [(foreign-label) + (vector-set! vec reloc-idx (fxlogor 1 (fxsll idx 2))) + (vector-set! vec (fx+ reloc-idx 1) v) + (set! reloc-idx (fx+ reloc-idx 2))] + [(reloc-word+) + (let ([obj (car v)] [disp (cdr v)]) + (vector-set! vec reloc-idx (fxlogor 2 (fxsll idx 2))) + (vector-set! vec (fx+ reloc-idx 1) disp) + (vector-set! vec (fx+ reloc-idx 2) obj) + (set! reloc-idx (fx+ reloc-idx 3)))] + [(label-addr) + (let ([loc (label-loc v)]) + (let ([obj (car loc)] [disp (cdr loc)]) + (vector-set! vec reloc-idx (fxlogor 2 (fxsll idx 2))) + (vector-set! vec (fx+ reloc-idx 1) (fx+ disp 11)) + (vector-set! vec (fx+ reloc-idx 2) obj))) + (set! reloc-idx (fx+ reloc-idx 3))] + [(local-relative) + (let ([loc (label-loc v)]) + (let ([obj (car loc)] [disp (cdr loc)]) + (unless (eq? obj code) + (error 'whack-reloc "local-relative differ")) + (let ([rel (fx- disp (fx+ idx 4))]) + (code-set! code (fx+ idx 0) (fxlogand rel #xFF)) + (code-set! code (fx+ idx 1) (fxlogand (fxsra rel 8) #xFF)) + (code-set! code (fx+ idx 2) (fxlogand (fxsra rel 16) #xFF)) + (code-set! code (fx+ idx 3) (fxlogand (fxsra rel 24) #xFF)))))] + [(relative) + (let ([loc (label-loc v)]) + (let ([obj (car loc)] [disp (cdr loc)]) + (vector-set! vec reloc-idx (fxlogor 3 (fxsll idx 2))) + (vector-set! vec (fx+ reloc-idx 1) (fx+ disp 11)) + (vector-set! vec (fx+ reloc-idx 2) obj))) + (set! reloc-idx (fx+ reloc-idx 3))] + [else (error 'whack-reloc "invalid reloc type ~s" type)])) + ))) + + +;;; (define list->code +;;; (lambda (ls) +;;; (let ([ls (convert-instructions ls)]) +;;; (let ([n (compute-code-size ls)] +;;; [m (compute-reloc-size ls)]) +;;; (let ([x (make-code n m 1)]) +;;; (let ([reloc* (whack-instructions x ls)]) +;;; (for-each (whack-reloc x) reloc*)) +;;; (make-code-executable! x) +;;; x))))) + +(define list*->code* + (lambda (ls*) + (let ([closure-size* (map car ls*)] + [ls* (map cdr ls*)]) + (let* ([ls* (map convert-instructions ls*)] + [ls* (map optimize-local-jumps ls*)]) + (let ([n* (map compute-code-size ls*)] + [m* (map compute-reloc-size ls*)]) + (let ([code* (map make-code n* closure-size*)] + [relv* (map make-vector m*)]) + (let ([reloc** (map whack-instructions code* ls*)]) + (for-each + (lambda (foo reloc*) + (for-each (whack-reloc (car foo) (cdr foo)) reloc*)) + (map cons code* relv*) reloc**) + (for-each set-code-reloc-vector! code* relv*) + code*))))))) + +(define list->code + (lambda (ls) + (car (list*->code* (list ls))))) + +(primitive-set! 'list*->code* list*->code*) +) diff --git a/src/libinterpret-6.5.ss b/src/libinterpret-6.5.ss new file mode 100644 index 0000000..f064d7b --- /dev/null +++ b/src/libinterpret-6.5.ss @@ -0,0 +1,324 @@ + +;;; Changes: +;;; 6.5: handles letrec +;;; 6.1: adding case-lambda, dropping lambda +;;; 6.0: basic version working +;;; + +;;; Expand : Scheme -> Core Scheme +;;; +;;; ::= (quote datum) +;;; | +;;; | (if ) +;;; | (set! ) +;;; | (begin ...) +;;; | (case-lambda ( ) ( ) ...) +;;; | ( ...) +;;; | (primref ) +;;; | ( ...) +;;; ::= () +;;; | +;;; | ( . ) +;;; ::= void | memv | top-level-value | set-top-level-value! +;;; + + +(let () + (define syntax-error + (lambda (x) + (error 'interpret "invalid syntax ~s" x))) + ;;; + (define C*->last + (lambda (a d env) + (cond + [(null? d) (C a env)] + [else + (let ([a (C a env)] + [d (C*->last (car d) (cdr d) env)]) + (lambda (renv) + (a renv) + (d renv)))]))) + ;;; + (define C*->list + (lambda (a d env) + (cond + [(null? d) + (let ([a (C a env)]) + (lambda (renv) + (list (a renv))))] + [else + (let ([a (C a env)] + [d (C*->list (car d) (cdr d) env)]) + (lambda (renv) + (cons (a renv) (d renv))))]))) + ;;; + (define extend-env + (lambda (fml* env) + (cons fml* env))) + ;;; + (define fml-length + (lambda (fml* x) + (cond + [(pair? fml*) (fxadd1 (fml-length (cdr fml*) x))] + [(null? fml*) 0] + [(symbol? fml*) 1] + [else (syntax-error x)]))) + ;;; + (define whack-proper + (lambda (v ls i j) + (cond + [(null? ls) + (if (fx= i j) + v + (error 'apply1 "incorrect number of arguments to procedure"))] + [(fx= i j) + (error 'apply2 "incorrect number of arguments to procedure")] + [else + (vector-set! v i (car ls)) + (whack-proper v (cdr ls) (fxadd1 i) j)]))) + ;;; + (define whack-improper + (lambda (v ls i j) + (cond + [(fx= i j) (vector-set! v i ls) v] + [(null? ls) + (error 'apply3 "incorrect number of arguments to procedure")] + [else + (vector-set! v i (car ls)) + (whack-improper v (cdr ls) (fxadd1 i) j)]))) + ;;; + (define lookup + (lambda (x env) + (define Lj + (lambda (x fml* j) + (cond + [(pair? fml*) + (if (eq? (car fml*) x) + j + (Lj x (cdr fml*) (fxadd1 j)))] + [(eq? x fml*) j] + [else #f]))) + (define Li + (lambda (x env i) + (cond + [(null? env) #f] + [(Lj x (car env) 0) => + (lambda (j) + (cons i j))] + [else (Li x (cdr env) (fxadd1 i))]))) + (Li x env 0))) + ;;; + (define C + (lambda (x env) + (cond + [(gensym? x) + (cond + [(lookup x env) => + (lambda (b) + (let ([i (car b)] [j (cdr b)]) + (lambda (renv) + (vector-ref (list-ref renv i) j))))] + [else (syntax-error x)])] + [(pair? x) + (let ([a (car x)] [d (cdr x)]) + (unless (list? d) (syntax-error x)) + (cond + [(eq? a 'quote) + (unless (fx= (length d) 1) (syntax-error x)) + (let ([v (car d)]) + (lambda (renv) v))] + [(eq? a 'if) + (unless (fx= (length d) 3) (syntax-error x)) + (let ([test (C (car d) env)] + [conseq (C (cadr d) env)] + [altern (C (caddr d) env)]) + (lambda (renv) + (if (test renv) + (conseq renv) + (altern renv))))] + [(eq? a 'set!) + (unless (fx= (length d) 2) (syntax-error x)) + (let ([var (car d)] [val (C (cadr d) env)]) + (cond + [(lookup var env) => + (lambda (b) + (let ([i (car b)] [j (cdr b)]) + (lambda (renv) + (vector-set! (list-ref renv i) j (val renv)))))] + [else (syntax-error x)]))] + [(eq? a 'begin) + (unless (fx>= (length d) 1) (syntax-error x)) + (C*->last (car d) (cdr d) env)] + [(eq? a 'letrec) + (let ([bind* (car d)] [body* (cdr d)]) + (if (null? bind*) + (C*->last (car body*) (cdr body*) env) + (let ([lhs* (map car bind*)] [rhs* (map cadr bind*)]) + (let ([env (extend-env lhs* env)]) + (let ([body* (C*->last (car body*) (cdr body*) env)] + [rhs* (C*->list (car rhs*) (cdr rhs*) env)] + [n (length lhs*)]) + (lambda (renv) + (let ([v (make-vector n)]) + (let ([renv (cons v renv)]) + (let f ([i 0] [ls (rhs* renv)]) + (if (null? ls) + (body* renv) + (begin + (vector-set! v i (car ls)) + (f (fxadd1 i) (cdr ls)))))))) + )))))] + [(eq? a 'case-lambda) + (unless (fx>= (length d) 1) (syntax-error x)) + (let () + (define generate + (lambda (d) + (cond + [(null? d) + (lambda (n args renv) + (error 'apply + "incorrect number of arguments ~s to procedure" + n))] + [else + (let ([k (generate (cdr d))] + [a (car d)]) + (let ([fml (car a)] [body* (cdr a)]) + (let ([env (extend-env fml env)] + [n (fml-length fml x)]) + (let ([body* + (C*->last (car body*) (cdr body*) env)]) + (if (list? fml) + (lambda (m args renv) + (if (fx= n m) + (body* (cons (list->vector args) renv)) + (k m args renv))) + (let ([q (fxsub1 n)]) + (lambda (m args renv) + (if (fx>= m q) + (let ([v (make-vector n)]) + (let f ([i 0] [args args]) + (cond + [(fx= i q) + (vector-set! v q args)] + [else + (vector-set! v i (car args)) + (f (fxadd1 i) (cdr args))])) + (body* (cons v renv))) + (k m args renv)))))))))]))) + (let ([dispatch (generate d)]) + (lambda (renv) + (lambda args + (dispatch (length args) args renv)))))] + [(eq? a 'void) + (unless (fx= (length d) 0) (syntax-error x)) + (lambda (renv) (void))] + [(eq? a 'memv) + (unless (fx= (length d) 2) (syntax-error x)) + (let ([val (C (car d) env)] [list (C (cadr d) env)]) + (lambda (renv) + (memq (val renv) (list renv))))] + [(eq? a 'top-level-value) + (unless (fx= (length d) 1) (syntax-error x)) + (let ([qsym (car d)]) + (unless (and (pair? qsym) + (fx= (length qsym) 2) + (eq? (car qsym) 'quote) + (symbol? (cadr qsym))) + (syntax-error x)) + (let ([sym (cadr qsym)]) + (if (top-level-bound? sym) + (lambda (renv) + (top-level-value sym)) + (lambda (renv) + (if (top-level-bound? sym) + (top-level-value sym) + (error #f "~s is unbound" sym))))))] + [(memq a '(set-top-level-value!)) + (unless (fx= (length d) 2) (syntax-error x)) + (let ([qsym (car d)] [val (C (cadr d) env)]) + (unless (and (pair? qsym) + (fx= (length qsym) 2) + (eq? (car qsym) 'quote) + (symbol? (cadr qsym))) + (syntax-error x)) + (let ([sym (cadr qsym)]) + (lambda (renv) + (set-top-level-value! sym (val renv)))))] + ;;; [(eq? a '$pcb-set!) + ;;; (unless (fx= (length d) 2) (syntax-error x)) + ;;; (let ([sym (car d)] [val (C (cadr d) env)]) + ;;; (unless (symbol? sym) (syntax-error x)) + ;;; (lambda (renv) + ;;; (set-top-level-value! sym (val renv))))] + [(eq? a '|#primitive|) + (unless (fx= (length d) 1) (syntax-error x)) + (let ([sym (car d)]) + (let ([prim (primitive-ref sym)]) + (if (procedure? prim) + (lambda (renv) prim) + (syntax-error x))))] + [(memq a '(foreign-call $apply)) + (error 'interpret "~a form is not supported" a)] + ;;; [else + ;;; (let ([rator (C a env)] [n (length d)]) + ;;; (cond + ;;; [(fx= n 0) + ;;; (lambda (renv) + ;;; (let ([p (rator renv)]) + ;;; (p)))] + ;;; [(fx= n 1) + ;;; (let ([arg1 (C (car d) env)]) + ;;; (lambda (renv) + ;;; (let ([p (rator renv)]) + ;;; (p (arg1 renv)))))] + ;;; [(fx= n 2) + ;;; (let ([arg1 (C (car d) env)] + ;;; [arg2 (C (cadr d) env)]) + ;;; (lambda (renv) + ;;; (let ([p (rator renv)]) + ;;; (p (arg1 renv) (arg2 renv)))))] + ;;; [else + ;;; (let ([arg* (C*->list (car d) (cdr d) env)]) + ;;; (lambda (renv) + ;;; (apply (rator renv) (arg* renv))))]))] + [else + (let ([rator (C a env)] [n (length d)]) + (cond + [(fx= n 0) + (lambda (renv) + (apply (rator renv) '()))] + ;[(fx= n 1) + ; (let ([arg1 (C (car d) env)]) + ; (lambda (renv) + ; ((rator renv) (arg1 renv))))] + ;[(fx= n 2) + ; (let ([arg1 (C (car d) env)] + ; [arg2 (C (cadr d) env)]) + ; (lambda (renv) + ; ((rator renv) (arg1 renv) (arg2 renv))))] + [else + (let ([arg* (C*->list (car d) (cdr d) env)]) + (lambda (renv) + (apply (rator renv) (arg* renv))))]))] + + ))] + [else (syntax-error x)]))) + ;;; + (primitive-set! 'interpret + (lambda (x) + (let ([x (expand x)]) + (let ([p (C x '())]) + (p '()))))) + ;;; + (primitive-set! 'current-eval + (make-parameter + interpret + (lambda (f) + (unless (procedure? f) + (error 'current-eval "~s is not a procedure" f)) + f))) + ;;; + (primitive-set! 'eval + (lambda (x) + ((current-eval) x)))) + diff --git a/src/libinterpret.fasl b/src/libinterpret.fasl index 1a7af32..d167d41 100644 Binary files a/src/libinterpret.fasl and b/src/libinterpret.fasl differ diff --git a/src/libio-6.9.ss b/src/libio-6.9.ss new file mode 100644 index 0000000..216fb60 --- /dev/null +++ b/src/libio-6.9.ss @@ -0,0 +1,407 @@ + +;;; OUTPUT PORTS + +(let () + ;;; only file-based ports are supported at this point + ;;; + ;;; an output port is a vector with the following fields: + ;;; 0. id + ;;; 1. file-name + ;;; 2. file-descriptor + ;;; 3. open? + ;;; 4. buffer + ;;; 5. buffer-size + ;;; 6. index + ;;; 7. flush-proc + ;;; 8. close-proc + (define-record output-port + (name fd open? + buffer size index flush-proc close-proc)) + (define fd->port + (lambda (fd filename) + (make-output-port filename fd #t + (make-string 4096) 4096 0 + fd-flush-proc fd-close-proc))) + (define open-output-string + (lambda () + (make-output-port '*string-port* '() #t + (make-string 4096) 4096 0 + str-flush-proc (lambda (port) (void))))) + (define get-output-string + (lambda (p) + (define fill + (lambda (dst src di si sj) + (cond + [(fx= si sj) dst] + [else + (string-set! dst di (string-ref src si)) + (fill dst src (fxadd1 di) (fxadd1 si) sj)]))) + (unless (output-port? p) + (error 'get-output-string "~s is not an output port" p)) + (let ([ls (output-port-fd p)]) + (unless (list? ls) + (error 'get-output-string "~s is not an output port" p)) + (let f ([ls (reverse ls)] [n 0]) + (cond + [(null? ls) + (let ([idx (output-port-index p)] + [buf (output-port-buffer p)]) + (let ([str (make-string (fx+ n idx))]) + (fill str buf n 0 idx)))] + [else + (let ([buf (car ls)]) + (let ([idx (string-length buf)]) + (let ([str (f (cdr ls) (fx+ n idx))]) + (fill str buf n 0 idx))))]))))) + (define open-output-file + (lambda (name mode) + (unless (string? name) + (error 'open-output-file "~s is not a valid file name" name)) + (let ([mode + (cond + [(assq mode '([error 0] [append 1] [replace 2] [truncate 3])) + => cadr] + [else + (error 'open-output-file "~s is not a valid mode" mode)])]) + (let ([fh (foreign-call "ik_open_file" name mode)]) + (fd->port fh name))))) + (define write-char + (lambda (c port) + (unless (char? c) + (error 'write-char "not a char: ~s" c)) + (unless (output-port-open? port) + (error 'write-char "port ~s closed" port)) + (let ([idx (output-port-index port)] [size (output-port-size port)]) + (if (fx< idx size) + (begin + (string-set! (output-port-buffer port) idx c) + (set-output-port-index! port (fxadd1 idx)) + (when ($char= c #\newline) + (flush-output-port port))) + (begin + (flush-output-port port) + (write-char c port)))))) + (define fd-flush-proc + (lambda (port) + (let ([idx (output-port-index port)]) + (when (fx> idx 0) + (foreign-call "ik_write" + (output-port-fd port) + idx + (output-port-buffer port)))) + (set-output-port-index! port 0))) + (define str-flush-proc + (lambda (port) + (let ([idx (output-port-index port)]) + (when (fx> idx 0) + (let ([str (output-port-buffer port)]) + (when (fx= idx (string-length str)) + (set-output-port-fd! port + (cons str (output-port-fd port))) + (set-output-port-buffer! port + (make-string (string-length str))) + (set-output-port-index! port 0))))))) + (define fd-close-proc + (lambda (port) + (let ([idx (output-port-index port)]) + (when (fx> idx 0) + (foreign-call "ik_write" + (output-port-fd port) + idx + (output-port-buffer port)))) + (foreign-call "ik_close" (output-port-fd port)))) + + (define flush-output-port + (lambda (port) + (unless (output-port-open? port) + (error 'flush-output-port "port ~s closed" port)) + ((output-port-flush-proc port) port))) + (define close-output-port + (lambda (port) + (when (output-port-open? port) + ((output-port-close-proc port) port) + (set-output-port-open?! port #f)))) + + ;;; init section + (primitive-set! 'close-output-port + (case-lambda + [() (close-output-port (current-output-port))] + [(p) + (unless (output-port? p) + (error 'close-output-port "~s is not an output port" p)) + (close-output-port p)])) + (primitive-set! 'output-port? output-port?) + (primitive-set! 'open-output-file + (case-lambda + [(filename) (open-output-file filename 'error)] + [(filename mode) (open-output-file filename mode)])) + (primitive-set! 'write-char + (case-lambda + [(c) (write-char c (current-output-port))] + [(c p) + (unless (output-port? p) + (error 'write-char "~s is not an output port" p)) + (write-char c p)])) + (primitive-set! 'flush-output-port + (case-lambda + [() (flush-output-port (current-output-port))] + [(p) + (unless (output-port? p) + (error 'flush-output-port "~s is not an output port" p)) + (flush-output-port p)])) + (primitive-set! 'standard-output-port + (let ([p (fd->port 1 '*stdout*)]) + (lambda () p))) + (primitive-set! 'standard-error-port + (let ([p (fd->port 2 '*stderr*)]) + (lambda () p))) + (primitive-set! 'current-output-port + (make-parameter (standard-output-port) + (lambda (p) + (unless (output-port? p) + (error 'current-output-port "not a port ~s" p)) + p))) + (primitive-set! 'console-output-port + (make-parameter (standard-output-port) + (lambda (p) + (unless (output-port? p) + (error 'console-output-port "not a port ~s" p)) + p))) + (primitive-set! 'newline + (case-lambda + [() (write-char #\newline (current-output-port))] + [(p) + (unless (output-port? p) + (error 'newline "~s is not an output port" p)) + (write-char #\newline p)])) + + (primitive-set! 'open-output-string open-output-string) + (primitive-set! 'get-output-string get-output-string) + (primitive-set! 'output-port-name + (lambda (x) + (if (output-port? x) + (output-port-name x) + (error 'output-port-name "~s is not an output port" x))))) + +;;; INPUT PORTS + +(let () + ;;; input ports are similar to output ports, with the exception of + ;;; the ungetchar buffer + ;;; Fields: + ;;; 0. id + ;;; 1. file-name + ;;; 2. file-descriptor + ;;; 3. open? + ;;; 4. buffer + ;;; 5. buffer-size + ;;; 6. index + ;;; 7. unget + (define-record input-port + (name fd open? buffer size index returned-char)) + (define fd->port + (lambda (fd filename) + (make-input-port filename fd #t (make-string 4096) 0 0 #f))) + (define open-input-file + (lambda (filename) + (unless (string? filename) + (error 'open-input-file "not a string: ~s" filename)) + (let ([fd (foreign-call "ik_open_file" filename 4)]) + (fd->port fd filename)))) + (define close-input-port + (lambda (port) + (foreign-call "ik_close" (input-port-fd port)) + (set-input-port-open?! port #f) + (set-input-port-returned-char! port #f) + (set-input-port-index! port (input-port-size port)))) + (define read-char + (lambda (port) + (if (input-port-returned-char port) + (let ([c (input-port-returned-char port)]) + (set-input-port-returned-char! port #f) + c) + (let ([index (input-port-index port)]) + (if ($fx< index (input-port-size port)) + (begin + (set-input-port-index! port ($fxadd1 index)) + ($string-ref (input-port-buffer port) index)) + (if (input-port-open? port) + (let* ([buffer (input-port-buffer port)] + [bytes + (foreign-call "ik_read" + (input-port-fd port) + buffer + ($string-length buffer))]) + (set-input-port-size! port bytes) + (if ($fxzero? bytes) + (begin + (set-input-port-index! port 0) + (eof-object)) + (let ([c ($string-ref buffer 0)]) + (set-input-port-index! port 1) + c))) + (error 'read-char "input port ~s is not open" port))))))) + (define peek-char + (lambda (port) + (unless (input-port-open? port) + (error 'peek-char "port closed")) + (cond + [(input-port-returned-char port) => + (lambda (c) c)] + [else + (let ([idx (input-port-index port)] + [size (input-port-size port)] + [buf (input-port-buffer port)]) + (if (fx< idx size) + (string-ref buf idx) + (let ([bytes + (foreign-call "ik_read" + (input-port-fd port) + buf + ($string-length buf))]) + (set-input-port-size! port bytes) + (set-input-port-index! port 0) + (if (fxzero? bytes) + (eof-object) + (string-ref buf 0)))))]))) + (define reset-input-port! + (lambda (p) + (unless (input-port? p) + (error 'reset-input-port! "~s is not an input port" p)) + (set-input-port-index! p 0) + (set-input-port-size! p 0) + (set-input-port-returned-char! p #f))) + (define unread-char + (lambda (c port) + (unless (char? c) + (error 'unread-char "not a character ~s" c)) + (unless (input-port-open? port) + (error 'unread-char "port closed")) + (when (input-port-returned-char port) + (error 'unread-char "cannot unread twice")) + (set-input-port-returned-char! port c))) + (define *current-input-port* #f) + (primitive-set! 'open-input-file open-input-file) + (primitive-set! 'close-input-port + (case-lambda + [() (close-input-port *current-input-port*)] + [(p) + (unless (input-port? p) + (error 'close-input-port "~s is not an input port" p)) + (close-input-port p)])) + (primitive-set! 'input-port? input-port?) + (primitive-set! 'read-char + (case-lambda + [() (read-char *current-input-port*)] + [(p) (if (input-port? p) + (read-char p) + (error 'read-char "~s is not an input-port" p))])) + (primitive-set! 'peek-char + (case-lambda + [() (peek-char *current-input-port*)] + [(p) + (unless (input-port? p) + (error 'peek-char "~s is not an input port" p)) + (peek-char p)])) + (primitive-set! 'unread-char + (case-lambda + [(c) (unread-char c *current-input-port*)] + [(c p) + (unless (input-port? p) + (error 'unread-char "~s is not an input port" p)) + (unread-char c p)])) + (primitive-set! 'standard-input-port + (let ([p (fd->port 0 '*stdin*)]) + (lambda () p))) + (set! *current-input-port* (standard-input-port)) + (primitive-set! 'current-input-port + (case-lambda + [() *current-input-port*] + [(x) (if (input-port? x) + (set! *current-input-port* x) + (error 'current-input-port "~s is not an input port" x))])) + (primitive-set! 'console-input-port + (make-parameter (standard-input-port) + (lambda (x) + (unless (input-port? x) + (error 'console-input-port "not an input port ~s" x)) + x))) + (primitive-set! 'input-port-name + (lambda (x) + (if (input-port? x) + (input-port-name x) + (error 'input-port-name "~s is not an input port" x)))) + (primitive-set! 'reset-input-port! reset-input-port!)) + +(primitive-set! 'with-output-to-file + (lambda (name proc . args) + (unless (string? name) + (error 'with-output-to-file "~s is not a string" name)) + (unless (procedure? proc) + (error 'with-output-to-file "~s is not a procedure" proc)) + (let ([p (apply open-output-file name args)] + [shot #f]) + (parameterize ([current-output-port p]) + (dynamic-wind + (lambda () + (when shot + (error 'with-output-to-file + "cannot reenter"))) + proc + (lambda () + (close-output-port p) + (set! shot #t))))))) + +(primitive-set! 'call-with-output-file + (lambda (name proc . args) + (unless (string? name) + (error 'call-with-output-file "~s is not a string" name)) + (unless (procedure? proc) + (error 'call-with-output-file "~s is not a procedure" proc)) + (let ([p (apply open-output-file name args)] + [shot #f]) + (dynamic-wind + (lambda () + (when shot + (error 'call-with-output-file "cannot reenter"))) + (lambda () (proc p)) + (lambda () + (close-output-port p) + (set! shot #t)))))) + +(primitive-set! 'with-input-from-file + (lambda (name proc . args) + (unless (string? name) + (error 'with-input-from-file "~s is not a string" name)) + (unless (procedure? proc) + (error 'with-input-from-file "~s is not a procedure" proc)) + (let ([p (apply open-input-file name args)] + [shot #f]) + (parameterize ([current-input-port p]) + (dynamic-wind + (lambda () + (when shot + (error 'with-input-from-file + "cannot reenter"))) + proc + (lambda () + (close-input-port p) + (set! shot #t))))))) + +(primitive-set! 'call-with-input-file + (lambda (name proc . args) + (unless (string? name) + (error 'call-with-input-file "~s is not a string" name)) + (unless (procedure? proc) + (error 'call-with-input-file "~s is not a procedure" proc)) + (let ([p (apply open-input-file name args)] + [shot #f]) + (dynamic-wind + (lambda () + (when shot + (error 'call-with-input-file "cannot reenter"))) + (lambda () (proc p)) + (lambda () + (close-input-port p) + (set! shot #t)))))) + diff --git a/src/libio.fasl b/src/libio.fasl index c5205dd..da36080 100644 Binary files a/src/libio.fasl and b/src/libio.fasl differ diff --git a/src/libnumerics-7.1.ss b/src/libnumerics-7.1.ss new file mode 100644 index 0000000..26d081c --- /dev/null +++ b/src/libnumerics-7.1.ss @@ -0,0 +1,53 @@ + +(let () + (define (generic+ a b) + (cond + [(fixnum? a) + (cond + [(fixnum? b) (foreign-call "iknum_add_fx_fx" a b)] + [(bignum? b) (foreign-call "iknum_add_fx_bn" a b)] + [else (error '+ "~s is not a number" b)])] + [(bignum? a) + (cond + [(fixnum? b) (foreign-call "iknum_add_fx_bn" b a)] + [(bignum? b) (foreign-call "iknum_add_bn_bn" a b)] + [else (error '+ "~s is not a number" b)])] + [else (error '+ "~s is not a number" a)])) + + (primitive-set! '+ + (case-lambda + [(a b) (generic+ a b)] + [(a b c) (generic+ a (generic+ b c))] + [(a) (if (number? a) a (error '+ "~s is not a number" a))] + [() 0] + [(a b . rest) + (let f ([a a] [b b] [rest rest]) + (generic+ a + (if (null? rest) + b + (f b ($car rest) ($cdr rest)))))])) + + (primitive-set! 'add1 + (lambda (a) + (cond + [(fixnum? a) + (if ($fx< a (most-positive-fixnum)) + ($fxadd1 a) + (foreign-call "iknum_add_fx_fx" a 1))] + [(bignum? a) + (foreign-call "iknum_add_fx_bn" 1 a)] + [else (error 'add1 "~s is not a number" a)]))) + + (primitive-set! 'sub1 + (lambda (a) + (cond + [(fixnum? a) + (if ($fx> a (most-negative-fixnum)) + ($fxsub1 a) + (foreign-call "iknum_add_fx_fx" a -1))] + [(bignum? a) + (foreign-call "iknum_add_fx_bn" -1 a)] + [else (error 'add1 "~s is not a number" a)]))) + + ) + diff --git a/src/librecord-6.4.ss b/src/librecord-6.4.ss new file mode 100644 index 0000000..bae25c7 --- /dev/null +++ b/src/librecord-6.4.ss @@ -0,0 +1,254 @@ + + + +(let () + + (define rtd? + (lambda (x) + (and ($record? x) + (eq? ($record-rtd x) $base-rtd)))) + + (define rtd-name + (lambda (rtd) + ($record-ref rtd 0))) + + (define rtd-length + (lambda (rtd) + ($record-ref rtd 1))) + + (define rtd-fields + (lambda (rtd) + ($record-ref rtd 2))) + + (define rtd-printer + (lambda (rtd) + ($record-ref rtd 3))) + + (define rtd-symbol + (lambda (rtd) + ($record-ref rtd 4))) + + (define set-rtd-name! + (lambda (rtd name) + ($record-set! rtd 0 name))) + + (define set-rtd-length! + (lambda (rtd n) + ($record-set! rtd 1 n))) + + (define set-rtd-fields! + (lambda (rtd fields) + ($record-set! rtd 2 fields))) + + (define set-rtd-printer! + (lambda (rtd printer) + ($record-set! rtd 3 printer))) + + (define set-rtd-symbol! + (lambda (rtd symbol) + ($record-set! rtd 4 symbol))) + + (define make-rtd + (lambda (name fields printer symbol) + (let ([rtd ($make-record $base-rtd 5)]) + ($record-set! rtd 0 name) + ($record-set! rtd 1 (length fields)) + ($record-set! rtd 2 fields) + ($record-set! rtd 3 printer) + ($record-set! rtd 4 symbol) + rtd))) + + (define verify-field + (lambda (x) + (unless (symbol? x) + (error 'make-record-type "~s is not a valid field name" x)))) + + (define set-fields + (lambda (r f* i n) + (cond + [(null? f*) + (if ($fx= i n) + r + #f)] + [($fx< i n) + (if (null? f*) + #f + (begin + ($record-set! r i ($car f*)) + (set-fields r ($cdr f*) ($fxadd1 i) n)))] + [else #f]))) + + (define make-record-type + (lambda (name fields) + (unless (string? name) + (error 'make-record-type "name must be a string, got ~s" name)) + (unless (list? fields) + (error 'make-record-type "fields must be a list, got ~s" fields)) + (for-each verify-field fields) + (make-rtd name fields #f (gensym name)))) + + + (define record-type-name + (lambda (rtd) + (unless (rtd? rtd) + (error 'record-type-name "~s is not an rtd" rtd)) + (rtd-name rtd))) + + + (define record-type-symbol + (lambda (rtd) + (unless (rtd? rtd) + (error 'record-type-symbol "~s is not an rtd" rtd)) + (rtd-symbol rtd))) + + (define record-type-field-names + (lambda (rtd) + (unless (rtd? rtd) + (error 'record-type-field-names "~s is not an rtd" rtd)) + (rtd-fields rtd))) + + + (define record-constructor + (lambda (rtd) + (unless (rtd? rtd) + (error 'record-constructor "~s is not an rtd")) + (lambda args + (let ([n (rtd-length rtd)]) + (let ([r ($make-record rtd n)]) + (or (set-fields r args 0 n) + (error 'record-constructor + "incorrect number of arguments to the constructor of ~s" + rtd))))))) + + (define record-predicate + (lambda (rtd) + (unless (rtd? rtd) + (error 'record-predicate "~s is not an rtd")) + (lambda (x) + (and ($record? x) + (eq? ($record-rtd x) rtd))))) + + (define field-index + (lambda (i rtd who) + (cond + [(fixnum? i) + (unless (and ($fx>= i 0) ($fx< i (rtd-length rtd))) + (error who "~s is out of range for rtd ~s" rtd)) + i] + [(symbol? i) + (letrec ([lookup + (lambda (n ls) + (cond + [(null? ls) + (error who "~s is not a field in ~s" rtd)] + [(eq? i ($car ls)) n] + [else (lookup ($fx+ n 1) ($cdr ls))]))]) + (lookup 0 (rtd-fields rtd)))] + [else (error who "~s is not a valid index" i)]))) + + (define record-field-accessor + (lambda (rtd i) + (unless (rtd? rtd) + (error 'record-field-accessor "~s is not an rtd" rtd)) + (let ([i (field-index i rtd 'record-field-accessor)]) + (lambda (x) + (unless (and ($record? x) + (eq? ($record-rtd x) rtd)) + (error 'record-field-accessor "~s is not of type ~s" x rtd)) + ($record-ref x i))))) + + (define record-field-mutator + (lambda (rtd i) + (unless (rtd? rtd) + (error 'record-field-mutator "~s is not an rtd" rtd)) + (let ([i (field-index i rtd 'record-field-mutator)]) + (lambda (x v) + (unless (and ($record? x) + (eq? ($record-rtd x) rtd)) + (error 'record-field-mutator "~s is not of type ~s" x rtd)) + ($record-set! x i v))))) + + (define record? + (lambda (x . rest) + (if (null? rest) + ($record? x) + (let ([rtd ($car rest)]) + (unless (null? ($cdr rest)) + (error 'record? "too many arguments")) + (unless (rtd? rtd) + (error 'record? "~s is not an rtd")) + (and ($record? x) + (eq? ($record-rtd x) rtd)))))) + + (define record-rtd + (lambda (x) + (if ($record? x) + ($record-rtd x) + (error 'record-rtd "~s is not a record" x)))) + + (define record-length + (lambda (x) + (if ($record? x) + (rtd-length ($record-rtd x)) + (error 'record-length "~s is not a record" x)))) + + (define record-name + (lambda (x) + (if ($record? x) + (rtd-name ($record-rtd x)) + (error 'record-name "~s is not a record" x)))) + + (define record-printer + (lambda (x) + (if ($record? x) + (rtd-printer ($record-rtd x)) + (error 'record-printer "~s is not a record" x)))) + + (define record-ref + (lambda (x i) + (unless ($record? x) (error 'record-ref "~s is not a record" x)) + (unless (fixnum? i) (error 'record-ref "~s is not a valid index" i)) + (let ([n (rtd-length ($record-rtd x))]) + (unless (and ($fx>= i 0) ($fx< i n)) + (error 'record-ref "index ~s is out of range for ~s" i x)) + ($record-ref x i)))) + + (define record-set! + (lambda (x i v) + (unless ($record? x) (error 'record-set! "~s is not a record" x)) + (unless (fixnum? i) (error 'record-set! "~s is not a valid index" i)) + (let ([n (rtd-length ($record-rtd x))]) + (unless (and ($fx>= i 0) ($fx< i n)) + (error 'record-set! "index ~s is out of range for ~s" i x)) + ($record-set! x i v)))) + + (primitive-set! 'make-record-type make-record-type) + (primitive-set! 'record-type-name record-type-name) + (primitive-set! 'record-type-symbol record-type-symbol) + (primitive-set! 'record-type-field-names record-type-field-names) + (primitive-set! 'record-constructor record-constructor) + (primitive-set! 'record-predicate record-predicate) + (primitive-set! 'record-field-accessor record-field-accessor) + (primitive-set! 'record-field-mutator record-field-mutator) + + (primitive-set! 'record? record?) + (primitive-set! 'record-rtd record-rtd) + (primitive-set! 'record-type-descriptor record-rtd) + (primitive-set! 'record-name record-name) + (primitive-set! 'record-printer record-printer) + (primitive-set! 'record-length record-length) + (primitive-set! 'record-ref record-ref) + (primitive-set! 'record-set! record-set!) + + (set-rtd-fields! $base-rtd '(name fields length printer symbol)) + (set-rtd-name! $base-rtd "base-rtd") + (set-rtd-printer! $base-rtd + (lambda (x p) + (unless (rtd? x) + (error 'record-type-printer "not an rtd")) + (display "#<" p) + (display (rtd-name x) p) + (display " rtd>" p))) + + ) + diff --git a/src/librecord.fasl b/src/librecord.fasl index f307aef..e69de29 100644 Binary files a/src/librecord.fasl and b/src/librecord.fasl differ diff --git a/src/libsyncase-6.2.ss b/src/libsyncase-6.2.ss deleted file mode 100644 index 02fcc6e..0000000 --- a/src/libsyncase-6.2.ss +++ /dev/null @@ -1,534 +0,0 @@ - -;;; 6.2: initial syncase implementation -;;; - - -;;; Expand : Scheme -> Core Scheme -;;; -;;; ::= (quote datum) -;;; | -;;; | (if ) -;;; | (set! ) -;;; | (begin ...) -;;; | (letrec ([ ] ...) ...) -;;; | (lambda ...) -;;; | ( ...) -;;; | (#primitive| ) -;;; | ( ...) -;;; ::= () -;;; | -;;; | ( . ) -;;; ::= void | memv | top-level-value | set-top-level-value! -;;; | primitive-set! | foreign-call | $apply - -(let ([*stx* (make-record-type "*stx*" '(e marks ribcage))] - [*rib* (make-record-type "*rib*" '(sym* marks* lab*))] - [*top* (make-record-type "*top*" '())]) - - (define stx? (record-predicate *stx*)) - (define make-stx (record-constructor *stx*)) - (define stx-e (record-field-accessor *stx* 'e)) - (define stx-marks (record-field-accessor *stx* 'marks)) - (define stx-ribcage (record-field-accessor *stx* 'ribcage)) - (define make-rib (record-constructor *rib*)) - (define rib-sym* (record-field-accessor *rib* 'sym*)) - (define rib-marks* (record-field-accessor *rib* 'marks*)) - (define rib-lab* (record-field-accessor *rib* 'lab*)) - (define *top-ribcage* ((record-constructor *top*))) - (define (top? x) (eq? x *top-ribcage*)) - (define *syncase-macro* (gensym "*syncase-macro*")) - - (define (build-data x) `(quote ,x)) - (define (build-global-ref x) `(top-level-value ',x)) - (define (build-lexical-ref x) x) - (define (build-app a d) `(,a . ,d)) - (define (build-lambda fml* body) - (cond - [(and (pair? body) (eq? (car body) 'begin)) - `(lambda ,fml* . ,(cdr body))] - [else - `(lambda ,fml* ,body)])) - (define (build-begin body*) `(begin . ,body*)) - - - (define (build-void) `(void)) - (define (build-if e0 e1 e2) `(if ,e0 ,e1 ,e2)) - (define (build-foreign-call e e*) `(foreign-call ,e ,e*)) - - - - (define (id? x) - (and (stx? x) - (symbol? (stx-e x)))) - - (define (stx->datum x) ;;;; use strip - (cond - [(stx? x) (stx-e x)] - [else x])) - - (define (stx-pair? x) - (and (stx? x) - (pair? (stx-e x)))) - - (define (strip x) - (cond - [(stx? x) (stx-e x)] - [else x])) - - (define label? string?) - - (define (eqmarks? m1* m2*) - (cond - [(null? m1*) (null? m2*)] - [(memq (car m1*) m2*) (eqmarks? (cdr m1*) (remq (car m1*) m2*))] - [else #f])) - - (define (rib-lookup sym m* sym* m** lab*) - (and (pair? sym*) - (if (and (eq? sym (car sym*)) - (eqmarks? m* (car m**))) - (car lab*) - (rib-lookup sym m* (cdr sym*) (cdr m**) (cdr lab*))))) - - (define (ribcage-lookup sym m* rc) - (cond - [(pair? rc) - (let ([r (car rc)]) - (cond - [(eq? r 'shift) - (ribcage-lookup sym (cdr m*) (cdr rc))] - [else - (or (rib-lookup sym m* (rib-sym* r) (rib-marks* r) (rib-lab* r)) - (ribcage-lookup sym m* (cdr rc)))]))] - [(top? rc) #f] - [else (error "BUG1")])) - - (define (resolve x) - (unless (id? x) (error "BUG2")) - (let ([sym (stx-e x)] - [m* (stx-marks x)] - [rc (stx-ribcage x)]) - (or (ribcage-lookup sym m* rc) ; bound -> label - (getprop sym *syncase-macro*) ; top-level-macros -> pair - sym ; global -> symbol - ))) - - (define (remove-last ls) - (let ([d (cdr ls)]) - (cond - [(null? d) '()] - [else (cons (car ls) (remove-last d))]))) - - (define (unshift rc) - (cond - [(pair? rc) - (if (eq? (car rc) 'shift) - (cdr rc) - (cons (car rc) (unshift (cdr rc))))] - [else (error "BUG3: missing shift")])) - - (define (push-wrap m r x) - (cond - [(stx? x) - (let ([xm (stx-marks x)]) - (cond - [(and (pair? xm) (eq? (car xm) #f)) - (make-stx (stx-e x) - (append (remove-last m) (cdr xm)) - (unshift (append r (stx-ribcage x))))] - [else - (make-stx (stx-e x) - (append m xm) - (append r (stx-ribcage x)))]))] - [else (make-stx x m r)])) - - (define (push-subst sym* marks* lab* x) - (cond - [(stx? x) - (make-stx (stx-e x) - (stx-marks x) - (cons (make-rib sym* marks* lab*) (stx-ribcage x)))] - [else - (make-stx x - '() - (cons (make-rib sym* marks* lab*) '()))])) - - (define (push-antimark x) - (cond - [(stx? x) - (make-stx (stx-e x) - (cons #f (stx-marks x)) - (stx-ribcage x))] - [else (make-stx x (cons #f '()) '())])) - - (define (push-mark m x) - (cond - [(stx? x) - (let ([m* (stx-marks x)]) - (cond - [(and (pair? m*) (eq? (car m*) #f)) - (make-stx (stx-e x) (cdr m*) (stx-ribcage x))] - [else - (make-stx (stx-e x) (cons m m*) (cons 'shift (stx-ribcage x)))]))] - [else - (make-stx x (list m) '(shift))])) - - (define (push-rib rib x) - (cond - [(stx? x) - (make-stx (stx-e x) (stx-marks x) (cons rib (stx-ribcage x)))] - [else (make-stx x '() (list rib))])) - - (define (expose-stx x) - (let ([e (stx-e x)]) - (cond - [(pair? e) - (let ([m (stx-marks x)] - [r (stx-ribcage x)]) - (cons - (push-wrap m r (car e)) - (push-wrap m r (cdr e))))] - [(vector? e) - (let ([m (stx-marks x)] - [r (stx-ribcage x)]) - (list->vector - (map (lambda (x) (push-wrap m r x)) - (vector->list e))))] - [(null? e) e] - [else x]))) - - (define (expose x) - (cond - [(stx? x) (expose-stx x)] - [else x])) - - (define (expose-ls ox) - (let loop ([x (expose ox)]) - (cond - [(pair? x) (cons (car x) (loop (expose (cdr x))))] - [(null? x) '()] - [else (error 'expose-ls "BUG: not a list: ~s" x)]))) - - (define (expose* x) - (cond - [(id? x) x] - [(stx? x) (expose* (expose x))] - [(pair? x) (cons (expose* (car x)) (expose* (cdr x)))] - [(vector? x) - (list->vector (map expose* (vector->list x)))] - [else x])) - - (define (lookup lab r) - (define (lookup1 lab lab* g*) - (cond - [(null? lab*) #f] - [(eq? lab (car lab*)) (car g*)] - [else (lookup1 lab (cdr lab*) (cdr g*))])) - (cond - [(null? r) #f] - [(eq? (car r) 'lexical-barrier) - (let ([v (lookup lab (cdr r))]) - (cond - [(not (symbol? v)) v] - [else #f]))] - [else - (or (lookup1 lab (caar r) (cdar r)) - (lookup lab (cdr r)))])) - - (define (genmark) (gensym "M")) - (define (newsym x) - (gensym)) - ;(gensym (symbol->string x))) - - (define (apply-macro proc x r) - (expand-ctx (push-mark (genmark) (proc (push-antimark x))) r)) - - (define (identifier-macro? x r) - (and (id? x) - (let ([a (resolve x)]) - (or (and (label? a) - (let ([a (lookup a r)]) - (and (procedure? a) a))) - (and (pair? a) - (eq? (car a) '*user-macro*) - (cdr a)))))) - - (define (macro-call? x r) - (if (id? x) - (identifier-macro? x r) - (let ([x (expose x)]) - (and (pair? x) - (identifier-macro? (car x) r))))) - - (define (core? x) - (and (pair? x) (eq? (car x) '*core-macro*))) - - (define (apply-core-form a d ctx r) - (unless (core? a) (syntax-error ctx)) - ((cdr a) a d ctx r)) - - (define (E* d r ctx) - (let ([d (expose-ls d)]) - (map (lambda (x) (E x r)) d))) - - (define (extend-core name proc) - (putprop name *syncase-macro* (cons '*core-macro* proc))) - - (define (extend-user-macro name proc) - (putprop name *syncase-macro* (cons '*user-macro* proc))) - - (define (E ctx r) - (let ([x (expose ctx)]) - (cond - [(macro-call? x r) => - (lambda (proc) - (apply-macro proc ctx r))] - [(pair? x) - (let ([a (car x)] [d (cdr x)]) - (cond - [(id? a) - (let ([a (resolve a)]) - (cond - [(label? a) - (cond - [(lookup a r) => - (lambda (g) - (cond - [(symbol? g) - (build-app (build-lexical-ref g) - (E* d r ctx))] - [(and (pair? g) (eq? (car g) 'pat)) - (syntax-error ctx)] - [else (error 'expand "BUG4")]))] - [else (syntax-error ctx)])] - [(core? a) - (apply-core-form a d ctx r)] - [(symbol? a) - (build-app (build-global-ref a) - (E* d r ctx))] - [else (syntax-error ctx)]))] - [else - (build-app - (E a r) - (E* d r ctx))]))] - [(id? x) - (let ([a (resolve x)]) - (cond - [(label? a) - (cond - [(lookup a r) => - (lambda (g) - (cond - [(symbol? g) (build-lexical-ref g)] - [(and (pair? g) (eq? (car g) 'pat)) - (syntax-error ctx)] - [else (error 'expand "BUG5")]))] - [else (syntax-error ctx)])] - [(core? a) (syntax-error ctx)] - [(symbol? a) - (build-global-ref a)] - [else (syntax-error ctx)]))] - [else (build-data (strip x))]))) - - (define (core-expand x) - (E (make-stx x '() *top-ribcage*) '())) - - (define (process-fml* bind* ctx) - (define (assert-no-dups s m* s* m**) - (unless (null? s*) - (when (and (eq? s (car s*)) - (eqmarks? m* (car m**))) - (syntax-error ctx)) - (assert-no-dups s m* (cdr s*) (cdr m*)))) - (let loop ([bind* (expose bind*)]) - (cond - [(null? bind*) (values '() '() '() '() '())] - [(pair? bind*) - (let ([b (car bind*)]) - (unless (id? b) (syntax-error ctx)) - (let-values ([(fml* s* m** g* lab*) - (loop (expose (cdr bind*)))]) - (let ([s (stx-e b)] [m* (stx-marks b)]) - (assert-no-dups s m* s* m**) - (let ([lab (string #\i)] [g (newsym s)]) - (values (cons g fml*) - (cons s s*) - (cons m* m**) - (cons g g*) - (cons lab lab*))))))] - [else (syntax-error ctx)]))) - - (define (top-level-macro? x r sym) - (let ([x (expose x)]) - (and (pair? x) - (id? (car x)) - (let ([loc (resolve (car x))]) - (and (or (and (pair? loc) - (eq? (car loc) '*core-macro*)) - (symbol? loc)) - (eq? (stx->datum (car x)) sym)))))) - - (define (define? x r) - (top-level-macro? x r 'define)) - - (define (begin? x r) - (top-level-macro? x r 'begin)) - - (define (begin-e* x ctx) - (let ([x (expose x)]) - (let loop ([x (expose (cdr x))]) - (cond - [(null? x) '()] - [(pair? x) (cons (car x) (loop (expose (cdr x))))] - [else (syntax-error ctx)])))) - - (define (expand-body* body* ctx r) - (let ([rib (make-rib '() '() '())]) - (let loop ([body* (expose (push-rib rib body*))] - [r r] - [lab* '()] [sym* '()] [marks* '()] [vrhs* '()]) - (cond - [(null? body*) (syntax-error ctx)] - [(pair? body*) - (let ([a (car body*)] [d (cdr body*)]) - (cond - [(macro-call? a r) => - (lambda (proc) - (loop (cons (push-mark (genmark) (proc (push-antimark a))) d) - r lab* sym* marks* vrhs*))] - [(define? a r) - (let-values ([(lhs rhs) (extract-define a ctx)]) - (loop (expose d) - r - (cons (string #\p) lab*) - (cons (stx-e lhs) sym*) - (cons (stx-marks lhs) marks*) - (cons rhs vrhs*)))] - [(begin? a r) - (loop (expose (append (begin-e* a ctx) d)) - r lab* sym* marks* vrhs*)] - [else - ;;; done - (cond - [(null? sym*) - (let ([body* (E* body* r ctx)]) - (build-begin body*))] - [else - (let ([g* (map newsym sym*)]) - (let* ([r (cons (cons lab* g*) r)] - [rhs* - (E* (push-subst sym* marks* lab* vrhs*) - r ctx)] - [body* - (E* (push-subst sym* marks* lab* body*) - r ctx)]) - (build-letrec g* rhs* (build-begin body*))))])]))] - [else (syntax-error ctx)])))) - - (define (extract-bindings bind* ctx) - (let ([bind* (expose bind*)]) - (cond - [(null? bind*) (values '() '())] - [(not (pair? bind*)) (syntax-error ctx)] - [else - (let ([a (car bind*)] [d (cdr bind*)]) - (let ([a (expose-ls a)]) - (cond - [(fx= (length a) 2) - (let-values ([(lhs* rhs*) - (extract-bindings d ctx)]) - (values (cons (car a) lhs*) - (cons (cadr a) rhs*)))] - [else (syntax-error ctx)])))]))) - - (define (core-stx x) - (make-stx x '() *top-ribcage*)) - - (extend-core 'quote - (lambda (a d ctx r) - (let ([d (expose-ls d)]) - (cond - [(and (list? d) (fx= (length d) 1)) - (build-data (strip (car d)))] - [else (syntax-error ctx)])))) - - (extend-core 'lambda - (lambda (a d ctx r) - (let ([d (expose d)]) - (cond - [(pair? d) - (let ([fml* (car d)] [body* (cdr d)]) - (let-values ([(fml* s* m** g* lab*) - (process-fml* fml* ctx)]) - (let ([body* (push-subst s* m** lab* body*)]) - (let ([r (cons (cons lab* g*) r)]) - (build-lambda fml* - (expand-body* body* ctx r))))))] - [else (syntax-error ctx)])))) - - (extend-core 'if - (lambda (a d ctx r) - (let ([d (expose d)]) - (unless (pair? d) (syntax-error ctx)) - (let ([test (car d)] [d (expose (cdr d))]) - (unless (pair? d) (syntax-error ctx)) - (let ([conseq (car d)] [d (expose (cdr d))]) - (let ([altern - (cond - [(null? d) (build-void)] - [(pair? d) - (let ([altern (car d)] [d (expose (cdr d))]) - (cond - [(null? d) (E altern r)] - [else (syntax-error ctx)]))] - [else (syntax-error ctx)])]) - (build-if (E test r) (E conseq r) altern))))))) - - (extend-core 'begin - (lambda (a d ctx r) - (let ([d (expose-ls d)]) - (when (null? d) (syntax-error ctx)) - (build-begin (E* d r ctx))))) - - - (extend-core 'define - (lambda (a d ctx r) (syntax-error ctx))) - - (extend-core 'foreign-call - (lambda (a d ctx r) - (let ([d (expose-ls d)]) - (unless (fx>= (length d) 1) (syntax-error ctx)) - (build-foreign-call - (E (car d) r) - (E* (cdr d) r ctx))))) - - (extend-core 'let - (lambda (a d ctx r) - (let ([d (expose d)]) - (unless (pair? d) (syntax-error ctx)) - (let ([bind* (car d)] [body* (cdr d)]) - (let-values ([(lhs* rhs*) - (extract-bindings bind* ctx)]) - (let ([lambda^ (core-stx 'lambda)]) - (E `((,lambda^ ,lhs* . ,body*) . ,rhs*) r))))))) - - (extend-core 'let* - (lambda (a d ctx r) - (let ([d (expose d)]) - (unless (pair? d) (syntax-error ctx)) - (let ([bind* (car d)] [body* (cdr d)]) - (let-values ([(lhs* rhs*) - (extract-bindings bind* ctx)]) - (let ([lambda^ (core-stx 'lambda)]) - (E (let f ([lhs* lhs*] [rhs* rhs*]) - (cond - [(null? lhs*) - `((,lambda^ () . ,body*))] - [else - `((,lambda^ (,(car lhs*)) - ,(f (cdr lhs*) (cdr rhs*))) - ,(car rhs*))])) - r))))))) - - (set! expand core-expand) -) diff --git a/src/libtokenizer.fasl b/src/libtokenizer.fasl index 3ef1482..6060fa1 100644 Binary files a/src/libtokenizer.fasl and b/src/libtokenizer.fasl differ diff --git a/src/libtoplevel-6.9.ss b/src/libtoplevel-6.9.ss new file mode 100644 index 0000000..5be0b17 --- /dev/null +++ b/src/libtoplevel-6.9.ss @@ -0,0 +1,61 @@ + +(for-each + (lambda (x) + ($set-symbol-value! x (primitive-ref x))) + (public-primitives)) + +(let () + (define add-prim + (lambda (x) + (let ([g (gensym (symbol->string x))]) + (putprop x '|#system| g) + (putprop g '*sc-expander* (cons 'core-primitive x))))) + (for-each add-prim (public-primitives)) + (for-each add-prim (system-primitives))) + +(for-each + (lambda (x) + (cond + [(getprop x '*sc-expander*) => + (lambda (p) + (let ([g (gensym (symbol->string x))]) + (putprop x '|#system| g) + (putprop g '*sc-expander* p)))] + [(getprop x '|#system|) => + (lambda (g) + (let ([p (getprop g '*sc-expander*)]) + (putprop x '*sc-expander* p)))] + [else (error #f "~s is not a macro" x)])) + (macros)) + +(let ([gsys (gensym "#system")] [gsch (gensym "*scheme*")]) + (define (make-stx x) + (vector 'syntax-object x + (list '(top) + (vector 'ribcage + (vector x) + (vector '(top)) + (vector (getprop x '|#system|)))))) + (define (make-module stx* name) + `($module . #(interface (top) ,(list->vector stx*) ,name))) + (putprop '|#system| '|#system| gsys) + (putprop 'scheme '|#system| gsch) + (putprop 'scheme '*scheme* gsch) + (let* ([schls (append '(scheme) (public-primitives) (macros))] + [sysls (append '(|#system|) (system-primitives) schls)]) + (let ([sysmod (make-module (map make-stx sysls) '|#system|)] + [schmod (make-module (map make-stx schls) '*scheme*)]) + (for-each + (lambda (x) + (putprop x '*scheme* (getprop x '|#system|))) + schls) + (putprop gsch '*sc-expander* schmod) + (putprop gsys '*sc-expander* sysmod) + (putprop '|#system| '*sc-expander* sysmod) + (putprop 'scheme '*sc-expander* schmod)))) + +(begin + (printf "Petite Ikarus Scheme (Build ~a)\n" (compile-time-date-string)) + (display "Copyright (c) 2006 Abdulaziz Ghuloum\n\n") + (current-eval compile) + (new-cafe)) diff --git a/src/libtoplevel.fasl b/src/libtoplevel.fasl index d25a608..c93904f 100644 Binary files a/src/libtoplevel.fasl and b/src/libtoplevel.fasl differ diff --git a/src/libtrace-6.9.ss b/src/libtrace-6.9.ss new file mode 100644 index 0000000..1b01788 --- /dev/null +++ b/src/libtrace-6.9.ss @@ -0,0 +1,89 @@ + +(let () + (define k* '()) + + (define display-prefix + (lambda (ls t) + (unless (null? ls) + (display (if t "|" " ")) + (display-prefix (cdr ls) (not t))))) + + (define display-trace + (lambda (k* v) + (display-prefix k* #t) + (write v) + (newline))) + + (define make-traced-procedure + (lambda (name proc) + (lambda args + (call/cf + (lambda (f) + (cond + [(memq f k*) => + (lambda (ls) + (display-trace ls (cons name args)) + (apply proc args))] + [else + (display-trace (cons 1 k*) (cons name args)) + (dynamic-wind + (lambda () (set! k* (cons f k*))) + (lambda () + (let ([v + (call/cf + (lambda (nf) + (set! f nf) + (set-car! k* nf) + (apply proc args)))]) + (display-trace k* v) + v)) + (lambda () (set! k* (cdr k*))))])))))) + + (define traced-symbols '()) + + (define trace-symbol! + (lambda (s) + (cond + [(assq s traced-symbols) => + (lambda (pr) + (let ([a (cdr pr)] [v (top-level-value s)]) + (unless (eq? (cdr a) v) + (unless (procedure? v) + (error 'trace + "the top-level value of ~s is ~s (not a procedure)" + s v)) + (let ([p (make-traced-procedure s v)]) + (set-car! a v) + (set-cdr! a p) + (set-top-level-value! s p)))))] + [else + (unless (top-level-bound? s) + (error 'trace "~s is unbound" s)) + (let ([v (top-level-value s)]) + (unless (procedure? v) + (error 'trace "the top-level value of ~s is ~s (not a procedure)" + s v)) + (let ([p (make-traced-procedure s v)]) + (set! traced-symbols + (cons (cons s (cons v p)) traced-symbols)) + (set-top-level-value! s p)))]))) + + (define untrace-symbol! + (lambda (s) + (define loop + (lambda (ls) + (cond + [(null? ls) '()] + [(eq? s (caar ls)) + (let ([a (cdar ls)]) + (when (eq? (cdr a) (top-level-value s)) + (set-top-level-value! s (car a))) + (cdr ls))] + [else (cons (car ls) (loop (cdr ls)))]))) + (set! traced-symbols (loop traced-symbols)))) + + (primitive-set! 'make-traced-procedure make-traced-procedure) + (primitive-set! 'trace-symbol! trace-symbol!) + (primitive-set! 'untrace-symbol! untrace-symbol!)) + + diff --git a/src/libwriter-6.2.ss b/src/libwriter-6.2.ss index 2f114f8..1dc06ca 100644 --- a/src/libwriter-6.2.ss +++ b/src/libwriter-6.2.ss @@ -308,13 +308,15 @@ (error 'fprintf "~s is not an output port" port)) (unless (string? fmt) (error 'fprintf "~s is not a string" fmt)) - (formatter 'fprintf port fmt args))) + (formatter 'fprintf port fmt args) + (flush-output-port port))) (define printf (lambda (fmt . args) (unless (string? fmt) (error 'printf "~s is not a string" fmt)) - (formatter 'printf (current-output-port) fmt args))) + (formatter 'printf (current-output-port) fmt args) + (flush-output-port (current-output-port)))) (define format (lambda (fmt . args) @@ -369,5 +371,6 @@ (error 'current-error-handler "~s is not a procedure" x))))) (primitive-set! 'error (lambda args - (apply (current-error-handler) args)))) + (apply (current-error-handler) args))) + ) diff --git a/src/libwriter.fasl b/src/libwriter.fasl index 05fb9ce..c6f70d2 100644 Binary files a/src/libwriter.fasl and b/src/libwriter.fasl differ diff --git a/src/message-case.ss b/src/message-case.ss new file mode 100644 index 0000000..4831666 --- /dev/null +++ b/src/message-case.ss @@ -0,0 +1,24 @@ + + +(define-syntax message-case + (syntax-rules (else) + [(_ msg args + [(msg-name msg-arg* ...) b b* ...] ... + [else else1 else2 ...]) + (let ([tmsg msg] [targs args]) + (define-syntax match-and-bind + (syntax-rules () + [(__ y () body) + (if (null? y) + body + (error 'message-case "unmatched ~s" (cons tmsg targs)))] + [(__ y (a a* (... ...)) body) + (if (pair? y) + (let ([a (car y)] [d (cdr y)]) + (match-and-bind d (a* (... ...)) body)) + (error 'message-case "unmatched ~s" (cons tmsg targs)))])) + (case tmsg + [(msg-name) + (match-and-bind targs (msg-arg* ...) (begin b b* ...))] ... + [else else1 else2 ...]))])) + diff --git a/src/petite-ikarus.fasl b/src/petite-ikarus.fasl deleted file mode 100644 index 35ae3ac..0000000 Binary files a/src/petite-ikarus.fasl and /dev/null differ diff --git a/src/psyntax-7.1-6.5.ss b/src/psyntax-7.1-6.5.ss new file mode 100644 index 0000000..d45f439 --- /dev/null +++ b/src/psyntax-7.1-6.5.ss @@ -0,0 +1,4613 @@ +;;; Portable implementation of syntax-case +;;; Extracted from Chez Scheme Version 7.1 (Aug 01, 2006) +;;; Authors: R. Kent Dybvig, Oscar Waddell, Bob Hieb, Carl Bruggeman + +;;; Copyright (c) 1992-2002 Cadence Research Systems +;;; Permission to copy this software, in whole or in part, to use this +;;; software for any lawful purpose, and to redistribute this software +;;; is granted subject to the restriction that all copies made of this +;;; software must include this copyright notice in full. This software +;;; is provided AS IS, with NO WARRANTY, EITHER EXPRESS OR IMPLIED, +;;; INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES OF MERCHANTABILITY +;;; OR FITNESS FOR ANY PARTICULAR PURPOSE. IN NO EVENT SHALL THE +;;; AUTHORS BE LIABLE FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES OF ANY +;;; NATURE WHATSOEVER. + +;;; Before attempting to port this code to a new implementation of +;;; Scheme, please read the notes below carefully. + +;;; This file defines the syntax-case expander, sc-expand, and a set +;;; of associated syntactic forms and procedures. Of these, the +;;; following are documented in The Scheme Programming Language, +;;; Third Edition (R. Kent Dybvig, MIT Press, 2003), which can be +;;; found online at http://www.scheme.com/tspl3/. Most are also documented +;;; in the R4RS and draft R5RS. +;;; +;;; bound-identifier=? +;;; datum->syntax-object +;;; define-syntax +;;; fluid-let-syntax +;;; free-identifier=? +;;; generate-temporaries +;;; identifier? +;;; identifier-syntax +;;; let-syntax +;;; letrec-syntax +;;; syntax +;;; syntax-case +;;; syntax-object->datum +;;; syntax-rules +;;; with-syntax +;;; +;;; All standard Scheme syntactic forms are supported by the expander +;;; or syntactic abstractions defined in this file. Only the R4RS +;;; delay is omitted, since its expansion is implementation-dependent. + +;;; Also defined are three forms that support modules: module, import, +;;; and import-only. These are documented in the Chez Scheme User's +;;; Guide (R. Kent Dybvig, Cadence Research Systems, 1998), which can +;;; also be found online at http://www.scheme.com/csug/. They are +;;; described briefly here as well. + +;;; All are definitions and may appear where and only where other +;;; definitions may appear. modules may be named: +;;; +;;; (module id (ex ...) defn ... init ...) +;;; +;;; or anonymous: +;;; +;;; (module (ex ...) defn ... init ...) +;;; +;;; The latter form is semantically equivalent to: +;;; +;;; (module T (ex ...) defn ... init ...) +;;; (import T) +;;; +;;; where T is a fresh identifier. +;;; +;;; In either form, each of the exports in (ex ...) is either an +;;; identifier or of the form (id ex ...). In the former case, the +;;; single identifier ex is exported. In the latter, the identifier +;;; id is exported and the exports ex ... are "implicitly" exported. +;;; This listing of implicit exports is useful only when id is a +;;; keyword bound to a transformer that expands into references to +;;; the listed implicit exports. In the present implementation, +;;; listing of implicit exports is necessary only for top-level +;;; modules and allows the implementation to avoid placing all +;;; identifiers into the top-level environment where subsequent passes +;;; of the compiler will be unable to deal effectively with them. +;;; +;;; Named modules may be referenced in import statements, which +;;; always take one of the forms: +;;; +;;; (import id) +;;; (import-only id) +;;; +;;; id must name a module. Each exported identifier becomes visible +;;; within the scope of the import form. In the case of import-only, +;;; all other identifiers become invisible in the scope of the +;;; import-only form, except for those established by definitions +;;; that appear textually after the import-only form. + +;;; import and import-only also support a variety of identifier +;;; selection and renaming forms: only, except, add-prefix, +;;; drop-prefix, rename, and alias. +;;; +;;; (import (only m x y)) +;;; +;;; imports x and y (and nothing else) from m. +;;; +;;; (import (except m x y)) +;;; +;;; imports all of m's imports except for x and y. +;;; +;;; (import (add-prefix (only m x y) m:)) +;;; +;;; imports x and y as m:x and m:y. +;;; +;;; (import (drop-prefix m foo:)) +;;; +;;; imports all of m's imports, dropping the common foo: prefix +;;; (which must appear on all of m's exports). +;;; +;;; (import (rename (except m a b) (m-c c) (m-d d))) +;;; +;;; imports all of m's imports except for x and y, renaming c +;;; m-c and d m-d. +;;; +;;; (import (alias (except m a b) (m-c c) (m-d d))) +;;; +;;; imports all of m's imports except for x and y, with additional +;;; aliases m-c for c and m-d for d. +;;; +;;; multiple imports may be specified with one import form: +;;; +;;; (import (except m1 x) (only m2 x)) +;;; +;;; imports all of m1's exports except for x plus x from m2. + +;;; Another form, meta, may be used as a prefix for any definition and +;;; causes any resulting variable bindings to be created at expansion +;;; time. Meta variables (variables defined using meta) are available +;;; only at expansion time. Meta definitions are often used to create +;;; data and helpers that can be shared by multiple macros, for example: + +;;; (module (alpha beta) +;;; (meta define key-error +;;; (lambda (key) +;;; (syntax-error key "invalid key"))) +;;; (meta define parse-keys +;;; (lambda (keys) +;;; (let f ((keys keys) (c #'white) (s 10)) +;;; (syntax-case keys (color size) +;;; (() (list c s)) +;;; (((color c) . keys) (f #'keys #'c s)) +;;; (((size s) . keys) (f #'keys c #'s)) +;;; ((k . keys) (key-error #'k)))))) +;;; (define-syntax alpha +;;; (lambda (x) +;;; (syntax-case x () +;;; ((_ (k ...) ) +;;; (with-syntax (((c s) (parse-keys (syntax (k ...))))) +;;; ---))))) +;;; (define-syntax beta +;;; (lambda (x) +;;; (syntax-case x () +;;; ((_ (k ...) ) +;;; (with-syntax (((c s) (parse-keys (syntax (k ...))))) +;;; ---)))))) + +;;; As with define-syntax rhs expressions, meta expressions can evaluate +;;; references only to identifiers whose values are (already) available +;;; in the compile-time environment, e.g., macros and meta variables. +;;; They can, however, like define-syntax rhs expressions, build syntax +;;; objects containing occurrences of any identifiers in their scope. + +;;; meta definitions propagate through macro expansion, so one can write, +;;; for example: +;;; +;;; (module (a) +;;; (meta define-structure (foo x)) +;;; (define-syntax a +;;; (let ((q (make-foo (syntax 'q)))) +;;; (lambda (x) +;;; (foo-x q))))) +;;; a -> q +;;; +;;; where define-record is a macro that expands into a set of defines. +;;; +;;; It is also sometimes convenient to write +;;; +;;; (meta begin defn ...) +;;; +;;; or +;;; +;;; (meta module {exports} defn ...) +;;; +;;; to create groups of meta bindings. + +;;; Another form, alias, is used to create aliases from one identifier +;;; to another. This is used primarily to support the extended import +;;; syntaxes (add-prefix, drop-prefix, rename, and alias). + +;;; (let ((x 3)) (alias y x) y) -> 3 + +;;; The remaining exports are listed below. sc-expand, eval-when, and +;;; syntax-error are described in the Chez Scheme User's Guide. +;;; +;;; (sc-expand datum) +;;; if datum represents a valid expression, sc-expand returns an +;;; expanded version of datum in a core language that includes no +;;; syntactic abstractions. The core language includes begin, +;;; define, if, lambda, letrec, quote, and set!. +;;; (eval-when situations expr ...) +;;; conditionally evaluates expr ... at compile-time or run-time +;;; depending upon situations +;;; (syntax-error object message) +;;; used to report errors found during expansion +;;; ($syntax-dispatch e p) +;;; used by expanded code to handle syntax-case matching +;;; ($sc-put-cte symbol val top-token) +;;; used to establish top-level compile-time (expand-time) bindings. + +;;; The following nonstandard procedures must be provided by the +;;; implementation for this code to run. +;;; +;;; (void) +;;; returns the implementation's cannonical "unspecified value". The +;;; following usually works: +;;; +;;; (define void (lambda () (if #f #f))). +;;; +;;; (andmap proc list1 list2 ...) +;;; returns true if proc returns true when applied to each element of list1 +;;; along with the corresponding elements of list2 .... The following +;;; definition works but does no error checking: +;;; +;;; (define andmap +;;; (lambda (f first . rest) +;;; (or (null? first) +;;; (if (null? rest) +;;; (let andmap ((first first)) +;;; (let ((x (car first)) (first (cdr first))) +;;; (if (null? first) +;;; (f x) +;;; (and (f x) (andmap first))))) +;;; (let andmap ((first first) (rest rest)) +;;; (let ((x (car first)) +;;; (xr (map car rest)) +;;; (first (cdr first)) +;;; (rest (map cdr rest))) +;;; (if (null? first) +;;; (apply f (cons x xr)) +;;; (and (apply f (cons x xr)) (andmap first rest))))))))) +;;; +;;; (ormap proc list1) +;;; returns the first non-false return result of proc applied to +;;; the elements of list1 or false if none. The following definition +;;; works but does no error checking: +;;; +;;; (define ormap +;;; (lambda (proc list1) +;;; (and (not (null? list1)) +;;; (or (proc (car list1)) (ormap proc (cdr list1)))))) +;;; +;;; The following nonstandard procedures must also be provided by the +;;; implementation for this code to run using the standard portable +;;; hooks and output constructors. They are not used by expanded code, +;;; and so need be present only at expansion time. +;;; +;;; (eval x) +;;; where x is always in the form ("noexpand" expr). +;;; returns the value of expr. the "noexpand" flag is used to tell the +;;; evaluator/expander that no expansion is necessary, since expr has +;;; already been fully expanded to core forms. +;;; +;;; eval will not be invoked during the loading of psyntax.pp. After +;;; psyntax.pp has been loaded, the expansion of any macro definition, +;;; whether local or global, results in a call to eval. If, however, +;;; sc-expand has already been registered as the expander to be used +;;; by eval, and eval accepts one argument, nothing special must be done +;;; to support the "noexpand" flag, since it is handled by sc-expand. +;;; +;;; (error who format-string why what) +;;; where who is either a symbol or #f, format-string is always "~a ~s", +;;; why is always a string, and what may be any object. error should +;;; signal an error with a message something like +;;; +;;; "error in : " +;;; +;;; (gensym) +;;; returns a unique symbol each time it's called. In Chez Scheme, gensym +;;; returns a symbol with a "globally" unique name so that gensyms that +;;; end up in the object code of separately compiled files cannot conflict. +;;; This is necessary only if you intend to support compiled files. +;;; +;;; (gensym? x) +;;; returns #t if x is a gensym, otherwise false. +;;; +;;; (putprop symbol key value) +;;; (getprop symbol key) +;;; (remprop symbol key) +;;; key is always a symbol; value may be any object. putprop should +;;; associate the given value with the given symbol and key in some way +;;; that it can be retrieved later with getprop. getprop should return +;;; #f if no value is associated with the given symbol and key. remprop +;;; should remove the association between the given symbol and key. + +;;; When porting to a new Scheme implementation, you should define the +;;; procedures listed above, load the expanded version of psyntax.ss +;;; (psyntax.pp, which should be available whereever you found +;;; psyntax.ss), and register sc-expand as the current expander (how +;;; you do this depends upon your implementation of Scheme). You may +;;; change the hooks and constructors defined toward the beginning of +;;; the code below, but to avoid bootstrapping problems, do so only +;;; after you have a working version of the expander. + +;;; Chez Scheme allows the syntactic form (syntax