Update of /project/movitz/cvsroot/movitz In directory common-lisp.net:/tmp/cvs-serv26284
Modified Files: special-operators-cl.lisp Log Message: Fixed tagbody/go for stack discipline.
Date: Thu Oct 7 14:52:48 2004 Author: ffjeld
Index: movitz/special-operators-cl.lisp diff -u movitz/special-operators-cl.lisp:1.24 movitz/special-operators-cl.lisp:1.25 --- movitz/special-operators-cl.lisp:1.24 Fri Sep 17 13:12:47 2004 +++ movitz/special-operators-cl.lisp Thu Oct 7 14:52:47 2004 @@ -9,7 +9,7 @@ ;;;; Created at: Fri Nov 24 16:31:11 2000 ;;;; Distribution: See the accompanying file COPYING. ;;;; -;;;; $Id: special-operators-cl.lisp,v 1.24 2004/09/17 11:12:47 ffjeld Exp $ +;;;; $Id: special-operators-cl.lisp,v 1.25 2004/10/07 12:52:47 ffjeld Exp $ ;;;; ;;;;------------------------------------------------------------------
@@ -624,10 +624,13 @@ :returns last-returns :functional-p nil)))) -(define-special-operator tagbody (&all forward &funobj funobj &form form &env env &result-mode result-mode) +(define-special-operator tagbody + (&all forward &funobj funobj &form form &env env) (let* ((save-esp-variable (gensym "tagbody-save-esp")) (lexical-catch-tag-variable (gensym "tagbody-lexical-catch-tag-")) - (tagbody-env (make-instance 'lexical-exit-point-env + (label-set-name (gensym "label-set-")) + (tagbody-env (make-instance 'tagbody-env + :label-set-name label-set-name :uplink env :funobj funobj :save-esp-variable save-esp-variable @@ -642,8 +645,7 @@ (movitz-env-load-declarations `((muerte.cl::ignorable ,save-esp-variable ,lexical-catch-tag-variable)) tagbody-env nil) ;; First generate an assembly-level label for each tag. - (let* ((label-set-name (gensym "label-set-")) - (label-set (loop with label-id = 0 + (let* ((label-set (loop with label-id = 0 for tag-or-statement in (cdr form) as label = (when (or (symbolp tag-or-statement) (integerp tag-or-statement)) @@ -654,59 +656,60 @@ (setf (movitz-env-get tag-or-statement 'go-tag-label-id nil tagbody-env) (post-incf label-id)) and collect label)) - (tagbody-functional-p t) - (tagbody-code + (tagbody-codes (loop for tag-or-statement in (cdr form) -;;; when (and (symbolp tag-or-statement) -;;; (movitz-env-get tag-or-statement 'muerte::loop-tag nil tagbody-env)) -;;; collect '(:align :code :loop) if (or (symbolp tag-or-statement) ; Tagbody tags are "compiled" into.. (integerp tag-or-statement)) ; ..their assembly-level labels. collect (movitz-env-get tag-or-statement 'go-tag nil tagbody-env) - else append - (compiler-values-bind (&code code &functional-p functional-p) - (compiler-call #'compile-form - :defaults forward - :form tag-or-statement - :env tagbody-env - :result-mode :ignore) - (unless functional-p - (setf tagbody-functional-p nil)) - code)))) - (let ((maybe-store-esp-code - (when (and (not (eq result-mode :function)) - (operators-present-in-code-p tagbody-code '(:lexical-control-transfer) nil - :test (lambda (x) (eq tagbody-env (fifth x))))) - `((:init-lexvar ,save-esp-binding - :init-with-register :esp - :init-with-type t))))) - (if (not (code-uses-binding-p tagbody-code lexical-catch-tag-binding)) + else collect + (compiler-call #'compile-form + :defaults forward + :form tag-or-statement + :env tagbody-env + :result-mode :ignore)))) + (let* ((unlexical-target-p (some (lambda (code) + (when (listp code) + (code-uses-binding-p code save-esp-binding))) + tagbody-codes)) + (maybe-store-esp-code + (when (or unlexical-target-p + (some (lambda (code) + (when (listp code) + (operators-present-in-code-p code '(:lexical-control-transfer) nil + :test (lambda (x) + (eq tagbody-env (fifth x)))))) + tagbody-codes)) + `((:init-lexvar ,save-esp-binding + :init-with-register :esp + :init-with-type t))))) + (if (not unlexical-target-p) (compiler-values () - :code (append maybe-store-esp-code tagbody-code) - :functional-p tagbody-functional-p + :code (append maybe-store-esp-code + (loop for code in tagbody-codes + if (listp code) + append code + else append (list code))) :returns :nothing) - (let ((code (append maybe-store-esp-code - `((:declare-label-set ,label-set-name ,label-set) - (:leal ((:esi 8) :esp) :eax) ; generate some semi-unique value - (:leal ((:eax 2) :edi) :eax) ; with tag5. - (:init-lexvar ,lexical-catch-tag-binding - :init-with-register :eax - :init-with-type t)) - ;; catcher - `((:locally (:pushl (:edi (:edi-offset dynamic-env)))) + (let ((code (append `((:declare-label-set ,label-set-name ,label-set) + ;; catcher + (:locally (:pushl (:edi (:edi-offset dynamic-env)))) (:pushl ',label-set-name) (:pushl :eax) (:pushl :ebp) (:locally (:movl :esp (:edi (:edi-offset dynamic-env))))) - tagbody-code - `((:leal (:esp ,(+ -4 16)) :esp) - (:locally (:popl (:edi (:edi-offset dynamic-env))))) + maybe-store-esp-code + (loop for code in tagbody-codes + if (listp code) + append code + else append (list code '(:movl (:esp) :ebp))) + `((:movl (:esp 12) :edx) + (:locally (:movl :edx (:edi (:edi-offset dynamic-env)))) + (:leal (:esp 16) :esp)) ))) (setf (num-specials tagbody-env) 1 (stack-used tagbody-env) 4) (compiler-values () :code code - :functional-p tagbody-functional-p :returns :nothing))))))) @@ -724,8 +727,31 @@ :code `((:lexical-control-transfer nil :nothing ,env ,tagbody-env ,label))) ;; Perform a lexical "throw" to the tag. Much like a regular throw, except ;; no values are transferred, and we step _into_ that dynamic env, not outside it. - (let ((label-id (movitz-env-get tag 'go-tag-label-id nil tagbody-env nil))) + (let ((save-esp-binding (movitz-binding (save-esp-variable tagbody-env) env)) + (label-id (movitz-env-get tag 'go-tag-label-id nil tagbody-env nil))) (assert label-id) + #+ignore + (compiler-call #'compile-form-unprotected + :forward all + :form `(muerte::exact-throw ,(movitz-env-lexical-catch-tag-variable tagbody-env) + 0 nil)) + (compiler-values () + :returns :non-local-exit + :code `((:load-lexical ,save-esp-binding :edx) + (:movl :edx :eax) + (:globally (:call (:edi (:edi-offset dynamic-unwind-next)))) + (:jnc '(:sub-program () (:int 63))) + ;; have next-continuation in EAX, final-continuation in EDX + (:locally (:movl :edx (:edi (:edi-offset raw-scratch0)))) ; final continuation + (:locally (:movl :esi (:edi (:edi-offset scratch1)))) + (:locally (:movl :eax (:edi (:edi-offset dynamic-env)))) ; exit to next-env + (:movl :eax :esp) ; enter non-local jump stack mode. + (:movl (:esp) :eax) ; target stack-frame EBP + (:movl (:eax -4) :esi) ; get target funobj into ESI + (:movl (:esp 8) :eax) ; target jumper number + (:jmp (:esi :eax + ,(* 4 label-id) ,(slot-offset 'movitz-funobj 'constant0))))) + #+ignore (compiler-values () :returns :non-local-exit :code (append (compiler-call #'compile-form