guile-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

guile/guile-lightning compiler.scm


From: Marius Vollmer
Subject: guile/guile-lightning compiler.scm
Date: Tue, 10 Apr 2001 17:02:27 -0700

CVSROOT:        /cvs
Module name:    guile
Changes by:             01/04/10 17:02:27

Modified files:
        guile-lightning: compiler.scm 

Log message:
        * compiler.scm: Lotsa new stuff related to register allocation and
        spilling.
        (compile-to-asm): Invoke peephole optimizer, with an option to not
        invoke it.
        (compile-show): Pass peephole option to compile-to-asm.

CVSWeb URLs:
http://subversions.gnu.org/cgi-bin/cvsweb/guile/guile-lightning/compiler.scm.diff?tr1=1.1&tr2=1.2r1=text&r2=text

Patches:
Index: guile/guile-lightning/compiler.scm
diff -u guile/guile-lightning/compiler.scm:1.1 
guile/guile-lightning/compiler.scm:1.2
--- guile/guile-lightning/compiler.scm:1.1      Sun Apr  8 20:53:17 2001
+++ guile/guile-lightning/compiler.scm  Tue Apr 10 17:02:27 2001
@@ -21,7 +21,7 @@
 ;;
 ;; - (make-closure TEMPLATE ENV)
 ;;
-;;   Make a closure form a closure template and an environment.  A
+;;   Make a closure from a closure template and an environment.  A
 ;;   closure can be invoked.  ENV can be anything.
 ;;
 ;; - (if TEST THEN ELSE)
@@ -35,12 +35,12 @@
 ;; - (local SYMBOL)
 ;;
 ;;   Retrieve the value of the local variable SYMBOL, as established
-;;   by LOCALS or LAMBDA-TEMPLATE.
+;;   by LABELS, FUNCTIONS or LAMBDA-TEMPLATE.
 ;;
 ;; - (set-local SYMBOL VAL)
 ;;
 ;;   Set the value of the local variable SYMBOL, as established
-;;   by LOCALS or LAMBDA-TEMPLATE.
+;;   by LABELS, FUNCTIONS or LAMBDA-TEMPLATE.
 ;;
 ;;   Note that SET-LOCAL does not interact correctly with call/cc.
 ;;   The values of locals are copied by call/cc and any changes to
@@ -49,7 +49,7 @@
 ;;  
 ;; - (global SYMBOL)
 ;;
-;;   Retrieve the value of the global variable that is named by symbol
+;;   Retrieve the value of the global variable that is named by SYMBOL
 ;;   in the current module.  (Current at the time of linking.)
 ;;
 ;; - (invoke PROC ARGS...)
@@ -102,7 +102,7 @@
 ;; A `functions' form where all `calls' appear in tail positions is
 ;; semantically equivalent to a `labels' form, but the compiler
 ;; doesn't detect this.  It still emits code to handle the general
-;; code.  You have to help it by explicitely using a `labels' form
+;; case.  You have to help it by explicitely using a `labels' form
 ;; when possible.  This might change in the future, but right now,
 ;; `functions' isn't even implemented at all.
 ;;
@@ -125,17 +125,17 @@
 
 ;; TODO:
 ;;
-;; - register allocation
+;; - take preference strength into account for register allocation
 ;; - find common tails in `labels'
-;; - tail calling
 ;; - rest args
 ;; - inline ops
-;; - peephole optimizer
+;; - continuously extend peephole optimizer
 
 (read-set! keywords 'prefix)
 
 (define-module (lightning compiler)
   :use-module (lightning assembler)
+  :use-module (lightning peephole)
   :use-module (oop goops)
   :use-module (ice-9 receive)
   :use-module (ice-9 common-list))
@@ -193,10 +193,10 @@
 ;;; The compilation environment
 
 ;; The environment describes the stack at a certain point in the code.
-;; It includes the value of the stack pointer and the locations of the
-;; local variables (stack offset or register).  It also includes
-;; information about labels so that the stack can be correctly unwound
-;; when jumping to a label.
+;; It includes the locations of the local variables (stack offset or
+;; register) and where the various registers have been spilled.  It
+;; also includes information about labels so that the stack can be
+;; correctly unwound when jumping to a label.
 
 (define (make-empty-env)
   '())
@@ -214,30 +214,116 @@
 (define (env-push env)
   (env-push-local #f env))
 
-(define (env-stack-depth target? env)
+;; We have allocated a variable to a register
+;;
+(define (env-alloc-reg var reg env)
+  (extend-env `(reg ,var ,reg) env))
+
+;; We have spilled a register to the stack
+;;
+(define (env-spill-reg reg env)
+  ;; There must be at most one spill frame per register allocation and
+  ;; each spill frame must have a register allocation.
+  (define (find-reg env)
+    (cond ((or (null? env)
+              (and (form? 'spill (car env))
+                   (eq? (caddr (cadr (car env))) reg)))
+          (pk 'nope)
+          #f)
+         ((and (form? 'reg (car env))
+               (eq? (caddr (car env)) reg))
+          (car env))
+         (else
+          (find-reg (cdr env)))))
+  (pk 'spilling reg)
+  (let ((alloc-frame (find-reg env)))
+    (if alloc-frame
+       (extend-env `(spill ,alloc-frame) env)
+       env)))
+
+(define (env-stack-depth frame env)
   (let loop ((e env)
             (offset 0))
-    (cond ((target? e)
+    (cond ((eq? frame e)
           offset)
          ((form? 'push (car e))
-          (loop (cdr e) (+ offset 4)))
+          (loop (cdr e) (+ offset 1)))
+         ((form? 'reg (car e))
+          (loop (cdr e) offset))
+         ((form? 'spill (car e))
+          (loop (cdr e) (+ offset 1)))
          ((form? 'labels (car e))
           (loop (cdr e) offset))
          (else
           (error "unsupported environment frame:" (car e))))))
 
+;; Lookup the local variable VAR.  VAR can be a symbol, in which case
+;; we look for the most recent `push' or `reg' frame.  When VAR is
+;; defined in a `reg' frame we will defer to its spill frame, if any.
+;; VAR can also be a frame, in which case we find the variable defined
+;; by that frame.  This function returns the part of the environment
+;; beginning with the frame defining VAR.
+
+(define (lookup-local-frame var env)
+  (let loop ((e env)
+            (spill-e #f))
+    (cond ((null? e)
+          (error "undefined local variable:" var))
+         ((form? 'push (car e))
+          (if (or (eq? var (car e))
+                  (eq? (cadr (car e)) var))
+              e
+              (loop (cdr e) spill-e)))
+         ((form? 'reg (car e))
+          (if (or (eq? var (car e))
+                  (eq? (cadr (car e)) var))
+              (if (and spill-e (eq? (cadr (car spill-e)) (car e)))
+                  spill-e
+                  e)
+              (loop (cdr e) spill-e)))
+         ((form? 'spill (car e))
+          (if (or (eq? var (cadr (car e)))
+                  (eq? (cadr (cadr (car e))) var))
+              (loop (cdr e) e)
+              (loop (cdr e) spill-e)))
+         ((form? 'labels (car e))
+          (loop (cdr e) spill-e))
+         (else
+          (error "unsupported environment frame:" (car e))))))
+
+;; Lookup the local variable defined by VAR, as explained above.
+;; Return its palcement, which is either a stack offset or a register
+;; name.
+
 (define (lookup-local var env)
-  (env-stack-depth (lambda (e)
-                    (and (form? 'push (car e))
-                         (eq? (cadr (car e)) var)))
-                  env))
-
-(define (unwind-env target-env env)
-  (let ((offset (env-stack-depth (lambda (e)
-                                  (eq? e target-env))
-                                env)))
-    `((add sp sp ,offset))))
+  (let ((frame (lookup-local-frame var env)))
+    (if (form? 'reg (car frame))
+       (caddr (car frame))
+       (env-stack-depth frame env))))
+
+;; Lookup the variable that is in register REG and is not spilled.
+;; Return the part of the environment that starts with the defining
+;; frame.
 
+(define (lookup-register-frame reg env)
+  (let loop ((e env))
+    (cond ((null? e)
+          #f)
+         ((form? 'push (car e))
+          (loop (cdr e)))
+         ((form? 'reg (car e))
+          (if (eq? (caddr (car e)) reg)
+              e
+              (loop (cdr e))))
+         ((form? 'spill (car e))
+          (if (eq? (caddr (cadr (car e))) reg)
+              #f
+              (loop (cdr e))))
+         ((form? 'labels (car e))
+          (loop (cdr e)))
+         (else
+          (error "unsupported environment frame:" (car e))))))
+
 (define invoke-code
   (assemble `(  (bms l0 r0 6)
                (ld r2 r0)
@@ -266,9 +352,8 @@
       (string->symbol (string-append "l" (number->string seqno))))))
 
 (define (compile-with-return exp env)
-  `(,@(compile-expression exp env 'r0)
-    ,@(compile-expression '(local :ret) env 'r2)
-    ,@(unwind-env '() env)
+  (pk 'return)
+  `(,@(compile-tail-args `((r0 . ,exp) (r2 . (local :ret))) base-env env)
     (mov r1 4)
     (jmp r2)))
 
@@ -287,12 +372,17 @@
 ;;   (name label args)
 ;;
 ;; where NAME is the label from the statement, LABEL is a generated
-;; unique assembler label, ARGS is the list of arguments of this
-;; label.
+;; unique assembler label, ARGS is the list of arguments and their
+;; placements in the form
+;;
+;;   ((PLACE . NAME) ...)
+;;
+;; A place of `stack' denotes stack passing, else it names a register.
 
-(define (make-labels-frame labels)
+(define (make-labels-frame labels env)
   `(labels ,@(map (lambda (l)
-                   (list (car l) (genlabel) (cadr l)))
+                   (list (car l) (genlabel)
+                         (allocate-places (cadr l) env)))
                  labels)))
 
 (define (find-labels-frame target env)
@@ -305,6 +395,36 @@
          (else
           (loop (cdr e))))))
 
+;; Register allocation
+
+(define (allocate-places args env)
+
+  (define (get-reg-pref a)
+    (let ((pref-opt (and (pair? a) (memq :reg a))))
+      (if pref-opt
+         (cadr pref-opt)
+         0)))
+
+  (define (get-arg-name a)
+    (if (pair? a) (car a) a))
+
+  (let loop ((available-regs non-volatile-regs)
+            (a args)
+            (res '()))
+    (cond ((null? a)
+          (reverse! res))
+         ((or (null? available-regs)
+              (zero? (get-reg-pref (car a))))
+          (loop available-regs
+                (cdr a)
+                (cons (cons 'stack (get-arg-name (car a)))
+                      res)))
+         (else
+          (loop (cdr available-regs)
+                (cdr a)
+                (cons (cons (car available-regs) (get-arg-name (car a)))
+                      res))))))
+
 ;; Find the free locals in EXP
 
 (define (unions . lists) (reduce union lists))
@@ -320,7 +440,7 @@
    ((form? 'local exp)
     (list (cadr exp)))
    ((form? 'set-local exp)
-    (list (cadr exp)))
+    (union (list (cadr exp)) (free-locals (caddr exp))))
    ((form? 'invoke exp)
     (union-map free-locals (cdr exp)))
    ((form? 'if exp)
@@ -343,20 +463,47 @@
    (else
     (error "unsupported form:" exp))))
 
+;; Find the registers clobbered by exp
+
+(define (clobbered-regs exp)
+  (cond
+   ((form? 'global exp)
+    '())
+   ((form? 'quote exp)
+    '())
+   ((form? 'local exp)
+    '())
+   ((form? 'set-local exp)
+    (clobbered-regs (caddr exp)))
+   ((form? 'invoke exp)
+    volatile-regs)
+   ((form? 'if exp)
+    (union-map clobbered-regs (cdr exp)))
+   ((form? 'begin exp)
+    (union-map clobbered-regs (cdr exp)))
+   ((form? 'goto exp)
+    '())
+   ((form? 'labels exp)
+    volatile-regs)
+   (else
+    (error "unsupported form:" exp))))
+
+
 (define-struct arg-node ()
   exp slot (conflicts '()) (id #f) (comp-id #f))
 
 (define volatile-regs '(r0 r1 r2))
+(define non-volatile-regs '(v0 v1 v2))
 
 ;; Generate code for pushing ARGS and simultanously unwinding the
 ;; stack to TARGET-ENV.
 
-;; REG-ARGS is a list of (reg . exp) pairs, where REG is a symbol and
-;; EXP is the expression that computes the value for that argument.
-;; STACK-ARGS is just a list of expressions that will be pushed in
-;; reverse order.
+;; ARGS is a list of (reg . exp) pairs, where REG is a symbol and EXP
+;; is the expression that computes the value for that argument.  When
+;; REG is the symbol `stack', the argument will be passed on the
+;; stack, else it will be passed in the register denoted by REG.
 
-(define (compile-tail-args reg-args stack-args target-env env)
+(define (compile-tail-args args target-env env)
 
   ;; We partition the arguments into `easy' and `tough'.  An easy
   ;; argument is one that is in a stack slot above the current stack
@@ -372,6 +519,19 @@
   ;; strongly connected component, pushing it, and replacing it with
   ;; an expression that retrieves the pushed value.
 
+  ;; We also deal with register spilling here.  For each argument that
+  ;; is to be passed in a non-volatile register, we spill that
+  ;; register into a stack slot.  The value spilled will be the one
+  ;; that is live in the register at the target env, but will be found
+  ;; using the current env.  The non-volatile registers that are not
+  ;; used to pass arguments are directly loaded with the value live in
+  ;; the target env, using the current env to find that value.
+
+  ;; This spilling is implemented by creating addition arguments that
+  ;; describe the spill slots, and register values.  This might seem
+  ;; to lead to a lot of overhead, but one should realize that most of
+  ;; these additional arguments lead to noops in typical loops.
+
   (define (push-conflict node conf)
     (set! (arg-node-conflicts node)
          (cons conf (arg-node-conflicts node))))
@@ -400,12 +560,11 @@
                  nodes))
       (for-each (lambda (n)
                  (for-each (lambda (l)
-                             (update-conflicts  n 
-                                                (/ (lookup-local l env) 4)))
+                             (update-conflicts n (lookup-local l env)))
                            (free-locals (arg-node-exp n)))
                  (for-each (lambda (r)
                              (update-conflicts n r))
-                           volatile-regs))
+                           (adjoin 'r1 (clobbered-regs (arg-node-exp n)))))
                nodes)
       nodes))
 
@@ -468,20 +627,17 @@
   (define (schedule-strongly-connected comp)
     (let* ((arg (car comp))
           (slot (arg-node-slot arg))
-          (target (if (number? slot) 'r0 slot))
+          (target (if (number? slot) 'r1 slot))
           (store-code (if (number? slot)
-                          `((stx ,(+ tough-offset (* 4 slot)) sp r0))
+                          `((stx ,(* 4 (+ tough-offset slot)) sp r1)
+                            (die r1))
                           `())))
-      (set! tough-code
-           `(,@tough-code
-             ,@(compile-expression (arg-node-exp arg) tough-env target)))
       (cond ((null? (cdr comp))
-            ;; XXX - special casing this ought to be unnecessary when
-            ;; the peephole optimizer removes empty push/pop
-            ;; sequences.
             (pk 'storing (arg-node-slot (car comp)))
             (set! tough-code
                   `(,@tough-code
+                    ,@(compile-expression (arg-node-exp arg)
+                                          tough-env target)
                     ,@store-code)))
            (else
             (pk 'pushing (arg-node-slot (car comp)))
@@ -489,8 +645,11 @@
                   (offset tough-offset))
               (set! tough-code
                     `(,@tough-code
-                      (push r0)))
-              (set! tough-offset (+ 4 tough-offset))
+                      ,@(compile-expression (arg-node-exp arg)
+                                            tough-env 'r1)
+                      (push r1)
+                      (die r1)))
+              (set! tough-offset (+ 1 tough-offset))
               (set! tough-env (env-push tough-env))
               (set! comp-id (1+ comp-id))
               (schedule-component (cdr comp) comp-id)
@@ -511,13 +670,78 @@
       (set! tough-env env)
       (schedule-component nodes comp-id)
       tough-code))
+
+  (define (pick-stack-args args)
+    (let loop ((a args)
+              (s '()))
+      (cond ((null? a)
+            (reverse! s))
+           ((eq? (car (car a)) 'stack)
+            (loop (cdr a) (cons (cdr (car a)) s)))
+           (else
+            (loop (cdr a) s)))))
+
+  (define (pick-reg-args args)
+    (let loop ((a args)
+              (r '()))
+      (cond ((null? a)
+            (reverse! r))
+           ((eq? (car (car a)) 'stack)
+            (loop (cdr a) r))
+           (else
+            (loop (cdr a) (cons (car a) r))))))
 
-  (let* ((n-stack-args (length stack-args))
+  ;; Construct a `(local ...)' expression that refers to the variable
+  ;; that is stored in REG in TARGET-ENV.  Return #f when the register
+  ;; is not allocated in TARGET-ENV.
+  ;;
+  (define (make-register-value-expression reg)
+    (if (memq reg non-volatile-regs)
+       (let ((frame (lookup-register-frame reg target-env)))
+         (if frame
+             `(local ,(car frame))
+             #f))
+       #f))
+
+  ;; Make the stack-args that will spill the used registers.
+  ;;
+  (define (make-spill-args reg-args)
+    (pk 'spill-args reg-args
+    (let loop ((sa '())
+              (ra reg-args))
+      (cond ((null? ra)
+            sa)
+           (else
+            (let* ((reg (car (car ra)))
+                   (exp (make-register-value-expression reg)))
+              (if exp
+                  (loop (cons exp sa) (cdr ra))
+                  (loop sa (cdr ra)))))))))
+
+  ;; Make the reg-args that will load the unused registers.
+  ;;
+  (define (make-unspill-args reg-args)
+    (pk 'unspill-args reg-args
+    (let loop ((ua '())
+              (regs (set-difference non-volatile-regs
+                                    (map car reg-args))))
+      (cond ((null? regs)
+            ua)
+           (else
+            (let* ((reg (car regs))
+                   (exp (make-register-value-expression reg)))
+              (if exp
+                  (loop (cons (cons reg exp) ua) (cdr regs))
+                  (loop ua (cdr regs)))))))))
+
+  (let* ((reg-args-1 (pick-reg-args args))
+        (stack-args (append! (pick-stack-args args)
+                             (make-spill-args reg-args-1)))
+        (reg-args (append! reg-args-1
+                           (make-unspill-args reg-args-1)))
+        (n-stack-args (length stack-args))
         (n-reg-args (length reg-args))
-        (n-stack-slots (/ (env-stack-depth (lambda (e)
-                                             (eq? e target-env))
-                                           env)
-                          4))
+        (n-stack-slots (env-stack-depth target-env env))
         (n-tough (min n-stack-args n-stack-slots))
         (n-easy (- n-stack-args n-tough)))
     (pk 'tail-args
@@ -542,8 +766,46 @@
                   (env-push env)
                   `(,@code
                     ,@(compile-expression (car rev-args) env 'r0)
-                    (push r0))))))))
+                    (push r0)
+                    (die r0))))))))
+
+(define (stackify args)
+  (map (lambda (a) (cons 'stack a)) args))
+
+(define (splice-places places args)
+  (map (lambda (p a) (cons (car p) a)) places args))
 
+(define (env-for-args args env)
+  (pk 'for-args args
+      (let loop ((a args)
+                (env env))
+    (cond ((null? a)
+          (let loop ((rev-args (reverse args))
+                     (env env))
+            (cond ((null? rev-args)
+                   env)
+                  (else
+                   (loop (cdr rev-args)
+                         (if (eq? (car (car rev-args)) 'stack)
+                             (env-push-local (cdr (car rev-args)) env)
+                             (env-alloc-reg (cdr (car rev-args))
+                                            (car (car rev-args)) env)))))))
+         ((memq (car (car a)) non-volatile-regs)
+          (loop (cdr a)
+                (env-spill-reg (car (car a)) env)))
+         (else
+          (loop (cdr a)
+                env))))))
+
+(define (env-alloc-non-volatile-regs env)
+  (let loop ((regs non-volatile-regs)
+            (env env))
+    (cond ((null? regs)
+          env)
+         (else
+          (loop (cdr regs)
+                (env-alloc-reg #f (car regs) env))))))
+
 (define (compile-expression exp env target)
   (cond
 
@@ -556,19 +818,27 @@
       (else
        (let ((acc (lookup-local (cadr exp) env)))
          (cond ((number? acc)
-                `((ldx ,target sp ,acc)))
+                `((ldx ,target sp ,(* 4 acc))))
                (else
-                (error "unsupported access method:" acc)))))))
+                `((mov ,target ,acc))))))))
 
    ((form? 'set-local exp)
     (let ((acc (lookup-local (cadr exp) env))
          (val (caddr exp)))
-      `(,@(compile-expression val env 'r0)
-       ,@(cond ((number? acc)
-                `((stx sp ,acc r0)))
-               (else
-                (error "unsupported access method:" acc)))
-       ,@(compile-expression (cadr exp) env target))))
+      (case target
+       ((:tail)
+        (compile-with-return exp env))
+       (else
+        `(,@(compile-expression val env 'r0)
+          ,@(cond ((number? acc)
+                   `((stx ,(* 4 acc) sp r0)
+                     (die r0)))
+                  (else
+                   `((mov ,acc r0)
+                     (die r0))))
+          ,@(if (not (eq? target :none))
+                `((mov ,target (scm ,(if #f #f))))
+                '()))))))
 
    ((form? 'quote exp)
     (case target
@@ -591,44 +861,21 @@
             `((ld ,target (var ,var)))
             (error "undefined global variable:" (cadr exp)))))))
 
-;    ((form? 'invoke exp)
-;     (if (eq? target :tail)
-;      (begin
-;        (display ";;; no tail-calls yet.\n")
-;        (compile-with-return exp env))
-;      ;; push args in reverse order
-;      (let loop ((args (reverse (cddr exp)))
-;                 (env env)
-;                 (code '()))
-;        (cond ((not (null? args))
-;               (loop (cdr args)
-;                     (env-push env)
-;                     (append! code
-;                              `(,@(compile-expression (car args)
-;                                                      env 'r0)
-;                                (push r0)))))
-;              (else
-;               ;; load argument count into r1,
-;               ;; load proc into r0 and jump to "invoke"
-;               (append! code
-;                        `(
-;                          ,@(compile-expression (cadr exp) env 'r0)
-;                          (mov r1 ,(* 4 (length (cddr exp))))
-;                          (call (code ,invoke-code))
-;                          (mov ,target r0))))))))
-
    ((form? 'invoke exp)
     (let ((proc (cadr exp))
          (args (cddr exp)))
       (cond ((eq? target :tail)
-            `(,@(compile-tail-args (list (cons 'r0 proc))
-                                   (cons '(local :ret) args)
-                                   '() env)
+            `(,@(compile-tail-args (list* (cons 'r0 proc)
+                                          (stackify
+                                           (cons '(local :ret)
+                                                 args)))
+                                   base-env env)
               (mov r1 ,(* 4 (length args)))
               (jmp (code ,invoke-code))))
            (else
-            `(,@(compile-tail-args (list (cons 'r0 proc))
-                                   args env env)
+            `(,@(compile-tail-args (list* (cons 'r0 proc)
+                                          (stackify args))
+                                   env env)
               (mov r1 ,(* 4 (length args)))
               (call (code ,invoke-code))
               ,@(if (not (eq? target :none))
@@ -666,7 +913,7 @@
     (let* ((labels (cadr exp))
           (bodies (map cddr labels))
           (body (cons 'begin (cddr exp)))
-          (frame (make-labels-frame labels))
+          (frame (make-labels-frame labels env))
           (env (extend-env frame env))
           (end-label (genlabel)))
       `(,@(compile-expression body env target)
@@ -674,18 +921,12 @@
        ,@(apply append!
                 (map (lambda (l b)
                        (let ((label (cadr l))
-                             (body (cons 'begin b)))
-                       (let loop ((rev-args (reverse (caddr l)))
-                                  (inner-env env))
-                         (cond ((null? rev-args)
-                                `(,label
-                                  ,@(compile-expression body inner-env target)
-                                  ,@(unwind-env env inner-env)
-                                  (b ,end-label)))
-                               (else
-                                (loop (cdr rev-args)
-                                      (env-push-local (car rev-args)
-                                                      inner-env)))))))
+                             (body (cons 'begin b))
+                             (inner-env (env-for-args (caddr l) env)))
+                         `(,label
+                           ,@(compile-expression body inner-env target)
+                           ,@(compile-tail-args '() env inner-env)
+                           (b ,end-label))))
                      (cdr frame) bodies))
        ,end-label)))
 
@@ -699,36 +940,35 @@
       (if (not (= (length args) (length target-args)))
          (error "wrong number of arguments in goto:" exp))
       (pk 'goto label target-label)
-      `(,@(compile-tail-args '() args target-env env)
+      `(,@(compile-tail-args (splice-places target-args args) target-env env)
        (b ,target-label))))
 
    (else
     (error "unsupported form:" exp))))
 
-(define (compile-to-asm form)
+(define base-env (env-alloc-non-volatile-regs (make-empty-env)))
+
+(define (compile-to-asm form . opt-nopeep)
   (if (or (not (list? form)) (not (eq? (car form) 'lambda-template)))
       (error "only lambda-templates can be compiled"))
-  (let* ((rev-args (reverse (cadr form)))
-        (nargs (length rev-args)))
-    (let loop ((a rev-args)
-              (env '()))
-      (cond ((not (null? a))
-            (loop (cdr a)
-                  (env-push-local (car a) env)))
-           (else
-            (let ((env (env-push-local :ret env))
-                  (argsok (genlabel)))
-              `(  (beq ,argsok r1 ,(* 4 nargs))
+  (let* ((args (cadr form))
+        (nargs (length args))
+        (env (env-push-local :ret (env-for-args (stackify args) base-env)))
+        (argsok (genlabel))
+        (code `(  (beq ,argsok r1 ,(* 4 nargs))
                   (prepare 1)
                   (mov r0 "some procedure")
                   (pusharg r0)
                   (finish (subr "scm_error_num_args_subr"))
                 ,argsok
                   ,@(compile-expression `(begin ,@(cddr form))
-                                        env :tail))))))))
+                                        env :tail))))
+    (if (or (null? opt-nopeep) (car opt-nopeep))
+       (peephole-optimize code)
+       code)))
 
 (define (compile form)
   (make-closure (assemble (compile-to-asm form)) #f))
 
-(define (compile-show form)
-  (display-asm (compile-to-asm form)))
+(define (compile-show form . opt-no-peep)
+  (display-asm (apply compile-to-asm form opt-no-peep)))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]