Coverage Report

Created: 2025-07-01 06:18

/src/WasmEdge/lib/loader/ast/component/component_canonical.cpp
Line
Count
Source (jump to first uncovered line)
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: 2019-2024 Second State INC
3
4
#include "loader/loader.h"
5
6
namespace WasmEdge {
7
namespace Loader {
8
9
0
Expect<void> Loader::loadCanonical(AST::Component::Canon &C) {
10
0
  auto ReportError = [this](auto E) {
11
0
    return logLoadError(E, FMgr.getLastOffset(), ASTNodeAttr::Comp_Canonical);
12
0
  };
13
  // canon ::= 0x00 0x00 f:<core:funcidx> opts:<opts> ft:<typeidx>
14
  //           => (canon lift f opts type-index-space[ft])
15
  //         | 0x01 0x00 f:<funcidx> opts:<opts>
16
  //           => (canon lower f opts (core func))
17
  //         | 0x02 rt:<typeidx>    => (canon resource.new rt (core func))
18
  //         | 0x03 rt:<typeidx>    => (canon resource.drop rt (core func))
19
  //         | 0x07 rt:<typeidx>
20
  //           => (canon resource.drop rt async (core func)) ๐Ÿ”€
21
  //         | 0x04 rt:<typeidx>    => (canon resource.rep rt (core func))
22
  //         | 0x08                 => (canon backpressure.set (core func)) ๐Ÿ”€
23
  //         | 0x09 rs:<resultlist> opts:<opts>
24
  //           => (canon task.return rs opts (core func)) ๐Ÿ”€
25
  //         | 0x05                 => (canon task.cancel (core func)) ๐Ÿ”€
26
  //         | 0x0a 0x7f i:<u32>    => (canon context.get i32 i (core func)) ๐Ÿ”€
27
  //         | 0x0b 0x7f i:<u32>    => (canon context.set i32 i (core func)) ๐Ÿ”€
28
  //         | 0x0c async?:<async>? => (canon yield async? (core func)) ๐Ÿ”€
29
  //         | 0x06 async?:<async?>
30
  //           => (canon subtask.cancel async? (core func)) ๐Ÿ”€
31
  //         | 0x0d                 => (canon subtask.drop (core func)) ๐Ÿ”€
32
  //         | 0x0e t:<typeidx>     => (canon stream.new t (core func)) ๐Ÿ”€
33
  //         | 0x0f t:<typeidx> opts:<opts>
34
  //           => (canon stream.read t opts (core func)) ๐Ÿ”€
35
  //         | 0x10 t:<typeidx> opts:<opts>
36
  //           => (canon stream.write t opts (core func)) ๐Ÿ”€
37
  //         | 0x11 t:<typeidx> async?:<async?>
38
  //           => (canon stream.cancel-read async? (core func)) ๐Ÿ”€
39
  //         | 0x12 t:<typeidx> async?:<async?>
40
  //           => (canon stream.cancel-write async? (core func)) ๐Ÿ”€
41
  //         | 0x13 t:<typeidx>
42
  //           => (canon stream.close-readable t (core func)) ๐Ÿ”€
43
  //         | 0x14 t:<typeidx>
44
  //           => (canon stream.close-writable t (core func)) ๐Ÿ”€
45
  //         | 0x15 t:<typeidx> => (canon future.new t (core func)) ๐Ÿ”€
46
  //         | 0x16 t:<typeidx> opts:<opts>
47
  //           => (canon future.read t opts (core func)) ๐Ÿ”€
48
  //         | 0x17 t:<typeidx> opts:<opts>
49
  //           => (canon future.write t opts (core func)) ๐Ÿ”€
50
  //         | 0x18 t:<typeidx> async?:<async?>
51
  //           => (canon future.cancel-read async? (core func)) ๐Ÿ”€
52
  //         | 0x19 t:<typeidx> async?:<async?>
53
  //           => (canon future.cancel-write async? (core func)) ๐Ÿ”€
54
  //         | 0x1a t:<typeidx>
55
  //           => (canon future.close-readable t (core func)) ๐Ÿ”€
56
  //         | 0x1b t:<typeidx>
57
  //           => (canon future.close-writable t (core func)) ๐Ÿ”€
58
  //         | 0x1c opts:<opts> => (canon error-context.new opts (core func)) ๐Ÿ“
59
  //         | 0x1d opts:<opts>
60
  //           => (canon error-context.debug-message opts (core func)) ๐Ÿ“
61
  //         | 0x1e                => (canon error-context.drop (core func)) ๐Ÿ“
62
  //         | 0x1f                => (canon waitable-set.new (core func)) ๐Ÿ”€
63
  //         | 0x20 async?:<async>? m:<core:memidx>
64
  //           => (canon waitable-set.wait async? (memory m) (core func)) ๐Ÿ”€
65
  //         | 0x21 async?:<async>? m:<core:memidx>
66
  //           => (canon waitable-set.poll async? (memory m) (core func)) ๐Ÿ”€
67
  //         | 0x22                => (canon waitable-set.drop (core func)) ๐Ÿ”€
68
  //         | 0x23                => (canon waitable.join (core func)) ๐Ÿ”€
69
  //         | 0x40 ft:<typeidx>   => (canon thread.spawn_ref ft (core func)) ๐Ÿงต
70
  //         | 0x41 ft:<typeidx> tbl:<core:tableidx>
71
  //           => (canon thread.spawn_indirect ft tbl (core func)) ๐Ÿงต
72
  //         | 0x42 => (canon thread.available_parallelism (core func)) ๐Ÿงต
73
  // async? ::= 0x00 => ฯต
74
  //          | 0x01 => async
75
76
  // TODO: COMPONENT - collect the canon loading here.
77
78
0
  EXPECTED_TRY(uint8_t Flag, FMgr.readByte().map_error([this](auto E) {
79
0
    return logLoadError(E, FMgr.getLastOffset(), ASTNodeAttr::Comp_Canonical);
80
0
  }));
81
0
  switch (Flag) {
82
0
  case 0x00: {
83
0
    EXPECTED_TRY(auto B, FMgr.readByte().map_error(ReportError));
84
0
    if (unlikely(B != 0x00)) {
85
0
      return logLoadError(ErrCode::Value::MalformedCanonical,
86
0
                          FMgr.getLastOffset(), ASTNodeAttr::Comp_Canonical);
87
0
    }
88
0
    EXPECTED_TRY(loadCanonical(C.emplace<AST::Component::Lift>()));
89
0
    return {};
90
0
  }
91
0
  case 0x01: {
92
0
    EXPECTED_TRY(auto B, FMgr.readByte().map_error(ReportError));
93
0
    if (unlikely(B != 0x00)) {
94
0
      return logLoadError(ErrCode::Value::MalformedCanonical,
95
0
                          FMgr.getLastOffset(), ASTNodeAttr::Comp_Canonical);
96
0
    }
97
0
    EXPECTED_TRY(loadCanonical(C.emplace<AST::Component::Lower>()));
98
0
    return {};
99
0
  }
100
0
  case 0x02: {
101
0
    EXPECTED_TRY(C.emplace<AST::Component::ResourceNew>().getTypeIndex(),
102
0
                 FMgr.readU32().map_error(ReportError));
103
0
    return {};
104
0
  }
105
0
  case 0x03: {
106
0
    EXPECTED_TRY(C.emplace<AST::Component::ResourceDrop>().getTypeIndex(),
107
0
                 FMgr.readU32().map_error(ReportError));
108
0
    return {};
109
0
  }
110
0
  case 0x04: {
111
0
    EXPECTED_TRY(C.emplace<AST::Component::ResourceRep>().getTypeIndex(),
112
0
                 FMgr.readU32().map_error(ReportError));
113
0
    return {};
114
0
  }
115
0
  default:
116
0
    return logLoadError(ErrCode::Value::MalformedCanonical,
117
0
                        FMgr.getLastOffset(), ASTNodeAttr::Comp_Canonical);
118
0
  }
119
0
}
120
121
0
Expect<void> Loader::loadCanonical(AST::Component::Lift &C) {
122
0
  EXPECTED_TRY(C.getCoreFuncIndex(), FMgr.readU32().map_error([this](auto E) {
123
0
    return logLoadError(E, FMgr.getLastOffset(), ASTNodeAttr::Comp_Canonical);
124
0
  }));
125
0
  EXPECTED_TRY(loadVec<AST::Component::Canon>(
126
0
      C.getOptions(), [this](AST::Component::CanonOpt &Opt) {
127
0
        return loadCanonicalOption(Opt);
128
0
      }));
129
0
  EXPECTED_TRY(C.getFuncTypeIndex(), FMgr.readU32().map_error([this](auto E) {
130
0
    return logLoadError(E, FMgr.getLastOffset(), ASTNodeAttr::Comp_Canonical);
131
0
  }));
132
0
  return {};
133
0
}
134
135
0
Expect<void> Loader::loadCanonical(AST::Component::Lower &C) {
136
0
  EXPECTED_TRY(C.getFuncIndex(), FMgr.readU32().map_error([this](auto E) {
137
0
    return logLoadError(E, FMgr.getLastOffset(), ASTNodeAttr::Comp_Canonical);
138
0
  }));
139
0
  return loadVec<AST::Component::Canon>(C.getOptions(),
140
0
                                        [this](AST::Component::CanonOpt &Opt) {
141
0
                                          return loadCanonicalOption(Opt);
142
0
                                        });
143
0
}
144
145
0
Expect<void> Loader::loadCanonicalOption(AST::Component::CanonOpt &C) {
146
0
  auto ReportError = [this](auto E) {
147
0
    return logLoadError(E, FMgr.getLastOffset(), ASTNodeAttr::Comp_CanonOpt);
148
0
  };
149
  // canonopt ::= 0x00                  => string-encoding=utf8
150
  //            | 0x01                  => string-encoding=utf16
151
  //            | 0x02                  => string-encoding=latin1+utf16
152
  //            | 0x03 m:<core:memidx>  => (memory m)
153
  //            | 0x04 f:<core:funcidx> => (realloc f)
154
  //            | 0x05 f:<core:funcidx> => (post-return f)
155
  //            | 0x06                  => async ๐Ÿ”€
156
  //            | 0x07 f:<core:funcidx> => (callback f) ๐Ÿ”€
157
  //            | 0x08                  => always-task-return ๐Ÿ”€
158
159
0
  EXPECTED_TRY(uint8_t Flag, FMgr.readByte().map_error(ReportError));
160
0
  switch (Flag) {
161
0
  case 0x00:
162
0
  case 0x01:
163
0
  case 0x02: {
164
165
0
    C.emplace<AST::Component::StringEncoding>() =
166
0
        static_cast<AST::Component::StringEncoding>(Flag);
167
0
    return {};
168
0
  }
169
0
  case 0x03: {
170
0
    EXPECTED_TRY(C.emplace<AST::Component::Memory>().getMemIndex(),
171
0
                 FMgr.readU32().map_error(ReportError));
172
0
    return {};
173
0
  }
174
0
  case 0x04: {
175
0
    EXPECTED_TRY(C.emplace<AST::Component::Realloc>().getFuncIndex(),
176
0
                 FMgr.readU32().map_error(ReportError));
177
0
    return {};
178
0
  }
179
0
  case 0x05: {
180
0
    EXPECTED_TRY(C.emplace<AST::Component::PostReturn>().getFuncIndex(),
181
0
                 FMgr.readU32().map_error(ReportError));
182
0
    return {};
183
0
  }
184
0
  case 0x06:
185
0
  case 0x07:
186
0
  case 0x08:
187
    // TODO: COMPONENT - implement these cases.
188
0
    return logLoadError(ErrCode::Value::ComponentNotImplLoader,
189
0
                        FMgr.getLastOffset(), ASTNodeAttr::Comp_CanonOpt);
190
0
  default:
191
0
    return logLoadError(ErrCode::Value::UnknownCanonicalOption,
192
0
                        FMgr.getLastOffset(), ASTNodeAttr::Comp_CanonOpt);
193
0
  }
194
0
}
195
196
} // namespace Loader
197
} // namespace WasmEdge