2024-03-20 17:45:14 +00:00
|
|
|
use rustc_middle::mir::interpret::{AllocId, ConstAllocation, InterpResult};
|
|
|
|
|
use rustc_middle::mir::*;
|
|
|
|
|
use rustc_middle::query::TyCtxtAt;
|
2024-11-16 09:04:30 +00:00
|
|
|
use rustc_middle::ty::Ty;
|
2024-03-20 17:45:14 +00:00
|
|
|
use rustc_middle::ty::layout::TyAndLayout;
|
2024-05-08 19:03:14 +10:00
|
|
|
use rustc_middle::{bug, span_bug, ty};
|
2024-03-20 17:45:14 +00:00
|
|
|
use rustc_span::def_id::DefId;
|
2024-11-16 09:04:30 +00:00
|
|
|
use rustc_target::callconv::FnAbi;
|
2024-03-20 17:45:14 +00:00
|
|
|
|
2024-05-08 19:03:14 +10:00
|
|
|
use crate::interpret::{
|
2024-09-29 11:53:23 +02:00
|
|
|
self, HasStaticRootDefId, ImmTy, Immediate, InterpCx, PointerArithmetic, interp_ok,
|
|
|
|
|
throw_machine_stop,
|
2024-07-29 08:13:50 +10:00
|
|
|
};
|
|
|
|
|
|
2024-03-20 17:45:14 +00:00
|
|
|
/// Macro for machine-specific `InterpError` without allocation.
|
|
|
|
|
/// (These will never be shown to the user, but they help diagnose ICEs.)
|
|
|
|
|
pub macro throw_machine_stop_str($($tt:tt)*) {{
|
|
|
|
|
// We make a new local type for it. The type itself does not carry any information,
|
|
|
|
|
// but its vtable (for the `MachineStopType` trait) does.
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
struct Zst;
|
|
|
|
|
// Printing this type shows the desired string.
|
|
|
|
|
impl std::fmt::Display for Zst {
|
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
|
write!(f, $($tt)*)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl rustc_middle::mir::interpret::MachineStopType for Zst {
|
|
|
|
|
fn diagnostic_message(&self) -> rustc_errors::DiagMessage {
|
|
|
|
|
self.to_string().into()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn add_args(
|
|
|
|
|
self: Box<Self>,
|
|
|
|
|
_: &mut dyn FnMut(rustc_errors::DiagArgName, rustc_errors::DiagArgValue),
|
|
|
|
|
) {}
|
|
|
|
|
}
|
|
|
|
|
throw_machine_stop!(Zst)
|
|
|
|
|
}}
|
|
|
|
|
|
|
|
|
|
pub struct DummyMachine;
|
|
|
|
|
|
|
|
|
|
impl HasStaticRootDefId for DummyMachine {
|
|
|
|
|
fn static_def_id(&self) -> Option<rustc_hir::def_id::LocalDefId> {
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-27 08:24:23 +02:00
|
|
|
impl<'tcx> interpret::Machine<'tcx> for DummyMachine {
|
|
|
|
|
interpret::compile_time_machine!(<'tcx>);
|
2024-03-20 17:45:14 +00:00
|
|
|
type MemoryKind = !;
|
|
|
|
|
const PANIC_ON_ALLOC_FAIL: bool = true;
|
|
|
|
|
|
2024-03-21 13:53:00 +01:00
|
|
|
// We want to just eval random consts in the program, so `eval_mir_const` can fail.
|
|
|
|
|
const ALL_CONSTS_ARE_PRECHECKED: bool = false;
|
2024-03-14 07:28:25 +01:00
|
|
|
|
2024-03-20 17:45:14 +00:00
|
|
|
#[inline(always)]
|
2024-05-27 08:24:23 +02:00
|
|
|
fn enforce_alignment(_ecx: &InterpCx<'tcx, Self>) -> bool {
|
2024-03-20 17:45:14 +00:00
|
|
|
false // no reason to enforce alignment
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-27 08:24:23 +02:00
|
|
|
fn enforce_validity(_ecx: &InterpCx<'tcx, Self>, _layout: TyAndLayout<'tcx>) -> bool {
|
2024-03-20 17:45:14 +00:00
|
|
|
false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn before_access_global(
|
|
|
|
|
_tcx: TyCtxtAt<'tcx>,
|
|
|
|
|
_machine: &Self,
|
|
|
|
|
_alloc_id: AllocId,
|
|
|
|
|
alloc: ConstAllocation<'tcx>,
|
|
|
|
|
_static_def_id: Option<DefId>,
|
|
|
|
|
is_write: bool,
|
|
|
|
|
) -> InterpResult<'tcx> {
|
|
|
|
|
if is_write {
|
|
|
|
|
throw_machine_stop_str!("can't write to global");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If the static allocation is mutable, then we can't const prop it as its content
|
|
|
|
|
// might be different at runtime.
|
|
|
|
|
if alloc.inner().mutability.is_mut() {
|
|
|
|
|
throw_machine_stop_str!("can't access mutable globals in ConstProp");
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-29 11:53:23 +02:00
|
|
|
interp_ok(())
|
2024-03-20 17:45:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn find_mir_or_eval_fn(
|
2024-05-27 08:24:23 +02:00
|
|
|
_ecx: &mut InterpCx<'tcx, Self>,
|
2024-03-20 17:45:14 +00:00
|
|
|
_instance: ty::Instance<'tcx>,
|
2024-11-16 09:04:30 +00:00
|
|
|
_abi: &FnAbi<'tcx, Ty<'tcx>>,
|
2024-03-20 17:45:14 +00:00
|
|
|
_args: &[interpret::FnArg<'tcx, Self::Provenance>],
|
|
|
|
|
_destination: &interpret::MPlaceTy<'tcx, Self::Provenance>,
|
|
|
|
|
_target: Option<BasicBlock>,
|
|
|
|
|
_unwind: UnwindAction,
|
2024-05-26 20:20:43 +02:00
|
|
|
) -> interpret::InterpResult<'tcx, Option<(&'tcx Body<'tcx>, ty::Instance<'tcx>)>> {
|
2024-03-20 17:45:14 +00:00
|
|
|
unimplemented!()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn panic_nounwind(
|
2024-05-27 08:24:23 +02:00
|
|
|
_ecx: &mut InterpCx<'tcx, Self>,
|
2024-03-20 17:45:14 +00:00
|
|
|
_msg: &str,
|
|
|
|
|
) -> interpret::InterpResult<'tcx> {
|
|
|
|
|
unimplemented!()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn call_intrinsic(
|
2024-05-27 08:24:23 +02:00
|
|
|
_ecx: &mut InterpCx<'tcx, Self>,
|
2024-03-20 17:45:14 +00:00
|
|
|
_instance: ty::Instance<'tcx>,
|
|
|
|
|
_args: &[interpret::OpTy<'tcx, Self::Provenance>],
|
|
|
|
|
_destination: &interpret::MPlaceTy<'tcx, Self::Provenance>,
|
|
|
|
|
_target: Option<BasicBlock>,
|
|
|
|
|
_unwind: UnwindAction,
|
2024-04-23 13:12:17 +00:00
|
|
|
) -> interpret::InterpResult<'tcx, Option<ty::Instance<'tcx>>> {
|
2024-03-20 17:45:14 +00:00
|
|
|
unimplemented!()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn assert_panic(
|
2024-05-27 08:24:23 +02:00
|
|
|
_ecx: &mut InterpCx<'tcx, Self>,
|
2024-03-20 17:45:14 +00:00
|
|
|
_msg: &rustc_middle::mir::AssertMessage<'tcx>,
|
|
|
|
|
_unwind: UnwindAction,
|
|
|
|
|
) -> interpret::InterpResult<'tcx> {
|
|
|
|
|
unimplemented!()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn binary_ptr_op(
|
2024-05-27 08:24:23 +02:00
|
|
|
ecx: &InterpCx<'tcx, Self>,
|
2024-03-20 17:45:14 +00:00
|
|
|
bin_op: BinOp,
|
|
|
|
|
left: &interpret::ImmTy<'tcx, Self::Provenance>,
|
|
|
|
|
right: &interpret::ImmTy<'tcx, Self::Provenance>,
|
2024-05-21 12:17:34 +02:00
|
|
|
) -> interpret::InterpResult<'tcx, ImmTy<'tcx, Self::Provenance>> {
|
2024-03-20 17:45:14 +00:00
|
|
|
use rustc_middle::mir::BinOp::*;
|
2024-09-29 11:53:23 +02:00
|
|
|
interp_ok(match bin_op {
|
2024-03-20 17:45:14 +00:00
|
|
|
Eq | Ne | Lt | Le | Gt | Ge => {
|
|
|
|
|
// Types can differ, e.g. fn ptrs with different `for`.
|
2024-10-29 13:37:26 -07:00
|
|
|
assert_eq!(left.layout.backend_repr, right.layout.backend_repr);
|
2024-03-20 17:45:14 +00:00
|
|
|
let size = ecx.pointer_size();
|
|
|
|
|
// Just compare the bits. ScalarPairs are compared lexicographically.
|
|
|
|
|
// We thus always compare pairs and simply fill scalars up with 0.
|
|
|
|
|
// If the pointer has provenance, `to_bits` will return `Err` and we bail out.
|
|
|
|
|
let left = match **left {
|
|
|
|
|
Immediate::Scalar(l) => (l.to_bits(size)?, 0),
|
|
|
|
|
Immediate::ScalarPair(l1, l2) => (l1.to_bits(size)?, l2.to_bits(size)?),
|
|
|
|
|
Immediate::Uninit => panic!("we should never see uninit data here"),
|
|
|
|
|
};
|
|
|
|
|
let right = match **right {
|
|
|
|
|
Immediate::Scalar(r) => (r.to_bits(size)?, 0),
|
|
|
|
|
Immediate::ScalarPair(r1, r2) => (r1.to_bits(size)?, r2.to_bits(size)?),
|
|
|
|
|
Immediate::Uninit => panic!("we should never see uninit data here"),
|
|
|
|
|
};
|
|
|
|
|
let res = match bin_op {
|
|
|
|
|
Eq => left == right,
|
|
|
|
|
Ne => left != right,
|
|
|
|
|
Lt => left < right,
|
|
|
|
|
Le => left <= right,
|
|
|
|
|
Gt => left > right,
|
|
|
|
|
Ge => left >= right,
|
|
|
|
|
_ => bug!(),
|
|
|
|
|
};
|
2024-05-21 12:17:34 +02:00
|
|
|
ImmTy::from_bool(res, *ecx.tcx)
|
2024-03-20 17:45:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Some more operations are possible with atomics.
|
|
|
|
|
// The return value always has the provenance of the *left* operand.
|
|
|
|
|
Add | Sub | BitOr | BitAnd | BitXor => {
|
|
|
|
|
throw_machine_stop_str!("pointer arithmetic is not handled")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_ => span_bug!(ecx.cur_span(), "Invalid operator on pointers: {:?}", bin_op),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-30 20:29:05 +02:00
|
|
|
fn expose_provenance(
|
|
|
|
|
_ecx: &InterpCx<'tcx, Self>,
|
|
|
|
|
_provenance: Self::Provenance,
|
2024-03-20 17:45:14 +00:00
|
|
|
) -> interpret::InterpResult<'tcx> {
|
|
|
|
|
unimplemented!()
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-27 23:28:32 +02:00
|
|
|
fn init_frame(
|
2024-05-27 08:24:23 +02:00
|
|
|
_ecx: &mut InterpCx<'tcx, Self>,
|
2024-05-26 20:20:43 +02:00
|
|
|
_frame: interpret::Frame<'tcx, Self::Provenance>,
|
2024-05-27 08:24:23 +02:00
|
|
|
) -> interpret::InterpResult<'tcx, interpret::Frame<'tcx, Self::Provenance, Self::FrameExtra>>
|
|
|
|
|
{
|
2024-03-20 17:45:14 +00:00
|
|
|
unimplemented!()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn stack<'a>(
|
2024-05-27 08:24:23 +02:00
|
|
|
_ecx: &'a InterpCx<'tcx, Self>,
|
2024-05-26 20:20:43 +02:00
|
|
|
) -> &'a [interpret::Frame<'tcx, Self::Provenance, Self::FrameExtra>] {
|
2024-03-20 17:45:14 +00:00
|
|
|
// Return an empty stack instead of panicking, as `cur_span` uses it to evaluate constants.
|
|
|
|
|
&[]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn stack_mut<'a>(
|
2024-05-27 08:24:23 +02:00
|
|
|
_ecx: &'a mut InterpCx<'tcx, Self>,
|
2024-05-26 20:20:43 +02:00
|
|
|
) -> &'a mut Vec<interpret::Frame<'tcx, Self::Provenance, Self::FrameExtra>> {
|
2024-03-20 17:45:14 +00:00
|
|
|
unimplemented!()
|
|
|
|
|
}
|
|
|
|
|
}
|