use middle::const_eval::{const_int_checked_rem, const_uint_checked_rem};
use middle::const_eval::{const_int_checked_shl, const_uint_checked_shl};
use middle::const_eval::{const_int_checked_shr, const_uint_checked_shr};
-use middle::const_eval::EvalHint::ExprTypeChecked;
-use middle::const_eval::eval_const_expr_partial;
use middle::def::Def;
use middle::def_id::DefId;
use trans::{adt, closure, debuginfo, expr, inline, machine};
use trans::Disr;
use middle::subst::Substs;
use middle::ty::adjustment::{AdjustDerefRef, AdjustReifyFnPointer};
-use middle::ty::adjustment::AdjustUnsafeFnPointer;
+use middle::ty::adjustment::{AdjustUnsafeFnPointer, AdjustMutToConstPointer};
use middle::ty::{self, Ty};
use middle::ty::cast::{CastTy,IntTy};
use util::nodemap::NodeMap;
gv
}
-fn const_deref_ptr(cx: &CrateContext, v: ValueRef) -> ValueRef {
+/// Deref a constant pointer
+fn load_const(cx: &CrateContext, v: ValueRef, t: Ty) -> ValueRef {
let v = match cx.const_unsized().borrow().get(&v) {
Some(&v) => v,
None => v
};
- unsafe {
- llvm::LLVMGetInitializer(v)
+ let d = unsafe { llvm::LLVMGetInitializer(v) };
+ if t.is_bool() {
+ unsafe { llvm::LLVMConstTrunc(d, Type::i1(cx).to_ref()) }
+ } else {
+ d
}
}
match ty.builtin_deref(true, ty::NoPreference) {
Some(mt) => {
if type_is_sized(cx.tcx(), mt.ty) {
- (const_deref_ptr(cx, v), mt.ty)
+ (load_const(cx, v, mt.ty), mt.ty)
} else {
// Derefing a fat pointer does not change the representation,
// just the type to the unsized contents.
}
}
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum TrueConst {
Yes, No
}
// FIXME(#19925) once fn item types are
// zero-sized, we'll need to do something here
}
- Some(AdjustUnsafeFnPointer) => {
+ Some(AdjustUnsafeFnPointer) | Some(AdjustMutToConstPointer) => {
// purely a type-level thing
}
Some(AdjustDerefRef(adj)) => {
let is_float = ty.is_fp();
let signed = ty.is_signed();
- let (te2, _) = try!(const_expr(cx, &e2, param_substs, fn_args, trueconst));
+ let (te2, ty2) = try!(const_expr(cx, &e2, param_substs, fn_args, trueconst));
+ debug!("const_expr_unadjusted: te2={}, ty={:?}",
+ cx.tn().val_to_string(te2),
+ ty2);
try!(check_binary_expr_validity(cx, e, ty, te1, te2, trueconst));
},
hir::ExprIndex(ref base, ref index) => {
let (bv, bt) = try!(const_expr(cx, &base, param_substs, fn_args, trueconst));
- let iv = match eval_const_expr_partial(cx.tcx(), &index, ExprTypeChecked, None) {
- Ok(ConstVal::Int(i)) => i as u64,
- Ok(ConstVal::Uint(u)) => u,
- _ => cx.sess().span_bug(index.span,
- "index is not an integer-constant expression")
+ let iv = try!(const_expr(cx, &index, param_substs, fn_args, TrueConst::Yes)).0;
+ let iv = if let Some(iv) = const_to_opt_uint(iv) {
+ iv
+ } else {
+ cx.sess().span_bug(index.span, "index is not an integer-constant expression");
};
let (arr, len) = match bt.sty {
ty::TyArray(_, u) => (bv, C_uint(cx, u)),
- ty::TySlice(_) | ty::TyStr => {
+ ty::TySlice(..) | ty::TyStr => {
let e1 = const_get_elt(cx, bv, &[0]);
- (const_deref_ptr(cx, e1), const_get_elt(cx, bv, &[1]))
+ (load_const(cx, e1, bt), const_get_elt(cx, bv, &[1]))
},
ty::TyRef(_, mt) => match mt.ty.sty {
ty::TyArray(_, u) => {
- (const_deref_ptr(cx, bv), C_uint(cx, u))
+ (load_const(cx, bv, mt.ty), C_uint(cx, u))
},
_ => cx.sess().span_bug(base.span,
&format!("index-expr base must be a vector \
expr::trans_def_fn_unadjusted(cx, e, def, param_substs).val
}
Def::Const(def_id) | Def::AssociatedConst(def_id) => {
- const_deref_ptr(cx, try!(get_const_val(cx, def_id, e, param_substs)))
+ load_const(cx, try!(get_const_val(cx, def_id, e, param_substs)),
+ ety)
}
Def::Variant(enum_did, variant_did) => {
let vinfo = cx.tcx().lookup_adt_def(enum_did).variant_with_id(variant_did);
}
}
Def::Struct(..) => {
- if let ty::TyBareFn(..) = ety.sty {
+ if let ty::TyFnDef(..) = ety.sty {
// Tuple struct.
expr::trans_def_fn_unadjusted(cx, e, def, param_substs).val
} else {