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