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