Interpreter.cpp 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817
  1. /*
  2. * Copyright (c) 2021, Ali Mohammad Pur <mpfard@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Debug.h>
  7. #include <LibWasm/AbstractMachine/AbstractMachine.h>
  8. #include <LibWasm/AbstractMachine/Configuration.h>
  9. #include <LibWasm/AbstractMachine/Interpreter.h>
  10. #include <LibWasm/Opcode.h>
  11. #include <LibWasm/Printer/Printer.h>
  12. #include <math.h>
  13. namespace Wasm {
  14. #define TRAP_IF_NOT(x) \
  15. do { \
  16. if (trap_if_not(x)) \
  17. return; \
  18. } while (false)
  19. void Interpreter::interpret(Configuration& configuration)
  20. {
  21. auto& instructions = configuration.frame()->expression().instructions();
  22. auto max_ip_value = InstructionPointer { instructions.size() };
  23. auto& current_ip_value = configuration.ip();
  24. while (current_ip_value < max_ip_value) {
  25. auto& instruction = instructions[current_ip_value.value()];
  26. auto old_ip = current_ip_value;
  27. interpret(configuration, current_ip_value, instruction);
  28. if (m_do_trap)
  29. return;
  30. if (current_ip_value == old_ip) // If no jump occurred
  31. ++current_ip_value;
  32. }
  33. }
  34. void Interpreter::branch_to_label(Configuration& configuration, LabelIndex index)
  35. {
  36. dbgln_if(WASM_TRACE_DEBUG, "Branch to label with index {}...", index.value());
  37. auto label = configuration.nth_label(index.value());
  38. TRAP_IF_NOT(label.has_value());
  39. dbgln_if(WASM_TRACE_DEBUG, "...which is actually IP {}, and has {} result(s)", label->continuation().value(), label->arity());
  40. auto results = pop_values(configuration, label->arity());
  41. size_t drop_count = index.value() + 1;
  42. for (; !configuration.stack().is_empty();) {
  43. auto& entry = configuration.stack().peek();
  44. if (entry.has<NonnullOwnPtr<Label>>()) {
  45. if (drop_count-- == 0)
  46. break;
  47. }
  48. configuration.stack().pop();
  49. }
  50. // Push results in reverse
  51. for (size_t i = results.size(); i > 0; --i)
  52. configuration.stack().push(move(static_cast<Vector<NonnullOwnPtr<Value>>&>(results)[i - 1]));
  53. configuration.ip() = label->continuation();
  54. }
  55. ReadonlyBytes Interpreter::load_from_memory(Configuration& configuration, const Instruction& instruction, size_t size)
  56. {
  57. auto& address = configuration.frame()->module().memories().first();
  58. auto memory = configuration.store().get(address);
  59. if (!memory) {
  60. m_do_trap = true;
  61. return {};
  62. }
  63. auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
  64. auto base = configuration.stack().pop().get<NonnullOwnPtr<Value>>()->to<i32>();
  65. if (!base.has_value()) {
  66. m_do_trap = true;
  67. return {};
  68. }
  69. auto instance_address = base.value() + static_cast<i64>(arg.offset);
  70. if (instance_address < 0 || static_cast<u64>(instance_address + size) > memory->size()) {
  71. m_do_trap = true;
  72. dbgln("LibWasm: Memory access out of bounds (expected 0 > {} and {} > {})", instance_address, instance_address + size, memory->size());
  73. return {};
  74. }
  75. dbgln_if(WASM_TRACE_DEBUG, "load({} : {}) -> stack", instance_address, size);
  76. return memory->data().bytes().slice(instance_address, size);
  77. }
  78. void Interpreter::store_to_memory(Configuration& configuration, const Instruction& instruction, ReadonlyBytes data)
  79. {
  80. auto& address = configuration.frame()->module().memories().first();
  81. auto memory = configuration.store().get(address);
  82. TRAP_IF_NOT(memory);
  83. auto& arg = instruction.arguments().get<Instruction::MemoryArgument>();
  84. auto base = configuration.stack().pop().get<NonnullOwnPtr<Value>>()->to<i32>();
  85. TRAP_IF_NOT(base.has_value());
  86. auto instance_address = base.value() + static_cast<i64>(arg.offset);
  87. if (instance_address < 0 || static_cast<u64>(instance_address + data.size()) > memory->size()) {
  88. m_do_trap = true;
  89. dbgln("LibWasm: Memory access out of bounds (expected 0 > {} and {} > {})", instance_address, instance_address + data.size(), memory->size());
  90. return;
  91. }
  92. dbgln_if(WASM_TRACE_DEBUG, "tempoaray({}b) -> store({})", data.size(), instance_address);
  93. data.copy_to(memory->data().bytes().slice(instance_address, data.size()));
  94. }
  95. void Interpreter::call_address(Configuration& configuration, FunctionAddress address)
  96. {
  97. auto instance = configuration.store().get(address);
  98. TRAP_IF_NOT(instance);
  99. const FunctionType* type { nullptr };
  100. instance->visit([&](const auto& function) { type = &function.type(); });
  101. TRAP_IF_NOT(type);
  102. Vector<Value> args;
  103. args.ensure_capacity(type->parameters().size());
  104. for (size_t i = 0; i < type->parameters().size(); ++i) {
  105. args.prepend(move(*configuration.stack().pop().get<NonnullOwnPtr<Value>>()));
  106. }
  107. Configuration function_configuration { configuration.store() };
  108. function_configuration.depth() = configuration.depth() + 1;
  109. auto result = function_configuration.call(address, move(args));
  110. if (result.is_trap()) {
  111. m_do_trap = true;
  112. return;
  113. }
  114. for (auto& entry : result.values())
  115. configuration.stack().push(make<Value>(move(entry)));
  116. }
  117. #define BINARY_NUMERIC_OPERATION(type, operator, cast, ...) \
  118. do { \
  119. auto rhs = configuration.stack().pop().get<NonnullOwnPtr<Value>>()->to<type>(); \
  120. auto lhs = configuration.stack().pop().get<NonnullOwnPtr<Value>>()->to<type>(); \
  121. TRAP_IF_NOT(lhs.has_value()); \
  122. TRAP_IF_NOT(rhs.has_value()); \
  123. __VA_ARGS__; \
  124. auto result = lhs.value() operator rhs.value(); \
  125. dbgln_if(WASM_TRACE_DEBUG, "{} {} {} = {}", lhs.value(), #operator, rhs.value(), result); \
  126. configuration.stack().push(make<Value>(cast(result))); \
  127. return; \
  128. } while (false)
  129. #define OVF_CHECKED_BINARY_NUMERIC_OPERATION(type, operator, cast, ...) \
  130. do { \
  131. auto rhs = configuration.stack().pop().get<NonnullOwnPtr<Value>>()->to<type>(); \
  132. auto ulhs = configuration.stack().pop().get<NonnullOwnPtr<Value>>()->to<type>(); \
  133. TRAP_IF_NOT(ulhs.has_value()); \
  134. TRAP_IF_NOT(rhs.has_value()); \
  135. dbgln_if(WASM_TRACE_DEBUG, "{} {} {} = ??", ulhs.value(), #operator, rhs.value()); \
  136. __VA_ARGS__; \
  137. Checked lhs = ulhs.value(); \
  138. lhs operator##= rhs.value(); \
  139. TRAP_IF_NOT(!lhs.has_overflow()); \
  140. auto result = lhs.value(); \
  141. dbgln_if(WASM_TRACE_DEBUG, "{} {} {} = {}", ulhs.value(), #operator, rhs.value(), result); \
  142. configuration.stack().push(make<Value>(cast(result))); \
  143. return; \
  144. } while (false)
  145. #define BINARY_PREFIX_NUMERIC_OPERATION(type, operation, cast, ...) \
  146. do { \
  147. auto rhs = configuration.stack().pop().get<NonnullOwnPtr<Value>>()->to<type>(); \
  148. auto lhs = configuration.stack().pop().get<NonnullOwnPtr<Value>>()->to<type>(); \
  149. TRAP_IF_NOT(lhs.has_value()); \
  150. TRAP_IF_NOT(rhs.has_value()); \
  151. auto result = operation(lhs.value(), rhs.value()); \
  152. dbgln_if(WASM_TRACE_DEBUG, "{}({} {}) = {}", #operation, lhs.value(), rhs.value(), result); \
  153. configuration.stack().push(make<Value>(cast(result))); \
  154. return; \
  155. } while (false)
  156. #define UNARY_MAP(pop_type, operation, ...) \
  157. do { \
  158. auto value = configuration.stack().pop().get<NonnullOwnPtr<Value>>()->to<pop_type>(); \
  159. TRAP_IF_NOT(value.has_value()); \
  160. auto result = operation(value.value()); \
  161. dbgln_if(WASM_TRACE_DEBUG, "map({}) {} = {}", #operation, value.value(), result); \
  162. configuration.stack().push(make<Value>(__VA_ARGS__(result))); \
  163. return; \
  164. } while (false)
  165. #define UNARY_NUMERIC_OPERATION(type, operation) \
  166. UNARY_MAP(type, operation, type)
  167. #define LOAD_AND_PUSH(read_type, push_type) \
  168. do { \
  169. auto slice = load_from_memory(configuration, instruction, sizeof(read_type)); \
  170. TRAP_IF_NOT(slice.size() == sizeof(read_type)); \
  171. if constexpr (sizeof(read_type) == 1) \
  172. configuration.stack().push(make<Value>(static_cast<push_type>(slice[0]))); \
  173. else \
  174. configuration.stack().push(make<Value>(read_value<push_type>(slice))); \
  175. return; \
  176. } while (false)
  177. #define POP_AND_STORE(pop_type, store_type) \
  178. do { \
  179. auto value = ConvertToRaw<pop_type> {}(*configuration.stack().pop().get<NonnullOwnPtr<Value>>()->to<pop_type>()); \
  180. dbgln_if(WASM_TRACE_DEBUG, "stack({}) -> temporary({}b)", value, sizeof(store_type)); \
  181. store_to_memory(configuration, instruction, { &value, sizeof(store_type) }); \
  182. return; \
  183. } while (false)
  184. template<typename T>
  185. static T read_value(ReadonlyBytes data)
  186. {
  187. T value;
  188. InputMemoryStream stream { data };
  189. auto ok = IsSigned<T> ? LEB128::read_signed(stream, value) : LEB128::read_unsigned(stream, value);
  190. VERIFY(ok);
  191. return value;
  192. }
  193. template<>
  194. float read_value<float>(ReadonlyBytes data)
  195. {
  196. InputMemoryStream stream { data };
  197. LittleEndian<u32> raw_value;
  198. stream >> raw_value;
  199. VERIFY(!stream.has_any_error());
  200. return bit_cast<float>(static_cast<u32>(raw_value));
  201. }
  202. template<>
  203. double read_value<double>(ReadonlyBytes data)
  204. {
  205. InputMemoryStream stream { data };
  206. LittleEndian<u64> raw_value;
  207. stream >> raw_value;
  208. VERIFY(!stream.has_any_error());
  209. return bit_cast<double>(static_cast<u64>(raw_value));
  210. }
  211. template<typename T>
  212. struct ConvertToRaw {
  213. T operator()(T value)
  214. {
  215. return value;
  216. }
  217. };
  218. template<>
  219. struct ConvertToRaw<float> {
  220. u32 operator()(float value)
  221. {
  222. LittleEndian<u32> res;
  223. ReadonlyBytes bytes { &value, sizeof(float) };
  224. InputMemoryStream stream { bytes };
  225. stream >> res;
  226. VERIFY(!stream.has_any_error());
  227. return static_cast<u32>(res);
  228. }
  229. };
  230. template<>
  231. struct ConvertToRaw<double> {
  232. u64 operator()(double value)
  233. {
  234. LittleEndian<u64> res;
  235. ReadonlyBytes bytes { &value, sizeof(double) };
  236. InputMemoryStream stream { bytes };
  237. stream >> res;
  238. VERIFY(!stream.has_any_error());
  239. return static_cast<u64>(res);
  240. }
  241. };
  242. Vector<NonnullOwnPtr<Value>> Interpreter::pop_values(Configuration& configuration, size_t count)
  243. {
  244. Vector<NonnullOwnPtr<Value>> results;
  245. // Pop results in order
  246. for (size_t i = 0; i < count; ++i) {
  247. auto top_of_stack = configuration.stack().pop();
  248. if (auto value = top_of_stack.get_pointer<NonnullOwnPtr<Value>>())
  249. results.append(move(*value));
  250. else
  251. trap_if_not(value);
  252. }
  253. return results;
  254. }
  255. void Interpreter::interpret(Configuration& configuration, InstructionPointer& ip, const Instruction& instruction)
  256. {
  257. dbgln_if(WASM_TRACE_DEBUG, "Executing instruction {} at ip {}", instruction_name(instruction.opcode()), ip.value());
  258. if constexpr (WASM_TRACE_DEBUG)
  259. configuration.dump_stack();
  260. switch (instruction.opcode().value()) {
  261. case Instructions::unreachable.value():
  262. m_do_trap = true;
  263. return;
  264. case Instructions::nop.value():
  265. return;
  266. case Instructions::local_get.value():
  267. configuration.stack().push(make<Value>(configuration.frame()->locals()[instruction.arguments().get<LocalIndex>().value()]));
  268. return;
  269. case Instructions::local_set.value(): {
  270. auto entry = configuration.stack().pop();
  271. configuration.frame()->locals()[instruction.arguments().get<LocalIndex>().value()] = move(*entry.get<NonnullOwnPtr<Value>>());
  272. return;
  273. }
  274. case Instructions::i32_const.value():
  275. configuration.stack().push(make<Value>(ValueType { ValueType::I32 }, static_cast<i64>(instruction.arguments().get<i32>())));
  276. return;
  277. case Instructions::i64_const.value():
  278. configuration.stack().push(make<Value>(ValueType { ValueType::I64 }, instruction.arguments().get<i64>()));
  279. return;
  280. case Instructions::f32_const.value():
  281. configuration.stack().push(make<Value>(ValueType { ValueType::F32 }, static_cast<double>(instruction.arguments().get<float>())));
  282. return;
  283. case Instructions::f64_const.value():
  284. configuration.stack().push(make<Value>(ValueType { ValueType::F64 }, instruction.arguments().get<double>()));
  285. return;
  286. case Instructions::block.value(): {
  287. size_t arity = 0;
  288. auto& args = instruction.arguments().get<Instruction::StructuredInstructionArgs>();
  289. if (args.block_type.kind() != BlockType::Empty)
  290. arity = 1;
  291. configuration.stack().push(make<Label>(arity, args.end_ip));
  292. return;
  293. }
  294. case Instructions::loop.value(): {
  295. size_t arity = 0;
  296. auto& args = instruction.arguments().get<Instruction::StructuredInstructionArgs>();
  297. if (args.block_type.kind() != BlockType::Empty)
  298. arity = 1;
  299. configuration.stack().push(make<Label>(arity, ip.value()));
  300. return;
  301. }
  302. case Instructions::if_.value(): {
  303. size_t arity = 0;
  304. auto& args = instruction.arguments().get<Instruction::StructuredInstructionArgs>();
  305. if (args.block_type.kind() != BlockType::Empty)
  306. arity = 1;
  307. auto entry = configuration.stack().pop();
  308. auto value = entry.get<NonnullOwnPtr<Value>>()->to<i32>();
  309. TRAP_IF_NOT(value.has_value());
  310. configuration.stack().push(make<Label>(arity, args.end_ip));
  311. if (value.value() == 0) {
  312. if (args.else_ip.has_value()) {
  313. configuration.ip() = args.else_ip.value();
  314. } else {
  315. configuration.ip() = args.end_ip;
  316. configuration.stack().pop();
  317. }
  318. }
  319. return;
  320. }
  321. case Instructions::structured_end.value():
  322. return;
  323. case Instructions::structured_else.value(): {
  324. auto label = configuration.nth_label(0);
  325. TRAP_IF_NOT(label.has_value());
  326. auto results = pop_values(configuration, label->arity());
  327. // drop all locals
  328. for (; !configuration.stack().is_empty();) {
  329. auto entry = configuration.stack().pop();
  330. if (entry.has<NonnullOwnPtr<Label>>())
  331. break;
  332. }
  333. // Push results in reverse
  334. for (size_t i = 1; i < results.size() + 1; ++i)
  335. configuration.stack().push(move(static_cast<Vector<NonnullOwnPtr<Value>>&>(results)[results.size() - i]));
  336. if (instruction.opcode() == Instructions::structured_end)
  337. return;
  338. // Jump to the end label
  339. configuration.ip() = label->continuation();
  340. return;
  341. }
  342. case Instructions::return_.value(): {
  343. Vector<Stack::EntryType> results;
  344. auto& frame = *configuration.frame();
  345. results.ensure_capacity(frame.arity());
  346. for (size_t i = 0; i < frame.arity(); ++i)
  347. results.prepend(configuration.stack().pop());
  348. // drop all locals
  349. OwnPtr<Label> last_label;
  350. for (; !configuration.stack().is_empty();) {
  351. auto entry = configuration.stack().pop();
  352. if (entry.has<NonnullOwnPtr<Label>>()) {
  353. last_label = move(entry.get<NonnullOwnPtr<Label>>());
  354. continue;
  355. }
  356. if (entry.has<NonnullOwnPtr<Frame>>()) {
  357. // Push the frame back
  358. configuration.stack().push(move(entry));
  359. // Push its label back (if there is one)
  360. if (last_label)
  361. configuration.stack().push(last_label.release_nonnull());
  362. break;
  363. }
  364. last_label.clear();
  365. }
  366. // Push the results back
  367. for (auto& result : results)
  368. configuration.stack().push(move(result));
  369. // Jump past the call/indirect instruction
  370. configuration.ip() = configuration.frame()->expression().instructions().size() - 1;
  371. return;
  372. }
  373. case Instructions::br.value():
  374. return branch_to_label(configuration, instruction.arguments().get<LabelIndex>());
  375. case Instructions::br_if.value(): {
  376. if (configuration.stack().pop().get<NonnullOwnPtr<Value>>()->to<i32>().value_or(0) == 0)
  377. return;
  378. return branch_to_label(configuration, instruction.arguments().get<LabelIndex>());
  379. }
  380. case Instructions::br_table.value():
  381. goto unimplemented;
  382. case Instructions::call.value(): {
  383. auto index = instruction.arguments().get<FunctionIndex>();
  384. auto address = configuration.frame()->module().functions()[index.value()];
  385. dbgln_if(WASM_TRACE_DEBUG, "call({})", address.value());
  386. call_address(configuration, address);
  387. return;
  388. }
  389. case Instructions::call_indirect.value(): {
  390. auto& args = instruction.arguments().get<Instruction::IndirectCallArgs>();
  391. auto table_address = configuration.frame()->module().tables()[args.table.value()];
  392. auto table_instance = configuration.store().get(table_address);
  393. auto index = configuration.stack().pop().get<NonnullOwnPtr<Value>>()->to<i32>();
  394. TRAP_IF_NOT(index.has_value());
  395. if (index.value() < 0 || static_cast<size_t>(index.value()) >= table_instance->elements().size()) {
  396. dbgln("LibWasm: Element access out of bounds, expected {0} > 0 and {0} < {1}", index.value(), table_instance->elements().size());
  397. m_do_trap = true;
  398. return;
  399. }
  400. auto element = table_instance->elements()[index.value()];
  401. if (!element.has_value() || !element->ref().has<FunctionAddress>()) {
  402. dbgln("LibWasm: call_indirect attempted with invalid address element (not a function)");
  403. m_do_trap = true;
  404. return;
  405. }
  406. auto address = element->ref().get<FunctionAddress>();
  407. dbgln_if(WASM_TRACE_DEBUG, "call_indirect({} -> {})", index.value(), address.value());
  408. call_address(configuration, address);
  409. return;
  410. }
  411. case Instructions::i32_load.value():
  412. LOAD_AND_PUSH(i32, i32);
  413. case Instructions::i64_load.value():
  414. LOAD_AND_PUSH(i64, i64);
  415. case Instructions::f32_load.value():
  416. LOAD_AND_PUSH(float, float);
  417. case Instructions::f64_load.value():
  418. LOAD_AND_PUSH(double, double);
  419. case Instructions::i32_load8_s.value():
  420. LOAD_AND_PUSH(i8, i32);
  421. case Instructions::i32_load8_u.value():
  422. LOAD_AND_PUSH(u8, i32);
  423. case Instructions::i32_load16_s.value():
  424. LOAD_AND_PUSH(i16, i32);
  425. case Instructions::i32_load16_u.value():
  426. LOAD_AND_PUSH(u16, i32);
  427. case Instructions::i64_load8_s.value():
  428. LOAD_AND_PUSH(i8, i64);
  429. case Instructions::i64_load8_u.value():
  430. LOAD_AND_PUSH(u8, i64);
  431. case Instructions::i64_load16_s.value():
  432. LOAD_AND_PUSH(i16, i64);
  433. case Instructions::i64_load16_u.value():
  434. LOAD_AND_PUSH(u16, i64);
  435. case Instructions::i64_load32_s.value():
  436. LOAD_AND_PUSH(i32, i64);
  437. case Instructions::i64_load32_u.value():
  438. LOAD_AND_PUSH(u32, i64);
  439. case Instructions::i32_store.value():
  440. POP_AND_STORE(i32, i32);
  441. case Instructions::i64_store.value():
  442. POP_AND_STORE(i64, i64);
  443. case Instructions::f32_store.value():
  444. POP_AND_STORE(float, float);
  445. case Instructions::f64_store.value():
  446. POP_AND_STORE(double, double);
  447. case Instructions::i32_store8.value():
  448. POP_AND_STORE(i32, i8);
  449. case Instructions::i32_store16.value():
  450. POP_AND_STORE(i32, i16);
  451. case Instructions::i64_store8.value():
  452. POP_AND_STORE(i64, i8);
  453. case Instructions::i64_store16.value():
  454. POP_AND_STORE(i64, i16);
  455. case Instructions::i64_store32.value():
  456. POP_AND_STORE(i64, i32);
  457. case Instructions::local_tee.value(): {
  458. auto value = *configuration.stack().peek().get<NonnullOwnPtr<Value>>();
  459. auto local_index = instruction.arguments().get<LocalIndex>();
  460. TRAP_IF_NOT(configuration.frame()->locals().size() > local_index.value());
  461. dbgln_if(WASM_TRACE_DEBUG, "stack:peek -> locals({})", local_index.value());
  462. configuration.frame()->locals()[local_index.value()] = move(value);
  463. return;
  464. }
  465. case Instructions::global_get.value(): {
  466. auto global_index = instruction.arguments().get<GlobalIndex>();
  467. TRAP_IF_NOT(configuration.frame()->module().globals().size() > global_index.value());
  468. auto address = configuration.frame()->module().globals()[global_index.value()];
  469. dbgln_if(WASM_TRACE_DEBUG, "global({}) -> stack", address.value());
  470. auto global = configuration.store().get(address);
  471. configuration.stack().push(make<Value>(global->value()));
  472. return;
  473. }
  474. case Instructions::global_set.value(): {
  475. auto global_index = instruction.arguments().get<GlobalIndex>();
  476. TRAP_IF_NOT(configuration.frame()->module().globals().size() > global_index.value());
  477. auto address = configuration.frame()->module().globals()[global_index.value()];
  478. auto value = *configuration.stack().pop().get<NonnullOwnPtr<Value>>();
  479. dbgln_if(WASM_TRACE_DEBUG, "stack -> global({})", address.value());
  480. auto global = configuration.store().get(address);
  481. global->set_value(move(value));
  482. return;
  483. }
  484. case Instructions::memory_size.value(): {
  485. auto address = configuration.frame()->module().memories()[0];
  486. auto instance = configuration.store().get(address);
  487. auto pages = instance->size() / Constants::page_size;
  488. dbgln_if(WASM_TRACE_DEBUG, "memory.size -> stack({})", pages);
  489. configuration.stack().push(make<Value>((i32)pages));
  490. return;
  491. }
  492. case Instructions::memory_grow.value(): {
  493. auto address = configuration.frame()->module().memories()[0];
  494. auto instance = configuration.store().get(address);
  495. i32 old_pages = instance->size() / Constants::page_size;
  496. auto new_pages = configuration.stack().pop().get<NonnullOwnPtr<Value>>()->to<i32>();
  497. TRAP_IF_NOT(new_pages.has_value());
  498. dbgln_if(WASM_TRACE_DEBUG, "memory.grow({}), previously {} pages...", *new_pages, old_pages);
  499. if (instance->grow(new_pages.value() * Constants::page_size))
  500. configuration.stack().push(make<Value>((i32)old_pages));
  501. else
  502. configuration.stack().push(make<Value>((i32)-1));
  503. return;
  504. }
  505. case Instructions::table_get.value():
  506. case Instructions::table_set.value():
  507. case Instructions::ref_null.value():
  508. case Instructions::ref_func.value():
  509. case Instructions::ref_is_null.value():
  510. goto unimplemented;
  511. case Instructions::drop.value():
  512. configuration.stack().pop();
  513. return;
  514. case Instructions::select.value():
  515. case Instructions::select_typed.value(): {
  516. // Note: The type seems to only be used for validation.
  517. auto value = configuration.stack().pop().get<NonnullOwnPtr<Value>>()->to<i32>();
  518. TRAP_IF_NOT(value.has_value());
  519. dbgln_if(WASM_TRACE_DEBUG, "select({})", value.value());
  520. auto rhs = move(configuration.stack().pop().get<NonnullOwnPtr<Value>>());
  521. auto lhs = move(configuration.stack().pop().get<NonnullOwnPtr<Value>>());
  522. configuration.stack().push(value.value() != 0 ? move(lhs) : move(rhs));
  523. return;
  524. }
  525. case Instructions::i32_eqz.value():
  526. UNARY_NUMERIC_OPERATION(i32, 0 ==);
  527. case Instructions::i32_eq.value():
  528. BINARY_NUMERIC_OPERATION(i32, ==, i32);
  529. case Instructions::i32_ne.value():
  530. BINARY_NUMERIC_OPERATION(i32, !=, i32);
  531. case Instructions::i32_lts.value():
  532. BINARY_NUMERIC_OPERATION(i32, <, i32);
  533. case Instructions::i32_ltu.value():
  534. BINARY_NUMERIC_OPERATION(u32, <, i32);
  535. case Instructions::i32_gts.value():
  536. BINARY_NUMERIC_OPERATION(i32, >, i32);
  537. case Instructions::i32_gtu.value():
  538. BINARY_NUMERIC_OPERATION(u32, >, i32);
  539. case Instructions::i32_les.value():
  540. BINARY_NUMERIC_OPERATION(i32, <=, i32);
  541. case Instructions::i32_leu.value():
  542. BINARY_NUMERIC_OPERATION(u32, <=, i32);
  543. case Instructions::i32_ges.value():
  544. BINARY_NUMERIC_OPERATION(i32, >=, i32);
  545. case Instructions::i32_geu.value():
  546. BINARY_NUMERIC_OPERATION(u32, >=, i32);
  547. case Instructions::i64_eqz.value():
  548. UNARY_NUMERIC_OPERATION(i64, 0ull ==);
  549. case Instructions::i64_eq.value():
  550. BINARY_NUMERIC_OPERATION(i64, ==, i32);
  551. case Instructions::i64_ne.value():
  552. BINARY_NUMERIC_OPERATION(i64, !=, i32);
  553. case Instructions::i64_lts.value():
  554. BINARY_NUMERIC_OPERATION(i64, <, i32);
  555. case Instructions::i64_ltu.value():
  556. BINARY_NUMERIC_OPERATION(u64, <, i32);
  557. case Instructions::i64_gts.value():
  558. BINARY_NUMERIC_OPERATION(i64, >, i32);
  559. case Instructions::i64_gtu.value():
  560. BINARY_NUMERIC_OPERATION(u64, >, i32);
  561. case Instructions::i64_les.value():
  562. BINARY_NUMERIC_OPERATION(i64, <=, i32);
  563. case Instructions::i64_leu.value():
  564. BINARY_NUMERIC_OPERATION(u64, <=, i32);
  565. case Instructions::i64_ges.value():
  566. BINARY_NUMERIC_OPERATION(i64, >=, i32);
  567. case Instructions::i64_geu.value():
  568. BINARY_NUMERIC_OPERATION(u64, >=, i32);
  569. case Instructions::f32_eq.value():
  570. BINARY_NUMERIC_OPERATION(float, ==, i32);
  571. case Instructions::f32_ne.value():
  572. BINARY_NUMERIC_OPERATION(float, !=, i32);
  573. case Instructions::f32_lt.value():
  574. BINARY_NUMERIC_OPERATION(float, <, i32);
  575. case Instructions::f32_gt.value():
  576. BINARY_NUMERIC_OPERATION(float, >, i32);
  577. case Instructions::f32_le.value():
  578. BINARY_NUMERIC_OPERATION(float, <=, i32);
  579. case Instructions::f32_ge.value():
  580. BINARY_NUMERIC_OPERATION(float, >=, i32);
  581. case Instructions::f64_eq.value():
  582. BINARY_NUMERIC_OPERATION(double, ==, i32);
  583. case Instructions::f64_ne.value():
  584. BINARY_NUMERIC_OPERATION(double, !=, i32);
  585. case Instructions::f64_lt.value():
  586. BINARY_NUMERIC_OPERATION(double, <, i32);
  587. case Instructions::f64_gt.value():
  588. BINARY_NUMERIC_OPERATION(double, >, i32);
  589. case Instructions::f64_le.value():
  590. BINARY_NUMERIC_OPERATION(double, <=, i32);
  591. case Instructions::f64_ge.value():
  592. BINARY_NUMERIC_OPERATION(double, >, i32);
  593. case Instructions::i32_clz.value():
  594. case Instructions::i32_ctz.value():
  595. case Instructions::i32_popcnt.value():
  596. goto unimplemented;
  597. case Instructions::i32_add.value():
  598. OVF_CHECKED_BINARY_NUMERIC_OPERATION(i32, +, i32);
  599. case Instructions::i32_sub.value():
  600. OVF_CHECKED_BINARY_NUMERIC_OPERATION(i32, -, i32);
  601. case Instructions::i32_mul.value():
  602. OVF_CHECKED_BINARY_NUMERIC_OPERATION(i32, *, i32);
  603. case Instructions::i32_divs.value():
  604. OVF_CHECKED_BINARY_NUMERIC_OPERATION(i32, /, i32, TRAP_IF_NOT(rhs.value() != 0));
  605. case Instructions::i32_divu.value():
  606. OVF_CHECKED_BINARY_NUMERIC_OPERATION(u32, /, i32, TRAP_IF_NOT(rhs.value() != 0));
  607. case Instructions::i32_rems.value():
  608. BINARY_NUMERIC_OPERATION(i32, %, i32, TRAP_IF_NOT(rhs.value() != 0));
  609. case Instructions::i32_remu.value():
  610. BINARY_NUMERIC_OPERATION(u32, %, i32, TRAP_IF_NOT(rhs.value() != 0));
  611. case Instructions::i32_and.value():
  612. BINARY_NUMERIC_OPERATION(i32, &, i32);
  613. case Instructions::i32_or.value():
  614. BINARY_NUMERIC_OPERATION(i32, |, i32);
  615. case Instructions::i32_xor.value():
  616. BINARY_NUMERIC_OPERATION(i32, ^, i32);
  617. case Instructions::i32_shl.value():
  618. BINARY_NUMERIC_OPERATION(i32, <<, i32);
  619. case Instructions::i32_shrs.value():
  620. BINARY_NUMERIC_OPERATION(i32, >>, i32);
  621. case Instructions::i32_shru.value():
  622. BINARY_NUMERIC_OPERATION(u32, >>, i32);
  623. case Instructions::i32_rotl.value():
  624. case Instructions::i32_rotr.value():
  625. case Instructions::i64_clz.value():
  626. case Instructions::i64_ctz.value():
  627. case Instructions::i64_popcnt.value():
  628. goto unimplemented;
  629. case Instructions::i64_add.value():
  630. OVF_CHECKED_BINARY_NUMERIC_OPERATION(i64, +, i64);
  631. case Instructions::i64_sub.value():
  632. OVF_CHECKED_BINARY_NUMERIC_OPERATION(i64, -, i64);
  633. case Instructions::i64_mul.value():
  634. OVF_CHECKED_BINARY_NUMERIC_OPERATION(i64, *, i64);
  635. case Instructions::i64_divs.value():
  636. OVF_CHECKED_BINARY_NUMERIC_OPERATION(i64, /, i64, TRAP_IF_NOT(rhs.value() != 0));
  637. case Instructions::i64_divu.value():
  638. OVF_CHECKED_BINARY_NUMERIC_OPERATION(u64, /, i64, TRAP_IF_NOT(rhs.value() != 0));
  639. case Instructions::i64_rems.value():
  640. BINARY_NUMERIC_OPERATION(i64, %, i64, TRAP_IF_NOT(rhs.value() != 0));
  641. case Instructions::i64_remu.value():
  642. BINARY_NUMERIC_OPERATION(u64, %, i64, TRAP_IF_NOT(rhs.value() != 0));
  643. case Instructions::i64_and.value():
  644. BINARY_NUMERIC_OPERATION(i64, &, i64);
  645. case Instructions::i64_or.value():
  646. BINARY_NUMERIC_OPERATION(i64, |, i64);
  647. case Instructions::i64_xor.value():
  648. BINARY_NUMERIC_OPERATION(i64, ^, i64);
  649. case Instructions::i64_shl.value():
  650. BINARY_NUMERIC_OPERATION(i64, <<, i64);
  651. case Instructions::i64_shrs.value():
  652. BINARY_NUMERIC_OPERATION(i64, >>, i64);
  653. case Instructions::i64_shru.value():
  654. BINARY_NUMERIC_OPERATION(u64, >>, i64);
  655. case Instructions::i64_rotl.value():
  656. case Instructions::i64_rotr.value():
  657. goto unimplemented;
  658. case Instructions::f32_abs.value():
  659. UNARY_NUMERIC_OPERATION(float, fabsf);
  660. case Instructions::f32_neg.value():
  661. UNARY_NUMERIC_OPERATION(float, -);
  662. case Instructions::f32_ceil.value():
  663. UNARY_NUMERIC_OPERATION(float, ceilf);
  664. case Instructions::f32_floor.value():
  665. UNARY_NUMERIC_OPERATION(float, floorf);
  666. case Instructions::f32_trunc.value():
  667. UNARY_NUMERIC_OPERATION(float, truncf);
  668. case Instructions::f32_nearest.value():
  669. UNARY_NUMERIC_OPERATION(float, roundf);
  670. case Instructions::f32_sqrt.value():
  671. UNARY_NUMERIC_OPERATION(float, sqrtf);
  672. case Instructions::f32_add.value():
  673. UNARY_NUMERIC_OPERATION(float, +);
  674. case Instructions::f32_sub.value():
  675. UNARY_NUMERIC_OPERATION(float, -);
  676. case Instructions::f32_mul.value():
  677. BINARY_NUMERIC_OPERATION(float, *, float);
  678. case Instructions::f32_div.value():
  679. BINARY_NUMERIC_OPERATION(float, /, float);
  680. case Instructions::f32_min.value():
  681. BINARY_PREFIX_NUMERIC_OPERATION(float, min, float);
  682. case Instructions::f32_max.value():
  683. BINARY_PREFIX_NUMERIC_OPERATION(float, max, float);
  684. case Instructions::f32_copysign.value():
  685. BINARY_PREFIX_NUMERIC_OPERATION(float, copysignf, float);
  686. case Instructions::f64_abs.value():
  687. UNARY_NUMERIC_OPERATION(double, fabs);
  688. case Instructions::f64_neg.value():
  689. UNARY_NUMERIC_OPERATION(double, -);
  690. case Instructions::f64_ceil.value():
  691. UNARY_NUMERIC_OPERATION(double, ceil);
  692. case Instructions::f64_floor.value():
  693. UNARY_NUMERIC_OPERATION(double, floor);
  694. case Instructions::f64_trunc.value():
  695. UNARY_NUMERIC_OPERATION(double, trunc);
  696. case Instructions::f64_nearest.value():
  697. UNARY_NUMERIC_OPERATION(double, round);
  698. case Instructions::f64_sqrt.value():
  699. UNARY_NUMERIC_OPERATION(double, sqrt);
  700. case Instructions::f64_add.value():
  701. BINARY_NUMERIC_OPERATION(double, +, double);
  702. case Instructions::f64_sub.value():
  703. BINARY_NUMERIC_OPERATION(double, -, double);
  704. case Instructions::f64_mul.value():
  705. BINARY_NUMERIC_OPERATION(double, *, double);
  706. case Instructions::f64_div.value():
  707. BINARY_NUMERIC_OPERATION(double, /, double);
  708. case Instructions::f64_min.value():
  709. BINARY_PREFIX_NUMERIC_OPERATION(double, min, double);
  710. case Instructions::f64_max.value():
  711. BINARY_PREFIX_NUMERIC_OPERATION(double, max, double);
  712. case Instructions::f64_copysign.value():
  713. BINARY_PREFIX_NUMERIC_OPERATION(double, copysign, double);
  714. case Instructions::i32_wrap_i64.value():
  715. UNARY_MAP(i64, i32, i32);
  716. case Instructions::i32_trunc_sf32.value():
  717. case Instructions::i32_trunc_uf32.value():
  718. case Instructions::i32_trunc_sf64.value():
  719. case Instructions::i32_trunc_uf64.value():
  720. goto unimplemented;
  721. case Instructions::i64_extend_si32.value():
  722. UNARY_MAP(i32, i64, i64);
  723. case Instructions::i64_extend_ui32.value():
  724. UNARY_MAP(u32, i64, i64);
  725. case Instructions::i64_trunc_sf32.value():
  726. case Instructions::i64_trunc_uf32.value():
  727. case Instructions::i64_trunc_sf64.value():
  728. case Instructions::i64_trunc_uf64.value():
  729. goto unimplemented;
  730. case Instructions::f32_convert_si32.value():
  731. UNARY_MAP(i32, float, float);
  732. case Instructions::f32_convert_ui32.value():
  733. UNARY_MAP(u32, float, float);
  734. case Instructions::f32_convert_si64.value():
  735. UNARY_MAP(i64, float, float);
  736. case Instructions::f32_convert_ui64.value():
  737. UNARY_MAP(u32, float, float);
  738. case Instructions::f32_demote_f64.value():
  739. UNARY_MAP(double, float, float);
  740. case Instructions::f64_convert_si32.value():
  741. UNARY_MAP(i32, double, double);
  742. case Instructions::f64_convert_ui32.value():
  743. UNARY_MAP(u32, double, double);
  744. case Instructions::f64_convert_si64.value():
  745. UNARY_MAP(i64, double, double);
  746. case Instructions::f64_convert_ui64.value():
  747. UNARY_MAP(u64, double, double);
  748. case Instructions::f64_promote_f32.value():
  749. UNARY_MAP(float, double, double);
  750. case Instructions::i32_reinterpret_f32.value():
  751. UNARY_MAP(float, bit_cast<i32>, i32);
  752. case Instructions::i64_reinterpret_f64.value():
  753. UNARY_MAP(double, bit_cast<i64>, i64);
  754. case Instructions::f32_reinterpret_i32.value():
  755. UNARY_MAP(i32, bit_cast<float>, float);
  756. case Instructions::f64_reinterpret_i64.value():
  757. UNARY_MAP(i64, bit_cast<double>, double);
  758. case Instructions::i32_trunc_sat_f32_s.value():
  759. case Instructions::i32_trunc_sat_f32_u.value():
  760. case Instructions::i32_trunc_sat_f64_s.value():
  761. case Instructions::i32_trunc_sat_f64_u.value():
  762. case Instructions::i64_trunc_sat_f32_s.value():
  763. case Instructions::i64_trunc_sat_f32_u.value():
  764. case Instructions::i64_trunc_sat_f64_s.value():
  765. case Instructions::i64_trunc_sat_f64_u.value():
  766. case Instructions::memory_init.value():
  767. case Instructions::data_drop.value():
  768. case Instructions::memory_copy.value():
  769. case Instructions::memory_fill.value():
  770. case Instructions::table_init.value():
  771. case Instructions::elem_drop.value():
  772. case Instructions::table_copy.value():
  773. case Instructions::table_grow.value():
  774. case Instructions::table_size.value():
  775. case Instructions::table_fill.value():
  776. default:
  777. unimplemented:;
  778. dbgln("Instruction '{}' not implemented", instruction_name(instruction.opcode()));
  779. m_do_trap = true;
  780. return;
  781. }
  782. }
  783. }