#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): /* * Note [Adjustor templates live in data section] * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Some linkers (namely Apple's ld64 and some ld.lld configurations on Linux) do not allow relocations in the text section; in * principle this should be mitigated by only using local symbol references, as * described in Note [Adjustors: Local symbol references]. However, for reasons * that remain a mystery the assembler produces a relocations regardless. * To work around this we must declare this code to be data. This is okay since * we will never execute it here; it will always be copied to an executable * page first. */ #if defined(darwin_HOST_OS) .section __DATA,__data #else .section .data #endif /* * Note [Adjustors: Local symbol references] * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Some platforms (e.g. Darwin) don't allow relocations in text sections. However, * the assembler tends to produce relocations for references to a global symbols. * Consequently we must refer to RIP-relative things only via local symbols. */ /* ------------------------------------------------------------------ * Adjustor for a call with less than 6 integer arguments. * ------------------------------------------------------------------ */ DECLARE_CSYM(simple_ccall_adjustor) // Shuffle the argument registers down mov %r8, %r9 mov %rcx, %r8 mov %rdx, %rcx mov %rsi, %rdx mov %rdi, %rsi mov lcl_simple_ccall_adjustor_context(%rip), %rax // load the address of the context mov HPTR_OFF(%rax), %rdi // load the StablePtr jmp *WPTR_OFF(%rax) // jump to the entrypoint .align 8 DECLARE_CSYM(simple_ccall_adjustor_context) lcl_simple_ccall_adjustor_context: // See Note [Adjustors: Local symbol references] // this will be overwritten with a pointer to the AdjustorContext .quad 0 DECLARE_CSYM(simple_ccall_adjustor_end) /* ------------------------------------------------------------------ * Adjustor for a call with 6 or more integer arguments. * ------------------------------------------------------------------ */ DECLARE_CSYM(complex_ccall_adjustor) push %r9 pushq complex_ccall_ret_code_ptr(%rip) // Shuffle the argument registers down mov %r8, %r9 mov %rcx, %r8 mov %rdx, %rcx mov %rsi, %rdx mov %rdi, %rsi mov lcl_complex_ccall_adjustor_context(%rip), %rax // load the address of the context mov HPTR_OFF(%rax), %rdi // load the StablePtr jmpq *WPTR_OFF(%rax) // jump to the entrypoint .align 8 complex_ccall_ret_code_ptr: .quad complex_ccall_ret_code DECLARE_CSYM(complex_ccall_adjustor_context) lcl_complex_ccall_adjustor_context: // See Note [Adjustors: Local symbol references] // this will be overwritten with a pointer to the AdjustorContext .quad 0x0 DECLARE_CSYM(complex_ccall_adjustor_end) /* See Note [Adjustor templates live in data section]. */ #if defined(darwin_HOST_OS) .section __TEXT,__text #else .section .text #endif /* 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 ret /* mark stack as nonexecutable */ #if defined(__linux__) && defined(__ELF__) .section .note.GNU-stack,"",@progbits #endif