diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 21b9549cf822979a1bd835c78f44caf98da140b1..d46a47f0bd0e7d6d98eed38bedfc016f447be13b 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -706,12 +706,6 @@ fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) { let bcx = drop_ty(bcx, body, body_mt.ty); trans_free(bcx, v) } - - ty::ty_estr(ty::vstore_box) { - let v = PointerCast(bcx, v, type_of(ccx, t)); - trans_free(bcx, v) - } - ty::ty_opaque_box { let v = PointerCast(bcx, v, type_of(ccx, t)); let td = Load(bcx, GEPi(bcx, v, [0u, abi::box_field_tydesc])); @@ -725,8 +719,11 @@ fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) { uniq::make_free_glue(bcx, v, t) } ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) | + ty::ty_evec(_, ty::vstore_box) | ty::ty_estr(ty::vstore_box) | ty::ty_vec(_) | ty::ty_str { - tvec::make_free_glue(bcx, PointerCast(bcx, v, type_of(ccx, t)), t) + make_free_glue(bcx, v, + tvec::expand_boxed_vec_ty(bcx.tcx(), t)); + ret; } ty::ty_evec(_, _) { bcx.sess().unimpl("trans::base::make_free_glue on other evec"); @@ -794,6 +791,9 @@ fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) { ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) { free_ty(bcx, Load(bcx, v0), t) } + ty::ty_unboxed_vec(_) { + tvec::make_drop_glue_unboxed(bcx, v0, t) + } ty::ty_res(did, inner, substs) { trans_res_drop(bcx, v0, did, inner, substs.tps) } diff --git a/src/rustc/middle/trans/shape.rs b/src/rustc/middle/trans/shape.rs index cfd779460eb34b8a7bb35909a433236a7858828a..1d35d6548ae001fbf670c26dd05a35b88d419301 100644 --- a/src/rustc/middle/trans/shape.rs +++ b/src/rustc/middle/trans/shape.rs @@ -277,8 +277,7 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t) -> [u8] { } ty::ty_evec(mt, ty::vstore_uniq) | ty::ty_vec(mt) { - shape_of(ccx, - ty::mk_imm_uniq(ccx.tcx, ty::mk_unboxed_vec(ccx.tcx, mt))) + shape_of(ccx, tvec::expand_boxed_vec_ty(ccx.tcx, t)) } ty::ty_estr(ty::vstore_fixed(n)) { diff --git a/src/rustc/middle/trans/tvec.rs b/src/rustc/middle/trans/tvec.rs index 1861f690f9eacbecc045a470cb546784d779829f..3a543b968b762becd3677b92dc64bdefadba0a00 100644 --- a/src/rustc/middle/trans/tvec.rs +++ b/src/rustc/middle/trans/tvec.rs @@ -5,13 +5,35 @@ import base::{call_memmove, INIT, copy_val, load_if_immediate, get_tydesc, sub_block, do_spill_noroot, - dest, bcx_icx, non_gc_box_cast}; + dest, bcx_icx, non_gc_box_cast, + heap, heap_exchange, heap_shared}; import syntax::codemap::span; import shape::llsize_of; import build::*; import common::*; import util::ppaux::ty_to_str; +// Boxed vector types are in some sense currently a "shorthand" for a box +// containing an unboxed vector. This expands a boxed vector type into such an +// expanded type. It doesn't respect mutability, but that doesn't matter at +// this point. +fn expand_boxed_vec_ty(tcx: ty::ctxt, t: ty::t) -> ty::t { + let unit_ty = ty::sequence_element_type(tcx, t); + let unboxed_vec_ty = ty::mk_mut_unboxed_vec(tcx, unit_ty); + alt ty::get(t).struct { + ty::ty_vec(_) | ty::ty_str | + ty::ty_estr(ty::vstore_uniq) | ty::ty_evec(_, ty::vstore_uniq) { + ty::mk_imm_uniq(tcx, unboxed_vec_ty) + } + ty::ty_estr(ty::vstore_box) | ty::ty_evec(_, ty::vstore_box) { + ty::mk_imm_box(tcx, unboxed_vec_ty) + } + _ { tcx.sess.bug("non boxed-vec type \ + in tvec::expand_boxed_vec_ty"); + } + } +} + fn get_fill(bcx: block, vptr: ValueRef) -> ValueRef { let _icx = bcx.insn_ctxt("tvec::get_fill"); Load(bcx, GEPi(bcx, vptr, [0u, abi::vec_elt_fill])) @@ -40,21 +62,25 @@ 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, unit_ty: ty::t, - fill: ValueRef, alloc: ValueRef) -> result { - let _icx = bcx.insn_ctxt("tvec::alloc_uniq_raw"); +fn alloc_raw(bcx: block, unit_ty: ty::t, + fill: ValueRef, alloc: ValueRef, heap: heap) -> result { + let _icx = bcx.insn_ctxt("tvec::alloc_uniq"); let ccx = bcx.ccx(); let vecbodyty = ty::mk_mut_unboxed_vec(bcx.tcx(), unit_ty); let vecsize = Add(bcx, alloc, llsize_of(ccx, ccx.opaque_vec_type)); - let {box, body} = base::malloc_unique_dyn(bcx, vecbodyty, vecsize); + let {box, body} = base::malloc_general_dyn(bcx, vecbodyty, heap, vecsize); Store(bcx, fill, GEPi(bcx, body, [0u, abi::vec_elt_fill])); Store(bcx, alloc, GEPi(bcx, body, [0u, abi::vec_elt_alloc])); ret {bcx: bcx, val: box}; } +fn alloc_uniq_raw(bcx: block, unit_ty: ty::t, + fill: ValueRef, alloc: ValueRef) -> result { + alloc_raw(bcx, unit_ty, fill, alloc, heap_exchange) +} -fn alloc_uniq(bcx: block, unit_ty: ty::t, elts: uint) -> result { +fn alloc_vec(bcx: block, unit_ty: ty::t, elts: uint, heap: heap) -> result { let _icx = bcx.insn_ctxt("tvec::alloc_uniq"); let ccx = bcx.ccx(); let llunitty = type_of::type_of(ccx, unit_ty); @@ -63,7 +89,7 @@ fn alloc_uniq(bcx: block, unit_ty: ty::t, elts: uint) -> result { 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, unit_ty, fill, alloc); + let {bcx: bcx, val: vptr} = alloc_raw(bcx, unit_ty, fill, alloc, heap); ret {bcx: bcx, val: vptr}; } @@ -79,20 +105,18 @@ fn duplicate_uniq(bcx: block, vptr: ValueRef, vec_ty: ty::t) -> result { call_memmove(bcx, new_data_ptr, data_ptr, fill); let bcx = if ty::type_needs_drop(bcx.tcx(), unit_ty) { - iter_vec(bcx, newptr, vec_ty, base::take_ty) + iter_vec_raw(bcx, new_data_ptr, vec_ty, fill, base::take_ty) } else { bcx }; ret rslt(bcx, newptr); } -fn make_free_glue(bcx: block, vptr: ValueRef, vec_ty: ty::t) -> + +fn make_drop_glue_unboxed(bcx: block, vptr: ValueRef, vec_ty: ty::t) -> block { - let _icx = bcx.insn_ctxt("tvec::make_free_glue"); + let _icx = bcx.insn_ctxt("tvec::make_drop_glue_unboxed"); let tcx = bcx.tcx(), unit_ty = ty::sequence_element_type(tcx, vec_ty); - base::with_cond(bcx, IsNotNull(bcx, vptr)) {|bcx| - let bcx = if ty::type_needs_drop(tcx, unit_ty) { - iter_vec(bcx, vptr, vec_ty, base::drop_ty) - } else { bcx }; - base::trans_unique_free(bcx, vptr) - } + if ty::type_needs_drop(tcx, unit_ty) { + iter_vec_unboxed(bcx, vptr, vec_ty, base::drop_ty) + } else { bcx } } fn trans_evec(bcx: block, args: [@ast::expr], @@ -141,13 +165,18 @@ fn trans_evec(bcx: block, args: [@ast::expr], {bcx: bcx, val: p, dataptr: vp} } ast::vstore_uniq { - let {bcx, val} = alloc_uniq(bcx, unit_ty, args.len()); + let {bcx, val} = alloc_vec(bcx, unit_ty, args.len(), + heap_exchange); add_clean_free(bcx, val, true); let dataptr = get_dataptr(bcx, get_bodyptr(bcx, val)); {bcx: bcx, val: val, dataptr: dataptr} } ast::vstore_box { - bcx.ccx().sess.unimpl("unhandled tvec::trans_evec"); + let {bcx, val} = alloc_vec(bcx, unit_ty, args.len(), + heap_shared); + add_clean_free(bcx, val, true); + let dataptr = get_dataptr(bcx, get_bodyptr(bcx, val)); + {bcx: bcx, val: val, dataptr: dataptr} } }; @@ -223,13 +252,11 @@ fn get_base_and_len(cx: block, v: ValueRef, e_ty: ty::t) let len = Load(cx, GEPi(cx, v, [0u, abi::slice_elt_len])); (base, len) } - ty::vstore_uniq { + ty::vstore_uniq | ty::vstore_box { + #debug["get_base_and_len: %s", val_str(ccx.tn, v)]; let body = tvec::get_bodyptr(cx, v); (tvec::get_dataptr(cx, body), tvec::get_fill(cx, body)) } - ty::vstore_box { - cx.ccx().sess.unimpl("unhandled tvec::get_base_and_len"); - } } } @@ -388,7 +415,7 @@ fn trans_add(bcx: block, vec_ty: ty::t, lhs: ValueRef, fn iter_vec_raw(bcx: block, data_ptr: ValueRef, vec_ty: ty::t, fill: ValueRef, f: iter_vec_block) -> block { - let _icx = bcx.insn_ctxt("tvec::iter_vec_uniq"); + let _icx = bcx.insn_ctxt("tvec::iter_vec_raw"); let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty); @@ -422,11 +449,12 @@ fn iter_vec_uniq(bcx: block, vptr: ValueRef, vec_ty: ty::t, 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 fill = get_fill(bcx, get_bodyptr(bcx, vptr)); - ret iter_vec_uniq(bcx, vptr, vec_ty, fill, f); +fn iter_vec_unboxed(bcx: block, body_ptr: ValueRef, vec_ty: ty::t, + f: iter_vec_block) -> block { + let _icx = bcx.insn_ctxt("tvec::iter_vec_unboxed"); + let fill = get_fill(bcx, body_ptr); + let dataptr = get_dataptr(bcx, body_ptr); + ret iter_vec_raw(bcx, dataptr, vec_ty, fill, f); } // diff --git a/src/rustc/middle/trans/type_of.rs b/src/rustc/middle/trans/type_of.rs index fb9112fc751ff88c0209d5d585f5db8e60444b4d..760b2b4ee0afb105cc33788ad248cfb009152fe7 100644 --- a/src/rustc/middle/trans/type_of.rs +++ b/src/rustc/middle/trans/type_of.rs @@ -91,7 +91,9 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef { } 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) | + ty::ty_evec(mt, ty::vstore_box) { + T_box_ptr(T_box(cx, T_vec(cx, type_of(cx, mt.ty)))) + } ty::ty_box(mt) { T_box_ptr(T_box(cx, type_of(cx, mt.ty))) } 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))) } diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index a76a8143a89e3f9f8f5bdd02bed3cfc5ec673df0..0d4cc92b1ef85dca94db83bb7704a6fe41f8b270 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -1112,7 +1112,7 @@ fn type_is_str(ty: t) -> bool { fn sequence_element_type(cx: ctxt, ty: t) -> t { alt get(ty).struct { ty_str | ty_estr(_) { ret mk_mach_uint(cx, ast::ty_u8); } - ty_vec(mt) | ty_evec(mt, _) { ret mt.ty; } + ty_vec(mt) | ty_evec(mt, _) | ty_unboxed_vec(mt) { ret mt.ty; } _ { cx.sess.bug("sequence_element_type called on non-sequence value"); } } } @@ -1134,7 +1134,8 @@ fn get_element_type(ty: t, i: uint) -> t { pure fn type_is_boxed(ty: t) -> bool { alt get(ty).struct { - ty_box(_) | ty_opaque_box { true } + ty_box(_) | ty_opaque_box | + ty_evec(_, vstore_box) | ty_estr(vstore_box) { true } _ { false } } } @@ -1212,6 +1213,7 @@ fn type_needs_drop(cx: ctxt, ty: t) -> bool { ty_estr(vstore_fixed(_)) | ty_estr(vstore_slice(_)) | ty_evec(_, vstore_slice(_)) { false } ty_evec(mt, vstore_fixed(_)) { type_needs_drop(cx, mt.ty) } + ty_unboxed_vec(mt) { type_needs_drop(cx, mt.ty) } ty_rec(flds) { for flds.each {|f| if type_needs_drop(cx, f.mt.ty) { accum = true; } } accum