• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
10 namespace v8 {
11 namespace internal {
12 
13 class HeapNumber;
14 class BigInt;
15 class Object;
16 class Smi;
17 class TaggedIndex;
18 
19 namespace compiler {
20 
21 class Node;
22 
23 }  // namespace compiler
24 
25 struct UntaggedT {};
26 
27 struct IntegralT : UntaggedT {};
28 
29 struct WordT : IntegralT {
30   static const MachineRepresentation kMachineRepresentation =
31       MachineType::PointerRepresentation();
32 };
33 
34 struct RawPtrT : WordT {
35   static constexpr MachineType kMachineType = MachineType::Pointer();
36 };
37 
38 // A RawPtrT that is guaranteed to point into the sandbox.
39 struct SandboxedPtrT : WordT {
40   static constexpr MachineType kMachineType = MachineType::SandboxedPointer();
41 };
42 
43 template <class To>
44 struct RawPtr : RawPtrT {};
45 
46 struct Word32T : IntegralT {
47   static const MachineRepresentation kMachineRepresentation =
48       MachineRepresentation::kWord32;
49 };
50 struct Int32T : Word32T {
51   static constexpr MachineType kMachineType = MachineType::Int32();
52 };
53 struct Uint32T : Word32T {
54   static constexpr MachineType kMachineType = MachineType::Uint32();
55 };
56 struct Int16T : Int32T {
57   static constexpr MachineType kMachineType = MachineType::Int16();
58 };
59 struct Uint16T : Uint32T, Int32T {
60   static constexpr MachineType kMachineType = MachineType::Uint16();
61 };
62 struct Int8T : Int16T {
63   static constexpr MachineType kMachineType = MachineType::Int8();
64 };
65 struct Uint8T : Uint16T, Int16T {
66   static constexpr MachineType kMachineType = MachineType::Uint8();
67 };
68 
69 struct Word64T : IntegralT {
70   static const MachineRepresentation kMachineRepresentation =
71       MachineRepresentation::kWord64;
72 };
73 struct Int64T : Word64T {
74   static constexpr MachineType kMachineType = MachineType::Int64();
75 };
76 struct Uint64T : Word64T {
77   static constexpr MachineType kMachineType = MachineType::Uint64();
78 };
79 
80 struct IntPtrT : WordT {
81   static constexpr MachineType kMachineType = MachineType::IntPtr();
82 };
83 struct 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
89 struct ExternalPointerT : Uint32T {
90   static constexpr MachineType kMachineType = MachineType::Uint32();
91 };
92 #else
93 struct ExternalPointerT : UntaggedT {
94   static constexpr MachineType kMachineType = MachineType::Pointer();
95 };
96 #endif
97 
98 struct Float32T : UntaggedT {
99   static const MachineRepresentation kMachineRepresentation =
100       MachineRepresentation::kFloat32;
101   static constexpr MachineType kMachineType = MachineType::Float32();
102 };
103 
104 struct Float64T : UntaggedT {
105   static const MachineRepresentation kMachineRepresentation =
106       MachineRepresentation::kFloat64;
107   static constexpr MachineType kMachineType = MachineType::Float64();
108 };
109 
110 #ifdef V8_COMPRESS_POINTERS
111 using TaggedT = Int32T;
112 #else
113 using TaggedT = IntPtrT;
114 #endif
115 
116 // Result of a comparison operation.
117 struct BoolT : Word32T {};
118 
119 // Value type of a Turbofan node with two results.
120 template <class T1, class T2>
121 struct PairT {};
122 
123 struct Simd128T : UntaggedT {
124   static const MachineRepresentation kMachineRepresentation =
125       MachineRepresentation::kSimd128;
126   static constexpr MachineType kMachineType = MachineType::Simd128();
127 };
128 
129 struct I8x16T : Simd128T {};
130 struct I16x8T : Simd128T {};
131 struct I32x2T : Simd128T {};
132 
CommonMachineType(MachineType type1,MachineType type2)133 inline 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 
141 template <class Type, class Enable = void>
142 struct MachineTypeOf {
143   static constexpr MachineType value = Type::kMachineType;
144 };
145 
146 template <class Type, class Enable>
147 constexpr MachineType MachineTypeOf<Type, Enable>::value;
148 
149 template <>
150 struct MachineTypeOf<Object> {
151   static constexpr MachineType value = MachineType::AnyTagged();
152 };
153 template <>
154 struct MachineTypeOf<MaybeObject> {
155   static constexpr MachineType value = MachineType::AnyTagged();
156 };
157 template <>
158 struct MachineTypeOf<Smi> {
159   static constexpr MachineType value = MachineType::TaggedSigned();
160 };
161 template <>
162 struct MachineTypeOf<TaggedIndex> {
163   static constexpr MachineType value = MachineType::Pointer();
164 };
165 template <class HeapObjectSubtype>
166 struct MachineTypeOf<HeapObjectSubtype,
167                      typename std::enable_if<std::is_base_of<
168                          HeapObject, HeapObjectSubtype>::value>::type> {
169   static constexpr MachineType value = MachineType::TaggedPointer();
170 };
171 template <>
172 struct MachineTypeOf<ExternalReference> {
173   static constexpr MachineType value = MachineType::Pointer();
174 };
175 
176 template <class HeapObjectSubtype>
177 constexpr MachineType MachineTypeOf<
178     HeapObjectSubtype, typename std::enable_if<std::is_base_of<
179                            HeapObject, HeapObjectSubtype>::value>::type>::value;
180 
181 template <class Type, class Enable = void>
182 struct MachineRepresentationOf {
183   static const MachineRepresentation value = Type::kMachineRepresentation;
184 };
185 // If T defines kMachineType, then we take the machine representation from
186 // there.
187 template <class T>
188 struct MachineRepresentationOf<T, std::void_t<decltype(T::kMachineType)>> {
189   static const MachineRepresentation value = T::kMachineType.representation();
190 };
191 template <class T>
192 struct 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 };
197 template <class T>
198 struct 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 };
203 template <>
204 struct MachineRepresentationOf<ExternalReference> {
205   static const MachineRepresentation value = RawPtrT::kMachineRepresentation;
206 };
207 
208 template <typename T>
209 constexpr bool IsMachineRepresentationOf(MachineRepresentation r) {
210   return MachineRepresentationOf<T>::value == r;
211 }
212 
213 template <class T>
214 constexpr MachineRepresentation PhiMachineRepresentationOf =
215     std::is_base_of<Word32T, T>::value ? MachineRepresentation::kWord32
216                                        : MachineRepresentationOf<T>::value;
217 
218 template <class T>
219 struct 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 
228 template <class T1, class T2>
229 struct 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 
235 template <class T1, class T2>
236 struct UnionT;
237 
238 template <class T1, class T2>
239 struct 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 
245 template <class T1, class T2>
246 struct 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 
258 using AnyTaggedT = UnionT<Object, MaybeObject>;
259 using Number = UnionT<Smi, HeapNumber>;
260 using Numeric = UnionT<Number, BigInt>;
261 using ContextOrEmptyContext = UnionT<Context, Smi>;
262 
263 // A pointer to a builtin function, used by Torque's function pointers.
264 using BuiltinPtr = Smi;
265 
266 template <class T, class U>
267 struct 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 };
273 template <class T1, class T2, class U>
274 struct is_subtype<UnionT<T1, T2>, U> {
275   static const bool value =
276       is_subtype<T1, U>::value && is_subtype<T2, U>::value;
277 };
278 template <class T, class U1, class U2>
279 struct is_subtype<T, UnionT<U1, U2>> {
280   static const bool value =
281       is_subtype<T, U1>::value || is_subtype<T, U2>::value;
282 };
283 template <class T1, class T2, class U1, class U2>
284 struct 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 };
289 template <>
290 struct is_subtype<ExternalReference, RawPtrT> {
291   static const bool value = true;
292 };
293 
294 template <class T, class U>
295 struct types_have_common_values {
296   static const bool value = is_subtype<T, U>::value || is_subtype<U, T>::value;
297 };
298 template <class U>
299 struct types_have_common_values<BoolT, U> {
300   static const bool value = types_have_common_values<Word32T, U>::value;
301 };
302 template <class U>
303 struct types_have_common_values<Uint32T, U> {
304   static const bool value = types_have_common_values<Word32T, U>::value;
305 };
306 template <class U>
307 struct types_have_common_values<Int32T, U> {
308   static const bool value = types_have_common_values<Word32T, U>::value;
309 };
310 template <class U>
311 struct types_have_common_values<Uint64T, U> {
312   static const bool value = types_have_common_values<Word64T, U>::value;
313 };
314 template <class U>
315 struct types_have_common_values<Int64T, U> {
316   static const bool value = types_have_common_values<Word64T, U>::value;
317 };
318 template <class U>
319 struct types_have_common_values<IntPtrT, U> {
320   static const bool value = types_have_common_values<WordT, U>::value;
321 };
322 template <class U>
323 struct types_have_common_values<UintPtrT, U> {
324   static const bool value = types_have_common_values<WordT, U>::value;
325 };
326 template <class T1, class T2, class U>
327 struct 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 
332 template <class T, class U1, class U2>
333 struct 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 };
337 template <class T1, class T2, class U1, class U2>
338 struct 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.
355 template <class T>
356 class 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