From 7d5b7538f703ad5aff810a3ce1cc1e3f0fdc9e06 Mon Sep 17 00:00:00 2001 From: Andrei Maiboroda Date: Tue, 15 Dec 2020 15:57:11 +0100 Subject: [PATCH] capi: Add function to clone a module --- include/fizzy/fizzy.h | 11 +++++++++ lib/fizzy/capi.cpp | 13 +++++++++++ test/unittests/capi_test.cpp | 43 ++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) diff --git a/include/fizzy/fizzy.h b/include/fizzy/fizzy.h index bbd723795..d6329dbe4 100644 --- a/include/fizzy/fizzy.h +++ b/include/fizzy/fizzy.h @@ -157,6 +157,17 @@ const FizzyModule* fizzy_parse(const uint8_t* wasm_binary, size_t wasm_binary_si /// If passed pointer is NULL, has no effect. void fizzy_free_module(const FizzyModule* module); +/// Make a copy of a module. +/// +/// @param module Pointer to module. Cannot be NULL. +/// @returns Pointer to a newly allocated module, identical to @a module, or NULL in case +/// memory for a module could not be allocated. +/// +/// @note Creating a copy is needed if more than single instance of a module is required, because +/// instantiation takes ownership of a module, and the same module cannot be instantiated twice. +/// @note Input module is not modified neither in success nor in failure case. +const FizzyModule* fizzy_clone_module(const FizzyModule* module); + /// Get type of the function defined in the module. /// /// @param module Pointer to module. Cannot be NULL. diff --git a/lib/fizzy/capi.cpp b/lib/fizzy/capi.cpp index 98f4c0db3..216d2444c 100644 --- a/lib/fizzy/capi.cpp +++ b/lib/fizzy/capi.cpp @@ -308,6 +308,19 @@ void fizzy_free_module(const FizzyModule* module) delete unwrap(module); } +const FizzyModule* fizzy_clone_module(const FizzyModule* module) +{ + try + { + auto clone = std::make_unique(*unwrap(module)); + return wrap(clone.release()); + } + catch (...) + { + return nullptr; + } +} + FizzyFunctionType fizzy_get_function_type(const FizzyModule* module, uint32_t func_idx) { return wrap(unwrap(module)->get_function_type(func_idx)); diff --git a/test/unittests/capi_test.cpp b/test/unittests/capi_test.cpp index 53b713840..6b8c1a6d3 100644 --- a/test/unittests/capi_test.cpp +++ b/test/unittests/capi_test.cpp @@ -35,6 +35,29 @@ TEST(capi, free_module_null) fizzy_free_module(nullptr); } +TEST(capi, clone_module) +{ + /* wat2wasm + (func (param i32 i32) (result i32) (i32.const 0)) + */ + const auto wasm = from_hex("0061736d0100000001070160027f7f017f030201000a0601040041000b"); + const auto* module1 = fizzy_parse(wasm.data(), wasm.size()); + EXPECT_NE(module1, nullptr); + + const auto* module2 = fizzy_clone_module(module1); + EXPECT_NE(module2, nullptr); + EXPECT_NE(module1, module2); + + const auto type2 = fizzy_get_function_type(module2, 0); + EXPECT_EQ(type2.output, FizzyValueTypeI32); + ASSERT_EQ(type2.inputs_size, 2); + EXPECT_EQ(type2.inputs[0], FizzyValueTypeI32); + EXPECT_EQ(type2.inputs[1], FizzyValueTypeI32); + + fizzy_free_module(module2); + fizzy_free_module(module1); +} + TEST(capi, get_function_type) { /* wat2wasm @@ -397,6 +420,26 @@ TEST(capi, instantiate_imported_globals) fizzy_instantiate(module, nullptr, 0, nullptr, nullptr, globals_type_mismatch, 4), nullptr); } +TEST(capi, instantiate_twice) +{ + uint8_t wasm_prefix[]{0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00}; + const auto* module1 = fizzy_parse(wasm_prefix, sizeof(wasm_prefix)); + ASSERT_NE(module1, nullptr); + + auto* instance1 = fizzy_instantiate(module1, nullptr, 0, nullptr, nullptr, nullptr, 0); + EXPECT_NE(instance1, nullptr); + + const auto* module2 = fizzy_clone_module(module1); + ASSERT_NE(module2, nullptr); + + auto* instance2 = fizzy_instantiate(module2, nullptr, 0, nullptr, nullptr, nullptr, 0); + EXPECT_NE(instance2, nullptr); + EXPECT_NE(instance1, instance2); + + fizzy_free_instance(instance2); + fizzy_free_instance(instance1); +} + TEST(capi, resolve_instantiate_no_imports) { /* wat2wasm