#include "include/ghcconfig.h" #define HPTR_OFF 0 #define WPTR_OFF 8 #if defined(LEADING_UNDERSCORE) #define CSYM(x) _ ## x #else #define CSYM(x) x #endif #define DECLARE_CSYM(x) \ .globl CSYM(x) ; \ CSYM(x): /* ------------------------------------------------------------------ * Adjustor for a call with less than 4 integer arguments. * ------------------------------------------------------------------ */ DECLARE_CSYM(simple_ccall_adjustor) // Shuffle the argument registers down mov %r8, %r9 mov %rdx, %r8 mov %rcx, %rdx movsd %xmm2, %xmm3 movsd %xmm1, %xmm2 movsd %xmm0, %xmm1 mov lcl_simple_ccall_adjustor_context(%rip), %rax // load the address of the context mov HPTR_OFF(%rax), %rcx // load the StablePtr jmp *WPTR_OFF(%rax) // jump to the entrypoint .align 8 DECLARE_CSYM(simple_ccall_adjustor_context) // See Note [Adjustors: Local symbol references] in NativeAmd64Asm.S lcl_simple_ccall_adjustor_context: // this will be overwritten with a pointer to the AdjustorContext .quad 0 DECLARE_CSYM(simple_ccall_adjustor_end) /* ------------------------------------------------------------------ * Adjustor for a call with 4 or more integer arguments and where the fourth * argument is not floating-point. * ------------------------------------------------------------------ */ DECLARE_CSYM(complex_nofloat_ccall_adjustor) sub $8,%rsp // Handle the fourth argument; this is the only difference between the // float/non-float cases mov %r9, 0x20(%rsp) // Push the new return address onto the stack pushq complex_nofloat_ccall_ret_code_ptr(%rip) // But the old return address has been moved up into a spill slot, so we // need to move it above them mov 0x10(%rsp), %r9 mov %r9, 0x30(%rsp) // Now do the normal argument shuffle mov %r8, %r9 mov %rdx, %r8 mov %rcx, %rdx movsd %xmm2, %xmm3 movsd %xmm1, %xmm2 movsd %xmm0, %xmm1 // Load the address of the context mov lcl_complex_nofloat_ccall_adjustor_context(%rip), %rax mov HPTR_OFF(%rax), %rcx jmpq *WPTR_OFF(%rax) .align 8 complex_nofloat_ccall_ret_code_ptr: .quad complex_ccall_ret_code DECLARE_CSYM(complex_nofloat_ccall_adjustor_context) // See Note [Adjustors: Local symbol references] in NativeAmd64Asm.S lcl_complex_nofloat_ccall_adjustor_context: // this will be overwritten with a pointer to the AdjustorContext .quad 0x0 DECLARE_CSYM(complex_nofloat_ccall_adjustor_end) /* ------------------------------------------------------------------ * Adjustor for a call with 4 or more integer arguments and where the fourth * argument is floating point. * ------------------------------------------------------------------ */ DECLARE_CSYM(complex_float_ccall_adjustor) sub $8,%rsp // Handle the fourth argument; this is the only difference between the // float/non-float cases movsd %xmm3,0x20(%rsp) // Push the new return address onto the stack pushq complex_float_ccall_ret_code_ptr(%rip) // But the old return address has been moved up into a spill slot, so we // need to move it above them mov 0x10(%rsp),%r9 mov %r9,0x30(%rsp) // Now do the normal argument shuffle mov %r8, %r9 mov %rdx, %r8 mov %rcx, %rdx movsd %xmm2, %xmm3 movsd %xmm1, %xmm2 movsd %xmm0, %xmm1 // Load the address of the context mov complex_float_ccall_adjustor_context(%rip), %rax mov HPTR_OFF(%rax), %rcx jmpq *WPTR_OFF(%rax) .align 8 complex_float_ccall_ret_code_ptr: .quad complex_ccall_ret_code DECLARE_CSYM(complex_float_ccall_adjustor_context) // See Note [Adjustors: Local symbol references] in NativeAmd64Asm.S lcl_complex_float_ccall_adjustor_context: // this will be overwritten with a pointer to the AdjustorContext .quad 0x0 DECLARE_CSYM(complex_float_ccall_adjustor_end) /* When generating an adjustor thunk that uses the C calling convention, we have to make sure that the thunk kicks off the process of jumping into Haskell with a tail jump. Why? Because as a result of jumping in into Haskell we may end up freeing the very adjustor thunk we came from using freeHaskellFunctionPtr(). Hence, we better not return to the adjustor code on our way out, since it could by then point to junk. The fix is readily at hand, just include the opcodes for the C stack fixup code that we need to perform when returning in some static piece of memory and arrange to return to it before tail jumping from the adjustor thunk. */ complex_ccall_ret_code: addq $0x8, %rsp /* On Win64, we had to put the original return address after the arg 1-4 spill slots, ro now we have to move it back */ movq 0x20(%rsp), %rcx movq %rcx, (%rsp) ret /* mark stack as nonexecutable */ #if defined(__linux__) && defined(__ELF__) .section .note.GNU-stack,"",@progbits #endif