From: Niko Matsakis Date: Fri, 6 Jan 2012 20:06:35 +0000 (-0800) Subject: fix how we walk functions to match new closure fmt X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=8506241f3a0dce3f0d24764a3ce3d16f99bcb809;p=rust.git fix how we walk functions to match new closure fmt --- diff --git a/mk/target.mk b/mk/target.mk index 2ac8fe73ad3..9ca01837f15 100644 --- a/mk/target.mk +++ b/mk/target.mk @@ -35,11 +35,6 @@ $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_STDLIB): \ @$$(call E, compile_and_link: $$@) $$(STAGE$(1)_T_$(2)_H_$(3)) --lib -o $$@ $$< && touch $$@ -$$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_RUNTIME): \ - rt/$(2)/$$(CFG_RUNTIME) - @$$(call E, cp: $$@) - $$(Q)cp $$< $$@ - $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_RUSTLLVM): \ rustllvm/$(2)/$$(CFG_RUSTLLVM) @$$(call E, cp: $$@) @@ -62,10 +57,49 @@ $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBRUSTC): \ endef +# The stage0 (snapshot) compiler produces binaries that expect the +# snapshot runtime. Therefore, the stage1 compiler and libraries +# (which are produced by stage0) should use the runtime from the +# snapshot. The stage2 compiler and libraries (which are produced by +# stage1) will be the first that are expecting to run against the +# runtime as defined in the working directory. +# +# Arguments are the same as for TARGET_BASE_STAGE_N +define TARGET_RT_FROM_SNAPSHOT + +$$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_RUNTIME): \ + $$(HLIB$(1)_H_$(3))/$$(CFG_RUNTIME) + @$$(call E, cp: $$@) + $$(Q)cp $$< $$@ + +endef + +# This rule copies from the runtime for the working directory. It +# applies to targets produced by stage1 or later. See comment on +# previous rule. +# +# Arguments are the same as for TARGET_BASE_STAGE_N +define TARGET_RT_FROM_WD + +$$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_RUNTIME): \ + rt/$(2)/$$(CFG_RUNTIME) + @$$(call E, cp: $$@) + $$(Q)cp $$< $$@ + +endef + # In principle, each host can build each target: $(foreach source,$(CFG_TARGET_TRIPLES), \ $(foreach target,$(CFG_TARGET_TRIPLES), \ - $(eval $(call TARGET_STAGE_N,0,$(source),$(target))) \ - $(eval $(call TARGET_STAGE_N,1,$(source),$(target))) \ - $(eval $(call TARGET_STAGE_N,2,$(source),$(target))) \ - $(eval $(call TARGET_STAGE_N,3,$(source),$(target))))) + $(eval $(call TARGET_STAGE_N,0,$(target),$(source))) \ + $(eval $(call TARGET_STAGE_N,1,$(target),$(source))) \ + $(eval $(call TARGET_STAGE_N,2,$(target),$(source))) \ + $(eval $(call TARGET_STAGE_N,3,$(target),$(source))))) + +$(eval $(call TARGET_RT_FROM_SNAPSHOT,0,$(CFG_HOST_TRIPLE),$(CFG_HOST_TRIPLE))) + +$(foreach source,$(CFG_TARGET_TRIPLES), \ + $(foreach target,$(CFG_TARGET_TRIPLES), \ + $(eval $(call TARGET_RT_FROM_WD,1,$(target),$(source))) \ + $(eval $(call TARGET_RT_FROM_WD,2,$(target),$(source))) \ + $(eval $(call TARGET_RT_FROM_WD,3,$(target),$(source))))) diff --git a/src/comp/middle/trans_closure.rs b/src/comp/middle/trans_closure.rs index 57791f17ee0..aed74da88a0 100644 --- a/src/comp/middle/trans_closure.rs +++ b/src/comp/middle/trans_closure.rs @@ -646,8 +646,12 @@ fn make_opaque_cbox_take_glue( -> @block_ctxt { // Easy cases: alt ck { - ty::closure_block. { ret bcx; } - ty::closure_shared. { ret incr_refcnt_of_boxed(bcx, Load(bcx, cboxptr)); } + ty::closure_block. { + ret bcx; + } + ty::closure_shared. { + ret incr_refcnt_of_boxed(bcx, Load(bcx, cboxptr)); + } ty::closure_send. { /* hard case: */ } } @@ -858,7 +862,8 @@ fn trans_bind_thunk(cx: @local_ctxt, // Copy in the type parameters. check type_is_tup_like(l_bcx, cboxptr_ty); let {bcx: l_bcx, val: param_record} = - GEP_tup_like(l_bcx, cboxptr_ty, llclosure, [0, abi::cbox_elt_ty_params]); + GEP_tup_like(l_bcx, cboxptr_ty, llclosure, + [0, abi::cbox_elt_ty_params]); let off = 0; for param in param_bounds { let dsc = Load(l_bcx, GEPi(l_bcx, param_record, [0, off])), diff --git a/src/rt/rust.cpp b/src/rt/rust.cpp index 03acdaa91e0..6542c7237a7 100644 --- a/src/rt/rust.cpp +++ b/src/rt/rust.cpp @@ -1,4 +1,5 @@ #include "rust_internal.h" +#include "rust_util.h" #include struct diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index 4f951a7faf0..264e6fdb325 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -3,6 +3,7 @@ #include "rust_internal.h" #include "rust_scheduler.h" #include "rust_task.h" +#include "rust_util.h" #if !defined(__WIN32__) #include @@ -420,11 +421,6 @@ rust_get_task() { return rust_scheduler::get_task(); } -struct fn_env_pair { - spawn_fn f; - rust_boxed_closure *env; -}; - extern "C" CDECL void start_task(rust_task_id id, fn_env_pair *f) { rust_task *task = rust_scheduler::get_task(); diff --git a/src/rt/rust_internal.h b/src/rt/rust_internal.h index 889b5f62018..b83d74f6bfe 100644 --- a/src/rt/rust_internal.h +++ b/src/rt/rust_internal.h @@ -241,8 +241,6 @@ struct rust_timer { ~rust_timer(); }; -#include "rust_util.h" - typedef void CDECL (glue_fn)(void *, void *, const type_desc **, void *); typedef void CDECL (cmp_glue_fn)(void *, void *, @@ -254,6 +252,30 @@ struct rust_shape_tables { uint8_t *resources; }; +struct rust_opaque_closure; + +// The type of functions that we spawn, which fall into two categories: +// - the main function: has a NULL environment, but uses the void* arg +// - unique closures of type fn~(): have a non-NULL environment, but +// no arguments (and hence the final void*) is harmless +typedef void (*CDECL spawn_fn)(void*, rust_opaque_closure*, void *); + +// corresponds to the layout of a fn(), fn@(), fn~() etc +struct fn_env_pair { + spawn_fn f; + rust_opaque_closure *env; +}; + +// corresponds the closures generated in trans_closure.rs +struct rust_opaque_closure { + intptr_t ref_count; + const type_desc *td; + // The size/types of these will vary per closure, so they + // cannot be statically expressed. See trans_closure.rs: + const type_desc *captured_tds[0]; + // struct bound_data; +}; + struct type_desc { // First part of type_desc is known to compiler. // first_param = &descs[1] if dynamic, null if static. @@ -297,7 +319,6 @@ extern "C" type_desc *rust_clone_type_desc(type_desc*); // indent-tabs-mode: nil // c-basic-offset: 4 // buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; // End: // diff --git a/src/rt/rust_kernel.cpp b/src/rt/rust_kernel.cpp index f009541053d..3078f6b78c4 100644 --- a/src/rt/rust_kernel.cpp +++ b/src/rt/rust_kernel.cpp @@ -1,4 +1,5 @@ #include "rust_internal.h" +#include "rust_util.h" #define KLOG_(...) \ KLOG(this, kern, __VA_ARGS__) @@ -216,6 +217,5 @@ rust_kernel::win32_require(LPCTSTR fn, BOOL ok) { // indent-tabs-mode: nil // c-basic-offset: 4 // buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; // End: // diff --git a/src/rt/rust_scheduler.cpp b/src/rt/rust_scheduler.cpp index bf40fea36ee..1df70306975 100644 --- a/src/rt/rust_scheduler.cpp +++ b/src/rt/rust_scheduler.cpp @@ -3,6 +3,7 @@ #include #include #include "rust_internal.h" +#include "rust_util.h" #include "globals.h" #ifndef _WIN32 @@ -414,6 +415,5 @@ rust_scheduler::get_task() { // indent-tabs-mode: nil // c-basic-offset: 4 // buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; // End: // diff --git a/src/rt/rust_shape.cpp b/src/rt/rust_shape.cpp index bd388ffff82..1743aaad9dd 100644 --- a/src/rt/rust_shape.cpp +++ b/src/rt/rust_shape.cpp @@ -47,13 +47,9 @@ type_param::make(const type_desc **tydescs, unsigned n_tydescs, // Constructs type parameters from a function shape. This is a bit messy, // because it requires that the function shape have a specific format. type_param * -type_param::from_fn_shape(const uint8_t *sp, ptr dp, arena &arena) { - const type_desc *tydesc = bump_dp(dp); - const type_desc **tydescs = (const type_desc **)dp; - unsigned n_tydescs = tydesc->n_obj_params & 0x7fffffff; - for (unsigned i = 0; i < n_tydescs; i++) - bump_dp(dp); - return make(tydescs, n_tydescs, arena); +type_param::from_fn_shape(rust_opaque_closure *env, arena &arena) { + unsigned n_tydescs = env->td->n_obj_params & 0x7fffffff; + return make(env->captured_tds, n_tydescs, arena); } // Constructs type parameters from an object shape. This is also a bit messy, diff --git a/src/rt/rust_shape.h b/src/rt/rust_shape.h index e6f3cfcd3d3..af21865f828 100644 --- a/src/rt/rust_shape.h +++ b/src/rt/rust_shape.h @@ -10,6 +10,7 @@ #include #include "rust_internal.h" +#include "rust_util.h" // ISAAC pollutes our namespace. #undef align @@ -300,7 +301,7 @@ public: const type_param *params; // subparameters // Constructs type parameters from a function shape. - static type_param *from_fn_shape(const uint8_t *sp, ptr dp, arena &arena); + static type_param *from_fn_shape(rust_opaque_closure *env, arena &arena); // Creates type parameters from an object shape description. static type_param *from_obj_shape(const uint8_t *sp, ptr dp, arena &arena); @@ -952,23 +953,17 @@ data::walk_tag(tag_info &tinfo) { template void data::walk_fn_contents(ptr &dp) { - dp += sizeof(void *); // Skip over the code pointer. - - uint8_t *box_ptr = bump_dp(dp); - if (!box_ptr) + fn_env_pair pair = bump_dp(dp); + if (!pair.env) return; - type_desc *subtydesc = - *reinterpret_cast(box_ptr + sizeof(void *)); - ptr closure_dp(box_ptr + sizeof(void *)); - arena arena; - type_param *params = type_param::from_fn_shape(subtydesc->shape, - closure_dp, arena); - - closure_dp += sizeof(void *); - T sub(*static_cast(this), subtydesc->shape, params, - subtydesc->shape_tables, closure_dp); + type_param *params = + type_param::from_fn_shape(pair.env, arena); + const type_desc *closure_td = pair.env->td; + ptr closure_dp((uintptr_t)pair.env); + T sub(*static_cast(this), closure_td->shape, params, + closure_td->shape_tables, closure_dp); sub.align = true; sub.walk(); } diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp index cade11e372d..79a6abdcf39 100644 --- a/src/rt/rust_task.cpp +++ b/src/rt/rust_task.cpp @@ -293,7 +293,7 @@ rust_task::~rust_task() struct spawn_args { rust_task *task; spawn_fn f; - rust_boxed_closure *envptr; + rust_opaque_closure *envptr; void *argptr; }; @@ -347,12 +347,13 @@ void task_start_wrapper(spawn_args *a) failed = true; } - rust_boxed_closure* boxed_env = (rust_boxed_closure*)a->envptr; - if(boxed_env) { + rust_opaque_closure* env = a->envptr; + if(env) { // free the environment. - const type_desc *td = boxed_env->closure.td; - td->drop_glue(NULL, NULL, td->first_param, &boxed_env->closure); - upcall_shared_free(boxed_env); + const type_desc *td = env->td; + LOG(task, task, "Freeing env %p with td %p", env, td); + td->drop_glue(NULL, NULL, td->first_param, env); + upcall_shared_free(env); } // The cleanup work needs lots of stack @@ -364,7 +365,7 @@ void task_start_wrapper(spawn_args *a) void rust_task::start(spawn_fn spawnee_fn, - rust_boxed_closure *envptr, + rust_opaque_closure *envptr, void *argptr) { LOG(this, task, "starting task from fn 0x%" PRIxPTR diff --git a/src/rt/rust_task.h b/src/rt/rust_task.h index 6be28f41574..d0e3d0e2ad6 100644 --- a/src/rt/rust_task.h +++ b/src/rt/rust_task.h @@ -21,18 +21,6 @@ struct chan_handle { rust_port_id port; }; -struct rust_closure { - const type_desc *td; - // ... see trans_closure.rs for full description ... -}; - -struct rust_boxed_closure { - intptr_t ref_count; - rust_closure closure; -}; - -typedef void (*CDECL spawn_fn)(void*, rust_boxed_closure*, void *); - struct rust_box; struct stk_seg { @@ -145,7 +133,7 @@ rust_task : public kernel_owned, rust_cond ~rust_task(); void start(spawn_fn spawnee_fn, - rust_boxed_closure *env, + rust_opaque_closure *env, void *args); void start(); bool running(); diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index 6baac699e8f..a520770be3a 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -12,6 +12,7 @@ #include "rust_scheduler.h" #include "rust_unwind.h" #include "rust_upcall.h" +#include "rust_util.h" #include diff --git a/src/rt/rust_util.h b/src/rt/rust_util.h index 50545b21310..37a1eb93e1d 100644 --- a/src/rt/rust_util.h +++ b/src/rt/rust_util.h @@ -210,7 +210,6 @@ make_str(rust_kernel* kernel, char* c, size_t strlen, const char* name) { // indent-tabs-mode: nil // c-basic-offset: 4 // buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; // End: // diff --git a/src/rt/test/rust_test_runtime.cpp b/src/rt/test/rust_test_runtime.cpp index 7bfa06fdc99..815d55acd86 100644 --- a/src/rt/test/rust_test_runtime.cpp +++ b/src/rt/test/rust_test_runtime.cpp @@ -39,7 +39,7 @@ rust_domain_test::run() { return true; } -void task_entry(void *, rust_boxed_closure *, void *) { +void task_entry(void *, rust_opaque_closure *, void *) { printf("task entry\n"); } diff --git a/src/test/stdtest/task.rs b/src/test/stdtest/task.rs index 7945aaed744..d1408d183d5 100644 --- a/src/test/stdtest/task.rs +++ b/src/test/stdtest/task.rs @@ -53,7 +53,7 @@ fn test_join_chan_fail() { #[test] fn spawn_polymorphic() { - fn foo(x: T) { log(error, x); } + fn foo(x: T) { log(error, x); } task::spawn {|| foo(true);}; task::spawn {|| foo(42);}; }