Skip to content

Commit

Permalink
Merge branch 'main' into rf-update-wasi-dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
Robbepop committed Aug 20, 2024
2 parents aef0a96 + 79996af commit ebb70f1
Show file tree
Hide file tree
Showing 18 changed files with 382 additions and 28 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,11 @@ jobs:
run: rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-gnu
- name: Build Tests
env:
RUSTFLAGS: "--cfg debug_assertions -Zsanitizer=address"
RUSTFLAGS: "-C debug-assertions -Zsanitizer=address"
run: cargo build --tests --workspace --locked -Zbuild-std --target x86_64-unknown-linux-gnu --verbose
- name: Test
env:
RUSTFLAGS: "--cfg debug_assertions -Zsanitizer=address"
RUSTFLAGS: "-C debug-assertions -Zsanitizer=address"
run: cargo test --workspace --locked --tests -Zbuild-std --target x86_64-unknown-linux-gnu

test:
Expand Down
5 changes: 0 additions & 5 deletions crates/core/src/untyped.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1135,11 +1135,6 @@ impl UntypedVal {
self.execute_unary(<i32 as ExtendInto<i64>>::extend_into)
}

/// Execute `i64.extend_i32_u` Wasm operation.
pub fn i64_extend_i32_u(self) -> Self {
self.execute_unary(<u32 as ExtendInto<i64>>::extend_into)
}

/// Execute `i64.trunc_f32_s` Wasm operation.
///
/// # Errors
Expand Down
2 changes: 0 additions & 2 deletions crates/wasmi/src/engine/bytecode/construct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1386,8 +1386,6 @@ constructor_for_unary_instrs! {
fn i64_extend32_s() -> Self::I64Extend32S;

fn i32_wrap_i64() -> Self::I32WrapI64;
fn i64_extend_i32_s() -> Self::I64ExtendI32S;
fn i64_extend_i32_u() -> Self::I64ExtendI32U;

fn f32_demote_f64() -> Self::F32DemoteF64;
fn f64_promote_f32() -> Self::F64PromoteF32;
Expand Down
4 changes: 0 additions & 4 deletions crates/wasmi/src/engine/bytecode/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2119,10 +2119,6 @@ pub enum Instruction {

/// Wasm `i32.wrap_i64` instruction.
I32WrapI64(UnaryInstr),
/// Wasm `i64.extend_i32_s` instruction.
I64ExtendI32S(UnaryInstr),
/// Wasm `i64.extend_i32_u` instruction.
I64ExtendI32U(UnaryInstr),

/// Wasm `i32.extend8_s` instruction.
///
Expand Down
2 changes: 0 additions & 2 deletions crates/wasmi/src/engine/executor/instrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -613,8 +613,6 @@ impl<'engine> Executor<'engine> {
Instr::I64RotrImm(instr) => self.execute_i64_rotr_imm(instr),
Instr::I64RotrImm16Rev(instr) => self.execute_i64_rotr_imm16_rev(instr),
Instr::I32WrapI64(instr) => self.execute_i32_wrap_i64(instr),
Instr::I64ExtendI32S(instr) => self.execute_i64_extend_i32_s(instr),
Instr::I64ExtendI32U(instr) => self.execute_i64_extend_i32_u(instr),
Instr::I32Extend8S(instr) => self.execute_i32_extend8_s(instr),
Instr::I32Extend16S(instr) => self.execute_i32_extend16_s(instr),
Instr::I64Extend8S(instr) => self.execute_i64_extend8_s(instr),
Expand Down
9 changes: 8 additions & 1 deletion crates/wasmi/src/engine/executor/instrs/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use crate::{
},
func::{FuncEntity, HostFuncEntity},
store::StoreInner,
CallHook,
Error,
Func,
FuncRef,
Expand Down Expand Up @@ -469,7 +470,13 @@ impl<'engine> Executor<'engine> {
Ok(())
}
FuncEntity::Host(host_func) => {
self.execute_host_func::<C, T>(store, results, func, *host_func)
let host_func = *host_func;

store.invoke_call_hook(CallHook::CallingHost)?;
self.execute_host_func::<C, T>(store, results, func, host_func)?;
store.invoke_call_hook(CallHook::ReturningFromHost)?;

Ok(())
}
}
}
Expand Down
2 changes: 0 additions & 2 deletions crates/wasmi/src/engine/executor/instrs/conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ macro_rules! impl_fallible_conversion_impls {
impl<'engine> Executor<'engine> {
impl_conversion_impls! {
(Instruction::I32WrapI64, execute_i32_wrap_i64, UntypedVal::i32_wrap_i64),
(Instruction::I64ExtendI32S, execute_i64_extend_i32_s, UntypedVal::i64_extend_i32_s),
(Instruction::I64ExtendI32U, execute_i64_extend_i32_u, UntypedVal::i64_extend_i32_u),

(Instruction::I32TruncSatF32S, execute_i32_trunc_sat_f32_s, UntypedVal::i32_trunc_sat_f32_s),
(Instruction::I32TruncSatF32U, execute_i32_trunc_sat_f32_u, UntypedVal::i32_trunc_sat_f32_u),
Expand Down
3 changes: 3 additions & 0 deletions crates/wasmi/src/engine/executor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::{
ResumableInvocation,
},
func::HostFuncEntity,
CallHook,
Error,
Func,
FuncEntity,
Expand Down Expand Up @@ -219,7 +220,9 @@ impl<'engine> EngineExecutor<'engine> {
),
Some(instance),
)?;
store.invoke_call_hook(CallHook::CallingWasm)?;
self.execute_func(store)?;
store.invoke_call_hook(CallHook::ReturningFromWasm)?;
}
FuncEntity::Host(host_func) => {
// The host function signature is required for properly
Expand Down
19 changes: 19 additions & 0 deletions crates/wasmi/src/engine/translator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2520,6 +2520,25 @@ impl FuncTranslator {
Ok(())
}

/// Translates a Wasm `i64.extend_i32_u` instruction.
fn translate_i64_extend_i32_u(&mut self) -> Result<(), Error> {
bail_unreachable!(self);
if let TypedProvider::Register(_) = self.alloc.stack.peek() {
// Nothing to do.
//
// We try to not manipulate the emulation stack if not needed.
return Ok(());
}
// Case: At this point we know that the top-most stack item is a constant value.
// We pop it, change its type and push it back onto the stack.
let TypedProvider::Const(value) = self.alloc.stack.pop() else {
panic!("the top-most stack item was asserted to be a constant value but a register was found")
};
debug_assert_eq!(value.ty(), ValType::I32);
self.alloc.stack.push_const(u64::from(u32::from(value)));
Ok(())
}

/// Translates an unconditional `return` instruction.
fn translate_return(&mut self) -> Result<(), Error> {
let fuel_info = self.fuel_info();
Expand Down
2 changes: 0 additions & 2 deletions crates/wasmi/src/engine/translator/relink_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -497,8 +497,6 @@ impl Instruction {
I::I64RemUImm16Rev(instr) => relink_simple(instr, new_result, old_result),

I::I32WrapI64(instr) |
I::I64ExtendI32S(instr) |
I::I64ExtendI32U(instr) |
I::I32TruncF32S(instr) |
I::I32TruncF32U(instr) |
I::I32TruncF64S(instr) |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ mod i64_extend_i32_s {
#[test]
#[cfg_attr(miri, ignore)]
fn reg() {
conversion_reg::<i32, i64>(OP, Instruction::i64_extend_i32_s);
conversion_reg::<i32, i64>(OP, Instruction::i64_extend32_s);
}

#[test]
Expand All @@ -57,7 +57,8 @@ mod i64_extend_i32_u {
#[test]
#[cfg_attr(miri, ignore)]
fn reg() {
conversion_reg::<i32, i64>(OP, Instruction::i64_extend_i32_u);
let expected = [Instruction::return_reg(0)];
conversion_reg_with::<i32, i64, _>(OP, expected)
}

#[test]
Expand Down
1 change: 0 additions & 1 deletion crates/wasmi/src/engine/translator/typed_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,6 @@ impl TypedVal {

fn i32_wrap_i64(i64) -> i32;
fn i64_extend_i32_s(i32) -> i64;
fn i64_extend_i32_u(i32) -> i64;

fn f32_demote_f64(f64) -> f32;
fn f64_promote_f32(f32) -> f64;
Expand Down
4 changes: 2 additions & 2 deletions crates/wasmi/src/engine/translator/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3049,11 +3049,11 @@ impl<'a> VisitOperator<'a> for FuncTranslator {
}

fn visit_i64_extend_i32_s(&mut self) -> Self::Output {
self.translate_unary(Instruction::i64_extend_i32_s, TypedVal::i64_extend_i32_s)
self.translate_unary(Instruction::i64_extend32_s, TypedVal::i64_extend_i32_s)
}

fn visit_i64_extend_i32_u(&mut self) -> Self::Output {
self.translate_unary(Instruction::i64_extend_i32_u, TypedVal::i64_extend_i32_u)
self.translate_i64_extend_i32_u()
}

fn visit_i64_trunc_f32_s(&mut self) -> Self::Output {
Expand Down
2 changes: 0 additions & 2 deletions crates/wasmi/src/engine/translator/visit_register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -523,8 +523,6 @@ impl VisitInputRegisters for Instruction {
Instruction::F32CopysignImm(instr) => instr.visit_input_registers(f),
Instruction::F64CopysignImm(instr) => instr.visit_input_registers(f),
Instruction::I32WrapI64(instr) => instr.visit_input_registers(f),
Instruction::I64ExtendI32S(instr) => instr.visit_input_registers(f),
Instruction::I64ExtendI32U(instr) => instr.visit_input_registers(f),
Instruction::I32TruncF32S(instr) => instr.visit_input_registers(f),
Instruction::I32TruncF32U(instr) => instr.visit_input_registers(f),
Instruction::I32TruncF64S(instr) => instr.visit_input_registers(f),
Expand Down
2 changes: 1 addition & 1 deletion crates/wasmi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ pub use self::{
ModuleImportsIter,
Read,
},
store::{AsContext, AsContextMut, Store, StoreContext, StoreContextMut},
store::{AsContext, AsContextMut, CallHook, Store, StoreContext, StoreContextMut},
table::{Table, TableType},
value::Val,
};
Expand Down
81 changes: 81 additions & 0 deletions crates/wasmi/src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,19 @@ impl<T> Debug for ResourceLimiterQuery<T> {
}
}

/// A wrapper used to store hooks added with [`Store::call_hook`], containing a
/// boxed `FnMut(&mut T, CallHook) -> Result<(), Error>`.
///
/// This wrapper exists to provide a `Debug` impl so that `#[derive(Debug)]`
/// works for [`Store`].
#[allow(clippy::type_complexity)]
struct CallHookWrapper<T>(Box<dyn FnMut(&mut T, CallHook) -> Result<(), Error> + Send + Sync>);
impl<T> Debug for CallHookWrapper<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "CallHook(...)")
}
}

/// The store that owns all data associated to Wasm modules.
#[derive(Debug)]
pub struct Store<T> {
Expand All @@ -119,6 +132,10 @@ pub struct Store<T> {
data: T,
/// User provided hook to retrieve a [`ResourceLimiter`].
limiter: Option<ResourceLimiterQuery<T>>,
/// User provided callback called when a host calls a WebAssembly function
/// or a WebAssembly function calls a host function, or these functions
/// return.
call_hook: Option<CallHookWrapper<T>>,
}

/// The inner store that owns all data not associated to the host state.
Expand Down Expand Up @@ -166,6 +183,20 @@ fn test_store_is_send_sync() {
};
}

/// Argument to the callback set by [`Store::call_hook`] to indicate why the
/// callback was invoked.
#[derive(Debug)]
pub enum CallHook {
/// Indicates that a WebAssembly function is being called from the host.
CallingWasm,
/// Indicates that a WebAssembly function called from the host is returning.
ReturningFromWasm,
/// Indicates that a host function is being called from a WebAssembly function.
CallingHost,
/// Indicates that a host function called from a WebAssembly function is returning.
ReturningFromHost,
}

/// An error that may be encountered when operating on the [`Store`].
#[derive(Debug, Clone)]
pub enum FuelError {
Expand Down Expand Up @@ -821,6 +852,7 @@ where
trampolines: Arena::new(),
data: T::default(),
limiter: None,
call_hook: None,
}
}
}
Expand All @@ -833,6 +865,7 @@ impl<T> Store<T> {
trampolines: Arena::new(),
data,
limiter: None,
call_hook: None,
}
}

Expand Down Expand Up @@ -978,6 +1011,54 @@ impl<T> Store<T> {
.get(entity_index)
.unwrap_or_else(|| panic!("failed to resolve stored host function: {entity_index:?}"))
}

/// Sets a callback function that is executed whenever a WebAssembly
/// function is called from the host or a host function is called from
/// WebAssembly, or these functions return.
///
/// The function is passed a `&mut T` to the underlying store, and a
/// [`CallHook`]. [`CallHook`] can be used to find out what kind of function
/// is being called or returned from.
///
/// The callback can either return `Ok(())` or an `Err` with an
/// [`Error`]. If an error is returned, it is returned to the host
/// caller. If there are nested calls, only the most recent host caller
/// receives the error and it is not propagated further automatically. The
/// hook may be invoked again as new functions are called and returned from.
pub fn call_hook(
&mut self,
hook: impl FnMut(&mut T, CallHook) -> Result<(), Error> + Send + Sync + 'static,
) {
self.call_hook = Some(CallHookWrapper(Box::new(hook)));
}

/// Executes the callback set by [`Store::call_hook`] if any has been set.
///
/// # Note
///
/// - Returns the value returned by the call hook.
/// - Returns `Ok(())` if no call hook exists.
#[inline]
pub(crate) fn invoke_call_hook(&mut self, call_type: CallHook) -> Result<(), Error> {
match self.call_hook.as_mut() {
None => Ok(()),
Some(call_hook) => Self::invoke_call_hook_impl(&mut self.data, call_type, call_hook),
}
}

/// Utility function to invoke the [`Store::call_hook`] that is asserted to
/// be available in this case.
///
/// This is kept as a separate `#[cold]` function to help the compiler speed
/// up the code path without any call hooks.
#[cold]
fn invoke_call_hook_impl(
data: &mut T,
call_type: CallHook,
call_hook: &mut CallHookWrapper<T>,
) -> Result<(), Error> {
call_hook.0(data, call_type)
}
}

/// A trait used to get shared access to a [`Store`] in Wasmi.
Expand Down
Loading

0 comments on commit ebb70f1

Please sign in to comment.