2011-08-22 15:30:53 -05:00
|
|
|
import std::vec;
|
2011-08-22 13:48:00 -05:00
|
|
|
import std::option::none;
|
|
|
|
import syntax::ast;
|
|
|
|
import lib::llvm::llvm::{ValueRef, TypeRef};
|
|
|
|
import back::abi;
|
2011-09-02 17:34:58 -05:00
|
|
|
import trans::{call_memmove, trans_shared_malloc, llsize_of, type_of_or_i8,
|
2011-09-09 07:20:15 -05:00
|
|
|
INIT, copy_val, load_if_immediate, alloca, size_of,
|
2011-09-02 17:34:58 -05:00
|
|
|
llderivedtydescs_block_ctxt, lazily_emit_tydesc_glue,
|
|
|
|
get_tydesc, load_inbounds, move_val_if_temp, trans_lval,
|
2011-09-07 14:10:37 -05:00
|
|
|
node_id_type, new_sub_block_ctxt, tps_normal, do_spill_noroot,
|
2011-09-27 01:42:27 -05:00
|
|
|
GEPi, alloc_ty, dest};
|
2011-08-25 03:18:02 -05:00
|
|
|
import trans_build::*;
|
2011-08-22 13:48:00 -05:00
|
|
|
import trans_common::*;
|
|
|
|
|
2011-09-12 04:27:30 -05:00
|
|
|
fn get_fill(bcx: @block_ctxt, vptrptr: ValueRef) -> ValueRef {
|
2011-09-07 14:10:37 -05:00
|
|
|
Load(bcx, GEPi(bcx, Load(bcx, vptrptr), [0, abi::vec_elt_fill as int]))
|
2011-08-25 03:18:02 -05:00
|
|
|
}
|
2011-09-12 04:27:30 -05:00
|
|
|
fn get_alloc(bcx: @block_ctxt, vptrptr: ValueRef) -> ValueRef {
|
2011-09-07 14:10:37 -05:00
|
|
|
Load(bcx, GEPi(bcx, Load(bcx, vptrptr), [0, abi::vec_elt_alloc as int]))
|
2011-08-25 03:18:02 -05:00
|
|
|
}
|
2011-09-12 04:27:30 -05:00
|
|
|
fn get_dataptr(bcx: @block_ctxt, vptrptr: ValueRef, unit_ty: TypeRef) ->
|
2011-09-02 17:34:58 -05:00
|
|
|
ValueRef {
|
2011-09-27 17:56:32 -05:00
|
|
|
let ptr = GEPi(bcx, Load(bcx, vptrptr), [0, abi::vec_elt_elems as int]);
|
2011-08-25 03:18:02 -05:00
|
|
|
PointerCast(bcx, ptr, T_ptr(unit_ty))
|
|
|
|
}
|
2011-08-22 13:48:00 -05:00
|
|
|
|
2011-09-12 04:27:30 -05:00
|
|
|
fn pointer_add(bcx: @block_ctxt, ptr: ValueRef, bytes: ValueRef) -> ValueRef {
|
2011-08-25 03:18:02 -05:00
|
|
|
let old_ty = val_ty(ptr);
|
|
|
|
let bptr = PointerCast(bcx, ptr, T_ptr(T_i8()));
|
|
|
|
ret PointerCast(bcx, InBoundsGEP(bcx, bptr, [bytes]), old_ty);
|
|
|
|
}
|
2011-08-22 13:48:00 -05:00
|
|
|
|
2011-09-12 04:27:30 -05:00
|
|
|
fn alloc_raw(bcx: @block_ctxt, fill: ValueRef, alloc: ValueRef) -> result {
|
2011-09-02 09:09:41 -05:00
|
|
|
let llvecty = T_opaque_vec();
|
2011-08-29 15:30:18 -05:00
|
|
|
let vecsize = Add(bcx, alloc, llsize_of(llvecty));
|
2011-09-02 17:34:58 -05:00
|
|
|
let {bcx: bcx, val: vecptr} =
|
2011-08-29 15:30:18 -05:00
|
|
|
trans_shared_malloc(bcx, T_ptr(llvecty), vecsize);
|
2011-09-02 17:34:58 -05:00
|
|
|
Store(bcx, fill,
|
|
|
|
InBoundsGEP(bcx, vecptr, [C_int(0), C_uint(abi::vec_elt_fill)]));
|
|
|
|
Store(bcx, alloc,
|
|
|
|
InBoundsGEP(bcx, vecptr, [C_int(0), C_uint(abi::vec_elt_alloc)]));
|
2011-08-29 15:30:18 -05:00
|
|
|
ret {bcx: bcx, val: vecptr};
|
|
|
|
}
|
|
|
|
|
2011-09-02 17:34:58 -05:00
|
|
|
type alloc_result =
|
|
|
|
{bcx: @block_ctxt,
|
|
|
|
val: ValueRef,
|
|
|
|
unit_ty: ty::t,
|
|
|
|
llunitsz: ValueRef,
|
|
|
|
llunitty: TypeRef};
|
2011-08-22 13:48:00 -05:00
|
|
|
|
2011-09-27 17:56:32 -05:00
|
|
|
fn alloc(bcx: @block_ctxt, vec_ty: ty::t, elts: uint, dest: dest)
|
|
|
|
-> alloc_result {
|
2011-08-25 03:18:02 -05:00
|
|
|
let unit_ty = ty::sequence_element_type(bcx_tcx(bcx), vec_ty);
|
|
|
|
let llunitty = type_of_or_i8(bcx, unit_ty);
|
2011-09-02 09:09:41 -05:00
|
|
|
let llvecty = T_vec(llunitty);
|
2011-09-02 17:34:58 -05:00
|
|
|
let {bcx: bcx, val: unit_sz} = size_of(bcx, unit_ty);
|
2011-08-25 03:18:02 -05:00
|
|
|
|
2011-08-29 15:30:18 -05:00
|
|
|
let fill = Mul(bcx, C_uint(elts), unit_sz);
|
|
|
|
let alloc = if elts < 4u { Mul(bcx, C_int(4), unit_sz) } else { fill };
|
2011-09-02 17:34:58 -05:00
|
|
|
let {bcx: bcx, val: vptr} = alloc_raw(bcx, fill, alloc);
|
2011-08-29 15:30:18 -05:00
|
|
|
let vptr = PointerCast(bcx, vptr, T_ptr(llvecty));
|
2011-09-07 14:10:37 -05:00
|
|
|
|
2011-09-27 17:56:32 -05:00
|
|
|
let vptrptr = alt dest { trans::save_in(a) { a } };
|
|
|
|
Store(bcx, vptr, vptrptr);
|
|
|
|
// add_clean_temp(bcx, vptrptr, vec_ty);
|
2011-09-02 17:34:58 -05:00
|
|
|
ret {bcx: bcx,
|
2011-09-27 17:56:32 -05:00
|
|
|
val: vptrptr,
|
2011-09-02 17:34:58 -05:00
|
|
|
unit_ty: unit_ty,
|
|
|
|
llunitsz: unit_sz,
|
|
|
|
llunitty: llunitty};
|
2011-08-25 03:18:02 -05:00
|
|
|
}
|
2011-08-29 15:30:18 -05:00
|
|
|
|
2011-09-12 04:27:30 -05:00
|
|
|
fn duplicate(bcx: @block_ctxt, vptrptr: ValueRef) -> @block_ctxt {
|
2011-09-07 14:10:37 -05:00
|
|
|
let fill = get_fill(bcx, vptrptr);
|
2011-08-25 03:18:02 -05:00
|
|
|
let vptr = Load(bcx, vptrptr);
|
2011-09-02 09:09:41 -05:00
|
|
|
let size = Add(bcx, fill, llsize_of(T_opaque_vec()));
|
2011-09-02 17:34:58 -05:00
|
|
|
let {bcx: bcx, val: newptr} =
|
|
|
|
trans_shared_malloc(bcx, val_ty(vptr), size);
|
2011-08-25 03:18:02 -05:00
|
|
|
let bcx = call_memmove(bcx, newptr, vptr, size).bcx;
|
|
|
|
Store(bcx, fill,
|
2011-09-02 09:09:41 -05:00
|
|
|
InBoundsGEP(bcx, newptr, [C_int(0), C_uint(abi::vec_elt_alloc)]));
|
2011-08-25 03:18:02 -05:00
|
|
|
Store(bcx, newptr, vptrptr);
|
|
|
|
ret bcx;
|
|
|
|
}
|
2011-09-12 04:27:30 -05:00
|
|
|
fn make_drop_glue(bcx: @block_ctxt, vptrptr: ValueRef, vec_ty: ty::t) ->
|
2011-09-02 17:34:58 -05:00
|
|
|
@block_ctxt {
|
2011-08-25 03:18:02 -05:00
|
|
|
let unit_ty = ty::sequence_element_type(bcx_tcx(bcx), vec_ty);
|
|
|
|
let vptr = Load(bcx, vptrptr);
|
2011-09-02 17:34:58 -05:00
|
|
|
let drop_cx = new_sub_block_ctxt(bcx, "drop");
|
|
|
|
let next_cx = new_sub_block_ctxt(bcx, "next");
|
2011-08-25 03:18:02 -05:00
|
|
|
let null_test = IsNull(bcx, vptr);
|
|
|
|
CondBr(bcx, null_test, next_cx.llbb, drop_cx.llbb);
|
|
|
|
if ty::type_needs_drop(bcx_tcx(bcx), unit_ty) {
|
2011-09-02 09:09:41 -05:00
|
|
|
drop_cx = iter_vec(drop_cx, vptrptr, vec_ty, trans::drop_ty);
|
2011-08-22 13:48:00 -05:00
|
|
|
}
|
2011-08-30 06:50:58 -05:00
|
|
|
drop_cx = trans::trans_shared_free(drop_cx, vptr);
|
2011-09-02 19:51:03 -05:00
|
|
|
Store(drop_cx, C_null(val_ty(vptr)), vptrptr);
|
2011-08-25 03:18:02 -05:00
|
|
|
Br(drop_cx, next_cx.llbb);
|
|
|
|
ret next_cx;
|
2011-08-22 15:30:53 -05:00
|
|
|
}
|
|
|
|
|
2011-09-27 01:42:27 -05:00
|
|
|
fn trans_vec(bcx: @block_ctxt, args: [@ast::expr], id: ast::node_id,
|
|
|
|
dest: dest) -> @block_ctxt {
|
2011-09-27 03:50:18 -05:00
|
|
|
if dest == trans::ignore {
|
|
|
|
for arg in args {
|
|
|
|
bcx = trans::trans_expr_dps(bcx, arg, trans::ignore);
|
|
|
|
}
|
|
|
|
ret bcx;
|
|
|
|
}
|
2011-08-25 03:18:02 -05:00
|
|
|
let vec_ty = node_id_type(bcx_ccx(bcx), id);
|
2011-09-02 17:34:58 -05:00
|
|
|
let {bcx: bcx,
|
2011-09-27 17:56:32 -05:00
|
|
|
val: vptrptr,
|
2011-09-02 17:34:58 -05:00
|
|
|
llunitsz: llunitsz,
|
|
|
|
unit_ty: unit_ty,
|
|
|
|
llunitty: llunitty} =
|
2011-09-27 17:56:32 -05:00
|
|
|
alloc(bcx, vec_ty, vec::len(args), dest);
|
2011-08-22 15:30:53 -05:00
|
|
|
|
2011-09-27 17:56:32 -05:00
|
|
|
let vptr = Load(bcx, vptrptr);
|
2011-09-27 06:19:55 -05:00
|
|
|
add_clean_free(bcx, vptr, true);
|
2011-08-22 15:30:53 -05:00
|
|
|
// Store the individual elements.
|
2011-09-27 17:56:32 -05:00
|
|
|
let dataptr = get_dataptr(bcx, vptrptr, llunitty);
|
2011-09-27 06:19:55 -05:00
|
|
|
let i = 0u, temp_cleanups = [vptr];
|
2011-08-25 03:18:02 -05:00
|
|
|
for e in args {
|
2011-08-22 13:48:00 -05:00
|
|
|
let lv = trans_lval(bcx, e);
|
2011-09-16 09:27:34 -05:00
|
|
|
bcx = lv.bcx;
|
2011-09-27 03:50:18 -05:00
|
|
|
let lleltptr = if ty::type_has_dynamic_size(bcx_tcx(bcx), unit_ty) {
|
|
|
|
InBoundsGEP(bcx, dataptr, [Mul(bcx, C_uint(i), llunitsz)])
|
|
|
|
} else { InBoundsGEP(bcx, dataptr, [C_uint(i)]) };
|
2011-08-22 13:48:00 -05:00
|
|
|
bcx = move_val_if_temp(bcx, INIT, lleltptr, lv, unit_ty);
|
2011-09-27 03:50:18 -05:00
|
|
|
add_clean_temp_mem(bcx, lleltptr, unit_ty);
|
|
|
|
temp_cleanups += [lleltptr];
|
2011-08-22 13:48:00 -05:00
|
|
|
i += 1u;
|
|
|
|
}
|
2011-09-27 03:50:18 -05:00
|
|
|
for clean in temp_cleanups { revoke_clean(bcx, clean); }
|
2011-09-27 01:42:27 -05:00
|
|
|
ret bcx;
|
2011-08-22 13:48:00 -05:00
|
|
|
}
|
2011-09-27 01:42:27 -05:00
|
|
|
fn trans_str(bcx: @block_ctxt, s: str, dest: dest) -> @block_ctxt {
|
2011-09-01 19:27:58 -05:00
|
|
|
let veclen = std::str::byte_len(s) + 1u; // +1 for \0
|
2011-09-27 17:56:32 -05:00
|
|
|
let {bcx: bcx, val: sptrptr, _} =
|
|
|
|
alloc(bcx, ty::mk_str(bcx_tcx(bcx)), veclen, dest);
|
2011-08-22 13:48:00 -05:00
|
|
|
|
2011-08-25 03:18:02 -05:00
|
|
|
let llcstr = C_cstr(bcx_ccx(bcx), s);
|
2011-09-02 17:34:58 -05:00
|
|
|
let bcx =
|
2011-09-27 17:56:32 -05:00
|
|
|
call_memmove(bcx, get_dataptr(bcx, sptrptr, T_i8()), llcstr,
|
2011-09-02 17:34:58 -05:00
|
|
|
C_uint(veclen)).bcx;
|
2011-09-27 01:42:27 -05:00
|
|
|
ret bcx;
|
2011-08-22 13:48:00 -05:00
|
|
|
}
|
|
|
|
|
2011-09-12 04:27:30 -05:00
|
|
|
fn trans_append(cx: @block_ctxt, vec_ty: ty::t, lhsptr: ValueRef,
|
2011-09-27 01:03:06 -05:00
|
|
|
rhsptr: ValueRef) -> @block_ctxt {
|
2011-08-22 13:48:00 -05:00
|
|
|
// Cast to opaque interior vector types if necessary.
|
2011-08-25 03:18:02 -05:00
|
|
|
let unit_ty = ty::sequence_element_type(bcx_tcx(cx), vec_ty);
|
|
|
|
let dynamic = ty::type_has_dynamic_size(bcx_tcx(cx), unit_ty);
|
|
|
|
if dynamic {
|
2011-09-02 09:09:41 -05:00
|
|
|
lhsptr = PointerCast(cx, lhsptr, T_ptr(T_ptr(T_opaque_vec())));
|
2011-09-07 14:10:37 -05:00
|
|
|
rhsptr = PointerCast(cx, rhsptr, T_ptr(T_ptr(T_opaque_vec())));
|
2011-08-24 06:53:34 -05:00
|
|
|
}
|
2011-09-02 17:34:58 -05:00
|
|
|
let strings =
|
|
|
|
alt ty::struct(bcx_tcx(cx), vec_ty) {
|
2011-09-02 18:45:00 -05:00
|
|
|
ty::ty_str. { true }
|
2011-09-02 17:34:58 -05:00
|
|
|
ty::ty_vec(_) { false }
|
|
|
|
};
|
2011-08-22 19:35:38 -05:00
|
|
|
|
2011-09-02 17:34:58 -05:00
|
|
|
let {bcx: bcx, val: unit_sz} = size_of(cx, unit_ty);
|
2011-08-25 03:18:02 -05:00
|
|
|
let llunitty = type_of_or_i8(cx, unit_ty);
|
2011-08-22 13:48:00 -05:00
|
|
|
|
2011-09-07 14:10:37 -05:00
|
|
|
let rhs = Load(bcx, rhsptr);
|
2011-08-25 03:18:02 -05:00
|
|
|
let lhs = Load(bcx, lhsptr);
|
|
|
|
let self_append = ICmp(bcx, lib::llvm::LLVMIntEQ, lhs, rhs);
|
2011-09-07 14:10:37 -05:00
|
|
|
let lfill = get_fill(bcx, lhsptr);
|
|
|
|
let rfill = get_fill(bcx, rhsptr);
|
2011-08-25 03:18:02 -05:00
|
|
|
let new_fill = Add(bcx, lfill, rfill);
|
|
|
|
if strings { new_fill = Sub(bcx, new_fill, C_int(1)); }
|
2011-09-02 09:09:41 -05:00
|
|
|
let opaque_lhs = PointerCast(bcx, lhsptr, T_ptr(T_ptr(T_opaque_vec())));
|
|
|
|
Call(bcx, bcx_ccx(cx).upcalls.vec_grow,
|
2011-08-25 03:18:02 -05:00
|
|
|
[cx.fcx.lltaskptr, opaque_lhs, new_fill]);
|
|
|
|
// Was overwritten if we resized
|
2011-09-07 14:10:37 -05:00
|
|
|
rhsptr = Select(bcx, self_append, lhsptr, rhsptr);
|
2011-08-25 03:18:02 -05:00
|
|
|
|
2011-09-07 14:10:37 -05:00
|
|
|
let lhs_data = get_dataptr(bcx, lhsptr, llunitty);
|
2011-08-25 03:18:02 -05:00
|
|
|
let lhs_off = lfill;
|
2011-08-29 09:14:24 -05:00
|
|
|
if strings { lhs_off = Sub(bcx, lhs_off, C_int(1)); }
|
2011-08-25 03:18:02 -05:00
|
|
|
let write_ptr = pointer_add(bcx, lhs_data, lhs_off);
|
2011-09-02 17:12:27 -05:00
|
|
|
let write_ptr_ptr = do_spill_noroot(bcx, write_ptr);
|
2011-09-02 17:34:58 -05:00
|
|
|
let bcx =
|
2011-09-07 14:10:37 -05:00
|
|
|
iter_vec_raw(bcx, rhsptr, vec_ty, rfill,
|
2011-09-02 17:34:58 -05:00
|
|
|
// We have to increment by the dynamically-computed size.
|
2011-09-12 04:27:30 -05:00
|
|
|
{|bcx, addr, _ty|
|
2011-09-02 17:34:58 -05:00
|
|
|
let write_ptr = Load(bcx, write_ptr_ptr);
|
|
|
|
let bcx =
|
|
|
|
copy_val(bcx, INIT, write_ptr,
|
|
|
|
load_if_immediate(bcx, addr, unit_ty),
|
|
|
|
unit_ty);
|
2011-09-09 07:20:15 -05:00
|
|
|
let incr = dynamic ? unit_sz : C_int(1);
|
|
|
|
Store(bcx, InBoundsGEP(bcx, write_ptr, [incr]),
|
|
|
|
write_ptr_ptr);
|
2011-09-02 17:34:58 -05:00
|
|
|
ret bcx;
|
|
|
|
});
|
2011-09-27 01:03:06 -05:00
|
|
|
ret bcx;
|
2011-08-22 13:48:00 -05:00
|
|
|
}
|
|
|
|
|
2011-09-12 04:27:30 -05:00
|
|
|
fn trans_append_literal(bcx: @block_ctxt, vptrptr: ValueRef, vec_ty: ty::t,
|
|
|
|
vals: [@ast::expr]) -> @block_ctxt {
|
2011-08-24 06:53:34 -05:00
|
|
|
let elt_ty = ty::sequence_element_type(bcx_tcx(bcx), vec_ty);
|
|
|
|
let ti = none;
|
2011-09-02 17:34:58 -05:00
|
|
|
let {bcx: bcx, val: td} =
|
2011-08-24 20:36:51 -05:00
|
|
|
get_tydesc(bcx, elt_ty, false, tps_normal, ti).result;
|
2011-08-25 03:18:02 -05:00
|
|
|
trans::lazily_emit_tydesc_glue(bcx, abi::tydesc_field_take_glue, ti);
|
2011-09-02 09:09:41 -05:00
|
|
|
let opaque_v = PointerCast(bcx, vptrptr, T_ptr(T_ptr(T_opaque_vec())));
|
2011-08-24 06:53:34 -05:00
|
|
|
for val in vals {
|
|
|
|
let {bcx: e_bcx, val: elt} = trans::trans_expr(bcx, val);
|
|
|
|
bcx = e_bcx;
|
2011-09-02 17:12:27 -05:00
|
|
|
let r = trans::spill_if_immediate(bcx, elt, elt_ty);
|
2011-09-02 17:34:58 -05:00
|
|
|
let spilled = r.val;
|
|
|
|
bcx = r.bcx;
|
2011-09-02 09:09:41 -05:00
|
|
|
Call(bcx, bcx_ccx(bcx).upcalls.vec_push,
|
2011-08-25 03:18:02 -05:00
|
|
|
[bcx.fcx.lltaskptr, opaque_v, td,
|
|
|
|
PointerCast(bcx, spilled, T_ptr(T_i8()))]);
|
2011-08-24 06:53:34 -05:00
|
|
|
}
|
|
|
|
ret bcx;
|
|
|
|
}
|
|
|
|
|
2011-09-12 04:27:30 -05:00
|
|
|
fn trans_add(bcx: @block_ctxt, vec_ty: ty::t, lhsptr: ValueRef,
|
2011-09-27 03:50:18 -05:00
|
|
|
rhsptr: ValueRef, dest: dest) -> @block_ctxt {
|
|
|
|
let strings = alt ty::struct(bcx_tcx(bcx), vec_ty) {
|
|
|
|
ty::ty_str. { true }
|
|
|
|
ty::ty_vec(_) { false }
|
|
|
|
};
|
2011-08-29 15:30:18 -05:00
|
|
|
let unit_ty = ty::sequence_element_type(bcx_tcx(bcx), vec_ty);
|
|
|
|
let llunitty = type_of_or_i8(bcx, unit_ty);
|
2011-09-02 17:34:58 -05:00
|
|
|
let {bcx: bcx, val: llunitsz} = size_of(bcx, unit_ty);
|
2011-08-29 15:30:18 -05:00
|
|
|
|
2011-09-07 14:10:37 -05:00
|
|
|
let lhs_fill = get_fill(bcx, lhsptr);
|
2011-08-25 03:18:02 -05:00
|
|
|
if strings { lhs_fill = Sub(bcx, lhs_fill, C_int(1)); }
|
2011-09-07 14:10:37 -05:00
|
|
|
let rhs_fill = get_fill(bcx, rhsptr);
|
2011-08-25 03:18:02 -05:00
|
|
|
let new_fill = Add(bcx, lhs_fill, rhs_fill);
|
2011-09-07 14:10:37 -05:00
|
|
|
let {bcx: bcx, val: new_vec_ptr} = alloc_raw(bcx, new_fill, new_fill);
|
|
|
|
new_vec_ptr = PointerCast(bcx, new_vec_ptr, T_ptr(T_vec(llunitty)));
|
2011-09-27 17:56:32 -05:00
|
|
|
let new_vec_ptr_ptr = alt dest { trans::save_in(a) { a } };
|
|
|
|
Store(bcx, new_vec_ptr, new_vec_ptr_ptr);
|
2011-08-25 03:18:02 -05:00
|
|
|
|
2011-09-27 17:56:32 -05:00
|
|
|
let write_ptr_ptr =
|
|
|
|
do_spill_noroot(bcx, get_dataptr(bcx, new_vec_ptr_ptr, llunitty));
|
2011-09-02 17:34:58 -05:00
|
|
|
let copy_fn =
|
2011-09-12 04:27:30 -05:00
|
|
|
bind fn (bcx: @block_ctxt, addr: ValueRef, _ty: ty::t,
|
2011-09-02 17:34:58 -05:00
|
|
|
write_ptr_ptr: ValueRef, unit_ty: ty::t, llunitsz: ValueRef)
|
|
|
|
-> @block_ctxt {
|
|
|
|
let write_ptr = Load(bcx, write_ptr_ptr);
|
|
|
|
let bcx =
|
|
|
|
copy_val(bcx, INIT, write_ptr,
|
|
|
|
load_if_immediate(bcx, addr, unit_ty), unit_ty);
|
2011-09-12 04:27:30 -05:00
|
|
|
let incr =
|
|
|
|
ty::type_has_dynamic_size(bcx_tcx(bcx), unit_ty) ?
|
|
|
|
llunitsz : C_int(1);
|
2011-09-09 07:20:15 -05:00
|
|
|
Store(bcx, InBoundsGEP(bcx, write_ptr, [incr]),
|
|
|
|
write_ptr_ptr);
|
2011-09-02 17:34:58 -05:00
|
|
|
ret bcx;
|
|
|
|
}(_, _, _, write_ptr_ptr, unit_ty, llunitsz);
|
2011-08-22 18:39:18 -05:00
|
|
|
|
2011-09-07 14:10:37 -05:00
|
|
|
let bcx = iter_vec_raw(bcx, lhsptr, vec_ty, lhs_fill, copy_fn);
|
2011-09-27 17:56:32 -05:00
|
|
|
ret iter_vec_raw(bcx, rhsptr, vec_ty, rhs_fill, copy_fn);
|
2011-08-29 09:14:24 -05:00
|
|
|
}
|
2011-08-22 13:48:00 -05:00
|
|
|
|
2011-09-12 04:27:30 -05:00
|
|
|
type val_and_ty_fn = fn(@block_ctxt, ValueRef, ty::t) -> result;
|
2011-08-22 13:48:00 -05:00
|
|
|
|
2011-09-12 04:27:30 -05:00
|
|
|
type iter_vec_block = block(@block_ctxt, ValueRef, ty::t) -> @block_ctxt;
|
2011-08-22 13:48:00 -05:00
|
|
|
|
2011-09-12 04:27:30 -05:00
|
|
|
fn iter_vec_raw(bcx: @block_ctxt, vptrptr: ValueRef, vec_ty: ty::t,
|
|
|
|
fill: ValueRef, f: iter_vec_block) -> @block_ctxt {
|
2011-08-25 03:18:02 -05:00
|
|
|
let unit_ty = ty::sequence_element_type(bcx_tcx(bcx), vec_ty);
|
|
|
|
let llunitty = type_of_or_i8(bcx, unit_ty);
|
2011-09-02 17:34:58 -05:00
|
|
|
let {bcx: bcx, val: unit_sz} = size_of(bcx, unit_ty);
|
2011-09-07 14:10:37 -05:00
|
|
|
vptrptr = PointerCast(bcx, vptrptr, T_ptr(T_ptr(T_vec(llunitty))));
|
|
|
|
let data_ptr = get_dataptr(bcx, vptrptr, llunitty);
|
2011-08-25 03:18:02 -05:00
|
|
|
|
|
|
|
// Calculate the last pointer address we want to handle.
|
|
|
|
// TODO: Optimize this when the size of the unit type is statically
|
|
|
|
// known to not use pointer casts, which tend to confuse LLVM.
|
|
|
|
let data_end_ptr = pointer_add(bcx, data_ptr, fill);
|
|
|
|
|
|
|
|
// Now perform the iteration.
|
2011-09-02 17:34:58 -05:00
|
|
|
let header_cx = new_sub_block_ctxt(bcx, "iter_vec_loop_header");
|
2011-08-25 03:18:02 -05:00
|
|
|
Br(bcx, header_cx.llbb);
|
2011-09-09 07:20:15 -05:00
|
|
|
let data_ptr = Phi(header_cx, val_ty(data_ptr), [data_ptr], [bcx.llbb]);
|
2011-09-02 17:34:58 -05:00
|
|
|
let not_yet_at_end =
|
|
|
|
ICmp(header_cx, lib::llvm::LLVMIntULT, data_ptr, data_end_ptr);
|
2011-09-21 05:40:27 -05:00
|
|
|
let body_cx = new_sub_block_ctxt(header_cx, "iter_vec_loop_body");
|
|
|
|
let next_cx = new_sub_block_ctxt(header_cx, "iter_vec_next");
|
2011-08-25 03:18:02 -05:00
|
|
|
CondBr(header_cx, not_yet_at_end, body_cx.llbb, next_cx.llbb);
|
2011-08-30 06:50:58 -05:00
|
|
|
body_cx = f(body_cx, data_ptr, unit_ty);
|
2011-09-02 17:34:58 -05:00
|
|
|
let increment =
|
|
|
|
if ty::type_has_dynamic_size(bcx_tcx(bcx), unit_ty) {
|
|
|
|
unit_sz
|
|
|
|
} else { C_int(1) };
|
2011-09-23 16:20:19 -05:00
|
|
|
AddIncomingToPhi(data_ptr, InBoundsGEP(body_cx, data_ptr, [increment]),
|
|
|
|
body_cx.llbb);
|
2011-08-25 03:18:02 -05:00
|
|
|
Br(body_cx, header_cx.llbb);
|
2011-08-30 06:50:58 -05:00
|
|
|
ret next_cx;
|
2011-08-22 13:48:00 -05:00
|
|
|
}
|
2011-08-25 03:18:02 -05:00
|
|
|
|
2011-09-12 04:27:30 -05:00
|
|
|
fn iter_vec(bcx: @block_ctxt, vptrptr: ValueRef, vec_ty: ty::t,
|
|
|
|
f: iter_vec_block) -> @block_ctxt {
|
2011-09-07 14:10:37 -05:00
|
|
|
vptrptr = PointerCast(bcx, vptrptr, T_ptr(T_ptr(T_opaque_vec())));
|
|
|
|
ret iter_vec_raw(bcx, vptrptr, vec_ty, get_fill(bcx, vptrptr), f);
|
2011-08-29 09:14:24 -05:00
|
|
|
}
|
|
|
|
|
2011-08-24 06:53:34 -05:00
|
|
|
//
|
|
|
|
// Local Variables:
|
|
|
|
// mode: rust
|
|
|
|
// fill-column: 78;
|
|
|
|
// indent-tabs-mode: nil
|
|
|
|
// c-basic-offset: 4
|
|
|
|
// buffer-file-coding-system: utf-8-unix
|
|
|
|
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
|
|
|
|
// End:
|
|
|
|
//
|