blob: 75a2513c822d3b03305a8ab7ae2ada97d5f4fe63 [file] [log] [blame]
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
#include <cinttypes>
#include "wasm.hh"
auto get_export_global(wasm::vec<wasm::Extern*>& exports, size_t i) -> wasm::Global* {
if (exports.size() <= i || !exports[i]->global()) {
std::cout << "> Error accessing global export " << i << "!" << std::endl;
exit(1);
}
return exports[i]->global();
}
auto get_export_func(const wasm::vec<wasm::Extern*>& exports, size_t i) -> const wasm::Func* {
if (exports.size() <= i || !exports[i]->func()) {
std::cout << "> Error accessing function export " << i << "!" << std::endl;
exit(1);
}
return exports[i]->func();
}
template<class T, class U>
void check(T actual, U expected) {
if (actual != expected) {
std::cout << "> Error reading value, expected " << expected << ", got " << actual << std::endl;
exit(1);
}
}
auto call(const wasm::Func* func) -> wasm::Val {
wasm::Val results[1];
if (func->call(nullptr, results)) {
std::cout << "> Error calling function!" << std::endl;
exit(1);
}
return results[0].copy();
}
void call(const wasm::Func* func, wasm::Val&& arg) {
wasm::Val args[1] = {std::move(arg)};
if (func->call(args)) {
std::cout << "> Error calling function!" << std::endl;
exit(1);
}
}
void run() {
// Initialize.
std::cout << "Initializing..." << std::endl;
auto engine = wasm::Engine::make();
auto store_ = wasm::Store::make(engine.get());
auto store = store_.get();
// Load binary.
std::cout << "Loading binary..." << std::endl;
std::ifstream file("global.wasm");
file.seekg(0, std::ios_base::end);
auto file_size = file.tellg();
file.seekg(0);
auto binary = wasm::vec<byte_t>::make_uninitialized(file_size);
file.read(binary.get(), file_size);
file.close();
if (file.fail()) {
std::cout << "> Error loading module!" << std::endl;
return;
}
// Compile.
std::cout << "Compiling module..." << std::endl;
auto module = wasm::Module::make(store, binary);
if (!module) {
std::cout << "> Error compiling module!" << std::endl;
return;
}
// Create external globals.
std::cout << "Creating globals..." << std::endl;
auto const_f32_type = wasm::GlobalType::make(
wasm::ValType::make(wasm::F32), wasm::CONST);
auto const_i64_type = wasm::GlobalType::make(
wasm::ValType::make(wasm::I64), wasm::CONST);
auto var_f32_type = wasm::GlobalType::make(
wasm::ValType::make(wasm::F32), wasm::VAR);
auto var_i64_type = wasm::GlobalType::make(
wasm::ValType::make(wasm::I64), wasm::VAR);
auto const_f32_import = wasm::Global::make(store, const_f32_type.get(), wasm::Val::f32(1));
auto const_i64_import = wasm::Global::make(store, const_i64_type.get(), wasm::Val::i64(2));
auto var_f32_import = wasm::Global::make(store, var_f32_type.get(), wasm::Val::f32(3));
auto var_i64_import = wasm::Global::make(store, var_i64_type.get(), wasm::Val::i64(4));
// Instantiate.
std::cout << "Instantiating module..." << std::endl;
wasm::Extern* imports[] = {
const_f32_import.get(), const_i64_import.get(),
var_f32_import.get(), var_i64_import.get()
};
auto instance = wasm::Instance::make(store, module.get(), imports);
if (!instance) {
std::cout << "> Error instantiating module!" << std::endl;
return;
}
// Extract export.
std::cout << "Extracting exports..." << std::endl;
auto exports = instance->exports();
size_t i = 0;
auto const_f32_export = get_export_global(exports, i++);
auto const_i64_export = get_export_global(exports, i++);
auto var_f32_export = get_export_global(exports, i++);
auto var_i64_export = get_export_global(exports, i++);
auto get_const_f32_import = get_export_func(exports, i++);
auto get_const_i64_import = get_export_func(exports, i++);
auto get_var_f32_import = get_export_func(exports, i++);
auto get_var_i64_import = get_export_func(exports, i++);
auto get_const_f32_export = get_export_func(exports, i++);
auto get_const_i64_export = get_export_func(exports, i++);
auto get_var_f32_export = get_export_func(exports, i++);
auto get_var_i64_export = get_export_func(exports, i++);
auto set_var_f32_import = get_export_func(exports, i++);
auto set_var_i64_import = get_export_func(exports, i++);
auto set_var_f32_export = get_export_func(exports, i++);
auto set_var_i64_export = get_export_func(exports, i++);
// Interact.
std::cout << "Accessing globals..." << std::endl;
// Check initial values.
check(const_f32_import->get().f32(), 1);
check(const_i64_import->get().i64(), 2);
check(var_f32_import->get().f32(), 3);
check(var_i64_import->get().i64(), 4);
check(const_f32_export->get().f32(), 5);
check(const_i64_export->get().i64(), 6);
check(var_f32_export->get().f32(), 7);
check(var_i64_export->get().i64(), 8);
check(call(get_const_f32_import).f32(), 1);
check(call(get_const_i64_import).i64(), 2);
check(call(get_var_f32_import).f32(), 3);
check(call(get_var_i64_import).i64(), 4);
check(call(get_const_f32_export).f32(), 5);
check(call(get_const_i64_export).i64(), 6);
check(call(get_var_f32_export).f32(), 7);
check(call(get_var_i64_export).i64(), 8);
// Modify variables through API and check again.
var_f32_import->set(wasm::Val::f32(33));
var_i64_import->set(wasm::Val::i64(34));
var_f32_export->set(wasm::Val::f32(37));
var_i64_export->set(wasm::Val::i64(38));
check(var_f32_import->get().f32(), 33);
check(var_i64_import->get().i64(), 34);
check(var_f32_export->get().f32(), 37);
check(var_i64_export->get().i64(), 38);
check(call(get_var_f32_import).f32(), 33);
check(call(get_var_i64_import).i64(), 34);
check(call(get_var_f32_export).f32(), 37);
check(call(get_var_i64_export).i64(), 38);
// Modify variables through calls and check again.
call(set_var_f32_import, wasm::Val::f32(73));
call(set_var_i64_import, wasm::Val::i64(74));
call(set_var_f32_export, wasm::Val::f32(77));
call(set_var_i64_export, wasm::Val::i64(78));
check(var_f32_import->get().f32(), 73);
check(var_i64_import->get().i64(), 74);
check(var_f32_export->get().f32(), 77);
check(var_i64_export->get().i64(), 78);
check(call(get_var_f32_import).f32(), 73);
check(call(get_var_i64_import).i64(), 74);
check(call(get_var_f32_export).f32(), 77);
check(call(get_var_i64_export).i64(), 78);
// Shut down.
std::cout << "Shutting down..." << std::endl;
}
int main(int argc, const char* argv[]) {
run();
std::cout << "Done." << std::endl;
return 0;
}