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