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