diff --git a/include/fizzy/fizzy.h b/include/fizzy/fizzy.h index c2e570244a..5358c47742 100644 --- a/include/fizzy/fizzy.h +++ b/include/fizzy/fizzy.h @@ -80,6 +80,20 @@ typedef struct FizzyExternalFunction void* context; } FizzyExternalFunction; +/// Global type. +typedef struct FizzyGlobalType +{ + FizzyValueType value_type; + bool is_mutable; +} FizzyGlobalType; + +/// External global. +typedef struct FizzyExternalGlobal +{ + FizzyValue* value; + FizzyGlobalType type; +} FizzyExternalGlobal; + /// Imported function. typedef struct FizzyImportedFunction { @@ -139,7 +153,8 @@ bool fizzy_find_exported_function( /// When number of passed functions or their order is different from the one defined by the /// module, behaviour is undefined. FizzyInstance* fizzy_instantiate(const FizzyModule* module, - const FizzyExternalFunction* imported_functions, size_t imported_functions_size); + const FizzyExternalFunction* imported_functions, size_t imported_functions_size, + 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. @@ -155,7 +170,8 @@ FizzyInstance* fizzy_instantiate(const FizzyModule* module, /// functions not required by the module. /// Functions are matched to module's imports based on their module and name strings. FizzyInstance* fizzy_resolve_instantiate(const FizzyModule* module, - const FizzyImportedFunction* imported_functions, size_t imported_functions_size); + const FizzyImportedFunction* imported_functions, size_t imported_functions_size, + const FizzyExternalGlobal* imported_globals, size_t imported_globals_size); /// Free resources associated with the instance. /// If passed pointer is NULL, has no effect. diff --git a/lib/fizzy/capi.cpp b/lib/fizzy/capi.cpp index 5bc1bdce7c..1fc1a8ca80 100644 --- a/lib/fizzy/capi.cpp +++ b/lib/fizzy/capi.cpp @@ -76,6 +76,11 @@ inline const fizzy::Value* unwrap(const FizzyValue* values) noexcept return reinterpret_cast(values); } +inline fizzy::Value* unwrap(FizzyValue* value) noexcept +{ + return reinterpret_cast(value); +} + inline FizzyInstance* wrap(fizzy::Instance* instance) noexcept { return reinterpret_cast(instance); @@ -138,6 +143,15 @@ inline fizzy::ImportedFunction unwrap(const FizzyImportedFunction& c_imported_fu return imported_func; } +inline fizzy::GlobalType unwrap(const FizzyGlobalType& global_type) noexcept +{ + return {unwrap(global_type.value_type), global_type.is_mutable}; +} + +inline fizzy::ExternalGlobal unwrap(const FizzyExternalGlobal& external_global) noexcept +{ + return fizzy::ExternalGlobal{unwrap(external_global.value), unwrap(external_global.type)}; +} } // namespace extern "C" { @@ -189,7 +203,8 @@ bool fizzy_find_exported_function( } FizzyInstance* fizzy_instantiate(const FizzyModule* module, - const FizzyExternalFunction* imported_functions, size_t imported_functions_size) + const FizzyExternalFunction* imported_functions, size_t imported_functions_size, + const FizzyExternalGlobal* imported_globals, size_t imported_globals_size) { try { @@ -198,8 +213,13 @@ FizzyInstance* fizzy_instantiate(const FizzyModule* module, std::transform(imported_functions, imported_functions + imported_functions_size, functions.begin(), unwrap_external_func_fn); - auto instance = fizzy::instantiate( - std::unique_ptr(unwrap(module)), std::move(functions)); + std::vector globals(imported_globals_size); + fizzy::ExternalGlobal (*unwrap_external_global_fn)(const FizzyExternalGlobal&) = &unwrap; + std::transform(imported_globals, imported_globals + imported_globals_size, globals.begin(), + unwrap_external_global_fn); + + auto instance = fizzy::instantiate(std::unique_ptr(unwrap(module)), + std::move(functions), {}, {}, std::move(globals)); return wrap(instance.release()); } @@ -210,7 +230,8 @@ 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 FizzyImportedFunction* c_imported_functions, size_t imported_functions_size, + const FizzyExternalGlobal* imported_globals, size_t imported_globals_size) { try { @@ -219,10 +240,16 @@ FizzyInstance* fizzy_resolve_instantiate(const FizzyModule* c_module, std::transform(c_imported_functions, c_imported_functions + imported_functions_size, imported_functions.begin(), unwrap_imported_func_fn); + std::vector globals(imported_globals_size); + fizzy::ExternalGlobal (*unwrap_external_global_fn)(const FizzyExternalGlobal&) = &unwrap; + std::transform(imported_globals, imported_globals + imported_globals_size, globals.begin(), + unwrap_external_global_fn); + std::unique_ptr 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)); + auto instance = fizzy::instantiate( + std::move(module), std::move(resolved_imports), {}, {}, std::move(globals)); return wrap(instance.release()); } diff --git a/test/unittests/capi_test.cpp b/test/unittests/capi_test.cpp index 367e87b067..9d8923c86d 100644 --- a/test/unittests/capi_test.cpp +++ b/test/unittests/capi_test.cpp @@ -104,7 +104,7 @@ TEST(capi, instantiate) auto module = fizzy_parse(wasm_prefix, sizeof(wasm_prefix)); ASSERT_NE(module, nullptr); - auto instance = fizzy_instantiate(module, nullptr, 0); + auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, 0); EXPECT_NE(instance, nullptr); fizzy_free_instance(instance); @@ -119,7 +119,7 @@ TEST(capi, instantiate_imported_function) auto module = fizzy_parse(wasm.data(), wasm.size()); ASSERT_NE(module, nullptr); - EXPECT_EQ(fizzy_instantiate(module, nullptr, 0), nullptr); + EXPECT_EQ(fizzy_instantiate(module, nullptr, 0, nullptr, 0), nullptr); module = fizzy_parse(wasm.data(), wasm.size()); ASSERT_NE(module, nullptr); @@ -130,7 +130,7 @@ TEST(capi, instantiate_imported_function) }, nullptr}}; - auto instance = fizzy_instantiate(module, host_funcs, 1); + auto instance = fizzy_instantiate(module, host_funcs, 1, nullptr, 0); EXPECT_NE(instance, nullptr); fizzy_free_instance(instance); @@ -145,7 +145,7 @@ TEST(capi, resolve_instantiate_no_imports) auto module = fizzy_parse(wasm.data(), wasm.size()); ASSERT_NE(module, nullptr); - auto instance = fizzy_resolve_instantiate(module, nullptr, 0); + auto instance = fizzy_resolve_instantiate(module, nullptr, 0, nullptr, 0); EXPECT_NE(instance, nullptr); fizzy_free_instance(instance); @@ -158,7 +158,7 @@ TEST(capi, resolve_instantiate_no_imports) [](void*, FizzyInstance*, const FizzyValue*, int) { return FizzyExecutionResult{}; }, nullptr}}}; - instance = fizzy_resolve_instantiate(module, host_funcs, 1); + instance = fizzy_resolve_instantiate(module, host_funcs, 1, nullptr, 0); EXPECT_NE(instance, nullptr); fizzy_free_instance(instance); @@ -178,7 +178,7 @@ TEST(capi, resolve_instantiate) auto module = fizzy_parse(wasm.data(), wasm.size()); ASSERT_NE(module, nullptr); - EXPECT_EQ(fizzy_instantiate(module, nullptr, 0), nullptr); + EXPECT_EQ(fizzy_instantiate(module, nullptr, 0, nullptr, 0), nullptr); module = fizzy_parse(wasm.data(), wasm.size()); ASSERT_NE(module, nullptr); @@ -201,7 +201,7 @@ TEST(capi, resolve_instantiate) FizzyImportedFunction host_funcs[] = {{"mod1", "foo1", mod1foo1}, {"mod1", "foo2", mod1foo2}, {"mod2", "foo1", mod2foo1}, {"mod2", "foo2", mod2foo2}}; - auto instance = fizzy_resolve_instantiate(module, host_funcs, 4); + auto instance = fizzy_resolve_instantiate(module, host_funcs, 4, nullptr, 0); EXPECT_NE(instance, nullptr); fizzy_free_instance(instance); @@ -210,7 +210,7 @@ TEST(capi, resolve_instantiate) ASSERT_NE(module, nullptr); FizzyImportedFunction host_funcs_reordered[] = {{"mod1", "foo2", mod1foo2}, {"mod2", "foo1", mod2foo1}, {"mod2", "foo2", mod2foo2}, {"mod1", "foo1", mod1foo1}}; - instance = fizzy_resolve_instantiate(module, host_funcs_reordered, 4); + instance = fizzy_resolve_instantiate(module, host_funcs_reordered, 4, nullptr, 0); EXPECT_NE(instance, nullptr); fizzy_free_instance(instance); @@ -220,14 +220,14 @@ TEST(capi, resolve_instantiate) FizzyImportedFunction host_funcs_extra[] = {{"mod1", "foo1", mod1foo1}, {"mod1", "foo2", mod1foo2}, {"mod2", "foo1", mod2foo1}, {"mod2", "foo2", mod2foo2}, {"mod3", "foo1", mod1foo1}}; - instance = fizzy_resolve_instantiate(module, host_funcs_extra, 4); + instance = fizzy_resolve_instantiate(module, host_funcs_extra, 4, nullptr, 0); EXPECT_NE(instance, nullptr); fizzy_free_instance(instance); // not enough functions module = fizzy_parse(wasm.data(), wasm.size()); ASSERT_NE(module, nullptr); - EXPECT_EQ(fizzy_resolve_instantiate(module, host_funcs, 3), nullptr); + EXPECT_EQ(fizzy_resolve_instantiate(module, host_funcs, 3, nullptr, 0), nullptr); } TEST(capi, free_instance_null) @@ -244,7 +244,7 @@ TEST(capi, get_instance_module) auto module = fizzy_parse(wasm.data(), wasm.size()); ASSERT_NE(module, nullptr); - auto instance = fizzy_instantiate(module, nullptr, 0); + auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, 0); ASSERT_NE(instance, nullptr); auto instance_module = fizzy_get_instance_module(instance); @@ -264,7 +264,7 @@ TEST(capi, memory_access_no_memory) auto module = fizzy_parse(wasm.data(), wasm.size()); ASSERT_NE(module, nullptr); - auto instance = fizzy_instantiate(module, nullptr, 0); + auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, 0); ASSERT_NE(instance, nullptr); EXPECT_EQ(fizzy_get_instance_memory_data(instance), nullptr); @@ -289,7 +289,7 @@ TEST(capi, memory_access) auto module = fizzy_parse(wasm.data(), wasm.size()); ASSERT_NE(module, nullptr); - auto instance = fizzy_instantiate(module, nullptr, 0); + auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, 0); ASSERT_NE(instance, nullptr); uint8_t* memory = fizzy_get_instance_memory_data(instance); @@ -316,7 +316,7 @@ TEST(capi, imported_memory_access) auto module = fizzy_parse(wasm.data(), wasm.size()); ASSERT_NE(module, nullptr); - auto instance = fizzy_instantiate(module, nullptr, 0); + auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, 0); EXPECT_EQ(instance, nullptr); } @@ -337,7 +337,7 @@ TEST(capi, execute) auto module = fizzy_parse(wasm.data(), wasm.size()); ASSERT_NE(module, nullptr); - auto instance = fizzy_instantiate(module, nullptr, 0); + auto instance = fizzy_instantiate(module, nullptr, 0, nullptr, 0); ASSERT_NE(instance, nullptr); EXPECT_THAT(fizzy_execute(instance, 0, nullptr, 0), Result()); @@ -374,7 +374,7 @@ TEST(capi, execute_with_host_function) }, nullptr}}; - auto instance = fizzy_instantiate(module, host_funcs, 2); + auto instance = fizzy_instantiate(module, host_funcs, 2, nullptr, 0); ASSERT_NE(instance, nullptr); EXPECT_THAT(fizzy_execute(instance, 0, nullptr, 0), Result(42)); @@ -404,7 +404,7 @@ TEST(capi, imported_function_traps) }, nullptr}}; - auto instance = fizzy_instantiate(module, host_funcs, 1); + auto instance = fizzy_instantiate(module, host_funcs, 1, nullptr, 0); ASSERT_NE(instance, nullptr); EXPECT_THAT(fizzy_execute(instance, 1, nullptr, 0), Traps()); @@ -433,7 +433,7 @@ TEST(capi, imported_function_void) }, &called}}; - auto instance = fizzy_instantiate(module, host_funcs, 1); + auto instance = fizzy_instantiate(module, host_funcs, 1, nullptr, 0); ASSERT_NE(instance, nullptr); EXPECT_THAT(fizzy_execute(instance, 1, nullptr, 0), Result()); @@ -457,7 +457,7 @@ TEST(capi, imported_function_from_another_module) "0061736d0100000001070160027f7f017f030201000707010373756200000a09010700200020016b0b"); auto module1 = fizzy_parse(bin1.data(), bin1.size()); ASSERT_NE(module1, nullptr); - auto instance1 = fizzy_instantiate(module1, nullptr, 0); + auto instance1 = fizzy_instantiate(module1, nullptr, 0, nullptr, 0); ASSERT_NE(instance1, nullptr); /* wat2wasm @@ -494,7 +494,7 @@ TEST(capi, imported_function_from_another_module) FizzyExternalFunction host_funcs[] = {{{FizzyValueTypeI32, &inputs[0], 2}, sub, &host_context}}; - auto instance2 = fizzy_instantiate(module2, host_funcs, 1); + auto instance2 = fizzy_instantiate(module2, host_funcs, 1, nullptr, 0); ASSERT_NE(instance2, nullptr); FizzyValue args[] = {{44}, {2}}; diff --git a/test/utils/fizzy_c_engine.cpp b/test/utils/fizzy_c_engine.cpp index f1a3cb694c..801cae1ebb 100644 --- a/test/utils/fizzy_c_engine.cpp +++ b/test/utils/fizzy_c_engine.cpp @@ -64,7 +64,7 @@ bool FizzyCEngine::instantiate(bytes_view wasm_binary) FizzyValueType inputs[] = {FizzyValueTypeI32, FizzyValueTypeI32}; FizzyImportedFunction imports[] = { {"env", "adler32", {{FizzyValueTypeI32, inputs, 2}, env_adler32, nullptr}}}; - m_instance.reset(fizzy_resolve_instantiate(module, imports, 1)); + m_instance.reset(fizzy_resolve_instantiate(module, imports, 1, nullptr, 0)); return (m_instance != nullptr); }