use rustc_macros::HashStable;
use rustc_middle::mir;
use rustc_middle::mir::interpret::{InterpError, InvalidProgramInfo};
-use rustc_middle::ty::layout::{self, LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
+use rustc_middle::ty::layout::{
+ self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOf, LayoutOfHelpers,
+ TyAndLayout,
+};
use rustc_middle::ty::{
self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable,
};
use rustc_query_system::ich::StableHashingContext;
use rustc_session::Limit;
use rustc_span::{Pos, Span};
-use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout};
+use rustc_target::abi::{call::FnAbi, Align, HasDataLayout, Size, TargetDataLayout};
use super::{
AllocId, GlobalId, Immediate, InterpErrorInfo, InterpResult, MPlaceTy, Machine, MemPlace,
/// `ret` stores the block we jump to on a normal return, while `unwind`
/// stores the block used for cleanup during unwinding.
Goto { ret: Option<mir::BasicBlock>, unwind: StackPopUnwind },
- /// Just do nothing: Used by Main and for the `box_alloc` hook in miri.
+ /// The root frame of the stack: nowhere else to jump to.
/// `cleanup` says whether locals are deallocated. Static computation
/// wants them leaked to intern what they need (and just throw away
/// the entire `ecx` when it is done).
- None { cleanup: bool },
+ Root { cleanup: bool },
}
/// State of a local variable including a memoized layout
}
}
+impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> FnAbiOfHelpers<'tcx> for InterpCx<'mir, 'tcx, M> {
+ type FnAbiOfResult = InterpResult<'tcx, &'tcx FnAbi<'tcx, Ty<'tcx>>>;
+
+ fn handle_fn_abi_err(
+ &self,
+ err: FnAbiError<'tcx>,
+ _span: Span,
+ _fn_abi_request: FnAbiRequest<'tcx>,
+ ) -> InterpErrorInfo<'tcx> {
+ match err {
+ FnAbiError::Layout(err) => err_inval!(Layout(err)).into(),
+ FnAbiError::AdjustForForeignAbi(err) => {
+ err_inval!(FnAbiAdjustForForeignAbi(err)).into()
+ }
+ }
+ }
+}
+
/// Test if it is valid for a MIR assignment to assign `src`-typed place to `dest`-typed value.
/// This test should be symmetric, as it is primarily about layout compatibility.
pub(super) fn mir_assign_valid_types<'tcx>(
// because this is CTFE and the final value will be thoroughly validated anyway.
let cleanup = match return_to_block {
StackPopCleanup::Goto { .. } => true,
- StackPopCleanup::None { cleanup, .. } => cleanup,
+ StackPopCleanup::Root { cleanup, .. } => cleanup,
};
if !cleanup {
// Follow the unwind edge.
let unwind = match return_to_block {
StackPopCleanup::Goto { unwind, .. } => unwind,
- StackPopCleanup::None { .. } => {
- panic!("Encountered StackPopCleanup::None when unwinding!")
+ StackPopCleanup::Root { .. } => {
+ panic!("encountered StackPopCleanup::Root when unwinding!")
}
};
self.unwind_to_block(unwind)
// Follow the normal return edge.
match return_to_block {
StackPopCleanup::Goto { ret, .. } => self.return_to_block(ret),
- StackPopCleanup::None { .. } => Ok(()),
+ StackPopCleanup::Root { .. } => {
+ assert!(
+ self.stack().is_empty(),
+ "only the topmost frame can have StackPopCleanup::Root"
+ );
+ Ok(())
+ }
}
}
}