3007 lines
102 KiB
Scheme
3007 lines
102 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 (alt-cogen compile-call-frame)
|
|
;;; input to cogen is <Program>:
|
|
;;; <Expr> ::= (constant x)
|
|
;;; | (var)
|
|
;;; | (primref name)
|
|
;;; | (bind var* <Expr>* <Expr>)
|
|
;;; | (fix var* <FixRhs>* <Expr>)
|
|
;;; | (conditional <Expr> <Expr> <Expr>)
|
|
;;; | (seq <Expr> <Expr>)
|
|
;;; | (closure <codeloc> <var>*) ; thunk special case
|
|
;;; | (forcall "name" <Expr>*)
|
|
;;; | (funcall <Expr> <Expr>*)
|
|
;;; | (jmpcall <label> <Expr> <Expr>*)
|
|
;;; | (mvcall <Expr> <clambda>)
|
|
;;; <codeloc> ::= (code-loc <label>)
|
|
;;; <clambda> ::= (clambda <label> <case>* <cp> <free var>*)
|
|
;;; <case> ::= (clambda-case <info> <body>)
|
|
;;; <info> ::= (clambda-info label <arg var>* proper)
|
|
;;; <Program> ::= (codes <clambda>* <Expr>)
|
|
|
|
|
|
|
|
|
|
|
|
(define (introduce-primcalls x)
|
|
;;;
|
|
(define who 'introduce-primcalls)
|
|
;;;
|
|
(define (check-gensym x)
|
|
(unless (gensym? x)
|
|
(error who "invalid gensym" x)))
|
|
;;;
|
|
(define (check-label x)
|
|
(struct-case x
|
|
[(code-loc label)
|
|
(check-gensym label)]
|
|
[else (error who "invalid label" x)]))
|
|
;;;
|
|
(define (check-var x)
|
|
(struct-case x
|
|
[(var) (void)]
|
|
[else (error who "invalid var" x)]))
|
|
;;;
|
|
(define (check-closure x)
|
|
(struct-case x
|
|
[(closure label free*)
|
|
(check-label label)
|
|
(for-each check-var free*)]
|
|
[else (error who "invalid closure" x)]))
|
|
;;;
|
|
(define (mkfuncall op arg*)
|
|
(import primops)
|
|
(struct-case op
|
|
[(known x t)
|
|
(struct-case x
|
|
[(primref name)
|
|
(if (primop? name)
|
|
(make-primcall name arg*)
|
|
(make-funcall op arg*))]
|
|
[else (make-funcall op arg*)])]
|
|
[(primref name)
|
|
(cond
|
|
[(primop? name)
|
|
(make-primcall name arg*)]
|
|
[else (make-funcall op arg*)])]
|
|
[else (make-funcall op arg*)]))
|
|
;;;
|
|
(define (A x)
|
|
(struct-case x
|
|
[(known x t) (make-known (Expr x) t)]
|
|
[else (Expr x)]))
|
|
(define (Expr x)
|
|
(struct-case x
|
|
[(constant) x]
|
|
[(var) x]
|
|
[(primref) x]
|
|
[(bind lhs* rhs* body)
|
|
(make-bind lhs* (map Expr rhs*) (Expr body))]
|
|
[(fix lhs* rhs* body)
|
|
(make-fix lhs* rhs* (Expr body))]
|
|
[(conditional e0 e1 e2)
|
|
(make-conditional (Expr e0) (Expr e1) (Expr e2))]
|
|
[(seq e0 e1)
|
|
(make-seq (Expr e0) (Expr e1))]
|
|
[(closure) x]
|
|
[(forcall op arg*)
|
|
(make-forcall op (map Expr arg*))]
|
|
[(funcall rator arg*)
|
|
(mkfuncall (A rator) (map A arg*))]
|
|
[(jmpcall label rator arg*)
|
|
(make-jmpcall label (Expr rator) (map Expr arg*))]
|
|
[else (error who "invalid expr" x)]))
|
|
;;;
|
|
(define (ClambdaCase x)
|
|
(struct-case x
|
|
[(clambda-case info body)
|
|
(make-clambda-case info (Expr body))]
|
|
[else (error who "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 who "invalid clambda" x)]))
|
|
;;;
|
|
(define (Program x)
|
|
(struct-case x
|
|
[(codes code* body)
|
|
(make-codes (map Clambda code*) (Expr body))]
|
|
[else (error who "invalid program" x)]))
|
|
;;;
|
|
(Program x))
|
|
|
|
|
|
|
|
(define (eliminate-fix x)
|
|
;;;
|
|
(define who 'eliminate-fix)
|
|
;;;
|
|
(define (Expr main-cpvar cpvar free*)
|
|
;;;
|
|
(define (Var x)
|
|
(cond
|
|
[(eq? x main-cpvar) cpvar]
|
|
[else
|
|
(let f ([free* free*] [i 0])
|
|
(cond
|
|
[(null? free*) x]
|
|
[(eq? x (car free*))
|
|
(make-primcall '$cpref (list cpvar (make-constant i)))]
|
|
[else (f (cdr free*) (fxadd1 i))]))]))
|
|
(define (do-fix lhs* rhs* body)
|
|
(define (handle-closure x)
|
|
(struct-case x
|
|
[(closure code free* well-known?)
|
|
(make-closure code (map Var free*) well-known?)]))
|
|
(make-fix lhs* (map handle-closure rhs*) body))
|
|
(define (A x)
|
|
(struct-case x
|
|
[(known x t) (make-known (Expr x) t)]
|
|
[else (Expr x)]))
|
|
(define (Expr x)
|
|
(struct-case x
|
|
[(constant) x]
|
|
[(var) (Var x)]
|
|
[(primref) x]
|
|
[(bind lhs* rhs* body)
|
|
(make-bind lhs* (map Expr rhs*) (Expr body))]
|
|
[(fix lhs* rhs* body)
|
|
(do-fix lhs* rhs* (Expr body))]
|
|
[(conditional e0 e1 e2)
|
|
(make-conditional (Expr e0) (Expr e1) (Expr e2))]
|
|
[(seq e0 e1)
|
|
(make-seq (Expr e0) (Expr e1))]
|
|
[(closure)
|
|
(let ([t (unique-var 'tmp)])
|
|
(Expr (make-fix (list t) (list x) t)))]
|
|
[(primcall op arg*)
|
|
(make-primcall op (map A arg*))]
|
|
[(forcall op arg*)
|
|
(make-forcall op (map Expr arg*))]
|
|
[(funcall rator arg*)
|
|
(make-funcall (A rator) (map A arg*))]
|
|
[(jmpcall label rator arg*)
|
|
(make-jmpcall label (Expr rator) (map Expr arg*))]
|
|
[else (error who "invalid expr" x)]))
|
|
Expr)
|
|
;;;
|
|
(define (ClambdaCase main-cp free*)
|
|
(lambda (x)
|
|
(struct-case x
|
|
[(clambda-case info body)
|
|
(struct-case info
|
|
[(case-info label args proper)
|
|
(let ([cp (unique-var 'cp)])
|
|
(make-clambda-case
|
|
(make-case-info label (cons cp args) proper)
|
|
((Expr main-cp cp free*) body)))])]
|
|
[else (error who "invalid clambda-case" x)])))
|
|
;;;
|
|
(define (Clambda x)
|
|
(struct-case x
|
|
[(clambda label case* cp free* name)
|
|
(make-clambda label (map (ClambdaCase cp free*) case*)
|
|
#f free* name)]
|
|
[else (error who "invalid clambda" x)]))
|
|
;;;
|
|
(define (Program x)
|
|
(struct-case x
|
|
[(codes code* body)
|
|
(make-codes (map Clambda code*) ((Expr #f #f '()) body))]
|
|
[else (error who "invalid program" x)]))
|
|
;;;
|
|
(Program x))
|
|
|
|
|
|
|
|
(define-syntax seq*
|
|
(syntax-rules ()
|
|
[(_ e) e]
|
|
[(_ e* ... e)
|
|
(make-seq (seq* e* ...) e)]))
|
|
|
|
(define (insert-engine-checks x)
|
|
(define who 'insert-engine-checks)
|
|
(define (known-primref? x)
|
|
(struct-case x
|
|
[(known x t) (known-primref? x)]
|
|
[(primref) #t]
|
|
[else #f]))
|
|
(define (A x)
|
|
(struct-case x
|
|
[(known x t) (Expr x)]
|
|
[else (Expr x)]))
|
|
(define (Expr x)
|
|
(struct-case x
|
|
[(constant) #f]
|
|
[(var) #f]
|
|
[(primref) #f]
|
|
[(jmpcall label rator arg*) #t]
|
|
[(funcall rator arg*)
|
|
(if (known-primref? rator) (ormap A arg*) #t)]
|
|
[(bind lhs* rhs* body) (or (ormap Expr rhs*) (Expr body))]
|
|
[(fix lhs* rhs* body) (Expr body)]
|
|
[(conditional e0 e1 e2) (or (Expr e0) (Expr e1) (Expr e2))]
|
|
[(seq e0 e1) (or (Expr e0) (Expr e1))]
|
|
[(primcall op arg*) (ormap A arg*)]
|
|
[(forcall op arg*) (ormap Expr arg*)]
|
|
[else (error who "invalid expr" x)]))
|
|
(define (Main x)
|
|
(if (Expr x)
|
|
(make-seq (make-primcall '$do-event '()) x)
|
|
x))
|
|
(define (CaseExpr x)
|
|
(struct-case x
|
|
[(clambda-case info body)
|
|
(make-clambda-case info (Main body))]))
|
|
(define (CodeExpr x)
|
|
(struct-case x
|
|
[(clambda L cases cp free name)
|
|
(make-clambda L (map CaseExpr cases) cp free name)]))
|
|
(define (CodesExpr x)
|
|
(struct-case x
|
|
[(codes list body)
|
|
(make-codes (map CodeExpr list) (Main body))]))
|
|
(CodesExpr x))
|
|
|
|
|
|
(define (insert-stack-overflow-check x)
|
|
(define who 'insert-stack-overflow-check)
|
|
(define (A x)
|
|
(struct-case x
|
|
[(known x t) (NonTail x)]
|
|
[else (NonTail x)]))
|
|
(define (NonTail x)
|
|
(struct-case x
|
|
[(constant) #f]
|
|
[(var) #f]
|
|
[(primref) #f]
|
|
[(funcall rator arg*) #t]
|
|
[(jmpcall label rator arg*) #t]
|
|
[(mvcall rator k) #t]
|
|
[(bind lhs* rhs* body) (or (ormap NonTail rhs*) (NonTail body))]
|
|
[(fix lhs* rhs* body) (NonTail body)]
|
|
[(conditional e0 e1 e2) (or (NonTail e0) (NonTail e1) (NonTail e2))]
|
|
[(seq e0 e1) (or (NonTail e0) (NonTail e1))]
|
|
[(primcall op arg*) (ormap A arg*)]
|
|
[(forcall op arg*) (ormap NonTail arg*)]
|
|
[(known x t v) (NonTail x)]
|
|
[else (error who "invalid expr" x)]))
|
|
(define (Tail x)
|
|
(struct-case x
|
|
[(constant) #f]
|
|
[(var) #f]
|
|
[(primref) #f]
|
|
[(bind lhs* rhs* body) (or (ormap NonTail rhs*) (Tail body))]
|
|
[(fix lhs* rhs* body) (Tail body)]
|
|
[(conditional e0 e1 e2) (or (NonTail e0) (Tail e1) (Tail e2))]
|
|
[(seq e0 e1) (or (NonTail e0) (Tail e1))]
|
|
[(primcall op arg*) (ormap NonTail arg*)]
|
|
[(forcall op arg*) (ormap NonTail arg*)]
|
|
[(funcall rator arg*) (or (NonTail rator) (ormap NonTail arg*))]
|
|
[(jmpcall label rator arg*) (or (NonTail rator) (ormap NonTail arg*))]
|
|
[(mvcall rator k) #t] ; punt
|
|
[else (error who "invalid expr" x)]))
|
|
(define (insert-check x)
|
|
(make-seq (make-primcall '$stack-overflow-check '()) x))
|
|
(define (ClambdaCase x)
|
|
(struct-case x
|
|
[(clambda-case info body)
|
|
(make-clambda-case info (Main body))]))
|
|
(define (Clambda x)
|
|
(struct-case x
|
|
[(clambda label case* cp free* name)
|
|
(make-clambda label (map ClambdaCase case*) cp free* name)]))
|
|
(define (Main x)
|
|
(if (Tail x)
|
|
(insert-check x)
|
|
x))
|
|
(define (Program x)
|
|
(struct-case x
|
|
[(codes code* body)
|
|
(make-codes (map Clambda code*) (Main body))]))
|
|
(Program x))
|
|
|
|
(include "pass-specify-rep.ss")
|
|
|
|
(define parameter-registers '(%edi))
|
|
(define return-value-register '%eax)
|
|
(define cp-register '%edi)
|
|
(define all-registers
|
|
(case wordsize
|
|
[(4) '(%eax %edi %ebx %edx %ecx)]
|
|
[else '(%eax %edi %ebx %edx %ecx %r8 %r9 %r10 %r11 %r14 %r15)]))
|
|
|
|
(define non-8bit-registers
|
|
(case wordsize
|
|
[(4) '(%edi)]
|
|
[else '(%edi %r8 %r9 %r10 %r11 %r14 %r15)]))
|
|
|
|
(define argc-register '%eax)
|
|
|
|
;;; apr = %ebp
|
|
;;; esp = %esp
|
|
;;; pcr = %esi
|
|
;;; cpr = %edi
|
|
|
|
(define (register-index x)
|
|
(cond
|
|
[(assq x '([%eax 0] [%edi 1] [%ebx 2] [%edx 3]
|
|
[%ecx 4] [%esi 5] [%esp 6] [%ebp 7]))
|
|
=> cadr]
|
|
[else (error 'register-index "not a register" x)]))
|
|
|
|
(define (impose-calling-convention/evaluation-order x)
|
|
(define who 'impose-calling-convention/evaluation-order)
|
|
;;;
|
|
;;;
|
|
(define (S* x* k)
|
|
(cond
|
|
[(null? x*) (k '())]
|
|
[else
|
|
(S (car x*)
|
|
(lambda (a)
|
|
(S* (cdr x*)
|
|
(lambda (d)
|
|
(k (cons a d))))))]))
|
|
;;;
|
|
(define (S x k)
|
|
(struct-case x
|
|
[(bind lhs* rhs* body)
|
|
(do-bind lhs* rhs* (S body k))]
|
|
[(seq e0 e1)
|
|
(make-seq (E e0) (S e1 k))]
|
|
[(known x) (S x k)]
|
|
[else
|
|
(cond
|
|
[(or (constant? x) (symbol? x)) (k x)]
|
|
[(var? x)
|
|
(cond
|
|
[(var-loc x) => k]
|
|
[else (k x)])]
|
|
[(or (funcall? x) (primcall? x) (jmpcall? x)
|
|
(forcall? x) (shortcut? x)
|
|
(conditional? x))
|
|
(let ([t (unique-var 'tmp)])
|
|
(do-bind (list t) (list x)
|
|
(k t)))]
|
|
[else (error who "invalid S" x)])]))
|
|
(define (Mem x k)
|
|
(struct-case x
|
|
[(primcall op arg*)
|
|
(if (eq? op 'mref)
|
|
(S* arg*
|
|
(lambda (arg*)
|
|
(k (make-disp (car arg*) (cadr arg*)))))
|
|
(S x k))]
|
|
[else (S x k)]))
|
|
;;;
|
|
(define (do-bind lhs* rhs* body)
|
|
(cond
|
|
[(null? lhs*) body]
|
|
[else
|
|
(set! locals (cons (car lhs*) locals))
|
|
(make-seq
|
|
(V (car lhs*) (car rhs*))
|
|
(do-bind (cdr lhs*) (cdr rhs*) body))]))
|
|
;;;
|
|
(define (nontail-locations args)
|
|
(let f ([regs parameter-registers] [args args])
|
|
(cond
|
|
[(null? args) (values '() '() '())]
|
|
[(null? regs) (values '() '() args)]
|
|
[else
|
|
(let-values ([(r* rl* f*) (f (cdr regs) (cdr args))])
|
|
(values (cons (car regs) r*)
|
|
(cons (car args) rl*)
|
|
f*))])))
|
|
(define (make-set lhs rhs)
|
|
(make-asm-instr 'move lhs rhs))
|
|
(define (do-bind-frmt* nf* v* ac)
|
|
(cond
|
|
[(null? nf*) ac]
|
|
[else
|
|
(make-seq
|
|
(V (car nf*) (car v*))
|
|
(do-bind-frmt* (cdr nf*) (cdr v*) ac))]))
|
|
;;;
|
|
(define (handle-nontail-call rator rands value-dest call-targ)
|
|
(let-values ([(reg-locs reg-args frm-args)
|
|
(nontail-locations (cons rator rands))])
|
|
(let ([regt* (map (lambda (x) (unique-var 'rt)) reg-args)]
|
|
[frmt* (map (lambda (x) (make-nfv 'unset-conflicts #f #f #f #f))
|
|
frm-args)])
|
|
(let* ([call
|
|
(make-ntcall call-targ value-dest
|
|
(cons* argc-register
|
|
pcr esp apr
|
|
(append reg-locs frmt*))
|
|
#f #f)]
|
|
[body
|
|
(make-nframe frmt* #f
|
|
(do-bind-frmt* frmt* frm-args
|
|
(do-bind (cdr regt*) (cdr reg-args)
|
|
;;; evaluate cpt last
|
|
(do-bind (list (car regt*)) (list (car reg-args))
|
|
(assign* reg-locs regt*
|
|
(make-seq
|
|
(make-set argc-register
|
|
(make-constant
|
|
(argc-convention (length rands))))
|
|
call))))))])
|
|
(if value-dest
|
|
(make-seq body (make-set value-dest return-value-register))
|
|
body)))))
|
|
;;; (define (alloc-check size)
|
|
;;; (E (make-conditional ;;; PCB ALLOC-REDLINE
|
|
;;; (make-primcall '<=
|
|
;;; (list (make-primcall 'int+ (list apr size))
|
|
;;; (make-primcall 'mref (list pcr (make-constant 4)))))
|
|
;;; (make-primcall 'nop '())
|
|
;;; (make-funcall
|
|
;;; (make-primcall 'mref
|
|
;;; (list
|
|
;;; (make-constant (make-object (primref->symbol 'do-overflow)))
|
|
;;; (make-constant (- disp-symbol-record-proc symbol-ptag))))
|
|
;;; (list size)))))
|
|
(define (alloc-check size)
|
|
(define (test size)
|
|
(if (struct-case size
|
|
[(constant i) (<= i 4096)]
|
|
[else #f])
|
|
(make-primcall '<=
|
|
(list
|
|
apr
|
|
(make-primcall 'mref
|
|
(list pcr (make-constant pcb-allocation-redline)))))
|
|
(make-primcall '>=
|
|
(list (make-primcall 'int-
|
|
(list
|
|
(make-primcall 'mref
|
|
(list pcr (make-constant pcb-allocation-redline)))
|
|
apr))
|
|
size))))
|
|
(E (make-shortcut
|
|
(make-conditional ;;; PCB ALLOC-REDLINE
|
|
(test size)
|
|
(make-primcall 'nop '())
|
|
(make-primcall 'interrupt '()))
|
|
(make-funcall
|
|
(make-primcall 'mref
|
|
(list
|
|
(make-constant (make-object (primref->symbol 'do-overflow)))
|
|
(make-constant (- disp-symbol-record-proc symbol-ptag))))
|
|
(list size)))))
|
|
;;; impose value
|
|
(define (V d x)
|
|
(struct-case x
|
|
[(constant) (make-set d x)]
|
|
[(var)
|
|
(cond
|
|
[(var-loc x) => (lambda (loc) (make-set d loc))]
|
|
[else (make-set d x)])]
|
|
[(bind lhs* rhs* e)
|
|
(do-bind lhs* rhs* (V d e))]
|
|
[(seq e0 e1)
|
|
(make-seq (E e0) (V d e1))]
|
|
[(conditional e0 e1 e2)
|
|
(make-conditional (P e0) (V d e1) (V d e2))]
|
|
[(primcall op rands)
|
|
(case op
|
|
[(alloc)
|
|
(S (car rands)
|
|
(lambda (size)
|
|
(make-seq
|
|
(alloc-check size)
|
|
(S (cadr rands)
|
|
(lambda (tag)
|
|
(make-seq
|
|
(make-seq
|
|
(make-set d apr)
|
|
(make-asm-instr 'logor d tag))
|
|
(make-asm-instr 'int+ apr size)))))))]
|
|
[(mref)
|
|
(S* rands
|
|
(lambda (rands)
|
|
(make-set d (make-disp (car rands) (cadr rands)))))]
|
|
[(mref32)
|
|
(S* rands
|
|
(lambda (rands)
|
|
(make-asm-instr 'load32 d
|
|
(make-disp (car rands) (cadr rands)))))]
|
|
[(bref)
|
|
(S* rands
|
|
(lambda (rands)
|
|
(make-asm-instr 'move-byte d
|
|
(make-disp (car rands) (cadr rands)))))]
|
|
[(logand logxor logor int+ int- int*
|
|
int-/overflow int+/overflow int*/overflow)
|
|
(make-seq
|
|
(V d (car rands))
|
|
(S (cadr rands)
|
|
(lambda (s)
|
|
(make-asm-instr op d s))))]
|
|
[(int-quotient)
|
|
(S* rands
|
|
(lambda (rands)
|
|
(seq*
|
|
(make-set eax (car rands))
|
|
(make-asm-instr 'cltd edx eax)
|
|
(make-asm-instr 'idiv eax (cadr rands))
|
|
(make-set d eax))))]
|
|
[(int-remainder)
|
|
(S* rands
|
|
(lambda (rands)
|
|
(seq*
|
|
(make-set eax (car rands))
|
|
(make-asm-instr 'cltd edx eax)
|
|
(make-asm-instr 'idiv edx (cadr rands))
|
|
(make-set d edx))))]
|
|
[(sll sra srl sll/overflow)
|
|
(let ([a (car rands)] [b (cadr rands)])
|
|
(cond
|
|
[(constant? b)
|
|
(make-seq
|
|
(V d a)
|
|
(make-asm-instr op d b))]
|
|
[else
|
|
(S b
|
|
(lambda (b)
|
|
(seq*
|
|
(V d a)
|
|
(make-set ecx b)
|
|
(make-asm-instr op d ecx))))]))]
|
|
[else (error who "invalid value op" op)])]
|
|
[(funcall rator rands)
|
|
(handle-nontail-call rator rands d #f)]
|
|
[(jmpcall label rator rands)
|
|
(handle-nontail-call rator rands d label)]
|
|
[(forcall op rands)
|
|
(handle-nontail-call
|
|
(make-constant (make-foreign-label op))
|
|
rands d op)]
|
|
[(shortcut body handler)
|
|
(make-shortcut
|
|
(V d body)
|
|
(V d handler))]
|
|
[(known x) (V d x)]
|
|
[else
|
|
(if (symbol? x)
|
|
(make-set d x)
|
|
(error who "invalid value" (unparse x)))]))
|
|
;;;
|
|
(define (assign* lhs* rhs* ac)
|
|
(cond
|
|
[(null? lhs*) ac]
|
|
[else
|
|
(make-seq
|
|
(make-set (car lhs*) (car rhs*))
|
|
(assign* (cdr lhs*) (cdr rhs*) ac))]))
|
|
;;;
|
|
(define (VT x)
|
|
(S x
|
|
(lambda (x)
|
|
(make-seq
|
|
(make-set return-value-register x)
|
|
(make-primcall 'return
|
|
(list pcr esp apr return-value-register))))))
|
|
;;; impose effect
|
|
(define (E x)
|
|
(struct-case x
|
|
[(seq e0 e1) (make-seq (E e0) (E e1))]
|
|
[(conditional e0 e1 e2)
|
|
(make-conditional (P e0) (E e1) (E e2))]
|
|
[(bind lhs* rhs* e)
|
|
(do-bind lhs* rhs* (E e))]
|
|
[(primcall op rands)
|
|
(case op
|
|
[(mset bset bset/c mset32)
|
|
(S* rands
|
|
(lambda (s*)
|
|
(make-asm-instr op
|
|
(make-disp (car s*) (cadr s*))
|
|
(caddr s*))))]
|
|
[(fl:load fl:store fl:add! fl:sub! fl:mul! fl:div!
|
|
fl:from-int fl:shuffle bswap!
|
|
fl:store-single fl:load-single)
|
|
(S* rands
|
|
(lambda (s*)
|
|
(make-asm-instr op (car s*) (cadr s*))))]
|
|
[(nop interrupt incr/zero? fl:double->single
|
|
fl:single->double) x]
|
|
[else (error 'impose-effect "invalid instr" x)])]
|
|
[(funcall rator rands)
|
|
(handle-nontail-call rator rands #f #f)]
|
|
[(jmpcall label rator rands)
|
|
(handle-nontail-call rator rands #f label)]
|
|
[(forcall op rands)
|
|
(handle-nontail-call
|
|
(make-constant (make-foreign-label op))
|
|
rands #f op)]
|
|
[(shortcut body handler)
|
|
(make-shortcut (E body) (E handler))]
|
|
[else (error who "invalid effect" x)]))
|
|
;;; impose pred
|
|
(define (P x)
|
|
(struct-case x
|
|
[(constant) x]
|
|
[(seq e0 e1) (make-seq (E e0) (P e1))]
|
|
[(conditional e0 e1 e2)
|
|
(make-conditional (P e0) (P e1) (P e2))]
|
|
[(bind lhs* rhs* e)
|
|
(do-bind lhs* rhs* (P e))]
|
|
[(primcall op rands)
|
|
(let ([a (car rands)] [b (cadr rands)])
|
|
(cond
|
|
[(and (constant? a) (constant? b))
|
|
(let ([t (unique-var 'tmp)])
|
|
(P (make-bind (list t) (list a)
|
|
(make-primcall op (list t b)))))]
|
|
[else
|
|
(Mem a
|
|
(lambda (a)
|
|
(Mem b
|
|
(lambda (b)
|
|
(make-asm-instr op a b)))))]))]
|
|
;(cond
|
|
; [(and (constant? a) (constant? b))
|
|
; (let ([t (unique-var 'tmp)])
|
|
; (P (make-bind (list t) (list a)
|
|
; (make-primcall op (list t b)))))]
|
|
; [(constant? a)
|
|
; (Mem b (lambda (b) (make-asm-instr op a b)))]
|
|
; [(constant? b)
|
|
; (Mem a (lambda (a) (make-asm-instr op a b)))]
|
|
; [else
|
|
; (S* rands
|
|
; (lambda (rands)
|
|
; (let ([a (car rands)] [b (cadr rands)])
|
|
; (make-asm-instr op a b))))]))]
|
|
[(shortcut body handler)
|
|
(make-shortcut (P body) (P handler))]
|
|
[else (error who "invalid pred" x)]))
|
|
;;;
|
|
(define (handle-tail-call target rator rands)
|
|
(let* ([args (cons rator rands)]
|
|
[locs (formals-locations args)]
|
|
[rest
|
|
(make-seq
|
|
(make-set argc-register
|
|
(make-constant
|
|
(argc-convention (length rands))))
|
|
(cond
|
|
[target
|
|
(make-primcall 'direct-jump
|
|
(cons target
|
|
(cons* argc-register
|
|
pcr esp apr
|
|
locs)))]
|
|
[else
|
|
(make-primcall 'indirect-jump
|
|
(cons* argc-register
|
|
pcr esp apr
|
|
locs))]))])
|
|
(let f ([args (reverse args)]
|
|
[locs (reverse locs)]
|
|
[targs '()]
|
|
[tlocs '()])
|
|
(cond
|
|
[(null? args) (assign* tlocs targs rest)]
|
|
[(constant? (car args))
|
|
(f (cdr args) (cdr locs)
|
|
(cons (car args) targs)
|
|
(cons (car locs) tlocs))]
|
|
[(and (fvar? (car locs))
|
|
(var? (car args))
|
|
(eq? (car locs) (var-loc (car args))))
|
|
(f (cdr args) (cdr locs) targs tlocs)]
|
|
[else
|
|
(let ([t (unique-var 'tmp)])
|
|
(set! locals (cons t locals))
|
|
(make-seq
|
|
(V t (car args))
|
|
(f (cdr args) (cdr locs)
|
|
(cons t targs) (cons (car locs) tlocs))))]))))
|
|
(define (Tail x)
|
|
(struct-case x
|
|
[(constant) (VT x)]
|
|
[(var) (VT x)]
|
|
[(primcall op rands)
|
|
(case op
|
|
[($call-with-underflow-handler)
|
|
(let ([t0 (unique-var 't)]
|
|
[t1 (unique-var 't)]
|
|
[t2 (unique-var 't)]
|
|
[handler (car rands)]
|
|
[proc (cadr rands)]
|
|
[k (caddr rands)])
|
|
(set! locals (cons* t0 t1 t2 locals))
|
|
(seq*
|
|
(V t0 handler)
|
|
(V t1 k)
|
|
(V t2 proc)
|
|
(make-set (mkfvar 1) t0)
|
|
(make-set (mkfvar 2) t1)
|
|
(make-set cpr t2)
|
|
(make-set argc-register (make-constant (argc-convention 1)))
|
|
(make-asm-instr 'int- fpr (make-constant wordsize))
|
|
(make-primcall 'indirect-jump
|
|
(list argc-register cpr pcr esp apr
|
|
(mkfvar 1) (mkfvar 2)))))]
|
|
[else (VT x)])]
|
|
[(bind lhs* rhs* e)
|
|
(do-bind lhs* rhs* (Tail e))]
|
|
[(seq e0 e1)
|
|
(make-seq (E e0) (Tail e1))]
|
|
[(conditional e0 e1 e2)
|
|
(make-conditional (P e0) (Tail e1) (Tail e2))]
|
|
[(funcall rator rands)
|
|
(handle-tail-call #f rator rands)]
|
|
[(jmpcall label rator rands)
|
|
(handle-tail-call (make-code-loc label) rator rands)]
|
|
[(forcall) (VT x)]
|
|
[(shortcut body handler)
|
|
(make-shortcut (Tail body) (Tail handler))]
|
|
[else (error who "invalid tail" x)]))
|
|
;;;
|
|
(define (formals-locations args)
|
|
(let f ([regs parameter-registers] [args args])
|
|
(cond
|
|
[(null? args) '()]
|
|
[(null? regs)
|
|
(let f ([i 1] [args args])
|
|
(cond
|
|
[(null? args) '()]
|
|
[else
|
|
(cons (mkfvar i)
|
|
(f (fxadd1 i) (cdr args)))]))]
|
|
[else
|
|
(cons (car regs) (f (cdr regs) (cdr args)))])))
|
|
;;;
|
|
(define locals '())
|
|
(define (partition-formals ls)
|
|
(let f ([regs parameter-registers] [ls ls])
|
|
(cond
|
|
[(null? regs)
|
|
(let ([flocs
|
|
(let f ([i 1] [ls ls])
|
|
(cond
|
|
[(null? ls) '()]
|
|
[else (cons (mkfvar i) (f (fxadd1 i) (cdr ls)))]))])
|
|
(values '() '() ls flocs))]
|
|
[(null? ls)
|
|
(values '() '() '() '())]
|
|
[else
|
|
(let-values ([(rargs rlocs fargs flocs)
|
|
(f (cdr regs) (cdr ls))])
|
|
(values (cons (car ls) rargs)
|
|
(cons (car regs) rlocs)
|
|
fargs flocs))])))
|
|
;;;
|
|
(define (ClambdaCase x)
|
|
(struct-case x
|
|
[(clambda-case info body)
|
|
(struct-case info
|
|
[(case-info label args proper)
|
|
(let-values ([(rargs rlocs fargs flocs)
|
|
(partition-formals args)])
|
|
(set! locals rargs)
|
|
(for-each set-var-loc! fargs flocs)
|
|
(let ([body (let f ([args rargs] [locs rlocs])
|
|
(cond
|
|
[(null? args) (Tail body)]
|
|
[else
|
|
(make-seq
|
|
(make-set (car args) (car locs))
|
|
(f (cdr args) (cdr locs)))]))])
|
|
(make-clambda-case
|
|
(make-case-info label (append rlocs flocs) proper)
|
|
(make-locals locals body))))])]))
|
|
;;;
|
|
(define (Clambda x)
|
|
(struct-case x
|
|
[(clambda label case* cp free* name)
|
|
(make-clambda label (map ClambdaCase case*) cp free* name)]))
|
|
;;;
|
|
(define (Main x)
|
|
(set! locals '())
|
|
(let ([x (Tail x)])
|
|
(make-locals locals x)))
|
|
;;;
|
|
(define (Program x)
|
|
(struct-case x
|
|
[(codes code* body)
|
|
(make-codes (map Clambda code*) (Main body))]))
|
|
;;;
|
|
; (print-code x)
|
|
(Program x))
|
|
|
|
(module ListySet
|
|
(make-empty-set set-member? set-add set-rem set-difference set-union
|
|
empty-set?
|
|
set->list list->set)
|
|
(define-struct set (v))
|
|
(define (make-empty-set) (make-set '()))
|
|
(define (set-member? x s)
|
|
;(unless (fixnum? x) (error 'set-member? "not a fixnum" x))
|
|
(unless (set? s) (error 'set-member? "not a set" s))
|
|
(memq x (set-v s)))
|
|
(define (empty-set? s)
|
|
(unless (set? s) (error 'empty-set? "not a set" s))
|
|
(null? (set-v s)))
|
|
(define (set->list s)
|
|
(unless (set? s) (error 'set->list "not a set" s))
|
|
(set-v s))
|
|
(define (set-add x s)
|
|
;(unless (fixnum? x) (error 'set-add "not a fixnum" x))
|
|
(unless (set? s) (error 'set-add "not a set" s))
|
|
(cond
|
|
[(memq x (set-v s)) s]
|
|
[else (make-set (cons x (set-v s)))]))
|
|
(define (rem x s)
|
|
(cond
|
|
[(null? s) '()]
|
|
[(eq? x (car s)) (cdr s)]
|
|
[else (cons (car s) (rem x (cdr s)))]))
|
|
(define (set-rem x s)
|
|
;(unless (fixnum? x) (error 'set-rem "not a fixnum" x))
|
|
(unless (set? s) (error 'set-rem "not a set" s))
|
|
(make-set (rem x (set-v s))))
|
|
(define (difference s1 s2)
|
|
(cond
|
|
[(null? s2) s1]
|
|
[else (difference (rem (car s2) s1) (cdr s2))]))
|
|
(define (set-difference s1 s2)
|
|
(unless (set? s1) (error 'set-difference "not a set" s1))
|
|
(unless (set? s2) (error 'set-difference "not a set" s2))
|
|
(make-set (difference (set-v s1) (set-v s2))))
|
|
(define (set-union s1 s2)
|
|
(unless (set? s1) (error 'set-union "not a set" s1))
|
|
(unless (set? s2) (error 'set-union "not a set" s2))
|
|
(make-set (union (set-v s1) (set-v s2))))
|
|
(define (list->set ls)
|
|
;(unless (andmap fixnum? ls) (error 'set-rem "not a list of fixnum" ls))
|
|
(make-set ls))
|
|
(define (union s1 s2)
|
|
(cond
|
|
[(null? s1) s2]
|
|
[(memq (car s1) s2) (union (cdr s1) s2)]
|
|
[else (cons (car s1) (union (cdr s1) s2))])))
|
|
|
|
(module IntegerSet
|
|
(make-empty-set set-member? set-add set-rem set-difference
|
|
set-union empty-set? set->list list->set)
|
|
;;;
|
|
(begin
|
|
(define-syntax car (identifier-syntax $car))
|
|
(define-syntax cdr (identifier-syntax $cdr))
|
|
(define-syntax fxsll (identifier-syntax $fxsll))
|
|
(define-syntax fxsra (identifier-syntax $fxsra))
|
|
(define-syntax fxlogor (identifier-syntax $fxlogor))
|
|
(define-syntax fxlogand (identifier-syntax $fxlogand))
|
|
(define-syntax fxlognot (identifier-syntax $fxlognot))
|
|
(define-syntax fx+ (identifier-syntax $fx+))
|
|
(define-syntax fxzero? (identifier-syntax $fxzero?))
|
|
(define-syntax fxeven?
|
|
(syntax-rules ()
|
|
[(_ x) ($fxzero? ($fxlogand x 1))])))
|
|
;;;
|
|
(define bits 28)
|
|
(define (index-of n) (fxquotient n bits))
|
|
(define (mask-of n) (fxsll 1 (fxremainder n bits)))
|
|
;;;
|
|
(define (make-empty-set) 0)
|
|
(define (empty-set? s) (eqv? s 0))
|
|
|
|
(define (set-member? n s)
|
|
(unless (fixnum? n) (error 'set-member? "not a fixnum" n))
|
|
(let f ([s s] [i (index-of n)] [j (mask-of n)])
|
|
(cond
|
|
[(pair? s)
|
|
(if (fxeven? i)
|
|
(f (car s) (fxsra i 1) j)
|
|
(f (cdr s) (fxsra i 1) j))]
|
|
[(eq? i 0) (eq? j (fxlogand s j))]
|
|
[else #f])))
|
|
;;;
|
|
(define (set-add n s)
|
|
(unless (fixnum? n) (error 'set-add "not a fixnum" n))
|
|
(let f ([s s] [i (index-of n)] [j (mask-of n)])
|
|
(cond
|
|
[(pair? s)
|
|
(if (fxeven? i)
|
|
(let ([a0 (car s)])
|
|
(let ([a1 (f a0 (fxsra i 1) j)])
|
|
(if (eq? a0 a1) s (cons a1 (cdr s)))))
|
|
(let ([d0 (cdr s)])
|
|
(let ([d1 (f d0 (fxsra i 1) j)])
|
|
(if (eq? d0 d1) s (cons (car s) d1)))))]
|
|
[(eq? i 0) (fxlogor s j)]
|
|
[else
|
|
(if (fxeven? i)
|
|
(cons (f s (fxsra i 1) j) 0)
|
|
(cons s (f 0 (fxsra i 1) j)))])))
|
|
;;;
|
|
(define (cons^ a d)
|
|
(if (and (eq? d 0) (fixnum? a))
|
|
a
|
|
(cons a d)))
|
|
;;;
|
|
(define (set-rem n s)
|
|
(unless (fixnum? n) (error 'set-rem "not a fixnum" n))
|
|
(let f ([s s] [i (index-of n)] [j (mask-of n)])
|
|
(cond
|
|
[(pair? s)
|
|
(if (fxeven? i)
|
|
(let ([a0 (car s)])
|
|
(let ([a1 (f a0 (fxsra i 1) j)])
|
|
(if (eq? a0 a1) s (cons^ a1 (cdr s)))))
|
|
(let ([d0 (cdr s)])
|
|
(let ([d1 (f d0 (fxsra i 1) j)])
|
|
(if (eq? d0 d1) s (cons^ (car s) d1)))))]
|
|
[(eq? i 0) (fxlogand s (fxlognot j))]
|
|
[else s])))
|
|
|
|
(define (set-union^ s1 m2)
|
|
(if (pair? s1)
|
|
(let ([a0 (car s1)])
|
|
(let ([a1 (set-union^ a0 m2)])
|
|
(if (eq? a0 a1) s1 (cons a1 (cdr s1)))))
|
|
(fxlogor s1 m2)))
|
|
;;;
|
|
(define (set-union s1 s2)
|
|
(if (pair? s1)
|
|
(if (pair? s2)
|
|
(if (eq? s1 s2)
|
|
s1
|
|
(cons (set-union (car s1) (car s2))
|
|
(set-union (cdr s1) (cdr s2))))
|
|
(let ([a0 (car s1)])
|
|
(let ([a1 (set-union^ a0 s2)])
|
|
(if (eq? a0 a1) s1 (cons a1 (cdr s1))))))
|
|
(if (pair? s2)
|
|
(let ([a0 (car s2)])
|
|
(let ([a1 (set-union^ a0 s1)])
|
|
(if (eq? a0 a1) s2 (cons a1 (cdr s2)))))
|
|
(fxlogor s1 s2))))
|
|
;;;
|
|
(define (set-difference^ s1 m2)
|
|
(if (pair? s1)
|
|
(let ([a0 (car s1)])
|
|
(let ([a1 (set-difference^ a0 m2)])
|
|
(if (eq? a0 a1) s1 (cons^ a1 (cdr s1)))))
|
|
(fxlogand s1 (fxlognot m2))))
|
|
|
|
(define (set-difference^^ m1 s2)
|
|
(if (pair? s2)
|
|
(set-difference^^ m1 (car s2))
|
|
(fxlogand m1 (fxlognot s2))))
|
|
;;;
|
|
(define (set-difference s1 s2)
|
|
(if (pair? s1)
|
|
(if (pair? s2)
|
|
(if (eq? s1 s2)
|
|
0
|
|
(cons^ (set-difference (car s1) (car s2))
|
|
(set-difference (cdr s1) (cdr s2))))
|
|
(let ([a0 (car s1)])
|
|
(let ([a1 (set-difference^ a0 s2)])
|
|
(if (eq? a0 a1) s1 (cons^ a1 (cdr s1))))))
|
|
(if (pair? s2)
|
|
(set-difference^^ s1 (car s2))
|
|
(fxlogand s1 (fxlognot s2)))))
|
|
;;;
|
|
(define (list->set ls)
|
|
(unless (andmap fixnum? ls) (error 'list->set "not a list of fixnum" ls))
|
|
(let f ([ls ls] [s 0])
|
|
(cond
|
|
[(null? ls) s]
|
|
[else (f (cdr ls) (set-add (car ls) s))])))
|
|
;;;
|
|
(define (set->list s)
|
|
(let f ([i 0] [j 1] [s s] [ac '()])
|
|
(cond
|
|
[(pair? s)
|
|
(f i (fxsll j 1) (car s)
|
|
(f (fxlogor i j) (fxsll j 1) (cdr s) ac))]
|
|
[else
|
|
(let f ([i (fx* i bits)] [m s] [ac ac])
|
|
(cond
|
|
[(fxeven? m)
|
|
(if (fxzero? m)
|
|
ac
|
|
(f (fx+ i 1) (fxsra m 1) ac))]
|
|
[else
|
|
(f (fx+ i 1) (fxsra m 1) (cons i ac))]))])))
|
|
#|IntegerSet|#)
|
|
|
|
(module ListyGraphs
|
|
(empty-graph add-edge! empty-graph? print-graph node-neighbors
|
|
delete-node!)
|
|
(import ListySet)
|
|
;;;
|
|
(define-struct graph (ls))
|
|
;;;
|
|
(define (empty-graph) (make-graph '()))
|
|
;;;
|
|
(define (empty-graph? g)
|
|
(andmap (lambda (x) (empty-set? (cdr x))) (graph-ls g)))
|
|
;;;
|
|
(define (single x)
|
|
(set-add x (make-empty-set)))
|
|
;;;
|
|
(define (add-edge! g x y)
|
|
(let ([ls (graph-ls g)])
|
|
(cond
|
|
[(assq x ls) =>
|
|
(lambda (p0)
|
|
(unless (set-member? y (cdr p0))
|
|
(set-cdr! p0 (set-add y (cdr p0)))
|
|
(cond
|
|
[(assq y ls) =>
|
|
(lambda (p1)
|
|
(set-cdr! p1 (set-add x (cdr p1))))]
|
|
[else
|
|
(set-graph-ls! g
|
|
(cons (cons y (single x)) ls))])))]
|
|
[(assq y ls) =>
|
|
(lambda (p1)
|
|
(set-cdr! p1 (set-add x (cdr p1)))
|
|
(set-graph-ls! g (cons (cons x (single y)) ls)))]
|
|
[else
|
|
(set-graph-ls! g
|
|
(cons* (cons x (single y))
|
|
(cons y (single x))
|
|
ls))])))
|
|
(define (print-graph g)
|
|
(printf "G={\n")
|
|
(parameterize ([print-gensym 'pretty])
|
|
(for-each (lambda (x)
|
|
(let ([lhs (car x)] [rhs* (cdr x)])
|
|
(printf " ~s => ~s\n"
|
|
(unparse lhs)
|
|
(map unparse (set->list rhs*)))))
|
|
(graph-ls g)))
|
|
(printf "}\n"))
|
|
(define (node-neighbors x g)
|
|
(cond
|
|
[(assq x (graph-ls g)) => cdr]
|
|
[else (make-empty-set)]))
|
|
;;;
|
|
(define (delete-node! x g)
|
|
(let ([ls (graph-ls g)])
|
|
(cond
|
|
[(assq x ls) =>
|
|
(lambda (p)
|
|
(for-each (lambda (y)
|
|
(let ([p (assq y ls)])
|
|
(set-cdr! p (set-rem x (cdr p)))))
|
|
(set->list (cdr p)))
|
|
(set-cdr! p (make-empty-set)))]
|
|
[else (void)])))
|
|
;;;
|
|
#|ListyGraphs|#)
|
|
|
|
|
|
(module IntegerGraphs
|
|
(empty-graph add-edge! empty-graph? print-graph node-neighbors
|
|
delete-node!)
|
|
(import IntegerSet)
|
|
;;;
|
|
(define-struct graph (ls))
|
|
;;;
|
|
(define (empty-graph) (make-graph '()))
|
|
;;;
|
|
(define (empty-graph? g)
|
|
(andmap (lambda (x) (empty-set? (cdr x))) (graph-ls g)))
|
|
;;;
|
|
(define (single x)
|
|
(set-add x (make-empty-set)))
|
|
;;;
|
|
(define (add-edge! g x y)
|
|
(let ([ls (graph-ls g)])
|
|
(cond
|
|
[(assq x ls) =>
|
|
(lambda (p0)
|
|
(unless (set-member? y (cdr p0))
|
|
(set-cdr! p0 (set-add y (cdr p0)))
|
|
(cond
|
|
[(assq y ls) =>
|
|
(lambda (p1)
|
|
(set-cdr! p1 (set-add x (cdr p1))))]
|
|
[else
|
|
(set-graph-ls! g
|
|
(cons (cons y (single x)) ls))])))]
|
|
[(assq y ls) =>
|
|
(lambda (p1)
|
|
(set-cdr! p1 (set-add x (cdr p1)))
|
|
(set-graph-ls! g (cons (cons x (single y)) ls)))]
|
|
[else
|
|
(set-graph-ls! g
|
|
(cons* (cons x (single y))
|
|
(cons y (single x))
|
|
ls))])))
|
|
(define (print-graph g)
|
|
(printf "G={\n")
|
|
(parameterize ([print-gensym 'pretty])
|
|
(for-each (lambda (x)
|
|
(let ([lhs (car x)] [rhs* (cdr x)])
|
|
(printf " ~s => ~s\n"
|
|
(unparse lhs)
|
|
(map unparse (set->list rhs*)))))
|
|
(graph-ls g)))
|
|
(printf "}\n"))
|
|
(define (node-neighbors x g)
|
|
(cond
|
|
[(assq x (graph-ls g)) => cdr]
|
|
[else (make-empty-set)]))
|
|
;;;
|
|
(define (delete-node! x g)
|
|
(let ([ls (graph-ls g)])
|
|
(cond
|
|
[(assq x ls) =>
|
|
(lambda (p)
|
|
(for-each (lambda (y)
|
|
(let ([p (assq y ls)])
|
|
(set-cdr! p (set-rem x (cdr p)))))
|
|
(set->list (cdr p)))
|
|
(set-cdr! p (make-empty-set)))]
|
|
[else (void)])))
|
|
;;;
|
|
#|IntegerGraphs|#)
|
|
|
|
(module conflict-helpers
|
|
(empty-var-set rem-var add-var union-vars mem-var? for-each-var init-vars!
|
|
empty-nfv-set rem-nfv add-nfv union-nfvs mem-nfv? for-each-nfv init-nfv!
|
|
empty-frm-set rem-frm add-frm union-frms mem-frm?
|
|
empty-reg-set rem-reg add-reg union-regs mem-reg?
|
|
reg?)
|
|
(import IntegerSet)
|
|
(begin
|
|
(define (add-frm x s) (set-add (fvar-idx x) s))
|
|
(define (rem-nfv x s)
|
|
(remq1 x s))
|
|
(define (init-var! x i)
|
|
(set-var-index! x i)
|
|
(set-var-var-move! x (empty-var-set))
|
|
(set-var-reg-move! x (empty-reg-set))
|
|
(set-var-frm-move! x (empty-frm-set))
|
|
(set-var-var-conf! x (empty-var-set))
|
|
(set-var-reg-conf! x (empty-reg-set))
|
|
(set-var-frm-conf! x (empty-frm-set)))
|
|
(define (init-vars! ls)
|
|
(let f ([ls ls] [i 0])
|
|
(unless (null? ls)
|
|
(init-var! (car ls) i)
|
|
(f (cdr ls) (fxadd1 i)))))
|
|
(define (init-nfv! x)
|
|
(set-nfv-frm-conf! x (empty-frm-set))
|
|
(set-nfv-nfv-conf! x (empty-nfv-set))
|
|
(set-nfv-var-conf! x (empty-var-set)))
|
|
(define (reg? x) (symbol? x))
|
|
(define (empty-var-set) (make-empty-set))
|
|
(define (add-var x s) (set-add (var-index x) s))
|
|
(define (mem-var? x s) (set-member? (var-index x) s))
|
|
(define (rem-var x s) (set-rem (var-index x) s))
|
|
(define (union-vars s1 s2) (set-union s1 s2))
|
|
(define (for-each-var s varvec f)
|
|
(for-each (lambda (i) (f (vector-ref varvec i)))
|
|
(set->list s)))
|
|
(define (empty-reg-set) (make-empty-set))
|
|
(define (add-reg x s) (set-add (register-index x) s))
|
|
(define (rem-reg x s) (set-rem (register-index x) s))
|
|
(define (mem-reg? x s) (set-member? (register-index x) s))
|
|
(define (union-regs s1 s2) (set-union s1 s2))
|
|
(define (empty-frm-set) (make-empty-set))
|
|
(define (mem-frm? x s) (set-member? (fvar-idx x) s))
|
|
(define (rem-frm x s) (set-rem (fvar-idx x) s))
|
|
(define (union-frms s1 s2) (set-union s1 s2))
|
|
(define (empty-nfv-set) '())
|
|
(define (add-nfv x s)
|
|
(cond
|
|
[(memq x s) s]
|
|
[else (cons x s)]))
|
|
(define (mem-nfv? x s)
|
|
(memq x s))
|
|
(define (union-nfvs s1 s2)
|
|
(let f ([s1 s1] [s2 s2])
|
|
(cond
|
|
[(null? s1) s2]
|
|
[(memq (car s1) s2) (f (cdr s1) s2)]
|
|
[else (cons (car s1) (f (cdr s1) s2))])))
|
|
(define (for-each-nfv s f)
|
|
(for-each f s))))
|
|
|
|
(define (uncover-frame-conflicts x varvec)
|
|
(import IntegerSet)
|
|
(import conflict-helpers)
|
|
(define who 'uncover-frame-conflicts)
|
|
(define spill-set (make-empty-set))
|
|
(define (mark-reg/vars-conf! r vs)
|
|
(for-each-var vs varvec
|
|
(lambda (v)
|
|
(set-var-reg-conf! v
|
|
(add-reg r (var-reg-conf v))))))
|
|
(define (mark-frm/vars-conf! f vs)
|
|
(for-each-var vs varvec
|
|
(lambda (v)
|
|
(set-var-frm-conf! v
|
|
(add-frm f (var-frm-conf v))))))
|
|
(define (mark-frm/nfvs-conf! f ns)
|
|
(for-each-nfv ns
|
|
(lambda (n)
|
|
(set-nfv-frm-conf! n
|
|
(add-frm f (nfv-frm-conf n))))))
|
|
(define (mark-var/vars-conf! v vs)
|
|
(for-each-var vs varvec
|
|
(lambda (w)
|
|
(set-var-var-conf! w
|
|
(add-var v (var-var-conf w)))))
|
|
(set-var-var-conf! v
|
|
(union-vars vs (var-var-conf v))))
|
|
(define (mark-var/frms-conf! v fs)
|
|
(set-var-frm-conf! v
|
|
(union-frms fs (var-frm-conf v))))
|
|
(define (mark-var/regs-conf! v rs)
|
|
(set-var-reg-conf! v
|
|
(union-regs rs (var-reg-conf v))))
|
|
(define (mark-var/nfvs-conf! v ns)
|
|
(for-each-nfv ns
|
|
(lambda (n)
|
|
(set-nfv-var-conf! n
|
|
(add-var v (nfv-var-conf n))))))
|
|
(define (mark-nfv/vars-conf! n vs)
|
|
(set-nfv-var-conf! n
|
|
(union-vars vs (nfv-var-conf n))))
|
|
(define (mark-nfv/frms-conf! n fs)
|
|
(set-nfv-frm-conf! n
|
|
(union-frms fs (nfv-frm-conf n))))
|
|
(define (mark-nfv/nfvs-conf! n ns)
|
|
(set-nfv-nfv-conf! n
|
|
(union-nfvs ns (nfv-nfv-conf n)))
|
|
(for-each-nfv ns
|
|
(lambda (m)
|
|
(set-nfv-nfv-conf! m
|
|
(add-nfv n (nfv-nfv-conf m))))))
|
|
(define (mark-var/var-move! x y)
|
|
(set-var-var-move! x
|
|
(add-var y (var-var-move x)))
|
|
(set-var-var-move! y
|
|
(add-var x (var-var-move y))))
|
|
(define (mark-var/frm-move! x y)
|
|
(set-var-frm-move! x
|
|
(add-frm y (var-frm-move x))))
|
|
(define (mark-var/reg-move! x y)
|
|
(set-var-reg-move! x
|
|
(add-reg y (var-reg-move x))))
|
|
(define (const? x)
|
|
(or (constant? x)
|
|
(code-loc? x)))
|
|
(define (R x vs rs fs ns)
|
|
(cond
|
|
[(const? x) (values vs rs fs ns)]
|
|
[(reg? x)
|
|
(values vs (add-reg x rs) fs ns)]
|
|
[(fvar? x)
|
|
(values vs rs (add-frm x fs) ns)]
|
|
[(var? x)
|
|
(values (add-var x vs) rs fs ns)]
|
|
[(nfv? x)
|
|
(values vs rs fs (add-nfv x ns))]
|
|
[(disp? x)
|
|
(let-values ([(vs rs fs ns) (R (disp-s0 x) vs rs fs ns)])
|
|
(R (disp-s1 x) vs rs fs ns))]
|
|
[else (error who "invalid R" x)]))
|
|
(define (R* ls vs rs fs ns)
|
|
(cond
|
|
[(null? ls) (values vs rs fs ns)]
|
|
[else
|
|
(let-values ([(vs rs fs ns) (R (car ls) vs rs fs ns)])
|
|
(R* (cdr ls) vs rs fs ns))]))
|
|
(define (E x vs rs fs ns)
|
|
(struct-case x
|
|
[(seq e0 e1)
|
|
(let-values ([(vs rs fs ns) (E e1 vs rs fs ns)])
|
|
(E e0 vs rs fs ns))]
|
|
[(conditional e0 e1 e2)
|
|
(let-values ([(vs1 rs1 fs1 ns1) (E e1 vs rs fs ns)]
|
|
[(vs2 rs2 fs2 ns2) (E e2 vs rs fs ns)])
|
|
(P e0
|
|
vs1 rs1 fs1 ns1
|
|
vs2 rs2 fs2 ns2
|
|
(union-vars vs1 vs2)
|
|
(union-regs rs1 rs2)
|
|
(union-frms fs1 fs2)
|
|
(union-nfvs ns1 ns2)))]
|
|
[(asm-instr op d s)
|
|
(case op
|
|
[(move move-byte load32)
|
|
(cond
|
|
[(reg? d)
|
|
(cond
|
|
[(not (mem-reg? d rs))
|
|
(set-asm-instr-op! x 'nop)
|
|
(values vs rs fs ns)]
|
|
[(or (const? s) (disp? s) (reg? s))
|
|
(let ([rs (rem-reg d rs)])
|
|
(mark-reg/vars-conf! d vs)
|
|
(R s vs rs fs ns))]
|
|
[(var? s)
|
|
(let ([rs (rem-reg d rs)]
|
|
[vs (rem-var s vs)])
|
|
(mark-var/reg-move! s d)
|
|
(mark-reg/vars-conf! d vs)
|
|
(values (add-var s vs) rs fs ns))]
|
|
[(fvar? s)
|
|
(let ([rs (rem-reg d rs)])
|
|
(mark-reg/vars-conf! d vs)
|
|
(values vs rs (add-frm s fs) ns))]
|
|
[else (error who "invalid rs" (unparse x))])]
|
|
[(fvar? d)
|
|
(cond
|
|
[(not (mem-frm? d fs))
|
|
(set-asm-instr-op! x 'nop)
|
|
(values vs rs fs ns)]
|
|
[(or (const? s) (disp? s) (reg? s))
|
|
(let ([fs (rem-frm d fs)])
|
|
(mark-frm/vars-conf! d vs)
|
|
(mark-frm/nfvs-conf! d ns)
|
|
(R s vs rs fs ns))]
|
|
[(var? s)
|
|
(let ([fs (rem-frm d fs)]
|
|
[vs (rem-var s vs)])
|
|
(mark-var/frm-move! s d)
|
|
(mark-frm/vars-conf! d vs)
|
|
(mark-frm/nfvs-conf! d ns)
|
|
(values (add-var s vs) rs fs ns))]
|
|
[else (error who "invalid fs" s)])]
|
|
[(var? d)
|
|
(cond
|
|
[(not (mem-var? d vs))
|
|
(set-asm-instr-op! x 'nop)
|
|
(values vs rs fs ns)]
|
|
[(or (disp? s) (constant? s))
|
|
(let ([vs (rem-var d vs)])
|
|
(mark-var/vars-conf! d vs)
|
|
(mark-var/frms-conf! d fs)
|
|
(mark-var/regs-conf! d rs)
|
|
(mark-var/nfvs-conf! d ns)
|
|
(R s vs rs fs ns))]
|
|
[(reg? s)
|
|
(let ([vs (rem-var d vs)]
|
|
[rs (rem-reg s rs)])
|
|
(mark-var/reg-move! d s)
|
|
(mark-var/vars-conf! d vs)
|
|
(mark-var/frms-conf! d fs)
|
|
(mark-var/regs-conf! d rs)
|
|
(mark-var/nfvs-conf! d ns)
|
|
(values vs (add-reg s rs) fs ns))]
|
|
[(var? s)
|
|
(let ([vs (rem-var d (rem-var s vs))])
|
|
(mark-var/var-move! d s)
|
|
(mark-var/vars-conf! d vs)
|
|
(mark-var/frms-conf! d fs)
|
|
(mark-var/regs-conf! d rs)
|
|
(mark-var/nfvs-conf! d ns)
|
|
(values (add-var s vs) rs fs ns))]
|
|
[(fvar? s)
|
|
(let ([vs (rem-var d vs)]
|
|
[fs (rem-frm s fs)])
|
|
(mark-var/frm-move! d s)
|
|
(mark-var/vars-conf! d vs)
|
|
(mark-var/frms-conf! d fs)
|
|
(mark-var/regs-conf! d rs)
|
|
(mark-var/nfvs-conf! d ns)
|
|
(values vs rs (add-frm s fs) ns))]
|
|
[else (error who "invalid vs" s)])]
|
|
[(nfv? d)
|
|
(cond
|
|
[(not (mem-nfv? d ns)) (error who "dead nfv")]
|
|
[(or (disp? s) (constant? s) (reg? s))
|
|
(let ([ns (rem-nfv d ns)])
|
|
(mark-nfv/vars-conf! d vs)
|
|
(mark-nfv/frms-conf! d fs)
|
|
(R s vs rs fs ns))]
|
|
[(var? s)
|
|
(let ([ns (rem-nfv d ns)]
|
|
[vs (rem-var s vs)])
|
|
(mark-nfv/vars-conf! d vs)
|
|
(mark-nfv/frms-conf! d fs)
|
|
(values (add-var s vs) rs fs ns))]
|
|
[(fvar? s)
|
|
(let ([ns (rem-nfv d ns)]
|
|
[fs (rem-frm s fs)])
|
|
(mark-nfv/vars-conf! d vs)
|
|
(mark-nfv/frms-conf! d fs)
|
|
(values vs rs (add-frm s fs) ns))]
|
|
[else (error who "invalid ns" s)])]
|
|
[else (error who "invalid d" d)])]
|
|
[(int-/overflow int+/overflow int*/overflow)
|
|
(let ([v (exception-live-set)])
|
|
(unless (vector? v)
|
|
(error who "unbound exception" x v))
|
|
(let ([vs (union-vars vs (vector-ref v 0))]
|
|
[rs (union-regs rs (vector-ref v 1))]
|
|
[fs (union-frms fs (vector-ref v 2))]
|
|
[ns (union-nfvs ns (vector-ref v 3))])
|
|
(cond
|
|
[(var? d)
|
|
(cond
|
|
[(not (mem-var? d vs))
|
|
(set-asm-instr-op! x 'nop)
|
|
(values vs rs fs ns)]
|
|
[else
|
|
(let ([vs (rem-var d vs)])
|
|
(mark-var/vars-conf! d vs)
|
|
(mark-var/frms-conf! d fs)
|
|
(mark-var/nfvs-conf! d ns)
|
|
(mark-var/regs-conf! d rs)
|
|
(R s (add-var d vs) rs fs ns))])]
|
|
[(reg? d)
|
|
(cond
|
|
[(not (mem-reg? d rs))
|
|
(values vs rs fs ns)]
|
|
[else
|
|
(let ([rs (rem-reg d rs)])
|
|
(mark-reg/vars-conf! d vs)
|
|
(R s vs (add-reg d rs) fs ns))])]
|
|
[(nfv? d)
|
|
(cond
|
|
[(not (mem-nfv? d ns)) (error who "dead nfv")]
|
|
[else
|
|
(let ([ns (rem-nfv d ns)])
|
|
(mark-nfv/vars-conf! d vs)
|
|
(mark-nfv/frms-conf! d fs)
|
|
(R s vs rs fs (add-nfv d ns)))])]
|
|
[else (error who "invalid op d" (unparse x))])))]
|
|
[(nop) (values vs rs fs ns)]
|
|
[(logand logor logxor sll sra srl int+ int- int* bswap!
|
|
sll/overflow)
|
|
(cond
|
|
[(var? d)
|
|
(cond
|
|
[(not (mem-var? d vs))
|
|
(set-asm-instr-op! x 'nop)
|
|
(values vs rs fs ns)]
|
|
[else
|
|
(let ([vs (rem-var d vs)])
|
|
(mark-var/vars-conf! d vs)
|
|
(mark-var/frms-conf! d fs)
|
|
(mark-var/nfvs-conf! d ns)
|
|
(mark-var/regs-conf! d rs)
|
|
(R s (add-var d vs) rs fs ns))])]
|
|
[(reg? d)
|
|
(cond
|
|
[(not (mem-reg? d rs))
|
|
(set-asm-instr-op! x 'nop)
|
|
(values vs rs fs ns)]
|
|
[else
|
|
(let ([rs (rem-reg d rs)])
|
|
(mark-reg/vars-conf! d vs)
|
|
(R s vs (add-reg d rs) fs ns))])]
|
|
[(nfv? d)
|
|
(cond
|
|
[(not (mem-nfv? d ns)) (error who "dead nfv")]
|
|
[else
|
|
(let ([ns (rem-nfv d ns)])
|
|
(mark-nfv/vars-conf! d vs)
|
|
(mark-nfv/frms-conf! d fs)
|
|
(R s vs rs fs (add-nfv d ns)))])]
|
|
[else (error who "invalid op d" (unparse x))])]
|
|
[(idiv)
|
|
(mark-reg/vars-conf! eax vs)
|
|
(mark-reg/vars-conf! edx vs)
|
|
(R s vs (add-reg eax (add-reg edx rs)) fs ns)]
|
|
[(cltd)
|
|
(mark-reg/vars-conf! edx vs)
|
|
(R s vs (rem-reg edx rs) fs ns)]
|
|
[(mset mset32 bset bset/c
|
|
fl:load fl:store fl:add! fl:sub! fl:mul! fl:div! fl:from-int
|
|
fl:shuffle fl:load-single fl:store-single)
|
|
(R* (list s d) vs rs fs ns)]
|
|
[else (error who "invalid effect op" (unparse x))])]
|
|
[(ntcall target value args mask size)
|
|
(set! spill-set (union-vars vs spill-set))
|
|
(for-each-var vs varvec (lambda (x) (set-var-loc! x #t)))
|
|
(R* args vs (empty-reg-set) fs ns)]
|
|
[(nframe nfvs live body)
|
|
(for-each init-nfv! nfvs)
|
|
(set-nframe-live! x (vector vs fs ns))
|
|
(E body vs rs fs ns)]
|
|
[(primcall op args)
|
|
(case op
|
|
[(nop fl:double->single fl:single->double) (values vs rs fs ns)]
|
|
[(interrupt incr/zero?)
|
|
(let ([v (exception-live-set)])
|
|
(unless (vector? v)
|
|
(error who "unbound exception2"))
|
|
(values (vector-ref v 0)
|
|
(vector-ref v 1)
|
|
(vector-ref v 2)
|
|
(vector-ref v 3)))]
|
|
[else (error who "invalid effect op" op)])]
|
|
[(shortcut body handler)
|
|
(let-values ([(vsh rsh fsh nsh) (E handler vs rs fs ns)])
|
|
(parameterize ([exception-live-set
|
|
(vector vsh rsh fsh nsh)])
|
|
(E body vs rs fs ns)))]
|
|
[else (error who "invalid effect" (unparse x))]))
|
|
(define (P x vst rst fst nst
|
|
vsf rsf fsf nsf
|
|
vsu rsu fsu nsu)
|
|
(struct-case x
|
|
[(seq e0 e1)
|
|
(let-values ([(vs rs fs ns)
|
|
(P e1 vst rst fst nst
|
|
vsf rsf fsf nsf
|
|
vsu rsu fsu nsu)])
|
|
(E e0 vs rs fs ns))]
|
|
[(conditional e0 e1 e2)
|
|
(let-values ([(vs1 rs1 fs1 ns1)
|
|
(P e1 vst rst fst nst
|
|
vsf rsf fsf nsf
|
|
vsu rsu fsu nsu)]
|
|
[(vs2 rs2 fs2 ns2)
|
|
(P e2 vst rst fst nst
|
|
vsf rsf fsf nsf
|
|
vsu rsu fsu nsu)])
|
|
(P e0
|
|
vs1 rs1 fs1 ns1
|
|
vs2 rs2 fs2 ns2
|
|
(union-vars vs1 vs2)
|
|
(union-regs rs1 rs2)
|
|
(union-frms fs1 fs2)
|
|
(union-nfvs ns1 ns2)))]
|
|
[(constant t)
|
|
(if t
|
|
(values vst rst fst nst)
|
|
(values vsf rsf fsf nsf))]
|
|
[(asm-instr op d s)
|
|
(R* (list d s) vsu rsu fsu nsu)]
|
|
[(shortcut body handler)
|
|
(let-values ([(vsh rsh fsh nsh)
|
|
(P handler vst rst fst nst
|
|
vsf rsf fsf nsf
|
|
vsu rsu fsu nsu)])
|
|
(parameterize ([exception-live-set
|
|
(vector vsh rsh fsh nsh)])
|
|
(P body vst rst fst nst
|
|
vsf rsf fsf nsf
|
|
vsu rsu fsu nsu)))]
|
|
[else (error who "invalid pred" (unparse x))]))
|
|
(define (T x)
|
|
(struct-case x
|
|
[(seq e0 e1)
|
|
(let-values ([(vs rs fs ns) (T e1)])
|
|
(E e0 vs rs fs ns))]
|
|
[(conditional e0 e1 e2)
|
|
(let-values ([(vs1 rs1 fs1 ns1) (T e1)]
|
|
[(vs2 rs2 fs2 ns2) (T e2)])
|
|
(P e0
|
|
vs1 rs1 fs1 ns1
|
|
vs2 rs2 fs2 ns2
|
|
(union-vars vs1 vs2)
|
|
(union-regs rs1 rs2)
|
|
(union-frms fs1 fs2)
|
|
(union-nfvs ns1 ns2)))]
|
|
[(primcall op arg*)
|
|
(case op
|
|
[(return indirect-jump direct-jump)
|
|
(R* arg* (empty-var-set)
|
|
(empty-reg-set)
|
|
(empty-frm-set)
|
|
(empty-nfv-set))]
|
|
[else (error who "invalid tail op" x)])]
|
|
[(shortcut body handler)
|
|
(let-values ([(vsh rsh fsh nsh) (T handler)])
|
|
(parameterize ([exception-live-set
|
|
(vector vsh rsh fsh nsh)])
|
|
(T body)))]
|
|
[else (error who "invalid tail" x)]))
|
|
(define exception-live-set
|
|
(make-parameter #f))
|
|
(T x)
|
|
spill-set)
|
|
|
|
|
|
|
|
(module (assign-frame-sizes)
|
|
;;; assign-frame-sizes module
|
|
(define indent (make-parameter 0))
|
|
(import IntegerSet)
|
|
(import conflict-helpers)
|
|
(define (rewrite x varvec)
|
|
(define who 'rewrite)
|
|
(define (assign x)
|
|
(let ()
|
|
(define (assign-any)
|
|
(let ([frms (var-frm-conf x)]
|
|
[vars (var-var-conf x)])
|
|
(let f ([i 1])
|
|
(cond
|
|
[(set-member? i frms) (f (fxadd1 i))]
|
|
[else
|
|
(let ([fv (mkfvar i)])
|
|
(set-var-loc! x fv)
|
|
(for-each-var vars varvec
|
|
(lambda (var)
|
|
(set-var-frm-conf! var
|
|
(add-frm fv (var-frm-conf var)))))
|
|
fv)]))))
|
|
(define (assign-move x)
|
|
(let ([mr (set->list
|
|
(set-difference
|
|
(var-frm-move x)
|
|
(var-frm-conf x)))])
|
|
(cond
|
|
[(null? mr) #f]
|
|
[else
|
|
(let ([fv (mkfvar (car mr))])
|
|
(set-var-loc! x fv)
|
|
(for-each-var (var-var-conf x) varvec
|
|
(lambda (var)
|
|
(set-var-frm-conf! var
|
|
(add-frm fv (var-frm-conf var)))))
|
|
(for-each-var (var-var-move x) varvec
|
|
(lambda (var)
|
|
(set-var-frm-move! var
|
|
(add-frm fv (var-frm-move var)))))
|
|
fv)])))
|
|
(or (assign-move x)
|
|
(assign-any))))
|
|
(define (NFE idx mask x)
|
|
(struct-case x
|
|
[(seq e0 e1)
|
|
(let ([e0 (E e0)])
|
|
(make-seq e0 (NFE idx mask e1)))]
|
|
[(ntcall target value args mask^ size)
|
|
(make-ntcall target value
|
|
(map (lambda (x)
|
|
(cond
|
|
[(symbol? x) x]
|
|
[(nfv? x) (nfv-loc x)]
|
|
[else (error who "invalid arg")]))
|
|
args)
|
|
mask idx)]
|
|
[else (error who "invalid NF effect" x)]))
|
|
(define (Var x)
|
|
(cond
|
|
[(var-loc x) =>
|
|
(lambda (loc)
|
|
(if (fvar? loc)
|
|
loc
|
|
(assign x)))]
|
|
[else x]))
|
|
(define (R x)
|
|
(cond
|
|
[(or (constant? x) (reg? x) (fvar? x)) x]
|
|
[(nfv? x)
|
|
(or (nfv-loc x)
|
|
(error who "unassigned nfv"))]
|
|
[(var? x) (Var x)]
|
|
[(disp? x)
|
|
(make-disp (R (disp-s0 x)) (R (disp-s1 x)))]
|
|
[else (error who "invalid R" (unparse x))]))
|
|
(define (E x)
|
|
(struct-case x
|
|
[(seq e0 e1)
|
|
(let ([e0 (E e0)])
|
|
(make-seq e0 (E e1)))]
|
|
[(conditional e0 e1 e2)
|
|
(make-conditional (P e0) (E e1) (E e2))]
|
|
[(asm-instr op d s)
|
|
(case op
|
|
[(move move-byte load32)
|
|
(let ([d (R d)] [s (R s)])
|
|
(cond
|
|
[(eq? d s)
|
|
(make-primcall 'nop '())]
|
|
[else
|
|
(make-asm-instr op d s)]))]
|
|
[(logand logor logxor int+ int- int* mset bset mset32 bset/c
|
|
sll sra srl bswap!
|
|
cltd idiv int-/overflow int+/overflow int*/overflow
|
|
fl:load fl:store fl:add! fl:sub! fl:mul! fl:div!
|
|
fl:from-int fl:shuffle fl:load-single fl:store-single
|
|
sll/overflow)
|
|
(make-asm-instr op (R d) (R s))]
|
|
[(nop) (make-primcall 'nop '())]
|
|
[else (error who "invalid op" op)])]
|
|
[(nframe vars live body)
|
|
(let ([live-frms1
|
|
(map (lambda (i) (Var (vector-ref varvec i)))
|
|
(set->list (vector-ref live 0)))]
|
|
[live-frms2 (set->list (vector-ref live 1))]
|
|
[live-nfvs (vector-ref live 2)])
|
|
(define (max-frm ls i)
|
|
(cond
|
|
[(null? ls) i]
|
|
[else
|
|
(max-frm (cdr ls)
|
|
(max i (fvar-idx (car ls))))]))
|
|
(define (max-ls ls i)
|
|
(cond
|
|
[(null? ls) i]
|
|
[else
|
|
(max-ls (cdr ls) (max i (car ls)))]))
|
|
(define (max-nfv ls i)
|
|
(cond
|
|
[(null? ls) i]
|
|
[else
|
|
(let ([loc (nfv-loc (car ls))])
|
|
(unless (fvar? loc) (error 'max-nfv "not assigned"))
|
|
(max-nfv (cdr ls) (max i (fvar-idx loc))))]))
|
|
(define (actual-frame-size vars i)
|
|
(define (var-conflict? i vs)
|
|
(ormap (lambda (xi)
|
|
(let ([loc (var-loc (vector-ref varvec xi))])
|
|
(and (fvar? loc)
|
|
(fx= i (fvar-idx loc)))))
|
|
(set->list vs)))
|
|
(define (frame-size-ok? i vars)
|
|
(or (null? vars)
|
|
(let ([x (car vars)])
|
|
(and (not (set-member? i (nfv-frm-conf x)))
|
|
(not (var-conflict? i (nfv-var-conf x)))
|
|
(frame-size-ok? (fxadd1 i) (cdr vars))))))
|
|
(cond
|
|
[(frame-size-ok? i vars) i]
|
|
[else (actual-frame-size vars (fxadd1 i))]))
|
|
(define (assign-frame-vars! vars i)
|
|
(unless (null? vars)
|
|
(let ([v (car vars)] [fv (mkfvar i)])
|
|
(set-nfv-loc! v fv)
|
|
;(for-each
|
|
; (lambda (j)
|
|
; (when (fx= j i)
|
|
; (error who "invalid assignment")))
|
|
; (set->list (nfv-frm-conf v)))
|
|
(for-each
|
|
(lambda (x)
|
|
(let ([loc (nfv-loc x)])
|
|
(cond
|
|
[loc
|
|
(when (fx= (fvar-idx loc) i)
|
|
(error who "invalid assignment"))]
|
|
[else
|
|
(set-nfv-nfv-conf! x
|
|
(rem-nfv v (nfv-nfv-conf x)))
|
|
(set-nfv-frm-conf! x
|
|
(add-frm fv (nfv-frm-conf x)))])))
|
|
(nfv-nfv-conf v))
|
|
(for-each-var (nfv-var-conf v) varvec
|
|
(lambda (x)
|
|
(let ([loc (var-loc x)])
|
|
(cond
|
|
[(fvar? loc)
|
|
(when (fx= (fvar-idx loc) i)
|
|
(error who "invalid assignment"))]
|
|
[else
|
|
(set-var-frm-conf! x
|
|
(add-frm fv (var-frm-conf x)))])))))
|
|
(assign-frame-vars! (cdr vars) (fxadd1 i))))
|
|
(define (make-mask n)
|
|
(let ([v (make-vector (fxsra (fx+ n 7) 3) 0)])
|
|
(define (set-bit idx)
|
|
(let ([q (fxsra idx 3)]
|
|
[r (fxlogand idx 7)])
|
|
(vector-set! v q
|
|
(fxlogor (vector-ref v q) (fxsll 1 r)))))
|
|
(for-each (lambda (x) (set-bit (fvar-idx x))) live-frms1)
|
|
(for-each set-bit live-frms2)
|
|
(for-each (lambda (x)
|
|
(let ([loc (nfv-loc x)])
|
|
(when loc
|
|
(set-bit (fvar-idx loc)))))
|
|
live-nfvs) v))
|
|
(let ([i (actual-frame-size vars
|
|
(fx+ 2
|
|
(max-frm live-frms1
|
|
(max-nfv live-nfvs
|
|
(max-ls live-frms2 0)))))])
|
|
(assign-frame-vars! vars i)
|
|
(NFE (fxsub1 i) (make-mask (fxsub1 i)) body)))]
|
|
[(primcall op args)
|
|
(case op
|
|
[(nop interrupt incr/zero? fl:double->single
|
|
fl:single->double) x]
|
|
[else (error who "invalid effect prim" op)])]
|
|
[(shortcut body handler)
|
|
(make-shortcut (E body) (E handler))]
|
|
[else (error who "invalid effect" (unparse x))]))
|
|
(define (P x)
|
|
(struct-case x
|
|
[(seq e0 e1)
|
|
(let ([e0 (E e0)])
|
|
(make-seq e0 (P e1)))]
|
|
[(conditional e0 e1 e2)
|
|
(make-conditional (P e0) (P e1) (P e2))]
|
|
[(asm-instr op d s) (make-asm-instr op (R d) (R s))]
|
|
[(constant) x]
|
|
[(shortcut body handler)
|
|
(make-shortcut (P body) (P handler))]
|
|
[else (error who "invalid pred" (unparse x))]))
|
|
(define (T x)
|
|
(struct-case x
|
|
[(seq e0 e1)
|
|
(let ([e0 (E e0)])
|
|
(make-seq e0 (T e1)))]
|
|
[(conditional e0 e1 e2)
|
|
(make-conditional (P e0) (T e1) (T e2))]
|
|
[(primcall op args) x]
|
|
[(shortcut body handler)
|
|
(make-shortcut (T body) (T handler))]
|
|
[else (error who "invalid tail" (unparse x))]))
|
|
(T x))
|
|
;;;
|
|
(define (Main x)
|
|
(struct-case x
|
|
[(locals vars body)
|
|
(init-vars! vars)
|
|
(let ([varvec (list->vector vars)])
|
|
(let ([call-live* (uncover-frame-conflicts body varvec)])
|
|
(let ([body (rewrite body varvec)])
|
|
(make-locals
|
|
(cons varvec
|
|
(let f ([vars vars])
|
|
(cond
|
|
[(null? vars) '()]
|
|
[(var-loc (car vars)) (f (cdr vars))]
|
|
[else (cons (car vars) (f (cdr vars)))])))
|
|
body))))]
|
|
[else (error 'assign-frame-sizes "invalid main" x)]))
|
|
;;;
|
|
(define (ClambdaCase x)
|
|
(struct-case x
|
|
[(clambda-case info body)
|
|
(make-clambda-case info (Main body))]))
|
|
;;;
|
|
(define (Clambda x)
|
|
(struct-case x
|
|
[(clambda label case* cp free* name)
|
|
(make-clambda label (map ClambdaCase case*) cp free* name)]))
|
|
;;;
|
|
(define (Program x)
|
|
(struct-case x
|
|
[(codes code* body)
|
|
(make-codes (map Clambda code*) (Main body))]))
|
|
;;;
|
|
(define (assign-frame-sizes x)
|
|
(let ([v (Program x)])
|
|
v)))
|
|
|
|
|
|
|
|
|
|
(module (color-by-chaitin)
|
|
(import ListySet)
|
|
(import ListyGraphs)
|
|
;(import IntegerSet)
|
|
;(import IntegerGraphs)
|
|
;;;
|
|
(define (set-for-each f s)
|
|
(for-each f (set->list s)))
|
|
;;;
|
|
(define (build-graph x)
|
|
(define who 'build-graph)
|
|
(define g (empty-graph))
|
|
(define (R* ls)
|
|
(cond
|
|
[(null? ls) (make-empty-set)]
|
|
[else (set-union (R (car ls)) (R* (cdr ls)))]))
|
|
(define (R x)
|
|
(struct-case x
|
|
[(constant) (make-empty-set)]
|
|
[(var) (list->set (list x))]
|
|
[(disp s0 s1) (set-union (R s0) (R s1))]
|
|
[(fvar) (make-empty-set)]
|
|
[(code-loc) (make-empty-set)]
|
|
[else
|
|
(cond
|
|
[(symbol? x)
|
|
(if (memq x all-registers)
|
|
(set-add x (make-empty-set))
|
|
(make-empty-set))]
|
|
[else (error who "invalid R" x)])]))
|
|
;;; build effect
|
|
(define (E x s)
|
|
(struct-case x
|
|
[(asm-instr op d v)
|
|
(case op
|
|
[(move load32)
|
|
(let ([s (set-rem d s)])
|
|
(set-for-each (lambda (y) (add-edge! g d y)) s)
|
|
(set-union (R v) s))]
|
|
[(move-byte)
|
|
(let ([s (set-rem d s)])
|
|
(set-for-each (lambda (y) (add-edge! g d y)) s)
|
|
(when (var? d)
|
|
(for-each (lambda (r) (add-edge! g d r)) non-8bit-registers))
|
|
(when (var? v)
|
|
(for-each (lambda (r) (add-edge! g v r)) non-8bit-registers))
|
|
(set-union (R v) s))]
|
|
[(int-/overflow int+/overflow int*/overflow)
|
|
(unless (exception-live-set)
|
|
(error who "uninitialized live set"))
|
|
(let ([s (set-rem d (set-union s (exception-live-set)))])
|
|
(set-for-each (lambda (y) (add-edge! g d y)) s)
|
|
(set-union (set-union (R v) (R d)) s))]
|
|
[(logand logxor int+ int- int* logor sll sra srl bswap!
|
|
sll/overflow)
|
|
(let ([s (set-rem d s)])
|
|
(set-for-each (lambda (y) (add-edge! g d y)) s)
|
|
(set-union (set-union (R v) (R d)) s))]
|
|
[(bset/c)
|
|
(set-union (set-union (R v) (R d)) s)]
|
|
[(bset)
|
|
(when (var? v)
|
|
(for-each (lambda (r) (add-edge! g v r))
|
|
non-8bit-registers))
|
|
(set-union (set-union (R v) (R d)) s)]
|
|
[(cltd)
|
|
(let ([s (set-rem edx s)])
|
|
(when (register? edx)
|
|
(set-for-each (lambda (y) (add-edge! g edx y)) s))
|
|
(set-union (R eax) s))]
|
|
[(idiv)
|
|
(let ([s (set-rem eax (set-rem edx s))])
|
|
(when (register? eax)
|
|
(set-for-each
|
|
(lambda (y) (add-edge! g eax y) (add-edge! g edx y))
|
|
s))
|
|
(set-union (set-union (R eax) (R edx))
|
|
(set-union (R v) s)))]
|
|
[(mset mset32 fl:load fl:store fl:add! fl:sub! fl:mul! fl:div!
|
|
fl:from-int fl:shuffle fl:store-single
|
|
fl:load-single)
|
|
(set-union (R v) (set-union (R d) s))]
|
|
[else (error who "invalid effect" x)])]
|
|
[(seq e0 e1) (E e0 (E e1 s))]
|
|
[(conditional e0 e1 e2)
|
|
(let ([s1 (E e1 s)] [s2 (E e2 s)])
|
|
(P e0 s1 s2 (set-union s1 s2)))]
|
|
[(ntcall targ value args mask size)
|
|
(set-union (R* args) s)]
|
|
[(primcall op arg*)
|
|
(case op
|
|
[(nop fl:single->double fl:double->single) s]
|
|
[(interrupt incr/zero?)
|
|
(or (exception-live-set) (error who "uninitialized exception"))]
|
|
[else (error who "invalid effect primcall" op)])]
|
|
[(shortcut body handler)
|
|
(let ([s2 (E handler s)])
|
|
(parameterize ([exception-live-set s2])
|
|
(E body s)))]
|
|
[else (error who "invalid effect" (unparse x))]))
|
|
(define (P x st sf su)
|
|
(struct-case x
|
|
[(constant c) (if c st sf)]
|
|
[(seq e0 e1)
|
|
(E e0 (P e1 st sf su))]
|
|
[(conditional e0 e1 e2)
|
|
(let ([s1 (P e1 st sf su)] [s2 (P e2 st sf su)])
|
|
(P e0 s1 s2 (set-union s1 s2)))]
|
|
[(asm-instr op s0 s1)
|
|
(set-union (set-union (R s0) (R s1)) su)]
|
|
[(shortcut body handler)
|
|
(let ([s2 (P handler st sf su)])
|
|
(parameterize ([exception-live-set s2])
|
|
(P body st sf su)))]
|
|
[else (error who "invalid pred" (unparse x))]))
|
|
(define (T x)
|
|
(struct-case x
|
|
[(conditional e0 e1 e2)
|
|
(let ([s1 (T e1)] [s2 (T e2)])
|
|
(P e0 s1 s2 (set-union s1 s2)))]
|
|
[(primcall op rands)
|
|
(R* rands)]
|
|
[(seq e0 e1) (E e0 (T e1))]
|
|
[(shortcut body handler)
|
|
(let ([s2 (T handler)])
|
|
(parameterize ([exception-live-set s2])
|
|
(T body)))]
|
|
[else (error who "invalid tail" (unparse x))]))
|
|
(define exception-live-set (make-parameter #f))
|
|
(let ([s (T x)])
|
|
;(pretty-print (unparse x))
|
|
;(print-graph g)
|
|
g))
|
|
;;;
|
|
(define (color-graph sp* un* g)
|
|
(define (find-low-degree ls g)
|
|
(cond
|
|
[(null? ls) #f]
|
|
[(fx< (length (set->list (node-neighbors (car ls) g)))
|
|
(length all-registers))
|
|
(car ls)]
|
|
[else (find-low-degree (cdr ls) g)]))
|
|
(define (find-color/maybe x confs env)
|
|
(let ([cr (map (lambda (x)
|
|
(cond
|
|
[(symbol? x) x]
|
|
[(assq x env) => cdr]
|
|
[else #f]))
|
|
(set->list confs))])
|
|
(let ([r* (set->list
|
|
(set-difference
|
|
(list->set all-registers)
|
|
(list->set cr)))])
|
|
(if (null? r*)
|
|
#f
|
|
(car r*)))))
|
|
(define (find-color x confs env)
|
|
(or (find-color/maybe x confs env)
|
|
(error 'find-color "cannot find color for" x)))
|
|
(cond
|
|
[(and (empty-set? sp*) (empty-set? un*))
|
|
(values '() (make-empty-set) '())]
|
|
[(find-low-degree (set->list un*) g) =>
|
|
(lambda (un)
|
|
(let ([n* (node-neighbors un g)])
|
|
(delete-node! un g)
|
|
(let-values ([(spills sp* env)
|
|
(color-graph sp* (set-rem un un*) g)])
|
|
(let ([r (find-color un n* env)])
|
|
(values spills sp*
|
|
(cons (cons un r) env))))))]
|
|
[(find-low-degree (set->list sp*) g) =>
|
|
(lambda (sp)
|
|
(let ([n* (node-neighbors sp g)])
|
|
(delete-node! sp g)
|
|
(let-values ([(spills sp* env)
|
|
(color-graph (set-rem sp sp*) un* g)])
|
|
(let ([r (find-color sp n* env)])
|
|
(values spills (set-add sp sp*)
|
|
(cons (cons sp r) env))))))]
|
|
[(pair? (set->list sp*))
|
|
(let ([sp (car (set->list sp*))])
|
|
(let ([n* (node-neighbors sp g)])
|
|
(delete-node! sp g)
|
|
(let-values ([(spills sp* env)
|
|
(color-graph (set-rem sp sp*) un* g)])
|
|
(let ([r (find-color/maybe sp n* env)])
|
|
(if r
|
|
(values spills (set-add sp sp*)
|
|
(cons (cons sp r) env))
|
|
(values (cons sp spills) sp* env))))))]
|
|
[else (error 'color-graph "whoaaa")]))
|
|
;;;
|
|
(define (substitute env x)
|
|
(define who 'substitute)
|
|
(define (Var x)
|
|
(cond
|
|
[(assq x env) => cdr]
|
|
[else x]))
|
|
(define (Rhs x)
|
|
(struct-case x
|
|
[(var) (Var x)]
|
|
[(primcall op rand*)
|
|
(make-primcall op (map Rand rand*))]
|
|
[else x]))
|
|
(define (Rand x)
|
|
(struct-case x
|
|
[(var) (Var x)]
|
|
[else x]))
|
|
(define (Lhs x)
|
|
(struct-case x
|
|
[(var) (Var x)]
|
|
[(nfv confs loc)
|
|
(or loc (error who "LHS not set" x))]
|
|
[else x]))
|
|
(define (D x)
|
|
(struct-case x
|
|
[(constant) x]
|
|
[(var) (Var x)]
|
|
[(fvar) x]
|
|
[else
|
|
(if (symbol? x) x (error who "invalid D" x))]))
|
|
(define (R x)
|
|
(struct-case x
|
|
[(constant) x]
|
|
[(var) (Var x)]
|
|
[(fvar) x]
|
|
[(nfv c loc)
|
|
(or loc (error who "unset nfv in R" x))]
|
|
[(disp s0 s1) (make-disp (D s0) (D s1))]
|
|
[else
|
|
(if (symbol? x) x (error who "invalid R" x))]))
|
|
;;; substitute effect
|
|
(define (E x)
|
|
(struct-case x
|
|
[(seq e0 e1) (make-seq (E e0) (E e1))]
|
|
[(conditional e0 e1 e2)
|
|
(make-conditional (P e0) (E e1) (E e2))]
|
|
[(asm-instr op x v)
|
|
(make-asm-instr op (R x) (R v))]
|
|
[(primcall op rands)
|
|
(make-primcall op (map R rands))]
|
|
[(ntcall) x]
|
|
[(shortcut body handler)
|
|
(make-shortcut (E body) (E handler))]
|
|
[else (error who "invalid effect" (unparse x))]))
|
|
(define (P x)
|
|
(struct-case x
|
|
[(constant) x]
|
|
[(asm-instr op x v)
|
|
(make-asm-instr op (R x) (R v))]
|
|
[(conditional e0 e1 e2)
|
|
(make-conditional (P e0) (P e1) (P e2))]
|
|
[(seq e0 e1) (make-seq (E e0) (P e1))]
|
|
[(shortcut body handler)
|
|
(make-shortcut (P body) (P handler))]
|
|
[else (error who "invalid pred" (unparse x))]))
|
|
(define (T x)
|
|
(struct-case x
|
|
[(primcall op rands) x]
|
|
[(conditional e0 e1 e2)
|
|
(make-conditional (P e0) (T e1) (T e2))]
|
|
[(seq e0 e1) (make-seq (E e0) (T e1))]
|
|
[(shortcut body handler)
|
|
(make-shortcut (T body) (T handler))]
|
|
[else (error who "invalid tail" (unparse x))]))
|
|
;(print-code x)
|
|
(T x))
|
|
;;;
|
|
(define (do-spill sp* varvec)
|
|
(import conflict-helpers)
|
|
(define (find/set-loc x)
|
|
(let f ([i 1] [conf (var-frm-conf x)])
|
|
(let ([fv (mkfvar i)])
|
|
(cond
|
|
[(mem-frm? fv conf) (f (fxadd1 i) conf)]
|
|
[else
|
|
(for-each-var (var-var-conf x) varvec
|
|
(lambda (y)
|
|
(set-var-var-conf! y
|
|
(rem-var x (var-var-conf y)))
|
|
(set-var-frm-conf! y
|
|
(add-frm fv (var-frm-conf y)))))
|
|
(set-var-loc! x fv)
|
|
(cons x fv)]))))
|
|
(map find/set-loc sp*))
|
|
;;;
|
|
(define (add-unspillables un* x)
|
|
(define who 'add-unspillables)
|
|
(define (mku)
|
|
(let ([u (unique-var 'u)])
|
|
(set! un* (set-add u un*))
|
|
u))
|
|
(define (S x k)
|
|
(cond
|
|
[(or (constant? x) (var? x) (symbol? x))
|
|
(k x)]
|
|
[else
|
|
(let ([u (mku)])
|
|
(make-seq (E (make-asm-instr 'move u x)) (k u)))]))
|
|
(define (S* ls k)
|
|
(cond
|
|
[(null? ls) (k '())]
|
|
[else
|
|
(S (car ls)
|
|
(lambda (a)
|
|
(S* (cdr ls)
|
|
(lambda (d)
|
|
(k (cons a d))))))]))
|
|
(define (long-imm? x)
|
|
(struct-case x
|
|
[(constant n)
|
|
(cond
|
|
[(integer? n)
|
|
(not (<= (- (expt 2 31)) n (- (expt 2 31) 1)))]
|
|
[else #t])]
|
|
[else #f]))
|
|
(define (small-operand? x)
|
|
(case wordsize
|
|
[(4) (not (mem? x))]
|
|
[(8)
|
|
(struct-case x
|
|
[(constant n)
|
|
(cond
|
|
[(integer? n)
|
|
(<= (- (expt 2 31)) n (- (expt 2 31) 1))]
|
|
[else #f])]
|
|
[else (or (register? x) (var? x))])]
|
|
[else (error 'small-operand? "huh?")]))
|
|
(define (mem? x)
|
|
(or (disp? x) (fvar? x)))
|
|
;;; unspillable effect
|
|
(define (E x)
|
|
(struct-case x
|
|
[(seq e0 e1) (make-seq (E e0) (E e1))]
|
|
[(conditional e0 e1 e2)
|
|
(make-conditional (P e0) (E e1) (E e2))]
|
|
[(asm-instr op a b)
|
|
(case op
|
|
[(logor logxor logand int+ int- int* move
|
|
move-byte load32
|
|
int-/overflow int+/overflow int*/overflow)
|
|
(cond
|
|
[(and (eq? op 'move) (eq? a b))
|
|
(make-primcall 'nop '())]
|
|
[(and (= wordsize 8)
|
|
(not (eq? op 'move))
|
|
(long-imm? b))
|
|
(let ([u (mku)])
|
|
(make-seq
|
|
(E (make-asm-instr 'move u b))
|
|
(E (make-asm-instr op a u))))]
|
|
[(and (memq op '(int* int*/overflow)) (mem? a))
|
|
(let ([u (mku)])
|
|
(make-seq
|
|
(make-seq
|
|
(E (make-asm-instr 'move u a))
|
|
(E (make-asm-instr op u b)))
|
|
(E (make-asm-instr 'move a u))))]
|
|
[(and (mem? a) (not (small-operand? b)))
|
|
(case op
|
|
[(load32)
|
|
(let ([u (mku)])
|
|
(make-seq
|
|
(E (make-asm-instr 'load32 u b))
|
|
(E (make-asm-instr 'move a u))))]
|
|
[else
|
|
(let ([u (mku)])
|
|
(make-seq
|
|
(E (make-asm-instr 'move u b))
|
|
(E (make-asm-instr op a u))))])]
|
|
[(disp? a)
|
|
(let ([s0 (disp-s0 a)] [s1 (disp-s1 a)])
|
|
(cond
|
|
[(not (small-operand? s0))
|
|
(let ([u (mku)])
|
|
(make-seq
|
|
(E (make-asm-instr 'move u s0))
|
|
(E (make-asm-instr op (make-disp u s1) b))))]
|
|
[(not (small-operand? s1))
|
|
(let ([u (mku)])
|
|
(make-seq
|
|
(E (make-asm-instr 'move u s1))
|
|
(E (make-asm-instr op (make-disp s0 u) b))))]
|
|
[(small-operand? b) x]
|
|
[else
|
|
(let ([u (mku)])
|
|
(make-seq
|
|
(E (make-asm-instr 'move u b))
|
|
(E (make-asm-instr op a u))))]))]
|
|
[(disp? b)
|
|
(let ([s0 (disp-s0 b)] [s1 (disp-s1 b)])
|
|
(cond
|
|
[(not (small-operand? s0))
|
|
(let ([u (mku)])
|
|
(make-seq
|
|
(E (make-asm-instr 'move u s0))
|
|
(E (make-asm-instr op a (make-disp u s1)))))]
|
|
[(not (small-operand? s1))
|
|
(let ([u (mku)])
|
|
(make-seq
|
|
(E (make-asm-instr 'move u s1))
|
|
(E (make-asm-instr op a (make-disp s0 u)))))]
|
|
[else x]))]
|
|
[else x])]
|
|
[(bswap!)
|
|
(cond
|
|
[(mem? b)
|
|
(let ([u (mku)])
|
|
(make-seq
|
|
(E (make-asm-instr 'move u a))
|
|
(E (make-asm-instr 'bswap! u u))
|
|
(E (make-asm-instr 'move b u))))]
|
|
[else x])]
|
|
[(cltd)
|
|
(unless (and (symbol? a) (symbol? b))
|
|
(error who "invalid args to cltd"))
|
|
x]
|
|
[(idiv)
|
|
(unless (symbol? a)
|
|
(error who "invalid arg to idiv"))
|
|
(cond
|
|
[(or (var? b) (symbol? b)) x]
|
|
[else
|
|
(let ([u (mku)])
|
|
(make-seq
|
|
(E (make-asm-instr 'move u b))
|
|
(E (make-asm-instr 'idiv a u))))])]
|
|
[(sll sra srl sll/overflow)
|
|
(unless (or (constant? b)
|
|
(eq? b ecx))
|
|
(error who "invalid shift" b))
|
|
x]
|
|
[(mset mset32 bset bset/c )
|
|
(cond
|
|
[(not (small-operand? b))
|
|
(let ([u (mku)])
|
|
(make-seq
|
|
(E (make-asm-instr 'move u b))
|
|
(E (make-asm-instr op a u))))]
|
|
[else
|
|
(let ([s1 (disp-s0 a)] [s2 (disp-s1 a)])
|
|
(cond
|
|
[(and (mem? s1) (mem? s2))
|
|
(let ([u (mku)])
|
|
(make-seq
|
|
(make-seq
|
|
(E (make-asm-instr 'move u s1))
|
|
(E (make-asm-instr 'int+ u s2)))
|
|
(make-asm-instr op
|
|
(make-disp u (make-constant 0))
|
|
b)))]
|
|
[(mem? s1)
|
|
(let ([u (mku)])
|
|
(make-seq
|
|
(E (make-asm-instr 'move u s1))
|
|
(E (make-asm-instr op (make-disp u s2) b))))]
|
|
[(mem? s2)
|
|
(let ([u (mku)])
|
|
(make-seq
|
|
(E (make-asm-instr 'move u s2))
|
|
(E (make-asm-instr op (make-disp u s1) b))))]
|
|
[else x]))])]
|
|
[(fl:load fl:store fl:add! fl:sub! fl:mul! fl:div!
|
|
fl:load-single fl:store-single)
|
|
(check-disp-arg a
|
|
(lambda (a)
|
|
(check-disp-arg b
|
|
(lambda (b)
|
|
(make-asm-instr op a b)))))]
|
|
[(fl:from-int fl:shuffle) x]
|
|
[else (error who "invalid effect op" op)])]
|
|
[(primcall op rands)
|
|
(case op
|
|
[(nop interrupt incr/zero? fl:single->double
|
|
fl:double->single) x]
|
|
[else (error who "invalid op in" (unparse x))])]
|
|
[(ntcall) x]
|
|
[(shortcut body handler)
|
|
(let ([body (E body)])
|
|
(make-shortcut body (E handler)))]
|
|
[else (error who "invalid effect" (unparse x))]))
|
|
(define (check-disp-arg x k)
|
|
(cond
|
|
[(small-operand? x)
|
|
(k x)]
|
|
[else
|
|
(let ([u (mku)])
|
|
(make-seq
|
|
(E (make-asm-instr 'move u x))
|
|
(k u)))]))
|
|
(define (check-disp x k)
|
|
(struct-case x
|
|
[(disp a b)
|
|
(check-disp-arg a
|
|
(lambda (a)
|
|
(check-disp-arg b
|
|
(lambda (b)
|
|
(k (make-disp a b))))))]
|
|
[else (k x)]))
|
|
(define (P x)
|
|
(struct-case x
|
|
[(constant) x]
|
|
[(conditional e0 e1 e2)
|
|
(make-conditional (P e0) (P e1) (P e2))]
|
|
[(seq e0 e1) (make-seq (E e0) (P e1))]
|
|
[(asm-instr op a b)
|
|
(cond
|
|
[(memq op '(fl:= fl:< fl:<= fl:> fl:>=))
|
|
(if (mem? a)
|
|
(let ([u (mku)])
|
|
(make-seq
|
|
(E (make-asm-instr 'move u a))
|
|
(make-asm-instr op u b)))
|
|
x)]
|
|
[(and (not (mem? a)) (not (small-operand? a)))
|
|
(let ([u (mku)])
|
|
(make-seq
|
|
(E (make-asm-instr 'move u a))
|
|
(P (make-asm-instr op u b))))]
|
|
[(and (not (mem? b)) (not (small-operand? b)))
|
|
(let ([u (mku)])
|
|
(make-seq
|
|
(E (make-asm-instr 'move u b))
|
|
(P (make-asm-instr op a u))))]
|
|
[(and (mem? a) (mem? b))
|
|
(let ([u (mku)])
|
|
(make-seq
|
|
(E (make-asm-instr 'move u b))
|
|
(P (make-asm-instr op a u))))]
|
|
[else
|
|
(check-disp a
|
|
(lambda (a)
|
|
(check-disp b
|
|
(lambda (b)
|
|
(make-asm-instr op a b)))))])]
|
|
[(shortcut body handler)
|
|
(let ([body (P body)])
|
|
(make-shortcut body (P handler)))]
|
|
[else (error who "invalid pred" (unparse x))]))
|
|
(define (T x)
|
|
(struct-case x
|
|
[(primcall op rands) x]
|
|
[(conditional e0 e1 e2)
|
|
(make-conditional (P e0) (T e1) (T e2))]
|
|
[(seq e0 e1) (make-seq (E e0) (T e1))]
|
|
[(shortcut body handler)
|
|
(make-shortcut (T body) (T handler))]
|
|
[else (error who "invalid tail" (unparse x))]))
|
|
(let ([x (T x)])
|
|
(values un* x)))
|
|
;;;
|
|
(define (color-program x)
|
|
(define who 'color-program)
|
|
(struct-case x
|
|
[(locals vars body)
|
|
(let ([varvec (car vars)] [sp* (cdr vars)])
|
|
(let loop ([sp* (list->set sp*)] [un* (make-empty-set)] [body body])
|
|
(let-values ([(un* body) (add-unspillables un* body)])
|
|
(let ([g (build-graph body)])
|
|
(let-values ([(spills sp* env) (color-graph sp* un* g)])
|
|
(cond
|
|
[(null? spills) (substitute env body)]
|
|
[else
|
|
(let* ([env (do-spill spills varvec)]
|
|
[body (substitute env body)])
|
|
(loop sp* un* body))]))))))]))
|
|
;;;
|
|
(define (color-by-chaitin x)
|
|
;;;
|
|
(define (ClambdaCase x)
|
|
(struct-case x
|
|
[(clambda-case info body)
|
|
(make-clambda-case info (color-program body))]))
|
|
;;;
|
|
(define (Clambda x)
|
|
(struct-case x
|
|
[(clambda label case* cp free* name)
|
|
(make-clambda label (map ClambdaCase case*) cp free* name)]))
|
|
;;;
|
|
(define (Program x)
|
|
(struct-case x
|
|
[(codes code* body)
|
|
(make-codes (map Clambda code*) (color-program body))]))
|
|
;;;
|
|
(Program x))
|
|
#|chaitin module|#)
|
|
|
|
|
|
|
|
|
|
(define (compile-call-frame framesize livemask-vec multiarg-rp call-sequence)
|
|
(let ([L_CALL (label (gensym))]
|
|
[padding
|
|
(- call-instruction-size
|
|
(instruction-size call-sequence))])
|
|
(when (< padding 0)
|
|
(error 'compile-call-frame "call sequence too long" call-sequence))
|
|
(list 'seq
|
|
(if (or (= framesize 0) (= framesize 1))
|
|
'(seq)
|
|
`(subl ,(* (fxsub1 framesize) wordsize) ,fpr))
|
|
(jmp L_CALL)
|
|
`(byte-vector ,livemask-vec)
|
|
`(int ,(* framesize wordsize))
|
|
'(current-frame-offset)
|
|
multiarg-rp
|
|
`(byte-vector ,(make-vector padding 0))
|
|
L_CALL
|
|
call-sequence
|
|
(if (or (= framesize 0) (= framesize 1))
|
|
'(seq)
|
|
`(addl ,(* (fxsub1 framesize) wordsize) ,fpr)))))
|
|
|
|
|
|
|
|
(define (flatten-codes x)
|
|
(define who 'flatten-codes)
|
|
;;;
|
|
(define (FVar i)
|
|
`(disp ,(* i (- wordsize)) ,fpr))
|
|
;;;
|
|
(define (C x)
|
|
(struct-case x
|
|
[(code-loc label) (label-address label)]
|
|
[(foreign-label L) `(foreign-label ,L)]
|
|
[(closure label free*)
|
|
(unless (null? free*) (error who "nonempty closure"))
|
|
`(obj ,x)]
|
|
[(object o)
|
|
`(obj ,o)]
|
|
[else
|
|
(if (integer? x)
|
|
x
|
|
(error who "invalid constant C" x))]))
|
|
(define (BYTE x)
|
|
(struct-case x
|
|
[(constant x)
|
|
(unless (and (integer? x) (fx<= x 255) (fx<= -128 x))
|
|
(error who "invalid byte" x))
|
|
x]
|
|
[else (error who "invalid byte" x)]))
|
|
(define (D x)
|
|
(struct-case x
|
|
[(constant c) (C c)]
|
|
[else
|
|
(if (symbol? x) x (error who "invalid D" x))]))
|
|
(define (R x)
|
|
(struct-case x
|
|
[(constant c) (C c)]
|
|
[(fvar i) (FVar i)]
|
|
[(disp s0 s1)
|
|
(let ([s0 (D s0)] [s1 (D s1)])
|
|
`(disp ,s0 ,s1))]
|
|
[else
|
|
(if (symbol? x) x (error who "invalid R" x))]))
|
|
(define (R/l x)
|
|
(struct-case x
|
|
[(constant c) (C c)]
|
|
[(fvar i) (FVar i)]
|
|
[(disp s0 s1)
|
|
(let ([s0 (D s0)] [s1 (D s1)])
|
|
`(disp ,s0 ,s1))]
|
|
[else
|
|
(if (symbol? x) (reg/l x) (error who "invalid R/l" x))]))
|
|
(define (reg/h x)
|
|
(cond
|
|
[(assq x '([%eax %ah] [%ebx %bh] [%ecx %ch] [%edx %dh]))
|
|
=> cadr]
|
|
[else (error who "invalid reg/h" x)]))
|
|
(define (reg/l x)
|
|
(cond
|
|
[(assq x '([%eax %al] [%ebx %bl] [%ecx %cl] [%edx %dl]))
|
|
=> cadr]
|
|
[else (error who "invalid reg/l" x)]))
|
|
(define (R/cl x)
|
|
(struct-case x
|
|
[(constant i)
|
|
(unless (fixnum? i)
|
|
(error who "invalid R/cl" x))
|
|
(fxlogand i (- (* wordsize 8) 1))]
|
|
[else
|
|
(if (eq? x ecx)
|
|
'%cl
|
|
(error who "invalid R/cl" x))]))
|
|
(define (interrupt? x)
|
|
(struct-case x
|
|
[(primcall op args) (eq? op 'interrupt)]
|
|
[else #f]))
|
|
;;; flatten effect
|
|
(define (E x ac)
|
|
(struct-case x
|
|
[(seq e0 e1) (E e0 (E e1 ac))]
|
|
[(conditional e0 e1 e2)
|
|
(cond
|
|
[(interrupt? e1)
|
|
(let ([L (or (exception-label)
|
|
(error who "no exception label"))])
|
|
(P e0 L #f (E e2 ac)))]
|
|
[(interrupt? e2)
|
|
(let ([L (or (exception-label)
|
|
(error who "no exception label"))])
|
|
(P e0 #f L (E e1 ac)))]
|
|
[else
|
|
(let ([lf (unique-label)] [le (unique-label)])
|
|
(P e0 #f lf
|
|
(E e1
|
|
(cons* `(jmp ,le) lf
|
|
(E e2 (cons le ac))))))])]
|
|
[(ntcall target value args mask size)
|
|
(let ([LCALL (unique-label)])
|
|
(define (rp-label value)
|
|
(if value
|
|
(label-address (sl-mv-error-rp-label))
|
|
(label-address (sl-mv-ignore-rp-label))))
|
|
(cond
|
|
[(string? target) ;; foreign call
|
|
(cons* ;`(subl ,(* (fxsub1 size) wordsize) ,fpr)
|
|
`(movl (foreign-label "ik_foreign_call") %ebx)
|
|
(compile-call-frame
|
|
size
|
|
mask
|
|
(rp-label value)
|
|
`(call %ebx))
|
|
;`(addl ,(* (fxsub1 size) wordsize) ,fpr)
|
|
ac)]
|
|
[target ;;; known call
|
|
(cons* ;`(subl ,(* (fxsub1 size) wordsize) ,fpr)
|
|
(compile-call-frame
|
|
size
|
|
mask
|
|
(rp-label value)
|
|
`(call (label ,target)))
|
|
;`(addl ,(* (fxsub1 size) wordsize) ,fpr)
|
|
ac)]
|
|
[else
|
|
(cons* ;`(subl ,(* (fxsub1 size) wordsize) ,fpr)
|
|
(compile-call-frame
|
|
size
|
|
mask
|
|
(rp-label value)
|
|
`(call (disp ,(fx- disp-closure-code closure-tag)
|
|
,cp-register)))
|
|
;`(addl ,(* (fxsub1 size) wordsize) ,fpr)
|
|
ac)]))]
|
|
[(asm-instr op d s)
|
|
(case op
|
|
[(logand) (cons `(andl ,(R s) ,(R d)) ac)]
|
|
[(int+) (cons `(addl ,(R s) ,(R d)) ac)]
|
|
[(int*) (cons `(imull ,(R s) ,(R d)) ac)]
|
|
[(int-) (cons `(subl ,(R s) ,(R d)) ac)]
|
|
[(logor) (cons `(orl ,(R s) ,(R d)) ac)]
|
|
[(logxor) (cons `(xorl ,(R s) ,(R d)) ac)]
|
|
[(mset) (cons `(movl ,(R s) ,(R d)) ac)]
|
|
[(move)
|
|
(if (eq? d s)
|
|
ac
|
|
(cons `(movl ,(R s) ,(R d)) ac))]
|
|
[(move-byte)
|
|
(if (eq? d s)
|
|
ac
|
|
(cons `(movb ,(R/l s) ,(R/l d)) ac))]
|
|
[(bset/c) (cons `(movb ,(BYTE s) ,(R d)) ac)]
|
|
[(bset) (cons `(movb ,(reg/l s) ,(R d)) ac)]
|
|
[(sll) (cons `(sall ,(R/cl s) ,(R d)) ac)]
|
|
[(sra) (cons `(sarl ,(R/cl s) ,(R d)) ac)]
|
|
[(srl) (cons `(shrl ,(R/cl s) ,(R d)) ac)]
|
|
[(idiv) (cons `(idivl ,(R s)) ac)]
|
|
[(cltd) (cons `(cltd) ac)]
|
|
[(bswap!)
|
|
(let ([s (R s)] [d (R d)])
|
|
(unless (eq? s d) (error who "invalid instr" x))
|
|
(cons `(bswap ,s) ac))]
|
|
[(mset32) (cons `(mov32 ,(R s) ,(R d)) ac)]
|
|
[(load32) (cons `(mov32 ,(R s) ,(R d)) ac)]
|
|
[(int-/overflow)
|
|
(let ([L (or (exception-label)
|
|
(error who "no exception label"))])
|
|
(cons* `(subl ,(R s) ,(R d))
|
|
`(jo ,L)
|
|
ac))]
|
|
[(sll/overflow)
|
|
(let ([L (or (exception-label)
|
|
(error who "no exception label"))])
|
|
(cons* `(sall ,(R/cl s) ,(R d))
|
|
`(jo ,L)
|
|
ac))]
|
|
[(int*/overflow)
|
|
(let ([L (or (exception-label)
|
|
(error who "no exception label"))])
|
|
(cons* `(imull ,(R s) ,(R d))
|
|
`(jo ,L)
|
|
ac))]
|
|
[(int+/overflow)
|
|
(let ([L (or (exception-label)
|
|
(error who "no exception label"))])
|
|
(cons* `(addl ,(R s) ,(R d))
|
|
`(jo ,L)
|
|
ac))]
|
|
[(fl:store)
|
|
(cons `(movsd xmm0 ,(R (make-disp s d))) ac)]
|
|
[(fl:store-single)
|
|
(cons `(movss xmm0 ,(R (make-disp s d))) ac)]
|
|
[(fl:load)
|
|
(cons `(movsd ,(R (make-disp s d)) xmm0) ac)]
|
|
[(fl:load-single)
|
|
(cons `(movss ,(R (make-disp s d)) xmm0) ac)]
|
|
[(fl:from-int)
|
|
(cons `(cvtsi2sd ,(R s) xmm0) ac)]
|
|
[(fl:shuffle)
|
|
(cons `(pshufb ,(R (make-disp s d)) xmm0) ac)]
|
|
[(fl:add!)
|
|
(cons `(addsd ,(R (make-disp s d)) xmm0) ac)]
|
|
[(fl:sub!)
|
|
(cons `(subsd ,(R (make-disp s d)) xmm0) ac)]
|
|
[(fl:mul!)
|
|
(cons `(mulsd ,(R (make-disp s d)) xmm0) ac)]
|
|
[(fl:div!)
|
|
(cons `(divsd ,(R (make-disp s d)) xmm0) ac)]
|
|
[else (error who "invalid instr" x)])]
|
|
[(primcall op rands)
|
|
(case op
|
|
[(nop) ac]
|
|
[(interrupt)
|
|
(let ([l (or (exception-label)
|
|
(error who "no exception label"))])
|
|
(cons `(jmp ,l) ac))]
|
|
[(incr/zero?)
|
|
(let ([l (or (exception-label)
|
|
(error who "no exception label"))])
|
|
(cons*
|
|
`(addl ,(D (caddr rands)) ,(R (make-disp (car rands) (cadr rands))))
|
|
`(je ,l)
|
|
ac))]
|
|
[(fl:double->single)
|
|
(cons '(cvtsd2ss xmm0 xmm0) ac)]
|
|
[(fl:single->double)
|
|
(cons '(cvtss2sd xmm0 xmm0) ac)]
|
|
[else (error who "invalid effect" (unparse x))])]
|
|
[(shortcut body handler)
|
|
(let ([L (unique-interrupt-label)] [L2 (unique-label)])
|
|
(let ([hand (cons L (E handler `((jmp ,L2))))])
|
|
(let ([tc (exceptions-conc)])
|
|
(set-cdr! tc (append hand (cdr tc)))))
|
|
(parameterize ([exception-label L])
|
|
(E body (cons L2 ac))))]
|
|
[else (error who "invalid effect" (unparse x))]))
|
|
;;;
|
|
(define (unique-interrupt-label)
|
|
(label (gensym "ERROR")))
|
|
(define (unique-label)
|
|
(label (gensym)))
|
|
;;;
|
|
(define (constant=? x k)
|
|
(struct-case x
|
|
[(constant k0) (equal? k0 k)]
|
|
[else #f]))
|
|
;;;
|
|
(define (P x lt lf ac)
|
|
(struct-case x
|
|
[(constant c)
|
|
(if c
|
|
(if lt (cons `(jmp ,lt) ac) ac)
|
|
(if lf (cons `(jmp ,lf) ac) ac))]
|
|
[(seq e0 e1)
|
|
(E e0 (P e1 lt lf ac))]
|
|
[(conditional e0 e1 e2)
|
|
(cond
|
|
[(and (constant=? e1 #t) (constant=? e2 #f))
|
|
(P e0 lt lf ac)]
|
|
[(and (constant=? e1 #f) (constant=? e2 #t))
|
|
(P e0 lf lt ac)]
|
|
[(and lt lf)
|
|
(let ([l (unique-label)])
|
|
(P e0 #f l
|
|
(P e1 lt lf
|
|
(cons l (P e2 lt lf ac)))))]
|
|
[lt
|
|
(let ([lf (unique-label)] [l (unique-label)])
|
|
(P e0 #f l
|
|
(P e1 lt lf
|
|
(cons l (P e2 lt #f (cons lf ac))))))]
|
|
[lf
|
|
(let ([lt (unique-label)] [l (unique-label)])
|
|
(P e0 #f l
|
|
(P e1 lt lf
|
|
(cons l (P e2 #f lf (cons lt ac))))))]
|
|
[else
|
|
(let ([lf (unique-label)] [l (unique-label)])
|
|
(P e0 #f l
|
|
(P e1 #f #f
|
|
(cons `(jmp ,lf)
|
|
(cons l (P e2 #f #f (cons lf ac)))))))])]
|
|
[(asm-instr op a0 a1)
|
|
(let ()
|
|
(define (notop x)
|
|
(cond
|
|
[(assq x '([= !=] [!= =] [< >=] [<= >] [> <=] [>= <]
|
|
[u< u>=] [u<= u>] [u> u<=] [u>= u<]
|
|
[fl:= fl:o!=] [fl:!= fl:o=]
|
|
[fl:< fl:o>=] [fl:<= fl:o>]
|
|
[fl:> fl:o<=] [fl:>= fl:o<]
|
|
))
|
|
=> cadr]
|
|
[else (error who "invalid notop" x)]))
|
|
(define (jmpname x)
|
|
(cond
|
|
[(assq x '([= je] [!= jne] [< jl] [<= jle] [> jg] [>= jge]
|
|
[u< jb] [u<= jbe] [u> ja] [u>= jae]
|
|
[fl:= je] [fl:!= jne]
|
|
[fl:< jb] [fl:> ja] [fl:<= jbe] [fl:>= jae]
|
|
[fl:o= je] [fl:o!= jne]
|
|
[fl:o< jb] [fl:o> ja] [fl:o<= jbe] [fl:o>= jae]
|
|
))
|
|
=> cadr]
|
|
[else (error who "invalid jmpname" x)]))
|
|
(define (revjmpname x)
|
|
(cond
|
|
[(assq x '([= je] [!= jne] [< jg] [<= jge] [> jl] [>= jle]
|
|
[u< ja] [u<= jae] [u> jb] [u>= jbe]))
|
|
=> cadr]
|
|
[else (error who "invalid jmpname" x)]))
|
|
(define (cmp op a0 a1 lab ac)
|
|
(cond
|
|
[(memq op '(fl:= fl:!= fl:< fl:<= fl:> fl:>=))
|
|
(cons* `(ucomisd ,(R (make-disp a0 a1)) xmm0)
|
|
`(,(jmpname op) ,lab)
|
|
;;; BOGUS!
|
|
ac)]
|
|
[(memq op '(fl:o= fl:o!= fl:o< fl:o<= fl:o> fl:o>=))
|
|
(cons* `(ucomisd ,(R (make-disp a0 a1)) xmm0)
|
|
`(jp ,lab)
|
|
`(,(jmpname op) ,lab)
|
|
ac)]
|
|
[(or (symbol? a0) (constant? a1))
|
|
(cons* `(cmpl ,(R a1) ,(R a0))
|
|
`(,(jmpname op) ,lab)
|
|
ac)]
|
|
[(or (symbol? a1) (constant? a0))
|
|
(cons* `(cmpl ,(R a0) ,(R a1))
|
|
`(,(revjmpname op) ,lab)
|
|
ac)]
|
|
[else (error who "invalid cmpops" a0 a1)]))
|
|
(cond
|
|
[(and lt lf)
|
|
(cmp op a0 a1 lt
|
|
(cons `(jmp ,lf) ac))]
|
|
[lt
|
|
(cmp op a0 a1 lt ac)]
|
|
[lf
|
|
(cmp (notop op) a0 a1 lf ac)]
|
|
[else ac]))]
|
|
[(shortcut body handler)
|
|
(let ([L (unique-interrupt-label)] [lj (unique-label)])
|
|
(let ([ac (if (and lt lf) ac (cons lj ac))])
|
|
(let ([hand (cons L (P handler (or lt lj) (or lf lj) '()))])
|
|
(let ([tc (exceptions-conc)])
|
|
(set-cdr! tc (append hand (cdr tc)))))
|
|
(parameterize ([exception-label L])
|
|
(P body lt lf ac))))]
|
|
[else (error who "invalid pred" x)]))
|
|
;;;
|
|
(define (T x ac)
|
|
(struct-case x
|
|
[(seq e0 e1) (E e0 (T e1 ac))]
|
|
[(conditional e0 e1 e2)
|
|
(let ([L (unique-label)])
|
|
(P e0 #f L (T e1 (cons L (T e2 ac)))))]
|
|
[(primcall op rands)
|
|
(case op
|
|
[(return) (cons '(ret) ac)]
|
|
[(indirect-jump)
|
|
(cons `(jmp (disp ,(fx- disp-closure-code closure-tag) ,cp-register))
|
|
ac)]
|
|
[(direct-jump)
|
|
(cons `(jmp (label ,(code-loc-label (car rands)))) ac)]
|
|
[else (error who "invalid tail" x)])]
|
|
[(shortcut body handler)
|
|
(let ([L (unique-interrupt-label)])
|
|
(let ([hand (cons L (T handler '()))])
|
|
(let ([tc (exceptions-conc)])
|
|
(set-cdr! tc (append hand (cdr tc)))))
|
|
(parameterize ([exception-label L])
|
|
(T body ac)))]
|
|
[else (error who "invalid tail" x)]))
|
|
(define exception-label (make-parameter #f))
|
|
;;;
|
|
(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))
|
|
(cons* (cmpl (int (argc-convention (fxsub1 fml-count))) eax)
|
|
(jl CONS_LABEL)
|
|
(movl (int nil) ebx)
|
|
(jmp DONE_LABEL)
|
|
CONS_LABEL
|
|
(movl (mem pcb-allocation-redline pcr) 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 (obj (primref->symbol 'do-vararg-overflow)) cpr)
|
|
(movl (mem (- disp-symbol-record-proc record-tag) cpr) cpr)
|
|
;(movl (primref-loc 'do-vararg-overflow) cpr) ; load handler
|
|
(compile-call-frame 0 '#() '(int 0) (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 (properize args proper ac)
|
|
(cond
|
|
[proper ac]
|
|
[else
|
|
(handle-vararg (length (cdr args)) ac)]))
|
|
;;;
|
|
(define (ClambdaCase x ac)
|
|
(struct-case x
|
|
[(clambda-case info body)
|
|
(struct-case info
|
|
[(case-info L args proper)
|
|
(let ([lothers (unique-label)])
|
|
(cons* `(cmpl ,(argc-convention
|
|
(if proper
|
|
(length (cdr args))
|
|
(length (cddr args))))
|
|
,argc-register)
|
|
(cond
|
|
[proper `(jne ,lothers)]
|
|
[(> (argc-convention 0) (argc-convention 1))
|
|
`(jg ,lothers)]
|
|
[else
|
|
`(jl ,lothers)])
|
|
(properize args proper
|
|
(cons (label L)
|
|
(T body (cons lothers ac))))))])]))
|
|
;;;
|
|
(define (Clambda x)
|
|
(struct-case x
|
|
[(clambda L case* cp free* name)
|
|
(cons* (length free*)
|
|
`(name ,name)
|
|
(label L)
|
|
(let ([ac (list '(nop))])
|
|
(parameterize ([exceptions-conc ac])
|
|
(let f ([case* case*])
|
|
(cond
|
|
[(null? case*)
|
|
(cons `(jmp (label ,(sl-invalid-args-label))) ac)]
|
|
[else
|
|
(ClambdaCase (car case*) (f (cdr case*)))])))))]))
|
|
;;;
|
|
(define exceptions-conc (make-parameter #f))
|
|
;;;
|
|
(define (Program x)
|
|
(struct-case x
|
|
[(codes code* body)
|
|
(cons (cons* 0
|
|
(label (gensym))
|
|
(let ([ac (list '(nop))])
|
|
(parameterize ([exceptions-conc ac])
|
|
(T body ac))))
|
|
(map Clambda code*))]))
|
|
(Program x))
|
|
|
|
(define (print-code x)
|
|
(parameterize ([print-gensym '#t])
|
|
(pretty-print (unparse x))))
|
|
|
|
(define (alt-cogen x)
|
|
(define (time-it name proc)
|
|
(proc))
|
|
(let* ([x (introduce-primcalls x)]
|
|
[x (eliminate-fix x)]
|
|
[x (insert-engine-checks x)]
|
|
[x (insert-stack-overflow-check x)]
|
|
[x (specify-representation x)]
|
|
[x (impose-calling-convention/evaluation-order x)]
|
|
[x (time-it "frame" (lambda () (assign-frame-sizes x)))]
|
|
[x (time-it "register" (lambda () (color-by-chaitin x)))]
|
|
[ls (flatten-codes x)])
|
|
ls))
|
|
|
|
|
|
#|module alt-cogen|#)
|
|
|
|
|