1.0.27.12: x86/x86-64 calling convention comments, refactoring
authorGabor Melis <mega@hotpop.com>
Tue, 21 Apr 2009 10:25:04 +0000 (10:25 +0000)
committerGabor Melis <mega@hotpop.com>
Tue, 21 Apr 2009 10:25:04 +0000 (10:25 +0000)
src/compiler/x86-64/call.lisp
src/compiler/x86/call.lisp
version.lisp-expr

index 73ff2ac..db0848e 100644 (file)
 ;;; Nvals is the number of values that are to be received (should
 ;;; equal the length of Values).
 ;;;
-;;; MOVE-TEMP is a DESCRIPTOR-REG TN used as a temporary.
-;;;
-;;; This code exploits the fact that in the unknown-values convention,
-;;; a single value return returns at the return PC + 2, whereas a
-;;; return of other than one value returns directly at the return PC.
-;;;
 ;;; If 0 or 1 values are expected, then we just emit an instruction to
 ;;; reset the SP (which will only be executed when other than 1 value
 ;;; is returned.)
 \f
 ;;;; local call with unknown values convention return
 
+(defun check-ocfp-and-return-pc (old-fp return-pc)
+  #+nil
+  (format t "*known-return: old-fp ~S, tn-kind ~S; ~S ~S~%"
+          old-fp (sb!c::tn-kind old-fp) (sb!c::tn-save-tn old-fp)
+          (sb!c::tn-kind (sb!c::tn-save-tn old-fp)))
+  #+nil
+  (format t "*known-return: return-pc ~S, tn-kind ~S; ~S ~S~%"
+          return-pc (sb!c::tn-kind return-pc)
+          (sb!c::tn-save-tn return-pc)
+          (sb!c::tn-kind (sb!c::tn-save-tn return-pc)))
+  (unless (and (sc-is old-fp control-stack)
+               (= (tn-offset old-fp) ocfp-save-offset))
+    (error "ocfp not on stack in standard save location?"))
+  (unless (and (sc-is return-pc sap-stack)
+               (= (tn-offset return-pc) return-pc-save-offset))
+    (error "return-pc not on stack in standard save location?")))
+
 ;;; Non-TR local call for a fixed number of values passed according to
 ;;; the unknown values convention.
 ;;;
     (note-this-location vop :known-return)
     (trace-table-entry trace-table-normal)))
 \f
-;;; Return from known values call. We receive the return locations as
-;;; arguments to terminate their lifetimes in the returning function. We
-;;; restore FP and CSP and jump to the Return-PC.
-;;;
-;;; We can assume we know exactly where old-fp and return-pc are because
-;;; make-old-fp-save-location and make-return-pc-save-location always
-;;; return the same place.
-#+nil
-(define-vop (known-return)
-  (:args (old-fp)
-         (return-pc :scs (any-reg immediate-stack) :target rpc)
-         (vals :more t))
-  (:move-args :known-return)
-  (:info val-locs)
-  (:temporary (:sc unsigned-reg :from (:argument 1)) rpc)
-  (:ignore val-locs vals)
-  (:vop-var vop)
-  (:generator 6
-    (trace-table-entry trace-table-fun-epilogue)
-    ;; Save the return-pc in a register 'cause the frame-pointer is
-    ;; going away. Note this not in the usual stack location so we
-    ;; can't use RET
-    (move rpc return-pc)
-    ;; Restore the stack.
-    (move rsp-tn rbp-tn)
-    ;; Restore the old fp. We know OLD-FP is going to be in its stack
-    ;; save slot, which is a different frame that than this one,
-    ;; so we don't have to worry about having just cleared
-    ;; most of the stack.
-    (move rbp-tn old-fp)
-    (inst jmp rpc)
-    (trace-table-entry trace-table-normal)))
-\f
 ;;; From Douglas Crosher
 ;;; Return from known values call. We receive the return locations as
 ;;; arguments to terminate their lifetimes in the returning function. We
 ;;; restore FP and CSP and jump to the Return-PC.
-;;;
-;;; The old-fp may be either in a register or on the stack in its
-;;; standard save locations - slot 0.
-;;;
-;;; The return-pc may be in a register or on the stack in any slot.
 (define-vop (known-return)
   (:args (old-fp)
          (return-pc)
   (:ignore val-locs vals)
   (:vop-var vop)
   (:generator 6
+    (check-ocfp-and-return-pc old-fp return-pc)
     (trace-table-entry trace-table-fun-epilogue)
-    ;; return-pc may be either in a register or on the stack.
-    (sc-case return-pc
-      ((sap-stack)
-       (unless (and (sc-is old-fp control-stack)
-                    (= (tn-offset old-fp) ocfp-save-offset))
-         (error "known-return: ocfp not on stack in standard save location?"))
-       (unless (and (sc-is return-pc sap-stack)
-                    (= (tn-offset return-pc) return-pc-save-offset))
-         (error
-          "known-return: return-pc not on stack in standard save location?"))
-
-       ;; Zot all of the stack except for the old-fp and return-pc.
-       (inst lea rsp-tn
-             (make-ea :qword :base rbp-tn
-                      :disp (frame-byte-offset ocfp-save-offset)))
-       (inst pop rbp-tn)
-       (inst ret (* (tn-offset return-pc) n-word-bytes)))
-      (t
-       (error "known-return, return-pc not on stack")))
-
+    ;; Zot all of the stack except for the old-fp and return-pc.
+    (inst lea rsp-tn
+          (make-ea :qword :base rbp-tn
+                   :disp (frame-byte-offset ocfp-save-offset)))
+    (inst pop rbp-tn)
+    (inst ret)
     (trace-table-entry trace-table-normal)))
 \f
 ;;;; full call
   (:args (args :scs (any-reg control-stack) :target rsi)
          (function :scs (descriptor-reg control-stack) :target rax)
          (old-fp)
-         (ret-addr))
+         (return-pc))
   (:temporary (:sc unsigned-reg :offset rsi-offset :from (:argument 0)) rsi)
   (:temporary (:sc unsigned-reg :offset rax-offset :from (:argument 1)) rax)
   (:temporary (:sc unsigned-reg) call-target)
-;  (:ignore ret-addr old-fp)
   (:generator 75
+    (check-ocfp-and-return-pc old-fp return-pc)
     ;; Move these into the passing locations if they are not already there.
     (move rsi args)
     (move rax function)
-
-    ;; The following assumes that the return-pc and old-fp are on the
-    ;; stack in their standard save locations - Check this.
-    (unless (and (sc-is old-fp control-stack)
-                 (= (tn-offset old-fp) ocfp-save-offset))
-            (error "tail-call-variable: ocfp not on stack in standard save location?"))
-    (unless (and (sc-is ret-addr sap-stack)
-                 (= (tn-offset ret-addr) return-pc-save-offset))
-            (error "tail-call-variable: ret-addr not on stack in standard save location?"))
-
-
+    ;; And jump to the assembly routine.
     (inst lea call-target
           (make-ea :qword
                    :disp (make-fixup 'tail-call-variable :assembly-routine)))
-    ;; And jump to the assembly routine.
     (inst jmp call-target)))
 \f
 ;;;; unknown values return
          (value))
   (:ignore value)
   (:generator 6
+    (check-ocfp-and-return-pc old-fp return-pc)
     (trace-table-entry trace-table-fun-epilogue)
-    ;; Code structure lifted from known-return.
-    (sc-case return-pc
-      ((sap-stack)
-       ;; Note that this will only work right if, when old-fp is on
-       ;; the stack, it has a lower tn-offset than return-pc. One of
-       ;; the comments in known-return indicate that this is the case
-       ;; (in that it will be in its save location), but we may wish
-       ;; to assert that (in either the weaker or stronger forms).
-       ;; Should this ever not be the case, we should load old-fp into
-       ;; a temp reg while we fix the stack.
-       (unless (and (sc-is old-fp control-stack)
-                    (= (tn-offset old-fp) ocfp-save-offset))
-         (error "ocfp not on stack in standard save location?"))
-       (unless (and (sc-is return-pc sap-stack)
-                    (= (tn-offset return-pc) return-pc-save-offset))
-         (error "return-pc not on stack in standard save location?"))
-       ;; Drop stack above old-fp
-       (inst lea rsp-tn (make-ea :qword :base rbp-tn
-                                 :disp (frame-byte-offset (tn-offset old-fp))))
-       ;; Set single-value return flag
-       (inst clc)
-       ;; Restore the old frame pointer
-       (inst pop rbp-tn)
-       ;; And return, dropping the rest of the stack as we go.
-       (inst ret (* (tn-offset return-pc) n-word-bytes)))
-      (t
-       (error "return pc not on stack")))))
+    ;; Drop stack above old-fp
+    (inst lea rsp-tn (make-ea :qword :base rbp-tn
+                              :disp (frame-byte-offset (tn-offset old-fp))))
+    ;; Clear the multiple-value return flag
+    (inst clc)
+    ;; Restore the old frame pointer
+    (inst pop rbp-tn)
+    ;; And return, dropping the rest of the stack as we go.
+    (inst ret)))
 
 ;;; Do unknown-values return of a fixed (other than 1) number of
 ;;; values. The VALUES are required to be set up in the standard
          (values :more t))
   (:ignore values)
   (:info nvals)
-
   ;; In the case of other than one value, we need these registers to
   ;; tell the caller where they are and how many there are.
   (:temporary (:sc unsigned-reg :offset rbx-offset) rbx)
   (:temporary (:sc unsigned-reg :offset rcx-offset) rcx)
-
   ;; We need to stretch the lifetime of return-pc past the argument
   ;; registers so that we can default the argument registers without
   ;; trashing return-pc.
                    :from :eval) a2)
 
   (:generator 6
+    (check-ocfp-and-return-pc old-fp return-pc)
     (trace-table-entry trace-table-fun-epilogue)
     ;; Establish the values pointer and values count.
     (move rbx rbp-tn)
          (return-pc :target rax)
          (vals :scs (any-reg) :target rsi)
          (nvals :scs (any-reg) :target rcx))
-
   (:temporary (:sc unsigned-reg :offset rax-offset :from (:argument 1)) rax)
   (:temporary (:sc unsigned-reg :offset rsi-offset :from (:argument 2)) rsi)
   (:temporary (:sc unsigned-reg :offset rcx-offset :from (:argument 3)) rcx)
                    :from (:eval 0)) a0)
   (:temporary (:sc unsigned-reg :from (:eval 1)) old-fp-temp)
   (:node-var node)
-
   (:generator 13
+    (check-ocfp-and-return-pc old-fp return-pc)
     (trace-table-entry trace-table-fun-epilogue)
     ;; Load the return-pc.
     (move rax return-pc)
       (let ((not-single (gen-label)))
         (inst cmp nvals (fixnumize 1))
         (inst jmp :ne not-single)
-
         ;; Return with one value.
         (loadw a0 vals -1)
         ;; Clear the stack. We load old-fp into a register before clearing
index f4f0c29..a2b3302 100644 (file)
 ;;; Nvals is the number of values that are to be received (should
 ;;; equal the length of Values).
 ;;;
-;;; MOVE-TEMP is a DESCRIPTOR-REG TN used as a temporary.
-;;;
-;;; This code exploits the fact that in the unknown-values convention,
-;;; a single value return returns at the return PC + 2, whereas a
-;;; return of other than one value returns directly at the return PC.
-;;;
 ;;; If 0 or 1 values are expected, then we just emit an instruction to
 ;;; reset the SP (which will only be executed when other than 1 value
 ;;; is returned.)
   (cond
    ((<= nvals 1)
     (note-this-location vop :single-value-return)
-    (let ((single-value (gen-label)))
-      (cond
-       ((member :cmov *backend-subfeatures*)
-        (inst cmov :c esp-tn ebx-tn))
-       (t
-        (inst jmp :nc single-value)
-        (inst mov esp-tn ebx-tn)
-        (emit-label single-value)))))
+    (cond
+      ((member :cmov *backend-subfeatures*)
+       (inst cmov :c esp-tn ebx-tn))
+      (t
+       (let ((single-value (gen-label)))
+         (inst jmp :nc single-value)
+         (inst mov esp-tn ebx-tn)
+         (emit-label single-value)))))
    ((<= nvals register-arg-count)
     (let ((regs-defaulted (gen-label)))
       (note-this-location vop :unknown-return)
 \f
 ;;;; local call with unknown values convention return
 
+(defun check-ocfp-and-return-pc (old-fp return-pc)
+  #+nil
+  (format t "*known-return: old-fp ~S, tn-kind ~S; ~S ~S~%"
+          old-fp (sb!c::tn-kind old-fp) (sb!c::tn-save-tn old-fp)
+          (sb!c::tn-kind (sb!c::tn-save-tn old-fp)))
+  #+nil
+  (format t "*known-return: return-pc ~S, tn-kind ~S; ~S ~S~%"
+          return-pc (sb!c::tn-kind return-pc)
+          (sb!c::tn-save-tn return-pc)
+          (sb!c::tn-kind (sb!c::tn-save-tn return-pc)))
+  (unless (and (sc-is old-fp control-stack)
+               (= (tn-offset old-fp) ocfp-save-offset))
+    (error "ocfp not on stack in standard save location?"))
+  (unless (and (sc-is return-pc sap-stack)
+               (= (tn-offset return-pc) return-pc-save-offset))
+    (error "return-pc not on stack in standard save location?")))
+
 ;;; Non-TR local call for a fixed number of values passed according to
 ;;; the unknown values convention.
 ;;;
     (note-this-location vop :known-return)
     (trace-table-entry trace-table-normal)))
 \f
-;;; Return from known values call. We receive the return locations as
-;;; arguments to terminate their lifetimes in the returning function. We
-;;; restore FP and CSP and jump to the Return-PC.
-;;;
-;;; We can assume we know exactly where old-fp and return-pc are because
-;;; make-old-fp-save-location and make-return-pc-save-location always
-;;; return the same place.
-#+nil
-(define-vop (known-return)
-  (:args (old-fp)
-         (return-pc :scs (any-reg immediate-stack) :target rpc)
-         (vals :more t))
-  (:move-args :known-return)
-  (:info val-locs)
-  (:temporary (:sc unsigned-reg :from (:argument 1)) rpc)
-  (:ignore val-locs vals)
-  (:vop-var vop)
-  (:generator 6
-    (trace-table-entry trace-table-fun-epilogue)
-    ;; Save the return-pc in a register 'cause the frame-pointer is
-    ;; going away. Note this not in the usual stack location so we
-    ;; can't use RET
-    (move rpc return-pc)
-    ;; Restore the stack.
-    (move esp-tn ebp-tn)
-    ;; Restore the old fp. We know OLD-FP is going to be in its stack
-    ;; save slot, which is a different frame that than this one,
-    ;; so we don't have to worry about having just cleared
-    ;; most of the stack.
-    (move ebp-tn old-fp)
-    (inst jmp rpc)
-    (trace-table-entry trace-table-normal)))
-\f
 ;;; From Douglas Crosher
 ;;; Return from known values call. We receive the return locations as
 ;;; arguments to terminate their lifetimes in the returning function. We
 ;;; restore FP and CSP and jump to the Return-PC.
-;;;
-;;; The old-fp may be either in a register or on the stack in its
-;;; standard save locations - slot 0.
-;;;
-;;; The return-pc may be in a register or on the stack in any slot.
 (define-vop (known-return)
   (:args (old-fp)
          (return-pc)
   (:ignore val-locs vals)
   (:vop-var vop)
   (:generator 6
+    (check-ocfp-and-return-pc old-fp return-pc)
     (trace-table-entry trace-table-fun-epilogue)
-
-    #+nil (format t "*known-return: old-fp ~S, tn-kind ~S; ~S ~S~%"
-                  old-fp (sb!c::tn-kind old-fp) (sb!c::tn-save-tn old-fp)
-                  (sb!c::tn-kind (sb!c::tn-save-tn old-fp)))
-
-    #+nil (format t "*known-return: return-pc ~S, tn-kind ~S; ~S ~S~%"
-                  return-pc (sb!c::tn-kind return-pc)
-                  (sb!c::tn-save-tn return-pc)
-                  (sb!c::tn-kind (sb!c::tn-save-tn return-pc)))
-
-    ;; return-pc may be either in a register or on the stack.
-    (sc-case return-pc
-      ((sap-stack)
-       #+nil (format t "*known-return: return-pc ~S on stack; offset=~S~%"
-                     return-pc (tn-offset return-pc))
-       (unless (and (sc-is old-fp control-stack)
-                    (= (tn-offset old-fp) ocfp-save-offset))
-         (error "known-return: ocfp not on stack in standard save location?"))
-       (unless (and (sc-is return-pc sap-stack)
-                    (= (tn-offset return-pc) return-pc-save-offset))
-         (error
-          "known-return: return-pc not on stack in standard save location?"))
-
-       ;; Zot all of the stack except for the old-fp and return-pc.
-       (inst lea esp-tn
-             (make-ea :dword :base ebp-tn
-                      :disp (frame-byte-offset ocfp-save-offset)))
-       (inst pop ebp-tn)
-       (inst ret (* (tn-offset return-pc) n-word-bytes)))
-      (t
-       (error "known-return, return-pc not on stack")))
-
+    ;; Zot all of the stack except for the old-fp and return-pc.
+    (inst lea esp-tn
+          (make-ea :dword :base ebp-tn
+                   :disp (frame-byte-offset ocfp-save-offset)))
+    (inst pop ebp-tn)
+    (inst ret)
     (trace-table-entry trace-table-normal)))
 \f
 ;;;; full call
   (:args (args :scs (any-reg control-stack) :target esi)
          (function :scs (descriptor-reg control-stack) :target eax)
          (old-fp)
-         (ret-addr))
+         (return-pc))
   (:temporary (:sc unsigned-reg :offset esi-offset :from (:argument 0)) esi)
   (:temporary (:sc unsigned-reg :offset eax-offset :from (:argument 1)) eax)
-;  (:ignore ret-addr old-fp)
   (:generator 75
+    (check-ocfp-and-return-pc old-fp return-pc)
     ;; Move these into the passing locations if they are not already there.
     (move esi args)
     (move eax function)
-
-    ;; The following assumes that the return-pc and old-fp are on the
-    ;; stack in their standard save locations - Check this.
-    (unless (and (sc-is old-fp control-stack)
-                 (= (tn-offset old-fp) ocfp-save-offset))
-            (error "tail-call-variable: ocfp not on stack in standard save location?"))
-    (unless (and (sc-is ret-addr sap-stack)
-                 (= (tn-offset ret-addr) return-pc-save-offset))
-            (error "tail-call-variable: ret-addr not on stack in standard save location?"))
-
-
     ;; And jump to the assembly routine.
     (inst jmp (make-fixup 'tail-call-variable :assembly-routine))))
 \f
          (value))
   (:ignore value)
   (:generator 6
+    (check-ocfp-and-return-pc old-fp return-pc)
     (trace-table-entry trace-table-fun-epilogue)
-    ;; Code structure lifted from known-return.
-    (sc-case return-pc
-      ((sap-stack)
-       ;; Note that this will only work right if, when old-fp is on
-       ;; the stack, it has a lower tn-offset than return-pc. One of
-       ;; the comments in known-return indicate that this is the case
-       ;; (in that it will be in its save location), but we may wish
-       ;; to assert that (in either the weaker or stronger forms).
-       ;; Should this ever not be the case, we should load old-fp into
-       ;; a temp reg while we fix the stack.
-       (unless (and (sc-is old-fp control-stack)
-                    (= (tn-offset old-fp) ocfp-save-offset))
-         (error "ocfp not on stack in standard save location?"))
-       (unless (and (sc-is return-pc sap-stack)
-                    (= (tn-offset return-pc) return-pc-save-offset))
-         (error "return-pc not on stack in standard save location?"))
-       ;; Drop stack above old-fp
-       (inst lea esp-tn (make-ea :dword :base ebp-tn
-                                 :disp (frame-byte-offset (tn-offset old-fp))))
-       ;; Set single-value return flag
-       (inst clc)
-       ;; Restore the old frame pointer
-       (inst pop ebp-tn)
-       ;; And return, dropping the rest of the stack as we go.
-       (inst ret (* (tn-offset return-pc) n-word-bytes)))
-      (t
-       (error "return pc not on stack")))))
+    ;; Drop stack above old-fp
+    (inst lea esp-tn (make-ea :dword :base ebp-tn
+                              :disp (frame-byte-offset (tn-offset old-fp))))
+    ;; Clear the multiple-value return flag
+    (inst clc)
+    ;; Restore the old frame pointer
+    (inst pop ebp-tn)
+    ;; And return, dropping the rest of the stack as we go.
+    (inst ret)))
 
 ;;; Do unknown-values return of a fixed (other than 1) number of
 ;;; values. The VALUES are required to be set up in the standard
          (values :more t))
   (:ignore values)
   (:info nvals)
-
   ;; In the case of other than one value, we need these registers to
   ;; tell the caller where they are and how many there are.
   (:temporary (:sc unsigned-reg :offset ebx-offset) ebx)
   (:temporary (:sc unsigned-reg :offset ecx-offset) ecx)
-
   ;; We need to stretch the lifetime of return-pc past the argument
   ;; registers so that we can default the argument registers without
   ;; trashing return-pc.
                    :from :eval) a2)
 
   (:generator 6
-    (unless (and (sc-is old-fp control-stack)
-                 (= (tn-offset old-fp) ocfp-save-offset))
-      (error "ocfp not on stack in standard save location?"))
-    (unless (and (sc-is return-pc sap-stack)
-                 (= (tn-offset return-pc) return-pc-save-offset))
-      (error "return-pc not on stack in standard save location?"))
-
+    (check-ocfp-and-return-pc old-fp return-pc)
     (trace-table-entry trace-table-fun-epilogue)
     ;; Establish the values pointer and values count.
     (move ebx ebp-tn)
          (return-pc :target eax)
          (vals :scs (any-reg) :target esi)
          (nvals :scs (any-reg) :target ecx))
-
   (:temporary (:sc unsigned-reg :offset eax-offset :from (:argument 1)) eax)
   (:temporary (:sc unsigned-reg :offset esi-offset :from (:argument 2)) esi)
   (:temporary (:sc unsigned-reg :offset ecx-offset :from (:argument 3)) ecx)
                    :from (:eval 0)) a0)
   (:temporary (:sc unsigned-reg :from (:eval 1)) old-fp-temp)
   (:node-var node)
-
   (:generator 13
+    (check-ocfp-and-return-pc old-fp return-pc)
     (trace-table-entry trace-table-fun-epilogue)
     ;; Load the return-pc.
     (move eax return-pc)
       (let ((not-single (gen-label)))
         (inst cmp nvals (fixnumize 1))
         (inst jmp :ne not-single)
-
         ;; Return with one value.
         (loadw a0 vals -1)
         ;; Clear the stack. We load old-fp into a register before clearing
index 091d37f..cd41ba7 100644 (file)
@@ -17,4 +17,4 @@
 ;;; checkins which aren't released. (And occasionally for internal
 ;;; versions, especially for internal versions off the main CVS
 ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"1.0.27.11"
+"1.0.27.12"