]> git.lizzy.rs Git - rust.git/blobdiff - src/shims/panic.rs
Add getpid shim
[rust.git] / src / shims / panic.rs
index abc7aa2ad1bdc64f08edaf269f2ab6631ffc6fce..ed6e72591dd002e331b3ab45193573854486dfc4 100644 (file)
 
 use log::trace;
 
+use rustc_ast::Mutability;
 use rustc_middle::{mir, ty};
+use rustc_span::Symbol;
+use rustc_target::spec::abi::Abi;
 use rustc_target::spec::PanicStrategy;
 
 use crate::*;
@@ -38,28 +41,25 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
     /// by libpanic_unwind to delegate the actual unwinding process to Miri.
     fn handle_miri_start_panic(
         &mut self,
+        abi: Abi,
+        link_name: Symbol,
         args: &[OpTy<'tcx, Tag>],
-        unwind: Option<mir::BasicBlock>,
+        unwind: StackPopUnwind,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
         trace!("miri_start_panic: {:?}", this.frame().instance);
-        // Make sure we only start unwinding when this matches our panic strategy.
-        assert_eq!(this.tcx.sess.panic_strategy(), PanicStrategy::Unwind);
 
         // Get the raw pointer stored in arg[0] (the panic payload).
-        let &[ref payload] = check_arg_count(args)?;
+        let [payload] = this.check_shim(abi, Abi::Rust, link_name, args)?;
         let payload = this.read_scalar(payload)?.check_init()?;
         let thread = this.active_thread_mut();
-        assert!(
-            thread.panic_payload.is_none(),
-            "the panic runtime should avoid double-panics"
-        );
+        assert!(thread.panic_payload.is_none(), "the panic runtime should avoid double-panics");
         thread.panic_payload = Some(payload);
 
         // Jump to the unwind block to begin unwinding.
-        this.unwind_to_block(unwind);
-        return Ok(());
+        this.unwind_to_block(unwind)?;
+        Ok(())
     }
 
     /// Handles the `try` intrinsic, the underlying implementation of `std::panicking::try`.
@@ -83,21 +83,22 @@ fn handle_try(
         // a pointer to `Box<dyn Any + Send + 'static>`.
 
         // Get all the arguments.
-        let &[ref try_fn, ref data, ref catch_fn] = check_arg_count(args)?;
-        let try_fn = this.read_scalar(try_fn)?.check_init()?;
+        let [try_fn, data, catch_fn] = check_arg_count(args)?;
+        let try_fn = this.read_pointer(try_fn)?;
         let data = this.read_scalar(data)?.check_init()?;
         let catch_fn = this.read_scalar(catch_fn)?.check_init()?;
 
         // Now we make a function call, and pass `data` as first and only argument.
-        let f_instance = this.memory.get_fn(try_fn)?.as_instance()?;
+        let f_instance = this.get_ptr_fn(try_fn)?.as_instance()?;
         trace!("try_fn: {:?}", f_instance);
-        let ret_place = MPlaceTy::dangling(this.machine.layouts.unit, this).into();
+        let ret_place = MPlaceTy::dangling(this.machine.layouts.unit).into();
         this.call_function(
             f_instance,
+            Abi::Rust,
             &[data.into()],
-            Some(&ret_place),
+            &ret_place,
             // Directly return to caller.
-            StackPopCleanup::Goto { ret: Some(ret), unwind: None },
+            StackPopCleanup::Goto { ret: Some(ret), unwind: StackPopUnwind::Skip },
         )?;
 
         // We ourselves will return `0`, eventually (will be overwritten if we catch a panic).
@@ -107,10 +108,11 @@ fn handle_try(
         // This lets `handle_stack_pop` (below) know that we should stop unwinding
         // when we pop this frame.
         if this.tcx.sess.panic_strategy() == PanicStrategy::Unwind {
-            this.frame_mut().extra.catch_unwind = Some(CatchUnwindData { catch_fn, data, dest: *dest, ret });
+            this.frame_mut().extra.catch_unwind =
+                Some(CatchUnwindData { catch_fn, data, dest: *dest, ret });
         }
 
-        return Ok(());
+        Ok(())
     }
 
     fn handle_stack_pop(
@@ -121,7 +123,7 @@ fn handle_stack_pop(
         let this = self.eval_context_mut();
 
         trace!("handle_stack_pop(extra = {:?}, unwinding = {})", extra, unwinding);
-        if let Some(stacked_borrows) = &this.memory.extra.stacked_borrows {
+        if let Some(stacked_borrows) = &this.machine.stacked_borrows {
             stacked_borrows.borrow_mut().end_call(extra.call_id);
         }
 
@@ -130,7 +132,10 @@ fn handle_stack_pop(
         if let (true, Some(catch_unwind)) = (unwinding, extra.catch_unwind.take()) {
             // We've just popped a frame that was pushed by `try`,
             // and we are unwinding, so we should catch that.
-            trace!("unwinding: found catch_panic frame during unwinding: {:?}", this.frame().instance);
+            trace!(
+                "unwinding: found catch_panic frame during unwinding: {:?}",
+                this.frame().instance
+            );
 
             // We set the return value of `try` to 1, since there was a panic.
             this.write_scalar(Scalar::from_i32(1), &catch_unwind.dest)?;
@@ -140,15 +145,17 @@ fn handle_stack_pop(
             let payload = this.active_thread_mut().panic_payload.take().unwrap();
 
             // Push the `catch_fn` stackframe.
-            let f_instance = this.memory.get_fn(catch_unwind.catch_fn)?.as_instance()?;
+            let f_instance =
+                this.get_ptr_fn(this.scalar_to_ptr(catch_unwind.catch_fn)?)?.as_instance()?;
             trace!("catch_fn: {:?}", f_instance);
-            let ret_place = MPlaceTy::dangling(this.machine.layouts.unit, this).into();
+            let ret_place = MPlaceTy::dangling(this.machine.layouts.unit).into();
             this.call_function(
                 f_instance,
+                Abi::Rust,
                 &[catch_unwind.data.into(), payload.into()],
-                Some(&ret_place),
+                &ret_place,
                 // Directly return to caller of `try`.
-                StackPopCleanup::Goto { ret: Some(catch_unwind.ret), unwind: None },
+                StackPopCleanup::Goto { ret: Some(catch_unwind.ret), unwind: StackPopUnwind::Skip },
             )?;
 
             // We pushed a new stack frame, the engine should not do any jumping now!
@@ -158,24 +165,21 @@ fn handle_stack_pop(
         }
     }
 
-    /// Starta a panic in the interpreter with the given message as payload.
-    fn start_panic(
-        &mut self,
-        msg: &str,
-        unwind: Option<mir::BasicBlock>,
-    ) -> InterpResult<'tcx> {
+    /// Start a panic in the interpreter with the given message as payload.
+    fn start_panic(&mut self, msg: &str, unwind: StackPopUnwind) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
         // First arg: message.
-        let msg = this.allocate_str(msg, MiriMemoryKind::Machine.into());
+        let msg = this.allocate_str(msg, MiriMemoryKind::Machine.into(), Mutability::Not);
 
         // Call the lang item.
         let panic = this.tcx.lang_items().panic_fn().unwrap();
         let panic = ty::Instance::mono(this.tcx.tcx, panic);
         this.call_function(
             panic,
-            &[msg.to_ref()],
-            None,
+            Abi::Rust,
+            &[msg.to_ref(this)],
+            &MPlaceTy::dangling(this.machine.layouts.unit).into(),
             StackPopCleanup::Goto { ret: None, unwind },
         )
     }
@@ -202,14 +206,27 @@ fn assert_panic(
                 let panic_bounds_check = ty::Instance::mono(this.tcx.tcx, panic_bounds_check);
                 this.call_function(
                     panic_bounds_check,
+                    Abi::Rust,
                     &[index.into(), len.into()],
-                    None,
-                    StackPopCleanup::Goto { ret: None, unwind },
+                    &MPlaceTy::dangling(this.machine.layouts.unit).into(),
+                    StackPopCleanup::Goto {
+                        ret: None,
+                        unwind: match unwind {
+                            Some(cleanup) => StackPopUnwind::Cleanup(cleanup),
+                            None => StackPopUnwind::Skip,
+                        },
+                    },
                 )?;
             }
             _ => {
                 // Forward everything else to `panic` lang item.
-                this.start_panic(msg.description(), unwind)?;
+                this.start_panic(
+                    msg.description(),
+                    match unwind {
+                        Some(cleanup) => StackPopUnwind::Cleanup(cleanup),
+                        None => StackPopUnwind::Skip,
+                    },
+                )?;
             }
         }
         Ok(())