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

capi: imported and exported tables #628

Merged
merged 3 commits into from
Nov 3, 2020
Merged
Changes from 1 commit
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
Next Next commit
capi: Add imported table to instantiate
gumb0 committed Nov 3, 2020
commit e83e795b5395e5acc94130ebfa3aeda6463f32c1
34 changes: 32 additions & 2 deletions include/fizzy/fizzy.h
Original file line number Diff line number Diff line change
@@ -87,6 +87,30 @@ typedef struct FizzyGlobalType
bool is_mutable;
} FizzyGlobalType;

/// The opaque data type representing a table.
typedef struct FizzyTable FizzyTable;

/// Limits.
typedef struct FizzyLimits
{
/// Minimum value.
uint32_t min;
/// Maximum value.
/// Valid only if has_max equals true.
uint32_t max;
/// Whether limits has maximum value.
bool has_max;
} FizzyLimits;

/// External table.
typedef struct FizzyExternalTable
{
/// Opaque pointer to table data.
FizzyTable* table;
/// Table limits.
FizzyLimits limits;
} FizzyExternalTable;

/// External global.
typedef struct FizzyExternalGlobal
{
@@ -147,6 +171,8 @@ bool fizzy_find_exported_function(
/// @param imported_functions Pointer to the imported function array. Can be NULL iff
/// imported_functions_size equals 0.
/// @param imported_functions_size Size of the imported function array. Can be zero.
/// @param imported_table Pointer to the imported table. Can be NULL iff module
/// doesn't import a table.
/// @param imported_globals Pointer to the imported globals array. Can be NULL iff
/// imported_globals_size equals 0.
/// @param imported_globals_size Size of the imported global array. Can be zero.
@@ -164,7 +190,8 @@ bool fizzy_find_exported_function(
/// module, behaviour is undefined.
FizzyInstance* fizzy_instantiate(const FizzyModule* module,
const FizzyExternalFunction* imported_functions, size_t imported_functions_size,
const FizzyExternalGlobal* imported_globals, size_t imported_globals_size);
const FizzyExternalTable* imported_table, const FizzyExternalGlobal* imported_globals,
size_t imported_globals_size);

/// Instantiate a module resolving imported functions.
/// Takes ownership of module, i.e. @p module is invalidated after this call.
@@ -173,6 +200,8 @@ FizzyInstance* fizzy_instantiate(const FizzyModule* module,
/// @param imported_functions Pointer to the imported function array. Can be NULL iff
/// imported_functions_size equals 0.
/// @param imported_functions_size Size of the imported function array. Can be zero.
/// @param imported_table Pointer to the imported table. Can be NULL iff module
/// doesn't import a table.
/// @param imported_globals Pointer to the imported globals array. Can be NULL iff
/// imported_globals_size equals 0.
/// @param imported_globals_size Size of the imported global array. Can be zero.
@@ -189,7 +218,8 @@ FizzyInstance* fizzy_instantiate(const FizzyModule* module,
/// module, behaviour is undefined.
FizzyInstance* fizzy_resolve_instantiate(const FizzyModule* module,
const FizzyImportedFunction* imported_functions, size_t imported_functions_size,
const FizzyExternalGlobal* imported_globals, size_t imported_globals_size);
const FizzyExternalTable* imported_table, const FizzyExternalGlobal* imported_globals,
size_t imported_globals_size);

/// Free resources associated with the instance.
/// If passed pointer is NULL, has no effect.
35 changes: 30 additions & 5 deletions lib/fizzy/capi.cpp
Original file line number Diff line number Diff line change
@@ -168,6 +168,27 @@ inline std::vector<fizzy::ImportedFunction> unwrap(
return imported_functions;
}

inline fizzy::table_elements* unwrap(FizzyTable* table) noexcept
{
return reinterpret_cast<fizzy::table_elements*>(table);
}

inline fizzy::Limits unwrap(const FizzyLimits& limits) noexcept
{
return {limits.min, limits.has_max ? std::make_optional(limits.max) : std::nullopt};
}

inline fizzy::ExternalTable unwrap(const FizzyExternalTable& external_table) noexcept
{
return {unwrap(external_table.table), unwrap(external_table.limits)};
}

inline std::vector<fizzy::ExternalTable> unwrap(const FizzyExternalTable* external_table)
{
return external_table ? std::vector<fizzy::ExternalTable>{unwrap(*external_table)} :
std::vector<fizzy::ExternalTable>{};
Copy link
Member

@axic axic Nov 3, 2020

Choose a reason for hiding this comment

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

Cannot just {} work here? And same with {unwrap(...)}?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No, error: initializer list cannot be used on the right hand side of operator '?'

}

inline FizzyGlobalType wrap(const fizzy::GlobalType& global_type) noexcept
{
return {wrap(global_type.value_type), global_type.is_mutable};
@@ -260,15 +281,17 @@ bool fizzy_find_exported_global(

FizzyInstance* fizzy_instantiate(const FizzyModule* module,
const FizzyExternalFunction* imported_functions, size_t imported_functions_size,
const FizzyExternalGlobal* imported_globals, size_t imported_globals_size)
const FizzyExternalTable* imported_table, const FizzyExternalGlobal* imported_globals,
size_t imported_globals_size)
{
try
{
auto functions = unwrap(imported_functions, imported_functions_size);
auto table = unwrap(imported_table);
auto globals = unwrap(imported_globals, imported_globals_size);

auto instance = fizzy::instantiate(std::unique_ptr<const fizzy::Module>(unwrap(module)),
std::move(functions), {}, {}, std::move(globals));
std::move(functions), std::move(table), {}, std::move(globals));

return wrap(instance.release());
}
@@ -280,18 +303,20 @@ FizzyInstance* fizzy_instantiate(const FizzyModule* module,

FizzyInstance* fizzy_resolve_instantiate(const FizzyModule* c_module,
const FizzyImportedFunction* c_imported_functions, size_t imported_functions_size,
const FizzyExternalGlobal* imported_globals, size_t imported_globals_size)
const FizzyExternalTable* imported_table, const FizzyExternalGlobal* imported_globals,
size_t imported_globals_size)
{
try
{
auto imported_functions = unwrap(c_imported_functions, imported_functions_size);
auto table = unwrap(imported_table);
auto globals = unwrap(imported_globals, imported_globals_size);

std::unique_ptr<const fizzy::Module> module{unwrap(c_module)};
auto resolved_imports = fizzy::resolve_imported_functions(*module, imported_functions);

auto instance = fizzy::instantiate(
std::move(module), std::move(resolved_imports), {}, {}, std::move(globals));
auto instance = fizzy::instantiate(std::move(module), std::move(resolved_imports),
std::move(table), {}, std::move(globals));

return wrap(instance.release());
}
56 changes: 28 additions & 28 deletions test/unittests/capi_test.cpp
Original file line number Diff line number Diff line change
@@ -115,7 +115,7 @@ TEST(capi, find_exported_global)
auto module = fizzy_parse(wasm.data(), wasm.size());
ASSERT_NE(module, nullptr);

auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, 0);
auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, 0);
ASSERT_NE(instance, nullptr);

FizzyExternalGlobal global;
@@ -138,7 +138,7 @@ TEST(capi, instantiate)
auto module = fizzy_parse(wasm_prefix, sizeof(wasm_prefix));
ASSERT_NE(module, nullptr);

auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, 0);
auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, 0);
EXPECT_NE(instance, nullptr);

fizzy_free_instance(instance);
@@ -153,7 +153,7 @@ TEST(capi, instantiate_imported_function)
auto module = fizzy_parse(wasm.data(), wasm.size());
ASSERT_NE(module, nullptr);

EXPECT_EQ(fizzy_instantiate(module, nullptr, 0, nullptr, 0), nullptr);
EXPECT_EQ(fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, 0), nullptr);

module = fizzy_parse(wasm.data(), wasm.size());
ASSERT_NE(module, nullptr);
@@ -164,7 +164,7 @@ TEST(capi, instantiate_imported_function)
},
nullptr}};

auto instance = fizzy_instantiate(module, host_funcs, 1, nullptr, 0);
auto instance = fizzy_instantiate(module, host_funcs, 1, nullptr, nullptr, 0);
EXPECT_NE(instance, nullptr);

fizzy_free_instance(instance);
@@ -199,7 +199,7 @@ TEST(capi, instantiate_imported_globals)
{&g2, {FizzyValueTypeI64, false}}, {&g3, {FizzyValueTypeF32, false}},
{&g4, {FizzyValueTypeF64, true}}};

auto instance = fizzy_instantiate(module, nullptr, 0, globals, 4);
auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, globals, 4);
EXPECT_NE(instance, nullptr);

EXPECT_THAT(fizzy_execute(instance, 0, nullptr, 0), CResult(42));
@@ -212,12 +212,12 @@ TEST(capi, instantiate_imported_globals)
// No globals provided.
module = fizzy_parse(wasm.data(), wasm.size());
ASSERT_NE(module, nullptr);
EXPECT_EQ(fizzy_instantiate(module, nullptr, 0, nullptr, 0), nullptr);
EXPECT_EQ(fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, 0), nullptr);

// Not enough globals provided.
module = fizzy_parse(wasm.data(), wasm.size());
ASSERT_NE(module, nullptr);
EXPECT_EQ(fizzy_instantiate(module, nullptr, 0, globals, 3), nullptr);
EXPECT_EQ(fizzy_instantiate(module, nullptr, 0, nullptr, globals, 3), nullptr);

// Incorrect order or globals.
module = fizzy_parse(wasm.data(), wasm.size());
@@ -227,7 +227,7 @@ TEST(capi, instantiate_imported_globals)
{&g2, {FizzyValueTypeI64, false}}, {&g4, {FizzyValueTypeF64, true}},
{&g3, {FizzyValueTypeF32, false}}};

EXPECT_EQ(fizzy_instantiate(module, nullptr, 0, globals_incorrect_order, 4), nullptr);
EXPECT_EQ(fizzy_instantiate(module, nullptr, 0, nullptr, globals_incorrect_order, 4), nullptr);

// Global type mismatch.
module = fizzy_parse(wasm.data(), wasm.size());
@@ -237,7 +237,7 @@ TEST(capi, instantiate_imported_globals)
{&g2, {FizzyValueTypeI64, false}}, {&g3, {FizzyValueTypeF32, false}},
{&g4, {FizzyValueTypeF64, true}}};

EXPECT_EQ(fizzy_instantiate(module, nullptr, 0, globals_type_mismatch, 4), nullptr);
EXPECT_EQ(fizzy_instantiate(module, nullptr, 0, nullptr, globals_type_mismatch, 4), nullptr);
}

TEST(capi, resolve_instantiate_no_imports)
@@ -249,7 +249,7 @@ TEST(capi, resolve_instantiate_no_imports)
auto module = fizzy_parse(wasm.data(), wasm.size());
ASSERT_NE(module, nullptr);

auto instance = fizzy_resolve_instantiate(module, nullptr, 0, nullptr, 0);
auto instance = fizzy_resolve_instantiate(module, nullptr, 0, nullptr, nullptr, 0);
EXPECT_NE(instance, nullptr);

fizzy_free_instance(instance);
@@ -262,7 +262,7 @@ TEST(capi, resolve_instantiate_no_imports)
[](void*, FizzyInstance*, const FizzyValue*, int) { return FizzyExecutionResult{}; },
nullptr}}};

instance = fizzy_resolve_instantiate(module, host_funcs, 1, nullptr, 0);
instance = fizzy_resolve_instantiate(module, host_funcs, 1, nullptr, nullptr, 0);
EXPECT_NE(instance, nullptr);

fizzy_free_instance(instance);
@@ -282,7 +282,7 @@ TEST(capi, resolve_instantiate)
auto module = fizzy_parse(wasm.data(), wasm.size());
ASSERT_NE(module, nullptr);

EXPECT_EQ(fizzy_instantiate(module, nullptr, 0, nullptr, 0), nullptr);
EXPECT_EQ(fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, 0), nullptr);

module = fizzy_parse(wasm.data(), wasm.size());
ASSERT_NE(module, nullptr);
@@ -305,7 +305,7 @@ TEST(capi, resolve_instantiate)
FizzyImportedFunction host_funcs[] = {{"mod1", "foo1", mod1foo1}, {"mod1", "foo2", mod1foo2},
{"mod2", "foo1", mod2foo1}, {"mod2", "foo2", mod2foo2}};

auto instance = fizzy_resolve_instantiate(module, host_funcs, 4, nullptr, 0);
auto instance = fizzy_resolve_instantiate(module, host_funcs, 4, nullptr, nullptr, 0);
EXPECT_NE(instance, nullptr);
fizzy_free_instance(instance);

@@ -314,7 +314,7 @@ TEST(capi, resolve_instantiate)
ASSERT_NE(module, nullptr);
FizzyImportedFunction host_funcs_reordered[] = {{"mod1", "foo2", mod1foo2},
{"mod2", "foo1", mod2foo1}, {"mod2", "foo2", mod2foo2}, {"mod1", "foo1", mod1foo1}};
instance = fizzy_resolve_instantiate(module, host_funcs_reordered, 4, nullptr, 0);
instance = fizzy_resolve_instantiate(module, host_funcs_reordered, 4, nullptr, nullptr, 0);
EXPECT_NE(instance, nullptr);
fizzy_free_instance(instance);

@@ -324,14 +324,14 @@ TEST(capi, resolve_instantiate)
FizzyImportedFunction host_funcs_extra[] = {{"mod1", "foo1", mod1foo1},
{"mod1", "foo2", mod1foo2}, {"mod2", "foo1", mod2foo1}, {"mod2", "foo2", mod2foo2},
{"mod3", "foo1", mod1foo1}};
instance = fizzy_resolve_instantiate(module, host_funcs_extra, 4, nullptr, 0);
instance = fizzy_resolve_instantiate(module, host_funcs_extra, 4, nullptr, nullptr, 0);
EXPECT_NE(instance, nullptr);
fizzy_free_instance(instance);

// not enough functions
module = fizzy_parse(wasm.data(), wasm.size());
ASSERT_NE(module, nullptr);
EXPECT_EQ(fizzy_resolve_instantiate(module, host_funcs, 3, nullptr, 0), nullptr);
EXPECT_EQ(fizzy_resolve_instantiate(module, host_funcs, 3, nullptr, nullptr, 0), nullptr);
}

TEST(capi, free_instance_null)
@@ -348,7 +348,7 @@ TEST(capi, get_instance_module)
auto module = fizzy_parse(wasm.data(), wasm.size());
ASSERT_NE(module, nullptr);

auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, 0);
auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, 0);
ASSERT_NE(instance, nullptr);

auto instance_module = fizzy_get_instance_module(instance);
@@ -368,7 +368,7 @@ TEST(capi, memory_access_no_memory)
auto module = fizzy_parse(wasm.data(), wasm.size());
ASSERT_NE(module, nullptr);

auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, 0);
auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, 0);
ASSERT_NE(instance, nullptr);

EXPECT_EQ(fizzy_get_instance_memory_data(instance), nullptr);
@@ -393,7 +393,7 @@ TEST(capi, memory_access)
auto module = fizzy_parse(wasm.data(), wasm.size());
ASSERT_NE(module, nullptr);

auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, 0);
auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, 0);
ASSERT_NE(instance, nullptr);

uint8_t* memory = fizzy_get_instance_memory_data(instance);
@@ -420,7 +420,7 @@ TEST(capi, imported_memory_access)
auto module = fizzy_parse(wasm.data(), wasm.size());
ASSERT_NE(module, nullptr);

auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, 0);
auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, 0);
EXPECT_EQ(instance, nullptr);
}

@@ -441,7 +441,7 @@ TEST(capi, execute)
auto module = fizzy_parse(wasm.data(), wasm.size());
ASSERT_NE(module, nullptr);

auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, 0);
auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, 0);
ASSERT_NE(instance, nullptr);

EXPECT_THAT(fizzy_execute(instance, 0, nullptr, 0), CResult());
@@ -478,7 +478,7 @@ TEST(capi, execute_with_host_function)
},
nullptr}};

auto instance = fizzy_instantiate(module, host_funcs, 2, nullptr, 0);
auto instance = fizzy_instantiate(module, host_funcs, 2, nullptr, nullptr, 0);
ASSERT_NE(instance, nullptr);

EXPECT_THAT(fizzy_execute(instance, 0, nullptr, 0), CResult(42));
@@ -508,7 +508,7 @@ TEST(capi, imported_function_traps)
},
nullptr}};

auto instance = fizzy_instantiate(module, host_funcs, 1, nullptr, 0);
auto instance = fizzy_instantiate(module, host_funcs, 1, nullptr, nullptr, 0);
ASSERT_NE(instance, nullptr);

EXPECT_THAT(fizzy_execute(instance, 1, nullptr, 0), CTraps());
@@ -537,7 +537,7 @@ TEST(capi, imported_function_void)
},
&called}};

auto instance = fizzy_instantiate(module, host_funcs, 1, nullptr, 0);
auto instance = fizzy_instantiate(module, host_funcs, 1, nullptr, nullptr, 0);
ASSERT_NE(instance, nullptr);

EXPECT_THAT(fizzy_execute(instance, 1, nullptr, 0), CResult());
@@ -561,7 +561,7 @@ TEST(capi, imported_function_from_another_module)
"0061736d0100000001070160027f7f017f030201000707010373756200000a09010700200020016b0b");
auto module1 = fizzy_parse(bin1.data(), bin1.size());
ASSERT_NE(module1, nullptr);
auto instance1 = fizzy_instantiate(module1, nullptr, 0, nullptr, 0);
auto instance1 = fizzy_instantiate(module1, nullptr, 0, nullptr, nullptr, 0);
ASSERT_NE(instance1, nullptr);

/* wat2wasm
@@ -598,7 +598,7 @@ TEST(capi, imported_function_from_another_module)

FizzyExternalFunction host_funcs[] = {{{FizzyValueTypeI32, &inputs[0], 2}, sub, &host_context}};

auto instance2 = fizzy_instantiate(module2, host_funcs, 1, nullptr, 0);
auto instance2 = fizzy_instantiate(module2, host_funcs, 1, nullptr, nullptr, 0);
ASSERT_NE(instance2, nullptr);

FizzyValue args[] = {{44}, {2}};
@@ -616,7 +616,7 @@ TEST(capi, imported_global_from_another_module)
const auto bin1 = from_hex("0061736d010000000606017f00412a0b07050101670300");
auto module1 = fizzy_parse(bin1.data(), bin1.size());
ASSERT_NE(module1, nullptr);
auto instance1 = fizzy_instantiate(module1, nullptr, 0, nullptr, 0);
auto instance1 = fizzy_instantiate(module1, nullptr, 0, nullptr, nullptr, 0);
ASSERT_NE(instance1, nullptr);

/* wat2wasm
@@ -635,7 +635,7 @@ TEST(capi, imported_global_from_another_module)
FizzyExternalGlobal global;
ASSERT_TRUE(fizzy_find_exported_global(instance1, "g", &global));

auto instance2 = fizzy_instantiate(module2, nullptr, 0, &global, 1);
auto instance2 = fizzy_instantiate(module2, nullptr, 0, nullptr, &global, 1);
ASSERT_NE(instance2, nullptr);

EXPECT_THAT(fizzy_execute(instance2, 0, nullptr, 0), CResult(42));
2 changes: 1 addition & 1 deletion test/utils/fizzy_c_engine.cpp
Original file line number Diff line number Diff line change
@@ -64,7 +64,7 @@ bool FizzyCEngine::instantiate(bytes_view wasm_binary)
FizzyValueType inputs[] = {FizzyValueTypeI32, FizzyValueTypeI32};
FizzyImportedFunction imports[] = {
{"env", "adler32", {{FizzyValueTypeI32, inputs, 2}, env_adler32, nullptr}}};
m_instance.reset(fizzy_resolve_instantiate(module, imports, 1, nullptr, 0));
m_instance.reset(fizzy_resolve_instantiate(module, imports, 1, nullptr, nullptr, 0));

return (m_instance != nullptr);
}