xref: /third_party/node/deps/v8/src/codegen/tnode.h (revision 1cb0ef41)
1// Copyright 2015 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_CODEGEN_TNODE_H_
6#define V8_CODEGEN_TNODE_H_
7
8#include "src/codegen/machine-type.h"
9
10namespace v8 {
11namespace internal {
12
13class HeapNumber;
14class BigInt;
15class Object;
16class Smi;
17class TaggedIndex;
18
19namespace compiler {
20
21class Node;
22
23}  // namespace compiler
24
25struct UntaggedT {};
26
27struct IntegralT : UntaggedT {};
28
29struct WordT : IntegralT {
30  static const MachineRepresentation kMachineRepresentation =
31      MachineType::PointerRepresentation();
32};
33
34struct RawPtrT : WordT {
35  static constexpr MachineType kMachineType = MachineType::Pointer();
36};
37
38// A RawPtrT that is guaranteed to point into the sandbox.
39struct SandboxedPtrT : WordT {
40  static constexpr MachineType kMachineType = MachineType::SandboxedPointer();
41};
42
43template <class To>
44struct RawPtr : RawPtrT {};
45
46struct Word32T : IntegralT {
47  static const MachineRepresentation kMachineRepresentation =
48      MachineRepresentation::kWord32;
49};
50struct Int32T : Word32T {
51  static constexpr MachineType kMachineType = MachineType::Int32();
52};
53struct Uint32T : Word32T {
54  static constexpr MachineType kMachineType = MachineType::Uint32();
55};
56struct Int16T : Int32T {
57  static constexpr MachineType kMachineType = MachineType::Int16();
58};
59struct Uint16T : Uint32T, Int32T {
60  static constexpr MachineType kMachineType = MachineType::Uint16();
61};
62struct Int8T : Int16T {
63  static constexpr MachineType kMachineType = MachineType::Int8();
64};
65struct Uint8T : Uint16T, Int16T {
66  static constexpr MachineType kMachineType = MachineType::Uint8();
67};
68
69struct Word64T : IntegralT {
70  static const MachineRepresentation kMachineRepresentation =
71      MachineRepresentation::kWord64;
72};
73struct Int64T : Word64T {
74  static constexpr MachineType kMachineType = MachineType::Int64();
75};
76struct Uint64T : Word64T {
77  static constexpr MachineType kMachineType = MachineType::Uint64();
78};
79
80struct IntPtrT : WordT {
81  static constexpr MachineType kMachineType = MachineType::IntPtr();
82};
83struct UintPtrT : WordT {
84  static constexpr MachineType kMachineType = MachineType::UintPtr();
85};
86
87// An index into the external pointer table.
88#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
89struct ExternalPointerT : Uint32T {
90  static constexpr MachineType kMachineType = MachineType::Uint32();
91};
92#else
93struct ExternalPointerT : UntaggedT {
94  static constexpr MachineType kMachineType = MachineType::Pointer();
95};
96#endif
97
98struct Float32T : UntaggedT {
99  static const MachineRepresentation kMachineRepresentation =
100      MachineRepresentation::kFloat32;
101  static constexpr MachineType kMachineType = MachineType::Float32();
102};
103
104struct Float64T : UntaggedT {
105  static const MachineRepresentation kMachineRepresentation =
106      MachineRepresentation::kFloat64;
107  static constexpr MachineType kMachineType = MachineType::Float64();
108};
109
110#ifdef V8_COMPRESS_POINTERS
111using TaggedT = Int32T;
112#else
113using TaggedT = IntPtrT;
114#endif
115
116// Result of a comparison operation.
117struct BoolT : Word32T {};
118
119// Value type of a Turbofan node with two results.
120template <class T1, class T2>
121struct PairT {};
122
123struct Simd128T : UntaggedT {
124  static const MachineRepresentation kMachineRepresentation =
125      MachineRepresentation::kSimd128;
126  static constexpr MachineType kMachineType = MachineType::Simd128();
127};
128
129struct I8x16T : Simd128T {};
130struct I16x8T : Simd128T {};
131struct I32x2T : Simd128T {};
132
133inline constexpr MachineType CommonMachineType(MachineType type1,
134                                               MachineType type2) {
135  return (type1 == type2) ? type1
136                          : ((type1.IsTagged() && type2.IsTagged())
137                                 ? MachineType::AnyTagged()
138                                 : MachineType::None());
139}
140
141template <class Type, class Enable = void>
142struct MachineTypeOf {
143  static constexpr MachineType value = Type::kMachineType;
144};
145
146template <class Type, class Enable>
147constexpr MachineType MachineTypeOf<Type, Enable>::value;
148
149template <>
150struct MachineTypeOf<Object> {
151  static constexpr MachineType value = MachineType::AnyTagged();
152};
153template <>
154struct MachineTypeOf<MaybeObject> {
155  static constexpr MachineType value = MachineType::AnyTagged();
156};
157template <>
158struct MachineTypeOf<Smi> {
159  static constexpr MachineType value = MachineType::TaggedSigned();
160};
161template <>
162struct MachineTypeOf<TaggedIndex> {
163  static constexpr MachineType value = MachineType::Pointer();
164};
165template <class HeapObjectSubtype>
166struct MachineTypeOf<HeapObjectSubtype,
167                     typename std::enable_if<std::is_base_of<
168                         HeapObject, HeapObjectSubtype>::value>::type> {
169  static constexpr MachineType value = MachineType::TaggedPointer();
170};
171template <>
172struct MachineTypeOf<ExternalReference> {
173  static constexpr MachineType value = MachineType::Pointer();
174};
175
176template <class HeapObjectSubtype>
177constexpr MachineType MachineTypeOf<
178    HeapObjectSubtype, typename std::enable_if<std::is_base_of<
179                           HeapObject, HeapObjectSubtype>::value>::type>::value;
180
181template <class Type, class Enable = void>
182struct MachineRepresentationOf {
183  static const MachineRepresentation value = Type::kMachineRepresentation;
184};
185// If T defines kMachineType, then we take the machine representation from
186// there.
187template <class T>
188struct MachineRepresentationOf<T, std::void_t<decltype(T::kMachineType)>> {
189  static const MachineRepresentation value = T::kMachineType.representation();
190};
191template <class T>
192struct MachineRepresentationOf<
193    T, typename std::enable_if<std::is_base_of<Object, T>::value>::type> {
194  static const MachineRepresentation value =
195      MachineTypeOf<T>::value.representation();
196};
197template <class T>
198struct MachineRepresentationOf<
199    T, typename std::enable_if<std::is_base_of<MaybeObject, T>::value>::type> {
200  static const MachineRepresentation value =
201      MachineTypeOf<T>::value.representation();
202};
203template <>
204struct MachineRepresentationOf<ExternalReference> {
205  static const MachineRepresentation value = RawPtrT::kMachineRepresentation;
206};
207
208template <typename T>
209constexpr bool IsMachineRepresentationOf(MachineRepresentation r) {
210  return MachineRepresentationOf<T>::value == r;
211}
212
213template <class T>
214constexpr MachineRepresentation PhiMachineRepresentationOf =
215    std::is_base_of<Word32T, T>::value ? MachineRepresentation::kWord32
216                                       : MachineRepresentationOf<T>::value;
217
218template <class T>
219struct is_valid_type_tag {
220  static const bool value = std::is_base_of<Object, T>::value ||
221                            std::is_base_of<UntaggedT, T>::value ||
222                            std::is_base_of<MaybeObject, T>::value ||
223                            std::is_same<ExternalReference, T>::value;
224  static const bool is_tagged = std::is_base_of<Object, T>::value ||
225                                std::is_base_of<MaybeObject, T>::value;
226};
227
228template <class T1, class T2>
229struct is_valid_type_tag<PairT<T1, T2>> {
230  static const bool value =
231      is_valid_type_tag<T1>::value && is_valid_type_tag<T2>::value;
232  static const bool is_tagged = false;
233};
234
235template <class T1, class T2>
236struct UnionT;
237
238template <class T1, class T2>
239struct is_valid_type_tag<UnionT<T1, T2>> {
240  static const bool is_tagged =
241      is_valid_type_tag<T1>::is_tagged && is_valid_type_tag<T2>::is_tagged;
242  static const bool value = is_tagged;
243};
244
245template <class T1, class T2>
246struct UnionT {
247  static constexpr MachineType kMachineType =
248      CommonMachineType(MachineTypeOf<T1>::value, MachineTypeOf<T2>::value);
249  static const MachineRepresentation kMachineRepresentation =
250      kMachineType.representation();
251  static_assert(kMachineRepresentation != MachineRepresentation::kNone,
252                "no common representation");
253  static_assert(is_valid_type_tag<T1>::is_tagged &&
254                    is_valid_type_tag<T2>::is_tagged,
255                "union types are only possible for tagged values");
256};
257
258using AnyTaggedT = UnionT<Object, MaybeObject>;
259using Number = UnionT<Smi, HeapNumber>;
260using Numeric = UnionT<Number, BigInt>;
261using ContextOrEmptyContext = UnionT<Context, Smi>;
262
263// A pointer to a builtin function, used by Torque's function pointers.
264using BuiltinPtr = Smi;
265
266template <class T, class U>
267struct is_subtype {
268  static const bool value =
269      std::disjunction<std::is_base_of<U, T>,
270                       std::conjunction<std::is_same<U, MaybeObject>,
271                                        std::is_convertible<T, Object>>>::value;
272};
273template <class T1, class T2, class U>
274struct is_subtype<UnionT<T1, T2>, U> {
275  static const bool value =
276      is_subtype<T1, U>::value && is_subtype<T2, U>::value;
277};
278template <class T, class U1, class U2>
279struct is_subtype<T, UnionT<U1, U2>> {
280  static const bool value =
281      is_subtype<T, U1>::value || is_subtype<T, U2>::value;
282};
283template <class T1, class T2, class U1, class U2>
284struct is_subtype<UnionT<T1, T2>, UnionT<U1, U2>> {
285  static const bool value =
286      (is_subtype<T1, U1>::value || is_subtype<T1, U2>::value) &&
287      (is_subtype<T2, U1>::value || is_subtype<T2, U2>::value);
288};
289template <>
290struct is_subtype<ExternalReference, RawPtrT> {
291  static const bool value = true;
292};
293
294template <class T, class U>
295struct types_have_common_values {
296  static const bool value = is_subtype<T, U>::value || is_subtype<U, T>::value;
297};
298template <class U>
299struct types_have_common_values<BoolT, U> {
300  static const bool value = types_have_common_values<Word32T, U>::value;
301};
302template <class U>
303struct types_have_common_values<Uint32T, U> {
304  static const bool value = types_have_common_values<Word32T, U>::value;
305};
306template <class U>
307struct types_have_common_values<Int32T, U> {
308  static const bool value = types_have_common_values<Word32T, U>::value;
309};
310template <class U>
311struct types_have_common_values<Uint64T, U> {
312  static const bool value = types_have_common_values<Word64T, U>::value;
313};
314template <class U>
315struct types_have_common_values<Int64T, U> {
316  static const bool value = types_have_common_values<Word64T, U>::value;
317};
318template <class U>
319struct types_have_common_values<IntPtrT, U> {
320  static const bool value = types_have_common_values<WordT, U>::value;
321};
322template <class U>
323struct types_have_common_values<UintPtrT, U> {
324  static const bool value = types_have_common_values<WordT, U>::value;
325};
326template <class T1, class T2, class U>
327struct types_have_common_values<UnionT<T1, T2>, U> {
328  static const bool value = types_have_common_values<T1, U>::value ||
329                            types_have_common_values<T2, U>::value;
330};
331
332template <class T, class U1, class U2>
333struct types_have_common_values<T, UnionT<U1, U2>> {
334  static const bool value = types_have_common_values<T, U1>::value ||
335                            types_have_common_values<T, U2>::value;
336};
337template <class T1, class T2, class U1, class U2>
338struct types_have_common_values<UnionT<T1, T2>, UnionT<U1, U2>> {
339  static const bool value = types_have_common_values<T1, U1>::value ||
340                            types_have_common_values<T1, U2>::value ||
341                            types_have_common_values<T2, U1>::value ||
342                            types_have_common_values<T2, U2>::value;
343};
344
345// TNode<T> is an SSA value with the static type tag T, which is one of the
346// following:
347//   - MaybeObject represents the type of all tagged values, including weak
348//     pointers.
349//   - a subclass of internal::Object represents a non-weak tagged type.
350//   - a subclass of internal::UntaggedT represents an untagged type
351//   - ExternalReference
352//   - PairT<T1, T2> for an operation returning two values, with types T1
353//     and T2
354//   - UnionT<T1, T2> represents either a value of type T1 or of type T2.
355template <class T>
356class TNode {
357 public:
358  template <class U,
359            typename std::enable_if<is_subtype<U, T>::value, int>::type = 0>
360  TNode(const TNode<U>& other) : node_(other) {
361    LazyTemplateChecks();
362  }
363  TNode(const TNode& other) : node_(other) { LazyTemplateChecks(); }
364  TNode() : TNode(nullptr) {}
365
366  TNode operator=(TNode other) {
367    DCHECK_NOT_NULL(other.node_);
368    node_ = other.node_;
369    return *this;
370  }
371
372  operator compiler::Node*() const { return node_; }
373
374  static TNode UncheckedCast(compiler::Node* node) { return TNode(node); }
375
376 private:
377  explicit TNode(compiler::Node* node) : node_(node) { LazyTemplateChecks(); }
378  // These checks shouldn't be checked before TNode is actually used.
379  void LazyTemplateChecks() {
380    static_assert(is_valid_type_tag<T>::value, "invalid type tag");
381  }
382
383  compiler::Node* node_;
384};
385
386}  // namespace internal
387}  // namespace v8
388
389#endif  // V8_CODEGEN_TNODE_H_
390