1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sts=4 et sw=4 tw=99:
3 *
4 * Copyright 2016 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 *
10 * http://www.apache.org/licenses/LICENSE-2.0
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/WasmBinaryToAST.h"
20
21 #include "mozilla/CheckedInt.h"
22 #include "mozilla/MathAlgorithms.h"
23 #include "mozilla/Sprintf.h"
24
25 #include "jscntxt.h"
26
27 #include "wasm/WasmBinaryFormat.h"
28 #include "wasm/WasmBinaryIterator.h"
29
30 using namespace js;
31 using namespace js::wasm;
32
33 using mozilla::CheckedInt;
34 using mozilla::FloorLog2;
35
36 enum AstDecodeTerminationKind
37 {
38 Unknown,
39 End,
40 Else
41 };
42
43 struct AstDecodeStackItem
44 {
45 AstExpr* expr;
46 AstDecodeTerminationKind terminationKind;
47 ExprType type;
48
AstDecodeStackItemAstDecodeStackItem49 explicit AstDecodeStackItem()
50 : expr(nullptr),
51 terminationKind(AstDecodeTerminationKind::Unknown),
52 type(ExprType::Limit)
53 {}
AstDecodeStackItemAstDecodeStackItem54 explicit AstDecodeStackItem(AstDecodeTerminationKind terminationKind, ExprType type)
55 : expr(nullptr),
56 terminationKind(terminationKind),
57 type(type)
58 {}
AstDecodeStackItemAstDecodeStackItem59 explicit AstDecodeStackItem(AstExpr* expr)
60 : expr(expr),
61 terminationKind(AstDecodeTerminationKind::Unknown),
62 type(ExprType::Limit)
63 {}
64 };
65
66 // We don't define a Value type because OpIter doesn't push void values, which
67 // we actually need here because we're building an AST, so we maintain our own
68 // stack.
69 struct AstDecodePolicy : OpIterPolicy
70 {
71 // Enable validation because we can be called from wasmBinaryToText on bytes
72 // which are not necessarily valid, and we shouldn't run the decoder in
73 // non-validating mode on invalid code.
74 static const bool Validate = true;
75
76 static const bool Output = true;
77 };
78
79 typedef OpIter<AstDecodePolicy> AstDecodeOpIter;
80
81 class AstDecodeContext
82 {
83 public:
84 typedef AstVector<uint32_t> AstIndexVector;
85 typedef AstVector<AstDecodeStackItem> AstDecodeStack;
86 typedef AstVector<uint32_t> DepthStack;
87
88 JSContext* cx;
89 LifoAlloc& lifo;
90 Decoder& d;
91 bool generateNames;
92
93 private:
94 AstModule& module_;
95 AstIndexVector funcDefSigs_;
96 AstDecodeOpIter *iter_;
97 AstDecodeStack exprs_;
98 DepthStack depths_;
99 const ValTypeVector* locals_;
100 GlobalDescVector globals_;
101 AstNameVector blockLabels_;
102 uint32_t currentLabelIndex_;
103 ExprType retType_;
104
105 public:
AstDecodeContext(JSContext * cx,LifoAlloc & lifo,Decoder & d,AstModule & module,bool generateNames)106 AstDecodeContext(JSContext* cx, LifoAlloc& lifo, Decoder& d, AstModule& module,
107 bool generateNames)
108 : cx(cx),
109 lifo(lifo),
110 d(d),
111 generateNames(generateNames),
112 module_(module),
113 funcDefSigs_(lifo),
114 iter_(nullptr),
115 exprs_(lifo),
116 depths_(lifo),
117 locals_(nullptr),
118 blockLabels_(lifo),
119 currentLabelIndex_(0),
120 retType_(ExprType::Limit)
121 {}
122
module()123 AstModule& module() { return module_; }
funcDefSigs()124 AstIndexVector& funcDefSigs() { return funcDefSigs_; }
iter()125 AstDecodeOpIter& iter() { return *iter_; }
exprs()126 AstDecodeStack& exprs() { return exprs_; }
depths()127 DepthStack& depths() { return depths_; }
128
blockLabels()129 AstNameVector& blockLabels() { return blockLabels_; }
130
retType() const131 ExprType retType() const { return retType_; }
locals() const132 const ValTypeVector& locals() const { return *locals_; }
133
addGlobalDesc(ValType type,bool isMutable,bool isImport)134 bool addGlobalDesc(ValType type, bool isMutable, bool isImport) {
135 if (isImport)
136 return globals_.append(GlobalDesc(type, isMutable, globals_.length()));
137 // No need to have the precise init expr value; we just need the right
138 // type.
139 Val dummy;
140 switch (type) {
141 case ValType::I32: dummy = Val(uint32_t(0)); break;
142 case ValType::I64: dummy = Val(uint64_t(0)); break;
143 case ValType::F32: dummy = Val(RawF32(0.f)); break;
144 case ValType::F64: dummy = Val(RawF64(0.0)); break;
145 default: return false;
146 }
147 return globals_.append(GlobalDesc(InitExpr(dummy), isMutable));
148 }
globalDescs() const149 const GlobalDescVector& globalDescs() const { return globals_; }
150
popBack()151 void popBack() { return exprs().popBack(); }
popCopy()152 AstDecodeStackItem popCopy() { return exprs().popCopy(); }
top()153 AstDecodeStackItem& top() { return exprs().back(); }
push(AstDecodeStackItem item)154 MOZ_MUST_USE bool push(AstDecodeStackItem item) { return exprs().append(item); }
155
needFirst()156 bool needFirst() {
157 for (size_t i = depths().back(); i < exprs().length(); ++i) {
158 if (!exprs()[i].expr->isVoid())
159 return true;
160 }
161 return false;
162 }
163
handleVoidExpr(AstExpr * voidNode)164 AstExpr* handleVoidExpr(AstExpr* voidNode)
165 {
166 MOZ_ASSERT(voidNode->isVoid());
167
168 // To attach a node that "returns void" to the middle of an AST, wrap it
169 // in a first node next to the node it should accompany.
170 if (needFirst()) {
171 AstExpr *prev = popCopy().expr;
172
173 // If the previous/A node is already a First, reuse it.
174 if (prev->kind() == AstExprKind::First) {
175 if (!prev->as<AstFirst>().exprs().append(voidNode))
176 return nullptr;
177 return prev;
178 }
179
180 AstExprVector exprs(lifo);
181 if (!exprs.append(prev))
182 return nullptr;
183 if (!exprs.append(voidNode))
184 return nullptr;
185
186 return new(lifo) AstFirst(Move(exprs));
187 }
188
189 return voidNode;
190 }
191
startFunction(AstDecodeOpIter * iter,const ValTypeVector * locals,ExprType retType)192 void startFunction(AstDecodeOpIter* iter, const ValTypeVector* locals, ExprType retType)
193 {
194 iter_ = iter;
195 locals_ = locals;
196 currentLabelIndex_ = 0;
197 retType_ = retType;
198 }
endFunction()199 void endFunction()
200 {
201 iter_ = nullptr;
202 locals_ = nullptr;
203 retType_ = ExprType::Limit;
204 MOZ_ASSERT(blockLabels_.length() == 0);
205 }
nextLabelIndex()206 uint32_t nextLabelIndex()
207 {
208 return currentLabelIndex_++;
209 }
210 };
211
212 static bool
GenerateName(AstDecodeContext & c,const AstName & prefix,uint32_t index,AstName * name)213 GenerateName(AstDecodeContext& c, const AstName& prefix, uint32_t index, AstName* name)
214 {
215 if (!c.generateNames) {
216 *name = AstName();
217 return true;
218 }
219
220 AstVector<char16_t> result(c.lifo);
221 if (!result.append(u'$'))
222 return false;
223 if (!result.append(prefix.begin(), prefix.length()))
224 return false;
225
226 uint32_t tmp = index;
227 do {
228 if (!result.append(u'0'))
229 return false;
230 tmp /= 10;
231 } while (tmp);
232
233 if (index) {
234 char16_t* p = result.end();
235 for (tmp = index; tmp; tmp /= 10)
236 *(--p) = u'0' + (tmp % 10);
237 }
238
239 size_t length = result.length();
240 char16_t* begin = result.extractOrCopyRawBuffer();
241 if (!begin)
242 return false;
243
244 *name = AstName(begin, length);
245 return true;
246 }
247
248 static bool
GenerateRef(AstDecodeContext & c,const AstName & prefix,uint32_t index,AstRef * ref)249 GenerateRef(AstDecodeContext& c, const AstName& prefix, uint32_t index, AstRef* ref)
250 {
251 MOZ_ASSERT(index != AstNoIndex);
252
253 if (!c.generateNames) {
254 *ref = AstRef(index);
255 return true;
256 }
257
258 AstName name;
259 if (!GenerateName(c, prefix, index, &name))
260 return false;
261 MOZ_ASSERT(!name.empty());
262
263 *ref = AstRef(name);
264 ref->setIndex(index);
265 return true;
266 }
267
268 static bool
AstDecodeCallArgs(AstDecodeContext & c,const AstSig & sig,AstExprVector * funcArgs)269 AstDecodeCallArgs(AstDecodeContext& c, const AstSig& sig, AstExprVector* funcArgs)
270 {
271 MOZ_ASSERT(c.iter().inReachableCode());
272
273 const AstValTypeVector& args = sig.args();
274 uint32_t numArgs = args.length();
275
276 if (!funcArgs->resize(numArgs))
277 return false;
278
279 for (size_t i = 0; i < numArgs; ++i) {
280 ValType argType = args[i];
281 AstDecodeStackItem item;
282 if (!c.iter().readCallArg(argType, numArgs, i, nullptr))
283 return false;
284 (*funcArgs)[i] = c.exprs()[c.exprs().length() - numArgs + i].expr;
285 }
286 c.exprs().shrinkBy(numArgs);
287
288 return c.iter().readCallArgsEnd(numArgs);
289 }
290
291 static bool
AstDecodeCallReturn(AstDecodeContext & c,const AstSig & sig)292 AstDecodeCallReturn(AstDecodeContext& c, const AstSig& sig)
293 {
294 return c.iter().readCallReturn(sig.ret());
295 }
296
297 static bool
298 AstDecodeExpr(AstDecodeContext& c);
299
300 static bool
AstDecodeDrop(AstDecodeContext & c)301 AstDecodeDrop(AstDecodeContext& c)
302 {
303 if (!c.iter().readDrop())
304 return false;
305
306 AstDecodeStackItem value = c.popCopy();
307
308 AstExpr* tmp = new(c.lifo) AstDrop(*value.expr);
309 if (!tmp)
310 return false;
311
312 tmp = c.handleVoidExpr(tmp);
313 if (!tmp)
314 return false;
315
316 if (!c.push(AstDecodeStackItem(tmp)))
317 return false;
318
319 return true;
320 }
321
322 static bool
AstDecodeCall(AstDecodeContext & c)323 AstDecodeCall(AstDecodeContext& c)
324 {
325 uint32_t funcIndex;
326 if (!c.iter().readCall(&funcIndex))
327 return false;
328
329 if (!c.iter().inReachableCode())
330 return true;
331
332 uint32_t sigIndex;
333 AstRef funcRef;
334 if (funcIndex < c.module().numFuncImports()) {
335 AstImport* import = c.module().imports()[funcIndex];
336 sigIndex = import->funcSig().index();
337 funcRef = AstRef(import->name());
338 } else {
339 uint32_t funcDefIndex = funcIndex - c.module().numFuncImports();
340 if (funcDefIndex >= c.funcDefSigs().length())
341 return c.iter().fail("callee index out of range");
342
343 sigIndex = c.funcDefSigs()[funcDefIndex];
344
345 if (!GenerateRef(c, AstName(u"func"), funcIndex, &funcRef))
346 return false;
347 }
348
349 const AstSig* sig = c.module().sigs()[sigIndex];
350
351 AstExprVector args(c.lifo);
352 if (!AstDecodeCallArgs(c, *sig, &args))
353 return false;
354
355 if (!AstDecodeCallReturn(c, *sig))
356 return false;
357
358 AstCall* call = new(c.lifo) AstCall(Op::Call, sig->ret(), funcRef, Move(args));
359 if (!call)
360 return false;
361
362 AstExpr* result = call;
363 if (IsVoid(sig->ret()))
364 result = c.handleVoidExpr(call);
365
366 if (!c.push(AstDecodeStackItem(result)))
367 return false;
368
369 return true;
370 }
371
372 static bool
AstDecodeCallIndirect(AstDecodeContext & c)373 AstDecodeCallIndirect(AstDecodeContext& c)
374 {
375 uint32_t sigIndex;
376 if (!c.iter().readCallIndirect(&sigIndex, nullptr))
377 return false;
378
379 if (!c.iter().inReachableCode())
380 return true;
381
382 if (sigIndex >= c.module().sigs().length())
383 return c.iter().fail("signature index out of range");
384
385 AstDecodeStackItem index = c.popCopy();
386
387 AstRef sigRef;
388 if (!GenerateRef(c, AstName(u"type"), sigIndex, &sigRef))
389 return false;
390
391 const AstSig* sig = c.module().sigs()[sigIndex];
392 AstExprVector args(c.lifo);
393 if (!AstDecodeCallArgs(c, *sig, &args))
394 return false;
395
396 if (!AstDecodeCallReturn(c, *sig))
397 return false;
398
399 AstCallIndirect* call = new(c.lifo) AstCallIndirect(sigRef, sig->ret(),
400 Move(args), index.expr);
401 if (!call)
402 return false;
403
404 AstExpr* result = call;
405 if (IsVoid(sig->ret()))
406 result = c.handleVoidExpr(call);
407
408 if (!c.push(AstDecodeStackItem(result)))
409 return false;
410
411 return true;
412 }
413
414 static bool
AstDecodeGetBlockRef(AstDecodeContext & c,uint32_t depth,AstRef * ref)415 AstDecodeGetBlockRef(AstDecodeContext& c, uint32_t depth, AstRef* ref)
416 {
417 if (!c.generateNames || depth >= c.blockLabels().length()) {
418 // Also ignoring if it's a function body label.
419 *ref = AstRef(depth);
420 return true;
421 }
422
423 uint32_t index = c.blockLabels().length() - depth - 1;
424 if (c.blockLabels()[index].empty()) {
425 if (!GenerateName(c, AstName(u"label"), c.nextLabelIndex(), &c.blockLabels()[index]))
426 return false;
427 }
428 *ref = AstRef(c.blockLabels()[index]);
429 ref->setIndex(depth);
430 return true;
431 }
432
433 static bool
AstDecodeBrTable(AstDecodeContext & c)434 AstDecodeBrTable(AstDecodeContext& c)
435 {
436 uint32_t tableLength;
437 ExprType type;
438 if (!c.iter().readBrTable(&tableLength, &type, nullptr, nullptr))
439 return false;
440
441 AstRefVector table(c.lifo);
442 if (!table.resize(tableLength))
443 return false;
444
445 uint32_t depth;
446 for (size_t i = 0, e = tableLength; i < e; ++i) {
447 if (!c.iter().readBrTableEntry(&type, nullptr, &depth))
448 return false;
449 if (!AstDecodeGetBlockRef(c, depth, &table[i]))
450 return false;
451 }
452
453 // Read the default label.
454 if (!c.iter().readBrTableDefault(&type, nullptr, &depth))
455 return false;
456
457 AstDecodeStackItem index = c.popCopy();
458 AstDecodeStackItem value;
459 if (!IsVoid(type))
460 value = c.popCopy();
461
462 AstRef def;
463 if (!AstDecodeGetBlockRef(c, depth, &def))
464 return false;
465
466 AstBranchTable* branchTable = new(c.lifo) AstBranchTable(*index.expr,
467 def, Move(table), value.expr);
468 if (!branchTable)
469 return false;
470
471 if (!c.push(AstDecodeStackItem(branchTable)))
472 return false;
473
474 return true;
475 }
476
477 static bool
AstDecodeBlock(AstDecodeContext & c,Op op)478 AstDecodeBlock(AstDecodeContext& c, Op op)
479 {
480 MOZ_ASSERT(op == Op::Block || op == Op::Loop);
481
482 if (!c.blockLabels().append(AstName()))
483 return false;
484
485 if (op == Op::Loop) {
486 if (!c.iter().readLoop())
487 return false;
488 } else {
489 if (!c.iter().readBlock())
490 return false;
491 }
492
493 if (!c.depths().append(c.exprs().length()))
494 return false;
495
496 ExprType type;
497 while (true) {
498 if (!AstDecodeExpr(c))
499 return false;
500
501 const AstDecodeStackItem& item = c.top();
502 if (!item.expr) { // Op::End was found
503 type = item.type;
504 c.popBack();
505 break;
506 }
507 }
508
509 AstExprVector exprs(c.lifo);
510 for (auto i = c.exprs().begin() + c.depths().back(), e = c.exprs().end();
511 i != e; ++i) {
512 if (!exprs.append(i->expr))
513 return false;
514 }
515 c.exprs().shrinkTo(c.depths().popCopy());
516
517 AstName name = c.blockLabels().popCopy();
518 AstBlock* block = new(c.lifo) AstBlock(op, type, name, Move(exprs));
519 if (!block)
520 return false;
521
522 AstExpr* result = block;
523 if (IsVoid(type))
524 result = c.handleVoidExpr(block);
525
526 if (!c.push(AstDecodeStackItem(result)))
527 return false;
528
529 return true;
530 }
531
532 static bool
AstDecodeIf(AstDecodeContext & c)533 AstDecodeIf(AstDecodeContext& c)
534 {
535 if (!c.iter().readIf(nullptr))
536 return false;
537
538 AstDecodeStackItem cond = c.popCopy();
539
540 bool hasElse = false;
541
542 if (!c.depths().append(c.exprs().length()))
543 return false;
544
545 if (!c.blockLabels().append(AstName()))
546 return false;
547
548 ExprType type;
549 while (true) {
550 if (!AstDecodeExpr(c))
551 return false;
552
553 const AstDecodeStackItem& item = c.top();
554 if (!item.expr) { // Op::End was found
555 hasElse = item.terminationKind == AstDecodeTerminationKind::Else;
556 type = item.type;
557 c.popBack();
558 break;
559 }
560 }
561
562 AstExprVector thenExprs(c.lifo);
563 for (auto i = c.exprs().begin() + c.depths().back(), e = c.exprs().end();
564 i != e; ++i) {
565 if (!thenExprs.append(i->expr))
566 return false;
567 }
568 c.exprs().shrinkTo(c.depths().back());
569
570 AstExprVector elseExprs(c.lifo);
571 if (hasElse) {
572 while (true) {
573 if (!AstDecodeExpr(c))
574 return false;
575
576 const AstDecodeStackItem& item = c.top();
577 if (!item.expr) { // Op::End was found
578 c.popBack();
579 break;
580 }
581 }
582
583 for (auto i = c.exprs().begin() + c.depths().back(), e = c.exprs().end();
584 i != e; ++i) {
585 if (!elseExprs.append(i->expr))
586 return false;
587 }
588 c.exprs().shrinkTo(c.depths().back());
589 }
590
591 c.depths().popBack();
592
593 AstName name = c.blockLabels().popCopy();
594
595 AstIf* if_ = new(c.lifo) AstIf(type, cond.expr, name, Move(thenExprs), Move(elseExprs));
596 if (!if_)
597 return false;
598
599 AstExpr* result = if_;
600 if (IsVoid(type))
601 result = c.handleVoidExpr(if_);
602
603 if (!c.push(AstDecodeStackItem(result)))
604 return false;
605
606 return true;
607 }
608
609 static bool
AstDecodeEnd(AstDecodeContext & c)610 AstDecodeEnd(AstDecodeContext& c)
611 {
612 LabelKind kind;
613 ExprType type;
614 if (!c.iter().readEnd(&kind, &type, nullptr))
615 return false;
616
617 if (!c.push(AstDecodeStackItem(AstDecodeTerminationKind::End, type)))
618 return false;
619
620 return true;
621 }
622
623 static bool
AstDecodeElse(AstDecodeContext & c)624 AstDecodeElse(AstDecodeContext& c)
625 {
626 ExprType type;
627
628 if (!c.iter().readElse(&type, nullptr))
629 return false;
630
631 if (!c.push(AstDecodeStackItem(AstDecodeTerminationKind::Else, type)))
632 return false;
633
634 return true;
635 }
636
637 static bool
AstDecodeNop(AstDecodeContext & c)638 AstDecodeNop(AstDecodeContext& c)
639 {
640 if (!c.iter().readNop())
641 return false;
642
643 AstExpr* tmp = new(c.lifo) AstNop();
644 if (!tmp)
645 return false;
646
647 tmp = c.handleVoidExpr(tmp);
648 if (!tmp)
649 return false;
650
651 if (!c.push(AstDecodeStackItem(tmp)))
652 return false;
653
654 return true;
655 }
656
657 static bool
AstDecodeUnary(AstDecodeContext & c,ValType type,Op op)658 AstDecodeUnary(AstDecodeContext& c, ValType type, Op op)
659 {
660 if (!c.iter().readUnary(type, nullptr))
661 return false;
662
663 AstDecodeStackItem operand = c.popCopy();
664
665 AstUnaryOperator* unary = new(c.lifo) AstUnaryOperator(op, operand.expr);
666 if (!unary)
667 return false;
668
669 if (!c.push(AstDecodeStackItem(unary)))
670 return false;
671
672 return true;
673 }
674
675 static bool
AstDecodeBinary(AstDecodeContext & c,ValType type,Op op)676 AstDecodeBinary(AstDecodeContext& c, ValType type, Op op)
677 {
678 if (!c.iter().readBinary(type, nullptr, nullptr))
679 return false;
680
681 AstDecodeStackItem rhs = c.popCopy();
682 AstDecodeStackItem lhs = c.popCopy();
683
684 AstBinaryOperator* binary = new(c.lifo) AstBinaryOperator(op, lhs.expr, rhs.expr);
685 if (!binary)
686 return false;
687
688 if (!c.push(AstDecodeStackItem(binary)))
689 return false;
690
691 return true;
692 }
693
694 static bool
AstDecodeSelect(AstDecodeContext & c)695 AstDecodeSelect(AstDecodeContext& c)
696 {
697 ValType type;
698 if (!c.iter().readSelect(&type, nullptr, nullptr, nullptr))
699 return false;
700
701 AstDecodeStackItem selectFalse = c.popCopy();
702 AstDecodeStackItem selectTrue = c.popCopy();
703 AstDecodeStackItem cond = c.popCopy();
704
705 AstTernaryOperator* ternary = new(c.lifo) AstTernaryOperator(Op::Select, cond.expr, selectTrue.expr, selectFalse.expr);
706 if (!ternary)
707 return false;
708
709 if (!c.push(AstDecodeStackItem(ternary)))
710 return false;
711
712 return true;
713 }
714
715 static bool
AstDecodeComparison(AstDecodeContext & c,ValType type,Op op)716 AstDecodeComparison(AstDecodeContext& c, ValType type, Op op)
717 {
718 if (!c.iter().readComparison(type, nullptr, nullptr))
719 return false;
720
721 AstDecodeStackItem rhs = c.popCopy();
722 AstDecodeStackItem lhs = c.popCopy();
723
724 AstComparisonOperator* comparison = new(c.lifo) AstComparisonOperator(op, lhs.expr, rhs.expr);
725 if (!comparison)
726 return false;
727
728 if (!c.push(AstDecodeStackItem(comparison)))
729 return false;
730
731 return true;
732 }
733
734 static bool
AstDecodeConversion(AstDecodeContext & c,ValType fromType,ValType toType,Op op)735 AstDecodeConversion(AstDecodeContext& c, ValType fromType, ValType toType, Op op)
736 {
737 if (!c.iter().readConversion(fromType, toType, nullptr))
738 return false;
739
740 AstDecodeStackItem operand = c.popCopy();
741
742 AstConversionOperator* conversion = new(c.lifo) AstConversionOperator(op, operand.expr);
743 if (!conversion)
744 return false;
745
746 if (!c.push(AstDecodeStackItem(conversion)))
747 return false;
748
749 return true;
750 }
751
752 static AstLoadStoreAddress
AstDecodeLoadStoreAddress(const LinearMemoryAddress<Nothing> & addr,const AstDecodeStackItem & item)753 AstDecodeLoadStoreAddress(const LinearMemoryAddress<Nothing>& addr, const AstDecodeStackItem& item)
754 {
755 uint32_t flags = FloorLog2(addr.align);
756 return AstLoadStoreAddress(item.expr, flags, addr.offset);
757 }
758
759 static bool
AstDecodeLoad(AstDecodeContext & c,ValType type,uint32_t byteSize,Op op)760 AstDecodeLoad(AstDecodeContext& c, ValType type, uint32_t byteSize, Op op)
761 {
762 LinearMemoryAddress<Nothing> addr;
763 if (!c.iter().readLoad(type, byteSize, &addr))
764 return false;
765
766 AstDecodeStackItem item = c.popCopy();
767
768 AstLoad* load = new(c.lifo) AstLoad(op, AstDecodeLoadStoreAddress(addr, item));
769 if (!load)
770 return false;
771
772 if (!c.push(AstDecodeStackItem(load)))
773 return false;
774
775 return true;
776 }
777
778 static bool
AstDecodeStore(AstDecodeContext & c,ValType type,uint32_t byteSize,Op op)779 AstDecodeStore(AstDecodeContext& c, ValType type, uint32_t byteSize, Op op)
780 {
781 LinearMemoryAddress<Nothing> addr;
782 if (!c.iter().readStore(type, byteSize, &addr, nullptr))
783 return false;
784
785 AstDecodeStackItem value = c.popCopy();
786 AstDecodeStackItem item = c.popCopy();
787
788 AstStore* store = new(c.lifo) AstStore(op, AstDecodeLoadStoreAddress(addr, item), value.expr);
789 if (!store)
790 return false;
791
792 AstExpr* wrapped = c.handleVoidExpr(store);
793 if (!wrapped)
794 return false;
795
796 if (!c.push(AstDecodeStackItem(wrapped)))
797 return false;
798
799 return true;
800 }
801
802 static bool
AstDecodeCurrentMemory(AstDecodeContext & c)803 AstDecodeCurrentMemory(AstDecodeContext& c)
804 {
805 if (!c.iter().readCurrentMemory())
806 return false;
807
808 AstCurrentMemory* gm = new(c.lifo) AstCurrentMemory();
809 if (!gm)
810 return false;
811
812 if (!c.push(AstDecodeStackItem(gm)))
813 return false;
814
815 return true;
816 }
817
818 static bool
AstDecodeGrowMemory(AstDecodeContext & c)819 AstDecodeGrowMemory(AstDecodeContext& c)
820 {
821 if (!c.iter().readGrowMemory(nullptr))
822 return false;
823
824 AstDecodeStackItem operand = c.popCopy();
825
826 AstGrowMemory* gm = new(c.lifo) AstGrowMemory(operand.expr);
827 if (!gm)
828 return false;
829
830 if (!c.push(AstDecodeStackItem(gm)))
831 return false;
832
833 return true;
834 }
835
836 static bool
AstDecodeBranch(AstDecodeContext & c,Op op)837 AstDecodeBranch(AstDecodeContext& c, Op op)
838 {
839 MOZ_ASSERT(op == Op::Br || op == Op::BrIf);
840
841 uint32_t depth;
842 ExprType type;
843 AstDecodeStackItem value;
844 AstDecodeStackItem cond;
845 if (op == Op::Br) {
846 if (!c.iter().readBr(&depth, &type, nullptr))
847 return false;
848 if (!IsVoid(type))
849 value = c.popCopy();
850 } else {
851 if (!c.iter().readBrIf(&depth, &type, nullptr, nullptr))
852 return false;
853 if (!IsVoid(type))
854 value = c.popCopy();
855 cond = c.popCopy();
856 }
857
858 AstRef depthRef;
859 if (!AstDecodeGetBlockRef(c, depth, &depthRef))
860 return false;
861
862 if (op == Op::Br || !value.expr)
863 type = ExprType::Void;
864 AstBranch* branch = new(c.lifo) AstBranch(op, type, cond.expr, depthRef, value.expr);
865 if (!branch)
866 return false;
867
868 if (!c.push(AstDecodeStackItem(branch)))
869 return false;
870
871 return true;
872 }
873
874 static bool
AstDecodeGetLocal(AstDecodeContext & c)875 AstDecodeGetLocal(AstDecodeContext& c)
876 {
877 uint32_t getLocalId;
878 if (!c.iter().readGetLocal(c.locals(), &getLocalId))
879 return false;
880
881 AstRef localRef;
882 if (!GenerateRef(c, AstName(u"var"), getLocalId, &localRef))
883 return false;
884
885 AstGetLocal* getLocal = new(c.lifo) AstGetLocal(localRef);
886 if (!getLocal)
887 return false;
888
889 if (!c.push(AstDecodeStackItem(getLocal)))
890 return false;
891
892 return true;
893 }
894
895 static bool
AstDecodeSetLocal(AstDecodeContext & c)896 AstDecodeSetLocal(AstDecodeContext& c)
897 {
898 uint32_t setLocalId;
899 if (!c.iter().readSetLocal(c.locals(), &setLocalId, nullptr))
900 return false;
901
902 AstDecodeStackItem setLocalValue = c.popCopy();
903
904 AstRef localRef;
905 if (!GenerateRef(c, AstName(u"var"), setLocalId, &localRef))
906 return false;
907
908 AstSetLocal* setLocal = new(c.lifo) AstSetLocal(localRef, *setLocalValue.expr);
909 if (!setLocal)
910 return false;
911
912 AstExpr* expr = c.handleVoidExpr(setLocal);
913 if (!expr)
914 return false;
915
916 if (!c.push(AstDecodeStackItem(expr)))
917 return false;
918
919 return true;
920 }
921
922 static bool
AstDecodeTeeLocal(AstDecodeContext & c)923 AstDecodeTeeLocal(AstDecodeContext& c)
924 {
925 uint32_t teeLocalId;
926 if (!c.iter().readTeeLocal(c.locals(), &teeLocalId, nullptr))
927 return false;
928
929 AstDecodeStackItem teeLocalValue = c.popCopy();
930
931 AstRef localRef;
932 if (!GenerateRef(c, AstName(u"var"), teeLocalId, &localRef))
933 return false;
934
935 AstTeeLocal* teeLocal = new(c.lifo) AstTeeLocal(localRef, *teeLocalValue.expr);
936 if (!teeLocal)
937 return false;
938
939 if (!c.push(AstDecodeStackItem(teeLocal)))
940 return false;
941
942 return true;
943 }
944
945 static bool
AstDecodeGetGlobal(AstDecodeContext & c)946 AstDecodeGetGlobal(AstDecodeContext& c)
947 {
948 uint32_t globalId;
949 if (!c.iter().readGetGlobal(c.globalDescs(), &globalId))
950 return false;
951
952 AstRef globalRef;
953 if (!GenerateRef(c, AstName(u"global"), globalId, &globalRef))
954 return false;
955
956 auto* getGlobal = new(c.lifo) AstGetGlobal(globalRef);
957 if (!getGlobal)
958 return false;
959
960 if (!c.push(AstDecodeStackItem(getGlobal)))
961 return false;
962
963 return true;
964 }
965
966 static bool
AstDecodeSetGlobal(AstDecodeContext & c)967 AstDecodeSetGlobal(AstDecodeContext& c)
968 {
969 uint32_t globalId;
970 if (!c.iter().readSetGlobal(c.globalDescs(), &globalId, nullptr))
971 return false;
972
973 AstDecodeStackItem value = c.popCopy();
974
975 AstRef globalRef;
976 if (!GenerateRef(c, AstName(u"global"), globalId, &globalRef))
977 return false;
978
979 auto* setGlobal = new(c.lifo) AstSetGlobal(globalRef, *value.expr);
980 if (!setGlobal)
981 return false;
982
983 AstExpr* expr = c.handleVoidExpr(setGlobal);
984 if (!expr)
985 return false;
986
987 if (!c.push(AstDecodeStackItem(expr)))
988 return false;
989
990 return true;
991 }
992
993 static bool
AstDecodeReturn(AstDecodeContext & c)994 AstDecodeReturn(AstDecodeContext& c)
995 {
996 if (!c.iter().readReturn(nullptr))
997 return false;
998
999 AstDecodeStackItem result;
1000 if (!IsVoid(c.retType()))
1001 result = c.popCopy();
1002
1003 AstReturn* ret = new(c.lifo) AstReturn(result.expr);
1004 if (!ret)
1005 return false;
1006
1007 if (!c.push(AstDecodeStackItem(ret)))
1008 return false;
1009
1010 return true;
1011 }
1012
1013 static bool
AstDecodeExpr(AstDecodeContext & c)1014 AstDecodeExpr(AstDecodeContext& c)
1015 {
1016 uint32_t exprOffset = c.iter().currentOffset();
1017 uint16_t op;
1018 if (!c.iter().readOp(&op))
1019 return false;
1020
1021 AstExpr* tmp;
1022 switch (op) {
1023 case uint16_t(Op::Nop):
1024 if (!AstDecodeNop(c))
1025 return false;
1026 break;
1027 case uint16_t(Op::Drop):
1028 if (!AstDecodeDrop(c))
1029 return false;
1030 break;
1031 case uint16_t(Op::Call):
1032 if (!AstDecodeCall(c))
1033 return false;
1034 break;
1035 case uint16_t(Op::CallIndirect):
1036 if (!AstDecodeCallIndirect(c))
1037 return false;
1038 break;
1039 case uint16_t(Op::I32Const):
1040 int32_t i32;
1041 if (!c.iter().readI32Const(&i32))
1042 return false;
1043 tmp = new(c.lifo) AstConst(Val((uint32_t)i32));
1044 if (!tmp || !c.push(AstDecodeStackItem(tmp)))
1045 return false;
1046 break;
1047 case uint16_t(Op::I64Const):
1048 int64_t i64;
1049 if (!c.iter().readI64Const(&i64))
1050 return false;
1051 tmp = new(c.lifo) AstConst(Val((uint64_t)i64));
1052 if (!tmp || !c.push(AstDecodeStackItem(tmp)))
1053 return false;
1054 break;
1055 case uint16_t(Op::F32Const): {
1056 RawF32 f32;
1057 if (!c.iter().readF32Const(&f32))
1058 return false;
1059 tmp = new(c.lifo) AstConst(Val(f32));
1060 if (!tmp || !c.push(AstDecodeStackItem(tmp)))
1061 return false;
1062 break;
1063 }
1064 case uint16_t(Op::F64Const): {
1065 RawF64 f64;
1066 if (!c.iter().readF64Const(&f64))
1067 return false;
1068 tmp = new(c.lifo) AstConst(Val(f64));
1069 if (!tmp || !c.push(AstDecodeStackItem(tmp)))
1070 return false;
1071 break;
1072 }
1073 case uint16_t(Op::GetLocal):
1074 if (!AstDecodeGetLocal(c))
1075 return false;
1076 break;
1077 case uint16_t(Op::SetLocal):
1078 if (!AstDecodeSetLocal(c))
1079 return false;
1080 break;
1081 case uint16_t(Op::TeeLocal):
1082 if (!AstDecodeTeeLocal(c))
1083 return false;
1084 break;
1085 case uint16_t(Op::Select):
1086 if (!AstDecodeSelect(c))
1087 return false;
1088 break;
1089 case uint16_t(Op::Block):
1090 case uint16_t(Op::Loop):
1091 if (!AstDecodeBlock(c, Op(op)))
1092 return false;
1093 break;
1094 case uint16_t(Op::If):
1095 if (!AstDecodeIf(c))
1096 return false;
1097 break;
1098 case uint16_t(Op::Else):
1099 if (!AstDecodeElse(c))
1100 return false;
1101 break;
1102 case uint16_t(Op::End):
1103 if (!AstDecodeEnd(c))
1104 return false;
1105 break;
1106 case uint16_t(Op::I32Clz):
1107 case uint16_t(Op::I32Ctz):
1108 case uint16_t(Op::I32Popcnt):
1109 if (!AstDecodeUnary(c, ValType::I32, Op(op)))
1110 return false;
1111 break;
1112 case uint16_t(Op::I64Clz):
1113 case uint16_t(Op::I64Ctz):
1114 case uint16_t(Op::I64Popcnt):
1115 if (!AstDecodeUnary(c, ValType::I64, Op(op)))
1116 return false;
1117 break;
1118 case uint16_t(Op::F32Abs):
1119 case uint16_t(Op::F32Neg):
1120 case uint16_t(Op::F32Ceil):
1121 case uint16_t(Op::F32Floor):
1122 case uint16_t(Op::F32Sqrt):
1123 case uint16_t(Op::F32Trunc):
1124 case uint16_t(Op::F32Nearest):
1125 if (!AstDecodeUnary(c, ValType::F32, Op(op)))
1126 return false;
1127 break;
1128 case uint16_t(Op::F64Abs):
1129 case uint16_t(Op::F64Neg):
1130 case uint16_t(Op::F64Ceil):
1131 case uint16_t(Op::F64Floor):
1132 case uint16_t(Op::F64Sqrt):
1133 case uint16_t(Op::F64Trunc):
1134 case uint16_t(Op::F64Nearest):
1135 if (!AstDecodeUnary(c, ValType::F64, Op(op)))
1136 return false;
1137 break;
1138 case uint16_t(Op::I32Add):
1139 case uint16_t(Op::I32Sub):
1140 case uint16_t(Op::I32Mul):
1141 case uint16_t(Op::I32DivS):
1142 case uint16_t(Op::I32DivU):
1143 case uint16_t(Op::I32RemS):
1144 case uint16_t(Op::I32RemU):
1145 case uint16_t(Op::I32And):
1146 case uint16_t(Op::I32Or):
1147 case uint16_t(Op::I32Xor):
1148 case uint16_t(Op::I32Shl):
1149 case uint16_t(Op::I32ShrS):
1150 case uint16_t(Op::I32ShrU):
1151 case uint16_t(Op::I32Rotl):
1152 case uint16_t(Op::I32Rotr):
1153 if (!AstDecodeBinary(c, ValType::I32, Op(op)))
1154 return false;
1155 break;
1156 case uint16_t(Op::I64Add):
1157 case uint16_t(Op::I64Sub):
1158 case uint16_t(Op::I64Mul):
1159 case uint16_t(Op::I64DivS):
1160 case uint16_t(Op::I64DivU):
1161 case uint16_t(Op::I64RemS):
1162 case uint16_t(Op::I64RemU):
1163 case uint16_t(Op::I64And):
1164 case uint16_t(Op::I64Or):
1165 case uint16_t(Op::I64Xor):
1166 case uint16_t(Op::I64Shl):
1167 case uint16_t(Op::I64ShrS):
1168 case uint16_t(Op::I64ShrU):
1169 case uint16_t(Op::I64Rotl):
1170 case uint16_t(Op::I64Rotr):
1171 if (!AstDecodeBinary(c, ValType::I64, Op(op)))
1172 return false;
1173 break;
1174 case uint16_t(Op::F32Add):
1175 case uint16_t(Op::F32Sub):
1176 case uint16_t(Op::F32Mul):
1177 case uint16_t(Op::F32Div):
1178 case uint16_t(Op::F32Min):
1179 case uint16_t(Op::F32Max):
1180 case uint16_t(Op::F32CopySign):
1181 if (!AstDecodeBinary(c, ValType::F32, Op(op)))
1182 return false;
1183 break;
1184 case uint16_t(Op::F64Add):
1185 case uint16_t(Op::F64Sub):
1186 case uint16_t(Op::F64Mul):
1187 case uint16_t(Op::F64Div):
1188 case uint16_t(Op::F64Min):
1189 case uint16_t(Op::F64Max):
1190 case uint16_t(Op::F64CopySign):
1191 if (!AstDecodeBinary(c, ValType::F64, Op(op)))
1192 return false;
1193 break;
1194 case uint16_t(Op::I32Eq):
1195 case uint16_t(Op::I32Ne):
1196 case uint16_t(Op::I32LtS):
1197 case uint16_t(Op::I32LtU):
1198 case uint16_t(Op::I32LeS):
1199 case uint16_t(Op::I32LeU):
1200 case uint16_t(Op::I32GtS):
1201 case uint16_t(Op::I32GtU):
1202 case uint16_t(Op::I32GeS):
1203 case uint16_t(Op::I32GeU):
1204 if (!AstDecodeComparison(c, ValType::I32, Op(op)))
1205 return false;
1206 break;
1207 case uint16_t(Op::I64Eq):
1208 case uint16_t(Op::I64Ne):
1209 case uint16_t(Op::I64LtS):
1210 case uint16_t(Op::I64LtU):
1211 case uint16_t(Op::I64LeS):
1212 case uint16_t(Op::I64LeU):
1213 case uint16_t(Op::I64GtS):
1214 case uint16_t(Op::I64GtU):
1215 case uint16_t(Op::I64GeS):
1216 case uint16_t(Op::I64GeU):
1217 if (!AstDecodeComparison(c, ValType::I64, Op(op)))
1218 return false;
1219 break;
1220 case uint16_t(Op::F32Eq):
1221 case uint16_t(Op::F32Ne):
1222 case uint16_t(Op::F32Lt):
1223 case uint16_t(Op::F32Le):
1224 case uint16_t(Op::F32Gt):
1225 case uint16_t(Op::F32Ge):
1226 if (!AstDecodeComparison(c, ValType::F32, Op(op)))
1227 return false;
1228 break;
1229 case uint16_t(Op::F64Eq):
1230 case uint16_t(Op::F64Ne):
1231 case uint16_t(Op::F64Lt):
1232 case uint16_t(Op::F64Le):
1233 case uint16_t(Op::F64Gt):
1234 case uint16_t(Op::F64Ge):
1235 if (!AstDecodeComparison(c, ValType::F64, Op(op)))
1236 return false;
1237 break;
1238 case uint16_t(Op::I32Eqz):
1239 if (!AstDecodeConversion(c, ValType::I32, ValType::I32, Op(op)))
1240 return false;
1241 break;
1242 case uint16_t(Op::I64Eqz):
1243 case uint16_t(Op::I32WrapI64):
1244 if (!AstDecodeConversion(c, ValType::I64, ValType::I32, Op(op)))
1245 return false;
1246 break;
1247 case uint16_t(Op::I32TruncSF32):
1248 case uint16_t(Op::I32TruncUF32):
1249 case uint16_t(Op::I32ReinterpretF32):
1250 if (!AstDecodeConversion(c, ValType::F32, ValType::I32, Op(op)))
1251 return false;
1252 break;
1253 case uint16_t(Op::I32TruncSF64):
1254 case uint16_t(Op::I32TruncUF64):
1255 if (!AstDecodeConversion(c, ValType::F64, ValType::I32, Op(op)))
1256 return false;
1257 break;
1258 case uint16_t(Op::I64ExtendSI32):
1259 case uint16_t(Op::I64ExtendUI32):
1260 if (!AstDecodeConversion(c, ValType::I32, ValType::I64, Op(op)))
1261 return false;
1262 break;
1263 case uint16_t(Op::I64TruncSF32):
1264 case uint16_t(Op::I64TruncUF32):
1265 if (!AstDecodeConversion(c, ValType::F32, ValType::I64, Op(op)))
1266 return false;
1267 break;
1268 case uint16_t(Op::I64TruncSF64):
1269 case uint16_t(Op::I64TruncUF64):
1270 case uint16_t(Op::I64ReinterpretF64):
1271 if (!AstDecodeConversion(c, ValType::F64, ValType::I64, Op(op)))
1272 return false;
1273 break;
1274 case uint16_t(Op::F32ConvertSI32):
1275 case uint16_t(Op::F32ConvertUI32):
1276 case uint16_t(Op::F32ReinterpretI32):
1277 if (!AstDecodeConversion(c, ValType::I32, ValType::F32, Op(op)))
1278 return false;
1279 break;
1280 case uint16_t(Op::F32ConvertSI64):
1281 case uint16_t(Op::F32ConvertUI64):
1282 if (!AstDecodeConversion(c, ValType::I64, ValType::F32, Op(op)))
1283 return false;
1284 break;
1285 case uint16_t(Op::F32DemoteF64):
1286 if (!AstDecodeConversion(c, ValType::F64, ValType::F32, Op(op)))
1287 return false;
1288 break;
1289 case uint16_t(Op::F64ConvertSI32):
1290 case uint16_t(Op::F64ConvertUI32):
1291 if (!AstDecodeConversion(c, ValType::I32, ValType::F64, Op(op)))
1292 return false;
1293 break;
1294 case uint16_t(Op::F64ConvertSI64):
1295 case uint16_t(Op::F64ConvertUI64):
1296 case uint16_t(Op::F64ReinterpretI64):
1297 if (!AstDecodeConversion(c, ValType::I64, ValType::F64, Op(op)))
1298 return false;
1299 break;
1300 case uint16_t(Op::F64PromoteF32):
1301 if (!AstDecodeConversion(c, ValType::F32, ValType::F64, Op(op)))
1302 return false;
1303 break;
1304 case uint16_t(Op::I32Load8S):
1305 case uint16_t(Op::I32Load8U):
1306 if (!AstDecodeLoad(c, ValType::I32, 1, Op(op)))
1307 return false;
1308 break;
1309 case uint16_t(Op::I32Load16S):
1310 case uint16_t(Op::I32Load16U):
1311 if (!AstDecodeLoad(c, ValType::I32, 2, Op(op)))
1312 return false;
1313 break;
1314 case uint16_t(Op::I32Load):
1315 if (!AstDecodeLoad(c, ValType::I32, 4, Op(op)))
1316 return false;
1317 break;
1318 case uint16_t(Op::I64Load8S):
1319 case uint16_t(Op::I64Load8U):
1320 if (!AstDecodeLoad(c, ValType::I64, 1, Op(op)))
1321 return false;
1322 break;
1323 case uint16_t(Op::I64Load16S):
1324 case uint16_t(Op::I64Load16U):
1325 if (!AstDecodeLoad(c, ValType::I64, 2, Op(op)))
1326 return false;
1327 break;
1328 case uint16_t(Op::I64Load32S):
1329 case uint16_t(Op::I64Load32U):
1330 if (!AstDecodeLoad(c, ValType::I64, 4, Op(op)))
1331 return false;
1332 break;
1333 case uint16_t(Op::I64Load):
1334 if (!AstDecodeLoad(c, ValType::I64, 8, Op(op)))
1335 return false;
1336 break;
1337 case uint16_t(Op::F32Load):
1338 if (!AstDecodeLoad(c, ValType::F32, 4, Op(op)))
1339 return false;
1340 break;
1341 case uint16_t(Op::F64Load):
1342 if (!AstDecodeLoad(c, ValType::F64, 8, Op(op)))
1343 return false;
1344 break;
1345 case uint16_t(Op::I32Store8):
1346 if (!AstDecodeStore(c, ValType::I32, 1, Op(op)))
1347 return false;
1348 break;
1349 case uint16_t(Op::I32Store16):
1350 if (!AstDecodeStore(c, ValType::I32, 2, Op(op)))
1351 return false;
1352 break;
1353 case uint16_t(Op::I32Store):
1354 if (!AstDecodeStore(c, ValType::I32, 4, Op(op)))
1355 return false;
1356 break;
1357 case uint16_t(Op::I64Store8):
1358 if (!AstDecodeStore(c, ValType::I64, 1, Op(op)))
1359 return false;
1360 break;
1361 case uint16_t(Op::I64Store16):
1362 if (!AstDecodeStore(c, ValType::I64, 2, Op(op)))
1363 return false;
1364 break;
1365 case uint16_t(Op::I64Store32):
1366 if (!AstDecodeStore(c, ValType::I64, 4, Op(op)))
1367 return false;
1368 break;
1369 case uint16_t(Op::I64Store):
1370 if (!AstDecodeStore(c, ValType::I64, 8, Op(op)))
1371 return false;
1372 break;
1373 case uint16_t(Op::F32Store):
1374 if (!AstDecodeStore(c, ValType::F32, 4, Op(op)))
1375 return false;
1376 break;
1377 case uint16_t(Op::F64Store):
1378 if (!AstDecodeStore(c, ValType::F64, 8, Op(op)))
1379 return false;
1380 break;
1381 case uint16_t(Op::CurrentMemory):
1382 if (!AstDecodeCurrentMemory(c))
1383 return false;
1384 break;
1385 case uint16_t(Op::GrowMemory):
1386 if (!AstDecodeGrowMemory(c))
1387 return false;
1388 break;
1389 case uint16_t(Op::SetGlobal):
1390 if (!AstDecodeSetGlobal(c))
1391 return false;
1392 break;
1393 case uint16_t(Op::GetGlobal):
1394 if (!AstDecodeGetGlobal(c))
1395 return false;
1396 break;
1397 case uint16_t(Op::Br):
1398 case uint16_t(Op::BrIf):
1399 if (!AstDecodeBranch(c, Op(op)))
1400 return false;
1401 break;
1402 case uint16_t(Op::BrTable):
1403 if (!AstDecodeBrTable(c))
1404 return false;
1405 break;
1406 case uint16_t(Op::Return):
1407 if (!AstDecodeReturn(c))
1408 return false;
1409 break;
1410 case uint16_t(Op::Unreachable):
1411 if (!c.iter().readUnreachable())
1412 return false;
1413 tmp = new(c.lifo) AstUnreachable();
1414 if (!tmp)
1415 return false;
1416 if (!c.push(AstDecodeStackItem(tmp)))
1417 return false;
1418 break;
1419 default:
1420 return c.iter().unrecognizedOpcode(op);
1421 }
1422
1423 AstExpr* lastExpr = c.top().expr;
1424 if (lastExpr)
1425 lastExpr->setOffset(exprOffset);
1426 return true;
1427 }
1428
1429 /*****************************************************************************/
1430 // wasm decoding and generation
1431
1432 static bool
AstDecodeTypeSection(AstDecodeContext & c,SigWithIdVector * sigs)1433 AstDecodeTypeSection(AstDecodeContext& c, SigWithIdVector* sigs)
1434 {
1435 if (!DecodeTypeSection(c.d, sigs))
1436 return false;
1437
1438 for (size_t sigIndex = 0; sigIndex < sigs->length(); sigIndex++) {
1439 const Sig& sig = (*sigs)[sigIndex];
1440
1441 AstValTypeVector args(c.lifo);
1442 if (!args.appendAll(sig.args()))
1443 return false;
1444
1445 AstSig sigNoName(Move(args), sig.ret());
1446 AstName sigName;
1447 if (!GenerateName(c, AstName(u"type"), sigIndex, &sigName))
1448 return false;
1449
1450 AstSig* astSig = new(c.lifo) AstSig(sigName, Move(sigNoName));
1451 if (!astSig || !c.module().append(astSig))
1452 return false;
1453 }
1454
1455 return true;
1456 }
1457
1458 static AstName
ToAstName(AstDecodeContext & c,const UniqueChars & name)1459 ToAstName(AstDecodeContext& c, const UniqueChars& name)
1460 {
1461 size_t len = strlen(name.get());
1462 char16_t* buffer = static_cast<char16_t *>(c.lifo.alloc(len * sizeof(char16_t)));
1463 if (!buffer)
1464 return AstName();
1465
1466 for (size_t i = 0; i < len; i++)
1467 buffer[i] = name.get()[i];
1468
1469 return AstName(buffer, len);
1470 }
1471
1472 static bool
AstDecodeImportSection(AstDecodeContext & c,const SigWithIdVector & sigs)1473 AstDecodeImportSection(AstDecodeContext& c, const SigWithIdVector& sigs)
1474 {
1475 Uint32Vector funcSigIndices;
1476 GlobalDescVector globals;
1477 TableDescVector tables;
1478 Maybe<Limits> memory;
1479 ImportVector imports;
1480 if (!DecodeImportSection(c.d, sigs, &funcSigIndices, &globals, &tables, &memory, &imports))
1481 return false;
1482
1483 size_t lastFunc = 0;
1484 size_t lastGlobal = 0;
1485 size_t lastTable = 0;
1486 size_t lastMemory = 0;
1487
1488 for (size_t importIndex = 0; importIndex < imports.length(); importIndex++) {
1489 const Import& import = imports[importIndex];
1490
1491 AstName moduleName = ToAstName(c, import.module);
1492 AstName fieldName = ToAstName(c, import.field);
1493
1494 AstImport* ast = nullptr;
1495 switch (import.kind) {
1496 case DefinitionKind::Function: {
1497 AstName importName;
1498 if (!GenerateName(c, AstName(u"import"), lastFunc, &importName))
1499 return false;
1500
1501 AstRef sigRef;
1502 if (!GenerateRef(c, AstName(u"type"), funcSigIndices[lastFunc], &sigRef))
1503 return false;
1504
1505 ast = new(c.lifo) AstImport(importName, moduleName, fieldName, sigRef);
1506 lastFunc++;
1507 break;
1508 }
1509 case DefinitionKind::Global: {
1510 AstName importName;
1511 if (!GenerateName(c, AstName(u"global"), lastGlobal, &importName))
1512 return false;
1513
1514 const GlobalDesc& global = globals[lastGlobal];
1515 ValType type = global.type();
1516 bool isMutable = global.isMutable();
1517
1518 if (!c.addGlobalDesc(type, isMutable, /* import */ true))
1519 return false;
1520
1521 ast = new(c.lifo) AstImport(importName, moduleName, fieldName,
1522 AstGlobal(importName, type, isMutable));
1523 lastGlobal++;
1524 break;
1525 }
1526 case DefinitionKind::Table: {
1527 AstName importName;
1528 if (!GenerateName(c, AstName(u"table"), lastTable, &importName))
1529 return false;
1530
1531 ast = new(c.lifo) AstImport(importName, moduleName, fieldName, DefinitionKind::Table,
1532 tables[lastTable].limits);
1533 lastTable++;
1534 break;
1535 }
1536 case DefinitionKind::Memory: {
1537 AstName importName;
1538 if (!GenerateName(c, AstName(u"memory"), lastMemory, &importName))
1539 return false;
1540
1541 ast = new(c.lifo) AstImport(importName, moduleName, fieldName, DefinitionKind::Memory,
1542 *memory);
1543 lastMemory++;
1544 break;
1545 }
1546 }
1547
1548 if (!ast || !c.module().append(ast))
1549 return false;
1550 }
1551
1552 return true;
1553 }
1554
1555 static bool
AstDecodeFunctionSection(AstDecodeContext & c,const SigWithIdVector & sigs)1556 AstDecodeFunctionSection(AstDecodeContext& c, const SigWithIdVector& sigs)
1557 {
1558 Uint32Vector funcSigIndexes;
1559 if (!DecodeFunctionSection(c.d, sigs, c.module().numFuncImports(), &funcSigIndexes))
1560 return false;
1561
1562 return c.funcDefSigs().appendAll(funcSigIndexes);
1563 }
1564
1565 static bool
AstDecodeTableSection(AstDecodeContext & c)1566 AstDecodeTableSection(AstDecodeContext& c)
1567 {
1568 uint32_t sectionStart, sectionSize;
1569 if (!c.d.startSection(SectionId::Table, §ionStart, §ionSize, "table"))
1570 return false;
1571 if (sectionStart == Decoder::NotStarted)
1572 return true;
1573
1574 uint32_t numTables;
1575 if (!c.d.readVarU32(&numTables))
1576 return c.d.fail("failed to read number of tables");
1577
1578 if (numTables != 1)
1579 return c.d.fail("the number of tables must be exactly one");
1580
1581 uint32_t typeConstructorValue;
1582 if (!c.d.readVarU32(&typeConstructorValue))
1583 return c.d.fail("expected type constructor kind");
1584
1585 if (typeConstructorValue != uint32_t(TypeCode::AnyFunc))
1586 return c.d.fail("unknown type constructor kind");
1587
1588 Limits table;
1589 if (!DecodeLimits(c.d, &table))
1590 return false;
1591
1592 if (table.initial > MaxTableElems)
1593 return c.d.fail("too many table elements");
1594
1595 if (c.module().hasTable())
1596 return c.d.fail("already have a table");
1597
1598 AstName name;
1599 if (!GenerateName(c, AstName(u"table"), c.module().tables().length(), &name))
1600 return false;
1601
1602 if (!c.module().addTable(name, table))
1603 return false;
1604
1605 if (!c.d.finishSection(sectionStart, sectionSize, "table"))
1606 return false;
1607
1608 return true;
1609 }
1610
1611 static bool
AstDecodeName(AstDecodeContext & c,AstName * name)1612 AstDecodeName(AstDecodeContext& c, AstName* name)
1613 {
1614 uint32_t length;
1615 if (!c.d.readVarU32(&length))
1616 return false;
1617
1618 const uint8_t* bytes;
1619 if (!c.d.readBytes(length, &bytes))
1620 return false;
1621
1622 char16_t* buffer = static_cast<char16_t *>(c.lifo.alloc(length * sizeof(char16_t)));
1623 for (size_t i = 0; i < length; i++)
1624 buffer[i] = bytes[i];
1625
1626 *name = AstName(buffer, length);
1627 return true;
1628 }
1629
1630 static bool
AstDecodeMemorySection(AstDecodeContext & c)1631 AstDecodeMemorySection(AstDecodeContext& c)
1632 {
1633 bool present;
1634 Limits memory;
1635 if (!DecodeMemorySection(c.d, c.module().hasMemory(), &memory, &present))
1636 return false;
1637
1638 if (present) {
1639 AstName name;
1640 if (!GenerateName(c, AstName(u"memory"), c.module().memories().length(), &name))
1641 return false;
1642 if (!c.module().addMemory(name, memory))
1643 return false;
1644 }
1645
1646 return true;
1647 }
1648
1649 static AstExpr*
ToAstExpr(AstDecodeContext & c,const InitExpr & initExpr)1650 ToAstExpr(AstDecodeContext& c, const InitExpr& initExpr)
1651 {
1652 switch (initExpr.kind()) {
1653 case InitExpr::Kind::Constant: {
1654 return new(c.lifo) AstConst(Val(initExpr.val()));
1655 }
1656 case InitExpr::Kind::GetGlobal: {
1657 AstRef globalRef;
1658 if (!GenerateRef(c, AstName(u"global"), initExpr.globalIndex(), &globalRef))
1659 return nullptr;
1660 return new(c.lifo) AstGetGlobal(globalRef);
1661 }
1662 }
1663 return nullptr;
1664 }
1665
1666 static bool
AstDecodeInitializerExpression(AstDecodeContext & c,ValType type,AstExpr ** init)1667 AstDecodeInitializerExpression(AstDecodeContext& c, ValType type, AstExpr** init)
1668 {
1669 InitExpr initExpr;
1670 if (!DecodeInitializerExpression(c.d, c.globalDescs(), type, &initExpr))
1671 return false;
1672
1673 *init = ToAstExpr(c, initExpr);
1674 return !!*init;
1675 }
1676
1677 static bool
AstDecodeGlobal(AstDecodeContext & c,uint32_t i,AstGlobal * global)1678 AstDecodeGlobal(AstDecodeContext& c, uint32_t i, AstGlobal* global)
1679 {
1680 AstName name;
1681 if (!GenerateName(c, AstName(u"global"), i, &name))
1682 return false;
1683
1684 ValType type;
1685 bool isMutable;
1686 if (!DecodeGlobalType(c.d, &type, &isMutable))
1687 return false;
1688
1689 AstExpr* init;
1690 if (!AstDecodeInitializerExpression(c, type, &init))
1691 return false;
1692
1693 if (!c.addGlobalDesc(type, isMutable, /* import */ false))
1694 return false;
1695
1696 *global = AstGlobal(name, type, isMutable, Some(init));
1697 return true;
1698 }
1699
1700 static bool
AstDecodeGlobalSection(AstDecodeContext & c)1701 AstDecodeGlobalSection(AstDecodeContext& c)
1702 {
1703 uint32_t sectionStart, sectionSize;
1704 if (!c.d.startSection(SectionId::Global, §ionStart, §ionSize, "global"))
1705 return false;
1706 if (sectionStart == Decoder::NotStarted)
1707 return true;
1708
1709 uint32_t numGlobals;
1710 if (!c.d.readVarU32(&numGlobals))
1711 return c.d.fail("expected number of globals");
1712
1713 uint32_t numImported = c.globalDescs().length();
1714
1715 for (uint32_t i = 0; i < numGlobals; i++) {
1716 auto* global = new(c.lifo) AstGlobal;
1717 if (!AstDecodeGlobal(c, i + numImported, global))
1718 return false;
1719 if (!c.module().append(global))
1720 return false;
1721 }
1722
1723 if (!c.d.finishSection(sectionStart, sectionSize, "global"))
1724 return false;
1725
1726 return true;
1727 }
1728
1729 static bool
AstDecodeExport(AstDecodeContext & c,AstExport ** export_)1730 AstDecodeExport(AstDecodeContext& c, AstExport** export_)
1731 {
1732 AstName fieldName;
1733 if (!AstDecodeName(c, &fieldName))
1734 return c.d.fail("expected export name");
1735
1736 uint32_t kindValue;
1737 if (!c.d.readVarU32(&kindValue))
1738 return c.d.fail("expected export kind");
1739
1740 uint32_t index;
1741 if (!c.d.readVarU32(&index))
1742 return c.d.fail("expected export internal index");
1743
1744 *export_ = new(c.lifo) AstExport(fieldName, DefinitionKind(kindValue), AstRef(index));
1745 if (!*export_)
1746 return false;
1747
1748 return true;
1749 }
1750
1751 static bool
AstDecodeExportSection(AstDecodeContext & c)1752 AstDecodeExportSection(AstDecodeContext& c)
1753 {
1754 uint32_t sectionStart, sectionSize;
1755 if (!c.d.startSection(SectionId::Export, §ionStart, §ionSize, "export"))
1756 return false;
1757 if (sectionStart == Decoder::NotStarted)
1758 return true;
1759
1760 uint32_t numExports;
1761 if (!c.d.readVarU32(&numExports))
1762 return c.d.fail("failed to read number of exports");
1763
1764 if (numExports > MaxExports)
1765 return c.d.fail("too many exports");
1766
1767 for (uint32_t i = 0; i < numExports; i++) {
1768 AstExport* export_ = nullptr;
1769 if (!AstDecodeExport(c, &export_))
1770 return false;
1771 if (!c.module().append(export_))
1772 return false;
1773 }
1774
1775 if (!c.d.finishSection(sectionStart, sectionSize, "export"))
1776 return false;
1777
1778 return true;
1779 }
1780
1781 static bool
AstDecodeFunctionBody(AstDecodeContext & c,uint32_t funcDefIndex,AstFunc ** func)1782 AstDecodeFunctionBody(AstDecodeContext &c, uint32_t funcDefIndex, AstFunc** func)
1783 {
1784 uint32_t offset = c.d.currentOffset();
1785 uint32_t bodySize;
1786 if (!c.d.readVarU32(&bodySize))
1787 return c.d.fail("expected number of function body bytes");
1788
1789 if (c.d.bytesRemain() < bodySize)
1790 return c.d.fail("function body length too big");
1791
1792 const uint8_t* bodyBegin = c.d.currentPosition();
1793 const uint8_t* bodyEnd = bodyBegin + bodySize;
1794
1795 AstDecodeOpIter iter(c.d);
1796
1797 uint32_t sigIndex = c.funcDefSigs()[funcDefIndex];
1798 const AstSig* sig = c.module().sigs()[sigIndex];
1799
1800 AstValTypeVector vars(c.lifo);
1801 AstNameVector localsNames(c.lifo);
1802 AstExprVector body(c.lifo);
1803
1804 ValTypeVector locals;
1805 if (!locals.appendAll(sig->args()))
1806 return false;
1807
1808 if (!DecodeLocalEntries(c.d, ModuleKind::Wasm, &locals))
1809 return c.d.fail("failed decoding local entries");
1810
1811 c.startFunction(&iter, &locals, sig->ret());
1812
1813 AstName funcName;
1814 if (!GenerateName(c, AstName(u"func"), c.module().numFuncImports() + funcDefIndex, &funcName))
1815 return false;
1816
1817 uint32_t numParams = sig->args().length();
1818 uint32_t numLocals = locals.length();
1819 for (uint32_t i = numParams; i < numLocals; i++) {
1820 if (!vars.append(locals[i]))
1821 return false;
1822 }
1823 for (uint32_t i = 0; i < numLocals; i++) {
1824 AstName varName;
1825 if (!GenerateName(c, AstName(u"var"), i, &varName))
1826 return false;
1827 if (!localsNames.append(varName))
1828 return false;
1829 }
1830
1831 if (!c.iter().readFunctionStart(sig->ret()))
1832 return false;
1833
1834 if (!c.depths().append(c.exprs().length()))
1835 return false;
1836
1837 while (c.d.currentPosition() < bodyEnd) {
1838 if (!AstDecodeExpr(c))
1839 return false;
1840
1841 const AstDecodeStackItem& item = c.top();
1842 if (!item.expr) { // Op::End was found
1843 c.popBack();
1844 break;
1845 }
1846 }
1847
1848 for (auto i = c.exprs().begin() + c.depths().back(), e = c.exprs().end();
1849 i != e; ++i) {
1850 if (!body.append(i->expr))
1851 return false;
1852 }
1853 c.exprs().shrinkTo(c.depths().popCopy());
1854
1855 if (!c.iter().readFunctionEnd())
1856 return false;
1857
1858 c.endFunction();
1859
1860 if (c.d.currentPosition() != bodyEnd)
1861 return c.d.fail("function body length mismatch");
1862
1863 AstRef sigRef;
1864 if (!GenerateRef(c, AstName(u"type"), sigIndex, &sigRef))
1865 return false;
1866
1867 *func = new(c.lifo) AstFunc(funcName, sigRef, Move(vars), Move(localsNames), Move(body));
1868 if (!*func)
1869 return false;
1870 (*func)->setOffset(offset);
1871
1872 return true;
1873 }
1874
1875 static bool
AstDecodeCodeSection(AstDecodeContext & c)1876 AstDecodeCodeSection(AstDecodeContext &c)
1877 {
1878 uint32_t sectionStart, sectionSize;
1879 if (!c.d.startSection(SectionId::Code, §ionStart, §ionSize, "code"))
1880 return false;
1881
1882 if (sectionStart == Decoder::NotStarted) {
1883 if (c.funcDefSigs().length() != 0)
1884 return c.d.fail("expected function bodies");
1885
1886 return false;
1887 }
1888
1889 uint32_t numFuncBodies;
1890 if (!c.d.readVarU32(&numFuncBodies))
1891 return c.d.fail("expected function body count");
1892
1893 if (numFuncBodies != c.funcDefSigs().length())
1894 return c.d.fail("function body count does not match function signature count");
1895
1896 for (uint32_t funcDefIndex = 0; funcDefIndex < numFuncBodies; funcDefIndex++) {
1897 AstFunc* func;
1898 if (!AstDecodeFunctionBody(c, funcDefIndex, &func))
1899 return false;
1900 if (!c.module().append(func))
1901 return false;
1902 }
1903
1904 if (!c.d.finishSection(sectionStart, sectionSize, "code"))
1905 return false;
1906
1907 return true;
1908 }
1909
1910 // Number of bytes to display in a single fragment of a data section (per line).
1911 static const size_t WRAP_DATA_BYTES = 30;
1912
1913 static bool
AstDecodeDataSection(AstDecodeContext & c)1914 AstDecodeDataSection(AstDecodeContext &c)
1915 {
1916 DataSegmentVector segments;
1917 bool hasMemory = c.module().hasMemory();
1918
1919 MOZ_ASSERT(c.module().memories().length() <= 1, "at most one memory in MVP");
1920 uint32_t memByteLength = hasMemory ? c.module().memories()[0].limits.initial : 0;
1921
1922 if (!DecodeDataSection(c.d, hasMemory, memByteLength, c.globalDescs(), &segments))
1923 return false;
1924
1925 for (DataSegment& s : segments) {
1926 const uint8_t* src = c.d.begin() + s.bytecodeOffset;
1927 char16_t* buffer = static_cast<char16_t*>(c.lifo.alloc(s.length * sizeof(char16_t)));
1928 for (size_t i = 0; i < s.length; i++)
1929 buffer[i] = src[i];
1930
1931 AstExpr* offset = ToAstExpr(c, s.offset);
1932 if (!offset)
1933 return false;
1934
1935 AstNameVector fragments(c.lifo);
1936 for (size_t start = 0; start < s.length; start += WRAP_DATA_BYTES) {
1937 AstName name(buffer + start, Min(WRAP_DATA_BYTES, s.length - start));
1938 if (!fragments.append(name))
1939 return false;
1940 }
1941
1942 AstDataSegment* segment = new(c.lifo) AstDataSegment(offset, Move(fragments));
1943 if (!segment || !c.module().append(segment))
1944 return false;
1945 }
1946
1947 return true;
1948 }
1949
1950 static bool
AstDecodeElemSection(AstDecodeContext & c)1951 AstDecodeElemSection(AstDecodeContext &c)
1952 {
1953 uint32_t sectionStart, sectionSize;
1954 if (!c.d.startSection(SectionId::Elem, §ionStart, §ionSize, "elem"))
1955 return false;
1956 if (sectionStart == Decoder::NotStarted)
1957 return true;
1958
1959 uint32_t numElems;
1960 if (!c.d.readVarU32(&numElems))
1961 return c.d.fail("failed to read number of table elements");
1962
1963 for (uint32_t i = 0; i < numElems; i++) {
1964 uint32_t tableIndex;
1965 if (!c.d.readVarU32(&tableIndex))
1966 return c.d.fail("expected table index for element");
1967
1968 if (tableIndex != 0)
1969 return c.d.fail("non-zero table index for element");
1970
1971 AstExpr* offset;
1972 if (!AstDecodeInitializerExpression(c, ValType::I32, &offset))
1973 return false;
1974
1975 uint32_t count;
1976 if (!c.d.readVarU32(&count))
1977 return c.d.fail("expected element count");
1978
1979 AstRefVector elems(c.lifo);
1980 if (!elems.resize(count))
1981 return false;
1982
1983 for (uint32_t i = 0; i < count; i++) {
1984 uint32_t index;
1985 if (!c.d.readVarU32(&index))
1986 return c.d.fail("expected element index");
1987
1988 elems[i] = AstRef(index);
1989 }
1990
1991 AstElemSegment* segment = new(c.lifo) AstElemSegment(offset, Move(elems));
1992 if (!segment || !c.module().append(segment))
1993 return false;
1994 }
1995
1996 if (!c.d.finishSection(sectionStart, sectionSize, "elem"))
1997 return false;
1998
1999 return true;
2000 }
2001
2002 static bool
AstDecodeStartSection(AstDecodeContext & c)2003 AstDecodeStartSection(AstDecodeContext &c)
2004 {
2005 uint32_t sectionStart, sectionSize;
2006 if (!c.d.startSection(SectionId::Start, §ionStart, §ionSize, "start"))
2007 return false;
2008 if (sectionStart == Decoder::NotStarted)
2009 return true;
2010
2011 uint32_t funcIndex;
2012 if (!c.d.readVarU32(&funcIndex))
2013 return c.d.fail("failed to read start func index");
2014
2015 AstRef funcRef;
2016 if (!GenerateRef(c, AstName(u"func"), funcIndex, &funcRef))
2017 return false;
2018
2019 c.module().setStartFunc(AstStartFunc(funcRef));
2020
2021 if (!c.d.finishSection(sectionStart, sectionSize, "start"))
2022 return false;
2023
2024 return true;
2025 }
2026
2027 bool
BinaryToAst(JSContext * cx,const uint8_t * bytes,uint32_t length,LifoAlloc & lifo,AstModule ** module)2028 wasm::BinaryToAst(JSContext* cx, const uint8_t* bytes, uint32_t length,
2029 LifoAlloc& lifo, AstModule** module)
2030 {
2031 AstModule* result = new(lifo) AstModule(lifo);
2032 if (!result->init())
2033 return false;
2034
2035 UniqueChars error;
2036 Decoder d(bytes, bytes + length, &error);
2037 AstDecodeContext c(cx, lifo, d, *result, true);
2038
2039 SigWithIdVector sigs;
2040 if (!DecodePreamble(d) ||
2041 !AstDecodeTypeSection(c, &sigs) ||
2042 !AstDecodeImportSection(c, sigs) ||
2043 !AstDecodeFunctionSection(c, sigs) ||
2044 !AstDecodeTableSection(c) ||
2045 !AstDecodeMemorySection(c) ||
2046 !AstDecodeGlobalSection(c) ||
2047 !AstDecodeExportSection(c) ||
2048 !AstDecodeStartSection(c) ||
2049 !AstDecodeElemSection(c) ||
2050 !AstDecodeCodeSection(c) ||
2051 !AstDecodeDataSection(c) ||
2052 !DecodeUnknownSections(c.d))
2053 {
2054 if (error) {
2055 JS_ReportErrorNumberASCII(c.cx, GetErrorMessage, nullptr, JSMSG_WASM_COMPILE_ERROR,
2056 error.get());
2057 return false;
2058 }
2059 ReportOutOfMemory(c.cx);
2060 return false;
2061 }
2062
2063 MOZ_ASSERT(!error, "unreported error in decoding");
2064
2065 *module = result;
2066 return true;
2067 }
2068