(mach-port-name :c-type "mach_port_name_t")
(nonpointer-data :c-type "struct nonpointer_thread_data *" :length #!+alpha 2 #!-alpha 1)
#!+(and sb-safepoint x86) (selfptr :c-type "struct thread *")
+ ;; Context base pointer for running on top of system libraries built using
+ ;; -fomit-frame-pointer. Currently truly required and implemented only
+ ;; for (and win32 x86-64), but could be generalized to other platforms if
+ ;; needed:
+ #!+win32 (carried-base-pointer :c-type "os_context_register_t")
#!+sb-safepoint (csp-around-foreign-call :c-type "lispobj *")
#!+sb-safepoint (pc-around-foreign-call :c-type "lispobj *")
#!+win32 (synchronous-io-handle-and-flag :c-type "HANDLE" :length 1)
if (!th)
lose("callback invoked in non-lisp thread. Sorry, that is not supported yet.");
+#ifdef LISP_FEATURE_WIN32
+ /* arg2 is the pointer to a return value, which sits on the stack */
+ th->carried_base_pointer = (os_context_register_t) *(((void**)arg2)-1);
+#endif
+
WITH_GC_AT_SAFEPOINTS_ONLY()
funcall3(SymbolValue(ENTER_ALIEN_CALLBACK, 0), arg0, arg1, arg2);
}
th->os_thread=0;
#ifdef LISP_FEATURE_SB_SAFEPOINT
+# ifdef LISP_FEATURE_WIN32
+ th->carried_base_pointer = 0;
+# endif
+# ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
th->pc_around_foreign_call = 0;
+# endif
th->csp_around_foreign_call = csp_page;
#endif
context.sigmask = self ? self->os_thread->blocked_signal_set : 0;
#endif
+ os_context_register_t oldbp = NULL;
+ if (self) {
+ oldbp = self ? self->carried_base_pointer : 0;
+ self->carried_base_pointer
+ = (os_context_register_t) voidreg(win32_context, bp);
+ }
+
/* For EXCEPTION_ACCESS_VIOLATION only. */
void *fault_address = (void *)exception_record->ExceptionInformation[1];
/* All else failed, drop through to the lisp-side exception handler. */
signal_internal_error_or_lose(ctx, exception_record, fault_address);
+ if (self)
+ self->carried_base_pointer = oldbp;
+
errno = lastErrno;
SetLastError(lastError);
return ExceptionContinueExecution;
}
#endif
+os_context_register_t
+carry_frame_pointer(os_context_register_t default_value)
+{
+ struct thread* self = arch_os_get_current_thread();
+ os_context_register_t bp = self->carried_base_pointer;
+ return bp ? bp : default_value;
+}
+
void
wos_install_interrupt_handlers(struct lisp_exception_frame *handler)
{
* return values in rax rdx
* callee saves rbp rbx r12-15 if it uses them
*/
-
+#ifdef LISP_FEATURE_WIN32
+# define SUPPORT_FOMIT_FRAME_POINTER
+#endif
.align align_16byte,0x90
GNAME(call_into_lisp):
+#ifdef SUPPORT_FOMIT_FRAME_POINTER
+ mov %rbp,%rax
+#endif
push %rbp # Save old frame pointer.
mov %rsp,%rbp # Establish new frame.
Lstack:
+#ifdef SUPPORT_FOMIT_FRAME_POINTER
+ /* If called through call_into_lisp_first_time, %r15 becomes invalid
+ * here, but we will not return in that case. */
+ push %r15
+ mov %rax,%r15
+#endif
/* FIXME x86 saves FPU state here */
push %rbx # these regs are callee-saved according to C
push %r12 # so must be preserved and restored when
push %rsi #
push %rdx #
#ifdef LISP_FEATURE_SB_THREAD
+# ifdef SUPPORT_FOMIT_FRAME_POINTER
+ mov (%rbp),%rcx
+ sub $32,%rsp
+ call GNAME(carry_frame_pointer)
+ add $32,%rsp
+ mov %rax,(%rbp)
+# endif
#ifdef LISP_FEATURE_GCC_TLS
movq %fs:0, %rax
movq GNAME(current_thread)@TPOFF(%rax), %r12
/* FIXME Restore the NPX state. */
mov %rdx,%rax # c-val
+#ifdef SUPPORT_FOMIT_FRAME_POINTER
+ mov %r15,%rbp # orig rbp
+ pop %r15 # orig r15
+ add $8,%rsp # no need for saved (overridden) rbp
+#else
leave
+#endif
ret
SIZE(GNAME(call_into_lisp))
\f