Types.h 26 KB

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