Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Side by Side Diff: src/wasm/ast-decoder.cc

Issue 1830663002: [wasm] Binary 11: AST changes. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/signature.h" 5 #include "src/signature.h"
6 6
7 #include "src/bit-vector.h" 7 #include "src/bit-vector.h"
8 #include "src/flags.h" 8 #include "src/flags.h"
9 #include "src/handles.h" 9 #include "src/handles.h"
10 #include "src/zone-containers.h" 10 #include "src/zone-containers.h"
(...skipping 24 matching lines...) Expand all
35 struct Tree { 35 struct Tree {
36 LocalType type; // tree type. 36 LocalType type; // tree type.
37 uint32_t count; // number of children. 37 uint32_t count; // number of children.
38 const byte* pc; // start of the syntax tree. 38 const byte* pc; // start of the syntax tree.
39 TFNode* node; // node in the TurboFan graph. 39 TFNode* node; // node in the TurboFan graph.
40 Tree* children[1]; // pointers to children. 40 Tree* children[1]; // pointers to children.
41 41
42 WasmOpcode opcode() const { return static_cast<WasmOpcode>(*pc); } 42 WasmOpcode opcode() const { return static_cast<WasmOpcode>(*pc); }
43 }; 43 };
44 44
45 // A production represents an incomplete decoded tree in the LR decoder.
46 struct Production {
47 Tree* tree; // the root of the syntax tree.
48 int index; // the current index into the children of the tree.
49
50 WasmOpcode opcode() const { return static_cast<WasmOpcode>(*pc()); }
51 const byte* pc() const { return tree->pc; }
52 bool done() const { return index >= static_cast<int>(tree->count); }
53 Tree* last() const { return index > 0 ? tree->children[index - 1] : nullptr; }
54 };
55
56 // An SsaEnv environment carries the current local variable renaming 45 // An SsaEnv environment carries the current local variable renaming
57 // as well as the current effect and control dependency in the TF graph. 46 // as well as the current effect and control dependency in the TF graph.
58 // It maintains a control state that tracks whether the environment 47 // It maintains a control state that tracks whether the environment
59 // is reachable, has reached a control end, or has been merged. 48 // is reachable, has reached a control end, or has been merged.
60 struct SsaEnv { 49 struct SsaEnv {
61 enum State { kControlEnd, kUnreachable, kReached, kMerged }; 50 enum State { kControlEnd, kUnreachable, kReached, kMerged };
62 51
63 State state; 52 State state;
64 TFNode* control; 53 TFNode* control;
65 TFNode* effect; 54 TFNode* effect;
66 TFNode** locals; 55 TFNode** locals;
67 56
68 bool go() { return state >= kReached; } 57 bool go() { return state >= kReached; }
69 void Kill(State new_state = kControlEnd) { 58 void Kill(State new_state = kControlEnd) {
70 state = new_state; 59 state = new_state;
71 locals = nullptr; 60 locals = nullptr;
72 control = nullptr; 61 control = nullptr;
73 effect = nullptr; 62 effect = nullptr;
74 } 63 }
64 void SetNotMerged() {
65 if (state == kMerged) state = kReached;
66 }
75 }; 67 };
76 68
77 // An entry in the stack of blocks during decoding. 69 // An entry on the value stack.
78 struct Block { 70 struct Value {
79 SsaEnv* ssa_env; // SSA renaming environment. 71 const byte* pc;
80 int stack_depth; // production stack depth. 72 TFNode* node;
73 LocalType type;
81 }; 74 };
82 75
83 // An entry in the stack of ifs during decoding. 76 // An entry on the control stack (i.e. if, block, loop).
84 struct IfEnv { 77 struct Control {
85 SsaEnv* false_env; 78 const byte* pc;
86 SsaEnv* merge_env; 79 int stack_depth; // stack height at the beginning of the construct.
87 SsaEnv** case_envs; 80 int block_depth; // block height at the beginning of the construct.
81 SsaEnv* ssa_env; // end environment for the construct.
82 TFNode* node; // result node for the construct.
83 LocalType type; // result type for the construct.
84
85 int counter; // used by if.
86 int max; // used by fi
87
88 bool is_if() { return *pc == kExprIf; }
89 bool is_block() { return *pc == kExprBlock; }
90 bool is_loop() { return *pc == kExprLoop && stack_depth < 0; }
88 }; 91 };
89 92
90 // Macros that build nodes only if there is a graph and the current SSA 93 // Macros that build nodes only if there is a graph and the current SSA
91 // environment is reachable from start. This avoids problems with malformed 94 // environment is reachable from start. This avoids problems with malformed
92 // TF graphs when decoding inputs that have unreachable code. 95 // TF graphs when decoding inputs that have unreachable code.
93 #define BUILD(func, ...) (build() ? builder_->func(__VA_ARGS__) : nullptr) 96 #define BUILD(func, ...) (build() ? builder_->func(__VA_ARGS__) : nullptr)
94 #define BUILD0(func) (build() ? builder_->func() : nullptr) 97 #define BUILD0(func) (build() ? builder_->func() : nullptr)
95 98
96 // Generic Wasm bytecode decoder with utilities for decoding operands, 99 // Generic Wasm bytecode decoder with utilities for decoding operands,
97 // lengths, etc. 100 // lengths, etc.
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 ModuleEnv* m = module_; 184 ModuleEnv* m = module_;
182 if (m && m->module && operand.index < m->module->import_table.size()) { 185 if (m && m->module && operand.index < m->module->import_table.size()) {
183 operand.sig = m->module->import_table[operand.index].sig; 186 operand.sig = m->module->import_table[operand.index].sig;
184 return true; 187 return true;
185 } 188 }
186 error(pc, pc + 1, "invalid signature index"); 189 error(pc, pc + 1, "invalid signature index");
187 return false; 190 return false;
188 } 191 }
189 192
190 inline bool Validate(const byte* pc, BreakDepthOperand& operand, 193 inline bool Validate(const byte* pc, BreakDepthOperand& operand,
191 ZoneVector<Block>& blocks) { 194 ZoneVector<size_t>& blocks,
195 ZoneVector<Control>& control) {
192 if (operand.depth < blocks.size()) { 196 if (operand.depth < blocks.size()) {
193 operand.target = &blocks[blocks.size() - operand.depth - 1]; 197 operand.target = &control[blocks[blocks.size() - operand.depth - 1]];
198 DCHECK(!operand.target->is_if());
194 return true; 199 return true;
195 } 200 }
196 error(pc, pc + 1, "invalid break depth"); 201 error(pc, pc + 1, "invalid break depth");
197 return false; 202 return false;
198 } 203 }
199 204
200 bool Validate(const byte* pc, BranchTableOperand& operand, 205 bool Validate(const byte* pc, BranchTableOperand& operand,
201 size_t block_depth) { 206 size_t block_depth) {
202 // Verify table. 207 // Verify table.
203 for (uint32_t i = 0; i < operand.table_count + 1; i++) { 208 for (uint32_t i = 0; i < operand.table_count + 1; i++) {
(...skipping 18 matching lines...) Expand all
222 switch (static_cast<WasmOpcode>(*pc)) { 227 switch (static_cast<WasmOpcode>(*pc)) {
223 case kExprI8Const: 228 case kExprI8Const:
224 case kExprI32Const: 229 case kExprI32Const:
225 case kExprI64Const: 230 case kExprI64Const:
226 case kExprF64Const: 231 case kExprF64Const:
227 case kExprF32Const: 232 case kExprF32Const:
228 case kExprGetLocal: 233 case kExprGetLocal:
229 case kExprLoadGlobal: 234 case kExprLoadGlobal:
230 case kExprNop: 235 case kExprNop:
231 case kExprUnreachable: 236 case kExprUnreachable:
237 case kExprEnd:
238 case kExprNext:
232 return 0; 239 return 0;
233 240
234 case kExprBr: 241 case kExprBr:
235 case kExprStoreGlobal: 242 case kExprStoreGlobal:
236 case kExprSetLocal: 243 case kExprSetLocal:
244 case kExprElse:
237 return 1; 245 return 1;
238 246
239 case kExprIf: 247 case kExprIf:
240 case kExprBrIf: 248 case kExprBrIf:
241 return 2; 249 return 2;
242 case kExprIfElse:
243 case kExprSelect: 250 case kExprSelect:
244 return 3; 251 return 3;
245 252
246 case kExprBlock: 253 case kExprBlock:
247 case kExprLoop: { 254 case kExprLoop: {
248 BlockCountOperand operand(this, pc); 255 BlockCountOperand operand(this, pc);
249 return operand.count; 256 return operand.count;
250 } 257 }
251 258
252 case kExprCallFunction: { 259 case kExprCallFunction: {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 int OpcodeLength(const byte* pc) { 298 int OpcodeLength(const byte* pc) {
292 switch (static_cast<WasmOpcode>(*pc)) { 299 switch (static_cast<WasmOpcode>(*pc)) {
293 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: 300 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
294 FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE) 301 FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
295 FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE) 302 FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
296 #undef DECLARE_OPCODE_CASE 303 #undef DECLARE_OPCODE_CASE
297 { 304 {
298 MemoryAccessOperand operand(this, pc); 305 MemoryAccessOperand operand(this, pc);
299 return 1 + operand.length; 306 return 1 + operand.length;
300 } 307 }
301 case kExprBlock:
302 case kExprLoop: {
303 BlockCountOperand operand(this, pc);
304 return 1 + operand.length;
305 }
306 case kExprBr: 308 case kExprBr:
307 case kExprBrIf: { 309 case kExprBrIf: {
308 BreakDepthOperand operand(this, pc); 310 BreakDepthOperand operand(this, pc);
309 return 1 + operand.length; 311 return 1 + operand.length;
310 } 312 }
311 case kExprStoreGlobal: 313 case kExprStoreGlobal:
312 case kExprLoadGlobal: { 314 case kExprLoadGlobal: {
313 GlobalIndexOperand operand(this, pc); 315 GlobalIndexOperand operand(this, pc);
314 return 1 + operand.length; 316 return 1 + operand.length;
315 } 317 }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 // A shift-reduce-parser strategy for decoding Wasm code that uses an explicit 363 // A shift-reduce-parser strategy for decoding Wasm code that uses an explicit
362 // shift-reduce strategy with multiple internal stacks. 364 // shift-reduce strategy with multiple internal stacks.
363 class SR_WasmDecoder : public WasmDecoder { 365 class SR_WasmDecoder : public WasmDecoder {
364 public: 366 public:
365 SR_WasmDecoder(Zone* zone, TFBuilder* builder, FunctionBody& body) 367 SR_WasmDecoder(Zone* zone, TFBuilder* builder, FunctionBody& body)
366 : WasmDecoder(body.module, body.sig, body.start, body.end), 368 : WasmDecoder(body.module, body.sig, body.start, body.end),
367 zone_(zone), 369 zone_(zone),
368 builder_(builder), 370 builder_(builder),
369 base_(body.base), 371 base_(body.base),
370 local_type_vec_(zone), 372 local_type_vec_(zone),
371 trees_(zone),
372 stack_(zone), 373 stack_(zone),
373 blocks_(zone), 374 control_(zone),
374 ifs_(zone) { 375 blocks_(zone) {
375 local_types_ = &local_type_vec_; 376 local_types_ = &local_type_vec_;
376 } 377 }
377 378
378 TreeResult Decode() { 379 bool Decode() {
380 base::ElapsedTimer decode_timer;
381 if (FLAG_trace_wasm_decode_time) {
382 decode_timer.Start();
383 }
384 stack_.clear();
385 control_.clear();
386
379 if (end_ < pc_) { 387 if (end_ < pc_) {
380 error(pc_, "function body end < start"); 388 error(pc_, "function body end < start");
381 return result_; 389 return false;
382 } 390 }
383 391
384 DecodeLocalDecls(); 392 DecodeLocalDecls();
385 InitSsaEnv(); 393 InitSsaEnv();
386 DecodeFunctionBody(); 394 DecodeFunctionBody();
387 395
388 Tree* tree = nullptr; 396 if (failed()) return TraceFailed();
389 if (ok()) { 397
390 if (ssa_env_->go()) { 398 if (!control_.empty()) {
391 if (stack_.size() > 0) { 399 error(pc_, control_.back().pc, "unterminated control structure");
392 error(stack_.back().pc(), end_, "fell off end of code"); 400 return TraceFailed();
393 }
394 AddImplicitReturnAtEnd();
395 }
396 if (trees_.size() == 0) {
397 if (sig_->return_count() > 0) {
398 error(start_, "no trees created");
399 }
400 } else {
401 tree = trees_[0];
402 }
403 } 401 }
404 402
405 if (ok()) { 403 if (ssa_env_->go()) {
406 TRACE("wasm-decode ok\n"); 404 TRACE(" @%-6d #xx:%-20s|", startrel(pc_), "ImplicitReturn");
407 } else { 405 DoReturn();
408 TRACE("wasm-error module+%-6d func+%d: %s\n\n", baserel(error_pc_), 406 if (failed()) return TraceFailed();
409 startrel(error_pc_), error_msg_.get()); 407 TRACE("\n");
410 } 408 }
411 409
412 return toResult(tree); 410 if (FLAG_trace_wasm_decode_time) {
411 double ms = decode_timer.Elapsed().InMillisecondsF();
412 PrintF("wasm-decode ok (%0.3f ms)\n\n", ms);
413 } else {
414 TRACE("wasm-decode ok\n\n");
415 }
416
417 return true;
418 }
419
420 bool TraceFailed() {
421 TRACE("wasm-error module+%-6d func+%d: %s\n\n", baserel(error_pc_),
422 startrel(error_pc_), error_msg_.get());
423 return false;
413 } 424 }
414 425
415 std::vector<LocalType>* DecodeLocalDeclsForTesting() { 426 std::vector<LocalType>* DecodeLocalDeclsForTesting() {
416 DecodeLocalDecls(); 427 DecodeLocalDecls();
417 if (failed()) return nullptr; 428 if (failed()) return nullptr;
418 auto result = new std::vector<LocalType>(); 429 auto result = new std::vector<LocalType>();
419 result->reserve(local_type_vec_.size()); 430 result->reserve(local_type_vec_.size());
420 for (size_t i = 0; i < local_type_vec_.size(); i++) { 431 for (size_t i = 0; i < local_type_vec_.size(); i++) {
421 result->push_back(local_type_vec_[i]); 432 result->push_back(local_type_vec_[i]);
422 } 433 }
(...skipping 10 matching lines...) Expand all
433 } 444 }
434 return AnalyzeLoopAssignment(pc); 445 return AnalyzeLoopAssignment(pc);
435 } 446 }
436 447
437 private: 448 private:
438 static const size_t kErrorMsgSize = 128; 449 static const size_t kErrorMsgSize = 128;
439 450
440 Zone* zone_; 451 Zone* zone_;
441 TFBuilder* builder_; 452 TFBuilder* builder_;
442 const byte* base_; 453 const byte* base_;
443 TreeResult result_;
444 454
445 SsaEnv* ssa_env_; 455 SsaEnv* ssa_env_;
446 456
447 ZoneVector<LocalType> local_type_vec_; 457 ZoneVector<LocalType> local_type_vec_;
448 ZoneVector<Tree*> trees_; 458 ZoneVector<Value> stack_;
449 ZoneVector<Production> stack_; 459 ZoneVector<Control> control_;
450 ZoneVector<Block> blocks_; 460 ZoneVector<size_t> blocks_;
451 ZoneVector<IfEnv> ifs_;
452 461
453 inline bool build() { return builder_ && ssa_env_->go(); } 462 inline bool build() { return builder_ && ssa_env_->go(); }
454 463
455 void InitSsaEnv() { 464 void InitSsaEnv() {
456 TFNode* start = nullptr; 465 TFNode* start = nullptr;
457 SsaEnv* ssa_env = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv))); 466 SsaEnv* ssa_env = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
458 size_t size = sizeof(TFNode*) * EnvironmentCount(); 467 size_t size = sizeof(TFNode*) * EnvironmentCount();
459 ssa_env->state = SsaEnv::kReached; 468 ssa_env->state = SsaEnv::kReached;
460 ssa_env->locals = 469 ssa_env->locals =
461 size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr; 470 size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
493 case kAstF32: 502 case kAstF32:
494 return builder_->Float32Constant(0); 503 return builder_->Float32Constant(0);
495 case kAstF64: 504 case kAstF64:
496 return builder_->Float64Constant(0); 505 return builder_->Float64Constant(0);
497 default: 506 default:
498 UNREACHABLE(); 507 UNREACHABLE();
499 return nullptr; 508 return nullptr;
500 } 509 }
501 } 510 }
502 511
503 void Leaf(LocalType type, TFNode* node = nullptr) {
504 size_t size = sizeof(Tree);
505 Tree* tree = reinterpret_cast<Tree*>(zone_->New(size));
506 tree->type = type;
507 tree->count = 0;
508 tree->pc = pc_;
509 tree->node = node;
510 tree->children[0] = nullptr;
511 Reduce(tree);
512 }
513
514 void Shift(LocalType type, uint32_t count) {
515 size_t size =
516 sizeof(Tree) + (count == 0 ? 0 : ((count - 1) * sizeof(Tree*)));
517 Tree* tree = reinterpret_cast<Tree*>(zone_->New(size));
518 tree->type = type;
519 tree->count = count;
520 tree->pc = pc_;
521 tree->node = nullptr;
522 for (uint32_t i = 0; i < count; i++) tree->children[i] = nullptr;
523 if (count == 0) {
524 Production p = {tree, 0};
525 Reduce(&p);
526 Reduce(tree);
527 } else {
528 stack_.push_back({tree, 0});
529 }
530 }
531
532 void Reduce(Tree* tree) {
533 while (true) {
534 if (stack_.size() == 0) {
535 trees_.push_back(tree);
536 break;
537 }
538 Production* p = &stack_.back();
539 p->tree->children[p->index++] = tree;
540 Reduce(p);
541 if (p->done()) {
542 tree = p->tree;
543 stack_.pop_back();
544 } else {
545 break;
546 }
547 }
548 }
549
550 char* indentation() { 512 char* indentation() {
551 static const int kMaxIndent = 64; 513 static const int kMaxIndent = 64;
552 static char bytes[kMaxIndent + 1]; 514 static char bytes[kMaxIndent + 1];
553 for (int i = 0; i < kMaxIndent; i++) bytes[i] = ' '; 515 for (int i = 0; i < kMaxIndent; i++) bytes[i] = ' ';
554 bytes[kMaxIndent] = 0; 516 bytes[kMaxIndent] = 0;
555 if (stack_.size() < kMaxIndent / 2) { 517 if (stack_.size() < kMaxIndent / 2) {
556 bytes[stack_.size() * 2] = 0; 518 bytes[stack_.size() * 2] = 0;
557 } 519 }
558 return bytes; 520 return bytes;
559 } 521 }
(...skipping 30 matching lines...) Expand all
590 break; 552 break;
591 default: 553 default:
592 error(pc_ - 1, "invalid local type"); 554 error(pc_ - 1, "invalid local type");
593 return; 555 return;
594 } 556 }
595 local_type_vec_.insert(local_type_vec_.end(), count, type); 557 local_type_vec_.insert(local_type_vec_.end(), count, type);
596 } 558 }
597 total_locals_ = local_type_vec_.size(); 559 total_locals_ = local_type_vec_.size();
598 } 560 }
599 561
600 // Decodes the body of a function, producing reduced trees into {result}. 562 // Decodes the body of a function.
601 void DecodeFunctionBody() { 563 void DecodeFunctionBody() {
602 TRACE("wasm-decode %p...%p (%d bytes) %s\n", 564 TRACE("wasm-decode %p...%p (module+%d, %d bytes) %s\n",
603 reinterpret_cast<const void*>(start_), 565 reinterpret_cast<const void*>(start_),
604 reinterpret_cast<const void*>(limit_), 566 reinterpret_cast<const void*>(limit_), baserel(pc_),
605 static_cast<int>(limit_ - start_), builder_ ? "graph building" : ""); 567 static_cast<int>(limit_ - start_), builder_ ? "graph building" : "");
606 568
607 if (pc_ >= limit_) return; // Nothing to do. 569 if (pc_ >= limit_) return; // Nothing to do.
608 570
609 while (true) { // decoding loop. 571 while (true) { // decoding loop.
610 int len = 1; 572 int len = 1;
611 WasmOpcode opcode = static_cast<WasmOpcode>(*pc_); 573 WasmOpcode opcode = static_cast<WasmOpcode>(*pc_);
612 TRACE("wasm-decode module+%-6d %s func+%d: 0x%02x %s\n", baserel(pc_), 574 TRACE(" @%-6d #%02x:%-20s|", startrel(pc_), opcode,
613 indentation(), startrel(pc_), opcode, 575 WasmOpcodes::ShortOpcodeName(opcode));
614 WasmOpcodes::OpcodeName(opcode));
615 576
616 FunctionSig* sig = WasmOpcodes::Signature(opcode); 577 FunctionSig* sig = WasmOpcodes::Signature(opcode);
617 if (sig) { 578 if (sig) {
618 // A simple expression with a fixed signature. 579 // Fast case of a simple operator.
619 Shift(sig->GetReturn(), static_cast<uint32_t>(sig->parameter_count())); 580 TFNode* node;
620 pc_ += len; 581 switch (sig->parameter_count()) {
621 if (pc_ >= limit_) { 582 case 1: {
622 // End of code reached or exceeded. 583 Value val = Pop(0, sig->GetParam(0));
623 if (pc_ > limit_ && ok()) { 584 node = BUILD(Unop, opcode, val.node);
624 error("Beyond end of code"); 585 break;
625 } 586 }
626 return; 587 case 2: {
588 Value rval = Pop(1, sig->GetParam(1));
589 Value lval = Pop(0, sig->GetParam(0));
590 node = BUILD(Binop, opcode, lval.node, rval.node);
591 break;
592 }
593 default:
594 UNREACHABLE();
595 node = nullptr;
596 break;
627 } 597 }
628 continue; // back to decoding loop. 598 Push(GetReturnType(sig), node);
629 } 599 } else {
630 600 // Complex bytecode.
631 switch (opcode) { 601 switch (opcode) {
632 case kExprNop: 602 case kExprNop:
633 Leaf(kAstStmt); 603 Push(kAstStmt, nullptr);
634 break; 604 break;
635 case kExprBlock: { 605 case kExprBlock: {
636 BlockCountOperand operand(this, pc_);
637 if (operand.count < 1) {
638 Leaf(kAstStmt);
639 } else {
640 Shift(kAstEnd, operand.count);
641 // The break environment is the outer environment. 606 // The break environment is the outer environment.
642 SsaEnv* break_env = ssa_env_; 607 SsaEnv* break_env = ssa_env_;
643 PushBlock(break_env); 608 PushBlock(break_env);
644 SetEnv("block:start", Steal(break_env)); 609 SetEnv("block:start", Steal(break_env));
610 break;
645 } 611 }
646 len = 1 + operand.length; 612 case kExprLoop: {
647 break;
648 }
649 case kExprLoop: {
650 BlockCountOperand operand(this, pc_);
651 if (operand.count < 1) {
652 Leaf(kAstStmt);
653 } else {
654 Shift(kAstEnd, operand.count);
655 // The break environment is the outer environment. 613 // The break environment is the outer environment.
656 SsaEnv* break_env = ssa_env_; 614 SsaEnv* break_env = ssa_env_;
657 PushBlock(break_env); 615 PushBlock(break_env);
658 SsaEnv* cont_env = Steal(break_env); 616 SsaEnv* cont_env = Steal(break_env);
659 // The continue environment is the inner environment. 617 // The continue environment is the inner environment.
660 PrepareForLoop(pc_, cont_env); 618 PrepareForLoop(pc_, cont_env);
661 SetEnv("loop:start", Split(cont_env)); 619 SetEnv("loop:start", Split(cont_env));
662 if (ssa_env_->go()) ssa_env_->state = SsaEnv::kReached; 620 ssa_env_->SetNotMerged();
663 PushBlock(cont_env); 621 PushBlock(cont_env, true);
664 blocks_.back().stack_depth = -1; // no production for inner block. 622 break;
665 } 623 }
666 len = 1 + operand.length; 624 case kExprIf: {
667 break; 625 // Condition on top of stack. Split environment for true branch.
626 Value cond = Pop(0, kAstI32);
627 SsaEnv* false_env = ssa_env_;
628 SsaEnv* true_env = Split(ssa_env_);
629 false_env->SetNotMerged();
630 PushIf(false_env);
631 BUILD(Branch, cond.node, &true_env->control, &false_env->control);
632 SetEnv("if:true", true_env);
633 break;
634 }
635 case kExprElse: {
636 if (control_.empty()) {
637 error(pc_, "else does not match any if");
638 break;
639 }
640 Control* c = &control_.back();
641 if (!c->is_if()) {
642 error(pc_, c->pc, "else does not match an if");
643 break;
644 }
645 if (++c->counter > 1) {
646 error(pc_, c->pc, "else already present for if");
647 break;
648 }
649 Value val = PopUpTo(c->stack_depth);
650 // The {ssa_env} stores the false env for an if.
651 SsaEnv* false_env = Steal(c->ssa_env);
652 MergeInto(c->ssa_env, &c->node, &c->type, val);
653 // Switch to environment for false branch.
654 SetEnv("if_else:false", false_env);
655 break;
656 }
657 case kExprEnd: {
658 if (control_.empty()) {
659 error(pc_, "end does not match any if or block");
660 break;
661 }
662 const char* name = "block:end";
663 Control* c = &control_.back();
664 if (c->is_loop()) {
665 // Loops always push control in pairs.
666 control_.pop_back();
667 c = &control_.back();
668 name = "loop:end";
669 }
670 Value val = PopUpTo(c->stack_depth);
671 if (c->is_if()) {
672 if (c->counter == 0) {
673 // End of a one-armed if.
674 val = {val.pc, nullptr, kAstStmt};
675 name = "if:merge";
676 } else {
677 // End of a two-armed if.
678 name = "if_else:merge";
679 }
680 }
681 if (ssa_env_->go()) {
682 MergeInto(c->ssa_env, &c->node, &c->type, val);
683 }
684 SetEnv(name, c->ssa_env);
685 stack_.resize(c->stack_depth);
686 blocks_.resize(c->block_depth);
687 Push(c->type, c->node);
688 control_.pop_back();
689 break;
690 }
691 case kExprSelect: {
692 Value cond = Pop(2, kAstI32);
693 Value fval = Pop();
694 Value tval = Pop();
695 if (tval.type == kAstStmt || tval.type != fval.type) {
696 if (tval.type != kAstEnd && fval.type != kAstEnd) {
697 error(pc_, "type mismatch in select");
698 break;
699 }
700 }
701 if (build()) {
702 DCHECK(tval.type != kAstEnd);
703 DCHECK(fval.type != kAstEnd);
704 DCHECK(cond.type != kAstEnd);
705 TFNode* controls[2];
706 builder_->Branch(cond.node, &controls[0], &controls[1]);
707 TFNode* merge = builder_->Merge(2, controls);
708 TFNode* vals[2] = {tval.node, fval.node};
709 TFNode* phi = builder_->Phi(tval.type, 2, vals, merge);
710 Push(tval.type, phi);
711 ssa_env_->control = merge;
712 } else {
713 Push(tval.type, nullptr);
714 }
715 break;
716 }
717 case kExprBr: {
718 Value val = Pop();
719 BreakDepthOperand operand(this, pc_);
720 if (Validate(pc_, operand, blocks_, control_)) {
721 BreakTo(operand.target, val);
722 }
723 len = 1 + operand.length;
724 Push(kAstEnd, nullptr);
725 break;
726 }
727 case kExprBrIf: {
728 Value cond = Pop(1, kAstI32);
729 Value val = Pop();
730 BreakDepthOperand operand(this, pc_);
731 if (Validate(pc_, operand, blocks_, control_)) {
732 SsaEnv* fenv = ssa_env_;
733 SsaEnv* tenv = Split(fenv);
734 fenv->SetNotMerged();
735 BUILD(Branch, cond.node, &tenv->control, &fenv->control);
736 ssa_env_ = tenv;
737 BreakTo(operand.target, val);
738 ssa_env_ = fenv;
739 }
740 len = 1 + operand.length;
741 Push(kAstStmt, nullptr);
742 break;
743 }
744 case kExprBrTable: {
745 BranchTableOperand operand(this, pc_);
746 if (Validate(pc_, operand, blocks_.size())) {
747 Value key = Pop(0, kAstI32);
748 if (failed()) break;
749
750 Value voidval = {pc_, nullptr, kAstStmt};
751 SsaEnv* break_env = ssa_env_;
752 if (operand.table_count > 0) {
753 // Build branches to the various blocks based on the table.
754 TFNode* sw = BUILD(Switch, operand.table_count + 1, key.node);
755
756 SsaEnv* copy = Steal(break_env);
757 ssa_env_ = copy;
758 for (uint32_t i = 0; i < operand.table_count + 1; i++) {
759 uint16_t target = operand.read_entry(this, i);
760 ssa_env_ = Split(copy);
761 ssa_env_->control = (i == operand.table_count)
762 ? BUILD(IfDefault, sw)
763 : BUILD(IfValue, i, sw);
764 int depth = target;
765 size_t block_index = blocks_[blocks_.size() - depth - 1];
766 Control* c = &control_[block_index];
767 MergeInto(c->ssa_env, &c->node, &c->type, voidval);
768 }
769 } else {
770 // Only a default target. Do the equivalent of br.
771 uint16_t target = operand.read_entry(this, 0);
772 int depth = target;
773 size_t block_index = blocks_[blocks_.size() - depth - 1];
774 Control* c = &control_[block_index];
775 MergeInto(c->ssa_env, &c->node, &c->type, voidval);
776 }
777 // br_table ends the control flow like br.
778 ssa_env_ = break_env;
779 Push(kAstStmt, nullptr);
780 }
781 len = 1 + operand.length;
782 break;
783 }
784 case kExprReturn: {
785 DoReturn();
786 break;
787 }
788 case kExprUnreachable: {
789 Push(kAstEnd, BUILD0(Unreachable));
790 ssa_env_->Kill(SsaEnv::kControlEnd);
791 break;
792 }
793 case kExprI8Const: {
794 ImmI8Operand operand(this, pc_);
795 Push(kAstI32, BUILD(Int32Constant, operand.value));
796 len = 1 + operand.length;
797 break;
798 }
799 case kExprI32Const: {
800 ImmI32Operand operand(this, pc_);
801 Push(kAstI32, BUILD(Int32Constant, operand.value));
802 len = 1 + operand.length;
803 break;
804 }
805 case kExprI64Const: {
806 ImmI64Operand operand(this, pc_);
807 Push(kAstI64, BUILD(Int64Constant, operand.value));
808 len = 1 + operand.length;
809 break;
810 }
811 case kExprF32Const: {
812 ImmF32Operand operand(this, pc_);
813 Push(kAstF32, BUILD(Float32Constant, operand.value));
814 len = 1 + operand.length;
815 break;
816 }
817 case kExprF64Const: {
818 ImmF64Operand operand(this, pc_);
819 Push(kAstF64, BUILD(Float64Constant, operand.value));
820 len = 1 + operand.length;
821 break;
822 }
823 case kExprGetLocal: {
824 LocalIndexOperand operand(this, pc_);
825 if (Validate(pc_, operand)) {
826 if (build()) {
827 Push(operand.type, ssa_env_->locals[operand.index]);
828 } else {
829 Push(operand.type, nullptr);
830 }
831 }
832 len = 1 + operand.length;
833 break;
834 }
835 case kExprSetLocal: {
836 LocalIndexOperand operand(this, pc_);
837 if (Validate(pc_, operand)) {
838 Value val = Pop(0, local_type_vec_[operand.index]);
839 if (ssa_env_->locals) ssa_env_->locals[operand.index] = val.node;
840 Push(val.type, val.node);
841 }
842 len = 1 + operand.length;
843 break;
844 }
845 case kExprLoadGlobal: {
846 GlobalIndexOperand operand(this, pc_);
847 if (Validate(pc_, operand)) {
848 Push(operand.type, BUILD(LoadGlobal, operand.index));
849 }
850 len = 1 + operand.length;
851 break;
852 }
853 case kExprStoreGlobal: {
854 GlobalIndexOperand operand(this, pc_);
855 if (Validate(pc_, operand)) {
856 Value val = Pop(0, operand.type);
857 BUILD(StoreGlobal, operand.index, val.node);
858 Push(val.type, val.node);
859 }
860 len = 1 + operand.length;
861 break;
862 }
863 case kExprI32LoadMem8S:
864 len = DecodeLoadMem(kAstI32, MachineType::Int8());
865 break;
866 case kExprI32LoadMem8U:
867 len = DecodeLoadMem(kAstI32, MachineType::Uint8());
868 break;
869 case kExprI32LoadMem16S:
870 len = DecodeLoadMem(kAstI32, MachineType::Int16());
871 break;
872 case kExprI32LoadMem16U:
873 len = DecodeLoadMem(kAstI32, MachineType::Uint16());
874 break;
875 case kExprI32LoadMem:
876 len = DecodeLoadMem(kAstI32, MachineType::Int32());
877 break;
878
879 case kExprI64LoadMem8S:
880 len = DecodeLoadMem(kAstI64, MachineType::Int8());
881 break;
882 case kExprI64LoadMem8U:
883 len = DecodeLoadMem(kAstI64, MachineType::Uint8());
884 break;
885 case kExprI64LoadMem16S:
886 len = DecodeLoadMem(kAstI64, MachineType::Int16());
887 break;
888 case kExprI64LoadMem16U:
889 len = DecodeLoadMem(kAstI64, MachineType::Uint16());
890 break;
891 case kExprI64LoadMem32S:
892 len = DecodeLoadMem(kAstI64, MachineType::Int32());
893 break;
894 case kExprI64LoadMem32U:
895 len = DecodeLoadMem(kAstI64, MachineType::Uint32());
896 break;
897 case kExprI64LoadMem:
898 len = DecodeLoadMem(kAstI64, MachineType::Int64());
899 break;
900 case kExprF32LoadMem:
901 len = DecodeLoadMem(kAstF32, MachineType::Float32());
902 break;
903 case kExprF64LoadMem:
904 len = DecodeLoadMem(kAstF64, MachineType::Float64());
905 break;
906 case kExprI32StoreMem8:
907 len = DecodeStoreMem(kAstI32, MachineType::Int8());
908 break;
909 case kExprI32StoreMem16:
910 len = DecodeStoreMem(kAstI32, MachineType::Int16());
911 break;
912 case kExprI32StoreMem:
913 len = DecodeStoreMem(kAstI32, MachineType::Int32());
914 break;
915 case kExprI64StoreMem8:
916 len = DecodeStoreMem(kAstI64, MachineType::Int8());
917 break;
918 case kExprI64StoreMem16:
919 len = DecodeStoreMem(kAstI64, MachineType::Int16());
920 break;
921 case kExprI64StoreMem32:
922 len = DecodeStoreMem(kAstI64, MachineType::Int32());
923 break;
924 case kExprI64StoreMem:
925 len = DecodeStoreMem(kAstI64, MachineType::Int64());
926 break;
927 case kExprF32StoreMem:
928 len = DecodeStoreMem(kAstF32, MachineType::Float32());
929 break;
930 case kExprF64StoreMem:
931 len = DecodeStoreMem(kAstF64, MachineType::Float64());
932 break;
933
934 case kExprMemorySize:
935 Push(kAstI32, BUILD(MemSize, 0));
936 break;
937 case kExprGrowMemory: {
938 Value val = Pop(0, kAstI32);
939 USE(val); // TODO(titzer): build node for grow memory
940 Push(kAstI32, BUILD(Int32Constant, 0));
941 break;
942 }
943 case kExprCallFunction: {
944 FunctionIndexOperand operand(this, pc_);
945 if (Validate(pc_, operand)) {
946 TFNode** buffer = PopArgs(operand.sig);
947 Push(GetReturnType(operand.sig),
948 BUILD(CallDirect, operand.index, buffer));
949 }
950 len = 1 + operand.length;
951 break;
952 }
953 case kExprCallIndirect: {
954 SignatureIndexOperand operand(this, pc_);
955 if (Validate(pc_, operand)) {
956 TFNode** buffer = PopArgs(operand.sig);
957 Value index = Pop(0, kAstI32);
958 if (buffer) buffer[0] = index.node;
959 Push(GetReturnType(operand.sig),
960 BUILD(CallIndirect, operand.index, buffer));
961 }
962 len = 1 + operand.length;
963 break;
964 }
965 case kExprCallImport: {
966 ImportIndexOperand operand(this, pc_);
967 if (Validate(pc_, operand)) {
968 TFNode** buffer = PopArgs(operand.sig);
969 Push(GetReturnType(operand.sig),
970 BUILD(CallImport, operand.index, buffer));
971 }
972 len = 1 + operand.length;
973 break;
974 }
975 default:
976 error("Invalid opcode");
977 return;
668 } 978 }
669 case kExprIf: 979 } // end complex bytecode
670 Shift(kAstStmt, 2); 980
671 break; 981 #if DEBUG
672 case kExprIfElse: 982 if (FLAG_trace_wasm_decoder) {
673 Shift(kAstEnd, 3); // Result type is typeof(x) in {c ? x : y}. 983 for (size_t i = 0; i < stack_.size(); i++) {
674 break; 984 Value& val = stack_[i];
675 case kExprSelect: 985 PrintF(
676 Shift(kAstStmt, 3); // Result type is typeof(x) in {c ? x : y}. 986 " %c@%d:%s", WasmOpcodes::ShortNameOf(val.type),
677 break; 987 static_cast<int>(val.pc - start_),
678 case kExprBr: { 988 WasmOpcodes::ShortOpcodeName(static_cast<WasmOpcode>(*val.pc)));
679 BreakDepthOperand operand(this, pc_);
680 if (Validate(pc_, operand, blocks_)) {
681 Shift(kAstEnd, 1);
682 }
683 len = 1 + operand.length;
684 break;
685 } 989 }
686 case kExprBrIf: { 990 PrintF("\n");
687 BreakDepthOperand operand(this, pc_); 991 }
688 if (Validate(pc_, operand, blocks_)) { 992 #endif
689 Shift(kAstStmt, 2);
690 }
691 len = 1 + operand.length;
692 break;
693 }
694 case kExprBrTable: {
695 BranchTableOperand operand(this, pc_);
696 if (Validate(pc_, operand, blocks_.size())) {
697 Shift(kAstEnd, 1);
698 }
699 len = 1 + operand.length;
700 break;
701 }
702 case kExprReturn: {
703 int count = static_cast<int>(sig_->return_count());
704 if (count == 0) {
705 BUILD(Return, 0, builder_->Buffer(0));
706 ssa_env_->Kill();
707 Leaf(kAstEnd);
708 } else {
709 Shift(kAstEnd, count);
710 }
711 break;
712 }
713 case kExprUnreachable: {
714 BUILD0(Unreachable);
715 ssa_env_->Kill(SsaEnv::kControlEnd);
716 Leaf(kAstEnd, nullptr);
717 break;
718 }
719 case kExprI8Const: {
720 ImmI8Operand operand(this, pc_);
721 Leaf(kAstI32, BUILD(Int32Constant, operand.value));
722 len = 1 + operand.length;
723 break;
724 }
725 case kExprI32Const: {
726 ImmI32Operand operand(this, pc_);
727 Leaf(kAstI32, BUILD(Int32Constant, operand.value));
728 len = 1 + operand.length;
729 break;
730 }
731 case kExprI64Const: {
732 ImmI64Operand operand(this, pc_);
733 Leaf(kAstI64, BUILD(Int64Constant, operand.value));
734 len = 1 + operand.length;
735 break;
736 }
737 case kExprF32Const: {
738 ImmF32Operand operand(this, pc_);
739 Leaf(kAstF32, BUILD(Float32Constant, operand.value));
740 len = 1 + operand.length;
741 break;
742 }
743 case kExprF64Const: {
744 ImmF64Operand operand(this, pc_);
745 Leaf(kAstF64, BUILD(Float64Constant, operand.value));
746 len = 1 + operand.length;
747 break;
748 }
749 case kExprGetLocal: {
750 LocalIndexOperand operand(this, pc_);
751 if (Validate(pc_, operand)) {
752 TFNode* val = build() ? ssa_env_->locals[operand.index] : nullptr;
753 Leaf(operand.type, val);
754 }
755 len = 1 + operand.length;
756 break;
757 }
758 case kExprSetLocal: {
759 LocalIndexOperand operand(this, pc_);
760 if (Validate(pc_, operand)) {
761 Shift(operand.type, 1);
762 }
763 len = 1 + operand.length;
764 break;
765 }
766 case kExprLoadGlobal: {
767 GlobalIndexOperand operand(this, pc_);
768 if (Validate(pc_, operand)) {
769 Leaf(operand.type, BUILD(LoadGlobal, operand.index));
770 }
771 len = 1 + operand.length;
772 break;
773 }
774 case kExprStoreGlobal: {
775 GlobalIndexOperand operand(this, pc_);
776 if (Validate(pc_, operand)) {
777 Shift(operand.type, 1);
778 }
779 len = 1 + operand.length;
780 break;
781 }
782 case kExprI32LoadMem8S:
783 case kExprI32LoadMem8U:
784 case kExprI32LoadMem16S:
785 case kExprI32LoadMem16U:
786 case kExprI32LoadMem:
787 len = DecodeLoadMem(pc_, kAstI32);
788 break;
789 case kExprI64LoadMem8S:
790 case kExprI64LoadMem8U:
791 case kExprI64LoadMem16S:
792 case kExprI64LoadMem16U:
793 case kExprI64LoadMem32S:
794 case kExprI64LoadMem32U:
795 case kExprI64LoadMem:
796 len = DecodeLoadMem(pc_, kAstI64);
797 break;
798 case kExprF32LoadMem:
799 len = DecodeLoadMem(pc_, kAstF32);
800 break;
801 case kExprF64LoadMem:
802 len = DecodeLoadMem(pc_, kAstF64);
803 break;
804 case kExprI32StoreMem8:
805 case kExprI32StoreMem16:
806 case kExprI32StoreMem:
807 len = DecodeStoreMem(pc_, kAstI32);
808 break;
809 case kExprI64StoreMem8:
810 case kExprI64StoreMem16:
811 case kExprI64StoreMem32:
812 case kExprI64StoreMem:
813 len = DecodeStoreMem(pc_, kAstI64);
814 break;
815 case kExprF32StoreMem:
816 len = DecodeStoreMem(pc_, kAstF32);
817 break;
818 case kExprF64StoreMem:
819 len = DecodeStoreMem(pc_, kAstF64);
820 break;
821 case kExprMemorySize:
822 Leaf(kAstI32, BUILD(MemSize, 0));
823 break;
824 case kExprGrowMemory:
825 Shift(kAstI32, 1);
826 break;
827 case kExprCallFunction: {
828 FunctionIndexOperand operand(this, pc_);
829 if (Validate(pc_, operand)) {
830 LocalType type = operand.sig->return_count() == 0
831 ? kAstStmt
832 : operand.sig->GetReturn();
833 Shift(type, static_cast<int>(operand.sig->parameter_count()));
834 }
835 len = 1 + operand.length;
836 break;
837 }
838 case kExprCallIndirect: {
839 SignatureIndexOperand operand(this, pc_);
840 if (Validate(pc_, operand)) {
841 LocalType type = operand.sig->return_count() == 0
842 ? kAstStmt
843 : operand.sig->GetReturn();
844 Shift(type, static_cast<int>(1 + operand.sig->parameter_count()));
845 }
846 len = 1 + operand.length;
847 break;
848 }
849 case kExprCallImport: {
850 ImportIndexOperand operand(this, pc_);
851 if (Validate(pc_, operand)) {
852 LocalType type = operand.sig->return_count() == 0
853 ? kAstStmt
854 : operand.sig->GetReturn();
855 Shift(type, static_cast<int>(operand.sig->parameter_count()));
856 }
857 len = 1 + operand.length;
858 break;
859 }
860 case kExprDeclLocals:
861 default:
862 error("Invalid opcode");
863 return;
864 }
865 pc_ += len; 993 pc_ += len;
866 if (pc_ >= limit_) { 994 if (pc_ >= limit_) {
867 // End of code reached or exceeded. 995 // End of code reached or exceeded.
868 if (pc_ > limit_ && ok()) { 996 if (pc_ > limit_ && ok()) error("Beyond end of code");
869 error("Beyond end of code");
870 }
871 return; 997 return;
872 } 998 }
873 } 999 } // end decode loop
874 } 1000 } // end DecodeFunctionBody()
875 1001
876 void PushBlock(SsaEnv* ssa_env) { 1002 TFNode** PopArgs(FunctionSig* sig) {
877 blocks_.push_back({ssa_env, static_cast<int>(stack_.size() - 1)}); 1003 if (build()) {
878 } 1004 int count = static_cast<int>(sig->parameter_count());
879 1005 TFNode** buffer = builder_->Buffer(count + 1);
880 int DecodeLoadMem(const byte* pc, LocalType type) { 1006 buffer[0] = nullptr; // reserved for code object or function index.
881 MemoryAccessOperand operand(this, pc); 1007 for (int i = count - 1; i >= 0; i--) {
882 Shift(type, 1); 1008 buffer[i + 1] = Pop(i, sig->GetParam(i)).node;
1009 }
1010 return buffer;
1011 } else {
1012 int count = static_cast<int>(sig->parameter_count());
1013 for (int i = count - 1; i >= 0; i--) {
1014 Pop(i, sig->GetParam(i));
1015 }
1016 return nullptr;
1017 }
1018 }
1019
1020 LocalType GetReturnType(FunctionSig* sig) {
1021 return sig->return_count() == 0 ? kAstStmt : sig->GetReturn();
1022 }
1023
1024 void PushBlock(SsaEnv* merge_env, bool loop = false) {
1025 int stack_depth = loop ? -1 : static_cast<int>(stack_.size());
1026 int block_depth = static_cast<int>(blocks_.size());
1027 control_.push_back(
1028 {pc_, stack_depth, block_depth, merge_env, nullptr, kAstEnd, 0, 0});
1029 blocks_.push_back(control_.size() - 1);
1030 }
1031
1032 void PushIf(SsaEnv* merge_env) {
1033 int stack_depth = static_cast<int>(stack_.size());
1034 int block_depth = static_cast<int>(blocks_.size());
1035 control_.push_back(
1036 {pc_, stack_depth, block_depth, merge_env, nullptr, kAstStmt, 0, 0});
1037 }
1038
1039 int DecodeLoadMem(LocalType type, MachineType mem_type) {
1040 MemoryAccessOperand operand(this, pc_);
1041 Value index = Pop(0, kAstI32);
1042 TFNode* node = BUILD(LoadMem, type, mem_type, index.node, operand.offset);
1043 Push(type, node);
883 return 1 + operand.length; 1044 return 1 + operand.length;
884 } 1045 }
885 1046
886 int DecodeStoreMem(const byte* pc, LocalType type) { 1047 int DecodeStoreMem(LocalType type, MachineType mem_type) {
887 MemoryAccessOperand operand(this, pc); 1048 MemoryAccessOperand operand(this, pc_);
888 Shift(type, 2); 1049 Value val = Pop(1, type);
1050 Value index = Pop(0, kAstI32);
1051 BUILD(StoreMem, mem_type, index.node, operand.offset, val.node);
1052 Push(type, val.node);
889 return 1 + operand.length; 1053 return 1 + operand.length;
890 } 1054 }
891 1055
892 void AddImplicitReturnAtEnd() { 1056 void DoReturn() {
893 int retcount = static_cast<int>(sig_->return_count()); 1057 int count = static_cast<int>(sig_->return_count());
894 if (retcount == 0) { 1058 TFNode** buffer = nullptr;
895 BUILD0(ReturnVoid); 1059 if (build()) buffer = builder_->Buffer(count);
896 return; 1060
897 } 1061 // Pop return values off the stack in reverse order.
898 1062 for (int i = count - 1; i >= 0; i--) {
899 if (static_cast<int>(trees_.size()) < retcount) { 1063 Value val = Pop(i, sig_->GetReturn(i));
900 error(limit_, nullptr, 1064 if (buffer) buffer[i] = val.node;
901 "ImplicitReturn expects %d arguments, only %d remain", retcount, 1065 }
902 static_cast<int>(trees_.size())); 1066
903 return; 1067 Push(kAstEnd, BUILD(Return, count, buffer));
904 } 1068 ssa_env_->Kill(SsaEnv::kControlEnd);
905 1069 }
906 TRACE("wasm-decode implicit return of %d args\n", retcount); 1070
907 1071 void Push(LocalType type, TFNode* node) {
908 TFNode** buffer = BUILD(Buffer, retcount); 1072 stack_.push_back({pc_, node, type});
909 for (int index = 0; index < retcount; index++) { 1073 }
910 Tree* tree = trees_[trees_.size() - 1 - index]; 1074
911 if (buffer) buffer[index] = tree->node; 1075 Value Pop(int index, LocalType expected) {
912 LocalType expected = sig_->GetReturn(index); 1076 Value val = Pop();
913 if (tree->type != expected) { 1077 if (val.type != expected) {
914 error(limit_, tree->pc, 1078 if (val.type != kAstEnd) {
915 "ImplicitReturn[%d] expected type %s, found %s of type %s", index, 1079 error(pc_, val.pc, "%s[%d] expected type %s, found %s of type %s",
916 WasmOpcodes::TypeName(expected), 1080 WasmOpcodes::ShortOpcodeName(static_cast<WasmOpcode>(*pc_)),
917 WasmOpcodes::OpcodeName(tree->opcode()), 1081 index, WasmOpcodes::TypeName(expected),
918 WasmOpcodes::TypeName(tree->type)); 1082 WasmOpcodes::ShortOpcodeName(static_cast<WasmOpcode>(*val.pc)),
919 return; 1083 WasmOpcodes::TypeName(val.type));
920 } 1084 }
921 } 1085 }
922 1086 return val;
923 BUILD(Return, retcount, buffer); 1087 }
1088
1089 Value Pop() {
1090 if (stack_.empty()) {
1091 Value val = {pc_, nullptr, kAstStmt};
1092 error(pc_, pc_, "%s found empty stack",
1093 WasmOpcodes::ShortOpcodeName(static_cast<WasmOpcode>(*pc_)));
1094 return val;
1095 }
1096 Value val = stack_.back();
1097 stack_.pop_back();
1098 return val;
1099 }
1100
1101 Value PopUpTo(int stack_depth) {
1102 if (stack_depth == stack_.size()) {
1103 Value val = {pc_, nullptr, kAstStmt};
1104 return val;
1105 } else {
1106 DCHECK_LE(stack_depth, static_cast<int>(stack_.size()));
1107 Value val = Pop();
1108 stack_.resize(stack_depth);
1109 return val;
1110 }
924 } 1111 }
925 1112
926 int baserel(const byte* ptr) { 1113 int baserel(const byte* ptr) {
927 return base_ ? static_cast<int>(ptr - base_) : 0; 1114 return base_ ? static_cast<int>(ptr - base_) : 0;
928 } 1115 }
929 1116
930 int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); } 1117 int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); }
931 1118
932 void Reduce(Production* p) { 1119 void BreakTo(Control* block, Value& val) {
933 WasmOpcode opcode = p->opcode(); 1120 DCHECK(!block->is_if());
934 TRACE("-----reduce module+%-6d %s func+%d: 0x%02x %s\n", baserel(p->pc()), 1121 if (block->is_loop()) {
935 indentation(), startrel(p->pc()), opcode,
936 WasmOpcodes::OpcodeName(opcode));
937 FunctionSig* sig = WasmOpcodes::Signature(opcode);
938 if (sig) {
939 // A simple expression with a fixed signature.
940 TypeCheckLast(p, sig->GetParam(p->index - 1));
941 if (p->done() && build()) {
942 if (sig->parameter_count() == 2) {
943 p->tree->node = builder_->Binop(opcode, p->tree->children[0]->node,
944 p->tree->children[1]->node);
945 } else if (sig->parameter_count() == 1) {
946 p->tree->node = builder_->Unop(opcode, p->tree->children[0]->node);
947 } else {
948 UNREACHABLE();
949 }
950 }
951 return;
952 }
953
954 switch (opcode) {
955 case kExprBlock: {
956 if (p->done()) {
957 Block* last = &blocks_.back();
958 DCHECK_EQ(stack_.size() - 1, last->stack_depth);
959 // fallthrough with the last expression.
960 ReduceBreakToExprBlock(p, last);
961 SetEnv("block:end", last->ssa_env);
962 blocks_.pop_back();
963 }
964 break;
965 }
966 case kExprLoop: {
967 if (p->done()) {
968 // Pop the continue environment.
969 blocks_.pop_back();
970 // Get the break environment.
971 Block* last = &blocks_.back();
972 DCHECK_EQ(stack_.size() - 1, last->stack_depth);
973 // fallthrough with the last expression.
974 ReduceBreakToExprBlock(p, last);
975 SetEnv("loop:end", last->ssa_env);
976 blocks_.pop_back();
977 }
978 break;
979 }
980 case kExprIf: {
981 if (p->index == 1) {
982 // Condition done. Split environment for true branch.
983 TypeCheckLast(p, kAstI32);
984 SsaEnv* false_env = ssa_env_;
985 SsaEnv* true_env = Split(ssa_env_);
986 ifs_.push_back({nullptr, false_env, nullptr});
987 BUILD(Branch, p->last()->node, &true_env->control,
988 &false_env->control);
989 SetEnv("if:true", true_env);
990 } else if (p->index == 2) {
991 // True block done. Merge true and false environments.
992 IfEnv* env = &ifs_.back();
993 SsaEnv* merge = env->merge_env;
994 if (merge->go()) {
995 merge->state = SsaEnv::kReached;
996 Goto(ssa_env_, merge);
997 }
998 SetEnv("if:merge", merge);
999 ifs_.pop_back();
1000 }
1001 break;
1002 }
1003 case kExprIfElse: {
1004 if (p->index == 1) {
1005 // Condition done. Split environment for true and false branches.
1006 TypeCheckLast(p, kAstI32);
1007 SsaEnv* merge_env = ssa_env_;
1008 TFNode* if_true = nullptr;
1009 TFNode* if_false = nullptr;
1010 BUILD(Branch, p->last()->node, &if_true, &if_false);
1011 SsaEnv* false_env = Split(ssa_env_);
1012 SsaEnv* true_env = Steal(ssa_env_);
1013 false_env->control = if_false;
1014 true_env->control = if_true;
1015 ifs_.push_back({false_env, merge_env, nullptr});
1016 SetEnv("if_else:true", true_env);
1017 } else if (p->index == 2) {
1018 // True expr done.
1019 IfEnv* env = &ifs_.back();
1020 MergeIntoProduction(p, env->merge_env, p->last());
1021 // Switch to environment for false branch.
1022 SsaEnv* false_env = ifs_.back().false_env;
1023 SetEnv("if_else:false", false_env);
1024 } else if (p->index == 3) {
1025 // False expr done.
1026 IfEnv* env = &ifs_.back();
1027 MergeIntoProduction(p, env->merge_env, p->last());
1028 SetEnv("if_else:merge", env->merge_env);
1029 ifs_.pop_back();
1030 }
1031 break;
1032 }
1033 case kExprSelect: {
1034 if (p->index == 1) {
1035 // True expression done.
1036 p->tree->type = p->last()->type;
1037 if (p->tree->type == kAstStmt) {
1038 error(p->pc(), p->tree->children[1]->pc,
1039 "select operand should be expression");
1040 }
1041 } else if (p->index == 2) {
1042 // False expression done.
1043 TypeCheckLast(p, p->tree->type);
1044 } else {
1045 // Condition done.
1046 DCHECK(p->done());
1047 TypeCheckLast(p, kAstI32);
1048 if (build()) {
1049 TFNode* controls[2];
1050 builder_->Branch(p->tree->children[2]->node, &controls[0],
1051 &controls[1]);
1052 TFNode* merge = builder_->Merge(2, controls);
1053 TFNode* vals[2] = {p->tree->children[0]->node,
1054 p->tree->children[1]->node};
1055 TFNode* phi = builder_->Phi(p->tree->type, 2, vals, merge);
1056 p->tree->node = phi;
1057 ssa_env_->control = merge;
1058 }
1059 }
1060 break;
1061 }
1062 case kExprBr: {
1063 BreakDepthOperand operand(this, p->pc());
1064 CHECK(Validate(p->pc(), operand, blocks_));
1065 ReduceBreakToExprBlock(p, operand.target);
1066 break;
1067 }
1068 case kExprBrIf: {
1069 if (p->done()) {
1070 TypeCheckLast(p, kAstI32);
1071 BreakDepthOperand operand(this, p->pc());
1072 CHECK(Validate(p->pc(), operand, blocks_));
1073 SsaEnv* fenv = ssa_env_;
1074 SsaEnv* tenv = Split(fenv);
1075 BUILD(Branch, p->tree->children[1]->node, &tenv->control,
1076 &fenv->control);
1077 ssa_env_ = tenv;
1078 ReduceBreakToExprBlock(p, operand.target, p->tree->children[0]);
1079 ssa_env_ = fenv;
1080 }
1081 break;
1082 }
1083 case kExprBrTable: {
1084 if (p->index == 1) {
1085 // Switch key finished.
1086 TypeCheckLast(p, kAstI32);
1087 if (failed()) break;
1088
1089 BranchTableOperand operand(this, p->pc());
1090 DCHECK(Validate(p->pc(), operand, blocks_.size()));
1091
1092 // Build a switch only if it has more than just a default target.
1093 bool build_switch = operand.table_count > 0;
1094 TFNode* sw = nullptr;
1095 if (build_switch) {
1096 sw = BUILD(Switch, operand.table_count + 1, p->last()->node);
1097 }
1098
1099 // Process the targets of the break table.
1100 SsaEnv* prev = ssa_env_;
1101 SsaEnv* copy = Steal(prev);
1102 for (uint32_t i = 0; i < operand.table_count + 1; i++) {
1103 uint32_t target = operand.read_entry(this, i);
1104 SsaEnv* env = copy;
1105 if (build_switch) {
1106 ssa_env_ = env = Split(env);
1107 env->control = i == operand.table_count ? BUILD(IfDefault, sw)
1108 : BUILD(IfValue, i, sw);
1109 }
1110 SsaEnv* tenv = blocks_[blocks_.size() - target - 1].ssa_env;
1111 Goto(env, tenv);
1112 }
1113 ssa_env_ = prev;
1114 }
1115 break;
1116 }
1117 case kExprReturn: {
1118 TypeCheckLast(p, sig_->GetReturn(p->index - 1));
1119 if (p->done()) {
1120 if (build()) {
1121 int count = p->tree->count;
1122 TFNode** buffer = builder_->Buffer(count);
1123 for (int i = 0; i < count; i++) {
1124 buffer[i] = p->tree->children[i]->node;
1125 }
1126 BUILD(Return, count, buffer);
1127 }
1128 ssa_env_->Kill(SsaEnv::kControlEnd);
1129 }
1130 break;
1131 }
1132 case kExprSetLocal: {
1133 LocalIndexOperand operand(this, p->pc());
1134 CHECK(Validate(p->pc(), operand));
1135 Tree* val = p->last();
1136 if (operand.type == val->type) {
1137 if (build()) ssa_env_->locals[operand.index] = val->node;
1138 p->tree->node = val->node;
1139 } else {
1140 error(p->pc(), val->pc, "Typecheck failed in SetLocal");
1141 }
1142 break;
1143 }
1144 case kExprStoreGlobal: {
1145 GlobalIndexOperand operand(this, p->pc());
1146 CHECK(Validate(p->pc(), operand));
1147 Tree* val = p->last();
1148 if (operand.type == val->type) {
1149 BUILD(StoreGlobal, operand.index, val->node);
1150 p->tree->node = val->node;
1151 } else {
1152 error(p->pc(), val->pc, "Typecheck failed in StoreGlobal");
1153 }
1154 break;
1155 }
1156
1157 case kExprI32LoadMem8S:
1158 return ReduceLoadMem(p, kAstI32, MachineType::Int8());
1159 case kExprI32LoadMem8U:
1160 return ReduceLoadMem(p, kAstI32, MachineType::Uint8());
1161 case kExprI32LoadMem16S:
1162 return ReduceLoadMem(p, kAstI32, MachineType::Int16());
1163 case kExprI32LoadMem16U:
1164 return ReduceLoadMem(p, kAstI32, MachineType::Uint16());
1165 case kExprI32LoadMem:
1166 return ReduceLoadMem(p, kAstI32, MachineType::Int32());
1167
1168 case kExprI64LoadMem8S:
1169 return ReduceLoadMem(p, kAstI64, MachineType::Int8());
1170 case kExprI64LoadMem8U:
1171 return ReduceLoadMem(p, kAstI64, MachineType::Uint8());
1172 case kExprI64LoadMem16S:
1173 return ReduceLoadMem(p, kAstI64, MachineType::Int16());
1174 case kExprI64LoadMem16U:
1175 return ReduceLoadMem(p, kAstI64, MachineType::Uint16());
1176 case kExprI64LoadMem32S:
1177 return ReduceLoadMem(p, kAstI64, MachineType::Int32());
1178 case kExprI64LoadMem32U:
1179 return ReduceLoadMem(p, kAstI64, MachineType::Uint32());
1180 case kExprI64LoadMem:
1181 return ReduceLoadMem(p, kAstI64, MachineType::Int64());
1182
1183 case kExprF32LoadMem:
1184 return ReduceLoadMem(p, kAstF32, MachineType::Float32());
1185
1186 case kExprF64LoadMem:
1187 return ReduceLoadMem(p, kAstF64, MachineType::Float64());
1188
1189 case kExprI32StoreMem8:
1190 return ReduceStoreMem(p, kAstI32, MachineType::Int8());
1191 case kExprI32StoreMem16:
1192 return ReduceStoreMem(p, kAstI32, MachineType::Int16());
1193 case kExprI32StoreMem:
1194 return ReduceStoreMem(p, kAstI32, MachineType::Int32());
1195
1196 case kExprI64StoreMem8:
1197 return ReduceStoreMem(p, kAstI64, MachineType::Int8());
1198 case kExprI64StoreMem16:
1199 return ReduceStoreMem(p, kAstI64, MachineType::Int16());
1200 case kExprI64StoreMem32:
1201 return ReduceStoreMem(p, kAstI64, MachineType::Int32());
1202 case kExprI64StoreMem:
1203 return ReduceStoreMem(p, kAstI64, MachineType::Int64());
1204
1205 case kExprF32StoreMem:
1206 return ReduceStoreMem(p, kAstF32, MachineType::Float32());
1207
1208 case kExprF64StoreMem:
1209 return ReduceStoreMem(p, kAstF64, MachineType::Float64());
1210
1211 case kExprGrowMemory:
1212 TypeCheckLast(p, kAstI32);
1213 // TODO(titzer): build node for GrowMemory
1214 p->tree->node = BUILD(Int32Constant, 0);
1215 return;
1216
1217 case kExprCallFunction: {
1218 FunctionIndexOperand operand(this, p->pc());
1219 CHECK(Validate(p->pc(), operand));
1220 if (p->index > 0) {
1221 TypeCheckLast(p, operand.sig->GetParam(p->index - 1));
1222 }
1223 if (p->done() && build()) {
1224 uint32_t count = p->tree->count + 1;
1225 TFNode** buffer = builder_->Buffer(count);
1226 buffer[0] = nullptr; // reserved for code object.
1227 for (uint32_t i = 1; i < count; i++) {
1228 buffer[i] = p->tree->children[i - 1]->node;
1229 }
1230 p->tree->node = builder_->CallDirect(operand.index, buffer);
1231 }
1232 break;
1233 }
1234 case kExprCallIndirect: {
1235 SignatureIndexOperand operand(this, p->pc());
1236 CHECK(Validate(p->pc(), operand));
1237 if (p->index == 1) {
1238 TypeCheckLast(p, kAstI32);
1239 } else {
1240 TypeCheckLast(p, operand.sig->GetParam(p->index - 2));
1241 }
1242 if (p->done() && build()) {
1243 uint32_t count = p->tree->count;
1244 TFNode** buffer = builder_->Buffer(count);
1245 for (uint32_t i = 0; i < count; i++) {
1246 buffer[i] = p->tree->children[i]->node;
1247 }
1248 p->tree->node = builder_->CallIndirect(operand.index, buffer);
1249 }
1250 break;
1251 }
1252 case kExprCallImport: {
1253 ImportIndexOperand operand(this, p->pc());
1254 CHECK(Validate(p->pc(), operand));
1255 if (p->index > 0) {
1256 TypeCheckLast(p, operand.sig->GetParam(p->index - 1));
1257 }
1258 if (p->done() && build()) {
1259 uint32_t count = p->tree->count + 1;
1260 TFNode** buffer = builder_->Buffer(count);
1261 buffer[0] = nullptr; // reserved for code object.
1262 for (uint32_t i = 1; i < count; i++) {
1263 buffer[i] = p->tree->children[i - 1]->node;
1264 }
1265 p->tree->node = builder_->CallImport(operand.index, buffer);
1266 }
1267 break;
1268 }
1269 default:
1270 break;
1271 }
1272 }
1273
1274 void ReduceBreakToExprBlock(Production* p, Block* block) {
1275 ReduceBreakToExprBlock(p, block, p->tree->count > 0 ? p->last() : nullptr);
1276 }
1277
1278 void ReduceBreakToExprBlock(Production* p, Block* block, Tree* val) {
1279 if (block->stack_depth < 0) {
1280 // This is the inner loop block, which does not have a value. 1122 // This is the inner loop block, which does not have a value.
1281 Goto(ssa_env_, block->ssa_env); 1123 Goto(ssa_env_, block->ssa_env);
1282 } else { 1124 } else {
1283 // Merge the value into the production for the block. 1125 // Merge the value into the production for the block.
1284 Production* bp = &stack_[block->stack_depth]; 1126 MergeInto(block->ssa_env, &block->node, &block->type, val);
1285 MergeIntoProduction(bp, block->ssa_env, val); 1127 }
1286 } 1128 }
1287 } 1129
1288 1130 void MergeInto(SsaEnv* target, TFNode** node, LocalType* type, Value& val) {
1289 void MergeIntoProduction(Production* p, SsaEnv* target, Tree* expr) {
1290 if (!ssa_env_->go()) return; 1131 if (!ssa_env_->go()) return;
1132 DCHECK_NE(kAstEnd, val.type);
1291 1133
1292 bool first = target->state == SsaEnv::kUnreachable; 1134 bool first = target->state == SsaEnv::kUnreachable;
1293 Goto(ssa_env_, target); 1135 Goto(ssa_env_, target);
1294 if (expr == nullptr || expr->type == kAstEnd) return;
1295 1136
1296 if (first) { 1137 if (first) {
1297 // first merge to this environment; set the type and the node. 1138 // first merge to this environment; set the type and the node.
1298 p->tree->type = expr->type; 1139 *type = val.type;
1299 p->tree->node = expr->node; 1140 *node = val.node;
1141 } else if (val.type == *type && val.type != kAstStmt) {
1142 // merge with the existing value for this block.
1143 *node = CreateOrMergeIntoPhi(*type, target->control, *node, val.node);
1300 } else { 1144 } else {
1301 // merge with the existing value for this block. 1145 // types don't match, or block is already a stmt.
1302 LocalType type = p->tree->type; 1146 *type = kAstStmt;
1303 if (expr->type != type) { 1147 *node = nullptr;
1304 type = kAstStmt;
1305 p->tree->type = kAstStmt;
1306 p->tree->node = nullptr;
1307 } else if (type != kAstStmt) {
1308 p->tree->node = CreateOrMergeIntoPhi(type, target->control,
1309 p->tree->node, expr->node);
1310 }
1311 }
1312 }
1313
1314 void ReduceLoadMem(Production* p, LocalType type, MachineType mem_type) {
1315 DCHECK_EQ(1, p->index);
1316 TypeCheckLast(p, kAstI32); // index
1317 if (build()) {
1318 MemoryAccessOperand operand(this, p->pc());
1319 p->tree->node =
1320 builder_->LoadMem(type, mem_type, p->last()->node, operand.offset);
1321 }
1322 }
1323
1324 void ReduceStoreMem(Production* p, LocalType type, MachineType mem_type) {
1325 if (p->index == 1) {
1326 TypeCheckLast(p, kAstI32); // index
1327 } else {
1328 DCHECK_EQ(2, p->index);
1329 TypeCheckLast(p, type);
1330 if (build()) {
1331 MemoryAccessOperand operand(this, p->pc());
1332 TFNode* val = p->tree->children[1]->node;
1333 builder_->StoreMem(mem_type, p->tree->children[0]->node, operand.offset,
1334 val);
1335 p->tree->node = val;
1336 }
1337 }
1338 }
1339
1340 void TypeCheckLast(Production* p, LocalType expected) {
1341 LocalType result = p->last()->type;
1342 if (result == expected) return;
1343 if (result == kAstEnd) return;
1344 if (expected != kAstStmt) {
1345 error(p->pc(), p->last()->pc,
1346 "%s[%d] expected type %s, found %s of type %s",
1347 WasmOpcodes::OpcodeName(p->opcode()), p->index - 1,
1348 WasmOpcodes::TypeName(expected),
1349 WasmOpcodes::OpcodeName(p->last()->opcode()),
1350 WasmOpcodes::TypeName(p->last()->type));
1351 } 1148 }
1352 } 1149 }
1353 1150
1354 void SetEnv(const char* reason, SsaEnv* env) { 1151 void SetEnv(const char* reason, SsaEnv* env) {
1355 #if DEBUG 1152 #if DEBUG
1356 TRACE(" env = %p, block depth = %d, reason = %s", static_cast<void*>(env), 1153 if (FLAG_trace_wasm_decoder) {
1357 static_cast<int>(blocks_.size()), reason); 1154 char state = 'X';
1358 if (FLAG_trace_wasm_decoder && env && env->control) { 1155 if (env) {
1359 TRACE(", control = "); 1156 switch (env->state) {
1360 compiler::WasmGraphBuilder::PrintDebugName(env->control); 1157 case SsaEnv::kReached:
1361 } 1158 state = 'R';
1362 TRACE("\n"); 1159 break;
1160 case SsaEnv::kUnreachable:
1161 state = 'U';
1162 break;
1163 case SsaEnv::kMerged:
1164 state = 'M';
1165 break;
1166 case SsaEnv::kControlEnd:
1167 state = 'E';
1168 break;
1169 }
1170 }
1171 PrintF(" env = %p, state = %c, reason = %s", static_cast<void*>(env),
1172 state, reason);
1173 if (env && env->control) {
1174 PrintF(", control = ");
1175 compiler::WasmGraphBuilder::PrintDebugName(env->control);
1176 }
1177 PrintF("\n");
1178 }
1363 #endif 1179 #endif
1364 ssa_env_ = env; 1180 ssa_env_ = env;
1365 if (builder_) { 1181 if (builder_) {
1366 builder_->set_control_ptr(&env->control); 1182 builder_->set_control_ptr(&env->control);
1367 builder_->set_effect_ptr(&env->effect); 1183 builder_->set_effect_ptr(&env->effect);
1368 } 1184 }
1369 } 1185 }
1370 1186
1371 void Goto(SsaEnv* from, SsaEnv* to) { 1187 void Goto(SsaEnv* from, SsaEnv* to) {
1372 DCHECK_NOT_NULL(to); 1188 DCHECK_NOT_NULL(to);
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
1486 } 1302 }
1487 } 1303 }
1488 1304
1489 // Create a complete copy of the {from}. 1305 // Create a complete copy of the {from}.
1490 SsaEnv* Split(SsaEnv* from) { 1306 SsaEnv* Split(SsaEnv* from) {
1491 DCHECK_NOT_NULL(from); 1307 DCHECK_NOT_NULL(from);
1492 SsaEnv* result = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv))); 1308 SsaEnv* result = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
1493 size_t size = sizeof(TFNode*) * EnvironmentCount(); 1309 size_t size = sizeof(TFNode*) * EnvironmentCount();
1494 result->control = from->control; 1310 result->control = from->control;
1495 result->effect = from->effect; 1311 result->effect = from->effect;
1496 result->state = from->state == SsaEnv::kUnreachable ? SsaEnv::kUnreachable
1497 : SsaEnv::kReached;
1498 1312
1499 if (from->go()) { 1313 if (from->go()) {
1500 result->state = SsaEnv::kReached; 1314 result->state = SsaEnv::kReached;
1501 result->locals = 1315 result->locals =
1502 size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr; 1316 size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr;
1503 memcpy(result->locals, from->locals, size); 1317 memcpy(result->locals, from->locals, size);
1504 } else { 1318 } else {
1505 result->state = SsaEnv::kUnreachable; 1319 result->state = SsaEnv::kUnreachable;
1506 result->locals = nullptr; 1320 result->locals = nullptr;
1507 } 1321 }
(...skipping 26 matching lines...) Expand all
1534 } 1348 }
1535 1349
1536 int EnvironmentCount() { 1350 int EnvironmentCount() {
1537 if (builder_) return static_cast<int>(local_type_vec_.size()); 1351 if (builder_) return static_cast<int>(local_type_vec_.size());
1538 return 0; // if we aren't building a graph, don't bother with SSA renaming. 1352 return 0; // if we aren't building a graph, don't bother with SSA renaming.
1539 } 1353 }
1540 1354
1541 virtual void onFirstError() { 1355 virtual void onFirstError() {
1542 limit_ = start_; // Terminate decoding loop. 1356 limit_ = start_; // Terminate decoding loop.
1543 builder_ = nullptr; // Don't build any more nodes. 1357 builder_ = nullptr; // Don't build any more nodes.
1544 #if DEBUG 1358 TRACE(" !%s\n", error_msg_.get());
1545 PrintStackForDebugging();
1546 #endif
1547 } 1359 }
1548
1549 #if DEBUG
1550 void PrintStackForDebugging() { PrintProduction(0); }
1551
1552 void PrintProduction(size_t depth) {
1553 if (depth >= stack_.size()) return;
1554 Production* p = &stack_[depth];
1555 for (size_t d = 0; d < depth; d++) PrintF(" ");
1556
1557 PrintF("@%d %s [%d]\n", static_cast<int>(p->tree->pc - start_),
1558 WasmOpcodes::OpcodeName(p->opcode()), p->tree->count);
1559 for (int i = 0; i < p->index; i++) {
1560 Tree* child = p->tree->children[i];
1561 for (size_t d = 0; d <= depth; d++) PrintF(" ");
1562 PrintF("@%d %s [%d]", static_cast<int>(child->pc - start_),
1563 WasmOpcodes::OpcodeName(child->opcode()), child->count);
1564 if (child->node) {
1565 PrintF(" => TF");
1566 compiler::WasmGraphBuilder::PrintDebugName(child->node);
1567 }
1568 PrintF("\n");
1569 }
1570 PrintProduction(depth + 1);
1571 }
1572 #endif
1573
1574 BitVector* AnalyzeLoopAssignment(const byte* pc) { 1360 BitVector* AnalyzeLoopAssignment(const byte* pc) {
1575 if (pc >= limit_) return nullptr; 1361 if (pc >= limit_) return nullptr;
1576 if (*pc != kExprLoop) return nullptr; 1362 if (*pc != kExprLoop) return nullptr;
1577 1363
1578 BitVector* assigned = 1364 BitVector* assigned =
1579 new (zone_) BitVector(static_cast<int>(total_locals_), zone_); 1365 new (zone_) BitVector(static_cast<int>(local_type_vec_.size()), zone_);
1580 // Keep a stack to model the nesting of expressions. 1366 int depth = 0;
1581 std::vector<int> arity_stack;
1582 arity_stack.push_back(OpcodeArity(pc));
1583 pc += OpcodeLength(pc);
1584
1585 // Iteratively process all AST nodes nested inside the loop. 1367 // Iteratively process all AST nodes nested inside the loop.
1586 while (pc < limit_) { 1368 while (pc_ < limit_) {
1587 WasmOpcode opcode = static_cast<WasmOpcode>(*pc); 1369 WasmOpcode opcode = static_cast<WasmOpcode>(*pc_);
1588 int arity = 0;
1589 int length = 1; 1370 int length = 1;
1590 int assigned_index = -1; 1371 switch (opcode) {
1591 if (opcode == kExprSetLocal) { 1372 case kExprLoop:
1592 LocalIndexOperand operand(this, pc); 1373 case kExprIf:
1593 if (assigned->length() > 0 && 1374 case kExprBlock:
1594 static_cast<int>(operand.index) < assigned->length()) { 1375 depth++;
1595 // Unverified code might have an out-of-bounds index. 1376 DCHECK_EQ(1, OpcodeLength(pc_));
1596 // Ignore out-of-bounds indices, as the main verification will fail. 1377 break;
1597 assigned->Add(operand.index); 1378 case kExprSetLocal: {
1598 assigned_index = operand.index; 1379 LocalIndexOperand operand(this, pc_);
1380 if (assigned->length() > 0 &&
1381 static_cast<int>(operand.index) < assigned->length()) {
1382 // Unverified code might have an out-of-bounds index.
1383 assigned->Add(operand.index);
1384 }
1385 length = 1 + operand.length;
1386 break;
1599 } 1387 }
1600 arity = 1; 1388 case kExprEnd:
1601 length = 1 + operand.length; 1389 depth--;
1602 } else { 1390 break;
1603 arity = OpcodeArity(pc); 1391 default:
1604 length = OpcodeLength(pc); 1392 length = OpcodeLength(pc_);
1393 break;
1605 } 1394 }
1606 1395 if (depth <= 0) break;
1607 TRACE("loop-assign module+%-6d %s func+%d: 0x%02x %s", baserel(pc), 1396 pc_ += length;
1608 indentation(), startrel(pc), opcode,
1609 WasmOpcodes::OpcodeName(opcode));
1610
1611 if (assigned_index >= 0) {
1612 TRACE(" (assigned local #%d)\n", assigned_index);
1613 } else {
1614 TRACE("\n");
1615 }
1616
1617 pc += length;
1618 arity_stack.push_back(arity);
1619 while (arity_stack.back() == 0) {
1620 arity_stack.pop_back();
1621 if (arity_stack.empty()) return assigned; // reached end of loop
1622 arity_stack.back()--;
1623 }
1624 } 1397 }
1625 return assigned; 1398 return assigned;
1626 } 1399 }
1627 }; 1400 };
1628 1401
1629 std::vector<LocalType>* DecodeLocalDeclsForTesting(const byte* start, 1402 std::vector<LocalType>* DecodeLocalDeclsForTesting(const byte* start,
1630 const byte* end) { 1403 const byte* end) {
1631 Zone zone; 1404 Zone zone;
1632 FunctionBody body = {nullptr, nullptr, nullptr, start, end}; 1405 FunctionBody body = {nullptr, nullptr, nullptr, start, end};
1633 SR_WasmDecoder decoder(&zone, nullptr, body); 1406 SR_WasmDecoder decoder(&zone, nullptr, body);
1634 return decoder.DecodeLocalDeclsForTesting(); 1407 return decoder.DecodeLocalDeclsForTesting();
1635 } 1408 }
1636 1409
1637 TreeResult VerifyWasmCode(FunctionBody& body) { 1410 TreeResult VerifyWasmCode(FunctionBody& body) {
1638 Zone zone; 1411 Zone zone;
1639 SR_WasmDecoder decoder(&zone, nullptr, body); 1412 SR_WasmDecoder decoder(&zone, nullptr, body);
1640 TreeResult result = decoder.Decode(); 1413 decoder.Decode();
1641 return result; 1414 return decoder.toResult<Tree*>(nullptr);
1642 } 1415 }
1643 1416
1644 TreeResult BuildTFGraph(TFBuilder* builder, FunctionBody& body) { 1417 TreeResult BuildTFGraph(TFBuilder* builder, FunctionBody& body) {
1645 Zone zone; 1418 Zone zone;
1646 SR_WasmDecoder decoder(&zone, builder, body); 1419 SR_WasmDecoder decoder(&zone, builder, body);
1647 TreeResult result = decoder.Decode(); 1420 decoder.Decode();
1648 return result; 1421 return decoder.toResult<Tree*>(nullptr);
1649 } 1422 }
1650 1423
1651 1424
1652 std::ostream& operator<<(std::ostream& os, const Tree& tree) { 1425 std::ostream& operator<<(std::ostream& os, const Tree& tree) {
1653 if (tree.pc == nullptr) { 1426 if (tree.pc == nullptr) {
1654 os << "null"; 1427 os << "null";
1655 return os; 1428 return os;
1656 } 1429 }
1657 PrintF("%s", WasmOpcodes::OpcodeName(tree.opcode())); 1430 PrintF("%s", WasmOpcodes::OpcodeName(tree.opcode()));
1658 if (tree.count > 0) os << "("; 1431 if (tree.count > 0) os << "(";
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
1783 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, 1556 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals,
1784 const byte* start, const byte* end) { 1557 const byte* start, const byte* end) {
1785 FunctionBody body = {nullptr, nullptr, nullptr, start, end}; 1558 FunctionBody body = {nullptr, nullptr, nullptr, start, end};
1786 SR_WasmDecoder decoder(zone, nullptr, body); 1559 SR_WasmDecoder decoder(zone, nullptr, body);
1787 return decoder.AnalyzeLoopAssignmentForTesting(start, num_locals); 1560 return decoder.AnalyzeLoopAssignmentForTesting(start, num_locals);
1788 } 1561 }
1789 1562
1790 } // namespace wasm 1563 } // namespace wasm
1791 } // namespace internal 1564 } // namespace internal
1792 } // namespace v8 1565 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698