Line data Source code
1 : // Copyright 2015 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/signature.h"
6 :
7 : #include "src/base/platform/elapsed-timer.h"
8 : #include "src/bit-vector.h"
9 : #include "src/flags.h"
10 : #include "src/handles.h"
11 : #include "src/objects-inl.h"
12 : #include "src/zone/zone-containers.h"
13 :
14 : #include "src/wasm/decoder.h"
15 : #include "src/wasm/function-body-decoder-impl.h"
16 : #include "src/wasm/function-body-decoder.h"
17 : #include "src/wasm/wasm-limits.h"
18 : #include "src/wasm/wasm-module.h"
19 : #include "src/wasm/wasm-opcodes.h"
20 :
21 : #include "src/ostreams.h"
22 :
23 : #include "src/compiler/wasm-compiler.h"
24 :
25 : namespace v8 {
26 : namespace internal {
27 : namespace wasm {
28 :
29 : #if DEBUG
30 : #define TRACE(...) \
31 : do { \
32 : if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \
33 : } while (false)
34 : #else
35 : #define TRACE(...)
36 : #endif
37 :
38 : #define CHECK_PROTOTYPE_OPCODE(flag) \
39 : if (module_ != nullptr && module_->is_asm_js()) { \
40 : error("Opcode not supported for asmjs modules"); \
41 : } \
42 : if (!FLAG_##flag) { \
43 : error("Invalid opcode (enable with --" #flag ")"); \
44 : break; \
45 : }
46 :
47 : // An SsaEnv environment carries the current local variable renaming
48 : // as well as the current effect and control dependency in the TF graph.
49 : // It maintains a control state that tracks whether the environment
50 : // is reachable, has reached a control end, or has been merged.
51 : struct SsaEnv {
52 : enum State { kControlEnd, kUnreachable, kReached, kMerged };
53 :
54 : State state;
55 : TFNode* control;
56 : TFNode* effect;
57 : TFNode** locals;
58 :
59 3400550 : bool go() { return state >= kReached; }
60 : void Kill(State new_state = kControlEnd) {
61 806003 : state = new_state;
62 806003 : locals = nullptr;
63 806003 : control = nullptr;
64 806003 : effect = nullptr;
65 : }
66 : void SetNotMerged() {
67 20858 : if (state == kMerged) state = kReached;
68 : }
69 : };
70 :
71 : // An entry on the value stack.
72 : struct Value {
73 : const byte* pc;
74 : TFNode* node;
75 : ValueType type;
76 : };
77 :
78 : struct TryInfo : public ZoneObject {
79 : SsaEnv* catch_env;
80 : TFNode* exception;
81 :
82 124 : explicit TryInfo(SsaEnv* c) : catch_env(c), exception(nullptr) {}
83 : };
84 :
85 : struct MergeValues {
86 : uint32_t arity;
87 : union {
88 : Value* array;
89 : Value first;
90 : } vals; // Either multiple values or a single value.
91 :
92 : Value& operator[](size_t i) {
93 : DCHECK_GT(arity, i);
94 85588 : return arity == 1 ? vals.first : vals.array[i];
95 : }
96 : };
97 :
98 : static Value* NO_VALUE = nullptr;
99 :
100 : enum ControlKind { kControlIf, kControlBlock, kControlLoop, kControlTry };
101 :
102 : // An entry on the control stack (i.e. if, block, loop).
103 : struct Control {
104 : const byte* pc;
105 : ControlKind kind;
106 : size_t stack_depth; // stack height at the beginning of the construct.
107 : SsaEnv* end_env; // end environment for the construct.
108 : SsaEnv* false_env; // false environment (only for if).
109 : TryInfo* try_info; // Information used for compiling try statements.
110 : int32_t previous_catch; // The previous Control (on the stack) with a catch.
111 : bool unreachable; // The current block has been ended.
112 :
113 : // Values merged into the end of this control construct.
114 : MergeValues merge;
115 :
116 : inline bool is_if() const { return kind == kControlIf; }
117 : inline bool is_block() const { return kind == kControlBlock; }
118 : inline bool is_loop() const { return kind == kControlLoop; }
119 : inline bool is_try() const { return kind == kControlTry; }
120 :
121 : // Named constructors.
122 : static Control Block(const byte* pc, size_t stack_depth, SsaEnv* end_env,
123 : int32_t previous_catch) {
124 : return {pc, kControlBlock, stack_depth, end_env, nullptr,
125 224850 : nullptr, previous_catch, false, {0, {NO_VALUE}}};
126 : }
127 :
128 : static Control If(const byte* pc, size_t stack_depth, SsaEnv* end_env,
129 : SsaEnv* false_env, int32_t previous_catch) {
130 : return {pc, kControlIf, stack_depth, end_env, false_env,
131 71911 : nullptr, previous_catch, false, {0, {NO_VALUE}}};
132 : }
133 :
134 : static Control Loop(const byte* pc, size_t stack_depth, SsaEnv* end_env,
135 : int32_t previous_catch) {
136 : return {pc, kControlLoop, stack_depth, end_env, nullptr,
137 11623 : nullptr, previous_catch, false, {0, {NO_VALUE}}};
138 : }
139 :
140 : static Control Try(const byte* pc, size_t stack_depth, SsaEnv* end_env,
141 : Zone* zone, SsaEnv* catch_env, int32_t previous_catch) {
142 : DCHECK_NOT_NULL(catch_env);
143 : TryInfo* try_info = new (zone) TryInfo(catch_env);
144 : return {pc, kControlTry, stack_depth, end_env, nullptr,
145 124 : try_info, previous_catch, false, {0, {NO_VALUE}}};
146 : }
147 : };
148 :
149 : // Macros that build nodes only if there is a graph and the current SSA
150 : // environment is reachable from start. This avoids problems with malformed
151 : // TF graphs when decoding inputs that have unreachable code.
152 : #define BUILD(func, ...) \
153 : (build() ? CheckForException(builder_->func(__VA_ARGS__)) : nullptr)
154 : #define BUILD0(func) (build() ? CheckForException(builder_->func()) : nullptr)
155 :
156 : // Generic Wasm bytecode decoder with utilities for decoding operands,
157 : // lengths, etc.
158 323113 : class WasmDecoder : public Decoder {
159 : public:
160 : WasmDecoder(const WasmModule* module, FunctionSig* sig, const byte* start,
161 : const byte* end)
162 : : Decoder(start, end),
163 : module_(module),
164 : sig_(sig),
165 323178 : local_types_(nullptr) {}
166 : const WasmModule* module_;
167 : FunctionSig* sig_;
168 :
169 : ZoneVector<ValueType>* local_types_;
170 :
171 : size_t total_locals() const {
172 627341 : return local_types_ == nullptr ? 0 : local_types_->size();
173 : }
174 :
175 116968 : static bool DecodeLocals(Decoder* decoder, const FunctionSig* sig,
176 : ZoneVector<ValueType>* type_list) {
177 : DCHECK_NOT_NULL(type_list);
178 : DCHECK_EQ(0, type_list->size());
179 : // Initialize from signature.
180 108187 : if (sig != nullptr) {
181 95353 : type_list->assign(sig->parameters().begin(), sig->parameters().end());
182 : }
183 : // Decode local declarations, if any.
184 : uint32_t entries = decoder->consume_u32v("local decls count");
185 108210 : if (decoder->failed()) return false;
186 :
187 : TRACE("local decls count: %u\n", entries);
188 134409 : while (entries-- > 0 && decoder->ok() && decoder->more()) {
189 : uint32_t count = decoder->consume_u32v("local count");
190 8783 : if (decoder->failed()) return false;
191 :
192 17492 : if ((count + type_list->size()) > kV8MaxWasmFunctionLocals) {
193 3 : decoder->error(decoder->pc() - 1, "local count too large");
194 3 : return false;
195 : }
196 : byte code = decoder->consume_u8("local type");
197 8743 : if (decoder->failed()) return false;
198 :
199 : ValueType type;
200 8742 : switch (code) {
201 : case kLocalI32:
202 5911 : type = kWasmI32;
203 5911 : break;
204 : case kLocalI64:
205 295 : type = kWasmI64;
206 295 : break;
207 : case kLocalF32:
208 459 : type = kWasmF32;
209 459 : break;
210 : case kLocalF64:
211 1705 : type = kWasmF64;
212 1705 : break;
213 : case kLocalS128:
214 343 : type = kWasmS128;
215 343 : break;
216 : case kLocalS1x4:
217 0 : type = kWasmS1x4;
218 0 : break;
219 : case kLocalS1x8:
220 0 : type = kWasmS1x8;
221 0 : break;
222 : case kLocalS1x16:
223 0 : type = kWasmS1x16;
224 0 : break;
225 : default:
226 29 : decoder->error(decoder->pc() - 1, "invalid local type");
227 29 : return false;
228 : }
229 8713 : type_list->insert(type_list->end(), count, type);
230 : }
231 : DCHECK(decoder->ok());
232 : return true;
233 : }
234 :
235 1867757 : static BitVector* AnalyzeLoopAssignment(Decoder* decoder, const byte* pc,
236 : int locals_count, Zone* zone) {
237 8845 : if (pc >= decoder->end()) return nullptr;
238 8844 : if (*pc != kExprLoop) return nullptr;
239 :
240 282393 : BitVector* assigned = new (zone) BitVector(locals_count, zone);
241 : int depth = 0;
242 : // Iteratively process all AST nodes nested inside the loop.
243 3726662 : while (pc < decoder->end() && decoder->ok()) {
244 1858906 : WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
245 : unsigned length = 1;
246 : switch (opcode) {
247 : case kExprLoop:
248 : case kExprIf:
249 : case kExprBlock:
250 : case kExprTry:
251 164840 : length = OpcodeLength(decoder, pc);
252 164840 : depth++;
253 164840 : break;
254 : case kExprSetLocal: // fallthru
255 : case kExprTeeLocal: {
256 : LocalIndexOperand<true> operand(decoder, pc);
257 273549 : if (assigned->length() > 0 &&
258 136774 : operand.index < static_cast<uint32_t>(assigned->length())) {
259 : // Unverified code might have an out-of-bounds index.
260 136774 : assigned->Add(operand.index);
261 : }
262 136775 : length = 1 + operand.length;
263 : break;
264 : }
265 : case kExprEnd:
266 164834 : depth--;
267 164834 : break;
268 : default:
269 1392457 : length = OpcodeLength(decoder, pc);
270 1392457 : break;
271 : }
272 1858906 : if (depth <= 0) break;
273 1850068 : pc += length;
274 : }
275 8844 : return decoder->ok() ? assigned : nullptr;
276 : }
277 :
278 1237148 : inline bool Validate(const byte* pc, LocalIndexOperand<true>& operand) {
279 1237148 : if (operand.index < total_locals()) {
280 618545 : if (local_types_) {
281 618545 : operand.type = local_types_->at(operand.index);
282 : } else {
283 0 : operand.type = kWasmStmt;
284 : }
285 : return true;
286 : }
287 29 : errorf(pc + 1, "invalid local index: %u", operand.index);
288 29 : return false;
289 : }
290 :
291 18832 : inline bool Validate(const byte* pc, GlobalIndexOperand<true>& operand) {
292 56496 : if (module_ != nullptr && operand.index < module_->globals.size()) {
293 37664 : operand.global = &module_->globals[operand.index];
294 18832 : operand.type = operand.global->type;
295 18832 : return true;
296 : }
297 0 : errorf(pc + 1, "invalid global index: %u", operand.index);
298 0 : return false;
299 : }
300 :
301 : inline bool Complete(const byte* pc, CallFunctionOperand<true>& operand) {
302 109635 : if (module_ != nullptr && operand.index < module_->functions.size()) {
303 73094 : operand.sig = module_->functions[operand.index].sig;
304 : return true;
305 : }
306 : return false;
307 : }
308 :
309 33771 : inline bool Validate(const byte* pc, CallFunctionOperand<true>& operand) {
310 33771 : if (Complete(pc, operand)) {
311 : return true;
312 : }
313 0 : errorf(pc + 1, "invalid function index: %u", operand.index);
314 0 : return false;
315 : }
316 :
317 : inline bool Complete(const byte* pc, CallIndirectOperand<true>& operand) {
318 7371 : if (module_ != nullptr && operand.index < module_->signatures.size()) {
319 4898 : operand.sig = module_->signatures[operand.index];
320 : return true;
321 : }
322 : return false;
323 : }
324 :
325 2384 : inline bool Validate(const byte* pc, CallIndirectOperand<true>& operand) {
326 4768 : if (module_ == nullptr || module_->function_tables.empty()) {
327 3 : error("function table has to exist to execute call_indirect");
328 3 : return false;
329 : }
330 2381 : if (Complete(pc, operand)) {
331 : return true;
332 : }
333 12 : errorf(pc + 1, "invalid signature index: #%u", operand.index);
334 12 : return false;
335 : }
336 :
337 42973 : inline bool Validate(const byte* pc, BreakDepthOperand<true>& operand,
338 : ZoneVector<Control>& control) {
339 85946 : if (operand.depth < control.size()) {
340 85024 : operand.target = &control[control.size() - operand.depth - 1];
341 : return true;
342 : }
343 461 : errorf(pc + 1, "invalid break depth: %u", operand.depth);
344 : return false;
345 : }
346 :
347 : bool Validate(const byte* pc, BranchTableOperand<true>& operand,
348 : size_t block_depth) {
349 : // TODO(titzer): add extra redundant validation for br_table here?
350 : return true;
351 : }
352 :
353 5390 : inline bool Validate(const byte* pc, WasmOpcode opcode,
354 : SimdLaneOperand<true>& operand) {
355 : uint8_t num_lanes = 0;
356 5390 : switch (opcode) {
357 : case kExprF32x4ExtractLane:
358 : case kExprF32x4ReplaceLane:
359 : case kExprI32x4ExtractLane:
360 : case kExprI32x4ReplaceLane:
361 : num_lanes = 4;
362 : break;
363 : case kExprI16x8ExtractLane:
364 : case kExprI16x8ReplaceLane:
365 : num_lanes = 8;
366 : break;
367 : case kExprI8x16ExtractLane:
368 : case kExprI8x16ReplaceLane:
369 : num_lanes = 16;
370 : break;
371 : default:
372 0 : UNREACHABLE();
373 : break;
374 : }
375 5390 : if (operand.lane < 0 || operand.lane >= num_lanes) {
376 0 : error(pc_ + 2, "invalid lane index");
377 : return false;
378 : } else {
379 : return true;
380 : }
381 : }
382 :
383 42 : inline bool Validate(const byte* pc, WasmOpcode opcode,
384 : SimdShiftOperand<true>& operand) {
385 : uint8_t max_shift = 0;
386 42 : switch (opcode) {
387 : case kExprI32x4Shl:
388 : case kExprI32x4ShrS:
389 : case kExprI32x4ShrU:
390 : max_shift = 32;
391 : break;
392 : case kExprI16x8Shl:
393 : case kExprI16x8ShrS:
394 : case kExprI16x8ShrU:
395 : max_shift = 16;
396 : break;
397 : case kExprI8x16Shl:
398 : case kExprI8x16ShrS:
399 : case kExprI8x16ShrU:
400 : max_shift = 8;
401 : break;
402 : default:
403 0 : UNREACHABLE();
404 : break;
405 : }
406 42 : if (operand.shift < 0 || operand.shift >= max_shift) {
407 0 : error(pc_ + 2, "invalid shift amount");
408 : return false;
409 : } else {
410 : return true;
411 : }
412 : }
413 :
414 0 : inline bool Validate(const byte* pc, WasmOpcode opcode,
415 : SimdConcatOperand<true>& operand) {
416 : DCHECK_EQ(wasm::kExprS8x16Concat, opcode);
417 0 : if (operand.bytes <= 0 || operand.bytes >= kSimd128Size) {
418 0 : error(pc_ + 2, "invalid byte amount");
419 : return false;
420 : } else {
421 : return true;
422 : }
423 : }
424 :
425 1794963 : static unsigned OpcodeLength(Decoder* decoder, const byte* pc) {
426 1794963 : switch (static_cast<byte>(*pc)) {
427 : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
428 : FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
429 : FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
430 : #undef DECLARE_OPCODE_CASE
431 : {
432 10793 : MemoryAccessOperand<true> operand(decoder, pc, UINT32_MAX);
433 10793 : return 1 + operand.length;
434 : }
435 : case kExprBr:
436 : case kExprBrIf: {
437 : BreakDepthOperand<true> operand(decoder, pc);
438 48303 : return 1 + operand.length;
439 : }
440 : case kExprSetGlobal:
441 : case kExprGetGlobal: {
442 : GlobalIndexOperand<true> operand(decoder, pc);
443 2811 : return 1 + operand.length;
444 : }
445 :
446 : case kExprCallFunction: {
447 : CallFunctionOperand<true> operand(decoder, pc);
448 20783 : return 1 + operand.length;
449 : }
450 : case kExprCallIndirect: {
451 731 : CallIndirectOperand<true> operand(decoder, pc);
452 731 : return 1 + operand.length;
453 : }
454 :
455 : case kExprTry:
456 : case kExprIf: // fall thru
457 : case kExprLoop:
458 : case kExprBlock: {
459 202797 : BlockTypeOperand<true> operand(decoder, pc);
460 202797 : return 1 + operand.length;
461 : }
462 :
463 : case kExprSetLocal:
464 : case kExprTeeLocal:
465 : case kExprGetLocal:
466 : case kExprCatch: {
467 : LocalIndexOperand<true> operand(decoder, pc);
468 387358 : return 1 + operand.length;
469 : }
470 : case kExprBrTable: {
471 7580 : BranchTableOperand<true> operand(decoder, pc);
472 : BranchTableIterator<true> iterator(decoder, operand);
473 7580 : return 1 + iterator.length();
474 : }
475 : case kExprI32Const: {
476 : ImmI32Operand<true> operand(decoder, pc);
477 387143 : return 1 + operand.length;
478 : }
479 : case kExprI64Const: {
480 : ImmI64Operand<true> operand(decoder, pc);
481 4230 : return 1 + operand.length;
482 : }
483 : case kExprGrowMemory:
484 : case kExprMemorySize: {
485 52 : MemoryIndexOperand<true> operand(decoder, pc);
486 52 : return 1 + operand.length;
487 : }
488 : case kExprF32Const:
489 : return 5;
490 : case kExprF64Const:
491 4402 : return 9;
492 : case kSimdPrefix: {
493 168 : byte simd_index = decoder->read_u8<true>(pc + 1, "simd_index");
494 : WasmOpcode opcode =
495 168 : static_cast<WasmOpcode>(kSimdPrefix << 8 | simd_index);
496 168 : switch (opcode) {
497 : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
498 : FOREACH_SIMD_0_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
499 : #undef DECLARE_OPCODE_CASE
500 : {
501 : return 2;
502 : }
503 : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
504 : FOREACH_SIMD_1_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
505 : #undef DECLARE_OPCODE_CASE
506 : {
507 18 : return 3;
508 : }
509 : default:
510 : decoder->error(pc, "invalid SIMD opcode");
511 1 : return 2;
512 : }
513 : }
514 : default:
515 717475 : return 1;
516 : }
517 : }
518 :
519 239451 : std::pair<uint32_t, uint32_t> StackEffect(const byte* pc) {
520 236601 : WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
521 : // Handle "simple" opcodes with a fixed signature first.
522 241831 : FunctionSig* sig = WasmOpcodes::Signature(opcode);
523 236601 : if (!sig) sig = WasmOpcodes::AsmjsSignature(opcode);
524 241831 : if (sig) return {sig->parameter_count(), sig->return_count()};
525 :
526 : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
527 : // clang-format off
528 231371 : switch (opcode) {
529 : case kExprSelect:
530 35 : return {3, 1};
531 : FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
532 927 : return {2, 0};
533 : FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
534 : case kExprTeeLocal:
535 : case kExprGrowMemory:
536 9762 : return {1, 1};
537 : case kExprSetLocal:
538 : case kExprSetGlobal:
539 : case kExprDrop:
540 : case kExprBrIf:
541 : case kExprBrTable:
542 : case kExprIf:
543 10435 : return {1, 0};
544 : case kExprGetLocal:
545 : case kExprGetGlobal:
546 : case kExprI32Const:
547 : case kExprI64Const:
548 : case kExprF32Const:
549 : case kExprF64Const:
550 : case kExprMemorySize:
551 76892 : return {0, 1};
552 : case kExprCallFunction: {
553 2770 : CallFunctionOperand<true> operand(this, pc);
554 2770 : CHECK(Complete(pc, operand));
555 5540 : return {operand.sig->parameter_count(), operand.sig->return_count()};
556 : }
557 : case kExprCallIndirect: {
558 80 : CallIndirectOperand<true> operand(this, pc);
559 80 : CHECK(Complete(pc, operand));
560 : // Indirect calls pop an additional argument for the table index.
561 80 : return {operand.sig->parameter_count() + 1,
562 160 : operand.sig->return_count()};
563 : }
564 : case kExprBr:
565 : case kExprBlock:
566 : case kExprLoop:
567 : case kExprEnd:
568 : case kExprElse:
569 : case kExprNop:
570 : case kExprReturn:
571 : case kExprUnreachable:
572 130470 : return {0, 0};
573 : default:
574 0 : V8_Fatal(__FILE__, __LINE__, "unimplemented opcode: %x", opcode);
575 : return {0, 0};
576 : }
577 : #undef DECLARE_OPCODE_CASE
578 : // clang-format on
579 : }
580 : };
581 :
582 : static const int32_t kNullCatch = -1;
583 :
584 : // The full WASM decoder for bytecode. Verifies bytecode and, optionally,
585 : // generates a TurboFan IR graph.
586 86512 : class WasmFullDecoder : public WasmDecoder {
587 : public:
588 14839 : WasmFullDecoder(Zone* zone, const wasm::WasmModule* module,
589 : const FunctionBody& body)
590 14839 : : WasmFullDecoder(zone, module, nullptr, body) {}
591 :
592 71738 : WasmFullDecoder(Zone* zone, TFBuilder* builder, const FunctionBody& body)
593 : : WasmFullDecoder(zone, builder->module_env() == nullptr
594 : ? nullptr
595 : : builder->module_env()->module,
596 143476 : builder, body) {}
597 :
598 86567 : bool Decode() {
599 86567 : if (FLAG_wasm_code_fuzzer_gen_test) {
600 0 : PrintRawWasmCode(start_, end_);
601 : }
602 : base::ElapsedTimer decode_timer;
603 86518 : if (FLAG_trace_wasm_decode_time) {
604 : decode_timer.Start();
605 : }
606 : stack_.clear();
607 : control_.clear();
608 :
609 86518 : if (end_ < pc_) {
610 0 : error("function body end < start");
611 0 : return false;
612 : }
613 :
614 : DCHECK_EQ(0, local_types_->size());
615 86518 : WasmDecoder::DecodeLocals(this, sig_, local_types_);
616 86617 : InitSsaEnv();
617 86599 : DecodeFunctionBody();
618 :
619 86607 : if (failed()) return TraceFailed();
620 :
621 75823 : if (!control_.empty()) {
622 : // Generate a better error message whether the unterminated control
623 : // structure is the function body block or an innner structure.
624 53 : if (control_.size() > 1) {
625 0 : error(control_.back().pc, "unterminated control structure");
626 : } else {
627 : error("function body must end with \"end\" opcode.");
628 : }
629 : return TraceFailed();
630 : }
631 :
632 75770 : if (!last_end_found_) {
633 : error("function body must end with \"end\" opcode.");
634 0 : return false;
635 : }
636 :
637 75770 : if (FLAG_trace_wasm_decode_time) {
638 0 : double ms = decode_timer.Elapsed().InMillisecondsF();
639 0 : PrintF("wasm-decode %s (%0.3f ms)\n\n", ok() ? "ok" : "failed", ms);
640 : } else {
641 : TRACE("wasm-decode %s\n\n", ok() ? "ok" : "failed");
642 : }
643 :
644 : return true;
645 : }
646 :
647 : bool TraceFailed() {
648 : TRACE("wasm-error module+%-6d func+%d: %s\n\n", baserel(error_pc_),
649 : startrel(error_pc_), error_msg_.c_str());
650 : return false;
651 : }
652 :
653 : private:
654 : WasmFullDecoder(Zone* zone, const wasm::WasmModule* module,
655 : TFBuilder* builder, const FunctionBody& body)
656 : : WasmDecoder(module, body.sig, body.start, body.end),
657 : zone_(zone),
658 : builder_(builder),
659 : base_(body.base),
660 : local_type_vec_(zone),
661 : stack_(zone),
662 : control_(zone),
663 : last_end_found_(false),
664 259731 : current_catch_(kNullCatch) {
665 86577 : local_types_ = &local_type_vec_;
666 : }
667 :
668 : static const size_t kErrorMsgSize = 128;
669 :
670 : Zone* zone_;
671 : TFBuilder* builder_;
672 : const byte* base_;
673 :
674 : SsaEnv* ssa_env_;
675 :
676 : ZoneVector<ValueType> local_type_vec_; // types of local variables.
677 : ZoneVector<Value> stack_; // stack of values.
678 : ZoneVector<Control> control_; // stack of blocks, loops, and ifs.
679 : bool last_end_found_;
680 :
681 : int32_t current_catch_;
682 :
683 300 : TryInfo* current_try_info() { return control_[current_catch_].try_info; }
684 :
685 4020319 : inline bool build() { return builder_ && ssa_env_->go(); }
686 :
687 86616 : void InitSsaEnv() {
688 : TFNode* start = nullptr;
689 86616 : SsaEnv* ssa_env = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
690 86627 : size_t size = sizeof(TFNode*) * EnvironmentCount();
691 86627 : ssa_env->state = SsaEnv::kReached;
692 : ssa_env->locals =
693 86627 : size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr;
694 :
695 86634 : if (builder_) {
696 265866 : start = builder_->Start(static_cast<int>(sig_->parameter_count() + 1));
697 : // Initialize local variables.
698 : uint32_t index = 0;
699 459950 : while (index < sig_->parameter_count()) {
700 122306 : ssa_env->locals[index] = builder_->Param(index);
701 122302 : index++;
702 : }
703 158604 : while (index < local_type_vec_.size()) {
704 122521 : ValueType type = local_type_vec_[index];
705 7524 : TFNode* node = DefaultValue(type);
706 109067 : while (index < local_type_vec_.size() &&
707 30153 : local_type_vec_[index] == type) {
708 : // Do a whole run of like-typed locals at a time.
709 28171 : ssa_env->locals[index++] = node;
710 : }
711 : }
712 : }
713 86630 : ssa_env->control = start;
714 86630 : ssa_env->effect = start;
715 : SetEnv("initial", ssa_env);
716 86630 : if (builder_) {
717 : // The function-prologue stack check is associated with position 0, which
718 : // is never a position of any instruction in the function.
719 71784 : builder_->StackCheck(0);
720 : }
721 86609 : }
722 :
723 7524 : TFNode* DefaultValue(ValueType type) {
724 7524 : switch (type) {
725 : case kWasmI32:
726 5424 : return builder_->Int32Constant(0);
727 : case kWasmI64:
728 91 : return builder_->Int64Constant(0);
729 : case kWasmF32:
730 220 : return builder_->Float32Constant(0);
731 : case kWasmF64:
732 1446 : return builder_->Float64Constant(0);
733 : case kWasmS128:
734 343 : return builder_->S128Zero();
735 : case kWasmS1x4:
736 0 : return builder_->S1x4Zero();
737 : case kWasmS1x8:
738 0 : return builder_->S1x8Zero();
739 : case kWasmS1x16:
740 0 : return builder_->S1x16Zero();
741 : default:
742 0 : UNREACHABLE();
743 : return nullptr;
744 : }
745 : }
746 :
747 : char* indentation() {
748 : static const int kMaxIndent = 64;
749 : static char bytes[kMaxIndent + 1];
750 : for (int i = 0; i < kMaxIndent; ++i) bytes[i] = ' ';
751 : bytes[kMaxIndent] = 0;
752 : if (stack_.size() < kMaxIndent / 2) {
753 : bytes[stack_.size() * 2] = 0;
754 : }
755 : return bytes;
756 : }
757 :
758 19587 : bool CheckHasMemory() {
759 19587 : if (!module_->has_memory) {
760 15 : error(pc_ - 1, "memory instruction with no memory");
761 : }
762 19587 : return module_->has_memory;
763 : }
764 :
765 : // Decodes the body of a function.
766 1283409 : void DecodeFunctionBody() {
767 : TRACE("wasm-decode %p...%p (module+%d, %d bytes) %s\n",
768 : reinterpret_cast<const void*>(start_),
769 : reinterpret_cast<const void*>(end_), baserel(pc_),
770 : static_cast<int>(end_ - start_), builder_ ? "graph building" : "");
771 :
772 : {
773 : // Set up initial function block.
774 86565 : SsaEnv* break_env = ssa_env_;
775 86565 : SetEnv("initial env", Steal(break_env));
776 86573 : PushBlock(break_env);
777 397954 : Control* c = &control_.back();
778 160653 : c->merge.arity = static_cast<uint32_t>(sig_->return_count());
779 :
780 86549 : if (c->merge.arity == 1) {
781 142504 : c->merge.vals.first = {pc_, nullptr, sig_->GetReturn(0)};
782 15297 : } else if (c->merge.arity > 1) {
783 2848 : c->merge.vals.array = zone_->NewArray<Value>(c->merge.arity);
784 4276 : for (unsigned i = 0; i < c->merge.arity; i++) {
785 5704 : c->merge.vals.array[i] = {pc_, nullptr, sig_->GetReturn(i)};
786 : }
787 : }
788 : }
789 :
790 2579761 : while (pc_ < end_) { // decoding loop.
791 : unsigned len = 1;
792 2493339 : WasmOpcode opcode = static_cast<WasmOpcode>(*pc_);
793 : #if DEBUG
794 : if (FLAG_trace_wasm_decoder && !WasmOpcodes::IsPrefixOpcode(opcode)) {
795 : TRACE(" @%-8d #%-20s|", startrel(pc_),
796 : WasmOpcodes::OpcodeName(opcode));
797 : }
798 : #endif
799 :
800 2493339 : FunctionSig* sig = WasmOpcodes::Signature(opcode);
801 2493354 : if (sig) {
802 411395 : BuildSimpleOperator(opcode, sig);
803 : } else {
804 : // Complex bytecode.
805 2081959 : switch (opcode) {
806 : case kExprNop:
807 : break;
808 : case kExprBlock: {
809 : // The break environment is the outer environment.
810 138277 : BlockTypeOperand<true> operand(this, pc_);
811 138277 : SsaEnv* break_env = ssa_env_;
812 138277 : PushBlock(break_env);
813 138277 : SetEnv("block:start", Steal(break_env));
814 138277 : SetBlockType(&control_.back(), operand);
815 138277 : len = 1 + operand.length;
816 : break;
817 : }
818 : case kExprThrow: {
819 128093 : CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype);
820 169 : Value value = Pop(0, kWasmI32);
821 169 : BUILD(Throw, value.node);
822 : // TODO(titzer): Throw should end control, but currently we build a
823 : // (reachable) runtime call instead of connecting it directly to
824 : // end.
825 : // EndControl();
826 : break;
827 : }
828 : case kExprTry: {
829 368 : CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype);
830 124 : BlockTypeOperand<true> operand(this, pc_);
831 124 : SsaEnv* outer_env = ssa_env_;
832 124 : SsaEnv* try_env = Steal(outer_env);
833 : SsaEnv* catch_env = UnreachableEnv();
834 124 : PushTry(outer_env, catch_env);
835 : SetEnv("try_catch:start", try_env);
836 124 : SetBlockType(&control_.back(), operand);
837 124 : len = 1 + operand.length;
838 124 : break;
839 : }
840 : case kExprCatch: {
841 368 : CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype);
842 124 : LocalIndexOperand<true> operand(this, pc_);
843 124 : len = 1 + operand.length;
844 :
845 124 : if (control_.empty()) {
846 : error("catch does not match any try");
847 : break;
848 : }
849 :
850 124 : Control* c = &control_.back();
851 124 : if (!c->is_try()) {
852 : error("catch does not match any try");
853 : break;
854 : }
855 :
856 124 : if (c->try_info->catch_env == nullptr) {
857 1 : error(pc_, "catch already present for try with catch");
858 : break;
859 : }
860 :
861 123 : FallThruTo(c);
862 19954 : stack_.resize(c->stack_depth);
863 :
864 : DCHECK_NOT_NULL(c->try_info);
865 123 : SsaEnv* catch_env = c->try_info->catch_env;
866 123 : c->try_info->catch_env = nullptr;
867 : SetEnv("catch:begin", catch_env);
868 123 : current_catch_ = c->previous_catch;
869 :
870 123 : if (Validate(pc_, operand)) {
871 75888 : if (ssa_env_->locals) {
872 : TFNode* exception_as_i32 =
873 240 : BUILD(Catch, c->try_info->exception, position());
874 120 : ssa_env_->locals[operand.index] = exception_as_i32;
875 : }
876 : }
877 :
878 : break;
879 : }
880 : case kExprLoop: {
881 11623 : BlockTypeOperand<true> operand(this, pc_);
882 11623 : SsaEnv* finish_try_env = Steal(ssa_env_);
883 : // The continue environment is the inner environment.
884 11623 : SsaEnv* loop_body_env = PrepareForLoop(pc_, finish_try_env);
885 : SetEnv("loop:start", loop_body_env);
886 11623 : ssa_env_->SetNotMerged();
887 11623 : PushLoop(finish_try_env);
888 11623 : SetBlockType(&control_.back(), operand);
889 11623 : len = 1 + operand.length;
890 : break;
891 : }
892 : case kExprIf: {
893 : // Condition on top of stack. Split environments for branches.
894 71911 : BlockTypeOperand<true> operand(this, pc_);
895 71911 : Value cond = Pop(0, kWasmI32);
896 71911 : TFNode* if_true = nullptr;
897 71911 : TFNode* if_false = nullptr;
898 71911 : BUILD(BranchNoHint, cond.node, &if_true, &if_false);
899 71911 : SsaEnv* end_env = ssa_env_;
900 71911 : SsaEnv* false_env = Split(ssa_env_);
901 71911 : false_env->control = if_false;
902 71911 : SsaEnv* true_env = Steal(ssa_env_);
903 71911 : true_env->control = if_true;
904 71911 : PushIf(end_env, false_env);
905 : SetEnv("if:true", true_env);
906 71911 : SetBlockType(&control_.back(), operand);
907 71911 : len = 1 + operand.length;
908 : break;
909 : }
910 : case kExprElse: {
911 30867 : if (control_.empty()) {
912 0 : error("else does not match any if");
913 : break;
914 : }
915 30867 : Control* c = &control_.back();
916 30867 : if (!c->is_if()) {
917 0 : error(pc_, "else does not match an if");
918 : break;
919 : }
920 30867 : if (c->false_env == nullptr) {
921 2 : error(pc_, "else already present for if");
922 : break;
923 : }
924 30865 : FallThruTo(c);
925 30865 : stack_.resize(c->stack_depth);
926 : // Switch to environment for false branch.
927 30865 : SetEnv("if_else:false", c->false_env);
928 30865 : c->false_env = nullptr; // record that an else is already seen
929 30865 : break;
930 : }
931 : case kExprEnd: {
932 295599 : if (control_.empty()) {
933 0 : error("end does not match any if, try, or block");
934 : return;
935 : }
936 : const char* name = "block:end";
937 295599 : Control* c = &control_.back();
938 295599 : if (c->is_loop()) {
939 : // A loop just leaves the values on the stack.
940 10243 : TypeCheckFallThru(c);
941 10243 : if (c->unreachable) PushEndValues(c);
942 : PopControl();
943 10243 : SetEnv("loop:end", ssa_env_);
944 : break;
945 : }
946 285356 : if (c->is_if()) {
947 71853 : if (c->false_env != nullptr) {
948 : // End the true branch of a one-armed if.
949 41011 : Goto(c->false_env, c->end_env);
950 60842 : if (!c->unreachable && stack_.size() != c->stack_depth) {
951 1 : error("end of if expected empty stack");
952 1 : stack_.resize(c->stack_depth);
953 : }
954 41011 : if (c->merge.arity > 0) {
955 0 : error("non-void one-armed if");
956 : }
957 : name = "if:merge";
958 : } else {
959 : // End the false branch of a two-armed if.
960 : name = "if_else:merge";
961 : }
962 213503 : } else if (c->is_try()) {
963 : name = "try:end";
964 :
965 : // validate that catch was seen.
966 123 : if (c->try_info->catch_env != nullptr) {
967 1 : error(pc_, "missing catch in try");
968 : break;
969 : }
970 : }
971 285355 : FallThruTo(c);
972 285359 : SetEnv(name, c->end_env);
973 285359 : PushEndValues(c);
974 :
975 285389 : if (control_.size() == 1) {
976 : // If at the last (implicit) control, check we are at end.
977 76815 : if (pc_ + 1 != end_) {
978 1050 : error(pc_ + 1, "trailing code after function end");
979 : break;
980 : }
981 75765 : last_end_found_ = true;
982 151530 : if (ssa_env_->go()) {
983 : // The result of the block is the return value.
984 : TRACE(" @%-8d #xx:%-20s|", startrel(pc_), "(implicit) return");
985 60157 : DoReturn();
986 : TRACE("\n");
987 : } else {
988 15608 : TypeCheckFallThru(c);
989 : }
990 : }
991 : PopControl();
992 : break;
993 : }
994 : case kExprSelect: {
995 123 : Value cond = Pop(2, kWasmI32);
996 123 : Value fval = Pop();
997 123 : Value tval = Pop(0, fval.type);
998 123 : if (build()) {
999 : TFNode* controls[2];
1000 95 : builder_->BranchNoHint(cond.node, &controls[0], &controls[1]);
1001 95 : TFNode* merge = builder_->Merge(2, controls);
1002 95 : TFNode* vals[2] = {tval.node, fval.node};
1003 95 : TFNode* phi = builder_->Phi(tval.type, 2, vals, merge);
1004 : Push(tval.type, phi);
1005 95 : ssa_env_->control = merge;
1006 : } else {
1007 28 : Push(tval.type == kWasmVar ? fval.type : tval.type, nullptr);
1008 : }
1009 : break;
1010 : }
1011 : case kExprBr: {
1012 33738 : BreakDepthOperand<true> operand(this, pc_);
1013 33738 : if (Validate(pc_, operand, control_)) {
1014 33277 : BreakTo(operand.depth);
1015 : }
1016 33738 : len = 1 + operand.length;
1017 33738 : EndControl();
1018 : break;
1019 : }
1020 : case kExprBrIf: {
1021 9247 : BreakDepthOperand<true> operand(this, pc_);
1022 9247 : Value cond = Pop(0, kWasmI32);
1023 9247 : if (ok() && Validate(pc_, operand, control_)) {
1024 9235 : SsaEnv* fenv = ssa_env_;
1025 9235 : SsaEnv* tenv = Split(fenv);
1026 : fenv->SetNotMerged();
1027 9235 : BUILD(BranchNoHint, cond.node, &tenv->control, &fenv->control);
1028 9235 : ssa_env_ = tenv;
1029 9235 : BreakTo(operand.depth);
1030 9235 : ssa_env_ = fenv;
1031 : }
1032 9247 : len = 1 + operand.length;
1033 : break;
1034 : }
1035 : case kExprBrTable: {
1036 7848 : BranchTableOperand<true> operand(this, pc_);
1037 : BranchTableIterator<true> iterator(this, operand);
1038 : if (Validate(pc_, operand, control_.size())) {
1039 7848 : Value key = Pop(0, kWasmI32);
1040 7848 : if (failed()) break;
1041 :
1042 7847 : SsaEnv* break_env = ssa_env_;
1043 7847 : if (operand.table_count > 0) {
1044 : // Build branches to the various blocks based on the table.
1045 7721 : TFNode* sw = BUILD(Switch, operand.table_count + 1, key.node);
1046 :
1047 7721 : SsaEnv* copy = Steal(break_env);
1048 7721 : ssa_env_ = copy;
1049 : MergeValues* merge = nullptr;
1050 135522 : while (ok() && iterator.has_next()) {
1051 56227 : uint32_t i = iterator.cur_index();
1052 56227 : const byte* pos = iterator.pc();
1053 56227 : uint32_t target = iterator.next();
1054 112454 : if (target >= control_.size()) {
1055 : error(pos, "improper branch in br_table");
1056 : break;
1057 : }
1058 56212 : ssa_env_ = Split(copy);
1059 56212 : ssa_env_->control = (i == operand.table_count)
1060 7624 : ? BUILD(IfDefault, sw)
1061 120048 : : BUILD(IfValue, i, sw);
1062 56212 : BreakTo(target);
1063 :
1064 : // Check that label types match up.
1065 : static MergeValues loop_dummy = {0, {nullptr}};
1066 112424 : Control* c = &control_[control_.size() - target - 1];
1067 56212 : MergeValues* current = c->is_loop() ? &loop_dummy : &c->merge;
1068 56212 : if (i == 0) {
1069 : merge = current;
1070 48491 : } else if (merge->arity != current->arity) {
1071 : errorf(pos,
1072 : "inconsistent arity in br_table target %d"
1073 : " (previous was %u, this one %u)",
1074 32 : i, merge->arity, current->arity);
1075 48459 : } else if (control_.back().unreachable) {
1076 144 : for (uint32_t j = 0; ok() && j < merge->arity; ++j) {
1077 144 : if ((*merge)[j].type != (*current)[j].type) {
1078 : errorf(pos,
1079 : "type error in br_table target %d operand %d"
1080 : " (previous expected %s, this one %s)",
1081 : i, j, WasmOpcodes::TypeName((*merge)[j].type),
1082 64 : WasmOpcodes::TypeName((*current)[j].type));
1083 : }
1084 : }
1085 : }
1086 : }
1087 7721 : if (failed()) break;
1088 : } else {
1089 : // Only a default target. Do the equivalent of br.
1090 126 : const byte* pos = iterator.pc();
1091 126 : uint32_t target = iterator.next();
1092 252 : if (target >= control_.size()) {
1093 : error(pos, "improper branch in br_table");
1094 : break;
1095 : }
1096 116 : BreakTo(target);
1097 : }
1098 : // br_table ends the control flow like br.
1099 7757 : ssa_env_ = break_env;
1100 : }
1101 7757 : len = 1 + iterator.length();
1102 7757 : EndControl();
1103 7757 : break;
1104 : }
1105 : case kExprReturn: {
1106 79069 : DoReturn();
1107 79069 : break;
1108 : }
1109 : case kExprUnreachable: {
1110 1706 : BUILD(Unreachable, position());
1111 1267 : EndControl();
1112 1267 : break;
1113 : }
1114 : case kExprI32Const: {
1115 470450 : ImmI32Operand<true> operand(this, pc_);
1116 470440 : Push(kWasmI32, BUILD(Int32Constant, operand.value));
1117 470541 : len = 1 + operand.length;
1118 : break;
1119 : }
1120 : case kExprI64Const: {
1121 6108 : ImmI64Operand<true> operand(this, pc_);
1122 6108 : Push(kWasmI64, BUILD(Int64Constant, operand.value));
1123 6108 : len = 1 + operand.length;
1124 : break;
1125 : }
1126 : case kExprF32Const: {
1127 944 : ImmF32Operand<true> operand(this, pc_);
1128 944 : Push(kWasmF32, BUILD(Float32Constant, operand.value));
1129 944 : len = 1 + operand.length;
1130 : break;
1131 : }
1132 : case kExprF64Const: {
1133 10799 : ImmF64Operand<true> operand(this, pc_);
1134 10799 : Push(kWasmF64, BUILD(Float64Constant, operand.value));
1135 10798 : len = 1 + operand.length;
1136 : break;
1137 : }
1138 : case kExprGetLocal: {
1139 469047 : LocalIndexOperand<true> operand(this, pc_);
1140 469063 : if (Validate(pc_, operand)) {
1141 469079 : if (build()) {
1142 451812 : Push(operand.type, ssa_env_->locals[operand.index]);
1143 : } else {
1144 17267 : Push(operand.type, nullptr);
1145 : }
1146 : }
1147 469104 : len = 1 + operand.length;
1148 : break;
1149 : }
1150 : case kExprSetLocal: {
1151 132019 : LocalIndexOperand<true> operand(this, pc_);
1152 132019 : if (Validate(pc_, operand)) {
1153 281373 : Value val = Pop(0, local_type_vec_[operand.index]);
1154 132013 : if (ssa_env_->locals) ssa_env_->locals[operand.index] = val.node;
1155 : }
1156 132017 : len = 1 + operand.length;
1157 : break;
1158 : }
1159 : case kExprTeeLocal: {
1160 17344 : LocalIndexOperand<true> operand(this, pc_);
1161 17344 : if (Validate(pc_, operand)) {
1162 34686 : Value val = Pop(0, local_type_vec_[operand.index]);
1163 17343 : if (ssa_env_->locals) ssa_env_->locals[operand.index] = val.node;
1164 17343 : Push(val.type, val.node);
1165 : }
1166 17344 : len = 1 + operand.length;
1167 : break;
1168 : }
1169 : case kExprDrop: {
1170 71164 : Pop();
1171 71164 : break;
1172 : }
1173 : case kExprGetGlobal: {
1174 7854 : GlobalIndexOperand<true> operand(this, pc_);
1175 7854 : if (Validate(pc_, operand)) {
1176 7854 : Push(operand.type, BUILD(GetGlobal, operand.index));
1177 : }
1178 7854 : len = 1 + operand.length;
1179 : break;
1180 : }
1181 : case kExprSetGlobal: {
1182 10978 : GlobalIndexOperand<true> operand(this, pc_);
1183 10978 : if (Validate(pc_, operand)) {
1184 10978 : if (operand.global->mutability) {
1185 10977 : Value val = Pop(0, operand.type);
1186 10977 : BUILD(SetGlobal, operand.index, val.node);
1187 : } else {
1188 : errorf(pc_, "immutable global #%u cannot be assigned",
1189 1 : operand.index);
1190 : }
1191 : }
1192 10978 : len = 1 + operand.length;
1193 : break;
1194 : }
1195 : case kExprI32LoadMem8S:
1196 4961 : len = DecodeLoadMem(kWasmI32, MachineType::Int8());
1197 4961 : break;
1198 : case kExprI32LoadMem8U:
1199 295 : len = DecodeLoadMem(kWasmI32, MachineType::Uint8());
1200 295 : break;
1201 : case kExprI32LoadMem16S:
1202 34 : len = DecodeLoadMem(kWasmI32, MachineType::Int16());
1203 34 : break;
1204 : case kExprI32LoadMem16U:
1205 310 : len = DecodeLoadMem(kWasmI32, MachineType::Uint16());
1206 310 : break;
1207 : case kExprI32LoadMem:
1208 5894 : len = DecodeLoadMem(kWasmI32, MachineType::Int32());
1209 5894 : break;
1210 : case kExprI64LoadMem8S:
1211 19 : len = DecodeLoadMem(kWasmI64, MachineType::Int8());
1212 19 : break;
1213 : case kExprI64LoadMem8U:
1214 5 : len = DecodeLoadMem(kWasmI64, MachineType::Uint8());
1215 5 : break;
1216 : case kExprI64LoadMem16S:
1217 19 : len = DecodeLoadMem(kWasmI64, MachineType::Int16());
1218 19 : break;
1219 : case kExprI64LoadMem16U:
1220 5 : len = DecodeLoadMem(kWasmI64, MachineType::Uint16());
1221 5 : break;
1222 : case kExprI64LoadMem32S:
1223 19 : len = DecodeLoadMem(kWasmI64, MachineType::Int32());
1224 19 : break;
1225 : case kExprI64LoadMem32U:
1226 5 : len = DecodeLoadMem(kWasmI64, MachineType::Uint32());
1227 5 : break;
1228 : case kExprI64LoadMem:
1229 1073 : len = DecodeLoadMem(kWasmI64, MachineType::Int64());
1230 1073 : break;
1231 : case kExprF32LoadMem:
1232 1623 : len = DecodeLoadMem(kWasmF32, MachineType::Float32());
1233 1623 : break;
1234 : case kExprF64LoadMem:
1235 1868 : len = DecodeLoadMem(kWasmF64, MachineType::Float64());
1236 1868 : break;
1237 : case kExprS128LoadMem:
1238 0 : CHECK_PROTOTYPE_OPCODE(wasm_simd_prototype);
1239 0 : len = DecodeLoadMem(kWasmS128, MachineType::Simd128());
1240 0 : break;
1241 : case kExprI32StoreMem8:
1242 322 : len = DecodeStoreMem(kWasmI32, MachineType::Int8());
1243 322 : break;
1244 : case kExprI32StoreMem16:
1245 293 : len = DecodeStoreMem(kWasmI32, MachineType::Int16());
1246 293 : break;
1247 : case kExprI32StoreMem:
1248 784 : len = DecodeStoreMem(kWasmI32, MachineType::Int32());
1249 784 : break;
1250 : case kExprI64StoreMem8:
1251 0 : len = DecodeStoreMem(kWasmI64, MachineType::Int8());
1252 0 : break;
1253 : case kExprI64StoreMem16:
1254 0 : len = DecodeStoreMem(kWasmI64, MachineType::Int16());
1255 0 : break;
1256 : case kExprI64StoreMem32:
1257 0 : len = DecodeStoreMem(kWasmI64, MachineType::Int32());
1258 0 : break;
1259 : case kExprI64StoreMem:
1260 167 : len = DecodeStoreMem(kWasmI64, MachineType::Int64());
1261 167 : break;
1262 : case kExprF32StoreMem:
1263 177 : len = DecodeStoreMem(kWasmF32, MachineType::Float32());
1264 177 : break;
1265 : case kExprF64StoreMem:
1266 205 : len = DecodeStoreMem(kWasmF64, MachineType::Float64());
1267 205 : break;
1268 : case kExprS128StoreMem:
1269 0 : CHECK_PROTOTYPE_OPCODE(wasm_simd_prototype);
1270 0 : len = DecodeStoreMem(kWasmS128, MachineType::Simd128());
1271 0 : break;
1272 : case kExprGrowMemory: {
1273 939 : if (!CheckHasMemory()) break;
1274 924 : MemoryIndexOperand<true> operand(this, pc_);
1275 : DCHECK_NOT_NULL(module_);
1276 1848 : if (module_->is_wasm()) {
1277 923 : Value val = Pop(0, kWasmI32);
1278 923 : Push(kWasmI32, BUILD(GrowMemory, val.node));
1279 : } else {
1280 : error("grow_memory is not supported for asmjs modules");
1281 : }
1282 924 : len = 1 + operand.length;
1283 924 : break;
1284 : }
1285 : case kExprMemorySize: {
1286 571 : if (!CheckHasMemory()) break;
1287 571 : MemoryIndexOperand<true> operand(this, pc_);
1288 571 : Push(kWasmI32, BUILD(CurrentMemoryPages));
1289 571 : len = 1 + operand.length;
1290 571 : break;
1291 : }
1292 : case kExprCallFunction: {
1293 33774 : CallFunctionOperand<true> operand(this, pc_);
1294 33773 : if (Validate(pc_, operand)) {
1295 33782 : TFNode** buffer = PopArgs(operand.sig);
1296 33784 : TFNode** rets = nullptr;
1297 66975 : BUILD(CallDirect, operand.index, buffer, &rets, position());
1298 33789 : PushReturns(operand.sig, rets);
1299 : }
1300 33784 : len = 1 + operand.length;
1301 : break;
1302 : }
1303 : case kExprCallIndirect: {
1304 2384 : CallIndirectOperand<true> operand(this, pc_);
1305 2384 : if (Validate(pc_, operand)) {
1306 2369 : Value index = Pop(0, kWasmI32);
1307 2369 : TFNode** buffer = PopArgs(operand.sig);
1308 2369 : if (buffer) buffer[0] = index.node;
1309 2369 : TFNode** rets = nullptr;
1310 4733 : BUILD(CallIndirect, operand.index, buffer, &rets, position());
1311 2369 : PushReturns(operand.sig, rets);
1312 : }
1313 2384 : len = 1 + operand.length;
1314 : break;
1315 : }
1316 : case kSimdPrefix: {
1317 19383 : CHECK_PROTOTYPE_OPCODE(wasm_simd_prototype);
1318 : len++;
1319 6461 : byte simd_index = read_u8<true>(pc_ + 1, "simd index");
1320 6461 : opcode = static_cast<WasmOpcode>(opcode << 8 | simd_index);
1321 : TRACE(" @%-4d #%-20s|", startrel(pc_),
1322 : WasmOpcodes::OpcodeName(opcode));
1323 6461 : len += DecodeSimdOpcode(opcode);
1324 6461 : break;
1325 : }
1326 : case kAtomicPrefix: {
1327 0 : if (module_ == nullptr || !module_->is_asm_js()) {
1328 0 : error("Atomics are allowed only in AsmJs modules");
1329 : break;
1330 : }
1331 0 : if (!FLAG_wasm_atomics_prototype) {
1332 0 : error("Invalid opcode (enable with --wasm_atomics_prototype)");
1333 : break;
1334 : }
1335 : len = 2;
1336 0 : byte atomic_opcode = read_u8<true>(pc_ + 1, "atomic index");
1337 0 : opcode = static_cast<WasmOpcode>(opcode << 8 | atomic_opcode);
1338 0 : sig = WasmOpcodes::AtomicSignature(opcode);
1339 0 : if (sig) {
1340 0 : BuildAtomicOperator(opcode);
1341 : }
1342 : break;
1343 : }
1344 : default: {
1345 : // Deal with special asmjs opcodes.
1346 240248 : if (module_ != nullptr && module_->is_asm_js()) {
1347 119935 : sig = WasmOpcodes::AsmjsSignature(opcode);
1348 119935 : if (sig) {
1349 119935 : BuildSimpleOperator(opcode, sig);
1350 : }
1351 : } else {
1352 189 : error("Invalid opcode");
1353 : return;
1354 : }
1355 : }
1356 : }
1357 : }
1358 :
1359 : #if DEBUG
1360 : if (FLAG_trace_wasm_decoder) {
1361 : PrintF(" ");
1362 : for (size_t i = 0; i < control_.size(); ++i) {
1363 : Control* c = &control_[i];
1364 : enum ControlKind {
1365 : kControlIf,
1366 : kControlBlock,
1367 : kControlLoop,
1368 : kControlTry
1369 : };
1370 : switch (c->kind) {
1371 : case kControlIf:
1372 : PrintF("I");
1373 : break;
1374 : case kControlBlock:
1375 : PrintF("B");
1376 : break;
1377 : case kControlLoop:
1378 : PrintF("L");
1379 : break;
1380 : case kControlTry:
1381 : PrintF("T");
1382 : break;
1383 : default:
1384 : break;
1385 : }
1386 : PrintF("%u", c->merge.arity);
1387 : if (c->unreachable) PrintF("*");
1388 : }
1389 : PrintF(" | ");
1390 : for (size_t i = 0; i < stack_.size(); ++i) {
1391 : Value& val = stack_[i];
1392 : WasmOpcode opcode = static_cast<WasmOpcode>(*val.pc);
1393 : if (WasmOpcodes::IsPrefixOpcode(opcode)) {
1394 : opcode = static_cast<WasmOpcode>(opcode << 8 | *(val.pc + 1));
1395 : }
1396 : PrintF(" %c@%d:%s", WasmOpcodes::ShortNameOf(val.type),
1397 : static_cast<int>(val.pc - start_),
1398 : WasmOpcodes::OpcodeName(opcode));
1399 : switch (opcode) {
1400 : case kExprI32Const: {
1401 : ImmI32Operand<true> operand(this, val.pc);
1402 : PrintF("[%d]", operand.value);
1403 : break;
1404 : }
1405 : case kExprGetLocal: {
1406 : LocalIndexOperand<true> operand(this, val.pc);
1407 : PrintF("[%u]", operand.index);
1408 : break;
1409 : }
1410 : case kExprSetLocal: // fallthru
1411 : case kExprTeeLocal: {
1412 : LocalIndexOperand<true> operand(this, val.pc);
1413 : PrintF("[%u]", operand.index);
1414 : break;
1415 : }
1416 : default:
1417 : break;
1418 : }
1419 : if (val.node == nullptr) PrintF("?");
1420 : }
1421 : PrintF("\n");
1422 : }
1423 : #endif
1424 2493212 : pc_ += len;
1425 : } // end decode loop
1426 96949 : if (pc_ > end_ && ok()) error("Beyond end of code");
1427 : }
1428 :
1429 182005 : void EndControl() {
1430 182005 : ssa_env_->Kill(SsaEnv::kControlEnd);
1431 182005 : if (!control_.empty()) {
1432 182044 : stack_.resize(control_.back().stack_depth);
1433 182043 : control_.back().unreachable = true;
1434 : }
1435 182004 : }
1436 :
1437 228699 : void SetBlockType(Control* c, BlockTypeOperand<true>& operand) {
1438 221935 : c->merge.arity = operand.arity;
1439 221935 : if (c->merge.arity == 1) {
1440 13416 : c->merge.vals.first = {pc_, nullptr, operand.read_entry(0)};
1441 215227 : } else if (c->merge.arity > 1) {
1442 56 : c->merge.vals.array = zone_->NewArray<Value>(c->merge.arity);
1443 84 : for (unsigned i = 0; i < c->merge.arity; i++) {
1444 112 : c->merge.vals.array[i] = {pc_, nullptr, operand.read_entry(i)};
1445 : }
1446 : }
1447 221935 : }
1448 :
1449 170849 : TFNode** PopArgs(FunctionSig* sig) {
1450 36152 : if (build()) {
1451 35560 : int count = static_cast<int>(sig->parameter_count());
1452 35560 : TFNode** buffer = builder_->Buffer(count + 1);
1453 35561 : buffer[0] = nullptr; // reserved for code object or function index.
1454 133962 : for (int i = count - 1; i >= 0; i--) {
1455 196812 : buffer[i + 1] = Pop(i, sig->GetParam(i)).node;
1456 : }
1457 : return buffer;
1458 : } else {
1459 592 : int count = static_cast<int>(sig->parameter_count());
1460 731 : for (int i = count - 1; i >= 0; i--) {
1461 278 : Pop(i, sig->GetParam(i));
1462 : }
1463 : return nullptr;
1464 : }
1465 : }
1466 :
1467 1064778 : ValueType GetReturnType(FunctionSig* sig) {
1468 532389 : return sig->return_count() == 0 ? kWasmStmt : sig->GetReturn();
1469 : }
1470 :
1471 224850 : void PushBlock(SsaEnv* end_env) {
1472 : control_.emplace_back(
1473 674550 : Control::Block(pc_, stack_.size(), end_env, current_catch_));
1474 224806 : }
1475 :
1476 11623 : void PushLoop(SsaEnv* end_env) {
1477 : control_.emplace_back(
1478 34869 : Control::Loop(pc_, stack_.size(), end_env, current_catch_));
1479 11623 : }
1480 :
1481 71911 : void PushIf(SsaEnv* end_env, SsaEnv* false_env) {
1482 : control_.emplace_back(
1483 215733 : Control::If(pc_, stack_.size(), end_env, false_env, current_catch_));
1484 71911 : }
1485 :
1486 124 : void PushTry(SsaEnv* end_env, SsaEnv* catch_env) {
1487 : control_.emplace_back(Control::Try(pc_, stack_.size(), end_env, zone_,
1488 372 : catch_env, current_catch_));
1489 124 : current_catch_ = static_cast<int32_t>(control_.size() - 1);
1490 124 : }
1491 :
1492 : void PopControl() { control_.pop_back(); }
1493 :
1494 48250 : int DecodeLoadMem(ValueType type, MachineType mem_type) {
1495 16130 : if (!CheckHasMemory()) return 0;
1496 : MemoryAccessOperand<true> operand(
1497 16130 : this, pc_, ElementSizeLog2Of(mem_type.representation()));
1498 :
1499 16130 : Value index = Pop(0, kWasmI32);
1500 32120 : TFNode* node = BUILD(LoadMem, type, mem_type, index.node, operand.offset,
1501 : operand.alignment, position());
1502 : Push(type, node);
1503 16130 : return 1 + operand.length;
1504 : }
1505 :
1506 5779 : int DecodeStoreMem(ValueType type, MachineType mem_type) {
1507 1948 : if (!CheckHasMemory()) return 0;
1508 : MemoryAccessOperand<true> operand(
1509 1948 : this, pc_, ElementSizeLog2Of(mem_type.representation()));
1510 1947 : Value val = Pop(1, type);
1511 1947 : Value index = Pop(0, kWasmI32);
1512 1883 : BUILD(StoreMem, mem_type, index.node, operand.offset, operand.alignment,
1513 3831 : val.node, position());
1514 1948 : return 1 + operand.length;
1515 : }
1516 :
1517 10304 : unsigned SimdExtractLane(WasmOpcode opcode, ValueType type) {
1518 5152 : SimdLaneOperand<true> operand(this, pc_);
1519 5152 : if (Validate(pc_, opcode, operand)) {
1520 5152 : compiler::NodeVector inputs(1, zone_);
1521 5152 : inputs[0] = Pop(0, ValueType::kSimd128).node;
1522 5152 : TFNode* node = BUILD(SimdLaneOp, opcode, operand.lane, inputs);
1523 : Push(type, node);
1524 : }
1525 5152 : return operand.length;
1526 : }
1527 :
1528 476 : unsigned SimdReplaceLane(WasmOpcode opcode, ValueType type) {
1529 238 : SimdLaneOperand<true> operand(this, pc_);
1530 238 : if (Validate(pc_, opcode, operand)) {
1531 238 : compiler::NodeVector inputs(2, zone_);
1532 238 : inputs[1] = Pop(1, type).node;
1533 238 : inputs[0] = Pop(0, ValueType::kSimd128).node;
1534 238 : TFNode* node = BUILD(SimdLaneOp, opcode, operand.lane, inputs);
1535 : Push(ValueType::kSimd128, node);
1536 : }
1537 238 : return operand.length;
1538 : }
1539 :
1540 84 : unsigned SimdShiftOp(WasmOpcode opcode) {
1541 42 : SimdShiftOperand<true> operand(this, pc_);
1542 42 : if (Validate(pc_, opcode, operand)) {
1543 42 : compiler::NodeVector inputs(1, zone_);
1544 42 : inputs[0] = Pop(0, ValueType::kSimd128).node;
1545 42 : TFNode* node = BUILD(SimdShiftOp, opcode, operand.shift, inputs);
1546 : Push(ValueType::kSimd128, node);
1547 : }
1548 42 : return operand.length;
1549 : }
1550 :
1551 0 : unsigned SimdConcatOp(WasmOpcode opcode) {
1552 : DCHECK_EQ(wasm::kExprS8x16Concat, opcode);
1553 0 : SimdConcatOperand<true> operand(this, pc_);
1554 0 : if (Validate(pc_, opcode, operand)) {
1555 0 : compiler::NodeVector inputs(2, zone_);
1556 0 : inputs[1] = Pop(1, ValueType::kSimd128).node;
1557 0 : inputs[0] = Pop(0, ValueType::kSimd128).node;
1558 0 : TFNode* node = BUILD(SimdConcatOp, operand.bytes, inputs);
1559 : Push(ValueType::kSimd128, node);
1560 : }
1561 0 : return operand.length;
1562 : }
1563 :
1564 7490 : unsigned DecodeSimdOpcode(WasmOpcode opcode) {
1565 : unsigned len = 0;
1566 6461 : switch (opcode) {
1567 : case kExprF32x4ExtractLane: {
1568 0 : len = SimdExtractLane(opcode, ValueType::kFloat32);
1569 0 : break;
1570 : }
1571 : case kExprI32x4ExtractLane:
1572 : case kExprI16x8ExtractLane:
1573 : case kExprI8x16ExtractLane: {
1574 5152 : len = SimdExtractLane(opcode, ValueType::kWord32);
1575 5152 : break;
1576 : }
1577 : case kExprF32x4ReplaceLane: {
1578 0 : len = SimdReplaceLane(opcode, ValueType::kFloat32);
1579 0 : break;
1580 : }
1581 : case kExprI32x4ReplaceLane:
1582 : case kExprI16x8ReplaceLane:
1583 : case kExprI8x16ReplaceLane: {
1584 238 : len = SimdReplaceLane(opcode, ValueType::kWord32);
1585 238 : break;
1586 : }
1587 : case kExprI32x4Shl:
1588 : case kExprI32x4ShrS:
1589 : case kExprI32x4ShrU:
1590 : case kExprI16x8Shl:
1591 : case kExprI16x8ShrS:
1592 : case kExprI16x8ShrU:
1593 : case kExprI8x16Shl:
1594 : case kExprI8x16ShrS:
1595 : case kExprI8x16ShrU: {
1596 42 : len = SimdShiftOp(opcode);
1597 42 : break;
1598 : }
1599 : case kExprS8x16Concat: {
1600 0 : len = SimdConcatOp(opcode);
1601 0 : break;
1602 : }
1603 : default: {
1604 4501 : FunctionSig* sig = WasmOpcodes::Signature(opcode);
1605 1029 : if (sig != nullptr) {
1606 1029 : compiler::NodeVector inputs(sig->parameter_count(), zone_);
1607 3472 : for (size_t i = sig->parameter_count(); i > 0; i--) {
1608 2828 : Value val = Pop(static_cast<int>(i - 1), sig->GetParam(i - 1));
1609 2828 : inputs[i - 1] = val.node;
1610 : }
1611 1029 : TFNode* node = BUILD(SimdOp, opcode, inputs);
1612 : Push(GetReturnType(sig), node);
1613 : } else {
1614 0 : error("invalid simd opcode");
1615 : }
1616 : }
1617 : }
1618 6461 : return len;
1619 : }
1620 :
1621 0 : void BuildAtomicOperator(WasmOpcode opcode) { UNIMPLEMENTED(); }
1622 :
1623 417506 : void DoReturn() {
1624 265281 : int count = static_cast<int>(sig_->return_count());
1625 : TFNode** buffer = nullptr;
1626 139133 : if (build()) buffer = builder_->Buffer(count);
1627 :
1628 : // Pop return values off the stack in reverse order.
1629 265388 : for (int i = count - 1; i >= 0; i--) {
1630 252296 : Value val = Pop(i, sig_->GetReturn(i));
1631 126179 : if (buffer) buffer[i] = val.node;
1632 : }
1633 :
1634 139240 : BUILD(Return, count, buffer);
1635 139240 : EndControl();
1636 139283 : }
1637 :
1638 : void Push(ValueType type, TFNode* node) {
1639 1070714 : if (type != kWasmStmt) {
1640 3121675 : stack_.push_back({pc_, node, type});
1641 : }
1642 : }
1643 :
1644 287113 : void PushEndValues(Control* c) {
1645 : DCHECK_EQ(c, &control_.back());
1646 287113 : stack_.resize(c->stack_depth);
1647 287162 : if (c->merge.arity == 1) {
1648 68971 : stack_.push_back(c->merge.vals.first);
1649 : } else {
1650 2899 : for (unsigned i = 0; i < c->merge.arity; i++) {
1651 2899 : stack_.push_back(c->merge.vals.array[i]);
1652 : }
1653 : }
1654 : DCHECK_EQ(c->stack_depth + c->merge.arity, stack_.size());
1655 287157 : }
1656 :
1657 117587 : void PushReturns(FunctionSig* sig, TFNode** rets) {
1658 117594 : for (size_t i = 0; i < sig->return_count(); i++) {
1659 : // When verifying only, then {rets} will be null, so push null.
1660 22644 : Push(sig->GetReturn(i), rets ? rets[i] : nullptr);
1661 : }
1662 36153 : }
1663 :
1664 : const char* SafeOpcodeNameAt(const byte* pc) {
1665 25745 : if (pc >= end_) return "<end>";
1666 21305 : return WasmOpcodes::OpcodeName(static_cast<WasmOpcode>(*pc));
1667 : }
1668 :
1669 1491398 : Value Pop(int index, ValueType expected) {
1670 1465964 : Value val = Pop();
1671 1466034 : if (val.type != expected && val.type != kWasmVar && expected != kWasmVar) {
1672 : errorf(val.pc, "%s[%d] expected type %s, found %s of type %s",
1673 : SafeOpcodeNameAt(pc_), index, WasmOpcodes::TypeName(expected),
1674 38151 : SafeOpcodeNameAt(val.pc), WasmOpcodes::TypeName(val.type));
1675 : }
1676 1466034 : return val;
1677 : }
1678 :
1679 1537579 : Value Pop() {
1680 1537268 : size_t limit = control_.empty() ? 0 : control_.back().stack_depth;
1681 3074536 : if (stack_.size() <= limit) {
1682 : // Popping past the current control start in reachable code.
1683 821 : Value val = {pc_, nullptr, kWasmVar};
1684 821 : if (!control_.back().unreachable) {
1685 311 : errorf(pc_, "%s found empty stack", SafeOpcodeNameAt(pc_));
1686 : }
1687 821 : return val;
1688 : }
1689 1536447 : Value val = stack_.back();
1690 : stack_.pop_back();
1691 1536447 : return val;
1692 : }
1693 :
1694 : int baserel(const byte* ptr) {
1695 : return base_ ? static_cast<int>(ptr - base_) : 0;
1696 : }
1697 :
1698 234 : int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); }
1699 :
1700 98906 : void BreakTo(unsigned depth) {
1701 296520 : Control* c = &control_[control_.size() - depth - 1];
1702 98840 : if (c->is_loop()) {
1703 : // This is the inner loop block, which does not have a value.
1704 9797 : Goto(ssa_env_, c->end_env);
1705 : } else {
1706 : // Merge the value(s) into the end of the block.
1707 89043 : size_t expected = control_.back().stack_depth + c->merge.arity;
1708 178086 : if (stack_.size() < expected && !control_.back().unreachable) {
1709 : errorf(
1710 : pc_,
1711 : "expected at least %u values on the stack for br to @%d, found %d",
1712 : c->merge.arity, startrel(c->pc),
1713 132 : static_cast<int>(stack_.size() - c->stack_depth));
1714 98906 : return;
1715 : }
1716 88977 : MergeValuesInto(c);
1717 : }
1718 : }
1719 :
1720 316498 : void FallThruTo(Control* c) {
1721 : DCHECK_EQ(c, &control_.back());
1722 : // Merge the value(s) into the end of the block.
1723 316333 : size_t expected = c->stack_depth + c->merge.arity;
1724 948999 : if (stack_.size() == expected ||
1725 6635 : (stack_.size() < expected && c->unreachable)) {
1726 316168 : MergeValuesInto(c);
1727 316195 : c->unreachable = false;
1728 632555 : return;
1729 : }
1730 : errorf(pc_, "expected %u elements on the stack for fallthru to @%d",
1731 330 : c->merge.arity, startrel(c->pc));
1732 : }
1733 :
1734 : inline Value& GetMergeValueFromStack(Control* c, size_t i) {
1735 157042 : return stack_[stack_.size() - c->merge.arity + i];
1736 : }
1737 :
1738 25854 : void TypeCheckFallThru(Control* c) {
1739 : DCHECK_EQ(c, &control_.back());
1740 : // Fallthru must match arity exactly.
1741 25851 : int arity = static_cast<int>(c->merge.arity);
1742 77553 : if (c->stack_depth + arity < stack_.size() ||
1743 3 : (c->stack_depth + arity != stack_.size() && !c->unreachable)) {
1744 : errorf(pc_, "expected %d elements on the stack for fallthru to @%d",
1745 6 : arity, startrel(c->pc));
1746 3 : return;
1747 : }
1748 : // Typecheck the values left on the stack.
1749 25848 : size_t avail = stack_.size() - c->stack_depth;
1750 39662 : for (size_t i = avail >= c->merge.arity ? 0 : c->merge.arity - avail;
1751 : i < c->merge.arity; i++) {
1752 : Value& val = GetMergeValueFromStack(c, i);
1753 : Value& old = c->merge[i];
1754 13814 : if (val.type != old.type) {
1755 : errorf(pc_, "type error in merge[%zu] (expected %s, got %s)", i,
1756 : WasmOpcodes::TypeName(old.type),
1757 0 : WasmOpcodes::TypeName(val.type));
1758 0 : return;
1759 : }
1760 : }
1761 : }
1762 :
1763 405145 : void MergeValuesInto(Control* c) {
1764 405145 : SsaEnv* target = c->end_env;
1765 405145 : bool first = target->state == SsaEnv::kUnreachable;
1766 405145 : bool reachable = ssa_env_->go();
1767 405145 : Goto(ssa_env_, target);
1768 :
1769 810444 : size_t avail = stack_.size() - control_.back().stack_depth;
1770 951704 : for (size_t i = avail >= c->merge.arity ? 0 : c->merge.arity - avail;
1771 475852 : i < c->merge.arity; i++) {
1772 : Value& val = GetMergeValueFromStack(c, i);
1773 : Value& old = c->merge[i];
1774 71614 : if (val.type != old.type && val.type != kWasmVar) {
1775 : errorf(pc_, "type error in merge[%zu] (expected %s, got %s)", i,
1776 : WasmOpcodes::TypeName(old.type),
1777 1015 : WasmOpcodes::TypeName(val.type));
1778 406198 : return;
1779 : }
1780 70599 : if (builder_ && reachable) {
1781 : DCHECK_NOT_NULL(val.node);
1782 : old.node =
1783 : first ? val.node : CreateOrMergeIntoPhi(old.type, target->control,
1784 59637 : old.node, val.node);
1785 : }
1786 : }
1787 : }
1788 :
1789 : void SetEnv(const char* reason, SsaEnv* env) {
1790 : #if DEBUG
1791 : if (FLAG_trace_wasm_decoder) {
1792 : char state = 'X';
1793 : if (env) {
1794 : switch (env->state) {
1795 : case SsaEnv::kReached:
1796 : state = 'R';
1797 : break;
1798 : case SsaEnv::kUnreachable:
1799 : state = 'U';
1800 : break;
1801 : case SsaEnv::kMerged:
1802 : state = 'M';
1803 : break;
1804 : case SsaEnv::kControlEnd:
1805 : state = 'E';
1806 : break;
1807 : }
1808 : }
1809 : PrintF("{set_env = %p, state = %c, reason = %s", static_cast<void*>(env),
1810 : state, reason);
1811 : if (env && env->control) {
1812 : PrintF(", control = ");
1813 : compiler::WasmGraphBuilder::PrintDebugName(env->control);
1814 : }
1815 : PrintF("}\n");
1816 : }
1817 : #endif
1818 711635 : ssa_env_ = env;
1819 721878 : if (builder_) {
1820 676094 : builder_->set_control_ptr(&env->control);
1821 676094 : builder_->set_effect_ptr(&env->effect);
1822 : }
1823 : }
1824 :
1825 1340071 : TFNode* CheckForException(TFNode* node) {
1826 1340071 : if (node == nullptr) {
1827 : return nullptr;
1828 : }
1829 :
1830 1339654 : const bool inside_try_scope = current_catch_ != kNullCatch;
1831 :
1832 1339654 : if (!inside_try_scope) {
1833 : return node;
1834 : }
1835 :
1836 644 : TFNode* if_success = nullptr;
1837 644 : TFNode* if_exception = nullptr;
1838 644 : if (!builder_->ThrowsException(node, &if_success, &if_exception)) {
1839 : return node;
1840 : }
1841 :
1842 150 : SsaEnv* success_env = Steal(ssa_env_);
1843 150 : success_env->control = if_success;
1844 :
1845 150 : SsaEnv* exception_env = Split(success_env);
1846 150 : exception_env->control = if_exception;
1847 : TryInfo* try_info = current_try_info();
1848 150 : Goto(exception_env, try_info->catch_env);
1849 150 : TFNode* exception = try_info->exception;
1850 150 : if (exception == nullptr) {
1851 : DCHECK_EQ(SsaEnv::kReached, try_info->catch_env->state);
1852 120 : try_info->exception = if_exception;
1853 : } else {
1854 : DCHECK_EQ(SsaEnv::kMerged, try_info->catch_env->state);
1855 : try_info->exception =
1856 : CreateOrMergeIntoPhi(kWasmI32, try_info->catch_env->control,
1857 30 : try_info->exception, if_exception);
1858 : }
1859 :
1860 : SetEnv("if_success", success_env);
1861 150 : return node;
1862 : }
1863 :
1864 456077 : void Goto(SsaEnv* from, SsaEnv* to) {
1865 : DCHECK_NOT_NULL(to);
1866 456077 : if (!from->go()) return;
1867 307801 : switch (to->state) {
1868 : case SsaEnv::kUnreachable: { // Overwrite destination.
1869 233144 : to->state = SsaEnv::kReached;
1870 233144 : to->locals = from->locals;
1871 233144 : to->control = from->control;
1872 233144 : to->effect = from->effect;
1873 233144 : break;
1874 : }
1875 : case SsaEnv::kReached: { // Create a new merge.
1876 50611 : to->state = SsaEnv::kMerged;
1877 50611 : if (!builder_) break;
1878 : // Merge control.
1879 50271 : TFNode* controls[] = {to->control, from->control};
1880 50271 : TFNode* merge = builder_->Merge(2, controls);
1881 50271 : to->control = merge;
1882 : // Merge effects.
1883 50271 : if (from->effect != to->effect) {
1884 24717 : TFNode* effects[] = {to->effect, from->effect, merge};
1885 24717 : to->effect = builder_->EffectPhi(2, effects, merge);
1886 : }
1887 : // Merge SSA values.
1888 926422 : for (int i = EnvironmentCount() - 1; i >= 0; i--) {
1889 876151 : TFNode* a = to->locals[i];
1890 876151 : TFNode* b = from->locals[i];
1891 876151 : if (a != b) {
1892 72937 : TFNode* vals[] = {a, b};
1893 153674 : to->locals[i] = builder_->Phi(local_type_vec_[i], 2, vals, merge);
1894 : }
1895 : }
1896 : break;
1897 : }
1898 : case SsaEnv::kMerged: {
1899 24046 : if (!builder_) break;
1900 24041 : TFNode* merge = to->control;
1901 : // Extend the existing merge.
1902 24041 : builder_->AppendToMerge(merge, from->control);
1903 : // Merge effects.
1904 24041 : if (builder_->IsPhiWithMerge(to->effect, merge)) {
1905 14769 : builder_->AppendToPhi(to->effect, from->effect);
1906 9272 : } else if (to->effect != from->effect) {
1907 294 : uint32_t count = builder_->InputCount(merge);
1908 294 : TFNode** effects = builder_->Buffer(count);
1909 1119 : for (uint32_t j = 0; j < count - 1; j++) {
1910 825 : effects[j] = to->effect;
1911 : }
1912 294 : effects[count - 1] = from->effect;
1913 294 : to->effect = builder_->EffectPhi(count, effects, merge);
1914 : }
1915 : // Merge locals.
1916 463908 : for (int i = EnvironmentCount() - 1; i >= 0; i--) {
1917 439867 : TFNode* tnode = to->locals[i];
1918 439867 : TFNode* fnode = from->locals[i];
1919 439867 : if (builder_->IsPhiWithMerge(tnode, merge)) {
1920 93522 : builder_->AppendToPhi(tnode, fnode);
1921 346345 : } else if (tnode != fnode) {
1922 7800 : uint32_t count = builder_->InputCount(merge);
1923 7800 : TFNode** vals = builder_->Buffer(count);
1924 32920 : for (uint32_t j = 0; j < count - 1; j++) {
1925 25120 : vals[j] = tnode;
1926 : }
1927 7800 : vals[count - 1] = fnode;
1928 7800 : to->locals[i] =
1929 7800 : builder_->Phi(local_type_vec_[i], count, vals, merge);
1930 : }
1931 : }
1932 : break;
1933 : }
1934 : default:
1935 0 : UNREACHABLE();
1936 : }
1937 : return from->Kill();
1938 : }
1939 :
1940 6221 : TFNode* CreateOrMergeIntoPhi(ValueType type, TFNode* merge, TFNode* tnode,
1941 : TFNode* fnode) {
1942 : DCHECK_NOT_NULL(builder_);
1943 6221 : if (builder_->IsPhiWithMerge(tnode, merge)) {
1944 70 : builder_->AppendToPhi(tnode, fnode);
1945 6151 : } else if (tnode != fnode) {
1946 6105 : uint32_t count = builder_->InputCount(merge);
1947 6105 : TFNode** vals = builder_->Buffer(count);
1948 6105 : for (uint32_t j = 0; j < count - 1; j++) vals[j] = tnode;
1949 6105 : vals[count - 1] = fnode;
1950 6105 : return builder_->Phi(type, count, vals, merge);
1951 : }
1952 116 : return tnode;
1953 : }
1954 :
1955 29157 : SsaEnv* PrepareForLoop(const byte* pc, SsaEnv* env) {
1956 11623 : if (!builder_) return Split(env);
1957 8767 : if (!env->go()) return Split(env);
1958 8767 : env->state = SsaEnv::kMerged;
1959 :
1960 8767 : env->control = builder_->Loop(env->control);
1961 8767 : env->effect = builder_->EffectPhi(1, &env->effect, env->control);
1962 8767 : builder_->Terminate(env->effect, env->control);
1963 205986 : BitVector* assigned = AnalyzeLoopAssignment(
1964 17534 : this, pc, static_cast<int>(total_locals()), zone_);
1965 8767 : if (failed()) return env;
1966 8767 : if (assigned != nullptr) {
1967 : // Only introduce phis for variables assigned in this loop.
1968 214753 : for (int i = EnvironmentCount() - 1; i >= 0; i--) {
1969 205986 : if (!assigned->Contains(i)) continue;
1970 : env->locals[i] =
1971 86668 : builder_->Phi(local_type_vec_[i], 1, &env->locals[i], env->control);
1972 : }
1973 8767 : SsaEnv* loop_body_env = Split(env);
1974 : builder_->StackCheck(position(), &(loop_body_env->effect),
1975 17534 : &(loop_body_env->control));
1976 8767 : return loop_body_env;
1977 : }
1978 :
1979 : // Conservatively introduce phis for all local variables.
1980 0 : for (int i = EnvironmentCount() - 1; i >= 0; i--) {
1981 : env->locals[i] =
1982 0 : builder_->Phi(local_type_vec_[i], 1, &env->locals[i], env->control);
1983 : }
1984 :
1985 0 : SsaEnv* loop_body_env = Split(env);
1986 : builder_->StackCheck(position(), &(loop_body_env->effect),
1987 0 : &(loop_body_env->control));
1988 0 : return loop_body_env;
1989 : }
1990 :
1991 : // Create a complete copy of the {from}.
1992 298262 : SsaEnv* Split(SsaEnv* from) {
1993 : DCHECK_NOT_NULL(from);
1994 149131 : SsaEnv* result = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
1995 149131 : size_t size = sizeof(TFNode*) * EnvironmentCount();
1996 149131 : result->control = from->control;
1997 149131 : result->effect = from->effect;
1998 :
1999 149131 : if (from->go()) {
2000 148942 : result->state = SsaEnv::kReached;
2001 : result->locals =
2002 148942 : size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr;
2003 148942 : memcpy(result->locals, from->locals, size);
2004 : } else {
2005 189 : result->state = SsaEnv::kUnreachable;
2006 189 : result->locals = nullptr;
2007 : }
2008 :
2009 149131 : return result;
2010 : }
2011 :
2012 : // Create a copy of {from} that steals its state and leaves {from}
2013 : // unreachable.
2014 316556 : SsaEnv* Steal(SsaEnv* from) {
2015 : DCHECK_NOT_NULL(from);
2016 316556 : if (!from->go()) return UnreachableEnv();
2017 316208 : SsaEnv* result = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
2018 316197 : result->state = SsaEnv::kReached;
2019 316197 : result->locals = from->locals;
2020 316197 : result->control = from->control;
2021 316197 : result->effect = from->effect;
2022 : from->Kill(SsaEnv::kUnreachable);
2023 316197 : return result;
2024 : }
2025 :
2026 : // Create an unreachable environment.
2027 : SsaEnv* UnreachableEnv() {
2028 298 : SsaEnv* result = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
2029 298 : result->state = SsaEnv::kUnreachable;
2030 298 : result->control = nullptr;
2031 298 : result->effect = nullptr;
2032 298 : result->locals = nullptr;
2033 : return result;
2034 : }
2035 :
2036 : int EnvironmentCount() {
2037 619441 : if (builder_) return static_cast<int>(local_type_vec_.size());
2038 : return 0; // if we aren't building a graph, don't bother with SSA renaming.
2039 : }
2040 :
2041 10782 : virtual void onFirstError() {
2042 10782 : end_ = pc_; // Terminate decoding loop.
2043 10782 : builder_ = nullptr; // Don't build any more nodes.
2044 : TRACE(" !%s\n", error_msg_.c_str());
2045 10782 : }
2046 :
2047 : inline wasm::WasmCodePosition position() {
2048 584416 : int offset = static_cast<int>(pc_ - start_);
2049 : DCHECK_EQ(pc_ - start_, offset); // overflows cannot happen
2050 : return offset;
2051 : }
2052 :
2053 2545453 : inline void BuildSimpleOperator(WasmOpcode opcode, FunctionSig* sig) {
2054 : TFNode* node;
2055 531307 : switch (sig->parameter_count()) {
2056 : case 1: {
2057 101554 : Value val = Pop(0, sig->GetParam(0));
2058 201884 : node = BUILD(Unop, opcode, val.node, position());
2059 : break;
2060 : }
2061 : case 2: {
2062 429753 : Value rval = Pop(1, sig->GetParam(1));
2063 429811 : Value lval = Pop(0, sig->GetParam(0));
2064 851144 : node = BUILD(Binop, opcode, lval.node, rval.node, position());
2065 : break;
2066 : }
2067 : default:
2068 0 : UNREACHABLE();
2069 : node = nullptr;
2070 : break;
2071 : }
2072 : Push(GetReturnType(sig), node);
2073 531362 : }
2074 : };
2075 :
2076 21585 : bool DecodeLocalDecls(BodyLocalDecls* decls, const byte* start,
2077 : const byte* end) {
2078 : Decoder decoder(start, end);
2079 21585 : if (WasmDecoder::DecodeLocals(&decoder, nullptr, &decls->type_list)) {
2080 : DCHECK(decoder.ok());
2081 43110 : decls->encoded_size = decoder.pc_offset();
2082 21555 : return true;
2083 : }
2084 : return false;
2085 : }
2086 :
2087 21496 : BytecodeIterator::BytecodeIterator(const byte* start, const byte* end,
2088 : BodyLocalDecls* decls)
2089 21496 : : Decoder(start, end) {
2090 21496 : if (decls != nullptr) {
2091 21493 : if (DecodeLocalDecls(decls, start, end)) {
2092 21464 : pc_ += decls->encoded_size;
2093 21464 : if (pc_ > end_) pc_ = end_;
2094 : }
2095 : }
2096 21496 : }
2097 :
2098 14839 : DecodeResult VerifyWasmCode(AccountingAllocator* allocator,
2099 : const wasm::WasmModule* module,
2100 : FunctionBody& body) {
2101 14839 : Zone zone(allocator, ZONE_NAME);
2102 14839 : WasmFullDecoder decoder(&zone, module, body);
2103 14839 : decoder.Decode();
2104 29678 : return decoder.toResult<DecodeStruct*>(nullptr);
2105 : }
2106 :
2107 71769 : DecodeResult BuildTFGraph(AccountingAllocator* allocator, TFBuilder* builder,
2108 : FunctionBody& body) {
2109 71769 : Zone zone(allocator, ZONE_NAME);
2110 71754 : WasmFullDecoder decoder(&zone, builder, body);
2111 71716 : decoder.Decode();
2112 143358 : return decoder.toResult<DecodeStruct*>(nullptr);
2113 : }
2114 :
2115 237666 : unsigned OpcodeLength(const byte* pc, const byte* end) {
2116 : Decoder decoder(pc, end);
2117 475332 : return WasmDecoder::OpcodeLength(&decoder, pc);
2118 : }
2119 :
2120 236601 : std::pair<uint32_t, uint32_t> StackEffect(const WasmModule* module,
2121 : FunctionSig* sig, const byte* pc,
2122 : const byte* end) {
2123 : WasmDecoder decoder(module, sig, pc, end);
2124 473202 : return decoder.StackEffect(pc);
2125 : }
2126 :
2127 0 : void PrintRawWasmCode(const byte* start, const byte* end) {
2128 0 : AccountingAllocator allocator;
2129 0 : PrintRawWasmCode(&allocator, FunctionBodyForTesting(start, end), nullptr);
2130 0 : }
2131 :
2132 : namespace {
2133 0 : const char* RawOpcodeName(WasmOpcode opcode) {
2134 0 : switch (opcode) {
2135 : #define DECLARE_NAME_CASE(name, opcode, sig) \
2136 : case kExpr##name: \
2137 : return "kExpr" #name;
2138 0 : FOREACH_OPCODE(DECLARE_NAME_CASE)
2139 : #undef DECLARE_NAME_CASE
2140 : default:
2141 : break;
2142 : }
2143 0 : return "Unknown";
2144 : }
2145 : } // namespace
2146 :
2147 0 : bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
2148 : const wasm::WasmModule* module) {
2149 0 : OFStream os(stdout);
2150 0 : Zone zone(allocator, ZONE_NAME);
2151 0 : WasmFullDecoder decoder(&zone, module, body);
2152 : int line_nr = 0;
2153 :
2154 : // Print the function signature.
2155 0 : if (body.sig) {
2156 0 : os << "// signature: " << *body.sig << std::endl;
2157 : ++line_nr;
2158 : }
2159 :
2160 : // Print the local declarations.
2161 : BodyLocalDecls decls(&zone);
2162 0 : BytecodeIterator i(body.start, body.end, &decls);
2163 0 : if (body.start != i.pc() && !FLAG_wasm_code_fuzzer_gen_test) {
2164 0 : os << "// locals: ";
2165 0 : if (!decls.type_list.empty()) {
2166 0 : ValueType type = decls.type_list[0];
2167 : uint32_t count = 0;
2168 0 : for (size_t pos = 0; pos < decls.type_list.size(); ++pos) {
2169 0 : if (decls.type_list[pos] == type) {
2170 0 : ++count;
2171 : } else {
2172 0 : os << " " << count << " " << WasmOpcodes::TypeName(type);
2173 0 : type = decls.type_list[pos];
2174 : count = 1;
2175 : }
2176 : }
2177 : }
2178 : os << std::endl;
2179 : ++line_nr;
2180 :
2181 0 : for (const byte* locals = body.start; locals < i.pc(); locals++) {
2182 0 : os << (locals == body.start ? "0x" : " 0x") << AsHex(*locals, 2) << ",";
2183 : }
2184 : os << std::endl;
2185 : ++line_nr;
2186 : }
2187 :
2188 0 : os << "// body: " << std::endl;
2189 : ++line_nr;
2190 : unsigned control_depth = 0;
2191 0 : for (; i.has_next(); i.next()) {
2192 0 : unsigned length = WasmDecoder::OpcodeLength(&decoder, i.pc());
2193 :
2194 0 : WasmOpcode opcode = i.current();
2195 0 : if (opcode == kExprElse) control_depth--;
2196 :
2197 0 : int num_whitespaces = control_depth < 32 ? 2 * control_depth : 64;
2198 :
2199 : // 64 whitespaces
2200 : const char* padding =
2201 : " ";
2202 0 : os.write(padding, num_whitespaces);
2203 :
2204 0 : os << RawOpcodeName(opcode) << ",";
2205 :
2206 0 : for (size_t j = 1; j < length; ++j) {
2207 0 : os << " 0x" << AsHex(i.pc()[j], 2) << ",";
2208 : }
2209 :
2210 0 : switch (opcode) {
2211 : case kExprElse:
2212 0 : os << " // @" << i.pc_offset();
2213 0 : control_depth++;
2214 0 : break;
2215 : case kExprLoop:
2216 : case kExprIf:
2217 : case kExprBlock:
2218 : case kExprTry: {
2219 0 : BlockTypeOperand<true> operand(&i, i.pc());
2220 0 : os << " // @" << i.pc_offset();
2221 0 : for (unsigned i = 0; i < operand.arity; i++) {
2222 0 : os << " " << WasmOpcodes::TypeName(operand.read_entry(i));
2223 : }
2224 0 : control_depth++;
2225 : break;
2226 : }
2227 : case kExprEnd:
2228 0 : os << " // @" << i.pc_offset();
2229 0 : control_depth--;
2230 0 : break;
2231 : case kExprBr: {
2232 0 : BreakDepthOperand<true> operand(&i, i.pc());
2233 0 : os << " // depth=" << operand.depth;
2234 : break;
2235 : }
2236 : case kExprBrIf: {
2237 0 : BreakDepthOperand<true> operand(&i, i.pc());
2238 0 : os << " // depth=" << operand.depth;
2239 : break;
2240 : }
2241 : case kExprBrTable: {
2242 0 : BranchTableOperand<true> operand(&i, i.pc());
2243 0 : os << " // entries=" << operand.table_count;
2244 : break;
2245 : }
2246 : case kExprCallIndirect: {
2247 0 : CallIndirectOperand<true> operand(&i, i.pc());
2248 0 : os << " // sig #" << operand.index;
2249 0 : if (decoder.Complete(i.pc(), operand)) {
2250 0 : os << ": " << *operand.sig;
2251 : }
2252 : break;
2253 : }
2254 : case kExprCallFunction: {
2255 0 : CallFunctionOperand<true> operand(&i, i.pc());
2256 0 : os << " // function #" << operand.index;
2257 0 : if (decoder.Complete(i.pc(), operand)) {
2258 0 : os << ": " << *operand.sig;
2259 : }
2260 : break;
2261 : }
2262 : default:
2263 : break;
2264 : }
2265 : os << std::endl;
2266 : ++line_nr;
2267 : }
2268 :
2269 0 : return decoder.ok();
2270 : }
2271 :
2272 78 : BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals,
2273 : const byte* start, const byte* end) {
2274 : Decoder decoder(start, end);
2275 : return WasmDecoder::AnalyzeLoopAssignment(&decoder, start,
2276 156 : static_cast<int>(num_locals), zone);
2277 : }
2278 :
2279 : } // namespace wasm
2280 : } // namespace internal
2281 : } // namespace v8
|