Types.h 24 KB

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