Home | History | Annotate | Download | only in compiler
      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/flags.h"
      9 #include "src/machine-type.h"
     10 
     11 namespace v8 {
     12 namespace internal {
     13 namespace compiler {
     14 
     15 // Forward declarations.
     16 struct MachineOperatorGlobalCache;
     17 class Operator;
     18 
     19 
     20 // For operators that are not supported on all platforms.
     21 class OptionalOperator final {
     22  public:
     23   explicit OptionalOperator(const Operator* op) : op_(op) {}
     24 
     25   bool IsSupported() const { return op_ != nullptr; }
     26   const Operator* op() const {
     27     DCHECK_NOT_NULL(op_);
     28     return op_;
     29   }
     30 
     31  private:
     32   const Operator* const op_;
     33 };
     34 
     35 
     36 // Supported float64 to int32 truncation modes.
     37 enum class TruncationMode : uint8_t {
     38   kJavaScript,  // ES6 section 7.1.5
     39   kRoundToZero  // Round towards zero. Implementation defined for NaN and ovf.
     40 };
     41 
     42 V8_INLINE size_t hash_value(TruncationMode mode) {
     43   return static_cast<uint8_t>(mode);
     44 }
     45 
     46 std::ostream& operator<<(std::ostream&, TruncationMode);
     47 
     48 TruncationMode TruncationModeOf(Operator const*);
     49 
     50 
     51 // Supported write barrier modes.
     52 enum WriteBarrierKind {
     53   kNoWriteBarrier,
     54   kMapWriteBarrier,
     55   kPointerWriteBarrier,
     56   kFullWriteBarrier
     57 };
     58 
     59 std::ostream& operator<<(std::ostream& os, WriteBarrierKind);
     60 
     61 
     62 // A Load needs a MachineType.
     63 typedef MachineType LoadRepresentation;
     64 
     65 LoadRepresentation LoadRepresentationOf(Operator const*);
     66 
     67 // A Store needs a MachineType and a WriteBarrierKind in order to emit the
     68 // correct write barrier.
     69 class StoreRepresentation final {
     70  public:
     71   StoreRepresentation(MachineRepresentation representation,
     72                       WriteBarrierKind write_barrier_kind)
     73       : representation_(representation),
     74         write_barrier_kind_(write_barrier_kind) {}
     75 
     76   MachineRepresentation representation() const { return representation_; }
     77   WriteBarrierKind write_barrier_kind() const { return write_barrier_kind_; }
     78 
     79  private:
     80   MachineRepresentation representation_;
     81   WriteBarrierKind write_barrier_kind_;
     82 };
     83 
     84 bool operator==(StoreRepresentation, StoreRepresentation);
     85 bool operator!=(StoreRepresentation, StoreRepresentation);
     86 
     87 size_t hash_value(StoreRepresentation);
     88 
     89 std::ostream& operator<<(std::ostream&, StoreRepresentation);
     90 
     91 StoreRepresentation const& StoreRepresentationOf(Operator const*);
     92 
     93 
     94 // A CheckedLoad needs a MachineType.
     95 typedef MachineType CheckedLoadRepresentation;
     96 
     97 CheckedLoadRepresentation CheckedLoadRepresentationOf(Operator const*);
     98 
     99 
    100 // A CheckedStore needs a MachineType.
    101 typedef MachineRepresentation CheckedStoreRepresentation;
    102 
    103 CheckedStoreRepresentation CheckedStoreRepresentationOf(Operator const*);
    104 
    105 
    106 // Interface for building machine-level operators. These operators are
    107 // machine-level but machine-independent and thus define a language suitable
    108 // for generating code to run on architectures such as ia32, x64, arm, etc.
    109 class MachineOperatorBuilder final : public ZoneObject {
    110  public:
    111   // Flags that specify which operations are available. This is useful
    112   // for operations that are unsupported by some back-ends.
    113   enum Flag {
    114     kNoFlags = 0u,
    115     // Note that Float*Max behaves like `(b < a) ? a : b`, not like Math.max().
    116     // Note that Float*Min behaves like `(a < b) ? a : b`, not like Math.min().
    117     kFloat32Max = 1u << 0,
    118     kFloat32Min = 1u << 1,
    119     kFloat64Max = 1u << 2,
    120     kFloat64Min = 1u << 3,
    121     kFloat32RoundDown = 1u << 4,
    122     kFloat64RoundDown = 1u << 5,
    123     kFloat32RoundUp = 1u << 6,
    124     kFloat64RoundUp = 1u << 7,
    125     kFloat32RoundTruncate = 1u << 8,
    126     kFloat64RoundTruncate = 1u << 9,
    127     kFloat32RoundTiesEven = 1u << 10,
    128     kFloat64RoundTiesEven = 1u << 11,
    129     kFloat64RoundTiesAway = 1u << 12,
    130     kInt32DivIsSafe = 1u << 13,
    131     kUint32DivIsSafe = 1u << 14,
    132     kWord32ShiftIsSafe = 1u << 15,
    133     kWord32Ctz = 1u << 16,
    134     kWord64Ctz = 1u << 17,
    135     kWord32Popcnt = 1u << 18,
    136     kWord64Popcnt = 1u << 19,
    137     kAllOptionalOps = kFloat32Max | kFloat32Min | kFloat64Max | kFloat64Min |
    138                       kFloat32RoundDown | kFloat64RoundDown | kFloat32RoundUp |
    139                       kFloat64RoundUp | kFloat32RoundTruncate |
    140                       kFloat64RoundTruncate | kFloat64RoundTiesAway |
    141                       kFloat32RoundTiesEven | kFloat64RoundTiesEven |
    142                       kWord32Ctz | kWord64Ctz | kWord32Popcnt | kWord64Popcnt
    143   };
    144   typedef base::Flags<Flag, unsigned> Flags;
    145 
    146   explicit MachineOperatorBuilder(
    147       Zone* zone,
    148       MachineRepresentation word = MachineType::PointerRepresentation(),
    149       Flags supportedOperators = kNoFlags);
    150 
    151   const Operator* Word32And();
    152   const Operator* Word32Or();
    153   const Operator* Word32Xor();
    154   const Operator* Word32Shl();
    155   const Operator* Word32Shr();
    156   const Operator* Word32Sar();
    157   const Operator* Word32Ror();
    158   const Operator* Word32Equal();
    159   const Operator* Word32Clz();
    160   const OptionalOperator Word32Ctz();
    161   const OptionalOperator Word32Popcnt();
    162   const OptionalOperator Word64Popcnt();
    163   bool Word32ShiftIsSafe() const { return flags_ & kWord32ShiftIsSafe; }
    164 
    165   const Operator* Word64And();
    166   const Operator* Word64Or();
    167   const Operator* Word64Xor();
    168   const Operator* Word64Shl();
    169   const Operator* Word64Shr();
    170   const Operator* Word64Sar();
    171   const Operator* Word64Ror();
    172   const Operator* Word64Clz();
    173   const OptionalOperator Word64Ctz();
    174   const Operator* Word64Equal();
    175 
    176   const Operator* Int32Add();
    177   const Operator* Int32AddWithOverflow();
    178   const Operator* Int32Sub();
    179   const Operator* Int32SubWithOverflow();
    180   const Operator* Int32Mul();
    181   const Operator* Int32MulHigh();
    182   const Operator* Int32Div();
    183   const Operator* Int32Mod();
    184   const Operator* Int32LessThan();
    185   const Operator* Int32LessThanOrEqual();
    186   const Operator* Uint32Div();
    187   const Operator* Uint32LessThan();
    188   const Operator* Uint32LessThanOrEqual();
    189   const Operator* Uint32Mod();
    190   const Operator* Uint32MulHigh();
    191   bool Int32DivIsSafe() const { return flags_ & kInt32DivIsSafe; }
    192   bool Uint32DivIsSafe() const { return flags_ & kUint32DivIsSafe; }
    193 
    194   const Operator* Int64Add();
    195   const Operator* Int64AddWithOverflow();
    196   const Operator* Int64Sub();
    197   const Operator* Int64SubWithOverflow();
    198   const Operator* Int64Mul();
    199   const Operator* Int64Div();
    200   const Operator* Int64Mod();
    201   const Operator* Int64LessThan();
    202   const Operator* Int64LessThanOrEqual();
    203   const Operator* Uint64Div();
    204   const Operator* Uint64LessThan();
    205   const Operator* Uint64LessThanOrEqual();
    206   const Operator* Uint64Mod();
    207 
    208   // These operators change the representation of numbers while preserving the
    209   // value of the number. Narrowing operators assume the input is representable
    210   // in the target type and are *not* defined for other inputs.
    211   // Use narrowing change operators only when there is a static guarantee that
    212   // the input value is representable in the target value.
    213   const Operator* ChangeFloat32ToFloat64();
    214   const Operator* ChangeFloat64ToInt32();   // narrowing
    215   const Operator* ChangeFloat64ToUint32();  // narrowing
    216   const Operator* TryTruncateFloat32ToInt64();
    217   const Operator* TryTruncateFloat64ToInt64();
    218   const Operator* TryTruncateFloat32ToUint64();
    219   const Operator* TryTruncateFloat64ToUint64();
    220   const Operator* ChangeInt32ToFloat64();
    221   const Operator* ChangeInt32ToInt64();
    222   const Operator* ChangeUint32ToFloat64();
    223   const Operator* ChangeUint32ToUint64();
    224 
    225   // These operators truncate or round numbers, both changing the representation
    226   // of the number and mapping multiple input values onto the same output value.
    227   const Operator* TruncateFloat64ToFloat32();
    228   const Operator* TruncateFloat64ToInt32(TruncationMode);
    229   const Operator* TruncateInt64ToInt32();
    230   const Operator* RoundInt64ToFloat32();
    231   const Operator* RoundInt64ToFloat64();
    232   const Operator* RoundUint64ToFloat32();
    233   const Operator* RoundUint64ToFloat64();
    234 
    235   // These operators reinterpret the bits of a floating point number as an
    236   // integer and vice versa.
    237   const Operator* BitcastFloat32ToInt32();
    238   const Operator* BitcastFloat64ToInt64();
    239   const Operator* BitcastInt32ToFloat32();
    240   const Operator* BitcastInt64ToFloat64();
    241 
    242   // Floating point operators always operate with IEEE 754 round-to-nearest
    243   // (single-precision).
    244   const Operator* Float32Add();
    245   const Operator* Float32Sub();
    246   const Operator* Float32Mul();
    247   const Operator* Float32Div();
    248   const Operator* Float32Sqrt();
    249 
    250   // Floating point operators always operate with IEEE 754 round-to-nearest
    251   // (double-precision).
    252   const Operator* Float64Add();
    253   const Operator* Float64Sub();
    254   const Operator* Float64Mul();
    255   const Operator* Float64Div();
    256   const Operator* Float64Mod();
    257   const Operator* Float64Sqrt();
    258 
    259   // Floating point comparisons complying to IEEE 754 (single-precision).
    260   const Operator* Float32Equal();
    261   const Operator* Float32LessThan();
    262   const Operator* Float32LessThanOrEqual();
    263 
    264   // Floating point comparisons complying to IEEE 754 (double-precision).
    265   const Operator* Float64Equal();
    266   const Operator* Float64LessThan();
    267   const Operator* Float64LessThanOrEqual();
    268 
    269   // Floating point min/max complying to IEEE 754 (single-precision).
    270   const OptionalOperator Float32Max();
    271   const OptionalOperator Float32Min();
    272 
    273   // Floating point min/max complying to IEEE 754 (double-precision).
    274   const OptionalOperator Float64Max();
    275   const OptionalOperator Float64Min();
    276 
    277   // Floating point abs complying to IEEE 754 (single-precision).
    278   const Operator* Float32Abs();
    279 
    280   // Floating point abs complying to IEEE 754 (double-precision).
    281   const Operator* Float64Abs();
    282 
    283   // Floating point rounding.
    284   const OptionalOperator Float32RoundDown();
    285   const OptionalOperator Float64RoundDown();
    286   const OptionalOperator Float32RoundUp();
    287   const OptionalOperator Float64RoundUp();
    288   const OptionalOperator Float32RoundTruncate();
    289   const OptionalOperator Float64RoundTruncate();
    290   const OptionalOperator Float64RoundTiesAway();
    291   const OptionalOperator Float32RoundTiesEven();
    292   const OptionalOperator Float64RoundTiesEven();
    293 
    294   // Floating point bit representation.
    295   const Operator* Float64ExtractLowWord32();
    296   const Operator* Float64ExtractHighWord32();
    297   const Operator* Float64InsertLowWord32();
    298   const Operator* Float64InsertHighWord32();
    299 
    300   // load [base + index]
    301   const Operator* Load(LoadRepresentation rep);
    302 
    303   // store [base + index], value
    304   const Operator* Store(StoreRepresentation rep);
    305 
    306   // Access to the machine stack.
    307   const Operator* LoadStackPointer();
    308   const Operator* LoadFramePointer();
    309 
    310   // checked-load heap, index, length
    311   const Operator* CheckedLoad(CheckedLoadRepresentation);
    312   // checked-store heap, index, length, value
    313   const Operator* CheckedStore(CheckedStoreRepresentation);
    314 
    315   // Target machine word-size assumed by this builder.
    316   bool Is32() const { return word() == MachineRepresentation::kWord32; }
    317   bool Is64() const { return word() == MachineRepresentation::kWord64; }
    318   MachineRepresentation word() const { return word_; }
    319 
    320 // Pseudo operators that translate to 32/64-bit operators depending on the
    321 // word-size of the target machine assumed by this builder.
    322 #define PSEUDO_OP_LIST(V) \
    323   V(Word, And)            \
    324   V(Word, Or)             \
    325   V(Word, Xor)            \
    326   V(Word, Shl)            \
    327   V(Word, Shr)            \
    328   V(Word, Sar)            \
    329   V(Word, Ror)            \
    330   V(Word, Equal)          \
    331   V(Int, Add)             \
    332   V(Int, Sub)             \
    333   V(Int, Mul)             \
    334   V(Int, Div)             \
    335   V(Int, Mod)             \
    336   V(Int, LessThan)        \
    337   V(Int, LessThanOrEqual) \
    338   V(Uint, Div)            \
    339   V(Uint, LessThan)       \
    340   V(Uint, Mod)
    341 #define PSEUDO_OP(Prefix, Suffix)                                \
    342   const Operator* Prefix##Suffix() {                             \
    343     return Is32() ? Prefix##32##Suffix() : Prefix##64##Suffix(); \
    344   }
    345   PSEUDO_OP_LIST(PSEUDO_OP)
    346 #undef PSEUDO_OP
    347 #undef PSEUDO_OP_LIST
    348 
    349  private:
    350   MachineOperatorGlobalCache const& cache_;
    351   MachineRepresentation const word_;
    352   Flags const flags_;
    353 
    354   DISALLOW_COPY_AND_ASSIGN(MachineOperatorBuilder);
    355 };
    356 
    357 
    358 DEFINE_OPERATORS_FOR_FLAGS(MachineOperatorBuilder::Flags)
    359 
    360 }  // namespace compiler
    361 }  // namespace internal
    362 }  // namespace v8
    363 
    364 #endif  // V8_COMPILER_MACHINE_OPERATOR_H_
    365