| Index: src/wasm/function-body-decoder.cc
|
| diff --git a/src/wasm/function-body-decoder.cc b/src/wasm/function-body-decoder.cc
|
| index a5466d258da44f6716b6d6429c30ac9092160194..32a211e951669b720791924ac97357d71dddd8a0 100644
|
| --- a/src/wasm/function-body-decoder.cc
|
| +++ b/src/wasm/function-body-decoder.cc
|
| @@ -149,16 +149,28 @@ struct Control {
|
| (build() ? CheckForException(builder_->func(__VA_ARGS__)) : nullptr)
|
| #define BUILD0(func) (build() ? CheckForException(builder_->func()) : nullptr)
|
|
|
| -struct LaneOperand {
|
| +// Operand for SIMD lane operations.
|
| +struct SimdLaneOperand {
|
| uint8_t lane;
|
| unsigned length;
|
|
|
| - inline LaneOperand(Decoder* decoder, const byte* pc) {
|
| + inline SimdLaneOperand(Decoder* decoder, const byte* pc) {
|
| lane = decoder->checked_read_u8(pc, 2, "lane");
|
| length = 1;
|
| }
|
| };
|
|
|
| +// Operand for SIMD shift operations.
|
| +struct SimdShiftOperand {
|
| + uint8_t shift;
|
| + unsigned length;
|
| +
|
| + inline SimdShiftOperand(Decoder* decoder, const byte* pc) {
|
| + shift = decoder->checked_read_u8(pc, 2, "shift");
|
| + length = 1;
|
| + }
|
| +};
|
| +
|
| // Generic Wasm bytecode decoder with utilities for decoding operands,
|
| // lengths, etc.
|
| class WasmDecoder : public Decoder {
|
| @@ -350,7 +362,7 @@ class WasmDecoder : public Decoder {
|
| }
|
|
|
| inline bool Validate(const byte* pc, WasmOpcode opcode,
|
| - LaneOperand& operand) {
|
| + SimdLaneOperand& operand) {
|
| uint8_t num_lanes = 0;
|
| switch (opcode) {
|
| case kExprF32x4ExtractLane:
|
| @@ -372,7 +384,38 @@ class WasmDecoder : public Decoder {
|
| break;
|
| }
|
| if (operand.lane < 0 || operand.lane >= num_lanes) {
|
| - error(pc_, pc_ + 2, "invalid lane value");
|
| + error(pc_, pc_ + 2, "invalid lane index");
|
| + return false;
|
| + } else {
|
| + return true;
|
| + }
|
| + }
|
| +
|
| + inline bool Validate(const byte* pc, WasmOpcode opcode,
|
| + SimdShiftOperand& operand) {
|
| + uint8_t max_shift = 0;
|
| + switch (opcode) {
|
| + case kExprI32x4Shl:
|
| + case kExprI32x4ShrS:
|
| + case kExprI32x4ShrU:
|
| + max_shift = 32;
|
| + break;
|
| + case kExprI16x8Shl:
|
| + case kExprI16x8ShrS:
|
| + case kExprI16x8ShrU:
|
| + max_shift = 16;
|
| + break;
|
| + case kExprI8x16Shl:
|
| + case kExprI8x16ShrS:
|
| + case kExprI8x16ShrU:
|
| + max_shift = 8;
|
| + break;
|
| + default:
|
| + UNREACHABLE();
|
| + break;
|
| + }
|
| + if (operand.shift < 0 || operand.shift >= max_shift) {
|
| + error(pc_, pc_ + 2, "invalid shift amount");
|
| return false;
|
| } else {
|
| return true;
|
| @@ -1369,8 +1412,8 @@ class WasmFullDecoder : public WasmDecoder {
|
| return 1 + operand.length;
|
| }
|
|
|
| - unsigned ExtractLane(WasmOpcode opcode, ValueType type) {
|
| - LaneOperand operand(this, pc_);
|
| + unsigned SimdExtractLane(WasmOpcode opcode, ValueType type) {
|
| + SimdLaneOperand operand(this, pc_);
|
| if (Validate(pc_, opcode, operand)) {
|
| compiler::NodeVector inputs(1, zone_);
|
| inputs[0] = Pop(0, ValueType::kSimd128).node;
|
| @@ -1380,8 +1423,8 @@ class WasmFullDecoder : public WasmDecoder {
|
| return operand.length;
|
| }
|
|
|
| - unsigned ReplaceLane(WasmOpcode opcode, ValueType type) {
|
| - LaneOperand operand(this, pc_);
|
| + unsigned SimdReplaceLane(WasmOpcode opcode, ValueType type) {
|
| + SimdLaneOperand operand(this, pc_);
|
| if (Validate(pc_, opcode, operand)) {
|
| compiler::NodeVector inputs(2, zone_);
|
| inputs[1] = Pop(1, type).node;
|
| @@ -1392,27 +1435,50 @@ class WasmFullDecoder : public WasmDecoder {
|
| return operand.length;
|
| }
|
|
|
| + unsigned SimdShiftOp(WasmOpcode opcode) {
|
| + SimdShiftOperand operand(this, pc_);
|
| + if (Validate(pc_, opcode, operand)) {
|
| + compiler::NodeVector inputs(1, zone_);
|
| + inputs[0] = Pop(0, ValueType::kSimd128).node;
|
| + TFNode* node = BUILD(SimdShiftOp, opcode, operand.shift, inputs);
|
| + Push(ValueType::kSimd128, node);
|
| + }
|
| + return operand.length;
|
| + }
|
| +
|
| unsigned DecodeSimdOpcode(WasmOpcode opcode) {
|
| unsigned len = 0;
|
| switch (opcode) {
|
| case kExprF32x4ExtractLane: {
|
| - len = ExtractLane(opcode, ValueType::kFloat32);
|
| + len = SimdExtractLane(opcode, ValueType::kFloat32);
|
| break;
|
| }
|
| case kExprI32x4ExtractLane:
|
| case kExprI16x8ExtractLane:
|
| case kExprI8x16ExtractLane: {
|
| - len = ExtractLane(opcode, ValueType::kWord32);
|
| + len = SimdExtractLane(opcode, ValueType::kWord32);
|
| break;
|
| }
|
| case kExprF32x4ReplaceLane: {
|
| - len = ReplaceLane(opcode, ValueType::kFloat32);
|
| + len = SimdReplaceLane(opcode, ValueType::kFloat32);
|
| break;
|
| }
|
| case kExprI32x4ReplaceLane:
|
| case kExprI16x8ReplaceLane:
|
| case kExprI8x16ReplaceLane: {
|
| - len = ReplaceLane(opcode, ValueType::kWord32);
|
| + len = SimdReplaceLane(opcode, ValueType::kWord32);
|
| + break;
|
| + }
|
| + case kExprI32x4Shl:
|
| + case kExprI32x4ShrS:
|
| + case kExprI32x4ShrU:
|
| + case kExprI16x8Shl:
|
| + case kExprI16x8ShrS:
|
| + case kExprI16x8ShrU:
|
| + case kExprI8x16Shl:
|
| + case kExprI8x16ShrS:
|
| + case kExprI8x16ShrU: {
|
| + len = SimdShiftOp(opcode);
|
| break;
|
| }
|
| default: {
|
|
|