Skip to content

capi: imported and exported memory #631

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

Merged
merged 3 commits into from
Nov 5, 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
45 changes: 39 additions & 6 deletions include/fizzy/fizzy.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,18 @@ typedef struct FizzyExternalTable
FizzyLimits limits;
} FizzyExternalTable;

/// The opaque data type representing a memory.
typedef struct FizzyMemory FizzyMemory;

/// External memory.
typedef struct FizzyExternalMemory
{
/// Opaque pointer to memory data.
FizzyMemory* memory;
/// Memory limits.
FizzyLimits limits;
} FizzyExternalMemory;

/// External global.
typedef struct FizzyExternalGlobal
{
Expand Down Expand Up @@ -172,7 +184,11 @@ bool fizzy_find_exported_function(
/// 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.
/// doesn't import a table. Not an array, because Wasm 1.0
/// doesn't support more than one table in a module.
/// @param imported_memory Pointer to the imported memory. Can be NULL iff module
/// doesn't import a memory. Not an array, because Wasm 1.0
/// doesn't support more than one memory in a module.
/// @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.
Expand All @@ -190,8 +206,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 FizzyExternalTable* imported_table, const FizzyExternalGlobal* imported_globals,
size_t imported_globals_size);
const FizzyExternalTable* imported_table, const FizzyExternalMemory* imported_memory,
Copy link
Member

Choose a reason for hiding this comment

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

The C++ API supports a vector of tables and memories, while the C API only supports a singular for both. While both can be at most one in wasm 1.0, there is a discrepancy between the two APIs.

Perhaps should also comment about this, as it may be confused to those familiar with the wasm spec.

In short: I think we should support a single table/memory in the C API as we can make a breaking API release if we do start supporting newer wasm versions. I would be inclined to say the same restriction would make sense in C++. Perhaps just open a tracking issue about this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Copy link
Collaborator

Choose a reason for hiding this comment

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

I agree on having single table/memory.

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.
Expand All @@ -201,7 +217,11 @@ FizzyInstance* fizzy_instantiate(const FizzyModule* module,
/// 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.
/// doesn't import a table. Not an array, because Wasm 1.0
/// doesn't support more than one table in a module.
/// @param imported_memory Pointer to the imported memory. Can be NULL iff module
/// doesn't import a memory. Not an array, because Wasm 1.0
/// doesn't support more than one memory in a module.
/// @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.
Expand All @@ -218,8 +238,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 FizzyExternalTable* imported_table, const FizzyExternalGlobal* imported_globals,
size_t imported_globals_size);
const FizzyExternalTable* imported_table, const FizzyExternalMemory* imported_memory,
const FizzyExternalGlobal* imported_globals, size_t imported_globals_size);

/// Free resources associated with the instance.
/// If passed pointer is NULL, has no effect.
Expand Down Expand Up @@ -249,9 +269,22 @@ size_t fizzy_get_instance_memory_size(FizzyInstance* instance);
/// @param name The table name. NULL-terminated string. Cannot be NULL.
/// @param out_table Pointer to output struct to store found table. Cannot be NULL.
/// @returns true if table was found, false otherwise.
///
/// @note Wasm 1.0 spec allows at most one table in a module.
bool fizzy_find_exported_table(
FizzyInstance* instance, const char* name, FizzyExternalTable* out_table);

/// Find exported memory by name.
///
/// @param instance Pointer to instance.
/// @param name The table name. NULL-terminated string. Cannot be NULL.
/// @param out_memory Pointer to output struct to store found memory. Cannot be NULL.
/// @returns true if memory was found, false otherwise.
///
/// @note Wasm 1.0 spec allows at most one memory in a module.
bool fizzy_find_exported_memory(
FizzyInstance* instance, const char* name, FizzyExternalMemory* out_memory);

/// Find exported global by name.
///
/// @param instance Pointer to instance.
Expand Down
51 changes: 45 additions & 6 deletions lib/fizzy/capi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,16 @@ inline fizzy::table_elements* unwrap(FizzyTable* table) noexcept
return reinterpret_cast<fizzy::table_elements*>(table);
}

inline FizzyMemory* wrap(fizzy::bytes* memory) noexcept
{
return reinterpret_cast<FizzyMemory*>(memory);
}

inline fizzy::bytes* unwrap(FizzyMemory* memory) noexcept
{
return reinterpret_cast<fizzy::bytes*>(memory);
}

inline FizzyLimits wrap(const fizzy::Limits& limits) noexcept
{
return {limits.min, (limits.max.has_value() ? *limits.max : 0), limits.max.has_value()};
Expand All @@ -198,12 +208,28 @@ inline fizzy::ExternalTable unwrap(const FizzyExternalTable& external_table) noe
return {unwrap(external_table.table), unwrap(external_table.limits)};
}

inline FizzyExternalMemory wrap(const fizzy::ExternalMemory& external_memory) noexcept
{
return {wrap(external_memory.data), wrap(external_memory.limits)};
}

inline fizzy::ExternalMemory unwrap(const FizzyExternalMemory& external_memory) noexcept
{
return {unwrap(external_memory.memory), unwrap(external_memory.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>{};
}

inline std::vector<fizzy::ExternalMemory> unwrap(const FizzyExternalMemory* external_memory)
{
return external_memory ? std::vector<fizzy::ExternalMemory>{unwrap(*external_memory)} :
std::vector<fizzy::ExternalMemory>{};
}

inline FizzyGlobalType wrap(const fizzy::GlobalType& global_type) noexcept
{
return {wrap(global_type.value_type), global_type.is_mutable};
Expand Down Expand Up @@ -294,6 +320,17 @@ bool fizzy_find_exported_table(
return true;
}

bool fizzy_find_exported_memory(
FizzyInstance* instance, const char* name, FizzyExternalMemory* out_memory)
{
const auto optional_external_memory = fizzy::find_exported_memory(*unwrap(instance), name);
if (!optional_external_memory)
return false;

*out_memory = wrap(*optional_external_memory);
return true;
}

bool fizzy_find_exported_global(
FizzyInstance* instance, const char* name, FizzyExternalGlobal* out_global)
{
Expand All @@ -307,17 +344,18 @@ bool fizzy_find_exported_global(

FizzyInstance* fizzy_instantiate(const FizzyModule* module,
const FizzyExternalFunction* imported_functions, size_t imported_functions_size,
const FizzyExternalTable* imported_table, const FizzyExternalGlobal* imported_globals,
size_t imported_globals_size)
const FizzyExternalTable* imported_table, const FizzyExternalMemory* imported_memory,
const FizzyExternalGlobal* imported_globals, size_t imported_globals_size)
{
try
{
auto functions = unwrap(imported_functions, imported_functions_size);
auto table = unwrap(imported_table);
auto memory = unwrap(imported_memory);
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(table), {}, std::move(globals));
std::move(functions), std::move(table), std::move(memory), std::move(globals));

return wrap(instance.release());
}
Expand All @@ -329,20 +367,21 @@ 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 FizzyExternalTable* imported_table, const FizzyExternalGlobal* imported_globals,
size_t imported_globals_size)
const FizzyExternalTable* imported_table, const FizzyExternalMemory* imported_memory,
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 memory = unwrap(imported_memory);
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(table), {}, std::move(globals));
std::move(table), std::move(memory), std::move(globals));

return wrap(instance.release());
}
Expand Down
Loading