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
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
43 changes: 41 additions & 2 deletions include/fizzy/fizzy.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -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.
Expand All @@ -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.
Expand All @@ -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.
Expand All @@ -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.
Expand All @@ -213,6 +243,15 @@ uint8_t* fizzy_get_instance_memory_data(FizzyInstance* instance);
/// @note Function returns memory size regardless of whether memory is exported or not.
size_t fizzy_get_instance_memory_size(FizzyInstance* instance);

/// Find exported table by name.
///
/// @param instance Pointer to 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.
bool fizzy_find_exported_table(
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.

I was going to say why isn't this grouped with find_exported_function, but realised that is over the module. This still confuses me in our API, both C++ and in C.

I think perhaps it would be clearer all these are instance related and later we could add some module inspection features.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, I put them separately, because this one operates on instance.

The change in #633 adds another fizzy_find_exported_function, that operates on instance and would be convenient, when you need to get an exported function and import it into another instance. With it there's going to be 4 similar fizzy_find_exported_* as in C++ API.
(However it has some complications with managing the lifetime of capture, so I'm not completely sure it's a good idea)
The function operating on module is renamed there to fizzy_find_exported_function_index, which better reflects what it does.

FizzyInstance* instance, const char* name, FizzyExternalTable* out_table);

/// Find exported global by name.
///
/// @param instance Pointer to instance.
Expand Down
61 changes: 56 additions & 5 deletions lib/fizzy/capi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,42 @@ inline std::vector<fizzy::ImportedFunction> unwrap(
return imported_functions;
}

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

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

inline FizzyLimits wrap(const fizzy::Limits& limits) noexcept
{
return {limits.min, (limits.max.has_value() ? *limits.max : 0), limits.max.has_value()};
}

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

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

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};
Expand Down Expand Up @@ -247,6 +283,17 @@ bool fizzy_find_exported_function(
return true;
}

bool fizzy_find_exported_table(
FizzyInstance* instance, const char* name, FizzyExternalTable* out_table)
{
const auto optional_external_table = fizzy::find_exported_table(*unwrap(instance), name);
if (!optional_external_table)
return false;

*out_table = wrap(*optional_external_table);
return true;
}

bool fizzy_find_exported_global(
FizzyInstance* instance, const char* name, FizzyExternalGlobal* out_global)
{
Expand All @@ -260,15 +307,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());
}
Expand All @@ -280,18 +329,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());
}
Expand Down
Loading