]> git.lizzy.rs Git - rust.git/blobdiff - src/eval.rs
Add communicate field to evaluator and fix formatting
[rust.git] / src / eval.rs
index a1157af0e39b6d3103d5baf373a72f269167da8d..e80162ec1796dc40a20f9b4aa12398df2c2be85a 100644 (file)
@@ -1,3 +1,5 @@
+//! Main evaluator loop and setting up the initial stack frame.
+
 use rand::rngs::StdRng;
 use rand::SeedableRng;
 
@@ -5,22 +7,23 @@
 use rustc::ty::{self, TyCtxt};
 use rustc::ty::layout::{LayoutOf, Size, Align};
 use rustc::hir::def_id::DefId;
-use rustc::mir;
 
 use crate::{
-    InterpResult, InterpError, InterpretCx, StackPopCleanup, struct_error,
-    Scalar, Tag, Pointer,
-    MemoryExtra, MiriMemoryKind, Evaluator, TlsEvalContextExt,
+    InterpResult, InterpError, InterpCx, StackPopCleanup, struct_error,
+    Scalar, Tag, Pointer, FnVal,
+    MemoryExtra, MiriMemoryKind, Evaluator, TlsEvalContextExt, HelpersEvalContextExt,
 };
 
 /// Configuration needed to spawn a Miri instance.
 #[derive(Clone)]
 pub struct MiriConfig {
     pub validate: bool,
+    /// Determines if communication with the host environment is enabled.
+    pub communicate: bool,
     pub args: Vec<String>,
 
-    // The seed to use when non-determinism is required (e.g. getrandom())
-    pub seed: Option<u64>
+    /// The seed to use when non-determinism is required (e.g. getrandom())
+    pub seed: Option<u64>,
 }
 
 // Used by priroda.
@@ -28,24 +31,21 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
     tcx: TyCtxt<'tcx>,
     main_id: DefId,
     config: MiriConfig,
-) -> InterpResult<'tcx, InterpretCx<'mir, 'tcx, Evaluator<'tcx>>> {
-    let mut ecx = InterpretCx::new(
+) -> InterpResult<'tcx, InterpCx<'mir, 'tcx, Evaluator<'tcx>>> {
+    let mut ecx = InterpCx::new(
         tcx.at(syntax::source_map::DUMMY_SP),
         ty::ParamEnv::reveal_all(),
-        Evaluator::new(),
+        Evaluator::new(config.communicate),
+        MemoryExtra::new(StdRng::seed_from_u64(config.seed.unwrap_or(0)), config.validate),
     );
 
-    // FIXME: InterpretCx::new should take an initial MemoryExtra
-    ecx.memory_mut().extra = MemoryExtra::new(config.seed.map(StdRng::seed_from_u64), config.validate);
-    
     let main_instance = ty::Instance::mono(ecx.tcx.tcx, main_id);
     let main_mir = ecx.load_mir(main_instance.def)?;
 
     if !main_mir.return_ty().is_unit() || main_mir.arg_count != 0 {
-        return err!(Unimplemented(
+        throw_unsup_format!(
             "miri does not support main functions without `fn()` type signatures"
-                .to_owned(),
-        ));
+        );
     }
 
     let start_id = tcx.lang_items().start_fn().unwrap();
@@ -61,10 +61,10 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
     let start_mir = ecx.load_mir(start_instance.def)?;
 
     if start_mir.arg_count != 3 {
-        return err!(AbiViolation(format!(
+        bug!(
             "'start' lang item should have three arguments, but has {}",
             start_mir.arg_count
-        )));
+        );
     }
 
     // Return value (in static memory so that it does not count as leak).
@@ -84,12 +84,12 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
     let mut args = ecx.frame().body.args_iter();
 
     // First argument: pointer to `main()`.
-    let main_ptr = ecx.memory_mut().create_fn_alloc(main_instance);
-    let dest = ecx.eval_place(&mir::Place::Base(mir::PlaceBase::Local(args.next().unwrap())))?;
+    let main_ptr = ecx.memory_mut().create_fn_alloc(FnVal::Instance(main_instance));
+    let dest = ecx.local_place(args.next().unwrap())?;
     ecx.write_scalar(Scalar::Ptr(main_ptr), dest)?;
 
     // Second argument (argc): `1`.
-    let dest = ecx.eval_place(&mir::Place::Base(mir::PlaceBase::Local(args.next().unwrap())))?;
+    let dest = ecx.local_place(args.next().unwrap())?;
     let argc = Scalar::from_uint(config.args.len() as u128, dest.layout.size);
     ecx.write_scalar(argc, dest)?;
     // Store argc for macOS's `_NSGetArgc`.
@@ -99,9 +99,8 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
         ecx.machine.argc = Some(argc_place.ptr.to_ptr()?);
     }
 
-    // FIXME: extract main source file path.
     // Third argument (`argv`): created from `config.args`.
-    let dest = ecx.eval_place(&mir::Place::Base(mir::PlaceBase::Local(args.next().unwrap())))?;
+    let dest = ecx.local_place(args.next().unwrap())?;
     // For Windows, construct a command string with all the aguments.
     let mut cmd = String::new();
     for arg in config.args.iter() {
@@ -127,7 +126,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
         let place = ecx.mplace_field(argvs_place, idx as u64)?;
         ecx.write_scalar(Scalar::Ptr(arg), place.into())?;
     }
-    ecx.memory_mut().mark_immutable(argvs_place.to_ptr()?.alloc_id)?;
+    ecx.memory_mut().mark_immutable(argvs_place.ptr.assert_ptr().alloc_id)?;
     // Write a pointer to that place as the argument.
     let argv = argvs_place.ptr;
     ecx.write_scalar(argv, dest)?;
@@ -161,7 +160,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
             cur_ptr = cur_ptr.offset(char_size, tcx)?;
         }
     }
+
     assert!(args.next().is_none(), "start lang item has more arguments than expected");
 
     Ok(ecx)
@@ -181,7 +180,7 @@ pub fn eval_main<'tcx>(
     };
 
     // Perform the main execution.
-    let res: InterpResult = (|| {
+    let res: InterpResult<'_> = (|| {
         ecx.run()?;
         ecx.run_tls_dtors()
     })();
@@ -202,7 +201,7 @@ pub fn eval_main<'tcx>(
             // Special treatment for some error kinds
             let msg = match e.kind {
                 InterpError::Exit(code) => std::process::exit(code),
-                InterpError::NoMirFor(..) =>
+                err_unsup!(NoMirFor(..)) =>
                     format!("{}. Did you set `MIRI_SYSROOT` to a Miri-enabled sysroot? You can prepare one with `cargo miri setup`.", e),
                 _ => e.to_string()
             };