Types.h 24 KB

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