Coverage Report

Created: 2024-09-11 06:32

/src/wabt/src/wast-parser.cc
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2017 WebAssembly Community Group participants
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
#include "wabt/wast-parser.h"
18
19
#include "wabt/binary-reader-ir.h"
20
#include "wabt/binary-reader.h"
21
#include "wabt/cast.h"
22
#include "wabt/expr-visitor.h"
23
#include "wabt/resolve-names.h"
24
#include "wabt/stream.h"
25
#include "wabt/utf8.h"
26
#include "wabt/validator.h"
27
28
#define WABT_TRACING 0
29
#include "wabt/tracing.h"
30
31
11.5M
#define EXPECT(token_type) CHECK_RESULT(Expect(TokenType::token_type))
32
33
namespace wabt {
34
35
namespace {
36
37
static const size_t kMaxErrorTokenLength = 80;
38
39
3.53k
bool IsPowerOfTwo(uint32_t x) {
40
3.53k
  return x && ((x & (x - 1)) == 0);
41
3.53k
}
42
43
template <typename OutputIter>
44
454k
void RemoveEscapes(std::string_view text, OutputIter dest) {
45
  // Remove surrounding quotes; if any. This may be empty if the string was
46
  // invalid (e.g. if it contained a bad escape sequence).
47
454k
  if (text.size() <= 2) {
48
345k
    return;
49
345k
  }
50
51
108k
  text = text.substr(1, text.size() - 2);
52
53
108k
  const char* src = text.data();
54
108k
  const char* end = text.data() + text.size();
55
56
6.88M
  while (src < end) {
57
6.77M
    if (*src == '\\') {
58
11.6k
      src++;
59
11.6k
      switch (*src) {
60
702
        case 'n':
61
702
          *dest++ = '\n';
62
702
          break;
63
810
        case 'r':
64
810
          *dest++ = '\r';
65
810
          break;
66
798
        case 't':
67
798
          *dest++ = '\t';
68
798
          break;
69
1.75k
        case '\\':
70
1.75k
          *dest++ = '\\';
71
1.75k
          break;
72
626
        case '\'':
73
626
          *dest++ = '\'';
74
626
          break;
75
848
        case '\"':
76
848
          *dest++ = '\"';
77
848
          break;
78
5.24k
        case 'u': {
79
          // The string should be validated already,
80
          // so this must be a valid unicode escape sequence.
81
5.24k
          uint32_t digit;
82
5.24k
          uint32_t scalar_value = 0;
83
84
          // Skip u and { characters.
85
5.24k
          src += 2;
86
87
16.8k
          do {
88
16.8k
            if (Succeeded(ParseHexdigit(src[0], &digit))) {
89
16.8k
              scalar_value = (scalar_value << 4) | digit;
90
16.8k
            } else {
91
0
              assert(0);
92
0
            }
93
16.8k
            src++;
94
16.8k
          } while (src[0] != '}');
95
96
          // Maximum value of a unicode scalar value
97
5.24k
          assert(scalar_value < 0x110000);
98
99
          // Encode the unicode scalar value as UTF8 sequence
100
5.24k
          if (scalar_value < 0x80) {
101
938
            *dest++ = static_cast<uint8_t>(scalar_value);
102
4.30k
          } else {
103
4.30k
            if (scalar_value < 0x800) {
104
1.02k
              *dest++ = static_cast<uint8_t>(0xc0 | (scalar_value >> 6));
105
3.28k
            } else {
106
3.28k
              if (scalar_value < 0x10000) {
107
1.80k
                *dest++ = static_cast<uint8_t>(0xe0 | (scalar_value >> 12));
108
1.80k
              } else {
109
1.47k
                *dest++ = static_cast<uint8_t>(0xf0 | (scalar_value >> 18));
110
1.47k
                *dest++ =
111
1.47k
                    static_cast<uint8_t>(0x80 | ((scalar_value >> 12) & 0x3f));
112
1.47k
              }
113
114
3.28k
              *dest++ =
115
3.28k
                  static_cast<uint8_t>(0x80 | ((scalar_value >> 6) & 0x3f));
116
3.28k
            }
117
118
4.30k
            *dest++ = static_cast<uint8_t>(0x80 | (scalar_value & 0x3f));
119
4.30k
          }
120
5.24k
          break;
121
5.24k
        }
122
866
        default: {
123
          // The string should be validated already, so we know this is a hex
124
          // sequence.
125
866
          uint32_t hi;
126
866
          uint32_t lo;
127
866
          if (Succeeded(ParseHexdigit(src[0], &hi)) &&
128
866
              Succeeded(ParseHexdigit(src[1], &lo))) {
129
866
            *dest++ = (hi << 4) | lo;
130
866
          } else {
131
0
            assert(0);
132
0
          }
133
866
          src++;
134
866
          break;
135
866
        }
136
11.6k
      }
137
11.6k
      src++;
138
6.76M
    } else {
139
6.76M
      *dest++ = *src++;
140
6.76M
    }
141
6.77M
  }
142
108k
}
wast-parser.cc:void wabt::(anonymous namespace)::RemoveEscapes<std::__1::back_insert_iterator<std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > > >(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::back_insert_iterator<std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > >)
Line
Count
Source
44
6.16k
void RemoveEscapes(std::string_view text, OutputIter dest) {
45
  // Remove surrounding quotes; if any. This may be empty if the string was
46
  // invalid (e.g. if it contained a bad escape sequence).
47
6.16k
  if (text.size() <= 2) {
48
3.73k
    return;
49
3.73k
  }
50
51
2.43k
  text = text.substr(1, text.size() - 2);
52
53
2.43k
  const char* src = text.data();
54
2.43k
  const char* end = text.data() + text.size();
55
56
4.00M
  while (src < end) {
57
4.00M
    if (*src == '\\') {
58
8.28k
      src++;
59
8.28k
      switch (*src) {
60
452
        case 'n':
61
452
          *dest++ = '\n';
62
452
          break;
63
603
        case 'r':
64
603
          *dest++ = '\r';
65
603
          break;
66
593
        case 't':
67
593
          *dest++ = '\t';
68
593
          break;
69
1.51k
        case '\\':
70
1.51k
          *dest++ = '\\';
71
1.51k
          break;
72
416
        case '\'':
73
416
          *dest++ = '\'';
74
416
          break;
75
654
        case '\"':
76
654
          *dest++ = '\"';
77
654
          break;
78
3.42k
        case 'u': {
79
          // The string should be validated already,
80
          // so this must be a valid unicode escape sequence.
81
3.42k
          uint32_t digit;
82
3.42k
          uint32_t scalar_value = 0;
83
84
          // Skip u and { characters.
85
3.42k
          src += 2;
86
87
10.9k
          do {
88
10.9k
            if (Succeeded(ParseHexdigit(src[0], &digit))) {
89
10.9k
              scalar_value = (scalar_value << 4) | digit;
90
10.9k
            } else {
91
0
              assert(0);
92
0
            }
93
10.9k
            src++;
94
10.9k
          } while (src[0] != '}');
95
96
          // Maximum value of a unicode scalar value
97
3.42k
          assert(scalar_value < 0x110000);
98
99
          // Encode the unicode scalar value as UTF8 sequence
100
3.42k
          if (scalar_value < 0x80) {
101
459
            *dest++ = static_cast<uint8_t>(scalar_value);
102
2.96k
          } else {
103
2.96k
            if (scalar_value < 0x800) {
104
809
              *dest++ = static_cast<uint8_t>(0xc0 | (scalar_value >> 6));
105
2.15k
            } else {
106
2.15k
              if (scalar_value < 0x10000) {
107
1.18k
                *dest++ = static_cast<uint8_t>(0xe0 | (scalar_value >> 12));
108
1.18k
              } else {
109
967
                *dest++ = static_cast<uint8_t>(0xf0 | (scalar_value >> 18));
110
967
                *dest++ =
111
967
                    static_cast<uint8_t>(0x80 | ((scalar_value >> 12) & 0x3f));
112
967
              }
113
114
2.15k
              *dest++ =
115
2.15k
                  static_cast<uint8_t>(0x80 | ((scalar_value >> 6) & 0x3f));
116
2.15k
            }
117
118
2.96k
            *dest++ = static_cast<uint8_t>(0x80 | (scalar_value & 0x3f));
119
2.96k
          }
120
3.42k
          break;
121
3.42k
        }
122
630
        default: {
123
          // The string should be validated already, so we know this is a hex
124
          // sequence.
125
630
          uint32_t hi;
126
630
          uint32_t lo;
127
630
          if (Succeeded(ParseHexdigit(src[0], &hi)) &&
128
630
              Succeeded(ParseHexdigit(src[1], &lo))) {
129
630
            *dest++ = (hi << 4) | lo;
130
630
          } else {
131
0
            assert(0);
132
0
          }
133
630
          src++;
134
630
          break;
135
630
        }
136
8.28k
      }
137
8.28k
      src++;
138
3.99M
    } else {
139
3.99M
      *dest++ = *src++;
140
3.99M
    }
141
4.00M
  }
142
2.43k
}
wast-parser.cc:void wabt::(anonymous namespace)::RemoveEscapes<std::__1::back_insert_iterator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::back_insert_iterator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >)
Line
Count
Source
44
447k
void RemoveEscapes(std::string_view text, OutputIter dest) {
45
  // Remove surrounding quotes; if any. This may be empty if the string was
46
  // invalid (e.g. if it contained a bad escape sequence).
47
447k
  if (text.size() <= 2) {
48
341k
    return;
49
341k
  }
50
51
106k
  text = text.substr(1, text.size() - 2);
52
53
106k
  const char* src = text.data();
54
106k
  const char* end = text.data() + text.size();
55
56
2.87M
  while (src < end) {
57
2.77M
    if (*src == '\\') {
58
3.35k
      src++;
59
3.35k
      switch (*src) {
60
250
        case 'n':
61
250
          *dest++ = '\n';
62
250
          break;
63
207
        case 'r':
64
207
          *dest++ = '\r';
65
207
          break;
66
205
        case 't':
67
205
          *dest++ = '\t';
68
205
          break;
69
234
        case '\\':
70
234
          *dest++ = '\\';
71
234
          break;
72
210
        case '\'':
73
210
          *dest++ = '\'';
74
210
          break;
75
194
        case '\"':
76
194
          *dest++ = '\"';
77
194
          break;
78
1.82k
        case 'u': {
79
          // The string should be validated already,
80
          // so this must be a valid unicode escape sequence.
81
1.82k
          uint32_t digit;
82
1.82k
          uint32_t scalar_value = 0;
83
84
          // Skip u and { characters.
85
1.82k
          src += 2;
86
87
5.86k
          do {
88
5.86k
            if (Succeeded(ParseHexdigit(src[0], &digit))) {
89
5.86k
              scalar_value = (scalar_value << 4) | digit;
90
5.86k
            } else {
91
0
              assert(0);
92
0
            }
93
5.86k
            src++;
94
5.86k
          } while (src[0] != '}');
95
96
          // Maximum value of a unicode scalar value
97
1.82k
          assert(scalar_value < 0x110000);
98
99
          // Encode the unicode scalar value as UTF8 sequence
100
1.82k
          if (scalar_value < 0x80) {
101
479
            *dest++ = static_cast<uint8_t>(scalar_value);
102
1.34k
          } else {
103
1.34k
            if (scalar_value < 0x800) {
104
216
              *dest++ = static_cast<uint8_t>(0xc0 | (scalar_value >> 6));
105
1.12k
            } else {
106
1.12k
              if (scalar_value < 0x10000) {
107
613
                *dest++ = static_cast<uint8_t>(0xe0 | (scalar_value >> 12));
108
613
              } else {
109
512
                *dest++ = static_cast<uint8_t>(0xf0 | (scalar_value >> 18));
110
512
                *dest++ =
111
512
                    static_cast<uint8_t>(0x80 | ((scalar_value >> 12) & 0x3f));
112
512
              }
113
114
1.12k
              *dest++ =
115
1.12k
                  static_cast<uint8_t>(0x80 | ((scalar_value >> 6) & 0x3f));
116
1.12k
            }
117
118
1.34k
            *dest++ = static_cast<uint8_t>(0x80 | (scalar_value & 0x3f));
119
1.34k
          }
120
1.82k
          break;
121
1.82k
        }
122
236
        default: {
123
          // The string should be validated already, so we know this is a hex
124
          // sequence.
125
236
          uint32_t hi;
126
236
          uint32_t lo;
127
236
          if (Succeeded(ParseHexdigit(src[0], &hi)) &&
128
236
              Succeeded(ParseHexdigit(src[1], &lo))) {
129
236
            *dest++ = (hi << 4) | lo;
130
236
          } else {
131
0
            assert(0);
132
0
          }
133
236
          src++;
134
236
          break;
135
236
        }
136
3.35k
      }
137
3.35k
      src++;
138
2.76M
    } else {
139
2.76M
      *dest++ = *src++;
140
2.76M
    }
141
2.77M
  }
142
106k
}
143
144
using TextVector = std::vector<std::string_view>;
145
146
template <typename OutputIter>
147
44.0k
void RemoveEscapes(const TextVector& texts, OutputIter out) {
148
44.0k
  for (std::string_view text : texts)
149
6.16k
    RemoveEscapes(text, out);
150
44.0k
}
151
152
8.12M
bool IsPlainInstr(TokenType token_type) {
153
8.12M
  switch (token_type) {
154
2.06k
    case TokenType::Unreachable:
155
310k
    case TokenType::Nop:
156
312k
    case TokenType::Drop:
157
316k
    case TokenType::Select:
158
332k
    case TokenType::Br:
159
334k
    case TokenType::BrIf:
160
373k
    case TokenType::BrTable:
161
390k
    case TokenType::Return:
162
393k
    case TokenType::ReturnCall:
163
413k
    case TokenType::ReturnCallIndirect:
164
419k
    case TokenType::Call:
165
438k
    case TokenType::CallIndirect:
166
439k
    case TokenType::CallRef:
167
444k
    case TokenType::LocalGet:
168
448k
    case TokenType::LocalSet:
169
461k
    case TokenType::LocalTee:
170
465k
    case TokenType::GlobalGet:
171
469k
    case TokenType::GlobalSet:
172
557k
    case TokenType::Load:
173
577k
    case TokenType::Store:
174
1.72M
    case TokenType::Const:
175
1.78M
    case TokenType::Unary:
176
1.81M
    case TokenType::Binary:
177
1.82M
    case TokenType::Compare:
178
1.83M
    case TokenType::Convert:
179
1.84M
    case TokenType::MemoryCopy:
180
1.84M
    case TokenType::DataDrop:
181
1.84M
    case TokenType::MemoryFill:
182
1.85M
    case TokenType::MemoryGrow:
183
1.85M
    case TokenType::MemoryInit:
184
1.92M
    case TokenType::MemorySize:
185
1.93M
    case TokenType::TableCopy:
186
1.93M
    case TokenType::ElemDrop:
187
1.94M
    case TokenType::TableInit:
188
1.94M
    case TokenType::TableGet:
189
1.94M
    case TokenType::TableSet:
190
1.95M
    case TokenType::TableGrow:
191
1.96M
    case TokenType::TableSize:
192
1.96M
    case TokenType::TableFill:
193
1.97M
    case TokenType::Throw:
194
1.97M
    case TokenType::Rethrow:
195
1.97M
    case TokenType::RefFunc:
196
1.98M
    case TokenType::RefNull:
197
1.98M
    case TokenType::RefIsNull:
198
1.98M
    case TokenType::AtomicLoad:
199
2.05M
    case TokenType::AtomicStore:
200
2.08M
    case TokenType::AtomicRmw:
201
2.08M
    case TokenType::AtomicRmwCmpxchg:
202
2.09M
    case TokenType::AtomicNotify:
203
2.09M
    case TokenType::AtomicFence:
204
2.09M
    case TokenType::AtomicWait:
205
2.11M
    case TokenType::Ternary:
206
2.13M
    case TokenType::SimdLaneOp:
207
2.16M
    case TokenType::SimdLoadLane:
208
2.16M
    case TokenType::SimdStoreLane:
209
2.22M
    case TokenType::SimdShuffleOp:
210
2.22M
      return true;
211
5.90M
    default:
212
5.90M
      return false;
213
8.12M
  }
214
8.12M
}
215
216
5.73M
bool IsBlockInstr(TokenType token_type) {
217
5.73M
  switch (token_type) {
218
34.5k
    case TokenType::Block:
219
181k
    case TokenType::Loop:
220
352k
    case TokenType::If:
221
440k
    case TokenType::Try:
222
440k
      return true;
223
5.29M
    default:
224
5.29M
      return false;
225
5.73M
  }
226
5.73M
}
227
228
6.80M
bool IsPlainOrBlockInstr(TokenType token_type) {
229
6.80M
  return IsPlainInstr(token_type) || IsBlockInstr(token_type);
230
6.80M
}
231
232
7.15M
bool IsExpr(TokenTypePair pair) {
233
7.15M
  return pair[0] == TokenType::Lpar && IsPlainOrBlockInstr(pair[1]);
234
7.15M
}
235
236
4.40M
bool IsInstr(TokenTypePair pair) {
237
4.40M
  return IsPlainOrBlockInstr(pair[0]) || IsExpr(pair);
238
4.40M
}
239
240
2.27M
bool IsLparAnn(TokenTypePair pair) {
241
2.27M
  return pair[0] == TokenType::LparAnn;
242
2.27M
}
243
244
43.0k
bool IsCatch(TokenType token_type) {
245
43.0k
  return token_type == TokenType::Catch || token_type == TokenType::CatchAll;
246
43.0k
}
247
248
9.65M
bool IsModuleField(TokenTypePair pair) {
249
9.65M
  if (pair[0] != TokenType::Lpar) {
250
2.87M
    return false;
251
2.87M
  }
252
253
6.77M
  switch (pair[1]) {
254
133k
    case TokenType::Data:
255
382k
    case TokenType::Elem:
256
544k
    case TokenType::Tag:
257
636k
    case TokenType::Export:
258
4.55M
    case TokenType::Func:
259
4.62M
    case TokenType::Type:
260
4.71M
    case TokenType::Global:
261
4.85M
    case TokenType::Import:
262
5.54M
    case TokenType::Memory:
263
5.54M
    case TokenType::Start:
264
6.40M
    case TokenType::Table:
265
6.40M
      return true;
266
369k
    default:
267
369k
      return false;
268
6.77M
  }
269
6.77M
}
270
271
0
bool IsCommand(TokenTypePair pair) {
272
0
  if (pair[0] != TokenType::Lpar) {
273
0
    return false;
274
0
  }
275
276
0
  switch (pair[1]) {
277
0
    case TokenType::AssertException:
278
0
    case TokenType::AssertExhaustion:
279
0
    case TokenType::AssertInvalid:
280
0
    case TokenType::AssertMalformed:
281
0
    case TokenType::AssertReturn:
282
0
    case TokenType::AssertTrap:
283
0
    case TokenType::AssertUnlinkable:
284
0
    case TokenType::Get:
285
0
    case TokenType::Invoke:
286
0
    case TokenType::Input:
287
0
    case TokenType::Module:
288
0
    case TokenType::Output:
289
0
    case TokenType::Register:
290
0
      return true;
291
0
    default:
292
0
      return false;
293
0
  }
294
0
}
295
296
10.0k
bool IsEmptySignature(const FuncSignature& sig) {
297
10.0k
  return sig.result_types.empty() && sig.param_types.empty();
298
10.0k
}
299
300
bool ResolveFuncTypeWithEmptySignature(const Module& module,
301
1.60M
                                       FuncDeclaration* decl) {
302
  // Resolve func type variables where the signature was not specified
303
  // explicitly, e.g.: (func (type 1) ...)
304
1.60M
  if (decl->has_func_type && IsEmptySignature(decl->sig)) {
305
6.18k
    const FuncType* func_type = module.GetFuncType(decl->type_var);
306
6.18k
    if (func_type) {
307
2.85k
      decl->sig = func_type->sig;
308
2.85k
      return true;
309
2.85k
    }
310
6.18k
  }
311
1.60M
  return false;
312
1.60M
}
313
314
void ResolveTypeName(
315
    const Module& module,
316
    Type& type,
317
    Index index,
318
54.9k
    const std::unordered_map<uint32_t, std::string>& bindings) {
319
54.9k
  if (type != Type::Reference || type.GetReferenceIndex() != kInvalidIndex) {
320
54.9k
    return;
321
54.9k
  }
322
323
0
  const auto name_iterator = bindings.find(index);
324
0
  assert(name_iterator != bindings.cend());
325
0
  const auto type_index = module.type_bindings.FindIndex(name_iterator->second);
326
0
  assert(type_index != kInvalidIndex);
327
0
  type = Type(Type::Reference, type_index);
328
0
}
329
330
1.59M
void ResolveTypeNames(const Module& module, FuncDeclaration* decl) {
331
1.59M
  assert(decl);
332
1.59M
  auto& signature = decl->sig;
333
334
1.63M
  for (uint32_t param_index = 0; param_index < signature.GetNumParams();
335
1.59M
       ++param_index) {
336
39.7k
    ResolveTypeName(module, signature.param_types[param_index], param_index,
337
39.7k
                    signature.param_type_names);
338
39.7k
  }
339
340
1.60M
  for (uint32_t result_index = 0; result_index < signature.GetNumResults();
341
1.59M
       ++result_index) {
342
15.2k
    ResolveTypeName(module, signature.result_types[result_index], result_index,
343
15.2k
                    signature.result_type_names);
344
15.2k
  }
345
1.59M
}
346
347
void ResolveImplicitlyDefinedFunctionType(const Location& loc,
348
                                          Module* module,
349
1.57M
                                          const FuncDeclaration& decl) {
350
  // Resolve implicitly defined function types, e.g.: (func (param i32) ...)
351
1.57M
  if (!decl.has_func_type) {
352
1.57M
    Index func_type_index = module->GetFuncTypeIndex(decl.sig);
353
1.57M
    if (func_type_index == kInvalidIndex) {
354
5.82k
      auto func_type_field = std::make_unique<TypeModuleField>(loc);
355
5.82k
      auto func_type = std::make_unique<FuncType>();
356
5.82k
      func_type->sig = decl.sig;
357
5.82k
      func_type_field->type = std::move(func_type);
358
5.82k
      module->AppendField(std::move(func_type_field));
359
5.82k
    }
360
1.57M
  }
361
1.57M
}
362
363
Result CheckTypeIndex(const Location& loc,
364
                      Type actual,
365
                      Type expected,
366
                      const char* desc,
367
                      Index index,
368
                      const char* index_kind,
369
1.32k
                      Errors* errors) {
370
  // Types must match exactly; no subtyping should be allowed.
371
1.32k
  if (actual != expected) {
372
612
    errors->emplace_back(
373
612
        ErrorLevel::Error, loc,
374
612
        StringPrintf("type mismatch for %s %" PRIindex
375
612
                     " of %s. got %s, expected %s",
376
612
                     index_kind, index, desc, actual.GetName().c_str(),
377
612
                     expected.GetName().c_str()));
378
612
    return Result::Error;
379
612
  }
380
713
  return Result::Ok;
381
1.32k
}
382
383
Result CheckTypes(const Location& loc,
384
                  const TypeVector& actual,
385
                  const TypeVector& expected,
386
                  const char* desc,
387
                  const char* index_kind,
388
9.40k
                  Errors* errors) {
389
9.40k
  Result result = Result::Ok;
390
9.40k
  if (actual.size() == expected.size()) {
391
8.41k
    for (size_t i = 0; i < actual.size(); ++i) {
392
1.32k
      result |= CheckTypeIndex(loc, actual[i], expected[i], desc, i, index_kind,
393
1.32k
                               errors);
394
1.32k
    }
395
7.09k
  } else {
396
2.31k
    errors->emplace_back(
397
2.31k
        ErrorLevel::Error, loc,
398
2.31k
        StringPrintf("expected %" PRIzd " %ss, got %" PRIzd, expected.size(),
399
2.31k
                     index_kind, actual.size()));
400
2.31k
    result = Result::Error;
401
2.31k
  }
402
9.40k
  return result;
403
9.40k
}
404
405
Result CheckFuncTypeVarMatchesExplicit(const Location& loc,
406
                                       const Module& module,
407
                                       const FuncDeclaration& decl,
408
1.60M
                                       Errors* errors) {
409
1.60M
  Result result = Result::Ok;
410
1.60M
  if (decl.has_func_type) {
411
10.0k
    const FuncType* func_type = module.GetFuncType(decl.type_var);
412
10.0k
    if (func_type) {
413
4.70k
      result |=
414
4.70k
          CheckTypes(loc, decl.sig.result_types, func_type->sig.result_types,
415
4.70k
                     "function", "result", errors);
416
4.70k
      result |=
417
4.70k
          CheckTypes(loc, decl.sig.param_types, func_type->sig.param_types,
418
4.70k
                     "function", "argument", errors);
419
5.32k
    } else if (!(decl.sig.param_types.empty() &&
420
5.32k
                 decl.sig.result_types.empty())) {
421
      // We want to check whether the function type at the explicit index
422
      // matches the given param and result types. If they were omitted then
423
      // they'll be resolved automatically (see
424
      // ResolveFuncTypeWithEmptySignature), but if they are provided then we
425
      // have to check. If we get here then the type var is invalid, so we
426
      // can't check whether they match.
427
1.98k
      if (decl.type_var.is_index()) {
428
1.27k
        errors->emplace_back(ErrorLevel::Error, loc,
429
1.27k
                             StringPrintf("invalid func type index %" PRIindex,
430
1.27k
                                          decl.type_var.index()));
431
1.27k
      } else {
432
712
        errors->emplace_back(ErrorLevel::Error, loc,
433
712
                             StringPrintf("expected func type identifier %s",
434
712
                                          decl.type_var.name().c_str()));
435
712
      }
436
1.98k
      result = Result::Error;
437
1.98k
    }
438
10.0k
  }
439
1.60M
  return result;
440
1.60M
}
441
442
27.3k
bool IsInlinableFuncSignature(const FuncSignature& sig) {
443
27.3k
  return sig.GetNumParams() == 0 && sig.GetNumResults() <= 1;
444
27.3k
}
445
446
class ResolveFuncTypesExprVisitorDelegate : public ExprVisitor::DelegateNop {
447
 public:
448
  explicit ResolveFuncTypesExprVisitorDelegate(Module* module, Errors* errors)
449
1.52M
      : module_(module), errors_(errors) {}
450
451
27.3k
  void ResolveBlockDeclaration(const Location& loc, BlockDeclaration* decl) {
452
27.3k
    ResolveTypeNames(*module_, decl);
453
27.3k
    ResolveFuncTypeWithEmptySignature(*module_, decl);
454
27.3k
    if (!IsInlinableFuncSignature(decl->sig)) {
455
1.61k
      ResolveImplicitlyDefinedFunctionType(loc, module_, *decl);
456
1.61k
    }
457
27.3k
  }
458
459
6.78k
  Result BeginBlockExpr(BlockExpr* expr) override {
460
6.78k
    ResolveBlockDeclaration(expr->loc, &expr->block.decl);
461
6.78k
    return CheckFuncTypeVarMatchesExplicit(expr->loc, *module_,
462
6.78k
                                           expr->block.decl, errors_);
463
6.78k
  }
464
465
1.72k
  Result BeginIfExpr(IfExpr* expr) override {
466
1.72k
    ResolveBlockDeclaration(expr->loc, &expr->true_.decl);
467
1.72k
    return CheckFuncTypeVarMatchesExplicit(expr->loc, *module_,
468
1.72k
                                           expr->true_.decl, errors_);
469
1.72k
  }
470
471
16.3k
  Result BeginLoopExpr(LoopExpr* expr) override {
472
16.3k
    ResolveBlockDeclaration(expr->loc, &expr->block.decl);
473
16.3k
    return CheckFuncTypeVarMatchesExplicit(expr->loc, *module_,
474
16.3k
                                           expr->block.decl, errors_);
475
16.3k
  }
476
477
2.48k
  Result BeginTryExpr(TryExpr* expr) override {
478
2.48k
    ResolveBlockDeclaration(expr->loc, &expr->block.decl);
479
2.48k
    return CheckFuncTypeVarMatchesExplicit(expr->loc, *module_,
480
2.48k
                                           expr->block.decl, errors_);
481
2.48k
  }
482
483
6.76k
  Result OnCallIndirectExpr(CallIndirectExpr* expr) override {
484
6.76k
    ResolveFuncTypeWithEmptySignature(*module_, &expr->decl);
485
6.76k
    ResolveImplicitlyDefinedFunctionType(expr->loc, module_, expr->decl);
486
6.76k
    return CheckFuncTypeVarMatchesExplicit(expr->loc, *module_, expr->decl,
487
6.76k
                                           errors_);
488
6.76k
  }
489
490
5.49k
  Result OnReturnCallIndirectExpr(ReturnCallIndirectExpr* expr) override {
491
5.49k
    ResolveFuncTypeWithEmptySignature(*module_, &expr->decl);
492
5.49k
    ResolveImplicitlyDefinedFunctionType(expr->loc, module_, expr->decl);
493
5.49k
    return CheckFuncTypeVarMatchesExplicit(expr->loc, *module_, expr->decl,
494
5.49k
                                           errors_);
495
5.49k
  }
496
497
 private:
498
  Module* module_;
499
  Errors* errors_;
500
};
501
502
7.25k
Result ResolveFuncTypes(Module* module, Errors* errors) {
503
7.25k
  Result result = Result::Ok;
504
2.05M
  for (ModuleField& field : module->fields) {
505
2.05M
    Func* func = nullptr;
506
2.05M
    FuncDeclaration* decl = nullptr;
507
2.05M
    if (auto* func_field = dyn_cast<FuncModuleField>(&field)) {
508
1.52M
      func = &func_field->func;
509
1.52M
      decl = &func->decl;
510
1.52M
    } else if (auto* tag_field = dyn_cast<TagModuleField>(&field)) {
511
0
      decl = &tag_field->tag.decl;
512
530k
    } else if (auto* import_field = dyn_cast<ImportModuleField>(&field)) {
513
40.5k
      if (auto* func_import =
514
40.5k
              dyn_cast<FuncImport>(import_field->import.get())) {
515
        // Only check the declaration, not the function itself, since it is an
516
        // import.
517
27.1k
        decl = &func_import->func.decl;
518
27.1k
      } else if (auto* tag_import =
519
13.4k
                     dyn_cast<TagImport>(import_field->import.get())) {
520
12.9k
        decl = &tag_import->tag.decl;
521
12.9k
      } else {
522
517
        continue;
523
517
      }
524
490k
    } else {
525
490k
      continue;
526
490k
    }
527
528
1.56M
    bool has_func_type_and_empty_signature = false;
529
530
1.56M
    if (decl) {
531
1.56M
      ResolveTypeNames(*module, decl);
532
1.56M
      has_func_type_and_empty_signature =
533
1.56M
          ResolveFuncTypeWithEmptySignature(*module, decl);
534
1.56M
      ResolveImplicitlyDefinedFunctionType(field.loc, module, *decl);
535
1.56M
      result |=
536
1.56M
          CheckFuncTypeVarMatchesExplicit(field.loc, *module, *decl, errors);
537
1.56M
    }
538
539
1.56M
    if (func) {
540
1.52M
      if (has_func_type_and_empty_signature) {
541
        // The call to ResolveFuncTypeWithEmptySignature may have updated the
542
        // function signature so there are parameters. Since parameters and
543
        // local variables share the same index space, we need to increment the
544
        // local indexes bound to a given name by the number of parameters in
545
        // the function.
546
2.04k
        for (auto& [name, binding] : func->bindings) {
547
2.04k
          binding.index += func->GetNumParams();
548
2.04k
        }
549
1.33k
      }
550
551
1.52M
      ResolveFuncTypesExprVisitorDelegate delegate(module, errors);
552
1.52M
      ExprVisitor visitor(&delegate);
553
1.52M
      result |= visitor.VisitFunc(func);
554
1.52M
    }
555
1.56M
  }
556
7.25k
  return result;
557
7.25k
}
558
559
void AppendInlineExportFields(Module* module,
560
                              ModuleFieldList* fields,
561
2.80M
                              Index index) {
562
2.80M
  Location last_field_loc = module->fields.back().loc;
563
564
2.80M
  for (ModuleField& field : *fields) {
565
48.8k
    auto* export_field = cast<ExportModuleField>(&field);
566
48.8k
    export_field->export_.var = Var(index, last_field_loc);
567
48.8k
  }
568
569
2.80M
  module->AppendFields(fields);
570
2.80M
}
571
572
}  // End of anonymous namespace
573
574
WastParser::WastParser(WastLexer* lexer,
575
                       Errors* errors,
576
                       WastParseOptions* options)
577
22.7k
    : lexer_(lexer), errors_(errors), options_(options) {}
578
579
6.23M
void WastParser::Error(Location loc, const char* format, ...) {
580
6.23M
  WABT_SNPRINTF_ALLOCA(buffer, length, format);
581
6.23M
  errors_->emplace_back(ErrorLevel::Error, loc, buffer);
582
6.23M
}
583
584
8.86M
Token WastParser::GetToken() {
585
8.86M
  if (tokens_.empty()) {
586
618k
    tokens_.push_back(lexer_->GetToken());
587
618k
  }
588
8.86M
  return tokens_.front();
589
8.86M
}
590
591
7.89M
Location WastParser::GetLocation() {
592
7.89M
  return GetToken().loc;
593
7.89M
}
594
595
88.2M
TokenType WastParser::Peek(size_t n) {
596
88.2M
  assert(n <= 1);
597
112M
  while (tokens_.size() <= n) {
598
24.2M
    Token cur = lexer_->GetToken();
599
24.2M
    if (cur.token_type() != TokenType::LparAnn) {
600
22.8M
      tokens_.push_back(cur);
601
22.8M
    } else {
602
      // Custom annotation. For now, discard until matching Rpar, unless it is
603
      // a code metadata annotation or custom section. In those cases, we know
604
      // how to parse it.
605
1.41M
      if (!options_->features.annotations_enabled()) {
606
1.41M
        Error(cur.loc, "annotations not enabled: %s", cur.to_string().c_str());
607
1.41M
        tokens_.push_back(Token(cur.loc, TokenType::Invalid));
608
1.41M
        continue;
609
1.41M
      }
610
0
      if ((options_->features.code_metadata_enabled() &&
611
0
           cur.text().find("metadata.code.") == 0) ||
612
0
          cur.text() == "custom") {
613
0
        tokens_.push_back(cur);
614
0
        continue;
615
0
      }
616
0
      int indent = 1;
617
0
      while (indent > 0) {
618
0
        cur = lexer_->GetToken();
619
0
        switch (cur.token_type()) {
620
0
          case TokenType::Lpar:
621
0
          case TokenType::LparAnn:
622
0
            indent++;
623
0
            break;
624
625
0
          case TokenType::Rpar:
626
0
            indent--;
627
0
            break;
628
629
0
          case TokenType::Eof:
630
0
            indent = 0;
631
0
            Error(cur.loc, "unterminated annotation");
632
0
            break;
633
634
0
          default:
635
0
            break;
636
0
        }
637
0
      }
638
0
    }
639
24.2M
  }
640
88.2M
  return tokens_.at(n).token_type();
641
88.2M
}
642
643
17.2M
TokenTypePair WastParser::PeekPair() {
644
17.2M
  return TokenTypePair{{Peek(), Peek(1)}};
645
17.2M
}
646
647
28.8M
bool WastParser::PeekMatch(TokenType type, size_t n) {
648
28.8M
  return Peek(n) == type;
649
28.8M
}
650
651
16.7M
bool WastParser::PeekMatchLpar(TokenType type) {
652
16.7M
  return Peek() == TokenType::Lpar && Peek(1) == type;
653
16.7M
}
654
655
1.44M
bool WastParser::PeekMatchExpr() {
656
1.44M
  return IsExpr(PeekPair());
657
1.44M
}
658
659
221k
bool WastParser::PeekMatchRefType() {
660
221k
  return options_->features.function_references_enabled() &&
661
221k
         PeekMatchLpar(TokenType::Ref);
662
221k
}
663
664
15.3M
bool WastParser::Match(TokenType type) {
665
15.3M
  if (PeekMatch(type)) {
666
9.21M
    Consume();
667
9.21M
    return true;
668
9.21M
  }
669
6.11M
  return false;
670
15.3M
}
671
672
10.2M
bool WastParser::MatchLpar(TokenType type) {
673
10.2M
  if (PeekMatchLpar(type)) {
674
117k
    Consume();
675
117k
    Consume();
676
117k
    return true;
677
117k
  }
678
10.1M
  return false;
679
10.2M
}
680
681
11.5M
Result WastParser::Expect(TokenType type) {
682
11.5M
  if (!Match(type)) {
683
2.64M
    Token token = Consume();
684
2.64M
    Error(token.loc, "unexpected token %s, expected %s.",
685
2.64M
          token.to_string_clamp(kMaxErrorTokenLength).c_str(),
686
2.64M
          GetTokenTypeName(type));
687
2.64M
    return Result::Error;
688
2.64M
  }
689
690
8.88M
  return Result::Ok;
691
11.5M
}
692
693
24.8M
Token WastParser::Consume() {
694
24.8M
  assert(!tokens_.empty());
695
24.8M
  Token token = tokens_.front();
696
24.8M
  tokens_.pop_front();
697
24.8M
  return token;
698
24.8M
}
699
700
3.44M
Result WastParser::Synchronize(SynchronizeFunc func) {
701
3.44M
  static const int kMaxConsumed = 10;
702
9.49M
  for (int i = 0; i < kMaxConsumed; ++i) {
703
9.31M
    if (func(PeekPair())) {
704
3.26M
      return Result::Ok;
705
3.26M
    }
706
707
6.05M
    Token token = Consume();
708
6.05M
    if (token.token_type() == TokenType::Reserved) {
709
1.23M
      Error(token.loc, "unexpected token %s.",
710
1.23M
            token.to_string_clamp(kMaxErrorTokenLength).c_str());
711
1.23M
    }
712
6.05M
  }
713
714
181k
  return Result::Error;
715
3.44M
}
716
717
231k
void WastParser::ErrorUnlessOpcodeEnabled(const Token& token) {
718
231k
  Opcode opcode = token.opcode();
719
231k
  if (!opcode.IsEnabled(options_->features)) {
720
98.0k
    Error(token.loc, "opcode not allowed: %s", opcode.GetName());
721
98.0k
  }
722
231k
}
723
724
Result WastParser::ErrorExpected(const std::vector<std::string>& expected,
725
488k
                                 const char* example) {
726
488k
  GetToken();
727
488k
  Token token = Consume();
728
488k
  std::string expected_str;
729
488k
  if (!expected.empty()) {
730
488k
    expected_str = ", expected ";
731
1.11M
    for (size_t i = 0; i < expected.size(); ++i) {
732
625k
      if (i != 0) {
733
137k
        if (i == expected.size() - 1) {
734
62.8k
          expected_str += " or ";
735
74.5k
        } else {
736
74.5k
          expected_str += ", ";
737
74.5k
        }
738
137k
      }
739
740
625k
      expected_str += expected[i];
741
625k
    }
742
743
488k
    if (example) {
744
171k
      expected_str += " (e.g. ";
745
171k
      expected_str += example;
746
171k
      expected_str += ")";
747
171k
    }
748
488k
  }
749
750
488k
  Error(token.loc, "unexpected token \"%s\"%s.",
751
488k
        token.to_string_clamp(kMaxErrorTokenLength).c_str(),
752
488k
        expected_str.c_str());
753
488k
  return Result::Error;
754
488k
}
755
756
Result WastParser::ErrorIfLpar(const std::vector<std::string>& expected,
757
2.70M
                               const char* example) {
758
2.70M
  if (Match(TokenType::Lpar)) {
759
259k
    return ErrorExpected(expected, example);
760
259k
  }
761
2.44M
  return Result::Ok;
762
2.70M
}
763
764
3.48M
bool WastParser::ParseBindVarOpt(std::string* name) {
765
3.48M
  WABT_TRACE(ParseBindVarOpt);
766
3.48M
  if (!PeekMatch(TokenType::Var)) {
767
2.50M
    return false;
768
2.50M
  }
769
982k
  Token token = Consume();
770
982k
  *name = std::string(token.text());
771
982k
  return true;
772
3.48M
}
773
774
992k
Result WastParser::ParseVar(Var* out_var) {
775
992k
  WABT_TRACE(ParseVar);
776
992k
  if (PeekMatch(TokenType::Nat)) {
777
256k
    Token token = Consume();
778
256k
    std::string_view sv = token.literal().text;
779
256k
    uint64_t index = kInvalidIndex;
780
256k
    if (Failed(ParseUint64(sv, &index))) {
781
      // Print an error, but don't fail parsing.
782
1.03k
      Error(token.loc, "invalid int \"" PRIstringview "\"",
783
1.03k
            WABT_PRINTF_STRING_VIEW_ARG(sv));
784
1.03k
    }
785
786
256k
    *out_var = Var(index, token.loc);
787
256k
    return Result::Ok;
788
736k
  } else if (PeekMatch(TokenType::Var)) {
789
715k
    Token token = Consume();
790
715k
    *out_var = Var(token.text(), token.loc);
791
715k
    return Result::Ok;
792
715k
  } else {
793
21.2k
    return ErrorExpected({"a numeric index", "a name"}, "12 or $foo");
794
21.2k
  }
795
992k
}
796
797
1.45M
bool WastParser::ParseVarOpt(Var* out_var, Var default_var) {
798
1.45M
  WABT_TRACE(ParseVarOpt);
799
1.45M
  if (PeekMatch(TokenType::Nat) || PeekMatch(TokenType::Var)) {
800
861k
    Result result = ParseVar(out_var);
801
    // Should always succeed, the only way it could fail is if the token
802
    // doesn't match.
803
861k
    assert(Succeeded(result));
804
861k
    WABT_USE(result);
805
861k
    return true;
806
861k
  } else {
807
593k
    *out_var = default_var;
808
593k
    return false;
809
593k
  }
810
1.45M
}
811
812
4.18k
Result WastParser::ParseOffsetExpr(ExprList* out_expr_list) {
813
4.18k
  WABT_TRACE(ParseOffsetExpr);
814
4.18k
  if (!ParseOffsetExprOpt(out_expr_list)) {
815
3.01k
    return ErrorExpected({"an offset expr"}, "(i32.const 123)");
816
3.01k
  }
817
1.17k
  return Result::Ok;
818
4.18k
}
819
820
277k
bool WastParser::ParseOffsetExprOpt(ExprList* out_expr_list) {
821
277k
  WABT_TRACE(ParseOffsetExprOpt);
822
277k
  if (MatchLpar(TokenType::Offset)) {
823
393
    CHECK_RESULT(ParseTerminatingInstrList(out_expr_list));
824
194
    EXPECT(Rpar);
825
0
    return true;
826
276k
  } else if (PeekMatchExpr()) {
827
2.56k
    CHECK_RESULT(ParseExpr(out_expr_list));
828
555
    return true;
829
274k
  } else {
830
274k
    return false;
831
274k
  }
832
277k
}
833
834
0
Result WastParser::ParseTextList(std::vector<uint8_t>* out_data) {
835
0
  WABT_TRACE(ParseTextList);
836
0
  if (!ParseTextListOpt(out_data)) {
837
    // TODO(binji): Add error message here.
838
0
    return Result::Error;
839
0
  }
840
841
0
  return Result::Ok;
842
0
}
843
844
44.0k
bool WastParser::ParseTextListOpt(std::vector<uint8_t>* out_data) {
845
44.0k
  WABT_TRACE(ParseTextListOpt);
846
44.0k
  TextVector texts;
847
50.2k
  while (PeekMatch(TokenType::Text))
848
6.16k
    texts.push_back(Consume().text());
849
850
44.0k
  RemoveEscapes(texts, std::back_inserter(*out_data));
851
44.0k
  return !texts.empty();
852
44.0k
}
853
854
10.8k
Result WastParser::ParseVarList(VarVector* out_var_list) {
855
10.8k
  WABT_TRACE(ParseVarList);
856
10.8k
  Var var;
857
287k
  while (ParseVarOpt(&var)) {
858
276k
    out_var_list->emplace_back(var);
859
276k
  }
860
10.8k
  if (out_var_list->empty()) {
861
9.72k
    return ErrorExpected({"a var"}, "12 or $foo");
862
9.72k
  } else {
863
1.14k
    return Result::Ok;
864
1.14k
  }
865
10.8k
}
866
867
4.67k
bool WastParser::ParseElemExprOpt(ExprList* out_elem_expr) {
868
4.67k
  WABT_TRACE(ParseElemExprOpt);
869
4.67k
  bool item = MatchLpar(TokenType::Item);
870
4.67k
  ExprList exprs;
871
4.67k
  if (item) {
872
633
    if (ParseTerminatingInstrList(&exprs) != Result::Ok) {
873
197
      return false;
874
197
    }
875
436
    EXPECT(Rpar);
876
4.04k
  } else {
877
4.04k
    if (!IsExpr(PeekPair()) || ParseExpr(&exprs) != Result::Ok) {
878
2.39k
      return false;
879
2.39k
    }
880
4.04k
  }
881
1.83k
  if (!exprs.size()) {
882
194
    return false;
883
194
  }
884
1.64k
  *out_elem_expr = std::move(exprs);
885
1.64k
  return true;
886
1.83k
}
887
888
1.92k
bool WastParser::ParseElemExprListOpt(ExprListVector* out_list) {
889
1.92k
  ExprList elem_expr;
890
3.61k
  while (ParseElemExprOpt(&elem_expr)) {
891
1.69k
    out_list->push_back(std::move(elem_expr));
892
1.69k
  }
893
1.92k
  return !out_list->empty();
894
1.92k
}
895
896
229k
bool WastParser::ParseElemExprVarListOpt(ExprListVector* out_list) {
897
229k
  WABT_TRACE(ParseElemExprVarListOpt);
898
229k
  Var var;
899
229k
  ExprList init_expr;
900
761k
  while (ParseVarOpt(&var)) {
901
531k
    init_expr.push_back(std::make_unique<RefFuncExpr>(var));
902
531k
    out_list->push_back(std::move(init_expr));
903
531k
  }
904
229k
  return !out_list->empty();
905
229k
}
906
907
173k
Result WastParser::ParseValueType(Var* out_type) {
908
173k
  WABT_TRACE(ParseValueType);
909
910
173k
  const bool is_ref_type = PeekMatchRefType();
911
173k
  const bool is_value_type = PeekMatch(TokenType::ValueType);
912
913
173k
  if (!is_value_type && !is_ref_type) {
914
12.6k
    return ErrorExpected(
915
12.6k
        {"i32", "i64", "f32", "f64", "v128", "externref", "funcref"});
916
12.6k
  }
917
918
160k
  if (is_ref_type) {
919
0
    EXPECT(Lpar);
920
0
    EXPECT(Ref);
921
0
    CHECK_RESULT(ParseVar(out_type));
922
0
    EXPECT(Rpar);
923
0
    return Result::Ok;
924
0
  }
925
926
160k
  Token token = Consume();
927
160k
  Type type = token.type();
928
160k
  bool is_enabled;
929
160k
  switch (type) {
930
195
    case Type::V128:
931
195
      is_enabled = options_->features.simd_enabled();
932
195
      break;
933
220
    case Type::FuncRef:
934
416
    case Type::ExternRef:
935
416
      is_enabled = options_->features.reference_types_enabled();
936
416
      break;
937
160k
    default:
938
160k
      is_enabled = true;
939
160k
      break;
940
160k
  }
941
942
160k
  if (!is_enabled) {
943
0
    Error(token.loc, "value type not allowed: %s", type.GetName().c_str());
944
0
    return Result::Error;
945
0
  }
946
947
160k
  *out_type = Var(type, GetLocation());
948
160k
  return Result::Ok;
949
160k
}
950
951
Result WastParser::ParseValueTypeList(
952
    TypeVector* out_type_list,
953
16.1k
    std::unordered_map<uint32_t, std::string>* type_names) {
954
16.1k
  WABT_TRACE(ParseValueTypeList);
955
48.1k
  while (true) {
956
48.1k
    if (!PeekMatchRefType() && !PeekMatch(TokenType::ValueType)) {
957
16.1k
      break;
958
16.1k
    }
959
960
32.0k
    Var type;
961
32.0k
    CHECK_RESULT(ParseValueType(&type));
962
963
32.0k
    if (type.is_index()) {
964
32.0k
      out_type_list->push_back(Type(type.index()));
965
32.0k
    } else {
966
0
      assert(type.is_name());
967
0
      assert(options_->features.function_references_enabled());
968
0
      type_names->emplace(out_type_list->size(), type.name());
969
0
      out_type_list->push_back(Type(Type::Reference, kInvalidIndex));
970
0
    }
971
32.0k
  }
972
973
16.1k
  return Result::Ok;
974
16.1k
}
975
976
1.58k
Result WastParser::ParseRefKind(Type* out_type) {
977
1.58k
  WABT_TRACE(ParseRefKind);
978
1.58k
  if (!IsTokenTypeRefKind(Peek())) {
979
861
    return ErrorExpected({"func", "extern", "exn"});
980
861
  }
981
982
728
  Token token = Consume();
983
728
  Type type = token.type();
984
985
728
  if ((type == Type::ExternRef &&
986
728
       !options_->features.reference_types_enabled()) ||
987
728
      ((type == Type::Struct || type == Type::Array) &&
988
728
       !options_->features.gc_enabled())) {
989
0
    Error(token.loc, "value type not allowed: %s", type.GetName().c_str());
990
0
    return Result::Error;
991
0
  }
992
993
728
  *out_type = type;
994
728
  return Result::Ok;
995
728
}
996
997
415k
Result WastParser::ParseRefType(Type* out_type) {
998
415k
  WABT_TRACE(ParseRefType);
999
415k
  if (!PeekMatch(TokenType::ValueType)) {
1000
15.9k
    return ErrorExpected({"funcref", "externref"});
1001
15.9k
  }
1002
1003
399k
  Token token = Consume();
1004
399k
  Type type = token.type();
1005
399k
  if (type == Type::ExternRef &&
1006
399k
      !options_->features.reference_types_enabled()) {
1007
0
    Error(token.loc, "value type not allowed: %s", type.GetName().c_str());
1008
0
    return Result::Error;
1009
0
  }
1010
1011
399k
  *out_type = type;
1012
399k
  return Result::Ok;
1013
399k
}
1014
1015
230k
bool WastParser::ParseRefTypeOpt(Type* out_type) {
1016
230k
  WABT_TRACE(ParseRefTypeOpt);
1017
230k
  if (!PeekMatch(TokenType::ValueType)) {
1018
229k
    return false;
1019
229k
  }
1020
1021
1.72k
  Token token = Consume();
1022
1.72k
  Type type = token.type();
1023
1.72k
  if (type == Type::ExternRef &&
1024
1.72k
      !options_->features.reference_types_enabled()) {
1025
0
    return false;
1026
0
  }
1027
1028
1.72k
  *out_type = type;
1029
1.72k
  return true;
1030
1.72k
}
1031
1032
474k
Result WastParser::ParseQuotedText(std::string* text, bool check_utf8) {
1033
474k
  WABT_TRACE(ParseQuotedText);
1034
474k
  if (!PeekMatch(TokenType::Text)) {
1035
26.9k
    return ErrorExpected({"a quoted string"}, "\"foo\"");
1036
26.9k
  }
1037
1038
447k
  Token token = Consume();
1039
447k
  RemoveEscapes(token.text(), std::back_inserter(*text));
1040
447k
  if (check_utf8 && !IsValidUtf8(text->data(), text->length())) {
1041
96.3k
    Error(token.loc, "quoted string has an invalid utf-8 encoding");
1042
96.3k
  }
1043
447k
  return Result::Ok;
1044
474k
}
1045
1046
57.4k
bool WastParser::ParseOffsetOpt(Address* out_offset) {
1047
57.4k
  WABT_TRACE(ParseOffsetOpt);
1048
57.4k
  if (PeekMatch(TokenType::OffsetEqNat)) {
1049
20.0k
    Token token = Consume();
1050
20.0k
    uint64_t offset64;
1051
20.0k
    std::string_view sv = token.text();
1052
20.0k
    if (Failed(ParseInt64(sv, &offset64, ParseIntType::SignedAndUnsigned))) {
1053
18.3k
      Error(token.loc, "invalid offset \"" PRIstringview "\"",
1054
18.3k
            WABT_PRINTF_STRING_VIEW_ARG(sv));
1055
18.3k
    }
1056
    // With memory64, offsets > UINT32_MAX for i32 memories are no longer
1057
    // malformed (just invalid)
1058
20.0k
    if ((!options_->features.memory64_enabled()) && (offset64 > UINT32_MAX)) {
1059
1.09k
      Error(token.loc, "offset must be less than or equal to 0xffffffff");
1060
1.09k
    }
1061
20.0k
    *out_offset = offset64;
1062
20.0k
    return true;
1063
37.3k
  } else {
1064
37.3k
    *out_offset = 0;
1065
37.3k
    return false;
1066
37.3k
  }
1067
57.4k
}
1068
1069
57.4k
bool WastParser::ParseAlignOpt(Address* out_align) {
1070
57.4k
  WABT_TRACE(ParseAlignOpt);
1071
57.4k
  if (PeekMatch(TokenType::AlignEqNat)) {
1072
3.53k
    Token token = Consume();
1073
3.53k
    std::string_view sv = token.text();
1074
3.53k
    if (Failed(ParseInt64(sv, out_align, ParseIntType::UnsignedOnly))) {
1075
393
      Error(token.loc, "invalid alignment \"" PRIstringview "\"",
1076
393
            WABT_PRINTF_STRING_VIEW_ARG(sv));
1077
393
    }
1078
1079
3.53k
    if (!IsPowerOfTwo(*out_align)) {
1080
1.50k
      Error(token.loc, "alignment must be power-of-two");
1081
1.50k
    }
1082
1083
3.53k
    return true;
1084
53.8k
  } else {
1085
53.8k
    *out_align = WABT_USE_NATURAL_ALIGNMENT;
1086
53.8k
    return false;
1087
53.8k
  }
1088
57.4k
}
1089
1090
94.0k
Result WastParser::ParseMemidx(Location loc, Var* out_memidx) {
1091
94.0k
  WABT_TRACE(ParseMemidx);
1092
94.0k
  if (PeekMatchLpar(TokenType::Memory)) {
1093
1.77k
    if (!options_->features.multi_memory_enabled()) {
1094
1.77k
      Error(loc, "Specifying memory variable is not allowed");
1095
1.77k
      return Result::Error;
1096
1.77k
    }
1097
0
    EXPECT(Lpar);
1098
0
    EXPECT(Memory);
1099
0
    CHECK_RESULT(ParseVar(out_memidx));
1100
0
    EXPECT(Rpar);
1101
92.2k
  } else {
1102
92.2k
    if (ParseVarOpt(out_memidx, Var(0, loc)) &&
1103
92.2k
        !options_->features.multi_memory_enabled()) {
1104
22.6k
      Error(loc, "Specifying memory variable is not allowed");
1105
22.6k
      return Result::Error;
1106
22.6k
    }
1107
92.2k
  }
1108
69.5k
  return Result::Ok;
1109
94.0k
}
1110
1111
784k
Result WastParser::ParseLimitsIndex(Limits* out_limits) {
1112
784k
  WABT_TRACE(ParseLimitsIndex);
1113
1114
784k
  if (PeekMatch(TokenType::ValueType)) {
1115
3.01k
    if (GetToken().type() == Type::I64) {
1116
886
      Consume();
1117
886
      out_limits->is_64 = true;
1118
2.12k
    } else if (GetToken().type() == Type::I32) {
1119
225
      Consume();
1120
225
      out_limits->is_64 = false;
1121
225
    }
1122
3.01k
  }
1123
1124
784k
  return Result::Ok;
1125
784k
}
1126
1127
782k
Result WastParser::ParseLimits(Limits* out_limits) {
1128
782k
  WABT_TRACE(ParseLimits);
1129
1130
782k
  CHECK_RESULT(ParseNat(&out_limits->initial, out_limits->is_64));
1131
744k
  if (PeekMatch(TokenType::Nat)) {
1132
20.5k
    CHECK_RESULT(ParseNat(&out_limits->max, out_limits->is_64));
1133
20.5k
    out_limits->has_max = true;
1134
724k
  } else {
1135
724k
    out_limits->has_max = false;
1136
724k
  }
1137
1138
744k
  if (Match(TokenType::Shared)) {
1139
215
    out_limits->is_shared = true;
1140
215
  }
1141
1142
744k
  return Result::Ok;
1143
744k
}
1144
1145
802k
Result WastParser::ParseNat(uint64_t* out_nat, bool is_64) {
1146
802k
  WABT_TRACE(ParseNat);
1147
802k
  if (!PeekMatch(TokenType::Nat)) {
1148
37.4k
    return ErrorExpected({"a natural number"}, "123");
1149
37.4k
  }
1150
1151
765k
  Token token = Consume();
1152
765k
  std::string_view sv = token.literal().text;
1153
765k
  if (Failed(ParseUint64(sv, out_nat)) || (!is_64 && *out_nat > 0xffffffffu)) {
1154
2.15k
    Error(token.loc, "invalid int \"" PRIstringview "\"",
1155
2.15k
          WABT_PRINTF_STRING_VIEW_ARG(sv));
1156
2.15k
  }
1157
1158
765k
  return Result::Ok;
1159
802k
}
1160
1161
22.7k
Result WastParser::ParseModule(std::unique_ptr<Module>* out_module) {
1162
22.7k
  WABT_TRACE(ParseModule);
1163
22.7k
  auto module = std::make_unique<Module>();
1164
1165
22.7k
  if (PeekMatchLpar(TokenType::Module)) {
1166
    // Starts with "(module". Allow text and binary modules, but no quoted
1167
    // modules.
1168
128
    CommandPtr command;
1169
128
    CHECK_RESULT(ParseModuleCommand(nullptr, &command));
1170
71
    if (isa<ModuleCommand>(command.get())) {
1171
71
      auto module_command = cast<ModuleCommand>(std::move(command));
1172
71
      *module = std::move(module_command->module);
1173
71
    } else {
1174
0
      assert(isa<ScriptModuleCommand>(command.get()));
1175
0
      auto module_command = cast<ScriptModuleCommand>(std::move(command));
1176
0
      *module = std::move(module_command->module);
1177
0
    }
1178
22.5k
  } else if (IsModuleField(PeekPair()) || PeekIsCustom()) {
1179
    // Parse an inline module (i.e. one with no surrounding (module)).
1180
20.5k
    CHECK_RESULT(ParseModuleFieldList(module.get()));
1181
20.5k
  } else if (PeekMatch(TokenType::Eof)) {
1182
679
    errors_->emplace_back(ErrorLevel::Warning, GetLocation(), "empty module");
1183
1.31k
  } else {
1184
1.31k
    ConsumeIfLpar();
1185
1.31k
    ErrorExpected({"a module field", "a module"});
1186
1.31k
  }
1187
1188
4.26k
  EXPECT(Eof);
1189
3.38k
  if (!HasError()) {
1190
1.66k
    *out_module = std::move(module);
1191
1.66k
    return Result::Ok;
1192
1.71k
  } else {
1193
1.71k
    return Result::Error;
1194
1.71k
  }
1195
3.38k
}
1196
1197
0
Result WastParser::ParseScript(std::unique_ptr<Script>* out_script) {
1198
0
  WABT_TRACE(ParseScript);
1199
0
  auto script = std::make_unique<Script>();
1200
1201
  // Don't consume the Lpar yet, even though it is required. This way the
1202
  // sub-parser functions (e.g. ParseFuncModuleField) can consume it and keep
1203
  // the parsing structure more regular.
1204
0
  if (IsModuleField(PeekPair()) || PeekIsCustom()) {
1205
    // Parse an inline module (i.e. one with no surrounding (module)).
1206
0
    auto command = std::make_unique<ModuleCommand>();
1207
0
    command->module.loc = GetLocation();
1208
0
    CHECK_RESULT(ParseModuleFieldList(&command->module));
1209
0
    script->commands.emplace_back(std::move(command));
1210
0
  } else if (IsCommand(PeekPair())) {
1211
0
    CHECK_RESULT(ParseCommandList(script.get(), &script->commands));
1212
0
  } else if (PeekMatch(TokenType::Eof)) {
1213
0
    errors_->emplace_back(ErrorLevel::Warning, GetLocation(), "empty script");
1214
0
  } else {
1215
0
    ConsumeIfLpar();
1216
0
    ErrorExpected({"a module field", "a command"});
1217
0
  }
1218
1219
0
  EXPECT(Eof);
1220
0
  if (!HasError()) {
1221
0
    *out_script = std::move(script);
1222
0
    return Result::Ok;
1223
0
  } else {
1224
0
    return Result::Error;
1225
0
  }
1226
0
}
1227
1228
0
Result WastParser::ParseCustomSectionAnnotation(Module* module) {
1229
0
  WABT_TRACE(ParseCustomSectionAnnotation);
1230
0
  Location loc = GetLocation();
1231
0
  Token token = Consume();
1232
0
  if (token.text() != "custom") {
1233
0
    assert(
1234
0
        !"ParseCustomSectionAnnotation should only be called if PeekIsCustom() is true");
1235
0
    return Result::Error;
1236
0
  }
1237
0
  std::string section_name;
1238
0
  CHECK_RESULT(ParseQuotedText(&section_name));
1239
0
  if (Match(TokenType::Lpar)) {
1240
0
    if (!PeekMatch(TokenType::After) && !PeekMatch(TokenType::Before)) {
1241
0
      return ErrorExpected({"before", "after"});
1242
0
    }
1243
0
    Consume();
1244
0
    switch (Peek()) {
1245
0
      case TokenType::Function:
1246
0
      case TokenType::Type:
1247
0
      case TokenType::Import:
1248
0
      case TokenType::Export:
1249
0
      case TokenType::Table:
1250
0
      case TokenType::Global:
1251
0
      case TokenType::Elem:
1252
0
      case TokenType::Data:
1253
0
      case TokenType::Memory:
1254
0
      case TokenType::Code:
1255
0
      case TokenType::Start: {
1256
0
        Consume();
1257
0
        break;
1258
0
      }
1259
0
      default: {
1260
0
        return ErrorExpected({"type", "import", "function", "table", "memory",
1261
0
                              "global", "export", "start", "elem", "code",
1262
0
                              "data"});
1263
0
      }
1264
0
    }
1265
0
    EXPECT(Rpar);
1266
0
  }
1267
0
  std::vector<uint8_t> data;
1268
0
  CHECK_RESULT(ParseTextList(&data));
1269
0
  EXPECT(Rpar);
1270
1271
0
  Custom custom = Custom(loc, section_name, data);
1272
0
  module->customs.push_back(custom);
1273
1274
0
  return Result::Ok;
1275
0
}
1276
1277
3.59M
bool WastParser::PeekIsCustom() {
1278
  // If IsLparAnn succeeds, tokens_.front() must have text, as it is an LparAnn
1279
  // token.
1280
3.59M
  return options_->features.annotations_enabled() && IsLparAnn(PeekPair()) &&
1281
3.59M
         tokens_.front().text() == "custom";
1282
3.59M
}
1283
1284
20.7k
Result WastParser::ParseModuleFieldList(Module* module) {
1285
20.7k
  WABT_TRACE(ParseModuleFieldList);
1286
3.59M
  while (IsModuleField(PeekPair()) || PeekIsCustom()) {
1287
3.58M
    if (PeekIsCustom()) {
1288
0
      CHECK_RESULT(ParseCustomSectionAnnotation(module));
1289
0
      continue;
1290
0
    }
1291
3.58M
    if (Failed(ParseModuleField(module))) {
1292
2.81M
      CHECK_RESULT(Synchronize(IsModuleField));
1293
2.81M
    }
1294
3.58M
  }
1295
7.25k
  CHECK_RESULT(ResolveFuncTypes(module, errors_));
1296
6.99k
  CHECK_RESULT(ResolveNamesModule(module, errors_));
1297
2.27k
  return Result::Ok;
1298
6.99k
}
1299
1300
3.58M
Result WastParser::ParseModuleField(Module* module) {
1301
3.58M
  WABT_TRACE(ParseModuleField);
1302
3.58M
  switch (Peek(1)) {
1303
77.4k
    case TokenType::Data:   return ParseDataModuleField(module);
1304
231k
    case TokenType::Elem:   return ParseElemModuleField(module);
1305
80.8k
    case TokenType::Tag:    return ParseTagModuleField(module);
1306
53.4k
    case TokenType::Export: return ParseExportModuleField(module);
1307
2.17M
    case TokenType::Func:   return ParseFuncModuleField(module);
1308
50.1k
    case TokenType::Type:   return ParseTypeModuleField(module);
1309
68.8k
    case TokenType::Global: return ParseGlobalModuleField(module);
1310
70.4k
    case TokenType::Import: return ParseImportModuleField(module);
1311
347k
    case TokenType::Memory: return ParseMemoryModuleField(module);
1312
1.26k
    case TokenType::Start:  return ParseStartModuleField(module);
1313
432k
    case TokenType::Table:  return ParseTableModuleField(module);
1314
0
    default:
1315
0
      assert(
1316
0
          !"ParseModuleField should only be called if IsModuleField() is true");
1317
0
      return Result::Error;
1318
3.58M
  }
1319
3.58M
}
1320
1321
77.4k
Result WastParser::ParseDataModuleField(Module* module) {
1322
77.4k
  WABT_TRACE(ParseDataModuleField);
1323
77.4k
  EXPECT(Lpar);
1324
77.4k
  Location loc = GetLocation();
1325
77.4k
  EXPECT(Data);
1326
77.4k
  std::string name;
1327
77.4k
  ParseBindVarOpt(&name);
1328
77.4k
  auto field = std::make_unique<DataSegmentModuleField>(loc, name);
1329
1330
77.4k
  if (PeekMatchLpar(TokenType::Memory)) {
1331
31.5k
    EXPECT(Lpar);
1332
31.5k
    EXPECT(Memory);
1333
31.5k
    CHECK_RESULT(ParseVar(&field->data_segment.memory_var));
1334
29.9k
    EXPECT(Rpar);
1335
528
    CHECK_RESULT(ParseOffsetExpr(&field->data_segment.offset));
1336
45.9k
  } else if (ParseVarOpt(&field->data_segment.memory_var, Var(0, loc))) {
1337
3.65k
    CHECK_RESULT(ParseOffsetExpr(&field->data_segment.offset));
1338
42.2k
  } else if (!ParseOffsetExprOpt(&field->data_segment.offset)) {
1339
41.1k
    if (!options_->features.bulk_memory_enabled()) {
1340
0
      Error(loc, "passive data segments are not allowed");
1341
0
      return Result::Error;
1342
0
    }
1343
1344
41.1k
    field->data_segment.kind = SegmentKind::Passive;
1345
41.1k
  }
1346
1347
43.4k
  ParseTextListOpt(&field->data_segment.data);
1348
43.4k
  EXPECT(Rpar);
1349
21.6k
  module->AppendField(std::move(field));
1350
21.6k
  return Result::Ok;
1351
43.4k
}
1352
1353
231k
Result WastParser::ParseElemModuleField(Module* module) {
1354
231k
  WABT_TRACE(ParseElemModuleField);
1355
231k
  EXPECT(Lpar);
1356
231k
  Location loc = GetLocation();
1357
231k
  EXPECT(Elem);
1358
1359
  // With MVP text format the name here was intended to refer to the table
1360
  // that the elem segment was part of, but we never did anything with this name
1361
  // since there was only one table anyway.
1362
  // With bulk-memory enabled this introduces a new name for the particular
1363
  // elem segment.
1364
231k
  std::string initial_name;
1365
231k
  bool has_name = ParseBindVarOpt(&initial_name);
1366
1367
231k
  std::string segment_name = initial_name;
1368
231k
  if (!options_->features.bulk_memory_enabled()) {
1369
0
    segment_name = "";
1370
0
  }
1371
231k
  auto field = std::make_unique<ElemSegmentModuleField>(loc, segment_name);
1372
231k
  if (options_->features.reference_types_enabled() &&
1373
231k
      Match(TokenType::Declare)) {
1374
194
    field->elem_segment.kind = SegmentKind::Declared;
1375
194
  }
1376
1377
  // Optional table specifier
1378
231k
  if (options_->features.bulk_memory_enabled()) {
1379
231k
    if (PeekMatchLpar(TokenType::Table)) {
1380
711
      EXPECT(Lpar);
1381
711
      EXPECT(Table);
1382
711
      CHECK_RESULT(ParseVar(&field->elem_segment.table_var));
1383
512
      EXPECT(Rpar);
1384
230k
    } else {
1385
230k
      ParseVarOpt(&field->elem_segment.table_var, Var(0, loc));
1386
230k
    }
1387
231k
  } else {
1388
0
    if (has_name) {
1389
0
      field->elem_segment.table_var = Var(initial_name, loc);
1390
0
    } else {
1391
0
      ParseVarOpt(&field->elem_segment.table_var, Var(0, loc));
1392
0
    }
1393
0
  }
1394
1395
  // Parse offset expression, if not declared/passive segment.
1396
230k
  if (options_->features.bulk_memory_enabled()) {
1397
230k
    if (field->elem_segment.kind != SegmentKind::Declared &&
1398
230k
        !ParseOffsetExprOpt(&field->elem_segment.offset)) {
1399
229k
      field->elem_segment.kind = SegmentKind::Passive;
1400
229k
    }
1401
230k
  } else {
1402
0
    CHECK_RESULT(ParseOffsetExpr(&field->elem_segment.offset));
1403
0
  }
1404
1405
230k
  if (ParseRefTypeOpt(&field->elem_segment.elem_type)) {
1406
1.72k
    ParseElemExprListOpt(&field->elem_segment.elem_exprs);
1407
229k
  } else {
1408
229k
    field->elem_segment.elem_type = Type::FuncRef;
1409
229k
    if (PeekMatch(TokenType::Func)) {
1410
263
      EXPECT(Func);
1411
263
    }
1412
229k
    ParseElemExprVarListOpt(&field->elem_segment.elem_exprs);
1413
229k
  }
1414
230k
  EXPECT(Rpar);
1415
215k
  module->AppendField(std::move(field));
1416
215k
  return Result::Ok;
1417
230k
}
1418
1419
80.8k
Result WastParser::ParseTagModuleField(Module* module) {
1420
80.8k
  WABT_TRACE(ParseTagModuleField);
1421
80.8k
  if (!options_->features.exceptions_enabled()) {
1422
80.8k
    Error(Consume().loc, "tag not allowed");
1423
80.8k
    return Result::Error;
1424
80.8k
  }
1425
0
  EXPECT(Lpar);
1426
0
  EXPECT(Tag);
1427
0
  Location loc = GetLocation();
1428
1429
0
  std::string name;
1430
0
  ParseBindVarOpt(&name);
1431
1432
0
  ModuleFieldList export_fields;
1433
0
  CHECK_RESULT(ParseInlineExports(&export_fields, ExternalKind::Tag));
1434
1435
0
  if (PeekMatchLpar(TokenType::Import)) {
1436
0
    CheckImportOrdering(module);
1437
0
    auto import = std::make_unique<TagImport>(name);
1438
0
    Tag& tag = import->tag;
1439
0
    CHECK_RESULT(ParseInlineImport(import.get()));
1440
0
    CHECK_RESULT(ParseTypeUseOpt(&tag.decl));
1441
0
    CHECK_RESULT(ParseUnboundFuncSignature(&tag.decl.sig));
1442
0
    CHECK_RESULT(ErrorIfLpar({"type", "param", "result"}));
1443
0
    auto field =
1444
0
        std::make_unique<ImportModuleField>(std::move(import), GetLocation());
1445
0
    module->AppendField(std::move(field));
1446
0
  } else {
1447
0
    auto field = std::make_unique<TagModuleField>(loc, name);
1448
0
    CHECK_RESULT(ParseTypeUseOpt(&field->tag.decl));
1449
0
    CHECK_RESULT(ParseUnboundFuncSignature(&field->tag.decl.sig));
1450
0
    module->AppendField(std::move(field));
1451
0
  }
1452
1453
0
  AppendInlineExportFields(module, &export_fields, module->tags.size() - 1);
1454
1455
0
  EXPECT(Rpar);
1456
0
  return Result::Ok;
1457
0
}
1458
1459
53.4k
Result WastParser::ParseExportModuleField(Module* module) {
1460
53.4k
  WABT_TRACE(ParseExportModuleField);
1461
53.4k
  EXPECT(Lpar);
1462
53.4k
  auto field = std::make_unique<ExportModuleField>(GetLocation());
1463
53.4k
  EXPECT(Export);
1464
53.4k
  CHECK_RESULT(ParseQuotedText(&field->export_.name));
1465
48.8k
  CHECK_RESULT(ParseExportDesc(&field->export_));
1466
15.0k
  EXPECT(Rpar);
1467
14.6k
  module->AppendField(std::move(field));
1468
14.6k
  return Result::Ok;
1469
15.0k
}
1470
1471
2.17M
Result WastParser::ParseFuncModuleField(Module* module) {
1472
2.17M
  WABT_TRACE(ParseFuncModuleField);
1473
2.17M
  EXPECT(Lpar);
1474
2.17M
  Location loc = GetLocation();
1475
2.17M
  EXPECT(Func);
1476
2.17M
  std::string name;
1477
2.17M
  ParseBindVarOpt(&name);
1478
1479
2.17M
  ModuleFieldList export_fields;
1480
2.17M
  CHECK_RESULT(ParseInlineExports(&export_fields, ExternalKind::Func));
1481
1482
2.16M
  if (PeekMatchLpar(TokenType::Import)) {
1483
46.9k
    CheckImportOrdering(module);
1484
46.9k
    auto import = std::make_unique<FuncImport>(name);
1485
46.9k
    Func& func = import->func;
1486
46.9k
    CHECK_RESULT(ParseInlineImport(import.get()));
1487
44.7k
    CHECK_RESULT(ParseTypeUseOpt(&func.decl));
1488
44.0k
    CHECK_RESULT(ParseFuncSignature(&func.decl.sig, &func.bindings));
1489
43.8k
    CHECK_RESULT(ErrorIfLpar({"type", "param", "result"}));
1490
43.4k
    auto field =
1491
43.4k
        std::make_unique<ImportModuleField>(std::move(import), GetLocation());
1492
43.4k
    module->AppendField(std::move(field));
1493
2.12M
  } else {
1494
2.12M
    auto field = std::make_unique<FuncModuleField>(loc, name);
1495
2.12M
    Func& func = field->func;
1496
2.12M
    func.loc = GetLocation();
1497
2.12M
    CHECK_RESULT(ParseTypeUseOpt(&func.decl));
1498
2.12M
    CHECK_RESULT(ParseFuncSignature(&func.decl.sig, &func.bindings));
1499
2.12M
    TypeVector local_types;
1500
2.12M
    CHECK_RESULT(ParseBoundValueTypeList(
1501
2.12M
        TokenType::Local, &local_types, &func.bindings,
1502
2.12M
        &func.decl.sig.param_type_names, func.GetNumParams()));
1503
2.11M
    func.local_types.Set(local_types);
1504
2.11M
    CHECK_RESULT(ParseTerminatingInstrList(&func.exprs));
1505
1.98M
    module->AppendField(std::move(field));
1506
1.98M
  }
1507
1508
2.03M
  AppendInlineExportFields(module, &export_fields, module->funcs.size() - 1);
1509
1510
2.03M
  EXPECT(Rpar);
1511
427k
  return Result::Ok;
1512
2.03M
}
1513
1514
50.1k
Result WastParser::ParseTypeModuleField(Module* module) {
1515
50.1k
  WABT_TRACE(ParseTypeModuleField);
1516
50.1k
  EXPECT(Lpar);
1517
50.1k
  auto field = std::make_unique<TypeModuleField>(GetLocation());
1518
50.1k
  EXPECT(Type);
1519
1520
50.1k
  std::string name;
1521
50.1k
  ParseBindVarOpt(&name);
1522
50.1k
  EXPECT(Lpar);
1523
45.8k
  Location loc = GetLocation();
1524
1525
45.8k
  if (Match(TokenType::Func)) {
1526
38.1k
    auto func_type = std::make_unique<FuncType>(name);
1527
38.1k
    BindingHash bindings;
1528
38.1k
    CHECK_RESULT(ParseFuncSignature(&func_type->sig, &bindings));
1529
37.4k
    CHECK_RESULT(ErrorIfLpar({"param", "result"}));
1530
37.1k
    field->type = std::move(func_type);
1531
37.1k
  } else if (Match(TokenType::Struct)) {
1532
0
    if (!options_->features.gc_enabled()) {
1533
0
      Error(loc, "struct not allowed");
1534
0
      return Result::Error;
1535
0
    }
1536
0
    auto struct_type = std::make_unique<StructType>(name);
1537
0
    CHECK_RESULT(ParseFieldList(&struct_type->fields));
1538
0
    field->type = std::move(struct_type);
1539
7.65k
  } else if (Match(TokenType::Array)) {
1540
0
    if (!options_->features.gc_enabled()) {
1541
0
      Error(loc, "array type not allowed");
1542
0
    }
1543
0
    auto array_type = std::make_unique<ArrayType>(name);
1544
0
    CHECK_RESULT(ParseField(&array_type->field));
1545
0
    field->type = std::move(array_type);
1546
7.65k
  } else {
1547
7.65k
    return ErrorExpected({"func", "struct", "array"});
1548
7.65k
  }
1549
1550
37.1k
  EXPECT(Rpar);
1551
27.3k
  EXPECT(Rpar);
1552
26.7k
  module->AppendField(std::move(field));
1553
26.7k
  return Result::Ok;
1554
27.3k
}
1555
1556
0
Result WastParser::ParseField(Field* field) {
1557
0
  WABT_TRACE(ParseField);
1558
0
  auto parse_mut_valuetype = [&]() -> Result {
1559
    // TODO: Share with ParseGlobalType?
1560
0
    if (MatchLpar(TokenType::Mut)) {
1561
0
      field->mutable_ = true;
1562
0
      Var type;
1563
0
      CHECK_RESULT(ParseValueType(&type));
1564
0
      field->type = Type(type.index());
1565
0
      EXPECT(Rpar);
1566
0
    } else {
1567
0
      field->mutable_ = false;
1568
0
      Var type;
1569
0
      CHECK_RESULT(ParseValueType(&type));
1570
0
      field->type = Type(type.index());
1571
0
    }
1572
0
    return Result::Ok;
1573
0
  };
1574
1575
0
  if (MatchLpar(TokenType::Field)) {
1576
0
    ParseBindVarOpt(&field->name);
1577
0
    CHECK_RESULT(parse_mut_valuetype());
1578
0
    EXPECT(Rpar);
1579
0
  } else {
1580
0
    CHECK_RESULT(parse_mut_valuetype());
1581
0
  }
1582
1583
0
  return Result::Ok;
1584
0
}
1585
1586
0
Result WastParser::ParseFieldList(std::vector<Field>* fields) {
1587
0
  WABT_TRACE(ParseFieldList);
1588
0
  while (PeekMatch(TokenType::ValueType) || PeekMatch(TokenType::Lpar)) {
1589
0
    Field field;
1590
0
    CHECK_RESULT(ParseField(&field));
1591
0
    fields->push_back(field);
1592
0
  }
1593
0
  return Result::Ok;
1594
0
}
1595
1596
68.8k
Result WastParser::ParseGlobalModuleField(Module* module) {
1597
68.8k
  WABT_TRACE(ParseGlobalModuleField);
1598
68.8k
  EXPECT(Lpar);
1599
68.8k
  Location loc = GetLocation();
1600
68.8k
  EXPECT(Global);
1601
68.8k
  std::string name;
1602
68.8k
  ParseBindVarOpt(&name);
1603
1604
68.8k
  ModuleFieldList export_fields;
1605
68.8k
  CHECK_RESULT(ParseInlineExports(&export_fields, ExternalKind::Global));
1606
1607
68.6k
  if (PeekMatchLpar(TokenType::Import)) {
1608
2.91k
    CheckImportOrdering(module);
1609
2.91k
    auto import = std::make_unique<GlobalImport>(name);
1610
2.91k
    CHECK_RESULT(ParseInlineImport(import.get()));
1611
402
    CHECK_RESULT(ParseGlobalType(&import->global));
1612
205
    auto field =
1613
205
        std::make_unique<ImportModuleField>(std::move(import), GetLocation());
1614
205
    module->AppendField(std::move(field));
1615
65.7k
  } else {
1616
65.7k
    auto field = std::make_unique<GlobalModuleField>(loc, name);
1617
65.7k
    CHECK_RESULT(ParseGlobalType(&field->global));
1618
56.0k
    CHECK_RESULT(ParseTerminatingInstrList(&field->global.init_expr));
1619
54.7k
    module->AppendField(std::move(field));
1620
54.7k
  }
1621
1622
54.9k
  AppendInlineExportFields(module, &export_fields, module->globals.size() - 1);
1623
1624
54.9k
  EXPECT(Rpar);
1625
51.9k
  return Result::Ok;
1626
54.9k
}
1627
1628
70.4k
Result WastParser::ParseImportModuleField(Module* module) {
1629
70.4k
  WABT_TRACE(ParseImportModuleField);
1630
70.4k
  EXPECT(Lpar);
1631
70.4k
  Location loc = GetLocation();
1632
70.4k
  CheckImportOrdering(module);
1633
70.4k
  EXPECT(Import);
1634
70.4k
  std::string module_name;
1635
70.4k
  std::string field_name;
1636
70.4k
  CHECK_RESULT(ParseQuotedText(&module_name));
1637
67.2k
  CHECK_RESULT(ParseQuotedText(&field_name));
1638
56.6k
  EXPECT(Lpar);
1639
1640
38.9k
  std::unique_ptr<ImportModuleField> field;
1641
38.9k
  std::string name;
1642
1643
38.9k
  switch (Peek()) {
1644
2.33k
    case TokenType::Func: {
1645
2.33k
      Consume();
1646
2.33k
      ParseBindVarOpt(&name);
1647
2.33k
      auto import = std::make_unique<FuncImport>(name);
1648
2.33k
      CHECK_RESULT(ParseTypeUseOpt(&import->func.decl));
1649
2.13k
      CHECK_RESULT(
1650
2.13k
          ParseFuncSignature(&import->func.decl.sig, &import->func.bindings));
1651
1.93k
      CHECK_RESULT(ErrorIfLpar({"param", "result"}));
1652
1.58k
      EXPECT(Rpar);
1653
647
      field = std::make_unique<ImportModuleField>(std::move(import), loc);
1654
647
      break;
1655
1.58k
    }
1656
1657
6.14k
    case TokenType::Table: {
1658
6.14k
      Consume();
1659
6.14k
      ParseBindVarOpt(&name);
1660
6.14k
      auto import = std::make_unique<TableImport>(name);
1661
6.14k
      CHECK_RESULT(ParseLimitsIndex(&import->table.elem_limits));
1662
6.14k
      CHECK_RESULT(ParseLimits(&import->table.elem_limits));
1663
5.45k
      CHECK_RESULT(ParseRefType(&import->table.elem_type));
1664
5.16k
      EXPECT(Rpar);
1665
495
      field = std::make_unique<ImportModuleField>(std::move(import), loc);
1666
495
      break;
1667
5.16k
    }
1668
1669
3.95k
    case TokenType::Memory: {
1670
3.95k
      Consume();
1671
3.95k
      ParseBindVarOpt(&name);
1672
3.95k
      auto import = std::make_unique<MemoryImport>(name);
1673
3.95k
      CHECK_RESULT(ParseLimitsIndex(&import->memory.page_limits));
1674
3.95k
      CHECK_RESULT(ParseLimits(&import->memory.page_limits));
1675
404
      EXPECT(Rpar);
1676
201
      field = std::make_unique<ImportModuleField>(std::move(import), loc);
1677
201
      break;
1678
404
    }
1679
1680
2.53k
    case TokenType::Global: {
1681
2.53k
      Consume();
1682
2.53k
      ParseBindVarOpt(&name);
1683
2.53k
      auto import = std::make_unique<GlobalImport>(name);
1684
2.53k
      CHECK_RESULT(ParseGlobalType(&import->global));
1685
675
      EXPECT(Rpar);
1686
481
      field = std::make_unique<ImportModuleField>(std::move(import), loc);
1687
481
      break;
1688
675
    }
1689
1690
22.3k
    case TokenType::Tag: {
1691
22.3k
      Consume();
1692
22.3k
      ParseBindVarOpt(&name);
1693
22.3k
      auto import = std::make_unique<TagImport>(name);
1694
22.3k
      CHECK_RESULT(ParseTypeUseOpt(&import->tag.decl));
1695
22.1k
      CHECK_RESULT(ParseUnboundFuncSignature(&import->tag.decl.sig));
1696
21.8k
      EXPECT(Rpar);
1697
16.6k
      field = std::make_unique<ImportModuleField>(std::move(import), loc);
1698
16.6k
      break;
1699
21.8k
    }
1700
1701
1.65k
    default:
1702
1.65k
      return ErrorExpected({"an external kind"});
1703
38.9k
  }
1704
1705
18.4k
  field->import->module_name = module_name;
1706
18.4k
  field->import->field_name = field_name;
1707
1708
18.4k
  module->AppendField(std::move(field));
1709
18.4k
  EXPECT(Rpar);
1710
1.30k
  return Result::Ok;
1711
18.4k
}
1712
1713
347k
Result WastParser::ParseMemoryModuleField(Module* module) {
1714
347k
  WABT_TRACE(ParseMemoryModuleField);
1715
347k
  EXPECT(Lpar);
1716
347k
  Location loc = GetLocation();
1717
347k
  EXPECT(Memory);
1718
347k
  std::string name;
1719
347k
  ParseBindVarOpt(&name);
1720
1721
347k
  ModuleFieldList export_fields;
1722
347k
  CHECK_RESULT(ParseInlineExports(&export_fields, ExternalKind::Memory));
1723
1724
347k
  if (PeekMatchLpar(TokenType::Import)) {
1725
3.05k
    CheckImportOrdering(module);
1726
3.05k
    auto import = std::make_unique<MemoryImport>(name);
1727
3.05k
    CHECK_RESULT(ParseInlineImport(import.get()));
1728
831
    CHECK_RESULT(ParseLimitsIndex(&import->memory.page_limits));
1729
831
    CHECK_RESULT(ParseLimits(&import->memory.page_limits));
1730
493
    auto field =
1731
493
        std::make_unique<ImportModuleField>(std::move(import), GetLocation());
1732
493
    module->AppendField(std::move(field));
1733
343k
  } else {
1734
343k
    auto field = std::make_unique<MemoryModuleField>(loc, name);
1735
343k
    CHECK_RESULT(ParseLimitsIndex(&field->memory.page_limits));
1736
343k
    if (MatchLpar(TokenType::Data)) {
1737
627
      auto data_segment_field = std::make_unique<DataSegmentModuleField>(loc);
1738
627
      DataSegment& data_segment = data_segment_field->data_segment;
1739
627
      data_segment.memory_var = Var(module->memories.size(), GetLocation());
1740
627
      data_segment.offset.push_back(std::make_unique<ConstExpr>(
1741
627
          field->memory.page_limits.is_64 ? Const::I64(0) : Const::I32(0)));
1742
627
      data_segment.offset.back().loc = loc;
1743
627
      ParseTextListOpt(&data_segment.data);
1744
627
      EXPECT(Rpar);
1745
1746
245
      uint32_t byte_size = WABT_ALIGN_UP_TO_PAGE(data_segment.data.size());
1747
245
      uint32_t page_size = WABT_BYTES_TO_PAGES(byte_size);
1748
245
      field->memory.page_limits.initial = page_size;
1749
245
      field->memory.page_limits.max = page_size;
1750
245
      field->memory.page_limits.has_max = true;
1751
1752
245
      module->AppendField(std::move(field));
1753
245
      module->AppendField(std::move(data_segment_field));
1754
343k
    } else {
1755
343k
      CHECK_RESULT(ParseLimits(&field->memory.page_limits));
1756
330k
      module->AppendField(std::move(field));
1757
330k
    }
1758
343k
  }
1759
1760
330k
  AppendInlineExportFields(module, &export_fields, module->memories.size() - 1);
1761
1762
330k
  EXPECT(Rpar);
1763
1.11k
  return Result::Ok;
1764
330k
}
1765
1766
1.26k
Result WastParser::ParseStartModuleField(Module* module) {
1767
1.26k
  WABT_TRACE(ParseStartModuleField);
1768
1.26k
  EXPECT(Lpar);
1769
1.26k
  Location loc = GetLocation();
1770
1.26k
  if (module->starts.size() > 0) {
1771
729
    Error(loc, "multiple start sections");
1772
729
    return Result::Error;
1773
729
  }
1774
534
  EXPECT(Start);
1775
534
  Var var;
1776
534
  CHECK_RESULT(ParseVar(&var));
1777
308
  EXPECT(Rpar);
1778
84
  module->AppendField(std::make_unique<StartModuleField>(var, loc));
1779
84
  return Result::Ok;
1780
308
}
1781
1782
432k
Result WastParser::ParseTableModuleField(Module* module) {
1783
432k
  WABT_TRACE(ParseTableModuleField);
1784
432k
  EXPECT(Lpar);
1785
432k
  Location loc = GetLocation();
1786
432k
  EXPECT(Table);
1787
432k
  std::string name;
1788
432k
  ParseBindVarOpt(&name);
1789
1790
432k
  ModuleFieldList export_fields;
1791
432k
  CHECK_RESULT(ParseInlineExports(&export_fields, ExternalKind::Table));
1792
1793
432k
  if (PeekMatchLpar(TokenType::Import)) {
1794
51.6k
    CheckImportOrdering(module);
1795
51.6k
    auto import = std::make_unique<TableImport>(name);
1796
51.6k
    CHECK_RESULT(ParseInlineImport(import.get()));
1797
49.1k
    CHECK_RESULT(ParseLimitsIndex(&import->table.elem_limits));
1798
49.1k
    CHECK_RESULT(ParseLimits(&import->table.elem_limits));
1799
48.8k
    CHECK_RESULT(ParseRefType(&import->table.elem_type));
1800
48.5k
    auto field =
1801
48.5k
        std::make_unique<ImportModuleField>(std::move(import), GetLocation());
1802
48.5k
    module->AppendField(std::move(field));
1803
380k
  } else {
1804
380k
    auto field = std::make_unique<TableModuleField>(loc, name);
1805
380k
    auto& table = field->table;
1806
380k
    CHECK_RESULT(ParseLimitsIndex(&table.elem_limits));
1807
380k
    if (PeekMatch(TokenType::ValueType)) {
1808
1.81k
      Type elem_type;
1809
1.81k
      CHECK_RESULT(ParseRefType(&elem_type));
1810
1811
1.81k
      EXPECT(Lpar);
1812
1.34k
      EXPECT(Elem);
1813
1814
1.06k
      auto elem_segment_field = std::make_unique<ElemSegmentModuleField>(loc);
1815
1.06k
      ElemSegment& elem_segment = elem_segment_field->elem_segment;
1816
1.06k
      elem_segment.table_var = Var(module->tables.size(), GetLocation());
1817
1.06k
      auto offset = table.elem_limits.is_64 ? Const::I64(0) : Const::I32(0);
1818
1.06k
      elem_segment.offset.push_back(std::make_unique<ConstExpr>(offset));
1819
1.06k
      elem_segment.offset.back().loc = loc;
1820
1.06k
      elem_segment.elem_type = elem_type;
1821
      // Syntax is either an optional list of var (legacy), or a non-empty list
1822
      // of elem expr.
1823
1.06k
      ExprList elem_expr;
1824
1.06k
      if (ParseElemExprOpt(&elem_expr)) {
1825
196
        elem_segment.elem_exprs.push_back(std::move(elem_expr));
1826
        // Parse the rest.
1827
196
        ParseElemExprListOpt(&elem_segment.elem_exprs);
1828
864
      } else {
1829
864
        ParseElemExprVarListOpt(&elem_segment.elem_exprs);
1830
864
      }
1831
1.06k
      EXPECT(Rpar);
1832
1833
374
      table.elem_limits.initial = elem_segment.elem_exprs.size();
1834
374
      table.elem_limits.max = elem_segment.elem_exprs.size();
1835
374
      table.elem_limits.has_max = true;
1836
374
      table.elem_type = elem_type;
1837
374
      module->AppendField(std::move(field));
1838
374
      module->AppendField(std::move(elem_segment_field));
1839
378k
    } else {
1840
378k
      CHECK_RESULT(ParseLimits(&table.elem_limits));
1841
359k
      CHECK_RESULT(ParseRefType(&table.elem_type));
1842
344k
      module->AppendField(std::move(field));
1843
344k
    }
1844
380k
  }
1845
1846
392k
  AppendInlineExportFields(module, &export_fields, module->tables.size() - 1);
1847
1848
392k
  EXPECT(Rpar);
1849
7.07k
  return Result::Ok;
1850
392k
}
1851
1852
48.8k
Result WastParser::ParseExportDesc(Export* export_) {
1853
48.8k
  WABT_TRACE(ParseExportDesc);
1854
48.8k
  EXPECT(Lpar);
1855
19.8k
  switch (Peek()) {
1856
1.46k
    case TokenType::Func:   export_->kind = ExternalKind::Func; break;
1857
9.08k
    case TokenType::Table:  export_->kind = ExternalKind::Table; break;
1858
805
    case TokenType::Memory: export_->kind = ExternalKind::Memory; break;
1859
3.63k
    case TokenType::Global: export_->kind = ExternalKind::Global; break;
1860
1.42k
    case TokenType::Tag:    export_->kind = ExternalKind::Tag; break;
1861
3.38k
    default:
1862
3.38k
      return ErrorExpected({"an external kind"});
1863
19.8k
  }
1864
16.4k
  Consume();
1865
16.4k
  CHECK_RESULT(ParseVar(&export_->var));
1866
15.6k
  EXPECT(Rpar);
1867
15.0k
  return Result::Ok;
1868
15.6k
}
1869
1870
Result WastParser::ParseInlineExports(ModuleFieldList* fields,
1871
3.01M
                                      ExternalKind kind) {
1872
3.01M
  WABT_TRACE(ParseInlineExports);
1873
3.09M
  while (PeekMatchLpar(TokenType::Export)) {
1874
75.4k
    EXPECT(Lpar);
1875
75.4k
    auto field = std::make_unique<ExportModuleField>(GetLocation());
1876
75.4k
    field->export_.kind = kind;
1877
75.4k
    EXPECT(Export);
1878
75.4k
    CHECK_RESULT(ParseQuotedText(&field->export_.name));
1879
74.2k
    EXPECT(Rpar);
1880
73.0k
    fields->push_back(std::move(field));
1881
73.0k
  }
1882
3.01M
  return Result::Ok;
1883
3.01M
}
1884
1885
104k
Result WastParser::ParseInlineImport(Import* import) {
1886
104k
  WABT_TRACE(ParseInlineImport);
1887
104k
  EXPECT(Lpar);
1888
104k
  EXPECT(Import);
1889
104k
  CHECK_RESULT(ParseQuotedText(&import->module_name));
1890
101k
  CHECK_RESULT(ParseQuotedText(&import->field_name));
1891
97.9k
  EXPECT(Rpar);
1892
95.0k
  return Result::Ok;
1893
97.9k
}
1894
1895
2.42M
Result WastParser::ParseTypeUseOpt(FuncDeclaration* decl) {
1896
2.42M
  WABT_TRACE(ParseTypeUseOpt);
1897
2.42M
  if (MatchLpar(TokenType::Type)) {
1898
24.4k
    decl->has_func_type = true;
1899
24.4k
    CHECK_RESULT(ParseVar(&decl->type_var));
1900
15.9k
    EXPECT(Rpar);
1901
2.40M
  } else {
1902
2.40M
    decl->has_func_type = false;
1903
2.40M
  }
1904
2.41M
  return Result::Ok;
1905
2.42M
}
1906
1907
Result WastParser::ParseFuncSignature(FuncSignature* sig,
1908
2.20M
                                      BindingHash* param_bindings) {
1909
2.20M
  WABT_TRACE(ParseFuncSignature);
1910
2.20M
  CHECK_RESULT(ParseBoundValueTypeList(TokenType::Param, &sig->param_types,
1911
2.20M
                                       param_bindings, &sig->param_type_names));
1912
2.20M
  CHECK_RESULT(ParseResultList(&sig->result_types, &sig->result_type_names));
1913
2.20M
  return Result::Ok;
1914
2.20M
}
1915
1916
246k
Result WastParser::ParseUnboundFuncSignature(FuncSignature* sig) {
1917
246k
  WABT_TRACE(ParseUnboundFuncSignature);
1918
246k
  CHECK_RESULT(ParseUnboundValueTypeList(TokenType::Param, &sig->param_types,
1919
246k
                                         &sig->param_type_names));
1920
244k
  CHECK_RESULT(ParseResultList(&sig->result_types, &sig->result_type_names));
1921
244k
  return Result::Ok;
1922
244k
}
1923
1924
Result WastParser::ParseBoundValueTypeList(
1925
    TokenType token,
1926
    TypeVector* types,
1927
    BindingHash* bindings,
1928
    std::unordered_map<uint32_t, std::string>* type_names,
1929
4.32M
    Index binding_index_offset) {
1930
4.32M
  WABT_TRACE(ParseBoundValueTypeList);
1931
4.40M
  while (MatchLpar(token)) {
1932
78.2k
    if (PeekMatch(TokenType::Var)) {
1933
72.7k
      std::string name;
1934
72.7k
      Var type;
1935
72.7k
      Location loc = GetLocation();
1936
72.7k
      ParseBindVarOpt(&name);
1937
72.7k
      CHECK_RESULT(ParseValueType(&type));
1938
70.9k
      bindings->emplace(name,
1939
70.9k
                        Binding(loc, binding_index_offset + types->size()));
1940
70.9k
      if (type.is_index()) {
1941
70.9k
        types->push_back(Type(type.index()));
1942
70.9k
      } else {
1943
0
        assert(type.is_name());
1944
0
        assert(options_->features.function_references_enabled());
1945
0
        type_names->emplace(binding_index_offset + types->size(), type.name());
1946
0
        types->push_back(Type(Type::Reference, kInvalidIndex));
1947
0
      }
1948
70.9k
    } else {
1949
5.42k
      CHECK_RESULT(ParseValueTypeList(types, type_names));
1950
5.42k
    }
1951
76.4k
    EXPECT(Rpar);
1952
76.4k
  }
1953
4.32M
  return Result::Ok;
1954
4.32M
}
1955
1956
Result WastParser::ParseUnboundValueTypeList(
1957
    TokenType token,
1958
    TypeVector* types,
1959
2.69M
    std::unordered_map<uint32_t, std::string>* type_names) {
1960
2.69M
  WABT_TRACE(ParseUnboundValueTypeList);
1961
2.70M
  while (MatchLpar(token)) {
1962
10.7k
    CHECK_RESULT(ParseValueTypeList(types, type_names));
1963
10.7k
    EXPECT(Rpar);
1964
10.7k
  }
1965
2.69M
  return Result::Ok;
1966
2.69M
}
1967
1968
Result WastParser::ParseResultList(
1969
    TypeVector* result_types,
1970
2.44M
    std::unordered_map<uint32_t, std::string>* type_names) {
1971
2.44M
  WABT_TRACE(ParseResultList);
1972
2.44M
  return ParseUnboundValueTypeList(TokenType::Result, result_types, type_names);
1973
2.44M
}
1974
1975
2.33M
Result WastParser::ParseInstrList(ExprList* exprs) {
1976
2.33M
  WABT_TRACE(ParseInstrList);
1977
2.33M
  ExprList new_exprs;
1978
2.82M
  while (true) {
1979
2.82M
    auto pair = PeekPair();
1980
2.82M
    if (IsInstr(pair)) {
1981
558k
      if (Succeeded(ParseInstr(&new_exprs))) {
1982
206k
        exprs->splice(exprs->end(), new_exprs);
1983
352k
      } else {
1984
352k
        CHECK_RESULT(Synchronize(IsInstr));
1985
352k
      }
1986
2.26M
    } else if (IsLparAnn(pair)) {
1987
2.17k
      if (Succeeded(ParseCodeMetadataAnnotation(&new_exprs))) {
1988
1.20k
        exprs->splice(exprs->end(), new_exprs);
1989
1.20k
      } else {
1990
971
        CHECK_RESULT(Synchronize(IsLparAnn));
1991
971
      }
1992
2.26M
    } else {
1993
2.26M
      break;
1994
2.26M
    }
1995
2.82M
  }
1996
2.26M
  return Result::Ok;
1997
2.33M
}
1998
1999
2.20M
Result WastParser::ParseTerminatingInstrList(ExprList* exprs) {
2000
2.20M
  WABT_TRACE(ParseTerminatingInstrList);
2001
2.20M
  Result result = ParseInstrList(exprs);
2002
  // An InstrList often has no further Lpar following it, because it would have
2003
  // gobbled it up. So if there is a following Lpar it is an error. If we
2004
  // handle it here we can produce a nicer error message.
2005
2.20M
  CHECK_RESULT(ErrorIfLpar({"an instr"}));
2006
2.09M
  return result;
2007
2.20M
}
2008
2009
558k
Result WastParser::ParseInstr(ExprList* exprs) {
2010
558k
  WABT_TRACE(ParseInstr);
2011
558k
  if (IsPlainInstr(Peek())) {
2012
242k
    std::unique_ptr<Expr> expr;
2013
242k
    CHECK_RESULT(ParsePlainInstr(&expr));
2014
178k
    exprs->push_back(std::move(expr));
2015
178k
    return Result::Ok;
2016
315k
  } else if (IsBlockInstr(Peek())) {
2017
46.8k
    std::unique_ptr<Expr> expr;
2018
46.8k
    CHECK_RESULT(ParseBlockInstr(&expr));
2019
5.45k
    exprs->push_back(std::move(expr));
2020
5.45k
    return Result::Ok;
2021
268k
  } else if (PeekMatchExpr()) {
2022
268k
    return ParseExpr(exprs);
2023
268k
  } else {
2024
0
    assert(!"ParseInstr should only be called when IsInstr() is true");
2025
0
    return Result::Error;
2026
0
  }
2027
558k
}
2028
2029
2.17k
Result WastParser::ParseCodeMetadataAnnotation(ExprList* exprs) {
2030
2.17k
  WABT_TRACE(ParseCodeMetadataAnnotation);
2031
2.17k
  Token tk = Consume();
2032
2.17k
  std::string_view name = tk.text();
2033
2.17k
  name.remove_prefix(sizeof("metadata.code.") - 1);
2034
2.17k
  std::string data_text;
2035
2.17k
  CHECK_RESULT(ParseQuotedText(&data_text, false));
2036
1.49k
  std::vector<uint8_t> data(data_text.begin(), data_text.end());
2037
1.49k
  exprs->push_back(std::make_unique<CodeMetadataExpr>(name, std::move(data)));
2038
1.49k
  EXPECT(Rpar);
2039
1.20k
  return Result::Ok;
2040
1.49k
}
2041
2042
template <typename T>
2043
Result WastParser::ParsePlainInstrVar(Location loc,
2044
28.7k
                                      std::unique_ptr<Expr>* out_expr) {
2045
28.7k
  Var var;
2046
28.7k
  CHECK_RESULT(ParseVar(&var));
2047
19.9k
  out_expr->reset(new T(var, loc));
2048
19.9k
  return Result::Ok;
2049
28.7k
}
wabt::Result wabt::WastParser::ParsePlainInstrVar<wabt::VarExpr<(wabt::ExprType)9> >(wabt::Location, std::__1::unique_ptr<wabt::Expr, std::__1::default_delete<wabt::Expr> >*)
Line
Count
Source
2044
6.58k
                                      std::unique_ptr<Expr>* out_expr) {
2045
6.58k
  Var var;
2046
6.58k
  CHECK_RESULT(ParseVar(&var));
2047
4.46k
  out_expr->reset(new T(var, loc));
2048
4.46k
  return Result::Ok;
2049
6.58k
}
wabt::Result wabt::WastParser::ParsePlainInstrVar<wabt::VarExpr<(wabt::ExprType)10> >(wabt::Location, std::__1::unique_ptr<wabt::Expr, std::__1::default_delete<wabt::Expr> >*)
Line
Count
Source
2044
783
                                      std::unique_ptr<Expr>* out_expr) {
2045
783
  Var var;
2046
783
  CHECK_RESULT(ParseVar(&var));
2047
422
  out_expr->reset(new T(var, loc));
2048
422
  return Result::Ok;
2049
783
}
wabt::Result wabt::WastParser::ParsePlainInstrVar<wabt::VarExpr<(wabt::ExprType)12> >(wabt::Location, std::__1::unique_ptr<wabt::Expr, std::__1::default_delete<wabt::Expr> >*)
Line
Count
Source
2044
2.71k
                                      std::unique_ptr<Expr>* out_expr) {
2045
2.71k
  Var var;
2046
2.71k
  CHECK_RESULT(ParseVar(&var));
2047
2.14k
  out_expr->reset(new T(var, loc));
2048
2.14k
  return Result::Ok;
2049
2.71k
}
wabt::Result wabt::WastParser::ParsePlainInstrVar<wabt::VarExpr<(wabt::ExprType)40> >(wabt::Location, std::__1::unique_ptr<wabt::Expr, std::__1::default_delete<wabt::Expr> >*)
Line
Count
Source
2044
1.28k
                                      std::unique_ptr<Expr>* out_expr) {
2045
1.28k
  Var var;
2046
1.28k
  CHECK_RESULT(ParseVar(&var));
2047
912
  out_expr->reset(new T(var, loc));
2048
912
  return Result::Ok;
2049
1.28k
}
wabt::Result wabt::WastParser::ParsePlainInstrVar<wabt::VarExpr<(wabt::ExprType)24> >(wabt::Location, std::__1::unique_ptr<wabt::Expr, std::__1::default_delete<wabt::Expr> >*)
Line
Count
Source
2044
1.43k
                                      std::unique_ptr<Expr>* out_expr) {
2045
1.43k
  Var var;
2046
1.43k
  CHECK_RESULT(ParseVar(&var));
2047
1.10k
  out_expr->reset(new T(var, loc));
2048
1.10k
  return Result::Ok;
2049
1.43k
}
wabt::Result wabt::WastParser::ParsePlainInstrVar<wabt::VarExpr<(wabt::ExprType)25> >(wabt::Location, std::__1::unique_ptr<wabt::Expr, std::__1::default_delete<wabt::Expr> >*)
Line
Count
Source
2044
1.82k
                                      std::unique_ptr<Expr>* out_expr) {
2045
1.82k
  Var var;
2046
1.82k
  CHECK_RESULT(ParseVar(&var));
2047
1.47k
  out_expr->reset(new T(var, loc));
2048
1.47k
  return Result::Ok;
2049
1.82k
}
wabt::Result wabt::WastParser::ParsePlainInstrVar<wabt::VarExpr<(wabt::ExprType)26> >(wabt::Location, std::__1::unique_ptr<wabt::Expr, std::__1::default_delete<wabt::Expr> >*)
Line
Count
Source
2044
3.62k
                                      std::unique_ptr<Expr>* out_expr) {
2045
3.62k
  Var var;
2046
3.62k
  CHECK_RESULT(ParseVar(&var));
2047
2.17k
  out_expr->reset(new T(var, loc));
2048
2.17k
  return Result::Ok;
2049
3.62k
}
wabt::Result wabt::WastParser::ParsePlainInstrVar<wabt::VarExpr<(wabt::ExprType)20> >(wabt::Location, std::__1::unique_ptr<wabt::Expr, std::__1::default_delete<wabt::Expr> >*)
Line
Count
Source
2044
1.52k
                                      std::unique_ptr<Expr>* out_expr) {
2045
1.52k
  Var var;
2046
1.52k
  CHECK_RESULT(ParseVar(&var));
2047
1.09k
  out_expr->reset(new T(var, loc));
2048
1.09k
  return Result::Ok;
2049
1.52k
}
wabt::Result wabt::WastParser::ParsePlainInstrVar<wabt::VarExpr<(wabt::ExprType)21> >(wabt::Location, std::__1::unique_ptr<wabt::Expr, std::__1::default_delete<wabt::Expr> >*)
Line
Count
Source
2044
1.41k
                                      std::unique_ptr<Expr>* out_expr) {
2045
1.41k
  Var var;
2046
1.41k
  CHECK_RESULT(ParseVar(&var));
2047
1.02k
  out_expr->reset(new T(var, loc));
2048
1.02k
  return Result::Ok;
2049
1.41k
}
wabt::Result wabt::WastParser::ParsePlainInstrVar<wabt::VarExpr<(wabt::ExprType)29> >(wabt::Location, std::__1::unique_ptr<wabt::Expr, std::__1::default_delete<wabt::Expr> >*)
Line
Count
Source
2044
1.58k
                                      std::unique_ptr<Expr>* out_expr) {
2045
1.58k
  Var var;
2046
1.58k
  CHECK_RESULT(ParseVar(&var));
2047
994
  out_expr->reset(new T(var, loc));
2048
994
  return Result::Ok;
2049
1.58k
}
wabt::Result wabt::WastParser::ParsePlainInstrVar<wabt::VarExpr<(wabt::ExprType)51> >(wabt::Location, std::__1::unique_ptr<wabt::Expr, std::__1::default_delete<wabt::Expr> >*)
Line
Count
Source
2044
1.40k
                                      std::unique_ptr<Expr>* out_expr) {
2045
1.40k
  Var var;
2046
1.40k
  CHECK_RESULT(ParseVar(&var));
2047
1.04k
  out_expr->reset(new T(var, loc));
2048
1.04k
  return Result::Ok;
2049
1.40k
}
wabt::Result wabt::WastParser::ParsePlainInstrVar<wabt::VarExpr<(wabt::ExprType)36> >(wabt::Location, std::__1::unique_ptr<wabt::Expr, std::__1::default_delete<wabt::Expr> >*)
Line
Count
Source
2044
1.52k
                                      std::unique_ptr<Expr>* out_expr) {
2045
1.52k
  Var var;
2046
1.52k
  CHECK_RESULT(ParseVar(&var));
2047
1.04k
  out_expr->reset(new T(var, loc));
2048
1.04k
  return Result::Ok;
2049
1.52k
}
wabt::Result wabt::WastParser::ParsePlainInstrVar<wabt::VarExpr<(wabt::ExprType)59> >(wabt::Location, std::__1::unique_ptr<wabt::Expr, std::__1::default_delete<wabt::Expr> >*)
Line
Count
Source
2044
2.10k
                                      std::unique_ptr<Expr>* out_expr) {
2045
2.10k
  Var var;
2046
2.10k
  CHECK_RESULT(ParseVar(&var));
2047
1.58k
  out_expr->reset(new T(var, loc));
2048
1.58k
  return Result::Ok;
2049
2.10k
}
wabt::Result wabt::WastParser::ParsePlainInstrVar<wabt::VarExpr<(wabt::ExprType)38> >(wabt::Location, std::__1::unique_ptr<wabt::Expr, std::__1::default_delete<wabt::Expr> >*)
Line
Count
Source
2044
925
                                      std::unique_ptr<Expr>* out_expr) {
2045
925
  Var var;
2046
925
  CHECK_RESULT(ParseVar(&var));
2047
474
  out_expr->reset(new T(var, loc));
2048
474
  return Result::Ok;
2049
925
}
2050
2051
template <typename T>
2052
Result WastParser::ParseMemoryInstrVar(Location loc,
2053
2.22k
                                       std::unique_ptr<Expr>* out_expr) {
2054
2.22k
  Var memidx;
2055
2.22k
  Var var;
2056
2.22k
  if (PeekMatchLpar(TokenType::Memory)) {
2057
194
    if (!options_->features.multi_memory_enabled()) {
2058
194
      Error(loc, "Specifying memory variable is not allowed");
2059
194
      return Result::Error;
2060
194
    }
2061
0
    CHECK_RESULT(ParseMemidx(loc, &memidx));
2062
0
    CHECK_RESULT(ParseVar(&var));
2063
0
    out_expr->reset(new T(var, memidx, loc));
2064
2.03k
  } else {
2065
2.03k
    CHECK_RESULT(ParseVar(&memidx));
2066
1.62k
    if (ParseVarOpt(&var, Var(0, loc))) {
2067
414
      if (!options_->features.multi_memory_enabled()) {
2068
414
        Error(loc, "Specifiying memory variable is not allowed");
2069
414
        return Result::Error;
2070
414
      }
2071
0
      out_expr->reset(new T(var, memidx, loc));
2072
1.20k
    } else {
2073
1.20k
      out_expr->reset(new T(memidx, var, loc));
2074
1.20k
    }
2075
1.62k
  }
2076
1.20k
  return Result::Ok;
2077
2.22k
}
2078
2079
template <typename T>
2080
Result WastParser::ParseLoadStoreInstr(Location loc,
2081
                                       Token token,
2082
68.0k
                                       std::unique_ptr<Expr>* out_expr) {
2083
68.0k
  Opcode opcode = token.opcode();
2084
68.0k
  Var memidx;
2085
68.0k
  Address offset;
2086
68.0k
  Address align;
2087
68.0k
  CHECK_RESULT(ParseMemidx(loc, &memidx));
2088
46.1k
  ParseOffsetOpt(&offset);
2089
46.1k
  ParseAlignOpt(&align);
2090
46.1k
  out_expr->reset(new T(opcode, memidx, align, offset, loc));
2091
46.1k
  return Result::Ok;
2092
68.0k
}
wabt::Result wabt::WastParser::ParseLoadStoreInstr<wabt::LoadStoreExpr<(wabt::ExprType)23> >(wabt::Location, wabt::Token, std::__1::unique_ptr<wabt::Expr, std::__1::default_delete<wabt::Expr> >*)
Line
Count
Source
2082
23.0k
                                       std::unique_ptr<Expr>* out_expr) {
2083
23.0k
  Opcode opcode = token.opcode();
2084
23.0k
  Var memidx;
2085
23.0k
  Address offset;
2086
23.0k
  Address align;
2087
23.0k
  CHECK_RESULT(ParseMemidx(loc, &memidx));
2088
22.6k
  ParseOffsetOpt(&offset);
2089
22.6k
  ParseAlignOpt(&align);
2090
22.6k
  out_expr->reset(new T(opcode, memidx, align, offset, loc));
2091
22.6k
  return Result::Ok;
2092
23.0k
}
wabt::Result wabt::WastParser::ParseLoadStoreInstr<wabt::LoadStoreExpr<(wabt::ExprType)49> >(wabt::Location, wabt::Token, std::__1::unique_ptr<wabt::Expr, std::__1::default_delete<wabt::Expr> >*)
Line
Count
Source
2082
6.63k
                                       std::unique_ptr<Expr>* out_expr) {
2083
6.63k
  Opcode opcode = token.opcode();
2084
6.63k
  Var memidx;
2085
6.63k
  Address offset;
2086
6.63k
  Address align;
2087
6.63k
  CHECK_RESULT(ParseMemidx(loc, &memidx));
2088
6.41k
  ParseOffsetOpt(&offset);
2089
6.41k
  ParseAlignOpt(&align);
2090
6.41k
  out_expr->reset(new T(opcode, memidx, align, offset, loc));
2091
6.41k
  return Result::Ok;
2092
6.63k
}
wabt::Result wabt::WastParser::ParseLoadStoreInstr<wabt::LoadStoreExpr<(wabt::ExprType)4> >(wabt::Location, wabt::Token, std::__1::unique_ptr<wabt::Expr, std::__1::default_delete<wabt::Expr> >*)
Line
Count
Source
2082
799
                                       std::unique_ptr<Expr>* out_expr) {
2083
799
  Opcode opcode = token.opcode();
2084
799
  Var memidx;
2085
799
  Address offset;
2086
799
  Address align;
2087
799
  CHECK_RESULT(ParseMemidx(loc, &memidx));
2088
351
  ParseOffsetOpt(&offset);
2089
351
  ParseAlignOpt(&align);
2090
351
  out_expr->reset(new T(opcode, memidx, align, offset, loc));
2091
351
  return Result::Ok;
2092
799
}
wabt::Result wabt::WastParser::ParseLoadStoreInstr<wabt::LoadStoreExpr<(wabt::ExprType)6> >(wabt::Location, wabt::Token, std::__1::unique_ptr<wabt::Expr, std::__1::default_delete<wabt::Expr> >*)
Line
Count
Source
2082
744
                                       std::unique_ptr<Expr>* out_expr) {
2083
744
  Opcode opcode = token.opcode();
2084
744
  Var memidx;
2085
744
  Address offset;
2086
744
  Address align;
2087
744
  CHECK_RESULT(ParseMemidx(loc, &memidx));
2088
366
  ParseOffsetOpt(&offset);
2089
366
  ParseAlignOpt(&align);
2090
366
  out_expr->reset(new T(opcode, memidx, align, offset, loc));
2091
366
  return Result::Ok;
2092
744
}
wabt::Result wabt::WastParser::ParseLoadStoreInstr<wabt::LoadStoreExpr<(wabt::ExprType)0> >(wabt::Location, wabt::Token, std::__1::unique_ptr<wabt::Expr, std::__1::default_delete<wabt::Expr> >*)
Line
Count
Source
2082
2.02k
                                       std::unique_ptr<Expr>* out_expr) {
2083
2.02k
  Opcode opcode = token.opcode();
2084
2.02k
  Var memidx;
2085
2.02k
  Address offset;
2086
2.02k
  Address align;
2087
2.02k
  CHECK_RESULT(ParseMemidx(loc, &memidx));
2088
1.72k
  ParseOffsetOpt(&offset);
2089
1.72k
  ParseAlignOpt(&align);
2090
1.72k
  out_expr->reset(new T(opcode, memidx, align, offset, loc));
2091
1.72k
  return Result::Ok;
2092
2.02k
}
wabt::Result wabt::WastParser::ParseLoadStoreInstr<wabt::LoadStoreExpr<(wabt::ExprType)3> >(wabt::Location, wabt::Token, std::__1::unique_ptr<wabt::Expr, std::__1::default_delete<wabt::Expr> >*)
Line
Count
Source
2082
21.2k
                                       std::unique_ptr<Expr>* out_expr) {
2083
21.2k
  Opcode opcode = token.opcode();
2084
21.2k
  Var memidx;
2085
21.2k
  Address offset;
2086
21.2k
  Address align;
2087
21.2k
  CHECK_RESULT(ParseMemidx(loc, &memidx));
2088
1.88k
  ParseOffsetOpt(&offset);
2089
1.88k
  ParseAlignOpt(&align);
2090
1.88k
  out_expr->reset(new T(opcode, memidx, align, offset, loc));
2091
1.88k
  return Result::Ok;
2092
21.2k
}
wabt::Result wabt::WastParser::ParseLoadStoreInstr<wabt::LoadStoreExpr<(wabt::ExprType)1> >(wabt::Location, wabt::Token, std::__1::unique_ptr<wabt::Expr, std::__1::default_delete<wabt::Expr> >*)
Line
Count
Source
2082
10.9k
                                       std::unique_ptr<Expr>* out_expr) {
2083
10.9k
  Opcode opcode = token.opcode();
2084
10.9k
  Var memidx;
2085
10.9k
  Address offset;
2086
10.9k
  Address align;
2087
10.9k
  CHECK_RESULT(ParseMemidx(loc, &memidx));
2088
10.3k
  ParseOffsetOpt(&offset);
2089
10.3k
  ParseAlignOpt(&align);
2090
10.3k
  out_expr->reset(new T(opcode, memidx, align, offset, loc));
2091
10.3k
  return Result::Ok;
2092
10.9k
}
wabt::Result wabt::WastParser::ParseLoadStoreInstr<wabt::LoadStoreExpr<(wabt::ExprType)2> >(wabt::Location, wabt::Token, std::__1::unique_ptr<wabt::Expr, std::__1::default_delete<wabt::Expr> >*)
Line
Count
Source
2082
2.65k
                                       std::unique_ptr<Expr>* out_expr) {
2083
2.65k
  Opcode opcode = token.opcode();
2084
2.65k
  Var memidx;
2085
2.65k
  Address offset;
2086
2.65k
  Address align;
2087
2.65k
  CHECK_RESULT(ParseMemidx(loc, &memidx));
2088
2.39k
  ParseOffsetOpt(&offset);
2089
2.39k
  ParseAlignOpt(&align);
2090
2.39k
  out_expr->reset(new T(opcode, memidx, align, offset, loc));
2091
2.39k
  return Result::Ok;
2092
2.65k
}
2093
2094
template <typename T>
2095
Result WastParser::ParseSIMDLoadStoreInstr(Location loc,
2096
                                           Token token,
2097
11.2k
                                           std::unique_ptr<Expr>* out_expr) {
2098
11.2k
  ErrorUnlessOpcodeEnabled(token);
2099
2100
11.2k
  Var memidx(0, loc);
2101
2102
11.2k
  if (options_->features.multi_memory_enabled()) {
2103
    // We have to be a little careful when reading the memeory index.
2104
    // If there is just a single integer folloing the instruction that
2105
    // represents the lane index, so we check for either a pair of intergers
2106
    // or an integers followed by offset= or align=.
2107
0
    bool try_read_mem_index = true;
2108
0
    if (PeekMatch(TokenType::Nat)) {
2109
      // The next token could be a memory index or a lane index
2110
0
      if (!PeekMatch(TokenType::OffsetEqNat, 1) &&
2111
0
          !PeekMatch(TokenType::AlignEqNat, 1) &&
2112
0
          !PeekMatch(TokenType::Nat, 1)) {
2113
0
        try_read_mem_index = false;
2114
0
      }
2115
0
    }
2116
0
    if (try_read_mem_index) {
2117
0
      CHECK_RESULT(ParseMemidx(loc, &memidx));
2118
0
    }
2119
0
  }
2120
11.2k
  Address offset;
2121
11.2k
  Address align;
2122
11.2k
  ParseOffsetOpt(&offset);
2123
11.2k
  ParseAlignOpt(&align);
2124
2125
11.2k
  uint64_t lane_idx = 0;
2126
11.2k
  Result result = ParseSimdLane(loc, &lane_idx);
2127
2128
11.2k
  if (Failed(result)) {
2129
7.37k
    return Result::Error;
2130
7.37k
  }
2131
2132
3.87k
  out_expr->reset(new T(token.opcode(), memidx, align, offset, lane_idx, loc));
2133
3.87k
  return Result::Ok;
2134
11.2k
}
wabt::Result wabt::WastParser::ParseSIMDLoadStoreInstr<wabt::SimdLoadLaneExpr>(wabt::Location, wabt::Token, std::__1::unique_ptr<wabt::Expr, std::__1::default_delete<wabt::Expr> >*)
Line
Count
Source
2097
10.0k
                                           std::unique_ptr<Expr>* out_expr) {
2098
10.0k
  ErrorUnlessOpcodeEnabled(token);
2099
2100
10.0k
  Var memidx(0, loc);
2101
2102
10.0k
  if (options_->features.multi_memory_enabled()) {
2103
    // We have to be a little careful when reading the memeory index.
2104
    // If there is just a single integer folloing the instruction that
2105
    // represents the lane index, so we check for either a pair of intergers
2106
    // or an integers followed by offset= or align=.
2107
0
    bool try_read_mem_index = true;
2108
0
    if (PeekMatch(TokenType::Nat)) {
2109
      // The next token could be a memory index or a lane index
2110
0
      if (!PeekMatch(TokenType::OffsetEqNat, 1) &&
2111
0
          !PeekMatch(TokenType::AlignEqNat, 1) &&
2112
0
          !PeekMatch(TokenType::Nat, 1)) {
2113
0
        try_read_mem_index = false;
2114
0
      }
2115
0
    }
2116
0
    if (try_read_mem_index) {
2117
0
      CHECK_RESULT(ParseMemidx(loc, &memidx));
2118
0
    }
2119
0
  }
2120
10.0k
  Address offset;
2121
10.0k
  Address align;
2122
10.0k
  ParseOffsetOpt(&offset);
2123
10.0k
  ParseAlignOpt(&align);
2124
2125
10.0k
  uint64_t lane_idx = 0;
2126
10.0k
  Result result = ParseSimdLane(loc, &lane_idx);
2127
2128
10.0k
  if (Failed(result)) {
2129
6.45k
    return Result::Error;
2130
6.45k
  }
2131
2132
3.56k
  out_expr->reset(new T(token.opcode(), memidx, align, offset, lane_idx, loc));
2133
3.56k
  return Result::Ok;
2134
10.0k
}
wabt::Result wabt::WastParser::ParseSIMDLoadStoreInstr<wabt::SimdStoreLaneExpr>(wabt::Location, wabt::Token, std::__1::unique_ptr<wabt::Expr, std::__1::default_delete<wabt::Expr> >*)
Line
Count
Source
2097
1.22k
                                           std::unique_ptr<Expr>* out_expr) {
2098
1.22k
  ErrorUnlessOpcodeEnabled(token);
2099
2100
1.22k
  Var memidx(0, loc);
2101
2102
1.22k
  if (options_->features.multi_memory_enabled()) {
2103
    // We have to be a little careful when reading the memeory index.
2104
    // If there is just a single integer folloing the instruction that
2105
    // represents the lane index, so we check for either a pair of intergers
2106
    // or an integers followed by offset= or align=.
2107
0
    bool try_read_mem_index = true;
2108
0
    if (PeekMatch(TokenType::Nat)) {
2109
      // The next token could be a memory index or a lane index
2110
0
      if (!PeekMatch(TokenType::OffsetEqNat, 1) &&
2111
0
          !PeekMatch(TokenType::AlignEqNat, 1) &&
2112
0
          !PeekMatch(TokenType::Nat, 1)) {
2113
0
        try_read_mem_index = false;
2114
0
      }
2115
0
    }
2116
0
    if (try_read_mem_index) {
2117
0
      CHECK_RESULT(ParseMemidx(loc, &memidx));
2118
0
    }
2119
0
  }
2120
1.22k
  Address offset;
2121
1.22k
  Address align;
2122
1.22k
  ParseOffsetOpt(&offset);
2123
1.22k
  ParseAlignOpt(&align);
2124
2125
1.22k
  uint64_t lane_idx = 0;
2126
1.22k
  Result result = ParseSimdLane(loc, &lane_idx);
2127
2128
1.22k
  if (Failed(result)) {
2129
920
    return Result::Error;
2130
920
  }
2131
2132
309
  out_expr->reset(new T(token.opcode(), memidx, align, offset, lane_idx, loc));
2133
309
  return Result::Ok;
2134
1.22k
}
2135
2136
template <typename T>
2137
Result WastParser::ParseMemoryExpr(Location loc,
2138
24.4k
                                   std::unique_ptr<Expr>* out_expr) {
2139
24.4k
  Var memidx;
2140
24.4k
  CHECK_RESULT(ParseMemidx(loc, &memidx));
2141
22.2k
  out_expr->reset(new T(memidx, loc));
2142
22.2k
  return Result::Ok;
2143
24.4k
}
wabt::Result wabt::WastParser::ParseMemoryExpr<wabt::MemoryExpr<(wabt::ExprType)30> >(wabt::Location, std::__1::unique_ptr<wabt::Expr, std::__1::default_delete<wabt::Expr> >*)
Line
Count
Source
2138
777
                                   std::unique_ptr<Expr>* out_expr) {
2139
777
  Var memidx;
2140
777
  CHECK_RESULT(ParseMemidx(loc, &memidx));
2141
579
  out_expr->reset(new T(memidx, loc));
2142
579
  return Result::Ok;
2143
777
}
wabt::Result wabt::WastParser::ParseMemoryExpr<wabt::MemoryExpr<(wabt::ExprType)33> >(wabt::Location, std::__1::unique_ptr<wabt::Expr, std::__1::default_delete<wabt::Expr> >*)
Line
Count
Source
2138
22.8k
                                   std::unique_ptr<Expr>* out_expr) {
2139
22.8k
  Var memidx;
2140
22.8k
  CHECK_RESULT(ParseMemidx(loc, &memidx));
2141
21.0k
  out_expr->reset(new T(memidx, loc));
2142
21.0k
  return Result::Ok;
2143
22.8k
}
wabt::Result wabt::WastParser::ParseMemoryExpr<wabt::MemoryExpr<(wabt::ExprType)31> >(wabt::Location, std::__1::unique_ptr<wabt::Expr, std::__1::default_delete<wabt::Expr> >*)
Line
Count
Source
2138
842
                                   std::unique_ptr<Expr>* out_expr) {
2139
842
  Var memidx;
2140
842
  CHECK_RESULT(ParseMemidx(loc, &memidx));
2141
606
  out_expr->reset(new T(memidx, loc));
2142
606
  return Result::Ok;
2143
842
}
2144
2145
template <typename T>
2146
Result WastParser::ParseMemoryBinaryExpr(Location loc,
2147
908
                                         std::unique_ptr<Expr>* out_expr) {
2148
908
  Var destmemidx;
2149
908
  Var srcmemidx;
2150
908
  CHECK_RESULT(ParseMemidx(loc, &destmemidx));
2151
568
  CHECK_RESULT(ParseMemidx(loc, &srcmemidx));
2152
568
  out_expr->reset(new T(destmemidx, srcmemidx, loc));
2153
568
  return Result::Ok;
2154
568
}
2155
2156
48.0k
Result WastParser::ParseSimdLane(Location loc, uint64_t* lane_idx) {
2157
48.0k
  if (!PeekMatch(TokenType::Nat) && !PeekMatch(TokenType::Int)) {
2158
11.9k
    return ErrorExpected({"a natural number in range [0, 32)"});
2159
11.9k
  }
2160
2161
36.0k
  Literal literal = Consume().literal();
2162
2163
36.0k
  Result result =
2164
36.0k
      ParseInt64(literal.text, lane_idx, ParseIntType::UnsignedOnly);
2165
2166
36.0k
  if (Failed(result)) {
2167
11.8k
    Error(loc, "invalid literal \"" PRIstringview "\"",
2168
11.8k
          WABT_PRINTF_STRING_VIEW_ARG(literal.text));
2169
11.8k
    return Result::Error;
2170
11.8k
  }
2171
2172
  // The valid range is only [0, 32), but it's only malformed if it can't
2173
  // fit in a byte.
2174
24.2k
  if (*lane_idx > 255) {
2175
871
    Error(loc, "lane index \"" PRIstringview "\" out-of-range [0, 32)",
2176
871
          WABT_PRINTF_STRING_VIEW_ARG(literal.text));
2177
871
    return Result::Error;
2178
871
  }
2179
2180
23.3k
  return Result::Ok;
2181
24.2k
}
2182
2183
835k
Result WastParser::ParsePlainInstr(std::unique_ptr<Expr>* out_expr) {
2184
835k
  WABT_TRACE(ParsePlainInstr);
2185
835k
  Location loc = GetLocation();
2186
835k
  switch (Peek()) {
2187
684
    case TokenType::Unreachable:
2188
684
      Consume();
2189
684
      out_expr->reset(new UnreachableExpr(loc));
2190
684
      break;
2191
2192
152k
    case TokenType::Nop:
2193
152k
      Consume();
2194
152k
      out_expr->reset(new NopExpr(loc));
2195
152k
      break;
2196
2197
569
    case TokenType::Drop:
2198
569
      Consume();
2199
569
      out_expr->reset(new DropExpr(loc));
2200
569
      break;
2201
2202
1.76k
    case TokenType::Select: {
2203
1.76k
      Consume();
2204
1.76k
      TypeVector result;
2205
1.76k
      if (options_->features.reference_types_enabled() &&
2206
1.76k
          PeekMatchLpar(TokenType::Result)) {
2207
524
        CHECK_RESULT(ParseResultList(&result, nullptr));
2208
524
      }
2209
1.55k
      out_expr->reset(new SelectExpr(result, loc));
2210
1.55k
      break;
2211
1.76k
    }
2212
2213
6.58k
    case TokenType::Br:
2214
6.58k
      Consume();
2215
6.58k
      CHECK_RESULT(ParsePlainInstrVar<BrExpr>(loc, out_expr));
2216
4.46k
      break;
2217
2218
4.46k
    case TokenType::BrIf:
2219
783
      Consume();
2220
783
      CHECK_RESULT(ParsePlainInstrVar<BrIfExpr>(loc, out_expr));
2221
422
      break;
2222
2223
10.8k
    case TokenType::BrTable: {
2224
10.8k
      Consume();
2225
10.8k
      auto expr = std::make_unique<BrTableExpr>(loc);
2226
10.8k
      CHECK_RESULT(ParseVarList(&expr->targets));
2227
1.14k
      expr->default_target = expr->targets.back();
2228
1.14k
      expr->targets.pop_back();
2229
1.14k
      *out_expr = std::move(expr);
2230
1.14k
      break;
2231
10.8k
    }
2232
2233
8.58k
    case TokenType::Return:
2234
8.58k
      Consume();
2235
8.58k
      out_expr->reset(new ReturnExpr(loc));
2236
8.58k
      break;
2237
2238
2.71k
    case TokenType::Call:
2239
2.71k
      Consume();
2240
2.71k
      CHECK_RESULT(ParsePlainInstrVar<CallExpr>(loc, out_expr));
2241
2.14k
      break;
2242
2243
8.39k
    case TokenType::CallIndirect: {
2244
8.39k
      Consume();
2245
8.39k
      auto expr = std::make_unique<CallIndirectExpr>(loc);
2246
8.39k
      ParseVarOpt(&expr->table, Var(0, loc));
2247
8.39k
      CHECK_RESULT(ParseTypeUseOpt(&expr->decl));
2248
7.93k
      CHECK_RESULT(ParseUnboundFuncSignature(&expr->decl.sig));
2249
7.72k
      *out_expr = std::move(expr);
2250
7.72k
      break;
2251
7.93k
    }
2252
2253
442
    case TokenType::CallRef: {
2254
442
      ErrorUnlessOpcodeEnabled(Consume());
2255
442
      out_expr->reset(new CallRefExpr(loc));
2256
442
      break;
2257
7.93k
    }
2258
2259
1.28k
    case TokenType::ReturnCall:
2260
1.28k
      ErrorUnlessOpcodeEnabled(Consume());
2261
1.28k
      CHECK_RESULT(ParsePlainInstrVar<ReturnCallExpr>(loc, out_expr));
2262
912
      break;
2263
2264
8.89k
    case TokenType::ReturnCallIndirect: {
2265
8.89k
      ErrorUnlessOpcodeEnabled(Consume());
2266
8.89k
      auto expr = std::make_unique<ReturnCallIndirectExpr>(loc);
2267
8.89k
      ParseVarOpt(&expr->table, Var(0, loc));
2268
8.89k
      CHECK_RESULT(ParseTypeUseOpt(&expr->decl));
2269
8.34k
      CHECK_RESULT(ParseUnboundFuncSignature(&expr->decl.sig));
2270
8.13k
      *out_expr = std::move(expr);
2271
8.13k
      break;
2272
8.34k
    }
2273
2274
1.43k
    case TokenType::LocalGet:
2275
1.43k
      Consume();
2276
1.43k
      CHECK_RESULT(ParsePlainInstrVar<LocalGetExpr>(loc, out_expr));
2277
1.10k
      break;
2278
2279
1.82k
    case TokenType::LocalSet:
2280
1.82k
      Consume();
2281
1.82k
      CHECK_RESULT(ParsePlainInstrVar<LocalSetExpr>(loc, out_expr));
2282
1.47k
      break;
2283
2284
3.62k
    case TokenType::LocalTee:
2285
3.62k
      Consume();
2286
3.62k
      CHECK_RESULT(ParsePlainInstrVar<LocalTeeExpr>(loc, out_expr));
2287
2.17k
      break;
2288
2289
2.17k
    case TokenType::GlobalGet:
2290
1.52k
      Consume();
2291
1.52k
      CHECK_RESULT(ParsePlainInstrVar<GlobalGetExpr>(loc, out_expr));
2292
1.09k
      break;
2293
2294
1.41k
    case TokenType::GlobalSet:
2295
1.41k
      Consume();
2296
1.41k
      CHECK_RESULT(ParsePlainInstrVar<GlobalSetExpr>(loc, out_expr));
2297
1.02k
      break;
2298
2299
23.0k
    case TokenType::Load:
2300
23.0k
      CHECK_RESULT(ParseLoadStoreInstr<LoadExpr>(loc, Consume(), out_expr));
2301
22.6k
      break;
2302
2303
22.6k
    case TokenType::Store:
2304
6.63k
      CHECK_RESULT(ParseLoadStoreInstr<StoreExpr>(loc, Consume(), out_expr));
2305
6.41k
      break;
2306
2307
417k
    case TokenType::Const: {
2308
417k
      Const const_;
2309
417k
      CHECK_RESULT(ParseConst(&const_, ConstType::Normal));
2310
326k
      out_expr->reset(new ConstExpr(const_, loc));
2311
326k
      break;
2312
417k
    }
2313
2314
22.6k
    case TokenType::Unary: {
2315
22.6k
      Token token = Consume();
2316
22.6k
      ErrorUnlessOpcodeEnabled(token);
2317
22.6k
      out_expr->reset(new UnaryExpr(token.opcode(), loc));
2318
22.6k
      break;
2319
417k
    }
2320
2321
14.2k
    case TokenType::Binary: {
2322
14.2k
      Token token = Consume();
2323
14.2k
      ErrorUnlessOpcodeEnabled(token);
2324
14.2k
      out_expr->reset(new BinaryExpr(token.opcode(), loc));
2325
14.2k
      break;
2326
417k
    }
2327
2328
1.10k
    case TokenType::Compare:
2329
1.10k
      out_expr->reset(new CompareExpr(Consume().opcode(), loc));
2330
1.10k
      break;
2331
2332
5.84k
    case TokenType::Convert: {
2333
5.84k
      Token token = Consume();
2334
5.84k
      ErrorUnlessOpcodeEnabled(token);
2335
5.84k
      out_expr->reset(new ConvertExpr(token.opcode(), loc));
2336
5.84k
      break;
2337
417k
    }
2338
2339
908
    case TokenType::MemoryCopy:
2340
908
      ErrorUnlessOpcodeEnabled(Consume());
2341
908
      CHECK_RESULT(ParseMemoryBinaryExpr<MemoryCopyExpr>(loc, out_expr));
2342
568
      break;
2343
2344
777
    case TokenType::MemoryFill:
2345
777
      ErrorUnlessOpcodeEnabled(Consume());
2346
777
      CHECK_RESULT(ParseMemoryExpr<MemoryFillExpr>(loc, out_expr));
2347
579
      break;
2348
2349
1.58k
    case TokenType::DataDrop:
2350
1.58k
      ErrorUnlessOpcodeEnabled(Consume());
2351
1.58k
      CHECK_RESULT(ParsePlainInstrVar<DataDropExpr>(loc, out_expr));
2352
994
      break;
2353
2354
2.22k
    case TokenType::MemoryInit:
2355
2.22k
      ErrorUnlessOpcodeEnabled(Consume());
2356
2.22k
      CHECK_RESULT(ParseMemoryInstrVar<MemoryInitExpr>(loc, out_expr));
2357
1.20k
      break;
2358
2359
22.8k
    case TokenType::MemorySize:
2360
22.8k
      Consume();
2361
22.8k
      CHECK_RESULT(ParseMemoryExpr<MemorySizeExpr>(loc, out_expr));
2362
21.0k
      break;
2363
2364
21.0k
    case TokenType::MemoryGrow:
2365
842
      Consume();
2366
842
      CHECK_RESULT(ParseMemoryExpr<MemoryGrowExpr>(loc, out_expr));
2367
606
      break;
2368
2369
3.41k
    case TokenType::TableCopy: {
2370
3.41k
      ErrorUnlessOpcodeEnabled(Consume());
2371
3.41k
      Var dst(0, loc);
2372
3.41k
      Var src(0, loc);
2373
3.41k
      if (options_->features.reference_types_enabled()) {
2374
3.41k
        ParseVarOpt(&dst, dst);
2375
3.41k
        ParseVarOpt(&src, src);
2376
3.41k
      }
2377
3.41k
      out_expr->reset(new TableCopyExpr(dst, src, loc));
2378
3.41k
      break;
2379
842
    }
2380
2381
1.40k
    case TokenType::ElemDrop:
2382
1.40k
      ErrorUnlessOpcodeEnabled(Consume());
2383
1.40k
      CHECK_RESULT(ParsePlainInstrVar<ElemDropExpr>(loc, out_expr));
2384
1.04k
      break;
2385
2386
2.41k
    case TokenType::TableInit: {
2387
2.41k
      ErrorUnlessOpcodeEnabled(Consume());
2388
2.41k
      Var segment_index(0, loc);
2389
2.41k
      CHECK_RESULT(ParseVar(&segment_index));
2390
1.97k
      Var table_index(0, loc);
2391
1.97k
      if (ParseVarOpt(&table_index, table_index)) {
2392
        // Here are the two forms:
2393
        //
2394
        //   table.init $elemidx ...
2395
        //   table.init $tableidx $elemidx ...
2396
        //
2397
        // So if both indexes are provided, we need to swap them.
2398
995
        std::swap(segment_index, table_index);
2399
995
      }
2400
1.97k
      out_expr->reset(new TableInitExpr(segment_index, table_index, loc));
2401
1.97k
      break;
2402
2.41k
    }
2403
2404
1.14k
    case TokenType::TableGet: {
2405
1.14k
      ErrorUnlessOpcodeEnabled(Consume());
2406
1.14k
      Var table_index(0, loc);
2407
1.14k
      ParseVarOpt(&table_index, table_index);
2408
1.14k
      out_expr->reset(new TableGetExpr(table_index, loc));
2409
1.14k
      break;
2410
2.41k
    }
2411
2412
1.17k
    case TokenType::TableSet: {
2413
1.17k
      ErrorUnlessOpcodeEnabled(Consume());
2414
1.17k
      Var table_index(0, loc);
2415
1.17k
      ParseVarOpt(&table_index, table_index);
2416
1.17k
      out_expr->reset(new TableSetExpr(table_index, loc));
2417
1.17k
      break;
2418
2.41k
    }
2419
2420
2.89k
    case TokenType::TableGrow: {
2421
2.89k
      ErrorUnlessOpcodeEnabled(Consume());
2422
2.89k
      Var table_index(0, loc);
2423
2.89k
      ParseVarOpt(&table_index, table_index);
2424
2.89k
      out_expr->reset(new TableGrowExpr(table_index, loc));
2425
2.89k
      break;
2426
2.41k
    }
2427
2428
2.07k
    case TokenType::TableSize: {
2429
2.07k
      ErrorUnlessOpcodeEnabled(Consume());
2430
2.07k
      Var table_index(0, loc);
2431
2.07k
      ParseVarOpt(&table_index, table_index);
2432
2.07k
      out_expr->reset(new TableSizeExpr(table_index, loc));
2433
2.07k
      break;
2434
2.41k
    }
2435
2436
2.00k
    case TokenType::TableFill: {
2437
2.00k
      ErrorUnlessOpcodeEnabled(Consume());
2438
2.00k
      Var table_index(0, loc);
2439
2.00k
      ParseVarOpt(&table_index, table_index);
2440
2.00k
      out_expr->reset(new TableFillExpr(table_index, loc));
2441
2.00k
      break;
2442
2.41k
    }
2443
2444
1.52k
    case TokenType::RefFunc:
2445
1.52k
      ErrorUnlessOpcodeEnabled(Consume());
2446
1.52k
      CHECK_RESULT(ParsePlainInstrVar<RefFuncExpr>(loc, out_expr));
2447
1.04k
      break;
2448
2449
1.58k
    case TokenType::RefNull: {
2450
1.58k
      ErrorUnlessOpcodeEnabled(Consume());
2451
1.58k
      Type type;
2452
1.58k
      CHECK_RESULT(ParseRefKind(&type));
2453
728
      out_expr->reset(new RefNullExpr(type, loc));
2454
728
      break;
2455
1.58k
    }
2456
2457
426
    case TokenType::RefIsNull:
2458
426
      ErrorUnlessOpcodeEnabled(Consume());
2459
426
      out_expr->reset(new RefIsNullExpr(loc));
2460
426
      break;
2461
2462
2.10k
    case TokenType::Throw:
2463
2.10k
      ErrorUnlessOpcodeEnabled(Consume());
2464
2.10k
      CHECK_RESULT(ParsePlainInstrVar<ThrowExpr>(loc, out_expr));
2465
1.58k
      break;
2466
2467
1.58k
    case TokenType::Rethrow:
2468
925
      ErrorUnlessOpcodeEnabled(Consume());
2469
925
      CHECK_RESULT(ParsePlainInstrVar<RethrowExpr>(loc, out_expr));
2470
474
      break;
2471
2472
799
    case TokenType::AtomicNotify: {
2473
799
      Token token = Consume();
2474
799
      ErrorUnlessOpcodeEnabled(token);
2475
799
      CHECK_RESULT(ParseLoadStoreInstr<AtomicNotifyExpr>(loc, token, out_expr));
2476
351
      break;
2477
799
    }
2478
2479
422
    case TokenType::AtomicFence: {
2480
422
      Token token = Consume();
2481
422
      ErrorUnlessOpcodeEnabled(token);
2482
422
      uint32_t consistency_model = 0x0;
2483
422
      out_expr->reset(new AtomicFenceExpr(consistency_model, loc));
2484
422
      break;
2485
799
    }
2486
2487
744
    case TokenType::AtomicWait: {
2488
744
      Token token = Consume();
2489
744
      ErrorUnlessOpcodeEnabled(token);
2490
744
      CHECK_RESULT(ParseLoadStoreInstr<AtomicWaitExpr>(loc, token, out_expr));
2491
366
      break;
2492
744
    }
2493
2494
2.02k
    case TokenType::AtomicLoad: {
2495
2.02k
      Token token = Consume();
2496
2.02k
      ErrorUnlessOpcodeEnabled(token);
2497
2.02k
      CHECK_RESULT(ParseLoadStoreInstr<AtomicLoadExpr>(loc, token, out_expr));
2498
1.72k
      break;
2499
2.02k
    }
2500
2501
21.2k
    case TokenType::AtomicStore: {
2502
21.2k
      Token token = Consume();
2503
21.2k
      ErrorUnlessOpcodeEnabled(token);
2504
21.2k
      CHECK_RESULT(ParseLoadStoreInstr<AtomicStoreExpr>(loc, token, out_expr));
2505
1.88k
      break;
2506
21.2k
    }
2507
2508
10.9k
    case TokenType::AtomicRmw: {
2509
10.9k
      Token token = Consume();
2510
10.9k
      ErrorUnlessOpcodeEnabled(token);
2511
10.9k
      CHECK_RESULT(ParseLoadStoreInstr<AtomicRmwExpr>(loc, token, out_expr));
2512
10.3k
      break;
2513
10.9k
    }
2514
2515
10.3k
    case TokenType::AtomicRmwCmpxchg: {
2516
2.65k
      Token token = Consume();
2517
2.65k
      ErrorUnlessOpcodeEnabled(token);
2518
2.65k
      CHECK_RESULT(
2519
2.65k
          ParseLoadStoreInstr<AtomicRmwCmpxchgExpr>(loc, token, out_expr));
2520
2.39k
      break;
2521
2.65k
    }
2522
2523
9.72k
    case TokenType::Ternary: {
2524
9.72k
      Token token = Consume();
2525
9.72k
      ErrorUnlessOpcodeEnabled(token);
2526
9.72k
      out_expr->reset(new TernaryExpr(token.opcode(), loc));
2527
9.72k
      break;
2528
2.65k
    }
2529
2530
3.72k
    case TokenType::SimdLaneOp: {
2531
3.72k
      Token token = Consume();
2532
3.72k
      ErrorUnlessOpcodeEnabled(token);
2533
2534
3.72k
      uint64_t lane_idx = 0;
2535
3.72k
      Result result = ParseSimdLane(loc, &lane_idx);
2536
2537
3.72k
      if (Failed(result)) {
2538
3.13k
        return Result::Error;
2539
3.13k
      }
2540
2541
586
      out_expr->reset(new SimdLaneOpExpr(token.opcode(), lane_idx, loc));
2542
586
      break;
2543
3.72k
    }
2544
2545
10.0k
    case TokenType::SimdLoadLane: {
2546
10.0k
      CHECK_RESULT(
2547
10.0k
          ParseSIMDLoadStoreInstr<SimdLoadLaneExpr>(loc, Consume(), out_expr));
2548
3.56k
      break;
2549
10.0k
    }
2550
2551
3.56k
    case TokenType::SimdStoreLane: {
2552
1.22k
      CHECK_RESULT(
2553
1.22k
          ParseSIMDLoadStoreInstr<SimdStoreLaneExpr>(loc, Consume(), out_expr));
2554
309
      break;
2555
1.22k
    }
2556
2557
15.1k
    case TokenType::SimdShuffleOp: {
2558
15.1k
      Token token = Consume();
2559
15.1k
      ErrorUnlessOpcodeEnabled(token);
2560
15.1k
      v128 values;
2561
34.0k
      for (int lane = 0; lane < 16; ++lane) {
2562
33.0k
        Location loc = GetLocation();
2563
33.0k
        uint64_t lane_idx;
2564
33.0k
        Result result = ParseSimdLane(loc, &lane_idx);
2565
33.0k
        if (Failed(result)) {
2566
14.1k
          return Result::Error;
2567
14.1k
        }
2568
2569
18.9k
        values.set_u8(lane, static_cast<uint8_t>(lane_idx));
2570
18.9k
      }
2571
2572
970
      out_expr->reset(new SimdShuffleOpExpr(token.opcode(), values, loc));
2573
970
      break;
2574
15.1k
    }
2575
2576
0
    default:
2577
0
      assert(
2578
0
          !"ParsePlainInstr should only be called when IsPlainInstr() is true");
2579
0
      return Result::Error;
2580
835k
  }
2581
2582
672k
  return Result::Ok;
2583
835k
}
2584
2585
Result WastParser::ParseSimdV128Const(Const* const_,
2586
                                      TokenType token_type,
2587
36.5k
                                      ConstType const_type) {
2588
36.5k
  WABT_TRACE(ParseSimdV128Const);
2589
2590
36.5k
  uint8_t lane_count = 0;
2591
36.5k
  bool integer = true;
2592
36.5k
  switch (token_type) {
2593
1.24k
    case TokenType::I8X16: { lane_count = 16; break; }
2594
9.14k
    case TokenType::I16X8: { lane_count = 8; break; }
2595
580
    case TokenType::I32X4: { lane_count = 4; break; }
2596
375
    case TokenType::I64X2: { lane_count = 2; break; }
2597
537
    case TokenType::F32X4: { lane_count = 4; integer = false; break; }
2598
20.3k
    case TokenType::F64X2: { lane_count = 2; integer = false; break; }
2599
4.35k
    default: {
2600
4.35k
      Error(const_->loc,
2601
4.35k
            "Unexpected type at start of simd constant. "
2602
4.35k
            "Expected one of: i8x16, i16x8, i32x4, i64x2, f32x4, f64x2. "
2603
4.35k
            "Found \"%s\".",
2604
4.35k
            GetTokenTypeName(token_type));
2605
4.35k
      return Result::Error;
2606
0
    }
2607
36.5k
  }
2608
32.2k
  Consume();
2609
2610
32.2k
  const_->loc = GetLocation();
2611
2612
81.7k
  for (int lane = 0; lane < lane_count; ++lane) {
2613
61.8k
    Location loc = GetLocation();
2614
2615
    // Check that the lane literal type matches the element type of the v128:
2616
61.8k
    Token token = GetToken();
2617
61.8k
    switch (token.token_type()) {
2618
11.6k
      case TokenType::Nat:
2619
15.7k
      case TokenType::Int:
2620
        // OK.
2621
15.7k
        break;
2622
2623
40.0k
      case TokenType::Float:
2624
40.2k
      case TokenType::NanArithmetic:
2625
40.5k
      case TokenType::NanCanonical:
2626
40.5k
        if (integer) {
2627
485
          goto error;
2628
485
        }
2629
40.0k
        break;
2630
2631
40.0k
      error:
2632
5.98k
      default:
2633
5.98k
        if (integer) {
2634
5.15k
          return ErrorExpected({"a Nat or Integer literal"}, "123");
2635
5.15k
        } else {
2636
825
          return ErrorExpected({"a Float literal"}, "42.0");
2637
825
        }
2638
61.8k
    }
2639
2640
55.8k
    Result result;
2641
2642
    // For each type, parse the next literal, bound check it, and write it to
2643
    // the array of bytes:
2644
55.8k
    if (integer) {
2645
14.6k
      std::string_view sv = Consume().literal().text;
2646
2647
14.6k
      switch (lane_count) {
2648
2.81k
        case 16: {
2649
2.81k
          uint8_t value = 0;
2650
2.81k
          result = ParseInt8(sv, &value, ParseIntType::SignedAndUnsigned);
2651
2.81k
          const_->set_v128_u8(lane, value);
2652
2.81k
          break;
2653
0
        }
2654
10.9k
        case 8: {
2655
10.9k
          uint16_t value = 0;
2656
10.9k
          result = ParseInt16(sv, &value, ParseIntType::SignedAndUnsigned);
2657
10.9k
          const_->set_v128_u16(lane, value);
2658
10.9k
          break;
2659
0
        }
2660
431
        case 4: {
2661
431
          uint32_t value = 0;
2662
431
          result = ParseInt32(sv, &value, ParseIntType::SignedAndUnsigned);
2663
431
          const_->set_v128_u32(lane, value);
2664
431
          break;
2665
0
        }
2666
510
        case 2: {
2667
510
          uint64_t value = 0;
2668
510
          result = ParseInt64(sv, &value, ParseIntType::SignedAndUnsigned);
2669
510
          const_->set_v128_u64(lane, value);
2670
510
          break;
2671
0
        }
2672
14.6k
      }
2673
41.1k
    } else {
2674
41.1k
      Const lane_const_;
2675
41.1k
      switch (lane_count) {
2676
1.22k
        case 4:
2677
1.22k
          result = ParseF32(&lane_const_, const_type);
2678
1.22k
          const_->set_v128_f32(lane, lane_const_.f32_bits());
2679
1.22k
          break;
2680
2681
39.9k
        case 2:
2682
39.9k
          result = ParseF64(&lane_const_, const_type);
2683
39.9k
          const_->set_v128_f64(lane, lane_const_.f64_bits());
2684
39.9k
          break;
2685
41.1k
      }
2686
2687
41.1k
      const_->set_expected_nan(lane, lane_const_.expected_nan());
2688
41.1k
    }
2689
2690
55.8k
    if (Failed(result)) {
2691
6.26k
      Error(loc, "invalid literal \"%s\"", token.to_string().c_str());
2692
6.26k
      return Result::Error;
2693
6.26k
    }
2694
55.8k
  }
2695
2696
19.9k
  return Result::Ok;
2697
32.2k
}
2698
2699
0
Result WastParser::ParseExpectedNan(ExpectedNan* expected) {
2700
0
  WABT_TRACE(ParseExpectedNan);
2701
0
  TokenType token_type = Peek();
2702
0
  switch (token_type) {
2703
0
    case TokenType::NanArithmetic:
2704
0
      *expected = ExpectedNan::Arithmetic;
2705
0
      break;
2706
0
    case TokenType::NanCanonical:
2707
0
      *expected = ExpectedNan::Canonical;
2708
0
      break;
2709
0
    default:
2710
0
      return Result::Error;
2711
0
  }
2712
0
  Consume();
2713
0
  return Result::Ok;
2714
0
}
2715
2716
209k
Result WastParser::ParseF32(Const* const_, ConstType const_type) {
2717
209k
  ExpectedNan expected;
2718
209k
  if (const_type == ConstType::Expectation &&
2719
209k
      Succeeded(ParseExpectedNan(&expected))) {
2720
0
    const_->set_f32(expected);
2721
0
    return Result::Ok;
2722
0
  }
2723
2724
209k
  auto token = Consume();
2725
209k
  if (!token.HasLiteral()) {
2726
195
    return Result::Error;
2727
195
  }
2728
2729
208k
  auto literal = token.literal();
2730
208k
  uint32_t f32_bits;
2731
208k
  Result result = ParseFloat(literal.type, literal.text, &f32_bits);
2732
208k
  const_->set_f32(f32_bits);
2733
208k
  return result;
2734
209k
}
2735
2736
149k
Result WastParser::ParseF64(Const* const_, ConstType const_type) {
2737
149k
  ExpectedNan expected;
2738
149k
  if (const_type == ConstType::Expectation &&
2739
149k
      Succeeded(ParseExpectedNan(&expected))) {
2740
0
    const_->set_f64(expected);
2741
0
    return Result::Ok;
2742
0
  }
2743
2744
149k
  auto token = Consume();
2745
149k
  if (!token.HasLiteral()) {
2746
350
    return Result::Error;
2747
350
  }
2748
2749
149k
  auto literal = token.literal();
2750
149k
  uint64_t f64_bits;
2751
149k
  Result result = ParseDouble(literal.type, literal.text, &f64_bits);
2752
149k
  const_->set_f64(f64_bits);
2753
149k
  return result;
2754
149k
}
2755
2756
417k
Result WastParser::ParseConst(Const* const_, ConstType const_type) {
2757
417k
  WABT_TRACE(ParseConst);
2758
417k
  Token opcode_token = Consume();
2759
417k
  Opcode opcode = opcode_token.opcode();
2760
417k
  const_->loc = GetLocation();
2761
417k
  Token token = GetToken();
2762
2763
  // V128 is fully handled by ParseSimdV128Const:
2764
417k
  if (opcode != Opcode::V128Const) {
2765
381k
    switch (token.token_type()) {
2766
35.0k
      case TokenType::Nat:
2767
36.7k
      case TokenType::Int:
2768
326k
      case TokenType::Float:
2769
        // OK.
2770
326k
        break;
2771
396
      case TokenType::NanArithmetic:
2772
794
      case TokenType::NanCanonical:
2773
794
        break;
2774
53.7k
      default:
2775
53.7k
        return ErrorExpected({"a numeric literal"}, "123, -45, 6.7e8");
2776
381k
    }
2777
381k
  }
2778
2779
363k
  Result result;
2780
363k
  switch (opcode) {
2781
8.46k
    case Opcode::I32Const: {
2782
8.46k
      auto token = Consume();
2783
8.46k
      if (!token.HasLiteral()) {
2784
327
        return Result::Error;
2785
327
      }
2786
8.13k
      auto sv = token.literal().text;
2787
8.13k
      uint32_t u32;
2788
8.13k
      result = ParseInt32(sv, &u32, ParseIntType::SignedAndUnsigned);
2789
8.13k
      const_->set_u32(u32);
2790
8.13k
      break;
2791
8.46k
    }
2792
2793
1.14k
    case Opcode::I64Const: {
2794
1.14k
      auto token = Consume();
2795
1.14k
      if (!token.HasLiteral()) {
2796
206
        return Result::Error;
2797
206
      }
2798
940
      auto sv = token.literal().text;
2799
940
      uint64_t u64;
2800
940
      result = ParseInt64(sv, &u64, ParseIntType::SignedAndUnsigned);
2801
940
      const_->set_u64(u64);
2802
940
      break;
2803
1.14k
    }
2804
2805
207k
    case Opcode::F32Const:
2806
207k
      result = ParseF32(const_, const_type);
2807
207k
      break;
2808
2809
109k
    case Opcode::F64Const:
2810
109k
      result = ParseF64(const_, const_type);
2811
109k
      break;
2812
2813
36.5k
    case Opcode::V128Const:
2814
36.5k
      ErrorUnlessOpcodeEnabled(opcode_token);
2815
      // Parse V128 Simd Const (16 bytes).
2816
36.5k
      result = ParseSimdV128Const(const_, token.token_type(), const_type);
2817
      // ParseSimdV128Const report error already, just return here if parser get
2818
      // errors.
2819
36.5k
      if (Failed(result)) {
2820
16.6k
        return Result::Error;
2821
16.6k
      }
2822
19.9k
      break;
2823
2824
19.9k
    default:
2825
0
      assert(!"ParseConst called with invalid opcode");
2826
0
      return Result::Error;
2827
363k
  }
2828
2829
346k
  if (Failed(result)) {
2830
20.2k
    Error(const_->loc, "invalid literal \"%s\"", token.to_string().c_str());
2831
    // Return if parser get errors.
2832
20.2k
    return Result::Error;
2833
20.2k
  }
2834
2835
326k
  return Result::Ok;
2836
346k
}
2837
2838
0
Result WastParser::ParseExternref(Const* const_) {
2839
0
  WABT_TRACE(ParseExternref);
2840
0
  Token token = Consume();
2841
0
  if (!options_->features.reference_types_enabled()) {
2842
0
    Error(token.loc, "externref not allowed");
2843
0
    return Result::Error;
2844
0
  }
2845
2846
0
  Literal literal;
2847
0
  std::string_view sv;
2848
0
  const_->loc = GetLocation();
2849
0
  TokenType token_type = Peek();
2850
2851
0
  switch (token_type) {
2852
0
    case TokenType::Nat:
2853
0
    case TokenType::Int: {
2854
0
      literal = Consume().literal();
2855
0
      sv = literal.text;
2856
0
      break;
2857
0
    }
2858
0
    default:
2859
0
      return ErrorExpected({"a numeric literal"}, "123");
2860
0
  }
2861
2862
0
  uint64_t ref_bits;
2863
0
  Result result = ParseInt64(sv, &ref_bits, ParseIntType::UnsignedOnly);
2864
2865
0
  const_->set_externref(static_cast<uintptr_t>(ref_bits));
2866
2867
0
  if (Failed(result)) {
2868
0
    Error(const_->loc, "invalid literal \"" PRIstringview "\"",
2869
0
          WABT_PRINTF_STRING_VIEW_ARG(literal.text));
2870
    // Return if parser get errors.
2871
0
    return Result::Error;
2872
0
  }
2873
2874
0
  return Result::Ok;
2875
0
}
2876
2877
0
Result WastParser::ParseConstList(ConstVector* consts, ConstType type) {
2878
0
  WABT_TRACE(ParseConstList);
2879
0
  while (PeekMatchLpar(TokenType::Const) || PeekMatchLpar(TokenType::RefNull) ||
2880
0
         PeekMatchLpar(TokenType::RefExtern) ||
2881
0
         PeekMatchLpar(TokenType::RefFunc)) {
2882
0
    Consume();
2883
0
    Const const_;
2884
0
    switch (Peek()) {
2885
0
      case TokenType::Const:
2886
0
        CHECK_RESULT(ParseConst(&const_, type));
2887
0
        break;
2888
0
      case TokenType::RefNull: {
2889
0
        auto token = Consume();
2890
0
        Type type;
2891
0
        CHECK_RESULT(ParseRefKind(&type));
2892
0
        ErrorUnlessOpcodeEnabled(token);
2893
0
        const_.loc = GetLocation();
2894
0
        const_.set_null(type);
2895
0
        break;
2896
0
      }
2897
0
      case TokenType::RefFunc: {
2898
0
        auto token = Consume();
2899
0
        ErrorUnlessOpcodeEnabled(token);
2900
0
        const_.loc = GetLocation();
2901
0
        const_.set_funcref();
2902
0
        break;
2903
0
      }
2904
0
      case TokenType::RefExtern:
2905
0
        CHECK_RESULT(ParseExternref(&const_));
2906
0
        break;
2907
0
      default:
2908
0
        assert(!"unreachable");
2909
0
        return Result::Error;
2910
0
    }
2911
0
    EXPECT(Rpar);
2912
0
    consts->push_back(const_);
2913
0
  }
2914
2915
0
  return Result::Ok;
2916
0
}
2917
2918
46.8k
Result WastParser::ParseBlockInstr(std::unique_ptr<Expr>* out_expr) {
2919
46.8k
  WABT_TRACE(ParseBlockInstr);
2920
46.8k
  Location loc = GetLocation();
2921
2922
46.8k
  switch (Peek()) {
2923
2.25k
    case TokenType::Block: {
2924
2.25k
      Consume();
2925
2.25k
      auto expr = std::make_unique<BlockExpr>(loc);
2926
2.25k
      CHECK_RESULT(ParseLabelOpt(&expr->block.label));
2927
2.25k
      CHECK_RESULT(ParseBlock(&expr->block));
2928
1.34k
      EXPECT(End);
2929
197
      CHECK_RESULT(ParseEndLabelOpt(expr->block.label));
2930
197
      *out_expr = std::move(expr);
2931
197
      break;
2932
197
    }
2933
2934
1.41k
    case TokenType::Loop: {
2935
1.41k
      Consume();
2936
1.41k
      auto expr = std::make_unique<LoopExpr>(loc);
2937
1.41k
      CHECK_RESULT(ParseLabelOpt(&expr->block.label));
2938
1.41k
      CHECK_RESULT(ParseBlock(&expr->block));
2939
906
      EXPECT(End);
2940
194
      CHECK_RESULT(ParseEndLabelOpt(expr->block.label));
2941
194
      *out_expr = std::move(expr);
2942
194
      break;
2943
194
    }
2944
2945
21.8k
    case TokenType::If: {
2946
21.8k
      Consume();
2947
21.8k
      auto expr = std::make_unique<IfExpr>(loc);
2948
21.8k
      CHECK_RESULT(ParseLabelOpt(&expr->true_.label));
2949
21.8k
      CHECK_RESULT(ParseBlock(&expr->true_));
2950
11.0k
      if (Match(TokenType::Else)) {
2951
1.67k
        CHECK_RESULT(ParseEndLabelOpt(expr->true_.label));
2952
1.67k
        CHECK_RESULT(ParseTerminatingInstrList(&expr->false_));
2953
368
        expr->false_end_loc = GetLocation();
2954
368
      }
2955
9.71k
      EXPECT(End);
2956
4.31k
      CHECK_RESULT(ParseEndLabelOpt(expr->true_.label));
2957
4.31k
      *out_expr = std::move(expr);
2958
4.31k
      break;
2959
4.31k
    }
2960
2961
21.2k
    case TokenType::Try: {
2962
21.2k
      ErrorUnlessOpcodeEnabled(Consume());
2963
21.2k
      auto expr = std::make_unique<TryExpr>(loc);
2964
21.2k
      CatchVector catches;
2965
21.2k
      CHECK_RESULT(ParseLabelOpt(&expr->block.label));
2966
21.2k
      CHECK_RESULT(ParseBlock(&expr->block));
2967
19.4k
      if (IsCatch(Peek())) {
2968
1.87k
        CHECK_RESULT(ParseCatchInstrList(&expr->catches));
2969
625
        expr->kind = TryKind::Catch;
2970
17.5k
      } else if (PeekMatch(TokenType::Delegate)) {
2971
0
        Consume();
2972
0
        Var var;
2973
0
        CHECK_RESULT(ParseVar(&var));
2974
0
        expr->delegate_target = var;
2975
0
        expr->kind = TryKind::Delegate;
2976
0
      }
2977
18.1k
      CHECK_RESULT(ErrorIfLpar({"a valid try clause"}));
2978
13.8k
      expr->block.end_loc = GetLocation();
2979
13.8k
      if (expr->kind != TryKind::Delegate) {
2980
13.8k
        EXPECT(End);
2981
13.8k
      }
2982
743
      CHECK_RESULT(ParseEndLabelOpt(expr->block.label));
2983
743
      *out_expr = std::move(expr);
2984
743
      break;
2985
743
    }
2986
2987
0
    default:
2988
0
      assert(
2989
0
          !"ParseBlockInstr should only be called when IsBlockInstr() is true");
2990
0
      return Result::Error;
2991
46.8k
  }
2992
2993
5.45k
  return Result::Ok;
2994
46.8k
}
2995
2996
223k
Result WastParser::ParseLabelOpt(std::string* out_label) {
2997
223k
  WABT_TRACE(ParseLabelOpt);
2998
223k
  if (PeekMatch(TokenType::Var)) {
2999
13.9k
    *out_label = std::string(Consume().text());
3000
209k
  } else {
3001
209k
    out_label->clear();
3002
209k
  }
3003
223k
  return Result::Ok;
3004
223k
}
3005
3006
7.13k
Result WastParser::ParseEndLabelOpt(const std::string& begin_label) {
3007
7.13k
  WABT_TRACE(ParseEndLabelOpt);
3008
7.13k
  Location loc = GetLocation();
3009
7.13k
  std::string end_label;
3010
7.13k
  CHECK_RESULT(ParseLabelOpt(&end_label));
3011
7.13k
  if (!end_label.empty()) {
3012
2.63k
    if (begin_label.empty()) {
3013
412
      Error(loc, "unexpected label \"%s\"", end_label.c_str());
3014
2.22k
    } else if (begin_label != end_label) {
3015
1.88k
      Error(loc, "mismatching label \"%s\" != \"%s\"", begin_label.c_str(),
3016
1.88k
            end_label.c_str());
3017
1.88k
    }
3018
2.63k
  }
3019
7.13k
  return Result::Ok;
3020
7.13k
}
3021
3022
216k
Result WastParser::ParseBlockDeclaration(BlockDeclaration* decl) {
3023
216k
  WABT_TRACE(ParseBlockDeclaration);
3024
216k
  FuncDeclaration func_decl;
3025
216k
  CHECK_RESULT(ParseTypeUseOpt(&func_decl));
3026
207k
  CHECK_RESULT(ParseUnboundFuncSignature(&func_decl.sig));
3027
206k
  decl->has_func_type = func_decl.has_func_type;
3028
206k
  decl->type_var = func_decl.type_var;
3029
206k
  decl->sig = func_decl.sig;
3030
206k
  return Result::Ok;
3031
207k
}
3032
3033
118k
Result WastParser::ParseBlock(Block* block) {
3034
118k
  WABT_TRACE(ParseBlock);
3035
118k
  CHECK_RESULT(ParseBlockDeclaration(&block->decl));
3036
115k
  CHECK_RESULT(ParseInstrList(&block->exprs));
3037
90.4k
  block->end_loc = GetLocation();
3038
90.4k
  return Result::Ok;
3039
115k
}
3040
3041
494k
Result WastParser::ParseExprList(ExprList* exprs) {
3042
494k
  WABT_TRACE(ParseExprList);
3043
494k
  ExprList new_exprs;
3044
815k
  while (PeekMatchExpr()) {
3045
426k
    if (Succeeded(ParseExpr(&new_exprs))) {
3046
151k
      exprs->splice(exprs->end(), new_exprs);
3047
274k
    } else {
3048
274k
      CHECK_RESULT(Synchronize(IsExpr));
3049
274k
    }
3050
426k
  }
3051
389k
  return Result::Ok;
3052
494k
}
3053
3054
762k
Result WastParser::ParseExpr(ExprList* exprs) {
3055
762k
  WABT_TRACE(ParseExpr);
3056
762k
  if (!PeekMatch(TokenType::Lpar)) {
3057
0
    return Result::Error;
3058
0
  }
3059
3060
762k
  if (IsPlainInstr(Peek(1))) {
3061
592k
    Consume();
3062
592k
    std::unique_ptr<Expr> expr;
3063
592k
    CHECK_RESULT(ParsePlainInstr(&expr));
3064
494k
    CHECK_RESULT(ParseExprList(exprs));
3065
389k
    CHECK_RESULT(ErrorIfLpar({"an expr"}));
3066
241k
    exprs->push_back(std::move(expr));
3067
241k
  } else {
3068
169k
    Location loc = GetLocation();
3069
3070
169k
    switch (Peek(1)) {
3071
14.0k
      case TokenType::Block: {
3072
14.0k
        Consume();
3073
14.0k
        Consume();
3074
14.0k
        auto expr = std::make_unique<BlockExpr>(loc);
3075
14.0k
        CHECK_RESULT(ParseLabelOpt(&expr->block.label));
3076
14.0k
        CHECK_RESULT(ParseBlock(&expr->block));
3077
12.6k
        exprs->push_back(std::move(expr));
3078
12.6k
        break;
3079
14.0k
      }
3080
3081
57.7k
      case TokenType::Loop: {
3082
57.7k
        Consume();
3083
57.7k
        Consume();
3084
57.7k
        auto expr = std::make_unique<LoopExpr>(loc);
3085
57.7k
        CHECK_RESULT(ParseLabelOpt(&expr->block.label));
3086
57.7k
        CHECK_RESULT(ParseBlock(&expr->block));
3087
45.0k
        exprs->push_back(std::move(expr));
3088
45.0k
        break;
3089
57.7k
      }
3090
3091
84.7k
      case TokenType::If: {
3092
84.7k
        Consume();
3093
84.7k
        Consume();
3094
84.7k
        auto expr = std::make_unique<IfExpr>(loc);
3095
3096
84.7k
        CHECK_RESULT(ParseLabelOpt(&expr->true_.label));
3097
84.7k
        CHECK_RESULT(ParseBlockDeclaration(&expr->true_.decl));
3098
3099
82.3k
        while (PeekMatchExpr()) {
3100
62.6k
          ExprList cond;
3101
62.6k
          CHECK_RESULT(ParseExpr(&cond));
3102
4.05k
          exprs->splice(exprs->end(), cond);
3103
4.05k
        }
3104
3105
19.6k
        EXPECT(Lpar);
3106
17.5k
        if (!Match(TokenType::Then)) {
3107
13.2k
          return ErrorExpected({"then block"}, "(then ...)");
3108
13.2k
        }
3109
3110
4.27k
        CHECK_RESULT(ParseTerminatingInstrList(&expr->true_.exprs));
3111
1.90k
        expr->true_.end_loc = GetLocation();
3112
1.90k
        EXPECT(Rpar);
3113
3114
1.30k
        if (MatchLpar(TokenType::Else)) {
3115
726
          CHECK_RESULT(ParseTerminatingInstrList(&expr->false_));
3116
531
          EXPECT(Rpar);
3117
531
        }
3118
902
        expr->false_end_loc = GetLocation();
3119
3120
902
        exprs->push_back(std::move(expr));
3121
902
        break;
3122
1.30k
      }
3123
3124
12.8k
      case TokenType::Try: {
3125
12.8k
        Consume();
3126
12.8k
        ErrorUnlessOpcodeEnabled(Consume());
3127
3128
12.8k
        auto expr = std::make_unique<TryExpr>(loc);
3129
12.8k
        CHECK_RESULT(ParseLabelOpt(&expr->block.label));
3130
12.8k
        CHECK_RESULT(ParseBlockDeclaration(&expr->block.decl));
3131
12.4k
        EXPECT(Lpar);
3132
11.4k
        EXPECT(Do);
3133
7.45k
        CHECK_RESULT(ParseInstrList(&expr->block.exprs));
3134
7.22k
        EXPECT(Rpar);
3135
6.92k
        if (PeekMatch(TokenType::Lpar)) {
3136
5.64k
          Consume();
3137
5.64k
          TokenType type = Peek();
3138
5.64k
          switch (type) {
3139
2.88k
            case TokenType::Catch:
3140
3.72k
            case TokenType::CatchAll:
3141
3.72k
              CHECK_RESULT(ParseCatchExprList(&expr->catches));
3142
1.65k
              expr->kind = TryKind::Catch;
3143
1.65k
              break;
3144
0
            case TokenType::Delegate: {
3145
0
              Consume();
3146
0
              Var var;
3147
0
              CHECK_RESULT(ParseVar(&var));
3148
0
              expr->delegate_target = var;
3149
0
              expr->kind = TryKind::Delegate;
3150
0
              EXPECT(Rpar);
3151
0
              break;
3152
0
            }
3153
1.92k
            default:
3154
1.92k
              ErrorExpected({"catch", "catch_all", "delegate"});
3155
1.92k
              break;
3156
5.64k
          }
3157
5.64k
        }
3158
4.86k
        CHECK_RESULT(ErrorIfLpar({"a valid try clause"}));
3159
4.56k
        expr->block.end_loc = GetLocation();
3160
4.56k
        exprs->push_back(std::move(expr));
3161
4.56k
        break;
3162
4.86k
      }
3163
3164
0
      default:
3165
0
        assert(!"ParseExpr should only be called when IsExpr() is true");
3166
0
        return Result::Error;
3167
169k
    }
3168
169k
  }
3169
3170
304k
  EXPECT(Rpar);
3171
179k
  return Result::Ok;
3172
304k
}
3173
3174
1.87k
Result WastParser::ParseCatchInstrList(CatchVector* catches) {
3175
1.87k
  WABT_TRACE(ParseCatchInstrList);
3176
1.87k
  bool parsedCatch = false;
3177
1.87k
  bool parsedCatchAll = false;
3178
3179
3.99k
  while (IsCatch(Peek())) {
3180
3.37k
    Catch catch_(GetLocation());
3181
3182
3.37k
    auto token = Consume();
3183
3.37k
    if (token.token_type() == TokenType::Catch) {
3184
2.63k
      CHECK_RESULT(ParseVar(&catch_.var));
3185
2.63k
    } else {
3186
738
      if (parsedCatchAll) {
3187
199
        Error(token.loc, "multiple catch_all clauses not allowed");
3188
199
        return Result::Error;
3189
199
      }
3190
539
      parsedCatchAll = true;
3191
539
    }
3192
3193
2.95k
    CHECK_RESULT(ParseInstrList(&catch_.exprs));
3194
2.12k
    catches->push_back(std::move(catch_));
3195
2.12k
    parsedCatch = true;
3196
2.12k
  }
3197
3198
625
  if (!parsedCatch) {
3199
0
    return ErrorExpected({"catch"});
3200
0
  }
3201
3202
625
  return Result::Ok;
3203
625
}
3204
3205
3.72k
Result WastParser::ParseCatchExprList(CatchVector* catches) {
3206
3.72k
  WABT_TRACE(ParseCatchExprList);
3207
3.72k
  bool parsedCatchAll = false;
3208
3209
22.8k
  do {
3210
22.8k
    Catch catch_(GetLocation());
3211
3212
22.8k
    auto token = Consume();
3213
22.8k
    if (token.token_type() == TokenType::Catch) {
3214
21.7k
      CHECK_RESULT(ParseVar(&catch_.var));
3215
21.7k
    } else {
3216
1.10k
      if (parsedCatchAll) {
3217
270
        Error(token.loc, "multiple catch_all clauses not allowed");
3218
270
        return Result::Error;
3219
270
      }
3220
839
      parsedCatchAll = true;
3221
839
    }
3222
3223
22.3k
    CHECK_RESULT(ParseTerminatingInstrList(&catch_.exprs));
3224
21.4k
    EXPECT(Rpar);
3225
20.8k
    catches->push_back(std::move(catch_));
3226
20.8k
  } while (Match(TokenType::Lpar) && IsCatch(Peek()));
3227
3228
1.65k
  return Result::Ok;
3229
3.72k
}
3230
3231
68.7k
Result WastParser::ParseGlobalType(Global* global) {
3232
68.7k
  WABT_TRACE(ParseGlobalType);
3233
68.7k
  if (MatchLpar(TokenType::Mut)) {
3234
1.40k
    global->mutable_ = true;
3235
1.40k
    Var type;
3236
1.40k
    CHECK_RESULT(ParseValueType(&type));
3237
1.11k
    global->type = Type(type.index());
3238
1.11k
    CHECK_RESULT(ErrorIfLpar({"i32", "i64", "f32", "f64"}));
3239
851
    EXPECT(Rpar);
3240
67.3k
  } else {
3241
67.3k
    Var type;
3242
67.3k
    CHECK_RESULT(ParseValueType(&type));
3243
56.7k
    global->type = Type(type.index());
3244
56.7k
  }
3245
3246
56.9k
  return Result::Ok;
3247
68.7k
}
3248
3249
Result WastParser::ParseCommandList(Script* script,
3250
0
                                    CommandPtrVector* commands) {
3251
0
  WABT_TRACE(ParseCommandList);
3252
0
  while (IsCommand(PeekPair())) {
3253
0
    CommandPtr command;
3254
0
    if (Succeeded(ParseCommand(script, &command))) {
3255
0
      commands->push_back(std::move(command));
3256
0
    } else {
3257
0
      CHECK_RESULT(Synchronize(IsCommand));
3258
0
    }
3259
0
  }
3260
0
  return Result::Ok;
3261
0
}
3262
3263
0
Result WastParser::ParseCommand(Script* script, CommandPtr* out_command) {
3264
0
  WABT_TRACE(ParseCommand);
3265
0
  switch (Peek(1)) {
3266
0
    case TokenType::AssertException:
3267
0
      return ParseAssertExceptionCommand(out_command);
3268
3269
0
    case TokenType::AssertExhaustion:
3270
0
      return ParseAssertExhaustionCommand(out_command);
3271
3272
0
    case TokenType::AssertInvalid:
3273
0
      return ParseAssertInvalidCommand(out_command);
3274
3275
0
    case TokenType::AssertMalformed:
3276
0
      return ParseAssertMalformedCommand(out_command);
3277
3278
0
    case TokenType::AssertReturn:
3279
0
      return ParseAssertReturnCommand(out_command);
3280
3281
0
    case TokenType::AssertTrap:
3282
0
      return ParseAssertTrapCommand(out_command);
3283
3284
0
    case TokenType::AssertUnlinkable:
3285
0
      return ParseAssertUnlinkableCommand(out_command);
3286
3287
0
    case TokenType::Get:
3288
0
    case TokenType::Invoke:
3289
0
      return ParseActionCommand(out_command);
3290
3291
0
    case TokenType::Module:
3292
0
      return ParseModuleCommand(script, out_command);
3293
3294
0
    case TokenType::Register:
3295
0
      return ParseRegisterCommand(out_command);
3296
3297
0
    case TokenType::Input:
3298
0
      return ParseInputCommand(out_command);
3299
3300
0
    case TokenType::Output:
3301
0
      return ParseOutputCommand(out_command);
3302
3303
0
    default:
3304
0
      assert(!"ParseCommand should only be called when IsCommand() is true");
3305
0
      return Result::Error;
3306
0
  }
3307
0
}
3308
3309
0
Result WastParser::ParseAssertExceptionCommand(CommandPtr* out_command) {
3310
0
  WABT_TRACE(ParseAssertExceptionCommand);
3311
0
  return ParseAssertActionCommand<AssertExceptionCommand>(
3312
0
      TokenType::AssertException, out_command);
3313
0
}
3314
3315
0
Result WastParser::ParseAssertExhaustionCommand(CommandPtr* out_command) {
3316
0
  WABT_TRACE(ParseAssertExhaustionCommand);
3317
0
  return ParseAssertActionTextCommand<AssertExhaustionCommand>(
3318
0
      TokenType::AssertExhaustion, out_command);
3319
0
}
3320
3321
0
Result WastParser::ParseAssertInvalidCommand(CommandPtr* out_command) {
3322
0
  WABT_TRACE(ParseAssertInvalidCommand);
3323
0
  return ParseAssertScriptModuleCommand<AssertInvalidCommand>(
3324
0
      TokenType::AssertInvalid, out_command);
3325
0
}
3326
3327
0
Result WastParser::ParseAssertMalformedCommand(CommandPtr* out_command) {
3328
0
  WABT_TRACE(ParseAssertMalformedCommand);
3329
0
  return ParseAssertScriptModuleCommand<AssertMalformedCommand>(
3330
0
      TokenType::AssertMalformed, out_command);
3331
0
}
3332
3333
0
Result WastParser::ParseAssertReturnCommand(CommandPtr* out_command) {
3334
0
  WABT_TRACE(ParseAssertReturnCommand);
3335
0
  EXPECT(Lpar);
3336
0
  EXPECT(AssertReturn);
3337
0
  auto command = std::make_unique<AssertReturnCommand>();
3338
0
  CHECK_RESULT(ParseAction(&command->action));
3339
0
  CHECK_RESULT(ParseExpectedValues(&command->expected));
3340
0
  EXPECT(Rpar);
3341
0
  *out_command = std::move(command);
3342
0
  return Result::Ok;
3343
0
}
3344
3345
0
Result WastParser::ParseAssertTrapCommand(CommandPtr* out_command) {
3346
0
  WABT_TRACE(ParseAssertTrapCommand);
3347
0
  EXPECT(Lpar);
3348
0
  EXPECT(AssertTrap);
3349
0
  if (PeekMatchLpar(TokenType::Module)) {
3350
0
    auto command = std::make_unique<AssertUninstantiableCommand>();
3351
0
    CHECK_RESULT(ParseScriptModule(&command->module));
3352
0
    CHECK_RESULT(ParseQuotedText(&command->text));
3353
0
    *out_command = std::move(command);
3354
0
  } else {
3355
0
    auto command = std::make_unique<AssertTrapCommand>();
3356
0
    CHECK_RESULT(ParseAction(&command->action));
3357
0
    CHECK_RESULT(ParseQuotedText(&command->text));
3358
0
    *out_command = std::move(command);
3359
0
  }
3360
0
  EXPECT(Rpar);
3361
0
  return Result::Ok;
3362
0
}
3363
3364
0
Result WastParser::ParseAssertUnlinkableCommand(CommandPtr* out_command) {
3365
0
  WABT_TRACE(ParseAssertUnlinkableCommand);
3366
0
  return ParseAssertScriptModuleCommand<AssertUnlinkableCommand>(
3367
0
      TokenType::AssertUnlinkable, out_command);
3368
0
}
3369
3370
0
Result WastParser::ParseActionCommand(CommandPtr* out_command) {
3371
0
  WABT_TRACE(ParseActionCommand);
3372
0
  auto command = std::make_unique<ActionCommand>();
3373
0
  CHECK_RESULT(ParseAction(&command->action));
3374
0
  *out_command = std::move(command);
3375
0
  return Result::Ok;
3376
0
}
3377
3378
128
Result WastParser::ParseModuleCommand(Script* script, CommandPtr* out_command) {
3379
128
  WABT_TRACE(ParseModuleCommand);
3380
128
  std::unique_ptr<ScriptModule> script_module;
3381
128
  CHECK_RESULT(ParseScriptModule(&script_module));
3382
3383
71
  Module* module = nullptr;
3384
3385
71
  switch (script_module->type()) {
3386
71
    case ScriptModuleType::Text: {
3387
71
      auto command = std::make_unique<ModuleCommand>();
3388
71
      module = &command->module;
3389
71
      *module = std::move(cast<TextScriptModule>(script_module.get())->module);
3390
71
      *out_command = std::move(command);
3391
71
      break;
3392
0
    }
3393
3394
0
    case ScriptModuleType::Binary: {
3395
0
      auto command = std::make_unique<ScriptModuleCommand>();
3396
0
      module = &command->module;
3397
0
      auto* bsm = cast<BinaryScriptModule>(script_module.get());
3398
0
      ReadBinaryOptions options;
3399
#if WABT_TRACING
3400
      auto log_stream = FileStream::CreateStdout();
3401
      options.log_stream = log_stream.get();
3402
#endif
3403
0
      options.features = options_->features;
3404
0
      Errors errors;
3405
0
      const char* filename = "<text>";
3406
0
      ReadBinaryIr(filename, bsm->data.data(), bsm->data.size(), options,
3407
0
                   &errors, module);
3408
0
      module->name = bsm->name;
3409
0
      module->loc = bsm->loc;
3410
0
      for (const auto& error : errors) {
3411
0
        if (error.loc.offset == kInvalidOffset) {
3412
0
          Error(bsm->loc, "error in binary module: %s", error.message.c_str());
3413
0
        } else {
3414
0
          Error(bsm->loc, "error in binary module: @0x%08" PRIzx ": %s",
3415
0
                error.loc.offset, error.message.c_str());
3416
0
        }
3417
0
      }
3418
3419
0
      command->script_module = std::move(script_module);
3420
0
      *out_command = std::move(command);
3421
0
      break;
3422
0
    }
3423
3424
0
    case ScriptModuleType::Quoted:
3425
0
      auto command = std::make_unique<ModuleCommand>();
3426
0
      module = &command->module;
3427
0
      auto* qsm = cast<QuotedScriptModule>(script_module.get());
3428
0
      Errors errors;
3429
0
      const char* filename = "<text>";
3430
0
      std::unique_ptr<Module> m;
3431
0
      std::unique_ptr<WastLexer> lexer = WastLexer::CreateBufferLexer(
3432
0
          filename, qsm->data.data(), qsm->data.size(), &errors);
3433
0
      ParseWatModule(lexer.get(), &m, &errors, options_);
3434
0
      for (const auto& error : errors) {
3435
0
        if (error.loc.offset == kInvalidOffset) {
3436
0
          Error(qsm->loc, "error in quoted module: %s", error.message.c_str());
3437
0
        } else {
3438
0
          Error(qsm->loc, "error in quoted module: @0x%08" PRIzx ": %s",
3439
0
                error.loc.offset, error.message.c_str());
3440
0
        }
3441
0
      }
3442
0
      *module = std::move(*m.get());
3443
0
      *out_command = std::move(command);
3444
0
      break;
3445
71
  }
3446
3447
  // script is nullptr when ParseModuleCommand is called from ParseModule.
3448
71
  if (script) {
3449
0
    Index command_index = script->commands.size();
3450
3451
0
    if (!module->name.empty()) {
3452
0
      script->module_bindings.emplace(module->name,
3453
0
                                      Binding(module->loc, command_index));
3454
0
    }
3455
3456
0
    last_module_index_ = command_index;
3457
0
  }
3458
3459
71
  return Result::Ok;
3460
71
}
3461
3462
0
Result WastParser::ParseRegisterCommand(CommandPtr* out_command) {
3463
0
  WABT_TRACE(ParseRegisterCommand);
3464
0
  EXPECT(Lpar);
3465
0
  Location loc = GetLocation();
3466
0
  EXPECT(Register);
3467
0
  std::string text;
3468
0
  Var var;
3469
0
  CHECK_RESULT(ParseQuotedText(&text));
3470
0
  ParseVarOpt(&var, Var(last_module_index_, loc));
3471
0
  EXPECT(Rpar);
3472
0
  out_command->reset(new RegisterCommand(text, var));
3473
0
  return Result::Ok;
3474
0
}
3475
3476
0
Result WastParser::ParseInputCommand(CommandPtr*) {
3477
  // Parse the input command, but always fail since this command is not
3478
  // actually supported.
3479
0
  WABT_TRACE(ParseInputCommand);
3480
0
  EXPECT(Lpar);
3481
0
  Location loc = GetLocation();
3482
0
  EXPECT(Input);
3483
0
  Error(loc, "input command is not supported");
3484
0
  Var var;
3485
0
  std::string text;
3486
0
  ParseVarOpt(&var);
3487
0
  CHECK_RESULT(ParseQuotedText(&text));
3488
0
  EXPECT(Rpar);
3489
0
  return Result::Error;
3490
0
}
3491
3492
0
Result WastParser::ParseOutputCommand(CommandPtr*) {
3493
  // Parse the output command, but always fail since this command is not
3494
  // actually supported.
3495
0
  WABT_TRACE(ParseOutputCommand);
3496
0
  EXPECT(Lpar);
3497
0
  Location loc = GetLocation();
3498
0
  EXPECT(Output);
3499
0
  Error(loc, "output command is not supported");
3500
0
  Var var;
3501
0
  std::string text;
3502
0
  ParseVarOpt(&var);
3503
0
  if (Peek() == TokenType::Text) {
3504
0
    CHECK_RESULT(ParseQuotedText(&text));
3505
0
  }
3506
0
  EXPECT(Rpar);
3507
0
  return Result::Error;
3508
0
}
3509
3510
0
Result WastParser::ParseAction(ActionPtr* out_action) {
3511
0
  WABT_TRACE(ParseAction);
3512
0
  EXPECT(Lpar);
3513
0
  Location loc = GetLocation();
3514
3515
0
  switch (Peek()) {
3516
0
    case TokenType::Invoke: {
3517
0
      Consume();
3518
0
      auto action = std::make_unique<InvokeAction>(loc);
3519
0
      ParseVarOpt(&action->module_var, Var(last_module_index_, loc));
3520
0
      CHECK_RESULT(ParseQuotedText(&action->name));
3521
0
      CHECK_RESULT(ParseConstList(&action->args, ConstType::Normal));
3522
0
      *out_action = std::move(action);
3523
0
      break;
3524
0
    }
3525
3526
0
    case TokenType::Get: {
3527
0
      Consume();
3528
0
      auto action = std::make_unique<GetAction>(loc);
3529
0
      ParseVarOpt(&action->module_var, Var(last_module_index_, loc));
3530
0
      CHECK_RESULT(ParseQuotedText(&action->name));
3531
0
      *out_action = std::move(action);
3532
0
      break;
3533
0
    }
3534
3535
0
    default:
3536
0
      return ErrorExpected({"invoke", "get"});
3537
0
  }
3538
0
  EXPECT(Rpar);
3539
0
  return Result::Ok;
3540
0
}
3541
3542
0
Result WastParser::ParseExpectedValues(ExpectationPtr* expectation) {
3543
0
  WABT_TRACE(ParseExpectedValues);
3544
0
  Location loc = GetLocation();
3545
0
  if (PeekMatchLpar(TokenType::Either)) {
3546
0
    auto either = std::make_unique<EitherExpectation>(loc);
3547
0
    CHECK_RESULT(ParseEither(&either->expected));
3548
0
    *expectation = std::move(either);
3549
0
  } else {
3550
0
    auto values = std::make_unique<ValueExpectation>(loc);
3551
0
    CHECK_RESULT(ParseConstList(&values->expected, ConstType::Expectation));
3552
0
    *expectation = std::move(values);
3553
0
  }
3554
0
  return Result::Ok;
3555
0
}
3556
3557
0
Result WastParser::ParseEither(ConstVector* alternatives) {
3558
0
  WABT_TRACE(ParseEither);
3559
0
  MatchLpar(TokenType::Either);
3560
0
  CHECK_RESULT(ParseConstList(alternatives, ConstType::Expectation));
3561
0
  EXPECT(Rpar);
3562
0
  return Result::Ok;
3563
0
}
3564
3565
Result WastParser::ParseScriptModule(
3566
128
    std::unique_ptr<ScriptModule>* out_module) {
3567
128
  WABT_TRACE(ParseScriptModule);
3568
128
  EXPECT(Lpar);
3569
128
  Location loc = GetLocation();
3570
128
  EXPECT(Module);
3571
128
  std::string name;
3572
128
  ParseBindVarOpt(&name);
3573
3574
128
  switch (Peek()) {
3575
0
    case TokenType::Bin: {
3576
0
      Consume();
3577
0
      std::vector<uint8_t> data;
3578
      // TODO(binji): The spec allows this to be empty, switch to
3579
      // ParseTextListOpt.
3580
0
      CHECK_RESULT(ParseTextList(&data));
3581
3582
0
      auto bsm = std::make_unique<BinaryScriptModule>();
3583
0
      bsm->name = name;
3584
0
      bsm->loc = loc;
3585
0
      bsm->data = std::move(data);
3586
0
      *out_module = std::move(bsm);
3587
0
      break;
3588
0
    }
3589
3590
0
    case TokenType::Quote: {
3591
0
      Consume();
3592
0
      std::vector<uint8_t> data;
3593
      // TODO(binji): The spec allows this to be empty, switch to
3594
      // ParseTextListOpt.
3595
0
      CHECK_RESULT(ParseTextList(&data));
3596
3597
0
      auto qsm = std::make_unique<QuotedScriptModule>();
3598
0
      qsm->name = name;
3599
0
      qsm->loc = loc;
3600
0
      qsm->data = std::move(data);
3601
0
      *out_module = std::move(qsm);
3602
0
      break;
3603
0
    }
3604
3605
128
    default: {
3606
128
      auto tsm = std::make_unique<TextScriptModule>();
3607
128
      tsm->module.name = name;
3608
128
      tsm->module.loc = loc;
3609
128
      if (IsModuleField(PeekPair()) || PeekIsCustom()) {
3610
113
        CHECK_RESULT(ParseModuleFieldList(&tsm->module));
3611
113
      } else if (!PeekMatch(TokenType::Rpar)) {
3612
14
        ConsumeIfLpar();
3613
14
        return ErrorExpected({"a module field"});
3614
14
      }
3615
72
      *out_module = std::move(tsm);
3616
72
      break;
3617
128
    }
3618
128
  }
3619
3620
72
  EXPECT(Rpar);
3621
71
  return Result::Ok;
3622
72
}
3623
3624
template <typename T>
3625
Result WastParser::ParseAssertActionCommand(TokenType token_type,
3626
0
                                            CommandPtr* out_command) {
3627
0
  WABT_TRACE(ParseAssertActionCommand);
3628
0
  EXPECT(Lpar);
3629
0
  CHECK_RESULT(Expect(token_type));
3630
0
  auto command = std::make_unique<T>();
3631
0
  CHECK_RESULT(ParseAction(&command->action));
3632
0
  EXPECT(Rpar);
3633
0
  *out_command = std::move(command);
3634
0
  return Result::Ok;
3635
0
}
3636
3637
template <typename T>
3638
Result WastParser::ParseAssertActionTextCommand(TokenType token_type,
3639
0
                                                CommandPtr* out_command) {
3640
0
  WABT_TRACE(ParseAssertActionTextCommand);
3641
0
  EXPECT(Lpar);
3642
0
  CHECK_RESULT(Expect(token_type));
3643
0
  auto command = std::make_unique<T>();
3644
0
  CHECK_RESULT(ParseAction(&command->action));
3645
0
  CHECK_RESULT(ParseQuotedText(&command->text));
3646
0
  EXPECT(Rpar);
3647
0
  *out_command = std::move(command);
3648
0
  return Result::Ok;
3649
0
}
3650
3651
template <typename T>
3652
Result WastParser::ParseAssertScriptModuleCommand(TokenType token_type,
3653
0
                                                  CommandPtr* out_command) {
3654
0
  WABT_TRACE(ParseAssertScriptModuleCommand);
3655
0
  EXPECT(Lpar);
3656
0
  CHECK_RESULT(Expect(token_type));
3657
0
  auto command = std::make_unique<T>();
3658
0
  CHECK_RESULT(ParseScriptModule(&command->module));
3659
0
  CHECK_RESULT(ParseQuotedText(&command->text));
3660
0
  EXPECT(Rpar);
3661
0
  *out_command = std::move(command);
3662
0
  return Result::Ok;
3663
0
}
Unexecuted instantiation: wabt::Result wabt::WastParser::ParseAssertScriptModuleCommand<wabt::AssertModuleCommand<(wabt::CommandType)5> >(wabt::TokenType, std::__1::unique_ptr<wabt::Command, std::__1::default_delete<wabt::Command> >*)
Unexecuted instantiation: wabt::Result wabt::WastParser::ParseAssertScriptModuleCommand<wabt::AssertModuleCommand<(wabt::CommandType)4> >(wabt::TokenType, std::__1::unique_ptr<wabt::Command, std::__1::default_delete<wabt::Command> >*)
Unexecuted instantiation: wabt::Result wabt::WastParser::ParseAssertScriptModuleCommand<wabt::AssertModuleCommand<(wabt::CommandType)6> >(wabt::TokenType, std::__1::unique_ptr<wabt::Command, std::__1::default_delete<wabt::Command> >*)
3664
3665
175k
void WastParser::CheckImportOrdering(Module* module) {
3666
175k
  if (module->funcs.size() != module->num_func_imports ||
3667
175k
      module->tables.size() != module->num_table_imports ||
3668
175k
      module->memories.size() != module->num_memory_imports ||
3669
175k
      module->globals.size() != module->num_global_imports ||
3670
175k
      module->tags.size() != module->num_tag_imports) {
3671
77.1k
    Error(GetLocation(),
3672
77.1k
          "imports must occur before all non-import definitions");
3673
77.1k
  }
3674
175k
}
3675
3676
3.38k
bool WastParser::HasError() const {
3677
3.38k
  return std::any_of(errors_->begin(), errors_->end(), [](const auto& x) {
3678
2.39k
    return x.error_level == ErrorLevel::Error;
3679
2.39k
  });
3680
3.38k
}
3681
3682
24.8M
void WastParser::TokenQueue::push_back(Token t) {
3683
24.8M
  assert(!tokens[!i]);
3684
24.8M
  tokens[!i] = t;
3685
24.8M
  if (empty()) {
3686
10.8M
    i = !i;
3687
10.8M
  }
3688
24.8M
}
3689
3690
24.8M
void WastParser::TokenQueue::pop_front() {
3691
24.8M
  assert(tokens[i]);
3692
24.8M
  tokens[i].reset();
3693
24.8M
  i = !i;
3694
24.8M
}
3695
3696
121M
const Token& WastParser::TokenQueue::at(size_t n) const {
3697
121M
  assert(n <= 1);
3698
121M
  return tokens[i ^ static_cast<bool>(n)].value();
3699
121M
}
3700
3701
33.7M
const Token& WastParser::TokenQueue::front() const {
3702
33.7M
  return at(0);
3703
33.7M
}
3704
3705
171M
bool WastParser::TokenQueue::empty() const {
3706
171M
  return !tokens[i];
3707
171M
}
3708
3709
112M
size_t WastParser::TokenQueue::size() const {
3710
112M
  return empty() ? 0 : 1 + tokens[!i].has_value();
3711
112M
}
3712
3713
Result ParseWatModule(WastLexer* lexer,
3714
                      std::unique_ptr<Module>* out_module,
3715
                      Errors* errors,
3716
22.7k
                      WastParseOptions* options) {
3717
22.7k
  assert(out_module != nullptr);
3718
22.7k
  assert(options != nullptr);
3719
22.7k
  WastParser parser(lexer, errors, options);
3720
22.7k
  CHECK_RESULT(parser.ParseModule(out_module));
3721
1.66k
  return Result::Ok;
3722
22.7k
}
3723
3724
Result ParseWastScript(WastLexer* lexer,
3725
                       std::unique_ptr<Script>* out_script,
3726
                       Errors* errors,
3727
0
                       WastParseOptions* options) {
3728
0
  assert(out_script != nullptr);
3729
0
  assert(options != nullptr);
3730
0
  WastParser parser(lexer, errors, options);
3731
0
  CHECK_RESULT(parser.ParseScript(out_script));
3732
0
  CHECK_RESULT(ResolveNamesScript(out_script->get(), errors));
3733
0
  return Result::Ok;
3734
0
}
3735
3736
}  // namespace wabt