diff options
| author | Brian Anderson <banderson@mozilla.com> | 2011-11-30 14:24:54 -0800 |
|---|---|---|
| committer | Brian Anderson <banderson@mozilla.com> | 2011-11-30 20:31:32 -0800 |
| commit | 037ca7f7cb00c5eb2def4b766c01aac4c07a9fb4 (patch) | |
| tree | 1560ec50fa608feeb3e9fb5991de86bb880af040 /src/rt | |
| parent | fdebd1e2ef440312ac791d505af7dd089efa2499 (diff) | |
rt: Rewrite 32-bit __morestack to use the shim upcall
Diffstat (limited to 'src/rt')
| -rw-r--r-- | src/rt/arch/i386/morestack.S | 148 |
1 files changed, 63 insertions, 85 deletions
diff --git a/src/rt/arch/i386/morestack.S b/src/rt/arch/i386/morestack.S index f888373e5cf..d739f820422 100644 --- a/src/rt/arch/i386/morestack.S +++ b/src/rt/arch/i386/morestack.S @@ -6,42 +6,22 @@ // 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 RUST_GET_PREV_STACK _rust_get_prev_stack #define RUST_GET_TASK _rust_get_task -#define UPCALL_ALLOC_C_STACK _upcall_alloc_c_stack -#define UPCALL_CALL_C_STACK _upcall_call_c_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 RUST_GET_PREV_STACK rust_get_prev_stack #define RUST_GET_TASK rust_get_task -#define UPCALL_ALLOC_C_STACK upcall_alloc_c_stack -#define UPCALL_CALL_C_STACK upcall_call_c_stack +#define UPCALL_CALL_C upcall_call_shim_on_c_stack #define MORESTACK __morestack #endif -#ifdef __APPLE__ -#define ALIGNMENT 4 -#else -#define ALIGNMENT 8 -#endif - -#if defined (__APPLE__) -#define NEW_STACK_ADDR rust_new_stack_sym-.L$pic_ref_pt_0(%eax) -#define DEL_STACK_ADDR rust_del_stack_sym-.L$pic_ref_pt_1(%edx) -#else -#if defined (_WIN32) -#define NEW_STACK_ADDR $_rust_new_stack -#define DEL_STACK_ADDR $_rust_del_stack -#else -#define NEW_STACK_ADDR $rust_new_stack -#define DEL_STACK_ADDR $rust_del_stack -#endif -#endif - +#define ALIGNMENT 8 #define RETURN_OFFSET 7 .globl RUST_NEW_STACK @@ -68,68 +48,66 @@ #if defined(__linux__) MORESTACK: - // Sanity check to make sure that there is a currently-running task. - subl $12,%esp - calll RUST_GET_TASK - testl %eax,%eax - jz .L$bail - - movl $16, (%esp) - calll UPCALL_ALLOC_C_STACK - movl %eax,%edx - - movl %esp, 12(%edx) - // C stack | esp+12 - // ---------------------+------------------------- - movl 20(%esp),%eax // | ra stksz argsz x ra args - movl %eax,8(%edx) // argsz > | ra stksz argsz x ra args - leal 28+ALIGNMENT(%esp),%eax // argsz | ra stksz argsz x ra args - movl %eax,4(%edx) // argp > argsz | ra stksz argsz x ra args - movl 16(%esp),%eax // argp argsz | ra stksz argsz x ra args - movl %eax,(%edx) // stksz > argp argsz | ra stksz argsz x ra args - - calll .L$pic_ref_pt_0 -.L$pic_ref_pt_0: - popl %eax - - movl NEW_STACK_ADDR,%eax - movl %eax,(%esp) - movl %edx,4(%esp) - // FIXME: Don't understand why just _here_ I have to say @PLT - calll UPCALL_CALL_C_STACK@PLT - - movl 12(%esp),%edx // Grab the return pointer. - addl $RETURN_OFFSET,%edx // Skip past the `add esp,4` and the `ret`. - - movl %eax,%esp // Switch stacks. - calll *%edx // Re-enter the function that called us. - - // Now the function that called us has returned, so we need to delete the - // old stack space. - - calll RUST_GET_PREV_STACK - movl %eax,%esp // Switch back to the old stack. - - movl $0,(%esp) - calll UPCALL_ALLOC_C_STACK - - calll .L$pic_ref_pt_1 -.L$pic_ref_pt_1: - popl %edx - - movl DEL_STACK_ADDR,%edx - movl %edx,(%esp) - movl %eax,4(%esp) - calll UPCALL_CALL_C_STACK - - addl $12,%esp - retl $8 // ra stksz argsz x ra args + pushl %ebp + movl %esp, %ebp + + // FIXME (1226): main is compiled with the split-stack prologue, + // causing it to call __morestack, so we have to jump back out + subl $24,%esp + calll RUST_GET_TASK + testl %eax,%eax + jz .L$bail + + // The arguments to rust_new_stack2 + movl %esp, 20(%esp) // Save the stack pointer + movl 36(%esp),%eax // Size of stack arguments + movl %eax,16(%esp) + leal 44+ALIGNMENT(%esp),%eax // Address of stack arguments + movl %eax,12(%esp) + movl 32(%esp),%eax // The amount of stack needed + movl %eax,8(%esp) + + movl $RUST_NEW_STACK2,4(%esp) + leal 8(%esp), %eax + movl %eax,(%esp) + call UPCALL_CALL_C + + movl 28(%esp),%edx // Grab the return pointer. + addl $RETURN_OFFSET,%edx // Skip past the `add esp,4` and the `ret`. + + movl %eax,%esp // Switch stacks. + call *%edx // Re-enter the function that called us. + + // Now the function that called us has returned, so we need to delete the + // old stack space. + + // NB: This is assuming we already have at least 2 words + // pushed onto the C stack. This is always true because + // Rust functions have implicit arguments. + movl $RUST_GET_PREV_STACK,4(%esp) + movl $0, (%esp) + call UPCALL_CALL_C + + // Switch back to the rust stack + movl %eax, %esp + + movl $RUST_DEL_STACK,4(%esp) + movl $0, (%esp) + call UPCALL_CALL_C + + addl $24,%esp + popl %ebp + retl $8 .L$bail: - movl 12(%esp),%edx - addl $RETURN_OFFSET,%edx - addl $12+4+8+ALIGNMENT,%esp - jmpl *%edx + movl 28(%esp),%edx + addl $RETURN_OFFSET,%edx + + addl $24, %esp + popl %ebp + addl $4+8+ALIGNMENT,%esp + + jmpl *%edx #else |
