• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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