| Index: src/wasm/ast-decoder.cc
|
| diff --git a/src/wasm/ast-decoder.cc b/src/wasm/ast-decoder.cc
|
| index 86b5e4cac42858c84382393585ac66c55f4ce444..4e19d0f6b6a1894851890ffb5bedbac1790f9c99 100644
|
| --- a/src/wasm/ast-decoder.cc
|
| +++ b/src/wasm/ast-decoder.cc
|
| @@ -150,6 +150,16 @@ struct Control {
|
| (build() ? CheckForException(builder_->func(__VA_ARGS__)) : nullptr)
|
| #define BUILD0(func) (build() ? CheckForException(builder_->func()) : nullptr)
|
|
|
| +struct LaneOperand {
|
| + uint8_t lane;
|
| + unsigned length;
|
| +
|
| + inline LaneOperand(Decoder* decoder, const byte* pc) {
|
| + lane = decoder->checked_read_u8(pc, 2, "lane");
|
| + length = 1;
|
| + }
|
| +};
|
| +
|
| // Generic Wasm bytecode decoder with utilities for decoding operands,
|
| // lengths, etc.
|
| class WasmDecoder : public Decoder {
|
| @@ -240,8 +250,17 @@ class WasmDecoder : public Decoder {
|
| return true;
|
| }
|
|
|
| + inline bool Validate(const byte* pc, LaneOperand& operand) {
|
| + if (operand.lane < 0 || operand.lane > 3) {
|
| + error(pc_, pc_ + 2, "invalid extract lane value");
|
| + return false;
|
| + } else {
|
| + return true;
|
| + }
|
| + }
|
| +
|
| unsigned OpcodeLength(const byte* pc) {
|
| - switch (static_cast<WasmOpcode>(*pc)) {
|
| + switch (static_cast<byte>(*pc)) {
|
| #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
|
| FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
|
| FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
|
| @@ -304,6 +323,27 @@ class WasmDecoder : public Decoder {
|
| return 5;
|
| case kExprF64Const:
|
| return 9;
|
| + case kSimdPrefix: {
|
| + byte simd_index = *(pc + 1);
|
| + WasmOpcode opcode =
|
| + static_cast<WasmOpcode>(kSimdPrefix << 8 | simd_index);
|
| + switch (opcode) {
|
| +#define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
|
| + FOREACH_SIMD_0_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
|
| +#undef DECLARE_OPCODE_CASE
|
| + {
|
| + return 2;
|
| + }
|
| +#define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
|
| + FOREACH_SIMD_1_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
|
| +#undef DECLARE_OPCODE_CASE
|
| + {
|
| + return 3;
|
| + }
|
| + default:
|
| + UNREACHABLE();
|
| + }
|
| + }
|
| default:
|
| return 1;
|
| }
|
| @@ -1249,18 +1289,25 @@ class WasmFullDecoder : public WasmDecoder {
|
| return 1 + operand.length;
|
| }
|
|
|
| + unsigned ExtractLane(WasmOpcode opcode, LocalType type) {
|
| + LaneOperand operand(this, pc_);
|
| + if (Validate(pc_, operand)) {
|
| + TFNode* input = Pop(0, LocalType::kSimd128).node;
|
| + TFNode* node = BUILD(SimdExtractLane, opcode, operand.lane, input);
|
| + Push(type, node);
|
| + }
|
| + return operand.length;
|
| + }
|
| +
|
| unsigned DecodeSimdOpcode(WasmOpcode opcode) {
|
| unsigned len = 0;
|
| switch (opcode) {
|
| case kExprI32x4ExtractLane: {
|
| - uint8_t lane = this->checked_read_u8(pc_, 2, "lane number");
|
| - if (lane < 0 || lane > 3) {
|
| - error(pc_, pc_ + 2, "invalid extract lane value");
|
| - }
|
| - TFNode* input = Pop(0, LocalType::kSimd128).node;
|
| - TFNode* node = BUILD(SimdExtractLane, opcode, lane, input);
|
| - Push(LocalType::kWord32, node);
|
| - len++;
|
| + len = ExtractLane(opcode, LocalType::kWord32);
|
| + break;
|
| + }
|
| + case kExprF32x4ExtractLane: {
|
| + len = ExtractLane(opcode, LocalType::kFloat32);
|
| break;
|
| }
|
| default: {
|
|
|