v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
representations.h
Go to the documentation of this file.
1// Copyright 2022 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_TURBOSHAFT_REPRESENTATIONS_H_
6#define V8_COMPILER_TURBOSHAFT_REPRESENTATIONS_H_
7
8#include <cstdint>
9
10#include "include/v8-internal.h"
11#include "src/base/hashing.h"
12#include "src/base/logging.h"
15
17
18class WordRepresentation;
19class FloatRepresentation;
20
21// Optional register representation.
23 public:
24 enum class Enum : uint8_t {
25 kWord32,
26 kWord64,
29 kTagged,
33 kNone, // No register representation.
34 };
35
36 explicit constexpr MaybeRegisterRepresentation(Enum value) : value_(value) {}
38
39 constexpr bool is_valid() const { return value_ != kInvalid; }
40
41 constexpr Enum value() const {
43 return value_;
44 }
45
46 constexpr operator Enum() const { return value(); }
47
51
55
57 if constexpr (kSystemPointerSize == 4) {
58 return Word32();
59 } else {
61 return Word64();
62 }
63 }
64
68
72
76
80
84
88
92
93 constexpr bool IsWord() const {
94 switch (*this) {
95 case Enum::kWord32:
96 case Enum::kWord64:
97 return true;
98 case Enum::kFloat32:
99 case Enum::kFloat64:
100 case Enum::kTagged:
102 case Enum::kSimd128:
103 case Enum::kSimd256:
104 case Enum::kNone:
105 return false;
106 }
107 }
108
109 constexpr bool IsFloat() const {
110 switch (*this) {
111 case Enum::kFloat32:
112 case Enum::kFloat64:
113 return true;
114 case Enum::kWord32:
115 case Enum::kWord64:
116 case Enum::kTagged:
118 case Enum::kSimd128:
119 case Enum::kSimd256:
120 case Enum::kNone:
121 return false;
122 }
123 }
124
125 constexpr bool IsTaggedOrCompressed() const {
126 switch (*this) {
127 case Enum::kTagged:
129 return true;
130 case Enum::kWord32:
131 case Enum::kWord64:
132 case Enum::kFloat32:
133 case Enum::kFloat64:
134 case Enum::kSimd128:
135 case Enum::kSimd256:
136 case Enum::kNone:
137 return false;
138 }
139 }
140
141 uint64_t MaxUnsignedValue() const {
142 switch (this->value()) {
143 case Word32():
144 return std::numeric_limits<uint32_t>::max();
145 case Word64():
146 return std::numeric_limits<uint64_t>::max();
147 case Enum::kFloat32:
148 case Enum::kFloat64:
149 case Enum::kTagged:
151 case Enum::kSimd128:
152 case Enum::kSimd256:
153 case Enum::kNone:
154 UNREACHABLE();
155 }
156 }
157
159 switch (this->value()) {
160 case Word32():
162 case Word64():
164 case Float32():
166 case Float64():
168 case Tagged():
170 case Compressed():
172 case Simd128():
174 case Simd256():
176 case None():
177 UNREACHABLE();
178 }
179 }
180
181 constexpr uint16_t bit_width() const {
182 switch (this->value()) {
183 case Word32():
184 return 32;
185 case Word64():
186 return 64;
187 case Float32():
188 return 32;
189 case Float64():
190 return 64;
191 case Tagged():
192 return kSystemPointerSize;
193 case Compressed():
194 return kSystemPointerSize;
195 case Simd128():
196 return 128;
197 case Simd256():
198 return 256;
199 case None():
200 UNREACHABLE();
201 }
202 }
203
204 private:
206
207 static constexpr Enum kInvalid = static_cast<Enum>(-1);
208};
209
211 public:
223
224 explicit constexpr RegisterRepresentation(Enum value)
226 static_cast<MaybeRegisterRepresentation::Enum>(value)) {}
228
230 : RegisterRepresentation(static_cast<Enum>(rep.value())) {}
231
232 constexpr operator Enum() const { return value(); }
233
234 constexpr Enum value() const {
235 return static_cast<Enum>(MaybeRegisterRepresentation::value());
236 }
237
238 static constexpr RegisterRepresentation Word32() {
240 }
241 static constexpr RegisterRepresentation Word64() {
243 }
244 // The equivalent of intptr_t/uintptr_t: An integral type with the same size
245 // as machine pointers.
255 // A tagged pointer stored in a register, in the case of pointer compression
256 // it is an uncompressed pointer or a Smi.
257 static constexpr RegisterRepresentation Tagged() {
259 }
260 // A compressed tagged pointer stored in a register, the upper 32bit are
261 // unspecified.
271
274 switch (rep) {
279 return Word32();
281 return Word64();
286 return Tagged();
289 return Compressed();
292 return Float32();
294 return Float64();
296 return Simd128();
298 return Simd256();
300 // Turboshaft does not support map packing.
305 // TODO(saelo/jkummerow): This is suspicious: after resolving the
306 // indirection, we have a Tagged pointer.
307 return WordPtr();
310 UNREACHABLE();
311 }
312 }
313
315 return FromMachineRepresentation(type.representation());
316 }
317
320 if (t.GetType() == CTypeInfo::Type::kVoid ||
321 t.GetType() == CTypeInfo::Type::kPointer) {
323 } else if (t.GetType() == CTypeInfo::Type::kInt64 ||
324 t.GetType() == CTypeInfo::Type::kUint64) {
327 } else {
330 }
331 } else {
334 }
335 }
336
338 RegisterRepresentation dst_rep, bool graph_created_from_turbofan) const;
339
341 if (this->value() == RegisterRepresentation::Tagged()) {
344 }
345 return *this;
346 }
347};
348
351 return a.value() == b.value();
352}
355 return a.value() != b.value();
356}
357
359 return static_cast<size_t>(rep.value());
360}
361
363 RegisterRepresentation dst_rep, bool graph_created_from_turbofan) const {
364 if (*this == dst_rep) {
365 return true;
366 }
367 switch (dst_rep.value()) {
369 // We allow implicit tagged -> untagged conversions.
370 // Even without pointer compression, we use `Word32And` for Smi-checks on
371 // tagged values.
374 return true;
375 }
376 if (graph_created_from_turbofan &&
378 // TODO(12783): Remove this once Turboshaft graphs are not constructed
379 // via Turbofan any more. Unfortunately Turbofan has many implicit
380 // truncations which are hard to fix. Still, for wasm it is required
381 // that truncations in Turboshaft are explicit.
382 return true;
383 }
384 break;
386 // We allow implicit tagged -> untagged conversions.
387 if (kTaggedSize == kInt64Size &&
389 return true;
390 }
391 break;
393 // We allow implicit untagged -> tagged conversions. This is only safe for
394 // Smi values.
395 if (*this == RegisterRepresentation::WordPtr()) {
396 return true;
397 }
398 break;
400 // Compression is a no-op.
404 return true;
405 }
406 break;
407 default:
408 break;
409 }
410 return false;
411}
412
413V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
415
416template <typename T>
418 T, std::enable_if_t<std::is_base_of_v<MaybeRegisterRepresentation, T>>> {
419 static constexpr uint64_t max_value = 8;
420 static constexpr uint64_t encode(T rep) {
421 const uint64_t value = static_cast<uint64_t>(rep.value());
422 DCHECK_LT(value, max_value);
423 return value;
424 }
425};
426
428 public:
429 enum class Enum : uint8_t {
432 };
433 explicit constexpr WordRepresentation(Enum value)
435 static_cast<RegisterRepresentation::Enum>(value)) {}
438 : WordRepresentation(static_cast<Enum>(rep.value())) {
439 DCHECK(rep.IsWord());
440 }
441
442 static constexpr WordRepresentation Word32() {
444 }
445 static constexpr WordRepresentation Word64() {
447 }
448
452
453 constexpr Enum value() const {
454 return static_cast<Enum>(RegisterRepresentation::value());
455 }
456 constexpr operator Enum() const { return value(); }
457
458 constexpr uint64_t MaxUnsignedValue() const {
459 switch (this->value()) {
460 case Word32():
461 return std::numeric_limits<uint32_t>::max();
462 case Word64():
463 return std::numeric_limits<uint64_t>::max();
464 }
465 }
466 constexpr int64_t MinSignedValue() const {
467 switch (this->value()) {
468 case Word32():
469 return std::numeric_limits<int32_t>::min();
470 case Word64():
471 return std::numeric_limits<int64_t>::min();
472 }
473 }
474 constexpr int64_t MaxSignedValue() const {
475 switch (this->value()) {
476 case Word32():
477 return std::numeric_limits<int32_t>::max();
478 case Word64():
479 return std::numeric_limits<int64_t>::max();
480 }
481 }
482};
483
485 public:
486 enum class Enum : uint8_t {
489 };
490
491 static constexpr FloatRepresentation Float32() {
493 }
494 static constexpr FloatRepresentation Float64() {
496 }
497
498 explicit constexpr FloatRepresentation(Enum value)
500 static_cast<RegisterRepresentation::Enum>(value)) {}
502 : FloatRepresentation(static_cast<Enum>(rep.value())) {
503 DCHECK(rep.IsFloat());
504 }
506
507 constexpr Enum value() const {
508 return static_cast<Enum>(RegisterRepresentation::value());
509 }
510 constexpr operator Enum() const { return value(); }
511};
512
514 public:
539
540 explicit constexpr MemoryRepresentation(Enum value) : value_(value) {}
542
543 constexpr bool is_valid() const { return value_ != kInvalid; }
544
545 constexpr Enum value() const {
546 DCHECK(is_valid());
547 return value_;
548 }
549 constexpr operator Enum() const { return value(); }
550
551 static constexpr MemoryRepresentation Int8() {
553 }
554 static constexpr MemoryRepresentation Uint8() {
556 }
557 static constexpr MemoryRepresentation Int16() {
559 }
560 static constexpr MemoryRepresentation Uint16() {
562 }
563 static constexpr MemoryRepresentation Int32() {
565 }
566 static constexpr MemoryRepresentation Uint32() {
568 }
569 static constexpr MemoryRepresentation Int64() {
571 }
572 static constexpr MemoryRepresentation Uint64() {
574 }
575 static constexpr MemoryRepresentation UintPtr() {
576 if constexpr (Is64()) {
577 return Uint64();
578 } else {
579 return Uint32();
580 }
581 }
582 static constexpr MemoryRepresentation Float16() {
584 }
585 static constexpr MemoryRepresentation Float32() {
587 }
588 static constexpr MemoryRepresentation Float64() {
590 }
618 static constexpr MemoryRepresentation Simd128() {
620 }
621 static constexpr MemoryRepresentation Simd256() {
623 }
624
625 bool IsSigned() const {
626 switch (*this) {
627 case Int8():
628 case Int16():
629 case Int32():
630 case Int64():
631 return true;
632 case Uint8():
633 case Uint16():
634 case Uint32():
635 case Uint64():
636 return false;
637 case Float16():
638 case Float32():
639 case Float64():
640 case AnyTagged():
641 case TaggedPointer():
642 case TaggedSigned():
646 case ProtectedPointer():
647 case IndirectPointer():
648 case SandboxedPointer():
649 case Simd128():
650 case Simd256():
651 UNREACHABLE();
652 }
653 }
654
655 // This predicate is used in particular to decide which load/store ops
656 // have to deal with pointer compression. Indirect/sandboxed pointers,
657 // while they resolve to tagged pointers, return {false} because they
658 // use incompatible compression schemes.
659 bool IsCompressibleTagged() const {
660 switch (*this) {
661 case AnyTagged():
662 case TaggedPointer():
663 case TaggedSigned():
664 return true;
665 case Int8():
666 case Int16():
667 case Int32():
668 case Int64():
669 case Uint8():
670 case Uint16():
671 case Uint32():
672 case Uint64():
673 case Float16():
674 case Float32():
675 case Float64():
679 case IndirectPointer():
680 case ProtectedPointer():
681 case SandboxedPointer():
682 case Simd128():
683 case Simd256():
684 return false;
685 }
686 }
687
689 switch (*this) {
690 case Int8():
691 case Uint8():
692 case Int16():
693 case Uint16():
694 case Int32():
695 case Uint32():
697 case Int64():
698 case Uint64():
700 case Float16():
701 case Float32():
703 case Float64():
705 case AnyTagged():
706 case TaggedPointer():
707 case TaggedSigned():
711 case IndirectPointer():
712 case ProtectedPointer():
714 case SandboxedPointer():
716 case Simd128():
718 case Simd256():
720 }
721 }
722
725 switch (repr.value()) {
727 return is_signed ? Int32() : Uint32();
729 return is_signed ? Int64() : Uint64();
731 return Float32();
733 return Float64();
735 return AnyTagged();
737 return Simd128();
739 return Simd256();
741 UNREACHABLE();
742 }
743 }
744
745 // The required register representation for storing a value. When pointer
746 // compression is enabled, we only store the lower 32bit of a tagged value,
747 // which we indicate as `RegisterRepresentation::Compressed()` here.
757
759 switch (*this) {
760 case Int8():
761 return MachineType::Int8();
762 case Uint8():
763 return MachineType::Uint8();
764 case Int16():
765 return MachineType::Int16();
766 case Uint16():
767 return MachineType::Uint16();
768 case Int32():
769 return MachineType::Int32();
770 case Uint32():
771 return MachineType::Uint32();
772 case Int64():
773 return MachineType::Int64();
774 case Uint64():
775 return MachineType::Uint64();
776 case Float16():
777 return MachineType::Float16();
778 case Float32():
779 return MachineType::Float32();
780 case Float64():
781 return MachineType::Float64();
782 case AnyTagged():
783 return MachineType::AnyTagged();
784 case TaggedPointer():
786 case TaggedSigned():
789 return MachineType::AnyTagged();
794 case ProtectedPointer():
796 case IndirectPointer():
798 case SandboxedPointer():
800 case Simd128():
801 return MachineType::Simd128();
802 case Simd256():
803 return MachineType::Simd256();
804 }
805 }
806
808 switch (type.representation()) {
810 return type.IsSigned() ? Int8() : Uint8();
812 return type.IsSigned() ? Int16() : Uint16();
814 return type.IsSigned() ? Int32() : Uint32();
816 return type.IsSigned() ? Int64() : Uint64();
818 return TaggedSigned();
820 return TaggedPointer();
822 // Turboshaft does not support map packing.
824 return TaggedPointer();
826 return ProtectedPointer();
828 return IndirectPointer();
830 return AnyTagged();
832 return Float16();
834 return Float32();
836 return Float64();
838 return SandboxedPointer();
840 return Simd128();
842 return Simd256();
848 UNREACHABLE();
849 }
850 }
851
892
893 constexpr uint8_t SizeInBytes() const {
894 return uint8_t{1} << SizeInBytesLog2();
895 }
896
897 constexpr uint8_t SizeInBytesLog2() const {
898 switch (*this) {
899 case Int8():
900 case Uint8():
901 return 0;
902 case Int16():
903 case Uint16():
904 case Float16():
905 return 1;
906 case Int32():
907 case Uint32():
908 case Float32():
909 case IndirectPointer():
910 return 2;
911 case Int64():
912 case Uint64():
913 case Float64():
914 case SandboxedPointer():
915 return 3;
916 case AnyTagged():
917 case TaggedPointer():
918 case TaggedSigned():
919 case ProtectedPointer():
920 return kTaggedSizeLog2;
925 case Simd128():
926 return 4;
927 case Simd256():
928 return 5;
929 }
930 }
931
932 private:
934
935 static constexpr Enum kInvalid = static_cast<Enum>(-1);
936};
937
940 return a.value() == b.value();
941}
944 return a.value() != b.value();
945}
946
948 return static_cast<size_t>(rep.value());
949}
950
951V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
953
954} // namespace v8::internal::compiler::turboshaft
955
956#endif // V8_COMPILER_TURBOSHAFT_REPRESENTATIONS_H_
static constexpr MachineType Simd256()
static constexpr MachineType Float16()
static constexpr MachineType Float64()
static constexpr MachineType Uint8()
static constexpr MachineType Int32()
static constexpr MachineType Simd128()
static constexpr MachineType AnyTagged()
static constexpr MachineType Uint64()
static constexpr MachineType Uint32()
static MachineType TypeForCType(const CTypeInfo &type)
static constexpr MachineType SandboxedPointer()
static constexpr MachineType TaggedSigned()
static constexpr MachineType IndirectPointer()
static constexpr MachineType Uint16()
static constexpr MachineType Int16()
static constexpr MachineType Float32()
static constexpr MachineType Int64()
static constexpr MachineType TaggedPointer()
static constexpr MachineType ProtectedPointer()
static constexpr MachineType Int8()
constexpr FloatRepresentation(RegisterRepresentation rep)
static constexpr FloatRepresentation Float32()
static constexpr FloatRepresentation Float64()
static constexpr MaybeRegisterRepresentation WordPtr()
static constexpr MaybeRegisterRepresentation Float64()
static constexpr MaybeRegisterRepresentation None()
static constexpr MaybeRegisterRepresentation Compressed()
static constexpr MaybeRegisterRepresentation Word64()
static constexpr MaybeRegisterRepresentation Float32()
static constexpr MaybeRegisterRepresentation Tagged()
static constexpr MaybeRegisterRepresentation Word32()
static constexpr MaybeRegisterRepresentation Simd128()
static constexpr MaybeRegisterRepresentation Simd256()
static constexpr MemoryRepresentation FromMachineRepresentation(MachineRepresentation rep)
static MemoryRepresentation FromMachineType(MachineType type)
static constexpr MemoryRepresentation AnyTagged()
static MemoryRepresentation FromRegisterRepresentation(RegisterRepresentation repr, bool is_signed)
static constexpr MemoryRepresentation Float16()
static constexpr MemoryRepresentation AnyUncompressedTagged()
static constexpr MemoryRepresentation UncompressedTaggedPointer()
static constexpr MemoryRepresentation Uint32()
static constexpr MemoryRepresentation TaggedSigned()
RegisterRepresentation ToRegisterRepresentationForStore() const
static constexpr MemoryRepresentation Int32()
static constexpr MemoryRepresentation Int64()
static constexpr MemoryRepresentation Simd128()
static constexpr MemoryRepresentation SandboxedPointer()
static constexpr MemoryRepresentation Uint16()
static constexpr MemoryRepresentation ProtectedPointer()
static constexpr MemoryRepresentation TaggedPointer()
static constexpr MemoryRepresentation UintPtr()
static constexpr MemoryRepresentation Uint8()
static constexpr MemoryRepresentation Simd256()
static constexpr MemoryRepresentation Int16()
static constexpr MemoryRepresentation IndirectPointer()
static constexpr MemoryRepresentation Uint64()
static constexpr MemoryRepresentation Float32()
static constexpr MemoryRepresentation UncompressedTaggedSigned()
static constexpr MemoryRepresentation Float64()
static constexpr RegisterRepresentation FromMachineType(MachineType type)
static constexpr RegisterRepresentation Compressed()
static constexpr RegisterRepresentation FromMachineRepresentation(MachineRepresentation rep)
static constexpr RegisterRepresentation Simd128()
static constexpr RegisterRepresentation Word32()
static constexpr RegisterRepresentation Float64()
constexpr RegisterRepresentation MapTaggedToWord() const
static constexpr RegisterRepresentation WordPtr()
static constexpr RegisterRepresentation Float32()
static constexpr RegisterRepresentation FromCTypeInfo(CTypeInfo t, CFunctionInfo::Int64Representation int64_repr)
static constexpr RegisterRepresentation Simd256()
constexpr bool AllowImplicitRepresentationChangeTo(RegisterRepresentation dst_rep, bool graph_created_from_turbofan) const
static constexpr RegisterRepresentation Word64()
constexpr RegisterRepresentation(MaybeRegisterRepresentation rep)
static constexpr RegisterRepresentation Tagged()
constexpr WordRepresentation(RegisterRepresentation rep)
static constexpr WordRepresentation WordPtr()
#define V8_MAP_PACKING_BOOL
Definition globals.h:93
#define COMPRESS_POINTERS_BOOL
Definition globals.h:99
ZoneVector< RpoNumber > & result
STL namespace.
std::ostream & operator<<(std::ostream &os, PaddingSpace padding)
bool operator==(const ControlState &lhs, const ControlState &rhs)
any_of(const Args &...) -> any_of< Args... >
V8_INLINE size_t hash_value(OpIndex op)
Definition index.h:773
bool operator!=(const ControlState &lhs, const ControlState &rhs)
constexpr int kTaggedSize
Definition globals.h:542
constexpr int kInt64Size
Definition globals.h:402
constexpr int kSystemPointerSizeLog2
Definition globals.h:494
constexpr int kSystemPointerSize
Definition globals.h:410
constexpr int kTaggedSizeLog2
Definition globals.h:543
return value
Definition map-inl.h:893
constexpr bool Is64()
bool is_signed(Condition cond)
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define V8_EXPORT_PRIVATE
Definition macros.h:460
#define V8_INLINE
Definition v8config.h:500