2007-10-25 16:27:34 -04:00
|
|
|
;;; Ikarus Scheme -- A compiler for R6RS Scheme.
|
2008-01-29 00:34:34 -05:00
|
|
|
;;; Copyright (C) 2006,2007,2008 Abdulaziz Ghuloum
|
2007-10-25 16:27:34 -04:00
|
|
|
;;;
|
|
|
|
;;; 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/>.
|
|
|
|
|
2007-02-10 18:51:12 -05:00
|
|
|
|
2008-01-02 07:01:45 -05:00
|
|
|
(module (alt-cogen compile-call-frame)
|
2007-02-10 18:51:12 -05:00
|
|
|
;;; 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>)
|
2007-11-21 04:00:10 -05:00
|
|
|
;;; <clambda> ::= (clambda <label> <case>* <cp> <free var>*)
|
2007-02-10 18:51:12 -05:00
|
|
|
;;; <case> ::= (clambda-case <info> <body>)
|
|
|
|
;;; <info> ::= (clambda-info label <arg var>* proper)
|
|
|
|
;;; <Program> ::= (codes <clambda>* <Expr>)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2007-02-19 18:21:35 -05:00
|
|
|
|
2007-06-05 20:11:12 -04:00
|
|
|
(define (introduce-primcalls x)
|
2007-02-10 18:51:12 -05:00
|
|
|
;;;
|
2007-06-05 20:11:12 -04:00
|
|
|
(define who 'introduce-primcalls)
|
2007-02-10 18:51:12 -05:00
|
|
|
;;;
|
|
|
|
(define (check-gensym x)
|
|
|
|
(unless (gensym? x)
|
2007-10-25 14:32:26 -04:00
|
|
|
(error who "invalid gensym" x)))
|
2007-02-10 18:51:12 -05:00
|
|
|
;;;
|
|
|
|
(define (check-label x)
|
2007-10-12 02:59:27 -04:00
|
|
|
(struct-case x
|
2007-02-10 18:51:12 -05:00
|
|
|
[(code-loc label)
|
|
|
|
(check-gensym label)]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid label" x)]))
|
2007-02-10 18:51:12 -05:00
|
|
|
;;;
|
|
|
|
(define (check-var x)
|
2007-10-12 02:59:27 -04:00
|
|
|
(struct-case x
|
2007-02-10 18:51:12 -05:00
|
|
|
[(var) (void)]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid var" x)]))
|
2007-02-10 18:51:12 -05:00
|
|
|
;;;
|
|
|
|
(define (check-closure x)
|
2007-10-12 02:59:27 -04:00
|
|
|
(struct-case x
|
2007-02-10 18:51:12 -05:00
|
|
|
[(closure label free*)
|
|
|
|
(check-label label)
|
|
|
|
(for-each check-var free*)]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid closure" x)]))
|
2007-02-10 18:51:12 -05:00
|
|
|
;;;
|
2007-02-12 13:58:04 -05:00
|
|
|
(define (mkfuncall op arg*)
|
2009-05-24 04:59:18 -04:00
|
|
|
(define (primop? x)
|
|
|
|
(import primops)
|
|
|
|
(or (eq? x 'debug-call) (primop? x)))
|
2007-10-12 02:59:27 -04:00
|
|
|
(struct-case op
|
2008-07-07 02:48:16 -04:00
|
|
|
[(known x t)
|
|
|
|
(struct-case x
|
|
|
|
[(primref name)
|
|
|
|
(if (primop? name)
|
|
|
|
(make-primcall name arg*)
|
|
|
|
(make-funcall op arg*))]
|
|
|
|
[else (make-funcall op arg*)])]
|
2007-02-12 13:58:04 -05:00
|
|
|
[(primref name)
|
|
|
|
(cond
|
2007-03-03 23:17:04 -05:00
|
|
|
[(primop? name)
|
2007-02-12 13:58:04 -05:00
|
|
|
(make-primcall name arg*)]
|
|
|
|
[else (make-funcall op arg*)])]
|
|
|
|
[else (make-funcall op arg*)]))
|
|
|
|
;;;
|
2008-07-07 02:48:16 -04:00
|
|
|
(define (A x)
|
|
|
|
(struct-case x
|
|
|
|
[(known x t) (make-known (Expr x) t)]
|
|
|
|
[else (Expr x)]))
|
2007-02-10 18:51:12 -05:00
|
|
|
(define (Expr x)
|
2007-10-12 02:59:27 -04:00
|
|
|
(struct-case x
|
2007-02-10 18:51:12 -05:00
|
|
|
[(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*)
|
2008-07-07 02:48:16 -04:00
|
|
|
(mkfuncall (A rator) (map A arg*))]
|
2007-02-10 18:51:12 -05:00
|
|
|
[(jmpcall label rator arg*)
|
|
|
|
(make-jmpcall label (Expr rator) (map Expr arg*))]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid expr" x)]))
|
2007-02-10 18:51:12 -05:00
|
|
|
;;;
|
|
|
|
(define (ClambdaCase x)
|
2007-10-12 02:59:27 -04:00
|
|
|
(struct-case x
|
2007-02-10 18:51:12 -05:00
|
|
|
[(clambda-case info body)
|
|
|
|
(make-clambda-case info (Expr body))]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid clambda-case" x)]))
|
2007-02-10 18:51:12 -05:00
|
|
|
;;;
|
|
|
|
(define (Clambda x)
|
2007-10-12 02:59:27 -04:00
|
|
|
(struct-case x
|
2007-11-21 04:00:10 -05:00
|
|
|
[(clambda label case* cp free* name)
|
|
|
|
(make-clambda label (map ClambdaCase case*) cp free* name)]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid clambda" x)]))
|
2007-02-10 18:51:12 -05:00
|
|
|
;;;
|
|
|
|
(define (Program x)
|
2007-10-12 02:59:27 -04:00
|
|
|
(struct-case x
|
2007-02-10 18:51:12 -05:00
|
|
|
[(codes code* body)
|
|
|
|
(make-codes (map Clambda code*) (Expr body))]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid program" x)]))
|
2007-02-10 18:51:12 -05:00
|
|
|
;;;
|
|
|
|
(Program x))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(define (eliminate-fix x)
|
|
|
|
;;;
|
|
|
|
(define who 'eliminate-fix)
|
|
|
|
;;;
|
2007-11-21 04:00:10 -05:00
|
|
|
(define (Expr main-cpvar cpvar free*)
|
2007-02-10 18:51:12 -05:00
|
|
|
;;;
|
|
|
|
(define (Var x)
|
2007-11-21 04:00:10 -05:00
|
|
|
(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))]))]))
|
2007-02-10 18:51:12 -05:00
|
|
|
(define (do-fix lhs* rhs* body)
|
2007-02-13 17:24:00 -05:00
|
|
|
(define (handle-closure x)
|
2007-10-12 02:59:27 -04:00
|
|
|
(struct-case x
|
2008-02-11 22:18:32 -05:00
|
|
|
[(closure code free* well-known?)
|
|
|
|
(make-closure code (map Var free*) well-known?)]))
|
2007-02-13 17:24:00 -05:00
|
|
|
(make-fix lhs* (map handle-closure rhs*) body))
|
2008-07-07 02:48:16 -04:00
|
|
|
(define (A x)
|
|
|
|
(struct-case x
|
|
|
|
[(known x t) (make-known (Expr x) t)]
|
|
|
|
[else (Expr x)]))
|
2007-02-10 18:51:12 -05:00
|
|
|
(define (Expr x)
|
2007-10-12 02:59:27 -04:00
|
|
|
(struct-case x
|
2007-02-10 18:51:12 -05:00
|
|
|
[(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))]
|
2007-02-13 17:24:00 -05:00
|
|
|
[(closure)
|
2007-02-10 18:51:12 -05:00
|
|
|
(let ([t (unique-var 'tmp)])
|
|
|
|
(Expr (make-fix (list t) (list x) t)))]
|
|
|
|
[(primcall op arg*)
|
2008-07-07 02:48:16 -04:00
|
|
|
(make-primcall op (map A arg*))]
|
2007-02-10 18:51:12 -05:00
|
|
|
[(forcall op arg*)
|
|
|
|
(make-forcall op (map Expr arg*))]
|
|
|
|
[(funcall rator arg*)
|
2008-07-07 02:48:16 -04:00
|
|
|
(make-funcall (A rator) (map A arg*))]
|
2007-02-10 18:51:12 -05:00
|
|
|
[(jmpcall label rator arg*)
|
|
|
|
(make-jmpcall label (Expr rator) (map Expr arg*))]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid expr" x)]))
|
2007-02-10 18:51:12 -05:00
|
|
|
Expr)
|
|
|
|
;;;
|
2007-11-21 04:00:10 -05:00
|
|
|
(define (ClambdaCase main-cp free*)
|
2007-02-10 18:51:12 -05:00
|
|
|
(lambda (x)
|
2007-10-12 02:59:27 -04:00
|
|
|
(struct-case x
|
2007-02-10 18:51:12 -05:00
|
|
|
[(clambda-case info body)
|
2007-10-12 02:59:27 -04:00
|
|
|
(struct-case info
|
2007-02-10 18:51:12 -05:00
|
|
|
[(case-info label args proper)
|
|
|
|
(let ([cp (unique-var 'cp)])
|
|
|
|
(make-clambda-case
|
|
|
|
(make-case-info label (cons cp args) proper)
|
2007-11-21 04:00:10 -05:00
|
|
|
((Expr main-cp cp free*) body)))])]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid clambda-case" x)])))
|
2007-02-10 18:51:12 -05:00
|
|
|
;;;
|
|
|
|
(define (Clambda x)
|
2007-10-12 02:59:27 -04:00
|
|
|
(struct-case x
|
2007-11-21 04:00:10 -05:00
|
|
|
[(clambda label case* cp free* name)
|
|
|
|
(make-clambda label (map (ClambdaCase cp free*) case*)
|
2008-02-11 09:29:59 -05:00
|
|
|
#f free* name)]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid clambda" x)]))
|
2007-02-10 18:51:12 -05:00
|
|
|
;;;
|
|
|
|
(define (Program x)
|
2007-10-12 02:59:27 -04:00
|
|
|
(struct-case x
|
2007-02-10 18:51:12 -05:00
|
|
|
[(codes code* body)
|
2007-11-21 04:00:10 -05:00
|
|
|
(make-codes (map Clambda code*) ((Expr #f #f '()) body))]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid program" x)]))
|
2007-02-10 18:51:12 -05:00
|
|
|
;;;
|
|
|
|
(Program x))
|
|
|
|
|
|
|
|
|
2007-03-02 00:41:28 -05:00
|
|
|
|
2007-02-12 19:17:31 -05:00
|
|
|
(define-syntax seq*
|
|
|
|
(syntax-rules ()
|
|
|
|
[(_ e) e]
|
|
|
|
[(_ e* ... e)
|
|
|
|
(make-seq (seq* e* ...) e)]))
|
|
|
|
|
2007-09-05 01:47:57 -04:00
|
|
|
(define (insert-engine-checks x)
|
2007-11-05 16:23:13 -05:00
|
|
|
(define who 'insert-engine-checks)
|
2008-07-07 02:48:16 -04:00
|
|
|
(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)]))
|
2007-11-05 16:23:13 -05:00
|
|
|
(define (Expr x)
|
|
|
|
(struct-case x
|
|
|
|
[(constant) #f]
|
|
|
|
[(var) #f]
|
|
|
|
[(primref) #f]
|
|
|
|
[(jmpcall label rator arg*) #t]
|
|
|
|
[(funcall rator arg*)
|
2008-07-07 02:48:16 -04:00
|
|
|
(if (known-primref? rator) (ormap A arg*) #t)]
|
2007-11-05 16:23:13 -05:00
|
|
|
[(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))]
|
2008-07-07 02:48:16 -04:00
|
|
|
[(primcall op arg*) (ormap A arg*)]
|
2007-11-05 16:23:13 -05:00
|
|
|
[(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))
|
2007-09-05 01:47:57 -04:00
|
|
|
(define (CaseExpr x)
|
2007-10-12 02:59:27 -04:00
|
|
|
(struct-case x
|
2007-09-05 01:47:57 -04:00
|
|
|
[(clambda-case info body)
|
2007-11-05 16:23:13 -05:00
|
|
|
(make-clambda-case info (Main body))]))
|
2007-09-05 01:47:57 -04:00
|
|
|
(define (CodeExpr x)
|
2007-10-12 02:59:27 -04:00
|
|
|
(struct-case x
|
2007-11-21 04:00:10 -05:00
|
|
|
[(clambda L cases cp free name)
|
|
|
|
(make-clambda L (map CaseExpr cases) cp free name)]))
|
2007-09-05 01:47:57 -04:00
|
|
|
(define (CodesExpr x)
|
2007-10-12 02:59:27 -04:00
|
|
|
(struct-case x
|
2007-09-05 01:47:57 -04:00
|
|
|
[(codes list body)
|
2007-11-05 16:23:13 -05:00
|
|
|
(make-codes (map CodeExpr list) (Main body))]))
|
2007-09-05 01:47:57 -04:00
|
|
|
(CodesExpr x))
|
|
|
|
|
2007-11-05 15:30:42 -05:00
|
|
|
|
2007-07-13 06:54:25 -04:00
|
|
|
(define (insert-stack-overflow-check x)
|
|
|
|
(define who 'insert-stack-overflow-check)
|
2008-07-07 02:48:16 -04:00
|
|
|
(define (A x)
|
|
|
|
(struct-case x
|
|
|
|
[(known x t) (NonTail x)]
|
|
|
|
[else (NonTail x)]))
|
2008-05-17 02:27:08 -04:00
|
|
|
(define (NonTail x)
|
2007-11-05 16:23:13 -05:00
|
|
|
(struct-case x
|
|
|
|
[(constant) #f]
|
|
|
|
[(var) #f]
|
|
|
|
[(primref) #f]
|
|
|
|
[(funcall rator arg*) #t]
|
|
|
|
[(jmpcall label rator arg*) #t]
|
|
|
|
[(mvcall rator k) #t]
|
2008-09-06 07:17:20 -04:00
|
|
|
[(primcall op arg*) (ormap A arg*)] ;PUNT!!! FIXME!
|
2007-11-05 16:23:13 -05:00
|
|
|
[(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))]
|
|
|
|
[(forcall op arg*) (ormap NonTail arg*)]
|
2009-05-14 01:59:41 -04:00
|
|
|
[(known x t) (NonTail x)]
|
2007-11-05 16:23:13 -05:00
|
|
|
[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)]))
|
2007-07-13 06:54:25 -04:00
|
|
|
(define (insert-check x)
|
2007-11-05 15:30:42 -05:00
|
|
|
(make-seq (make-primcall '$stack-overflow-check '()) x))
|
|
|
|
(define (ClambdaCase x)
|
2007-10-12 02:59:27 -04:00
|
|
|
(struct-case x
|
2007-07-13 06:54:25 -04:00
|
|
|
[(clambda-case info body)
|
|
|
|
(make-clambda-case info (Main body))]))
|
|
|
|
(define (Clambda x)
|
2007-10-12 02:59:27 -04:00
|
|
|
(struct-case x
|
2007-11-21 04:00:10 -05:00
|
|
|
[(clambda label case* cp free* name)
|
|
|
|
(make-clambda label (map ClambdaCase case*) cp free* name)]))
|
2007-07-13 06:54:25 -04:00
|
|
|
(define (Main x)
|
2008-08-14 01:28:22 -04:00
|
|
|
(if (Tail x)
|
2007-07-13 06:54:25 -04:00
|
|
|
(insert-check x)
|
|
|
|
x))
|
|
|
|
(define (Program x)
|
2007-10-12 02:59:27 -04:00
|
|
|
(struct-case x
|
2007-07-13 06:54:25 -04:00
|
|
|
[(codes code* body)
|
|
|
|
(make-codes (map Clambda code*) (Main body))]))
|
|
|
|
(Program x))
|
|
|
|
|
2009-05-30 03:46:45 -04:00
|
|
|
(include "pass-specify-rep.ss")
|
2007-07-13 06:54:25 -04:00
|
|
|
|
2007-02-10 18:51:12 -05:00
|
|
|
(define parameter-registers '(%edi))
|
|
|
|
(define return-value-register '%eax)
|
|
|
|
(define cp-register '%edi)
|
2007-12-31 03:02:12 -05:00
|
|
|
(define all-registers
|
2008-07-30 10:47:22 -04:00
|
|
|
(case wordsize
|
|
|
|
[(4) '(%eax %edi %ebx %edx %ecx)]
|
2008-08-02 13:11:04 -04:00
|
|
|
[else '(%eax %edi %ebx %edx %ecx %r8 %r9 %r10 %r11 %r14 %r15)]))
|
2008-07-30 10:47:22 -04:00
|
|
|
|
|
|
|
(define non-8bit-registers
|
|
|
|
(case wordsize
|
|
|
|
[(4) '(%edi)]
|
2008-08-09 08:47:44 -04:00
|
|
|
[else '(%edi)]))
|
2008-07-30 10:47:22 -04:00
|
|
|
|
2007-02-11 04:12:09 -05:00
|
|
|
(define argc-register '%eax)
|
2007-02-10 18:51:12 -05:00
|
|
|
|
2007-06-05 23:10:28 -04:00
|
|
|
;;; apr = %ebp
|
|
|
|
;;; esp = %esp
|
|
|
|
;;; pcr = %esi
|
|
|
|
;;; cpr = %edi
|
|
|
|
|
2007-03-10 16:47:13 -05:00
|
|
|
(define (register-index x)
|
|
|
|
(cond
|
|
|
|
[(assq x '([%eax 0] [%edi 1] [%ebx 2] [%edx 3]
|
|
|
|
[%ecx 4] [%esi 5] [%esp 6] [%ebp 7]))
|
|
|
|
=> cadr]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error 'register-index "not a register" x)]))
|
2007-03-10 16:47:13 -05:00
|
|
|
|
2007-02-10 18:51:12 -05:00
|
|
|
(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)
|
2007-10-12 02:59:27 -04:00
|
|
|
(struct-case x
|
2007-02-11 19:17:59 -05:00
|
|
|
[(bind lhs* rhs* body)
|
|
|
|
(do-bind lhs* rhs* (S body k))]
|
|
|
|
[(seq e0 e1)
|
|
|
|
(make-seq (E e0) (S e1 k))]
|
2008-07-07 02:48:16 -04:00
|
|
|
[(known x) (S x k)]
|
2007-02-11 19:17:59 -05:00
|
|
|
[else
|
|
|
|
(cond
|
2007-03-11 03:40:47 -04:00
|
|
|
[(or (constant? x) (symbol? x)) (k x)]
|
|
|
|
[(var? x)
|
|
|
|
(cond
|
|
|
|
[(var-loc x) => k]
|
|
|
|
[else (k x)])]
|
2007-02-12 13:58:04 -05:00
|
|
|
[(or (funcall? x) (primcall? x) (jmpcall? x)
|
2007-02-24 15:42:57 -05:00
|
|
|
(forcall? x) (shortcut? x)
|
2007-02-12 13:58:04 -05:00
|
|
|
(conditional? x))
|
2007-02-11 19:17:59 -05:00
|
|
|
(let ([t (unique-var 'tmp)])
|
|
|
|
(do-bind (list t) (list x)
|
|
|
|
(k t)))]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid S" x)])]))
|
2008-06-11 02:01:22 -04:00
|
|
|
(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)]))
|
2007-02-10 18:51:12 -05:00
|
|
|
;;;
|
|
|
|
(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))]))
|
|
|
|
;;;
|
2007-02-11 04:12:09 -05:00
|
|
|
(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*))])))
|
2007-02-17 18:09:03 -05:00
|
|
|
(define (make-set lhs rhs)
|
|
|
|
(make-asm-instr 'move lhs rhs))
|
2007-02-12 13:58:04 -05:00
|
|
|
(define (do-bind-frmt* nf* v* ac)
|
|
|
|
(cond
|
|
|
|
[(null? nf*) ac]
|
|
|
|
[else
|
2007-02-19 23:33:29 -05:00
|
|
|
(make-seq
|
|
|
|
(V (car nf*) (car v*))
|
|
|
|
(do-bind-frmt* (cdr nf*) (cdr v*) ac))]))
|
2007-02-12 13:58:04 -05:00
|
|
|
;;;
|
2007-02-11 18:52:10 -05:00
|
|
|
(define (handle-nontail-call rator rands value-dest call-targ)
|
2007-02-11 17:51:42 -05:00
|
|
|
(let-values ([(reg-locs reg-args frm-args)
|
|
|
|
(nontail-locations (cons rator rands))])
|
|
|
|
(let ([regt* (map (lambda (x) (unique-var 'rt)) reg-args)]
|
2007-02-17 18:09:03 -05:00
|
|
|
[frmt* (map (lambda (x) (make-nfv 'unset-conflicts #f #f #f #f))
|
|
|
|
frm-args)])
|
2007-02-11 18:52:10 -05:00
|
|
|
(let* ([call
|
2007-02-12 13:58:04 -05:00
|
|
|
(make-ntcall call-targ value-dest
|
2007-09-09 23:31:19 -04:00
|
|
|
(cons* argc-register
|
2007-02-17 19:22:14 -05:00
|
|
|
pcr esp apr
|
|
|
|
(append reg-locs frmt*))
|
2007-02-12 13:58:04 -05:00
|
|
|
#f #f)]
|
2007-02-11 18:52:10 -05:00
|
|
|
[body
|
|
|
|
(make-nframe frmt* #f
|
2007-02-12 13:58:04 -05:00
|
|
|
(do-bind-frmt* frmt* frm-args
|
2007-02-24 15:42:57 -05:00
|
|
|
(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))))))])
|
2007-02-12 13:58:04 -05:00
|
|
|
(if value-dest
|
2007-02-11 18:52:10 -05:00
|
|
|
(make-seq body (make-set value-dest return-value-register))
|
2007-02-11 17:51:42 -05:00
|
|
|
body)))))
|
2007-11-15 13:40:36 -05:00
|
|
|
;;; (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)))))
|
2007-02-13 05:08:48 -05:00
|
|
|
(define (alloc-check size)
|
2008-06-11 02:01:22 -04:00
|
|
|
(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))))
|
2007-11-15 13:40:36 -05:00
|
|
|
(E (make-shortcut
|
|
|
|
(make-conditional ;;; PCB ALLOC-REDLINE
|
2008-06-11 02:01:22 -04:00
|
|
|
(test size)
|
2007-11-15 13:40:36 -05:00
|
|
|
(make-primcall 'nop '())
|
|
|
|
(make-primcall 'interrupt '()))
|
2007-02-13 05:08:48 -05:00
|
|
|
(make-funcall
|
|
|
|
(make-primcall 'mref
|
2007-11-06 17:04:27 -05:00
|
|
|
(list
|
|
|
|
(make-constant (make-object (primref->symbol 'do-overflow)))
|
|
|
|
(make-constant (- disp-symbol-record-proc symbol-ptag))))
|
2007-02-13 05:08:48 -05:00
|
|
|
(list size)))))
|
2007-02-12 17:59:58 -05:00
|
|
|
;;; impose value
|
2007-02-10 18:51:12 -05:00
|
|
|
(define (V d x)
|
2007-10-12 02:59:27 -04:00
|
|
|
(struct-case x
|
2007-02-10 18:51:12 -05:00
|
|
|
[(constant) (make-set d x)]
|
2007-03-11 03:40:47 -04:00
|
|
|
[(var)
|
|
|
|
(cond
|
|
|
|
[(var-loc x) => (lambda (loc) (make-set d loc))]
|
|
|
|
[else (make-set d x)])]
|
2007-02-10 18:51:12 -05:00
|
|
|
[(bind lhs* rhs* e)
|
|
|
|
(do-bind lhs* rhs* (V d e))]
|
|
|
|
[(seq e0 e1)
|
|
|
|
(make-seq (E e0) (V d e1))]
|
2007-02-11 17:23:13 -05:00
|
|
|
[(conditional e0 e1 e2)
|
|
|
|
(make-conditional (P e0) (V d e1) (V d e2))]
|
2007-02-10 18:51:12 -05:00
|
|
|
[(primcall op rands)
|
2007-02-12 17:59:58 -05:00
|
|
|
(case op
|
|
|
|
[(alloc)
|
|
|
|
(S (car rands)
|
|
|
|
(lambda (size)
|
2007-02-13 05:08:48 -05:00
|
|
|
(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)))))))]
|
2007-02-12 17:59:58 -05:00
|
|
|
[(mref)
|
|
|
|
(S* rands
|
|
|
|
(lambda (rands)
|
|
|
|
(make-set d (make-disp (car rands) (cadr rands)))))]
|
2008-04-09 03:05:19 -04:00
|
|
|
[(mref32)
|
|
|
|
(S* rands
|
|
|
|
(lambda (rands)
|
|
|
|
(make-asm-instr 'load32 d
|
|
|
|
(make-disp (car rands) (cadr rands)))))]
|
2007-06-08 01:54:10 -04:00
|
|
|
[(bref)
|
|
|
|
(S* rands
|
|
|
|
(lambda (rands)
|
2008-09-06 07:17:20 -04:00
|
|
|
(make-asm-instr 'load8 d
|
2007-06-08 01:54:10 -04:00
|
|
|
(make-disp (car rands) (cadr rands)))))]
|
2007-02-22 21:58:38 -05:00
|
|
|
[(logand logxor logor int+ int- int*
|
2007-02-25 21:29:28 -05:00
|
|
|
int-/overflow int+/overflow int*/overflow)
|
2007-02-12 17:59:58 -05:00
|
|
|
(make-seq
|
|
|
|
(V d (car rands))
|
|
|
|
(S (cadr rands)
|
|
|
|
(lambda (s)
|
|
|
|
(make-asm-instr op d s))))]
|
2008-07-26 15:28:51 -04:00
|
|
|
[(int-quotient)
|
2007-02-14 15:50:34 -05:00
|
|
|
(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))))]
|
2008-07-26 15:28:51 -04:00
|
|
|
[(int-remainder)
|
2007-02-12 23:03:41 -05:00
|
|
|
(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))))]
|
2008-03-18 00:49:24 -04:00
|
|
|
[(sll sra srl sll/overflow)
|
2007-02-12 17:59:58 -05:00
|
|
|
(let ([a (car rands)] [b (cadr rands)])
|
|
|
|
(cond
|
|
|
|
[(constant? b)
|
|
|
|
(make-seq
|
|
|
|
(V d a)
|
|
|
|
(make-asm-instr op d b))]
|
2007-02-14 15:50:34 -05:00
|
|
|
[else
|
|
|
|
(S b
|
|
|
|
(lambda (b)
|
|
|
|
(seq*
|
|
|
|
(V d a)
|
|
|
|
(make-set ecx b)
|
|
|
|
(make-asm-instr op d ecx))))]))]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid value op" op)])]
|
2007-02-11 04:12:09 -05:00
|
|
|
[(funcall rator rands)
|
2007-02-11 18:52:10 -05:00
|
|
|
(handle-nontail-call rator rands d #f)]
|
|
|
|
[(jmpcall label rator rands)
|
2007-02-12 13:58:04 -05:00
|
|
|
(handle-nontail-call rator rands d label)]
|
2007-02-12 23:03:41 -05:00
|
|
|
[(forcall op rands)
|
|
|
|
(handle-nontail-call
|
|
|
|
(make-constant (make-foreign-label op))
|
|
|
|
rands d op)]
|
2007-02-22 23:02:50 -05:00
|
|
|
[(shortcut body handler)
|
|
|
|
(make-shortcut
|
2007-02-22 21:58:38 -05:00
|
|
|
(V d body)
|
2007-02-22 23:02:50 -05:00
|
|
|
(V d handler))]
|
2008-07-07 02:48:16 -04:00
|
|
|
[(known x) (V d x)]
|
2007-02-12 23:03:41 -05:00
|
|
|
[else
|
|
|
|
(if (symbol? x)
|
|
|
|
(make-set d x)
|
2007-10-25 14:32:26 -04:00
|
|
|
(error who "invalid value" (unparse x)))]))
|
2007-02-10 18:51:12 -05:00
|
|
|
;;;
|
2007-02-11 04:12:09 -05:00
|
|
|
(define (assign* lhs* rhs* ac)
|
|
|
|
(cond
|
|
|
|
[(null? lhs*) ac]
|
|
|
|
[else
|
|
|
|
(make-seq
|
|
|
|
(make-set (car lhs*) (car rhs*))
|
|
|
|
(assign* (cdr lhs*) (cdr rhs*) ac))]))
|
|
|
|
;;;
|
2007-02-10 18:51:12 -05:00
|
|
|
(define (VT x)
|
2007-03-03 23:17:04 -05:00
|
|
|
(S x
|
|
|
|
(lambda (x)
|
|
|
|
(make-seq
|
|
|
|
(make-set return-value-register x)
|
2007-11-06 17:04:27 -05:00
|
|
|
(make-primcall 'return
|
|
|
|
(list pcr esp apr return-value-register))))))
|
2007-02-12 17:59:58 -05:00
|
|
|
;;; impose effect
|
2007-02-11 17:23:13 -05:00
|
|
|
(define (E x)
|
2007-10-12 02:59:27 -04:00
|
|
|
(struct-case x
|
2007-02-11 17:23:13 -05:00
|
|
|
[(seq e0 e1) (make-seq (E e0) (E e1))]
|
|
|
|
[(conditional e0 e1 e2)
|
|
|
|
(make-conditional (P e0) (E e1) (E e2))]
|
2007-02-12 13:58:04 -05:00
|
|
|
[(bind lhs* rhs* e)
|
|
|
|
(do-bind lhs* rhs* (E e))]
|
2007-02-11 17:23:13 -05:00
|
|
|
[(primcall op rands)
|
2007-02-12 17:59:58 -05:00
|
|
|
(case op
|
2008-09-06 07:17:20 -04:00
|
|
|
[(mset bset mset32)
|
2007-02-12 17:59:58 -05:00
|
|
|
(S* rands
|
|
|
|
(lambda (s*)
|
2007-02-14 15:50:34 -05:00
|
|
|
(make-asm-instr op
|
2008-06-28 05:25:44 -04:00
|
|
|
(make-disp (car s*) (cadr s*))
|
2007-02-12 17:59:58 -05:00
|
|
|
(caddr s*))))]
|
2007-06-18 07:29:39 -04:00
|
|
|
[(fl:load fl:store fl:add! fl:sub! fl:mul! fl:div!
|
2007-11-08 22:22:24 -05:00
|
|
|
fl:from-int fl:shuffle bswap!
|
|
|
|
fl:store-single fl:load-single)
|
2007-06-15 01:53:34 -04:00
|
|
|
(S* rands
|
|
|
|
(lambda (s*)
|
|
|
|
(make-asm-instr op (car s*) (cadr s*))))]
|
2007-11-08 22:22:24 -05:00
|
|
|
[(nop interrupt incr/zero? fl:double->single
|
|
|
|
fl:single->double) x]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error 'impose-effect "invalid instr" x)])]
|
2007-02-13 17:24:00 -05:00
|
|
|
[(funcall rator rands)
|
2007-02-11 18:52:10 -05:00
|
|
|
(handle-nontail-call rator rands #f #f)]
|
2007-02-11 21:18:12 -05:00
|
|
|
[(jmpcall label rator rands)
|
2007-02-12 13:58:04 -05:00
|
|
|
(handle-nontail-call rator rands #f label)]
|
2007-02-12 23:03:41 -05:00
|
|
|
[(forcall op rands)
|
|
|
|
(handle-nontail-call
|
|
|
|
(make-constant (make-foreign-label op))
|
|
|
|
rands #f op)]
|
2007-02-25 21:29:28 -05:00
|
|
|
[(shortcut body handler)
|
|
|
|
(make-shortcut (E body) (E handler))]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid effect" x)]))
|
2007-02-12 17:59:58 -05:00
|
|
|
;;; impose pred
|
2007-02-11 17:23:13 -05:00
|
|
|
(define (P x)
|
2007-10-12 02:59:27 -04:00
|
|
|
(struct-case x
|
2007-02-12 13:58:04 -05:00
|
|
|
[(constant) x]
|
2007-02-11 17:23:13 -05:00
|
|
|
[(seq e0 e1) (make-seq (E e0) (P e1))]
|
|
|
|
[(conditional e0 e1 e2)
|
|
|
|
(make-conditional (P e0) (P e1) (P e2))]
|
2007-02-12 13:58:04 -05:00
|
|
|
[(bind lhs* rhs* e)
|
|
|
|
(do-bind lhs* rhs* (P e))]
|
2007-02-11 17:23:13 -05:00
|
|
|
[(primcall op rands)
|
2007-02-13 17:24:00 -05:00
|
|
|
(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
|
2008-06-11 02:01:22 -04:00
|
|
|
(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))))]))]
|
2007-02-24 15:42:57 -05:00
|
|
|
[(shortcut body handler)
|
|
|
|
(make-shortcut (P body) (P handler))]
|
2007-10-25 14:32:26 -04:00
|
|
|
[else (error who "invalid pred" x)]))
|
2007-02-11 17:23:13 -05:00
|
|
|
;;;
|
2007-03-11 03:40:47 -04:00
|
|
|
(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
|
2007-09-09 23:31:19 -04:00
|
|
|
(cons* argc-register
|
2007-03-11 03:40:47 -04:00
|
|
|
pcr esp apr
|
|
|
|
locs)))]
|
|
|
|
[else
|
|
|
|
(make-primcall 'indirect-jump
|
2007-09-09 23:31:19 -04:00
|
|
|
(cons* argc-register
|
2007-03-11 03:40:47 -04:00
|
|
|
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))
|
2007-02-19 18:21:35 -05:00
|
|
|
(make-seq
|
2007-03-11 03:40:47 -04:00
|
|
|
(V t (car args))
|
|
|
|
(f (cdr args) (cdr locs)
|
|
|
|
(cons t targs) (cons (car locs) tlocs))))]))))
|
|
|
|
(define (Tail x)
|
2007-10-12 02:59:27 -04:00
|
|
|
(struct-case x
|
2007-03-11 03:40:47 -04:00
|
|
|
[(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)])
|
2007-09-09 23:31:19 -04:00
|
|
|
(set! locals (cons* t0 t1 t2 locals))
|
|