Various changes for self-describing vecs

This commit is contained in:
Brian Anderson 2012-05-21 18:36:52 -07:00
parent 846dfbc922
commit 09a1b94907
9 changed files with 204 additions and 110 deletions

View file

@ -13,7 +13,7 @@ command_line_args : public kernel_owned<command_line_args>
char **argv;
// [str] passed to rust_task::start.
rust_vec *args;
rust_vec_box *args;
command_line_args(rust_task *task,
int sys_argc,
@ -47,7 +47,7 @@ command_line_args : public kernel_owned<command_line_args>
~command_line_args() {
for (int i = 0; i < argc; ++i) {
rust_vec *s = ((rust_vec**)&args->data)[i];
rust_vec *s = ((rust_vec**)&args->body.data)[i];
kernel->free(s);
}
kernel->free(args);

View file

@ -85,7 +85,7 @@ rust_getcwd() {
}
#if defined(__WIN32__)
extern "C" CDECL rust_vec *
extern "C" CDECL rust_vec_box *
rust_env_pairs() {
rust_task *task = rust_get_current_task();
size_t envc = 0;
@ -102,7 +102,7 @@ rust_env_pairs() {
for (size_t i = 0; i < envc; ++i) {
size_t n = strlen(c);
rust_str *str = make_str(task->kernel, c, n, "str");
((rust_str**)&v->data)[i] = str;
((rust_str**)&v->body.data)[i] = str;
c += n + 1;
}
if (ch) {
@ -111,7 +111,7 @@ rust_env_pairs() {
return v;
}
#else
extern "C" CDECL rust_vec *
extern "C" CDECL rust_vec_box *
rust_env_pairs() {
rust_task *task = rust_get_current_task();
#ifdef __APPLE__
@ -140,14 +140,14 @@ unsupervise() {
}
extern "C" CDECL void
vec_reserve_shared(type_desc* ty, rust_vec** vp,
vec_reserve_shared(type_desc* ty, rust_vec_box** vp,
size_t n_elts) {
rust_task *task = rust_get_current_task();
reserve_vec_exact(task, vp, n_elts * ty->size);
}
extern "C" CDECL void
str_reserve_shared(rust_vec** sp,
str_reserve_shared(rust_vec_box** sp,
size_t n_elts) {
rust_task *task = rust_get_current_task();
reserve_vec_exact(task, sp, n_elts + 1);
@ -169,13 +169,13 @@ vec_from_buf_shared(type_desc *ty, void *ptr, size_t count) {
}
extern "C" CDECL void
rust_str_push(rust_vec** sp, uint8_t byte) {
rust_str_push(rust_vec_box** sp, uint8_t byte) {
rust_task *task = rust_get_current_task();
size_t fill = (*sp)->fill;
size_t fill = (*sp)->body.fill;
reserve_vec(task, sp, fill + 1);
(*sp)->data[fill-1] = byte;
(*sp)->data[fill] = 0;
(*sp)->fill = fill + 1;
(*sp)->body.data[fill-1] = byte;
(*sp)->body.data[fill] = 0;
(*sp)->body.fill = fill + 1;
}
extern "C" CDECL rust_vec*
@ -373,7 +373,7 @@ rust_list_files(rust_str *path) {
array_list<rust_str*> strings;
#if defined(__WIN32__)
WIN32_FIND_DATA FindFileData;
HANDLE hFind = FindFirstFile((char*)path->data, &FindFileData);
HANDLE hFind = FindFirstFile((char*)path->body.data, &FindFileData);
if (hFind != INVALID_HANDLE_VALUE) {
do {
rust_str *str = make_str(task->kernel, FindFileData.cFileName,
@ -384,11 +384,11 @@ rust_list_files(rust_str *path) {
FindClose(hFind);
}
#else
DIR *dirp = opendir((char*)path->data);
DIR *dirp = opendir((char*)path->body.data);
if (dirp) {
struct dirent *dp;
while ((dp = readdir(dirp))) {
rust_vec *str = make_str(task->kernel, dp->d_name,
rust_vec_box *str = make_str(task->kernel, dp->d_name,
strlen(dp->d_name),
"list_files_str");
strings.push(str);
@ -520,9 +520,9 @@ void tm_to_rust_tm(tm* in_tm, rust_tm* out_tm, int32_t gmtoff,
if (zone != NULL) {
size_t size = strlen(zone);
str_reserve_shared(&out_tm->tm_zone, size);
memcpy(out_tm->tm_zone->data, zone, size);
out_tm->tm_zone->fill = size + 1;
out_tm->tm_zone->data[size] = '\0';
memcpy(out_tm->tm_zone->body.data, zone, size);
out_tm->tm_zone->body.fill = size + 1;
out_tm->tm_zone->body.data[size] = '\0';
}
}

View file

@ -1110,9 +1110,9 @@ data<T,U>::walk_variant1(tag_info &tinfo, tag_variant_t variant_id) {
template<typename T,typename U>
std::pair<uint8_t *,uint8_t *>
data<T,U>::get_vec_data_range(ptr dp) {
rust_vec* ptr = bump_dp<rust_vec*>(dp);
uint8_t* data = &ptr->data[0];
return std::make_pair(data, data + ptr->fill);
rust_vec_box* ptr = bump_dp<rust_vec_box*>(dp);
uint8_t* data = &ptr->body.data[0];
return std::make_pair(data, data + ptr->body.fill);
}
template<typename T,typename U>

View file

@ -445,10 +445,10 @@ upcall_s_str_new_shared(s_str_new_shared_args *args) {
vec_size<char>(str_fill),
"str_new_shared");
rust_str *str = (rust_str *)box_body(args->retval);
str->fill = str_fill;
str->alloc = str_alloc;
memcpy(&str->data, args->cstr, args->len);
str->data[args->len] = '\0';
str->body.fill = str_fill;
str->body.alloc = str_alloc;
memcpy(&str->body.data, args->cstr, args->len);
str->body.data[args->len] = '\0';
}
extern "C" CDECL rust_opaque_box*
@ -460,7 +460,7 @@ upcall_str_new_shared(const char *cstr, size_t len) {
struct s_vec_grow_args {
rust_vec** vp;
rust_vec_box** vp;
size_t new_sz;
};
@ -469,37 +469,38 @@ upcall_s_vec_grow(s_vec_grow_args *args) {
rust_task *task = rust_get_current_task();
LOG_UPCALL_ENTRY(task);
reserve_vec(task, args->vp, args->new_sz);
(*args->vp)->fill = args->new_sz;
(*args->vp)->body.fill = args->new_sz;
}
extern "C" CDECL void
upcall_vec_grow(rust_vec** vp, size_t new_sz) {
upcall_vec_grow(rust_vec_box** vp, size_t new_sz) {
s_vec_grow_args args = {vp, new_sz};
UPCALL_SWITCH_STACK(&args, upcall_s_vec_grow);
}
struct s_str_concat_args {
rust_vec* lhs;
rust_vec* rhs;
rust_vec* retval;
rust_vec_box* lhs;
rust_vec_box* rhs;
rust_vec_box* retval;
};
extern "C" CDECL void
upcall_s_str_concat(s_str_concat_args *args) {
rust_vec *lhs = args->lhs;
rust_vec *rhs = args->rhs;
rust_vec *lhs = &args->lhs->body;
rust_vec *rhs = &args->rhs->body;
rust_task *task = rust_get_current_task();
size_t fill = lhs->fill + rhs->fill - 1;
rust_vec* v = (rust_vec*)task->kernel->malloc(fill + sizeof(rust_vec),
rust_vec_box* v = (rust_vec_box*)
task->kernel->malloc(fill + sizeof(rust_vec_box),
"str_concat");
v->fill = v->alloc = fill;
memmove(&v->data[0], &lhs->data[0], lhs->fill - 1);
memmove(&v->data[lhs->fill - 1], &rhs->data[0], rhs->fill);
v->body.fill = v->body.alloc = fill;
memmove(&v->body.data[0], &lhs->data[0], lhs->fill - 1);
memmove(&v->body.data[lhs->fill - 1], &rhs->data[0], rhs->fill);
args->retval = v;
}
extern "C" CDECL rust_vec*
upcall_str_concat(rust_vec* lhs, rust_vec* rhs) {
extern "C" CDECL rust_vec_box*
upcall_str_concat(rust_vec_box* lhs, rust_vec_box* rhs) {
s_str_concat_args args = {lhs, rhs, 0};
UPCALL_SWITCH_STACK(&args, upcall_s_str_concat);
return args.retval;

View file

@ -42,9 +42,16 @@ rust_vec
uint8_t data[0];
};
struct
rust_vec_box
{
rust_opaque_box header;
rust_vec body;
};
template <typename T>
inline size_t vec_size(size_t elems) {
return sizeof(rust_vec) + sizeof(T) * elems;
return sizeof(rust_vec_box) + sizeof(T) * elems;
}
template <typename T>
@ -53,19 +60,20 @@ vec_data(rust_vec *v) {
return reinterpret_cast<T*>(v->data);
}
inline void reserve_vec_exact(rust_task* task, rust_vec** vpp, size_t size) {
if (size > (*vpp)->alloc) {
*vpp = (rust_vec*)task->kernel
->realloc(*vpp, size + sizeof(rust_vec));
(*vpp)->alloc = size;
inline void reserve_vec_exact(rust_task* task, rust_vec_box** vpp,
size_t size) {
if (size > (*vpp)->body.alloc) {
*vpp = (rust_vec_box*)task->kernel
->realloc(*vpp, size + sizeof(rust_vec_box));
(*vpp)->body.alloc = size;
}
}
inline void reserve_vec(rust_task* task, rust_vec** vpp, size_t size) {
inline void reserve_vec(rust_task* task, rust_vec_box** vpp, size_t size) {
reserve_vec_exact(task, vpp, next_power_of_two(size));
}
typedef rust_vec rust_str;
typedef rust_vec_box rust_str;
inline rust_str *
make_str(rust_kernel* kernel, const char* c, size_t strlen,
@ -74,24 +82,24 @@ make_str(rust_kernel* kernel, const char* c, size_t strlen,
size_t str_alloc = str_fill;
rust_str *str = (rust_str *)
kernel->malloc(vec_size<char>(str_fill), name);
str->fill = str_fill;
str->alloc = str_alloc;
memcpy(&str->data, c, strlen);
str->data[strlen] = '\0';
str->body.fill = str_fill;
str->body.alloc = str_alloc;
memcpy(&str->body.data, c, strlen);
str->body.data[strlen] = '\0';
return str;
}
inline rust_vec *
inline rust_vec_box *
make_str_vec(rust_kernel* kernel, size_t nstrs, char **strs) {
rust_vec *v = (rust_vec *)
kernel->malloc(vec_size<rust_vec*>(nstrs),
rust_vec_box *v = (rust_vec_box *)
kernel->malloc(vec_size<rust_vec_box*>(nstrs),
"str vec interior");
v->fill = v->alloc = sizeof(rust_vec*) * nstrs;
v->body.fill = v->body.alloc = sizeof(rust_vec_box*) * nstrs;
for (size_t i = 0; i < nstrs; ++i) {
rust_str *str = make_str(kernel, strs[i],
strlen(strs[i]),
"str");
((rust_str**)&v->data)[i] = str;
((rust_str**)&v->body.data)[i] = str;
}
return v;
}

View file

@ -3,8 +3,8 @@ import driver::session;
import middle::trans::base;
import middle::trans::common::{T_fn, T_i1, T_i8, T_i32,
T_int, T_nil,
T_opaque_vec, T_ptr,
T_size_t, T_void};
T_opaque_vec, T_ptr, T_unique_ptr,
T_size_t, T_void, T_vec2};
import lib::llvm::{type_names, ModuleRef, ValueRef, TypeRef};
type upcalls =
@ -13,6 +13,7 @@ type upcalls =
malloc: ValueRef,
free: ValueRef,
exchange_malloc: ValueRef,
exchange_malloc_dyn: ValueRef,
exchange_free: ValueRef,
validate_box: ValueRef,
shared_malloc: ValueRef,
@ -51,7 +52,6 @@ fn declare_upcalls(targ_cfg: @session::config,
let int_t = T_int(targ_cfg);
let size_t = T_size_t(targ_cfg);
let opaque_vec_t = T_opaque_vec(targ_cfg);
ret @{_fail: dv("fail", [T_ptr(T_i8()),
T_ptr(T_i8()),
@ -67,6 +67,10 @@ fn declare_upcalls(targ_cfg: @session::config,
exchange_malloc:
nothrow(d("exchange_malloc", [T_ptr(tydesc_type)],
T_ptr(T_i8()))),
exchange_malloc_dyn:
nothrow(d("exchange_malloc_dyn",
[T_ptr(tydesc_type), int_t],
T_ptr(T_i8()))),
exchange_free:
nothrow(dv("exchange_free", [T_ptr(T_i8())])),
validate_box:
@ -81,17 +85,17 @@ fn declare_upcalls(targ_cfg: @session::config,
mark:
d("mark", [T_ptr(T_i8())], int_t),
vec_grow:
nothrow(dv("vec_grow", [T_ptr(T_ptr(opaque_vec_t)), int_t])),
nothrow(dv("vec_grow", [T_ptr(T_ptr(T_i8())), int_t])),
str_new_uniq:
nothrow(d("str_new_uniq", [T_ptr(T_i8()), int_t],
T_ptr(opaque_vec_t))),
T_ptr(T_i8()))),
str_new_shared:
nothrow(d("str_new_shared", [T_ptr(T_i8()), int_t],
T_ptr(T_i8()))),
str_concat:
nothrow(d("str_concat", [T_ptr(opaque_vec_t),
T_ptr(opaque_vec_t)],
T_ptr(opaque_vec_t))),
nothrow(d("str_concat", [T_ptr(T_i8()),
T_ptr(T_i8())],
T_ptr(T_i8()))),
cmp_type:
dv("cmp_type",
[T_ptr(T_i1()), T_ptr(tydesc_type),

View file

@ -417,6 +417,33 @@ fn malloc_unique(bcx: block, t: ty::t) -> {box: ValueRef, body: ValueRef} {
ret {box: box, body: body};
}
fn malloc_unique_dyn_raw(bcx: block, t: ty::t, size: ValueRef) -> ValueRef {
let _icx = bcx.insn_ctxt("malloc_unique_box_raw");
let ccx = bcx.ccx();
// Grab the TypeRef type of box_ptr, because that's what trans_raw_malloc
// wants.
let box_ptr = ty::mk_imm_uniq(ccx.tcx, t);
let llty = type_of(ccx, box_ptr);
// Get the tydesc for the body:
let mut static_ti = none;
let lltydesc = get_tydesc(ccx, t, static_ti);
lazily_emit_all_tydesc_glue(ccx, static_ti);
// Allocate space:
let rval = Call(bcx, ccx.upcalls.exchange_malloc_dyn, [lltydesc, size]);
ret PointerCast(bcx, rval, llty);
}
fn malloc_unique_dyn(bcx: block, t: ty::t, size: ValueRef
) -> {box: ValueRef, body: ValueRef} {
let _icx = bcx.insn_ctxt("malloc_unique_box");
let box = malloc_unique_dyn_raw(bcx, t, size);
let body = GEPi(bcx, box, [0u, abi::box_field_body]);
ret {box: box, body: body};
}
// Type descriptor and type glue stuff
fn get_tydesc_simple(ccx: @crate_ctxt, t: ty::t) -> ValueRef {
@ -560,7 +587,9 @@ fn make_generic_glue_inner(ccx: @crate_ctxt, t: ty::t,
// the caller has no idea if it's dealing with something that can be
// passed by value.
#error("%?", ty::get(t));
let llty = T_ptr(type_of(ccx, t));
#error("%?", ty_str(ccx.tn, llty));
let bcx = top_scope_block(fcx, none);
let lltop = bcx.llbb;

View file

@ -21,6 +21,24 @@ fn set_fill(bcx: block, vptr: ValueRef, fill: ValueRef) {
fn get_alloc(bcx: block, vptr: ValueRef) -> ValueRef {
Load(bcx, GEPi(bcx, vptr, [0u, abi::vec_elt_alloc]))
}
fn get_bodyptr(bcx: block, vptr: ValueRef, vec_ty: ty::t) -> ValueRef {
let ccx = bcx.ccx();
alt ty::get(vec_ty).struct {
ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq)
| ty::ty_vec(_) | ty::ty_str {
let boxptr = PointerCast(bcx, vptr, T_ptr(T_box_header(ccx)));
let bodyptr = GEPi(bcx, boxptr, [1u]);
let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty);
let llunit_ty = type_of::type_of(ccx, unit_ty);
PointerCast(bcx, bodyptr, T_ptr(T_vec(ccx, llunit_ty)))
}
_ {
vptr
}
}
}
fn get_dataptr(bcx: block, vptr: ValueRef, unit_ty: TypeRef)
-> ValueRef {
let _icx = bcx.insn_ctxt("tvec::get_dataptr");
@ -35,41 +53,55 @@ fn pointer_add(bcx: block, ptr: ValueRef, bytes: ValueRef) -> ValueRef {
ret PointerCast(bcx, InBoundsGEP(bcx, bptr, [bytes]), old_ty);
}
fn alloc_uniq_raw(bcx: block, fill: ValueRef, alloc: ValueRef) -> result {
fn alloc_uniq_raw(bcx: block, unit_ty: ty::t,
fill: ValueRef, alloc: ValueRef) -> result {
let _icx = bcx.insn_ctxt("tvec::alloc_uniq_raw");
let ccx = bcx.ccx();
let llvecty = ccx.opaque_vec_type;
let llunitty = type_of::type_of(ccx, unit_ty);
let llvecty = T_vec(ccx, llunitty);
let vecsize = Add(bcx, alloc, llsize_of(ccx, llvecty));
let vecptr = shared_malloc(bcx, T_ptr(llvecty), vecsize);
Store(bcx, fill, GEPi(bcx, vecptr, [0u, abi::vec_elt_fill]));
Store(bcx, alloc, GEPi(bcx, vecptr, [0u, abi::vec_elt_alloc]));
ret {bcx: bcx, val: vecptr};
let vecbodyty = unit_ty; // FIXME: This is not the correct type
let {box, body} = base::malloc_unique_dyn(bcx, vecbodyty, vecsize);
let boxptr = PointerCast(bcx, box,
T_unique_ptr(T_unique(bcx.ccx(), llvecty)));
let bodyptr = PointerCast(bcx, body, T_ptr(llvecty));
Store(bcx, fill, GEPi(bcx, bodyptr, [0u, abi::vec_elt_fill]));
Store(bcx, alloc, GEPi(bcx, bodyptr, [0u, abi::vec_elt_alloc]));
ret {bcx: bcx, val: boxptr};
}
fn alloc_uniq(bcx: block, llunitty: TypeRef, elts: uint) -> result {
fn alloc_uniq(bcx: block, unit_ty: ty::t, elts: uint) -> result {
let _icx = bcx.insn_ctxt("tvec::alloc_uniq");
let ccx = bcx.ccx();
let llvecty = T_vec(ccx, llunitty);
let llunitty = type_of::type_of(ccx, unit_ty);
let unit_sz = llsize_of(ccx, llunitty);
let fill = Mul(bcx, C_uint(ccx, elts), unit_sz);
let alloc = if elts < 4u { Mul(bcx, C_int(ccx, 4), unit_sz) }
else { fill };
let {bcx: bcx, val: vptr} = alloc_uniq_raw(bcx, fill, alloc);
let vptr = PointerCast(bcx, vptr, T_ptr(llvecty));
let {bcx: bcx, val: vptr} = alloc_uniq_raw(bcx, unit_ty, fill, alloc);
ret {bcx: bcx, val: vptr};
}
fn duplicate_uniq(bcx: block, vptr: ValueRef, vec_ty: ty::t) -> result {
let _icx = bcx.insn_ctxt("tvec::duplicate_uniq");
let ccx = bcx.ccx();
let fill = get_fill(bcx, vptr);
let body_ptr = get_bodyptr(bcx, vptr, vec_ty);
let fill = get_fill(bcx, body_ptr);
let size = Add(bcx, fill, llsize_of(ccx, ccx.opaque_vec_type));
let newptr = shared_malloc(bcx, val_ty(vptr), size);
call_memmove(bcx, newptr, vptr, size);
let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty);
Store(bcx, fill, GEPi(bcx, newptr, [0u, abi::vec_elt_alloc]));
let llunitty = type_of::type_of(ccx, unit_ty);
let llvecty = T_vec(ccx, llunitty);
let vecbodyty = unit_ty; // FIXME: This is not the correct type
let {box: newptr, body: new_body_ptr} =
base::malloc_unique_dyn(bcx, vecbodyty, size);
let newptr = PointerCast(bcx, newptr,
T_unique_ptr(T_unique(bcx.ccx(), llvecty)));
let new_body_ptr = PointerCast(bcx, new_body_ptr, T_ptr(llvecty));
call_memmove(bcx, new_body_ptr, body_ptr, size);
Store(bcx, fill, GEPi(bcx, new_body_ptr, [0u, abi::vec_elt_alloc]));
let bcx = if ty::type_needs_drop(bcx.tcx(), unit_ty) {
iter_vec(bcx, newptr, vec_ty, base::take_ty)
} else { bcx };
@ -133,9 +165,10 @@ fn trans_evec(bcx: block, args: [@ast::expr],
{bcx: bcx, val: p, dataptr: vp}
}
ast::vstore_uniq {
let {bcx, val} = alloc_uniq(bcx, llunitty, args.len());
let {bcx, val} = alloc_uniq(bcx, unit_ty, args.len());
add_clean_free(bcx, val, true);
let dataptr = get_dataptr(bcx, val, llunitty);
let body = get_bodyptr(bcx, val, vec_ty);
let dataptr = get_dataptr(bcx, body, llunitty);
{bcx: bcx, val: val, dataptr: dataptr}
}
ast::vstore_box {
@ -216,8 +249,9 @@ fn get_base_and_len(cx: block, v: ValueRef, e_ty: ty::t)
(base, len)
}
ty::vstore_uniq {
let base = tvec::get_dataptr(cx, v, llunitty);
let len = tvec::get_fill(cx, v);
let body = tvec::get_bodyptr(cx, v, vec_ty);
let base = tvec::get_dataptr(cx, body, llunitty);
let len = tvec::get_fill(cx, body);
(base, len)
}
ty::vstore_box {
@ -249,7 +283,9 @@ fn trans_estr(bcx: block, s: str, vstore: ast::vstore,
ast::vstore_uniq {
let cs = PointerCast(bcx, C_cstr(ccx, s), T_ptr(T_i8()));
let len = C_uint(ccx, str::len(s));
Call(bcx, ccx.upcalls.str_new_uniq, [cs, len])
let c = Call(bcx, ccx.upcalls.str_new_uniq, [cs, len]);
PointerCast(bcx, c,
T_unique_ptr(T_unique(ccx, T_vec(ccx, T_i8()))))
}
ast::vstore_box {
@ -274,19 +310,23 @@ fn trans_append(bcx: block, vec_ty: ty::t, lhsptr: ValueRef,
let lhs = Load(bcx, lhsptr);
let self_append = ICmp(bcx, lib::llvm::IntEQ, lhs, rhs);
let lfill = get_fill(bcx, lhs);
let rfill = get_fill(bcx, rhs);
let lbody = get_bodyptr(bcx, lhs, vec_ty);
let rbody = get_bodyptr(bcx, rhs, vec_ty);
let lfill = get_fill(bcx, lbody);
let rfill = get_fill(bcx, rbody);
let mut new_fill = Add(bcx, lfill, rfill);
if strings { new_fill = Sub(bcx, new_fill, C_int(ccx, 1)); }
let opaque_lhs = PointerCast(bcx, lhsptr,
T_ptr(T_ptr(ccx.opaque_vec_type)));
T_ptr(T_ptr(T_i8())));
Call(bcx, ccx.upcalls.vec_grow,
[opaque_lhs, new_fill]);
// Was overwritten if we resized
let lhs = Load(bcx, lhsptr);
let rhs = Select(bcx, self_append, lhs, rhs);
let lhs_data = get_dataptr(bcx, lhs, llunitty);
let lbody = get_bodyptr(bcx, lhs, vec_ty);
let lhs_data = get_dataptr(bcx, lbody, llunitty);
let mut lhs_off = lfill;
if strings { lhs_off = Sub(bcx, lhs_off, C_int(ccx, 1)); }
let write_ptr = pointer_add(bcx, lhs_data, lhs_off);
@ -311,18 +351,18 @@ fn trans_append_literal(bcx: block, vptrptr: ValueRef, vec_ty: ty::t,
let scratch = base::alloca(bcx, elt_llty);
for vec::each(vals) {|val|
bcx = base::trans_expr_save_in(bcx, val, scratch);
let vptr = Load(bcx, vptrptr);
let vptr = get_bodyptr(bcx, Load(bcx, vptrptr), vec_ty);
let old_fill = get_fill(bcx, vptr);
let new_fill = Add(bcx, old_fill, elt_sz);
let do_grow = ICmp(bcx, lib::llvm::IntUGT, new_fill,
get_alloc(bcx, vptr));
bcx = base::with_cond(bcx, do_grow) {|bcx|
let pt = PointerCast(bcx, vptrptr,
T_ptr(T_ptr(ccx.opaque_vec_type)));
T_ptr(T_ptr(T_i8())));
Call(bcx, ccx.upcalls.vec_grow, [pt, new_fill]);
bcx
};
let vptr = Load(bcx, vptrptr);
let vptr = get_bodyptr(bcx, Load(bcx, vptrptr), vec_ty);
set_fill(bcx, vptr, new_fill);
let targetptr = pointer_add(bcx, get_dataptr(bcx, vptr, elt_llty),
old_fill);
@ -336,23 +376,30 @@ fn trans_add(bcx: block, vec_ty: ty::t, lhs: ValueRef,
let _icx = bcx.insn_ctxt("tvec::trans_add");
let ccx = bcx.ccx();
if ty::get(vec_ty).struct == ty::ty_str {
let n = Call(bcx, ccx.upcalls.str_concat, [lhs, rhs]);
ret base::store_in_dest(bcx, n, dest);
}
let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty);
let llunitty = type_of::type_of(ccx, unit_ty);
let lhs_fill = get_fill(bcx, lhs);
let rhs_fill = get_fill(bcx, rhs);
if ty::get(vec_ty).struct == ty::ty_str {
let lhs = PointerCast(bcx, lhs, T_ptr(T_i8()));
let rhs = PointerCast(bcx, rhs, T_ptr(T_i8()));
let n = Call(bcx, ccx.upcalls.str_concat, [lhs, rhs]);
let n = PointerCast(
bcx, n, T_unique_ptr(T_unique(ccx, T_vec(ccx, llunitty))));
ret base::store_in_dest(bcx, n, dest);
}
let lhs_body = get_bodyptr(bcx, lhs, vec_ty);
let rhs_body = get_bodyptr(bcx, rhs, vec_ty);
let lhs_fill = get_fill(bcx, lhs_body);
let rhs_fill = get_fill(bcx, rhs_body);
let new_fill = Add(bcx, lhs_fill, rhs_fill);
let mut {bcx: bcx, val: new_vec_ptr} =
alloc_uniq_raw(bcx, new_fill, new_fill);
new_vec_ptr = PointerCast(bcx, new_vec_ptr, T_ptr(T_vec(ccx, llunitty)));
alloc_uniq_raw(bcx, unit_ty, new_fill, new_fill);
let new_vec_body_ptr = get_bodyptr(bcx, new_vec_ptr, vec_ty);
let write_ptr_ptr = do_spill_noroot
(bcx, get_dataptr(bcx, new_vec_ptr, llunitty));
(bcx, get_dataptr(bcx, new_vec_body_ptr, llunitty));
let copy_fn = fn@(bcx: block, addr: ValueRef,
_ty: ty::t) -> block {
let ccx = bcx.ccx();
@ -408,16 +455,17 @@ fn iter_vec_uniq(bcx: block, vptr: ValueRef, vec_ty: ty::t,
let ccx = bcx.ccx();
let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty);
let llunitty = type_of::type_of(ccx, unit_ty);
let vptr = PointerCast(bcx, vptr, T_ptr(T_vec(ccx, llunitty)));
let data_ptr = get_dataptr(bcx, vptr, llunitty);
let body_ptr = get_bodyptr(bcx, vptr, vec_ty);
let data_ptr = get_dataptr(bcx, body_ptr, llunitty);
iter_vec_raw(bcx, data_ptr, vec_ty, fill, f)
}
fn iter_vec(bcx: block, vptr: ValueRef, vec_ty: ty::t,
f: iter_vec_block) -> block {
let _icx = bcx.insn_ctxt("tvec::iter_vec");
let vptr = PointerCast(bcx, vptr, T_ptr(bcx.ccx().opaque_vec_type));
ret iter_vec_uniq(bcx, vptr, vec_ty, get_fill(bcx, vptr), f);
let body_ptr = get_bodyptr(bcx, vptr, vec_ty);
let fill = get_fill(bcx, body_ptr);
ret iter_vec_uniq(bcx, vptr, vec_ty, fill, f);
}
//

View file

@ -85,7 +85,9 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
ty::ty_uint(t) { T_uint_ty(cx, t) }
ty::ty_float(t) { T_float_ty(cx, t) }
ty::ty_estr(ty::vstore_uniq) |
ty::ty_str { T_ptr(T_vec(cx, T_i8())) }
ty::ty_str {
T_unique_ptr(T_unique(cx, T_vec(cx, T_i8())))
}
ty::ty_enum(did, _) { type_of_enum(cx, did, t) }
ty::ty_estr(ty::vstore_box) { T_box_ptr(T_box(cx, T_i8())) }
ty::ty_evec(mt, ty::vstore_box) |
@ -93,7 +95,9 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
ty::ty_opaque_box { T_box_ptr(T_box(cx, T_i8())) }
ty::ty_uniq(mt) { T_unique_ptr(T_unique(cx, type_of(cx, mt.ty))) }
ty::ty_evec(mt, ty::vstore_uniq) |
ty::ty_vec(mt) { T_ptr(T_vec(cx, type_of(cx, mt.ty))) }
ty::ty_vec(mt) {
T_unique_ptr(T_unique(cx, T_vec(cx, type_of(cx, mt.ty))))
}
ty::ty_ptr(mt) { T_ptr(type_of(cx, mt.ty)) }
ty::ty_rptr(_, mt) { T_ptr(type_of(cx, mt.ty)) }