| 9 | namespace Loader { |
| 10 | |
| 11 | Expect<void> Loader::loadType(AST::Component::CoreDefType &Ty) { |
| 12 | auto ReportError = [](auto E) { |
| 13 | spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Comp_CoreDefType)); |
| 14 | return E; |
| 15 | }; |
| 16 | /// FROM: |
| 17 | /// https://github.com/WebAssembly/component-model/blob/main/design/mvp/Binary.md#type-definitions |
| 18 | /// |
| 19 | /// Unfortunately, the `core:deftype` rule results in an encoding ambiguity: |
| 20 | /// the `0x50` opcode is used by both `core:moduletype` and a non-final |
| 21 | /// `core:subtype`, which can be decoded as a top-level form of |
| 22 | /// `core:rectype`. |
| 23 | /// |
| 24 | /// To resolve this, prior to v1.0 of this specification, we require |
| 25 | /// `core:subtype` to be prefixed by `0x00` in this context (i.e., a non-final |
| 26 | /// sub as a component core type is `0x00 0x50`; elsewhere, `0x50`). By the |
| 27 | /// v1.0 release of this specification, `core:moduletype` will receive a new, |
| 28 | /// non-overlapping opcode. |
| 29 | |
| 30 | // core:type ::= dt:<core:deftype> => (type dt) |
| 31 | // core:deftype ::= rt:<core:rectype> |
| 32 | // => rt (WebAssembly 3.0) |
| 33 | // | 0x00 0x50 x*:vec(<core:typeidx>) ct:<core:comptype> |
| 34 | // => sub x* ct (WebAssembly 3.0) |
| 35 | // | mt:<core:moduletype> |
| 36 | // => mt |
| 37 | // core:moduletype ::= 0x50 md*:vec(<core:moduledecl>) => (module md*) |
| 38 | |
| 39 | // Peek the first byte to determine the type to load. |
| 40 | EXPECTED_TRY(uint8_t Flag, FMgr.peekByte().map_error([this](auto E) { |
| 41 | return logLoadError(E, FMgr.getLastOffset(), ASTNodeAttr::Comp_CoreDefType); |
| 42 | })); |
| 43 | switch (Flag) { |
| 44 | case 0x50: { |
| 45 | FMgr.readByte(); |
| 46 | std::vector<AST::Component::CoreModuleDecl> Decls; |
| 47 | EXPECTED_TRY(loadVec<AST::Component::CoreDefType>( |
| 48 | Decls, [this](AST::Component::CoreModuleDecl &Decl) { |
| 49 | return loadDecl(Decl); |
| 50 | })); |
| 51 | Ty.setModuleType(std::move(Decls)); |
| 52 | return {}; |
| 53 | } |
| 54 | case 0x00: // sub non-final case |
| 55 | FMgr.readByte(); |
| 56 | [[fallthrough]]; |
| 57 | default: { // recursive type case |
| 58 | std::vector<AST::SubType> STypes; |
| 59 | if (static_cast<TypeCode>(Flag) == TypeCode::Rec) { |
| 60 | // Case: 0x4E vec(subtype). |
| 61 | FMgr.readByte(); |
| 62 | EXPECTED_TRY(uint32_t RecVecCnt, loadVecCnt().map_error([this](auto E) { |
| 63 | return logLoadError(E, FMgr.getLastOffset(), |
| 64 | ASTNodeAttr::Comp_CoreDefType); |
| 65 | })); |
| 66 | for (uint32_t I = 0; I < RecVecCnt; ++I) { |
| 67 | STypes.emplace_back(); |
| 68 | EXPECTED_TRY(loadType(STypes.back()).map_error(ReportError)); |
nothing calls this directly
no test coverage detected