fix how we walk functions to match new closure fmt

This commit is contained in:
Niko Matsakis 2012-01-06 12:06:35 -08:00
parent 8e89df69de
commit 8506241f3a
15 changed files with 104 additions and 67 deletions

View File

@ -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)))))

View File

@ -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])),

View File

@ -1,4 +1,5 @@
#include "rust_internal.h"
#include "rust_util.h"
#include <cstdio>
struct

View File

@ -3,6 +3,7 @@
#include "rust_internal.h"
#include "rust_scheduler.h"
#include "rust_task.h"
#include "rust_util.h"
#if !defined(__WIN32__)
#include <sys/time.h>
@ -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();

View File

@ -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:
//

View File

@ -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:
//

View File

@ -3,6 +3,7 @@
#include <cassert>
#include <pthread.h>
#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:
//

View File

@ -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<const type_desc *>(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<const type_desc*>(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,

View File

@ -10,6 +10,7 @@
#include <iostream>
#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<T,U>::walk_tag(tag_info &tinfo) {
template<typename T,typename U>
void
data<T,U>::walk_fn_contents(ptr &dp) {
dp += sizeof(void *); // Skip over the code pointer.
uint8_t *box_ptr = bump_dp<uint8_t *>(dp);
if (!box_ptr)
fn_env_pair pair = bump_dp<fn_env_pair>(dp);
if (!pair.env)
return;
type_desc *subtydesc =
*reinterpret_cast<type_desc **>(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<T *>(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<T *>(this), closure_td->shape, params,
closure_td->shape_tables, closure_dp);
sub.align = true;
sub.walk();
}

View File

@ -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

View File

@ -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_task>, rust_cond
~rust_task();
void start(spawn_fn spawnee_fn,
rust_boxed_closure *env,
rust_opaque_closure *env,
void *args);
void start();
bool running();

View File

@ -12,6 +12,7 @@
#include "rust_scheduler.h"
#include "rust_unwind.h"
#include "rust_upcall.h"
#include "rust_util.h"
#include <stdint.h>

View File

@ -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:
//

View File

@ -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");
}

View File

@ -53,7 +53,7 @@ fn test_join_chan_fail() {
#[test]
fn spawn_polymorphic() {
fn foo<send T>(x: T) { log(error, x); }
fn foo<T:send>(x: T) { log(error, x); }
task::spawn {|| foo(true);};
task::spawn {|| foo(42);};
}