1 // Copyright 2013 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_COMPILER_MACHINE_OPERATOR_H_ 6 #define V8_COMPILER_MACHINE_OPERATOR_H_ 7 8 #include "src/base/compiler-specific.h" 9 #include "src/base/enum-set.h" 10 #include "src/base/flags.h" 11 #include "src/codegen/atomic-memory-order.h" 12 #include "src/codegen/machine-type.h" 13 #include "src/compiler/globals.h" 14 #include "src/compiler/write-barrier-kind.h" 15 #include "src/zone/zone.h" 16 17 namespace v8 { 18 namespace internal { 19 namespace compiler { 20 21 // Forward declarations. 22 struct MachineOperatorGlobalCache; 23 class Operator; 24 25 26 // For operators that are not supported on all platforms. 27 class OptionalOperator final { 28 public: OptionalOperator(bool supported,const Operator * op)29 OptionalOperator(bool supported, const Operator* op) 30 : supported_(supported), op_(op) {} 31 IsSupported()32 bool IsSupported() const { return supported_; } 33 // Gets the operator only if it is supported. op()34 const Operator* op() const { 35 DCHECK(supported_); 36 return op_; 37 } 38 // Always gets the operator, even for unsupported operators. This is useful to 39 // use the operator as a placeholder in a graph, for instance. placeholder()40 const Operator* placeholder() const { return op_; } 41 42 private: 43 bool supported_; 44 const Operator* const op_; 45 }; 46 47 48 // A Load needs a MachineType. 49 using LoadRepresentation = MachineType; 50 51 V8_EXPORT_PRIVATE LoadRepresentation LoadRepresentationOf(Operator const*) 52 V8_WARN_UNUSED_RESULT; 53 54 // A Word(32|64)AtomicLoad needs both a LoadRepresentation and a memory 55 // order. 56 class AtomicLoadParameters final { 57 public: AtomicLoadParameters(LoadRepresentation representation,AtomicMemoryOrder order)58 AtomicLoadParameters(LoadRepresentation representation, 59 AtomicMemoryOrder order) 60 : representation_(representation), order_(order) {} 61 representation()62 LoadRepresentation representation() const { return representation_; } order()63 AtomicMemoryOrder order() const { return order_; } 64 65 private: 66 LoadRepresentation representation_; 67 AtomicMemoryOrder order_; 68 }; 69 70 V8_EXPORT_PRIVATE bool operator==(AtomicLoadParameters, AtomicLoadParameters); 71 bool operator!=(AtomicLoadParameters, AtomicLoadParameters); 72 73 size_t hash_value(AtomicLoadParameters); 74 75 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, AtomicLoadParameters); 76 77 V8_EXPORT_PRIVATE AtomicLoadParameters AtomicLoadParametersOf(Operator const*) 78 V8_WARN_UNUSED_RESULT; 79 80 enum class MemoryAccessKind { 81 kNormal, 82 kUnaligned, 83 kProtected, 84 }; 85 86 size_t hash_value(MemoryAccessKind); 87 88 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, MemoryAccessKind); 89 90 enum class LoadTransformation { 91 kS128Load8Splat, 92 kS128Load16Splat, 93 kS128Load32Splat, 94 kS128Load64Splat, 95 kS128Load8x8S, 96 kS128Load8x8U, 97 kS128Load16x4S, 98 kS128Load16x4U, 99 kS128Load32x2S, 100 kS128Load32x2U, 101 kS128Load32Zero, 102 kS128Load64Zero, 103 }; 104 105 size_t hash_value(LoadTransformation); 106 107 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, LoadTransformation); 108 109 struct LoadTransformParameters { 110 MemoryAccessKind kind; 111 LoadTransformation transformation; 112 }; 113 114 size_t hash_value(LoadTransformParameters); 115 116 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, 117 LoadTransformParameters); 118 119 V8_EXPORT_PRIVATE LoadTransformParameters const& LoadTransformParametersOf( 120 Operator const*) V8_WARN_UNUSED_RESULT; 121 122 V8_EXPORT_PRIVATE bool operator==(LoadTransformParameters, 123 LoadTransformParameters); 124 bool operator!=(LoadTransformParameters, LoadTransformParameters); 125 126 struct LoadLaneParameters { 127 MemoryAccessKind kind; 128 LoadRepresentation rep; 129 uint8_t laneidx; 130 }; 131 132 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, LoadLaneParameters); 133 134 V8_EXPORT_PRIVATE LoadLaneParameters const& LoadLaneParametersOf( 135 Operator const*) V8_WARN_UNUSED_RESULT; 136 137 // A Store needs a MachineType and a WriteBarrierKind in order to emit the 138 // correct write barrier, and needs to state whether it is storing into the 139 // header word, so that the value can be packed, if necessary. 140 class StoreRepresentation final { 141 public: StoreRepresentation(MachineRepresentation representation,WriteBarrierKind write_barrier_kind)142 StoreRepresentation(MachineRepresentation representation, 143 WriteBarrierKind write_barrier_kind) 144 : representation_(representation), 145 write_barrier_kind_(write_barrier_kind) {} 146 representation()147 MachineRepresentation representation() const { return representation_; } write_barrier_kind()148 WriteBarrierKind write_barrier_kind() const { return write_barrier_kind_; } 149 150 private: 151 MachineRepresentation representation_; 152 WriteBarrierKind write_barrier_kind_; 153 }; 154 155 V8_EXPORT_PRIVATE bool operator==(StoreRepresentation, StoreRepresentation); 156 bool operator!=(StoreRepresentation, StoreRepresentation); 157 158 size_t hash_value(StoreRepresentation); 159 160 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, StoreRepresentation); 161 162 V8_EXPORT_PRIVATE StoreRepresentation const& StoreRepresentationOf( 163 Operator const*) V8_WARN_UNUSED_RESULT; 164 165 // A Word(32|64)AtomicStore needs both a StoreRepresentation and a memory order. 166 class AtomicStoreParameters final { 167 public: AtomicStoreParameters(MachineRepresentation representation,WriteBarrierKind write_barrier_kind,AtomicMemoryOrder order)168 AtomicStoreParameters(MachineRepresentation representation, 169 WriteBarrierKind write_barrier_kind, 170 AtomicMemoryOrder order) 171 : store_representation_(representation, write_barrier_kind), 172 order_(order) {} 173 representation()174 MachineRepresentation representation() const { 175 return store_representation_.representation(); 176 } write_barrier_kind()177 WriteBarrierKind write_barrier_kind() const { 178 return store_representation_.write_barrier_kind(); 179 } order()180 AtomicMemoryOrder order() const { return order_; } 181 store_representation()182 StoreRepresentation store_representation() const { 183 return store_representation_; 184 } 185 186 private: 187 StoreRepresentation store_representation_; 188 AtomicMemoryOrder order_; 189 }; 190 191 V8_EXPORT_PRIVATE bool operator==(AtomicStoreParameters, AtomicStoreParameters); 192 bool operator!=(AtomicStoreParameters, AtomicStoreParameters); 193 194 size_t hash_value(AtomicStoreParameters); 195 196 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, 197 AtomicStoreParameters); 198 199 V8_EXPORT_PRIVATE AtomicStoreParameters const& AtomicStoreParametersOf( 200 Operator const*) V8_WARN_UNUSED_RESULT; 201 202 // An UnalignedStore needs a MachineType. 203 using UnalignedStoreRepresentation = MachineRepresentation; 204 205 UnalignedStoreRepresentation const& UnalignedStoreRepresentationOf( 206 Operator const*) V8_WARN_UNUSED_RESULT; 207 208 struct StoreLaneParameters { 209 MemoryAccessKind kind; 210 MachineRepresentation rep; 211 uint8_t laneidx; 212 }; 213 214 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, StoreLaneParameters); 215 216 V8_EXPORT_PRIVATE StoreLaneParameters const& StoreLaneParametersOf( 217 Operator const*) V8_WARN_UNUSED_RESULT; 218 219 class StackSlotRepresentation final { 220 public: StackSlotRepresentation(int size,int alignment)221 StackSlotRepresentation(int size, int alignment) 222 : size_(size), alignment_(alignment) {} 223 size()224 int size() const { return size_; } alignment()225 int alignment() const { return alignment_; } 226 227 private: 228 int size_; 229 int alignment_; 230 }; 231 232 V8_EXPORT_PRIVATE bool operator==(StackSlotRepresentation, 233 StackSlotRepresentation); 234 bool operator!=(StackSlotRepresentation, StackSlotRepresentation); 235 236 size_t hash_value(StackSlotRepresentation); 237 238 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, 239 StackSlotRepresentation); 240 241 V8_EXPORT_PRIVATE StackSlotRepresentation const& StackSlotRepresentationOf( 242 Operator const* op) V8_WARN_UNUSED_RESULT; 243 244 MachineType AtomicOpType(Operator const* op) V8_WARN_UNUSED_RESULT; 245 246 class S128ImmediateParameter { 247 public: S128ImmediateParameter(const uint8_t immediate[16])248 explicit S128ImmediateParameter(const uint8_t immediate[16]) { 249 std::copy(immediate, immediate + 16, immediate_.begin()); 250 } 251 S128ImmediateParameter() = default; immediate()252 const std::array<uint8_t, 16>& immediate() const { return immediate_; } data()253 const uint8_t* data() const { return immediate_.data(); } 254 uint8_t operator[](int x) const { return immediate_[x]; } 255 256 private: 257 std::array<uint8_t, 16> immediate_; 258 }; 259 260 V8_EXPORT_PRIVATE bool operator==(S128ImmediateParameter const& lhs, 261 S128ImmediateParameter const& rhs); 262 bool operator!=(S128ImmediateParameter const& lhs, 263 S128ImmediateParameter const& rhs); 264 265 size_t hash_value(S128ImmediateParameter const& p); 266 267 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, 268 S128ImmediateParameter const&); 269 270 V8_EXPORT_PRIVATE S128ImmediateParameter const& S128ImmediateParameterOf( 271 Operator const* op) V8_WARN_UNUSED_RESULT; 272 273 StackCheckKind StackCheckKindOf(Operator const* op) V8_WARN_UNUSED_RESULT; 274 275 // ShiftKind::kShiftOutZeros means that it is guaranteed that the bits shifted 276 // out of the left operand are all zeros. If this is not the case, undefined 277 // behavior (i.e., incorrect optimizations) will happen. 278 // This is mostly useful for Smi untagging. 279 enum class ShiftKind { kNormal, kShiftOutZeros }; 280 281 size_t hash_value(ShiftKind); 282 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, ShiftKind); 283 ShiftKind ShiftKindOf(Operator const*) V8_WARN_UNUSED_RESULT; 284 285 // TruncateKind::kSetOverflowToMin sets the result of a saturating float-to-int 286 // conversion to INT_MIN if the conversion returns INT_MAX due to overflow. This 287 // makes it easier to detect an overflow. This parameter is ignored on platforms 288 // like x64 and ia32 where a range overflow does not result in INT_MAX. 289 enum class TruncateKind { kArchitectureDefault, kSetOverflowToMin }; 290 std::ostream& operator<<(std::ostream& os, TruncateKind kind); 291 size_t hash_value(TruncateKind kind); 292 293 // Interface for building machine-level operators. These operators are 294 // machine-level but machine-independent and thus define a language suitable 295 // for generating code to run on architectures such as ia32, x64, arm, etc. 296 class V8_EXPORT_PRIVATE MachineOperatorBuilder final NON_EXPORTED_BASE(ZoneObject)297 : public NON_EXPORTED_BASE(ZoneObject) { 298 public: 299 // Flags that specify which operations are available. This is useful 300 // for operations that are unsupported by some back-ends. 301 enum Flag : unsigned { 302 kNoFlags = 0u, 303 kFloat32RoundDown = 1u << 0, 304 kFloat64RoundDown = 1u << 1, 305 kFloat32RoundUp = 1u << 2, 306 kFloat64RoundUp = 1u << 3, 307 kFloat32RoundTruncate = 1u << 4, 308 kFloat64RoundTruncate = 1u << 5, 309 kFloat32RoundTiesEven = 1u << 6, 310 kFloat64RoundTiesEven = 1u << 7, 311 kFloat64RoundTiesAway = 1u << 8, 312 kInt32DivIsSafe = 1u << 9, 313 kUint32DivIsSafe = 1u << 10, 314 kWord32ShiftIsSafe = 1u << 11, 315 kWord32Ctz = 1u << 12, 316 kWord64Ctz = 1u << 13, 317 kWord64CtzLowerable = 1u << 14, 318 kWord32Popcnt = 1u << 15, 319 kWord64Popcnt = 1u << 16, 320 kWord32ReverseBits = 1u << 17, 321 kWord64ReverseBits = 1u << 18, 322 kFloat32Select = 1u << 19, 323 kFloat64Select = 1u << 20, 324 kInt32AbsWithOverflow = 1u << 21, 325 kInt64AbsWithOverflow = 1u << 22, 326 kWord32Rol = 1u << 23, 327 kWord64Rol = 1u << 24, 328 kWord64RolLowerable = 1u << 25, 329 kSatConversionIsSafe = 1u << 26, 330 kWord32Select = 1u << 27, 331 kWord64Select = 1u << 28, 332 kAllOptionalOps = 333 kFloat32RoundDown | kFloat64RoundDown | kFloat32RoundUp | 334 kFloat64RoundUp | kFloat32RoundTruncate | kFloat64RoundTruncate | 335 kFloat64RoundTiesAway | kFloat32RoundTiesEven | kFloat64RoundTiesEven | 336 kWord32Ctz | kWord64Ctz | kWord64CtzLowerable | kWord32Popcnt | 337 kWord64Popcnt | kWord32ReverseBits | kWord64ReverseBits | 338 kInt32AbsWithOverflow | kInt64AbsWithOverflow | kWord32Rol | 339 kWord64Rol | kWord64RolLowerable | kSatConversionIsSafe | 340 kFloat32Select | kFloat64Select | kWord32Select | kWord64Select 341 }; 342 using Flags = base::Flags<Flag, unsigned>; 343 344 class AlignmentRequirements { 345 public: 346 enum UnalignedAccessSupport { kNoSupport, kSomeSupport, kFullSupport }; 347 348 bool IsUnalignedLoadSupported(MachineRepresentation rep) const { 349 return IsUnalignedSupported(unalignedLoadUnsupportedTypes_, rep); 350 } 351 352 bool IsUnalignedStoreSupported(MachineRepresentation rep) const { 353 return IsUnalignedSupported(unalignedStoreUnsupportedTypes_, rep); 354 } 355 356 static AlignmentRequirements FullUnalignedAccessSupport() { 357 return AlignmentRequirements(kFullSupport); 358 } 359 static AlignmentRequirements NoUnalignedAccessSupport() { 360 return AlignmentRequirements(kNoSupport); 361 } 362 static AlignmentRequirements SomeUnalignedAccessUnsupported( 363 base::EnumSet<MachineRepresentation> unalignedLoadUnsupportedTypes, 364 base::EnumSet<MachineRepresentation> unalignedStoreUnsupportedTypes) { 365 return AlignmentRequirements(kSomeSupport, unalignedLoadUnsupportedTypes, 366 unalignedStoreUnsupportedTypes); 367 } 368 369 private: 370 explicit AlignmentRequirements( 371 AlignmentRequirements::UnalignedAccessSupport unalignedAccessSupport, 372 base::EnumSet<MachineRepresentation> unalignedLoadUnsupportedTypes = 373 base::EnumSet<MachineRepresentation>(), 374 base::EnumSet<MachineRepresentation> unalignedStoreUnsupportedTypes = 375 base::EnumSet<MachineRepresentation>()) 376 : unalignedSupport_(unalignedAccessSupport), 377 unalignedLoadUnsupportedTypes_(unalignedLoadUnsupportedTypes), 378 unalignedStoreUnsupportedTypes_(unalignedStoreUnsupportedTypes) {} 379 380 bool IsUnalignedSupported(base::EnumSet<MachineRepresentation> unsupported, 381 MachineRepresentation rep) const { 382 // All accesses of bytes in memory are aligned. 383 DCHECK_NE(MachineRepresentation::kWord8, rep); 384 switch (unalignedSupport_) { 385 case kFullSupport: 386 return true; 387 case kNoSupport: 388 return false; 389 case kSomeSupport: 390 return !unsupported.contains(rep); 391 } 392 UNREACHABLE(); 393 } 394 395 const AlignmentRequirements::UnalignedAccessSupport unalignedSupport_; 396 const base::EnumSet<MachineRepresentation> unalignedLoadUnsupportedTypes_; 397 const base::EnumSet<MachineRepresentation> unalignedStoreUnsupportedTypes_; 398 }; 399 400 explicit MachineOperatorBuilder( 401 Zone* zone, 402 MachineRepresentation word = MachineType::PointerRepresentation(), 403 Flags supportedOperators = kNoFlags, 404 AlignmentRequirements alignmentRequirements = 405 AlignmentRequirements::FullUnalignedAccessSupport()); 406 407 MachineOperatorBuilder(const MachineOperatorBuilder&) = delete; 408 MachineOperatorBuilder& operator=(const MachineOperatorBuilder&) = delete; 409 410 const Operator* Comment(const char* msg); 411 const Operator* AbortCSADcheck(); 412 const Operator* DebugBreak(); 413 const Operator* UnsafePointerAdd(); 414 415 const Operator* Word32And(); 416 const Operator* Word32Or(); 417 const Operator* Word32Xor(); 418 const Operator* Word32Shl(); 419 const Operator* Word32Shr(); 420 const Operator* Word32Sar(ShiftKind kind); 421 const Operator* Word32Sar() { return Word32Sar(ShiftKind::kNormal); } 422 const Operator* Word32SarShiftOutZeros() { 423 return Word32Sar(ShiftKind::kShiftOutZeros); 424 } 425 const OptionalOperator Word32Rol(); 426 const Operator* Word32Ror(); 427 const Operator* Word32Equal(); 428 const Operator* Word32Clz(); 429 const OptionalOperator Word32Ctz(); 430 const OptionalOperator Word32Popcnt(); 431 const OptionalOperator Word64Popcnt(); 432 const OptionalOperator Word32ReverseBits(); 433 const OptionalOperator Word64ReverseBits(); 434 const Operator* Word32ReverseBytes(); 435 const Operator* Word64ReverseBytes(); 436 const Operator* Simd128ReverseBytes(); 437 const OptionalOperator Int32AbsWithOverflow(); 438 const OptionalOperator Int64AbsWithOverflow(); 439 440 // Return true if the target's Word32 shift implementation is directly 441 // compatible with JavaScript's specification. Otherwise, we have to manually 442 // generate a mask with 0x1f on the amount ahead of generating the shift. 443 bool Word32ShiftIsSafe() const { return flags_ & kWord32ShiftIsSafe; } 444 445 // Return true if the target's implementation of float-to-int-conversions is a 446 // saturating conversion rounding towards 0. Otherwise, we have to manually 447 // generate the correct value if a saturating conversion is requested. 448 bool SatConversionIsSafe() const { return flags_ & kSatConversionIsSafe; } 449 450 const Operator* Word64And(); 451 const Operator* Word64Or(); 452 const Operator* Word64Xor(); 453 const Operator* Word64Shl(); 454 const Operator* Word64Shr(); 455 const Operator* Word64Sar(ShiftKind kind); 456 const Operator* Word64Sar() { return Word64Sar(ShiftKind::kNormal); } 457 const Operator* Word64SarShiftOutZeros() { 458 return Word64Sar(ShiftKind::kShiftOutZeros); 459 } 460 461 // 64-bit rol, ror, clz and ctz operators have two versions: the non-suffixed 462 // ones are meant to be used in 64-bit systems and have no control input. The 463 // "Lowerable"-suffixed ones are meant to be temporary operators in 32-bit 464 // systems and will be lowered to 32-bit operators. They have a control input 465 // to enable the lowering. 466 const OptionalOperator Word64Rol(); 467 const Operator* Word64Ror(); 468 const Operator* Word64Clz(); 469 const OptionalOperator Word64Ctz(); 470 const OptionalOperator Word64RolLowerable(); 471 const Operator* Word64RorLowerable(); 472 const Operator* Word64ClzLowerable(); 473 const OptionalOperator Word64CtzLowerable(); 474 475 const Operator* Word64Equal(); 476 477 const Operator* Int32PairAdd(); 478 const Operator* Int32PairSub(); 479 const Operator* Int32PairMul(); 480 const Operator* Word32PairShl(); 481 const Operator* Word32PairShr(); 482 const Operator* Word32PairSar(); 483 484 const Operator* Int32Add(); 485 const Operator* Int32AddWithOverflow(); 486 const Operator* Int32Sub(); 487 const Operator* Int32SubWithOverflow(); 488 const Operator* Int32Mul(); 489 const Operator* Int32MulWithOverflow(); 490 const Operator* Int32MulHigh(); 491 const Operator* Int32Div(); 492 const Operator* Int32Mod(); 493 const Operator* Int32LessThan(); 494 const Operator* Int32LessThanOrEqual(); 495 const Operator* Uint32Div(); 496 const Operator* Uint32LessThan(); 497 const Operator* Uint32LessThanOrEqual(); 498 const Operator* Uint32Mod(); 499 const Operator* Uint32MulHigh(); 500 bool Int32DivIsSafe() const { return flags_ & kInt32DivIsSafe; } 501 bool Uint32DivIsSafe() const { return flags_ & kUint32DivIsSafe; } 502 503 const Operator* Int64Add(); 504 const Operator* Int64AddWithOverflow(); 505 const Operator* Int64Sub(); 506 const Operator* Int64SubWithOverflow(); 507 const Operator* Int64Mul(); 508 const Operator* Int64Div(); 509 const Operator* Int64Mod(); 510 const Operator* Int64LessThan(); 511 const Operator* Int64LessThanOrEqual(); 512 const Operator* Uint64Div(); 513 const Operator* Uint64LessThan(); 514 const Operator* Uint64LessThanOrEqual(); 515 const Operator* Uint64Mod(); 516 517 // This operator reinterprets the bits of a tagged pointer as a word. 518 const Operator* BitcastTaggedToWord(); 519 520 // This operator reinterprets the bits of a tagged value as a word preserving 521 // non-pointer bits (all the bits that are not modified by GC): 522 // 1) smi tag 523 // 2) weak tag 524 // 3) smi payload if the tagged value is a smi. 525 // Note, that it's illegal to "look" at the pointer bits of non-smi values. 526 const Operator* BitcastTaggedToWordForTagAndSmiBits(); 527 528 // This operator reinterprets the bits of a tagged MaybeObject pointer as 529 // word. 530 const Operator* BitcastMaybeObjectToWord(); 531 532 // This operator reinterprets the bits of a word as tagged pointer. 533 const Operator* BitcastWordToTagged(); 534 535 // This operator reinterprets the bits of a word as a Smi. 536 const Operator* BitcastWordToTaggedSigned(); 537 538 // JavaScript float64 to int32/uint32 truncation. 539 const Operator* TruncateFloat64ToWord32(); 540 541 // These operators change the representation of numbers while preserving the 542 // value of the number. Narrowing operators assume the input is representable 543 // in the target type and are *not* defined for other inputs. 544 // Use narrowing change operators only when there is a static guarantee that 545 // the input value is representable in the target value. 546 // 547 // Some operators can have the behaviour on overflow change through specifying 548 // TruncateKind. The exact semantics are documented in the tests in 549 // test/cctest/compiler/test-run-machops.cc . 550 const Operator* ChangeFloat32ToFloat64(); 551 const Operator* ChangeFloat64ToInt32(); // narrowing 552 const Operator* ChangeFloat64ToInt64(); 553 const Operator* ChangeFloat64ToUint32(); // narrowing 554 const Operator* ChangeFloat64ToUint64(); 555 const Operator* TruncateFloat64ToInt64(TruncateKind kind); 556 const Operator* TruncateFloat64ToUint32(); 557 const Operator* TruncateFloat32ToInt32(TruncateKind kind); 558 const Operator* TruncateFloat32ToUint32(TruncateKind kind); 559 const Operator* TryTruncateFloat32ToInt64(); 560 const Operator* TryTruncateFloat64ToInt64(); 561 const Operator* TryTruncateFloat32ToUint64(); 562 const Operator* TryTruncateFloat64ToUint64(); 563 const Operator* ChangeInt32ToFloat64(); 564 const Operator* BitcastWord32ToWord64(); 565 const Operator* ChangeInt32ToInt64(); 566 const Operator* ChangeInt64ToFloat64(); 567 const Operator* ChangeUint32ToFloat64(); 568 const Operator* ChangeUint32ToUint64(); 569 570 // These operators truncate or round numbers, both changing the representation 571 // of the number and mapping multiple input values onto the same output value. 572 const Operator* TruncateFloat64ToFloat32(); 573 const Operator* TruncateInt64ToInt32(); 574 const Operator* RoundFloat64ToInt32(); 575 const Operator* RoundInt32ToFloat32(); 576 const Operator* RoundInt64ToFloat32(); 577 const Operator* RoundInt64ToFloat64(); 578 const Operator* RoundUint32ToFloat32(); 579 const Operator* RoundUint64ToFloat32(); 580 const Operator* RoundUint64ToFloat64(); 581 582 // These operators reinterpret the bits of a floating point number as an 583 // integer and vice versa. 584 const Operator* BitcastFloat32ToInt32(); 585 const Operator* BitcastFloat64ToInt64(); 586 const Operator* BitcastInt32ToFloat32(); 587 const Operator* BitcastInt64ToFloat64(); 588 589 // These operators sign-extend to Int32/Int64 590 const Operator* SignExtendWord8ToInt32(); 591 const Operator* SignExtendWord16ToInt32(); 592 const Operator* SignExtendWord8ToInt64(); 593 const Operator* SignExtendWord16ToInt64(); 594 const Operator* SignExtendWord32ToInt64(); 595 596 // Floating point operators always operate with IEEE 754 round-to-nearest 597 // (single-precision). 598 const Operator* Float32Add(); 599 const Operator* Float32Sub(); 600 const Operator* Float32Mul(); 601 const Operator* Float32Div(); 602 const Operator* Float32Sqrt(); 603 604 // Floating point operators always operate with IEEE 754 round-to-nearest 605 // (double-precision). 606 const Operator* Float64Add(); 607 const Operator* Float64Sub(); 608 const Operator* Float64Mul(); 609 const Operator* Float64Div(); 610 const Operator* Float64Mod(); 611 const Operator* Float64Sqrt(); 612 613 // Floating point comparisons complying to IEEE 754 (single-precision). 614 const Operator* Float32Equal(); 615 const Operator* Float32LessThan(); 616 const Operator* Float32LessThanOrEqual(); 617 618 // Floating point comparisons complying to IEEE 754 (double-precision). 619 const Operator* Float64Equal(); 620 const Operator* Float64LessThan(); 621 const Operator* Float64LessThanOrEqual(); 622 623 // Floating point min/max complying to EcmaScript 6 (double-precision). 624 const Operator* Float64Max(); 625 const Operator* Float64Min(); 626 // Floating point min/max complying to WebAssembly (single-precision). 627 const Operator* Float32Max(); 628 const Operator* Float32Min(); 629 630 // Floating point abs complying to IEEE 754 (single-precision). 631 const Operator* Float32Abs(); 632 633 // Floating point abs complying to IEEE 754 (double-precision). 634 const Operator* Float64Abs(); 635 636 // Floating point rounding. 637 const OptionalOperator Float32RoundDown(); 638 const OptionalOperator Float64RoundDown(); 639 const OptionalOperator Float32RoundUp(); 640 const OptionalOperator Float64RoundUp(); 641 const OptionalOperator Float32RoundTruncate(); 642 const OptionalOperator Float64RoundTruncate(); 643 const OptionalOperator Float64RoundTiesAway(); 644 const OptionalOperator Float32RoundTiesEven(); 645 const OptionalOperator Float64RoundTiesEven(); 646 647 // Conditional selects. Input 1 is the condition, Input 2 is the result value 648 // if the condition is {true}, Input 3 is the result value if the condition is 649 // false. 650 const OptionalOperator Word32Select(); 651 const OptionalOperator Word64Select(); 652 const OptionalOperator Float32Select(); 653 const OptionalOperator Float64Select(); 654 655 // Floating point neg. 656 const Operator* Float32Neg(); 657 const Operator* Float64Neg(); 658 659 // Floating point trigonometric functions (double-precision). 660 const Operator* Float64Acos(); 661 const Operator* Float64Acosh(); 662 const Operator* Float64Asin(); 663 const Operator* Float64Asinh(); 664 const Operator* Float64Atan(); 665 const Operator* Float64Atan2(); 666 const Operator* Float64Atanh(); 667 const Operator* Float64Cos(); 668 const Operator* Float64Cosh(); 669 const Operator* Float64Sin(); 670 const Operator* Float64Sinh(); 671 const Operator* Float64Tan(); 672 const Operator* Float64Tanh(); 673 674 // Floating point exponential functions (double-precision). 675 const Operator* Float64Exp(); 676 const Operator* Float64Expm1(); 677 const Operator* Float64Pow(); 678 679 // Floating point logarithm (double-precision). 680 const Operator* Float64Log(); 681 const Operator* Float64Log1p(); 682 const Operator* Float64Log2(); 683 const Operator* Float64Log10(); 684 685 // Floating point cube root (double-precision). 686 const Operator* Float64Cbrt(); 687 688 // Floating point bit representation. 689 const Operator* Float64ExtractLowWord32(); 690 const Operator* Float64ExtractHighWord32(); 691 const Operator* Float64InsertLowWord32(); 692 const Operator* Float64InsertHighWord32(); 693 694 // Change signalling NaN to quiet NaN. 695 // Identity for any input that is not signalling NaN. 696 const Operator* Float64SilenceNaN(); 697 698 // SIMD operators. 699 const Operator* F64x2Splat(); 700 const Operator* F64x2Abs(); 701 const Operator* F64x2Neg(); 702 const Operator* F64x2Sqrt(); 703 const Operator* F64x2Add(); 704 const Operator* F64x2Sub(); 705 const Operator* F64x2Mul(); 706 const Operator* F64x2Div(); 707 const Operator* F64x2ExtractLane(int32_t); 708 const Operator* F64x2Min(); 709 const Operator* F64x2Max(); 710 const Operator* F64x2ReplaceLane(int32_t); 711 const Operator* F64x2Eq(); 712 const Operator* F64x2Ne(); 713 const Operator* F64x2Lt(); 714 const Operator* F64x2Le(); 715 const Operator* F64x2Qfma(); 716 const Operator* F64x2Qfms(); 717 const Operator* F64x2Pmin(); 718 const Operator* F64x2Pmax(); 719 const Operator* F64x2Ceil(); 720 const Operator* F64x2Floor(); 721 const Operator* F64x2Trunc(); 722 const Operator* F64x2NearestInt(); 723 const Operator* F64x2ConvertLowI32x4S(); 724 const Operator* F64x2ConvertLowI32x4U(); 725 const Operator* F64x2PromoteLowF32x4(); 726 727 const Operator* F32x4Splat(); 728 const Operator* F32x4ExtractLane(int32_t); 729 const Operator* F32x4ReplaceLane(int32_t); 730 const Operator* F32x4SConvertI32x4(); 731 const Operator* F32x4UConvertI32x4(); 732 const Operator* F32x4Abs(); 733 const Operator* F32x4Neg(); 734 const Operator* F32x4Sqrt(); 735 const Operator* F32x4RecipApprox(); 736 const Operator* F32x4RecipSqrtApprox(); 737 const Operator* F32x4Add(); 738 const Operator* F32x4Sub(); 739 const Operator* F32x4Mul(); 740 const Operator* F32x4Div(); 741 const Operator* F32x4Min(); 742 const Operator* F32x4Max(); 743 const Operator* F32x4Eq(); 744 const Operator* F32x4Ne(); 745 const Operator* F32x4Lt(); 746 const Operator* F32x4Le(); 747 const Operator* F32x4Qfma(); 748 const Operator* F32x4Qfms(); 749 const Operator* F32x4Pmin(); 750 const Operator* F32x4Pmax(); 751 const Operator* F32x4Ceil(); 752 const Operator* F32x4Floor(); 753 const Operator* F32x4Trunc(); 754 const Operator* F32x4NearestInt(); 755 const Operator* F32x4DemoteF64x2Zero(); 756 757 const Operator* I64x2Splat(); 758 const Operator* I64x2SplatI32Pair(); 759 const Operator* I64x2ExtractLane(int32_t); 760 const Operator* I64x2ReplaceLane(int32_t); 761 const Operator* I64x2ReplaceLaneI32Pair(int32_t); 762 const Operator* I64x2Abs(); 763 const Operator* I64x2Neg(); 764 const Operator* I64x2SConvertI32x4Low(); 765 const Operator* I64x2SConvertI32x4High(); 766 const Operator* I64x2UConvertI32x4Low(); 767 const Operator* I64x2UConvertI32x4High(); 768 const Operator* I64x2BitMask(); 769 const Operator* I64x2Shl(); 770 const Operator* I64x2ShrS(); 771 const Operator* I64x2Add(); 772 const Operator* I64x2Sub(); 773 const Operator* I64x2Mul(); 774 const Operator* I64x2Eq(); 775 const Operator* I64x2Ne(); 776 const Operator* I64x2GtS(); 777 const Operator* I64x2GeS(); 778 const Operator* I64x2ShrU(); 779 const Operator* I64x2ExtMulLowI32x4S(); 780 const Operator* I64x2ExtMulHighI32x4S(); 781 const Operator* I64x2ExtMulLowI32x4U(); 782 const Operator* I64x2ExtMulHighI32x4U(); 783 784 const Operator* I32x4Splat(); 785 const Operator* I32x4ExtractLane(int32_t); 786 const Operator* I32x4ReplaceLane(int32_t); 787 const Operator* I32x4SConvertF32x4(); 788 const Operator* I32x4SConvertI16x8Low(); 789 const Operator* I32x4SConvertI16x8High(); 790 const Operator* I32x4Neg(); 791 const Operator* I32x4Shl(); 792 const Operator* I32x4ShrS(); 793 const Operator* I32x4Add(); 794 const Operator* I32x4Sub(); 795 const Operator* I32x4Mul(); 796 const Operator* I32x4MinS(); 797 const Operator* I32x4MaxS(); 798 const Operator* I32x4Eq(); 799 const Operator* I32x4Ne(); 800 const Operator* I32x4GtS(); 801 const Operator* I32x4GeS(); 802 803 const Operator* I32x4UConvertF32x4(); 804 const Operator* I32x4UConvertI16x8Low(); 805 const Operator* I32x4UConvertI16x8High(); 806 const Operator* I32x4ShrU(); 807 const Operator* I32x4MinU(); 808 const Operator* I32x4MaxU(); 809 const Operator* I32x4GtU(); 810 const Operator* I32x4GeU(); 811 const Operator* I32x4Abs(); 812 const Operator* I32x4BitMask(); 813 const Operator* I32x4DotI16x8S(); 814 const Operator* I32x4ExtMulLowI16x8S(); 815 const Operator* I32x4ExtMulHighI16x8S(); 816 const Operator* I32x4ExtMulLowI16x8U(); 817 const Operator* I32x4ExtMulHighI16x8U(); 818 const Operator* I32x4ExtAddPairwiseI16x8S(); 819 const Operator* I32x4ExtAddPairwiseI16x8U(); 820 const Operator* I32x4TruncSatF64x2SZero(); 821 const Operator* I32x4TruncSatF64x2UZero(); 822 823 const Operator* I16x8Splat(); 824 const Operator* I16x8ExtractLaneU(int32_t); 825 const Operator* I16x8ExtractLaneS(int32_t); 826 const Operator* I16x8ReplaceLane(int32_t); 827 const Operator* I16x8SConvertI8x16Low(); 828 const Operator* I16x8SConvertI8x16High(); 829 const Operator* I16x8Neg(); 830 const Operator* I16x8Shl(); 831 const Operator* I16x8ShrS(); 832 const Operator* I16x8SConvertI32x4(); 833 const Operator* I16x8Add(); 834 const Operator* I16x8AddSatS(); 835 const Operator* I16x8Sub(); 836 const Operator* I16x8SubSatS(); 837 const Operator* I16x8Mul(); 838 const Operator* I16x8MinS(); 839 const Operator* I16x8MaxS(); 840 const Operator* I16x8Eq(); 841 const Operator* I16x8Ne(); 842 const Operator* I16x8GtS(); 843 const Operator* I16x8GeS(); 844 845 const Operator* I16x8UConvertI8x16Low(); 846 const Operator* I16x8UConvertI8x16High(); 847 const Operator* I16x8ShrU(); 848 const Operator* I16x8UConvertI32x4(); 849 const Operator* I16x8AddSatU(); 850 const Operator* I16x8SubSatU(); 851 const Operator* I16x8MinU(); 852 const Operator* I16x8MaxU(); 853 const Operator* I16x8GtU(); 854 const Operator* I16x8GeU(); 855 const Operator* I16x8RoundingAverageU(); 856 const Operator* I16x8Q15MulRSatS(); 857 const Operator* I16x8Abs(); 858 const Operator* I16x8BitMask(); 859 const Operator* I16x8ExtMulLowI8x16S(); 860 const Operator* I16x8ExtMulHighI8x16S(); 861 const Operator* I16x8ExtMulLowI8x16U(); 862 const Operator* I16x8ExtMulHighI8x16U(); 863 const Operator* I16x8ExtAddPairwiseI8x16S(); 864 const Operator* I16x8ExtAddPairwiseI8x16U(); 865 866 const Operator* I8x16Splat(); 867 const Operator* I8x16ExtractLaneU(int32_t); 868 const Operator* I8x16ExtractLaneS(int32_t); 869 const Operator* I8x16ReplaceLane(int32_t); 870 const Operator* I8x16Neg(); 871 const Operator* I8x16Shl(); 872 const Operator* I8x16ShrS(); 873 const Operator* I8x16SConvertI16x8(); 874 const Operator* I8x16Add(); 875 const Operator* I8x16AddSatS(); 876 const Operator* I8x16Sub(); 877 const Operator* I8x16SubSatS(); 878 const Operator* I8x16MinS(); 879 const Operator* I8x16MaxS(); 880 const Operator* I8x16Eq(); 881 const Operator* I8x16Ne(); 882 const Operator* I8x16GtS(); 883 const Operator* I8x16GeS(); 884 885 const Operator* I8x16ShrU(); 886 const Operator* I8x16UConvertI16x8(); 887 const Operator* I8x16AddSatU(); 888 const Operator* I8x16SubSatU(); 889 const Operator* I8x16MinU(); 890 const Operator* I8x16MaxU(); 891 const Operator* I8x16GtU(); 892 const Operator* I8x16GeU(); 893 const Operator* I8x16RoundingAverageU(); 894 const Operator* I8x16Popcnt(); 895 const Operator* I8x16Abs(); 896 const Operator* I8x16BitMask(); 897 898 const Operator* S128Const(const uint8_t value[16]); 899 900 const Operator* S128Zero(); 901 const Operator* S128And(); 902 const Operator* S128Or(); 903 const Operator* S128Xor(); 904 const Operator* S128Not(); 905 const Operator* S128Select(); 906 const Operator* S128AndNot(); 907 908 const Operator* I8x16Swizzle(bool relaxed = false); 909 const Operator* I8x16Shuffle(const uint8_t shuffle[16]); 910 911 const Operator* V128AnyTrue(); 912 const Operator* I64x2AllTrue(); 913 const Operator* I32x4AllTrue(); 914 const Operator* I16x8AllTrue(); 915 const Operator* I8x16AllTrue(); 916 917 // Relaxed SIMD operators. 918 const Operator* I8x16RelaxedLaneSelect(); 919 const Operator* I16x8RelaxedLaneSelect(); 920 const Operator* I32x4RelaxedLaneSelect(); 921 const Operator* I64x2RelaxedLaneSelect(); 922 const Operator* F32x4RelaxedMin(); 923 const Operator* F32x4RelaxedMax(); 924 const Operator* F64x2RelaxedMin(); 925 const Operator* F64x2RelaxedMax(); 926 const Operator* I32x4RelaxedTruncF32x4S(); 927 const Operator* I32x4RelaxedTruncF32x4U(); 928 const Operator* I32x4RelaxedTruncF64x2SZero(); 929 const Operator* I32x4RelaxedTruncF64x2UZero(); 930 931 // load [base + index] 932 const Operator* Load(LoadRepresentation rep); 933 const Operator* LoadImmutable(LoadRepresentation rep); 934 const Operator* ProtectedLoad(LoadRepresentation rep); 935 936 const Operator* LoadTransform(MemoryAccessKind kind, 937 LoadTransformation transform); 938 939 // SIMD load: replace a specified lane with [base + index]. 940 const Operator* LoadLane(MemoryAccessKind kind, LoadRepresentation rep, 941 uint8_t laneidx); 942 943 // store [base + index], value 944 const Operator* Store(StoreRepresentation rep); 945 const Operator* ProtectedStore(MachineRepresentation rep); 946 947 // SIMD store: store a specified lane of value into [base + index]. 948 const Operator* StoreLane(MemoryAccessKind kind, MachineRepresentation rep, 949 uint8_t laneidx); 950 951 // unaligned load [base + index] 952 const Operator* UnalignedLoad(LoadRepresentation rep); 953 954 // unaligned store [base + index], value 955 const Operator* UnalignedStore(UnalignedStoreRepresentation rep); 956 957 const Operator* StackSlot(int size, int alignment = 0); 958 const Operator* StackSlot(MachineRepresentation rep, int alignment = 0); 959 960 // Access to the machine stack. 961 const Operator* LoadFramePointer(); 962 const Operator* LoadParentFramePointer(); 963 964 // Compares: stack_pointer [- offset] > value. The offset is optionally 965 // applied for kFunctionEntry stack checks. 966 const Operator* StackPointerGreaterThan(StackCheckKind kind); 967 968 // Loads the offset that should be applied to the current stack 969 // pointer before a stack check. Used as input to the 970 // Runtime::kStackGuardWithGap call. 971 const Operator* LoadStackCheckOffset(); 972 973 // Memory barrier. 974 const Operator* MemBarrier(); 975 976 // atomic-load [base + index] 977 const Operator* Word32AtomicLoad(AtomicLoadParameters params); 978 // atomic-load [base + index] 979 const Operator* Word64AtomicLoad(AtomicLoadParameters params); 980 // atomic-store [base + index], value 981 const Operator* Word32AtomicStore(AtomicStoreParameters params); 982 // atomic-store [base + index], value 983 const Operator* Word64AtomicStore(AtomicStoreParameters params); 984 // atomic-exchange [base + index], value 985 const Operator* Word32AtomicExchange(MachineType type); 986 // atomic-exchange [base + index], value 987 const Operator* Word64AtomicExchange(MachineType type); 988 // atomic-compare-exchange [base + index], old_value, new_value 989 const Operator* Word32AtomicCompareExchange(MachineType type); 990 // atomic-compare-exchange [base + index], old_value, new_value 991 const Operator* Word64AtomicCompareExchange(MachineType type); 992 // atomic-add [base + index], value 993 const Operator* Word32AtomicAdd(MachineType type); 994 // atomic-sub [base + index], value 995 const Operator* Word32AtomicSub(MachineType type); 996 // atomic-and [base + index], value 997 const Operator* Word32AtomicAnd(MachineType type); 998 // atomic-or [base + index], value 999 const Operator* Word32AtomicOr(MachineType type); 1000 // atomic-xor [base + index], value 1001 const Operator* Word32AtomicXor(MachineType type); 1002 // atomic-add [base + index], value 1003 const Operator* Word64AtomicAdd(MachineType type); 1004 // atomic-sub [base + index], value 1005 const Operator* Word64AtomicSub(MachineType type); 1006 // atomic-and [base + index], value 1007 const Operator* Word64AtomicAnd(MachineType type); 1008 // atomic-or [base + index], value 1009 const Operator* Word64AtomicOr(MachineType type); 1010 // atomic-xor [base + index], value 1011 const Operator* Word64AtomicXor(MachineType type); 1012 // atomic-pair-load [base + index] 1013 const Operator* Word32AtomicPairLoad(AtomicMemoryOrder order); 1014 // atomic-pair-sub [base + index], value_high, value-low 1015 const Operator* Word32AtomicPairStore(AtomicMemoryOrder order); 1016 // atomic-pair-add [base + index], value_high, value_low 1017 const Operator* Word32AtomicPairAdd(); 1018 // atomic-pair-sub [base + index], value_high, value-low 1019 const Operator* Word32AtomicPairSub(); 1020 // atomic-pair-and [base + index], value_high, value_low 1021 const Operator* Word32AtomicPairAnd(); 1022 // atomic-pair-or [base + index], value_high, value_low 1023 const Operator* Word32AtomicPairOr(); 1024 // atomic-pair-xor [base + index], value_high, value_low 1025 const Operator* Word32AtomicPairXor(); 1026 // atomic-pair-exchange [base + index], value_high, value_low 1027 const Operator* Word32AtomicPairExchange(); 1028 // atomic-pair-compare-exchange [base + index], old_value_high, old_value_low, 1029 // new_value_high, new_value_low 1030 const Operator* Word32AtomicPairCompareExchange(); 1031 1032 // Target machine word-size assumed by this builder. 1033 bool Is32() const { return word() == MachineRepresentation::kWord32; } 1034 bool Is64() const { return word() == MachineRepresentation::kWord64; } 1035 MachineRepresentation word() const { return word_; } 1036 1037 bool UnalignedLoadSupported(MachineRepresentation rep) { 1038 return alignment_requirements_.IsUnalignedLoadSupported(rep); 1039 } 1040 1041 bool UnalignedStoreSupported(MachineRepresentation rep) { 1042 return alignment_requirements_.IsUnalignedStoreSupported(rep); 1043 } 1044 1045 // Pseudo operators that translate to 32/64-bit operators depending on the 1046 // word-size of the target machine assumed by this builder. 1047 #define PSEUDO_OP_LIST(V) \ 1048 V(Word, And) \ 1049 V(Word, Or) \ 1050 V(Word, Xor) \ 1051 V(Word, Shl) \ 1052 V(Word, Shr) \ 1053 V(Word, Ror) \ 1054 V(Word, Clz) \ 1055 V(Word, Equal) \ 1056 V(Int, Add) \ 1057 V(Int, Sub) \ 1058 V(Int, Mul) \ 1059 V(Int, Div) \ 1060 V(Int, Mod) \ 1061 V(Int, LessThan) \ 1062 V(Int, LessThanOrEqual) \ 1063 V(Uint, Div) \ 1064 V(Uint, LessThan) \ 1065 V(Uint, Mod) 1066 #define PSEUDO_OP(Prefix, Suffix) \ 1067 const Operator* Prefix##Suffix() { \ 1068 return Is32() ? Prefix##32##Suffix() : Prefix##64##Suffix(); \ 1069 } 1070 PSEUDO_OP_LIST(PSEUDO_OP) 1071 #undef PSEUDO_OP 1072 #undef PSEUDO_OP_LIST 1073 1074 const Operator* WordSar(ShiftKind kind = ShiftKind::kNormal) { 1075 return Is32() ? Word32Sar(kind) : Word64Sar(kind); 1076 } 1077 const Operator* WordSarShiftOutZeros() { 1078 return WordSar(ShiftKind::kShiftOutZeros); 1079 } 1080 1081 private: 1082 Zone* zone_; 1083 MachineOperatorGlobalCache const& cache_; 1084 MachineRepresentation const word_; 1085 Flags const flags_; 1086 AlignmentRequirements const alignment_requirements_; 1087 }; 1088 1089 1090 DEFINE_OPERATORS_FOR_FLAGS(MachineOperatorBuilder::Flags) 1091 1092 } // namespace compiler 1093 } // namespace internal 1094 } // namespace v8 1095 1096 #endif // V8_COMPILER_MACHINE_OPERATOR_H_ 1097