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(), §ionStart, §ionSize, "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 : }
|