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: Type and global inspection functions #675

Merged
merged 2 commits into from
Jan 11, 2021
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
31 changes: 31 additions & 0 deletions include/fizzy/fizzy.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,20 @@ void fizzy_free_module(const FizzyModule* module);
/// @note Input module is not modified neither in success nor in failure case.
const FizzyModule* fizzy_clone_module(const FizzyModule* module);

/// Get number of types defined in the module.
///
/// @param module Pointer to module. Cannot be NULL.
axic marked this conversation as resolved.
Show resolved Hide resolved
/// @return Number of type in the module.
uint32_t fizzy_get_type_count(const FizzyModule* module);

/// Get type defined in the module.
///
/// @param module Pointer to module. Cannot be NULL.
/// @param type_idx Type index. Behaviour is undefined if index is not valid according
/// to module definition.
axic marked this conversation as resolved.
Show resolved Hide resolved
/// @return Type corresponding to the index.
FizzyFunctionType fizzy_get_type(const FizzyModule* module, uint32_t type_idx);

/// Get type of the function defined in the module.
///
/// @param module Pointer to module. Cannot be NULL.
Expand All @@ -191,6 +205,23 @@ bool fizzy_module_has_table(const FizzyModule* module);
/// @return true if module has a memory definition, false otherwise.
bool fizzy_module_has_memory(const FizzyModule* module);

/// Get number of globals defined in the module.
///
/// @param module Pointer to module. Cannot be NULL.
/// @return Number of globals in the module.
uint32_t fizzy_get_global_count(const FizzyModule* module);
axic marked this conversation as resolved.
Show resolved Hide resolved

/// Get type of a given global defined in the module.
///
/// @param module Pointer to module. Cannot be NULL.
/// @param global_idx Global index. Can be either index of an imported global or of a global
/// defined in module. Behaviour is undefined if index is not valid according
/// to module definition.
/// @return Type of the global corresponding to the index.
///
axic marked this conversation as resolved.
Show resolved Hide resolved
/// @note All module global indices are greater than all imported global indices.
FizzyGlobalType fizzy_get_global_type(const FizzyModule* module, uint32_t global_idx);

/// Find index of exported function by name.
///
/// @param module Pointer to module. Cannot be NULL.
Expand Down
20 changes: 20 additions & 0 deletions lib/fizzy/capi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,16 @@ const FizzyModule* fizzy_clone_module(const FizzyModule* module)
}
}

uint32_t fizzy_get_type_count(const FizzyModule* module)
{
return static_cast<uint32_t>(unwrap(module)->typesec.size());
}

FizzyFunctionType fizzy_get_type(const FizzyModule* module, uint32_t type_idx)
{
return wrap(unwrap(module)->typesec[type_idx]);
}

FizzyFunctionType fizzy_get_function_type(const FizzyModule* module, uint32_t func_idx)
{
return wrap(unwrap(module)->get_function_type(func_idx));
Expand All @@ -344,6 +354,16 @@ bool fizzy_module_has_memory(const FizzyModule* module)
return unwrap(module)->has_memory();
}

uint32_t fizzy_get_global_count(const FizzyModule* module)
{
return static_cast<uint32_t>(unwrap(module)->get_global_count());
}

FizzyGlobalType fizzy_get_global_type(const FizzyModule* module, uint32_t global_idx)
{
return wrap(unwrap(module)->get_global_type(global_idx));
}

bool fizzy_find_exported_function_index(
const FizzyModule* module, const char* name, uint32_t* out_func_idx)
{
Expand Down
216 changes: 216 additions & 0 deletions test/unittests/capi_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1069,3 +1069,219 @@ TEST(capi, imported_global_from_another_module)
fizzy_free_instance(instance2);
fizzy_free_instance(instance1);
}

TEST(capi, get_type_count)
{
/* wat2wasm
(module)
*/
const auto wasm = from_hex("0061736d01000000");

const auto* module_empty = fizzy_parse(wasm.data(), wasm.size());
ASSERT_NE(module_empty, nullptr);

EXPECT_EQ(fizzy_get_type_count(module_empty), 0);
fizzy_free_module(module_empty);

/* wat2wasm
(func)
*/
const auto wasm_one_func = from_hex("0061736d01000000010401600000030201000a040102000b");

const auto* module_one_func = fizzy_parse(wasm_one_func.data(), wasm_one_func.size());
ASSERT_NE(module_one_func, nullptr);

EXPECT_EQ(fizzy_get_type_count(module_one_func), 1);
fizzy_free_module(module_one_func);

/* wat2wasm
(type (func (param i32)))
(type (func (param i32) (result i32)))
(type (func (result i32)))
(func (type 0))
(func (type 1) (return (i32.const 0)))
(func (type 1) (return (i32.const 0)))
(func (type 2) (return (i32.const 0)))
*/
const auto wasm_three_types = from_hex(
"0061736d01000000010e0360017f0060017f017f6000017f030504000101020a160402000b050041000f0b0500"
"41000f0b050041000f0b");

const auto* module_three_types = fizzy_parse(wasm_three_types.data(), wasm_three_types.size());
ASSERT_NE(module_three_types, nullptr);

EXPECT_EQ(fizzy_get_type_count(module_three_types), 3);
fizzy_free_module(module_three_types);
}

TEST(capi, get_type)
{
/* wat2wasm
(func)
*/
const auto wasm_one_func = from_hex("0061736d01000000010401600000030201000a040102000b");

const auto* module_one_func = fizzy_parse(wasm_one_func.data(), wasm_one_func.size());
ASSERT_NE(module_one_func, nullptr);
ASSERT_EQ(fizzy_get_type_count(module_one_func), 1);

const auto type_one_func = fizzy_get_type(module_one_func, 0);
axic marked this conversation as resolved.
Show resolved Hide resolved
EXPECT_EQ(type_one_func.inputs_size, 0);
EXPECT_EQ(type_one_func.output, FizzyValueTypeVoid);
fizzy_free_module(module_one_func);

/* wat2wasm
(type (func))
(type (func (param i32)))
(type (func (param i32) (result i32)))
(type (func (result i32)))
axic marked this conversation as resolved.
Show resolved Hide resolved
(func (type 0))
(func (type 1))
(func (type 2) (return (i32.const 0)))
(func (type 2) (return (i32.const 0)))
(func (type 3) (return (i32.const 0)))
*/
const auto wasm_three_types = from_hex(
"0061736d0100000001110460000060017f0060017f017f6000017f03060500010202030a190502000b02000b05"
"0041000f0b050041000f0b050041000f0b");

const auto* module_three_types = fizzy_parse(wasm_three_types.data(), wasm_three_types.size());
ASSERT_NE(module_three_types, nullptr);
ASSERT_EQ(fizzy_get_type_count(module_three_types), 4);

const auto type0 = fizzy_get_type(module_three_types, 0);
ASSERT_EQ(type0.inputs_size, 0);
EXPECT_EQ(type0.output, FizzyValueTypeVoid);

const auto type1 = fizzy_get_type(module_three_types, 1);
ASSERT_EQ(type1.inputs_size, 1);
EXPECT_EQ(type1.inputs[0], FizzyValueTypeI32);
EXPECT_EQ(type1.output, FizzyValueTypeVoid);

const auto type2 = fizzy_get_type(module_three_types, 2);
ASSERT_EQ(type2.inputs_size, 1);
EXPECT_EQ(type2.inputs[0], FizzyValueTypeI32);
EXPECT_EQ(type2.output, FizzyValueTypeI32);

const auto type3 = fizzy_get_type(module_three_types, 3);
EXPECT_EQ(type3.inputs_size, 0);
EXPECT_EQ(type3.output, FizzyValueTypeI32);

fizzy_free_module(module_three_types);

/* wat2wasm
(func (import "mod" "f") (param i64 i64))
(func (param i32))
*/
const auto wasm_imported_func = from_hex(
"0061736d01000000010a0260027e7e0060017f00020901036d6f6401660000030201010a040102000b");

const auto* module_imported_func =
fizzy_parse(wasm_imported_func.data(), wasm_imported_func.size());
ASSERT_NE(module_imported_func, nullptr);
ASSERT_EQ(fizzy_get_type_count(module_imported_func), 2);

const auto type_imported = fizzy_get_type(module_imported_func, 0);
ASSERT_EQ(type_imported.inputs_size, 2);
EXPECT_EQ(type_imported.inputs[0], FizzyValueTypeI64);
EXPECT_EQ(type_imported.inputs[1], FizzyValueTypeI64);
EXPECT_EQ(type_imported.output, FizzyValueTypeVoid);

const auto type_local = fizzy_get_type(module_imported_func, 1);
ASSERT_EQ(type_local.inputs_size, 1);
EXPECT_EQ(type_local.inputs[0], FizzyValueTypeI32);
EXPECT_EQ(type_local.output, FizzyValueTypeVoid);

fizzy_free_module(module_imported_func);
}

TEST(capi, get_global_count)
{
/* wat2wasm
(module)
*/
const auto wasm = from_hex("0061736d01000000");

const auto* module_empty = fizzy_parse(wasm.data(), wasm.size());
ASSERT_NE(module_empty, nullptr);

EXPECT_EQ(fizzy_get_global_count(module_empty), 0);
fizzy_free_module(module_empty);

/* wat2wasm
(global i32 (i32.const 0))
*/
const auto wasm_one_global = from_hex("0061736d010000000606017f0041000b");

const auto* module_one_global = fizzy_parse(wasm_one_global.data(), wasm_one_global.size());
ASSERT_NE(module_one_global, nullptr);

EXPECT_EQ(fizzy_get_global_count(module_one_global), 1);
fizzy_free_module(module_one_global);

/* wat2wasm
(global (import "mod" "g") i32)
(global i32 (i32.const 0))
*/
const auto wasm_imported_global =
from_hex("0061736d01000000020a01036d6f640167037f000606017f0041000b");

const auto* module_imported_global =
fizzy_parse(wasm_imported_global.data(), wasm_imported_global.size());
ASSERT_NE(module_imported_global, nullptr);

EXPECT_EQ(fizzy_get_global_count(module_imported_global), 2);
fizzy_free_module(module_imported_global);
}

TEST(capi, get_global_type)
{
/* wat2wasm
(global i32 (i32.const 0))
(global (mut i64) (i64.const 0))
(global f32 (f32.const 0))
(global (mut f64) (f64.const 0))
*/
const auto wasm = from_hex(
"0061736d01000000061f047f0041000b7e0142000b7d0043000000000b7c014400000000000000000b");

const auto* module = fizzy_parse(wasm.data(), wasm.size());
ASSERT_NE(module, nullptr);
ASSERT_EQ(fizzy_get_global_count(module), 4);

EXPECT_EQ(fizzy_get_global_type(module, 0).value_type, FizzyValueTypeI32);
axic marked this conversation as resolved.
Show resolved Hide resolved
EXPECT_EQ(fizzy_get_global_type(module, 0).is_mutable, false);
EXPECT_EQ(fizzy_get_global_type(module, 1).value_type, FizzyValueTypeI64);
EXPECT_EQ(fizzy_get_global_type(module, 1).is_mutable, true);
EXPECT_EQ(fizzy_get_global_type(module, 2).value_type, FizzyValueTypeF32);
EXPECT_EQ(fizzy_get_global_type(module, 2).is_mutable, false);
EXPECT_EQ(fizzy_get_global_type(module, 3).value_type, FizzyValueTypeF64);
EXPECT_EQ(fizzy_get_global_type(module, 3).is_mutable, true);

fizzy_free_module(module);

/* wat2wasm
(global (import "mod" "g1") i32)
(global (import "mod" "g2") (mut i64))
(global (import "mod" "g3") f32)
(global (import "mod" "g4") (mut f64))
*/
const auto wasm_imports = from_hex(
"0061736d01000000022904036d6f64026731037f00036d6f64026732037e01036d6f64026733037d00036d6f64"
"026734037c01");

const auto* module_imports = fizzy_parse(wasm_imports.data(), wasm_imports.size());
ASSERT_NE(module_imports, nullptr);
ASSERT_EQ(fizzy_get_global_count(module_imports), 4);

EXPECT_EQ(fizzy_get_global_type(module_imports, 0).value_type, FizzyValueTypeI32);
axic marked this conversation as resolved.
Show resolved Hide resolved
EXPECT_EQ(fizzy_get_global_type(module_imports, 0).is_mutable, false);
EXPECT_EQ(fizzy_get_global_type(module_imports, 1).value_type, FizzyValueTypeI64);
EXPECT_EQ(fizzy_get_global_type(module_imports, 1).is_mutable, true);
EXPECT_EQ(fizzy_get_global_type(module_imports, 2).value_type, FizzyValueTypeF32);
EXPECT_EQ(fizzy_get_global_type(module_imports, 2).is_mutable, false);
EXPECT_EQ(fizzy_get_global_type(module_imports, 3).value_type, FizzyValueTypeF64);
EXPECT_EQ(fizzy_get_global_type(module_imports, 3).is_mutable, true);

fizzy_free_module(module_imports);
}