LCOV - code coverage report
Current view: top level - js/src/wasm - WasmBinaryToAST.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 1061 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 70 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13