1
Fork 0

Second field of ScalarPair can be undef in some cases

This commit is contained in:
Oliver Schneider 2018-08-02 13:16:53 +02:00
parent c8e30c4295
commit 37e18e7a30
6 changed files with 28 additions and 18 deletions

View file

@ -18,7 +18,9 @@ pub enum ConstValue<'tcx> {
/// Used only for types with layout::abi::Scalar ABI and ZSTs
Scalar(Scalar),
/// Used only for types with layout::abi::ScalarPair
ScalarPair(Scalar, Scalar),
///
/// The second field may be undef in case of `Option<usize>::None`
ScalarPair(Scalar, ScalarMaybeUndef),
/// Used only for the remaining cases. An allocation + offset into the allocation
ByRef(&'tcx Allocation, Size),
}
@ -28,10 +30,7 @@ impl<'tcx> ConstValue<'tcx> {
pub fn from_byval_value(val: Value) -> EvalResult<'static, Self> {
Ok(match val {
Value::ByRef(..) => bug!(),
Value::ScalarPair(a, b) => ConstValue::ScalarPair(
a.unwrap_or_err()?,
b.unwrap_or_err()?,
),
Value::ScalarPair(a, b) => ConstValue::ScalarPair(a.unwrap_or_err()?, b),
Value::Scalar(val) => ConstValue::Scalar(val.unwrap_or_err()?),
})
}
@ -41,7 +40,7 @@ impl<'tcx> ConstValue<'tcx> {
match *self {
ConstValue::Unevaluated(..) |
ConstValue::ByRef(..) => None,
ConstValue::ScalarPair(a, b) => Some(Value::ScalarPair(a.into(), b.into())),
ConstValue::ScalarPair(a, b) => Some(Value::ScalarPair(a.into(), b)),
ConstValue::Scalar(val) => Some(Value::Scalar(val.into())),
}
}

View file

@ -10,7 +10,7 @@
use rustc::mir::interpret::ConstEvalErr;
use rustc::mir;
use rustc::mir::interpret::ConstValue;
use rustc::mir::interpret::{ConstValue, ScalarMaybeUndef};
use rustc::ty;
use rustc::ty::layout::{self, Align, LayoutOf, TyLayout};
use rustc_data_structures::indexed_vec::Idx;
@ -110,12 +110,16 @@ impl OperandRef<'ll, 'tcx> {
a_scalar,
layout.scalar_pair_element_llvm_type(bx.cx, 0, true),
);
let b_llval = scalar_to_llvm(
bx.cx,
b,
b_scalar,
layout.scalar_pair_element_llvm_type(bx.cx, 1, true),
);
let b_layout = layout.scalar_pair_element_llvm_type(bx.cx, 1, true);
let b_llval = match b {
ScalarMaybeUndef::Scalar(b) => scalar_to_llvm(
bx.cx,
b,
b_scalar,
b_layout,
),
ScalarMaybeUndef::Undef => C_undef(b_layout),
};
OperandValue::Pair(a_llval, b_llval)
},
ConstValue::ByRef(alloc, offset) => {

View file

@ -1102,6 +1102,13 @@ pub fn compare_const_vals<'a, 'tcx>(
len_b,
),
) if ptr_a.offset.bytes() == 0 && ptr_b.offset.bytes() == 0 => {
let len_a = len_a.unwrap_or_err().ok();
let len_b = len_b.unwrap_or_err().ok();
if len_a.is_none() || len_b.is_none() {
tcx.sess.struct_err("str slice len is undef").delay_as_bug();
}
let len_a = len_a?;
let len_b = len_b?;
if let Ok(len_a) = len_a.to_bits(tcx.data_layout.pointer_size) {
if let Ok(len_b) = len_b.to_bits(tcx.data_layout.pointer_size) {
if len_a == len_b {

View file

@ -87,7 +87,7 @@ pub fn value_to_const_value<'tcx>(
}
let val = match val {
Value::Scalar(val) => ConstValue::Scalar(val.unwrap_or_err()?),
Value::ScalarPair(a, b) => ConstValue::ScalarPair(a.unwrap_or_err()?, b.unwrap_or_err()?),
Value::ScalarPair(a, b) => ConstValue::ScalarPair(a.unwrap_or_err()?, b),
Value::ByRef(ptr, align) => {
let ptr = ptr.to_ptr().unwrap();
let alloc = ecx.memory.get(ptr.alloc_id)?;

View file

@ -193,7 +193,7 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor;
use rustc::hir::map as hir_map;
use rustc::hir::def_id::DefId;
use rustc::mir::interpret::{AllocId, ConstValue};
use rustc::mir::interpret::{AllocId, ConstValue, ScalarMaybeUndef};
use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem};
use rustc::ty::subst::Substs;
use rustc::ty::{self, TypeFoldable, Ty, TyCtxt, GenericParamDefKind};
@ -1264,11 +1264,11 @@ fn collect_const<'a, 'tcx>(
};
match val {
ConstValue::Unevaluated(..) => bug!("const eval yielded unevaluated const"),
ConstValue::ScalarPair(Scalar::Ptr(a), Scalar::Ptr(b)) => {
ConstValue::ScalarPair(Scalar::Ptr(a), ScalarMaybeUndef::Scalar(Scalar::Ptr(b))) => {
collect_miri(tcx, a.alloc_id, output);
collect_miri(tcx, b.alloc_id, output);
}
ConstValue::ScalarPair(_, Scalar::Ptr(ptr)) |
ConstValue::ScalarPair(_, ScalarMaybeUndef::Scalar(Scalar::Ptr(ptr))) |
ConstValue::ScalarPair(Scalar::Ptr(ptr), _) |
ConstValue::Scalar(Scalar::Ptr(ptr)) =>
collect_miri(tcx, ptr.alloc_id, output),

View file

@ -16,7 +16,7 @@ union Foo {
enum Bar {
Boo = [unsafe { Foo { b: () }.a }; 4][3],
//~^ ERROR constant evaluation of enum discriminant resulted in non-integer
//~^ ERROR could not evaluate enum discriminant
}
fn main() {