1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5/*****************************************************************************/
6#ifndef _VARTYPE_H_
7#define _VARTYPE_H_
8/*****************************************************************************/
9#include "error.h"
10
11enum var_types_classification
12{
13 VTF_ANY = 0x0000,
14 VTF_INT = 0x0001,
15 VTF_UNS = 0x0002, // type is unsigned
16 VTF_FLT = 0x0004,
17 VTF_GCR = 0x0008, // type is GC ref
18 VTF_BYR = 0x0010, // type is Byref
19 VTF_I = 0x0020, // is machine sized
20 VTF_S = 0x0040, // is a struct type
21};
22
23enum var_types : BYTE
24{
25#define DEF_TP(tn, nm, jitType, verType, sz, sze, asze, st, al, tf, howUsed) TYP_##tn,
26#include "typelist.h"
27#undef DEF_TP
28
29 TYP_COUNT,
30
31 TYP_lastIntrins = TYP_DOUBLE
32};
33
34/*****************************************************************************
35 * C-style pointers are implemented as TYP_INT or TYP_LONG depending on the
36 * platform
37 */
38
39#ifdef _TARGET_64BIT_
40#define TYP_I_IMPL TYP_LONG
41#define TYP_U_IMPL TYP_ULONG
42#define TYPE_REF_IIM TYPE_REF_LNG
43#else
44#define TYP_I_IMPL TYP_INT
45#define TYP_U_IMPL TYP_UINT
46#define TYPE_REF_IIM TYPE_REF_INT
47#ifdef _PREFAST_
48// We silence this in the 32-bit build because for portability, we like to have asserts like this:
49// assert(op2->gtType == TYP_INT || op2->gtType == TYP_I_IMPL);
50// This is obviously redundant for 32-bit builds, but we don't want to have ifdefs and different
51// asserts just for 64-bit builds, so for now just silence the assert
52#pragma warning(disable : 6287) // warning 6287: the left and right sub-expressions are identical
53#endif //_PREFAST_
54#endif
55
56/*****************************************************************************/
57
58const extern BYTE varTypeClassification[TYP_COUNT];
59
60// make any class with a TypeGet member also have a function TypeGet() that does the same thing
61template <class T>
62inline var_types TypeGet(T* t)
63{
64 return t->TypeGet();
65}
66
67// make a TypeGet function which is the identity function for var_types
68// the point of this and the preceding template is now you can make template functions
69// that work on var_types as well as any object that exposes a TypeGet method.
70// such as all of these varTypeIs* functions
71inline var_types TypeGet(var_types v)
72{
73 return v;
74}
75
76#ifdef FEATURE_SIMD
77template <class T>
78inline bool varTypeIsSIMD(T vt)
79{
80 switch (TypeGet(vt))
81 {
82 case TYP_SIMD8:
83 case TYP_SIMD12:
84 case TYP_SIMD16:
85 case TYP_SIMD32:
86 return true;
87 default:
88 return false;
89 }
90}
91#else // FEATURE_SIMD
92
93// Always return false if FEATURE_SIMD is not enabled
94template <class T>
95inline bool varTypeIsSIMD(T vt)
96{
97 return false;
98}
99#endif // !FEATURE_SIMD
100
101template <class T>
102inline bool varTypeIsIntegral(T vt)
103{
104 return ((varTypeClassification[TypeGet(vt)] & (VTF_INT)) != 0);
105}
106
107template <class T>
108inline bool varTypeIsIntegralOrI(T vt)
109{
110 return ((varTypeClassification[TypeGet(vt)] & (VTF_INT | VTF_I)) != 0);
111}
112
113template <class T>
114inline bool varTypeIsUnsigned(T vt)
115{
116 return ((varTypeClassification[TypeGet(vt)] & (VTF_UNS)) != 0);
117}
118
119// If "vt" is an unsigned integral type, returns the corresponding signed integral type, otherwise
120// return "vt".
121inline var_types varTypeUnsignedToSigned(var_types vt)
122{
123 if (varTypeIsUnsigned(vt))
124 {
125 switch (vt)
126 {
127 case TYP_BOOL:
128 case TYP_UBYTE:
129 return TYP_BYTE;
130 case TYP_USHORT:
131 return TYP_SHORT;
132 case TYP_UINT:
133 return TYP_INT;
134 case TYP_ULONG:
135 return TYP_LONG;
136 default:
137 unreached();
138 }
139 }
140 else
141 {
142 return vt;
143 }
144}
145
146template <class T>
147inline bool varTypeIsFloating(T vt)
148{
149 return ((varTypeClassification[TypeGet(vt)] & (VTF_FLT)) != 0);
150}
151
152template <class T>
153inline bool varTypeIsArithmetic(T vt)
154{
155 return ((varTypeClassification[TypeGet(vt)] & (VTF_INT | VTF_FLT)) != 0);
156}
157
158template <class T>
159inline unsigned varTypeGCtype(T vt)
160{
161 return (unsigned)(varTypeClassification[TypeGet(vt)] & (VTF_GCR | VTF_BYR));
162}
163
164template <class T>
165inline bool varTypeIsGC(T vt)
166{
167 return (varTypeGCtype(vt) != 0);
168}
169
170template <class T>
171inline bool varTypeIsI(T vt)
172{
173 return ((varTypeClassification[TypeGet(vt)] & VTF_I) != 0);
174}
175
176template <class T>
177inline bool varTypeCanReg(T vt)
178{
179 return ((varTypeClassification[TypeGet(vt)] & (VTF_INT | VTF_I | VTF_FLT)) != 0);
180}
181
182template <class T>
183inline bool varTypeIsByte(T vt)
184{
185 return (TypeGet(vt) >= TYP_BOOL) && (TypeGet(vt) <= TYP_UBYTE);
186}
187
188template <class T>
189inline bool varTypeIsShort(T vt)
190{
191 return (TypeGet(vt) == TYP_SHORT) || (TypeGet(vt) == TYP_USHORT);
192}
193
194template <class T>
195inline bool varTypeIsSmall(T vt)
196{
197 return (TypeGet(vt) >= TYP_BOOL) && (TypeGet(vt) <= TYP_USHORT);
198}
199
200template <class T>
201inline bool varTypeIsSmallInt(T vt)
202{
203 return (TypeGet(vt) >= TYP_BYTE) && (TypeGet(vt) <= TYP_USHORT);
204}
205
206template <class T>
207inline bool varTypeIsIntOrI(T vt)
208{
209 return ((TypeGet(vt) == TYP_INT)
210#ifdef _TARGET_64BIT_
211 || (TypeGet(vt) == TYP_I_IMPL)
212#endif // _TARGET_64BIT_
213 );
214}
215
216template <class T>
217inline bool genActualTypeIsIntOrI(T vt)
218{
219 return ((TypeGet(vt) >= TYP_BOOL) && (TypeGet(vt) <= TYP_U_IMPL));
220}
221
222template <class T>
223inline bool varTypeIsLong(T vt)
224{
225 return (TypeGet(vt) >= TYP_LONG) && (TypeGet(vt) <= TYP_ULONG);
226}
227
228template <class T>
229inline bool varTypeIsMultiReg(T vt)
230{
231#ifdef _TARGET_64BIT_
232 return false;
233#else
234 return (TypeGet(vt) == TYP_LONG);
235#endif
236}
237
238template <class T>
239inline bool varTypeIsSingleReg(T vt)
240{
241 return !varTypeIsMultiReg(vt);
242}
243
244template <class T>
245inline bool varTypeIsComposite(T vt)
246{
247 return (!varTypeIsArithmetic(TypeGet(vt)) && TypeGet(vt) != TYP_VOID);
248}
249
250// Is this type promotable?
251// In general only structs are promotable.
252// However, a SIMD type, e.g. TYP_SIMD may be handled as either a struct, OR a
253// fully-promoted register type.
254// On 32-bit systems longs are split into an upper and lower half, and they are
255// handled as if they are structs with two integer fields.
256
257template <class T>
258inline bool varTypeIsPromotable(T vt)
259{
260 return (varTypeIsStruct(vt) || (TypeGet(vt) == TYP_BLK)
261#if !defined(_TARGET_64BIT_)
262 || varTypeIsLong(vt)
263#endif // !defined(_TARGET_64BIT_)
264 );
265}
266
267template <class T>
268inline bool varTypeIsStruct(T vt)
269{
270 return ((varTypeClassification[TypeGet(vt)] & VTF_S) != 0);
271}
272
273template <class T>
274inline bool varTypeIsEnregisterableStruct(T vt)
275{
276 return (TypeGet(vt) != TYP_STRUCT);
277}
278
279/*****************************************************************************/
280#endif // _VARTYPE_H_
281/*****************************************************************************/
282