Types.h 25 KB

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