AbstractMachine.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. /*
  2. * Copyright (c) 2021, Ali Mohammad Pur <mpfard@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/OwnPtr.h>
  8. #include <AK/Result.h>
  9. #include <LibWasm/Types.h>
  10. namespace Wasm {
  11. struct InstantiationError {
  12. String error { "Unknown error" };
  13. };
  14. using InstantiationResult = Result<void, InstantiationError>;
  15. TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, true, true, false, false, false, true, FunctionAddress);
  16. TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, true, true, false, false, false, true, ExternAddress);
  17. TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, true, true, false, false, false, true, TableAddress);
  18. TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, true, true, false, false, false, true, GlobalAddress);
  19. TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, true, true, false, false, false, true, MemoryAddress);
  20. // FIXME: These should probably be made generic/virtual if/when we decide to do something more
  21. // fancy than just a dumb interpreter.
  22. class Value {
  23. public:
  24. using AnyValueType = Variant<i32, i64, float, double, FunctionAddress, ExternAddress>;
  25. explicit Value(AnyValueType value)
  26. : m_value(move(value))
  27. , m_type(ValueType::I32)
  28. {
  29. if (m_value.has<i32>())
  30. m_type = ValueType { ValueType::I32 };
  31. else if (m_value.has<i64>())
  32. m_type = ValueType { ValueType::I64 };
  33. else if (m_value.has<float>())
  34. m_type = ValueType { ValueType::F32 };
  35. else if (m_value.has<double>())
  36. m_type = ValueType { ValueType::F64 };
  37. else if (m_value.has<FunctionAddress>())
  38. m_type = ValueType { ValueType::FunctionReference };
  39. else if (m_value.has<ExternAddress>())
  40. m_type = ValueType { ValueType::ExternReference };
  41. else
  42. VERIFY_NOT_REACHED();
  43. }
  44. template<typename T>
  45. requires(sizeof(T) == sizeof(u64)) explicit Value(ValueType type, T raw_value)
  46. : m_value(0)
  47. , m_type(type)
  48. {
  49. switch (type.kind()) {
  50. case ValueType::Kind::ExternReference:
  51. m_value = ExternAddress { bit_cast<u64>(raw_value) };
  52. break;
  53. case ValueType::Kind::FunctionReference:
  54. m_value = FunctionAddress { bit_cast<u64>(raw_value) };
  55. break;
  56. case ValueType::Kind::I32:
  57. m_value = static_cast<i32>(bit_cast<i64>(raw_value));
  58. break;
  59. case ValueType::Kind::I64:
  60. m_value = static_cast<i64>(bit_cast<u64>(raw_value));
  61. break;
  62. case ValueType::Kind::F32:
  63. m_value = static_cast<float>(bit_cast<double>(raw_value));
  64. break;
  65. case ValueType::Kind::F64:
  66. m_value = bit_cast<double>(raw_value);
  67. break;
  68. default:
  69. VERIFY_NOT_REACHED();
  70. }
  71. }
  72. Value(const Value& value)
  73. : m_value(AnyValueType { value.m_value })
  74. , m_type(value.m_type)
  75. {
  76. }
  77. Value(Value&& value)
  78. : m_value(move(value.m_value))
  79. , m_type(move(value.m_type))
  80. {
  81. }
  82. Value& operator=(Value&& value)
  83. {
  84. m_value = move(value.m_value);
  85. m_type = move(value.m_type);
  86. return *this;
  87. }
  88. template<typename T>
  89. Optional<T> to()
  90. {
  91. Optional<T> result;
  92. m_value.visit(
  93. [&](auto value) {
  94. if constexpr (!IsSame<T, FunctionAddress> && !IsSame<T, ExternAddress>)
  95. result = value;
  96. },
  97. [&](const FunctionAddress& address) {
  98. if constexpr (IsSame<T, FunctionAddress>)
  99. result = address;
  100. },
  101. [&](const ExternAddress& address) {
  102. if constexpr (IsSame<T, ExternAddress>)
  103. result = address;
  104. });
  105. return result;
  106. }
  107. auto& type() const { return m_type; }
  108. auto& value() const { return m_value; }
  109. private:
  110. AnyValueType m_value;
  111. ValueType m_type;
  112. };
  113. struct Trap {
  114. // Empty value type
  115. };
  116. class Result {
  117. public:
  118. explicit Result(Vector<Value> values)
  119. : m_values(move(values))
  120. {
  121. }
  122. Result(Trap)
  123. : m_is_trap(true)
  124. {
  125. }
  126. auto& values() const { return m_values; }
  127. auto& values() { return m_values; }
  128. auto is_trap() const { return m_is_trap; }
  129. private:
  130. Vector<Value> m_values;
  131. bool m_is_trap { false };
  132. };
  133. using ExternValue = Variant<FunctionAddress, TableAddress, MemoryAddress, GlobalAddress>;
  134. class ExportInstance {
  135. public:
  136. explicit ExportInstance(String name, ExternValue value)
  137. : m_name(move(name))
  138. , m_value(move(value))
  139. {
  140. }
  141. auto& name() const { return m_name; }
  142. auto& value() const { return m_value; }
  143. private:
  144. String m_name;
  145. ExternValue m_value;
  146. };
  147. class ModuleInstance {
  148. public:
  149. explicit ModuleInstance(
  150. Vector<FunctionType> types, Vector<FunctionAddress> function_addresses, Vector<TableAddress> table_addresses,
  151. Vector<MemoryAddress> memory_addresses, Vector<GlobalAddress> global_addresses, Vector<ExportInstance> exports)
  152. : m_types(move(types))
  153. , m_functions(move(function_addresses))
  154. , m_tables(move(table_addresses))
  155. , m_memories(move(memory_addresses))
  156. , m_globals(move(global_addresses))
  157. , m_exports(move(exports))
  158. {
  159. }
  160. ModuleInstance() = default;
  161. auto& types() const { return m_types; }
  162. auto& functions() const { return m_functions; }
  163. auto& tables() const { return m_tables; }
  164. auto& memories() const { return m_memories; }
  165. auto& globals() const { return m_globals; }
  166. auto& exports() const { return m_exports; }
  167. auto& types() { return m_types; }
  168. auto& functions() { return m_functions; }
  169. auto& tables() { return m_tables; }
  170. auto& memories() { return m_memories; }
  171. auto& globals() { return m_globals; }
  172. auto& exports() { return m_exports; }
  173. private:
  174. Vector<FunctionType> m_types;
  175. Vector<FunctionAddress> m_functions;
  176. Vector<TableAddress> m_tables;
  177. Vector<MemoryAddress> m_memories;
  178. Vector<GlobalAddress> m_globals;
  179. Vector<ExportInstance> m_exports;
  180. };
  181. class WasmFunction {
  182. public:
  183. explicit WasmFunction(const FunctionType& type, const ModuleInstance& module, const Module::Function& code)
  184. : m_type(type)
  185. , m_module(module)
  186. , m_code(code)
  187. {
  188. }
  189. auto& type() const { return m_type; }
  190. auto& module() const { return m_module; }
  191. auto& code() const { return m_code; }
  192. private:
  193. const FunctionType& m_type;
  194. const ModuleInstance& m_module;
  195. const Module::Function& m_code;
  196. };
  197. class HostFunction {
  198. public:
  199. explicit HostFunction(FlatPtr ptr, const FunctionType& type)
  200. : m_ptr(ptr)
  201. , m_type(type)
  202. {
  203. }
  204. auto ptr() const { return m_ptr; }
  205. auto& type() const { return m_type; }
  206. private:
  207. FlatPtr m_ptr { 0 };
  208. const FunctionType& m_type;
  209. };
  210. using FunctionInstance = Variant<WasmFunction, HostFunction>;
  211. class Reference {
  212. public:
  213. struct Null {
  214. ValueType type;
  215. };
  216. struct Func {
  217. FunctionAddress address;
  218. };
  219. struct Extern {
  220. ExternAddress address;
  221. };
  222. using RefType = Variant<Null, Func, Extern>;
  223. explicit Reference(RefType ref)
  224. : m_ref(move(ref))
  225. {
  226. }
  227. auto& ref() const { return m_ref; }
  228. private:
  229. RefType m_ref;
  230. };
  231. class TableInstance {
  232. public:
  233. explicit TableInstance(const TableType& type, Vector<Optional<Reference>> elements)
  234. : m_elements(move(elements))
  235. , m_type(type)
  236. {
  237. }
  238. auto& elements() const { return m_elements; }
  239. auto& elements() { return m_elements; }
  240. auto& type() const { return m_type; }
  241. private:
  242. Vector<Optional<Reference>> m_elements;
  243. const TableType& m_type;
  244. };
  245. class MemoryInstance {
  246. public:
  247. explicit MemoryInstance(const MemoryType& type)
  248. : m_type(type)
  249. {
  250. grow(m_type.limits().min());
  251. }
  252. auto& type() const { return m_type; }
  253. auto size() const { return m_size; }
  254. auto& data() const { return m_data; }
  255. auto& data() { return m_data; }
  256. void grow(size_t new_size) { m_data.grow(new_size); }
  257. private:
  258. const MemoryType& m_type;
  259. size_t m_size { 0 };
  260. ByteBuffer m_data;
  261. };
  262. class GlobalInstance {
  263. public:
  264. explicit GlobalInstance(Value value, bool is_mutable)
  265. : m_mutable(is_mutable)
  266. , m_value(move(value))
  267. {
  268. }
  269. auto is_mutable() const { return m_mutable; }
  270. auto& value() const { return m_value; }
  271. void set_value(Value value)
  272. {
  273. VERIFY(is_mutable());
  274. m_value = move(value);
  275. }
  276. private:
  277. bool m_mutable { false };
  278. Value m_value;
  279. };
  280. class Store {
  281. public:
  282. Store() = default;
  283. Optional<FunctionAddress> allocate(ModuleInstance& module, const Module::Function& function);
  284. Optional<FunctionAddress> allocate(const HostFunction&);
  285. Optional<TableAddress> allocate(const TableType&);
  286. Optional<MemoryAddress> allocate(const MemoryType&);
  287. Optional<GlobalAddress> allocate(const GlobalType&, Value);
  288. FunctionInstance* get(FunctionAddress);
  289. TableInstance* get(TableAddress);
  290. MemoryInstance* get(MemoryAddress);
  291. GlobalInstance* get(GlobalAddress);
  292. private:
  293. Vector<FunctionInstance> m_functions;
  294. Vector<TableInstance> m_tables;
  295. Vector<MemoryInstance> m_memories;
  296. Vector<GlobalInstance> m_globals;
  297. };
  298. class Label {
  299. public:
  300. explicit Label(size_t arity, InstructionPointer continuation)
  301. : m_arity(arity)
  302. , m_continuation(continuation)
  303. {
  304. }
  305. auto continuation() const { return m_continuation; }
  306. auto arity() const { return m_arity; }
  307. private:
  308. size_t m_arity { 0 };
  309. InstructionPointer m_continuation;
  310. };
  311. class Frame {
  312. AK_MAKE_NONCOPYABLE(Frame);
  313. public:
  314. explicit Frame(const ModuleInstance& module, Vector<Value> locals, const Expression& expression, size_t arity)
  315. : m_module(module)
  316. , m_locals(move(locals))
  317. , m_expression(expression)
  318. , m_arity(arity)
  319. {
  320. }
  321. auto& module() const { return m_module; }
  322. auto& locals() const { return m_locals; }
  323. auto& locals() { return m_locals; }
  324. auto& expression() const { return m_expression; }
  325. auto arity() const { return m_arity; }
  326. private:
  327. const ModuleInstance& m_module;
  328. Vector<Value> m_locals;
  329. const Expression& m_expression;
  330. size_t m_arity { 0 };
  331. };
  332. class Stack {
  333. public:
  334. using EntryType = Variant<NonnullOwnPtr<Value>, NonnullOwnPtr<Label>, NonnullOwnPtr<Frame>>;
  335. Stack() = default;
  336. [[nodiscard]] bool is_empty() const { return m_data.is_empty(); }
  337. void push(EntryType entry) { m_data.append(move(entry)); }
  338. auto pop() { return m_data.take_last(); }
  339. auto& peek() const { return m_data.last(); }
  340. auto size() const { return m_data.size(); }
  341. auto& entries() const { return m_data; }
  342. private:
  343. Vector<EntryType> m_data;
  344. };
  345. class AbstractMachine {
  346. public:
  347. explicit AbstractMachine() = default;
  348. // Load and instantiate a module, and link it into this interpreter.
  349. InstantiationResult instantiate(const Module&, Vector<ExternValue>);
  350. Result invoke(FunctionAddress, Vector<Value>);
  351. auto& module_instance() const { return m_module_instance; }
  352. auto& module_instance() { return m_module_instance; }
  353. auto& store() const { return m_store; }
  354. auto& store() { return m_store; }
  355. private:
  356. InstantiationResult allocate_all(const Module&, Vector<ExternValue>&, Vector<Value>& global_values);
  357. ModuleInstance m_module_instance;
  358. Store m_store;
  359. };
  360. }