AbstractMachine.h 14 KB

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