Skip to content

rust: add support for imported functions #782

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 11 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 83 additions & 6 deletions bindings/rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,16 +191,70 @@ impl Drop for Instance {
}
}

struct HostFunction {
module: CString,
name: CString,
inputs: Vec<sys::FizzyValueType>,
output: sys::FizzyValueType,
index: usize,
}

unsafe extern "C" fn host_callback(
host_context: *mut std::os::raw::c_void,
instance: *mut sys::FizzyInstance,
args: *const sys::FizzyValue,
context: *mut sys::FizzyExecutionContext,
) -> sys::FizzyExecutionResult {
println!("host fuction called!");
//unimplemented!()
sys::FizzyExecutionResult {
trapped: false,
has_value: false,
value: sys::FizzyValue { i32: 0 },
}
}

fn create_function_import_list(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still need to figure out what is the best API defining host functions, but at least this semi-finished translation layer works.

host_functions: &[&HostFunction],
) -> Vec<sys::FizzyImportedFunction> {
assert!(host_functions.len() == 1);
let host_function = &host_functions[0];
let fn_type = sys::FizzyFunctionType {
output: host_function.output,
inputs: host_function.inputs.as_ptr(),
inputs_size: host_function.inputs.len(),
};
let ext_fn = sys::FizzyExternalFunction {
type_: fn_type,
function: Some(host_callback),
context: std::ptr::null_mut(),
};
vec![sys::FizzyImportedFunction {
module: host_function.module.as_ptr(),
name: host_function.name.as_ptr(),
external_function: ext_fn,
}]
}

impl Module {
/// Create an instance of a module.
// TODO: support imported functions
pub fn instantiate(self) -> Result<Instance, Error> {
let mut err = FizzyErrorBox::new();
let host_fn1 = HostFunction {
module: CString::new("env").expect("cstring to work"),
name: CString::new("print").expect("cstring to work"),
inputs: vec![],
output: sys::FizzyValueTypeVoid,
index: 0,
};
let import_list = vec![&host_fn1];
let import_list = create_function_import_list(&import_list);
let ptr = unsafe {
sys::fizzy_instantiate(
sys::fizzy_resolve_instantiate(
self.0.as_ptr(),
std::ptr::null(),
0,
import_list.as_ptr(),
import_list.len(),
std::ptr::null(),
std::ptr::null(),
std::ptr::null(),
Expand Down Expand Up @@ -1271,9 +1325,7 @@ mod tests {
assert!(instance.is_err());
assert_eq!(
instance.err().unwrap(),
Error::InstantiationFailed(
"module requires 1 imported functions, 0 provided".to_string()
)
Error::InstantiationFailed("imported function env.adler32 is required".to_string())
);
}

Expand All @@ -1298,4 +1350,29 @@ mod tests {
assert!(result.is_err());
assert_eq!(result.err().unwrap(), Error::Trapped);
}

#[test]
fn execute_host_function2() {
/* wat2wasm
(module
(func $print (import "env" "print"))
(func (export "foo")
call $print
)
)
*/
let input = hex::decode(
"0061736d01000000010401600000020d0103656e76057072696e7400000302010007070103666f6f00010a0601040010000b").unwrap();

let module = parse(&input);
assert!(module.is_ok());
let instance = module.unwrap().instantiate();
assert!(instance.is_ok());
let mut instance = instance.unwrap();

// Successful execution.
let result = instance.execute("foo", &[]);
assert!(result.is_ok());
assert!(result.unwrap().is_none());
}
}
7 changes: 7 additions & 0 deletions lib/fizzy/capi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <fizzy/fizzy.h>
#include <cstring>
#include <memory>
#include <iostream>

namespace
{
Expand Down Expand Up @@ -275,6 +276,7 @@ inline fizzy::ImportedFunction unwrap(const FizzyImportedFunction& c_imported_fu

auto function = unwrap(
c_imported_func.external_function.function, c_imported_func.external_function.context);
std::cout << "c_imported_func:" << c_imported_func.module << ":" << c_imported_func.name << std::endl;

return {c_imported_func.module, c_imported_func.name, std::move(inputs), output,
std::move(function)};
Expand Down Expand Up @@ -641,6 +643,11 @@ FizzyInstance* fizzy_instantiate(const FizzyModule* module,
set_success(error);
return wrap(instance.release());
}
catch (fizzy::instantiate_error const& e)
{
std::cout << e.what() << std::endl;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These was my error reporting prior to us adding proper support 😅

return nullptr;
}
catch (...)
{
set_error_from_current_exception(error);
Expand Down
3 changes: 2 additions & 1 deletion lib/fizzy/instantiate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <algorithm>
#include <cassert>
#include <cstring>
#include <iostream>

namespace fizzy
{
Expand Down Expand Up @@ -261,7 +262,7 @@ ExternalFunction find_imported_function(const std::string& module, const std::st
const FuncType& module_func_type, const std::vector<ImportedFunction>& imported_functions)
{
const auto it = std::find_if(imported_functions.begin(), imported_functions.end(),
[module, name](const auto& func) { return module == func.module && name == func.name; });
[module, name](const auto& func) { std::cout << func.module << ":" << func.name << std::endl; return module == func.module && name == func.name; });

if (it == imported_functions.end())
{
Expand Down