| 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 | // File: palclr.h |
| 6 | // |
| 7 | // Various macros and constants that are necessary to make the CLR portable. |
| 8 | // |
| 9 | |
| 10 | // =========================================================================== |
| 11 | |
| 12 | |
| 13 | #if !defined(FEATURE_PAL) |
| 14 | |
| 15 | #ifndef __PALCLR_H__ |
| 16 | #define __PALCLR_H__ |
| 17 | |
| 18 | // This macro is used to standardize the wide character string literals between UNIX and Windows. |
| 19 | // Unix L"" is UTF32, and on windows it's UTF16. Because of built-in assumptions on the size |
| 20 | // of string literals, it's important to match behaviour between Unix and Windows. Unix will be defined |
| 21 | // as u"" (char16_t) |
| 22 | #ifdef PLATFORM_UNIX |
| 23 | #define W(str) u##str |
| 24 | #else // PLATFORM_UNIX |
| 25 | #define W(str) L##str |
| 26 | #endif // PLATFORM_UNIX |
| 27 | |
| 28 | #include <windef.h> |
| 29 | |
| 30 | #if !defined(_DEBUG_IMPL) && defined(_DEBUG) && !defined(DACCESS_COMPILE) |
| 31 | #define _DEBUG_IMPL 1 |
| 32 | #endif |
| 33 | |
| 34 | // |
| 35 | // CPP_ASSERT() can be used within a class definition, to perform a |
| 36 | // compile-time assertion involving private names within the class. |
| 37 | // |
| 38 | // MS compiler doesn't allow redefinition of the typedef within a template. |
| 39 | // gcc doesn't allow redefinition of the typedef within a class, though |
| 40 | // it does at file scope. |
| 41 | #define CPP_ASSERT(n, e) typedef char __C_ASSERT__##n[(e) ? 1 : -1]; |
| 42 | |
| 43 | |
| 44 | // PORTABILITY_ASSERT and PORTABILITY_WARNING macros are meant to be used to |
| 45 | // mark places in the code that needs attention for portability. The usual |
| 46 | // usage pattern is: |
| 47 | // |
| 48 | // int get_scratch_register() { |
| 49 | // #if defined(_TARGET_X86_) |
| 50 | // return eax; |
| 51 | // #elif defined(_TARGET_AMD64_) |
| 52 | // return rax; |
| 53 | // #elif defined(_TARGET_ARM_) |
| 54 | // return r0; |
| 55 | // #else |
| 56 | // PORTABILITY_ASSERT("scratch register"); |
| 57 | // return 0; |
| 58 | // #endif |
| 59 | // } |
| 60 | // |
| 61 | // PORTABILITY_ASSERT is meant to be used inside functions/methods. It can |
| 62 | // introduce compile-time and/or run-time errors. |
| 63 | // PORTABILITY_WARNING is meant to be used outside functions/methods. It can |
| 64 | // introduce compile-time errors or warnings only. |
| 65 | // |
| 66 | // People starting new ports will first define these to just cause run-time |
| 67 | // errors. Once they fix all the places that need attention for portability, |
| 68 | // they can define PORTABILITY_ASSERT and PORTABILITY_WARNING to cause |
| 69 | // compile-time errors to make sure that they haven't missed anything. |
| 70 | // |
| 71 | // If it is reasonably possible all codepaths containing PORTABILITY_ASSERT |
| 72 | // should be compilable (e.g. functions should return NULL or something if |
| 73 | // they are expected to return a value). |
| 74 | // |
| 75 | // The message in these two macros should not contain any keywords like TODO |
| 76 | // or NYI. It should be just the brief description of the problem. |
| 77 | |
| 78 | #if defined(_TARGET_X86_) |
| 79 | // Finished ports - compile-time errors |
| 80 | #define PORTABILITY_WARNING(message) NEED_TO_PORT_THIS_ONE(NEED_TO_PORT_THIS_ONE) |
| 81 | #define PORTABILITY_ASSERT(message) NEED_TO_PORT_THIS_ONE(NEED_TO_PORT_THIS_ONE) |
| 82 | #else |
| 83 | // Ports in progress - run-time asserts only |
| 84 | #define PORTABILITY_WARNING(message) |
| 85 | #define PORTABILITY_ASSERT(message) _ASSERTE(false && message) |
| 86 | #endif |
| 87 | |
| 88 | #define DIRECTORY_SEPARATOR_CHAR_A '\\' |
| 89 | #define DIRECTORY_SEPARATOR_STR_A "\\" |
| 90 | #define DIRECTORY_SEPARATOR_CHAR_W W('\\') |
| 91 | #define DIRECTORY_SEPARATOR_STR_W W("\\") |
| 92 | |
| 93 | #define PATH_SEPARATOR_CHAR_W W(';') |
| 94 | #define PATH_SEPARATOR_STR_W W(";") |
| 95 | |
| 96 | #define VOLUME_SEPARATOR_CHAR_W W(':') |
| 97 | |
| 98 | // PAL Macros |
| 99 | // Not all compilers support fully anonymous aggregate types, so the |
| 100 | // PAL provides names for those types. To allow existing definitions of |
| 101 | // those types to continue to work, we provide macros that should be |
| 102 | // used to reference fields within those types. |
| 103 | |
| 104 | #ifndef DECIMAL_SCALE |
| 105 | #define DECIMAL_SCALE(dec) ((dec).scale) |
| 106 | #endif |
| 107 | |
| 108 | #ifndef DECIMAL_SIGN |
| 109 | #define DECIMAL_SIGN(dec) ((dec).sign) |
| 110 | #endif |
| 111 | |
| 112 | #ifndef DECIMAL_SIGNSCALE |
| 113 | #define DECIMAL_SIGNSCALE(dec) ((dec).signscale) |
| 114 | #endif |
| 115 | |
| 116 | #ifndef DECIMAL_LO32 |
| 117 | #define DECIMAL_LO32(dec) ((dec).Lo32) |
| 118 | #endif |
| 119 | |
| 120 | #ifndef DECIMAL_MID32 |
| 121 | #define DECIMAL_MID32(dec) ((dec).Mid32) |
| 122 | #endif |
| 123 | |
| 124 | #ifndef DECIMAL_HI32 |
| 125 | #define DECIMAL_HI32(dec) ((dec).Hi32) |
| 126 | #endif |
| 127 | |
| 128 | #ifndef DECIMAL_LO64_GET |
| 129 | #define DECIMAL_LO64_GET(dec) ((dec).Lo64) |
| 130 | #endif |
| 131 | |
| 132 | #ifndef DECIMAL_LO64_SET |
| 133 | #define DECIMAL_LO64_SET(dec,value) {(dec).Lo64 = value; } |
| 134 | #endif |
| 135 | |
| 136 | #ifndef IMAGE_RELOC_FIELD |
| 137 | #define IMAGE_RELOC_FIELD(img, f) ((img).f) |
| 138 | #endif |
| 139 | |
| 140 | #ifndef IMAGE_IMPORT_DESC_FIELD |
| 141 | #define IMAGE_IMPORT_DESC_FIELD(img, f) ((img).f) |
| 142 | #endif |
| 143 | |
| 144 | #define IMAGE_RDE_ID(img) ((img)->Id) |
| 145 | |
| 146 | #define IMAGE_RDE_NAME(img) ((img)->Name) |
| 147 | |
| 148 | #define IMAGE_RDE_OFFSET(img) ((img)->OffsetToData) |
| 149 | |
| 150 | #ifndef IMAGE_RDE_NAME_FIELD |
| 151 | #define IMAGE_RDE_NAME_FIELD(img, f) ((img)->f) |
| 152 | #endif |
| 153 | |
| 154 | #define IMAGE_RDE_OFFSET_FIELD(img, f) ((img)->f) |
| 155 | |
| 156 | #ifndef IMAGE_FE64_FIELD |
| 157 | #define IMAGE_FE64_FIELD(img, f) ((img).f) |
| 158 | #endif |
| 159 | |
| 160 | #ifndef IMPORT_OBJ_HEADER_FIELD |
| 161 | #define IMPORT_OBJ_HEADER_FIELD(obj, f) ((obj).f) |
| 162 | #endif |
| 163 | |
| 164 | #ifndef IMAGE_COR20_HEADER_FIELD |
| 165 | #define IMAGE_COR20_HEADER_FIELD(obj, f) ((obj).f) |
| 166 | #endif |
| 167 | |
| 168 | |
| 169 | // PAL Numbers |
| 170 | // Used to ensure cross-compiler compatibility when declaring large |
| 171 | // integer constants. 64-bit integer constants should be wrapped in the |
| 172 | // declarations listed here. |
| 173 | // |
| 174 | // Each of the #defines here is wrapped to avoid conflicts with pal.h. |
| 175 | |
| 176 | #if defined(_MSC_VER) |
| 177 | |
| 178 | // MSVC's way of declaring large integer constants |
| 179 | // If you define these in one step, without the _HELPER macros, you |
| 180 | // get extra whitespace when composing these with other concatenating macros. |
| 181 | #ifndef I64 |
| 182 | #define I64_HELPER(x) x ## i64 |
| 183 | #define I64(x) I64_HELPER(x) |
| 184 | #endif |
| 185 | |
| 186 | #ifndef UI64 |
| 187 | #define UI64_HELPER(x) x ## ui64 |
| 188 | #define UI64(x) UI64_HELPER(x) |
| 189 | #endif |
| 190 | |
| 191 | #else |
| 192 | |
| 193 | // GCC's way of declaring large integer constants |
| 194 | // If you define these in one step, without the _HELPER macros, you |
| 195 | // get extra whitespace when composing these with other concatenating macros. |
| 196 | #ifndef I64 |
| 197 | #define I64_HELPER(x) x ## LL |
| 198 | #define I64(x) I64_HELPER(x) |
| 199 | #endif |
| 200 | |
| 201 | #ifndef UI64 |
| 202 | #define UI64_HELPER(x) x ## ULL |
| 203 | #define UI64(x) UI64_HELPER(x) |
| 204 | #endif |
| 205 | |
| 206 | #endif |
| 207 | |
| 208 | |
| 209 | // PAL SEH |
| 210 | // Macros for portable exception handling. The Win32 SEH is emulated using |
| 211 | // these macros and setjmp/longjmp on Unix |
| 212 | // |
| 213 | // Usage notes: |
| 214 | // |
| 215 | // - The filter has to be a function taking two parameters: |
| 216 | // LONG MyFilter(PEXCEPTION_POINTERS *pExceptionInfo, PVOID pv) |
| 217 | // |
| 218 | // - It is not possible to directly use the local variables in the filter. |
| 219 | // All the local information that the filter has to need to know about should |
| 220 | // be passed through pv parameter |
| 221 | // |
| 222 | // - Do not use goto to jump out of the PAL_TRY block |
| 223 | // (jumping out of the try block is not a good idea even on Win32, because of |
| 224 | // it causes stack unwind) |
| 225 | // |
| 226 | // - It is not possible to directly use the local variables in the try block. |
| 227 | // All the local information that the filter has to need to know about should |
| 228 | // be passed through pv parameter |
| 229 | // |
| 230 | // |
| 231 | // Simple examples: |
| 232 | // |
| 233 | // struct Param { ... local variables used in try block and filter ... } param; |
| 234 | // PAL_TRY(Param *, pParam, ¶m) { // read as: Param *pParam = ¶m; |
| 235 | // .... |
| 236 | // } PAL_FINALLY { |
| 237 | // .... |
| 238 | // } |
| 239 | // PAL_ENDTRY |
| 240 | // |
| 241 | // |
| 242 | // struct Param { ... local variables used in try block and filter ... } param; |
| 243 | // PAL_TRY(Param *, pParam, ¶m) { |
| 244 | // .... |
| 245 | // } PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { |
| 246 | // .... |
| 247 | // } |
| 248 | // PAL_ENDTRY |
| 249 | // |
| 250 | // |
| 251 | // LONG MyFilter(PEXCEPTION_POINTERS *pExceptionInfo, PVOID pv) |
| 252 | // { |
| 253 | // ... |
| 254 | // } |
| 255 | // PAL_TRY(void *, unused, NULL) { |
| 256 | // .... |
| 257 | // } PAL_EXCEPT_FILTER(MyFilter) { |
| 258 | // .... |
| 259 | // } |
| 260 | // PAL_ENDTRY |
| 261 | // |
| 262 | // |
| 263 | // Complex example: |
| 264 | // |
| 265 | // struct MyParams |
| 266 | // { |
| 267 | // ... |
| 268 | // } params; |
| 269 | // |
| 270 | // PAL_TRY(MyParams *, pMyParamsOuter, ¶ms) { |
| 271 | // PAL_TRY(MyParams *, pMyParamsInnter, pMyParamsOuter) { |
| 272 | // ... |
| 273 | // if (error) goto Done; |
| 274 | // ... |
| 275 | // Done: ; |
| 276 | // } PAL_EXCEPT_FILTER(OtherFilter) { |
| 277 | // ... |
| 278 | // } |
| 279 | // PAL_ENDTRY |
| 280 | // } |
| 281 | // PAL_FINALLY { |
| 282 | // } |
| 283 | // PAL_ENDTRY |
| 284 | // |
| 285 | |
| 286 | #include "staticcontract.h" |
| 287 | |
| 288 | #define HardwareExceptionHolder |
| 289 | |
| 290 | // Note: PAL_SEH_RESTORE_GUARD_PAGE is only ever defined in clrex.h, so we only restore guard pages automatically |
| 291 | // when these macros are used from within the VM. |
| 292 | #define PAL_SEH_RESTORE_GUARD_PAGE |
| 293 | |
| 294 | #define PAL_TRY_NAKED \ |
| 295 | { \ |
| 296 | bool __exHandled; __exHandled = false; \ |
| 297 | DWORD __exCode; __exCode = 0; \ |
| 298 | SCAN_EHMARKER(); \ |
| 299 | __try \ |
| 300 | { \ |
| 301 | SCAN_EHMARKER_TRY(); |
| 302 | |
| 303 | #define PAL_EXCEPT_NAKED(Disposition) \ |
| 304 | } \ |
| 305 | __except(__exCode = GetExceptionCode(), Disposition) \ |
| 306 | { \ |
| 307 | __exHandled = true; \ |
| 308 | SCAN_EHMARKER_CATCH(); \ |
| 309 | PAL_SEH_RESTORE_GUARD_PAGE |
| 310 | |
| 311 | #define PAL_EXCEPT_FILTER_NAKED(pfnFilter, param) \ |
| 312 | } \ |
| 313 | __except(__exCode = GetExceptionCode(), \ |
| 314 | pfnFilter(GetExceptionInformation(), param)) \ |
| 315 | { \ |
| 316 | __exHandled = true; \ |
| 317 | SCAN_EHMARKER_CATCH(); \ |
| 318 | PAL_SEH_RESTORE_GUARD_PAGE |
| 319 | |
| 320 | #define PAL_FINALLY_NAKED \ |
| 321 | } \ |
| 322 | __finally \ |
| 323 | { \ |
| 324 | |
| 325 | #define PAL_ENDTRY_NAKED \ |
| 326 | } \ |
| 327 | PAL_ENDTRY_NAKED_DBG \ |
| 328 | } \ |
| 329 | |
| 330 | |
| 331 | #if defined(_DEBUG) && !defined(DACCESS_COMPILE) |
| 332 | // |
| 333 | // In debug mode, compile the try body as a method of a local class. |
| 334 | // This way, the compiler will check that the body is not directly |
| 335 | // accessing any local variables and arguments. |
| 336 | // |
| 337 | #define PAL_TRY(__ParamType, __paramDef, __paramRef) \ |
| 338 | { \ |
| 339 | __ParamType __param = __paramRef; \ |
| 340 | __ParamType __paramToPassToFilter = __paramRef; \ |
| 341 | class __Body \ |
| 342 | { \ |
| 343 | public: \ |
| 344 | static void Run(__ParamType __paramDef) \ |
| 345 | { \ |
| 346 | PAL_TRY_HANDLER_DBG_BEGIN |
| 347 | |
| 348 | // PAL_TRY implementation that abstracts usage of COMPILER_INSTANCE*, which is used by |
| 349 | // JIT64. On Windows, we dont need to do anything special as we dont have nested classes/methods |
| 350 | // as on PAL. |
| 351 | #define PAL_TRY_CI(__ParamType, __paramDef, __paramRef) \ |
| 352 | { \ |
| 353 | struct __HandlerData { \ |
| 354 | __ParamType __param; \ |
| 355 | COMPILER_INSTANCE *__ciPtr; \ |
| 356 | }; \ |
| 357 | __HandlerData handlerData; \ |
| 358 | handlerData.__param = __paramRef; \ |
| 359 | handlerData.__ciPtr = ciPtr; \ |
| 360 | __HandlerData* __param = &handlerData; \ |
| 361 | __ParamType __paramToPassToFilter = __paramRef; \ |
| 362 | class __Body \ |
| 363 | { \ |
| 364 | public: \ |
| 365 | static void Run(__HandlerData* __pHandlerData) \ |
| 366 | { \ |
| 367 | PAL_TRY_HANDLER_DBG_BEGIN \ |
| 368 | COMPILER_INSTANCE *ciPtr = __pHandlerData->__ciPtr; \ |
| 369 | __ParamType __paramDef = __pHandlerData->__param; |
| 370 | |
| 371 | |
| 372 | #define PAL_TRY_FOR_DLLMAIN(__ParamType, __paramDef, __paramRef, __reason) \ |
| 373 | { \ |
| 374 | __ParamType __param = __paramRef; \ |
| 375 | __ParamType __paramToPassToFilter = __paramRef; \ |
| 376 | class __Body \ |
| 377 | { \ |
| 378 | public: \ |
| 379 | static void Run(__ParamType __paramDef) \ |
| 380 | { \ |
| 381 | PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(__reason) |
| 382 | |
| 383 | #define PAL_EXCEPT(Disposition) \ |
| 384 | PAL_TRY_HANDLER_DBG_END \ |
| 385 | } \ |
| 386 | }; \ |
| 387 | PAL_TRY_NAKED \ |
| 388 | __Body::Run(__param); \ |
| 389 | PAL_EXCEPT_NAKED(Disposition) |
| 390 | |
| 391 | #define PAL_EXCEPT_FILTER(pfnFilter) \ |
| 392 | PAL_TRY_HANDLER_DBG_END \ |
| 393 | } \ |
| 394 | }; \ |
| 395 | PAL_TRY_NAKED \ |
| 396 | __Body::Run(__param); \ |
| 397 | PAL_EXCEPT_FILTER_NAKED(pfnFilter, __paramToPassToFilter) |
| 398 | |
| 399 | #define PAL_FINALLY \ |
| 400 | PAL_TRY_HANDLER_DBG_END \ |
| 401 | } \ |
| 402 | }; \ |
| 403 | PAL_TRY_NAKED \ |
| 404 | __Body::Run(__param); \ |
| 405 | PAL_FINALLY_NAKED |
| 406 | |
| 407 | #define PAL_ENDTRY \ |
| 408 | PAL_ENDTRY_NAKED \ |
| 409 | } |
| 410 | |
| 411 | #else // _DEBUG |
| 412 | |
| 413 | #define PAL_TRY(__ParamType, __paramDef, __paramRef) \ |
| 414 | { \ |
| 415 | __ParamType __param = __paramRef; \ |
| 416 | __ParamType __paramDef = __param; \ |
| 417 | PAL_TRY_NAKED \ |
| 418 | PAL_TRY_HANDLER_DBG_BEGIN |
| 419 | |
| 420 | // PAL_TRY implementation that abstracts usage of COMPILER_INSTANCE*, which is used by |
| 421 | // JIT64. On Windows, we dont need to do anything special as we dont have nested classes/methods |
| 422 | // as on PAL. |
| 423 | #define PAL_TRY_CI(__ParamType, __paramDef, __paramRef) PAL_TRY(__ParamType, __paramDef, __paramRef) |
| 424 | |
| 425 | #define PAL_TRY_FOR_DLLMAIN(__ParamType, __paramDef, __paramRef, __reason) \ |
| 426 | { \ |
| 427 | __ParamType __param = __paramRef; \ |
| 428 | __ParamType __paramDef; __paramDef = __param; \ |
| 429 | PAL_TRY_NAKED \ |
| 430 | PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(__reason) |
| 431 | |
| 432 | #define PAL_EXCEPT(Disposition) \ |
| 433 | PAL_TRY_HANDLER_DBG_END \ |
| 434 | PAL_EXCEPT_NAKED(Disposition) |
| 435 | |
| 436 | #define PAL_EXCEPT_FILTER(pfnFilter) \ |
| 437 | PAL_TRY_HANDLER_DBG_END \ |
| 438 | PAL_EXCEPT_FILTER_NAKED(pfnFilter, __param) |
| 439 | |
| 440 | #define PAL_FINALLY \ |
| 441 | PAL_TRY_HANDLER_DBG_END \ |
| 442 | PAL_FINALLY_NAKED |
| 443 | |
| 444 | #define PAL_ENDTRY \ |
| 445 | PAL_ENDTRY_NAKED \ |
| 446 | } |
| 447 | |
| 448 | #endif // _DEBUG |
| 449 | |
| 450 | // Executes the handler if the specified exception code matches |
| 451 | // the one in the exception. Otherwise, returns EXCEPTION_CONTINUE_SEARCH. |
| 452 | #define PAL_EXCEPT_IF_EXCEPTION_CODE(dwExceptionCode) PAL_EXCEPT((GetExceptionCode() == dwExceptionCode)?EXCEPTION_EXECUTE_HANDLER:EXCEPTION_CONTINUE_SEARCH) |
| 453 | |
| 454 | #define PAL_CPP_TRY try |
| 455 | #define PAL_CPP_ENDTRY |
| 456 | #define PAL_CPP_THROW(type, obj) do { SCAN_THROW_MARKER; throw obj; } while (false) |
| 457 | #define PAL_CPP_RETHROW do { SCAN_THROW_MARKER; throw; } while (false) |
| 458 | #define PAL_CPP_CATCH_DERIVED(type, obj) catch (type * obj) |
| 459 | #define PAL_CPP_CATCH_ALL catch (...) |
| 460 | #define PAL_CPP_CATCH_EXCEPTION_NOARG catch (Exception *) |
| 461 | |
| 462 | |
| 463 | // SELECTANY macro is intended to prevent duplication of static const |
| 464 | // arrays declared in .h files in binary modules. |
| 465 | // The problem is that const variables have static internal linkage |
| 466 | // in C++. That means that if a const variable is declared in a .h file |
| 467 | // the compiler will emit it into every translation unit that uses that .h file. |
| 468 | // That will cause duplication of the data when those translation units |
| 469 | // are linked into a binary module. |
| 470 | // SELECTANY declares a variable as extern to give it external linkage |
| 471 | // and it provides __declspec(selectany) to instruct the linker to merge |
| 472 | // duplicate external const static data copies into one. |
| 473 | // |
| 474 | #if defined(SOURCE_FORMATTING) |
| 475 | #define SELECTANY extern |
| 476 | #else |
| 477 | #define SELECTANY extern __declspec(selectany) |
| 478 | #endif |
| 479 | #if defined(SOURCE_FORMATTING) |
| 480 | #define __annotation(x) |
| 481 | #endif |
| 482 | |
| 483 | |
| 484 | #if defined(_DEBUG_IMPL) && !defined(JIT_BUILD) && !defined(JIT64_BUILD) && !defined(CROSS_COMPILE) && !defined(_TARGET_ARM_) // @ARMTODO: no contracts for speed |
| 485 | #define PAL_TRY_HANDLER_DBG_BEGIN \ |
| 486 | BOOL ___oldOkayToThrowValue = FALSE; \ |
| 487 | SO_INFRASTRUCTURE_CODE(BOOL ___oldSOTolerantState = FALSE;) \ |
| 488 | ClrDebugState *___pState = ::GetClrDebugState(); \ |
| 489 | __try \ |
| 490 | { \ |
| 491 | ___oldOkayToThrowValue = ___pState->IsOkToThrow(); \ |
| 492 | SO_INFRASTRUCTURE_CODE(___oldSOTolerantState = ___pState->IsSOTolerant();) \ |
| 493 | ___pState->SetOkToThrow(); \ |
| 494 | PAL_ENTER_THROWS_REGION; |
| 495 | |
| 496 | // Special version that avoids touching the debug state after doing work in a DllMain for process or thread detach. |
| 497 | #define PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(_reason) \ |
| 498 | BOOL ___oldOkayToThrowValue = FALSE; \ |
| 499 | SO_INFRASTRUCTURE_CODE(BOOL ___oldSOTolerantState = FALSE;) \ |
| 500 | ClrDebugState *___pState = NULL; \ |
| 501 | if (_reason != DLL_PROCESS_ATTACH) \ |
| 502 | ___pState = CheckClrDebugState(); \ |
| 503 | __try \ |
| 504 | { \ |
| 505 | if (___pState) \ |
| 506 | { \ |
| 507 | ___oldOkayToThrowValue = ___pState->IsOkToThrow(); \ |
| 508 | SO_INFRASTRUCTURE_CODE(___oldSOTolerantState = ___pState->IsSOTolerant();) \ |
| 509 | ___pState->SetOkToThrow(); \ |
| 510 | } \ |
| 511 | if ((_reason == DLL_PROCESS_DETACH) || (_reason == DLL_THREAD_DETACH)) \ |
| 512 | { \ |
| 513 | ___pState = NULL; \ |
| 514 | } \ |
| 515 | PAL_ENTER_THROWS_REGION; |
| 516 | |
| 517 | #define PAL_TRY_HANDLER_DBG_END \ |
| 518 | PAL_LEAVE_THROWS_REGION \ |
| 519 | } \ |
| 520 | __finally \ |
| 521 | { \ |
| 522 | if (___pState != NULL) \ |
| 523 | { \ |
| 524 | _ASSERTE(___pState == CheckClrDebugState()); \ |
| 525 | ___pState->SetOkToThrow( ___oldOkayToThrowValue ); \ |
| 526 | SO_INFRASTRUCTURE_CODE(___pState->SetSOTolerance( ___oldSOTolerantState );) \ |
| 527 | } \ |
| 528 | } |
| 529 | |
| 530 | #define PAL_ENDTRY_NAKED_DBG \ |
| 531 | if (__exHandled) \ |
| 532 | { \ |
| 533 | RESTORE_SO_TOLERANCE_STATE; \ |
| 534 | } \ |
| 535 | |
| 536 | #else |
| 537 | #define PAL_TRY_HANDLER_DBG_BEGIN ANNOTATION_TRY_BEGIN; |
| 538 | #define PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(_reason) ANNOTATION_TRY_BEGIN; |
| 539 | #define PAL_TRY_HANDLER_DBG_END ANNOTATION_TRY_END; |
| 540 | #define PAL_ENDTRY_NAKED_DBG |
| 541 | #endif // defined(ENABLE_CONTRACTS_IMPL) && !defined(JIT64_BUILD) |
| 542 | |
| 543 | |
| 544 | #if !BIGENDIAN |
| 545 | // For little-endian machines, do nothing |
| 546 | #define VAL16(x) x |
| 547 | #define VAL32(x) x |
| 548 | #define VAL64(x) x |
| 549 | #define SwapString(x) |
| 550 | #define SwapStringLength(x, y) |
| 551 | #define SwapGuid(x) |
| 552 | #endif // !BIGENDIAN |
| 553 | |
| 554 | #ifdef _MSC_VER |
| 555 | // Get Unaligned values from a potentially unaligned object |
| 556 | #define GET_UNALIGNED_16(_pObject) (*(UINT16 UNALIGNED *)(_pObject)) |
| 557 | #define GET_UNALIGNED_32(_pObject) (*(UINT32 UNALIGNED *)(_pObject)) |
| 558 | #define GET_UNALIGNED_64(_pObject) (*(UINT64 UNALIGNED *)(_pObject)) |
| 559 | |
| 560 | // Set Value on an potentially unaligned object |
| 561 | #define SET_UNALIGNED_16(_pObject, _Value) (*(UNALIGNED UINT16 *)(_pObject)) = (UINT16)(_Value) |
| 562 | #define SET_UNALIGNED_32(_pObject, _Value) (*(UNALIGNED UINT32 *)(_pObject)) = (UINT32)(_Value) |
| 563 | #define SET_UNALIGNED_64(_pObject, _Value) (*(UNALIGNED UINT64 *)(_pObject)) = (UINT64)(_Value) |
| 564 | |
| 565 | // Get Unaligned values from a potentially unaligned object and swap the value |
| 566 | #define GET_UNALIGNED_VAL16(_pObject) VAL16(GET_UNALIGNED_16(_pObject)) |
| 567 | #define GET_UNALIGNED_VAL32(_pObject) VAL32(GET_UNALIGNED_32(_pObject)) |
| 568 | #define GET_UNALIGNED_VAL64(_pObject) VAL64(GET_UNALIGNED_64(_pObject)) |
| 569 | |
| 570 | // Set a swap Value on an potentially unaligned object |
| 571 | #define SET_UNALIGNED_VAL16(_pObject, _Value) SET_UNALIGNED_16(_pObject, VAL16((UINT16)_Value)) |
| 572 | #define SET_UNALIGNED_VAL32(_pObject, _Value) SET_UNALIGNED_32(_pObject, VAL32((UINT32)_Value)) |
| 573 | #define SET_UNALIGNED_VAL64(_pObject, _Value) SET_UNALIGNED_64(_pObject, VAL64((UINT64)_Value)) |
| 574 | #endif |
| 575 | |
| 576 | #ifdef _WIN64 |
| 577 | #define VALPTR(x) VAL64(x) |
| 578 | #define GET_UNALIGNED_PTR(x) GET_UNALIGNED_64(x) |
| 579 | #define GET_UNALIGNED_VALPTR(x) GET_UNALIGNED_VAL64(x) |
| 580 | #define SET_UNALIGNED_PTR(p,x) SET_UNALIGNED_64(p,x) |
| 581 | #define SET_UNALIGNED_VALPTR(p,x) SET_UNALIGNED_VAL64(p,x) |
| 582 | #else |
| 583 | #define VALPTR(x) VAL32(x) |
| 584 | #define GET_UNALIGNED_PTR(x) GET_UNALIGNED_32(x) |
| 585 | #define GET_UNALIGNED_VALPTR(x) GET_UNALIGNED_VAL32(x) |
| 586 | #define SET_UNALIGNED_PTR(p,x) SET_UNALIGNED_32(p,x) |
| 587 | #define SET_UNALIGNED_VALPTR(p,x) SET_UNALIGNED_VAL32(p,x) |
| 588 | #endif |
| 589 | |
| 590 | #define MAKEDLLNAME_W(name) name W(".dll") |
| 591 | #define MAKEDLLNAME_A(name) name ".dll" |
| 592 | |
| 593 | #ifdef UNICODE |
| 594 | #define MAKEDLLNAME(x) MAKEDLLNAME_W(x) |
| 595 | #else |
| 596 | #define MAKEDLLNAME(x) MAKEDLLNAME_A(x) |
| 597 | #endif |
| 598 | |
| 599 | #if !defined(MAX_LONGPATH) |
| 600 | #define MAX_LONGPATH 260 /* max. length of full pathname */ |
| 601 | #endif |
| 602 | #if !defined(MAX_PATH_FNAME) |
| 603 | #define MAX_PATH_FNAME MAX_PATH /* max. length of full pathname */ |
| 604 | #endif |
| 605 | |
| 606 | #define __clr_reserved __reserved |
| 607 | |
| 608 | #endif // __PALCLR_H__ |
| 609 | |
| 610 | #include "palclr_win.h" |
| 611 | |
| 612 | #endif // !defined(FEATURE_PAL) |
| 613 | |