b19d37763b02c52358cbcf90c0b9ffbaad43fb78
[platform/framework/web/lwnode.git] /
1 #include <iostream>
2 #include <fstream>
3 #include <cstdlib>
4 #include <string>
5 #include <cinttypes>
6
7 #include "wasm.hh"
8
9
10 // A function to be called from Wasm code.
11 auto neg_callback(
12   const wasm::Val args[], wasm::Val results[]
13 ) -> wasm::own<wasm::Trap> {
14   std::cout << "Calling back..." << std::endl;
15   results[0] = wasm::Val(-args[0].i32());
16   return nullptr;
17 }
18
19
20 auto get_export_table(wasm::ownvec<wasm::Extern>& exports, size_t i) -> wasm::Table* {
21   if (exports.size() <= i || !exports[i]->table()) {
22     std::cout << "> Error accessing table export " << i << "!" << std::endl;
23     exit(1);
24   }
25   return exports[i]->table();
26 }
27
28 auto get_export_func(const wasm::ownvec<wasm::Extern>& exports, size_t i) -> const wasm::Func* {
29   if (exports.size() <= i || !exports[i]->func()) {
30     std::cout << "> Error accessing function export " << i << "!" << std::endl;
31     exit(1);
32   }
33   return exports[i]->func();
34 }
35
36 template<class T, class U>
37 void check(T actual, U expected) {
38   if (actual != expected) {
39     std::cout << "> Error on result, expected " << expected << ", got " << actual << std::endl;
40     exit(1);
41   }
42 }
43
44 void check(bool success) {
45   if (! success) {
46     std::cout << "> Error, expected success" << std::endl;
47     exit(1);
48   }
49 }
50
51 auto call(
52   const wasm::Func* func, wasm::Val&& arg1, wasm::Val&& arg2
53 ) -> wasm::Val {
54   wasm::Val args[2] = {std::move(arg1), std::move(arg2)};
55   wasm::Val results[1];
56   if (func->call(args, results)) {
57     std::cout << "> Error on result, expected return" << std::endl;
58     exit(1);
59   }
60   return results[0].copy();
61 }
62
63 void check_trap(const wasm::Func* func, wasm::Val&& arg1, wasm::Val&& arg2) {
64   wasm::Val args[2] = {std::move(arg1), std::move(arg2)};
65   wasm::Val results[1];
66   if (! func->call(args, results)) {
67     std::cout << "> Error on result, expected trap" << std::endl;
68     exit(1);
69   }
70 }
71
72 void run() {
73   // Initialize.
74   std::cout << "Initializing..." << std::endl;
75   auto engine = wasm::Engine::make();
76   auto store_ = wasm::Store::make(engine.get());
77   auto store = store_.get();
78
79   // Load binary.
80   std::cout << "Loading binary..." << std::endl;
81   std::ifstream file("table.wasm");
82   file.seekg(0, std::ios_base::end);
83   auto file_size = file.tellg();
84   file.seekg(0);
85   auto binary = wasm::vec<byte_t>::make_uninitialized(file_size);
86   file.read(binary.get(), file_size);
87   file.close();
88   if (file.fail()) {
89     std::cout << "> Error loading module!" << std::endl;
90     exit(1);
91   }
92
93   // Compile.
94   std::cout << "Compiling module..." << std::endl;
95   auto module = wasm::Module::make(store, binary);
96   if (!module) {
97     std::cout << "> Error compiling module!" << std::endl;
98     exit(1);
99   }
100
101   // Instantiate.
102   std::cout << "Instantiating module..." << std::endl;
103   auto instance = wasm::Instance::make(store, module.get(), nullptr);
104   if (!instance) {
105     std::cout << "> Error instantiating module!" << std::endl;
106     exit(1);
107   }
108
109   // Extract export.
110   std::cout << "Extracting exports..." << std::endl;
111   auto exports = instance->exports();
112   size_t i = 0;
113   auto table = get_export_table(exports, i++);
114   auto call_indirect = get_export_func(exports, i++);
115   auto f = get_export_func(exports, i++);
116   auto g = get_export_func(exports, i++);
117
118   // Create external function.
119   std::cout << "Creating callback..." << std::endl;
120   auto neg_type = wasm::FuncType::make(
121     wasm::ownvec<wasm::ValType>::make(wasm::ValType::make(wasm::I32)),
122     wasm::ownvec<wasm::ValType>::make(wasm::ValType::make(wasm::I32))
123   );
124   auto h = wasm::Func::make(store, neg_type.get(), neg_callback);
125
126   // Try cloning.
127   assert(table->copy()->same(table));
128
129   // Check initial table.
130   std::cout << "Checking table..." << std::endl;
131   check(table->size(), 2u);
132   check(table->get(0) == nullptr);
133   check(table->get(1) != nullptr);
134   check_trap(call_indirect, wasm::Val::i32(0), wasm::Val::i32(0));
135   check(call(call_indirect, wasm::Val::i32(7), wasm::Val::i32(1)).i32(), 7);
136   check_trap(call_indirect, wasm::Val::i32(0), wasm::Val::i32(2));
137
138   // Mutate table.
139   std::cout << "Mutating table..." << std::endl;
140   check(table->set(0, g));
141   check(table->set(1, nullptr));
142   check(! table->set(2, f));
143   check(table->get(0) != nullptr);
144   check(table->get(1) == nullptr);
145   check(call(call_indirect, wasm::Val::i32(7), wasm::Val::i32(0)).i32(), 666);
146   check_trap(call_indirect, wasm::Val::i32(0), wasm::Val::i32(1));
147   check_trap(call_indirect, wasm::Val::i32(0), wasm::Val::i32(2));
148
149   // Grow table.
150   std::cout << "Growing table..." << std::endl;
151   check(table->grow(3));
152   check(table->size(), 5u);
153   check(table->set(2, f));
154   check(table->set(3, h.get()));
155   check(! table->set(5, nullptr));
156   check(table->get(2) != nullptr);
157   check(table->get(3) != nullptr);
158   check(table->get(4) == nullptr);
159   check(call(call_indirect, wasm::Val::i32(5), wasm::Val::i32(2)).i32(), 5);
160   check(call(call_indirect, wasm::Val::i32(6), wasm::Val::i32(3)).i32(), -6);
161   check_trap(call_indirect, wasm::Val::i32(0), wasm::Val::i32(4));
162   check_trap(call_indirect, wasm::Val::i32(0), wasm::Val::i32(5));
163
164   check(table->grow(2, f));
165   check(table->size(), 7u);
166   check(table->get(5) != nullptr);
167   check(table->get(6) != nullptr);
168
169   check(! table->grow(5));
170   check(table->grow(3));
171   check(table->grow(0));
172
173   // Create stand-alone table.
174   // TODO(wasm+): Once Wasm allows multiple tables, turn this into import.
175   std::cout << "Creating stand-alone table..." << std::endl;
176   auto tabletype = wasm::TableType::make(
177     wasm::ValType::make(wasm::FUNCREF), wasm::Limits(5, 5));
178   auto table2 = wasm::Table::make(store, tabletype.get());
179   check(table2->size() == 5);
180   check(! table2->grow(1));
181   check(table2->grow(0));
182
183   // Shut down.
184   std::cout << "Shutting down..." << std::endl;
185 }
186
187
188 int main(int argc, const char* argv[]) {
189   run();
190   std::cout << "Done." << std::endl;
191   return 0;
192 }