2011-08-22 13:48:00 -05:00
|
|
|
import syntax::ast;
|
2012-01-30 23:00:57 -06:00
|
|
|
import driver::session::session;
|
2012-02-01 04:04:56 -06:00
|
|
|
import lib::llvm::{ValueRef, TypeRef};
|
2011-08-22 13:48:00 -05:00
|
|
|
import back::abi;
|
2012-05-25 19:22:14 -05:00
|
|
|
import base::{call_memmove,
|
2012-06-07 12:51:21 -05:00
|
|
|
INIT, copy_val, load_if_immediate, get_tydesc,
|
|
|
|
sub_block, do_spill_noroot,
|
2012-08-03 20:48:17 -05:00
|
|
|
dest, bcx_icx, non_gc_box_cast, move_val, lval_owned};
|
2012-04-09 19:32:49 -05:00
|
|
|
import syntax::codemap::span;
|
2012-03-12 04:05:15 -05:00
|
|
|
import shape::llsize_of;
|
2012-01-27 06:17:06 -06:00
|
|
|
import build::*;
|
|
|
|
import common::*;
|
2012-06-12 18:41:20 -05:00
|
|
|
import util::ppaux::ty_to_str;
|
2011-08-22 13:48:00 -05:00
|
|
|
|
2012-06-14 19:34:06 -05:00
|
|
|
// Boxed vector types are in some sense currently a "shorthand" for a box
|
|
|
|
// containing an unboxed vector. This expands a boxed vector type into such an
|
|
|
|
// expanded type. It doesn't respect mutability, but that doesn't matter at
|
|
|
|
// this point.
|
|
|
|
fn expand_boxed_vec_ty(tcx: ty::ctxt, t: ty::t) -> ty::t {
|
|
|
|
let unit_ty = ty::sequence_element_type(tcx, t);
|
|
|
|
let unboxed_vec_ty = ty::mk_mut_unboxed_vec(tcx, unit_ty);
|
|
|
|
alt ty::get(t).struct {
|
|
|
|
ty::ty_estr(ty::vstore_uniq) | ty::ty_evec(_, ty::vstore_uniq) {
|
|
|
|
ty::mk_imm_uniq(tcx, unboxed_vec_ty)
|
|
|
|
}
|
|
|
|
ty::ty_estr(ty::vstore_box) | ty::ty_evec(_, ty::vstore_box) {
|
|
|
|
ty::mk_imm_box(tcx, unboxed_vec_ty)
|
|
|
|
}
|
2012-07-14 00:57:48 -05:00
|
|
|
_ { tcx.sess.bug(~"non boxed-vec type \
|
2012-06-14 19:34:06 -05:00
|
|
|
in tvec::expand_boxed_vec_ty");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn get_fill(bcx: block, vptr: ValueRef) -> ValueRef {
|
2012-07-14 00:57:48 -05:00
|
|
|
let _icx = bcx.insn_ctxt(~"tvec::get_fill");
|
2012-06-29 18:26:56 -05:00
|
|
|
Load(bcx, GEPi(bcx, vptr, ~[0u, abi::vec_elt_fill]))
|
2011-08-25 03:18:02 -05:00
|
|
|
}
|
2012-03-22 10:02:34 -05:00
|
|
|
fn set_fill(bcx: block, vptr: ValueRef, fill: ValueRef) {
|
2012-06-29 18:26:56 -05:00
|
|
|
Store(bcx, fill, GEPi(bcx, vptr, ~[0u, abi::vec_elt_fill]));
|
2012-03-22 10:02:34 -05:00
|
|
|
}
|
|
|
|
fn get_alloc(bcx: block, vptr: ValueRef) -> ValueRef {
|
2012-06-29 18:26:56 -05:00
|
|
|
Load(bcx, GEPi(bcx, vptr, ~[0u, abi::vec_elt_alloc]))
|
2012-03-22 10:02:34 -05:00
|
|
|
}
|
2012-05-21 20:36:52 -05:00
|
|
|
|
2012-06-12 18:41:20 -05:00
|
|
|
fn get_bodyptr(bcx: block, vptr: ValueRef) -> ValueRef {
|
2012-06-29 18:26:56 -05:00
|
|
|
non_gc_box_cast(bcx, GEPi(bcx, vptr, ~[0u, abi::box_field_body]))
|
2012-05-21 20:36:52 -05:00
|
|
|
}
|
|
|
|
|
2012-06-12 18:41:20 -05:00
|
|
|
fn get_dataptr(bcx: block, vptr: ValueRef)
|
2011-09-27 13:21:44 -05:00
|
|
|
-> ValueRef {
|
2012-07-14 00:57:48 -05:00
|
|
|
let _icx = bcx.insn_ctxt(~"tvec::get_dataptr");
|
2012-06-29 18:26:56 -05:00
|
|
|
GEPi(bcx, vptr, ~[0u, abi::vec_elt_elems, 0u])
|
2011-08-25 03:18:02 -05:00
|
|
|
}
|
2011-08-22 13:48:00 -05:00
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
fn pointer_add(bcx: block, ptr: ValueRef, bytes: ValueRef) -> ValueRef {
|
2012-07-14 00:57:48 -05:00
|
|
|
let _icx = bcx.insn_ctxt(~"tvec::pointer_add");
|
2011-08-25 03:18:02 -05:00
|
|
|
let old_ty = val_ty(ptr);
|
|
|
|
let bptr = PointerCast(bcx, ptr, T_ptr(T_i8()));
|
2012-08-01 19:30:05 -05:00
|
|
|
return PointerCast(bcx, InBoundsGEP(bcx, bptr, ~[bytes]), old_ty);
|
2011-08-25 03:18:02 -05:00
|
|
|
}
|
2011-08-22 13:48:00 -05:00
|
|
|
|
2012-06-14 19:34:06 -05:00
|
|
|
fn alloc_raw(bcx: block, unit_ty: ty::t,
|
|
|
|
fill: ValueRef, alloc: ValueRef, heap: heap) -> result {
|
2012-07-14 00:57:48 -05:00
|
|
|
let _icx = bcx.insn_ctxt(~"tvec::alloc_uniq");
|
2012-02-21 07:20:18 -06:00
|
|
|
let ccx = bcx.ccx();
|
2012-06-12 16:54:02 -05:00
|
|
|
|
|
|
|
let vecbodyty = ty::mk_mut_unboxed_vec(bcx.tcx(), unit_ty);
|
|
|
|
let vecsize = Add(bcx, alloc, llsize_of(ccx, ccx.opaque_vec_type));
|
|
|
|
|
2012-07-17 12:48:19 -05:00
|
|
|
let {bcx, box, body} =
|
|
|
|
base::malloc_general_dyn(bcx, vecbodyty, heap, vecsize);
|
2012-06-29 18:26:56 -05:00
|
|
|
Store(bcx, fill, GEPi(bcx, body, ~[0u, abi::vec_elt_fill]));
|
|
|
|
Store(bcx, alloc, GEPi(bcx, body, ~[0u, abi::vec_elt_alloc]));
|
2012-08-01 19:30:05 -05:00
|
|
|
return {bcx: bcx, val: box};
|
2011-08-29 15:30:18 -05:00
|
|
|
}
|
2012-06-14 19:34:06 -05:00
|
|
|
fn alloc_uniq_raw(bcx: block, unit_ty: ty::t,
|
|
|
|
fill: ValueRef, alloc: ValueRef) -> result {
|
|
|
|
alloc_raw(bcx, unit_ty, fill, alloc, heap_exchange)
|
|
|
|
}
|
2011-08-29 15:30:18 -05:00
|
|
|
|
2012-06-14 19:34:06 -05:00
|
|
|
fn alloc_vec(bcx: block, unit_ty: ty::t, elts: uint, heap: heap) -> result {
|
2012-07-14 00:57:48 -05:00
|
|
|
let _icx = bcx.insn_ctxt(~"tvec::alloc_uniq");
|
2012-02-21 07:20:18 -06:00
|
|
|
let ccx = bcx.ccx();
|
2012-05-21 20:36:52 -05:00
|
|
|
let llunitty = type_of::type_of(ccx, unit_ty);
|
2012-03-12 04:05:15 -05:00
|
|
|
let unit_sz = llsize_of(ccx, llunitty);
|
2011-08-25 03:18:02 -05:00
|
|
|
|
2011-10-14 22:38:24 -05:00
|
|
|
let fill = Mul(bcx, C_uint(ccx, elts), unit_sz);
|
2012-03-12 04:05:15 -05:00
|
|
|
let alloc = if elts < 4u { Mul(bcx, C_int(ccx, 4), unit_sz) }
|
|
|
|
else { fill };
|
2012-06-14 19:34:06 -05:00
|
|
|
let {bcx: bcx, val: vptr} = alloc_raw(bcx, unit_ty, fill, alloc, heap);
|
2012-08-01 19:30:05 -05:00
|
|
|
return {bcx: bcx, val: vptr};
|
2011-08-25 03:18:02 -05:00
|
|
|
}
|
2011-08-29 15:30:18 -05:00
|
|
|
|
2012-04-19 17:42:02 -05:00
|
|
|
fn duplicate_uniq(bcx: block, vptr: ValueRef, vec_ty: ty::t) -> result {
|
2012-07-14 00:57:48 -05:00
|
|
|
let _icx = bcx.insn_ctxt(~"tvec::duplicate_uniq");
|
2012-05-21 20:36:52 -05:00
|
|
|
|
2012-06-13 12:46:33 -05:00
|
|
|
let fill = get_fill(bcx, get_bodyptr(bcx, vptr));
|
2012-02-21 07:20:18 -06:00
|
|
|
let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty);
|
2012-06-13 12:46:33 -05:00
|
|
|
let {bcx, val: newptr} = alloc_uniq_raw(bcx, unit_ty, fill, fill);
|
|
|
|
|
|
|
|
let data_ptr = get_dataptr(bcx, get_bodyptr(bcx, vptr));
|
|
|
|
let new_data_ptr = get_dataptr(bcx, get_bodyptr(bcx, newptr));
|
|
|
|
call_memmove(bcx, new_data_ptr, data_ptr, fill);
|
2012-05-21 20:36:52 -05:00
|
|
|
|
2012-03-23 08:45:47 -05:00
|
|
|
let bcx = if ty::type_needs_drop(bcx.tcx(), unit_ty) {
|
2012-06-14 19:34:06 -05:00
|
|
|
iter_vec_raw(bcx, new_data_ptr, vec_ty, fill, base::take_ty)
|
2012-03-23 08:45:47 -05:00
|
|
|
} else { bcx };
|
2012-08-01 19:30:05 -05:00
|
|
|
return rslt(bcx, newptr);
|
2011-08-25 03:18:02 -05:00
|
|
|
}
|
2012-06-14 19:34:06 -05:00
|
|
|
|
|
|
|
fn make_drop_glue_unboxed(bcx: block, vptr: ValueRef, vec_ty: ty::t) ->
|
2012-02-17 06:17:40 -06:00
|
|
|
block {
|
2012-07-14 00:57:48 -05:00
|
|
|
let _icx = bcx.insn_ctxt(~"tvec::make_drop_glue_unboxed");
|
2012-02-21 07:20:18 -06:00
|
|
|
let tcx = bcx.tcx(), unit_ty = ty::sequence_element_type(tcx, vec_ty);
|
2012-06-14 19:34:06 -05:00
|
|
|
if ty::type_needs_drop(tcx, unit_ty) {
|
|
|
|
iter_vec_unboxed(bcx, vptr, vec_ty, base::drop_ty)
|
|
|
|
} else { bcx }
|
2011-08-22 15:30:53 -05:00
|
|
|
}
|
|
|
|
|
2012-08-03 20:48:17 -05:00
|
|
|
enum evec_elements {
|
|
|
|
individual_evec(~[@ast::expr]),
|
|
|
|
repeating_evec(@ast::expr, uint)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn trans_evec(bcx: block, elements: evec_elements,
|
2012-04-19 17:42:02 -05:00
|
|
|
vst: ast::vstore, id: ast::node_id, dest: dest) -> block {
|
2012-07-14 00:57:48 -05:00
|
|
|
let _icx = bcx.insn_ctxt(~"tvec::trans_evec");
|
2012-03-15 08:47:03 -05:00
|
|
|
let ccx = bcx.ccx();
|
|
|
|
let mut bcx = bcx;
|
2012-08-03 20:48:17 -05:00
|
|
|
|
|
|
|
// Handle the ignored case.
|
2012-01-27 06:17:06 -06:00
|
|
|
if dest == base::ignore {
|
2012-08-03 20:48:17 -05:00
|
|
|
match elements {
|
|
|
|
individual_evec(args) => {
|
|
|
|
for vec::each(args) |arg| {
|
|
|
|
bcx = base::trans_expr(bcx, arg, base::ignore);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
repeating_evec(element, _) => {
|
|
|
|
bcx = base::trans_expr(bcx, element, base::ignore);
|
|
|
|
}
|
2011-09-27 03:50:18 -05:00
|
|
|
}
|
2012-08-01 19:30:05 -05:00
|
|
|
return bcx;
|
2011-09-27 03:50:18 -05:00
|
|
|
}
|
2012-04-19 17:42:02 -05:00
|
|
|
|
2012-08-03 20:48:17 -05:00
|
|
|
// Figure out the number of elements we need.
|
|
|
|
let count;
|
|
|
|
match elements {
|
|
|
|
individual_evec(args) => count = args.len(),
|
|
|
|
repeating_evec(_, len) => count = len
|
|
|
|
}
|
|
|
|
|
2012-02-02 05:37:17 -06:00
|
|
|
let vec_ty = node_id_type(bcx, id);
|
2012-04-19 17:42:02 -05:00
|
|
|
let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty);
|
|
|
|
let llunitty = type_of::type_of(ccx, unit_ty);
|
2012-04-19 18:37:06 -05:00
|
|
|
let unit_sz = llsize_of(ccx, llunitty);
|
2012-04-19 17:42:02 -05:00
|
|
|
|
|
|
|
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))
|
|
|
|
}
|
|
|
|
_ {
|
2012-07-14 00:57:48 -05:00
|
|
|
bcx.ccx().sess.bug(~"bad dest for vstore_fixed \
|
2012-04-19 17:42:02 -05:00
|
|
|
in tvec::trans_evec");
|
|
|
|
}
|
|
|
|
};
|
|
|
|
{bcx: bcx, val: v, dataptr: v}
|
|
|
|
}
|
|
|
|
ast::vstore_slice(_) {
|
2012-06-26 14:47:06 -05:00
|
|
|
// Make a fake type to use for the cleanup
|
|
|
|
let ty = ty::mk_evec(bcx.tcx(),
|
|
|
|
{ty: unit_ty, mutbl: ast::m_mutbl},
|
2012-08-03 20:48:17 -05:00
|
|
|
ty::vstore_fixed(count));
|
2012-06-26 14:47:06 -05:00
|
|
|
|
2012-08-03 20:48:17 -05:00
|
|
|
let n = C_uint(ccx, count);
|
2012-04-19 17:42:02 -05:00
|
|
|
let vp = base::arrayalloca(bcx, llunitty, n);
|
2012-06-26 14:47:06 -05:00
|
|
|
add_clean(bcx, vp, ty);
|
|
|
|
|
2012-04-19 18:37:06 -05:00
|
|
|
let len = Mul(bcx, n, unit_sz);
|
|
|
|
|
2012-06-29 18:26:56 -05:00
|
|
|
let p = base::alloca(bcx, T_struct(~[T_ptr(llunitty),
|
|
|
|
ccx.int_type]));
|
|
|
|
Store(bcx, vp, GEPi(bcx, p, ~[0u, abi::slice_elt_base]));
|
|
|
|
Store(bcx, len, GEPi(bcx, p, ~[0u, abi::slice_elt_len]));
|
2012-04-19 18:37:06 -05:00
|
|
|
|
|
|
|
{bcx: bcx, val: p, dataptr: vp}
|
2012-04-19 17:42:02 -05:00
|
|
|
}
|
|
|
|
ast::vstore_uniq {
|
2012-08-03 20:48:17 -05:00
|
|
|
let {bcx, val} = alloc_vec(bcx, unit_ty, count, heap_exchange);
|
2012-06-26 15:50:43 -05:00
|
|
|
add_clean_free(bcx, val, heap_exchange);
|
2012-06-12 18:41:20 -05:00
|
|
|
let dataptr = get_dataptr(bcx, get_bodyptr(bcx, val));
|
2012-04-19 17:42:02 -05:00
|
|
|
{bcx: bcx, val: val, dataptr: dataptr}
|
|
|
|
}
|
|
|
|
ast::vstore_box {
|
2012-08-03 20:48:17 -05:00
|
|
|
let {bcx, val} = alloc_vec(bcx, unit_ty, count, heap_shared);
|
2012-06-26 15:50:43 -05:00
|
|
|
add_clean_free(bcx, val, heap_shared);
|
2012-06-14 19:34:06 -05:00
|
|
|
let dataptr = get_dataptr(bcx, get_bodyptr(bcx, val));
|
|
|
|
{bcx: bcx, val: val, dataptr: dataptr}
|
2012-04-19 17:42:02 -05:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2011-08-22 15:30:53 -05:00
|
|
|
|
|
|
|
// Store the individual elements.
|
2012-06-29 18:26:56 -05:00
|
|
|
let mut i = 0u, temp_cleanups = ~[val];
|
2012-07-30 18:01:07 -05:00
|
|
|
debug!{"trans_evec: v: %s, dataptr: %s",
|
2012-04-19 17:42:02 -05:00
|
|
|
val_str(ccx.tn, val),
|
2012-07-30 18:01:07 -05:00
|
|
|
val_str(ccx.tn, dataptr)};
|
2012-08-03 20:48:17 -05:00
|
|
|
match elements {
|
|
|
|
individual_evec(args) => {
|
|
|
|
for vec::each(args) |e| {
|
|
|
|
let lleltptr = InBoundsGEP(bcx, dataptr, ~[C_uint(ccx, i)]);
|
|
|
|
bcx = base::trans_expr_save_in(bcx, e, lleltptr);
|
|
|
|
add_clean_temp_mem(bcx, lleltptr, unit_ty);
|
|
|
|
vec::push(temp_cleanups, lleltptr);
|
|
|
|
i += 1u;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
repeating_evec(e, len) => {
|
|
|
|
// We make temporary space in the hope that this will be
|
|
|
|
// friendlier to LLVM alias analysis.
|
|
|
|
let lltmpspace = base::alloca(bcx, llunitty);
|
|
|
|
bcx = base::trans_expr_save_in(bcx, e, lltmpspace);
|
|
|
|
add_clean_temp_mem(bcx, lltmpspace, unit_ty);
|
|
|
|
vec::push(temp_cleanups, lltmpspace);
|
|
|
|
for len.timesi |i| {
|
|
|
|
let lleltptr = InBoundsGEP(bcx, dataptr, ~[C_uint(ccx, i)]);
|
|
|
|
if i == len - 1 {
|
|
|
|
// Move the last one in.
|
|
|
|
bcx = move_val(bcx, INIT, lleltptr,
|
|
|
|
lval_owned(bcx, lltmpspace), unit_ty);
|
|
|
|
} else {
|
|
|
|
// Copy all but the last one in.
|
|
|
|
let llval = load_if_immediate(bcx, lltmpspace, unit_ty);
|
|
|
|
bcx = copy_val(bcx, INIT, lleltptr, llval, unit_ty);
|
|
|
|
}
|
|
|
|
add_clean_temp_mem(bcx, lleltptr, unit_ty);
|
|
|
|
vec::push(temp_cleanups, lleltptr);
|
|
|
|
}
|
|
|
|
}
|
2011-08-22 13:48:00 -05:00
|
|
|
}
|
2012-04-19 17:42:02 -05:00
|
|
|
|
2012-06-30 18:19:07 -05:00
|
|
|
for vec::each(temp_cleanups) |cln| { revoke_clean(bcx, cln); }
|
2012-04-19 17:42:02 -05:00
|
|
|
|
|
|
|
alt vst {
|
|
|
|
ast::vstore_fixed(_) {
|
|
|
|
// We wrote into the destination in the fixed case.
|
2012-08-01 19:30:05 -05:00
|
|
|
return bcx;
|
2012-04-19 17:42:02 -05:00
|
|
|
}
|
2012-04-19 18:37:06 -05:00
|
|
|
ast::vstore_slice(_) {
|
2012-08-01 19:30:05 -05:00
|
|
|
return base::store_in_dest(bcx, Load(bcx, val), dest);
|
2012-04-19 18:37:06 -05:00
|
|
|
}
|
2012-04-19 17:42:02 -05:00
|
|
|
_ {
|
2012-08-01 19:30:05 -05:00
|
|
|
return base::store_in_dest(bcx, val, dest);
|
2012-04-19 17:42:02 -05:00
|
|
|
}
|
|
|
|
}
|
2011-08-22 13:48:00 -05:00
|
|
|
}
|
2011-09-27 13:21:44 -05:00
|
|
|
|
2012-04-09 19:32:49 -05:00
|
|
|
fn trans_vstore(bcx: block, e: @ast::expr,
|
|
|
|
v: ast::vstore, dest: dest) -> block {
|
|
|
|
alt e.node {
|
2012-08-03 20:48:17 -05:00
|
|
|
ast::expr_lit(@{node: ast::lit_str(s), span: _}) => {
|
2012-08-03 13:51:04 -05:00
|
|
|
return trans_estr(bcx, s, some(v), dest);
|
2012-04-09 19:32:49 -05:00
|
|
|
}
|
2012-08-03 20:48:17 -05:00
|
|
|
ast::expr_vec(es, mutbl) => {
|
|
|
|
return trans_evec(bcx, individual_evec(es), v, e.id, dest);
|
2012-04-09 19:32:49 -05:00
|
|
|
}
|
2012-08-03 20:48:17 -05:00
|
|
|
ast::expr_repeat(element, count_expr, mutbl) => {
|
|
|
|
let count = ty::eval_repeat_count(bcx.tcx(), count_expr, e.span);
|
|
|
|
return trans_evec(bcx, repeating_evec(element, count), v, e.id, dest);
|
|
|
|
}
|
|
|
|
_ => {
|
2012-07-14 00:57:48 -05:00
|
|
|
bcx.sess().span_bug(e.span, ~"vstore on non-sequence type");
|
2012-04-09 19:32:49 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-04-17 17:07:38 -05:00
|
|
|
fn get_base_and_len(cx: block, v: ValueRef, e_ty: ty::t)
|
|
|
|
-> (ValueRef, ValueRef) {
|
|
|
|
|
2012-04-19 17:42:02 -05:00
|
|
|
let ccx = cx.ccx();
|
|
|
|
let tcx = ccx.tcx;
|
2012-04-17 17:07:38 -05:00
|
|
|
let vec_ty = ty::type_autoderef(tcx, e_ty);
|
|
|
|
let unit_ty = ty::sequence_element_type(tcx, vec_ty);
|
2012-04-19 17:42:02 -05:00
|
|
|
let llunitty = type_of::type_of(ccx, unit_ty);
|
|
|
|
let unit_sz = llsize_of(ccx, llunitty);
|
|
|
|
|
2012-04-17 17:07:38 -05:00
|
|
|
let vstore = alt ty::get(vec_ty).struct {
|
|
|
|
ty::ty_estr(vst) | ty::ty_evec(_, vst) { vst }
|
|
|
|
_ { ty::vstore_uniq }
|
|
|
|
};
|
|
|
|
|
|
|
|
alt vstore {
|
|
|
|
ty::vstore_fixed(n) {
|
2012-06-29 18:26:56 -05:00
|
|
|
let base = GEPi(cx, v, ~[0u, 0u]);
|
2012-04-19 17:42:02 -05:00
|
|
|
let n = if ty::type_is_str(e_ty) { n + 1u } else { n };
|
|
|
|
let len = Mul(cx, C_uint(ccx, n), unit_sz);
|
2012-04-17 17:07:38 -05:00
|
|
|
(base, len)
|
|
|
|
}
|
|
|
|
ty::vstore_slice(_) {
|
2012-06-29 18:26:56 -05:00
|
|
|
let base = Load(cx, GEPi(cx, v, ~[0u, abi::slice_elt_base]));
|
|
|
|
let len = Load(cx, GEPi(cx, v, ~[0u, abi::slice_elt_len]));
|
2012-04-17 17:07:38 -05:00
|
|
|
(base, len)
|
|
|
|
}
|
2012-06-14 19:34:06 -05:00
|
|
|
ty::vstore_uniq | ty::vstore_box {
|
2012-07-30 18:01:07 -05:00
|
|
|
debug!{"get_base_and_len: %s", val_str(ccx.tn, v)};
|
2012-06-12 18:41:20 -05:00
|
|
|
let body = tvec::get_bodyptr(cx, v);
|
|
|
|
(tvec::get_dataptr(cx, body), tvec::get_fill(cx, body))
|
2012-04-17 17:07:38 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-03 13:51:04 -05:00
|
|
|
fn trans_estr(bcx: block, s: @~str, vstore: option<ast::vstore>,
|
2012-04-16 18:17:51 -05:00
|
|
|
dest: dest) -> block {
|
2012-07-14 00:57:48 -05:00
|
|
|
let _icx = bcx.insn_ctxt(~"tvec::trans_estr");
|
2012-08-01 19:30:05 -05:00
|
|
|
if dest == base::ignore { return bcx; }
|
2012-04-10 20:34:21 -05:00
|
|
|
let ccx = bcx.ccx();
|
|
|
|
|
|
|
|
let c = alt vstore {
|
2012-08-03 13:51:04 -05:00
|
|
|
some(ast::vstore_fixed(_)) => {
|
2012-06-29 18:26:56 -05:00
|
|
|
// "hello"/_ => "hello"/5 => ~[i8 x 6] in llvm
|
2012-07-30 18:01:07 -05:00
|
|
|
debug!{"trans_estr: fixed: %s", *s};
|
2012-06-10 02:49:59 -05:00
|
|
|
C_postr(*s)
|
2012-04-10 20:34:21 -05:00
|
|
|
}
|
|
|
|
|
2012-08-03 13:51:04 -05:00
|
|
|
some(ast::vstore_slice(_)) | none => {
|
2012-04-18 19:02:00 -05:00
|
|
|
// "hello" => (*i8, 6u) in llvm
|
2012-07-30 18:01:07 -05:00
|
|
|
debug!{"trans_estr: slice '%s'", *s};
|
2012-06-10 02:49:59 -05:00
|
|
|
C_estr_slice(ccx, *s)
|
2012-04-09 19:32:49 -05:00
|
|
|
}
|
2012-04-10 20:34:21 -05:00
|
|
|
|
2012-08-03 13:51:04 -05:00
|
|
|
some(ast::vstore_uniq) => {
|
2012-06-10 02:49:59 -05:00
|
|
|
let cs = PointerCast(bcx, C_cstr(ccx, *s), T_ptr(T_i8()));
|
|
|
|
let len = C_uint(ccx, str::len(*s));
|
2012-06-29 18:26:56 -05:00
|
|
|
let c = Call(bcx, ccx.upcalls.str_new_uniq, ~[cs, len]);
|
2012-05-21 20:36:52 -05:00
|
|
|
PointerCast(bcx, c,
|
|
|
|
T_unique_ptr(T_unique(ccx, T_vec(ccx, T_i8()))))
|
2012-04-16 18:17:51 -05:00
|
|
|
}
|
|
|
|
|
2012-08-03 13:51:04 -05:00
|
|
|
some(ast::vstore_box) => {
|
2012-06-10 02:49:59 -05:00
|
|
|
let cs = PointerCast(bcx, C_cstr(ccx, *s), T_ptr(T_i8()));
|
|
|
|
let len = C_uint(ccx, str::len(*s));
|
2012-06-29 18:26:56 -05:00
|
|
|
let c = Call(bcx, ccx.upcalls.str_new_shared, ~[cs, len]);
|
2012-06-18 14:50:09 -05:00
|
|
|
PointerCast(bcx, c,
|
|
|
|
T_box_ptr(T_box(ccx, T_vec(ccx, T_i8()))))
|
2012-04-09 19:32:49 -05:00
|
|
|
}
|
2012-04-10 20:34:21 -05:00
|
|
|
};
|
|
|
|
|
2012-07-30 18:01:07 -05:00
|
|
|
debug!{"trans_estr: type: %s", val_str(ccx.tn, c)};
|
2012-04-10 20:34:21 -05:00
|
|
|
base::store_in_dest(bcx, c, dest)
|
2012-04-09 19:32:49 -05:00
|
|
|
}
|
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
type val_and_ty_fn = fn@(block, ValueRef, ty::t) -> result;
|
2011-08-22 13:48:00 -05:00
|
|
|
|
2012-02-17 06:17:40 -06:00
|
|
|
type iter_vec_block = fn(block, ValueRef, ty::t) -> block;
|
2011-08-22 13:48:00 -05:00
|
|
|
|
2012-04-19 17:42:02 -05:00
|
|
|
fn iter_vec_raw(bcx: block, data_ptr: ValueRef, vec_ty: ty::t,
|
2012-02-17 06:17:40 -06:00
|
|
|
fill: ValueRef, f: iter_vec_block) -> block {
|
2012-07-14 00:57:48 -05:00
|
|
|
let _icx = bcx.insn_ctxt(~"tvec::iter_vec_raw");
|
2012-04-19 17:42:02 -05:00
|
|
|
|
2012-02-21 07:20:18 -06:00
|
|
|
let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty);
|
2011-08-25 03:18:02 -05:00
|
|
|
|
|
|
|
// Calculate the last pointer address we want to handle.
|
2012-06-21 18:44:10 -05:00
|
|
|
// FIXME (#2536): Optimize this when the size of the unit type is
|
|
|
|
// statically known to not use pointer casts, which tend to confuse
|
|
|
|
// LLVM.
|
2011-08-25 03:18:02 -05:00
|
|
|
let data_end_ptr = pointer_add(bcx, data_ptr, fill);
|
|
|
|
|
|
|
|
// Now perform the iteration.
|
2012-07-14 00:57:48 -05:00
|
|
|
let header_cx = sub_block(bcx, ~"iter_vec_loop_header");
|
2011-08-25 03:18:02 -05:00
|
|
|
Br(bcx, header_cx.llbb);
|
2012-06-25 22:00:46 -05:00
|
|
|
let data_ptr =
|
2012-06-29 18:26:56 -05:00
|
|
|
Phi(header_cx, val_ty(data_ptr), ~[data_ptr], ~[bcx.llbb]);
|
2011-09-02 17:34:58 -05:00
|
|
|
let not_yet_at_end =
|
2012-02-01 04:04:56 -06:00
|
|
|
ICmp(header_cx, lib::llvm::IntULT, data_ptr, data_end_ptr);
|
2012-07-14 00:57:48 -05:00
|
|
|
let body_cx = sub_block(header_cx, ~"iter_vec_loop_body");
|
|
|
|
let next_cx = sub_block(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);
|
2012-03-15 08:47:03 -05:00
|
|
|
let body_cx = f(body_cx, data_ptr, unit_ty);
|
2012-03-12 04:05:15 -05:00
|
|
|
AddIncomingToPhi(data_ptr, InBoundsGEP(body_cx, data_ptr,
|
2012-06-29 18:26:56 -05:00
|
|
|
~[C_int(bcx.ccx(), 1)]),
|
2012-04-19 17:42:02 -05:00
|
|
|
body_cx.llbb);
|
2011-08-25 03:18:02 -05:00
|
|
|
Br(body_cx, header_cx.llbb);
|
2012-08-01 19:30:05 -05:00
|
|
|
return next_cx;
|
2012-04-19 17:42:02 -05:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
fn iter_vec_uniq(bcx: block, vptr: ValueRef, vec_ty: ty::t,
|
|
|
|
fill: ValueRef, f: iter_vec_block) -> block {
|
2012-07-14 00:57:48 -05:00
|
|
|
let _icx = bcx.insn_ctxt(~"tvec::iter_vec_uniq");
|
2012-06-12 18:41:20 -05:00
|
|
|
let data_ptr = get_dataptr(bcx, get_bodyptr(bcx, vptr));
|
2012-04-19 17:42:02 -05:00
|
|
|
iter_vec_raw(bcx, data_ptr, vec_ty, fill, f)
|
2011-08-22 13:48:00 -05:00
|
|
|
}
|
2011-08-25 03:18:02 -05:00
|
|
|
|
2012-06-14 19:34:06 -05:00
|
|
|
fn iter_vec_unboxed(bcx: block, body_ptr: ValueRef, vec_ty: ty::t,
|
|
|
|
f: iter_vec_block) -> block {
|
2012-07-14 00:57:48 -05:00
|
|
|
let _icx = bcx.insn_ctxt(~"tvec::iter_vec_unboxed");
|
2012-06-14 19:34:06 -05:00
|
|
|
let fill = get_fill(bcx, body_ptr);
|
|
|
|
let dataptr = get_dataptr(bcx, body_ptr);
|
2012-08-01 19:30:05 -05:00
|
|
|
return iter_vec_raw(bcx, dataptr, vec_ty, fill, 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
|
|
|
|
// End:
|
|
|
|
//
|