| OLD | NEW |
| 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/zone-containers.h" | 10 #include "src/zone/zone-containers.h" |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 141 } | 141 } |
| 142 }; | 142 }; |
| 143 | 143 |
| 144 // Macros that build nodes only if there is a graph and the current SSA | 144 // Macros that build nodes only if there is a graph and the current SSA |
| 145 // environment is reachable from start. This avoids problems with malformed | 145 // environment is reachable from start. This avoids problems with malformed |
| 146 // TF graphs when decoding inputs that have unreachable code. | 146 // TF graphs when decoding inputs that have unreachable code. |
| 147 #define BUILD(func, ...) \ | 147 #define BUILD(func, ...) \ |
| 148 (build() ? CheckForException(builder_->func(__VA_ARGS__)) : nullptr) | 148 (build() ? CheckForException(builder_->func(__VA_ARGS__)) : nullptr) |
| 149 #define BUILD0(func) (build() ? CheckForException(builder_->func()) : nullptr) | 149 #define BUILD0(func) (build() ? CheckForException(builder_->func()) : nullptr) |
| 150 | 150 |
| 151 struct LaneOperand { | 151 // Operand for SIMD lane operations. |
| 152 struct SimdLaneOperand { |
| 152 uint8_t lane; | 153 uint8_t lane; |
| 153 unsigned length; | 154 unsigned length; |
| 154 | 155 |
| 155 inline LaneOperand(Decoder* decoder, const byte* pc) { | 156 inline SimdLaneOperand(Decoder* decoder, const byte* pc) { |
| 156 lane = decoder->checked_read_u8(pc, 2, "lane"); | 157 lane = decoder->checked_read_u8(pc, 2, "lane"); |
| 157 length = 1; | 158 length = 1; |
| 158 } | 159 } |
| 159 }; | 160 }; |
| 160 | 161 |
| 162 // Operand for SIMD shift operations. |
| 163 struct SimdShiftOperand { |
| 164 uint8_t shift; |
| 165 unsigned length; |
| 166 |
| 167 inline SimdShiftOperand(Decoder* decoder, const byte* pc) { |
| 168 shift = decoder->checked_read_u8(pc, 2, "shift"); |
| 169 length = 1; |
| 170 } |
| 171 }; |
| 172 |
| 161 // Generic Wasm bytecode decoder with utilities for decoding operands, | 173 // Generic Wasm bytecode decoder with utilities for decoding operands, |
| 162 // lengths, etc. | 174 // lengths, etc. |
| 163 class WasmDecoder : public Decoder { | 175 class WasmDecoder : public Decoder { |
| 164 public: | 176 public: |
| 165 WasmDecoder(const WasmModule* module, FunctionSig* sig, const byte* start, | 177 WasmDecoder(const WasmModule* module, FunctionSig* sig, const byte* start, |
| 166 const byte* end) | 178 const byte* end) |
| 167 : Decoder(start, end), | 179 : Decoder(start, end), |
| 168 module_(module), | 180 module_(module), |
| 169 sig_(sig), | 181 sig_(sig), |
| 170 local_types_(nullptr) {} | 182 local_types_(nullptr) {} |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 342 return false; | 354 return false; |
| 343 } | 355 } |
| 344 | 356 |
| 345 bool Validate(const byte* pc, BranchTableOperand& operand, | 357 bool Validate(const byte* pc, BranchTableOperand& operand, |
| 346 size_t block_depth) { | 358 size_t block_depth) { |
| 347 // TODO(titzer): add extra redundant validation for br_table here? | 359 // TODO(titzer): add extra redundant validation for br_table here? |
| 348 return true; | 360 return true; |
| 349 } | 361 } |
| 350 | 362 |
| 351 inline bool Validate(const byte* pc, WasmOpcode opcode, | 363 inline bool Validate(const byte* pc, WasmOpcode opcode, |
| 352 LaneOperand& operand) { | 364 SimdLaneOperand& operand) { |
| 353 uint8_t num_lanes = 0; | 365 uint8_t num_lanes = 0; |
| 354 switch (opcode) { | 366 switch (opcode) { |
| 355 case kExprF32x4ExtractLane: | 367 case kExprF32x4ExtractLane: |
| 356 case kExprF32x4ReplaceLane: | 368 case kExprF32x4ReplaceLane: |
| 357 case kExprI32x4ExtractLane: | 369 case kExprI32x4ExtractLane: |
| 358 case kExprI32x4ReplaceLane: | 370 case kExprI32x4ReplaceLane: |
| 359 num_lanes = 4; | 371 num_lanes = 4; |
| 360 break; | 372 break; |
| 361 case kExprI16x8ExtractLane: | 373 case kExprI16x8ExtractLane: |
| 362 case kExprI16x8ReplaceLane: | 374 case kExprI16x8ReplaceLane: |
| 363 num_lanes = 8; | 375 num_lanes = 8; |
| 364 break; | 376 break; |
| 365 case kExprI8x16ExtractLane: | 377 case kExprI8x16ExtractLane: |
| 366 case kExprI8x16ReplaceLane: | 378 case kExprI8x16ReplaceLane: |
| 367 num_lanes = 16; | 379 num_lanes = 16; |
| 368 break; | 380 break; |
| 369 default: | 381 default: |
| 370 UNREACHABLE(); | 382 UNREACHABLE(); |
| 371 break; | 383 break; |
| 372 } | 384 } |
| 373 if (operand.lane < 0 || operand.lane >= num_lanes) { | 385 if (operand.lane < 0 || operand.lane >= num_lanes) { |
| 374 error(pc_, pc_ + 2, "invalid lane value"); | 386 error(pc_, pc_ + 2, "invalid lane index"); |
| 375 return false; | 387 return false; |
| 376 } else { | 388 } else { |
| 377 return true; | 389 return true; |
| 390 } |
| 391 } |
| 392 |
| 393 inline bool Validate(const byte* pc, WasmOpcode opcode, |
| 394 SimdShiftOperand& operand) { |
| 395 uint8_t max_shift = 0; |
| 396 switch (opcode) { |
| 397 case kExprI32x4Shl: |
| 398 case kExprI32x4ShrS: |
| 399 case kExprI32x4ShrU: |
| 400 max_shift = 32; |
| 401 break; |
| 402 case kExprI16x8Shl: |
| 403 case kExprI16x8ShrS: |
| 404 case kExprI16x8ShrU: |
| 405 max_shift = 16; |
| 406 break; |
| 407 case kExprI8x16Shl: |
| 408 case kExprI8x16ShrS: |
| 409 case kExprI8x16ShrU: |
| 410 max_shift = 8; |
| 411 break; |
| 412 default: |
| 413 UNREACHABLE(); |
| 414 break; |
| 415 } |
| 416 if (operand.shift < 0 || operand.shift >= max_shift) { |
| 417 error(pc_, pc_ + 2, "invalid shift amount"); |
| 418 return false; |
| 419 } else { |
| 420 return true; |
| 378 } | 421 } |
| 379 } | 422 } |
| 380 | 423 |
| 381 static unsigned OpcodeLength(Decoder* decoder, const byte* pc) { | 424 static unsigned OpcodeLength(Decoder* decoder, const byte* pc) { |
| 382 switch (static_cast<byte>(*pc)) { | 425 switch (static_cast<byte>(*pc)) { |
| 383 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: | 426 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: |
| 384 FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE) | 427 FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE) |
| 385 FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE) | 428 FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE) |
| 386 #undef DECLARE_OPCODE_CASE | 429 #undef DECLARE_OPCODE_CASE |
| 387 { | 430 { |
| (...skipping 962 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1350 if (!CheckHasMemory()) return 0; | 1393 if (!CheckHasMemory()) return 0; |
| 1351 MemoryAccessOperand operand(this, pc_, | 1394 MemoryAccessOperand operand(this, pc_, |
| 1352 ElementSizeLog2Of(mem_type.representation())); | 1395 ElementSizeLog2Of(mem_type.representation())); |
| 1353 Value val = Pop(1, type); | 1396 Value val = Pop(1, type); |
| 1354 Value index = Pop(0, kWasmI32); | 1397 Value index = Pop(0, kWasmI32); |
| 1355 BUILD(StoreMem, mem_type, index.node, operand.offset, operand.alignment, | 1398 BUILD(StoreMem, mem_type, index.node, operand.offset, operand.alignment, |
| 1356 val.node, position()); | 1399 val.node, position()); |
| 1357 return 1 + operand.length; | 1400 return 1 + operand.length; |
| 1358 } | 1401 } |
| 1359 | 1402 |
| 1360 unsigned ExtractLane(WasmOpcode opcode, ValueType type) { | 1403 unsigned SimdExtractLane(WasmOpcode opcode, ValueType type) { |
| 1361 LaneOperand operand(this, pc_); | 1404 SimdLaneOperand operand(this, pc_); |
| 1362 if (Validate(pc_, opcode, operand)) { | 1405 if (Validate(pc_, opcode, operand)) { |
| 1363 compiler::NodeVector inputs(1, zone_); | 1406 compiler::NodeVector inputs(1, zone_); |
| 1364 inputs[0] = Pop(0, ValueType::kSimd128).node; | 1407 inputs[0] = Pop(0, ValueType::kSimd128).node; |
| 1365 TFNode* node = BUILD(SimdLaneOp, opcode, operand.lane, inputs); | 1408 TFNode* node = BUILD(SimdLaneOp, opcode, operand.lane, inputs); |
| 1366 Push(type, node); | 1409 Push(type, node); |
| 1367 } | 1410 } |
| 1368 return operand.length; | 1411 return operand.length; |
| 1369 } | 1412 } |
| 1370 | 1413 |
| 1371 unsigned ReplaceLane(WasmOpcode opcode, ValueType type) { | 1414 unsigned SimdReplaceLane(WasmOpcode opcode, ValueType type) { |
| 1372 LaneOperand operand(this, pc_); | 1415 SimdLaneOperand operand(this, pc_); |
| 1373 if (Validate(pc_, opcode, operand)) { | 1416 if (Validate(pc_, opcode, operand)) { |
| 1374 compiler::NodeVector inputs(2, zone_); | 1417 compiler::NodeVector inputs(2, zone_); |
| 1375 inputs[1] = Pop(1, type).node; | 1418 inputs[1] = Pop(1, type).node; |
| 1376 inputs[0] = Pop(0, ValueType::kSimd128).node; | 1419 inputs[0] = Pop(0, ValueType::kSimd128).node; |
| 1377 TFNode* node = BUILD(SimdLaneOp, opcode, operand.lane, inputs); | 1420 TFNode* node = BUILD(SimdLaneOp, opcode, operand.lane, inputs); |
| 1378 Push(ValueType::kSimd128, node); | 1421 Push(ValueType::kSimd128, node); |
| 1379 } | 1422 } |
| 1380 return operand.length; | 1423 return operand.length; |
| 1381 } | 1424 } |
| 1382 | 1425 |
| 1426 unsigned SimdShiftOp(WasmOpcode opcode) { |
| 1427 SimdShiftOperand operand(this, pc_); |
| 1428 if (Validate(pc_, opcode, operand)) { |
| 1429 compiler::NodeVector inputs(1, zone_); |
| 1430 inputs[0] = Pop(0, ValueType::kSimd128).node; |
| 1431 TFNode* node = BUILD(SimdShiftOp, opcode, operand.shift, inputs); |
| 1432 Push(ValueType::kSimd128, node); |
| 1433 } |
| 1434 return operand.length; |
| 1435 } |
| 1436 |
| 1383 unsigned DecodeSimdOpcode(WasmOpcode opcode) { | 1437 unsigned DecodeSimdOpcode(WasmOpcode opcode) { |
| 1384 unsigned len = 0; | 1438 unsigned len = 0; |
| 1385 switch (opcode) { | 1439 switch (opcode) { |
| 1386 case kExprF32x4ExtractLane: { | 1440 case kExprF32x4ExtractLane: { |
| 1387 len = ExtractLane(opcode, ValueType::kFloat32); | 1441 len = SimdExtractLane(opcode, ValueType::kFloat32); |
| 1388 break; | 1442 break; |
| 1389 } | 1443 } |
| 1390 case kExprI32x4ExtractLane: | 1444 case kExprI32x4ExtractLane: |
| 1391 case kExprI16x8ExtractLane: | 1445 case kExprI16x8ExtractLane: |
| 1392 case kExprI8x16ExtractLane: { | 1446 case kExprI8x16ExtractLane: { |
| 1393 len = ExtractLane(opcode, ValueType::kWord32); | 1447 len = SimdExtractLane(opcode, ValueType::kWord32); |
| 1394 break; | 1448 break; |
| 1395 } | 1449 } |
| 1396 case kExprF32x4ReplaceLane: { | 1450 case kExprF32x4ReplaceLane: { |
| 1397 len = ReplaceLane(opcode, ValueType::kFloat32); | 1451 len = SimdReplaceLane(opcode, ValueType::kFloat32); |
| 1398 break; | 1452 break; |
| 1399 } | 1453 } |
| 1400 case kExprI32x4ReplaceLane: | 1454 case kExprI32x4ReplaceLane: |
| 1401 case kExprI16x8ReplaceLane: | 1455 case kExprI16x8ReplaceLane: |
| 1402 case kExprI8x16ReplaceLane: { | 1456 case kExprI8x16ReplaceLane: { |
| 1403 len = ReplaceLane(opcode, ValueType::kWord32); | 1457 len = SimdReplaceLane(opcode, ValueType::kWord32); |
| 1458 break; |
| 1459 } |
| 1460 case kExprI32x4Shl: |
| 1461 case kExprI32x4ShrS: |
| 1462 case kExprI32x4ShrU: |
| 1463 case kExprI16x8Shl: |
| 1464 case kExprI16x8ShrS: |
| 1465 case kExprI16x8ShrU: |
| 1466 case kExprI8x16Shl: |
| 1467 case kExprI8x16ShrS: |
| 1468 case kExprI8x16ShrU: { |
| 1469 len = SimdShiftOp(opcode); |
| 1404 break; | 1470 break; |
| 1405 } | 1471 } |
| 1406 default: { | 1472 default: { |
| 1407 FunctionSig* sig = WasmOpcodes::Signature(opcode); | 1473 FunctionSig* sig = WasmOpcodes::Signature(opcode); |
| 1408 if (sig != nullptr) { | 1474 if (sig != nullptr) { |
| 1409 compiler::NodeVector inputs(sig->parameter_count(), zone_); | 1475 compiler::NodeVector inputs(sig->parameter_count(), zone_); |
| 1410 for (size_t i = sig->parameter_count(); i > 0; i--) { | 1476 for (size_t i = sig->parameter_count(); i > 0; i--) { |
| 1411 Value val = Pop(static_cast<int>(i - 1), sig->GetParam(i - 1)); | 1477 Value val = Pop(static_cast<int>(i - 1), sig->GetParam(i - 1)); |
| 1412 inputs[i - 1] = val.node; | 1478 inputs[i - 1] = val.node; |
| 1413 } | 1479 } |
| (...skipping 638 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2052 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, | 2118 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, |
| 2053 const byte* start, const byte* end) { | 2119 const byte* start, const byte* end) { |
| 2054 Decoder decoder(start, end); | 2120 Decoder decoder(start, end); |
| 2055 return WasmDecoder::AnalyzeLoopAssignment(&decoder, start, | 2121 return WasmDecoder::AnalyzeLoopAssignment(&decoder, start, |
| 2056 static_cast<int>(num_locals), zone); | 2122 static_cast<int>(num_locals), zone); |
| 2057 } | 2123 } |
| 2058 | 2124 |
| 2059 } // namespace wasm | 2125 } // namespace wasm |
| 2060 } // namespace internal | 2126 } // namespace internal |
| 2061 } // namespace v8 | 2127 } // namespace v8 |
| OLD | NEW |