595 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Scheme
		
	
	
	
			
		
		
	
	
			595 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Scheme
		
	
	
	
| ;;; Ikarus Scheme -- A compiler for R6RS Scheme.
 | |
| ;;; Copyright (C) 2006,2007,2008  Abdulaziz Ghuloum
 | |
| ;;; 
 | |
| ;;; This program is free software: you can redistribute it and/or modify
 | |
| ;;; it under the terms of the GNU General Public License version 3 as
 | |
| ;;; published by the Free Software Foundation.
 | |
| ;;; 
 | |
| ;;; This program is distributed in the hope that it will be useful, but
 | |
| ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
| ;;; General Public License for more details.
 | |
| ;;; 
 | |
| ;;; You should have received a copy of the GNU General Public License
 | |
| ;;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | |
| 
 | |
| 
 | |
| ;(module primops (primop? cogen-primop)
 | |
| ;  (define (primop? x) #f)
 | |
| ;  (define cogen-primop (lambda args (error 'cogen-primop "not yet"))))
 | |
| ;
 | |
| ;#!eof
 | |
| 
 | |
| ;(define-syntax export-all-module
 | |
| ;  (syntax-rules (define)
 | |
| ;    [(_ M (define name* v*) ...)
 | |
| ;     (module M (name* ...)
 | |
| ;       (define name* v*) ...)]))
 | |
| ;
 | |
| ;(export-all-module object-representation
 | |
| ;  (define fixnum-scale 4)
 | |
| ;  (define fixnum-shift 2)
 | |
| ;  (define fixnum-tag 0)
 | |
| ;  (define fixnum-mask 3))
 | |
| 
 | |
| (module primops (primop? get-primop set-primop!)
 | |
|   (define cookie (gensym))
 | |
|   (define (primop? x)
 | |
|     (and (getprop x cookie) #t))
 | |
|   (define (get-primop x)
 | |
|     (or (getprop x cookie)
 | |
|         (error 'getprimop "not a primitive" x)))
 | |
|   (define (set-primop! x v)
 | |
|     (putprop x cookie v))
 | |
|   )
 | |
| 
 | |
| (module (specify-representation)
 | |
|   (import primops)
 | |
|   (define-struct PH
 | |
|     (interruptable? p-handler p-handled? v-handler v-handled? e-handler e-handled?))
 | |
|   (define interrupt-handler
 | |
|     (make-parameter (lambda () (error 'interrupt-handler "uninitialized"))))
 | |
|   (define (interrupt) 
 | |
|     ((interrupt-handler))
 | |
|     (prm 'interrupt))
 | |
|   (define (with-interrupt-handler p x ctxt args
 | |
|              make-interrupt-call make-no-interrupt-call 
 | |
|              k)
 | |
|     (cond
 | |
|       [(not (PH-interruptable? p))
 | |
|        (parameterize ([interrupt-handler 
 | |
|                        (lambda ()
 | |
|                          (error 'cogen "uninterruptable" 
 | |
|                                 x args ctxt))])
 | |
|           (k))]
 | |
|       [else
 | |
|        (let ([interrupted? #f])
 | |
|          (let ([body 
 | |
|                 (parameterize ([interrupt-handler
 | |
|                                 (lambda () (set! interrupted? #t))])
 | |
|                    (k))])
 | |
|            (cond
 | |
|              [(not interrupted?) body]
 | |
|              [(eq? ctxt 'V)
 | |
|               (let ([h (make-interrupt-call x args)])
 | |
|                 (if (struct-case body
 | |
|                       [(primcall op) (eq? op 'interrupt)]
 | |
|                       [else #f])
 | |
|                      (make-no-interrupt-call x args)
 | |
|                      (make-shortcut body h)))]
 | |
|              [(eq? ctxt 'E)
 | |
|               (let ([h (make-interrupt-call x args)])
 | |
|                 (if (struct-case body
 | |
|                       [(primcall op) (eq? op 'interrupt)]
 | |
|                       [else #f])
 | |
|                      (make-no-interrupt-call x args)
 | |
|                      (make-shortcut body h)))]
 | |
|              [(eq? ctxt 'P)
 | |
|               (let ([h (prm '!= (make-interrupt-call x args) (K bool-f))])
 | |
|                 (if (struct-case body
 | |
|                       [(primcall op) (eq? op 'interrupt)]
 | |
|                       [else #f])
 | |
|                      (prm '!= (make-no-interrupt-call x args) (K bool-f))
 | |
|                      (make-shortcut body h)))]
 | |
|              [else (error 'with-interrupt-handler "invalid context" ctxt)])))]))
 | |
|   (define (copy-tag orig new)
 | |
|     (struct-case orig
 | |
|       [(known _ t) (make-known new t)]
 | |
|       [else new]))
 | |
|   (define (remove-tag x)
 | |
|     (struct-case x
 | |
|       [(known expr t) expr]
 | |
|       [else x]))
 | |
|   (define-syntax with-tmp
 | |
|     (lambda (x)
 | |
|       (syntax-case x ()
 | |
|         [(_ ([lhs* rhs*] ...) b b* ...)
 | |
|          (with-syntax ([(n* ...) (generate-temporaries #'(lhs* ...))])
 | |
|            #'(let ([lhs* rhs*] ...)
 | |
|                (let ([n* (unique-var 'lhs*)] ...)
 | |
|                  (make-bind (list n* ...) (list lhs* ...)
 | |
|                     (let ([lhs* (copy-tag lhs* n*)] ...)
 | |
|                       (seq* b b* ...))))))])))
 | |
|   ;;; if ctxt is V:
 | |
|   ;;;   if cogen-value, then V
 | |
|   ;;;   if cogen-pred, then (if P #f #t)
 | |
|   ;;;   if cogen-effect, then (seq E (void))
 | |
|   ;;;
 | |
|   ;;; if ctxt is P:
 | |
|   ;;;   if cogen-pred, then P
 | |
|   ;;;   if cogen-value, then (!= V #f) 
 | |
|   ;;;   if cogen-effect, then (seq E #t)
 | |
|   ;;;
 | |
|   ;;; if ctxt is E:
 | |
|   ;;;   if cogen-effect, then E
 | |
|   ;;;   if cogen-value, then (let ([tmp V]) (nop))
 | |
|   ;;;   if cogen-pred, then (if P (nop) (nop))
 | |
|   (define (simplify* args k)
 | |
|     (define (S* ls)
 | |
|       (cond
 | |
|         [(null? ls) (values '() '() '())]
 | |
|         [else
 | |
|          (let-values ([(lhs* rhs* arg*) (S* (cdr ls))])
 | |
|            (let ([a (car ls)])
 | |
|              (struct-case a
 | |
|                [(known expr type)
 | |
|                 (struct-case expr
 | |
|                   [(constant i)
 | |
|                    ;;; erase known tag
 | |
|                    (values lhs* rhs* (cons expr arg*))]
 | |
|                   [else
 | |
|                    ;(printf "known ~s ~s\n" type expr)
 | |
|                    (let ([tmp (unique-var 'tmp)])
 | |
|                      (values (cons tmp lhs*)
 | |
|                              (cons (V expr) rhs*)
 | |
|                              (cons (make-known tmp type) arg*)))])]
 | |
|                [(constant i)
 | |
|                 (values lhs* rhs* (cons a arg*))]
 | |
|                [else
 | |
|                 (let ([t (unique-var 'tmp)])
 | |
|                   (values (cons t lhs*) (cons (V a) rhs*) (cons t arg*)))])))]))
 | |
|     (let-values ([(lhs* rhs* args) (S* args)])
 | |
|       (cond
 | |
|         [(null? lhs*) (k args)]
 | |
|         [else
 | |
|          (make-bind lhs* rhs* (k args))])))
 | |
|   ;;;
 | |
|   (define (make-cogen-handler make-interrupt-call make-no-interrupt-call)
 | |
|     (define (cogen-primop x ctxt args)
 | |
|       (define (interrupt? x)
 | |
|         (struct-case x
 | |
|           [(primcall x) (eq? x 'interrupt)]
 | |
|           [else #f]))
 | |
|       (let ([p (get-primop x)])
 | |
|          (simplify* args
 | |
|            (lambda (args)
 | |
|              (with-interrupt-handler p x ctxt (map T args)
 | |
|                make-interrupt-call make-no-interrupt-call
 | |
|                (lambda ()
 | |
|                  (case ctxt
 | |
|                    [(P) 
 | |
|                     (cond
 | |
|                       [(PH-p-handled? p) 
 | |
|                        (apply (PH-p-handler p) args)]
 | |
|                       [(PH-v-handled? p)
 | |
|                        (let ([e (apply (PH-v-handler p) args)])
 | |
|                          (if (interrupt? e) e (prm '!= e (K bool-f))))]
 | |
|                       [(PH-e-handled? p)
 | |
|                        (let ([e (apply (PH-e-handler p) args)])
 | |
|                          (if (interrupt? e) e (make-seq e (K #t))))]
 | |
|                       [else (error 'cogen-primop "not handled" x)])]
 | |
|                    [(V) 
 | |
|                     (cond
 | |
|                       [(PH-v-handled? p) 
 | |
|                        (apply (PH-v-handler p) args)]
 | |
|                       [(PH-p-handled? p) 
 | |
|                        (let ([e (apply (PH-p-handler p) args)])
 | |
|                          (if (interrupt? e)
 | |
|                              e 
 | |
|                              (make-conditional e (K bool-t) (K bool-f))))]
 | |
|                       [(PH-e-handled? p)
 | |
|                        (let ([e (apply (PH-e-handler p) args)])
 | |
|                          (if (interrupt? e) e (make-seq e (K void-object))))]
 | |
|                       [else (error 'cogen-primop "not handled" x)])]
 | |
|                    [(E) 
 | |
|                     (cond
 | |
|                       [(PH-e-handled? p) 
 | |
|                        (apply (PH-e-handler p) args)]
 | |
|                       [(PH-p-handled? p) 
 | |
|                        (let ([e (apply (PH-p-handler p) args)])
 | |
|                          (if (interrupt? e)
 | |
|                              e 
 | |
|                              (make-conditional e (prm 'nop) (prm 'nop))))]
 | |
|                       [(PH-v-handled? p)
 | |
|                        (let ([e (apply (PH-v-handler p) args)])
 | |
|                          (if (interrupt? e)
 | |
|                              e
 | |
|                              (with-tmp ([t e]) (prm 'nop))))]
 | |
|                       [else (error 'cogen-primop "not handled" x)])]
 | |
|                    [else 
 | |
|                     (error 'cogen-primop "invalid context" ctxt)])))))))
 | |
|     cogen-primop)
 | |
|   (module (cogen-primop cogen-debug-primop)
 | |
|     (define (primop-interrupt-handler x)
 | |
|       (case x
 | |
|         [(fx+)                      'error@fx+]
 | |
|         [(fx-)                      'error@fx-]
 | |
|         [(fx*)                      'error@fx*]
 | |
|         [(add1)                     'error@add1]
 | |
|         [(sub1)                     'error@sub1]
 | |
|         [(fxadd1)                   'error@fxadd1]
 | |
|         [(fxsub1)                   'error@fxsub1]
 | |
|         [(fxarithmetic-shift-left)  'error@fxarithmetic-shift-left]
 | |
|         [(fxarithmetic-shift-right) 'error@fxarithmetic-shift-right]
 | |
|         [else                      x]))
 | |
|     (define (make-interrupt-call op args)
 | |
|       (make-funcall 
 | |
|         (V (make-primref (primop-interrupt-handler op)))
 | |
|         args))
 | |
|     (define (make-no-interrupt-call op args)
 | |
|       (make-funcall (V (make-primref op)) args))
 | |
|     (define cogen-primop 
 | |
|       (make-cogen-handler make-interrupt-call make-no-interrupt-call))
 | |
|     (define (cogen-debug-primop op src/loc ctxt args)
 | |
|       (define (make-call op args)
 | |
|         (make-funcall 
 | |
|           (V (make-primref 'debug-call))
 | |
|           (cons* (V src/loc) (V (make-primref op)) args)))
 | |
|       ((make-cogen-handler make-call make-call)
 | |
|        op ctxt args)))
 | |
| 
 | |
|   
 | |
|   (define-syntax define-primop
 | |
|     (lambda (x)
 | |
|       (define (cogen-name stx name suffix)
 | |
|         (datum->syntax stx
 | |
|           (string->symbol
 | |
|             (format "cogen-~a-~a" 
 | |
|               suffix 
 | |
|               (syntax->datum name)))))
 | |
|       (define (generate-handler name ctxt case*)
 | |
|         (define (filter-cases case*)
 | |
|           (syntax-case case* ()
 | |
|             [() '()]
 | |
|             [([(c . arg*) b b* ...] . rest)
 | |
|              (free-identifier=? #'c ctxt)
 | |
|              (cons #'[arg* b b* ...] (filter-cases #'rest))]
 | |
|             [(c . rest) (filter-cases #'rest)]))
 | |
|         (let ([case* (filter-cases case*)])
 | |
|           (with-syntax ([ctxt ctxt] [name name]
 | |
|                         [(case* ...) case*]
 | |
|                         [handled? (not (null? case*))])
 | |
|             #'[(case-lambda 
 | |
|                  case* ...
 | |
|                  [args (interrupt)])
 | |
|                handled?])))
 | |
|       (syntax-case x ()
 | |
|         [(stx name int? case* ...) 
 | |
|          (with-syntax ([cogen-p (cogen-name #'stx #'name "pred")]
 | |
|                        [cogen-e (cogen-name #'stx #'name "effect")]
 | |
|                        [cogen-v (cogen-name #'stx #'name "value")]
 | |
|                        [interruptable?
 | |
|                         (syntax-case #'int? (safe unsafe)
 | |
|                           [safe   #t] [unsafe #f])]
 | |
|                        [(p-handler phandled?) 
 | |
|                         (generate-handler #'name #'P #'(case* ...))]
 | |
|                        [(v-handler vhandled?)
 | |
|                         (generate-handler #'name #'V #'(case* ...))]
 | |
|                        [(e-handler ehandled?) 
 | |
|                         (generate-handler #'name #'E #'(case* ...))])
 | |
|            #'(begin
 | |
|                (define cogen-p p-handler)
 | |
|                (define cogen-v v-handler)
 | |
|                (define cogen-e e-handler)
 | |
|                (module ()
 | |
|                  (set-primop! 'name
 | |
|                     (make-PH interruptable? 
 | |
|                        cogen-p phandled? 
 | |
|                        cogen-v vhandled?
 | |
|                        cogen-e ehandled?)))))])))
 | |
| 
 | |
| 
 | |
|   (define (handle-fix lhs* rhs* body)
 | |
|     (define (closure-size x)
 | |
|       (struct-case x
 | |
|         [(closure code free*) 
 | |
|          (if (null? free*) 
 | |
|              0
 | |
|              (align (+ disp-closure-data
 | |
|                        (* (length free*) wordsize))))]))
 | |
|     (define (partition p? lhs* rhs*)
 | |
|       (cond
 | |
|         [(null? lhs*) (values '() '() '() '())]
 | |
|         [else
 | |
|          (let-values ([(a* b* c* d*)
 | |
|                        (partition p? (cdr lhs*) (cdr rhs*))]
 | |
|                       [(x y) (values (car lhs*) (car rhs*))])
 | |
|            (cond
 | |
|              [(p? x y)
 | |
|               (values (cons x a*) (cons y b*) c* d*)]
 | |
|              [else 
 | |
|               (values a* b* (cons x c*) (cons y d*))]))]))
 | |
|     (define (combinator? lhs rhs)
 | |
|       (struct-case rhs
 | |
|         [(closure code free*) (null? free*)]))
 | |
|     (define (sum n* n)
 | |
|       (cond
 | |
|         [(null? n*) n]
 | |
|         [else (sum (cdr n*) (+ n (car n*)))]))
 | |
|     (define (adders lhs n n*)
 | |
|       (cond
 | |
|         [(null? n*) '()]
 | |
|         [else
 | |
|          (cons (prm 'int+ lhs (K n))
 | |
|                (adders lhs (+ n (car n*)) (cdr n*)))]))
 | |
|     (define (build-closures lhs* rhs* body)
 | |
|       (let ([lhs (car lhs*)] [rhs (car rhs*)]
 | |
|             [lhs* (cdr lhs*)] [rhs* (cdr rhs*)])
 | |
|         (let ([n (closure-size rhs)] 
 | |
|               [n* (map closure-size rhs*)])
 | |
|           (make-bind (list lhs) 
 | |
|                      (list (prm 'alloc 
 | |
|                                 (K (sum n* n))
 | |
|                                 (K closure-tag)))
 | |
|             (make-bind lhs* (adders lhs n n*)
 | |
|               body)))))
 | |
|     (define (build-setters lhs* rhs* body)
 | |
|       (define (build-setter lhs rhs body)
 | |
|         (struct-case rhs
 | |
|           [(closure code free*) 
 | |
|            (make-seq
 | |
|              (prm 'mset lhs 
 | |
|                   (K (- disp-closure-code closure-tag))
 | |
|                   (V code))
 | |
|              (let f ([ls free*] 
 | |
|                      [i (- disp-closure-data closure-tag)])
 | |
|                (cond
 | |
|                  [(null? ls) body]
 | |
|                  [else
 | |
|                   (make-seq
 | |
|                     (prm 'mset lhs (K i) (V (car ls)))
 | |
|                     (f (cdr ls) (+ i wordsize)))])))]))
 | |
|       (cond
 | |
|         [(null? lhs*) body]
 | |
|         [else
 | |
|          (build-setter (car lhs*) (car rhs*)
 | |
|            (build-setters (cdr lhs*) (cdr rhs*) body))]))
 | |
|     (let-values ([(flhs* frhs* clhs* crhs*)
 | |
|                   (partition combinator? lhs* rhs*)])
 | |
|       (cond
 | |
|         [(null? clhs*) (make-bind flhs* (map V frhs*) body)]
 | |
|         [(null? flhs*)
 | |
|          (build-closures clhs* crhs*
 | |
|             (build-setters clhs* crhs* body))]
 | |
|         [else
 | |
|          (make-bind flhs* (map V frhs*)
 | |
|            (build-closures clhs* crhs*
 | |
|              (build-setters clhs* crhs* body)))])))
 | |
| 
 | |
| 
 | |
|   (define (constant-rep x)
 | |
|     (let ([c (constant-value x)])
 | |
|       (cond
 | |
|         [(fx? c) (make-constant (* c fx-scale))]
 | |
|         [(boolean? c) (make-constant (if c bool-t bool-f))]
 | |
|         [(eq? c (void)) (make-constant void-object)]
 | |
|         [(bwp-object? c) (make-constant bwp-object)]
 | |
|         [(char? c) (make-constant 
 | |
|                      (fxlogor char-tag
 | |
|                        (fxsll (char->integer c) char-shift)))]
 | |
|         [(null? c) (make-constant nil)]
 | |
|         [(eof-object? c) (make-constant eof)]
 | |
|         [(object? c) (error 'constant-rep "double-wrap")]
 | |
|         [else (make-constant (make-object c))])))
 | |
| 
 | |
|   (define (V x) ;;; erase known values
 | |
|     (struct-case x 
 | |
|       [(known x t)
 | |
|        (unknown-V x)]
 | |
|       [else (unknown-V x)]))
 | |
| 
 | |
|   (define (unknown-V x)
 | |
|     (struct-case x
 | |
|       [(constant) (constant-rep x)]
 | |
|       [(var)      x]
 | |
|       [(primref name)  
 | |
|        (prm 'mref
 | |
|              (K (make-object (primref->symbol name)))
 | |
|              (K (- disp-symbol-record-value symbol-ptag)))]
 | |
|       [(code-loc) (make-constant x)]
 | |
|       [(closure)  (make-constant x)]
 | |
|       [(bind lhs* rhs* body)
 | |
|        (make-bind lhs* (map V rhs*) (V body))]
 | |
|       [(fix lhs* rhs* body) 
 | |
|        (handle-fix lhs* rhs* (V body))]
 | |
|       [(conditional e0 e1 e2) 
 | |
|        (make-conditional (P e0) (V e1) (V e2))]
 | |
|       [(seq e0 e1)
 | |
|        (make-seq (E e0) (V e1))]
 | |
|       [(primcall op arg*)
 | |
|        (case op
 | |
|          [(debug-call) 
 | |
|           (cogen-debug-call op 'V arg* V)]
 | |
|          [else (cogen-primop op 'V arg*)])]
 | |
|       [(forcall op arg*)
 | |
|        (make-forcall op (map V arg*))]
 | |
|       [(funcall rator arg*)
 | |
|        (make-funcall (Function rator) (map V arg*))]
 | |
|       [(jmpcall label rator arg*)
 | |
|        (make-jmpcall label (V rator) (map V arg*))]
 | |
|       [else (error 'cogen-V "invalid value expr" x)])) 
 | |
| 
 | |
|   (define (cogen-debug-call op ctxt arg* k)
 | |
|     (define (fail)
 | |
|       (k (make-funcall (make-primref 'debug-call) arg*)))
 | |
|     (assert (>= (length arg*) 2))
 | |
|     (let ([src/expr (car arg*)] 
 | |
|           [op (cadr arg*)]
 | |
|           [args (cddr arg*)])
 | |
|       (struct-case (remove-tag op)
 | |
|         [(primref name) 
 | |
|          (if (primop? name)
 | |
|              (cogen-debug-primop name src/expr ctxt args)
 | |
|              (fail))] 
 | |
|         [else (fail)])))
 | |
| 
 | |
|   (define (P x)
 | |
|     (struct-case x
 | |
|       [(constant c) (if c (K #t) (K #f))]
 | |
|       [(primref)  (K #t)]
 | |
|       [(code-loc) (K #t)]
 | |
|       [(closure)  (K #t)]
 | |
|       [(bind lhs* rhs* body)
 | |
|        (make-bind lhs* (map V rhs*) (P body))]
 | |
|       [(conditional e0 e1 e2) 
 | |
|        (make-conditional (P e0) (P e1) (P e2))]
 | |
|       [(seq e0 e1)
 | |
|        (make-seq (E e0) (P e1))]
 | |
|       [(fix lhs* rhs* body) 
 | |
|        (handle-fix lhs* rhs* (P body))]
 | |
|       [(primcall op arg*)
 | |
|        (case op
 | |
|          [(debug-call) 
 | |
|           (cogen-debug-call op 'P arg* P)]
 | |
|          [else (cogen-primop op 'P arg*)])]
 | |
|       [(var)     (prm '!= (V x) (V (K #f)))]
 | |
|       [(funcall) (prm '!= (V x) (V (K #f)))]
 | |
|       [(jmpcall) (prm '!= (V x) (V (K #f)))]
 | |
|       [(forcall) (prm '!= (V x) (V (K #f)))]
 | |
|       [(known expr type)
 | |
|        ;;; FIXME: suboptimal
 | |
|        (P expr)]
 | |
|       [else (error 'cogen-P "invalid pred expr" x)])) 
 | |
|   
 | |
|   (define (E x)
 | |
|     (struct-case x
 | |
|       [(constant) (nop)]
 | |
|       [(var)      (nop)]
 | |
|       [(primref)  (nop)]
 | |
|       [(code-loc) (nop)]
 | |
|       [(closure)  (nop)]
 | |
|       [(bind lhs* rhs* body)
 | |
|        (make-bind lhs* (map V rhs*) (E body))]
 | |
|       [(conditional e0 e1 e2) 
 | |
|        (make-conditional (P e0) (E e1) (E e2))]
 | |
|       [(seq e0 e1)
 | |
|        (make-seq (E e0) (E e1))]
 | |
|       [(fix lhs* rhs* body) 
 | |
|        (handle-fix lhs* rhs* (E body))]
 | |
|       [(primcall op arg*)
 | |
|        (case op
 | |
|          [(debug-call) 
 | |
|           (cogen-debug-call op 'E arg* E)]
 | |
|          [else (cogen-primop op 'E arg*)])]
 | |
|       [(forcall op arg*)
 | |
|        (make-forcall op (map V arg*))]
 | |
|       [(funcall rator arg*)
 | |
|        (make-funcall (Function rator) (map V arg*))]
 | |
|       [(jmpcall label rator arg*)
 | |
|        (make-jmpcall label (V rator) (map V arg*))]
 | |
|       [(known expr type)
 | |
|        ;;; FIXME: suboptimal
 | |
|        (E expr)]
 | |
|       [else (error 'cogen-E "invalid effect expr" x)]))
 | |
| 
 | |
|   (define (Function x)
 | |
|     (define (Function x check?)
 | |
|       (define (nonproc x check?)
 | |
|         (cond
 | |
|           [check?
 | |
|            (with-tmp ([x (V x)])
 | |
|              (make-shortcut
 | |
|                (make-seq
 | |
|                  (make-conditional
 | |
|                    (tag-test x closure-mask closure-tag)
 | |
|                    (prm 'nop)
 | |
|                    (prm 'interrupt))
 | |
|                  x)
 | |
|                (V (make-funcall (make-primref 'error)
 | |
|                     (list (K 'apply) (K "not a procedure") x)))))]
 | |
|           [else
 | |
|            (V x)]))
 | |
|       (struct-case x
 | |
|          [(primcall op args)
 | |
|           (cond
 | |
|             [(and (eq? op 'top-level-value)
 | |
|                   (= (length args) 1)
 | |
|                   (let f ([x (car args)])
 | |
|                     (struct-case x
 | |
|                       [(constant x) 
 | |
|                        (and (symbol? x) x)]
 | |
|                       [(known x t) (f x)]
 | |
|                       [else #f]))) =>
 | |
|              (lambda (sym)
 | |
|                (reset-symbol-proc! sym)
 | |
|                (prm 'mref (T (K sym))
 | |
|                     (K (- disp-symbol-record-proc symbol-ptag))))]
 | |
|             [else (nonproc x check?)])]
 | |
|          [(primref op) (V x)]
 | |
|          [(known x t)
 | |
|           (cond
 | |
|             [(eq? (T:procedure? t) 'yes)
 | |
|              ;(record-optimization 'procedure x)
 | |
|              (Function x #f)]
 | |
|             [else (Function x check?)])]
 | |
|          [else (nonproc x check?)]))
 | |
|     (Function x #t))
 | |
| 
 | |
| 
 | |
| 
 | |
|   (define record-optimization^
 | |
|     (let ([h (make-eq-hashtable)])
 | |
|       (lambda (what expr)
 | |
|         (let ([n (hashtable-ref h what 0)])
 | |
|           (hashtable-set! h what (+ n 1))
 | |
|           (printf "optimize ~a[~s]: ~s\n" what n (unparse expr))))))
 | |
|   (define-syntax record-optimization
 | |
|     (syntax-rules ()
 | |
|       [(_ what expr) (void)]))
 | |
| 
 | |
|   ;;;========================================================================
 | |
|   ;;;
 | |
|   (define (interrupt-unless x)
 | |
|     (make-conditional x (prm 'nop) (interrupt))) 
 | |
|   (define (interrupt-when x)
 | |
|     (make-conditional x (interrupt) (prm 'nop))) 
 | |
|   (define (interrupt-unless-fixnum x)
 | |
|     (interrupt-unless (tag-test x fx-mask fx-tag)))
 | |
| 
 | |
| 
 | |
|   (define (T x)
 | |
|     (struct-case x
 | |
|       [(var) x]
 | |
|       [(constant i) (constant-rep x)]
 | |
|       [(known expr type)
 | |
|        (make-known (T expr) type)]
 | |
|       [else (error 'cogen-T "invalid" (unparse x))]))
 | |
| 
 | |
|   (define (ClambdaCase x)
 | |
|     (struct-case x
 | |
|       [(clambda-case info body)
 | |
|        (make-clambda-case info (V body))]
 | |
|       [else (error 'specify-rep "invalid clambda-case" x)]))
 | |
|   ;;;
 | |
|   (define (Clambda x)
 | |
|     (struct-case x
 | |
|       [(clambda label case* cp free* name)
 | |
|        (make-clambda label 
 | |
|           (map ClambdaCase case*)
 | |
|           cp free* name)]
 | |
|       [else (error 'specify-rep "invalid clambda" x)]))
 | |
|   ;;;
 | |
|   (define (Program x)
 | |
|     (struct-case x 
 | |
|       [(codes code* body)
 | |
|        (let ([code* (map Clambda code*)]
 | |
|              [body (V body)])
 | |
|          (make-codes code* body))]
 | |
|       [else (error 'specify-rep "invalid program" x)]))
 | |
| 
 | |
|   (define (specify-representation x)
 | |
|     (let ([x (Program x)])
 | |
|       x))
 | |
| 
 | |
|   (include "pass-specify-rep-primops.ss"))
 |