Don't duplicate ivec-iterating loop code

trans_ivec is starting to look almost pleasant
This commit is contained in:
Marijn Haverbeke 2011-08-29 16:14:24 +02:00
parent 9084a3ca1b
commit 9f41bc854d

View File

@ -151,37 +151,22 @@ fn trans_append(cx: &@block_ctxt, vec_ty: ty::t, lhsptr: ValueRef,
let lhs_data = get_dataptr(bcx, lhs, llunitty);
let lhs_off = lfill;
if strings { lhs_off = Sub(bcx, lfill, C_int(1)); }
if strings { lhs_off = Sub(bcx, lhs_off, C_int(1)); }
let write_ptr = pointer_add(bcx, lhs_data, lhs_off);
let write_ptr_ptr = do_spill(bcx, write_ptr);
let end_ptr = pointer_add(bcx, write_ptr, rfill);
let read_ptr_ptr = do_spill(bcx, get_dataptr(bcx, rhs, llunitty));
let header_cx = new_sub_block_ctxt(bcx, ~"copy_loop_header");
Br(bcx, header_cx.llbb);
let write_ptr = Load(header_cx, write_ptr_ptr);
let not_yet_at_end = ICmp(header_cx, lib::llvm::LLVMIntNE,
write_ptr, end_ptr);
let body_cx = new_sub_block_ctxt(bcx, ~"copy_loop_body");
let next_cx = new_sub_block_ctxt(bcx, ~"next");
CondBr(header_cx, not_yet_at_end,
body_cx.llbb, next_cx.llbb);
let read_ptr = Load(body_cx, read_ptr_ptr);
let body_cx = copy_val(body_cx, INIT, write_ptr,
load_if_immediate(body_cx, read_ptr, unit_ty),
unit_ty);
// Increment both pointers.
if dynamic {
// We have to increment by the dynamically-computed size.
incr_ptr(body_cx, write_ptr, unit_sz, write_ptr_ptr);
incr_ptr(body_cx, read_ptr, unit_sz, read_ptr_ptr);
} else {
incr_ptr(body_cx, write_ptr, C_int(1), write_ptr_ptr);
incr_ptr(body_cx, read_ptr, C_int(1), read_ptr_ptr);
}
Br(body_cx, header_cx.llbb);
ret rslt(next_cx, C_nil());
let bcx = iter_ivec_raw(bcx, rhs, vec_ty, rfill, { | &bcx, addr, _ty |
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);
if dynamic {
// We have to increment by the dynamically-computed size.
incr_ptr(bcx, write_ptr, unit_sz, write_ptr_ptr);
} else {
incr_ptr(bcx, write_ptr, C_int(1), write_ptr_ptr);
}
ret rslt(bcx, C_nil());
}).bcx;
ret rslt(bcx, C_nil());
}
fn trans_append_literal(bcx: &@block_ctxt, vptrptr: ValueRef, vec_ty: ty::t,
@ -216,75 +201,35 @@ fn trans_add(bcx: &@block_ctxt, vec_ty: ty::t, lhs: ValueRef,
let {bcx, val: new_vec, unit_ty, llunitsz, llunitty} =
alloc(bcx, vec_ty, new_fill, true);
// Emit the copy loop
let write_ptr_ptr = do_spill(bcx, get_dataptr(bcx, new_vec, llunitty));
let lhs_ptr = get_dataptr(bcx, lhs, llunitty);
let lhs_ptr_ptr = do_spill(bcx, lhs_ptr);
let lhs_end_ptr = pointer_add(bcx, lhs_ptr, lhs_fill);
let rhs_ptr = get_dataptr(bcx, rhs, llunitty);
let rhs_ptr_ptr = do_spill(bcx, rhs_ptr);
let rhs_end_ptr = pointer_add(bcx, rhs_ptr, rhs_fill);
let copy_block = { | &bcx, addr, _ty |
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);
if ty::type_has_dynamic_size(bcx_tcx(bcx), unit_ty) {
// We have to increment by the dynamically-computed size.
incr_ptr(bcx, write_ptr, llunitsz, write_ptr_ptr);
} else {
incr_ptr(bcx, write_ptr, C_int(1), write_ptr_ptr);
}
ret rslt(bcx, C_nil());
};
// Copy in elements from the LHS.
let lhs_cx = new_sub_block_ctxt(bcx, ~"lhs_copy_header");
Br(bcx, lhs_cx.llbb);
let lhs_ptr = Load(lhs_cx, lhs_ptr_ptr);
let not_at_end_lhs =
ICmp(lhs_cx, lib::llvm::LLVMIntNE, lhs_ptr, lhs_end_ptr);
let lhs_copy_cx = new_sub_block_ctxt(bcx, ~"lhs_copy_body");
let rhs_cx = new_sub_block_ctxt(bcx, ~"rhs_copy_header");
CondBr(lhs_cx, not_at_end_lhs, lhs_copy_cx.llbb, rhs_cx.llbb);
let write_ptr = Load(lhs_copy_cx, write_ptr_ptr);
lhs_copy_cx =
copy_val(lhs_copy_cx, INIT, write_ptr,
load_if_immediate(lhs_copy_cx, lhs_ptr, unit_ty), unit_ty);
// Increment both pointers.
if ty::type_has_dynamic_size(bcx_tcx(bcx), unit_ty) {
// We have to increment by the dynamically-computed size.
incr_ptr(lhs_copy_cx, write_ptr, llunitsz, write_ptr_ptr);
incr_ptr(lhs_copy_cx, lhs_ptr, llunitsz, lhs_ptr_ptr);
} else {
incr_ptr(lhs_copy_cx, write_ptr, C_int(1), write_ptr_ptr);
incr_ptr(lhs_copy_cx, lhs_ptr, C_int(1), lhs_ptr_ptr);
}
Br(lhs_copy_cx, lhs_cx.llbb);
// Copy in elements from the RHS.
let rhs_ptr = Load(rhs_cx, rhs_ptr_ptr);
let not_at_end_rhs =
ICmp(rhs_cx, lib::llvm::LLVMIntNE, rhs_ptr, rhs_end_ptr);
let rhs_copy_cx = new_sub_block_ctxt(bcx, ~"rhs_copy_body");
let next_cx = new_sub_block_ctxt(bcx, ~"next");
CondBr(rhs_cx, not_at_end_rhs, rhs_copy_cx.llbb, next_cx.llbb);
let write_ptr = Load(rhs_copy_cx, write_ptr_ptr);
rhs_copy_cx =
copy_val(rhs_copy_cx, INIT, write_ptr,
load_if_immediate(rhs_copy_cx, rhs_ptr, unit_ty), unit_ty);
// Increment both pointers.
if ty::type_has_dynamic_size(bcx_tcx(bcx), unit_ty) {
// We have to increment by the dynamically-computed size.
incr_ptr(rhs_copy_cx, write_ptr, llunitsz, write_ptr_ptr);
incr_ptr(rhs_copy_cx, rhs_ptr, llunitsz, rhs_ptr_ptr);
} else {
incr_ptr(rhs_copy_cx, write_ptr, C_int(1), write_ptr_ptr);
incr_ptr(rhs_copy_cx, rhs_ptr, C_int(1), rhs_ptr_ptr);
}
Br(rhs_copy_cx, rhs_cx.llbb);
ret rslt(next_cx, new_vec);
let bcx = iter_ivec_raw(bcx, lhs, vec_ty, lhs_fill, copy_block).bcx;
let bcx = iter_ivec_raw(bcx, rhs, vec_ty, rhs_fill, copy_block).bcx;
ret rslt(bcx, new_vec);
}
// FIXME factor out a utility that can be used to create the loops built
// above
fn iter_ivec(bcx: &@block_ctxt, vptrptr: ValueRef, vec_ty: ty::t,
f: &trans::val_and_ty_fn) -> result {
type val_and_ty_fn = fn(&@block_ctxt, ValueRef, ty::t) -> result;
type iter_ivec_block = block(&@block_ctxt, ValueRef, ty::t) -> result;
fn iter_ivec_raw(bcx: &@block_ctxt, vptr: ValueRef, vec_ty: ty::t,
fill: ValueRef, f: &iter_ivec_block) -> result {
let unit_ty = ty::sequence_element_type(bcx_tcx(bcx), vec_ty);
let llunitty = type_of_or_i8(bcx, unit_ty);
let {bcx, val: unit_sz} = size_of(bcx, unit_ty);
let vptr = Load(bcx, PointerCast(bcx, vptrptr,
T_ptr(T_ptr(T_ivec(llunitty)))));
let fill = get_fill(bcx, vptr);
let vptr = PointerCast(bcx, vptr, T_ptr(T_ivec(llunitty)));
let data_ptr = get_dataptr(bcx, vptr, llunitty);
// Calculate the last pointer address we want to handle.
@ -312,6 +257,13 @@ fn iter_ivec(bcx: &@block_ctxt, vptrptr: ValueRef, vec_ty: ty::t,
ret rslt(next_cx, C_nil());
}
fn iter_ivec(bcx: &@block_ctxt, vptrptr: ValueRef, vec_ty: ty::t,
f: &iter_ivec_block) -> result {
let vptr = Load(bcx, PointerCast(bcx, vptrptr,
T_ptr(T_ptr(T_opaque_ivec()))));
ret iter_ivec_raw(bcx, vptr, vec_ty, get_fill(bcx, vptr), f);
}
//
// Local Variables:
// mode: rust