Skip to content

Commit

Permalink
Pass arguments to host function as const Value*
Browse files Browse the repository at this point in the history
  • Loading branch information
chfast committed Oct 13, 2020
1 parent c18dc87 commit 626ac4a
Show file tree
Hide file tree
Showing 11 changed files with 57 additions and 90 deletions.
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), 0, 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
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
43 changes: 8 additions & 35 deletions test/unittests/execute_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -774,7 +774,7 @@ TEST(execute, imported_function)
const auto module = parse(wasm);
ASSERT_EQ(module->typesec.size(), 1);

constexpr auto host_foo = [](Instance&, span<const Value> args, int) {
constexpr auto host_foo = [](Instance&, const Value* args, int) {
return Value{as_uint32(args[0]) + as_uint32(args[1])};
};

Expand All @@ -794,10 +794,10 @@ TEST(execute, imported_two_functions)
const auto module = parse(wasm);
ASSERT_EQ(module->typesec.size(), 1);

constexpr auto host_foo1 = [](Instance&, span<const Value> args, int) {
constexpr auto host_foo1 = [](Instance&, const Value* args, int) {
return Value{as_uint32(args[0]) + as_uint32(args[1])};
};
constexpr auto host_foo2 = [](Instance&, span<const Value> args, int) {
constexpr auto host_foo2 = [](Instance&, const Value* args, int) {
return Value{as_uint32(args[0]) * as_uint32(args[1])};
};

Expand All @@ -821,10 +821,10 @@ TEST(execute, imported_functions_and_regular_one)
"0061736d0100000001070160027f7f017f021702036d6f6404666f6f310000036d6f6404666f6f320000030201"
"000a0901070041aa80a8010b");

constexpr auto host_foo1 = [](Instance&, span<const Value> args, int) {
constexpr auto host_foo1 = [](Instance&, const Value* args, int) {
return Value{as_uint32(args[0]) + as_uint32(args[1])};
};
constexpr auto host_foo2 = [](Instance&, span<const Value> args, int) {
constexpr auto host_foo2 = [](Instance&, const Value* args, int) {
return Value{as_uint32(args[0]) * as_uint32(args[1])};
};

Expand All @@ -836,31 +836,6 @@ TEST(execute, imported_functions_and_regular_one)
EXPECT_THAT(execute(*instance, 1, {20, 10}), Result(200));
}

TEST(execute, imported_functions_count_args)
{
/* wat2wasm
(type (func (param i32 i32) (result i32)))
(type (func (param i32) (result i32)))
(import "mod" "foo1" (func (type 0)))
(import "mod" "foo2" (func (type 1)))
*/
const auto wasm = from_hex(
"0061736d01000000010c0260027f7f017f60017f017f021702036d6f6404666f6f310000036d6f6404666f6f32"
"0001");

// Check if correct number of arguments is passed to host functions.
constexpr auto count_args = [](Instance&, span<const Value> args, int) {
return Value{args.size()};
};

const auto module = parse(wasm);
ASSERT_EQ(module->typesec.size(), 2);
auto instance_counter =
instantiate(*module, {{count_args, module->typesec[0]}, {count_args, module->typesec[1]}});
EXPECT_THAT(execute(*instance_counter, 0, {20, 22}), Result(2));
EXPECT_THAT(execute(*instance_counter, 1, {20}), Result(1));
}

TEST(execute, imported_two_functions_different_type)
{
/* wat2wasm
Expand All @@ -876,10 +851,10 @@ TEST(execute, imported_two_functions_different_type)
"0061736d01000000010c0260027f7f017f60017e017e021702036d6f6404666f6f310000036d6f6404666f6f32"
"0001030201010a0901070042aa80a8010b");

constexpr auto host_foo1 = [](Instance&, span<const Value> args, int) {
constexpr auto host_foo1 = [](Instance&, const Value* args, int) {
return Value{as_uint32(args[0]) + as_uint32(args[1])};
};
constexpr auto host_foo2 = [](Instance&, span<const Value> args, int) {
constexpr auto host_foo2 = [](Instance&, const Value* args, int) {
return Value{args[0].i64 * args[0].i64};
};

Expand All @@ -900,9 +875,7 @@ TEST(execute, imported_function_traps)
*/
const auto wasm = from_hex("0061736d0100000001070160027f7f017f020b01036d6f6403666f6f0000");

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

const auto module = parse(wasm);
auto instance = instantiate(*module, {{host_foo, module->typesec[0]}});
Expand Down
12 changes: 6 additions & 6 deletions test/unittests/instantiate_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ TEST(instantiate, imported_functions)
const auto bin = from_hex("0061736d0100000001060160017f017f020b01036d6f6403666f6f0000");
const auto module = parse(bin);

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

ASSERT_EQ(instance->imported_functions.size(), 1);
Expand All @@ -53,8 +53,8 @@ TEST(instantiate, imported_functions_multiple)
"0061736d0100000001090260017f017f600000021702036d6f6404666f6f310000036d6f6404666f6f320001");
const auto module = parse(bin);

auto host_foo1 = [](Instance&, span<const Value>, int) { return Trap; };
auto host_foo2 = [](Instance&, span<const Value>, int) { return Trap; };
auto host_foo1 = [](Instance&, const Value*, int) { return Trap; };
auto host_foo2 = [](Instance&, const Value*, int) { return Trap; };
auto instance =
instantiate(*module, {{host_foo1, module->typesec[0]}, {host_foo2, module->typesec[1]}});

Expand Down Expand Up @@ -87,7 +87,7 @@ TEST(instantiate, imported_function_wrong_type)
*/
const auto bin = from_hex("0061736d0100000001060160017f017f020b01036d6f6403666f6f0000");

auto host_foo = [](Instance&, span<const Value>, int) { return Trap; };
auto host_foo = [](Instance&, const Value*, int) { return Trap; };
const auto host_foo_type = FuncType{{}, {}};

EXPECT_THROW_MESSAGE(instantiate(parse(bin), {{host_foo, host_foo_type}}), instantiate_error,
Expand Down Expand Up @@ -637,7 +637,7 @@ TEST(instantiate, element_section_fills_imported_table)
"0061736d010000000105016000017f020b01016d037461620170000403050400000000090f020041010b020001"
"0041020b0202030a1504040041010b040041020b040041030b040041040b");

auto f0 = [](Instance&, span<const Value>, int) { return Value{0}; };
auto f0 = [](Instance&, const Value*, int) { return Value{0}; };

table_elements table(4);
table[0] = ExternalFunction{f0, FuncType{{}, {ValType::i32}}};
Expand All @@ -664,7 +664,7 @@ TEST(instantiate, element_section_out_of_bounds_doesnt_change_imported_table)
"0061736d010000000105016000017f020b01016d037461620170000303020100090f020041000b020000004102"
"0b0200000a0601040041010b");

auto f0 = [](Instance&, span<const Value>, int) { return Value{0}; };
auto f0 = [](Instance&, const Value*, int) { return Value{0}; };

table_elements table(3);
table[0] = ExternalFunction{f0, FuncType{{}, {ValType::i32}}};
Expand Down
2 changes: 1 addition & 1 deletion test/utils/fizzy_engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ FuncType translate_signature(std::string_view signature)
return func_type;
}

fizzy::ExecutionResult env_adler32(fizzy::Instance& instance, fizzy::span<const Value> args, int)
fizzy::ExecutionResult env_adler32(fizzy::Instance& instance, const fizzy::Value* args, int)
{
assert(instance.memory != nullptr);
const auto ret = fizzy::test::adler32(
Expand Down
Loading

0 comments on commit 626ac4a

Please sign in to comment.