Skip to content

Commit ac743cf

Browse files
committed
Merge pull request #490 from msullivan/fix_vec_append
Move the implementation of vec_append from llvm assembly to a regular upcall
2 parents c6be352 + ccd1bcf commit ac743cf

File tree

6 files changed

+80
-54
lines changed

6 files changed

+80
-54
lines changed

src/comp/back/abi.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,8 @@ fn bzero_glue_name() -> str {
8888
ret "rust_bzero_glue";
8989
}
9090

91-
fn vec_append_glue_name() -> str {
92-
ret "rust_vec_append_glue";
91+
fn yield_glue_name() -> str {
92+
ret "rust_yield_glue";
9393
}
9494

9595
fn no_op_type_glue_name() -> str {

src/comp/back/upcall.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import trans::decl_cdecl_fn;
55
import trans::T_f32;
66
import trans::T_f64;
77
import trans::T_fn;
8+
import trans::T_bool;
89
import trans::T_i8;
910
import trans::T_i32;
1011
import trans::T_int;
@@ -53,6 +54,7 @@ type upcalls = rec(
5354
ValueRef new_str,
5455
ValueRef new_vec,
5556
ValueRef vec_grow,
57+
ValueRef vec_append,
5658
ValueRef get_type_desc,
5759
ValueRef new_task,
5860
ValueRef start_task,
@@ -111,6 +113,9 @@ fn declare_upcalls(type_names tn, ModuleRef llmod) -> @upcalls {
111113
vec_grow=d("vec_grow", [T_opaque_vec_ptr(), T_size_t(),
112114
T_ptr(T_int()), T_ptr(T_tydesc(tn))],
113115
T_opaque_vec_ptr()),
116+
vec_append=d("vec_append", [T_ptr(T_tydesc(tn)), T_ptr(T_tydesc(tn)),
117+
T_ptr(T_opaque_vec_ptr()),
118+
T_opaque_vec_ptr(), T_bool()], T_void()),
114119
get_type_desc=d("get_type_desc",
115120
[T_ptr(T_nil()), T_size_t(), T_size_t(),
116121
T_size_t(), T_ptr(T_ptr(T_tydesc(tn)))],

src/comp/middle/trans.rs

Lines changed: 10 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,7 @@ state obj namegen(mutable int i) {
8585

8686
type derived_tydesc_info = rec(ValueRef lltydesc, bool escapes);
8787

88-
type glue_fns = rec(ValueRef no_op_type_glue,
89-
ValueRef vec_append_glue);
88+
type glue_fns = rec(ValueRef no_op_type_glue);
9089

9190
type tydesc_info = rec(ty::t ty,
9291
ValueRef tydesc,
@@ -1972,7 +1971,7 @@ fn declare_generic_glue(&@local_ctxt cx,
19721971
fn_nm = mangle_internal_name_by_seq(cx.ccx,
19731972
"glue_" + name);
19741973
}
1975-
auto llfn = decl_fastcall_fn(cx.ccx.llmod, fn_nm, llfnty);
1974+
auto llfn = decl_cdecl_fn(cx.ccx.llmod, fn_nm, llfnty);
19761975
set_glue_inlining(cx, llfn, t);
19771976
ret llfn;
19781977
}
@@ -3263,11 +3262,11 @@ fn call_tydesc_glue_full(&@block_ctxt cx, ValueRef v,
32633262
auto llfnptr = cx.build.GEP(tydesc, [C_int(0), C_int(field)]);
32643263
auto llfn = cx.build.Load(llfnptr);
32653264

3266-
cx.build.FastCall(llfn, [C_null(T_ptr(T_nil())),
3267-
cx.fcx.lltaskptr,
3268-
C_null(T_ptr(T_nil())),
3269-
lltydescs,
3270-
llrawptr]);
3265+
cx.build.Call(llfn, [C_null(T_ptr(T_nil())),
3266+
cx.fcx.lltaskptr,
3267+
C_null(T_ptr(T_nil())),
3268+
lltydescs,
3269+
llrawptr]);
32713270
}
32723271

32733272
fn call_tydesc_glue(&@block_ctxt cx, ValueRef v,
@@ -3342,7 +3341,7 @@ fn call_cmp_glue(&@block_ctxt cx,
33423341
llrawrhsptr,
33433342
llop];
33443343

3345-
r.bcx.build.FastCall(llfn, llargs);
3344+
r.bcx.build.Call(llfn, llargs);
33463345

33473346
ret res(r.bcx, r.bcx.build.Load(llcmpresultptr));
33483347
}
@@ -3711,7 +3710,7 @@ fn trans_vec_append(&@block_ctxt cx, &ty::t t,
37113710
auto dst = bcx.build.PointerCast(lhs, T_ptr(T_opaque_vec_ptr()));
37123711
auto src = bcx.build.PointerCast(rhs, T_opaque_vec_ptr());
37133712

3714-
ret res(bcx, bcx.build.FastCall(cx.fcx.lcx.ccx.glues.vec_append_glue,
3713+
ret res(bcx, bcx.build.Call(cx.fcx.lcx.ccx.upcalls.vec_append,
37153714
[cx.fcx.lltaskptr,
37163715
llvec_tydesc.val,
37173716
llelt_tydesc.val,
@@ -8742,39 +8741,6 @@ fn make_no_op_type_glue(ValueRef fun) {
87428741
new_builder(llbb).RetVoid();
87438742
}
87448743

8745-
fn make_vec_append_glue(ModuleRef llmod, type_names tn) -> ValueRef {
8746-
/*
8747-
* Args to vec_append_glue:
8748-
*
8749-
* 0. (Implicit) task ptr
8750-
*
8751-
* 1. Pointer to the tydesc of the vec, so that we can tell if it's gc
8752-
* mem, and have a tydesc to pass to malloc if we're allocating anew.
8753-
*
8754-
* 2. Pointer to the tydesc of the vec's stored element type, so that
8755-
* elements can be copied to a newly alloc'ed vec if one must be
8756-
* created.
8757-
*
8758-
* 3. Dst vec ptr (i.e. ptr to ptr to rust_vec).
8759-
*
8760-
* 4. Src vec (i.e. ptr to rust_vec).
8761-
*
8762-
* 5. Flag indicating whether to skip trailing null on dst.
8763-
*
8764-
*/
8765-
8766-
auto ty = T_fn([T_taskptr(tn),
8767-
T_ptr(T_tydesc(tn)),
8768-
T_ptr(T_tydesc(tn)),
8769-
T_ptr(T_opaque_vec_ptr()),
8770-
T_opaque_vec_ptr(), T_bool()],
8771-
T_void());
8772-
8773-
auto llfn = decl_fastcall_fn(llmod, abi::vec_append_glue_name(), ty);
8774-
ret llfn;
8775-
}
8776-
8777-
87788744
fn vec_fill(&@block_ctxt bcx, ValueRef v) -> ValueRef {
87798745
ret bcx.build.Load(bcx.build.GEP(v, [C_int(0),
87808746
C_int(abi::vec_elt_fill)]));
@@ -8787,8 +8753,7 @@ fn vec_p0(&@block_ctxt bcx, ValueRef v) -> ValueRef {
87878753
}
87888754

87898755
fn make_glues(ModuleRef llmod, &type_names tn) -> @glue_fns {
8790-
ret @rec(no_op_type_glue = decl_no_op_type_glue(llmod, tn),
8791-
vec_append_glue = make_vec_append_glue(llmod, tn));
8756+
ret @rec(no_op_type_glue = decl_no_op_type_glue(llmod, tn));
87928757
}
87938758

87948759
fn make_common_glue(&session::session sess, &str output) {

src/rt/rust_internal.h

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -206,19 +206,27 @@ struct rust_timer {
206206

207207
#include "rust_util.h"
208208

209+
typedef void CDECL (glue_fn)(void *, rust_task *, void *,
210+
const type_desc **, void *);
211+
typedef void CDECL (cmp_glue_fn)(void *, rust_task *, void *,
212+
const type_desc **,
213+
void *, void *, int8_t);
214+
215+
209216
struct type_desc {
210217
// First part of type_desc is known to compiler.
211218
// first_param = &descs[1] if dynamic, null if static.
212219
const type_desc **first_param;
213220
size_t size;
214221
size_t align;
215-
uintptr_t copy_glue_off;
216-
uintptr_t drop_glue_off;
217-
uintptr_t free_glue_off;
218-
uintptr_t sever_glue_off; // For GC.
219-
uintptr_t mark_glue_off; // For GC.
220-
uintptr_t obj_drop_glue_off; // For custom destructors.
222+
glue_fn *take_glue;
223+
glue_fn *drop_glue;
224+
glue_fn *free_glue;
225+
glue_fn *sever_glue; // For GC.
226+
glue_fn *mark_glue; // For GC.
227+
glue_fn *obj_drop_glue; // For custom destructors.
221228
uintptr_t is_stateful;
229+
cmp_glue_fn *cmp_glue;
222230

223231
// Residual fields past here are known only to runtime.
224232
UT_hash_handle hh;

src/rt/rust_upcall.cpp

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,7 @@ upcall_vec_grow(rust_task *task,
415415
*
416416
* Step 3 is a bit tricky. We don't know how to properly copy the
417417
* elements in the runtime (all we have are bits in a buffer; no
418-
* type infromation and no copy glue). What we do instead is set the
418+
* type information and no copy glue). What we do instead is set the
419419
* need_copy outparam flag to indicate to our caller (vec-copy glue)
420420
* that we need the copies performed for us.
421421
*/
@@ -436,6 +436,53 @@ upcall_vec_grow(rust_task *task,
436436
return v;
437437
}
438438

439+
// Copy elements from one vector to another,
440+
// dealing with reference counts
441+
static inline void
442+
copy_elements(rust_task *task, type_desc *elem_t,
443+
void *pdst, void *psrc, size_t n)
444+
{
445+
char *dst = (char *)pdst, *src = (char *)psrc;
446+
447+
// increment the refcount of each element of the vector
448+
if (elem_t->take_glue) {
449+
glue_fn *take_glue = elem_t->take_glue;
450+
size_t elem_size = elem_t->size;
451+
const type_desc **tydescs = elem_t->first_param;
452+
for (char *p = src; p < src+n; p += elem_size) {
453+
take_glue(NULL, task, NULL, tydescs, p);
454+
}
455+
}
456+
memmove(dst, src, n);
457+
}
458+
459+
extern "C" CDECL void
460+
upcall_vec_append(rust_task *task, type_desc *t, type_desc *elem_t,
461+
rust_vec **dst_ptr, rust_vec *src, bool skip_null)
462+
{
463+
LOG_UPCALL_ENTRY(task);
464+
rust_vec *dst = *dst_ptr;
465+
uintptr_t need_copy;
466+
size_t n_src_bytes = skip_null ? src->fill - 1 : src->fill;
467+
size_t n_dst_bytes = skip_null ? dst->fill - 1 : dst->fill;
468+
rust_vec *new_vec = upcall_vec_grow(task, dst, n_src_bytes,
469+
&need_copy, t);
470+
471+
if (need_copy) {
472+
// Copy any dst elements in, omitting null if doing str.
473+
copy_elements(task, elem_t, &new_vec->data, &dst->data, n_dst_bytes);
474+
}
475+
476+
// Copy any src elements in, carrying along null if doing str.
477+
void *new_end = (void *)((char *)new_vec->data + n_dst_bytes);
478+
copy_elements(task, elem_t, new_end, &src->data, src->fill);
479+
new_vec->fill = n_dst_bytes + src->fill;
480+
481+
// Write new_vec back through the alias we were given.
482+
*dst_ptr = new_vec;
483+
}
484+
485+
439486
extern "C" CDECL type_desc *
440487
upcall_get_type_desc(rust_task *task,
441488
void *curr_crate, // ignored, legacy compat.

src/rt/rustrt.def.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ upcall_start_thread
7373
upcall_trace_str
7474
upcall_trace_word
7575
upcall_vec_grow
76+
upcall_vec_append
7677
upcall_yield
7778
vec_alloc
7879
vec_alloc_mut

0 commit comments

Comments
 (0)