AbstractMachine.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  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/Function.h>
  8. #include <AK/HashMap.h>
  9. #include <AK/HashTable.h>
  10. #include <AK/OwnPtr.h>
  11. #include <AK/Result.h>
  12. #include <LibWasm/Types.h>
  13. namespace Wasm {
  14. class Configuration;
  15. struct Interpreter;
  16. struct InstantiationError {
  17. String error { "Unknown error" };
  18. };
  19. struct LinkError {
  20. enum OtherErrors {
  21. InvalidImportedModule,
  22. };
  23. Vector<String> missing_imports;
  24. Vector<OtherErrors> other_errors;
  25. };
  26. TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, true, true, false, false, false, true, FunctionAddress);
  27. TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, true, true, false, false, false, true, ExternAddress);
  28. TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, true, true, false, false, false, true, TableAddress);
  29. TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, true, true, false, false, false, true, GlobalAddress);
  30. TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, true, true, false, false, false, true, MemoryAddress);
  31. // FIXME: These should probably be made generic/virtual if/when we decide to do something more
  32. // fancy than just a dumb interpreter.
  33. class Value {
  34. public:
  35. Value()
  36. : m_value(0)
  37. , m_type(ValueType::I32)
  38. {
  39. }
  40. struct Null {
  41. ValueType type;
  42. };
  43. using AnyValueType = Variant<i32, i64, float, double, FunctionAddress, ExternAddress, Null>;
  44. explicit Value(AnyValueType value)
  45. : m_value(move(value))
  46. , m_type(ValueType::I32)
  47. {
  48. if (m_value.has<i32>())
  49. m_type = ValueType { ValueType::I32 };
  50. else if (m_value.has<i64>())
  51. m_type = ValueType { ValueType::I64 };
  52. else if (m_value.has<float>())
  53. m_type = ValueType { ValueType::F32 };
  54. else if (m_value.has<double>())
  55. m_type = ValueType { ValueType::F64 };
  56. else if (m_value.has<FunctionAddress>())
  57. m_type = ValueType { ValueType::FunctionReference };
  58. else if (m_value.has<ExternAddress>())
  59. m_type = ValueType { ValueType::ExternReference };
  60. else if (m_value.has<Null>())
  61. m_type = ValueType { m_value.get<Null>().type.kind() == ValueType::ExternReference ? ValueType::NullExternReference : ValueType::NullFunctionReference };
  62. else
  63. VERIFY_NOT_REACHED();
  64. }
  65. template<typename T>
  66. requires(sizeof(T) == sizeof(u64)) explicit Value(ValueType type, T raw_value)
  67. : m_value(0)
  68. , m_type(type)
  69. {
  70. switch (type.kind()) {
  71. case ValueType::Kind::ExternReference:
  72. m_value = ExternAddress { bit_cast<u64>(raw_value) };
  73. break;
  74. case ValueType::Kind::FunctionReference:
  75. m_value = FunctionAddress { bit_cast<u64>(raw_value) };
  76. break;
  77. case ValueType::Kind::I32:
  78. m_value = static_cast<i32>(bit_cast<i64>(raw_value));
  79. break;
  80. case ValueType::Kind::I64:
  81. m_value = static_cast<i64>(bit_cast<u64>(raw_value));
  82. break;
  83. case ValueType::Kind::F32:
  84. m_value = static_cast<float>(bit_cast<double>(raw_value));
  85. break;
  86. case ValueType::Kind::F64:
  87. m_value = bit_cast<double>(raw_value);
  88. break;
  89. case ValueType::Kind::NullFunctionReference:
  90. VERIFY(raw_value == 0);
  91. m_value = Null { ValueType(ValueType::Kind::FunctionReference) };
  92. break;
  93. case ValueType::Kind::NullExternReference:
  94. VERIFY(raw_value == 0);
  95. m_value = Null { ValueType(ValueType::Kind::ExternReference) };
  96. break;
  97. default:
  98. VERIFY_NOT_REACHED();
  99. }
  100. }
  101. Value(const Value& value)
  102. : m_value(AnyValueType { value.m_value })
  103. , m_type(value.m_type)
  104. {
  105. }
  106. Value(Value&& value)
  107. : m_value(move(value.m_value))
  108. , m_type(move(value.m_type))
  109. {
  110. }
  111. Value& operator=(Value&& value)
  112. {
  113. m_value = move(value.m_value);
  114. m_type = move(value.m_type);
  115. return *this;
  116. }
  117. Value& operator=(const Value& value)
  118. {
  119. m_value = value.m_value;
  120. m_type = value.m_type;
  121. return *this;
  122. }
  123. template<typename T>
  124. Optional<T> to()
  125. {
  126. Optional<T> result;
  127. m_value.visit(
  128. [&](auto value) {
  129. if constexpr (IsSame<T, decltype(value)>)
  130. result = value;
  131. else if constexpr (!IsFloatingPoint<T> && IsSame<decltype(value), MakeSigned<T>>)
  132. result = value;
  133. },
  134. [&](const FunctionAddress& address) {
  135. if constexpr (IsSame<T, FunctionAddress>)
  136. result = address;
  137. },
  138. [&](const ExternAddress& address) {
  139. if constexpr (IsSame<T, ExternAddress>)
  140. result = address;
  141. },
  142. [&](const Null& null) {
  143. if constexpr (IsSame<T, Null>)
  144. result = null;
  145. });
  146. return result;
  147. }
  148. auto& type() const { return m_type; }
  149. auto& value() const { return m_value; }
  150. private:
  151. AnyValueType m_value;
  152. ValueType m_type;
  153. };
  154. struct Trap {
  155. // Empty value type
  156. };
  157. class Result {
  158. public:
  159. explicit Result(Vector<Value> values)
  160. : m_values(move(values))
  161. {
  162. }
  163. Result(Trap)
  164. : m_is_trap(true)
  165. {
  166. }
  167. auto& values() const { return m_values; }
  168. auto& values() { return m_values; }
  169. auto is_trap() const { return m_is_trap; }
  170. private:
  171. Vector<Value> m_values;
  172. bool m_is_trap { false };
  173. };
  174. using ExternValue = Variant<FunctionAddress, TableAddress, MemoryAddress, GlobalAddress>;
  175. class ExportInstance {
  176. public:
  177. explicit ExportInstance(String name, ExternValue value)
  178. : m_name(move(name))
  179. , m_value(move(value))
  180. {
  181. }
  182. auto& name() const { return m_name; }
  183. auto& value() const { return m_value; }
  184. private:
  185. String m_name;
  186. ExternValue m_value;
  187. };
  188. class ModuleInstance {
  189. public:
  190. explicit ModuleInstance(
  191. Vector<FunctionType> types, Vector<FunctionAddress> function_addresses, Vector<TableAddress> table_addresses,
  192. Vector<MemoryAddress> memory_addresses, Vector<GlobalAddress> global_addresses, Vector<ExportInstance> exports)
  193. : m_types(move(types))
  194. , m_functions(move(function_addresses))
  195. , m_tables(move(table_addresses))
  196. , m_memories(move(memory_addresses))
  197. , m_globals(move(global_addresses))
  198. , m_exports(move(exports))
  199. {
  200. }
  201. ModuleInstance() = default;
  202. auto& types() const { return m_types; }
  203. auto& functions() const { return m_functions; }
  204. auto& tables() const { return m_tables; }
  205. auto& memories() const { return m_memories; }
  206. auto& globals() const { return m_globals; }
  207. auto& exports() const { return m_exports; }
  208. auto& types() { return m_types; }
  209. auto& functions() { return m_functions; }
  210. auto& tables() { return m_tables; }
  211. auto& memories() { return m_memories; }
  212. auto& globals() { return m_globals; }
  213. auto& exports() { return m_exports; }
  214. private:
  215. Vector<FunctionType> m_types;
  216. Vector<FunctionAddress> m_functions;
  217. Vector<TableAddress> m_tables;
  218. Vector<MemoryAddress> m_memories;
  219. Vector<GlobalAddress> m_globals;
  220. Vector<ExportInstance> m_exports;
  221. };
  222. class WasmFunction {
  223. public:
  224. explicit WasmFunction(const FunctionType& type, const ModuleInstance& module, const Module::Function& code)
  225. : m_type(type)
  226. , m_module(module)
  227. , m_code(code)
  228. {
  229. }
  230. auto& type() const { return m_type; }
  231. auto& module() const { return m_module; }
  232. auto& code() const { return m_code; }
  233. private:
  234. FunctionType m_type;
  235. const ModuleInstance& m_module;
  236. const Module::Function& m_code;
  237. };
  238. class HostFunction {
  239. public:
  240. explicit HostFunction(AK::Function<Result(Configuration&, Vector<Value>&)> function, const FunctionType& type)
  241. : m_function(move(function))
  242. , m_type(type)
  243. {
  244. }
  245. auto& function() { return m_function; }
  246. auto& type() const { return m_type; }
  247. private:
  248. AK::Function<Result(Configuration&, Vector<Value>&)> m_function;
  249. FunctionType m_type;
  250. };
  251. using FunctionInstance = Variant<WasmFunction, HostFunction>;
  252. class Reference {
  253. public:
  254. struct Null {
  255. ValueType type;
  256. };
  257. struct Func {
  258. FunctionAddress address;
  259. };
  260. struct Extern {
  261. ExternAddress address;
  262. };
  263. using RefType = Variant<Null, Func, Extern>;
  264. explicit Reference(RefType ref)
  265. : m_ref(move(ref))
  266. {
  267. }
  268. auto& ref() const { return m_ref; }
  269. private:
  270. RefType m_ref;
  271. };
  272. class TableInstance {
  273. public:
  274. explicit TableInstance(const TableType& type, Vector<Optional<Reference>> elements)
  275. : m_elements(move(elements))
  276. , m_type(type)
  277. {
  278. }
  279. auto& elements() const { return m_elements; }
  280. auto& elements() { return m_elements; }
  281. auto& type() const { return m_type; }
  282. private:
  283. Vector<Optional<Reference>> m_elements;
  284. const TableType& m_type;
  285. };
  286. class MemoryInstance {
  287. public:
  288. explicit MemoryInstance(const MemoryType& type)
  289. : m_type(type)
  290. {
  291. grow(m_type.limits().min() * Constants::page_size);
  292. }
  293. auto& type() const { return m_type; }
  294. auto size() const { return m_size; }
  295. auto& data() const { return m_data; }
  296. auto& data() { return m_data; }
  297. bool grow(size_t size_to_grow)
  298. {
  299. if (size_to_grow == 0)
  300. return true;
  301. auto new_size = m_data.size() + size_to_grow;
  302. if (m_type.limits().max().value_or(new_size) < new_size)
  303. return false;
  304. auto previous_size = m_size;
  305. m_data.resize(new_size);
  306. m_size = new_size;
  307. // The spec requires that we zero out everything on grow
  308. __builtin_memset(m_data.offset_pointer(previous_size), 0, size_to_grow);
  309. return true;
  310. }
  311. private:
  312. const MemoryType& m_type;
  313. size_t m_size { 0 };
  314. ByteBuffer m_data;
  315. };
  316. class GlobalInstance {
  317. public:
  318. explicit GlobalInstance(Value value, bool is_mutable)
  319. : m_mutable(is_mutable)
  320. , m_value(move(value))
  321. {
  322. }
  323. auto is_mutable() const { return m_mutable; }
  324. auto& value() const { return m_value; }
  325. void set_value(Value value)
  326. {
  327. VERIFY(is_mutable());
  328. m_value = move(value);
  329. }
  330. private:
  331. bool m_mutable { false };
  332. Value m_value;
  333. };
  334. class Store {
  335. public:
  336. Store() = default;
  337. Optional<FunctionAddress> allocate(ModuleInstance& module, const Module::Function& function);
  338. Optional<FunctionAddress> allocate(HostFunction&&);
  339. Optional<TableAddress> allocate(const TableType&);
  340. Optional<MemoryAddress> allocate(const MemoryType&);
  341. Optional<GlobalAddress> allocate(const GlobalType&, Value);
  342. FunctionInstance* get(FunctionAddress);
  343. TableInstance* get(TableAddress);
  344. MemoryInstance* get(MemoryAddress);
  345. GlobalInstance* get(GlobalAddress);
  346. private:
  347. Vector<FunctionInstance> m_functions;
  348. Vector<TableInstance> m_tables;
  349. Vector<MemoryInstance> m_memories;
  350. Vector<GlobalInstance> m_globals;
  351. };
  352. class Label {
  353. public:
  354. explicit Label(size_t arity, InstructionPointer continuation)
  355. : m_arity(arity)
  356. , m_continuation(continuation)
  357. {
  358. }
  359. auto continuation() const { return m_continuation; }
  360. auto arity() const { return m_arity; }
  361. private:
  362. size_t m_arity { 0 };
  363. InstructionPointer m_continuation { 0 };
  364. };
  365. class Frame {
  366. public:
  367. explicit Frame(const ModuleInstance& module, Vector<Value> locals, const Expression& expression, size_t arity)
  368. : m_module(module)
  369. , m_locals(move(locals))
  370. , m_expression(expression)
  371. , m_arity(arity)
  372. {
  373. }
  374. auto& module() const { return m_module; }
  375. auto& locals() const { return m_locals; }
  376. auto& locals() { return m_locals; }
  377. auto& expression() const { return m_expression; }
  378. auto arity() const { return m_arity; }
  379. private:
  380. const ModuleInstance& m_module;
  381. Vector<Value> m_locals;
  382. const Expression& m_expression;
  383. size_t m_arity { 0 };
  384. };
  385. class Stack {
  386. public:
  387. using EntryType = Variant<Value, Label, Frame>;
  388. Stack() = default;
  389. [[nodiscard]] ALWAYS_INLINE bool is_empty() const { return m_data.is_empty(); }
  390. FLATTEN void push(EntryType entry) { m_data.append(move(entry)); }
  391. FLATTEN auto pop() { return m_data.take_last(); }
  392. FLATTEN auto& peek() const { return m_data.last(); }
  393. FLATTEN auto& peek() { return m_data.last(); }
  394. ALWAYS_INLINE auto size() const { return m_data.size(); }
  395. ALWAYS_INLINE auto& entries() const { return m_data; }
  396. ALWAYS_INLINE auto& entries() { return m_data; }
  397. private:
  398. Vector<EntryType, 1024> m_data;
  399. };
  400. using InstantiationResult = AK::Result<NonnullOwnPtr<ModuleInstance>, InstantiationError>;
  401. class AbstractMachine {
  402. public:
  403. explicit AbstractMachine() = default;
  404. // Load and instantiate a module, and link it into this interpreter.
  405. InstantiationResult instantiate(const Module&, Vector<ExternValue>);
  406. Result invoke(FunctionAddress, Vector<Value>);
  407. Result invoke(Interpreter&, FunctionAddress, Vector<Value>);
  408. auto& store() const { return m_store; }
  409. auto& store() { return m_store; }
  410. private:
  411. Optional<InstantiationError> allocate_all(const Module&, ModuleInstance&, Vector<ExternValue>&, Vector<Value>& global_values);
  412. Store m_store;
  413. };
  414. class Linker {
  415. public:
  416. struct Name {
  417. String module;
  418. String name;
  419. ImportSection::Import::ImportDesc type;
  420. };
  421. explicit Linker(const Module& module)
  422. : m_module(module)
  423. {
  424. }
  425. // Link a module, the import 'module name' is ignored with this.
  426. void link(const ModuleInstance&);
  427. // Link a bunch of qualified values, also matches 'module name'.
  428. void link(const HashMap<Name, ExternValue>&);
  429. auto& unresolved_imports()
  430. {
  431. populate();
  432. return m_unresolved_imports;
  433. }
  434. AK::Result<Vector<ExternValue>, LinkError> finish();
  435. private:
  436. void populate();
  437. const Module& m_module;
  438. HashMap<Name, ExternValue> m_resolved_imports;
  439. HashTable<Name> m_unresolved_imports;
  440. Vector<Name> m_ordered_imports;
  441. Optional<LinkError> m_error;
  442. };
  443. }
  444. template<>
  445. struct AK::Traits<Wasm::Linker::Name> : public AK::GenericTraits<Wasm::Linker::Name> {
  446. static constexpr bool is_trivial() { return false; }
  447. static unsigned hash(const Wasm::Linker::Name& entry) { return pair_int_hash(entry.module.hash(), entry.name.hash()); }
  448. static bool equals(const Wasm::Linker::Name& a, const Wasm::Linker::Name& b) { return a.name == b.name && a.module == b.module; }
  449. };