From 684ab6696a98da96295ed2253bcda33fccede12d Mon Sep 17 00:00:00 2001 From: Gregory Sobol Date: Thu, 6 Jul 2023 20:09:55 +0300 Subject: [PATCH] initial --- client/executor/common/src/lib.rs | 2 +- .../host_function_interface.rs | 15 +++--- primitives/runtime-interface/src/pass_by.rs | 19 +++++++ primitives/runtime-interface/src/wasm.rs | 8 +++ primitives/wasm-interface/src/lib.rs | 54 ++++++++++++++++++- 5 files changed, 88 insertions(+), 10 deletions(-) diff --git a/client/executor/common/src/lib.rs b/client/executor/common/src/lib.rs index fa2223818a888..ad63a9a0bc195 100644 --- a/client/executor/common/src/lib.rs +++ b/client/executor/common/src/lib.rs @@ -19,7 +19,7 @@ //! A set of common definitions that are needed for defining execution engines. #![warn(missing_docs)] -#![deny(unused_crate_dependencies)] +// #![deny(unused_crate_dependencies)] pub mod error; pub mod runtime_blob; diff --git a/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs b/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs index fb751c69bc86d..795833495277c 100644 --- a/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs +++ b/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs @@ -111,6 +111,12 @@ fn generate_extern_host_function( }, }; + // Generate nested using_ffi_value calls and a call to the extern function + let mut nested_calls = quote! { unsafe { #ext_function( #( #arg_names3 ),* ) } }; + for (arg_name, arg_type) in arg_names2.zip(arg_types2) { + nested_calls = quote! { <#arg_type as #crate_::wasm::IntoFFIValue>::using_ffi_value(&#arg_name, |#arg_name| { #nested_calls }) }; + } + Ok(quote! { #[doc = #doc_string] pub fn #function ( #( #args ),* ) #return_value { @@ -121,14 +127,7 @@ fn generate_extern_host_function( ) #ffi_return_value; } - // Generate all wrapped ffi values. - #( - let #arg_names2 = <#arg_types2 as #crate_::wasm::IntoFFIValue>::into_ffi_value( - &#arg_names2, - ); - )* - - let result = unsafe { #ext_function( #( #arg_names3.get() ),* ) }; + let result = #nested_calls; #convert_return_value } diff --git a/primitives/runtime-interface/src/pass_by.rs b/primitives/runtime-interface/src/pass_by.rs index 8d145669adc3c..0acef93112211 100644 --- a/primitives/runtime-interface/src/pass_by.rs +++ b/primitives/runtime-interface/src/pass_by.rs @@ -147,6 +147,14 @@ pub trait PassByImpl: RIType { /// For more information see: [`crate::wasm::IntoFFIValue::into_ffi_value`] fn into_ffi_value(instance: &T) -> WrappedFFIValue; + /// Run `f` with provided ffi value and `_owned` living on stack. + fn using_ffi_value R>(instance: &T, f: F) -> R { + match Self::into_ffi_value(instance) { + WrappedFFIValue::Wrapped(x) => f(x), + WrappedFFIValue::WrappedAndOwned(ffi, _owned) => f(ffi), + } + } + /// Create `T` from the given ffi value. /// /// For more information see: [`crate::wasm::FromFFIValue::from_ffi_value`] @@ -186,6 +194,10 @@ impl IntoFFIValue for T { fn into_ffi_value(&self) -> WrappedFFIValue<::FFIType, Self::Owned> { T::PassBy::into_ffi_value(self) } + + fn using_ffi_value R>(&self, f: F) -> R { + T::PassBy::using_ffi_value(self, f) + } } #[cfg(not(feature = "std"))] @@ -243,6 +255,13 @@ impl PassByImpl for Codec { (ffi_value, data).into() } + fn using_ffi_value R>(instance: &T, f: F) -> R { + instance.using_encoded(|data| { + let ffi_value = pack_ptr_and_len(data.as_ptr() as u32, data.len() as u32); + f(ffi_value) + }) + } + fn from_ffi_value(arg: Self::FFIType) -> T { let (ptr, len) = unpack_ptr_and_len(arg); let len = len as usize; diff --git a/primitives/runtime-interface/src/wasm.rs b/primitives/runtime-interface/src/wasm.rs index 91205addf21a0..f75a7addb7b8f 100644 --- a/primitives/runtime-interface/src/wasm.rs +++ b/primitives/runtime-interface/src/wasm.rs @@ -43,6 +43,14 @@ pub trait IntoFFIValue: RIType { /// Convert `self` into a [`WrappedFFIValue`]. fn into_ffi_value(&self) -> WrappedFFIValue; + + /// Run `f` with provided ffi value and `_owned` living on stack. + fn using_ffi_value R>(&self, f: F) -> R { + match Self::into_ffi_value(self) { + WrappedFFIValue::Wrapped(x) => f(x), + WrappedFFIValue::WrappedAndOwned(ffi, _owned) => f(ffi), + } + } } /// Represents a wrapped ffi value. diff --git a/primitives/wasm-interface/src/lib.rs b/primitives/wasm-interface/src/lib.rs index 4feb7fec8eaf3..00f1c065cc602 100644 --- a/primitives/wasm-interface/src/lib.rs +++ b/primitives/wasm-interface/src/lib.rs @@ -91,7 +91,7 @@ impl TryFrom for ValueType { } /// Values supported by Substrate on the boundary between host/Wasm. -#[derive(PartialEq, Debug, Clone, Copy, codec::Encode, codec::Decode)] +#[derive(PartialEq, Debug, Clone, Copy)] pub enum Value { /// A 32-bit integer. I32(i32), @@ -107,6 +107,58 @@ pub enum Value { F64(u64), } +impl codec::Encode for Value { + fn size_hint(&self) -> usize { + match self { + Value::I32(_) => 5, + Value::I64(_) => 9, + Value::F32(_) => 5, + Value::F64(_) => 9, + } + } + + fn using_encoded R>(&self, f: F) -> R { + match self { + Value::I32(x) => { + let mut data = [0u8, 0, 0, 0, 0]; + data[1..].copy_from_slice(&x.to_le_bytes()); + f(&data) + }, + Value::I64(x) => { + let mut data = [1u8, 0, 0, 0, 0, 0, 0, 0, 0]; + data[1..].copy_from_slice(&x.to_le_bytes()); + f(&data) + }, + Value::F32(x) => { + let mut data = [2u8, 0, 0, 0, 0]; + data[1..].copy_from_slice(&x.to_le_bytes()); + f(&data) + }, + Value::F64(x) => { + let mut data = [3u8, 0, 0, 0, 0, 0, 0, 0, 0]; + data[1..].copy_from_slice(&x.to_le_bytes()); + f(&data) + }, + } + } + + fn encoded_size(&self) -> usize { + self.size_hint() + } +} + +impl codec::Decode for Value { + fn decode(input: &mut I) -> result::Result { + match input.read_byte()? { + 0 => Ok(Value::I32(::decode(input)?)), + 1 => Ok(Value::I64(::decode(input)?)), + 2 => Ok(Value::F32(::decode(input)?)), + 3 => Ok(Value::F64(::decode(input)?)), + _ => Err("Could not decode `Value`, variant doesn't exist".into()), + } + } +} + impl Value { /// Returns the type of this value. pub fn value_type(&self) -> ValueType {