Source code

Revision control

Other Tools

1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2
* vim: set ts=8 sts=2 et sw=2 tw=80:
3
*
4
* Copyright 2015 Mozilla Foundation
5
*
6
* Licensed under the Apache License, Version 2.0 (the "License");
7
* you may not use this file except in compliance with the License.
8
* You may obtain a copy of the License at
9
*
11
*
12
* Unless required by applicable law or agreed to in writing, software
13
* distributed under the License is distributed on an "AS IS" BASIS,
14
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
* See the License for the specific language governing permissions and
16
* limitations under the License.
17
*/
18
19
#include "wasm/WasmTextToBinary.h"
20
21
#include "mozilla/CheckedInt.h"
22
#include "mozilla/MathAlgorithms.h"
23
#include "mozilla/Maybe.h"
24
#include "mozilla/Sprintf.h"
25
26
#include "jsnum.h"
27
28
#include "ds/LifoAlloc.h"
29
#include "js/CharacterEncoding.h"
30
#include "js/HashTable.h"
31
#include "js/Printf.h"
32
#include "util/DoubleToString.h"
33
#include "util/Memory.h"
34
#include "wasm/WasmAST.h"
35
#include "wasm/WasmTypes.h"
36
#include "wasm/WasmValidate.h"
37
38
using namespace js;
39
using namespace js::wasm;
40
41
using mozilla::BitwiseCast;
42
using mozilla::CeilingLog2;
43
using mozilla::CheckedInt;
44
using mozilla::CountLeadingZeroes32;
45
using mozilla::FloatingPoint;
46
using mozilla::IsPowerOfTwo;
47
using mozilla::Maybe;
48
using mozilla::PositiveInfinity;
49
50
/*****************************************************************************/
51
// wasm text token stream
52
53
namespace {
54
55
class WasmToken {
56
public:
57
enum FloatLiteralKind { HexNumber, DecNumber, Infinity, NaN };
58
59
enum Kind {
60
Align,
61
AtomicCmpXchg,
62
AtomicLoad,
63
AtomicRMW,
64
AtomicStore,
65
BinaryOpcode,
66
Block,
67
Br,
68
BrIf,
69
BrTable,
70
Call,
71
CallIndirect,
72
CloseParen,
73
ComparisonOpcode,
74
Const,
75
ConversionOpcode,
76
Data,
77
DataCount,
78
DataDrop,
79
Declared,
80
Drop,
81
Elem,
82
Else,
83
End,
84
EndOfFile,
85
Equal,
86
Error,
87
Export,
88
ExtraConversionOpcode,
89
Fence,
90
Field,
91
Float,
92
Func,
93
#ifdef ENABLE_WASM_GC
94
GcFeatureOptIn,
95
#endif
96
GetGlobal,
97
GetLocal,
98
Global,
99
If,
100
Import,
101
Index,
102
Memory,
103
NegativeZero,
104
Load,
105
Local,
106
Loop,
107
MemCopy,
108
MemFill,
109
MemInit,
110
MemoryGrow,
111
MemorySize,
112
Module,
113
Mutable,
114
Name,
115
#ifdef ENABLE_WASM_GC
116
StructNew,
117
StructGet,
118
StructSet,
119
StructNarrow,
120
#endif
121
Nop,
122
Offset,
123
OpenParen,
124
Param,
125
Passive,
126
Ref,
127
RefFunc,
128
RefNull,
129
Result,
130
Return,
131
Select,
132
SetGlobal,
133
SetLocal,
134
Shared,
135
SignedInteger,
136
Start,
137
Struct,
138
Store,
139
Table,
140
TableCopy,
141
ElemDrop,
142
TableInit,
143
#ifdef ENABLE_WASM_REFTYPES
144
TableFill,
145
TableGet,
146
TableGrow,
147
TableSet,
148
TableSize,
149
#endif
150
TeeLocal,
151
Text,
152
Then,
153
Type,
154
UnaryOpcode,
155
Unreachable,
156
UnsignedInteger,
157
ValueType,
158
Wait,
159
Wake,
160
Invalid
161
};
162
private:
163
Kind kind_;
164
const char16_t* begin_;
165
const char16_t* end_;
166
union U {
167
uint32_t index_;
168
uint64_t uint_;
169
int64_t sint_;
170
FloatLiteralKind floatLiteralKind_;
171
ValType valueType_;
172
Op op_;
173
MiscOp miscOp_;
174
ThreadOp threadOp_;
175
U() : index_(0) {}
176
} u;
177
178
public:
179
WasmToken() : kind_(Kind::Invalid), begin_(nullptr), end_(nullptr), u() {}
180
WasmToken(Kind kind, const char16_t* begin, const char16_t* end)
181
: kind_(kind), begin_(begin), end_(end), u{} {
182
MOZ_ASSERT(kind_ != Error);
183
MOZ_ASSERT(kind_ != Invalid);
184
MOZ_ASSERT((kind == EndOfFile) == (begin == end));
185
}
186
explicit WasmToken(uint32_t index, const char16_t* begin, const char16_t* end)
187
: kind_(Index), begin_(begin), end_(end) {
188
MOZ_ASSERT(begin != end);
189
u.index_ = index;
190
}
191
explicit WasmToken(uint64_t uint, const char16_t* begin, const char16_t* end)
192
: kind_(UnsignedInteger), begin_(begin), end_(end) {
193
MOZ_ASSERT(begin != end);
194
u.uint_ = uint;
195
}
196
explicit WasmToken(int64_t sint, const char16_t* begin, const char16_t* end)
197
: kind_(SignedInteger), begin_(begin), end_(end) {
198
MOZ_ASSERT(begin != end);
199
u.sint_ = sint;
200
}
201
explicit WasmToken(FloatLiteralKind floatLiteralKind, const char16_t* begin,
202
const char16_t* end)
203
: kind_(Float), begin_(begin), end_(end) {
204
MOZ_ASSERT(begin != end);
205
u.floatLiteralKind_ = floatLiteralKind;
206
}
207
explicit WasmToken(Kind kind, ValType valueType, const char16_t* begin,
208
const char16_t* end)
209
: kind_(kind), begin_(begin), end_(end) {
210
MOZ_ASSERT(begin != end);
211
MOZ_ASSERT(kind_ == ValueType || kind_ == Const);
212
u.valueType_ = valueType;
213
}
214
explicit WasmToken(Kind kind, Op op, const char16_t* begin,
215
const char16_t* end)
216
: kind_(kind), begin_(begin), end_(end) {
217
MOZ_ASSERT(begin != end);
218
MOZ_ASSERT(kind_ == UnaryOpcode || kind_ == BinaryOpcode ||
219
kind_ == ComparisonOpcode || kind_ == ConversionOpcode ||
220
kind_ == Load || kind_ == Store);
221
u.op_ = op;
222
}
223
explicit WasmToken(Kind kind, MiscOp op, const char16_t* begin,
224
const char16_t* end)
225
: kind_(kind), begin_(begin), end_(end) {
226
MOZ_ASSERT(begin != end);
227
MOZ_ASSERT(kind_ == ExtraConversionOpcode);
228
u.miscOp_ = op;
229
}
230
explicit WasmToken(Kind kind, ThreadOp op, const char16_t* begin,
231
const char16_t* end)
232
: kind_(kind), begin_(begin), end_(end) {
233
MOZ_ASSERT(begin != end);
234
MOZ_ASSERT(kind_ == AtomicCmpXchg || kind_ == AtomicLoad ||
235
kind_ == AtomicRMW || kind_ == AtomicStore || kind_ == Wait ||
236
kind_ == Wake || kind_ == Fence);
237
u.threadOp_ = op;
238
}
239
explicit WasmToken(const char16_t* begin)
240
: kind_(Error), begin_(begin), end_(begin), u{} {}
241
Kind kind() const {
242
MOZ_ASSERT(kind_ != Kind::Invalid);
243
return kind_;
244
}
245
const char16_t* begin() const { return begin_; }
246
const char16_t* end() const { return end_; }
247
AstName text() const {
248
MOZ_ASSERT(kind_ == Text);
249
MOZ_ASSERT(begin_[0] == '"');
250
MOZ_ASSERT(end_[-1] == '"');
251
MOZ_ASSERT(end_ - begin_ >= 2);
252
return AstName(begin_ + 1, end_ - begin_ - 2);
253
}
254
AstName name() const { return AstName(begin_, end_ - begin_); }
255
uint32_t index() const {
256
MOZ_ASSERT(kind_ == Index);
257
return u.index_;
258
}
259
uint64_t uint() const {
260
MOZ_ASSERT(kind_ == UnsignedInteger);
261
return u.uint_;
262
}
263
int64_t sint() const {
264
MOZ_ASSERT(kind_ == SignedInteger);
265
return u.sint_;
266
}
267
FloatLiteralKind floatLiteralKind() const {
268
MOZ_ASSERT(kind_ == Float);
269
return u.floatLiteralKind_;
270
}
271
ValType valueType() const {
272
MOZ_ASSERT(kind_ == ValueType || kind_ == Const);
273
return u.valueType_;
274
}
275
Op op() const {
276
MOZ_ASSERT(kind_ == UnaryOpcode || kind_ == BinaryOpcode ||
277
kind_ == ComparisonOpcode || kind_ == ConversionOpcode ||
278
kind_ == Load || kind_ == Store);
279
return u.op_;
280
}
281
MiscOp miscOp() const {
282
MOZ_ASSERT(kind_ == ExtraConversionOpcode);
283
return u.miscOp_;
284
}
285
ThreadOp threadOp() const {
286
MOZ_ASSERT(kind_ == AtomicCmpXchg || kind_ == AtomicLoad ||
287
kind_ == AtomicRMW || kind_ == AtomicStore || kind_ == Wait ||
288
kind_ == Wake);
289
return u.threadOp_;
290
}
291
bool isOpcode() const {
292
switch (kind_) {
293
case AtomicCmpXchg:
294
case AtomicLoad:
295
case AtomicRMW:
296
case AtomicStore:
297
case BinaryOpcode:
298
case Block:
299
case Br:
300
case BrIf:
301
case BrTable:
302
case Call:
303
case CallIndirect:
304
case ComparisonOpcode:
305
case Const:
306
case ConversionOpcode:
307
case ExtraConversionOpcode:
308
case DataDrop:
309
case Drop:
310
case ElemDrop:
311
case Fence:
312
case GetGlobal:
313
case GetLocal:
314
case If:
315
case Load:
316
case Loop:
317
case MemCopy:
318
case MemFill:
319
case MemInit:
320
case MemoryGrow:
321
case MemorySize:
322
case Select:
323
#ifdef ENABLE_WASM_GC
324
case StructNew:
325
case StructGet:
326
case StructSet:
327
case StructNarrow:
328
#endif
329
case Nop:
330
case RefNull:
331
case RefFunc:
332
case Return:
333
case SetGlobal:
334
case SetLocal:
335
case Store:
336
case TableCopy:
337
case TableInit:
338
#ifdef ENABLE_WASM_REFTYPES
339
case TableFill:
340
case TableGet:
341
case TableGrow:
342
case TableSet:
343
case TableSize:
344
#endif
345
case TeeLocal:
346
case UnaryOpcode:
347
case Unreachable:
348
case Wait:
349
case Wake:
350
return true;
351
case Align:
352
case CloseParen:
353
case Data:
354
case DataCount:
355
case Declared:
356
case Elem:
357
case Else:
358
case EndOfFile:
359
case Equal:
360
case End:
361
case Error:
362
case Export:
363
case Field:
364
case Float:
365
case Func:
366
#ifdef ENABLE_WASM_GC
367
case GcFeatureOptIn:
368
#endif
369
case Global:
370
case Mutable:
371
case Import:
372
case Index:
373
case Memory:
374
case NegativeZero:
375
case Local:
376
case Module:
377
case Name:
378
case Offset:
379
case OpenParen:
380
case Param:
381
case Passive:
382
case Ref:
383
case Result:
384
case Shared:
385
case SignedInteger:
386
case Start:
387
case Struct:
388
case Table:
389
case Text:
390
case Then:
391
case Type:
392
case UnsignedInteger:
393
case ValueType:
394
return false;
395
case Invalid:
396
break;
397
}
398
MOZ_CRASH("unexpected token kind");
399
}
400
};
401
402
struct InlineImport {
403
WasmToken module;
404
WasmToken field;
405
};
406
407
} // end anonymous namespace
408
409
static bool IsWasmNewLine(char16_t c) { return c == '\n'; }
410
411
static bool IsWasmSpace(char16_t c) {
412
switch (c) {
413
case ' ':
414
case '\n':
415
case '\r':
416
case '\t':
417
case '\v':
418
case '\f':
419
return true;
420
default:
421
return false;
422
}
423
}
424
425
static bool IsWasmDigit(char16_t c) { return c >= '0' && c <= '9'; }
426
427
static bool IsWasmLetter(char16_t c) {
428
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
429
}
430
431
static bool IsNameAfterDollar(char16_t c) {
432
return IsWasmLetter(c) || IsWasmDigit(c) || c == '_' || c == '$' ||
433
c == '-' || c == '.' || c == '>';
434
}
435
436
static bool IsHexDigit(char c, uint8_t* value) {
437
if (c >= '0' && c <= '9') {
438
*value = c - '0';
439
return true;
440
}
441
442
if (c >= 'a' && c <= 'f') {
443
*value = 10 + (c - 'a');
444
return true;
445
}
446
447
if (c >= 'A' && c <= 'F') {
448
*value = 10 + (c - 'A');
449
return true;
450
}
451
452
return false;
453
}
454
455
static WasmToken LexHexFloatLiteral(const char16_t* begin, const char16_t* end,
456
const char16_t** curp) {
457
const char16_t* cur = begin;
458
459
if (cur != end && (*cur == '-' || *cur == '+')) {
460
cur++;
461
}
462
463
MOZ_ASSERT(cur != end && *cur == '0');
464
cur++;
465
MOZ_ASSERT(cur != end && *cur == 'x');
466
cur++;
467
468
uint8_t digit;
469
while (cur != end && IsHexDigit(*cur, &digit)) {
470
cur++;
471
}
472
473
if (cur != end && *cur == '.') {
474
cur++;
475
}
476
477
while (cur != end && IsHexDigit(*cur, &digit)) {
478
cur++;
479
}
480
481
if (cur != end && *cur == 'p') {
482
cur++;
483
484
if (cur != end && (*cur == '-' || *cur == '+')) {
485
cur++;
486
}
487
488
while (cur != end && IsWasmDigit(*cur)) {
489
cur++;
490
}
491
}
492
493
*curp = cur;
494
return WasmToken(WasmToken::HexNumber, begin, cur);
495
}
496
497
static WasmToken LexDecFloatLiteral(const char16_t* begin, const char16_t* end,
498
const char16_t** curp) {
499
const char16_t* cur = begin;
500
501
if (cur != end && (*cur == '-' || *cur == '+')) {
502
cur++;
503
}
504
505
while (cur != end && IsWasmDigit(*cur)) {
506
cur++;
507
}
508
509
if (cur != end && *cur == '.') {
510
cur++;
511
}
512
513
while (cur != end && IsWasmDigit(*cur)) {
514
cur++;
515
}
516
517
if (cur != end && *cur == 'e') {
518
cur++;
519
520
if (cur != end && (*cur == '-' || *cur == '+')) {
521
cur++;
522
}
523
524
while (cur != end && IsWasmDigit(*cur)) {
525
cur++;
526
}
527
}
528
529
*curp = cur;
530
return WasmToken(WasmToken::DecNumber, begin, cur);
531
}
532
533
static bool ConsumeTextByte(const char16_t** curp, const char16_t* end,
534
uint8_t* byte = nullptr) {
535
const char16_t*& cur = *curp;
536
MOZ_ASSERT(cur != end);
537
538
if (*cur != '\\') {
539
if (byte) {
540
*byte = *cur;
541
}
542
cur++;
543
return true;
544
}
545
546
if (++cur == end) {
547
return false;
548
}
549
550
uint8_t u8;
551
switch (*cur) {
552
case 'n':
553
u8 = '\n';
554
break;
555
case 't':
556
u8 = '\t';
557
break;
558
case '\\':
559
u8 = '\\';
560
break;
561
case '\"':
562
u8 = '\"';
563
break;
564
case '\'':
565
u8 = '\'';
566
break;
567
default: {
568
uint8_t highNibble;
569
if (!IsHexDigit(*cur, &highNibble)) {
570
return false;
571
}
572
573
if (++cur == end) {
574
return false;
575
}
576
577
uint8_t lowNibble;
578
if (!IsHexDigit(*cur, &lowNibble)) {
579
return false;
580
}
581
582
u8 = lowNibble | (highNibble << 4);
583
break;
584
}
585
}
586
587
if (byte) {
588
*byte = u8;
589
}
590
cur++;
591
return true;
592
}
593
594
namespace {
595
596
class WasmTokenStream {
597
static const uint32_t LookaheadSize = 2;
598
599
const char16_t* cur_;
600
const char16_t* const end_;
601
const char16_t* lineStart_;
602
unsigned line_;
603
uint32_t lookaheadIndex_;
604
uint32_t lookaheadDepth_;
605
WasmToken lookahead_[LookaheadSize];
606
607
bool consume(const char16_t* match) {
608
const char16_t* p = cur_;
609
for (; *match; p++, match++) {
610
if (p == end_ || *p != *match) {
611
return false;
612
}
613
}
614
cur_ = p;
615
return true;
616
}
617
WasmToken fail(const char16_t* begin) const { return WasmToken(begin); }
618
619
WasmToken nan(const char16_t* begin);
620
WasmToken literal(const char16_t* begin);
621
WasmToken next();
622
void skipSpaces();
623
624
public:
625
explicit WasmTokenStream(const char16_t* text, size_t textLen)
626
: cur_(text),
627
end_(text + textLen),
628
lineStart_(text),
629
line_(1),
630
lookaheadIndex_(0),
631
lookaheadDepth_(0) {}
632
void generateError(WasmToken token, UniqueChars* error) {
633
unsigned column = token.begin() - lineStart_ + 1;
634
*error = JS_smprintf("parsing wasm text at %u:%u", line_, column);
635
}
636
void generateError(WasmToken token, const char* msg, UniqueChars* error) {
637
unsigned column = token.begin() - lineStart_ + 1;
638
*error = JS_smprintf("parsing wasm text at %u:%u: %s", line_, column, msg);
639
}
640
WasmToken peek() {
641
if (!lookaheadDepth_) {
642
lookahead_[lookaheadIndex_] = next();
643
lookaheadDepth_ = 1;
644
}
645
return lookahead_[lookaheadIndex_];
646
}
647
WasmToken get() {
648
static_assert(LookaheadSize == 2, "can just flip");
649
if (lookaheadDepth_) {
650
lookaheadDepth_--;
651
WasmToken ret = lookahead_[lookaheadIndex_];
652
lookaheadIndex_ ^= 1;
653
return ret;
654
}
655
return next();
656
}
657
void unget(WasmToken token) {
658
static_assert(LookaheadSize == 2, "can just flip");
659
lookaheadDepth_++;
660
lookaheadIndex_ ^= 1;
661
lookahead_[lookaheadIndex_] = token;
662
}
663
664
// Helpers:
665
bool getIf(WasmToken::Kind kind, WasmToken* token) {
666
if (peek().kind() == kind) {
667
*token = get();
668
return true;
669
}
670
return false;
671
}
672
bool getIf(WasmToken::Kind kind) {
673
WasmToken token;
674
if (getIf(kind, &token)) {
675
return true;
676
}
677
return false;
678
}
679
AstName getIfName() {
680
WasmToken token;
681
if (getIf(WasmToken::Name, &token)) {
682
return token.name();
683
}
684
return AstName();
685
}
686
bool getIfRef(AstRef* ref) {
687
WasmToken token = peek();
688
if (token.kind() == WasmToken::Name || token.kind() == WasmToken::Index) {
689
return matchRef(ref, nullptr);
690
}
691
return false;
692
}
693
bool getIfOpcode(WasmToken* token) {
694
*token = peek();
695
if (token->isOpcode()) {
696
(void)get();
697
return true;
698
}
699
return false;
700
}
701
bool match(WasmToken::Kind expect, WasmToken* token, UniqueChars* error) {
702
*token = get();
703
if (token->kind() == expect) {
704
return true;
705
}
706
generateError(*token, error);
707
return false;
708
}
709
bool match(WasmToken::Kind expect, UniqueChars* error) {
710
WasmToken token;
711
return match(expect, &token, error);
712
}
713
bool matchRef(AstRef* ref, UniqueChars* error) {
714
WasmToken token = get();
715
switch (token.kind()) {
716
case WasmToken::Name:
717
*ref = AstRef(token.name());
718
break;
719
case WasmToken::Index:
720
if (token.index() != AstNoIndex) {
721
*ref = AstRef(token.index());
722
break;
723
}
724
MOZ_FALLTHROUGH;
725
default:
726
generateError(token, error);
727
return false;
728
}
729
return true;
730
}
731
};
732
733
} // end anonymous namespace
734
735
WasmToken WasmTokenStream::nan(const char16_t* begin) {
736
if (consume(u":")) {
737
if (!consume(u"0x")) {
738
return fail(begin);
739
}
740
741
uint8_t digit;
742
while (cur_ != end_ && IsHexDigit(*cur_, &digit)) {
743
cur_++;
744
}
745
}
746
747
return WasmToken(WasmToken::NaN, begin, cur_);
748
}
749
750
WasmToken WasmTokenStream::literal(const char16_t* begin) {
751
CheckedInt<uint64_t> u = 0;
752
if (consume(u"0x")) {
753
if (cur_ == end_) {
754
return fail(begin);
755
}
756
757
do {
758
if (*cur_ == '.' || *cur_ == 'p') {
759
return LexHexFloatLiteral(begin, end_, &cur_);
760
}
761
762
uint8_t digit;
763
if (!IsHexDigit(*cur_, &digit)) {
764
break;
765
}
766
767
u *= 16;
768
u += digit;
769
if (!u.isValid()) {
770
return LexHexFloatLiteral(begin, end_, &cur_);
771
}
772
773
cur_++;
774
} while (cur_ != end_);
775
776
if (*begin == '-') {
777
uint64_t value = u.value();
778
if (value == 0) {
779
return WasmToken(WasmToken::NegativeZero, begin, cur_);
780
}
781
if (value > uint64_t(INT64_MIN)) {
782
return LexHexFloatLiteral(begin, end_, &cur_);
783
}
784
785
value = -value;
786
return WasmToken(int64_t(value), begin, cur_);
787
}
788
} else {
789
while (cur_ != end_) {
790
if (*cur_ == '.' || *cur_ == 'e') {
791
return LexDecFloatLiteral(begin, end_, &cur_);
792
}
793
794
if (!IsWasmDigit(*cur_)) {
795
break;
796
}
797
798
u *= 10;
799
u += *cur_ - '0';
800
if (!u.isValid()) {
801
return LexDecFloatLiteral(begin, end_, &cur_);
802
}
803
804
cur_++;
805
}
806
807
if (*begin == '-') {
808
uint64_t value = u.value();
809
if (value == 0) {
810
return WasmToken(WasmToken::NegativeZero, begin, cur_);
811
}
812
if (value > uint64_t(INT64_MIN)) {
813
return LexDecFloatLiteral(begin, end_, &cur_);
814
}
815
816
value = -value;
817
return WasmToken(int64_t(value), begin, cur_);
818
}
819
}
820
821
CheckedInt<uint32_t> index = u.value();
822
if (index.isValid()) {
823
return WasmToken(index.value(), begin, cur_);
824
}
825
826
return WasmToken(u.value(), begin, cur_);
827
}
828
829
void WasmTokenStream::skipSpaces() {
830
while (cur_ != end_) {
831
char16_t ch = *cur_;
832
if (ch == ';' && consume(u";;")) {
833
// Skipping single line comment.
834
while (cur_ != end_ && !IsWasmNewLine(*cur_)) {
835
cur_++;
836
}
837
} else if (ch == '(' && consume(u"(;")) {
838
// Skipping multi-line and possibly nested comments.
839
size_t level = 1;
840
while (cur_ != end_) {
841
char16_t ch = *cur_;
842
if (ch == '(' && consume(u"(;")) {
843
level++;
844
} else if (ch == ';' && consume(u";)")) {
845
if (--level == 0) {
846
break;
847
}
848
} else {
849
cur_++;
850
if (IsWasmNewLine(ch)) {
851
lineStart_ = cur_;
852
line_++;
853
}
854
}
855
}
856
} else if (IsWasmSpace(ch)) {
857
cur_++;
858
if (IsWasmNewLine(ch)) {
859
lineStart_ = cur_;
860
line_++;
861
}
862
} else
863
break; // non-whitespace found
864
}
865
}
866
867
WasmToken WasmTokenStream::next() {
868
skipSpaces();
869
870
if (cur_ == end_) {
871
return WasmToken(WasmToken::EndOfFile, cur_, cur_);
872
}
873
874
const char16_t* begin = cur_;
875
switch (*begin) {
876
case '"':
877
cur_++;
878
while (true) {
879
if (cur_ == end_) {
880
return fail(begin);
881
}
882
if (*cur_ == '"') {
883
break;
884
}
885
if (!ConsumeTextByte(&cur_, end_)) {
886
return fail(begin);
887
}
888
}
889
cur_++;
890
return WasmToken(WasmToken::Text, begin, cur_);
891
892
case '$':
893
cur_++;
894
while (cur_ != end_ && IsNameAfterDollar(*cur_)) {
895
cur_++;
896
}
897
return WasmToken(WasmToken::Name, begin, cur_);
898
899
case '(':
900
cur_++;
901
return WasmToken(WasmToken::OpenParen, begin, cur_);
902
903
case ')':
904
cur_++;
905
return WasmToken(WasmToken::CloseParen, begin, cur_);
906
907
case '=':
908
cur_++;
909
return WasmToken(WasmToken::Equal, begin, cur_);
910
911
case '+':
912
case '-':
913
cur_++;
914
if (consume(u"infinity") || consume(u"inf")) {
915
return WasmToken(WasmToken::Infinity, begin, cur_);
916
}
917
if (consume(u"nan")) {
918
return nan(begin);
919
}
920
if (!IsWasmDigit(*cur_)) {
921
break;
922
}
923
MOZ_FALLTHROUGH;
924
case '0':
925
case '1':
926
case '2':
927
case '3':
928
case '4':
929
case '5':
930
case '6':
931
case '7':
932
case '8':
933
case '9':
934
return literal(begin);
935
936
case 'a':
937
if (consume(u"align")) {
938
return WasmToken(WasmToken::Align, begin, cur_);
939
}
940
if (consume(u"anyfunc")) {
941
return WasmToken(WasmToken::ValueType, ValType::FuncRef, begin, cur_);
942
}
943
if (consume(u"anyref")) {
944
return WasmToken(WasmToken::ValueType, ValType::AnyRef, begin, cur_);
945
}
946
if (consume(u"atomic.")) {
947
if (consume(u"wake") || consume(u"notify")) {
948
return WasmToken(WasmToken::Wake, ThreadOp::Wake, begin, cur_);
949
}
950
if (consume(u"fence")) {
951
return WasmToken(WasmToken::Fence, ThreadOp::Fence, begin, cur_);
952
}
953
break;
954
}
955
break;
956
957
case 'b':
958
if (consume(u"block")) {
959
return WasmToken(WasmToken::Block, begin, cur_);
960
}
961
if (consume(u"br")) {
962
if (consume(u"_table")) {
963
return WasmToken(WasmToken::BrTable, begin, cur_);
964
}
965
if (consume(u"_if")) {
966
return WasmToken(WasmToken::BrIf, begin, cur_);
967
}
968
return WasmToken(WasmToken::Br, begin, cur_);
969
}
970
break;
971
972
case 'c':
973
if (consume(u"call")) {
974
if (consume(u"_indirect")) {
975
return WasmToken(WasmToken::CallIndirect, begin, cur_);
976
}
977
return WasmToken(WasmToken::Call, begin, cur_);
978
}
979
if (consume(u"current_memory")) {
980
return WasmToken(WasmToken::MemorySize, begin, cur_);
981
}
982
break;
983
984
case 'd':
985
if (consume(u"data")) {
986
if (consume(u"count")) {
987
return WasmToken(WasmToken::DataCount, begin, cur_);
988
}
989
if (consume(u".drop")) {
990
return WasmToken(WasmToken::DataDrop, begin, cur_);
991
}
992
return WasmToken(WasmToken::Data, begin, cur_);
993
}
994
if (consume(u"declared")) {
995
return WasmToken(WasmToken::Declared, begin, cur_);
996
}
997
if (consume(u"drop")) {
998
return WasmToken(WasmToken::Drop, begin, cur_);
999
}
1000
break;
1001
1002
case 'e':
1003
if (consume(u"elem")) {
1004
if (consume(u".drop")) {
1005
return WasmToken(WasmToken::ElemDrop, begin, cur_);
1006
}
1007
return WasmToken(WasmToken::Elem, begin, cur_);
1008
}
1009
if (consume(u"else")) {
1010
return WasmToken(WasmToken::Else, begin, cur_);
1011
}
1012
if (consume(u"end")) {
1013
return WasmToken(WasmToken::End, begin, cur_);
1014
}
1015
if (consume(u"export")) {
1016
return WasmToken(WasmToken::Export, begin, cur_);
1017
}
1018
break;
1019
1020
case 'f':
1021
if (consume(u"field")) {
1022
return WasmToken(WasmToken::Field, begin, cur_);
1023
}
1024
1025
if (consume(u"funcref")) {
1026
return WasmToken(WasmToken::ValueType, ValType::FuncRef, begin, cur_);
1027
}
1028
1029
if (consume(u"func")) {
1030
return WasmToken(WasmToken::Func, begin, cur_);
1031
}
1032
1033
if (consume(u"f32")) {
1034
if (!consume(u".")) {
1035
return WasmToken(WasmToken::ValueType, ValType::F32, begin, cur_);
1036
}
1037
1038
switch (*cur_) {
1039
case 'a':
1040
if (consume(u"abs")) {
1041
return WasmToken(WasmToken::UnaryOpcode, Op::F32Abs, begin, cur_);
1042
}
1043
if (consume(u"add")) {
1044
return WasmToken(WasmToken::BinaryOpcode, Op::F32Add, begin,
1045
cur_);
1046
}
1047
break;
1048
case 'c':
1049
if (consume(u"ceil")) {
1050
return WasmToken(WasmToken::UnaryOpcode, Op::F32Ceil, begin,
1051
cur_);
1052
}
1053
if (consume(u"const")) {
1054
return WasmToken(WasmToken::Const, ValType::F32, begin, cur_);
1055
}
1056
if (consume(u"convert_i32_s") || consume(u"convert_s/i32")) {
1057
return WasmToken(WasmToken::ConversionOpcode, Op::F32ConvertSI32,
1058
begin, cur_);
1059
}
1060
if (consume(u"convert_i32_u") || consume(u"convert_u/i32")) {
1061
return WasmToken(WasmToken::ConversionOpcode, Op::F32ConvertUI32,
1062
begin, cur_);
1063
}
1064
if (consume(u"convert_i64_s") || consume(u"convert_s/i64")) {
1065
return WasmToken(WasmToken::ConversionOpcode, Op::F32ConvertSI64,
1066
begin, cur_);
1067
}
1068
if (consume(u"convert_i64_u") || consume(u"convert_u/i64")) {
1069
return WasmToken(WasmToken::ConversionOpcode, Op::F32ConvertUI64,
1070
begin, cur_);
1071
}
1072
if (consume(u"copysign")) {
1073
return WasmToken(WasmToken::BinaryOpcode, Op::F32CopySign, begin,
1074
cur_);
1075
}
1076
break;
1077
case 'd':
1078
if (consume(u"demote_f64") || consume(u"demote/f64")) {
1079
return WasmToken(WasmToken::ConversionOpcode, Op::F32DemoteF64,
1080
begin, cur_);
1081
}
1082
if (consume(u"div")) {
1083
return WasmToken(WasmToken::BinaryOpcode, Op::F32Div, begin,
1084
cur_);
1085
}
1086
break;
1087
case 'e':
1088
if (consume(u"eq")) {
1089
return WasmToken(WasmToken::ComparisonOpcode, Op::F32Eq, begin,
1090
cur_);
1091
}
1092
break;
1093
case 'f':
1094
if (consume(u"floor")) {
1095
return WasmToken(WasmToken::UnaryOpcode, Op::F32Floor, begin,
1096
cur_);
1097
}
1098
break;
1099
case 'g':
1100
if (consume(u"ge")) {
1101
return WasmToken(WasmToken::ComparisonOpcode, Op::F32Ge, begin,
1102
cur_);
1103
}
1104
if (consume(u"gt")) {
1105
return WasmToken(WasmToken::ComparisonOpcode, Op::F32Gt, begin,
1106
cur_);
1107
}
1108
break;
1109
case 'l':
1110
if (consume(u"le")) {
1111
return WasmToken(WasmToken::ComparisonOpcode, Op::F32Le, begin,
1112
cur_);
1113
}
1114
if (consume(u"lt")) {
1115
return WasmToken(WasmToken::ComparisonOpcode, Op::F32Lt, begin,
1116
cur_);
1117
}
1118
if (consume(u"load")) {
1119
return WasmToken(WasmToken::Load, Op::F32Load, begin, cur_);
1120
}
1121
break;
1122
case 'm':
1123
if (consume(u"max")) {
1124
return WasmToken(WasmToken::BinaryOpcode, Op::F32Max, begin,
1125
cur_);
1126
}
1127
if (consume(u"min")) {
1128
return WasmToken(WasmToken::BinaryOpcode, Op::F32Min, begin,
1129
cur_);
1130
}
1131
if (consume(u"mul")) {
1132
return WasmToken(WasmToken::BinaryOpcode, Op::F32Mul, begin,
1133
cur_);
1134
}
1135
break;
1136
case 'n':
1137
if (consume(u"nearest")) {
1138
return WasmToken(WasmToken::UnaryOpcode, Op::F32Nearest, begin,
1139
cur_);
1140
}
1141
if (consume(u"neg")) {
1142
return WasmToken(WasmToken::UnaryOpcode, Op::F32Neg, begin, cur_);
1143
}
1144
if (consume(u"ne")) {
1145
return WasmToken(WasmToken::ComparisonOpcode, Op::F32Ne, begin,
1146
cur_);
1147
}
1148
break;
1149
case 'r':
1150
if (consume(u"reinterpret_i32") || consume(u"reinterpret/i32")) {
1151
return WasmToken(WasmToken::ConversionOpcode,
1152
Op::F32ReinterpretI32, begin, cur_);
1153
}
1154
break;
1155
case 's':
1156
if (consume(u"sqrt")) {
1157
return WasmToken(WasmToken::UnaryOpcode, Op::F32Sqrt, begin,
1158
cur_);
1159
}
1160
if (consume(u"sub")) {
1161
return WasmToken(WasmToken::BinaryOpcode, Op::F32Sub, begin,
1162
cur_);
1163
}
1164
if (consume(u"store")) {
1165
return WasmToken(WasmToken::Store, Op::F32Store, begin, cur_);
1166
}
1167
break;
1168
case 't':
1169
if (consume(u"trunc")) {
1170
return WasmToken(WasmToken::UnaryOpcode, Op::F32Trunc, begin,
1171
cur_);
1172
}
1173
break;
1174
}
1175
break;
1176
}
1177
if (consume(u"f64")) {
1178
if (!consume(u".")) {
1179
return WasmToken(WasmToken::ValueType, ValType::F64, begin, cur_);
1180
}
1181
1182
switch (*cur_) {
1183
case 'a':
1184
if (consume(u"abs")) {
1185
return WasmToken(WasmToken::UnaryOpcode, Op::F64Abs, begin, cur_);
1186
}
1187
if (consume(u"add")) {
1188
return WasmToken(WasmToken::BinaryOpcode, Op::F64Add, begin,
1189
cur_);
1190
}
1191
break;
1192
case 'c':
1193
if (consume(u"ceil")) {
1194
return WasmToken(WasmToken::UnaryOpcode, Op::F64Ceil, begin,
1195
cur_);
1196
}
1197
if (consume(u"const")) {
1198
return WasmToken(WasmToken::Const, ValType::F64, begin, cur_);
1199
}
1200
if (consume(u"convert_i32_s") || consume(u"convert_s/i32")) {
1201
return WasmToken(WasmToken::ConversionOpcode, Op::F64ConvertSI32,
1202
begin, cur_);
1203
}
1204
if (consume(u"convert_i32_u") || consume(u"convert_u/i32")) {
1205
return WasmToken(WasmToken::ConversionOpcode, Op::F64ConvertUI32,
1206
begin, cur_);
1207
}
1208
if (consume(u"convert_i64_s") || consume(u"convert_s/i64")) {
1209
return WasmToken(WasmToken::ConversionOpcode, Op::F64ConvertSI64,
1210
begin, cur_);
1211
}
1212
if (consume(u"convert_i64_u") || consume(u"convert_u/i64")) {
1213
return WasmToken(WasmToken::ConversionOpcode, Op::F64ConvertUI64,
1214
begin, cur_);
1215
}
1216
if (consume(u"copysign")) {
1217
return WasmToken(WasmToken::BinaryOpcode, Op::F64CopySign, begin,
1218
cur_);
1219
}
1220
break;
1221
case 'd':
1222
if (consume(u"div")) {
1223
return WasmToken(WasmToken::BinaryOpcode, Op::F64Div, begin,
1224
cur_);
1225
}
1226
break;
1227
case 'e':
1228
if (consume(u"eq")) {
1229
return WasmToken(WasmToken::ComparisonOpcode, Op::F64Eq, begin,
1230
cur_);
1231
}
1232
break;
1233
case 'f':
1234
if (consume(u"floor")) {
1235
return WasmToken(WasmToken::UnaryOpcode, Op::F64Floor, begin,
1236
cur_);
1237
}
1238
break;
1239
case 'g':
1240
if (consume(u"ge")) {
1241
return WasmToken(WasmToken::ComparisonOpcode, Op::F64Ge, begin,
1242
cur_);
1243
}
1244
if (consume(u"gt")) {
1245
return WasmToken(WasmToken::ComparisonOpcode, Op::F64Gt, begin,
1246
cur_);
1247
}
1248
break;
1249
case 'l':
1250
if (consume(u"le")) {
1251
return WasmToken(WasmToken::ComparisonOpcode, Op::F64Le, begin,
1252
cur_);
1253
}
1254
if (consume(u"lt")) {
1255
return WasmToken(WasmToken::ComparisonOpcode, Op::F64Lt, begin,
1256
cur_);
1257
}
1258
if (consume(u"load")) {
1259
return WasmToken(WasmToken::Load, Op::F64Load, begin, cur_);
1260
}
1261
break;
1262
case 'm':
1263
if (consume(u"max")) {
1264
return WasmToken(WasmToken::BinaryOpcode, Op::F64Max, begin,
1265
cur_);
1266
}
1267
if (consume(u"min")) {
1268
return WasmToken(WasmToken::BinaryOpcode, Op::F64Min, begin,
1269
cur_);
1270
}
1271
if (consume(u"mul")) {
1272
return WasmToken(WasmToken::BinaryOpcode, Op::F64Mul, begin,
1273
cur_);
1274
}
1275
break;
1276
case 'n':
1277
if (consume(u"nearest")) {
1278
return WasmToken(WasmToken::UnaryOpcode, Op::F64Nearest, begin,
1279
cur_);
1280
}
1281
if (consume(u"neg")) {
1282
return WasmToken(WasmToken::UnaryOpcode, Op::F64Neg, begin, cur_);
1283
}
1284
if (consume(u"ne")) {
1285
return WasmToken(WasmToken::ComparisonOpcode, Op::F64Ne, begin,
1286
cur_);
1287
}
1288
break;
1289
case 'p':
1290
if (consume(u"promote_f32") || consume(u"promote/f32")) {
1291
return WasmToken(WasmToken::ConversionOpcode, Op::F64PromoteF32,
1292
begin, cur_);
1293
}
1294
break;
1295
case 'r':
1296
if (consume(u"reinterpret_i64") || consume(u"reinterpret/i64")) {
1297
return WasmToken(WasmToken::UnaryOpcode, Op::F64ReinterpretI64,
1298
begin, cur_);
1299
}
1300
break;
1301
case 's':
1302
if (consume(u"sqrt")) {
1303
return WasmToken(WasmToken::UnaryOpcode, Op::F64Sqrt, begin,
1304
cur_);
1305
}
1306
if (consume(u"sub")) {
1307
return WasmToken(WasmToken::BinaryOpcode, Op::F64Sub, begin,
1308
cur_);
1309
}
1310
if (consume(u"store")) {
1311
return WasmToken(WasmToken::Store, Op::F64Store, begin, cur_);
1312
}
1313
break;
1314
case 't':
1315
if (consume(u"trunc")) {
1316
return WasmToken(WasmToken::UnaryOpcode, Op::F64Trunc, begin,
1317
cur_);
1318
}
1319
break;
1320
}
1321
break;
1322
}
1323
break;
1324
1325
case 'g':
1326
#ifdef ENABLE_WASM_GC
1327
if (consume(u"gc_feature_opt_in")) {
1328
return WasmToken(WasmToken::GcFeatureOptIn, begin, cur_);
1329
}
1330
#endif
1331
if (consume(u"get_global")) {
1332
return WasmToken(WasmToken::GetGlobal, begin, cur_);
1333
}
1334
if (consume(u"get_local")) {
1335
return WasmToken(WasmToken::GetLocal, begin, cur_);
1336
}
1337
if (consume(u"global")) {
1338
if (consume(u".get")) {
1339
return WasmToken(WasmToken::GetGlobal, begin, cur_);
1340
}
1341
if (consume(u".set")) {
1342
return WasmToken(WasmToken::SetGlobal, begin, cur_);
1343
}
1344
return WasmToken(WasmToken::Global, begin, cur_);
1345
}
1346
if (consume(u"grow_memory")) {
1347
return WasmToken(WasmToken::MemoryGrow, begin, cur_);
1348
}
1349
break;
1350
1351
case 'i':
1352
if (consume(u"i32")) {
1353
if (!consume(u".")) {
1354
return WasmToken(WasmToken::ValueType, ValType::I32, begin, cur_);
1355
}
1356
1357
switch (*cur_) {
1358
case 'a':
1359
if (consume(u"add")) {
1360
return WasmToken(WasmToken::BinaryOpcode, Op::I32Add, begin,
1361
cur_);
1362
}
1363
if (consume(u"and")) {
1364
return WasmToken(WasmToken::BinaryOpcode, Op::I32And, begin,
1365
cur_);
1366
}
1367
if (consume(u"atomic.")) {
1368
if (consume(u"rmw8.add_u") || consume(u"rmw8_u.add")) {
1369
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicAdd8U,
1370
begin, cur_);
1371
}
1372
if (consume(u"rmw16.add_u") || consume(u"rmw16_u.add")) {
1373
return WasmToken(WasmToken::AtomicRMW,
1374
ThreadOp::I32AtomicAdd16U, begin, cur_);
1375
}
1376
if (consume(u"rmw.add")) {
1377
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicAdd,
1378
begin, cur_);
1379
}
1380
if (consume(u"rmw8.and_u") || consume(u"rmw8_u.and")) {
1381
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicAnd8U,
1382
begin, cur_);
1383
}
1384
if (consume(u"rmw16.and_u") || consume(u"rmw16_u.and")) {
1385
return WasmToken(WasmToken::AtomicRMW,
1386
ThreadOp::I32AtomicAnd16U, begin, cur_);
1387
}
1388
if (consume(u"rmw.and")) {
1389
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicAnd,
1390
begin, cur_);
1391
}
1392
if (consume(u"rmw8.cmpxchg_u") || consume(u"rmw8_u.cmpxchg")) {
1393
return WasmToken(WasmToken::AtomicCmpXchg,
1394
ThreadOp::I32AtomicCmpXchg8U, begin, cur_);
1395
}
1396
if (consume(u"rmw16.cmpxchg_u") || consume(u"rmw16_u.cmpxchg")) {
1397
return WasmToken(WasmToken::AtomicCmpXchg,
1398
ThreadOp::I32AtomicCmpXchg16U, begin, cur_);
1399
}
1400
if (consume(u"rmw.cmpxchg")) {
1401
return WasmToken(WasmToken::AtomicCmpXchg,
1402
ThreadOp::I32AtomicCmpXchg, begin, cur_);
1403
}
1404
if (consume(u"load8_u")) {
1405
return WasmToken(WasmToken::AtomicLoad,
1406
ThreadOp::I32AtomicLoad8U, begin, cur_);
1407
}
1408
if (consume(u"load16_u")) {
1409
return WasmToken(WasmToken::AtomicLoad,
1410
ThreadOp::I32AtomicLoad16U, begin, cur_);
1411
}
1412
if (consume(u"load")) {
1413
return WasmToken(WasmToken::AtomicLoad, ThreadOp::I32AtomicLoad,
1414
begin, cur_);
1415
}
1416
if (consume(u"rmw8.or_u") || consume(u"rmw8_u.or")) {
1417
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicOr8U,
1418
begin, cur_);
1419
}
1420
if (consume(u"rmw16.or_u") || consume(u"rmw16_u.or")) {
1421
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicOr16U,
1422
begin, cur_);
1423
}
1424
if (consume(u"rmw.or")) {
1425
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicOr,
1426
begin, cur_);
1427
}
1428
if (consume(u"store8_u")) {
1429
return WasmToken(WasmToken::AtomicStore,
1430
ThreadOp::I32AtomicStore8U, begin, cur_);
1431
}
1432
if (consume(u"store16_u")) {
1433
return WasmToken(WasmToken::AtomicStore,
1434
ThreadOp::I32AtomicStore16U, begin, cur_);
1435
}
1436
if (consume(u"store")) {
1437
return WasmToken(WasmToken::AtomicStore,
1438
ThreadOp::I32AtomicStore, begin, cur_);
1439
}
1440
if (consume(u"rmw8.sub_u") || consume(u"rmw8_u.sub")) {
1441
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicSub8U,
1442
begin, cur_);
1443
}
1444
if (consume(u"rmw16.sub_u") || consume(u"rmw16_u.sub")) {
1445
return WasmToken(WasmToken::AtomicRMW,
1446
ThreadOp::I32AtomicSub16U, begin, cur_);
1447
}
1448
if (consume(u"rmw.sub")) {
1449
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicSub,
1450
begin, cur_);
1451
}
1452
if (consume(u"rmw8.xor_u") || consume(u"rmw8_u.xor")) {
1453
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicXor8U,
1454
begin, cur_);
1455
}
1456
if (consume(u"rmw16.xor_u") || consume(u"rmw16_u.xor")) {
1457
return WasmToken(WasmToken::AtomicRMW,
1458
ThreadOp::I32AtomicXor16U, begin, cur_);
1459
}
1460
if (consume(u"rmw.xor")) {
1461
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicXor,
1462
begin, cur_);
1463
}
1464
if (consume(u"rmw8.xchg_u") || consume(u"rmw8_u.xchg")) {
1465
return WasmToken(WasmToken::AtomicRMW,
1466
ThreadOp::I32AtomicXchg8U, begin, cur_);
1467
}
1468
if (consume(u"rmw16.xchg_u") || consume(u"rmw16_u.xchg")) {
1469
return WasmToken(WasmToken::AtomicRMW,
1470
ThreadOp::I32AtomicXchg16U, begin, cur_);
1471
}
1472
if (consume(u"rmw.xchg")) {
1473
return WasmToken(WasmToken::AtomicRMW, ThreadOp::I32AtomicXchg,
1474
begin, cur_);
1475
}
1476
if (consume(u"wait")) {
1477
return WasmToken(WasmToken::Wait, ThreadOp::I32Wait, begin,
1478
cur_);
1479
}
1480
}
1481
break;
1482
case 'c':
1483
if (consume(u"const")) {
1484
return WasmToken(WasmToken::Const, ValType::I32, begin, cur_);
1485
}
1486
if (consume(u"clz")) {
1487
return WasmToken(WasmToken::UnaryOpcode, Op::I32Clz, begin, cur_);
1488
}
1489
if (consume(u"ctz")) {
1490
return WasmToken(WasmToken::UnaryOpcode, Op::I32Ctz, begin, cur_);
1491
}
1492
break;
1493
case 'd':
1494
if (consume(u"div_s")) {
1495
return WasmToken(WasmToken::BinaryOpcode, Op::I32DivS, begin,
1496
cur_);
1497
}
1498
if (consume(u"div_u")) {
1499
return WasmToken(WasmToken::BinaryOpcode, Op::I32DivU, begin,
1500
cur_);
1501
}
1502
break;
1503
case 'e':
1504
if (consume(u"eqz")) {
1505
return WasmToken(WasmToken::UnaryOpcode, Op::I32Eqz, begin, cur_);
1506
}
1507
if (consume(u"eq")) {
1508
return WasmToken(WasmToken::ComparisonOpcode, Op::I32Eq, begin,
1509
cur_);
1510
}
1511
if (consume(u"extend8_s")) {
1512
return WasmToken(WasmToken::ConversionOpcode, Op::I32Extend8S,
1513
begin, cur_);
1514
}
1515
if (consume(u"extend16_s")) {
1516
return WasmToken(WasmToken::ConversionOpcode, Op::I32Extend16S,
1517
begin, cur_);
1518
}
1519
break;
1520
case 'g':
1521
if (consume(u"ge_s")) {
1522
return WasmToken(WasmToken::ComparisonOpcode, Op::I32GeS, begin,
1523
cur_);
1524
}
1525
if (consume(u"ge_u")) {
1526
return WasmToken(WasmToken::ComparisonOpcode, Op::I32GeU, begin,
1527
cur_);
1528
}
1529
if (consume(u"gt_s")) {
1530
return WasmToken(WasmToken::ComparisonOpcode, Op::I32GtS, begin,
1531
cur_);
1532
}
1533
if (consume(u"gt_u")) {
1534
return WasmToken(WasmToken::ComparisonOpcode, Op::I32GtU, begin,
1535
cur_);
1536
}
1537
break;
1538
case 'l':
1539
if (consume(u"le_s")) {
1540
return WasmToken(WasmToken::ComparisonOpcode, Op::I32LeS, begin,
1541
cur_);
1542
}
1543
if (consume(u"le_u")) {
1544
return WasmToken(WasmToken::ComparisonOpcode, Op::I32LeU, begin,
1545
cur_);
1546
}
1547
if (consume(u"lt_s")) {
1548
return WasmToken(WasmToken::ComparisonOpcode, Op::I32LtS, begin,
1549
cur_);
1550
}
1551
if (consume(u"lt_u")) {
1552
return WasmToken(WasmToken::ComparisonOpcode, Op::I32LtU, begin,
1553
cur_);
1554
}
1555
if (consume(u"load")) {
1556
if (IsWasmSpace(*cur_)) {
1557
return WasmToken(WasmToken::Load, Op::I32Load, begin, cur_);
1558
}
1559
if (consume(u"8_s")) {
1560
return WasmToken(WasmToken::Load, Op::I32Load8S, begin, cur_);
1561
}
1562
if (consume(u"8_u")) {
1563
return WasmToken(WasmToken::Load, Op::I32Load8U, begin, cur_);
1564
}
1565
if (consume(u"16_s")) {
1566
return WasmToken(WasmToken::Load, Op::I32Load16S, begin, cur_);
1567
}
1568
if (consume(u"16_u")) {
1569
return WasmToken(WasmToken::Load, Op::I32Load16U, begin, cur_);
1570
}
1571
break;
1572
}
1573
break;
1574
case 'm':
1575
if (consume(u"mul")) {
1576
return WasmToken(WasmToken::BinaryOpcode, Op::I32Mul, begin,
1577
cur_);
1578
}
1579
break;
1580
case 'n':
1581
if (consume(u"ne")) {
1582
return WasmToken(WasmToken::ComparisonOpcode, Op::I32Ne, begin,
1583
cur_);
1584
}
1585
break;
1586
case 'o':
1587
if (consume(u"or")) {
1588
return WasmToken(WasmToken::BinaryOpcode, Op::I32Or, begin, cur_);
1589
}
1590
break;
1591
case 'p':
1592
if (consume(u"popcnt")) {
1593
return WasmToken(WasmToken::UnaryOpcode, Op::I32Popcnt, begin,
1594
cur_);
1595
}
1596
break;
1597
case 'r':
1598
if (consume(u"reinterpret_f32") || consume(u"reinterpret/f32")) {
1599
return WasmToken(WasmToken::UnaryOpcode, Op::I32ReinterpretF32,
1600
begin, cur_);
1601
}
1602
if (consume(u"rem_s")) {
1603
return WasmToken(WasmToken::BinaryOpcode, Op::I32RemS, begin,
1604
cur_);
1605
}
1606
if (consume(u"rem_u")) {
1607
return WasmToken(WasmToken::BinaryOpcode, Op::I32RemU, begin,
1608
cur_);
1609
}
1610
if (consume(u"rotr")) {
1611
return WasmToken(WasmToken::BinaryOpcode, Op::I32Rotr, begin,
1612
cur_);
1613
}
1614
if (consume(u"rotl")) {
1615
return WasmToken(WasmToken::BinaryOpcode, Op::I32Rotl, begin,
1616
cur_);
1617
}
1618
break;
1619
case 's':
1620
if (consume(u"sub")) {
1621
return WasmToken(WasmToken::BinaryOpcode, Op::I32Sub, begin,
1622
cur_);
1623
}
1624
if (consume(u"shl")) {
1625
return WasmToken(WasmToken::BinaryOpcode, Op::I32Shl, begin,
1626
cur_);
1627
}
1628
if (consume(u"shr_s")) {
1629
return WasmToken(WasmToken::BinaryOpcode, Op::I32ShrS, begin,
1630
cur_);
1631
}
1632
if (consume(u"shr_u")) {
1633
return WasmToken(WasmToken::BinaryOpcode, Op::I32ShrU, begin,
1634
cur_);
1635
}
1636
if (consume(u"store")) {
1637
if (IsWasmSpace(*cur_)) {
1638
return WasmToken(WasmToken::Store, Op::I32Store, begin, cur_);
1639
}
1640
if (consume(u"8")) {
1641
return WasmToken(WasmToken::Store, Op::I32Store8, begin, cur_);
1642
}
1643
if (consume(u"16")) {
1644
return WasmToken(WasmToken::Store, Op::I32Store16, begin, cur_);
1645
}
1646
break;
1647
}
1648
break;
1649
case 't':
1650
if (consume(u"trunc_f32_s") || consume(u"trunc_s/f32")) {
1651
return WasmToken(WasmToken::ConversionOpcode, Op::I32TruncSF32,
1652
begin, cur_);
1653
}
1654
if (consume(u"trunc_f64_s") || consume(u"trunc_s/f64")) {
1655
return WasmToken(WasmToken::ConversionOpcode, Op::I32TruncSF64,
1656
begin, cur_);
1657
}
1658
if (consume(u"trunc_f32_u") || consume(u"trunc_u/f32")) {
1659
return WasmToken(WasmToken::ConversionOpcode, Op::I32TruncUF32,
1660
begin, cur_);
1661
}
1662
if (consume(u"trunc_f64_u") || consume(u"trunc_u/f64")) {
1663
return WasmToken(WasmToken::ConversionOpcode, Op::I32TruncUF64,
1664
begin, cur_);
1665
}
1666
if (consume(u"trunc_sat_f32_s") || consume(u"trunc_s:sat/f32")) {
1667
return WasmToken(WasmToken::ExtraConversionOpcode,
1668
MiscOp::I32TruncSSatF32, begin, cur_);
1669
}
1670
if (consume(u"trunc_sat_f64_s") || consume(u"trunc_s:sat/f64")) {
1671
return WasmToken(WasmToken::ExtraConversionOpcode,
1672
MiscOp::I32TruncSSatF64, begin, cur_);
1673
}
1674
if (consume(u"trunc_sat_f32_u") || consume(u"trunc_u:sat/f32")) {
1675
return WasmToken(WasmToken::ExtraConversionOpcode,
1676
MiscOp::I32TruncUSatF32, begin, cur_);
1677
}
1678
if (consume(u"trunc_sat_f64_u") || consume(u"trunc_u:sat/f64")) {
1679
return WasmToken(WasmToken::ExtraConversionOpcode,
1680
MiscOp::I32TruncUSatF64, begin, cur_);
1681
}
1682
break;
1683
case 'w':
1684
if (consume(u"wrap_i64") || consume(u"wrap/i64")) {
1685
return WasmToken(WasmToken::ConversionOpcode, Op::I32WrapI64,
1686
begin, cur_);
1687
}
1688
break;
1689
case 'x':
1690
if (consume(u"xor")) {
1691
return WasmToken(WasmToken::BinaryOpcode, Op::I32Xor, begin,
1692
cur_);
1693
}
1694
break;
1695
}
1696
break;
1697
}
1698
if (consume(u"i64")) {
1699
if (!