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, &sectionStart, &sectionSize, "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, &sectionStart, &sectionSize, "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, &sectionStart, &sectionSize, "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, &sectionStart, &sectionSize, "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, &sectionStart, &sectionSize, "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, &sectionStart, &sectionSize, "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