summaryrefslogtreecommitdiff
path: root/src/inc/stdmacros.h
blob: 3ec8bec6f348d0388c552237413ccab44894b255 (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
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
// 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.

//

//
// common.h - precompiled headers include for the COM+ Execution Engine
//

//
// Make sure _ASSERTE is defined before including this header file
// Other than that, please keep this header self-contained so that it can be included in
//  all dlls
//


#ifndef _stdmacros_h_
#define _stdmacros_h_

#include "specstrings.h"
#include "contract.h"

#ifndef _ASSERTE
#error Please define _ASSERTE before including StdMacros.h
#endif

#ifdef _DEBUG
#define     DEBUG_ARG(x)  , x
#define     DEBUG_ARG1(x)  x
#else
#define     DEBUG_ARG(x) 
#define     DEBUG_ARG1(x)
#endif

#ifdef DACCESS_COMPILE
#define     DAC_ARG(x)  , x
#else
#define     DAC_ARG(x) 
#endif


/********************************************/
/*         Portability macros               */
/********************************************/

#ifdef _TARGET_AMD64_
#define AMD64_FIRST_ARG(x)  x ,
#define AMD64_ARG(x)        , x
#define AMD64_ONLY(x)       x
#define NOT_AMD64(x)
#define NOT_AMD64_ARG(x)
#else
#define AMD64_FIRST_ARG(x)
#define AMD64_ARG(x)
#define AMD64_ONLY(x)
#define NOT_AMD64(x)        x
#define NOT_AMD64_ARG(x)    , x
#endif

#ifdef _TARGET_X86_
#define X86_FIRST_ARG(x)    x ,
#define X86_ARG(x)          , x
#define X86_ONLY(x)         x
#define NOT_X86(x)
#define NOT_X86_ARG(x)
#else
#define X86_FIRST_ARG(x)
#define X86_ARG(x)
#define X86_ONLY(x)
#define NOT_X86(x)          x
#define NOT_X86_ARG(x)      , x
#endif

#ifdef _WIN64
#define WIN64_ARG(x)  , x 
#define WIN64_ONLY(x) x 
#define NOT_WIN64(x)
#define NOT_WIN64_ARG(x)
#else
#define WIN64_ARG(x)
#define WIN64_ONLY(x) 
#define NOT_WIN64(x)    x
#define NOT_WIN64_ARG(x)    , x
#endif // _WIN64

#ifdef _TARGET_ARM_
#define ARM_FIRST_ARG(x)  x ,
#define ARM_ARG(x)        , x
#define ARM_ONLY(x)       x
#define NOT_ARM(x)
#define NOT_ARM_ARG(x)
#else
#define ARM_FIRST_ARG(x)
#define ARM_ARG(x)
#define ARM_ONLY(x)
#define NOT_ARM(x)        x
#define NOT_ARM_ARG(x)    , x
#endif

#ifdef _TARGET_ARM64_
#define ARM64_FIRST_ARG(x)  x ,
#define ARM64_ARG(x)        , x
#define ARM64_ONLY(x)       x
#define NOT_ARM64(x)
#define NOT_ARM64_ARG(x)
#else
#define ARM64_FIRST_ARG(x)
#define ARM64_ARG(x)
#define ARM64_ONLY(x)
#define NOT_ARM64(x)        x
#define NOT_ARM64_ARG(x)    , x
#endif

#ifdef _WIN64
    #define LOG2_PTRSIZE       3
    #define INVALID_POINTER_CC 0xcccccccccccccccc
    #define INVALID_POINTER_CD 0xcdcdcdcdcdcdcdcd
    #define FMT_ADDR           " %08x`%08x "
    #define LFMT_ADDR          W(" %08x`%08x ")
    #define DBG_ADDR(ptr)      (((UINT_PTR) (ptr)) >> 32), (((UINT_PTR) (ptr)) & 0xffffffff)
#else // _WIN64
    #define LOG2_PTRSIZE       2
    #define INVALID_POINTER_CC 0xcccccccc
    #define INVALID_POINTER_CD 0xcdcdcdcd
    #define FMT_ADDR           " %08x "
    #define LFMT_ADDR          W(" %08x ")
    #define DBG_ADDR(ptr)      ((UINT_PTR)(ptr))
#endif // _WIN64

#ifdef _TARGET_ARM_
    #define ALIGN_ACCESS        ((1<<LOG2_PTRSIZE)-1)
#endif


#ifndef ALLOC_ALIGN_CONSTANT
#define ALLOC_ALIGN_CONSTANT ((1<<LOG2_PTRSIZE)-1)
#endif


inline void *GetTopMemoryAddress(void)
{
    WRAPPER_NO_CONTRACT;
    
    static void *result; // = NULL;
    if( NULL == result )
    {
        SYSTEM_INFO sysInfo;
        GetSystemInfo( &sysInfo );
        result = sysInfo.lpMaximumApplicationAddress;
    }
    return result;
}
inline void *GetBotMemoryAddress(void)
{
    WRAPPER_NO_CONTRACT;
    
    static void *result; // = NULL;
    if( NULL == result )
    {
        SYSTEM_INFO sysInfo;
        GetSystemInfo( &sysInfo );
        result = sysInfo.lpMinimumApplicationAddress;
    }
    return result;
}

#define TOP_MEMORY (GetTopMemoryAddress())
#define BOT_MEMORY (GetBotMemoryAddress())


//
// This macro returns val rounded up as necessary to be a multiple of alignment; alignment must be a power of 2
//
inline size_t ALIGN_UP( size_t val, size_t alignment )
{
    LIMITED_METHOD_DAC_CONTRACT;
    
    // alignment must be a power of 2 for this implementation to work (need modulo otherwise)
    _ASSERTE( 0 == (alignment & (alignment - 1)) ); 
    size_t result = (val + (alignment - 1)) & ~(alignment - 1);
    _ASSERTE( result >= val );      // check for overflow
    return result;
}
inline void* ALIGN_UP( void* val, size_t alignment )
{
    WRAPPER_NO_CONTRACT;
    
    return (void*) ALIGN_UP( (size_t)val, alignment );
}
inline uint8_t* ALIGN_UP( uint8_t* val, size_t alignment )
{
    WRAPPER_NO_CONTRACT;
    
    return (uint8_t*) ALIGN_UP( (size_t)val, alignment );
}

inline size_t ALIGN_DOWN( size_t val, size_t alignment )
{
    LIMITED_METHOD_CONTRACT;
    
    // alignment must be a power of 2 for this implementation to work (need modulo otherwise)
    _ASSERTE( 0 == (alignment & (alignment - 1)) );
    size_t result = val & ~(alignment - 1);
    return result;
}
inline void* ALIGN_DOWN( void* val, size_t alignment )
{
    WRAPPER_NO_CONTRACT;
    return (void*) ALIGN_DOWN( (size_t)val, alignment );
}
inline uint8_t* ALIGN_DOWN( uint8_t* val, size_t alignment )
{
    WRAPPER_NO_CONTRACT;
    return (uint8_t*) ALIGN_DOWN( (size_t)val, alignment );
}

inline BOOL IS_ALIGNED( size_t val, size_t alignment )
{
    LIMITED_METHOD_CONTRACT;
    SUPPORTS_DAC;
    
    // alignment must be a power of 2 for this implementation to work (need modulo otherwise)
    _ASSERTE( 0 == (alignment & (alignment - 1)) ); 
    return 0 == (val & (alignment - 1));
}
inline BOOL IS_ALIGNED( const void* val, size_t alignment )
{
    WRAPPER_NO_CONTRACT;
    return IS_ALIGNED( (size_t) val, alignment );
}

// Rounds a ULONG up to the nearest power of two number.
inline ULONG RoundUpToPower2(ULONG x) 
{
    if (x == 0) return 1;

    x = x - 1;
    x = x | (x >> 1);
    x = x | (x >> 2);
    x = x | (x >> 4);
    x = x | (x >> 8);
    x = x | (x >> 16);
    return x + 1;
}

#ifdef ALIGN_ACCESS

// NOTE: pSrc is evaluated three times!!!
#define MAYBE_UNALIGNED_READ(pSrc, bits)        (IS_ALIGNED((size_t)(pSrc), sizeof(UINT##bits)) ? \
                                                    (*(UINT##bits*)      (pSrc)) : \
                                                    (GET_UNALIGNED_##bits(pSrc)) )

#define MAYBE_UNALIGNED_WRITE(pDst, bits, expr) do { if (IS_ALIGNED((size_t)(pDst), sizeof(UINT##bits))) \
                                                    *(UINT##bits*)(pDst) = (UINT##bits)(expr); else \
                                                    SET_UNALIGNED_##bits(pDst, (UINT##bits)(expr)); } while (0)

// these are necessary for MAYBE_UNALIGNED_XXX to work with UINT_PTR
#define GET_UNALIGNED__PTR(x) GET_UNALIGNED_PTR(x)
#define SET_UNALIGNED__PTR(p,x) SET_UNALIGNED_PTR(p,x)

#else // ALIGN_ACCESS
#define MAYBE_UNALIGNED_READ(pSrc, bits)        (*(UINT##bits*)(pSrc))
#define MAYBE_UNALIGNED_WRITE(pDst, bits, expr) do { *(UINT##bits*)(pDst) = (UINT##bits)(expr); } while(0)
#endif // ALIGN_ACCESS

//
// define some useful macros for logging object
//

#define FMT_OBJECT  "object" FMT_ADDR
#define FMT_HANDLE  "handle" FMT_ADDR
#define FMT_CLASS   "%s"
#define FMT_REG     "r%d "
#define FMT_STK     "sp%s0x%02x "
#define FMT_PIPTR   "%s%s pointer "


#define DBG_GET_CLASS_NAME(pMT)        \
        (((pMT) == NULL)  ? NULL : (pMT)->GetClass()->GetDebugClassName())

#define DBG_CLASS_NAME_MT(pMT)         \
        (DBG_GET_CLASS_NAME(pMT) == NULL) ? "<null-class>" : DBG_GET_CLASS_NAME(pMT) 

#define DBG_GET_MT_FROM_OBJ(obj)       \
        (MethodTable*)((size_t)((Object*) (obj))->GetGCSafeMethodTable()) 

#define DBG_CLASS_NAME_OBJ(obj)        \
        ((obj) == NULL)  ? "null" : DBG_CLASS_NAME_MT(DBG_GET_MT_FROM_OBJ(obj)) 

#define DBG_CLASS_NAME_IPTR2(obj,iptr) \
        ((iptr) != 0)    ? ""     : DBG_CLASS_NAME_MT(DBG_GET_MT_FROM_OBJ(obj))

#define DBG_CLASS_NAME_IPTR(obj,iptr)  \
        ((obj)  == NULL) ? "null" : DBG_CLASS_NAME_IPTR2(obj,iptr)

#define DBG_STK(off)                   \
        (off >= 0) ? "+" : "-",        \
        (off >= 0) ? off : -off

#define DBG_PIN_NAME(pin)              \
        (pin)  ? "pinned "  : ""

#define DBG_IPTR_NAME(iptr)            \
        (iptr) ? "interior" : "base"

#define LOG_HANDLE_OBJECT_CLASS(str1, hnd, str2, obj)    \
        str1 FMT_HANDLE str2 FMT_OBJECT FMT_CLASS "\n",  \
        DBG_ADDR(hnd), DBG_ADDR(obj), DBG_CLASS_NAME_OBJ(obj)

#define LOG_OBJECT_CLASS(obj)                            \
        FMT_OBJECT FMT_CLASS "\n",                       \
        DBG_ADDR(obj), DBG_CLASS_NAME_OBJ(obj)

#define LOG_PIPTR_OBJECT_CLASS(obj, pin, iptr)           \
        FMT_PIPTR FMT_ADDR FMT_CLASS "\n",               \
        DBG_PIN_NAME(pin), DBG_IPTR_NAME(iptr),          \
        DBG_ADDR(obj), DBG_CLASS_NAME_IPTR(obj,iptr)

#define LOG_HANDLE_OBJECT(str1, hnd, str2, obj)          \
        str1 FMT_HANDLE str2 FMT_OBJECT "\n",            \
        DBG_ADDR(hnd), DBG_ADDR(obj)

#define LOG_PIPTR_OBJECT(obj, pin, iptr)                 \
        FMT_PIPTR FMT_ADDR "\n",                         \
        DBG_PIN_NAME(pin), DBG_IPTR_NAME(iptr),          \
        DBG_ADDR(obj)

#define UNIQUE_LABEL_DEF(a,x)           a##x
#define UNIQUE_LABEL_DEF_X(a,x)         UNIQUE_LABEL_DEF(a,x)
#ifdef _MSC_VER
#define UNIQUE_LABEL(a)                 UNIQUE_LABEL_DEF_X(_unique_label_##a##_, __COUNTER__)
#else
#define UNIQUE_LABEL(a)                 UNIQUE_LABEL_DEF_X(_unique_label_##a##_, __LINE__)
#endif


#ifndef _countof
#define _countof(_array) (sizeof(_array)/sizeof(_array[0]))
#endif


// This is temporary.  LKG should provide these macros and we should then 
// remove STRUNCATE and _TRUNCATE from here.

/* error codes */
#if !defined(STRUNCATE)
#define STRUNCATE       80
#endif

/* _TRUNCATE */
#if !defined(_TRUNCATE)
#define _TRUNCATE ((size_t)-1)
#endif

#endif //_stdmacros_h_