auto merge of #9885 : thestinger/rust/vector, r=brson
The goal here is to avoid requiring a division or multiplication to compare against the length. The bounds check previously used an incorrect micro-optimization to replace the division by a multiplication, but now neither is necessary *for slices*. Unique/managed vectors will have to do a division to get the length until they are reworked/replaced.
This commit is contained in:
commit
9d6c251881
@ -1025,8 +1025,7 @@ fn extract_vec_elems(bcx: @mut Block,
|
||||
-> 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_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| {
|
||||
@ -1043,13 +1042,9 @@ fn extract_vec_elems(bcx: @mut Block,
|
||||
};
|
||||
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},
|
||||
@ -1059,9 +1054,7 @@ fn extract_vec_elems(bcx: @mut Block,
|
||||
Store(bcx, slice_begin,
|
||||
GEPi(bcx, scratch.val, [0u, abi::slice_elt_base])
|
||||
);
|
||||
Store(bcx, slice_len,
|
||||
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);
|
||||
}
|
||||
@ -1647,10 +1640,8 @@ fn compile_submatch_continue(mut bcx: @mut Block,
|
||||
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_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;
|
||||
}
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ use middle::trans::glue;
|
||||
use middle::trans::inline;
|
||||
use middle::trans::llrepr::LlvmRepr;
|
||||
use middle::trans::machine;
|
||||
use middle::trans::machine::{llalign_of_min, llsize_of, llsize_of_alloc};
|
||||
use middle::trans::machine::{llalign_of_min, llsize_of};
|
||||
use middle::trans::meth;
|
||||
use middle::trans::monomorphize;
|
||||
use middle::trans::tvec;
|
||||
@ -745,7 +745,7 @@ pub fn iter_structural_ty(cx: @mut Block, av: ValueRef, t: ty::t,
|
||||
}
|
||||
ty::ty_estr(ty::vstore_fixed(_)) |
|
||||
ty::ty_evec(_, ty::vstore_fixed(_)) => {
|
||||
let (base, len) = tvec::get_base_and_len(cx, av, t);
|
||||
let (base, len) = tvec::get_base_and_byte_len(cx, av, t);
|
||||
cx = tvec::iter_vec_raw(cx, base, t, len, f);
|
||||
}
|
||||
ty::ty_tup(ref args) => {
|
||||
@ -2910,7 +2910,7 @@ pub fn decl_gc_metadata(ccx: &mut CrateContext, llmod_id: &str) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_module_map(ccx: &mut CrateContext) -> (ValueRef, uint, uint) {
|
||||
pub fn create_module_map(ccx: &mut CrateContext) -> (ValueRef, uint) {
|
||||
let str_slice_type = Type::struct_([Type::i8p(), ccx.int_type], false);
|
||||
let elttype = Type::struct_([str_slice_type, ccx.int_type], false);
|
||||
let maptype = Type::array(&elttype, ccx.module_data.len() as u64);
|
||||
@ -2942,7 +2942,7 @@ pub fn create_module_map(ccx: &mut CrateContext) -> (ValueRef, uint, uint) {
|
||||
unsafe {
|
||||
llvm::LLVMSetInitializer(map, C_array(elttype, elts));
|
||||
}
|
||||
return (map, keys.len(), llsize_of_alloc(ccx, elttype));
|
||||
return (map, keys.len())
|
||||
}
|
||||
|
||||
|
||||
@ -3004,19 +3004,17 @@ pub fn fill_crate_map(ccx: &mut CrateContext, map: ValueRef) {
|
||||
lib::llvm::SetLinkage(vec_elements, lib::llvm::InternalLinkage);
|
||||
|
||||
llvm::LLVMSetInitializer(vec_elements, C_array(ccx.int_type, subcrates));
|
||||
let (mod_map, mod_count, mod_struct_size) = create_module_map(ccx);
|
||||
let (mod_map, mod_count) = create_module_map(ccx);
|
||||
|
||||
llvm::LLVMSetInitializer(map, C_struct(
|
||||
[C_i32(2),
|
||||
C_struct([
|
||||
p2i(ccx, mod_map),
|
||||
// byte size of the module map array, an entry consists of two integers
|
||||
C_int(ccx, ((mod_count * mod_struct_size) as int))
|
||||
C_uint(ccx, mod_count)
|
||||
], false),
|
||||
C_struct([
|
||||
p2i(ccx, vec_elements),
|
||||
// byte size of the subcrates array, an entry consists of an integer
|
||||
C_int(ccx, (subcrates.len() * llsize_of_alloc(ccx, ccx.int_type)) as int)
|
||||
C_uint(ccx, subcrates.len())
|
||||
], false)
|
||||
], false));
|
||||
}
|
||||
|
@ -83,23 +83,18 @@ pub fn const_ptrcast(cx: &mut CrateContext, a: ValueRef, t: Type) -> ValueRef {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn const_vec(cx: @mut CrateContext, e: &ast::Expr, es: &[@ast::Expr])
|
||||
-> (ValueRef, ValueRef, Type, bool) {
|
||||
unsafe {
|
||||
let vec_ty = ty::expr_ty(cx.tcx, e);
|
||||
let unit_ty = ty::sequence_element_type(cx.tcx, vec_ty);
|
||||
let llunitty = type_of::type_of(cx, unit_ty);
|
||||
let unit_sz = machine::llsize_of(cx, llunitty);
|
||||
let sz = llvm::LLVMConstMul(C_uint(cx, es.len()), unit_sz);
|
||||
let (vs, inlineable) = vec::unzip(es.iter().map(|e| const_expr(cx, *e)));
|
||||
// If the vector contains enums, an LLVM array won't work.
|
||||
let v = if vs.iter().any(|vi| val_ty(*vi) != llunitty) {
|
||||
C_struct(vs, false)
|
||||
} else {
|
||||
C_array(llunitty, vs)
|
||||
};
|
||||
return (v, sz, llunitty, inlineable.iter().fold(true, |a, &b| a && b));
|
||||
}
|
||||
fn const_vec(cx: @mut CrateContext, e: &ast::Expr, es: &[@ast::Expr]) -> (ValueRef, Type, bool) {
|
||||
let vec_ty = ty::expr_ty(cx.tcx, e);
|
||||
let unit_ty = ty::sequence_element_type(cx.tcx, vec_ty);
|
||||
let llunitty = type_of::type_of(cx, unit_ty);
|
||||
let (vs, inlineable) = vec::unzip(es.iter().map(|e| const_expr(cx, *e)));
|
||||
// If the vector contains enums, an LLVM array won't work.
|
||||
let v = if vs.iter().any(|vi| val_ty(*vi) != llunitty) {
|
||||
C_struct(vs, false)
|
||||
} else {
|
||||
C_array(llunitty, vs)
|
||||
};
|
||||
(v, llunitty, inlineable.iter().fold(true, |a, &b| a && b))
|
||||
}
|
||||
|
||||
fn const_addr_of(cx: &mut CrateContext, cv: ValueRef) -> ValueRef {
|
||||
@ -225,9 +220,8 @@ pub fn const_expr(cx: @mut CrateContext, e: &ast::Expr) -> (ValueRef, bool) {
|
||||
assert_eq!(abi::slice_elt_len, 1);
|
||||
|
||||
match ty::get(ty).sty {
|
||||
ty::ty_evec(_, ty::vstore_fixed(*)) => {
|
||||
let size = machine::llsize_of(cx, val_ty(llconst));
|
||||
llconst = C_struct([llptr, size], false);
|
||||
ty::ty_evec(_, ty::vstore_fixed(len)) => {
|
||||
llconst = C_struct([llptr, C_uint(cx, len)], false);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@ -412,14 +406,8 @@ fn const_expr_unadjusted(cx: @mut CrateContext,
|
||||
(bv, C_uint(cx, u)),
|
||||
|
||||
ty::vstore_slice(_) => {
|
||||
let unit_ty = ty::sequence_element_type(cx.tcx, bt);
|
||||
let llunitty = type_of::type_of(cx, unit_ty);
|
||||
let unit_sz = machine::llsize_of(cx, llunitty);
|
||||
|
||||
let e1 = const_get_elt(cx, bv, [0]);
|
||||
(const_deref_ptr(cx, e1),
|
||||
llvm::LLVMConstUDiv(const_get_elt(cx, bv, [1]),
|
||||
unit_sz))
|
||||
(const_deref_ptr(cx, e1), const_get_elt(cx, bv, [1]))
|
||||
},
|
||||
_ => cx.sess.span_bug(base.span,
|
||||
"index-expr base must be fixed-size or slice")
|
||||
@ -538,7 +526,7 @@ fn const_expr_unadjusted(cx: @mut CrateContext,
|
||||
}
|
||||
}
|
||||
ast::ExprVec(ref es, ast::MutImmutable) => {
|
||||
let (v, _, _, inlineable) = const_vec(cx, e, *es);
|
||||
let (v, _, inlineable) = const_vec(cx, e, *es);
|
||||
(v, inlineable)
|
||||
}
|
||||
ast::ExprVstore(sub, ast::ExprVstoreSlice) => {
|
||||
@ -550,7 +538,7 @@ fn const_expr_unadjusted(cx: @mut CrateContext,
|
||||
}
|
||||
}
|
||||
ast::ExprVec(ref es, ast::MutImmutable) => {
|
||||
let (cv, sz, llunitty, _) = const_vec(cx, e, *es);
|
||||
let (cv, llunitty, _) = const_vec(cx, e, *es);
|
||||
let llty = val_ty(cv);
|
||||
let gv = do "const".with_c_str |name| {
|
||||
llvm::LLVMAddGlobal(cx.llmod, llty.to_ref(), name)
|
||||
@ -559,7 +547,7 @@ fn const_expr_unadjusted(cx: @mut CrateContext,
|
||||
llvm::LLVMSetGlobalConstant(gv, True);
|
||||
SetLinkage(gv, PrivateLinkage);
|
||||
let p = const_ptrcast(cx, gv, llunitty);
|
||||
(C_struct([p, sz], false), false)
|
||||
(C_struct([p, C_uint(cx, es.len())], false), false)
|
||||
}
|
||||
_ => cx.sess.span_bug(e.span, "bad const-slice expr")
|
||||
}
|
||||
|
@ -770,12 +770,36 @@ impl Datum {
|
||||
DatumBlock { bcx: bcx, datum: datum }
|
||||
}
|
||||
|
||||
pub fn get_vec_base_and_byte_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_byte_len_no_root(bcx);
|
||||
(bcx, base, len)
|
||||
}
|
||||
|
||||
pub fn get_vec_base_and_byte_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_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) {
|
||||
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.
|
||||
|
||||
@ -786,7 +810,7 @@ impl Datum {
|
||||
}
|
||||
|
||||
pub fn get_vec_base_and_len_no_root(&self, bcx: @mut Block)
|
||||
-> (ValueRef, ValueRef) {
|
||||
-> (ValueRef, ValueRef) {
|
||||
//! Converts a vector into the slice pair. Des not root
|
||||
//! nor perform write guard checks.
|
||||
|
||||
|
@ -1867,7 +1867,7 @@ fn vec_slice_metadata(cx: &mut CrateContext,
|
||||
offset: ComputedMemberOffset,
|
||||
},
|
||||
MemberDescription {
|
||||
name: @"size_in_bytes",
|
||||
name: @"length",
|
||||
llvm_type: member_llvm_types[1],
|
||||
type_metadata: type_metadata(cx, ty::mk_uint(), span),
|
||||
offset: ComputedMemberOffset,
|
||||
|
@ -274,6 +274,7 @@ pub fn trans_to_datum(bcx: @mut Block, expr: &ast::Expr) -> DatumBlock {
|
||||
ty::vstore_slice(ty::re_static));
|
||||
|
||||
let scratch = scratch_datum(bcx, slice_ty, "__adjust", false);
|
||||
|
||||
Store(bcx, base, GEPi(bcx, scratch.val, [0u, abi::slice_elt_base]));
|
||||
Store(bcx, len, GEPi(bcx, scratch.val, [0u, abi::slice_elt_len]));
|
||||
DatumBlock {bcx: bcx, datum: scratch}
|
||||
@ -972,21 +973,16 @@ fn trans_lvalue_unadjusted(bcx: @mut Block, expr: &ast::Expr) -> DatumBlock {
|
||||
|
||||
let vt = tvec::vec_types(bcx, base_datum.ty);
|
||||
base::maybe_name_value(bcx.ccx(), vt.llunit_size, "unit_sz");
|
||||
let scaled_ix = Mul(bcx, ix_val, vt.llunit_size);
|
||||
base::maybe_name_value(bcx.ccx(), scaled_ix, "scaled_ix");
|
||||
|
||||
let (bcx, base, len) =
|
||||
base_datum.get_vec_base_and_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 bounds_check = ICmp(bcx, lib::llvm::IntUGE, scaled_ix, len);
|
||||
let bounds_check = ICmp(bcx, lib::llvm::IntUGE, ix_val, len);
|
||||
let bcx = do with_cond(bcx, bounds_check) |bcx| {
|
||||
let unscaled_len = UDiv(bcx, len, vt.llunit_size);
|
||||
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());
|
||||
|
@ -77,8 +77,8 @@ pub fn get_dataptr(bcx: @mut Block, vptr: ValueRef) -> ValueRef {
|
||||
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);
|
||||
@ -237,8 +237,7 @@ pub fn trans_slice_vstore(bcx: @mut Block,
|
||||
Ignore => {}
|
||||
SaveIn(lldest) => {
|
||||
Store(bcx, llfixed, GEPi(bcx, lldest, [0u, abi::slice_elt_base]));
|
||||
let lllen = Mul(bcx, llcount, vt.llunit_size);
|
||||
Store(bcx, lllen, GEPi(bcx, lldest, [0u, abi::slice_elt_len]));
|
||||
Store(bcx, llcount, GEPi(bcx, lldest, [0u, abi::slice_elt_len]));
|
||||
}
|
||||
}
|
||||
|
||||
@ -502,14 +501,49 @@ pub fn elements_required(bcx: @mut Block, content_expr: &ast::Expr) -> uint {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_base_and_len(bcx: @mut Block,
|
||||
llval: ValueRef,
|
||||
pub fn get_base_and_byte_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_byte_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]);
|
||||
let len = Mul(bcx, C_uint(ccx, n), vt.llunit_size);
|
||||
(base, len)
|
||||
}
|
||||
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]));
|
||||
let len = Mul(bcx, count, vt.llunit_size);
|
||||
(base, len)
|
||||
}
|
||||
ty::vstore_uniq | ty::vstore_box => {
|
||||
let body = get_bodyptr(bcx, llval, vec_ty);
|
||||
(get_dataptr(bcx, body), get_fill(bcx, body))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
@ -524,17 +558,16 @@ pub fn get_base_and_len(bcx: @mut Block,
|
||||
match vstore {
|
||||
ty::vstore_fixed(n) => {
|
||||
let base = GEPi(bcx, llval, [0u, 0u]);
|
||||
let len = Mul(bcx, C_uint(ccx, n), vt.llunit_size);
|
||||
(base, len)
|
||||
(base, C_uint(ccx, n))
|
||||
}
|
||||
ty::vstore_slice(_) => {
|
||||
let base = Load(bcx, GEPi(bcx, llval, [0u, abi::slice_elt_base]));
|
||||
let len = Load(bcx, GEPi(bcx, llval, [0u, abi::slice_elt_len]));
|
||||
(base, len)
|
||||
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), get_fill(bcx, body))
|
||||
(get_dataptr(bcx, body), UDiv(bcx, get_fill(bcx, body), vt.llunit_size))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -551,7 +584,7 @@ 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");
|
||||
|
@ -52,6 +52,8 @@ fn main () {
|
||||
```
|
||||
*/
|
||||
|
||||
use sys::size_of;
|
||||
use unstable::raw::Slice;
|
||||
use cast;
|
||||
use container::Container;
|
||||
use iter::{Iterator, range};
|
||||
@ -133,10 +135,10 @@ pub trait Rng {
|
||||
/// println!("{:?}", v);
|
||||
/// }
|
||||
/// ```
|
||||
fn fill_bytes(&mut self, mut dest: &mut [u8]) {
|
||||
// this relies on the lengths being transferred correctly when
|
||||
// transmuting between vectors like this.
|
||||
let as_u64: &mut &mut [u64] = unsafe { cast::transmute(&mut dest) };
|
||||
fn fill_bytes(&mut self, dest: &mut [u8]) {
|
||||
let mut slice: Slice<u64> = unsafe { cast::transmute_copy(&dest) };
|
||||
slice.len /= size_of::<u64>();
|
||||
let as_u64: &mut [u64] = unsafe { cast::transmute(slice) };
|
||||
for dest in as_u64.mut_iter() {
|
||||
*dest = self.next_u64();
|
||||
}
|
||||
@ -147,7 +149,9 @@ pub trait Rng {
|
||||
|
||||
// space for a u32
|
||||
if remaining >= 4 {
|
||||
let as_u32: &mut &mut [u32] = unsafe { cast::transmute(&mut dest) };
|
||||
let mut slice: Slice<u32> = unsafe { cast::transmute_copy(&dest) };
|
||||
slice.len /= size_of::<u32>();
|
||||
let as_u32: &mut [u32] = unsafe { cast::transmute(slice) };
|
||||
as_u32[as_u32.len() - 1] = self.next_u32();
|
||||
remaining -= 4;
|
||||
}
|
||||
|
@ -186,12 +186,7 @@ impl<'self> ReprVisitor<'self> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_vec_range(&mut self,
|
||||
_mtbl: uint,
|
||||
ptr: *(),
|
||||
len: uint,
|
||||
inner: *TyDesc)
|
||||
-> bool {
|
||||
pub fn write_vec_range(&mut self, ptr: *(), len: uint, inner: *TyDesc) -> bool {
|
||||
let mut p = ptr as *u8;
|
||||
let (sz, al) = unsafe { ((*inner).size, (*inner).align) };
|
||||
self.writer.write(['[' as u8]);
|
||||
@ -213,13 +208,8 @@ impl<'self> ReprVisitor<'self> {
|
||||
true
|
||||
}
|
||||
|
||||
pub fn write_unboxed_vec_repr(&mut self,
|
||||
mtbl: uint,
|
||||
v: &raw::Vec<()>,
|
||||
inner: *TyDesc)
|
||||
-> bool {
|
||||
self.write_vec_range(mtbl, ptr::to_unsafe_ptr(&v.data),
|
||||
v.fill, inner)
|
||||
pub fn write_unboxed_vec_repr(&mut self, _: uint, v: &raw::Vec<()>, inner: *TyDesc) -> bool {
|
||||
self.write_vec_range(ptr::to_unsafe_ptr(&v.data), v.fill, inner)
|
||||
}
|
||||
|
||||
fn write_escaped_char(&mut self, ch: char, is_str: bool) {
|
||||
@ -377,19 +367,32 @@ impl<'self> TyVisitor for ReprVisitor<'self> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
fn visit_evec_slice(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
|
||||
do self.get::<raw::Slice<()>> |this, s| {
|
||||
this.writer.write(['&' as u8]);
|
||||
this.write_mut_qualifier(mtbl);
|
||||
this.write_vec_range(mtbl, s.data, s.len, inner);
|
||||
this.write_vec_range(s.data, s.len, inner);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
fn visit_evec_slice(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
|
||||
do self.get::<raw::Slice<()>> |this, s| {
|
||||
this.writer.write(['&' as u8]);
|
||||
this.write_mut_qualifier(mtbl);
|
||||
let size = unsafe {
|
||||
if (*inner).size == 0 { 1 } else { (*inner).size }
|
||||
};
|
||||
this.write_vec_range(s.data, s.len * size, inner);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_evec_fixed(&mut self, n: uint, sz: uint, _align: uint,
|
||||
mtbl: uint, inner: *TyDesc) -> bool {
|
||||
_: uint, inner: *TyDesc) -> bool {
|
||||
let assumed_size = if sz == 0 { n } else { sz };
|
||||
do self.get::<()> |this, b| {
|
||||
this.write_vec_range(mtbl, ptr::to_unsafe_ptr(b), assumed_size, inner);
|
||||
this.write_vec_range(ptr::to_unsafe_ptr(b), assumed_size, inner);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ pub fn fail_(expr: *c_char, file: *c_char, line: size_t) -> ! {
|
||||
pub fn fail_bounds_check(file: *c_char, line: size_t,
|
||||
index: size_t, len: size_t) {
|
||||
let msg = format!("index out of bounds: the len is {} but the index is {}",
|
||||
len as int, index as int);
|
||||
len as uint, index as uint);
|
||||
do msg.with_c_str |buf| {
|
||||
fail_(buf, file, line);
|
||||
}
|
||||
|
@ -974,6 +974,7 @@ pub trait ImmutableVector<'self, T> {
|
||||
|
||||
impl<'self,T> ImmutableVector<'self, T> for &'self [T] {
|
||||
#[inline]
|
||||
#[cfg(stage0)]
|
||||
fn slice(&self, start: uint, end: uint) -> &'self [T] {
|
||||
assert!(start <= end);
|
||||
assert!(end <= self.len());
|
||||
@ -986,10 +987,27 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(not(stage0))]
|
||||
fn slice(&self, start: uint, end: uint) -> &'self [T] {
|
||||
assert!(start <= end);
|
||||
assert!(end <= self.len());
|
||||
do self.as_imm_buf |p, _len| {
|
||||
unsafe {
|
||||
cast::transmute(Slice {
|
||||
data: ptr::offset(p, start as int),
|
||||
len: (end - start)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn slice_from(&self, start: uint) -> &'self [T] {
|
||||
self.slice(start, self.len())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn slice_to(&self, end: uint) -> &'self [T] {
|
||||
self.slice(0, end)
|
||||
@ -1130,10 +1148,18 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(stage0)]
|
||||
fn as_imm_buf<U>(&self, f: &fn(*T, uint) -> U) -> U {
|
||||
let s = self.repr();
|
||||
f(s.data, s.len / sys::nonzero_size_of::<T>())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(not(stage0))]
|
||||
fn as_imm_buf<U>(&self, f: &fn(*T, uint) -> U) -> U {
|
||||
let s = self.repr();
|
||||
f(s.data, s.len)
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension methods for vectors contain `Eq` elements.
|
||||
@ -1899,6 +1925,7 @@ pub trait MutableVector<'self, T> {
|
||||
|
||||
impl<'self,T> MutableVector<'self, T> for &'self mut [T] {
|
||||
#[inline]
|
||||
#[cfg(stage0)]
|
||||
fn mut_slice(self, start: uint, end: uint) -> &'self mut [T] {
|
||||
assert!(start <= end);
|
||||
assert!(end <= self.len());
|
||||
@ -1912,6 +1939,21 @@ impl<'self,T> MutableVector<'self, T> for &'self mut [T] {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(not(stage0))]
|
||||
fn mut_slice(self, start: uint, end: uint) -> &'self mut [T] {
|
||||
assert!(start <= end);
|
||||
assert!(end <= self.len());
|
||||
do self.as_mut_buf |p, _len| {
|
||||
unsafe {
|
||||
cast::transmute(Slice {
|
||||
data: ptr::mut_offset(p, start as int) as *T,
|
||||
len: (end - start)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mut_slice_from(self, start: uint) -> &'self mut [T] {
|
||||
let len = self.len();
|
||||
@ -1991,11 +2033,18 @@ impl<'self,T> MutableVector<'self, T> for &'self mut [T] {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(stage0)]
|
||||
fn as_mut_buf<U>(self, f: &fn(*mut T, uint) -> U) -> U {
|
||||
let Slice{ data, len } = self.repr();
|
||||
f(data as *mut T, len / sys::nonzero_size_of::<T>())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(not(stage0))]
|
||||
fn as_mut_buf<U>(self, f: &fn(*mut T, uint) -> U) -> U {
|
||||
let Slice{ data, len } = self.repr();
|
||||
f(data as *mut T, len)
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for &[T] where T is Cloneable
|
||||
@ -2083,6 +2132,7 @@ pub mod raw {
|
||||
* not bytes).
|
||||
*/
|
||||
#[inline]
|
||||
#[cfg(stage0)]
|
||||
pub unsafe fn buf_as_slice<T,U>(p: *T,
|
||||
len: uint,
|
||||
f: &fn(v: &[T]) -> U) -> U {
|
||||
@ -2097,6 +2147,22 @@ pub mod raw {
|
||||
* not bytes).
|
||||
*/
|
||||
#[inline]
|
||||
#[cfg(not(stage0))]
|
||||
pub unsafe fn buf_as_slice<T,U>(p: *T,
|
||||
len: uint,
|
||||
f: &fn(v: &[T]) -> U) -> U {
|
||||
f(cast::transmute(Slice {
|
||||
data: p,
|
||||
len: len
|
||||
}))
|
||||
}
|
||||
|
||||
/**
|
||||
* Form a slice from a pointer and length (as a number of units,
|
||||
* not bytes).
|
||||
*/
|
||||
#[inline]
|
||||
#[cfg(stage0)]
|
||||
pub unsafe fn mut_buf_as_slice<T,U>(p: *mut T,
|
||||
len: uint,
|
||||
f: &fn(v: &mut [T]) -> U) -> U {
|
||||
@ -2106,6 +2172,21 @@ pub mod raw {
|
||||
}))
|
||||
}
|
||||
|
||||
/**
|
||||
* Form a slice from a pointer and length (as a number of units,
|
||||
* not bytes).
|
||||
*/
|
||||
#[inline]
|
||||
#[cfg(not(stage0))]
|
||||
pub unsafe fn mut_buf_as_slice<T,U>(p: *mut T,
|
||||
len: uint,
|
||||
f: &fn(v: &mut [T]) -> U) -> U {
|
||||
f(cast::transmute(Slice {
|
||||
data: p as *T,
|
||||
len: len
|
||||
}))
|
||||
}
|
||||
|
||||
/**
|
||||
* Unchecked vector indexing.
|
||||
*/
|
||||
|
@ -13,33 +13,33 @@
|
||||
// debugger:rbreak zzz
|
||||
// debugger:run
|
||||
// debugger:finish
|
||||
// debugger:print empty.size_in_bytes
|
||||
// debugger:print empty.length
|
||||
// check:$1 = 0
|
||||
|
||||
// debugger:print singleton.size_in_bytes
|
||||
// check:$2 = 8
|
||||
// debugger:print singleton.length
|
||||
// check:$2 = 1
|
||||
// debugger:print *((int64_t[1]*)(singleton.data_ptr))
|
||||
// check:$3 = {1}
|
||||
|
||||
// debugger:print multiple.size_in_bytes
|
||||
// check:$4 = 32
|
||||
// debugger:print multiple.length
|
||||
// check:$4 = 4
|
||||
// debugger:print *((int64_t[4]*)(multiple.data_ptr))
|
||||
// check:$5 = {2, 3, 4, 5}
|
||||
|
||||
// debugger:print slice_of_slice.size_in_bytes
|
||||
// check:$6 = 16
|
||||
// debugger:print slice_of_slice.length
|
||||
// check:$6 = 2
|
||||
// debugger:print *((int64_t[2]*)(slice_of_slice.data_ptr))
|
||||
// check:$7 = {3, 4}
|
||||
|
||||
// debugger:print padded_tuple.size_in_bytes
|
||||
// check:$8 = 16
|
||||
// debugger:print padded_tuple.length
|
||||
// check:$8 = 2
|
||||
// debugger:print padded_tuple.data_ptr[0]
|
||||
// check:$9 = {6, 7}
|
||||
// debugger:print padded_tuple.data_ptr[1]
|
||||
// check:$10 = {8, 9}
|
||||
|
||||
// debugger:print padded_struct.size_in_bytes
|
||||
// check:$11 = 24
|
||||
// debugger:print padded_struct.length
|
||||
// check:$11 = 2
|
||||
// debugger:print padded_struct.data_ptr[0]
|
||||
// check:$12 = {x = 10, y = 11, z = 12}
|
||||
// debugger:print padded_struct.data_ptr[1]
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
@ -8,12 +8,12 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// error-pattern:index out of bounds: the len is 1024 but the index is -1
|
||||
// error-pattern:index out of bounds: the len is 3 but the index is
|
||||
|
||||
use std::vec;
|
||||
use std::uint::max_value;
|
||||
use std::sys::size_of;
|
||||
|
||||
fn main() {
|
||||
let v = vec::from_fn(1024u, {|n| n});
|
||||
// this should trip a bounds check
|
||||
error2!("{:?}", v[-1i8]);
|
||||
let xs = [1, 2, 3];
|
||||
xs[max_value / size_of::<int>() + 1];
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
// -*- rust -*-
|
||||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
|
||||
// error-pattern:index out of bounds: the len is 2 but the index is -1
|
||||
fn main() {
|
||||
let v: ~[int] = ~[10, 20];
|
||||
let x: int = 0;
|
||||
assert_eq!(v[x], 10);
|
||||
// Bounds-check failure.
|
||||
|
||||
assert_eq!(v[x - 1], 20);
|
||||
}
|
0
src/test/run-pass/generic-static-methods.rs
Executable file → Normal file
0
src/test/run-pass/generic-static-methods.rs
Executable file → Normal file
Loading…
x
Reference in New Issue
Block a user