From cd75c9ce11672f360c6e430e824823a4d265c85b Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 28 Nov 2011 16:25:45 -0800 Subject: [PATCH] rt: Implement part of the 64-bit __morestack --- src/rt/arch/x86_64/morestack.S | 64 +++++++++++++++++++++++----------- src/rt/rust_task.cpp | 15 ++++++++ 2 files changed, 58 insertions(+), 21 deletions(-) diff --git a/src/rt/arch/x86_64/morestack.S b/src/rt/arch/x86_64/morestack.S index b8cc4c2b9c4b..1e51a3167c6e 100644 --- a/src/rt/arch/x86_64/morestack.S +++ b/src/rt/arch/x86_64/morestack.S @@ -6,12 +6,14 @@ // prolog when we run out. #if defined(__APPLE__) || defined(_WIN32) -#define RUST_NEW_STACK _rust_new_stack +#define RUST_NEW_STACK2 _rust_new_stack2 #define RUST_DEL_STACK _rust_del_stack +#define UPCALL_CALL_C _upcall_call_shim_on_c_stack #define MORESTACK ___morestack #else -#define RUST_NEW_STACK rust_new_stack +#define RUST_NEW_STACK2 rust_new_stack2 #define RUST_DEL_STACK rust_del_stack +#define UPCALL_CALL_C upcall_call_shim_on_c_stack #define MORESTACK __morestack #endif @@ -28,31 +30,51 @@ # define ARG2 %rdx #endif -.globl RUST_NEW_STACK +.globl RUST_NEW_STACK2 .globl RUST_DEL_STACK - +.globl UPCALL_CALL_C .globl MORESTACK -MORESTACK: - // Hastily and probably incorrectly ported from i386 version. - // Actually this calling convention doens't make so much sense - // for x86_64... - mov %rcx, ARG0 // param 0: amount of space needed - mov %rdx, ARG2 // param 2: size of arguments - lea 8(%rsp),ARG1 - call rust_new_stack_sym +#ifdef __ELF__ + .type MORESTACK,@function +#endif +MORESTACK: + .cfi_startproc + + # Set up a normal backtrace + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp + + // Save argument registers + pushq %rdi + pushq %rsi + pushq %rdx + pushq %rcx + pushq %r8 + pushq %r9 + + // Calculate the address of the stack arguments + movq %rbp, %rcx + addq $16, %rcx // Add the saved %rbp, and return address + addq %r11, %rcx // Add the size of stack arguments + + pushq %r10 // The amount of stack needed + pushq %rcx // Address of stack arguments + pushq %r11 // Size of stack arguments + pushq %rbp // Save the Rust stack pointer + + // FIXME: Don't understand why I have to use the PLT here + lea RUST_NEW_STACK2@PLT(%rip), %rsi + lea 24(%rsp), %rdi + call UPCALL_CALL_C@PLT + mov (%rsp),%rdx // Grab the return pointer. inc %rdx // Skip past the `ret`. mov %rax,%rsp // Switch to the new stack. call *%rdx // Enter the new function. - // Now the function that called us has returned, so we need to delete the - // old stack space. - call rust_new_stack_sym - mov %rax,%rsp // Switch back to the old stack. - ret - -// This is totally broken -rust_new_stack_sym: -rust_del_stack_sym: \ No newline at end of file + .cfi_endproc \ No newline at end of file diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp index 30489b1d6692..3933692f0155 100644 --- a/src/rt/rust_task.cpp +++ b/src/rt/rust_task.cpp @@ -86,6 +86,21 @@ rust_new_stack(size_t stk_sz, void *args_addr, size_t args_sz, return new_sp; } +struct rust_new_stack2_args { + size_t stk_sz; + void *args_addr; + size_t args_sz; + uintptr_t current_sp; +}; + +// A new stack function suitable for calling through +// upcall_call_shim_on_c_stack +extern "C" void * +rust_new_stack2(struct rust_new_stack2_args *args) { + return rust_new_stack(args->stk_sz, args->args_addr, + args->args_sz, args->current_sp); +} + extern "C" void rust_del_stack() { rust_task *task = rust_scheduler::get_task();