1
Fork 0
This commit is contained in:
Oliver Schneider 2017-02-24 10:39:55 +01:00
parent 1af2c397bf
commit 35502fd47d
5 changed files with 27 additions and 36 deletions

View file

@ -456,7 +456,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
General { discr, ref variants, .. } => {
if let mir::AggregateKind::Adt(adt_def, variant, _, _) = *kind {
let discr_val = adt_def.variants[variant].disr_val.to_u128_unchecked();
let discr_val = adt_def.variants[variant].disr_val;
let discr_size = discr.size().bytes();
if variants[variant].packed {
let ptr = self.force_allocation(dest)?.to_ptr_and_extra().0;
@ -529,7 +529,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
CEnum { .. } => {
assert_eq!(operands.len(), 0);
if let mir::AggregateKind::Adt(adt_def, variant, _, _) = *kind {
let n = adt_def.variants[variant].disr_val.to_u128_unchecked();
let n = adt_def.variants[variant].disr_val;
self.write_primval(dest, PrimVal::Bytes(n), dest_ty)?;
} else {
bug!("tried to assign {:?} to Layout::CEnum", kind);
@ -661,7 +661,20 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
}
}
InlineAsm { .. } => return Err(EvalError::InlineAsm),
Discriminant(ref lvalue) => {
let lval = self.eval_lvalue(lvalue)?;
let ty = self.lvalue_ty(lvalue);
let ptr = self.force_allocation(lval)?.to_ptr();
let discr_val = self.read_discriminant_value(ptr, ty)?;
if let ty::TyAdt(adt_def, _) = ty.sty {
if adt_def.variants.iter().all(|v| discr_val != v.disr_val) {
return Err(EvalError::InvalidDiscriminant);
}
} else {
bug!("rustc only generates Rvalue::Discriminant for enums");
}
self.write_primval(dest, PrimVal::Bytes(discr_val), dest_ty)?;
},
}
if log_enabled!(::log::LogLevel::Trace) {

View file

@ -1,7 +1,6 @@
#![feature(
btree_range,
collections,
field_init_shorthand,
i128_type,
pub_restricted,
rustc_private,

View file

@ -119,6 +119,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
// Defined to do nothing. These are added by optimization passes, to avoid changing the
// size of MIR constantly.
Nop => {}
InlineAsm { .. } => return Err(EvalError::InlineAsm),
}
self.frame_mut().stmt += 1;

View file

@ -121,7 +121,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
Layout::General { .. } => {
let discr_val = self.read_discriminant_value(adt_ptr, ty)? as u128;
let ptr = self.force_allocation(lval)?.to_ptr();
match adt_def.variants.iter().position(|v| discr_val == v.disr_val.to_u128_unchecked()) {
match adt_def.variants.iter().position(|v| discr_val == v.disr_val) {
Some(i) => {
lval = Lvalue::Ptr {
ptr,

View file

@ -35,22 +35,16 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
Goto { target } => self.goto_block(target),
If { ref cond, targets: (then_target, else_target) } => {
let cond_val = self.eval_operand_to_primval(cond)?.to_bool()?;
self.goto_block(if cond_val { then_target } else { else_target });
}
SwitchInt { ref discr, ref values, ref targets, .. } => {
let discr_val = self.eval_and_read_lvalue(discr)?;
let discr_ty = self.lvalue_ty(discr);
let discr_val = self.eval_operand(discr)?;
let discr_ty = self.operand_ty(discr);
let discr_prim = self.value_to_primval(discr_val, discr_ty)?;
// Branch to the `otherwise` case by default, if no match is found.
let mut target_block = targets[targets.len() - 1];
for (index, const_val) in values.iter().enumerate() {
let val = self.const_to_value(const_val)?;
let prim = self.value_to_primval(val, discr_ty)?;
for (index, const_int) in values.iter().enumerate() {
let prim = PrimVal::Bytes(const_int.to_u128_unchecked());
if discr_prim.to_bytes()? == prim.to_bytes()? {
target_block = targets[index];
break;
@ -60,23 +54,6 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
self.goto_block(target_block);
}
Switch { ref discr, ref targets, adt_def } => {
// FIXME(solson)
let lvalue = self.eval_lvalue(discr)?;
let lvalue = self.force_allocation(lvalue)?;
let adt_ptr = lvalue.to_ptr();
let adt_ty = self.lvalue_ty(discr);
let discr_val = self.read_discriminant_value(adt_ptr, adt_ty)?;
let matching = adt_def.variants.iter()
.position(|v| discr_val == v.disr_val.to_u128_unchecked());
match matching {
Some(i) => self.goto_block(targets[i]),
None => return Err(EvalError::InvalidDiscriminant),
}
}
Call { ref func, ref args, ref destination, .. } => {
let destination = match *destination {
Some((ref lv, target)) => Some((self.eval_lvalue(lv)?, target)),
@ -216,12 +193,12 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
trace!("layout({:?}) = {:#?}", dest_ty, dest_layout);
match *dest_layout {
Layout::Univariant { .. } => {
let disr_val = v.disr_val.to_u128_unchecked();
let disr_val = v.disr_val;
assert_eq!(disr_val, 0);
self.assign_fields(lvalue, dest_ty, args)?;
},
Layout::General { discr, ref variants, .. } => {
let disr_val = v.disr_val.to_u128_unchecked();
let disr_val = v.disr_val;
let discr_size = discr.size().bytes();
self.assign_discr_and_fields(
lvalue,
@ -234,7 +211,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
)?;
},
Layout::StructWrappedNullablePointer { nndiscr, ref discrfield, .. } => {
let disr_val = v.disr_val.to_u128_unchecked();
let disr_val = v.disr_val;
if nndiscr as u128 == disr_val {
self.assign_fields(lvalue, dest_ty, args)?;
} else {
@ -325,7 +302,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
}
}
fn read_discriminant_value(&self, adt_ptr: Pointer, adt_ty: Ty<'tcx>) -> EvalResult<'tcx, u128> {
pub fn read_discriminant_value(&self, adt_ptr: Pointer, adt_ty: Ty<'tcx>) -> EvalResult<'tcx, u128> {
use rustc::ty::layout::Layout::*;
let adt_layout = self.type_layout(adt_ty)?;
trace!("read_discriminant_value {:#?}", adt_layout);