1 // Copyright 2017 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_WASM_FUNCTION_BODY_DECODER_IMPL_H_ 6 #define V8_WASM_FUNCTION_BODY_DECODER_IMPL_H_ 7 8 // Do only include this header for implementing new Interface of the 9 // WasmFullDecoder. 10 11 #include "src/base/platform/elapsed-timer.h" 12 #include "src/bit-vector.h" 13 #include "src/wasm/decoder.h" 14 #include "src/wasm/function-body-decoder.h" 15 #include "src/wasm/wasm-features.h" 16 #include "src/wasm/wasm-limits.h" 17 #include "src/wasm/wasm-module.h" 18 #include "src/wasm/wasm-opcodes.h" 19 20 namespace v8 { 21 namespace internal { 22 namespace wasm { 23 24 struct WasmGlobal; 25 struct WasmException; 26 27 #define TRACE(...) \ 28 do { \ 29 if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \ 30 } while (false) 31 32 #define TRACE_INST_FORMAT " @%-8d #%-20s|" 33 34 // Return the evaluation of `condition` if validate==true, DCHECK that it's 35 // true and always return true otherwise. 36 #define VALIDATE(condition) \ 37 (validate ? (condition) : [&] { \ 38 DCHECK(condition); \ 39 return true; \ 40 }()) 41 42 #define RET_ON_PROTOTYPE_OPCODE(feat) \ 43 DCHECK(!this->module_ || this->module_->origin == kWasmOrigin); \ 44 if (!this->enabled_.feat) { \ 45 this->error("Invalid opcode (enable with --experimental-wasm-" #feat ")"); \ 46 } else { \ 47 this->detected_->feat = true; \ 48 } 49 50 #define CHECK_PROTOTYPE_OPCODE(feat) \ 51 DCHECK(!this->module_ || this->module_->origin == kWasmOrigin); \ 52 if (!this->enabled_.feat) { \ 53 this->error("Invalid opcode (enable with --experimental-wasm-" #feat ")"); \ 54 break; \ 55 } else { \ 56 this->detected_->feat = true; \ 57 } 58 59 #define OPCODE_ERROR(opcode, message) \ 60 (this->errorf(this->pc_, "%s: %s", WasmOpcodes::OpcodeName(opcode), \ 61 (message))) 62 63 #define ATOMIC_OP_LIST(V) \ 64 V(I32AtomicLoad, Uint32) \ 65 V(I64AtomicLoad, Uint64) \ 66 V(I32AtomicLoad8U, Uint8) \ 67 V(I32AtomicLoad16U, Uint16) \ 68 V(I64AtomicLoad8U, Uint8) \ 69 V(I64AtomicLoad16U, Uint16) \ 70 V(I64AtomicLoad32U, Uint32) \ 71 V(I32AtomicAdd, Uint32) \ 72 V(I32AtomicAdd8U, Uint8) \ 73 V(I32AtomicAdd16U, Uint16) \ 74 V(I64AtomicAdd, Uint64) \ 75 V(I64AtomicAdd8U, Uint8) \ 76 V(I64AtomicAdd16U, Uint16) \ 77 V(I64AtomicAdd32U, Uint32) \ 78 V(I32AtomicSub, Uint32) \ 79 V(I64AtomicSub, Uint64) \ 80 V(I32AtomicSub8U, Uint8) \ 81 V(I32AtomicSub16U, Uint16) \ 82 V(I64AtomicSub8U, Uint8) \ 83 V(I64AtomicSub16U, Uint16) \ 84 V(I64AtomicSub32U, Uint32) \ 85 V(I32AtomicAnd, Uint32) \ 86 V(I64AtomicAnd, Uint64) \ 87 V(I32AtomicAnd8U, Uint8) \ 88 V(I32AtomicAnd16U, Uint16) \ 89 V(I64AtomicAnd8U, Uint8) \ 90 V(I64AtomicAnd16U, Uint16) \ 91 V(I64AtomicAnd32U, Uint32) \ 92 V(I32AtomicOr, Uint32) \ 93 V(I64AtomicOr, Uint64) \ 94 V(I32AtomicOr8U, Uint8) \ 95 V(I32AtomicOr16U, Uint16) \ 96 V(I64AtomicOr8U, Uint8) \ 97 V(I64AtomicOr16U, Uint16) \ 98 V(I64AtomicOr32U, Uint32) \ 99 V(I32AtomicXor, Uint32) \ 100 V(I64AtomicXor, Uint64) \ 101 V(I32AtomicXor8U, Uint8) \ 102 V(I32AtomicXor16U, Uint16) \ 103 V(I64AtomicXor8U, Uint8) \ 104 V(I64AtomicXor16U, Uint16) \ 105 V(I64AtomicXor32U, Uint32) \ 106 V(I32AtomicExchange, Uint32) \ 107 V(I64AtomicExchange, Uint64) \ 108 V(I32AtomicExchange8U, Uint8) \ 109 V(I32AtomicExchange16U, Uint16) \ 110 V(I64AtomicExchange8U, Uint8) \ 111 V(I64AtomicExchange16U, Uint16) \ 112 V(I64AtomicExchange32U, Uint32) \ 113 V(I32AtomicCompareExchange, Uint32) \ 114 V(I64AtomicCompareExchange, Uint64) \ 115 V(I32AtomicCompareExchange8U, Uint8) \ 116 V(I32AtomicCompareExchange16U, Uint16) \ 117 V(I64AtomicCompareExchange8U, Uint8) \ 118 V(I64AtomicCompareExchange16U, Uint16) \ 119 V(I64AtomicCompareExchange32U, Uint32) 120 121 #define ATOMIC_STORE_OP_LIST(V) \ 122 V(I32AtomicStore, Uint32) \ 123 V(I64AtomicStore, Uint64) \ 124 V(I32AtomicStore8U, Uint8) \ 125 V(I32AtomicStore16U, Uint16) \ 126 V(I64AtomicStore8U, Uint8) \ 127 V(I64AtomicStore16U, Uint16) \ 128 V(I64AtomicStore32U, Uint32) 129 130 template <typename T, typename Allocator> 131 Vector<T> vec2vec(std::vector<T, Allocator>& vec) { 132 return Vector<T>(vec.data(), vec.size()); 133 } 134 135 // Helpers for decoding different kinds of immediates which follow bytecodes. 136 template <Decoder::ValidateFlag validate> 137 struct LocalIndexImmediate { 138 uint32_t index; 139 ValueType type = kWasmStmt; 140 unsigned length; 141 142 inline LocalIndexImmediate(Decoder* decoder, const byte* pc) { 143 index = decoder->read_u32v<validate>(pc + 1, &length, "local index"); 144 } 145 }; 146 147 template <Decoder::ValidateFlag validate> 148 struct ExceptionIndexImmediate { 149 uint32_t index; 150 const WasmException* exception = nullptr; 151 unsigned length; 152 153 inline ExceptionIndexImmediate(Decoder* decoder, const byte* pc) { 154 index = decoder->read_u32v<validate>(pc + 1, &length, "exception index"); 155 } 156 }; 157 158 template <Decoder::ValidateFlag validate> 159 struct ImmI32Immediate { 160 int32_t value; 161 unsigned length; 162 inline ImmI32Immediate(Decoder* decoder, const byte* pc) { 163 value = decoder->read_i32v<validate>(pc + 1, &length, "immi32"); 164 } 165 }; 166 167 template <Decoder::ValidateFlag validate> 168 struct ImmI64Immediate { 169 int64_t value; 170 unsigned length; 171 inline ImmI64Immediate(Decoder* decoder, const byte* pc) { 172 value = decoder->read_i64v<validate>(pc + 1, &length, "immi64"); 173 } 174 }; 175 176 template <Decoder::ValidateFlag validate> 177 struct ImmF32Immediate { 178 float value; 179 unsigned length = 4; 180 inline ImmF32Immediate(Decoder* decoder, const byte* pc) { 181 // Avoid bit_cast because it might not preserve the signalling bit of a NaN. 182 uint32_t tmp = decoder->read_u32<validate>(pc + 1, "immf32"); 183 memcpy(&value, &tmp, sizeof(value)); 184 } 185 }; 186 187 template <Decoder::ValidateFlag validate> 188 struct ImmF64Immediate { 189 double value; 190 unsigned length = 8; 191 inline ImmF64Immediate(Decoder* decoder, const byte* pc) { 192 // Avoid bit_cast because it might not preserve the signalling bit of a NaN. 193 uint64_t tmp = decoder->read_u64<validate>(pc + 1, "immf64"); 194 memcpy(&value, &tmp, sizeof(value)); 195 } 196 }; 197 198 template <Decoder::ValidateFlag validate> 199 struct GlobalIndexImmediate { 200 uint32_t index; 201 ValueType type = kWasmStmt; 202 const WasmGlobal* global = nullptr; 203 unsigned length; 204 205 inline GlobalIndexImmediate(Decoder* decoder, const byte* pc) { 206 index = decoder->read_u32v<validate>(pc + 1, &length, "global index"); 207 } 208 }; 209 210 template <Decoder::ValidateFlag validate> 211 struct BlockTypeImmediate { 212 unsigned length = 1; 213 ValueType type = kWasmStmt; 214 uint32_t sig_index = 0; 215 FunctionSig* sig = nullptr; 216 217 inline BlockTypeImmediate(const WasmFeatures& enabled, Decoder* decoder, 218 const byte* pc) { 219 uint8_t val = decoder->read_u8<validate>(pc + 1, "block type"); 220 if (!decode_local_type(val, &type)) { 221 // Handle multi-value blocks. 222 if (!VALIDATE(enabled.mv)) { 223 decoder->error(pc + 1, "invalid block type"); 224 return; 225 } 226 if (!VALIDATE(decoder->ok())) return; 227 int32_t index = 228 decoder->read_i32v<validate>(pc + 1, &length, "block arity"); 229 if (!VALIDATE(length > 0 && index >= 0)) { 230 decoder->error(pc + 1, "invalid block type index"); 231 return; 232 } 233 sig_index = static_cast<uint32_t>(index); 234 } 235 } 236 237 // Decode a byte representing a local type. Return {false} if the encoded 238 // byte was invalid or the start of a type index. 239 inline bool decode_local_type(uint8_t val, ValueType* result) { 240 switch (static_cast<ValueTypeCode>(val)) { 241 case kLocalVoid: 242 *result = kWasmStmt; 243 return true; 244 case kLocalI32: 245 *result = kWasmI32; 246 return true; 247 case kLocalI64: 248 *result = kWasmI64; 249 return true; 250 case kLocalF32: 251 *result = kWasmF32; 252 return true; 253 case kLocalF64: 254 *result = kWasmF64; 255 return true; 256 case kLocalS128: 257 *result = kWasmS128; 258 return true; 259 case kLocalAnyFunc: 260 *result = kWasmAnyFunc; 261 return true; 262 case kLocalAnyRef: 263 *result = kWasmAnyRef; 264 return true; 265 default: 266 *result = kWasmVar; 267 return false; 268 } 269 } 270 271 uint32_t in_arity() const { 272 if (type != kWasmVar) return 0; 273 return static_cast<uint32_t>(sig->parameter_count()); 274 } 275 uint32_t out_arity() const { 276 if (type == kWasmStmt) return 0; 277 if (type != kWasmVar) return 1; 278 return static_cast<uint32_t>(sig->return_count()); 279 } 280 ValueType in_type(uint32_t index) { 281 DCHECK_EQ(kWasmVar, type); 282 return sig->GetParam(index); 283 } 284 ValueType out_type(uint32_t index) { 285 if (type == kWasmVar) return sig->GetReturn(index); 286 DCHECK_NE(kWasmStmt, type); 287 DCHECK_EQ(0, index); 288 return type; 289 } 290 }; 291 292 template <Decoder::ValidateFlag validate> 293 struct BreakDepthImmediate { 294 uint32_t depth; 295 unsigned length; 296 inline BreakDepthImmediate(Decoder* decoder, const byte* pc) { 297 depth = decoder->read_u32v<validate>(pc + 1, &length, "break depth"); 298 } 299 }; 300 301 template <Decoder::ValidateFlag validate> 302 struct CallIndirectImmediate { 303 uint32_t table_index; 304 uint32_t sig_index; 305 FunctionSig* sig = nullptr; 306 unsigned length = 0; 307 inline CallIndirectImmediate(Decoder* decoder, const byte* pc) { 308 unsigned len = 0; 309 sig_index = decoder->read_u32v<validate>(pc + 1, &len, "signature index"); 310 if (!VALIDATE(decoder->ok())) return; 311 table_index = decoder->read_u8<validate>(pc + 1 + len, "table index"); 312 if (!VALIDATE(table_index == 0)) { 313 decoder->errorf(pc + 1 + len, "expected table index 0, found %u", 314 table_index); 315 } 316 length = 1 + len; 317 } 318 }; 319 320 template <Decoder::ValidateFlag validate> 321 struct CallFunctionImmediate { 322 uint32_t index; 323 FunctionSig* sig = nullptr; 324 unsigned length; 325 inline CallFunctionImmediate(Decoder* decoder, const byte* pc) { 326 index = decoder->read_u32v<validate>(pc + 1, &length, "function index"); 327 } 328 }; 329 330 template <Decoder::ValidateFlag validate> 331 struct MemoryIndexImmediate { 332 uint32_t index; 333 unsigned length = 1; 334 inline MemoryIndexImmediate(Decoder* decoder, const byte* pc) { 335 index = decoder->read_u8<validate>(pc + 1, "memory index"); 336 if (!VALIDATE(index == 0)) { 337 decoder->errorf(pc + 1, "expected memory index 0, found %u", index); 338 } 339 } 340 }; 341 342 template <Decoder::ValidateFlag validate> 343 struct BranchTableImmediate { 344 uint32_t table_count; 345 const byte* start; 346 const byte* table; 347 inline BranchTableImmediate(Decoder* decoder, const byte* pc) { 348 DCHECK_EQ(kExprBrTable, decoder->read_u8<validate>(pc, "opcode")); 349 start = pc + 1; 350 unsigned len = 0; 351 table_count = decoder->read_u32v<validate>(pc + 1, &len, "table count"); 352 table = pc + 1 + len; 353 } 354 }; 355 356 // A helper to iterate over a branch table. 357 template <Decoder::ValidateFlag validate> 358 class BranchTableIterator { 359 public: 360 unsigned cur_index() { return index_; } 361 bool has_next() { return VALIDATE(decoder_->ok()) && index_ <= table_count_; } 362 uint32_t next() { 363 DCHECK(has_next()); 364 index_++; 365 unsigned length; 366 uint32_t result = 367 decoder_->read_u32v<validate>(pc_, &length, "branch table entry"); 368 pc_ += length; 369 return result; 370 } 371 // length, including the length of the {BranchTableImmediate}, but not the 372 // opcode. 373 unsigned length() { 374 while (has_next()) next(); 375 return static_cast<unsigned>(pc_ - start_); 376 } 377 const byte* pc() { return pc_; } 378 379 BranchTableIterator(Decoder* decoder, 380 const BranchTableImmediate<validate>& imm) 381 : decoder_(decoder), 382 start_(imm.start), 383 pc_(imm.table), 384 table_count_(imm.table_count) {} 385 386 private: 387 Decoder* decoder_; 388 const byte* start_; 389 const byte* pc_; 390 uint32_t index_ = 0; // the current index. 391 uint32_t table_count_; // the count of entries, not including default. 392 }; 393 394 template <Decoder::ValidateFlag validate> 395 struct MemoryAccessImmediate { 396 uint32_t alignment; 397 uint32_t offset; 398 unsigned length = 0; 399 inline MemoryAccessImmediate(Decoder* decoder, const byte* pc, 400 uint32_t max_alignment) { 401 unsigned alignment_length; 402 alignment = 403 decoder->read_u32v<validate>(pc + 1, &alignment_length, "alignment"); 404 if (!VALIDATE(alignment <= max_alignment)) { 405 decoder->errorf(pc + 1, 406 "invalid alignment; expected maximum alignment is %u, " 407 "actual alignment is %u", 408 max_alignment, alignment); 409 } 410 if (!VALIDATE(decoder->ok())) return; 411 unsigned offset_length; 412 offset = decoder->read_u32v<validate>(pc + 1 + alignment_length, 413 &offset_length, "offset"); 414 length = alignment_length + offset_length; 415 } 416 }; 417 418 // Immediate for SIMD lane operations. 419 template <Decoder::ValidateFlag validate> 420 struct SimdLaneImmediate { 421 uint8_t lane; 422 unsigned length = 1; 423 424 inline SimdLaneImmediate(Decoder* decoder, const byte* pc) { 425 lane = decoder->read_u8<validate>(pc + 2, "lane"); 426 } 427 }; 428 429 // Immediate for SIMD shift operations. 430 template <Decoder::ValidateFlag validate> 431 struct SimdShiftImmediate { 432 uint8_t shift; 433 unsigned length = 1; 434 435 inline SimdShiftImmediate(Decoder* decoder, const byte* pc) { 436 shift = decoder->read_u8<validate>(pc + 2, "shift"); 437 } 438 }; 439 440 // Immediate for SIMD S8x16 shuffle operations. 441 template <Decoder::ValidateFlag validate> 442 struct Simd8x16ShuffleImmediate { 443 uint8_t shuffle[kSimd128Size] = {0}; 444 445 inline Simd8x16ShuffleImmediate(Decoder* decoder, const byte* pc) { 446 for (uint32_t i = 0; i < kSimd128Size; ++i) { 447 shuffle[i] = decoder->read_u8<validate>(pc + 2 + i, "shuffle"); 448 if (!VALIDATE(decoder->ok())) return; 449 } 450 } 451 }; 452 453 // An entry on the value stack. 454 struct ValueBase { 455 const byte* pc; 456 ValueType type; 457 458 // Named constructors. 459 static ValueBase Unreachable(const byte* pc) { return {pc, kWasmVar}; } 460 461 static ValueBase New(const byte* pc, ValueType type) { return {pc, type}; } 462 }; 463 464 template <typename Value> 465 struct Merge { 466 uint32_t arity; 467 union { 468 Value* array; 469 Value first; 470 } vals; // Either multiple values or a single value. 471 472 // Tracks whether this merge was ever reached. Uses precise reachability, like 473 // Reachability::kReachable. 474 bool reached; 475 476 Merge(bool reached = false) : reached(reached) {} 477 478 Value& operator[](uint32_t i) { 479 DCHECK_GT(arity, i); 480 return arity == 1 ? vals.first : vals.array[i]; 481 } 482 }; 483 484 enum ControlKind : uint8_t { 485 kControlIf, 486 kControlIfElse, 487 kControlBlock, 488 kControlLoop, 489 kControlTry, 490 kControlTryCatch 491 }; 492 493 enum Reachability : uint8_t { 494 // reachable code. 495 kReachable, 496 // reachable code in unreachable block (implies normal validation). 497 kSpecOnlyReachable, 498 // code unreachable in its own block (implies polymorphic validation). 499 kUnreachable 500 }; 501 502 // An entry on the control stack (i.e. if, block, loop, or try). 503 template <typename Value> 504 struct ControlBase { 505 ControlKind kind; 506 uint32_t stack_depth; // stack height at the beginning of the construct. 507 const byte* pc; 508 Reachability reachability = kReachable; 509 510 // Values merged into the start or end of this control construct. 511 Merge<Value> start_merge; 512 Merge<Value> end_merge; 513 514 ControlBase() = default; 515 ControlBase(ControlKind kind, uint32_t stack_depth, const byte* pc) 516 : kind(kind), stack_depth(stack_depth), pc(pc) {} 517 518 // Check whether the current block is reachable. 519 bool reachable() const { return reachability == kReachable; } 520 521 // Check whether the rest of the block is unreachable. 522 // Note that this is different from {!reachable()}, as there is also the 523 // "indirect unreachable state", for which both {reachable()} and 524 // {unreachable()} return false. 525 bool unreachable() const { return reachability == kUnreachable; } 526 527 // Return the reachability of new control structs started in this block. 528 Reachability innerReachability() const { 529 return reachability == kReachable ? kReachable : kSpecOnlyReachable; 530 } 531 532 bool is_if() const { return is_onearmed_if() || is_if_else(); } 533 bool is_onearmed_if() const { return kind == kControlIf; } 534 bool is_if_else() const { return kind == kControlIfElse; } 535 bool is_block() const { return kind == kControlBlock; } 536 bool is_loop() const { return kind == kControlLoop; } 537 bool is_try() const { return is_incomplete_try() || is_try_catch(); } 538 bool is_incomplete_try() const { return kind == kControlTry; } 539 bool is_try_catch() const { return kind == kControlTryCatch; } 540 541 inline Merge<Value>* br_merge() { 542 return is_loop() ? &this->start_merge : &this->end_merge; 543 } 544 545 // Named constructors. 546 static ControlBase Block(const byte* pc, uint32_t stack_depth) { 547 return {kControlBlock, stack_depth, pc}; 548 } 549 550 static ControlBase If(const byte* pc, uint32_t stack_depth) { 551 return {kControlIf, stack_depth, pc}; 552 } 553 554 static ControlBase Loop(const byte* pc, uint32_t stack_depth) { 555 return {kControlLoop, stack_depth, pc}; 556 } 557 558 static ControlBase Try(const byte* pc, uint32_t stack_depth) { 559 return {kControlTry, stack_depth, pc}; 560 } 561 }; 562 563 #define CONCRETE_NAMED_CONSTRUCTOR(concrete_type, abstract_type, name) \ 564 template <typename... Args> \ 565 static concrete_type name(Args&&... args) { \ 566 concrete_type val; \ 567 static_cast<abstract_type&>(val) = \ 568 abstract_type::name(std::forward<Args>(args)...); \ 569 return val; \ 570 } 571 572 // Provide the default named constructors, which default-initialize the 573 // ConcreteType and the initialize the fields of ValueBase correctly. 574 // Use like this: 575 // struct Value : public ValueWithNamedConstructors<Value> { int new_field; }; 576 template <typename ConcreteType> 577 struct ValueWithNamedConstructors : public ValueBase { 578 // Named constructors. 579 CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ValueBase, Unreachable) 580 CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ValueBase, New) 581 }; 582 583 // Provide the default named constructors, which default-initialize the 584 // ConcreteType and the initialize the fields of ControlBase correctly. 585 // Use like this: 586 // struct Control : public ControlWithNamedConstructors<Control, Value> { 587 // int my_uninitialized_field; 588 // char* other_field = nullptr; 589 // }; 590 template <typename ConcreteType, typename Value> 591 struct ControlWithNamedConstructors : public ControlBase<Value> { 592 // Named constructors. 593 CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ControlBase<Value>, Block) 594 CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ControlBase<Value>, If) 595 CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ControlBase<Value>, Loop) 596 CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ControlBase<Value>, Try) 597 }; 598 599 // This is the list of callback functions that an interface for the 600 // WasmFullDecoder should implement. 601 // F(Name, args...) 602 #define INTERFACE_FUNCTIONS(F) \ 603 /* General: */ \ 604 F(StartFunction) \ 605 F(StartFunctionBody, Control* block) \ 606 F(FinishFunction) \ 607 F(OnFirstError) \ 608 F(NextInstruction, WasmOpcode) \ 609 /* Control: */ \ 610 F(Block, Control* block) \ 611 F(Loop, Control* block) \ 612 F(Try, Control* block) \ 613 F(If, const Value& cond, Control* if_block) \ 614 F(FallThruTo, Control* c) \ 615 F(PopControl, Control* block) \ 616 F(EndControl, Control* block) \ 617 /* Instructions: */ \ 618 F(UnOp, WasmOpcode opcode, FunctionSig*, const Value& value, Value* result) \ 619 F(BinOp, WasmOpcode opcode, FunctionSig*, const Value& lhs, \ 620 const Value& rhs, Value* result) \ 621 F(I32Const, Value* result, int32_t value) \ 622 F(I64Const, Value* result, int64_t value) \ 623 F(F32Const, Value* result, float value) \ 624 F(F64Const, Value* result, double value) \ 625 F(RefNull, Value* result) \ 626 F(Drop, const Value& value) \ 627 F(DoReturn, Vector<Value> values, bool implicit) \ 628 F(GetLocal, Value* result, const LocalIndexImmediate<validate>& imm) \ 629 F(SetLocal, const Value& value, const LocalIndexImmediate<validate>& imm) \ 630 F(TeeLocal, const Value& value, Value* result, \ 631 const LocalIndexImmediate<validate>& imm) \ 632 F(GetGlobal, Value* result, const GlobalIndexImmediate<validate>& imm) \ 633 F(SetGlobal, const Value& value, const GlobalIndexImmediate<validate>& imm) \ 634 F(Unreachable) \ 635 F(Select, const Value& cond, const Value& fval, const Value& tval, \ 636 Value* result) \ 637 F(Br, Control* target) \ 638 F(BrIf, const Value& cond, Control* target) \ 639 F(BrTable, const BranchTableImmediate<validate>& imm, const Value& key) \ 640 F(Else, Control* if_block) \ 641 F(LoadMem, LoadType type, const MemoryAccessImmediate<validate>& imm, \ 642 const Value& index, Value* result) \ 643 F(StoreMem, StoreType type, const MemoryAccessImmediate<validate>& imm, \ 644 const Value& index, const Value& value) \ 645 F(CurrentMemoryPages, Value* result) \ 646 F(GrowMemory, const Value& value, Value* result) \ 647 F(CallDirect, const CallFunctionImmediate<validate>& imm, \ 648 const Value args[], Value returns[]) \ 649 F(CallIndirect, const Value& index, \ 650 const CallIndirectImmediate<validate>& imm, const Value args[], \ 651 Value returns[]) \ 652 F(SimdOp, WasmOpcode opcode, Vector<Value> args, Value* result) \ 653 F(SimdLaneOp, WasmOpcode opcode, const SimdLaneImmediate<validate>& imm, \ 654 const Vector<Value> inputs, Value* result) \ 655 F(SimdShiftOp, WasmOpcode opcode, const SimdShiftImmediate<validate>& imm, \ 656 const Value& input, Value* result) \ 657 F(Simd8x16ShuffleOp, const Simd8x16ShuffleImmediate<validate>& imm, \ 658 const Value& input0, const Value& input1, Value* result) \ 659 F(Throw, const ExceptionIndexImmediate<validate>&, Control* block, \ 660 const Vector<Value>& args) \ 661 F(CatchException, const ExceptionIndexImmediate<validate>& imm, \ 662 Control* block, Vector<Value> caught_values) \ 663 F(AtomicOp, WasmOpcode opcode, Vector<Value> args, \ 664 const MemoryAccessImmediate<validate>& imm, Value* result) 665 666 // Generic Wasm bytecode decoder with utilities for decoding immediates, 667 // lengths, etc. 668 template <Decoder::ValidateFlag validate> 669 class WasmDecoder : public Decoder { 670 public: 671 WasmDecoder(const WasmModule* module, const WasmFeatures& enabled, 672 WasmFeatures* detected, FunctionSig* sig, const byte* start, 673 const byte* end, uint32_t buffer_offset = 0) 674 : Decoder(start, end, buffer_offset), 675 module_(module), 676 enabled_(enabled), 677 detected_(detected), 678 sig_(sig), 679 local_types_(nullptr) {} 680 const WasmModule* module_; 681 const WasmFeatures enabled_; 682 WasmFeatures* detected_; 683 FunctionSig* sig_; 684 685 ZoneVector<ValueType>* local_types_; 686 687 uint32_t total_locals() const { 688 return local_types_ == nullptr 689 ? 0 690 : static_cast<uint32_t>(local_types_->size()); 691 } 692 693 static bool DecodeLocals(const WasmFeatures& enabled, Decoder* decoder, 694 const FunctionSig* sig, 695 ZoneVector<ValueType>* type_list) { 696 DCHECK_NOT_NULL(type_list); 697 DCHECK_EQ(0, type_list->size()); 698 // Initialize from signature. 699 if (sig != nullptr) { 700 type_list->assign(sig->parameters().begin(), sig->parameters().end()); 701 } 702 // Decode local declarations, if any. 703 uint32_t entries = decoder->consume_u32v("local decls count"); 704 if (decoder->failed()) return false; 705 706 TRACE("local decls count: %u\n", entries); 707 while (entries-- > 0 && VALIDATE(decoder->ok()) && decoder->more()) { 708 uint32_t count = decoder->consume_u32v("local count"); 709 if (decoder->failed()) return false; 710 711 DCHECK_LE(type_list->size(), kV8MaxWasmFunctionLocals); 712 if (count > kV8MaxWasmFunctionLocals - type_list->size()) { 713 decoder->error(decoder->pc() - 1, "local count too large"); 714 return false; 715 } 716 byte code = decoder->consume_u8("local type"); 717 if (decoder->failed()) return false; 718 719 ValueType type; 720 switch (code) { 721 case kLocalI32: 722 type = kWasmI32; 723 break; 724 case kLocalI64: 725 type = kWasmI64; 726 break; 727 case kLocalF32: 728 type = kWasmF32; 729 break; 730 case kLocalF64: 731 type = kWasmF64; 732 break; 733 case kLocalAnyRef: 734 if (enabled.anyref) { 735 type = kWasmAnyRef; 736 break; 737 } 738 decoder->error(decoder->pc() - 1, "invalid local type"); 739 return false; 740 case kLocalS128: 741 if (enabled.simd) { 742 type = kWasmS128; 743 break; 744 } 745 V8_FALLTHROUGH; 746 default: 747 decoder->error(decoder->pc() - 1, "invalid local type"); 748 return false; 749 } 750 type_list->insert(type_list->end(), count, type); 751 } 752 DCHECK(decoder->ok()); 753 return true; 754 } 755 756 static BitVector* AnalyzeLoopAssignment(Decoder* decoder, const byte* pc, 757 uint32_t locals_count, Zone* zone) { 758 if (pc >= decoder->end()) return nullptr; 759 if (*pc != kExprLoop) return nullptr; 760 761 // The number of locals_count is augmented by 2 so that 'locals_count - 2' 762 // can be used to track mem_size, and 'locals_count - 1' to track mem_start. 763 BitVector* assigned = new (zone) BitVector(locals_count, zone); 764 int depth = 0; 765 // Iteratively process all AST nodes nested inside the loop. 766 while (pc < decoder->end() && VALIDATE(decoder->ok())) { 767 WasmOpcode opcode = static_cast<WasmOpcode>(*pc); 768 unsigned length = 1; 769 switch (opcode) { 770 case kExprLoop: 771 case kExprIf: 772 case kExprBlock: 773 case kExprTry: 774 length = OpcodeLength(decoder, pc); 775 depth++; 776 break; 777 case kExprSetLocal: // fallthru 778 case kExprTeeLocal: { 779 LocalIndexImmediate<Decoder::kValidate> imm(decoder, pc); 780 if (assigned->length() > 0 && 781 imm.index < static_cast<uint32_t>(assigned->length())) { 782 // Unverified code might have an out-of-bounds index. 783 assigned->Add(imm.index); 784 } 785 length = 1 + imm.length; 786 break; 787 } 788 case kExprGrowMemory: 789 case kExprCallFunction: 790 case kExprCallIndirect: 791 // Add instance cache nodes to the assigned set. 792 // TODO(titzer): make this more clear. 793 assigned->Add(locals_count - 1); 794 length = OpcodeLength(decoder, pc); 795 break; 796 case kExprEnd: 797 depth--; 798 break; 799 default: 800 length = OpcodeLength(decoder, pc); 801 break; 802 } 803 if (depth <= 0) break; 804 pc += length; 805 } 806 return VALIDATE(decoder->ok()) ? assigned : nullptr; 807 } 808 809 inline bool Validate(const byte* pc, 810 LocalIndexImmediate<Decoder::kValidate>& imm) { 811 if (!VALIDATE(imm.index < total_locals())) { 812 errorf(pc + 1, "invalid local index: %u", imm.index); 813 return false; 814 } 815 imm.type = local_types_ ? local_types_->at(imm.index) : kWasmStmt; 816 return true; 817 } 818 819 inline bool Validate(const byte* pc, ExceptionIndexImmediate<validate>& imm) { 820 if (!VALIDATE(module_ != nullptr && 821 imm.index < module_->exceptions.size())) { 822 errorf(pc + 1, "Invalid exception index: %u", imm.index); 823 return false; 824 } 825 imm.exception = &module_->exceptions[imm.index]; 826 return true; 827 } 828 829 inline bool Validate(const byte* pc, GlobalIndexImmediate<validate>& imm) { 830 if (!VALIDATE(module_ != nullptr && imm.index < module_->globals.size())) { 831 errorf(pc + 1, "invalid global index: %u", imm.index); 832 return false; 833 } 834 imm.global = &module_->globals[imm.index]; 835 imm.type = imm.global->type; 836 return true; 837 } 838 839 inline bool Complete(const byte* pc, CallFunctionImmediate<validate>& imm) { 840 if (!VALIDATE(module_ != nullptr && 841 imm.index < module_->functions.size())) { 842 return false; 843 } 844 imm.sig = module_->functions[imm.index].sig; 845 return true; 846 } 847 848 inline bool Validate(const byte* pc, CallFunctionImmediate<validate>& imm) { 849 if (Complete(pc, imm)) { 850 return true; 851 } 852 errorf(pc + 1, "invalid function index: %u", imm.index); 853 return false; 854 } 855 856 inline bool Complete(const byte* pc, CallIndirectImmediate<validate>& imm) { 857 if (!VALIDATE(module_ != nullptr && 858 imm.sig_index < module_->signatures.size())) { 859 return false; 860 } 861 imm.sig = module_->signatures[imm.sig_index]; 862 return true; 863 } 864 865 inline bool Validate(const byte* pc, CallIndirectImmediate<validate>& imm) { 866 if (!VALIDATE(module_ != nullptr && !module_->tables.empty())) { 867 error("function table has to exist to execute call_indirect"); 868 return false; 869 } 870 if (!Complete(pc, imm)) { 871 errorf(pc + 1, "invalid signature index: #%u", imm.sig_index); 872 return false; 873 } 874 return true; 875 } 876 877 inline bool Validate(const byte* pc, BreakDepthImmediate<validate>& imm, 878 size_t control_depth) { 879 if (!VALIDATE(imm.depth < control_depth)) { 880 errorf(pc + 1, "invalid break depth: %u", imm.depth); 881 return false; 882 } 883 return true; 884 } 885 886 bool Validate(const byte* pc, BranchTableImmediate<validate>& imm, 887 size_t block_depth) { 888 if (!VALIDATE(imm.table_count < kV8MaxWasmFunctionSize)) { 889 errorf(pc + 1, "invalid table count (> max function size): %u", 890 imm.table_count); 891 return false; 892 } 893 return checkAvailable(imm.table_count); 894 } 895 896 inline bool Validate(const byte* pc, WasmOpcode opcode, 897 SimdLaneImmediate<validate>& imm) { 898 uint8_t num_lanes = 0; 899 switch (opcode) { 900 case kExprF32x4ExtractLane: 901 case kExprF32x4ReplaceLane: 902 case kExprI32x4ExtractLane: 903 case kExprI32x4ReplaceLane: 904 num_lanes = 4; 905 break; 906 case kExprI16x8ExtractLane: 907 case kExprI16x8ReplaceLane: 908 num_lanes = 8; 909 break; 910 case kExprI8x16ExtractLane: 911 case kExprI8x16ReplaceLane: 912 num_lanes = 16; 913 break; 914 default: 915 UNREACHABLE(); 916 break; 917 } 918 if (!VALIDATE(imm.lane >= 0 && imm.lane < num_lanes)) { 919 error(pc_ + 2, "invalid lane index"); 920 return false; 921 } else { 922 return true; 923 } 924 } 925 926 inline bool Validate(const byte* pc, WasmOpcode opcode, 927 SimdShiftImmediate<validate>& imm) { 928 uint8_t max_shift = 0; 929 switch (opcode) { 930 case kExprI32x4Shl: 931 case kExprI32x4ShrS: 932 case kExprI32x4ShrU: 933 max_shift = 32; 934 break; 935 case kExprI16x8Shl: 936 case kExprI16x8ShrS: 937 case kExprI16x8ShrU: 938 max_shift = 16; 939 break; 940 case kExprI8x16Shl: 941 case kExprI8x16ShrS: 942 case kExprI8x16ShrU: 943 max_shift = 8; 944 break; 945 default: 946 UNREACHABLE(); 947 break; 948 } 949 if (!VALIDATE(imm.shift >= 0 && imm.shift < max_shift)) { 950 error(pc_ + 2, "invalid shift amount"); 951 return false; 952 } else { 953 return true; 954 } 955 } 956 957 inline bool Validate(const byte* pc, 958 Simd8x16ShuffleImmediate<validate>& imm) { 959 uint8_t max_lane = 0; 960 for (uint32_t i = 0; i < kSimd128Size; ++i) { 961 max_lane = std::max(max_lane, imm.shuffle[i]); 962 } 963 // Shuffle indices must be in [0..31] for a 16 lane shuffle. 964 if (!VALIDATE(max_lane <= 2 * kSimd128Size)) { 965 error(pc_ + 2, "invalid shuffle mask"); 966 return false; 967 } 968 return true; 969 } 970 971 inline bool Complete(BlockTypeImmediate<validate>& imm) { 972 if (imm.type != kWasmVar) return true; 973 if (!VALIDATE((module_ && imm.sig_index < module_->signatures.size()))) { 974 return false; 975 } 976 imm.sig = module_->signatures[imm.sig_index]; 977 return true; 978 } 979 980 inline bool Validate(BlockTypeImmediate<validate>& imm) { 981 if (!Complete(imm)) { 982 errorf(pc_, "block type index %u out of bounds (%zu signatures)", 983 imm.sig_index, module_ ? module_->signatures.size() : 0); 984 return false; 985 } 986 return true; 987 } 988 989 static unsigned OpcodeLength(Decoder* decoder, const byte* pc) { 990 WasmOpcode opcode = static_cast<WasmOpcode>(*pc); 991 switch (opcode) { 992 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: 993 FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE) 994 FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE) 995 #undef DECLARE_OPCODE_CASE 996 { 997 MemoryAccessImmediate<validate> imm(decoder, pc, UINT32_MAX); 998 return 1 + imm.length; 999 } 1000 case kExprBr: 1001 case kExprBrIf: { 1002 BreakDepthImmediate<validate> imm(decoder, pc); 1003 return 1 + imm.length; 1004 } 1005 case kExprSetGlobal: 1006 case kExprGetGlobal: { 1007 GlobalIndexImmediate<validate> imm(decoder, pc); 1008 return 1 + imm.length; 1009 } 1010 1011 case kExprCallFunction: { 1012 CallFunctionImmediate<validate> imm(decoder, pc); 1013 return 1 + imm.length; 1014 } 1015 case kExprCallIndirect: { 1016 CallIndirectImmediate<validate> imm(decoder, pc); 1017 return 1 + imm.length; 1018 } 1019 1020 case kExprTry: 1021 case kExprIf: // fall through 1022 case kExprLoop: 1023 case kExprBlock: { 1024 BlockTypeImmediate<validate> imm(kAllWasmFeatures, decoder, pc); 1025 return 1 + imm.length; 1026 } 1027 1028 case kExprThrow: 1029 case kExprCatch: { 1030 ExceptionIndexImmediate<validate> imm(decoder, pc); 1031 return 1 + imm.length; 1032 } 1033 1034 case kExprSetLocal: 1035 case kExprTeeLocal: 1036 case kExprGetLocal: { 1037 LocalIndexImmediate<Decoder::kValidate> imm(decoder, pc); 1038 return 1 + imm.length; 1039 } 1040 case kExprBrTable: { 1041 BranchTableImmediate<validate> imm(decoder, pc); 1042 BranchTableIterator<validate> iterator(decoder, imm); 1043 return 1 + iterator.length(); 1044 } 1045 case kExprI32Const: { 1046 ImmI32Immediate<validate> imm(decoder, pc); 1047 return 1 + imm.length; 1048 } 1049 case kExprI64Const: { 1050 ImmI64Immediate<validate> imm(decoder, pc); 1051 return 1 + imm.length; 1052 } 1053 case kExprRefNull: { 1054 return 1; 1055 } 1056 case kExprGrowMemory: 1057 case kExprMemorySize: { 1058 MemoryIndexImmediate<validate> imm(decoder, pc); 1059 return 1 + imm.length; 1060 } 1061 case kExprF32Const: 1062 return 5; 1063 case kExprF64Const: 1064 return 9; 1065 case kNumericPrefix: 1066 return 2; 1067 case kSimdPrefix: { 1068 byte simd_index = decoder->read_u8<validate>(pc + 1, "simd_index"); 1069 WasmOpcode opcode = 1070 static_cast<WasmOpcode>(kSimdPrefix << 8 | simd_index); 1071 switch (opcode) { 1072 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: 1073 FOREACH_SIMD_0_OPERAND_OPCODE(DECLARE_OPCODE_CASE) 1074 #undef DECLARE_OPCODE_CASE 1075 return 2; 1076 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: 1077 FOREACH_SIMD_1_OPERAND_OPCODE(DECLARE_OPCODE_CASE) 1078 #undef DECLARE_OPCODE_CASE 1079 return 3; 1080 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: 1081 FOREACH_SIMD_MEM_OPCODE(DECLARE_OPCODE_CASE) 1082 #undef DECLARE_OPCODE_CASE 1083 { 1084 MemoryAccessImmediate<validate> imm(decoder, pc + 1, UINT32_MAX); 1085 return 2 + imm.length; 1086 } 1087 // Shuffles require a byte per lane, or 16 immediate bytes. 1088 case kExprS8x16Shuffle: 1089 return 2 + kSimd128Size; 1090 default: 1091 decoder->error(pc, "invalid SIMD opcode"); 1092 return 2; 1093 } 1094 } 1095 case kAtomicPrefix: { 1096 byte atomic_index = decoder->read_u8<validate>(pc + 1, "atomic_index"); 1097 WasmOpcode opcode = 1098 static_cast<WasmOpcode>(kAtomicPrefix << 8 | atomic_index); 1099 switch (opcode) { 1100 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: 1101 FOREACH_ATOMIC_OPCODE(DECLARE_OPCODE_CASE) 1102 #undef DECLARE_OPCODE_CASE 1103 { 1104 MemoryAccessImmediate<validate> imm(decoder, pc + 1, UINT32_MAX); 1105 return 2 + imm.length; 1106 } 1107 default: 1108 decoder->error(pc, "invalid Atomics opcode"); 1109 return 2; 1110 } 1111 } 1112 default: 1113 return 1; 1114 } 1115 } 1116 1117 std::pair<uint32_t, uint32_t> StackEffect(const byte* pc) { 1118 WasmOpcode opcode = static_cast<WasmOpcode>(*pc); 1119 // Handle "simple" opcodes with a fixed signature first. 1120 FunctionSig* sig = WasmOpcodes::Signature(opcode); 1121 if (!sig) sig = WasmOpcodes::AsmjsSignature(opcode); 1122 if (sig) return {sig->parameter_count(), sig->return_count()}; 1123 1124 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: 1125 // clang-format off 1126 switch (opcode) { 1127 case kExprSelect: 1128 return {3, 1}; 1129 FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE) 1130 return {2, 0}; 1131 FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE) 1132 case kExprTeeLocal: 1133 case kExprGrowMemory: 1134 return {1, 1}; 1135 case kExprSetLocal: 1136 case kExprSetGlobal: 1137 case kExprDrop: 1138 case kExprBrIf: 1139 case kExprBrTable: 1140 case kExprIf: 1141 return {1, 0}; 1142 case kExprGetLocal: 1143 case kExprGetGlobal: 1144 case kExprI32Const: 1145 case kExprI64Const: 1146 case kExprF32Const: 1147 case kExprF64Const: 1148 case kExprRefNull: 1149 case kExprMemorySize: 1150 return {0, 1}; 1151 case kExprCallFunction: { 1152 CallFunctionImmediate<validate> imm(this, pc); 1153 CHECK(Complete(pc, imm)); 1154 return {imm.sig->parameter_count(), imm.sig->return_count()}; 1155 } 1156 case kExprCallIndirect: { 1157 CallIndirectImmediate<validate> imm(this, pc); 1158 CHECK(Complete(pc, imm)); 1159 // Indirect calls pop an additional argument for the table index. 1160 return {imm.sig->parameter_count() + 1, 1161 imm.sig->return_count()}; 1162 } 1163 case kExprBr: 1164 case kExprBlock: 1165 case kExprLoop: 1166 case kExprEnd: 1167 case kExprElse: 1168 case kExprNop: 1169 case kExprReturn: 1170 case kExprUnreachable: 1171 return {0, 0}; 1172 case kNumericPrefix: 1173 case kAtomicPrefix: 1174 case kSimdPrefix: { 1175 opcode = static_cast<WasmOpcode>(opcode << 8 | *(pc + 1)); 1176 switch (opcode) { 1177 FOREACH_SIMD_1_OPERAND_1_PARAM_OPCODE(DECLARE_OPCODE_CASE) 1178 return {1, 1}; 1179 FOREACH_SIMD_1_OPERAND_2_PARAM_OPCODE(DECLARE_OPCODE_CASE) 1180 FOREACH_SIMD_MASK_OPERAND_OPCODE(DECLARE_OPCODE_CASE) 1181 return {2, 1}; 1182 default: { 1183 sig = WasmOpcodes::Signature(opcode); 1184 if (sig) { 1185 return {sig->parameter_count(), sig->return_count()}; 1186 } 1187 } 1188 } 1189 V8_FALLTHROUGH; 1190 } 1191 default: 1192 V8_Fatal(__FILE__, __LINE__, "unimplemented opcode: %x (%s)", opcode, 1193 WasmOpcodes::OpcodeName(opcode)); 1194 return {0, 0}; 1195 } 1196 #undef DECLARE_OPCODE_CASE 1197 // clang-format on 1198 } 1199 }; 1200 1201 #define CALL_INTERFACE(name, ...) interface_.name(this, ##__VA_ARGS__) 1202 #define CALL_INTERFACE_IF_REACHABLE(name, ...) \ 1203 do { \ 1204 DCHECK(!control_.empty()); \ 1205 if (VALIDATE(this->ok()) && control_.back().reachable()) { \ 1206 interface_.name(this, ##__VA_ARGS__); \ 1207 } \ 1208 } while (false) 1209 #define CALL_INTERFACE_IF_PARENT_REACHABLE(name, ...) \ 1210 do { \ 1211 DCHECK(!control_.empty()); \ 1212 if (VALIDATE(this->ok()) && \ 1213 (control_.size() == 1 || control_at(1)->reachable())) { \ 1214 interface_.name(this, ##__VA_ARGS__); \ 1215 } \ 1216 } while (false) 1217 1218 template <Decoder::ValidateFlag validate, typename Interface> 1219 class WasmFullDecoder : public WasmDecoder<validate> { 1220 using Value = typename Interface::Value; 1221 using Control = typename Interface::Control; 1222 using MergeValues = Merge<Value>; 1223 1224 // All Value types should be trivially copyable for performance. We push, pop, 1225 // and store them in local variables. 1226 ASSERT_TRIVIALLY_COPYABLE(Value); 1227 1228 public: 1229 template <typename... InterfaceArgs> 1230 WasmFullDecoder(Zone* zone, const WasmModule* module, 1231 const WasmFeatures& enabled, WasmFeatures* detected, 1232 const FunctionBody& body, InterfaceArgs&&... interface_args) 1233 : WasmDecoder<validate>(module, enabled, detected, body.sig, body.start, 1234 body.end, body.offset), 1235 zone_(zone), 1236 interface_(std::forward<InterfaceArgs>(interface_args)...), 1237 local_type_vec_(zone), 1238 stack_(zone), 1239 control_(zone), 1240 args_(zone), 1241 last_end_found_(false) { 1242 this->local_types_ = &local_type_vec_; 1243 } 1244 1245 Interface& interface() { return interface_; } 1246 1247 bool Decode() { 1248 DCHECK(stack_.empty()); 1249 DCHECK(control_.empty()); 1250 1251 base::ElapsedTimer decode_timer; 1252 if (FLAG_trace_wasm_decode_time) { 1253 decode_timer.Start(); 1254 } 1255 1256 if (this->end_ < this->pc_) { 1257 this->error("function body end < start"); 1258 return false; 1259 } 1260 1261 DCHECK_EQ(0, this->local_types_->size()); 1262 WasmDecoder<validate>::DecodeLocals(this->enabled_, this, this->sig_, 1263 this->local_types_); 1264 CALL_INTERFACE(StartFunction); 1265 DecodeFunctionBody(); 1266 if (!this->failed()) CALL_INTERFACE(FinishFunction); 1267 1268 if (this->failed()) return this->TraceFailed(); 1269 1270 if (!control_.empty()) { 1271 // Generate a better error message whether the unterminated control 1272 // structure is the function body block or an innner structure. 1273 if (control_.size() > 1) { 1274 this->error(control_.back().pc, "unterminated control structure"); 1275 } else { 1276 this->error("function body must end with \"end\" opcode"); 1277 } 1278 return TraceFailed(); 1279 } 1280 1281 if (!last_end_found_) { 1282 this->error("function body must end with \"end\" opcode"); 1283 return false; 1284 } 1285 1286 if (FLAG_trace_wasm_decode_time) { 1287 double ms = decode_timer.Elapsed().InMillisecondsF(); 1288 PrintF("wasm-decode %s (%0.3f ms)\n\n", 1289 VALIDATE(this->ok()) ? "ok" : "failed", ms); 1290 } else { 1291 TRACE("wasm-decode %s\n\n", VALIDATE(this->ok()) ? "ok" : "failed"); 1292 } 1293 1294 return true; 1295 } 1296 1297 bool TraceFailed() { 1298 TRACE("wasm-error module+%-6d func+%d: %s\n\n", this->error_offset_, 1299 this->GetBufferRelativeOffset(this->error_offset_), 1300 this->error_msg_.c_str()); 1301 return false; 1302 } 1303 1304 const char* SafeOpcodeNameAt(const byte* pc) { 1305 if (pc >= this->end_) return "<end>"; 1306 return WasmOpcodes::OpcodeName(static_cast<WasmOpcode>(*pc)); 1307 } 1308 1309 inline Zone* zone() const { return zone_; } 1310 1311 inline uint32_t NumLocals() { 1312 return static_cast<uint32_t>(local_type_vec_.size()); 1313 } 1314 1315 inline ValueType GetLocalType(uint32_t index) { 1316 return local_type_vec_[index]; 1317 } 1318 1319 inline WasmCodePosition position() { 1320 int offset = static_cast<int>(this->pc_ - this->start_); 1321 DCHECK_EQ(this->pc_ - this->start_, offset); // overflows cannot happen 1322 return offset; 1323 } 1324 1325 inline uint32_t control_depth() const { 1326 return static_cast<uint32_t>(control_.size()); 1327 } 1328 1329 inline Control* control_at(uint32_t depth) { 1330 DCHECK_GT(control_.size(), depth); 1331 return &control_.back() - depth; 1332 } 1333 1334 inline uint32_t stack_size() const { 1335 DCHECK_GE(kMaxUInt32, stack_.size()); 1336 return static_cast<uint32_t>(stack_.size()); 1337 } 1338 1339 inline Value* stack_value(uint32_t depth) { 1340 DCHECK_GT(stack_.size(), depth); 1341 return &stack_[stack_.size() - depth - 1]; 1342 } 1343 1344 inline Value& GetMergeValueFromStack( 1345 Control* c, Merge<Value>* merge, uint32_t i) { 1346 DCHECK(merge == &c->start_merge || merge == &c->end_merge); 1347 DCHECK_GT(merge->arity, i); 1348 DCHECK_GE(stack_.size(), c->stack_depth + merge->arity); 1349 return stack_[stack_.size() - merge->arity + i]; 1350 } 1351 1352 private: 1353 static constexpr size_t kErrorMsgSize = 128; 1354 1355 Zone* zone_; 1356 1357 Interface interface_; 1358 1359 ZoneVector<ValueType> local_type_vec_; // types of local variables. 1360 ZoneVector<Value> stack_; // stack of values. 1361 ZoneVector<Control> control_; // stack of blocks, loops, and ifs. 1362 ZoneVector<Value> args_; // parameters of current block or call 1363 bool last_end_found_; 1364 1365 bool CheckHasMemory() { 1366 if (!VALIDATE(this->module_->has_memory)) { 1367 this->error(this->pc_ - 1, "memory instruction with no memory"); 1368 return false; 1369 } 1370 return true; 1371 } 1372 1373 bool CheckHasSharedMemory() { 1374 if (!VALIDATE(this->module_->has_shared_memory)) { 1375 this->error(this->pc_ - 1, "Atomic opcodes used without shared memory"); 1376 return false; 1377 } 1378 return true; 1379 } 1380 1381 class TraceLine { 1382 public: 1383 static constexpr int kMaxLen = 512; 1384 ~TraceLine() { 1385 if (!FLAG_trace_wasm_decoder) return; 1386 PrintF("%.*s\n", len_, buffer_); 1387 } 1388 1389 // Appends a formatted string. 1390 PRINTF_FORMAT(2, 3) 1391 void Append(const char* format, ...) { 1392 if (!FLAG_trace_wasm_decoder) return; 1393 va_list va_args; 1394 va_start(va_args, format); 1395 size_t remaining_len = kMaxLen - len_; 1396 Vector<char> remaining_msg_space(buffer_ + len_, remaining_len); 1397 int len = VSNPrintF(remaining_msg_space, format, va_args); 1398 va_end(va_args); 1399 len_ += len < 0 ? remaining_len : len; 1400 } 1401 1402 private: 1403 char buffer_[kMaxLen]; 1404 int len_ = 0; 1405 }; 1406 1407 // Decodes the body of a function. 1408 void DecodeFunctionBody() { 1409 TRACE("wasm-decode %p...%p (module+%u, %d bytes)\n", 1410 reinterpret_cast<const void*>(this->start()), 1411 reinterpret_cast<const void*>(this->end()), this->pc_offset(), 1412 static_cast<int>(this->end() - this->start())); 1413 1414 // Set up initial function block. 1415 { 1416 auto* c = PushBlock(); 1417 InitMerge(&c->start_merge, 0, [](uint32_t) -> Value { UNREACHABLE(); }); 1418 InitMerge(&c->end_merge, 1419 static_cast<uint32_t>(this->sig_->return_count()), 1420 [&] (uint32_t i) { 1421 return Value::New(this->pc_, this->sig_->GetReturn(i)); }); 1422 CALL_INTERFACE(StartFunctionBody, c); 1423 } 1424 1425 while (this->pc_ < this->end_) { // decoding loop. 1426 unsigned len = 1; 1427 WasmOpcode opcode = static_cast<WasmOpcode>(*this->pc_); 1428 1429 CALL_INTERFACE_IF_REACHABLE(NextInstruction, opcode); 1430 1431 #if DEBUG 1432 TraceLine trace_msg; 1433 #define TRACE_PART(...) trace_msg.Append(__VA_ARGS__) 1434 if (!WasmOpcodes::IsPrefixOpcode(opcode)) { 1435 TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_), 1436 WasmOpcodes::OpcodeName(opcode)); 1437 } 1438 #else 1439 #define TRACE_PART(...) 1440 #endif 1441 1442 FunctionSig* sig = const_cast<FunctionSig*>(kSimpleOpcodeSigs[opcode]); 1443 if (sig) { 1444 BuildSimpleOperator(opcode, sig); 1445 } else { 1446 // Complex bytecode. 1447 switch (opcode) { 1448 case kExprNop: 1449 break; 1450 case kExprBlock: { 1451 BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_); 1452 if (!this->Validate(imm)) break; 1453 PopArgs(imm.sig); 1454 auto* block = PushBlock(); 1455 SetBlockType(block, imm); 1456 CALL_INTERFACE_IF_REACHABLE(Block, block); 1457 PushMergeValues(block, &block->start_merge); 1458 len = 1 + imm.length; 1459 break; 1460 } 1461 case kExprRethrow: { 1462 // TODO(kschimpf): Implement. 1463 CHECK_PROTOTYPE_OPCODE(eh); 1464 OPCODE_ERROR(opcode, "not implemented yet"); 1465 break; 1466 } 1467 case kExprThrow: { 1468 CHECK_PROTOTYPE_OPCODE(eh); 1469 ExceptionIndexImmediate<Decoder::kValidate> imm(this, this->pc_); 1470 len = 1 + imm.length; 1471 if (!this->Validate(this->pc_, imm)) break; 1472 PopArgs(imm.exception->ToFunctionSig()); 1473 CALL_INTERFACE_IF_REACHABLE(Throw, imm, &control_.back(), 1474 vec2vec(args_)); 1475 EndControl(); 1476 break; 1477 } 1478 case kExprTry: { 1479 CHECK_PROTOTYPE_OPCODE(eh); 1480 BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_); 1481 if (!this->Validate(imm)) break; 1482 PopArgs(imm.sig); 1483 auto* try_block = PushTry(); 1484 SetBlockType(try_block, imm); 1485 len = 1 + imm.length; 1486 CALL_INTERFACE_IF_REACHABLE(Try, try_block); 1487 PushMergeValues(try_block, &try_block->start_merge); 1488 break; 1489 } 1490 case kExprCatch: { 1491 // TODO(kschimpf): Fix to use type signature of exception. 1492 CHECK_PROTOTYPE_OPCODE(eh); 1493 ExceptionIndexImmediate<Decoder::kValidate> imm(this, this->pc_); 1494 len = 1 + imm.length; 1495 1496 if (!this->Validate(this->pc_, imm)) break; 1497 1498 if (!VALIDATE(!control_.empty())) { 1499 this->error("catch does not match any try"); 1500 break; 1501 } 1502 1503 Control* c = &control_.back(); 1504 if (!VALIDATE(c->is_try())) { 1505 this->error("catch does not match any try"); 1506 break; 1507 } 1508 1509 if (!VALIDATE(c->is_incomplete_try())) { 1510 OPCODE_ERROR(opcode, "multiple catch blocks not implemented"); 1511 break; 1512 } 1513 c->kind = kControlTryCatch; 1514 FallThruTo(c); 1515 stack_.resize(c->stack_depth); 1516 const WasmExceptionSig* sig = imm.exception->sig; 1517 for (size_t i = 0, e = sig->parameter_count(); i < e; ++i) { 1518 Push(sig->GetParam(i)); 1519 } 1520 Vector<Value> values(stack_.data() + c->stack_depth, 1521 sig->parameter_count()); 1522 CALL_INTERFACE_IF_PARENT_REACHABLE(CatchException, imm, c, values); 1523 c->reachability = control_at(1)->innerReachability(); 1524 break; 1525 } 1526 case kExprCatchAll: { 1527 // TODO(kschimpf): Implement. 1528 CHECK_PROTOTYPE_OPCODE(eh); 1529 OPCODE_ERROR(opcode, "not implemented yet"); 1530 break; 1531 } 1532 case kExprLoop: { 1533 BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_); 1534 if (!this->Validate(imm)) break; 1535 PopArgs(imm.sig); 1536 auto* block = PushLoop(); 1537 SetBlockType(&control_.back(), imm); 1538 len = 1 + imm.length; 1539 CALL_INTERFACE_IF_REACHABLE(Loop, block); 1540 PushMergeValues(block, &block->start_merge); 1541 break; 1542 } 1543 case kExprIf: { 1544 BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_); 1545 if (!this->Validate(imm)) break; 1546 auto cond = Pop(0, kWasmI32); 1547 PopArgs(imm.sig); 1548 if (!VALIDATE(this->ok())) break; 1549 auto* if_block = PushIf(); 1550 SetBlockType(if_block, imm); 1551 CALL_INTERFACE_IF_REACHABLE(If, cond, if_block); 1552 len = 1 + imm.length; 1553 PushMergeValues(if_block, &if_block->start_merge); 1554 break; 1555 } 1556 case kExprElse: { 1557 if (!VALIDATE(!control_.empty())) { 1558 this->error("else does not match any if"); 1559 break; 1560 } 1561 Control* c = &control_.back(); 1562 if (!VALIDATE(c->is_if())) { 1563 this->error(this->pc_, "else does not match an if"); 1564 break; 1565 } 1566 if (c->is_if_else()) { 1567 this->error(this->pc_, "else already present for if"); 1568 break; 1569 } 1570 FallThruTo(c); 1571 c->kind = kControlIfElse; 1572 CALL_INTERFACE_IF_PARENT_REACHABLE(Else, c); 1573 PushMergeValues(c, &c->start_merge); 1574 c->reachability = control_at(1)->innerReachability(); 1575 break; 1576 } 1577 case kExprEnd: { 1578 if (!VALIDATE(!control_.empty())) { 1579 this->error("end does not match any if, try, or block"); 1580 return; 1581 } 1582 Control* c = &control_.back(); 1583 if (!VALIDATE(!c->is_incomplete_try())) { 1584 this->error(this->pc_, "missing catch in try"); 1585 break; 1586 } 1587 if (c->is_onearmed_if()) { 1588 // Emulate empty else arm. 1589 FallThruTo(c); 1590 if (this->failed()) break; 1591 CALL_INTERFACE_IF_PARENT_REACHABLE(Else, c); 1592 PushMergeValues(c, &c->start_merge); 1593 c->reachability = control_at(1)->innerReachability(); 1594 } 1595 1596 FallThruTo(c); 1597 // A loop just leaves the values on the stack. 1598 if (!c->is_loop()) PushMergeValues(c, &c->end_merge); 1599 1600 if (control_.size() == 1) { 1601 // If at the last (implicit) control, check we are at end. 1602 if (!VALIDATE(this->pc_ + 1 == this->end_)) { 1603 this->error(this->pc_ + 1, "trailing code after function end"); 1604 break; 1605 } 1606 last_end_found_ = true; 1607 // The result of the block is the return value. 1608 TRACE_PART("\n" TRACE_INST_FORMAT, startrel(this->pc_), 1609 "(implicit) return"); 1610 DoReturn(c, true); 1611 } 1612 1613 PopControl(c); 1614 break; 1615 } 1616 case kExprSelect: { 1617 auto cond = Pop(2, kWasmI32); 1618 auto fval = Pop(); 1619 auto tval = Pop(0, fval.type); 1620 auto* result = Push(tval.type == kWasmVar ? fval.type : tval.type); 1621 CALL_INTERFACE_IF_REACHABLE(Select, cond, fval, tval, result); 1622 break; 1623 } 1624 case kExprBr: { 1625 BreakDepthImmediate<validate> imm(this, this->pc_); 1626 if (!this->Validate(this->pc_, imm, control_.size())) break; 1627 Control* c = control_at(imm.depth); 1628 if (!TypeCheckBreak(c)) break; 1629 if (control_.back().reachable()) { 1630 CALL_INTERFACE(Br, c); 1631 c->br_merge()->reached = true; 1632 } 1633 len = 1 + imm.length; 1634 EndControl(); 1635 break; 1636 } 1637 case kExprBrIf: { 1638 BreakDepthImmediate<validate> imm(this, this->pc_); 1639 auto cond = Pop(0, kWasmI32); 1640 if (this->failed()) break; 1641 if (!this->Validate(this->pc_, imm, control_.size())) break; 1642 Control* c = control_at(imm.depth); 1643 if (!TypeCheckBreak(c)) break; 1644 if (control_.back().reachable()) { 1645 CALL_INTERFACE(BrIf, cond, c); 1646 c->br_merge()->reached = true; 1647 } 1648 len = 1 + imm.length; 1649 break; 1650 } 1651 case kExprBrTable: { 1652 BranchTableImmediate<validate> imm(this, this->pc_); 1653 BranchTableIterator<validate> iterator(this, imm); 1654 auto key = Pop(0, kWasmI32); 1655 if (this->failed()) break; 1656 if (!this->Validate(this->pc_, imm, control_.size())) break; 1657 uint32_t br_arity = 0; 1658 std::vector<bool> br_targets(control_.size()); 1659 while (iterator.has_next()) { 1660 const uint32_t i = iterator.cur_index(); 1661 const byte* pos = iterator.pc(); 1662 uint32_t target = iterator.next(); 1663 if (!VALIDATE(target < control_.size())) { 1664 this->errorf(pos, 1665 "improper branch in br_table target %u (depth %u)", 1666 i, target); 1667 break; 1668 } 1669 // Avoid redundant break target checks. 1670 if (br_targets[target]) continue; 1671 br_targets[target] = true; 1672 // Check that label types match up. 1673 Control* c = control_at(target); 1674 uint32_t arity = c->br_merge()->arity; 1675 if (i == 0) { 1676 br_arity = arity; 1677 } else if (!VALIDATE(br_arity == arity)) { 1678 this->errorf(pos, 1679 "inconsistent arity in br_table target %u" 1680 " (previous was %u, this one %u)", 1681 i, br_arity, arity); 1682 } 1683 if (!TypeCheckBreak(c)) break; 1684 } 1685 if (this->failed()) break; 1686 1687 if (control_.back().reachable()) { 1688 CALL_INTERFACE(BrTable, imm, key); 1689 1690 for (uint32_t depth = control_depth(); depth-- > 0;) { 1691 if (!br_targets[depth]) continue; 1692 control_at(depth)->br_merge()->reached = true; 1693 } 1694 } 1695 1696 len = 1 + iterator.length(); 1697 EndControl(); 1698 break; 1699 } 1700 case kExprReturn: { 1701 DoReturn(&control_.back(), false); 1702 break; 1703 } 1704 case kExprUnreachable: { 1705 CALL_INTERFACE_IF_REACHABLE(Unreachable); 1706 EndControl(); 1707 break; 1708 } 1709 case kExprI32Const: { 1710 ImmI32Immediate<validate> imm(this, this->pc_); 1711 auto* value = Push(kWasmI32); 1712 CALL_INTERFACE_IF_REACHABLE(I32Const, value, imm.value); 1713 len = 1 + imm.length; 1714 break; 1715 } 1716 case kExprI64Const: { 1717 ImmI64Immediate<validate> imm(this, this->pc_); 1718 auto* value = Push(kWasmI64); 1719 CALL_INTERFACE_IF_REACHABLE(I64Const, value, imm.value); 1720 len = 1 + imm.length; 1721 break; 1722 } 1723 case kExprF32Const: { 1724 ImmF32Immediate<validate> imm(this, this->pc_); 1725 auto* value = Push(kWasmF32); 1726 CALL_INTERFACE_IF_REACHABLE(F32Const, value, imm.value); 1727 len = 1 + imm.length; 1728 break; 1729 } 1730 case kExprF64Const: { 1731 ImmF64Immediate<validate> imm(this, this->pc_); 1732 auto* value = Push(kWasmF64); 1733 CALL_INTERFACE_IF_REACHABLE(F64Const, value, imm.value); 1734 len = 1 + imm.length; 1735 break; 1736 } 1737 case kExprRefNull: { 1738 CHECK_PROTOTYPE_OPCODE(anyref); 1739 auto* value = Push(kWasmAnyRef); 1740 CALL_INTERFACE_IF_REACHABLE(RefNull, value); 1741 len = 1; 1742 break; 1743 } 1744 case kExprGetLocal: { 1745 LocalIndexImmediate<Decoder::kValidate> imm(this, this->pc_); 1746 if (!this->Validate(this->pc_, imm)) break; 1747 auto* value = Push(imm.type); 1748 CALL_INTERFACE_IF_REACHABLE(GetLocal, value, imm); 1749 len = 1 + imm.length; 1750 break; 1751 } 1752 case kExprSetLocal: { 1753 LocalIndexImmediate<Decoder::kValidate> imm(this, this->pc_); 1754 if (!this->Validate(this->pc_, imm)) break; 1755 auto value = Pop(0, local_type_vec_[imm.index]); 1756 CALL_INTERFACE_IF_REACHABLE(SetLocal, value, imm); 1757 len = 1 + imm.length; 1758 break; 1759 } 1760 case kExprTeeLocal: { 1761 LocalIndexImmediate<Decoder::kValidate> imm(this, this->pc_); 1762 if (!this->Validate(this->pc_, imm)) break; 1763 auto value = Pop(0, local_type_vec_[imm.index]); 1764 auto* result = Push(value.type); 1765 CALL_INTERFACE_IF_REACHABLE(TeeLocal, value, result, imm); 1766 len = 1 + imm.length; 1767 break; 1768 } 1769 case kExprDrop: { 1770 auto value = Pop(); 1771 CALL_INTERFACE_IF_REACHABLE(Drop, value); 1772 break; 1773 } 1774 case kExprGetGlobal: { 1775 GlobalIndexImmediate<validate> imm(this, this->pc_); 1776 len = 1 + imm.length; 1777 if (!this->Validate(this->pc_, imm)) break; 1778 auto* result = Push(imm.type); 1779 CALL_INTERFACE_IF_REACHABLE(GetGlobal, result, imm); 1780 break; 1781 } 1782 case kExprSetGlobal: { 1783 GlobalIndexImmediate<validate> imm(this, this->pc_); 1784 len = 1 + imm.length; 1785 if (!this->Validate(this->pc_, imm)) break; 1786 if (!VALIDATE(imm.global->mutability)) { 1787 this->errorf(this->pc_, "immutable global #%u cannot be assigned", 1788 imm.index); 1789 break; 1790 } 1791 auto value = Pop(0, imm.type); 1792 CALL_INTERFACE_IF_REACHABLE(SetGlobal, value, imm); 1793 break; 1794 } 1795 case kExprI32LoadMem8S: 1796 len = 1 + DecodeLoadMem(LoadType::kI32Load8S); 1797 break; 1798 case kExprI32LoadMem8U: 1799 len = 1 + DecodeLoadMem(LoadType::kI32Load8U); 1800 break; 1801 case kExprI32LoadMem16S: 1802 len = 1 + DecodeLoadMem(LoadType::kI32Load16S); 1803 break; 1804 case kExprI32LoadMem16U: 1805 len = 1 + DecodeLoadMem(LoadType::kI32Load16U); 1806 break; 1807 case kExprI32LoadMem: 1808 len = 1 + DecodeLoadMem(LoadType::kI32Load); 1809 break; 1810 case kExprI64LoadMem8S: 1811 len = 1 + DecodeLoadMem(LoadType::kI64Load8S); 1812 break; 1813 case kExprI64LoadMem8U: 1814 len = 1 + DecodeLoadMem(LoadType::kI64Load8U); 1815 break; 1816 case kExprI64LoadMem16S: 1817 len = 1 + DecodeLoadMem(LoadType::kI64Load16S); 1818 break; 1819 case kExprI64LoadMem16U: 1820 len = 1 + DecodeLoadMem(LoadType::kI64Load16U); 1821 break; 1822 case kExprI64LoadMem32S: 1823 len = 1 + DecodeLoadMem(LoadType::kI64Load32S); 1824 break; 1825 case kExprI64LoadMem32U: 1826 len = 1 + DecodeLoadMem(LoadType::kI64Load32U); 1827 break; 1828 case kExprI64LoadMem: 1829 len = 1 + DecodeLoadMem(LoadType::kI64Load); 1830 break; 1831 case kExprF32LoadMem: 1832 len = 1 + DecodeLoadMem(LoadType::kF32Load); 1833 break; 1834 case kExprF64LoadMem: 1835 len = 1 + DecodeLoadMem(LoadType::kF64Load); 1836 break; 1837 case kExprI32StoreMem8: 1838 len = 1 + DecodeStoreMem(StoreType::kI32Store8); 1839 break; 1840 case kExprI32StoreMem16: 1841 len = 1 + DecodeStoreMem(StoreType::kI32Store16); 1842 break; 1843 case kExprI32StoreMem: 1844 len = 1 + DecodeStoreMem(StoreType::kI32Store); 1845 break; 1846 case kExprI64StoreMem8: 1847 len = 1 + DecodeStoreMem(StoreType::kI64Store8); 1848 break; 1849 case kExprI64StoreMem16: 1850 len = 1 + DecodeStoreMem(StoreType::kI64Store16); 1851 break; 1852 case kExprI64StoreMem32: 1853 len = 1 + DecodeStoreMem(StoreType::kI64Store32); 1854 break; 1855 case kExprI64StoreMem: 1856 len = 1 + DecodeStoreMem(StoreType::kI64Store); 1857 break; 1858 case kExprF32StoreMem: 1859 len = 1 + DecodeStoreMem(StoreType::kF32Store); 1860 break; 1861 case kExprF64StoreMem: 1862 len = 1 + DecodeStoreMem(StoreType::kF64Store); 1863 break; 1864 case kExprGrowMemory: { 1865 if (!CheckHasMemory()) break; 1866 MemoryIndexImmediate<validate> imm(this, this->pc_); 1867 len = 1 + imm.length; 1868 DCHECK_NOT_NULL(this->module_); 1869 if (!VALIDATE(this->module_->origin == kWasmOrigin)) { 1870 this->error("grow_memory is not supported for asmjs modules"); 1871 break; 1872 } 1873 auto value = Pop(0, kWasmI32); 1874 auto* result = Push(kWasmI32); 1875 CALL_INTERFACE_IF_REACHABLE(GrowMemory, value, result); 1876 break; 1877 } 1878 case kExprMemorySize: { 1879 if (!CheckHasMemory()) break; 1880 MemoryIndexImmediate<validate> imm(this, this->pc_); 1881 auto* result = Push(kWasmI32); 1882 len = 1 + imm.length; 1883 CALL_INTERFACE_IF_REACHABLE(CurrentMemoryPages, result); 1884 break; 1885 } 1886 case kExprCallFunction: { 1887 CallFunctionImmediate<validate> imm(this, this->pc_); 1888 len = 1 + imm.length; 1889 if (!this->Validate(this->pc_, imm)) break; 1890 // TODO(clemensh): Better memory management. 1891 PopArgs(imm.sig); 1892 auto* returns = PushReturns(imm.sig); 1893 CALL_INTERFACE_IF_REACHABLE(CallDirect, imm, args_.data(), returns); 1894 break; 1895 } 1896 case kExprCallIndirect: { 1897 CallIndirectImmediate<validate> imm(this, this->pc_); 1898 len = 1 + imm.length; 1899 if (!this->Validate(this->pc_, imm)) break; 1900 auto index = Pop(0, kWasmI32); 1901 PopArgs(imm.sig); 1902 auto* returns = PushReturns(imm.sig); 1903 CALL_INTERFACE_IF_REACHABLE(CallIndirect, index, imm, args_.data(), 1904 returns); 1905 break; 1906 } 1907 case kNumericPrefix: { 1908 CHECK_PROTOTYPE_OPCODE(sat_f2i_conversions); 1909 ++len; 1910 byte numeric_index = this->template read_u8<validate>( 1911 this->pc_ + 1, "numeric index"); 1912 opcode = static_cast<WasmOpcode>(opcode << 8 | numeric_index); 1913 TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_), 1914 WasmOpcodes::OpcodeName(opcode)); 1915 sig = WasmOpcodes::Signature(opcode); 1916 if (sig == nullptr) { 1917 this->errorf(this->pc_, "Unrecognized numeric opcode: %x\n", 1918 opcode); 1919 return; 1920 } 1921 BuildSimpleOperator(opcode, sig); 1922 break; 1923 } 1924 case kSimdPrefix: { 1925 CHECK_PROTOTYPE_OPCODE(simd); 1926 len++; 1927 byte simd_index = 1928 this->template read_u8<validate>(this->pc_ + 1, "simd index"); 1929 opcode = static_cast<WasmOpcode>(opcode << 8 | simd_index); 1930 TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_), 1931 WasmOpcodes::OpcodeName(opcode)); 1932 len += DecodeSimdOpcode(opcode); 1933 break; 1934 } 1935 case kAtomicPrefix: { 1936 CHECK_PROTOTYPE_OPCODE(threads); 1937 if (!CheckHasSharedMemory()) break; 1938 len++; 1939 byte atomic_index = 1940 this->template read_u8<validate>(this->pc_ + 1, "atomic index"); 1941 opcode = static_cast<WasmOpcode>(opcode << 8 | atomic_index); 1942 TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_), 1943 WasmOpcodes::OpcodeName(opcode)); 1944 len += DecodeAtomicOpcode(opcode); 1945 break; 1946 } 1947 // Note that prototype opcodes are not handled in the fastpath 1948 // above this switch, to avoid checking a feature flag. 1949 #define SIMPLE_PROTOTYPE_CASE(name, opc, sig) \ 1950 case kExpr##name: /* fallthrough */ 1951 FOREACH_SIMPLE_PROTOTYPE_OPCODE(SIMPLE_PROTOTYPE_CASE) 1952 #undef SIMPLE_PROTOTYPE_CASE 1953 BuildSimplePrototypeOperator(opcode); 1954 break; 1955 default: { 1956 // Deal with special asmjs opcodes. 1957 if (this->module_ != nullptr && 1958 this->module_->origin == kAsmJsOrigin) { 1959 sig = WasmOpcodes::AsmjsSignature(opcode); 1960 if (sig) { 1961 BuildSimpleOperator(opcode, sig); 1962 } 1963 } else { 1964 this->error("Invalid opcode"); 1965 return; 1966 } 1967 } 1968 } 1969 } 1970 1971 #if DEBUG 1972 if (FLAG_trace_wasm_decoder) { 1973 TRACE_PART(" "); 1974 for (Control& c : control_) { 1975 switch (c.kind) { 1976 case kControlIf: 1977 TRACE_PART("I"); 1978 break; 1979 case kControlBlock: 1980 TRACE_PART("B"); 1981 break; 1982 case kControlLoop: 1983 TRACE_PART("L"); 1984 break; 1985 case kControlTry: 1986 TRACE_PART("T"); 1987 break; 1988 default: 1989 break; 1990 } 1991 if (c.start_merge.arity) TRACE_PART("%u-", c.start_merge.arity); 1992 TRACE_PART("%u", c.end_merge.arity); 1993 if (!c.reachable()) TRACE_PART("%c", c.unreachable() ? '*' : '#'); 1994 } 1995 TRACE_PART(" | "); 1996 for (size_t i = 0; i < stack_.size(); ++i) { 1997 auto& val = stack_[i]; 1998 WasmOpcode opcode = static_cast<WasmOpcode>(*val.pc); 1999 if (WasmOpcodes::IsPrefixOpcode(opcode)) { 2000 opcode = static_cast<WasmOpcode>(opcode << 8 | *(val.pc + 1)); 2001 } 2002 TRACE_PART(" %c@%d:%s", ValueTypes::ShortNameOf(val.type), 2003 static_cast<int>(val.pc - this->start_), 2004 WasmOpcodes::OpcodeName(opcode)); 2005 // If the decoder failed, don't try to decode the immediates, as this 2006 // can trigger a DCHECK failure. 2007 if (this->failed()) continue; 2008 switch (opcode) { 2009 case kExprI32Const: { 2010 ImmI32Immediate<Decoder::kNoValidate> imm(this, val.pc); 2011 TRACE_PART("[%d]", imm.value); 2012 break; 2013 } 2014 case kExprGetLocal: 2015 case kExprSetLocal: 2016 case kExprTeeLocal: { 2017 LocalIndexImmediate<Decoder::kNoValidate> imm(this, val.pc); 2018 TRACE_PART("[%u]", imm.index); 2019 break; 2020 } 2021 case kExprGetGlobal: 2022 case kExprSetGlobal: { 2023 GlobalIndexImmediate<Decoder::kNoValidate> imm(this, val.pc); 2024 TRACE_PART("[%u]", imm.index); 2025 break; 2026 } 2027 default: 2028 break; 2029 } 2030 } 2031 } 2032 #endif 2033 this->pc_ += len; 2034 } // end decode loop 2035 if (!VALIDATE(this->pc_ == this->end_) && this->ok()) { 2036 this->error("Beyond end of code"); 2037 } 2038 } 2039 2040 void EndControl() { 2041 DCHECK(!control_.empty()); 2042 auto* current = &control_.back(); 2043 stack_.resize(current->stack_depth); 2044 CALL_INTERFACE_IF_REACHABLE(EndControl, current); 2045 current->reachability = kUnreachable; 2046 } 2047 2048 template<typename func> 2049 void InitMerge(Merge<Value>* merge, uint32_t arity, func get_val) { 2050 merge->arity = arity; 2051 if (arity == 1) { 2052 merge->vals.first = get_val(0); 2053 } else if (arity > 1) { 2054 merge->vals.array = zone_->NewArray<Value>(arity); 2055 for (unsigned i = 0; i < arity; i++) { 2056 merge->vals.array[i] = get_val(i); 2057 } 2058 } 2059 } 2060 2061 void SetBlockType(Control* c, BlockTypeImmediate<validate>& imm) { 2062 DCHECK_EQ(imm.in_arity(), this->args_.size()); 2063 const byte* pc = this->pc_; 2064 Value* args = this->args_.data(); 2065 InitMerge(&c->end_merge, imm.out_arity(), [pc, &imm](uint32_t i) { 2066 return Value::New(pc, imm.out_type(i)); 2067 }); 2068 InitMerge(&c->start_merge, imm.in_arity(), 2069 [args](uint32_t i) { return args[i]; }); 2070 } 2071 2072 // Pops arguments as required by signature into {args_}. 2073 V8_INLINE void PopArgs(FunctionSig* sig) { 2074 int count = sig ? static_cast<int>(sig->parameter_count()) : 0; 2075 args_.resize(count); 2076 for (int i = count - 1; i >= 0; --i) { 2077 args_[i] = Pop(i, sig->GetParam(i)); 2078 } 2079 } 2080 2081 ValueType GetReturnType(FunctionSig* sig) { 2082 DCHECK_GE(1, sig->return_count()); 2083 return sig->return_count() == 0 ? kWasmStmt : sig->GetReturn(); 2084 } 2085 2086 Control* PushControl(Control&& new_control) { 2087 Reachability reachability = 2088 control_.empty() ? kReachable : control_.back().innerReachability(); 2089 control_.emplace_back(std::move(new_control)); 2090 Control* c = &control_.back(); 2091 c->reachability = reachability; 2092 c->start_merge.reached = c->reachable(); 2093 return c; 2094 } 2095 2096 Control* PushBlock() { 2097 return PushControl(Control::Block(this->pc_, stack_size())); 2098 } 2099 Control* PushLoop() { 2100 return PushControl(Control::Loop(this->pc_, stack_size())); 2101 } 2102 Control* PushIf() { 2103 return PushControl(Control::If(this->pc_, stack_size())); 2104 } 2105 Control* PushTry() { 2106 // current_catch_ = static_cast<int32_t>(control_.size() - 1); 2107 return PushControl(Control::Try(this->pc_, stack_size())); 2108 } 2109 2110 void PopControl(Control* c) { 2111 DCHECK_EQ(c, &control_.back()); 2112 CALL_INTERFACE_IF_PARENT_REACHABLE(PopControl, c); 2113 bool reached = c->end_merge.reached; 2114 control_.pop_back(); 2115 // If the parent block was reachable before, but the popped control does not 2116 // return to here, this block becomes indirectly unreachable. 2117 if (!control_.empty() && !reached && control_.back().reachable()) { 2118 control_.back().reachability = kSpecOnlyReachable; 2119 } 2120 } 2121 2122 int DecodeLoadMem(LoadType type, int prefix_len = 0) { 2123 if (!CheckHasMemory()) return 0; 2124 MemoryAccessImmediate<validate> imm(this, this->pc_ + prefix_len, 2125 type.size_log_2()); 2126 auto index = Pop(0, kWasmI32); 2127 auto* result = Push(type.value_type()); 2128 CALL_INTERFACE_IF_REACHABLE(LoadMem, type, imm, index, result); 2129 return imm.length; 2130 } 2131 2132 int DecodeStoreMem(StoreType store, int prefix_len = 0) { 2133 if (!CheckHasMemory()) return 0; 2134 MemoryAccessImmediate<validate> imm(this, this->pc_ + prefix_len, 2135 store.size_log_2()); 2136 auto value = Pop(1, store.value_type()); 2137 auto index = Pop(0, kWasmI32); 2138 CALL_INTERFACE_IF_REACHABLE(StoreMem, store, imm, index, value); 2139 return imm.length; 2140 } 2141 2142 unsigned SimdExtractLane(WasmOpcode opcode, ValueType type) { 2143 SimdLaneImmediate<validate> imm(this, this->pc_); 2144 if (this->Validate(this->pc_, opcode, imm)) { 2145 Value inputs[] = {Pop(0, kWasmS128)}; 2146 auto* result = Push(type); 2147 CALL_INTERFACE_IF_REACHABLE(SimdLaneOp, opcode, imm, ArrayVector(inputs), 2148 result); 2149 } 2150 return imm.length; 2151 } 2152 2153 unsigned SimdReplaceLane(WasmOpcode opcode, ValueType type) { 2154 SimdLaneImmediate<validate> imm(this, this->pc_); 2155 if (this->Validate(this->pc_, opcode, imm)) { 2156 Value inputs[2]; 2157 inputs[1] = Pop(1, type); 2158 inputs[0] = Pop(0, kWasmS128); 2159 auto* result = Push(kWasmS128); 2160 CALL_INTERFACE_IF_REACHABLE(SimdLaneOp, opcode, imm, ArrayVector(inputs), 2161 result); 2162 } 2163 return imm.length; 2164 } 2165 2166 unsigned SimdShiftOp(WasmOpcode opcode) { 2167 SimdShiftImmediate<validate> imm(this, this->pc_); 2168 if (this->Validate(this->pc_, opcode, imm)) { 2169 auto input = Pop(0, kWasmS128); 2170 auto* result = Push(kWasmS128); 2171 CALL_INTERFACE_IF_REACHABLE(SimdShiftOp, opcode, imm, input, result); 2172 } 2173 return imm.length; 2174 } 2175 2176 unsigned Simd8x16ShuffleOp() { 2177 Simd8x16ShuffleImmediate<validate> imm(this, this->pc_); 2178 if (this->Validate(this->pc_, imm)) { 2179 auto input1 = Pop(1, kWasmS128); 2180 auto input0 = Pop(0, kWasmS128); 2181 auto* result = Push(kWasmS128); 2182 CALL_INTERFACE_IF_REACHABLE(Simd8x16ShuffleOp, imm, input0, input1, 2183 result); 2184 } 2185 return 16; 2186 } 2187 2188 unsigned DecodeSimdOpcode(WasmOpcode opcode) { 2189 unsigned len = 0; 2190 switch (opcode) { 2191 case kExprF32x4ExtractLane: { 2192 len = SimdExtractLane(opcode, kWasmF32); 2193 break; 2194 } 2195 case kExprI32x4ExtractLane: 2196 case kExprI16x8ExtractLane: 2197 case kExprI8x16ExtractLane: { 2198 len = SimdExtractLane(opcode, kWasmI32); 2199 break; 2200 } 2201 case kExprF32x4ReplaceLane: { 2202 len = SimdReplaceLane(opcode, kWasmF32); 2203 break; 2204 } 2205 case kExprI32x4ReplaceLane: 2206 case kExprI16x8ReplaceLane: 2207 case kExprI8x16ReplaceLane: { 2208 len = SimdReplaceLane(opcode, kWasmI32); 2209 break; 2210 } 2211 case kExprI32x4Shl: 2212 case kExprI32x4ShrS: 2213 case kExprI32x4ShrU: 2214 case kExprI16x8Shl: 2215 case kExprI16x8ShrS: 2216 case kExprI16x8ShrU: 2217 case kExprI8x16Shl: 2218 case kExprI8x16ShrS: 2219 case kExprI8x16ShrU: { 2220 len = SimdShiftOp(opcode); 2221 break; 2222 } 2223 case kExprS8x16Shuffle: { 2224 len = Simd8x16ShuffleOp(); 2225 break; 2226 } 2227 case kExprS128LoadMem: 2228 len = DecodeLoadMem(LoadType::kS128Load, 1); 2229 break; 2230 case kExprS128StoreMem: 2231 len = DecodeStoreMem(StoreType::kS128Store, 1); 2232 break; 2233 default: { 2234 FunctionSig* sig = WasmOpcodes::Signature(opcode); 2235 if (!VALIDATE(sig != nullptr)) { 2236 this->error("invalid simd opcode"); 2237 break; 2238 } 2239 PopArgs(sig); 2240 auto* results = 2241 sig->return_count() == 0 ? nullptr : Push(GetReturnType(sig)); 2242 CALL_INTERFACE_IF_REACHABLE(SimdOp, opcode, vec2vec(args_), results); 2243 } 2244 } 2245 return len; 2246 } 2247 2248 unsigned DecodeAtomicOpcode(WasmOpcode opcode) { 2249 unsigned len = 0; 2250 ValueType ret_type; 2251 FunctionSig* sig = WasmOpcodes::Signature(opcode); 2252 if (sig != nullptr) { 2253 MachineType memtype; 2254 switch (opcode) { 2255 #define CASE_ATOMIC_STORE_OP(Name, Type) \ 2256 case kExpr##Name: { \ 2257 memtype = MachineType::Type(); \ 2258 ret_type = kWasmStmt; \ 2259 break; \ 2260 } 2261 ATOMIC_STORE_OP_LIST(CASE_ATOMIC_STORE_OP) 2262 #undef CASE_ATOMIC_OP 2263 #define CASE_ATOMIC_OP(Name, Type) \ 2264 case kExpr##Name: { \ 2265 memtype = MachineType::Type(); \ 2266 ret_type = GetReturnType(sig); \ 2267 break; \ 2268 } 2269 ATOMIC_OP_LIST(CASE_ATOMIC_OP) 2270 #undef CASE_ATOMIC_OP 2271 default: 2272 this->error("invalid atomic opcode"); 2273 return 0; 2274 } 2275 MemoryAccessImmediate<validate> imm( 2276 this, this->pc_ + 1, ElementSizeLog2Of(memtype.representation())); 2277 len += imm.length; 2278 PopArgs(sig); 2279 auto result = ret_type == kWasmStmt ? nullptr : Push(GetReturnType(sig)); 2280 CALL_INTERFACE_IF_REACHABLE(AtomicOp, opcode, vec2vec(args_), imm, 2281 result); 2282 } else { 2283 this->error("invalid atomic opcode"); 2284 } 2285 return len; 2286 } 2287 2288 void DoReturn(Control* c, bool implicit) { 2289 int return_count = static_cast<int>(this->sig_->return_count()); 2290 args_.resize(return_count); 2291 2292 // Pop return values off the stack in reverse order. 2293 for (int i = return_count - 1; i >= 0; --i) { 2294 args_[i] = Pop(i, this->sig_->GetReturn(i)); 2295 } 2296 2297 // Simulate that an implicit return morally comes after the current block. 2298 if (implicit && c->end_merge.reached) c->reachability = kReachable; 2299 CALL_INTERFACE_IF_REACHABLE(DoReturn, vec2vec(args_), implicit); 2300 2301 EndControl(); 2302 } 2303 2304 inline Value* Push(ValueType type) { 2305 DCHECK_NE(kWasmStmt, type); 2306 stack_.push_back(Value::New(this->pc_, type)); 2307 return &stack_.back(); 2308 } 2309 2310 void PushMergeValues(Control* c, Merge<Value>* merge) { 2311 DCHECK_EQ(c, &control_.back()); 2312 DCHECK(merge == &c->start_merge || merge == &c->end_merge); 2313 stack_.resize(c->stack_depth); 2314 if (merge->arity == 1) { 2315 stack_.push_back(merge->vals.first); 2316 } else { 2317 for (unsigned i = 0; i < merge->arity; i++) { 2318 stack_.push_back(merge->vals.array[i]); 2319 } 2320 } 2321 DCHECK_EQ(c->stack_depth + merge->arity, stack_.size()); 2322 } 2323 2324 Value* PushReturns(FunctionSig* sig) { 2325 size_t return_count = sig->return_count(); 2326 if (return_count == 0) return nullptr; 2327 size_t old_size = stack_.size(); 2328 for (size_t i = 0; i < return_count; ++i) { 2329 Push(sig->GetReturn(i)); 2330 } 2331 return stack_.data() + old_size; 2332 } 2333 2334 Value Pop(int index, ValueType expected) { 2335 auto val = Pop(); 2336 if (!VALIDATE(val.type == expected || val.type == kWasmVar || 2337 expected == kWasmVar)) { 2338 this->errorf(val.pc, "%s[%d] expected type %s, found %s of type %s", 2339 SafeOpcodeNameAt(this->pc_), index, 2340 ValueTypes::TypeName(expected), SafeOpcodeNameAt(val.pc), 2341 ValueTypes::TypeName(val.type)); 2342 } 2343 return val; 2344 } 2345 2346 Value Pop() { 2347 DCHECK(!control_.empty()); 2348 uint32_t limit = control_.back().stack_depth; 2349 if (stack_.size() <= limit) { 2350 // Popping past the current control start in reachable code. 2351 if (!VALIDATE(control_.back().unreachable())) { 2352 this->errorf(this->pc_, "%s found empty stack", 2353 SafeOpcodeNameAt(this->pc_)); 2354 } 2355 return Value::Unreachable(this->pc_); 2356 } 2357 auto val = stack_.back(); 2358 stack_.pop_back(); 2359 return val; 2360 } 2361 2362 int startrel(const byte* ptr) { return static_cast<int>(ptr - this->start_); } 2363 2364 void FallThruTo(Control* c) { 2365 DCHECK_EQ(c, &control_.back()); 2366 if (!TypeCheckFallThru(c)) return; 2367 if (!c->reachable()) return; 2368 2369 if (!c->is_loop()) CALL_INTERFACE(FallThruTo, c); 2370 c->end_merge.reached = true; 2371 } 2372 2373 bool TypeCheckMergeValues(Control* c, Merge<Value>* merge) { 2374 DCHECK(merge == &c->start_merge || merge == &c->end_merge); 2375 DCHECK_GE(stack_.size(), c->stack_depth + merge->arity); 2376 // Typecheck the topmost {merge->arity} values on the stack. 2377 for (uint32_t i = 0; i < merge->arity; ++i) { 2378 auto& val = GetMergeValueFromStack(c, merge, i); 2379 auto& old = (*merge)[i]; 2380 if (val.type != old.type) { 2381 // If {val.type} is polymorphic, which results from unreachable, make 2382 // it more specific by using the merge value's expected type. 2383 // If it is not polymorphic, this is a type error. 2384 if (!VALIDATE(val.type == kWasmVar)) { 2385 this->errorf( 2386 this->pc_, "type error in merge[%u] (expected %s, got %s)", i, 2387 ValueTypes::TypeName(old.type), ValueTypes::TypeName(val.type)); 2388 return false; 2389 } 2390 val.type = old.type; 2391 } 2392 } 2393 2394 return true; 2395 } 2396 2397 bool TypeCheckFallThru(Control* c) { 2398 DCHECK_EQ(c, &control_.back()); 2399 if (!validate) return true; 2400 uint32_t expected = c->end_merge.arity; 2401 DCHECK_GE(stack_.size(), c->stack_depth); 2402 uint32_t actual = static_cast<uint32_t>(stack_.size()) - c->stack_depth; 2403 // Fallthrus must match the arity of the control exactly. 2404 if (!InsertUnreachablesIfNecessary(expected, actual) || actual > expected) { 2405 this->errorf( 2406 this->pc_, 2407 "expected %u elements on the stack for fallthru to @%d, found %u", 2408 expected, startrel(c->pc), actual); 2409 return false; 2410 } 2411 2412 return TypeCheckMergeValues(c, &c->end_merge); 2413 } 2414 2415 bool TypeCheckBreak(Control* c) { 2416 // Breaks must have at least the number of values expected; can have more. 2417 uint32_t expected = c->br_merge()->arity; 2418 DCHECK_GE(stack_.size(), control_.back().stack_depth); 2419 uint32_t actual = 2420 static_cast<uint32_t>(stack_.size()) - control_.back().stack_depth; 2421 if (!InsertUnreachablesIfNecessary(expected, actual)) { 2422 this->errorf(this->pc_, 2423 "expected %u elements on the stack for br to @%d, found %u", 2424 expected, startrel(c->pc), actual); 2425 return false; 2426 } 2427 return TypeCheckMergeValues(c, c->br_merge()); 2428 } 2429 2430 inline bool InsertUnreachablesIfNecessary(uint32_t expected, 2431 uint32_t actual) { 2432 if (V8_LIKELY(actual >= expected)) { 2433 return true; // enough actual values are there. 2434 } 2435 if (!VALIDATE(control_.back().unreachable())) { 2436 // There aren't enough values on the stack. 2437 return false; 2438 } 2439 // A slow path. When the actual number of values on the stack is less 2440 // than the expected number of values and the current control is 2441 // unreachable, insert unreachable values below the actual values. 2442 // This simplifies {TypeCheckMergeValues}. 2443 auto pos = stack_.begin() + (stack_.size() - actual); 2444 stack_.insert(pos, (expected - actual), Value::Unreachable(this->pc_)); 2445 return true; 2446 } 2447 2448 virtual void onFirstError() { 2449 this->end_ = this->pc_; // Terminate decoding loop. 2450 TRACE(" !%s\n", this->error_msg_.c_str()); 2451 CALL_INTERFACE(OnFirstError); 2452 } 2453 2454 void BuildSimplePrototypeOperator(WasmOpcode opcode) { 2455 if (WasmOpcodes::IsSignExtensionOpcode(opcode)) { 2456 RET_ON_PROTOTYPE_OPCODE(se); 2457 } 2458 if (WasmOpcodes::IsAnyRefOpcode(opcode)) { 2459 RET_ON_PROTOTYPE_OPCODE(anyref); 2460 } 2461 FunctionSig* sig = WasmOpcodes::Signature(opcode); 2462 BuildSimpleOperator(opcode, sig); 2463 } 2464 2465 inline void BuildSimpleOperator(WasmOpcode opcode, FunctionSig* sig) { 2466 switch (sig->parameter_count()) { 2467 case 1: { 2468 auto val = Pop(0, sig->GetParam(0)); 2469 auto* ret = 2470 sig->return_count() == 0 ? nullptr : Push(sig->GetReturn(0)); 2471 CALL_INTERFACE_IF_REACHABLE(UnOp, opcode, sig, val, ret); 2472 break; 2473 } 2474 case 2: { 2475 auto rval = Pop(1, sig->GetParam(1)); 2476 auto lval = Pop(0, sig->GetParam(0)); 2477 auto* ret = 2478 sig->return_count() == 0 ? nullptr : Push(sig->GetReturn(0)); 2479 CALL_INTERFACE_IF_REACHABLE(BinOp, opcode, sig, lval, rval, ret); 2480 break; 2481 } 2482 default: 2483 UNREACHABLE(); 2484 } 2485 } 2486 }; 2487 2488 #undef CALL_INTERFACE 2489 #undef CALL_INTERFACE_IF_REACHABLE 2490 #undef CALL_INTERFACE_IF_PARENT_REACHABLE 2491 2492 class EmptyInterface { 2493 public: 2494 static constexpr Decoder::ValidateFlag validate = Decoder::kValidate; 2495 using Value = ValueBase; 2496 using Control = ControlBase<Value>; 2497 using FullDecoder = WasmFullDecoder<validate, EmptyInterface>; 2498 2499 #define DEFINE_EMPTY_CALLBACK(name, ...) \ 2500 void name(FullDecoder* decoder, ##__VA_ARGS__) {} 2501 INTERFACE_FUNCTIONS(DEFINE_EMPTY_CALLBACK) 2502 #undef DEFINE_EMPTY_CALLBACK 2503 }; 2504 2505 #undef TRACE 2506 #undef TRACE_INST_FORMAT 2507 #undef VALIDATE 2508 #undef CHECK_PROTOTYPE_OPCODE 2509 #undef OPCODE_ERROR 2510 2511 } // namespace wasm 2512 } // namespace internal 2513 } // namespace v8 2514 2515 #endif // V8_WASM_FUNCTION_BODY_DECODER_IMPL_H_ 2516