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
17namespace v8 {
18namespace internal {
19namespace compiler {
20
21// Forward declarations.
22struct MachineOperatorGlobalCache;
23class Operator;
24
25
26// For operators that are not supported on all platforms.
27class OptionalOperator final {
28 public:
29  OptionalOperator(bool supported, const Operator* op)
30      : supported_(supported), op_(op) {}
31
32  bool IsSupported() const { return supported_; }
33  // Gets the operator only if it is supported.
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.
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.
49using LoadRepresentation = MachineType;
50
51V8_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.
56class AtomicLoadParameters final {
57 public:
58  AtomicLoadParameters(LoadRepresentation representation,
59                       AtomicMemoryOrder order)
60      : representation_(representation), order_(order) {}
61
62  LoadRepresentation representation() const { return representation_; }
63  AtomicMemoryOrder order() const { return order_; }
64
65 private:
66  LoadRepresentation representation_;
67  AtomicMemoryOrder order_;
68};
69
70V8_EXPORT_PRIVATE bool operator==(AtomicLoadParameters, AtomicLoadParameters);
71bool operator!=(AtomicLoadParameters, AtomicLoadParameters);
72
73size_t hash_value(AtomicLoadParameters);
74
75V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, AtomicLoadParameters);
76
77V8_EXPORT_PRIVATE AtomicLoadParameters AtomicLoadParametersOf(Operator const*)
78    V8_WARN_UNUSED_RESULT;
79
80enum class MemoryAccessKind {
81  kNormal,
82  kUnaligned,
83  kProtected,
84};
85
86size_t hash_value(MemoryAccessKind);
87
88V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, MemoryAccessKind);
89
90enum 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
105size_t hash_value(LoadTransformation);
106
107V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, LoadTransformation);
108
109struct LoadTransformParameters {
110  MemoryAccessKind kind;
111  LoadTransformation transformation;
112};
113
114size_t hash_value(LoadTransformParameters);
115
116V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&,
117                                           LoadTransformParameters);
118
119V8_EXPORT_PRIVATE LoadTransformParameters const& LoadTransformParametersOf(
120    Operator const*) V8_WARN_UNUSED_RESULT;
121
122V8_EXPORT_PRIVATE bool operator==(LoadTransformParameters,
123                                  LoadTransformParameters);
124bool operator!=(LoadTransformParameters, LoadTransformParameters);
125
126struct LoadLaneParameters {
127  MemoryAccessKind kind;
128  LoadRepresentation rep;
129  uint8_t laneidx;
130};
131
132V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, LoadLaneParameters);
133
134V8_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.
140class StoreRepresentation final {
141 public:
142  StoreRepresentation(MachineRepresentation representation,
143                      WriteBarrierKind write_barrier_kind)
144      : representation_(representation),
145        write_barrier_kind_(write_barrier_kind) {}
146
147  MachineRepresentation representation() const { return representation_; }
148  WriteBarrierKind write_barrier_kind() const { return write_barrier_kind_; }
149
150 private:
151  MachineRepresentation representation_;
152  WriteBarrierKind write_barrier_kind_;
153};
154
155V8_EXPORT_PRIVATE bool operator==(StoreRepresentation, StoreRepresentation);
156bool operator!=(StoreRepresentation, StoreRepresentation);
157
158size_t hash_value(StoreRepresentation);
159
160V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, StoreRepresentation);
161
162V8_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.
166class AtomicStoreParameters final {
167 public:
168  AtomicStoreParameters(MachineRepresentation representation,
169                        WriteBarrierKind write_barrier_kind,
170                        AtomicMemoryOrder order)
171      : store_representation_(representation, write_barrier_kind),
172        order_(order) {}
173
174  MachineRepresentation representation() const {
175    return store_representation_.representation();
176  }
177  WriteBarrierKind write_barrier_kind() const {
178    return store_representation_.write_barrier_kind();
179  }
180  AtomicMemoryOrder order() const { return order_; }
181
182  StoreRepresentation store_representation() const {
183    return store_representation_;
184  }
185
186 private:
187  StoreRepresentation store_representation_;
188  AtomicMemoryOrder order_;
189};
190
191V8_EXPORT_PRIVATE bool operator==(AtomicStoreParameters, AtomicStoreParameters);
192bool operator!=(AtomicStoreParameters, AtomicStoreParameters);
193
194size_t hash_value(AtomicStoreParameters);
195
196V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&,
197                                           AtomicStoreParameters);
198
199V8_EXPORT_PRIVATE AtomicStoreParameters const& AtomicStoreParametersOf(
200    Operator const*) V8_WARN_UNUSED_RESULT;
201
202// An UnalignedStore needs a MachineType.
203using UnalignedStoreRepresentation = MachineRepresentation;
204
205UnalignedStoreRepresentation const& UnalignedStoreRepresentationOf(
206    Operator const*) V8_WARN_UNUSED_RESULT;
207
208struct StoreLaneParameters {
209  MemoryAccessKind kind;
210  MachineRepresentation rep;
211  uint8_t laneidx;
212};
213
214V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, StoreLaneParameters);
215
216V8_EXPORT_PRIVATE StoreLaneParameters const& StoreLaneParametersOf(
217    Operator const*) V8_WARN_UNUSED_RESULT;
218
219class StackSlotRepresentation final {
220 public:
221  StackSlotRepresentation(int size, int alignment)
222      : size_(size), alignment_(alignment) {}
223
224  int size() const { return size_; }
225  int alignment() const { return alignment_; }
226
227 private:
228  int size_;
229  int alignment_;
230};
231
232V8_EXPORT_PRIVATE bool operator==(StackSlotRepresentation,
233                                  StackSlotRepresentation);
234bool operator!=(StackSlotRepresentation, StackSlotRepresentation);
235
236size_t hash_value(StackSlotRepresentation);
237
238V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&,
239                                           StackSlotRepresentation);
240
241V8_EXPORT_PRIVATE StackSlotRepresentation const& StackSlotRepresentationOf(
242    Operator const* op) V8_WARN_UNUSED_RESULT;
243
244MachineType AtomicOpType(Operator const* op) V8_WARN_UNUSED_RESULT;
245
246class S128ImmediateParameter {
247 public:
248  explicit S128ImmediateParameter(const uint8_t immediate[16]) {
249    std::copy(immediate, immediate + 16, immediate_.begin());
250  }
251  S128ImmediateParameter() = default;
252  const std::array<uint8_t, 16>& immediate() const { return immediate_; }
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
260V8_EXPORT_PRIVATE bool operator==(S128ImmediateParameter const& lhs,
261                                  S128ImmediateParameter const& rhs);
262bool operator!=(S128ImmediateParameter const& lhs,
263                S128ImmediateParameter const& rhs);
264
265size_t hash_value(S128ImmediateParameter const& p);
266
267V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&,
268                                           S128ImmediateParameter const&);
269
270V8_EXPORT_PRIVATE S128ImmediateParameter const& S128ImmediateParameterOf(
271    Operator const* op) V8_WARN_UNUSED_RESULT;
272
273StackCheckKind 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.
279enum class ShiftKind { kNormal, kShiftOutZeros };
280
281size_t hash_value(ShiftKind);
282V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, ShiftKind);
283ShiftKind 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.
289enum class TruncateKind { kArchitectureDefault, kSetOverflowToMin };
290std::ostream& operator<<(std::ostream& os, TruncateKind kind);
291size_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.
296class V8_EXPORT_PRIVATE MachineOperatorBuilder final
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
1090DEFINE_OPERATORS_FOR_FLAGS(MachineOperatorBuilder::Flags)
1091
1092}  // namespace compiler
1093}  // namespace internal
1094}  // namespace v8
1095
1096#endif  // V8_COMPILER_MACHINE_OPERATOR_H_
1097