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