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:
OptionalOperator(const Operator * op)23 explicit OptionalOperator(const Operator* op) : op_(op) {}
24
IsSupported()25 bool IsSupported() const { return op_ != nullptr; }
op()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
hash_value(TruncationMode mode)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:
StoreRepresentation(MachineRepresentation representation,WriteBarrierKind write_barrier_kind)71 StoreRepresentation(MachineRepresentation representation,
72 WriteBarrierKind write_barrier_kind)
73 : representation_(representation),
74 write_barrier_kind_(write_barrier_kind) {}
75
representation()76 MachineRepresentation representation() const { return representation_; }
write_barrier_kind()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();
Word32ShiftIsSafe()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();
Int32DivIsSafe()191 bool Int32DivIsSafe() const { return flags_ & kInt32DivIsSafe; }
Uint32DivIsSafe()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.
Is32()316 bool Is32() const { return word() == MachineRepresentation::kWord32; }
Is64()317 bool Is64() const { return word() == MachineRepresentation::kWord64; }
word()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