524 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Scheme
		
	
	
	
			
		
		
	
	
			524 lines
		
	
	
		
			18 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 object-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 (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]
 | 
						|
      [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 (with-interrupt-handler p x ctxt args 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-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* 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 v)
 | 
						|
                (let ([tmp (unique-var 'tmp)])
 | 
						|
                  (values (cons tmp lhs*)
 | 
						|
                          (cons (V expr) rhs*)
 | 
						|
                          (cons (make-known tmp type v) 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 (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)
 | 
						|
             (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)])))))))
 | 
						|
  
 | 
						|
  (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 type value)
 | 
						|
       (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*)
 | 
						|
       (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 (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*)
 | 
						|
       (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 val)
 | 
						|
       ;;; 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*)
 | 
						|
       (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 val)
 | 
						|
       ;;; FIXME: suboptimal
 | 
						|
       (E expr)]
 | 
						|
      [else (error 'cogen-E "invalid effect expr" x)]))
 | 
						|
 | 
						|
  (define (Function x)
 | 
						|
    (define (nonproc x)
 | 
						|
      (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))))))
 | 
						|
    (struct-case x
 | 
						|
       [(primcall op args)
 | 
						|
        (cond
 | 
						|
          [(and (eq? op 'top-level-value)
 | 
						|
                (= (length args) 1)
 | 
						|
                (struct-case (car args)
 | 
						|
                  [(constant t) 
 | 
						|
                   (and (symbol? t) t)]
 | 
						|
                  [else #f])) =>
 | 
						|
           (lambda (sym)
 | 
						|
             (record-symbol-call! sym)
 | 
						|
             (reset-symbol-proc! sym)
 | 
						|
             (prm 'mref (T (K sym))
 | 
						|
                  (K (- disp-symbol-record-proc symbol-ptag))))]
 | 
						|
          [else (nonproc x)])]
 | 
						|
       [(primref op) (V x)]
 | 
						|
       [else (nonproc x)]))
 | 
						|
 | 
						|
 | 
						|
  (define encountered-symbol-calls '())
 | 
						|
  (define (record-symbol-call! x)
 | 
						|
    
 | 
						|
    (unless (memq x encountered-symbol-calls)
 | 
						|
      (set! encountered-symbol-calls 
 | 
						|
        (cons x encountered-symbol-calls))))
 | 
						|
 | 
						|
 | 
						|
  ;;;========================================================================
 | 
						|
  ;;;
 | 
						|
  (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 val) (T expr)]
 | 
						|
      [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"))
 |