Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move the implementation of vec_append from llvm assembly to a regular upcall #471

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion mk/rt.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 0 additions & 4 deletions src/comp/back/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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";
}
Expand Down
5 changes: 5 additions & 0 deletions src/comp/back/upcall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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)))],
Expand Down
41 changes: 3 additions & 38 deletions src/comp/middle/trans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -3540,7 +3539,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,
Expand Down Expand Up @@ -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)]));
Expand All @@ -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) {
Expand Down
3 changes: 3 additions & 0 deletions src/rt/rust.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

/*
Expand Down
18 changes: 12 additions & 6 deletions src/rt/rust_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,20 +204,26 @@ 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.
// first_param = &descs[1] if dynamic, null if static.
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;
Expand Down
49 changes: 48 additions & 1 deletion src/rt/rust_upcall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand All @@ -436,6 +436,53 @@ 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)
{
LOG_UPCALL_ENTRY(task);
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.
Expand Down
2 changes: 1 addition & 1 deletion src/rt/rustrt.def.in
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ rust_process_wait
rust_ptr_eq
rust_run_program
rust_start
rust_vec_append_glue
size_of
squareroot
str_alloc
Expand Down Expand Up @@ -69,6 +68,7 @@ upcall_start_thread
upcall_trace_str
upcall_trace_word
upcall_vec_grow
upcall_vec_append
upcall_yield
vec_alloc
vec_alloc_mut
Expand Down
138 changes: 0 additions & 138 deletions src/rt/vec_append.ll

This file was deleted.