diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index b0381684626..6c824d9626f 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1321,6 +1321,15 @@ fn dynamic_size_of(&@block_ctxt cx, ty::t t) -> result { auto total_size = bcx.build.Add(max_size_val, llsize_of(T_int())); ret res(bcx, total_size); } + case (ty::ty_ivec(?mt)) { + auto rslt = field_of_tydesc(cx, mt.ty, false, + abi::tydesc_field_size); + auto bcx = rslt.bcx; + auto llunitszptr = rslt.val; + auto llunitsz = bcx.build.Load(llunitszptr); + auto llsz = bcx.build.Add(llsize_of(T_opaque_ivec()), llunitsz); + ret res(bcx, llsz); + } } } @@ -1353,7 +1362,13 @@ fn dynamic_align_of(&@block_ctxt cx, &ty::t t) -> result { } case (ty::ty_tag(_, _)) { ret res(cx, C_int(1)); // FIXME: stub - + } + case (ty::ty_ivec(?tm)) { + auto rslt = align_of(cx, tm.ty); + auto bcx = rslt.bcx; + auto llunitalign = rslt.val; + auto llalign = umax(bcx, llalign_of(T_int()), llunitalign); + ret res(bcx, llalign); } } } @@ -2044,8 +2059,15 @@ fn make_drop_glue(&@block_ctxt cx, ValueRef v0, &ty::t t) { case (ty::ty_str) { rslt = decr_refcnt_maybe_free(cx, v0, v0, t); } case (ty::ty_vec(_)) { rslt = decr_refcnt_maybe_free(cx, v0, v0, t); } case (ty::ty_ivec(?tm)) { - rslt = iter_structural_ty(cx, v0, t, drop_ty); - rslt = maybe_free_ivec_heap_part(rslt.bcx, v0, tm.ty); + auto v1; + if (ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, tm.ty)) { + v1 = cx.build.PointerCast(v0, T_ptr(T_opaque_ivec())); + } else { + v1 = v0; + } + + rslt = iter_structural_ty(cx, v1, t, drop_ty); + rslt = maybe_free_ivec_heap_part(rslt.bcx, v1, tm.ty); } case (ty::ty_box(_)) { rslt = decr_refcnt_maybe_free(cx, v0, v0, t); } case (ty::ty_port(_)) { @@ -2396,74 +2418,6 @@ fn make_numerical_cmp_glue(&@block_ctxt cx, ValueRef lhs, ValueRef rhs, } -// Returns the length of an interior vector and a pointer to its first -// element, in that order. -fn get_len_and_data(&@block_ctxt bcx, ValueRef v, ty::t unit_ty) -> - tup(ValueRef, ValueRef, @block_ctxt) { - auto llunitty = type_of_or_i8(bcx, unit_ty); - auto stack_len = - bcx.build.Load(bcx.build.InBoundsGEP(v, - [C_int(0), - C_uint(abi::ivec_elt_len)])); - auto stack_elem = - bcx.build.InBoundsGEP(v, - [C_int(0), C_uint(abi::ivec_elt_elems), - C_int(0)]); - auto on_heap = bcx.build.ICmp(lib::llvm::LLVMIntEQ, stack_len, C_int(0)); - auto on_heap_cx = new_sub_block_ctxt(bcx, "on_heap"); - auto next_cx = new_sub_block_ctxt(bcx, "next"); - bcx.build.CondBr(on_heap, on_heap_cx.llbb, next_cx.llbb); - auto heap_stub = - on_heap_cx.build.PointerCast(v, T_ptr(T_ivec_heap(llunitty))); - auto heap_ptr = - { - auto v = [C_int(0), C_uint(abi::ivec_heap_stub_elt_ptr)]; - on_heap_cx.build.Load(on_heap_cx.build.InBoundsGEP(heap_stub, v)) - }; - // Check whether the heap pointer is null. If it is, the vector length is - // truly zero. - - auto llstubty = T_ivec_heap(llunitty); - auto llheapptrty = struct_elt(llstubty, abi::ivec_heap_stub_elt_ptr); - auto heap_ptr_is_null = - on_heap_cx.build.ICmp(lib::llvm::LLVMIntEQ, heap_ptr, - C_null(T_ptr(llheapptrty))); - auto zero_len_cx = new_sub_block_ctxt(bcx, "zero_len"); - auto nonzero_len_cx = new_sub_block_ctxt(bcx, "nonzero_len"); - on_heap_cx.build.CondBr(heap_ptr_is_null, zero_len_cx.llbb, - nonzero_len_cx.llbb); - // Technically this context is unnecessary, but it makes this function - // clearer. - - auto zero_len = C_int(0); - auto zero_elem = C_null(T_ptr(llunitty)); - zero_len_cx.build.Br(next_cx.llbb); - // If we're here, then we actually have a heapified vector. - - auto heap_len = - { - auto v = [C_int(0), C_uint(abi::ivec_heap_elt_len)]; - auto m = nonzero_len_cx.build.InBoundsGEP(heap_ptr, v); - nonzero_len_cx.build.Load(m) - }; - auto heap_elem = - nonzero_len_cx.build.InBoundsGEP(heap_ptr, - [C_int(0), - C_uint(abi::ivec_heap_elt_elems), - C_int(0)]); - nonzero_len_cx.build.Br(next_cx.llbb); - // Now we can figure out the length of `v` and get a pointer to its first - // element. - - auto len = - next_cx.build.Phi(T_int(), [stack_len, zero_len, heap_len], - [bcx.llbb, zero_len_cx.llbb, nonzero_len_cx.llbb]); - auto elem = - next_cx.build.Phi(T_ptr(llunitty), [stack_elem, zero_elem, heap_elem], - [bcx.llbb, zero_len_cx.llbb, nonzero_len_cx.llbb]); - ret tup(len, elem, next_cx); -} - type val_pair_fn = fn(&@block_ctxt, ValueRef, ValueRef) -> result ; type val_and_ty_fn = fn(&@block_ctxt, ValueRef, ty::t) -> result ; @@ -3017,8 +2971,10 @@ fn memmove_ty(&@block_ctxt cx, ValueRef dst, ValueRef src, &ty::t t) -> tag copy_action { INIT; DROP_EXISTING; } +// FIXME: This should copy the contents of the heap part for ivecs. fn copy_val(&@block_ctxt cx, copy_action action, ValueRef dst, ValueRef src, &ty::t t) -> result { + if (ty::type_is_scalar(cx.fcx.lcx.ccx.tcx, t) || ty::type_is_native(cx.fcx.lcx.ccx.tcx, t)) { ret res(cx, cx.build.Store(src, dst)); @@ -3245,8 +3201,18 @@ mod ivec { // Returns the length of an interior vector and a pointer to its first // element, in that order. - fn get_len_and_data(&@block_ctxt bcx, ValueRef v, ty::t unit_ty) -> - tup(ValueRef, ValueRef, @block_ctxt) { + fn get_len_and_data(&@block_ctxt bcx, ValueRef orig_v, ty::t unit_ty) + -> tup(ValueRef, ValueRef, @block_ctxt) { + // If this interior vector has dynamic size, we can't assume anything + // about the LLVM type of the value passed in, so we cast it to an + // opaque vector type. + auto v; + if (ty::type_has_dynamic_size(bcx.fcx.lcx.ccx.tcx, unit_ty)) { + v = bcx.build.PointerCast(orig_v, T_ptr(T_opaque_ivec())); + } else { + v = orig_v; + } + auto llunitty = type_of_or_i8(bcx, unit_ty); auto stack_len = { @@ -4715,7 +4681,7 @@ fn trans_index(&@block_ctxt cx, &span sp, &@ast::expr base, &@ast::expr idx, maybe_name_value(cx.fcx.lcx.ccx, scaled_ix, "scaled_ix"); auto interior_len_and_data; if (is_interior) { - auto rslt = get_len_and_data(bcx, v, unit_ty); + auto rslt = ivec::get_len_and_data(bcx, v, unit_ty); interior_len_and_data = some(tup(rslt._0, rslt._1)); bcx = rslt._2; } else { interior_len_and_data = none; } diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index deaf925f0b8..c2c46cb7e07 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -883,12 +883,38 @@ fn type_is_native(&ctxt cx, &t ty) -> bool { fn type_has_dynamic_size(&ctxt cx, &t ty) -> bool { alt (struct(cx, ty)) { + case (ty_nil) { ret false; } + case (ty_bot) { ret false; } + case (ty_bool) { ret false; } + case (ty_int) { ret false; } + case (ty_float) { ret false; } + case (ty_uint) { ret false; } + case (ty_machine(_)) { ret false; } + case (ty_char) { ret false; } + case (ty_str) { ret false; } + case (ty_istr) { ret false; } + case (ty_tag(_, ?subtys)) { + auto i = 0u; + while (i < vec::len[t](subtys)) { + if (type_has_dynamic_size(cx, subtys.(i))) { ret true; } + i += 1u; + } + ret false; + } + case (ty_box(_)) { ret false; } + case (ty_vec(_)) { ret false; } + case (ty_ivec(?mt)) { ret type_has_dynamic_size(cx, mt.ty); } + case (ty_ptr(_)) { ret false; } + case (ty_port(_)) { ret false; } + case (ty_chan(_)) { ret false; } + case (ty_task) { ret false; } case (ty_tup(?mts)) { auto i = 0u; while (i < vec::len[mt](mts)) { if (type_has_dynamic_size(cx, mts.(i).ty)) { ret true; } i += 1u; } + ret false; } case (ty_rec(?fields)) { auto i = 0u; @@ -896,18 +922,16 @@ fn type_has_dynamic_size(&ctxt cx, &t ty) -> bool { if (type_has_dynamic_size(cx, fields.(i).mt.ty)) { ret true; } i += 1u; } + ret false; } - case (ty_tag(_, ?subtys)) { - auto i = 0u; - while (i < vec::len[t](subtys)) { - if (type_has_dynamic_size(cx, subtys.(i))) { ret true; } - i += 1u; - } - } + case (ty_fn(_,_,_,_,_)) { ret false; } + case (ty_native_fn(_,_,_)) { ret false; } + case (ty_obj(_)) { ret false; } + case (ty_var(_)) { fail "ty_var in type_has_dynamic_size()"; } case (ty_param(_)) { ret true; } - case (_) {/* fall through */ } + case (ty_type) { ret false; } + case (ty_native) { ret false; } } - ret false; } fn type_is_integral(&ctxt cx, &t ty) -> bool {