0.9.13.36: global policy / null-lexenv confusion fix
[sbcl.git] / src / compiler / x86-64 / call.lisp
index 384155b..5488403 100644 (file)
   (cond
    ((<= nvals 1)
     (note-this-location vop :single-value-return)
-    (inst mov rsp-tn rbx-tn))
+    (inst cmov :c rsp-tn rbx-tn))
    ((<= nvals register-arg-count)
     (let ((regs-defaulted (gen-label)))
       (note-this-location vop :unknown-return)
-      (inst nop)
-      (inst jmp-short regs-defaulted)
+      (inst jmp :c regs-defaulted)
       ;; Default the unsupplied registers.
       (let* ((2nd-tn-ref (tn-ref-across values))
              (2nd-tn (tn-ref-tn 2nd-tn-ref)))
           (default-stack-slots (gen-label)))
       (note-this-location vop :unknown-return)
       ;; Branch off to the MV case.
-      (inst nop)
-      (inst jmp-short regs-defaulted)
+      (inst jmp :c regs-defaulted)
       ;; Do the single value case.
       ;; Default the register args
       (inst mov rax-tn nil-value)
   (declare (type tn args nargs start count))
   (let ((variable-values (gen-label))
         (done (gen-label)))
-    (inst nop)
-    (inst jmp-short variable-values)
+    (inst jmp :c variable-values)
 
     (cond ((location= start (first *register-arg-tns*))
            (inst push (first *register-arg-tns*))
   (:args (old-fp)
          (return-pc)
          (value))
-  (:temporary (:sc unsigned-reg) ofp)
-  (:temporary (:sc unsigned-reg) ret)
   (:ignore value)
   (:generator 6
     (trace-table-entry trace-table-fun-epilogue)
-    (move ret return-pc)
-    ;; Clear the control stack
-    (move ofp old-fp)
-    ;; Adjust the return address for the single value return.
-    (inst add ret 3)
-    ;; Restore the frame pointer.
-    (move rsp-tn rbp-tn)
-    (move rbp-tn ofp)
-    ;; Out of here.
-    (inst jmp ret)))
+    ;; Code structure lifted from known-return.
+    (sc-case return-pc
+      ((sap-reg)
+       ;; return PC in register for some reason (local call?)
+       ;; we jmp to the return pc after fixing the stack and frame.
+       (sc-case old-fp
+         ((control-stack)
+          ;; ofp on stack must be in slot 0 (the traditional storage place).
+          ;; Drop the stack above it and pop it off.
+          (cond ((zerop (tn-offset old-fp))
+                 (inst lea rsp-tn (make-ea :dword :base rbp-tn
+                                           :disp (- (* (1+ ocfp-save-offset)
+                                                       n-word-bytes))))
+                 (inst pop rbp-tn))
+                (t
+                 ;; Should this ever happen, we do the same as above, but
+                 ;; using (tn-offset old-fp) instead of ocfp-save-offset
+                 ;; (which is 0 anyway, see src/compiler/x86/vm.lisp) and
+                 ;; then lea rsp again against itself with a displacement
+                 ;; of (* (tn-offset old-fp) n-word-bytes) to clear the
+                 ;; rest of the stack.
+                 (cerror "Continue anyway"
+                         "VOP return-single doesn't work if old-fp (in slot ~S) is not in slot 0" (tn-offset old-fp)))))
+         ((any-reg descriptor-reg)
+          ;; ofp in reg, drop the stack and load the real fp.
+          (move rsp-tn rbp-tn)
+          (move rbp-tn old-fp)))
+
+       ;; Set single-value-return flag
+       (inst clc)
+       ;; And return
+       (inst jmp 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.
+       ;; Drop stack above return-pc
+       (inst lea rsp-tn (make-ea :dword :base rbp-tn
+                                 :disp (- (* (1+ (tn-offset return-pc))
+                                             n-word-bytes))))
+       ;; Set single-value return flag
+       (inst clc)
+       ;; Restore the old frame pointer
+       (move rbp-tn old-fp)
+       ;; And return, dropping the rest of the stack as we go.
+       (inst ret (* (tn-offset return-pc) n-word-bytes))))))
 
 ;;; Do unknown-values return of a fixed (other than 1) number of
 ;;; values. The VALUES are required to be set up in the standard
         (inst mov first nil-value)
         (dolist (tn (cdr arg-tns))
           (inst mov tn first))))
+    ;; Set the multiple value return flag.
+    (inst stc)
     ;; And away we go. Except that return-pc is still on the
     ;; stack and we've changed the stack pointer. So we have to
     ;; tell it to index off of RBX instead of RBP.
         (move old-fp-temp old-fp)
         (move rsp-tn rbp-tn)
         (move rbp-tn old-fp-temp)
-        ;; Fix the return-pc to point at the single-value entry point.
-        (inst add rax 3) ; skip "mov %rbx,%rsp" insn in caller
+        ;; clear the multiple-value return flag
+        (inst clc)
         ;; Out of here.
         (inst jmp rax)