1use rustc_abi::ExternAbi;
4use rustc_middle::{mir, ty};
5
6use crate::*;
7
8impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
9pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
10    fn start_panic(&mut self, msg: &str, unwind: mir::UnwindAction) -> InterpResult<'tcx> {
12        let this = self.eval_context_mut();
13
14        let msg = this.allocate_str_dedup(msg)?;
16
17        let panic = this.tcx.lang_items().panic_fn().unwrap();
19        let panic = ty::Instance::mono(this.tcx.tcx, panic);
20        this.call_function(
21            panic,
22            ExternAbi::Rust,
23            &[this.mplace_to_ref(&msg)?],
24            None,
25            ReturnContinuation::Goto { ret: None, unwind },
26        )
27    }
28
29    fn start_panic_nounwind(&mut self, msg: &str) -> InterpResult<'tcx> {
31        let this = self.eval_context_mut();
32
33        let msg = this.allocate_str_dedup(msg)?;
35
36        let panic = this.tcx.lang_items().panic_nounwind().unwrap();
38        let panic = ty::Instance::mono(this.tcx.tcx, panic);
39        this.call_function(
40            panic,
41            ExternAbi::Rust,
42            &[this.mplace_to_ref(&msg)?],
43            None,
44            ReturnContinuation::Goto { ret: None, unwind: mir::UnwindAction::Unreachable },
45        )
46    }
47
48    fn assert_panic(
49        &mut self,
50        msg: &mir::AssertMessage<'tcx>,
51        unwind: mir::UnwindAction,
52    ) -> InterpResult<'tcx> {
53        use rustc_middle::mir::AssertKind::*;
54        let this = self.eval_context_mut();
55
56        match msg {
57            BoundsCheck { index, len } => {
58                let index = this.read_immediate(&this.eval_operand(index, None)?)?;
62                let len = this.read_immediate(&this.eval_operand(len, None)?)?;
64
65                let panic_bounds_check = this.tcx.lang_items().panic_bounds_check_fn().unwrap();
67                let panic_bounds_check = ty::Instance::mono(this.tcx.tcx, panic_bounds_check);
68                this.call_function(
69                    panic_bounds_check,
70                    ExternAbi::Rust,
71                    &[index, len],
72                    None,
73                    ReturnContinuation::Goto { ret: None, unwind },
74                )?;
75            }
76            MisalignedPointerDereference { required, found } => {
77                let required = this.read_immediate(&this.eval_operand(required, None)?)?;
81                let found = this.read_immediate(&this.eval_operand(found, None)?)?;
83
84                let panic_misaligned_pointer_dereference =
86                    this.tcx.lang_items().panic_misaligned_pointer_dereference_fn().unwrap();
87                let panic_misaligned_pointer_dereference =
88                    ty::Instance::mono(this.tcx.tcx, panic_misaligned_pointer_dereference);
89                this.call_function(
90                    panic_misaligned_pointer_dereference,
91                    ExternAbi::Rust,
92                    &[required, found],
93                    None,
94                    ReturnContinuation::Goto { ret: None, unwind },
95                )?;
96            }
97
98            _ => {
99                let fn_item = this.tcx.require_lang_item(msg.panic_function(), this.tcx.span);
101                let instance = ty::Instance::mono(this.tcx.tcx, fn_item);
102                this.call_function(
103                    instance,
104                    ExternAbi::Rust,
105                    &[],
106                    None,
107                    ReturnContinuation::Goto { ret: None, unwind },
108                )?;
109            }
110        }
111        interp_ok(())
112    }
113}