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