blob: e2f6a046b36d59acefe8f28b3650e6c377c4ebf4 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005#include "src/signature.h"
6
Ben Murdoch097c5b22016-05-18 11:27:45 +01007#include "src/bit-vector.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008#include "src/flags.h"
9#include "src/handles.h"
10#include "src/zone-containers.h"
11
12#include "src/wasm/ast-decoder.h"
13#include "src/wasm/decoder.h"
14#include "src/wasm/wasm-module.h"
15#include "src/wasm/wasm-opcodes.h"
16
Ben Murdochda12d292016-06-02 14:46:10 +010017#include "src/ostreams.h"
18
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019#include "src/compiler/wasm-compiler.h"
20
21namespace v8 {
22namespace internal {
23namespace wasm {
24
25#if DEBUG
26#define TRACE(...) \
27 do { \
28 if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \
29 } while (false)
30#else
31#define TRACE(...)
32#endif
33
34// The root of a decoded tree.
35struct Tree {
36 LocalType type; // tree type.
37 uint32_t count; // number of children.
38 const byte* pc; // start of the syntax tree.
39 TFNode* node; // node in the TurboFan graph.
40 Tree* children[1]; // pointers to children.
41
42 WasmOpcode opcode() const { return static_cast<WasmOpcode>(*pc); }
43};
44
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000045// A production represents an incomplete decoded tree in the LR decoder.
46struct 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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000056// An SsaEnv environment carries the current local variable renaming
57// as well as the current effect and control dependency in the TF graph.
58// It maintains a control state that tracks whether the environment
59// is reachable, has reached a control end, or has been merged.
60struct SsaEnv {
61 enum State { kControlEnd, kUnreachable, kReached, kMerged };
62
63 State state;
64 TFNode* control;
65 TFNode* effect;
66 TFNode** locals;
67
68 bool go() { return state >= kReached; }
69 void Kill(State new_state = kControlEnd) {
70 state = new_state;
71 locals = nullptr;
72 control = nullptr;
73 effect = nullptr;
74 }
75};
76
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000077// An entry in the stack of blocks during decoding.
78struct Block {
79 SsaEnv* ssa_env; // SSA renaming environment.
80 int stack_depth; // production stack depth.
81};
82
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000083// An entry in the stack of ifs during decoding.
84struct IfEnv {
85 SsaEnv* false_env;
86 SsaEnv* merge_env;
87 SsaEnv** case_envs;
88};
89
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000090// 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
92// TF graphs when decoding inputs that have unreachable code.
93#define BUILD(func, ...) (build() ? builder_->func(__VA_ARGS__) : nullptr)
94#define BUILD0(func) (build() ? builder_->func() : nullptr)
95
Ben Murdoch097c5b22016-05-18 11:27:45 +010096// Generic Wasm bytecode decoder with utilities for decoding operands,
97// lengths, etc.
98class WasmDecoder : public Decoder {
99 public:
Ben Murdochda12d292016-06-02 14:46:10 +0100100 WasmDecoder(ModuleEnv* module, FunctionSig* sig, const byte* start,
101 const byte* end)
102 : Decoder(start, end),
103 module_(module),
104 sig_(sig),
105 total_locals_(0),
106 local_types_(nullptr) {}
107 ModuleEnv* module_;
108 FunctionSig* sig_;
109 size_t total_locals_;
110 ZoneVector<LocalType>* local_types_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100111
112 byte ByteOperand(const byte* pc, const char* msg = "missing 1-byte operand") {
113 if ((pc + sizeof(byte)) >= limit_) {
114 error(pc, msg);
115 return 0;
116 }
117 return pc[1];
118 }
119
120 uint32_t Uint32Operand(const byte* pc) {
121 if ((pc + sizeof(uint32_t)) >= limit_) {
122 error(pc, "missing 4-byte operand");
123 return 0;
124 }
125 return read_u32(pc + 1);
126 }
127
128 uint64_t Uint64Operand(const byte* pc) {
129 if ((pc + sizeof(uint64_t)) >= limit_) {
130 error(pc, "missing 8-byte operand");
131 return 0;
132 }
133 return read_u64(pc + 1);
134 }
135
136 inline bool Validate(const byte* pc, LocalIndexOperand& operand) {
Ben Murdochda12d292016-06-02 14:46:10 +0100137 if (operand.index < total_locals_) {
138 if (local_types_) {
139 operand.type = local_types_->at(operand.index);
140 } else {
141 operand.type = kAstStmt;
142 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100143 return true;
144 }
145 error(pc, pc + 1, "invalid local index");
146 return false;
147 }
148
149 inline bool Validate(const byte* pc, GlobalIndexOperand& operand) {
Ben Murdochda12d292016-06-02 14:46:10 +0100150 ModuleEnv* m = module_;
151 if (m && m->module && operand.index < m->module->globals.size()) {
152 operand.machine_type = m->module->globals[operand.index].type;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100153 operand.type = WasmOpcodes::LocalTypeFor(operand.machine_type);
154 return true;
155 }
156 error(pc, pc + 1, "invalid global index");
157 return false;
158 }
159
160 inline bool Validate(const byte* pc, FunctionIndexOperand& operand) {
Ben Murdochda12d292016-06-02 14:46:10 +0100161 ModuleEnv* m = module_;
162 if (m && m->module && operand.index < m->module->functions.size()) {
163 operand.sig = m->module->functions[operand.index].sig;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100164 return true;
165 }
166 error(pc, pc + 1, "invalid function index");
167 return false;
168 }
169
170 inline bool Validate(const byte* pc, SignatureIndexOperand& operand) {
Ben Murdochda12d292016-06-02 14:46:10 +0100171 ModuleEnv* m = module_;
172 if (m && m->module && operand.index < m->module->signatures.size()) {
173 operand.sig = m->module->signatures[operand.index];
Ben Murdoch097c5b22016-05-18 11:27:45 +0100174 return true;
175 }
176 error(pc, pc + 1, "invalid signature index");
177 return false;
178 }
179
180 inline bool Validate(const byte* pc, ImportIndexOperand& operand) {
Ben Murdochda12d292016-06-02 14:46:10 +0100181 ModuleEnv* m = module_;
182 if (m && m->module && operand.index < m->module->import_table.size()) {
183 operand.sig = m->module->import_table[operand.index].sig;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100184 return true;
185 }
186 error(pc, pc + 1, "invalid signature index");
187 return false;
188 }
189
190 inline bool Validate(const byte* pc, BreakDepthOperand& operand,
191 ZoneVector<Block>& blocks) {
192 if (operand.depth < blocks.size()) {
193 operand.target = &blocks[blocks.size() - operand.depth - 1];
194 return true;
195 }
196 error(pc, pc + 1, "invalid break depth");
197 return false;
198 }
199
Ben Murdochda12d292016-06-02 14:46:10 +0100200 bool Validate(const byte* pc, BranchTableOperand& operand,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100201 size_t block_depth) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100202 // Verify table.
Ben Murdochda12d292016-06-02 14:46:10 +0100203 for (uint32_t i = 0; i < operand.table_count + 1; i++) {
204 uint32_t target = operand.read_entry(this, i);
205 if (target >= block_depth) {
206 error(operand.table + i * 2, "improper branch in br_table");
207 return false;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100208 }
209 }
210 return true;
211 }
212
213 int OpcodeArity(const byte* pc) {
214#define DECLARE_ARITY(name, ...) \
215 static const LocalType kTypes_##name[] = {__VA_ARGS__}; \
216 static const int kArity_##name = \
217 static_cast<int>(arraysize(kTypes_##name) - 1);
218
219 FOREACH_SIGNATURE(DECLARE_ARITY);
220#undef DECLARE_ARITY
221
222 switch (static_cast<WasmOpcode>(*pc)) {
223 case kExprI8Const:
224 case kExprI32Const:
225 case kExprI64Const:
226 case kExprF64Const:
227 case kExprF32Const:
228 case kExprGetLocal:
229 case kExprLoadGlobal:
230 case kExprNop:
231 case kExprUnreachable:
232 return 0;
233
234 case kExprBr:
235 case kExprStoreGlobal:
236 case kExprSetLocal:
237 return 1;
238
239 case kExprIf:
240 case kExprBrIf:
241 return 2;
242 case kExprIfElse:
243 case kExprSelect:
244 return 3;
245
246 case kExprBlock:
247 case kExprLoop: {
248 BlockCountOperand operand(this, pc);
249 return operand.count;
250 }
251
252 case kExprCallFunction: {
253 FunctionIndexOperand operand(this, pc);
254 return static_cast<int>(
Ben Murdochda12d292016-06-02 14:46:10 +0100255 module_->GetFunctionSignature(operand.index)->parameter_count());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100256 }
257 case kExprCallIndirect: {
258 SignatureIndexOperand operand(this, pc);
259 return 1 + static_cast<int>(
Ben Murdochda12d292016-06-02 14:46:10 +0100260 module_->GetSignature(operand.index)->parameter_count());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100261 }
262 case kExprCallImport: {
263 ImportIndexOperand operand(this, pc);
264 return static_cast<int>(
Ben Murdochda12d292016-06-02 14:46:10 +0100265 module_->GetImportSignature(operand.index)->parameter_count());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100266 }
267 case kExprReturn: {
Ben Murdochda12d292016-06-02 14:46:10 +0100268 return static_cast<int>(sig_->return_count());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100269 }
Ben Murdochda12d292016-06-02 14:46:10 +0100270 case kExprBrTable: {
271 return 1;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100272 }
273
274#define DECLARE_OPCODE_CASE(name, opcode, sig) \
275 case kExpr##name: \
276 return kArity_##sig;
277
278 FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
279 FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
280 FOREACH_MISC_MEM_OPCODE(DECLARE_OPCODE_CASE)
281 FOREACH_SIMPLE_OPCODE(DECLARE_OPCODE_CASE)
Ben Murdochda12d292016-06-02 14:46:10 +0100282 FOREACH_ASMJS_COMPAT_OPCODE(DECLARE_OPCODE_CASE)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100283#undef DECLARE_OPCODE_CASE
Ben Murdochda12d292016-06-02 14:46:10 +0100284 case kExprDeclLocals:
285 default:
286 UNREACHABLE();
287 return 0;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100288 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100289 }
290
291 int OpcodeLength(const byte* pc) {
292 switch (static_cast<WasmOpcode>(*pc)) {
293#define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
294 FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
295 FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
296#undef DECLARE_OPCODE_CASE
297 {
298 MemoryAccessOperand operand(this, pc);
299 return 1 + operand.length;
300 }
301 case kExprBlock:
302 case kExprLoop: {
303 BlockCountOperand operand(this, pc);
304 return 1 + operand.length;
305 }
306 case kExprBr:
307 case kExprBrIf: {
308 BreakDepthOperand operand(this, pc);
309 return 1 + operand.length;
310 }
311 case kExprStoreGlobal:
312 case kExprLoadGlobal: {
313 GlobalIndexOperand operand(this, pc);
314 return 1 + operand.length;
315 }
316
317 case kExprCallFunction: {
318 FunctionIndexOperand operand(this, pc);
319 return 1 + operand.length;
320 }
321 case kExprCallIndirect: {
322 SignatureIndexOperand operand(this, pc);
323 return 1 + operand.length;
324 }
325 case kExprCallImport: {
326 ImportIndexOperand operand(this, pc);
327 return 1 + operand.length;
328 }
329
330 case kExprSetLocal:
331 case kExprGetLocal: {
332 LocalIndexOperand operand(this, pc);
333 return 1 + operand.length;
334 }
Ben Murdochda12d292016-06-02 14:46:10 +0100335 case kExprBrTable: {
336 BranchTableOperand operand(this, pc);
337 return 1 + operand.length;
338 }
339 case kExprI32Const: {
340 ImmI32Operand operand(this, pc);
341 return 1 + operand.length;
342 }
343 case kExprI64Const: {
344 ImmI64Operand operand(this, pc);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100345 return 1 + operand.length;
346 }
347 case kExprI8Const:
348 return 2;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100349 case kExprF32Const:
350 return 5;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100351 case kExprF64Const:
352 return 9;
353
354 default:
355 return 1;
356 }
357 }
358};
359
360
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000361// A shift-reduce-parser strategy for decoding Wasm code that uses an explicit
362// shift-reduce strategy with multiple internal stacks.
Ben Murdochda12d292016-06-02 14:46:10 +0100363class SR_WasmDecoder : public WasmDecoder {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000364 public:
Ben Murdochda12d292016-06-02 14:46:10 +0100365 SR_WasmDecoder(Zone* zone, TFBuilder* builder, FunctionBody& body)
366 : WasmDecoder(body.module, body.sig, body.start, body.end),
367 zone_(zone),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000368 builder_(builder),
Ben Murdochda12d292016-06-02 14:46:10 +0100369 base_(body.base),
370 local_type_vec_(zone),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000371 trees_(zone),
372 stack_(zone),
373 blocks_(zone),
Ben Murdochda12d292016-06-02 14:46:10 +0100374 ifs_(zone) {
375 local_types_ = &local_type_vec_;
376 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000377
Ben Murdochda12d292016-06-02 14:46:10 +0100378 TreeResult Decode() {
379 if (end_ < pc_) {
380 error(pc_, "function body end < start");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000381 return result_;
382 }
383
Ben Murdochda12d292016-06-02 14:46:10 +0100384 DecodeLocalDecls();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000385 InitSsaEnv();
386 DecodeFunctionBody();
387
388 Tree* tree = nullptr;
389 if (ok()) {
390 if (ssa_env_->go()) {
391 if (stack_.size() > 0) {
Ben Murdochda12d292016-06-02 14:46:10 +0100392 error(stack_.back().pc(), end_, "fell off end of code");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000393 }
394 AddImplicitReturnAtEnd();
395 }
396 if (trees_.size() == 0) {
Ben Murdochda12d292016-06-02 14:46:10 +0100397 if (sig_->return_count() > 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000398 error(start_, "no trees created");
399 }
400 } else {
401 tree = trees_[0];
402 }
403 }
404
405 if (ok()) {
Ben Murdochda12d292016-06-02 14:46:10 +0100406 TRACE("wasm-decode ok\n");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000407 } else {
408 TRACE("wasm-error module+%-6d func+%d: %s\n\n", baserel(error_pc_),
409 startrel(error_pc_), error_msg_.get());
410 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100411
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000412 return toResult(tree);
413 }
414
Ben Murdochda12d292016-06-02 14:46:10 +0100415 bool DecodeLocalDecls(AstLocalDecls& decls) {
416 DecodeLocalDecls();
417 if (failed()) return false;
418 decls.decls_encoded_size = pc_offset();
419 decls.total_local_count = 0;
420 decls.local_types.reserve(local_type_vec_.size());
421 for (size_t pos = 0; pos < local_type_vec_.size();) {
422 uint32_t count = 0;
423 LocalType type = local_type_vec_[pos];
424 while (pos < local_type_vec_.size() && local_type_vec_[pos] == type) {
425 pos++;
426 count++;
427 }
428 decls.total_local_count += count;
429 decls.local_types.push_back(std::pair<LocalType, uint32_t>(type, count));
430 }
431 return true;
432 }
433
434 BitVector* AnalyzeLoopAssignmentForTesting(const byte* pc,
435 size_t num_locals) {
436 total_locals_ = num_locals;
437 local_type_vec_.reserve(num_locals);
438 if (num_locals > local_type_vec_.size()) {
439 local_type_vec_.insert(local_type_vec_.end(),
440 num_locals - local_type_vec_.size(), kAstI32);
441 }
442 return AnalyzeLoopAssignment(pc);
443 }
444
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000445 private:
446 static const size_t kErrorMsgSize = 128;
447
448 Zone* zone_;
449 TFBuilder* builder_;
450 const byte* base_;
451 TreeResult result_;
452
453 SsaEnv* ssa_env_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000454
Ben Murdochda12d292016-06-02 14:46:10 +0100455 ZoneVector<LocalType> local_type_vec_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000456 ZoneVector<Tree*> trees_;
457 ZoneVector<Production> stack_;
458 ZoneVector<Block> blocks_;
459 ZoneVector<IfEnv> ifs_;
460
461 inline bool build() { return builder_ && ssa_env_->go(); }
462
463 void InitSsaEnv() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000464 TFNode* start = nullptr;
465 SsaEnv* ssa_env = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
466 size_t size = sizeof(TFNode*) * EnvironmentCount();
467 ssa_env->state = SsaEnv::kReached;
468 ssa_env->locals =
469 size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr;
470
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000471 if (builder_) {
Ben Murdochda12d292016-06-02 14:46:10 +0100472 start = builder_->Start(static_cast<int>(sig_->parameter_count() + 1));
473 // Initialize local variables.
474 uint32_t index = 0;
475 while (index < sig_->parameter_count()) {
476 ssa_env->locals[index] = builder_->Param(index, local_type_vec_[index]);
477 index++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000478 }
Ben Murdochda12d292016-06-02 14:46:10 +0100479 while (index < local_type_vec_.size()) {
480 LocalType type = local_type_vec_[index];
481 TFNode* node = DefaultValue(type);
482 while (index < local_type_vec_.size() &&
483 local_type_vec_[index] == type) {
484 // Do a whole run of like-typed locals at a time.
485 ssa_env->locals[index++] = node;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000486 }
487 }
Ben Murdochda12d292016-06-02 14:46:10 +0100488 builder_->set_module(module_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000489 }
490 ssa_env->control = start;
491 ssa_env->effect = start;
492 SetEnv("initial", ssa_env);
493 }
494
Ben Murdochda12d292016-06-02 14:46:10 +0100495 TFNode* DefaultValue(LocalType type) {
496 switch (type) {
497 case kAstI32:
498 return builder_->Int32Constant(0);
499 case kAstI64:
500 return builder_->Int64Constant(0);
501 case kAstF32:
502 return builder_->Float32Constant(0);
503 case kAstF64:
504 return builder_->Float64Constant(0);
505 default:
506 UNREACHABLE();
507 return nullptr;
508 }
509 }
510
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000511 void Leaf(LocalType type, TFNode* node = nullptr) {
512 size_t size = sizeof(Tree);
513 Tree* tree = reinterpret_cast<Tree*>(zone_->New(size));
514 tree->type = type;
515 tree->count = 0;
516 tree->pc = pc_;
517 tree->node = node;
518 tree->children[0] = nullptr;
519 Reduce(tree);
520 }
521
522 void Shift(LocalType type, uint32_t count) {
523 size_t size =
524 sizeof(Tree) + (count == 0 ? 0 : ((count - 1) * sizeof(Tree*)));
525 Tree* tree = reinterpret_cast<Tree*>(zone_->New(size));
526 tree->type = type;
527 tree->count = count;
528 tree->pc = pc_;
529 tree->node = nullptr;
530 for (uint32_t i = 0; i < count; i++) tree->children[i] = nullptr;
531 if (count == 0) {
532 Production p = {tree, 0};
533 Reduce(&p);
534 Reduce(tree);
535 } else {
536 stack_.push_back({tree, 0});
537 }
538 }
539
540 void Reduce(Tree* tree) {
541 while (true) {
542 if (stack_.size() == 0) {
543 trees_.push_back(tree);
544 break;
545 }
546 Production* p = &stack_.back();
547 p->tree->children[p->index++] = tree;
548 Reduce(p);
549 if (p->done()) {
550 tree = p->tree;
551 stack_.pop_back();
552 } else {
553 break;
554 }
555 }
556 }
557
558 char* indentation() {
559 static const int kMaxIndent = 64;
560 static char bytes[kMaxIndent + 1];
561 for (int i = 0; i < kMaxIndent; i++) bytes[i] = ' ';
562 bytes[kMaxIndent] = 0;
563 if (stack_.size() < kMaxIndent / 2) {
564 bytes[stack_.size() * 2] = 0;
565 }
566 return bytes;
567 }
568
Ben Murdochda12d292016-06-02 14:46:10 +0100569 // Decodes the locals declarations, if any, populating {local_type_vec_}.
570 void DecodeLocalDecls() {
571 DCHECK_EQ(0, local_type_vec_.size());
572 // Initialize {local_type_vec} from signature.
573 if (sig_) {
574 local_type_vec_.reserve(sig_->parameter_count());
575 for (size_t i = 0; i < sig_->parameter_count(); i++) {
576 local_type_vec_.push_back(sig_->GetParam(i));
577 }
578 }
579 // Decode local declarations, if any.
580 int length;
581 uint32_t entries = consume_u32v(&length, "local decls count");
582 while (entries-- > 0 && pc_ < limit_) {
583 uint32_t count = consume_u32v(&length, "local count");
584 byte code = consume_u8("local type");
585 LocalType type;
586 switch (code) {
587 case kLocalI32:
588 type = kAstI32;
589 break;
590 case kLocalI64:
591 type = kAstI64;
592 break;
593 case kLocalF32:
594 type = kAstF32;
595 break;
596 case kLocalF64:
597 type = kAstF64;
598 break;
599 default:
600 error(pc_ - 1, "invalid local type");
601 return;
602 }
603 local_type_vec_.insert(local_type_vec_.end(), count, type);
604 }
605 total_locals_ = local_type_vec_.size();
606 }
607
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000608 // Decodes the body of a function, producing reduced trees into {result}.
609 void DecodeFunctionBody() {
610 TRACE("wasm-decode %p...%p (%d bytes) %s\n",
611 reinterpret_cast<const void*>(start_),
612 reinterpret_cast<const void*>(limit_),
613 static_cast<int>(limit_ - start_), builder_ ? "graph building" : "");
614
615 if (pc_ >= limit_) return; // Nothing to do.
616
617 while (true) { // decoding loop.
618 int len = 1;
619 WasmOpcode opcode = static_cast<WasmOpcode>(*pc_);
620 TRACE("wasm-decode module+%-6d %s func+%d: 0x%02x %s\n", baserel(pc_),
621 indentation(), startrel(pc_), opcode,
622 WasmOpcodes::OpcodeName(opcode));
623
624 FunctionSig* sig = WasmOpcodes::Signature(opcode);
625 if (sig) {
626 // A simple expression with a fixed signature.
627 Shift(sig->GetReturn(), static_cast<uint32_t>(sig->parameter_count()));
628 pc_ += len;
629 if (pc_ >= limit_) {
630 // End of code reached or exceeded.
631 if (pc_ > limit_ && ok()) {
632 error("Beyond end of code");
633 }
634 return;
635 }
636 continue; // back to decoding loop.
637 }
638
639 switch (opcode) {
640 case kExprNop:
641 Leaf(kAstStmt);
642 break;
643 case kExprBlock: {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100644 BlockCountOperand operand(this, pc_);
645 if (operand.count < 1) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000646 Leaf(kAstStmt);
647 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100648 Shift(kAstEnd, operand.count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000649 // The break environment is the outer environment.
650 SsaEnv* break_env = ssa_env_;
651 PushBlock(break_env);
652 SetEnv("block:start", Steal(break_env));
653 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100654 len = 1 + operand.length;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000655 break;
656 }
657 case kExprLoop: {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100658 BlockCountOperand operand(this, pc_);
659 if (operand.count < 1) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000660 Leaf(kAstStmt);
661 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100662 Shift(kAstEnd, operand.count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000663 // The break environment is the outer environment.
664 SsaEnv* break_env = ssa_env_;
665 PushBlock(break_env);
666 SsaEnv* cont_env = Steal(break_env);
667 // The continue environment is the inner environment.
Ben Murdochda12d292016-06-02 14:46:10 +0100668 PrepareForLoop(pc_, cont_env);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000669 SetEnv("loop:start", Split(cont_env));
670 if (ssa_env_->go()) ssa_env_->state = SsaEnv::kReached;
671 PushBlock(cont_env);
672 blocks_.back().stack_depth = -1; // no production for inner block.
673 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100674 len = 1 + operand.length;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000675 break;
676 }
677 case kExprIf:
678 Shift(kAstStmt, 2);
679 break;
680 case kExprIfElse:
681 Shift(kAstEnd, 3); // Result type is typeof(x) in {c ? x : y}.
682 break;
683 case kExprSelect:
684 Shift(kAstStmt, 3); // Result type is typeof(x) in {c ? x : y}.
685 break;
686 case kExprBr: {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100687 BreakDepthOperand operand(this, pc_);
688 if (Validate(pc_, operand, blocks_)) {
689 Shift(kAstEnd, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000690 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100691 len = 1 + operand.length;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000692 break;
693 }
694 case kExprBrIf: {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100695 BreakDepthOperand operand(this, pc_);
696 if (Validate(pc_, operand, blocks_)) {
697 Shift(kAstStmt, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000698 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100699 len = 1 + operand.length;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000700 break;
701 }
Ben Murdochda12d292016-06-02 14:46:10 +0100702 case kExprBrTable: {
703 BranchTableOperand operand(this, pc_);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100704 if (Validate(pc_, operand, blocks_.size())) {
Ben Murdochda12d292016-06-02 14:46:10 +0100705 Shift(kAstEnd, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000706 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100707 len = 1 + operand.length;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000708 break;
709 }
710 case kExprReturn: {
Ben Murdochda12d292016-06-02 14:46:10 +0100711 int count = static_cast<int>(sig_->return_count());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000712 if (count == 0) {
713 BUILD(Return, 0, builder_->Buffer(0));
714 ssa_env_->Kill();
715 Leaf(kAstEnd);
716 } else {
717 Shift(kAstEnd, count);
718 }
719 break;
720 }
721 case kExprUnreachable: {
722 BUILD0(Unreachable);
723 ssa_env_->Kill(SsaEnv::kControlEnd);
724 Leaf(kAstEnd, nullptr);
725 break;
726 }
727 case kExprI8Const: {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100728 ImmI8Operand operand(this, pc_);
729 Leaf(kAstI32, BUILD(Int32Constant, operand.value));
730 len = 1 + operand.length;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000731 break;
732 }
733 case kExprI32Const: {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100734 ImmI32Operand operand(this, pc_);
735 Leaf(kAstI32, BUILD(Int32Constant, operand.value));
736 len = 1 + operand.length;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000737 break;
738 }
739 case kExprI64Const: {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100740 ImmI64Operand operand(this, pc_);
741 Leaf(kAstI64, BUILD(Int64Constant, operand.value));
742 len = 1 + operand.length;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000743 break;
744 }
745 case kExprF32Const: {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100746 ImmF32Operand operand(this, pc_);
747 Leaf(kAstF32, BUILD(Float32Constant, operand.value));
748 len = 1 + operand.length;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000749 break;
750 }
751 case kExprF64Const: {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100752 ImmF64Operand operand(this, pc_);
753 Leaf(kAstF64, BUILD(Float64Constant, operand.value));
754 len = 1 + operand.length;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000755 break;
756 }
757 case kExprGetLocal: {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100758 LocalIndexOperand operand(this, pc_);
759 if (Validate(pc_, operand)) {
760 TFNode* val = build() ? ssa_env_->locals[operand.index] : nullptr;
761 Leaf(operand.type, val);
762 }
763 len = 1 + operand.length;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000764 break;
765 }
766 case kExprSetLocal: {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100767 LocalIndexOperand operand(this, pc_);
768 if (Validate(pc_, operand)) {
769 Shift(operand.type, 1);
770 }
771 len = 1 + operand.length;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000772 break;
773 }
774 case kExprLoadGlobal: {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100775 GlobalIndexOperand operand(this, pc_);
776 if (Validate(pc_, operand)) {
777 Leaf(operand.type, BUILD(LoadGlobal, operand.index));
778 }
779 len = 1 + operand.length;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000780 break;
781 }
782 case kExprStoreGlobal: {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100783 GlobalIndexOperand operand(this, pc_);
784 if (Validate(pc_, operand)) {
785 Shift(operand.type, 1);
786 }
787 len = 1 + operand.length;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000788 break;
789 }
790 case kExprI32LoadMem8S:
791 case kExprI32LoadMem8U:
792 case kExprI32LoadMem16S:
793 case kExprI32LoadMem16U:
794 case kExprI32LoadMem:
795 len = DecodeLoadMem(pc_, kAstI32);
796 break;
797 case kExprI64LoadMem8S:
798 case kExprI64LoadMem8U:
799 case kExprI64LoadMem16S:
800 case kExprI64LoadMem16U:
801 case kExprI64LoadMem32S:
802 case kExprI64LoadMem32U:
803 case kExprI64LoadMem:
804 len = DecodeLoadMem(pc_, kAstI64);
805 break;
806 case kExprF32LoadMem:
807 len = DecodeLoadMem(pc_, kAstF32);
808 break;
809 case kExprF64LoadMem:
810 len = DecodeLoadMem(pc_, kAstF64);
811 break;
812 case kExprI32StoreMem8:
813 case kExprI32StoreMem16:
814 case kExprI32StoreMem:
815 len = DecodeStoreMem(pc_, kAstI32);
816 break;
817 case kExprI64StoreMem8:
818 case kExprI64StoreMem16:
819 case kExprI64StoreMem32:
820 case kExprI64StoreMem:
821 len = DecodeStoreMem(pc_, kAstI64);
822 break;
823 case kExprF32StoreMem:
824 len = DecodeStoreMem(pc_, kAstF32);
825 break;
826 case kExprF64StoreMem:
827 len = DecodeStoreMem(pc_, kAstF64);
828 break;
829 case kExprMemorySize:
830 Leaf(kAstI32, BUILD(MemSize, 0));
831 break;
832 case kExprGrowMemory:
833 Shift(kAstI32, 1);
834 break;
835 case kExprCallFunction: {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100836 FunctionIndexOperand operand(this, pc_);
837 if (Validate(pc_, operand)) {
838 LocalType type = operand.sig->return_count() == 0
839 ? kAstStmt
840 : operand.sig->GetReturn();
841 Shift(type, static_cast<int>(operand.sig->parameter_count()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000842 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100843 len = 1 + operand.length;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000844 break;
845 }
846 case kExprCallIndirect: {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100847 SignatureIndexOperand operand(this, pc_);
848 if (Validate(pc_, operand)) {
849 LocalType type = operand.sig->return_count() == 0
850 ? kAstStmt
851 : operand.sig->GetReturn();
852 Shift(type, static_cast<int>(1 + operand.sig->parameter_count()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000853 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100854 len = 1 + operand.length;
855 break;
856 }
857 case kExprCallImport: {
858 ImportIndexOperand operand(this, pc_);
859 if (Validate(pc_, operand)) {
860 LocalType type = operand.sig->return_count() == 0
861 ? kAstStmt
862 : operand.sig->GetReturn();
863 Shift(type, static_cast<int>(operand.sig->parameter_count()));
864 }
865 len = 1 + operand.length;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000866 break;
867 }
Ben Murdochda12d292016-06-02 14:46:10 +0100868 case kExprDeclLocals:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000869 default:
870 error("Invalid opcode");
871 return;
872 }
873 pc_ += len;
874 if (pc_ >= limit_) {
875 // End of code reached or exceeded.
876 if (pc_ > limit_ && ok()) {
877 error("Beyond end of code");
878 }
879 return;
880 }
881 }
882 }
883
884 void PushBlock(SsaEnv* ssa_env) {
885 blocks_.push_back({ssa_env, static_cast<int>(stack_.size() - 1)});
886 }
887
888 int DecodeLoadMem(const byte* pc, LocalType type) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100889 MemoryAccessOperand operand(this, pc);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000890 Shift(type, 1);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100891 return 1 + operand.length;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000892 }
893
894 int DecodeStoreMem(const byte* pc, LocalType type) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100895 MemoryAccessOperand operand(this, pc);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000896 Shift(type, 2);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100897 return 1 + operand.length;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000898 }
899
900 void AddImplicitReturnAtEnd() {
Ben Murdochda12d292016-06-02 14:46:10 +0100901 int retcount = static_cast<int>(sig_->return_count());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000902 if (retcount == 0) {
903 BUILD0(ReturnVoid);
904 return;
905 }
906
907 if (static_cast<int>(trees_.size()) < retcount) {
908 error(limit_, nullptr,
909 "ImplicitReturn expects %d arguments, only %d remain", retcount,
910 static_cast<int>(trees_.size()));
911 return;
912 }
913
914 TRACE("wasm-decode implicit return of %d args\n", retcount);
915
916 TFNode** buffer = BUILD(Buffer, retcount);
917 for (int index = 0; index < retcount; index++) {
918 Tree* tree = trees_[trees_.size() - 1 - index];
919 if (buffer) buffer[index] = tree->node;
Ben Murdochda12d292016-06-02 14:46:10 +0100920 LocalType expected = sig_->GetReturn(index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000921 if (tree->type != expected) {
922 error(limit_, tree->pc,
923 "ImplicitReturn[%d] expected type %s, found %s of type %s", index,
924 WasmOpcodes::TypeName(expected),
925 WasmOpcodes::OpcodeName(tree->opcode()),
926 WasmOpcodes::TypeName(tree->type));
927 return;
928 }
929 }
930
931 BUILD(Return, retcount, buffer);
932 }
933
934 int baserel(const byte* ptr) {
935 return base_ ? static_cast<int>(ptr - base_) : 0;
936 }
937
938 int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); }
939
940 void Reduce(Production* p) {
941 WasmOpcode opcode = p->opcode();
942 TRACE("-----reduce module+%-6d %s func+%d: 0x%02x %s\n", baserel(p->pc()),
943 indentation(), startrel(p->pc()), opcode,
944 WasmOpcodes::OpcodeName(opcode));
945 FunctionSig* sig = WasmOpcodes::Signature(opcode);
946 if (sig) {
947 // A simple expression with a fixed signature.
948 TypeCheckLast(p, sig->GetParam(p->index - 1));
949 if (p->done() && build()) {
950 if (sig->parameter_count() == 2) {
951 p->tree->node = builder_->Binop(opcode, p->tree->children[0]->node,
952 p->tree->children[1]->node);
953 } else if (sig->parameter_count() == 1) {
954 p->tree->node = builder_->Unop(opcode, p->tree->children[0]->node);
955 } else {
956 UNREACHABLE();
957 }
958 }
959 return;
960 }
961
962 switch (opcode) {
963 case kExprBlock: {
964 if (p->done()) {
965 Block* last = &blocks_.back();
966 DCHECK_EQ(stack_.size() - 1, last->stack_depth);
967 // fallthrough with the last expression.
968 ReduceBreakToExprBlock(p, last);
969 SetEnv("block:end", last->ssa_env);
970 blocks_.pop_back();
971 }
972 break;
973 }
974 case kExprLoop: {
975 if (p->done()) {
976 // Pop the continue environment.
977 blocks_.pop_back();
978 // Get the break environment.
979 Block* last = &blocks_.back();
980 DCHECK_EQ(stack_.size() - 1, last->stack_depth);
981 // fallthrough with the last expression.
982 ReduceBreakToExprBlock(p, last);
983 SetEnv("loop:end", last->ssa_env);
984 blocks_.pop_back();
985 }
986 break;
987 }
988 case kExprIf: {
989 if (p->index == 1) {
990 // Condition done. Split environment for true branch.
991 TypeCheckLast(p, kAstI32);
992 SsaEnv* false_env = ssa_env_;
993 SsaEnv* true_env = Split(ssa_env_);
994 ifs_.push_back({nullptr, false_env, nullptr});
995 BUILD(Branch, p->last()->node, &true_env->control,
996 &false_env->control);
997 SetEnv("if:true", true_env);
998 } else if (p->index == 2) {
999 // True block done. Merge true and false environments.
1000 IfEnv* env = &ifs_.back();
1001 SsaEnv* merge = env->merge_env;
1002 if (merge->go()) {
1003 merge->state = SsaEnv::kReached;
1004 Goto(ssa_env_, merge);
1005 }
1006 SetEnv("if:merge", merge);
1007 ifs_.pop_back();
1008 }
1009 break;
1010 }
1011 case kExprIfElse: {
1012 if (p->index == 1) {
1013 // Condition done. Split environment for true and false branches.
1014 TypeCheckLast(p, kAstI32);
1015 SsaEnv* merge_env = ssa_env_;
1016 TFNode* if_true = nullptr;
1017 TFNode* if_false = nullptr;
1018 BUILD(Branch, p->last()->node, &if_true, &if_false);
1019 SsaEnv* false_env = Split(ssa_env_);
1020 SsaEnv* true_env = Steal(ssa_env_);
1021 false_env->control = if_false;
1022 true_env->control = if_true;
1023 ifs_.push_back({false_env, merge_env, nullptr});
1024 SetEnv("if_else:true", true_env);
1025 } else if (p->index == 2) {
1026 // True expr done.
1027 IfEnv* env = &ifs_.back();
1028 MergeIntoProduction(p, env->merge_env, p->last());
1029 // Switch to environment for false branch.
1030 SsaEnv* false_env = ifs_.back().false_env;
1031 SetEnv("if_else:false", false_env);
1032 } else if (p->index == 3) {
1033 // False expr done.
1034 IfEnv* env = &ifs_.back();
1035 MergeIntoProduction(p, env->merge_env, p->last());
1036 SetEnv("if_else:merge", env->merge_env);
1037 ifs_.pop_back();
1038 }
1039 break;
1040 }
1041 case kExprSelect: {
1042 if (p->index == 1) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001043 // True expression done.
1044 p->tree->type = p->last()->type;
1045 if (p->tree->type == kAstStmt) {
1046 error(p->pc(), p->tree->children[1]->pc,
1047 "select operand should be expression");
1048 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001049 } else if (p->index == 2) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001050 // False expression done.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001051 TypeCheckLast(p, p->tree->type);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001052 } else {
1053 // Condition done.
1054 DCHECK(p->done());
1055 TypeCheckLast(p, kAstI32);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001056 if (build()) {
1057 TFNode* controls[2];
Ben Murdoch097c5b22016-05-18 11:27:45 +01001058 builder_->Branch(p->tree->children[2]->node, &controls[0],
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001059 &controls[1]);
1060 TFNode* merge = builder_->Merge(2, controls);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001061 TFNode* vals[2] = {p->tree->children[0]->node,
1062 p->tree->children[1]->node};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001063 TFNode* phi = builder_->Phi(p->tree->type, 2, vals, merge);
1064 p->tree->node = phi;
1065 ssa_env_->control = merge;
1066 }
1067 }
1068 break;
1069 }
1070 case kExprBr: {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001071 BreakDepthOperand operand(this, p->pc());
1072 CHECK(Validate(p->pc(), operand, blocks_));
1073 ReduceBreakToExprBlock(p, operand.target);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001074 break;
1075 }
1076 case kExprBrIf: {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001077 if (p->done()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001078 TypeCheckLast(p, kAstI32);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001079 BreakDepthOperand operand(this, p->pc());
1080 CHECK(Validate(p->pc(), operand, blocks_));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001081 SsaEnv* fenv = ssa_env_;
1082 SsaEnv* tenv = Split(fenv);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001083 BUILD(Branch, p->tree->children[1]->node, &tenv->control,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001084 &fenv->control);
1085 ssa_env_ = tenv;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001086 ReduceBreakToExprBlock(p, operand.target, p->tree->children[0]);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001087 ssa_env_ = fenv;
1088 }
1089 break;
1090 }
Ben Murdochda12d292016-06-02 14:46:10 +01001091 case kExprBrTable: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001092 if (p->index == 1) {
1093 // Switch key finished.
1094 TypeCheckLast(p, kAstI32);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001095 if (failed()) break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001096
Ben Murdochda12d292016-06-02 14:46:10 +01001097 BranchTableOperand operand(this, p->pc());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001098 DCHECK(Validate(p->pc(), operand, blocks_.size()));
1099
Ben Murdochda12d292016-06-02 14:46:10 +01001100 // Build a switch only if it has more than just a default target.
1101 bool build_switch = operand.table_count > 0;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001102 TFNode* sw = nullptr;
Ben Murdochda12d292016-06-02 14:46:10 +01001103 if (build_switch) {
1104 sw = BUILD(Switch, operand.table_count + 1, p->last()->node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001105 }
1106
Ben Murdochda12d292016-06-02 14:46:10 +01001107 // Process the targets of the break table.
1108 SsaEnv* prev = ssa_env_;
1109 SsaEnv* copy = Steal(prev);
1110 for (uint32_t i = 0; i < operand.table_count + 1; i++) {
1111 uint32_t target = operand.read_entry(this, i);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001112 SsaEnv* env = copy;
1113 if (build_switch) {
Ben Murdochda12d292016-06-02 14:46:10 +01001114 ssa_env_ = env = Split(env);
1115 env->control = i == operand.table_count ? BUILD(IfDefault, sw)
1116 : BUILD(IfValue, i, sw);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001117 }
Ben Murdochda12d292016-06-02 14:46:10 +01001118 SsaEnv* tenv = blocks_[blocks_.size() - target - 1].ssa_env;
1119 Goto(env, tenv);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001120 }
Ben Murdochda12d292016-06-02 14:46:10 +01001121 ssa_env_ = prev;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001122 }
1123 break;
1124 }
1125 case kExprReturn: {
Ben Murdochda12d292016-06-02 14:46:10 +01001126 TypeCheckLast(p, sig_->GetReturn(p->index - 1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001127 if (p->done()) {
1128 if (build()) {
1129 int count = p->tree->count;
1130 TFNode** buffer = builder_->Buffer(count);
1131 for (int i = 0; i < count; i++) {
1132 buffer[i] = p->tree->children[i]->node;
1133 }
1134 BUILD(Return, count, buffer);
1135 }
1136 ssa_env_->Kill(SsaEnv::kControlEnd);
1137 }
1138 break;
1139 }
1140 case kExprSetLocal: {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001141 LocalIndexOperand operand(this, p->pc());
1142 CHECK(Validate(p->pc(), operand));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001143 Tree* val = p->last();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001144 if (operand.type == val->type) {
1145 if (build()) ssa_env_->locals[operand.index] = val->node;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001146 p->tree->node = val->node;
1147 } else {
1148 error(p->pc(), val->pc, "Typecheck failed in SetLocal");
1149 }
1150 break;
1151 }
1152 case kExprStoreGlobal: {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001153 GlobalIndexOperand operand(this, p->pc());
1154 CHECK(Validate(p->pc(), operand));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001155 Tree* val = p->last();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001156 if (operand.type == val->type) {
1157 BUILD(StoreGlobal, operand.index, val->node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001158 p->tree->node = val->node;
1159 } else {
1160 error(p->pc(), val->pc, "Typecheck failed in StoreGlobal");
1161 }
1162 break;
1163 }
1164
1165 case kExprI32LoadMem8S:
1166 return ReduceLoadMem(p, kAstI32, MachineType::Int8());
1167 case kExprI32LoadMem8U:
1168 return ReduceLoadMem(p, kAstI32, MachineType::Uint8());
1169 case kExprI32LoadMem16S:
1170 return ReduceLoadMem(p, kAstI32, MachineType::Int16());
1171 case kExprI32LoadMem16U:
1172 return ReduceLoadMem(p, kAstI32, MachineType::Uint16());
1173 case kExprI32LoadMem:
1174 return ReduceLoadMem(p, kAstI32, MachineType::Int32());
1175
1176 case kExprI64LoadMem8S:
1177 return ReduceLoadMem(p, kAstI64, MachineType::Int8());
1178 case kExprI64LoadMem8U:
1179 return ReduceLoadMem(p, kAstI64, MachineType::Uint8());
1180 case kExprI64LoadMem16S:
1181 return ReduceLoadMem(p, kAstI64, MachineType::Int16());
1182 case kExprI64LoadMem16U:
1183 return ReduceLoadMem(p, kAstI64, MachineType::Uint16());
1184 case kExprI64LoadMem32S:
1185 return ReduceLoadMem(p, kAstI64, MachineType::Int32());
1186 case kExprI64LoadMem32U:
1187 return ReduceLoadMem(p, kAstI64, MachineType::Uint32());
1188 case kExprI64LoadMem:
1189 return ReduceLoadMem(p, kAstI64, MachineType::Int64());
1190
1191 case kExprF32LoadMem:
1192 return ReduceLoadMem(p, kAstF32, MachineType::Float32());
1193
1194 case kExprF64LoadMem:
1195 return ReduceLoadMem(p, kAstF64, MachineType::Float64());
1196
1197 case kExprI32StoreMem8:
1198 return ReduceStoreMem(p, kAstI32, MachineType::Int8());
1199 case kExprI32StoreMem16:
1200 return ReduceStoreMem(p, kAstI32, MachineType::Int16());
1201 case kExprI32StoreMem:
1202 return ReduceStoreMem(p, kAstI32, MachineType::Int32());
1203
1204 case kExprI64StoreMem8:
1205 return ReduceStoreMem(p, kAstI64, MachineType::Int8());
1206 case kExprI64StoreMem16:
1207 return ReduceStoreMem(p, kAstI64, MachineType::Int16());
1208 case kExprI64StoreMem32:
1209 return ReduceStoreMem(p, kAstI64, MachineType::Int32());
1210 case kExprI64StoreMem:
1211 return ReduceStoreMem(p, kAstI64, MachineType::Int64());
1212
1213 case kExprF32StoreMem:
1214 return ReduceStoreMem(p, kAstF32, MachineType::Float32());
1215
1216 case kExprF64StoreMem:
1217 return ReduceStoreMem(p, kAstF64, MachineType::Float64());
1218
1219 case kExprGrowMemory:
1220 TypeCheckLast(p, kAstI32);
1221 // TODO(titzer): build node for GrowMemory
1222 p->tree->node = BUILD(Int32Constant, 0);
1223 return;
1224
1225 case kExprCallFunction: {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001226 FunctionIndexOperand operand(this, p->pc());
1227 CHECK(Validate(p->pc(), operand));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001228 if (p->index > 0) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001229 TypeCheckLast(p, operand.sig->GetParam(p->index - 1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001230 }
1231 if (p->done() && build()) {
1232 uint32_t count = p->tree->count + 1;
1233 TFNode** buffer = builder_->Buffer(count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001234 buffer[0] = nullptr; // reserved for code object.
1235 for (uint32_t i = 1; i < count; i++) {
1236 buffer[i] = p->tree->children[i - 1]->node;
1237 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001238 p->tree->node = builder_->CallDirect(operand.index, buffer);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001239 }
1240 break;
1241 }
1242 case kExprCallIndirect: {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001243 SignatureIndexOperand operand(this, p->pc());
1244 CHECK(Validate(p->pc(), operand));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001245 if (p->index == 1) {
1246 TypeCheckLast(p, kAstI32);
1247 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001248 TypeCheckLast(p, operand.sig->GetParam(p->index - 2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001249 }
1250 if (p->done() && build()) {
1251 uint32_t count = p->tree->count;
1252 TFNode** buffer = builder_->Buffer(count);
1253 for (uint32_t i = 0; i < count; i++) {
1254 buffer[i] = p->tree->children[i]->node;
1255 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001256 p->tree->node = builder_->CallIndirect(operand.index, buffer);
1257 }
1258 break;
1259 }
1260 case kExprCallImport: {
1261 ImportIndexOperand operand(this, p->pc());
1262 CHECK(Validate(p->pc(), operand));
1263 if (p->index > 0) {
1264 TypeCheckLast(p, operand.sig->GetParam(p->index - 1));
1265 }
1266 if (p->done() && build()) {
1267 uint32_t count = p->tree->count + 1;
1268 TFNode** buffer = builder_->Buffer(count);
1269 buffer[0] = nullptr; // reserved for code object.
1270 for (uint32_t i = 1; i < count; i++) {
1271 buffer[i] = p->tree->children[i - 1]->node;
1272 }
1273 p->tree->node = builder_->CallImport(operand.index, buffer);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001274 }
1275 break;
1276 }
1277 default:
1278 break;
1279 }
1280 }
1281
1282 void ReduceBreakToExprBlock(Production* p, Block* block) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001283 ReduceBreakToExprBlock(p, block, p->tree->count > 0 ? p->last() : nullptr);
1284 }
1285
1286 void ReduceBreakToExprBlock(Production* p, Block* block, Tree* val) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001287 if (block->stack_depth < 0) {
1288 // This is the inner loop block, which does not have a value.
1289 Goto(ssa_env_, block->ssa_env);
1290 } else {
1291 // Merge the value into the production for the block.
1292 Production* bp = &stack_[block->stack_depth];
Ben Murdoch097c5b22016-05-18 11:27:45 +01001293 MergeIntoProduction(bp, block->ssa_env, val);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001294 }
1295 }
1296
1297 void MergeIntoProduction(Production* p, SsaEnv* target, Tree* expr) {
1298 if (!ssa_env_->go()) return;
1299
1300 bool first = target->state == SsaEnv::kUnreachable;
1301 Goto(ssa_env_, target);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001302 if (expr == nullptr || expr->type == kAstEnd) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001303
1304 if (first) {
1305 // first merge to this environment; set the type and the node.
1306 p->tree->type = expr->type;
1307 p->tree->node = expr->node;
1308 } else {
1309 // merge with the existing value for this block.
1310 LocalType type = p->tree->type;
1311 if (expr->type != type) {
1312 type = kAstStmt;
1313 p->tree->type = kAstStmt;
1314 p->tree->node = nullptr;
1315 } else if (type != kAstStmt) {
1316 p->tree->node = CreateOrMergeIntoPhi(type, target->control,
1317 p->tree->node, expr->node);
1318 }
1319 }
1320 }
1321
1322 void ReduceLoadMem(Production* p, LocalType type, MachineType mem_type) {
1323 DCHECK_EQ(1, p->index);
1324 TypeCheckLast(p, kAstI32); // index
1325 if (build()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001326 MemoryAccessOperand operand(this, p->pc());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001327 p->tree->node =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001328 builder_->LoadMem(type, mem_type, p->last()->node, operand.offset);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001329 }
1330 }
1331
1332 void ReduceStoreMem(Production* p, LocalType type, MachineType mem_type) {
1333 if (p->index == 1) {
1334 TypeCheckLast(p, kAstI32); // index
1335 } else {
1336 DCHECK_EQ(2, p->index);
1337 TypeCheckLast(p, type);
1338 if (build()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001339 MemoryAccessOperand operand(this, p->pc());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001340 TFNode* val = p->tree->children[1]->node;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001341 builder_->StoreMem(mem_type, p->tree->children[0]->node, operand.offset,
1342 val);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001343 p->tree->node = val;
1344 }
1345 }
1346 }
1347
1348 void TypeCheckLast(Production* p, LocalType expected) {
1349 LocalType result = p->last()->type;
1350 if (result == expected) return;
1351 if (result == kAstEnd) return;
1352 if (expected != kAstStmt) {
1353 error(p->pc(), p->last()->pc,
1354 "%s[%d] expected type %s, found %s of type %s",
1355 WasmOpcodes::OpcodeName(p->opcode()), p->index - 1,
1356 WasmOpcodes::TypeName(expected),
1357 WasmOpcodes::OpcodeName(p->last()->opcode()),
1358 WasmOpcodes::TypeName(p->last()->type));
1359 }
1360 }
1361
1362 void SetEnv(const char* reason, SsaEnv* env) {
Ben Murdochda12d292016-06-02 14:46:10 +01001363#if DEBUG
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001364 TRACE(" env = %p, block depth = %d, reason = %s", static_cast<void*>(env),
1365 static_cast<int>(blocks_.size()), reason);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001366 if (FLAG_trace_wasm_decoder && env && env->control) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001367 TRACE(", control = ");
1368 compiler::WasmGraphBuilder::PrintDebugName(env->control);
1369 }
1370 TRACE("\n");
Ben Murdochda12d292016-06-02 14:46:10 +01001371#endif
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001372 ssa_env_ = env;
1373 if (builder_) {
1374 builder_->set_control_ptr(&env->control);
1375 builder_->set_effect_ptr(&env->effect);
1376 }
1377 }
1378
1379 void Goto(SsaEnv* from, SsaEnv* to) {
1380 DCHECK_NOT_NULL(to);
1381 if (!from->go()) return;
1382 switch (to->state) {
1383 case SsaEnv::kUnreachable: { // Overwrite destination.
1384 to->state = SsaEnv::kReached;
1385 to->locals = from->locals;
1386 to->control = from->control;
1387 to->effect = from->effect;
1388 break;
1389 }
1390 case SsaEnv::kReached: { // Create a new merge.
1391 to->state = SsaEnv::kMerged;
1392 if (!builder_) break;
1393 // Merge control.
1394 TFNode* controls[] = {to->control, from->control};
1395 TFNode* merge = builder_->Merge(2, controls);
1396 to->control = merge;
1397 // Merge effects.
1398 if (from->effect != to->effect) {
1399 TFNode* effects[] = {to->effect, from->effect, merge};
1400 to->effect = builder_->EffectPhi(2, effects, merge);
1401 }
1402 // Merge SSA values.
1403 for (int i = EnvironmentCount() - 1; i >= 0; i--) {
1404 TFNode* a = to->locals[i];
1405 TFNode* b = from->locals[i];
1406 if (a != b) {
1407 TFNode* vals[] = {a, b};
Ben Murdochda12d292016-06-02 14:46:10 +01001408 to->locals[i] = builder_->Phi(local_type_vec_[i], 2, vals, merge);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001409 }
1410 }
1411 break;
1412 }
1413 case SsaEnv::kMerged: {
1414 if (!builder_) break;
1415 TFNode* merge = to->control;
1416 // Extend the existing merge.
1417 builder_->AppendToMerge(merge, from->control);
1418 // Merge effects.
1419 if (builder_->IsPhiWithMerge(to->effect, merge)) {
1420 builder_->AppendToPhi(merge, to->effect, from->effect);
1421 } else if (to->effect != from->effect) {
1422 uint32_t count = builder_->InputCount(merge);
1423 TFNode** effects = builder_->Buffer(count);
1424 for (uint32_t j = 0; j < count - 1; j++) {
1425 effects[j] = to->effect;
1426 }
1427 effects[count - 1] = from->effect;
1428 to->effect = builder_->EffectPhi(count, effects, merge);
1429 }
1430 // Merge locals.
1431 for (int i = EnvironmentCount() - 1; i >= 0; i--) {
1432 TFNode* tnode = to->locals[i];
1433 TFNode* fnode = from->locals[i];
1434 if (builder_->IsPhiWithMerge(tnode, merge)) {
1435 builder_->AppendToPhi(merge, tnode, fnode);
1436 } else if (tnode != fnode) {
1437 uint32_t count = builder_->InputCount(merge);
1438 TFNode** vals = builder_->Buffer(count);
1439 for (uint32_t j = 0; j < count - 1; j++) {
1440 vals[j] = tnode;
1441 }
1442 vals[count - 1] = fnode;
Ben Murdochda12d292016-06-02 14:46:10 +01001443 to->locals[i] =
1444 builder_->Phi(local_type_vec_[i], count, vals, merge);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001445 }
1446 }
1447 break;
1448 }
1449 default:
1450 UNREACHABLE();
1451 }
1452 return from->Kill();
1453 }
1454
1455 TFNode* CreateOrMergeIntoPhi(LocalType type, TFNode* merge, TFNode* tnode,
1456 TFNode* fnode) {
1457 if (builder_->IsPhiWithMerge(tnode, merge)) {
1458 builder_->AppendToPhi(merge, tnode, fnode);
1459 } else if (tnode != fnode) {
1460 uint32_t count = builder_->InputCount(merge);
1461 TFNode** vals = builder_->Buffer(count);
1462 for (uint32_t j = 0; j < count - 1; j++) vals[j] = tnode;
1463 vals[count - 1] = fnode;
1464 return builder_->Phi(type, count, vals, merge);
1465 }
1466 return tnode;
1467 }
1468
Ben Murdochda12d292016-06-02 14:46:10 +01001469 void PrepareForLoop(const byte* pc, SsaEnv* env) {
1470 if (!env->go()) return;
1471 env->state = SsaEnv::kMerged;
1472 if (!builder_) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001473
Ben Murdochda12d292016-06-02 14:46:10 +01001474 env->control = builder_->Loop(env->control);
1475 env->effect = builder_->EffectPhi(1, &env->effect, env->control);
1476 builder_->Terminate(env->effect, env->control);
1477 if (FLAG_wasm_loop_assignment_analysis) {
1478 BitVector* assigned = AnalyzeLoopAssignment(pc);
1479 if (assigned != nullptr) {
1480 // Only introduce phis for variables assigned in this loop.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001481 for (int i = EnvironmentCount() - 1; i >= 0; i--) {
Ben Murdochda12d292016-06-02 14:46:10 +01001482 if (!assigned->Contains(i)) continue;
1483 env->locals[i] = builder_->Phi(local_type_vec_[i], 1, &env->locals[i],
1484 env->control);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001485 }
Ben Murdochda12d292016-06-02 14:46:10 +01001486 return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001487 }
1488 }
Ben Murdochda12d292016-06-02 14:46:10 +01001489
1490 // Conservatively introduce phis for all local variables.
1491 for (int i = EnvironmentCount() - 1; i >= 0; i--) {
1492 env->locals[i] =
1493 builder_->Phi(local_type_vec_[i], 1, &env->locals[i], env->control);
1494 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001495 }
1496
1497 // Create a complete copy of the {from}.
1498 SsaEnv* Split(SsaEnv* from) {
1499 DCHECK_NOT_NULL(from);
1500 SsaEnv* result = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
1501 size_t size = sizeof(TFNode*) * EnvironmentCount();
1502 result->control = from->control;
1503 result->effect = from->effect;
1504 result->state = from->state == SsaEnv::kUnreachable ? SsaEnv::kUnreachable
1505 : SsaEnv::kReached;
1506
1507 if (from->go()) {
1508 result->state = SsaEnv::kReached;
1509 result->locals =
1510 size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr;
1511 memcpy(result->locals, from->locals, size);
1512 } else {
1513 result->state = SsaEnv::kUnreachable;
1514 result->locals = nullptr;
1515 }
1516
1517 return result;
1518 }
1519
1520 // Create a copy of {from} that steals its state and leaves {from}
1521 // unreachable.
1522 SsaEnv* Steal(SsaEnv* from) {
1523 DCHECK_NOT_NULL(from);
1524 if (!from->go()) return UnreachableEnv();
1525 SsaEnv* result = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
1526 result->state = SsaEnv::kReached;
1527 result->locals = from->locals;
1528 result->control = from->control;
1529 result->effect = from->effect;
1530 from->Kill(SsaEnv::kUnreachable);
1531 return result;
1532 }
1533
1534 // Create an unreachable environment.
1535 SsaEnv* UnreachableEnv() {
1536 SsaEnv* result = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
1537 result->state = SsaEnv::kUnreachable;
1538 result->control = nullptr;
1539 result->effect = nullptr;
1540 result->locals = nullptr;
1541 return result;
1542 }
1543
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001544 int EnvironmentCount() {
Ben Murdochda12d292016-06-02 14:46:10 +01001545 if (builder_) return static_cast<int>(local_type_vec_.size());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001546 return 0; // if we aren't building a graph, don't bother with SSA renaming.
1547 }
1548
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001549 virtual void onFirstError() {
1550 limit_ = start_; // Terminate decoding loop.
1551 builder_ = nullptr; // Don't build any more nodes.
1552#if DEBUG
1553 PrintStackForDebugging();
1554#endif
1555 }
1556
1557#if DEBUG
1558 void PrintStackForDebugging() { PrintProduction(0); }
1559
1560 void PrintProduction(size_t depth) {
1561 if (depth >= stack_.size()) return;
1562 Production* p = &stack_[depth];
1563 for (size_t d = 0; d < depth; d++) PrintF(" ");
1564
1565 PrintF("@%d %s [%d]\n", static_cast<int>(p->tree->pc - start_),
1566 WasmOpcodes::OpcodeName(p->opcode()), p->tree->count);
1567 for (int i = 0; i < p->index; i++) {
1568 Tree* child = p->tree->children[i];
1569 for (size_t d = 0; d <= depth; d++) PrintF(" ");
1570 PrintF("@%d %s [%d]", static_cast<int>(child->pc - start_),
1571 WasmOpcodes::OpcodeName(child->opcode()), child->count);
1572 if (child->node) {
1573 PrintF(" => TF");
1574 compiler::WasmGraphBuilder::PrintDebugName(child->node);
1575 }
1576 PrintF("\n");
1577 }
1578 PrintProduction(depth + 1);
1579 }
1580#endif
Ben Murdochda12d292016-06-02 14:46:10 +01001581
1582 BitVector* AnalyzeLoopAssignment(const byte* pc) {
1583 if (pc >= limit_) return nullptr;
1584 if (*pc != kExprLoop) return nullptr;
1585
1586 BitVector* assigned =
1587 new (zone_) BitVector(static_cast<int>(total_locals_), zone_);
1588 // Keep a stack to model the nesting of expressions.
1589 std::vector<int> arity_stack;
1590 arity_stack.push_back(OpcodeArity(pc));
1591 pc += OpcodeLength(pc);
1592
1593 // Iteratively process all AST nodes nested inside the loop.
1594 while (pc < limit_) {
1595 WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
1596 int arity = 0;
1597 int length = 1;
1598 int assigned_index = -1;
1599 if (opcode == kExprSetLocal) {
1600 LocalIndexOperand operand(this, pc);
1601 if (assigned->length() > 0 &&
1602 static_cast<int>(operand.index) < assigned->length()) {
1603 // Unverified code might have an out-of-bounds index.
1604 // Ignore out-of-bounds indices, as the main verification will fail.
1605 assigned->Add(operand.index);
1606 assigned_index = operand.index;
1607 }
1608 arity = 1;
1609 length = 1 + operand.length;
1610 } else {
1611 arity = OpcodeArity(pc);
1612 length = OpcodeLength(pc);
1613 }
1614
1615 TRACE("loop-assign module+%-6d %s func+%d: 0x%02x %s", baserel(pc),
1616 indentation(), startrel(pc), opcode,
1617 WasmOpcodes::OpcodeName(opcode));
1618
1619 if (assigned_index >= 0) {
1620 TRACE(" (assigned local #%d)\n", assigned_index);
1621 } else {
1622 TRACE("\n");
1623 }
1624
1625 pc += length;
1626 arity_stack.push_back(arity);
1627 while (arity_stack.back() == 0) {
1628 arity_stack.pop_back();
1629 if (arity_stack.empty()) return assigned; // reached end of loop
1630 arity_stack.back()--;
1631 }
1632 }
1633 return assigned;
1634 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001635};
1636
Ben Murdochda12d292016-06-02 14:46:10 +01001637bool DecodeLocalDecls(AstLocalDecls& decls, const byte* start,
1638 const byte* end) {
1639 base::AccountingAllocator allocator;
1640 Zone tmp(&allocator);
1641 FunctionBody body = {nullptr, nullptr, nullptr, start, end};
1642 SR_WasmDecoder decoder(&tmp, nullptr, body);
1643 return decoder.DecodeLocalDecls(decls);
1644}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001645
Ben Murdochda12d292016-06-02 14:46:10 +01001646TreeResult VerifyWasmCode(base::AccountingAllocator* allocator,
1647 FunctionBody& body) {
1648 Zone zone(allocator);
1649 SR_WasmDecoder decoder(&zone, nullptr, body);
1650 TreeResult result = decoder.Decode();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001651 return result;
1652}
1653
Ben Murdochda12d292016-06-02 14:46:10 +01001654TreeResult BuildTFGraph(base::AccountingAllocator* allocator,
1655 TFBuilder* builder, FunctionBody& body) {
1656 Zone zone(allocator);
1657 SR_WasmDecoder decoder(&zone, builder, body);
1658 TreeResult result = decoder.Decode();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001659 return result;
1660}
1661
1662
1663std::ostream& operator<<(std::ostream& os, const Tree& tree) {
1664 if (tree.pc == nullptr) {
1665 os << "null";
1666 return os;
1667 }
1668 PrintF("%s", WasmOpcodes::OpcodeName(tree.opcode()));
1669 if (tree.count > 0) os << "(";
1670 for (uint32_t i = 0; i < tree.count; i++) {
1671 if (i > 0) os << ", ";
1672 os << *tree.children[i];
1673 }
1674 if (tree.count > 0) os << ")";
1675 return os;
1676}
1677
1678
1679ReadUnsignedLEB128ErrorCode ReadUnsignedLEB128Operand(const byte* pc,
1680 const byte* limit,
1681 int* length,
1682 uint32_t* result) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001683 Decoder decoder(pc, limit);
1684 *result = decoder.checked_read_u32v(pc, 0, length);
1685 if (decoder.ok()) return kNoError;
1686 return (limit - pc) > 1 ? kInvalidLEB128 : kMissingLEB128;
1687}
1688
1689int OpcodeLength(const byte* pc, const byte* end) {
Ben Murdochda12d292016-06-02 14:46:10 +01001690 WasmDecoder decoder(nullptr, nullptr, pc, end);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001691 return decoder.OpcodeLength(pc);
1692}
1693
Ben Murdochda12d292016-06-02 14:46:10 +01001694int OpcodeArity(ModuleEnv* module, FunctionSig* sig, const byte* pc,
1695 const byte* end) {
1696 WasmDecoder decoder(module, sig, pc, end);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001697 return decoder.OpcodeArity(pc);
1698}
1699
Ben Murdochda12d292016-06-02 14:46:10 +01001700void PrintAst(base::AccountingAllocator* allocator, FunctionBody& body) {
1701 Zone zone(allocator);
1702 SR_WasmDecoder decoder(&zone, nullptr, body);
1703
1704 OFStream os(stdout);
1705
1706 // Print the function signature.
1707 if (body.sig) {
1708 os << "// signature: " << *body.sig << std::endl;
1709 }
1710
1711 // Print the local declarations.
1712 AstLocalDecls decls(&zone);
1713 decoder.DecodeLocalDecls(decls);
1714 const byte* pc = decoder.pc();
1715 if (body.start != decoder.pc()) {
1716 printf("// locals:");
1717 for (auto p : decls.local_types) {
1718 LocalType type = p.first;
1719 uint32_t count = p.second;
1720 os << " " << count << " " << WasmOpcodes::TypeName(type);
1721 }
1722 os << std::endl;
1723
1724 for (const byte* locals = body.start; locals < pc; locals++) {
1725 printf(" 0x%02x,", *locals);
1726 }
1727 printf("\n");
1728 }
1729
1730 printf("// body: \n");
Ben Murdoch097c5b22016-05-18 11:27:45 +01001731 std::vector<int> arity_stack;
Ben Murdochda12d292016-06-02 14:46:10 +01001732 while (pc < body.end) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001733 int arity = decoder.OpcodeArity(pc);
1734 size_t length = decoder.OpcodeLength(pc);
1735
1736 for (auto arity : arity_stack) {
1737 printf(" ");
1738 USE(arity);
1739 }
1740
1741 WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
1742 printf("k%s,", WasmOpcodes::OpcodeName(opcode));
1743
1744 for (size_t i = 1; i < length; i++) {
1745 printf(" 0x%02x,", pc[i]);
1746 }
Ben Murdochda12d292016-06-02 14:46:10 +01001747
1748 if (body.module) {
1749 switch (opcode) {
1750 case kExprCallIndirect: {
1751 SignatureIndexOperand operand(&decoder, pc);
1752 if (decoder.Validate(pc, operand)) {
1753 os << " // sig #" << operand.index << ": " << *operand.sig;
1754 }
1755 break;
1756 }
1757 case kExprCallImport: {
1758 ImportIndexOperand operand(&decoder, pc);
1759 if (decoder.Validate(pc, operand)) {
1760 os << " // import #" << operand.index << ": " << *operand.sig;
1761 }
1762 break;
1763 }
1764 case kExprCallFunction: {
1765 FunctionIndexOperand operand(&decoder, pc);
1766 if (decoder.Validate(pc, operand)) {
1767 os << " // function #" << operand.index << ": " << *operand.sig;
1768 }
1769 break;
1770 }
1771 default:
1772 break;
1773 }
1774 }
1775
Ben Murdoch097c5b22016-05-18 11:27:45 +01001776 pc += length;
1777 printf("\n");
1778
1779 arity_stack.push_back(arity);
1780 while (arity_stack.back() == 0) {
1781 arity_stack.pop_back();
1782 if (arity_stack.empty()) break;
1783 arity_stack.back()--;
1784 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001785 }
1786}
1787
Ben Murdochda12d292016-06-02 14:46:10 +01001788BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals,
Ben Murdoch097c5b22016-05-18 11:27:45 +01001789 const byte* start, const byte* end) {
Ben Murdochda12d292016-06-02 14:46:10 +01001790 FunctionBody body = {nullptr, nullptr, nullptr, start, end};
1791 SR_WasmDecoder decoder(zone, nullptr, body);
1792 return decoder.AnalyzeLoopAssignmentForTesting(start, num_locals);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001793}
1794
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001795} // namespace wasm
1796} // namespace internal
1797} // namespace v8