//------------------------------------------------------------------------------------------------------- // Copyright (C) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. //------------------------------------------------------------------------------------------------------- #pragma once #define __MAKE_WARNING__(X) "This compiler does not support '" ## X ## "'" // Define _ALWAYSINLINE for template that want to always inline, but doesn't allow inline linkage in clang #if defined(__GNUC__) || defined(__clang__) #if __has_attribute(always_inline) #define _ALWAYSINLINE __attribute__((always_inline)) #define __forceinline inline _ALWAYSINLINE #else // No always_inline support #pragma message __MAKE_WARNING__("always_inline") #define _ALWAYSINLINE inline #define __forceinline _ALWAYSINLINE #endif #if __has_attribute(noinline) #ifdef CLANG_HAS_DISABLE_TAIL_CALLS #define _NOINLINE __attribute__((noinline, disable_tail_calls)) #else #define _NOINLINE __attribute__((noinline)) #endif #else // No noinline support #pragma message __MAKE_WARNING__("noinline") #define _NOINLINE #endif #else // Windows #define _ALWAYSINLINE __forceinline #define _NOINLINE __declspec(noinline) #define __forceinline inline #endif // Only VC compiler support overflow guard #if defined(__GNUC__) || defined(__clang__) #define DECLSPEC_GUARD_OVERFLOW #else // Windows #define DECLSPEC_GUARD_OVERFLOW __declspec(guard(overflow)) #endif #ifdef __clang__ #define CLANG_WNO_BEGIN_(x) \ _Pragma("clang diagnostic push")\ _Pragma(#x) #define CLANG_WNO_BEGIN(x) CLANG_WNO_BEGIN_(clang diagnostic ignored x) #define CLANG_WNO_END _Pragma("clang diagnostic pop") #else #define CLANG_WNO_BEGIN(x) #define CLANG_WNO_END #endif #ifndef __has_builtin #define __has_builtin(x) 0 #endif #ifdef _WIN32 #pragma warning(push) #pragma warning(disable: 4995) /* 'function': name was marked as #pragma deprecated */ // === Windows Header Files === #define INC_OLE2 /* for windows.h */ #define CONST_VTABLE /* for objbase.h */ #include /* Don't want GetObject and GetClassName to be defined to GetObjectW and GetClassNameW */ #undef GetObject #undef GetClassName #undef Yield /* winbase.h defines this but we want to use it for Js::OpCode::Yield; it is Win16 legacy, no harm undef'ing it */ #pragma warning(pop) // xplat-todo: get a better name for this macro #define _u(s) L##s #define INIT_PRIORITY(x) #define get_cpuid __cpuid #if defined(__clang__) __forceinline void __int2c() { __asm int 0x2c } #endif #else // !_WIN32 #define USING_PAL_STDLIB 1 #define STRSAFE_INLINE 1 #ifdef PAL_STDCPP_COMPAT #include #include #include #if defined(_AMD64_) || defined(__i686__) #include #include #endif // defined(_AMD64_) || defined(__i686__) #endif #include "inc/pal.h" #include "inc/rt/palrt.h" #include "inc/rt/no_sal2.h" #include "inc/rt/oaidl.h" #define _u(s) u##s typedef GUID UUID; #define INIT_PRIORITY(x) __attribute__((init_priority(x))) #ifdef PAL_STDCPP_COMPAT #define __in #define __out #define FILE PAL_FILE #endif #if defined(_AMD64_) || defined(__i686__) // xplat-todo: verify below is correct #include inline int get_cpuid(int cpuInfo[4], int function_id) { return __get_cpuid( static_cast(function_id), reinterpret_cast(&cpuInfo[0]), reinterpret_cast(&cpuInfo[1]), reinterpret_cast(&cpuInfo[2]), reinterpret_cast(&cpuInfo[3])); } #elif defined(_ARM_) inline int get_cpuid(int cpuInfo[4], int function_id) { int empty[4] = {0}; memcpy(cpuInfo, empty, sizeof(int) * 4); // xplat-todo: implement me!! } #endif inline void DebugBreak() { __builtin_trap(); } #define EXIT_FAILURE 1 #define _BitScanForward BitScanForward #define _BitScanForward64 BitScanForward64 #define _BitScanReverse BitScanReverse #define _BitScanReverse64 BitScanReverse64 #define _bittest BitTest #define _bittestandset BitTestAndSet #define _interlockedbittestandset InterlockedBitTestAndSet #define DbgRaiseAssertionFailure() __builtin_trap() // These are not available in pal #define fwprintf_s fwprintf // PAL LoadLibraryExW not supported #define LOAD_LIBRARY_SEARCH_SYSTEM32 0 // winnt.h #define FAST_FAIL_INVALID_ARG 5 // winerror.h #define FACILITY_JSCRIPT 2306 #define JSCRIPT_E_CANTEXECUTE _HRESULT_TYPEDEF_(0x89020001L) #define DISP_E_UNKNOWNINTERFACE _HRESULT_TYPEDEF_(0x80020001L) #define DISP_E_MEMBERNOTFOUND _HRESULT_TYPEDEF_(0x80020003L) #define DISP_E_UNKNOWNNAME _HRESULT_TYPEDEF_(0x80020006L) #define DISP_E_NONAMEDARGS _HRESULT_TYPEDEF_(0x80020007L) #define DISP_E_EXCEPTION _HRESULT_TYPEDEF_(0x80020009L) #define DISP_E_BADINDEX _HRESULT_TYPEDEF_(0x8002000BL) #define DISP_E_UNKNOWNLCID _HRESULT_TYPEDEF_(0x8002000CL) #define DISP_E_ARRAYISLOCKED _HRESULT_TYPEDEF_(0x8002000DL) #define DISP_E_BADPARAMCOUNT _HRESULT_TYPEDEF_(0x8002000EL) #define DISP_E_PARAMNOTOPTIONAL _HRESULT_TYPEDEF_(0x8002000FL) #define DISP_E_NOTACOLLECTION _HRESULT_TYPEDEF_(0x80020011L) #define TYPE_E_DLLFUNCTIONNOTFOUND _HRESULT_TYPEDEF_(0x8002802FL) #define TYPE_E_TYPEMISMATCH _HRESULT_TYPEDEF_(0x80028CA0L) #define TYPE_E_OUTOFBOUNDS _HRESULT_TYPEDEF_(0x80028CA1L) #define TYPE_E_IOERROR _HRESULT_TYPEDEF_(0x80028CA2L) #define TYPE_E_CANTCREATETMPFILE _HRESULT_TYPEDEF_(0x80028CA3L) #define TYPE_E_CANTLOADLIBRARY _HRESULT_TYPEDEF_(0x80029C4AL) #define STG_E_TOOMANYOPENFILES _HRESULT_TYPEDEF_(0x80030004L) #define STG_E_ACCESSDENIED _HRESULT_TYPEDEF_(0x80030005L) #define STG_E_INSUFFICIENTMEMORY _HRESULT_TYPEDEF_(0x80030008L) #define STG_E_NOMOREFILES _HRESULT_TYPEDEF_(0x80030012L) #define STG_E_DISKISWRITEPROTECTED _HRESULT_TYPEDEF_(0x80030013L) #define STG_E_READFAULT _HRESULT_TYPEDEF_(0x8003001EL) #define STG_E_SHAREVIOLATION _HRESULT_TYPEDEF_(0x80030020L) #define STG_E_LOCKVIOLATION _HRESULT_TYPEDEF_(0x80030021L) #define STG_E_MEDIUMFULL _HRESULT_TYPEDEF_(0x80030070L) #define STG_E_INVALIDNAME _HRESULT_TYPEDEF_(0x800300FCL) #define STG_E_INUSE _HRESULT_TYPEDEF_(0x80030100L) #define STG_E_NOTCURRENT _HRESULT_TYPEDEF_(0x80030101L) #define STG_E_CANTSAVE _HRESULT_TYPEDEF_(0x80030103L) #define REGDB_E_CLASSNOTREG _HRESULT_TYPEDEF_(0x80040154L) #define MK_E_UNAVAILABLE _HRESULT_TYPEDEF_(0x800401E3L) #define MK_E_INVALIDEXTENSION _HRESULT_TYPEDEF_(0x800401E6L) #define MK_E_CANTOPENFILE _HRESULT_TYPEDEF_(0x800401EAL) #define CO_E_APPNOTFOUND _HRESULT_TYPEDEF_(0x800401F5L) #define CO_E_APPDIDNTREG _HRESULT_TYPEDEF_(0x800401FEL) #define GetScode(hr) ((SCODE) (hr)) // activscp.h #define SCRIPT_E_RECORDED _HRESULT_TYPEDEF_(0x86664004L) #define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS (0x00000004) typedef enum tagBREAKPOINT_STATE { BREAKPOINT_DELETED = 0, BREAKPOINT_DISABLED = 1, BREAKPOINT_ENABLED = 2 } BREAKPOINT_STATE; typedef enum tagBREAKRESUME_ACTION { BREAKRESUMEACTION_ABORT = 0, BREAKRESUMEACTION_CONTINUE = ( BREAKRESUMEACTION_ABORT + 1 ) , BREAKRESUMEACTION_STEP_INTO = ( BREAKRESUMEACTION_CONTINUE + 1 ) , BREAKRESUMEACTION_STEP_OVER = ( BREAKRESUMEACTION_STEP_INTO + 1 ) , BREAKRESUMEACTION_STEP_OUT = ( BREAKRESUMEACTION_STEP_OVER + 1 ) , BREAKRESUMEACTION_IGNORE = ( BREAKRESUMEACTION_STEP_OUT + 1 ) , BREAKRESUMEACTION_STEP_DOCUMENT = ( BREAKRESUMEACTION_IGNORE + 1 ) } BREAKRESUMEACTION; enum tagDBGPROP_ATTRIB_FLAGS { DBGPROP_ATTRIB_NO_ATTRIB= 0, DBGPROP_ATTRIB_VALUE_IS_INVALID= 0x8, DBGPROP_ATTRIB_VALUE_IS_EXPANDABLE= 0x10, DBGPROP_ATTRIB_VALUE_IS_FAKE= 0x20, DBGPROP_ATTRIB_VALUE_IS_METHOD= 0x100, DBGPROP_ATTRIB_VALUE_IS_EVENT= 0x200, DBGPROP_ATTRIB_VALUE_IS_RAW_STRING= 0x400, DBGPROP_ATTRIB_VALUE_READONLY= 0x800, DBGPROP_ATTRIB_ACCESS_PUBLIC= 0x1000, DBGPROP_ATTRIB_ACCESS_PRIVATE= 0x2000, DBGPROP_ATTRIB_ACCESS_PROTECTED= 0x4000, DBGPROP_ATTRIB_ACCESS_FINAL= 0x8000, DBGPROP_ATTRIB_STORAGE_GLOBAL= 0x10000, DBGPROP_ATTRIB_STORAGE_STATIC= 0x20000, DBGPROP_ATTRIB_STORAGE_FIELD= 0x40000, DBGPROP_ATTRIB_STORAGE_VIRTUAL= 0x80000, DBGPROP_ATTRIB_TYPE_IS_CONSTANT= 0x100000, DBGPROP_ATTRIB_TYPE_IS_SYNCHRONIZED= 0x200000, DBGPROP_ATTRIB_TYPE_IS_VOLATILE= 0x400000, DBGPROP_ATTRIB_HAS_EXTENDED_ATTRIBS= 0x800000, DBGPROP_ATTRIB_FRAME_INTRYBLOCK= 0x1000000, DBGPROP_ATTRIB_FRAME_INCATCHBLOCK= 0x2000000, DBGPROP_ATTRIB_FRAME_INFINALLYBLOCK= 0x4000000, DBGPROP_ATTRIB_VALUE_IS_RETURN_VALUE= 0x8000000 }; typedef DWORD DBGPROP_ATTRIB_FLAGS; enum tagDBGPROP_INFO_FLAgS { DBGPROP_INFO_NAME= 0x1, DBGPROP_INFO_TYPE= 0x2, DBGPROP_INFO_VALUE= 0x4, DBGPROP_INFO_FULLNAME= 0x20, DBGPROP_INFO_ATTRIBUTES= 0x8, DBGPROP_INFO_DEBUGPROP= 0x10, DBGPROP_INFO_BEAUTIFY= 0x2000000, DBGPROP_INFO_CALLTOSTRING= 0x4000000, DBGPROP_INFO_AUTOEXPAND= 0x800000 }; typedef DWORD DBGPROP_INFO_FLAGS; #define DBGPROP_INFO_STANDARD ((((DBGPROP_INFO_NAME | DBGPROP_INFO_TYPE) | DBGPROP_INFO_VALUE) | DBGPROP_INFO_ATTRIBUTES)) #define DBGPROP_INFO_ALL ((((((DBGPROP_INFO_NAME | DBGPROP_INFO_TYPE ) | DBGPROP_INFO_VALUE) | DBGPROP_INFO_FULLNAME) | DBGPROP_INFO_ATTRIBUTES) | DBGPROP_INFO_DEBUGPROP)) // _countof #if defined _M_X64 || defined _M_ARM || defined _M_ARM64 #define _UNALIGNED __unaligned #else #define _UNALIGNED #endif #ifdef __cplusplus extern "C++" { template char(*__countof_helper(_UNALIGNED _CountofType(&_Array)[_SizeOfArray]))[_SizeOfArray]; #define __crt_countof(_Array) (sizeof(*__countof_helper(_Array)) + 0) } #else #define __crt_countof(_Array) (sizeof(_Array) / sizeof(_Array[0])) #endif #ifndef _countof #define _countof __crt_countof #endif // _countof #define ARRAYSIZE(A) _countof(A) // // Singly linked list structure. Can be used as either a list head, or // as link words. // typedef struct _SINGLE_LIST_ENTRY { struct _SINGLE_LIST_ENTRY *Next; } SINGLE_LIST_ENTRY, *PSINGLE_LIST_ENTRY; #if defined(_WIN64) // // The type SINGLE_LIST_ENTRY is not suitable for use with SLISTs. For // WIN64, an entry on an SLIST is required to be 16-byte aligned, while a // SINGLE_LIST_ENTRY structure has only 8 byte alignment. // // Therefore, all SLIST code should use the SLIST_ENTRY type instead of the // SINGLE_LIST_ENTRY type. // #pragma warning(push) #pragma warning(disable:4324) // structure padded due to align() typedef struct DECLSPEC_ALIGN(16) _SLIST_ENTRY { struct _SLIST_ENTRY *Next; } SLIST_ENTRY, *PSLIST_ENTRY; #pragma warning(pop) #else typedef struct _SINGLE_LIST_ENTRY SLIST_ENTRY, *PSLIST_ENTRY; #endif // _WIN64 #if defined(_AMD64_) typedef union DECLSPEC_ALIGN(16) _SLIST_HEADER { struct { // original struct ULONGLONG Alignment; ULONGLONG Region; } DUMMYSTRUCTNAME; struct { // x64 16-byte header ULONGLONG Depth : 16; ULONGLONG Sequence : 48; ULONGLONG Reserved : 4; ULONGLONG NextEntry : 60; // last 4 bits are always 0's } HeaderX64; } SLIST_HEADER, *PSLIST_HEADER; #elif defined(_X86_) typedef union _SLIST_HEADER { ULONGLONG Alignment; struct { SLIST_ENTRY Next; WORD Depth; WORD CpuId; } DUMMYSTRUCTNAME; } SLIST_HEADER, *PSLIST_HEADER; #elif defined(_ARM_) typedef union _SLIST_HEADER { ULONGLONG Alignment; struct { SLIST_ENTRY Next; WORD Depth; WORD Reserved; } DUMMYSTRUCTNAME; } SLIST_HEADER, *PSLIST_HEADER; #endif PALIMPORT VOID PALAPI InitializeSListHead(IN OUT PSLIST_HEADER ListHead); PALIMPORT PSLIST_ENTRY PALAPI InterlockedPushEntrySList(IN OUT PSLIST_HEADER ListHead, IN OUT PSLIST_ENTRY ListEntry); PALIMPORT PSLIST_ENTRY PALAPI InterlockedPopEntrySList(IN OUT PSLIST_HEADER ListHead); template inline T InterlockedExchangeAdd( IN OUT T volatile *Addend, IN T Value) { return __sync_fetch_and_add(Addend, Value); } template inline T InterlockedExchangeSubtract( IN OUT T volatile *Addend, IN T Value) { return __sync_fetch_and_sub(Addend, Value); } template inline T InterlockedIncrement( IN OUT T volatile *Addend) { return __sync_add_and_fetch(Addend, T(1)); } template inline T InterlockedDecrement( IN OUT T volatile *Addend) { return __sync_sub_and_fetch(Addend, T(1)); } inline __int64 _abs64(__int64 n) { return n < 0 ? -n : n; } int GetCurrentThreadStackLimits(ULONG_PTR* lowLimit, ULONG_PTR* highLimit); bool IsAddressOnStack(ULONG_PTR address); errno_t rand_s(unsigned int* randomValue); inline char16* wmemset(char16* wcs, char16 wc, size_t n) { while (n) { wcs[--n] = wc; } return wcs; } inline errno_t wmemcpy_s(char16* dest, size_t destSize, const char16* src, size_t count) { return memcpy_s(dest, sizeof(char16) * destSize, src, sizeof(char16) * count); } inline int _wunlink(const char16* filename) { // WARN: does not set errno when fail return DeleteFile(filename) ? 0 : -1; } template inline errno_t _wcserror_s(char16 (&buffer)[size], int errnum) { const char* str = strerror(errnum); // WARN: does not return detail errno when fail return MultiByteToWideChar(CP_ACP, 0, str, -1, buffer, size) ? 0 : -1; } #define midl_user_allocate(size) \ HeapAlloc(GetProcessHeap(), 0, (size)) #define midl_user_free(ptr) \ if (ptr != NULL) { HeapFree(GetProcessHeap(), NULL, ptr); } DWORD __cdecl CharLowerBuffW(const char16* lpsz, DWORD cchLength); DWORD __cdecl CharUpperBuffW(const char16* lpsz, DWORD cchLength); #define MAXUINT32 ((uint32_t)~((uint32_t)0)) #define MAXINT32 ((int32_t)(MAXUINT32 >> 1)) #define BYTE_MAX 0xff #define USHORT_MAX 0xffff #ifdef UNICODE #define StringCchPrintf StringCchPrintfW #endif #endif // _WIN32 // Use intsafe.h for internal builds (currently missing some files with stdint.h) #if defined(_WIN32) && defined(NTBUILD) #define ENABLE_INTSAFE_SIGNED_FUNCTIONS 1 #include #else #include #endif #if defined(_MSC_VER) && !defined(__clang__) // ms-specific keywords #define _ABSTRACT abstract // MSVC2015 does not support C++11 semantics for `typename QualifiedName` declarations // outside of template code. #define _TYPENAME #else #define _ABSTRACT #define _TYPENAME typename #endif #if (defined(_MSC_VER) && _MSC_VER < 1900) || defined(NTBUILD) // "noexcept" not supported before VS 2015 #define _NOEXCEPT_ throw() #else #define _NOEXCEPT_ noexcept #endif #ifdef _MSC_VER extern "C" PVOID _ReturnAddress(VOID); #pragma intrinsic(_ReturnAddress) extern "C" void * _AddressOfReturnAddress(void); #elif defined(__GNUC__) || defined(__clang__) #define _ReturnAddress() __builtin_return_address(0) #if !__has_builtin(_AddressOfReturnAddress) __forceinline void * _AddressOfReturnAddress() { return (void*)((char*) __builtin_frame_address(0) + sizeof(void*)); } #endif #else #error _AddressOfReturnAddress and _ReturnAddress not defined for this platform #endif // Define strsafe related types and defines for non-VC++ compilers #ifndef _MSC_VER // xplat-todo: figure out why strsafe.h includes stdio etc // which prevents me from directly including PAL's strsafe.h #ifdef __cplusplus #define _STRSAFE_EXTERN_C extern "C" #else #define _STRSAFE_EXTERN_C extern #endif // If you do not want to use these functions inline (and instead want to link w/ strsafe.lib), then // #define STRSAFE_LIB before including this header file. #if defined(STRSAFE_LIB) #define STRSAFEAPI _STRSAFE_EXTERN_C HRESULT __stdcall #pragma comment(lib, "strsafe.lib") #elif defined(STRSAFE_LIB_IMPL) #define STRSAFEAPI _STRSAFE_EXTERN_C HRESULT __stdcall #else #define STRSAFEAPI inline HRESULT __stdcall #define STRSAFE_INLINE #endif STRSAFEAPI StringCchPrintfW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszFormat, ...); STRSAFEAPI StringVPrintfWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszFormat, va_list argList); #define STRSAFE_MAX_CCH 2147483647 // max # of characters we support (same as INT_MAX) // STRSAFE error return codes // #define STRSAFE_E_INSUFFICIENT_BUFFER ((HRESULT)0x8007007AL) // 0x7A = 122L = ERROR_INSUFFICIENT_BUFFER #define STRSAFE_E_INVALID_PARAMETER ((HRESULT)0x80070057L) // 0x57 = 87L = ERROR_INVALID_PARAMETER #define STRSAFE_E_END_OF_FILE ((HRESULT)0x80070026L) // 0x26 = 38L = ERROR_HANDLE_EOF #endif // Provide the definitions for non-windows platforms #ifndef _MSC_VER STRSAFEAPI StringVPrintfWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszFormat, va_list argList) { HRESULT hr = S_OK; if (cchDest == 0) { // can not null terminate a zero-byte dest buffer hr = STRSAFE_E_INVALID_PARAMETER; } else { int iRet; size_t cchMax; // leave the last space for the null terminator cchMax = cchDest - 1; iRet = _vsnwprintf(pszDest, cchMax, pszFormat, argList); // ASSERT((iRet < 0) || (((size_t)iRet) <= cchMax)); if ((iRet < 0) || (((size_t)iRet) > cchMax)) { // need to null terminate the string pszDest += cchMax; *pszDest = _u('\0'); // we have truncated pszDest hr = STRSAFE_E_INSUFFICIENT_BUFFER; } else if (((size_t)iRet) == cchMax) { // need to null terminate the string pszDest += cchMax; *pszDest = _u('\0'); } } return hr; } STRSAFEAPI StringCchPrintfW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszFormat, ...) { HRESULT hr; if (cchDest > STRSAFE_MAX_CCH) { hr = STRSAFE_E_INVALID_PARAMETER; } else { va_list argList; va_start(argList, pszFormat); hr = StringVPrintfWorkerW(pszDest, cchDest, pszFormat, argList); va_end(argList); } return hr; } #endif #ifndef _WIN32 __inline HRESULT ULongMult(ULONG ulMultiplicand, ULONG ulMultiplier, ULONG* pulResult); #endif /* **** WARNING : finallyFunc is not allowed to raise exception ***** * **** DO NOT ADD stack probe or memory allocations within the finallyFunc **** */ template void TryFinally(const TryFunc& tryFunc, const FinallyFunc& finallyFunc) { class FinallyObject { public: FinallyObject(const FinallyFunc& finallyFunc) : finallyFunc(finallyFunc), abnormalTermination(true) {} ~FinallyObject() { finallyFunc(abnormalTermination); } void SetHasNoAbnormalTermination() { abnormalTermination = false; } private: const FinallyFunc& finallyFunc; bool abnormalTermination; } finallyObject(finallyFunc); tryFunc(); finallyObject.SetHasNoAbnormalTermination(); } #ifdef DISABLE_SEH #define __TRY_FINALLY_BEGIN TryFinally([&]() #define __FINALLY , [&](bool /* hasException */) #define __TRY_FINALLY_END ); #else #define __TRY_FINALLY_BEGIN __try #define __FINALLY __finally #define __TRY_FINALLY_END #endif namespace PlatformAgnostic { __forceinline unsigned char _BitTestAndSet(LONG *_BitBase, int _BitPos) { #if defined(__clang__) && !defined(_ARM_) // Clang doesn't expand _bittestandset intrinic to bts, and it's implemention also doesn't work for _BitPos >= 32 unsigned char retval = 0; asm( "bts %[_BitPos], %[_BitBase]\n\t" "setc %b[retval]\n\t" : [_BitBase] "+m" (*_BitBase), [retval] "+rm" (retval) : [_BitPos] "ri" (_BitPos) : "cc" // clobber condition code ); return retval; #else return _bittestandset(_BitBase, _BitPos); #endif } __forceinline unsigned char _BitTest(LONG *_BitBase, int _BitPos) { #if defined(__clang__) && !defined(_ARM_) // Clang doesn't expand _bittest intrinic to bt, and it's implemention also doesn't work for _BitPos >= 32 unsigned char retval; asm( "bt %[_BitPos], %[_BitBase]\n\t" "setc %b[retval]\n\t" : [retval] "+rm" (retval) : [_BitPos] "ri" (_BitPos), [_BitBase] "m" (*_BitBase) : "cc" // clobber condition code ); return retval; #else return _bittest(_BitBase, _BitPos); #endif } __forceinline unsigned char _InterlockedBitTestAndSet(volatile LONG *_BitBase, int _BitPos) { #if defined(__clang__) && !defined(_ARM_) // Clang doesn't expand _interlockedbittestandset intrinic to lock bts, and it's implemention also doesn't work for _BitPos >= 32 unsigned char retval; asm( "lock bts %[_BitPos], %[_BitBase]\n\t" "setc %b[retval]\n\t" : [_BitBase] "+m" (*_BitBase), [retval] "+rm" (retval) : [_BitPos] "ri" (_BitPos) : "cc" // clobber condition code ); return retval; #else return _interlockedbittestandset(_BitBase, _BitPos); #endif } __forceinline unsigned char _InterlockedBitTestAndReset(volatile LONG *_BitBase, int _BitPos) { #if defined(__clang__) && !defined(_ARM_) // Clang doesn't expand _interlockedbittestandset intrinic to lock btr, and it's implemention also doesn't work for _BitPos >= 32 unsigned char retval; asm( "lock btr %[_BitPos], %[_BitBase]\n\t" "setc %b[retval]\n\t" : [_BitBase] "+m" (*_BitBase), [retval] "+rm" (retval) : [_BitPos] "ri" (_BitPos) : "cc" // clobber condition code ); return retval; #elif !defined(__ANDROID__) return _interlockedbittestandreset(_BitBase, (long)_BitPos); #else // xplat-todo: Implement _interlockedbittestandreset for Android abort(); #endif } }; #include "PlatformAgnostic/DateTime.h" #include "PlatformAgnostic/Numbers.h" #include "PlatformAgnostic/SystemInfo.h" #include "PlatformAgnostic/Thread.h" #include "PlatformAgnostic/AssemblyCommon.h" #include "PlatformAgnostic/Debugger.h"