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

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, 7 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
« no previous file with comments | « src/wasm/ast-decoder.h ('k') | src/wasm/encoder.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 SsaEnv* end_env; // end environment for the construct.
81 SsaEnv* false_env; // false environment (only for if).
82 TFNode* node; // result node for the construct.
83 LocalType type; // result type for the construct.
84 bool is_loop; // true if this is the inner label of a loop.
85
86 bool is_if() { return *pc == kExprIf; }
87 bool is_block() { return *pc == kExprBlock; }
88 }; 88 };
89 89
90 // Macros that build nodes only if there is a graph and the current SSA 90 // 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 91 // environment is reachable from start. This avoids problems with malformed
92 // TF graphs when decoding inputs that have unreachable code. 92 // TF graphs when decoding inputs that have unreachable code.
93 #define BUILD(func, ...) (build() ? builder_->func(__VA_ARGS__) : nullptr) 93 #define BUILD(func, ...) (build() ? builder_->func(__VA_ARGS__) : nullptr)
94 #define BUILD0(func) (build() ? builder_->func() : nullptr) 94 #define BUILD0(func) (build() ? builder_->func() : nullptr)
95 95
96 // Generic Wasm bytecode decoder with utilities for decoding operands, 96 // Generic Wasm bytecode decoder with utilities for decoding operands,
97 // lengths, etc. 97 // lengths, etc.
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 ModuleEnv* m = module_; 150 ModuleEnv* m = module_;
151 if (m && m->module && operand.index < m->module->globals.size()) { 151 if (m && m->module && operand.index < m->module->globals.size()) {
152 operand.machine_type = m->module->globals[operand.index].type; 152 operand.machine_type = m->module->globals[operand.index].type;
153 operand.type = WasmOpcodes::LocalTypeFor(operand.machine_type); 153 operand.type = WasmOpcodes::LocalTypeFor(operand.machine_type);
154 return true; 154 return true;
155 } 155 }
156 error(pc, pc + 1, "invalid global index"); 156 error(pc, pc + 1, "invalid global index");
157 return false; 157 return false;
158 } 158 }
159 159
160 inline bool Validate(const byte* pc, FunctionIndexOperand& operand) { 160 inline bool Validate(const byte* pc, CallFunctionOperand& operand) {
161 ModuleEnv* m = module_; 161 ModuleEnv* m = module_;
162 if (m && m->module && operand.index < m->module->functions.size()) { 162 if (m && m->module && operand.index < m->module->functions.size()) {
163 operand.sig = m->module->functions[operand.index].sig; 163 operand.sig = m->module->functions[operand.index].sig;
164 uint32_t expected = static_cast<uint32_t>(operand.sig->parameter_count());
165 if (operand.arity != expected) {
166 error(pc, pc + 1,
167 "arity mismatch in direct function call (expected %u, got %u)",
168 expected, operand.arity);
169 return false;
170 }
164 return true; 171 return true;
165 } 172 }
166 error(pc, pc + 1, "invalid function index"); 173 error(pc, pc + 1, "invalid function index");
167 return false; 174 return false;
168 } 175 }
169 176
170 inline bool Validate(const byte* pc, SignatureIndexOperand& operand) { 177 inline bool Validate(const byte* pc, CallIndirectOperand& operand) {
171 ModuleEnv* m = module_; 178 ModuleEnv* m = module_;
172 if (m && m->module && operand.index < m->module->signatures.size()) { 179 if (m && m->module && operand.index < m->module->signatures.size()) {
173 operand.sig = m->module->signatures[operand.index]; 180 operand.sig = m->module->signatures[operand.index];
181 uint32_t expected = static_cast<uint32_t>(operand.sig->parameter_count());
182 if (operand.arity != expected) {
183 error(pc, pc + 1,
184 "arity mismatch in indirect function call (expected %u, got %u)",
185 expected, operand.arity);
186 return false;
187 }
174 return true; 188 return true;
175 } 189 }
176 error(pc, pc + 1, "invalid signature index"); 190 error(pc, pc + 1, "invalid signature index");
177 return false; 191 return false;
178 } 192 }
179 193
180 inline bool Validate(const byte* pc, ImportIndexOperand& operand) { 194 inline bool Validate(const byte* pc, CallImportOperand& operand) {
181 ModuleEnv* m = module_; 195 ModuleEnv* m = module_;
182 if (m && m->module && operand.index < m->module->import_table.size()) { 196 if (m && m->module && operand.index < m->module->import_table.size()) {
183 operand.sig = m->module->import_table[operand.index].sig; 197 operand.sig = m->module->import_table[operand.index].sig;
198 uint32_t expected = static_cast<uint32_t>(operand.sig->parameter_count());
199 if (operand.arity != expected) {
200 error(pc, pc + 1, "arity mismatch in import call (expected %u, got %u)",
201 expected, operand.arity);
202 return false;
203 }
184 return true; 204 return true;
185 } 205 }
186 error(pc, pc + 1, "invalid signature index"); 206 error(pc, pc + 1, "invalid signature index");
187 return false; 207 return false;
188 } 208 }
189 209
190 inline bool Validate(const byte* pc, BreakDepthOperand& operand, 210 inline bool Validate(const byte* pc, BreakDepthOperand& operand,
191 ZoneVector<Block>& blocks) { 211 ZoneVector<Control>& control) {
192 if (operand.depth < blocks.size()) { 212 if (operand.arity > 1) {
193 operand.target = &blocks[blocks.size() - operand.depth - 1]; 213 error(pc, pc + 1, "invalid arity for br or br_if");
214 return false;
215 }
216 if (operand.depth < control.size()) {
217 operand.target = &control[control.size() - operand.depth - 1];
194 return true; 218 return true;
195 } 219 }
196 error(pc, pc + 1, "invalid break depth"); 220 error(pc, pc + 1, "invalid break depth");
197 return false; 221 return false;
198 } 222 }
199 223
200 bool Validate(const byte* pc, BranchTableOperand& operand, 224 bool Validate(const byte* pc, BranchTableOperand& operand,
201 size_t block_depth) { 225 size_t block_depth) {
226 if (operand.arity > 1) {
227 error(pc, pc + 1, "invalid arity for break");
228 return false;
229 }
202 // Verify table. 230 // Verify table.
203 for (uint32_t i = 0; i < operand.table_count + 1; i++) { 231 for (uint32_t i = 0; i < operand.table_count + 1; i++) {
204 uint32_t target = operand.read_entry(this, i); 232 uint32_t target = operand.read_entry(this, i);
205 if (target >= block_depth) { 233 if (target >= block_depth) {
206 error(operand.table + i * 2, "improper branch in br_table"); 234 error(operand.table + i * 2, "improper branch in br_table");
207 return false; 235 return false;
208 } 236 }
209 } 237 }
210 return true; 238 return true;
211 } 239 }
(...skipping 10 matching lines...) Expand all
222 switch (static_cast<WasmOpcode>(*pc)) { 250 switch (static_cast<WasmOpcode>(*pc)) {
223 case kExprI8Const: 251 case kExprI8Const:
224 case kExprI32Const: 252 case kExprI32Const:
225 case kExprI64Const: 253 case kExprI64Const:
226 case kExprF64Const: 254 case kExprF64Const:
227 case kExprF32Const: 255 case kExprF32Const:
228 case kExprGetLocal: 256 case kExprGetLocal:
229 case kExprLoadGlobal: 257 case kExprLoadGlobal:
230 case kExprNop: 258 case kExprNop:
231 case kExprUnreachable: 259 case kExprUnreachable:
260 case kExprEnd:
261 case kExprBlock:
262 case kExprLoop:
232 return 0; 263 return 0;
233 264
234 case kExprBr:
235 case kExprStoreGlobal: 265 case kExprStoreGlobal:
236 case kExprSetLocal: 266 case kExprSetLocal:
267 case kExprElse:
237 return 1; 268 return 1;
238 269
270 case kExprBr: {
271 BreakDepthOperand operand(this, pc);
272 return operand.arity;
273 }
274 case kExprBrIf: {
275 BreakDepthOperand operand(this, pc);
276 return 1 + operand.arity;
277 }
278 case kExprBrTable: {
279 BranchTableOperand operand(this, pc);
280 return 1 + operand.arity;
281 }
282
239 case kExprIf: 283 case kExprIf:
240 case kExprBrIf: 284 return 1;
241 return 2;
242 case kExprIfElse:
243 case kExprSelect: 285 case kExprSelect:
244 return 3; 286 return 3;
245 287
246 case kExprBlock:
247 case kExprLoop: {
248 BlockCountOperand operand(this, pc);
249 return operand.count;
250 }
251
252 case kExprCallFunction: { 288 case kExprCallFunction: {
253 FunctionIndexOperand operand(this, pc); 289 CallFunctionOperand operand(this, pc);
254 return static_cast<int>( 290 return static_cast<int>(
255 module_->GetFunctionSignature(operand.index)->parameter_count()); 291 module_->GetFunctionSignature(operand.index)->parameter_count());
256 } 292 }
257 case kExprCallIndirect: { 293 case kExprCallIndirect: {
258 SignatureIndexOperand operand(this, pc); 294 CallIndirectOperand operand(this, pc);
259 return 1 + static_cast<int>( 295 return 1 + static_cast<int>(
260 module_->GetSignature(operand.index)->parameter_count()); 296 module_->GetSignature(operand.index)->parameter_count());
261 } 297 }
262 case kExprCallImport: { 298 case kExprCallImport: {
263 ImportIndexOperand operand(this, pc); 299 CallImportOperand operand(this, pc);
264 return static_cast<int>( 300 return static_cast<int>(
265 module_->GetImportSignature(operand.index)->parameter_count()); 301 module_->GetImportSignature(operand.index)->parameter_count());
266 } 302 }
267 case kExprReturn: { 303 case kExprReturn: {
268 return static_cast<int>(sig_->return_count()); 304 return static_cast<int>(sig_->return_count());
269 } 305 }
270 case kExprBrTable: {
271 return 1;
272 }
273 306
274 #define DECLARE_OPCODE_CASE(name, opcode, sig) \ 307 #define DECLARE_OPCODE_CASE(name, opcode, sig) \
275 case kExpr##name: \ 308 case kExpr##name: \
276 return kArity_##sig; 309 return kArity_##sig;
277 310
278 FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE) 311 FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
279 FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE) 312 FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
280 FOREACH_MISC_MEM_OPCODE(DECLARE_OPCODE_CASE) 313 FOREACH_MISC_MEM_OPCODE(DECLARE_OPCODE_CASE)
281 FOREACH_SIMPLE_OPCODE(DECLARE_OPCODE_CASE) 314 FOREACH_SIMPLE_OPCODE(DECLARE_OPCODE_CASE)
282 FOREACH_ASMJS_COMPAT_OPCODE(DECLARE_OPCODE_CASE) 315 FOREACH_ASMJS_COMPAT_OPCODE(DECLARE_OPCODE_CASE)
283 #undef DECLARE_OPCODE_CASE 316 #undef DECLARE_OPCODE_CASE
284 case kExprDeclLocals:
285 default: 317 default:
286 UNREACHABLE(); 318 UNREACHABLE();
287 return 0; 319 return 0;
288 } 320 }
289 } 321 }
290 322
291 int OpcodeLength(const byte* pc) { 323 int OpcodeLength(const byte* pc) {
292 switch (static_cast<WasmOpcode>(*pc)) { 324 switch (static_cast<WasmOpcode>(*pc)) {
293 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: 325 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
294 FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE) 326 FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
295 FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE) 327 FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
296 #undef DECLARE_OPCODE_CASE 328 #undef DECLARE_OPCODE_CASE
297 { 329 {
298 MemoryAccessOperand operand(this, pc); 330 MemoryAccessOperand operand(this, pc);
299 return 1 + operand.length; 331 return 1 + operand.length;
300 } 332 }
301 case kExprBlock:
302 case kExprLoop: {
303 BlockCountOperand operand(this, pc);
304 return 1 + operand.length;
305 }
306 case kExprBr: 333 case kExprBr:
307 case kExprBrIf: { 334 case kExprBrIf: {
308 BreakDepthOperand operand(this, pc); 335 BreakDepthOperand operand(this, pc);
309 return 1 + operand.length; 336 return 1 + operand.length;
310 } 337 }
311 case kExprStoreGlobal: 338 case kExprStoreGlobal:
312 case kExprLoadGlobal: { 339 case kExprLoadGlobal: {
313 GlobalIndexOperand operand(this, pc); 340 GlobalIndexOperand operand(this, pc);
314 return 1 + operand.length; 341 return 1 + operand.length;
315 } 342 }
316 343
317 case kExprCallFunction: { 344 case kExprCallFunction: {
318 FunctionIndexOperand operand(this, pc); 345 CallFunctionOperand operand(this, pc);
319 return 1 + operand.length; 346 return 1 + operand.length;
320 } 347 }
321 case kExprCallIndirect: { 348 case kExprCallIndirect: {
322 SignatureIndexOperand operand(this, pc); 349 CallIndirectOperand operand(this, pc);
323 return 1 + operand.length; 350 return 1 + operand.length;
324 } 351 }
325 case kExprCallImport: { 352 case kExprCallImport: {
326 ImportIndexOperand operand(this, pc); 353 CallImportOperand operand(this, pc);
327 return 1 + operand.length; 354 return 1 + operand.length;
328 } 355 }
329 356
330 case kExprSetLocal: 357 case kExprSetLocal:
331 case kExprGetLocal: { 358 case kExprGetLocal: {
332 LocalIndexOperand operand(this, pc); 359 LocalIndexOperand operand(this, pc);
333 return 1 + operand.length; 360 return 1 + operand.length;
334 } 361 }
335 case kExprBrTable: { 362 case kExprBrTable: {
336 BranchTableOperand operand(this, pc); 363 BranchTableOperand operand(this, pc);
337 return 1 + operand.length; 364 return 1 + operand.length;
338 } 365 }
339 case kExprI32Const: { 366 case kExprI32Const: {
340 ImmI32Operand operand(this, pc); 367 ImmI32Operand operand(this, pc);
341 return 1 + operand.length; 368 return 1 + operand.length;
342 } 369 }
343 case kExprI64Const: { 370 case kExprI64Const: {
344 ImmI64Operand operand(this, pc); 371 ImmI64Operand operand(this, pc);
345 return 1 + operand.length; 372 return 1 + operand.length;
346 } 373 }
347 case kExprI8Const: 374 case kExprI8Const:
348 return 2; 375 return 2;
349 case kExprF32Const: 376 case kExprF32Const:
350 return 5; 377 return 5;
351 case kExprF64Const: 378 case kExprF64Const:
352 return 9; 379 return 9;
380 case kExprReturn: {
381 ReturnArityOperand operand(this, pc);
382 return 1 + operand.length;
383 }
353 384
354 default: 385 default:
355 return 1; 386 return 1;
356 } 387 }
357 } 388 }
358 }; 389 };
359 390
360 391
361 // A shift-reduce-parser strategy for decoding Wasm code that uses an explicit 392 // A shift-reduce-parser strategy for decoding Wasm code that uses an explicit
362 // shift-reduce strategy with multiple internal stacks. 393 // shift-reduce strategy with multiple internal stacks.
363 class SR_WasmDecoder : public WasmDecoder { 394 class SR_WasmDecoder : public WasmDecoder {
364 public: 395 public:
365 SR_WasmDecoder(Zone* zone, TFBuilder* builder, FunctionBody& body) 396 SR_WasmDecoder(Zone* zone, TFBuilder* builder, FunctionBody& body)
366 : WasmDecoder(body.module, body.sig, body.start, body.end), 397 : WasmDecoder(body.module, body.sig, body.start, body.end),
367 zone_(zone), 398 zone_(zone),
368 builder_(builder), 399 builder_(builder),
369 base_(body.base), 400 base_(body.base),
370 local_type_vec_(zone), 401 local_type_vec_(zone),
371 trees_(zone),
372 stack_(zone), 402 stack_(zone),
373 blocks_(zone), 403 control_(zone) {
374 ifs_(zone) {
375 local_types_ = &local_type_vec_; 404 local_types_ = &local_type_vec_;
376 } 405 }
377 406
378 TreeResult Decode() { 407 bool Decode() {
408 base::ElapsedTimer decode_timer;
409 if (FLAG_trace_wasm_decode_time) {
410 decode_timer.Start();
411 }
412 stack_.clear();
413 control_.clear();
414
379 if (end_ < pc_) { 415 if (end_ < pc_) {
380 error(pc_, "function body end < start"); 416 error(pc_, "function body end < start");
381 return result_; 417 return false;
382 } 418 }
383 419
384 DecodeLocalDecls(); 420 DecodeLocalDecls();
385 InitSsaEnv(); 421 InitSsaEnv();
386 DecodeFunctionBody(); 422 DecodeFunctionBody();
387 423
388 Tree* tree = nullptr; 424 if (failed()) return TraceFailed();
389 if (ok()) { 425
390 if (ssa_env_->go()) { 426 if (!control_.empty()) {
391 if (stack_.size() > 0) { 427 error(pc_, control_.back().pc, "unterminated control structure");
392 error(stack_.back().pc(), end_, "fell off end of code"); 428 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 } 429 }
404 430
405 if (ok()) { 431 if (ssa_env_->go()) {
406 TRACE("wasm-decode ok\n"); 432 TRACE(" @%-6d #xx:%-20s|", startrel(pc_), "ImplicitReturn");
407 } else { 433 DoReturn();
408 TRACE("wasm-error module+%-6d func+%d: %s\n\n", baserel(error_pc_), 434 if (failed()) return TraceFailed();
409 startrel(error_pc_), error_msg_.get()); 435 TRACE("\n");
410 } 436 }
411 437
412 return toResult(tree); 438 if (FLAG_trace_wasm_decode_time) {
439 double ms = decode_timer.Elapsed().InMillisecondsF();
440 PrintF("wasm-decode ok (%0.3f ms)\n\n", ms);
441 } else {
442 TRACE("wasm-decode ok\n\n");
443 }
444
445 return true;
446 }
447
448 bool TraceFailed() {
449 TRACE("wasm-error module+%-6d func+%d: %s\n\n", baserel(error_pc_),
450 startrel(error_pc_), error_msg_.get());
451 return false;
413 } 452 }
414 453
415 bool DecodeLocalDecls(AstLocalDecls& decls) { 454 bool DecodeLocalDecls(AstLocalDecls& decls) {
416 DecodeLocalDecls(); 455 DecodeLocalDecls();
417 if (failed()) return false; 456 if (failed()) return false;
418 decls.decls_encoded_size = pc_offset(); 457 decls.decls_encoded_size = pc_offset();
419 decls.local_types.reserve(local_type_vec_.size()); 458 decls.local_types.reserve(local_type_vec_.size());
420 for (size_t pos = 0; pos < local_type_vec_.size();) { 459 for (size_t pos = 0; pos < local_type_vec_.size();) {
421 uint32_t count = 0; 460 uint32_t count = 0;
422 LocalType type = local_type_vec_[pos]; 461 LocalType type = local_type_vec_[pos];
(...skipping 17 matching lines...) Expand all
440 } 479 }
441 return AnalyzeLoopAssignment(pc); 480 return AnalyzeLoopAssignment(pc);
442 } 481 }
443 482
444 private: 483 private:
445 static const size_t kErrorMsgSize = 128; 484 static const size_t kErrorMsgSize = 128;
446 485
447 Zone* zone_; 486 Zone* zone_;
448 TFBuilder* builder_; 487 TFBuilder* builder_;
449 const byte* base_; 488 const byte* base_;
450 TreeResult result_;
451 489
452 SsaEnv* ssa_env_; 490 SsaEnv* ssa_env_;
453 491
454 ZoneVector<LocalType> local_type_vec_; 492 ZoneVector<LocalType> local_type_vec_;
455 ZoneVector<Tree*> trees_; 493 ZoneVector<Value> stack_;
456 ZoneVector<Production> stack_; 494 ZoneVector<Control> control_;
457 ZoneVector<Block> blocks_;
458 ZoneVector<IfEnv> ifs_;
459 495
460 inline bool build() { return builder_ && ssa_env_->go(); } 496 inline bool build() { return builder_ && ssa_env_->go(); }
461 497
462 void InitSsaEnv() { 498 void InitSsaEnv() {
463 TFNode* start = nullptr; 499 TFNode* start = nullptr;
464 SsaEnv* ssa_env = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv))); 500 SsaEnv* ssa_env = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
465 size_t size = sizeof(TFNode*) * EnvironmentCount(); 501 size_t size = sizeof(TFNode*) * EnvironmentCount();
466 ssa_env->state = SsaEnv::kReached; 502 ssa_env->state = SsaEnv::kReached;
467 ssa_env->locals = 503 ssa_env->locals =
468 size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr; 504 size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
500 case kAstF32: 536 case kAstF32:
501 return builder_->Float32Constant(0); 537 return builder_->Float32Constant(0);
502 case kAstF64: 538 case kAstF64:
503 return builder_->Float64Constant(0); 539 return builder_->Float64Constant(0);
504 default: 540 default:
505 UNREACHABLE(); 541 UNREACHABLE();
506 return nullptr; 542 return nullptr;
507 } 543 }
508 } 544 }
509 545
510 void Leaf(LocalType type, TFNode* node = nullptr) {
511 size_t size = sizeof(Tree);
512 Tree* tree = reinterpret_cast<Tree*>(zone_->New(size));
513 tree->type = type;
514 tree->count = 0;
515 tree->pc = pc_;
516 tree->node = node;
517 tree->children[0] = nullptr;
518 Reduce(tree);
519 }
520
521 void Shift(LocalType type, uint32_t count) {
522 size_t size =
523 sizeof(Tree) + (count == 0 ? 0 : ((count - 1) * sizeof(Tree*)));
524 Tree* tree = reinterpret_cast<Tree*>(zone_->New(size));
525 tree->type = type;
526 tree->count = count;
527 tree->pc = pc_;
528 tree->node = nullptr;
529 for (uint32_t i = 0; i < count; i++) tree->children[i] = nullptr;
530 if (count == 0) {
531 Production p = {tree, 0};
532 Reduce(&p);
533 Reduce(tree);
534 } else {
535 stack_.push_back({tree, 0});
536 }
537 }
538
539 void Reduce(Tree* tree) {
540 while (true) {
541 if (stack_.size() == 0) {
542 trees_.push_back(tree);
543 break;
544 }
545 Production* p = &stack_.back();
546 p->tree->children[p->index++] = tree;
547 Reduce(p);
548 if (p->done()) {
549 tree = p->tree;
550 stack_.pop_back();
551 } else {
552 break;
553 }
554 }
555 }
556
557 char* indentation() { 546 char* indentation() {
558 static const int kMaxIndent = 64; 547 static const int kMaxIndent = 64;
559 static char bytes[kMaxIndent + 1]; 548 static char bytes[kMaxIndent + 1];
560 for (int i = 0; i < kMaxIndent; i++) bytes[i] = ' '; 549 for (int i = 0; i < kMaxIndent; i++) bytes[i] = ' ';
561 bytes[kMaxIndent] = 0; 550 bytes[kMaxIndent] = 0;
562 if (stack_.size() < kMaxIndent / 2) { 551 if (stack_.size() < kMaxIndent / 2) {
563 bytes[stack_.size() * 2] = 0; 552 bytes[stack_.size() * 2] = 0;
564 } 553 }
565 return bytes; 554 return bytes;
566 } 555 }
(...skipping 30 matching lines...) Expand all
597 break; 586 break;
598 default: 587 default:
599 error(pc_ - 1, "invalid local type"); 588 error(pc_ - 1, "invalid local type");
600 return; 589 return;
601 } 590 }
602 local_type_vec_.insert(local_type_vec_.end(), count, type); 591 local_type_vec_.insert(local_type_vec_.end(), count, type);
603 } 592 }
604 total_locals_ = local_type_vec_.size(); 593 total_locals_ = local_type_vec_.size();
605 } 594 }
606 595
607 // Decodes the body of a function, producing reduced trees into {result}. 596 // Decodes the body of a function.
608 void DecodeFunctionBody() { 597 void DecodeFunctionBody() {
609 TRACE("wasm-decode %p...%p (%d bytes) %s\n", 598 TRACE("wasm-decode %p...%p (module+%d, %d bytes) %s\n",
610 reinterpret_cast<const void*>(start_), 599 reinterpret_cast<const void*>(start_),
611 reinterpret_cast<const void*>(limit_), 600 reinterpret_cast<const void*>(limit_), baserel(pc_),
612 static_cast<int>(limit_ - start_), builder_ ? "graph building" : ""); 601 static_cast<int>(limit_ - start_), builder_ ? "graph building" : "");
613 602
614 if (pc_ >= limit_) return; // Nothing to do. 603 if (pc_ >= limit_) return; // Nothing to do.
615 604
616 while (true) { // decoding loop. 605 while (true) { // decoding loop.
617 int len = 1; 606 int len = 1;
618 WasmOpcode opcode = static_cast<WasmOpcode>(*pc_); 607 WasmOpcode opcode = static_cast<WasmOpcode>(*pc_);
619 TRACE("wasm-decode module+%-6d %s func+%d: 0x%02x %s\n", baserel(pc_), 608 TRACE(" @%-6d #%02x:%-20s|", startrel(pc_), opcode,
620 indentation(), startrel(pc_), opcode, 609 WasmOpcodes::ShortOpcodeName(opcode));
621 WasmOpcodes::OpcodeName(opcode));
622 610
623 FunctionSig* sig = WasmOpcodes::Signature(opcode); 611 FunctionSig* sig = WasmOpcodes::Signature(opcode);
624 if (sig) { 612 if (sig) {
625 // A simple expression with a fixed signature. 613 // Fast case of a simple operator.
626 Shift(sig->GetReturn(), static_cast<uint32_t>(sig->parameter_count())); 614 TFNode* node;
627 pc_ += len; 615 switch (sig->parameter_count()) {
628 if (pc_ >= limit_) { 616 case 1: {
629 // End of code reached or exceeded. 617 Value val = Pop(0, sig->GetParam(0));
630 if (pc_ > limit_ && ok()) { 618 node = BUILD(Unop, opcode, val.node);
631 error("Beyond end of code"); 619 break;
632 } 620 }
633 return; 621 case 2: {
622 Value rval = Pop(1, sig->GetParam(1));
623 Value lval = Pop(0, sig->GetParam(0));
624 node = BUILD(Binop, opcode, lval.node, rval.node);
625 break;
626 }
627 default:
628 UNREACHABLE();
629 node = nullptr;
630 break;
634 } 631 }
635 continue; // back to decoding loop. 632 Push(GetReturnType(sig), node);
636 } 633 } else {
637 634 // Complex bytecode.
638 switch (opcode) { 635 switch (opcode) {
639 case kExprNop: 636 case kExprNop:
640 Leaf(kAstStmt); 637 Push(kAstStmt, nullptr);
641 break; 638 break;
642 case kExprBlock: { 639 case kExprBlock: {
643 BlockCountOperand operand(this, pc_);
644 if (operand.count < 1) {
645 Leaf(kAstStmt);
646 } else {
647 Shift(kAstEnd, operand.count);
648 // The break environment is the outer environment. 640 // The break environment is the outer environment.
649 SsaEnv* break_env = ssa_env_; 641 SsaEnv* break_env = ssa_env_;
650 PushBlock(break_env); 642 PushBlock(break_env);
651 SetEnv("block:start", Steal(break_env)); 643 SetEnv("block:start", Steal(break_env));
644 break;
652 } 645 }
653 len = 1 + operand.length; 646 case kExprLoop: {
654 break;
655 }
656 case kExprLoop: {
657 BlockCountOperand operand(this, pc_);
658 if (operand.count < 1) {
659 Leaf(kAstStmt);
660 } else {
661 Shift(kAstEnd, operand.count);
662 // The break environment is the outer environment. 647 // The break environment is the outer environment.
663 SsaEnv* break_env = ssa_env_; 648 SsaEnv* break_env = ssa_env_;
664 PushBlock(break_env); 649 PushBlock(break_env);
665 SsaEnv* cont_env = Steal(break_env); 650 SsaEnv* cont_env = Steal(break_env);
666 // The continue environment is the inner environment. 651 // The continue environment is the inner environment.
667 PrepareForLoop(pc_, cont_env); 652 PrepareForLoop(pc_, cont_env);
668 SetEnv("loop:start", Split(cont_env)); 653 SetEnv("loop:start", Split(cont_env));
669 if (ssa_env_->go()) ssa_env_->state = SsaEnv::kReached; 654 ssa_env_->SetNotMerged();
670 PushBlock(cont_env); 655 PushLoop(cont_env);
671 blocks_.back().stack_depth = -1; // no production for inner block. 656 break;
672 } 657 }
673 len = 1 + operand.length; 658 case kExprIf: {
674 break; 659 // Condition on top of stack. Split environments for branches.
660 Value cond = Pop(0, kAstI32);
661 TFNode* if_true = nullptr;
662 TFNode* if_false = nullptr;
663 BUILD(Branch, cond.node, &if_true, &if_false);
664 SsaEnv* end_env = ssa_env_;
665 SsaEnv* false_env = Split(ssa_env_);
666 false_env->control = if_false;
667 SsaEnv* true_env = Steal(ssa_env_);
668 true_env->control = if_true;
669 PushIf(end_env, false_env);
670 SetEnv("if:true", true_env);
671 break;
672 }
673 case kExprElse: {
674 if (control_.empty()) {
675 error(pc_, "else does not match any if");
676 break;
677 }
678 Control* c = &control_.back();
679 if (!c->is_if()) {
680 error(pc_, c->pc, "else does not match an if");
681 break;
682 }
683 if (c->false_env == nullptr) {
684 error(pc_, c->pc, "else already present for if");
685 break;
686 }
687 Value val = PopUpTo(c->stack_depth);
688 MergeInto(c->end_env, &c->node, &c->type, val);
689 // Switch to environment for false branch.
690 SetEnv("if_else:false", c->false_env);
691 c->false_env = nullptr; // record that an else is already seen
692 break;
693 }
694 case kExprEnd: {
695 if (control_.empty()) {
696 error(pc_, "end does not match any if or block");
697 break;
698 }
699 const char* name = "block:end";
700 Control* c = &control_.back();
701 if (c->is_loop) {
702 // Loops always push control in pairs.
703 control_.pop_back();
704 c = &control_.back();
705 name = "loop:end";
706 }
707 Value val = PopUpTo(c->stack_depth);
708 if (c->is_if()) {
709 if (c->false_env != nullptr) {
710 // End the true branch of a one-armed if.
711 Goto(c->false_env, c->end_env);
712 val = {val.pc, nullptr, kAstStmt};
713 name = "if:merge";
714 } else {
715 // End the false branch of a two-armed if.
716 name = "if_else:merge";
717 }
718 }
719 if (ssa_env_->go()) {
720 MergeInto(c->end_env, &c->node, &c->type, val);
721 }
722 SetEnv(name, c->end_env);
723 stack_.resize(c->stack_depth);
724 Push(c->type, c->node);
725 control_.pop_back();
726 break;
727 }
728 case kExprSelect: {
729 Value cond = Pop(2, kAstI32);
730 Value fval = Pop();
731 Value tval = Pop();
732 if (tval.type == kAstStmt || tval.type != fval.type) {
733 if (tval.type != kAstEnd && fval.type != kAstEnd) {
734 error(pc_, "type mismatch in select");
735 break;
736 }
737 }
738 if (build()) {
739 DCHECK(tval.type != kAstEnd);
740 DCHECK(fval.type != kAstEnd);
741 DCHECK(cond.type != kAstEnd);
742 TFNode* controls[2];
743 builder_->Branch(cond.node, &controls[0], &controls[1]);
744 TFNode* merge = builder_->Merge(2, controls);
745 TFNode* vals[2] = {tval.node, fval.node};
746 TFNode* phi = builder_->Phi(tval.type, 2, vals, merge);
747 Push(tval.type, phi);
748 ssa_env_->control = merge;
749 } else {
750 Push(tval.type, nullptr);
751 }
752 break;
753 }
754 case kExprBr: {
755 BreakDepthOperand operand(this, pc_);
756 Value val = {pc_, nullptr, kAstStmt};
757 if (operand.arity) val = Pop();
758 if (Validate(pc_, operand, control_)) {
759 BreakTo(operand.target, val);
760 }
761 len = 1 + operand.length;
762 Push(kAstEnd, nullptr);
763 break;
764 }
765 case kExprBrIf: {
766 BreakDepthOperand operand(this, pc_);
767 Value cond = Pop(operand.arity, kAstI32);
768 Value val = {pc_, nullptr, kAstStmt};
769 if (operand.arity == 1) val = Pop();
770 if (Validate(pc_, operand, control_)) {
771 SsaEnv* fenv = ssa_env_;
772 SsaEnv* tenv = Split(fenv);
773 fenv->SetNotMerged();
774 BUILD(Branch, cond.node, &tenv->control, &fenv->control);
775 ssa_env_ = tenv;
776 BreakTo(operand.target, val);
777 ssa_env_ = fenv;
778 }
779 len = 1 + operand.length;
780 Push(kAstStmt, nullptr);
781 break;
782 }
783 case kExprBrTable: {
784 BranchTableOperand operand(this, pc_);
785 if (Validate(pc_, operand, control_.size())) {
786 Value key = Pop(operand.arity, kAstI32);
787 Value val = {pc_, nullptr, kAstStmt};
788 if (operand.arity == 1) val = Pop();
789 if (failed()) break;
790
791 SsaEnv* break_env = ssa_env_;
792 if (operand.table_count > 0) {
793 // Build branches to the various blocks based on the table.
794 TFNode* sw = BUILD(Switch, operand.table_count + 1, key.node);
795
796 SsaEnv* copy = Steal(break_env);
797 ssa_env_ = copy;
798 for (uint32_t i = 0; i < operand.table_count + 1; i++) {
799 uint16_t target = operand.read_entry(this, i);
800 ssa_env_ = Split(copy);
801 ssa_env_->control = (i == operand.table_count)
802 ? BUILD(IfDefault, sw)
803 : BUILD(IfValue, i, sw);
804 int depth = target;
805 Control* c = &control_[control_.size() - depth - 1];
806 MergeInto(c->end_env, &c->node, &c->type, val);
807 }
808 } else {
809 // Only a default target. Do the equivalent of br.
810 uint16_t target = operand.read_entry(this, 0);
811 int depth = target;
812 Control* c = &control_[control_.size() - depth - 1];
813 MergeInto(c->end_env, &c->node, &c->type, val);
814 }
815 // br_table ends the control flow like br.
816 ssa_env_ = break_env;
817 Push(kAstStmt, nullptr);
818 }
819 len = 1 + operand.length;
820 break;
821 }
822 case kExprReturn: {
823 ReturnArityOperand operand(this, pc_);
824 if (operand.arity != sig_->return_count()) {
825 error(pc_, pc_ + 1, "arity mismatch in return");
826 }
827 DoReturn();
828 len = 1 + operand.length;
829 break;
830 }
831 case kExprUnreachable: {
832 // TODO(clemensh): add source position for unreachable
833 Push(kAstEnd, BUILD0(Unreachable));
834 ssa_env_->Kill(SsaEnv::kControlEnd);
835 break;
836 }
837 case kExprI8Const: {
838 ImmI8Operand operand(this, pc_);
839 Push(kAstI32, BUILD(Int32Constant, operand.value));
840 len = 1 + operand.length;
841 break;
842 }
843 case kExprI32Const: {
844 ImmI32Operand operand(this, pc_);
845 Push(kAstI32, BUILD(Int32Constant, operand.value));
846 len = 1 + operand.length;
847 break;
848 }
849 case kExprI64Const: {
850 ImmI64Operand operand(this, pc_);
851 Push(kAstI64, BUILD(Int64Constant, operand.value));
852 len = 1 + operand.length;
853 break;
854 }
855 case kExprF32Const: {
856 ImmF32Operand operand(this, pc_);
857 Push(kAstF32, BUILD(Float32Constant, operand.value));
858 len = 1 + operand.length;
859 break;
860 }
861 case kExprF64Const: {
862 ImmF64Operand operand(this, pc_);
863 Push(kAstF64, BUILD(Float64Constant, operand.value));
864 len = 1 + operand.length;
865 break;
866 }
867 case kExprGetLocal: {
868 LocalIndexOperand operand(this, pc_);
869 if (Validate(pc_, operand)) {
870 if (build()) {
871 Push(operand.type, ssa_env_->locals[operand.index]);
872 } else {
873 Push(operand.type, nullptr);
874 }
875 }
876 len = 1 + operand.length;
877 break;
878 }
879 case kExprSetLocal: {
880 LocalIndexOperand operand(this, pc_);
881 if (Validate(pc_, operand)) {
882 Value val = Pop(0, local_type_vec_[operand.index]);
883 if (ssa_env_->locals) ssa_env_->locals[operand.index] = val.node;
884 Push(val.type, val.node);
885 }
886 len = 1 + operand.length;
887 break;
888 }
889 case kExprLoadGlobal: {
890 GlobalIndexOperand operand(this, pc_);
891 if (Validate(pc_, operand)) {
892 Push(operand.type, BUILD(LoadGlobal, operand.index));
893 }
894 len = 1 + operand.length;
895 break;
896 }
897 case kExprStoreGlobal: {
898 GlobalIndexOperand operand(this, pc_);
899 if (Validate(pc_, operand)) {
900 Value val = Pop(0, operand.type);
901 BUILD(StoreGlobal, operand.index, val.node);
902 Push(val.type, val.node);
903 }
904 len = 1 + operand.length;
905 break;
906 }
907 case kExprI32LoadMem8S:
908 len = DecodeLoadMem(kAstI32, MachineType::Int8());
909 break;
910 case kExprI32LoadMem8U:
911 len = DecodeLoadMem(kAstI32, MachineType::Uint8());
912 break;
913 case kExprI32LoadMem16S:
914 len = DecodeLoadMem(kAstI32, MachineType::Int16());
915 break;
916 case kExprI32LoadMem16U:
917 len = DecodeLoadMem(kAstI32, MachineType::Uint16());
918 break;
919 case kExprI32LoadMem:
920 len = DecodeLoadMem(kAstI32, MachineType::Int32());
921 break;
922
923 case kExprI64LoadMem8S:
924 len = DecodeLoadMem(kAstI64, MachineType::Int8());
925 break;
926 case kExprI64LoadMem8U:
927 len = DecodeLoadMem(kAstI64, MachineType::Uint8());
928 break;
929 case kExprI64LoadMem16S:
930 len = DecodeLoadMem(kAstI64, MachineType::Int16());
931 break;
932 case kExprI64LoadMem16U:
933 len = DecodeLoadMem(kAstI64, MachineType::Uint16());
934 break;
935 case kExprI64LoadMem32S:
936 len = DecodeLoadMem(kAstI64, MachineType::Int32());
937 break;
938 case kExprI64LoadMem32U:
939 len = DecodeLoadMem(kAstI64, MachineType::Uint32());
940 break;
941 case kExprI64LoadMem:
942 len = DecodeLoadMem(kAstI64, MachineType::Int64());
943 break;
944 case kExprF32LoadMem:
945 len = DecodeLoadMem(kAstF32, MachineType::Float32());
946 break;
947 case kExprF64LoadMem:
948 len = DecodeLoadMem(kAstF64, MachineType::Float64());
949 break;
950 case kExprI32StoreMem8:
951 len = DecodeStoreMem(kAstI32, MachineType::Int8());
952 break;
953 case kExprI32StoreMem16:
954 len = DecodeStoreMem(kAstI32, MachineType::Int16());
955 break;
956 case kExprI32StoreMem:
957 len = DecodeStoreMem(kAstI32, MachineType::Int32());
958 break;
959 case kExprI64StoreMem8:
960 len = DecodeStoreMem(kAstI64, MachineType::Int8());
961 break;
962 case kExprI64StoreMem16:
963 len = DecodeStoreMem(kAstI64, MachineType::Int16());
964 break;
965 case kExprI64StoreMem32:
966 len = DecodeStoreMem(kAstI64, MachineType::Int32());
967 break;
968 case kExprI64StoreMem:
969 len = DecodeStoreMem(kAstI64, MachineType::Int64());
970 break;
971 case kExprF32StoreMem:
972 len = DecodeStoreMem(kAstF32, MachineType::Float32());
973 break;
974 case kExprF64StoreMem:
975 len = DecodeStoreMem(kAstF64, MachineType::Float64());
976 break;
977
978 case kExprMemorySize:
979 Push(kAstI32, BUILD(MemSize, 0));
980 break;
981 case kExprGrowMemory: {
982 Value val = Pop(0, kAstI32);
983 USE(val); // TODO(titzer): build node for grow memory
984 Push(kAstI32, BUILD(Int32Constant, 0));
985 break;
986 }
987 case kExprCallFunction: {
988 CallFunctionOperand operand(this, pc_);
989 if (Validate(pc_, operand)) {
990 TFNode** buffer = PopArgs(operand.sig);
991 TFNode* call = BUILD(CallDirect, operand.index, buffer);
992 Push(GetReturnType(operand.sig), call);
993 AddSourcePosition(call, pc_);
994 }
995 len = 1 + operand.length;
996 break;
997 }
998 case kExprCallIndirect: {
999 CallIndirectOperand operand(this, pc_);
1000 if (Validate(pc_, operand)) {
1001 TFNode** buffer = PopArgs(operand.sig);
1002 Value index = Pop(0, kAstI32);
1003 if (buffer) buffer[0] = index.node;
1004 TFNode* call = BUILD(CallIndirect, operand.index, buffer);
1005 Push(GetReturnType(operand.sig), call);
1006 AddSourcePosition(call, pc_);
1007 }
1008 len = 1 + operand.length;
1009 break;
1010 }
1011 case kExprCallImport: {
1012 CallImportOperand operand(this, pc_);
1013 if (Validate(pc_, operand)) {
1014 TFNode** buffer = PopArgs(operand.sig);
1015 TFNode* call = BUILD(CallImport, operand.index, buffer);
1016 Push(GetReturnType(operand.sig), call);
1017 AddSourcePosition(call, pc_);
1018 }
1019 len = 1 + operand.length;
1020 break;
1021 }
1022 default:
1023 error("Invalid opcode");
1024 return;
675 } 1025 }
676 case kExprIf: 1026 } // end complex bytecode
677 Shift(kAstStmt, 2); 1027
678 break; 1028 #if DEBUG
679 case kExprIfElse: 1029 if (FLAG_trace_wasm_decoder) {
680 Shift(kAstEnd, 3); // Result type is typeof(x) in {c ? x : y}. 1030 for (size_t i = 0; i < stack_.size(); i++) {
681 break; 1031 Value& val = stack_[i];
682 case kExprSelect: 1032 WasmOpcode opcode = static_cast<WasmOpcode>(*val.pc);
683 Shift(kAstStmt, 3); // Result type is typeof(x) in {c ? x : y}. 1033 PrintF(" %c@%d:%s", WasmOpcodes::ShortNameOf(val.type),
684 break; 1034 static_cast<int>(val.pc - start_),
685 case kExprBr: { 1035 WasmOpcodes::ShortOpcodeName(opcode));
686 BreakDepthOperand operand(this, pc_); 1036 switch (opcode) {
687 if (Validate(pc_, operand, blocks_)) { 1037 case kExprI32Const: {
688 Shift(kAstEnd, 1); 1038 ImmI32Operand operand(this, val.pc);
689 } 1039 PrintF("[%d]", operand.value);
690 len = 1 + operand.length; 1040 break;
691 break; 1041 }
1042 case kExprGetLocal: {
1043 LocalIndexOperand operand(this, val.pc);
1044 PrintF("[%u]", operand.index);
1045 break;
1046 }
1047 case kExprSetLocal: {
1048 LocalIndexOperand operand(this, val.pc);
1049 PrintF("[%u]", operand.index);
1050 break;
1051 }
1052 default:
1053 break;
1054 }
692 } 1055 }
693 case kExprBrIf: { 1056 PrintF("\n");
694 BreakDepthOperand operand(this, pc_);
695 if (Validate(pc_, operand, blocks_)) {
696 Shift(kAstStmt, 2);
697 }
698 len = 1 + operand.length;
699 break;
700 }
701 case kExprBrTable: {
702 BranchTableOperand operand(this, pc_);
703 if (Validate(pc_, operand, blocks_.size())) {
704 Shift(kAstEnd, 1);
705 }
706 len = 1 + operand.length;
707 break;
708 }
709 case kExprReturn: {
710 int count = static_cast<int>(sig_->return_count());
711 if (count == 0) {
712 BUILD(Return, 0, builder_->Buffer(0));
713 ssa_env_->Kill();
714 Leaf(kAstEnd);
715 } else {
716 Shift(kAstEnd, count);
717 }
718 break;
719 }
720 case kExprUnreachable: {
721 // TODO(clemensh): add source position for unreachable
722 BUILD0(Unreachable);
723 ssa_env_->Kill(SsaEnv::kControlEnd);
724 Leaf(kAstEnd, nullptr);
725 break;
726 }
727 case kExprI8Const: {
728 ImmI8Operand operand(this, pc_);
729 Leaf(kAstI32, BUILD(Int32Constant, operand.value));
730 len = 1 + operand.length;
731 break;
732 }
733 case kExprI32Const: {
734 ImmI32Operand operand(this, pc_);
735 Leaf(kAstI32, BUILD(Int32Constant, operand.value));
736 len = 1 + operand.length;
737 break;
738 }
739 case kExprI64Const: {
740 ImmI64Operand operand(this, pc_);
741 Leaf(kAstI64, BUILD(Int64Constant, operand.value));
742 len = 1 + operand.length;
743 break;
744 }
745 case kExprF32Const: {
746 ImmF32Operand operand(this, pc_);
747 Leaf(kAstF32, BUILD(Float32Constant, operand.value));
748 len = 1 + operand.length;
749 break;
750 }
751 case kExprF64Const: {
752 ImmF64Operand operand(this, pc_);
753 Leaf(kAstF64, BUILD(Float64Constant, operand.value));
754 len = 1 + operand.length;
755 break;
756 }
757 case kExprGetLocal: {
758 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;
764 break;
765 }
766 case kExprSetLocal: {
767 LocalIndexOperand operand(this, pc_);
768 if (Validate(pc_, operand)) {
769 Shift(operand.type, 1);
770 }
771 len = 1 + operand.length;
772 break;
773 }
774 case kExprLoadGlobal: {
775 GlobalIndexOperand operand(this, pc_);
776 if (Validate(pc_, operand)) {
777 Leaf(operand.type, BUILD(LoadGlobal, operand.index));
778 }
779 len = 1 + operand.length;
780 break;
781 }
782 case kExprStoreGlobal: {
783 GlobalIndexOperand operand(this, pc_);
784 if (Validate(pc_, operand)) {
785 Shift(operand.type, 1);
786 }
787 len = 1 + operand.length;
788 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: {
836 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()));
842 }
843 len = 1 + operand.length;
844 break;
845 }
846 case kExprCallIndirect: {
847 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()));
853 }
854 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;
866 break;
867 }
868 case kExprDeclLocals:
869 default:
870 error("Invalid opcode");
871 return;
872 } 1057 }
1058 #endif
873 pc_ += len; 1059 pc_ += len;
874 if (pc_ >= limit_) { 1060 if (pc_ >= limit_) {
875 // End of code reached or exceeded. 1061 // End of code reached or exceeded.
876 if (pc_ > limit_ && ok()) { 1062 if (pc_ > limit_ && ok()) error("Beyond end of code");
877 error("Beyond end of code");
878 }
879 return; 1063 return;
880 } 1064 }
881 } 1065 } // end decode loop
882 } 1066 } // end DecodeFunctionBody()
883 1067
884 void PushBlock(SsaEnv* ssa_env) { 1068 TFNode** PopArgs(FunctionSig* sig) {
885 blocks_.push_back({ssa_env, static_cast<int>(stack_.size() - 1)}); 1069 if (build()) {
886 } 1070 int count = static_cast<int>(sig->parameter_count());
887 1071 TFNode** buffer = builder_->Buffer(count + 1);
888 int DecodeLoadMem(const byte* pc, LocalType type) { 1072 buffer[0] = nullptr; // reserved for code object or function index.
889 MemoryAccessOperand operand(this, pc); 1073 for (int i = count - 1; i >= 0; i--) {
890 Shift(type, 1); 1074 buffer[i + 1] = Pop(i, sig->GetParam(i)).node;
1075 }
1076 return buffer;
1077 } else {
1078 int count = static_cast<int>(sig->parameter_count());
1079 for (int i = count - 1; i >= 0; i--) {
1080 Pop(i, sig->GetParam(i));
1081 }
1082 return nullptr;
1083 }
1084 }
1085
1086 LocalType GetReturnType(FunctionSig* sig) {
1087 return sig->return_count() == 0 ? kAstStmt : sig->GetReturn();
1088 }
1089
1090 void PushBlock(SsaEnv* end_env) {
1091 int stack_depth = static_cast<int>(stack_.size());
1092 control_.push_back(
1093 {pc_, stack_depth, end_env, nullptr, nullptr, kAstEnd, false});
1094 }
1095
1096 void PushLoop(SsaEnv* end_env) {
1097 int stack_depth = static_cast<int>(stack_.size());
1098 control_.push_back(
1099 {pc_, stack_depth, end_env, nullptr, nullptr, kAstEnd, true});
1100 }
1101
1102 void PushIf(SsaEnv* end_env, SsaEnv* false_env) {
1103 int stack_depth = static_cast<int>(stack_.size());
1104 control_.push_back(
1105 {pc_, stack_depth, end_env, false_env, nullptr, kAstStmt, false});
1106 }
1107
1108 int DecodeLoadMem(LocalType type, MachineType mem_type) {
1109 MemoryAccessOperand operand(this, pc_);
1110 Value index = Pop(0, kAstI32);
1111 TFNode* node = BUILD(LoadMem, type, mem_type, index.node, operand.offset);
1112 Push(type, node);
891 return 1 + operand.length; 1113 return 1 + operand.length;
892 } 1114 }
893 1115
894 int DecodeStoreMem(const byte* pc, LocalType type) { 1116 int DecodeStoreMem(LocalType type, MachineType mem_type) {
895 MemoryAccessOperand operand(this, pc); 1117 MemoryAccessOperand operand(this, pc_);
896 Shift(type, 2); 1118 Value val = Pop(1, type);
1119 Value index = Pop(0, kAstI32);
1120 BUILD(StoreMem, mem_type, index.node, operand.offset, val.node);
1121 Push(type, val.node);
897 return 1 + operand.length; 1122 return 1 + operand.length;
898 } 1123 }
899 1124
900 void AddImplicitReturnAtEnd() { 1125 void DoReturn() {
901 int retcount = static_cast<int>(sig_->return_count()); 1126 int count = static_cast<int>(sig_->return_count());
902 if (retcount == 0) { 1127 TFNode** buffer = nullptr;
903 BUILD0(ReturnVoid); 1128 if (build()) buffer = builder_->Buffer(count);
904 return; 1129
905 } 1130 // Pop return values off the stack in reverse order.
906 1131 for (int i = count - 1; i >= 0; i--) {
907 if (static_cast<int>(trees_.size()) < retcount) { 1132 Value val = Pop(i, sig_->GetReturn(i));
908 error(limit_, nullptr, 1133 if (buffer) buffer[i] = val.node;
909 "ImplicitReturn expects %d arguments, only %d remain", retcount, 1134 }
910 static_cast<int>(trees_.size())); 1135
911 return; 1136 Push(kAstEnd, BUILD(Return, count, buffer));
912 } 1137 ssa_env_->Kill(SsaEnv::kControlEnd);
913 1138 }
914 TRACE("wasm-decode implicit return of %d args\n", retcount); 1139
915 1140 void Push(LocalType type, TFNode* node) {
916 TFNode** buffer = BUILD(Buffer, retcount); 1141 stack_.push_back({pc_, node, type});
917 for (int index = 0; index < retcount; index++) { 1142 }
918 Tree* tree = trees_[trees_.size() - 1 - index]; 1143
919 if (buffer) buffer[index] = tree->node; 1144 const char* SafeOpcodeNameAt(const byte* pc) {
920 LocalType expected = sig_->GetReturn(index); 1145 if (pc >= end_) return "<end>";
921 if (tree->type != expected) { 1146 return WasmOpcodes::ShortOpcodeName(static_cast<WasmOpcode>(*pc));
922 error(limit_, tree->pc, 1147 }
923 "ImplicitReturn[%d] expected type %s, found %s of type %s", index, 1148
924 WasmOpcodes::TypeName(expected), 1149 Value Pop(int index, LocalType expected) {
925 WasmOpcodes::OpcodeName(tree->opcode()), 1150 Value val = Pop();
926 WasmOpcodes::TypeName(tree->type)); 1151 if (val.type != expected) {
927 return; 1152 if (val.type != kAstEnd) {
1153 error(pc_, val.pc, "%s[%d] expected type %s, found %s of type %s",
1154 SafeOpcodeNameAt(pc_), index, WasmOpcodes::TypeName(expected),
1155 SafeOpcodeNameAt(val.pc), WasmOpcodes::TypeName(val.type));
928 } 1156 }
929 } 1157 }
930 1158 return val;
931 BUILD(Return, retcount, buffer); 1159 }
1160
1161 Value Pop() {
1162 if (stack_.empty()) {
1163 Value val = {pc_, nullptr, kAstStmt};
1164 error(pc_, pc_, "%s found empty stack", SafeOpcodeNameAt(pc_));
1165 return val;
1166 }
1167 Value val = stack_.back();
1168 stack_.pop_back();
1169 return val;
1170 }
1171
1172 Value PopUpTo(int stack_depth) {
1173 if (stack_depth == stack_.size()) {
1174 Value val = {pc_, nullptr, kAstStmt};
1175 return val;
1176 } else {
1177 DCHECK_LE(stack_depth, static_cast<int>(stack_.size()));
1178 Value val = Pop();
1179 stack_.resize(stack_depth);
1180 return val;
1181 }
932 } 1182 }
933 1183
934 int baserel(const byte* ptr) { 1184 int baserel(const byte* ptr) {
935 return base_ ? static_cast<int>(ptr - base_) : 0; 1185 return base_ ? static_cast<int>(ptr - base_) : 0;
936 } 1186 }
937 1187
938 int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); } 1188 int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); }
939 1189
940 void Reduce(Production* p) { 1190 void BreakTo(Control* block, Value& val) {
941 WasmOpcode opcode = p->opcode(); 1191 if (block->is_loop) {
942 TRACE("-----reduce module+%-6d %s func+%d: 0x%02x %s\n", baserel(p->pc()), 1192 // This is the inner loop block, which does not have a value.
943 indentation(), startrel(p->pc()), opcode, 1193 Goto(ssa_env_, block->end_env);
944 WasmOpcodes::OpcodeName(opcode)); 1194 } else {
945 FunctionSig* sig = WasmOpcodes::Signature(opcode); 1195 // Merge the value into the production for the block.
946 if (sig) { 1196 MergeInto(block->end_env, &block->node, &block->type, val);
947 // A simple expression with a fixed signature. 1197 }
948 TypeCheckLast(p, sig->GetParam(p->index - 1)); 1198 }
949 if (p->done() && build()) { 1199
950 if (sig->parameter_count() == 2) { 1200 void MergeInto(SsaEnv* target, TFNode** node, LocalType* type, Value& val) {
951 p->tree->node = builder_->Binop(opcode, p->tree->children[0]->node, 1201 if (!ssa_env_->go()) return;
952 p->tree->children[1]->node); 1202 DCHECK_NE(kAstEnd, val.type);
953 } else if (sig->parameter_count() == 1) { 1203
954 p->tree->node = builder_->Unop(opcode, p->tree->children[0]->node); 1204 bool first = target->state == SsaEnv::kUnreachable;
955 } else { 1205 Goto(ssa_env_, target);
956 UNREACHABLE(); 1206
1207 if (first) {
1208 // first merge to this environment; set the type and the node.
1209 *type = val.type;
1210 *node = val.node;
1211 } else if (val.type == *type && val.type != kAstStmt) {
1212 // merge with the existing value for this block.
1213 *node = CreateOrMergeIntoPhi(*type, target->control, *node, val.node);
1214 } else {
1215 // types don't match, or block is already a stmt.
1216 *type = kAstStmt;
1217 *node = nullptr;
1218 }
1219 }
1220
1221 void SetEnv(const char* reason, SsaEnv* env) {
1222 #if DEBUG
1223 if (FLAG_trace_wasm_decoder) {
1224 char state = 'X';
1225 if (env) {
1226 switch (env->state) {
1227 case SsaEnv::kReached:
1228 state = 'R';
1229 break;
1230 case SsaEnv::kUnreachable:
1231 state = 'U';
1232 break;
1233 case SsaEnv::kMerged:
1234 state = 'M';
1235 break;
1236 case SsaEnv::kControlEnd:
1237 state = 'E';
1238 break;
957 } 1239 }
958 } 1240 }
959 return; 1241 PrintF(" env = %p, state = %c, reason = %s", static_cast<void*>(env),
960 } 1242 state, reason);
961 1243 if (env && env->control) {
962 switch (opcode) { 1244 PrintF(", control = ");
963 case kExprBlock: { 1245 compiler::WasmGraphBuilder::PrintDebugName(env->control);
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 } 1246 }
974 case kExprLoop: { 1247 PrintF("\n");
975 if (p->done()) { 1248 }
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) {
1043 // 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 }
1049 } else if (p->index == 2) {
1050 // False expression done.
1051 TypeCheckLast(p, p->tree->type);
1052 } else {
1053 // Condition done.
1054 DCHECK(p->done());
1055 TypeCheckLast(p, kAstI32);
1056 if (build()) {
1057 TFNode* controls[2];
1058 builder_->Branch(p->tree->children[2]->node, &controls[0],
1059 &controls[1]);
1060 TFNode* merge = builder_->Merge(2, controls);
1061 TFNode* vals[2] = {p->tree->children[0]->node,
1062 p->tree->children[1]->node};
1063 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: {
1071 BreakDepthOperand operand(this, p->pc());
1072 CHECK(Validate(p->pc(), operand, blocks_));
1073 ReduceBreakToExprBlock(p, operand.target);
1074 break;
1075 }
1076 case kExprBrIf: {
1077 if (p->done()) {
1078 TypeCheckLast(p, kAstI32);
1079 BreakDepthOperand operand(this, p->pc());
1080 CHECK(Validate(p->pc(), operand, blocks_));
1081 SsaEnv* fenv = ssa_env_;
1082 SsaEnv* tenv = Split(fenv);
1083 BUILD(Branch, p->tree->children[1]->node, &tenv->control,
1084 &fenv->control);
1085 ssa_env_ = tenv;
1086 ReduceBreakToExprBlock(p, operand.target, p->tree->children[0]);
1087 ssa_env_ = fenv;
1088 }
1089 break;
1090 }
1091 case kExprBrTable: {
1092 if (p->index == 1) {
1093 // Switch key finished.
1094 TypeCheckLast(p, kAstI32);
1095 if (failed()) break;
1096
1097 BranchTableOperand operand(this, p->pc());
1098 DCHECK(Validate(p->pc(), operand, blocks_.size()));
1099
1100 // Build a switch only if it has more than just a default target.
1101 bool build_switch = operand.table_count > 0;
1102 TFNode* sw = nullptr;
1103 if (build_switch) {
1104 sw = BUILD(Switch, operand.table_count + 1, p->last()->node);
1105 }
1106
1107 // 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);
1112 SsaEnv* env = copy;
1113 if (build_switch) {
1114 ssa_env_ = env = Split(env);
1115 env->control = i == operand.table_count ? BUILD(IfDefault, sw)
1116 : BUILD(IfValue, i, sw);
1117 }
1118 SsaEnv* tenv = blocks_[blocks_.size() - target - 1].ssa_env;
1119 Goto(env, tenv);
1120 }
1121 ssa_env_ = prev;
1122 }
1123 break;
1124 }
1125 case kExprReturn: {
1126 TypeCheckLast(p, sig_->GetReturn(p->index - 1));
1127 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: {
1141 LocalIndexOperand operand(this, p->pc());
1142 CHECK(Validate(p->pc(), operand));
1143 Tree* val = p->last();
1144 if (operand.type == val->type) {
1145 if (build()) ssa_env_->locals[operand.index] = val->node;
1146 p->tree->node = val->node;
1147 } else {
1148 error(p->pc(), val->pc, "Typecheck failed in SetLocal");
1149 }
1150 break;
1151 }
1152 case kExprStoreGlobal: {
1153 GlobalIndexOperand operand(this, p->pc());
1154 CHECK(Validate(p->pc(), operand));
1155 Tree* val = p->last();
1156 if (operand.type == val->type) {
1157 BUILD(StoreGlobal, operand.index, val->node);
1158 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: {
1226 FunctionIndexOperand operand(this, p->pc());
1227 CHECK(Validate(p->pc(), operand));
1228 if (p->index > 0) {
1229 TypeCheckLast(p, operand.sig->GetParam(p->index - 1));
1230 }
1231 if (p->done() && build()) {
1232 uint32_t count = p->tree->count + 1;
1233 TFNode** buffer = builder_->Buffer(count);
1234 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 }
1238 p->tree->node = builder_->CallDirect(operand.index, buffer);
1239 AddSourcePosition(p);
1240 }
1241 break;
1242 }
1243 case kExprCallIndirect: {
1244 SignatureIndexOperand operand(this, p->pc());
1245 CHECK(Validate(p->pc(), operand));
1246 if (p->index == 1) {
1247 TypeCheckLast(p, kAstI32);
1248 } else {
1249 TypeCheckLast(p, operand.sig->GetParam(p->index - 2));
1250 }
1251 if (p->done() && build()) {
1252 uint32_t count = p->tree->count;
1253 TFNode** buffer = builder_->Buffer(count);
1254 for (uint32_t i = 0; i < count; i++) {
1255 buffer[i] = p->tree->children[i]->node;
1256 }
1257 p->tree->node = builder_->CallIndirect(operand.index, buffer);
1258 AddSourcePosition(p);
1259 }
1260 break;
1261 }
1262 case kExprCallImport: {
1263 ImportIndexOperand operand(this, p->pc());
1264 CHECK(Validate(p->pc(), operand));
1265 if (p->index > 0) {
1266 TypeCheckLast(p, operand.sig->GetParam(p->index - 1));
1267 }
1268 if (p->done() && build()) {
1269 uint32_t count = p->tree->count + 1;
1270 TFNode** buffer = builder_->Buffer(count);
1271 buffer[0] = nullptr; // reserved for code object.
1272 for (uint32_t i = 1; i < count; i++) {
1273 buffer[i] = p->tree->children[i - 1]->node;
1274 }
1275 p->tree->node = builder_->CallImport(operand.index, buffer);
1276 AddSourcePosition(p);
1277 }
1278 break;
1279 }
1280 default:
1281 break;
1282 }
1283 }
1284
1285 void ReduceBreakToExprBlock(Production* p, Block* block) {
1286 ReduceBreakToExprBlock(p, block, p->tree->count > 0 ? p->last() : nullptr);
1287 }
1288
1289 void ReduceBreakToExprBlock(Production* p, Block* block, Tree* val) {
1290 if (block->stack_depth < 0) {
1291 // This is the inner loop block, which does not have a value.
1292 Goto(ssa_env_, block->ssa_env);
1293 } else {
1294 // Merge the value into the production for the block.
1295 Production* bp = &stack_[block->stack_depth];
1296 MergeIntoProduction(bp, block->ssa_env, val);
1297 }
1298 }
1299
1300 void MergeIntoProduction(Production* p, SsaEnv* target, Tree* expr) {
1301 if (!ssa_env_->go()) return;
1302
1303 bool first = target->state == SsaEnv::kUnreachable;
1304 Goto(ssa_env_, target);
1305 if (expr == nullptr || expr->type == kAstEnd) return;
1306
1307 if (first) {
1308 // first merge to this environment; set the type and the node.
1309 p->tree->type = expr->type;
1310 p->tree->node = expr->node;
1311 } else {
1312 // merge with the existing value for this block.
1313 LocalType type = p->tree->type;
1314 if (expr->type != type) {
1315 type = kAstStmt;
1316 p->tree->type = kAstStmt;
1317 p->tree->node = nullptr;
1318 } else if (type != kAstStmt) {
1319 p->tree->node = CreateOrMergeIntoPhi(type, target->control,
1320 p->tree->node, expr->node);
1321 }
1322 }
1323 }
1324
1325 void ReduceLoadMem(Production* p, LocalType type, MachineType mem_type) {
1326 DCHECK_EQ(1, p->index);
1327 TypeCheckLast(p, kAstI32); // index
1328 if (build()) {
1329 MemoryAccessOperand operand(this, p->pc());
1330 p->tree->node =
1331 builder_->LoadMem(type, mem_type, p->last()->node, operand.offset);
1332 }
1333 }
1334
1335 void ReduceStoreMem(Production* p, LocalType type, MachineType mem_type) {
1336 if (p->index == 1) {
1337 TypeCheckLast(p, kAstI32); // index
1338 } else {
1339 DCHECK_EQ(2, p->index);
1340 TypeCheckLast(p, type);
1341 if (build()) {
1342 MemoryAccessOperand operand(this, p->pc());
1343 TFNode* val = p->tree->children[1]->node;
1344 builder_->StoreMem(mem_type, p->tree->children[0]->node, operand.offset,
1345 val);
1346 p->tree->node = val;
1347 }
1348 }
1349 }
1350
1351 void TypeCheckLast(Production* p, LocalType expected) {
1352 LocalType result = p->last()->type;
1353 if (result == expected) return;
1354 if (result == kAstEnd) return;
1355 if (expected != kAstStmt) {
1356 error(p->pc(), p->last()->pc,
1357 "%s[%d] expected type %s, found %s of type %s",
1358 WasmOpcodes::OpcodeName(p->opcode()), p->index - 1,
1359 WasmOpcodes::TypeName(expected),
1360 WasmOpcodes::OpcodeName(p->last()->opcode()),
1361 WasmOpcodes::TypeName(p->last()->type));
1362 }
1363 }
1364
1365 void SetEnv(const char* reason, SsaEnv* env) {
1366 #if DEBUG
1367 TRACE(" env = %p, block depth = %d, reason = %s", static_cast<void*>(env),
1368 static_cast<int>(blocks_.size()), reason);
1369 if (FLAG_trace_wasm_decoder && env && env->control) {
1370 TRACE(", control = ");
1371 compiler::WasmGraphBuilder::PrintDebugName(env->control);
1372 }
1373 TRACE("\n");
1374 #endif 1249 #endif
1375 ssa_env_ = env; 1250 ssa_env_ = env;
1376 if (builder_) { 1251 if (builder_) {
1377 builder_->set_control_ptr(&env->control); 1252 builder_->set_control_ptr(&env->control);
1378 builder_->set_effect_ptr(&env->effect); 1253 builder_->set_effect_ptr(&env->effect);
1379 } 1254 }
1380 } 1255 }
1381 1256
1382 void Goto(SsaEnv* from, SsaEnv* to) { 1257 void Goto(SsaEnv* from, SsaEnv* to) {
1383 DCHECK_NOT_NULL(to); 1258 DCHECK_NOT_NULL(to);
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
1497 } 1372 }
1498 } 1373 }
1499 1374
1500 // Create a complete copy of the {from}. 1375 // Create a complete copy of the {from}.
1501 SsaEnv* Split(SsaEnv* from) { 1376 SsaEnv* Split(SsaEnv* from) {
1502 DCHECK_NOT_NULL(from); 1377 DCHECK_NOT_NULL(from);
1503 SsaEnv* result = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv))); 1378 SsaEnv* result = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
1504 size_t size = sizeof(TFNode*) * EnvironmentCount(); 1379 size_t size = sizeof(TFNode*) * EnvironmentCount();
1505 result->control = from->control; 1380 result->control = from->control;
1506 result->effect = from->effect; 1381 result->effect = from->effect;
1507 result->state = from->state == SsaEnv::kUnreachable ? SsaEnv::kUnreachable
1508 : SsaEnv::kReached;
1509 1382
1510 if (from->go()) { 1383 if (from->go()) {
1511 result->state = SsaEnv::kReached; 1384 result->state = SsaEnv::kReached;
1512 result->locals = 1385 result->locals =
1513 size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr; 1386 size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr;
1514 memcpy(result->locals, from->locals, size); 1387 memcpy(result->locals, from->locals, size);
1515 } else { 1388 } else {
1516 result->state = SsaEnv::kUnreachable; 1389 result->state = SsaEnv::kUnreachable;
1517 result->locals = nullptr; 1390 result->locals = nullptr;
1518 } 1391 }
(...skipping 26 matching lines...) Expand all
1545 } 1418 }
1546 1419
1547 int EnvironmentCount() { 1420 int EnvironmentCount() {
1548 if (builder_) return static_cast<int>(local_type_vec_.size()); 1421 if (builder_) return static_cast<int>(local_type_vec_.size());
1549 return 0; // if we aren't building a graph, don't bother with SSA renaming. 1422 return 0; // if we aren't building a graph, don't bother with SSA renaming.
1550 } 1423 }
1551 1424
1552 virtual void onFirstError() { 1425 virtual void onFirstError() {
1553 limit_ = start_; // Terminate decoding loop. 1426 limit_ = start_; // Terminate decoding loop.
1554 builder_ = nullptr; // Don't build any more nodes. 1427 builder_ = nullptr; // Don't build any more nodes.
1555 #if DEBUG 1428 TRACE(" !%s\n", error_msg_.get());
1556 PrintStackForDebugging();
1557 #endif
1558 } 1429 }
1559
1560 #if DEBUG
1561 void PrintStackForDebugging() { PrintProduction(0); }
1562
1563 void PrintProduction(size_t depth) {
1564 if (depth >= stack_.size()) return;
1565 Production* p = &stack_[depth];
1566 for (size_t d = 0; d < depth; d++) PrintF(" ");
1567
1568 PrintF("@%d %s [%d]\n", static_cast<int>(p->tree->pc - start_),
1569 WasmOpcodes::OpcodeName(p->opcode()), p->tree->count);
1570 for (int i = 0; i < p->index; i++) {
1571 Tree* child = p->tree->children[i];
1572 for (size_t d = 0; d <= depth; d++) PrintF(" ");
1573 PrintF("@%d %s [%d]", static_cast<int>(child->pc - start_),
1574 WasmOpcodes::OpcodeName(child->opcode()), child->count);
1575 if (child->node) {
1576 PrintF(" => TF");
1577 compiler::WasmGraphBuilder::PrintDebugName(child->node);
1578 }
1579 PrintF("\n");
1580 }
1581 PrintProduction(depth + 1);
1582 }
1583 #endif
1584
1585 BitVector* AnalyzeLoopAssignment(const byte* pc) { 1430 BitVector* AnalyzeLoopAssignment(const byte* pc) {
1586 if (pc >= limit_) return nullptr; 1431 if (pc >= limit_) return nullptr;
1587 if (*pc != kExprLoop) return nullptr; 1432 if (*pc != kExprLoop) return nullptr;
1588 1433
1589 BitVector* assigned = 1434 BitVector* assigned =
1590 new (zone_) BitVector(static_cast<int>(total_locals_), zone_); 1435 new (zone_) BitVector(static_cast<int>(local_type_vec_.size()), zone_);
1591 // Keep a stack to model the nesting of expressions. 1436 int depth = 0;
1592 std::vector<int> arity_stack;
1593 arity_stack.push_back(OpcodeArity(pc));
1594 pc += OpcodeLength(pc);
1595
1596 // Iteratively process all AST nodes nested inside the loop. 1437 // Iteratively process all AST nodes nested inside the loop.
1597 while (pc < limit_) { 1438 while (pc < limit_) {
1598 WasmOpcode opcode = static_cast<WasmOpcode>(*pc); 1439 WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
1599 int arity = 0;
1600 int length = 1; 1440 int length = 1;
1601 int assigned_index = -1; 1441 switch (opcode) {
1602 if (opcode == kExprSetLocal) { 1442 case kExprLoop:
1603 LocalIndexOperand operand(this, pc); 1443 case kExprIf:
1604 if (assigned->length() > 0 && 1444 case kExprBlock:
1605 static_cast<int>(operand.index) < assigned->length()) { 1445 depth++;
1606 // Unverified code might have an out-of-bounds index. 1446 DCHECK_EQ(1, OpcodeLength(pc));
1607 // Ignore out-of-bounds indices, as the main verification will fail. 1447 break;
1608 assigned->Add(operand.index); 1448 case kExprSetLocal: {
1609 assigned_index = operand.index; 1449 LocalIndexOperand operand(this, pc);
1450 if (assigned->length() > 0 &&
1451 static_cast<int>(operand.index) < assigned->length()) {
1452 // Unverified code might have an out-of-bounds index.
1453 assigned->Add(operand.index);
1454 }
1455 length = 1 + operand.length;
1456 break;
1610 } 1457 }
1611 arity = 1; 1458 case kExprEnd:
1612 length = 1 + operand.length; 1459 depth--;
1613 } else { 1460 break;
1614 arity = OpcodeArity(pc); 1461 default:
1615 length = OpcodeLength(pc); 1462 length = OpcodeLength(pc);
1463 break;
1616 } 1464 }
1617 1465 if (depth <= 0) break;
1618 TRACE("loop-assign module+%-6d %s func+%d: 0x%02x %s", baserel(pc),
1619 indentation(), startrel(pc), opcode,
1620 WasmOpcodes::OpcodeName(opcode));
1621
1622 if (assigned_index >= 0) {
1623 TRACE(" (assigned local #%d)\n", assigned_index);
1624 } else {
1625 TRACE("\n");
1626 }
1627
1628 pc += length; 1466 pc += length;
1629 arity_stack.push_back(arity);
1630 while (arity_stack.back() == 0) {
1631 arity_stack.pop_back();
1632 if (arity_stack.empty()) return assigned; // reached end of loop
1633 arity_stack.back()--;
1634 }
1635 } 1467 }
1636 return assigned; 1468 return assigned;
1637 } 1469 }
1638 1470
1639 void AddSourcePosition(Production* p) {
1640 DCHECK_NOT_NULL(p->tree->node);
1641 AddSourcePosition(p->tree->node, p->pc());
1642 }
1643
1644 void AddSourcePosition(TFNode* node, const byte* pc) { 1471 void AddSourcePosition(TFNode* node, const byte* pc) {
1645 int offset = static_cast<int>(pc - start_); 1472 if (node) {
1646 DCHECK_EQ(pc - start_, offset); // overflows cannot happen 1473 int offset = static_cast<int>(pc - start_);
1647 builder_->SetSourcePosition(node, offset); 1474 DCHECK_EQ(pc - start_, offset); // overflows cannot happen
1475 builder_->SetSourcePosition(node, offset);
1476 }
1648 } 1477 }
1649 }; 1478 };
1650 1479
1651 bool DecodeLocalDecls(AstLocalDecls& decls, const byte* start, 1480 bool DecodeLocalDecls(AstLocalDecls& decls, const byte* start,
1652 const byte* end) { 1481 const byte* end) {
1653 base::AccountingAllocator allocator; 1482 base::AccountingAllocator allocator;
1654 Zone tmp(&allocator); 1483 Zone tmp(&allocator);
1655 FunctionBody body = {nullptr, nullptr, nullptr, start, end}; 1484 FunctionBody body = {nullptr, nullptr, nullptr, start, end};
1656 SR_WasmDecoder decoder(&tmp, nullptr, body); 1485 SR_WasmDecoder decoder(&tmp, nullptr, body);
1657 return decoder.DecodeLocalDecls(decls); 1486 return decoder.DecodeLocalDecls(decls);
1658 } 1487 }
1659 1488
1660 TreeResult VerifyWasmCode(base::AccountingAllocator* allocator, 1489 TreeResult VerifyWasmCode(base::AccountingAllocator* allocator,
1661 FunctionBody& body) { 1490 FunctionBody& body) {
1662 Zone zone(allocator); 1491 Zone zone(allocator);
1663 SR_WasmDecoder decoder(&zone, nullptr, body); 1492 SR_WasmDecoder decoder(&zone, nullptr, body);
1664 TreeResult result = decoder.Decode(); 1493 decoder.Decode();
1665 return result; 1494 return decoder.toResult<Tree*>(nullptr);
1666 } 1495 }
1667 1496
1668 TreeResult BuildTFGraph(base::AccountingAllocator* allocator, 1497 TreeResult BuildTFGraph(base::AccountingAllocator* allocator,
1669 TFBuilder* builder, FunctionBody& body) { 1498 TFBuilder* builder, FunctionBody& body) {
1670 Zone zone(allocator); 1499 Zone zone(allocator);
1671 SR_WasmDecoder decoder(&zone, builder, body); 1500 SR_WasmDecoder decoder(&zone, builder, body);
1672 TreeResult result = decoder.Decode(); 1501 decoder.Decode();
1673 return result; 1502 return decoder.toResult<Tree*>(nullptr);
1674 } 1503 }
1675 1504
1676 1505
1677 std::ostream& operator<<(std::ostream& os, const Tree& tree) { 1506 std::ostream& operator<<(std::ostream& os, const Tree& tree) {
1678 if (tree.pc == nullptr) { 1507 if (tree.pc == nullptr) {
1679 os << "null"; 1508 os << "null";
1680 return os; 1509 return os;
1681 } 1510 }
1682 PrintF("%s", WasmOpcodes::OpcodeName(tree.opcode())); 1511 PrintF("%s", WasmOpcodes::OpcodeName(tree.opcode()));
1683 if (tree.count > 0) os << "("; 1512 if (tree.count > 0) os << "(";
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1744 WasmOpcode opcode = static_cast<WasmOpcode>(*pc); 1573 WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
1745 printf("k%s,", WasmOpcodes::OpcodeName(opcode)); 1574 printf("k%s,", WasmOpcodes::OpcodeName(opcode));
1746 1575
1747 for (size_t i = 1; i < length; i++) { 1576 for (size_t i = 1; i < length; i++) {
1748 printf(" 0x%02x,", pc[i]); 1577 printf(" 0x%02x,", pc[i]);
1749 } 1578 }
1750 1579
1751 if (body.module) { 1580 if (body.module) {
1752 switch (opcode) { 1581 switch (opcode) {
1753 case kExprCallIndirect: { 1582 case kExprCallIndirect: {
1754 SignatureIndexOperand operand(&decoder, pc); 1583 CallIndirectOperand operand(&decoder, pc);
1755 if (decoder.Validate(pc, operand)) { 1584 if (decoder.Validate(pc, operand)) {
1756 os << " // sig #" << operand.index << ": " << *operand.sig; 1585 os << " // sig #" << operand.index << ": " << *operand.sig;
1757 } 1586 }
1758 break; 1587 break;
1759 } 1588 }
1760 case kExprCallImport: { 1589 case kExprCallImport: {
1761 ImportIndexOperand operand(&decoder, pc); 1590 CallImportOperand operand(&decoder, pc);
1762 if (decoder.Validate(pc, operand)) { 1591 if (decoder.Validate(pc, operand)) {
1763 os << " // import #" << operand.index << ": " << *operand.sig; 1592 os << " // import #" << operand.index << ": " << *operand.sig;
1764 } 1593 }
1765 break; 1594 break;
1766 } 1595 }
1767 case kExprCallFunction: { 1596 case kExprCallFunction: {
1768 FunctionIndexOperand operand(&decoder, pc); 1597 CallFunctionOperand operand(&decoder, pc);
1769 if (decoder.Validate(pc, operand)) { 1598 if (decoder.Validate(pc, operand)) {
1770 os << " // function #" << operand.index << ": " << *operand.sig; 1599 os << " // function #" << operand.index << ": " << *operand.sig;
1771 } 1600 }
1772 break; 1601 break;
1773 } 1602 }
1774 default: 1603 default:
1775 break; 1604 break;
1776 } 1605 }
1777 } 1606 }
1778 1607
(...skipping 12 matching lines...) Expand all
1791 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, 1620 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals,
1792 const byte* start, const byte* end) { 1621 const byte* start, const byte* end) {
1793 FunctionBody body = {nullptr, nullptr, nullptr, start, end}; 1622 FunctionBody body = {nullptr, nullptr, nullptr, start, end};
1794 SR_WasmDecoder decoder(zone, nullptr, body); 1623 SR_WasmDecoder decoder(zone, nullptr, body);
1795 return decoder.AnalyzeLoopAssignmentForTesting(start, num_locals); 1624 return decoder.AnalyzeLoopAssignmentForTesting(start, num_locals);
1796 } 1625 }
1797 1626
1798 } // namespace wasm 1627 } // namespace wasm
1799 } // namespace internal 1628 } // namespace internal
1800 } // namespace v8 1629 } // namespace v8
OLDNEW
« no previous file with comments | « src/wasm/ast-decoder.h ('k') | src/wasm/encoder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698