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