aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGraydon Hoare <[email protected]>2011-02-22 16:37:01 -0800
committerGraydon Hoare <[email protected]>2011-02-22 16:37:27 -0800
commitaf4d6ae76b05d4edb9d7074b971600a447c9c9a4 (patch)
tree20b65962db38b2c2cddd0eea9ba7563584fec0d0 /src
parentRework typechecking of bind expressions (diff)
downloadrust-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')
-rw-r--r--src/boot/be/abi.ml34
-rw-r--r--src/boot/be/x86.ml2
-rw-r--r--src/boot/me/trans.ml4
-rw-r--r--src/comp/back/abi.rs3
-rw-r--r--src/comp/back/x86.rs4
-rw-r--r--src/comp/middle/trans.rs13
-rw-r--r--src/rt/rust.cpp8
-rw-r--r--src/rt/rust_internal.h6
-rw-r--r--src/rt/rust_task.cpp52
-rw-r--r--src/rt/rust_task.h1
-rw-r--r--src/rt/rust_upcall.cpp11
-rw-r--r--src/rt/test/rust_test_runtime.cpp1
12 files changed, 97 insertions, 42 deletions
diff --git a/src/boot/be/abi.ml b/src/boot/be/abi.ml
index 035d1f05..89e308bf 100644
--- a/src/boot/be/abi.ml
+++ b/src/boot/be/abi.ml
@@ -110,23 +110,33 @@ let indirect_args_elt_closure = 0;;
(* Current worst case is by vec grow glue *)
let worst_case_glue_call_args = 8;;
+(*
+ * ABI tags used to inform the runtime which sort of frame to set up for new
+ * spawned functions. FIXME: There is almost certainly a better abstraction to
+ * use.
+ *)
+let abi_x86_rustboot_cdecl = 1;;
+let abi_x86_rustc_fastcall = 2;;
+
type abi =
- {
- abi_word_sz: int64;
- abi_word_bits: Il.bits;
- abi_word_ty: Common.ty_mach;
+ {
+ abi_word_sz: int64;
+ abi_word_bits: Il.bits;
+ abi_word_ty: Common.ty_mach;
+
+ abi_tag: int;
- abi_has_pcrel_data: bool;
- abi_has_pcrel_code: bool;
+ abi_has_pcrel_data: bool;
+ abi_has_pcrel_code: bool;
- abi_n_hardregs: int;
- abi_str_of_hardreg: (int -> string);
+ abi_n_hardregs: int;
+ abi_str_of_hardreg: (int -> string);
- abi_emit_target_specific: (Il.emitter -> Il.quad -> unit);
- abi_constrain_vregs: (Il.quad -> (Il.vreg,Bits.t) Hashtbl.t -> unit);
+ abi_emit_target_specific: (Il.emitter -> Il.quad -> unit);
+ abi_constrain_vregs: (Il.quad -> (Il.vreg,Bits.t) Hashtbl.t -> unit);
- abi_emit_fn_prologue: (Il.emitter
- -> Common.size (* framesz *)
+ abi_emit_fn_prologue: (Il.emitter
+ -> Common.size (* framesz *)
-> Common.size (* callsz *)
-> Common.nabi
-> Common.fixup (* grow_task *)
diff --git a/src/boot/be/x86.ml b/src/boot/be/x86.ml
index 30b49ed1..49b660be 100644
--- a/src/boot/be/x86.ml
+++ b/src/boot/be/x86.ml
@@ -1851,6 +1851,8 @@ let (abi:Abi.abi) =
Abi.abi_word_bits = word_bits;
Abi.abi_word_ty = word_ty;
+ Abi.abi_tag = Abi.abi_x86_rustboot_cdecl;
+
Abi.abi_has_pcrel_data = false;
Abi.abi_has_pcrel_code = true;
diff --git a/src/boot/me/trans.ml b/src/boot/me/trans.ml
index 4f717219..bbf49e83 100644
--- a/src/boot/me/trans.ml
+++ b/src/boot/me/trans.ml
@@ -2727,6 +2727,7 @@ let trans_visitor
[|
Il.Cell new_task;
exit_task_glue_fptr;
+ (imm (Int64.of_int abi.Abi.abi_tag));
fptr_operand;
callsz
|];
@@ -2739,6 +2740,7 @@ let trans_visitor
[|
Il.Cell new_task;
exit_task_glue_fptr;
+ (imm (Int64.of_int abi.Abi.abi_tag));
fptr_operand;
callsz
|];
@@ -6183,6 +6185,8 @@ let trans_visitor
tab_sz cx.ctxt_required_rust_sym_num;
tab_sz cx.ctxt_required_c_sym_num;
tab_sz cx.ctxt_required_lib_num;
+
+ Asm.WORD (word_ty_mach, Asm.IMM (Int64.of_int abi.Abi.abi_tag));
|]))
in
diff --git a/src/comp/back/abi.rs b/src/comp/back/abi.rs
index 82a85a6c..f41f6e20 100644
--- a/src/comp/back/abi.rs
+++ b/src/comp/back/abi.rs
@@ -60,6 +60,9 @@ const int worst_case_glue_call_args = 7;
const int n_upcall_glues = 7;
+const int abi_x86_rustboot_cdecl = 1;
+const int abi_x86_rustc_fastcall = 2;
+
fn memcpy_glue_name() -> str {
ret "rust_memcpy_glue";
}
diff --git a/src/comp/back/x86.rs b/src/comp/back/x86.rs
index 907cb32e..10227df7 100644
--- a/src/comp/back/x86.rs
+++ b/src/comp/back/x86.rs
@@ -98,12 +98,12 @@ fn rust_activate_glue() -> vec[str] {
* | esi |
* | ebx | <-- current task->rust_sp == current esp
*
- *
+ *
* This is a problem. If we return to "esp <- task->rust_sp" it
* will push esp back down by 5 words. This manifests as a rust
* stack that grows by 5 words on each yield/reactivate. Not
* good.
- *
+ *
* So what we do here is just adjust task->rust_sp up 5 words as
* well, to mirror the movement in esp we're about to
* perform. That way the "esp <- task->rust_sp" we 'ret' to below
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 9da7e009..4a672f49 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -345,7 +345,8 @@ fn T_crate(type_names tn) -> TypeRef {
T_int(), // size_t main_exit_task_glue_off
T_int(), // int n_rust_syms
T_int(), // int n_c_syms
- T_int() // int n_libs
+ T_int(), // int n_libs
+ T_int() // uintptr_t abi_tag
));
tn.associate(s, t);
ret t;
@@ -4545,7 +4546,7 @@ fn trans_exit_task_glue(@crate_ctxt cx) {
let vec[ValueRef] V_args = vec();
auto llfn = cx.glues.exit_task_glue;
- let ValueRef lltaskptr = llvm.LLVMGetParam(llfn, 0u);
+ let ValueRef lltaskptr = llvm.LLVMGetParam(llfn, 3u);
auto fcx = @rec(llfn=llfn,
lltaskptr=lltaskptr,
llenv=C_null(T_opaque_closure_ptr(cx.tn)),
@@ -4596,7 +4597,8 @@ fn create_crate_constant(@crate_ctxt cx) {
exit_task_glue_off, // size_t main_exit_task_glue_off
C_null(T_int()), // int n_rust_syms
C_null(T_int()), // int n_c_syms
- C_null(T_int()) // int n_libs
+ C_null(T_int()), // int n_libs
+ C_int(abi.abi_x86_rustc_fastcall) // uintptr_t abi_tag
));
llvm.LLVMSetInitializer(cx.crate_ptr, crate_val);
@@ -4810,7 +4812,10 @@ fn make_glues(ModuleRef llmod, type_names tn) -> @glue_fns {
* this is the signature required to retrieve it.
*/
exit_task_glue = decl_cdecl_fn(llmod, abi.exit_task_glue_name(),
- T_fn(vec(T_taskptr(tn)),
+ T_fn(vec(T_int(),
+ T_int(),
+ T_int(),
+ T_taskptr(tn)),
T_void())),
upcall_glues =
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);