Types.h 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093
  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/Badge.h>
  8. #include <AK/ByteString.h>
  9. #include <AK/DistinctNumeric.h>
  10. #include <AK/LEB128.h>
  11. #include <AK/Result.h>
  12. #include <AK/String.h>
  13. #include <AK/UFixedBigInt.h>
  14. #include <AK/Variant.h>
  15. #include <LibWasm/Constants.h>
  16. #include <LibWasm/Forward.h>
  17. #include <LibWasm/Opcode.h>
  18. namespace Wasm {
  19. template<size_t M>
  20. using NativeIntegralType = Conditional<M == 8, u8, Conditional<M == 16, u16, Conditional<M == 32, u32, Conditional<M == 64, u64, void>>>>;
  21. template<size_t M>
  22. using NativeFloatingType = Conditional<M == 32, f32, Conditional<M == 64, f64, void>>;
  23. template<size_t M, size_t N, template<typename> typename SetSign, typename ElementType = SetSign<NativeIntegralType<M>>>
  24. using NativeVectorType __attribute__((vector_size(N * sizeof(ElementType)))) = ElementType;
  25. template<typename T, template<typename> typename SetSign>
  26. using Native128ByteVectorOf = NativeVectorType<sizeof(T) * 8, 16 / sizeof(T), SetSign, T>;
  27. enum class ParseError {
  28. UnexpectedEof,
  29. UnknownInstruction,
  30. ExpectedFloatingImmediate,
  31. ExpectedIndex,
  32. ExpectedKindTag,
  33. ExpectedSignedImmediate,
  34. ExpectedSize,
  35. ExpectedValueOrTerminator,
  36. InvalidImmediate,
  37. InvalidIndex,
  38. InvalidInput,
  39. InvalidModuleMagic,
  40. InvalidModuleVersion,
  41. InvalidSize,
  42. InvalidTag,
  43. InvalidType,
  44. HugeAllocationRequested,
  45. OutOfMemory,
  46. // FIXME: This should not exist!
  47. NotImplemented,
  48. };
  49. ByteString parse_error_to_byte_string(ParseError);
  50. template<typename T>
  51. using ParseResult = Result<T, ParseError>;
  52. AK_TYPEDEF_DISTINCT_ORDERED_ID(size_t, TypeIndex);
  53. AK_TYPEDEF_DISTINCT_ORDERED_ID(size_t, FunctionIndex);
  54. AK_TYPEDEF_DISTINCT_ORDERED_ID(size_t, TableIndex);
  55. AK_TYPEDEF_DISTINCT_ORDERED_ID(size_t, ElementIndex);
  56. AK_TYPEDEF_DISTINCT_ORDERED_ID(size_t, MemoryIndex);
  57. AK_TYPEDEF_DISTINCT_ORDERED_ID(size_t, LocalIndex);
  58. AK_TYPEDEF_DISTINCT_ORDERED_ID(size_t, GlobalIndex);
  59. AK_TYPEDEF_DISTINCT_ORDERED_ID(size_t, LabelIndex);
  60. AK_TYPEDEF_DISTINCT_ORDERED_ID(size_t, DataIndex);
  61. AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, InstructionPointer, Arithmetic, Comparison, Flags, Increment);
  62. ParseError with_eof_check(Stream const& stream, ParseError error_if_not_eof);
  63. template<typename T>
  64. struct GenericIndexParser {
  65. static ParseResult<T> parse(Stream& stream)
  66. {
  67. auto value_or_error = stream.read_value<LEB128<size_t>>();
  68. if (value_or_error.is_error())
  69. return with_eof_check(stream, ParseError::ExpectedIndex);
  70. size_t value = value_or_error.release_value();
  71. return T { value };
  72. }
  73. };
  74. class ReconsumableStream : public Stream {
  75. public:
  76. explicit ReconsumableStream(Stream& stream)
  77. : m_stream(stream)
  78. {
  79. }
  80. void unread(ReadonlyBytes data) { m_buffer.append(data.data(), data.size()); }
  81. private:
  82. virtual ErrorOr<Bytes> read_some(Bytes bytes) override
  83. {
  84. auto original_bytes = bytes;
  85. size_t bytes_read_from_buffer = 0;
  86. if (!m_buffer.is_empty()) {
  87. auto read_size = min(bytes.size(), m_buffer.size());
  88. m_buffer.span().slice(0, read_size).copy_to(bytes);
  89. bytes = bytes.slice(read_size);
  90. for (size_t i = 0; i < read_size; ++i)
  91. m_buffer.take_first();
  92. bytes_read_from_buffer = read_size;
  93. }
  94. return original_bytes.trim(TRY(m_stream.read_some(bytes)).size() + bytes_read_from_buffer);
  95. }
  96. virtual bool is_eof() const override
  97. {
  98. return m_buffer.is_empty() && m_stream.is_eof();
  99. }
  100. virtual ErrorOr<void> discard(size_t count) override
  101. {
  102. size_t bytes_discarded_from_buffer = 0;
  103. if (!m_buffer.is_empty()) {
  104. auto read_size = min(count, m_buffer.size());
  105. for (size_t i = 0; i < read_size; ++i)
  106. m_buffer.take_first();
  107. bytes_discarded_from_buffer = read_size;
  108. }
  109. return m_stream.discard(count - bytes_discarded_from_buffer);
  110. }
  111. virtual ErrorOr<size_t> write_some(ReadonlyBytes) override
  112. {
  113. return Error::from_errno(EBADF);
  114. }
  115. virtual bool is_open() const override
  116. {
  117. return m_stream.is_open();
  118. }
  119. virtual void close() override
  120. {
  121. m_stream.close();
  122. }
  123. Stream& m_stream;
  124. Vector<u8, 8> m_buffer;
  125. };
  126. // https://webassembly.github.io/spec/core/bikeshed/#value-types%E2%91%A2
  127. class ValueType {
  128. public:
  129. enum Kind {
  130. I32,
  131. I64,
  132. F32,
  133. F64,
  134. V128,
  135. FunctionReference,
  136. ExternReference,
  137. NullFunctionReference,
  138. NullExternReference,
  139. };
  140. explicit ValueType(Kind kind)
  141. : m_kind(kind)
  142. {
  143. }
  144. bool operator==(ValueType const&) const = default;
  145. auto is_reference() const { return m_kind == ExternReference || m_kind == FunctionReference || m_kind == NullExternReference || m_kind == NullFunctionReference; }
  146. auto is_vector() const { return m_kind == V128; }
  147. auto is_numeric() const { return !is_reference() && !is_vector(); }
  148. auto kind() const { return m_kind; }
  149. static ParseResult<ValueType> parse(Stream& stream);
  150. static ByteString kind_name(Kind kind)
  151. {
  152. switch (kind) {
  153. case I32:
  154. return "i32";
  155. case I64:
  156. return "i64";
  157. case F32:
  158. return "f32";
  159. case F64:
  160. return "f64";
  161. case V128:
  162. return "v128";
  163. case FunctionReference:
  164. return "funcref";
  165. case ExternReference:
  166. return "externref";
  167. case NullFunctionReference:
  168. return "ref.null externref";
  169. case NullExternReference:
  170. return "ref.null funcref";
  171. }
  172. VERIFY_NOT_REACHED();
  173. }
  174. private:
  175. Kind m_kind;
  176. };
  177. // https://webassembly.github.io/spec/core/bikeshed/#result-types%E2%91%A2
  178. class ResultType {
  179. public:
  180. explicit ResultType(Vector<ValueType> types)
  181. : m_types(move(types))
  182. {
  183. }
  184. auto const& types() const { return m_types; }
  185. static ParseResult<ResultType> parse(Stream& stream);
  186. private:
  187. Vector<ValueType> m_types;
  188. };
  189. // https://webassembly.github.io/spec/core/bikeshed/#function-types%E2%91%A4
  190. class FunctionType {
  191. public:
  192. FunctionType(Vector<ValueType> parameters, Vector<ValueType> results)
  193. : m_parameters(move(parameters))
  194. , m_results(move(results))
  195. {
  196. }
  197. auto& parameters() const { return m_parameters; }
  198. auto& results() const { return m_results; }
  199. static ParseResult<FunctionType> parse(Stream& stream);
  200. private:
  201. Vector<ValueType> m_parameters;
  202. Vector<ValueType> m_results;
  203. };
  204. // https://webassembly.github.io/spec/core/bikeshed/#limits%E2%91%A5
  205. class Limits {
  206. public:
  207. explicit Limits(u32 min, Optional<u32> max = {})
  208. : m_min(min)
  209. , m_max(move(max))
  210. {
  211. }
  212. auto min() const { return m_min; }
  213. auto& max() const { return m_max; }
  214. static ParseResult<Limits> parse(Stream& stream);
  215. private:
  216. u32 m_min { 0 };
  217. Optional<u32> m_max;
  218. };
  219. // https://webassembly.github.io/spec/core/bikeshed/#memory-types%E2%91%A4
  220. class MemoryType {
  221. public:
  222. explicit MemoryType(Limits limits)
  223. : m_limits(move(limits))
  224. {
  225. }
  226. auto& limits() const { return m_limits; }
  227. static ParseResult<MemoryType> parse(Stream& stream);
  228. private:
  229. Limits m_limits;
  230. };
  231. // https://webassembly.github.io/spec/core/bikeshed/#table-types%E2%91%A4
  232. class TableType {
  233. public:
  234. explicit TableType(ValueType element_type, Limits limits)
  235. : m_element_type(element_type)
  236. , m_limits(move(limits))
  237. {
  238. VERIFY(m_element_type.is_reference());
  239. }
  240. auto& limits() const { return m_limits; }
  241. auto& element_type() const { return m_element_type; }
  242. static ParseResult<TableType> parse(Stream& stream);
  243. private:
  244. ValueType m_element_type;
  245. Limits m_limits;
  246. };
  247. // https://webassembly.github.io/spec/core/bikeshed/#global-types%E2%91%A4
  248. class GlobalType {
  249. public:
  250. GlobalType(ValueType type, bool is_mutable)
  251. : m_type(type)
  252. , m_is_mutable(is_mutable)
  253. {
  254. }
  255. auto& type() const { return m_type; }
  256. auto is_mutable() const { return m_is_mutable; }
  257. static ParseResult<GlobalType> parse(Stream& stream);
  258. private:
  259. ValueType m_type;
  260. bool m_is_mutable { false };
  261. };
  262. // https://webassembly.github.io/spec/core/bikeshed/#binary-blocktype
  263. class BlockType {
  264. public:
  265. enum Kind {
  266. Empty,
  267. Type,
  268. Index,
  269. };
  270. BlockType()
  271. : m_kind(Empty)
  272. , m_empty(0)
  273. {
  274. }
  275. explicit BlockType(ValueType type)
  276. : m_kind(Type)
  277. , m_value_type(type)
  278. {
  279. }
  280. explicit BlockType(TypeIndex index)
  281. : m_kind(Index)
  282. , m_type_index(index)
  283. {
  284. }
  285. auto kind() const { return m_kind; }
  286. auto& value_type() const
  287. {
  288. VERIFY(kind() == Type);
  289. return m_value_type;
  290. }
  291. auto& type_index() const
  292. {
  293. VERIFY(kind() == Index);
  294. return m_type_index;
  295. }
  296. static ParseResult<BlockType> parse(Stream& stream);
  297. private:
  298. Kind m_kind { Empty };
  299. union {
  300. ValueType m_value_type;
  301. TypeIndex m_type_index;
  302. u8 m_empty;
  303. };
  304. };
  305. // https://webassembly.github.io/spec/core/bikeshed/#binary-instr
  306. // https://webassembly.github.io/spec/core/bikeshed/#reference-instructions%E2%91%A6
  307. // https://webassembly.github.io/spec/core/bikeshed/#parametric-instructions%E2%91%A6
  308. // https://webassembly.github.io/spec/core/bikeshed/#variable-instructions%E2%91%A6
  309. // https://webassembly.github.io/spec/core/bikeshed/#table-instructions%E2%91%A6
  310. // https://webassembly.github.io/spec/core/bikeshed/#memory-instructions%E2%91%A6
  311. // https://webassembly.github.io/spec/core/bikeshed/#numeric-instructions%E2%91%A6
  312. class Instruction {
  313. public:
  314. explicit Instruction(OpCode opcode)
  315. : m_opcode(opcode)
  316. , m_arguments(static_cast<u8>(0))
  317. {
  318. }
  319. struct TableElementArgs {
  320. ElementIndex element_index;
  321. TableIndex table_index;
  322. };
  323. struct TableTableArgs {
  324. TableIndex lhs;
  325. TableIndex rhs;
  326. };
  327. struct StructuredInstructionArgs {
  328. BlockType block_type;
  329. InstructionPointer end_ip;
  330. Optional<InstructionPointer> else_ip;
  331. };
  332. struct TableBranchArgs {
  333. Vector<LabelIndex> labels;
  334. LabelIndex default_;
  335. };
  336. struct IndirectCallArgs {
  337. TypeIndex type;
  338. TableIndex table;
  339. };
  340. struct MemoryArgument {
  341. u32 align;
  342. u32 offset;
  343. MemoryIndex memory_index { 0 };
  344. };
  345. struct MemoryAndLaneArgument {
  346. MemoryArgument memory;
  347. u8 lane;
  348. };
  349. struct LaneIndex {
  350. u8 lane;
  351. };
  352. // Proposal "multi-memory"
  353. struct MemoryCopyArgs {
  354. MemoryIndex src_index;
  355. MemoryIndex dst_index;
  356. };
  357. struct MemoryInitArgs {
  358. DataIndex data_index;
  359. MemoryIndex memory_index;
  360. };
  361. struct MemoryIndexArgument {
  362. MemoryIndex memory_index;
  363. };
  364. struct ShuffleArgument {
  365. explicit ShuffleArgument(u8 (&lanes)[16])
  366. : lanes {
  367. lanes[0], lanes[1], lanes[2], lanes[3], lanes[4], lanes[5], lanes[6], lanes[7],
  368. lanes[8], lanes[9], lanes[10], lanes[11], lanes[12], lanes[13], lanes[14], lanes[15]
  369. }
  370. {
  371. }
  372. u8 lanes[16];
  373. };
  374. template<typename T>
  375. explicit Instruction(OpCode opcode, T argument)
  376. : m_opcode(opcode)
  377. , m_arguments(move(argument))
  378. {
  379. }
  380. static ParseResult<Vector<Instruction>> parse(Stream& stream, InstructionPointer& ip);
  381. auto& opcode() const { return m_opcode; }
  382. auto& arguments() const { return m_arguments; }
  383. private:
  384. OpCode m_opcode { 0 };
  385. // clang-format off
  386. Variant<
  387. BlockType,
  388. DataIndex,
  389. ElementIndex,
  390. FunctionIndex,
  391. GlobalIndex,
  392. IndirectCallArgs,
  393. LabelIndex,
  394. LaneIndex,
  395. LocalIndex,
  396. MemoryArgument,
  397. MemoryAndLaneArgument,
  398. MemoryCopyArgs,
  399. MemoryIndexArgument,
  400. MemoryInitArgs,
  401. StructuredInstructionArgs,
  402. ShuffleArgument,
  403. TableBranchArgs,
  404. TableElementArgs,
  405. TableIndex,
  406. TableTableArgs,
  407. ValueType,
  408. Vector<ValueType>,
  409. double,
  410. float,
  411. i32,
  412. i64,
  413. u128,
  414. u8 // Empty state
  415. > m_arguments;
  416. // clang-format on
  417. };
  418. class CustomSection {
  419. public:
  420. static constexpr u8 section_id = 0;
  421. CustomSection(ByteString name, ByteBuffer contents)
  422. : m_name(move(name))
  423. , m_contents(move(contents))
  424. {
  425. }
  426. auto& name() const { return m_name; }
  427. auto& contents() const { return m_contents; }
  428. static ParseResult<CustomSection> parse(Stream& stream);
  429. private:
  430. ByteString m_name;
  431. ByteBuffer m_contents;
  432. };
  433. class TypeSection {
  434. public:
  435. static constexpr u8 section_id = 1;
  436. explicit TypeSection(Vector<FunctionType> types)
  437. : m_types(move(types))
  438. {
  439. }
  440. auto& types() const { return m_types; }
  441. static ParseResult<TypeSection> parse(Stream& stream);
  442. private:
  443. Vector<FunctionType> m_types;
  444. };
  445. class ImportSection {
  446. public:
  447. class Import {
  448. public:
  449. using ImportDesc = Variant<TypeIndex, TableType, MemoryType, GlobalType, FunctionType>;
  450. Import(ByteString module, ByteString name, ImportDesc description)
  451. : m_module(move(module))
  452. , m_name(move(name))
  453. , m_description(move(description))
  454. {
  455. }
  456. auto& module() const { return m_module; }
  457. auto& name() const { return m_name; }
  458. auto& description() const { return m_description; }
  459. static ParseResult<Import> parse(Stream& stream);
  460. private:
  461. template<typename T>
  462. static ParseResult<Import> parse_with_type(auto&& stream, auto&& module, auto&& name)
  463. {
  464. auto result = T::parse(stream);
  465. if (result.is_error())
  466. return result.error();
  467. return Import { module.release_value(), name.release_value(), result.release_value() };
  468. }
  469. ByteString m_module;
  470. ByteString m_name;
  471. ImportDesc m_description;
  472. };
  473. public:
  474. static constexpr u8 section_id = 2;
  475. explicit ImportSection(Vector<Import> imports)
  476. : m_imports(move(imports))
  477. {
  478. }
  479. auto& imports() const { return m_imports; }
  480. static ParseResult<ImportSection> parse(Stream& stream);
  481. private:
  482. Vector<Import> m_imports;
  483. };
  484. class FunctionSection {
  485. public:
  486. static constexpr u8 section_id = 3;
  487. explicit FunctionSection(Vector<TypeIndex> types)
  488. : m_types(move(types))
  489. {
  490. }
  491. auto& types() const { return m_types; }
  492. static ParseResult<FunctionSection> parse(Stream& stream);
  493. private:
  494. Vector<TypeIndex> m_types;
  495. };
  496. class TableSection {
  497. public:
  498. class Table {
  499. public:
  500. explicit Table(TableType type)
  501. : m_type(move(type))
  502. {
  503. }
  504. auto& type() const { return m_type; }
  505. static ParseResult<Table> parse(Stream& stream);
  506. private:
  507. TableType m_type;
  508. };
  509. public:
  510. static constexpr u8 section_id = 4;
  511. explicit TableSection(Vector<Table> tables)
  512. : m_tables(move(tables))
  513. {
  514. }
  515. auto& tables() const { return m_tables; }
  516. static ParseResult<TableSection> parse(Stream& stream);
  517. private:
  518. Vector<Table> m_tables;
  519. };
  520. class MemorySection {
  521. public:
  522. class Memory {
  523. public:
  524. explicit Memory(MemoryType type)
  525. : m_type(move(type))
  526. {
  527. }
  528. auto& type() const { return m_type; }
  529. static ParseResult<Memory> parse(Stream& stream);
  530. private:
  531. MemoryType m_type;
  532. };
  533. public:
  534. static constexpr u8 section_id = 5;
  535. explicit MemorySection(Vector<Memory> memories)
  536. : m_memories(move(memories))
  537. {
  538. }
  539. auto& memories() const { return m_memories; }
  540. static ParseResult<MemorySection> parse(Stream& stream);
  541. private:
  542. Vector<Memory> m_memories;
  543. };
  544. class Expression {
  545. public:
  546. explicit Expression(Vector<Instruction> instructions)
  547. : m_instructions(move(instructions))
  548. {
  549. }
  550. auto& instructions() const { return m_instructions; }
  551. static ParseResult<Expression> parse(Stream& stream);
  552. private:
  553. Vector<Instruction> m_instructions;
  554. };
  555. class GlobalSection {
  556. public:
  557. class Global {
  558. public:
  559. explicit Global(GlobalType type, Expression expression)
  560. : m_type(move(type))
  561. , m_expression(move(expression))
  562. {
  563. }
  564. auto& type() const { return m_type; }
  565. auto& expression() const { return m_expression; }
  566. static ParseResult<Global> parse(Stream& stream);
  567. private:
  568. GlobalType m_type;
  569. Expression m_expression;
  570. };
  571. public:
  572. static constexpr u8 section_id = 6;
  573. explicit GlobalSection(Vector<Global> entries)
  574. : m_entries(move(entries))
  575. {
  576. }
  577. auto& entries() const { return m_entries; }
  578. static ParseResult<GlobalSection> parse(Stream& stream);
  579. private:
  580. Vector<Global> m_entries;
  581. };
  582. class ExportSection {
  583. private:
  584. using ExportDesc = Variant<FunctionIndex, TableIndex, MemoryIndex, GlobalIndex>;
  585. public:
  586. class Export {
  587. public:
  588. explicit Export(ByteString name, ExportDesc description)
  589. : m_name(move(name))
  590. , m_description(move(description))
  591. {
  592. }
  593. auto& name() const { return m_name; }
  594. auto& description() const { return m_description; }
  595. static ParseResult<Export> parse(Stream& stream);
  596. private:
  597. ByteString m_name;
  598. ExportDesc m_description;
  599. };
  600. static constexpr u8 section_id = 7;
  601. explicit ExportSection(Vector<Export> entries)
  602. : m_entries(move(entries))
  603. {
  604. }
  605. auto& entries() const { return m_entries; }
  606. static ParseResult<ExportSection> parse(Stream& stream);
  607. private:
  608. Vector<Export> m_entries;
  609. };
  610. class StartSection {
  611. public:
  612. class StartFunction {
  613. public:
  614. explicit StartFunction(FunctionIndex index)
  615. : m_index(index)
  616. {
  617. }
  618. auto& index() const { return m_index; }
  619. static ParseResult<StartFunction> parse(Stream& stream);
  620. private:
  621. FunctionIndex m_index;
  622. };
  623. static constexpr u8 section_id = 8;
  624. explicit StartSection(StartFunction func)
  625. : m_function(move(func))
  626. {
  627. }
  628. auto& function() const { return m_function; }
  629. static ParseResult<StartSection> parse(Stream& stream);
  630. private:
  631. StartFunction m_function;
  632. };
  633. class ElementSection {
  634. public:
  635. struct Active {
  636. TableIndex index;
  637. Expression expression;
  638. };
  639. struct Declarative {
  640. };
  641. struct Passive {
  642. };
  643. struct SegmentType0 {
  644. static ParseResult<SegmentType0> parse(Stream& stream);
  645. Vector<FunctionIndex> function_indices;
  646. Active mode;
  647. };
  648. struct SegmentType1 {
  649. static ParseResult<SegmentType1> parse(Stream& stream);
  650. Vector<FunctionIndex> function_indices;
  651. };
  652. struct SegmentType2 {
  653. // FIXME: Implement me!
  654. static ParseResult<SegmentType2> parse(Stream& stream);
  655. };
  656. struct SegmentType3 {
  657. // FIXME: Implement me!
  658. static ParseResult<SegmentType3> parse(Stream& stream);
  659. };
  660. struct SegmentType4 {
  661. static ParseResult<SegmentType4> parse(Stream& stream);
  662. Active mode;
  663. Vector<Expression> initializer;
  664. };
  665. struct SegmentType5 {
  666. // FIXME: Implement me!
  667. static ParseResult<SegmentType5> parse(Stream& stream);
  668. };
  669. struct SegmentType6 {
  670. // FIXME: Implement me!
  671. static ParseResult<SegmentType6> parse(Stream& stream);
  672. };
  673. struct SegmentType7 {
  674. // FIXME: Implement me!
  675. static ParseResult<SegmentType7> parse(Stream& stream);
  676. };
  677. struct Element {
  678. static ParseResult<Element> parse(Stream&);
  679. ValueType type;
  680. Vector<Expression> init;
  681. Variant<Active, Passive, Declarative> mode;
  682. };
  683. static constexpr u8 section_id = 9;
  684. explicit ElementSection(Vector<Element> segs)
  685. : m_segments(move(segs))
  686. {
  687. }
  688. auto& segments() const { return m_segments; }
  689. static ParseResult<ElementSection> parse(Stream& stream);
  690. private:
  691. Vector<Element> m_segments;
  692. };
  693. class Locals {
  694. public:
  695. explicit Locals(u32 n, ValueType type)
  696. : m_n(n)
  697. , m_type(type)
  698. {
  699. }
  700. // Yikes...
  701. auto n() const { return m_n; }
  702. auto& type() const { return m_type; }
  703. static ParseResult<Locals> parse(Stream& stream);
  704. private:
  705. u32 m_n { 0 };
  706. ValueType m_type;
  707. };
  708. class CodeSection {
  709. public:
  710. // https://webassembly.github.io/spec/core/bikeshed/#binary-func
  711. class Func {
  712. public:
  713. explicit Func(Vector<Locals> locals, Expression body)
  714. : m_locals(move(locals))
  715. , m_body(move(body))
  716. {
  717. }
  718. auto& locals() const { return m_locals; }
  719. auto& body() const { return m_body; }
  720. static ParseResult<Func> parse(Stream& stream);
  721. private:
  722. Vector<Locals> m_locals;
  723. Expression m_body;
  724. };
  725. class Code {
  726. public:
  727. explicit Code(u32 size, Func func)
  728. : m_size(size)
  729. , m_func(move(func))
  730. {
  731. }
  732. auto size() const { return m_size; }
  733. auto& func() const { return m_func; }
  734. static ParseResult<Code> parse(Stream& stream);
  735. private:
  736. u32 m_size { 0 };
  737. Func m_func;
  738. };
  739. static constexpr u8 section_id = 10;
  740. explicit CodeSection(Vector<Code> funcs)
  741. : m_functions(move(funcs))
  742. {
  743. }
  744. auto& functions() const { return m_functions; }
  745. static ParseResult<CodeSection> parse(Stream& stream);
  746. private:
  747. Vector<Code> m_functions;
  748. };
  749. class DataSection {
  750. public:
  751. class Data {
  752. public:
  753. struct Passive {
  754. Vector<u8> init;
  755. };
  756. struct Active {
  757. Vector<u8> init;
  758. MemoryIndex index;
  759. Expression offset;
  760. };
  761. using Value = Variant<Passive, Active>;
  762. explicit Data(Value value)
  763. : m_value(move(value))
  764. {
  765. }
  766. auto& value() const { return m_value; }
  767. static ParseResult<Data> parse(Stream& stream);
  768. private:
  769. Value m_value;
  770. };
  771. static constexpr u8 section_id = 11;
  772. explicit DataSection(Vector<Data> data)
  773. : m_data(move(data))
  774. {
  775. }
  776. auto& data() const { return m_data; }
  777. static ParseResult<DataSection> parse(Stream& stream);
  778. private:
  779. Vector<Data> m_data;
  780. };
  781. class DataCountSection {
  782. public:
  783. static constexpr u8 section_id = 12;
  784. explicit DataCountSection(Optional<u32> count)
  785. : m_count(move(count))
  786. {
  787. }
  788. auto& count() const { return m_count; }
  789. static ParseResult<DataCountSection> parse(Stream& stream);
  790. private:
  791. Optional<u32> m_count;
  792. };
  793. class Module {
  794. public:
  795. enum class ValidationStatus {
  796. Unchecked,
  797. Invalid,
  798. Valid,
  799. };
  800. class Function {
  801. public:
  802. explicit Function(TypeIndex type, Vector<ValueType> local_types, Expression body)
  803. : m_type(type)
  804. , m_local_types(move(local_types))
  805. , m_body(move(body))
  806. {
  807. }
  808. auto& type() const { return m_type; }
  809. auto& locals() const { return m_local_types; }
  810. auto& body() const { return m_body; }
  811. private:
  812. TypeIndex m_type;
  813. Vector<ValueType> m_local_types;
  814. Expression m_body;
  815. };
  816. using AnySection = Variant<
  817. CustomSection,
  818. TypeSection,
  819. ImportSection,
  820. FunctionSection,
  821. TableSection,
  822. MemorySection,
  823. GlobalSection,
  824. ExportSection,
  825. StartSection,
  826. ElementSection,
  827. CodeSection,
  828. DataSection,
  829. DataCountSection>;
  830. static constexpr Array<u8, 4> wasm_magic { 0, 'a', 's', 'm' };
  831. static constexpr Array<u8, 4> wasm_version { 1, 0, 0, 0 };
  832. explicit Module(Vector<AnySection> sections)
  833. : m_sections(move(sections))
  834. {
  835. if (!populate_sections()) {
  836. m_validation_status = ValidationStatus::Invalid;
  837. m_validation_error = "Failed to populate module sections"sv;
  838. }
  839. }
  840. auto& sections() const { return m_sections; }
  841. auto& functions() const { return m_functions; }
  842. auto& type(TypeIndex index) const
  843. {
  844. FunctionType const* type = nullptr;
  845. for_each_section_of_type<TypeSection>([&](TypeSection const& section) {
  846. type = &section.types().at(index.value());
  847. });
  848. VERIFY(type != nullptr);
  849. return *type;
  850. }
  851. template<typename T, typename Callback>
  852. void for_each_section_of_type(Callback&& callback) const
  853. {
  854. for (auto& section : m_sections) {
  855. if (auto ptr = section.get_pointer<T>())
  856. callback(*ptr);
  857. }
  858. }
  859. template<typename T, typename Callback>
  860. void for_each_section_of_type(Callback&& callback)
  861. {
  862. for (auto& section : m_sections) {
  863. if (auto ptr = section.get_pointer<T>())
  864. callback(*ptr);
  865. }
  866. }
  867. void set_validation_status(ValidationStatus status, Badge<Validator>) { set_validation_status(status); }
  868. ValidationStatus validation_status() const { return m_validation_status; }
  869. StringView validation_error() const { return *m_validation_error; }
  870. void set_validation_error(ByteString error) { m_validation_error = move(error); }
  871. static ParseResult<Module> parse(Stream& stream);
  872. private:
  873. bool populate_sections();
  874. void set_validation_status(ValidationStatus status) { m_validation_status = status; }
  875. Vector<AnySection> m_sections;
  876. Vector<Function> m_functions;
  877. ValidationStatus m_validation_status { ValidationStatus::Unchecked };
  878. Optional<ByteString> m_validation_error;
  879. };
  880. }