Skip to content

Commit

Permalink
don't go through llvm for const indexing
Browse files Browse the repository at this point in the history
  • Loading branch information
Oliver Schneider committed May 13, 2015
1 parent 30a42fa commit fc24ef3
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 53 deletions.
55 changes: 54 additions & 1 deletion src/librustc/middle/const_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,9 @@ pub enum const_val {
const_binary(Rc<Vec<u8>>),
const_bool(bool),
Struct(ast::NodeId),
Tuple(ast::NodeId)
Tuple(ast::NodeId),
Array(Vec<P<Expr>>),
Repeat(P<Expr>, u64),
}

pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<ast::Pat> {
Expand Down Expand Up @@ -294,11 +296,15 @@ pub enum ErrKind {
NegateOnBinary,
NegateOnStruct,
NegateOnTuple,
NegateOnArray,
NegateOnRepeat,
NotOnFloat,
NotOnString,
NotOnBinary,
NotOnStruct,
NotOnTuple,
NotOnArray,
NotOnRepeat,

NegateWithOverflow(i64),
AddiWithOverflow(i64, i64),
Expand All @@ -318,6 +324,12 @@ pub enum ErrKind {
ExpectedConstTuple,
ExpectedConstStruct,
TupleIndexOutOfBounds,
IndexedNonVec,
IndexNotNatural,
IndexNotInt,
IndexOutOfBounds,
RepeatCountNotNatural,
RepeatCountNotInt,

MiscBinaryOp,
MiscCatchAll,
Expand All @@ -339,11 +351,15 @@ impl ConstEvalErr {
NegateOnBinary => "negate on binary literal".into_cow(),
NegateOnStruct => "negate on struct".into_cow(),
NegateOnTuple => "negate on tuple".into_cow(),
NegateOnArray => "negate on array".into_cow(),
NegateOnRepeat => "negate on repeat".into_cow(),
NotOnFloat => "not on float or string".into_cow(),
NotOnString => "not on float or string".into_cow(),
NotOnBinary => "not on binary literal".into_cow(),
NotOnStruct => "not on struct".into_cow(),
NotOnTuple => "not on tuple".into_cow(),
NotOnArray => "not on array".into_cow(),
NotOnRepeat => "not on repeat".into_cow(),

NegateWithOverflow(..) => "attempted to negate with overflow".into_cow(),
AddiWithOverflow(..) => "attempted to add with overflow".into_cow(),
Expand All @@ -363,6 +379,12 @@ impl ConstEvalErr {
ExpectedConstTuple => "expected constant tuple".into_cow(),
ExpectedConstStruct => "expected constant struct".into_cow(),
TupleIndexOutOfBounds => "tuple index out of bounds".into_cow(),
IndexedNonVec => "indexing is only supported for arrays".into_cow(),
IndexNotNatural => "indices must be a natural number".into_cow(),
IndexNotInt => "indices must be integers".into_cow(),
IndexOutOfBounds => "array index out of bounds".into_cow(),
RepeatCountNotNatural => "repeat count must be a natural number".into_cow(),
RepeatCountNotInt => "repeat count must be integers".into_cow(),

MiscBinaryOp => "bad operands for binary".into_cow(),
MiscCatchAll => "unsupported constant expr".into_cow(),
Expand Down Expand Up @@ -672,6 +694,8 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
const_binary(_) => signal!(e, NegateOnBinary),
const_val::Tuple(_) => signal!(e, NegateOnTuple),
const_val::Struct(..) => signal!(e, NegateOnStruct),
const_val::Array(_) => signal!(e, NegateOnArray),
const_val::Repeat(..) => signal!(e, NegateOnRepeat),
}
}
ast::ExprUnary(ast::UnNot, ref inner) => {
Expand All @@ -684,6 +708,8 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
const_binary(_) => signal!(e, NotOnBinary),
const_val::Tuple(_) => signal!(e, NotOnTuple),
const_val::Struct(..) => signal!(e, NotOnStruct),
const_val::Array(_) => signal!(e, NotOnArray),
const_val::Repeat(..) => signal!(e, NotOnRepeat),
}
}
ast::ExprBinary(op, ref a, ref b) => {
Expand Down Expand Up @@ -873,6 +899,33 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
ast::ExprTup(_) => {
const_val::Tuple(e.id)
}
ast::ExprIndex(ref arr, ref idx) => {
let arr = try!(eval_const_expr_partial(tcx, arr, None));
let idx = try!(eval_const_expr_partial(tcx, idx, None));
let idx = match idx {
const_int(i) if i >= 0 => i as u64,
const_int(_) => signal!(e, IndexNotNatural),
const_uint(i) => i,
_ => signal!(e, IndexNotInt),
};
match arr {
const_val::Array(ref v) if idx as usize >= v.len() => signal!(e, IndexOutOfBounds),
const_val::Array(v) => try!(eval_const_expr_partial(tcx, &*v[idx as usize], None)),
const_val::Repeat(_, n) if idx >= n => signal!(e, IndexOutOfBounds),
const_val::Repeat(elem, _) => try!(eval_const_expr_partial(tcx, &*elem, None)),
_ => signal!(e, IndexedNonVec),
}
}
ast::ExprVec(ref arr) => const_val::Array(arr.clone()), // FIXME: eval elements?
ast::ExprRepeat(ref elem, ref n) => const_val::Repeat(
elem.clone(),
match try!(eval_const_expr_partial(tcx, &**n, None)) {
const_int(i) if i >= 0 => i as u64,
const_int(_) => signal!(e, RepeatCountNotNatural),
const_uint(i) => i,
_ => signal!(e, RepeatCountNotInt),
},
),
ast::ExprStruct(..) => {
const_val::Struct(e.id)
}
Expand Down
4 changes: 3 additions & 1 deletion src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6198,7 +6198,9 @@ pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> usize {
const_eval::const_bool(_) => "boolean",
const_eval::const_binary(_) => "binary array",
const_eval::Struct(..) => "struct",
const_eval::Tuple(_) => "tuple"
const_eval::Tuple(_) => "tuple",
const_eval::Array(_) => "array",
const_eval::Repeat(..) => "repeat",
};
span_err!(tcx.sess, count_expr.span, E0306,
"expected positive integer for repeat count, found {}",
Expand Down
51 changes: 0 additions & 51 deletions src/librustc_trans/trans/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ use middle::ty::{self, Ty};
use util::ppaux::{Repr, ty_to_string};

use std::iter::repeat;
use libc::c_uint;
use syntax::{ast, ast_util};
use syntax::parse::token;
use syntax::ptr::P;
Expand Down Expand Up @@ -565,56 +564,6 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
})
}

ast::ExprIndex(ref base, ref index) => {
let (bv, bt) = const_expr(cx, &**base, param_substs);
let iv = match const_eval::eval_const_expr_partial(cx.tcx(), &**index, None) {
Ok(const_eval::const_int(i)) => i as u64,
Ok(const_eval::const_uint(u)) => u,
_ => cx.sess().span_bug(index.span,
"index is not an integer-constant expression")
};
let (arr, len) = match bt.sty {
ty::ty_vec(_, Some(u)) => (bv, C_uint(cx, u)),
ty::ty_vec(_, None) | ty::ty_str => {
let e1 = const_get_elt(cx, bv, &[0]);
(const_deref_ptr(cx, e1), const_get_elt(cx, bv, &[1]))
}
ty::ty_rptr(_, mt) => match mt.ty.sty {
ty::ty_vec(_, Some(u)) => {
(const_deref_ptr(cx, bv), C_uint(cx, u))
},
_ => cx.sess().span_bug(base.span,
&format!("index-expr base must be a vector \
or string type, found {}",
ty_to_string(cx.tcx(), bt)))
},
_ => cx.sess().span_bug(base.span,
&format!("index-expr base must be a vector \
or string type, found {}",
ty_to_string(cx.tcx(), bt)))
};

let len = llvm::LLVMConstIntGetZExtValue(len) as u64;
let len = match bt.sty {
ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => match ty.sty {
ty::ty_str => {
assert!(len > 0);
len - 1
}
_ => len
},
_ => len
};
if iv >= len {
// FIXME #3170: report this earlier on in the const-eval
// pass. Reporting here is a bit late.
cx.sess().span_err(e.span,
"const index-expr is out of bounds");
C_undef(type_of::type_of(cx, bt).element_type())
} else {
const_get_elt(cx, arr, &[iv as c_uint])
}
}
ast::ExprCast(ref base, _) => {
let llty = type_of::type_of(cx, ety);
let (v, basety) = const_expr(cx, &**base, param_substs);
Expand Down
16 changes: 16 additions & 0 deletions src/test/run-pass/array_const_slice.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright 2015 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.


fn main() {
const arr: [i32; 6] = [42, 43, 44, 45, 46, 47];
const idx: usize = 3;
const val: i32 = arr[idx];
}

0 comments on commit fc24ef3

Please sign in to comment.