From 09a1b949071cd573cd171362e9c3b894105556c1 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 21 May 2012 18:36:52 -0700 Subject: [PATCH] Various changes for self-describing vecs --- src/rt/rust.cpp | 4 +- src/rt/rust_builtin.cpp | 36 ++++----- src/rt/rust_shape.h | 6 +- src/rt/rust_upcall.cpp | 39 ++++----- src/rt/rust_util.h | 42 ++++++---- src/rustc/back/upcall.rs | 20 +++-- src/rustc/middle/trans/base.rs | 29 +++++++ src/rustc/middle/trans/tvec.rs | 130 ++++++++++++++++++++---------- src/rustc/middle/trans/type_of.rs | 8 +- 9 files changed, 204 insertions(+), 110 deletions(-) diff --git a/src/rt/rust.cpp b/src/rt/rust.cpp index 2fed06854cb..4019c8701ac 100644 --- a/src/rt/rust.cpp +++ b/src/rt/rust.cpp @@ -13,7 +13,7 @@ command_line_args : public kernel_owned 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() { 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); diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index 97fbcf4953d..ce86bc0901b 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -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 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,13 +384,13 @@ 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, - strlen(dp->d_name), - "list_files_str"); + rust_vec_box *str = make_str(task->kernel, dp->d_name, + strlen(dp->d_name), + "list_files_str"); strings.push(str); } closedir(dirp); @@ -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'; } } diff --git a/src/rt/rust_shape.h b/src/rt/rust_shape.h index 5ebd794ab1d..77a253d2bb7 100644 --- a/src/rt/rust_shape.h +++ b/src/rt/rust_shape.h @@ -1110,9 +1110,9 @@ data::walk_variant1(tag_info &tinfo, tag_variant_t variant_id) { template std::pair data::get_vec_data_range(ptr dp) { - rust_vec* ptr = bump_dp(dp); - uint8_t* data = &ptr->data[0]; - return std::make_pair(data, data + ptr->fill); + rust_vec_box* ptr = bump_dp(dp); + uint8_t* data = &ptr->body.data[0]; + return std::make_pair(data, data + ptr->body.fill); } template diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index 6a9d663f8fd..667a511debf 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -445,10 +445,10 @@ upcall_s_str_new_shared(s_str_new_shared_args *args) { vec_size(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), - "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); + rust_vec_box* v = (rust_vec_box*) + task->kernel->malloc(fill + sizeof(rust_vec_box), + "str_concat"); + 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; diff --git a/src/rt/rust_util.h b/src/rt/rust_util.h index b517362df1f..3a7bd0b7d71 100644 --- a/src/rt/rust_util.h +++ b/src/rt/rust_util.h @@ -42,9 +42,16 @@ rust_vec uint8_t data[0]; }; +struct +rust_vec_box +{ + rust_opaque_box header; + rust_vec body; +}; + template inline size_t vec_size(size_t elems) { - return sizeof(rust_vec) + sizeof(T) * elems; + return sizeof(rust_vec_box) + sizeof(T) * elems; } template @@ -53,19 +60,20 @@ vec_data(rust_vec *v) { return reinterpret_cast(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(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(nstrs), + rust_vec_box *v = (rust_vec_box *) + kernel->malloc(vec_size(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; } diff --git a/src/rustc/back/upcall.rs b/src/rustc/back/upcall.rs index ec78b5bb946..6430632d5c0 100644 --- a/src/rustc/back/upcall.rs +++ b/src/rustc/back/upcall.rs @@ -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), diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 2fb4dd9877f..29e06334270 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -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; diff --git a/src/rustc/middle/trans/tvec.rs b/src/rustc/middle/trans/tvec.rs index bcc5bbc3fa0..a9b78918295 100644 --- a/src/rustc/middle/trans/tvec.rs +++ b/src/rustc/middle/trans/tvec.rs @@ -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); } // diff --git a/src/rustc/middle/trans/type_of.rs b/src/rustc/middle/trans/type_of.rs index 52d924df032..fedd7c713cf 100644 --- a/src/rustc/middle/trans/type_of.rs +++ b/src/rustc/middle/trans/type_of.rs @@ -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)) }