diff --git a/test/utils/CMakeLists.txt b/test/utils/CMakeLists.txt index 16a3afc40..84ea6c000 100644 --- a/test/utils/CMakeLists.txt +++ b/test/utils/CMakeLists.txt @@ -14,6 +14,7 @@ target_sources( asserts.cpp asserts.hpp execute_helpers.hpp + fizzy_c_engine.cpp fizzy_engine.cpp floating_point_utils.hpp hex.cpp diff --git a/test/utils/fizzy_c_engine.cpp b/test/utils/fizzy_c_engine.cpp new file mode 100644 index 000000000..00699d08f --- /dev/null +++ b/test/utils/fizzy_c_engine.cpp @@ -0,0 +1,130 @@ +// Fizzy: A fast WebAssembly interpreter +// Copyright 2019-2020 The Fizzy Authors. +// SPDX-License-Identifier: Apache-2.0 + +#include + +#include +#include +#include +#include + +namespace fizzy::test +{ +class FizzyCEngine final : public WasmEngine +{ + FizzyInstance* m_instance = nullptr; + +public: + ~FizzyCEngine(); + + bool parse(bytes_view input) const final; + std::optional find_function( + std::string_view name, std::string_view signature) const final; + bool instantiate(bytes_view wasm_binary) final; + bool init_memory(bytes_view memory) final; + bytes_view get_memory() const final; + Result execute(FuncRef func_ref, const std::vector& args) final; +}; + +namespace +{ +FizzyExecutionResult env_adler32( + void*, FizzyInstance* instance, const FizzyValue* args, size_t, int) +{ + auto* memory = fizzy_get_instance_memory_data(instance); + assert(memory != nullptr); + const auto size = fizzy_get_instance_memory_size(instance); + const auto ret = fizzy::test::adler32( + bytes_view(memory, size) + .substr(static_cast(args[0].i64), static_cast(args[1].i64))); + return {false, true, {ret}}; +} +} // namespace + +std::unique_ptr create_fizzy_c_engine() +{ + return std::make_unique(); +} + +FizzyCEngine::~FizzyCEngine() +{ + if (m_instance) + fizzy_free_instance(m_instance); +} + +bool FizzyCEngine::parse(bytes_view input) const +{ + const auto module = fizzy_parse(input.data(), input.size()); + if (!module) + return false; + + fizzy_free_module(module); + return true; +} + +bool FizzyCEngine::instantiate(bytes_view wasm_binary) +{ + const auto module = fizzy_parse(wasm_binary.data(), wasm_binary.size()); + if (!module) + return false; + + // TODO resolve_imported_functions + FizzyExternalFunction imports[] = {{env_adler32, nullptr}}; + m_instance = fizzy_instantiate(module, imports, 1); + + assert(m_instance != nullptr); + return true; +} + +bool FizzyCEngine::init_memory(bytes_view memory) +{ + auto* instance_memory = fizzy_get_instance_memory_data(m_instance); + if (instance_memory == nullptr) + return false; + + const auto size = fizzy_get_instance_memory_size(m_instance); + if (size < memory.size()) + return false; + + std::memcpy(instance_memory, memory.data(), memory.size()); + return true; +} + +bytes_view FizzyCEngine::get_memory() const +{ + auto* data = fizzy_get_instance_memory_data(m_instance); + if (data == nullptr) + return {}; + + const auto size = fizzy_get_instance_memory_size(m_instance); + return {data, size}; +} + +std::optional FizzyCEngine::find_function( + std::string_view name, std::string_view /*signature*/) const +{ + uint32_t func_idx; + if (!fizzy_find_exported_function( + fizzy_get_instance_module(m_instance), std::string{name}.c_str(), &func_idx)) + { + // TODO check function type + return std::nullopt; + } + return func_idx; +} + +WasmEngine::Result FizzyCEngine::execute( + WasmEngine::FuncRef func_ref, const std::vector& args) +{ + static_assert(sizeof(uint64_t) == sizeof(FizzyValue)); + const auto first_arg = reinterpret_cast(args.data()); + const auto status = fizzy_execute(m_instance, static_cast(func_ref), first_arg, 0); + if (status.trapped) + return {true, std::nullopt}; + else if (status.has_value) + return {false, status.value.i64}; + else + return {false, std::nullopt}; +} +} // namespace fizzy::test diff --git a/test/utils/wasm_engine.hpp b/test/utils/wasm_engine.hpp index 825f49113..d09e0e197 100644 --- a/test/utils/wasm_engine.hpp +++ b/test/utils/wasm_engine.hpp @@ -61,6 +61,7 @@ class WasmEngine void validate_function_signature(std::string_view signature); std::unique_ptr create_fizzy_engine(); +std::unique_ptr create_fizzy_c_engine(); std::unique_ptr create_wabt_engine(); std::unique_ptr create_wasm3_engine(); } // namespace fizzy::test