-
Notifications
You must be signed in to change notification settings - Fork 34
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: Import inspection functions #683
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -140,6 +140,38 @@ typedef struct FizzyExternalGlobal | |||||||
FizzyGlobalType type; | ||||||||
} FizzyExternalGlobal; | ||||||||
|
||||||||
/// External kind. | ||||||||
typedef enum FizzyExternalKind | ||||||||
{ | ||||||||
FizzyExternalKindFunction, | ||||||||
FizzyExternalKindTable, | ||||||||
FizzyExternalKindMemory, | ||||||||
FizzyExternalKindGlobal | ||||||||
} FizzyExternalKind; | ||||||||
|
||||||||
/// Import description. | ||||||||
/// | ||||||||
/// @note Only one member of #desc union corresponding to #kind is defined for each import. | ||||||||
/// @note For the lifetime of the #module and #kind fields, please refer to the description provided | ||||||||
/// by the function used to obtain this structure. | ||||||||
typedef struct FizzyImportDescription | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need to mention the lifetime of module/name here? It is explained in Perhaps what we could note here is that the user should refer to the documentation from the function returning this value about lifetimes:
Suggested change
Is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, |
||||||||
{ | ||||||||
/// Import's module name. | ||||||||
const char* module; | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||
/// Import name. | ||||||||
const char* name; | ||||||||
/// Import kind. | ||||||||
FizzyExternalKind kind; | ||||||||
/// Import type definition. | ||||||||
union | ||||||||
{ | ||||||||
FizzyFunctionType function_type; | ||||||||
FizzyLimits memory_limits; | ||||||||
FizzyLimits table_limits; | ||||||||
FizzyGlobalType global_type; | ||||||||
} desc; | ||||||||
} FizzyImportDescription; | ||||||||
|
||||||||
/// Imported function. | ||||||||
typedef struct FizzyImportedFunction | ||||||||
{ | ||||||||
|
@@ -198,6 +230,23 @@ uint32_t fizzy_get_type_count(const FizzyModule* module); | |||||||
/// @return Type corresponding to the index. | ||||||||
FizzyFunctionType fizzy_get_type(const FizzyModule* module, uint32_t type_idx); | ||||||||
|
||||||||
/// Get number of imports defined in the module. | ||||||||
/// | ||||||||
/// @param module Pointer to module. Cannot be NULL. | ||||||||
/// @return Number of imports in the module. | ||||||||
uint32_t fizzy_get_import_count(const FizzyModule* module); | ||||||||
|
||||||||
/// Get the import description defined in the module. | ||||||||
/// | ||||||||
/// @param module Pointer to module. Cannot be NULL. | ||||||||
/// @param import_idx Import index. Behaviour is undefined if index is not valid according | ||||||||
/// to module definition. | ||||||||
/// @return Type of the import corresponding to the index. | ||||||||
/// FizzyImportDescription::module and FizzyImportDescription::name fields | ||||||||
/// point to the string stored inside the module and are valid as long as | ||||||||
/// module is alive (including after successful instantiation.) | ||||||||
FizzyImportDescription fizzy_get_import_description(const FizzyModule* module, uint32_t import_idx); | ||||||||
|
||||||||
/// Get type of the function defined in the module. | ||||||||
/// | ||||||||
/// @param module Pointer to module. Cannot be NULL. | ||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -282,6 +282,37 @@ inline std::vector<fizzy::ExternalGlobal> unwrap( | |
external_globals.begin(), unwrap_external_global_fn); | ||
return external_globals; | ||
} | ||
|
||
inline FizzyExternalKind wrap(fizzy::ExternalKind kind) noexcept | ||
{ | ||
return static_cast<FizzyExternalKind>(kind); | ||
} | ||
|
||
inline FizzyImportDescription wrap( | ||
const fizzy::Import& import, const fizzy::Module& module) noexcept | ||
{ | ||
FizzyImportDescription c_import_description; | ||
c_import_description.module = import.module.c_str(); | ||
c_import_description.name = import.name.c_str(); | ||
c_import_description.kind = wrap(import.kind); | ||
switch (c_import_description.kind) | ||
{ | ||
case FizzyExternalKindFunction: | ||
c_import_description.desc.function_type = | ||
wrap(module.typesec[import.desc.function_type_index]); | ||
break; | ||
case FizzyExternalKindTable: | ||
c_import_description.desc.table_limits = wrap(import.desc.table.limits); | ||
break; | ||
case FizzyExternalKindMemory: | ||
c_import_description.desc.memory_limits = wrap(import.desc.memory.limits); | ||
break; | ||
case FizzyExternalKindGlobal: | ||
c_import_description.desc.global_type = wrap(import.desc.global); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Never mind I see it includes both type and mutability. |
||
break; | ||
} | ||
return c_import_description; | ||
} | ||
} // namespace | ||
|
||
extern "C" { | ||
|
@@ -339,6 +370,18 @@ FizzyFunctionType fizzy_get_type(const FizzyModule* module, uint32_t type_idx) | |
return wrap(unwrap(module)->typesec[type_idx]); | ||
} | ||
|
||
uint32_t fizzy_get_import_count(const FizzyModule* module) | ||
{ | ||
return static_cast<uint32_t>(unwrap(module)->importsec.size()); | ||
} | ||
|
||
FizzyImportDescription fizzy_get_import_description( | ||
const FizzyModule* c_module, uint32_t import_idx) | ||
{ | ||
const auto* module = unwrap(c_module); | ||
return wrap(module->importsec[import_idx], *module); | ||
} | ||
|
||
FizzyFunctionType fizzy_get_function_type(const FizzyModule* module, uint32_t func_idx) | ||
{ | ||
return wrap(unwrap(module)->get_function_type(func_idx)); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1197,6 +1197,146 @@ TEST(capi, get_type) | |
fizzy_free_module(module_imported_func); | ||
} | ||
|
||
TEST(capi, get_import_count) | ||
{ | ||
/* wat2wasm | ||
(module) | ||
*/ | ||
const auto wasm_empty = from_hex("0061736d01000000"); | ||
|
||
const auto* module_empty = fizzy_parse(wasm_empty.data(), wasm_empty.size()); | ||
ASSERT_NE(module_empty, nullptr); | ||
|
||
EXPECT_EQ(fizzy_get_import_count(module_empty), 0); | ||
fizzy_free_module(module_empty); | ||
|
||
/* wat2wasm | ||
(func (import "m" "f") (result i32)) | ||
(global (import "m" "g") i32) | ||
(table (import "m" "t") 0 anyfunc) | ||
(memory (import "m" "m") 1) | ||
*/ | ||
const auto wasm = from_hex( | ||
"0061736d010000000105016000017f021d04016d01660000016d0167037f00016d017401700000016d016d0200" | ||
"01"); | ||
|
||
const auto* module = fizzy_parse(wasm.data(), wasm.size()); | ||
ASSERT_NE(module, nullptr); | ||
|
||
EXPECT_EQ(fizzy_get_import_count(module), 4); | ||
fizzy_free_module(module); | ||
} | ||
|
||
TEST(capi, get_import_description) | ||
{ | ||
/* wat2wasm | ||
(func (import "m" "f1")) | ||
(func (import "m" "f2") (result i32)) | ||
(func (import "m" "f3") (param i64)) | ||
(func (import "m" "f4") (param f32 f64) (result i64)) | ||
(global (import "m" "g1") i32) | ||
(global (import "m" "g2") (mut f64)) | ||
(table (import "m" "t") 10 anyfunc) | ||
(memory (import "m" "mem") 1 4) | ||
*/ | ||
const auto wasm = from_hex( | ||
"0061736d010000000112046000006000017f60017e0060027d7c017e023f08016d0266310000016d0266320001" | ||
"016d0266330002016d0266340003016d026731037f00016d026732037c01016d01740170000a016d036d656d02" | ||
"010104"); | ||
|
||
const auto* module = fizzy_parse(wasm.data(), wasm.size()); | ||
ASSERT_NE(module, nullptr); | ||
ASSERT_EQ(fizzy_get_import_count(module), 8); | ||
|
||
const auto import0 = fizzy_get_import_description(module, 0); | ||
EXPECT_STREQ(import0.module, "m"); | ||
EXPECT_STREQ(import0.name, "f1"); | ||
EXPECT_EQ(import0.kind, FizzyExternalKindFunction); | ||
EXPECT_EQ(import0.desc.function_type.inputs_size, 0); | ||
EXPECT_EQ(import0.desc.function_type.output, FizzyValueTypeVoid); | ||
|
||
const auto import1 = fizzy_get_import_description(module, 1); | ||
EXPECT_STREQ(import1.module, "m"); | ||
EXPECT_STREQ(import1.name, "f2"); | ||
EXPECT_EQ(import1.kind, FizzyExternalKindFunction); | ||
EXPECT_EQ(import1.desc.function_type.inputs_size, 0); | ||
EXPECT_EQ(import1.desc.function_type.output, FizzyValueTypeI32); | ||
|
||
const auto import2 = fizzy_get_import_description(module, 2); | ||
EXPECT_STREQ(import2.module, "m"); | ||
EXPECT_STREQ(import2.name, "f3"); | ||
EXPECT_EQ(import2.kind, FizzyExternalKindFunction); | ||
ASSERT_EQ(import2.desc.function_type.inputs_size, 1); | ||
EXPECT_EQ(import2.desc.function_type.inputs[0], FizzyValueTypeI64); | ||
EXPECT_EQ(import2.desc.function_type.output, FizzyValueTypeVoid); | ||
|
||
const auto import3 = fizzy_get_import_description(module, 3); | ||
EXPECT_STREQ(import3.module, "m"); | ||
EXPECT_STREQ(import3.name, "f4"); | ||
EXPECT_EQ(import3.kind, FizzyExternalKindFunction); | ||
ASSERT_EQ(import3.desc.function_type.inputs_size, 2); | ||
EXPECT_EQ(import3.desc.function_type.inputs[0], FizzyValueTypeF32); | ||
EXPECT_EQ(import3.desc.function_type.inputs[1], FizzyValueTypeF64); | ||
EXPECT_EQ(import3.desc.function_type.output, FizzyValueTypeI64); | ||
|
||
const auto import4 = fizzy_get_import_description(module, 4); | ||
EXPECT_STREQ(import4.module, "m"); | ||
EXPECT_STREQ(import4.name, "g1"); | ||
EXPECT_EQ(import4.kind, FizzyExternalKindGlobal); | ||
EXPECT_EQ(import4.desc.global_type.value_type, FizzyValueTypeI32); | ||
EXPECT_FALSE(import4.desc.global_type.is_mutable); | ||
|
||
const auto import5 = fizzy_get_import_description(module, 5); | ||
EXPECT_STREQ(import5.module, "m"); | ||
EXPECT_STREQ(import5.name, "g2"); | ||
EXPECT_EQ(import5.kind, FizzyExternalKindGlobal); | ||
EXPECT_EQ(import5.desc.global_type.value_type, FizzyValueTypeF64); | ||
EXPECT_TRUE(import5.desc.global_type.is_mutable); | ||
|
||
const auto import6 = fizzy_get_import_description(module, 6); | ||
EXPECT_STREQ(import6.module, "m"); | ||
EXPECT_STREQ(import6.name, "t"); | ||
EXPECT_EQ(import6.kind, FizzyExternalKindTable); | ||
EXPECT_EQ(import6.desc.table_limits.min, 10); | ||
EXPECT_FALSE(import6.desc.table_limits.has_max); | ||
|
||
const auto import7 = fizzy_get_import_description(module, 7); | ||
EXPECT_STREQ(import7.module, "m"); | ||
EXPECT_STREQ(import7.name, "mem"); | ||
EXPECT_EQ(import7.kind, FizzyExternalKindMemory); | ||
EXPECT_EQ(import7.desc.memory_limits.min, 1); | ||
EXPECT_TRUE(import7.desc.memory_limits.has_max); | ||
EXPECT_EQ(import7.desc.memory_limits.max, 4); | ||
|
||
fizzy_free_module(module); | ||
} | ||
|
||
TEST(capi, import_name_after_instantiate) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this testing the lifetime of the name/namespace pointers? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, checks that it's alive after instantiation, as the documentation claims. |
||
{ | ||
/* wat2wasm | ||
(func (import "m" "f1") (result i32)) | ||
*/ | ||
const auto wasm = from_hex("0061736d010000000105016000017f020801016d0266310000"); | ||
|
||
const auto* module = fizzy_parse(wasm.data(), wasm.size()); | ||
ASSERT_NE(module, nullptr); | ||
ASSERT_EQ(fizzy_get_import_count(module), 1); | ||
|
||
const auto import0 = fizzy_get_import_description(module, 0); | ||
EXPECT_STREQ(import0.module, "m"); | ||
EXPECT_STREQ(import0.name, "f1"); | ||
|
||
FizzyExternalFunction host_funcs[] = {{{FizzyValueTypeI32, nullptr, 0}, NullFn, nullptr}}; | ||
|
||
auto instance = fizzy_instantiate(module, host_funcs, 1, nullptr, nullptr, nullptr, 0); | ||
EXPECT_NE(instance, nullptr); | ||
|
||
EXPECT_STREQ(import0.module, "m"); | ||
EXPECT_STREQ(import0.name, "f1"); | ||
|
||
fizzy_free_instance(instance); | ||
} | ||
|
||
TEST(capi, get_global_count) | ||
{ | ||
/* wat2wasm | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please compare with https://github.com/WebAssembly/wasm-c-api/blob/master/include/wasm.h#L254-L260.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you mean? They're quite similar except that I use full word for "function" and list them in the order of the spec.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They use
uint8_t
storage type. So it could be used in C++ directly. Or wrap it in C++ for better control.This may be done other day, but I'm suggesting exploring the design where some declarations are imported from C to C++ instead of only declaring C equivalents of C++ ones.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, this could have been done for
FizzyValueType
, too 🤔There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True. We may go old-school in this PR and then consider conversion. This probably requires off-site discussion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this better.
So is the wasm-c-api not in order with the spec?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, there it's func-global-table-memory.