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