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

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

Issue 2345593003: [wasm] Master CL for Binary 0xC changes. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Signed/unsigned mismatch Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/signature.h" 5 #include "src/signature.h"
6 6
7 #include "src/bit-vector.h" 7 #include "src/bit-vector.h"
8 #include "src/flags.h" 8 #include "src/flags.h"
9 #include "src/handles.h" 9 #include "src/handles.h"
10 #include "src/zone-containers.h" 10 #include "src/zone-containers.h"
(...skipping 18 matching lines...) Expand all
29 } while (false) 29 } while (false)
30 #else 30 #else
31 #define TRACE(...) 31 #define TRACE(...)
32 #endif 32 #endif
33 33
34 #define CHECK_PROTOTYPE_OPCODE(flag) \ 34 #define CHECK_PROTOTYPE_OPCODE(flag) \
35 if (!FLAG_##flag) { \ 35 if (!FLAG_##flag) { \
36 error("Invalid opcode (enable with --" #flag ")"); \ 36 error("Invalid opcode (enable with --" #flag ")"); \
37 break; \ 37 break; \
38 } 38 }
39 // TODO(titzer): this is only for intermediate migration.
40 #define IMPLICIT_FUNCTION_END 1
39 41
40 // An SsaEnv environment carries the current local variable renaming 42 // An SsaEnv environment carries the current local variable renaming
41 // as well as the current effect and control dependency in the TF graph. 43 // as well as the current effect and control dependency in the TF graph.
42 // It maintains a control state that tracks whether the environment 44 // It maintains a control state that tracks whether the environment
43 // is reachable, has reached a control end, or has been merged. 45 // is reachable, has reached a control end, or has been merged.
44 struct SsaEnv { 46 struct SsaEnv {
45 enum State { kControlEnd, kUnreachable, kReached, kMerged }; 47 enum State { kControlEnd, kUnreachable, kReached, kMerged };
46 48
47 State state; 49 State state;
48 TFNode* control; 50 TFNode* control;
(...skipping 14 matching lines...) Expand all
63 65
64 // An entry on the value stack. 66 // An entry on the value stack.
65 struct Value { 67 struct Value {
66 const byte* pc; 68 const byte* pc;
67 TFNode* node; 69 TFNode* node;
68 LocalType type; 70 LocalType type;
69 }; 71 };
70 72
71 struct Control; 73 struct Control;
72 74
73 // An entry on the control stack (i.e. if, block, loop, try). 75 struct MergeValues {
76 int32_t arity;
77 union {
78 Value* array;
79 Value first;
80 } vals; // Either multiple values or a single value.
81
82 Value& first() {
83 DCHECK_GT(arity, 0);
84 return arity == 1 ? vals.first : vals.array[0];
85 }
86 };
87
88 // IncomingBranch is used by exception handling code for managing finally's.
89 struct IncomingBranch {
90 int32_t token_value;
91 Control* target;
92 MergeValues merge;
93 };
94
95 static Value* NO_VALUE = nullptr;
96
97 enum ControlKind { kControlIf, kControlBlock, kControlLoop, kControlTry };
98
99 // An entry on the control stack (i.e. if, block, loop).
74 struct Control { 100 struct Control {
75 const byte* pc; 101 const byte* pc;
102 ControlKind kind;
76 int stack_depth; // stack height at the beginning of the construct. 103 int stack_depth; // stack height at the beginning of the construct.
77 SsaEnv* end_env; // end environment for the construct. 104 SsaEnv* end_env; // end environment for the construct.
78 SsaEnv* false_env; // false environment (only for if). 105 SsaEnv* false_env; // false environment (only for if).
79 SsaEnv* catch_env; // catch environment (only for try). 106 SsaEnv* catch_env; // catch environment (only for try).
80 TFNode* node; // result node for the construct.
81 LocalType type; // result type for the construct.
82 bool is_loop; // true if this is the inner label of a loop.
83 107
84 bool is_if() const { return *pc == kExprIf; } 108 // Values merged into the end of this control construct.
109 MergeValues merge;
85 110
86 bool is_try() const { return *pc == kExprTry; } 111 inline bool is_if() { return kind == kControlIf; }
112 inline bool is_block() { return kind == kControlBlock; }
113 inline bool is_loop() { return kind == kControlLoop; }
114 inline bool is_try() const { return kind == kControlTry; }
87 115
88 // Named constructors. 116 // Named constructors.
89 static Control Block(const byte* pc, int stack_depth, SsaEnv* end_env) { 117 static Control Block(const byte* pc, int stack_depth, SsaEnv* end_env) {
90 return {pc, stack_depth, end_env, nullptr, 118 return {pc, kControlBlock, stack_depth, end_env,
91 nullptr, nullptr, kAstEnd, false}; 119 nullptr, nullptr, {0, {NO_VALUE}}};
92 } 120 }
93 121
94 static Control If(const byte* pc, int stack_depth, SsaEnv* end_env, 122 static Control If(const byte* pc, int stack_depth, SsaEnv* end_env,
95 SsaEnv* false_env) { 123 SsaEnv* false_env) {
96 return {pc, stack_depth, end_env, false_env, 124 return {pc, kControlIf, stack_depth, end_env,
97 nullptr, nullptr, kAstStmt, false}; 125 false_env, nullptr, {0, {NO_VALUE}}};
98 } 126 }
99 127
100 static Control Loop(const byte* pc, int stack_depth, SsaEnv* end_env) { 128 static Control Loop(const byte* pc, int stack_depth, SsaEnv* end_env) {
101 return {pc, stack_depth, end_env, nullptr, nullptr, nullptr, kAstEnd, true}; 129 return {pc, kControlLoop, stack_depth, end_env,
130 nullptr, nullptr, {-1, {NO_VALUE}}};
102 } 131 }
103 132
104 static Control Try(const byte* pc, int stack_depth, SsaEnv* end_env, 133 static Control Try(const byte* pc, int stack_depth, SsaEnv* end_env,
105 SsaEnv* catch_env) { 134 SsaEnv* catch_env) {
106 return {pc, stack_depth, end_env, nullptr, 135 return {pc, kControlTry, stack_depth, end_env,
107 catch_env, nullptr, kAstEnd, false}; 136 nullptr, catch_env, {0, {NO_VALUE}}};
108 } 137 }
109 }; 138 };
110 139
111 // Macros that build nodes only if there is a graph and the current SSA 140 // Macros that build nodes only if there is a graph and the current SSA
112 // environment is reachable from start. This avoids problems with malformed 141 // environment is reachable from start. This avoids problems with malformed
113 // TF graphs when decoding inputs that have unreachable code. 142 // TF graphs when decoding inputs that have unreachable code.
114 #define BUILD(func, ...) (build() ? builder_->func(__VA_ARGS__) : nullptr) 143 #define BUILD(func, ...) (build() ? builder_->func(__VA_ARGS__) : nullptr)
115 #define BUILD0(func) (build() ? builder_->func() : nullptr) 144 #define BUILD0(func) (build() ? builder_->func() : nullptr)
116 145
117 // Generic Wasm bytecode decoder with utilities for decoding operands, 146 // Generic Wasm bytecode decoder with utilities for decoding operands,
(...skipping 14 matching lines...) Expand all
132 161
133 inline bool Validate(const byte* pc, LocalIndexOperand& operand) { 162 inline bool Validate(const byte* pc, LocalIndexOperand& operand) {
134 if (operand.index < total_locals_) { 163 if (operand.index < total_locals_) {
135 if (local_types_) { 164 if (local_types_) {
136 operand.type = local_types_->at(operand.index); 165 operand.type = local_types_->at(operand.index);
137 } else { 166 } else {
138 operand.type = kAstStmt; 167 operand.type = kAstStmt;
139 } 168 }
140 return true; 169 return true;
141 } 170 }
142 error(pc, pc + 1, "invalid local index"); 171 error(pc, pc + 1, "invalid local index: %u", operand.index);
143 return false; 172 return false;
144 } 173 }
145 174
146 inline bool Validate(const byte* pc, GlobalIndexOperand& operand) { 175 inline bool Validate(const byte* pc, GlobalIndexOperand& operand) {
147 ModuleEnv* m = module_; 176 ModuleEnv* m = module_;
148 if (m && m->module && operand.index < m->module->globals.size()) { 177 if (m && m->module && operand.index < m->module->globals.size()) {
149 operand.type = m->module->globals[operand.index].type; 178 operand.global = &m->module->globals[operand.index];
179 operand.type = operand.global->type;
150 return true; 180 return true;
151 } 181 }
152 error(pc, pc + 1, "invalid global index"); 182 error(pc, pc + 1, "invalid global index: %u", operand.index);
153 return false; 183 return false;
154 } 184 }
155 185
156 inline bool Complete(const byte* pc, CallFunctionOperand& operand) { 186 inline bool Complete(const byte* pc, CallFunctionOperand& operand) {
157 ModuleEnv* m = module_; 187 ModuleEnv* m = module_;
158 if (m && m->module && operand.index < m->module->functions.size()) { 188 if (m && m->module && operand.index < m->module->functions.size()) {
159 operand.sig = m->module->functions[operand.index].sig; 189 operand.sig = m->module->functions[operand.index].sig;
160 return true; 190 return true;
161 } 191 }
162 return false; 192 return false;
163 } 193 }
164 194
165 inline bool Validate(const byte* pc, CallFunctionOperand& operand) { 195 inline bool Validate(const byte* pc, CallFunctionOperand& operand) {
166 if (Complete(pc, operand)) { 196 if (Complete(pc, operand)) {
167 uint32_t expected = static_cast<uint32_t>(operand.sig->parameter_count());
168 if (operand.arity != expected) {
169 error(pc, pc + 1,
170 "arity mismatch in direct function call (expected %u, got %u)",
171 expected, operand.arity);
172 return false;
173 }
174 return true; 197 return true;
175 } 198 }
176 error(pc, pc + 1, "invalid function index"); 199 error(pc, pc + 1, "invalid function index: %u", operand.index);
177 return false; 200 return false;
178 } 201 }
179 202
180 inline bool Complete(const byte* pc, CallIndirectOperand& operand) { 203 inline bool Complete(const byte* pc, CallIndirectOperand& operand) {
181 ModuleEnv* m = module_; 204 ModuleEnv* m = module_;
182 if (m && m->module && operand.index < m->module->signatures.size()) { 205 if (m && m->module && operand.index < m->module->signatures.size()) {
183 operand.sig = m->module->signatures[operand.index]; 206 operand.sig = m->module->signatures[operand.index];
184 return true; 207 return true;
185 } 208 }
186 return false; 209 return false;
187 } 210 }
188 211
189 inline bool Validate(const byte* pc, CallIndirectOperand& operand) { 212 inline bool Validate(const byte* pc, CallIndirectOperand& operand) {
190 if (Complete(pc, operand)) { 213 if (Complete(pc, operand)) {
191 uint32_t expected = static_cast<uint32_t>(operand.sig->parameter_count());
192 if (operand.arity != expected) {
193 error(pc, pc + 1,
194 "arity mismatch in indirect function call (expected %u, got %u)",
195 expected, operand.arity);
196 return false;
197 }
198 return true; 214 return true;
199 } 215 }
200 error(pc, pc + 1, "invalid signature index"); 216 error(pc, pc + 1, "invalid signature index: #%u", operand.index);
201 return false;
202 }
203
204 inline bool Complete(const byte* pc, CallImportOperand& operand) {
205 ModuleEnv* m = module_;
206 if (m && m->module && operand.index < m->module->import_table.size()) {
207 operand.sig = m->module->import_table[operand.index].sig;
208 return true;
209 }
210 return false;
211 }
212
213 inline bool Validate(const byte* pc, CallImportOperand& operand) {
214 if (Complete(pc, operand)) {
215 uint32_t expected = static_cast<uint32_t>(operand.sig->parameter_count());
216 if (operand.arity != expected) {
217 error(pc, pc + 1, "arity mismatch in import call (expected %u, got %u)",
218 expected, operand.arity);
219 return false;
220 }
221 return true;
222 }
223 error(pc, pc + 1, "invalid signature index");
224 return false; 217 return false;
225 } 218 }
226 219
227 inline bool Validate(const byte* pc, BreakDepthOperand& operand, 220 inline bool Validate(const byte* pc, BreakDepthOperand& operand,
228 ZoneVector<Control>& control) { 221 ZoneVector<Control>& control) {
229 if (operand.arity > 1) {
230 error(pc, pc + 1, "invalid arity for br or br_if");
231 return false;
232 }
233 if (operand.depth < control.size()) { 222 if (operand.depth < control.size()) {
234 operand.target = &control[control.size() - operand.depth - 1]; 223 operand.target = &control[control.size() - operand.depth - 1];
235 return true; 224 return true;
236 } 225 }
237 error(pc, pc + 1, "invalid break depth"); 226 error(pc, pc + 1, "invalid break depth: %u", operand.depth);
238 return false; 227 return false;
239 } 228 }
240 229
241 bool Validate(const byte* pc, BranchTableOperand& operand, 230 bool Validate(const byte* pc, BranchTableOperand& operand,
242 size_t block_depth) { 231 size_t block_depth) {
243 if (operand.arity > 1) {
244 error(pc, pc + 1, "invalid arity for break");
245 return false;
246 }
247 // Verify table. 232 // Verify table.
248 for (uint32_t i = 0; i < operand.table_count + 1; ++i) { 233 for (uint32_t i = 0; i < operand.table_count + 1; ++i) {
249 uint32_t target = operand.read_entry(this, i); 234 uint32_t target = operand.read_entry(this, i);
250 if (target >= block_depth) { 235 if (target >= block_depth) {
251 error(operand.table + i * 2, "improper branch in br_table"); 236 error(operand.table + i * 2, "improper branch in br_table");
252 return false; 237 return false;
253 } 238 }
254 } 239 }
255 return true; 240 return true;
256 } 241 }
257 242
258 unsigned OpcodeArity(const byte* pc) {
259 #define DECLARE_ARITY(name, ...) \
260 static const LocalType kTypes_##name[] = {__VA_ARGS__}; \
261 static const int kArity_##name = \
262 static_cast<int>(arraysize(kTypes_##name) - 1);
263
264 FOREACH_SIGNATURE(DECLARE_ARITY);
265 #undef DECLARE_ARITY
266
267 switch (static_cast<WasmOpcode>(*pc)) {
268 case kExprI8Const:
269 case kExprI32Const:
270 case kExprI64Const:
271 case kExprF64Const:
272 case kExprF32Const:
273 case kExprGetLocal:
274 case kExprGetGlobal:
275 case kExprNop:
276 case kExprUnreachable:
277 case kExprEnd:
278 case kExprBlock:
279 case kExprThrow:
280 case kExprTry:
281 case kExprLoop:
282 return 0;
283
284 case kExprSetGlobal:
285 case kExprSetLocal:
286 case kExprElse:
287 case kExprCatch:
288 return 1;
289
290 case kExprBr: {
291 BreakDepthOperand operand(this, pc);
292 return operand.arity;
293 }
294 case kExprBrIf: {
295 BreakDepthOperand operand(this, pc);
296 return 1 + operand.arity;
297 }
298 case kExprBrTable: {
299 BranchTableOperand operand(this, pc);
300 return 1 + operand.arity;
301 }
302
303 case kExprIf:
304 return 1;
305 case kExprSelect:
306 return 3;
307
308 case kExprCallFunction: {
309 CallFunctionOperand operand(this, pc);
310 return operand.arity;
311 }
312 case kExprCallIndirect: {
313 CallIndirectOperand operand(this, pc);
314 return 1 + operand.arity;
315 }
316 case kExprCallImport: {
317 CallImportOperand operand(this, pc);
318 return operand.arity;
319 }
320 case kExprReturn: {
321 ReturnArityOperand operand(this, pc);
322 return operand.arity;
323 }
324
325 #define DECLARE_OPCODE_CASE(name, opcode, sig) \
326 case kExpr##name: \
327 return kArity_##sig;
328
329 FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
330 FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
331 FOREACH_MISC_MEM_OPCODE(DECLARE_OPCODE_CASE)
332 FOREACH_SIMPLE_OPCODE(DECLARE_OPCODE_CASE)
333 FOREACH_SIMPLE_MEM_OPCODE(DECLARE_OPCODE_CASE)
334 FOREACH_ASMJS_COMPAT_OPCODE(DECLARE_OPCODE_CASE)
335 FOREACH_SIMD_0_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
336 #undef DECLARE_OPCODE_CASE
337 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
338 FOREACH_SIMD_1_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
339 #undef DECLARE_OPCODE_CASE
340 return 1;
341 default:
342 UNREACHABLE();
343 return 0;
344 }
345 }
346
347 unsigned OpcodeLength(const byte* pc) { 243 unsigned OpcodeLength(const byte* pc) {
348 switch (static_cast<WasmOpcode>(*pc)) { 244 switch (static_cast<WasmOpcode>(*pc)) {
349 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: 245 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
350 FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE) 246 FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
351 FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE) 247 FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
352 #undef DECLARE_OPCODE_CASE 248 #undef DECLARE_OPCODE_CASE
353 { 249 {
354 MemoryAccessOperand operand(this, pc, UINT32_MAX); 250 MemoryAccessOperand operand(this, pc, UINT32_MAX);
355 return 1 + operand.length; 251 return 1 + operand.length;
356 } 252 }
357 case kExprBr: 253 case kExprBr:
358 case kExprBrIf: { 254 case kExprBrIf: {
359 BreakDepthOperand operand(this, pc); 255 BreakDepthOperand operand(this, pc);
360 return 1 + operand.length; 256 return 1 + operand.length;
361 } 257 }
362 case kExprSetGlobal: 258 case kExprSetGlobal:
363 case kExprGetGlobal: { 259 case kExprGetGlobal: {
364 GlobalIndexOperand operand(this, pc); 260 GlobalIndexOperand operand(this, pc);
365 return 1 + operand.length; 261 return 1 + operand.length;
366 } 262 }
367 263
368 case kExprCallFunction: { 264 case kExprCallFunction: {
369 CallFunctionOperand operand(this, pc); 265 CallFunctionOperand operand(this, pc);
370 return 1 + operand.length; 266 return 1 + operand.length;
371 } 267 }
372 case kExprCallIndirect: { 268 case kExprCallIndirect: {
373 CallIndirectOperand operand(this, pc); 269 CallIndirectOperand operand(this, pc);
374 return 1 + operand.length; 270 return 1 + operand.length;
375 } 271 }
376 case kExprCallImport: { 272
377 CallImportOperand operand(this, pc); 273 case kExprTry:
274 case kExprIf: // fall thru
275 case kExprLoop:
276 case kExprBlock: {
277 BlockTypeOperand operand(this, pc);
378 return 1 + operand.length; 278 return 1 + operand.length;
379 } 279 }
380 280
381 case kExprSetLocal: 281 case kExprSetLocal:
282 case kExprTeeLocal:
382 case kExprGetLocal: 283 case kExprGetLocal:
383 case kExprCatch: { 284 case kExprCatch: {
384 LocalIndexOperand operand(this, pc); 285 LocalIndexOperand operand(this, pc);
385 return 1 + operand.length; 286 return 1 + operand.length;
386 } 287 }
387 case kExprBrTable: { 288 case kExprBrTable: {
388 BranchTableOperand operand(this, pc); 289 BranchTableOperand operand(this, pc);
389 return 1 + operand.length; 290 return 1 + operand.length;
390 } 291 }
391 case kExprI32Const: { 292 case kExprI32Const: {
392 ImmI32Operand operand(this, pc); 293 ImmI32Operand operand(this, pc);
393 return 1 + operand.length; 294 return 1 + operand.length;
394 } 295 }
395 case kExprI64Const: { 296 case kExprI64Const: {
396 ImmI64Operand operand(this, pc); 297 ImmI64Operand operand(this, pc);
397 return 1 + operand.length; 298 return 1 + operand.length;
398 } 299 }
399 case kExprI8Const: 300 case kExprI8Const:
400 return 2; 301 return 2;
401 case kExprF32Const: 302 case kExprF32Const:
402 return 5; 303 return 5;
403 case kExprF64Const: 304 case kExprF64Const:
404 return 9; 305 return 9;
405 case kExprReturn: {
406 ReturnArityOperand operand(this, pc);
407 return 1 + operand.length;
408 }
409 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
410 FOREACH_SIMD_0_OPERAND_OPCODE(DECLARE_OPCODE_CASE) { return 2; }
411 FOREACH_SIMD_1_OPERAND_OPCODE(DECLARE_OPCODE_CASE) { return 3; }
412 #undef DECLARE_OPCODE_CASE
413 default: 306 default:
414 return 1; 307 return 1;
415 } 308 }
416 } 309 }
417 }; 310 };
418 311
419 // The full WASM decoder for bytecode. Both verifies bytecode and generates 312 // The full WASM decoder for bytecode. Both verifies bytecode and generates
420 // a TurboFan IR graph. 313 // a TurboFan IR graph.
421 class WasmFullDecoder : public WasmDecoder { 314 class WasmFullDecoder : public WasmDecoder {
422 public: 315 public:
423 WasmFullDecoder(Zone* zone, TFBuilder* builder, const FunctionBody& body) 316 WasmFullDecoder(Zone* zone, TFBuilder* builder, const FunctionBody& body)
424 : WasmDecoder(body.module, body.sig, body.start, body.end), 317 : WasmDecoder(body.module, body.sig, body.start, body.end),
425 zone_(zone), 318 zone_(zone),
426 builder_(builder), 319 builder_(builder),
427 base_(body.base), 320 base_(body.base),
428 local_type_vec_(zone), 321 local_type_vec_(zone),
429 stack_(zone), 322 stack_(zone),
430 control_(zone) { 323 control_(zone),
324 last_end_found_(false) {
431 local_types_ = &local_type_vec_; 325 local_types_ = &local_type_vec_;
432 } 326 }
433 327
434 bool Decode() { 328 bool Decode() {
435 base::ElapsedTimer decode_timer; 329 base::ElapsedTimer decode_timer;
436 if (FLAG_trace_wasm_decode_time) { 330 if (FLAG_trace_wasm_decode_time) {
437 decode_timer.Start(); 331 decode_timer.Start();
438 } 332 }
439 stack_.clear(); 333 stack_.clear();
440 control_.clear(); 334 control_.clear();
441 335
442 if (end_ < pc_) { 336 if (end_ < pc_) {
443 error(pc_, "function body end < start"); 337 error(pc_, "function body end < start");
444 return false; 338 return false;
445 } 339 }
446 340
447 DecodeLocalDecls(); 341 DecodeLocalDecls();
448 InitSsaEnv(); 342 InitSsaEnv();
449 DecodeFunctionBody(); 343 DecodeFunctionBody();
450 344
451 if (failed()) return TraceFailed(); 345 if (failed()) return TraceFailed();
452 346
347 #if IMPLICIT_FUNCTION_END
348 // With implicit end support (old style), the function block
349 // remains on the stack. Other control blocks are an error.
350 if (control_.size() > 1) {
351 error(pc_, control_.back().pc, "unterminated control structure");
352 return TraceFailed();
353 }
354
355 // Assume an implicit end to the function body block.
356 if (control_.size() == 1) {
357 Control* c = &control_.back();
358 if (ssa_env_->go()) {
359 FallThruTo(c);
360 }
361
362 if (c->end_env->go()) {
363 // Push the end values onto the stack.
364 stack_.resize(c->stack_depth);
365 if (c->merge.arity == 1) {
366 stack_.push_back(c->merge.vals.first);
367 } else {
368 for (int i = 0; i < c->merge.arity; i++) {
369 stack_.push_back(c->merge.vals.array[i]);
370 }
371 }
372
373 TRACE(" @%-8d #xx:%-20s|", startrel(pc_), "ImplicitReturn");
374 SetEnv("function:end", c->end_env);
375 DoReturn();
376 TRACE("\n");
377 }
378 }
379 #else
453 if (!control_.empty()) { 380 if (!control_.empty()) {
454 error(pc_, control_.back().pc, "unterminated control structure"); 381 error(pc_, control_.back().pc, "unterminated control structure");
455 return TraceFailed(); 382 return TraceFailed();
456 } 383 }
457 384
458 if (ssa_env_->go()) { 385 if (!last_end_found_) {
459 TRACE(" @%-8d #xx:%-20s|", startrel(pc_), "ImplicitReturn"); 386 error(pc_, pc_, "function body must end with \"end\" opcode.");
460 DoReturn(); 387 return false;
461 if (failed()) return TraceFailed();
462 TRACE("\n");
463 } 388 }
389 #endif
464 390
465 if (FLAG_trace_wasm_decode_time) { 391 if (FLAG_trace_wasm_decode_time) {
466 double ms = decode_timer.Elapsed().InMillisecondsF(); 392 double ms = decode_timer.Elapsed().InMillisecondsF();
467 PrintF("wasm-decode ok (%0.3f ms)\n\n", ms); 393 PrintF("wasm-decode %s (%0.3f ms)\n\n", ok() ? "ok" : "failed", ms);
468 } else { 394 } else {
469 TRACE("wasm-decode ok\n\n"); 395 TRACE("wasm-decode %s\n\n", ok() ? "ok" : "failed");
470 } 396 }
471 397
472 return true; 398 return true;
473 } 399 }
474 400
475 bool TraceFailed() { 401 bool TraceFailed() {
476 TRACE("wasm-error module+%-6d func+%d: %s\n\n", baserel(error_pc_), 402 TRACE("wasm-error module+%-6d func+%d: %s\n\n", baserel(error_pc_),
477 startrel(error_pc_), error_msg_.get()); 403 startrel(error_pc_), error_msg_.get());
478 return false; 404 return false;
479 } 405 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
512 438
513 Zone* zone_; 439 Zone* zone_;
514 TFBuilder* builder_; 440 TFBuilder* builder_;
515 const byte* base_; 441 const byte* base_;
516 442
517 SsaEnv* ssa_env_; 443 SsaEnv* ssa_env_;
518 444
519 ZoneVector<LocalType> local_type_vec_; // types of local variables. 445 ZoneVector<LocalType> local_type_vec_; // types of local variables.
520 ZoneVector<Value> stack_; // stack of values. 446 ZoneVector<Value> stack_; // stack of values.
521 ZoneVector<Control> control_; // stack of blocks, loops, and ifs. 447 ZoneVector<Control> control_; // stack of blocks, loops, and ifs.
448 bool last_end_found_;
522 449
523 inline bool build() { return builder_ && ssa_env_->go(); } 450 inline bool build() { return builder_ && ssa_env_->go(); }
524 451
525 void InitSsaEnv() { 452 void InitSsaEnv() {
526 TFNode* start = nullptr; 453 TFNode* start = nullptr;
527 SsaEnv* ssa_env = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv))); 454 SsaEnv* ssa_env = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
528 size_t size = sizeof(TFNode*) * EnvironmentCount(); 455 size_t size = sizeof(TFNode*) * EnvironmentCount();
529 ssa_env->state = SsaEnv::kReached; 456 ssa_env->state = SsaEnv::kReached;
530 ssa_env->locals = 457 ssa_env->locals =
531 size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr; 458 size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr;
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
632 total_locals_ = local_type_vec_.size(); 559 total_locals_ = local_type_vec_.size();
633 } 560 }
634 561
635 // Decodes the body of a function. 562 // Decodes the body of a function.
636 void DecodeFunctionBody() { 563 void DecodeFunctionBody() {
637 TRACE("wasm-decode %p...%p (module+%d, %d bytes) %s\n", 564 TRACE("wasm-decode %p...%p (module+%d, %d bytes) %s\n",
638 reinterpret_cast<const void*>(start_), 565 reinterpret_cast<const void*>(start_),
639 reinterpret_cast<const void*>(limit_), baserel(pc_), 566 reinterpret_cast<const void*>(limit_), baserel(pc_),
640 static_cast<int>(limit_ - start_), builder_ ? "graph building" : ""); 567 static_cast<int>(limit_ - start_), builder_ ? "graph building" : "");
641 568
569 {
570 // Set up initial function block.
571 SsaEnv* break_env = ssa_env_;
572 SetEnv("initial env", Steal(break_env));
573 PushBlock(break_env);
574 Control* c = &control_.back();
575 c->merge.arity = static_cast<uint32_t>(sig_->return_count());
576
577 if (c->merge.arity == 1) {
578 c->merge.vals.first = {pc_, nullptr, sig_->GetReturn(0)};
579 } else if (c->merge.arity > 1) {
580 c->merge.vals.array = zone_->NewArray<Value>(c->merge.arity);
581 for (unsigned i = 0; i < c->merge.arity; i++) {
582 c->merge.vals.array[i] = {pc_, nullptr, sig_->GetReturn(i)};
583 }
584 }
585 }
586
642 if (pc_ >= limit_) return; // Nothing to do. 587 if (pc_ >= limit_) return; // Nothing to do.
643 588
644 while (true) { // decoding loop. 589 while (true) { // decoding loop.
645 unsigned len = 1; 590 unsigned len = 1;
646 WasmOpcode opcode = static_cast<WasmOpcode>(*pc_); 591 WasmOpcode opcode = static_cast<WasmOpcode>(*pc_);
647 if (!WasmOpcodes::IsPrefixOpcode(opcode)) { 592 if (!WasmOpcodes::IsPrefixOpcode(opcode)) {
648 TRACE(" @%-8d #%02x:%-20s|", startrel(pc_), opcode, 593 TRACE(" @%-8d #%02x:%-20s|", startrel(pc_), opcode,
649 WasmOpcodes::ShortOpcodeName(opcode)); 594 WasmOpcodes::ShortOpcodeName(opcode));
650 } 595 }
651 596
652 FunctionSig* sig = WasmOpcodes::Signature(opcode); 597 FunctionSig* sig = WasmOpcodes::Signature(opcode);
653 if (sig) { 598 if (sig) {
654 BuildSimpleOperator(opcode, sig); 599 BuildSimpleOperator(opcode, sig);
655 } else { 600 } else {
656 // Complex bytecode. 601 // Complex bytecode.
657 switch (opcode) { 602 switch (opcode) {
658 case kExprNop: 603 case kExprNop:
659 Push(kAstStmt, nullptr);
660 break; 604 break;
661 case kExprBlock: { 605 case kExprBlock: {
662 // The break environment is the outer environment. 606 // The break environment is the outer environment.
607 BlockTypeOperand operand(this, pc_);
663 SsaEnv* break_env = ssa_env_; 608 SsaEnv* break_env = ssa_env_;
664 PushBlock(break_env); 609 PushBlock(break_env);
665 SetEnv("block:start", Steal(break_env)); 610 SetEnv("block:start", Steal(break_env));
611 SetBlockType(&control_.back(), operand);
612 len = 1 + operand.length;
666 break; 613 break;
667 } 614 }
668 case kExprThrow: { 615 case kExprThrow: {
669 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype); 616 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype);
670 Pop(0, kAstI32); 617 Pop(0, kAstI32);
671 618
672 // TODO(jpp): start exception propagation. 619 // TODO(jpp): start exception propagation.
673 break; 620 break;
674 } 621 }
675 case kExprTry: { 622 case kExprTry: {
676 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype); 623 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype);
624 BlockTypeOperand operand(this, pc_);
677 SsaEnv* outer_env = ssa_env_; 625 SsaEnv* outer_env = ssa_env_;
678 SsaEnv* try_env = Steal(outer_env); 626 SsaEnv* try_env = Steal(outer_env);
679 SsaEnv* catch_env = Split(try_env); 627 SsaEnv* catch_env = Split(try_env);
680 PushTry(outer_env, catch_env); 628 PushTry(outer_env, catch_env);
681 SetEnv("try:start", try_env); 629 SetEnv("try_catch:start", try_env);
630 SetBlockType(&control_.back(), operand);
631 len = 1 + operand.length;
682 break; 632 break;
683 } 633 }
684 case kExprCatch: { 634 case kExprCatch: {
685 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype); 635 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype);
686 LocalIndexOperand operand(this, pc_); 636 LocalIndexOperand operand(this, pc_);
687 len = 1 + operand.length; 637 len = 1 + operand.length;
688 638
689 if (control_.empty()) { 639 if (control_.empty()) {
690 error(pc_, "catch does not match a any try"); 640 error(pc_, "catch does not match any try");
691 break; 641 break;
692 } 642 }
693 643
694 Control* c = &control_.back(); 644 Control* c = &control_.back();
695 if (!c->is_try()) { 645 if (!c->is_try()) {
696 error(pc_, "catch does not match a try"); 646 error(pc_, "catch does not match any try");
697 break; 647 break;
698 } 648 }
699 649
700 if (c->catch_env == nullptr) { 650 if (c->catch_env == nullptr) {
701 error(pc_, "catch already present for try with catch"); 651 error(pc_, "catch already present for try with catch");
702 break; 652 break;
703 } 653 }
704 654
705 Goto(ssa_env_, c->end_env); 655 Goto(ssa_env_, c->end_env);
706 656
707 SsaEnv* catch_env = c->catch_env; 657 SsaEnv* catch_env = c->catch_env;
708 c->catch_env = nullptr; 658 c->catch_env = nullptr;
709 SetEnv("catch:begin", catch_env); 659 SetEnv("catch:begin", catch_env);
710 660
711 if (Validate(pc_, operand)) { 661 if (Validate(pc_, operand)) {
712 // TODO(jpp): figure out how thrown value is propagated. It is 662 // TODO(jpp): figure out how thrown value is propagated. It is
713 // unlikely to be a value on the stack. 663 // unlikely to be a value on the stack.
714 if (ssa_env_->locals) { 664 if (ssa_env_->locals) {
715 ssa_env_->locals[operand.index] = nullptr; 665 ssa_env_->locals[operand.index] = nullptr;
716 } 666 }
717 } 667 }
718 668
719 PopUpTo(c->stack_depth); 669 PopUpTo(c->stack_depth);
720
721 break; 670 break;
722 } 671 }
723 case kExprLoop: { 672 case kExprLoop: {
724 // The break environment is the outer environment. 673 BlockTypeOperand operand(this, pc_);
725 SsaEnv* break_env = ssa_env_; 674 SsaEnv* finish_try_env = Steal(ssa_env_);
726 PushBlock(break_env);
727 SsaEnv* finish_try_env = Steal(break_env);
728 // The continue environment is the inner environment. 675 // The continue environment is the inner environment.
729 PrepareForLoop(pc_, finish_try_env); 676 PrepareForLoop(pc_, finish_try_env);
730 SetEnv("loop:start", Split(finish_try_env)); 677 SetEnv("loop:start", Split(finish_try_env));
731 ssa_env_->SetNotMerged(); 678 ssa_env_->SetNotMerged();
732 PushLoop(finish_try_env); 679 PushLoop(finish_try_env);
680 SetBlockType(&control_.back(), operand);
681 len = 1 + operand.length;
733 break; 682 break;
734 } 683 }
735 case kExprIf: { 684 case kExprIf: {
736 // Condition on top of stack. Split environments for branches. 685 // Condition on top of stack. Split environments for branches.
686 BlockTypeOperand operand(this, pc_);
737 Value cond = Pop(0, kAstI32); 687 Value cond = Pop(0, kAstI32);
738 TFNode* if_true = nullptr; 688 TFNode* if_true = nullptr;
739 TFNode* if_false = nullptr; 689 TFNode* if_false = nullptr;
740 BUILD(Branch, cond.node, &if_true, &if_false); 690 BUILD(Branch, cond.node, &if_true, &if_false);
741 SsaEnv* end_env = ssa_env_; 691 SsaEnv* end_env = ssa_env_;
742 SsaEnv* false_env = Split(ssa_env_); 692 SsaEnv* false_env = Split(ssa_env_);
743 false_env->control = if_false; 693 false_env->control = if_false;
744 SsaEnv* true_env = Steal(ssa_env_); 694 SsaEnv* true_env = Steal(ssa_env_);
745 true_env->control = if_true; 695 true_env->control = if_true;
746 PushIf(end_env, false_env); 696 PushIf(end_env, false_env);
747 SetEnv("if:true", true_env); 697 SetEnv("if:true", true_env);
698 SetBlockType(&control_.back(), operand);
699 len = 1 + operand.length;
748 break; 700 break;
749 } 701 }
750 case kExprElse: { 702 case kExprElse: {
751 if (control_.empty()) { 703 if (control_.empty()) {
752 error(pc_, "else does not match any if"); 704 error(pc_, "else does not match any if");
753 break; 705 break;
754 } 706 }
755 Control* c = &control_.back(); 707 Control* c = &control_.back();
756 if (!c->is_if()) { 708 if (!c->is_if()) {
757 error(pc_, c->pc, "else does not match an if"); 709 error(pc_, c->pc, "else does not match an if");
758 break; 710 break;
759 } 711 }
760 if (c->false_env == nullptr) { 712 if (c->false_env == nullptr) {
761 error(pc_, c->pc, "else already present for if"); 713 error(pc_, c->pc, "else already present for if");
762 break; 714 break;
763 } 715 }
764 Value val = PopUpTo(c->stack_depth); 716 FallThruTo(c);
765 MergeInto(c->end_env, &c->node, &c->type, val);
766 // Switch to environment for false branch. 717 // Switch to environment for false branch.
718 stack_.resize(c->stack_depth);
767 SetEnv("if_else:false", c->false_env); 719 SetEnv("if_else:false", c->false_env);
768 c->false_env = nullptr; // record that an else is already seen 720 c->false_env = nullptr; // record that an else is already seen
769 break; 721 break;
770 } 722 }
771 case kExprEnd: { 723 case kExprEnd: {
772 if (control_.empty()) { 724 if (control_.empty()) {
773 error(pc_, "end does not match any if, try, or block"); 725 error(pc_, "end does not match any if, try, or block");
774 break; 726 return;
775 } 727 }
776 const char* name = "block:end"; 728 const char* name = "block:end";
777 Control* c = &control_.back(); 729 Control* c = &control_.back();
778 Value val = PopUpTo(c->stack_depth); 730 if (c->is_loop()) {
779 if (c->is_loop) { 731 // A loop just leaves the values on the stack.
780 // Loops always push control in pairs. 732 TypeCheckLoopFallThru(c);
781 PopControl(); 733 PopControl();
782 c = &control_.back(); 734 SetEnv("loop:end", ssa_env_);
783 name = "loop:end"; 735 break;
784 } else if (c->is_if()) { 736 }
737 if (c->is_if()) {
785 if (c->false_env != nullptr) { 738 if (c->false_env != nullptr) {
786 // End the true branch of a one-armed if. 739 // End the true branch of a one-armed if.
787 Goto(c->false_env, c->end_env); 740 Goto(c->false_env, c->end_env);
788 val = {val.pc, nullptr, kAstStmt}; 741 if (ssa_env_->go() && stack_.size() != c->stack_depth) {
742 error(pc_, pc_, "end of if expected empty stack");
743 stack_.resize(c->stack_depth);
744 }
745 if (c->merge.arity > 0) {
746 error(pc_, pc_, "non-void one-armed if");
747 }
789 name = "if:merge"; 748 name = "if:merge";
790 } else { 749 } else {
791 // End the false branch of a two-armed if. 750 // End the false branch of a two-armed if.
792 name = "if_else:merge"; 751 name = "if_else:merge";
793 } 752 }
794 } else if (c->is_try()) { 753 } else if (c->is_try()) {
795 name = "try:end"; 754 name = "try:end";
796 755
797 // validate that catch was seen. 756 // validate that catch was seen.
798 if (c->catch_env != nullptr) { 757 if (c->catch_env != nullptr) {
799 error(pc_, "missing catch in try"); 758 error(pc_, "missing catch in try");
800 break; 759 break;
801 } 760 }
802 } 761 }
762 FallThruTo(c);
763 SetEnv(name, c->end_env);
803 764
804 if (ssa_env_->go()) { 765 // Push the end values onto the stack.
805 // Adds a fallthrough edge to the next control block. 766 stack_.resize(c->stack_depth);
806 MergeInto(c->end_env, &c->node, &c->type, val); 767 if (c->merge.arity == 1) {
768 stack_.push_back(c->merge.vals.first);
769 } else {
770 for (int i = 0; i < c->merge.arity; i++) {
771 stack_.push_back(c->merge.vals.array[i]);
772 }
807 } 773 }
808 SetEnv(name, c->end_env); 774
809 stack_.resize(c->stack_depth);
810 Push(c->type, c->node);
811 PopControl(); 775 PopControl();
776
777 if (control_.empty()) {
778 // If the last (implicit) control was popped, check we are at end.
779 if (pc_ + 1 != end_) {
780 error(pc_, pc_ + 1, "trailing code after function end");
781 }
782 last_end_found_ = true;
783 if (ssa_env_->go()) {
784 // The result of the block is the return value.
785 TRACE(" @%-8d #xx:%-20s|", startrel(pc_), "ImplicitReturn");
786 DoReturn();
787 TRACE("\n");
788 }
789 return;
790 }
812 break; 791 break;
813 } 792 }
814 case kExprSelect: { 793 case kExprSelect: {
815 Value cond = Pop(2, kAstI32); 794 Value cond = Pop(2, kAstI32);
816 Value fval = Pop(); 795 Value fval = Pop();
817 Value tval = Pop(); 796 Value tval = Pop();
818 if (tval.type == kAstStmt || tval.type != fval.type) { 797 if (tval.type == kAstStmt || tval.type != fval.type) {
819 if (tval.type != kAstEnd && fval.type != kAstEnd) { 798 if (tval.type != kAstEnd && fval.type != kAstEnd) {
820 error(pc_, "type mismatch in select"); 799 error(pc_, "type mismatch in select");
821 break; 800 break;
(...skipping 10 matching lines...) Expand all
832 TFNode* phi = builder_->Phi(tval.type, 2, vals, merge); 811 TFNode* phi = builder_->Phi(tval.type, 2, vals, merge);
833 Push(tval.type, phi); 812 Push(tval.type, phi);
834 ssa_env_->control = merge; 813 ssa_env_->control = merge;
835 } else { 814 } else {
836 Push(tval.type, nullptr); 815 Push(tval.type, nullptr);
837 } 816 }
838 break; 817 break;
839 } 818 }
840 case kExprBr: { 819 case kExprBr: {
841 BreakDepthOperand operand(this, pc_); 820 BreakDepthOperand operand(this, pc_);
842 Value val = {pc_, nullptr, kAstStmt};
843 if (operand.arity) val = Pop();
844 if (Validate(pc_, operand, control_)) { 821 if (Validate(pc_, operand, control_)) {
845 BreakTo(operand.target, val); 822 BreakTo(&control_[control_.size() - operand.depth - 1]);
846 } 823 }
847 len = 1 + operand.length; 824 len = 1 + operand.length;
848 Push(kAstEnd, nullptr); 825 EndControl();
849 break; 826 break;
850 } 827 }
851 case kExprBrIf: { 828 case kExprBrIf: {
852 BreakDepthOperand operand(this, pc_); 829 BreakDepthOperand operand(this, pc_);
853 Value cond = Pop(operand.arity, kAstI32); 830 Value cond = Pop(0, kAstI32);
854 Value val = {pc_, nullptr, kAstStmt};
855 if (operand.arity == 1) val = Pop();
856 if (ok() && Validate(pc_, operand, control_)) { 831 if (ok() && Validate(pc_, operand, control_)) {
857 SsaEnv* fenv = ssa_env_; 832 SsaEnv* fenv = ssa_env_;
858 SsaEnv* tenv = Split(fenv); 833 SsaEnv* tenv = Split(fenv);
859 fenv->SetNotMerged(); 834 fenv->SetNotMerged();
860 BUILD(Branch, cond.node, &tenv->control, &fenv->control); 835 BUILD(Branch, cond.node, &tenv->control, &fenv->control);
861 ssa_env_ = tenv; 836 ssa_env_ = tenv;
862 BreakTo(operand.target, val); 837 BreakTo(&control_[control_.size() - operand.depth - 1]);
863 ssa_env_ = fenv; 838 ssa_env_ = fenv;
864 } 839 }
865 len = 1 + operand.length; 840 len = 1 + operand.length;
866 Push(kAstStmt, nullptr);
867 break; 841 break;
868 } 842 }
869 case kExprBrTable: { 843 case kExprBrTable: {
870 BranchTableOperand operand(this, pc_); 844 BranchTableOperand operand(this, pc_);
871 if (Validate(pc_, operand, control_.size())) { 845 if (Validate(pc_, operand, control_.size())) {
872 Value key = Pop(operand.arity, kAstI32); 846 Value key = Pop(0, kAstI32);
873 Value val = {pc_, nullptr, kAstStmt};
874 if (operand.arity == 1) val = Pop();
875 if (failed()) break; 847 if (failed()) break;
876 848
877 SsaEnv* break_env = ssa_env_; 849 SsaEnv* break_env = ssa_env_;
878 if (operand.table_count > 0) { 850 if (operand.table_count > 0) {
879 // Build branches to the various blocks based on the table. 851 // Build branches to the various blocks based on the table.
880 TFNode* sw = BUILD(Switch, operand.table_count + 1, key.node); 852 TFNode* sw = BUILD(Switch, operand.table_count + 1, key.node);
881 853
882 SsaEnv* copy = Steal(break_env); 854 SsaEnv* copy = Steal(break_env);
883 ssa_env_ = copy; 855 ssa_env_ = copy;
884 for (uint32_t i = 0; i < operand.table_count + 1; ++i) { 856 for (uint32_t i = 0; i < operand.table_count + 1; ++i) {
885 uint16_t target = operand.read_entry(this, i); 857 uint16_t target = operand.read_entry(this, i);
886 ssa_env_ = Split(copy); 858 ssa_env_ = Split(copy);
887 ssa_env_->control = (i == operand.table_count) 859 ssa_env_->control = (i == operand.table_count)
888 ? BUILD(IfDefault, sw) 860 ? BUILD(IfDefault, sw)
889 : BUILD(IfValue, i, sw); 861 : BUILD(IfValue, i, sw);
890 int depth = target; 862 BreakTo(&control_[control_.size() - target - 1]);
891 Control* c = &control_[control_.size() - depth - 1];
892 MergeInto(c->end_env, &c->node, &c->type, val);
893 } 863 }
894 } else { 864 } else {
895 // Only a default target. Do the equivalent of br. 865 // Only a default target. Do the equivalent of br.
896 uint16_t target = operand.read_entry(this, 0); 866 uint16_t target = operand.read_entry(this, 0);
897 int depth = target; 867 BreakTo(&control_[control_.size() - target - 1]);
898 Control* c = &control_[control_.size() - depth - 1];
899 MergeInto(c->end_env, &c->node, &c->type, val);
900 } 868 }
901 // br_table ends the control flow like br. 869 // br_table ends the control flow like br.
902 ssa_env_ = break_env; 870 ssa_env_ = break_env;
903 Push(kAstStmt, nullptr);
904 } 871 }
905 len = 1 + operand.length; 872 len = 1 + operand.length;
906 break; 873 break;
907 } 874 }
908 case kExprReturn: { 875 case kExprReturn: {
909 ReturnArityOperand operand(this, pc_);
910 if (operand.arity != sig_->return_count()) {
911 error(pc_, pc_ + 1, "arity mismatch in return");
912 }
913 DoReturn(); 876 DoReturn();
914 len = 1 + operand.length;
915 break; 877 break;
916 } 878 }
917 case kExprUnreachable: { 879 case kExprUnreachable: {
918 Push(kAstEnd, BUILD(Unreachable, position())); 880 BUILD(Unreachable, position());
919 ssa_env_->Kill(SsaEnv::kControlEnd); 881 EndControl();
920 break; 882 break;
921 } 883 }
922 case kExprI8Const: { 884 case kExprI8Const: {
923 ImmI8Operand operand(this, pc_); 885 ImmI8Operand operand(this, pc_);
924 Push(kAstI32, BUILD(Int32Constant, operand.value)); 886 Push(kAstI32, BUILD(Int32Constant, operand.value));
925 len = 1 + operand.length; 887 len = 1 + operand.length;
926 break; 888 break;
927 } 889 }
928 case kExprI32Const: { 890 case kExprI32Const: {
929 ImmI32Operand operand(this, pc_); 891 ImmI32Operand operand(this, pc_);
(...skipping 29 matching lines...) Expand all
959 } 921 }
960 } 922 }
961 len = 1 + operand.length; 923 len = 1 + operand.length;
962 break; 924 break;
963 } 925 }
964 case kExprSetLocal: { 926 case kExprSetLocal: {
965 LocalIndexOperand operand(this, pc_); 927 LocalIndexOperand operand(this, pc_);
966 if (Validate(pc_, operand)) { 928 if (Validate(pc_, operand)) {
967 Value val = Pop(0, local_type_vec_[operand.index]); 929 Value val = Pop(0, local_type_vec_[operand.index]);
968 if (ssa_env_->locals) ssa_env_->locals[operand.index] = val.node; 930 if (ssa_env_->locals) ssa_env_->locals[operand.index] = val.node;
931 }
932 len = 1 + operand.length;
933 break;
934 }
935 case kExprTeeLocal: {
936 LocalIndexOperand operand(this, pc_);
937 if (Validate(pc_, operand)) {
938 Value val = Pop(0, local_type_vec_[operand.index]);
939 if (ssa_env_->locals) ssa_env_->locals[operand.index] = val.node;
969 Push(val.type, val.node); 940 Push(val.type, val.node);
970 } 941 }
971 len = 1 + operand.length; 942 len = 1 + operand.length;
972 break; 943 break;
973 } 944 }
945 case kExprDrop: {
946 Pop();
947 break;
948 }
974 case kExprGetGlobal: { 949 case kExprGetGlobal: {
975 GlobalIndexOperand operand(this, pc_); 950 GlobalIndexOperand operand(this, pc_);
976 if (Validate(pc_, operand)) { 951 if (Validate(pc_, operand)) {
977 Push(operand.type, BUILD(GetGlobal, operand.index)); 952 Push(operand.type, BUILD(GetGlobal, operand.index));
978 } 953 }
979 len = 1 + operand.length; 954 len = 1 + operand.length;
980 break; 955 break;
981 } 956 }
982 case kExprSetGlobal: { 957 case kExprSetGlobal: {
983 GlobalIndexOperand operand(this, pc_); 958 GlobalIndexOperand operand(this, pc_);
984 if (Validate(pc_, operand)) { 959 if (Validate(pc_, operand)) {
985 Value val = Pop(0, operand.type); 960 if (operand.global->mutability) {
986 BUILD(SetGlobal, operand.index, val.node); 961 Value val = Pop(0, operand.type);
987 Push(val.type, val.node); 962 BUILD(SetGlobal, operand.index, val.node);
963 } else {
964 error(pc_, pc_ + 1, "immutable global #%u cannot be assigned",
965 operand.index);
966 }
988 } 967 }
989 len = 1 + operand.length; 968 len = 1 + operand.length;
990 break; 969 break;
991 } 970 }
992 case kExprI32LoadMem8S: 971 case kExprI32LoadMem8S:
993 len = DecodeLoadMem(kAstI32, MachineType::Int8()); 972 len = DecodeLoadMem(kAstI32, MachineType::Int8());
994 break; 973 break;
995 case kExprI32LoadMem8U: 974 case kExprI32LoadMem8U:
996 len = DecodeLoadMem(kAstI32, MachineType::Uint8()); 975 len = DecodeLoadMem(kAstI32, MachineType::Uint8());
997 break; 976 break;
998 case kExprI32LoadMem16S: 977 case kExprI32LoadMem16S:
999 len = DecodeLoadMem(kAstI32, MachineType::Int16()); 978 len = DecodeLoadMem(kAstI32, MachineType::Int16());
1000 break; 979 break;
1001 case kExprI32LoadMem16U: 980 case kExprI32LoadMem16U:
1002 len = DecodeLoadMem(kAstI32, MachineType::Uint16()); 981 len = DecodeLoadMem(kAstI32, MachineType::Uint16());
1003 break; 982 break;
1004 case kExprI32LoadMem: 983 case kExprI32LoadMem:
1005 len = DecodeLoadMem(kAstI32, MachineType::Int32()); 984 len = DecodeLoadMem(kAstI32, MachineType::Int32());
1006 break; 985 break;
1007
1008 case kExprI64LoadMem8S: 986 case kExprI64LoadMem8S:
1009 len = DecodeLoadMem(kAstI64, MachineType::Int8()); 987 len = DecodeLoadMem(kAstI64, MachineType::Int8());
1010 break; 988 break;
1011 case kExprI64LoadMem8U: 989 case kExprI64LoadMem8U:
1012 len = DecodeLoadMem(kAstI64, MachineType::Uint8()); 990 len = DecodeLoadMem(kAstI64, MachineType::Uint8());
1013 break; 991 break;
1014 case kExprI64LoadMem16S: 992 case kExprI64LoadMem16S:
1015 len = DecodeLoadMem(kAstI64, MachineType::Int16()); 993 len = DecodeLoadMem(kAstI64, MachineType::Int16());
1016 break; 994 break;
1017 case kExprI64LoadMem16U: 995 case kExprI64LoadMem16U:
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1067 error("grow_memory is not supported for asmjs modules"); 1045 error("grow_memory is not supported for asmjs modules");
1068 } 1046 }
1069 break; 1047 break;
1070 case kExprMemorySize: 1048 case kExprMemorySize:
1071 Push(kAstI32, BUILD(MemSize, 0)); 1049 Push(kAstI32, BUILD(MemSize, 0));
1072 break; 1050 break;
1073 case kExprCallFunction: { 1051 case kExprCallFunction: {
1074 CallFunctionOperand operand(this, pc_); 1052 CallFunctionOperand operand(this, pc_);
1075 if (Validate(pc_, operand)) { 1053 if (Validate(pc_, operand)) {
1076 TFNode** buffer = PopArgs(operand.sig); 1054 TFNode** buffer = PopArgs(operand.sig);
1077 TFNode* call = 1055 TFNode** rets =
1078 BUILD(CallDirect, operand.index, buffer, position()); 1056 BUILD(CallDirect, operand.index, buffer, position());
1079 Push(GetReturnType(operand.sig), call); 1057 PushReturns(operand.sig, rets);
1080 } 1058 }
1081 len = 1 + operand.length; 1059 len = 1 + operand.length;
1082 break; 1060 break;
1083 } 1061 }
1084 case kExprCallIndirect: { 1062 case kExprCallIndirect: {
1085 CallIndirectOperand operand(this, pc_); 1063 CallIndirectOperand operand(this, pc_);
1086 if (Validate(pc_, operand)) { 1064 if (Validate(pc_, operand)) {
1065 Value index = Pop(0, kAstI32);
1087 TFNode** buffer = PopArgs(operand.sig); 1066 TFNode** buffer = PopArgs(operand.sig);
1088 Value index = Pop(0, kAstI32);
1089 if (buffer) buffer[0] = index.node; 1067 if (buffer) buffer[0] = index.node;
1090 TFNode* call = 1068 TFNode** rets =
1091 BUILD(CallIndirect, operand.index, buffer, position()); 1069 BUILD(CallIndirect, operand.index, buffer, position());
1092 Push(GetReturnType(operand.sig), call); 1070 PushReturns(operand.sig, rets);
1093 } 1071 }
1094 len = 1 + operand.length; 1072 len = 1 + operand.length;
1095 break; 1073 break;
1096 }
1097 case kExprCallImport: {
1098 CallImportOperand operand(this, pc_);
1099 if (Validate(pc_, operand)) {
1100 TFNode** buffer = PopArgs(operand.sig);
1101 TFNode* call =
1102 BUILD(CallImport, operand.index, buffer, position());
1103 Push(GetReturnType(operand.sig), call);
1104 }
1105 len = 1 + operand.length;
1106 break;
1107 } 1074 }
1108 case kSimdPrefix: { 1075 case kSimdPrefix: {
1109 CHECK_PROTOTYPE_OPCODE(wasm_simd_prototype); 1076 CHECK_PROTOTYPE_OPCODE(wasm_simd_prototype);
1110 len++; 1077 len++;
1111 byte simd_index = *(pc_ + 1); 1078 byte simd_index = *(pc_ + 1);
1112 opcode = static_cast<WasmOpcode>(opcode << 8 | simd_index); 1079 opcode = static_cast<WasmOpcode>(opcode << 8 | simd_index);
1113 TRACE(" @%-4d #%02x #%02x:%-20s|", startrel(pc_), kSimdPrefix, 1080 TRACE(" @%-4d #%02x #%02x:%-20s|", startrel(pc_), kSimdPrefix,
1114 simd_index, WasmOpcodes::ShortOpcodeName(opcode)); 1081 simd_index, WasmOpcodes::ShortOpcodeName(opcode));
1115 len += DecodeSimdOpcode(opcode); 1082 len += DecodeSimdOpcode(opcode);
1116 break; 1083 break;
1117 } 1084 }
1118 default: 1085 default: {
1119 // Deal with special asmjs opcodes. 1086 // Deal with special asmjs opcodes.
1120 if (module_->origin == kAsmJsOrigin) { 1087 if (module_ && module_->origin == kAsmJsOrigin) {
1121 sig = WasmOpcodes::AsmjsSignature(opcode); 1088 sig = WasmOpcodes::AsmjsSignature(opcode);
1122 if (sig) { 1089 if (sig) {
1123 BuildSimpleOperator(opcode, sig); 1090 BuildSimpleOperator(opcode, sig);
1124 } 1091 }
1125 } else { 1092 } else {
1126 error("Invalid opcode"); 1093 error("Invalid opcode");
1127 return; 1094 return;
1128 } 1095 }
1096 }
1129 } 1097 }
1130 } // end complex bytecode 1098 }
1131 1099
1132 #if DEBUG 1100 #if DEBUG
1133 if (FLAG_trace_wasm_decoder) { 1101 if (FLAG_trace_wasm_decoder) {
1134 for (size_t i = 0; i < stack_.size(); ++i) { 1102 for (size_t i = 0; i < stack_.size(); ++i) {
1135 Value& val = stack_[i]; 1103 Value& val = stack_[i];
1136 WasmOpcode opcode = static_cast<WasmOpcode>(*val.pc); 1104 WasmOpcode opcode = static_cast<WasmOpcode>(*val.pc);
1137 if (WasmOpcodes::IsPrefixOpcode(opcode)) { 1105 if (WasmOpcodes::IsPrefixOpcode(opcode)) {
1138 opcode = static_cast<WasmOpcode>(opcode << 8 | *(val.pc + 1)); 1106 opcode = static_cast<WasmOpcode>(opcode << 8 | *(val.pc + 1));
1139 } 1107 }
1140 PrintF(" %c@%d:%s", WasmOpcodes::ShortNameOf(val.type), 1108 PrintF(" %c@%d:%s", WasmOpcodes::ShortNameOf(val.type),
1141 static_cast<int>(val.pc - start_), 1109 static_cast<int>(val.pc - start_),
1142 WasmOpcodes::ShortOpcodeName(opcode)); 1110 WasmOpcodes::ShortOpcodeName(opcode));
1143 switch (opcode) { 1111 switch (opcode) {
1144 case kExprI32Const: { 1112 case kExprI32Const: {
1145 ImmI32Operand operand(this, val.pc); 1113 ImmI32Operand operand(this, val.pc);
1146 PrintF("[%d]", operand.value); 1114 PrintF("[%d]", operand.value);
1147 break; 1115 break;
1148 } 1116 }
1149 case kExprGetLocal: { 1117 case kExprGetLocal: {
1150 LocalIndexOperand operand(this, val.pc); 1118 LocalIndexOperand operand(this, val.pc);
1151 PrintF("[%u]", operand.index); 1119 PrintF("[%u]", operand.index);
1152 break; 1120 break;
1153 } 1121 }
1154 case kExprSetLocal: { 1122 case kExprSetLocal: // fallthru
1123 case kExprTeeLocal: {
1155 LocalIndexOperand operand(this, val.pc); 1124 LocalIndexOperand operand(this, val.pc);
1156 PrintF("[%u]", operand.index); 1125 PrintF("[%u]", operand.index);
1157 break; 1126 break;
1158 } 1127 }
1159 default: 1128 default:
1160 break; 1129 break;
1161 } 1130 }
1162 } 1131 }
1163 PrintF("\n"); 1132 PrintF("\n");
1164 } 1133 }
1165 #endif 1134 #endif
1166 pc_ += len; 1135 pc_ += len;
1167 if (pc_ >= limit_) { 1136 if (pc_ >= limit_) {
1168 // End of code reached or exceeded. 1137 // End of code reached or exceeded.
1169 if (pc_ > limit_ && ok()) error("Beyond end of code"); 1138 if (pc_ > limit_ && ok()) error("Beyond end of code");
1170 return; 1139 return;
1171 } 1140 }
1172 } // end decode loop 1141 } // end decode loop
1173 } // end DecodeFunctionBody() 1142 }
1143
1144 void EndControl() { ssa_env_->Kill(SsaEnv::kControlEnd); }
1145
1146 void SetBlockType(Control* c, BlockTypeOperand& operand) {
1147 c->merge.arity = operand.arity;
1148 if (c->merge.arity == 1) {
1149 c->merge.vals.first = {pc_, nullptr, operand.read_entry(0)};
1150 } else if (c->merge.arity > 1) {
1151 c->merge.vals.array = zone_->NewArray<Value>(c->merge.arity);
1152 for (unsigned i = 0; i < c->merge.arity; i++) {
1153 c->merge.vals.array[i] = {pc_, nullptr, operand.read_entry(i)};
1154 }
1155 }
1156 }
1174 1157
1175 TFNode** PopArgs(FunctionSig* sig) { 1158 TFNode** PopArgs(FunctionSig* sig) {
1176 if (build()) { 1159 if (build()) {
1177 int count = static_cast<int>(sig->parameter_count()); 1160 int count = static_cast<int>(sig->parameter_count());
1178 TFNode** buffer = builder_->Buffer(count + 1); 1161 TFNode** buffer = builder_->Buffer(count + 1);
1179 buffer[0] = nullptr; // reserved for code object or function index. 1162 buffer[0] = nullptr; // reserved for code object or function index.
1180 for (int i = count - 1; i >= 0; i--) { 1163 for (int i = count - 1; i >= 0; i--) {
1181 buffer[i + 1] = Pop(i, sig->GetParam(i)).node; 1164 buffer[i + 1] = Pop(i, sig->GetParam(i)).node;
1182 } 1165 }
1183 return buffer; 1166 return buffer;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1227 return 1 + operand.length; 1210 return 1 + operand.length;
1228 } 1211 }
1229 1212
1230 int DecodeStoreMem(LocalType type, MachineType mem_type) { 1213 int DecodeStoreMem(LocalType type, MachineType mem_type) {
1231 MemoryAccessOperand operand(this, pc_, 1214 MemoryAccessOperand operand(this, pc_,
1232 ElementSizeLog2Of(mem_type.representation())); 1215 ElementSizeLog2Of(mem_type.representation()));
1233 Value val = Pop(1, type); 1216 Value val = Pop(1, type);
1234 Value index = Pop(0, kAstI32); 1217 Value index = Pop(0, kAstI32);
1235 BUILD(StoreMem, mem_type, index.node, operand.offset, operand.alignment, 1218 BUILD(StoreMem, mem_type, index.node, operand.offset, operand.alignment,
1236 val.node, position()); 1219 val.node, position());
1237 Push(type, val.node);
1238 return 1 + operand.length; 1220 return 1 + operand.length;
1239 } 1221 }
1240 1222
1241 unsigned DecodeSimdOpcode(WasmOpcode opcode) { 1223 unsigned DecodeSimdOpcode(WasmOpcode opcode) {
1242 unsigned len = 0; 1224 unsigned len = 0;
1243 switch (opcode) { 1225 switch (opcode) {
1244 case kExprI32x4ExtractLane: { 1226 case kExprI32x4ExtractLane: {
1245 uint8_t lane = this->checked_read_u8(pc_, 2, "lane number"); 1227 uint8_t lane = this->checked_read_u8(pc_, 2, "lane number");
1246 if (lane < 0 || lane > 3) { 1228 if (lane < 0 || lane > 3) {
1247 error(pc_, pc_ + 2, "invalid extract lane value"); 1229 error(pc_, pc_ + 2, "invalid extract lane value");
(...skipping 26 matching lines...) Expand all
1274 int count = static_cast<int>(sig_->return_count()); 1256 int count = static_cast<int>(sig_->return_count());
1275 TFNode** buffer = nullptr; 1257 TFNode** buffer = nullptr;
1276 if (build()) buffer = builder_->Buffer(count); 1258 if (build()) buffer = builder_->Buffer(count);
1277 1259
1278 // Pop return values off the stack in reverse order. 1260 // Pop return values off the stack in reverse order.
1279 for (int i = count - 1; i >= 0; i--) { 1261 for (int i = count - 1; i >= 0; i--) {
1280 Value val = Pop(i, sig_->GetReturn(i)); 1262 Value val = Pop(i, sig_->GetReturn(i));
1281 if (buffer) buffer[i] = val.node; 1263 if (buffer) buffer[i] = val.node;
1282 } 1264 }
1283 1265
1284 Push(kAstEnd, BUILD(Return, count, buffer)); 1266 BUILD(Return, count, buffer);
1285 ssa_env_->Kill(SsaEnv::kControlEnd); 1267 EndControl();
1286 } 1268 }
1287 1269
1288 void Push(LocalType type, TFNode* node) { 1270 void Push(LocalType type, TFNode* node) {
1289 stack_.push_back({pc_, node, type}); 1271 if (type != kAstStmt && type != kAstEnd) {
1272 stack_.push_back({pc_, node, type});
1273 }
1274 }
1275
1276 void PushReturns(FunctionSig* sig, TFNode** rets) {
1277 for (size_t i = 0; i < sig->return_count(); i++) {
1278 Push(sig->GetReturn(i), rets ? rets[i] : nullptr);
1279 }
1290 } 1280 }
1291 1281
1292 const char* SafeOpcodeNameAt(const byte* pc) { 1282 const char* SafeOpcodeNameAt(const byte* pc) {
1293 if (pc >= end_) return "<end>"; 1283 if (pc >= end_) return "<end>";
1294 return WasmOpcodes::ShortOpcodeName(static_cast<WasmOpcode>(*pc)); 1284 return WasmOpcodes::ShortOpcodeName(static_cast<WasmOpcode>(*pc));
1295 } 1285 }
1296 1286
1297 Value Pop(int index, LocalType expected) { 1287 Value Pop(int index, LocalType expected) {
1288 if (!ssa_env_->go()) {
1289 // Unreachable code is essentially not typechecked.
1290 return {pc_, nullptr, expected};
1291 }
1298 Value val = Pop(); 1292 Value val = Pop();
1299 if (val.type != expected) { 1293 if (val.type != expected) {
1300 if (val.type != kAstEnd) { 1294 if (val.type != kAstEnd) {
1301 error(pc_, val.pc, "%s[%d] expected type %s, found %s of type %s", 1295 error(pc_, val.pc, "%s[%d] expected type %s, found %s of type %s",
1302 SafeOpcodeNameAt(pc_), index, WasmOpcodes::TypeName(expected), 1296 SafeOpcodeNameAt(pc_), index, WasmOpcodes::TypeName(expected),
1303 SafeOpcodeNameAt(val.pc), WasmOpcodes::TypeName(val.type)); 1297 SafeOpcodeNameAt(val.pc), WasmOpcodes::TypeName(val.type));
1304 } 1298 }
1305 } 1299 }
1306 return val; 1300 return val;
1307 } 1301 }
1308 1302
1309 Value Pop() { 1303 Value Pop() {
1304 if (!ssa_env_->go()) {
1305 // Unreachable code is essentially not typechecked.
1306 return {pc_, nullptr, kAstEnd};
1307 }
1310 size_t limit = control_.empty() ? 0 : control_.back().stack_depth; 1308 size_t limit = control_.empty() ? 0 : control_.back().stack_depth;
1311 if (stack_.size() <= limit) { 1309 if (stack_.size() <= limit) {
1312 Value val = {pc_, nullptr, kAstStmt}; 1310 Value val = {pc_, nullptr, kAstStmt};
1313 error(pc_, pc_, "%s found empty stack", SafeOpcodeNameAt(pc_)); 1311 error(pc_, pc_, "%s found empty stack", SafeOpcodeNameAt(pc_));
1314 return val; 1312 return val;
1315 } 1313 }
1316 Value val = stack_.back(); 1314 Value val = stack_.back();
1317 stack_.pop_back(); 1315 stack_.pop_back();
1318 return val; 1316 return val;
1319 } 1317 }
1320 1318
1321 Value PopUpTo(int stack_depth) { 1319 Value PopUpTo(int stack_depth) {
1320 if (!ssa_env_->go()) {
1321 // Unreachable code is essentially not typechecked.
1322 return {pc_, nullptr, kAstEnd};
1323 }
1322 if (stack_depth == stack_.size()) { 1324 if (stack_depth == stack_.size()) {
1323 Value val = {pc_, nullptr, kAstStmt}; 1325 Value val = {pc_, nullptr, kAstStmt};
1324 return val; 1326 return val;
1325 } else { 1327 } else {
1326 DCHECK_LE(stack_depth, static_cast<int>(stack_.size())); 1328 DCHECK_LE(stack_depth, static_cast<int>(stack_.size()));
1327 Value val = Pop(); 1329 Value val = Pop();
1328 stack_.resize(stack_depth); 1330 stack_.resize(stack_depth);
1329 return val; 1331 return val;
1330 } 1332 }
1331 } 1333 }
1332 1334
1333 int baserel(const byte* ptr) { 1335 int baserel(const byte* ptr) {
1334 return base_ ? static_cast<int>(ptr - base_) : 0; 1336 return base_ ? static_cast<int>(ptr - base_) : 0;
1335 } 1337 }
1336 1338
1337 int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); } 1339 int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); }
1338 1340
1339 void BreakTo(Control* block, const Value& val) { 1341 void BreakTo(Control* c) {
1340 if (block->is_loop) { 1342 if (!ssa_env_->go()) return;
1343 if (c->is_loop()) {
1341 // This is the inner loop block, which does not have a value. 1344 // This is the inner loop block, which does not have a value.
1342 Goto(ssa_env_, block->end_env); 1345 Goto(ssa_env_, c->end_env);
1343 } else { 1346 } else {
1344 // Merge the value into the production for the block. 1347 // Merge the value(s) into the end of the block.
1345 MergeInto(block->end_env, &block->node, &block->type, val); 1348 if (c->stack_depth + c->merge.arity > stack_.size()) {
1349 error(
1350 pc_, pc_,
1351 "expected at least %d values on the stack for br to @%d, found %d",
1352 c->merge.arity, startrel(c->pc),
1353 static_cast<int>(stack_.size() - c->stack_depth));
1354 return;
1355 }
1356 MergeValuesInto(c);
1346 } 1357 }
1347 } 1358 }
1348 1359
1349 void MergeInto(SsaEnv* target, TFNode** node, LocalType* type, 1360 void FallThruTo(Control* c) {
1350 const Value& val) {
1351 if (!ssa_env_->go()) return; 1361 if (!ssa_env_->go()) return;
1352 DCHECK_NE(kAstEnd, val.type); 1362 // Merge the value(s) into the end of the block.
1363 int arity = static_cast<int>(c->merge.arity);
1364 if (c->stack_depth + arity != stack_.size()) {
1365 error(pc_, pc_, "expected %d elements on the stack for fallthru to @%d",
1366 arity, startrel(c->pc));
1367 return;
1368 }
1369 MergeValuesInto(c);
1370 }
1353 1371
1372 void TypeCheckLoopFallThru(Control* c) {
1373 if (!ssa_env_->go()) return;
1374 // Fallthru must match arity exactly.
1375 int arity = static_cast<int>(c->merge.arity);
1376 if (c->stack_depth + arity != stack_.size()) {
1377 error(pc_, pc_, "expected %d elements on the stack for fallthru to @%d",
1378 arity, startrel(c->pc));
1379 return;
1380 }
1381 // Typecheck the values left on the stack.
1382 for (uint32_t i = 0; i < c->merge.arity; i++) {
1383 Value& val = stack_[stack_.size() - c->merge.arity + i];
1384 Value& old =
1385 c->merge.arity == 1 ? c->merge.vals.first : c->merge.vals.array[i];
1386 if (val.type != old.type) {
1387 error(pc_, pc_, "type error in merge[%d] (expected %s, got %s)", i,
1388 WasmOpcodes::TypeName(old.type), WasmOpcodes::TypeName(val.type));
1389 return;
1390 }
1391 }
1392 }
1393
1394 void MergeValuesInto(Control* c) {
1395 SsaEnv* target = c->end_env;
1354 bool first = target->state == SsaEnv::kUnreachable; 1396 bool first = target->state == SsaEnv::kUnreachable;
1355 Goto(ssa_env_, target); 1397 Goto(ssa_env_, target);
1356 1398
1357 if (first) { 1399 for (uint32_t i = 0; i < c->merge.arity; i++) {
1358 // first merge to this environment; set the type and the node. 1400 Value& val = stack_[stack_.size() - c->merge.arity + i];
1359 *type = val.type; 1401 Value& old =
1360 *node = val.node; 1402 c->merge.arity == 1 ? c->merge.vals.first : c->merge.vals.array[i];
1361 } else if (val.type == *type && val.type != kAstStmt) { 1403 if (val.type != old.type) {
1362 // merge with the existing value for this block. 1404 error(pc_, pc_, "type error in merge[%d] (expected %s, got %s)", i,
1363 *node = CreateOrMergeIntoPhi(*type, target->control, *node, val.node); 1405 WasmOpcodes::TypeName(old.type), WasmOpcodes::TypeName(val.type));
1364 } else { 1406 return;
1365 // types don't match, or block is already a stmt. 1407 }
1366 *type = kAstStmt; 1408 old.node =
1367 *node = nullptr; 1409 first ? val.node : CreateOrMergeIntoPhi(old.type, target->control,
1410 old.node, val.node);
1368 } 1411 }
1369 } 1412 }
1370 1413
1371 void SetEnv(const char* reason, SsaEnv* env) { 1414 void SetEnv(const char* reason, SsaEnv* env) {
1372 #if DEBUG 1415 #if DEBUG
1373 if (FLAG_trace_wasm_decoder) { 1416 if (FLAG_trace_wasm_decoder) {
1374 char state = 'X'; 1417 char state = 'X';
1375 if (env) { 1418 if (env) {
1376 switch (env->state) { 1419 switch (env->state) {
1377 case SsaEnv::kReached: 1420 case SsaEnv::kReached:
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
1586 int depth = 0; 1629 int depth = 0;
1587 // Iteratively process all AST nodes nested inside the loop. 1630 // Iteratively process all AST nodes nested inside the loop.
1588 while (pc < limit_ && ok()) { 1631 while (pc < limit_ && ok()) {
1589 WasmOpcode opcode = static_cast<WasmOpcode>(*pc); 1632 WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
1590 unsigned length = 1; 1633 unsigned length = 1;
1591 switch (opcode) { 1634 switch (opcode) {
1592 case kExprLoop: 1635 case kExprLoop:
1593 case kExprIf: 1636 case kExprIf:
1594 case kExprBlock: 1637 case kExprBlock:
1595 case kExprTry: 1638 case kExprTry:
1639 length = OpcodeLength(pc);
1596 depth++; 1640 depth++;
1597 DCHECK_EQ(1, OpcodeLength(pc));
1598 break; 1641 break;
1599 case kExprSetLocal: { 1642 case kExprSetLocal: // fallthru
1643 case kExprTeeLocal: {
1600 LocalIndexOperand operand(this, pc); 1644 LocalIndexOperand operand(this, pc);
1601 if (assigned->length() > 0 && 1645 if (assigned->length() > 0 &&
1602 operand.index < static_cast<uint32_t>(assigned->length())) { 1646 operand.index < static_cast<uint32_t>(assigned->length())) {
1603 // Unverified code might have an out-of-bounds index. 1647 // Unverified code might have an out-of-bounds index.
1604 assigned->Add(operand.index); 1648 assigned->Add(operand.index);
1605 } 1649 }
1606 length = 1 + operand.length; 1650 length = 1 + operand.length;
1607 break; 1651 break;
1608 } 1652 }
1609 case kExprEnd: 1653 case kExprEnd:
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1682 WasmFullDecoder decoder(&zone, builder, body); 1726 WasmFullDecoder decoder(&zone, builder, body);
1683 decoder.Decode(); 1727 decoder.Decode();
1684 return decoder.toResult<DecodeStruct*>(nullptr); 1728 return decoder.toResult<DecodeStruct*>(nullptr);
1685 } 1729 }
1686 1730
1687 unsigned OpcodeLength(const byte* pc, const byte* end) { 1731 unsigned OpcodeLength(const byte* pc, const byte* end) {
1688 WasmDecoder decoder(nullptr, nullptr, pc, end); 1732 WasmDecoder decoder(nullptr, nullptr, pc, end);
1689 return decoder.OpcodeLength(pc); 1733 return decoder.OpcodeLength(pc);
1690 } 1734 }
1691 1735
1692 unsigned OpcodeArity(const byte* pc, const byte* end) {
1693 WasmDecoder decoder(nullptr, nullptr, pc, end);
1694 return decoder.OpcodeArity(pc);
1695 }
1696
1697 void PrintAstForDebugging(const byte* start, const byte* end) { 1736 void PrintAstForDebugging(const byte* start, const byte* end) {
1698 base::AccountingAllocator allocator; 1737 base::AccountingAllocator allocator;
1699 OFStream os(stdout); 1738 OFStream os(stdout);
1700 PrintAst(&allocator, FunctionBodyForTesting(start, end), os, nullptr); 1739 PrintAst(&allocator, FunctionBodyForTesting(start, end), os, nullptr);
1701 } 1740 }
1702 1741
1703 bool PrintAst(base::AccountingAllocator* allocator, const FunctionBody& body, 1742 bool PrintAst(base::AccountingAllocator* allocator, const FunctionBody& body,
1704 std::ostream& os, 1743 std::ostream& os,
1705 std::vector<std::tuple<uint32_t, int, int>>* offset_table) { 1744 std::vector<std::tuple<uint32_t, int, int>>* offset_table) {
1706 Zone zone(allocator); 1745 Zone zone(allocator);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1752 const char* padding = 1791 const char* padding =
1753 " "; 1792 " ";
1754 os.write(padding, num_whitespaces); 1793 os.write(padding, num_whitespaces);
1755 os << "k" << WasmOpcodes::OpcodeName(opcode) << ","; 1794 os << "k" << WasmOpcodes::OpcodeName(opcode) << ",";
1756 1795
1757 for (size_t j = 1; j < length; ++j) { 1796 for (size_t j = 1; j < length; ++j) {
1758 os << " " << AsHex(i.pc()[j], 2) << ","; 1797 os << " " << AsHex(i.pc()[j], 2) << ",";
1759 } 1798 }
1760 1799
1761 switch (opcode) { 1800 switch (opcode) {
1762 case kExprIf:
1763 case kExprElse: 1801 case kExprElse:
1764 case kExprLoop:
1765 case kExprBlock:
1766 case kExprTry:
1767 os << " // @" << i.pc_offset(); 1802 os << " // @" << i.pc_offset();
1768 control_depth++; 1803 control_depth++;
1769 break; 1804 break;
1805 case kExprLoop:
1806 case kExprIf:
1807 case kExprBlock:
1808 case kExprTry: {
1809 BlockTypeOperand operand(&i, i.pc());
1810 os << " // @" << i.pc_offset();
1811 for (unsigned i = 0; i < operand.arity; i++) {
1812 os << " " << WasmOpcodes::TypeName(operand.read_entry(i));
1813 }
1814 control_depth++;
1815 break;
1816 }
1770 case kExprEnd: 1817 case kExprEnd:
1771 os << " // @" << i.pc_offset(); 1818 os << " // @" << i.pc_offset();
1772 control_depth--; 1819 control_depth--;
1773 break; 1820 break;
1774 case kExprBr: { 1821 case kExprBr: {
1775 BreakDepthOperand operand(&i, i.pc()); 1822 BreakDepthOperand operand(&i, i.pc());
1776 os << " // arity=" << operand.arity << " depth=" << operand.depth; 1823 os << " // depth=" << operand.depth;
1777 break; 1824 break;
1778 } 1825 }
1779 case kExprBrIf: { 1826 case kExprBrIf: {
1780 BreakDepthOperand operand(&i, i.pc()); 1827 BreakDepthOperand operand(&i, i.pc());
1781 os << " // arity=" << operand.arity << " depth" << operand.depth; 1828 os << " // depth=" << operand.depth;
1782 break; 1829 break;
1783 } 1830 }
1784 case kExprBrTable: { 1831 case kExprBrTable: {
1785 BranchTableOperand operand(&i, i.pc()); 1832 BranchTableOperand operand(&i, i.pc());
1786 os << " // arity=" << operand.arity 1833 os << " // entries=" << operand.table_count;
1787 << " entries=" << operand.table_count;
1788 break; 1834 break;
1789 } 1835 }
1790 case kExprCallIndirect: { 1836 case kExprCallIndirect: {
1791 CallIndirectOperand operand(&i, i.pc()); 1837 CallIndirectOperand operand(&i, i.pc());
1838 os << " // sig #" << operand.index;
1792 if (decoder.Complete(i.pc(), operand)) { 1839 if (decoder.Complete(i.pc(), operand)) {
1793 os << " // sig #" << operand.index << ": " << *operand.sig; 1840 os << ": " << *operand.sig;
1794 } else {
1795 os << " // arity=" << operand.arity << " sig #" << operand.index;
1796 }
1797 break;
1798 }
1799 case kExprCallImport: {
1800 CallImportOperand operand(&i, i.pc());
1801 if (decoder.Complete(i.pc(), operand)) {
1802 os << " // import #" << operand.index << ": " << *operand.sig;
1803 } else {
1804 os << " // arity=" << operand.arity << " import #" << operand.index;
1805 } 1841 }
1806 break; 1842 break;
1807 } 1843 }
1808 case kExprCallFunction: { 1844 case kExprCallFunction: {
1809 CallFunctionOperand operand(&i, i.pc()); 1845 CallFunctionOperand operand(&i, i.pc());
1846 os << " // function #" << operand.index;
1810 if (decoder.Complete(i.pc(), operand)) { 1847 if (decoder.Complete(i.pc(), operand)) {
1811 os << " // function #" << operand.index << ": " << *operand.sig; 1848 os << ": " << *operand.sig;
1812 } else {
1813 os << " // arity=" << operand.arity << " function #" << operand.index;
1814 } 1849 }
1815 break; 1850 break;
1816 } 1851 }
1817 case kExprReturn: {
1818 ReturnArityOperand operand(&i, i.pc());
1819 os << " // arity=" << operand.arity;
1820 break;
1821 }
1822 default: 1852 default:
1823 break; 1853 break;
1824 } 1854 }
1825 os << std::endl; 1855 os << std::endl;
1826 ++line_nr; 1856 ++line_nr;
1827 } 1857 }
1828 1858
1829 return decoder.ok(); 1859 return decoder.ok();
1830 } 1860 }
1831 1861
1832 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, 1862 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals,
1833 const byte* start, const byte* end) { 1863 const byte* start, const byte* end) {
1834 FunctionBody body = {nullptr, nullptr, nullptr, start, end}; 1864 FunctionBody body = {nullptr, nullptr, nullptr, start, end};
1835 WasmFullDecoder decoder(zone, nullptr, body); 1865 WasmFullDecoder decoder(zone, nullptr, body);
1836 return decoder.AnalyzeLoopAssignmentForTesting(start, num_locals); 1866 return decoder.AnalyzeLoopAssignmentForTesting(start, num_locals);
1837 } 1867 }
1838 1868
1839 } // namespace wasm 1869 } // namespace wasm
1840 } // namespace internal 1870 } // namespace internal
1841 } // namespace v8 1871 } // namespace v8
OLDNEW
« no previous file with comments | « src/wasm/ast-decoder.h ('k') | src/wasm/decoder.h » ('j') | src/wasm/wasm-module.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698