Skip to content

Commit

Permalink
Merge pull request #574 from wasmx/host_funcs_args
Browse files Browse the repository at this point in the history
Pass arguments to host function as const Value*
  • Loading branch information
chfast authored Oct 14, 2020
2 parents 86506aa + 2a22c03 commit 4c2c504
Show file tree
Hide file tree
Showing 13 changed files with 75 additions and 112 deletions.
7 changes: 3 additions & 4 deletions include/fizzy/fizzy.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,10 @@ typedef struct FizzyExecutionResult
///
/// @param context Opaque pointer to execution context.
/// @param instance Pointer to module instance.
/// @param args Pointer to the argument array. Can be NULL iff args_size equals 0.
/// @param args_size Size of the argument array.
/// @param args Pointer to the argument array. Can be NULL iff function has no inputs.
/// @param depth Call stack depth.
typedef FizzyExecutionResult (*FizzyExternalFn)(void* context, FizzyInstance* instance,
const union FizzyValue* args, size_t args_size, int depth);
typedef FizzyExecutionResult (*FizzyExternalFn)(
void* context, FizzyInstance* instance, const union FizzyValue* args, int depth);

/// External function.
typedef struct FizzyExternalFunction
Expand Down
4 changes: 2 additions & 2 deletions lib/fizzy/capi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ inline fizzy::ExecutionResult unwrap(const FizzyExecutionResult& result) noexcep

inline auto unwrap(FizzyExternalFn func, void* context) noexcept
{
return [func, context](fizzy::Instance& instance, fizzy::span<const fizzy::Value> args,
return [func, context](fizzy::Instance& instance, const fizzy::Value* args,
int depth) noexcept -> fizzy::ExecutionResult {
const auto result = func(context, wrap(&instance), wrap(args.data()), args.size(), depth);
const auto result = func(context, wrap(&instance), wrap(args), depth);
return unwrap(result);
};
}
Expand Down
9 changes: 4 additions & 5 deletions lib/fizzy/execute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ inline bool invoke_function(
{
const auto num_args = func_type.inputs.size();
assert(stack.size() >= num_args);
span<const Value> call_args{stack.rend() - num_args, num_args};
const auto call_args = stack.rend() - num_args;

const auto ret = func(instance, call_args, depth + 1);
// Bubble up traps
Expand All @@ -509,8 +509,8 @@ inline bool invoke_function(
inline bool invoke_function(const FuncType& func_type, uint32_t func_idx, Instance& instance,
OperandStack& stack, int depth)
{
const auto func = [func_idx](Instance& _instance, span<const Value> args, int _depth) {
return execute(_instance, func_idx, args.data(), _depth);
const auto func = [func_idx](Instance& _instance, const Value* args, int _depth) {
return execute(_instance, func_idx, args, _depth);
};
return invoke_function(func_type, func, instance, stack, depth);
}
Expand All @@ -526,8 +526,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args,

assert(instance.module->imported_function_types.size() == instance.imported_functions.size());
if (func_idx < instance.imported_functions.size())
return instance.imported_functions[func_idx].function(
instance, {args, func_type.inputs.size()}, depth);
return instance.imported_functions[func_idx].function(instance, args, depth);

const auto& code = instance.module->get_code(func_idx);
auto* const memory = instance.memory.get();
Expand Down
10 changes: 5 additions & 5 deletions lib/fizzy/instantiate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,8 +330,8 @@ std::unique_ptr<Instance> instantiate(std::unique_ptr<const Module> module,
auto it_table = instance->table->begin() + elementsec_offsets[i];
for (const auto idx : instance->module->elementsec[i].init)
{
auto func = [idx, &instance_ref = *instance](fizzy::Instance&, span<const Value> args,
int depth) { return execute(instance_ref, idx, args.data(), depth); };
auto func = [idx, &instance_ref = *instance](fizzy::Instance&, const Value* args,
int depth) { return execute(instance_ref, idx, args, depth); };

*it_table++ =
ExternalFunction{std::move(func), instance->module->get_function_type(idx)};
Expand Down Expand Up @@ -363,7 +363,7 @@ std::unique_ptr<Instance> instantiate(std::unique_ptr<const Module> module,
// Wrap the function with the lambda capturing shared instance
auto& table_function = (*it_table)->function;
table_function = [shared_instance, func = std::move(table_function)](
fizzy::Instance& _instance, span<const Value> args,
fizzy::Instance& _instance, const Value* args,
int depth) { return func(_instance, args, depth); };
++it_table;
}
Expand Down Expand Up @@ -435,8 +435,8 @@ std::optional<ExternalFunction> find_exported_function(Instance& instance, std::
return std::nullopt;

const auto idx = *opt_index;
auto func = [idx, &instance](fizzy::Instance&, span<const Value> args, int depth) {
return execute(instance, idx, args.data(), depth);
auto func = [idx, &instance](fizzy::Instance&, const Value* args, int depth) {
return execute(instance, idx, args, depth);
};

return ExternalFunction{std::move(func), instance.module->get_function_type(idx)};
Expand Down
4 changes: 2 additions & 2 deletions lib/fizzy/instantiate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ struct Instance;

struct ExternalFunction
{
std::function<ExecutionResult(Instance&, span<const Value>, int depth)> function;
std::function<ExecutionResult(Instance&, const Value*, int depth)> function;
FuncType type;
};

Expand Down Expand Up @@ -101,7 +101,7 @@ struct ImportedFunction
std::string name;
std::vector<ValType> inputs;
std::optional<ValType> output;
std::function<ExecutionResult(Instance&, span<const Value>, int depth)> function;
std::function<ExecutionResult(Instance&, const Value*, int depth)> function;
};

// Create vector of ExternalFunctions ready to be passed to instantiate.
Expand Down
6 changes: 3 additions & 3 deletions test/unittests/api_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ namespace
{
auto function_returning_value(Value value) noexcept
{
return [value](Instance&, span<const Value>, int) { return value; };
return [value](Instance&, const Value*, int) { return value; };
}

ExecutionResult function_returning_void(Instance&, span<const Value>, int) noexcept
ExecutionResult function_returning_void(Instance&, const Value*, int) noexcept
{
return Void;
}
Expand Down Expand Up @@ -263,7 +263,7 @@ TEST(api, find_exported_function)
"0061736d010000000105016000017f021001087370656374657374036261720000040401700000050401010102"
"0606017f0041000b07170403666f6f000001670300037461620100036d656d0200");

auto bar = [](Instance&, span<const Value>, int) { return Value{42}; };
auto bar = [](Instance&, const Value*, int) { return Value{42}; };
const auto bar_type = FuncType{{}, {ValType::i32}};

auto instance_reexported_function =
Expand Down
33 changes: 15 additions & 18 deletions test/unittests/capi_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,10 @@ TEST(capi, instantiate_imported_function)
module = fizzy_parse(wasm.data(), wasm.size());
ASSERT_NE(module, nullptr);

FizzyExternalFunction host_funcs[] = {
{[](void*, FizzyInstance*, const FizzyValue*, size_t, int) {
return FizzyExecutionResult{false, true, {42}};
},
nullptr}};
FizzyExternalFunction host_funcs[] = {{[](void*, FizzyInstance*, const FizzyValue*, int) {
return FizzyExecutionResult{false, true, {42}};
},
nullptr}};

auto instance = fizzy_instantiate(module, host_funcs, 1);
EXPECT_NE(instance, nullptr);
Expand Down Expand Up @@ -210,12 +209,11 @@ TEST(capi, execute_with_host_function)
auto module = fizzy_parse(wasm.data(), wasm.size());
ASSERT_NE(module, nullptr);

FizzyExternalFunction host_funcs[] = {
{[](void*, FizzyInstance*, const FizzyValue*, size_t, int) {
return FizzyExecutionResult{false, true, {42}};
},
nullptr},
{[](void*, FizzyInstance*, const FizzyValue* args, size_t, int) {
FizzyExternalFunction host_funcs[] = {{[](void*, FizzyInstance*, const FizzyValue*, int) {
return FizzyExecutionResult{false, true, {42}};
},
nullptr},
{[](void*, FizzyInstance*, const FizzyValue* args, int) {
return FizzyExecutionResult{false, true, {args[0].i64 / args[1].i64}};
},
nullptr}};
Expand Down Expand Up @@ -244,11 +242,10 @@ TEST(capi, imported_function_traps)
auto module = fizzy_parse(wasm.data(), wasm.size());
ASSERT_NE(module, nullptr);

FizzyExternalFunction host_funcs[] = {
{[](void*, FizzyInstance*, const FizzyValue*, size_t, int) {
return FizzyExecutionResult{true, false, {}};
},
nullptr}};
FizzyExternalFunction host_funcs[] = {{[](void*, FizzyInstance*, const FizzyValue*, int) {
return FizzyExecutionResult{true, false, {}};
},
nullptr}};

auto instance = fizzy_instantiate(module, host_funcs, 1);
ASSERT_NE(instance, nullptr);
Expand All @@ -273,7 +270,7 @@ TEST(capi, imported_function_void)

bool called = false;
FizzyExternalFunction host_funcs[] = {
{[](void* context, FizzyInstance*, const FizzyValue*, size_t, int) {
{[](void* context, FizzyInstance*, const FizzyValue*, int) {
*static_cast<bool*>(context) = true;
return FizzyExecutionResult{false, false, {}};
},
Expand Down Expand Up @@ -328,7 +325,7 @@ TEST(capi, imported_function_from_another_module)

auto host_context = std::make_pair(instance1, func_idx);

auto sub = [](void* context, FizzyInstance*, const FizzyValue* args, size_t,
auto sub = [](void* context, FizzyInstance*, const FizzyValue* args,
int depth) -> FizzyExecutionResult {
const auto* instance_and_func_idx =
static_cast<std::pair<FizzyInstance*, uint32_t>*>(context);
Expand Down
40 changes: 19 additions & 21 deletions test/unittests/execute_call_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,11 +171,11 @@ TEST(execute_call, call_indirect_imported_table)
"0061736d01000000010a026000017f60017f017f020a01016d01740170010514030201010a0901070020001100"
"000b");

auto f1 = [](Instance&, span<const Value>, int) { return Value{1}; };
auto f2 = [](Instance&, span<const Value>, int) { return Value{2}; };
auto f3 = [](Instance&, span<const Value>, int) { return Value{3}; };
auto f4 = [](Instance&, span<const Value>, int) { return Value{4}; };
auto f5 = [](Instance&, span<const Value>, int) { return Trap; };
auto f1 = [](Instance&, const Value*, int) { return Value{1}; };
auto f2 = [](Instance&, const Value*, int) { return Value{2}; };
auto f3 = [](Instance&, const Value*, int) { return Value{3}; };
auto f4 = [](Instance&, const Value*, int) { return Value{4}; };
auto f5 = [](Instance&, const Value*, int) { return Trap; };

auto out_i32 = FuncType{{}, {ValType::i32}};
auto out_i64 = FuncType{{}, {ValType::i64}};
Expand Down Expand Up @@ -270,7 +270,7 @@ TEST(execute_call, imported_function_call)

const auto module = parse(wasm);

constexpr auto host_foo = [](Instance&, span<const Value>, int) { return Value{42}; };
constexpr auto host_foo = [](Instance&, const Value*, int) { return Value{42}; };
const auto host_foo_type = module->typesec[0];

auto instance = instantiate(*module, {{host_foo, host_foo_type}});
Expand All @@ -295,9 +295,7 @@ TEST(execute_call, imported_function_call_with_arguments)

const auto module = parse(wasm);

auto host_foo = [](Instance&, span<const Value> args, int) {
return Value{as_uint32(args[0]) * 2};
};
auto host_foo = [](Instance&, const Value* args, int) { return Value{as_uint32(args[0]) * 2}; };
const auto host_foo_type = module->typesec[0];

auto instance = instantiate(*module, {{host_foo, host_foo_type}});
Expand Down Expand Up @@ -339,11 +337,11 @@ TEST(execute_call, imported_functions_call_indirect)
ASSERT_EQ(module->importsec.size(), 2);
ASSERT_EQ(module->codesec.size(), 2);

constexpr auto sqr = [](Instance&, span<const Value> args, int) {
constexpr auto sqr = [](Instance&, const Value* args, int) {
const auto x = as_uint32(args[0]);
return Value{uint64_t{x} * uint64_t{x}};
};
constexpr auto isqrt = [](Instance&, span<const Value> args, int) {
constexpr auto isqrt = [](Instance&, const Value* args, int) {
const auto x = as_uint32(args[0]);
return Value{(11 + uint64_t{x} / 11) / 2};
};
Expand Down Expand Up @@ -388,8 +386,8 @@ TEST(execute_call, imported_function_from_another_module)
const auto func_idx = fizzy::find_exported_function(*module1, "sub");
ASSERT_TRUE(func_idx.has_value());

auto sub = [&instance1, func_idx](Instance&, span<const Value> args, int) -> ExecutionResult {
return fizzy::execute(*instance1, *func_idx, args.data());
auto sub = [&instance1, func_idx](Instance&, const Value* args, int) -> ExecutionResult {
return fizzy::execute(*instance1, *func_idx, args);
};

auto instance2 = instantiate(parse(bin2), {{sub, module1->typesec[0]}});
Expand Down Expand Up @@ -560,9 +558,9 @@ TEST(execute_call, call_imported_infinite_recursion)
const auto wasm = from_hex("0061736d010000000105016000017f020b01036d6f6403666f6f0000");

const auto module = parse(wasm);
auto host_foo = [](Instance& instance, span<const Value>, int depth) -> ExecutionResult {
auto host_foo = [](Instance& instance, const Value* args, int depth) -> ExecutionResult {
EXPECT_LE(depth, MaxDepth);
return execute(instance, 0, {}, depth + 1);
return execute(instance, 0, args, depth + 1);
};
const auto host_foo_type = module->typesec[0];

Expand All @@ -583,10 +581,10 @@ TEST(execute_call, call_via_imported_infinite_recursion)
"0061736d010000000105016000017f020b01036d6f6403666f6f0000030201000a0601040010000b");

const auto module = parse(wasm);
auto host_foo = [](Instance& instance, span<const Value>, int depth) -> ExecutionResult {
auto host_foo = [](Instance& instance, const Value* args, int depth) -> ExecutionResult {
// Function $f will increase depth. This means each iteration goes 2 steps deeper.
EXPECT_LE(depth, MaxDepth - 1);
return execute(instance, 1, {}, depth + 1);
return execute(instance, 1, args, depth + 1);
};
const auto host_foo_type = module->typesec[0];

Expand All @@ -603,10 +601,10 @@ TEST(execute_call, call_imported_max_depth_recursion)
const auto wasm = from_hex("0061736d010000000105016000017f020b01036d6f6403666f6f0000");

const auto module = parse(wasm);
auto host_foo = [](Instance& instance, span<const Value>, int depth) -> ExecutionResult {
auto host_foo = [](Instance& instance, const Value* args, int depth) -> ExecutionResult {
if (depth == MaxDepth)
return Value{uint32_t{1}}; // Terminate recursion on the max depth.
return execute(instance, 0, {}, depth + 1);
return execute(instance, 0, args, depth + 1);
};
const auto host_foo_type = module->typesec[0];

Expand All @@ -627,11 +625,11 @@ TEST(execute_call, call_via_imported_max_depth_recursion)
"0061736d010000000105016000017f020b01036d6f6403666f6f0000030201000a0601040010000b");

const auto module = parse(wasm);
auto host_foo = [](Instance& instance, span<const Value>, int depth) -> ExecutionResult {
auto host_foo = [](Instance& instance, const Value* args, int depth) -> ExecutionResult {
// Function $f will increase depth. This means each iteration goes 2 steps deeper.
if (depth == (MaxDepth - 1))
return Value{uint32_t{1}}; // Terminate recursion on the max depth.
return execute(instance, 1, {}, depth + 1);
return execute(instance, 1, args, depth + 1);
};
const auto host_foo_type = module->typesec[0];

Expand Down
2 changes: 1 addition & 1 deletion test/unittests/execute_control_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,7 @@ TEST(execute_control, br_1_out_of_function_and_imported_function)
"0061736d010000000108026000006000017f02150108696d706f727465640866756e6374696f6e000003020101"
"0a0d010b00034041010c010b41000b");

constexpr auto fake_imported_function = [](Instance&, span<const Value>,
constexpr auto fake_imported_function = [](Instance&, const Value*,
int) noexcept -> ExecutionResult { return Void; };

const auto module = parse(bin);
Expand Down
Loading

0 comments on commit 4c2c504

Please sign in to comment.