diff --git a/eng/native/configureplatform.cmake b/eng/native/configureplatform.cmake index 274ab363bf7905..b04bfc9ca1397c 100644 --- a/eng/native/configureplatform.cmake +++ b/eng/native/configureplatform.cmake @@ -522,7 +522,7 @@ if (CLR_CMAKE_TARGET_ANDROID OR CLR_CMAKE_TARGET_MACCATALYST OR CLR_CMAKE_TARGET set(CLR_CMAKE_USE_SYSTEM_ZLIB 1) endif() -if (NOT CLR_CMAKE_TARGET_ANDROID) +if (NOT CLR_CMAKE_TARGET_ANDROID AND NOT CLR_CMAKE_TARGET_BROWSER) # opt into building tools like ildasm/ilasm set(CLR_CMAKE_BUILD_TOOLS 1) endif() diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml index fe9c980fbb9354..1eac8b3924b036 100644 --- a/eng/pipelines/runtime.yml +++ b/eng/pipelines/runtime.yml @@ -125,7 +125,7 @@ extends: - browser_wasm jobParameters: nameSuffix: AllSubsets_CoreCLR - buildArgs: -s mono.emsdk+clr.paltests -rc Release -c Release -lc $(_BuildConfig) + buildArgs: -s mono.emsdk+clr.runtime -rc Release -c Release -lc $(_BuildConfig) timeoutInMinutes: 120 condition: >- or( diff --git a/src/coreclr/CMakeLists.txt b/src/coreclr/CMakeLists.txt index ad1cfcc279549f..ed016fad7214f1 100644 --- a/src/coreclr/CMakeLists.txt +++ b/src/coreclr/CMakeLists.txt @@ -35,6 +35,10 @@ endif() OPTION(CLR_CMAKE_ENABLE_CODE_COVERAGE "Enable code coverage" OFF) +if (DEFINED CLR_CMAKE_ICU_DIR) + include_directories(${CLR_CMAKE_ICU_DIR}/include) +endif(DEFINED CLR_CMAKE_ICU_DIR) + #---------------------------------------------------- # Cross target Component build specific configuration #---------------------------------------------------- @@ -59,7 +63,7 @@ include(components.cmake) #--------------------------- # Build the single file host #--------------------------- -if(NOT CLR_CROSS_COMPONENTS_BUILD AND NOT CLR_CMAKE_TARGET_MACCATALYST AND NOT CLR_CMAKE_TARGET_IOS AND NOT CLR_CMAKE_TARGET_TVOS) +if(NOT CLR_CROSS_COMPONENTS_BUILD AND NOT CLR_CMAKE_TARGET_MACCATALYST AND NOT CLR_CMAKE_TARGET_IOS AND NOT CLR_CMAKE_TARGET_TVOS AND NOT CLR_CMAKE_TARGET_ARCH_WASM) set(CLR_SINGLE_FILE_HOST_ONLY 1) add_subdirectory(${CLR_SRC_NATIVE_DIR}/corehost/apphost/static Corehost.Static) add_dependencies(runtime singlefilehost) @@ -267,7 +271,7 @@ if(CLR_CMAKE_HOST_UNIX) add_subdirectory(nativeresources) endif(CLR_CMAKE_HOST_UNIX) -if(NOT CLR_CMAKE_HOST_TVOS AND NOT CLR_CMAKE_HOST_BROWSER) +if(NOT CLR_CMAKE_HOST_TVOS) add_subdirectory(utilcode) add_subdirectory(inc) @@ -276,16 +280,27 @@ if(NOT CLR_CMAKE_HOST_TVOS AND NOT CLR_CMAKE_HOST_BROWSER) add_subdirectory(ildasm) endif(CLR_CMAKE_BUILD_TOOLS) add_subdirectory(gcinfo) - add_subdirectory(jit) + + if (NOT CLR_CMAKE_TARGET_ARCH_WASM) + add_subdirectory(jit) + endif() + add_subdirectory(vm) add_subdirectory(md) - add_subdirectory(debug) + + if (NOT CLR_CMAKE_TARGET_ARCH_WASM) + add_subdirectory(debug) + endif() + add_subdirectory(binder) add_subdirectory(classlibnative) add_subdirectory(dlls) - add_subdirectory(unwinder) - add_subdirectory(interop) -endif(NOT CLR_CMAKE_HOST_TVOS AND NOT CLR_CMAKE_HOST_BROWSER) + + if (NOT CLR_CMAKE_TARGET_ARCH_WASM) + add_subdirectory(unwinder) + add_subdirectory(interop) + endif() +endif(NOT CLR_CMAKE_HOST_TVOS) if(NOT CLR_CMAKE_HOST_MACCATALYST AND NOT CLR_CMAKE_HOST_IOS AND NOT CLR_CMAKE_HOST_TVOS) add_subdirectory(tools) diff --git a/src/coreclr/clrdefinitions.cmake b/src/coreclr/clrdefinitions.cmake index d5b2d29d2e5d5a..c37a4277e80b8d 100644 --- a/src/coreclr/clrdefinitions.cmake +++ b/src/coreclr/clrdefinitions.cmake @@ -58,7 +58,7 @@ if(CLR_CMAKE_HOST_WIN32) add_compile_definitions(NOMINMAX) endif(CLR_CMAKE_HOST_WIN32) -if (NOT (CLR_CMAKE_TARGET_ARCH_I386 AND CLR_CMAKE_TARGET_UNIX)) +if (NOT ((CLR_CMAKE_TARGET_ARCH_I386 AND CLR_CMAKE_TARGET_UNIX) OR CLR_CMAKE_TARGET_ARCH_WASM)) add_compile_definitions(FEATURE_METADATA_UPDATER) endif() if(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64 OR (CLR_CMAKE_TARGET_ARCH_I386 AND CLR_CMAKE_TARGET_WIN32)) @@ -119,9 +119,9 @@ if(CLR_CMAKE_TARGET_LINUX) add_definitions(-DFEATURE_EVENTSOURCE_XPLAT) endif(CLR_CMAKE_TARGET_LINUX) # NetBSD doesn't implement this feature -if(NOT CLR_CMAKE_TARGET_NETBSD) +if(NOT CLR_CMAKE_TARGET_NETBSD AND NOT CLR_CMAKE_TARGET_ARCH_WASM) add_definitions(-DFEATURE_HIJACK) -endif(NOT CLR_CMAKE_TARGET_NETBSD) +endif(NOT CLR_CMAKE_TARGET_NETBSD AND NOT CLR_CMAKE_TARGET_ARCH_WASM) if (CLR_CMAKE_TARGET_WIN32 AND (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_I386 OR CLR_CMAKE_TARGET_ARCH_ARM64)) add_definitions(-DFEATURE_INTEROP_DEBUGGING) endif (CLR_CMAKE_TARGET_WIN32 AND (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_I386 OR CLR_CMAKE_TARGET_ARCH_ARM64)) diff --git a/src/coreclr/clrfeatures.cmake b/src/coreclr/clrfeatures.cmake index d6a8965843e585..6bb761a8e0e2f8 100644 --- a/src/coreclr/clrfeatures.cmake +++ b/src/coreclr/clrfeatures.cmake @@ -52,7 +52,7 @@ if (CLR_CMAKE_TARGET_WIN32) endif(CLR_CMAKE_TARGET_WIN32) -if (CLR_CMAKE_TARGET_MACCATALYST OR CLR_CMAKE_TARGET_IOS OR CLR_CMAKE_TARGET_TVOS) +if (CLR_CMAKE_TARGET_MACCATALYST OR CLR_CMAKE_TARGET_IOS OR CLR_CMAKE_TARGET_TVOS OR CLR_CMAKE_TARGET_ARCH_WASM) set(FEATURE_CORECLR_CACHED_INTERFACE_DISPATCH 1) set(FEATURE_CORECLR_VIRTUAL_STUB_DISPATCH 0) else() diff --git a/src/coreclr/debug/inc/dbgipcevents.h b/src/coreclr/debug/inc/dbgipcevents.h index 6c39939f00307e..9ff25d86edf185 100644 --- a/src/coreclr/debug/inc/dbgipcevents.h +++ b/src/coreclr/debug/inc/dbgipcevents.h @@ -1938,6 +1938,9 @@ C_ASSERT(DBG_TARGET_REGNUM_AMBIENT_SP == ICorDebugInfo::REGNUM_AMBIENT_SP); C_ASSERT(DBG_TARGET_REGNUM_SP == ICorDebugInfo::REGNUM_SP); C_ASSERT(DBG_TARGET_REGNUM_AMBIENT_SP == ICorDebugInfo::REGNUM_AMBIENT_SP); #endif +#elif defined(TARGET_WASM) +#define DBG_TARGET_REGNUM_SP 0 +#define DBG_TARGET_REGNUM_AMBIENT_SP 0 #else #error Target registers are not defined for this platform #endif diff --git a/src/coreclr/debug/inc/dbgtargetcontext.h b/src/coreclr/debug/inc/dbgtargetcontext.h index dab7ca29c7db33..ea374cf8b6def6 100644 --- a/src/coreclr/debug/inc/dbgtargetcontext.h +++ b/src/coreclr/debug/inc/dbgtargetcontext.h @@ -58,6 +58,8 @@ #define DTCONTEXT_IS_LOONGARCH64 #elif defined (TARGET_RISCV64) #define DTCONTEXT_IS_RISCV64 +#elif defined (TARGET_WASM) +#define DTCONTEXT_IS_WASM #endif #define CONTEXT_AREA_MASK 0xffff @@ -614,6 +616,10 @@ typedef struct DECLSPEC_ALIGN(16) { static_assert(sizeof(DT_CONTEXT) == sizeof(T_CONTEXT), "DT_CONTEXT size must equal the T_CONTEXT size"); +#elif defined(DTCONTEXT_IS_WASM) +// no context for wasm +typedef struct { +} DT_CONTEXT; #else #error Unsupported platform #endif diff --git a/src/coreclr/debug/inc/wasm/primitives.h b/src/coreclr/debug/inc/wasm/primitives.h new file mode 100644 index 00000000000000..5c428fe76ceb62 --- /dev/null +++ b/src/coreclr/debug/inc/wasm/primitives.h @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +//***************************************************************************** +// File: primitives.h +// + +// +// Platform-specific debugger primitives +// +//***************************************************************************** + +#ifndef PRIMITIVES_H_ +#define PRIMITIVES_H_ + +inline CORDB_ADDRESS GetPatchEndAddr(CORDB_ADDRESS patchAddr) +{ + _ASSERTE("The function is not implemented on wasm"); + return patchAddr; +} + +typedef const BYTE CORDB_ADDRESS_TYPE; +typedef DPTR(CORDB_ADDRESS_TYPE) PTR_CORDB_ADDRESS_TYPE; + +//This is an abstraction to keep x86/ia64 patch data separate +#define PRD_TYPE USHORT + +#define MAX_INSTRUCTION_LENGTH 2 // update once we have codegen + +#define CORDbg_BREAK_INSTRUCTION_SIZE 1 +#define CORDbg_BREAK_INSTRUCTION 0 // unreachable intruction + +inline bool PRDIsEmpty(PRD_TYPE p1) +{ + LIMITED_METHOD_CONTRACT; + + return p1 == 0; +} + +#endif diff --git a/src/coreclr/dlls/CMakeLists.txt b/src/coreclr/dlls/CMakeLists.txt index 9bd79f94d6fd91..0a2ab14d8db82f 100644 --- a/src/coreclr/dlls/CMakeLists.txt +++ b/src/coreclr/dlls/CMakeLists.txt @@ -2,9 +2,13 @@ if(CLR_CMAKE_TARGET_WIN32 AND FEATURE_EVENT_TRACE) add_subdirectory(clretwrc) endif(CLR_CMAKE_TARGET_WIN32 AND FEATURE_EVENT_TRACE) if (NOT (CLR_CMAKE_TARGET_WIN32 AND FEATURE_CROSSBITNESS)) - add_subdirectory(mscordbi) - add_subdirectory(mscordac) + if (NOT CLR_CMAKE_TARGET_ARCH_WASM) + add_subdirectory(mscordbi) + add_subdirectory(mscordac) + endif() add_subdirectory(mscoree) endif() -add_subdirectory(mscorpe) +if (NOT CLR_CMAKE_TARGET_ARCH_WASM) + add_subdirectory(mscorpe) +endif() add_subdirectory(mscorrc) diff --git a/src/coreclr/gc/env/gcenv.base.h b/src/coreclr/gc/env/gcenv.base.h index 1603448ae2a4f8..94d88e46466940 100644 --- a/src/coreclr/gc/env/gcenv.base.h +++ b/src/coreclr/gc/env/gcenv.base.h @@ -143,7 +143,10 @@ typedef DWORD (WINAPI *PTHREAD_START_ROUTINE)(void* lpThreadParameter); #pragma intrinsic(__dmb) #define MemoryBarrier() { __dmb(_ARM64_BARRIER_SY); } - #elif defined(HOST_AMD64) + #elif defined(HOST_BROWSER) + #define YieldProcessor() + #define MemoryBarrier __sync_synchronize +#elif defined(HOST_AMD64) extern "C" void _mm_pause ( diff --git a/src/coreclr/gc/unix/gcenv.unix.cpp b/src/coreclr/gc/unix/gcenv.unix.cpp index 43588c66eb015a..5a199f4b7db69e 100644 --- a/src/coreclr/gc/unix/gcenv.unix.cpp +++ b/src/coreclr/gc/unix/gcenv.unix.cpp @@ -35,6 +35,9 @@ #define membarrier(...) syscall(__NR_membarrier, __VA_ARGS__) #elif HAVE_SYS_MEMBARRIER_H #include +#ifdef TARGET_BROWSER +#define membarrier(cmd, flags, cpu_id) 0 // browser/wasm is currently single threaded +#endif #endif #include diff --git a/src/coreclr/inc/check.h b/src/coreclr/inc/check.h index 21d717c13e6bb7..5a7218cc652d77 100644 --- a/src/coreclr/inc/check.h +++ b/src/coreclr/inc/check.h @@ -723,7 +723,9 @@ CHECK CheckOverflow(UINT64 value1, UINT64 value2); #ifdef __APPLE__ CHECK CheckOverflow(SIZE_T value1, SIZE_T value2); #endif +#ifndef __wasm__ CHECK CheckOverflow(PTR_CVOID address, UINT offset); +#endif #if defined(_MSC_VER) CHECK CheckOverflow(const void *address, ULONG offset); #endif diff --git a/src/coreclr/inc/check.inl b/src/coreclr/inc/check.inl index 34a2956d1be6e2..b0f65c5d218bbd 100644 --- a/src/coreclr/inc/check.inl +++ b/src/coreclr/inc/check.inl @@ -156,7 +156,7 @@ inline CHECK CheckAligned(UINT64 value, UINT alignment) CHECK_OK; } -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__wasm__) inline CHECK CheckAligned(SIZE_T value, UINT alignment) { STATIC_CONTRACT_WRAPPER; @@ -237,7 +237,7 @@ inline CHECK CheckOverflow(const void *address, UINT64 offset) CHECK_OK; } -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__wasm__) inline CHECK CheckOverflow(const void *address, SIZE_T offset) { CHECK((UINT64) address + offset >= (UINT64) address); @@ -316,10 +316,11 @@ inline CHECK CheckUnderflow(const void *address, UINT64 offset) CHECK_OK; } -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__wasm__) inline CHECK CheckUnderflow(const void *address, SIZE_T offset) { -#if POINTER_BITS == 32 + // SIZE_T is 32bit on wasm32 +#if !defined(__wasm__) && POINTER_BITS == 32 CHECK(offset >> 32 == 0); CHECK((UINT) (SIZE_T) address - (UINT) offset <= (UINT) (SIZE_T) address); #else diff --git a/src/coreclr/inc/clrnt.h b/src/coreclr/inc/clrnt.h index 2d935a95317e69..bcd4427538babe 100644 --- a/src/coreclr/inc/clrnt.h +++ b/src/coreclr/inc/clrnt.h @@ -501,4 +501,48 @@ RtlVirtualUnwind( #endif // TARGET_RISCV64 +#ifdef TARGET_WASM +// +// Define unwind information flags. +// + +#define UNW_FLAG_NHANDLER 0x0 /* any handler */ +#define UNW_FLAG_EHANDLER 0x1 /* filter handler */ +#define UNW_FLAG_UHANDLER 0x2 /* unwind handler */ + +PEXCEPTION_ROUTINE +RtlVirtualUnwind ( + _In_ DWORD HandlerType, + _In_ DWORD ImageBase, + _In_ DWORD ControlPc, + _In_ PRUNTIME_FUNCTION FunctionEntry, + __inout PT_CONTEXT ContextRecord, + _Out_ PVOID *HandlerData, + _Out_ PDWORD EstablisherFrame, + __inout_opt PT_KNONVOLATILE_CONTEXT_POINTERS ContextPointers + ); + +FORCEINLINE +ULONG +RtlpGetFunctionEndAddress ( + _In_ PT_RUNTIME_FUNCTION FunctionEntry, + _In_ TADDR ImageBase + ) +{ + _ASSERTE("The function RtlpGetFunctionEndAddress is not implemented on wasm"); + return 0; +} + +#define RUNTIME_FUNCTION__BeginAddress(FunctionEntry) ((FunctionEntry)->BeginAddress) +#define RUNTIME_FUNCTION__SetBeginAddress(FunctionEntry,address) ((FunctionEntry)->BeginAddress = (address)) + +#define RUNTIME_FUNCTION__EndAddress(FunctionEntry, ImageBase) (RtlpGetFunctionEndAddress(FunctionEntry, (ULONG64)(ImageBase))) + +#define RUNTIME_FUNCTION__SetUnwindInfoAddress(prf,address) do { (prf)->UnwindData = (address); } while (0) + +typedef struct _UNWIND_INFO { + // dummy +} UNWIND_INFO, *PUNWIND_INFO; +#endif + #endif // CLRNT_H_ diff --git a/src/coreclr/inc/clrtypes.h b/src/coreclr/inc/clrtypes.h index 9094e4932a2527..b1990054c48738 100644 --- a/src/coreclr/inc/clrtypes.h +++ b/src/coreclr/inc/clrtypes.h @@ -338,7 +338,7 @@ inline UINT64 AlignUp(UINT64 value, UINT alignment) return (value+alignment-1)&~(UINT64)(alignment-1); } -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__wasm__) inline SIZE_T AlignUp(SIZE_T value, UINT alignment) { STATIC_CONTRACT_LEAF; @@ -399,13 +399,13 @@ inline UINT AlignmentPad(UINT64 value, UINT alignment) return (UINT) (AlignUp(value, alignment) - value); } -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__wasm__) inline UINT AlignmentPad(SIZE_T value, UINT alignment) { STATIC_CONTRACT_WRAPPER; return (UINT) (AlignUp(value, alignment) - value); } -#endif // __APPLE__ +#endif // __APPLE__ || __wasm__ inline UINT AlignmentTrim(UINT value, UINT alignment) { @@ -432,7 +432,7 @@ inline UINT AlignmentTrim(UINT64 value, UINT alignment) return ((UINT)value)&(alignment-1); } -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__wasm__) inline UINT AlignmentTrim(SIZE_T value, UINT alignment) { STATIC_CONTRACT_LEAF; diff --git a/src/coreclr/inc/corcompile.h b/src/coreclr/inc/corcompile.h index 845b72465c3439..57ca94832e6be7 100644 --- a/src/coreclr/inc/corcompile.h +++ b/src/coreclr/inc/corcompile.h @@ -56,6 +56,11 @@ inline ReadyToRunCrossModuleInlineFlags operator &( const ReadyToRunCrossModuleI return static_cast(static_cast(left) & static_cast(right)); } +#ifdef TARGET_WASM +// why was it defined only for x86 before? +typedef DPTR(RUNTIME_FUNCTION) PTR_RUNTIME_FUNCTION; +#endif + #ifdef TARGET_X86 typedef DPTR(RUNTIME_FUNCTION) PTR_RUNTIME_FUNCTION; diff --git a/src/coreclr/inc/cordebuginfo.h b/src/coreclr/inc/cordebuginfo.h index b3125060f308eb..b6979c52f3ac5c 100644 --- a/src/coreclr/inc/cordebuginfo.h +++ b/src/coreclr/inc/cordebuginfo.h @@ -213,6 +213,8 @@ class ICorDebugInfo REGNUM_T5, REGNUM_T6, REGNUM_PC, +#elif TARGET_WASM + REGNUM_PC, // wasm doesn't have registers #else PORTABILITY_WARNING("Register numbers not defined on this platform") #endif diff --git a/src/coreclr/inc/crosscomp.h b/src/coreclr/inc/crosscomp.h index c3c1f97ddeedea..36081dee778ab4 100644 --- a/src/coreclr/inc/crosscomp.h +++ b/src/coreclr/inc/crosscomp.h @@ -721,6 +721,8 @@ typedef struct _T_KNONVOLATILE_CONTEXT_POINTERS { #define DAC_CS_NATIVE_DATA_SIZE 48 #elif defined(TARGET_HAIKU) && defined(TARGET_AMD64) #define DAC_CS_NATIVE_DATA_SIZE 56 +#elif defined(TARGET_WASM) +#define DAC_CS_NATIVE_DATA_SIZE 76 #else #warning #error DAC_CS_NATIVE_DATA_SIZE is not defined for this architecture. This should be same value as PAL_CS_NATIVE_DATA_SIZE (aka sizeof(PAL_CS_NATIVE_DATA)). diff --git a/src/coreclr/inc/pedecoder.h b/src/coreclr/inc/pedecoder.h index 057dfa9a25de61..6b13de957bfb93 100644 --- a/src/coreclr/inc/pedecoder.h +++ b/src/coreclr/inc/pedecoder.h @@ -89,6 +89,8 @@ inline CHECK CheckOverflow(RVA value1, COUNT_T value2) #define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_UNKNOWN #elif defined(TARGET_RISCV64) #define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_RISCV64 +#elif defined(TARGET_WASM) +#define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_UNKNOWN #else #error "port me" #endif diff --git a/src/coreclr/inc/regdisp.h b/src/coreclr/inc/regdisp.h index 07d3f1f6d5e057..3aa4be6fd9e60c 100644 --- a/src/coreclr/inc/regdisp.h +++ b/src/coreclr/inc/regdisp.h @@ -345,6 +345,25 @@ inline TADDR GetRegdisplayStackMark(REGDISPLAY *display) { return GetSP(display->pCallerContext); } +#elif defined(TARGET_WASM) +struct REGDISPLAY : public REGDISPLAY_BASE { + REGDISPLAY() + { + // Initialize + memset(this, 0, sizeof(REGDISPLAY)); + } +}; + +inline void SyncRegDisplayToCurrentContext(REGDISPLAY* pRD) +{ +} + +// This function tells us if the given stack pointer is in one of the frames of the functions called by the given frame +inline BOOL IsInCalleesFrames(REGDISPLAY *display, LPVOID stackPointer) { + _ASSERTE("IsInCalleesFrames is not implemented on wasm"); + return FALSE; +} + #else // none of the above processors #error "RegDisplay functions are not implemented on this platform." #endif diff --git a/src/coreclr/inc/switches.h b/src/coreclr/inc/switches.h index 06fdaa5f397510..9534511ef2a99d 100644 --- a/src/coreclr/inc/switches.h +++ b/src/coreclr/inc/switches.h @@ -43,7 +43,7 @@ #define GC_STATS #endif -#if defined(TARGET_X86) || defined(TARGET_ARM) +#if defined(TARGET_X86) || defined(TARGET_ARM) || defined(TARGET_BROWSER) #define USE_LAZY_PREFERRED_RANGE 0 #elif defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_S390X) || defined(TARGET_LOONGARCH64) || defined(TARGET_POWERPC64) || defined(TARGET_RISCV64) diff --git a/src/coreclr/inc/targetosarch.h b/src/coreclr/inc/targetosarch.h index 00fe5b70647e7d..217db1de7b6fa3 100644 --- a/src/coreclr/inc/targetosarch.h +++ b/src/coreclr/inc/targetosarch.h @@ -95,6 +95,14 @@ class TargetArchitecture static const bool IsArmArch = false; static const bool IsLoongArch64 = false; static const bool IsRiscV64 = true; +#elif defined(TARGET_WASM) + static const bool IsX86 = false; + static const bool IsX64 = false; + static const bool IsArm64 = false; + static const bool IsArm32 = false; + static const bool IsArmArch = false; + static const bool IsLoongArch64 = false; + static const bool IsRiscV64 = false; #else #error Unknown architecture #endif diff --git a/src/coreclr/pal/inc/pal.h b/src/coreclr/pal/inc/pal.h index c065859ce757c1..da749d1a19f71c 100644 --- a/src/coreclr/pal/inc/pal.h +++ b/src/coreclr/pal/inc/pal.h @@ -2475,7 +2475,9 @@ typedef struct _KNONVOLATILE_CONTEXT_POINTERS { #define CONTEXT_CONTROL 0 #define CONTEXT_INTEGER 0 #define CONTEXT_FLOATING_POINT 0 +#define CONTEXT_DEBUG_REGISTERS 0 #define CONTEXT_FULL 0 +#define CONTEXT_ALL 0 #define CONTEXT_XSTATE 0 diff --git a/src/coreclr/runtime.proj b/src/coreclr/runtime.proj index 7b440d5689c469..1a887cbb41e9c3 100644 --- a/src/coreclr/runtime.proj +++ b/src/coreclr/runtime.proj @@ -4,11 +4,13 @@ <_BuildNativeTargetOS>$(TargetOS) <_BuildNativeTargetOS Condition="'$(TargetsLinuxBionic)' == 'true'">linux-bionic true + <_IcuDir Condition="'$(PkgMicrosoft_NETCore_Runtime_ICU_Transport)' != '' and '$(TargetsBrowser)' == 'true'">$(PkgMicrosoft_NETCore_Runtime_ICU_Transport)/runtimes/$(TargetOS)-$(TargetArchitecture)$(_RuntimeVariant)/native + @@ -48,6 +50,7 @@ <_CoreClrBuildArg Condition="'$(BuildSubdirectory)' != ''" Include="-subdir $(BuildSubdirectory)" /> <_CoreClrBuildArg Include="-cmakeargs "-DCLR_DOTNET_HOST_PATH=$(DOTNET_HOST_PATH)"" /> <_CoreClrBuildArg Condition="'$(HasCdacBuildTool)' == 'true'" Include="-cmakeargs "-DCDAC_BUILD_TOOL_BINARY_PATH=$(RuntimeBinDir)cdac-build-tool\cdac-build-tool.dll"" /> + <_CoreClrBuildArg Condition="'$(_IcuDir)' != ''" Include="-cmakeargs "-DCLR_CMAKE_ICU_DIR=$(_IcuDir)"" /> diff --git a/src/coreclr/utilcode/CMakeLists.txt b/src/coreclr/utilcode/CMakeLists.txt index 06282d39189e56..78ae6b2b365632 100644 --- a/src/coreclr/utilcode/CMakeLists.txt +++ b/src/coreclr/utilcode/CMakeLists.txt @@ -84,7 +84,9 @@ convert_to_absolute_path(UTILCODE_SOURCES ${UTILCODE_SOURCES}) convert_to_absolute_path(UTILCODE_DAC_SOURCES ${UTILCODE_DAC_SOURCES}) convert_to_absolute_path(UTILCODE_STATICNOHOST_SOURCES ${UTILCODE_STATICNOHOST_SOURCES}) +if(NOT CLR_CMAKE_TARGET_ARCH_WASM) add_library_clr(utilcode_dac STATIC ${UTILCODE_DAC_SOURCES}) +endif() add_library_clr(utilcode OBJECT ${UTILCODE_SOURCES}) add_library_clr(utilcodestaticnohost STATIC ${UTILCODE_STATICNOHOST_SOURCES}) @@ -92,9 +94,11 @@ target_link_libraries(utilcodestaticnohost PUBLIC coreclrminipal) if(CLR_CMAKE_HOST_UNIX) target_link_libraries(utilcodestaticnohost PUBLIC nativeresourcestring) - target_link_libraries(utilcode_dac PUBLIC nativeresourcestring) + if (NOT CLR_CMAKE_TARGET_ARCH_WASM) + target_link_libraries(utilcode_dac PUBLIC nativeresourcestring) + add_dependencies(utilcode_dac coreclrpal) + endif() target_link_libraries(utilcode INTERFACE nativeresourcestring) - add_dependencies(utilcode_dac coreclrpal) add_dependencies(utilcode coreclrpal) endif(CLR_CMAKE_HOST_UNIX) @@ -107,12 +111,14 @@ if(CLR_CMAKE_HOST_WIN32) link_natvis_sources_for_target(utilcode INTERFACE utilcode.natvis) endif(CLR_CMAKE_HOST_WIN32) -set_target_properties(utilcode_dac PROPERTIES DAC_COMPONENT TRUE) -target_compile_definitions(utilcode_dac PRIVATE SELF_NO_HOST) +if (NOT CLR_CMAKE_TARGET_ARCH_WASM) + set_target_properties(utilcode_dac PROPERTIES DAC_COMPONENT TRUE) + target_compile_definitions(utilcode_dac PRIVATE SELF_NO_HOST) + add_dependencies(utilcode_dac ${UTILCODE_DEPENDENCIES}) + target_precompile_headers(utilcode_dac PRIVATE [["stdafx.h"]]) + endif() target_compile_definitions(utilcodestaticnohost PRIVATE SELF_NO_HOST) -add_dependencies(utilcode_dac ${UTILCODE_DEPENDENCIES}) add_dependencies(utilcode ${UTILCODE_DEPENDENCIES}) add_dependencies(utilcodestaticnohost ${UTILCODE_DEPENDENCIES}) -target_precompile_headers(utilcode_dac PRIVATE [["stdafx.h"]]) target_precompile_headers(utilcode PRIVATE [["stdafx.h"]]) target_precompile_headers(utilcodestaticnohost PRIVATE [["stdafx.h"]]) diff --git a/src/coreclr/vm/CMakeLists.txt b/src/coreclr/vm/CMakeLists.txt index 61a210eb37ef36..df3636832dd5b3 100644 --- a/src/coreclr/vm/CMakeLists.txt +++ b/src/coreclr/vm/CMakeLists.txt @@ -955,10 +955,12 @@ convert_to_absolute_path(VM_SOURCES_WKS_ARCH_ASM ${VM_SOURCES_WKS_ARCH_ASM}) convert_to_absolute_path(VM_SOURCES_DAC ${VM_SOURCES_DAC}) convert_to_absolute_path(VM_SOURCES_WKS_SPECIAL ${VM_SOURCES_WKS_SPECIAL}) -add_library_clr(cee_dac ${VM_SOURCES_DAC}) -add_dependencies(cee_dac eventing_headers) -set_target_properties(cee_dac PROPERTIES DAC_COMPONENT TRUE) -target_precompile_headers(cee_dac PRIVATE [["common.h"]]) +if (NOT CLR_CMAKE_TARGET_ARCH_WASM) + add_library_clr(cee_dac ${VM_SOURCES_DAC}) + add_dependencies(cee_dac eventing_headers) + set_target_properties(cee_dac PROPERTIES DAC_COMPONENT TRUE) + target_precompile_headers(cee_dac PRIVATE [["common.h"]]) +endif() add_subdirectory(wks) diff --git a/src/coreclr/vm/callcounting.h b/src/coreclr/vm/callcounting.h index 34bbf526225fc0..8073e860f5e88c 100644 --- a/src/coreclr/vm/callcounting.h +++ b/src/coreclr/vm/callcounting.h @@ -101,6 +101,8 @@ class CallCountingStub static const SIZE_T CodeSize = 40; #elif defined(TARGET_RISCV64) static const SIZE_T CodeSize = 40; +#elif defined(TARGET_WASM) + static const SIZE_T CodeSize = 0; #endif private: diff --git a/src/coreclr/vm/callingconvention.h b/src/coreclr/vm/callingconvention.h index 63a92f9b1fbcf5..5b167300ec856d 100644 --- a/src/coreclr/vm/callingconvention.h +++ b/src/coreclr/vm/callingconvention.h @@ -186,6 +186,16 @@ struct TransitionBlock }; TADDR padding; // Keep size of TransitionBlock as multiple of 16-byte. Simplifies code in PROLOG_WITH_TRANSITION_BLOCK ArgumentRegisters m_argumentRegisters; +#elif defined(TARGET_WASM) + // No transition block on WASM yet + union { + CalleeSavedRegisters m_calleeSavedRegisters; + // alias saved link register as m_ReturnAddress + struct { + TADDR m_ReturnAddress; + }; + }; + ArgumentRegisters m_argumentRegisters; #else PORTABILITY_ASSERT("TransitionBlock"); #endif @@ -924,6 +934,16 @@ class ArgIteratorTemplate : public ARGITERATOR_BASE } #endif // TARGET_LOONGARCH64 || TARGET_RISCV64 + +#ifdef TARGET_WASM + + // Get layout information for the argument that the ArgIterator is currently visiting. + void GetArgLoc(int argOffset, ArgLocDesc *pLoc) + { + _ASSERTE(!"GetArgLoc not implemented for WASM"); + } +#endif // TARGET_WASM + protected: DWORD m_dwFlags; // Cached flags int m_nSizeOfArgStack; // Cached value of SizeOfArgStack diff --git a/src/coreclr/vm/codeman.h b/src/coreclr/vm/codeman.h index 9ff3492a399b9c..fd52513be864c1 100644 --- a/src/coreclr/vm/codeman.h +++ b/src/coreclr/vm/codeman.h @@ -2565,6 +2565,10 @@ class EECodeInfo } #endif // TARGET_X86 +#if defined(TARGET_WASM) +ULONG GetFixedStackSize(); +#endif + #if defined(TARGET_AMD64) BOOL HasFrameRegister(); ULONG GetFixedStackSize(); diff --git a/src/coreclr/vm/frames.h b/src/coreclr/vm/frames.h index be519af3b9b239..b96598c516f818 100644 --- a/src/coreclr/vm/frames.h +++ b/src/coreclr/vm/frames.h @@ -729,6 +729,9 @@ class ResumableFrame : public Frame #elif defined(TARGET_RISCV64) Object** firstIntReg = (Object**)&this->GetContext()->Gp; Object** lastIntReg = (Object**)&this->GetContext()->T6; +#elif defined(TARGET_WASM) + Object** firstIntReg = nullptr; + Object** lastIntReg = nullptr; #else _ASSERTE(!"nyi for platform"); #endif diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp index 0f3c65c12981b6..16186cb5b08f1a 100644 --- a/src/coreclr/vm/methodtablebuilder.cpp +++ b/src/coreclr/vm/methodtablebuilder.cpp @@ -10181,6 +10181,8 @@ void MethodTableBuilder::CheckForSystemTypes() // although applying 16 byte alignment is consistent with treatment of 128 bit SSE types // even on X86 pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16; // sizeof(__int128) +#elif defined(TARGET_WASM) + pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16; // sizeof(v128) #else #error Unknown architecture #endif // TARGET_64BIT diff --git a/src/coreclr/vm/precode.h b/src/coreclr/vm/precode.h index c9a07e8751b217..f7a1bc336d02bb 100644 --- a/src/coreclr/vm/precode.h +++ b/src/coreclr/vm/precode.h @@ -50,6 +50,11 @@ EXTERN_C VOID STDCALL PrecodeRemotingThunk(); #define SIZEOF_PRECODE_BASE CODE_SIZE_ALIGN #define OFFSETOF_PRECODE_TYPE 0 +#elif defined(TARGET_WASM) + +#define SIZEOF_PRECODE_BASE 0 +#define OFFSETOF_PRECODE_TYPE 0 + #endif // TARGET_AMD64 #ifndef DACCESS_COMPILE @@ -71,6 +76,9 @@ struct InvalidPrecode static const int Type = 0xff; #elif defined(TARGET_RISCV64) static const int Type = 0xff; +#elif defined(TARGET_WASM) + // unreachable instruction + static const int Type = 0; #endif }; @@ -118,6 +126,9 @@ struct StubPrecode #elif defined(TARGET_RISCV64) static const int Type = 0x17; static const SIZE_T CodeSize = 24; +#elif defined(TARGET_WASM) + static const int Type = 0; + static const SIZE_T CodeSize = 0; #endif // TARGET_AMD64 BYTE m_code[CodeSize]; @@ -311,6 +322,10 @@ struct FixupPrecode static const int Type = 0x97; static const SIZE_T CodeSize = 32; static const int FixupCodeOffset = 10; +#elif defined(TARGET_WASM) + static const int Type = 2; + static const SIZE_T CodeSize = 0; + static const int FixupCodeOffset = 0; #endif // TARGET_AMD64 BYTE m_code[CodeSize]; diff --git a/src/coreclr/vm/stackwalk.cpp b/src/coreclr/vm/stackwalk.cpp index c84c6105fcff30..817cbb65514628 100644 --- a/src/coreclr/vm/stackwalk.cpp +++ b/src/coreclr/vm/stackwalk.cpp @@ -440,6 +440,10 @@ PCODE Thread::VirtualUnwindCallFrame(T_CONTEXT* pContext, T_KNONVOLATILE_CONTEXT_POINTERS* pContextPointers /*= NULL*/, EECodeInfo * pCodeInfo /*= NULL*/) { +#ifdef TARGET_WASM + _ASSERTE("VirtualUnwindCallFrame is not supported on WebAssembly"); + return 0; +#else CONTRACTL { NOTHROW; @@ -542,6 +546,7 @@ PCODE Thread::VirtualUnwindCallFrame(T_CONTEXT* pContext, #endif // !DACCESS_COMPILE return uControlPc; +#endif // TARGET_WASM } #ifndef DACCESS_COMPILE diff --git a/src/coreclr/vm/wasm/asmconstants.h b/src/coreclr/vm/wasm/asmconstants.h new file mode 100644 index 00000000000000..c43f599357ea26 --- /dev/null +++ b/src/coreclr/vm/wasm/asmconstants.h @@ -0,0 +1,10 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// asmconstants.h - +// +// This header defines field offsets and constants used by assembly code +// Be sure to rebuild clr/src/vm/ceemain.cpp after changing this file, to +// ensure that the constants match the expected C/C++ values + +#define DynamicHelperFrameFlags_ObjectArg 1 +#define DynamicHelperFrameFlags_ObjectArg2 2 diff --git a/src/coreclr/vm/wasm/cgencpu.h b/src/coreclr/vm/wasm/cgencpu.h new file mode 100644 index 00000000000000..f77b2608fbb1be --- /dev/null +++ b/src/coreclr/vm/wasm/cgencpu.h @@ -0,0 +1,194 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// + +#ifndef __cgenwasm_h__ +#define __cgenwasm_h__ + +#include "stublink.h" +#include "utilcode.h" + +// preferred alignment for data +#define DATA_ALIGNMENT 4 + +#define CODE_SIZE_ALIGN 4 +#define LOG2SLOT LOG2_PTRSIZE + +// looks like this is mandatory for now +#define HAS_NDIRECT_IMPORT_PRECODE 1 +#define HAS_FIXUP_PRECODE 1 +// ThisPtrRetBufPrecode one is necessary for closed delegates over static methods with return buffer +#define HAS_THISPTR_RETBUF_PRECODE 1 + +#define BACK_TO_BACK_JUMP_ALLOCATE_SIZE 8 // # bytes to allocate for a back to back jump instruction + +//********************************************************************** +// Parameter size +//********************************************************************** + +inline unsigned StackElemSize(unsigned parmSize, bool isValueType = false /* unused */, bool isFloatHfa = false /* unused */) +{ + _ASSERTE("The function is not implemented on wasm"); + return 0; +} + +inline TADDR GetSP(const T_CONTEXT * context) +{ + _ASSERTE("The function is not implemented on wasm, it lacks registers"); + return 0; +} + +struct HijackArgs +{ +}; + +inline LPVOID STDCALL GetCurrentSP() +{ + _ASSERTE("The function is not implemented on wasm, it lacks registers"); + return nullptr; +} + +extern PCODE GetPreStubEntryPoint(); + +struct ThisPtrRetBufPrecode { + static const int Type = 0x01; + + void Init(MethodDesc* pMD, LoaderAllocator *pLoaderAllocator) + { + _ASSERTE("The ThisPtrRetBufPrecode::Init is not implemented on wasm"); + } + + TADDR GetMethodDesc() + { + _ASSERTE("The ThisPtrRetBufPrecode::GetMethodDesc is not implemented on wasm"); + return 0; + } + + PCODE GetTarget() + { + _ASSERTE("The ThisPtrRetBufPrecode::GetTarget is not implemented on wasm"); + return 0; + } + + BOOL SetTargetInterlocked(TADDR target, TADDR expected) + { + _ASSERTE("The ThisPtrRetBufPrecode::SetTargetInterlocked is not implemented on wasm"); + return FALSE; + } +}; + +typedef DPTR(ThisPtrRetBufPrecode) PTR_ThisPtrRetBufPrecode; + +#define GetEEFuncEntryPoint(pfn) GFN_TADDR(pfn) + +//********************************************************************** +// Frames +//********************************************************************** + +//-------------------------------------------------------------------- +// This represents the callee saved (non-volatile) registers saved as +// of a FramedMethodFrame. +//-------------------------------------------------------------------- +typedef DPTR(struct CalleeSavedRegisters) PTR_CalleeSavedRegisters; +struct CalleeSavedRegisters { +}; + +//-------------------------------------------------------------------- +// This represents the arguments that are stored in volatile registers. +// This should not overlap the CalleeSavedRegisters since those are already +// saved separately and it would be wasteful to save the same register twice. +// If we do use a non-volatile register as an argument, then the ArgIterator +// will probably have to communicate this back to the PromoteCallerStack +// routine to avoid a double promotion. +//-------------------------------------------------------------------- +typedef DPTR(struct ArgumentRegisters) PTR_ArgumentRegisters; +struct ArgumentRegisters { +}; +#define NUM_ARGUMENT_REGISTERS 0 +#define ARGUMENTREGISTERS_SIZE sizeof(ArgumentRegisters) + +#define ENREGISTERED_RETURNTYPE_MAXSIZE 16 // not sure here, 16 bytes is v128 + +#define STACKWALK_CONTROLPC_ADJUST_OFFSET 0 + +class StubLinkerCPU : public StubLinker +{ +public: + static void Init(); + void EmitShuffleThunk(struct ShuffleEntry *pShuffleEntryArray); + VOID EmitComputedInstantiatingMethodStub(MethodDesc* pSharedMD, struct ShuffleEntry *pShuffleEntryArray, void* extraArg); +}; + +//********************************************************************** +// Exception handling +//********************************************************************** + +inline PCODE GetIP(const T_CONTEXT * context) { + _ASSERT("GetIP is not implemented on wasm, it lacks registers"); + return 0; +} + +inline void SetIP(T_CONTEXT *context, PCODE eip) { + _ASSERT("SetIP is not implemented on wasm, it lacks registers"); +} + +inline void SetSP(T_CONTEXT *context, TADDR esp) { + _ASSERT("SetSP is not implemented on wasm, it lacks registers"); +} + +inline void SetFP(T_CONTEXT *context, TADDR ebp) { + _ASSERT("SetFP is not implemented on wasm, it lacks registers"); +} + +inline TADDR GetFP(const T_CONTEXT * context) +{ + _ASSERT("GetFP is not implemented on wasm, it lacks registers"); + return 0; +} + +#define ENUM_CALLEE_SAVED_REGISTERS() + +#define ENUM_FP_CALLEE_SAVED_REGISTERS() + +// ClrFlushInstructionCache is used when we want to call FlushInstructionCache +// for a specific architecture in the common code, but not for other architectures. +// On IA64 ClrFlushInstructionCache calls the Kernel FlushInstructionCache function +// to flush the instruction cache. +// We call ClrFlushInstructionCache whenever we create or modify code in the heap. +// Currently ClrFlushInstructionCache has no effect on X86 +// + +inline BOOL ClrFlushInstructionCache(LPCVOID pCodeAddr, size_t sizeOfCode, bool hasCodeExecutedBefore = false) +{ + // no-op on wasm + return true; +} + +// +// On IA64 back to back jumps should be separated by a nop bundle to get +// the best performance from the hardware's branch prediction logic. +// For all other platforms back to back jumps don't require anything special +// That is why we have these two wrapper functions that call emitJump and decodeJump +// + +//------------------------------------------------------------------------ +inline void emitBackToBackJump(LPBYTE pBufferRX, LPBYTE pBufferRW, LPVOID target) +{ + _ASSERTE("emitBackToBackJump is not implemented on wasm"); +} + +//------------------------------------------------------------------------ +inline PCODE decodeBackToBackJump(PCODE pBuffer) +{ + _ASSERTE("decodeBackToBackJump is not implemented on wasm"); + return 0; +} + +FORCEINLINE int64_t PalInterlockedCompareExchange64(_Inout_ int64_t volatile *pDst, int64_t iValue, int64_t iComparand) +{ + int64_t result = __sync_val_compare_and_swap(pDst, iComparand, iValue); + __sync_synchronize(); + return result; +} + +#endif // __cgenwasm_h__ diff --git a/src/coreclr/vm/wasm/excepcpu.h b/src/coreclr/vm/wasm/excepcpu.h new file mode 100644 index 00000000000000..7ca5a994a60760 --- /dev/null +++ b/src/coreclr/vm/wasm/excepcpu.h @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// +// copied from arm and left empty. wasm cannot do most of it + +#ifndef __excepcpu_h__ +#define __excepcpu_h__ + +#define THROW_CONTROL_FOR_THREAD_FUNCTION ThrowControlForThread + +#define STATUS_CLR_GCCOVER_CODE STATUS_ILLEGAL_INSTRUCTION + +class Thread; +class FaultingExceptionFrame; + +#define INSTALL_EXCEPTION_HANDLING_RECORD(record) +#define UNINSTALL_EXCEPTION_HANDLING_RECORD(record) +#define DECLARE_CPFH_EH_RECORD(pCurThread) + +// +// Retrieves the redirected CONTEXT* from the stack frame of one of the +// RedirectedHandledJITCaseForXXX_Stub's. +// +PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_CONTEXT * pContext); + +inline +PCODE GetAdjustedCallAddress(PCODE returnAddress) +{ + return returnAddress; +} + +BOOL AdjustContextForVirtualStub(EXCEPTION_RECORD *pExceptionRecord, T_CONTEXT *pContext); + +#endif // __excepcpu_h__ diff --git a/src/coreclr/vm/wasm/gmscpu.h b/src/coreclr/vm/wasm/gmscpu.h new file mode 100644 index 00000000000000..5355cfbc546ee6 --- /dev/null +++ b/src/coreclr/vm/wasm/gmscpu.h @@ -0,0 +1,72 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef __gmscpu_h__ +#define __gmscpu_h__ + +#define __gmscpu_h__ + + // A MachState indicates the register state of the processor at some point in time (usually + // just before or after a call is made). It can be made one of two ways. Either explicitly + // (when you for some reason know the values of all the registers), or implicitly using the + // GET_STATE macros. + + typedef DPTR(struct MachState) PTR_MachState; + struct MachState { + + BOOL isValid() { LIMITED_METHOD_DAC_CONTRACT; return TRUE; } + TADDR GetRetAddr() { LIMITED_METHOD_DAC_CONTRACT; return 0; } + + friend class HelperMethodFrame; + friend class CheckAsmOffsets; + friend struct LazyMachState; + }; + + /********************************************************************/ + /* This allows you to defer the computation of the Machine state + until later. Note that we don't reuse slots, because we want + this to be threadsafe without locks */ + + struct LazyMachState : public MachState { + // compute the machine state of the processor as it will exist just + // after the return after at most'funCallDepth' number of functions. + // if 'testFtn' is non-NULL, the return address is tested at each + // return instruction encountered. If this test returns non-NULL, + // then stack walking stops (thus you can walk up to the point that the + // return address matches some criteria + + // Normally this is called with funCallDepth=1 and testFtn = 0 so that + // it returns the state of the processor after the function that called 'captureState()' + void setLazyStateFromUnwind(MachState* copy); + static void unwindLazyState(LazyMachState* baseState, + MachState* lazyState, + DWORD threadId, + int funCallDepth = 1); + + friend class HelperMethodFrame; + friend class CheckAsmOffsets; + }; + + // R4 - R11 + #define NUM_NONVOLATILE_CONTEXT_POINTERS 8 + + inline void LazyMachState::setLazyStateFromUnwind(MachState* copy) + { + _ASSERTE("LazyMachState::setLazyStateFromUnwind is not implemented"); + } + typedef DPTR(LazyMachState) PTR_LazyMachState; + + // Do the initial capture of the machine state. This is meant to be + // as light weight as possible, as we may never need the state that + // we capture. Thus to complete the process you need to call + // 'getMachState()', which finishes the process + EXTERN_C void LazyMachStateCaptureState(struct LazyMachState *pState); + + // CAPTURE_STATE captures just enough register state so that the state of the + // processor can be deterined just after the routine that has CAPTURE_STATE in + // it returns. + + #define CAPTURE_STATE(machState, ret) \ + LazyMachStateCaptureState(machState) + + #endif