Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

represent slices with length in elements, not bytes #9885

Merged
merged 6 commits into from
Oct 16, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 7 additions & 16 deletions src/librustc/middle/trans/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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| {
Expand All @@ -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},
Expand All @@ -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);
}
Expand Down Expand Up @@ -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;
}
}
Expand Down
16 changes: 7 additions & 9 deletions src/librustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) => {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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())
}


Expand Down Expand Up @@ -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));
}
Expand Down
48 changes: 18 additions & 30 deletions src/librustc/middle/trans/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
}
_ => {}
}
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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) => {
Expand All @@ -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)
Expand All @@ -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")
}
Expand Down
36 changes: 30 additions & 6 deletions src/librustc/middle/trans/datum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand All @@ -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.

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/trans/debuginfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1865,7 +1865,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,
Expand Down
12 changes: 4 additions & 8 deletions src/librustc/middle/trans/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down Expand Up @@ -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());
Expand Down
51 changes: 42 additions & 9 deletions src/librustc/middle/trans/tvec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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]));
}
}

Expand Down Expand Up @@ -502,15 +501,14 @@ 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_len()` which will handle any conversions for
// call `Datum::get_base_and_byte_len()` which will handle any conversions for
// you.

let ccx = bcx.ccx();
Expand All @@ -529,7 +527,8 @@ pub fn get_base_and_len(bcx: @mut Block,
}
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]));
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 => {
Expand All @@ -539,6 +538,40 @@ pub fn get_base_and_len(bcx: @mut Block,
}
}

pub fn get_base_and_len(bcx: @mut Block, llval: ValueRef, vec_ty: ty::t) -> (ValueRef, ValueRef) {
//!
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, this will mean the doc-string of get_base_and_len is ""; the rest of the block is ignored (it's treated as a normal comment).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I just copy-pasted it from above since I plan on removing the other function soon. I didn't notice it was missing the other ! markers.

//
// 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,
Expand All @@ -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");
Expand Down
Loading