Types.h 24 KB

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