summaryrefslogtreecommitdiff
path: root/src/jit/vartype.h
blob: 550aeb9c5b799e43cfd1f5aca453b8736008b404 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

/*****************************************************************************/
#ifndef _VARTYPE_H_
#define _VARTYPE_H_
/*****************************************************************************/
#include "error.h"

enum var_types_classification
{
    VTF_ANY = 0x0000,
    VTF_INT = 0x0001,
    VTF_UNS = 0x0002, // type is unsigned
    VTF_FLT = 0x0004,
    VTF_GCR = 0x0008, // type is GC ref
    VTF_BYR = 0x0010, // type is Byref
    VTF_I   = 0x0020, // is machine sized
    VTF_S   = 0x0040, // is a struct type
};

DECLARE_TYPED_ENUM(var_types, BYTE)
{
#define DEF_TP(tn, nm, jitType, verType, sz, sze, asze, st, al, tf, howUsed) TYP_##tn,
#include "typelist.h"
#undef DEF_TP

    TYP_COUNT,

        TYP_lastIntrins = TYP_DOUBLE
}
END_DECLARE_TYPED_ENUM(var_types, BYTE)

/*****************************************************************************
 * C-style pointers are implemented as TYP_INT or TYP_LONG depending on the
 * platform
 */

#ifdef _TARGET_64BIT_
#define TYP_I_IMPL TYP_LONG
#define TYP_U_IMPL TYP_ULONG
#define TYPE_REF_IIM TYPE_REF_LNG
#else
#define TYP_I_IMPL TYP_INT
#define TYP_U_IMPL TYP_UINT
#define TYPE_REF_IIM TYPE_REF_INT
#ifdef _PREFAST_
// We silence this in the 32-bit build because for portability, we like to have asserts like this:
// assert(op2->gtType == TYP_INT || op2->gtType == TYP_I_IMPL);
// This is obviously redundant for 32-bit builds, but we don't want to have ifdefs and different
// asserts just for 64-bit builds, so for now just silence the assert
#pragma warning(disable : 6287) // warning 6287: the left and right sub-expressions are identical
#endif                          //_PREFAST_
#endif

/*****************************************************************************/

const extern BYTE varTypeClassification[TYP_COUNT];

// make any class with a TypeGet member also have a function TypeGet() that does the same thing
template <class T>
inline var_types TypeGet(T* t)
{
    return t->TypeGet();
}

// make a TypeGet function which is the identity function for var_types
// the point of this and the preceding template is now you can make template functions
// that work on var_types as well as any object that exposes a TypeGet method.
// such as all of these varTypeIs* functions
inline var_types TypeGet(var_types v)
{
    return v;
}

#ifdef FEATURE_SIMD
template <class T>
inline bool varTypeIsSIMD(T vt)
{
    switch (TypeGet(vt))
    {
        case TYP_SIMD8:
        case TYP_SIMD12:
        case TYP_SIMD16:
#ifdef FEATURE_AVX_SUPPORT
        case TYP_SIMD32:
#endif // FEATURE_AVX_SUPPORT
            return true;
        default:
            return false;
    }
}
#else  // FEATURE_SIMD

// Always return false if FEATURE_SIMD is not enabled
template <class T>
inline bool varTypeIsSIMD(T vt)
{
    return false;
}
#endif // !FEATURE_SIMD

template <class T>
inline bool varTypeIsIntegral(T vt)
{
    return ((varTypeClassification[TypeGet(vt)] & (VTF_INT)) != 0);
}

template <class T>
inline bool varTypeIsIntegralOrI(T vt)
{
    return ((varTypeClassification[TypeGet(vt)] & (VTF_INT | VTF_I)) != 0);
}

template <class T>
inline bool varTypeIsUnsigned(T vt)
{
    return ((varTypeClassification[TypeGet(vt)] & (VTF_UNS)) != 0);
}

// If "vt" is an unsigned integral type, returns the corresponding signed integral type, otherwise
// return "vt".
inline var_types varTypeUnsignedToSigned(var_types vt)
{
    if (varTypeIsUnsigned(vt))
    {
        switch (vt)
        {
            case TYP_BOOL:
            case TYP_UBYTE:
                return TYP_BYTE;
            case TYP_USHORT:
            case TYP_CHAR:
                return TYP_SHORT;
            case TYP_UINT:
                return TYP_INT;
            case TYP_ULONG:
                return TYP_LONG;
            default:
                unreached();
        }
    }
    else
    {
        return vt;
    }
}

template <class T>
inline bool varTypeIsFloating(T vt)
{
    return ((varTypeClassification[TypeGet(vt)] & (VTF_FLT)) != 0);
}

template <class T>
inline bool varTypeIsArithmetic(T vt)
{
    return ((varTypeClassification[TypeGet(vt)] & (VTF_INT | VTF_FLT)) != 0);
}

template <class T>
inline unsigned varTypeGCtype(T vt)
{
    return (unsigned)(varTypeClassification[TypeGet(vt)] & (VTF_GCR | VTF_BYR));
}

template <class T>
inline bool varTypeIsGC(T vt)
{
    return (varTypeGCtype(vt) != 0);
}

template <class T>
inline bool varTypeIsI(T vt)
{
    return ((varTypeClassification[TypeGet(vt)] & VTF_I) != 0);
}

template <class T>
inline bool varTypeCanReg(T vt)
{
    return ((varTypeClassification[TypeGet(vt)] & (VTF_INT | VTF_I | VTF_FLT)) != 0);
}

template <class T>
inline bool varTypeIsByte(T vt)
{
    return (TypeGet(vt) >= TYP_BOOL) && (TypeGet(vt) <= TYP_UBYTE);
}

template <class T>
inline bool varTypeIsShort(T vt)
{
    return (TypeGet(vt) >= TYP_CHAR) && (TypeGet(vt) <= TYP_USHORT);
}

template <class T>
inline bool varTypeIsSmall(T vt)
{
    return (TypeGet(vt) >= TYP_BOOL) && (TypeGet(vt) <= TYP_USHORT);
}

template <class T>
inline bool varTypeIsSmallInt(T vt)
{
    return (TypeGet(vt) >= TYP_BYTE) && (TypeGet(vt) <= TYP_USHORT);
}

template <class T>
inline bool varTypeIsIntOrI(T vt)
{
    return ((TypeGet(vt) == TYP_INT)
#ifdef _TARGET_64BIT_
            || (TypeGet(vt) == TYP_I_IMPL)
#endif // _TARGET_64BIT_
                );
}

template <class T>
inline bool genActualTypeIsIntOrI(T vt)
{
    return ((TypeGet(vt) >= TYP_BOOL) && (TypeGet(vt) <= TYP_U_IMPL));
}

template <class T>
inline bool varTypeIsLong(T vt)
{
    return (TypeGet(vt) >= TYP_LONG) && (TypeGet(vt) <= TYP_ULONG);
}

template <class T>
inline bool varTypeIsMultiReg(T vt)
{
#ifdef _TARGET_64BIT_
    return false;
#else
    return (TypeGet(vt) == TYP_LONG);
#endif
}

template <class T>
inline bool varTypeIsSingleReg(T vt)
{
    return !varTypeIsMultiReg(vt);
}

template <class T>
inline bool varTypeIsComposite(T vt)
{
    return (!varTypeIsArithmetic(TypeGet(vt)) && TypeGet(vt) != TYP_VOID);
}

// Is this type promotable?
// In general only structs are promotable.
// However, a SIMD type, e.g. TYP_SIMD may be handled as either a struct, OR a
// fully-promoted register type.
// On 32-bit systems longs are split into an upper and lower half, and they are
// handled as if they are structs with two integer fields.

template <class T>
inline bool varTypeIsPromotable(T vt)
{
    return (varTypeIsStruct(vt) || (TypeGet(vt) == TYP_BLK)
#if !defined(_TARGET_64BIT_)
            || varTypeIsLong(vt)
#endif // !defined(_TARGET_64BIT_)
                );
}

template <class T>
inline bool varTypeIsStruct(T vt)
{
    return ((varTypeClassification[TypeGet(vt)] & VTF_S) != 0);
}

template <class T>
inline bool varTypeIsEnregisterableStruct(T vt)
{
    return (TypeGet(vt) != TYP_STRUCT);
}

/*****************************************************************************/
#endif // _VARTYPE_H_
/*****************************************************************************/