blob: 4c2f14acd4cad7f26e9446df38f6def8cf816f15 [file]
//-------------------------------------------------------------------------------------------------------
// 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 <windows.h>
/* 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 <wchar.h>
#include <math.h>
#include <time.h>
#if defined(_AMD64_) || defined(__i686__)
#include <smmintrin.h>
#include <xmmintrin.h>
#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 <cpuid.h>
inline int get_cpuid(int cpuInfo[4], int function_id)
{
return __get_cpuid(
static_cast<unsigned int>(function_id),
reinterpret_cast<unsigned int*>(&cpuInfo[0]),
reinterpret_cast<unsigned int*>(&cpuInfo[1]),
reinterpret_cast<unsigned int*>(&cpuInfo[2]),
reinterpret_cast<unsigned int*>(&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 <typename _CountofType, size_t _SizeOfArray>
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 <class T>
inline T InterlockedExchangeAdd(
IN OUT T volatile *Addend,
IN T Value)
{
return __sync_fetch_and_add(Addend, Value);
}
template <class T>
inline T InterlockedExchangeSubtract(
IN OUT T volatile *Addend,
IN T Value)
{
return __sync_fetch_and_sub(Addend, Value);
}
template <class T>
inline T InterlockedIncrement(
IN OUT T volatile *Addend)
{
return __sync_add_and_fetch(Addend, T(1));
}
template <class T>
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 <size_t size>
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 <intsafe.h>
#else
#include <stdint.h>
#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 <class TryFunc, class FinallyFunc>
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"