1 // Copyright 2014 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_MACHINE_TYPE_H_
6 #define V8_MACHINE_TYPE_H_
7 
8 #include <iosfwd>
9 
10 #include "src/base/bits.h"
11 #include "src/globals.h"
12 #include "src/signature.h"
13 #include "src/zone/zone.h"
14 
15 namespace v8 {
16 namespace internal {
17 
18 enum class MachineRepresentation : uint8_t {
19   kNone,
20   kBit,
21   kWord8,
22   kWord16,
23   kWord32,
24   kWord64,
25   kTaggedSigned,
26   kTaggedPointer,
27   kTagged,
28   // FP representations must be last, and in order of increasing size.
29   kFloat32,
30   kFloat64,
31   kSimd128,
32   kFirstFPRepresentation = kFloat32,
33   kLastRepresentation = kSimd128
34 };
35 
36 static_assert(static_cast<int>(MachineRepresentation::kLastRepresentation) <
37                   kIntSize * kBitsPerByte,
38               "Bit masks of MachineRepresentation should fit in an int");
39 
40 const char* MachineReprToString(MachineRepresentation);
41 
42 enum class MachineSemantic : uint8_t {
43   kNone,
44   kBool,
45   kInt32,
46   kUint32,
47   kInt64,
48   kUint64,
49   kNumber,
50   kAny
51 };
52 
53 class MachineType {
54  public:
MachineType()55   MachineType()
56       : representation_(MachineRepresentation::kNone),
57         semantic_(MachineSemantic::kNone) {}
MachineType(MachineRepresentation representation,MachineSemantic semantic)58   MachineType(MachineRepresentation representation, MachineSemantic semantic)
59       : representation_(representation), semantic_(semantic) {}
60 
61   bool operator==(MachineType other) const {
62     return representation() == other.representation() &&
63            semantic() == other.semantic();
64   }
65 
66   bool operator!=(MachineType other) const { return !(*this == other); }
67 
68 
representation()69   MachineRepresentation representation() const { return representation_; }
semantic()70   MachineSemantic semantic() const { return semantic_; }
71 
IsNone()72   bool IsNone() { return representation() == MachineRepresentation::kNone; }
73 
IsSigned()74   bool IsSigned() {
75     return semantic() == MachineSemantic::kInt32 ||
76            semantic() == MachineSemantic::kInt64;
77   }
IsUnsigned()78   bool IsUnsigned() {
79     return semantic() == MachineSemantic::kUint32 ||
80            semantic() == MachineSemantic::kUint64;
81   }
82 
PointerRepresentation()83   static MachineRepresentation PointerRepresentation() {
84     return (kPointerSize == 4) ? MachineRepresentation::kWord32
85                                : MachineRepresentation::kWord64;
86   }
Pointer()87   static MachineType Pointer() {
88     return MachineType(PointerRepresentation(), MachineSemantic::kNone);
89   }
IntPtr()90   static MachineType IntPtr() {
91     return (kPointerSize == 4) ? Int32() : Int64();
92   }
Float32()93   static MachineType Float32() {
94     return MachineType(MachineRepresentation::kFloat32,
95                        MachineSemantic::kNumber);
96   }
Float64()97   static MachineType Float64() {
98     return MachineType(MachineRepresentation::kFloat64,
99                        MachineSemantic::kNumber);
100   }
Simd128()101   static MachineType Simd128() {
102     return MachineType(MachineRepresentation::kSimd128, MachineSemantic::kNone);
103   }
Int8()104   static MachineType Int8() {
105     return MachineType(MachineRepresentation::kWord8, MachineSemantic::kInt32);
106   }
Uint8()107   static MachineType Uint8() {
108     return MachineType(MachineRepresentation::kWord8, MachineSemantic::kUint32);
109   }
Int16()110   static MachineType Int16() {
111     return MachineType(MachineRepresentation::kWord16, MachineSemantic::kInt32);
112   }
Uint16()113   static MachineType Uint16() {
114     return MachineType(MachineRepresentation::kWord16,
115                        MachineSemantic::kUint32);
116   }
Int32()117   static MachineType Int32() {
118     return MachineType(MachineRepresentation::kWord32, MachineSemantic::kInt32);
119   }
Uint32()120   static MachineType Uint32() {
121     return MachineType(MachineRepresentation::kWord32,
122                        MachineSemantic::kUint32);
123   }
Int64()124   static MachineType Int64() {
125     return MachineType(MachineRepresentation::kWord64, MachineSemantic::kInt64);
126   }
Uint64()127   static MachineType Uint64() {
128     return MachineType(MachineRepresentation::kWord64,
129                        MachineSemantic::kUint64);
130   }
TaggedPointer()131   static MachineType TaggedPointer() {
132     return MachineType(MachineRepresentation::kTaggedPointer,
133                        MachineSemantic::kAny);
134   }
TaggedSigned()135   static MachineType TaggedSigned() {
136     return MachineType(MachineRepresentation::kTaggedSigned,
137                        MachineSemantic::kInt32);
138   }
AnyTagged()139   static MachineType AnyTagged() {
140     return MachineType(MachineRepresentation::kTagged, MachineSemantic::kAny);
141   }
Bool()142   static MachineType Bool() {
143     return MachineType(MachineRepresentation::kBit, MachineSemantic::kBool);
144   }
TaggedBool()145   static MachineType TaggedBool() {
146     return MachineType(MachineRepresentation::kTagged, MachineSemantic::kBool);
147   }
None()148   static MachineType None() {
149     return MachineType(MachineRepresentation::kNone, MachineSemantic::kNone);
150   }
151 
152   // These naked representations should eventually go away.
RepWord8()153   static MachineType RepWord8() {
154     return MachineType(MachineRepresentation::kWord8, MachineSemantic::kNone);
155   }
RepWord16()156   static MachineType RepWord16() {
157     return MachineType(MachineRepresentation::kWord16, MachineSemantic::kNone);
158   }
RepWord32()159   static MachineType RepWord32() {
160     return MachineType(MachineRepresentation::kWord32, MachineSemantic::kNone);
161   }
RepWord64()162   static MachineType RepWord64() {
163     return MachineType(MachineRepresentation::kWord64, MachineSemantic::kNone);
164   }
RepFloat32()165   static MachineType RepFloat32() {
166     return MachineType(MachineRepresentation::kFloat32, MachineSemantic::kNone);
167   }
RepFloat64()168   static MachineType RepFloat64() {
169     return MachineType(MachineRepresentation::kFloat64, MachineSemantic::kNone);
170   }
RepSimd128()171   static MachineType RepSimd128() {
172     return MachineType(MachineRepresentation::kSimd128, MachineSemantic::kNone);
173   }
RepTagged()174   static MachineType RepTagged() {
175     return MachineType(MachineRepresentation::kTagged, MachineSemantic::kNone);
176   }
RepBit()177   static MachineType RepBit() {
178     return MachineType(MachineRepresentation::kBit, MachineSemantic::kNone);
179   }
180 
181   static MachineType TypeForRepresentation(const MachineRepresentation& rep,
182                                            bool isSigned = true) {
183     switch (rep) {
184       case MachineRepresentation::kNone:
185         return MachineType::None();
186       case MachineRepresentation::kBit:
187         return MachineType::Bool();
188       case MachineRepresentation::kWord8:
189         return isSigned ? MachineType::Int8() : MachineType::Uint8();
190       case MachineRepresentation::kWord16:
191         return isSigned ? MachineType::Int16() : MachineType::Uint16();
192       case MachineRepresentation::kWord32:
193         return isSigned ? MachineType::Int32() : MachineType::Uint32();
194       case MachineRepresentation::kWord64:
195         return isSigned ? MachineType::Int64() : MachineType::Uint64();
196       case MachineRepresentation::kFloat32:
197         return MachineType::Float32();
198       case MachineRepresentation::kFloat64:
199         return MachineType::Float64();
200       case MachineRepresentation::kSimd128:
201         return MachineType::Simd128();
202       case MachineRepresentation::kTagged:
203         return MachineType::AnyTagged();
204       case MachineRepresentation::kTaggedSigned:
205         return MachineType::TaggedSigned();
206       case MachineRepresentation::kTaggedPointer:
207         return MachineType::TaggedPointer();
208       default:
209         UNREACHABLE();
210         return MachineType::None();
211     }
212   }
213 
214  private:
215   MachineRepresentation representation_;
216   MachineSemantic semantic_;
217 };
218 
hash_value(MachineRepresentation rep)219 V8_INLINE size_t hash_value(MachineRepresentation rep) {
220   return static_cast<size_t>(rep);
221 }
222 
hash_value(MachineType type)223 V8_INLINE size_t hash_value(MachineType type) {
224   return static_cast<size_t>(type.representation()) +
225          static_cast<size_t>(type.semantic()) * 16;
226 }
227 
228 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
229                                            MachineRepresentation rep);
230 std::ostream& operator<<(std::ostream& os, MachineSemantic type);
231 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, MachineType type);
232 
IsFloatingPoint(MachineRepresentation rep)233 inline bool IsFloatingPoint(MachineRepresentation rep) {
234   return rep >= MachineRepresentation::kFirstFPRepresentation;
235 }
236 
CanBeTaggedPointer(MachineRepresentation rep)237 inline bool CanBeTaggedPointer(MachineRepresentation rep) {
238   return rep == MachineRepresentation::kTagged ||
239          rep == MachineRepresentation::kTaggedPointer;
240 }
241 
CanBeTaggedSigned(MachineRepresentation rep)242 inline bool CanBeTaggedSigned(MachineRepresentation rep) {
243   return rep == MachineRepresentation::kTagged ||
244          rep == MachineRepresentation::kTaggedSigned;
245 }
246 
IsAnyTagged(MachineRepresentation rep)247 inline bool IsAnyTagged(MachineRepresentation rep) {
248   return CanBeTaggedPointer(rep) || rep == MachineRepresentation::kTaggedSigned;
249 }
250 
251 // Gets the log2 of the element size in bytes of the machine type.
ElementSizeLog2Of(MachineRepresentation rep)252 V8_EXPORT_PRIVATE inline int ElementSizeLog2Of(MachineRepresentation rep) {
253   switch (rep) {
254     case MachineRepresentation::kBit:
255     case MachineRepresentation::kWord8:
256       return 0;
257     case MachineRepresentation::kWord16:
258       return 1;
259     case MachineRepresentation::kWord32:
260     case MachineRepresentation::kFloat32:
261       return 2;
262     case MachineRepresentation::kWord64:
263     case MachineRepresentation::kFloat64:
264       return 3;
265     case MachineRepresentation::kSimd128:
266       return 4;
267     case MachineRepresentation::kTaggedSigned:
268     case MachineRepresentation::kTaggedPointer:
269     case MachineRepresentation::kTagged:
270       return kPointerSizeLog2;
271     default:
272       break;
273   }
274   UNREACHABLE();
275   return -1;
276 }
277 
278 typedef Signature<MachineType> MachineSignature;
279 
280 }  // namespace internal
281 }  // namespace v8
282 
283 #endif  // V8_MACHINE_TYPE_H_
284