rustup
This commit is contained in:
parent
1af2c397bf
commit
35502fd47d
5 changed files with 27 additions and 36 deletions
|
@ -456,7 +456,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
|
|
||||||
General { discr, ref variants, .. } => {
|
General { discr, ref variants, .. } => {
|
||||||
if let mir::AggregateKind::Adt(adt_def, variant, _, _) = *kind {
|
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();
|
let discr_size = discr.size().bytes();
|
||||||
if variants[variant].packed {
|
if variants[variant].packed {
|
||||||
let ptr = self.force_allocation(dest)?.to_ptr_and_extra().0;
|
let ptr = self.force_allocation(dest)?.to_ptr_and_extra().0;
|
||||||
|
@ -529,7 +529,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
CEnum { .. } => {
|
CEnum { .. } => {
|
||||||
assert_eq!(operands.len(), 0);
|
assert_eq!(operands.len(), 0);
|
||||||
if let mir::AggregateKind::Adt(adt_def, variant, _, _) = *kind {
|
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)?;
|
self.write_primval(dest, PrimVal::Bytes(n), dest_ty)?;
|
||||||
} else {
|
} else {
|
||||||
bug!("tried to assign {:?} to Layout::CEnum", kind);
|
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) {
|
if log_enabled!(::log::LogLevel::Trace) {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#![feature(
|
#![feature(
|
||||||
btree_range,
|
btree_range,
|
||||||
collections,
|
collections,
|
||||||
field_init_shorthand,
|
|
||||||
i128_type,
|
i128_type,
|
||||||
pub_restricted,
|
pub_restricted,
|
||||||
rustc_private,
|
rustc_private,
|
||||||
|
|
|
@ -119,6 +119,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
// Defined to do nothing. These are added by optimization passes, to avoid changing the
|
// Defined to do nothing. These are added by optimization passes, to avoid changing the
|
||||||
// size of MIR constantly.
|
// size of MIR constantly.
|
||||||
Nop => {}
|
Nop => {}
|
||||||
|
|
||||||
|
InlineAsm { .. } => return Err(EvalError::InlineAsm),
|
||||||
}
|
}
|
||||||
|
|
||||||
self.frame_mut().stmt += 1;
|
self.frame_mut().stmt += 1;
|
||||||
|
|
|
@ -121,7 +121,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
Layout::General { .. } => {
|
Layout::General { .. } => {
|
||||||
let discr_val = self.read_discriminant_value(adt_ptr, ty)? as u128;
|
let discr_val = self.read_discriminant_value(adt_ptr, ty)? as u128;
|
||||||
let ptr = self.force_allocation(lval)?.to_ptr();
|
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) => {
|
Some(i) => {
|
||||||
lval = Lvalue::Ptr {
|
lval = Lvalue::Ptr {
|
||||||
ptr,
|
ptr,
|
||||||
|
|
|
@ -35,22 +35,16 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
|
|
||||||
Goto { target } => self.goto_block(target),
|
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, .. } => {
|
SwitchInt { ref discr, ref values, ref targets, .. } => {
|
||||||
let discr_val = self.eval_and_read_lvalue(discr)?;
|
let discr_val = self.eval_operand(discr)?;
|
||||||
let discr_ty = self.lvalue_ty(discr);
|
let discr_ty = self.operand_ty(discr);
|
||||||
let discr_prim = self.value_to_primval(discr_val, discr_ty)?;
|
let discr_prim = self.value_to_primval(discr_val, discr_ty)?;
|
||||||
|
|
||||||
// Branch to the `otherwise` case by default, if no match is found.
|
// Branch to the `otherwise` case by default, if no match is found.
|
||||||
let mut target_block = targets[targets.len() - 1];
|
let mut target_block = targets[targets.len() - 1];
|
||||||
|
|
||||||
for (index, const_val) in values.iter().enumerate() {
|
for (index, const_int) in values.iter().enumerate() {
|
||||||
let val = self.const_to_value(const_val)?;
|
let prim = PrimVal::Bytes(const_int.to_u128_unchecked());
|
||||||
let prim = self.value_to_primval(val, discr_ty)?;
|
|
||||||
if discr_prim.to_bytes()? == prim.to_bytes()? {
|
if discr_prim.to_bytes()? == prim.to_bytes()? {
|
||||||
target_block = targets[index];
|
target_block = targets[index];
|
||||||
break;
|
break;
|
||||||
|
@ -60,23 +54,6 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
self.goto_block(target_block);
|
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, .. } => {
|
Call { ref func, ref args, ref destination, .. } => {
|
||||||
let destination = match *destination {
|
let destination = match *destination {
|
||||||
Some((ref lv, target)) => Some((self.eval_lvalue(lv)?, target)),
|
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);
|
trace!("layout({:?}) = {:#?}", dest_ty, dest_layout);
|
||||||
match *dest_layout {
|
match *dest_layout {
|
||||||
Layout::Univariant { .. } => {
|
Layout::Univariant { .. } => {
|
||||||
let disr_val = v.disr_val.to_u128_unchecked();
|
let disr_val = v.disr_val;
|
||||||
assert_eq!(disr_val, 0);
|
assert_eq!(disr_val, 0);
|
||||||
self.assign_fields(lvalue, dest_ty, args)?;
|
self.assign_fields(lvalue, dest_ty, args)?;
|
||||||
},
|
},
|
||||||
Layout::General { discr, ref variants, .. } => {
|
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();
|
let discr_size = discr.size().bytes();
|
||||||
self.assign_discr_and_fields(
|
self.assign_discr_and_fields(
|
||||||
lvalue,
|
lvalue,
|
||||||
|
@ -234,7 +211,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
)?;
|
)?;
|
||||||
},
|
},
|
||||||
Layout::StructWrappedNullablePointer { nndiscr, ref discrfield, .. } => {
|
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 {
|
if nndiscr as u128 == disr_val {
|
||||||
self.assign_fields(lvalue, dest_ty, args)?;
|
self.assign_fields(lvalue, dest_ty, args)?;
|
||||||
} else {
|
} 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::*;
|
use rustc::ty::layout::Layout::*;
|
||||||
let adt_layout = self.type_layout(adt_ty)?;
|
let adt_layout = self.type_layout(adt_ty)?;
|
||||||
trace!("read_discriminant_value {:#?}", adt_layout);
|
trace!("read_discriminant_value {:#?}", adt_layout);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue