rustc: Make unique pointers no longer immediates.

This commit is contained in:
Patrick Walton 2011-09-07 12:10:37 -07:00 committed by Marijn Haverbeke
parent 9946e467ff
commit 7a0c9759fe
3 changed files with 88 additions and 70 deletions

View File

@ -2088,12 +2088,13 @@ fn memmove_ty(cx: &@block_ctxt, dst: ValueRef, src: ValueRef, t: ty::t) ->
let sp = cx.sp;
let llsz = llsize_of(type_of(ccx, sp, t));
ret call_memmove(cx, dst, src, llsz);
} else { ret rslt(cx, Store(cx, Load(cx, src), dst)); }
}
else {
let llsz = size_of(cx, t);
ret call_memmove(llsz.bcx, dst, src, llsz.val);
}
ret rslt(cx, Store(cx, Load(cx, src), dst));
}
let llsz = size_of(cx, t);
ret call_memmove(llsz.bcx, dst, src, llsz.val);
}
tag copy_action { INIT; DROP_EXISTING; }
@ -2136,17 +2137,18 @@ fn copy_val_no_check(cx: &@block_ctxt, action: copy_action, dst: ValueRef,
if ty::type_is_scalar(ccx.tcx, t) || ty::type_is_native(ccx.tcx, t) {
Store(cx, src, dst);
ret cx;
} else if ty::type_is_nil(ccx.tcx, t) || ty::type_is_bot(ccx.tcx, t) {
ret cx;
} else if ty::type_is_boxed(ccx.tcx, t) || ty::type_is_vec(ccx.tcx, t) {
let bcx =
if action == DROP_EXISTING { drop_ty(cx, dst, t) } else { cx };
}
if ty::type_is_nil(ccx.tcx, t) || ty::type_is_bot(ccx.tcx, t) { ret cx; }
if ty::type_is_boxed(ccx.tcx, t) {
let bcx = cx;
if action == DROP_EXISTING { bcx = drop_ty(cx, dst, t); }
Store(bcx, src, dst);
bcx = take_ty(bcx, dst, t);
ret bcx;
} else if type_is_structural_or_param(ccx.tcx, t) {
let bcx =
if action == DROP_EXISTING { drop_ty(cx, dst, t) } else { cx };
ret take_ty(bcx, dst, t);
}
if type_is_structural_or_param(ccx.tcx, t) ||
ty::type_is_vec(ccx.tcx, t) {
let bcx = cx;
if action == DROP_EXISTING { bcx = drop_ty(cx, dst, t); }
bcx = memmove_ty(bcx, dst, src, t).bcx;
ret take_ty(bcx, dst, t);
}
@ -2170,7 +2172,7 @@ fn move_val(cx: @block_ctxt, action: copy_action, dst: ValueRef,
ret cx;
} else if ty::type_is_nil(tcx, t) || ty::type_is_bot(tcx, t) {
ret cx;
} else if ty::type_is_unique(tcx, t) || ty::type_is_boxed(tcx, t) {
} else if ty::type_is_boxed(tcx, t) {
if src.is_mem { src_val = Load(cx, src_val); }
if action == DROP_EXISTING { cx = drop_ty(cx, dst, t); }
Store(cx, src_val, dst);
@ -2179,7 +2181,8 @@ fn move_val(cx: @block_ctxt, action: copy_action, dst: ValueRef,
// If we're here, it must be a temporary.
revoke_clean(cx, src_val);
ret cx;
} else if type_is_structural_or_param(tcx, t) {
} else if ty::type_is_unique(tcx, t) ||
type_is_structural_or_param(tcx, t) {
if action == DROP_EXISTING { cx = drop_ty(cx, dst, t); }
cx = memmove_ty(cx, dst, src_val, t).bcx;
if src.is_mem {
@ -3496,7 +3499,8 @@ fn trans_bind_thunk(cx: &@local_ctxt, sp: &span, incoming_fty: ty::t,
if is_val { T_ptr(llout_arg_ty) } else { llout_arg_ty };
val = PointerCast(bcx, val, ty);
}
if is_val && type_is_immediate(cx.ccx, e_ty) {
if is_val && (type_is_immediate(cx.ccx, e_ty) ||
ty::type_is_unique(cx.ccx.tcx, e_ty)) {
val = Load(bcx, val);
}
llargs += [val];
@ -3529,6 +3533,7 @@ fn trans_bind_thunk(cx: &@local_ctxt, sp: &span, incoming_fty: ty::t,
type_of_fn_from_ty(bcx_ccx(bcx), sp, outgoing_fty, ty_param_count);
lltargetfn = PointerCast(bcx, lltargetfn, T_ptr(T_ptr(lltargetty)));
lltargetfn = Load(bcx, lltargetfn);
FastCall(bcx, lltargetfn, llargs);
build_return(bcx);
finish_fn(fcx, lltop);
@ -3629,25 +3634,25 @@ fn trans_arg_expr(cx: &@block_ctxt, arg: &ty::arg, lldestty0: TypeRef,
// to have type lldestty0 (the callee's expected type).
val = llvm::LLVMGetUndef(lldestty0);
} else if arg.mode == ty::mo_val {
if !lv.is_mem {
// Do nothing for temporaries, just give them to callee
if ty::type_is_vec(ccx.tcx, e_ty) {
let r = do_spill(bcx, Load(bcx, val), e_ty);
bcx = r.bcx;
let arg_copy = r.val;
bcx = take_ty(bcx, arg_copy, e_ty);
val = Load(bcx, arg_copy);
add_clean_temp(bcx, arg_copy, e_ty);
} else if !lv.is_mem {
// Do nothing for non-vector temporaries; just give them to the
// callee.
} else if type_is_structural_or_param(ccx.tcx, e_ty) {
let dst = alloc_ty(bcx, e_ty);
bcx = copy_val(dst.bcx, INIT, dst.val, val, e_ty);
val = dst.val;
add_clean_temp(bcx, val, e_ty);
} else {
if ty::type_is_vec(ccx.tcx, e_ty) {
let r = do_spill(bcx, Load(bcx, val), e_ty);
bcx = r.bcx;
let arg_copy = r.val;
bcx = take_ty(bcx, arg_copy, e_ty);
val = Load(bcx, arg_copy);
} else {
bcx = take_ty(bcx, val, e_ty);
val = load_if_immediate(bcx, val, e_ty);
}
bcx = take_ty(bcx, val, e_ty);
val = load_if_immediate(bcx, val, e_ty);
add_clean_temp(bcx, val, e_ty);
}
} else if type_is_immediate(ccx, e_ty) && !lv.is_mem {
@ -4185,7 +4190,7 @@ fn with_out_method(work: fn(&out_method) -> result, cx: @block_ctxt,
// immediate-ness of the type.
fn type_is_immediate(ccx: &@crate_ctxt, t: ty::t) -> bool {
ret ty::type_is_scalar(ccx.tcx, t) || ty::type_is_boxed(ccx.tcx, t) ||
ty::type_is_native(ccx.tcx, t) || ty::type_is_vec(ccx.tcx, t);
ty::type_is_native(ccx.tcx, t);
}
fn do_spill(cx: &@block_ctxt, v: ValueRef, t: ty::t) -> result {
@ -5305,9 +5310,12 @@ fn trans_tag_variant(cx: @local_ctxt, tag_id: ast::node_id,
let arg_ty = arg_tys[i].ty;
let llargval;
if ty::type_is_structural(cx.ccx.tcx, arg_ty) ||
ty::type_has_dynamic_size(cx.ccx.tcx, arg_ty) {
ty::type_has_dynamic_size(cx.ccx.tcx, arg_ty) ||
ty::type_is_unique(cx.ccx.tcx, arg_ty) {
llargval = llargptr;
} else { llargval = Load(bcx, llargptr); }
} else {
llargval = Load(bcx, llargptr);
}
bcx = copy_val(bcx, INIT, lldestptr, llargval, arg_ty);
i += 1u;
}

View File

@ -407,8 +407,10 @@ fn compile_submatch(bcx: @block_ctxt, m: &match, vals: [ValueRef],
}
}
lit(l) {
test_val = Load(bcx, val);
kind = alt l.node { ast::lit_str(_) { compare } _ { switch } };
kind = alt l.node {
ast::lit_str(_) { compare }
_ { test_val = Load(bcx, val); switch }
};
}
}
}

View File

@ -7,19 +7,20 @@ import trans::{call_memmove, trans_shared_malloc, llsize_of, type_of_or_i8,
incr_ptr, INIT, copy_val, load_if_immediate, alloca, size_of,
llderivedtydescs_block_ctxt, lazily_emit_tydesc_glue,
get_tydesc, load_inbounds, move_val_if_temp, trans_lval,
node_id_type, new_sub_block_ctxt, tps_normal, do_spill_noroot};
node_id_type, new_sub_block_ctxt, tps_normal, do_spill_noroot,
GEPi, alloc_ty};
import trans_build::*;
import trans_common::*;
fn get_fill(bcx: &@block_ctxt, vptr: ValueRef) -> ValueRef {
Load(bcx, InBoundsGEP(bcx, vptr, [C_int(0), C_uint(abi::vec_elt_fill)]))
fn get_fill(bcx: &@block_ctxt, vptrptr: ValueRef) -> ValueRef {
Load(bcx, GEPi(bcx, Load(bcx, vptrptr), [0, abi::vec_elt_fill as int]))
}
fn get_alloc(bcx: &@block_ctxt, vptr: ValueRef) -> ValueRef {
Load(bcx, InBoundsGEP(bcx, vptr, [C_int(0), C_uint(abi::vec_elt_alloc)]))
fn get_alloc(bcx: &@block_ctxt, vptrptr: ValueRef) -> ValueRef {
Load(bcx, GEPi(bcx, Load(bcx, vptrptr), [0, abi::vec_elt_alloc as int]))
}
fn get_dataptr(bcx: &@block_ctxt, vpt: ValueRef, unit_ty: TypeRef) ->
fn get_dataptr(bcx: &@block_ctxt, vptrptr: ValueRef, unit_ty: TypeRef) ->
ValueRef {
let ptr = InBoundsGEP(bcx, vpt, [C_int(0), C_uint(abi::vec_elt_elems)]);
let ptr = GEPi(bcx, Load(bcx, vptrptr), [0, abi::vec_elt_elems as int]);
PointerCast(bcx, ptr, T_ptr(unit_ty))
}
@ -59,17 +60,22 @@ fn alloc(bcx: &@block_ctxt, vec_ty: &ty::t, elts: uint) -> alloc_result {
let alloc = if elts < 4u { Mul(bcx, C_int(4), unit_sz) } else { fill };
let {bcx: bcx, val: vptr} = alloc_raw(bcx, fill, alloc);
let vptr = PointerCast(bcx, vptr, T_ptr(llvecty));
add_clean_temp(bcx, vptr, vec_ty);
let r = alloc_ty(bcx, vec_ty);
let vptrptr = r.val; bcx = r.bcx;
Store(bcx, vptr, vptrptr);
add_clean_temp(bcx, vptrptr, vec_ty);
ret {bcx: bcx,
val: vptr,
val: vptrptr,
unit_ty: unit_ty,
llunitsz: unit_sz,
llunitty: llunitty};
}
fn duplicate(bcx: &@block_ctxt, vptrptr: ValueRef) -> @block_ctxt {
let fill = get_fill(bcx, vptrptr);
let vptr = Load(bcx, vptrptr);
let fill = get_fill(bcx, vptr);
let size = Add(bcx, fill, llsize_of(T_opaque_vec()));
let {bcx: bcx, val: newptr} =
trans_shared_malloc(bcx, val_ty(vptr), size);
@ -135,13 +141,13 @@ fn trans_str(bcx: &@block_ctxt, s: str) -> result {
}
fn trans_append(cx: &@block_ctxt, vec_ty: ty::t, lhsptr: ValueRef,
rhs: ValueRef) -> result {
rhsptr: ValueRef) -> result {
// Cast to opaque interior vector types if necessary.
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 {
lhsptr = PointerCast(cx, lhsptr, T_ptr(T_ptr(T_opaque_vec())));
rhs = PointerCast(cx, rhs, T_ptr(T_opaque_vec()));
rhsptr = PointerCast(cx, rhsptr, T_ptr(T_ptr(T_opaque_vec())));
}
let strings =
alt ty::struct(bcx_tcx(cx), vec_ty) {
@ -152,26 +158,26 @@ fn trans_append(cx: &@block_ctxt, vec_ty: ty::t, lhsptr: ValueRef,
let {bcx: bcx, val: unit_sz} = size_of(cx, unit_ty);
let llunitty = type_of_or_i8(cx, unit_ty);
let rhs = Load(bcx, rhsptr);
let lhs = Load(bcx, lhsptr);
let self_append = ICmp(bcx, lib::llvm::LLVMIntEQ, lhs, rhs);
let lfill = get_fill(bcx, lhs);
let rfill = get_fill(bcx, rhs);
let lfill = get_fill(bcx, lhsptr);
let rfill = get_fill(bcx, rhsptr);
let new_fill = Add(bcx, lfill, rfill);
if strings { new_fill = Sub(bcx, new_fill, C_int(1)); }
let opaque_lhs = PointerCast(bcx, lhsptr, T_ptr(T_ptr(T_opaque_vec())));
Call(bcx, bcx_ccx(cx).upcalls.vec_grow,
[cx.fcx.lltaskptr, opaque_lhs, new_fill]);
// Was overwritten if we resized
let lhs = Load(bcx, lhsptr);
let rhs = Select(bcx, self_append, lhs, rhs);
rhsptr = Select(bcx, self_append, lhsptr, rhsptr);
let lhs_data = get_dataptr(bcx, lhs, llunitty);
let lhs_data = get_dataptr(bcx, lhsptr, llunitty);
let lhs_off = lfill;
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_noroot(bcx, write_ptr);
let bcx =
iter_vec_raw(bcx, rhs, vec_ty, rfill,
iter_vec_raw(bcx, rhsptr, vec_ty, rfill,
// We have to increment by the dynamically-computed size.
{|&bcx, addr, _ty|
let write_ptr = Load(bcx, write_ptr_ptr);
@ -211,7 +217,8 @@ fn trans_append_literal(bcx: &@block_ctxt, vptrptr: ValueRef, vec_ty: ty::t,
ret bcx;
}
fn trans_add(bcx: &@block_ctxt, vec_ty: ty::t, lhs: ValueRef, rhs: ValueRef)
fn trans_add(bcx: &@block_ctxt, vec_ty: ty::t, lhsptr: ValueRef,
rhsptr: ValueRef)
-> result {
let strings =
alt ty::struct(bcx_tcx(bcx), vec_ty) {
@ -222,16 +229,18 @@ fn trans_add(bcx: &@block_ctxt, vec_ty: ty::t, lhs: ValueRef, rhs: ValueRef)
let llunitty = type_of_or_i8(bcx, unit_ty);
let {bcx: bcx, val: llunitsz} = size_of(bcx, unit_ty);
let lhs_fill = get_fill(bcx, lhs);
let lhs_fill = get_fill(bcx, lhsptr);
if strings { lhs_fill = Sub(bcx, lhs_fill, C_int(1)); }
let rhs_fill = get_fill(bcx, rhs);
let rhs_fill = get_fill(bcx, rhsptr);
let new_fill = Add(bcx, lhs_fill, rhs_fill);
let {bcx: bcx, val: new_vec} = alloc_raw(bcx, new_fill, new_fill);
let new_vec = PointerCast(bcx, new_vec, T_ptr(T_vec(llunitty)));
add_clean_temp(bcx, new_vec, vec_ty);
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)));
let {bcx: bcx, val: new_vec_ptr_ptr} = alloc_ty(bcx, vec_ty);
Store(bcx, new_vec_ptr, new_vec_ptr_ptr);
add_clean_temp(bcx, new_vec_ptr_ptr, vec_ty);
let write_ptr_ptr =
do_spill_noroot(bcx, get_dataptr(bcx, new_vec, llunitty));
do_spill_noroot(bcx, get_dataptr(bcx, new_vec_ptr_ptr, llunitty));
let copy_fn =
bind fn (bcx: &@block_ctxt, addr: ValueRef, _ty: ty::t,
write_ptr_ptr: ValueRef, unit_ty: ty::t, llunitsz: ValueRef)
@ -247,22 +256,22 @@ fn trans_add(bcx: &@block_ctxt, vec_ty: ty::t, lhs: ValueRef, rhs: ValueRef)
ret bcx;
}(_, _, _, write_ptr_ptr, unit_ty, llunitsz);
let bcx = iter_vec_raw(bcx, lhs, vec_ty, lhs_fill, copy_fn);
let bcx = iter_vec_raw(bcx, rhs, vec_ty, rhs_fill, copy_fn);
ret rslt(bcx, new_vec);
let bcx = iter_vec_raw(bcx, lhsptr, vec_ty, lhs_fill, copy_fn);
let bcx = iter_vec_raw(bcx, rhsptr, vec_ty, rhs_fill, copy_fn);
ret rslt(bcx, new_vec_ptr_ptr);
}
type val_and_ty_fn = fn(&@block_ctxt, ValueRef, ty::t) -> result;
type iter_vec_block = block(&@block_ctxt, ValueRef, ty::t) -> @block_ctxt;
fn iter_vec_raw(bcx: &@block_ctxt, vptr: ValueRef, vec_ty: ty::t,
fn iter_vec_raw(bcx: &@block_ctxt, vptrptr: ValueRef, vec_ty: ty::t,
fill: ValueRef, f: &iter_vec_block) -> @block_ctxt {
let unit_ty = ty::sequence_element_type(bcx_tcx(bcx), vec_ty);
let llunitty = type_of_or_i8(bcx, unit_ty);
let {bcx: bcx, val: unit_sz} = size_of(bcx, unit_ty);
let vptr = PointerCast(bcx, vptr, T_ptr(T_vec(llunitty)));
let data_ptr = get_dataptr(bcx, vptr, llunitty);
vptrptr = PointerCast(bcx, vptrptr, T_ptr(T_ptr(T_vec(llunitty))));
let data_ptr = get_dataptr(bcx, vptrptr, llunitty);
// Calculate the last pointer address we want to handle.
// TODO: Optimize this when the size of the unit type is statically
@ -292,9 +301,8 @@ fn iter_vec_raw(bcx: &@block_ctxt, vptr: ValueRef, vec_ty: ty::t,
fn iter_vec(bcx: &@block_ctxt, vptrptr: ValueRef, vec_ty: ty::t,
f: &iter_vec_block) -> @block_ctxt {
let vptr =
Load(bcx, PointerCast(bcx, vptrptr, T_ptr(T_ptr(T_opaque_vec()))));
ret iter_vec_raw(bcx, vptr, vec_ty, get_fill(bcx, vptr), f);
vptrptr = PointerCast(bcx, vptrptr, T_ptr(T_ptr(T_opaque_vec())));
ret iter_vec_raw(bcx, vptrptr, vec_ty, get_fill(bcx, vptrptr), f);
}
//