#[cfg_attr(feature = "portable-dispatch", path = "backend/loop.rs")]
#[cfg_attr(not(feature = "portable-dispatch"), path = "backend/tail.rs")]
#[macro_use]
pub mod backend;
pub use self::backend::{Done, Handler, execute_until_done, op_code_to_handler};
use super::state::Ip;
use crate::{
Error,
TrapCode,
engine::{ResumableHostTrapError, ResumableOutOfFuelError},
};
use core::ops::ControlFlow;
#[inline(always)]
pub fn control_break<T>() -> Control<T> {
Control::Break(Break::WithReason)
}
#[allow(unused)]
#[inline(always)]
fn decode_op_code(ip: Ip) -> crate::ir::OpCode {
let (_, op_code) = unsafe { ip.decode::<crate::ir::OpCode>() };
op_code
}
#[allow(unused)]
#[inline(always)]
fn decode_handler(ip: Ip) -> Handler {
use core::{mem, ptr};
let (_, addr) = unsafe { ip.decode::<usize>() };
unsafe { mem::transmute::<*const (), Handler>(ptr::with_exposed_provenance(addr)) }
}
#[derive(Debug)]
pub enum ExecutionOutcome {
Host(ResumableHostTrapError),
OutOfFuel(ResumableOutOfFuelError),
Error(Error),
}
impl From<ExecutionOutcome> for Error {
fn from(error: ExecutionOutcome) -> Self {
match error {
ExecutionOutcome::Host(error) => error.into(),
ExecutionOutcome::OutOfFuel(error) => error.into(),
ExecutionOutcome::Error(error) => error,
}
}
}
impl From<ResumableHostTrapError> for ExecutionOutcome {
#[cold]
#[inline]
fn from(error: ResumableHostTrapError) -> Self {
Self::Host(error)
}
}
impl From<ResumableOutOfFuelError> for ExecutionOutcome {
#[cold]
#[inline]
fn from(error: ResumableOutOfFuelError) -> Self {
Self::OutOfFuel(error)
}
}
impl From<TrapCode> for ExecutionOutcome {
#[cold]
#[inline]
fn from(error: TrapCode) -> Self {
Self::Error(error.into())
}
}
impl From<Error> for ExecutionOutcome {
#[cold]
#[inline]
fn from(error: Error) -> Self {
Self::Error(error)
}
}
impl ExecutionOutcome {
#[inline]
pub fn into_non_resumable(self) -> Error {
match self {
Self::Host(error) => error.into_error(),
Self::OutOfFuel(_error) => Error::from(TrapCode::OutOfFuel),
Self::Error(error) => error,
}
}
}
#[derive(Debug, Copy, Clone)]
pub enum Break {
UnreachableCodeReached = TrapCode::UnreachableCodeReached as _,
MemoryOutOfBounds = TrapCode::MemoryOutOfBounds as _,
TableOutOfBounds = TrapCode::TableOutOfBounds as _,
IndirectCallToNull = TrapCode::IndirectCallToNull as _,
IntegerDivisionByZero = TrapCode::IntegerDivisionByZero as _,
IntegerOverflow = TrapCode::IntegerOverflow as _,
BadConversionToInteger = TrapCode::BadConversionToInteger as _,
StackOverflow = TrapCode::StackOverflow as _,
BadSignature = TrapCode::BadSignature as _,
OutOfFuel = TrapCode::OutOfFuel as _,
GrowthOperationLimited = TrapCode::GrowthOperationLimited as _,
OutOfSystemMemory = TrapCode::OutOfSystemMemory as _,
WithReason,
}
impl From<TrapCode> for Break {
#[inline]
fn from(trap_code: TrapCode) -> Self {
match trap_code {
TrapCode::UnreachableCodeReached => Self::UnreachableCodeReached,
TrapCode::MemoryOutOfBounds => Self::MemoryOutOfBounds,
TrapCode::TableOutOfBounds => Self::TableOutOfBounds,
TrapCode::IndirectCallToNull => Self::IndirectCallToNull,
TrapCode::IntegerDivisionByZero => Self::IntegerDivisionByZero,
TrapCode::IntegerOverflow => Self::IntegerOverflow,
TrapCode::BadConversionToInteger => Self::BadConversionToInteger,
TrapCode::StackOverflow => Self::StackOverflow,
TrapCode::BadSignature => Self::BadSignature,
TrapCode::OutOfFuel => Self::OutOfFuel,
TrapCode::GrowthOperationLimited => Self::GrowthOperationLimited,
TrapCode::OutOfSystemMemory => Self::OutOfSystemMemory,
}
}
}
impl Break {
#[inline]
pub fn trap_code(self) -> Option<TrapCode> {
let trap_code = match self {
Self::UnreachableCodeReached => TrapCode::UnreachableCodeReached,
Self::MemoryOutOfBounds => TrapCode::MemoryOutOfBounds,
Self::TableOutOfBounds => TrapCode::TableOutOfBounds,
Self::IndirectCallToNull => TrapCode::IndirectCallToNull,
Self::IntegerDivisionByZero => TrapCode::IntegerDivisionByZero,
Self::IntegerOverflow => TrapCode::IntegerOverflow,
Self::BadConversionToInteger => TrapCode::BadConversionToInteger,
Self::StackOverflow => TrapCode::StackOverflow,
Self::BadSignature => TrapCode::BadSignature,
Self::OutOfFuel => TrapCode::OutOfFuel,
Self::GrowthOperationLimited => TrapCode::GrowthOperationLimited,
Self::OutOfSystemMemory => TrapCode::OutOfSystemMemory,
_ => return None,
};
Some(trap_code)
}
}
pub type Control<C = (), B = Break> = ControlFlow<B, C>;