diff options
| author | Graydon Hoare <[email protected]> | 2011-02-22 16:37:01 -0800 |
|---|---|---|
| committer | Graydon Hoare <[email protected]> | 2011-02-22 16:37:27 -0800 |
| commit | af4d6ae76b05d4edb9d7074b971600a447c9c9a4 (patch) | |
| tree | 20b65962db38b2c2cddd0eea9ba7563584fec0d0 /src/rt | |
| parent | Rework typechecking of bind expressions (diff) | |
| download | rust-af4d6ae76b05d4edb9d7074b971600a447c9c9a4.tar.xz rust-af4d6ae76b05d4edb9d7074b971600a447c9c9a4.zip | |
Add ABI tagging to crates, adjust rustc output and runtime stack-frame setup so access to argv works.
Diffstat (limited to 'src/rt')
| -rw-r--r-- | src/rt/rust.cpp | 8 | ||||
| -rw-r--r-- | src/rt/rust_internal.h | 6 | ||||
| -rw-r--r-- | src/rt/rust_task.cpp | 52 | ||||
| -rw-r--r-- | src/rt/rust_task.h | 1 | ||||
| -rw-r--r-- | src/rt/rust_upcall.cpp | 11 | ||||
| -rw-r--r-- | src/rt/test/rust_test_runtime.cpp | 1 |
6 files changed, 55 insertions, 24 deletions
diff --git a/src/rt/rust.cpp b/src/rt/rust.cpp index 0ea167a4..46fcb22e 100644 --- a/src/rt/rust.cpp +++ b/src/rt/rust.cpp @@ -78,7 +78,7 @@ command_line_args : public dom_owned<command_line_args> extern "C" CDECL int rust_start(uintptr_t main_fn, rust_crate const *crate, int argc, - char **argv) { + char **argv) { rust_srv *srv = new rust_srv(); rust_kernel *kernel = new rust_kernel(srv); @@ -87,7 +87,8 @@ rust_start(uintptr_t main_fn, rust_crate const *crate, int argc, rust_dom *dom = handle->referent(); command_line_args *args = new (dom) command_line_args(dom, argc, argv); - dom->log(rust_log::DOM, "startup: %d args", args->argc); + dom->log(rust_log::DOM, "startup: %d args in 0x%" PRIxPTR, + args->argc, (uintptr_t)args->args); for (int i = 0; i < args->argc; i++) { dom->log(rust_log::DOM, "startup: arg[%d] = '%s'", i, args->argv[i]); @@ -99,7 +100,8 @@ rust_start(uintptr_t main_fn, rust_crate const *crate, int argc, uintptr_t main_args[4] = {0, 0, 0, (uintptr_t)args->args}; dom->root_task->start(crate->get_exit_task_glue(), - main_fn, (uintptr_t)&main_args, sizeof(main_args)); + crate->abi_tag, main_fn, + (uintptr_t)&main_args, sizeof(main_args)); int ret = dom->start_main_loop(); delete args; kernel->destroy_domain(dom); diff --git a/src/rt/rust_internal.h b/src/rt/rust_internal.h index 61716703..42b61801 100644 --- a/src/rt/rust_internal.h +++ b/src/rt/rust_internal.h @@ -88,6 +88,10 @@ static size_t const TIME_SLICE_IN_MS = 10; static intptr_t const CONST_REFCOUNT = 0x7badface; +// ABI tags for rust_start, rust_task::start and friends. +static uintptr_t const ABI_X86_RUSTBOOT_CDECL = 1; +static uintptr_t const ABI_X86_RUSTC_FASTCALL = 2; + // This accounts for logging buffers. static size_t const BUF_BYTES = 2048; @@ -241,6 +245,8 @@ public: size_t n_c_syms; size_t n_libs; + uintptr_t abi_tag; + // Crates are immutable, constructed by the compiler. uintptr_t get_image_base() const; diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp index 3564b9e3..1afbfdd6 100644 --- a/src/rt/rust_task.cpp +++ b/src/rt/rust_task.cpp @@ -123,6 +123,7 @@ rust_task::~rust_task() void rust_task::start(uintptr_t exit_task_glue, + uintptr_t spawnee_abi, uintptr_t spawnee_fn, uintptr_t args, size_t callsz) @@ -147,26 +148,29 @@ rust_task::start(uintptr_t exit_task_glue, // The exit_task_glue frame we synthesize above the frame we activate: *spp-- = (uintptr_t) 0; // closure-or-obj *spp-- = (uintptr_t) this; // task - *spp-- = (uintptr_t) 0; // output - *spp-- = (uintptr_t) 0; // retpc + *spp-- = (uintptr_t) 0x0; // output + *spp-- = (uintptr_t) 0x0; // retpc uintptr_t exit_task_frame_base; - for (size_t j = 0; j < n_callee_saves; ++j) { + if (spawnee_abi == ABI_X86_RUSTBOOT_CDECL) { + for (size_t j = 0; j < n_callee_saves; ++j) { - // We want 'frame_base' to point to the old fp in this (exit-task) - // frame, because we're going to inject this frame-pointer into the - // callee-save frame pointer value in the *next* (spawnee) frame. A - // cheap trick, but this means the spawnee frame will restore the - // proper frame pointer of the glue frame as it runs its epilogue. - if (j == callee_save_fp) - exit_task_frame_base = (uintptr_t)spp; + // We want 'frame_base' to point to the old fp in this (exit-task) + // frame, because we're going to inject this frame-pointer into + // the callee-save frame pointer value in the *next* (spawnee) + // frame. A cheap trick, but this means the spawnee frame will + // restore the proper frame pointer of the glue frame as it runs + // its epilogue. + if (j == callee_save_fp) + exit_task_frame_base = (uintptr_t)spp; - *spp-- = 0; - } + *spp-- = 0; + } - *spp-- = (uintptr_t) dom->root_crate; // crate ptr - *spp-- = (uintptr_t) 0; // frame_glue_fns + *spp-- = (uintptr_t) dom->root_crate; // crate ptr + *spp-- = (uintptr_t) 0; // frame_glue_fns + } // Copy args from spawner to spawnee. if (args) { @@ -174,12 +178,16 @@ rust_task::start(uintptr_t exit_task_glue, src += 1; // spawn-call output slot src += 1; // spawn-call task slot src += 1; // spawn-call closure-or-obj slot + + // Undo previous sp-- so we're pointing at the last word pushed. + ++spp; + // Memcpy all but the task, output and env pointers callsz -= (3 * sizeof(uintptr_t)); spp = (uintptr_t*) (((uintptr_t)spp) - callsz); memcpy(spp, src, callsz); - // Move sp down to point to task cell. + // Move sp down to point to last implicit-arg cell (env). spp--; } else { // We're at root, starting up. @@ -188,10 +196,18 @@ rust_task::start(uintptr_t exit_task_glue, // The *implicit* incoming args to the spawnee frame we're // activating: + *spp-- = (uintptr_t) 0x0; // closure-or-obj + + if (spawnee_abi == ABI_X86_RUSTBOOT_CDECL) { + // in CDECL mode we write the task + outptr to the spawnee stack. + *spp-- = (uintptr_t) this; // task + *spp-- = (uintptr_t) 0; // output addr + } else { + // in FASTCALL mode we don't, the outptr will be in ecx and the task + // in edx, and the activate_glue will make sure to set that up. + I(dom, spawnee_abi == ABI_X86_RUSTC_FASTCALL); + } - *spp-- = (uintptr_t) 0; // closure-or-obj - *spp-- = (uintptr_t) this; // task - *spp-- = (uintptr_t) 0; // output addr *spp-- = (uintptr_t) exit_task_glue; // retpc // The context the activate_glue needs to switch stack. diff --git a/src/rt/rust_task.h b/src/rt/rust_task.h index 9fbc67ac..5318ab71 100644 --- a/src/rt/rust_task.h +++ b/src/rt/rust_task.h @@ -56,6 +56,7 @@ rust_task : public maybe_proxy<rust_task>, ~rust_task(); void start(uintptr_t exit_task_glue, + uintptr_t spawnee_abi, uintptr_t spawnee_fn, uintptr_t args, size_t callsz); diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index 46e53048..1dba1102 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -559,6 +559,7 @@ extern "C" CDECL rust_task * upcall_start_task(rust_task *spawner, rust_task *task, uintptr_t exit_task_glue, + uintptr_t spawnee_abi, uintptr_t spawnee_fn, size_t callsz) { LOG_UPCALL_ENTRY(spawner); @@ -570,7 +571,8 @@ upcall_start_task(rust_task *spawner, ", spawnee 0x%" PRIxPTR ", callsz %" PRIdPTR ")", task->name, task, exit_task_glue, spawnee_fn, callsz); - task->start(exit_task_glue, spawnee_fn, spawner->rust_sp, callsz); + task->start(exit_task_glue, spawnee_abi, spawnee_fn, + spawner->rust_sp, callsz); return task; } @@ -623,6 +625,7 @@ extern "C" CDECL maybe_proxy<rust_task> * upcall_start_thread(rust_task *task, rust_proxy<rust_task> *child_task_proxy, uintptr_t exit_task_glue, + uintptr_t spawnee_abi, uintptr_t spawnee_fn, size_t callsz) { LOG_UPCALL_ENTRY(task); @@ -630,9 +633,11 @@ upcall_start_thread(rust_task *task, rust_handle<rust_task> *child_task_handle = child_task_proxy->handle(); task->log(rust_log::UPCALL | rust_log::MEM | rust_log::TASK, "exit_task_glue: " PTR ", spawnee_fn " PTR - ", callsz %" PRIdPTR ")", exit_task_glue, spawnee_fn, callsz); + ", callsz %" PRIdPTR ")", + exit_task_glue, spawnee_fn, callsz); rust_task *child_task = child_task_handle->referent(); - child_task->start(exit_task_glue, spawnee_fn, task->rust_sp, callsz); + child_task->start(exit_task_glue, spawnee_abi, spawnee_fn, + task->rust_sp, callsz); #if defined(__WIN32__) HANDLE thread; thread = CreateThread(NULL, 0, rust_thread_start, child_task->dom, 0, diff --git a/src/rt/test/rust_test_runtime.cpp b/src/rt/test/rust_test_runtime.cpp index 1cde532e..e0e24156 100644 --- a/src/rt/test/rust_test_runtime.cpp +++ b/src/rt/test/rust_test_runtime.cpp @@ -54,6 +54,7 @@ rust_task_test::worker::run() { kernel->create_domain(crate, "test"); rust_dom *domain = handle->referent(); domain->root_task->start(crate->get_exit_task_glue(), + ABI_X86_RUSTBOOT_CDECL, (uintptr_t)&task_entry, (uintptr_t)NULL, 0); domain->start_main_loop(); kernel->destroy_domain(domain); |