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