7e4ae79c535c5f7ac205b1dc21a0ef7c4bc1f998
[platform/upstream/dotnet/runtime.git] / src / coreclr / inc / stdmacros.h
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
4 //
5
6 //
7 // common.h - precompiled headers include for the COM+ Execution Engine
8 //
9
10 //
11 // Make sure _ASSERTE is defined before including this header file
12 // Other than that, please keep this header self-contained so that it can be included in
13 //  all dlls
14 //
15
16
17 #ifndef _stdmacros_h_
18 #define _stdmacros_h_
19
20 #include "specstrings.h"
21 #include "contract.h"
22
23 #ifndef _ASSERTE
24 #error Please define _ASSERTE before including StdMacros.h
25 #endif
26
27 #ifdef _DEBUG
28 #define     DEBUG_ARG(x)  , x
29 #define     DEBUG_ARG1(x)  x
30 #else
31 #define     DEBUG_ARG(x)
32 #define     DEBUG_ARG1(x)
33 #endif
34
35 #ifdef DACCESS_COMPILE
36 #define     DAC_ARG(x)  , x
37 #else
38 #define     DAC_ARG(x)
39 #endif
40
41
42 /********************************************/
43 /*         Portability macros               */
44 /********************************************/
45
46 #ifdef TARGET_AMD64
47 #define AMD64_FIRST_ARG(x)  x ,
48 #define AMD64_ARG(x)        , x
49 #define AMD64_ONLY(x)       x
50 #define NOT_AMD64(x)
51 #define NOT_AMD64_ARG(x)
52 #else
53 #define AMD64_FIRST_ARG(x)
54 #define AMD64_ARG(x)
55 #define AMD64_ONLY(x)
56 #define NOT_AMD64(x)        x
57 #define NOT_AMD64_ARG(x)    , x
58 #endif
59
60 #ifdef TARGET_X86
61 #define X86_FIRST_ARG(x)    x ,
62 #define X86_ARG(x)          , x
63 #define X86_ONLY(x)         x
64 #define NOT_X86(x)
65 #define NOT_X86_ARG(x)
66 #else
67 #define X86_FIRST_ARG(x)
68 #define X86_ARG(x)
69 #define X86_ONLY(x)
70 #define NOT_X86(x)          x
71 #define NOT_X86_ARG(x)      , x
72 #endif
73
74 #ifdef HOST_64BIT
75 #define BIT64_ARG(x)  , x
76 #define BIT64_ONLY(x) x
77 #define NOT_BIT64(x)
78 #define NOT_BIT64_ARG(x)
79 #else
80 #define BIT64_ARG(x)
81 #define BIT64_ONLY(x)
82 #define NOT_BIT64(x)    x
83 #define NOT_BIT64_ARG(x)    , x
84 #endif // HOST_64BIT
85
86 #ifdef TARGET_ARM
87 #define ARM_FIRST_ARG(x)  x ,
88 #define ARM_ARG(x)        , x
89 #define ARM_ONLY(x)       x
90 #define NOT_ARM(x)
91 #define NOT_ARM_ARG(x)
92 #else
93 #define ARM_FIRST_ARG(x)
94 #define ARM_ARG(x)
95 #define ARM_ONLY(x)
96 #define NOT_ARM(x)        x
97 #define NOT_ARM_ARG(x)    , x
98 #endif
99
100 #ifdef TARGET_ARM64
101 #define ARM64_FIRST_ARG(x)  x ,
102 #define ARM64_ARG(x)        , x
103 #define ARM64_ONLY(x)       x
104 #define NOT_ARM64(x)
105 #define NOT_ARM64_ARG(x)
106 #else
107 #define ARM64_FIRST_ARG(x)
108 #define ARM64_ARG(x)
109 #define ARM64_ONLY(x)
110 #define NOT_ARM64(x)        x
111 #define NOT_ARM64_ARG(x)    , x
112 #endif
113
114 #ifdef TARGET_LOONGARCH64
115 #define LOONGARCH64_FIRST_ARG(x)  x ,
116 #define LOONGARCH64_ARG(x)        , x
117 #define LOONGARCH64_ONLY(x)       x
118 #define NOT_LOONGARCH64(x)
119 #define NOT_LOONGARCH64_ARG(x)
120 #else
121 #define LOONGARCH64_FIRST_ARG(x)
122 #define LOONGARCH64_ARG(x)
123 #define LOONGARCH64_ONLY(x)
124 #define NOT_LOONGARCH64(x)        x
125 #define NOT_LOONGARCH64_ARG(x)    , x
126 #endif
127
128 #ifdef TARGET_RISCV64
129 #define RISCV64_FIRST_ARG(x)  x ,
130 #define RISCV64_ARG(x)        , x
131 #define RISCV64_ONLY(x)       x
132 #define NOT_RISCV64(x)
133 #define NOT_RISCV64_ARG(x)
134 #else
135 #define RISCV64_FIRST_ARG(x)
136 #define RISCV64_ARG(x)
137 #define RISCV64_ONLY(x)
138 #define NOT_RISCV64(x)        x
139 #define NOT_RISCV64_ARG(x)    , x
140 #endif
141
142 #ifdef TARGET_64BIT
143 #define LOG2_PTRSIZE 3
144 #else
145 #define LOG2_PTRSIZE 2
146 #endif
147
148 #ifdef HOST_64BIT
149     #define INVALID_POINTER_CC 0xcccccccccccccccc
150     #define INVALID_POINTER_CD 0xcdcdcdcdcdcdcdcd
151     #define FMT_ADDR           " %08x`%08x "
152     #define LFMT_ADDR          W(" %08x`%08x ")
153     #define DBG_ADDR(ptr)      (DWORD)(((UINT_PTR) (ptr)) >> 32), (DWORD)(((UINT_PTR) (ptr)) & 0xffffffff)
154 #else // HOST_64BIT
155     #define INVALID_POINTER_CC 0xcccccccc
156     #define INVALID_POINTER_CD 0xcdcdcdcd
157     #define FMT_ADDR           " %08x "
158     #define LFMT_ADDR          W(" %08x ")
159     #define DBG_ADDR(ptr)      (DWORD)((UINT_PTR)(ptr))
160 #endif // HOST_64BIT
161
162 #ifdef TARGET_ARM
163     #define ALIGN_ACCESS        ((1<<LOG2_PTRSIZE)-1)
164 #endif
165
166
167 #ifndef ALLOC_ALIGN_CONSTANT
168 #define ALLOC_ALIGN_CONSTANT (sizeof(void*)-1)
169 #endif
170
171
172 inline void *GetTopMemoryAddress(void)
173 {
174     WRAPPER_NO_CONTRACT;
175
176     static void *result; // = NULL;
177     if( NULL == result )
178     {
179         SYSTEM_INFO sysInfo;
180         GetSystemInfo( &sysInfo );
181         result = sysInfo.lpMaximumApplicationAddress;
182     }
183     return result;
184 }
185 inline void *GetBotMemoryAddress(void)
186 {
187     WRAPPER_NO_CONTRACT;
188
189     static void *result; // = NULL;
190     if( NULL == result )
191     {
192         SYSTEM_INFO sysInfo;
193         GetSystemInfo( &sysInfo );
194         result = sysInfo.lpMinimumApplicationAddress;
195     }
196     return result;
197 }
198
199 #define TOP_MEMORY (GetTopMemoryAddress())
200 #define BOT_MEMORY (GetBotMemoryAddress())
201
202
203 //
204 // This macro returns val rounded up as necessary to be a multiple of alignment; alignment must be a power of 2
205 //
206 inline size_t ALIGN_UP( size_t val, size_t alignment )
207 {
208     LIMITED_METHOD_DAC_CONTRACT;
209
210     // alignment must be a power of 2 for this implementation to work (need modulo otherwise)
211     _ASSERTE( 0 == (alignment & (alignment - 1)) );
212     size_t result = (val + (alignment - 1)) & ~(alignment - 1);
213     _ASSERTE( result >= val );      // check for overflow
214     return result;
215 }
216
217 template <typename T> inline T ALIGN_UP(T val, size_t alignment)
218 {
219     WRAPPER_NO_CONTRACT;
220     return (T)ALIGN_UP((size_t)val, alignment);
221 }
222
223 inline size_t ALIGN_DOWN( size_t val, size_t alignment )
224 {
225     LIMITED_METHOD_CONTRACT;
226
227     // alignment must be a power of 2 for this implementation to work (need modulo otherwise)
228     _ASSERTE( 0 == (alignment & (alignment - 1)) );
229     size_t result = val & ~(alignment - 1);
230     return result;
231 }
232 inline void* ALIGN_DOWN( void* val, size_t alignment )
233 {
234     WRAPPER_NO_CONTRACT;
235     return (void*) ALIGN_DOWN( (size_t)val, alignment );
236 }
237 inline uint8_t* ALIGN_DOWN( uint8_t* val, size_t alignment )
238 {
239     WRAPPER_NO_CONTRACT;
240     return (uint8_t*) ALIGN_DOWN( (size_t)val, alignment );
241 }
242
243 inline BOOL IS_ALIGNED( size_t val, size_t alignment )
244 {
245     LIMITED_METHOD_CONTRACT;
246     SUPPORTS_DAC;
247
248     // alignment must be a power of 2 for this implementation to work (need modulo otherwise)
249     _ASSERTE( 0 == (alignment & (alignment - 1)) );
250     return 0 == (val & (alignment - 1));
251 }
252 inline BOOL IS_ALIGNED( const void* val, size_t alignment )
253 {
254     WRAPPER_NO_CONTRACT;
255     return IS_ALIGNED( (size_t) val, alignment );
256 }
257
258 // Rounds a ULONG up to the nearest power of two number.
259 inline ULONG RoundUpToPower2(ULONG x)
260 {
261     if (x == 0) return 1;
262
263     x = x - 1;
264     x = x | (x >> 1);
265     x = x | (x >> 2);
266     x = x | (x >> 4);
267     x = x | (x >> 8);
268     x = x | (x >> 16);
269     return x + 1;
270 }
271
272 #ifdef ALIGN_ACCESS
273
274 // NOTE: pSrc is evaluated three times!!!
275 #define MAYBE_UNALIGNED_READ(pSrc, bits)        (IS_ALIGNED((size_t)(pSrc), sizeof(UINT##bits)) ? \
276                                                     (*(UINT##bits*)      (pSrc)) : \
277                                                     (GET_UNALIGNED_##bits(pSrc)) )
278
279 #define MAYBE_UNALIGNED_WRITE(pDst, bits, expr) do { if (IS_ALIGNED((size_t)(pDst), sizeof(UINT##bits))) \
280                                                     *(UINT##bits*)(pDst) = (UINT##bits)(expr); else \
281                                                     SET_UNALIGNED_##bits(pDst, (UINT##bits)(expr)); } while (0)
282
283 // these are necessary for MAYBE_UNALIGNED_XXX to work with UINT_PTR
284 #define GET_UNALIGNED__PTR(x) GET_UNALIGNED_PTR(x)
285 #define SET_UNALIGNED__PTR(p,x) SET_UNALIGNED_PTR(p,x)
286
287 #else // ALIGN_ACCESS
288 #define MAYBE_UNALIGNED_READ(pSrc, bits)        (*(UINT##bits*)(pSrc))
289 #define MAYBE_UNALIGNED_WRITE(pDst, bits, expr) do { *(UINT##bits*)(pDst) = (UINT##bits)(expr); } while(0)
290 #endif // ALIGN_ACCESS
291
292 //
293 // define some useful macros for logging object
294 //
295
296 #define FMT_OBJECT  "object" FMT_ADDR
297 #define FMT_HANDLE  "handle" FMT_ADDR
298 #define FMT_CLASS   "%s"
299 #define FMT_REG     "r%d "
300 #define FMT_STK     "sp%s0x%02x "
301 #define FMT_PIPTR   "%s%s pointer "
302
303
304 #define DBG_GET_CLASS_NAME(pMT)        \
305         (((pMT) == NULL)  ? NULL : (pMT)->GetClass()->GetDebugClassName())
306
307 #define DBG_CLASS_NAME_MT(pMT)         \
308         (DBG_GET_CLASS_NAME(pMT) == NULL) ? "<null-class>" : DBG_GET_CLASS_NAME(pMT)
309
310 #define DBG_GET_MT_FROM_OBJ(obj)       \
311         (MethodTable*)((size_t)((Object*) (obj))->GetGCSafeMethodTable())
312
313 #define DBG_CLASS_NAME_OBJ(obj)        \
314         ((obj) == NULL)  ? "null" : DBG_CLASS_NAME_MT(DBG_GET_MT_FROM_OBJ(obj))
315
316 #define DBG_CLASS_NAME_IPTR2(obj,iptr) \
317         ((iptr) != 0)    ? ""     : DBG_CLASS_NAME_MT(DBG_GET_MT_FROM_OBJ(obj))
318
319 #define DBG_CLASS_NAME_IPTR(obj,iptr)  \
320         ((obj)  == NULL) ? "null" : DBG_CLASS_NAME_IPTR2(obj,iptr)
321
322 #define DBG_STK(off)                   \
323         (off >= 0) ? "+" : "-",        \
324         (off >= 0) ? off : -off
325
326 #define DBG_PIN_NAME(pin)              \
327         (pin)  ? "pinned "  : ""
328
329 #define DBG_IPTR_NAME(iptr)            \
330         (iptr) ? "interior" : "base"
331
332 #define LOG_HANDLE_OBJECT_CLASS(str1, hnd, str2, obj)    \
333         str1 FMT_HANDLE str2 FMT_OBJECT FMT_CLASS "\n",  \
334         DBG_ADDR(hnd), DBG_ADDR(obj), DBG_CLASS_NAME_OBJ(obj)
335
336 #define LOG_OBJECT_CLASS(obj)                            \
337         FMT_OBJECT FMT_CLASS "\n",                       \
338         DBG_ADDR(obj), DBG_CLASS_NAME_OBJ(obj)
339
340 #define LOG_PIPTR_OBJECT_CLASS(obj, pin, iptr)           \
341         FMT_PIPTR FMT_ADDR FMT_CLASS "\n",               \
342         DBG_PIN_NAME(pin), DBG_IPTR_NAME(iptr),          \
343         DBG_ADDR(obj), DBG_CLASS_NAME_IPTR(obj,iptr)
344
345 #define LOG_HANDLE_OBJECT(str1, hnd, str2, obj)          \
346         str1 FMT_HANDLE str2 FMT_OBJECT "\n",            \
347         DBG_ADDR(hnd), DBG_ADDR(obj)
348
349 #define LOG_PIPTR_OBJECT(obj, pin, iptr)                 \
350         FMT_PIPTR FMT_ADDR "\n",                         \
351         DBG_PIN_NAME(pin), DBG_IPTR_NAME(iptr),          \
352         DBG_ADDR(obj)
353
354 #define UNIQUE_LABEL_DEF(a,x)           a##x
355 #define UNIQUE_LABEL_DEF_X(a,x)         UNIQUE_LABEL_DEF(a,x)
356 #ifdef _MSC_VER
357 #define UNIQUE_LABEL(a)                 UNIQUE_LABEL_DEF_X(_unique_label_##a##_, __COUNTER__)
358 #else
359 #define UNIQUE_LABEL(a)                 UNIQUE_LABEL_DEF_X(_unique_label_##a##_, __LINE__)
360 #endif
361
362 // This is temporary.  LKG should provide these macros and we should then
363 // remove STRUNCATE and _TRUNCATE from here.
364
365 /* error codes */
366 #if !defined(STRUNCATE)
367 #define STRUNCATE       80
368 #endif
369
370 /* _TRUNCATE */
371 #if !defined(_TRUNCATE)
372 #define _TRUNCATE ((size_t)-1)
373 #endif
374
375 #endif //_stdmacros_h_