-> ExtractedBlock {
let _icx = push_ctxt("match::extract_vec_elems");
let vec_datum = match_datum(bcx, val, pat_id);
- let (bcx, base, len) = vec_datum.get_vec_base_and_byte_len(bcx, pat_span, pat_id, 0);
+ let (bcx, base, len) = vec_datum.get_vec_base_and_len(bcx, pat_span, pat_id, 0);
let vt = tvec::vec_types(bcx, node_id_type(bcx, pat_id));
let mut elems = do vec::from_fn(elem_count) |i| {
};
if slice.is_some() {
let n = slice.unwrap();
- let slice_offset = Mul(bcx, vt.llunit_size,
- C_int(bcx.ccx(), n as int)
- );
- let slice_begin = tvec::pointer_add(bcx, base, slice_offset);
- let slice_len_offset = Mul(bcx, vt.llunit_size,
- C_int(bcx.ccx(), (elem_count - 1u) as int)
- );
+ let slice_byte_offset = Mul(bcx, vt.llunit_size, C_uint(bcx.ccx(), n));
+ let slice_begin = tvec::pointer_add_byte(bcx, base, slice_byte_offset);
+ let slice_len_offset = C_uint(bcx.ccx(), elem_count - 1u);
let slice_len = Sub(bcx, len, slice_len_offset);
let slice_ty = ty::mk_evec(bcx.tcx(),
ty::mt {ty: vt.unit_ty, mutbl: ast::MutImmutable},
Store(bcx, slice_begin,
GEPi(bcx, scratch.val, [0u, abi::slice_elt_base])
);
- Store(bcx, UDiv(bcx, slice_len, vt.llunit_size),
- GEPi(bcx, scratch.val, [0u, abi::slice_elt_len])
- );
+ Store(bcx, slice_len, GEPi(bcx, scratch.val, [0u, abi::slice_elt_len]));
elems[n] = scratch.val;
scratch.add_clean(bcx);
}
vec_len(*) => {
let vt = tvec::vec_types(bcx, node_id_type(bcx, pat_id));
let unboxed = load_if_immediate(bcx, val, vt.vec_ty);
- let (_, len) = tvec::get_base_and_byte_len(bcx, unboxed, vt.vec_ty);
- test_val = SDiv(bcx, len, vt.llunit_size);
+ let (_, len) = tvec::get_base_and_len(bcx, unboxed, vt.vec_ty);
+ test_val = len;
kind = compare_vec_len;
}
}
bcx, expr::trans_to_datum(bcx, arg_expr));
if ty::type_is_str(arg_datum.ty) {
- let (lldata, _) = arg_datum.get_vec_base_and_byte_len_no_root(bcx);
+ let (lldata, _) = arg_datum.get_vec_base_and_len_no_root(bcx);
return trans_fail_value(bcx, sp_opt, lldata);
} else if bcx.unreachable || ty::type_is_bot(arg_datum.ty) {
return bcx;
tvec::get_base_and_byte_len(bcx, llval, self.ty)
}
+ pub fn get_vec_base_and_len(&self,
+ mut bcx: @mut Block,
+ span: Span,
+ expr_id: ast::NodeId,
+ derefs: uint)
+ -> (@mut Block, ValueRef, ValueRef) {
+ //! Converts a vector into the slice pair. Performs rooting
+ //! and write guards checks.
+
+ // only imp't for @[] and @str, but harmless
+ bcx = write_guard::root_and_write_guard(self, bcx, span, expr_id, derefs);
+ let (base, len) = self.get_vec_base_and_len_no_root(bcx);
+ (bcx, base, len)
+ }
+
+ pub fn get_vec_base_and_len_no_root(&self, bcx: @mut Block)
+ -> (ValueRef, ValueRef) {
+ //! Converts a vector into the slice pair. Des not root
+ //! nor perform write guard checks.
+
+ let llval = self.to_appropriate_llval(bcx);
+ tvec::get_base_and_len(bcx, llval, self.ty)
+ }
+
pub fn root_and_write_guard(&self,
bcx: @mut Block,
span: Span,
let unit_ty = ty::sequence_element_type(tcx, datum.ty);
let (bcx, base, len) =
- datum.get_vec_base_and_byte_len(bcx, expr.span, expr.id, autoderefs+1);
+ datum.get_vec_base_and_len(bcx, expr.span, expr.id, autoderefs+1);
// this type may have a different region/mutability than the
// real one, but it will have the same runtime representation
let scratch = scratch_datum(bcx, slice_ty, "__adjust", false);
- let vt = tvec::vec_types(bcx, datum.ty);
- let unscaled_len = UDiv(bcx, len, vt.llunit_size);
-
Store(bcx, base, GEPi(bcx, scratch.val, [0u, abi::slice_elt_base]));
- Store(bcx, unscaled_len, GEPi(bcx, scratch.val, [0u, abi::slice_elt_len]));
+ Store(bcx, len, GEPi(bcx, scratch.val, [0u, abi::slice_elt_len]));
DatumBlock {bcx: bcx, datum: scratch}
}
base::maybe_name_value(bcx.ccx(), vt.llunit_size, "unit_sz");
let (bcx, base, len) =
- base_datum.get_vec_base_and_byte_len(bcx, index_expr.span,
- index_expr.id, 0);
+ base_datum.get_vec_base_and_len(bcx, index_expr.span, index_expr.id, 0);
debug2!("trans_index: base {}", bcx.val_to_str(base));
debug2!("trans_index: len {}", bcx.val_to_str(len));
- let unscaled_len = UDiv(bcx, len, vt.llunit_size);
- let bounds_check = ICmp(bcx, lib::llvm::IntUGE, ix_val, unscaled_len);
+ let bounds_check = ICmp(bcx, lib::llvm::IntUGE, ix_val, len);
let bcx = do with_cond(bcx, bounds_check) |bcx| {
- controlflow::trans_fail_bounds_check(bcx, index_expr.span,
- ix_val, unscaled_len)
+ controlflow::trans_fail_bounds_check(bcx, index_expr.span, ix_val, len)
};
let elt = InBoundsGEP(bcx, base, [ix_val]);
let elt = PointerCast(bcx, elt, vt.llunit_ty.ptr_to());
GEPi(bcx, vptr, [0u, abi::vec_elt_elems, 0u])
}
-pub fn pointer_add(bcx: @mut Block, ptr: ValueRef, bytes: ValueRef) -> ValueRef {
- let _icx = push_ctxt("tvec::pointer_add");
+pub fn pointer_add_byte(bcx: @mut Block, ptr: ValueRef, bytes: ValueRef) -> ValueRef {
+ let _icx = push_ctxt("tvec::pointer_add_byte");
let old_ty = val_ty(ptr);
let bptr = PointerCast(bcx, ptr, Type::i8p());
return PointerCast(bcx, InBoundsGEP(bcx, bptr, [bytes]), old_ty);
}
}
-pub fn get_base_and_byte_len(bcx: @mut Block,
- llval: ValueRef,
+pub fn get_base_and_byte_len(bcx: @mut Block, llval: ValueRef,
vec_ty: ty::t) -> (ValueRef, ValueRef) {
//!
//
}
}
+pub fn get_base_and_len(bcx: @mut Block, llval: ValueRef, vec_ty: ty::t) -> (ValueRef, ValueRef) {
+ //!
+ //
+ // Converts a vector into the slice pair. The vector should be stored in
+ // `llval` which should be either immediate or by-ref as appropriate for
+ // the vector type. If you have a datum, you would probably prefer to
+ // call `Datum::get_base_and_len()` which will handle any conversions for
+ // you.
+
+ let ccx = bcx.ccx();
+ let vt = vec_types(bcx, vec_ty);
+
+ let vstore = match ty::get(vt.vec_ty).sty {
+ ty::ty_estr(vst) | ty::ty_evec(_, vst) => vst,
+ _ => ty::vstore_uniq
+ };
+
+ match vstore {
+ ty::vstore_fixed(n) => {
+ let base = GEPi(bcx, llval, [0u, 0u]);
+ (base, C_uint(ccx, n))
+ }
+ ty::vstore_slice(_) => {
+ let base = Load(bcx, GEPi(bcx, llval, [0u, abi::slice_elt_base]));
+ let count = Load(bcx, GEPi(bcx, llval, [0u, abi::slice_elt_len]));
+ (base, count)
+ }
+ ty::vstore_uniq | ty::vstore_box => {
+ let body = get_bodyptr(bcx, llval, vec_ty);
+ (get_dataptr(bcx, body), UDiv(bcx, get_fill(bcx, body), vt.llunit_size))
+ }
+ }
+}
+
pub type iter_vec_block<'self> = &'self fn(@mut Block, ValueRef, ty::t) -> @mut Block;
pub fn iter_vec_raw(bcx: @mut Block, data_ptr: ValueRef, vec_ty: ty::t,
// FIXME (#3729): 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);
+ let data_end_ptr = pointer_add_byte(bcx, data_ptr, fill);
// Now perform the iteration.
let header_bcx = base::sub_block(bcx, "iter_vec_loop_header");