Skip to content
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

Pass arguments to host function as const Value* #574

Merged
merged 2 commits into from
Oct 14, 2020
Merged
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
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;
Copy link
Member

Choose a reason for hiding this comment

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

Didn't I do the same change in some PR already? Perhaps one of your old refactorings.


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