From baf95a76bdd54f2bbb064c8a333c0701b5f1e4e3 Mon Sep 17 00:00:00 2001 From: Michael Sullivan Date: Fri, 10 Jun 2011 14:11:22 -0700 Subject: [PATCH 1/4] Make type_desc fields have useful types and better names. Add in cmp_glue. --- src/rt/rust.h | 3 +++ src/rt/rust_internal.h | 18 ++++++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/rt/rust.h b/src/rt/rust.h index 66185727cffac..1ca5dddd5e695 100644 --- a/src/rt/rust.h +++ b/src/rt/rust.h @@ -10,11 +10,14 @@ // 'cdecl' ABI only means anything on i386 #ifdef __WIN32__ #define CDECL __cdecl +#define FASTCALL __fastcall #else #define CDECL __attribute__((cdecl)) +#define FASTCALL __attribute__((fastcall)) #endif #else #define CDECL +#define FASTCALL #endif /* diff --git a/src/rt/rust_internal.h b/src/rt/rust_internal.h index 6b38004bc2632..56bcee974ec97 100644 --- a/src/rt/rust_internal.h +++ b/src/rt/rust_internal.h @@ -204,6 +204,11 @@ struct rust_timer { #include "rust_util.h" typedef void CDECL (*activate_glue_ty)(rust_task *); +typedef void FASTCALL (glue_fn)(void *, rust_task *, void *, + const type_desc **, void *); +typedef void FASTCALL (cmp_glue_fn)(void *, rust_task *, void *, + const type_desc **, + void *, void *, int8_t); struct type_desc { // First part of type_desc is known to compiler. @@ -211,13 +216,14 @@ struct type_desc { const type_desc **first_param; size_t size; size_t align; - uintptr_t copy_glue_off; - uintptr_t drop_glue_off; - uintptr_t free_glue_off; - uintptr_t sever_glue_off; // For GC. - uintptr_t mark_glue_off; // For GC. - uintptr_t obj_drop_glue_off; // For custom destructors. + glue_fn *take_glue; + glue_fn *drop_glue; + glue_fn *free_glue; + glue_fn *sever_glue; // For GC. + glue_fn *mark_glue; // For GC. + glue_fn *obj_drop_glue; // For custom destructors. uintptr_t is_stateful; + cmp_glue_fn *cmp_glue; // Residual fields past here are known only to runtime. UT_hash_handle hh; From da919fa727b11813bf5a3a23269e49dfa6a715a3 Mon Sep 17 00:00:00 2001 From: Michael Sullivan Date: Fri, 10 Jun 2011 14:14:00 -0700 Subject: [PATCH 2/4] Implement upcall_vec_append and use it for vector append. --- src/comp/back/upcall.rs | 5 +++++ src/comp/middle/trans.rs | 2 +- src/rt/rust_upcall.cpp | 48 +++++++++++++++++++++++++++++++++++++++- src/rt/rustrt.def.in | 1 + 4 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/comp/back/upcall.rs b/src/comp/back/upcall.rs index f6f6c26f6ae60..7df96c248004f 100644 --- a/src/comp/back/upcall.rs +++ b/src/comp/back/upcall.rs @@ -5,6 +5,7 @@ import trans::decl_cdecl_fn; import trans::T_f32; import trans::T_f64; import trans::T_fn; +import trans::T_bool; import trans::T_i8; import trans::T_i32; import trans::T_int; @@ -52,6 +53,7 @@ type upcalls = rec( ValueRef new_str, ValueRef new_vec, ValueRef vec_grow, + ValueRef vec_append, ValueRef get_type_desc, ValueRef new_task, ValueRef start_task, @@ -108,6 +110,9 @@ fn declare_upcalls(type_names tn, ModuleRef llmod) -> @upcalls { vec_grow=d("vec_grow", [T_opaque_vec_ptr(), T_size_t(), T_ptr(T_int()), T_ptr(T_tydesc(tn))], T_opaque_vec_ptr()), + vec_append=d("vec_append", [T_ptr(T_tydesc(tn)), T_ptr(T_tydesc(tn)), + T_ptr(T_opaque_vec_ptr()), + T_opaque_vec_ptr(), T_bool()], T_void()), get_type_desc=d("get_type_desc", [T_ptr(T_nil()), T_size_t(), T_size_t(), T_size_t(), T_ptr(T_ptr(T_tydesc(tn)))], diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 2c0965ead2fcf..e1ef1271631fd 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3540,7 +3540,7 @@ fn trans_vec_append(&@block_ctxt cx, &ty::t t, auto dst = bcx.build.PointerCast(lhs, T_ptr(T_opaque_vec_ptr())); auto src = bcx.build.PointerCast(rhs, T_opaque_vec_ptr()); - ret res(bcx, bcx.build.FastCall(cx.fcx.lcx.ccx.glues.vec_append_glue, + ret res(bcx, bcx.build.Call(cx.fcx.lcx.ccx.upcalls.vec_append, [cx.fcx.lltaskptr, llvec_tydesc.val, llelt_tydesc.val, diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index 6d8734bd43008..c9ce2bc3830f5 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -415,7 +415,7 @@ upcall_vec_grow(rust_task *task, * * Step 3 is a bit tricky. We don't know how to properly copy the * elements in the runtime (all we have are bits in a buffer; no - * type infromation and no copy glue). What we do instead is set the + * type information and no copy glue). What we do instead is set the * need_copy outparam flag to indicate to our caller (vec-copy glue) * that we need the copies performed for us. */ @@ -436,6 +436,52 @@ upcall_vec_grow(rust_task *task, return v; } +// Copy elements from one vector to another, +// dealing with reference counts +static inline void +copy_elements(rust_task *task, type_desc *elem_t, + void *pdst, void *psrc, size_t n) +{ + char *dst = (char *)pdst, *src = (char *)psrc; + + // increment the refcount of each element of the vector + if (elem_t->take_glue) { + glue_fn *take_glue = elem_t->take_glue; + size_t elem_size = elem_t->size; + const type_desc **tydescs = elem_t->first_param; + for (char *p = src; p < src+n; p += elem_size) { + take_glue(NULL, task, NULL, tydescs, p); + } + } + memmove(dst, src, n); +} + +extern "C" CDECL void +upcall_vec_append(rust_task *task, type_desc *t, type_desc *elem_t, + rust_vec **dst_ptr, rust_vec *src, bool skip_null) +{ + rust_vec *dst = *dst_ptr; + uintptr_t need_copy; + size_t n_src_bytes = skip_null ? src->fill - 1 : src->fill; + size_t n_dst_bytes = skip_null ? dst->fill - 1 : dst->fill; + rust_vec *new_vec = upcall_vec_grow(task, dst, n_src_bytes, + &need_copy, t); + + if (need_copy) { + // Copy any dst elements in, omitting null if doing str. + copy_elements(task, elem_t, &new_vec->data, &dst->data, n_dst_bytes); + } + + // Copy any src elements in, carrying along null if doing str. + void *new_end = (void *)((char *)new_vec->data + n_dst_bytes); + copy_elements(task, elem_t, new_end, &src->data, src->fill); + new_vec->fill = n_dst_bytes + src->fill; + + // Write new_vec back through the alias we were given. + *dst_ptr = new_vec; +} + + extern "C" CDECL type_desc * upcall_get_type_desc(rust_task *task, void *curr_crate, // ignored, legacy compat. diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 2c189d18d1dd2..9d3b9f15334b7 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -69,6 +69,7 @@ upcall_start_thread upcall_trace_str upcall_trace_word upcall_vec_grow +upcall_vec_append upcall_yield vec_alloc vec_alloc_mut From d4bdaa2bb3b502f597b6ce51657243e7fd2cffb3 Mon Sep 17 00:00:00 2001 From: Michael Sullivan Date: Fri, 10 Jun 2011 14:22:36 -0700 Subject: [PATCH 3/4] Eliminate vec_append_glue. --- mk/rt.mk | 2 +- src/comp/back/abi.rs | 4 -- src/comp/middle/trans.rs | 39 +---------- src/rt/rustrt.def.in | 1 - src/rt/vec_append.ll | 138 --------------------------------------- 5 files changed, 3 insertions(+), 181 deletions(-) delete mode 100644 src/rt/vec_append.ll diff --git a/mk/rt.mk b/mk/rt.mk index 566e5f285d4e0..b97eb12f2d82e 100644 --- a/mk/rt.mk +++ b/mk/rt.mk @@ -29,7 +29,7 @@ RUNTIME_CS := rt/sync/timer.cpp \ rt/test/rust_test_runtime.cpp \ rt/test/rust_test_util.cpp -RUNTIME_LL := rt/new_exit.ll rt/vec_append.ll +RUNTIME_LL := rt/new_exit.ll RUNTIME_S := rt/activate_glue.s rt/yield_glue.s diff --git a/src/comp/back/abi.rs b/src/comp/back/abi.rs index bfe601c15a396..27956eb45331c 100644 --- a/src/comp/back/abi.rs +++ b/src/comp/back/abi.rs @@ -77,10 +77,6 @@ fn bzero_glue_name() -> str { ret "rust_bzero_glue"; } -fn vec_append_glue_name() -> str { - ret "rust_vec_append_glue"; -} - fn yield_glue_name() -> str { ret "rust_yield_glue"; } diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index e1ef1271631fd..9cf1806d219e7 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -86,8 +86,7 @@ state obj namegen(mutable int i) { type derived_tydesc_info = rec(ValueRef lltydesc, bool escapes); type glue_fns = rec(ValueRef yield_glue, - ValueRef no_op_type_glue, - ValueRef vec_append_glue); + ValueRef no_op_type_glue); type tydesc_info = rec(ty::t ty, ValueRef tydesc, @@ -8247,39 +8246,6 @@ fn make_no_op_type_glue(ValueRef fun) { new_builder(llbb).RetVoid(); } -fn make_vec_append_glue(ModuleRef llmod, type_names tn) -> ValueRef { - /* - * Args to vec_append_glue: - * - * 0. (Implicit) task ptr - * - * 1. Pointer to the tydesc of the vec, so that we can tell if it's gc - * mem, and have a tydesc to pass to malloc if we're allocating anew. - * - * 2. Pointer to the tydesc of the vec's stored element type, so that - * elements can be copied to a newly alloc'ed vec if one must be - * created. - * - * 3. Dst vec ptr (i.e. ptr to ptr to rust_vec). - * - * 4. Src vec (i.e. ptr to rust_vec). - * - * 5. Flag indicating whether to skip trailing null on dst. - * - */ - - auto ty = T_fn([T_taskptr(tn), - T_ptr(T_tydesc(tn)), - T_ptr(T_tydesc(tn)), - T_ptr(T_opaque_vec_ptr()), - T_opaque_vec_ptr(), T_bool()], - T_void()); - - auto llfn = decl_fastcall_fn(llmod, abi::vec_append_glue_name(), ty); - ret llfn; -} - - fn vec_fill(&@block_ctxt bcx, ValueRef v) -> ValueRef { ret bcx.build.Load(bcx.build.GEP(v, [C_int(0), C_int(abi::vec_elt_fill)])); @@ -8293,8 +8259,7 @@ fn vec_p0(&@block_ctxt bcx, ValueRef v) -> ValueRef { fn make_glues(ModuleRef llmod, &type_names tn) -> @glue_fns { ret @rec(yield_glue = decl_glue(llmod, tn, abi::yield_glue_name()), - no_op_type_glue = decl_no_op_type_glue(llmod, tn), - vec_append_glue = make_vec_append_glue(llmod, tn)); + no_op_type_glue = decl_no_op_type_glue(llmod, tn)); } fn make_common_glue(&session::session sess, &str output) { diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 9d3b9f15334b7..01f222d561392 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -23,7 +23,6 @@ rust_process_wait rust_ptr_eq rust_run_program rust_start -rust_vec_append_glue size_of squareroot str_alloc diff --git a/src/rt/vec_append.ll b/src/rt/vec_append.ll deleted file mode 100644 index 28a6e793cdb4b..0000000000000 --- a/src/rt/vec_append.ll +++ /dev/null @@ -1,138 +0,0 @@ -%0 = type { i32, i32, i32, i32, [0 x i32] } -%task = type { i32, i32, i32, i32, i32, i32, i32, i32 } -%tydesc = type { %tydesc**, i32, i32, void (i1*, %task*, i1*, %tydesc**, i8*)*, void (i1*, %task*, i1*, %tydesc**, i8*)*, void (i1*, %task*, i1*, %tydesc**, i8*)*, void (i1*, %task*, i1*, %tydesc**, i8*)*, void (i1*, %task*, i1*, %tydesc**, i8*)*, void (i1*, %task*, i1*, %tydesc**, i8*)*, void (i1*, %task*, i1*, %tydesc**, i8*)*, void (i1*, %task*, i1*, %tydesc**, i8*, i8*, i8)* } - -declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32, i1) nounwind - -define fastcc void @rust_vec_append_glue(%task*, %tydesc*, %tydesc*, %0**, %0*, i1) { -allocas: - %6 = alloca i32 - %7 = alloca i8* - br label %copy_args - -copy_args: ; preds = %allocas - br label %derived_tydescs - -derived_tydescs: ; preds = %copy_args - br label %8 - -;