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// Standard primitive types for CLR code
6//
7// This header serves as a platform layer containing all of the primitive types
8// which we use across CLR implementation code.
9// ================================================================================
10
11
12#ifndef CLRTYPES_H_
13#define CLRTYPES_H_
14
15#if defined(_MSC_VER) && !defined(SOURCE_FORMATTING) && defined(FEATURE_CORESYSTEM)
16 // Prefer intsafe.h when available, which defines many of the MAX/MIN
17 // values below (which is why they are in #ifndef blocks).
18 #include <intsafe.h>
19#endif
20
21#include "crtwrap.h"
22#include "winwrap.h"
23#include "staticcontract.h"
24#include "static_assert.h"
25
26#if _WIN64
27 #define POINTER_BITS 64
28#else
29 #define POINTER_BITS 32
30#endif
31
32// ================================================================================
33// Integral types - use these for all integral types
34// These types are in ALL_CAPS. Each type has a _MIN and _MAX defined for it.
35// ================================================================================
36
37// --------------------------------------------------------------------------------
38// Use these types for fixed size integers:
39// INT8 UINT8 INT16 UINT16 INT32 UINT32 INT64 UINT64
40// --------------------------------------------------------------------------------
41
42#ifndef INT8_MAX
43 typedef signed char INT8;
44 typedef unsigned char UINT8;
45 typedef short INT16;
46 typedef unsigned short UINT16;
47 typedef int INT32;
48 typedef unsigned int UINT32;
49 typedef __int64 INT64;
50 typedef unsigned __int64 UINT64;
51
52 #ifdef _MSC_VER
53 /* These macros must exactly match those in the Windows SDK's intsafe.h */
54 #define INT8_MIN (-127i8 - 1)
55 #define INT16_MIN (-32767i16 - 1)
56 #define INT32_MIN (-2147483647i32 - 1)
57 #define INT64_MIN (-9223372036854775807i64 - 1)
58
59 #define INT8_MAX 127i8
60 #define INT16_MAX 32767i16
61 #define INT32_MAX 2147483647i32
62 #define INT64_MAX 9223372036854775807i64
63
64 #define UINT8_MAX 0xffui8
65 #define UINT16_MAX 0xffffui16
66 #define UINT32_MAX 0xffffffffui32
67 #define UINT64_MAX 0xffffffffffffffffui64
68 #else
69 #define INT8_MIN ((INT8)0x80)
70 #define INT16_MIN ((INT16)0x8000)
71 #define INT32_MIN ((INT32)0x80000000)
72 #define INT64_MIN ((INT64) I64(0x8000000000000000))
73
74 #define INT8_MAX ((INT8)0x7f)
75 #define INT16_MAX ((INT16)0x7fff)
76 #define INT32_MAX ((INT32)0x7fffffff)
77 #define INT64_MAX ((INT64) I64(0x7fffffffffffffff))
78
79 #define UINT8_MAX ((UINT8)0xffU)
80 #define UINT16_MAX ((UINT16)0xffffU)
81 #define UINT32_MAX ((UINT32)0xffffffffU)
82 #define UINT64_MAX ((UINT64) UI64(0xffffffffffffffff))
83 #endif
84#endif // !INT8_MAX
85
86// UINTX_MINs aren't defined in standard header files,
87// so definition must be separately predicated.
88#ifndef UINT8_MIN
89 #ifdef _MSC_VER
90 #define UINT8_MIN 0ui8
91 #define UINT16_MIN 0ui16
92 #define UINT32_MIN 0ui32
93 #define UINT64_MIN 0ui64
94 #else
95 #define UINT8_MIN ((UINT8)0U)
96 #define UINT16_MIN ((UINT16)0U)
97 #define UINT32_MIN ((UINT32)0U)
98 #define UINT64_MIN ((UINT64) UI64(0))
99 #endif
100#endif
101
102
103// --------------------------------------------------------------------------------
104// Use these types for pointer-sized integral types
105// SIZE_T SSIZE_T
106//
107// These types are the ONLY types which can be safely cast back and forth from a
108// pointer.
109// --------------------------------------------------------------------------------
110
111#ifndef SIZE_T_MAX
112 #if NEED_POINTER_SIZED_TYPEDEFS
113 typedef size_t SIZE_T;
114 typedef ptrdiff_t SSIZE_T;
115 #endif
116
117 #if POINTER_BITS == 64
118 #define SIZE_T_MAX UINT64_MAX
119 #define SIZE_T_MIN UINT64_MIN
120
121 #define SSIZE_T_MAX INT64_MAX
122 #define SSIZE_T_MIN INT64_MIN
123 #else
124 #define SIZE_T_MAX UINT32_MAX
125 #define SIZE_T_MIN UINT32_MIN
126
127 #define SSIZE_T_MAX INT32_MAX
128 #define SSIZE_T_MIN INT32_MIN
129 #endif
130#endif
131
132// --------------------------------------------------------------------------------
133// Non-pointer sized types
134// COUNT_T SCOUNT_T
135//
136// Use these types for "large" counts or indexes which will not exceed 32 bits. They
137// may also be used for pointer differences, if you can guarantee that the pointers
138// are pointing to the same region of memory. (It can NOT be used for arbitrary
139// pointer subtraction.)
140// --------------------------------------------------------------------------------
141
142#ifndef COUNT_T_MAX
143 typedef UINT32 COUNT_T;
144 typedef INT32 SCOUNT_T;
145
146 #define COUNT_T_MAX UINT32_MAX
147 #define COUNT_T_MIN UINT32_MIN
148
149 #define SCOUNT_T_MAX INT32_MAX
150 #define SCOUNT_T_MIN INT32_MIN
151#endif
152
153// --------------------------------------------------------------------------------
154// Integral types with additional semantic content
155// BOOL BYTE
156// --------------------------------------------------------------------------------
157
158#ifndef BYTE_MAX
159 #if NEED_BOOL_TYPEDEF
160 typedef bool BOOL;
161 #endif
162
163 #define BOOL_MAX 1
164 #define BOOL_MIN 0
165
166 #define TRUE 1
167 #define FALSE 0
168
169 typedef UINT8 BYTE;
170
171 #define BYTE_MAX UINT8_MAX
172 #define BYTE_MIN UINT8_MIN
173#endif
174
175// --------------------------------------------------------------------------------
176// Character types
177// CHAR SCHAR UCHAR WCHAR
178// --------------------------------------------------------------------------------
179
180typedef char CHAR;
181typedef signed char SCHAR;
182typedef unsigned char UCHAR;
183typedef wchar_t WCHAR;
184
185typedef CHAR ASCII;
186typedef CHAR ANSI;
187typedef CHAR UTF8;
188
189// Standard C defines:
190
191// CHAR_MAX
192// CHAR_MIN
193// SCHAR_MAX
194// SCHAR_MIN
195// UCHAR_MAX
196// UCHAR_MIN
197// WCHAR_MAX
198// WCHAR_MIN
199
200#ifndef ASCII_MAX
201 #define ASCII_MIN ((ASCII)0)
202 #define ASCII_MAX ((ASCII)127)
203
204 #define ANSI_MIN ((ANSI)0)
205 #define ANSI_MAX ((ANSI)255)
206
207 #define UTF8_MIN ((UTF8)0)
208 #define UTF8_MAX ((UTF8)255)
209#endif
210
211// ================================================================================
212// Non-integral types
213// These types are in ALL_CAPS.
214// ================================================================================
215
216// --------------------------------------------------------------------------------
217// Floating point types
218// FLOAT DOUBLE
219// --------------------------------------------------------------------------------
220
221// ================================================================================
222// Runtime type definitions - these are guaranteed to be identical with the
223// corresponding managed type
224// ================================================================================
225
226typedef WCHAR CLR_CHAR;
227typedef INT8 CLR_I1;
228typedef UINT8 CLR_U1;
229typedef INT16 CLR_I2;
230typedef UINT16 CLR_U2;
231typedef INT32 CLR_I4;
232typedef UINT32 CLR_U4;
233typedef INT64 CLR_I8;
234typedef UINT64 CLR_U8;
235typedef FLOAT CLR_R4;
236typedef DOUBLE CLR_R8;
237typedef SSIZE_T CLR_I;
238typedef SIZE_T CLR_U;
239
240#define CLR_CHAR_MAX WCHAR_MAX
241#define CLR_CHAR_MIN WCHAR_MIN
242
243#define CLR_I1_MAX INT8_MAX
244#define CLR_I1_MIN INT8_MIN
245
246#define CLR_U1_MAX UINT8_MAX
247#define CLR_U1_MIN UINT8_MIN
248
249#define CLR_I2_MAX INT16_MAX
250#define CLR_I2_MIN INT16_MIN
251
252#define CLR_U2_MAX UINT16_MAX
253#define CLR_U2_MIN UINT16_MIN
254
255#define CLR_I4_MAX INT32_MAX
256#define CLR_I4_MIN INT32_MIN
257
258#define CLR_U4_MAX UINT32_MAX
259#define CLR_U4_MIN UINT32_MIN
260
261#define CLR_I8_MAX INT64_MAX
262#define CLR_I8_MIN INT64_MIN
263
264#define CLR_U8_MAX UINT64_MAX
265#define CLR_U8_MIN UINT64_MIN
266
267#define CLR_I_MAX SSIZE_T_MAX
268#define CLR_I_MIN SSIZE_T_MIN
269
270#define CLR_U_MAX SIZE_T_MAX
271#define CLR_U_MIN SIZE_T_MIN
272
273 typedef bool CLR_BOOL;
274
275static_assert_no_msg(sizeof(CLR_BOOL) == 1);
276
277#define CLR_BOOL_MAX BOOL_MAX
278#define CLR_BOOL_MIN BOOL_MIN
279
280#define CLR_NAN_32 0xFFC00000
281#define CLR_NAN_64 I64(0xFFF8000000000000)
282
283// ================================================================================
284// Simple utility functions
285// ================================================================================
286
287// Note that these routines are in terms of UINT, ULONG, and ULONG64, since those are
288// the unsigned integral types the compiler overloads based on.
289
290// --------------------------------------------------------------------------------
291// Min/Max
292// --------------------------------------------------------------------------------
293
294template <typename T>
295T Min(T v1, T v2)
296{
297 STATIC_CONTRACT_LEAF;
298 STATIC_CONTRACT_SO_TOLERANT;
299 return v1 < v2 ? v1 : v2;
300}
301
302template <typename T>
303T Max(T v1, T v2)
304{
305 STATIC_CONTRACT_LEAF;
306 STATIC_CONTRACT_SO_TOLERANT;
307 return v1 > v2 ? v1 : v2;
308}
309
310// --------------------------------------------------------------------------------
311// Alignment bit twiddling macros - "alignment" must be power of 2
312//
313// AlignUp - align value to given increment, rounding up
314// AlignmentPad - amount adjusted by AlignUp
315// AlignUp(value, x) == value + AlignmentPad(value, x)
316//
317// AlignDown - align value to given increment, rounding down
318// AlignmentTrim - amount adjusted by AlignDown
319// AlignDown(value, x) == value - AlignmentTrim(value, x)
320// --------------------------------------------------------------------------------
321
322inline UINT AlignUp(UINT value, UINT alignment)
323{
324 STATIC_CONTRACT_LEAF;
325 STATIC_CONTRACT_SO_TOLERANT;
326 STATIC_CONTRACT_SUPPORTS_DAC;
327 return (value+alignment-1)&~(alignment-1);
328}
329
330#if defined(_MSC_VER)
331inline ULONG AlignUp(ULONG value, UINT alignment)
332{
333 STATIC_CONTRACT_LEAF;
334 STATIC_CONTRACT_SO_TOLERANT;
335 STATIC_CONTRACT_SUPPORTS_DAC;
336 return (value+alignment-1)&~(alignment-1);
337}
338#endif
339
340inline UINT64 AlignUp(UINT64 value, UINT alignment)
341{
342 STATIC_CONTRACT_LEAF;
343 STATIC_CONTRACT_SO_TOLERANT;
344 STATIC_CONTRACT_SUPPORTS_DAC;
345 return (value+alignment-1)&~(UINT64)(alignment-1);
346}
347
348inline UINT AlignDown(UINT value, UINT alignment)
349{
350 STATIC_CONTRACT_LEAF;
351 STATIC_CONTRACT_SO_TOLERANT;
352 STATIC_CONTRACT_SUPPORTS_DAC;
353 return (value&~(alignment-1));
354}
355
356#if defined(_MSC_VER)
357inline ULONG AlignDown(ULONG value, UINT alignment)
358{
359 STATIC_CONTRACT_LEAF;
360 STATIC_CONTRACT_SO_TOLERANT;
361 STATIC_CONTRACT_SUPPORTS_DAC;
362 return (value&~(ULONG)(alignment-1));
363}
364#endif
365
366inline UINT64 AlignDown(UINT64 value, UINT alignment)
367{
368 STATIC_CONTRACT_LEAF;
369 STATIC_CONTRACT_SO_TOLERANT;
370 STATIC_CONTRACT_SUPPORTS_DAC;
371 return (value&~(UINT64)(alignment-1));
372}
373
374inline UINT AlignmentPad(UINT value, UINT alignment)
375{
376 STATIC_CONTRACT_WRAPPER;
377 return AlignUp(value, alignment) - value;
378}
379
380#if defined(_MSC_VER)
381inline UINT AlignmentPad(ULONG value, UINT alignment)
382{
383 STATIC_CONTRACT_WRAPPER;
384 return AlignUp(value, alignment) - value;
385}
386#endif
387
388inline UINT AlignmentPad(UINT64 value, UINT alignment)
389{
390 STATIC_CONTRACT_WRAPPER;
391 return (UINT) (AlignUp(value, alignment) - value);
392}
393
394inline UINT AlignmentTrim(UINT value, UINT alignment)
395{
396 STATIC_CONTRACT_LEAF;
397 STATIC_CONTRACT_SO_TOLERANT;
398 STATIC_CONTRACT_SUPPORTS_DAC;
399 return value&(alignment-1);
400}
401
402#ifndef PLATFORM_UNIX
403// For Unix this and the previous function get the same types.
404// So, exclude this one.
405inline UINT AlignmentTrim(ULONG value, UINT alignment)
406{
407 STATIC_CONTRACT_LEAF;
408 STATIC_CONTRACT_SO_TOLERANT;
409 STATIC_CONTRACT_SUPPORTS_DAC;
410 return value&(alignment-1);
411}
412#endif // PLATFORM_UNIX
413
414inline UINT AlignmentTrim(UINT64 value, UINT alignment)
415{
416 STATIC_CONTRACT_LEAF;
417 STATIC_CONTRACT_SO_TOLERANT;
418 STATIC_CONTRACT_SUPPORTS_DAC;
419 return ((UINT)value)&(alignment-1);
420}
421
422#endif // CLRTYPES_H_
423