]> git.lizzy.rs Git - rust.git/commitdiff
rustup
authorOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Fri, 24 Feb 2017 09:39:55 +0000 (10:39 +0100)
committerOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Fri, 24 Feb 2017 09:39:55 +0000 (10:39 +0100)
src/eval_context.rs
src/lib.rs
src/step.rs
src/terminator/drop.rs
src/terminator/mod.rs

index 13fad7b4644afd8b2e713148cf5cf25524c6bd2a..54aae64c5caaf9eee61da1441e5dafe699c9dc88 100644 (file)
@@ -456,7 +456,7 @@ pub(super) fn eval_rvalue_into_lvalue(
 
                     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 @@ pub(super) fn eval_rvalue_into_lvalue(
                     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 @@ pub(super) fn eval_rvalue_into_lvalue(
                 }
             }
 
-            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) {
index 290b478eb648bd04dc336bd0e24399e8ee777472..d1d8e8cf229f66993176d48a1dbe1d7b9d566462 100644 (file)
@@ -1,7 +1,6 @@
 #![feature(
     btree_range,
     collections,
-    field_init_shorthand,
     i128_type,
     pub_restricted,
     rustc_private,
index 5c957f0cdc08b7e69b5c7a627ed2844824eeca29..c08ac9693a4b1d28f7ae8942c07a4ea4090711eb 100644 (file)
@@ -119,6 +119,8 @@ fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> EvalResult<'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;
index 71f3d46736605bd2a95cdd62164c9f97aa7a0d71..dd199a4266c14ddb98929abc7d0969f922689152 100644 (file)
@@ -121,7 +121,7 @@ pub fn drop(
                     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,
index 4fb3968161343736011686f36f9015bc0c0a1a68..183a3f54fb639d92ed927a0198ce6957145555f0 100644 (file)
@@ -35,22 +35,16 @@ pub(super) fn eval_terminator(
 
             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 @@ pub(super) fn eval_terminator(
                 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 @@ fn eval_fn_call(
                         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 @@ fn eval_fn_call(
                                 )?;
                             },
                             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 @@ fn eval_fn_call(
         }
     }
 
-    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);