mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-02 19:06:05 +00:00
Get fixed-size evecs working.
This commit is contained in:
parent
7ba0dce013
commit
1e51196f33
@ -259,6 +259,12 @@ fn alloca(cx: block, t: TypeRef) -> ValueRef {
|
||||
ret Alloca(raw_block(cx.fcx, cx.fcx.llstaticallocas), t);
|
||||
}
|
||||
|
||||
fn arrayalloca(cx: block, t: TypeRef, v: ValueRef) -> ValueRef {
|
||||
let _icx = cx.insn_ctxt("arrayalloca");
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(t); }
|
||||
ret ArrayAlloca(raw_block(cx.fcx, cx.fcx.llstaticallocas), t, v);
|
||||
}
|
||||
|
||||
// Given a pointer p, returns a pointer sz(p) (i.e., inc'd by sz bytes).
|
||||
// The type of the returned pointer is always i8*. If you care about the
|
||||
// return type, use bump_ptr().
|
||||
@ -584,7 +590,7 @@ fn make_take_glue(bcx: block, v: ValueRef, t: ty::t) {
|
||||
}
|
||||
ty::ty_vec(_) | ty::ty_str |
|
||||
ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) {
|
||||
let {bcx, val} = tvec::duplicate(bcx, Load(bcx, v), t);
|
||||
let {bcx, val} = tvec::duplicate_uniq(bcx, Load(bcx, v), t);
|
||||
Store(bcx, val, v);
|
||||
bcx
|
||||
}
|
||||
@ -928,7 +934,8 @@ fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t,
|
||||
}
|
||||
ty::ty_estr(ty::vstore_fixed(n)) |
|
||||
ty::ty_evec(_, ty::vstore_fixed(n)) {
|
||||
cx = tvec::iter_vec_raw(cx, av, t, C_uint(cx.ccx(), n), f);
|
||||
let (base, len) = tvec::get_base_and_len(cx, av, t);
|
||||
cx = tvec::iter_vec_raw(cx, base, t, len, f);
|
||||
}
|
||||
ty::ty_tup(args) {
|
||||
for vec::eachi(args) {|i, arg|
|
||||
@ -1170,7 +1177,7 @@ fn take_ty_immediate(bcx: block, v: ValueRef, t: ty::t) -> result {
|
||||
ty::ty_str | ty::ty_vec(_) |
|
||||
ty::ty_evec(_, ty::vstore_uniq) |
|
||||
ty::ty_estr(ty::vstore_uniq) {
|
||||
tvec::duplicate(bcx, v, t)
|
||||
tvec::duplicate_uniq(bcx, v, t)
|
||||
}
|
||||
_ { rslt(bcx, v) }
|
||||
}
|
||||
@ -3121,7 +3128,9 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
|
||||
ast::expr_tup(args) { ret trans_tup(bcx, args, dest); }
|
||||
ast::expr_vstore(e, v) { ret tvec::trans_vstore(bcx, e, v, dest); }
|
||||
ast::expr_lit(lit) { ret trans_lit(bcx, *lit, dest); }
|
||||
ast::expr_vec(args, _) { ret tvec::trans_vec(bcx, args, e.id, dest); }
|
||||
ast::expr_vec(args, _) {
|
||||
ret tvec::trans_evec(bcx, args, ast::vstore_uniq, e.id, dest);
|
||||
}
|
||||
ast::expr_binary(op, lhs, rhs) {
|
||||
ret trans_binary(bcx, op, lhs, rhs, dest, e);
|
||||
}
|
||||
|
@ -367,6 +367,7 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t, ty_param_map: [uint]) -> [u8] {
|
||||
let u8_t = ty::mk_mach_uint(ccx.tcx, ast::ty_u8);
|
||||
while i < n {
|
||||
sub += shape_of(ccx, u8_t, ty_param_map);
|
||||
i += 1u;
|
||||
}
|
||||
add_substr(s, sub);
|
||||
s
|
||||
@ -377,6 +378,7 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t, ty_param_map: [uint]) -> [u8] {
|
||||
let mut i = 0u;
|
||||
while i < n {
|
||||
sub += shape_of(ccx, mt.ty, ty_param_map);
|
||||
i += 1u;
|
||||
}
|
||||
add_substr(s, sub);
|
||||
s
|
||||
|
@ -35,8 +35,8 @@ fn pointer_add(bcx: block, ptr: ValueRef, bytes: ValueRef) -> ValueRef {
|
||||
ret PointerCast(bcx, InBoundsGEP(bcx, bptr, [bytes]), old_ty);
|
||||
}
|
||||
|
||||
fn alloc_raw(bcx: block, fill: ValueRef, alloc: ValueRef) -> result {
|
||||
let _icx = bcx.insn_ctxt("tvec::alloc_raw");
|
||||
fn alloc_uniq_raw(bcx: block, fill: ValueRef, alloc: ValueRef) -> result {
|
||||
let _icx = bcx.insn_ctxt("tvec::alloc_uniq_raw");
|
||||
let ccx = bcx.ccx();
|
||||
let llvecty = ccx.opaque_vec_type;
|
||||
let vecsize = Add(bcx, alloc, llsize_of(ccx, llvecty));
|
||||
@ -46,34 +46,23 @@ fn alloc_raw(bcx: block, fill: ValueRef, alloc: ValueRef) -> result {
|
||||
ret {bcx: bcx, val: vecptr};
|
||||
}
|
||||
|
||||
type alloc_result =
|
||||
{bcx: block,
|
||||
val: ValueRef,
|
||||
unit_ty: ty::t,
|
||||
llunitty: TypeRef};
|
||||
|
||||
fn alloc(bcx: block, vec_ty: ty::t, elts: uint) -> alloc_result {
|
||||
let _icx = bcx.insn_ctxt("tvec::alloc");
|
||||
fn alloc_uniq(bcx: block, llunitty: TypeRef, elts: uint) -> result {
|
||||
let _icx = bcx.insn_ctxt("tvec::alloc_uniq");
|
||||
let ccx = bcx.ccx();
|
||||
let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty);
|
||||
let llunitty = type_of::type_of(ccx, unit_ty);
|
||||
let llvecty = T_vec(ccx, llunitty);
|
||||
let unit_sz = llsize_of(ccx, llunitty);
|
||||
|
||||
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_raw(bcx, fill, alloc);
|
||||
let {bcx: bcx, val: vptr} = alloc_uniq_raw(bcx, fill, alloc);
|
||||
let vptr = PointerCast(bcx, vptr, T_ptr(llvecty));
|
||||
|
||||
ret {bcx: bcx,
|
||||
val: vptr,
|
||||
unit_ty: unit_ty,
|
||||
llunitty: llunitty};
|
||||
ret {bcx: bcx, val: vptr};
|
||||
}
|
||||
|
||||
fn duplicate(bcx: block, vptr: ValueRef, vec_ty: ty::t) -> result {
|
||||
let _icx = bcx.insn_ctxt("tvec::duplicate");
|
||||
fn duplicate_uniq(bcx: block, vptr: ValueRef, vec_ty: ty::t) -> result {
|
||||
let _icx = bcx.insn_ctxt("tvec::duplicate_uniq");
|
||||
let ccx = bcx.ccx();
|
||||
let fill = get_fill(bcx, vptr);
|
||||
let size = Add(bcx, fill, llsize_of(ccx, ccx.opaque_vec_type));
|
||||
@ -98,9 +87,9 @@ fn make_free_glue(bcx: block, vptr: ValueRef, vec_ty: ty::t) ->
|
||||
}
|
||||
}
|
||||
|
||||
fn trans_vec(bcx: block, args: [@ast::expr], id: ast::node_id,
|
||||
dest: dest) -> block {
|
||||
let _icx = bcx.insn_ctxt("tvec::trans_vec");
|
||||
fn trans_evec(bcx: block, args: [@ast::expr],
|
||||
vst: ast::vstore, id: ast::node_id, dest: dest) -> block {
|
||||
let _icx = bcx.insn_ctxt("tvec::trans_evec");
|
||||
let ccx = bcx.ccx();
|
||||
let mut bcx = bcx;
|
||||
if dest == base::ignore {
|
||||
@ -109,16 +98,50 @@ fn trans_vec(bcx: block, args: [@ast::expr], id: ast::node_id,
|
||||
}
|
||||
ret bcx;
|
||||
}
|
||||
let vec_ty = node_id_type(bcx, id);
|
||||
let mut {bcx: bcx,
|
||||
val: vptr,
|
||||
unit_ty: unit_ty,
|
||||
llunitty: llunitty} = alloc(bcx, vec_ty, args.len());
|
||||
|
||||
add_clean_free(bcx, vptr, true);
|
||||
let vec_ty = node_id_type(bcx, id);
|
||||
let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty);
|
||||
let llunitty = type_of::type_of(ccx, unit_ty);
|
||||
|
||||
let mut {bcx, val, dataptr} =
|
||||
alt vst {
|
||||
ast::vstore_fixed(_) {
|
||||
// Destination should be pre-allocated for us.
|
||||
let v = alt dest {
|
||||
base::save_in(v) {
|
||||
PointerCast(bcx, v, T_ptr(llunitty))
|
||||
}
|
||||
_ {
|
||||
bcx.ccx().sess.bug("bad dest for vstore_fixed \
|
||||
in tvec::trans_evec");
|
||||
}
|
||||
};
|
||||
{bcx: bcx, val: v, dataptr: v}
|
||||
}
|
||||
ast::vstore_slice(_) {
|
||||
let n = vec::len(args);
|
||||
let n = C_uint(ccx, n);
|
||||
let vp = base::arrayalloca(bcx, llunitty, n);
|
||||
let v = C_struct([vp, n]);
|
||||
{bcx: bcx, val: v, dataptr: vp}
|
||||
}
|
||||
ast::vstore_uniq {
|
||||
let {bcx, val} = alloc_uniq(bcx, llunitty, args.len());
|
||||
add_clean_free(bcx, val, true);
|
||||
let dataptr = get_dataptr(bcx, val, llunitty);
|
||||
{bcx: bcx, val: val, dataptr: dataptr}
|
||||
}
|
||||
ast::vstore_box {
|
||||
bcx.ccx().sess.unimpl("unhandled tvec::trans_evec");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Store the individual elements.
|
||||
let dataptr = get_dataptr(bcx, vptr, llunitty);
|
||||
let mut i = 0u, temp_cleanups = [vptr];
|
||||
let mut i = 0u, temp_cleanups = [val];
|
||||
#debug("trans_evec: v: %s, dataptr: %s",
|
||||
val_str(ccx.tn, val),
|
||||
val_str(ccx.tn, dataptr));
|
||||
for vec::each(args) {|e|
|
||||
let lleltptr = InBoundsGEP(bcx, dataptr, [C_uint(ccx, i)]);
|
||||
bcx = base::trans_expr_save_in(bcx, e, lleltptr);
|
||||
@ -126,8 +149,18 @@ fn trans_vec(bcx: block, args: [@ast::expr], id: ast::node_id,
|
||||
temp_cleanups += [lleltptr];
|
||||
i += 1u;
|
||||
}
|
||||
|
||||
for vec::each(temp_cleanups) {|cln| revoke_clean(bcx, cln); }
|
||||
ret base::store_in_dest(bcx, vptr, dest);
|
||||
|
||||
alt vst {
|
||||
ast::vstore_fixed(_) {
|
||||
// We wrote into the destination in the fixed case.
|
||||
ret bcx;
|
||||
}
|
||||
_ {
|
||||
ret base::store_in_dest(bcx, val, dest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn trans_vstore(bcx: block, e: @ast::expr,
|
||||
@ -137,7 +170,7 @@ fn trans_vstore(bcx: block, e: @ast::expr,
|
||||
ret trans_estr(bcx, s, v, dest);
|
||||
}
|
||||
ast::expr_vec(es, mutbl) {
|
||||
bcx.ccx().sess.span_unimpl(e.span, "unhandled tvec::trans_vstore");
|
||||
ret trans_evec(bcx, es, v, e.id, dest);
|
||||
}
|
||||
_ {
|
||||
bcx.sess().span_bug(e.span, "vstore on non-sequence type");
|
||||
@ -148,9 +181,13 @@ fn trans_vstore(bcx: block, e: @ast::expr,
|
||||
fn get_base_and_len(cx: block, v: ValueRef, e_ty: ty::t)
|
||||
-> (ValueRef, ValueRef) {
|
||||
|
||||
let tcx = cx.ccx().tcx;
|
||||
let ccx = cx.ccx();
|
||||
let tcx = ccx.tcx;
|
||||
let vec_ty = ty::type_autoderef(tcx, e_ty);
|
||||
let unit_ty = ty::sequence_element_type(tcx, vec_ty);
|
||||
let llunitty = type_of::type_of(ccx, unit_ty);
|
||||
let unit_sz = llsize_of(ccx, llunitty);
|
||||
|
||||
let vstore = alt ty::get(vec_ty).struct {
|
||||
ty::ty_estr(vst) | ty::ty_evec(_, vst) { vst }
|
||||
_ { ty::vstore_uniq }
|
||||
@ -159,7 +196,8 @@ fn get_base_and_len(cx: block, v: ValueRef, e_ty: ty::t)
|
||||
alt vstore {
|
||||
ty::vstore_fixed(n) {
|
||||
let base = GEPi(cx, v, [0, 0]);
|
||||
let len = C_uint(cx.ccx(), n + 1u /* +1 for null */);
|
||||
let n = if ty::type_is_str(e_ty) { n + 1u } else { n };
|
||||
let len = Mul(cx, C_uint(ccx, n), unit_sz);
|
||||
(base, len)
|
||||
}
|
||||
ty::vstore_slice(_) {
|
||||
@ -168,8 +206,7 @@ fn get_base_and_len(cx: block, v: ValueRef, e_ty: ty::t)
|
||||
(base, len)
|
||||
}
|
||||
ty::vstore_uniq {
|
||||
let base = tvec::get_dataptr(cx, v,
|
||||
type_of::type_of(cx.ccx(), unit_ty));
|
||||
let base = tvec::get_dataptr(cx, v, llunitty);
|
||||
let len = tvec::get_fill(cx, v);
|
||||
(base, len)
|
||||
}
|
||||
@ -222,11 +259,7 @@ fn trans_append(bcx: block, vec_ty: ty::t, lhsptr: ValueRef,
|
||||
// Cast to opaque interior vector types if necessary.
|
||||
let ccx = bcx.ccx();
|
||||
let unit_ty = ty::sequence_element_type(ccx.tcx, vec_ty);
|
||||
let strings = alt check ty::get(vec_ty).struct {
|
||||
ty::ty_str { true }
|
||||
ty::ty_vec(_) { false }
|
||||
};
|
||||
|
||||
let strings = ty::type_is_str(vec_ty);
|
||||
let llunitty = type_of::type_of(ccx, unit_ty);
|
||||
|
||||
let lhs = Load(bcx, lhsptr);
|
||||
@ -248,7 +281,7 @@ fn trans_append(bcx: block, vec_ty: ty::t, lhsptr: ValueRef,
|
||||
if strings { lhs_off = Sub(bcx, lhs_off, C_int(ccx, 1)); }
|
||||
let write_ptr = pointer_add(bcx, lhs_data, lhs_off);
|
||||
let write_ptr_ptr = do_spill_noroot(bcx, write_ptr);
|
||||
iter_vec_raw(bcx, rhs, vec_ty, rfill, {|bcx, addr, _ty|
|
||||
iter_vec_uniq(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);
|
||||
@ -304,7 +337,8 @@ fn trans_add(bcx: block, vec_ty: ty::t, lhs: ValueRef,
|
||||
let lhs_fill = get_fill(bcx, lhs);
|
||||
let rhs_fill = get_fill(bcx, rhs);
|
||||
let new_fill = Add(bcx, lhs_fill, rhs_fill);
|
||||
let mut {bcx: bcx, val: new_vec_ptr} = alloc_raw(bcx, new_fill, new_fill);
|
||||
let mut {bcx: bcx, val: new_vec_ptr} =
|
||||
alloc_uniq_raw(bcx, new_fill, new_fill);
|
||||
new_vec_ptr = PointerCast(bcx, new_vec_ptr, T_ptr(T_vec(ccx, llunitty)));
|
||||
|
||||
let write_ptr_ptr = do_spill_noroot
|
||||
@ -320,8 +354,8 @@ fn trans_add(bcx: block, vec_ty: ty::t, lhs: ValueRef,
|
||||
ret bcx;
|
||||
};
|
||||
|
||||
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);
|
||||
let bcx = iter_vec_uniq(bcx, lhs, vec_ty, lhs_fill, copy_fn);
|
||||
let bcx = iter_vec_uniq(bcx, rhs, vec_ty, rhs_fill, copy_fn);
|
||||
ret base::store_in_dest(bcx, new_vec_ptr, dest);
|
||||
}
|
||||
|
||||
@ -329,14 +363,11 @@ type val_and_ty_fn = fn@(block, ValueRef, ty::t) -> result;
|
||||
|
||||
type iter_vec_block = fn(block, ValueRef, ty::t) -> block;
|
||||
|
||||
fn iter_vec_raw(bcx: block, vptr: ValueRef, vec_ty: ty::t,
|
||||
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_raw");
|
||||
let ccx = bcx.ccx();
|
||||
let _icx = bcx.insn_ctxt("tvec::iter_vec_uniq");
|
||||
|
||||
let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty);
|
||||
let llunitty = type_of::type_of(ccx, unit_ty);
|
||||
let vptr = PointerCast(bcx, vptr, T_ptr(T_vec(ccx, llunitty)));
|
||||
let data_ptr = get_dataptr(bcx, vptr, llunitty);
|
||||
|
||||
// Calculate the last pointer address we want to handle.
|
||||
// FIXME: Optimize this when the size of the unit type is statically
|
||||
@ -354,16 +385,29 @@ fn iter_vec_raw(bcx: block, vptr: ValueRef, vec_ty: ty::t,
|
||||
CondBr(header_cx, not_yet_at_end, body_cx.llbb, next_cx.llbb);
|
||||
let body_cx = f(body_cx, data_ptr, unit_ty);
|
||||
AddIncomingToPhi(data_ptr, InBoundsGEP(body_cx, data_ptr,
|
||||
[C_int(ccx, 1)]), body_cx.llbb);
|
||||
[C_int(bcx.ccx(), 1)]),
|
||||
body_cx.llbb);
|
||||
Br(body_cx, header_cx.llbb);
|
||||
ret next_cx;
|
||||
|
||||
}
|
||||
|
||||
fn iter_vec_uniq(bcx: block, vptr: ValueRef, vec_ty: ty::t,
|
||||
fill: ValueRef, f: iter_vec_block) -> block {
|
||||
let _icx = bcx.insn_ctxt("tvec::iter_vec_uniq");
|
||||
let ccx = bcx.ccx();
|
||||
let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty);
|
||||
let llunitty = type_of::type_of(ccx, unit_ty);
|
||||
let vptr = PointerCast(bcx, vptr, T_ptr(T_vec(ccx, llunitty)));
|
||||
let data_ptr = get_dataptr(bcx, vptr, llunitty);
|
||||
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 vptr = PointerCast(bcx, vptr, T_ptr(bcx.ccx().opaque_vec_type));
|
||||
ret iter_vec_raw(bcx, vptr, vec_ty, get_fill(bcx, vptr), f);
|
||||
ret iter_vec_uniq(bcx, vptr, vec_ty, get_fill(bcx, vptr), f);
|
||||
}
|
||||
|
||||
//
|
||||
|
8
src/test/run-pass/evec-internal-boxes.rs
Normal file
8
src/test/run-pass/evec-internal-boxes.rs
Normal file
@ -0,0 +1,8 @@
|
||||
fn main() {
|
||||
let x : [@int]/5 = [@1,@2,@3,@4,@5]/5;
|
||||
let _y : [@int]/5 = [@1,@2,@3,@4,@5]/_;
|
||||
let mut z = [@1,@2,@3,@4,@5]/_;
|
||||
z = x;
|
||||
assert *z[0] == 1;
|
||||
assert *z[4] == 5;
|
||||
}
|
8
src/test/run-pass/evec-internal.rs
Normal file
8
src/test/run-pass/evec-internal.rs
Normal file
@ -0,0 +1,8 @@
|
||||
fn main() {
|
||||
let x : [int]/5 = [1,2,3,4,5]/5;
|
||||
let _y : [int]/5 = [1,2,3,4,5]/_;
|
||||
let mut z = [1,2,3,4,5]/_;
|
||||
z = x;
|
||||
assert z[0] == 1;
|
||||
assert z[4] == 5;
|
||||
}
|
Loading…
Reference in New Issue
Block a user