From c9003d301f602cb44d8cc3fd464c95b09e08548e Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 31 Oct 2011 13:31:04 -0700 Subject: [PATCH] Stub a __morestack implementation and stack segment allocation. Untested. --- mk/rt.mk | 3 ++- mk/rustllvm.mk | 5 +++++ src/rt/arch/i386/morestack.S | 38 ++++++++++++++++++++++++++++++++++++ src/rt/rust_task.cpp | 26 ++++++++++++++++++++++++ src/rt/rust_task.h | 7 ++++++- 5 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 src/rt/arch/i386/morestack.S diff --git a/mk/rt.mk b/mk/rt.mk index 07d1879efc2..8d096558923 100644 --- a/mk/rt.mk +++ b/mk/rt.mk @@ -38,7 +38,8 @@ RUNTIME_CS := rt/sync/timer.cpp \ RUNTIME_LL := RUNTIME_S := rt/arch/i386/_context.S \ - rt/arch/i386/ccall.S + rt/arch/i386/ccall.S \ + rt/arch/i386/morestack.S RUNTIME_HDR := rt/globals.h \ rt/rust.h \ diff --git a/mk/rustllvm.mk b/mk/rustllvm.mk index d8f9dd2ce52..7df9e3366e0 100644 --- a/mk/rustllvm.mk +++ b/mk/rustllvm.mk @@ -5,6 +5,11 @@ RUSTLLVM_OBJS_CS := $(addprefix rustllvm/, RustGCMetadataPrinter.cpp \ RustGCStrategy.cpp RustWrapper.cpp) +# Behind an ifdef for now since this requires a patched LLVM. +ifdef CFG_STACK_GROWTH +RUSTLLVM_OBJS_CS += rustllvm/RustPrologHook.cpp +endif + RUSTLLVM_DEF := rustllvm/rustllvm$(CFG_DEF_SUFFIX) RUSTLLVM_INCS := -iquote $(CFG_LLVM_INCDIR) \ diff --git a/src/rt/arch/i386/morestack.S b/src/rt/arch/i386/morestack.S new file mode 100644 index 00000000000..23492637fdb --- /dev/null +++ b/src/rt/arch/i386/morestack.S @@ -0,0 +1,38 @@ + .text + +// __morestack +// +// LLVM generates a call to this to allocate more stack space in a functiono +// prolog when we run out. + +#if defined(__APPLE__) || defined(_WIN32) +#define RUST_NEW_STACK _rust_new_stack +#define RUST_DEL_STACK _rust_del_stack +#else +#define RUST_NEW_STACK rust_new_stack +#define RUST_DEL_STACK rust_del_stack +#endif + +.globl RUST_NEW_STACK +.globl RUST_DEL_STACK + +.globl __morestack + +__morestack: + pushl %edx // param 2: size of arguments + leal 8(%esp),%eax + pushl %eax // param 1: starting addr of arguments + pushl %ecx // param 0: amount of space needed + calll RUST_NEW_STACK + + movl (%esp),%edx // Grab the return pointer. + incl %edx // Skip past the `ret`. + movl %eax,%esp // Switch to the new stack. + calll *%edx // Enter the new function. + + // Now the function that called us has returned, so we need to delete the + // old stack space. + calll RUST_DEL_STACK + movl %eax,%esp // Switch back to the old stack. + retl + diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp index 17faeec1a1c..5043f9ec4b0 100644 --- a/src/rt/rust_task.cpp +++ b/src/rt/rust_task.cpp @@ -8,6 +8,8 @@ #ifndef __WIN32__ #include #endif +#include +#include #include "globals.h" @@ -36,22 +38,46 @@ new_stk(rust_scheduler *sched, rust_task *task, size_t minsz) stk_seg *stk = (stk_seg *)task->malloc(sz, "stack"); LOGPTR(task->sched, "new stk", (uintptr_t)stk); memset(stk, 0, sizeof(stk_seg)); + stk->next = task->stk; stk->limit = (uintptr_t) &stk->data[minsz]; LOGPTR(task->sched, "stk limit", stk->limit); stk->valgrind_id = VALGRIND_STACK_REGISTER(&stk->data[0], &stk->data[minsz]); + task->stk = stk; return stk; } static void del_stk(rust_task *task, stk_seg *stk) { + assert(stk == task->stk && "Freeing stack segments out of order!"); + + task->stk = stk->next; + VALGRIND_STACK_DEREGISTER(stk->valgrind_id); LOGPTR(task->sched, "freeing stk segment", (uintptr_t)stk); task->free(stk); } +// Entry points for `__morestack` (see arch/*/morestack.S). +extern "C" void * +rust_new_stack(size_t stk_sz, void *args_addr, size_t args_sz) { + rust_task *task = rust_scheduler::get_task(); + stk_seg *stk_seg = new_stk(task->sched, task, stk_sz); + memcpy(stk_seg->data, args_addr, args_sz); + return stk_seg->data; +} + +extern "C" void * +rust_del_stack() { + rust_task *task = rust_scheduler::get_task(); + stk_seg *next_seg = task->stk->next; + del_stk(task, task->stk); + return next_seg->data; +} + + // Tasks rust_task::rust_task(rust_scheduler *sched, rust_task_list *state, rust_task *spawner, const char *name) : diff --git a/src/rt/rust_task.h b/src/rt/rust_task.h index fe19e06e657..783d46eaced 100644 --- a/src/rt/rust_task.h +++ b/src/rt/rust_task.h @@ -24,8 +24,13 @@ struct chan_handle { struct rust_box; struct stk_seg { - unsigned int valgrind_id; + stk_seg *next; uintptr_t limit; + unsigned int valgrind_id; +#ifndef _LP64 + uint32_t pad; +#endif + uint8_t data[]; };