From bd7610f3e3861f5b2323ef03ed1c3ccbb7acef55 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Wed, 16 Oct 2013 12:04:51 -0400 Subject: [PATCH] introduce `base_and_len` fns for element length --- src/librustc/middle/trans/_match.rs | 20 ++++------- src/librustc/middle/trans/controlflow.rs | 2 +- src/librustc/middle/trans/datum.rs | 24 +++++++++++++ src/librustc/middle/trans/expr.rs | 16 +++------ src/librustc/middle/trans/tvec.rs | 43 +++++++++++++++++++++--- 5 files changed, 75 insertions(+), 30 deletions(-) diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index dc07852ad91..dbcfb4eebbf 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -1025,7 +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_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| { @@ -1042,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}, @@ -1058,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, 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); } @@ -1646,8 +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_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; } } diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs index 3055c1e64fc..105cb6e5606 100644 --- a/src/librustc/middle/trans/controlflow.rs +++ b/src/librustc/middle/trans/controlflow.rs @@ -305,7 +305,7 @@ pub fn trans_fail_expr(bcx: @mut Block, 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; diff --git a/src/librustc/middle/trans/datum.rs b/src/librustc/middle/trans/datum.rs index 34f1a6fa2a7..6411283b79d 100644 --- a/src/librustc/middle/trans/datum.rs +++ b/src/librustc/middle/trans/datum.rs @@ -794,6 +794,30 @@ pub fn get_vec_base_and_byte_len_no_root(&self, bcx: @mut Block) 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, diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 81ab3b5f2ec..48d3e3f7c58 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -265,7 +265,7 @@ fn auto_slice(bcx: @mut Block, 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 @@ -275,11 +275,8 @@ fn auto_slice(bcx: @mut Block, 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} } @@ -978,17 +975,14 @@ fn trans_index(bcx: @mut Block, 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()); diff --git a/src/librustc/middle/trans/tvec.rs b/src/librustc/middle/trans/tvec.rs index eab642ccb91..bde98eff41c 100644 --- a/src/librustc/middle/trans/tvec.rs +++ b/src/librustc/middle/trans/tvec.rs @@ -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); @@ -501,8 +501,7 @@ pub fn elements_required(bcx: @mut Block, content_expr: &ast::Expr) -> uint { } } -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) { //! // @@ -539,6 +538,40 @@ pub fn get_base_and_byte_len(bcx: @mut Block, } } +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, @@ -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"); -- 2.44.0