From a983363aef657fa2b5436f9892546f85e4e3435f Mon Sep 17 00:00:00 2001 From: CW2 Date: Sun, 29 Jan 2017 09:51:20 +0100 Subject: [PATCH] [WIP] nanoCLR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Initial NETMF code import, converted to Visual C++ projects, and stubs are used for simple feature configuration in the test application. Removed endian conversion (swapping) code In [a rare] case the endian conversion is necessary, it should be done on the PC side. Removed JIT code Signed-off-by: Stanislav Šimíček --- .gitignore | 12 +- nf.props | 19 + src/CLR/CorLib/CorLib.h | 17 + src/CLR/CorLib/CorLib.vcxproj | 163 + src/CLR/CorLib/CorLib.vcxproj.filters | 42 + src/CLR/CorLib/CorLib_Native.h | 1151 +++++ .../CorLib/CorLib_Native_System_DateTime.cpp | 348 ++ .../CorLib/CorLib_Native_System_Exception.cpp | 246 + .../CorLib/CorLib_Native_System_String.cpp | 1085 ++++ .../CorLib_Native_System_Threading_Thread.cpp | 568 +++ .../CorLib/CorLib_Native_System_TimeSpan.cpp | 193 + src/CLR/Core/CLR_RT_DblLinkedList.cpp | 88 + src/CLR/Core/CLR_RT_HeapBlock.cpp | 1976 ++++++++ src/CLR/Core/CLR_RT_HeapBlock_Array.cpp | 370 ++ src/CLR/Core/CLR_RT_HeapBlock_BinaryBlob.cpp | 66 + src/CLR/Core/CLR_RT_HeapBlock_Delegate.cpp | 76 + .../Core/CLR_RT_HeapBlock_Delegate_List.cpp | 231 + src/CLR/Core/CLR_RT_HeapBlock_Finalizer.cpp | 79 + src/CLR/Core/CLR_RT_HeapBlock_Lock.cpp | 219 + src/CLR/Core/CLR_RT_HeapBlock_LockRequest.cpp | 28 + src/CLR/Core/CLR_RT_HeapBlock_Node.cpp | 15 + src/CLR/Core/CLR_RT_HeapBlock_Stack.cpp | 106 + src/CLR/Core/CLR_RT_HeapBlock_String.cpp | 112 + src/CLR/Core/CLR_RT_HeapBlock_Timer.cpp | 353 ++ .../Core/CLR_RT_HeapBlock_WaitForObject.cpp | 188 + src/CLR/Core/CLR_RT_HeapCluster.cpp | 291 ++ src/CLR/Core/CLR_RT_Memory.cpp | 208 + .../Core/CLR_RT_ObjectToEvent_Destination.cpp | 72 + src/CLR/Core/CLR_RT_ObjectToEvent_Source.cpp | 62 + src/CLR/Core/CLR_RT_RuntimeMemory.cpp | 136 + src/CLR/Core/CLR_RT_StackFrame.cpp | 1165 +++++ src/CLR/Core/CLR_RT_SystemAssembliesTable.cpp | 45 + src/CLR/Core/CLR_RT_UnicodeHelper.cpp | 539 ++ src/CLR/Core/Cache.cpp | 591 +++ src/CLR/Core/Checks.cpp | 79 + src/CLR/Core/Core.cpp | 90 + src/CLR/Core/Core.h | 29 + src/CLR/Core/Core.vcxproj | 212 + src/CLR/Core/Core.vcxproj.filters | 203 + src/CLR/Core/Execution.cpp | 3612 ++++++++++++++ src/CLR/Core/GarbageCollector.cpp | 853 ++++ src/CLR/Core/GarbageCollector_Compaction.cpp | 456 ++ ...bageCollector_ComputeReachabilityGraph.cpp | 296 ++ src/CLR/Core/Hardware/Hardware.cpp | 222 + src/CLR/Core/Hardware/Hardware.vcxproj | 158 + .../Core/Hardware/Hardware.vcxproj.filters | 22 + src/CLR/Core/Hardware/Hardware_stub.cpp | 50 + src/CLR/Core/Hardware/Hardware_stub.vcxproj | 158 + .../Hardware/Hardware_stub.vcxproj.filters | 22 + .../HeapPersistence/HeapPersistence.vcxproj | 158 + .../HeapPersistence.vcxproj.filters | 22 + .../HeapPersistence_stub.vcxproj | 158 + .../HeapPersistence_stub.vcxproj.filters | 22 + .../Core/HeapPersistence/Heap_Persistence.cpp | 1582 ++++++ .../HeapPersistence/Heap_Persistence_stub.cpp | 417 ++ .../Core/IOPort/CLR_RT_HeapBlock_IOPort.cpp | 269 + src/CLR/Core/IOPort/IOPort.vcxproj | 155 + src/CLR/Core/IOPort/IOPort.vcxproj.filters | 17 + src/CLR/Core/IOPort/IOPort_stub.cpp | 82 + src/CLR/Core/IOPort/IOPort_stub.vcxproj | 158 + .../Core/IOPort/IOPort_stub.vcxproj.filters | 22 + src/CLR/Core/Interpreter.cpp | 3125 ++++++++++++ .../InterruptHandler/InterruptHandler.cpp | 138 + .../InterruptHandler/InterruptHandler.vcxproj | 158 + .../InterruptHandler.vcxproj.filters | 22 + .../InterruptHandler_stub.cpp | 33 + .../InterruptHandler_stub.vcxproj | 158 + .../InterruptHandler_stub.vcxproj.filters | 22 + .../Core/RPC/CLR_RT_HeapBlock_EndPoint.cpp | 129 + src/CLR/Core/RPC/RPC.vcxproj | 158 + src/CLR/Core/RPC/RPC.vcxproj.filters | 22 + src/CLR/Core/RPC/RPC_stub.cpp | 61 + src/CLR/Core/RPC/RPC_stub.vcxproj | 158 + src/CLR/Core/RPC/RPC_stub.vcxproj.filters | 22 + .../Core/Serialization/BinaryFormatter.cpp | 2016 ++++++++ .../Serialization/BinaryFormatter_stub.cpp | 300 ++ .../Core/Serialization/Serialization.vcxproj | 158 + .../Serialization.vcxproj.filters | 22 + .../Serialization/Serialization_stub.vcxproj | 158 + .../Serialization_stub.vcxproj.filters | 22 + src/CLR/Core/Streams.cpp | 296 ++ src/CLR/Core/StringTable.cpp | 49 + src/CLR/Core/StringTableData.cpp | 1736 +++++++ src/CLR/Core/Thread.cpp | 1272 +++++ src/CLR/Core/TypeSystem.cpp | 4443 +++++++++++++++++ src/CLR/Core/TypeSystemLookup.cpp | 1775 +++++++ src/CLR/Core/Various.cpp | 125 + src/CLR/Core/corhdr_private.h | 110 + src/CLR/Debugger/Debugger.cpp | 3264 ++++++++++++ src/CLR/Debugger/Debugger.vcxproj | 166 + src/CLR/Debugger/Debugger.vcxproj.filters | 25 + src/CLR/Debugger/Debugger_full.cpp | 107 + src/CLR/Debugger/Debugger_stub.cpp | 61 + src/CLR/Debugger/Debugger_stub.vcxproj | 158 + .../Debugger/Debugger_stub.vcxproj.filters | 22 + src/CLR/Diagnostics/Diagnostics.h | 14 + src/CLR/Diagnostics/Diagnostics.vcxproj | 160 + .../Diagnostics/Diagnostics.vcxproj.filters | 33 + src/CLR/Diagnostics/Diagnostics_stub.cpp | 480 ++ src/CLR/Diagnostics/Diagnostics_stub.vcxproj | 161 + .../Diagnostics_stub.vcxproj.filters | 27 + src/CLR/Diagnostics/Info.cpp | 834 ++++ src/CLR/Diagnostics/Profile.cpp | 268 + src/CLR/Diagnostics/Profiler.cpp | 874 ++++ src/CLR/Include/BlockStorage_decl.h | 922 ++++ src/CLR/Include/TinyCLR_Application.h | 20 + src/CLR/Include/TinyCLR_Checks.h | 57 + src/CLR/Include/TinyCLR_Debugging.h | 1174 +++++ src/CLR/Include/TinyCLR_ErrorCodes.h | 26 + src/CLR/Include/TinyCLR_Hardware.h | 145 + src/CLR/Include/TinyCLR_Interop.h | 461 ++ src/CLR/Include/TinyCLR_Messaging.h | 8 +- src/CLR/Include/TinyCLR_PlatformDef.h | 293 ++ src/CLR/Include/TinyCLR_Profiling.h | 219 + src/CLR/Include/TinyCLR_Runtime.h | 3270 ++++++++++++ src/CLR/Include/TinyCLR_Runtime__HeapBlock.h | 2409 +++++++++ .../Include/TinyCLR_Runtime__Serialization.h | 284 ++ src/CLR/Include/TinyCLR_Types.h | 1149 +++++ src/CLR/Include/TinyCLR_Win32.h | 41 + src/CLR/Include/TinyHAL.h | 1627 ++++++ src/CLR/Include/TinyHAL_ReleaseInfo.h | 73 + src/CLR/Include/TinyHAL_Types.h | 93 + src/CLR/Include/TinyPAL.h | 392 ++ src/CLR/Include/TinySupport.h | 25 + src/CLR/Include/WireProtocol.h | 2 +- src/CLR/Include/netmf_errors.h | 170 + src/CLR/Include/opcode.def | 359 ++ src/CLR/Messaging/Messaging.cpp | 421 +- src/CLR/Messaging/Messaging.vcxproj | 162 + src/CLR/Messaging/Messaging.vcxproj.filters | 22 + src/CLR/Messaging/Messaging_stub.cpp | 66 + src/CLR/Messaging/Messaging_stub.vcxproj | 158 + .../Messaging/Messaging_stub.vcxproj.filters | 22 + src/CLR/StartUp/CLRStartup.cpp | 20 + src/CLR/StartUp/CLRStartup.h | 27 + src/CLR/StartUp/StartUp.vcxproj | 166 + src/CLR/StartUp/StartUp.vcxproj.filters | 27 + src/CLR/WireProtocol/WireProtocol.cpp | 2 +- src/CLR/WireProtocol/WireProtocol.vcxproj | 155 + .../WireProtocol/WireProtocol.vcxproj.filters | 22 + .../os/mbed-os/nanoBooter/TinyCLR_Messaging.h | 2 +- .../os/mbed-os/nanoBooter/WireProtocol.cpp | 2 +- targets/os/mbed-os/nanoBooter/WireProtocol.h | 2 +- targets/os/win32/nanoCLR.sln | 280 ++ targets/os/win32/nanoCLR/CLRStartup.cpp | 702 +++ targets/os/win32/nanoCLR/Events.cpp | 57 + targets/os/win32/nanoCLR/FileStore_Win32.cpp | 253 + .../CLR_RT_InteropAssembliesTable.cpp | 56 + targets/os/win32/nanoCLR/Memory.cpp | 51 + .../win32/nanoCLR/PAL/ComDirector_stubs.cpp | 81 + .../win32/nanoCLR/PAL/ConfigHelper_stubs.cpp | 85 + .../os/win32/nanoCLR/PAL/Watchdog_stubs.cpp | 28 + .../nanoCLR/PAL/blockstorageList_stubs.cpp | 136 + targets/os/win32/nanoCLR/PAL/time_stubs.cpp | 107 + .../os/win32/nanoCLR/ParseOptions_Win32.cpp | 316 ++ targets/os/win32/nanoCLR/Time.cpp | 123 + .../os/win32/nanoCLR/TinyCLR_ParseOptions.h | 136 + targets/os/win32/nanoCLR/Various.cpp | 614 +++ targets/os/win32/nanoCLR/WatchDog.cpp | 29 + targets/os/win32/nanoCLR/main.cpp | 88 + targets/os/win32/nanoCLR/nanoCLR.vcxproj | 314 ++ .../os/win32/nanoCLR/nanoCLR.vcxproj.filters | 87 + targets/os/win32/nanoCLR/platform_selector.h | 83 + targets/os/win32/nanoCLR/stdafx.cpp | 12 + targets/os/win32/nanoCLR/stdafx.h | 26 + targets/os/win32/nanoCLR/targetver.h | 12 + .../MFConsoleApplication.csproj | 44 + .../MFConsoleApplication.sln | 24 + .../netmf/MFConsoleApplication/Program.cs | 13 + .../Properties/AssemblyInfo.cs | 23 + 170 files changed, 61571 insertions(+), 430 deletions(-) create mode 100644 nf.props create mode 100644 src/CLR/CorLib/CorLib.h create mode 100644 src/CLR/CorLib/CorLib.vcxproj create mode 100644 src/CLR/CorLib/CorLib.vcxproj.filters create mode 100644 src/CLR/CorLib/CorLib_Native.h create mode 100644 src/CLR/CorLib/CorLib_Native_System_DateTime.cpp create mode 100644 src/CLR/CorLib/CorLib_Native_System_Exception.cpp create mode 100644 src/CLR/CorLib/CorLib_Native_System_String.cpp create mode 100644 src/CLR/CorLib/CorLib_Native_System_Threading_Thread.cpp create mode 100644 src/CLR/CorLib/CorLib_Native_System_TimeSpan.cpp create mode 100644 src/CLR/Core/CLR_RT_DblLinkedList.cpp create mode 100644 src/CLR/Core/CLR_RT_HeapBlock.cpp create mode 100644 src/CLR/Core/CLR_RT_HeapBlock_Array.cpp create mode 100644 src/CLR/Core/CLR_RT_HeapBlock_BinaryBlob.cpp create mode 100644 src/CLR/Core/CLR_RT_HeapBlock_Delegate.cpp create mode 100644 src/CLR/Core/CLR_RT_HeapBlock_Delegate_List.cpp create mode 100644 src/CLR/Core/CLR_RT_HeapBlock_Finalizer.cpp create mode 100644 src/CLR/Core/CLR_RT_HeapBlock_Lock.cpp create mode 100644 src/CLR/Core/CLR_RT_HeapBlock_LockRequest.cpp create mode 100644 src/CLR/Core/CLR_RT_HeapBlock_Node.cpp create mode 100644 src/CLR/Core/CLR_RT_HeapBlock_Stack.cpp create mode 100644 src/CLR/Core/CLR_RT_HeapBlock_String.cpp create mode 100644 src/CLR/Core/CLR_RT_HeapBlock_Timer.cpp create mode 100644 src/CLR/Core/CLR_RT_HeapBlock_WaitForObject.cpp create mode 100644 src/CLR/Core/CLR_RT_HeapCluster.cpp create mode 100644 src/CLR/Core/CLR_RT_Memory.cpp create mode 100644 src/CLR/Core/CLR_RT_ObjectToEvent_Destination.cpp create mode 100644 src/CLR/Core/CLR_RT_ObjectToEvent_Source.cpp create mode 100644 src/CLR/Core/CLR_RT_RuntimeMemory.cpp create mode 100644 src/CLR/Core/CLR_RT_StackFrame.cpp create mode 100644 src/CLR/Core/CLR_RT_SystemAssembliesTable.cpp create mode 100644 src/CLR/Core/CLR_RT_UnicodeHelper.cpp create mode 100644 src/CLR/Core/Cache.cpp create mode 100644 src/CLR/Core/Checks.cpp create mode 100644 src/CLR/Core/Core.cpp create mode 100644 src/CLR/Core/Core.h create mode 100644 src/CLR/Core/Core.vcxproj create mode 100644 src/CLR/Core/Core.vcxproj.filters create mode 100644 src/CLR/Core/Execution.cpp create mode 100644 src/CLR/Core/GarbageCollector.cpp create mode 100644 src/CLR/Core/GarbageCollector_Compaction.cpp create mode 100644 src/CLR/Core/GarbageCollector_ComputeReachabilityGraph.cpp create mode 100644 src/CLR/Core/Hardware/Hardware.cpp create mode 100644 src/CLR/Core/Hardware/Hardware.vcxproj create mode 100644 src/CLR/Core/Hardware/Hardware.vcxproj.filters create mode 100644 src/CLR/Core/Hardware/Hardware_stub.cpp create mode 100644 src/CLR/Core/Hardware/Hardware_stub.vcxproj create mode 100644 src/CLR/Core/Hardware/Hardware_stub.vcxproj.filters create mode 100644 src/CLR/Core/HeapPersistence/HeapPersistence.vcxproj create mode 100644 src/CLR/Core/HeapPersistence/HeapPersistence.vcxproj.filters create mode 100644 src/CLR/Core/HeapPersistence/HeapPersistence_stub.vcxproj create mode 100644 src/CLR/Core/HeapPersistence/HeapPersistence_stub.vcxproj.filters create mode 100644 src/CLR/Core/HeapPersistence/Heap_Persistence.cpp create mode 100644 src/CLR/Core/HeapPersistence/Heap_Persistence_stub.cpp create mode 100644 src/CLR/Core/IOPort/CLR_RT_HeapBlock_IOPort.cpp create mode 100644 src/CLR/Core/IOPort/IOPort.vcxproj create mode 100644 src/CLR/Core/IOPort/IOPort.vcxproj.filters create mode 100644 src/CLR/Core/IOPort/IOPort_stub.cpp create mode 100644 src/CLR/Core/IOPort/IOPort_stub.vcxproj create mode 100644 src/CLR/Core/IOPort/IOPort_stub.vcxproj.filters create mode 100644 src/CLR/Core/Interpreter.cpp create mode 100644 src/CLR/Core/InterruptHandler/InterruptHandler.cpp create mode 100644 src/CLR/Core/InterruptHandler/InterruptHandler.vcxproj create mode 100644 src/CLR/Core/InterruptHandler/InterruptHandler.vcxproj.filters create mode 100644 src/CLR/Core/InterruptHandler/InterruptHandler_stub.cpp create mode 100644 src/CLR/Core/InterruptHandler/InterruptHandler_stub.vcxproj create mode 100644 src/CLR/Core/InterruptHandler/InterruptHandler_stub.vcxproj.filters create mode 100644 src/CLR/Core/RPC/CLR_RT_HeapBlock_EndPoint.cpp create mode 100644 src/CLR/Core/RPC/RPC.vcxproj create mode 100644 src/CLR/Core/RPC/RPC.vcxproj.filters create mode 100644 src/CLR/Core/RPC/RPC_stub.cpp create mode 100644 src/CLR/Core/RPC/RPC_stub.vcxproj create mode 100644 src/CLR/Core/RPC/RPC_stub.vcxproj.filters create mode 100644 src/CLR/Core/Serialization/BinaryFormatter.cpp create mode 100644 src/CLR/Core/Serialization/BinaryFormatter_stub.cpp create mode 100644 src/CLR/Core/Serialization/Serialization.vcxproj create mode 100644 src/CLR/Core/Serialization/Serialization.vcxproj.filters create mode 100644 src/CLR/Core/Serialization/Serialization_stub.vcxproj create mode 100644 src/CLR/Core/Serialization/Serialization_stub.vcxproj.filters create mode 100644 src/CLR/Core/Streams.cpp create mode 100644 src/CLR/Core/StringTable.cpp create mode 100644 src/CLR/Core/StringTableData.cpp create mode 100644 src/CLR/Core/Thread.cpp create mode 100644 src/CLR/Core/TypeSystem.cpp create mode 100644 src/CLR/Core/TypeSystemLookup.cpp create mode 100644 src/CLR/Core/Various.cpp create mode 100644 src/CLR/Core/corhdr_private.h create mode 100644 src/CLR/Debugger/Debugger.cpp create mode 100644 src/CLR/Debugger/Debugger.vcxproj create mode 100644 src/CLR/Debugger/Debugger.vcxproj.filters create mode 100644 src/CLR/Debugger/Debugger_full.cpp create mode 100644 src/CLR/Debugger/Debugger_stub.cpp create mode 100644 src/CLR/Debugger/Debugger_stub.vcxproj create mode 100644 src/CLR/Debugger/Debugger_stub.vcxproj.filters create mode 100644 src/CLR/Diagnostics/Diagnostics.h create mode 100644 src/CLR/Diagnostics/Diagnostics.vcxproj create mode 100644 src/CLR/Diagnostics/Diagnostics.vcxproj.filters create mode 100644 src/CLR/Diagnostics/Diagnostics_stub.cpp create mode 100644 src/CLR/Diagnostics/Diagnostics_stub.vcxproj create mode 100644 src/CLR/Diagnostics/Diagnostics_stub.vcxproj.filters create mode 100644 src/CLR/Diagnostics/Info.cpp create mode 100644 src/CLR/Diagnostics/Profile.cpp create mode 100644 src/CLR/Diagnostics/Profiler.cpp create mode 100644 src/CLR/Include/BlockStorage_decl.h create mode 100644 src/CLR/Include/TinyCLR_Application.h create mode 100644 src/CLR/Include/TinyCLR_Checks.h create mode 100644 src/CLR/Include/TinyCLR_Debugging.h create mode 100644 src/CLR/Include/TinyCLR_ErrorCodes.h create mode 100644 src/CLR/Include/TinyCLR_Hardware.h create mode 100644 src/CLR/Include/TinyCLR_Interop.h create mode 100644 src/CLR/Include/TinyCLR_PlatformDef.h create mode 100644 src/CLR/Include/TinyCLR_Profiling.h create mode 100644 src/CLR/Include/TinyCLR_Runtime.h create mode 100644 src/CLR/Include/TinyCLR_Runtime__HeapBlock.h create mode 100644 src/CLR/Include/TinyCLR_Runtime__Serialization.h create mode 100644 src/CLR/Include/TinyCLR_Types.h create mode 100644 src/CLR/Include/TinyCLR_Win32.h create mode 100644 src/CLR/Include/TinyHAL.h create mode 100644 src/CLR/Include/TinyHAL_ReleaseInfo.h create mode 100644 src/CLR/Include/TinyHAL_Types.h create mode 100644 src/CLR/Include/TinyPAL.h create mode 100644 src/CLR/Include/TinySupport.h create mode 100644 src/CLR/Include/netmf_errors.h create mode 100644 src/CLR/Include/opcode.def create mode 100644 src/CLR/Messaging/Messaging.vcxproj create mode 100644 src/CLR/Messaging/Messaging.vcxproj.filters create mode 100644 src/CLR/Messaging/Messaging_stub.cpp create mode 100644 src/CLR/Messaging/Messaging_stub.vcxproj create mode 100644 src/CLR/Messaging/Messaging_stub.vcxproj.filters create mode 100644 src/CLR/StartUp/CLRStartup.cpp create mode 100644 src/CLR/StartUp/CLRStartup.h create mode 100644 src/CLR/StartUp/StartUp.vcxproj create mode 100644 src/CLR/StartUp/StartUp.vcxproj.filters create mode 100644 src/CLR/WireProtocol/WireProtocol.vcxproj create mode 100644 src/CLR/WireProtocol/WireProtocol.vcxproj.filters create mode 100644 targets/os/win32/nanoCLR.sln create mode 100644 targets/os/win32/nanoCLR/CLRStartup.cpp create mode 100644 targets/os/win32/nanoCLR/Events.cpp create mode 100644 targets/os/win32/nanoCLR/FileStore_Win32.cpp create mode 100644 targets/os/win32/nanoCLR/Generated/CLR_RT_InteropAssembliesTable.cpp create mode 100644 targets/os/win32/nanoCLR/Memory.cpp create mode 100644 targets/os/win32/nanoCLR/PAL/ComDirector_stubs.cpp create mode 100644 targets/os/win32/nanoCLR/PAL/ConfigHelper_stubs.cpp create mode 100644 targets/os/win32/nanoCLR/PAL/Watchdog_stubs.cpp create mode 100644 targets/os/win32/nanoCLR/PAL/blockstorageList_stubs.cpp create mode 100644 targets/os/win32/nanoCLR/PAL/time_stubs.cpp create mode 100644 targets/os/win32/nanoCLR/ParseOptions_Win32.cpp create mode 100644 targets/os/win32/nanoCLR/Time.cpp create mode 100644 targets/os/win32/nanoCLR/TinyCLR_ParseOptions.h create mode 100644 targets/os/win32/nanoCLR/Various.cpp create mode 100644 targets/os/win32/nanoCLR/WatchDog.cpp create mode 100644 targets/os/win32/nanoCLR/main.cpp create mode 100644 targets/os/win32/nanoCLR/nanoCLR.vcxproj create mode 100644 targets/os/win32/nanoCLR/nanoCLR.vcxproj.filters create mode 100644 targets/os/win32/nanoCLR/platform_selector.h create mode 100644 targets/os/win32/nanoCLR/stdafx.cpp create mode 100644 targets/os/win32/nanoCLR/stdafx.h create mode 100644 targets/os/win32/nanoCLR/targetver.h create mode 100644 targets/os/win32/netmf/MFConsoleApplication/MFConsoleApplication.csproj create mode 100644 targets/os/win32/netmf/MFConsoleApplication/MFConsoleApplication.sln create mode 100644 targets/os/win32/netmf/MFConsoleApplication/Program.cs create mode 100644 targets/os/win32/netmf/MFConsoleApplication/Properties/AssemblyInfo.cs diff --git a/.gitignore b/.gitignore index 301a9b08b3..59f060bf2a 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,7 @@ stcube_repository/* !stcube_repository/CMakeLists.txt # ignore build folder -build/* +/build/ # ignore cmake-variants file (will change frequently per user/board setup, use should derive content from cmake-variants.TEMPLATE.json) cmake-variants.json @@ -17,3 +17,13 @@ cmake-variants.json # ignore cmaketools user preferences file .vscode/.cmaketools.json + +# Visual Studio + +.vs/ + +[Bb]in/ +[Oo]bj/ + +*.suo +*.user diff --git a/nf.props b/nf.props new file mode 100644 index 0000000000..585f1a7c93 --- /dev/null +++ b/nf.props @@ -0,0 +1,19 @@ + + + + + + + $(__BuildDir)\ + $(MSBuildThisFileDirectory)build\ + + $(__BinDir) + $(BuildDir)bin\$(Configuration)\ + + $(__IntDir) + $(BuildDir)obj\$(Configuration)\$(ProjectName)\ + + + + + diff --git a/src/CLR/CorLib/CorLib.h b/src/CLR/CorLib/CorLib.h new file mode 100644 index 0000000000..640f373180 --- /dev/null +++ b/src/CLR/CorLib/CorLib.h @@ -0,0 +1,17 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _TINYCLR_CORLIB_NATIVE_H_ +#define _TINYCLR_CORLIB_NATIVE_H_ + +#include +#include +//#include +//#include +//#include + +#include "CorLib_Native.h" + +#endif diff --git a/src/CLR/CorLib/CorLib.vcxproj b/src/CLR/CorLib/CorLib.vcxproj new file mode 100644 index 0000000000..35e23bf1e5 --- /dev/null +++ b/src/CLR/CorLib/CorLib.vcxproj @@ -0,0 +1,163 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + {58E950CC-2FF6-423C-B006-A70A19272F20} + Win32Proj + CorLib + 10.0.14393.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/src/CLR/CorLib/CorLib.vcxproj.filters b/src/CLR/CorLib/CorLib.vcxproj.filters new file mode 100644 index 0000000000..d48e1b9e83 --- /dev/null +++ b/src/CLR/CorLib/CorLib.vcxproj.filters @@ -0,0 +1,42 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/src/CLR/CorLib/CorLib_Native.h b/src/CLR/CorLib/CorLib_Native.h new file mode 100644 index 0000000000..2133b04f78 --- /dev/null +++ b/src/CLR/CorLib/CorLib_Native.h @@ -0,0 +1,1151 @@ +//----------------------------------------------------------------------------- +// +// ** WARNING! ** +// This file was generated automatically by a tool. +// Re-running the tool will overwrite this file. +// You should copy this file to a custom location +// before adding any customization in the copy to +// prevent loss of your changes when the tool is +// re-run. +// +//----------------------------------------------------------------------------- + + +#ifndef _CORLIB_NATIVE_H_ +#define _CORLIB_NATIVE_H_ + +struct Library_corlib_native_System_Object +{ + TINYCLR_NATIVE_DECLARE(Equals___BOOLEAN__OBJECT); + TINYCLR_NATIVE_DECLARE(GetHashCode___I4); + TINYCLR_NATIVE_DECLARE(GetType___SystemType); + TINYCLR_NATIVE_DECLARE(MemberwiseClone___OBJECT); + TINYCLR_NATIVE_DECLARE(ReferenceEquals___STATIC__BOOLEAN__OBJECT__OBJECT); + + //--// + +}; + +/* // THIS CLASS IS BUILT INTO mscorlib and we need to offset static fields accordingly +struct Library_corlib_native__{232B98F2-8B22-4CE9-8AB0-12C746226FA4} +{ + static const int FIELD_STATIC__$$method0x60003e6-1 = 0; + static const int FIELD_STATIC__$$method0x60003e6-2 = 1; + static const int FIELD_STATIC__$$method0x60003e6-3 = 2; + + + //--// + +}; +*/ + +struct Library_corlib_native_System_ValueType +{ + TINYCLR_NATIVE_DECLARE(Equals___BOOLEAN__OBJECT); + + //--// + +}; + +struct Library_corlib_native_System_Collections_Hashtable +{ + static const int FIELD___buckets = 1; + static const int FIELD___numberOfBuckets = 2; + static const int FIELD___count = 3; + static const int FIELD___loadFactor = 4; + static const int FIELD___maxLoadFactor = 5; + static const int FIELD___growthFactor = 6; + + + //--// + +}; + +struct Library_corlib_native_System_Collections_Hashtable__Entry +{ + static const int FIELD__key = 1; + static const int FIELD__value = 2; + static const int FIELD__next = 3; + + + //--// + +}; + +struct Library_corlib_native_System_Collections_Hashtable__HashtableEnumerator +{ + static const int FIELD__ht = 1; + static const int FIELD__temp = 2; + static const int FIELD__index = 3; + static const int FIELD__returnType = 4; + + + //--// + +}; + +struct Library_corlib_native_System_Exception +{ + static const int FIELD___message = 1; + static const int FIELD__m_innerException = 2; + static const int FIELD__m_stackTrace = 3; + static const int FIELD__m_HResult = 4; + + TINYCLR_NATIVE_DECLARE(get_StackTrace___STRING); + + //--// + + struct StackTrace + { + CLR_RT_MethodDef_Index m_md; + CLR_UINT32 m_IP; + }; + + static HRESULT CreateInstance( CLR_RT_HeapBlock& ref, HRESULT hr, CLR_RT_StackFrame* stack ); + static HRESULT CreateInstance( CLR_RT_HeapBlock& ref, const CLR_RT_TypeDef_Index& cls , HRESULT hr, CLR_RT_StackFrame* stack ); + static HRESULT SetStackTrace ( CLR_RT_HeapBlock& ref, CLR_RT_StackFrame* stack ); + + static CLR_RT_HeapBlock* GetTarget ( CLR_RT_HeapBlock& ref ); + static StackTrace* GetStackTrace( CLR_RT_HeapBlock* obj, CLR_UINT32& depth ); + + //--// + + static LPCSTR GetMessage( CLR_RT_HeapBlock* obj ) { return obj[ Library_corlib_native_System_Exception::FIELD___message ].RecoverString() ; } + static CLR_UINT32 GetHResult( CLR_RT_HeapBlock* obj ) { return obj[ Library_corlib_native_System_Exception::FIELD__m_HResult ].NumericByRef().u4; } +}; + + +struct Library_corlib_native_System_Collections_Hashtable__KeyCollection +{ + static const int FIELD__ht = 1; + + + //--// + +}; + +struct Library_corlib_native_System_Array +{ + TINYCLR_NATIVE_DECLARE(System_Collections_IList_get_Item___OBJECT__I4); + TINYCLR_NATIVE_DECLARE(System_Collections_IList_set_Item___VOID__I4__OBJECT); + TINYCLR_NATIVE_DECLARE(get_Length___I4); + TINYCLR_NATIVE_DECLARE(CreateInstance___STATIC__SystemArray__SystemType__I4); + TINYCLR_NATIVE_DECLARE(Copy___STATIC__VOID__SystemArray__I4__SystemArray__I4__I4); + TINYCLR_NATIVE_DECLARE(Clear___STATIC__VOID__SystemArray__I4__I4); + TINYCLR_NATIVE_DECLARE(TrySZIndexOf___STATIC__BOOLEAN__SystemArray__I4__I4__OBJECT__BYREF_I4); + + //--// + + static HRESULT Clear ( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock& arg , int index , int length ); + static HRESULT Copy ( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock& argSrc, int indexSrc, CLR_RT_HeapBlock& argDst, int indexDst, int length ); + static HRESULT TrySZIndexOf( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock& argSrc, CLR_RT_HeapBlock& match , int start , int stop , bool fForward, CLR_RT_HeapBlock& retValue ); +}; + +struct Library_corlib_native_System_Array__SZArrayEnumerator +{ + static const int FIELD___array = 1; + static const int FIELD___index = 2; + static const int FIELD___endIndex = 3; + static const int FIELD___startIndex = 4; + static const int FIELD___arrayLength = 5; + + + //--// + +}; + +struct Library_corlib_native_System_Globalization_Resources_CultureInfo +{ + static const int FIELD_STATIC__manager = 3; + + + //--// + +}; + +struct Library_corlib_native_System_AppDomain +{ + static const int FIELD__m_appDomain = 1; + static const int FIELD__m_friendlyName = 2; + + TINYCLR_NATIVE_DECLARE(GetAssemblies___SZARRAY_SystemReflectionAssembly); + TINYCLR_NATIVE_DECLARE(LoadInternal___SystemReflectionAssembly__STRING__BOOLEAN__I4__I4__I4__I4); + TINYCLR_NATIVE_DECLARE(CreateDomain___STATIC__SystemAppDomain__STRING); + TINYCLR_NATIVE_DECLARE(Unload___STATIC__VOID__SystemAppDomain); + + //--// +#if defined(TINYCLR_APPDOMAINS) + static HRESULT GetAppDomain( CLR_RT_HeapBlock& ref, CLR_RT_AppDomain*& appDomain, CLR_RT_AppDomain*& appDomainSav, bool fCheckForUnloadingAppDomain ); +#endif +}; + +struct Library_corlib_native_System_ArgumentException +{ + static const int FIELD__m_paramName = 5; + + + //--// + +}; + +struct Library_corlib_native_System_Delegate +{ + TINYCLR_NATIVE_DECLARE(Equals___BOOLEAN__OBJECT); + TINYCLR_NATIVE_DECLARE(get_Method___SystemReflectionMethodInfo); + TINYCLR_NATIVE_DECLARE(get_Target___OBJECT); + TINYCLR_NATIVE_DECLARE(Combine___STATIC__SystemDelegate__SystemDelegate__SystemDelegate); + TINYCLR_NATIVE_DECLARE(Remove___STATIC__SystemDelegate__SystemDelegate__SystemDelegate); + TINYCLR_NATIVE_DECLARE(op_Equality___STATIC__BOOLEAN__SystemDelegate__SystemDelegate); + TINYCLR_NATIVE_DECLARE(op_Inequality___STATIC__BOOLEAN__SystemDelegate__SystemDelegate); + + //--// + + static CLR_RT_HeapBlock_Delegate* GetLastDelegate( CLR_RT_HeapBlock_Delegate* dlg ); +}; + +struct Library_corlib_native_System_MulticastDelegate +{ + TINYCLR_NATIVE_DECLARE(op_Equality___STATIC__BOOLEAN__SystemMulticastDelegate__SystemMulticastDelegate); + TINYCLR_NATIVE_DECLARE(op_Inequality___STATIC__BOOLEAN__SystemMulticastDelegate__SystemMulticastDelegate); + + //--// + +}; + +struct Library_corlib_native_System_BitConverter +{ + TINYCLR_NATIVE_DECLARE(get_IsLittleEndian___STATIC__BOOLEAN); + TINYCLR_NATIVE_DECLARE(DoubleToInt64Bits___STATIC__I8__R8); + TINYCLR_NATIVE_DECLARE(GetBytes___STATIC__SZARRAY_U1__BOOLEAN); + TINYCLR_NATIVE_DECLARE(GetBytes___STATIC__SZARRAY_U1__CHAR); + TINYCLR_NATIVE_DECLARE(GetBytes___STATIC__SZARRAY_U1__R8); + TINYCLR_NATIVE_DECLARE(GetBytes___STATIC__SZARRAY_U1__R4); + TINYCLR_NATIVE_DECLARE(GetBytes___STATIC__SZARRAY_U1__I4); + TINYCLR_NATIVE_DECLARE(GetBytes___STATIC__SZARRAY_U1__I8); + TINYCLR_NATIVE_DECLARE(GetBytes___STATIC__SZARRAY_U1__I2); + TINYCLR_NATIVE_DECLARE(GetBytes___STATIC__SZARRAY_U1__U4); + TINYCLR_NATIVE_DECLARE(GetBytes___STATIC__SZARRAY_U1__U8); + TINYCLR_NATIVE_DECLARE(GetBytes___STATIC__SZARRAY_U1__U2); + TINYCLR_NATIVE_DECLARE(Int64BitsToDouble___STATIC__R8__I8); + TINYCLR_NATIVE_DECLARE(ToBoolean___STATIC__BOOLEAN__SZARRAY_U1__I4); + TINYCLR_NATIVE_DECLARE(ToChar___STATIC__CHAR__SZARRAY_U1__I4); + TINYCLR_NATIVE_DECLARE(ToDouble___STATIC__R8__SZARRAY_U1__I4); + TINYCLR_NATIVE_DECLARE(ToInt16___STATIC__I2__SZARRAY_U1__I4); + TINYCLR_NATIVE_DECLARE(ToInt32___STATIC__I4__SZARRAY_U1__I4); + TINYCLR_NATIVE_DECLARE(ToInt64___STATIC__I8__SZARRAY_U1__I4); + TINYCLR_NATIVE_DECLARE(ToSingle___STATIC__R4__SZARRAY_U1__I4); + TINYCLR_NATIVE_DECLARE(ToString___STATIC__STRING__SZARRAY_U1); + TINYCLR_NATIVE_DECLARE(ToString___STATIC__STRING__SZARRAY_U1__I4); + TINYCLR_NATIVE_DECLARE(ToString___STATIC__STRING__SZARRAY_U1__I4__I4); + TINYCLR_NATIVE_DECLARE(ToUInt16___STATIC__U2__SZARRAY_U1__I4); + TINYCLR_NATIVE_DECLARE(ToUInt32___STATIC__U4__SZARRAY_U1__I4); + TINYCLR_NATIVE_DECLARE(ToUInt64___STATIC__U8__SZARRAY_U1__I4); + + //--// + +}; + +struct Library_corlib_native_System_Boolean +{ + static const int FIELD_STATIC__FalseString = 4; + static const int FIELD_STATIC__TrueString = 5; + + static const int FIELD__m_value = 1; + + + //--// + +}; + +struct Library_corlib_native_System_Byte +{ + static const int FIELD__m_value = 1; + + + //--// + +}; + +struct Library_corlib_native_System_Char +{ + static const int FIELD__m_value = 1; + + + //--// + +}; + +struct Library_corlib_native_System_Collections_ArrayList +{ + static const int FIELD___items = 1; + static const int FIELD___size = 2; + + TINYCLR_NATIVE_DECLARE(get_Item___OBJECT__I4); + TINYCLR_NATIVE_DECLARE(set_Item___VOID__I4__OBJECT); + TINYCLR_NATIVE_DECLARE(Add___I4__OBJECT); + TINYCLR_NATIVE_DECLARE(Clear___VOID); + TINYCLR_NATIVE_DECLARE(Insert___VOID__I4__OBJECT); + TINYCLR_NATIVE_DECLARE(RemoveAt___VOID__I4); + TINYCLR_NATIVE_DECLARE(SetCapacity___VOID__I4); + + //--// + +}; + +struct Library_corlib_native_System_Collections_DictionaryEntry +{ + static const int FIELD__Key = 1; + static const int FIELD__Value = 2; + + + //--// + +}; + +struct Library_corlib_native_System_Collections_Queue +{ + static const int FIELD___array = 1; + static const int FIELD___head = 2; + static const int FIELD___tail = 3; + static const int FIELD___size = 4; + + TINYCLR_NATIVE_DECLARE(Clear___VOID); + TINYCLR_NATIVE_DECLARE(CopyTo___VOID__SystemArray__I4); + TINYCLR_NATIVE_DECLARE(Enqueue___VOID__OBJECT); + TINYCLR_NATIVE_DECLARE(Dequeue___OBJECT); + TINYCLR_NATIVE_DECLARE(Peek___OBJECT); + + //--// + +}; + +struct Library_corlib_native_System_Collections_Stack +{ + static const int FIELD___array = 1; + static const int FIELD___size = 2; + + TINYCLR_NATIVE_DECLARE(Clear___VOID); + TINYCLR_NATIVE_DECLARE(Peek___OBJECT); + TINYCLR_NATIVE_DECLARE(Pop___OBJECT); + TINYCLR_NATIVE_DECLARE(Push___VOID__OBJECT); + + //--// + +}; + +struct Library_corlib_native_System_Convert +{ + static const int FIELD_STATIC__s_rgchBase64EncodingDefault = 6; + static const int FIELD_STATIC__s_rgchBase64EncodingRFC4648 = 7; + static const int FIELD_STATIC__s_rgchBase64Encoding = 8; + static const int FIELD_STATIC__s_rgbBase64Decode = 9; + + + //--// + +}; + +struct Library_corlib_native_System_TimeZone +{ + static const int FIELD__m_id = 1; + + TINYCLR_NATIVE_DECLARE(GetTimeZoneOffset___STATIC__I8); + + //--// + +}; + +struct Library_corlib_native_System_CurrentSystemTimeZone +{ + static const int FIELD__m_ticksOffset = 2; + + + //--// + +}; + +struct Library_corlib_native_System_DateTime +{ + static const int FIELD_STATIC__MinValue = 10; + static const int FIELD_STATIC__MaxValue = 11; + static const int FIELD_STATIC__ticksAtOrigin = 12; + + static const int FIELD__m_ticks = 1; + + TINYCLR_NATIVE_DECLARE(_ctor___VOID__I4__I4__I4__I4__I4__I4__I4); + TINYCLR_NATIVE_DECLARE(get_Day___I4); + TINYCLR_NATIVE_DECLARE(get_DayOfWeek___SystemDayOfWeek); + TINYCLR_NATIVE_DECLARE(get_DayOfYear___I4); + TINYCLR_NATIVE_DECLARE(get_Hour___I4); + TINYCLR_NATIVE_DECLARE(get_Millisecond___I4); + TINYCLR_NATIVE_DECLARE(get_Minute___I4); + TINYCLR_NATIVE_DECLARE(get_Month___I4); + TINYCLR_NATIVE_DECLARE(get_Second___I4); + TINYCLR_NATIVE_DECLARE(get_Year___I4); + TINYCLR_NATIVE_DECLARE(ToLocalTime___SystemDateTime); + TINYCLR_NATIVE_DECLARE(ToUniversalTime___SystemDateTime); + TINYCLR_NATIVE_DECLARE(DaysInMonth___STATIC__I4__I4__I4); + TINYCLR_NATIVE_DECLARE(get_Now___STATIC__SystemDateTime); + TINYCLR_NATIVE_DECLARE(get_UtcNow___STATIC__SystemDateTime); + TINYCLR_NATIVE_DECLARE(get_Today___STATIC__SystemDateTime); + + //--// + + static CLR_INT64* NewObject ( CLR_RT_StackFrame& stack ); + static CLR_INT64* GetValuePtr( CLR_RT_StackFrame& stack ); + static CLR_INT64* GetValuePtr( CLR_RT_HeapBlock& ref ); + + static void Expand ( CLR_RT_StackFrame& stack, SYSTEMTIME& st ); + static void Compress( CLR_RT_StackFrame& stack, const SYSTEMTIME& st ); +}; + +struct Library_corlib_native_System_Diagnostics_Debugger +{ + TINYCLR_NATIVE_DECLARE(get_IsAttached___STATIC__BOOLEAN); + TINYCLR_NATIVE_DECLARE(Break___STATIC__VOID); + + //--// + +}; + +struct Library_corlib_native_System_Double +{ + static const int FIELD__m_value = 1; + + TINYCLR_NATIVE_DECLARE(CompareTo___STATIC__I4__R8__R8); + TINYCLR_NATIVE_DECLARE(IsInfinity___STATIC__BOOLEAN__R8); + TINYCLR_NATIVE_DECLARE(IsNaN___STATIC__BOOLEAN__R8); + TINYCLR_NATIVE_DECLARE(IsNegativeInfinity___STATIC__BOOLEAN__R8); + TINYCLR_NATIVE_DECLARE(IsPositiveInfinity___STATIC__BOOLEAN__R8); + + //--// + +}; + +struct Library_corlib_native_System_GC +{ + TINYCLR_NATIVE_DECLARE(AnyPendingFinalizers___STATIC__BOOLEAN); + TINYCLR_NATIVE_DECLARE(SuppressFinalize___STATIC__VOID__OBJECT); + TINYCLR_NATIVE_DECLARE(ReRegisterForFinalize___STATIC__VOID__OBJECT); + + //--// + +}; + +struct Library_corlib_native_System_Globalization_CultureInfo +{ + static const int FIELD__numInfo = 1; + static const int FIELD__dateTimeInfo = 2; + static const int FIELD__m_name = 3; + static const int FIELD__m_rm = 4; + static const int FIELD__m_parent = 5; + + TINYCLR_NATIVE_DECLARE(get_CurrentUICultureInternal___STATIC__SystemGlobalizationCultureInfo); + TINYCLR_NATIVE_DECLARE(set_CurrentUICultureInternal___STATIC__VOID__SystemGlobalizationCultureInfo); + + //--// + +}; + +struct Library_corlib_native_System_Globalization_DateTimeFormat +{ + TINYCLR_NATIVE_DECLARE(FormatDigits___STATIC__STRING__I4__I4); + + //--// + +}; + +struct Library_corlib_native_System_Globalization_DateTimeFormatInfo +{ + static const int FIELD__amDesignator = 1; + static const int FIELD__pmDesignator = 2; + static const int FIELD__dateSeparator = 3; + static const int FIELD__longTimePattern = 4; + static const int FIELD__shortTimePattern = 5; + static const int FIELD__generalShortTimePattern = 6; + static const int FIELD__generalLongTimePattern = 7; + static const int FIELD__timeSeparator = 8; + static const int FIELD__monthDayPattern = 9; + static const int FIELD__fullDateTimePattern = 10; + static const int FIELD__longDatePattern = 11; + static const int FIELD__shortDatePattern = 12; + static const int FIELD__yearMonthPattern = 13; + static const int FIELD__abbreviatedDayNames = 14; + static const int FIELD__dayNames = 15; + static const int FIELD__abbreviatedMonthNames = 16; + static const int FIELD__monthNames = 17; + static const int FIELD__m_cultureInfo = 18; + + + //--// + +}; + +struct Library_corlib_native_System_Globalization_DaylightTime +{ + static const int FIELD__m_start = 1; + static const int FIELD__m_end = 2; + static const int FIELD__m_delta = 3; + + + //--// + +}; + +struct Library_corlib_native_System_Globalization_NumberFormatInfo +{ + static const int FIELD__numberGroupSizes = 1; + static const int FIELD__positiveSign = 2; + static const int FIELD__negativeSign = 3; + static const int FIELD__numberDecimalSeparator = 4; + static const int FIELD__numberGroupSeparator = 5; + static const int FIELD__m_cultureInfo = 6; + + + //--// + +}; + +struct Library_corlib_native_System_Guid +{ + static const int FIELD_STATIC__m_rand = 13; + static const int FIELD_STATIC__Empty = 14; + + static const int FIELD__m_data = 1; + + + //--// + +}; + +struct Library_corlib_native_System_Int16 +{ + static const int FIELD__m_value = 1; + + + //--// + +}; + +struct Library_corlib_native_System_Int32 +{ + static const int FIELD__m_value = 1; + + + //--// + +}; + +struct Library_corlib_native_System_Int64 +{ + static const int FIELD__m_value = 1; + + + //--// + +}; + +struct Library_corlib_native_System_Math +{ + TINYCLR_NATIVE_DECLARE(Acos___STATIC__R8__R8); + TINYCLR_NATIVE_DECLARE(Asin___STATIC__R8__R8); + TINYCLR_NATIVE_DECLARE(Atan___STATIC__R8__R8); + TINYCLR_NATIVE_DECLARE(Atan2___STATIC__R8__R8__R8); + TINYCLR_NATIVE_DECLARE(Ceiling___STATIC__R8__R8); + TINYCLR_NATIVE_DECLARE(Cos___STATIC__R8__R8); + TINYCLR_NATIVE_DECLARE(Cosh___STATIC__R8__R8); + TINYCLR_NATIVE_DECLARE(IEEERemainder___STATIC__R8__R8__R8); + TINYCLR_NATIVE_DECLARE(Exp___STATIC__R8__R8); + TINYCLR_NATIVE_DECLARE(Floor___STATIC__R8__R8); + TINYCLR_NATIVE_DECLARE(Log___STATIC__R8__R8); + TINYCLR_NATIVE_DECLARE(Log10___STATIC__R8__R8); + TINYCLR_NATIVE_DECLARE(Pow___STATIC__R8__R8__R8); + TINYCLR_NATIVE_DECLARE(Round___STATIC__R8__R8); + TINYCLR_NATIVE_DECLARE(Sign___STATIC__I4__R8); + TINYCLR_NATIVE_DECLARE(Sin___STATIC__R8__R8); + TINYCLR_NATIVE_DECLARE(Sinh___STATIC__R8__R8); + TINYCLR_NATIVE_DECLARE(Sqrt___STATIC__R8__R8); + TINYCLR_NATIVE_DECLARE(Tan___STATIC__R8__R8); + TINYCLR_NATIVE_DECLARE(Tanh___STATIC__R8__R8); + TINYCLR_NATIVE_DECLARE(Truncate___STATIC__R8__R8); + + //--// + +}; + +struct Library_corlib_native_System_Number +{ + TINYCLR_NATIVE_DECLARE(FormatNative___STATIC__STRING__OBJECT__CHAR__I4); + + //--// + +}; + +struct Library_corlib_native_System_Random +{ + static const int FIELD___random = 1; + + TINYCLR_NATIVE_DECLARE(Next___I4); + TINYCLR_NATIVE_DECLARE(Next___I4__I4); + TINYCLR_NATIVE_DECLARE(NextDouble___R8); + TINYCLR_NATIVE_DECLARE(NextBytes___VOID__SZARRAY_U1); + TINYCLR_NATIVE_DECLARE(_ctor___VOID); + TINYCLR_NATIVE_DECLARE(_ctor___VOID__I4); + + //--// + + static HRESULT GetRandom( CLR_RT_StackFrame& stack, CLR_RT_Random*& rand, bool create = false ); +}; + +struct Library_corlib_native_System_Reflection_Assembly +{ + TINYCLR_NATIVE_DECLARE(get_FullName___STRING); + TINYCLR_NATIVE_DECLARE(GetType___SystemType__STRING); + TINYCLR_NATIVE_DECLARE(GetTypes___SZARRAY_SystemType); + TINYCLR_NATIVE_DECLARE(GetVersion___VOID__BYREF_I4__BYREF_I4__BYREF_I4__BYREF_I4); + TINYCLR_NATIVE_DECLARE(GetManifestResourceNames___SZARRAY_STRING); + TINYCLR_NATIVE_DECLARE(GetExecutingAssembly___STATIC__SystemReflectionAssembly); + TINYCLR_NATIVE_DECLARE(LoadInternal___STATIC__SystemReflectionAssembly__STRING__BOOLEAN__I4__I4__I4__I4); + TINYCLR_NATIVE_DECLARE(Load___STATIC__SystemReflectionAssembly__SZARRAY_U1); + + //--// + + static HRESULT GetTypeDescriptor( CLR_RT_HeapBlock& arg, CLR_RT_Assembly_Instance& inst ); +}; + +struct Library_corlib_native_System_Reflection_AssemblyName +{ + static const int FIELD___assembly = 1; + + + //--// + +}; + +struct Library_corlib_native_System_Reflection_MethodBase +{ + TINYCLR_NATIVE_DECLARE(get_Name___STRING); + TINYCLR_NATIVE_DECLARE(get_DeclaringType___SystemType); + TINYCLR_NATIVE_DECLARE(get_IsPublic___BOOLEAN); + TINYCLR_NATIVE_DECLARE(get_IsStatic___BOOLEAN); + TINYCLR_NATIVE_DECLARE(get_IsFinal___BOOLEAN); + TINYCLR_NATIVE_DECLARE(get_IsVirtual___BOOLEAN); + TINYCLR_NATIVE_DECLARE(get_IsAbstract___BOOLEAN); + TINYCLR_NATIVE_DECLARE(Invoke___OBJECT__OBJECT__SZARRAY_OBJECT); + + //--// + + static HRESULT GetMethodDescriptor( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock& arg, CLR_RT_MethodDef_Instance& inst ); + + static HRESULT CheckFlags( CLR_RT_StackFrame& stack, CLR_UINT32 mask, CLR_UINT32 flag ); +}; + +struct Library_corlib_native_System_Reflection_ConstructorInfo +{ + TINYCLR_NATIVE_DECLARE(Invoke___OBJECT__SZARRAY_OBJECT); + + //--// + +}; + +struct Library_corlib_native_System_Reflection_FieldInfo +{ + TINYCLR_NATIVE_DECLARE(SetValue___VOID__OBJECT__OBJECT); + + //--// + + static HRESULT Initialize( CLR_RT_StackFrame& stack, CLR_RT_FieldDef_Instance& instFD, CLR_RT_TypeDef_Instance& instTD, CLR_RT_HeapBlock*& obj ); +}; + +struct Library_corlib_native_System_Reflection_PropertyInfo +{ + TINYCLR_NATIVE_DECLARE(GetValue___OBJECT__OBJECT__SZARRAY_OBJECT); + TINYCLR_NATIVE_DECLARE(SetValue___VOID__OBJECT__OBJECT__SZARRAY_OBJECT); + + //--// + +}; + +struct Library_corlib_native_System_Reflection_RuntimeFieldInfo +{ + TINYCLR_NATIVE_DECLARE(get_Name___STRING); + TINYCLR_NATIVE_DECLARE(get_DeclaringType___SystemType); + TINYCLR_NATIVE_DECLARE(get_FieldType___SystemType); + TINYCLR_NATIVE_DECLARE(GetValue___OBJECT__OBJECT); + + //--// + + static bool GetFieldDescriptor( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock& arg, CLR_RT_FieldDef_Instance& inst ); +}; + +struct Library_corlib_native_System_Reflection_RuntimeMethodInfo +{ + TINYCLR_NATIVE_DECLARE(get_ReturnType___SystemType); + + //--// + +}; + +struct Library_corlib_native_System_Resources_ResourceManager +{ + static const int FIELD__m_resourceFileId = 1; + static const int FIELD__m_assembly = 2; + static const int FIELD__m_baseAssembly = 3; + static const int FIELD__m_baseName = 4; + static const int FIELD__m_cultureName = 5; + static const int FIELD__m_rmFallback = 6; + + TINYCLR_NATIVE_DECLARE(GetObjectInternal___OBJECT__I2); + TINYCLR_NATIVE_DECLARE(GetObjectInternal___OBJECT__I2__I4__I4); + TINYCLR_NATIVE_DECLARE(FindResource___STATIC__I4__STRING__SystemReflectionAssembly); + TINYCLR_NATIVE_DECLARE(GetObject___STATIC__OBJECT__SystemResourcesResourceManager__SystemEnum); + + //--// + + TINYCLR_NATIVE_DECLARE(GetObject___STATIC__OBJECT__SystemResourcesResourceManager__SystemEnum__I4__I4); + +}; + +struct Library_corlib_native_System_Runtime_CompilerServices_AccessedThroughPropertyAttribute +{ + static const int FIELD__propertyName = 1; + + + //--// + +}; + +struct Library_corlib_native_System_Runtime_CompilerServices_RuntimeHelpers +{ + TINYCLR_NATIVE_DECLARE(InitializeArray___STATIC__VOID__SystemArray__SystemRuntimeFieldHandle); + TINYCLR_NATIVE_DECLARE(GetObjectValue___STATIC__OBJECT__OBJECT); + TINYCLR_NATIVE_DECLARE(RunClassConstructor___STATIC__VOID__SystemRuntimeTypeHandle); + TINYCLR_NATIVE_DECLARE(get_OffsetToStringData___STATIC__I4); + + //--// + +}; + +struct Library_corlib_native_System_Runtime_Remoting_RemotingServices +{ + TINYCLR_NATIVE_DECLARE(IsTransparentProxy___STATIC__BOOLEAN__OBJECT); + + //--// + +}; + +struct Library_corlib_native_System_Runtime_Versioning_TargetFrameworkAttribute +{ + static const int FIELD___frameworkName = 1; + static const int FIELD___frameworkDisplayName = 2; + + + //--// + +}; + +struct Library_corlib_native_System_Type +{ + TINYCLR_NATIVE_DECLARE(get_DeclaringType___SystemType); + TINYCLR_NATIVE_DECLARE(GetMethod___SystemReflectionMethodInfo__STRING__SystemReflectionBindingFlags); + TINYCLR_NATIVE_DECLARE(IsInstanceOfType___BOOLEAN__OBJECT); + TINYCLR_NATIVE_DECLARE(InvokeMember___OBJECT__STRING__SystemReflectionBindingFlags__SystemReflectionBinder__OBJECT__SZARRAY_OBJECT); + TINYCLR_NATIVE_DECLARE(GetConstructor___SystemReflectionConstructorInfo__SZARRAY_SystemType); + TINYCLR_NATIVE_DECLARE(GetMethod___SystemReflectionMethodInfo__STRING__SZARRAY_SystemType); + TINYCLR_NATIVE_DECLARE(GetMethod___SystemReflectionMethodInfo__STRING); + TINYCLR_NATIVE_DECLARE(get_IsNotPublic___BOOLEAN); + TINYCLR_NATIVE_DECLARE(get_IsPublic___BOOLEAN); + TINYCLR_NATIVE_DECLARE(get_IsClass___BOOLEAN); + TINYCLR_NATIVE_DECLARE(get_IsInterface___BOOLEAN); + TINYCLR_NATIVE_DECLARE(get_IsValueType___BOOLEAN); + TINYCLR_NATIVE_DECLARE(get_IsAbstract___BOOLEAN); + TINYCLR_NATIVE_DECLARE(get_IsEnum___BOOLEAN); + TINYCLR_NATIVE_DECLARE(get_IsSerializable___BOOLEAN); + TINYCLR_NATIVE_DECLARE(get_IsArray___BOOLEAN); + TINYCLR_NATIVE_DECLARE(GetTypeInternal___STATIC__SystemType__STRING__STRING__BOOLEAN__SZARRAY_I4); + TINYCLR_NATIVE_DECLARE(GetTypeFromHandle___STATIC__SystemType__SystemRuntimeTypeHandle); + + //--// + + // + static const int c_BindingFlags_Default = 0x00000000; // a place holder for no flag specifed + + static const int c_BindingFlags_IgnoreCase = 0x00000001; // Ignore the case of Names while searching + static const int c_BindingFlags_DeclaredOnly = 0x00000002; // Only look at the members declared on the Type + static const int c_BindingFlags_Instance = 0x00000004; // Include Instance members in search + static const int c_BindingFlags_Static = 0x00000008; // Include Static members in search + static const int c_BindingFlags_Public = 0x00000010; // Include Public members in search + static const int c_BindingFlags_NonPublic = 0x00000020; // Include Non-Public members in search + static const int c_BindingFlags_FlattenHierarchy = 0x00000040; // Rollup the statics into the class. + + static const int c_BindingFlags_InvokeMethod = 0x00000100; + static const int c_BindingFlags_CreateInstance = 0x00000200; + static const int c_BindingFlags_GetField = 0x00000400; + static const int c_BindingFlags_SetField = 0x00000800; + static const int c_BindingFlags_GetProperty = 0x00001000; + static const int c_BindingFlags_SetProperty = 0x00002000; + + static const int c_BindingFlags_PutDispProperty = 0x00004000; + static const int c_BindingFlags_PutRefDispProperty = 0x00008000; + + static const int c_BindingFlags_ExactBinding = 0x00010000; // Bind with Exact Type matching, No Change type + static const int c_BindingFlags_SuppressChangeType = 0x00020000; + + static const int c_BindingFlags_OptionalParamBinding = 0x00040000; + static const int c_BindingFlags_IgnoreReturn = 0x01000000; // This is used in COM Interop + + //--// + + static const int c_BindingFlags_DefaultLookup = c_BindingFlags_Instance | c_BindingFlags_Static | c_BindingFlags_Public; + + //--// + + static HRESULT CheckFlags( CLR_RT_StackFrame& stack, CLR_UINT32 mask, CLR_UINT32 flag ); + + static HRESULT GetFields ( CLR_RT_StackFrame& stack, LPCSTR szText, CLR_UINT32 attr , bool fAllMatches ); + static HRESULT GetMethods( CLR_RT_StackFrame& stack, LPCSTR szText, CLR_UINT32 attr, CLR_RT_HeapBlock* pParams, int iParams, bool fAllMatches ); +}; + +struct Library_corlib_native_System_RuntimeType +{ + TINYCLR_NATIVE_DECLARE(get_Assembly___SystemReflectionAssembly); + TINYCLR_NATIVE_DECLARE(get_Name___STRING); + TINYCLR_NATIVE_DECLARE(get_FullName___STRING); + TINYCLR_NATIVE_DECLARE(get_BaseType___SystemType); + TINYCLR_NATIVE_DECLARE(GetMethods___SZARRAY_SystemReflectionMethodInfo__SystemReflectionBindingFlags); + TINYCLR_NATIVE_DECLARE(GetField___SystemReflectionFieldInfo__STRING__SystemReflectionBindingFlags); + TINYCLR_NATIVE_DECLARE(GetFields___SZARRAY_SystemReflectionFieldInfo__SystemReflectionBindingFlags); + TINYCLR_NATIVE_DECLARE(GetInterfaces___SZARRAY_SystemType); + TINYCLR_NATIVE_DECLARE(GetElementType___SystemType); + + //--// + + static HRESULT GetTypeDescriptor( CLR_RT_HeapBlock& arg, CLR_RT_TypeDef_Instance& inst, CLR_UINT32* levels ); + static HRESULT GetTypeDescriptor( CLR_RT_HeapBlock& arg, CLR_RT_TypeDef_Instance& inst ); + static HRESULT GetName( CLR_RT_HeapBlock& arg, bool fFullName, CLR_RT_HeapBlock& res ); +}; + +struct Library_corlib_native_System_SByte +{ + static const int FIELD__m_value = 1; + + + //--// + +}; + +struct Library_corlib_native_System_Single +{ + static const int FIELD__m_value = 1; + + + //--// + +}; + +struct Library_corlib_native_System_String +{ + static const int FIELD_STATIC__Empty = 15; + + TINYCLR_NATIVE_DECLARE(CompareTo___I4__OBJECT); + TINYCLR_NATIVE_DECLARE(get_Chars___CHAR__I4); + TINYCLR_NATIVE_DECLARE(ToCharArray___SZARRAY_CHAR); + TINYCLR_NATIVE_DECLARE(ToCharArray___SZARRAY_CHAR__I4__I4); + TINYCLR_NATIVE_DECLARE(get_Length___I4); + TINYCLR_NATIVE_DECLARE(Split___SZARRAY_STRING__SZARRAY_CHAR); + TINYCLR_NATIVE_DECLARE(Split___SZARRAY_STRING__SZARRAY_CHAR__I4); + TINYCLR_NATIVE_DECLARE(Substring___STRING__I4); + TINYCLR_NATIVE_DECLARE(Substring___STRING__I4__I4); + TINYCLR_NATIVE_DECLARE(Trim___STRING__SZARRAY_CHAR); + TINYCLR_NATIVE_DECLARE(TrimStart___STRING__SZARRAY_CHAR); + TINYCLR_NATIVE_DECLARE(TrimEnd___STRING__SZARRAY_CHAR); + TINYCLR_NATIVE_DECLARE(_ctor___VOID__SZARRAY_CHAR__I4__I4); + TINYCLR_NATIVE_DECLARE(_ctor___VOID__SZARRAY_CHAR); + TINYCLR_NATIVE_DECLARE(_ctor___VOID__CHAR__I4); + TINYCLR_NATIVE_DECLARE(CompareTo___I4__STRING); + TINYCLR_NATIVE_DECLARE(IndexOf___I4__CHAR); + TINYCLR_NATIVE_DECLARE(IndexOf___I4__CHAR__I4); + TINYCLR_NATIVE_DECLARE(IndexOf___I4__CHAR__I4__I4); + TINYCLR_NATIVE_DECLARE(IndexOfAny___I4__SZARRAY_CHAR); + TINYCLR_NATIVE_DECLARE(IndexOfAny___I4__SZARRAY_CHAR__I4); + TINYCLR_NATIVE_DECLARE(IndexOfAny___I4__SZARRAY_CHAR__I4__I4); + TINYCLR_NATIVE_DECLARE(IndexOf___I4__STRING); + TINYCLR_NATIVE_DECLARE(IndexOf___I4__STRING__I4); + TINYCLR_NATIVE_DECLARE(IndexOf___I4__STRING__I4__I4); + TINYCLR_NATIVE_DECLARE(LastIndexOf___I4__CHAR); + TINYCLR_NATIVE_DECLARE(LastIndexOf___I4__CHAR__I4); + TINYCLR_NATIVE_DECLARE(LastIndexOf___I4__CHAR__I4__I4); + TINYCLR_NATIVE_DECLARE(LastIndexOfAny___I4__SZARRAY_CHAR); + TINYCLR_NATIVE_DECLARE(LastIndexOfAny___I4__SZARRAY_CHAR__I4); + TINYCLR_NATIVE_DECLARE(LastIndexOfAny___I4__SZARRAY_CHAR__I4__I4); + TINYCLR_NATIVE_DECLARE(LastIndexOf___I4__STRING); + TINYCLR_NATIVE_DECLARE(LastIndexOf___I4__STRING__I4); + TINYCLR_NATIVE_DECLARE(LastIndexOf___I4__STRING__I4__I4); + TINYCLR_NATIVE_DECLARE(ToLower___STRING); + TINYCLR_NATIVE_DECLARE(ToUpper___STRING); + TINYCLR_NATIVE_DECLARE(Trim___STRING); + TINYCLR_NATIVE_DECLARE(Equals___STATIC__BOOLEAN__STRING__STRING); + TINYCLR_NATIVE_DECLARE(op_Equality___STATIC__BOOLEAN__STRING__STRING); + TINYCLR_NATIVE_DECLARE(op_Inequality___STATIC__BOOLEAN__STRING__STRING); + TINYCLR_NATIVE_DECLARE(Compare___STATIC__I4__STRING__STRING); + TINYCLR_NATIVE_DECLARE(Concat___STATIC__STRING__STRING__STRING); + TINYCLR_NATIVE_DECLARE(Concat___STATIC__STRING__STRING__STRING__STRING); + TINYCLR_NATIVE_DECLARE(Concat___STATIC__STRING__STRING__STRING__STRING__STRING); + TINYCLR_NATIVE_DECLARE(Concat___STATIC__STRING__SZARRAY_STRING); + + //--// + + static const int c_IndexOf__SingleChar = 0x00000001; + static const int c_IndexOf__MultipleChars = 0x00000002; + static const int c_IndexOf__String = 0x00000004; + static const int c_IndexOf__StartIndex = 0x00000010; + static const int c_IndexOf__Count = 0x00000020; + static const int c_IndexOf__Last = 0x00000040; + + static HRESULT FromCharArray( CLR_RT_StackFrame& stack, int startIndex, int count ); + static HRESULT ToCharArray ( CLR_RT_StackFrame& stack, int startIndex, int count ); + static HRESULT IndexOf ( CLR_RT_StackFrame& stack, int mode ); + static HRESULT ChangeCase ( CLR_RT_StackFrame& stack, bool fToUpper ); + static HRESULT Substring ( CLR_RT_StackFrame& stack, int startIndex, int count ); + + + static HRESULT Trim( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock_Array* arrayTrimChars, bool fStart, bool fEnd ); + + static HRESULT Split( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock& chars, int maxStrings ); + + //--// + + static HRESULT Concat( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock* array, int num ); + + static HRESULT ConvertToCharArray( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock& ref, CLR_RT_HeapBlock_Array*& array, int startIndex, int length ); + static HRESULT ConvertToCharArray( LPCSTR szText , CLR_RT_HeapBlock& ref, CLR_RT_HeapBlock_Array*& array, int startIndex, int length ); +}; + +struct Library_corlib_native_System_Text_StringBuilder +{ + static const int FIELD__m_MaxCapacity = 1; + static const int FIELD__m_ChunkChars = 2; + static const int FIELD__m_ChunkLength = 3; + static const int FIELD__m_ChunkPrevious = 4; + static const int FIELD__m_ChunkOffset = 5; + + + //--// + +}; + +struct Library_corlib_native_System_Text_UTF8Decoder +{ + TINYCLR_NATIVE_DECLARE(Convert___VOID__SZARRAY_U1__I4__I4__SZARRAY_CHAR__I4__I4__BOOLEAN__BYREF_I4__BYREF_I4__BYREF_BOOLEAN); + + //--// + +}; + +struct Library_corlib_native_System_Text_UTF8Encoding +{ + TINYCLR_NATIVE_DECLARE(GetBytes___SZARRAY_U1__STRING); + TINYCLR_NATIVE_DECLARE(GetBytes___I4__STRING__I4__I4__SZARRAY_U1__I4); + TINYCLR_NATIVE_DECLARE(GetChars___SZARRAY_CHAR__SZARRAY_U1); + TINYCLR_NATIVE_DECLARE(GetChars___SZARRAY_CHAR__SZARRAY_U1__I4__I4); + + //--// + + static HRESULT Helper__GetChars(CLR_RT_StackFrame& stack, bool fIndexed); + +}; + +struct Library_corlib_native_System_Threading_WaitHandle +{ + TINYCLR_NATIVE_DECLARE(WaitOne___BOOLEAN__I4__BOOLEAN); + TINYCLR_NATIVE_DECLARE(WaitMultiple___STATIC__I4__SZARRAY_SystemThreadingWaitHandle__I4__BOOLEAN__BOOLEAN); + + //--// + + static void Set ( CLR_RT_StackFrame& stack ); + static void Reset( CLR_RT_StackFrame& stack ); + + static HRESULT Wait( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock& blkTimeout, CLR_RT_HeapBlock& blkExitContext, CLR_RT_HeapBlock* objects, int cObjects, bool fWaitAll ); +}; + +struct Library_corlib_native_System_Threading_AutoResetEvent +{ + TINYCLR_NATIVE_DECLARE(_ctor___VOID__BOOLEAN); + TINYCLR_NATIVE_DECLARE(Reset___BOOLEAN); + TINYCLR_NATIVE_DECLARE(Set___BOOLEAN); + + //--// + +}; + +struct Library_corlib_native_System_Threading_Interlocked +{ + TINYCLR_NATIVE_DECLARE(Increment___STATIC__I4__BYREF_I4); + TINYCLR_NATIVE_DECLARE(Decrement___STATIC__I4__BYREF_I4); + TINYCLR_NATIVE_DECLARE(Exchange___STATIC__I4__BYREF_I4__I4); + TINYCLR_NATIVE_DECLARE(CompareExchange___STATIC__I4__BYREF_I4__I4__I4); + + //--// + +}; + +struct Library_corlib_native_System_Threading_ManualResetEvent +{ + TINYCLR_NATIVE_DECLARE(_ctor___VOID__BOOLEAN); + TINYCLR_NATIVE_DECLARE(Reset___BOOLEAN); + TINYCLR_NATIVE_DECLARE(Set___BOOLEAN); + + //--// + +}; + +struct Library_corlib_native_System_Threading_Monitor +{ + TINYCLR_NATIVE_DECLARE(Enter___STATIC__VOID__OBJECT); + TINYCLR_NATIVE_DECLARE(Exit___STATIC__VOID__OBJECT); + + //--// + +}; + +struct Library_corlib_native_System_Threading_Thread +{ + static const int FIELD__m_Delegate = 1; + static const int FIELD__m_Priority = 2; + static const int FIELD__m_Thread = 3; + static const int FIELD__m_AppDomain = 4; + static const int FIELD__m_Id = 5; + + TINYCLR_NATIVE_DECLARE(_ctor___VOID__SystemThreadingThreadStart); + TINYCLR_NATIVE_DECLARE(Start___VOID); + TINYCLR_NATIVE_DECLARE(Abort___VOID); + TINYCLR_NATIVE_DECLARE(Suspend___VOID); + TINYCLR_NATIVE_DECLARE(Resume___VOID); + TINYCLR_NATIVE_DECLARE(get_Priority___SystemThreadingThreadPriority); + TINYCLR_NATIVE_DECLARE(set_Priority___VOID__SystemThreadingThreadPriority); + TINYCLR_NATIVE_DECLARE(get_ManagedThreadId___I4); + TINYCLR_NATIVE_DECLARE(get_IsAlive___BOOLEAN); + TINYCLR_NATIVE_DECLARE(Join___VOID); + TINYCLR_NATIVE_DECLARE(Join___BOOLEAN__I4); + TINYCLR_NATIVE_DECLARE(Join___BOOLEAN__SystemTimeSpan); + TINYCLR_NATIVE_DECLARE(get_ThreadState___SystemThreadingThreadState); + TINYCLR_NATIVE_DECLARE(Sleep___STATIC__VOID__I4); + TINYCLR_NATIVE_DECLARE(get_CurrentThread___STATIC__SystemThreadingThread); + TINYCLR_NATIVE_DECLARE(GetDomain___STATIC__SystemAppDomain); + + //--// + + static CLR_RT_ObjectToEvent_Source* GetThreadReference ( CLR_RT_StackFrame& stack ); + static void ResetThreadReference( CLR_RT_StackFrame& stack ); + static HRESULT SetThread ( CLR_RT_StackFrame& stack, CLR_RT_Thread* th ); + static HRESULT GetThread ( CLR_RT_StackFrame& stack, CLR_RT_Thread*& th, bool mustBeStarted, bool noSystemThreads ); + + static HRESULT Join( CLR_RT_StackFrame& stack, const CLR_INT64& timeExpire ); +}; + +struct Library_corlib_native_System_Threading_Timer +{ + static const int FIELD__m_timer = 1; + static const int FIELD__m_state = 2; + static const int FIELD__m_callback = 3; + + TINYCLR_NATIVE_DECLARE(Dispose___VOID); + TINYCLR_NATIVE_DECLARE(_ctor___VOID__SystemThreadingTimerCallback__OBJECT__I4__I4); + TINYCLR_NATIVE_DECLARE(_ctor___VOID__SystemThreadingTimerCallback__OBJECT__SystemTimeSpan__SystemTimeSpan); + TINYCLR_NATIVE_DECLARE(Change___BOOLEAN__I4__I4); + TINYCLR_NATIVE_DECLARE(Change___BOOLEAN__SystemTimeSpan__SystemTimeSpan); + + //--// + + static HRESULT SetValues ( CLR_RT_StackFrame& stack, CLR_UINT32 flags ); + static bool CheckDisposed( CLR_RT_StackFrame& stack ); +}; + +struct Library_corlib_native_System_TimeSpan +{ + static const int FIELD_STATIC__Zero = 16; + static const int FIELD_STATIC__MaxValue = 17; + static const int FIELD_STATIC__MinValue = 18; + + static const int FIELD__m_ticks = 1; + + TINYCLR_NATIVE_DECLARE(Equals___BOOLEAN__OBJECT); + TINYCLR_NATIVE_DECLARE(ToString___STRING); + TINYCLR_NATIVE_DECLARE(_ctor___VOID__I4__I4__I4); + TINYCLR_NATIVE_DECLARE(_ctor___VOID__I4__I4__I4__I4); + TINYCLR_NATIVE_DECLARE(_ctor___VOID__I4__I4__I4__I4__I4); + TINYCLR_NATIVE_DECLARE(CompareTo___I4__OBJECT); + TINYCLR_NATIVE_DECLARE(Compare___STATIC__I4__SystemTimeSpan__SystemTimeSpan); + TINYCLR_NATIVE_DECLARE(Equals___STATIC__BOOLEAN__SystemTimeSpan__SystemTimeSpan); + + //--// + + static CLR_INT64* NewObject ( CLR_RT_StackFrame& stack ); + static CLR_INT64* GetValuePtr( CLR_RT_StackFrame& stack ); + static CLR_INT64* GetValuePtr( CLR_RT_HeapBlock& ref ); + + static void ConstructTimeSpan( CLR_INT64* val, CLR_INT32 days, CLR_INT32 hours, CLR_INT32 minutes, CLR_INT32 seconds, CLR_INT32 ms ); +}; + +struct Library_corlib_native_System_UInt16 +{ + static const int FIELD__m_value = 1; + + + //--// + +}; + +struct Library_corlib_native_System_UInt32 +{ + static const int FIELD__m_value = 1; + + + //--// + +}; + +struct Library_corlib_native_System_UInt64 +{ + static const int FIELD__m_value = 1; + + + //--// + +}; + +struct Library_corlib_native_System_Version +{ + static const int FIELD___Major = 1; + static const int FIELD___Minor = 2; + static const int FIELD___Build = 3; + static const int FIELD___Revision = 4; + + + //--// + +}; + +struct Library_corlib_native_System_WeakReference +{ + TINYCLR_NATIVE_DECLARE(get_IsAlive___BOOLEAN); + TINYCLR_NATIVE_DECLARE(get_Target___OBJECT); + TINYCLR_NATIVE_DECLARE(set_Target___VOID__OBJECT); + TINYCLR_NATIVE_DECLARE(_ctor___VOID__OBJECT); + + //--// + +}; + +struct Library_corlib_native_System_Collections_Hashtable__ValueCollection +{ + static const int FIELD__ht = 1; + + + //--// + +}; + +extern const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_mscorlib; + +#endif // _CORLIB_NATIVE_H_ diff --git a/src/CLR/CorLib/CorLib_Native_System_DateTime.cpp b/src/CLR/CorLib/CorLib_Native_System_DateTime.cpp new file mode 100644 index 0000000000..95baee1ebc --- /dev/null +++ b/src/CLR/CorLib/CorLib_Native_System_DateTime.cpp @@ -0,0 +1,348 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + +CLR_INT64 s_UTCMask = ULONGLONGCONSTANT(0x8000000000000000); +CLR_INT64 s_TickMask = ULONGLONGCONSTANT(0x7FFFFFFFFFFFFFFF); + + +HRESULT Library_corlib_native_System_DateTime::_ctor___VOID__I4__I4__I4__I4__I4__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock* pArg = &(stack.Arg1()); + SYSTEMTIME st; + + TINYCLR_CLEAR(st); + st.wYear = pArg[ 0 ].NumericByRef().s4; + st.wMonth = pArg[ 1 ].NumericByRef().s4; + st.wDay = pArg[ 2 ].NumericByRef().s4; + st.wHour = pArg[ 3 ].NumericByRef().s4; + st.wMinute = pArg[ 4 ].NumericByRef().s4; + st.wSecond = pArg[ 5 ].NumericByRef().s4; + st.wMilliseconds = pArg[ 6 ].NumericByRef().s4; + + /// Our current supported range is between 1601 and 3000. Years before 1582 requires different calculation (see explanation + /// in time_decl.h), same way years after 3000 will not hold the simple arithmatic which we are using. More complex calculations + /// outside these range are not worth the CPU cycle and codesize. + if ((st.wYear < 1601) || (st.wYear > 3000) || + (st.wMonth < 1) || (st.wMonth > 12) || + (st.wDay < 1) || (st.wDay > 31)) + { + TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + + + Compress( stack, st ); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_DateTime::get_Day___I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + SYSTEMTIME st; Expand( stack, st ); + + stack.SetResult_I4( st.wDay ); + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_DateTime::get_DayOfWeek___SystemDayOfWeek( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + SYSTEMTIME st; Expand( stack, st ); + + stack.SetResult_I4( st.wDayOfWeek ); + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_DateTime::get_DayOfYear___I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + SYSTEMTIME st ; + INT32 days; + Expand( stack, st ); + + TINYCLR_CHECK_HRESULT(Time_AccDaysInMonth( st.wYear, st.wMonth, &days )); + days += st.wDay; + + stack.SetResult_I4( days ); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_DateTime::get_Hour___I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + SYSTEMTIME st; Expand( stack, st ); + + stack.SetResult_I4( st.wHour ); + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_DateTime::get_Millisecond___I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + SYSTEMTIME st; Expand( stack, st ); + + stack.SetResult_I4( st.wMilliseconds ); + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_DateTime::get_Minute___I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + SYSTEMTIME st; Expand( stack, st ); + + stack.SetResult_I4( st.wMinute ); + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_DateTime::get_Month___I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + SYSTEMTIME st; Expand( stack, st ); + + stack.SetResult_I4( st.wMonth ); + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_DateTime::get_Second___I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + SYSTEMTIME st; Expand( stack, st ); + + stack.SetResult_I4( st.wSecond ); + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_DateTime::get_Year___I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + SYSTEMTIME st; Expand( stack, st ); + + stack.SetResult_I4( st.wYear ); + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_DateTime::ToLocalTime___SystemDateTime( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_INT64* pThis; + CLR_INT64* pRes; + + pThis = Library_corlib_native_System_DateTime::GetValuePtr( stack ); FAULT_ON_NULL(pThis); + pRes = Library_corlib_native_System_DateTime::NewObject ( stack ); + + if ( *pThis & s_UTCMask ) + { + // The most significant bit of *val keeps flag if time is UTC. + // We cannot change *val, so we create copy and clear the bit. + CLR_INT64 ticks = *pThis & s_TickMask; + + *pRes = ticks + TIME_ZONE_OFFSET; + } + else + { + // If *pThis is already local time - we do not need conversion. + *pRes = *pThis; + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_DateTime::ToUniversalTime___SystemDateTime( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_INT64* pThis; + CLR_INT64* pRes; + + pThis = Library_corlib_native_System_DateTime::GetValuePtr( stack ); FAULT_ON_NULL(pThis); + pRes = Library_corlib_native_System_DateTime::NewObject ( stack ); + + if ( !(*pThis & s_UTCMask) ) + { + *pRes = *pThis - TIME_ZONE_OFFSET; + // In converted time we need to set UTC mask + *pRes |= s_UTCMask; + } + else + { + // If *pThis is already UTS time - we do not need conversion. + *pRes = *pThis; + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_DateTime::DaysInMonth___STATIC__I4__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_INT32 year = stack.Arg0().NumericByRef().s4; + CLR_INT32 month = stack.Arg1().NumericByRef().s4; + CLR_INT32 days = 0; + + Time_DaysInMonth( year, month, &days ); + + stack.SetResult_I4( days ); + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_DateTime::get_Now___STATIC__SystemDateTime( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_INT64* pRes = NewObject( stack ); + + *pRes = Time_GetLocalTime(); + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_DateTime::get_UtcNow___STATIC__SystemDateTime( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_INT64* pRes = NewObject( stack ); + + *pRes = Time_GetUtcTime() | s_UTCMask; + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_DateTime::get_Today___STATIC__SystemDateTime( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_INT64* pRes = NewObject( stack ); + + { + SYSTEMTIME st; + Time_ToSystemTime( Time_GetLocalTime(), &st ); + + st.wHour = 0; + st.wMinute = 0; + st.wSecond = 0; + st.wMilliseconds = 0; + + *pRes = Time_FromSystemTime( &st ); + } + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +//--// + +CLR_INT64* Library_corlib_native_System_DateTime::NewObject( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& ref = stack.PushValue(); + + ref.SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_DATETIME, 0, 1) ); + ref.ClearData( ); + + return (CLR_INT64*)&ref.NumericByRef().s8; +} + +CLR_INT64* Library_corlib_native_System_DateTime::GetValuePtr( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + return GetValuePtr( stack.Arg0() ); +} + +CLR_INT64* Library_corlib_native_System_DateTime::GetValuePtr( CLR_RT_HeapBlock& ref ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock* obj = &ref; + CLR_DataType dt = obj->DataType(); + + if(dt == DATATYPE_OBJECT || dt == DATATYPE_BYREF) + { + obj = obj->Dereference(); if(!obj) return NULL; + + dt = obj->DataType(); + } + + if(dt == DATATYPE_DATETIME) + { + return (CLR_INT64*)&obj->NumericByRef().s8; + } + + if(dt == DATATYPE_I8) + { + return (CLR_INT64*)&obj->NumericByRef().s8; + } + + if(dt == DATATYPE_VALUETYPE && obj->ObjectCls().m_data == g_CLR_RT_WellKnownTypes.m_DateTime.m_data) + { + return (CLR_INT64*)&obj[ FIELD__m_ticks ].NumericByRef().s8; + } + + return NULL; +} + +void Library_corlib_native_System_DateTime::Expand( CLR_RT_StackFrame& stack, SYSTEMTIME& st ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_INT64* val = GetValuePtr( stack ); + + if(val) + { + // The most significant bit of *val keeps flag if time is UTC. + // We cannot change *val, so we create copy and clear the bit. + CLR_INT64 ticks = *val & s_TickMask; + Time_ToSystemTime( ticks, &st ); + } +} + +// Compress function always creates local time. +void Library_corlib_native_System_DateTime::Compress( CLR_RT_StackFrame& stack, const SYSTEMTIME& st ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_INT64* val = GetValuePtr( stack ); + + if(val) + { + *val = Time_FromSystemTime( &st ); + } +} diff --git a/src/CLR/CorLib/CorLib_Native_System_Exception.cpp b/src/CLR/CorLib/CorLib_Native_System_Exception.cpp new file mode 100644 index 0000000000..7fa6886935 --- /dev/null +++ b/src/CLR/CorLib/CorLib_Native_System_Exception.cpp @@ -0,0 +1,246 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + +struct ExceptionLookup +{ + HRESULT hr; + CLR_RT_TypeDef_Index* ptr; +}; + +static const ExceptionLookup c_ExceptionLookup[] = +{ +#define EL(hr,fld) { hr, &g_CLR_RT_WellKnownTypes.fld } + EL(CLR_E_APPDOMAIN_EXITED , m_AppDomainUnloadedException ), + EL(CLR_E_INVALID_PARAMETER , m_ArgumentException ), + EL(CLR_E_ARGUMENT_NULL , m_ArgumentNullException ), + EL(CLR_E_OUT_OF_RANGE , m_ArgumentOutOfRangeException), + EL(CLR_E_INDEX_OUT_OF_RANGE , m_IndexOutOfRangeException ), + EL(CLR_E_INVALID_CAST , m_InvalidCastException ), + EL(CLR_E_INVALID_OPERATION , m_InvalidOperationException ), + EL(CLR_E_NOT_SUPPORTED , m_NotSupportedException ), + EL(CLR_E_NOTIMPL , m_NotImplementedException ), + EL(CLR_E_NULL_REFERENCE , m_NullReferenceException ), + EL(CLR_E_OUT_OF_MEMORY , m_OutOfMemoryException ), + EL(CLR_E_OBJECT_DISPOSED , m_ObjectDisposedException ), + EL(CLR_E_FILE_IO , m_IOException ), + EL(CLR_E_INVALID_DRIVER , m_IOException ), + EL(CLR_E_FILE_NOT_FOUND , m_IOException ), + EL(CLR_E_DIRECTORY_NOT_FOUND , m_IOException ), + EL(CLR_E_VOLUME_NOT_FOUND , m_IOException ), + EL(CLR_E_PATH_TOO_LONG , m_IOException ), + EL(CLR_E_DIRECTORY_NOT_EMPTY , m_IOException ), + EL(CLR_E_UNAUTHORIZED_ACCESS , m_IOException ), + EL(CLR_E_PATH_ALREADY_EXISTS , m_IOException ), + EL(CLR_E_TOO_MANY_OPEN_HANDLES , m_IOException ), + EL(CLR_E_WATCHDOG_TIMEOUT , m_WatchdogException ), + +#undef EL +}; + +//--// + +HRESULT Library_corlib_native_System_Exception::get_StackTrace___STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock_Array* pArray; + StackTrace* pStackTrace; + CLR_RT_HeapBlock* pBlkString; + char buf[ 512 ]; + LPSTR strName; + size_t iName; + CLR_RT_HeapBlock tmpArray; tmpArray.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc(tmpArray); + int depth = 0; + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + pArray = pThis[ FIELD__m_stackTrace ].DereferenceArray(); + + if(pArray) + { + _ASSERTE(pArray->m_typeOfElement == DATATYPE_U1); + + depth = pArray->m_numOfElements / sizeof(StackTrace); + } + + if(depth == 0) TINYCLR_SET_AND_LEAVE(stack.SetResult_String(NULL)); + + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( tmpArray, depth, g_CLR_RT_WellKnownTypes.m_String )); + + pStackTrace = (StackTrace*)pArray->GetFirstElement(); + pBlkString = (CLR_RT_HeapBlock*)tmpArray.DereferenceArray()->GetFirstElement(); + + for(int i = 0; i < depth; i++) + { + strName = &buf[ 0 ]; + iName = MAXSTRLEN(buf) - 2 ; + + TINYCLR_CHECK_HRESULT(g_CLR_RT_TypeSystem.BuildMethodName( pStackTrace->m_md, strName, iName )); + + memcpy(strName, "\r\n\0", 3); + + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( *pBlkString, buf )); + + pStackTrace++; + pBlkString++; + } + + TINYCLR_SET_AND_LEAVE(Library_corlib_native_System_String::Concat( stack, (CLR_RT_HeapBlock*)tmpArray.DereferenceArray()->GetFirstElement(), depth )); + + TINYCLR_NOCLEANUP(); +} + +//--// + +/* + This function will always succeed. + Return values + - S_OK. + - S_FALSE. ref points to the pre-allocated OutOfMemory exception +*/ +HRESULT Library_corlib_native_System_Exception::CreateInstance( CLR_RT_HeapBlock& ref, const CLR_RT_TypeDef_Index& cls, HRESULT hrIn, CLR_RT_StackFrame* stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + +#if defined(TINYCLR_APPDOMAINS) + CLR_RT_AppDomain* appDomainSav = g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( stack->m_appDomain ); +#endif + + CLR_RT_HeapBlock* obj; + + _ASSERTE(CLR_RT_ExecutionEngine::IsInstanceOf( cls, g_CLR_RT_WellKnownTypes.m_Exception )); + + if(FAILED(hr = g_CLR_RT_ExecutionEngine.NewObjectFromIndex( ref, cls ))) + { +#if defined(TINYCLR_APPDOMAINS) + ref.SetObjectReference( g_CLR_RT_ExecutionEngine.GetCurrentAppDomain()->m_outOfMemoryException ); +#else + ref.SetObjectReference( g_CLR_RT_ExecutionEngine.m_outOfMemoryException ); +#endif + + hrIn = CLR_E_OUT_OF_MEMORY; + hr = S_FALSE; + } + + obj = ref.Dereference(); + + obj[ FIELD__m_HResult ].SetInteger( (CLR_UINT32)hrIn ); + + if(hr == S_OK) + { + (void)SetStackTrace( ref, stack ); + } + +#if defined(TINYCLR_APPDOMAINS) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomainSav ); +#endif + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_Exception::CreateInstance( CLR_RT_HeapBlock& ref, HRESULT hrIn, CLR_RT_StackFrame* stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_TypeDef_Index* cls = &g_CLR_RT_WellKnownTypes.m_Exception; + + _ASSERTE(FAILED(hrIn)); + + for(int i = 0; i < ARRAYSIZE(c_ExceptionLookup); i++) + { + if(c_ExceptionLookup[ i ].hr == hrIn) + { + cls = c_ExceptionLookup[ i ].ptr; + break; + } + } + + return CreateInstance( ref, *cls, hrIn, stack ); +} + +HRESULT Library_corlib_native_System_Exception::SetStackTrace( CLR_RT_HeapBlock& ref, CLR_RT_StackFrame* stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + if(stack) + { + CLR_RT_HeapBlock* obj; + CLR_RT_HeapBlock_Array* array; + StackTrace* dst; + CLR_UINT32 depth; + + if(CLR_RT_ExecutionEngine::IsInstanceOf( ref, g_CLR_RT_WellKnownTypes.m_Exception ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + //--// + + obj = ref.Dereference(); + depth = 0; + + TINYCLR_FOREACH_NODE_BACKWARD__DIRECT(CLR_RT_StackFrame,stackSub,stack) + { + depth++; + } + TINYCLR_FOREACH_NODE_BACKWARD_END(); + + //--// + + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( obj[ FIELD__m_stackTrace ], depth * sizeof(StackTrace), g_CLR_RT_WellKnownTypes.m_UInt8 )); + + //--// + + array = obj[ FIELD__m_stackTrace ].DereferenceArray(); + dst = (StackTrace*)array->GetFirstElement(); + + TINYCLR_FOREACH_NODE_BACKWARD__DIRECT(CLR_RT_StackFrame,stackSub,stack) + { + dst->m_md = stackSub->m_call; + dst->m_IP = (CLR_UINT32)(stackSub->m_IP - stackSub->m_IPstart); + + dst++; + } + TINYCLR_FOREACH_NODE_BACKWARD_END(); + +#if !defined(BUILD_RTM) + //shutting down the EE happens by Thread->Abort. These exceptions are by design, and + //don't need to be logged, or written to the console.... + if(!g_CLR_RT_ExecutionEngine.m_fShuttingDown) +#endif + { + CLR_RT_DUMP::EXCEPTION( *stack, ref ); + } + } + + TINYCLR_NOCLEANUP(); +} + +CLR_RT_HeapBlock* Library_corlib_native_System_Exception::GetTarget( CLR_RT_HeapBlock& ref ) +{ + NATIVE_PROFILE_CLR_CORE(); + return CLR_RT_ExecutionEngine::IsInstanceOf( ref, g_CLR_RT_WellKnownTypes.m_Exception ) ? ref.Dereference() : NULL; +} + +Library_corlib_native_System_Exception::StackTrace* Library_corlib_native_System_Exception::GetStackTrace( CLR_RT_HeapBlock* obj, CLR_UINT32& depth ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(obj) + { + CLR_RT_HeapBlock_Array* array = obj[ FIELD__m_stackTrace ].DereferenceArray(); + + if(array) + { + depth = array->m_numOfElements / sizeof(StackTrace); + + return (StackTrace*)array->GetFirstElement(); + } + } + + depth = 0; + + return NULL; +} diff --git a/src/CLR/CorLib/CorLib_Native_System_String.cpp b/src/CLR/CorLib/CorLib_Native_System_String.cpp new file mode 100644 index 0000000000..78d83fb254 --- /dev/null +++ b/src/CLR/CorLib/CorLib_Native_System_String.cpp @@ -0,0 +1,1085 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +static const CLR_UINT16 c_WhiteSpaces[] = +{ + 0x0009, + 0x000A, + 0x000B, + 0x000C, + 0x000D, + 0x0020, + 0x00A0, + 0x2000, + 0x2001, + 0x2002, + 0x2003, + 0x2004, + 0x2005, + 0x2006, + 0x2007, + 0x2008, + 0x2009, + 0x200A, + 0x200B, + 0x3000, + 0xFEFF, +}; + +//--// + +HRESULT Library_corlib_native_System_String::get_Chars___CHAR__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + LPCSTR szText; + CLR_RT_UnicodeHelper uh; + CLR_UINT16 buf[ 3 ]; + int len; + int index; + + szText = stack.Arg0().RecoverString(); FAULT_ON_NULL(szText); + + uh.SetInputUTF8( szText ); + + len = uh.CountNumberOfCharacters() ; if(len < 0 ) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + index = stack.Arg1().NumericByRef().s4; if(index < 0 || index >= len) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + + uh.m_outputUTF16 = buf; + uh.m_outputUTF16_size = MAXSTRLEN(buf); + + // + // First move to the character, then read it. + // + uh.ConvertFromUTF8( index, true ); + uh.ConvertFromUTF8( 1 , false ); + + stack.SetResult( buf[ 0 ], DATATYPE_CHAR ); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::ToCharArray___SZARRAY_CHAR( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(ToCharArray( stack, 0, -1 )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::ToCharArray___SZARRAY_CHAR__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(ToCharArray( stack, stack.Arg1().NumericByRef().s4, stack.Arg2().NumericByRef().s4 )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::get_Length___I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + LPCSTR szText = stack.Arg0().RecoverString(); FAULT_ON_NULL(szText); + + CLR_RT_UnicodeHelper uh; uh.SetInputUTF8( szText ); + + stack.SetResult_I4( uh.CountNumberOfCharacters() ); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::Split___SZARRAY_STRING__SZARRAY_CHAR( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(Split( stack, stack.Arg1(), 0x7FFFFFFF )); /// Sending INT_MAX instead of -1. + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::Split___SZARRAY_STRING__SZARRAY_CHAR__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(Split( stack, stack.Arg1(), stack.Arg2().NumericByRef().s4 )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::Substring___STRING__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(Substring( stack, stack.Arg1().NumericByRef().s4, -1 )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::Substring___STRING__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_INT32 length = stack.Arg2().NumericByRef().s4; + + if(length < 0) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + + TINYCLR_SET_AND_LEAVE(Substring( stack, stack.Arg1().NumericByRef().s4, length )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::Trim___STRING__SZARRAY_CHAR( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(Trim( stack, stack.Arg1().DereferenceArray(), true, true )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::TrimStart___STRING__SZARRAY_CHAR( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(Trim( stack, stack.Arg1().DereferenceArray(), true, false )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::TrimEnd___STRING__SZARRAY_CHAR( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(Trim( stack, stack.Arg1().DereferenceArray(), false, true )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::_ctor___VOID__SZARRAY_CHAR__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(FromCharArray( stack, stack.Arg2().NumericByRef().s4, stack.Arg3().NumericByRef().s4 )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::_ctor___VOID__SZARRAY_CHAR( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(FromCharArray( stack, 0, -1 )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::_ctor___VOID__CHAR__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_UINT16 ch = stack.Arg1().NumericByRef().u2; + int len = stack.Arg2().NumericByRef().s4; if(len < 0) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + + { + CLR_RT_HeapBlock tmp; tmp.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( tmp ); + + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( tmp, len, g_CLR_RT_WellKnownTypes.m_Char )); + + { + CLR_RT_HeapBlock_Array* tmpArray = tmp.DereferenceArray(); + CLR_UINT16* pTmp = (CLR_UINT16*)tmpArray->GetFirstElement(); + CLR_UINT16* p; + + p = pTmp; while(len--) *p++ = ch; + + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( stack.Arg0(), pTmp, tmpArray->m_numOfElements )); + } + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::CompareTo___I4__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(Library_corlib_native_System_String::CompareTo___I4__STRING( stack )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::CompareTo___I4__STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock& pThis = stack.Arg0(); // String references are special, they don't point to an object, they are the object. So use stack.Arg0() instead of stack.This() + CLR_RT_HeapBlock& pArg = stack.Arg1(); + + stack.SetResult_I4( CLR_RT_HeapBlock::Compare_Unsigned_Values( pThis, pArg ) ); + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_String::IndexOf___I4__CHAR( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__SingleChar )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::IndexOf___I4__CHAR__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__SingleChar | c_IndexOf__StartIndex )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::IndexOf___I4__CHAR__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__SingleChar | c_IndexOf__StartIndex | c_IndexOf__Count )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::IndexOfAny___I4__SZARRAY_CHAR( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__MultipleChars )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::IndexOfAny___I4__SZARRAY_CHAR__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__MultipleChars | c_IndexOf__StartIndex )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::IndexOfAny___I4__SZARRAY_CHAR__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__MultipleChars | c_IndexOf__StartIndex | c_IndexOf__Count )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::IndexOf___I4__STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__String )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::IndexOf___I4__STRING__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__String | c_IndexOf__StartIndex )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::IndexOf___I4__STRING__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__String | c_IndexOf__StartIndex | c_IndexOf__Count )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::LastIndexOf___I4__CHAR( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__SingleChar | c_IndexOf__Last )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::LastIndexOf___I4__CHAR__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__SingleChar | c_IndexOf__Last | c_IndexOf__StartIndex )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::LastIndexOf___I4__CHAR__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__SingleChar | c_IndexOf__Last | c_IndexOf__StartIndex | c_IndexOf__Count )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::LastIndexOfAny___I4__SZARRAY_CHAR( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__MultipleChars | c_IndexOf__Last )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::LastIndexOfAny___I4__SZARRAY_CHAR__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__MultipleChars | c_IndexOf__Last | c_IndexOf__StartIndex )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::LastIndexOfAny___I4__SZARRAY_CHAR__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__MultipleChars | c_IndexOf__Last | c_IndexOf__StartIndex | c_IndexOf__Count )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::LastIndexOf___I4__STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__String | c_IndexOf__Last )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::LastIndexOf___I4__STRING__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__String | c_IndexOf__Last | c_IndexOf__StartIndex )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::LastIndexOf___I4__STRING__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(IndexOf( stack, c_IndexOf__String | c_IndexOf__Last | c_IndexOf__StartIndex | c_IndexOf__Count )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::ToLower___STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(ChangeCase( stack, false )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::ToUpper___STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(ChangeCase( stack, true )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::Trim___STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(Trim( stack, NULL, true, true )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::Equals___STATIC__BOOLEAN__STRING__STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + stack.SetResult_Boolean( CLR_RT_HeapBlock::Compare_Unsigned_Values( stack.Arg0(), stack.Arg1() ) == 0 ); + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_String::op_Equality___STATIC__BOOLEAN__STRING__STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(Library_corlib_native_System_String::Equals___STATIC__BOOLEAN__STRING__STRING( stack )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::op_Inequality___STATIC__BOOLEAN__STRING__STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_CHECK_HRESULT(Library_corlib_native_System_String::Equals___STATIC__BOOLEAN__STRING__STRING( stack )); + + stack.NegateResult(); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::Compare___STATIC__I4__STRING__STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + stack.SetResult_I4( CLR_RT_HeapBlock::Compare_Unsigned_Values( stack.Arg0(), stack.Arg1() ) ); + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_String::Concat___STATIC__STRING__STRING__STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(Concat( stack, &stack.Arg0(), 2 )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::Concat___STATIC__STRING__STRING__STRING__STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(Concat( stack, &stack.Arg0(), 3 )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::Concat___STATIC__STRING__STRING__STRING__STRING__STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(Concat( stack, &stack.Arg0(), 4 )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::Concat___STATIC__STRING__SZARRAY_STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock_Array* pArray = stack.Arg0().DereferenceArray(); FAULT_ON_NULL(pArray); + + TINYCLR_SET_AND_LEAVE(Concat( stack, (CLR_RT_HeapBlock*)pArray->GetFirstElement(), pArray->m_numOfElements )); + + TINYCLR_NOCLEANUP(); +} + +//--// + +HRESULT Library_corlib_native_System_String::FromCharArray( CLR_RT_StackFrame& stack, int startIndex, int length ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock_Array* array; + CLR_UINT32 len; + + array = stack.Arg1().DereferenceArray(); + if (!array || array->m_numOfElements == 0) + { + TINYCLR_SET_AND_LEAVE(CLR_RT_HeapBlock_String::CreateInstance(stack.Arg0(), "")); + } + else + { + len = array->m_numOfElements; + + if (length == -1) + length = len - startIndex; + + if (CLR_RT_HeapBlock_Array::CheckRange(startIndex, length, len) == false) + TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + + TINYCLR_SET_AND_LEAVE(CLR_RT_HeapBlock_String::CreateInstance(stack.Arg0(), (CLR_UINT16*)array->GetElement(startIndex), length)); + } + + TINYCLR_NOCLEANUP(); +} + + +HRESULT Library_corlib_native_System_String::ToCharArray( CLR_RT_StackFrame& stack, int startIndex, int length ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock_Array* array; + + TINYCLR_SET_AND_LEAVE(ConvertToCharArray( stack, stack.PushValueAndClear(), array, startIndex, length )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::IndexOf( CLR_RT_StackFrame& stack, int mode ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + LPCSTR szText; + int startIndex; + int count; + int pos; + LPCSTR pString; + const CLR_UINT16* pChars; + int iChars = 0; + CLR_RT_UnicodeHelper uh; + int len; + + szText = stack.Arg0().RecoverString(); if(!szText) szText = ""; + pos = -1; + pString = NULL; + pChars = NULL; + + if(mode & c_IndexOf__SingleChar) + { + pChars = (CLR_UINT16*)&stack.Arg1().NumericByRefConst().u2; + iChars = 1; + } + else if(mode & c_IndexOf__MultipleChars) + { + CLR_RT_HeapBlock_Array* array = stack.Arg1().DereferenceArray(); FAULT_ON_NULL(array); + + pChars = (const CLR_UINT16*)array->GetFirstElement(); + iChars = array->m_numOfElements; + } + else if(mode & c_IndexOf__String) + { + pString = stack.Arg1().RecoverString(); FAULT_ON_NULL(pString); + } + + + uh.SetInputUTF8( szText ); + + len = uh.CountNumberOfCharacters(); + + //--// + + if(mode & c_IndexOf__StartIndex) + { + startIndex = stack.Arg2().NumericByRefConst().s4; + + if(startIndex < 0 || startIndex > len) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + else + { + startIndex = 0; + } + + if(mode & c_IndexOf__Count) + { + count = stack.Arg3().NumericByRefConst().s4; + + if(startIndex + count > len) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + else + { + count = len - startIndex; + } + + //--// + + // + // First move to the character, then read it. + // + if(uh.ConvertFromUTF8( startIndex, true )) + { + if(pString) + { + while(count-- > 0) + { + CLR_RT_UnicodeHelper uh1; uh1.SetInputUTF8( (LPCSTR)uh.m_inputUTF8 ); + CLR_RT_UnicodeHelper uh2; uh2.SetInputUTF8( pString ); + + while(true) + { + CLR_UINT16 buf1[ 3 ]; + CLR_UINT16 buf2[ 3 ]; + + uh1.m_outputUTF16 = buf1; + uh1.m_outputUTF16_size = MAXSTRLEN(buf1); + + uh2.m_outputUTF16 = buf2; + uh2.m_outputUTF16_size = MAXSTRLEN(buf2); + + if(uh2.ConvertFromUTF8( 1, false ) == false) + { + if((mode & c_IndexOf__Last) || (pos == -1)) + { + pos = startIndex; + } + + break; + } + + if(uh1.ConvertFromUTF8( 1, false ) == false) + { + break; + } + + if(buf1[ 0 ] != buf2[ 0 ]) + { + break; + } + } + + if(uh.ConvertFromUTF8( 1, true ) == false) + { + break; + } + + startIndex++; + } + } + + if(pChars) + { + while(count-- > 0) + { + CLR_UINT16 buf[ 3 ]; + + uh.m_outputUTF16 = buf; + uh.m_outputUTF16_size = MAXSTRLEN(buf); + + if(uh.ConvertFromUTF8( 1, false ) == false) + { + break; + } + + for(int i=0; iGetFirstElement(); + + for(CLR_UINT32 i=0; im_numOfElements; i++) + { + CLR_UINT16 c = *ptr; + + if(fToUpper) + { + if(c >= 'a' && c <= 'z') c += 'A' - 'a'; + } + else + { + if(c >= 'A' && c <= 'Z') c -= 'A' - 'a'; + } + + *ptr++ = c; + } + + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( stack.PushValue(), (CLR_UINT16*)arrayTmp->GetFirstElement(), arrayTmp->m_numOfElements )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::Substring( CLR_RT_StackFrame& stack, int startIndex, int length ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock refTmp; refTmp.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( refTmp ); + CLR_RT_HeapBlock_Array* arrayTmp; + + TINYCLR_CHECK_HRESULT(ConvertToCharArray( stack, refTmp, arrayTmp, 0, -1 )); + + if(startIndex < 0 || startIndex > (int)arrayTmp->m_numOfElements) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + + if(length == -1) + { + length = arrayTmp->m_numOfElements - startIndex; + } + else + { + if(length < 0 || (startIndex + length) > (int)arrayTmp->m_numOfElements) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( stack.PushValue(), (CLR_UINT16*)arrayTmp->GetElement( startIndex ), length )); + + TINYCLR_NOCLEANUP(); +} + + +HRESULT Library_corlib_native_System_String::Trim( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock_Array* arrayTrimChars, bool fStart, bool fEnd ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock refTmp; refTmp.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( refTmp ); + CLR_RT_HeapBlock_Array* arrayTmp; + CLR_UINT16* pSrcStart; + CLR_UINT16* pSrcEnd; + + TINYCLR_CHECK_HRESULT(ConvertToCharArray( stack, refTmp, arrayTmp, 0, -1 )); + + pSrcStart = (CLR_UINT16*)arrayTmp->GetFirstElement(); + pSrcEnd = &pSrcStart[ arrayTmp->m_numOfElements ]; + + const CLR_UINT16* pTrim; + CLR_UINT32 iTrim; + + if(arrayTrimChars && arrayTrimChars->m_numOfElements) + { + pTrim = (const CLR_UINT16*)arrayTrimChars->GetFirstElement(); + iTrim = arrayTrimChars->m_numOfElements; + } + else + { + pTrim = c_WhiteSpaces; + iTrim = ARRAYSIZE(c_WhiteSpaces); + } + + //--// + + if(fStart) + { + while(pSrcStart < pSrcEnd) + { + const CLR_UINT16* p = pTrim; + CLR_UINT32 i; + + for(i=0; im_numOfElements > 0) + { + pChars = (CLR_UINT16*)arrayChars->GetFirstElement(); + cChars = arrayChars->m_numOfElements; + } + else + { + pChars = &c_WhiteSpaces[ 0 ]; + cChars = ARRAYSIZE(c_WhiteSpaces); + } + + arrayDst = NULL; + + { + CLR_RT_HeapBlock refSrc; refSrc.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( refSrc ); + + TINYCLR_CHECK_HRESULT(ConvertToCharArray( stack, refSrc, arraySrc, 0, -1 )); + + for(int pass=0; pass<2; pass++) + { + CLR_UINT16* pSrcStart = (CLR_UINT16*)arraySrc->GetFirstElement(); + CLR_UINT16* pSrc = pSrcStart; + int count = 0; + bool fFound = false; + bool fContinueSearching = true; + + for(CLR_UINT32 iSrc=0; iSrc <= arraySrc->m_numOfElements; iSrc++, pSrc++) + { + if(iSrc == arraySrc->m_numOfElements) + { + fFound = true; + } + else if ((count + 1) >= maxStrings) + { + fContinueSearching = false; + } + else if (fContinueSearching) + { + const CLR_UINT16* pCharsT = pChars; + + for(CLR_UINT32 iChars=0; iCharsGetElement( count ); + + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( *str, pSrcStart, (CLR_UINT32)(pSrc - pSrcStart) )); + + pSrcStart = pSrc + 1; + } + + count++; + fFound = false; + } + } + + if(pass == 0) + { + CLR_RT_HeapBlock& refTarget = stack.PushValue(); + + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( refTarget, count, g_CLR_RT_WellKnownTypes.m_String )); + + arrayDst = refTarget.DereferenceArray(); + } + } + } + } + + TINYCLR_NOCLEANUP(); +} + +//--// + +HRESULT Library_corlib_native_System_String::Concat( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock* array, int num ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock* ptrSrc; + LPCSTR szTextSrc; + LPSTR szTextDst = NULL; + CLR_UINT32 totLen; + CLR_UINT32 len; + + totLen = 0; + + for(int i=0; i<2; i++) + { + ptrSrc = array; + + for(int iStr=0; iStrDataType() == DATATYPE_OBJECT); + _ASSERTE(FIMPLIES(ptrSrc->Dereference(), ptrSrc->Dereference()->DataType() == DATATYPE_STRING)); + + szTextSrc = ptrSrc->RecoverString(); + if(szTextSrc) + { + len = (CLR_UINT32)hal_strlen_s( szTextSrc ); + + if(i==0) + { + totLen += len; + } + else + { + memcpy( szTextDst, szTextSrc, len ); + + szTextDst += len; + } + } + + ptrSrc++; + } + + if(i==0) + { + //push return value + CLR_RT_HeapBlock& blkResult = stack.PushValue(); + CLR_RT_HeapBlock_String* str = CLR_RT_HeapBlock_String::CreateInstance( blkResult, totLen ); CHECK_ALLOCATION(str); + + szTextDst = (LPSTR)str->StringText(); + szTextDst[ totLen ] = 0; + } + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::ConvertToCharArray( LPCSTR szText, CLR_RT_HeapBlock& ref, CLR_RT_HeapBlock_Array*& array, int startIndex, int length ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_UnicodeHelper uh; + int totLength; + + FAULT_ON_NULL(szText); + + uh.SetInputUTF8( szText ); + + totLength = uh.CountNumberOfCharacters(); if(totLength < 0) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + if(length == -1) length = totLength; + + if(CLR_RT_HeapBlock_Array::CheckRange( startIndex, length, totLength ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( ref, length, g_CLR_RT_WellKnownTypes.m_Char )); + + array = ref.DereferenceArray(); + + uh.m_outputUTF16 = (CLR_UINT16*)array->GetFirstElement(); + uh.m_outputUTF16_size = array->m_numOfElements; + + // + // First move to the character, then read it. + // + uh.ConvertFromUTF8( startIndex , true ); + uh.ConvertFromUTF8( array->m_numOfElements, false ); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_String::ConvertToCharArray( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock& ref, CLR_RT_HeapBlock_Array*& array, int startIndex, int length ) +{ + NATIVE_PROFILE_CLR_CORE(); + return ConvertToCharArray( stack.Arg0().RecoverString(), ref, array, startIndex, length ); +} diff --git a/src/CLR/CorLib/CorLib_Native_System_Threading_Thread.cpp b/src/CLR/CorLib/CorLib_Native_System_Threading_Thread.cpp new file mode 100644 index 0000000000..3b25ea3ffd --- /dev/null +++ b/src/CLR/CorLib/CorLib_Native_System_Threading_Thread.cpp @@ -0,0 +1,568 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + +//--// + +HRESULT Library_corlib_native_System_Threading_Thread::_ctor___VOID__SystemThreadingThreadStart( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock* pThis = stack.This(); + + pThis[ FIELD__m_Delegate ].Assign ( stack.Arg1() ); + + // Thread is always constructed with normal priority. + pThis[ FIELD__m_Priority ].NumericByRef().s4 = ThreadPriority::Normal; + + // Book a Thread ID + pThis[ FIELD__m_Id ].NumericByRef().s4 = g_CLR_RT_ExecutionEngine.GetNextThreadId(); + + +#if defined(TINYCLR_APPDOMAINS) + TINYCLR_CHECK_HRESULT(CLR_RT_ObjectToEvent_Source::CreateInstance( g_CLR_RT_ExecutionEngine.GetCurrentAppDomain(), *pThis, pThis[ FIELD__m_AppDomain ] )); + TINYCLR_NOCLEANUP(); +#else + TINYCLR_NOCLEANUP_NOLABEL(); +#endif + +} + +HRESULT Library_corlib_native_System_Threading_Thread::Start___VOID( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_Thread* th; + CLR_RT_HeapBlock* pThis; + CLR_RT_HeapBlock_Delegate* dlg; + int pri; + + // + // Don't start twice... + // + TINYCLR_CHECK_HRESULT(GetThread( stack, th, false, false )); + if(th != NULL) + { + TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + pThis = stack.This(); FAULT_ON_NULL(pThis); + dlg = pThis[ FIELD__m_Delegate ].DereferenceDelegate(); FAULT_ON_NULL(dlg ); + + // Set priority of new sub-thread to the priority stored in the thread C# object. + // The new sub-thread becames the current one, it should always match priority stored in Thread C# object + + pri = pThis[ FIELD__m_Priority ].NumericByRef().s4; + + pThis->ResetFlags( CLR_RT_HeapBlock::HB_Signaled ); + + TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewThread( th, dlg, pri, pThis[ FIELD__m_Id ].NumericByRef().s4 )); + + TINYCLR_SET_AND_LEAVE(SetThread( stack, th )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Threading_Thread::Abort___VOID( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_Thread* th; + + TINYCLR_CHECK_HRESULT(GetThread( stack, th, true, true )); + + if(th == stack.m_owningThread) + { + TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + th->Abort(); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Threading_Thread::Suspend___VOID( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + // Test if this the call from managed Thread.Suspend() or second call on resume. + switch( stack.m_customState ) + { + // This is the normal call from managed code. + case 0: + { + CLR_RT_Thread* th; + + TINYCLR_CHECK_HRESULT(GetThread( stack, th, true, true )); + + TINYCLR_CHECK_HRESULT(th->Suspend()); + + // If the thread suspends itself, then we need to re-schedule. + if ( stack.m_owningThread == th ) + { // Set flag in thread stack that thread is re-scheduled. + stack.m_customState = 1; + + // Call to th->Suspend() was successful and moved thread to suspended list. + // Now the threads should be re-scheduled to make suspension effective immidiately. + // In order to do it we return CLR_E_RESCHEDULE from this function - Suspend___VOID + TINYCLR_SET_AND_LEAVE( CLR_E_RESCHEDULE ); + } + } + + // This is the case when thread is resumed, brought back from suspeneded state. + case 1: + { + stack.m_customState = 0; + TINYCLR_SET_AND_LEAVE(S_OK); + } + + default: + TINYCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Threading_Thread::Resume___VOID( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_Thread* th; + + TINYCLR_CHECK_HRESULT(GetThread( stack, th, true, true )); + + TINYCLR_SET_AND_LEAVE(th->Resume()); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Threading_Thread::get_Priority___SystemThreadingThreadPriority( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_Thread* th; + int pri; + + // Get C# thread object + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Reads priority stored in C# object. + pri = pThis[ FIELD__m_Priority ].NumericByRef().s4; + + // Here we check consistency of values stored in C# and internal thread objects. + // Get thread associated with C# thread object. It might be NULL if thread was not started. + TINYCLR_CHECK_HRESULT(GetThread( stack, th, false, false )); + + // If thread was started, then we use priority from the CLR_RT_Thread. + // There are 2 reasons it might be different from priority from C# object: + // 1. The manager C# object was garbage collected and then re-created. + // 2. Sub-thread with different priority may have been created in Library_spot_native_Microsoft_SPOT_ExecutionConstraint::Install___STATIC__VOID__I4__I4 + + if ( th != NULL ) + { + pri = th->GetThreadPriority(); + + // We store it back to managed object to keep values consistent. + pThis[ FIELD__m_Priority ].NumericByRef().s4 = pri; + } + + // Zero priority correspond is equal to managed. ThreadPriority.Lowest. + // The highest value should be 4 ( ThreadPriority.highest ), but we allow higher values. + // Users cannot create threads with values outside the Lowest-Highest range; we exceed that + // range internally, but we can't expose those values to managed code. + if (pri < ThreadPriority::Lowest ) pri = ThreadPriority::Lowest; + else if (pri > ThreadPriority::Highest) pri = ThreadPriority::Highest; + + // Return value back to C# code. + stack.SetResult_I4( pri ); + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Threading_Thread::set_Priority___VOID__SystemThreadingThreadPriority( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + if ( stack.m_customState == 0 ) + { + CLR_RT_Thread* th; + + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Get argument for priority. Check the range - should be between ThreadPriority::Highest and ThreadPriority::Lowest ( 0 - 4 ) + int pri = stack.Arg1().NumericByRef().s4; + if ( pri < ThreadPriority::Lowest || pri > ThreadPriority::Highest ) + { + TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + // Get CLR thread. The object exists if thread was started. + TINYCLR_CHECK_HRESULT(GetThread( stack, th, false, true )); + + // Save priority to managed C# object + pThis[ FIELD__m_Priority ].NumericByRef().s4 = pri; + + if ( th ) + { + // Priority of current sub-thread is set the thread priority. + th->SetThreadPriority( pri ); + + stack.m_customState = 1; + + // If we set high priority to another thread, then we need to swtich to another thread. + if ( pri > stack.m_owningThread->GetThreadPriority() ) + { + TINYCLR_SET_AND_LEAVE(CLR_E_RESCHEDULE); + } + } + } + + TINYCLR_NOCLEANUP(); + +} + +HRESULT Library_corlib_native_System_Threading_Thread::get_ManagedThreadId___I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + int id; + + // Get C# thread object + CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); + + // Reads priority stored in C# object. + id = pThis[ FIELD__m_Id ].NumericByRef().s4; + + // Return value back to C# code. + stack.SetResult_I4( id ); + TINYCLR_NOCLEANUP(); +} + + +HRESULT Library_corlib_native_System_Threading_Thread::get_IsAlive___BOOLEAN( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_Thread* th; + + GetThread( stack, th, false, false ); + + stack.SetResult_Boolean( th != NULL && th->m_status != CLR_RT_Thread::TH_S_Terminated ); + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT Library_corlib_native_System_Threading_Thread::Join___VOID( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(Join( stack, TIMEOUT_INFINITE )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Threading_Thread::Join___BOOLEAN__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_INT64 timeExpire; + + TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.InitTimeout( timeExpire, stack.Arg1().NumericByRef().s4 )); + + TINYCLR_SET_AND_LEAVE(Join( stack, timeExpire )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Threading_Thread::Join___BOOLEAN__SystemTimeSpan( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_INT64* timeExpireIn; + CLR_INT64 timeExpireOut; + + timeExpireIn = Library_corlib_native_System_TimeSpan::GetValuePtr( stack.Arg1() ); FAULT_ON_NULL(timeExpireIn); + + TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.InitTimeout( timeExpireOut, *timeExpireIn )); + + TINYCLR_SET_AND_LEAVE(Join( stack, timeExpireOut )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Threading_Thread::get_ThreadState___SystemThreadingThreadState( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + + TINYCLR_HEADER(); + + CLR_RT_Thread* th; + int val = 0; + + TINYCLR_CHECK_HRESULT(GetThread( stack, th, false, false )); + + if(th == NULL) + { + val = 8; //Unstarted + } + else + { + switch(th->m_status) + { + case CLR_RT_Thread::TH_S_Ready : val = 0; break; // Running + case CLR_RT_Thread::TH_S_Waiting : val = 32; break; // WaitSleepJoin + case CLR_RT_Thread::TH_S_Terminated: val = 16; break; // Stopped + default : _ASSERTE(FALSE); break; + } + + // Suspended thread. Add ThreadState.Suspended to the return value + if(th->m_flags & CLR_RT_Thread::TH_F_Suspended) + { + val |= 64; // ThreadState.Suspended = 64 + } + // Aborted thread. Add ThreadState.Aborted to the return value + if(th->m_flags & CLR_RT_Thread::TH_F_Aborted) + { + val |= 256; // ThreadState.Aborted = 256 + } + + } + + stack.SetResult_I4( val ); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Threading_Thread::Sleep___STATIC__VOID__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_INT64 timeExpire; + CLR_INT32 timeSleep; + + switch(stack.m_customState) + { + case 0: + + timeSleep = stack.m_arguments[ 0 ].NumericByRef().s4; + if ( timeSleep != 0 ) + { + TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.InitTimeout( timeExpire, stack.m_arguments[ 0 ].NumericByRef().s4 )); + + hr = g_CLR_RT_ExecutionEngine.Sleep( stack.m_owningThread, timeExpire ); + if(hr == CLR_E_THREAD_WAITING) + { + stack.m_customState = 1; + } + } + else + { + // In case of Sleep(0) call the threads should be re-scheduled . + // This function updates execution counter in pThread and makes it last to execute. + // Used to Thread.Sleep(0) imlementation. The thread is still ready, but is last to execute. + g_CLR_RT_ExecutionEngine.UpdateToLowestExecutionCounter( stack.m_owningThread ); + // In order to do it we return CLR_E_RESCHEDULE from this function. + stack.m_customState = 1; + TINYCLR_SET_AND_LEAVE( CLR_E_RESCHEDULE ); + } + + + TINYCLR_LEAVE(); + + case 1: + TINYCLR_SET_AND_LEAVE(S_OK); + + default: + TINYCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Threading_Thread::get_CurrentThread___STATIC__SystemThreadingThread( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_Thread* thread = stack.m_owningThread; + CLR_RT_HeapBlock& top = stack.PushValueAndClear(); + CLR_RT_HeapBlock* pRes; + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + //If we are a thread spawned by the debugger to perform evaluations, + //return the thread object that correspond to thread that has focus in debugger. + thread = thread->m_realThread; +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + //Find an existing managed thread, if it exists + //making sure to only return the managed object association with the current appdomain + //to prevent leaking of managed Thread objects across AD boundaries. + TINYCLR_FOREACH_NODE(CLR_RT_ObjectToEvent_Source,src,thread->m_references) + { + CLR_RT_HeapBlock* pManagedThread = src->m_objectPtr; + bool fFound = false; + _ASSERTE(pManagedThread != NULL); + +#if defined(TINYCLR_APPDOMAINS) + { + CLR_RT_ObjectToEvent_Source* appDomainSrc = CLR_RT_ObjectToEvent_Source::ExtractInstance( pManagedThread[ FIELD__m_AppDomain ] ); + + FAULT_ON_NULL_HR(appDomainSrc, CLR_E_FAIL); + + fFound = (appDomainSrc->m_eventPtr == g_CLR_RT_ExecutionEngine.GetCurrentAppDomain()); + } +#else + fFound = true; +#endif + + if(fFound) + { + top.SetObjectReference( pManagedThread ); + + TINYCLR_SET_AND_LEAVE(S_OK); + } + } + TINYCLR_FOREACH_NODE_END(); + + + //Create the managed thread. + //This implies that there is no state in the managed object. This is not exactly true, as the managed thread + //contains the priority as well as the delegate to start. However, that state is really just used as a placeholder for + //the data before the thread is started. Once the thread is started, they are copied over to the unmanaged thread object + //and no longer used. The managed object is then used simply as a wrapper for the unmanaged thread. Therefore, it is safe + //to simply make another managed thread here. + TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex( top, g_CLR_RT_WellKnownTypes.m_Thread )); + + pRes = top.Dereference(); + + TINYCLR_CHECK_HRESULT(CLR_RT_ObjectToEvent_Source::CreateInstance( thread, *pRes, pRes[ FIELD__m_Thread ] )); + +#if defined(TINYCLR_APPDOMAINS) + TINYCLR_CHECK_HRESULT(CLR_RT_ObjectToEvent_Source::CreateInstance( g_CLR_RT_ExecutionEngine.GetCurrentAppDomain(), *pRes, pRes[ FIELD__m_AppDomain ] )); +#endif + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Threading_Thread::GetDomain___STATIC__SystemAppDomain( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + +#if !defined(TINYCLR_APPDOMAINS) + TINYCLR_SET_AND_LEAVE(stack.NotImplementedStub()); +#else + CLR_RT_AppDomain* appDomain = g_CLR_RT_ExecutionEngine.GetCurrentAppDomain(); + + TINYCLR_CHECK_HRESULT(appDomain->GetManagedObject( stack.PushValue() )); +#endif + + TINYCLR_NOCLEANUP(); +} + +//--// + +CLR_RT_ObjectToEvent_Source* Library_corlib_native_System_Threading_Thread::GetThreadReference( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock* pThis = stack.This(); + + return CLR_RT_ObjectToEvent_Source::ExtractInstance( pThis[ FIELD__m_Thread ] ); +} + +void Library_corlib_native_System_Threading_Thread::ResetThreadReference( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_ObjectToEvent_Source* src = GetThreadReference( stack ); + if(src) + { + src->Detach(); + } +} + +HRESULT Library_corlib_native_System_Threading_Thread::SetThread( CLR_RT_StackFrame& stack, CLR_RT_Thread* th ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock* pThis = stack.This(); + + ResetThreadReference( stack ); + + TINYCLR_SET_AND_LEAVE(CLR_RT_ObjectToEvent_Source::CreateInstance( th, *pThis, pThis[ FIELD__m_Thread ] )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Threading_Thread::GetThread( CLR_RT_StackFrame& stack, CLR_RT_Thread*& th, bool mustBeStarted, bool noSystemThreads ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + CLR_RT_ObjectToEvent_Source* src = GetThreadReference( stack ); + + th = (src == NULL) ? NULL : (CLR_RT_Thread*)src->m_eventPtr; + if(th == NULL) + { + if (mustBeStarted) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + else if (noSystemThreads && th->m_flags & CLR_RT_Thread::TH_F_System) + { + TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_OPERATION); + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_Threading_Thread::Join( CLR_RT_StackFrame& stack, const CLR_INT64& timeExpire ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_Thread* th; + bool fRes = true; + + TINYCLR_CHECK_HRESULT(GetThread( stack, th, true, false )); + + //Don't let programs join from system threads like interrupts or finalizers + if ( stack.m_owningThread->m_flags & CLR_RT_Thread::TH_F_System ) + { + TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_OPERATION); + } + + // + // You cannot join yourself. + // + if(th == stack.m_owningThread) + { + TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + if(th->m_status != CLR_RT_Thread::TH_S_Terminated) + { + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_WaitForObject::WaitForSignal( stack, timeExpire, stack.ThisRef() )); + + fRes = (stack.m_owningThread->m_waitForObject_Result != CLR_RT_Thread::TH_WAIT_RESULT_TIMEOUT); + } + + stack.SetResult_Boolean( fRes ); + + TINYCLR_NOCLEANUP(); +} diff --git a/src/CLR/CorLib/CorLib_Native_System_TimeSpan.cpp b/src/CLR/CorLib/CorLib_Native_System_TimeSpan.cpp new file mode 100644 index 0000000000..c56f1e4eff --- /dev/null +++ b/src/CLR/CorLib/CorLib_Native_System_TimeSpan.cpp @@ -0,0 +1,193 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CorLib.h" + + +HRESULT Library_corlib_native_System_TimeSpan::Equals___BOOLEAN__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_CHECK_HRESULT(CompareTo___I4__OBJECT( stack )); + + { + CLR_RT_HeapBlock& res = stack.TopValue(); + + res.SetBoolean( res.NumericByRef().s4 == 0 ); + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_TimeSpan::ToString___STRING( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + char rgBuffer[ 128 ]; + LPSTR szBuffer = rgBuffer; + size_t iBuffer = ARRAYSIZE(rgBuffer); + CLR_INT64* val = GetValuePtr( stack ); FAULT_ON_NULL(val); + + Time_TimeSpanToStringEx( *val, szBuffer, iBuffer ); + + TINYCLR_SET_AND_LEAVE(stack.SetResult_String( rgBuffer )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_TimeSpan::_ctor___VOID__I4__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock* pArgs = &(stack.Arg1()); + CLR_INT64* val = GetValuePtr( stack ); FAULT_ON_NULL(val); + + ConstructTimeSpan( val, 0, pArgs[ 0 ].NumericByRef().s4, pArgs[ 1 ].NumericByRef().s4, pArgs[ 2 ].NumericByRef().s4, 0 ); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_TimeSpan::_ctor___VOID__I4__I4__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock* pArgs = &(stack.Arg1()); + CLR_INT64* val = GetValuePtr( stack ); FAULT_ON_NULL(val); + + ConstructTimeSpan( val, pArgs[ 0 ].NumericByRef().s4, pArgs[ 1 ].NumericByRef().s4, pArgs[ 2 ].NumericByRef().s4, pArgs[ 3 ].NumericByRef().s4, 0 ); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_TimeSpan::_ctor___VOID__I4__I4__I4__I4__I4( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock* pArgs = &(stack.Arg1()); + CLR_INT64* val = GetValuePtr( stack ); FAULT_ON_NULL(val); + + ConstructTimeSpan( val, pArgs[ 0 ].NumericByRef().s4, pArgs[ 1 ].NumericByRef().s4, pArgs[ 2 ].NumericByRef().s4, pArgs[ 3 ].NumericByRef().s4, pArgs[ 4 ].NumericByRef().s4 ); + + TINYCLR_NOCLEANUP(); +} + +void Library_corlib_native_System_TimeSpan::ConstructTimeSpan( CLR_INT64* val, CLR_INT32 days, CLR_INT32 hours, CLR_INT32 minutes, CLR_INT32 seconds, CLR_INT32 msec ) + +{ + *val = ((CLR_INT64)days) * TIME_CONVERSION__ONEDAY + + hours * TIME_CONVERSION__ONEHOUR + + minutes * TIME_CONVERSION__ONEMINUTE + + seconds * TIME_CONVERSION__ONESECOND; + + *val *= 1000; + *val += msec; + *val *= TIME_CONVERSION__TICKUNITS; +} + +HRESULT Library_corlib_native_System_TimeSpan::CompareTo___I4__OBJECT( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock* pLeft = stack.This(); + CLR_RT_HeapBlock* pRight = stack.Arg1().Dereference(); + + if(pRight) + { + TINYCLR_SET_AND_LEAVE(Compare___STATIC__I4__SystemTimeSpan__SystemTimeSpan( stack )); + } + + stack.SetResult_I4( 1 ); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_TimeSpan::Compare___STATIC__I4__SystemTimeSpan__SystemTimeSpan( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_INT64* pLeft; + CLR_INT64* pRight; + CLR_RT_HeapBlock resLeft; + CLR_RT_HeapBlock resRight; + + pLeft = Library_corlib_native_System_TimeSpan::GetValuePtr( stack ); FAULT_ON_NULL(pLeft); + pRight = Library_corlib_native_System_TimeSpan::GetValuePtr( stack.Arg1() ); FAULT_ON_NULL(pRight); + + resLeft .SetInteger( *pLeft ); + resRight.SetInteger( *pRight ); + + stack.SetResult_I4( CLR_RT_HeapBlock::Compare_Signed_Values( resLeft, resRight ) ); + + TINYCLR_NOCLEANUP(); +} + +HRESULT Library_corlib_native_System_TimeSpan::Equals___STATIC__BOOLEAN__SystemTimeSpan__SystemTimeSpan( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_CHECK_HRESULT(Compare___STATIC__I4__SystemTimeSpan__SystemTimeSpan( stack )); + + stack.ConvertResultToBoolean(); + + TINYCLR_NOCLEANUP(); +} + +//--// + +CLR_INT64* Library_corlib_native_System_TimeSpan::NewObject( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& ref = stack.PushValue(); + + ref.SetDataId( CLR_RT_HEAPBLOCK_RAW_ID( DATATYPE_TIMESPAN, 0, 1 ) ); + ref.ClearData( ); + + return (CLR_INT64*)&ref.NumericByRef().s8; +} + +CLR_INT64* Library_corlib_native_System_TimeSpan::GetValuePtr( CLR_RT_StackFrame& stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + return GetValuePtr( stack.Arg0() ); +} + +CLR_INT64* Library_corlib_native_System_TimeSpan::GetValuePtr( CLR_RT_HeapBlock& ref ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock* obj = &ref; + CLR_DataType dt = obj->DataType(); + + if(dt == DATATYPE_OBJECT || dt == DATATYPE_BYREF) + { + obj = obj->Dereference(); if(!obj) return NULL; + + dt = obj->DataType(); + } + + if(dt == DATATYPE_TIMESPAN) + { + return (CLR_INT64*)&obj->NumericByRef().s8; + } + + if(dt == DATATYPE_I8) + { + return (CLR_INT64*)&obj->NumericByRef().s8; + } + + if(dt == DATATYPE_VALUETYPE && obj->ObjectCls().m_data == g_CLR_RT_WellKnownTypes.m_TimeSpan.m_data) + { + return (CLR_INT64*)&obj[ FIELD__m_ticks ].NumericByRef().s8; + } + + return NULL; +} diff --git a/src/CLR/Core/CLR_RT_DblLinkedList.cpp b/src/CLR/Core/CLR_RT_DblLinkedList.cpp new file mode 100644 index 0000000000..66511cb655 --- /dev/null +++ b/src/CLR/Core/CLR_RT_DblLinkedList.cpp @@ -0,0 +1,88 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_DblLinkedList::DblLinkedList_Initialize() +{ + NATIVE_PROFILE_CLR_CORE(); + m_first = Tail(); + m_null = NULL; + m_last = Head(); +} + +void CLR_RT_DblLinkedList::DblLinkedList_PushToCache() +{ + NATIVE_PROFILE_CLR_CORE(); + ValidateList(); + + while(true) + { + CLR_RT_HeapBlock_Node* node = ExtractFirstNode(); if(!node) break; + + g_CLR_RT_EventCache.Append_Node( node ); + } +} + +void CLR_RT_DblLinkedList::DblLinkedList_Release() +{ + NATIVE_PROFILE_CLR_CORE(); + ValidateList(); + + while(true) + { + CLR_RT_HeapBlock_Node* node = ExtractFirstNode(); if(!node) break; + + CLR_RT_Memory::Release( node ); + } +} + +int CLR_RT_DblLinkedList::NumOfNodes() +{ + NATIVE_PROFILE_CLR_CORE(); + ValidateList(); + + int num = 0; + + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_Node,node,(*this)) + { + num++; + } + TINYCLR_FOREACH_NODE_END(); + + return num; +} + +void CLR_RT_DblLinkedList::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_first ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_last ); +} + +#if TINYCLR_VALIDATE_HEAP >= TINYCLR_VALIDATE_HEAP_2_DblLinkedList + +void CLR_RT_DblLinkedList::ValidateList() +{ + NATIVE_PROFILE_CLR_CORE(); + + if(m_null != NULL) TINYCLR_DEBUG_STOP(); + + CLR_RT_HeapBlock_Node* prev = Head(); + CLR_RT_HeapBlock_Node* node = prev->Next(); + + while(node) + { + if(node->Prev() != prev) TINYCLR_DEBUG_STOP(); + + prev = node; + node = prev->Next(); + } +} + +#endif + diff --git a/src/CLR/Core/CLR_RT_HeapBlock.cpp b/src/CLR/Core/CLR_RT_HeapBlock.cpp new file mode 100644 index 0000000000..b773e7ca8c --- /dev/null +++ b/src/CLR/Core/CLR_RT_HeapBlock.cpp @@ -0,0 +1,1976 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_HeapBlock::InitializeToZero() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_Memory::ZeroFill( &m_data, this->DataSize() * sizeof(*this) - offsetof(CLR_RT_HeapBlock,m_data) ); +} + +//--//--//--//--//--// + +#if defined(TINYCLR_EMULATED_FLOATINGPOINT) + +HRESULT CLR_RT_HeapBlock::SetFloatIEEE754( const CLR_UINT32 arg ) +{ + + CLR_INT32 res; + CLR_UINT32 mantissa = ( arg & 0x007FFFFF) | 0x00800000; + int exponent = (int)((arg >> 23) & 0x000000FF) - 127; + + exponent -= (23 - CLR_RT_HeapBlock::HB_FloatShift); + + if(arg == 0) + { + res = 0; + } + else if(exponent <= -31) + { + res = 0; + + // + // Uncomment to produce an overflow exception for emulated floating points + // + // return CLR_E_OUT_OF_RANGE; + } + else if(exponent >= 31) + { + res = 0x7FFFFFFF; + + // + // Uncomment to produce an overflow exception for emulated floating points + // + // return CLR_E_OUT_OF_RANGE; + } + else + { + if(exponent > 0) + { + CLR_UINT64 tmpRes; + + tmpRes = ((CLR_UINT64)mantissa) << exponent; + + if(0 != (tmpRes >> 31)) + { + res = 0x7FFFFFFF; + + // + // Uncomment to produce an overflow exception for emulated floating points + // + // return CLR_E_OUT_OF_RANGE; + } + else + { + res = (CLR_UINT32)tmpRes; + } + } + else if(exponent < 0) res = mantissa >> (-exponent); + else res = mantissa; + } + + if(arg & 0x80000000) res = -res; + + SetFloat( res ); + + return S_OK; +} + +HRESULT CLR_RT_HeapBlock::SetDoubleIEEE754( const CLR_UINT64& arg ) +{ + + CLR_INT64 res; + CLR_UINT64 mantissa = ( arg & ULONGLONGCONSTANT(0x000FFFFFFFFFFFFF)) | ULONGLONGCONSTANT(0x0010000000000000); + int exponent = (int)((arg >> 52) & ULONGLONGCONSTANT(0x00000000000007FF)) - 1023; + + CLR_UINT64 mask = ULONGLONGCONSTANT(0xFFFFFFFFFFFFFFFF); + + exponent -= (52 - CLR_RT_HeapBlock::HB_DoubleShift); + + if(arg == 0) + { + res = 0; + } + else if(exponent <= -63) + { + res = 0; + + // + // Uncomment to produce an overflow exception for emulated floating points + // + // return CLR_E_OUT_OF_RANGE; + } + else if(exponent >= 63) + { + res = ULONGLONGCONSTANT(0x7FFFFFFFFFFFFFFF); + + // + // Uncomment to produce an overflow exception for emulated floating points + // + // return CLR_E_OUT_OF_RANGE; + } + else + { + if(exponent > 0) + { + mask <<= (63 - exponent); + + if(0 != (mask & mantissa)) + { + res = ULONGLONGCONSTANT(0x7FFFFFFFFFFFFFFF); + + // + // Uncomment to produce an overflow exception for emulated floating points + // + // return CLR_E_OUT_OF_RANGE; + } + else + { + res = mantissa << exponent; + } + } + else if(exponent < 0) res = mantissa >> (-exponent); + else res = mantissa; + } + + if(arg & ULONGLONGCONSTANT(0x8000000000000000)) res = -res; + + SetDouble( res ); + + return S_OK; +} + +#endif + + + +HRESULT CLR_RT_HeapBlock::EnsureObjectReference( CLR_RT_HeapBlock*& obj ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + switch(this->DataType()) + { + case DATATYPE_OBJECT: + case DATATYPE_BYREF: + { + obj = Dereference(); FAULT_ON_NULL(obj); + +#if defined(TINYCLR_APPDOMAINS) + if(obj->DataType() == DATATYPE_TRANSPARENT_PROXY) + { + TINYCLR_CHECK_HRESULT(obj->TransparentProxyValidate()); + obj = obj->TransparentProxyDereference(); FAULT_ON_NULL(obj); + } +#endif + switch(obj->DataType()) + { + case DATATYPE_CLASS : + case DATATYPE_VALUETYPE: + + case DATATYPE_DATETIME: // Special case. + case DATATYPE_TIMESPAN: // Special case. + + TINYCLR_SET_AND_LEAVE(S_OK); + } + } + break; + + case DATATYPE_DATETIME: // Special case. + case DATATYPE_TIMESPAN: // Special case. + obj = this; + + TINYCLR_SET_AND_LEAVE(S_OK); + } + + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + TINYCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_HeapBlock::SetReflection( const CLR_RT_ReflectionDef_Index& reflex ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_REFLECTION,0,1); + m_data.reflection = reflex; + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT CLR_RT_HeapBlock::SetReflection( const CLR_RT_Assembly_Index& assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_REFLECTION,0,1); + m_data.reflection.m_kind = REFLECTION_ASSEMBLY; + m_data.reflection.m_levels = 0; + m_data.reflection.m_data.m_assm = assm; + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT CLR_RT_HeapBlock::SetReflection( const CLR_RT_TypeSpec_Index& sig ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_TypeDescriptor desc; + + TINYCLR_CHECK_HRESULT(desc.InitializeFromTypeSpec( sig )); + + m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_REFLECTION,0,1); + m_data.reflection = desc.m_reflex; + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock::SetReflection( const CLR_RT_TypeDef_Index& cls ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_REFLECTION,0,1); + m_data.reflection.m_kind = REFLECTION_TYPE; + m_data.reflection.m_levels = 0; + m_data.reflection.m_data.m_type = cls; + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT CLR_RT_HeapBlock::SetReflection( const CLR_RT_FieldDef_Index& fd ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_REFLECTION,0,1); + m_data.reflection.m_kind = REFLECTION_FIELD; + m_data.reflection.m_levels = 0; + m_data.reflection.m_data.m_field = fd; + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT CLR_RT_HeapBlock::SetReflection( const CLR_RT_MethodDef_Index& md ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_MethodDef_Instance inst; + + if(inst.InitializeFromIndex( md ) == false) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_REFLECTION,0,1); + m_data.reflection.m_kind = (inst.m_target->flags & CLR_RECORD_METHODDEF::MD_Constructor) ? REFLECTION_CONSTRUCTOR : REFLECTION_METHOD; + m_data.reflection.m_levels = 0; + m_data.reflection.m_data.m_method = md; + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock::SetObjectCls( const CLR_RT_TypeDef_Index& cls ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_TypeDef_Instance inst; + + if(inst.InitializeFromIndex( cls ) == false) + { + TINYCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + m_data.objectHeader.cls = cls; + m_data.objectHeader.lock = NULL; + + TINYCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_HeapBlock::InitializeArrayReference( CLR_RT_HeapBlock& ref, int index ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock_Array* array; + + if(ref.DataType() != DATATYPE_OBJECT) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + array = ref.DereferenceArray(); FAULT_ON_NULL(array); + + if(array->DataType() != DATATYPE_SZARRAY) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + if(index < 0 || index >= (CLR_INT32)array->m_numOfElements) + { + TINYCLR_SET_AND_LEAVE(CLR_E_INDEX_OUT_OF_RANGE); + } + + InitializeArrayReferenceDirect( *array, index ); + + TINYCLR_NOCLEANUP(); +} + +void CLR_RT_HeapBlock::InitializeArrayReferenceDirect( CLR_RT_HeapBlock_Array& array, int index ) +{ + NATIVE_PROFILE_CLR_CORE(); + m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_ARRAY_BYREF,0,1); + m_data.arrayReference.array = &array; + m_data.arrayReference.index = index; +} + +void CLR_RT_HeapBlock::FixArrayReferenceForValueTypes() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock_Array* array = m_data.arrayReference.array; + + // + // ValueTypes are implemented as pointers to objects, + // so getting an array reference to a ValueType has to be treated like assigning a pointer! + // + // DateTime and TimeSpan are optimized as primitive types, + // so getting an array reference to them is like getting a reference to them. + // + switch(array->m_typeOfElement) + { + case DATATYPE_VALUETYPE: + this->SetReference( *(CLR_RT_HeapBlock*)array->GetElement( m_data.arrayReference.index ) ); + break; + + case DATATYPE_DATETIME: + case DATATYPE_TIMESPAN: + m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_BYREF,0,1); + m_data.objectReference.ptr = (CLR_RT_HeapBlock*)array->GetElement( m_data.arrayReference.index ); + break; + } +} + +HRESULT CLR_RT_HeapBlock::LoadFromReference( CLR_RT_HeapBlock& ref ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock tmp; + CLR_RT_HeapBlock* obj; + CLR_DataType dt = ref.DataType(); + + if(dt == DATATYPE_ARRAY_BYREF) + { + CLR_RT_HeapBlock_Array* array = ref.m_data.arrayReference.array; FAULT_ON_NULL(array); + CLR_UINT8* src = array->GetElement( ref.m_data.arrayReference.index ); + CLR_UINT32 size = array->m_sizeOfElement; + + if(!array->m_fReference) + { + CLR_UINT32 second = 0; + CLR_UINT32 first; + + SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(array->m_typeOfElement,0,1) ); + + if (size == 4) { first = ((CLR_UINT32*)src)[ 0 ]; } + else if(size == 8) { first = ((CLR_UINT32*)src)[ 0 ]; second = ((CLR_UINT32*)src)[ 1 ]; } + else if(size == 1) { first = ((CLR_UINT8 *)src)[ 0 ]; } + else { first = ((CLR_UINT16*)src)[ 0 ]; } + + ((CLR_UINT32*)&NumericByRef())[ 0 ] = first; + ((CLR_UINT32*)&NumericByRef())[ 1 ] = second; + + TINYCLR_SET_AND_LEAVE(S_OK); + } + + // + // It's a pointer to a full CLR_RT_HeapBlock. + // + obj = (CLR_RT_HeapBlock*)src; + } + else if(dt == DATATYPE_BYREF) + { + obj = ref.Dereference(); FAULT_ON_NULL(obj); + + if(obj->DataType() == DATATYPE_VALUETYPE) + { + tmp.SetObjectReference( obj ); + + obj = &tmp; + } + } + else if(c_CLR_RT_DataTypeLookup[ dt ].m_flags & CLR_RT_DataTypeLookup::c_Direct) + { + obj = &ref; + + if(dt == DATATYPE_OBJECT) + { + CLR_RT_HeapBlock* objT = ref.Dereference(); + + if(objT && objT->IsBoxed()) + { + CLR_RT_TypeDef_Instance inst; + if (objT->DataType() != DATATYPE_VALUETYPE) { TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); } + + if(!inst.InitializeFromIndex( objT->ObjectCls() )) { TINYCLR_SET_AND_LEAVE(CLR_E_TYPE_UNAVAILABLE); } + + if(inst.m_target->dataType != DATATYPE_VALUETYPE) // It's a boxed primitive/enum type. + { + obj = &objT[ 1 ]; + } + } + } + } + else + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + if(obj->IsAValueType()) + { + TINYCLR_SET_AND_LEAVE(g_CLR_RT_ExecutionEngine.CloneObject( *this, *obj )); + } + + this->Assign( *obj ); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock::StoreToReference( CLR_RT_HeapBlock& ref, int size ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock* obj; + CLR_DataType dt = ref.DataType(); + + if(dt == DATATYPE_ARRAY_BYREF) + { + CLR_RT_HeapBlock_Array* array = ref.m_data.arrayReference.array; FAULT_ON_NULL(array); + CLR_UINT8* dst = array->GetElement( ref.m_data.arrayReference.index ); + + if(!array->m_fReference) + { + CLR_UINT32 sizeArray = array->m_sizeOfElement; + + // + // Cannot copy NULL reference to a primitive type array. + // + obj = FixBoxingReference(); FAULT_ON_NULL(obj); + + if(size == -1) + { + //size == -1 tells StoreToReference to allow the value 'this' to have more precision than the dest + //array. This fixes the following bug. + // : conv.u1 + // : stobj [mscorlib]System.Byte + // The conv.u1 will convert the top of the eval stack to a u1. But since the eval stack is required + // to contain at least 4 byte values, this heap block will be promoted to an I4. + // stobj ignores the type token (System.Byte) and calls Reassign, which calls StoreToReference. + + if(c_CLR_RT_DataTypeLookup[ this->DataType() ].m_sizeInBytes < sizeArray) + { + //Not enough precision here. + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + +#if defined(_DEBUG) + { + CLR_DataType dtElem = (CLR_DataType)array->m_typeOfElement; + CLR_RT_HeapBlock blk; blk.Assign( *this ); + + TINYCLR_CHECK_HRESULT(blk.Convert( dtElem, false, (c_CLR_RT_DataTypeLookup[ dtElem ].m_flags & CLR_RT_DataTypeLookup::c_Signed) == 0)); + + switch(sizeArray) + { + case 1: _ASSERTE(blk.NumericByRefConst().u1 == this->NumericByRefConst().u1); break; + case 2: _ASSERTE(blk.NumericByRefConst().u2 == this->NumericByRefConst().u2); break; + case 4: _ASSERTE(blk.NumericByRefConst().u4 == this->NumericByRefConst().u4); break; + case 8: _ASSERTE(blk.NumericByRefConst().u8 == this->NumericByRefConst().u8); break; + } + } +#endif + } + else if(size == 0) + { + if(obj->DataType() != array->m_typeOfElement) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + else + { + if(size != sizeArray) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + + CLR_UINT32 first = ((CLR_UINT32*)&obj->NumericByRef())[ 0 ]; + CLR_UINT32 second = ((CLR_UINT32*)&obj->NumericByRef())[ 1 ]; + + if (sizeArray == 4) { ((CLR_UINT32*)dst)[ 0 ] = (CLR_UINT32)first; } + else if(sizeArray == 8) { ((CLR_UINT32*)dst)[ 0 ] = (CLR_UINT32)first; ((CLR_UINT32*)dst)[ 1 ] = (CLR_UINT32)second; } + else if(sizeArray == 1) { ((CLR_UINT8 *)dst)[ 0 ] = (CLR_UINT8 )first; } + else { ((CLR_UINT16*)dst)[ 0 ] = (CLR_UINT16)first; } + + TINYCLR_SET_AND_LEAVE(S_OK); + } + else + { + // + // If the source is not null, make sure the types are compatible. + // + if(this->DataType() == DATATYPE_OBJECT && this->Dereference()) + { + CLR_RT_TypeDescriptor descSrc; + CLR_RT_TypeDescriptor descDst; + CLR_RT_TypeDescriptor descDstSub; + + TINYCLR_CHECK_HRESULT(descSrc.InitializeFromObject( *this )); + TINYCLR_CHECK_HRESULT(descDst.InitializeFromObject( *array )); descDst.GetElementType( descDstSub ); + + if(CLR_RT_ExecutionEngine::IsInstanceOf( descSrc, descDstSub ) == false) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + + obj = (CLR_RT_HeapBlock*)dst; + + TINYCLR_SET_AND_LEAVE(obj->Reassign( *this )); + } + } + else if(dt == DATATYPE_BYREF) + { + obj = ref.Dereference(); FAULT_ON_NULL(obj); + + if(obj->DataType() == DATATYPE_VALUETYPE) + { + TINYCLR_SET_AND_LEAVE(ref.Reassign( *this )); + } + } + else if(c_CLR_RT_DataTypeLookup[ dt ].m_flags & CLR_RT_DataTypeLookup::c_Direct) + { + obj = &ref; + } + else + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + obj->Assign( *this ); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock::Reassign( const CLR_RT_HeapBlock& value ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock* obj; + CLR_RT_HeapBlock ref; + + if(this->DataType() == DATATYPE_BYREF) + { + obj = this->Dereference(); FAULT_ON_NULL(obj); + + // + // Real value types can be passed as references. + // + if(obj->DataType() == DATATYPE_VALUETYPE) + { + ref.SetObjectReference( obj ); + + obj = &ref; + } + + TINYCLR_SET_AND_LEAVE(obj->Reassign( value )); + } + else if(value.DataType() == DATATYPE_BYREF) + { + obj = value.Dereference(); FAULT_ON_NULL(obj); + + // + // Real value types can be passed as references. + // + if(obj->DataType() == DATATYPE_VALUETYPE) + { + ref.SetObjectReference( obj ); + + obj = &ref; + } + + TINYCLR_SET_AND_LEAVE(this->Reassign( *obj )); + } + else if(this->DataType() == DATATYPE_ARRAY_BYREF) + { + TINYCLR_CHECK_HRESULT(ref.LoadFromReference( *this )); + TINYCLR_CHECK_HRESULT(ref.Reassign ( value )); + TINYCLR_SET_AND_LEAVE(ref.StoreToReference ( *this, -1 )); + } + else if(value.DataType() == DATATYPE_ARRAY_BYREF) + { + _ASSERTE( FALSE ); //not tested + + CLR_RT_HeapBlock valueT; valueT.Assign( value ); + + TINYCLR_CHECK_HRESULT(ref.LoadFromReference( valueT )); + TINYCLR_SET_AND_LEAVE(this->Reassign ( ref )); + } + else + { + bool fDestination = this->IsAValueType(); + bool fSource = value.IsAValueType(); + + if(fSource != fDestination) + { + // For value type objects we don't care if the source item is boxed because + // CopyValueType will take care of the boxing/unboxing + if(fDestination != value.IsAReferenceOfThisType(DATATYPE_VALUETYPE)) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + + if(fDestination) + { + TINYCLR_SET_AND_LEAVE(g_CLR_RT_ExecutionEngine.CopyValueType( this->Dereference(), value.Dereference() )); + } + + this->Assign( value ); + } + + TINYCLR_NOCLEANUP(); +} + +void CLR_RT_HeapBlock::AssignAndPinReferencedObject( const CLR_RT_HeapBlock& value ) +{ + // This is very special case that we have local variable with pinned attribute in metadata. + // This code is called only if "fixed" keyword is present in the managed code. Executed on assigment to "fixed" pointer. + // First check if there is object referenced by the local var. We unpin it, since the reference is replaced. + if (m_data.objectReference.ptr != NULL && m_id.type.dataType == DATATYPE_ARRAY_BYREF || m_id.type.dataType == DATATYPE_BYREF) + { // Inpin the object that has been pointed by local variable. + m_data.objectReference.ptr->Unpin(); + } + + // Move the data. + m_data = value.m_data; + + // Leave the same logic as in AssignAndPreserveType + if(DataType() > DATATYPE_LAST_PRIMITIVE_TO_PRESERVE) + { + m_id.type.dataType = value.m_id.type.dataType; + m_id.type.size = value.m_id.type.size; + // We take new flags, but preserve "pinned" attribute + m_id.type.flags = m_id.type.flags | HB_Pinned; + } + + // Pin the object refernced by local variable. + if (m_data.objectReference.ptr != NULL && m_id.type.dataType == DATATYPE_ARRAY_BYREF || m_id.type.dataType == DATATYPE_BYREF) + { + m_data.objectReference.ptr->Pin(); + } +} + + +HRESULT CLR_RT_HeapBlock::PerformBoxingIfNeeded() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + + // we need to box the optimized value types... + bool fBox = (c_CLR_RT_DataTypeLookup[ this->DataType() ].m_flags & CLR_RT_DataTypeLookup::c_OptimizedValueType) != 0; + + // ... but also the value types under object types + if(!fBox && this->DataType() == DATATYPE_OBJECT) + { + CLR_RT_HeapBlock* src = this->Dereference(); + + if(src && src->DataType() == DATATYPE_VALUETYPE && !src->IsBoxed()) + { + fBox = true; + } + } + + if(fBox) + { + CLR_RT_TypeDescriptor desc; + + TINYCLR_CHECK_HRESULT(desc.InitializeFromObject( *this )); + + TINYCLR_CHECK_HRESULT(PerformBoxing( desc.m_handlerCls )); + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock::PerformBoxing( const CLR_RT_TypeDef_Instance& cls ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock tmp; + CLR_RT_HeapBlock* obj = this; + CLR_DataType dt = obj->DataType(); + + // + // System.DateTime and System.TimeSpan are real value types, so sometimes they are passed by reference. + // + if(dt == DATATYPE_BYREF) + { + obj = obj->Dereference(); FAULT_ON_NULL(obj); + dt = obj->DataType(); + + // + // Real value types can be passed as references. + // + if(dt == DATATYPE_VALUETYPE) + { + tmp.SetObjectReference( obj ); obj = &tmp; + + dt = DATATYPE_OBJECT; + } + } + + { + CLR_DataType dataType = (CLR_DataType)cls.m_target->dataType; + const CLR_RT_DataTypeLookup& dtl = c_CLR_RT_DataTypeLookup[ dataType ]; + + if(dtl.m_flags & CLR_RT_DataTypeLookup::c_OptimizedValueType) + { + CLR_RT_HeapBlock* ptr = g_CLR_RT_ExecutionEngine.ExtractHeapBlocksForClassOrValueTypes( DATATYPE_VALUETYPE, HB_Boxed, cls, 2 ); FAULT_ON_NULL(ptr); + + switch(dataType) + { + case DATATYPE_DATETIME: // Special case. + case DATATYPE_TIMESPAN: // Special case. + dataType = DATATYPE_I8; + break; + } + + ptr[ 1 ].SetDataId ( CLR_RT_HEAPBLOCK_RAW_ID(dataType,0,1) ); + ptr[ 1 ].AssignData( *this ); + + this->SetObjectReference( ptr ); + } + else if(dt == DATATYPE_OBJECT) + { + CLR_RT_HeapBlock* ptr = this->Dereference(); + + if(ptr->IsBoxed() || ptr->DataType() != DATATYPE_VALUETYPE) + { + TINYCLR_SET_AND_LEAVE(S_FALSE); // Don't box twice... + } + + TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.CloneObject( *this, *ptr )); + + this->Dereference()->Box(); + } + else + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + + TINYCLR_NOCLEANUP(); +} + +/******************************************************************************************* +* Thefunction CLR_RT_HeapBlock::PerformUnboxing is used during processing of unbox.any IL instruction. +* Example +* unbox.any [mscorlib]System.Int32 +* unbox.any takes the value at the top of evaluation stack and performs unboxing into the type +* specified after the instruction. In this case the type is [mscorlib]System.Int32. +* Function parameters: +* 1. this - Heap block at the top of evaluation stack. +* 2. cls - Runtime Type Definition of the type specified after instruction. +* The functoin takes the object pointed by top of ev. stack. Then it does 3 operatioins: +* 1. Dereferences the object +* 2. Validates the type of data kept by object corresponds to type in cls. +* 3. Moves de-referenced date to top of evaluation stack. +*******************************************************************************************/ + +HRESULT CLR_RT_HeapBlock::PerformUnboxing( const CLR_RT_TypeDef_Instance& cls ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock* src; + + if(this->DataType() != DATATYPE_OBJECT) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + // Finds the object that keeps the boxed type. + src = this->Dereference(); FAULT_ON_NULL(src); + + // Validates that src keeps something boxed and the boxed value is VALUE type. + if(src->IsBoxed() == false || src->DataType() != DATATYPE_VALUETYPE) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + // Validates the type of data kept by object corresponds to type in cls. + // If typedef indexes are the same, then skip and go to assigment of objects. + if(src->ObjectCls().m_data != cls.m_data) + { + // The typedef indexes are different, but src and cls may have identical basic data type. + // Need to check it. If identical - the unboxing is allowed. + // This "if" compares underlying type in object and cls. Should be equal in order to continue. + if ( !( src->DataSize() > 1 && ( src[ 1 ].DataType() == cls.m_target->dataType ) ) ) + { + // No luck. The types in src object and specified by cls are different. Need to throw exceptioin. + TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_CAST); + } + } + + if(cls.m_target->dataType == DATATYPE_VALUETYPE) + { + TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.CloneObject( *this, *this )); + + this->Dereference()->Unbox(); + } + else // It's a boxed primitive/enum type. + { + this->Assign( src[ 1 ] ); + + this->ChangeDataType( cls.m_target->dataType ); + } + + TINYCLR_NOCLEANUP(); +} + +CLR_RT_HeapBlock* CLR_RT_HeapBlock::FixBoxingReference() +{ + NATIVE_PROFILE_CLR_CORE(); + // + // Not boxed, nothing to do. + // + if(this->DataType() == DATATYPE_OBJECT) + { + CLR_RT_HeapBlock* src = this->Dereference(); if(!src) return src; + + if(src->DataType() == DATATYPE_VALUETYPE && src->IsBoxed()) + { + CLR_RT_TypeDef_Instance inst; + + if(!inst.InitializeFromIndex( src->ObjectCls() )) return NULL; + + if(inst.m_target->dataType != DATATYPE_VALUETYPE) // It's a boxed primitive/enum type. + { + return &src[ 1 ]; + } + } + } + + return this; +} + +//--// + +bool CLR_RT_HeapBlock::IsZero() const +{ + NATIVE_PROFILE_CLR_CORE(); + switch(DataType()) + { + case DATATYPE_OBJECT: return (m_data.objectReference.ptr == NULL); + + case DATATYPE_I8 : + case DATATYPE_U8 : return (m_data.numeric.u8 == 0); + + + case DATATYPE_R4 : return (m_data.numeric.r4 == 0); + case DATATYPE_R8 : return (m_data.numeric.r8 == 0); + + + default : return (m_data.numeric.u4 == 0); + } +} + +//--// + +void CLR_RT_HeapBlock::Promote() +{ + NATIVE_PROFILE_CLR_CORE(); + + switch(DataType()) + { + case DATATYPE_I1 : m_id.type.dataType = DATATYPE_I4; m_data.numeric.s4 = (CLR_INT32 )m_data.numeric.s1; break; + + case DATATYPE_I2 : m_id.type.dataType = DATATYPE_I4; m_data.numeric.s4 = (CLR_INT32 )m_data.numeric.s2; break; + + case DATATYPE_BOOLEAN: + case DATATYPE_U1 : m_id.type.dataType = DATATYPE_I4; m_data.numeric.u4 = (CLR_UINT32)m_data.numeric.u1; break; + + case DATATYPE_CHAR : + case DATATYPE_U2 : m_id.type.dataType = DATATYPE_I4; m_data.numeric.u4 = (CLR_UINT32)m_data.numeric.u2; break; + } +} + +//--// + +CLR_UINT32 CLR_RT_HeapBlock::GetHashCode( CLR_RT_HeapBlock* ptr, bool fRecurse, CLR_UINT32 crc = 0 ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(!ptr) return 0; + + switch(ptr->DataType()) + { + case DATATYPE_OBJECT: + crc = GetHashCode( ptr->Dereference(), fRecurse, crc ); + break; + + case DATATYPE_STRING: + { + LPCSTR szText = ptr->StringText(); + + crc = SUPPORT_ComputeCRC( szText, (int)hal_strlen_s( szText ), crc ); + } + break; + + case DATATYPE_CLASS: + case DATATYPE_VALUETYPE: + if(fRecurse) + { + CLR_RT_TypeDef_Instance cls; cls.InitializeFromIndex( ptr->ObjectCls() ); + int totFields = cls.CrossReference().m_totalFields; + + while(totFields-- > 0) + { + crc = GetHashCode( ++ptr, false, crc ); + } + } + break; + + case DATATYPE_DELEGATE_HEAD: + { + CLR_RT_HeapBlock_Delegate* dlg = (CLR_RT_HeapBlock_Delegate*)ptr; + const CLR_RT_MethodDef_Index& ftn = dlg->DelegateFtn(); + + crc = GetHashCode( &dlg->m_object, false, crc ); + + crc = SUPPORT_ComputeCRC( &ftn, sizeof(ftn), crc ); + } + break; + + case DATATYPE_OBJECT_TO_EVENT: + { + CLR_RT_ObjectToEvent_Source* evtSrc = (CLR_RT_ObjectToEvent_Source*)ptr; + + crc = GetHashCode(evtSrc->m_eventPtr, false, crc); + crc = GetHashCode(evtSrc->m_objectPtr, false, crc); + } + break; + + default: + crc = SUPPORT_ComputeCRC( &ptr->DataByRefConst(), ptr->GetAtomicDataUsedBytes(), crc ); + break; + } + + return crc; +} + +CLR_UINT32 CLR_RT_HeapBlock::GetAtomicDataUsedBytes() const + +{ + switch( DataType() ) + { + case DATATYPE_BOOLEAN : // Fall through, hashDataSize = 1 + case DATATYPE_U1 : // Fall through, hashDataSize = 1 + case DATATYPE_CHAR : return 1; + + case DATATYPE_I2 : // Fall through, hashDataSize = 2 + case DATATYPE_U2 : return 2; break; + + case DATATYPE_I4 : + case DATATYPE_U4 : + case DATATYPE_R4 : return 4; break; + + case DATATYPE_I8 : // Fall through, hashDataSize = 8 + case DATATYPE_U8 : // Fall through, hashDataSize = 8 + case DATATYPE_R8 : // Fall through, hashDataSize = 8 + case DATATYPE_DATETIME: // Fall through, hashDataSize = 8 + case DATATYPE_TIMESPAN: return 8; break; + + // Default full size of CLR_RT_HeapBlock_AtomicData + default : return sizeof(CLR_RT_HeapBlock_AtomicData); + } + // The same as default. This is never reached, but I put it to avoid potential compiler warning. + return sizeof(CLR_RT_HeapBlock_AtomicData); +} + +bool CLR_RT_HeapBlock::ObjectsEqual( const CLR_RT_HeapBlock& pArgLeft, const CLR_RT_HeapBlock& pArgRight, bool fSameReference ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(&pArgLeft == &pArgRight) return true; + + if(pArgLeft.DataType() == pArgRight.DataType()) + { + switch(pArgLeft.DataType()) + { + case DATATYPE_VALUETYPE: + if(pArgLeft.ObjectCls().m_data == pArgRight.ObjectCls().m_data) + { + const CLR_RT_HeapBlock* objLeft = &pArgLeft ; + const CLR_RT_HeapBlock* objRight = &pArgRight; + CLR_UINT32 num = pArgLeft.DataSize(); + + while(--num) + { + if(ObjectsEqual( *++objLeft, *++objRight, false ) == false) return false; + } + + return true; + } + break; + +#if defined(TINYCLR_APPDOMAINS) + case DATATYPE_TRANSPARENT_PROXY: +#endif + case DATATYPE_OBJECT: + { + CLR_RT_HeapBlock* objLeft = pArgLeft .Dereference(); + CLR_RT_HeapBlock* objRight = pArgRight.Dereference(); + if(objLeft == objRight) return true; + + if(objLeft && objRight) + { + if(!fSameReference || (objLeft->DataType() == DATATYPE_REFLECTION)) return ObjectsEqual( *objLeft, *objRight, false ); + } + } + break; + + case DATATYPE_SZARRAY: + if(fSameReference == false) + { + _ASSERTE(false); //can this code path ever be executed? + + CLR_RT_HeapBlock_Array* objLeft = (CLR_RT_HeapBlock_Array*)&pArgLeft; + CLR_RT_HeapBlock_Array* objRight = (CLR_RT_HeapBlock_Array*)&pArgRight; + + if(objLeft->m_numOfElements == objRight->m_numOfElements && + objLeft->m_sizeOfElement == objRight->m_sizeOfElement && + objLeft->m_typeOfElement == objRight->m_typeOfElement ) + { + if(!objLeft->m_fReference) + { + if(memcmp( objLeft->GetFirstElement(), objRight->GetFirstElement(), objLeft->m_numOfElements * objLeft->m_sizeOfElement ) == 0) + { + return true; + } + } + } + } + break; + case DATATYPE_REFLECTION: + if(pArgLeft.SameHeader( pArgRight )) return true; + break; + default: + if(fSameReference == false) + { + const CLR_RT_DataTypeLookup& dtl = c_CLR_RT_DataTypeLookup[ pArgLeft.DataType() ]; + + if((dtl.m_flags & CLR_RT_DataTypeLookup::c_Reference) == 0) + { + CLR_UINT32 size = (dtl.m_sizeInBits + 7) / 8; + + if(memcmp( &pArgLeft.DataByRefConst(), &pArgRight.DataByRefConst(), size ) == 0) + { + return true; + } + } + } + break; + } + } + + return false; +} + +//--// + +static const CLR_RT_HeapBlock* FixReflectionForType( const CLR_RT_HeapBlock& src, CLR_RT_HeapBlock& tmp ) +{ + NATIVE_PROFILE_CLR_CORE(); + const CLR_RT_ReflectionDef_Index& rd = src.ReflectionDataConst(); + + if(rd.m_kind == REFLECTION_TYPE) + { + CLR_RT_TypeDef_Instance inst; + CLR_UINT32 levels; + + if(inst.InitializeFromReflection( rd, &levels ) && levels == 0) + { + tmp.Assign( src ); + + CLR_RT_ReflectionDef_Index& rd2 = tmp.ReflectionData(); + + rd2.InitializeFromHash( inst.CrossReference().m_hash ); + + return &tmp; + } + } + + return &src; +} + +//--// + +static inline int CompareValues_Numeric( CLR_INT32 left, CLR_INT32 right ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(left > right) return 1; + if(left < right) return -1; + /**************/ return 0; +} + +static inline int CompareValues_Numeric( CLR_UINT32 left, CLR_UINT32 right ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(left > right) return 1; + if(left < right) return -1; + /**************/ return 0; +} + +static int CompareValues_Numeric( const CLR_INT64 left, const CLR_INT64 right ) +{ + NATIVE_PROFILE_CLR_CORE(); + + if(left > right) return 1; + if(left < right) return -1; + /**************/ return 0; +} + +static int CompareValues_Numeric( const CLR_UINT64 left, const CLR_UINT64 right ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(left > right) return 1; + if(left < right) return -1; + /**************/ return 0; +} + +static int CompareValues_Numeric( const CLR_RT_HeapBlock& left, const CLR_RT_HeapBlock& right, bool fSigned, int bytes ) +{ + NATIVE_PROFILE_CLR_CORE(); + + switch(bytes) + { + case 4: + if(fSigned) return CompareValues_Numeric( (CLR_INT32 )left.NumericByRefConst().s4, (CLR_INT32 )right.NumericByRefConst().s4 ); + else return CompareValues_Numeric( (CLR_UINT32)left.NumericByRefConst().u4, (CLR_UINT32)right.NumericByRefConst().u4 ); + + case 8: + if(fSigned) return CompareValues_Numeric( (CLR_INT64 )left.NumericByRefConst().s8, (CLR_INT64 )right.NumericByRefConst().s8 ); + else return CompareValues_Numeric( (CLR_UINT64)left.NumericByRefConst().u8, (CLR_UINT64)right.NumericByRefConst().u8 ); + + case 2: + if(fSigned) return CompareValues_Numeric( (CLR_INT32 )left.NumericByRefConst().s2, (CLR_INT32 )right.NumericByRefConst().s2 ); + else return CompareValues_Numeric( (CLR_UINT32)left.NumericByRefConst().u2, (CLR_UINT32)right.NumericByRefConst().u2 ); + + case 1: + if(fSigned) return CompareValues_Numeric( (CLR_INT32 )left.NumericByRefConst().s1, (CLR_INT32 )right.NumericByRefConst().s1 ); + else return CompareValues_Numeric( (CLR_UINT32)left.NumericByRefConst().u1, (CLR_UINT32)right.NumericByRefConst().u1 ); + + default: + return -1; + } +} + + + +static inline int CompareValues_Pointers( const CLR_RT_HeapBlock* left, const CLR_RT_HeapBlock* right ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(left > right) return 1; + if(left < right) return -1; + /**************/ return 0; +} + + +CLR_INT32 CLR_RT_HeapBlock::Compare_Values( const CLR_RT_HeapBlock& left, const CLR_RT_HeapBlock& right, bool fSigned ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_DataType leftDataType = left .DataType(); + CLR_DataType rightDataType = right.DataType(); + + if(leftDataType == rightDataType) + { + switch(leftDataType) + { +#if defined(TINYCLR_APPDOMAINS) + case DATATYPE_TRANSPARENT_PROXY: +#endif + case DATATYPE_OBJECT: + case DATATYPE_BYREF: + { + CLR_RT_HeapBlock* leftObj = left .Dereference(); + CLR_RT_HeapBlock* rightObj = right.Dereference(); + + if(!leftObj) + { + return !rightObj ? 0 : -1; // NULL references always compare smaller than non-NULL ones. + } + else if(!rightObj) + { + return 1; // NULL references always compare smaller than non-NULL ones. + } + + return Compare_Values( *leftObj, *rightObj, fSigned ); + } + + case DATATYPE_STRING: + { + CLR_RT_HeapBlock_String* leftStr = (CLR_RT_HeapBlock_String*)&left ; + CLR_RT_HeapBlock_String* rightStr = (CLR_RT_HeapBlock_String*)&right; + + return strcmp( leftStr->StringText(), rightStr->StringText() ); + } + + case DATATYPE_DELEGATELIST_HEAD: + { + CLR_RT_HeapBlock_Delegate_List* leftDlg = (CLR_RT_HeapBlock_Delegate_List*)&left ; + CLR_RT_HeapBlock_Delegate_List* rightDlg = (CLR_RT_HeapBlock_Delegate_List*)&right; + CLR_RT_HeapBlock* leftPtr = leftDlg ->GetDelegates(); + CLR_RT_HeapBlock* rightPtr = rightDlg->GetDelegates(); + CLR_UINT32 leftLen = leftDlg ->m_length; + CLR_UINT32 rightLen = rightDlg->m_length; + + while(leftLen > 0 && rightLen > 0) + { + int res = CLR_RT_HeapBlock::Compare_Values( *leftPtr++, *rightPtr++, fSigned ); if(res) return res; + + leftLen--; + rightLen--; + } + + if(!leftLen) + { + return !rightLen ? 0 : -1; // NULL references always compare smaller than non-NULL ones. + } + else // rightLen != 0 for sure. + { + return 1; // NULL references always compare smaller than non-NULL ones. + } + } + + case DATATYPE_DELEGATE_HEAD: + { + CLR_RT_HeapBlock_Delegate* leftDlg = (CLR_RT_HeapBlock_Delegate*)&left ; + CLR_RT_HeapBlock_Delegate* rightDlg = (CLR_RT_HeapBlock_Delegate*)&right; + CLR_UINT32 leftData = leftDlg ->DelegateFtn().m_data; + CLR_UINT32 rightData = rightDlg->DelegateFtn().m_data; + + if(leftData > rightData) return 1; + if(leftData < rightData) return -1; + + return Compare_Values( leftDlg->m_object, rightDlg->m_object, fSigned ); + } + + case DATATYPE_CLASS: + case DATATYPE_VALUETYPE: + case DATATYPE_SZARRAY: + case DATATYPE_WEAKCLASS: + return CompareValues_Pointers( &left, &right ); + + case DATATYPE_REFLECTION: + { + const CLR_RT_HeapBlock* ptrLeft; + const CLR_RT_HeapBlock* ptrRight; + CLR_RT_HeapBlock hbLeft; + CLR_RT_HeapBlock hbRight; + + if(left.ReflectionDataConst().m_kind != right.ReflectionDataConst().m_kind) + { + ptrLeft = FixReflectionForType( left , hbLeft ); + ptrRight = FixReflectionForType( right, hbRight ); + } + else + { + ptrLeft = &left; + ptrRight = &right; + } + + return CompareValues_Numeric( *ptrLeft, *ptrRight, false, 8 ); + } + + //--// +#if !defined(TINYCLR_EMULATED_FLOATINGPOINT) + + case DATATYPE_R4: + if(left.NumericByRefConst().r4 > right.NumericByRefConst().r4) return 1; + if(left.NumericByRefConst().r4 < right.NumericByRefConst().r4) return -1; + /************************************************************/ return 0; + + case DATATYPE_R8: + + if(left.NumericByRefConst().r8 > right.NumericByRefConst().r8) return 1; + if(left.NumericByRefConst().r8 < right.NumericByRefConst().r8) return -1; + /************************************************************/ return 0; + +#else + case DATATYPE_R4 : + case DATATYPE_R8 : + fSigned = true; +#endif + + case DATATYPE_BOOLEAN : + case DATATYPE_I1 : + case DATATYPE_U1 : + + case DATATYPE_CHAR : + case DATATYPE_I2 : + case DATATYPE_U2 : + + case DATATYPE_I4 : + case DATATYPE_U4 : + + case DATATYPE_I8 : + case DATATYPE_U8 : + case DATATYPE_DATETIME: + case DATATYPE_TIMESPAN: + return CompareValues_Numeric( left, right, fSigned, c_CLR_RT_DataTypeLookup[ leftDataType ].m_sizeInBytes ); + } + } + else + { + if(leftDataType == DATATYPE_STRING && rightDataType == DATATYPE_OBJECT) + { + CLR_RT_HeapBlock* rightObj = right.Dereference(); + + if(!rightObj) + { + return 1; // NULL references always compare smaller than non-NULL ones. + } + + return Compare_Values( left, *rightObj, fSigned ); + } + + if(leftDataType == DATATYPE_OBJECT && rightDataType == DATATYPE_STRING) + { + CLR_RT_HeapBlock* leftObj = left.Dereference(); + + if(!leftObj) + { + return -1; // NULL references always compare smaller than non-NULL ones. + } + + return Compare_Values( *leftObj, right, fSigned ); + } + + //--// + + const CLR_RT_DataTypeLookup& leftDtl = c_CLR_RT_DataTypeLookup[ leftDataType ]; + const CLR_RT_DataTypeLookup& rightDtl = c_CLR_RT_DataTypeLookup[ rightDataType ]; + + if((leftDtl .m_flags & CLR_RT_DataTypeLookup::c_Numeric) && + (rightDtl.m_flags & CLR_RT_DataTypeLookup::c_Numeric) ) + { + if(leftDtl.m_sizeInBytes == rightDtl.m_sizeInBytes) + { + return CompareValues_Numeric( left, right, fSigned, leftDtl.m_sizeInBytes ); + } + else + { + CLR_Debug::Printf( "\r\n\r\nRUNTIME ERROR: comparing two values of different size: %d vs. %d!!!\r\n\r\n\r\n", leftDataType, rightDataType ); +#if defined(TINYCLR_PROFILE_NEW) + g_CLR_PRF_Profiler.DumpHeap(); +#endif + } + } + } + + return -1; // Not comparable... +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_HeapBlock::NumericAdd( const CLR_RT_HeapBlock& right ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + switch(DataType()) + { + case DATATYPE_I4: m_data.numeric.s4 += right.m_data.numeric.s4; break; + + case DATATYPE_U4: m_data.numeric.u4 += right.m_data.numeric.u4; break; + + case DATATYPE_I8: m_data.numeric.s8 += right.m_data.numeric.s8; break; + + case DATATYPE_U8: m_data.numeric.u8 += right.m_data.numeric.u8; break; + + case DATATYPE_R4: +#if defined(TINYCLR_EMULATED_FLOATINGPOINT) + { + CLR_INT32 orig = (CLR_INT32)m_data.numeric.r4; + CLR_INT32 rhs = (CLR_INT32)right.m_data.numeric.r4; +#endif + m_data.numeric.r4 += right.m_data.numeric.r4; + +#if defined(TINYCLR_EMULATED_FLOATINGPOINT) + if(rhs > 0 && orig > 0 && orig > (CLR_INT32)m_data.numeric.r4) { m_data.numeric.r4 = 0x7FFFFFFF; /*return CLR_E_OUT_OF_RANGE*/ } + else if(rhs < 0 && orig < 0 && orig < (CLR_INT32)m_data.numeric.r4) { m_data.numeric.r4 = (CLR_INT32)(CLR_UINT32)0x80000000; /*return CLR_E_OUT_OF_RANGE*/ } + } +#endif + break; + + case DATATYPE_R8: +#if defined(TINYCLR_EMULATED_FLOATINGPOINT) + { + CLR_INT64 orig = (CLR_INT64)m_data.numeric.r8; + CLR_INT64 rhs = (CLR_INT64)right.m_data.numeric.r8; +#endif + m_data.numeric.r8 += right.m_data.numeric.r8; + +#if defined(TINYCLR_EMULATED_FLOATINGPOINT) + if(rhs > 0 && orig > 0 && orig > (CLR_INT64)m_data.numeric.r8) { m_data.numeric.r8 = (CLR_INT64)ULONGLONGCONSTANT(0x7FFFFFFFFFFFFFFF); /*return CLR_E_OUT_OF_RANGE*/ } + else if(rhs < 0 && orig < 0 && orig < (CLR_INT64)m_data.numeric.r8) { m_data.numeric.r8 = (CLR_INT64)ULONGLONGCONSTANT(0x8000000000000000); /*return CLR_E_OUT_OF_RANGE*/ } + } +#endif + break; + + + // Adding of value to array reference is like advancing the index in array. + case DATATYPE_ARRAY_BYREF: + { + // Retrieve refernced array. Test if it is not NULL + CLR_RT_HeapBlock_Array* array = m_data.arrayReference.array; FAULT_ON_NULL(array); + // Advance current index. C# on pointer operations multiplies the offset by object size. We need to reverse it. + m_data.arrayReference.index += right.m_data.numeric.s4 / array->m_sizeOfElement; + } + break; + + default : TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock::NumericSub( const CLR_RT_HeapBlock& right ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + switch(DataType()) + { + case DATATYPE_U4: m_data.numeric.u4 -= right.m_data.numeric.u4; break; + + case DATATYPE_I4: m_data.numeric.s4 -= right.m_data.numeric.s4; break; + + case DATATYPE_U8: m_data.numeric.u8 -= right.m_data.numeric.u8; break; + + case DATATYPE_I8: m_data.numeric.s8 -= right.m_data.numeric.s8; break; + + case DATATYPE_R4: +#if defined(TINYCLR_EMULATED_FLOATINGPOINT) + { + CLR_INT32 orig = (CLR_INT32)m_data.numeric.r8; + CLR_INT32 rhs = (CLR_INT32)right.m_data.numeric.r4; +#endif + m_data.numeric.r4 -= right.m_data.numeric.r4; + +#if defined(TINYCLR_EMULATED_FLOATINGPOINT) + if(rhs < 0 && orig > 0 && orig > (CLR_INT32)m_data.numeric.r4) { m_data.numeric.r4 = 0x7FFFFFFF; /*return CLR_E_OUT_OF_RANGE*/ } + else if(rhs > 0 && orig < 0 && orig < (CLR_INT32)m_data.numeric.r4) { m_data.numeric.r4 = (CLR_INT32)(CLR_UINT32)0x80000000; /*return CLR_E_OUT_OF_RANGE*/ } + } +#endif + + break; + + case DATATYPE_R8: +#if defined(TINYCLR_EMULATED_FLOATINGPOINT) + { + CLR_INT64 orig = (CLR_INT64)m_data.numeric.r8; + CLR_INT64 rhs = (CLR_INT64)right.m_data.numeric.r8; +#endif + + m_data.numeric.r8 -= right.m_data.numeric.r8; + +#if defined(TINYCLR_EMULATED_FLOATINGPOINT) + if(rhs < 0 && orig > 0 && orig > (CLR_INT64)m_data.numeric.r8) { m_data.numeric.r8 = (CLR_INT64)ULONGLONGCONSTANT(0x7FFFFFFFFFFFFFFF); /*return CLR_E_OUT_OF_RANGE*/ } + else if(rhs > 0 && orig < 0 && orig < (CLR_INT64)m_data.numeric.r8) { m_data.numeric.r8 = (CLR_INT64)ULONGLONGCONSTANT(0x8000000000000000); /*return CLR_E_OUT_OF_RANGE*/ } + } +#endif + + break; + + + // Substructing of value to array reference is like decreasing the index in array. + case DATATYPE_ARRAY_BYREF: + { + // Retrieve refernced array. Test if it is not NULL + CLR_RT_HeapBlock_Array* array = m_data.arrayReference.array; FAULT_ON_NULL(array); + // Advance current index. C# on pointer operations multiplies the offset by object size. We need to reverse it. + m_data.arrayReference.index -= right.m_data.numeric.s4 / array->m_sizeOfElement; + } + break; + default : TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock::NumericMul( const CLR_RT_HeapBlock& right ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + switch(DataType()) + { + case DATATYPE_U4: m_data.numeric.u4 = m_data.numeric.u4 * right.m_data.numeric.u4; break; + + case DATATYPE_I4: m_data.numeric.s4 = m_data.numeric.s4 * right.m_data.numeric.s4; break; + + case DATATYPE_U8: m_data.numeric.u8 = m_data.numeric.u8 * right.m_data.numeric.u8; break; + + case DATATYPE_I8: m_data.numeric.s8 = m_data.numeric.s8 * right.m_data.numeric.s8; break; + + case DATATYPE_R4: +#if defined(TINYCLR_EMULATED_FLOATINGPOINT) + { + CLR_INT32 orig = (CLR_INT32)m_data.numeric.r4; + CLR_INT32 rhs; +#endif + m_data.numeric.r4 = m_data.numeric.r4 * right.m_data.numeric.r4; + +#if defined(TINYCLR_EMULATED_FLOATINGPOINT) + rhs = (CLR_INT32)right.m_data.numeric.r4; + + if(orig != 0 && rhs != 0) + { + CLR_INT32 ret_value = (CLR_INT32)m_data.numeric.r4; + bool isNeg = orig < 0; + + if(rhs < 0) isNeg = !isNeg; + + if(!isNeg && (ret_value < 0 || ret_value < orig || ret_value < rhs)) { m_data.numeric.r4 = 0x7FFFFFFF; /* return CLR_E_OUT_OF_RANGE; */ } + else if( isNeg && (ret_value > 0 || ret_value > orig || ret_value > rhs)) { m_data.numeric.r4 = (CLR_INT32)(CLR_UINT32)0x80000000; /* return CLR_E_OUT_OF_RANGE; */ } + } + } +#endif + break; + + case DATATYPE_R8: +#if defined(TINYCLR_EMULATED_FLOATINGPOINT) + { + CLR_INT64 orig = (CLR_INT64)m_data.numeric.r8; + CLR_INT64 rhs; +#endif + m_data.numeric.r8 = m_data.numeric.r8 * right.m_data.numeric.r8; + +#if defined(TINYCLR_EMULATED_FLOATINGPOINT) + rhs = (CLR_INT64)right.m_data.numeric.r8; + + if(orig != 0 && rhs != 0) + { + CLR_INT64 ret_value = (CLR_INT64)m_data.numeric.r8; + bool isNeg = orig < 0; + + if(rhs < 0) isNeg = !isNeg; + + if(!isNeg && (ret_value < 0 || ret_value < orig || ret_value < rhs)) { m_data.numeric.r8 = (CLR_INT64)ULONGLONGCONSTANT(0x7FFFFFFFFFFFFFFF); /* return CLR_E_OUT_OF_RANGE; */ } + else if( isNeg && (ret_value > 0 || ret_value > orig || ret_value > rhs)) { m_data.numeric.r8 = (CLR_INT64)ULONGLONGCONSTANT(0x8000000000000000); /* return CLR_E_OUT_OF_RANGE; */ } + } + } +#endif + break; + + default : TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock::NumericDiv( const CLR_RT_HeapBlock& right ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + if(right.IsZero()) TINYCLR_SET_AND_LEAVE(CLR_E_DIVIDE_BY_ZERO); + + switch(DataType()) + { + case DATATYPE_U4: + case DATATYPE_I4: m_data.numeric.s4 = m_data.numeric.s4 / right.m_data.numeric.s4; break; + + case DATATYPE_U8: + case DATATYPE_I8: m_data.numeric.s8 = m_data.numeric.s8 / right.m_data.numeric.s8; break; + + case DATATYPE_R4: m_data.numeric.r4 = m_data.numeric.r4 / right.m_data.numeric.r4; break; + + case DATATYPE_R8: m_data.numeric.r8 = m_data.numeric.r8 / right.m_data.numeric.r8; break; + + default : TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock::NumericDivUn( const CLR_RT_HeapBlock& right ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + if(right.IsZero()) TINYCLR_SET_AND_LEAVE(CLR_E_DIVIDE_BY_ZERO); + + switch(DataType()) + { + case DATATYPE_I4: + case DATATYPE_U4: m_data.numeric.u4 = m_data.numeric.u4 / right.m_data.numeric.u4; break; + + case DATATYPE_I8: + case DATATYPE_U8:m_data.numeric.u8 = m_data.numeric.u8 / right.m_data.numeric.u8; break; + + default : TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock::NumericRem( const CLR_RT_HeapBlock& right ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + if(right.IsZero()) TINYCLR_SET_AND_LEAVE(CLR_E_DIVIDE_BY_ZERO); + + switch(DataType()) + { + case DATATYPE_U4: m_data.numeric.u4 %= right.m_data.numeric.u4 ; break; + + case DATATYPE_I4: m_data.numeric.s4 %= right.m_data.numeric.s4 ; break; + + case DATATYPE_U8: m_data.numeric.u8 %= right.m_data.numeric.u8 ; break; + + case DATATYPE_I8: m_data.numeric.s8 %= right.m_data.numeric.s8 ; break; + +#if !defined(TINYCLR_EMULATED_FLOATINGPOINT) + + case DATATYPE_R4: m_data.numeric.r4 = fmod( m_data.numeric.r4, right.m_data.numeric.r4 ); break; + + case DATATYPE_R8: m_data.numeric.r8 = fmod( (CLR_DOUBLE_TEMP_CAST)m_data.numeric.r8,(CLR_DOUBLE_TEMP_CAST) right.m_data.numeric.r8 ); break; + +#else + + case DATATYPE_R4: m_data.numeric.r4 %= right.m_data.numeric.r4; break; + + case DATATYPE_R8: m_data.numeric.r8 %= right.m_data.numeric.r8; break; + +#endif + + + default : TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock::NumericRemUn( const CLR_RT_HeapBlock& right ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + if(right.IsZero()) TINYCLR_SET_AND_LEAVE(CLR_E_DIVIDE_BY_ZERO); + + switch(DataType()) + { + case DATATYPE_I4: + case DATATYPE_U4: m_data.numeric.u4 %= right.m_data.numeric.u4; break; + + case DATATYPE_I8: + case DATATYPE_U8: m_data.numeric.u8 %= right.m_data.numeric.u8; break; + + default : TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock::NumericShl( const CLR_RT_HeapBlock& right ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + switch(DataType()) + { + case DATATYPE_I4: + case DATATYPE_U4: m_data.numeric.u4 <<= right.m_data.numeric.u4; break; + + case DATATYPE_I8: + case DATATYPE_U8: m_data.numeric.u8 <<= right.m_data.numeric.u4; break; + + default : TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock::NumericShr( const CLR_RT_HeapBlock& right ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + switch(DataType()) + { + case DATATYPE_U4: m_data.numeric.u4 >>= right.m_data.numeric.u4; break; + + case DATATYPE_I4: m_data.numeric.s4 >>= right.m_data.numeric.u4; break; + + case DATATYPE_U8: m_data.numeric.u8 >>= right.m_data.numeric.u4; break; + + case DATATYPE_I8: m_data.numeric.s8 >>= right.m_data.numeric.u4; break; + + default : TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock::NumericShrUn( const CLR_RT_HeapBlock& right ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + switch(DataType()) + { + case DATATYPE_I4: + case DATATYPE_U4: m_data.numeric.u4 >>= right.m_data.numeric.u4; break; + + case DATATYPE_I8: + case DATATYPE_U8: m_data.numeric.u8 >>= right.m_data.numeric.u4; break; + + default : TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock::NumericNeg() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + switch(DataType()) + { + case DATATYPE_U4: + case DATATYPE_I4: m_data.numeric.s4 = -m_data.numeric.s4; break; + + case DATATYPE_U8: + case DATATYPE_I8: m_data.numeric.s8 = -m_data.numeric.s8; break; + + case DATATYPE_R4: m_data.numeric.r4 = -m_data.numeric.r4; break; + + case DATATYPE_R8: m_data.numeric.r8 = -m_data.numeric.r8; break; + + + + default : TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + TINYCLR_NOCLEANUP(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +CLR_RT_HeapBlock* CLR_RT_HeapBlock::ExtractValueBlock( int offset ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock* ptr = Dereference(); + + if(ptr) + { + ptr = &ptr[ offset ]; + } + + return ptr; +} + +void CLR_RT_HeapBlock::ReadValue( CLR_INT64& val, int offset ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock* ptr = ExtractValueBlock( offset ); + + if(ptr) + { + val = ptr->NumericByRefConst().s8; + } + else + { + CLR_INT32 val2 = 0; + + val = val2; + } +} + +void CLR_RT_HeapBlock::WriteValue( const CLR_INT64& val, int offset ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock* ptr = ExtractValueBlock( offset ); + + if(ptr) ptr->NumericByRef().s8 = val; +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +#if defined(TINYCLR_APPDOMAINS) + +void CLR_RT_HeapBlock::SetTransparentProxyReference( CLR_RT_AppDomain* appDomain, CLR_RT_HeapBlock* ptr) + { +#if defined(_DEBUG) + if(ptr) + { + //Make sure the data points to a MBRO. + CLR_RT_TypeDef_Instance inst; + + _ASSERTE(ptr->DataType() == DATATYPE_CLASS); + + inst.InitializeFromIndex( ptr->ObjectCls() ); + _ASSERTE((inst.CrossReference().m_flags & CLR_RT_TypeDef_CrossReference::TD_CR_IsMarshalByRefObject) != 0); + } +#endif + + m_data.transparentProxy.appDomain = appDomain; + m_data.transparentProxy.ptr = ptr; + } + +HRESULT CLR_RT_HeapBlock::TransparentProxyValidate() const +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_AppDomain* appDomain = TransparentProxyAppDomain (); + CLR_RT_HeapBlock* obj = TransparentProxyDereference(); + + if(appDomain == NULL || !appDomain->IsLoaded()) TINYCLR_SET_AND_LEAVE(CLR_E_APPDOMAIN_EXITED); + + FAULT_ON_NULL(obj); + + TINYCLR_NOCLEANUP(); +} + +#endif //TINYCLR_APPDOMAINS +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_HeapBlock::Relocate__HeapBlock() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HEAPBLOCK_RELOCATE(this); +} + + +void CLR_RT_HeapBlock::Relocate_String() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_data.string.m_text ); +#if !defined(TINYCLR_NO_ASSEMBLY_STRINGS) + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_data.string.m_assm ); +#endif +} + +void CLR_RT_HeapBlock::Relocate_Obj() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_data.objectReference.ptr ); +} + +void CLR_RT_HeapBlock::Relocate_Cls() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_data.objectHeader.lock ); + + CLR_RT_GarbageCollector::Heap_Relocate( this + 1, DataSize() - 1 ); +} + +void CLR_RT_HeapBlock::Relocate_Ref() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_data.objectReference.ptr ); +} + +void CLR_RT_HeapBlock::Relocate_ArrayRef() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_data.arrayReference.array ); +} + +#if defined(TINYCLR_APPDOMAINS) +void CLR_RT_HeapBlock::Relocate_TransparentProxy() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_data.transparentProxy.ptr ); +} +#endif + +//--// + +#if defined(TINYCLR_FILL_MEMORY_WITH_DIRTY_PATTERN) + +void CLR_RT_HeapBlock::Debug_CheckPointer() const +{ + NATIVE_PROFILE_CLR_CORE(); + if(m_id.type.dataType == DATATYPE_OBJECT) + { + Debug_CheckPointer( Dereference() ); + } +} + +void CLR_RT_HeapBlock::Debug_CheckPointer( void* ptr ) +{ + NATIVE_PROFILE_CLR_CORE(); + switch((size_t)ptr) + { + case 0xCFCFCFCF: + case 0xCBCBCBCB: + case 0xABABABAB: + case 0xADADADAD: + case 0xDFDFDFDF: + TINYCLR_STOP(); + break; + } +} + +void CLR_RT_HeapBlock::Debug_ClearBlock( int data ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_UINT32 size = DataSize(); + + if(size > 1) + { + CLR_RT_HeapBlock_Raw* ptr = (CLR_RT_HeapBlock_Raw*)this; + CLR_UINT32 raw1 = CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_OBJECT,0,1); + CLR_UINT32 raw2; + + raw2 = data & 0xFF; + raw2 = raw2 | (raw2 << 8); + raw2 = raw2 | (raw2 << 16); + + while(--size) + { + ptr++; + + ptr->data[ 0 ] = raw1; + ptr->data[ 1 ] = raw2; + ptr->data[ 2 ] = raw2; + } + } +} + +#endif diff --git a/src/CLR/Core/CLR_RT_HeapBlock_Array.cpp b/src/CLR/Core/CLR_RT_HeapBlock_Array.cpp new file mode 100644 index 0000000000..bb4879a37a --- /dev/null +++ b/src/CLR/Core/CLR_RT_HeapBlock_Array.cpp @@ -0,0 +1,370 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_HeapBlock_Array::CreateInstance( CLR_RT_HeapBlock& reference, CLR_UINT32 length, const CLR_RT_ReflectionDef_Index& reflex ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock_Array* pArray; + CLR_RT_TypeDef_Index cls; + CLR_RT_TypeDef_Instance inst; + + reference.SetObjectReference( NULL ); + + if((CLR_INT32)length < 0) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + + if(reflex.m_kind != REFLECTION_TYPE) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + if(reflex.m_levels == 1) + { + cls = reflex.m_data.m_type; + } + else + { + cls = g_CLR_RT_WellKnownTypes.m_Array; + } + + if(inst.InitializeFromIndex( cls ) == false) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + else + { + CLR_DataType dt = (CLR_DataType)inst.m_target->dataType; + const CLR_RT_DataTypeLookup& dtl = c_CLR_RT_DataTypeLookup[ dt ]; + + if(dtl.m_sizeInBytes == CLR_RT_DataTypeLookup::c_NA) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + pArray = (CLR_RT_HeapBlock_Array*)g_CLR_RT_ExecutionEngine.ExtractHeapBlocksForArray( inst, length, reflex ); CHECK_ALLOCATION(pArray); + + reference.SetObjectReference( pArray ); + + TINYCLR_SET_AND_LEAVE(pArray->ClearElements( 0, length )); + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_Array::CreateInstance( CLR_RT_HeapBlock& reference, CLR_UINT32 length, const CLR_RT_TypeDef_Index& cls ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_ReflectionDef_Index reflex; + + reflex.m_kind = REFLECTION_TYPE; + reflex.m_levels = 1; + reflex.m_data.m_type = cls; + + TINYCLR_SET_AND_LEAVE(CreateInstance( reference, length, reflex )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_Array::CreateInstance( CLR_RT_HeapBlock& reference, CLR_UINT32 length, CLR_RT_Assembly* assm, CLR_UINT32 tk ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock ref; + CLR_RT_TypeDef_Instance cls; + CLR_RT_TypeSpec_Instance def; + + if(cls.ResolveToken( tk, assm )) + { + ref.SetReflection( cls ); + } + else if(def.ResolveToken( tk, assm )) + { + TINYCLR_CHECK_HRESULT(ref.SetReflection( def )); + } + else + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + ref.ReflectionData().m_levels++; + + TINYCLR_SET_AND_LEAVE(CreateInstance( reference, length, ref.ReflectionData() )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_Array::ClearElements( int index, int length ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + const CLR_RT_ReflectionDef_Index& reflex = ReflectionDataConst(); + CLR_UINT8* data = GetElement( index ); + + CLR_RT_Memory::ZeroFill( data, length * m_sizeOfElement ); + + if(m_fReference) + { + CLR_DataType dt = (CLR_DataType)m_typeOfElement; + bool fAllocate = (reflex.m_levels == 1 && dt == DATATYPE_VALUETYPE); + CLR_RT_HeapBlock* ptr = (CLR_RT_HeapBlock*)data; + + switch(dt) + { + case DATATYPE_VALUETYPE: + case DATATYPE_CLASS: + case DATATYPE_WEAKCLASS: + dt = DATATYPE_OBJECT; + break; + } + + while(length > 0) + { + ptr->SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(dt,0,1) ); + + if(fAllocate) + { + TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex( *ptr, reflex.m_data.m_type )); + } + + ptr++; length--; + } + } + + TINYCLR_NOCLEANUP(); +} + +void CLR_RT_HeapBlock_Array::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + // + // If the array is full of reference types, relocate each of them. + // + if(m_fReference) + { + CLR_RT_GarbageCollector::Heap_Relocate( (CLR_RT_HeapBlock*)GetFirstElement(), m_numOfElements ); + } +} + +bool CLR_RT_HeapBlock_Array::CheckRange( int index, int length, int numOfElements ) +{ + NATIVE_PROFILE_CLR_CORE(); + if( length < 0 ) return false; + if( index < 0 || index > numOfElements) return false; + if((index + length) < 0 || (index + length) > numOfElements) return false; + + return true; +} + +/* + This is not the same functionality as System.Array.IndexOf. CLR_RT_HeapBlock_Array::IndexOf does the search analogous + to calling Object.ReferenceEquals, not Object.Equals, as System.Array.IndexOf demands. This function is used by + TrySzIndexOf +*/ +HRESULT CLR_RT_HeapBlock_Array::IndexOf( CLR_RT_HeapBlock_Array* array, CLR_RT_HeapBlock& match, int start, int stop, bool fForward, int& index ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + int numElem = array->m_numOfElements; + int count; + + if(stop == -1) stop = numElem; + + count = stop - start; + + if(CheckRange( start, count, numElem ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + + if(count > 0) + { + CLR_UINT8* data = array->GetFirstElement(); + CLR_UINT8 sizeElem = array->m_sizeOfElement; + int pos; + int incr; + + if(fForward) { pos = start ; incr = 1; } + else { pos = stop-1; incr = -1; } + + data += pos * sizeElem; + + if(!array->m_fReference) + { + CLR_RT_HeapBlock* matchPtr = match.FixBoxingReference(); FAULT_ON_NULL(matchPtr); + + if(matchPtr->DataType() <= DATATYPE_LAST_PRIMITIVE) + { + int incrElem = incr * sizeElem; + + while(true) + { + if(memcmp( data, &matchPtr->NumericByRef(), sizeElem ) == 0) + { + index = pos; + TINYCLR_SET_AND_LEAVE(S_OK); + } + + if(--count == 0) break; + + pos += incr; + data += incrElem; + } + } + } + else + { + CLR_RT_HeapBlock* dataPtr = (CLR_RT_HeapBlock*)data; + + while(true) + { + if(CLR_RT_HeapBlock::Compare_Unsigned_Values( *dataPtr, match ) == 0) + { + index = pos; + TINYCLR_SET_AND_LEAVE(S_OK); + } + + if(--count == 0) break; + + pos += incr; + dataPtr += incr; + } + } + } + + index = -1; + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_Array::Copy( CLR_RT_HeapBlock_Array* arraySrc, int indexSrc, CLR_RT_HeapBlock_Array* arrayDst, int indexDst, int length ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + if(length) + { + int numElemSrc = arraySrc->m_numOfElements; + int numElemDst = arrayDst->m_numOfElements; + + if(length < 0 || + indexSrc < 0 || + indexDst < 0 || + length + indexSrc > numElemSrc || + length + indexDst > numElemDst ) + { + TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + + // + // Copy of an array on itself. + // + if(arraySrc == arrayDst && indexSrc == indexDst) TINYCLR_SET_AND_LEAVE(S_OK); + + if(arraySrc->SameHeader( *arrayDst )) + { + CLR_UINT8* dataSrc = arraySrc->GetFirstElement(); + CLR_UINT8* dataDst = arrayDst->GetFirstElement(); + CLR_UINT8 sizeElem = arraySrc->m_sizeOfElement; + + dataSrc += indexSrc * sizeElem; + dataDst += indexDst * sizeElem; + + if(!arraySrc->m_fReference) + { + memmove( dataDst, dataSrc, length * sizeElem ); + } + else + { + CLR_RT_HeapBlock* ptrSrc = (CLR_RT_HeapBlock*)dataSrc; + CLR_RT_HeapBlock* ptrDst = (CLR_RT_HeapBlock*)dataDst; + int incr; + + if(arraySrc == arrayDst && ptrSrc < ptrDst) + { + incr = -1; + ptrSrc += length-1; + ptrDst += length-1; + } + else + { + incr = 1; + } + + for(int i=0; iReassign( *ptrSrc )); + } + } + } + else if(arraySrc->m_fReference && arrayDst->m_fReference) + { + CLR_RT_TypeDescriptor descSrc; + CLR_RT_TypeDescriptor descDst; + CLR_RT_HeapBlock* ptrSrc = (CLR_RT_HeapBlock*)arraySrc->GetElement( indexSrc ); + CLR_RT_HeapBlock* ptrDst = (CLR_RT_HeapBlock*)arrayDst->GetElement( indexDst ); + + TINYCLR_CHECK_HRESULT(descDst.InitializeFromObject( *arrayDst )); descDst.GetElementType( descDst ); + + for(int i=0; iDataType() == DATATYPE_OBJECT && ptrSrc->Dereference() == NULL) + { + ; + } + else + { + TINYCLR_CHECK_HRESULT(descSrc.InitializeFromObject( *ptrSrc )); + + if(CLR_RT_ExecutionEngine::IsInstanceOf( descSrc, descDst ) == false) + { + TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_CAST); + } + } + + TINYCLR_CHECK_HRESULT(ptrDst->Reassign( *ptrSrc )); + } + } + else + { + CLR_RT_TypeDescriptor descSrc; + CLR_RT_TypeDescriptor descDst; + CLR_RT_HeapBlock ref; + CLR_RT_HeapBlock elem; elem.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( elem ); + + TINYCLR_CHECK_HRESULT(descDst.InitializeFromObject( *arrayDst )); descDst.GetElementType( descDst ); + + for(int i=0; iSetBinaryBlobHandlers( mark, relocate ); + obj->m_assembly = NULL; + + TINYCLR_NOCLEANUP(); +} + +CLR_RT_HeapBlock_BinaryBlob* CLR_RT_HeapBlock_BinaryBlob::Allocate( CLR_UINT32 length, CLR_UINT32 flags ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_UINT32 totLength = (CLR_UINT32)( sizeof(CLR_RT_HeapBlock_BinaryBlob) + length ); + + CLR_RT_HeapBlock_BinaryBlob* obj; + + if(flags & CLR_RT_HeapBlock::HB_Event) + { + obj = EVENTCACHE_EXTRACT_NODE_AS_BYTES(g_CLR_RT_EventCache,CLR_RT_HeapBlock_BinaryBlob,DATATYPE_BINARY_BLOB_HEAD,flags,totLength); + } + else + { + obj = (CLR_RT_HeapBlock_BinaryBlob*)g_CLR_RT_ExecutionEngine.ExtractHeapBytesForObjects( DATATYPE_BINARY_BLOB_HEAD, flags, totLength ); + } + + if(obj) + { + obj->SetBinaryBlobHandlers( NULL, NULL ); + } + + return obj; +} + +void CLR_RT_HeapBlock_BinaryBlob::Release( bool fEvent ) +{ + NATIVE_PROFILE_CLR_CORE(); + SetBinaryBlobHandlers( NULL, NULL ); + + if(fEvent) g_CLR_RT_EventCache.Append_Node( this ); +} + +void CLR_RT_HeapBlock_BinaryBlob::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_RelocationHandler relocate = BinaryBlobRelocationHandler(); + + if(relocate) + { + relocate( this ); + } +} diff --git a/src/CLR/Core/CLR_RT_HeapBlock_Delegate.cpp b/src/CLR/Core/CLR_RT_HeapBlock_Delegate.cpp new file mode 100644 index 0000000000..492f918d36 --- /dev/null +++ b/src/CLR/Core/CLR_RT_HeapBlock_Delegate.cpp @@ -0,0 +1,76 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_HeapBlock_Delegate::CreateInstance( CLR_RT_HeapBlock& reference, const CLR_RT_MethodDef_Index& ftn, CLR_RT_StackFrame* call ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + reference.SetObjectReference( NULL ); + + CLR_UINT32 length = 0; + +#if defined(TINYCLR_DELEGATE_PRESERVE_STACK) + if(call) + { + TINYCLR_FOREACH_NODE_BACKWARD__DIRECT(CLR_RT_StackFrame,ptr,call) + { + length++; + } + TINYCLR_FOREACH_NODE_BACKWARD_END(); + } + + // + // Limit depth to three callers. + // + if(length > 3) length = 3; +#endif + + CLR_UINT32 totLength = (CLR_UINT32)(sizeof(CLR_RT_HeapBlock_Delegate) + length * sizeof(CLR_RT_MethodDef_Index)); + + CLR_RT_HeapBlock_Delegate* dlg = (CLR_RT_HeapBlock_Delegate*)g_CLR_RT_ExecutionEngine.ExtractHeapBytesForObjects( DATATYPE_DELEGATE_HEAD, 0, totLength ); CHECK_ALLOCATION(dlg); + + reference.SetObjectReference( dlg ); + + dlg->ClearData(); + dlg->m_cls.Clear(); + dlg->m_ftn = ftn; +#if defined(TINYCLR_DELEGATE_PRESERVE_STACK) + dlg->m_numOfStackFrames = length; +#endif + + dlg->m_object.SetObjectReference( NULL ); + +#if defined(TINYCLR_APPDOMAINS) + dlg->m_appDomain = g_CLR_RT_ExecutionEngine.GetCurrentAppDomain(); +#endif + +#if defined(TINYCLR_DELEGATE_PRESERVE_STACK) + if(call) + { + CLR_RT_MethodDef_Index* callStack = dlg->GetStackFrames(); + + TINYCLR_FOREACH_NODE_BACKWARD__DIRECT(CLR_RT_StackFrame,ptr,call) + { + if(length-- == 0) break; + + *callStack++ = ptr->m_call; + } + TINYCLR_FOREACH_NODE_BACKWARD_END(); + } +#endif + + TINYCLR_NOCLEANUP(); +} + +void CLR_RT_HeapBlock_Delegate::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + m_object.Relocate__HeapBlock(); +} diff --git a/src/CLR/Core/CLR_RT_HeapBlock_Delegate_List.cpp b/src/CLR/Core/CLR_RT_HeapBlock_Delegate_List.cpp new file mode 100644 index 0000000000..47cd0133a4 --- /dev/null +++ b/src/CLR/Core/CLR_RT_HeapBlock_Delegate_List.cpp @@ -0,0 +1,231 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_HeapBlock_Delegate_List::CreateInstance( CLR_RT_HeapBlock_Delegate_List*& list, CLR_UINT32 length ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_UINT32 totLength = (CLR_UINT32)(sizeof(CLR_RT_HeapBlock_Delegate_List) + length * sizeof(CLR_RT_HeapBlock)); + + list = (CLR_RT_HeapBlock_Delegate_List*)g_CLR_RT_ExecutionEngine.ExtractHeapBytesForObjects( DATATYPE_DELEGATELIST_HEAD, 0, totLength ); CHECK_ALLOCATION(list); + + list->ClearData(); + list->m_cls.Clear(); + list->m_length = length; + list->m_flags = 0; + + TINYCLR_NOCLEANUP(); +} + +CLR_RT_HeapBlock* CLR_RT_HeapBlock_Delegate_List::CopyAndCompress( CLR_RT_HeapBlock* src, CLR_RT_HeapBlock* dst, CLR_UINT32 num ) +{ + NATIVE_PROFILE_CLR_CORE(); + while(num--) + { + CLR_RT_HeapBlock_Delegate* dlg = src->DereferenceDelegate(); + if(dlg) + { + dst->SetObjectReference( dlg ); + + dst++; + } + else + { + m_length--; + } + + src++; + } + + return dst; +} + +HRESULT CLR_RT_HeapBlock_Delegate_List::Change( CLR_RT_HeapBlock& reference, CLR_RT_HeapBlock& delegateSrc, CLR_RT_HeapBlock& delegateTarget, bool fCombine, bool fWeak ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock_Delegate_List* dlgListSrc; + CLR_RT_HeapBlock_Delegate_List* dlgListDst; + CLR_RT_HeapBlock_Delegate* dlg; + CLR_RT_HeapBlock* newDlgs; + CLR_RT_HeapBlock* oldDlgs; + CLR_UINT32 oldNum; + CLR_UINT32 newNum; + + CLR_UINT32 num = 0; + + reference.SetObjectReference( NULL ); + + if(delegateSrc .DataType() != DATATYPE_OBJECT || + delegateTarget.DataType() != DATATYPE_OBJECT ) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + dlg = delegateTarget.DereferenceDelegate(); + + if(dlg == NULL) + { + reference.SetObjectReference( delegateSrc.DereferenceDelegate() ); + TINYCLR_SET_AND_LEAVE(S_OK); + } + + if(dlg->DataType() == DATATYPE_DELEGATELIST_HEAD) + { + CLR_RT_HeapBlock intermediate; intermediate.Assign( delegateSrc ); + CLR_RT_ProtectFromGC gc( intermediate ); + + dlgListDst = (CLR_RT_HeapBlock_Delegate_List*)dlg; + newDlgs = dlgListDst->GetDelegates(); + + for(num=0; numm_length; num++, newDlgs++) + { + if(newDlgs->DataType() == DATATYPE_OBJECT && newDlgs->DereferenceDelegate() != NULL) // The delegate could have been GC'ed. + { + TINYCLR_CHECK_HRESULT(Change( reference, intermediate, *newDlgs, fCombine, fWeak )); + + intermediate.Assign( reference ); + } + } + } + else + { + dlgListSrc = delegateSrc.DereferenceDelegateList(); + if(dlgListSrc == NULL) + { + oldDlgs = NULL; + oldNum = 0; + } + else + { + switch(dlgListSrc->DataType()) + { + case DATATYPE_DELEGATE_HEAD: + oldDlgs = &delegateSrc; + oldNum = 1; + break; + + case DATATYPE_DELEGATELIST_HEAD: + oldDlgs = dlgListSrc->GetDelegates(); + oldNum = dlgListSrc->m_length; + break; + + default: + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + + if(fCombine) + { + if(oldNum == 0 && fWeak == false) + { + // + // Empty input list, copy the delegate. + // + reference.Assign( delegateTarget ); + TINYCLR_SET_AND_LEAVE(S_OK); + } + + //--// + + newNum = oldNum + 1; + } + else + { + for(num=0, newDlgs=oldDlgs; numDereferenceDelegate(); + if(ptr) + { + if( ptr->DelegateFtn().m_data == dlg->DelegateFtn().m_data && + ptr->m_object.Dereference() == dlg->m_object.Dereference() ) + { + break; + } + } + } + + if(num == oldNum) + { + reference.Assign( delegateSrc ); // Nothing to remove. + TINYCLR_SET_AND_LEAVE(S_OK); + } + + if(oldNum == 2 && (dlgListSrc->m_flags & CLR_RT_HeapBlock_Delegate_List::c_Weak) == 0) + { + reference.Assign( oldDlgs[ 1-num ] ); // Convert from a list to delegate. + TINYCLR_SET_AND_LEAVE(S_OK); + } + + if(oldNum == 1) + { + reference.SetObjectReference( NULL ); // Oops, empty delegate... + TINYCLR_SET_AND_LEAVE(S_OK); + } + + //--// + + newNum = oldNum - 1; + } + + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Delegate_List::CreateInstance( dlgListDst, newNum )); + + dlgListDst->m_cls = dlg->m_cls; + + newDlgs = dlgListDst->GetDelegates(); + + if(fCombine) + { + newDlgs = dlgListDst->CopyAndCompress( oldDlgs, newDlgs, oldNum ); + + newDlgs->Assign( delegateTarget ); + } + else + { + newDlgs = dlgListDst->CopyAndCompress( oldDlgs , newDlgs, num++ ); + newDlgs = dlgListDst->CopyAndCompress( oldDlgs + num, newDlgs, oldNum - num ); + } + + dlgListDst->m_flags = (dlgListSrc && oldNum > 1) ? dlgListSrc->m_flags : 0; + + if(fWeak) dlgListDst->m_flags |= CLR_RT_HeapBlock_Delegate_List::c_Weak; + + reference.SetObjectReference( dlgListDst ); + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_Delegate_List::Combine( CLR_RT_HeapBlock& reference, CLR_RT_HeapBlock& delegateSrc, CLR_RT_HeapBlock& delegateNew, bool fWeak ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(Change( reference, delegateSrc, delegateNew, true, fWeak )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_Delegate_List::Remove( CLR_RT_HeapBlock& reference, CLR_RT_HeapBlock& delegateSrc, CLR_RT_HeapBlock& delegateOld ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(Change( reference, delegateSrc, delegateOld, false, false )); + + TINYCLR_NOCLEANUP(); +} + +void CLR_RT_HeapBlock_Delegate_List::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_GarbageCollector::Heap_Relocate( GetDelegates(), m_length ); +} diff --git a/src/CLR/Core/CLR_RT_HeapBlock_Finalizer.cpp b/src/CLR/Core/CLR_RT_HeapBlock_Finalizer.cpp new file mode 100644 index 0000000000..3acd0ada96 --- /dev/null +++ b/src/CLR/Core/CLR_RT_HeapBlock_Finalizer.cpp @@ -0,0 +1,79 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_HeapBlock_Finalizer::CreateInstance( CLR_RT_HeapBlock* object, const CLR_RT_TypeDef_Instance& inst ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_TypeDef_Instance inst2 = inst; + + do + { + if(inst2.m_target->flags & CLR_RECORD_TYPEDEF::TD_HasFinalizer) + { + int pos = inst2.m_target->methods_First; + int end = pos + inst2.m_target->vMethods_Num + inst2.m_target->iMethods_Num; + const CLR_RECORD_METHODDEF* md = inst2.m_assm->GetMethodDef( pos ); + + for(; posflags & CLR_RECORD_METHODDEF::MD_Finalizer) break; + } + + if(pos < end) + { + CLR_RT_HeapBlock_Finalizer* fin = EVENTCACHE_EXTRACT_NODE_NOALLOC(g_CLR_RT_EventCache,CLR_RT_HeapBlock_Finalizer,DATATYPE_FINALIZER_HEAD); CHECK_ALLOCATION(fin); + + fin->m_object = object; + + fin->m_md.Set( inst2.Assembly(), pos ); + +#if defined(TINYCLR_APPDOMAINS) + fin->m_appDomain = g_CLR_RT_ExecutionEngine.GetCurrentAppDomain(); +#endif + + g_CLR_RT_ExecutionEngine.m_finalizersAlive.LinkAtBack( fin ); + + break; + } + } + } + while(inst2.SwitchToParent()); + + TINYCLR_NOCLEANUP(); +} + +void CLR_RT_HeapBlock_Finalizer::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_object ); +} + +void CLR_RT_HeapBlock_Finalizer::SuppressFinalize( CLR_RT_HeapBlock* object ) +{ + NATIVE_PROFILE_CLR_CORE(); + RemoveInstance( object, g_CLR_RT_ExecutionEngine.m_finalizersAlive ); + RemoveInstance( object, g_CLR_RT_ExecutionEngine.m_finalizersPending ); +} + +void CLR_RT_HeapBlock_Finalizer::RemoveInstance( CLR_RT_HeapBlock* object, CLR_RT_DblLinkedList& lst ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_Finalizer,fin,lst) + { + if(fin->m_object == object) + { + g_CLR_RT_EventCache.Append_Node( fin ); + + break; + } + } + TINYCLR_FOREACH_NODE_END(); +} diff --git a/src/CLR/Core/CLR_RT_HeapBlock_Lock.cpp b/src/CLR/Core/CLR_RT_HeapBlock_Lock.cpp new file mode 100644 index 0000000000..b7fdf87383 --- /dev/null +++ b/src/CLR/Core/CLR_RT_HeapBlock_Lock.cpp @@ -0,0 +1,219 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_HeapBlock_Lock::CreateInstance( CLR_RT_HeapBlock_Lock*& lock, CLR_RT_Thread* th, CLR_RT_HeapBlock& resource ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + lock = EVENTCACHE_EXTRACT_NODE(g_CLR_RT_EventCache,CLR_RT_HeapBlock_Lock,DATATYPE_LOCK_HEAD); CHECK_ALLOCATION(lock); + + lock->m_owningThread = th; // CLR_RT_Thread* m_owningThread; + // + lock->m_resource.Assign( resource ); // CLR_RT_HeapBlock m_resource; + // + lock->m_owners .DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_owners; + lock->m_requests.DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_requests; + +#if defined(TINYCLR_APPDOMAINS) + lock->m_appDomain = g_CLR_RT_ExecutionEngine.GetCurrentAppDomain(); +#endif + + //--// + + if(resource.DataType() == DATATYPE_OBJECT) + { + CLR_RT_HeapBlock* ptr = resource.Dereference(); + + if(ptr) + { + switch(ptr->DataType()) + { + case DATATYPE_VALUETYPE: + case DATATYPE_CLASS : + ptr->SetObjectLock( lock ); + break; + } + } + } + + th->m_locks.LinkAtBack( lock ); + + TINYCLR_NOCLEANUP(); +} + +void CLR_RT_HeapBlock_Lock::DestroyOwner( CLR_RT_SubThread* sth ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_Lock::Owner,owner,m_owners) + { + if(owner->m_owningSubThread == sth) + { + g_CLR_RT_EventCache.Append_Node( owner ); + } + } + TINYCLR_FOREACH_NODE_END(); + + if(m_owners.IsEmpty()) + { + ChangeOwner(); + } +} + +void CLR_RT_HeapBlock_Lock::ChangeOwner() +{ + NATIVE_PROFILE_CLR_CORE(); + m_owners.DblLinkedList_PushToCache(); + + while(true) + { + CLR_RT_HeapBlock_LockRequest* req = (CLR_RT_HeapBlock_LockRequest*)m_requests.ExtractFirstNode(); if(!req) break; + + CLR_RT_SubThread* sth = req->m_subthreadWaiting; + CLR_RT_Thread* th = sth->m_owningThread; + + g_CLR_RT_EventCache.Append_Node( req ); + + sth->ChangeLockRequestCount( -1 ); + + th->m_locks.LinkAtBack( this ); + + m_owningThread = th; + + CLR_RT_HeapBlock_Lock::IncrementOwnership( this, sth, TIMEOUT_INFINITE, false ); + + // + // If the new owner was waiting on something, update the flags. + // + { + CLR_RT_StackFrame* stack = th->CurrentFrame(); + + if(stack->m_flags & CLR_RT_StackFrame::c_PendingSynchronizeGlobally) + { + stack->m_flags &= ~CLR_RT_StackFrame::c_PendingSynchronizeGlobally; + stack->m_flags |= CLR_RT_StackFrame::c_SynchronizedGlobally; + } + + if(stack->m_flags & CLR_RT_StackFrame::c_PendingSynchronize) + { + stack->m_flags &= ~CLR_RT_StackFrame::c_PendingSynchronize; + stack->m_flags |= CLR_RT_StackFrame::c_Synchronized; + } + } + + return; + } + + // + // None is listening for this object, unlock it. + // + if(m_resource.DataType() == DATATYPE_OBJECT) + { + CLR_RT_HeapBlock* ptr = m_resource.Dereference(); + + if(ptr) + { + switch(ptr->DataType()) + { + case DATATYPE_VALUETYPE: + case DATATYPE_CLASS : + ptr->SetObjectLock( NULL ); + break; + } + } + } + + g_CLR_RT_EventCache.Append_Node( this ); +} + +HRESULT CLR_RT_HeapBlock_Lock::IncrementOwnership( CLR_RT_HeapBlock_Lock* lock, CLR_RT_SubThread* sth, const CLR_INT64& timeExpire, bool fForce ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_Thread* th = sth ->m_owningThread; + CLR_RT_Thread* thOwner = lock->m_owningThread; + + if(thOwner == th) + { + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_Lock::Owner,owner,lock->m_owners) + { + if(owner->m_owningSubThread == sth) + { + owner->m_recursion++; + TINYCLR_SET_AND_LEAVE(S_OK); + } + } + TINYCLR_FOREACH_NODE_END(); + + { + CLR_RT_HeapBlock_Lock::Owner* owner = EVENTCACHE_EXTRACT_NODE(g_CLR_RT_EventCache,Owner,DATATYPE_LOCK_OWNER_HEAD); CHECK_ALLOCATION(owner); + + owner->m_owningSubThread = sth; + owner->m_recursion = 1; + + lock->m_owners.LinkAtFront( owner ); + TINYCLR_SET_AND_LEAVE(S_OK); + } + } + + // + // Create a request and stop the calling thread. + // + TINYCLR_SET_AND_LEAVE(CLR_RT_HeapBlock_LockRequest::CreateInstance( lock, sth, timeExpire, fForce )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_Lock::DecrementOwnership( CLR_RT_HeapBlock_Lock* lock, CLR_RT_SubThread* sth ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_Thread* th = sth->m_owningThread; + + if(lock && lock->m_owningThread == th) + { + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_Lock::Owner,owner,lock->m_owners) + { + if(owner->m_owningSubThread == sth) + { + if(--owner->m_recursion == 0) + { + g_CLR_RT_EventCache.Append_Node( owner ); + } + + //--// + + if(lock->m_owners.IsEmpty()) + { + lock->ChangeOwner(); + } + + TINYCLR_SET_AND_LEAVE(S_OK); + } + } + TINYCLR_FOREACH_NODE_END(); + } + + TINYCLR_SET_AND_LEAVE(CLR_E_LOCK_SYNCHRONIZATION_EXCEPTION); + + TINYCLR_NOCLEANUP(); +} + +void CLR_RT_HeapBlock_Lock::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + m_resource.Relocate__HeapBlock(); +} + +void CLR_RT_HeapBlock_Lock::Relocate_Owner() +{ + NATIVE_PROFILE_CLR_CORE(); +} diff --git a/src/CLR/Core/CLR_RT_HeapBlock_LockRequest.cpp b/src/CLR/Core/CLR_RT_HeapBlock_LockRequest.cpp new file mode 100644 index 0000000000..c2deb46fb5 --- /dev/null +++ b/src/CLR/Core/CLR_RT_HeapBlock_LockRequest.cpp @@ -0,0 +1,28 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_HeapBlock_LockRequest::CreateInstance( CLR_RT_HeapBlock_Lock* lock, CLR_RT_SubThread* sth, const CLR_INT64& timeExpire, bool fForce ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock_LockRequest* req = EVENTCACHE_EXTRACT_NODE(g_CLR_RT_EventCache,CLR_RT_HeapBlock_LockRequest,DATATYPE_LOCK_REQUEST_HEAD); CHECK_ALLOCATION(req); + + req->m_subthreadWaiting = sth; + req->m_timeExpire = timeExpire; CLR_RT_ExecutionEngine::InvalidateTimerCache(); + req->m_fForce = fForce; + + lock->m_requests.LinkAtBack( req ); + + sth->ChangeLockRequestCount( +1 ); + + TINYCLR_SET_AND_LEAVE(CLR_E_THREAD_WAITING); + + TINYCLR_NOCLEANUP(); +} diff --git a/src/CLR/Core/CLR_RT_HeapBlock_Node.cpp b/src/CLR/Core/CLR_RT_HeapBlock_Node.cpp new file mode 100644 index 0000000000..98eee92d4d --- /dev/null +++ b/src/CLR/Core/CLR_RT_HeapBlock_Node.cpp @@ -0,0 +1,15 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_HeapBlock_Node::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_data.nodeLink.prevBlock ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_data.nodeLink.nextBlock ); +} diff --git a/src/CLR/Core/CLR_RT_HeapBlock_Stack.cpp b/src/CLR/Core/CLR_RT_HeapBlock_Stack.cpp new file mode 100644 index 0000000000..fa5b9216cf --- /dev/null +++ b/src/CLR/Core/CLR_RT_HeapBlock_Stack.cpp @@ -0,0 +1,106 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// +HRESULT CLR_RT_HeapBlock_Stack::Pop( CLR_RT_HeapBlock*& value ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock_Array* array = GetArray(); + CLR_INT32 size = GetSize(); + CLR_RT_HeapBlock* removed; + + if(size == 0) TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_OPERATION); + + removed = (CLR_RT_HeapBlock*)array->GetElement( array->m_numOfElements - size ); + + value = removed->Dereference(); + + removed->SetObjectReference( NULL ); + + SetSize( size - 1 ); + + TINYCLR_NOCLEANUP(); +} + +// May Trigger GC, but parameter value will be protected +HRESULT CLR_RT_HeapBlock_Stack::Push( CLR_RT_HeapBlock* value ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock_Array* array = GetArray(); + CLR_INT32 size = GetSize(); + CLR_INT32 capacity = array->m_numOfElements; + + if(size == capacity) + { + // Set new capacity + CLR_RT_HeapBlock newArrayHB; + CLR_RT_HeapBlock_Array* newArray; + + // Protect value from GC, in case CreateInstance triggers one + CLR_RT_HeapBlock valueHB; valueHB.SetObjectReference( value ); + CLR_RT_ProtectFromGC gc( valueHB ); + + capacity *= 2; + + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( newArrayHB, capacity, g_CLR_RT_WellKnownTypes.m_Object )); + + newArray = newArrayHB.DereferenceArray(); + + memcpy( newArray->GetElement( size ), array->GetFirstElement(), size * sizeof(CLR_RT_HeapBlock) ); + + SetArray( newArray ); + array = newArray; + } + + size++; + + ((CLR_RT_HeapBlock*)array->GetElement( capacity - size ))->SetObjectReference( value ); + + SetSize( size ); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_Stack::Peek( CLR_RT_HeapBlock*& value ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock_Array* array = GetArray(); + CLR_INT32 size = GetSize(); + + if(size == 0) TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_OPERATION); + + value = ((CLR_RT_HeapBlock*)array->GetElement( array->m_numOfElements - size ))->Dereference(); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_Stack::Clear() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock_Array* array = GetArray(); + CLR_INT32 size = GetSize(); + + TINYCLR_CHECK_HRESULT(array->ClearElements( array->m_numOfElements - size, size )); + + SetSize( 0 ); + + TINYCLR_NOCLEANUP(); +} + +//--// + +CT_ASSERT(Library_corlib_native_System_Collections_Stack__FIELD___array == Library_corlib_native_System_Collections_Stack::FIELD___array); +CT_ASSERT(Library_corlib_native_System_Collections_Stack__FIELD___size == Library_corlib_native_System_Collections_Stack::FIELD___size ); + diff --git a/src/CLR/Core/CLR_RT_HeapBlock_String.cpp b/src/CLR/Core/CLR_RT_HeapBlock_String.cpp new file mode 100644 index 0000000000..4cc1dddd92 --- /dev/null +++ b/src/CLR/Core/CLR_RT_HeapBlock_String.cpp @@ -0,0 +1,112 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +CLR_RT_HeapBlock_String* CLR_RT_HeapBlock_String::CreateInstance( CLR_RT_HeapBlock& reference, CLR_UINT32 length ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_UINT32 totLength = sizeof(CLR_RT_HeapBlock_String) + length + 1; + CLR_RT_HeapBlock_String* str; + + reference.SetObjectReference( NULL ); + + str = (CLR_RT_HeapBlock_String*)g_CLR_RT_ExecutionEngine.ExtractHeapBytesForObjects( DATATYPE_STRING, 0, totLength ); + if(str) + { + LPSTR szText = (LPSTR)&str[ 1 ]; szText[ 0 ] = 0; + +#if defined(TINYCLR_NO_ASSEMBLY_STRINGS) + str->SetStringText( szText ); +#else + str->SetStringText( szText, NULL ); +#endif + + reference.SetObjectReference( str ); + } + + return str; +} + +HRESULT CLR_RT_HeapBlock_String::CreateInstance( CLR_RT_HeapBlock& reference, LPCSTR szText ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + if(!szText) szText = ""; + + TINYCLR_SET_AND_LEAVE(CLR_RT_HeapBlock_String::CreateInstance( reference, szText, (CLR_UINT32)hal_strlen_s( szText ) )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_String::CreateInstance( CLR_RT_HeapBlock& reference, LPCSTR szText, CLR_UINT32 length ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock_String* str; + LPSTR szTextDst; + + str = CreateInstance( reference, length ); CHECK_ALLOCATION(str); + + szTextDst = (LPSTR)str->StringText(); + + memcpy( szTextDst, szText, length ); szTextDst[ length ] = 0; + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_String::CreateInstance( CLR_RT_HeapBlock& reference, LPCSTR szText, CLR_RT_Assembly* assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock_String* str; + + reference.SetObjectReference( NULL ); + + str = (CLR_RT_HeapBlock_String*)g_CLR_RT_ExecutionEngine.ExtractHeapBytesForObjects( DATATYPE_STRING, 0, sizeof(CLR_RT_HeapBlock_String) ); CHECK_ALLOCATION(str); + + reference.SetObjectReference( str ); + +#if defined(TINYCLR_NO_ASSEMBLY_STRINGS) + TINYCLR_CHECK_HRESULT( CLR_RT_HeapBlock_String::CreateInstance( reference, assm->GetString( CLR_DataFromTk( token ) ) )); +#else + str->SetStringText( szText, assm ); +#endif + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_String::CreateInstance( CLR_RT_HeapBlock& reference, CLR_UINT32 token, CLR_RT_Assembly* assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + return CreateInstance( reference, assm->GetString( CLR_DataFromTk( token ) ), assm ); +} + +HRESULT CLR_RT_HeapBlock_String::CreateInstance( CLR_RT_HeapBlock& reference, CLR_UINT16* szText, CLR_UINT32 length ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_UnicodeHelper uh; uh.SetInputUTF16 ( szText ); + CLR_UINT32 lengthInBytes = uh.CountNumberOfBytes( length ); + CLR_RT_HeapBlock_String* str = CreateInstance( reference, lengthInBytes ); CHECK_ALLOCATION(str); + + uh.m_outputUTF8 = (CLR_UINT8*)str->StringText(); + uh.m_outputUTF8_size = lengthInBytes + 1; + + uh.ConvertToUTF8( length, false ); + + TINYCLR_NOCLEANUP(); +} + +CLR_RT_HeapBlock_String* CLR_RT_HeapBlock_String::GetStringEmpty() +{ + return g_CLR_RT_TypeSystem.m_assemblyMscorlib->GetStaticField( Library_corlib_native_System_String::FIELD_STATIC__Empty )->DereferenceString(); +} diff --git a/src/CLR/Core/CLR_RT_HeapBlock_Timer.cpp b/src/CLR/Core/CLR_RT_HeapBlock_Timer.cpp new file mode 100644 index 0000000000..e684ebbcd7 --- /dev/null +++ b/src/CLR/Core/CLR_RT_HeapBlock_Timer.cpp @@ -0,0 +1,353 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + + HRESULT CLR_RT_HeapBlock_Timer::CreateInstance( CLR_UINT32 flags, CLR_RT_HeapBlock& owner, CLR_RT_HeapBlock& tmRef ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock_Timer* timer = NULL; + + // + // Create a request and stop the calling thread. + // + timer = EVENTCACHE_EXTRACT_NODE(g_CLR_RT_EventCache,CLR_RT_HeapBlock_Timer,DATATYPE_TIMER_HEAD); CHECK_ALLOCATION(timer); + + { + CLR_RT_ProtectFromGC gc( *timer ); + + timer->Initialize(); + + timer->m_flags = flags; + timer->m_timeExpire = TIMEOUT_INFINITE; + timer->m_timeFrequency = TIMEOUT_INFINITE; + timer->m_timeLastExpiration = 0; + timer->m_ticksLastExpiration = 0; + + g_CLR_RT_ExecutionEngine.m_timers.LinkAtBack( timer ); + + TINYCLR_SET_AND_LEAVE(CLR_RT_ObjectToEvent_Source::CreateInstance( timer, owner, tmRef )); + } + + TINYCLR_CLEANUP(); + + if(FAILED(hr)) + { + if(timer) timer->ReleaseWhenDead(); + } + + TINYCLR_CLEANUP_END(); +} + +HRESULT CLR_RT_HeapBlock_Timer::ExtractInstance( CLR_RT_HeapBlock& ref, CLR_RT_HeapBlock_Timer*& timer ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_ObjectToEvent_Source* src = CLR_RT_ObjectToEvent_Source::ExtractInstance( ref ); FAULT_ON_NULL(src); + + timer = (CLR_RT_HeapBlock_Timer*)src->m_eventPtr; + + TINYCLR_NOCLEANUP(); +} + +//--// + +void CLR_RT_HeapBlock_Timer::RecoverFromGC() +{ + NATIVE_PROFILE_CLR_CORE(); + CheckAll(); + + ReleaseWhenDead(); +} + +//--// + +void CLR_RT_HeapBlock_Timer::Trigger() +{ + NATIVE_PROFILE_CLR_CORE(); + if(m_references.IsEmpty()) return; + + if(m_flags & CLR_RT_HeapBlock_Timer::c_Executing) + { + return; + } + + m_flags |= CLR_RT_HeapBlock_Timer::c_Triggered; +} + +void CLR_RT_HeapBlock_Timer::SpawnTimer( CLR_RT_Thread* th ) +{ + NATIVE_PROFILE_CLR_CORE(); + //Only one managed timer max + _ASSERTE(m_references.NumOfNodes() == 1); + + CLR_RT_ObjectToEvent_Source* ref = (CLR_RT_ObjectToEvent_Source*)m_references.FirstValidNode(); + CLR_RT_HeapBlock* managedTimer = ref->m_objectPtr; + CLR_RT_HeapBlock* callback = &managedTimer[ Library_corlib_native_System_Threading_Timer::FIELD__m_callback ]; + CLR_RT_HeapBlock* state = &managedTimer[ Library_corlib_native_System_Threading_Timer::FIELD__m_state ]; + CLR_RT_HeapBlock_Delegate* delegate = callback->DereferenceDelegate(); + CLR_RT_ProtectFromGC gc( *managedTimer ); + + _ASSERTE(delegate != NULL); if(delegate == NULL) return; + _ASSERTE(delegate->DataType() == DATATYPE_DELEGATE_HEAD); + + m_ticksLastExpiration = g_CLR_RT_ExecutionEngine.m_currentMachineTime; + m_timeLastExpiration = m_timeExpire; + m_timeExpire = TIMEOUT_INFINITE; + + if(SUCCEEDED(th->PushThreadProcDelegate( delegate ))) + { + CLR_RT_StackFrame* stack = th->FirstFrame(); + if(stack->Next() != NULL) + { + int numArgs = stack->m_call.m_target->numArgs; + if(numArgs > 0) + { + stack->m_arguments[ numArgs-1 ].Assign( *state ); + } + } + + // + // Associate the timer with the thread. + // + m_flags |= CLR_RT_HeapBlock_Timer::c_Executing; + m_flags &= ~CLR_RT_HeapBlock_Timer::c_Triggered; + + th->m_terminationCallback = CLR_RT_HeapBlock_Timer::ThreadTerminationCallback; + th->m_terminationParameter = this; + } +} + +void CLR_RT_HeapBlock_Timer::ThreadTerminationCallback( void* param ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock_Timer* pThis = (CLR_RT_HeapBlock_Timer*)param; + + pThis->m_flags &= ~CLR_RT_HeapBlock_Timer::c_Executing; + + pThis->Reschedule(); + + g_CLR_RT_ExecutionEngine.SpawnTimer(); +} + +void CLR_RT_HeapBlock_Timer::Reschedule() +{ + NATIVE_PROFILE_CLR_CORE(); + if((m_flags & CLR_RT_HeapBlock_Timer::c_Recurring ) && + (m_flags & CLR_RT_HeapBlock_Timer::c_EnabledTimer) ) + { + CLR_INT64 cmp = (m_flags & CLR_RT_HeapBlock_Timer::c_AbsoluteTimer) ? g_CLR_RT_ExecutionEngine.m_currentLocalTime : g_CLR_RT_ExecutionEngine.m_currentMachineTime; + CLR_INT64 expire = m_timeLastExpiration + m_timeFrequency; + + // + // Normally, adding the 'timeFrequency' will put the expiration in the future. + // + // If we fall back too much, we need to compute the next expiration in the future, to avoid an avalanche effect. + // + if(expire < cmp) + { + expire = cmp - ((cmp - expire) % m_timeFrequency) + m_timeFrequency; + } + + m_timeExpire = expire; CLR_RT_ExecutionEngine::InvalidateTimerCache(); + } +} + +//--// + +void CLR_RT_HeapBlock_Timer::AdjustNextFixedExpire( const SYSTEMTIME& systemTime, bool fNext ) +{ + NATIVE_PROFILE_CLR_CORE(); + SYSTEMTIME st = systemTime; + CLR_INT64 baseTime; + CLR_INT64 add; + + CLR_RT_ExecutionEngine::InvalidateTimerCache(); + + switch(m_flags & CLR_RT_HeapBlock_Timer::c_AnyChange) + { + case CLR_RT_HeapBlock_Timer::c_SecondChange: add = TIME_CONVERSION__ONESECOND * (CLR_INT64)TIME_CONVERSION__TO_SECONDS; break; + case CLR_RT_HeapBlock_Timer::c_MinuteChange: add = TIME_CONVERSION__ONEMINUTE * (CLR_INT64)TIME_CONVERSION__TO_SECONDS; st.wSecond = 0; break; + case CLR_RT_HeapBlock_Timer::c_HourChange : add = TIME_CONVERSION__ONEHOUR * (CLR_INT64)TIME_CONVERSION__TO_SECONDS; st.wSecond = 0; st.wMinute = 0; break; + case CLR_RT_HeapBlock_Timer::c_DayChange : add = TIME_CONVERSION__ONEDAY * (CLR_INT64)TIME_CONVERSION__TO_SECONDS; st.wSecond = 0; st.wMinute = 0; st.wHour = 0; break; + + default : return; + } + + st.wMilliseconds = 0; + baseTime = Time_FromSystemTime( &st ); + + m_timeExpire = fNext ? baseTime + add : baseTime; + m_timeFrequency = add; + m_flags |= CLR_RT_HeapBlock_Timer::c_Recurring; +} + +bool CLR_RT_HeapBlock_Timer::CheckDisposed( CLR_RT_StackFrame& stack ) +{ + CLR_RT_HeapBlock* pThis = stack.This(); + CLR_RT_HeapBlock_Timer* timer; + + if(!FAILED(CLR_RT_HeapBlock_Timer::ExtractInstance( pThis[ Library_corlib_native_System_Threading_Timer::FIELD__m_timer ], timer ))) + { + if((timer->m_flags & CLR_RT_HeapBlock_Timer::c_ACTION_Destroy) == 0) + { + return false; + } + } + + return true; +} + +HRESULT CLR_RT_HeapBlock_Timer::ConfigureObject( CLR_RT_StackFrame& stack, CLR_UINT32 flags ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock* pThis = stack.This(); + CLR_RT_HeapBlock* args = &(stack.Arg1()); + CLR_RT_HeapBlock_Timer* timer; + + const CLR_INT64 maxTime = (CLR_INT64)0x7FFFFFFF * (CLR_INT64)TIME_CONVERSION__TO_MILLISECONDS; + const CLR_INT64 minTime = 0; + + // UNDONE: FIXME: _ASSERTE(Library_corlib_native_System_Threading_Timer::FIELD__m_timer == Library_spot_native_Microsoft_SPOT_ExtendedTimer::FIELD__m_timer ); + // UNDONE: FIXME: _ASSERTE(Library_corlib_native_System_Threading_Timer::FIELD__m_state == Library_spot_native_Microsoft_SPOT_ExtendedTimer::FIELD__m_state ); + // UNDONE: FIXME: _ASSERTE(Library_corlib_native_System_Threading_Timer::FIELD__m_callback == Library_spot_native_Microsoft_SPOT_ExtendedTimer::FIELD__m_callback); + + if(flags & CLR_RT_HeapBlock_Timer::c_ACTION_Create) + { + FAULT_ON_NULL(args[ 0 ].DereferenceDelegate()); + + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Timer::CreateInstance( 0, *pThis, pThis[ Library_corlib_native_System_Threading_Timer::FIELD__m_timer ] )); + + pThis[ Library_corlib_native_System_Threading_Timer::FIELD__m_callback ].Assign( args[ 0 ] ); + pThis[ Library_corlib_native_System_Threading_Timer::FIELD__m_state ].Assign( args[ 1 ] ); + + args += 2; + } + + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Timer::ExtractInstance( pThis[ Library_corlib_native_System_Threading_Timer::FIELD__m_timer ], timer )); + + if(flags & CLR_RT_HeapBlock_Timer::c_ACTION_Create) + { + CLR_UINT32 anyChange = (flags & CLR_RT_HeapBlock_Timer::c_AnyChange); + + if(anyChange) + { + SYSTEMTIME systemTime; Time_ToSystemTime( g_CLR_RT_ExecutionEngine.m_currentLocalTime, &systemTime ); + + timer->m_flags |= anyChange | (CLR_RT_HeapBlock_Timer::c_AbsoluteTimer | CLR_RT_HeapBlock_Timer::c_EnabledTimer); + + timer->AdjustNextFixedExpire( systemTime, true ); + } + else + { + flags |= CLR_RT_HeapBlock_Timer::c_ACTION_Change; + } + + if(flags & CLR_RT_HeapBlock_Timer::c_INPUT_Absolute) + { + timer->m_flags |= CLR_RT_HeapBlock_Timer::c_AbsoluteTimer; + } + } + + if(flags & CLR_RT_HeapBlock_Timer::c_ACTION_Destroy) + { + timer->m_flags &= ~CLR_RT_HeapBlock_Timer::c_EnabledTimer; + } + + if(flags & CLR_RT_HeapBlock_Timer::c_ACTION_Change) + { + // + // You cannot change a fixed timer after creation. + // + if(timer->m_flags & CLR_RT_HeapBlock_Timer::c_AnyChange) TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + if(flags & CLR_RT_HeapBlock_Timer::c_INPUT_Int32) + { + if((timer->m_flags & CLR_RT_HeapBlock_Timer::c_AbsoluteTimer) != 0) TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + timer->m_timeExpire = args[ 0 ].NumericByRef().s4; + timer->m_timeFrequency = args[ 1 ].NumericByRef().s4; + + if (timer->m_timeExpire == -1) timer->m_timeExpire = TIMEOUT_INFINITE; + if (timer->m_timeFrequency == -1) timer->m_timeFrequency = TIMEOUT_INFINITE; + } + else if(flags & CLR_RT_HeapBlock_Timer::c_INPUT_TimeSpan) + { + CLR_INT64* pVal; + + if((timer->m_flags & CLR_RT_HeapBlock_Timer::c_AbsoluteTimer) != 0) TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + pVal = Library_corlib_native_System_TimeSpan::GetValuePtr( args[ 0 ] ); FAULT_ON_NULL(pVal); + if (*pVal == -c_TickPerMillisecond) timer->m_timeExpire = TIMEOUT_INFINITE; + else timer->m_timeExpire = *pVal; + + pVal = Library_corlib_native_System_TimeSpan::GetValuePtr( args[ 1 ] ); FAULT_ON_NULL(pVal); + if (*pVal == -c_TickPerMillisecond) timer->m_timeFrequency = TIMEOUT_INFINITE; + else timer->m_timeFrequency = *pVal; + } + else if(flags & CLR_RT_HeapBlock_Timer::c_INPUT_Absolute) + { + CLR_INT64* pVal; + + if((timer->m_flags & CLR_RT_HeapBlock_Timer::c_AbsoluteTimer) == 0) TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + pVal = Library_corlib_native_System_DateTime::GetValuePtr( args[ 0 ] ); FAULT_ON_NULL(pVal); timer->m_timeExpire = *pVal; + pVal = Library_corlib_native_System_TimeSpan::GetValuePtr( args[ 1 ] ); FAULT_ON_NULL(pVal); timer->m_timeFrequency = *pVal; + } + + if(timer->m_timeExpire == TIMEOUT_INFINITE) + { + timer->m_flags &= ~CLR_RT_HeapBlock_Timer::c_EnabledTimer; + } + else if((flags & CLR_RT_HeapBlock_Timer::c_INPUT_Absolute) ) + { + timer->m_flags |= CLR_RT_HeapBlock_Timer::c_EnabledTimer; + } + else + { + if(flags & CLR_RT_HeapBlock_Timer::c_INPUT_Int32) timer->m_timeExpire *= TIME_CONVERSION__TO_MILLISECONDS; + + if (minTime <= timer->m_timeExpire && timer->m_timeExpire <= maxTime) + { + timer->m_timeExpire += Time_GetMachineTime(); + + timer->m_flags |= CLR_RT_HeapBlock_Timer::c_EnabledTimer; + } + else + { + TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + } + + if(timer->m_timeFrequency == 0 || timer->m_timeFrequency == TIMEOUT_INFINITE) + { + timer->m_flags &= ~CLR_RT_HeapBlock_Timer::c_Recurring; + } + else + { + if(flags & CLR_RT_HeapBlock_Timer::c_INPUT_Int32) timer->m_timeFrequency *= TIME_CONVERSION__TO_MILLISECONDS; + + if(minTime <= timer->m_timeFrequency && timer->m_timeFrequency <= maxTime ) + { + timer->m_flags |= CLR_RT_HeapBlock_Timer::c_Recurring; + } + else + { + TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + } + } + + CLR_RT_ExecutionEngine::InvalidateTimerCache(); + + TINYCLR_NOCLEANUP(); +} diff --git a/src/CLR/Core/CLR_RT_HeapBlock_WaitForObject.cpp b/src/CLR/Core/CLR_RT_HeapBlock_WaitForObject.cpp new file mode 100644 index 0000000000..711c7d2205 --- /dev/null +++ b/src/CLR/Core/CLR_RT_HeapBlock_WaitForObject.cpp @@ -0,0 +1,188 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// CreateInstance - Creates a wait object +// +// Result - returns S_OK - if the target object is in the signaled state - indicating no wait is needed +// - returns CLR_E_THREAD_WAITING - if the target object is not signaled - indicating that the caller thread is waiting +// for the object to be signaled +// +HRESULT CLR_RT_HeapBlock_WaitForObject::CreateInstance( CLR_RT_Thread* caller, const CLR_INT64& timeExpire, CLR_RT_HeapBlock* objects, CLR_UINT32 cObjects, bool fWaitAll ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + // + // Create a request and stop the calling thread. + // + + _ASSERTE( sizeof(CLR_RT_HeapBlock_WaitForObject) % 4 == 0 ); + + CLR_UINT32 totLength = (CLR_UINT32)(sizeof(CLR_RT_HeapBlock_WaitForObject) + cObjects * sizeof(CLR_RT_HeapBlock)); + + CLR_RT_HeapBlock_WaitForObject* wait = EVENTCACHE_EXTRACT_NODE_AS_BYTES(g_CLR_RT_EventCache,CLR_RT_HeapBlock_WaitForObject,DATATYPE_WAIT_FOR_OBJECT_HEAD,0,totLength); CHECK_ALLOCATION(wait); + + wait->m_timeExpire = timeExpire; CLR_RT_ExecutionEngine::InvalidateTimerCache(); + wait->m_cObjects = cObjects; + wait->m_fWaitAll = fWaitAll; + + memcpy( wait->GetWaitForObjects(), objects, sizeof(CLR_RT_HeapBlock) * cObjects ); + + caller->m_waitForObject = wait; + caller->m_status = CLR_RT_Thread::TH_S_Waiting; + caller->m_waitForObject_Result = CLR_RT_Thread::TH_WAIT_RESULT_INIT; + + TINYCLR_SET_AND_LEAVE(CLR_E_THREAD_WAITING); + + TINYCLR_NOCLEANUP(); +} + +void CLR_RT_HeapBlock_WaitForObject::TryWaitForSignal( CLR_RT_Thread* th ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock_WaitForObject* wait = th->m_waitForObject; + + if(wait) + { + if (CLR_RT_HeapBlock_WaitForObject::TryWaitForSignal( th, wait->GetWaitForObjects(), wait->m_cObjects, wait->m_fWaitAll )) + { + th->Restart( true ); + } + } +} + +bool CLR_RT_HeapBlock_WaitForObject::TryWaitForSignal(CLR_RT_Thread* caller, CLR_RT_HeapBlock* objects, CLR_UINT32 cObjects, bool fWaitAll) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock* blk; + CLR_RT_HeapBlock* obj; + + if(fWaitAll) + { + //first time through, find out whether or not the requested objects are signaled + //second time through, reset the signalled objects + for(int phase = 0; phase < 2; phase++) + { + blk = objects; + for(CLR_UINT32 i = 0; i < cObjects; i++) + { + obj = blk->Dereference(); + _ASSERTE(obj != NULL); + + if(phase == 0) + { + if(!obj->IsFlagSet( CLR_RT_HeapBlock::HB_Signaled )) + { + return false; + } + } + else + { + if(obj->IsFlagSet( CLR_RT_HeapBlock::HB_SignalAutoReset )) + { + obj->ResetFlags( CLR_RT_HeapBlock::HB_Signaled ); + } + } + + blk++; + } + } + + caller->m_waitForObject_Result = CLR_RT_Thread::TH_WAIT_RESULT_HANDLE_ALL; + return true; + } + else + { + blk = objects; + for(CLR_UINT32 i = 0; i < cObjects; i++) + { + obj = blk->Dereference(); + _ASSERTE(obj != NULL); + + if(obj->IsFlagSet( CLR_RT_HeapBlock::HB_Signaled )) + { + if(obj->IsFlagSet( CLR_RT_HeapBlock::HB_SignalAutoReset )) + { + obj->ResetFlags( CLR_RT_HeapBlock::HB_Signaled ); + } + + caller->m_waitForObject_Result = CLR_RT_Thread::TH_WAIT_RESULT_HANDLE_0 + i; + return true; + } + + blk++; + } + } + + return false; +} + +void CLR_RT_HeapBlock_WaitForObject::SignalObject( CLR_RT_HeapBlock& object ) +{ + NATIVE_PROFILE_CLR_CORE(); + object.SetFlags( CLR_RT_HeapBlock::HB_Signaled ); + + TINYCLR_FOREACH_NODE(CLR_RT_Thread,th,g_CLR_RT_ExecutionEngine.m_threadsWaiting) + { + CLR_RT_HeapBlock_WaitForObject::TryWaitForSignal( th ); + + if(!object.IsFlagSet( CLR_RT_HeapBlock::HB_Signaled )) + { + _ASSERTE(object.IsFlagSet( CLR_RT_HeapBlock::HB_SignalAutoReset )); + //This is an AutoResetEvent. Since the event got unsignaled, we can break out of + //the loop early, as this object can only free one thread. + break; + } + } + TINYCLR_FOREACH_NODE_END(); +} + +HRESULT CLR_RT_HeapBlock_WaitForObject::WaitForSignal( CLR_RT_StackFrame& stack, const CLR_INT64& timeExpire, CLR_RT_HeapBlock* objects, CLR_UINT32 cObjects, bool fWaitAll ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + if(stack.m_customState == 0) + { + CLR_RT_HeapBlock* objectsT = objects; + + stack.m_customState = 1; + + if(cObjects > 64) TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + for(CLR_UINT32 i = 0; i < cObjects; i++) + { + _ASSERTE(objects->DataType() == DATATYPE_OBJECT); + + FAULT_ON_NULL(objectsT->Dereference()); + + objectsT++; + } + + if(!TryWaitForSignal( stack.m_owningThread, objects, cObjects, fWaitAll )) + { + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_WaitForObject::CreateInstance( stack.m_owningThread, timeExpire, objects, cObjects, fWaitAll )); + } + } + + TINYCLR_NOCLEANUP(); +} + + +HRESULT CLR_RT_HeapBlock_WaitForObject::WaitForSignal ( CLR_RT_StackFrame& stack, const CLR_INT64& timeExpire, CLR_RT_HeapBlock& object ) +{ + NATIVE_PROFILE_CLR_CORE(); + return WaitForSignal( stack, timeExpire, &object, 1, false ); +} + +void CLR_RT_HeapBlock_WaitForObject::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_GarbageCollector::Heap_Relocate( GetWaitForObjects(), m_cObjects ); +} diff --git a/src/CLR/Core/CLR_RT_HeapCluster.cpp b/src/CLR/Core/CLR_RT_HeapCluster.cpp new file mode 100644 index 0000000000..bb0cb511e4 --- /dev/null +++ b/src/CLR/Core/CLR_RT_HeapCluster.cpp @@ -0,0 +1,291 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_HeapCluster::HeapCluster_Initialize( CLR_UINT32 size, CLR_UINT32 blockSize ) +{ + NATIVE_PROFILE_CLR_CORE(); + GenericNode_Initialize(); + + size = (size - sizeof(*this)) / sizeof(CLR_RT_HeapBlock); + + m_freeList.DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_freeList; + m_payloadStart = (CLR_RT_HeapBlock_Node*)&this[ 1 ]; // CLR_RT_HeapBlock_Node* m_payloadStart; + m_payloadEnd = &m_payloadStart[ size ]; // CLR_RT_HeapBlock_Node* m_payloadEnd; + + // + // Scan memory looking for possible objects to salvage. This method returns false if HeapPersistence is stubbed + // which requires us to set up the free list. + // + if(!CLR_RT_HeapBlock_WeakReference::PrepareForRecovery( m_payloadStart, m_payloadEnd, blockSize )) + { + CLR_RT_HeapBlock_Node *ptr = m_payloadStart; + + while(ptr < m_payloadEnd) + { + if((UINT32)(ptr + blockSize) > (UINT32)m_payloadEnd) + { + blockSize = (CLR_UINT32)(m_payloadEnd - ptr); + } + + ptr->SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_FREEBLOCK,0,blockSize) ); + ptr += blockSize; + } + } + + RecoverFromGC(); + + m_freeList.ValidateList(); +} + +CLR_RT_HeapBlock* CLR_RT_HeapCluster::ExtractBlocks( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 length ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock_Node* res = NULL; + CLR_UINT32 available = 0; + + m_freeList.ValidateList(); + + if(flags & CLR_RT_HeapBlock::HB_Event) + { + TINYCLR_FOREACH_NODE_BACKWARD(CLR_RT_HeapBlock_Node,ptr,m_freeList) + { + available = ptr->DataSize(); + + if(available >= length) + { + res = ptr; + break; + } + } + TINYCLR_FOREACH_NODE_BACKWARD_END(); + } + else + { + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_Node,ptr,m_freeList) + { + available = ptr->DataSize(); + + if(available >= length) + { + res = ptr; + break; + } + } + TINYCLR_FOREACH_NODE_END(); + } + + if(res) + { + CLR_RT_HeapBlock_Node* next = res->Next(); + CLR_RT_HeapBlock_Node* prev = res->Prev(); + + available -= length; + + if(available != 0) + { + if(flags & CLR_RT_HeapBlock::HB_Event) + { + res->SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_FREEBLOCK,CLR_RT_HeapBlock::HB_Pinned,available) ); + + res += available; + } + else + { + CLR_RT_HeapBlock_Node* ptr = &res[ length ]; + + // + // Relink to the new free block. + // + ptr->SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_FREEBLOCK,CLR_RT_HeapBlock::HB_Pinned,available) ); + + ptr->SetNext( next ); + ptr->SetPrev( prev ); + + prev->SetNext( ptr ); + next->SetPrev( ptr ); + } + } + else + { + // + // Unlink the whole block. + // + prev->SetNext( next ); + next->SetPrev( prev ); + } + + res->SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(dataType,flags,length) ); + + if(flags & CLR_RT_HeapBlock::HB_InitializeToZero) + { + res->InitializeToZero(); + } + else + { + res->Debug_ClearBlock( 0xCB ); + } + } + + m_freeList.ValidateList(); + + return res; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_HeapCluster::RecoverFromGC() +{ + NATIVE_PROFILE_CLR_CORE(); + + CLR_RT_HeapBlock_Node* ptr = m_payloadStart; + CLR_RT_HeapBlock_Node* end = m_payloadEnd; + + // + // Open the free list. + // + CLR_RT_HeapBlock_Node* last = m_freeList.Head(); last->SetPrev( NULL ); + + while(ptr < end) + { + + ValidateBlock( ptr ); + + if(ptr->IsAlive() == false) + { + CLR_RT_HeapBlock_Node* next = ptr; + CLR_UINT32 lenTot = 0; + + do + { + ValidateBlock( next ); + +#if defined(TINYCLR_PROFILE_NEW_ALLOCATIONS) + g_CLR_PRF_Profiler.TrackObjectDeletion( next ); +#endif + + TINYCLR_CHECK_EARLY_COLLECTION(next); + + int len = next->DataSize(); + + next += len; + lenTot += len; + + } while(next < end && next->IsAlive() == false); + + ptr->SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_FREEBLOCK,CLR_RT_HeapBlock::HB_Pinned,lenTot) ); + + // + // Link to the free list. + // + last->SetNext( ptr ); + ptr ->SetPrev( last ); + last = ptr; + + ptr->Debug_ClearBlock( 0xDF ); + + ptr = next; + } + else + { + if(ptr->IsEvent() == false) ptr->MarkDead(); + + ptr += ptr->DataSize(); + } + } + + // + // Close the free list. + // + last ->SetNext( m_freeList.Tail() ); + m_freeList.Tail()->SetPrev( last ); + m_freeList.Tail()->SetNext( NULL ); +} + +CLR_RT_HeapBlock_Node* CLR_RT_HeapCluster::InsertInOrder( CLR_RT_HeapBlock_Node* node, CLR_UINT32 size ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock_Node* ptr; + + TINYCLR_FOREACH_NODE__NODECL(CLR_RT_HeapBlock_Node,ptr,m_freeList) + { + if(ptr > node) break; + } + TINYCLR_FOREACH_NODE_END(); + + node->ClearData(); m_freeList.InsertBeforeNode( ptr, node ); + + // + // Try to coalesce with the following free block. + // + ptr = node->Next(); + if(ptr->Next() && (node + size) == ptr) + { + size += ptr->DataSize(); ptr->Unlink(); + } + + // + // Try to coalesce with the preceding free block. + // + ptr = node->Prev(); + if(ptr->Prev() && (ptr + ptr->DataSize()) == node) + { + size += ptr->DataSize(); node->Unlink(); node = ptr; + } + + node->SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_FREEBLOCK,CLR_RT_HeapBlock::HB_Pinned,size ) ); + node->Debug_ClearBlock( 0xCF ); + + return node; +} + +//--// + +#if TINYCLR_VALIDATE_HEAP >= TINYCLR_VALIDATE_HEAP_1_HeapBlocksAndUnlink + +void CLR_RT_HeapCluster::ValidateBlock( CLR_RT_HeapBlock* ptr ) +{ + NATIVE_PROFILE_CLR_CORE(); + + while(true) + { + if(ptr < m_payloadStart || ptr >= m_payloadEnd) + { + CLR_Debug::Printf( "Block beyond cluster limits: %08x [%08x : %08x-%08x]\r\n", (size_t)ptr, (size_t)this, (size_t)m_payloadStart, (size_t)m_payloadEnd ); + + break; + } + + if(ptr->DataType() >= DATATYPE_FIRST_INVALID) + { + CLR_Debug::Printf( "Bad Block Type: %08x %02x [%08x : %08x-%08x]\r\n", (size_t)ptr, ptr->DataType(), (size_t)this, (size_t)m_payloadStart, (size_t)m_payloadEnd ); + + break; + } + + if(ptr->DataSize() == 0) + { + CLR_Debug::Printf( "Bad Block null-size: %08x [%08x : %08x-%08x]\r\n", (size_t)ptr, (size_t)this, (size_t)m_payloadStart, (size_t)m_payloadEnd ); + + break; + } + + if(ptr + ptr->DataSize() > m_payloadEnd) + { + CLR_Debug::Printf( "Bad Block size: %d %08x [%08x : %08x-%08x]\r\n", ptr->DataSize(), (size_t)ptr, (size_t)this, (size_t)m_payloadStart, (size_t)m_payloadEnd ); + + break; + } + + return; + } + + TINYCLR_DEBUG_STOP(); +} + +#endif diff --git a/src/CLR/Core/CLR_RT_Memory.cpp b/src/CLR/Core/CLR_RT_Memory.cpp new file mode 100644 index 0000000000..876f6ab475 --- /dev/null +++ b/src/CLR/Core/CLR_RT_Memory.cpp @@ -0,0 +1,208 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(TINYCLR_TRACE_MALLOC) +static CLR_UINT32 s_TotalAllocated; +#endif + +CLR_RT_MemoryRange s_CLR_RT_Heap = { 0, 0 }; + +static int s_PreHeapInitIndex = 0; + +//////////////////////////////////////////////////////////// + +HAL_DECLARE_CUSTOM_HEAP( CLR_RT_Memory::Allocate, CLR_RT_Memory::Release, CLR_RT_Memory::ReAllocate ); + +//--// + +void CLR_RT_Memory::Reset() +{ + NATIVE_PROFILE_CLR_CORE(); + ::HeapLocation( s_CLR_RT_Heap.m_location, s_CLR_RT_Heap.m_size ); + +#if defined(TINYCLR_TRACE_MALLOC) + s_TotalAllocated = 0; +#endif +} + +void* CLR_RT_Memory::SubtractFromSystem( size_t len ) +{ + NATIVE_PROFILE_CLR_CORE(); + len = ROUNDTOMULTIPLE(len,CLR_UINT32); + + if(len <= s_CLR_RT_Heap.m_size) + { + s_CLR_RT_Heap.m_size -= (CLR_UINT32)len; + + return &s_CLR_RT_Heap.m_location[ s_CLR_RT_Heap.m_size ]; + } + + return NULL; +} + +//--// + +#if defined(TINYCLR_FILL_MEMORY_WITH_DIRTY_PATTERN) + +#define DEBUG_POINTER_INCREMENT(ptr,size) ptr = (void*)((char*)ptr + (size)) +#define DEBUG_POINTER_DECREMENT(ptr,size) ptr = (void*)((char*)ptr - (size)) + +const CLR_UINT32 c_extra = sizeof(CLR_RT_HeapBlock) * 2; + +#endif + + +void CLR_RT_Memory::Release( void* ptr ) +{ + NATIVE_PROFILE_CLR_CORE(); + + // CLR heap not initialized yet, return (this is not an error condition because we allow pre + if(s_CLR_RT_Heap.m_size == 0) + { + return; + } + + if(ptr) + { +#if defined(TINYCLR_FILL_MEMORY_WITH_DIRTY_PATTERN) + DEBUG_POINTER_DECREMENT(ptr,c_extra+sizeof(CLR_UINT32)); +#endif + + CLR_RT_HeapBlock_BinaryBlob* pThis = CLR_RT_HeapBlock_BinaryBlob::GetBlob( ptr ); + + if(pThis->DataType() != DATATYPE_BINARY_BLOB_HEAD) + { + TINYCLR_STOP(); + } + else + { +#if defined(TINYCLR_FILL_MEMORY_WITH_DIRTY_PATTERN) + CLR_UINT32 len = *(CLR_UINT32*)ptr; + CLR_UINT8* blk; + CLR_UINT32 pos; + + for(pos=0, blk=(CLR_UINT8*)ptr + sizeof(len); posDataSize(); + CLR_Debug::Printf( "CLR_RT_Memory::Release : %08x = %3d blocks (tot %4d)\r\n", ptr, pThis->DataSize(), s_TotalAllocated ); +#endif + + pThis->Release( true ); + } + } +} + +void* CLR_RT_Memory::Allocate( size_t len, CLR_UINT32 flags ) +{ + NATIVE_PROFILE_CLR_CORE(); + + if(s_CLR_RT_Heap.m_size == 0) + { + UINT8* heapStart = NULL; + UINT32 heapSize = 0; + + ::HeapLocation( heapStart, heapSize ); + + if(len > heapSize) + { + ASSERT(FALSE); + return NULL; + + } + + // use the current index to prevent heap thrashing before initialization + heapStart = &heapStart[ s_PreHeapInitIndex ]; + + s_PreHeapInitIndex += len; + + return heapStart; + } + + flags |= CLR_RT_HeapBlock::HB_Event; + +#if defined(TINYCLR_FILL_MEMORY_WITH_DIRTY_PATTERN) + len += c_extra * 2 + sizeof(CLR_UINT32); +#endif + + CLR_RT_HeapBlock_BinaryBlob* obj = CLR_RT_HeapBlock_BinaryBlob::Allocate( (CLR_UINT32)len, flags ); + if(obj) + { + void* res = obj->GetData(); + +#if defined(TINYCLR_TRACE_MALLOC) + s_TotalAllocated += obj->DataSize(); + CLR_Debug::Printf( "CLR_RT_Memory::Allocate: %08x = %3d blocks (tot %4d), %d bytes\r\n", res, obj->DataSize(), s_TotalAllocated, len ); +#endif + +#if defined(TINYCLR_FILL_MEMORY_WITH_DIRTY_PATTERN) + memset( res, 0xDD, len ); + + *(CLR_UINT32*)res = (CLR_UINT32)len; + + DEBUG_POINTER_INCREMENT(res,c_extra+sizeof(CLR_UINT32)); +#endif + + return res; + } + + return NULL; +} + +void* CLR_RT_Memory::Allocate_And_Erase( size_t len, CLR_UINT32 flags ) +{ + NATIVE_PROFILE_CLR_CORE(); + void* ptr = CLR_RT_Memory::Allocate( len, flags ); + + if(ptr) ZeroFill( ptr, len ); + + return ptr; +} + + +void* CLR_RT_Memory::ReAllocate( void* ptr, size_t len ) +{ + NATIVE_PROFILE_CLR_CORE(); + + // allocate always as an event but do not run GC on failure + void* p = CLR_RT_Memory::Allocate( len, CLR_RT_HeapBlock::HB_Event | CLR_RT_HeapBlock::HB_NoGcOnFailedAllocation); if(!p) return NULL; + + if(ptr) + { + CLR_RT_HeapBlock_BinaryBlob* pThis = CLR_RT_HeapBlock_BinaryBlob::GetBlob( ptr ); + + size_t prevLen = pThis->DataSize() * sizeof(CLR_RT_HeapBlock); + + memcpy( p, ptr, len > prevLen ? prevLen : len ); + + CLR_RT_Memory::Release( ptr ); + + ptr = p; + } + + return p; +} + diff --git a/src/CLR/Core/CLR_RT_ObjectToEvent_Destination.cpp b/src/CLR/Core/CLR_RT_ObjectToEvent_Destination.cpp new file mode 100644 index 0000000000..54a4d52395 --- /dev/null +++ b/src/CLR/Core/CLR_RT_ObjectToEvent_Destination.cpp @@ -0,0 +1,72 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_ObjectToEvent_Destination::Initialize() +{ + NATIVE_PROFILE_CLR_CORE(); + m_references.DblLinkedList_Initialize(); +} + +void CLR_RT_ObjectToEvent_Destination::CheckAll() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_FOREACH_NODE(CLR_RT_ObjectToEvent_Source,ref,m_references) + { + ref->EnsureObjectIsAlive(); + } + TINYCLR_FOREACH_NODE_END(); +} + +void CLR_RT_ObjectToEvent_Destination::SignalAll() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_FOREACH_NODE(CLR_RT_ObjectToEvent_Source,ref,m_references) + { + if(ref->m_objectPtr) + { + CLR_RT_HeapBlock_WaitForObject::SignalObject( *ref->m_objectPtr ); + } + } + TINYCLR_FOREACH_NODE_END(); +} + +void CLR_RT_ObjectToEvent_Destination::DetachAll() +{ + NATIVE_PROFILE_CLR_CORE(); + while(true) + { + CLR_RT_ObjectToEvent_Source* ref = (CLR_RT_ObjectToEvent_Source*)m_references.ExtractFirstNode(); if(!ref) break; + + ref->Detach(); + } +} + +bool CLR_RT_ObjectToEvent_Destination::IsReadyForRelease() +{ + NATIVE_PROFILE_CLR_CORE(); + if(m_references.IsEmpty()) + { + if(IsForcedAlive() == false) + { + return true; + } + } + + return false; +} + +bool CLR_RT_ObjectToEvent_Destination::ReleaseWhenDead() +{ + NATIVE_PROFILE_CLR_CORE(); + bool res = IsReadyForRelease(); + + if(res) g_CLR_RT_EventCache.Append_Node( this ); + + return res; +} diff --git a/src/CLR/Core/CLR_RT_ObjectToEvent_Source.cpp b/src/CLR/Core/CLR_RT_ObjectToEvent_Source.cpp new file mode 100644 index 0000000000..1cee23e3c4 --- /dev/null +++ b/src/CLR/Core/CLR_RT_ObjectToEvent_Source.cpp @@ -0,0 +1,62 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_ObjectToEvent_Source::CreateInstance( CLR_RT_ObjectToEvent_Destination* event, CLR_RT_HeapBlock& object, CLR_RT_HeapBlock& reference ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_ObjectToEvent_Source* oe = EVENTCACHE_EXTRACT_NODE(g_CLR_RT_EventCache,CLR_RT_ObjectToEvent_Source,DATATYPE_OBJECT_TO_EVENT); CHECK_ALLOCATION(oe); + + oe->m_eventPtr = event; // Pointer to the event referenced. + + oe->m_objectPtr = &object; // Pointer to the object to keep alive. + oe->m_referencePtr = &reference; // Pointer to the HeapBlock referencing this structure. + + reference.SetObjectReference( oe ); + + event->m_references.LinkAtBack( oe ); + + TINYCLR_NOCLEANUP(); +} + +CLR_RT_ObjectToEvent_Source* CLR_RT_ObjectToEvent_Source::ExtractInstance( CLR_RT_HeapBlock& reference ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(reference.IsAReferenceOfThisType( DATATYPE_OBJECT_TO_EVENT ) == false) return NULL; + + return (CLR_RT_ObjectToEvent_Source*)reference.Dereference(); +} + + +void CLR_RT_ObjectToEvent_Source::EnsureObjectIsAlive() +{ + NATIVE_PROFILE_CLR_CORE(); + if(m_objectPtr && m_objectPtr->IsAlive()) return; + + Detach(); +} + +void CLR_RT_ObjectToEvent_Source::Detach() +{ + NATIVE_PROFILE_CLR_CORE(); + if(m_referencePtr) + { + m_referencePtr->SetObjectReference( NULL ); + } + + g_CLR_RT_EventCache.Append_Node( this ); +} + +void CLR_RT_ObjectToEvent_Source::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_objectPtr ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_referencePtr ); +} diff --git a/src/CLR/Core/CLR_RT_RuntimeMemory.cpp b/src/CLR/Core/CLR_RT_RuntimeMemory.cpp new file mode 100644 index 0000000000..993c25a09b --- /dev/null +++ b/src/CLR/Core/CLR_RT_RuntimeMemory.cpp @@ -0,0 +1,136 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "TinyCLR_Interop.h" + +//////////////////////////////////////// +// !!! DO NOT EDIT THIS FILE !!! + +#define LINK_SIZE_BYTES 4 +#define PAYLOAD_SIZE_BYTES 12 +#define INTERRUPT_RECORD_SIZE_BYTES 24 +#define INLINE_SIZE_BYTES (8 * sizeof(int*) + sizeof(int)) + +#define ENTRY_SIZE__extrasmall 32 +#define HASH_TABLE_ENTRY__extrasmall 9 +#define INTERRUPT_RECORDS__extrasmall 16 +#define INLINE_BUFFER__extrasmall 16 + +#define ENTRY_SIZE__small 128 +#define HASH_TABLE_ENTRY__small 33 +#define INTERRUPT_RECORDS__small 64 +#define INLINE_BUFFER__small 32 + +#define ENTRY_SIZE__medium 512 +#define HASH_TABLE_ENTRY__medium 129 +#define INTERRUPT_RECORDS__medium 128 +#define INLINE_BUFFER__medium 64 + +#define ENTRY_SIZE__large 2048 +#define HASH_TABLE_ENTRY__large 521 +#define INTERRUPT_RECORDS__large 512 +#define INLINE_BUFFER__large 128 + +///////////////////////////////////////////// +// undefine everything and define defaults +#ifdef PLATFORM_DEPENDENT_ENTRY_SIZE +#undef PLATFORM_DEPENDENT_ENTRY_SIZE +#endif +#define PLATFORM_DEPENDENT_ENTRY_SIZE ENTRY_SIZE__medium + +#ifdef PLATFORM_DEPENDENT_HASH_TABLE_SIZE +#undef PLATFORM_DEPENDENT_HASH_TABLE_SIZE +#endif +#define PLATFORM_DEPENDENT_HASH_TABLE_SIZE HASH_TABLE_ENTRY__medium + +#ifdef PLATFORM_DEPENDENT_INTERRUPT_RECORDS +#undef PLATFORM_DEPENDENT_INTERRUPT_RECORDS +#endif +#define PLATFORM_DEPENDENT_INTERRUPT_RECORDS INTERRUPT_RECORDS__medium + +#ifdef PLATFORM_DEPENDENT_INLINE_BUFFER_SIZE +#undef PLATFORM_DEPENDENT_INLINE_BUFFER_SIZE +#endif +#define PLATFORM_DEPENDENT_INLINE_BUFFER_SIZE INLINE_BUFFER__medium + +// undefine everything and define defaults +///////////////////////////////////////////// + +//////////////////////////////////////////////////////// +// apply user selection from platform_selector.h file +#ifdef RUNTIME_MEMORY_PROFILE__extrasmall +#undef PLATFORM_DEPENDENT_ENTRY_SIZE +#define PLATFORM_DEPENDENT_ENTRY_SIZE ENTRY_SIZE__extrasmall +#undef PLATFORM_DEPENDENT_HASH_TABLE_SIZE +#define PLATFORM_DEPENDENT_HASH_TABLE_SIZE HASH_TABLE_ENTRY__extrasmall +#undef PLATFORM_DEPENDENT_INTERRUPT_RECORDS +#define PLATFORM_DEPENDENT_INTERRUPT_RECORDS INTERRUPT_RECORDS__extrasmall +#undef PLATFORM_DEPENDENT_INLINE_BUFFER_SIZE +#define PLATFORM_DEPENDENT_INLINE_BUFFER_SIZE INLINE_BUFFER__extrasmall +#endif + +#ifdef RUNTIME_MEMORY_PROFILE__small +#undef PLATFORM_DEPENDENT_ENTRY_SIZE +#define PLATFORM_DEPENDENT_ENTRY_SIZE ENTRY_SIZE__small +#undef PLATFORM_DEPENDENT_HASH_TABLE_SIZE +#define PLATFORM_DEPENDENT_HASH_TABLE_SIZE HASH_TABLE_ENTRY__small +#undef PLATFORM_DEPENDENT_INTERRUPT_RECORDS +#define PLATFORM_DEPENDENT_INTERRUPT_RECORDS INTERRUPT_RECORDS__small +#undef PLATFORM_DEPENDENT_INLINE_BUFFER_SIZE +#define PLATFORM_DEPENDENT_INLINE_BUFFER_SIZE INLINE_BUFFER__small +#endif + +#ifdef RUNTIME_MEMORY_PROFILE__medium +#undef PLATFORM_DEPENDENT_ENTRY_SIZE +#define PLATFORM_DEPENDENT_ENTRY_SIZE ENTRY_SIZE__medium +#undef PLATFORM_DEPENDENT_HASH_TABLE_SIZE +#define PLATFORM_DEPENDENT_HASH_TABLE_SIZE HASH_TABLE_ENTRY__medium +#undef PLATFORM_DEPENDENT_INTERRUPT_RECORDS +#define PLATFORM_DEPENDENT_INTERRUPT_RECORDS INTERRUPT_RECORDS__medium +#undef PLATFORM_DEPENDENT_INLINE_BUFFER_SIZE +#define PLATFORM_DEPENDENT_INLINE_BUFFER_SIZE INLINE_BUFFER__medium +#endif + +#ifdef RUNTIME_MEMORY_PROFILE__large +#undef PLATFORM_DEPENDENT_ENTRY_SIZE +#define PLATFORM_DEPENDENT_ENTRY_SIZE ENTRY_SIZE__large +#undef PLATFORM_DEPENDENT_HASH_TABLE_SIZE +#define PLATFORM_DEPENDENT_HASH_TABLE_SIZE HASH_TABLE_ENTRY__large +#undef PLATFORM_DEPENDENT_INTERRUPT_RECORDS +#define PLATFORM_DEPENDENT_INTERRUPT_RECORDS INTERRUPT_RECORDS__large +#undef PLATFORM_DEPENDENT_INLINE_BUFFER_SIZE +#define PLATFORM_DEPENDENT_INLINE_BUFFER_SIZE INLINE_BUFFER__large +#endif +// apply user selection from platform_selector.h file +//////////////////////////////////////////////////////// + +//--// + +size_t LinkArraySize () { return (PLATFORM_DEPENDENT_ENTRY_SIZE + PLATFORM_DEPENDENT_HASH_TABLE_SIZE); } +size_t LinkMRUArraySize() { return (PLATFORM_DEPENDENT_ENTRY_SIZE + 1 ); } +size_t PayloadArraySize() { return PLATFORM_DEPENDENT_ENTRY_SIZE; } +#ifndef TINYCLR_NO_IL_INLINE +size_t InlineBufferCount() { return PLATFORM_DEPENDENT_INLINE_BUFFER_SIZE; } +#endif + +UINT32 g_scratchVirtualMethodTableLink [ LINK_SIZE_BYTES * (PLATFORM_DEPENDENT_ENTRY_SIZE + PLATFORM_DEPENDENT_HASH_TABLE_SIZE) / sizeof(UINT32) + 1 ]; +UINT32 g_scratchVirtualMethodTableLinkMRU[ LINK_SIZE_BYTES * (PLATFORM_DEPENDENT_ENTRY_SIZE + 1 ) / sizeof(UINT32) + 1 ]; +UINT32 g_scratchVirtualMethodPayload [ PAYLOAD_SIZE_BYTES * PLATFORM_DEPENDENT_ENTRY_SIZE / sizeof(UINT32) + 1 ]; + +#ifndef TINYCLR_NO_IL_INLINE +UINT32 g_scratchInlineBuffer[ INLINE_SIZE_BYTES * PLATFORM_DEPENDENT_INLINE_BUFFER_SIZE / sizeof(UINT32) + 1 ]; +#endif + +//--// + +size_t InterruptRecords() { return PLATFORM_DEPENDENT_INTERRUPT_RECORDS; } + +UINT32 g_scratchInterruptDispatchingStorage[ (PLATFORM_DEPENDENT_INTERRUPT_RECORDS * INTERRUPT_RECORD_SIZE_BYTES) / sizeof(UINT32) + 1 ]; + +//--// + +// !!! DO NOT EDIT THIS FILE !!! +//////////////////////////////////////// + diff --git a/src/CLR/Core/CLR_RT_StackFrame.cpp b/src/CLR/Core/CLR_RT_StackFrame.cpp new file mode 100644 index 0000000000..1490bcc239 --- /dev/null +++ b/src/CLR/Core/CLR_RT_StackFrame.cpp @@ -0,0 +1,1165 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_StackFrame::Push( CLR_RT_Thread* th, const CLR_RT_MethodDef_Instance& callInst, CLR_INT32 extraBlocks ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_StackFrame* stack; + CLR_RT_StackFrame* caller; + CLR_RT_Assembly* assm; + const CLR_RECORD_METHODDEF* md; + const CLR_RT_MethodDef_Instance* callInstPtr = &callInst; + CLR_UINT32 sizeLocals; + CLR_UINT32 sizeEvalStack; + +#if defined(PLATFORM_WINDOWS_EMULATOR) + if(s_CLR_RT_fTrace_SimulateSpeed > c_CLR_RT_Trace_None) + { + CLR_PROF_Handler::SuspendTime(); + + HAL_Windows_FastSleep( g_HAL_Configuration_Windows.TicksPerMethodCall ); + + CLR_PROF_Handler::ResumeTime(); + } +#endif + + assm = callInstPtr->m_assm; + md = callInstPtr->m_target; + + sizeLocals = md->numLocals; +#ifndef TINYCLR_NO_IL_INLINE + sizeEvalStack = md->lengthEvalStack + CLR_RT_StackFrame::c_OverheadForNewObjOrInteropMethod + 1; +#else + sizeEvalStack = md->lengthEvalStack + CLR_RT_StackFrame::c_OverheadForNewObjOrInteropMethod; +#endif + + //--// + + caller = th->CurrentFrame(); + + //--// + + // + // Allocate memory for the runtime state. + // + { + CLR_UINT32 memorySize = sizeLocals + sizeEvalStack; + + if(extraBlocks > 0 ) memorySize += extraBlocks; +#ifndef TINYCLR_NO_IL_INLINE + if(memorySize < c_MinimumStack) + { + sizeEvalStack += c_MinimumStack - memorySize; + memorySize = c_MinimumStack; + } +#else + if(memorySize < c_MinimumStack) memorySize = c_MinimumStack; +#endif + + memorySize += CONVERTFROMSIZETOHEAPBLOCKS(offsetof(CLR_RT_StackFrame,m_extension)); + + stack = EVENTCACHE_EXTRACT_NODE_AS_BLOCKS(g_CLR_RT_EventCache,CLR_RT_StackFrame,DATATYPE_STACK_FRAME,0,memorySize); CHECK_ALLOCATION(stack); + } + + //--// + + { // + stack->m_owningSubThread = th->CurrentSubThread(); // CLR_RT_SubThread* m_owningSubThread; // EVENT HEAP - NO RELOCATION - + stack->m_owningThread = th; // CLR_RT_Thread* m_owningThread; // EVENT HEAP - NO RELOCATION - + // CLR_UINT32 m_flags; + // + stack->m_call = *callInstPtr; // CLR_RT_MethodDef_Instance m_call; + // + // CLR_RT_MethodHandler m_nativeMethod; + // CLR_PMETADATA m_IPstart; // ANY HEAP - DO RELOCATION - + // CLR_PMETADATA m_IP; // ANY HEAP - DO RELOCATION - + // + stack->m_locals = stack->m_extension; // CLR_RT_HeapBlock* m_locals; // EVENT HEAP - NO RELOCATION - + stack->m_evalStack = stack->m_extension + sizeLocals; // CLR_RT_HeapBlock* m_evalStack; // EVENT HEAP - NO RELOCATION - + stack->m_evalStackPos = stack->m_evalStack; // CLR_RT_HeapBlock* m_evalStackPos; // EVENT HEAP - NO RELOCATION - + stack->m_evalStackEnd = stack->m_evalStack + sizeEvalStack; // CLR_RT_HeapBlock* m_evalStackEnd; // EVENT HEAP - NO RELOCATION - + stack->m_arguments = NULL; // CLR_RT_HeapBlock* m_arguments; // EVENT HEAP - NO RELOCATION - + // + // union + // { + stack->m_customState = 0; // CLR_UINT32 m_customState; + // void* m_customPointer; + // }; + // +#ifndef TINYCLR_NO_IL_INLINE + stack->m_inlineFrame = NULL; +#endif +#if defined(TINYCLR_PROFILE_NEW_CALLS) + stack->m_callchain.Enter( stack ); // CLR_PROF_CounterCallChain m_callchain; +#endif + // + // CLR_RT_HeapBlock m_extension[1]; + // +#if defined(ENABLE_NATIVE_PROFILER) + stack->m_fNativeProfiled = stack->m_owningThread->m_fNativeProfiled; +#endif + CLR_RT_MethodHandler impl; + +#if defined(TINYCLR_APPDOMAINS) + stack->m_appDomain = g_CLR_RT_ExecutionEngine.GetCurrentAppDomain(); +#endif + + if(md->flags & CLR_RECORD_METHODDEF::MD_DelegateInvoke) // Special case for delegate calls. + { + stack->m_nativeMethod = (CLR_RT_MethodHandler)CLR_RT_Thread::Execute_DelegateInvoke; + + stack->m_flags = CLR_RT_StackFrame::c_MethodKind_Native; + stack->m_IPstart = NULL; + } + else if(assm->m_nativeCode && (impl = assm->m_nativeCode[ stack->m_call.Method() ]) != NULL) + { + stack->m_nativeMethod = impl; + + stack->m_flags = CLR_RT_StackFrame::c_MethodKind_Native; + stack->m_IPstart = NULL; + stack->m_IP = NULL; + } + else + { + stack->m_nativeMethod = (CLR_RT_MethodHandler)CLR_RT_Thread::Execute_IL; + + if(md->RVA == CLR_EmptyIndex) TINYCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + + stack->m_flags = CLR_RT_StackFrame::c_MethodKind_Interpreted; + stack->m_IPstart = assm->GetByteCode( md->RVA ); + stack->m_IP = stack->m_IPstart; + } + + #if defined(ENABLE_NATIVE_PROFILER) + if(stack->m_owningThread->m_fNativeProfiled == false && md->flags & CLR_RECORD_METHODDEF::MD_NativeProfiled) + { + stack->m_flags |= CLR_RT_StackFrame::c_NativeProfiled; + stack->m_owningThread->m_fNativeProfiled = true; + } + #endif + + //--// + + th->m_stackFrames.LinkAtBack( stack ); + +#if defined(TINYCLR_PROFILE_NEW_CALLS) + g_CLR_PRF_Profiler.RecordFunctionCall( th, callInst ); +#endif + } + + if(md->numLocals) + { + g_CLR_RT_ExecutionEngine.InitializeLocals( stack->m_locals, assm, md ); + } + + { + CLR_UINT32 flags = md->flags & (md->MD_Synchronized | md->MD_GloballySynchronized); + + if(flags) + { + if(flags & md->MD_Synchronized ) stack->m_flags |= c_NeedToSynchronize; + if(flags & md->MD_GloballySynchronized) stack->m_flags |= c_NeedToSynchronizeGlobally; + } + } + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + stack->m_depth = stack->Caller()->Prev() ? stack->Caller()->m_depth + 1 : 0; + + if(g_CLR_RT_ExecutionEngine.m_breakpointsNum) + { + if(stack->m_call.DebuggingInfo().HasBreakpoint()) + { + stack->m_flags |= CLR_RT_StackFrame::c_HasBreakpoint; + } + + if(stack->m_owningThread->m_fHasJMCStepper || (stack->m_flags & c_HasBreakpoint) || (caller->Prev() != NULL && (caller->m_flags & c_HasBreakpoint))) + { + g_CLR_RT_ExecutionEngine.Breakpoint_StackFrame_Push( stack, CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_DEPTH_STEP_CALL ); + } + } +#endif + + //--// + + if(caller->Prev() != NULL && caller->m_nativeMethod == stack->m_nativeMethod) + { + if(stack->m_flags & CLR_RT_StackFrame::c_ProcessSynchronize) + { + stack->m_flags |= CLR_RT_StackFrame::c_CallerIsCompatibleForRet; + } + else + { + stack->m_flags |= CLR_RT_StackFrame::c_CallerIsCompatibleForCall | CLR_RT_StackFrame::c_CallerIsCompatibleForRet; + } + } + + // + // If the arguments are in the caller's stack frame (var == 0), let's link the two. + // + if(extraBlocks < 0) + { +#if defined(_WIN32) || (defined(PLATFORM_WINCE) && defined(_DEBUG)) + if(caller->m_evalStackPos > caller->m_evalStackEnd) + { + TINYCLR_SET_AND_LEAVE(CLR_E_STACK_OVERFLOW); + } +#endif + + // + // Everything is set up correctly, pop the operands. + // + stack->m_arguments = &caller->m_evalStackPos[ -md->numArgs ]; + + caller->m_evalStackPos = stack->m_arguments; + +#if defined(_WIN32) || (defined(PLATFORM_WINCE) && defined(_DEBUG)) + if(stack->m_arguments < caller->m_evalStack) + { + TINYCLR_SET_AND_LEAVE(CLR_E_STACK_UNDERFLOW); + } +#endif + } + else + { + stack->m_arguments = stack->m_evalStackEnd; + } + + TINYCLR_CLEANUP(); + + + TINYCLR_CLEANUP_END(); +} + +#ifndef TINYCLR_NO_IL_INLINE +bool CLR_RT_StackFrame::PushInline( CLR_PMETADATA& ip, CLR_RT_Assembly*& assm, CLR_RT_HeapBlock*& evalPos, CLR_RT_MethodDef_Instance& calleeInst, CLR_RT_HeapBlock* pThis) +{ + const CLR_RECORD_METHODDEF* md = calleeInst.m_target; + + if( (m_inlineFrame != NULL) || // We can only support one inline at a time per stack call + (m_evalStackEnd - evalPos) <= (md->numArgs + md->numLocals + md->lengthEvalStack + 2) || // We must have enough space on the current stack for the inline method + (m_nativeMethod != (CLR_RT_MethodHandler)CLR_RT_Thread::Execute_IL) || // We only support IL inlining + (md->flags & ~CLR_RECORD_METHODDEF::MD_HasExceptionHandlers) >= CLR_RECORD_METHODDEF::MD_Constructor || // Do not try to inline constructors, etc because they require special processing + (0 != (md->flags & CLR_RECORD_METHODDEF::MD_Static)) || // Static methods also requires special processing + (calleeInst.m_assm->m_nativeCode != NULL && (calleeInst.m_assm->m_nativeCode[ calleeInst.Method() ] != NULL)) || // Make sure the callee is not an internal method + (md->RVA == CLR_EmptyIndex) || // Make sure we have a valid IP address for the method + !g_CLR_RT_EventCache.GetInlineFrameBuffer(&m_inlineFrame)) // Make sure we have an extra slot in the inline cache + { + return false; + } + + CLR_PMETADATA ipTmp = calleeInst.m_assm->GetByteCode( md->RVA ); + +#if defined(PLATFORM_WINDOWS_EMULATOR) + if(s_CLR_RT_fTrace_SimulateSpeed > c_CLR_RT_Trace_None) + { + CLR_PROF_Handler::SuspendTime(); + + HAL_Windows_FastSleep( g_HAL_Configuration_Windows.TicksPerMethodCall ); + + CLR_PROF_Handler::ResumeTime(); + } +#endif + + // make backup + m_inlineFrame->m_frame.m_IP = ip; + m_inlineFrame->m_frame.m_IPStart = m_IPstart; + m_inlineFrame->m_frame.m_locals = m_locals; + m_inlineFrame->m_frame.m_args = m_arguments; + m_inlineFrame->m_frame.m_call = m_call; + m_inlineFrame->m_frame.m_evalStack = m_evalStack; + m_inlineFrame->m_frame.m_evalPos = pThis; + + // increment the evalPos pointer so that we don't corrupt the real stack + evalPos++; + assm = calleeInst.m_assm; + ip = ipTmp; + + m_arguments = pThis; + m_locals = &m_evalStackEnd[-md->numLocals]; + m_call = calleeInst; + m_evalStackEnd = m_locals; + m_evalStack = evalPos; + m_evalStackPos = evalPos + 1; + m_IPstart = ip; + m_IP = ip; + + if(md->numLocals) + { + g_CLR_RT_ExecutionEngine.InitializeLocals( m_locals, calleeInst.m_assm, md ); + } + + m_flags |= CLR_RT_StackFrame::c_MethodKind_Inlined; + + if(md->retVal != DATATYPE_VOID) + { + m_flags |= CLR_RT_StackFrame::c_InlineMethodHasReturnValue; + } + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + m_depth++; + + if(g_CLR_RT_ExecutionEngine.m_breakpointsNum) + { + if(m_call.DebuggingInfo().HasBreakpoint()) + { + m_flags |= CLR_RT_StackFrame::c_HasBreakpoint; + } + + if(m_owningThread->m_fHasJMCStepper || (m_flags & CLR_RT_StackFrame::c_HasBreakpoint)) + { + g_CLR_RT_ExecutionEngine.Breakpoint_StackFrame_Push( this, CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_DEPTH_STEP_CALL ); + } + } +#endif + + return true; +} + +void CLR_RT_StackFrame::PopInline() +{ + + CLR_RT_HeapBlock& src = m_evalStackPos[0]; + + RestoreFromInlineStack(); + + if(m_flags & CLR_RT_StackFrame::c_InlineMethodHasReturnValue) + { + if(m_owningThread->m_currentException.Dereference() == NULL) + { + CLR_RT_HeapBlock& dst = PushValueAndAssign( src ); + + dst.Promote(); + } + } + + g_CLR_RT_EventCache.FreeInlineBuffer(m_inlineFrame); + m_inlineFrame = NULL; + m_flags &= ~(CLR_RT_StackFrame::c_MethodKind_Inlined | CLR_RT_StackFrame::c_InlineMethodHasReturnValue); + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + if(m_owningThread->m_fHasJMCStepper || (m_flags & CLR_RT_StackFrame::c_HasBreakpoint)) + { + g_CLR_RT_ExecutionEngine.Breakpoint_StackFrame_Pop( this, false ); + } + m_depth--; +#endif +} + +void CLR_RT_StackFrame::RestoreFromInlineStack() +{ + m_arguments = m_inlineFrame->m_frame.m_args; + m_locals = m_inlineFrame->m_frame.m_locals; + m_evalStackEnd += m_call.m_target->numLocals; + m_call = m_inlineFrame->m_frame.m_call; + m_IP = m_inlineFrame->m_frame.m_IP; + m_IPstart = m_inlineFrame->m_frame.m_IPStart; + m_evalStack = m_inlineFrame->m_frame.m_evalStack; + m_evalStackPos = m_inlineFrame->m_frame.m_evalPos; +} + +void CLR_RT_StackFrame::RestoreStack(CLR_RT_InlineFrame& frame) +{ + m_arguments = frame.m_args; + m_locals = frame.m_locals; + m_call = frame.m_call; + m_IP = frame.m_IP; + m_IPstart = frame.m_IPStart; + m_evalStack = frame.m_evalStack; + m_evalStackPos = frame.m_evalPos; + m_evalStackEnd -= m_call.m_target->numLocals; +} + +void CLR_RT_StackFrame::SaveStack(CLR_RT_InlineFrame& frame) +{ + frame.m_args = m_arguments; + frame.m_locals = m_locals; + frame.m_call = m_call; + frame.m_IP = m_IP; + frame.m_IPStart = m_IPstart; + frame.m_evalPos = m_evalStackPos; + frame.m_evalStack = m_evalStack; +} +#endif + +#if defined(TINYCLR_APPDOMAINS) +HRESULT CLR_RT_StackFrame::PopAppDomainTransition() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + bool fException = false; + CLR_RT_HeapBlock exception; + CLR_RT_StackFrame* caller = this->Caller(); + + exception.SetObjectReference( NULL ); + + if(m_flags & CLR_RT_StackFrame::c_AppDomainInjectException) + { + //this is the last frame on the thread in a doomed AppDomain + //Convert the current ThreadAbortException into an AppDomainUnloaded exception + + _ASSERTE(m_owningThread->m_flags & CLR_RT_Thread::TH_F_Aborted); + _ASSERTE(m_owningThread->m_flags & CLR_RT_Thread::TH_F_ContainsDoomedAppDomain); + _ASSERTE(m_owningThread->m_currentException.Dereference() != NULL); + _ASSERTE(m_owningThread->m_currentException.Dereference()->ObjectCls().m_data == g_CLR_RT_WellKnownTypes.m_ThreadAbortException.m_data); + _ASSERTE(!m_appDomain->IsLoaded()); + + m_owningThread->m_flags &= ~(CLR_RT_Thread::TH_F_Aborted | CLR_RT_Thread::TH_F_ContainsDoomedAppDomain); + + hr = CLR_E_APPDOMAIN_EXITED; + } + else if(m_owningThread->m_currentException.Dereference() == NULL) + { + _ASSERTE((m_flags & CLR_RT_StackFrame::c_AppDomainInjectException) == 0); + + //Normal return. No exception is in flight + + if(m_flags & CLR_RT_StackFrame::c_AppDomainMethodInvoke) + { + // For dynamic invoke, + // we do not marshal byRef parameters back to the calling AppDomain + // The caller is a native method (MethodBase::Invoke), and does not have the args on it's eval stack. + } + else + { + int cArgs = m_call.m_target->numArgs; + + //First marshal the ref parameters + TINYCLR_CHECK_HRESULT(caller->m_appDomain->MarshalParameters( &caller->m_evalStackPos[ -cArgs ], m_arguments, cArgs, true )); + + //Now, pop the caller's arguments off the eval stack + caller->m_evalStackPos -= cArgs; + } + + // Now, push the return, if any. + if(m_call.m_target->retVal != DATATYPE_VOID) + { + CLR_RT_HeapBlock& dst = caller->PushValueAndClear(); + CLR_RT_HeapBlock& src = this ->TopValue (); + + TINYCLR_CHECK_HRESULT(caller->m_appDomain->MarshalObject( src, dst )); + + dst.Promote(); + } + } + else //Exception + { + //Normal exceptions must be marshaled to the caller's AppDomain + TINYCLR_CHECK_HRESULT(caller->m_appDomain->MarshalObject( m_owningThread->m_currentException, exception )); + fException = true; + } + + TINYCLR_CLEANUP(); + + if(FAILED(hr) || fException) + { + if(FAILED(hr)) + { + (void)Library_corlib_native_System_Exception::CreateInstance( exception, hr, caller ); + } + + m_owningThread->m_currentException.Assign( exception ); + } + + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( caller->m_appDomain ); + + TINYCLR_CLEANUP_END(); +} + +HRESULT CLR_RT_StackFrame::PushAppDomainTransition( CLR_RT_Thread* th, const CLR_RT_MethodDef_Instance& callInst, CLR_RT_HeapBlock* pThis, CLR_RT_HeapBlock* pArgs ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_StackFrame* frame = NULL; + int cArgs = callInst.m_target->numArgs; + CLR_RT_HeapBlock* proxy; + + _ASSERTE(pThis->IsTransparentProxy()); + + proxy = pThis->Dereference(); + + TINYCLR_CHECK_HRESULT(proxy->TransparentProxyValidate()); + + TINYCLR_CHECK_HRESULT(Push( th, callInst, cArgs )); + + frame = th->CurrentFrame(); + + frame->m_appDomain = proxy->TransparentProxyAppDomain(); + frame->m_flags |= CLR_RT_StackFrame::c_AppDomainTransition; + frame->m_flags &= ~CLR_RT_StackFrame::c_CallerIsCompatibleForRet; + + //Marshal the arguments from the caller (on the eval stack) to the callee, unitialized heapblocks that + //are set up by the extra blocks in CLR_RT_StackFrame::Push + TINYCLR_CHECK_HRESULT(frame->m_appDomain->MarshalObject ( *pThis, frame->m_arguments[ 0 ] )); + TINYCLR_CHECK_HRESULT(frame->m_appDomain->MarshalParameters( pArgs, &frame->m_arguments[ 1 ], cArgs-1, false )); + + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( frame->m_appDomain ); + + TINYCLR_NOCLEANUP(); +} + +#endif //TINYCLR_APPDOMAINS + +HRESULT CLR_RT_StackFrame::MakeCall( CLR_RT_MethodDef_Instance md, CLR_RT_HeapBlock* obj, CLR_RT_HeapBlock* args, int nArgs ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + const CLR_RECORD_METHODDEF* mdR = md.m_target; + bool fStatic =(mdR->flags & CLR_RECORD_METHODDEF::MD_Static) != 0; + int numArgs = mdR->numArgs; + int argsOffset = 0; + CLR_RT_StackFrame* stackSub; + CLR_RT_HeapBlock tmp; tmp.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc(tmp); + + if(mdR->flags & CLR_RECORD_METHODDEF::MD_Constructor) + { + CLR_RT_TypeDef_Instance owner; owner.InitializeFromMethod( md ); + + _ASSERTE(obj == NULL); + + _SIDE_ASSERTE(owner.InitializeFromMethod( md )); + + TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObject( tmp, owner )); + + obj = &tmp; + + // + // Make a copy of the object pointer. + // + PushValueAndAssign( tmp ); + } + + if(!fStatic) + { + FAULT_ON_NULL(obj); + numArgs--; + argsOffset = 1; + } + + if(numArgs != nArgs) TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + // + // In case the invoked method is abstract or virtual, resolve it to the correct method implementation. + // + if(mdR->flags & (CLR_RECORD_METHODDEF::MD_Abstract | CLR_RECORD_METHODDEF::MD_Virtual)) + { + CLR_RT_TypeDef_Index cls; + CLR_RT_MethodDef_Index mdReal; + + _ASSERTE(obj); + _ASSERTE(!fStatic); + + TINYCLR_CHECK_HRESULT(CLR_RT_TypeDescriptor::ExtractTypeIndexFromObject( *obj, cls )); + + if(g_CLR_RT_EventCache.FindVirtualMethod( cls, md, mdReal ) == false) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + md.InitializeFromIndex( mdReal ); + + mdR = md.m_target; + } + +#if defined(TINYCLR_APPDOMAINS) + + if(!fStatic && obj->IsTransparentProxy()) + { + TINYCLR_CHECK_HRESULT(CLR_RT_StackFrame::PushAppDomainTransition( m_owningThread, md, obj, args )); + + stackSub = m_owningThread->CurrentFrame(); + + stackSub->m_flags |= CLR_RT_StackFrame::c_AppDomainMethodInvoke; + } + else +#endif + { + TINYCLR_CHECK_HRESULT(CLR_RT_StackFrame::Push( m_owningThread, md, md.m_target->numArgs )); + + stackSub = m_owningThread->CurrentFrame(); + + if(!fStatic) + { + stackSub->m_arguments[ 0 ].Assign( *obj ); + } + + if(numArgs) + { + memcpy( &stackSub->m_arguments[ argsOffset ], args, sizeof(CLR_RT_HeapBlock) * numArgs ); + } + } + + TINYCLR_CHECK_HRESULT(stackSub->FixCall()); + + TINYCLR_SET_AND_LEAVE(CLR_E_RESTART_EXECUTION); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_StackFrame::FixCall() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + const CLR_RECORD_METHODDEF* target = m_call.m_target; + CLR_UINT8 numArgs = target->numArgs; + + // + // The copy of ValueTypes is delayed as much as possible. + // + // If an argument is a ValueType, now it's a good time to clone it. + // + if(numArgs) + { + CLR_RT_SignatureParser parser; parser.Initialize_MethodSignature( m_call.m_assm, target ); + CLR_RT_SignatureParser::Element res; + CLR_RT_HeapBlock* args = m_arguments; + + if(parser.m_flags & PIMAGE_CEE_CS_CALLCONV_HASTHIS) + { + args++; + } + + // + // Skip return value. + // + TINYCLR_CHECK_HRESULT(parser.Advance( res )); + + for(;parser.Available() > 0;args++) + { + TINYCLR_CHECK_HRESULT(parser.Advance( res )); + + if(res.m_levels > 0) continue; // Array, no need to fix. + + if(args->DataType() == DATATYPE_OBJECT) + { + CLR_RT_TypeDef_Instance inst; inst.InitializeFromIndex( res.m_cls ); + CLR_DataType dtT = (CLR_DataType)inst.m_target->dataType; + const CLR_RT_DataTypeLookup& dtl = c_CLR_RT_DataTypeLookup[ dtT ]; + + if(dtl.m_flags & (CLR_RT_DataTypeLookup::c_OptimizedValueType | CLR_RT_DataTypeLookup::c_ValueType)) + { + CLR_RT_HeapBlock* value = args->FixBoxingReference(); FAULT_ON_NULL(value); + + if(value->DataType() == dtT) + { + // It's a boxed primitive/enum type. + args->Assign( *value ); + } + else if(args->Dereference()->ObjectCls().m_data == res.m_cls.m_data) + { + TINYCLR_CHECK_HRESULT(args->PerformUnboxing( inst )); + } + else + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + } + + if(res.m_dt == DATATYPE_VALUETYPE && res.m_fByRef == false) + { + if(args->IsAReferenceOfThisType( DATATYPE_VALUETYPE )) + { + TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.CloneObject( *args, *args )); + } + } + } + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_StackFrame::HandleSynchronized( bool fAcquire, bool fGlobal ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock refType; + CLR_RT_HeapBlock* obj; + CLR_RT_HeapBlock ref; + CLR_RT_HeapBlock** ppGlobalLock; + CLR_RT_HeapBlock* pGlobalLock; + + if(fGlobal) + { + obj = &ref; + +#if defined(TINYCLR_APPDOMAINS) + //With AppDomains enabled, the global lock is no longer global. It is only global wrt the AppDomain/ + //Do we need a GlobalGlobalLock? (an attribute on GloballySynchronized (GlobalAcrossAppDomain?) + ppGlobalLock = &g_CLR_RT_ExecutionEngine.GetCurrentAppDomain()->m_globalLock; +#else + ppGlobalLock = &g_CLR_RT_ExecutionEngine.m_globalLock; +#endif + + pGlobalLock = *ppGlobalLock; + + if(pGlobalLock) + { + obj->SetObjectReference( pGlobalLock ); + } + else + { + // + // Create an private object to implement global locks. + // + TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex( *obj, g_CLR_RT_WellKnownTypes.m_Object )); + + *ppGlobalLock = obj->Dereference(); + } + } + else if(m_call.m_target->flags & CLR_RECORD_METHODDEF::MD_Static) + { + CLR_RT_TypeDef_Index idx; + + idx.Set( m_call.Assembly(), m_call.CrossReference().GetOwner() ); + + refType.SetReflection( idx ); + + obj = &refType; + } + else + { + obj = &Arg0(); + } + + if(fAcquire) + { + TINYCLR_SET_AND_LEAVE(g_CLR_RT_ExecutionEngine.LockObject( *obj, m_owningSubThread, TIMEOUT_INFINITE, false )); + } + else + { + TINYCLR_SET_AND_LEAVE(g_CLR_RT_ExecutionEngine.UnlockObject( *obj, m_owningSubThread )); + } + + TINYCLR_NOCLEANUP(); +} + +void CLR_RT_StackFrame::Pop() +{ + NATIVE_PROFILE_CLR_CORE(); + +#if defined(TINYCLR_PROFILE_NEW_CALLS) + { + // + // This passivates any outstanding handler. + // + CLR_PROF_HANDLER_CALLCHAIN(pm2,m_callchain); + + m_callchain.Leave(); + } +#endif + +#if defined(TINYCLR_PROFILE_NEW_CALLS) + g_CLR_PRF_Profiler.RecordFunctionReturn( m_owningThread, m_callchain ); +#endif + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + if(m_owningThread->m_fHasJMCStepper || (m_flags & c_HasBreakpoint)) + { + g_CLR_RT_ExecutionEngine.Breakpoint_StackFrame_Pop( this, false ); + } +#endif + + const CLR_UINT32 c_flagsToCheck = CLR_RT_StackFrame::c_CallOnPop | CLR_RT_StackFrame::c_Synchronized | CLR_RT_StackFrame::c_SynchronizedGlobally | CLR_RT_StackFrame::c_NativeProfiled; + + if(m_flags & c_flagsToCheck) + { + if(m_flags & CLR_RT_StackFrame::c_CallOnPop) + { + m_flags |= CLR_RT_StackFrame::c_CalledOnPop; + + if(m_nativeMethod) + { + (void)m_nativeMethod( *this ); + } + } + + if(m_flags & CLR_RT_StackFrame::c_Synchronized) + { + m_flags &= ~CLR_RT_StackFrame::c_Synchronized; + + (void)HandleSynchronized( false, false ); + } + + if(m_flags & CLR_RT_StackFrame::c_SynchronizedGlobally) + { + m_flags &= ~CLR_RT_StackFrame::c_SynchronizedGlobally; + + (void)HandleSynchronized( false, true ); + } + + #if defined(ENABLE_NATIVE_PROFILER) + if(m_flags & CLR_RT_StackFrame::c_NativeProfiled) + { + m_owningThread->m_fNativeProfiled = false; + m_flags &= ~CLR_RT_StackFrame::c_NativeProfiled; + Native_Profiler_Stop(); + } + #endif + } + + CLR_RT_StackFrame* caller = Caller(); + + if(caller->Prev() != NULL) + { +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + if(caller->m_flags & CLR_RT_StackFrame::c_HasBreakpoint) + { + g_CLR_RT_ExecutionEngine.Breakpoint_StackFrame_Step( caller, caller->m_IP ); + } +#endif + + // + // Constructors are slightly different, they push the 'this' pointer back into the caller stack. + // + // This is to enable the special case for strings, where the object can be recreated by the constructor... + // + if(caller->m_flags & CLR_RT_StackFrame::c_ExecutingConstructor) + { + CLR_RT_HeapBlock& src = this ->Arg0 ( ); + CLR_RT_HeapBlock& dst = caller->PushValueAndAssign( src ); + + dst.Promote(); + + // + // Undo the special "object -> reference" hack done by CEE_NEWOBJ. + // + if(dst.DataType() == DATATYPE_BYREF) + { + dst.ChangeDataType( DATATYPE_OBJECT ); + } + + caller->m_flags &= ~CLR_RT_StackFrame::c_ExecutingConstructor; + + _ASSERTE((m_flags & CLR_RT_StackFrame::c_AppDomainTransition) == 0); + } + else + { //Note that ExecutingConstructor is checked on 'caller', whereas the other two flags are checked on 'this' + const CLR_UINT32 c_moreFlagsToCheck = CLR_RT_StackFrame::c_PseudoStackFrameForFilter | CLR_RT_StackFrame::c_AppDomainTransition; + + if(m_flags & c_moreFlagsToCheck) + { + if(m_flags & CLR_RT_StackFrame::c_PseudoStackFrameForFilter) + { + //Do nothing here. Pushing return values onto stack frames that don't expect them are a bad idea. + } +#if defined(TINYCLR_APPDOMAINS) + else if((m_flags & CLR_RT_StackFrame::c_AppDomainTransition) != 0) + { + (void)PopAppDomainTransition(); + } +#endif + } + else //!c_moreFlagsToCheck + { + // + // Push the return, if any. + // + if(m_call.m_target->retVal != DATATYPE_VOID) + { + if(m_owningThread->m_currentException.Dereference() == NULL) + { + CLR_RT_HeapBlock& src = this ->TopValue ( ); + CLR_RT_HeapBlock& dst = caller->PushValueAndAssign( src ); + + dst.Promote(); + } + } + } + } + } +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + else + { + int idx = m_owningThread->m_scratchPad; + + if(idx >= 0) + { + CLR_RT_HeapBlock_Array* array = g_CLR_RT_ExecutionEngine.m_scratchPadArray; + + if(array && array->m_numOfElements > (CLR_UINT32)idx) + { + CLR_RT_HeapBlock* dst = (CLR_RT_HeapBlock*)array->GetElement( (CLR_UINT32)idx ); + CLR_RT_HeapBlock* exception = m_owningThread->m_currentException.Dereference(); + + dst->SetObjectReference( NULL ); + + if(exception != NULL) + { + dst->SetObjectReference( exception ); + } + else if(m_call.m_target->retVal != DATATYPE_VOID) + { + CLR_RT_SignatureParser sig; sig.Initialize_MethodSignature( this->m_call.m_assm, this->m_call.m_target ); + CLR_RT_SignatureParser::Element res; + CLR_RT_TypeDescriptor desc; + + dst->Assign( this->TopValue() ); + + //Perform boxing, if needed. + + //Box to the return value type + _SIDE_ASSERTE(SUCCEEDED(sig.Advance( res ))); + _SIDE_ASSERTE(SUCCEEDED(desc.InitializeFromType( res.m_cls ))); + + + if(c_CLR_RT_DataTypeLookup[ this->DataType() ].m_flags & CLR_RT_DataTypeLookup::c_OptimizedValueType + || desc.m_handlerCls.m_target->IsEnum() + ) + { + if(FAILED(dst->PerformBoxing( desc.m_handlerCls ))) + { + dst->SetObjectReference( NULL ); + } + } + } + } + } + } +#endif + + // + // We could be jumping outside of a nested exception handler. + // + + m_owningThread->PopEH( this, NULL ); + + + // + // If this StackFrame owns a SubThread, kill it. + // + { + CLR_RT_SubThread* sth = (CLR_RT_SubThread*)m_owningSubThread->Next(); + + if(sth->Next() && sth->m_owningStackFrame == this) + { + CLR_RT_SubThread::DestroyInstance( sth->m_owningThread, sth, CLR_RT_SubThread::MODE_IncludeSelf ); + } + } + + g_CLR_RT_EventCache.Append_Node( this ); +} + +//--// + +void CLR_RT_StackFrame::SetResult( CLR_INT32 val, CLR_DataType dataType ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& top = PushValue(); + + top.SetInteger( val, dataType ); +} + +#if !defined(TINYCLR_EMULATED_FLOATINGPOINT) + +void CLR_RT_StackFrame::SetResult_R4( float val ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& top = PushValue(); + + top.SetFloat( val ); +} + +void CLR_RT_StackFrame::SetResult_R8( double val ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& top = PushValue(); + + top.SetDouble( val ); +} + +#else + +void CLR_RT_StackFrame::SetResult_R4( CLR_INT32 val ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& top = PushValue(); + + top.SetFloat( val ); +} + +void CLR_RT_StackFrame::SetResult_R8( CLR_INT64 val ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& top = PushValue(); + + top.SetDouble( val ); +} + +#endif + +void CLR_RT_StackFrame::SetResult_I4( CLR_INT32 val ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& top = PushValue(); + + top.SetInteger( val ); +} + +void CLR_RT_StackFrame::SetResult_I8( CLR_INT64& val ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& top = PushValue(); + + top.SetInteger( val ); +} + +void CLR_RT_StackFrame::SetResult_U4( CLR_UINT32 val ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& top = PushValue(); + + top.SetInteger( val ); +} + +void CLR_RT_StackFrame::SetResult_U8( CLR_UINT64& val ) + +{ + CLR_RT_HeapBlock& top = PushValue(); + + top.SetInteger( val ); +} + +void CLR_RT_StackFrame::SetResult_Boolean( bool val ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& top = PushValue(); + + top.SetBoolean( val ); +} + +void CLR_RT_StackFrame::SetResult_Object( CLR_RT_HeapBlock* val ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& top = PushValue(); + + top.SetObjectReference( val ); +} + +HRESULT CLR_RT_StackFrame::SetResult_String( LPCSTR val ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock& top = PushValue(); + + TINYCLR_SET_AND_LEAVE(CLR_RT_HeapBlock_String::CreateInstance( top, val )); + + TINYCLR_NOCLEANUP(); +} + + +void CLR_RT_StackFrame::ConvertResultToBoolean() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& top = TopValue(); + + top.SetBoolean( top.NumericByRef().s4 == 0 ); +} + +void CLR_RT_StackFrame::NegateResult() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock& top = TopValue(); + + top.NumericByRef().s4 = top.NumericByRef().s4 ? 0 : 1; +} + +//--// + +HRESULT CLR_RT_StackFrame::SetupTimeout( CLR_RT_HeapBlock& input, CLR_INT64*& output ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + if(m_customState == 0) + { + CLR_RT_HeapBlock& ref = PushValueAndClear(); + CLR_INT64 timeExpire; + + // + // Initialize timeout and save it on the stack. + // + TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.InitTimeout( timeExpire, input.NumericByRef().s4 )); + + ref.SetInteger( timeExpire ); + + m_customState = 1; + } + + output = (CLR_INT64*)&m_evalStack[ 0 ].NumericByRef().s8; + + TINYCLR_NOCLEANUP(); +} + +//--// + +void CLR_RT_StackFrame::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + +#ifndef TINYCLR_NO_IL_INLINE + if(m_inlineFrame) + { + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_inlineFrame->m_frame.m_call.m_assm ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_inlineFrame->m_frame.m_call.m_target ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_inlineFrame->m_frame.m_IPStart ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_inlineFrame->m_frame.m_IP ); + + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_call.m_assm ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_call.m_target ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_nativeMethod ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_IPstart ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_IP ); + + CLR_RT_GarbageCollector::Heap_Relocate( m_inlineFrame->m_frame.m_args , m_inlineFrame->m_frame.m_call.m_target->numArgs ); + CLR_RT_GarbageCollector::Heap_Relocate( m_inlineFrame->m_frame.m_locals , m_inlineFrame->m_frame.m_call.m_target->numLocals ); + CLR_RT_GarbageCollector::Heap_Relocate( m_inlineFrame->m_frame.m_evalStack, (int)(m_evalStackPos - m_inlineFrame->m_frame.m_evalStack) ); + CLR_RT_GarbageCollector::Heap_Relocate( m_locals, m_call.m_target->numLocals ); + } + else +#endif + { + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_call.m_assm ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_call.m_target ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_nativeMethod ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_IPstart ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_IP ); + + CLR_RT_GarbageCollector::Heap_Relocate( m_arguments, m_call.m_target->numArgs ); + CLR_RT_GarbageCollector::Heap_Relocate( m_locals , m_call.m_target->numLocals ); + CLR_RT_GarbageCollector::Heap_Relocate( m_evalStack, TopValuePosition() ); + } +} + +//--// + +HRESULT CLR_RT_StackFrame::NotImplementedStub() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + if(m_call.m_target->retVal != DATATYPE_VOID) + { + SetResult_I4( 0 ); + } + + TINYCLR_SET_AND_LEAVE(CLR_E_NOTIMPL); + + TINYCLR_NOCLEANUP(); +} + + diff --git a/src/CLR/Core/CLR_RT_SystemAssembliesTable.cpp b/src/CLR/Core/CLR_RT_SystemAssembliesTable.cpp new file mode 100644 index 0000000000..9fd41747ec --- /dev/null +++ b/src/CLR/Core/CLR_RT_SystemAssembliesTable.cpp @@ -0,0 +1,45 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include +//#include +//#include +//#include "TinyCLR_Interop.h" + +static const CLR_RT_NativeAssemblyData *LookUpAssemblyNativeDataByName +( + const CLR_RT_NativeAssemblyData **pAssembliesNativeData, + const char *lpszAssemblyName +) +{ + // Just sanity check to avoid crash in strcmp if name is NULL. + if ( lpszAssemblyName == NULL ) + { + return NULL; + } + + // Loops in all entries and looks for the CLR_RT_NativeAssemblyData with name same as lpszAssemblyName + for ( int i = 0; pAssembliesNativeData[ i ]; i++ ) + { + if ( pAssembliesNativeData[ i ] != NULL && 0 == strcmp( lpszAssemblyName, pAssembliesNativeData[ i ]->m_szAssemblyName ) ) + { + return pAssembliesNativeData[ i ]; + } + } + return NULL; +} + + +const CLR_RT_NativeAssemblyData *GetAssemblyNativeData( const char *lpszAssemblyName ) +{ + extern const CLR_RT_NativeAssemblyData *g_CLR_InteropAssembliesNativeData[]; + + // This will return NULL if there is no registered interop assembly of that name + return LookUpAssemblyNativeDataByName( + g_CLR_InteropAssembliesNativeData, + lpszAssemblyName + ); +} + diff --git a/src/CLR/Core/CLR_RT_UnicodeHelper.cpp b/src/CLR/Core/CLR_RT_UnicodeHelper.cpp new file mode 100644 index 0000000000..da33185818 --- /dev/null +++ b/src/CLR/Core/CLR_RT_UnicodeHelper.cpp @@ -0,0 +1,539 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#define UTF8_BAD_LOWPART(ch) (ch < 0x80 || ch > 0xBF) + +#define UTF8_CHECK_LOWPART(ch,src) ch = (CLR_UINT32)*src++; if(UTF8_BAD_LOWPART(ch)) return -1 + +#define UTF8_LOAD_LOWPART(ch,ch2,src) ch = (CLR_UINT32)*src++; ch2 <<= 6; ch2 |= (ch & 0x3F) + +//--// + +int CLR_RT_UnicodeHelper::CountNumberOfCharacters( int max ) +{ + NATIVE_PROFILE_CLR_CORE(); + const CLR_UINT8* pSrc = m_inputUTF8; + int num = 0; + + while(true) + { + CLR_UINT32 ch = (CLR_UINT32)*pSrc++; if(!ch) break; + + if(max-- == 0) break; // This works even if you pass -1 as argument (it will walk through the whole string). + + switch(ch & 0xF0) + { + case 0x00: + case 0x10: + case 0x20: + case 0x30: + case 0x40: + case 0x50: + case 0x60: + case 0x70: + num += 1; + break; + + case 0x80: + case 0x90: + case 0xA0: + case 0xB0: + return -1; // Illegal characters. + + case 0xC0: + case 0xD0: + UTF8_CHECK_LOWPART(ch,pSrc); + + num += 1; + break; + + case 0xE0: + UTF8_CHECK_LOWPART(ch,pSrc); + UTF8_CHECK_LOWPART(ch,pSrc); + + num += 1; + break; + + case 0xF0: + UTF8_CHECK_LOWPART(ch,pSrc); + UTF8_CHECK_LOWPART(ch,pSrc); + UTF8_CHECK_LOWPART(ch,pSrc); + + num += 2; + break; + } + } + + return num; +} + +int CLR_RT_UnicodeHelper::CountNumberOfBytes( int max ) +{ + NATIVE_PROFILE_CLR_CORE(); + const CLR_UINT16* pSrc = m_inputUTF16; + int num = 0; + + while(true) + { + CLR_UINT16 ch = *pSrc++; if(!ch) break; + + if(max-- == 0) break; // This works even if you pass -1 as argument (it will walk through the whole string). + + if(ch < 0x0080) + { + num += 1; + } + else if(ch < 0x0800) + { + num += 2; + } + else if(ch >= LOW_SURROGATE_START && ch <= LOW_SURROGATE_END) + { + return -1; // Invalid string: Low surrogate should only follow a high surrogate. + } + else if(ch >= HIGH_SURROGATE_START && ch <= HIGH_SURROGATE_END) + { + ch = *pSrc++; + + if(ch >= LOW_SURROGATE_START && ch <= LOW_SURROGATE_END) + { + num += 4; + max--; + } + else + { + return -1; // Invalid string: Low surrogate should follow a high surrogate. + } + } + else + { + num += 3; + } + } + + return num; +} + +//--// + +bool CLR_RT_UnicodeHelper::ConvertFromUTF8( int iMaxChars, bool fJustMove, int iMaxBytes ) +{ + NATIVE_PROFILE_CLR_CORE(); + const CLR_UINT8* inputUTF8 = m_inputUTF8; + CLR_UINT16* outputUTF16 = m_outputUTF16; + int outputUTF16_size = m_outputUTF16_size; + CLR_UINT32 ch; + CLR_UINT32 ch2; + bool res; + + if (iMaxBytes == -1) + { + iMaxBytes = iMaxChars * 3; // the max number of bytes it can have based on iMaxChars -- if all characters are of 3 bytes. + } + + while(iMaxChars > 0 && iMaxBytes > 0) + { + ch = (CLR_UINT32)*inputUTF8++; + + switch(ch & 0xF0) + { + case 0x00: if(ch == 0) { inputUTF8--; goto ExitFalse; } + case 0x10: + case 0x20: + case 0x30: + case 0x40: + case 0x50: + case 0x60: + case 0x70: + if(fJustMove == false) + { + if(outputUTF16_size < 1) + { + // un-read the byte before exiting + inputUTF8--; + goto ExitFalse; + } + + outputUTF16[ 0 ] = ch; + + outputUTF16 += 1; + outputUTF16_size -= 1; + } + + iMaxChars -= 1; + iMaxBytes -= 1; + break; + + case 0x80: + case 0x90: + case 0xA0: + case 0xB0: + goto ExitFalse; // Illegal characters. + + case 0xC0: + case 0xD0: + if((ch & 0xFF) < 0xC2) { inputUTF8--; goto ExitFalse; } // illegal - overlong encoding + + if(iMaxBytes >= 2) + { + if(fJustMove) + { + inputUTF8++; + } + else + { + if(outputUTF16_size < 1) + { + // un-read the byte before exiting + inputUTF8--; + goto ExitFalse; + } + ch2 = (ch & 0x1F); + UTF8_LOAD_LOWPART(ch,ch2,inputUTF8); + + outputUTF16[ 0 ] = ch2; + + outputUTF16 += 1; + outputUTF16_size -= 1; + } + + iMaxChars -= 1; + iMaxBytes -= 2; + } + else + { + // un-read the byte before exiting + inputUTF8--; + goto ExitFalse; + } + break; + + case 0xE0: + if(iMaxBytes >= 3) + { + if(fJustMove) + { + inputUTF8 += 2; + } + else + { + if(outputUTF16_size < 1) + { + // un-read the byte before exiting + inputUTF8--; + goto ExitFalse; + } + ch2 = (ch & 0x0F); + UTF8_LOAD_LOWPART(ch,ch2,inputUTF8); + UTF8_LOAD_LOWPART(ch,ch2,inputUTF8); + + outputUTF16[ 0 ] = ch2; + + outputUTF16 += 1; + outputUTF16_size -= 1; + } + + iMaxChars -= 1; + iMaxBytes -= 3; + } + else + { + // un-read the byte before exiting + inputUTF8--; + goto ExitFalse; + } + break; + + case 0xF0: + if((ch & 0xFF) >= 0xF5) { inputUTF8--; goto ExitFalse; } // restricted by RFC 3629 + + if(iMaxBytes >= 4) + { + if(fJustMove) + { + inputUTF8 += 3; + } + else + { + if(outputUTF16_size < 2) + { + // un-read the byte before exiting + inputUTF8--; + goto ExitFalse; + } + + ch2 = (ch & 0x07); + UTF8_LOAD_LOWPART(ch,ch2,inputUTF8); + UTF8_LOAD_LOWPART(ch,ch2,inputUTF8); + UTF8_LOAD_LOWPART(ch,ch2,inputUTF8); + + outputUTF16[ 0 ] = (ch2 >> SURROGATE_HALFSHIFT) + HIGH_SURROGATE_START; + outputUTF16[ 1 ] = (ch2 & SURROGATE_HALFMASK ) + LOW_SURROGATE_START ; + + outputUTF16 += 2; + outputUTF16_size -= 2; + } + + iMaxChars -= 2; + iMaxBytes -= 4; + } + else + { + // un-read the byte before exiting + inputUTF8--; + goto ExitFalse; + } + break; + } + } + + if(fJustMove == false) + { + if(outputUTF16_size < 1) goto ExitFalse; + + outputUTF16[ 0 ] = 0; + } + + res = true; + goto Exit; + +ExitFalse: + res = false; + +Exit: + m_inputUTF8 = inputUTF8; + m_outputUTF16 = outputUTF16; + m_outputUTF16_size = outputUTF16_size; + + return res; +} + +bool CLR_RT_UnicodeHelper::ConvertToUTF8( int iMaxChars, bool fJustMove ) +{ + NATIVE_PROFILE_CLR_CORE(); + const CLR_UINT16* inputUTF16 = m_inputUTF16; + CLR_UINT8* outputUTF8 = m_outputUTF8; + int outputUTF8_size = m_outputUTF8_size; + CLR_UINT32 ch; + bool res; + + while(iMaxChars > 0) + { + ch = (CLR_UINT32)*inputUTF16++; + + if(ch < 0x0080) + { + if(ch == 0) + { + break; + } + + if(fJustMove == false) + { + if(outputUTF8_size < 1) goto ExitFalse; + + outputUTF8[ 0 ] = ch; + + outputUTF8 += 1; + outputUTF8_size -= 1; + } + + iMaxChars -= 1; + } + else if(ch < 0x0800) + { + if(fJustMove == false) + { + if(outputUTF8_size < 2) goto ExitFalse; + + outputUTF8[ 1 ] = 0x80 | (ch & 0x3F); ch >>= 6; + outputUTF8[ 0 ] = 0xC0 | (ch & 0x1F); + + outputUTF8 += 2; + outputUTF8_size -= 2; + } + + iMaxChars -= 1; + } + else if(ch >= HIGH_SURROGATE_START && ch <= HIGH_SURROGATE_END) + { + ch = SURROGATE_HALFBASE + ((ch - HIGH_SURROGATE_START) << SURROGATE_HALFSHIFT) + (*inputUTF16++ - LOW_SURROGATE_START); + + if(fJustMove == false) + { + if(outputUTF8_size < 4) goto ExitFalse; + + outputUTF8[ 3 ] = 0x80 | (ch & 0x3F); ch >>= 6; + outputUTF8[ 2 ] = 0x80 | (ch & 0x3F); ch >>= 6; + outputUTF8[ 1 ] = 0x80 | (ch & 0x3F); ch >>= 6; + outputUTF8[ 0 ] = 0xF0 | (ch & 0x07); + + outputUTF8 += 4; + outputUTF8_size -= 4; + } + + iMaxChars -= 2; + } + else + { + if(fJustMove == false) + { + if(outputUTF8_size < 3) goto ExitFalse; + + outputUTF8[ 2 ] = 0x80 | (ch & 0x3F); ch >>= 6; + outputUTF8[ 1 ] = 0x80 | (ch & 0x3F); ch >>= 6; + outputUTF8[ 0 ] = 0xE0 | (ch & 0x0F); + + outputUTF8 += 3; + outputUTF8_size -= 3; + } + + iMaxChars -= 1; + } + } + + if(fJustMove == false) + { + if(outputUTF8_size < 1) goto ExitFalse; + + outputUTF8[ 0 ] = 0; + } + + res = true; + goto Exit; + +ExitFalse: + res = false; + +Exit: + m_inputUTF16 = inputUTF16; + m_outputUTF8 = outputUTF8; + m_outputUTF8_size = outputUTF8_size; + + return res; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(_WIN32) + +void CLR_RT_UnicodeHelper::ConvertToUTF8( const std::wstring& src , + std::string& dst ) +{ + if(src.size()) + { + LPSTR szBuf; + int iSize; + + iSize = ::WideCharToMultiByte( CP_UTF8, 0, src.c_str(), -1, NULL, 0, NULL, NULL ); + + if(iSize > 0) + { + szBuf = new CHAR[ iSize ]; + + iSize = ::WideCharToMultiByte( CP_UTF8, 0, src.c_str(), -1, szBuf, iSize, NULL, NULL ); + if(iSize > 0) + { + dst = szBuf; + } + + delete [] szBuf; + } + } + else + { + dst.erase(); + } +} + +void CLR_RT_UnicodeHelper::ConvertFromUTF8( const std::string& src , + std::wstring& dst ) +{ + if(src.size()) + { + LPWSTR szBuf; + int iSize; + + iSize = ::MultiByteToWideChar( CP_UTF8, 0, src.c_str(), -1, NULL, 0 ); + + if(iSize > 0) + { + szBuf = new WCHAR[ iSize ]; + + iSize = ::MultiByteToWideChar( CP_UTF8, 0, src.c_str(), -1, szBuf, iSize ); + if(iSize > 0) + { + dst = szBuf; + } + + delete [] szBuf; + } + } + else + { + dst.erase(); + } +} + + +#endif + +UnicodeString::UnicodeString() +{ + m_wCharArray = NULL; + m_length = 0; +} + +UnicodeString::~UnicodeString() +{ + Release(); +} + +HRESULT UnicodeString::Assign( LPCSTR string ) +{ + NATIVE_PROFILE_CLR_IO(); + TINYCLR_HEADER(); + + int byteLength = 0; + + /// Before we start assigning remove existing stuff. + Release(); + + m_unicodeHelper.SetInputUTF8( string ); + + m_length = m_unicodeHelper.CountNumberOfCharacters(); + + if(m_length < 0) TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + /// We have m_length >=0 now. + + byteLength = (m_length + 1) * sizeof (CLR_UINT16); + + m_wCharArray = (CLR_UINT16 *)CLR_RT_Memory::Allocate( byteLength ); CHECK_ALLOCATION(m_wCharArray); + + m_unicodeHelper.m_outputUTF16 = m_wCharArray; + m_unicodeHelper.m_outputUTF16_size = m_length + 1; + + m_unicodeHelper.ConvertFromUTF8( m_length , false ); + + /// Note m_length > 0 already (see above), hence m_length >= 0 or a valid index. + m_wCharArray[ m_length ] = 0; + + TINYCLR_NOCLEANUP(); +} + +void UnicodeString::Release() +{ + if (m_wCharArray != NULL) + { + CLR_RT_Memory::Release( m_wCharArray ); + } + + m_wCharArray = NULL; +} + diff --git a/src/CLR/Core/Cache.cpp b/src/CLR/Core/Cache.cpp new file mode 100644 index 0000000000..feb17055f7 --- /dev/null +++ b/src/CLR/Core/Cache.cpp @@ -0,0 +1,591 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(TINYCLR_USE_AVLTREE_FOR_METHODLOOKUP) + +int CLR_RT_EventCache::LookupEntry::Callback_Compare( void* state, CLR_RT_AVLTree::Entry* left, CLR_RT_AVLTree::Entry* right ) +{ + NATIVE_PROFILE_CLR_CORE(); + + LookupEntry* leftDirect = (LookupEntry*)left; + LookupEntry* rightDirect = (LookupEntry*)right; + + return leftDirect->m_payload.Compare( rightDirect->m_payload ); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_EventCache::VirtualMethodTable::Initialize() +{ + NATIVE_PROFILE_CLR_CORE(); + + m_entries = (Payload*)&g_scratchVirtualMethodPayload[ 0 ]; + + LookupEntry* node; + size_t i; + + m_tree.Initialize(); + + + m_list_freeItems.DblLinkedList_Initialize(); + m_list_inUse .DblLinkedList_Initialize(); + + m_tree.m_owner.m_ftn_compare = LookupEntry ::Callback_Compare; + m_tree.m_owner.m_ftn_newNode = VirtualMethodTable::Callback_NewNode; + m_tree.m_owner.m_ftn_freeNode = VirtualMethodTable::Callback_FreeNode; + m_tree.m_owner.m_ftn_reassignNode = VirtualMethodTable::Callback_Reassign; + m_tree.m_owner.m_state = this; + + + for(i=0, node=m_entries; iGenericNode_Initialize(); + + m_list_freeItems.LinkAtBack( node ); + } +} + +bool CLR_RT_EventCache::VirtualMethodTable::FindVirtualMethod( const CLR_RT_TypeDef_Index& cls, const CLR_RT_MethodDef_Index& mdVirtual, CLR_RT_MethodDef_Index& md ) +{ + NATIVE_PROFILE_CLR_CORE(); + LookupEntry* en; + LookupEntry key; + CLR_RT_MethodDef_Instance instMD; + CLR_RT_TypeDef_Instance instCLS; + + instMD .InitializeFromIndex ( mdVirtual ); + instCLS.InitializeFromMethod( instMD ); + + // + // Shortcut for terminal virtual methods. + // + if(cls.m_data == instCLS.m_data) + { + if((instMD.m_target->flags & CLR_RECORD_METHODDEF::MD_Abstract) == 0) + { + md = mdVirtual; + + return true; + } + } + + key.m_payload.m_mdVirtual = mdVirtual; + key.m_payload.m_cls = cls; + key.m_payload.m_md.Clear(); + + en = (LookupEntry*)m_tree.Find( &key ); + if(en) + { + md = en->m_payload.m_md; + + // + // Move the node to the top of the MRU list. + // + m_list_inUse.LinkAtFront( en ); + + return true; + } + + { + if(g_CLR_RT_TypeSystem.FindVirtualMethodDef( cls, mdVirtual, md ) == false) + { + return false; + } + } + + { + if(m_list_freeItems.IsEmpty()) + { + en = (LookupEntry*)m_list_inUse.LastNode(); + if(en->Prev() == NULL) + { + // + // No node to steal, return. + // + return true; + } + + m_tree.Remove( en ); + + CLR_PROF_Handler::SuspendTime(); + if(!ConsistencyCheck()) + { + DumpTree(); + } + CLR_PROF_Handler::ResumeTime(); + } + + key.m_payload.m_md = md; + m_tree.Insert( &key ); + + CLR_PROF_Handler::SuspendTime(); + if(!ConsistencyCheck()) + { + DumpTree(); + } + CLR_PROF_Handler::ResumeTime(); + } + + return true; +} + +//--// + +CLR_RT_AVLTree::Entry* CLR_RT_EventCache::VirtualMethodTable::Callback_NewNode( void* state, CLR_RT_AVLTree::Entry* payload ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_EventCache::VirtualMethodTable* pThis = (CLR_RT_EventCache::VirtualMethodTable*)state; + LookupEntry* payloadDirect = (LookupEntry*)payload; + LookupEntry* en; + + en = (LookupEntry*)pThis->m_list_freeItems.ExtractFirstNode(); + if(en) + { + en->m_payload = payloadDirect->m_payload; + + pThis->m_list_inUse.LinkAtFront( en ); + } + + return en; +} + +void CLR_RT_EventCache::VirtualMethodTable::Callback_FreeNode( void* state, CLR_RT_AVLTree::Entry* node ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_EventCache::VirtualMethodTable* pThis = (CLR_RT_EventCache::VirtualMethodTable*)state; + LookupEntry* nodeDirect = (LookupEntry*)node; + + pThis->m_list_freeItems.LinkAtBack( nodeDirect ); +} + +void CLR_RT_EventCache::VirtualMethodTable::Callback_Reassign( void* state, CLR_RT_AVLTree::Entry* from, CLR_RT_AVLTree::Entry* to ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_EventCache::VirtualMethodTable* pThis = (CLR_RT_EventCache::VirtualMethodTable*)state; + LookupEntry* fromDirect = (LookupEntry*)from; + LookupEntry* toDirect = (LookupEntry*)to; + + pThis->m_list_inUse.InsertAfterNode( fromDirect, toDirect ); + + toDirect->m_payload = fromDirect->m_payload; +} + +#else + +void CLR_RT_EventCache::VirtualMethodTable::Initialize() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_UINT32 idx; + + m_entries = (Link*) &g_scratchVirtualMethodTableLink [ 0 ]; + m_entriesMRU = (Link*) &g_scratchVirtualMethodTableLinkMRU[ 0 ]; + m_payloads = (Payload*)&g_scratchVirtualMethodPayload [ 0 ]; + + // + // Link all the entries to themselves => no elements in the lists. + // + for(idx = 0; idx < LinkArraySize(); idx++) + { + Link& lnk = m_entries[ idx ]; + + lnk.m_next = idx; + lnk.m_prev = idx; + } + + // + // Link all the entries to the following one => all the elements are in the MRU list. + // + _ASSERTE(LinkMRUArraySize() < 0xFFFF); + for(idx = 0; idx < LinkMRUArraySize(); idx++) + { + Link& lnk = m_entriesMRU[ idx ]; + + lnk.m_next = idx == LinkMRUArraySize() - 1 ? 0 : idx + 1; + lnk.m_prev = idx == 0 ? (CLR_UINT16)LinkMRUArraySize() - 1 : idx - 1; + } +} + +bool CLR_RT_EventCache::VirtualMethodTable::FindVirtualMethod( const CLR_RT_TypeDef_Index& cls, const CLR_RT_MethodDef_Index& mdVirtual, CLR_RT_MethodDef_Index& md ) +{ + NATIVE_PROFILE_CLR_CORE(); + Payload::Key key; + CLR_UINT32 idx; + CLR_UINT32 idxHead; + CLR_UINT32 clsData = cls .m_data; + CLR_UINT32 mdVirtualData = mdVirtual.m_data; + +#if defined(_WIN32) + bool fVerify = false; + + { + CLR_RT_MethodDef_Instance instMD; + CLR_RT_TypeDef_Instance instCLS; + + instMD .InitializeFromIndex ( mdVirtual ); + instCLS.InitializeFromMethod( instMD ); + + // + // Shortcut for terminal virtual methods. + // + if(clsData == instCLS.m_data) + { + if((instMD.m_target->flags & CLR_RECORD_METHODDEF::MD_Abstract) == 0) + { + md = mdVirtual; + + fVerify = true; + } + } + } +#endif + + if(cls.Assembly() == mdVirtual.Assembly()) + { + CLR_RT_Assembly* assm = g_CLR_RT_TypeSystem.m_assemblies [ mdVirtual.Assembly()-1 ]; + CLR_IDX owner = assm->m_pCrossReference_MethodDef[ mdVirtual.Method() ].GetOwner(); + + if(cls.Type() == owner) + { +#if defined(_WIN32) + if(fVerify != true) + { + CLR_Debug::Printf( "INTERNAL ERROR: Shortcut for terminal virtual methods failed: CLS:%08x:%08x => %08x\r\n", cls.m_data, mdVirtual.m_data, md.m_data ); + ::DebugBreak(); + } +#endif + + md = mdVirtual; + + return true; + } + } + +#if defined(_WIN32) + if(fVerify != false) + { + CLR_Debug::Printf( "INTERNAL ERROR: Shortcut for terminal virtual methods failed: CLS:%08x:%08x\r\n", cls.m_data, mdVirtual.m_data ); + ::DebugBreak(); + } +#endif + + + key.m_mdVirtual.m_data = mdVirtualData; + key.m_cls .m_data = clsData; + + idxHead = (SUPPORT_ComputeCRC( &key, sizeof(key), 0 ) % (LinkArraySize() - PayloadArraySize())) + PayloadArraySize(); + + for(idx = m_entries[ idxHead ].m_next; ; idx = m_entries[ idx ].m_next) + { + if(idx != idxHead) + { + Payload& res = m_payloads[ idx ]; + + if(res.m_key.m_mdVirtual.m_data != mdVirtualData) continue; + if(res.m_key.m_cls .m_data != clsData ) continue; + + md = res.m_md; + + break; + } + else + { + if(g_CLR_RT_TypeSystem.FindVirtualMethodDef( cls, mdVirtual, md ) == false) return false; + + idx = GetNewEntry(); + + Payload& res = m_payloads[ idx ]; + + res.m_md = md; + res.m_key = key; + + break; + } + } + + MoveEntryToTop( m_entries , idxHead , idx ); + MoveEntryToTop( m_entriesMRU, LinkMRUArraySize() - 1, idx ); + + return true; +} + +void CLR_RT_EventCache::VirtualMethodTable::MoveEntryToTop( Link* entries, CLR_UINT32 slot, CLR_UINT32 idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + Link& list = entries[ slot ]; + + if(list.m_next != idx) + { + Link& node = entries[ idx ]; + CLR_UINT32 next; + CLR_UINT32 prev; + + // + // Unlink. + // + next = node.m_next; + prev = node.m_prev; + + entries[ next ].m_prev = prev; + entries[ prev ].m_next = next; + + // + // Insert. + // + next = list.m_next; + + node.m_next = next; + node.m_prev = slot; + + list .m_next = idx; + entries[ next ].m_prev = idx; + } +} + +#endif // #if defined(TINYCLR_USE_AVLTREE_FOR_METHODLOOKUP) + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_EventCache::EventCache_Initialize() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_CLEAR(*this); + + m_events = (BoundedList*)&m_scratch[ 0 ]; + + BoundedList* lst = m_events; + size_t num = c_maxFastLists; + + while(num--) + { + lst->m_blocks.DblLinkedList_Initialize(); + + lst++; + } + + m_lookup_VirtualMethod.Initialize(); + +#ifndef TINYCLR_NO_IL_INLINE + m_inlineBufferStart = (CLR_RT_InlineBuffer*)g_scratchInlineBuffer; + + num = InlineBufferCount()-1; + + for(int i=0; i<(int)num; i++) + { + m_inlineBufferStart[i].m_pNext = &m_inlineBufferStart[i+1]; + } + m_inlineBufferStart[num].m_pNext = NULL; +#endif +} + +CLR_UINT32 CLR_RT_EventCache::EventCache_Cleanup() +{ + NATIVE_PROFILE_CLR_CORE(); + BoundedList* lst = m_events; + size_t num = c_maxFastLists; + CLR_UINT32 tot = 0; + + while(num--) + { + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_Node,ptr,lst->m_blocks) + { + ptr->SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_FREEBLOCK, CLR_RT_HeapBlock::HB_Pinned, ptr->DataSize()) ); + ptr->ClearData(); + + tot += ptr->DataSize(); + } + TINYCLR_FOREACH_NODE_END(); + + lst->m_blocks.DblLinkedList_Initialize(); + + lst++; + } + + return tot; +} + +//--// + +void CLR_RT_EventCache::Append_Node( CLR_RT_HeapBlock* node ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock_Node* ptr = (CLR_RT_HeapBlock_Node*)node; + CLR_UINT32 blocks = ptr->DataSize(); + BoundedList& lst = m_events[blocks < c_maxFastLists ? blocks : 0]; + + ptr->ChangeDataType ( DATATYPE_CACHEDBLOCK ); + ptr->ChangeDataFlags( CLR_RT_HeapBlock::HB_Alive | CLR_RT_HeapBlock::HB_Event ); + + TINYCLR_CHECK_EARLY_COLLECTION(ptr); + + ptr->Debug_ClearBlock( 0xAB ); + + lst.m_blocks.LinkAtBack( ptr ); + +#if defined(TINYCLR_PROFILE_NEW_ALLOCATIONS) + g_CLR_PRF_Profiler.TrackObjectDeletion(node); +#endif +} + +CLR_RT_HeapBlock* CLR_RT_EventCache::Extract_Node_Slow( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 blocks ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock_Node* ptr; + CLR_RT_HeapBlock_Node* best = NULL; + CLR_UINT32 bestSize = 0; + + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_Node,ptr,m_events[ 0 ].m_blocks) + { + CLR_UINT32 size = ptr->DataSize(); + + if(size == blocks) + { + best = ptr; + bestSize = blocks; + break; + } + + if(size >= blocks) + { + if(( best && (size < bestSize )) || + (!best && (size <= (blocks * 20) / 16)) ) // Accept a maximum overhead of 25%. + { + best = ptr; + bestSize = size; + } + } + } + TINYCLR_FOREACH_NODE_END(); + + ptr = best; + + if(ptr) + { + // + // Did we select a block bigger than requested? Requeue the tail. + // + if(bestSize > blocks) + { + CLR_RT_HeapBlock_Node* next = &ptr[ blocks ]; + + ptr->SetDataId ( CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_CACHEDBLOCK,CLR_RT_HeapBlock::HB_Alive | CLR_RT_HeapBlock::HB_Event, blocks) ); + next->SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_CACHEDBLOCK,CLR_RT_HeapBlock::HB_Alive | CLR_RT_HeapBlock::HB_Event,bestSize - blocks) ); + next->ClearData(); + + Append_Node( next ); + } + + ptr->Unlink(); + + ptr->ChangeDataType ( dataType ); + ptr->ChangeDataFlags( CLR_RT_HeapBlock::HB_Alive | CLR_RT_HeapBlock::HB_Event ); + + if(flags & CLR_RT_HeapBlock::HB_InitializeToZero) + { + ptr->InitializeToZero(); + } + else + { + ptr->Debug_ClearBlock( 0xAD ); + } + +#if defined(TINYCLR_PROFILE_NEW_ALLOCATIONS) + g_CLR_PRF_Profiler.TrackObjectCreation( ptr ); +#endif + + return ptr; + } + + return g_CLR_RT_ExecutionEngine.ExtractHeapBlocksForEvents( dataType, flags, blocks ); +} + +CLR_RT_HeapBlock* CLR_RT_EventCache::Extract_Node_Fast( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 blocks ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock_Node* ptr = m_events[ blocks ].m_blocks.FirstNode(); + + if(ptr->Next()) + { + ptr->Unlink(); + + ptr->ChangeDataType ( dataType ); + ptr->ChangeDataFlags( CLR_RT_HeapBlock::HB_Alive | CLR_RT_HeapBlock::HB_Event ); + + if(flags & CLR_RT_HeapBlock::HB_InitializeToZero) + { + ptr->InitializeToZero(); + } + else + { + ptr->Debug_ClearBlock( 0xAD ); + } + +#if defined(TINYCLR_PROFILE_NEW_ALLOCATIONS) + g_CLR_PRF_Profiler.TrackObjectCreation( ptr ); +#endif + + return ptr; + } + + return g_CLR_RT_ExecutionEngine.ExtractHeapBlocksForEvents( dataType, flags, blocks ); +} + +CLR_RT_HeapBlock* CLR_RT_EventCache::Extract_Node_Bytes( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 bytes ) +{ + NATIVE_PROFILE_CLR_CORE(); + return Extract_Node( dataType, flags, CONVERTFROMSIZETOHEAPBLOCKS(bytes) ); +} + +CLR_RT_HeapBlock* CLR_RT_EventCache::Extract_Node( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 blocks ) +{ + NATIVE_PROFILE_CLR_CORE(); +#if defined(TINYCLR_FORCE_GC_BEFORE_EVERY_ALLOCATION) + return g_CLR_RT_ExecutionEngine.ExtractHeapBlocksForEvents( dataType, flags, blocks ); +#else + if(blocks > 0 && blocks < c_maxFastLists) return Extract_Node_Fast( dataType, flags, blocks ); + else return Extract_Node_Slow( dataType, flags, blocks ); +#endif +} + +//--// + +bool CLR_RT_EventCache::FindVirtualMethod( const CLR_RT_TypeDef_Index& cls, const CLR_RT_MethodDef_Index& mdVirtual, CLR_RT_MethodDef_Index& md ) +{ + NATIVE_PROFILE_CLR_CORE(); + return m_lookup_VirtualMethod.FindVirtualMethod( cls, mdVirtual, md ); +} + +// -- // + +#ifndef TINYCLR_NO_IL_INLINE +bool CLR_RT_EventCache::GetInlineFrameBuffer(CLR_RT_InlineBuffer** ppBuffer) +{ + if(m_inlineBufferStart != NULL) + { + *ppBuffer = m_inlineBufferStart; + + m_inlineBufferStart = m_inlineBufferStart->m_pNext; + + return true; + } + + *ppBuffer = NULL; + + return false; +} + +bool CLR_RT_EventCache::FreeInlineBuffer(CLR_RT_InlineBuffer* pBuffer) +{ + pBuffer->m_pNext = m_inlineBufferStart; + m_inlineBufferStart = pBuffer; + return true; +} +#endif + +//////////////////////////////////////////////////////////////////////////////// + diff --git a/src/CLR/Core/Checks.cpp b/src/CLR/Core/Checks.cpp new file mode 100644 index 0000000000..4023906875 --- /dev/null +++ b/src/CLR/Core/Checks.cpp @@ -0,0 +1,79 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_Checks::VerifyObject( CLR_RT_HeapBlock& top ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + switch(top.DataType()) + { + case DATATYPE_OBJECT: + case DATATYPE_BYREF: + if(top.Dereference() != NULL) TINYCLR_SET_AND_LEAVE(S_OK); + break; + + case DATATYPE_ARRAY_BYREF: + if(top.DereferenceArray() != NULL) TINYCLR_SET_AND_LEAVE(S_OK); + break; + + default: + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + TINYCLR_SET_AND_LEAVE(CLR_E_NULL_REFERENCE); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_Checks::VerifyArrayReference( CLR_RT_HeapBlock& ref ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock_Array* array; + + if(ref.DataType() != DATATYPE_OBJECT) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + array = ref.DereferenceArray(); + if(array == NULL) + { + TINYCLR_SET_AND_LEAVE(CLR_E_NULL_REFERENCE); + } + + if(array->DataType() != DATATYPE_SZARRAY) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_Checks::VerifyUnknownInstruction( CLR_OPCODE op ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(CLR_E_UNKNOWN_INSTRUCTION); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_Checks::VerifyUnsupportedInstruction( CLR_OPCODE op ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(CLR_E_UNSUPPORTED_INSTRUCTION); + + TINYCLR_NOCLEANUP(); +} diff --git a/src/CLR/Core/Core.cpp b/src/CLR/Core/Core.cpp new file mode 100644 index 0000000000..f97bd2f4ce --- /dev/null +++ b/src/CLR/Core/Core.cpp @@ -0,0 +1,90 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +CLR_UINT32 g_buildCRC; + +CLR_RT_ExecutionEngine g_CLR_RT_ExecutionEngine; +CLR_RT_WellKnownTypes g_CLR_RT_WellKnownTypes; +CLR_RT_WellKnownMethods g_CLR_RT_WellKnownMethods; +CLR_RT_TypeSystem g_CLR_RT_TypeSystem; +CLR_RT_EventCache g_CLR_RT_EventCache; +CLR_RT_GarbageCollector g_CLR_RT_GarbageCollector; +CLR_HW_Hardware g_CLR_HW_Hardware; + +//const CLR_RADIAN c_CLR_radians[] = +//{ +// { 1000, -0 }, +// { 995, 105 }, +// { 978, 208 }, +// { 951, 309 }, +// { 914, 407 }, +// { 866, 500 }, +// { 809, 588 }, +// { 743, 669 }, +// { 669, 743 }, +// { 588, 809 }, +// { 500, 866 }, +// { 407, 914 }, +// { 309, 951 }, +// { 208, 978 }, +// { 105, 995 }, +// { 0, 1000 }, +// { -105, 995 }, +// { -208, 978 }, +// { -309, 951 }, +// { -407, 914 }, +// { -500, 866 }, +// { -588, 809 }, +// { -669, 743 }, +// { -743, 669 }, +// { -809, 588 }, +// { -866, 500 }, +// { -914, 407 }, +// { -951, 309 }, +// { -978, 208 }, +// { -995, 105 }, +// { -1000, 0 }, +// { -995, -105 }, +// { -978, -208 }, +// { -951, -309 }, +// { -914, -407 }, +// { -866, -500 }, +// { -809, -588 }, +// { -743, -669 }, +// { -669, -743 }, +// { -588, -809 }, +// { -500, -866 }, +// { -407, -914 }, +// { -309, -951 }, +// { -208, -978 }, +// { -105, -995 }, +// { 0, -1000 }, +// { 105, -995 }, +// { 208, -978 }, +// { 309, -951 }, +// { 407, -914 }, +// { 500, -866 }, +// { 588, -809 }, +// { 669, -743 }, +// { 743, -669 }, +// { 809, -588 }, +// { 866, -500 }, +// { 914, -407 }, +// { 951, -309 }, +// { 978, -208 }, +// { 995, -105 }, +//}; + +// UNDONE: FIXME: the Arm 3.0 compiler drags in a bunch of ABI methods (for initialization) if struct arrays are not initialized +CLR_UINT32 g_scratchDebugger [ sizeof(CLR_DBG_Debugger) * NUM_DEBUGGERS / sizeof(UINT32) + 1 ]; +CLR_UINT32 g_scratchDebuggerMessaging[ sizeof(CLR_Messaging) * NUM_DEBUGGERS / sizeof(UINT32) + 1 ]; +CLR_DBG_Debugger *g_CLR_DBG_Debuggers; + +CLR_RT_Persistence_Manager g_CLR_RT_Persistence_Manager; + +//--// + diff --git a/src/CLR/Core/Core.h b/src/CLR/Core/Core.h new file mode 100644 index 0000000000..33d0d58b47 --- /dev/null +++ b/src/CLR/Core/Core.h @@ -0,0 +1,29 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _TINYCLR_CORE_H_ +#define _TINYCLR_CORE_H_ + +#include +#include +//#include +//#include +#include +//#include +//#include +//#include +//#if defined(CLR_COMPONENTIZATION_USE_HANDLER) +//#include +//#endif +// +//#include +// +#include +//#include +//#include + +#include + +#endif // _TINYCLR_CORE_H_ diff --git a/src/CLR/Core/Core.vcxproj b/src/CLR/Core/Core.vcxproj new file mode 100644 index 0000000000..2bd2adffea --- /dev/null +++ b/src/CLR/Core/Core.vcxproj @@ -0,0 +1,212 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1} + Win32Proj + Core + 10.0.14393.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(IntDir) + $(BinDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\Include;..\CorLib + + + Windows + + + + + Use + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + Level3 + Use + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/src/CLR/Core/Core.vcxproj.filters b/src/CLR/Core/Core.vcxproj.filters new file mode 100644 index 0000000000..aa22aebe5f --- /dev/null +++ b/src/CLR/Core/Core.vcxproj.filters @@ -0,0 +1,203 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Header Files + + + \ No newline at end of file diff --git a/src/CLR/Core/Execution.cpp b/src/CLR/Core/Execution.cpp new file mode 100644 index 0000000000..6a37828d40 --- /dev/null +++ b/src/CLR/Core/Execution.cpp @@ -0,0 +1,3612 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +static const CLR_INT64 c_MaximumTimeToActive = (TIME_CONVERSION__ONEMINUTE * TIME_CONVERSION__TO_SECONDS); + + +//--// + +CLR_RT_ExecutionEngine::ExecutionConstraintCompensation CLR_RT_ExecutionEngine::s_compensation = { 0, 0, 0 }; + +//--// + +HRESULT CLR_RT_ExecutionEngine::CreateInstance() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_CLEAR(g_CLR_RT_ExecutionEngine); + + TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.ExecutionEngine_Initialize()); + + TINYCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_ExecutionEngine::ExecutionEngine_Initialize() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + m_maximumTimeToActive = c_MaximumTimeToActive; // CLR_INT64 m_maximumTimeToActive + // int m_iDebugger_Conditions; + // + // CLR_INT64 m_currentMachineTime; + // CLR_INT64 m_currentLocalTime; + m_lastTimeZoneOffset = Time_GetTimeZoneOffset();// CLR_INT32 m_lastTimeZoneOffset; + + // CLR_INT64 m_currentNextActivityTime; + m_timerCache = false; // bool m_timerCache; + // CLR_INT64 m_timerCacheNextTimeout; + // + m_heap .DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_heap; + // CLR_RT_HeapCluster* m_lastHcUsed; + m_heapState = c_HeapState_Normal; // int m_heapState; + // + m_weakReferences.DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_weakReferences; + // + m_timers .DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_timers; + m_raisedEvents = 0; // CLR_UINT32 m_raisedEvents; + // + m_threadsReady .DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_threadsReady; + m_threadsWaiting.DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_threadsWaiting; + m_threadsZombie .DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_threadsZombie; + // int m_lastPid; + // + m_finalizersAlive .DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_finalizersAlive; + m_finalizersPending.DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_finalizersPending; + // CLR_RT_Thread* m_finalizerThread; + // CLR_RT_Thread* m_cctorThread; + // +#if !defined(TINYCLR_APPDOMAINS) + m_globalLock = NULL; // CLR_RT_HeapBlock* m_globalLock; + m_outOfMemoryException = NULL; // CLR_RT_HeapBlock* m_outOfMemoryException; +#endif // + + m_currentUICulture = NULL; // CLR_RT_HeapBlock* m_currentUICulture; + +#if defined(CLR_COMPONENTIZATION_USE_HANDLER) + Handler_Initialize(); +#else + CLR_RT_HeapBlock_EndPoint::HandlerMethod_Initialize(); + // UNDONE: FIXME: CLR_RT_HeapBlock_NativeEventDispatcher::HandlerMethod_Initialize(); + // UNDONE: FIXME: CLR_RT_HeapBlock_I2CXAction::HandlerMethod_Initialize(); + +#endif + + m_interruptThread = NULL; // CLR_RT_Thread m_interruptThread; + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + m_scratchPadArray = NULL; // CLR_RT_HeapBlock_Array* m_scratchPadArray; +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + +#if defined(TINYCLR_APPDOMAINS) + m_appDomains.DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_appDomains; + + m_appDomainCurrent = NULL; // CLR_AppDomainCurrent* m_appDomainCurrent; + m_appDomainIdNext = c_AppDomainId_Invalid + 1; // int m_appDomainIdNext; +#endif + + m_currentThread = NULL; + + m_GlobalExecutionCounter = 0; + +#if !defined(BUILD_RTM) + m_fShuttingDown = false; //bool m_fShuttingDown; +#endif + + //--// + + TINYCLR_CHECK_HRESULT(AllocateHeaps()); + + g_CLR_RT_TypeSystem.TypeSystem_Initialize(); + g_CLR_RT_EventCache.EventCache_Initialize(); + + //--// + + TINYCLR_CHECK_HRESULT(CLR_HW_Hardware::CreateInstance()); + + //--// + + TINYCLR_CHECK_HRESULT(CLR_Messaging::CreateInstance()); + + TINYCLR_CHECK_HRESULT(CLR_DBG_Debugger::CreateInstance()); + +#if defined(TINYCLR_PROFILE_NEW) + TINYCLR_CHECK_HRESULT(CLR_PRF_Profiler::CreateInstance()); +#endif + +#if defined(TINYCLR_APPDOMAINS) + TINYCLR_CHECK_HRESULT(CLR_RT_AppDomain::CreateInstance( "default", m_appDomainCurrent )); +#endif + + UpdateTime(); + + m_startTime = Time_GetUtcTime(); + + CLR_RT_HeapBlock_WeakReference::RecoverObjects( m_heap ); + + //--// + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ExecutionEngine::AllocateHeaps() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + const CLR_UINT32 c_HeapClusterSize = sizeof(CLR_RT_HeapBlock) * CLR_RT_HeapBlock::HB_MaxSize; + + CLR_UINT8* heapFirstFree = s_CLR_RT_Heap.m_location; + CLR_UINT32 heapFree = s_CLR_RT_Heap.m_size; + CLR_INT32 i = 0; + CLR_UINT32 blockSize = 1; + + if(heapFree <= sizeof(CLR_RT_HeapCluster)) + { + TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + + while(heapFree > sizeof(CLR_RT_HeapCluster)) + { + CLR_RT_HeapCluster* hc = (CLR_RT_HeapCluster*) heapFirstFree; + CLR_UINT32 size = (heapFree < c_HeapClusterSize) ? heapFree : c_HeapClusterSize; + + /// + /// Speed up heap initialization for devices with very large heaps > 1MB + /// Exponentially increase the size of a default heap block + /// + if(i > 100*1024*1024) + { + blockSize = CLR_RT_HeapBlock::HB_MaxSize; + } + else if( i > 10*1024*1024) + { + blockSize = 10*1024; + } + else if(i > 1024*1024) + { + blockSize = 1*1024; + } + + hc->HeapCluster_Initialize( size, blockSize ); + + m_heap.LinkAtBack( hc ); + + heapFirstFree += size; + heapFree -= size; + i += size; + } + + TINYCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_ExecutionEngine::DeleteInstance() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + g_CLR_RT_ExecutionEngine.ExecutionEngine_Cleanup(); + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +void CLR_RT_ExecutionEngine::ExecutionEngine_Cleanup() +{ + NATIVE_PROFILE_CLR_CORE(); + m_fShuttingDown = true; + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + m_scratchPadArray = NULL; + m_breakpointsNum = 0; + + CLR_DBG_Debugger::DeleteInstance(); +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + +#if defined(TINYCLR_PROFILE_NEW) + CLR_PRF_Profiler::DeleteInstance(); +#endif + + CLR_Messaging::DeleteInstance(); + + CLR_HW_Hardware::DeleteInstance(); + + m_finalizersAlive .DblLinkedList_PushToCache(); + m_finalizersPending.DblLinkedList_PushToCache(); + m_finalizerThread = NULL; + m_cctorThread = NULL; + + m_timerThread = NULL; + + AbortAllThreads ( m_threadsReady ); + AbortAllThreads ( m_threadsWaiting ); + + ReleaseAllThreads( m_threadsReady ); + ReleaseAllThreads( m_threadsWaiting ); + ReleaseAllThreads( m_threadsZombie ); + + g_CLR_RT_TypeSystem.TypeSystem_Cleanup(); + g_CLR_RT_EventCache.EventCache_Cleanup(); + +#if !defined(TINYCLR_APPDOMAINS) + m_globalLock = NULL; +#endif + +#if defined(CLR_COMPONENTIZATION_USE_HANDLER) + Handler_CleanUp(); +#else + CLR_RT_HeapBlock_EndPoint::HandlerMethod_CleanUp(); + // UNDONE: FIXME: CLR_RT_HeapBlock_NativeEventDispatcher::HandlerMethod_CleanUp(); + // UNDONE: FIXME: CLR_RT_HeapBlock_I2CXAction::HandlerMethod_CleanUp(); +#endif + + m_interruptThread = NULL; + + m_heap.DblLinkedList_Initialize(); +} + +//--// + +HRESULT CLR_RT_ExecutionEngine::StartHardware() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(g_CLR_HW_Hardware.Hardware_Initialize()); + + TINYCLR_NOCLEANUP(); +} + +void CLR_RT_ExecutionEngine::Reboot( bool fHard ) +{ + NATIVE_PROFILE_CLR_CORE(); + + ::Watchdog_GetSetEnabled( FALSE, TRUE ); + + // UNDONE: FIXME: g_CLR_RT_Persistence_Manager.Flush(); + //g_CLR_RT_Persistence_Manager.m_state = CLR_RT_Persistence_Manager::STATE_FlushNextObject; + //g_CLR_RT_Persistence_Manager.m_pending_object = NULL; + //g_CLR_RT_Persistence_Manager.Flush(); + + if(fHard) + { + ::CPU_Reset(); + } + else + { + CLR_EE_REBOOT_SET(ClrOnly); + CLR_EE_DBG_SET(RebootPending); + } +} + +CLR_INT64 CLR_RT_ExecutionEngine::GetUptime() +{ + return Time_GetUtcTime() - g_CLR_RT_ExecutionEngine.m_startTime; +} + +void CLR_RT_ExecutionEngine::JoinAllThreadsAndExecuteFinalizer() +{ +} + +void CLR_RT_ExecutionEngine::LoadDownloadedAssemblies() +{ + NATIVE_PROFILE_CLR_CORE (); + PerformGarbageCollection(); + PerformHeapCompaction (); + + // + // Load any patch or similar! + // + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_WeakReference,weak,m_weakReferences) + { + if((weak->m_identity.m_flags & CLR_RT_HeapBlock_WeakReference::WR_ArrayOfBytes) != 0 && weak->m_targetSerialized) + { + CLR_RECORD_ASSEMBLY* header; + + header = (CLR_RECORD_ASSEMBLY*)weak->m_targetSerialized->GetFirstElement(); + + if(header->GoodAssembly()) + { + CLR_RT_Assembly* assm = NULL; + + if(SUCCEEDED(CLR_RT_Assembly::CreateInstance( header, assm ))) + { + assm->m_pFile = weak->m_targetSerialized; + + g_CLR_RT_TypeSystem.Link( assm ); + } + } + } + } + TINYCLR_FOREACH_NODE_END(); + + (void)g_CLR_RT_TypeSystem.ResolveAll(); + + TINYCLR_FOREACH_ASSEMBLY(g_CLR_RT_TypeSystem) + { + if(pASSM->m_pFile) + { + // + // For those assemblies that failed to load (missing dependency?), clean up. + // + if((pASSM->m_flags & CLR_RT_Assembly::c_ResolutionCompleted) == 0) + { + pASSM->m_pFile = NULL; + + pASSM->DestroyInstance(); + } + } + } + TINYCLR_FOREACH_ASSEMBLY_END(); + + g_CLR_RT_TypeSystem.PrepareForExecution(); +} + +//--// + +void CLR_RT_ExecutionEngine::ExecutionConstraint_Suspend() +{ + NATIVE_PROFILE_CLR_CORE(); + s_compensation.Suspend(); +} + +void CLR_RT_ExecutionEngine::ExecutionConstraint_Resume() +{ + NATIVE_PROFILE_CLR_CORE(); + s_compensation.Resume(); +} + +//--// + +CLR_UINT32 CLR_RT_ExecutionEngine::PerformGarbageCollection() +{ + NATIVE_PROFILE_CLR_CORE(); + m_heapState = c_HeapState_UnderGC; + + CLR_UINT32 freeMem = g_CLR_RT_GarbageCollector.ExecuteGarbageCollection(); + + m_heapState = c_HeapState_Normal; + + m_lastHcUsed = NULL; + +#if !defined(BUILD_RTM) || defined(_WIN32) + if(m_fPerformHeapCompaction) CLR_EE_SET( Compaction_Pending ); +#endif + + g_CLR_RT_ExecutionEngine.SpawnFinalizer(); + + return freeMem; +} + +void CLR_RT_ExecutionEngine::PerformHeapCompaction() +{ + NATIVE_PROFILE_CLR_CORE(); + if(CLR_EE_DBG_IS( NoCompaction )) return; + + g_CLR_RT_GarbageCollector.ExecuteCompaction(); + + CLR_EE_CLR( Compaction_Pending ); + + m_lastHcUsed = NULL; +} + +void CLR_RT_ExecutionEngine::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_scratchPadArray ); +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + +#if !defined(TINYCLR_APPDOMAINS) + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_globalLock ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_outOfMemoryException ); +#endif + + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_currentUICulture ); + + m_weakReferences.Relocate(); + + // UNDONE: FIXME: g_CLR_RT_Persistence_Manager.Relocate(); +} + +//--// + +#if defined(TINYCLR_APPDOMAINS) + +void CLR_RT_ExecutionEngine::TryToUnloadAppDomains_Helper_Threads( CLR_RT_DblLinkedList& threads ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_FOREACH_NODE(CLR_RT_Thread,th,threads) + { + if(th->m_flags & CLR_RT_Thread::TH_F_ContainsDoomedAppDomain) + { + TINYCLR_FOREACH_NODE(CLR_RT_StackFrame, stack, th->m_stackFrames) + { + stack->m_appDomain->m_fCanBeUnloaded = false; + } + TINYCLR_FOREACH_NODE_END(); + } + } + TINYCLR_FOREACH_NODE_END(); +} + +void CLR_RT_ExecutionEngine::TryToUnloadAppDomains_Helper_Finalizers( CLR_RT_DblLinkedList& finalizers, bool fAlive ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_Finalizer,fin,finalizers) + { + if(!fin->m_appDomain->IsLoaded()) + { + if(fAlive) + { + //When an AppDomain is being unloaded, all live finalizers are run, regardless + //of whether or not they are still reachable. + m_finalizersPending.LinkAtBack( fin ); + } + + fin->m_appDomain->m_fCanBeUnloaded = false; + } + } + TINYCLR_FOREACH_NODE_END(); +} + +bool CLR_RT_ExecutionEngine::TryToUnloadAppDomains() +{ + NATIVE_PROFILE_CLR_CORE(); + bool fAnyAppDomainsUnloaded = false; + + TINYCLR_FOREACH_NODE(CLR_RT_AppDomain,appDomain,m_appDomains) + { + appDomain->m_fCanBeUnloaded = true; + } + TINYCLR_FOREACH_NODE_END(); + + TryToUnloadAppDomains_Helper_Finalizers( m_finalizersAlive , true ); + TryToUnloadAppDomains_Helper_Finalizers( m_finalizersPending, false ); + + TryToUnloadAppDomains_Helper_Threads( m_threadsReady ); + TryToUnloadAppDomains_Helper_Threads( m_threadsWaiting ); + + CLR_EE_CLR( UnloadingAppDomain ); + + TINYCLR_FOREACH_NODE(CLR_RT_AppDomain,appDomain,m_appDomains) + { + if(appDomain->m_state == CLR_RT_AppDomain::AppDomainState_Unloading) + { + if(appDomain->m_fCanBeUnloaded) + { + appDomain->m_state = CLR_RT_AppDomain::AppDomainState_Unloaded; + appDomain->AppDomain_Uninitialize(); + fAnyAppDomainsUnloaded = true; + } + else + { + CLR_EE_SET(UnloadingAppDomain); + } + } + } + TINYCLR_FOREACH_NODE_END(); + + if(fAnyAppDomainsUnloaded) + { + SignalEvents( CLR_RT_ExecutionEngine::c_Event_AppDomain ); +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + Breakpoint_Assemblies_Loaded(); +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + } + + return fAnyAppDomainsUnloaded; +} + +#endif + +HRESULT CLR_RT_ExecutionEngine::WaitForDebugger() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + while(CLR_EE_DBG_IS(Stopped) && !CLR_EE_DBG_IS(RebootPending) && !CLR_EE_DBG_IS(ExitPending)) + { + // TODO: Generalize this as a standard HAL API +#if defined(WIN32) + if(HAL_Windows_IsShutdownPending()) + { + TINYCLR_SET_AND_LEAVE(CLR_E_SHUTTING_DOWN); + } +#endif + + DebuggerLoop(); + } + +#if defined(WIN32) + TINYCLR_NOCLEANUP(); +#else + TINYCLR_NOCLEANUP_NOLABEL(); +#endif +} + +#if defined(WIN32) +HRESULT CLR_RT_ExecutionEngine::CreateEntryPointArgs( CLR_RT_HeapBlock& argsBlk, WCHAR* szCommandLineArgs ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + std::list args; + + WCHAR* szArgNext = NULL; + WCHAR* szArg = szCommandLineArgs; + WCHAR* sep = L" "; + WCHAR* context = NULL; + + szArg = wcstok_s( szArg, sep, &context ); + + while(szArg != NULL) + { + std::wstring arg = szArg; + args.insert( args.end(), arg ); + + szArg = wcstok_s( NULL, sep, &context ); + } + + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( argsBlk, (CLR_UINT32)args.size(), g_CLR_RT_WellKnownTypes.m_String )); + + CLR_RT_HeapBlock_Array* array = argsBlk.Array(); + CLR_UINT32 iArg = 0; + + for(std::list::iterator it = args.begin(); it != args.end(); it++, iArg++) + { + std::string arg; + + CLR_RT_HeapBlock* blk = (CLR_RT_HeapBlock*)array->GetElement( iArg ); + CLR_RT_UnicodeHelper::ConvertToUTF8( (*it).c_str(), arg ); + + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( *blk, arg.c_str() )); + } + + TINYCLR_NOCLEANUP(); +} + +#endif + +HRESULT CLR_RT_ExecutionEngine::Execute( LPWSTR entryPointArgs, int maxContextSwitch ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock ref; + CLR_RT_Thread* thMain = NULL; + + + if(TINYCLR_INDEX_IS_INVALID(g_CLR_RT_TypeSystem.m_entryPoint)) + { +#if !defined(BUILD_RTM) || defined(WIN32) + CLR_Debug::Printf( "Cannot find any entrypoint!\r\n" ); +#endif + TINYCLR_SET_AND_LEAVE(CLR_E_ENTRYPOINT_NOT_FOUND); + } + + TINYCLR_CHECK_HRESULT(WaitForDebugger()); + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + CLR_EE_DBG_SET_MASK(State_ProgramRunning,State_Mask); +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Delegate::CreateInstance( ref, g_CLR_RT_TypeSystem.m_entryPoint, NULL )); + + { + CLR_RT_ProtectFromGC gc( ref ); + + TINYCLR_CHECK_HRESULT(NewThread( thMain, ref.DereferenceDelegate(), ThreadPriority::Normal, -1 )); + } + + { + CLR_RT_StackFrame* stack = thMain->CurrentFrame(); + + if(stack->m_call.m_target->numArgs > 0) + { + //Main entrypoint takes an optional String[] parameter. + //Set the arg to NULL, if that's the case. + +#if defined(WIN32) + if(entryPointArgs != NULL) + { + TINYCLR_CHECK_HRESULT(CreateEntryPointArgs( stack->m_arguments[ 0 ], entryPointArgs )); + } + else +#endif + { + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( stack->m_arguments[ 0 ], 0, g_CLR_RT_WellKnownTypes.m_String )); + } + } + } + + //To debug static constructors, the thread should be created after the entrypoint thread. + TINYCLR_CHECK_HRESULT(WaitForDebugger()); + + // m_cctorThread is NULL before call and inialized by the SpawnStaticConstructor + SpawnStaticConstructor( m_cctorThread ); + + + while(true) + { + HRESULT hr2 = ScheduleThreads( maxContextSwitch ); TINYCLR_CHECK_HRESULT(hr2); + + if(CLR_EE_DBG_IS( RebootPending ) || CLR_EE_DBG_IS( ExitPending ) || CLR_EE_REBOOT_IS(ClrOnly)) + { + TINYCLR_SET_AND_LEAVE(S_FALSE); + } + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + if(CLR_EE_DBG_IS( Stopped )) + { + CLR_RT_ExecutionEngine::ExecutionConstraint_Suspend(); + + TINYCLR_CHECK_HRESULT(WaitForDebugger()); + + CLR_RT_ExecutionEngine::ExecutionConstraint_Resume(); + } +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + if(CLR_EE_IS(Compaction_Pending)) + { + PerformHeapCompaction(); + _ASSERTE(FIMPLIES(CLR_EE_DBG_IS_NOT(NoCompaction), CLR_EE_IS_NOT(Compaction_Pending))); + } + + if(hr2 == CLR_S_NO_READY_THREADS) + { + WaitForActivity(); + } + else if(hr2 == CLR_S_QUANTUM_EXPIRED) + { +#if !defined(BUILD_RTM) || defined(WIN32) + if(m_fPerformGarbageCollection) + { +#if defined(TINYCLR_GC_VERBOSE) + if(s_CLR_RT_fTrace_GC >= c_CLR_RT_Trace_Info) + { + CLR_Debug::Printf( " Memory: Forcing GC.\r\n" ); + } +#endif + PerformGarbageCollection(); + +#if defined(TINYCLR_GC_VERBOSE) + if(s_CLR_RT_fTrace_Memory > c_CLR_RT_Trace_Info) + { + CLR_UINT32 inUse = g_CLR_RT_GarbageCollector.m_totalBytes - g_CLR_RT_GarbageCollector.m_freeBytes; + + CLR_Debug::Printf( " Memory: INUSE: %d\r\n", (int)inUse ); + } +#endif + } +#endif + } + else + { + break; + } + } + + TINYCLR_CLEANUP(); + +#if defined(TINYCLR_PROFILE_NEW) + /* g_CLR_RT_ExecutionEngine.Cleanup() gets called too late to flush things out on the emulator since it + * only gets called when the finalizer dealing with the managed half of the emulator runs. + */ + g_CLR_PRF_Profiler.Stream_Flush(); +#endif + + // UNDONE: FIXME: g_CLR_RT_Persistence_Manager.Flush(); + +#if defined(WIN32) +#if defined(TINYCLR_PROFILE_NEW) + if(CLR_EE_PRF_IS( Enabled )) + { + //Clients do not get all the messages they want if a program happens to end and the emulator terminates before + //the pipe can be read; furthermore the emulator must be able to persist until all required data is requested. + CLR_EE_DBG_SET(Stopped); + } +#endif + + //By skipping the whole CLRStartup routine, the Monitor_Program_Exit message never gets sent to clients. + CLR_EE_DBG_EVENT_BROADCAST(CLR_DBG_Commands::c_Monitor_ProgramExit,0,NULL,WP_Flags::c_NonCritical); + WaitForDebugger(); +#endif + + TINYCLR_CLEANUP_END(); +} + +bool CLR_RT_ExecutionEngine::EnsureSystemThread( CLR_RT_Thread*& thread, int priority ) +{ + NATIVE_PROFILE_CLR_CORE(); + + if(thread == NULL) + { + return SUCCEEDED(NewThread( thread, NULL, priority, -1, CLR_RT_Thread::TH_F_System )); + } + else + { + return thread->CanThreadBeReused(); + } +} + +void CLR_RT_ExecutionEngine::SpawnTimer() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_Timer,timer,m_timers) + { + if(timer->m_flags & CLR_RT_HeapBlock_Timer::c_Triggered) + { + if(EnsureSystemThread( m_timerThread, ThreadPriority::Normal )) + { + //only fire one timer at a time + + timer->SpawnTimer( m_timerThread ); + + //put at the back of the queue to allow for fairness of the timers. + m_timers.LinkAtBack( timer ); + } + break; + } + } + TINYCLR_FOREACH_NODE_END(); +} + +void CLR_RT_ExecutionEngine::StaticConstructorTerminationCallback( void* arg ) +{ + NATIVE_PROFILE_CLR_CORE(); + g_CLR_RT_ExecutionEngine.SpawnStaticConstructor( g_CLR_RT_ExecutionEngine.m_cctorThread ); +} + +#if defined(TINYCLR_APPDOMAINS) +bool CLR_RT_ExecutionEngine::SpawnStaticConstructorHelper( CLR_RT_AppDomain* appDomain, CLR_RT_AppDomainAssembly* appDomainAssembly, const CLR_RT_MethodDef_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_MethodDef_Index idxNext; + + _ASSERTE(m_cctorThread != NULL); + //_ASSERTE(m_cctorThread->CanThreadBeReused()); + + idxNext.m_data = idx.m_data; + + _ASSERTE(appDomainAssembly != NULL); + + //find next method with static constructor + if(appDomainAssembly->m_assembly->FindNextStaticConstructor( idxNext )) + { + CLR_RT_HeapBlock_Delegate* dlg; + CLR_RT_HeapBlock refDlg; refDlg.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( refDlg ); + + if(SUCCEEDED(CLR_RT_HeapBlock_Delegate::CreateInstance( refDlg, idxNext, NULL ))) + { + dlg = refDlg.DereferenceDelegate(); + dlg->m_appDomain = appDomain; + + if(SUCCEEDED(m_cctorThread->PushThreadProcDelegate( dlg ))) + { + m_cctorThread->m_terminationCallback = CLR_RT_ExecutionEngine::StaticConstructorTerminationCallback; + + return true; + } + } + } + + appDomainAssembly->m_flags |= CLR_RT_AppDomainAssembly::c_StaticConstructorsExecuted; + return false; +} + +void CLR_RT_ExecutionEngine::SpawnStaticConstructor( CLR_RT_Thread *&pCctorThread ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock_Delegate* dlg = NULL; + + if(!EnsureSystemThread(pCctorThread, ThreadPriority::System_Highest )) + return; + + dlg = pCctorThread->m_dlg; + + if(dlg != NULL) + { + CLR_RT_AppDomainAssembly* appDomainAssembly; + CLR_RT_MethodDef_Index idx = dlg->DelegateFtn(); + CLR_RT_MethodDef_Instance inst; + + //Find next static constructor for given idx + _ASSERTE(TINYCLR_INDEX_IS_VALID(idx)); + _SIDE_ASSERTE(inst.InitializeFromIndex( idx )); + + appDomainAssembly = dlg->m_appDomain->FindAppDomainAssembly( inst.m_assm ); + + _ASSERTE(appDomainAssembly != NULL); + _ASSERTE(appDomainAssembly->m_assembly == inst.m_assm ); + + //This is ok if idx is no longer valid. SpawnStaticConstructorHelper will call FindNextStaticConstructor + //which will fail + idx.m_data++; + + //This is not the first static constructor run in this appDomain + if(SpawnStaticConstructorHelper( dlg->m_appDomain, appDomainAssembly, idx )) + return; + } + + //first, find the AppDomainAssembly to run. (what about appdomains!!!) + TINYCLR_FOREACH_NODE(CLR_RT_AppDomain,appDomain,g_CLR_RT_ExecutionEngine.m_appDomains) + { + TINYCLR_FOREACH_NODE(CLR_RT_AppDomainAssembly,appDomainAssembly,appDomain->m_appDomainAssemblies) + { + CLR_RT_Assembly* assembly = appDomainAssembly->m_assembly; + + //Find an AppDomainAssembly that does not have it's static constructor bit set... + if((appDomainAssembly->m_flags & CLR_RT_AppDomainAssembly::c_StaticConstructorsExecuted) == 0) + { + CLR_RT_MethodDef_Index idx; idx.Set( assembly->m_idx, 0 ); + +#ifdef DEBUG + + //Check that all dependent assemblies have had static constructors run. + CLR_RT_AssemblyRef_CrossReference* ar = assembly->m_pCrossReference_AssemblyRef; + for(int i=0; im_pTablesSize[ TBL_AssemblyRef ]; i++, ar++) + { + CLR_RT_AppDomainAssembly* appDomainAssemblyRef = appDomain->FindAppDomainAssembly(ar->m_target); + + _ASSERTE(appDomainAssemblyRef != NULL); + _ASSERTE(appDomainAssemblyRef->m_flags & CLR_RT_AppDomainAssembly::c_StaticConstructorsExecuted); + } +#endif + + + if(SpawnStaticConstructorHelper( appDomain, appDomainAssembly, idx )) + return; + } + } + TINYCLR_FOREACH_NODE_END(); + } + TINYCLR_FOREACH_NODE_END(); + + + // No more static constructors needed... + // Perform 1 action: + // 1. Destroy constructor thread. + pCctorThread->DestroyInstance(); +} +#else //TINYCLR_APPDOMAINS + +bool CLR_RT_ExecutionEngine::SpawnStaticConstructorHelper( CLR_RT_Assembly* assembly, const CLR_RT_MethodDef_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_MethodDef_Index idxNext; + + _ASSERTE(m_cctorThread != NULL); + _ASSERTE(m_cctorThread->CanThreadBeReused()); + + idxNext.m_data = idx.m_data; + + _ASSERTE(assembly != NULL); + + //find next method with static constructor + if(assembly->FindNextStaticConstructor( idxNext )) + { + CLR_RT_HeapBlock_Delegate* dlg; + CLR_RT_HeapBlock refDlg; refDlg.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( refDlg ); + + if(SUCCEEDED(CLR_RT_HeapBlock_Delegate::CreateInstance( refDlg, idxNext, NULL ))) + { + dlg = refDlg.DereferenceDelegate(); + + if(SUCCEEDED(m_cctorThread->PushThreadProcDelegate( dlg ))) + { + m_cctorThread->m_terminationCallback = CLR_RT_ExecutionEngine::StaticConstructorTerminationCallback; + + return true; + } + } + } + + assembly->m_flags |= CLR_RT_Assembly::c_StaticConstructorsExecuted; + return false; +} + +void CLR_RT_ExecutionEngine::SpawnStaticConstructor( CLR_RT_Thread *&pCctorThread ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock_Delegate* dlg = NULL; + + if(!EnsureSystemThread(pCctorThread, ThreadPriority::System_Highest)) + return; + + dlg = pCctorThread->m_dlg; + + if(dlg != NULL) + { + CLR_RT_MethodDef_Index idx = dlg->DelegateFtn(); + CLR_RT_MethodDef_Instance inst; + + //Find next static constructor for given idx + _ASSERTE(TINYCLR_INDEX_IS_VALID(idx)); + _SIDE_ASSERTE(inst.InitializeFromIndex( idx )); + + //This is ok if idx is no longer valid. SpawnStaticConstructorHelper will call FindNextStaticConstructor + //which will fail + idx.m_data++; + + if(SpawnStaticConstructorHelper( inst.m_assm, idx )) + return; + } + + //first, find the AppDomainAssembly to run. (what about appdomains!!!) + TINYCLR_FOREACH_ASSEMBLY(g_CLR_RT_TypeSystem) + { + //Find an AppDomainAssembly that does not have it's static constructor bit set... + if((pASSM->m_flags & CLR_RT_Assembly::c_StaticConstructorsExecuted) == 0) + { + CLR_RT_MethodDef_Index idx; idx.Set( pASSM->m_idx, 0 ); + bool fDepedenciesRun = true; + + //Check that all dependent assemblies have had static constructors run. + CLR_RT_AssemblyRef_CrossReference* ar = pASSM->m_pCrossReference_AssemblyRef; + for(int i=0; im_pTablesSize[ TBL_AssemblyRef ]; i++, ar++) + { + if((ar->m_target->m_flags & CLR_RT_Assembly::c_StaticConstructorsExecuted) == 0) + { + fDepedenciesRun = true; + break; + } + } + + if(fDepedenciesRun && SpawnStaticConstructorHelper( pASSM, idx )) + return; + } + } + TINYCLR_FOREACH_ASSEMBLY_END(); + + //no more static constructors needed... + pCctorThread->DestroyInstance(); +} +#endif //TINYCLR_APPDOMAINS + +void CLR_RT_ExecutionEngine::FinalizerTerminationCallback(void* arg) +{ + NATIVE_PROFILE_CLR_CORE(); + g_CLR_RT_ExecutionEngine.SpawnFinalizer(); +} + +void CLR_RT_ExecutionEngine::SpawnFinalizer() +{ + NATIVE_PROFILE_CLR_CORE(); + + CLR_RT_HeapBlock_Finalizer* fin = (CLR_RT_HeapBlock_Finalizer*)m_finalizersPending.FirstNode(); + if(fin->Next() != NULL) + { + CLR_RT_HeapBlock delegate; delegate.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( delegate ); + +#if defined(TINYCLR_APPDOMAINS) + (void)SetCurrentAppDomain( fin->m_appDomain ); +#endif + + if(EnsureSystemThread(m_finalizerThread, ThreadPriority::BelowNormal)) + { + if(SUCCEEDED(CLR_RT_HeapBlock_Delegate::CreateInstance( delegate, fin->m_md, NULL ))) + { + CLR_RT_HeapBlock_Delegate* dlg = delegate.DereferenceDelegate(); + + dlg->m_object.SetObjectReference( fin->m_object ); + + if(SUCCEEDED(m_finalizerThread->PushThreadProcDelegate( dlg ))) + { + g_CLR_RT_EventCache.Append_Node( fin ); + m_finalizerThread->m_terminationCallback = CLR_RT_ExecutionEngine::FinalizerTerminationCallback; + } + } + } + } +} + +void CLR_RT_ExecutionEngine::AdjustExecutionCounter( CLR_RT_DblLinkedList &threadList, int iUpdateValue ) + +{ // Iterate over threads in increase executioin counter by iUpdateValue + TINYCLR_FOREACH_NODE(CLR_RT_Thread,pThread,threadList) + { + pThread->m_executionCounter += iUpdateValue; + // Update m_executionCounter if thread is too behind of m_GlobalExecutionCounter + pThread->BringExecCounterToDate( m_GlobalExecutionCounter, pThread->GetQuantumDebit() ); + } + TINYCLR_FOREACH_NODE_END() +} + +void CLR_RT_ExecutionEngine::UpdateToLowestExecutionCounter( CLR_RT_Thread *pThread ) const +{ + // Set the m_executionCounter in thread to lowest value among ready threads. + // Thus it will be executed last. + pThread->m_executionCounter = m_GlobalExecutionCounter - 1; +} + +void CLR_RT_ExecutionEngine::RetrieveCurrentMethod( CLR_UINT32& assmIdx, CLR_UINT32& methodIdx ) +{ + assmIdx = 0; + methodIdx = 0; + + if(m_currentThread != NULL) + { + CLR_RT_StackFrame* stack = m_currentThread->CurrentFrame(); + + if(stack) + { + assmIdx = stack->m_call.Assembly(); + methodIdx = stack->m_call.Method (); + } + } +} + +void CLR_RetrieveCurrentMethod( CLR_UINT32 & assmIdx, CLR_UINT32 & methodIdx ) +{ + g_CLR_RT_ExecutionEngine.RetrieveCurrentMethod( assmIdx, methodIdx ); +} + +void CLR_SoftReboot() +{ + CLR_EE_DBG_SET( RebootPending ); +} + +void CLR_DebuggerBreak() +{ + if(g_CLR_RT_ExecutionEngine.m_currentThread != NULL) + { + CLR_RT_HeapBlock *obj = g_CLR_RT_ExecutionEngine.m_currentThread->m_currentException.Dereference(); + + /// + /// Only inject the exception once -- if the dereference is not null then the exception is already set on the current thread + /// + if(obj == NULL) + { + Library_corlib_native_System_Exception::CreateInstance( g_CLR_RT_ExecutionEngine.m_currentThread->m_currentException, g_CLR_RT_WellKnownTypes.m_WatchdogException, CLR_E_WATCHDOG_TIMEOUT, g_CLR_RT_ExecutionEngine.m_currentThread->CurrentFrame() ); + } + } +} + +HRESULT CLR_RT_ExecutionEngine::ScheduleThreads( int maxContextSwitch ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + +#if defined(TINYCLR_APPDOMAINS) + CLR_RT_AppDomain* appDomainSav = g_CLR_RT_ExecutionEngine.GetCurrentAppDomain(); +#endif + + // We run threads based on the m_executionCounter. + // The thread with highest m_executionCounter is chosen for execution. + // The highest value of m_executionCounter of any thread is stored in m_GlobalExecutionCounter + // We need to check that m_GlobalExecutionCounter does not underflow ( runs below - -2147483647 ) This would be very rare condition, but it may happen. + // We put threshold at - 0x40000000 + if ( m_GlobalExecutionCounter < -EXECUTION_COUNTER_MAXIMUM ) + { // Iterate over threads in all queues and bump the execution counter by MAX_EXECUTION_COUNTER_ADJUSTMENT + + m_GlobalExecutionCounter += EXECUTION_COUNTER_ADJUSTMENT; + + // For each list of threads runs over it and updates execution counter. + // AdjustExecutionCounter gets const & to list of threads. + // List of threads is not modified, but m_executionCounter is bumped up in each thread. + + AdjustExecutionCounter( m_threadsReady, EXECUTION_COUNTER_ADJUSTMENT ); + AdjustExecutionCounter( m_threadsWaiting, EXECUTION_COUNTER_ADJUSTMENT ); + AdjustExecutionCounter( m_threadsZombie, EXECUTION_COUNTER_ADJUSTMENT ); + } + + while(maxContextSwitch-- > 0) + { + +#if defined(WIN32) + if(HAL_Windows_IsShutdownPending()) + { + TINYCLR_SET_AND_LEAVE(CLR_S_NO_THREADS); + } +#endif + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + if(CLR_EE_DBG_IS( Stopped )) + { + TINYCLR_SET_AND_LEAVE(CLR_S_NO_READY_THREADS); + } +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + CLR_RT_Thread* th = NULL; + + // If a static constructor thread exists, we should be running it. + // What about func-eval? + if (m_cctorThread == NULL) + { + // This is normal case execution. Looks for first ready thread. + th = (CLR_RT_Thread*)m_threadsReady.FirstNode(); + } + else //If a static constructor thread exists, we should be running it. + { + // This is special case executed during initialization of static constructors. + if (m_cctorThread->m_status == CLR_RT_Thread::TH_S_Ready && !(m_cctorThread->m_flags & CLR_RT_Thread::TH_F_Suspended)) + { + th = m_cctorThread; + } + else + { + // The m_cctorThread is exists, but not ready - means entered blocking call. + // We do not want to preempt constructor thread, so stay idle. + TINYCLR_SET_AND_LEAVE(CLR_S_NO_READY_THREADS); + } + } + + + + + // If th->Next() is NULL, then there are no Ready to run threads in the system. + // In this case we spawn finalizer and make finalizer thread as ready one. + if(th->Next() == NULL) + { + g_CLR_RT_ExecutionEngine.SpawnFinalizer(); + + // Now finalizer thread might be in ready state if there are object that need call to finalizer. + // th might point to finilizer thread. + th = (CLR_RT_Thread*)m_threadsReady.FirstNode(); + + //Thread create can cause stopping debugging event +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + if(CLR_EE_DBG_IS(Stopped)) + { + TINYCLR_SET_AND_LEAVE(CLR_S_NO_READY_THREADS); + } +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + } + + // If there is ready thread - decrease m_executionCounter for this (th) thread. + if( th->Next() != NULL ) + { + // The value to update m_executionCounter for each run. See comment for GetQuantumDebit for possible values + int debitForEachRun = th->GetQuantumDebit(); + + // If thread is way too much behind on its execution, we cutt off extra credit. + // We garantee the thread will not be scheduled more than 4 consequitive times. + th->BringExecCounterToDate( m_GlobalExecutionCounter, debitForEachRun ); + + // Substruct the execution counter by debit value ( for executing thread ) + th->m_executionCounter -= debitForEachRun; + + // Keep the track of lowest execution counter. + if ( th->m_executionCounter < m_GlobalExecutionCounter ) + { + m_GlobalExecutionCounter = th->m_executionCounter; + } + } + else + { + if(m_threadsWaiting.IsEmpty()) + { + TINYCLR_SET_AND_LEAVE(CLR_S_NO_THREADS); + } + + TINYCLR_SET_AND_LEAVE(CLR_S_NO_READY_THREADS); + } + + ::Watchdog_ResetCounter(); + + { + // Runs the tread until expiration of its quantum or until thread is blocked. + hr = th->Execute(); + } + + if(FAILED(hr)) + { + switch(hr) + { + case CLR_E_RESCHEDULE: + break; + + case CLR_E_THREAD_WAITING: + th->m_status = CLR_RT_Thread::TH_S_Waiting; + break; + + default: + th->m_status = CLR_RT_Thread::TH_S_Terminated; + break; + } + } + + ::Watchdog_ResetCounter(); + + PutInProperList( th ); + + UpdateTime(); + + (void)ProcessTimer(); + } + + TINYCLR_SET_AND_LEAVE(CLR_S_QUANTUM_EXPIRED); + + TINYCLR_CLEANUP(); + +#if defined(TINYCLR_APPDOMAINS) + + if(CLR_EE_IS( UnloadingAppDomain )) + { + if(TryToUnloadAppDomains()) + { + //If we are successful in unloading an AppDomain, return CLR_S_QUANTUM_EXPIRED + //to cause ScheduleThreads to be called again. This allows the somewhat expensive operation + //of trying to unload an AppDomain once every ScheduleThread call, rather than once every context switch + + hr = CLR_S_QUANTUM_EXPIRED; + } + } + + g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomainSav ); +#endif + + TINYCLR_CLEANUP_END(); +} + +CLR_UINT32 CLR_RT_ExecutionEngine::WaitForActivity() +{ + NATIVE_PROFILE_CLR_CORE(); + + UpdateTime(); + + CLR_INT64 timeoutMin = ProcessTimer(); + + if(m_threadsReady.IsEmpty() == false) return 0; // Someone woke up... + + if(timeoutMin > 0LL) + { + TINYCLR_FOREACH_NODE(CLR_RT_Thread,th,m_threadsWaiting) + { + if((th->m_waitForEvents & c_Event_IdleCPU) != 0 && th->m_waitForEvents_IdleTimeWorkItem < timeoutMin) + { + th->m_waitForEvents_IdleTimeWorkItem = TIMEOUT_ZERO; + + th->Restart( true ); + + return SYSTEM_EVENT_FLAG_ALL; // Someone woke up... + } + } + TINYCLR_FOREACH_NODE_END(); + + return WaitForActivity( SLEEP_LEVEL__SLEEP, g_CLR_HW_Hardware.m_wakeupEvents, timeoutMin ); + } + + return 0; +} + +CLR_UINT32 CLR_RT_ExecutionEngine::WaitForActivity( CLR_UINT32 powerLevel, CLR_UINT32 events, CLR_INT64 timeout_ms ) +{ + NATIVE_PROFILE_CLR_CORE(); + + if(powerLevel != CLR_HW_Hardware::PowerLevel__Active) + { + return WaitSystemEvents( powerLevel, events, timeout_ms ); + } + + return 0; +} + +//--// + +void CLR_RT_ExecutionEngine::PutInProperList( CLR_RT_Thread* th ) +{ + NATIVE_PROFILE_CLR_CORE(); + switch(th->m_status) + { + case CLR_RT_Thread::TH_S_Ready: + if((th->m_flags & CLR_RT_Thread::TH_F_Suspended) == 0) + { + InsertThreadRoundRobin( m_threadsReady, th ); + break; + } + // + // Fall-through... + // + case CLR_RT_Thread::TH_S_Waiting: + m_threadsWaiting.LinkAtBack( th ); + break; + + case CLR_RT_Thread::TH_S_Terminated: + th->Passivate(); + break; + + case CLR_RT_Thread::TH_S_Unstarted: + m_threadsZombie.LinkAtFront( th ); + break; + } +} + +void CLR_RT_ExecutionEngine::AbortAllThreads( CLR_RT_DblLinkedList& threads ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_FOREACH_NODE(CLR_RT_Thread,th,threads) + { + if((th->m_flags & CLR_RT_Thread::TH_F_Aborted) == 0) + { + th->Abort(); + + TINYCLR_FOREACH_NODE_RESTART(CLR_RT_Thread,th,threads); + } + } + TINYCLR_FOREACH_NODE_END(); +} + +void CLR_RT_ExecutionEngine::ReleaseAllThreads( CLR_RT_DblLinkedList& threads ) +{ + NATIVE_PROFILE_CLR_CORE(); + while(true) + { + CLR_RT_Thread* th = (CLR_RT_Thread*)threads.ExtractFirstNode(); if(!th) break; + + th->DestroyInstance(); + } +} + +void CLR_RT_ExecutionEngine::InsertThreadRoundRobin( CLR_RT_DblLinkedList& threads, CLR_RT_Thread* thTarget ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_Thread* th; + + thTarget->Unlink(); + + if(threads.IsEmpty()) + { + th = (CLR_RT_Thread*)threads.Tail(); + } + else + { + int priTarget = thTarget->GetExecutionCounter(); + + TINYCLR_FOREACH_NODE__NODECL(CLR_RT_Thread,th,threads) + { + if(th->GetExecutionCounter() < priTarget) break; + } + TINYCLR_FOREACH_NODE_END(); + } + + thTarget->m_waitForEvents = 0; + thTarget->m_waitForEvents_Timeout = TIMEOUT_INFINITE; + + if(thTarget->m_waitForObject != NULL) + { + g_CLR_RT_EventCache.Append_Node( thTarget->m_waitForObject ); + + thTarget->m_waitForObject = NULL; + } + + threads.InsertBeforeNode( th, thTarget ); +} + +//--// + +HRESULT CLR_RT_ExecutionEngine::NewThread( CLR_RT_Thread*& thRes, CLR_RT_HeapBlock_Delegate* pDelegate, int priority, CLR_INT32 id, CLR_UINT32 flags ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_CHECK_HRESULT(CLR_RT_Thread::CreateInstance( id != -1 ? id : ++m_lastPid, pDelegate, priority, thRes, flags )); + + PutInProperList( thRes ); + + TINYCLR_CLEANUP(); + + if(FAILED(hr)) + { + if(thRes) + { + thRes->DestroyInstance(); + + thRes = NULL; + } + } + + TINYCLR_CLEANUP_END(); +} + +CLR_INT32 CLR_RT_ExecutionEngine::GetNextThreadId() +{ + return ++m_lastPid; +} + +//--// + +CLR_RT_HeapBlock* CLR_RT_ExecutionEngine::ExtractHeapBlocksForArray( CLR_RT_TypeDef_Instance& inst, CLR_UINT32 length, const CLR_RT_ReflectionDef_Index& reflex ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_DataType dt = (CLR_DataType)inst.m_target->dataType; + const CLR_RT_DataTypeLookup& dtl = c_CLR_RT_DataTypeLookup[ dt ]; + + CLR_UINT32 totLength = (CLR_UINT32)(sizeof(CLR_RT_HeapBlock_Array) + length * dtl.m_sizeInBytes); + CLR_UINT32 lengthHB = CONVERTFROMSIZETOHEAPBLOCKS(totLength); + + if(lengthHB > CLR_RT_HeapBlock::HB_MaxSize) return NULL; + + CLR_RT_HeapBlock_Array* pArray = (CLR_RT_HeapBlock_Array*)ExtractHeapBlocks( m_heap, DATATYPE_SZARRAY, 0, lengthHB ); + + if(pArray) + { + pArray->ReflectionData() = reflex; + pArray->m_numOfElements = length; + + pArray->m_typeOfElement = dt; + pArray->m_sizeOfElement = dtl.m_sizeInBytes; + pArray->m_fReference = (dtl.m_flags & CLR_RT_DataTypeLookup::c_Numeric) == 0; + +#if defined(TINYCLR_PROFILE_NEW_ALLOCATIONS) + g_CLR_PRF_Profiler.TrackObjectCreation( pArray ); +#endif + } + + return pArray; +} + +CLR_RT_HeapBlock* CLR_RT_ExecutionEngine::ExtractHeapBlocksForClassOrValueTypes( CLR_UINT32 dataType, CLR_UINT32 flags, const CLR_RT_TypeDef_Index& cls, CLR_UINT32 length ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(length > CLR_RT_HeapBlock::HB_MaxSize) return NULL; + + _ASSERTE(dataType == DATATYPE_CLASS || dataType == DATATYPE_VALUETYPE); + + flags = flags | CLR_RT_HeapBlock::HB_InitializeToZero; + CLR_RT_HeapBlock* hb = ExtractHeapBlocks( m_heap, dataType, flags, length ); + + if(hb) + { + hb->SetObjectCls(cls); + +#if defined(TINYCLR_PROFILE_NEW_ALLOCATIONS) + g_CLR_PRF_Profiler.TrackObjectCreation( hb ); +#endif + } + + return hb; +} + +CLR_RT_HeapBlock* CLR_RT_ExecutionEngine::ExtractHeapBytesForObjects( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 length ) +{ + NATIVE_PROFILE_CLR_CORE(); + return ExtractHeapBlocksForObjects( dataType, flags, CONVERTFROMSIZETOHEAPBLOCKS(length) ); +} + +CLR_RT_HeapBlock* CLR_RT_ExecutionEngine::ExtractHeapBlocksForObjects( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 length ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(length > CLR_RT_HeapBlock::HB_MaxSize) return NULL; + + _ASSERTE(dataType != DATATYPE_CLASS && dataType != DATATYPE_VALUETYPE && dataType != DATATYPE_SZARRAY); + + flags &= ~CLR_RT_HeapBlock::HB_Alive; + + CLR_RT_HeapBlock* hb = ExtractHeapBlocks( m_heap, dataType, flags, length ); + +#if defined(TINYCLR_PROFILE_NEW_ALLOCATIONS) + if(hb) + { + g_CLR_PRF_Profiler.TrackObjectCreation( hb ); + } +#endif + + return hb; +} + +//--// + +CLR_RT_HeapBlock_Node* CLR_RT_ExecutionEngine::ExtractHeapBlocksForEvents( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 length ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(length > CLR_RT_HeapBlock::HB_MaxSize) return NULL; + + flags |= CLR_RT_HeapBlock::HB_Alive | CLR_RT_HeapBlock::HB_Event; + + CLR_RT_HeapBlock_Node* hb = (CLR_RT_HeapBlock_Node*)ExtractHeapBlocks( m_heap, dataType, flags, length ); + + if(hb) + { + hb->GenericNode_Initialize(); + +#if defined(TINYCLR_PROFILE_NEW_ALLOCATIONS) + g_CLR_PRF_Profiler.TrackObjectCreation( hb ); +#endif + } + + return hb; +} + +CLR_RT_HeapBlock* CLR_RT_ExecutionEngine::ExtractHeapBlocks( CLR_RT_DblLinkedList& heap, CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 length ) +{ + NATIVE_PROFILE_CLR_CORE(); +#if !defined(BUILD_RTM) + if(m_heapState == c_HeapState_UnderGC && ((flags & CLR_RT_HeapBlock::HB_SpecialGCAllocation) == 0)) + { + CLR_Debug::Printf( "Internal error: call to memory allocation during garbage collection!!!\r\n" ); + + // Getting here during a GC is possible, since the watchdog ISR may now require + // dynamic memory allocation for logging. Returning NULL means the watchdog log will + // be lost, but without major restructuring there is not much we can do. + return NULL; + } +#endif + +#if defined(TINYCLR_FORCE_GC_BEFORE_EVERY_ALLOCATION) + if(m_heapState != c_HeapState_UnderGC) + { + g_CLR_RT_EventCache.EventCache_Cleanup(); + PerformGarbageCollection(); + } +#endif + + for(int phase=0; ; phase++) + { + { + CLR_RT_HeapBlock* hb; + + if(flags & CLR_RT_HeapBlock::HB_Event) + { + TINYCLR_FOREACH_NODE_BACKWARD(CLR_RT_HeapCluster,hc,heap) + { + hb = hc->ExtractBlocks( dataType, flags, length ); + if(hb) + { + return hb; + } + } + TINYCLR_FOREACH_NODE_BACKWARD_END(); + } + else + { + if(m_lastHcUsed != NULL) + { + hb = m_lastHcUsed->ExtractBlocks( dataType, flags, length ); + if(hb) + { + return hb; + } + } + + TINYCLR_FOREACH_NODE(CLR_RT_HeapCluster,hc,heap) + { + hb = hc->ExtractBlocks( dataType, flags, length ); + if(hb) + { +#if defined(TINYCLR_GC_VERBOSE) + if(s_CLR_RT_fTrace_Memory >= c_CLR_RT_Trace_Info) + { + if(phase != 0) + { + CLR_Debug::Printf( "ExtractHeapBlocks succeeded at phase %d\r\n", phase ); + } + } +#endif + m_lastHcUsed = hc; + return hb; + } + } + TINYCLR_FOREACH_NODE_END(); + } + + m_lastHcUsed = NULL; + } + + if(flags & CLR_RT_HeapBlock::HB_NoGcOnFailedAllocation) + { + return NULL; + } + + switch(phase) + { + case 0: +#if defined(TINYCLR_GC_VERBOSE) + if(s_CLR_RT_fTrace_Memory >= c_CLR_RT_Trace_Info) + { + CLR_Debug::Printf( " Memory: ExtractHeapBlocks: %d bytes needed.\r\n", length * sizeof(CLR_RT_HeapBlock) ); + } +#endif + + PerformGarbageCollection(); + + break; + + default: // Total failure... +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Failed allocation for %d blocks, %d bytes\r\n\r\n", length, length * sizeof(CLR_RT_HeapBlock) ); +#endif + if(g_CLR_RT_GarbageCollector.m_freeBytes >= (length * sizeof(CLR_RT_HeapBlock))) + { + + //A compaction probably would have saved this OOM + //Compaction will occur for Bitmaps, Arrays, etc. if this function returns NULL, so lets not + //through an assert here + + //Throw the OOM, and schedule a compaction at a safe point + CLR_EE_SET( Compaction_Pending ); + } + + return NULL; + } + } +} + + +CLR_RT_HeapBlock* CLR_RT_ExecutionEngine::AccessStaticField( const CLR_RT_FieldDef_Index& fd ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_FieldDef_Instance inst; + + if(inst.InitializeFromIndex( fd ) && inst.m_target->flags & CLR_RECORD_FIELDDEF::FD_Static) + { +#if defined(TINYCLR_APPDOMAINS) + { + CLR_RT_AppDomainAssembly* appDomainAssembly = g_CLR_RT_ExecutionEngine.GetCurrentAppDomain()->FindAppDomainAssembly( inst.m_assm ); + + if(appDomainAssembly) + { + return &appDomainAssembly->m_pStaticFields[ inst.CrossReference().m_offset ]; + } + } +#else + return &inst.m_assm->m_pStaticFields[ inst.CrossReference().m_offset ]; +#endif + } + + return NULL; +} + +HRESULT CLR_RT_ExecutionEngine::InitializeReference( CLR_RT_HeapBlock& ref, CLR_RT_SignatureParser& parser ) +{ + NATIVE_PROFILE_CLR_CORE(); + // + // WARNING!!! + // + // If you change this method, change "CLR_RT_ExecutionEngine::InitializeLocals" too. + // + + TINYCLR_HEADER(); + + CLR_RT_SignatureParser::Element res; + CLR_DataType dt; + + TINYCLR_CHECK_HRESULT(parser.Advance( res )); + + dt = res.m_dt; + + if(res.m_levels > 0) // Array + { + dt = DATATYPE_OBJECT; + } + else + { + if(dt == DATATYPE_VALUETYPE) + { + CLR_RT_TypeDef_Instance inst; inst.InitializeFromIndex( res.m_cls ); + + if((inst.m_target->flags & CLR_RECORD_TYPEDEF::TD_Semantics_Mask) == CLR_RECORD_TYPEDEF::TD_Semantics_Enum) + { + dt = (CLR_DataType)inst.m_target->dataType; + } + else + { + TINYCLR_SET_AND_LEAVE(NewObject( ref, inst )); + } + } + else + { + if(c_CLR_RT_DataTypeLookup[ dt ].m_flags & CLR_RT_DataTypeLookup::c_Reference) + { + dt = DATATYPE_OBJECT; + } + } + } + + ref.SetDataId( CLR_RT_HEAPBLOCK_RAW_ID( dt, CLR_RT_HeapBlock::HB_Alive, 1 ) ); + ref.ClearData(); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ExecutionEngine::InitializeReference( CLR_RT_HeapBlock& ref, const CLR_RECORD_FIELDDEF* target, CLR_RT_Assembly* assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_SignatureParser parser; parser.Initialize_FieldDef( assm, target ); + + TINYCLR_SET_AND_LEAVE(InitializeReference( ref, parser )); + + TINYCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_ExecutionEngine::InitializeLocals( CLR_RT_HeapBlock* locals, CLR_RT_Assembly* assm, const CLR_RECORD_METHODDEF* md ) +{ + NATIVE_PROFILE_CLR_CORE(); + // + // WARNING!!! + // + // This method is a shortcut for the following code: + // + + TINYCLR_HEADER(); + + CLR_PMETADATA sig = assm->GetSignature( md->locals ); + CLR_UINT32 count = md->numLocals; + bool fZeroed = false; + + while(count) + { + CLR_DataType dt = DATATYPE_VOID; + CLR_RT_TypeDef_Index cls; + CLR_UINT32 levels = 0; + CLR_DataType dtModifier = DATATYPE_VOID; + + while(true) + { + dt = CLR_UncompressElementType( sig ); + + switch(dt) + { + case DATATYPE_TYPE_PINNED : + dtModifier = DATATYPE_TYPE_PINNED; + break; + + // Array declared on stack .locals init [0] int16[] foo, + case DATATYPE_SZARRAY: + // Reference declared on stack - .locals init [1] int16& pinned pShort, + case DATATYPE_BYREF: + levels++; + break; + + case DATATYPE_CLASS: + case DATATYPE_VALUETYPE: + { + CLR_UINT32 tk = CLR_TkFromStream( sig ); + CLR_UINT32 idx = CLR_DataFromTk( tk ); + + switch(CLR_TypeFromTk( tk )) + { + case TBL_TypeSpec: + { + CLR_RT_SignatureParser sub; sub.Initialize_TypeSpec( assm, assm->GetTypeSpec( idx ) ); + CLR_RT_SignatureParser::Element res; + + TINYCLR_CHECK_HRESULT(sub.Advance( res )); + + cls = res.m_cls; + levels += res.m_levels; + } + break; + + case TBL_TypeRef: + cls = assm->m_pCrossReference_TypeRef[ idx ].m_target; + break; + + case TBL_TypeDef: + cls.Set( assm->m_idx, idx ); + break; + + default: + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + } + goto done; + + default: + { + const CLR_RT_TypeDef_Index* cls2 = c_CLR_RT_DataTypeLookup[ dt ].m_cls; + + if(cls2 == NULL) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + cls = *cls2; + } + goto done; + } + } + +done: + if(levels > 0) // Array or reference + { + locals->SetObjectReference( NULL ); + + // If local varialb has DATATYPE_TYPE_PINNED, we mark heap block as + if ( dtModifier == DATATYPE_TYPE_PINNED ) + { + locals->Pin(); + } + } + else + { + if(dt == DATATYPE_VALUETYPE) + { + CLR_RT_TypeDef_Instance inst; inst.InitializeFromIndex( cls ); + + if(inst.m_target->dataType != DATATYPE_VALUETYPE) + { + locals->SetDataId( CLR_RT_HEAPBLOCK_RAW_ID( inst.m_target->dataType, CLR_RT_HeapBlock::HB_Alive, 1 ) ); + locals->ClearData(); + } + else + { + // + // Before we allocate anything, we need to make sure the rest of the local variables are in a consistent state. + // + if(fZeroed == false) + { + fZeroed = true; + + CLR_RT_HeapBlock* ptr = locals; + CLR_RT_HeapBlock* ptrEnd = &locals[ count ]; + + do + { + ptr->SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_I4,0,1) ); + + } while(++ptr < ptrEnd); + } + + TINYCLR_CHECK_HRESULT(NewObject( *locals, inst )); + } + } + else + { + if(c_CLR_RT_DataTypeLookup[ dt ].m_flags & CLR_RT_DataTypeLookup::c_Reference) + { + dt = DATATYPE_OBJECT; + } + + locals->SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(dt,CLR_RT_HeapBlock::HB_Alive,1) ); + locals->ClearData(); + } + } + + locals++; + count--; + } + + TINYCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_ExecutionEngine::NewObjectFromIndex( CLR_RT_HeapBlock& reference, const CLR_RT_TypeDef_Index& cls ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_TypeDef_Instance inst; + + if(inst.InitializeFromIndex( cls ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + TINYCLR_SET_AND_LEAVE(NewObject( reference, inst )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ExecutionEngine::NewObject( CLR_RT_HeapBlock& reference, const CLR_RT_TypeDef_Instance& inst ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + reference.SetObjectReference( NULL ); + + CLR_DataType dt = (CLR_DataType)inst.m_target->dataType; + + // + // You cannot create an array this way. + // + if(inst.m_data == g_CLR_RT_WellKnownTypes.m_Array.m_data) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + if((c_CLR_RT_DataTypeLookup[ dt ].m_flags & CLR_RT_DataTypeLookup::c_Reference) == 0) + { + reference.SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(dt,0,1) ); + } + else + { + switch(dt) + { + case DATATYPE_STRING: + // + // Special case for strings. + // + break; + + case DATATYPE_WEAKCLASS: + { + CLR_RT_HeapBlock_WeakReference* weakref; + + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_WeakReference::CreateInstance( weakref )); + + if(inst.m_data == g_CLR_RT_WellKnownTypes.m_ExtendedWeakReference.m_data) + { + weakref->m_identity.m_flags |= CLR_RT_HeapBlock_WeakReference::WR_ExtendedType; + } + + reference.SetObjectReference( weakref ); + } + break; + + case DATATYPE_CLASS: + case DATATYPE_VALUETYPE: + { + int clsFields = inst.m_target->iFields_Num; + int totFields = inst.CrossReference().m_totalFields + CLR_RT_HeapBlock::HB_Object_Fields_Offset; + CLR_RT_HeapBlock* obj = ExtractHeapBlocksForClassOrValueTypes( dt, 0, inst, totFields ); CHECK_ALLOCATION(obj); + + reference.SetObjectReference( obj ); + + { + const CLR_RECORD_FIELDDEF* target = NULL; + CLR_RT_Assembly* assm = NULL; + CLR_RT_TypeDef_Instance instSub = inst; + + + TINYCLR_CHECK_HRESULT(obj->SetObjectCls( inst )); + + // + // Initialize field types, from last to first. + // + // We do the decrement BEFORE the comparison because we want to stop short of the first field, the object descriptor (already initialized). + // + obj += totFields; + while(--totFields > 0) + { + while(clsFields == 0) + { + if(instSub.SwitchToParent() == false) TINYCLR_SET_AND_LEAVE(CLR_E_FAIL); + + clsFields = instSub.m_target->iFields_Num; + target = NULL; + } + + if(target == NULL) + { + assm = instSub.m_assm; + target = assm->GetFieldDef( instSub.m_target->iFields_First + clsFields ); + } + + obj--; target--; clsFields--; + + TINYCLR_CHECK_HRESULT(InitializeReference( *obj, target, assm )); + } + } + + if(inst.HasFinalizer()) + { + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Finalizer::CreateInstance( reference.Dereference(), inst )); + } + } + break; + + default: + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ExecutionEngine::NewObject( CLR_RT_HeapBlock& reference, CLR_UINT32 tk, CLR_RT_Assembly* assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_TypeDef_Instance res; + + if(res.ResolveToken( tk, assm ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + TINYCLR_CHECK_HRESULT(NewObjectFromIndex( reference, res )); + + TINYCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_ExecutionEngine::CloneObject( CLR_RT_HeapBlock& reference, const CLR_RT_HeapBlock& source ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + const CLR_RT_HeapBlock* obj = &source; + CLR_DataType dt; + + while(true) + { + dt = (CLR_DataType)obj->DataType(); + + if(dt == DATATYPE_BYREF || + dt == DATATYPE_OBJECT ) + { + obj = obj->Dereference(); FAULT_ON_NULL(obj); + } + else + { + break; + } + } + + switch(dt) + { + + case DATATYPE_VALUETYPE: + case DATATYPE_CLASS: + { + // + // Save the pointer to the object to clone, in case 'reference' and 'source' point to the same block. + // + CLR_RT_HeapBlock safeSource; safeSource.SetObjectReference( obj ); + CLR_RT_ProtectFromGC gc( safeSource ); + + TINYCLR_CHECK_HRESULT(NewObjectFromIndex( reference , obj->ObjectCls() )); + TINYCLR_CHECK_HRESULT(CopyValueType ( reference.Dereference(), obj )); + } + break; + + default: + if((c_CLR_RT_DataTypeLookup[ dt ].m_flags & CLR_RT_DataTypeLookup::c_OptimizedValueType) == 0) + { + TINYCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + } + + // + // Non-reference type, straight copy. + // + reference.Assign( source ); + break; + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ExecutionEngine::CopyValueType( CLR_RT_HeapBlock* destination, const CLR_RT_HeapBlock* source ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + if(destination != source) + { + const CLR_RT_TypeDef_Index& cls = source->ObjectCls(); + if(cls.m_data == destination->ObjectCls().m_data) + { + CLR_RT_TypeDef_Instance inst; inst.InitializeFromIndex( cls ); + CLR_UINT32 totFields = inst.CrossReference().m_totalFields; + + if(source->IsBoxed()) destination->Box(); + + while(true) + { + if(totFields-- == 0) break; + + // + // We increment the two pointers to skip the header of the objects. + // + source ++; + destination++; + + TINYCLR_CHECK_HRESULT(destination->Reassign( *source )); + } + + TINYCLR_SET_AND_LEAVE(S_OK); + } + + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + TINYCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_ExecutionEngine::NewArrayList( CLR_RT_HeapBlock& ref, int size, CLR_RT_HeapBlock_Array*& array ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + const int minCapacity = CLR_RT_ArrayListHelper::c_defaultCapacity; + int count = size; + int capacity = size < minCapacity ? minCapacity : size; + + TINYCLR_CHECK_HRESULT(NewObjectFromIndex( ref, g_CLR_RT_WellKnownTypes.m_ArrayList )); + + TINYCLR_CHECK_HRESULT(CLR_RT_ArrayListHelper::PrepareArrayList ( ref, count, capacity )); + TINYCLR_CHECK_HRESULT(CLR_RT_ArrayListHelper::ExtractArrayFromArrayList( ref, array, count, capacity )); + + TINYCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_ExecutionEngine::FindFieldDef( CLR_RT_TypeDef_Instance& inst, LPCSTR szText, CLR_RT_FieldDef_Index& res ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_TypeDef_Instance local = inst; + + do + { + if(local.m_assm->FindFieldDef( local.m_target, szText, NULL, 0, res )) TINYCLR_SET_AND_LEAVE(S_OK); + } + while(local.SwitchToParent()); + + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ExecutionEngine::FindFieldDef( CLR_RT_HeapBlock& reference, LPCSTR szText, CLR_RT_FieldDef_Index& res ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock* obj; + CLR_RT_TypeDef_Instance inst; + + if(reference.DataType() != DATATYPE_OBJECT) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + obj = reference.Dereference(); FAULT_ON_NULL(obj); + + if(inst.InitializeFromIndex( obj->ObjectCls() ) == false) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + TINYCLR_SET_AND_LEAVE(FindFieldDef( inst, szText, res )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ExecutionEngine::FindField( CLR_RT_HeapBlock& reference, LPCSTR szText, CLR_RT_HeapBlock*& field ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_FieldDef_Instance inst; + CLR_RT_FieldDef_Index idx; + CLR_RT_HeapBlock* res; + + field = NULL; + + TINYCLR_CHECK_HRESULT(FindFieldDef( reference, szText, idx )); + + inst.InitializeFromIndex( idx ); + + if(inst.m_target->flags & CLR_RECORD_FIELDDEF::FD_Static) + { + res = CLR_RT_ExecutionEngine::AccessStaticField( idx ); if(res == NULL) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + else + { + res = reference.Dereference(); FAULT_ON_NULL(res); + + res += inst.CrossReference().m_offset; + } + + field = res; + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ExecutionEngine::SetField( CLR_RT_HeapBlock& reference, LPCSTR szText, CLR_RT_HeapBlock& value ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock* field; + + TINYCLR_CHECK_HRESULT(FindField( reference, szText, field )); + + field->Assign( value ); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ExecutionEngine::GetField( CLR_RT_HeapBlock& reference, LPCSTR szText, CLR_RT_HeapBlock& value ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock* field; + + TINYCLR_CHECK_HRESULT(FindField( reference, szText, field )); + + value.Assign( *field ); + + TINYCLR_NOCLEANUP(); +} + +//--// + +CLR_RT_HeapBlock_Lock* CLR_RT_ExecutionEngine::FindLockObject( CLR_RT_DblLinkedList& threads, CLR_RT_HeapBlock& object ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_FOREACH_NODE(CLR_RT_Thread,th,threads) + { + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_Lock,lock,th->m_locks) + { + CLR_RT_HeapBlock& res = lock->m_resource; + +#if defined(TINYCLR_APPDOMAINS) + if(lock->m_appDomain != GetCurrentAppDomain()) continue; +#endif + + if(CLR_RT_HeapBlock::ObjectsEqual(res, object, true)) + { + return lock; + } + } + TINYCLR_FOREACH_NODE_END(); + } + TINYCLR_FOREACH_NODE_END(); + + return NULL; +} + +CLR_RT_HeapBlock_Lock* CLR_RT_ExecutionEngine::FindLockObject( CLR_RT_HeapBlock& object ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock_Lock* lock; + + if(object.DataType() == DATATYPE_OBJECT) + { + CLR_RT_HeapBlock* ptr = object.Dereference(); + + if(ptr) + { + switch(ptr->DataType()) + { + case DATATYPE_VALUETYPE: + case DATATYPE_CLASS : + return ptr->ObjectLock(); + } + } + } + + lock = FindLockObject( m_threadsReady , object ); if(lock) return lock; + lock = FindLockObject( m_threadsWaiting, object ); return lock; +} + +//--// + +void CLR_RT_ExecutionEngine::DeleteLockRequests( CLR_RT_Thread* thTarget, CLR_RT_SubThread* sthTarget ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(( thTarget && thTarget->m_lockRequestsCount) || + (sthTarget && sthTarget->m_lockRequestsCount) ) + { + DeleteLockRequests( thTarget, sthTarget, m_threadsReady ); + DeleteLockRequests( thTarget, sthTarget, m_threadsWaiting ); + } +} + +void CLR_RT_ExecutionEngine::DeleteLockRequests( CLR_RT_Thread* thTarget, CLR_RT_SubThread* sthTarget, CLR_RT_DblLinkedList& threads ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_FOREACH_NODE(CLR_RT_Thread,th,threads) + { + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_Lock,lock,th->m_locks) + { + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_LockRequest,req,lock->m_requests) + { + CLR_RT_SubThread* sth = req->m_subthreadWaiting; + + if(sth == sthTarget || sth->m_owningThread == thTarget) + { + g_CLR_RT_EventCache.Append_Node( req ); + + if(sth->ChangeLockRequestCount( -1 )) return; + } + } + TINYCLR_FOREACH_NODE_END(); + } + TINYCLR_FOREACH_NODE_END(); + } + TINYCLR_FOREACH_NODE_END(); +} + +//--// + +void CLR_RT_ExecutionEngine::ProcessHardware() +{ + NATIVE_PROFILE_CLR_CORE(); + ::Watchdog_ResetCounter(); + + g_CLR_HW_Hardware.ProcessActivity(); +} + +CLR_INT64 CLR_RT_ExecutionEngine::ProcessTimer() +{ + NATIVE_PROFILE_CLR_CORE(); + + CLR_INT64 timeoutMin; + + ProcessHardware(); + + timeoutMin = m_maximumTimeToActive; // max sleep. + + //////////////////////////////////////////////// + // WARNING + // + // The check on the 'Stopped' condition, and the 'else' + // condition below cause a race condition when the application is running under debugger + // and there are no ready threads in the app. teh desktop side debugger in facts is prodigal + // of Stopped commands and so is the runtime itself. Since the commands come asynchronously + // though and there is no co-ordination it is possible that + // a) a 'Stopped' condition reset get lost or + // b) waiting threads whose timers are expired are never moved to the ready queue + // + + if(CLR_EE_DBG_IS( Stopped ) && m_threadsWaiting.IsEmpty()) + { + // Don't process events while the debugger is stopped and no thread was waiting. + // if some thread was waiting we might need to transfer it to the ready queue + } + else + { + if(m_timerCache && m_timerCacheNextTimeout > m_currentMachineTime) + { + timeoutMin = m_timerCacheNextTimeout - m_currentMachineTime; + } + //else + { + CheckTimers( timeoutMin ); + + CheckThreads( timeoutMin, m_threadsReady ); + CheckThreads( timeoutMin, m_threadsWaiting ); + + m_timerCacheNextTimeout = timeoutMin + m_currentMachineTime; + m_timerCache = (m_timerCacheNextTimeout > m_currentMachineTime); + + } + } + + // if the system timer is not set as one of the wakeup events then just return the max time to active + if(0 == (g_CLR_HW_Hardware.m_wakeupEvents & SYSTEM_EVENT_FLAG_SYSTEM_TIMER)) + { + timeoutMin = m_maximumTimeToActive; + } + + return timeoutMin; +} + +void CLR_RT_ExecutionEngine::ProcessTimeEvent( CLR_UINT32 event ) +{ + NATIVE_PROFILE_CLR_CORE(); + SYSTEMTIME systemTime; + + UpdateTime(); + + Time_ToSystemTime( m_currentLocalTime, &systemTime ); + + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_Timer,timer,m_timers) + { + if(timer->m_flags & CLR_RT_HeapBlock_Timer::c_EnabledTimer) + { + CLR_UINT32 val = timer->m_flags & CLR_RT_HeapBlock_Timer::c_AnyChange; + + if(val) + { + timer->AdjustNextFixedExpire( systemTime, true ); + + if(val == event && (timer->m_flags & CLR_RT_HeapBlock_Timer::c_Recurring) == 0) + { + timer->Trigger(); + } + } + } + } + TINYCLR_FOREACH_NODE_END(); + + SpawnTimer(); +} + +void CLR_RT_ExecutionEngine::InvalidateTimerCache() +{ + NATIVE_PROFILE_CLR_CORE(); + g_CLR_RT_ExecutionEngine.m_timerCache = false; +} + +//--//--// + +bool CLR_RT_ExecutionEngine::IsTimeExpired( const CLR_INT64& timeExpire, CLR_INT64& timeoutMin, bool fAbsolute ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_INT64 cmp = (fAbsolute ? m_currentLocalTime : m_currentMachineTime); + + if(timeExpire <= cmp) return true; + + CLR_INT64 diff = timeExpire - cmp; + + if(diff < timeoutMin) + { + timeoutMin = diff; + } + + return false; +} + +bool CLR_RT_ExecutionEngine::IsThereEnoughIdleTime( CLR_UINT32 expectedMsec ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(::Events_MaskedRead( g_CLR_HW_Hardware.m_wakeupEvents )) return false; + + CLR_INT64 now = Time_GetMachineTime(); + + if(now + expectedMsec * TIME_CONVERSION__TO_MILLISECONDS >= m_currentNextActivityTime) return false; + + return true; +} + +//--// + +void CLR_RT_ExecutionEngine::CheckTimers( CLR_INT64& timeoutMin ) +{ + NATIVE_PROFILE_CLR_CORE(); + bool fAnyTimersExpired = false; + + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_Timer,timer,m_timers) + { + if(timer->m_flags & CLR_RT_HeapBlock_Timer::c_EnabledTimer) + { + CLR_INT64 expire = timer->m_timeExpire; + if(IsTimeExpired( expire, timeoutMin, (timer->m_flags & CLR_RT_HeapBlock_Timer::c_AbsoluteTimer) != 0 )) + { +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + if(CLR_EE_DBG_IS_NOT( PauseTimers )) +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + { + timer->Trigger(); + fAnyTimersExpired = true; + } + } + } + } + TINYCLR_FOREACH_NODE_END(); + + if(fAnyTimersExpired) + { + SpawnTimer(); + } + +} + +void CLR_RT_ExecutionEngine::CheckThreads( CLR_INT64& timeoutMin, CLR_RT_DblLinkedList& threads ) +{ + NATIVE_PROFILE_CLR_CORE(); + + TINYCLR_FOREACH_NODE(CLR_RT_Thread,th,threads) + { + CLR_INT64 expire; + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + if(th->m_flags & CLR_RT_Thread::TH_F_Suspended) + { + continue; + } +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + // + // Check events. + // + expire = th->m_waitForEvents_Timeout; + if(IsTimeExpired( expire, timeoutMin, false )) + { + th->m_waitForEvents_Timeout = TIMEOUT_INFINITE; + + th->Restart( false ); + } + + // + // Check wait for object. + // + + { + CLR_RT_HeapBlock_WaitForObject* wait = th->m_waitForObject; + + if(wait) + { + if(IsTimeExpired( wait->m_timeExpire, timeoutMin, false )) + { + th->m_waitForObject_Result = CLR_RT_Thread::TH_WAIT_RESULT_TIMEOUT; + + th->Restart( true ); + } + } + } + + // + // Check lock requests. + // + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_Lock,lock,th->m_locks) + { + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_LockRequest,req,lock->m_requests) + { + if(IsTimeExpired( req->m_timeExpire, timeoutMin, false )) + { + CLR_RT_SubThread* sth = req->m_subthreadWaiting; + + sth->ChangeLockRequestCount( -1 ); + + g_CLR_RT_EventCache.Append_Node( req ); + } + } + TINYCLR_FOREACH_NODE_END(); + } + TINYCLR_FOREACH_NODE_END(); + + // + // Check constraints. + // + TINYCLR_FOREACH_NODE_BACKWARD(CLR_RT_SubThread,sth,th->m_subThreads) + { + if(sth->m_timeConstraint != TIMEOUT_INFINITE) + { + if(IsTimeExpired( s_compensation.Adjust( sth->m_timeConstraint ), timeoutMin, false )) + { + (void)Library_corlib_native_System_Exception::CreateInstance( th->m_currentException, g_CLR_RT_WellKnownTypes.m_ConstraintException, S_OK, th->CurrentFrame() ); + + if((sth->m_status & CLR_RT_SubThread::STATUS_Triggered) == 0) + { + sth->m_status |= CLR_RT_SubThread::STATUS_Triggered; + + // + // This is the first time, give it 500msec to clean before killing it. + // + sth->m_timeConstraint += TIME_CONVERSION__TO_MILLISECONDS * 500; CLR_RT_ExecutionEngine::InvalidateTimerCache(); + } + else + { + CLR_RT_SubThread::DestroyInstance( th, sth, CLR_RT_SubThread::MODE_CheckLocks ); + + // + // So it doesn't fire again... + // + sth->m_timeConstraint = TIMEOUT_INFINITE; + } + + th->Restart( true ); + } + } + } + TINYCLR_FOREACH_NODE_END(); + } + TINYCLR_FOREACH_NODE_END(); +} + +//--// + +HRESULT CLR_RT_ExecutionEngine::LockObject( CLR_RT_HeapBlock& reference, CLR_RT_SubThread* sth, const CLR_INT64& timeExpire, bool fForce ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock_Lock* lock; + + lock = FindLockObject( reference ); + + if(lock == NULL) + { + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Lock::CreateInstance( lock, sth->m_owningThread, reference )); + } + + TINYCLR_SET_AND_LEAVE(CLR_RT_HeapBlock_Lock::IncrementOwnership( lock, sth, timeExpire, fForce )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ExecutionEngine::UnlockObject( CLR_RT_HeapBlock& reference, CLR_RT_SubThread* sth ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock_Lock* lock; + + lock = FindLockObject( reference ); + + TINYCLR_SET_AND_LEAVE(CLR_RT_HeapBlock_Lock::DecrementOwnership( lock, sth )); + + TINYCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_ExecutionEngine::Sleep( CLR_RT_Thread* caller, const CLR_INT64& timeExpire ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + caller->m_waitForEvents_Timeout = timeExpire; CLR_RT_ExecutionEngine::InvalidateTimerCache(); + caller->m_status = CLR_RT_Thread::TH_S_Waiting; + + TINYCLR_SET_AND_LEAVE(CLR_E_THREAD_WAITING); + + TINYCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_ExecutionEngine::WaitEvents( CLR_RT_Thread* caller, const CLR_INT64& timeExpire, CLR_UINT32 events, bool& fSuccess ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + if(m_raisedEvents & events) + { + m_raisedEvents &= ~events; + + fSuccess = true; + } + else + { + fSuccess = false; + + if(Time_GetMachineTime() < timeExpire) + { + caller->m_waitForEvents = events; + caller->m_waitForEvents_Timeout = timeExpire; CLR_RT_ExecutionEngine::InvalidateTimerCache(); + caller->m_status = CLR_RT_Thread::TH_S_Waiting; + + TINYCLR_SET_AND_LEAVE(CLR_E_THREAD_WAITING); + } + } + + TINYCLR_NOCLEANUP(); +} + +void CLR_RT_ExecutionEngine::SignalEvents( CLR_RT_DblLinkedList& threads, CLR_UINT32 events ) +{ + NATIVE_PROFILE_CLR_CORE(); + m_raisedEvents |= events; + + TINYCLR_FOREACH_NODE(CLR_RT_Thread,th,threads) + { + if((th->m_waitForEvents & events) != 0) + { + _ASSERTE(&threads == &m_threadsWaiting); + _ASSERTE(th->m_status == CLR_RT_Thread::TH_S_Waiting); + + th->Restart( true ); + } + } + TINYCLR_FOREACH_NODE_END(); +} + +void CLR_RT_ExecutionEngine::SignalEvents( CLR_UINT32 events ) +{ + NATIVE_PROFILE_CLR_CORE(); + //Why does the ready queue need to be checked. + SignalEvents( m_threadsReady , events ); + SignalEvents( m_threadsWaiting, events ); +} + +//--// + +bool CLR_RT_ExecutionEngine::IsInstanceOf( CLR_RT_TypeDescriptor& desc, CLR_RT_TypeDescriptor& descTarget ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_TypeDef_Instance& inst = desc .m_handlerCls; + CLR_RT_TypeDef_Instance& instTarget = descTarget.m_handlerCls; + bool fArray = false; + + while(desc .m_reflex.m_levels > 0 && + descTarget.m_reflex.m_levels > 0 ) + { + desc .GetElementType( desc ); + descTarget.GetElementType( descTarget ); + + fArray = true; + } + + if(desc.m_reflex.m_levels < descTarget.m_reflex.m_levels) return false; + + if(desc.m_reflex.m_levels > descTarget.m_reflex.m_levels) + { + if(descTarget.m_reflex.m_levels == 0) + { + // + // Casting from [] to System.Array or System.Object is always allowed. + // + if(inst.m_data == g_CLR_RT_WellKnownTypes.m_Array .m_data || + inst.m_data == g_CLR_RT_WellKnownTypes.m_Object .m_data || + inst.m_data == g_CLR_RT_WellKnownTypes.m_IList .m_data || + inst.m_data == g_CLR_RT_WellKnownTypes.m_ICloneable.m_data ) + { + return true; + } + } + + if(inst.m_target->dataType != instTarget.m_target->dataType) + { + return false; + } + } + + CLR_UINT32 semantic = (inst .m_target->flags & CLR_RECORD_TYPEDEF::TD_Semantics_Mask); + CLR_UINT32 semanticTarget = (instTarget.m_target->flags & CLR_RECORD_TYPEDEF::TD_Semantics_Mask); + + if(fArray) + { + if(semantic != semanticTarget) + { + return false; + } + } + + do + { + if(inst.m_data == instTarget.m_data) + { + return true; + } + + // + // Scan the list of interfaces. + // + if(semanticTarget == CLR_RECORD_TYPEDEF::TD_Semantics_Interface && inst.m_target->interfaces != CLR_EmptyIndex) + { + CLR_RT_SignatureParser parser; parser.Initialize_Interfaces( inst.m_assm, inst.m_target ); + CLR_RT_SignatureParser::Element res; + + while(parser.Available() > 0) + { + if(FAILED(parser.Advance( res ))) break; + + if(res.m_cls.m_data == instTarget.m_data) + { + return true; + } + } + } + } + while(inst.SwitchToParent()); + + return false; +} + +bool CLR_RT_ExecutionEngine::IsInstanceOf( const CLR_RT_TypeDef_Index& cls, const CLR_RT_TypeDef_Index& clsTarget ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_TypeDescriptor desc; + CLR_RT_TypeDescriptor descTarget; + + if(FAILED(desc .InitializeFromType( cls ))) return false; + if(FAILED(descTarget.InitializeFromType( clsTarget ))) return false; + + return IsInstanceOf( desc, descTarget ); +} + +bool CLR_RT_ExecutionEngine::IsInstanceOf( CLR_RT_HeapBlock& ref, const CLR_RT_TypeDef_Index& clsTarget ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_TypeDescriptor desc; + CLR_RT_TypeDescriptor descTarget; + + if(FAILED(desc .InitializeFromObject( ref ))) return false; + if(FAILED(descTarget.InitializeFromType ( clsTarget ))) return false; + + return IsInstanceOf( desc, descTarget ); +} + +bool CLR_RT_ExecutionEngine::IsInstanceOf( CLR_RT_HeapBlock& obj, CLR_RT_Assembly* assm, CLR_UINT32 token ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_TypeDescriptor desc; + CLR_RT_TypeDescriptor descTarget; + CLR_RT_TypeDef_Instance clsTarget; + CLR_RT_TypeSpec_Instance defTarget; + + if(FAILED(desc.InitializeFromObject( obj ))) return false; + + if(clsTarget.ResolveToken( token, assm )) + { + // + // Shortcut for identity. + // + if(desc.m_handlerCls.m_data == clsTarget.m_data) return true; + + if(FAILED(descTarget.InitializeFromType( clsTarget ))) return false; + } + else if(defTarget.ResolveToken( token, assm )) + { + if(FAILED(descTarget.InitializeFromTypeSpec( defTarget ))) return false; + } + else + { + return false; + } + + return IsInstanceOf( desc, descTarget ); +} + +HRESULT CLR_RT_ExecutionEngine::CastToType( CLR_RT_HeapBlock& ref, CLR_UINT32 tk, CLR_RT_Assembly* assm, bool fUpdate ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + if(ref.DataType() == DATATYPE_OBJECT && ref.Dereference() == NULL) + { + ; + } + else if(g_CLR_RT_ExecutionEngine.IsInstanceOf( ref, assm, tk ) == true) + { + ; + } + else + { + if(fUpdate == false) + { + TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_CAST); + } + + ref.SetObjectReference( NULL ); + } + + TINYCLR_NOCLEANUP(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + + +HRESULT CLR_RT_ExecutionEngine::InitTimeout( CLR_INT64& timeExpire, const CLR_INT64& timeout ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + if(timeout < 0) + { + if(timeout != -1L) + { + TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + + timeExpire = TIMEOUT_INFINITE; + } + else + { + timeExpire = timeout + Time_GetMachineTime(); + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ExecutionEngine::InitTimeout( CLR_INT64& timeExpire, CLR_INT32 timeout ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + if(timeout < 0) + { + if(timeout != -1) + { + TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + + timeExpire = TIMEOUT_INFINITE; + } + else + { + timeExpire = timeout; + timeExpire *= TIME_CONVERSION__TO_MILLISECONDS; + timeExpire += Time_GetMachineTime(); + } + + TINYCLR_NOCLEANUP(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_ExecutionEngine::DebuggerLoop() +{ + NATIVE_PROFILE_CLR_CORE(); + ProcessHardware(); + + UpdateTime(); + + WaitSystemEvents( SLEEP_LEVEL__SLEEP, g_CLR_HW_Hardware.m_wakeupEvents, TIME_CONVERSION__TO_MILLISECONDS * 100 ); +} + + +//--// + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + +void CLR_RT_ExecutionEngine::SetDebuggingInfoBreakpoints( bool fSet ) +{ + NATIVE_PROFILE_CLR_CORE(); + for(size_t pos=0; posm_pid; + th->m_timeQuantumExpired = TRUE; + } + + if(m_breakpointsActiveNum == 1) + { + CLR_EE_DBG_EVENT_SEND(CLR_DBG_Commands::c_Debugging_Execution_BreakpointHit,sizeof(CLR_DBG_Commands::Debugging_Execution_BreakpointDef),&m_breakpointsActive[ 0 ],WP_Flags::c_NonCritical); + } + } + else + { + _ASSERTE(FALSE); + } + } +} + +void CLR_RT_ExecutionEngine::StopOnBreakpoint( CLR_DBG_Commands::Debugging_Execution_BreakpointDef& def, CLR_RT_StackFrame* stack, CLR_PMETADATA ip ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(ip == NULL) ip = stack->m_IP; + + def.m_depth = stack->m_depth; + def.m_md = stack->m_call; + def.m_IP = (CLR_UINT32)(ip - stack->m_IPstart); + + //Don't fail for special cases regarding messages dealing with exception handling. + _ASSERTE(def.m_IP == 0xffffffff || ip >= stack->m_IPstart); + //we don't actually know the end of the method. + + StopOnBreakpoint( def, stack->m_owningThread ); +} + +bool CLR_RT_ExecutionEngine::DequeueActiveBreakpoint( CLR_DBG_Commands::Debugging_Execution_BreakpointDef& def ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(m_breakpointsActiveNum) + { + def = m_breakpointsActive[ 0 ]; + + if(--m_breakpointsActiveNum == 0) + { + def.m_flags |= CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_LAST_BREAKPOINT; + } + + memmove( &m_breakpointsActive[ 0 ], &m_breakpointsActive[ 1 ], sizeof(m_breakpointsActive[ 0 ]) * m_breakpointsActiveNum ); + + return true; + } + + return false; +} + +//--// + +void CLR_RT_ExecutionEngine::Breakpoint_System_Event( CLR_DBG_Commands::Debugging_Execution_BreakpointDef& hit, CLR_UINT16 event, CLR_RT_Thread* th, CLR_RT_StackFrame* stack, CLR_PMETADATA ip ) +{ + NATIVE_PROFILE_CLR_CORE(); + for(size_t pos=0; posm_owningThread)); + + th = stack->m_owningThread; + } + + if(th == NULL || def.m_pid == th->m_pid || def.m_pid == CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_PID_ANY) + { + if(def.m_flags & event) + { + hit.m_id = def.m_id; + hit.m_flags = event; + + if(stack != NULL) + { + StopOnBreakpoint( hit, stack, ip ); + } + else + { + StopOnBreakpoint( hit, th ); + } + } + } + } +} + +void CLR_RT_ExecutionEngine::Breakpoint_Assemblies_Loaded() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_DBG_Commands::Debugging_Execution_BreakpointDef hit; TINYCLR_CLEAR(hit); + + for(size_t i = 0; i < this->m_breakpointsActiveNum; i++) + { + CLR_DBG_Commands::Debugging_Execution_BreakpointDef& def = this->m_breakpointsActive[ i ]; + + if(def.m_flags & CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_ASSEMBLIES_LOADED) + { + //There is already one queued AssembliesLoaded breakpoint. No need to send another one. + return; + } + } + + Breakpoint_System_Event( hit, CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_ASSEMBLIES_LOADED, m_currentThread, NULL, NULL ); +} + +void CLR_RT_ExecutionEngine::Breakpoint_Threads_Prepare( CLR_RT_DblLinkedList& threads ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_FOREACH_NODE(CLR_RT_Thread,th,threads) + { + th->m_fHasJMCStepper = false; + + for(size_t pos=0; posm_pid) + { + th->m_fHasJMCStepper = true; + break; + } + } + } + + TINYCLR_FOREACH_NODE(CLR_RT_StackFrame,call,th->m_stackFrames) + { + call->m_flags &= ~CLR_RT_StackFrame::c_HasBreakpoint; + + if(call->m_call.DebuggingInfo().HasBreakpoint()) + { + call->m_flags |= CLR_RT_StackFrame::c_HasBreakpoint; + } + else + { + for(size_t pos=0; posm_pid && def.m_depth == call->m_depth) + { + call->m_flags |= CLR_RT_StackFrame::c_HasBreakpoint; + break; + } + } + } + } +#ifndef TINYCLR_NO_IL_INLINE + if(call->m_inlineFrame) + { + if(call->m_inlineFrame->m_frame.m_call.DebuggingInfo().HasBreakpoint()) + { + call->m_flags |= CLR_RT_StackFrame::c_HasBreakpoint; + } + else + { + for(size_t pos=0; posm_pid && def.m_depth == (call->m_depth-1)) + { + call->m_flags |= CLR_RT_StackFrame::c_HasBreakpoint; + break; + } + } + } + } + } +#endif + } + TINYCLR_FOREACH_NODE_END(); + } + TINYCLR_FOREACH_NODE_END(); +} + +void CLR_RT_ExecutionEngine::Breakpoint_Thread_Terminated( CLR_RT_Thread* th ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_DBG_Commands::Debugging_Execution_BreakpointDef hit; TINYCLR_CLEAR(hit); + CLR_UINT16 evt = CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_THREAD_TERMINATED; + + hit.m_depth = 0xFFFFFFFF; + + if(th->m_scratchPad >= 0) + { + evt |= CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_EVAL_COMPLETE; + } + + Breakpoint_System_Event( hit, evt, th, NULL, NULL ); +} + +void CLR_RT_ExecutionEngine::Breakpoint_Thread_Created( CLR_RT_Thread* th ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_DBG_Commands::Debugging_Execution_BreakpointDef hit; TINYCLR_CLEAR(hit); + + Breakpoint_System_Event( hit, CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_THREAD_CREATED, th, NULL, NULL ); +} + +//--// + +void CLR_RT_ExecutionEngine::Breakpoint_StackFrame_Push( CLR_RT_StackFrame* stack, CLR_UINT32 reason ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_Thread* th = stack->m_owningThread; + int pid = th->m_pid; + CLR_UINT32 depthMax = stack->m_depth - 1; + CLR_UINT16 flags = CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_STEP_IN; + CLR_UINT32 depthMin = depthMax; + + if(stack->m_flags & CLR_RT_StackFrame::c_PseudoStackFrameForFilter) + { + //If a filter frame is being pushed on (assuming the InterceptMask for filters is set), we want to intercept the frame + //in certain special cases. + _ASSERTE(th->m_nestedExceptionsPos); + CLR_RT_Thread::UnwindStack& us = th->m_nestedExceptions[ th->m_nestedExceptionsPos-1 ]; + _ASSERTE(us.m_stack == stack); + depthMin = us.m_handlerStack->m_depth; + //If we popped off frames from AppDomain transitions that had steppers, we want to break there as well. + depthMax = 0xffffffff; + flags |= CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_STEP_OVER | CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_STEP_OUT; + } + + for(size_t pos=0; posm_call.DebuggingInfo().IsJMC(); + } + else + { + fStop = (def.m_depth >= depthMin && def.m_depth <= depthMax); + } + + if(def.m_depth == depthMin && (def.m_flags & CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_STEP) == CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_STEP_OUT) + { + //In the case a user did a step out in a frame, we don't want to break if a filter gets pushed from that frame. However, if there is a step in or over on that frame, + //we should break. + fStop = false; + } + + if(fStop) + { + CLR_DBG_Commands::Debugging_Execution_BreakpointDef hit = def; + + hit.m_flags = CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_STEP_IN; + hit.m_depthExceptionHandler = reason; + + StopOnBreakpoint( hit, stack, NULL ); + } + } + } + } + + Breakpoint_StackFrame_Hard( stack, stack->m_IP ); +} + +void CLR_RT_ExecutionEngine::Breakpoint_StackFrame_Pop( CLR_RT_StackFrame* stack, bool stepEH ) +{ + NATIVE_PROFILE_CLR_CORE(); + int pid = stack->m_owningThread->m_pid; + CLR_UINT32 depth = stack->m_depth; + CLR_RT_StackFrame* caller = stack->Caller(); + + if(caller->Prev() || stepEH) + { + for(size_t pos=0; posm_call.DebuggingInfo().IsJMC(); + } + else + { + fStop = (depth <= def.m_depth); + } + + if(fStop) + { + CLR_DBG_Commands::Debugging_Execution_BreakpointDef hit = def; + + hit.m_flags = CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_STEP_OUT; + + if(stepEH) + { + hit.m_depthExceptionHandler = CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_DEPTH_STEP_EXCEPTION_HANDLER; + } + else + { + hit.m_depthExceptionHandler = CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_DEPTH_STEP_RETURN; + } + + StopOnBreakpoint( hit, (stepEH)? stack : caller, NULL ); + } + } + } + } + } +} + +void CLR_RT_ExecutionEngine::Breakpoint_StackFrame_Step( CLR_RT_StackFrame* stack, CLR_PMETADATA ip ) +{ + NATIVE_PROFILE_CLR_CORE(); + int pid = stack->m_owningThread->m_pid; + CLR_UINT32 depth = stack->m_depth; + CLR_UINT32 IPoffset = (CLR_UINT32)(ip - stack->m_IPstart); + + for(size_t pos=0; pos= def.m_IPEnd)) + { + if(def.m_flags & CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_STEP_JMC) + { + if(!stack->m_call.DebuggingInfo().IsJMC()) + { + continue; + } + } + + CLR_DBG_Commands::Debugging_Execution_BreakpointDef hit = def; + + hit.m_flags = CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_STEP_OVER; + + StopOnBreakpoint( hit, stack, ip ); + } + } + } + + Breakpoint_StackFrame_Hard( stack, ip ); +} + +void CLR_RT_ExecutionEngine::Breakpoint_StackFrame_Hard( CLR_RT_StackFrame* stack, CLR_PMETADATA ip ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(stack->Prev() != NULL && ip != NULL) + { + CLR_UINT32 IPoffset = (CLR_UINT32)(ip - stack->m_IPstart); + + for(size_t pos=0; posm_owningThread->m_pid || def.m_pid == CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_PID_ANY) + { + if(def.m_md.m_data == stack->m_call.m_data && def.m_IP == IPoffset) + { + CLR_DBG_Commands::Debugging_Execution_BreakpointDef hit = def; + + hit.m_flags = CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_HARD; + + StopOnBreakpoint( hit, stack, ip ); + } + } + } + } + } +} + +void CLR_RT_ExecutionEngine::Breakpoint_StackFrame_Break( CLR_RT_StackFrame* stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_DBG_Commands::Debugging_Execution_BreakpointDef hit; TINYCLR_CLEAR(hit); + + Breakpoint_System_Event( hit, CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_BREAK, NULL, stack, NULL ); +} + +//--// + +void CLR_RT_ExecutionEngine::Breakpoint_Exception( CLR_RT_StackFrame* stack, CLR_UINT32 reason, CLR_PMETADATA ip ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_DBG_Commands::Debugging_Execution_BreakpointDef hit; TINYCLR_CLEAR(hit); + hit.m_depthExceptionHandler = reason; + + Breakpoint_System_Event( hit, CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_EXCEPTION_THROWN, NULL, stack, ip ); +} + +void CLR_RT_ExecutionEngine::Breakpoint_Exception_Uncaught( CLR_RT_Thread* th ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_DBG_Commands::Debugging_Execution_BreakpointDef hit; TINYCLR_CLEAR(hit); + + hit.m_depth = CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_DEPTH_UNCAUGHT; + hit.m_depthExceptionHandler = CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_DEPTH_UNCAUGHT; + + Breakpoint_System_Event( hit, CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_EXCEPTION_THROWN, th, NULL, NULL ); +} + +void CLR_RT_ExecutionEngine::Breakpoint_Exception_Intercepted( CLR_RT_StackFrame* stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_DBG_Commands::Debugging_Execution_BreakpointDef hit; TINYCLR_CLEAR(hit); + CLR_UINT16 event = CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_EXCEPTION_CAUGHT + | CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_EXCEPTION_UNWIND; + + hit.m_depthExceptionHandler = stack->m_depth; + + Breakpoint_System_Event( hit, event, NULL, stack, NULL ); +} + +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(TINYCLR_APPDOMAINS) + +CLR_RT_AppDomain* CLR_RT_ExecutionEngine::SetCurrentAppDomain( CLR_RT_AppDomain* appDomain ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_AppDomain* ad = m_appDomainCurrent; + + m_appDomainCurrent = appDomain; + + return ad; +} + +CLR_RT_AppDomain* CLR_RT_ExecutionEngine::GetCurrentAppDomain() +{ + NATIVE_PROFILE_CLR_CORE(); + return m_appDomainCurrent; +} + +void CLR_RT_ExecutionEngine::PrepareThreadsForAppDomainUnload( CLR_RT_AppDomain* appDomain, CLR_RT_DblLinkedList& threads) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_FOREACH_NODE(CLR_RT_Thread, th, threads) + { + bool fFoundDoomedAppDomain = false; + bool fInjectThreadAbort = false; + + TINYCLR_FOREACH_NODE(CLR_RT_StackFrame, stack, th->m_stackFrames) + { + if(!fFoundDoomedAppDomain) + { + if(stack->m_appDomain == appDomain) + { + //The first stack frame found in a doomed AppDomain + fFoundDoomedAppDomain = true; + fInjectThreadAbort = true; + stack->m_flags |= CLR_RT_StackFrame::c_AppDomainInjectException; + th ->m_flags |= CLR_RT_Thread::TH_F_ContainsDoomedAppDomain; + } + } + else //fFoundDoomedAppDomain + { + if(stack->m_flags & CLR_RT_StackFrame::c_AppDomainInjectException) + { + //This thread is already being unwound due to an unloading AppDomain + stack->m_flags &= ~CLR_RT_StackFrame::c_AppDomainInjectException; + fInjectThreadAbort = false; + } + } + } + TINYCLR_FOREACH_NODE_END(); + + if(fInjectThreadAbort) + { + (void)th->Abort(); + } + } + TINYCLR_FOREACH_NODE_END(); +} + +HRESULT CLR_RT_ExecutionEngine::UnloadAppDomain( CLR_RT_AppDomain* appDomain, CLR_RT_Thread* th ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + //Check to make sure the current thread does not contain any doomed AppDomains + TINYCLR_FOREACH_NODE(CLR_RT_StackFrame, stack, th->m_stackFrames) + { + if(!stack->m_appDomain->IsLoaded() || stack->m_appDomain == appDomain) TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + TINYCLR_FOREACH_NODE_END(); + + PrepareThreadsForAppDomainUnload( appDomain, m_threadsReady ); + PrepareThreadsForAppDomainUnload( appDomain, m_threadsWaiting ); + + appDomain->m_state = CLR_RT_AppDomain::AppDomainState_Unloading; + CLR_EE_SET(UnloadingAppDomain); + + TINYCLR_NOCLEANUP(); +} + +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_ExecutionEngine::UpdateTime() +{ + NATIVE_PROFILE_CLR_CORE(); + + m_currentMachineTime = Time_GetMachineTime(); + m_currentLocalTime = Time_GetLocalTime(); + + /// Did timezone or daylight offset got adjusted? If yes make some adjustments in timers too. + CLR_INT32 timeZoneOffset = Time_GetTimeZoneOffset(); + + if(timeZoneOffset != m_lastTimeZoneOffset) + { + SYSTEMTIME systemTime; + + m_lastTimeZoneOffset = timeZoneOffset; + Time_ToSystemTime( m_currentLocalTime, &systemTime ); + + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_Timer,timer,m_timers) + { + if(timer->m_flags & CLR_RT_HeapBlock_Timer::c_EnabledTimer) + { + if(timer->m_flags & CLR_RT_HeapBlock_Timer::c_AnyChange) + { + timer->AdjustNextFixedExpire( systemTime, false ); + } + } + } + TINYCLR_FOREACH_NODE_END(); + } + +} + +CLR_UINT32 CLR_RT_ExecutionEngine::WaitSystemEvents( CLR_UINT32 powerLevel, CLR_UINT32 events, CLR_INT64 timeExpire ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_INT32 timeout; + + CLR_UINT32 res = 0; + + m_currentNextActivityTime = timeExpire + m_currentMachineTime; + + timeout = (CLR_INT32)timeExpire / TIME_CONVERSION__TO_MILLISECONDS; + + if(timeout == 0) timeout = 1; + +#if defined(TINYCLR_TRACE_SYSTEMEVENTWAIT) + CLR_INT64 start = Time_GetMachineTime(); +#endif + +//#define TINYCLR_STRESS_GC +#if defined(TINYCLR_STRESS_GC) + if(timeout > 100) + { + CLR_INT64 startGC = Time_GetMachineTime(); + + + g_CLR_RT_ExecutionEngine.PerformHeapCompaction (); + + CLR_INT64 endGC = Time_GetMachineTime(); + + timeout -= (CLR_INT32)((endGC - startGC) / TIME_CONVERSION__TO_MILLISECONDS); + } +#endif + + ::Watchdog_GetSetEnabled( FALSE, TRUE ); + res = ::Events_WaitForEvents( powerLevel, events, timeout ); + ::Watchdog_GetSetEnabled( TRUE, TRUE ); + + +#if defined(TINYCLR_TRACE_SYSTEMEVENTWAIT) + CLR_INT64 stop = Time_GetMachineTime(); + CLR_INT64 stop2 = Time_GetMachineTime(); + + static CLR_INT64 totalRequested = 0; + static CLR_INT64 totalActual = 0; + static CLR_INT64 samples = 0; + + totalRequested += timeout; + totalActual += (stop - start) - (stop2 - stop); + samples += 1; + + if(samples == 10000) + { + CLR_Debug::Printf( "Wait %lld %lld\r\n", totalRequested / samples, totalActual / samples ); + + totalRequested = 0; + totalActual = 0; + samples = 0; + } +#endif + + m_currentNextActivityTime = 0; + + return res; +} + diff --git a/src/CLR/Core/GarbageCollector.cpp b/src/CLR/Core/GarbageCollector.cpp new file mode 100644 index 0000000000..c407efbc1b --- /dev/null +++ b/src/CLR/Core/GarbageCollector.cpp @@ -0,0 +1,853 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +CLR_RT_ProtectFromGC* CLR_RT_ProtectFromGC::s_first = NULL; + +void CLR_RT_ProtectFromGC::Initialize( CLR_RT_HeapBlock& ref ) +{ + NATIVE_PROFILE_CLR_CORE(); + m_next = s_first; s_first = this; + + m_data = (void**)&ref; + m_fpn = NULL; + + if(ref.IsForcedAlive()) + { + m_flags = c_HeapBlock; + } + else + { + m_flags = c_HeapBlock | c_ResetKeepAlive; + + ref.MarkForcedAlive(); + } +} + +void CLR_RT_ProtectFromGC::Initialize( void** data, Callback fpn ) +{ + NATIVE_PROFILE_CLR_CORE(); + m_next = s_first; s_first = this; + + m_data = data; + m_fpn = fpn; + m_flags = c_Generic; +} + +void CLR_RT_ProtectFromGC::Cleanup() +{ + NATIVE_PROFILE_CLR_CORE(); + s_first = m_next; + + if(m_flags & c_ResetKeepAlive) + { + CLR_RT_HeapBlock* obj = (CLR_RT_HeapBlock*)m_data; + + obj->UnmarkForcedAlive(); + } +} + +void CLR_RT_ProtectFromGC::Invoke() +{ + NATIVE_PROFILE_CLR_CORE(); + if(m_fpn) + { + m_fpn( *m_data ); + } + else if(m_data) + { + g_CLR_RT_GarbageCollector.CheckMultipleBlocks( (CLR_RT_HeapBlock*)m_data, 1 ); + } +} + +void CLR_RT_ProtectFromGC::InvokeAll() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_ProtectFromGC* ptr; + + ptr = s_first; + while(ptr) + { + ptr->Invoke(); + + ptr = ptr->m_next; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(TINYCLR_TRACE_EARLYCOLLECTION) + +CLR_RT_AssertEarlyCollection* CLR_RT_AssertEarlyCollection::s_first = NULL; + +CLR_RT_AssertEarlyCollection::CLR_RT_AssertEarlyCollection( CLR_RT_HeapBlock* ptr ) +{ + NATIVE_PROFILE_CLR_CORE(); + m_next = s_first; s_first = this; + + m_ptr = ptr; +} + +CLR_RT_AssertEarlyCollection::~CLR_RT_AssertEarlyCollection() +{ + NATIVE_PROFILE_CLR_CORE(); + s_first = m_next; +} + +void CLR_RT_AssertEarlyCollection::Cancel() +{ + NATIVE_PROFILE_CLR_CORE(); + m_ptr = NULL; +} + +void CLR_RT_AssertEarlyCollection::CheckAll( CLR_RT_HeapBlock* ptr ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_AssertEarlyCollection* node; + + node = s_first; + while(node) + { + if(node->m_ptr == ptr) + { + CLR_Debug::Printf( "INTERNAL ERROR: %08x retired early!!!\r\n", ptr ); + +#if defined(_WIN32) + ::Sleep( 1000 ); + ::DebugBreak(); +#endif + } + + node = node->m_next; + } +} + +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +CLR_UINT32 CLR_RT_GarbageCollector::ExecuteGarbageCollection() +{ + NATIVE_PROFILE_CLR_CORE(); +#if defined(TINYCLR_PROFILE_NEW_ALLOCATIONS) + g_CLR_PRF_Profiler.RecordGarbageCollectionBegin(); +#endif + +#if defined(TINYCLR_GC_VERBOSE) + if(s_CLR_RT_fTrace_GC >= c_CLR_RT_Trace_Info) + { + CLR_Debug::Printf( " Memory: Start %s\r\n", Time_CurrentDateTimeToString() ); + } +#endif + + //////////////////////////////////////////////////////////////////////////////////////////////// + + CLR_RT_ExecutionEngine::ExecutionConstraint_Suspend(); + +#if defined(TINYCLR_TRACE_MEMORY_STATS) + CLR_UINT64 stats_start = 0; + + if(s_CLR_RT_fTrace_MemoryStats >= c_CLR_RT_Trace_Info) + { + stats_start = HAL_Time_CurrentTicks(); + } +#endif + + g_CLR_RT_EventCache.EventCache_Cleanup(); + + Mark (); + MarkWeak(); + Sweep (); + + Heap_ComputeAliveVsDeadRatio(); + + CheckMemoryPressure(); + +#if defined(TINYCLR_TRACE_MEMORY_STATS) + if(s_CLR_RT_fTrace_MemoryStats >= c_CLR_RT_Trace_Info) + { + int milliSec = ((int)::HAL_Time_TicksToTime( HAL_Time_CurrentTicks() - stats_start ) + TIME_CONVERSION__TICKUNITS - 1) / TIME_CONVERSION__TICKUNITS; + + CLR_Debug::Printf( "GC: %dmsec %d bytes used, %d bytes available\r\n", milliSec, m_totalBytes - m_freeBytes, m_freeBytes ); + } + + if(s_CLR_RT_fTrace_MemoryStats >= c_CLR_RT_Trace_Info) + { + int countBlocks[ DATATYPE_FIRST_INVALID ]; TINYCLR_CLEAR(countBlocks); + int countArryBlocks[ DATATYPE_FIRST_INVALID ]; TINYCLR_CLEAR(countArryBlocks); + int dt; + + TINYCLR_FOREACH_NODE(CLR_RT_HeapCluster,hc,g_CLR_RT_ExecutionEngine.m_heap) + { + CLR_RT_HeapBlock_Node* ptr = hc->m_payloadStart; + CLR_RT_HeapBlock_Node* end = hc->m_payloadEnd; + + while(ptr < end) + { + dt = ptr->DataType(); + if(dt < DATATYPE_FIRST_INVALID) + { + countBlocks[ dt ] += ptr->DataSize(); + + if(dt == DATATYPE_SZARRAY) + { + CLR_RT_HeapBlock_Array* arr = (CLR_RT_HeapBlock_Array*)ptr; + + if(arr != NULL) + { + dt = arr->m_typeOfElement; + + if(dt < DATATYPE_FIRST_INVALID) + { + countArryBlocks[ dt ] += ptr->DataSize(); + } + else + { + CLR_Debug::Printf("!!!!Unknown array type: %d\r\n", dt); + } + } + + } + } + + ptr += ptr->DataSize(); + } + } + TINYCLR_FOREACH_NODE_END(); + + for(dt = DATATYPE_VOID; dt < DATATYPE_FIRST_INVALID; dt++) + { + if(countBlocks[ dt ]) + { + CLR_Debug::Printf( "Type %02X (%-20s): %6d bytes\r\n", dt, c_CLR_RT_DataTypeLookup[ dt ].m_name, countBlocks[ dt ] * sizeof(CLR_RT_HeapBlock) ); + + if(dt == DATATYPE_SZARRAY) + { + for(int dt2 = DATATYPE_VOID; dt2 < DATATYPE_FIRST_INVALID; dt2++) + { + if(countArryBlocks[ dt2 ]) + { + CLR_Debug::Printf( " Type %02X (%-20s): %6d bytes\r\n", dt2, c_CLR_RT_DataTypeLookup[ dt2 ].m_name, countArryBlocks[ dt2 ] * sizeof(CLR_RT_HeapBlock) ); + } + } + } + } + } + } +#endif + + CLR_RT_ExecutionEngine::ExecutionConstraint_Resume(); + + m_numberOfGarbageCollections++; + + //////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(TINYCLR_GC_VERBOSE) + if(s_CLR_RT_fTrace_GC >= c_CLR_RT_Trace_Info) + { + CLR_Debug::Printf( " Memory: End %s\r\n", Time_CurrentDateTimeToString() ); + } +#endif + +#if defined(TINYCLR_PROFILE_NEW_ALLOCATIONS) + g_CLR_PRF_Profiler.RecordGarbageCollectionEnd(); +#endif + + return m_freeBytes; +} + +//--// + +void CLR_RT_GarbageCollector::MarkSlow() +{ + NATIVE_PROFILE_CLR_CORE(); + while(m_fOutOfStackSpaceForGC) + { + m_fOutOfStackSpaceForGC = false; + + //go through managed heap. + //find all objects that are not alive but are pointed to by a live object + //put them on the markstack. + for(CLR_RT_HeapCluster* hc = (CLR_RT_HeapCluster*)g_CLR_RT_ExecutionEngine.m_heap.FirstNode(); + hc->Next(); + hc = (CLR_RT_HeapCluster*)hc->Next() + ) + { + CLR_RT_HeapBlock* ptr = hc->m_payloadStart; + CLR_RT_HeapBlock* end = hc->m_payloadEnd; + + while(ptr < end) + { + if(ptr->IsAlive() && !ptr->IsEvent()) + { + CheckSingleBlock_Force( ptr ); + } + + ptr += ptr->DataSize(); + } + } + } +} + +void CLR_RT_GarbageCollector::Mark() +{ + NATIVE_PROFILE_CLR_CORE(); +#if defined(TINYCLR_VALIDATE_APPDOMAIN_ISOLATION) + CLR_RT_AppDomain* appDomainSav = g_CLR_RT_ExecutionEngine.GetCurrentAppDomain(); +#endif + + // + // Let's setup the proper workers. + // + m_funcSingleBlock = ComputeReachabilityGraphForSingleBlock; + m_funcMultipleBlocks = ComputeReachabilityGraphForMultipleBlocks; + + m_fOutOfStackSpaceForGC = false; + + //////////////////////////////////////////////////////////////////////////// + // + // Prepare the helper buffers. + // + m_weakDelegates_Reachable.DblLinkedList_Initialize(); + + CLR_RT_DblLinkedList markStackList; + MarkStack markStack; + MarkStackElement markStackBuffer[ c_minimumSpaceForGC ]; + + m_markStackList = &markStackList; + m_markStack = &markStack; + + m_markStack ->Initialize( markStackBuffer, ARRAYSIZE(markStackBuffer) ); + m_markStackList->DblLinkedList_Initialize(); + m_markStackList->LinkAtFront( m_markStack ); + + + //////////////////////////////////////////////////////////////////////////// + // + // Call global markers. + // +#if defined(TINYCLR_VALIDATE_APPDOMAIN_ISOLATION) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( NULL ); +#endif + + CLR_RT_ProtectFromGC::InvokeAll(); + + g_CLR_HW_Hardware.PrepareForGC(); + + + //////////////////////////////////////////////////////////////////////////// + // + // Do the recursive marking! + // + { + // + // Mark all the events, so we keep the related threads/objects alive. + // + { + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_Finalizer,fin,g_CLR_RT_ExecutionEngine.m_finalizersPending) + { +#if defined(TINYCLR_VALIDATE_APPDOMAIN_ISOLATION) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( fin->m_appDomain ); +#endif + CheckSingleBlock( &fin->m_object ); + } + TINYCLR_FOREACH_NODE_END(); + } + + // + // Mark all the static fields. + // + +#if defined(TINYCLR_APPDOMAINS) + AppDomain_Mark(); +#endif + + Assembly_Mark(); + + // + // Walk through all the stack frames, marking the objects as we dig down. + // + Thread_Mark( g_CLR_RT_ExecutionEngine.m_threadsReady ); + Thread_Mark( g_CLR_RT_ExecutionEngine.m_threadsWaiting ); + +#if !defined(TINYCLR_APPDOMAINS) + CheckSingleBlock_Force( g_CLR_RT_ExecutionEngine.m_globalLock ); +#endif + + CheckSingleBlock_Force( g_CLR_RT_ExecutionEngine.m_currentUICulture ); + + +#if defined(TINYCLR_VALIDATE_APPDOMAIN_ISOLATION) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( NULL ); +#endif //TINYCLR_VALIDATE_APPDOMAIN_ISOLATION + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + CheckSingleBlock_Force( g_CLR_RT_ExecutionEngine.m_scratchPadArray ); +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + if(m_fOutOfStackSpaceForGC) + { + MarkSlow(); + _ASSERTE(!m_fOutOfStackSpaceForGC); + } + } + // + // + // + //////////////////////////////////////////////////////////////////////////// + + + //////////////////////////////////////////////////////////////////////////// + // + // Prepare finalization of objects + // + { + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_Finalizer,fin,g_CLR_RT_ExecutionEngine.m_finalizersAlive) + { + // + // If the object is dead, make it alive one last time and put it in the pending finalizers list. + // + if(fin->m_object->IsAlive() == false) + { +#if defined(TINYCLR_VALIDATE_APPDOMAIN_ISOLATION) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( fin->m_appDomain ); +#endif + CheckSingleBlock( &fin->m_object ); + + g_CLR_RT_ExecutionEngine.m_finalizersPending.LinkAtBack( fin ); + } + } + TINYCLR_FOREACH_NODE_END(); + } + // + // + // + //////////////////////////////////////////////////////////////////////////// + + if(m_fOutOfStackSpaceForGC) + { + MarkSlow(); + } + + _ASSERTE(m_markStackList == &markStackList); + _ASSERTE(m_markStack == &markStack ); + + while((MarkStack*)m_markStackList->LastValidNode() != m_markStack) + { + MarkStack* markStackT = (MarkStack*)m_markStackList->LastValidNode(); + + markStackT->RemoveFromList(); + + CLR_RT_Memory::Release( markStackT ); + } + + m_markStackList = NULL; + m_markStack = NULL; + +#if defined(TINYCLR_VALIDATE_APPDOMAIN_ISOLATION) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomainSav ); +#endif +} + +void CLR_RT_GarbageCollector::MarkWeak() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_WeakReference,weak,g_CLR_RT_ExecutionEngine.m_weakReferences) + { + if(weak->m_identity.m_flags & CLR_RT_HeapBlock_WeakReference::WR_Restored) + { + if(weak->m_targetSerialized) + { + weak->MarkAlive(); + } + } + + if(weak->IsAlive()) + { + // + // Only extended weak references are kept alive, memory permitting. + // + if(weak->m_identity.m_flags & CLR_RT_HeapBlock_WeakReference::WR_ExtendedType) + { + if(weak->m_targetSerialized && weak->m_targetSerialized->IsAlive() == false) + { + weak->m_targetSerialized->MarkAlive(); + } + } + + if(weak->m_targetDirect) + { + if(weak->m_targetDirect->IsAlive()) + { + // + // If the direct object is alive, keep the serialized version around too!! + // + if(weak->m_targetSerialized && weak->m_targetSerialized->IsAlive() == false) + { + weak->m_targetSerialized->MarkAlive(); + } + } + else + { + weak->m_targetDirect = NULL; + } + } + } + else + { + g_CLR_RT_Persistence_Manager.InvalidateEntry( weak ); + + weak->Unlink(); + } + } + TINYCLR_FOREACH_NODE_END(); +} + +//--// + +void CLR_RT_GarbageCollector::Sweep() +{ + NATIVE_PROFILE_CLR_CORE(); + + //////////////////////////////////////////////////////////////////////////////////////////////// + // // + // At this point all the alive objects have been reached, let's start the clean up. // + // // + //////////////////////////////////////////////////////////////////////////////////////////////// + + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_Delegate_List,weak,m_weakDelegates_Reachable) + { + CLR_UINT32 num = weak->m_length; + CLR_RT_HeapBlock* dlgs = weak->GetDelegates(); + + for(;num--; dlgs++) + { + CLR_RT_HeapBlock_Delegate* dlg = dlgs->DereferenceDelegate(); + if(dlg) + { + CLR_RT_HeapBlock* obj = dlg->m_object.Dereference(); + if(obj && obj->IsAlive() == false) + { + // + // Found a dead delegate, kill it!! + // + dlgs->SetObjectReference( NULL ); + continue; + } + + dlg->MarkAlive(); + } + } + } + TINYCLR_FOREACH_NODE_END(); + + RecoverEventsFromGC(); + + //--// + + // + // All the dead objects are marked as such, it's time to reclaim them. + // + { + TINYCLR_FOREACH_NODE(CLR_RT_HeapCluster,hc,g_CLR_RT_ExecutionEngine.m_heap) + { + hc->RecoverFromGC(); + } + TINYCLR_FOREACH_NODE_END(); + } +} + +//--// + +void CLR_RT_GarbageCollector::CheckMemoryPressure() +{ + NATIVE_PROFILE_CLR_CORE(); + if(m_freeBytes > c_memoryThreshold2) + { + m_pressureCounter = 0; + } + else + { + bool fExit = false; + + // + // Drop all the restored objects that haven't been reclaimed by an application. + // + TINYCLR_FOREACH_NODE_BACKWARD(CLR_RT_HeapBlock_WeakReference,weak,g_CLR_RT_ExecutionEngine.m_weakReferences) + { + if(weak->m_identity.m_flags & CLR_RT_HeapBlock_WeakReference::WR_Restored) + { + if(weak->m_targetSerialized) + { + fExit = true; + + g_CLR_RT_Persistence_Manager.InvalidateEntry( weak ); + } + } + } + TINYCLR_FOREACH_NODE_BACKWARD_END(); + + if(fExit || m_freeBytes > c_memoryThreshold) + { + m_pressureCounter = 0; + } + else + { + m_pressureCounter++; + + if(m_pressureCounter > c_pressureThreshold) + { + TINYCLR_FOREACH_NODE_BACKWARD(CLR_RT_HeapBlock_WeakReference,weak,g_CLR_RT_ExecutionEngine.m_weakReferences) + { + if(weak->m_targetSerialized && weak->m_targetDirect == NULL) + { +#if !defined(BUILD_RTM) + CLR_RT_ReflectionDef_Index val; + CLR_RT_TypeDef_Instance inst; + char rgBuffer[ 512 ]; + LPSTR szBuffer = rgBuffer; + size_t iBuffer = MAXSTRLEN(rgBuffer); + + CLR_Debug::Printf( "DROPPING OBJECT " ); + + val.InitializeFromHash( weak->m_identity.m_selectorHash ); + + if(inst.InitializeFromReflection( val, NULL )) + { + g_CLR_RT_TypeSystem.BuildTypeName( inst, szBuffer, iBuffer ); rgBuffer[ MAXSTRLEN(rgBuffer) ] = 0; + + CLR_Debug::Printf( "%s:%d ", rgBuffer, weak->m_identity.m_id ); + } + + CLR_Debug::Printf( " [%d bytes] %s\r\n", weak->m_targetSerialized->m_numOfElements, (weak->m_targetDirect ? "DIRECT" : "") ); +#endif + + g_CLR_RT_Persistence_Manager.InvalidateEntry( weak ); + + break; + } + } + TINYCLR_FOREACH_NODE_BACKWARD_END(); + } + } + } +} + +//--// + +#if defined(TINYCLR_APPDOMAINS) + +void CLR_RT_GarbageCollector::AppDomain_Mark() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_FOREACH_NODE(CLR_RT_AppDomain,appDomain,g_CLR_RT_ExecutionEngine.m_appDomains) + { +#if defined(TINYCLR_VALIDATE_APPDOMAIN_ISOLATION) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomain ); +#endif + + TINYCLR_FOREACH_NODE(CLR_RT_AppDomainAssembly,appDomainAssembly,appDomain->m_appDomainAssemblies) + { + CheckMultipleBlocks( appDomainAssembly->m_pStaticFields, appDomainAssembly->m_assembly->m_iStaticFields ); + } + TINYCLR_FOREACH_NODE_END(); + + CheckSingleBlock_Force( appDomain->m_globalLock ); + CheckSingleBlock_Force( appDomain->m_strName ); + CheckSingleBlock_Force( appDomain->m_outOfMemoryException ); + } + TINYCLR_FOREACH_NODE_END(); +} + +#endif + +void CLR_RT_GarbageCollector::Assembly_Mark() +{ + NATIVE_PROFILE_CLR_CORE(); +#if defined(TINYCLR_VALIDATE_APPDOMAIN_ISOLATION) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( NULL ); +#endif + + TINYCLR_FOREACH_ASSEMBLY(g_CLR_RT_TypeSystem) + { + +#if !defined(TINYCLR_APPDOMAINS) + CheckMultipleBlocks( pASSM->m_pStaticFields, pASSM->m_iStaticFields ); +#endif + + CheckSingleBlock( &pASSM->m_pFile ); + } + TINYCLR_FOREACH_ASSEMBLY_END(); +} + +//--// + +void CLR_RT_GarbageCollector::Thread_Mark( CLR_RT_Thread* th ) +{ + NATIVE_PROFILE_CLR_CORE(); +#if defined(TINYCLR_VALIDATE_APPDOMAIN_ISOLATION) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( th->m_dlg->m_appDomain ); +#endif + CheckSingleBlock ( &th->m_dlg ); + +#if defined(TINYCLR_VALIDATE_APPDOMAIN_ISOLATION) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( th->CurrentAppDomain() ); +#endif + CheckSingleBlock_Force( &th->m_currentException ); + + for(int i=0; im_nestedExceptionsPos; i++) + { + CLR_RT_Thread::UnwindStack& us = th->m_nestedExceptions[ i ]; + +#if defined(TINYCLR_VALIDATE_APPDOMAIN_ISOLATION) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( us.m_stack->m_appDomain ); +#endif + + CheckSingleBlock_Force( us.m_exception ); + } + + // + // Mark all the objects on the stack frames. + // + TINYCLR_FOREACH_NODE(CLR_RT_StackFrame,stack,th->m_stackFrames) + { +#if defined(TINYCLR_VALIDATE_APPDOMAIN_ISOLATION) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( stack->m_appDomain ); +#endif +#ifndef TINYCLR_NO_IL_INLINE + if(stack->m_inlineFrame) + { + CheckMultipleBlocks( stack->m_inlineFrame->m_frame.m_args , stack->m_inlineFrame->m_frame.m_call.m_target->numArgs ); + CheckMultipleBlocks( stack->m_inlineFrame->m_frame.m_locals , stack->m_inlineFrame->m_frame.m_call.m_target->numLocals ); + CheckMultipleBlocks( stack->m_inlineFrame->m_frame.m_evalStack, (int)(stack->m_inlineFrame->m_frame.m_evalPos - stack->m_inlineFrame->m_frame.m_evalStack)); + } +#endif + CheckMultipleBlocks( stack->m_arguments, stack->m_call.m_target->numArgs ); + CheckMultipleBlocks( stack->m_locals , stack->m_call.m_target->numLocals ); + CheckMultipleBlocks( stack->m_evalStack, stack->TopValuePosition() ); + } + TINYCLR_FOREACH_NODE_END(); + + // + // Mark locked objects. + // + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_Lock,lock,th->m_locks) + { +#if defined(TINYCLR_VALIDATE_APPDOMAIN_ISOLATION) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( lock->m_appDomain ); +#endif + CheckSingleBlock_Force( &lock->m_resource ); + } + TINYCLR_FOREACH_NODE_END(); + + // + // Mark the objects this thread is waiting for. + // +#if defined(TINYCLR_VALIDATE_APPDOMAIN_ISOLATION) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( th->CurrentAppDomain() ); +#endif + + { + CLR_RT_HeapBlock_WaitForObject* wait = th->m_waitForObject; + + if(wait) + { + CheckMultipleBlocks( wait->GetWaitForObjects(), wait->m_cObjects ); + } + } +} + +void CLR_RT_GarbageCollector::Thread_Mark( CLR_RT_DblLinkedList& threads ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_FOREACH_NODE(CLR_RT_Thread,th,threads) + { + Thread_Mark( th ); + } + TINYCLR_FOREACH_NODE_END(); +} + +//--// + +void CLR_RT_GarbageCollector::RecoverEventsFromGC() +{ + NATIVE_PROFILE_CLR_CORE(); + +#if defined(CLR_COMPONENTIZATION_USE_HANDLER) + Handler_RecoverFromGC(); +#else + CLR_RT_HeapBlock_EndPoint::HandlerMethod_RecoverFromGC(); + // UNDONE: FIXME: CLR_RT_HeapBlock_NativeEventDispatcher::HandlerMethod_RecoverFromGC(); + // UNDONE: FIXME: CLR_RT_HeapBlock_I2CXAction::HandlerMethod_RecoverFromGC(); +#endif + + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_Timer,timer,g_CLR_RT_ExecutionEngine.m_timers) + { + timer->RecoverFromGC(); + } + TINYCLR_FOREACH_NODE_END(); + + //--// + + TINYCLR_FOREACH_NODE(CLR_RT_Thread,th,g_CLR_RT_ExecutionEngine.m_threadsReady) + { + th->RecoverFromGC(); + } + TINYCLR_FOREACH_NODE_END(); + + TINYCLR_FOREACH_NODE(CLR_RT_Thread,th,g_CLR_RT_ExecutionEngine.m_threadsWaiting) + { + th->RecoverFromGC(); + } + TINYCLR_FOREACH_NODE_END(); + + TINYCLR_FOREACH_NODE(CLR_RT_Thread,th,g_CLR_RT_ExecutionEngine.m_threadsZombie) + { + th->RecoverFromGC(); + th->ReleaseWhenDeadEx(); // After the GC has happened, we have to check if any zombie thread can be reclaimed. + } + TINYCLR_FOREACH_NODE_END(); + +#if defined(TINYCLR_APPDOMAINS) + TINYCLR_FOREACH_NODE(CLR_RT_AppDomain,appDomain,g_CLR_RT_ExecutionEngine.m_appDomains) + { + appDomain->RecoverFromGC(); + } + TINYCLR_FOREACH_NODE_END(); +#endif +} + +//--// + +CLR_UINT32 CLR_RT_GarbageCollector::Heap_ComputeAliveVsDeadRatio() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_UINT32 totalBytes = 0; + CLR_UINT32 freeBlocks = 0; + + TINYCLR_FOREACH_NODE(CLR_RT_HeapCluster,hc,g_CLR_RT_ExecutionEngine.m_heap) + { + CLR_RT_HeapBlock_Node* ptr = hc->m_payloadStart; + CLR_RT_HeapBlock_Node* end = hc->m_payloadEnd; + + totalBytes += (CLR_UINT32)((CLR_UINT8*)end - (CLR_UINT8*)ptr); + + TINYCLR_FOREACH_NODE_BACKWARD(CLR_RT_HeapBlock_Node,ptrFree,hc->m_freeList) + { + freeBlocks += ptrFree->DataSize(); + } + TINYCLR_FOREACH_NODE_BACKWARD_END(); + } + TINYCLR_FOREACH_NODE_END(); + + m_totalBytes = totalBytes; + m_freeBytes = freeBlocks * sizeof(CLR_RT_HeapBlock); + + return m_freeBytes; +} + diff --git a/src/CLR/Core/GarbageCollector_Compaction.cpp b/src/CLR/Core/GarbageCollector_Compaction.cpp new file mode 100644 index 0000000000..0cafffd1fe --- /dev/null +++ b/src/CLR/Core/GarbageCollector_Compaction.cpp @@ -0,0 +1,456 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +CLR_UINT32 CLR_RT_GarbageCollector::ExecuteCompaction() +{ + NATIVE_PROFILE_CLR_CORE(); +#if defined(TINYCLR_PROFILE_NEW_ALLOCATIONS) + g_CLR_PRF_Profiler.RecordHeapCompactionBegin(); +#endif + +#if defined(TINYCLR_TRACE_MEMORY_STATS) + if(s_CLR_RT_fTrace_MemoryStats >= c_CLR_RT_Trace_Info) + { + CLR_Debug::Printf( "GC: performing heap compaction...\r\n" ); + } +#endif + + //////////////////////////////////////////////////////////////////////////////////////////////// + + CLR_RT_ExecutionEngine::ExecutionConstraint_Suspend(); + + Heap_Compact(); + + CLR_RT_ExecutionEngine::ExecutionConstraint_Resume(); + + m_numberOfCompactions++; + + //////////////////////////////////////////////////////////////////////////////////////////////// +#if defined(TINYCLR_PROFILE_NEW_ALLOCATIONS) + g_CLR_PRF_Profiler.RecordHeapCompactionEnd(); +#endif + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_GarbageCollector::Heap_Compact() +{ + NATIVE_PROFILE_CLR_CORE(); + + ValidatePointers(); + + //--// + + RelocationRegion relocHelper[ c_minimumSpaceForCompact ]; + const size_t relocMax = ARRAYSIZE(relocHelper); + + Heap_Relocate_Prepare( relocHelper, relocMax ); + + RelocationRegion* relocBlocks = relocHelper; + RelocationRegion* relocCurrent = relocBlocks; + + //--// + + TestPointers_PopulateOld(); + + + CLR_RT_HeapCluster* freeRegion_hc = NULL;; + CLR_RT_HeapBlock_Node* freeRegion = NULL; + + CLR_RT_HeapCluster* currentSource_hc = (CLR_RT_HeapCluster*)g_CLR_RT_ExecutionEngine.m_heap.FirstNode(); + while(currentSource_hc->Next()) + { + CLR_RT_HeapBlock_Node* currentSource = currentSource_hc->m_payloadStart; + CLR_RT_HeapBlock_Node* currentSource_end = currentSource_hc->m_payloadEnd; + + if(!freeRegion) + { + // + // Move to the next first free region. + // + freeRegion_hc = (CLR_RT_HeapCluster*)g_CLR_RT_ExecutionEngine.m_heap.FirstNode(); + while(true) + { + CLR_RT_HeapCluster* freeRegion_hcNext = (CLR_RT_HeapCluster*)freeRegion_hc->Next(); if(!freeRegion_hcNext) break; + + freeRegion = freeRegion_hc->m_freeList.FirstNode(); if(freeRegion->Next()) break; + + freeRegion = NULL; + freeRegion_hc = freeRegion_hcNext; + } + if(!freeRegion) break; + } + + while(true) + { + // + // We can only move backward. + // + if(currentSource < freeRegion) + { + currentSource_hc = freeRegion_hc; + currentSource = freeRegion; + currentSource_end = freeRegion_hc->m_payloadEnd; + } + + while(currentSource < currentSource_end && currentSource->IsFlagSet( CLR_RT_HeapBlock::HB_Unmovable )) + { + currentSource += currentSource->DataSize(); + } + + if(currentSource == currentSource_end) break; + + ////////////////////////////////////////////////////// + // + // At this point, we have at least ONE movable block. + // + ////////////////////////////////////////////////////// + +#if TINYCLR_VALIDATE_HEAP >= TINYCLR_VALIDATE_HEAP_4_CompactionPlus + if(IsBlockInFreeList( g_CLR_RT_ExecutionEngine.m_heap, freeRegion, true ) == false) + { + CLR_Debug::Printf( "'freeRegion' is not in a free list!! %08x\r\n", freeRegion ); + + TINYCLR_DEBUG_STOP(); + } + + if(IsBlockInFreeList( g_CLR_RT_ExecutionEngine.m_heap, currentSource, false )) + { + CLR_Debug::Printf( "'currentSource' is in a free list!! %08x\r\n", currentSource ); + + TINYCLR_DEBUG_STOP(); + } +#endif + + if(m_relocCount >= relocMax) + { + ValidateHeap( g_CLR_RT_ExecutionEngine.m_heap ); + + Heap_Relocate(); + + ValidateHeap( g_CLR_RT_ExecutionEngine.m_heap ); + + relocBlocks = m_relocBlocks; + relocCurrent = relocBlocks; + + TestPointers_PopulateOld(); + } + + { + CLR_UINT32 move = 0; + CLR_UINT32 freeRegion_Size = freeRegion->DataSize(); + bool fSlide; + + relocCurrent->m_destination = (CLR_UINT8*)freeRegion; + relocCurrent->m_start = (CLR_UINT8*)currentSource; + relocCurrent->m_offset = (CLR_UINT32)(relocCurrent->m_destination - relocCurrent->m_start); + + + // + // Are the free block and the last moved block adjacent? + // + if(currentSource == freeRegion + freeRegion_Size) + { + while(currentSource < currentSource_end && currentSource->IsFlagSet( CLR_RT_HeapBlock::HB_Unmovable ) == false) + { + CLR_UINT32 len = currentSource->DataSize(); + + currentSource += len; + move += len; + } + + fSlide = true; + } + else + { + while(freeRegion_Size && currentSource < currentSource_end && currentSource->IsFlagSet( CLR_RT_HeapBlock::HB_Unmovable ) == false) + { + CLR_UINT32 len = currentSource->DataSize(); + + if(freeRegion_Size < len) + { + break; + } + + freeRegion_Size -= len; + currentSource += len; + move += len; + } + + fSlide = false; + } + + if(move) + { + // + // Skip forward to the next movable block. + // + while(currentSource < currentSource_end && currentSource->IsFlagSet( CLR_RT_HeapBlock::HB_Unmovable )) + { + currentSource += currentSource->DataSize(); + } + + CLR_UINT32 moveBytes = move * sizeof(*currentSource); + + relocCurrent->m_end = relocCurrent->m_start + moveBytes; + + //--// + + // + // Remove the old free block, copy the data, recreate the new free block. + // Merge with the following one if they are adjacent now. + // + CLR_RT_HeapBlock_Node* freeRegionNext = freeRegion->Next(); + + freeRegion->Unlink(); + + memmove( relocCurrent->m_destination, relocCurrent->m_start, moveBytes ); + + if(freeRegion_Size) + { + + freeRegion = freeRegion_hc->InsertInOrder( freeRegion + move, freeRegion_Size ); + + } + else + { + freeRegion = freeRegionNext; + + } + + if(fSlide == false) + { + CLR_RT_HeapBlock_Node* dst = currentSource_hc->InsertInOrder( (CLR_RT_HeapBlock_Node*)relocCurrent->m_start, move ); + + if(dst < freeRegion && freeRegion < (dst + dst->DataSize())) + { + freeRegion = dst; + } + + } + + CLR_RT_GarbageCollector::ValidateCluster( currentSource_hc ); + CLR_RT_GarbageCollector::ValidateCluster( freeRegion_hc ); + + relocCurrent++; + m_relocCount++; + } + else + { + freeRegion = freeRegion->Next(); + + } + + if(freeRegion->Next() == NULL) + { + + freeRegion = NULL; + freeRegion_hc = (CLR_RT_HeapCluster*)freeRegion_hc->Next(); + while(true) + { + CLR_RT_HeapCluster* freeRegion_hcNext = (CLR_RT_HeapCluster*)freeRegion_hc->Next(); if(!freeRegion_hcNext) break; + + freeRegion = freeRegion_hc->m_freeList.FirstNode(); if(freeRegion->Next()) break; + + freeRegion = NULL; + freeRegion_hc = freeRegion_hcNext; + } + if(!freeRegion) break; + + } + } + } + + currentSource_hc = (CLR_RT_HeapCluster*)currentSource_hc->Next(); + } + + if(m_relocCount) + { + ValidateHeap( g_CLR_RT_ExecutionEngine.m_heap ); + + Heap_Relocate(); + + ValidateHeap( g_CLR_RT_ExecutionEngine.m_heap ); + } +} + +void CLR_RT_GarbageCollector::Heap_Relocate_Prepare( RelocationRegion* blocks, size_t total ) +{ + NATIVE_PROFILE_CLR_CORE(); + m_relocBlocks = blocks; + m_relocTotal = total; + m_relocCount = 0; +} + +void CLR_RT_GarbageCollector::Heap_Relocate_AddBlock( CLR_UINT8* dst, CLR_UINT8* src, CLR_UINT32 length ) +{ + NATIVE_PROFILE_CLR_CORE(); + RelocationRegion* reloc = m_relocBlocks; + size_t count = m_relocCount; + + while(count) + { + if(reloc->m_start > src) + { + // + // Insert region, so they are sorted by start address. + // + memmove( &reloc[ 1 ], &reloc[ 0 ], count * sizeof(*reloc) ); + break; + } + + reloc++; + count--; + } + + reloc->m_start = src; + reloc->m_end = &src[ length ]; + reloc->m_destination = dst; + reloc->m_offset = (CLR_UINT32)(dst - src); + + if(++m_relocCount == m_relocTotal) + { + Heap_Relocate(); + } +} + +void CLR_RT_GarbageCollector::Heap_Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + if(m_relocCount) + { + RelocationRegion* relocBlocks = m_relocBlocks; + + CLR_UINT8* relocMinimum = relocBlocks->m_start; + CLR_UINT8* relocMaximum = relocBlocks->m_end; + + for(size_t i=0; i relocBlocks->m_start) relocMinimum = relocBlocks->m_start; + if(relocMaximum < relocBlocks->m_end ) relocMaximum = relocBlocks->m_end; + } + + m_relocMinimum = relocMinimum; + m_relocMaximum = relocMaximum; + + TestPointers_Remap(); + + Heap_Relocate_Pass( NULL ); + +#if defined(TINYCLR_PROFILE_NEW_ALLOCATIONS) + g_CLR_PRF_Profiler.TrackObjectRelocation(); +#endif + + ValidatePointers(); + + TestPointers_PopulateNew(); + + m_relocCount = 0; + } +} + +void CLR_RT_GarbageCollector::Heap_Relocate_Pass( RelocateFtn ftn ) +{ + NATIVE_PROFILE_CLR_CORE(); +#if TINYCLR_VALIDATE_HEAP > TINYCLR_VALIDATE_HEAP_0_None + m_relocWorker = ftn; +#endif + + TINYCLR_FOREACH_NODE(CLR_RT_HeapCluster,hc,g_CLR_RT_ExecutionEngine.m_heap) + { + CLR_RT_HeapBlock_Node* ptr = hc->m_payloadStart; + CLR_RT_HeapBlock_Node* end = hc->m_payloadEnd; + + + while(ptr < end) + { + CLR_RT_HEAPBLOCK_RELOCATE(ptr); + + ptr += ptr->DataSize(); + } + } + TINYCLR_FOREACH_NODE_END(); + + g_CLR_RT_ExecutionEngine.Relocate(); +} + +//--// + +void CLR_RT_GarbageCollector::Heap_Relocate( CLR_RT_HeapBlock* lst, CLR_UINT32 len ) +{ + NATIVE_PROFILE_CLR_CORE(); + while(len--) + { + CLR_RT_HEAPBLOCK_RELOCATE(lst); + + lst++; + } +} + +void CLR_RT_GarbageCollector::Heap_Relocate( void** ref ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_UINT8* dst = (CLR_UINT8*)*ref; + +#if TINYCLR_VALIDATE_HEAP > TINYCLR_VALIDATE_HEAP_0_None + if(g_CLR_RT_GarbageCollector.m_relocWorker) + { + g_CLR_RT_GarbageCollector.m_relocWorker( ref ); + } + else +#endif + { + if(dst >= g_CLR_RT_GarbageCollector.m_relocMinimum && dst < g_CLR_RT_GarbageCollector.m_relocMaximum) + { + RelocationRegion* relocBlocks = g_CLR_RT_GarbageCollector.m_relocBlocks; + size_t left = 0; + size_t right = g_CLR_RT_GarbageCollector.m_relocCount; + + while(left < right) + { + size_t center = (left + right) / 2; + RelocationRegion& relocCurrent = relocBlocks[ center ]; + + if(dst < relocCurrent.m_start) + { + right = center; + } + else if(dst >= relocCurrent.m_end) + { + left = center+1; + } + else + { + *ref = (void*)(dst + relocCurrent.m_offset); + + return; + } + } + } + } +} + +#if TINYCLR_VALIDATE_HEAP >= TINYCLR_VALIDATE_HEAP_3_Compaction + +bool CLR_RT_GarbageCollector::Relocation_JustCheck( void** ref ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_UINT8* dst = (CLR_UINT8*)*ref; + + if(dst) + { + ValidateBlockNotInFreeList( g_CLR_RT_ExecutionEngine.m_heap, (CLR_RT_HeapBlock_Node*)dst ); + } + + return true; +} + +#endif diff --git a/src/CLR/Core/GarbageCollector_ComputeReachabilityGraph.cpp b/src/CLR/Core/GarbageCollector_ComputeReachabilityGraph.cpp new file mode 100644 index 0000000000..d78a5bb6e1 --- /dev/null +++ b/src/CLR/Core/GarbageCollector_ComputeReachabilityGraph.cpp @@ -0,0 +1,296 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//--// + +void CLR_RT_GarbageCollector::MarkStack::Initialize( MarkStackElement* ptr, size_t num ) +{ + NATIVE_PROFILE_CLR_CORE(); + GenericNode_Initialize(); + + m_last = &ptr[ num-1 ]; + m_top = ptr; + + // + // Empty element to act a sentinel. + // + ptr->ptr = NULL; + ptr->num = 0; +#if defined(TINYCLR_VALIDATE_APPDOMAIN_ISOLATION) + ptr->appDomain = NULL; +#endif +} + +//--// + +bool CLR_RT_GarbageCollector::ComputeReachabilityGraphForSingleBlock( CLR_RT_HeapBlock** ptr ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock* obj = *ptr; if(obj == NULL || obj->IsAlive()) return true; + + return ComputeReachabilityGraphForMultipleBlocks( obj, 1 ); +} + + +bool CLR_RT_GarbageCollector::ComputeReachabilityGraphForMultipleBlocks( CLR_RT_HeapBlock* lst, CLR_UINT32 num ) +{ + NATIVE_PROFILE_CLR_CORE(); + + MarkStack * stackList; + MarkStackElement* stack; + MarkStackElement* stackLast; + +#define COMPUTEREACHABILITY_LOADSTATE() stackLast = g_CLR_RT_GarbageCollector.m_markStack->m_last; stack = g_CLR_RT_GarbageCollector.m_markStack->m_top; stackList = g_CLR_RT_GarbageCollector.m_markStack; +#define COMPUTEREACHABILITY_SAVESTATE() g_CLR_RT_GarbageCollector.m_markStack->m_last = stackLast; g_CLR_RT_GarbageCollector.m_markStack->m_top = stack; g_CLR_RT_GarbageCollector.m_markStack = stackList; + + COMPUTEREACHABILITY_LOADSTATE(); + + { + CLR_RT_HeapBlock* sub = NULL; + + while(true) + { + CLR_RT_HeapBlock* ptr = lst; + + if(num == 0) + { + if(stack->num == 0) + { + MarkStack* stackNext = (MarkStack*)stackList->Prev(); + + //finished with this MarkStack + if(stackNext->Prev() == NULL) + { + //finished marking + break; + } + else + { + COMPUTEREACHABILITY_SAVESTATE(); + g_CLR_RT_GarbageCollector.m_markStack = stackNext; + COMPUTEREACHABILITY_LOADSTATE(); + } + } + + ptr = stack->ptr; + + stack->ptr++; + stack->num--; + + if(stack->num == 0) + { + stack--; + +#if defined(TINYCLR_VALIDATE_APPDOMAIN_ISOLATION) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( stack->appDomain ); +#endif + } + } + else if(num > 1) + { + if(stack == stackLast) + { + MarkStack* stackNext = (MarkStack*)stackList->Next(); + + if(stackNext->Next() != NULL) + { + COMPUTEREACHABILITY_SAVESTATE(); + stackList = stackNext; + COMPUTEREACHABILITY_LOADSTATE(); + } + else + { + //try to allocate another stack list... + stackNext = NULL; + + //If there was no space for GC last time, don't bother trying to allocate again + if(!g_CLR_RT_GarbageCollector.m_fOutOfStackSpaceForGC) + { + for(int cElement = g_CLR_RT_GarbageCollector.c_minimumSpaceForGC; cElement >= 1; cElement /= 2) + { + CLR_UINT32 size = sizeof(MarkStack) + sizeof(MarkStackElement) * cElement; + + stackNext = (MarkStack*)CLR_RT_Memory::Allocate( size, CLR_RT_HeapBlock::HB_SpecialGCAllocation ); + + if(stackNext) + { + COMPUTEREACHABILITY_SAVESTATE(); + + stackNext->Initialize( (MarkStackElement*)(&stackNext[ 1 ]), (size_t)cElement ); + + g_CLR_RT_GarbageCollector.m_markStackList->LinkAtBack( stackNext ); + + g_CLR_RT_GarbageCollector.m_markStack = stackNext; + + COMPUTEREACHABILITY_LOADSTATE(); + + break; + } + } + } + + if(stackNext == NULL) + { + //Out of stack support space + //Set the failure flag and continue, ignoring lst, num + //The mark will complete later via MarkSlow + + g_CLR_RT_GarbageCollector.m_fOutOfStackSpaceForGC = true; + + lst = NULL; + num = 0; + continue; + } + } + } + + stack++; + + stack->ptr = lst+1; + stack->num = num-1; + +#if defined(TINYCLR_VALIDATE_APPDOMAIN_ISOLATION) + stack->appDomain = g_CLR_RT_ExecutionEngine.GetCurrentAppDomain(); +#endif + } + + + { + + lst = NULL; + num = 0; + + CLR_RT_HeapBlock::Debug_CheckPointer( ptr ); + + ptr->MarkAlive(); + + switch(ptr->DataType()) + { + case DATATYPE_OBJECT: + case DATATYPE_BYREF: + sub = ptr->Dereference(); + break; + + //--// + +#if defined(TINYCLR_APPDOMAINS) + case DATATYPE_TRANSPARENT_PROXY: + { + CLR_RT_AppDomain* appDomain = ptr->TransparentProxyAppDomain(); + + if(appDomain) + { + if(!appDomain->IsLoaded()) + { + //If the AppDomain is unloading, we no longer need to keep the reference around + ptr->SetTransparentProxyReference( NULL, NULL ); + } + else + { +#if defined(TINYCLR_VALIDATE_APPDOMAIN_ISOLATION) + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( ptr->TransparentProxyAppDomain() ); +#endif + sub = ptr->TransparentProxyDereference(); + } + } + } + break; +#endif + + //--// + + case DATATYPE_ARRAY_BYREF: + sub = (CLR_RT_HeapBlock*)ptr->Array(); + break; + + //--// + + case DATATYPE_CLASS: + case DATATYPE_VALUETYPE: + // + // This is the real object, mark all its fields. + // + lst = ptr + 1; + num = ptr->DataSize() - 1; + break; + + case DATATYPE_SZARRAY: + // + // If the array is full of reference types, mark each of them. + // + { + CLR_RT_HeapBlock_Array* array = (CLR_RT_HeapBlock_Array*)ptr; + + if(array->m_fReference) + { + lst = (CLR_RT_HeapBlock*)array->GetFirstElement(); + num = array->m_numOfElements; + } + } + break; + + case DATATYPE_REFLECTION: + break; + + case DATATYPE_DELEGATE_HEAD: + { + CLR_RT_HeapBlock_Delegate* dlg = (CLR_RT_HeapBlock_Delegate*)ptr; + + lst = &dlg->m_object; + num = 1; + } + break; + + case DATATYPE_BINARY_BLOB_HEAD: + { + CLR_RT_HeapBlock_BinaryBlob* blob = (CLR_RT_HeapBlock_BinaryBlob*)ptr; + + _ASSERTE(blob->BinaryBlobMarkingHandler() == NULL); + } + break; + + case DATATYPE_DELEGATELIST_HEAD: + { + CLR_RT_HeapBlock_Delegate_List* dlgList = (CLR_RT_HeapBlock_Delegate_List*)ptr; + + if(dlgList->m_flags & CLR_RT_HeapBlock_Delegate_List::c_Weak) + { + dlgList->ClearData(); + + g_CLR_RT_GarbageCollector.m_weakDelegates_Reachable.LinkAtBack( dlgList ); + } + else + { + lst = dlgList->GetDelegates(); + num = dlgList->m_length; + } + } + break; + } + + if(sub) + { + if(sub->IsAlive() == false) + { + lst = sub; + num = 1; + } + + sub = NULL; + } + + } + } + } + + COMPUTEREACHABILITY_SAVESTATE(); + + return true; +} + +//--// + diff --git a/src/CLR/Core/Hardware/Hardware.cpp b/src/CLR/Core/Hardware/Hardware.cpp new file mode 100644 index 0000000000..2ae5d5986b --- /dev/null +++ b/src/CLR/Core/Hardware/Hardware.cpp @@ -0,0 +1,222 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_HW_Hardware::CreateInstance() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + TINYCLR_HEADER(); + + TINYCLR_CLEAR(g_CLR_HW_Hardware); + + g_CLR_HW_Hardware.m_fInitialized = false; + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT CLR_HW_Hardware::Hardware_Initialize() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + TINYCLR_HEADER(); + + if(m_fInitialized == false) + { + Time_Initialize(); + + m_interruptData.m_HalQueue.Initialize( (CLR_HW_Hardware::HalInterruptRecord*)&g_scratchInterruptDispatchingStorage, InterruptRecords() ); + + m_interruptData.m_applicationQueue.DblLinkedList_Initialize (); + + m_interruptData.m_queuedInterrupts = 0; + + m_DebuggerEventsMask = 0; + m_MessagingEventsMask = 0; + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + for(int i = 0; i < HalSystemConfig.c_MaxDebuggers; i++) + { + m_DebuggerEventsMask |= ExtractEventFromTransport( HalSystemConfig.DebuggerPorts[ i ] ); + } +#endif + + for(int i = 0; i < HalSystemConfig.c_MaxMessaging; i++) + { + m_MessagingEventsMask |= ExtractEventFromTransport( HalSystemConfig.MessagingPorts[ i ] ); + } + + m_wakeupEvents = c_Default_WakeupEvents | m_DebuggerEventsMask; + m_powerLevel = PowerLevel__Active; + + m_fInitialized = true; + } + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +//--// + +HRESULT CLR_HW_Hardware::DeleteInstance() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + TINYCLR_HEADER(); + + g_CLR_HW_Hardware.Hardware_Cleanup(); + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +void CLR_HW_Hardware::Hardware_Cleanup() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + if(m_fInitialized == true) + { + m_fInitialized = false; + } +} + +//--// + +void CLR_HW_Hardware::PrepareForGC() +{ + NATIVE_PROFILE_CLR_HARDWARE(); +} + +void CLR_HW_Hardware::ProcessActivity() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + + for(int i=0; i<10; i++) + { + if(!HAL_CONTINUATION::Dequeue_And_Execute()) break; + } + + TINYCLR_FOREACH_MESSAGING(msg) + { + if(!msg.IsDebuggerInitialized()) + { + msg.InitializeDebugger(); + } + msg.PurgeCache(); + } + TINYCLR_FOREACH_MESSAGING_END(); + + TINYCLR_FOREACH_DEBUGGER(dbg) + { + dbg.PurgeCache(); + } + TINYCLR_FOREACH_DEBUGGER_END(); + + UINT32 events = ::Events_Get( m_wakeupEvents ); + UINT32 eventsCLR = 0; + + if(events & m_MessagingEventsMask) + { + TINYCLR_FOREACH_MESSAGING(msg) + { + msg.ProcessCommands(); + } + TINYCLR_FOREACH_MESSAGING_END(); + } + + if(events & m_DebuggerEventsMask) + { + TINYCLR_FOREACH_DEBUGGER(dbg) + { + dbg.ProcessCommands(); + } + TINYCLR_FOREACH_DEBUGGER_END(); + +#if defined(PLATFORM_ARM) + if(CLR_EE_DBG_IS(RebootPending)) + { +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Rebooting...\r\n" ); +#endif + + if(!CLR_EE_REBOOT_IS(ClrOnly)) + { + CLR_RT_ExecutionEngine::Reboot( true ); + } + } +#endif + } + + if( events & (SYSTEM_EVENT_FLAG_COM_IN | SYSTEM_EVENT_FLAG_COM_OUT) ) + { + eventsCLR |= CLR_RT_ExecutionEngine::c_Event_SerialPort; + } + + // UNDONE: FIXME: if(events & SYSTEM_EVENT_I2C_XACTION) + //{ + // eventsCLR |= CLR_RT_ExecutionEngine::c_Event_I2C; + //} + + if((events & SYSTEM_EVENT_HW_INTERRUPT) +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + || (!CLR_EE_DBG_IS(Stopped) && !g_CLR_HW_Hardware.m_interruptData.m_applicationQueue.IsEmpty()) +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + ) + { + ProcessInterrupts(); + } + + if(events & SYSTEM_EVENT_FLAG_SOCKET) + { + eventsCLR |= CLR_RT_ExecutionEngine::c_Event_Socket; + } + + if(events & SYSTEM_EVENT_FLAG_IO) + { + eventsCLR |= CLR_RT_ExecutionEngine::c_Event_IO; + } + + // UNDONE: FIXME: if(events & SYSTEM_EVENT_FLAG_CHARGER_CHANGE) + //{ + // static UINT32 lastStatus; + // UINT32 status; + + // if(::Charger_Status( status )) + // { + // status &= CHARGER_STATUS_ON_AC_POWER; + + // if(lastStatus != status) + // { + // lastStatus = status; + + // eventsCLR |= CLR_RT_ExecutionEngine::c_Event_Battery; + // } + // } + //} + + if(eventsCLR) + { + g_CLR_RT_ExecutionEngine.SignalEvents( eventsCLR ); + } +} + +//--// + +// UNDONE: FIXME: void CLR_HW_Hardware::Screen_Flush( CLR_GFX_Bitmap& bitmap, CLR_UINT16 x, CLR_UINT16 y, CLR_UINT16 width, CLR_UINT16 height ) +//{ +// NATIVE_PROFILE_CLR_HARDWARE(); +// CLR_INT32 widthMax = LCD_SCREEN_WIDTH; +// CLR_INT32 heightMax = LCD_SCREEN_HEIGHT; +// +// if((CLR_UINT32)(x + width) > bitmap.m_bm.m_width ) width = bitmap.m_bm.m_width - x; +// if((CLR_UINT32)(y + height) > bitmap.m_bm.m_height) height = bitmap.m_bm.m_height - y; +// +// if(bitmap.m_bm.m_width != widthMax ) return; +// if(bitmap.m_bm.m_height != heightMax ) return; +// if(bitmap.m_bm.m_bitsPerPixel != CLR_GFX_BitmapDescription::c_NativeBpp) return; +// if(bitmap.m_palBitmap.transparentColor != PAL_GFX_Bitmap::c_InvalidColor ) return; +// +// LCD_BitBltEx( x, y, width, height, bitmap.m_palBitmap.data ); +//} + +//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--// + diff --git a/src/CLR/Core/Hardware/Hardware.vcxproj b/src/CLR/Core/Hardware/Hardware.vcxproj new file mode 100644 index 0000000000..60ed9ddabb --- /dev/null +++ b/src/CLR/Core/Hardware/Hardware.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + {5D50772E-DAC8-407D-972F-37DEB4450B72} + Win32Proj + Hardware + 10.0.14393.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/src/CLR/Core/Hardware/Hardware.vcxproj.filters b/src/CLR/Core/Hardware/Hardware.vcxproj.filters new file mode 100644 index 0000000000..c750e91500 --- /dev/null +++ b/src/CLR/Core/Hardware/Hardware.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/src/CLR/Core/Hardware/Hardware_stub.cpp b/src/CLR/Core/Hardware/Hardware_stub.cpp new file mode 100644 index 0000000000..4f4afe089e --- /dev/null +++ b/src/CLR/Core/Hardware/Hardware_stub.cpp @@ -0,0 +1,50 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_HW_Hardware::CreateInstance() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + TINYCLR_HEADER(); + TINYCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT CLR_HW_Hardware::Hardware_Initialize() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + TINYCLR_HEADER(); + TINYCLR_NOCLEANUP_NOLABEL(); +} + +//--// + +HRESULT CLR_HW_Hardware::DeleteInstance() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + TINYCLR_HEADER(); + TINYCLR_NOCLEANUP_NOLABEL(); +} + +void CLR_HW_Hardware::Hardware_Cleanup() +{ + NATIVE_PROFILE_CLR_HARDWARE(); +} + +//--// + +void CLR_HW_Hardware::PrepareForGC() +{ + NATIVE_PROFILE_CLR_HARDWARE(); +} + +void CLR_HW_Hardware::ProcessActivity() +{ + NATIVE_PROFILE_CLR_HARDWARE(); +} + +//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--//--// diff --git a/src/CLR/Core/Hardware/Hardware_stub.vcxproj b/src/CLR/Core/Hardware/Hardware_stub.vcxproj new file mode 100644 index 0000000000..3e1c58b63d --- /dev/null +++ b/src/CLR/Core/Hardware/Hardware_stub.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + {31253D7F-147E-49A3-BC0D-E0ADE6CF040B} + Win32Proj + Hardware_stub + 10.0.14393.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/src/CLR/Core/Hardware/Hardware_stub.vcxproj.filters b/src/CLR/Core/Hardware/Hardware_stub.vcxproj.filters new file mode 100644 index 0000000000..d5de8ea40f --- /dev/null +++ b/src/CLR/Core/Hardware/Hardware_stub.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/src/CLR/Core/HeapPersistence/HeapPersistence.vcxproj b/src/CLR/Core/HeapPersistence/HeapPersistence.vcxproj new file mode 100644 index 0000000000..21757da707 --- /dev/null +++ b/src/CLR/Core/HeapPersistence/HeapPersistence.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + {BC2245B0-32E0-410E-B3F2-E2BFA0B503B3} + Win32Proj + HeapPersistence + 10.0.14393.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/src/CLR/Core/HeapPersistence/HeapPersistence.vcxproj.filters b/src/CLR/Core/HeapPersistence/HeapPersistence.vcxproj.filters new file mode 100644 index 0000000000..10f27cdafc --- /dev/null +++ b/src/CLR/Core/HeapPersistence/HeapPersistence.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/src/CLR/Core/HeapPersistence/HeapPersistence_stub.vcxproj b/src/CLR/Core/HeapPersistence/HeapPersistence_stub.vcxproj new file mode 100644 index 0000000000..ce07279c63 --- /dev/null +++ b/src/CLR/Core/HeapPersistence/HeapPersistence_stub.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + {4646F661-9505-45C2-9573-8409A9DD1149} + Win32Proj + HeapPersistence_stub + 10.0.14393.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/src/CLR/Core/HeapPersistence/HeapPersistence_stub.vcxproj.filters b/src/CLR/Core/HeapPersistence/HeapPersistence_stub.vcxproj.filters new file mode 100644 index 0000000000..f5d721ee42 --- /dev/null +++ b/src/CLR/Core/HeapPersistence/HeapPersistence_stub.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/src/CLR/Core/HeapPersistence/Heap_Persistence.cpp b/src/CLR/Core/HeapPersistence/Heap_Persistence.cpp new file mode 100644 index 0000000000..da60dfb94e --- /dev/null +++ b/src/CLR/Core/HeapPersistence/Heap_Persistence.cpp @@ -0,0 +1,1582 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include + +//--// + +#if defined(TINYCLR_TRACE_PERSISTENCE) + +void CLR_RT_Persistence_Manager::Trace_Emit( LPSTR szText ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + char rgBuffer[ 512 ]; + LPSTR szBuffer = rgBuffer; + size_t iBuffer = MAXSTRLEN(rgBuffer); +} + +void CLR_RT_Persistence_Manager::Trace_Printf( LPCSTR format, ... ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + char rgBuffer[ 512 ]; + LPSTR szBuffer = rgBuffer; + size_t iBuffer = MAXSTRLEN(rgBuffer); + va_list arg; + + va_start( arg, format ); + + CLR_SafeSprintfV( szBuffer, iBuffer, format, arg ); + + va_end( arg ); + + //--// + + Trace_Emit( rgBuffer ); +} + +void CLR_RT_Persistence_Manager::Trace_DumpIdentity( LPSTR& szBuffer, size_t& iBuffer, CLR_RT_HeapBlock_WeakReference_Identity* identity ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + CLR_RT_ReflectionDef_Index val; + CLR_RT_TypeDef_Instance inst; + + val.InitializeFromHash( identity->m_selectorHash ); + + if(inst.InitializeFromReflection( val, NULL )) + { + CLR_SafeSprintf( szBuffer, iBuffer, " PRI:%9d ", identity->m_priority ); + + g_CLR_RT_TypeSystem.BuildTypeName( inst, szBuffer, iBuffer ); + + CLR_SafeSprintf( szBuffer, iBuffer, ":%d", identity->m_id ); + } +} + +//--// + +void CLR_RT_Persistence_Manager::Trace_DumpState( LPCSTR szText, FLASH_WORD* dst, ObjectHeader* oh, CLR_RT_HeapBlock_WeakReference* wr ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + char rgBuffer[ 512 ]; + LPSTR szBuffer = rgBuffer; + size_t iBuffer = MAXSTRLEN(rgBuffer); + CLR_RT_HeapBlock_WeakReference_Identity* identity = NULL; + + if(szText) + { + CLR_SafeSprintf( szBuffer, iBuffer, "%-20s", szText ); + } + + if(dst) + { + CLR_SafeSprintf( szBuffer, iBuffer, " STG:%08X", (size_t)dst ); + } + + if(wr) + { + CLR_RT_HeapBlock_Array* array = wr->m_targetSerialized; + + CLR_SafeSprintf( szBuffer, iBuffer, " %08X(%5u:%5u)", (size_t)array, wr->m_identity.m_length, array ? array->m_numOfElements : (CLR_UINT32)-1 ); + } + + if(oh) + { + identity = &oh->m_identity; + } + else if(wr) + { + identity = &wr->m_identity; + } + + if(identity) + { + Trace_DumpIdentity( szBuffer, iBuffer, identity ); + } + + //--// + + Trace_Emit( rgBuffer ); +} + +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +bool CLR_RT_Persistence_Manager::ObjectHeader::Initialize( CLR_RT_HeapBlock_WeakReference* wr ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + if(!wr) return false; + + CLR_RT_HeapBlock_Array* array = wr->m_targetSerialized; if(!array) return false; + + m_signature = c_Version; + m_status = c_InUseBlock; + + m_identity = wr->m_identity; + m_identity.m_crc = m_identity.ComputeCRC( array->GetFirstElement(), m_identity.m_length ); + m_identity.m_flags &= CLR_RT_HeapBlock_WeakReference::WR_MaskForStorage; + + memcpy( &m_object, array, sizeof(m_object) ); + m_object.SetFlags( CLR_RT_HeapBlock::HB_Pinned | CLR_RT_HeapBlock::HB_Alive ); + + m_crcIdentity = ComputeCRC(); + + return true; +} + +bool CLR_RT_Persistence_Manager::ObjectHeader::IsGood( bool fIncludeData ) const +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + if(HasGoodSignature() == false) return false; + + if(m_crcIdentity != ComputeCRC()) return false; + + if(fIncludeData) + { + if(IsInUse() == false) return false; + + if(m_identity.m_crc != m_identity.ComputeCRC( (const CLR_UINT8*)&this[ 1 ], m_identity.m_length )) return false; + } + + return true; +} + +void CLR_RT_Persistence_Manager::ObjectHeader::Delete() +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + CLR_UINT32 sig = c_DeletedBlock; + + Bank::Write( (FLASH_WORD*)&m_status, (FLASH_WORD*)&sig, sizeof(sig) ); +} + +CLR_UINT32 CLR_RT_Persistence_Manager::ObjectHeader::Length() const +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + return ObjectHeader::Length( m_identity.m_length ); +} + +CLR_UINT32 CLR_RT_Persistence_Manager::ObjectHeader::Length( const CLR_RT_HeapBlock_WeakReference* ref ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + return ObjectHeader::Length( ref->m_identity.m_length ); +} + +CLR_UINT32 CLR_RT_Persistence_Manager::ObjectHeader::Length( CLR_UINT32 data ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + return ROUNDTOMULTIPLE(sizeof(ObjectHeader) + data,FLASH_WORD); +} + +CLR_RT_Persistence_Manager::ObjectHeader* CLR_RT_Persistence_Manager::ObjectHeader::Next() const +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + ObjectHeader *next = (ObjectHeader*)((CLR_UINT8*)this + this->Length()); + return next; +} + +CLR_UINT32 CLR_RT_Persistence_Manager::ObjectHeader::ComputeCRC() const +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + CLR_UINT32 crc; + + crc = SUPPORT_ComputeCRC( &m_identity, sizeof(m_identity), 0 ); + crc = SUPPORT_ComputeCRC( &m_object , sizeof(m_object ), crc ); + + return crc; +} + +CLR_RT_Persistence_Manager::ObjectHeader* CLR_RT_Persistence_Manager::ObjectHeader::Find( FLASH_WORD* start, FLASH_WORD* end ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + + end = Bank::DecrementPointer( end, sizeof(ObjectHeader) ); + + while(start < end) + { + ObjectHeader* oh = (ObjectHeader*)start; + + if(oh->HasGoodSignature()) + { + return oh; + } + + start++; + } + + return NULL; +} + +//--//--//--//--//--// + +void CLR_RT_Persistence_Manager::BankHeader::Initialize() +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + m_signature = c_Version; + m_status = c_InUseBank; + + m_sequenceNumber = 0xFFFFFFFF; +} + +bool CLR_RT_Persistence_Manager::BankHeader::IsGood() const +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + return (HasGoodSignature() && IsInUse() && m_sequenceNumber != 0); +} + +void CLR_RT_Persistence_Manager::BankHeader::Delete() +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + CLR_UINT32 sig = c_DeletedBank; + + Bank::Write( (FLASH_WORD*)&m_status, (FLASH_WORD*)&sig, sizeof(sig) ); +} + +CLR_RT_Persistence_Manager::BankHeader* CLR_RT_Persistence_Manager::BankHeader::Find( FLASH_WORD* start, FLASH_WORD* end ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + + end = Bank::DecrementPointer( end, sizeof(BankHeader) ); + + while(start < end) + { + BankHeader* bh = (BankHeader*)start; + + if(bh->IsGood()) + { + return bh; + } + + start++; + } + + return NULL; +} + +//--//--//--//--//--// + + + +bool CLR_RT_Persistence_Manager::Bank::Initialize( UINT32 kind ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + + // Bank may reinitialize again, have to keep the m_start for the buffer address. + BYTE * ewrBuffer = (BYTE *)m_start; + TINYCLR_CLEAR(*this); + + //--// + + if(!m_stream.Initialize( (kind & BlockRange::USAGE_MASK) )) + { + return false; + } + + const BlockDeviceInfo* deviceInfo = m_stream.Device->GetDeviceInfo(); + + if (!deviceInfo->Attribute.SupportsXIP) + { + + // if already assignd, don't allocated again. + if (ewrBuffer == NULL) + { + ewrBuffer = (BYTE*)CLR_RT_Memory::Allocate_And_Erase( m_stream.Length, CLR_RT_HeapBlock ::HB_Unmovable ); + // no buffer, no EWR + if (!ewrBuffer) + { + m_start = NULL; + m_end = NULL; + return false; + } + } + m_start =(FLASH_WORD*) ewrBuffer; + m_end =(FLASH_WORD*)(ewrBuffer + m_stream.Length); + + + // else it is assigned already. No need to do it. + + m_stream.Device->Read( m_stream.BaseAddress, m_stream.Length, (BYTE *)m_start ); + } + else + { + m_start = (FLASH_WORD *)m_stream.BaseAddress; + + // avoid error of getting the address at the last block end address, which will fall out of the + // address range, calcuate it directly from m_start + m_end = (FLASH_WORD *)((UINT32)m_start + m_stream.Length); + } + + m_totalBytes = (CLR_UINT32)((CLR_UINT8*)m_end - (CLR_UINT8*)m_start) - sizeof(BankHeader); + m_totalSafeBytes = m_totalBytes * (100 - c_SafetyMargin) / 100; + + m_bankHeader = BankHeader::Find( m_start, m_end ); + + if(m_bankHeader) + { + ObjectHeader* ptr = m_bankHeader->FirstObjectHeader(); + + m_current = (FLASH_WORD*)ptr; + + while((ptr = ObjectHeader::Find( (FLASH_WORD*)ptr, m_end )) != NULL) + { + while(ptr->IsGood( false )) + { + ptr = ptr->Next(); + + m_current = (FLASH_WORD*)ptr; + + } + + ptr = (ObjectHeader*)Bank::IncrementPointer( (FLASH_WORD*)ptr, sizeof(FLASH_WORD) ); + } + } + + return true; + +} + +bool CLR_RT_Persistence_Manager::Bank::IsGood() const +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + return m_bankHeader != NULL && m_current != NULL; +} + +bool CLR_RT_Persistence_Manager::Bank::Erase( int& blockIndex ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + const BlockDeviceInfo* deviceInfo = m_stream.Device->GetDeviceInfo(); + bool result = TRUE; + const BlockRegionInfo* pRegion = NULL; + const BlockRange* pRange = NULL; + + pRegion = &deviceInfo->Regions[ m_stream.RegionIndex ]; + + pRange = &pRegion->BlockRanges[ m_stream.RangeIndex ]; + + if(pRange->GetBlockCount() <= (CLR_UINT32)blockIndex) + { + return false; + } + + result = (TRUE == m_stream.Device->EraseBlock( pRegion->BlockAddress( pRange->StartBlock + blockIndex ) )); + + blockIndex++; + + if(!deviceInfo->Attribute.SupportsXIP) + { // reload the page. + this->ReloadNonXIPBufferData(); + } + + return result; +} + +void CLR_RT_Persistence_Manager::Bank::EraseAll() +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + + int idx = 0; + + while(Erase( idx )) + { + Watchdog_ResetCounter(); + } +} + +bool CLR_RT_Persistence_Manager::Bank::Format() +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + BankHeader bh; bh.Initialize(); + FLASH_WORD* ptr = m_start; + FLASH_WORD* ptrEnd = Bank::DecrementPointer( m_end, sizeof(bh) ); + + while(ptr < ptrEnd) + { + if(Bank::Write( ptr, (FLASH_WORD*)&bh, sizeof(bh) )) + { + return this->Initialize( m_stream.Usage ); + } + + Trace_Printf( "FAULT WRITING %08X(%d)", (size_t)ptr, sizeof(bh) ); + + Bank::Invalidate( ptr, BankHeader::c_Version, sizeof(bh) ); + + ptr++; + } + + return false; +} + +bool CLR_RT_Persistence_Manager::Bank::SetSequence( CLR_UINT32 sequenceNumber ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + if(m_bankHeader) + { + for(int retries=0; retries<10; retries++) + { + if(Bank::Write( (FLASH_WORD*)&m_bankHeader->m_sequenceNumber, &sequenceNumber, sizeof(sequenceNumber) )) + { + return true; + } + } + } + + return false; +} + +void CLR_RT_Persistence_Manager::Bank::Switch( Bank& other ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + Bank tmp; + + tmp = *this; *this = other; other = tmp; +} + +//--// + +CLR_RT_Persistence_Manager::ObjectHeader* CLR_RT_Persistence_Manager::Bank::RecoverHeader( CLR_RT_HeapBlock_WeakReference* ref ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + if(ref && ref->m_targetSerialized) + { + ObjectHeader* ptr = (ObjectHeader*)((CLR_UINT8*)ref->m_targetSerialized - offsetof(ObjectHeader,m_object)); + + if((FLASH_WORD*)ptr >= m_start && (FLASH_WORD*)ptr < m_end && ptr->IsGood( true )) + { + return ptr; + } + } + + return NULL; +} + +bool CLR_RT_Persistence_Manager::Bank::WriteHeader( CLR_RT_HeapBlock_WeakReference* ref, ObjectHeader*& pOH, FLASH_WORD*& pData ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + ObjectHeader oh; + + pOH = NULL; + pData = NULL; + + if(m_current && oh.Initialize( ref )) + { + CLR_UINT32 length = oh.Length() + sizeof(ObjectHeader) + sizeof(FLASH_WORD); + FLASH_WORD* endMarker = Bank::DecrementPointer( m_end, length ); + + while(m_current < endMarker) + { + if(Bank::CanWrite( m_current, length )) + { + Trace_DumpState( "Saving header", m_current, &oh, ref ); + + if(Bank::Write( m_current, (FLASH_WORD*)&oh, sizeof(oh) )) + { + pOH = (ObjectHeader*)m_current; + + pData = Bank::IncrementPointer( m_current, sizeof(oh) ); + + m_current = Bank::IncrementPointer( m_current, oh.Length() ); + return true; + } + + Trace_Printf( "FAULT WRITING %08X(%d)", (size_t)m_current, sizeof(oh) ); + } + + Bank::Invalidate( m_current, ObjectHeader::c_Version, sizeof(oh) ); + + m_current++; + } + } + + return false; +} + +void CLR_RT_Persistence_Manager::Bank::ReloadNonXIPBufferData() +{ + UINT32 lengthInBytes = 0; + + // buffer is allocated at initialize, no need to allocated, it is already point to by m_start; + + lengthInBytes = (UINT32)m_end - (UINT32)m_start; + m_stream.Device->Read( m_stream.BaseAddress, lengthInBytes, (BYTE*) m_start ); +} + + +bool CLR_RT_Persistence_Manager::Bank::WriteNonXIPData(FLASH_WORD* dst, CLR_UINT32 length) +{ + const BlockDeviceInfo *deviceInfo = m_stream.Device->GetDeviceInfo(); + + bool fRes = true; + + // if SupportsXIP then error? + if (deviceInfo->Attribute.SupportsXIP) + { +#if !defined(BUILD_RTM) + CLR_Debug::Printf("Error at try to write Non-XIP but found XIP\r\n"); +#endif + return false; + } + + UINT32 offset = (UINT32)dst - (UINT32)m_start; + + if(!m_stream.Device->Write( m_stream.BaseAddress + offset, length, (BYTE *)dst, FALSE )) + { + fRes=false; + } + + return fRes; +} + +bool CLR_RT_Persistence_Manager::Bank::FindBankWriteNonXIPData( FLASH_WORD* dst, CLR_UINT32 length ) +{ + if (((UINT32)dst >=(UINT32)g_CLR_RT_Persistence_Manager.m_bankA.m_start) && ((UINT32)dst <(UINT32)g_CLR_RT_Persistence_Manager.m_bankA.m_end)) + return g_CLR_RT_Persistence_Manager.m_bankA.WriteNonXIPData( dst, length ); + + else if (((UINT32)dst >=(UINT32)g_CLR_RT_Persistence_Manager.m_bankB.m_start) && ((UINT32)dst <(UINT32)g_CLR_RT_Persistence_Manager.m_bankB.m_end)) + return g_CLR_RT_Persistence_Manager.m_bankB.WriteNonXIPData( dst, length ); + + else + { +#if !defined(BUILD_RTM) + CLR_Debug::Printf("No right Persistence bank address found!!! (%x)\r\n",(UINT32)dst ); +#endif + return false; + } +} + + +//--// + +bool CLR_RT_Persistence_Manager::Bank::CanWrite( FLASH_WORD* dst, CLR_UINT32 length ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + + for(CLR_UINT32 pos=0; posGetDeviceInfo(); + + if (deviceInfo->Attribute.SupportsXIP) + { + if(!g_CLR_RT_Persistence_Manager.m_bankA.m_stream.Device->Write( (UINT32)dst, length,(BYTE *)src, FALSE )) + { + fRes=false; + } + + } + else + { + //update the buffer + memcpy( dst, src, length ); + fRes = FindBankWriteNonXIPData( dst, length ); + } + + return fRes; +} + +void CLR_RT_Persistence_Manager::Bank::Invalidate( FLASH_WORD* dst, FLASH_WORD match, CLR_UINT32 length ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + + const BlockDeviceInfo *deviceInfo = g_CLR_RT_Persistence_Manager.m_bankA.m_stream.Device->GetDeviceInfo(); + FLASH_WORD * start_dst = dst; + + FLASH_WORD data=c_Invalidated; + + if (deviceInfo->Attribute.SupportsXIP) + { + for(CLR_UINT32 pos=0; posWrite( (UINT32)dst, sizeof(FLASH_WORD), (BYTE *) &data, FALSE ); + } + dst++; + } + } + else + { + // update the buffer + for(CLR_UINT32 pos=0; posMaxSectorWrite_uSec() * (c_MaxWriteBurst / sizeof(FLASH_WORD)) * 2 + 1000 - 1) / 1000; + m_margin_BlockErase = (m_bankA.m_stream.Device->MaxBlockErase_uSec() * 2 + 1000 - 1) / 1000; + if(m_bankB.IsGood()) + { + if(m_bankA.IsGood() == false || m_bankA.GetBankHeader()->m_sequenceNumber < m_bankB.GetBankHeader()->m_sequenceNumber) + { + m_bankA.Switch( m_bankB ); + } + } + + if(m_bankA.IsGood() == false) + { + m_bankA.EraseAll ( ); + m_bankA.Format ( ); + m_bankA.SetSequence( 1 ); + } + +#if defined(TINYCLR_TRACE_PERSISTENCE) + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_WeakReference,weak,g_CLR_RT_ExecutionEngine.m_weakReferences) + { + Trace_DumpState( "Restored from RAM", NULL, NULL, weak ); + } + TINYCLR_FOREACH_NODE_END(); +#endif + + if(m_bankA.IsGood()) + { + ObjectHeader* ptr = m_bankA.GetBankHeader()->FirstObjectHeader(); + + while((ptr = ObjectHeader::Find( (FLASH_WORD*)ptr, m_bankA.m_end )) != NULL) + { + while(ptr->IsGood( false )) + { + if(ptr->IsGood( true )) + { + CLR_RT_HeapBlock_WeakReference* weakRef; + + if(SUCCEEDED(CLR_RT_HeapBlock_WeakReference::CreateInstance( weakRef ))) + { + weakRef->m_identity = ptr->m_identity; + weakRef->m_targetSerialized = &ptr->m_object; + + weakRef->InsertInPriorityOrder(); + + weakRef->m_identity.m_flags |= CLR_RT_HeapBlock_WeakReference::WR_Persisted; + weakRef->m_identity.m_flags |= CLR_RT_HeapBlock_WeakReference::WR_Restored; + + Trace_DumpState( "Restored from FLASH", (FLASH_WORD*)ptr, ptr, weakRef ); + } + } + else + { + Trace_DumpState( "Skip deleted item", (FLASH_WORD*)ptr, ptr, NULL ); + } + + ptr = ptr->Next(); + } + + ptr = (ObjectHeader*)Bank::IncrementPointer( (FLASH_WORD*)ptr, sizeof(FLASH_WORD) ); + } + } + + g_CLR_RT_ExecutionEngine.LoadDownloadedAssemblies(); + + EnqueueNextCallback(); +} + +void CLR_RT_Persistence_Manager::EraseAll() +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + if(!m_bankA.Initialize( BlockRange::BLOCKTYPE_STORAGE_A )) return; + if(!m_bankB.Initialize( BlockRange::BLOCKTYPE_STORAGE_B )) return; + + m_bankA.EraseAll(); + m_bankB.EraseAll(); +} + +//--// + +CLR_RT_Persistence_Manager::ObjectHeader* CLR_RT_Persistence_Manager::RecoverHeader( CLR_RT_HeapBlock_WeakReference* weak ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + ObjectHeader* oh; + + oh = m_bankA.RecoverHeader( weak ); + if(oh == NULL) + { + oh = m_bankB.RecoverHeader( weak ); + } + + return oh; +} + +void CLR_RT_Persistence_Manager::InvalidateEntry( CLR_RT_HeapBlock_WeakReference* weak ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + if(m_pending_object == weak) + { + if(m_pending_header) + { + Trace_DumpState( "Abort object", (FLASH_WORD*)m_pending_header, m_pending_header, weak ); + + m_pending_header->Delete(); + + m_pending_header = NULL; + } + + m_pending_object = NULL; + } + + if(weak->m_identity.m_flags & CLR_RT_HeapBlock_WeakReference::WR_Persisted) + { + ObjectHeader* oh = RecoverHeader( weak ); + if(oh != NULL) + { + Trace_DumpState( "Remove object", (FLASH_WORD*)oh, oh, weak ); + oh->Delete(); + } + + weak->m_identity.m_flags &= ~CLR_RT_HeapBlock_WeakReference::WR_Persisted; + } + + weak->m_targetSerialized = NULL; + weak->m_identity.m_flags &= ~CLR_RT_HeapBlock_WeakReference::WR_Restored; + + switch(m_state) + { + case STATE_FlushNextObject : break; + case STATE_Idle : m_state = STATE_FlushNextObject; EnqueueNextCallback() ; break; + case STATE_Erase : break; + case STATE_EraseSector : break; + ////////////////////////////// + case STATE_CopyToOtherBank : + case STATE_CopyBackToRam : + case STATE_SwitchBank : m_state = STATE_Erase; Trace_Printf( "Aborting erase" ); break; + } +} + +//--// + +void CLR_RT_Persistence_Manager::Callback( void* arg ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + + if(g_CLR_RT_Persistence_Manager.AdvanceState( false )) + { + g_CLR_RT_Persistence_Manager.EnqueueNextCallback(); + } + else + { + Trace_Printf( "Content synchronized!!" ); + } + +} + +void CLR_RT_Persistence_Manager::EnqueueNextCallback() +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + m_completion.Abort ( ); + m_completion.EnqueueDelta( 50000 ); +} + +void CLR_RT_Persistence_Manager::Relocate() +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + if(m_pending_object) CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_pending_object ); + if(m_pending_header) CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_pending_header ); + if(m_pending_src ) CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_pending_src ); + if(m_pending_dst ) CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_pending_dst ); +} + +bool CLR_RT_Persistence_Manager::AdvanceState( bool force ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + CLR_RT_GarbageCollector::RelocationRegion relocHelper[ CLR_RT_GarbageCollector::c_minimumSpaceForCompact ]; + while(true) + { + ::Watchdog_ResetCounter(); + switch(m_state) + { + case STATE_FlushNextObject: + { + if(!force && g_CLR_RT_ExecutionEngine.IsThereEnoughIdleTime( m_margin_BurstWrite ) == false) return true; + + if(m_pending_object == NULL) + { + CLR_UINT32 usedBytes = 0; + + // + // The list is sorted in priority order, we save higher priority objects first. + // + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_WeakReference,weak,g_CLR_RT_ExecutionEngine.m_weakReferences) + { + if(weak->m_identity.m_flags & CLR_RT_HeapBlock_WeakReference::WR_SurvivePowerdown) + { + CLR_RT_HeapBlock_Array* array = weak->m_targetSerialized; + + if(array) + { + usedBytes += ObjectHeader::Length( weak ); + + if((weak->m_identity.m_flags & CLR_RT_HeapBlock_WeakReference::WR_Persisted) == 0) + { + if(m_bankA.WriteHeader( weak, m_pending_header, m_pending_dst )) + { + m_pending_object = weak; + m_pending_src = (FLASH_WORD*)array->GetFirstElement(); + m_pending_size = array->m_numOfElements; + } + else + { + m_pending_src = NULL; + m_pending_size = 0; + + if(usedBytes < m_bankA.m_totalSafeBytes) + { + Trace_DumpState( "Triggering copy", NULL, NULL, weak ); + + // + // We found a non-persisted object that would fit in the storage if we compact. + // + // Let's start the bank switch. + // + m_state = STATE_Erase; + return true; + } + + Trace_DumpState( "Skipping block", NULL, NULL, weak ); + + // + // We don't have enough safety margin. + // + // Nothing to gain from a bank swicth. + // + } + + break; + } + } + } + } + TINYCLR_FOREACH_NODE_END(); + + if(m_pending_object == NULL) + { + m_state = STATE_Idle; + return false; + } + } + + Trace_DumpState( "Saving block", m_pending_dst, m_pending_header, m_pending_object ); + + CLR_UINT32 len = m_pending_size; if(len > c_MaxWriteBurst) len = c_MaxWriteBurst; + + if(Bank::Write( m_pending_dst, m_pending_src, len )) + { + m_pending_dst = Bank::IncrementPointer( m_pending_dst, len ); + m_pending_src = Bank::IncrementPointer( m_pending_src, len ); + m_pending_size -= len; + + if(m_pending_size == 0) + { + if(m_pending_object->m_identity.m_flags & CLR_RT_HeapBlock_WeakReference::WR_ArrayOfBytes) + { + CLR_UINT8* dst = (CLR_UINT8*)&m_pending_header->m_object; + CLR_UINT8* src = (CLR_UINT8*) m_pending_object->m_targetSerialized; + CLR_UINT32 len = m_pending_object->m_targetSerialized->DataSize() * sizeof(CLR_RT_HeapBlock); + + Trace_Printf( "Relocate Array - Flush: %08X %08X %d", (size_t)dst, (size_t)src, len ); + + g_CLR_RT_GarbageCollector.Heap_Relocate_Prepare ( relocHelper, ARRAYSIZE(relocHelper) ); + g_CLR_RT_GarbageCollector.Heap_Relocate_AddBlock( dst, src, len ); + g_CLR_RT_GarbageCollector.Heap_Relocate ( ); + } + else + { + m_pending_object->m_targetSerialized = &m_pending_header->m_object; + } + + m_pending_object->m_identity.m_flags |= CLR_RT_HeapBlock_WeakReference::WR_Persisted; + + m_pending_object = NULL; + m_pending_header = NULL; + m_pending_src = NULL; + m_pending_dst = NULL; + } + } + else + { + Trace_Printf( "FAULT WRITING %08X(%d)", (size_t)m_pending_dst, len ); + + m_pending_header->Delete(); + + m_pending_object = NULL; + m_pending_header = NULL; + m_pending_src = NULL; + m_pending_dst = NULL; + } + } + break; + + case STATE_Idle: + { + return false; + } + break; + + case STATE_Erase: + { + if(!force && g_CLR_RT_ExecutionEngine.IsThereEnoughIdleTime( m_margin_BlockErase ) == false) return true; + + Trace_Printf( "Start erase of storage" ); + + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_WeakReference,weak,g_CLR_RT_ExecutionEngine.m_weakReferences) + { + weak->m_targetCopied = NULL; + } + TINYCLR_FOREACH_NODE_END(); + + m_pending_object = NULL; + m_pending_header = NULL; + m_pending_src = NULL; + m_pending_dst = NULL; + m_pending_size = 0; + + m_eraseIndex = 0; + + m_state = STATE_EraseSector; + } + break; + + case STATE_EraseSector: + { + if(!force && g_CLR_RT_ExecutionEngine.IsThereEnoughIdleTime( m_margin_BlockErase ) == false) return true; + + if(m_bankB.Erase( m_eraseIndex ) ) + { + m_bankB.Format(); + + m_state = STATE_CopyToOtherBank; + } + } + break; + + case STATE_CopyToOtherBank: + { + if(!force && g_CLR_RT_ExecutionEngine.IsThereEnoughIdleTime( m_margin_BurstWrite ) == false) return true; + + if(m_pending_object == NULL) + { + CLR_UINT32 usedBytes = 0; + + // + // The list is sorted in priority order, we save higher priority objects first. + // + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_WeakReference,weak,g_CLR_RT_ExecutionEngine.m_weakReferences) + { + if(weak->m_identity.m_flags & CLR_RT_HeapBlock_WeakReference::WR_SurvivePowerdown) + { + CLR_RT_HeapBlock_Array* array = weak->m_targetSerialized; + + if(array) + { + usedBytes += ObjectHeader::Length( weak ); + + if((weak->m_identity.m_flags & CLR_RT_HeapBlock_WeakReference::WR_Persisted) && weak->m_targetCopied == NULL) + { + if(usedBytes < m_bankB.m_totalSafeBytes && m_bankB.WriteHeader( weak, m_pending_header, m_pending_dst )) + { + m_pending_object = weak; + m_pending_src = (FLASH_WORD*)array->GetFirstElement(); + m_pending_size = array->m_numOfElements; + } + + break; + } + } + } + } + TINYCLR_FOREACH_NODE_END(); + + if(m_pending_object == NULL) + { + m_state = STATE_CopyBackToRam; + break; + } + } + + Trace_DumpState( "Copying block", m_pending_dst, m_pending_header, m_pending_object ); + + CLR_UINT32 len = m_pending_size; if(len > c_MaxWriteBurst) len = c_MaxWriteBurst; + + if(Bank::Write( m_pending_dst, m_pending_src, len )) + { + m_pending_dst = Bank::IncrementPointer( m_pending_dst, len ); + m_pending_src = Bank::IncrementPointer( m_pending_src, len ); + m_pending_size -= len; + + if(m_pending_size == 0) + { + m_pending_object->m_targetCopied = &m_pending_header->m_object; + + m_pending_object = NULL; + m_pending_header = NULL; + m_pending_src = NULL; + m_pending_dst = NULL; + } + } + else + { + Trace_Printf( "FAULT WRITING %08X(%d)", (size_t)m_pending_dst, len ); + + m_pending_header->Delete(); + + m_pending_object = NULL; + m_pending_header = NULL; + m_pending_src = NULL; + m_pending_dst = NULL; + } + } + break; + + case STATE_CopyBackToRam: + { + if(!force && g_CLR_RT_ExecutionEngine.IsThereEnoughIdleTime( m_margin_BurstWrite ) == false) return true; + + if(m_pending_object == NULL) + { + // + // The list is sorted in priority order, we save higher priority objects first. + // + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_WeakReference,weak,g_CLR_RT_ExecutionEngine.m_weakReferences) + { + if((weak->m_identity.m_flags & CLR_RT_HeapBlock_WeakReference::WR_Persisted) && weak->m_targetCopied == NULL) + { + m_pending_header = m_bankA.RecoverHeader( weak ); + + if(m_pending_header != NULL) + { + m_pending_object = weak; + break; + } + } + } + TINYCLR_FOREACH_NODE_END(); + + if(m_pending_object == NULL) + { + m_state = STATE_SwitchBank; + break; + } + } + + { + CLR_RT_HeapBlock ref; + CLR_UINT32 len = m_pending_header->m_object.m_numOfElements; + + if(SUCCEEDED(CLR_RT_HeapBlock_Array::CreateInstance( ref, len, g_CLR_RT_WellKnownTypes.m_UInt8 ))) + { + CLR_RT_HeapBlock_Array* array = ref.DereferenceArray(); + + memcpy( array->GetFirstElement(), m_pending_header->m_object.GetFirstElement(), len ); + + if(m_pending_object->m_identity.m_flags & CLR_RT_HeapBlock_WeakReference::WR_ArrayOfBytes) + { + CLR_UINT8* dst = (CLR_UINT8*)array; + CLR_UINT8* src = (CLR_UINT8*)m_pending_object->m_targetSerialized; + CLR_UINT32 len = m_pending_object->m_targetSerialized->DataSize() * sizeof(CLR_RT_HeapBlock); + + Trace_Printf( "Relocate Array - Copy: %08X %08X %d", (size_t)dst, (size_t)src, len ); + + g_CLR_RT_GarbageCollector.Heap_Relocate_Prepare ( relocHelper, ARRAYSIZE(relocHelper) ); + g_CLR_RT_GarbageCollector.Heap_Relocate_AddBlock( dst, src, len ); + g_CLR_RT_GarbageCollector.Heap_Relocate ( ); + } + else + { + m_pending_object->m_targetSerialized = array; + } + + m_pending_object->m_identity.m_flags &= ~CLR_RT_HeapBlock_WeakReference::WR_Persisted; + + Trace_DumpState( "Revert block to RAM", NULL, m_pending_header, m_pending_object ); + + m_pending_header->Delete(); + } + else + { + // + // This is bad, out of memory, it should not happen during revert to RAM. + // + // Another case this could happen is if we try to move a big chunk back to RAM and + // the heap is too fragmented to proceed. + // + // Only course of action: abort the copy and restart everything, sooner or later the memory will be there. + // + m_state = STATE_Erase; + return true; + } + + m_pending_header = NULL; + m_pending_object = NULL; + } + } + break; + + case STATE_SwitchBank: + { + Trace_Printf( "Switching banks" ); + + g_CLR_RT_GarbageCollector.Heap_Relocate_Prepare( relocHelper, ARRAYSIZE(relocHelper) ); + + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_WeakReference,weak,g_CLR_RT_ExecutionEngine.m_weakReferences) + { + if(weak->m_targetCopied) + { + if(weak->m_identity.m_flags & CLR_RT_HeapBlock_WeakReference::WR_ArrayOfBytes) + { + CLR_UINT8* dst = (CLR_UINT8*)weak->m_targetCopied; + CLR_UINT8* src = (CLR_UINT8*)weak->m_targetSerialized; + CLR_UINT32 len = weak->m_targetSerialized->DataSize() * sizeof(CLR_RT_HeapBlock); + + Trace_Printf( "Relocate Array - Switch: %08X %08X %d", (size_t)dst, (size_t)src, len ); + + g_CLR_RT_GarbageCollector.Heap_Relocate_AddBlock( dst, src, len ); + } + else + { + weak->m_targetSerialized = weak->m_targetCopied; + } + + weak->m_targetCopied = NULL; + } + } + TINYCLR_FOREACH_NODE_END(); + + g_CLR_RT_GarbageCollector.Heap_Relocate(); + + m_bankB.SetSequence( m_bankA.GetBankHeader()->m_sequenceNumber + 1 ); + m_bankB.Switch ( m_bankA ); + + m_state = STATE_FlushNextObject; + } + break; + + default: + return false; + } + } + + return true; +} + + +void CLR_RT_Persistence_Manager::Flush() +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + AdvanceState( true ); +} + +//--// + +#if !defined(BUILD_RTM) + +void CLR_RT_Persistence_Manager::GenerateStatistics( CLR_UINT32& totalSize, CLR_UINT32& inUse ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + totalSize = 0; + inUse = 0; + + if(m_bankA.IsGood()) + { + totalSize = m_bankA.m_totalBytes; + + if(m_bankA.m_bankHeader) + { + ObjectHeader* ptr = m_bankA.m_bankHeader->FirstObjectHeader(); + + while((ptr = ObjectHeader::Find( (FLASH_WORD*)ptr, m_bankA.m_end )) != NULL) + { + while(ptr->IsGood( false )) + { + if(ptr->IsGood( true )) + { + inUse += ptr->Length(); + } + + ptr = ptr->Next(); + } + + ptr = (ObjectHeader*)Bank::IncrementPointer( (FLASH_WORD*)ptr, sizeof(FLASH_WORD) ); + } + } + } +} + +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +CLR_UINT32 CLR_RT_HeapBlock_WeakReference_Identity::ComputeCRC( const CLR_UINT8* ptr, CLR_UINT32 len ) const +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + CLR_UINT32 hash; + + hash = SUPPORT_ComputeCRC( ptr , len , g_buildCRC ); + hash = SUPPORT_ComputeCRC( &m_selectorHash, sizeof(m_selectorHash), hash ); + hash = SUPPORT_ComputeCRC( &m_id , sizeof(m_id ), hash ); + + return hash; +} + +//--// + +HRESULT CLR_RT_HeapBlock_WeakReference::CreateInstance( CLR_RT_HeapBlock_WeakReference*& weakref ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + TINYCLR_HEADER(); + + weakref = (CLR_RT_HeapBlock_WeakReference*)g_CLR_RT_ExecutionEngine.ExtractHeapBytesForObjects( DATATYPE_WEAKCLASS, CLR_RT_HeapBlock::HB_InitializeToZero, sizeof(*weakref) ); + + CHECK_ALLOCATION(weakref); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_WeakReference::SetTarget( CLR_RT_HeapBlock& targetReference ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + TINYCLR_HEADER(); + + // + // Only classes and value types can be associated with a weak reference! + // + if(targetReference.DataType() != DATATYPE_OBJECT) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + { + CLR_RT_HeapBlock* target = targetReference.Dereference(); + CLR_RT_HeapBlock input ; input .SetObjectReference( target ); + CLR_RT_HeapBlock output; output.SetObjectReference( NULL ); + + CLR_RT_ProtectFromGC gcInput ( input ); + CLR_RT_ProtectFromGC gcOutput( output ); + + m_targetDirect = target; + + // + // Check if this is an Extended Weak Reference before calling SerializationEnabled(). + // Checking a flag is faster than calling a function that is unlikely to be inlined + // (from a separate static library) + // + // As WR_ExtendedType can only be set in the constructor of the ExtendedWeakReference class, + // this flag cannot be unset after an EWR is persisted to flash. + // Thus, the EWR invalidation code only needs to be called when WR_ExtendedType is set, + // allowing it to be inside the following 'if' block, and minimizing the number of 'if' conditions + // to check for the non EWR case. + // + // This is particularly important to TinyCore and System.Threading.Dispatcher, which uses a + // WeakReference to cache the last used Dispatcher and improve event throughput. + // + if((m_identity.m_flags & CLR_RT_HeapBlock_WeakReference::WR_ExtendedType) != 0 && + CLR_RT_BinaryFormatter::SerializationEnabled()) + { + if(target) + { + switch(target->DataType()) + { + case DATATYPE_SZARRAY: + { + CLR_RT_HeapBlock_Array* array = (CLR_RT_HeapBlock_Array*)target; + + if(array->m_typeOfElement == DATATYPE_U1) + { + output.SetObjectReference( array ); + m_identity.m_flags |= CLR_RT_HeapBlock_WeakReference::WR_ArrayOfBytes; + break; + } + } + // + // Fall through!!! + // + case DATATYPE_STRING: + case DATATYPE_CLASS: + case DATATYPE_VALUETYPE: + { + TINYCLR_CHECK_HRESULT(CLR_RT_BinaryFormatter::Serialize( output, input, NULL, 0 )); + + m_identity.m_flags &= ~CLR_RT_HeapBlock_WeakReference::WR_ArrayOfBytes; + } + break; + + default: + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + + { + CLR_RT_HeapBlock_Array* targetSerialized = output.DereferenceArray(); + CLR_UINT32 len = targetSerialized ? targetSerialized->m_numOfElements : 0; + CLR_UINT32 lenOrig = m_targetSerialized ? m_targetSerialized->m_numOfElements : 0; + + // + // Check if we need to invalidate an entry. + // + if(len != lenOrig || (len > 0 && memcmp( targetSerialized->GetFirstElement(), m_targetSerialized->GetFirstElement(), len ))) + { + g_CLR_RT_Persistence_Manager.InvalidateEntry( this ); + m_identity.m_length = len; + + if(len > 0) + { + m_identity.m_crc = m_identity.ComputeCRC( targetSerialized->GetFirstElement(), len ); + m_targetSerialized = targetSerialized; + } + else + { + m_identity.m_crc = 0; + m_targetSerialized = NULL; + } + } + } + } + } + + InsertInPriorityOrder(); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_WeakReference::GetTarget( CLR_RT_HeapBlock& targetReference ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + TINYCLR_HEADER(); + + if(CLR_RT_BinaryFormatter::SerializationEnabled()) + { + targetReference.SetObjectReference( NULL ); + + if(m_targetDirect == NULL && m_targetSerialized != NULL) + { + if(m_identity.m_flags & CLR_RT_HeapBlock_WeakReference::WR_ArrayOfBytes) + { + m_targetDirect = m_targetSerialized; + } + else + { + CLR_RT_HeapBlock input ; input .SetObjectReference( m_targetSerialized ); + CLR_RT_HeapBlock output; output.SetObjectReference( NULL ); + + { + CLR_RT_ProtectFromGC gcInput ( input ); + CLR_RT_ProtectFromGC gcOutput( output ); + + if(FAILED(CLR_RT_BinaryFormatter::Deserialize( output, input, NULL, NULL, 0 ))) + { + output.SetObjectReference( NULL ); + } + } + + m_targetDirect = output.Dereference(); + } + } + } + + targetReference.SetObjectReference( m_targetDirect ); + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +void CLR_RT_HeapBlock_WeakReference::InsertInPriorityOrder() +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + this->Unlink(); // Remove from the list before looking for a spot, to avoid comparing against ourselves. + + if(m_identity.m_flags & CLR_RT_HeapBlock_WeakReference::WR_ExtendedType) + { + CLR_INT32 pri = m_identity.m_priority; + CLR_RT_HeapBlock_WeakReference* ptr = (CLR_RT_HeapBlock_WeakReference*)g_CLR_RT_ExecutionEngine.m_weakReferences.FirstNode(); + while(true) + { + CLR_RT_HeapBlock_WeakReference* ptrNext = (CLR_RT_HeapBlock_WeakReference*)ptr->Next(); if(!ptrNext) break; + + if(ptr->m_identity.m_priority <= pri) break; + + ptr = ptrNext; + } + + g_CLR_RT_ExecutionEngine.m_weakReferences.InsertBeforeNode( ptr, this ); + } + else + { + g_CLR_RT_ExecutionEngine.m_weakReferences.LinkAtBack( this ); + } +} + + +void CLR_RT_HeapBlock_WeakReference::Relocate() +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + CLR_RT_HeapBlock_Node::Relocate(); + + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_targetDirect ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_targetSerialized ); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +bool CLR_RT_HeapBlock_WeakReference::PrepareForRecovery( CLR_RT_HeapBlock_Node* ptr, CLR_RT_HeapBlock_Node* end, CLR_UINT32 blockSize ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + + while(ptr < end) + { + if(ptr->DataType() == DATATYPE_WEAKCLASS) + { + CLR_RT_HeapBlock_WeakReference* weak = (CLR_RT_HeapBlock_WeakReference*)ptr; + + if(weak->DataSize() == CONVERTFROMSIZETOHEAPBLOCKS(sizeof(*weak)) && weak->m_targetSerialized != NULL && (weak->m_identity.m_flags & CLR_RT_HeapBlock_WeakReference::WR_SurviveBoot)) + { + weak->SetNext( NULL ); + weak->SetPrev( NULL ); + + weak->m_identity.m_flags &= ~CLR_RT_HeapBlock_WeakReference::WR_Persisted; + + weak->m_targetDirect = NULL; + + weak->MarkAlive(); + + ptr += ptr->DataSize(); + continue; + } + } + else if(ptr->DataType() == DATATYPE_SZARRAY) + { + CLR_RT_HeapBlock_Array* array = (CLR_RT_HeapBlock_Array*)ptr; + + if(array->m_typeOfElement == DATATYPE_U1 && array->m_fReference == 0) + { + CLR_UINT32 tot = sizeof(*array) + array->m_sizeOfElement * array->m_numOfElements; + + if(array->DataSize() == CONVERTFROMSIZETOHEAPBLOCKS(tot) && (ptr + ptr->DataSize()) <= end) + { + array->MarkAlive(); + + ptr += ptr->DataSize(); + continue; + } + } + } + + if((UINT32)(ptr + blockSize) > (UINT32)end) + { + blockSize = (CLR_UINT32)(end - ptr); + } + + ptr->SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_FREEBLOCK,0,blockSize) ); + ptr += blockSize; + } + + return true; +} + +void CLR_RT_HeapBlock_WeakReference::RecoverObjects( CLR_RT_DblLinkedList& lstHeap ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + TINYCLR_FOREACH_NODE(CLR_RT_HeapCluster,hc,lstHeap) + { + CLR_RT_HeapBlock_Node* ptr = hc->m_payloadStart; + CLR_RT_HeapBlock_Node* end = hc->m_payloadEnd; + + while(ptr < end) + { + if(ptr->DataType() == DATATYPE_WEAKCLASS) + { + CLR_RT_HeapBlock_WeakReference* weak = (CLR_RT_HeapBlock_WeakReference*)ptr; + CLR_RT_HeapBlock* target = weak->m_targetSerialized; + + TINYCLR_FOREACH_NODE(CLR_RT_HeapCluster,hc2,lstHeap) + { + CLR_RT_HeapBlock_Node* ptr2 = hc2->m_payloadStart; + CLR_RT_HeapBlock_Node* end2 = hc2->m_payloadEnd; + + if(ptr2 <= target && target < end2) + { + while(ptr2 < end2) + { + if(ptr2 == target) + { + CLR_RT_HeapBlock_Array* array = (CLR_RT_HeapBlock_Array*)ptr2; + + if(array->m_numOfElements == weak->m_identity.m_length) + { + if(weak->m_identity.m_crc == weak->m_identity.ComputeCRC( array->GetFirstElement(), weak->m_identity.m_length )) + { + weak->m_identity.m_flags |= CLR_RT_HeapBlock_WeakReference::WR_Restored; + + weak->InsertInPriorityOrder(); + + weak = NULL; + } + } + + break; + } + + ptr2 += ptr2->DataSize(); + } + + if(ptr2 < end2) break; + } + } + TINYCLR_FOREACH_NODE_END(); + + if(weak) + { + weak->ChangeDataType( DATATYPE_FREEBLOCK ); + } + } + + ptr += ptr->DataSize(); + } + } + TINYCLR_FOREACH_NODE_END(); +} + diff --git a/src/CLR/Core/HeapPersistence/Heap_Persistence_stub.cpp b/src/CLR/Core/HeapPersistence/Heap_Persistence_stub.cpp new file mode 100644 index 0000000000..de0bb554cd --- /dev/null +++ b/src/CLR/Core/HeapPersistence/Heap_Persistence_stub.cpp @@ -0,0 +1,417 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// + + +bool CLR_RT_Persistence_Manager::ObjectHeader::Initialize( CLR_RT_HeapBlock_WeakReference* wr ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + return true; +} + +bool CLR_RT_Persistence_Manager::ObjectHeader::IsGood( bool fIncludeData ) const +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + return true; +} + +void CLR_RT_Persistence_Manager::ObjectHeader::Delete() +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); +} + +CLR_UINT32 CLR_RT_Persistence_Manager::ObjectHeader::Length() const +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + return 0; +} + +CLR_UINT32 CLR_RT_Persistence_Manager::ObjectHeader::Length( const CLR_RT_HeapBlock_WeakReference* ref ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + return 0; +} + +CLR_UINT32 CLR_RT_Persistence_Manager::ObjectHeader::Length( CLR_UINT32 data ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + return 0; +} + +CLR_RT_Persistence_Manager::ObjectHeader* CLR_RT_Persistence_Manager::ObjectHeader::Next() const +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + return NULL; +} + +CLR_UINT32 CLR_RT_Persistence_Manager::ObjectHeader::ComputeCRC() const +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + return 0; +} + +CLR_RT_Persistence_Manager::ObjectHeader* CLR_RT_Persistence_Manager::ObjectHeader::Find( FLASH_WORD* start, FLASH_WORD* end ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + return NULL; +} + +//--//--//--//--//--// + +void CLR_RT_Persistence_Manager::BankHeader::Initialize() +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); +} + +bool CLR_RT_Persistence_Manager::BankHeader::IsGood() const +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + return true; +} + +void CLR_RT_Persistence_Manager::BankHeader::Delete() +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); +} + +CLR_RT_Persistence_Manager::BankHeader* CLR_RT_Persistence_Manager::BankHeader::Find( FLASH_WORD* start, FLASH_WORD* end ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + return NULL; +} + +//--//--//--//--//--// + +bool CLR_RT_Persistence_Manager::Bank::Initialize( UINT32 kind ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + + return false; +} + +bool CLR_RT_Persistence_Manager::Bank::IsGood() const +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + return true; +} + +bool CLR_RT_Persistence_Manager::Bank::Erase( int& sectorIndex ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + return true; +} + +void CLR_RT_Persistence_Manager::Bank::EraseAll() +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); +} + +bool CLR_RT_Persistence_Manager::Bank::Format() +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + return true; +} + +void CLR_RT_Persistence_Manager::Bank::Switch( Bank& other ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); +} + +//--// + +CLR_RT_Persistence_Manager::ObjectHeader* CLR_RT_Persistence_Manager::Bank::RecoverHeader( CLR_RT_HeapBlock_WeakReference* ref ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + return NULL; +} + +bool CLR_RT_Persistence_Manager::Bank::WriteHeader( CLR_RT_HeapBlock_WeakReference* ref, ObjectHeader*& pOH, FLASH_WORD*& pData ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + return true; +} + +//--// + +bool CLR_RT_Persistence_Manager::Bank::CanWrite( FLASH_WORD* dst, CLR_UINT32 length ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + return true; +} + +bool CLR_RT_Persistence_Manager::Bank::Write( FLASH_WORD* dst, const FLASH_WORD* src, CLR_UINT32 length ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + return true; +} + +void CLR_RT_Persistence_Manager::Bank::Invalidate( FLASH_WORD* dst, FLASH_WORD match, CLR_UINT32 length ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); +} + +//--// + +void CLR_RT_Persistence_Manager::Uninitialize() +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); +} + + +void CLR_RT_Persistence_Manager::Initialize() +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); +} + +void CLR_RT_Persistence_Manager::EraseAll() +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); +} + +//--// + +CLR_RT_Persistence_Manager::ObjectHeader* CLR_RT_Persistence_Manager::RecoverHeader( CLR_RT_HeapBlock_WeakReference* weak ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + return NULL; +} + +void CLR_RT_Persistence_Manager::InvalidateEntry( CLR_RT_HeapBlock_WeakReference* weak ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); +} + +//--// + +void CLR_RT_Persistence_Manager::Callback( void* arg ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); +} + +void CLR_RT_Persistence_Manager::EnqueueNextCallback() +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); +} + +void CLR_RT_Persistence_Manager::Relocate() +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); +} + +bool CLR_RT_Persistence_Manager::AdvanceState( bool force ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + return false; +} + +void CLR_RT_Persistence_Manager::Flush() +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); +} + +//--// + +#if !defined(BUILD_RTM) +void CLR_RT_Persistence_Manager::GenerateStatistics( CLR_UINT32& totalSize, CLR_UINT32& inUse ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); +} +#endif +//////////////////////////////////////////////////////////////////////////////////////////////////// + +CLR_UINT32 CLR_RT_HeapBlock_WeakReference_Identity::ComputeCRC( const CLR_UINT8* ptr, CLR_UINT32 len ) const +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + CLR_UINT32 hash; + + hash = SUPPORT_ComputeCRC( ptr , len , g_buildCRC ); + hash = SUPPORT_ComputeCRC( &m_selectorHash, sizeof(m_selectorHash), hash ); + hash = SUPPORT_ComputeCRC( &m_id , sizeof(m_id ), hash ); + + return hash; +} + +//--// + +HRESULT CLR_RT_HeapBlock_WeakReference::CreateInstance( CLR_RT_HeapBlock_WeakReference*& weakref ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + TINYCLR_HEADER(); + + weakref = (CLR_RT_HeapBlock_WeakReference*)g_CLR_RT_ExecutionEngine.ExtractHeapBytesForObjects( DATATYPE_WEAKCLASS, CLR_RT_HeapBlock::HB_InitializeToZero, sizeof(*weakref) ); + + CHECK_ALLOCATION(weakref); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_WeakReference::SetTarget( CLR_RT_HeapBlock& targetReference ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + TINYCLR_HEADER(); + + // + // Only classes and value types can be associated with a weak reference! + // + if(targetReference.DataType() != DATATYPE_OBJECT) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + m_targetDirect = targetReference.Dereference(); + + InsertInPriorityOrder(); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_WeakReference::GetTarget( CLR_RT_HeapBlock& targetReference ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + TINYCLR_HEADER(); + + targetReference.SetObjectReference( m_targetDirect ); + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +void CLR_RT_HeapBlock_WeakReference::InsertInPriorityOrder() +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + + this->Unlink(); // Remove from the list before looking for a spot, to avoid comparing against ourselves. + + g_CLR_RT_ExecutionEngine.m_weakReferences.LinkAtBack( this ); +} + + +void CLR_RT_HeapBlock_WeakReference::Relocate() +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + CLR_RT_HeapBlock_Node::Relocate(); + + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_targetDirect ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_targetSerialized ); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +bool CLR_RT_HeapBlock_WeakReference::PrepareForRecovery( CLR_RT_HeapBlock_Node* ptr, CLR_RT_HeapBlock_Node* end, CLR_UINT32 blockSize ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + + while(ptr < end) + { + if(ptr->DataType() == DATATYPE_WEAKCLASS) + { + CLR_RT_HeapBlock_WeakReference* weak = (CLR_RT_HeapBlock_WeakReference*)ptr; + + if(weak->DataSize() == CONVERTFROMSIZETOHEAPBLOCKS(sizeof(*weak)) && weak->m_targetSerialized != NULL && (weak->m_identity.m_flags & CLR_RT_HeapBlock_WeakReference::WR_SurviveBoot)) + { + weak->SetNext( NULL ); + weak->SetPrev( NULL ); + + weak->m_identity.m_flags &= ~CLR_RT_HeapBlock_WeakReference::WR_Persisted; + + weak->m_targetDirect = NULL; + + weak->MarkAlive(); + + ptr += ptr->DataSize(); + continue; + } + } + else if(ptr->DataType() == DATATYPE_SZARRAY) + { + CLR_RT_HeapBlock_Array* array = (CLR_RT_HeapBlock_Array*)ptr; + + if(array->m_typeOfElement == DATATYPE_U1 && array->m_fReference == 0) + { + CLR_UINT32 tot = sizeof(*array) + array->m_sizeOfElement * array->m_numOfElements; + + if(array->DataSize() == CONVERTFROMSIZETOHEAPBLOCKS(tot) && (ptr + ptr->DataSize()) <= end) + { + array->MarkAlive(); + + ptr += ptr->DataSize(); + continue; + } + } + } + + if((UINT32)(ptr + blockSize) > (UINT32)end) + { + blockSize = (CLR_UINT32)(end - ptr); + } + + ptr->SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_FREEBLOCK,0,blockSize) ); + ptr += blockSize; + } + + return true; +} + +void CLR_RT_HeapBlock_WeakReference::RecoverObjects( CLR_RT_DblLinkedList& lstHeap ) +{ + NATIVE_PROFILE_CLR_HEAP_PERSISTENCE(); + TINYCLR_FOREACH_NODE(CLR_RT_HeapCluster,hc,lstHeap) + { + CLR_RT_HeapBlock_Node* ptr = hc->m_payloadStart; + CLR_RT_HeapBlock_Node* end = hc->m_payloadEnd; + + while(ptr < end) + { + if(ptr->DataType() == DATATYPE_WEAKCLASS) + { + CLR_RT_HeapBlock_WeakReference* weak = (CLR_RT_HeapBlock_WeakReference*)ptr; + CLR_RT_HeapBlock* target = weak->m_targetSerialized; + + TINYCLR_FOREACH_NODE(CLR_RT_HeapCluster,hc2,lstHeap) + { + CLR_RT_HeapBlock_Node* ptr2 = hc2->m_payloadStart; + CLR_RT_HeapBlock_Node* end2 = hc2->m_payloadEnd; + + if(ptr2 <= target && target < end2) + { + while(ptr2 < end2) + { + if(ptr2 == target) + { + CLR_RT_HeapBlock_Array* array = (CLR_RT_HeapBlock_Array*)ptr2; + + if(array->m_numOfElements == weak->m_identity.m_length) + { + if(weak->m_identity.m_crc == weak->m_identity.ComputeCRC( array->GetFirstElement(), weak->m_identity.m_length )) + { + weak->m_identity.m_flags |= CLR_RT_HeapBlock_WeakReference::WR_Restored; + + weak->InsertInPriorityOrder(); + + weak = NULL; + } + } + + break; + } + + ptr2 += ptr2->DataSize(); + } + + if(ptr2 < end2) break; + } + } + TINYCLR_FOREACH_NODE_END(); + + if(weak) + { + weak->ChangeDataType( DATATYPE_FREEBLOCK ); + } + } + + ptr += ptr->DataSize(); + } + } + TINYCLR_FOREACH_NODE_END(); +} diff --git a/src/CLR/Core/IOPort/CLR_RT_HeapBlock_IOPort.cpp b/src/CLR/Core/IOPort/CLR_RT_HeapBlock_IOPort.cpp new file mode 100644 index 0000000000..9bf2cc05e0 --- /dev/null +++ b/src/CLR/Core/IOPort/CLR_RT_HeapBlock_IOPort.cpp @@ -0,0 +1,269 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +CLR_RT_DblLinkedList CLR_RT_HeapBlock_NativeEventDispatcher::m_ioPorts; + +void CLR_RT_HeapBlock_NativeEventDispatcher::HandlerMethod_Initialize() +{ + NATIVE_PROFILE_CLR_IOPORT(); + CLR_RT_HeapBlock_NativeEventDispatcher::m_ioPorts.DblLinkedList_Initialize(); +} + +void CLR_RT_HeapBlock_NativeEventDispatcher::HandlerMethod_RecoverFromGC() +{ + NATIVE_PROFILE_CLR_IOPORT(); + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_NativeEventDispatcher,ioPort,CLR_RT_HeapBlock_NativeEventDispatcher::m_ioPorts) + { + ioPort->RecoverFromGC(); + } + TINYCLR_FOREACH_NODE_END(); +} + +void CLR_RT_HeapBlock_NativeEventDispatcher::HandlerMethod_CleanUp() +{ + NATIVE_PROFILE_CLR_IOPORT(); + CLR_RT_HeapBlock_NativeEventDispatcher* ioPort; + + while(NULL != (ioPort = (CLR_RT_HeapBlock_NativeEventDispatcher*)CLR_RT_HeapBlock_NativeEventDispatcher::m_ioPorts.FirstValidNode())) + { + if(ioPort->m_DriverMethods != NULL) + { + ioPort->m_DriverMethods->m_CleanupProc(ioPort); + } + ioPort->DetachAll(); + ioPort->ReleaseWhenDeadEx(); + } +} + +HRESULT CLR_RT_HeapBlock_NativeEventDispatcher::CreateInstance( CLR_RT_HeapBlock& owner, CLR_RT_HeapBlock& portRef ) +{ + NATIVE_PROFILE_CLR_IOPORT(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock_NativeEventDispatcher* port = NULL; + + port = EVENTCACHE_EXTRACT_NODE(g_CLR_RT_EventCache,CLR_RT_HeapBlock_NativeEventDispatcher,DATATYPE_IO_PORT); CHECK_ALLOCATION(port); + + { + + CLR_RT_ProtectFromGC gc( *port ); + + port->Initialize(); + + m_ioPorts.LinkAtBack( port ); + + TINYCLR_CHECK_HRESULT(CLR_RT_ObjectToEvent_Source::CreateInstance( port, owner, portRef )); + + } + + // Set pointer to driver custom data to NULL. It initialized later by users of CLR_RT_HeapBlock_NativeEventDispatcher + port->m_pDrvCustomData = NULL; + // Set pointers to drivers methods to NULL. + port->m_DriverMethods = NULL; + + TINYCLR_CLEANUP(); + + if(FAILED(hr)) + { + if(port) port->ReleaseWhenDead(); + } + + TINYCLR_CLEANUP_END(); +} + +HRESULT CLR_RT_HeapBlock_NativeEventDispatcher::ExtractInstance( CLR_RT_HeapBlock& ref, CLR_RT_HeapBlock_NativeEventDispatcher*& port ) +{ + NATIVE_PROFILE_CLR_IOPORT(); + TINYCLR_HEADER(); + + CLR_RT_ObjectToEvent_Source* src = CLR_RT_ObjectToEvent_Source::ExtractInstance( ref ); FAULT_ON_NULL(src); + + port = (CLR_RT_HeapBlock_NativeEventDispatcher*)src->m_eventPtr; + + TINYCLR_NOCLEANUP(); +} + +void CLR_RT_HeapBlock_NativeEventDispatcher::RecoverFromGC() +{ + NATIVE_PROFILE_CLR_IOPORT(); + CheckAll(); + + ReleaseWhenDeadEx(); +} + +bool CLR_RT_HeapBlock_NativeEventDispatcher::ReleaseWhenDeadEx() +{ + NATIVE_PROFILE_CLR_IOPORT(); + if(!IsReadyForRelease()) return false; + + //remove any queued interrupts for this port + TINYCLR_FOREACH_NODE(CLR_RT_ApplicationInterrupt,interrupt,g_CLR_HW_Hardware.m_interruptData.m_applicationQueue) + { + if(this == interrupt->m_interruptPortInterrupt.m_context) + { + interrupt->Unlink(); + + --g_CLR_HW_Hardware.m_interruptData.m_queuedInterrupts; + + ThreadTerminationCallback( interrupt ); + } + } + TINYCLR_FOREACH_NODE_END(); + + return ReleaseWhenDead(); +} + +/************************************************************************************************************ +** Iterates over HAL queue and remove records that point to this instance of CLR_RT_HeapBlock_NativeEventDispatcher. +** This operation should be done from Dispose as part of destroying the CLR_RT_HeapBlock_NativeEventDispatcher +** +*************************************************************************************************************/ + +void CLR_RT_HeapBlock_NativeEventDispatcher::RemoveFromHALQueue() + +{ // Since we are going to analyze and update the queue we need to disable interrupts. + // Interrupt service routines add records to this queue. + GLOBAL_LOCK(irq); + CLR_UINT32 elemCount = g_CLR_HW_Hardware.m_interruptData.m_HalQueue.NumberOfElements(); + + // For all elements in the queue + for ( CLR_UINT32 curElem = 0; curElem < elemCount; curElem++ ) + { // Retrieve the element ( actually remove it from the queue ) + CLR_HW_Hardware::HalInterruptRecord* testRec = g_CLR_HW_Hardware.m_interruptData.m_HalQueue.Pop(); + + // Check if context of this record points to the instance of CLR_RT_HeapBlock_NativeEventDispatcher + // If the "context" is the same as "this", then we skip the "Push" and record is removed. + if ( testRec->m_context != this ) + { // If it is different from this instance of CLR_RT_HeapBlock_NativeEventDispatcher, thin push it back + CLR_HW_Hardware::HalInterruptRecord* newRec = g_CLR_HW_Hardware.m_interruptData.m_HalQueue.Push(); + newRec->AssignFrom( *testRec ); + } + } + +} + + +void CLR_RT_HeapBlock_NativeEventDispatcher::SaveToHALQueue( UINT32 data1, UINT32 data2 ) +{ + NATIVE_PROFILE_CLR_IOPORT(); + ASSERT_IRQ_MUST_BE_OFF(); + + CLR_HW_Hardware::HalInterruptRecord* rec = g_CLR_HW_Hardware.m_interruptData.m_HalQueue.Push(); + + if(rec == NULL) + { + g_CLR_HW_Hardware.m_interruptData.m_HalQueue.Pop(); // remove the oldest interrupt to make room for the newest + rec = g_CLR_HW_Hardware.m_interruptData.m_HalQueue.Push(); + } + + if(rec) + { + rec->m_data1 = data1; + rec->m_data2 = data2; + rec->m_context = this; + rec->m_time = Time_GetUtcTime(); + } + + ::Events_Set( SYSTEM_EVENT_HW_INTERRUPT ); +} + +void SaveNativeEventToHALQueue( CLR_RT_HeapBlock_NativeEventDispatcher *pContext, UINT32 data1, UINT32 data2 ) +{ + pContext->SaveToHALQueue( data1, data2 ); +} + +void CleanupNativeEventsFromHALQueue( CLR_RT_HeapBlock_NativeEventDispatcher *pContext ) +{ + pContext->RemoveFromHALQueue(); +} + +HRESULT CLR_RT_HeapBlock_NativeEventDispatcher::StartDispatch( CLR_RT_ApplicationInterrupt* appInterrupt, CLR_RT_Thread* th ) +{ + NATIVE_PROFILE_CLR_IOPORT(); + TINYCLR_HEADER(); + + CLR_RT_StackFrame* stackTop; + CLR_RT_HeapBlock* args; + CLR_RT_HeapBlock_Delegate* dlg; + CLR_RT_HeapBlock* port; + const CLR_UINT64 c_UTCMask = 0x8000000000000000ULL; + + InterruptPortInterrupt& interrupt = appInterrupt->m_interruptPortInterrupt; + + TINYCLR_CHECK_HRESULT(RecoverManagedObject( port )); + dlg = port[ Library_spot_hardware_native_Microsoft_SPOT_Hardware_NativeEventDispatcher::FIELD__m_threadSpawn ].DereferenceDelegate(); FAULT_ON_NULL(dlg); + + TINYCLR_CHECK_HRESULT(th->PushThreadProcDelegate( dlg )); + + stackTop = th->CurrentFrame(); + + args = stackTop->m_arguments; + + if((stackTop->m_call.m_target->flags & CLR_RECORD_METHODDEF::MD_Static) == 0) + { + ++args; + } + + // + // set values for delegate arguments + // + args[0].SetInteger ( interrupt.m_data1 ); + args[1].SetInteger ( interrupt.m_data2 ); + args[2].SetInteger ( (CLR_UINT64)interrupt.m_time | c_UTCMask ); + args[2].ChangeDataType( DATATYPE_DATETIME ); + + + th->m_terminationCallback = CLR_RT_HeapBlock_NativeEventDispatcher::ThreadTerminationCallback; + th->m_terminationParameter = appInterrupt; + + TINYCLR_NOCLEANUP(); +} + +void CLR_RT_HeapBlock_NativeEventDispatcher::ThreadTerminationCallback( void* arg ) +{ + NATIVE_PROFILE_CLR_IOPORT(); + CLR_RT_ApplicationInterrupt* appInterrupt = (CLR_RT_ApplicationInterrupt*)arg; + CLR_RT_HeapBlock_NativeEventDispatcher::InterruptPortInterrupt& interrupt = appInterrupt->m_interruptPortInterrupt; + + FreeManagedEvent((interrupt.m_data1 >> 8) & 0xff, //category + (interrupt.m_data1 ) & 0xff, //subCategory + interrupt.m_data1 >> 16 , //data1 + interrupt.m_data2 ); + + interrupt.m_data1 = 0; + interrupt.m_data2 = 0; + + CLR_RT_Memory::Release( appInterrupt ); + + g_CLR_HW_Hardware.SpawnDispatcher(); +} + +HRESULT CLR_RT_HeapBlock_NativeEventDispatcher::RecoverManagedObject( CLR_RT_HeapBlock*& port ) +{ + NATIVE_PROFILE_CLR_IOPORT(); + TINYCLR_HEADER(); + + // recover the managed object + TINYCLR_FOREACH_NODE(CLR_RT_ObjectToEvent_Source,ref,this->m_references) + { + if(ref->m_objectPtr) + { + port = ref->m_objectPtr; + TINYCLR_SET_AND_LEAVE(S_OK); + } + } + TINYCLR_FOREACH_NODE_END(); + + port = NULL; + + TINYCLR_SET_AND_LEAVE(CLR_E_PIN_DEAD); + + TINYCLR_NOCLEANUP(); +} diff --git a/src/CLR/Core/IOPort/IOPort.vcxproj b/src/CLR/Core/IOPort/IOPort.vcxproj new file mode 100644 index 0000000000..549b501d3b --- /dev/null +++ b/src/CLR/Core/IOPort/IOPort.vcxproj @@ -0,0 +1,155 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {6DD5CA4F-2AE9-44D3-B9D7-A2A4A35FC5B2} + Win32Proj + IOPort + 10.0.14393.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include;..\..\CorLib + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include;..\..\CorLib + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include;..\..\CorLib + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include;..\..\CorLib + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/src/CLR/Core/IOPort/IOPort.vcxproj.filters b/src/CLR/Core/IOPort/IOPort.vcxproj.filters new file mode 100644 index 0000000000..6a1782f7d7 --- /dev/null +++ b/src/CLR/Core/IOPort/IOPort.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + \ No newline at end of file diff --git a/src/CLR/Core/IOPort/IOPort_stub.cpp b/src/CLR/Core/IOPort/IOPort_stub.cpp new file mode 100644 index 0000000000..cf63fc65e0 --- /dev/null +++ b/src/CLR/Core/IOPort/IOPort_stub.cpp @@ -0,0 +1,82 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_HeapBlock_NativeEventDispatcher::HandlerMethod_Initialize() +{ + NATIVE_PROFILE_CLR_IOPORT(); +} + +void CLR_RT_HeapBlock_NativeEventDispatcher::HandlerMethod_RecoverFromGC() +{ + NATIVE_PROFILE_CLR_IOPORT(); +} + +void CLR_RT_HeapBlock_NativeEventDispatcher::HandlerMethod_CleanUp() +{ + NATIVE_PROFILE_CLR_IOPORT(); +} + +void SaveNativeEventToHALQueue( CLR_RT_HeapBlock_NativeEventDispatcher *pContext, UINT32 data1, UINT32 data2 ) +{ + NATIVE_PROFILE_CLR_IOPORT(); +} + +void CleanupNativeEventsFromHALQueue( CLR_RT_HeapBlock_NativeEventDispatcher *pContext ) +{ + NATIVE_PROFILE_CLR_IOPORT(); +} + +HRESULT CLR_RT_HeapBlock_NativeEventDispatcher::CreateInstance( CLR_RT_HeapBlock& owner, CLR_RT_HeapBlock& portRef ) +{ + NATIVE_PROFILE_CLR_IOPORT(); + TINYCLR_FEATURE_STUB_RETURN(); +} + +HRESULT CLR_RT_HeapBlock_NativeEventDispatcher::ExtractInstance( CLR_RT_HeapBlock& ref, CLR_RT_HeapBlock_NativeEventDispatcher*& port ) +{ + NATIVE_PROFILE_CLR_IOPORT(); + TINYCLR_FEATURE_STUB_RETURN(); +} + +void CLR_RT_HeapBlock_NativeEventDispatcher::RecoverFromGC() +{ + NATIVE_PROFILE_CLR_IOPORT(); +} + +bool CLR_RT_HeapBlock_NativeEventDispatcher::ReleaseWhenDeadEx() +{ + NATIVE_PROFILE_CLR_IOPORT(); + return true; +} + +void CLR_RT_HeapBlock_NativeEventDispatcher::RemoveFromHALQueue() +{ + NATIVE_PROFILE_CLR_IOPORT(); +} +void CLR_RT_HeapBlock_NativeEventDispatcher::SaveToHALQueue( UINT32 data1, UINT32 data2 ) +{ + NATIVE_PROFILE_CLR_IOPORT(); +} + +HRESULT CLR_RT_HeapBlock_NativeEventDispatcher::StartDispatch( CLR_RT_ApplicationInterrupt* appInterrupt, CLR_RT_Thread* th ) +{ + NATIVE_PROFILE_CLR_IOPORT(); + TINYCLR_FEATURE_STUB_RETURN(); +} + +void CLR_RT_HeapBlock_NativeEventDispatcher::ThreadTerminationCallback( void* arg ) +{ + NATIVE_PROFILE_CLR_IOPORT(); +} + +HRESULT CLR_RT_HeapBlock_NativeEventDispatcher::RecoverManagedObject( CLR_RT_HeapBlock*& port ) +{ + NATIVE_PROFILE_CLR_IOPORT(); + TINYCLR_FEATURE_STUB_RETURN(); +} diff --git a/src/CLR/Core/IOPort/IOPort_stub.vcxproj b/src/CLR/Core/IOPort/IOPort_stub.vcxproj new file mode 100644 index 0000000000..1e34134caf --- /dev/null +++ b/src/CLR/Core/IOPort/IOPort_stub.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + {5406EB0C-2243-47E1-9F21-F2D7CA277092} + Win32Proj + IOPort_stub + 10.0.14393.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/src/CLR/Core/IOPort/IOPort_stub.vcxproj.filters b/src/CLR/Core/IOPort/IOPort_stub.vcxproj.filters new file mode 100644 index 0000000000..f58e45cfd0 --- /dev/null +++ b/src/CLR/Core/IOPort/IOPort_stub.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/src/CLR/Core/Interpreter.cpp b/src/CLR/Core/Interpreter.cpp new file mode 100644 index 0000000000..47c1d407fd --- /dev/null +++ b/src/CLR/Core/Interpreter.cpp @@ -0,0 +1,3125 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(TINYCLR_TRACE_EXCEPTIONS) && defined(_WIN32) + +struct BackTrackExecution +{ + CLR_RT_Assembly* m_assm; + CLR_RT_MethodDef_Index m_call; + CLR_PMETADATA m_IPstart; + CLR_PMETADATA m_IP; + int m_pid; + int m_depth; +}; + +static BackTrackExecution s_track[ 512 ]; +static int s_trackPos; + +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(TINYCLR_TRACE_STACK) + +bool g_CLR_RT_fBadStack; + +#define RESETSTACK() { g_CLR_RT_fBadStack = false; } +#define CHECKSTACK(stack,evalPos) { g_CLR_RT_fBadStack = stack->m_evalStackPos <= evalPos ; } +#define UPDATESTACK(stack,evalPos) { g_CLR_RT_fBadStack = false; stack->m_evalStackPos = &evalPos[ + 1]; } + + +#else + +#define RESETSTACK() +#define CHECKSTACK(stack,evalPos) +#define UPDATESTACK(stack,evalPos) { stack->m_evalStackPos = &evalPos[ +1 ]; } + +#endif + +//--// +#define EMPTYSTACK(stack,evalPos) { evalPos = &stack->m_evalStack [ -1 ]; RESETSTACK(); } +#define READCACHE(stack,evalPos,ip,fDirty) { evalPos = &stack->m_evalStackPos[ -1 ]; ip = stack->m_IP; fDirty = true ; RESETSTACK(); } +#define WRITEBACK(stack,evalPos,ip,fDirty) { stack->m_evalStackPos = &evalPos [ +1 ]; stack->m_IP = ip ; fDirty = false; RESETSTACK(); } + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +bool CLR_RT_HeapBlock::InitObject() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_HeapBlock* obj = this; + CLR_DataType dt = obj->DataType(); + const CLR_RT_DataTypeLookup& dtl = c_CLR_RT_DataTypeLookup[ dt ]; + + if(dtl.m_flags & CLR_RT_DataTypeLookup::c_OptimizedValueType) + { + obj->NumericByRef().u8 = 0; + return false; + } + + if(dt == DATATYPE_VALUETYPE && obj->IsBoxed() == false) + { + CLR_UINT32 num = obj->DataSize(); + + while(--num) + { + (++obj)->InitObject(); + } + + return false; + } + + if(dt == DATATYPE_OBJECT || dt == DATATYPE_BYREF) + { + CLR_RT_HeapBlock* ptr = obj->Dereference(); if(!ptr) return false; + + if(ptr->InitObject() == false) return false; + + obj->SetObjectReference( NULL ); + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_HeapBlock::Convert_Internal( CLR_DataType et ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_DataType dt = DataType(); + const CLR_RT_DataTypeLookup& dtlSrc = c_CLR_RT_DataTypeLookup[ dt ]; + const CLR_RT_DataTypeLookup& dtlDst = c_CLR_RT_DataTypeLookup[ et ]; + int scaleIn; + int scaleOut; + + // + // Extend to maximum precision. + // + switch(dt) + { + case DATATYPE_BOOLEAN : + case DATATYPE_I1 : + case DATATYPE_U1 : + + case DATATYPE_CHAR : + case DATATYPE_I2 : + case DATATYPE_U2 : + + case DATATYPE_I4 : + case DATATYPE_U4 : + { + CLR_UINT64 res = (CLR_UINT64)NumericByRef().u4; + + if((dtlSrc.m_flags & CLR_RT_DataTypeLookup::c_Signed) && (dtlDst.m_flags & CLR_RT_DataTypeLookup::c_Signed)) + { + CLR_UINT32 shift = 64 - dtlSrc.m_sizeInBits; + + res <<= shift; + res = (CLR_UINT64)((CLR_INT64 )res >> shift); + } + + NumericByRef().u8 = res; + } + // + // Fall-through!!! + // + case DATATYPE_I8: + case DATATYPE_U8: + scaleIn = 0; + break; + + case DATATYPE_R4: scaleIn = 1; break; + case DATATYPE_R8: scaleIn = 2; break; + + default: + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + //--// + + switch(et) + { + case DATATYPE_R4: scaleOut = 1; break; + case DATATYPE_R8: scaleOut = 2; break; + default : scaleOut = 0; break; + } + + //--// + + if(scaleOut != scaleIn) + { +#if !defined(TINYCLR_EMULATED_FLOATINGPOINT) + + + double val = 0; + + if((dtlSrc.m_flags & CLR_RT_DataTypeLookup::c_Signed) == 0) scaleIn = -1; + if((dtlDst.m_flags & CLR_RT_DataTypeLookup::c_Signed) == 0) scaleOut = -1; + + switch(scaleIn) + { + case -1: val = (double)((CLR_UINT64_TEMP_CAST)NumericByRef().u8); break; + case 0: val = (double)((CLR_INT64_TEMP_CAST) NumericByRef().s8); break; + case 1: val = (double) NumericByRef().r4; break; + case 2: val = NumericByRef().r8; break; + } + + switch(scaleOut) + { + // Direct casting of negative double to CLR_UINT64 is returns zero for RVDS 3.1 compiler. + // Double cast looks as most portable way. + case -1: NumericByRef().u8 = (CLR_UINT64)(CLR_INT64 )val; break; + case 0: NumericByRef().s8 = (CLR_INT64 )val; break; + case 1: NumericByRef().r4 = (float )val; break; + case 2: NumericByRef().r8 = val; break; + } +#else + CLR_INT64 val = 0; + CLR_INT64 orig = 0; + + if((dtlSrc.m_flags & CLR_RT_DataTypeLookup::c_Signed) == 0) scaleIn = -1; + if((dtlDst.m_flags & CLR_RT_DataTypeLookup::c_Signed) == 0) scaleOut = -1; + + switch(scaleIn) + { + case -1: orig = ((CLR_INT64)((CLR_UINT64_TEMP_CAST)NumericByRef().u8)); val = orig << CLR_RT_HeapBlock::HB_DoubleShift; break; + case 0: orig = ((CLR_INT64)((CLR_INT64_TEMP_CAST) NumericByRef().s8)); val = orig << CLR_RT_HeapBlock::HB_DoubleShift; break; + case 1: orig = ((CLR_INT64)((CLR_INT32) NumericByRef().r4)); val = orig << (CLR_RT_HeapBlock::HB_DoubleShift - CLR_RT_HeapBlock::HB_FloatShift); break; + case 2: orig = ((CLR_INT64) NumericByRef().r8 ); val = orig; break; + } + + switch(scaleOut) + { + // Direct casting of negative double to CLR_UINT64 is returns zero for RVDS 3.1 compiler. + // Double cast looks as most portable way. + case -1: NumericByRef().u8 = (CLR_UINT64)(CLR_INT64 )(val >> CLR_RT_HeapBlock::HB_DoubleShift); break; + case 0: NumericByRef().s8 = (CLR_INT64 ) (val >> CLR_RT_HeapBlock::HB_DoubleShift); break; + case 1: NumericByRef().r4 = (CLR_INT64 ) (val >> (CLR_RT_HeapBlock::HB_DoubleShift - CLR_RT_HeapBlock::HB_FloatShift)); break; + case 2: NumericByRef().r8 = val; break; + } + + if(scaleIn < 1 && scaleOut > 0) + { + switch(scaleOut) + { + case 1: + { + CLR_INT32 r4 = (CLR_INT32)NumericByRef().r4; + + if((orig != (((CLR_INT64)r4) >> CLR_RT_HeapBlock::HB_FloatShift)) || + (orig > 0 && r4 < 0)) + { + NumericByRef().r4 = orig < 0 ? 0x80000000 : 0x7FFFFFFF; + + // + // Uncomment to produce an overflow exception for emulated floating points + // + // TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + } + break; + case 2: + { + CLR_INT64 r8 = (CLR_INT64)NumericByRef().r8; + + if((orig != (r8 >> CLR_RT_HeapBlock::HB_DoubleShift)) || + (orig > 0 && r8 < 0)) + { + NumericByRef().r8 = orig < 0 ? ULONGLONGCONSTANT(0x8000000000000000) : ULONGLONGCONSTANT(0x7FFFFFFFFFFFFFFF); + + // + // Uncomment to produce an overflow exception for emulated floating points + // + // TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + } + break; + } + } + else if(scaleIn == 2 && scaleOut == 1) + { + CLR_INT32 r4 = (CLR_INT64)NumericByRef().r4; + + if((orig != (((CLR_UINT64)r4) << (CLR_RT_HeapBlock::HB_DoubleShift - CLR_RT_HeapBlock::HB_FloatShift))) || + (orig > 0 && r4 < 0)) + { + NumericByRef().r4 = orig < 0 ? 0x80000000 : 0x7FFFFFFF; + + // + // Uncomment to produce an overflow exception for emulated floating points + // + //TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + } +#endif + + } + + //--// + + // + // This takes care of truncations. + // + ChangeDataType( et ); + Promote ( ); + + TINYCLR_NOCLEANUP(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +CLR_RT_Thread::UnwindStack* CLR_RT_Thread::PushEH() +{ + NATIVE_PROFILE_CLR_CORE(); + if(m_nestedExceptionsPos < ARRAYSIZE(m_nestedExceptions)) + { + memset(&m_nestedExceptions[ m_nestedExceptionsPos ], 0, sizeof(UnwindStack)); + return &m_nestedExceptions[ m_nestedExceptionsPos++ ]; + } + else + { +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "WARNING: TOO MANY NESTED EXCEPTIONS!!\r\n" ); +#endif + // clip the oldest exception in the nest + memmove(&m_nestedExceptions[0], &m_nestedExceptions[1], sizeof(m_nestedExceptions) - sizeof(m_nestedExceptions[0])); + return &m_nestedExceptions[ m_nestedExceptionsPos-1 ]; + } +} + +void CLR_RT_Thread::PopEH_Inner( CLR_RT_StackFrame* stack, CLR_PMETADATA ip ) +{ + NATIVE_PROFILE_CLR_CORE(); + // + // We could be jumping outside of a nested exception handler. + // + if(m_nestedExceptionsPos > 0) + { + // + // Different stack, don't pop. + // + if(m_nestedExceptions[ m_nestedExceptionsPos-1 ].m_stack != stack) return; + + // + // No longer check for same stack since nested exceptions will have different + // stacks + // + while(m_nestedExceptionsPos > 0) + { + UnwindStack& us = m_nestedExceptions[ m_nestedExceptionsPos-1 ]; + + // + // The new target is within the previous handler, don't pop. + // + if(ip && (us.m_currentBlockStart <= ip && ip < us.m_currentBlockEnd)) break; + +#ifndef TINYCLR_NO_IL_INLINE + if(stack->m_inlineFrame) break; +#endif + + m_nestedExceptionsPos--; + } + } +} + +bool CLR_RT_Thread::FindEhBlock( CLR_RT_StackFrame* stack, CLR_PMETADATA from, CLR_PMETADATA to, CLR_RT_ExceptionHandler& eh, bool onlyFinallys) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_Assembly* assm = stack->m_call.m_assm; + CLR_RT_ExceptionHandler* ptrEhExt = NULL; + const CLR_RECORD_EH* ptrEh = NULL; + CLR_UINT32 numEh = 0; + + //FROM is always non-NULL and indicates the current IP + _ASSERTE(from); + //onlyFinallys is false when we're searching for a handler for an exception, and to should be NULL + _ASSERTE(FIMPLIES(!onlyFinallys, to==NULL)); + //onlyFinallys is true in Phase2, endfinally, leave, etc. to is NULL when we want to leave outside of the current stack frame, + //or non-NULL and pointing to an IL instruction that we are going to when finally's, if any, are processed. + +#if defined(TINYCLR_TRACE_EXCEPTIONS) + if(s_CLR_RT_fTrace_Exceptions >= c_CLR_RT_Trace_Annoying) + { + if(!onlyFinallys || s_CLR_RT_fTrace_Exceptions >= c_CLR_RT_Trace_Obnoxious) + { + CLR_Debug::Printf( "Unwinding at " ); CLR_RT_DUMP::METHOD( stack->m_call ); CLR_Debug::Printf( " [IP: %04x - %d]\r\n", (size_t)stack->m_IP, (stack->m_IP - stack->m_IPstart) ); + } + } +#endif + + if(stack->m_call.m_target->flags & CLR_RECORD_METHODDEF::MD_HasExceptionHandlers) + { + switch(stack->m_flags & CLR_RT_StackFrame::c_MethodKind_Mask) + { + case CLR_RT_StackFrame::c_MethodKind_Interpreted: + { + CLR_OFFSET ipMethod_Start; + CLR_OFFSET ipMethod_End; + + if(assm->FindMethodBoundaries( stack->m_call.Method(), ipMethod_Start, ipMethod_End )) + { + const CLR_RECORD_EH* ptrEh2; + CLR_UINT32 numEh2; + + CLR_RECORD_EH::ExtractEhFromByteCode( stack->m_IPstart + (ipMethod_End - ipMethod_Start), ptrEh2, numEh2 ); + + ptrEh = ptrEh2; // This allows the compiler to leave ptrEh and numEh in registers... + numEh = numEh2; // This allows the compiler to leave ptrEh and numEh in registers... + } + else + { + return false; + } + + ptrEhExt = NULL; + } + break; + + case CLR_RT_StackFrame::c_MethodKind_Native: + return false; + } + + // + // We're certain there's at least one EH. + // + while(numEh--) + { + if(ptrEh) + { + eh.ConvertFromEH( stack->m_call, stack->m_IPstart, ptrEh++ ); + + ptrEhExt = &eh; + } + +#if defined(TINYCLR_TRACE_EXCEPTIONS) + if(s_CLR_RT_fTrace_Exceptions >= c_CLR_RT_Trace_Annoying) + { + if(to == NULL || s_CLR_RT_fTrace_Exceptions >= c_CLR_RT_Trace_Obnoxious) + { + CLR_Debug::Printf( "Checking EH: %04X-%04X => %04X\r\n", (size_t)ptrEhExt->m_tryStart, (size_t)ptrEhExt->m_tryEnd, ptrEhExt->m_handlerStart - stack->m_IPstart ); + } + } +#endif + + if(ptrEhExt->IsFilter() && ptrEhExt->m_userFilterStart <= from && from < ptrEhExt->m_handlerStart) + { + //The IP was in the middle of this EH block's filter. + //Therefore, reset the IP to inside the original try block so we can try the next handler in this sequence: + // Try + // ... //2. set IP to here + // Catch When False + // Catch When False //1. from was in this filter + // Catch ... //3. This is the next EH block, and will be found correctly. + // ... + // End Try + from = ptrEhExt->m_tryStart; + } + else if(from >= ptrEhExt->m_tryStart && from < ptrEhExt->m_tryEnd) + { + if(onlyFinallys) + { + // + // Only execute the finally if this is an exception or we leave the block. + // + if(ptrEhExt->IsFinally() && (!to || (to < ptrEhExt->m_tryStart || to >= ptrEhExt->m_tryEnd))) + { +#if defined(TINYCLR_TRACE_EXCEPTIONS) + if(s_CLR_RT_fTrace_Exceptions >= c_CLR_RT_Trace_Obnoxious) + { + CLR_Debug::Printf( "Found match for a 'finally'\r\n" ); + } +#endif + + eh = *ptrEhExt; + return true; + } + } + else + { + if(ptrEhExt->IsCatchAll()) + { +#if defined(TINYCLR_TRACE_EXCEPTIONS) + if(s_CLR_RT_fTrace_Exceptions >= c_CLR_RT_Trace_Annoying) + { + CLR_Debug::Printf( "Found match for a 'catch all'\r\n" ); + } +#endif + + eh = *ptrEhExt; + return true; // Catch all... + } + else + { + if(ptrEhExt->IsFilter() || CLR_RT_ExecutionEngine::IsInstanceOf( m_currentException, ptrEhExt->m_typeFilter )) + { +#if defined(TINYCLR_TRACE_EXCEPTIONS) + if(s_CLR_RT_fTrace_Exceptions >= c_CLR_RT_Trace_Annoying) + { + if (ptrEhExt->IsFilter()) + { + CLR_Debug::Printf( "Trying a 'filter'\r\n" ); + } + else + { + CLR_Debug::Printf( "Found match for a 'catch'\r\n" ); + } + } +#endif + + eh = *ptrEhExt; + return true; + } + } + } + } + + ptrEhExt++; + } + } + +#if defined(TINYCLR_TRACE_EXCEPTIONS) + if(s_CLR_RT_fTrace_Exceptions >= c_CLR_RT_Trace_Annoying) + { + if(to == NULL || s_CLR_RT_fTrace_Exceptions >= c_CLR_RT_Trace_Obnoxious) + { + CLR_Debug::Printf( "No match\r\n" ); + } + } +#endif + + return false; +} + +//--// + +HRESULT CLR_RT_Thread::Execute() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + +#if defined(TINYCLR_APPDOMAINS) + CLR_RT_AppDomain* appDomainSav = g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( this->CurrentAppDomain() ); +#endif + + CLR_RT_Thread* currentThreadSav = g_CLR_RT_ExecutionEngine.m_currentThread; + + g_CLR_RT_ExecutionEngine.m_currentThread = this; + + if(m_currentException.Dereference() != NULL) + { + hr = CLR_E_PROCESS_EXCEPTION; + } + else + { + hr = S_OK; + } + + m_timeQuantumExpired = FALSE; + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + _ASSERTE(!CLR_EE_DBG_IS( Stopped )); +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + ::Events_SetBoolTimer( (BOOL*)&m_timeQuantumExpired, CLR_RT_Thread::c_TimeQuantum_Milliseconds ); + + while(m_timeQuantumExpired == FALSE && !CLR_EE_DBG_IS( Stopped )) + { + CLR_RT_StackFrame* stack; + + if(SUCCEEDED(hr)) + { + hr = Execute_Inner(); if(SUCCEEDED(hr)) TINYCLR_LEAVE(); + } + + switch(hr) + { + case CLR_E_THREAD_WAITING: + case CLR_E_RESCHEDULE: + TINYCLR_LEAVE(); + + case CLR_E_PROCESS_EXCEPTION: + CLR_RT_DUMP::POST_PROCESS_EXCEPTION( m_currentException ); + break; + + default: // Allocate a new exception. + stack = CurrentFrame(); + if(stack->Prev() != NULL) + { +#if defined(TINYCLR_TRACE_INSTRUCTIONS) && defined(PLATFORM_WINDOWS_EMULATOR) + for(int i = 0; i < ARRAYSIZE(s_track); i++) + { + BackTrackExecution& track = s_track[ (s_trackPos+i) % ARRAYSIZE(s_track) ]; + + CLR_Debug::Printf( " %3d ", track.m_depth ); + + CLR_RT_MethodDef_Instance inst; inst.InitializeFromIndex( track.m_call ); + + //track.m_assm->DumpOpcodeDirect( inst, track.m_IP, track.m_IPstart, track.m_pid ); + } + + CLR_Debug::Printf( "\r\n" ); +#endif + + (void)Library_corlib_native_System_Exception::CreateInstance( m_currentException, hr, stack ); + } + + hr = CLR_E_PROCESS_EXCEPTION; + break; + } + + // + // Process exception. + // + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + if(CLR_EE_DBG_IS( Stopped )) break; +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + TINYCLR_CHECK_HRESULT(ProcessException()); + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + if(CLR_EE_DBG_IS( Stopped )) break; +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + if(m_currentException.Dereference() != NULL) { break; } + } + + TINYCLR_SET_AND_LEAVE(CLR_S_QUANTUM_EXPIRED); + + TINYCLR_CLEANUP(); + +#if defined(TINYCLR_APPDOMAINS) + g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomainSav ); +#endif + + g_CLR_RT_ExecutionEngine.m_currentThread = currentThreadSav; + + ::Events_SetBoolTimer( NULL, 0 ); + + TINYCLR_CLEANUP_END(); +} + +HRESULT CLR_RT_Thread::Execute_Inner() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + while(m_timeQuantumExpired == FALSE && !CLR_EE_DBG_IS( Stopped )) + { + CLR_RT_StackFrame *stack = CurrentFrame(); + + #if defined(ENABLE_NATIVE_PROFILER) + if(stack->m_owningThread->m_fNativeProfiled == true) + { + Native_Profiler_Start(); + } + #endif + + if(stack->Prev() == NULL) + { + m_status = CLR_RT_Thread::TH_S_Terminated; + + TINYCLR_SET_AND_LEAVE(CLR_S_THREAD_EXITED); // End of Thread. + } + + if(stack->m_flags & CLR_RT_StackFrame::c_ProcessSynchronize) + { +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + if(stack->m_flags & CLR_RT_StackFrame::c_InvalidIP) + { + TINYCLR_SET_AND_LEAVE(CLR_E_FAIL); + } +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + // + // Thread cannot run if a lock request is still pending... + // + if(stack->m_flags & (CLR_RT_StackFrame::c_PendingSynchronizeGlobally | CLR_RT_StackFrame::c_PendingSynchronize)) + { + TINYCLR_SET_AND_LEAVE(CLR_E_THREAD_WAITING); + } + + if(stack->m_flags & CLR_RT_StackFrame::c_NeedToSynchronizeGlobally) + { + stack->m_flags &= ~CLR_RT_StackFrame::c_NeedToSynchronizeGlobally; + + if(FAILED(hr = stack->HandleSynchronized( true, true ))) + { + if(hr == CLR_E_THREAD_WAITING) + { + stack->m_flags |= CLR_RT_StackFrame::c_PendingSynchronizeGlobally; + } + + TINYCLR_LEAVE(); + } + + stack->m_flags |= CLR_RT_StackFrame::c_SynchronizedGlobally; + } + + if(stack->m_flags & CLR_RT_StackFrame::c_NeedToSynchronize) + { + stack->m_flags &= ~CLR_RT_StackFrame::c_NeedToSynchronize; + + if(FAILED(hr = stack->HandleSynchronized( true, false ))) + { + if(hr == CLR_E_THREAD_WAITING) + { + stack->m_flags |= CLR_RT_StackFrame::c_PendingSynchronize; + } + + TINYCLR_LEAVE(); + } + + stack->m_flags |= CLR_RT_StackFrame::c_Synchronized; + } + } + + { +#if defined(TINYCLR_PROFILE_NEW_CALLS) + CLR_PROF_HANDLER_CALLCHAIN( pm2, stack->m_callchain ); +#endif + + CLR_UINT32 methodKind = (stack->m_flags & CLR_RT_StackFrame::c_MethodKind_Mask); + + switch(methodKind) + { + case CLR_RT_StackFrame::c_MethodKind_Native: + CLR_RT_ExecutionEngine::ExecutionConstraint_Suspend(); + break; + + case CLR_RT_StackFrame::c_MethodKind_Interpreted: + //_ASSERTE((stack->m_flags & CLR_RT_StackFrame::c_InvalidIP) == 0); + stack->m_flags |= CLR_RT_StackFrame::c_ExecutingIL; + break; + } + + // perform systematic GC and compaction under memory pressure + // (g_CLR_RT_GarbageCollector.m_freeBytes refers to last time GC was run) + if(g_CLR_RT_GarbageCollector.m_freeBytes < g_CLR_RT_GarbageCollector.c_memoryThreshold2) + { + stack->m_flags |= CLR_RT_StackFrame::c_CompactAndRestartOnOutOfMemory; + } + + while(true) + { + { + #if defined(ENABLE_NATIVE_PROFILER) + if(stack->m_flags & CLR_RT_StackFrame::c_NativeProfiled) + { + Native_Profiler_Start(); + } + else if(stack->m_fNativeProfiled == false) + { + stack->m_owningThread->m_fNativeProfiled = false; + Native_Profiler_Stop(); + } + #endif + + hr = stack->m_nativeMethod( *stack ); + } + + // check for exception injected by native code + if(m_currentException.Dereference() != NULL) + { + hr = CLR_E_PROCESS_EXCEPTION; + } + + //The inner loop may push or pop more stack frames + stack = CurrentFrame(); + + if(stack->Prev() == NULL) + { + m_status = CLR_RT_Thread::TH_S_Terminated; + + TINYCLR_SET_AND_LEAVE(CLR_S_THREAD_EXITED); // End of Thread. + } + + if(hr == CLR_E_OUT_OF_MEMORY && (stack->m_flags & CLR_RT_StackFrame::c_CompactAndRestartOnOutOfMemory)) + { + stack->m_flags &= ~CLR_RT_StackFrame::c_CompactAndRestartOnOutOfMemory; + + g_CLR_RT_ExecutionEngine.PerformHeapCompaction(); + } + else + { + break; + } + } + + switch(methodKind) + { + case CLR_RT_StackFrame::c_MethodKind_Native: + CLR_RT_ExecutionEngine::ExecutionConstraint_Resume(); + break; + } + + if(FAILED(hr)) + { + // + // CLR_E_RESTART_EXECUTION is used to inject calls to methods from native code. + // + if(hr != CLR_E_RESTART_EXECUTION) TINYCLR_LEAVE(); + } + else + { + stack->m_flags &= ~CLR_RT_StackFrame::c_ExecutingIL; + + if(hr == S_OK) + { + CurrentFrame()->Pop(); + } + } + } + } + + TINYCLR_SET_AND_LEAVE(CLR_S_QUANTUM_EXPIRED); + + TINYCLR_CLEANUP(); + + #if defined(ENABLE_NATIVE_PROFILER) + Native_Profiler_Stop(); + #endif + + TINYCLR_CLEANUP_END(); +} + +HRESULT CLR_RT_Thread::Execute_DelegateInvoke( CLR_RT_StackFrame* stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + const CLR_RECORD_METHODDEF* md; + CLR_RT_HeapBlock_Delegate* dlg; + CLR_RT_HeapBlock* array; + CLR_RT_HeapBlock* ptr; + CLR_UINT32 num; + + ptr = &stack->m_arguments[ 0 ]; if(ptr->DataType() != DATATYPE_OBJECT) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + dlg = ptr->DereferenceDelegate(); FAULT_ON_NULL(dlg); + + md = stack->m_call.m_target; + + switch(dlg->DataType()) + { + case DATATYPE_DELEGATE_HEAD: + array = ptr; + num = 1; + break; + + case DATATYPE_DELEGATELIST_HEAD: + { + CLR_RT_HeapBlock_Delegate_List* list = ptr->DereferenceDelegateList(); + + array = list->GetDelegates(); + num = list->m_length; + } + break; + + default: + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + while(true) + { + if(stack->m_customState >= num) // We have called all the delegates, let's return. + { + TINYCLR_SET_AND_LEAVE(S_OK); + } + + dlg = array[ stack->m_customState++ ].DereferenceDelegate(); + + if(dlg == NULL || dlg->DataType() != DATATYPE_DELEGATE_HEAD) continue; + + break; + } + + //--// + + stack->ResetStack(); + + { + CLR_RT_ProtectFromGC gc( *dlg ); + CLR_RT_MethodDef_Instance inst; inst.InitializeFromIndex( dlg->DelegateFtn() ); + bool fStaticMethod = (inst.m_target->flags & CLR_RECORD_METHODDEF::MD_Static) != 0; + + TINYCLR_CHECK_HRESULT(stack->MakeCall(inst, fStaticMethod ? NULL : &dlg->m_object, &stack->m_arguments[ 1 ], md->numArgs - 1 )); + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_Thread::Execute_IL( CLR_RT_StackFrame* stack ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_Thread* th = stack->m_owningThread; + CLR_RT_Assembly* assm = stack->m_call.m_assm; + CLR_RT_HeapBlock* evalPos; + CLR_PMETADATA ip; + bool fCondition; + bool fDirty = false; + + READCACHE(stack,evalPos,ip,fDirty); + + while(true) + { +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + if(th->m_timeQuantumExpired == TRUE) + { + TINYCLR_SET_AND_LEAVE( CLR_S_QUANTUM_EXPIRED ); + } +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + +#if defined(TINYCLR_TRACE_EXCEPTIONS) && defined(_WIN32) + if(s_CLR_RT_fTrace_Exceptions >= c_CLR_RT_Trace_Annoying) + { + CLR_PROF_HANDLER_SUSPEND_TIME(); + + BackTrackExecution& track = s_track[ s_trackPos++ ]; s_trackPos %= ARRAYSIZE(s_track); + int depth = 0; + + TINYCLR_FOREACH_NODE_BACKWARD__DIRECT(CLR_RT_StackFrame,tmp,stack) + { + depth++; + } + TINYCLR_FOREACH_NODE_BACKWARD_END(); + + track.m_assm = assm; + track.m_call = stack->m_call; + track.m_IP = ip; + track.m_IPstart = stack->m_IPstart; + track.m_pid = stack->m_owningThread->m_pid; + track.m_depth = depth; + + CLR_PROF_HANDLER_RESUME_TIME(); + } +#endif + + assm->DumpOpcode( stack, ip ); + + CLR_OPCODE op = CLR_OPCODE(*ip++); + +Execute_RestartDecoding: + +#if defined(TINYCLR_OPCODE_STACKCHANGES) + if(op != CEE_PREFIX1) + { + TINYCLR_CHECK_HRESULT(CLR_Checks::VerifyStackOK( *stack, &evalPos[ 1 ], c_CLR_RT_OpcodeLookup[ op ].StackChanges() )); + } +#endif + + { + //////////////////////// + // + // +#if defined(PLATFORM_WINDOWS_EMULATOR) + if(s_CLR_RT_fTrace_SimulateSpeed > c_CLR_RT_Trace_None) + { + CLR_PROF_Handler::SuspendTime(); + + HAL_Windows_FastSleep( g_HAL_Configuration_Windows.TicksPerOpcode ); + + CLR_PROF_Handler::ResumeTime(); + } +#endif + // + // + //////////////////////// + + //--// + + + switch(op) + { +#define OPDEF(name,string,pop,push,oprType,opcType,l,s1,s2,ctrl) case name: + OPDEF(CEE_PREFIX1, "prefix1", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFE, META) + { + op = CLR_OPCODE(*ip++ + 256); + goto Execute_RestartDecoding; + } + + OPDEF(CEE_BREAK, "break", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x01, BREAK) + break; + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDARG_0, "ldarg.0", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x02, NEXT) + // Stack: ... ... -> ... + { + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].Assign( stack->m_arguments[ 0 ] ); + + goto Execute_LoadAndPromote; + } + + OPDEF(CEE_LDARG_1, "ldarg.1", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x03, NEXT) + OPDEF(CEE_LDARG_2, "ldarg.2", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x04, NEXT) + OPDEF(CEE_LDARG_3, "ldarg.3", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x05, NEXT) + // Stack: ... ... -> ... + { + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].Assign( stack->m_arguments[ op - CEE_LDARG_0 ] ); + + goto Execute_LoadAndPromote; + } + + OPDEF(CEE_LDARG_S, "ldarg.s", Pop0, Push1, ShortInlineVar, IMacro, 1, 0xFF, 0x0E, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_UINT8(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].Assign( stack->m_arguments[ arg ] ); + + goto Execute_LoadAndPromote; + } + + OPDEF(CEE_LDARG, "ldarg", Pop0, Push1, InlineVar, IPrimitive, 2, 0xFE, 0x09, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_UINT16(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].Assign( stack->m_arguments[ arg ] ); + + goto Execute_LoadAndPromote; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDLOC_0, "ldloc.0", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x06, NEXT) + // Stack: ... ... -> ... + { + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].Assign( stack->m_locals[ 0 ] ); + + goto Execute_LoadAndPromote; + } + + OPDEF(CEE_LDLOC_1, "ldloc.1", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x07, NEXT) + // Stack: ... ... -> ... + { + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].Assign( stack->m_locals[ 1 ] ); + + goto Execute_LoadAndPromote; + } + + OPDEF(CEE_LDLOC_2, "ldloc.2", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x08, NEXT) + // Stack: ... ... -> ... + { + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].Assign( stack->m_locals[ 2 ] ); + + goto Execute_LoadAndPromote; + } + + OPDEF(CEE_LDLOC_3, "ldloc.3", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x09, NEXT) + // Stack: ... ... -> ... + { + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].Assign( stack->m_locals[ 3 ] ); + + goto Execute_LoadAndPromote; + } + + OPDEF(CEE_LDLOC_S, "ldloc.s", Pop0, Push1, ShortInlineVar, IMacro, 1, 0xFF, 0x11, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_UINT8(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].Assign( stack->m_locals[ arg ] ); + + goto Execute_LoadAndPromote; + } + + OPDEF(CEE_LDLOC, "ldloc", Pop0, Push1, InlineVar, IPrimitive, 2, 0xFE, 0x0C, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_UINT16(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].Assign( stack->m_locals[ arg ] ); + + goto Execute_LoadAndPromote; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDLOCA_S, "ldloca.s", Pop0, PushI, ShortInlineVar, IMacro, 1, 0xFF, 0x12, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_UINT8(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetReference( stack->m_locals[ arg ] ); + break; + } + + OPDEF(CEE_LDLOCA, "ldloca", Pop0, PushI, InlineVar, IPrimitive, 2, 0xFE, 0x0D, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_UINT16(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetReference( stack->m_locals[ arg ] ); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDARGA_S, "ldarga.s", Pop0, PushI, ShortInlineVar, IMacro, 1, 0xFF, 0x0F, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_UINT8(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetReference( stack->m_arguments[ arg ] ); + break; + } + + OPDEF(CEE_LDARGA, "ldarga", Pop0, PushI, InlineVar, IPrimitive, 2, 0xFE, 0x0A, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_UINT16(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetReference( stack->m_arguments[ arg ] ); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_STLOC_0, "stloc.0", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0A, NEXT) + OPDEF(CEE_STLOC_1, "stloc.1", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0B, NEXT) + OPDEF(CEE_STLOC_2, "stloc.2", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0C, NEXT) + OPDEF(CEE_STLOC_3, "stloc.3", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0D, NEXT) + // Stack: ... ... -> ... + { + stack->m_locals[ op - CEE_STLOC_0 ].AssignPreserveTypeCheckPinned( evalPos[ 0 ] ); + + evalPos--; CHECKSTACK(stack,evalPos); + break; + } + + OPDEF(CEE_STLOC_S, "stloc.s", Pop1, Push0, ShortInlineVar, IMacro, 1, 0xFF, 0x13, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_UINT8(arg,ip); + + stack->m_locals[ arg ].AssignPreserveTypeCheckPinned( evalPos[ 0 ] ); + + evalPos--; CHECKSTACK(stack,evalPos); + break; + } + + OPDEF(CEE_STLOC, "stloc", Pop1, Push0, InlineVar, IPrimitive, 2, 0xFE, 0x0E, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_UINT16(arg,ip); + + stack->m_locals[ arg ].AssignPreserveTypeCheckPinned( evalPos[ 0 ] ); + + evalPos--; CHECKSTACK(stack,evalPos); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_STARG_S, "starg.s", Pop1, Push0, ShortInlineVar, IMacro, 1, 0xFF, 0x10, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_UINT8(arg,ip); + + stack->m_arguments[ arg ].AssignAndPreserveType( evalPos[ 0 ] ); + + evalPos--; CHECKSTACK(stack,evalPos); + break; + } + + OPDEF(CEE_STARG, "starg", Pop1, Push0, InlineVar, IPrimitive, 2, 0xFE, 0x0B, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_UINT16(arg,ip); + + stack->m_arguments[ arg ].AssignAndPreserveType( evalPos[ 0 ] ); + + evalPos--; CHECKSTACK(stack,evalPos); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDNULL, "ldnull", Pop0, PushRef, InlineNone, IPrimitive, 1, 0xFF, 0x14, NEXT) + // Stack: ... ... -> ... + { + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetObjectReference( NULL ); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDC_I4_M1, "ldc.i4.m1", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x15, NEXT) + OPDEF(CEE_LDC_I4_0, "ldc.i4.0", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x16, NEXT) + OPDEF(CEE_LDC_I4_1, "ldc.i4.1", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x17, NEXT) + OPDEF(CEE_LDC_I4_2, "ldc.i4.2", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x18, NEXT) + OPDEF(CEE_LDC_I4_3, "ldc.i4.3", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x19, NEXT) + OPDEF(CEE_LDC_I4_4, "ldc.i4.4", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1A, NEXT) + OPDEF(CEE_LDC_I4_5, "ldc.i4.5", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1B, NEXT) + OPDEF(CEE_LDC_I4_6, "ldc.i4.6", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1C, NEXT) + OPDEF(CEE_LDC_I4_7, "ldc.i4.7", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1D, NEXT) + OPDEF(CEE_LDC_I4_8, "ldc.i4.8", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1E, NEXT) + // Stack: ... ... -> ... + { + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetInteger( (CLR_INT32)op - (CLR_INT32)CEE_LDC_I4_0 ); + break; + } + + OPDEF(CEE_LDC_I4_S, "ldc.i4.s", Pop0, PushI, ShortInlineI, IMacro, 1, 0xFF, 0x1F, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_INT8(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetInteger( (CLR_INT32)arg ); + break; + } + + OPDEF(CEE_LDC_I4, "ldc.i4", Pop0, PushI, InlineI, IPrimitive, 1, 0xFF, 0x20, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_INT32(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetInteger( (CLR_INT32)arg ); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDC_I8, "ldc.i8", Pop0, PushI8, InlineI8, IPrimitive, 1, 0xFF, 0x21, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_INT64(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetInteger( (CLR_INT64)arg ); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDC_R4, "ldc.r4", Pop0, PushR4, ShortInlineR, IPrimitive, 1, 0xFF, 0x22, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_UINT32(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); + +#if !defined(TINYCLR_EMULATED_FLOATINGPOINT) + evalPos[ 0 ].SetFloatFromBits( arg ); +#else + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].SetFloatIEEE754( arg )); +#endif + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDC_R8, "ldc.r8", Pop0, PushR8, InlineR, IPrimitive, 1, 0xFF, 0x23, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_UINT64(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); +#if !defined(TINYCLR_EMULATED_FLOATINGPOINT) + evalPos[ 0 ].SetDoubleFromBits( arg ); +#else + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].SetDoubleIEEE754( arg )); +#endif + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_DUP, "dup", Pop1, Push1+Push1, InlineNone, IPrimitive, 1, 0xFF, 0x25, NEXT) + // Stack: ... ... -> ... + { + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].Assign( evalPos[ -1 ] ); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_POP, "pop", Pop1, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x26, NEXT) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + break; + } + + //----------------------------------------------------------------------------------------------------------// + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_BR_S, "br.s", Pop0, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2B, BRANCH) + OPDEF(CEE_BR, "br", Pop0, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0x38, BRANCH) + { + fCondition = true; + goto Execute_BR; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_BRFALSE_S, "brfalse.s", PopI, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2C, COND_BRANCH) + OPDEF(CEE_BRFALSE, "brfalse", PopI, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0x39, COND_BRANCH) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + fCondition = (evalPos[ 1 ].IsZero() == true); + goto Execute_BR; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_BRTRUE_S, "brtrue.s", PopI, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2D, COND_BRANCH) + OPDEF(CEE_BRTRUE, "brtrue", PopI, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0x3A, COND_BRANCH) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + fCondition = (evalPos[ 1 ].IsZero() == false); + goto Execute_BR; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_BEQ_S, "beq.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2E, COND_BRANCH) + OPDEF(CEE_BEQ, "beq", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3B, COND_BRANCH) + // Stack: ... ... -> ... + { + evalPos -= 2; CHECKSTACK(stack,evalPos); + + fCondition = (CLR_RT_HeapBlock::Compare_Signed_Values( evalPos[ 1 ], evalPos[ 2 ] ) == 0); + goto Execute_BR; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_BGE_S, "bge.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2F, COND_BRANCH) + OPDEF(CEE_BGE, "bge", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3C, COND_BRANCH) + // Stack: ... ... -> ... + { + evalPos -= 2; CHECKSTACK(stack,evalPos); + + fCondition = (CLR_RT_HeapBlock::Compare_Signed_Values( evalPos[ 1 ], evalPos[ 2 ] ) >= 0); + goto Execute_BR; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_BGT_S, "bgt.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x30, COND_BRANCH) + OPDEF(CEE_BGT, "bgt", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3D, COND_BRANCH) + // Stack: ... ... -> ... + { + evalPos -= 2; CHECKSTACK(stack,evalPos); + + fCondition = (CLR_RT_HeapBlock::Compare_Signed_Values( evalPos[ 1 ], evalPos[ 2 ] ) > 0); + goto Execute_BR; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_BLE_S, "ble.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x31, COND_BRANCH) + OPDEF(CEE_BLE, "ble", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3E, COND_BRANCH) + // Stack: ... ... -> ... + { + evalPos -= 2; CHECKSTACK(stack,evalPos); + + fCondition = (CLR_RT_HeapBlock::Compare_Signed_Values( evalPos[ 1 ], evalPos[ 2 ] ) <= 0); + goto Execute_BR; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_BLT_S, "blt.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x32, COND_BRANCH) + OPDEF(CEE_BLT, "blt", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3F, COND_BRANCH) + // Stack: ... ... -> ... + { + evalPos -= 2; CHECKSTACK(stack,evalPos); + + fCondition = (CLR_RT_HeapBlock::Compare_Signed_Values( evalPos[ 1 ], evalPos[ 2 ] ) < 0); + goto Execute_BR; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_BNE_UN_S, "bne.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x33, COND_BRANCH) + OPDEF(CEE_BNE_UN, "bne.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x40, COND_BRANCH) + // Stack: ... ... -> ... + { + evalPos -= 2; CHECKSTACK(stack,evalPos); + + fCondition = (CLR_RT_HeapBlock::Compare_Unsigned_Values( evalPos[ 1 ], evalPos[ 2 ] ) != 0); + goto Execute_BR; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_BGE_UN_S, "bge.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x34, COND_BRANCH) + OPDEF(CEE_BGE_UN, "bge.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x41, COND_BRANCH) + // Stack: ... ... -> ... + { + evalPos -= 2; CHECKSTACK(stack,evalPos); + + fCondition = (CLR_RT_HeapBlock::Compare_Unsigned_Values( evalPos[ 1 ], evalPos[ 2 ] ) >= 0); + goto Execute_BR; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_BGT_UN_S, "bgt.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x35, COND_BRANCH) + OPDEF(CEE_BGT_UN, "bgt.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x42, COND_BRANCH) + // Stack: ... ... -> ... + { + evalPos -= 2; CHECKSTACK(stack,evalPos); + + fCondition = (CLR_RT_HeapBlock::Compare_Unsigned_Values( evalPos[ 1 ], evalPos[ 2 ] ) > 0); + goto Execute_BR; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_BLE_UN_S, "ble.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x36, COND_BRANCH) + OPDEF(CEE_BLE_UN, "ble.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x43, COND_BRANCH) + // Stack: ... ... -> ... + { + evalPos -= 2; CHECKSTACK(stack,evalPos); + + fCondition = (CLR_RT_HeapBlock::Compare_Unsigned_Values( evalPos[ 1 ], evalPos[ 2 ] ) <= 0); + goto Execute_BR; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_BLT_UN_S, "blt.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x37, COND_BRANCH) + OPDEF(CEE_BLT_UN, "blt.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x44, COND_BRANCH) + // Stack: ... ... -> ... + { + evalPos -= 2; CHECKSTACK(stack,evalPos); + + fCondition = (CLR_RT_HeapBlock::Compare_Unsigned_Values( evalPos[ 1 ], evalPos[ 2 ] ) < 0); + goto Execute_BR; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_SWITCH, "switch", PopI, Push0, InlineSwitch, IPrimitive, 1, 0xFF, 0x45, COND_BRANCH) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + FETCH_ARG_UINT8(arg,ip); + + CLR_UINT32 numCases = arg; + CLR_UINT32 caseSelected = evalPos[ 1 ].NumericByRef().u4; + + if(caseSelected < numCases) + { + CLR_PMETADATA ipsub = ip + (CLR_INT32)caseSelected * sizeof(CLR_INT16); + + FETCH_ARG_INT16(offset,ipsub); + + ip += offset; + } + + ip += (CLR_INT32)numCases * sizeof(CLR_INT16); + break; + } + + //----------------------------------------------------------------------------------------------------------// + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDIND_I1, "ldind.i1", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x46, NEXT) + OPDEF(CEE_LDIND_U1, "ldind.u1", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x47, NEXT) + OPDEF(CEE_LDIND_I2, "ldind.i2", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x48, NEXT) + OPDEF(CEE_LDIND_U2, "ldind.u2", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x49, NEXT) + OPDEF(CEE_LDIND_I4, "ldind.i4", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x4A, NEXT) + OPDEF(CEE_LDIND_U4, "ldind.u4", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x4B, NEXT) + OPDEF(CEE_LDIND_I8, "ldind.i8", PopI, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x4C, NEXT) + OPDEF(CEE_LDIND_I, "ldind.i", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x4D, NEXT) + OPDEF(CEE_LDIND_R4, "ldind.r4", PopI, PushR4, InlineNone, IPrimitive, 1, 0xFF, 0x4E, NEXT) + OPDEF(CEE_LDIND_R8, "ldind.r8", PopI, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0x4F, NEXT) + OPDEF(CEE_LDIND_REF, "ldind.ref", PopI, PushRef, InlineNone, IPrimitive, 1, 0xFF, 0x50, NEXT) + // Stack: ... ...
-> ... + { + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].LoadFromReference( evalPos[ 0 ] )); + + goto Execute_LoadAndPromote; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_STIND_REF, "stind.ref", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x51, NEXT) + OPDEF(CEE_STIND_I1, "stind.i1", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x52, NEXT) + OPDEF(CEE_STIND_I2, "stind.i2", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x53, NEXT) + OPDEF(CEE_STIND_I4, "stind.i4", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x54, NEXT) + OPDEF(CEE_STIND_I8, "stind.i8", PopI+PopI8, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x55, NEXT) + OPDEF(CEE_STIND_R4, "stind.r4", PopI+PopR4, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x56, NEXT) + OPDEF(CEE_STIND_R8, "stind.r8", PopI+PopR8, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x57, NEXT) + OPDEF(CEE_STIND_I, "stind.i", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xDF, NEXT) + // Stack: ... ...
-> ... + { + int size = 0; + + evalPos -= 2; CHECKSTACK(stack,evalPos); + + switch(op) + { + case CEE_STIND_I : size = 4; break; + case CEE_STIND_I1 : size = 1; break; + case CEE_STIND_I2 : size = 2; break; + case CEE_STIND_I4 : size = 4; break; + case CEE_STIND_I8 : size = 8; break; + case CEE_STIND_R4 : size = 4; break; + case CEE_STIND_R8 : size = 8; break; + case CEE_STIND_REF: size = 0; break; + } + + evalPos[ 2 ].Promote(); + + TINYCLR_CHECK_HRESULT(evalPos[ 2 ].StoreToReference( evalPos[ 1 ], size )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_ADD, "add", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x58, NEXT) + OPDEF(CEE_ADD_OVF, "add.ovf", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD6, NEXT) + OPDEF(CEE_ADD_OVF_UN, "add.ovf.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD7, NEXT) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].NumericAdd( evalPos[ 1 ] )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_SUB, "sub", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x59, NEXT) + OPDEF(CEE_SUB_OVF, "sub.ovf", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xDA, NEXT) + OPDEF(CEE_SUB_OVF_UN, "sub.ovf.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xDB, NEXT) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].NumericSub( evalPos[ 1 ] )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_MUL, "mul", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5A, NEXT) + OPDEF(CEE_MUL_OVF, "mul.ovf", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD8, NEXT) + OPDEF(CEE_MUL_OVF_UN, "mul.ovf.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD9, NEXT) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].NumericMul( evalPos[ 1 ] )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_DIV, "div", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5B, NEXT) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].NumericDiv( evalPos[ 1 ] )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_DIV_UN, "div.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5C, NEXT) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].NumericDivUn( evalPos[ 1 ] )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_REM, "rem", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5D, NEXT) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].NumericRem( evalPos[ 1 ] )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_REM_UN, "rem.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5E, NEXT) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].NumericRemUn( evalPos[ 1 ] )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_AND, "and", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5F, NEXT) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].NumericByRef().u8 &= evalPos[ 1 ].NumericByRef().u8; + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_OR, "or", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x60, NEXT) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].NumericByRef().u8 |= evalPos[ 1 ].NumericByRef().u8; + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_XOR, "xor", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x61, NEXT) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].NumericByRef().u8 ^= evalPos[ 1 ].NumericByRef().u8; + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_SHL, "shl", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x62, NEXT) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].NumericShl( evalPos[ 1 ] )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_SHR, "shr", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x63, NEXT) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].NumericShr( evalPos[ 1 ] )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_SHR_UN, "shr.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x64, NEXT) + // Stack: ... ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].NumericShrUn( evalPos[ 1 ] )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_NEG, "neg", Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x65, NEXT) + // Stack: ... ... -> ... + { + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].NumericNeg()); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_NOT, "not", Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x66, NEXT) + // Stack: ... ... -> ... + { + evalPos[ 0 ].NumericByRef().u8 = ~evalPos[ 0 ].NumericByRef().u8; + break; + } + + //----------------------------------------------------------------------------------------------------------// + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CONV_I1, "conv.i1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x67, NEXT) + OPDEF(CEE_CONV_OVF_I1, "conv.ovf.i1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB3, NEXT) + OPDEF(CEE_CONV_OVF_I1_UN, "conv.ovf.i1.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x82, NEXT) + // Stack: ... ... -> ... + { + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].Convert( DATATYPE_I1, op != CEE_CONV_I1, op == CEE_CONV_OVF_I1_UN )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CONV_I2, "conv.i2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x68, NEXT) + OPDEF(CEE_CONV_OVF_I2, "conv.ovf.i2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB5, NEXT) + OPDEF(CEE_CONV_OVF_I2_UN, "conv.ovf.i2.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x83, NEXT) + // Stack: ... ... -> ... + { + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].Convert( DATATYPE_I2, op != CEE_CONV_I2, op == CEE_CONV_OVF_I2_UN )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CONV_I4, "conv.i4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x69, NEXT) + OPDEF(CEE_CONV_OVF_I4, "conv.ovf.i4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB7, NEXT) + OPDEF(CEE_CONV_OVF_I4_UN, "conv.ovf.i4.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x84, NEXT) + // Stack: ... ... -> ... + { + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].Convert( DATATYPE_I4, op != CEE_CONV_I4, op == CEE_CONV_OVF_I4_UN )); + break; + } + + OPDEF(CEE_CONV_I, "conv.i", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD3, NEXT) + OPDEF(CEE_CONV_OVF_I, "conv.ovf.i", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD4, NEXT) + OPDEF(CEE_CONV_OVF_I_UN, "conv.ovf.i.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x8A, NEXT) + // Stack: ... ... -> ... + { + if ( evalPos[ 0 ].DataType() == DATATYPE_BYREF || evalPos[ 0 ].DataType() == DATATYPE_ARRAY_BYREF ) + { + break; + } + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].Convert( DATATYPE_I4, op != CEE_CONV_I, op == CEE_CONV_OVF_I_UN )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CONV_I8, "conv.i8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x6A, NEXT) + OPDEF(CEE_CONV_OVF_I8, "conv.ovf.i8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0xB9, NEXT) + OPDEF(CEE_CONV_OVF_I8_UN, "conv.ovf.i8.un", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x85, NEXT) + // Stack: ... ... -> ... + { + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].Convert( DATATYPE_I8, op != CEE_CONV_I8, op == CEE_CONV_OVF_I8_UN )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CONV_R4, "conv.r4", Pop1, PushR4, InlineNone, IPrimitive, 1, 0xFF, 0x6B, NEXT) + // Stack: ... ... -> ... + { + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].Convert( DATATYPE_R4, false, false )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CONV_R_UN, "conv.r.un", Pop1, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0x76, NEXT) + OPDEF(CEE_CONV_R8, "conv.r8", Pop1, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0x6C, NEXT) + // Stack: ... ... -> ... + { + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].Convert( DATATYPE_R8, false, op == CEE_CONV_R_UN )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CONV_U1, "conv.u1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD2, NEXT) + OPDEF(CEE_CONV_OVF_U1, "conv.ovf.u1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB4, NEXT) + OPDEF(CEE_CONV_OVF_U1_UN, "conv.ovf.u1.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x86, NEXT) + // Stack: ... ... -> ... + { + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].Convert( DATATYPE_U1, op != CEE_CONV_U1, op == CEE_CONV_OVF_U1_UN )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CONV_U2, "conv.u2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD1, NEXT) + OPDEF(CEE_CONV_OVF_U2, "conv.ovf.u2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB6, NEXT) + OPDEF(CEE_CONV_OVF_U2_UN, "conv.ovf.u2.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x87, NEXT) + // Stack: ... ... -> ... + { + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].Convert( DATATYPE_U2, op != CEE_CONV_U2, op == CEE_CONV_OVF_U2_UN )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CONV_U4, "conv.u4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x6D, NEXT) + OPDEF(CEE_CONV_OVF_U4, "conv.ovf.u4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB8, NEXT) + OPDEF(CEE_CONV_OVF_U4_UN, "conv.ovf.u4.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x88, NEXT) + // Stack: ... ... -> ... + { + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].Convert( DATATYPE_U4, op != CEE_CONV_U4, op == CEE_CONV_OVF_U4_UN )); + break; + } + + OPDEF(CEE_CONV_U, "conv.u", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xE0, NEXT) + OPDEF(CEE_CONV_OVF_U, "conv.ovf.u", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD5, NEXT) + OPDEF(CEE_CONV_OVF_U_UN, "conv.ovf.u.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x8B, NEXT) + // Stack: ... ... -> ... + { + if ( evalPos[ 0 ].DataType() == DATATYPE_BYREF || evalPos[ 0 ].DataType() == DATATYPE_ARRAY_BYREF ) + { + break; + } + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].Convert( DATATYPE_U4, op != CEE_CONV_U, op == CEE_CONV_OVF_U_UN )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CONV_U8, "conv.u8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x6E, NEXT) + OPDEF(CEE_CONV_OVF_U8, "conv.ovf.u8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0xBA, NEXT) + OPDEF(CEE_CONV_OVF_U8_UN, "conv.ovf.u8.un", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x89, NEXT) + // Stack: ... ... -> ... + { + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].Convert( DATATYPE_U8, op != CEE_CONV_U8, op == CEE_CONV_OVF_U8_UN )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + //----------------------------------------------------------------------------------------------------------// + OPDEF(CEE_CALL, "call", VarPop, VarPush, InlineMethod, IPrimitive, 1, 0xFF, 0x28, CALL) + OPDEF(CEE_CALLVIRT, "callvirt", VarPop, VarPush, InlineMethod, IObjModel, 1, 0xFF, 0x6F, CALL) + + { + FETCH_ARG_COMPRESSED_METHODTOKEN(arg,ip); + + CLR_RT_MethodDef_Instance calleeInst; if(calleeInst.ResolveToken( arg, assm ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + CLR_RT_TypeDef_Index cls; + CLR_RT_HeapBlock* pThis; +#if defined(TINYCLR_APPDOMAINS) + bool fAppDomainTransition = false; +#endif + + pThis = &evalPos[1-calleeInst.m_target->numArgs]; // Point to the first arg, 'this' if an instance method + + if(calleeInst.m_target->flags & CLR_RECORD_METHODDEF::MD_DelegateInvoke) + { + CLR_RT_HeapBlock_Delegate* dlg = pThis->DereferenceDelegate(); FAULT_ON_NULL(dlg); + + if(dlg->DataType() == DATATYPE_DELEGATE_HEAD) + { + calleeInst.InitializeFromIndex( dlg->DelegateFtn() ); + + if((calleeInst.m_target->flags & CLR_RECORD_METHODDEF::MD_Static) == 0) + { + pThis->Assign( dlg->m_object ); + +#if defined(TINYCLR_APPDOMAINS) + fAppDomainTransition = pThis[ 0 ].IsTransparentProxy(); +#endif + } + else + { + memmove( &pThis[ 0 ], &pThis[ 1 ], calleeInst.m_target->numArgs * sizeof(CLR_RT_HeapBlock) ); + + evalPos--; + } + } + else + { + // + // The lookup for multicast delegates is done at a later stage... + // + } + } + else //Non delegate + { + CLR_RT_MethodDef_Index calleeReal; + + if((calleeInst.m_target->flags & CLR_RECORD_METHODDEF::MD_Static) == 0) + { + //Instance method, pThis[ 0 ] is valid + + if(op == CEE_CALL && pThis[ 0 ].Dereference() == NULL) + { + //CALL on a null instance is allowed, and should not throw a NullReferenceException on the call + //although a NullReferenceException is likely to be thrown soon thereafter if the call tries to access + //any member variables. + } + else + { + TINYCLR_CHECK_HRESULT(CLR_RT_TypeDescriptor::ExtractTypeIndexFromObject( pThis[ 0 ], cls )); + + //This test is for performance reasons. c# emits a callvirt on all instance methods to make sure that + //a NullReferenceException is thrown if 'this' is NULL. However, if the instance method isn't virtual + //we don't need to do the more expensive virtual method lookup. + if(op == CEE_CALLVIRT && (calleeInst.m_target->flags & (CLR_RECORD_METHODDEF::MD_Abstract | CLR_RECORD_METHODDEF::MD_Virtual))) + { + if(g_CLR_RT_EventCache.FindVirtualMethod( cls, calleeInst, calleeReal ) == false) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + calleeInst.InitializeFromIndex( calleeReal ); + } + +#if defined(TINYCLR_APPDOMAINS) + fAppDomainTransition = pThis[ 0 ].IsTransparentProxy(); +#endif + } + } + } + +#if defined(TINYCLR_APPDOMAINS) + if(fAppDomainTransition) + { + WRITEBACK(stack,evalPos,ip,fDirty); + + _ASSERTE(FIMPLIES(pThis->DataType() == DATATYPE_OBJECT, pThis->Dereference() != NULL)); + TINYCLR_CHECK_HRESULT(CLR_RT_StackFrame::PushAppDomainTransition( th, calleeInst, &pThis[ 0 ], &pThis[ 1 ])); + } + else +#endif //TINYCLR_APPDOMAINS + { +#ifndef TINYCLR_NO_IL_INLINE + if(stack->PushInline(ip, assm, evalPos, calleeInst, pThis)) + { + fDirty = true; + break; + } +#endif + + WRITEBACK(stack,evalPos,ip,fDirty); + TINYCLR_CHECK_HRESULT(CLR_RT_StackFrame::Push( th, calleeInst, -1 )); + } + + goto Execute_Restart; + } + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_RET, "ret", VarPop, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x2A, RETURN) + { +#ifndef TINYCLR_NO_IL_INLINE + if(stack->m_inlineFrame) + { + stack->m_evalStackPos = evalPos; + + stack->PopInline(); + + ip = stack->m_IP; + assm = stack->m_call.m_assm; + evalPos = stack->m_evalStackPos-1; + fDirty = true; + + break; + } +#endif + + WRITEBACK(stack,evalPos,ip,fDirty); + + // + // Same kind of handler, no need to pop back out, just restart execution in place. + // + if(stack->m_flags & CLR_RT_StackFrame::c_CallerIsCompatibleForRet) + { + CLR_RT_StackFrame* stackNext = stack->Caller(); + + stack->Pop(); + + stack = stackNext; + goto Execute_Reload; + } + else + { + stack->Pop(); + + TINYCLR_SET_AND_LEAVE(CLR_S_RESTART_EXECUTION); + } + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CPOBJ, "cpobj", PopI+PopI, Push0, InlineType, IObjModel, 1, 0xFF, 0x70, NEXT) + OPDEF(CEE_STOBJ, "stobj", PopI+Pop1, Push0, InlineType, IPrimitive, 1, 0xFF, 0x81, NEXT) + // Stack: ... ... -> ... + { + ip += 2; // Skip argument, not used... + + evalPos -= 2; CHECKSTACK(stack,evalPos); + + // + // Reassign will make sure these are objects of the same type. + // + TINYCLR_CHECK_HRESULT(evalPos[ 1 ].Reassign( evalPos[ 2 ] )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDOBJ, "ldobj", PopI, Push1, InlineType, IObjModel, 1, 0xFF, 0x71, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_COMPRESSED_TYPETOKEN(arg,ip); + + CLR_RT_TypeDef_Instance type; + CLR_RT_TypeDef_Index cls; + + if(type.ResolveToken( arg, assm ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + TINYCLR_CHECK_HRESULT(CLR_RT_TypeDescriptor::ExtractTypeIndexFromObject( evalPos[ 0 ], cls )); + + // Check this is an object of the requested type. + if(type.m_data != cls.m_data) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + UPDATESTACK(stack,evalPos); + + { + // + // Save the pointer to the object to load/copy and protect it from GC. + // + CLR_RT_HeapBlock safeSource; safeSource.Assign( evalPos[ 0 ] ); + CLR_RT_ProtectFromGC gc( safeSource ); + + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].LoadFromReference( safeSource )); + + } + + goto Execute_LoadAndPromote; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDSTR, "ldstr", Pop0, PushRef, InlineString, IObjModel, 1, 0xFF, 0x72, NEXT) + { + FETCH_ARG_COMPRESSED_STRINGTOKEN(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); + + UPDATESTACK(stack,evalPos); + + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( evalPos[ 0 ], arg, assm )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_NEWOBJ, "newobj", VarPop, PushRef, InlineMethod, IObjModel, 1, 0xFF, 0x73, CALL) + // Stack: ... ... -> ... + { + FETCH_ARG_COMPRESSED_METHODTOKEN(arg,ip); + + CLR_RT_MethodDef_Instance calleeInst; if(calleeInst.ResolveToken( arg, assm ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + CLR_RT_TypeDef_Instance cls; + CLR_RT_HeapBlock* top; + CLR_INT32 changes; + + cls.InitializeFromMethod( calleeInst ); // This is the class to create! + + evalPos++; + + WRITEBACK(stack,evalPos,ip,fDirty); + + if(cls.m_target->IsDelegate()) + { + // + // Special case for delegates. LDFTN or LDVIRTFTN have already created the delegate object, just check that... + // + changes = -calleeInst.m_target->numArgs; + TINYCLR_CHECK_HRESULT(CLR_Checks::VerifyStackOK( *stack, stack->m_evalStackPos, changes )); // Check to see if we have enough parameters. + stack->m_evalStackPos += changes; + + top = stack->m_evalStackPos++; // Push back the result. + + if(top[ 1 ].DataType() != DATATYPE_OBJECT) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + CLR_RT_HeapBlock_Delegate* dlg = top[ 1 ].DereferenceDelegate(); + + if(dlg == NULL) + { + TINYCLR_CHECK_HRESULT(CLR_E_NULL_REFERENCE); + } + + dlg->m_cls = cls; + + CLR_RT_MethodDef_Instance dlgInst; + + if(dlgInst.InitializeFromIndex( dlg->DelegateFtn() ) == false) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + if((dlgInst.m_target->flags & CLR_RECORD_METHODDEF::MD_Static) == 0) + { + dlg->m_object.Assign( top[ 0 ] ); + } + + top->SetObjectReference( dlg ); + } + else + { + changes = calleeInst.m_target->numArgs; + TINYCLR_CHECK_HRESULT(CLR_Checks::VerifyStackOK( *stack, stack->m_evalStackPos, -changes )); // Check to see if we have enough parameters. + top = stack->m_evalStackPos; + + // + // We have to insert the 'this' pointer as argument 0, that means moving all the arguments up one slot... + // + top--; + while(--changes > 0) + { + top[ 0 ].Assign( top[ -1 ] ); top--; + } + top->SetObjectReference( NULL ); + + // Stack: ... ... -> ... + // ^ + // Top points here. + + TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObject( top[ 0 ], cls )); + + // + // This is to flag the fact that we need to copy back the 'this' pointer into our stack. + // + // See CLR_RT_StackFrame::Pop() + // + stack->m_flags |= CLR_RT_StackFrame::c_ExecutingConstructor; + + // + // Ok, creating a ValueType then calls its constructor. + // But the constructor will try to load the 'this' pointer and since it's a value type, it will be cloned. + // For the length of the constructor, change the type from an object pointer to a reference. + // + // See CLR_RT_StackFrame::Pop() + // + if((cls.m_target->flags & CLR_RECORD_TYPEDEF::TD_Semantics_Mask) == CLR_RECORD_TYPEDEF::TD_Semantics_ValueType) + { + if(top[ 0 ].DataType() == DATATYPE_OBJECT) + { + top[ 0 ].ChangeDataType( DATATYPE_BYREF ); + } + else + { + // + // This is to support the optimization on DateTime and TimeSpan: + // + // These are passed as built-ins. But we need to pass them as a reference, + // so push everything down and undo the "ExecutingConstructor" trick. + // + top = stack->m_evalStackPos++; + + changes = calleeInst.m_target->numArgs; + while(--changes > 0) + { + top[ 0 ].Assign( top[ -1 ] ); top--; + } + top[ 0 ].SetReference( top[ -1 ] ); + + stack->m_flags &= ~CLR_RT_StackFrame::c_ExecutingConstructor; + } + } + + if(FAILED(hr = CLR_RT_StackFrame::Push( th, calleeInst, -1 ))) + { + if(hr == CLR_E_NOT_SUPPORTED) + { + // no matter what, we are no longer executing a ctor + stack->m_flags &= ~CLR_RT_StackFrame::c_ExecutingConstructor; + } + + TINYCLR_LEAVE(); + } + + goto Execute_Restart; + } + + READCACHE(stack,evalPos,ip,fDirty); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CASTCLASS, "castclass", PopRef, PushRef, InlineType, IObjModel, 1, 0xFF, 0x74, NEXT) + OPDEF(CEE_ISINST, "isinst", PopRef, PushI, InlineType, IObjModel, 1, 0xFF, 0x75, NEXT) + { + FETCH_ARG_COMPRESSED_TYPETOKEN(arg,ip); + + TINYCLR_CHECK_HRESULT(CLR_RT_ExecutionEngine::CastToType( evalPos[ 0 ], arg, assm, (op == CEE_ISINST) )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_THROW, "throw", PopRef, Push0, InlineNone, IObjModel, 1, 0xFF, 0x7A, THROW) + { + th->m_currentException.Assign( evalPos[ 0 ] ); + + EMPTYSTACK(stack, evalPos); + + Library_corlib_native_System_Exception::SetStackTrace( th->m_currentException, stack ); + + TINYCLR_CHECK_HRESULT(CLR_E_PROCESS_EXCEPTION); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDFLD, "ldfld", PopRef, Push1, InlineField, IObjModel, 1, 0xFF, 0x7B, NEXT) + // Stack: ... -> ... + { + FETCH_ARG_COMPRESSED_FIELDTOKEN(arg,ip); + + CLR_RT_FieldDef_Instance fieldInst; if(fieldInst.ResolveToken( arg, assm ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + CLR_RT_HeapBlock* obj = &evalPos[ 0 ]; + CLR_DataType dt = obj->DataType(); + + TINYCLR_CHECK_HRESULT(CLR_RT_TypeDescriptor::ExtractObjectAndDataType(obj, dt)); + + switch(dt) + { + case DATATYPE_CLASS: + case DATATYPE_VALUETYPE: + evalPos[ 0 ].Assign( obj[ fieldInst.CrossReference().m_offset ] ); + goto Execute_LoadAndPromote; + case DATATYPE_DATETIME: + case DATATYPE_TIMESPAN: + evalPos[ 0 ].SetInteger( (CLR_INT64)obj->NumericByRefConst().s8 ); + break; +#if defined(TINYCLR_APPDOMAINS) + case DATATYPE_TRANSPARENT_PROXY: + { + CLR_RT_HeapBlock val; + + TINYCLR_CHECK_HRESULT(obj->TransparentProxyValidate()); + + UPDATESTACK(stack,evalPos); + + TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.GetCurrentAppDomain()->MarshalObject( obj->TransparentProxyDereference()[ fieldInst.CrossReference().m_offset ], val, obj->TransparentProxyAppDomain() )); + + evalPos[ 0 ].Assign( val ); + } + goto Execute_LoadAndPromote; +#endif + default: + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + break; + + } + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDFLDA, "ldflda", PopRef, PushI, InlineField, IObjModel, 1, 0xFF, 0x7C, NEXT) + // Stack: ... ->
... + { + FETCH_ARG_COMPRESSED_FIELDTOKEN(arg,ip); + + CLR_RT_FieldDef_Instance fieldInst; if(fieldInst.ResolveToken( arg, assm ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + CLR_RT_HeapBlock* obj = &evalPos[ 0 ]; + CLR_DataType dt = obj->DataType(); + + TINYCLR_CHECK_HRESULT(CLR_RT_TypeDescriptor::ExtractObjectAndDataType(obj, dt)); + +#if defined(TINYCLR_APPDOMAINS) + _ASSERTE(dt != DATATYPE_TRANSPARENT_PROXY); +#endif + if(dt == DATATYPE_CLASS || dt == DATATYPE_VALUETYPE) + { + evalPos[ 0 ].SetReference( obj[ fieldInst.CrossReference().m_offset ] ); + } + else if(dt == DATATYPE_DATETIME || dt == DATATYPE_TIMESPAN) // Special case. + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); // NOT SUPPORTED. + } + else + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_STFLD, "stfld", PopRef+Pop1, Push0, InlineField, IObjModel, 1, 0xFF, 0x7D, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_COMPRESSED_FIELDTOKEN(arg,ip); + + evalPos -= 2; CHECKSTACK(stack,evalPos); + + CLR_RT_FieldDef_Instance fieldInst; if(fieldInst.ResolveToken( arg, assm ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + CLR_RT_HeapBlock* obj = &evalPos[ 1 ]; + CLR_DataType dt = obj->DataType(); + + TINYCLR_CHECK_HRESULT(CLR_RT_TypeDescriptor::ExtractObjectAndDataType(obj, dt)); + + switch(dt) + { + case DATATYPE_CLASS: + case DATATYPE_VALUETYPE: + obj[ fieldInst.CrossReference().m_offset ].AssignAndPreserveType( evalPos[ 2 ] ); + break; + case DATATYPE_DATETIME: // Special case. + case DATATYPE_TIMESPAN: // Special case. + obj->NumericByRef().s8 = evalPos[ 2 ].NumericByRefConst().s8; + break; + +#if defined(TINYCLR_APPDOMAINS) + case DATATYPE_TRANSPARENT_PROXY: + { + CLR_RT_HeapBlock val; + + UPDATESTACK(stack,evalPos); + + TINYCLR_CHECK_HRESULT(obj->TransparentProxyValidate()); + TINYCLR_CHECK_HRESULT(obj->TransparentProxyAppDomain()->MarshalObject( evalPos[ 2 ], val )); + + obj->TransparentProxyDereference()[ fieldInst.CrossReference().m_offset ].AssignAndPreserveType( val ); + } + break; +#endif + + default: + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + break; + } + + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDSFLD, "ldsfld", Pop0, Push1, InlineField, IObjModel, 1, 0xFF, 0x7E, NEXT) + // Stack: ... -> ... + { + FETCH_ARG_COMPRESSED_FIELDTOKEN(arg,ip); + + CLR_RT_FieldDef_Instance field; if(field.ResolveToken( arg, assm ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + CLR_RT_HeapBlock* ptr = CLR_RT_ExecutionEngine::AccessStaticField( field ); if(ptr == NULL) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].Assign( *ptr ); + + goto Execute_LoadAndPromote; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDSFLDA, "ldsflda", Pop0, PushI, InlineField, IObjModel, 1, 0xFF, 0x7F, NEXT) + // Stack: ... ->
... + { + FETCH_ARG_COMPRESSED_FIELDTOKEN(arg,ip); + + CLR_RT_FieldDef_Instance field; if(field.ResolveToken( arg, assm ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + CLR_RT_HeapBlock* ptr = CLR_RT_ExecutionEngine::AccessStaticField( field ); if(ptr == NULL) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetReference( *ptr ); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_STSFLD, "stsfld", Pop1, Push0, InlineField, IObjModel, 1, 0xFF, 0x80, NEXT) + // Stack: ... ... -> ... + { + FETCH_ARG_COMPRESSED_FIELDTOKEN(arg,ip); + + CLR_RT_FieldDef_Instance field; if(field.ResolveToken( arg, assm ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + CLR_RT_HeapBlock* ptr = CLR_RT_ExecutionEngine::AccessStaticField( field ); if(ptr == NULL) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + evalPos--; CHECKSTACK(stack,evalPos); + + ptr->AssignAndPreserveType( evalPos[ 1 ] ); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_BOX, "box", Pop1, PushRef, InlineType, IPrimitive, 1, 0xFF, 0x8C, NEXT) + OPDEF(CEE_UNBOX, "unbox", PopRef, PushI, InlineType, IPrimitive, 1, 0xFF, 0x79, NEXT) + { + FETCH_ARG_COMPRESSED_TYPETOKEN(arg,ip); + + CLR_RT_TypeDef_Instance typeInst; if(typeInst.ResolveToken( arg, assm ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + UPDATESTACK(stack,evalPos); + + if(op == CEE_BOX) + { + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].PerformBoxing( typeInst )); + } + else + { + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].PerformUnboxing( typeInst )); + } + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_UNBOX_ANY, "unbox.any", PopRef, Push1, InlineType, IObjModel, 1, 0xFF, 0xA5, NEXT) + { + //Stack: ... -> ..., value or obj + FETCH_ARG_COMPRESSED_TYPETOKEN(arg,ip); + + //When applied to the boxed form of a value type, the unbox.any instruction + //extracts the value contained within obj (of type O). (It is equivalent to unbox followed by ldobj.) + //When applied to a reference type, the unbox.any instruction has the same effect as castclass typeTok. + + CLR_RT_TypeDef_Instance typeInst; if(typeInst.ResolveToken( arg, assm ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + UPDATESTACK(stack,evalPos); + + if(((typeInst.m_target->flags & CLR_RECORD_TYPEDEF::TD_Semantics_Mask) == CLR_RECORD_TYPEDEF::TD_Semantics_ValueType) || + ((typeInst.m_target->flags & CLR_RECORD_TYPEDEF::TD_Semantics_Mask) == CLR_RECORD_TYPEDEF::TD_Semantics_Enum )) + { + //"unbox" + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].PerformUnboxing( typeInst )); + + //"ldobj" + { + CLR_RT_HeapBlock safeSource; safeSource.Assign( evalPos[ 0 ] ); + CLR_RT_ProtectFromGC gc( safeSource ); + + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].LoadFromReference( safeSource )); + + goto Execute_LoadAndPromote; + } + } + else + { + //"castclass" + TINYCLR_CHECK_HRESULT(CLR_RT_ExecutionEngine::CastToType( evalPos[ 0 ], arg, assm, false )); + } + + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_NEWARR, "newarr", PopI, PushRef, InlineType, IObjModel, 1, 0xFF, 0x8D, NEXT) + { + + FETCH_ARG_COMPRESSED_TYPETOKEN(arg,ip); + + CLR_UINT32 size = evalPos[ 0 ].NumericByRef().u4; + + UPDATESTACK(stack,evalPos); + + stack->m_flags &= ~CLR_RT_StackFrame::c_CompactAndRestartOnOutOfMemory; // we do not need this in this case + + for(int pass=0; pass<2; pass++) + { + hr = CLR_RT_HeapBlock_Array::CreateInstance( evalPos[ 0 ], size, assm, arg ); if(SUCCEEDED(hr)) break; + + // if we have an out of memory exception, perform a compaction and try again. + if (hr == CLR_E_OUT_OF_MEMORY && pass == 0) + { + WRITEBACK(stack, evalPos, ip, fDirty); + g_CLR_RT_ExecutionEngine.PerformHeapCompaction(); + READCACHE(stack, evalPos, ip, fDirty); + } + else + { + TINYCLR_SET_AND_LEAVE(hr); + } + } + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDLEN, "ldlen", PopRef, PushI, InlineNone, IObjModel, 1, 0xFF, 0x8E, NEXT) + // Stack: ... -> ... + { + TINYCLR_CHECK_HRESULT(CLR_Checks::VerifyArrayReference( evalPos[ 0 ] )); + + CLR_RT_HeapBlock_Array* array = evalPos[ 0 ].DereferenceArray(); + + evalPos[ 0 ].SetInteger( array->m_numOfElements ); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDELEMA, "ldelema", PopRef+PopI, PushI, InlineType, IObjModel, 1, 0xFF, 0x8F, NEXT) + // Stack: ... ->
... + { + ip += 2; // Skip argument, not used... + + evalPos--; CHECKSTACK(stack,evalPos); + + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].InitializeArrayReference( evalPos[ 0 ], evalPos[ 1 ].NumericByRef().s4 )); + + evalPos[ 0 ].FixArrayReferenceForValueTypes(); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDELEM_I1, "ldelem.i1", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x90, NEXT) + OPDEF(CEE_LDELEM_U1, "ldelem.u1", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x91, NEXT) + OPDEF(CEE_LDELEM_I2, "ldelem.i2", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x92, NEXT) + OPDEF(CEE_LDELEM_U2, "ldelem.u2", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x93, NEXT) + OPDEF(CEE_LDELEM_I4, "ldelem.i4", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x94, NEXT) + OPDEF(CEE_LDELEM_U4, "ldelem.u4", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x95, NEXT) + OPDEF(CEE_LDELEM_I8, "ldelem.i8", PopRef+PopI, PushI8, InlineNone, IObjModel, 1, 0xFF, 0x96, NEXT) + OPDEF(CEE_LDELEM_I, "ldelem.i", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x97, NEXT) + OPDEF(CEE_LDELEM_R4, "ldelem.r4", PopRef+PopI, PushR4, InlineNone, IObjModel, 1, 0xFF, 0x98, NEXT) + OPDEF(CEE_LDELEM_R8, "ldelem.r8", PopRef+PopI, PushR8, InlineNone, IObjModel, 1, 0xFF, 0x99, NEXT) + OPDEF(CEE_LDELEM_REF, "ldelem.ref", PopRef+PopI, PushRef, InlineNone, IObjModel, 1, 0xFF, 0x9A, NEXT) + // Stack: ... -> ... + { + evalPos--; CHECKSTACK(stack,evalPos); + + // + // To load an element from an array, we first initialize a temporary reference to the element and then dereference it. + // + CLR_RT_HeapBlock ref; TINYCLR_CHECK_HRESULT(ref.InitializeArrayReference( evalPos[ 0 ], evalPos[ 1 ].NumericByRef().s4 )); + + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].LoadFromReference( ref )); + + goto Execute_LoadAndPromote; + } + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDELEM, "ldelem", PopRef+PopI, Push1, InlineType, IObjModel, 1, 0xFF, 0xA3, NEXT) + // Stack: ... -> + { + // treat this like ldelema + ldobj + // read the type token argument from the instruction and advance the instruction pointer accordingly + // LDELEMA doesn't need the type token, but the ldobj portion does + FETCH_ARG_COMPRESSED_TYPETOKEN(arg,ip); + + // + // move stack pointer back so that evalpos[0] is the array + evalPos--; + CHECKSTACK(stack,evalPos); + + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].InitializeArrayReference( evalPos[ 0 ], evalPos[ 1 ].NumericByRef().s4 )); + + evalPos[ 0 ].FixArrayReferenceForValueTypes(); + // + // + CLR_RT_TypeDef_Instance type; + CLR_RT_TypeDef_Index cls; + + if( !type.ResolveToken( arg, assm ) ) + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + TINYCLR_CHECK_HRESULT(CLR_RT_TypeDescriptor::ExtractTypeIndexFromObject( evalPos[ 0 ], cls )); + + // Check this is an object of the requested type. + if( type.m_data != cls.m_data ) + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + UPDATESTACK(stack,evalPos); + { + // Save the pointer to the object to load/copy and protect it from GC. + CLR_RT_HeapBlock safeSource; + safeSource.Assign( evalPos[ 0 ] ); + CLR_RT_ProtectFromGC gc( safeSource ); + + TINYCLR_CHECK_HRESULT(evalPos[ 0 ].LoadFromReference( safeSource )); + } + + goto Execute_LoadAndPromote; + // + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_STELEM_I, "stelem.i", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9B, NEXT) + OPDEF(CEE_STELEM_I1, "stelem.i1", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9C, NEXT) + OPDEF(CEE_STELEM_I2, "stelem.i2", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9D, NEXT) + OPDEF(CEE_STELEM_I4, "stelem.i4", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9E, NEXT) + OPDEF(CEE_STELEM_I8, "stelem.i8", PopRef+PopI+PopI8, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9F, NEXT) + OPDEF(CEE_STELEM_R4, "stelem.r4", PopRef+PopI+PopR4, Push0, InlineNone, IObjModel, 1, 0xFF, 0xA0, NEXT) + OPDEF(CEE_STELEM_R8, "stelem.r8", PopRef+PopI+PopR8, Push0, InlineNone, IObjModel, 1, 0xFF, 0xA1, NEXT) + OPDEF(CEE_STELEM_REF, "stelem.ref", PopRef+PopI+PopRef, Push0, InlineNone, IObjModel, 1, 0xFF, 0xA2, NEXT) + // Stack: ... ... -> ... + { + evalPos -= 3; CHECKSTACK(stack,evalPos); + + // + // To load an element from an array, we first initialize a temporary reference to the element and then dereference it. + // + CLR_RT_HeapBlock ref; TINYCLR_CHECK_HRESULT(ref.InitializeArrayReference( evalPos[ 1 ], evalPos[ 2 ].NumericByRef().s4 )); + int size = 0; + + switch(op) + { + case CEE_STELEM_I : size = 4; break; + case CEE_STELEM_I1 : size = 1; break; + case CEE_STELEM_I2 : size = 2; break; + case CEE_STELEM_I4 : size = 4; break; + case CEE_STELEM_I8 : size = 8; break; + case CEE_STELEM_R4 : size = 4; break; + case CEE_STELEM_R8 : size = 8; break; + case CEE_STELEM_REF: size = 0; break; + } + + evalPos[ 3 ].Promote(); + + TINYCLR_CHECK_HRESULT(evalPos[ 3 ].StoreToReference( ref, size )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_STELEM, "stelem", PopRef+PopI+Pop1, Push0, InlineType, IObjModel, 1, 0xFF, 0xA4, NEXT) + // Stack: ... ... -> ... + { + // Treat STELEM like ldelema + stobj + ip += 2; // Skip type argument, not used... + + evalPos -= 3; // "pop" args from evaluation stack + CHECKSTACK(stack,evalPos); + + TINYCLR_CHECK_HRESULT(evalPos[ 1 ].InitializeArrayReference( evalPos[ 1 ], evalPos[ 2 ].NumericByRef().s4 )); + evalPos[ 1 ].FixArrayReferenceForValueTypes(); + + // Reassign will make sure these are objects of the same type. + TINYCLR_CHECK_HRESULT(evalPos[ 1 ].Reassign( evalPos[ 3 ] )); + + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDTOKEN, "ldtoken", Pop0, PushI, InlineTok, IPrimitive, 1, 0xFF, 0xD0, NEXT) + { + FETCH_ARG_UINT32(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetObjectReference( NULL ); + + switch(CLR_TypeFromTk( arg )) + { + case TBL_TypeSpec: + { + CLR_RT_TypeSpec_Instance sig; if(sig.ResolveToken( arg, assm ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + evalPos[ 0 ].SetReflection( sig ); + } + break; + + case TBL_TypeRef: + case TBL_TypeDef: + { + CLR_RT_TypeDef_Instance cls; if(cls.ResolveToken( arg, assm ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + evalPos[ 0 ].SetReflection( cls ); + } + break; + + case TBL_FieldRef: + case TBL_FieldDef: + { + CLR_RT_FieldDef_Instance field; if(field.ResolveToken( arg, assm ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + evalPos[ 0 ].SetReflection( field ); + } + break; + + case TBL_MethodRef: + case TBL_MethodDef: + { + CLR_RT_MethodDef_Instance method; if(method.ResolveToken( arg, assm ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + evalPos[ 0 ].SetReflection( method ); + } + break; + + default: + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + break; + } + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_ENDFINALLY, "endfinally", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xDC, RETURN) + { + EMPTYSTACK(stack, evalPos); + WRITEBACK(stack,evalPos,ip,fDirty); + + TINYCLR_CHECK_HRESULT(th->ProcessException_EndFinally()); + + _ASSERTE(th->m_currentException.Dereference() == NULL); + stack = th->CurrentFrame(); + goto Execute_Reload; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LEAVE, "leave", Pop0, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0xDD, BRANCH) + OPDEF(CEE_LEAVE_S, "leave.s", Pop0, Push0, ShortInlineBrTarget,IPrimitive, 1, 0xFF, 0xDE, BRANCH) + { + CLR_INT32 arg; + + EMPTYSTACK(stack, evalPos); + + if(op == CEE_LEAVE) + { + TINYCLR_READ_UNALIGNED_INT16( arg, ip ); + } + else + { + TINYCLR_READ_UNALIGNED_INT8( arg, ip ); + } + + { + CLR_PMETADATA ipLeave = ip + arg; + CLR_RT_ExceptionHandler eh; + + th->PopEH( stack, ipLeave ); + + if(th->FindEhBlock( stack, ip-1, ipLeave, eh, true )) + { + UnwindStack* us = th->PushEH(); + _ASSERTE(us); + + us->m_stack = stack; + us->m_exception = NULL; + us->m_ip = ipLeave; + us->m_currentBlockStart = eh.m_handlerStart; + us->m_currentBlockEnd = eh.m_handlerEnd; + us->m_flags = UnwindStack::p_4_NormalCleanup; + + ip = eh.m_handlerStart; + break; + } + + ip = ipLeave; + + if(th->m_flags & CLR_RT_Thread::TH_F_Aborted) + { + _ASSERTE(th->m_currentException.Dereference() == NULL); + + (void)Library_corlib_native_System_Exception::CreateInstance( th->m_currentException, g_CLR_RT_WellKnownTypes.m_ThreadAbortException, S_OK, stack ); + + TINYCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + } + } + + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CEQ, "ceq", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x01, NEXT) + { + evalPos--; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetInteger( CLR_RT_HeapBlock::Compare_Signed_Values( evalPos[ 0 ], evalPos[ 1 ] ) == 0 ? 1 : 0 ); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CGT, "cgt", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x02, NEXT) + { + evalPos--; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetInteger( CLR_RT_HeapBlock::Compare_Signed_Values( evalPos[ 0 ], evalPos[ 1 ] ) > 0 ? 1 : 0 ); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CGT_UN, "cgt.un", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x03, NEXT) + { + evalPos--; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetInteger( CLR_RT_HeapBlock::Compare_Unsigned_Values( evalPos[ 0 ], evalPos[ 1 ] ) > 0 ? 1 : 0 ); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CLT, "clt", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x04, NEXT) + { + evalPos--; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetInteger( CLR_RT_HeapBlock::Compare_Signed_Values( evalPos[ 0 ], evalPos[ 1 ] ) < 0 ? 1 : 0 ); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CLT_UN, "clt.un", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x05, NEXT) + { + evalPos--; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetInteger( CLR_RT_HeapBlock::Compare_Unsigned_Values( evalPos[ 0 ], evalPos[ 1 ] ) < 0 ? 1 : 0 ); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDFTN, "ldftn", Pop0, PushI, InlineMethod, IPrimitive, 2, 0xFE, 0x06, NEXT) + { + FETCH_ARG_COMPRESSED_METHODTOKEN(arg,ip); + + evalPos++; CHECKSTACK(stack,evalPos); + + CLR_RT_MethodDef_Instance method; if(method.ResolveToken( arg, assm ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + UPDATESTACK(stack,evalPos); + + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Delegate::CreateInstance( evalPos[ 0 ], method, stack )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_LDVIRTFTN, "ldvirtftn", PopRef, PushI, InlineMethod, IPrimitive, 2, 0xFE, 0x07, NEXT) + { + FETCH_ARG_COMPRESSED_METHODTOKEN(arg,ip); + + CLR_RT_MethodDef_Instance callee; if(callee.ResolveToken( arg, assm ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + CLR_RT_TypeDef_Index cls; + + TINYCLR_CHECK_HRESULT(CLR_RT_TypeDescriptor::ExtractTypeIndexFromObject( evalPos[ 0 ], cls )); + + CLR_RT_MethodDef_Index calleeReal; + + if(g_CLR_RT_EventCache.FindVirtualMethod( cls, callee, calleeReal ) == false) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + UPDATESTACK(stack,evalPos); + + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Delegate::CreateInstance( evalPos[ 0 ], calleeReal, stack )); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_INITOBJ, "initobj", PopI, Push0, InlineType, IObjModel, 2, 0xFE, 0x15, NEXT) + { + ip += 2; // Skip argument, not used... + + evalPos->InitObject(); evalPos--; CHECKSTACK(stack,evalPos); + + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_RETHROW, "rethrow", Pop0, Push0, InlineNone, IObjModel, 2, 0xFE, 0x1A, THROW) + { + if(th->m_nestedExceptionsPos == 0) + { + TINYCLR_SET_AND_LEAVE(CLR_E_STACK_UNDERFLOW); + } + else + { + UnwindStack& us = th->m_nestedExceptions[ --th->m_nestedExceptionsPos ]; + + if(us.m_exception) + { + th->m_currentException.SetObjectReference( us.m_exception ); + + TINYCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + } + else + { + TINYCLR_SET_AND_LEAVE(CLR_E_STACK_UNDERFLOW); + } + } + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_SIZEOF, "sizeof", Pop0, PushI, InlineType, IPrimitive, 2, 0xFE, 0x1C, NEXT) + { + FETCH_ARG_COMPRESSED_TYPETOKEN(arg,ip); + + CLR_RT_TypeDef_Instance clsInst; if(clsInst.ResolveToken( arg, assm ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + CLR_INT32 len; + + if(clsInst.m_target->dataType) + { + len = sizeof(CLR_RT_HeapBlock); + } + else + { + len = (CLR_RT_HeapBlock::HB_Object_Fields_Offset + clsInst.CrossReference().m_totalFields) * sizeof(CLR_RT_HeapBlock); + } + + evalPos++; CHECKSTACK(stack,evalPos); + + evalPos[ 0 ].SetInteger( len ); + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_CONSTRAINED, "constrained.", Pop0, Push0, InlineType, IPrefix, 2, 0xFE, 0x16, META) + { + FETCH_ARG_COMPRESSED_TYPETOKEN(arg,ip); + + //nop + break; + } + + //----------------------------------------------------------------------------------------------------------// + + OPDEF(CEE_ENDFILTER, "endfilter", PopI, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x11, RETURN) + { + + CHECKSTACK(stack,evalPos); + WRITEBACK(stack,evalPos,ip,fDirty); + + TINYCLR_CHECK_HRESULT(th->ProcessException_EndFilter()); + + stack = th->CurrentFrame(); + goto Execute_Reload; + } + + //----------------------------------------------------------------------------------------------------------// + + ////////////////////////////////////////////////////////////////////////////////////////// + // + // These opcodes do nothing... + // + OPDEF(CEE_NOP, "nop", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x00, NEXT) + OPDEF(CEE_UNALIGNED, "unaligned.", Pop0, Push0, ShortInlineI, IPrefix, 2, 0xFE, 0x12, META) + OPDEF(CEE_VOLATILE, "volatile.", Pop0, Push0, InlineNone, IPrefix, 2, 0xFE, 0x13, META) + OPDEF(CEE_TAILCALL, "tail.", Pop0, Push0, InlineNone, IPrefix, 2, 0xFE, 0x14, META) + break; + + ////////////////////////////////////////////////////////////////////////////////////////// + // + // Unsupported opcodes... + // + OPDEF(CEE_ARGLIST, "arglist", Pop0, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x00, NEXT) + OPDEF(CEE_CPBLK, "cpblk", PopI+PopI+PopI, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x17, NEXT) + OPDEF(CEE_JMP, "jmp", Pop0, Push0, InlineMethod, IPrimitive, 1, 0xFF, 0x27, CALL) + OPDEF(CEE_INITBLK, "initblk", PopI+PopI+PopI, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x18, NEXT) + OPDEF(CEE_CALLI, "calli", VarPop, VarPush, InlineSig, IPrimitive, 1, 0xFF, 0x29, CALL) + OPDEF(CEE_CKFINITE, "ckfinite", Pop1, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0xC3, NEXT) + OPDEF(CEE_LOCALLOC, "localloc", PopI, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x0F, NEXT) + OPDEF(CEE_MKREFANY, "mkrefany", PopI, Push1, InlineType, IPrimitive, 1, 0xFF, 0xC6, NEXT) + OPDEF(CEE_REFANYTYPE, "refanytype", Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x1D, NEXT) + OPDEF(CEE_REFANYVAL, "refanyval", Pop1, PushI, InlineType, IPrimitive, 1, 0xFF, 0xC2, NEXT) + OPDEF(CEE_READONLY, "readonly.", Pop0, Push0, InlineNone, IPrefix, 2, 0xFE, 0x1E, META) + + TINYCLR_CHECK_HRESULT(CLR_Checks::VerifyUnsupportedInstruction( op )); + break; + + ////////////////////////////////////////////////////////////////////////////////////////// + + default: + TINYCLR_CHECK_HRESULT(CLR_Checks::VerifyUnknownInstruction( op )); + break; +#undef OPDEF + } + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + if(stack->m_flags & CLR_RT_StackFrame::c_HasBreakpoint) + { + g_CLR_RT_ExecutionEngine.Breakpoint_StackFrame_Step( stack, ip ); + } +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + continue; + + //--// + + Execute_LoadAndPromote: + + { + CLR_RT_HeapBlock& res = evalPos[ 0 ]; + + switch(res.DataType()) + { + case DATATYPE_VOID : break; + + case DATATYPE_BOOLEAN : res.ChangeDataType( DATATYPE_I4 ); res.NumericByRef().u4 = (CLR_UINT32)res.NumericByRef().u1; break; + case DATATYPE_I1 : res.ChangeDataType( DATATYPE_I4 ); res.NumericByRef().s4 = (CLR_INT32 )res.NumericByRef().s1; break; + case DATATYPE_U1 : res.ChangeDataType( DATATYPE_I4 ); res.NumericByRef().u4 = (CLR_UINT32)res.NumericByRef().u1; break; + + case DATATYPE_CHAR : res.ChangeDataType( DATATYPE_I4 ); res.NumericByRef().u4 = (CLR_UINT32)res.NumericByRef().u2; break; + case DATATYPE_I2 : res.ChangeDataType( DATATYPE_I4 ); res.NumericByRef().s4 = (CLR_INT32 )res.NumericByRef().s2; break; + case DATATYPE_U2 : res.ChangeDataType( DATATYPE_I4 ); res.NumericByRef().u4 = (CLR_UINT32)res.NumericByRef().u2; break; + + case DATATYPE_I4 : break; + case DATATYPE_U4 : break; + case DATATYPE_R4 : break; + + case DATATYPE_I8 : break; + case DATATYPE_U8 : break; + case DATATYPE_R8 : break; + case DATATYPE_DATETIME: break; + case DATATYPE_TIMESPAN: break; + case DATATYPE_STRING : break; + + case DATATYPE_OBJECT : + if(evalPos[ 0 ].IsAValueType()) + { + UPDATESTACK(stack,evalPos); + + TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.CloneObject( evalPos[ 0 ], evalPos[ 0 ] )); + } + break; + } + } + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + if(stack->m_flags & CLR_RT_StackFrame::c_HasBreakpoint) + { + g_CLR_RT_ExecutionEngine.Breakpoint_StackFrame_Step( stack, ip ); + } +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + continue; + + //--// + + Execute_BR: + { + CLR_INT32 offset; + + if(c_CLR_RT_OpcodeLookup[ op ].m_opParam == CLR_OpcodeParam_ShortBrTarget) + { + TINYCLR_READ_UNALIGNED_INT8( offset, ip ); + } + else + { + TINYCLR_READ_UNALIGNED_INT16( offset, ip ); + } + + if(fCondition) ip += offset; + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + if(stack->m_flags & CLR_RT_StackFrame::c_HasBreakpoint) + { + g_CLR_RT_ExecutionEngine.Breakpoint_StackFrame_Step( stack, ip ); + } +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + if(th->m_timeQuantumExpired) + { + TINYCLR_SET_AND_LEAVE( CLR_S_QUANTUM_EXPIRED ); + } + + continue; + } + + //--// + + Execute_Restart: + { + CLR_RT_StackFrame* stackNext = th->CurrentFrame(); + + #if defined(ENABLE_NATIVE_PROFILER) + if(stackNext->m_flags & CLR_RT_StackFrame::c_NativeProfiled) + { + stackNext->m_owningThread->m_fNativeProfiled = true; + Native_Profiler_Start(); + } + else if(stackNext->m_fNativeProfiled == false) + { + stackNext->m_owningThread->m_fNativeProfiled = false; + Native_Profiler_Stop(); + } + #endif + + if((stackNext->m_flags & CLR_RT_StackFrame::c_CallerIsCompatibleForCall) == 0) + { + TINYCLR_SET_AND_LEAVE( CLR_S_RESTART_EXECUTION ); + } + + // + // Same kind of handler, no need to pop back out, just restart execution in place. + // + stack->m_flags &= ~CLR_RT_StackFrame::c_ExecutingIL; + + stack = stackNext; + goto Execute_Reload; + } + + Execute_Reload: + { + stack->m_flags |= CLR_RT_StackFrame::c_ExecutingIL; + + assm = stack->m_call.m_assm; + + READCACHE(stack,evalPos,ip,fDirty); + continue; + } + } + } + + + TINYCLR_CLEANUP(); + + if(fDirty) + { + WRITEBACK(stack,evalPos,ip,fDirty); + } + + TINYCLR_CLEANUP_END(); +} + diff --git a/src/CLR/Core/InterruptHandler/InterruptHandler.cpp b/src/CLR/Core/InterruptHandler/InterruptHandler.cpp new file mode 100644 index 0000000000..64b7a7c6f1 --- /dev/null +++ b/src/CLR/Core/InterruptHandler/InterruptHandler.cpp @@ -0,0 +1,138 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// + + //this method is called by Hardware_Initialize + //If you want to initialize your own interrupt handling related objects, put them here + +HRESULT CLR_HW_Hardware::ManagedHardware_Initialize() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + TINYCLR_HEADER(); + + m_interruptData.m_HalQueue.Initialize( (CLR_HW_Hardware::HalInterruptRecord*)&g_scratchInterruptDispatchingStorage, InterruptRecords() ); + + m_interruptData.m_applicationQueue.DblLinkedList_Initialize (); + + m_interruptData.m_queuedInterrupts = 0; + + TINYCLR_NOCLEANUP_NOLABEL(); + +} + +HRESULT CLR_HW_Hardware::SpawnDispatcher() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + TINYCLR_HEADER(); + + // UNDONE: FIXME: CLR_RT_ApplicationInterrupt* interrupt; + //CLR_RT_HeapBlock_NativeEventDispatcher* ioPort; + //CLR_RT_HeapBlock_NativeEventDispatcher ::InterruptPortInterrupt *interruptData; + + //// if reboot is in progress, just bail out + //if(CLR_EE_DBG_IS( RebootPending )) + //{ + // return S_OK; + //} + + //interrupt = (CLR_RT_ApplicationInterrupt*)m_interruptData.m_applicationQueue.FirstValidNode(); + + //if((interrupt == NULL) || !g_CLR_RT_ExecutionEngine.EnsureSystemThread( g_CLR_RT_ExecutionEngine.m_interruptThread, ThreadPriority::System_Highest )) + //{ + // return S_OK; + //} + + //interrupt->Unlink(); + + //interruptData = &interrupt->m_interruptPortInterrupt; + //ioPort = interruptData->m_context; + + //CLR_RT_ProtectFromGC gc1 ( *ioPort ); + // + //TINYCLR_SET_AND_LEAVE(ioPort->StartDispatch( interrupt, g_CLR_RT_ExecutionEngine.m_interruptThread )); + // + //TINYCLR_CLEANUP(); + + //if(FAILED(hr)) + //{ + // ioPort->ThreadTerminationCallback( interrupt ); + //} + + //--m_interruptData.m_queuedInterrupts; + + TINYCLR_CLEANUP_END(); +} + +HRESULT CLR_HW_Hardware::TransferAllInterruptsToApplicationQueue() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + TINYCLR_HEADER(); + + while(true) + { + HalInterruptRecord* rec; + + { + GLOBAL_LOCK(irq1); + + rec = m_interruptData.m_HalQueue.Peek(); + } + + if(rec == NULL) break; + + CLR_RT_ApplicationInterrupt* queueRec = (CLR_RT_ApplicationInterrupt*)CLR_RT_Memory::Allocate_And_Erase( sizeof(CLR_RT_ApplicationInterrupt), CLR_RT_HeapBlock::HB_CompactOnFailure ); CHECK_ALLOCATION(queueRec); + + queueRec->m_interruptPortInterrupt.m_data1 = rec->m_data1; + queueRec->m_interruptPortInterrupt.m_data2 = rec->m_data2; + queueRec->m_interruptPortInterrupt.m_data3 = rec->m_data3; + queueRec->m_interruptPortInterrupt.m_time = rec->m_time; + queueRec->m_interruptPortInterrupt.m_context = (CLR_RT_HeapBlock_NativeEventDispatcher*)rec->m_context; + + m_interruptData.m_applicationQueue.LinkAtBack( queueRec ); ++m_interruptData.m_queuedInterrupts; + + { + GLOBAL_LOCK(irq2); + + m_interruptData.m_HalQueue.Pop(); + } + } + + if(m_interruptData.m_queuedInterrupts == 0) + { + TINYCLR_SET_AND_LEAVE(CLR_E_NO_INTERRUPT); + } + + TINYCLR_CLEANUP(); + + if(CLR_E_OUT_OF_MEMORY == hr) + { + // if there is no memory left discard all interrupts to avoid getting into a death spiral of OOM exceptions + { + GLOBAL_LOCK(irq3); + + while(!m_interruptData.m_HalQueue.IsEmpty()) + { + m_interruptData.m_HalQueue.Pop(); + } + } + } + + TINYCLR_CLEANUP_END(); +} + +HRESULT CLR_HW_Hardware::ProcessInterrupts() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + TINYCLR_HEADER(); + + TINYCLR_CHECK_HRESULT(TransferAllInterruptsToApplicationQueue()); + + SpawnDispatcher(); + + TINYCLR_NOCLEANUP(); +} diff --git a/src/CLR/Core/InterruptHandler/InterruptHandler.vcxproj b/src/CLR/Core/InterruptHandler/InterruptHandler.vcxproj new file mode 100644 index 0000000000..7578ae692a --- /dev/null +++ b/src/CLR/Core/InterruptHandler/InterruptHandler.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + {D32EE397-7E49-452D-AC95-AFCB3C962E3D} + Win32Proj + InterruptHandler + 10.0.14393.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/src/CLR/Core/InterruptHandler/InterruptHandler.vcxproj.filters b/src/CLR/Core/InterruptHandler/InterruptHandler.vcxproj.filters new file mode 100644 index 0000000000..5678012159 --- /dev/null +++ b/src/CLR/Core/InterruptHandler/InterruptHandler.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/src/CLR/Core/InterruptHandler/InterruptHandler_stub.cpp b/src/CLR/Core/InterruptHandler/InterruptHandler_stub.cpp new file mode 100644 index 0000000000..4eba9b5b59 --- /dev/null +++ b/src/CLR/Core/InterruptHandler/InterruptHandler_stub.cpp @@ -0,0 +1,33 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_HW_Hardware::ManagedHardware_Initialize() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + TINYCLR_SYSTEM_STUB_RETURN(); +} + +HRESULT CLR_HW_Hardware::SpawnDispatcher() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + TINYCLR_SYSTEM_STUB_RETURN(); + +} + +HRESULT CLR_HW_Hardware::TransferAllInterruptsToApplicationQueue() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + TINYCLR_SYSTEM_STUB_RETURN(); +} + +HRESULT CLR_HW_Hardware::ProcessInterrupts() +{ + NATIVE_PROFILE_CLR_HARDWARE(); + TINYCLR_SYSTEM_STUB_RETURN(); +} diff --git a/src/CLR/Core/InterruptHandler/InterruptHandler_stub.vcxproj b/src/CLR/Core/InterruptHandler/InterruptHandler_stub.vcxproj new file mode 100644 index 0000000000..c8f0a3958d --- /dev/null +++ b/src/CLR/Core/InterruptHandler/InterruptHandler_stub.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + {5772D362-7277-49CF-9B49-42335A3154BD} + Win32Proj + InterruptHandler_stub + 10.0.14393.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/src/CLR/Core/InterruptHandler/InterruptHandler_stub.vcxproj.filters b/src/CLR/Core/InterruptHandler/InterruptHandler_stub.vcxproj.filters new file mode 100644 index 0000000000..9dc77bab66 --- /dev/null +++ b/src/CLR/Core/InterruptHandler/InterruptHandler_stub.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/src/CLR/Core/RPC/CLR_RT_HeapBlock_EndPoint.cpp b/src/CLR/Core/RPC/CLR_RT_HeapBlock_EndPoint.cpp new file mode 100644 index 0000000000..136d29d518 --- /dev/null +++ b/src/CLR/Core/RPC/CLR_RT_HeapBlock_EndPoint.cpp @@ -0,0 +1,129 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// + + +CLR_RT_DblLinkedList CLR_RT_HeapBlock_EndPoint::m_endPoints; + +void CLR_RT_HeapBlock_EndPoint::HandlerMethod_Initialize() +{ + CLR_RT_HeapBlock_EndPoint::m_endPoints.DblLinkedList_Initialize(); +} + +void CLR_RT_HeapBlock_EndPoint::HandlerMethod_RecoverFromGC() +{ + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_EndPoint,endPoint,CLR_RT_HeapBlock_EndPoint::m_endPoints) + { + endPoint->RecoverFromGC(); + } + TINYCLR_FOREACH_NODE_END(); +} + +void CLR_RT_HeapBlock_EndPoint::HandlerMethod_CleanUp() +{ +} + +CLR_RT_HeapBlock_EndPoint* CLR_RT_HeapBlock_EndPoint::FindEndPoint( const CLR_RT_HeapBlock_EndPoint::Port& port ) +{ + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_EndPoint,endPoint,CLR_RT_HeapBlock_EndPoint::m_endPoints) + { + if((endPoint->m_addr.m_type == port.m_type) && (endPoint->m_addr.m_id == port.m_id)) return endPoint; //eliminate the need for another func. call; member variables are public + } + TINYCLR_FOREACH_NODE_END(); + + return NULL; +} + +bool CLR_RT_HeapBlock_EndPoint::Port::Compare( const CLR_RT_HeapBlock_EndPoint::Port& port ) +{ + return m_type == port.m_type && m_id == port.m_id; +} + +//--// + +HRESULT CLR_RT_HeapBlock_EndPoint::CreateInstance( const CLR_RT_HeapBlock_EndPoint::Port& port, CLR_RT_HeapBlock& owner, CLR_RT_HeapBlock& epRef ) +{ + TINYCLR_HEADER(); + + CLR_RT_HeapBlock_EndPoint* endPoint = NULL; + + // + // Create a request and stop the calling thread. + // + endPoint = EVENTCACHE_EXTRACT_NODE(g_CLR_RT_EventCache,CLR_RT_HeapBlock_EndPoint,DATATYPE_ENDPOINT_HEAD); CHECK_ALLOCATION(endPoint); + + { + CLR_RT_ProtectFromGC gc( *endPoint ); + + endPoint->Initialize(); + + endPoint->m_seq = 0; + endPoint->m_addr = port; + + endPoint->m_messages.DblLinkedList_Initialize(); + + CLR_RT_HeapBlock_EndPoint::m_endPoints.LinkAtBack( endPoint ); + + TINYCLR_SET_AND_LEAVE(CLR_RT_ObjectToEvent_Source::CreateInstance( endPoint, owner, epRef )); + } + + TINYCLR_CLEANUP(); + + if(FAILED(hr)) + { + if(endPoint) endPoint->ReleaseWhenDeadEx(); + } + + TINYCLR_CLEANUP_END(); +} + +HRESULT CLR_RT_HeapBlock_EndPoint::ExtractInstance( CLR_RT_HeapBlock& ref, CLR_RT_HeapBlock_EndPoint*& endPoint ) +{ + TINYCLR_HEADER(); + + CLR_RT_ObjectToEvent_Source* src = CLR_RT_ObjectToEvent_Source::ExtractInstance( ref ); FAULT_ON_NULL(src); + + endPoint = (CLR_RT_HeapBlock_EndPoint*)src->m_eventPtr; + + TINYCLR_NOCLEANUP(); +} + +bool CLR_RT_HeapBlock_EndPoint::ReleaseWhenDeadEx() +{ + if(!IsReadyForRelease()) return false; + + m_messages.DblLinkedList_Release(); + + return ReleaseWhenDead(); +} + +//--// + +void CLR_RT_HeapBlock_EndPoint::RecoverFromGC() +{ + CheckAll(); + + ReleaseWhenDeadEx(); +} + +//--// + +CLR_RT_HeapBlock_EndPoint::Message* CLR_RT_HeapBlock_EndPoint::FindMessage( CLR_UINT32 cmd, const CLR_UINT32* seq ) +{ + TINYCLR_FOREACH_NODE(Message,msg,m_messages) + { + if(msg->m_cmd == cmd) + { + if(!seq ) return msg; + if(msg->m_addr.m_seq == *seq) return msg; + } + } + TINYCLR_FOREACH_NODE_END(); + + return NULL; +} diff --git a/src/CLR/Core/RPC/RPC.vcxproj b/src/CLR/Core/RPC/RPC.vcxproj new file mode 100644 index 0000000000..ed56165f12 --- /dev/null +++ b/src/CLR/Core/RPC/RPC.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + {ED4C887A-EC09-465B-B5D9-075450ADC52D} + Win32Proj + RPC + 10.0.14393.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/src/CLR/Core/RPC/RPC.vcxproj.filters b/src/CLR/Core/RPC/RPC.vcxproj.filters new file mode 100644 index 0000000000..b7ad38368a --- /dev/null +++ b/src/CLR/Core/RPC/RPC.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/src/CLR/Core/RPC/RPC_stub.cpp b/src/CLR/Core/RPC/RPC_stub.cpp new file mode 100644 index 0000000000..9aacfa8266 --- /dev/null +++ b/src/CLR/Core/RPC/RPC_stub.cpp @@ -0,0 +1,61 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// + + +void CLR_RT_HeapBlock_EndPoint::HandlerMethod_Initialize() +{ +} + +void CLR_RT_HeapBlock_EndPoint::HandlerMethod_RecoverFromGC() +{ +} + +void CLR_RT_HeapBlock_EndPoint::HandlerMethod_CleanUp() +{ +} + +CLR_RT_HeapBlock_EndPoint* CLR_RT_HeapBlock_EndPoint::FindEndPoint( const CLR_RT_HeapBlock_EndPoint::Port& port ) +{ + return NULL; +} + +bool CLR_RT_HeapBlock_EndPoint::Port::Compare( const CLR_RT_HeapBlock_EndPoint::Port& port ) +{ + return false; +} + +//--// + +HRESULT CLR_RT_HeapBlock_EndPoint::CreateInstance( const CLR_RT_HeapBlock_EndPoint::Port& port, CLR_RT_HeapBlock& owner, CLR_RT_HeapBlock& epRef ) +{ + TINYCLR_FEATURE_STUB_RETURN(); +} + +HRESULT CLR_RT_HeapBlock_EndPoint::ExtractInstance( CLR_RT_HeapBlock& ref, CLR_RT_HeapBlock_EndPoint*& endPoint ) +{ + TINYCLR_FEATURE_STUB_RETURN(); +} + +bool CLR_RT_HeapBlock_EndPoint::ReleaseWhenDeadEx() +{ + return true; +} + +//--// + +void CLR_RT_HeapBlock_EndPoint::RecoverFromGC() +{ +} + +//--// + +CLR_RT_HeapBlock_EndPoint::Message* CLR_RT_HeapBlock_EndPoint::FindMessage( CLR_UINT32 cmd, const CLR_UINT32* seq ) +{ + return NULL; +} diff --git a/src/CLR/Core/RPC/RPC_stub.vcxproj b/src/CLR/Core/RPC/RPC_stub.vcxproj new file mode 100644 index 0000000000..3f18a3fa77 --- /dev/null +++ b/src/CLR/Core/RPC/RPC_stub.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + {D0B2ADFE-3347-4D73-9364-9C36935D12F8} + Win32Proj + RPC_stub + 10.0.14393.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/src/CLR/Core/RPC/RPC_stub.vcxproj.filters b/src/CLR/Core/RPC/RPC_stub.vcxproj.filters new file mode 100644 index 0000000000..a1ac8e56b3 --- /dev/null +++ b/src/CLR/Core/RPC/RPC_stub.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/src/CLR/Core/Serialization/BinaryFormatter.cpp b/src/CLR/Core/Serialization/BinaryFormatter.cpp new file mode 100644 index 0000000000..8bf7ea512e --- /dev/null +++ b/src/CLR/Core/Serialization/BinaryFormatter.cpp @@ -0,0 +1,2016 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +//this method simply informs if Serialization is enabled +//the stub version of this method returns False +bool CLR_RT_BinaryFormatter::SerializationEnabled() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + return true; +} + +CLR_RT_HeapBlock* CLR_RT_BinaryFormatter::TypeHandler::FixDereference( CLR_RT_HeapBlock* v ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + return (v && v->DataType() == DATATYPE_OBJECT) ? v->Dereference() : v; +} + +CLR_RT_HeapBlock* CLR_RT_BinaryFormatter::TypeHandler::FixNull( CLR_RT_HeapBlock* v ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + if(v && v->DataType() == DATATYPE_OBJECT && v->Dereference() == NULL) return NULL; + + return v; +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::TypeHandler::TypeHandler_Initialize( CLR_RT_BinaryFormatter* bf, SerializationHintsAttribute* hints, CLR_RT_TypeDescriptor* expected ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_HEADER(); + + TINYCLR_CLEAR(*this); + + m_bf = bf; + + if(hints) + { + m_hints = *hints; + } + + if(expected) + { + m_typeExpected = &m_typeExpected_tmp; + + *m_typeExpected = *expected; + } + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT CLR_RT_BinaryFormatter::TypeHandler::SetValue( CLR_RT_HeapBlock* v ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_HEADER(); + + m_value = NULL; + m_type = NULL; + + v = TypeHandler::FixNull( v ); + if(v) + { + m_value = &m_value_tmp; + m_type = &m_type_tmp; + + m_value->Assign( *v ); + + TINYCLR_CHECK_HRESULT(m_type->InitializeFromObject( *v )); + +#if defined(TINYCLR_APPDOMAINS) + if(m_bf->m_flags & CLR_RT_BinaryFormatter::c_Flags_Marshal) + { + //MarshalByRefObjects are special for the AppDomain marshaler, and need to get marshaled regardless of whether or not they + //are serializable + + if((m_type->m_handlerCls.CrossReference().m_flags & CLR_RT_TypeDef_CrossReference::TD_CR_IsMarshalByRefObject) || + m_value->IsTransparentProxy()) + { + m_fIsMarshalByRefObject = true; + } + } + +#endif + + if((m_type->m_handlerCls.m_target->flags & CLR_RECORD_TYPEDEF::TD_Serializable) == 0) + { +#if defined(TINYCLR_APPDOMAINS) + + if(m_fIsMarshalByRefObject) TINYCLR_SET_AND_LEAVE(S_OK); + + //For marshaling, we want to throw an exception if we can't correctly marshal an object across AD boundaries + //In fact, this should probably be turned on for all serialization, but I don't know what other implications that + //would have + + if(m_bf->m_flags & CLR_RT_BinaryFormatter::c_Flags_Marshal) + { + TINYCLR_SET_AND_LEAVE(CLR_E_APPDOMAIN_MARSHAL_EXCEPTION); + } +#endif + m_value = NULL; + m_type = NULL; + } + } + + TINYCLR_NOCLEANUP(); +} + +//--// + +int CLR_RT_BinaryFormatter::TypeHandler::SignatureRequirements() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + int res = c_Signature_Header | c_Signature_Type | c_Signature_Length; + CLR_RT_TypeDescriptor* td; + CLR_RT_TypeDescriptor sub; + + if(m_hints.m_arraySize != 0) + { + res &= ~c_Signature_Length; + } + + m_typeForced = NULL; + + if(m_typeExpected != NULL) + { + switch(m_typeExpected->m_flags) + { + case CLR_RT_DataTypeLookup::c_Primitive: + case CLR_RT_DataTypeLookup::c_Enum : + case CLR_RT_DataTypeLookup::c_ValueType: + res = 0; + break; + + default: + if(m_hints.m_flags & SF_FixedType) + { + res &= ~c_Signature_Type; + break; + } + + if(m_typeExpected->m_flags & CLR_RT_DataTypeLookup::c_Array) + { + sub.InitializeFromType( m_typeExpected->m_reflex.m_data.m_type ); + + td = ⊂ + } + else + { + td = m_typeExpected; + } + + if(td->m_handlerCls.m_target->flags & CLR_RECORD_TYPEDEF::TD_Sealed) + { + res &= ~c_Signature_Type; + break; + } + } + } + + if((res & c_Signature_Type) == 0) + { + m_typeForced = &m_typeForced_tmp; + *m_typeForced = *m_typeExpected; + + if(m_hints.m_flags & SF_PointerNeverNull) + { + res &= ~c_Signature_Header; + } + } + + return res; +} + +bool CLR_RT_BinaryFormatter::TypeHandler::CompareTypes( CLR_RT_TypeDescriptor* left, CLR_RT_TypeDescriptor* right ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + if(!left && !right) return true; + if(!left || !right) return false; + + return memcmp( left, right, sizeof(*left) ) == 0; +} + +CLR_DataType CLR_RT_BinaryFormatter::TypeHandler::GetDataType( CLR_RT_TypeDescriptor* type ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + return (CLR_DataType)type->m_handlerCls.m_target->dataType; +} + +CLR_UINT32 CLR_RT_BinaryFormatter::TypeHandler::GetSizeOfType( CLR_RT_TypeDescriptor* type ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + return c_CLR_RT_DataTypeLookup[ type->GetDataType() ].m_sizeInBits; +} + +bool CLR_RT_BinaryFormatter::TypeHandler::GetSignOfType( CLR_RT_TypeDescriptor* type ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + return (c_CLR_RT_DataTypeLookup[ type->GetDataType() ].m_flags & CLR_RT_DataTypeLookup::c_Signed) != 0; +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::TypeHandler::EmitSignature( int& res ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_HEADER(); + + CLR_UINT32 idx; + int mask = SignatureRequirements(); + + if((mask & c_Signature_Type) == 0) + { + if(m_type && CompareTypes( m_type, m_typeForced ) == false) + { + while(true) + { + if(m_typeForced->m_flags == CLR_RT_DataTypeLookup::c_Enum) + { + break; + } + + if(m_typeForced->m_handlerCls.IsATypeHandler() && + m_type ->m_handlerCls.IsATypeHandler() ) + { + break; + } + + TINYCLR_SET_AND_LEAVE(CLR_E_SERIALIZATION_VIOLATION); + } + } + } + + if(m_value == NULL) + { + if(mask == 0) + { + // + // Special case for null strings (strings don't emit an hash): send a string of length -1. + // + if(m_typeExpected->GetDataType() == DATATYPE_STRING) + { + + TINYCLR_CHECK_HRESULT(m_bf->WriteCompressedUnsigned( 0xFFFFFFFF )); + + res = c_Action_None; TINYCLR_SET_AND_LEAVE(S_OK); + } + + TINYCLR_SET_AND_LEAVE(CLR_E_SERIALIZATION_VIOLATION); + } + + + TINYCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L1_Null, TE_L1 )); + + res = c_Action_None; TINYCLR_SET_AND_LEAVE(S_OK); + } + + //--// + +#if defined(TINYCLR_APPDOMAINS) + if(m_fIsMarshalByRefObject) + { + CLR_RT_HeapBlock* valPtr = m_value->Dereference(); + + TINYCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L1_Other, TE_L1 )); + TINYCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L2_Other, TE_L2 )); + TINYCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L3_MBRO , TE_L3 )); + + { + /* + The bit stream contains pointers to the MBRO and its AppDomain. Only the header is used, and no + duplicate detection is necessary -- all proxies pointing at the same object are equal. + which will get marshaled into either a proxy or MBRO, depending on the destination AppDomain. + Live pointers are stored, but this is ok since it is for marshaling only. The objects cannot + can collected during a GC due to the live object that is being marshaled. + */ + + _ASSERTE(CLR_EE_DBG_IS(NoCompaction)); + + CLR_RT_HeapBlock* ptr; + CLR_RT_AppDomain* appDomain; + + if(valPtr->DataType() == DATATYPE_TRANSPARENT_PROXY) + { + ptr = valPtr->TransparentProxyDereference(); + appDomain = valPtr->TransparentProxyAppDomain (); + } + else + { + ptr = valPtr; + appDomain = g_CLR_RT_ExecutionEngine.GetCurrentAppDomain(); + } + + TINYCLR_CHECK_HRESULT(m_bf->WriteBits( (CLR_UINT32)(size_t)ptr, 32)); + TINYCLR_CHECK_HRESULT(m_bf->WriteBits( (CLR_UINT32)(size_t)appDomain, 32)); + } + + res = c_Action_None; TINYCLR_SET_AND_LEAVE(S_OK); + } +#endif + + idx = m_bf->SearchDuplicate( m_value ); + if(idx != (CLR_UINT32)-1) + { + // + // No duplicates allowed for fixed-type objects. + // + if((mask & c_Signature_Header) == 0) + { + TINYCLR_SET_AND_LEAVE(CLR_E_SERIALIZATION_VIOLATION); + } + + TINYCLR_CHECK_HRESULT(m_bf->WriteBits ( TE_L1_Duplicate, TE_L1 )); + TINYCLR_CHECK_HRESULT(m_bf->WriteCompressedUnsigned( idx )); + + res = c_Action_None; TINYCLR_SET_AND_LEAVE(S_OK); + } + + //--// + + TINYCLR_CHECK_HRESULT(EmitSignature_Inner( mask, m_type, m_value )); + + res = c_Action_ObjectData; TINYCLR_SET_AND_LEAVE(S_OK); + + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_BinaryFormatter::TypeHandler::EmitSignature_Inner( int mask, CLR_RT_TypeDescriptor* type, CLR_RT_HeapBlock* value ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_HEADER(); + + // Unbox reflection types + if(value && value->DataType() == DATATYPE_OBJECT) + { + CLR_RT_HeapBlock* pObj = value->Dereference(); + + if(pObj && pObj->DataType() == DATATYPE_REFLECTION) + { + value = pObj; + } + } + + if(value && value->DataType() == DATATYPE_REFLECTION) + { + switch(value->ReflectionDataConst().m_kind) + { + case REFLECTION_TYPE: + case REFLECTION_TYPE_DELAYED: + if((mask & c_Signature_Header) != 0) + { + TINYCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L1_Other, TE_L1 )); + TINYCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L2_Other, TE_L2 )); + TINYCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L3_Type , TE_L3 )); + } + break; + +#if defined(TINYCLR_APPDOMAINS) + case REFLECTION_ASSEMBLY: + case REFLECTION_CONSTRUCTOR: + case REFLECTION_METHOD: + case REFLECTION_FIELD: + if((m_bf->m_flags & CLR_RT_BinaryFormatter::c_Flags_Marshal) == 0) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + if((mask & c_Signature_Header) != 0) + { + TINYCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L1_Other , TE_L1 )); + TINYCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L2_Other , TE_L2 )); + TINYCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L3_Reflection, TE_L3 )); + } + break; +#endif + + default: + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + else if(value && (type->m_flags & (CLR_RT_DataTypeLookup::c_Array | CLR_RT_DataTypeLookup::c_ArrayList))) + { + CLR_RT_HeapBlock_Array* array; + int sizeReal = -1; + + if(type->m_flags & CLR_RT_DataTypeLookup::c_Array) + { + + if((mask & c_Signature_Header) != 0) + { + TINYCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L1_Other, TE_L1 )); + TINYCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L2_Array, TE_L2 )); + } + + if((mask & c_Signature_Type) != 0) + { + TINYCLR_CHECK_HRESULT(m_bf->WriteBits( (CLR_UINT32)type->m_reflex.m_levels, TE_ArrayDepth )); + + CLR_RT_TypeDescriptor typeSub; typeSub.InitializeFromType( type->m_reflex.m_data.m_type ); + + TINYCLR_CHECK_HRESULT(EmitSignature_Inner( c_Signature_Header | c_Signature_Type, &typeSub, NULL )); + } + + + sizeReal = value->DereferenceArray()->m_numOfElements; + } + else + { + int capacity; + + if((mask & c_Signature_Header) != 0) + { + TINYCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L1_Other , TE_L1 )); + TINYCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L2_ArrayList, TE_L2 )); + } + + TINYCLR_CHECK_HRESULT(CLR_RT_ArrayListHelper::ExtractArrayFromArrayList( *value, array, sizeReal, capacity )); + } + + if((mask & c_Signature_Length) != 0) + { + int bitsMax = m_hints.m_bitPacked; + + if(bitsMax != 0) + { + if(sizeReal >= (1 << bitsMax)) + { + TINYCLR_SET_AND_LEAVE(CLR_E_SERIALIZATION_VIOLATION); + } + + TINYCLR_SET_AND_LEAVE(m_bf->WriteBits( (CLR_UINT32)sizeReal, bitsMax )); + } + else + { + TINYCLR_SET_AND_LEAVE(m_bf->WriteCompressedUnsigned( (CLR_UINT32)sizeReal )); + } + } + else + { + int sizeExpected = m_hints.m_arraySize; + + if(sizeExpected > 0 && sizeExpected != sizeReal) + { + TINYCLR_SET_AND_LEAVE(CLR_E_SERIALIZATION_VIOLATION); + } + } + } + else if(type->m_flags == CLR_RT_DataTypeLookup::c_Primitive || + type->m_flags == CLR_RT_DataTypeLookup::c_Enum ) + { + if((mask & c_Signature_Header) != 0) + { + TINYCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L1_Other , TE_L1 )); + TINYCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L2_Primitive, TE_L2 )); + } + + if((mask & c_Signature_Type) != 0) + { + TINYCLR_SET_AND_LEAVE(m_bf->WriteBits( CLR_RT_TypeSystem::MapDataTypeToElementType( type->GetDataType() ), TE_ElementType )); + } + } + else + { + if((mask & c_Signature_Header) != 0) + { + TINYCLR_CHECK_HRESULT(m_bf->WriteBits( TE_L1_Reference, TE_L1 )); + } + + if((mask & c_Signature_Type) != 0) + { + TINYCLR_SET_AND_LEAVE(m_bf->WriteType( type->m_handlerCls.CrossReference().m_hash )); + } + } + + TINYCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::TypeHandler::ReadSignature( int& res ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_HEADER(); + + int mask = SignatureRequirements(); + + m_value = NULL; + m_type = NULL; + + if(m_typeForced) + { + m_type = &m_type_tmp; + + *m_type = *m_typeForced; + } + + if((mask & c_Signature_Header) != 0) + { + CLR_UINT32 levelOne; + CLR_UINT32 levelTwo; + CLR_UINT32 levelThree; + + + TINYCLR_CHECK_HRESULT(m_bf->ReadBits( levelOne, TE_L1 )); + + if(levelOne == TE_L1_Null) + { + if(m_hints.m_flags & SF_PointerNeverNull) + { + TINYCLR_SET_AND_LEAVE(CLR_E_SERIALIZATION_VIOLATION); + } + + res = c_Action_None; TINYCLR_SET_AND_LEAVE(S_OK); + } + + if(levelOne == TE_L1_Duplicate) + { + CLR_RT_HeapBlock* dup; + CLR_UINT32 idx; + + TINYCLR_CHECK_HRESULT(m_bf->ReadCompressedUnsigned( idx )); + + dup = m_bf->GetDuplicate( idx ); + if(dup == NULL) + { + TINYCLR_SET_AND_LEAVE(CLR_E_SERIALIZATION_VIOLATION); + } + + m_value = &m_value_tmp; + m_value->SetObjectReference( dup ); + + m_type = &m_type_tmp; + TINYCLR_CHECK_HRESULT(m_type->InitializeFromObject( *m_value )); + + res = c_Action_None; TINYCLR_SET_AND_LEAVE(S_OK); + } + + if(levelOne == TE_L1_Reference) + { + if((mask & c_Signature_Type) != 0) + { + CLR_RT_ReflectionDef_Index idx; + + TINYCLR_CHECK_HRESULT(m_bf->ReadType( idx )); + + m_type = &m_type_tmp; + TINYCLR_CHECK_HRESULT(m_type->InitializeFromReflection( idx )); + } + } + else + { + TINYCLR_CHECK_HRESULT(m_bf->ReadBits( levelTwo, TE_L2 )); + if(levelTwo == TE_L2_Primitive) + { + if((mask & c_Signature_Type) != 0) + { + CLR_UINT32 et; + + TINYCLR_CHECK_HRESULT(m_bf->ReadBits( et, TE_ElementType )); + + m_type = &m_type_tmp; + TINYCLR_CHECK_HRESULT(m_type->InitializeFromDataType( CLR_RT_TypeSystem::MapElementTypeToDataType( et ) )); + } + } + else if(levelTwo == TE_L2_Array) + { + if((mask & c_Signature_Type) != 0) + { + CLR_UINT32 depth; + + TINYCLR_CHECK_HRESULT(m_bf->ReadBits( depth, TE_ArrayDepth )); + + TINYCLR_CHECK_HRESULT(m_bf->ReadBits( levelOne, TE_L1 )); + + if(levelOne == TE_L1_Reference) + { + CLR_RT_ReflectionDef_Index idx; + + TINYCLR_CHECK_HRESULT(m_bf->ReadType( idx )); + + m_type = &m_type_tmp; + TINYCLR_CHECK_HRESULT(m_type->InitializeFromReflection( idx )); + } + else if(levelOne == TE_L1_Other) + { + TINYCLR_CHECK_HRESULT(m_bf->ReadBits( levelTwo, TE_L2 )); + + if(levelTwo == TE_L2_Primitive) + { + CLR_UINT32 et; + + TINYCLR_CHECK_HRESULT(m_bf->ReadBits( et, TE_ElementType )); + + m_type = &m_type_tmp; + TINYCLR_CHECK_HRESULT(m_type->InitializeFromDataType( CLR_RT_TypeSystem::MapElementTypeToDataType( et ) )); + } + else + { + TINYCLR_SET_AND_LEAVE(CLR_E_SERIALIZATION_BADSTREAM); + } + } + else + { + TINYCLR_SET_AND_LEAVE(CLR_E_SERIALIZATION_BADSTREAM); + } + + m_type->m_reflex.m_levels = depth; + m_type->ConvertToArray(); + } + } + else if(levelTwo == TE_L2_ArrayList) + { + if((mask & c_Signature_Type) != 0) + { + m_type = &m_type_tmp; + TINYCLR_CHECK_HRESULT(m_type->InitializeFromType( g_CLR_RT_WellKnownTypes.m_ArrayList )); + } + } + else if(levelTwo == TE_L2_Other) + { + TINYCLR_CHECK_HRESULT(m_bf->ReadBits( levelThree, TE_L3 )); + if(levelThree == TE_L3_Type) + { + m_type = &m_type_tmp; + TINYCLR_CHECK_HRESULT(m_type->InitializeFromType( g_CLR_RT_WellKnownTypes.m_Type )); + } +#if defined(TINYCLR_APPDOMAINS) + else if (levelThree == TE_L3_Reflection) + { + CLR_RT_ReflectionDef_Index value; + CLR_UINT64 data; + + _ASSERTE(m_bf->m_flags & CLR_RT_BinaryFormatter::c_Flags_Marshal); + + TINYCLR_CHECK_HRESULT(m_bf->ReadBits( data, 64 )); + + value.SetRawData( data ); + + m_value = &m_value_tmp; + TINYCLR_CHECK_HRESULT(m_value->SetReflection( value )); + + res = c_Action_None; TINYCLR_SET_AND_LEAVE(S_OK); + } + else if (levelThree == TE_L3_MBRO) + { + CLR_UINT32 uintPtr; + CLR_UINT32 uintAppDomain; + CLR_RT_HeapBlock* ptr; + CLR_RT_AppDomain* appDomain; + + TINYCLR_CHECK_HRESULT(m_bf->ReadBits( uintPtr , 32 )); + TINYCLR_CHECK_HRESULT(m_bf->ReadBits( uintAppDomain, 32 )); + + _ASSERTE(CLR_EE_DBG_IS( NoCompaction )); + + ptr = (CLR_RT_HeapBlock*)(size_t)uintPtr; + appDomain = (CLR_RT_AppDomain*)(size_t)uintAppDomain; + + m_type = &m_type_tmp; + TINYCLR_CHECK_HRESULT(m_type->InitializeFromObject( *ptr )); + + m_value = &m_value_tmp; + if(appDomain != g_CLR_RT_ExecutionEngine.GetCurrentAppDomain()) + { + //The MarshalByRefObject lives in a separate AppDomain. + //We need to allocate a TRANSPARENT_PROXY object on the stack + + CLR_RT_HeapBlock* proxy = g_CLR_RT_ExecutionEngine.ExtractHeapBlocksForObjects( DATATYPE_TRANSPARENT_PROXY, 0, 1 ); CHECK_ALLOCATION(proxy); + + proxy->SetTransparentProxyReference( appDomain, ptr ); + + ptr = proxy; + } + + //Set the value reference to either the MBRO, or the proxy + m_value->SetObjectReference( ptr ); + + res = c_Action_None; TINYCLR_SET_AND_LEAVE(S_OK); + } +#endif + else + { + TINYCLR_SET_AND_LEAVE(CLR_E_SERIALIZATION_BADSTREAM); + } + } + } + } + + if(m_type->m_flags & (CLR_RT_DataTypeLookup::c_Array | CLR_RT_DataTypeLookup::c_ArrayList)) + { + CLR_UINT32 len; + + if(mask & c_Signature_Length) + { + int bitsMax = m_hints.m_bitPacked; + + if(bitsMax != 0) + { + TINYCLR_CHECK_HRESULT(m_bf->ReadBits( len, bitsMax )); + } + else + { + TINYCLR_CHECK_HRESULT(m_bf->ReadCompressedUnsigned( len )); + } + } + else + { + CLR_RT_TypeDescriptor sub; + + if(m_type->m_reflex.m_levels != 1) + { + // + // Only simple arrays can have variable size. + // + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + sub.InitializeFromType( m_type->m_reflex.m_data.m_type ); + + len = m_hints.m_arraySize; + + if(len == (CLR_UINT32)-1) + { + len = m_bf->BitsAvailable(); + + switch(TypeHandler::GetSizeOfType( &sub )) + { + case 1: break; + case 8: len /= 8; break; + case 16: len /= 16; break; + case 32: len /= 32; break; + case 64: len /= 64; break; + default: + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + } + + if(m_type->m_flags & CLR_RT_DataTypeLookup::c_ArrayList) + { + CLR_RT_HeapBlock_Array* array; + + m_value = &m_value_tmp; + TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewArrayList( *m_value, len, array )); + } + else + { + m_value = &m_value_tmp; + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( *m_value, len, m_type->m_reflex )); + } + } + else + { + m_value = &m_value_tmp; + + if(m_type->m_handlerCls.IsATypeHandler()) + { + CLR_RT_ReflectionDef_Index idx; + + TINYCLR_CHECK_HRESULT(m_bf->ReadType( idx )); + + TINYCLR_CHECK_HRESULT(m_value->SetReflection( idx )); + + res = c_Action_None; TINYCLR_SET_AND_LEAVE(S_OK); + } + + TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObject( *m_value, m_type->m_handlerCls )); + } + + res = c_Action_ObjectData; TINYCLR_SET_AND_LEAVE(S_OK); + + TINYCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::TypeHandler::EmitValue( int& res ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock* value = m_value->FixBoxingReference(); + CLR_UINT64 val; + CLR_UINT32 bits; + bool fSigned; + + // unbox reflection types + if(value->DataType() == DATATYPE_OBJECT) + { + CLR_RT_HeapBlock* obj = value->Dereference(); + + if(obj && obj->DataType() == DATATYPE_REFLECTION) + { + value = obj; + } + } + + if(value->DataType() == DATATYPE_REFLECTION) + { + switch(value->ReflectionDataConst().m_kind) + { + case REFLECTION_TYPE: + case REFLECTION_TYPE_DELAYED: + TINYCLR_CHECK_HRESULT(m_bf->WriteType( value->ReflectionDataConst() )); + break; +#if defined(TINYCLR_APPDOMAINS) + case REFLECTION_ASSEMBLY: + case REFLECTION_CONSTRUCTOR: + case REFLECTION_METHOD: + case REFLECTION_FIELD: + { + CLR_UINT64 data; + + _ASSERTE(m_bf->m_flags & CLR_RT_BinaryFormatter::c_Flags_Marshal); + + data = value->ReflectionDataConst().GetRawData(); + + TINYCLR_CHECK_HRESULT(m_bf->WriteBits( data, 64 )); + } + break; +#endif + } + + res = c_Action_None; TINYCLR_SET_AND_LEAVE(S_OK); + } + + if(m_type->m_handlerCls.m_data == g_CLR_RT_WellKnownTypes.m_DateTime.m_data) + { + CLR_INT64* pVal = Library_corlib_native_System_DateTime::GetValuePtr( *value ); FAULT_ON_NULL(pVal); + + val = *(CLR_UINT64*)pVal; + bits = 64; + fSigned = false; + } + else if(m_type->m_handlerCls.m_data == g_CLR_RT_WellKnownTypes.m_TimeSpan.m_data) + { + CLR_INT64* pVal = Library_corlib_native_System_TimeSpan::GetValuePtr( *value ); FAULT_ON_NULL(pVal); + + val = *(CLR_UINT64*)pVal; + bits = 64; + fSigned = true; + } + else if(m_type->m_flags == CLR_RT_DataTypeLookup::c_Primitive || + m_type->m_flags == CLR_RT_DataTypeLookup::c_Enum ) + { + bits = TypeHandler::GetSizeOfType( m_type ); + if(bits == CLR_RT_DataTypeLookup::c_VariableSize) + { + LPCSTR szText = value->RecoverString(); + CLR_UINT32 len = szText ? (CLR_UINT32)hal_strlen_s( szText ) : 0xFFFFFFFF; + + TINYCLR_CHECK_HRESULT(m_bf->WriteCompressedUnsigned( len )); + + if(len != (CLR_UINT32)-1) + { + TINYCLR_CHECK_HRESULT(m_bf->WriteArray( (CLR_UINT8*)szText, len )); + } + + res = c_Action_None; TINYCLR_SET_AND_LEAVE(S_OK); + } + else if(bits == CLR_RT_DataTypeLookup::c_NA) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + CLR_RT_HeapBlock* v = FixDereference( value ); FAULT_ON_NULL(v); + + val = v->NumericByRefConst().u8; + + fSigned = TypeHandler::GetSignOfType( m_type ); + } + +#if defined(TINYCLR_APPDOMAINS) + else if(m_fIsMarshalByRefObject) + { + CLR_RT_HeapBlock* valPtr = value->Dereference(); + CLR_RT_AppDomain* appDomain = g_CLR_RT_ExecutionEngine.GetCurrentAppDomain(); + + if(valPtr->DataType() == DATATYPE_TRANSPARENT_PROXY) + { + appDomain = valPtr->TransparentProxyAppDomain(); + valPtr = valPtr->TransparentProxyDereference(); + } + + TINYCLR_CHECK_HRESULT(m_bf->WriteBits( (CLR_UINT32)(size_t)valPtr , 32 )); + TINYCLR_CHECK_HRESULT(m_bf->WriteBits( (CLR_UINT32)(size_t)appDomain, 32 )); + + TINYCLR_SET_AND_LEAVE(S_OK); + } +#endif + + else + { + TINYCLR_SET_AND_LEAVE(TrackObject( res )); + } + + { + CLR_UINT32 shift = 64 - bits; + + if(shift) + { + val <<= shift; + + if(fSigned) val = (CLR_UINT64)((CLR_INT64 )val >> shift); + else val = (CLR_UINT64)((CLR_UINT64)val >> shift); + } + } + + if(m_hints.m_bitPacked) bits = m_hints.m_bitPacked; + + val -= m_hints.m_rangeBias; + + if(fSigned) + { + CLR_INT64 valS = (CLR_INT64)val; + + if(m_hints.m_scale != 0) valS /= (CLR_INT64)m_hints.m_scale; + + if(bits != 64) + { + CLR_INT64 maxVal = (LONGLONGCONSTANT(1) << (bits-1)) - 1; + + if(valS < (-maxVal-1) || valS > maxVal) + { + TINYCLR_SET_AND_LEAVE(CLR_E_SERIALIZATION_VIOLATION); + } + } + + val = (CLR_UINT64)valS; + } + else + { + CLR_UINT64 valU = (CLR_UINT64)val; + + if(m_hints.m_scale != 0) valU /= (CLR_UINT64)m_hints.m_scale; + + if(bits != 64) + { + CLR_UINT64 maxVal = (ULONGLONGCONSTANT(1) << bits) - 1; + + if(valU > maxVal) + { + TINYCLR_SET_AND_LEAVE(CLR_E_SERIALIZATION_VIOLATION); + } + } + + val = (CLR_UINT64)valU; + } + + TINYCLR_CHECK_HRESULT(m_bf->WriteBits( val, bits )); + + res = c_Action_None; TINYCLR_SET_AND_LEAVE(S_OK); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_BinaryFormatter::TypeHandler::ReadValue( int& res ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_HEADER(); + + CLR_UINT64* dst; + CLR_UINT64 val; + CLR_UINT32 bits; + bool fSigned; + + if(m_type->m_handlerCls.m_data == g_CLR_RT_WellKnownTypes.m_DateTime.m_data) + { + CLR_INT64* pVal = Library_corlib_native_System_DateTime::GetValuePtr( *m_value ); FAULT_ON_NULL(pVal); + + dst = (CLR_UINT64*)pVal; + bits = 64; + fSigned = false; + } + else if(m_type->m_handlerCls.m_data == g_CLR_RT_WellKnownTypes.m_TimeSpan.m_data) + { + CLR_INT64* pVal = Library_corlib_native_System_TimeSpan::GetValuePtr( *m_value ); FAULT_ON_NULL(pVal); + + dst = (CLR_UINT64*)pVal; + bits = 64; + fSigned = true; + } + else if(m_type->m_flags == CLR_RT_DataTypeLookup::c_Primitive || + m_type->m_flags == CLR_RT_DataTypeLookup::c_Enum ) + { + bits = TypeHandler::GetSizeOfType( m_type ); + + if(bits == CLR_RT_DataTypeLookup::c_VariableSize) + { + CLR_UINT32 len; + + TINYCLR_CHECK_HRESULT(m_bf->ReadCompressedUnsigned( len )); + + if(len == 0xFFFFFFFF) + { + m_value->SetObjectReference( NULL ); + } + else + { + CLR_RT_HeapBlock_String* str = CLR_RT_HeapBlock_String::CreateInstance( *m_value, len ); CHECK_ALLOCATION(str); + LPSTR dst = (LPSTR)str->StringText(); + + TINYCLR_CHECK_HRESULT(m_bf->ReadArray( (CLR_UINT8*)dst, len )); + dst[ len ] = 0; + } + + res = c_Action_None; TINYCLR_SET_AND_LEAVE(S_OK); + } + else if(bits == CLR_RT_DataTypeLookup::c_NA) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + else + { + m_value->SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(m_type->GetDataType(),0,1) ); + m_value->ClearData( ); + + dst = (CLR_UINT64*)&m_value->NumericByRef().u8; + + fSigned = TypeHandler::GetSignOfType( m_type ); + } + } + else + { + TINYCLR_SET_AND_LEAVE(TrackObject( res )); + } + + if(m_hints.m_bitPacked) bits = m_hints.m_bitPacked; + + TINYCLR_CHECK_HRESULT(m_bf->ReadBits( val, bits )); + + if(bits != 64) + { + int revBits = 64 - bits; + + val <<= revBits; + + if(fSigned) val = (CLR_UINT64)((CLR_INT64)val >> revBits); + else val = ( val >> revBits); + } + + if(m_hints.m_scale != 0) + { + val *= m_hints.m_scale; + } + + *dst = val + m_hints.m_rangeBias; + + res = c_Action_None; TINYCLR_SET_AND_LEAVE(S_OK); + + TINYCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::TypeHandler::TrackObject( int& res ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_HEADER(); + + if(m_type->m_flags & (CLR_RT_DataTypeLookup::c_Array | CLR_RT_DataTypeLookup::c_ArrayList)) + { + res = c_Action_ObjectElements; + } + else + { + res = c_Action_ObjectFields; + + if(m_typeExpected && m_typeExpected->m_flags == CLR_RT_DataTypeLookup::c_ValueType) + { + TINYCLR_SET_AND_LEAVE(S_OK); + } + } + + TINYCLR_SET_AND_LEAVE(m_bf->TrackDuplicate( m_value )); + + TINYCLR_NOCLEANUP(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_BinaryFormatter::State::CreateInstance( CLR_RT_BinaryFormatter* parent, SerializationHintsAttribute* hints, CLR_RT_HeapBlock* type ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_HEADER(); + + CLR_RT_TypeDef_Instance inst; + CLR_RT_TypeDescriptor desc; + CLR_RT_TypeDescriptor* pDesc; + SerializationHintsAttribute hintsTmp; + + if(type && CLR_RT_ReflectionDef_Index::Convert( *type, inst, NULL )) + { + TINYCLR_CHECK_HRESULT(desc.InitializeFromType( inst )); + + pDesc = &desc; + + if(hints == NULL) + { + hints = &hintsTmp; + + TINYCLR_CLEAR(*hints); + + hints->m_flags = (SerializationFlags)(SF_PointerNeverNull | SF_FixedType); + } + } + else + { + pDesc = NULL; + } + + TINYCLR_SET_AND_LEAVE(CreateInstance( parent, hints, pDesc )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_BinaryFormatter::State::CreateInstance( CLR_RT_BinaryFormatter* parent, SerializationHintsAttribute* hints, CLR_RT_TypeDescriptor* type ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_HEADER(); + + State* ptr = EVENTCACHE_EXTRACT_NODE_INITTOZERO(g_CLR_RT_EventCache,State,DATATYPE_SERIALIZER_STATE); + + CHECK_ALLOCATION(ptr); + + parent->m_states.LinkAtBack( ptr ); + + ptr->m_parent = parent; + ptr->m_value_NeedProcessing = true; + ptr->m_value.TypeHandler_Initialize( parent, hints, type ); + + TINYCLR_NOCLEANUP(); +} + +void CLR_RT_BinaryFormatter::State::DestroyInstance() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + g_CLR_RT_EventCache.Append_Node( this ); +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::State::FindHints( SerializationHintsAttribute& hints, const CLR_RT_TypeDef_Instance& cls ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_HEADER(); + + TINYCLR_CLEAR(hints); + + if(cls.m_target->flags & CLR_RECORD_TYPEDEF::TD_HasAttributes) + { + CLR_RT_TypeDef_Instance inst; inst.InitializeFromIndex( g_CLR_RT_WellKnownTypes.m_SerializationHintsAttribute ); + CLR_RT_AttributeEnumerator en; en.Initialize( cls ); + + if(en.MatchNext( &inst, NULL )) + { + CLR_RT_AttributeParser parser; + + TINYCLR_CHECK_HRESULT(parser.Initialize( en )); + + while(true) + { + CLR_RT_AttributeParser::Value* val; + + TINYCLR_CHECK_HRESULT(parser.Next( val )); + + if(val == NULL) break; + } + } + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_BinaryFormatter::State::FindHints( SerializationHintsAttribute& hints, const CLR_RT_FieldDef_Instance& fld ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_HEADER(); + + TINYCLR_CLEAR(hints); + + if(fld.m_target->flags & CLR_RECORD_FIELDDEF::FD_HasAttributes) + { + CLR_RT_TypeDef_Instance inst; inst.InitializeFromIndex( g_CLR_RT_WellKnownTypes.m_SerializationHintsAttribute ); + CLR_RT_AttributeEnumerator en; en.Initialize( fld ); + + if(en.MatchNext( &inst, NULL )) + { + CLR_RT_AttributeParser parser; + + TINYCLR_CHECK_HRESULT(parser.Initialize( en )); + + while(true) + { + CLR_RT_AttributeParser::Value* val; + + TINYCLR_CHECK_HRESULT(parser.Next( val )); + + if(val == NULL) + { + break; + } + else + { + if (!strcmp( val->m_name, "Flags" )) hints.m_flags = (SerializationFlags)val->m_value.NumericByRef().u4; + else if(!strcmp( val->m_name, "ArraySize" )) hints.m_arraySize = val->m_value.NumericByRef().s4; + else if(!strcmp( val->m_name, "BitPacked" )) hints.m_bitPacked = val->m_value.NumericByRef().s4; + else if(!strcmp( val->m_name, "RangeBias" )) hints.m_rangeBias = val->m_value.NumericByRef().s8; + else if(!strcmp( val->m_name, "Scale" )) hints.m_scale = val->m_value.NumericByRef().u8; + } + } + } + } + + TINYCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::State::AssignAndFixBoxing( CLR_RT_HeapBlock& dst ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock* src = m_value.m_value; + CLR_DataType dt = dst.DataType(); + CLR_DataType dt2 = (dt == DATATYPE_ARRAY_BYREF) ? (CLR_DataType)dst.DereferenceArray()->m_typeOfElement : dt; + + if(c_CLR_RT_DataTypeLookup[ dt2 ].m_flags & CLR_RT_DataTypeLookup::c_OptimizedValueType) + { + if(src && (c_CLR_RT_DataTypeLookup[ src->DataType() ].m_flags & CLR_RT_DataTypeLookup::c_OptimizedValueType) == 0) + { + src = TypeHandler::FixNull( src ); + } + + if(src == NULL || (c_CLR_RT_DataTypeLookup[ src->DataType() ].m_flags & CLR_RT_DataTypeLookup::c_OptimizedValueType) == 0) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + else + { + if(src) + { + bool fBox = false; + + if(c_CLR_RT_DataTypeLookup[ src->DataType() ].m_flags & CLR_RT_DataTypeLookup::c_OptimizedValueType) + { + fBox = true; + } + else if(src->IsAValueType()) + { + if(dt == DATATYPE_ARRAY_BYREF) + { + fBox = (dt2 != DATATYPE_VALUETYPE); + } + else + { + fBox = !dst.IsAValueType(); + } + } + // + // Box reflection types + // + else if(src->DataType() == DATATYPE_REFLECTION) + { + const CLR_RT_ReflectionDef_Index* reflex; + const CLR_RT_TypeDef_Index* cls; + CLR_RT_HeapBlock *pDst = &dst; + + reflex = &(src->ReflectionDataConst()); + + switch(reflex->m_kind) + { + case REFLECTION_ASSEMBLY : cls = &g_CLR_RT_WellKnownTypes.m_Assembly ; break; + case REFLECTION_TYPE : cls = &g_CLR_RT_WellKnownTypes.m_Type ; break; + case REFLECTION_TYPE_DELAYED: cls = &g_CLR_RT_WellKnownTypes.m_Type ; break; + case REFLECTION_CONSTRUCTOR : cls = &g_CLR_RT_WellKnownTypes.m_ConstructorInfo; break; + case REFLECTION_METHOD : cls = &g_CLR_RT_WellKnownTypes.m_MethodInfo ; break; + case REFLECTION_FIELD : cls = &g_CLR_RT_WellKnownTypes.m_FieldInfo ; break; + } + + // + // Dereference array element and create boxed reflection type + // + if(dt == DATATYPE_ARRAY_BYREF) + { + CLR_RT_HeapBlock_Array* array = dst.DereferenceArray(); FAULT_ON_NULL(array); + + pDst = (CLR_RT_HeapBlock*)array->GetElement( dst.ArrayIndex() ); + } + + // + // Create boxed object reference for reflection type + // + g_CLR_RT_ExecutionEngine.NewObjectFromIndex(*pDst, *cls); + + + // + // Set reflection type + // + pDst->Dereference()->SetReflection(*reflex); + + TINYCLR_SET_AND_LEAVE(S_OK); + } + + if(fBox) + { + TINYCLR_CHECK_HRESULT(m_value.m_value->PerformBoxing( m_value.m_type->m_handlerCls )); + } + } + else + { + src = &m_value.m_value_tmp; src->SetObjectReference( NULL ); + } + } + + if(dt == DATATYPE_ARRAY_BYREF) + { + TINYCLR_CHECK_HRESULT(src->StoreToReference( dst, 0 )); + } + else + { + dst.Assign( *src ); + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_BinaryFormatter::State::GetValue() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_HEADER(); + + State* prev = (State*)Prev(); + if(prev->Prev() == NULL) + { + TINYCLR_SET_AND_LEAVE(m_value.SetValue( &m_parent->m_value )); + } + + if(prev->m_fields_NeedProcessing) + { + TINYCLR_SET_AND_LEAVE(m_value.SetValue( prev->m_fields_Pointer )); + } + + if(prev->m_array_NeedProcessing) + { + CLR_RT_HeapBlock ref; ref.InitializeArrayReferenceDirect( *prev->m_array, prev->m_array_CurrentPos-1 ); + CLR_RT_HeapBlock val; + + TINYCLR_CHECK_HRESULT(val.LoadFromReference( ref )); + + TINYCLR_SET_AND_LEAVE(m_value.SetValue( &val )); + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_BinaryFormatter::State::SetValueAndDestroyInstance() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_HEADER(); + + if(m_parent->m_fDeserialize) + { + State* prev = (State*)Prev(); + + if(prev->Prev() == NULL) + { + TINYCLR_CHECK_HRESULT(AssignAndFixBoxing( m_parent->m_value )); + } + else + { + if(prev->m_fields_NeedProcessing) + { + TINYCLR_CHECK_HRESULT(AssignAndFixBoxing( *prev->m_fields_Pointer )); + } + + if(prev->m_array_NeedProcessing) + { + CLR_RT_HeapBlock ref; ref.InitializeArrayReferenceDirect( *prev->m_array, prev->m_array_CurrentPos-1 ); + + TINYCLR_CHECK_HRESULT(AssignAndFixBoxing( ref )); + } + } + } + + DestroyInstance(); + + TINYCLR_NOCLEANUP(); +} + +////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_BinaryFormatter::State::Advance() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_HEADER(); + + if(m_value_NeedProcessing) + { + int res; + + m_value_NeedProcessing = false; + + if(m_parent->m_fDeserialize) + { + TINYCLR_CHECK_HRESULT(m_value.ReadSignature( res )); + +#if defined(TINYCLR_APPDOMAINS) + //Make sure that the type being deserialized is loaded in the current appDomain + { + if(m_parent->m_flags & CLR_RT_BinaryFormatter::c_Flags_Marshal) + { + CLR_RT_TypeDef_Index idx; idx.Clear(); + CLR_RT_HeapBlock* value = m_value.m_value; + + if(value && value->DataType() == DATATYPE_REFLECTION) + { + switch(value->ReflectionDataConst().m_kind) + { + case REFLECTION_TYPE: + idx.m_data = value->ReflectionDataConst().m_data.m_type.m_data; + break; + case REFLECTION_TYPE_DELAYED: + //should this be allowed for appdomain+marshaling??? + break; + case REFLECTION_ASSEMBLY: + { + CLR_RT_Assembly_Instance inst; + + if(!inst.InitializeFromIndex( value->ReflectionDataConst().m_data.m_assm )) + { + _ASSERTE(FALSE); + } + + if(!g_CLR_RT_ExecutionEngine.GetCurrentAppDomain()->FindAppDomainAssembly( inst.m_assm )) + { + TINYCLR_SET_AND_LEAVE(CLR_E_APPDOMAIN_MARSHAL_EXCEPTION); + } + } + break; + case REFLECTION_CONSTRUCTOR: + case REFLECTION_METHOD: + { + CLR_RT_MethodDef_Instance inst; + + if(!inst.InitializeFromIndex( value->ReflectionDataConst().m_data.m_method )) + { + _ASSERTE(FALSE); + } + + idx.Set( inst.Assembly(), inst.CrossReference().GetOwner() ); + } + break; + case REFLECTION_FIELD: + { + CLR_RT_FieldDef_Instance inst; + CLR_RT_TypeDescriptor desc; + + if(!inst.InitializeFromIndex( value->ReflectionDataConst().m_data.m_field )) + { + _ASSERTE(FALSE); + } + + TINYCLR_CHECK_HRESULT(desc.InitializeFromFieldDefinition( inst )); + + idx = desc.m_handlerCls; + } + break; + } + } + else if(m_value.m_type) + { + idx = m_value.m_type->m_handlerCls; + } + + if(idx.m_data != 0) + { + TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.GetCurrentAppDomain()->VerifyTypeIsLoaded( idx )); + } + } + } +#endif + + } + else + { + TINYCLR_CHECK_HRESULT(GetValue()); + + TINYCLR_CHECK_HRESULT(m_value.EmitSignature( res )); + } + + if(res != TypeHandler::c_Action_None) + { + if(m_parent->m_fDeserialize) + { + TINYCLR_CHECK_HRESULT(m_value.ReadValue( res )); + + } + else + { + TINYCLR_CHECK_HRESULT(m_value.EmitValue( res )); + } + + switch(res) + { + case TypeHandler::c_Action_None: + break; + + case TypeHandler::c_Action_ObjectFields: + { + m_fields_NeedProcessing = true; + m_fields_CurrentClass = m_value.m_type->m_handlerCls; + m_fields_CurrentField = 0; + m_fields_Pointer = NULL; + break; + } + + case TypeHandler::c_Action_ObjectElements: + { + m_array_NeedProcessing = true; + m_array_CurrentPos = 0; + + if(m_value.m_type->m_flags & CLR_RT_DataTypeLookup::c_ArrayList) + { + int capacity; + + TINYCLR_CHECK_HRESULT(CLR_RT_ArrayListHelper::ExtractArrayFromArrayList( *m_value.m_value, m_array, m_array_LastPos, capacity )); + + m_array_ExpectedType = NULL; + } + else + { + m_array = m_value.m_value->DereferenceArray(); + m_array_LastPos = m_array->m_numOfElements; + + m_array_ExpectedType = &m_array_ExpectedType_Tmp; + m_value.m_type->GetElementType( *m_array_ExpectedType ); + } + + break; + } + } + } + } + + if(m_fields_NeedProcessing) + { + TINYCLR_SET_AND_LEAVE(AdvanceToTheNextField()); + } + + if(m_array_NeedProcessing) + { + TINYCLR_SET_AND_LEAVE(AdvanceToTheNextElement()); + } + + TINYCLR_SET_AND_LEAVE(SetValueAndDestroyInstance()); + + + TINYCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::State::AdvanceToTheNextField() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_HEADER(); + + while(TINYCLR_INDEX_IS_VALID(m_fields_CurrentClass)) + { + if(m_fields_CurrentField < m_fields_CurrentClass.m_target->iFields_Num) + { + int offset = m_fields_CurrentClass.m_target->iFields_First + m_fields_CurrentField++; + CLR_RT_FieldDef_Index idx ; idx.Set( m_fields_CurrentClass.Assembly(), offset ); + CLR_RT_FieldDef_Instance inst; inst.InitializeFromIndex( idx ); + + m_fields_Pointer = m_value.m_value->Dereference() + inst.CrossReference().m_offset; + + if((inst.m_target->flags & CLR_RECORD_FIELDDEF::FD_NotSerialized) == 0) + { + SerializationHintsAttribute hints; + CLR_RT_TypeDescriptor desc; + + if(m_value.m_type->m_flags & CLR_RT_DataTypeLookup::c_Enum) + { + hints = m_value.m_hints; + } + else + { + TINYCLR_CHECK_HRESULT(FindHints( hints, inst )); + } + + TINYCLR_CHECK_HRESULT(desc.InitializeFromFieldDefinition( inst )); + + TINYCLR_SET_AND_LEAVE(State::CreateInstance( m_parent, &hints, &desc )); + } + } + else + { + m_fields_CurrentClass.SwitchToParent(); + m_fields_CurrentField = 0; + } + } + + TINYCLR_SET_AND_LEAVE(SetValueAndDestroyInstance()); + + TINYCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::State::AdvanceToTheNextElement() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_HEADER(); + + if(m_array_ExpectedType && (c_CLR_RT_DataTypeLookup[ m_array->m_typeOfElement ].m_flags & CLR_RT_DataTypeLookup::c_Numeric)) + { + CLR_UINT8* ptr = m_array->GetFirstElement(); + CLR_UINT32 bits = TypeHandler::GetSizeOfType( m_array_ExpectedType ); + int count = m_array_LastPos; + bool fDeserialize = m_parent->m_fDeserialize; + CLR_UINT32 size; + CLR_UINT64 val; + + size = bits / 8; if(size == 0) size = 1; + + while(count > 0) + { + if(fDeserialize) + { + TINYCLR_CHECK_HRESULT(m_parent->ReadBits( val, bits )); + + memcpy( ptr, &val, size ); + } + else + { + val = 0; memcpy( &val, ptr, size ); + + TINYCLR_CHECK_HRESULT(m_parent->WriteBits( val, bits )); + } + + ptr += size; + + count--; + } + } + else if(m_array_CurrentPos < m_array_LastPos) + { + m_array_CurrentPos++; + + SerializationHintsAttribute* hints; + + if(m_value.m_hints.m_flags & (SF_FixedType | SF_PointerNeverNull)) + { + hints = &m_value.m_hints; + } + else + { + hints = NULL; + } + + TINYCLR_SET_AND_LEAVE(State::CreateInstance( m_parent, hints, m_array_ExpectedType )); + } + + TINYCLR_SET_AND_LEAVE(SetValueAndDestroyInstance()); + + TINYCLR_NOCLEANUP(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_BinaryFormatter::CreateInstance( CLR_UINT8* buf, int len, CLR_RT_BinaryFormatter*& res ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_HEADER(); + + CLR_RT_BinaryFormatter* ptr = EVENTCACHE_EXTRACT_NODE(g_CLR_RT_EventCache,CLR_RT_BinaryFormatter,DATATYPE_SERIALIZER_HEAD); + + res = ptr; CHECK_ALLOCATION(ptr); + + ptr->m_stream = NULL; // CLR_RT_HeapBlock_MemoryStream* m_stream; + ptr->m_idx = 0; // CLR_UINT32 m_idx; + ptr->m_lastTypeRead = 0; // CLR_UINT32 m_lastTypeRead; + ptr->m_duplicates.DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_duplicates; // EVENT HEAP - NO RELOCATION - list of CLR_RT_BinaryFormatter::DuplicateTracker + ptr->m_states .DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_states; // EVENT HEAP - NO RELOCATION - list of CLR_RT_BinaryFormatter::State + // + ptr->m_fDeserialize = (buf != NULL); // bool m_fDeserialize; + ptr->m_value.SetObjectReference( NULL ); // CLR_RT_HeapBlock m_value; + ptr->m_value_desc.TypeDescriptor_Initialize(); // CLR_RT_TypeDescriptor m_value_desc; + + + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_MemoryStream::CreateInstance( ptr->m_stream, buf, len )); + + TINYCLR_NOCLEANUP(); +} + +void CLR_RT_BinaryFormatter::DestroyInstance() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + m_states .DblLinkedList_PushToCache(); + m_duplicates.DblLinkedList_PushToCache(); + + CLR_RT_HeapBlock_MemoryStream::DeleteInstance( m_stream ); + + g_CLR_RT_EventCache.Append_Node( this ); +} + +HRESULT CLR_RT_BinaryFormatter::Advance() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_HEADER(); + + while(true) + { + State* top = (State*)m_states.LastNode(); if(top->Prev() == NULL) break; + + TINYCLR_CHECK_HRESULT(top->Advance()); + } + + TINYCLR_NOCLEANUP(); +} + +//--// + +void CLR_RT_BinaryFormatter::PrepareForGC( void* data ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + if(data != NULL) + { + CLR_RT_BinaryFormatter* bf = (CLR_RT_BinaryFormatter*)data; + + g_CLR_RT_GarbageCollector.CheckSingleBlock_Force( &bf->m_value ); + + TINYCLR_FOREACH_NODE(CLR_RT_BinaryFormatter::State,state,bf->m_states) + { + g_CLR_RT_GarbageCollector.CheckSingleBlock_Force( state->m_value.m_value ); + } + TINYCLR_FOREACH_NODE_END(); + } +} + +HRESULT CLR_RT_BinaryFormatter::Serialize( CLR_RT_HeapBlock& refData, CLR_RT_HeapBlock& object, CLR_RT_HeapBlock* cls, CLR_UINT32 flags ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_HEADER(); + + CLR_RT_BinaryFormatter* bf = NULL; + CLR_RT_ProtectFromGC pgc( (void**)&bf, CLR_RT_BinaryFormatter::PrepareForGC ); + + refData.SetObjectReference( NULL ); + + TINYCLR_CHECK_HRESULT(CLR_RT_BinaryFormatter::CreateInstance( NULL, 0, bf )); + + TINYCLR_CHECK_HRESULT(State::CreateInstance( bf, NULL, cls )); + + bf->m_flags = flags; + bf->m_value.Assign( object ); + + TINYCLR_CHECK_HRESULT(bf->Advance()); + + TINYCLR_CHECK_HRESULT(bf->m_stream->ToArray( refData )); + + TINYCLR_CLEANUP(); + + if(bf) + { + bf->DestroyInstance(); + + bf = NULL; + } + + TINYCLR_CLEANUP_END(); +} + +HRESULT CLR_RT_BinaryFormatter::Deserialize( CLR_RT_HeapBlock& refData, CLR_RT_HeapBlock& object, CLR_RT_HeapBlock* cls, CLR_UINT32* unknownType, CLR_UINT32 flags ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock_Array* array = object.DereferenceArray(); + + refData.SetObjectReference( NULL ); + + if(array != NULL) + { + TINYCLR_SET_AND_LEAVE(CLR_RT_BinaryFormatter::Deserialize( refData, array->GetFirstElement(), array->m_numOfElements, cls, unknownType, flags )); + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_BinaryFormatter::Deserialize( CLR_RT_HeapBlock& refData, CLR_UINT8* data, CLR_UINT32 size, CLR_RT_HeapBlock* cls, CLR_UINT32* unknownType, CLR_UINT32 flags ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_HEADER(); + + CLR_RT_BinaryFormatter* bf = NULL; + CLR_RT_ProtectFromGC pgc( (void**)&bf, CLR_RT_BinaryFormatter::PrepareForGC ); + + refData.SetObjectReference( NULL ); + + TINYCLR_CHECK_HRESULT(CLR_RT_BinaryFormatter::CreateInstance( data, size, bf )); + + TINYCLR_CHECK_HRESULT(State::CreateInstance( bf, NULL, cls )); + + bf->m_flags = flags; + + TINYCLR_CHECK_HRESULT(bf->Advance()); + + refData.Assign( bf->m_value ); + + + TINYCLR_CLEANUP(); + + if(bf) + { + if(unknownType) + { + *unknownType = (hr == CLR_E_WRONG_TYPE) ? bf->m_lastTypeRead : 0; + } + + bf->DestroyInstance(); + + bf = NULL; + } + + TINYCLR_CLEANUP_END(); +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::TrackDuplicate( CLR_RT_HeapBlock* object ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_HEADER(); + + DuplicateTracker* ptr = EVENTCACHE_EXTRACT_NODE(g_CLR_RT_EventCache,DuplicateTracker,DATATYPE_SERIALIZER_DUPLICATE); + + CHECK_ALLOCATION(ptr); + + m_duplicates.LinkAtBack( ptr ); + + ptr->m_ptr = TypeHandler::FixDereference( object ); + ptr->m_idx = m_idx++; + + TINYCLR_NOCLEANUP(); +} + +CLR_UINT32 CLR_RT_BinaryFormatter::SearchDuplicate( CLR_RT_HeapBlock* object ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + object = TypeHandler::FixDereference( object ); + + TINYCLR_FOREACH_NODE(DuplicateTracker,ptr,m_duplicates) + { + if(ptr->m_ptr == object) + { + return ptr->m_idx; + } + } + TINYCLR_FOREACH_NODE_END(); + + return (CLR_UINT32)-1; +} + +CLR_RT_HeapBlock* CLR_RT_BinaryFormatter::GetDuplicate( CLR_UINT32 idx ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_FOREACH_NODE(DuplicateTracker,ptr,m_duplicates) + { + if(ptr->m_idx == idx) + { + return ptr->m_ptr; + } + } + TINYCLR_FOREACH_NODE_END(); + + return NULL; +} + +//--//--// + +int CLR_RT_BinaryFormatter::BitsAvailable( ) { return m_stream->BitsAvailable( ); } + +HRESULT CLR_RT_BinaryFormatter::ReadBits ( CLR_UINT32& res, int bits ) { return m_stream->ReadBits ( res, bits ); } +HRESULT CLR_RT_BinaryFormatter::WriteBits ( CLR_UINT32 val, int bits ) { return m_stream->WriteBits ( val, bits ); } + +HRESULT CLR_RT_BinaryFormatter::ReadBits ( CLR_UINT64& res, int bits ) { return m_stream->ReadBits ( res, bits ); } +HRESULT CLR_RT_BinaryFormatter::WriteBits ( CLR_UINT64 val, int bits ) { return m_stream->WriteBits ( val, bits ); } + +HRESULT CLR_RT_BinaryFormatter::ReadArray ( CLR_UINT8* buf, int bytes ) { return m_stream->ReadArray ( buf, bytes ); } +HRESULT CLR_RT_BinaryFormatter::WriteArray ( const CLR_UINT8* buf, int bytes ) { return m_stream->WriteArray ( buf, bytes ); } + +HRESULT CLR_RT_BinaryFormatter::ReadCompressedUnsigned( CLR_UINT32& val ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_HEADER(); + + CLR_UINT32 extra; + + TINYCLR_CHECK_HRESULT(m_stream->ReadBits( val, 8 )); + + if(val == 0xFF) + { + val = 0xFFFFFFFF; + } + else + { + int bits = 0; + + switch(val & 0xC0) + { + case 0x00: bits = 0; break; + case 0x40: bits = 0; break; + case 0x80: bits = 8; break; + case 0xC0: bits = 24; break; + } + + if(bits) + { + hr = m_stream->ReadBits( extra, bits ); + + val = ((val & ~0xC0) << bits) | extra; + } + } + + + TINYCLR_CLEANUP(); + + TINYCLR_CLEANUP_END(); +} + +HRESULT CLR_RT_BinaryFormatter::WriteCompressedUnsigned( CLR_UINT32 val ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_HEADER(); + + int bits; + + if(val == 0xFFFFFFFF) + { + bits = 8; + } + else if(val < 0x80) + { + bits = 8; + } + else if(val < 0x3F00) + { + val |= 0x8000; + bits = 16; + } + else if(val < 0x3F000000) + { + val |= 0xC0000000; + bits = 32; + } + else + { + TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + + TINYCLR_CHECK_HRESULT(m_stream->WriteBits( val, bits )); + + + TINYCLR_CLEANUP(); + + TINYCLR_CLEANUP_END(); +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::ReadType( CLR_RT_ReflectionDef_Index& val ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_HEADER(); + + TINYCLR_CHECK_HRESULT(m_stream->ReadBits( m_lastTypeRead, 32 )); + + val.InitializeFromHash( m_lastTypeRead ); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_BinaryFormatter::WriteType( const CLR_RT_ReflectionDef_Index& val ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_HEADER(); + + TINYCLR_SET_AND_LEAVE(WriteType( val.GetTypeHash() )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_BinaryFormatter::WriteType( CLR_UINT32 hash ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_HEADER(); + + if(hash == 0xFFFFFFFF || hash == 0) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + TINYCLR_SET_AND_LEAVE(m_stream->WriteBits( hash, 32 )); + + TINYCLR_NOCLEANUP(); +} + diff --git a/src/CLR/Core/Serialization/BinaryFormatter_stub.cpp b/src/CLR/Core/Serialization/BinaryFormatter_stub.cpp new file mode 100644 index 0000000000..aa79455b5f --- /dev/null +++ b/src/CLR/Core/Serialization/BinaryFormatter_stub.cpp @@ -0,0 +1,300 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include + +bool CLR_RT_BinaryFormatter::SerializationEnabled() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + return false; +} + +CLR_RT_HeapBlock* CLR_RT_BinaryFormatter::TypeHandler::FixDereference( CLR_RT_HeapBlock* v ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + return NULL; +} + +CLR_RT_HeapBlock* CLR_RT_BinaryFormatter::TypeHandler::FixNull( CLR_RT_HeapBlock* v ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + return NULL; +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::TypeHandler::TypeHandler_Initialize( CLR_RT_BinaryFormatter* bf, SerializationHintsAttribute* hints, CLR_RT_TypeDescriptor* expected ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_FEATURE_STUB_RETURN(); +} + +HRESULT CLR_RT_BinaryFormatter::TypeHandler::SetValue( CLR_RT_HeapBlock* v ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_FEATURE_STUB_RETURN(); +} + +//--// + +int CLR_RT_BinaryFormatter::TypeHandler::SignatureRequirements() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + return 0; +} + +bool CLR_RT_BinaryFormatter::TypeHandler::CompareTypes( CLR_RT_TypeDescriptor* left, CLR_RT_TypeDescriptor* right ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + return true; +} + +CLR_DataType CLR_RT_BinaryFormatter::TypeHandler::GetDataType( CLR_RT_TypeDescriptor* type ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + return (CLR_DataType)0; +} + +CLR_UINT32 CLR_RT_BinaryFormatter::TypeHandler::GetSizeOfType( CLR_RT_TypeDescriptor* type ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + return 0; +} + +bool CLR_RT_BinaryFormatter::TypeHandler::GetSignOfType( CLR_RT_TypeDescriptor* type ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + return true; +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::TypeHandler::EmitSignature( int& res ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_FEATURE_STUB_RETURN(); +} + +HRESULT CLR_RT_BinaryFormatter::TypeHandler::EmitSignature_Inner( int mask, CLR_RT_TypeDescriptor* type, CLR_RT_HeapBlock* value ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_FEATURE_STUB_RETURN(); +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::TypeHandler::ReadSignature( int& res ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_FEATURE_STUB_RETURN(); +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::TypeHandler::EmitValue( int& res ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_FEATURE_STUB_RETURN(); +} + +HRESULT CLR_RT_BinaryFormatter::TypeHandler::ReadValue( int& res ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_FEATURE_STUB_RETURN(); +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::TypeHandler::TrackObject( int& res ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_FEATURE_STUB_RETURN(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_BinaryFormatter::State::CreateInstance( CLR_RT_BinaryFormatter* parent, SerializationHintsAttribute* hints, CLR_RT_HeapBlock* type ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_FEATURE_STUB_RETURN(); +} + +HRESULT CLR_RT_BinaryFormatter::State::CreateInstance( CLR_RT_BinaryFormatter* parent, SerializationHintsAttribute* hints, CLR_RT_TypeDescriptor* type ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_FEATURE_STUB_RETURN(); +} + +void CLR_RT_BinaryFormatter::State::DestroyInstance() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::State::FindHints( SerializationHintsAttribute& hints, const CLR_RT_TypeDef_Instance& cls ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_FEATURE_STUB_RETURN(); +} + +HRESULT CLR_RT_BinaryFormatter::State::FindHints( SerializationHintsAttribute& hints, const CLR_RT_FieldDef_Instance& fld ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_FEATURE_STUB_RETURN(); +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::State::AssignAndFixBoxing( CLR_RT_HeapBlock& dst ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_FEATURE_STUB_RETURN(); +} + +HRESULT CLR_RT_BinaryFormatter::State::GetValue() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_FEATURE_STUB_RETURN(); +} + +HRESULT CLR_RT_BinaryFormatter::State::SetValueAndDestroyInstance() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_FEATURE_STUB_RETURN(); +} + +////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_BinaryFormatter::State::Advance() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_FEATURE_STUB_RETURN(); +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::State::AdvanceToTheNextField() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_FEATURE_STUB_RETURN(); +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::State::AdvanceToTheNextElement() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_FEATURE_STUB_RETURN(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_BinaryFormatter::CreateInstance( CLR_UINT8* buf, int len, CLR_RT_BinaryFormatter*& res ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_FEATURE_STUB_RETURN(); +} + +void CLR_RT_BinaryFormatter::DestroyInstance() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); +} + +HRESULT CLR_RT_BinaryFormatter::Advance() +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_FEATURE_STUB_RETURN(); +} + +//--// + +void CLR_RT_BinaryFormatter::PrepareForGC( void* data ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); +} + +HRESULT CLR_RT_BinaryFormatter::Serialize( CLR_RT_HeapBlock& refData, CLR_RT_HeapBlock& object, CLR_RT_HeapBlock* cls, CLR_UINT32 flags ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_FEATURE_STUB_RETURN(); +} + +HRESULT CLR_RT_BinaryFormatter::Deserialize( CLR_RT_HeapBlock& refData, CLR_RT_HeapBlock& object, CLR_RT_HeapBlock* cls, CLR_UINT32* unknownType, CLR_UINT32 flags ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_FEATURE_STUB_RETURN(); +} + +HRESULT CLR_RT_BinaryFormatter::Deserialize( CLR_RT_HeapBlock& refData, CLR_UINT8* data, CLR_UINT32 size, CLR_RT_HeapBlock* cls, CLR_UINT32* unknownType, CLR_UINT32 flags ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_FEATURE_STUB_RETURN(); +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::TrackDuplicate( CLR_RT_HeapBlock* object ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_FEATURE_STUB_RETURN(); +} + +CLR_UINT32 CLR_RT_BinaryFormatter::SearchDuplicate( CLR_RT_HeapBlock* object ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + return (CLR_UINT32)-1; +} + +CLR_RT_HeapBlock* CLR_RT_BinaryFormatter::GetDuplicate( CLR_UINT32 idx ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + return NULL; +} + +//--//--// + +int CLR_RT_BinaryFormatter::BitsAvailable( ) { return 0; } + +HRESULT CLR_RT_BinaryFormatter::ReadBits ( CLR_UINT32& res, int bits ) { TINYCLR_FEATURE_STUB_RETURN(); } +HRESULT CLR_RT_BinaryFormatter::WriteBits ( CLR_UINT32 val, int bits ) { TINYCLR_FEATURE_STUB_RETURN(); } + +HRESULT CLR_RT_BinaryFormatter::ReadBits ( CLR_UINT64& res, int bits ) { TINYCLR_FEATURE_STUB_RETURN(); } +HRESULT CLR_RT_BinaryFormatter::WriteBits ( CLR_UINT64 val, int bits ) { TINYCLR_FEATURE_STUB_RETURN(); } + +HRESULT CLR_RT_BinaryFormatter::ReadArray ( CLR_UINT8* buf, int bytes ) { TINYCLR_FEATURE_STUB_RETURN(); } +HRESULT CLR_RT_BinaryFormatter::WriteArray ( const CLR_UINT8* buf, int bytes ) { TINYCLR_FEATURE_STUB_RETURN(); } + +HRESULT CLR_RT_BinaryFormatter::ReadCompressedUnsigned( CLR_UINT32& val ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_FEATURE_STUB_RETURN(); +} + +HRESULT CLR_RT_BinaryFormatter::WriteCompressedUnsigned( CLR_UINT32 val ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_FEATURE_STUB_RETURN(); +} + +//--// + +HRESULT CLR_RT_BinaryFormatter::ReadType( CLR_RT_ReflectionDef_Index& val ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_FEATURE_STUB_RETURN(); +} + +HRESULT CLR_RT_BinaryFormatter::WriteType( const CLR_RT_ReflectionDef_Index& val ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_FEATURE_STUB_RETURN(); +} + +HRESULT CLR_RT_BinaryFormatter::WriteType( CLR_UINT32 hash ) +{ + NATIVE_PROFILE_CLR_SERIALIZATION(); + TINYCLR_FEATURE_STUB_RETURN(); +} diff --git a/src/CLR/Core/Serialization/Serialization.vcxproj b/src/CLR/Core/Serialization/Serialization.vcxproj new file mode 100644 index 0000000000..724cf58a79 --- /dev/null +++ b/src/CLR/Core/Serialization/Serialization.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + {16BF6131-A3B8-4B97-B867-E45669FB48BD} + Win32Proj + Serialization + 10.0.14393.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include;..\..\CorLib + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include;..\..\CorLib + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include;..\..\CorLib + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include;..\..\CorLib + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/src/CLR/Core/Serialization/Serialization.vcxproj.filters b/src/CLR/Core/Serialization/Serialization.vcxproj.filters new file mode 100644 index 0000000000..2e4ce595ca --- /dev/null +++ b/src/CLR/Core/Serialization/Serialization.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/src/CLR/Core/Serialization/Serialization_stub.vcxproj b/src/CLR/Core/Serialization/Serialization_stub.vcxproj new file mode 100644 index 0000000000..4192ce03e3 --- /dev/null +++ b/src/CLR/Core/Serialization/Serialization_stub.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + {C337041D-344D-49FE-AD99-B137E7FD0188} + Win32Proj + Serialization_stub + 10.0.14393.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\Include + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/src/CLR/Core/Serialization/Serialization_stub.vcxproj.filters b/src/CLR/Core/Serialization/Serialization_stub.vcxproj.filters new file mode 100644 index 0000000000..4e5d8b8eb3 --- /dev/null +++ b/src/CLR/Core/Serialization/Serialization_stub.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/src/CLR/Core/Streams.cpp b/src/CLR/Core/Streams.cpp new file mode 100644 index 0000000000..332c4ec3da --- /dev/null +++ b/src/CLR/Core/Streams.cpp @@ -0,0 +1,296 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_HeapBlock_MemoryStream::CreateInstance( CLR_RT_HeapBlock_MemoryStream*& stream, CLR_UINT8* buf, int len ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + stream = EVENTCACHE_EXTRACT_NODE(g_CLR_RT_EventCache,CLR_RT_HeapBlock_MemoryStream,DATATYPE_MEMORY_STREAM_HEAD); CHECK_ALLOCATION(stream); + + TINYCLR_SET_AND_LEAVE(stream->Initialize( buf, len )); + + TINYCLR_NOCLEANUP(); +} + +void CLR_RT_HeapBlock_MemoryStream::DeleteInstance( CLR_RT_HeapBlock_MemoryStream*& stream ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(stream) + { + stream->Release(); + + g_CLR_RT_EventCache.Append_Node( stream ); + + stream = NULL; + } +} + +HRESULT CLR_RT_HeapBlock_MemoryStream::Initialize( CLR_UINT8* buf, CLR_UINT32 len ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + m_buffers.DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_buffers; // EVENT HEAP - NO RELOCATION - list of CLR_RT_HeapBlock_MemoryStream::Buffer + + CHECK_ALLOCATION(NewBuffer()); + + if(buf) + { + m_current->m_data = buf; + m_current->m_length = len; + } + + TINYCLR_NOCLEANUP(); +} + +void CLR_RT_HeapBlock_MemoryStream::Release() +{ + NATIVE_PROFILE_CLR_CORE(); + m_buffers.DblLinkedList_PushToCache(); +} + +//--// + +void CLR_RT_HeapBlock_MemoryStream::Rewind() +{ + NATIVE_PROFILE_CLR_CORE(); + m_current = (Buffer*)m_buffers.FirstNode(); + m_pos = -1; + m_avail = 0; +} + +void CLR_RT_HeapBlock_MemoryStream::Reset() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_FOREACH_NODE(Buffer,node,m_buffers) + { + node->m_length = 0; + } + TINYCLR_FOREACH_NODE_END(); + Rewind(); +} + +HRESULT CLR_RT_HeapBlock_MemoryStream::ToArray( CLR_RT_HeapBlock& ref ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_UINT32 tot; + CLR_RT_HeapBlock_Array* array; + CLR_UINT8* buf; + + tot = 0; + TINYCLR_FOREACH_NODE(Buffer,node,m_buffers) + { + tot += node->m_length; + } + TINYCLR_FOREACH_NODE_END(); + + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( ref, tot, g_CLR_RT_WellKnownTypes.m_UInt8 )); + + array = ref.DereferenceArray(); + buf = array->GetFirstElement(); + + TINYCLR_FOREACH_NODE(Buffer,node,m_buffers) + { + memcpy( buf, node->m_payload, node->m_length ); buf += node->m_length; + } + TINYCLR_FOREACH_NODE_END(); + + TINYCLR_NOCLEANUP(); +} + +//--// + +CLR_RT_HeapBlock_MemoryStream::Buffer* CLR_RT_HeapBlock_MemoryStream::NewBuffer() +{ + NATIVE_PROFILE_CLR_CORE(); + Buffer* ptr = EVENTCACHE_EXTRACT_NODE(g_CLR_RT_EventCache,Buffer,DATATYPE_MEMORY_STREAM_DATA); + + if(ptr) + { + m_current = ptr; + m_pos = -1; + m_avail = 0; + + ptr->m_data = ptr->m_payload; + ptr->m_length = 0; + + m_buffers.LinkAtBack( ptr ); + } + + return ptr; +} + +//--// + +int CLR_RT_HeapBlock_MemoryStream::BitsAvailable() +{ + NATIVE_PROFILE_CLR_CORE(); + int val = m_avail - 8 * m_pos - 8; + + TINYCLR_FOREACH_NODE__DIRECT(Buffer,ptr,m_current) + { + val += 8 * ptr->m_length; + } + TINYCLR_FOREACH_NODE_END(); + + return val; +} + +int CLR_RT_HeapBlock_MemoryStream::BitsWritten() +{ + NATIVE_PROFILE_CLR_CORE(); + int val = m_pos * 8 - m_avail + 8; + + TINYCLR_FOREACH_NODE_BACKWARD__DIRECT(Buffer,ptr,m_current->Prev()) + { + val += 8 * ptr->m_length; + } + TINYCLR_FOREACH_NODE_END(); + + return val; +} + +HRESULT CLR_RT_HeapBlock_MemoryStream::ReadBits( CLR_UINT64& res, CLR_UINT32 bits ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_UINT32* ptr = (CLR_UINT32*)&res; + + if(bits > 32) { TINYCLR_CHECK_HRESULT(ReadBits( ptr[ 1 ], bits - 32 )); bits = 32; } + else { ptr[ 1 ] = 0; } + + TINYCLR_SET_AND_LEAVE(ReadBits( ptr[ 0 ], bits )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_MemoryStream::ReadBits( CLR_UINT32& res, CLR_UINT32 bits ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_UINT32 val = 0; + CLR_UINT32 pos = bits; + + while(bits > 0) + { + while(m_avail == 0) + { + m_pos++; + m_avail = 8; + + while(m_pos >= m_current->m_length) + { + m_current = (Buffer*)m_current->Next(); + + if(m_current->Next() == NULL) + { + TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + + m_pos = 0; + } + } + + CLR_UINT32 insert = (bits < m_avail) ? bits : m_avail; + CLR_UINT32 mask = (1 << insert) - 1; + + pos -= insert; val |= (((CLR_UINT32)m_current->m_data[ m_pos ] >> (m_avail - insert)) & mask) << pos; + bits -= insert; + m_avail -= insert; + } + + res = val; + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_MemoryStream::WriteBits( CLR_UINT64 res, CLR_UINT32 bits ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + if(bits > 32) { TINYCLR_CHECK_HRESULT(WriteBits( (CLR_UINT32)(res >> 32), bits - 32 )); bits = 32; } + + TINYCLR_SET_AND_LEAVE(WriteBits( (CLR_UINT32)res, bits )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_MemoryStream::WriteBits( CLR_UINT32 val, CLR_UINT32 bits ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_UINT32 pos = bits; + + while(bits > 0) + { + while(m_avail == 0) + { + m_pos++; + + if(m_pos < sizeof(m_current->m_payload)) + { + m_current->m_length++; + m_current->m_payload[ m_pos ] = 0; + m_avail = 8; + break; + } + + CHECK_ALLOCATION(NewBuffer()); + } + + CLR_UINT32 insert = (bits < m_avail) ? bits : m_avail; + CLR_UINT32 mask = (1 << insert) - 1; + + pos -= insert; m_current->m_payload[ m_pos ] |= (CLR_UINT8)(((val >> pos) & mask) << (m_avail - insert)); + bits -= insert; + m_avail -= insert; + + } + + TINYCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_HeapBlock_MemoryStream::ReadArray( CLR_UINT8* buf, CLR_UINT32 bytes ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_UINT32 data; + + while(bytes-- > 0) + { + TINYCLR_CHECK_HRESULT(ReadBits( data, 8 )); + + *buf++ = (CLR_UINT8)data; + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_HeapBlock_MemoryStream::WriteArray( const CLR_UINT8* buf, CLR_UINT32 bytes ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + while(bytes-- > 0) + { + TINYCLR_CHECK_HRESULT(WriteBits( (CLR_UINT32)*buf++, 8 )); + } + + TINYCLR_NOCLEANUP(); +} diff --git a/src/CLR/Core/StringTable.cpp b/src/CLR/Core/StringTable.cpp new file mode 100644 index 0000000000..8009453d7c --- /dev/null +++ b/src/CLR/Core/StringTable.cpp @@ -0,0 +1,49 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#include "StringTableData.cpp" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_Assembly::InitString() +{ + NATIVE_PROFILE_CLR_CORE(); +} + +LPCSTR CLR_RT_Assembly::GetString( CLR_STRING i ) +{ + NATIVE_PROFILE_CLR_CORE(); + static const CLR_STRING iMax = 0xFFFF - c_CLR_StringTable_Size; + + if(i >= iMax) + { + return &c_CLR_StringTable_Data[ c_CLR_StringTable_Lookup[ (CLR_STRING)0xFFFF - i ] ]; + } + + return &(((LPCSTR)GetTable( TBL_Strings ))[ i ]); +} + +#if defined(_WIN32) + +void CLR_RT_Assembly::InitString( std::map& map ) +{ + NATIVE_PROFILE_CLR_CORE(); + const CLR_STRING* array = c_CLR_StringTable_Lookup; + size_t len = c_CLR_StringTable_Size; + CLR_STRING idx = 0xFFFF; + + map.clear(); + + while(len-- > 0) + { + map[ &c_CLR_StringTable_Data[ *array++ ] ] = idx--; + } +} + +#endif diff --git a/src/CLR/Core/StringTableData.cpp b/src/CLR/Core/StringTableData.cpp new file mode 100644 index 0000000000..2a911386df --- /dev/null +++ b/src/CLR/Core/StringTableData.cpp @@ -0,0 +1,1736 @@ +// +// The StringTable was generated from the following +// specified in Microsoft.SPOT.Support.Settings: +// +// Microsoft.SPOT.Native.strings +// mscorlib.strings +// + +const size_t c_CLR_StringTable_Size = 860; + +const CLR_STRING c_CLR_StringTable_Lookup[] = +{ + /* 0000 */ 0, + /* 0001 */ 7, + /* 0002 */ 13, + /* 0003 */ 19, + /* 0004 */ 23, + /* 0005 */ 56, + /* 0006 */ 61, + /* 0007 */ 65, + /* 0008 */ 73, + /* 0009 */ 82, + /* 000A */ 98, + /* 000B */ 109, + /* 000C */ 120, + /* 000D */ 129, + /* 000E */ 150, + /* 000F */ 160, + /* 0010 */ 187, + /* 0011 */ 194, + /* 0012 */ 207, + /* 0013 */ 218, + /* 0014 */ 238, + /* 0015 */ 259, + /* 0016 */ 277, + /* 0017 */ 299, + /* 0018 */ 327, + /* 0019 */ 337, + /* 001A */ 343, + /* 001B */ 353, + /* 001C */ 363, + /* 001D */ 368, + /* 001E */ 377, + /* 001F */ 390, + /* 0020 */ 409, + /* 0021 */ 422, + /* 0022 */ 440, + /* 0023 */ 452, + /* 0024 */ 472, + /* 0025 */ 479, + /* 0026 */ 493, + /* 0027 */ 498, + /* 0028 */ 504, + /* 0029 */ 514, + /* 002A */ 525, + /* 002B */ 544, + /* 002C */ 559, + /* 002D */ 569, + /* 002E */ 579, + /* 002F */ 591, + /* 0030 */ 596, + /* 0031 */ 609, + /* 0032 */ 616, + /* 0033 */ 629, + /* 0034 */ 642, + /* 0035 */ 652, + /* 0036 */ 660, + /* 0037 */ 666, + /* 0038 */ 671, + /* 0039 */ 680, + /* 003A */ 688, + /* 003B */ 695, + /* 003C */ 700, + /* 003D */ 706, + /* 003E */ 712, + /* 003F */ 718, + /* 0040 */ 724, + /* 0041 */ 732, + /* 0042 */ 746, + /* 0043 */ 754, + /* 0044 */ 770, + /* 0045 */ 780, + /* 0046 */ 791, + /* 0047 */ 798, + /* 0048 */ 818, + /* 0049 */ 834, + /* 004A */ 848, + /* 004B */ 861, + /* 004C */ 870, + /* 004D */ 878, + /* 004E */ 883, + /* 004F */ 890, + /* 0050 */ 907, + /* 0051 */ 911, + /* 0052 */ 916, + /* 0053 */ 929, + /* 0054 */ 944, + /* 0055 */ 968, + /* 0056 */ 980, + /* 0057 */ 993, + /* 0058 */ 1015, + /* 0059 */ 1024, + /* 005A */ 1039, + /* 005B */ 1058, + /* 005C */ 1071, + /* 005D */ 1075, + /* 005E */ 1085, + /* 005F */ 1098, + /* 0060 */ 1111, + /* 0061 */ 1124, + /* 0062 */ 1137, + /* 0063 */ 1149, + /* 0064 */ 1155, + /* 0065 */ 1175, + /* 0066 */ 1184, + /* 0067 */ 1199, + /* 0068 */ 1207, + /* 0069 */ 1217, + /* 006A */ 1226, + /* 006B */ 1234, + /* 006C */ 1246, + /* 006D */ 1262, + /* 006E */ 1270, + /* 006F */ 1277, + /* 0070 */ 1295, + /* 0071 */ 1304, + /* 0072 */ 1325, + /* 0073 */ 1331, + /* 0074 */ 1348, + /* 0075 */ 1357, + /* 0076 */ 1367, + /* 0077 */ 1376, + /* 0078 */ 1384, + /* 0079 */ 1399, + /* 007A */ 1425, + /* 007B */ 1446, + /* 007C */ 1452, + /* 007D */ 1458, + /* 007E */ 1470, + /* 007F */ 1475, + /* 0080 */ 1490, + /* 0081 */ 1497, + /* 0082 */ 1507, + /* 0083 */ 1521, + /* 0084 */ 1531, + /* 0085 */ 1544, + /* 0086 */ 1554, + /* 0087 */ 1563, + /* 0088 */ 1583, + /* 0089 */ 1588, + /* 008A */ 1592, + /* 008B */ 1607, + /* 008C */ 1621, + /* 008D */ 1643, + /* 008E */ 1662, + /* 008F */ 1684, + /* 0090 */ 1706, + /* 0091 */ 1718, + /* 0092 */ 1727, + /* 0093 */ 1744, + /* 0094 */ 1754, + /* 0095 */ 1763, + /* 0096 */ 1780, + /* 0097 */ 1789, + /* 0098 */ 1807, + /* 0099 */ 1820, + /* 009A */ 1826, + /* 009B */ 1832, + /* 009C */ 1838, + /* 009D */ 1847, + /* 009E */ 1854, + /* 009F */ 1871, + /* 00A0 */ 1884, + /* 00A1 */ 1897, + /* 00A2 */ 1917, + /* 00A3 */ 1934, + /* 00A4 */ 1944, + /* 00A5 */ 1947, + /* 00A6 */ 1960, + /* 00A7 */ 1968, + /* 00A8 */ 1982, + /* 00A9 */ 1994, + /* 00AA */ 2014, + /* 00AB */ 2030, + /* 00AC */ 2046, + /* 00AD */ 2068, + /* 00AE */ 2091, + /* 00AF */ 2100, + /* 00B0 */ 2109, + /* 00B1 */ 2124, + /* 00B2 */ 2136, + /* 00B3 */ 2155, + /* 00B4 */ 2166, + /* 00B5 */ 2193, + /* 00B6 */ 2221, + /* 00B7 */ 2231, + /* 00B8 */ 2247, + /* 00B9 */ 2264, + /* 00BA */ 2279, + /* 00BB */ 2293, + /* 00BC */ 2314, + /* 00BD */ 2332, + /* 00BE */ 2341, + /* 00BF */ 2351, + /* 00C0 */ 2361, + /* 00C1 */ 2373, + /* 00C2 */ 2387, + /* 00C3 */ 2402, + /* 00C4 */ 2427, + /* 00C5 */ 2438, + /* 00C6 */ 2448, + /* 00C7 */ 2459, + /* 00C8 */ 2467, + /* 00C9 */ 2477, + /* 00CA */ 2498, + /* 00CB */ 2514, + /* 00CC */ 2532, + /* 00CD */ 2547, + /* 00CE */ 2568, + /* 00CF */ 2580, + /* 00D0 */ 2595, + /* 00D1 */ 2609, + /* 00D2 */ 2630, + /* 00D3 */ 2640, + /* 00D4 */ 2657, + /* 00D5 */ 2675, + /* 00D6 */ 2683, + /* 00D7 */ 2701, + /* 00D8 */ 2717, + /* 00D9 */ 2729, + /* 00DA */ 2745, + /* 00DB */ 2754, + /* 00DC */ 2784, + /* 00DD */ 2797, + /* 00DE */ 2806, + /* 00DF */ 2817, + /* 00E0 */ 2847, + /* 00E1 */ 2852, + /* 00E2 */ 2857, + /* 00E3 */ 2867, + /* 00E4 */ 2887, + /* 00E5 */ 2897, + /* 00E6 */ 2902, + /* 00E7 */ 2915, + /* 00E8 */ 2926, + /* 00E9 */ 2938, + /* 00EA */ 2950, + /* 00EB */ 2960, + /* 00EC */ 2977, + /* 00ED */ 2989, + /* 00EE */ 3001, + /* 00EF */ 3015, + /* 00F0 */ 3027, + /* 00F1 */ 3039, + /* 00F2 */ 3057, + /* 00F3 */ 3072, + /* 00F4 */ 3088, + /* 00F5 */ 3104, + /* 00F6 */ 3117, + /* 00F7 */ 3123, + /* 00F8 */ 3128, + /* 00F9 */ 3140, + /* 00FA */ 3161, + /* 00FB */ 3170, + /* 00FC */ 3180, + /* 00FD */ 3188, + /* 00FE */ 3199, + /* 00FF */ 3224, + /* 0100 */ 3235, + /* 0101 */ 3251, + /* 0102 */ 3276, + /* 0103 */ 3296, + /* 0104 */ 3303, + /* 0105 */ 3325, + /* 0106 */ 3346, + /* 0107 */ 3354, + /* 0108 */ 3360, + /* 0109 */ 3366, + /* 010A */ 3372, + /* 010B */ 3390, + /* 010C */ 3397, + /* 010D */ 3409, + /* 010E */ 3416, + /* 010F */ 3437, + /* 0110 */ 3463, + /* 0111 */ 3470, + /* 0112 */ 3483, + /* 0113 */ 3504, + /* 0114 */ 3515, + /* 0115 */ 3526, + /* 0116 */ 3543, + /* 0117 */ 3554, + /* 0118 */ 3560, + /* 0119 */ 3579, + /* 011A */ 3598, + /* 011B */ 3611, + /* 011C */ 3630, + /* 011D */ 3643, + /* 011E */ 3648, + /* 011F */ 3652, + /* 0120 */ 3666, + /* 0121 */ 3678, + /* 0122 */ 3693, + /* 0123 */ 3698, + /* 0124 */ 3711, + /* 0125 */ 3715, + /* 0126 */ 3721, + /* 0127 */ 3730, + /* 0128 */ 3747, + /* 0129 */ 3766, + /* 012A */ 3771, + /* 012B */ 3775, + /* 012C */ 3784, + /* 012D */ 3795, + /* 012E */ 3807, + /* 012F */ 3823, + /* 0130 */ 3831, + /* 0131 */ 3844, + /* 0132 */ 3855, + /* 0133 */ 3865, + /* 0134 */ 3883, + /* 0135 */ 3894, + /* 0136 */ 3904, + /* 0137 */ 3922, + /* 0138 */ 3937, + /* 0139 */ 3961, + /* 013A */ 3986, + /* 013B */ 4007, + /* 013C */ 4020, + /* 013D */ 4024, + /* 013E */ 4033, + /* 013F */ 4040, + /* 0140 */ 4048, + /* 0141 */ 4054, + /* 0142 */ 4063, + /* 0143 */ 4081, + /* 0144 */ 4098, + /* 0145 */ 4105, + /* 0146 */ 4113, + /* 0147 */ 4118, + /* 0148 */ 4128, + /* 0149 */ 4139, + /* 014A */ 4163, + /* 014B */ 4185, + /* 014C */ 4208, + /* 014D */ 4215, + /* 014E */ 4232, + /* 014F */ 4239, + /* 0150 */ 4263, + /* 0151 */ 4271, + /* 0152 */ 4292, + /* 0153 */ 4298, + /* 0154 */ 4316, + /* 0155 */ 4333, + /* 0156 */ 4347, + /* 0157 */ 4364, + /* 0158 */ 4383, + /* 0159 */ 4397, + /* 015A */ 4402, + /* 015B */ 4408, + /* 015C */ 4412, + /* 015D */ 4429, + /* 015E */ 4448, + /* 015F */ 4452, + /* 0160 */ 4458, + /* 0161 */ 4472, + /* 0162 */ 4485, + /* 0163 */ 4507, + /* 0164 */ 4520, + /* 0165 */ 4525, + /* 0166 */ 4549, + /* 0167 */ 4555, + /* 0168 */ 4561, + /* 0169 */ 4569, + /* 016A */ 4576, + /* 016B */ 4586, + /* 016C */ 4608, + /* 016D */ 4613, + /* 016E */ 4622, + /* 016F */ 4630, + /* 0170 */ 4646, + /* 0171 */ 4662, + /* 0172 */ 4673, + /* 0173 */ 4680, + /* 0174 */ 4697, + /* 0175 */ 4714, + /* 0176 */ 4721, + /* 0177 */ 4730, + /* 0178 */ 4738, + /* 0179 */ 4756, + /* 017A */ 4780, + /* 017B */ 4802, + /* 017C */ 4822, + /* 017D */ 4828, + /* 017E */ 4837, + /* 017F */ 4843, + /* 0180 */ 4859, + /* 0181 */ 4875, + /* 0182 */ 4885, + /* 0183 */ 4899, + /* 0184 */ 4917, + /* 0185 */ 4932, + /* 0186 */ 4955, + /* 0187 */ 4962, + /* 0188 */ 4970, + /* 0189 */ 4976, + /* 018A */ 4996, + /* 018B */ 5018, + /* 018C */ 5041, + /* 018D */ 5060, + /* 018E */ 5077, + /* 018F */ 5092, + /* 0190 */ 5112, + /* 0191 */ 5130, + /* 0192 */ 5142, + /* 0193 */ 5160, + /* 0194 */ 5166, + /* 0195 */ 5184, + /* 0196 */ 5190, + /* 0197 */ 5197, + /* 0198 */ 5202, + /* 0199 */ 5213, + /* 019A */ 5225, + /* 019B */ 5240, + /* 019C */ 5259, + /* 019D */ 5287, + /* 019E */ 5297, + /* 019F */ 5301, + /* 01A0 */ 5313, + /* 01A1 */ 5333, + /* 01A2 */ 5343, + /* 01A3 */ 5356, + /* 01A4 */ 5365, + /* 01A5 */ 5370, + /* 01A6 */ 5381, + /* 01A7 */ 5385, + /* 01A8 */ 5392, + /* 01A9 */ 5397, + /* 01AA */ 5403, + /* 01AB */ 5410, + /* 01AC */ 5419, + /* 01AD */ 5431, + /* 01AE */ 5437, + /* 01AF */ 5442, + /* 01B0 */ 5448, + /* 01B1 */ 5461, + /* 01B2 */ 5474, + /* 01B3 */ 5487, + /* 01B4 */ 5493, + /* 01B5 */ 5504, + /* 01B6 */ 5517, + /* 01B7 */ 5524, + /* 01B8 */ 5531, + /* 01B9 */ 5545, + /* 01BA */ 5561, + /* 01BB */ 5569, + /* 01BC */ 5579, + /* 01BD */ 5588, + /* 01BE */ 5605, + /* 01BF */ 5613, + /* 01C0 */ 5620, + /* 01C1 */ 5639, + /* 01C2 */ 5680, + /* 01C3 */ 5709, + /* 01C4 */ 5740, + /* 01C5 */ 5774, + /* 01C6 */ 5807, + /* 01C7 */ 5839, + /* 01C8 */ 5871, + /* 01C9 */ 5905, + /* 01CA */ 5939, + /* 01CB */ 5973, + /* 01CC */ 5995, + /* 01CD */ 6014, + /* 01CE */ 6035, + /* 01CF */ 6066, + /* 01D0 */ 6076, + /* 01D1 */ 6094, + /* 01D2 */ 6111, + /* 01D3 */ 6143, + /* 01D4 */ 6167, + /* 01D5 */ 6193, + /* 01D6 */ 6239, + /* 01D7 */ 6251, + /* 01D8 */ 6268, + /* 01D9 */ 6284, + /* 01DA */ 6293, + /* 01DB */ 6304, + /* 01DC */ 6315, + /* 01DD */ 6319, + /* 01DE */ 6324, + /* 01DF */ 6331, + /* 01E0 */ 6356, + /* 01E1 */ 6363, + /* 01E2 */ 6384, + /* 01E3 */ 6399, + /* 01E4 */ 6411, + /* 01E5 */ 6423, + /* 01E6 */ 6428, + /* 01E7 */ 6439, + /* 01E8 */ 6448, + /* 01E9 */ 6458, + /* 01EA */ 6467, + /* 01EB */ 6478, + /* 01EC */ 6498, + /* 01ED */ 6504, + /* 01EE */ 6518, + /* 01EF */ 6528, + /* 01F0 */ 6536, + /* 01F1 */ 6551, + /* 01F2 */ 6561, + /* 01F3 */ 6568, + /* 01F4 */ 6580, + /* 01F5 */ 6587, + /* 01F6 */ 6599, + /* 01F7 */ 6608, + /* 01F8 */ 6616, + /* 01F9 */ 6624, + /* 01FA */ 6632, + /* 01FB */ 6644, + /* 01FC */ 6652, + /* 01FD */ 6660, + /* 01FE */ 6669, + /* 01FF */ 6678, + /* 0200 */ 6687, + /* 0201 */ 6696, + /* 0202 */ 6705, + /* 0203 */ 6721, + /* 0204 */ 6729, + /* 0205 */ 6740, + /* 0206 */ 6753, + /* 0207 */ 6775, + /* 0208 */ 6800, + /* 0209 */ 6811, + /* 020A */ 6827, + /* 020B */ 6841, + /* 020C */ 6862, + /* 020D */ 6886, + /* 020E */ 6894, + /* 020F */ 6900, + /* 0210 */ 6905, + /* 0211 */ 6913, + /* 0212 */ 6923, + /* 0213 */ 6934, + /* 0214 */ 6943, + /* 0215 */ 6952, + /* 0216 */ 6965, + /* 0217 */ 6970, + /* 0218 */ 6979, + /* 0219 */ 6987, + /* 021A */ 7003, + /* 021B */ 7011, + /* 021C */ 7027, + /* 021D */ 7036, + /* 021E */ 7053, + /* 021F */ 7060, + /* 0220 */ 7067, + /* 0221 */ 7074, + /* 0222 */ 7086, + /* 0223 */ 7099, + /* 0224 */ 7120, + /* 0225 */ 7127, + /* 0226 */ 7135, + /* 0227 */ 7150, + /* 0228 */ 7156, + /* 0229 */ 7172, + /* 022A */ 7182, + /* 022B */ 7190, + /* 022C */ 7195, + /* 022D */ 7203, + /* 022E */ 7211, + /* 022F */ 7236, + /* 0230 */ 7247, + /* 0231 */ 7260, + /* 0232 */ 7268, + /* 0233 */ 7281, + /* 0234 */ 7295, + /* 0235 */ 7301, + /* 0236 */ 7311, + /* 0237 */ 7313, + /* 0238 */ 7329, + /* 0239 */ 7331, + /* 023A */ 7336, + /* 023B */ 7341, + /* 023C */ 7348, + /* 023D */ 7355, + /* 023E */ 7362, + /* 023F */ 7372, + /* 0240 */ 7379, + /* 0241 */ 7392, + /* 0242 */ 7402, + /* 0243 */ 7411, + /* 0244 */ 7418, + /* 0245 */ 7428, + /* 0246 */ 7450, + /* 0247 */ 7465, + /* 0248 */ 7479, + /* 0249 */ 7485, + /* 024A */ 7492, + /* 024B */ 7499, + /* 024C */ 7511, + /* 024D */ 7526, + /* 024E */ 7535, + /* 024F */ 7552, + /* 0250 */ 7560, + /* 0251 */ 7566, + /* 0252 */ 7578, + /* 0253 */ 7584, + /* 0254 */ 7604, + /* 0255 */ 7626, + /* 0256 */ 7639, + /* 0257 */ 7653, + /* 0258 */ 7666, + /* 0259 */ 7675, + /* 025A */ 7695, + /* 025B */ 7718, + /* 025C */ 7742, + /* 025D */ 7759, + /* 025E */ 7783, + /* 025F */ 7809, + /* 0260 */ 7819, + /* 0261 */ 7832, + /* 0262 */ 7858, + /* 0263 */ 7871, + /* 0264 */ 7881, + /* 0265 */ 7893, + /* 0266 */ 7905, + /* 0267 */ 7920, + /* 0268 */ 7933, + /* 0269 */ 7946, + /* 026A */ 7956, + /* 026B */ 7966, + /* 026C */ 7978, + /* 026D */ 7996, + /* 026E */ 8012, + /* 026F */ 8030, + /* 0270 */ 8050, + /* 0271 */ 8071, + /* 0272 */ 8100, + /* 0273 */ 8109, + /* 0274 */ 8127, + /* 0275 */ 8146, + /* 0276 */ 8154, + /* 0277 */ 8167, + /* 0278 */ 8181, + /* 0279 */ 8195, + /* 027A */ 8212, + /* 027B */ 8221, + /* 027C */ 8239, + /* 027D */ 8249, + /* 027E */ 8257, + /* 027F */ 8271, + /* 0280 */ 8285, + /* 0281 */ 8295, + /* 0282 */ 8320, + /* 0283 */ 8338, + /* 0284 */ 8355, + /* 0285 */ 8379, + /* 0286 */ 8392, + /* 0287 */ 8419, + /* 0288 */ 8447, + /* 0289 */ 8464, + /* 028A */ 8473, + /* 028B */ 8483, + /* 028C */ 8490, + /* 028D */ 8509, + /* 028E */ 8524, + /* 028F */ 8536, + /* 0290 */ 8548, + /* 0291 */ 8563, + /* 0292 */ 8579, + /* 0293 */ 8591, + /* 0294 */ 8602, + /* 0295 */ 8614, + /* 0296 */ 8630, + /* 0297 */ 8646, + /* 0298 */ 8665, + /* 0299 */ 8681, + /* 029A */ 8694, + /* 029B */ 8709, + /* 029C */ 8728, + /* 029D */ 8741, + /* 029E */ 8760, + /* 029F */ 8772, + /* 02A0 */ 8788, + /* 02A1 */ 8802, + /* 02A2 */ 8813, + /* 02A3 */ 8822, + /* 02A4 */ 8831, + /* 02A5 */ 8840, + /* 02A6 */ 8859, + /* 02A7 */ 8870, + /* 02A8 */ 8890, + /* 02A9 */ 8910, + /* 02AA */ 8920, + /* 02AB */ 8940, + /* 02AC */ 8956, + /* 02AD */ 8974, + /* 02AE */ 8989, + /* 02AF */ 9001, + /* 02B0 */ 9012, + /* 02B1 */ 9028, + /* 02B2 */ 9045, + /* 02B3 */ 9055, + /* 02B4 */ 9066, + /* 02B5 */ 9078, + /* 02B6 */ 9088, + /* 02B7 */ 9098, + /* 02B8 */ 9118, + /* 02B9 */ 9133, + /* 02BA */ 9142, + /* 02BB */ 9159, + /* 02BC */ 9167, + /* 02BD */ 9194, + /* 02BE */ 9211, + /* 02BF */ 9236, + /* 02C0 */ 9257, + /* 02C1 */ 9265, + /* 02C2 */ 9279, + /* 02C3 */ 9302, + /* 02C4 */ 9319, + /* 02C5 */ 9333, + /* 02C6 */ 9344, + /* 02C7 */ 9356, + /* 02C8 */ 9371, + /* 02C9 */ 9384, + /* 02CA */ 9401, + /* 02CB */ 9414, + /* 02CC */ 9431, + /* 02CD */ 9448, + /* 02CE */ 9467, + /* 02CF */ 9483, + /* 02D0 */ 9503, + /* 02D1 */ 9518, + /* 02D2 */ 9531, + /* 02D3 */ 9539, + /* 02D4 */ 9550, + /* 02D5 */ 9562, + /* 02D6 */ 9575, + /* 02D7 */ 9596, + /* 02D8 */ 9617, + /* 02D9 */ 9645, + /* 02DA */ 9660, + /* 02DB */ 9677, + /* 02DC */ 9687, + /* 02DD */ 9699, + /* 02DE */ 9712, + /* 02DF */ 9723, + /* 02E0 */ 9739, + /* 02E1 */ 9749, + /* 02E2 */ 9763, + /* 02E3 */ 9781, + /* 02E4 */ 9791, + /* 02E5 */ 9800, + /* 02E6 */ 9837, + /* 02E7 */ 9860, + /* 02E8 */ 9871, + /* 02E9 */ 9882, + /* 02EA */ 9894, + /* 02EB */ 9911, + /* 02EC */ 9920, + /* 02ED */ 9941, + /* 02EE */ 9944, + /* 02EF */ 9950, + /* 02F0 */ 9954, + /* 02F1 */ 9970, + /* 02F2 */ 9986, + /* 02F3 */ 9998, + /* 02F4 */ 10011, + /* 02F5 */ 10025, + /* 02F6 */ 10039, + /* 02F7 */ 10055, + /* 02F8 */ 10066, + /* 02F9 */ 10076, + /* 02FA */ 10081, + /* 02FB */ 10095, + /* 02FC */ 10106, + /* 02FD */ 10115, + /* 02FE */ 10127, + /* 02FF */ 10138, + /* 0300 */ 10153, + /* 0301 */ 10164, + /* 0302 */ 10175, + /* 0303 */ 10189, + /* 0304 */ 10203, + /* 0305 */ 10217, + /* 0306 */ 10224, + /* 0307 */ 10232, + /* 0308 */ 10248, + /* 0309 */ 10254, + /* 030A */ 10271, + /* 030B */ 10279, + /* 030C */ 10294, + /* 030D */ 10303, + /* 030E */ 10310, + /* 030F */ 10315, + /* 0310 */ 10332, + /* 0311 */ 10341, + /* 0312 */ 10351, + /* 0313 */ 10358, + /* 0314 */ 10370, + /* 0315 */ 10379, + /* 0316 */ 10390, + /* 0317 */ 10400, + /* 0318 */ 10407, + /* 0319 */ 10414, + /* 031A */ 10431, + /* 031B */ 10436, + /* 031C */ 10449, + /* 031D */ 10460, + /* 031E */ 10466, + /* 031F */ 10482, + /* 0320 */ 10489, + /* 0321 */ 10498, + /* 0322 */ 10511, + /* 0323 */ 10519, + /* 0324 */ 10527, + /* 0325 */ 10537, + /* 0326 */ 10545, + /* 0327 */ 10559, + /* 0328 */ 10567, + /* 0329 */ 10574, + /* 032A */ 10582, + /* 032B */ 10590, + /* 032C */ 10606, + /* 032D */ 10617, + /* 032E */ 10626, + /* 032F */ 10639, + /* 0330 */ 10644, + /* 0331 */ 10652, + /* 0332 */ 10675, + /* 0333 */ 10696, + /* 0334 */ 10713, + /* 0335 */ 10725, + /* 0336 */ 10737, + /* 0337 */ 10752, + /* 0338 */ 10774, + /* 0339 */ 10788, + /* 033A */ 10800, + /* 033B */ 10819, + /* 033C */ 10834, + /* 033D */ 10851, + /* 033E */ 10864, + /* 033F */ 10877, + /* 0340 */ 10890, + /* 0341 */ 10903, + /* 0342 */ 10914, + /* 0343 */ 10920, + /* 0344 */ 10938, + /* 0345 */ 10959, + /* 0346 */ 10987, + /* 0347 */ 11015, + /* 0348 */ 11028, + /* 0349 */ 11057, + /* 034A */ 11082, + /* 034B */ 11099, + /* 034C */ 11108, + /* 034D */ 11119, + /* 034E */ 11137, + /* 034F */ 11150, + /* 0350 */ 11163, + /* 0351 */ 11179, + /* 0352 */ 11190, + /* 0353 */ 11213, + /* 0354 */ 11230, + /* 0355 */ 11247, + /* 0356 */ 11264, + /* 0357 */ 11269, + /* 0358 */ 11283, + /* 0359 */ 11297, + /* 035A */ 11303, + /* 035B */ 11311, +}; + +const char c_CLR_StringTable_Data[] = + /* 0000 */ ".cctor\0" + /* 0001 */ ".ctor\0" + /* 0002 */ "Abort\0" + /* 0003 */ "Abs\0" + /* 0004 */ "AccessedThroughPropertyAttribute\0" + /* 0005 */ "Acos\0" + /* 0006 */ "Add\0" + /* 0007 */ "AddDays\0" + /* 0008 */ "AddHours\0" + /* 0009 */ "AddMilliseconds\0" + /* 000A */ "AddMinutes\0" + /* 000B */ "AddSeconds\0" + /* 000C */ "AddTicks\0" + /* 000D */ "AnyPendingFinalizers\0" + /* 000E */ "AppDomain\0" + /* 000F */ "AppDomainUnloadedException\0" + /* 0010 */ "Append\0" + /* 0011 */ "AppendHelper\0" + /* 0012 */ "AppendLine\0" + /* 0013 */ "AppendTrailingZeros\0" + /* 0014 */ "ApplicationException\0" + /* 0015 */ "ArgumentException\0" + /* 0016 */ "ArgumentNullException\0" + /* 0017 */ "ArgumentOutOfRangeException\0" + /* 0018 */ "Arguments\0" + /* 0019 */ "Array\0" + /* 001A */ "ArrayList\0" + /* 001B */ "ArraySize\0" + /* 001C */ "Asin\0" + /* 001D */ "Assembly\0" + /* 001E */ "AssemblyInfo\0" + /* 001F */ "AssemblyMemoryInfo\0" + /* 0020 */ "AssemblyName\0" + /* 0021 */ "AssemblyNameFlags\0" + /* 0022 */ "AssemblyRef\0" + /* 0023 */ "AssemblyRefElements\0" + /* 0024 */ "Assert\0" + /* 0025 */ "AsyncCallback\0" + /* 0026 */ "Atan\0" + /* 0027 */ "Atan2\0" + /* 0028 */ "Attribute\0" + /* 0029 */ "Attributes\0" + /* 002A */ "AttributesElements\0" + /* 002B */ "AutoResetEvent\0" + /* 002C */ "Backlight\0" + /* 002D */ "BaseEvent\0" + /* 002E */ "BeginInvoke\0" + /* 002F */ "Bias\0" + /* 0030 */ "BinarySearch\0" + /* 0031 */ "Binder\0" + /* 0032 */ "BindingFlags\0" + /* 0033 */ "BitConverter\0" + /* 0034 */ "BitPacked\0" + /* 0035 */ "Boolean\0" + /* 0036 */ "Break\0" + /* 0037 */ "Byte\0" + /* 0038 */ "ByteCode\0" + /* 0039 */ "Ceiling\0" + /* 003A */ "Change\0" + /* 003B */ "Char\0" + /* 003C */ "Check\0" + /* 003D */ "Clear\0" + /* 003E */ "Clone\0" + /* 003F */ "Close\0" + /* 0040 */ "Combine\0" + /* 0041 */ "CombineArrays\0" + /* 0042 */ "Compare\0" + /* 0043 */ "CompareExchange\0" + /* 0044 */ "CompareTo\0" + /* 0045 */ "ComputeCRC\0" + /* 0046 */ "Concat\0" + /* 0047 */ "ConstraintException\0" + /* 0048 */ "ConstructorInfo\0" + /* 0049 */ "ContactHeight\0" + /* 004A */ "ContactWidth\0" + /* 004B */ "Contains\0" + /* 004C */ "Convert\0" + /* 004D */ "Copy\0" + /* 004E */ "CopyTo\0" + /* 004F */ "CopyToCollection\0" + /* 0050 */ "Cos\0" + /* 0051 */ "Cosh\0" + /* 0052 */ "CreateDomain\0" + /* 0053 */ "CreateInstance\0" + /* 0054 */ "CreateInstanceAndUnwrap\0" + /* 0055 */ "CultureInfo\0" + /* 0056 */ "CultureTypes\0" + /* 0057 */ "CurrentSystemTimeZone\0" + /* 0058 */ "DateTime\0" + /* 0059 */ "DateTimeFormat\0" + /* 005A */ "DateTimeFormatInfo\0" + /* 005B */ "DateTimeKind\0" + /* 005C */ "Day\0" + /* 005D */ "DayOfWeek\0" + /* 005E */ "DaylightBias\0" + /* 005F */ "DaylightDate\0" + /* 0060 */ "DaylightName\0" + /* 0061 */ "DaylightTime\0" + /* 0062 */ "DaysInMonth\0" + /* 0063 */ "Debug\0" + /* 0064 */ "DebuggableAttribute\0" + /* 0065 */ "Debugger\0" + /* 0066 */ "DebuggingModes\0" + /* 0067 */ "Decoder\0" + /* 0068 */ "Decrement\0" + /* 0069 */ "Delegate\0" + /* 006A */ "Dequeue\0" + /* 006B */ "Deserialize\0" + /* 006C */ "DictionaryEntry\0" + /* 006D */ "Dispose\0" + /* 006E */ "Double\0" + /* 006F */ "DoubleToInt64Bits\0" + /* 0070 */ "Duration\0" + /* 0071 */ "EditorBrowsableState\0" + /* 0072 */ "Empty\0" + /* 0073 */ "EnableGCMessages\0" + /* 0074 */ "Encoding\0" + /* 0075 */ "EndInvoke\0" + /* 0076 */ "EndPoint\0" + /* 0077 */ "Enqueue\0" + /* 0078 */ "EnsureCapacity\0" + /* 0079 */ "EnsureStringArrayResource\0" + /* 007A */ "EnsureStringResource\0" + /* 007B */ "Enter\0" + /* 007C */ "Entry\0" + /* 007D */ "EntryForKey\0" + /* 007E */ "Enum\0" + /* 007F */ "EnumeratorType\0" + /* 0080 */ "Equals\0" + /* 0081 */ "EventArgs\0" + /* 0082 */ "EventCategory\0" + /* 0083 */ "EventData\0" + /* 0084 */ "EventMessage\0" + /* 0085 */ "Exception\0" + /* 0086 */ "Exchange\0" + /* 0087 */ "ExecutionConstraint\0" + /* 0088 */ "Exit\0" + /* 0089 */ "Exp\0" + /* 008A */ "ExpandByABlock\0" + /* 008B */ "ExtendedTimer\0" + /* 008C */ "ExtendedWeakReference\0" + /* 008D */ "ExtensionAttribute\0" + /* 008E */ "ExtractRangeFromArray\0" + /* 008F */ "ExtractValueFromArray\0" + /* 0090 */ "FalseString\0" + /* 0091 */ "FieldDef\0" + /* 0092 */ "FieldDefElements\0" + /* 0093 */ "FieldInfo\0" + /* 0094 */ "FieldRef\0" + /* 0095 */ "FieldRefElements\0" + /* 0096 */ "Finalize\0" + /* 0097 */ "FindChunkForIndex\0" + /* 0098 */ "FindResource\0" + /* 0099 */ "Flags\0" + /* 009A */ "Floor\0" + /* 009B */ "Flush\0" + /* 009C */ "FlushAll\0" + /* 009D */ "Format\0" + /* 009E */ "FormatCustomized\0" + /* 009F */ "FormatDigits\0" + /* 00A0 */ "FormatNative\0" + /* 00A1 */ "FromBase64CharArray\0" + /* 00A2 */ "FromBase64String\0" + /* 00A3 */ "FromTicks\0" + /* 00A4 */ "GC\0" + /* 00A5 */ "GenericEvent\0" + /* 00A6 */ "Gesture\0" + /* 00A7 */ "GetAssemblies\0" + /* 00A8 */ "GetAssembly\0" + /* 00A9 */ "GetAssemblyFromHash\0" + /* 00AA */ "GetAssemblyHash\0" + /* 00AB */ "GetAssemblyInfo\0" + /* 00AC */ "GetAssemblyMemoryInfo\0" + /* 00AD */ "GetBase64EncodedLength\0" + /* 00AE */ "GetBytes\0" + /* 00AF */ "GetChars\0" + /* 00B0 */ "GetConstructor\0" + /* 00B1 */ "GetCultures\0" + /* 00B2 */ "GetDaylightChanges\0" + /* 00B3 */ "GetDecoder\0" + /* 00B4 */ "GetDelimitedStringResource\0" + /* 00B5 */ "GetDelimitedStringResources\0" + /* 00B6 */ "GetDomain\0" + /* 00B7 */ "GetDoubleNumber\0" + /* 00B8 */ "GetEffectiveDate\0" + /* 00B9 */ "GetElementType\0" + /* 00BA */ "GetEnumerator\0" + /* 00BB */ "GetExecutingAssembly\0" + /* 00BC */ "GetExpirationDate\0" + /* 00BD */ "GetField\0" + /* 00BE */ "GetFields\0" + /* 00BF */ "GetFormat\0" + /* 00C0 */ "GetHashCode\0" + /* 00C1 */ "GetInterfaces\0" + /* 00C2 */ "GetMachineTime\0" + /* 00C3 */ "GetManifestResourceNames\0" + /* 00C4 */ "GetMessage\0" + /* 00C5 */ "GetMethod\0" + /* 00C6 */ "GetMethods\0" + /* 00C7 */ "GetName\0" + /* 00C8 */ "GetObject\0" + /* 00C9 */ "GetObjectChunkFromId\0" + /* 00CA */ "GetObjectFromId\0" + /* 00CB */ "GetObjectInternal\0" + /* 00CC */ "GetObjectValue\0" + /* 00CD */ "GetParentCultureName\0" + /* 00CE */ "GetPosition\0" + /* 00CF */ "GetRawCertData\0" + /* 00D0 */ "GetRealFormat\0" + /* 00D1 */ "GetSatelliteAssembly\0" + /* 00D2 */ "GetString\0" + /* 00D3 */ "GetSystemVersion\0" + /* 00D4 */ "GetTimeZoneOffset\0" + /* 00D5 */ "GetType\0" + /* 00D6 */ "GetTypeFromHandle\0" + /* 00D7 */ "GetTypeFromHash\0" + /* 00D8 */ "GetTypeHash\0" + /* 00D9 */ "GetTypeInternal\0" + /* 00DA */ "GetTypes\0" + /* 00DB */ "GetTypesImplementingInterface\0" + /* 00DC */ "GetUtcOffset\0" + /* 00DD */ "GetValue\0" + /* 00DE */ "GetVersion\0" + /* 00DF */ "GloballySynchronizedAttribute\0" + /* 00E0 */ "Guid\0" + /* 00E1 */ "Hash\0" + /* 00E2 */ "Hashtable\0" + /* 00E3 */ "HashtableEnumerator\0" + /* 00E4 */ "HexToChar\0" + /* 00E5 */ "Hour\0" + /* 00E6 */ "IAsyncResult\0" + /* 00E7 */ "ICloneable\0" + /* 00E8 */ "ICollection\0" + /* 00E9 */ "IComparable\0" + /* 00EA */ "IComparer\0" + /* 00EB */ "ICustomFormatter\0" + /* 00EC */ "IDictionary\0" + /* 00ED */ "IDisposable\0" + /* 00EE */ "IEEERemainder\0" + /* 00EF */ "IEnumerable\0" + /* 00F0 */ "IEnumerator\0" + /* 00F1 */ "IEqualityComparer\0" + /* 00F2 */ "IEventListener\0" + /* 00F3 */ "IEventProcessor\0" + /* 00F4 */ "IFormatProvider\0" + /* 00F5 */ "IFormattable\0" + /* 00F6 */ "IList\0" + /* 00F7 */ "ILog\0" + /* 00F8 */ "IOException\0" + /* 00F9 */ "IOExceptionErrorCode\0" + /* 00FA */ "IReflect\0" + /* 00FB */ "Increment\0" + /* 00FC */ "IndexOf\0" + /* 00FD */ "IndexOfAny\0" + /* 00FE */ "IndexOutOfRangeException\0" + /* 00FF */ "Initialize\0" + /* 0100 */ "InitializeArray\0" + /* 0101 */ "InitializeForEventSource\0" + /* 0102 */ "InitializeHashTable\0" + /* 0103 */ "Insert\0" + /* 0104 */ "InsertGroupSeperators\0" + /* 0105 */ "InsertValueIntoArray\0" + /* 0106 */ "Install\0" + /* 0107 */ "Int16\0" + /* 0108 */ "Int32\0" + /* 0109 */ "Int64\0" + /* 010A */ "Int64BitsToDouble\0" + /* 010B */ "IntPtr\0" + /* 010C */ "Interlocked\0" + /* 010D */ "Intern\0" + /* 010E */ "InvalidCastException\0" + /* 010F */ "InvalidOperationException\0" + /* 0110 */ "Invoke\0" + /* 0111 */ "InvokeMember\0" + /* 0112 */ "IsDaylightSavingTime\0" + /* 0113 */ "IsEmulator\0" + /* 0114 */ "IsInfinity\0" + /* 0115 */ "IsInstanceOfType\0" + /* 0116 */ "IsInterned\0" + /* 0117 */ "IsNaN\0" + /* 0118 */ "IsNegativeInfinity\0" + /* 0119 */ "IsPositiveInfinity\0" + /* 011A */ "IsSubclassOf\0" + /* 011B */ "IsTransparentProxy\0" + /* 011C */ "IsTypeLoaded\0" + /* 011D */ "Join\0" + /* 011E */ "Key\0" + /* 011F */ "KeyCollection\0" + /* 0120 */ "LastIndexOf\0" + /* 0121 */ "LastIndexOfAny\0" + /* 0122 */ "Load\0" + /* 0123 */ "LoadInternal\0" + /* 0124 */ "Log\0" + /* 0125 */ "Log10\0" + /* 0126 */ "MakeRoom\0" + /* 0127 */ "ManualResetEvent\0" + /* 0128 */ "MarshalByRefObject\0" + /* 0129 */ "Math\0" + /* 012A */ "Max\0" + /* 012B */ "MaxValue\0" + /* 012C */ "MemberInfo\0" + /* 012D */ "MemberTypes\0" + /* 012E */ "MemberwiseClone\0" + /* 012F */ "Message\0" + /* 0130 */ "MetadataSize\0" + /* 0131 */ "MethodBase\0" + /* 0132 */ "MethodDef\0" + /* 0133 */ "MethodDefElements\0" + /* 0134 */ "MethodInfo\0" + /* 0135 */ "MethodRef\0" + /* 0136 */ "MethodRefElements\0" + /* 0137 */ "Microsoft.SPOT\0" + /* 0138 */ "Microsoft.SPOT.Hardware\0" + /* 0139 */ "Microsoft.SPOT.Messaging\0" + /* 013A */ "Microsoft.SPOT.Touch\0" + /* 013B */ "Milliseconds\0" + /* 013C */ "Min\0" + /* 013D */ "MinValue\0" + /* 013E */ "Minute\0" + /* 013F */ "Monitor\0" + /* 0140 */ "Month\0" + /* 0141 */ "MoveNext\0" + /* 0142 */ "MulticastDelegate\0" + /* 0143 */ "Native_Resources\0" + /* 0144 */ "Negate\0" + /* 0145 */ "NewGuid\0" + /* 0146 */ "Next\0" + /* 0147 */ "NextBytes\0" + /* 0148 */ "NextDouble\0" + /* 0149 */ "NotImplementedException\0" + /* 014A */ "NotSupportedException\0" + /* 014B */ "NullReferenceException\0" + /* 014C */ "Number\0" + /* 014D */ "NumberFormatInfo\0" + /* 014E */ "Object\0" + /* 014F */ "ObjectDisposedException\0" + /* 0150 */ "OnEvent\0" + /* 0151 */ "OutOfMemoryException\0" + /* 0152 */ "Parse\0" + /* 0153 */ "ParseAssemblyName\0" + /* 0154 */ "ParseCertificate\0" + /* 0155 */ "ParseNextChar\0" + /* 0156 */ "ParseQuoteString\0" + /* 0157 */ "ParseRepeatPattern\0" + /* 0158 */ "ParseTypeName\0" + /* 0159 */ "Peek\0" + /* 015A */ "Piezo\0" + /* 015B */ "Pop\0" + /* 015C */ "PostProcessFloat\0" + /* 015D */ "PostProcessInteger\0" + /* 015E */ "Pow\0" + /* 015F */ "Print\0" + /* 0160 */ "PriorityLevel\0" + /* 0161 */ "ProcessEvent\0" + /* 0162 */ "ProcessorArchitecture\0" + /* 0163 */ "PropertyInfo\0" + /* 0164 */ "Push\0" + /* 0165 */ "PushBackIntoRecoverList\0" + /* 0166 */ "Queue\0" + /* 0167 */ "Raise\0" + /* 0168 */ "RamSize\0" + /* 0169 */ "Random\0" + /* 016A */ "RangeBias\0" + /* 016B */ "ReRegisterForFinalize\0" + /* 016C */ "Read\0" + /* 016D */ "ReadByte\0" + /* 016E */ "Recover\0" + /* 016F */ "RecoverOrCreate\0" + /* 0170 */ "ReferenceEquals\0" + /* 0171 */ "Reflection\0" + /* 0172 */ "Rehash\0" + /* 0173 */ "RemotedException\0" + /* 0174 */ "RemotingServices\0" + /* 0175 */ "Remove\0" + /* 0176 */ "RemoveAt\0" + /* 0177 */ "Replace\0" + /* 0178 */ "ReplaceAllInChunk\0" + /* 0179 */ "ReplaceDecimalSeperator\0" + /* 017A */ "ReplaceInPlaceAtChunk\0" + /* 017B */ "ReplaceNegativeSign\0" + /* 017C */ "Reply\0" + /* 017D */ "ReplyRaw\0" + /* 017E */ "Reset\0" + /* 017F */ "ResourceManager\0" + /* 0180 */ "ResourceUtility\0" + /* 0181 */ "Resources\0" + /* 0182 */ "ResourcesData\0" + /* 0183 */ "ResourcesElements\0" + /* 0184 */ "ResourcesFiles\0" + /* 0185 */ "ResourcesFilesElements\0" + /* 0186 */ "Resume\0" + /* 0187 */ "RomSize\0" + /* 0188 */ "Round\0" + /* 0189 */ "RunClassConstructor\0" + /* 018A */ "RuntimeArgumentHandle\0" + /* 018B */ "RuntimeConstructorInfo\0" + /* 018C */ "RuntimeFieldHandle\0" + /* 018D */ "RuntimeFieldInfo\0" + /* 018E */ "RuntimeHelpers\0" + /* 018F */ "RuntimeMethodHandle\0" + /* 0190 */ "RuntimeMethodInfo\0" + /* 0191 */ "RuntimeType\0" + /* 0192 */ "RuntimeTypeHandle\0" + /* 0193 */ "SByte\0" + /* 0194 */ "SZArrayEnumerator\0" + /* 0195 */ "Scale\0" + /* 0196 */ "Second\0" + /* 0197 */ "Seek\0" + /* 0198 */ "SeekOrigin\0" + /* 0199 */ "SendMessage\0" + /* 019A */ "SendMessageRaw\0" + /* 019B */ "SerializationFlags\0" + /* 019C */ "SerializationHintsAttribute\0" + /* 019D */ "Serialize\0" + /* 019E */ "Set\0" + /* 019F */ "SetCapacity\0" + /* 01A0 */ "SetCurrentUICulture\0" + /* 01A1 */ "SetLength\0" + /* 01A2 */ "SetLocalTime\0" + /* 01A3 */ "SetValue\0" + /* 01A4 */ "Sign\0" + /* 01A5 */ "Signatures\0" + /* 01A6 */ "Sin\0" + /* 01A7 */ "Single\0" + /* 01A8 */ "Sinh\0" + /* 01A9 */ "Sleep\0" + /* 01AA */ "Source\0" + /* 01AB */ "SourceID\0" + /* 01AC */ "SpecifyKind\0" + /* 01AD */ "Split\0" + /* 01AE */ "Sqrt\0" + /* 01AF */ "Stack\0" + /* 01B0 */ "StandardBias\0" + /* 01B1 */ "StandardDate\0" + /* 01B2 */ "StandardName\0" + /* 01B3 */ "Start\0" + /* 01B4 */ "StartsWith\0" + /* 01B5 */ "StaticFields\0" + /* 01B6 */ "Stream\0" + /* 01B7 */ "String\0" + /* 01B8 */ "StringBuilder\0" + /* 01B9 */ "StringResources\0" + /* 01BA */ "Strings\0" + /* 01BB */ "Substring\0" + /* 01BC */ "Subtract\0" + /* 01BD */ "SuppressFinalize\0" + /* 01BE */ "Suspend\0" + /* 01BF */ "System\0" + /* 01C0 */ "System.Collections\0" + /* 01C1 */ "System.Collections.ICollection.get_Count\0" + /* 01C2 */ "System.Collections.IList.Add\0" + /* 01C3 */ "System.Collections.IList.Clear\0" + /* 01C4 */ "System.Collections.IList.Contains\0" + /* 01C5 */ "System.Collections.IList.IndexOf\0" + /* 01C6 */ "System.Collections.IList.Insert\0" + /* 01C7 */ "System.Collections.IList.Remove\0" + /* 01C8 */ "System.Collections.IList.RemoveAt\0" + /* 01C9 */ "System.Collections.IList.get_Item\0" + /* 01CA */ "System.Collections.IList.set_Item\0" + /* 01CB */ "System.ComponentModel\0" + /* 01CC */ "System.Diagnostics\0" + /* 01CD */ "System.Globalization\0" + /* 01CE */ "System.Globalization.Resources\0" + /* 01CF */ "System.IO\0" + /* 01D0 */ "System.Reflection\0" + /* 01D1 */ "System.Resources\0" + /* 01D2 */ "System.Runtime.CompilerServices\0" + /* 01D3 */ "System.Runtime.Remoting\0" + /* 01D4 */ "System.Runtime.Versioning\0" + /* 01D5 */ "System.Security.Cryptography.X509Certificates\0" + /* 01D6 */ "System.Text\0" + /* 01D7 */ "System.Threading\0" + /* 01D8 */ "SystemException\0" + /* 01D9 */ "SystemID\0" + /* 01DA */ "SystemInfo\0" + /* 01DB */ "SystemTime\0" + /* 01DC */ "Tan\0" + /* 01DD */ "Tanh\0" + /* 01DE */ "Target\0" + /* 01DF */ "TargetFrameworkAttribute\0" + /* 01E0 */ "Thread\0" + /* 01E1 */ "ThreadAbortException\0" + /* 01E2 */ "ThreadPriority\0" + /* 01E3 */ "ThreadStart\0" + /* 01E4 */ "ThreadState\0" + /* 01E5 */ "Time\0" + /* 01E6 */ "TimeEvents\0" + /* 01E7 */ "TimeSpan\0" + /* 01E8 */ "TimeStamp\0" + /* 01E9 */ "TimeZone\0" + /* 01EA */ "TimeZoneId\0" + /* 01EB */ "TimeZoneInformation\0" + /* 01EC */ "Timer\0" + /* 01ED */ "TimerCallback\0" + /* 01EE */ "Timestamp\0" + /* 01EF */ "ToArray\0" + /* 01F0 */ "ToBase64String\0" + /* 01F1 */ "ToBoolean\0" + /* 01F2 */ "ToByte\0" + /* 01F3 */ "ToByteArray\0" + /* 01F4 */ "ToChar\0" + /* 01F5 */ "ToCharArray\0" + /* 01F6 */ "ToDouble\0" + /* 01F7 */ "ToInt16\0" + /* 01F8 */ "ToInt32\0" + /* 01F9 */ "ToInt64\0" + /* 01FA */ "ToLocalTime\0" + /* 01FB */ "ToLower\0" + /* 01FC */ "ToSByte\0" + /* 01FD */ "ToSingle\0" + /* 01FE */ "ToString\0" + /* 01FF */ "ToUInt16\0" + /* 0200 */ "ToUInt32\0" + /* 0201 */ "ToUInt64\0" + /* 0202 */ "ToUniversalTime\0" + /* 0203 */ "ToUpper\0" + /* 0204 */ "TouchEvent\0" + /* 0205 */ "TouchGesture\0" + /* 0206 */ "TouchGestureEventArgs\0" + /* 0207 */ "TouchGestureEventHandler\0" + /* 0208 */ "TouchInput\0" + /* 0209 */ "TouchInputFlags\0" + /* 020A */ "TouchMessages\0" + /* 020B */ "TouchScreenEventArgs\0" + /* 020C */ "TouchScreenEventHandler\0" + /* 020D */ "Touches\0" + /* 020E */ "Trace\0" + /* 020F */ "Trim\0" + /* 0210 */ "TrimEnd\0" + /* 0211 */ "TrimStart\0" + /* 0212 */ "TrueString\0" + /* 0213 */ "Truncate\0" + /* 0214 */ "TryParse\0" + /* 0215 */ "TrySZIndexOf\0" + /* 0216 */ "Type\0" + /* 0217 */ "TypeCode\0" + /* 0218 */ "TypeDef\0" + /* 0219 */ "TypeDefElements\0" + /* 021A */ "TypeRef\0" + /* 021B */ "TypeRefElements\0" + /* 021C */ "TypeSpec\0" + /* 021D */ "TypeSpecElements\0" + /* 021E */ "UInt16\0" + /* 021F */ "UInt32\0" + /* 0220 */ "UInt64\0" + /* 0221 */ "UTF8Decoder\0" + /* 0222 */ "UTF8Encoding\0" + /* 0223 */ "UnknownTypeException\0" + /* 0224 */ "Unload\0" + /* 0225 */ "Utility\0" + /* 0226 */ "ValidateFormat\0" + /* 0227 */ "Value\0" + /* 0228 */ "ValueCollection\0" + /* 0229 */ "ValueType\0" + /* 022A */ "Version\0" + /* 022B */ "Void\0" + /* 022C */ "WaitAll\0" + /* 022D */ "WaitAny\0" + /* 022E */ "WaitForPendingFinalizers\0" + /* 022F */ "WaitHandle\0" + /* 0230 */ "WaitMultiple\0" + /* 0231 */ "WaitOne\0" + /* 0232 */ "WeakDelegate\0" + /* 0233 */ "WeakReference\0" + /* 0234 */ "Write\0" + /* 0235 */ "WriteByte\0" + /* 0236 */ "X\0" + /* 0237 */ "X509Certificate\0" + /* 0238 */ "Y\0" + /* 0239 */ "Year\0" + /* 023A */ "Zero\0" + /* 023B */ "_Build\0" + /* 023C */ "_Major\0" + /* 023D */ "_Minor\0" + /* 023E */ "_Revision\0" + /* 023F */ "_array\0" + /* 0240 */ "_arrayLength\0" + /* 0241 */ "_assembly\0" + /* 0242 */ "_buckets\0" + /* 0243 */ "_count\0" + /* 0244 */ "_endIndex\0" + /* 0245 */ "_frameworkDisplayName\0" + /* 0246 */ "_frameworkName\0" + /* 0247 */ "_growthFactor\0" + /* 0248 */ "_head\0" + /* 0249 */ "_index\0" + /* 024A */ "_items\0" + /* 024B */ "_loadFactor\0" + /* 024C */ "_maxLoadFactor\0" + /* 024D */ "_message\0" + /* 024E */ "_numberOfBuckets\0" + /* 024F */ "_random\0" + /* 0250 */ "_size\0" + /* 0251 */ "_startIndex\0" + /* 0252 */ "_tail\0" + /* 0253 */ "abbreviatedDayNames\0" + /* 0254 */ "abbreviatedMonthNames\0" + /* 0255 */ "amDesignator\0" + /* 0256 */ "dateSeparator\0" + /* 0257 */ "dateTimeInfo\0" + /* 0258 */ "dayNames\0" + /* 0259 */ "fullDateTimePattern\0" + /* 025A */ "generalLongTimePattern\0" + /* 025B */ "generalShortTimePattern\0" + /* 025C */ "get_AMDesignator\0" + /* 025D */ "get_AbbreviatedDayNames\0" + /* 025E */ "get_AbbreviatedMonthNames\0" + /* 025F */ "get_Angle\0" + /* 0260 */ "get_Assembly\0" + /* 0261 */ "get_AssemblyQualifiedName\0" + /* 0262 */ "get_BaseType\0" + /* 0263 */ "get_Build\0" + /* 0264 */ "get_CanRead\0" + /* 0265 */ "get_CanSeek\0" + /* 0266 */ "get_CanTimeout\0" + /* 0267 */ "get_CanWrite\0" + /* 0268 */ "get_Capacity\0" + /* 0269 */ "get_Chars\0" + /* 026A */ "get_Count\0" + /* 026B */ "get_Current\0" + /* 026C */ "get_CurrentDomain\0" + /* 026D */ "get_CurrentInfo\0" + /* 026E */ "get_CurrentThread\0" + /* 026F */ "get_CurrentTimeZone\0" + /* 0270 */ "get_CurrentUICulture\0" + /* 0271 */ "get_CurrentUICultureInternal\0" + /* 0272 */ "get_Date\0" + /* 0273 */ "get_DateSeparator\0" + /* 0274 */ "get_DateTimeFormat\0" + /* 0275 */ "get_Day\0" + /* 0276 */ "get_DayNames\0" + /* 0277 */ "get_DayOfWeek\0" + /* 0278 */ "get_DayOfYear\0" + /* 0279 */ "get_DaylightName\0" + /* 027A */ "get_Days\0" + /* 027B */ "get_DeclaringType\0" + /* 027C */ "get_Delta\0" + /* 027D */ "get_End\0" + /* 027E */ "get_ErrorCode\0" + /* 027F */ "get_FieldType\0" + /* 0280 */ "get_Flags\0" + /* 0281 */ "get_FrameworkDisplayName\0" + /* 0282 */ "get_FrameworkName\0" + /* 0283 */ "get_FriendlyName\0" + /* 0284 */ "get_FullDateTimePattern\0" + /* 0285 */ "get_FullName\0" + /* 0286 */ "get_GeneralLongTimePattern\0" + /* 0287 */ "get_GeneralShortTimePattern\0" + /* 0288 */ "get_GrowthFactor\0" + /* 0289 */ "get_Hour\0" + /* 028A */ "get_Hours\0" + /* 028B */ "get_Id\0" + /* 028C */ "get_InnerException\0" + /* 028D */ "get_IsAbstract\0" + /* 028E */ "get_IsAlive\0" + /* 028F */ "get_IsArray\0" + /* 0290 */ "get_IsAttached\0" + /* 0291 */ "get_IsBigEndian\0" + /* 0292 */ "get_IsClass\0" + /* 0293 */ "get_IsEnum\0" + /* 0294 */ "get_IsFinal\0" + /* 0295 */ "get_IsFixedSize\0" + /* 0296 */ "get_IsInterface\0" + /* 0297 */ "get_IsLittleEndian\0" + /* 0298 */ "get_IsNotPublic\0" + /* 0299 */ "get_IsPublic\0" + /* 029A */ "get_IsReadOnly\0" + /* 029B */ "get_IsSerializable\0" + /* 029C */ "get_IsStatic\0" + /* 029D */ "get_IsSynchronized\0" + /* 029E */ "get_IsValid\0" + /* 029F */ "get_IsValueType\0" + /* 02A0 */ "get_IsVirtual\0" + /* 02A1 */ "get_Issuer\0" + /* 02A2 */ "get_Item\0" + /* 02A3 */ "get_Keys\0" + /* 02A4 */ "get_Kind\0" + /* 02A5 */ "get_LastExpiration\0" + /* 02A6 */ "get_Length\0" + /* 02A7 */ "get_LongDatePattern\0" + /* 02A8 */ "get_LongTimePattern\0" + /* 02A9 */ "get_Major\0" + /* 02AA */ "get_ManagedThreadId\0" + /* 02AB */ "get_MaxCapacity\0" + /* 02AC */ "get_MaxLoadFactor\0" + /* 02AD */ "get_MemberType\0" + /* 02AE */ "get_Message\0" + /* 02AF */ "get_Method\0" + /* 02B0 */ "get_Millisecond\0" + /* 02B1 */ "get_Milliseconds\0" + /* 02B2 */ "get_Minor\0" + /* 02B3 */ "get_Minute\0" + /* 02B4 */ "get_Minutes\0" + /* 02B5 */ "get_Model\0" + /* 02B6 */ "get_Month\0" + /* 02B7 */ "get_MonthDayPattern\0" + /* 02B8 */ "get_MonthNames\0" + /* 02B9 */ "get_Name\0" + /* 02BA */ "get_NegativeSign\0" + /* 02BB */ "get_Now\0" + /* 02BC */ "get_NumberDecimalSeparator\0" + /* 02BD */ "get_NumberFormat\0" + /* 02BE */ "get_NumberGroupSeparator\0" + /* 02BF */ "get_NumberGroupSizes\0" + /* 02C0 */ "get_OEM\0" + /* 02C1 */ "get_OEMString\0" + /* 02C2 */ "get_OffsetToStringData\0" + /* 02C3 */ "get_PMDesignator\0" + /* 02C4 */ "get_ParamName\0" + /* 02C5 */ "get_Parent\0" + /* 02C6 */ "get_Payload\0" + /* 02C7 */ "get_PayloadRaw\0" + /* 02C8 */ "get_Position\0" + /* 02C9 */ "get_PositiveSign\0" + /* 02CA */ "get_Priority\0" + /* 02CB */ "get_PropertyName\0" + /* 02CC */ "get_PropertyType\0" + /* 02CD */ "get_RFC1123Pattern\0" + /* 02CE */ "get_ReadTimeout\0" + /* 02CF */ "get_ResourceManager\0" + /* 02D0 */ "get_ReturnType\0" + /* 02D1 */ "get_Revision\0" + /* 02D2 */ "get_SKU\0" + /* 02D3 */ "get_Second\0" + /* 02D4 */ "get_Seconds\0" + /* 02D5 */ "get_Selector\0" + /* 02D6 */ "get_ShortDatePattern\0" + /* 02D7 */ "get_ShortTimePattern\0" + /* 02D8 */ "get_SortableDateTimePattern\0" + /* 02D9 */ "get_StackTrace\0" + /* 02DA */ "get_StandardName\0" + /* 02DB */ "get_Start\0" + /* 02DC */ "get_Subject\0" + /* 02DD */ "get_SyncRoot\0" + /* 02DE */ "get_Target\0" + /* 02DF */ "get_ThreadState\0" + /* 02E0 */ "get_Ticks\0" + /* 02E1 */ "get_TimeOfDay\0" + /* 02E2 */ "get_TimeSeparator\0" + /* 02E3 */ "get_Today\0" + /* 02E4 */ "get_UTF8\0" + /* 02E5 */ "get_UniversalSortableDateTimePattern\0" + /* 02E6 */ "get_UseRFC4648Encoding\0" + /* 02E7 */ "get_UtcNow\0" + /* 02E8 */ "get_Values\0" + /* 02E9 */ "get_Version\0" + /* 02EA */ "get_WriteTimeout\0" + /* 02EB */ "get_Year\0" + /* 02EC */ "get_YearMonthPattern\0" + /* 02ED */ "ht\0" + /* 02EE */ "index\0" + /* 02EF */ "key\0" + /* 02F0 */ "longDatePattern\0" + /* 02F1 */ "longTimePattern\0" + /* 02F2 */ "m_AppDomain\0" + /* 02F3 */ "m_ChunkChars\0" + /* 02F4 */ "m_ChunkLength\0" + /* 02F5 */ "m_ChunkOffset\0" + /* 02F6 */ "m_ChunkPrevious\0" + /* 02F7 */ "m_Delegate\0" + /* 02F8 */ "m_HResult\0" + /* 02F9 */ "m_Id\0" + /* 02FA */ "m_MaxCapacity\0" + /* 02FB */ "m_Priority\0" + /* 02FC */ "m_Thread\0" + /* 02FD */ "m_appDomain\0" + /* 02FE */ "m_assembly\0" + /* 02FF */ "m_baseAssembly\0" + /* 0300 */ "m_baseName\0" + /* 0301 */ "m_callback\0" + /* 0302 */ "m_certificate\0" + /* 0303 */ "m_cultureInfo\0" + /* 0304 */ "m_cultureName\0" + /* 0305 */ "m_data\0" + /* 0306 */ "m_delta\0" + /* 0307 */ "m_effectiveDate\0" + /* 0308 */ "m_end\0" + /* 0309 */ "m_expirationDate\0" + /* 030A */ "m_flags\0" + /* 030B */ "m_friendlyName\0" + /* 030C */ "m_handle\0" + /* 030D */ "m_hash\0" + /* 030E */ "m_id\0" + /* 030F */ "m_innerException\0" + /* 0310 */ "m_issuer\0" + /* 0311 */ "m_message\0" + /* 0312 */ "m_name\0" + /* 0313 */ "m_paramName\0" + /* 0314 */ "m_parent\0" + /* 0315 */ "m_password\0" + /* 0316 */ "m_payload\0" + /* 0317 */ "m_rand\0" + /* 0318 */ "m_refs\0" + /* 0319 */ "m_resourceFileId\0" + /* 031A */ "m_rm\0" + /* 031B */ "m_rmFallback\0" + /* 031C */ "m_selector\0" + /* 031D */ "m_seq\0" + /* 031E */ "m_sessionHandle\0" + /* 031F */ "m_size\0" + /* 0320 */ "m_source\0" + /* 0321 */ "m_stackTrace\0" + /* 0322 */ "m_start\0" + /* 0323 */ "m_state\0" + /* 0324 */ "m_subject\0" + /* 0325 */ "m_ticks\0" + /* 0326 */ "m_ticksOffset\0" + /* 0327 */ "m_timer\0" + /* 0328 */ "m_type\0" + /* 0329 */ "m_value\0" + /* 032A */ "manager\0" + /* 032B */ "monthDayPattern\0" + /* 032C */ "monthNames\0" + /* 032D */ "mscorlib\0" + /* 032E */ "negativeSign\0" + /* 032F */ "next\0" + /* 0330 */ "numInfo\0" + /* 0331 */ "numberDecimalSeparator\0" + /* 0332 */ "numberGroupSeparator\0" + /* 0333 */ "numberGroupSizes\0" + /* 0334 */ "op_Addition\0" + /* 0335 */ "op_Equality\0" + /* 0336 */ "op_GreaterThan\0" + /* 0337 */ "op_GreaterThanOrEqual\0" + /* 0338 */ "op_Inequality\0" + /* 0339 */ "op_LessThan\0" + /* 033A */ "op_LessThanOrEqual\0" + /* 033B */ "op_Subtraction\0" + /* 033C */ "op_UnaryNegation\0" + /* 033D */ "op_UnaryPlus\0" + /* 033E */ "pmDesignator\0" + /* 033F */ "positiveSign\0" + /* 0340 */ "propertyName\0" + /* 0341 */ "returnType\0" + /* 0342 */ "s_ewr\0" + /* 0343 */ "s_rgbBase64Decode\0" + /* 0344 */ "s_rgchBase64Encoding\0" + /* 0345 */ "s_rgchBase64EncodingDefault\0" + /* 0346 */ "s_rgchBase64EncodingRFC4648\0" + /* 0347 */ "set_Capacity\0" + /* 0348 */ "set_CurrentUICultureInternal\0" + /* 0349 */ "set_FrameworkDisplayName\0" + /* 034A */ "set_GrowthFactor\0" + /* 034B */ "set_Item\0" + /* 034C */ "set_Length\0" + /* 034D */ "set_MaxLoadFactor\0" + /* 034E */ "set_Position\0" + /* 034F */ "set_Priority\0" + /* 0350 */ "set_ReadTimeout\0" + /* 0351 */ "set_Target\0" + /* 0352 */ "set_UseRFC4648Encoding\0" + /* 0353 */ "set_WriteTimeout\0" + /* 0354 */ "shortDatePattern\0" + /* 0355 */ "shortTimePattern\0" + /* 0356 */ "temp\0" + /* 0357 */ "ticksAtOrigin\0" + /* 0358 */ "timeSeparator\0" + /* 0359 */ "value\0" + /* 035A */ "value__\0" + /* 035B */ "yearMonthPattern\0" +; diff --git a/src/CLR/Core/Thread.cpp b/src/CLR/Core/Thread.cpp new file mode 100644 index 0000000000..425ddcd735 --- /dev/null +++ b/src/CLR/Core/Thread.cpp @@ -0,0 +1,1272 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_SubThread::CreateInstance( CLR_RT_Thread* th, CLR_RT_StackFrame* stack, int priority, CLR_RT_SubThread*& sthRef ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_SubThread* sth = EVENTCACHE_EXTRACT_NODE(g_CLR_RT_EventCache,CLR_RT_SubThread,DATATYPE_SUBTHREAD); CHECK_ALLOCATION(sth); + + sth->m_owningThread = th; // CLR_RT_Thread* m_owningThread; + sth->m_owningStackFrame = stack; // CLR_RT_StackFrame* m_owningStackFrame; + sth->m_lockRequestsCount = 0; // CLR_UINT32 m_lockRequestsCount; + // + sth->m_priority = priority; // int m_priority; + + sth->m_timeConstraint = TIMEOUT_INFINITE; // CLR_INT64 m_timeConstraint; + sth->m_status = 0; // CLR_UINT32 m_status; + + th->m_subThreads.LinkAtBack( sth ); + + TINYCLR_CLEANUP(); + + sthRef = sth; + + TINYCLR_CLEANUP_END(); +} + +void CLR_RT_SubThread::DestroyInstance( CLR_RT_Thread* th, CLR_RT_SubThread* sthBase, int flags ) +{ + NATIVE_PROFILE_CLR_CORE(); + // + // You cannot destroy a subthread without destroying all the children subthreads. + // + while(true) + { + CLR_RT_SubThread* sth = th->CurrentSubThread(); if(sth->Prev() == NULL) break; + + // + // Release all the frames for this subthread. + // + while(true) + { + CLR_RT_StackFrame* stack = th->CurrentFrame(); if(stack->Prev() == NULL) break; + + if(stack == sth->m_owningStackFrame) break; + + stack->Pop(); + } + + // + // Release all the locks for this subthread. + // + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_Lock,lock,th->m_locks) + { + lock->DestroyOwner( sth ); + } + TINYCLR_FOREACH_NODE_END(); + + // + // Release all the lock requests. + // + g_CLR_RT_ExecutionEngine.DeleteLockRequests( NULL, sth ); + + if(sth == sthBase && (flags & CLR_RT_SubThread::MODE_IncludeSelf) == 0) break; + + g_CLR_RT_EventCache.Append_Node( sth ); + + if(sth == sthBase) break; + } +} + +bool CLR_RT_SubThread::ChangeLockRequestCount( int diff ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_Thread* th = m_owningThread; + + this->m_lockRequestsCount += diff; + th ->m_lockRequestsCount += diff; + + if(th->m_lockRequestsCount == 0) + { + th->Restart( false ); + + return true; + } + else + { + th->m_status = CLR_RT_Thread::TH_S_Waiting; + + return false; + } +} + +void CLR_RT_Thread::BringExecCounterToDate( int iGlobalExecutionCounter, int iDebitForEachRun ) + +{ // Normally the condition is false. It becames true if thread was out of execution for some time. + // The value of ThreadPriority::System_Highest + 1) is 33. + // 33 for ThreadPriority::Highest gives up to 16 cycles to catch up. + // 33 for ThreadPriority::Lowest we provide only 1 cycle to catch up. + // If thread was sleeping for some time we forefeet the time it was sleeping and not updating execution counter. + if ( m_executionCounter - iGlobalExecutionCounter > (int)((1 << ThreadPriority::System_Highest) + 1) ) + { + m_executionCounter = iGlobalExecutionCounter + (int)((1 << ThreadPriority::System_Highest) + 1); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +bool CLR_RT_Thread::IsFinalizerThread() +{ + NATIVE_PROFILE_CLR_CORE(); + return g_CLR_RT_ExecutionEngine.m_finalizerThread == this; +} + +bool CLR_RT_Thread::CanThreadBeReused() +{ + NATIVE_PROFILE_CLR_CORE(); + return (m_flags & CLR_RT_Thread::TH_F_System) && + (m_status == CLR_RT_Thread::TH_S_Terminated || m_status == CLR_RT_Thread::TH_S_Unstarted ); +} + +HRESULT CLR_RT_Thread::PushThreadProcDelegate( CLR_RT_HeapBlock_Delegate* pDelegate ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_MethodDef_Instance inst; + +#if defined(TINYCLR_APPDOMAINS) + CLR_RT_AppDomain* appDomainSav = g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( pDelegate->m_appDomain ); +#endif + + if(pDelegate == NULL || pDelegate->DataType() != DATATYPE_DELEGATE_HEAD || inst.InitializeFromIndex( pDelegate->DelegateFtn() ) == false) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + +#if defined(TINYCLR_APPDOMAINS) + + if(!pDelegate->m_appDomain->IsLoaded()) + { + if(!IsFinalizerThread()) + { + TINYCLR_SET_AND_LEAVE(CLR_E_APPDOMAIN_EXITED); + } + + m_flags |= CLR_RT_Thread::TH_F_ContainsDoomedAppDomain; + } +#endif + + this->m_dlg = pDelegate; + this->m_status = TH_S_Ready; + + TINYCLR_CHECK_HRESULT(CLR_RT_StackFrame::Push( this, inst, inst.m_target->numArgs )); + + if((inst.m_target->flags & CLR_RECORD_METHODDEF::MD_Static) == 0) + { + CLR_RT_StackFrame* stackTop = this->CurrentFrame(); + + stackTop->m_arguments[ 0 ].Assign( pDelegate->m_object ); + } + + g_CLR_RT_ExecutionEngine.PutInProperList( this ); + + TINYCLR_CLEANUP(); + +#if defined(TINYCLR_APPDOMAINS) + g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomainSav ); +#endif + + TINYCLR_CLEANUP_END(); +} + +HRESULT CLR_RT_Thread::CreateInstance( int pid, int priority, CLR_RT_Thread*& th, CLR_UINT32 flags ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_SubThread* sth; + + //--// + + th = EVENTCACHE_EXTRACT_NODE(g_CLR_RT_EventCache,CLR_RT_Thread,DATATYPE_THREAD); CHECK_ALLOCATION(th); + + { + CLR_RT_ProtectFromGC gc( (void**)&th, CLR_RT_Thread::ProtectFromGCCallback ); + + th->Initialize(); + + th->m_pid = pid; // int m_pid; + th->m_status = TH_S_Unstarted; // CLR_UINT32 m_status; + th->m_flags = flags; // CLR_UINT32 m_flags; + th->m_executionCounter = 0; // int m_executionCounter; + th->m_timeQuantumExpired = FALSE; // BOOL m_timeQuantumExpired; + // + th->m_dlg = NULL; // CLR_RT_HeapBlock_Delegate* m_dlg; + th->m_currentException .SetObjectReference( NULL ); // CLR_RT_HeapBlock m_currentException; + // UnwindStack m_nestedExceptions[c_MaxStackUnwindDepth]; + th->m_nestedExceptionsPos = 0; // int m_nestedExceptionsPos; + + // + // //--// + // + th->m_terminationCallback = NULL; // ThreadTerminationCallback m_terminationCallback; + th->m_terminationParameter = NULL; // void* m_terminationParameter; + // + th->m_waitForEvents = 0; // CLR_UINT32 m_waitForEvents; + th->m_waitForEvents_Timeout = TIMEOUT_INFINITE; // CLR_INT64 m_waitForEvents_Timeout; + th->m_waitForEvents_IdleTimeWorkItem = TIMEOUT_ZERO; // CLR_INT64 m_waitForEvents_IdleTimeWorkItem; + // + th->m_locks .DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_locks; + th->m_lockRequestsCount = 0; // CLR_UINT32 m_lockRequestsCount; + th->m_waitForObject = NULL; + // + th->m_stackFrames .DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_stackFrames; + // + th->m_subThreads .DblLinkedList_Initialize(); // CLR_RT_DblLinkedList m_subThreads; + // + #if defined(ENABLE_NATIVE_PROFILER) + th->m_fNativeProfiled = false; + #endif + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + th->m_scratchPad = -1; // int m_scratchPad; + th->m_fHasJMCStepper = false; // bool m_fHasJMCStepper + + // For normal threads created in CLR m_realThread points to the thread object. + // If debugger creates managed thread for function evaluation, then m_realThread points to the thread that has focus in debugger + th->m_realThread = th; // CLR_RT_Thread* m_realThread +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + //--// + + TINYCLR_CHECK_HRESULT(CLR_RT_SubThread::CreateInstance( th, NULL, priority, sth )); + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + if(g_CLR_RT_ExecutionEngine.m_breakpointsNum) + { + // + // This needs to happen before the Push + // + g_CLR_RT_ExecutionEngine.Breakpoint_Thread_Created( th ); + } +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_Thread::CreateInstance( int pid, CLR_RT_HeapBlock_Delegate* pDelegate, int priority, CLR_RT_Thread*& th, CLR_UINT32 flags ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_CHECK_HRESULT(CreateInstance( pid, priority, th, flags )); + + if(pDelegate) + { + TINYCLR_CHECK_HRESULT(th->PushThreadProcDelegate( pDelegate )); + } + + TINYCLR_NOCLEANUP(); +} + +void CLR_RT_Thread::DestroyInstance() +{ + NATIVE_PROFILE_CLR_CORE(); + DetachAll(); + + Passivate(); + + //Prevent ReleaseWhenDeadEx from keeping the thread alive + if(m_flags & CLR_RT_Thread::TH_F_System) + { + m_flags &= ~CLR_RT_Thread::TH_F_System; + OnThreadTerminated(); + } + + ReleaseWhenDeadEx(); +} + +bool CLR_RT_Thread::ReleaseWhenDeadEx() +{ + NATIVE_PROFILE_CLR_CORE(); + //maybe separate for shutdown.... + //These threads live forever?!!? + if(m_flags & CLR_RT_Thread::TH_F_System) return false; + + if(!IsReadyForRelease()) return false; + + if(this == g_CLR_RT_ExecutionEngine.m_finalizerThread) g_CLR_RT_ExecutionEngine.m_finalizerThread = NULL; + if(this == g_CLR_RT_ExecutionEngine.m_interruptThread) g_CLR_RT_ExecutionEngine.m_interruptThread = NULL; + if(this == g_CLR_RT_ExecutionEngine.m_timerThread ) g_CLR_RT_ExecutionEngine.m_timerThread = NULL; + if(this == g_CLR_RT_ExecutionEngine.m_cctorThread ) g_CLR_RT_ExecutionEngine.m_cctorThread = NULL; + + return ReleaseWhenDead(); +} + +//--// + +void CLR_RT_Thread::ProtectFromGCCallback( void* state ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_Thread* th = (CLR_RT_Thread*)state; + + g_CLR_RT_GarbageCollector.Thread_Mark( th ); +} + +//--// + +HRESULT CLR_RT_Thread::Suspend() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + if((m_flags & CLR_RT_Thread::TH_F_Suspended) == 0 && m_status != CLR_RT_Thread::TH_S_Terminated) + { + m_flags |= CLR_RT_Thread::TH_F_Suspended; + + g_CLR_RT_ExecutionEngine.PutInProperList( this ); + } + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT CLR_RT_Thread::Resume() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + if((m_flags & CLR_RT_Thread::TH_F_Suspended) != 0 && m_status != CLR_RT_Thread::TH_S_Terminated) + { + m_flags &= ~CLR_RT_Thread::TH_F_Suspended; + + g_CLR_RT_ExecutionEngine.PutInProperList( this ); + } + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT CLR_RT_Thread::Terminate() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + m_status = CLR_RT_Thread::TH_S_Terminated; + + //An exception is needed to ensure that StackFrame::Pop does not copy uninitialized data + //to callers evaluation stacks. This would likely be harmless, as the entire thread is about to be killed + //However, this is simply a safeguard to prevent possible problems if it ever happens that + //between the start and end of killing the thread, a GC gets run. + (void)Library_corlib_native_System_Exception::CreateInstance( m_currentException, g_CLR_RT_WellKnownTypes.m_ThreadAbortException, S_OK, CurrentFrame() ); + + g_CLR_RT_ExecutionEngine.PutInProperList( this ); + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +HRESULT CLR_RT_Thread::Abort() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + // + // Only abort a non-terminated thread... + // + if(m_status != CLR_RT_Thread::TH_S_Terminated) + { + (void)Library_corlib_native_System_Exception::CreateInstance( m_currentException, g_CLR_RT_WellKnownTypes.m_ThreadAbortException, S_OK, CurrentFrame() ); + + m_flags |= CLR_RT_Thread::TH_F_Aborted; + + Restart( true ); + } + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +void CLR_RT_Thread::Restart( bool fDeleteEvent ) +{ + NATIVE_PROFILE_CLR_CORE(); + // + // Wake up and queue. + // + m_status = CLR_RT_Thread::TH_S_Ready; + + g_CLR_RT_ExecutionEngine.PutInProperList( this ); + + if(fDeleteEvent) + { + m_waitForEvents = 0; + m_waitForEvents_Timeout = TIMEOUT_INFINITE; + } +} + +void CLR_RT_Thread::OnThreadTerminated() +{ + NATIVE_PROFILE_CLR_CORE(); + SignalAll(); + + // + // Release all the subthreads. + // + CLR_RT_SubThread::DestroyInstance( this, NULL, 0 ); + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + if(g_CLR_RT_ExecutionEngine.m_breakpointsNum) + { + g_CLR_RT_ExecutionEngine.Breakpoint_Thread_Terminated( this ); + } +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) +} + +void CLR_RT_Thread::Passivate() +{ + NATIVE_PROFILE_CLR_CORE(); + m_flags &= ~(CLR_RT_Thread::TH_F_Suspended | CLR_RT_Thread::TH_F_ContainsDoomedAppDomain | CLR_RT_Thread::TH_F_Aborted); + + g_CLR_RT_ExecutionEngine.m_threadsZombie.LinkAtFront( this ); + + m_waitForEvents = 0; + m_waitForEvents_Timeout = TIMEOUT_INFINITE; + + //--// + + if(m_waitForObject != NULL) + { + g_CLR_RT_EventCache.Append_Node( m_waitForObject ); + m_waitForObject = NULL; + } + + //--// + + if((m_flags & CLR_RT_Thread::TH_F_System) == 0) + { + m_status = CLR_RT_Thread::TH_S_Terminated; + OnThreadTerminated(); + } + else + { + m_status = CLR_RT_Thread::TH_S_Unstarted; + } + + m_currentException.SetObjectReference( NULL ); // Reset exception flag. + + // + // If the thread is associated with a timer, advance the state of the timer. + // + if(m_terminationCallback) + { + ThreadTerminationCallback terminationCallback = m_terminationCallback; m_terminationCallback = NULL; + + terminationCallback( m_terminationParameter ); + } + + if(m_status == CLR_RT_Thread::TH_S_Terminated || m_status == CLR_RT_Thread::TH_S_Unstarted) + { + //This is used by Static constructor thread. + m_dlg = NULL; + } + + ReleaseWhenDeadEx(); +} + +bool CLR_RT_Thread::CouldBeActivated() +{ + NATIVE_PROFILE_CLR_CORE(); + if(m_waitForEvents_Timeout != TIMEOUT_INFINITE) return true; + if(m_waitForEvents ) return true; + + return false; +} + +void CLR_RT_Thread::RecoverFromGC() +{ + NATIVE_PROFILE_CLR_CORE(); + CheckAll(); +} + +void CLR_RT_Thread::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_dlg ); + + m_currentException.Relocate__HeapBlock(); + + for(int i=0; im_call ); CLR_Debug::Printf( " [IP: %04x]\r\n", (stack->m_IP - stack->m_IPstart) ); + } + TINYCLR_FOREACH_NODE_BACKWARD_END(); +} + +#endif + +//--// + +void CLR_RT_Thread::ProcessException_FilterPseudoFrameCopyVars(CLR_RT_StackFrame* to, CLR_RT_StackFrame* from) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_UINT8 numArgs = from->m_call.m_target->numArgs; + + if(numArgs) + { + memcpy( to->m_arguments, from->m_arguments, sizeof(CLR_RT_HeapBlock) * numArgs ); + } + + if(from->m_call.m_target->numLocals) + { + memcpy( to->m_locals, from->m_locals, sizeof(CLR_RT_HeapBlock) * from->m_call.m_target->numLocals ); + } +} + +HRESULT CLR_RT_Thread::ProcessException_EndFilter() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_StackFrame* stack = CurrentFrame(); + CLR_INT32 choice = stack->PopValue().NumericByRef().s4; + + + UnwindStack& us = m_nestedExceptions[ m_nestedExceptionsPos - 1 ]; + + ProcessException_FilterPseudoFrameCopyVars(us.m_handlerStack, stack); + + //Clear the stack variable so Pop doesn't remove us from the UnwindStack. + us.m_stack = NULL; + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + //We don't want to send any breakpoints until after we set the IP appropriately + bool fBreakpointsDisabledSav = CLR_EE_DBG_IS(BreakpointsDisabled); + CLR_EE_DBG_SET(BreakpointsDisabled); +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + stack->Pop(); + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + if(!fBreakpointsDisabledSav) + { + CLR_EE_DBG_CLR(BreakpointsDisabled); + } +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + if(choice == 1) + { + //The filter signaled that it will handle this exception. Update the phase state + us.SetPhase(UnwindStack::p_2_RunningFinallys_0); +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + g_CLR_RT_ExecutionEngine.Breakpoint_Exception(us.m_handlerStack, CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_DEPTH_EXCEPTION_HANDLER_FOUND, us.m_handlerBlockStart); +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + } + else + { + //Store the IP so Phase1/FindEhBlock knows to start looking from the point of the filter we were executing. + us.m_ip = us.m_currentBlockStart; + } + + //Signal that this is a continuation of processing for the handler on top of the unwind stack. + us.m_flags |= UnwindStack::c_ContinueExceptionHandler; + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + //We must stop if we sent out a Catch Handler found message. + if(CLR_EE_DBG_IS( Stopped )) + { //If the debugger stopped because of the messages we sent, then we should break out of Execute_IL, drop down, + //and wait for the debugger to continue. + m_currentException.SetObjectReference(us.m_exception); + TINYCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + } +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + (void)ProcessException(); + + + // Swap results around. ProcessException must return a success code in Thread::Execute and set m_currentException to continue processing. + // Execute_IL must get a FAILED hr in order to break outside of the execution loop. + if(m_currentException.Dereference() == NULL) + { + //Return S_OK because exception handling is complete or handling is in-flight and needs to execute IL to continue. + TINYCLR_SET_AND_LEAVE(S_OK); + } + else + { + //Return PROCESS_EXCEPTION to break out of the IL loop to rerun ProcessException and/or abort from an unhandled exception + TINYCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_Thread::ProcessException_EndFinally() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_StackFrame* stack = CurrentFrame(); + UnwindStack& us = m_nestedExceptions[ m_nestedExceptionsPos - 1 ]; + + if(us.m_ip) + { + CLR_PMETADATA ipLeave = us.m_ip; + CLR_RT_ExceptionHandler eh; + + if(FindEhBlock( stack, stack->m_IP-1, ipLeave, eh, true )) + { + us.m_stack = stack; + us.m_exception = NULL; + us.m_ip = ipLeave; + us.m_currentBlockStart = eh.m_handlerStart; + us.m_currentBlockEnd = eh.m_handlerEnd; + //Leave is not valid to leave a finally block, and is the only thing that leaves m_ip set when executing IL. + //Therefore if we're here then we are not interfering with an unhandled exception and flags can be safely set. + us.SetPhase( UnwindStack::p_4_NormalCleanup ); + stack->m_IP = eh.m_handlerStart ; + } + else + { //We're truely done with finally's for now. Pop off the handler + m_nestedExceptionsPos--; + stack->m_IP = ipLeave; + } + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + if(stack->m_flags & CLR_RT_StackFrame::c_HasBreakpoint) + { + g_CLR_RT_ExecutionEngine.Breakpoint_StackFrame_Step( stack, stack->m_IP ); + } +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + TINYCLR_SET_AND_LEAVE(S_OK); + } + else if(us.m_exception) + { + //This finally block was executed because an exception was thrown inside its protected block. + //Signal that this is a continuation of an already existing EH process. + us.m_flags |= UnwindStack::c_ContinueExceptionHandler; + + (void)ProcessException(); + //Similar to EndFilter, we need to swap the return codes around. Thread::Execute needs a success code or the thread will be aborted. + //ExecuteIL needs a failure code or we'll continue to execute IL when we possibly shouldn't. + if (m_currentException.Dereference() == NULL) + { + //Return S_OK because exception handling is complete or handling is in-flight and needs to execute IL to continue. + TINYCLR_SET_AND_LEAVE(S_OK); + } + else + { + //Return PROCESS_EXCEPTION to break out of the IL loop to rerun ProcessException and/or abort from an unhandled exception + TINYCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + } + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_Thread::ProcessException_Phase1() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + // Load the UnwindStack entry to process, as created/loaded by ProcessException + UnwindStack& us = m_nestedExceptions[ m_nestedExceptionsPos - 1 ]; + + CLR_RT_ExceptionHandler eh; + + // If we were executing a filter that returned false, there's not much point checking the stack frames above the point of the filter. + // Try to resume from the frame of the last filter executed. + CLR_RT_StackFrame* stack = us.m_handlerStack; + +#ifndef TINYCLR_NO_IL_INLINE + CLR_RT_InlineFrame tmpInline; + tmpInline.m_IP = NULL; +#endif + + // If this is the first pass through _Phase1 then start at the top. + if(!stack) { stack = CurrentFrame(); } + + //Search for a willing catch handler. + while(stack->Caller() != NULL) + { +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + if(g_CLR_RT_ExecutionEngine.m_breakpointsNum && us.GetPhase() < UnwindStack::p_1_SearchingForHandler_2_SentUsersChance && stack->m_IP) + { //We have a debugger attached and we need to send some messages before we start searching. + //These messages should only get sent when the search reaches managed code. Stack::Push sets m_IP to NULL for native code, + //so therefore we need IP to be non-NULL + + us.m_handlerStack = stack; + + if(us.GetPhase() < UnwindStack::p_1_SearchingForHandler_1_SentFirstChance) + { + g_CLR_RT_ExecutionEngine.Breakpoint_Exception( stack, CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_DEPTH_EXCEPTION_FIRST_CHANCE, NULL ); + us.SetPhase(UnwindStack::p_1_SearchingForHandler_1_SentFirstChance); + + //Break out here, because of synchronization issues (false positives) with JMC checking. + if(CLR_EE_DBG_IS( Stopped )) { goto ContinueAndExit; } + } + + //In order to send the User's first chance message, we have to know that we're in JMC + //Do we have thread synchronization issues here? The debugger is sending out 3 Not My Code messages for a function, + //presumably the one on the top of the stack, but when we execute this, we're reading true. + if(stack->m_call.DebuggingInfo().IsJMC()) + { + g_CLR_RT_ExecutionEngine.Breakpoint_Exception( stack, CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_DEPTH_EXCEPTION_USERS_CHANCE, NULL ); + us.SetPhase( UnwindStack::p_1_SearchingForHandler_2_SentUsersChance ); + if(CLR_EE_DBG_IS(Stopped)) { goto ContinueAndExit; } + } + } +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + if(stack->m_call.m_target->flags & CLR_RECORD_METHODDEF::MD_HasExceptionHandlers) + { + CLR_PMETADATA ip; + if (us.m_ip) + { + ip = us.m_ip; //Use the IP set by endfilter + us.m_ip = NULL; //Reset to prevent catch block & PopEH issues via 'leave' or 'endfinally' + } + else + { + ip = stack->m_IP; //Normal case: use the IP where the exception was thrown. + } + + if(ip) // No IP? Either out of memory during allocation of stack frame or native method. + { + if(FindEhBlock( stack, ip, NULL, eh, false )) + { //There are two cases here: + //1. We found a catch block... in this case, we want to break out and go to phase 2. + //2. We found a filter... in this case, we want to duplicate the stack and execute the filter. + + //Store the handler block address and stack frame. + //It's needed in Phase2 for when finally's are finished and we execute the catch handler + us.m_handlerBlockStart = eh.m_handlerStart; + us.m_handlerBlockEnd = eh.m_handlerEnd; + us.m_handlerStack = stack; + +#ifndef TINYCLR_NO_IL_INLINE + if(tmpInline.m_IP) + { + us.m_flags |= UnwindStack::c_MagicCatchForInline; + } +#endif + + if (eh.IsFilter()) + { + CLR_RT_StackFrame* newStack = NULL; + + //Store the IP range that we're currently executing so leave/PopEH doesn't accidentally pop the filter off. + us.m_currentBlockStart = eh.m_userFilterStart; + us.m_currentBlockEnd = eh.m_handlerStart; + + //Create a pseudo-frame at the top of the stack so the filter can call other functions. + CLR_UINT8 numArgs = stack->m_call.m_target->numArgs; + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + //We don't want to send any breakpoints until after we set the IP appropriately + bool fBreakpointsDisabledSav = CLR_EE_DBG_IS(BreakpointsDisabled); + CLR_EE_DBG_SET(BreakpointsDisabled); +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + hr = CLR_RT_StackFrame::Push( stack->m_owningThread, stack->m_call, numArgs ); + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + if(!fBreakpointsDisabledSav) + { + CLR_EE_DBG_CLR(BreakpointsDisabled); + } +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + if(FAILED(hr)) + { //We probably ran out of memory. In either case, don't run this handler. + //Set the IP so we'll try the next catch block. + us.m_ip = us.m_currentBlockStart; + continue; + } + + //stack is the original filter stack frame; newStack is the new pseudoframe + newStack = CurrentFrame(); + newStack->m_flags |= CLR_RT_StackFrame::c_PseudoStackFrameForFilter; + us.m_stack = newStack; + + //Copy local variables and arguments so the filter has access to them. + if(numArgs) + { + memcpy( newStack->m_arguments, stack->m_arguments, sizeof(CLR_RT_HeapBlock) * numArgs ); + } + + if (stack->m_call.m_target->numLocals) + { + memcpy( newStack->m_locals, stack->m_locals, sizeof(CLR_RT_HeapBlock) * stack->m_call.m_target->numLocals ); + } + + newStack->PushValueAndAssign( m_currentException ); + + //Set the ip to the handler + newStack->m_IP = eh.m_userFilterStart; + + //We are willing to execute IL again so clear the m_currentException flag. + m_currentException.SetObjectReference( NULL ); + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + g_CLR_RT_ExecutionEngine.Breakpoint_StackFrame_Push( newStack, CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_DEPTH_STEP_INTERCEPT ); +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + //Return a success value to break out of ProcessException and to signal that execution of IL can continue. + TINYCLR_SET_AND_LEAVE(S_OK); + } + else + { //We found a normal Catch or CatchAll block. We are all set to proceed onto the Unwinding phase. + //Note that we found a catch handler so we don't look for it again for this exception. + us.SetPhase( UnwindStack::p_2_RunningFinallys_0 ); + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + if(g_CLR_RT_ExecutionEngine.m_breakpointsNum) + { + g_CLR_RT_ExecutionEngine.Breakpoint_Exception( stack, CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_DEPTH_EXCEPTION_HANDLER_FOUND, eh.m_handlerStart ); + if(CLR_EE_DBG_IS(Stopped)) { goto ContinueAndExit; } + } +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + //We want to continue running EH "goo" code so leave m_currentException set and return PROCESS_EXCEPTION + TINYCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + } + } + } + } + + //We didn't find a catch block at this level... + //Check to see if we trickled up to a pseudoStack frame that we created to execute a handler + //Both of these shouldn't be set at once because of the two-pass handling mechanism. + if (stack->m_flags & CLR_RT_StackFrame::c_AppDomainTransition) + { + us.m_handlerStack = NULL; + us.SetPhase(UnwindStack::p_2_RunningFinallys_0); + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + if(g_CLR_RT_ExecutionEngine.m_breakpointsNum) + { + //Send the IP offset -1 for a catch handler in the case of an appdomain transition to mimic the desktop. + g_CLR_RT_ExecutionEngine.Breakpoint_Exception( stack, CLR_DBG_Commands::Debugging_Execution_BreakpointDef::c_DEPTH_EXCEPTION_HANDLER_FOUND, stack->m_IPstart - 1 ); + if(CLR_EE_DBG_IS(Stopped)) { goto ContinueAndExit; } + } +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + TINYCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + } + if (stack->m_flags & CLR_RT_StackFrame::c_PseudoStackFrameForFilter) + { + us.m_handlerStack = NULL; + us.SetPhase( UnwindStack::p_2_RunningFinallys_0 ); + TINYCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + } + +#ifndef TINYCLR_NO_IL_INLINE + if(stack->m_inlineFrame != NULL && tmpInline.m_IP == NULL) + { + stack->SaveStack(tmpInline); + stack->RestoreFromInlineStack(); + } + else + { + if(tmpInline.m_IP) + { + stack->RestoreStack(tmpInline); + tmpInline.m_IP = NULL; + } +#else + { +#endif + + stack = stack->Caller(); + } + } + + us.m_handlerStack = NULL; + us.SetPhase(UnwindStack::p_2_RunningFinallys_0); + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + if(g_CLR_RT_ExecutionEngine.m_breakpointsNum) + { + g_CLR_RT_ExecutionEngine.Breakpoint_Exception_Uncaught( this ); + if(CLR_EE_DBG_IS(Stopped)) { goto ContinueAndExit; } + } +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + //We want to continue running EH "goo" code so leave m_currentException set and return PROCESS_EXCEPTION + TINYCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) +ContinueAndExit: +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + //There are multiple cases where we want to break out of this function, send debug messages, and then resume exactly where we were. + //All of those cases jump to here. + //However, there are cases where we may be stopped but we don't want to set this flag (i.e. pushing on a filter and completing a stepper) + //where we do not want to set this flag, so it cannot be in TinyCLR_Cleanup. + us.m_flags |= UnwindStack::c_ContinueExceptionHandler; + TINYCLR_SET_AND_LEAVE(S_OK); + + TINYCLR_CLEANUP(); + +#ifndef TINYCLR_NO_IL_INLINE + if(tmpInline.m_IP) + { + stack->RestoreStack(tmpInline); + } +#endif + + TINYCLR_CLEANUP_END(); +} + +HRESULT CLR_RT_Thread::ProcessException_Phase2() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + /* + * Start running through the stack frames, running all finally handlers and popping them off until + * we hit our target catch handler, if any. + */ + + UnwindStack& us = m_nestedExceptions[ m_nestedExceptionsPos - 1 ]; + + CLR_RT_StackFrame* iterStack = CurrentFrame(); + + CLR_RT_ExceptionHandler eh; + + //Unwind the stack, running finally's as we go + while (iterStack->Caller() != NULL) + { +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + if (g_CLR_RT_ExecutionEngine.m_breakpointsNum && iterStack == us.m_handlerStack && (us.m_flags & UnwindStack::c_MagicCatchForInteceptedException) != 0) + { + //We've reached the frame we want to "handle" this exception. However, since the handler doesn't really exist, we want to remove the UnwindStack entry. + m_nestedExceptionsPos--; + iterStack->ResetStack(); + + //We are willing to execute IL again so clear the m_currentException flag. + m_currentException.SetObjectReference( NULL ); + + //CPDE better reset the IP, or there are going to be issues. + iterStack->m_flags |= CLR_RT_StackFrame::c_InvalidIP; + + //Send the message to the debugger. + g_CLR_RT_ExecutionEngine.Breakpoint_Exception_Intercepted( iterStack ); + + //Return a success value to break out of ProcessException and to signal that execution of IL can continue. + TINYCLR_SET_AND_LEAVE(S_OK); + } + else +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + if(iterStack->m_call.m_target->flags & CLR_RECORD_METHODDEF::MD_HasExceptionHandlers) + { + if(iterStack->m_IP) // No IP? Either out of memory during allocation of iterStack frame or native method. + { + //handlerBlockStart is used to not execute finally's who's protected blocks contain the handler itself. + //NULL is used when we're not in the handler stack frame to make it work in the case of recursive functions with filtered handlers. + if(FindEhBlock( iterStack, iterStack->m_IP, (us.m_handlerStack == iterStack)? us.m_handlerBlockStart : NULL, eh, true )) + { + //We have a finally block to process + + us.m_stack = iterStack; + us.m_ip = NULL; + us.m_currentBlockStart = eh.m_handlerStart; + us.m_currentBlockEnd = eh.m_handlerEnd; + us.SetPhase(UnwindStack::p_2_RunningFinallys_0); + + m_currentException.SetObjectReference( NULL ); // Reset exception flag. + + iterStack->ResetStack(); + iterStack->m_IP = eh.m_handlerStart; + iterStack->m_flags &= ~CLR_RT_StackFrame::c_InvalidIP; + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) +#ifndef TINYCLR_NO_IL_INLINE + if(iterStack->m_inlineFrame == NULL) +#endif + { + g_CLR_RT_ExecutionEngine.Breakpoint_StackFrame_Pop( iterStack, true ); + } +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + TINYCLR_SET_AND_LEAVE(S_OK); + } + + if (iterStack == us.m_handlerStack) + { +#ifndef TINYCLR_NO_IL_INLINE + if(iterStack->m_inlineFrame == NULL || 0 == (us.m_flags & UnwindStack::c_MagicCatchForInline)) +#endif + { + //We've popped off all stack frames above the target. + //Now we should run the exception handler. + + //Store the range of the block and the stack frame we're executing for PopEH + us.m_currentBlockStart = us.m_handlerBlockStart; + us.m_currentBlockEnd = us.m_handlerBlockEnd; + us.m_stack = us.m_handlerStack; + us.SetPhase( UnwindStack::p_3_RunningHandler ); + + //Set the IP and push the exception object on the stack. + iterStack->m_IP = us.m_handlerBlockStart; + iterStack->m_flags &= ~CLR_RT_StackFrame::c_InvalidIP; + + iterStack->ResetStack(); + iterStack->PushValue().SetObjectReference( us.m_exception ); + + //We are willing to execute IL again so clear the m_currentException flag. + m_currentException.SetObjectReference( NULL ); + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) +#ifndef TINYCLR_NO_IL_INLINE + if(iterStack->m_inlineFrame == NULL) +#endif + { + g_CLR_RT_ExecutionEngine.Breakpoint_StackFrame_Pop( iterStack, true ); + } +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + //Return a success value to break out of ProcessException and to signal that execution of IL can continue. + TINYCLR_SET_AND_LEAVE(S_OK); + } + } + } + } + + //We didn't find a finally block at this level... + //Check to see if we trickled up to a pseudoiterStack frame that we created to execute a filter handler: + if (iterStack->m_flags & CLR_RT_StackFrame::c_PseudoStackFrameForFilter) + { + //An exception was thrown while executing a filter block. + //The CLR should swallow the current exception, perform some filter-cleanup, act as if the filter returned false and + //continue looking for a handler for the old exception + m_nestedExceptionsPos--; + + UnwindStack& us = m_nestedExceptions[ m_nestedExceptionsPos - 1 ]; + + //Since there are no applicable handlers for this IP inside this filter block, and all finally's nested below the + //filter have executed, we should pop off our pseudoframe and try to find another catch block. + + //Copy the arguments and locals back to the original stack frame. + ProcessException_FilterPseudoFrameCopyVars( us.m_handlerStack, iterStack ); + + //Set IP so we can resume looking for the next filter. + us.m_ip = us.m_currentBlockStart; + + us.m_stack = NULL; //Prevent Pop from taking this handler off the stack. + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + //We don't want to send any breakpoints until after we set the IP appropriately + bool fBreakpointsDisabledSav = CLR_EE_DBG_IS(BreakpointsDisabled); + CLR_EE_DBG_SET(BreakpointsDisabled); +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + iterStack->Pop(); //No finally's for the current ip in this method, pop to the next. + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + if(!fBreakpointsDisabledSav) + { + CLR_EE_DBG_CLR(BreakpointsDisabled); + } +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + m_currentException.SetObjectReference( us.m_exception ); //Drop current exception, use old one. + + //Set the continue flag, and leave with S_OK to loop around and get Phase1 called again via ProcessException + us.m_flags |= UnwindStack::c_ContinueExceptionHandler; + + //We are not ready to execute IL yet so do NOT clear m_currentException flag. + //There still remains hope for this thread so return S_OK so ProcessException can get called again via Thread::Execute + TINYCLR_SET_AND_LEAVE(S_OK); + } + +#if defined(TINYCLR_APPDOMAINS) + if(iterStack->m_flags & CLR_RT_StackFrame::c_AppDomainTransition) + { + //If we hit an AppDomain transition and haven't handled the exception, then a special case occurs. + //Exception handling stops at this point and the whole process needs to start over in the caller's AppDomain. + //We need to pop the handler off the unwind stack, pop the current stack frame, and then proceed to Phase1. + m_nestedExceptionsPos--; //Take off the pseudo-handler + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + bool fBreakpointsDisabledSav = CLR_EE_DBG_IS(BreakpointsDisabled); + CLR_EE_DBG_SET(BreakpointsDisabled); +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + +#ifndef TINYCLR_NO_IL_INLINE + if(iterStack->m_inlineFrame) + { + iterStack->PopInline(); + } + else +#endif + { + iterStack->Pop(); //No finally's for the current ip in this method, pop to the next. + } + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + if(!fBreakpointsDisabledSav) + { + CLR_EE_DBG_CLR(BreakpointsDisabled); + } +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + //We are not ready to execute IL yet so do NOT clear m_currentException flag. + //There still remains hope for this thread so return S_OK so ProcessException can get called again via Thread::Execute + TINYCLR_SET_AND_LEAVE(S_OK); + } +#endif + + us.m_stack = NULL; //Don't pop off the handler when we pop this stack frame + + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + //We don't want to send any breakpoints until after we set the IP appropriately + bool fBreakpointsDisabledSav = CLR_EE_DBG_IS(BreakpointsDisabled); + CLR_EE_DBG_SET(BreakpointsDisabled); +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + +#ifndef TINYCLR_NO_IL_INLINE + if(iterStack->m_inlineFrame) + { + iterStack->PopInline(); + } + else +#endif + { + iterStack->Pop(); //No finally's for the current ip in this method, pop to the next. + } + iterStack = CurrentFrame(); + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + if(!fBreakpointsDisabledSav) + { + CLR_EE_DBG_CLR(BreakpointsDisabled); + } +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + } + + //If we reached this point, we've unwound the entire thread and have an unhandled exception. + m_nestedExceptionsPos = 0; //We have an unhandled exception, we might as well clean the unwind stack. + + //At this point, no hope remains. + //m_currentException is still set, but we return PROCESS_EXCEPTION signalling that there is no hope for the thread, + //which causes Thread::Execute to terminate it. +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) +#if !defined(BUILD_RTM) + //special case thread abort exception + if((this->m_flags & CLR_RT_Thread::TH_F_Aborted) == 0) + { + CLR_Debug::Printf(" Uncaught exception \r\n" ); + //Perhaps some stronger notification is needed. Consider CLR 2.0's fail-fast work + //We could kill the application, and perhaps even store relevant data to dump to the user + //when they connect to the PC. Save the state so the debug API for the uncaught exception could be + //retrieved? + } +#endif //!BUILD_RTM +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + TINYCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION); + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_Thread::ProcessException() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + CLR_RT_StackFrame* stack = CurrentFrame(); + UnwindStack* us = NULL; + + // If the exception was thrown in the middle of an IL instruction, + // back up the pointer to point to the executing instruction, not the next one. + // Not an assert because the exception can be thrown by a native method. + if(stack->m_flags & CLR_RT_StackFrame::c_ExecutingIL) + { + stack->m_IP--; + stack->m_flags &= ~CLR_RT_StackFrame::c_ExecutingIL; + stack->m_flags |= CLR_RT_StackFrame::c_InvalidIP; + } + + // If we are supposed to continue with the old exception handler, then pull the state from it rather than create a new exception. + if (m_nestedExceptionsPos) + { + us = &m_nestedExceptions[ m_nestedExceptionsPos - 1 ]; + if (us->m_flags & UnwindStack::c_ContinueExceptionHandler) + { + //Reset the flag so we don't get false positives from new exceptions + us->m_flags &= ~UnwindStack::c_ContinueExceptionHandler; + m_currentException.SetObjectReference( us->m_exception ); + } + else + { + //Signal that we need a new handler pushed on the stack. + us = NULL; + } + } + + if (us == NULL) + { + //Push a new handler on the unwind stack that will last until its handler gets executed or + //something out-of-band forces the stack frame to get popped. + us = PushEH(); + + //decent failure case is currently not implemented + //a. Clearing the unwind stack and throwing a new exception is just asking for undefined behavior if this exception is caught + //and the IP in stack frames somewhere below are in a finally due to an exception that hasn't yet ran a catch block and + //endfinally gets executed. Execution would continue, thinking that nothing was wrong... a guranteed way to create hard-to-find bugs. + + //b. We could treat it as an unhandled exception, which would terminate the thread. It would be annoying, but it wouldn't lead to + //unexpected code execution leading to potentially more exceptions. + + //c. We could forcibly pop stack frames until there is room on the unwind stack and then throw a stack overflow exception. + //It gives a program a chance to recover, especially for 'always-on' type devices that are inconvenient for the user to perform a cold-boot. + //At any restartable point in the program, there could be a try { } catch-all { } block inside a loop, causing the app to immediately restart + //after an error that would normally terminate the thread. + + //A similar setup would be needed for leave, involving goto Execute_Restart to compensate for possible stack frame changes. Perhaps it could be + //implemented directly in PushEh to reduce common code. + + us->m_exception = m_currentException.Dereference(); + us->m_stack = stack; + us->m_flags = UnwindStack::p_1_SearchingForHandler_0; + } + + if (us->GetPhase() <= UnwindStack::p_1_SearchingForHandler_2_SentUsersChance) + { + TINYCLR_EXIT_ON_SUCCESS(ProcessException_Phase1()); // Leave if we're executing a filter. + } + + TINYCLR_SET_AND_LEAVE(ProcessException_Phase2()); //Leave if we're executing a finally or the catch block, or have an unhandled exception + + TINYCLR_NOCLEANUP(); +} diff --git a/src/CLR/Core/TypeSystem.cpp b/src/CLR/Core/TypeSystem.cpp new file mode 100644 index 0000000000..394546df00 --- /dev/null +++ b/src/CLR/Core/TypeSystem.cpp @@ -0,0 +1,4443 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" +#include "corhdr_private.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#define ITERATE_THROUGH_RECORDS(assm,i,tblName,tblNameUC) \ + const CLR_RECORD_##tblNameUC* src = (const CLR_RECORD_##tblNameUC*)assm->GetTable( TBL_##tblName );\ + CLR_RT_##tblName##_CrossReference* dst = assm->m_pCrossReference_##tblName;\ + for(i=0; im_pTablesSize[TBL_##tblName]; i++, src++, dst++) + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(_WIN32) +#define TINYCLR_TRACE_DEFAULT(win,arm) (win) +#else +#define TINYCLR_TRACE_DEFAULT(win,arm) (arm) +#endif + +#if defined(TINYCLR_TRACE_ERRORS) +int s_CLR_RT_fTrace_Errors = TINYCLR_TRACE_DEFAULT(c_CLR_RT_Trace_Info,c_CLR_RT_Trace_Info); +#endif + +#if defined(TINYCLR_TRACE_EXCEPTIONS) +int s_CLR_RT_fTrace_Exceptions = TINYCLR_TRACE_DEFAULT(c_CLR_RT_Trace_Info,c_CLR_RT_Trace_Info); +#endif + +#if defined(TINYCLR_TRACE_INSTRUCTIONS) +int s_CLR_RT_fTrace_Instructions = TINYCLR_TRACE_DEFAULT(c_CLR_RT_Trace_None,c_CLR_RT_Trace_None); +#endif + +#if defined(TINYCLR_GC_VERBOSE) +int s_CLR_RT_fTrace_Memory = TINYCLR_TRACE_DEFAULT(c_CLR_RT_Trace_None,c_CLR_RT_Trace_None); +#endif + +#if defined(TINYCLR_TRACE_MEMORY_STATS) +int s_CLR_RT_fTrace_MemoryStats = TINYCLR_TRACE_DEFAULT(c_CLR_RT_Trace_Info,c_CLR_RT_Trace_Info); +#endif + +#if defined(TINYCLR_GC_VERBOSE) +int s_CLR_RT_fTrace_GC = TINYCLR_TRACE_DEFAULT(c_CLR_RT_Trace_None,c_CLR_RT_Trace_None); +#endif + +#if defined(WIN32) +int s_CLR_RT_fTrace_SimulateSpeed = TINYCLR_TRACE_DEFAULT(c_CLR_RT_Trace_Info,c_CLR_RT_Trace_None); +#endif + +#if !defined(BUILD_RTM) +int s_CLR_RT_fTrace_AssemblyOverhead = TINYCLR_TRACE_DEFAULT(c_CLR_RT_Trace_Info,c_CLR_RT_Trace_None); +#endif + +#if defined(WIN32) +int s_CLR_RT_fTrace_StopOnFAILED = TINYCLR_TRACE_DEFAULT(c_CLR_RT_Trace_None,c_CLR_RT_Trace_None); +#endif + +#if defined(WIN32) +int s_CLR_RT_fTrace_ARM_Execution = 0; + +int s_CLR_RT_fTrace_RedirectLinesPerFile; +std::wstring s_CLR_RT_fTrace_RedirectOutput; +std::wstring s_CLR_RT_fTrace_RedirectCallChain; + +std::wstring s_CLR_RT_fTrace_HeapDump_FilePrefix; +bool s_CLR_RT_fTrace_HeapDump_IncludeCreators = false; + +bool s_CLR_RT_fTimeWarp = false; +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_ReflectionDef_Index::Clear() +{ + NATIVE_PROFILE_CLR_CORE(); + m_kind = REFLECTION_INVALID; + m_levels = 0; + m_data.m_raw = 0; +} + +CLR_UINT32 CLR_RT_ReflectionDef_Index::GetTypeHash() const +{ + NATIVE_PROFILE_CLR_CORE(); + switch(m_kind) + { + case REFLECTION_TYPE: + { + CLR_RT_TypeDef_Instance inst; + + if(m_levels != 0) return 0; + + if(!inst.InitializeFromIndex( m_data.m_type )) return 0; + + return inst.CrossReference().m_hash; + } + + case REFLECTION_TYPE_DELAYED: + return m_data.m_raw; + } + + return 0; +} + +void CLR_RT_ReflectionDef_Index::InitializeFromHash( CLR_UINT32 hash ) +{ + NATIVE_PROFILE_CLR_CORE(); + m_kind = REFLECTION_TYPE_DELAYED; + m_levels = 0; + m_data.m_raw = hash; +} + +CLR_UINT64 CLR_RT_ReflectionDef_Index::GetRawData() const +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_UINT64 data; + _ASSERTE(sizeof(data) == sizeof(*this)); + + memcpy( &data, this, sizeof(data) ); + + return data; +} + +void CLR_RT_ReflectionDef_Index::SetRawData( CLR_UINT64 data ) +{ + NATIVE_PROFILE_CLR_CORE(); + _ASSERTE(sizeof(data) == sizeof(*this)); + + memcpy( this, &data, sizeof(data) ); +} + +bool CLR_RT_ReflectionDef_Index::Convert( CLR_RT_HeapBlock& ref, CLR_RT_Assembly_Instance& inst ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(ref.DataType() == DATATYPE_REFLECTION) + { + return inst.InitializeFromIndex( ref.ReflectionDataConst().m_data.m_assm ); + } + + return false; +} + +bool CLR_RT_ReflectionDef_Index::Convert( CLR_RT_HeapBlock& ref, CLR_RT_TypeDef_Instance& inst, CLR_UINT32* levels ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(ref.DataType() == DATATYPE_REFLECTION) + { + return inst.InitializeFromReflection( ref.ReflectionDataConst(), levels ); + } + + return false; +} + +bool CLR_RT_ReflectionDef_Index::Convert( CLR_RT_HeapBlock& ref, CLR_RT_MethodDef_Instance& inst ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(ref.DataType() == DATATYPE_REFLECTION) + { + switch(ref.ReflectionData().m_kind) + { + case REFLECTION_CONSTRUCTOR: + case REFLECTION_METHOD: + return inst.InitializeFromIndex( ref.ReflectionDataConst().m_data.m_method ); + } + } + + return false; +} + +bool CLR_RT_ReflectionDef_Index::Convert( CLR_RT_HeapBlock& ref, CLR_RT_FieldDef_Instance& inst ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(ref.DataType() == DATATYPE_REFLECTION && ref.ReflectionData().m_kind == REFLECTION_FIELD) + { + return inst.InitializeFromIndex( ref.ReflectionDataConst().m_data.m_field ); + } + + return false; +} + +bool CLR_RT_ReflectionDef_Index::Convert( CLR_RT_HeapBlock& ref, CLR_UINT32& hash ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(ref.DataType() != DATATYPE_REFLECTION) return false; + + hash = ref.ReflectionData().GetTypeHash(); + + return hash != 0; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_SignatureParser::Initialize_TypeSpec( CLR_RT_Assembly* assm, const CLR_RECORD_TYPESPEC* ts ) +{ + NATIVE_PROFILE_CLR_CORE(); + Initialize_TypeSpec( assm, assm->GetSignature( ts->sig ) ); +} + +void CLR_RT_SignatureParser::Initialize_TypeSpec( CLR_RT_Assembly* assm, CLR_PMETADATA ts ) +{ + NATIVE_PROFILE_CLR_CORE(); + m_assm = assm; + m_sig = ts; + + m_type = CLR_RT_SignatureParser::c_TypeSpec; + m_flags = 0; + m_count = 1; +} + +//--// + +void CLR_RT_SignatureParser::Initialize_Interfaces( CLR_RT_Assembly* assm, const CLR_RECORD_TYPEDEF* td ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(td->interfaces != CLR_EmptyIndex) + { + CLR_PMETADATA sig = assm->GetSignature( td->interfaces ); + + m_count = (*sig++); + m_sig = sig; + } + else + { + m_count = 0; + m_sig = NULL; + } + + m_type = CLR_RT_SignatureParser::c_Interfaces; + m_flags = 0; + + m_assm = assm; +} + +//--// + +void CLR_RT_SignatureParser::Initialize_FieldDef( CLR_RT_Assembly* assm, const CLR_RECORD_FIELDDEF* fd ) +{ + NATIVE_PROFILE_CLR_CORE(); + Initialize_FieldDef( assm, assm->GetSignature( fd->sig ) ); +} + +void CLR_RT_SignatureParser::Initialize_FieldDef( CLR_RT_Assembly* assm, CLR_PMETADATA fd ) +{ + NATIVE_PROFILE_CLR_CORE(); + m_type = CLR_RT_SignatureParser::c_Field; + m_flags = (*fd++); + m_count = 1; + + m_assm = assm; + m_sig = fd; +} + +//--// + +void CLR_RT_SignatureParser::Initialize_MethodSignature( CLR_RT_Assembly* assm, const CLR_RECORD_METHODDEF* md ) +{ + NATIVE_PROFILE_CLR_CORE(); + Initialize_MethodSignature( assm, assm->GetSignature( md->sig ) ); +} + +void CLR_RT_SignatureParser::Initialize_MethodSignature( CLR_RT_Assembly* assm, CLR_PMETADATA md ) +{ + NATIVE_PROFILE_CLR_CORE(); + m_type = CLR_RT_SignatureParser::c_Method; + m_flags = (*md++); + m_count = (*md++) + 1; + + m_assm = assm; + m_sig = md; +} + +//--// + +void CLR_RT_SignatureParser::Initialize_MethodLocals( CLR_RT_Assembly* assm, const CLR_RECORD_METHODDEF* md ) +{ + NATIVE_PROFILE_CLR_CORE(); + // + // WARNING!!! + // + // If you change this method, change "CLR_RT_ExecutionEngine::InitializeLocals" too. + // + + m_assm = assm; + m_sig = assm->GetSignature( md->locals ); + + m_type = CLR_RT_SignatureParser::c_Locals; + m_flags = 0; + m_count = md->numLocals; +} + +//--// + +void CLR_RT_SignatureParser::Initialize_Objects( CLR_RT_HeapBlock* lst, int count, bool fTypes ) +{ + NATIVE_PROFILE_CLR_CORE(); + m_lst = lst; + + m_type = CLR_RT_SignatureParser::c_Object; + m_flags = fTypes ? 1 : 0; + m_count = count; +} + +//--// + +HRESULT CLR_RT_SignatureParser::Advance( Element& res ) +{ + NATIVE_PROFILE_CLR_CORE(); + // + // WARNING!!! + // + // If you change this method, change "CLR_RT_ExecutionEngine::InitializeLocals" too. + // + + TINYCLR_HEADER(); + + _ASSERTE(m_count > 0); + + m_count--; + + res.m_fByRef = false; + res.m_levels = 0; + + switch(m_type) + { + case c_Interfaces: + { + CLR_RT_TypeDef_Instance cls; + + res.m_dt = DATATYPE_CLASS; + + if(cls.ResolveToken( CLR_TkFromStream( m_sig ), m_assm ) == false) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + res.m_cls = cls; + } + break; + + case c_Object: + { + CLR_RT_TypeDescriptor desc; + CLR_RT_HeapBlock* ptr = m_lst++; + + if(m_flags) + { + // Reflection types are now boxed, so unbox first + if(ptr->DataType() == DATATYPE_OBJECT) + { + ptr = ptr->Dereference(); + } + if(ptr->DataType() != DATATYPE_REFLECTION) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + TINYCLR_CHECK_HRESULT(desc.InitializeFromReflection( ptr->ReflectionDataConst() )); + } + else + { + switch(ptr->DataType()) + { + case DATATYPE_BYREF: + case DATATYPE_ARRAY_BYREF: + res.m_fByRef = true; + break; + } + + TINYCLR_CHECK_HRESULT(desc.InitializeFromObject( *ptr )); + } + + desc.m_handlerCls.InitializeFromIndex( desc.m_reflex.m_data.m_type ); + + res.m_levels = desc.m_reflex.m_levels; + res.m_dt = (CLR_DataType)desc.m_handlerCls.m_target->dataType; + res.m_cls = desc.m_reflex.m_data.m_type; + + // + // Special case for Object types. + // + if(res.m_cls.m_data == g_CLR_RT_WellKnownTypes.m_Object.m_data) + { + res.m_dt = DATATYPE_OBJECT; + } + } + break; + + default: + while(true) + { + res.m_dt = CLR_UncompressElementType( m_sig ); + + switch(res.m_dt) + { + case DATATYPE_BYREF: + if(res.m_fByRef) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + res.m_fByRef = true; + break; + + case DATATYPE_SZARRAY: + res.m_levels++; + break; + + case DATATYPE_CLASS : + case DATATYPE_VALUETYPE: + { + CLR_UINT32 tk = CLR_TkFromStream( m_sig ); + + if(CLR_TypeFromTk( tk ) == TBL_TypeSpec) + { + CLR_RT_SignatureParser sub; sub.Initialize_TypeSpec( m_assm, m_assm->GetTypeSpec( CLR_DataFromTk( tk ) ) ); + int extraLevels = res.m_levels; + + TINYCLR_CHECK_HRESULT(sub.Advance( res )); + + res.m_levels += extraLevels; + } + else + { + CLR_RT_TypeDef_Instance cls; + + if(cls.ResolveToken( tk, m_assm ) == false) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + res.m_cls = cls; + } + + TINYCLR_SET_AND_LEAVE(S_OK); + } + + case DATATYPE_OBJECT: + res.m_cls = g_CLR_RT_WellKnownTypes.m_Object; + + TINYCLR_SET_AND_LEAVE(S_OK); + + case DATATYPE_VOID: + res.m_cls = g_CLR_RT_WellKnownTypes.m_Void; + + TINYCLR_SET_AND_LEAVE(S_OK); + + default: + { + const CLR_RT_TypeDef_Index* cls = c_CLR_RT_DataTypeLookup[ res.m_dt ].m_cls; + + if(cls) + { + res.m_cls = *cls; + TINYCLR_SET_AND_LEAVE(S_OK); + } + else + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + } + } + break; + } + + TINYCLR_NOCLEANUP(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +bool CLR_RT_Assembly_Instance::InitializeFromIndex( const CLR_RT_Assembly_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(TINYCLR_INDEX_IS_VALID(idx)) + { + m_data = idx.m_data; + m_assm = g_CLR_RT_TypeSystem.m_assemblies[ Assembly()-1 ]; + + return true; + } + + m_data = 0; + m_assm = NULL; + + return false; +} + +void CLR_RT_Assembly_Instance::Clear() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_Assembly_Index::Clear(); + + m_assm = NULL; +} + +////////////////////////////// + +bool CLR_RT_TypeSpec_Instance::InitializeFromIndex( const CLR_RT_TypeSpec_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(TINYCLR_INDEX_IS_VALID(idx)) + { + m_data = idx.m_data; + m_assm = g_CLR_RT_TypeSystem.m_assemblies[ Assembly()-1 ] ; + m_target = m_assm->GetSignature( m_assm->GetTypeSpec ( TypeSpec() )->sig ); + + return true; + } + + m_data = 0; + m_assm = NULL; + m_target = NULL; + + return false; +} + +void CLR_RT_TypeSpec_Instance::Clear() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_TypeSpec_Index::Clear(); + + m_assm = NULL; + m_target = NULL; +} + +bool CLR_RT_TypeSpec_Instance::ResolveToken( CLR_UINT32 tk, CLR_RT_Assembly* assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(assm && CLR_TypeFromTk( tk ) == TBL_TypeSpec) + { + CLR_UINT32 idx = CLR_DataFromTk( tk ); + + Set( assm->m_idx, idx ); + + m_assm = assm; + m_target = assm->GetSignature( assm->GetTypeSpec( idx )->sig ); + + return true; + } + + Clear(); + + return false; +} + +////////////////////////////// + +bool CLR_RT_TypeDef_Instance::InitializeFromReflection( const CLR_RT_ReflectionDef_Index& reflex, CLR_UINT32* levels ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_TypeDef_Index cls; + const CLR_RT_TypeDef_Index* ptr = NULL; + + if(levels) *levels = reflex.m_levels; + + switch(reflex.m_kind) + { + case REFLECTION_TYPE: + if(reflex.m_levels > 0 && levels == NULL) + { + ptr = &g_CLR_RT_WellKnownTypes.m_Array; + } + else + { + ptr = &reflex.m_data.m_type; + } + break; + + case REFLECTION_TYPE_DELAYED: + if(g_CLR_RT_TypeSystem.FindTypeDef( reflex.m_data.m_raw, cls )) + { + ptr = &cls; + } + break; + } + + return ptr ? InitializeFromIndex( *ptr ) : false; +} + +bool CLR_RT_TypeDef_Instance::InitializeFromIndex( const CLR_RT_TypeDef_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(TINYCLR_INDEX_IS_VALID(idx)) + { + m_data = idx.m_data; + m_assm = g_CLR_RT_TypeSystem.m_assemblies[ Assembly()-1 ]; + m_target = m_assm->GetTypeDef ( Type () ); + + return true; + } + + m_data = 0; + m_assm = NULL; + m_target = NULL; + + return false; +} + +bool CLR_RT_TypeDef_Instance::InitializeFromMethod( const CLR_RT_MethodDef_Instance& md ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(TINYCLR_INDEX_IS_VALID(md)) + { + CLR_IDX idxAssm = md.Assembly(); + CLR_IDX idxType = md.CrossReference().GetOwner(); + + Set( idxAssm, idxType ); + + m_assm = g_CLR_RT_TypeSystem.m_assemblies[ idxAssm-1 ]; + m_target = m_assm->GetTypeDef ( idxType ); + + return true; + } + + Clear(); + + return false; +} + +bool CLR_RT_TypeDef_Instance::InitializeFromField( const CLR_RT_FieldDef_Instance& fd ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(TINYCLR_INDEX_IS_VALID(fd)) + { + CLR_RT_Assembly* assm = fd.m_assm; + const CLR_RECORD_TYPEDEF* td = (const CLR_RECORD_TYPEDEF*)assm->GetTable( TBL_TypeDef ); + CLR_IDX idxField = fd.Field(); + int i = assm->m_pTablesSize[ TBL_TypeDef ]; + + if(fd.m_target->flags & CLR_RECORD_FIELDDEF::FD_Static) + { + for(;i; i--, td++) + { + if(td->sFields_First <= idxField && idxField < td->sFields_First + td->sFields_Num) + { + break; + } + } + } + else + { + for(;i; i--, td++) + { + if(td->iFields_First <= idxField && idxField < td->iFields_First + td->iFields_Num) + { + break; + } + } + } + + if(i) + { + CLR_IDX idxAssm = fd.Assembly(); + CLR_IDX idxType = assm->m_pTablesSize[ TBL_TypeDef ] - i; + + Set( idxAssm, idxType ); + + m_assm = g_CLR_RT_TypeSystem.m_assemblies[ idxAssm-1 ]; + m_target = m_assm->GetTypeDef ( idxType ); + + return true; + } + } + + Clear(); + + return false; +} + +bool CLR_RT_TypeDef_Instance::IsATypeHandler() +{ + NATIVE_PROFILE_CLR_CORE(); + return (m_data == g_CLR_RT_WellKnownTypes.m_Type.m_data || m_data == g_CLR_RT_WellKnownTypes.m_TypeStatic.m_data); +} + +void CLR_RT_TypeDef_Instance::Clear() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_TypeDef_Index::Clear(); + + m_assm = NULL; + m_target = NULL; +} + +bool CLR_RT_TypeDef_Instance::ResolveToken( CLR_UINT32 tk, CLR_RT_Assembly* assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(assm) + { + CLR_UINT32 idx = CLR_DataFromTk( tk ); + + switch( CLR_TypeFromTk( tk ) ) + { + case TBL_TypeRef: + m_data = assm->m_pCrossReference_TypeRef[ idx ].m_target.m_data; + m_assm = g_CLR_RT_TypeSystem.m_assemblies[ Assembly()-1 ]; + m_target = m_assm->GetTypeDef ( Type () ); + return true; + + case TBL_TypeDef: + Set( assm->m_idx, idx ); + + m_assm = assm; + m_target = assm->GetTypeDef( idx ); + return true; + } + } + + Clear(); + + return false; +} + +//--// + +bool CLR_RT_TypeDef_Instance::SwitchToParent() +{ + NATIVE_PROFILE_CLR_CORE(); + if(TINYCLR_INDEX_IS_VALID(*this)) + { + CLR_IDX extends = m_target->extends; + + if(extends != CLR_EmptyIndex) + { + CLR_RT_TypeDef_Index tmp; + const CLR_RT_TypeDef_Index* cls; + + if(extends & 0x8000) // TypeRef + { + cls = &m_assm->m_pCrossReference_TypeRef[ extends & 0x7FFF ].m_target; + } + else + { + tmp.Set( Assembly(), extends ); + + cls = &tmp; + } + + return InitializeFromIndex( *cls ); + } + } + + Clear(); + + return false; +} + +bool CLR_RT_TypeDef_Instance::HasFinalizer() const +{ + NATIVE_PROFILE_CLR_CORE(); + return TINYCLR_INDEX_IS_VALID(*this) && (CrossReference().m_flags & CLR_RT_TypeDef_CrossReference::TD_CR_HasFinalizer); +} + +////////////////////////////// + +bool CLR_RT_FieldDef_Instance::InitializeFromIndex( const CLR_RT_FieldDef_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(TINYCLR_INDEX_IS_VALID(idx)) + { + m_data = idx.m_data; + m_assm = g_CLR_RT_TypeSystem.m_assemblies[ Assembly()-1 ]; + m_target = m_assm->GetFieldDef ( Field () ); + + return true; + } + + m_data = 0; + m_assm = NULL; + m_target = NULL; + + return false; +} + +void CLR_RT_FieldDef_Instance::Clear() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_FieldDef_Index::Clear(); + + m_assm = NULL; + m_target = NULL; +} + +bool CLR_RT_FieldDef_Instance::ResolveToken( CLR_UINT32 tk, CLR_RT_Assembly* assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(assm) + { + CLR_UINT32 idx = CLR_DataFromTk( tk ); + + switch(CLR_TypeFromTk( tk )) + { + case TBL_FieldRef: + m_data = assm->m_pCrossReference_FieldRef[ idx ].m_target.m_data; + m_assm = g_CLR_RT_TypeSystem.m_assemblies[ Assembly()-1 ]; + m_target = m_assm->GetFieldDef ( Field () ); + return true; + + case TBL_FieldDef: + Set( assm->m_idx, idx ); + + m_assm = assm; + m_target = m_assm->GetFieldDef( idx ); + return true; + } + } + + Clear(); + + return false; +} + +////////////////////////////// + +bool CLR_RT_MethodDef_Instance::InitializeFromIndex( const CLR_RT_MethodDef_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(TINYCLR_INDEX_IS_VALID(idx)) + { + m_data = idx.m_data; + m_assm = g_CLR_RT_TypeSystem.m_assemblies[ Assembly()-1 ]; + m_target = m_assm->GetMethodDef ( Method () ); + + return true; + } + + m_data = 0; + m_assm = NULL; + m_target = NULL; + + return false; +} + +void CLR_RT_MethodDef_Instance::Clear() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_MethodDef_Index::Clear(); + + m_assm = NULL; + m_target = NULL; +} + +bool CLR_RT_MethodDef_Instance::ResolveToken( CLR_UINT32 tk, CLR_RT_Assembly* assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(assm) + { + CLR_UINT32 idx = CLR_DataFromTk( tk ); + + switch(CLR_TypeFromTk( tk )) + { + case TBL_MethodRef: + m_data = assm->m_pCrossReference_MethodRef[ idx ].m_target.m_data; + m_assm = g_CLR_RT_TypeSystem.m_assemblies[ Assembly()-1 ]; + m_target = m_assm->GetMethodDef ( Method () ); + return true; + + case TBL_MethodDef: + Set( assm->m_idx, idx ); + + m_assm = assm; + m_target = m_assm->GetMethodDef( idx ); + return true; + } + } + + Clear(); + + return false; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_TypeDescriptor::TypeDescriptor_Initialize() +{ + NATIVE_PROFILE_CLR_CORE(); + m_flags = 0; // CLR_UINT32 m_flags; + m_handlerCls.Clear(); // CLR_RT_TypeDef_Instance m_handlerCls; + // + m_reflex .Clear(); // CLR_RT_ReflectionDef_Index m_reflex; +} + +HRESULT CLR_RT_TypeDescriptor::InitializeFromDataType( CLR_DataType dt ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + if(dt >= DATATYPE_FIRST_INVALID) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + else + { + const CLR_RT_DataTypeLookup& dtl = c_CLR_RT_DataTypeLookup[ dt ]; + + m_flags = dtl.m_flags & CLR_RT_DataTypeLookup::c_SemanticMask2; + + if(dtl.m_cls) + { + if(m_handlerCls.InitializeFromIndex( *dtl.m_cls ) == false) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + m_reflex.m_kind = REFLECTION_TYPE; + m_reflex.m_levels = 0; + m_reflex.m_data.m_type = *dtl.m_cls; + } + else + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_TypeDescriptor::InitializeFromReflection( const CLR_RT_ReflectionDef_Index& reflex ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_TypeDef_Instance inst; + CLR_UINT32 levels; + + if(inst.InitializeFromReflection( reflex, &levels ) == false) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + TINYCLR_CHECK_HRESULT(InitializeFromType( inst )); + + if(levels) + { + m_reflex.m_levels = levels; + + ConvertToArray(); + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_TypeDescriptor::InitializeFromTypeSpec( const CLR_RT_TypeSpec_Index& sig ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_TypeSpec_Instance inst; + CLR_RT_SignatureParser parser; + + if(inst.InitializeFromIndex( sig ) == false) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + parser.Initialize_TypeSpec( inst.m_assm, inst.m_target ); + + TINYCLR_SET_AND_LEAVE(InitializeFromSignatureParser( parser )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_TypeDescriptor::InitializeFromType( const CLR_RT_TypeDef_Index& cls ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + if(m_handlerCls.InitializeFromIndex( cls ) == false) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + else + { + const CLR_RT_DataTypeLookup& dtl = c_CLR_RT_DataTypeLookup[ m_handlerCls.m_target->dataType ]; + + m_flags = dtl.m_flags & CLR_RT_DataTypeLookup::c_SemanticMask; + + m_reflex.m_kind = REFLECTION_TYPE; + m_reflex.m_levels = 0; + m_reflex.m_data.m_type = m_handlerCls; + + if(m_flags == CLR_RT_DataTypeLookup::c_Primitive) + { + if((m_handlerCls.m_target->flags & CLR_RECORD_TYPEDEF::TD_Semantics_Mask) == CLR_RECORD_TYPEDEF::TD_Semantics_Enum) + { + m_flags = CLR_RT_DataTypeLookup::c_Enum; + } + } + else + { + switch(m_handlerCls.m_target->flags & CLR_RECORD_TYPEDEF::TD_Semantics_Mask) + { + case CLR_RECORD_TYPEDEF::TD_Semantics_ValueType: m_flags = CLR_RT_DataTypeLookup::c_ValueType; break; + case CLR_RECORD_TYPEDEF::TD_Semantics_Class : m_flags = CLR_RT_DataTypeLookup::c_Class ; break; + case CLR_RECORD_TYPEDEF::TD_Semantics_Interface: m_flags = CLR_RT_DataTypeLookup::c_Interface; break; + case CLR_RECORD_TYPEDEF::TD_Semantics_Enum : m_flags = CLR_RT_DataTypeLookup::c_Enum ; break; + } + } + + if(m_handlerCls.m_data == g_CLR_RT_WellKnownTypes.m_Array.m_data) + { + m_flags |= CLR_RT_DataTypeLookup::c_Array; + } + + if(m_handlerCls.m_data == g_CLR_RT_WellKnownTypes.m_ArrayList.m_data) + { + m_flags |= CLR_RT_DataTypeLookup::c_ArrayList; + } + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_TypeDescriptor::InitializeFromFieldDefinition( const CLR_RT_FieldDef_Instance& fd ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_SignatureParser parser; parser.Initialize_FieldDef( fd.m_assm, fd.m_target ); + + TINYCLR_SET_AND_LEAVE(InitializeFromSignatureParser( parser )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_TypeDescriptor::InitializeFromSignatureParser( CLR_RT_SignatureParser& parser ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_SignatureParser::Element res; + + if(parser.Available() <= 0) + { + TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + + TINYCLR_CHECK_HRESULT(parser.Advance( res )); + + TINYCLR_CHECK_HRESULT(InitializeFromType( res.m_cls )); + + if(res.m_levels) + { + m_reflex.m_levels = res.m_levels; + + ConvertToArray(); + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_TypeDescriptor::InitializeFromObject( const CLR_RT_HeapBlock& ref ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + const CLR_RT_HeapBlock* obj = &ref; + CLR_DataType dt; + + + while(true) + { + dt = (CLR_DataType)obj->DataType(); + + if(dt == DATATYPE_BYREF || + dt == DATATYPE_OBJECT ) + { + obj = obj->Dereference(); FAULT_ON_NULL(obj); + } +#if defined(TINYCLR_APPDOMAINS) + else if(dt == DATATYPE_TRANSPARENT_PROXY) + { + TINYCLR_CHECK_HRESULT(obj->TransparentProxyValidate()); + obj = obj->TransparentProxyDereference(); + } +#endif + else + { + break; + } + } + + { + const CLR_RT_TypeDef_Index* cls = NULL; + const CLR_RT_ReflectionDef_Index* reflex = NULL; + + switch(dt) + { + case DATATYPE_SZARRAY: + reflex = &obj->ReflectionDataConst(); + cls = &reflex->m_data.m_type; + break; + + case DATATYPE_VALUETYPE: + case DATATYPE_CLASS: + cls = &obj->ObjectCls(); + break; + + case DATATYPE_DELEGATE_HEAD: + { + CLR_RT_HeapBlock_Delegate* dlg = (CLR_RT_HeapBlock_Delegate*)obj; + + cls = TINYCLR_INDEX_IS_VALID(dlg->m_cls) ? &dlg->m_cls : &g_CLR_RT_WellKnownTypes.m_Delegate; + } + break; + + case DATATYPE_DELEGATELIST_HEAD: + { + CLR_RT_HeapBlock_Delegate_List* dlgLst = (CLR_RT_HeapBlock_Delegate_List*)obj; + + cls = TINYCLR_INDEX_IS_VALID(dlgLst->m_cls) ? &dlgLst->m_cls : &g_CLR_RT_WellKnownTypes.m_MulticastDelegate; + } + break; + + //--// + + case DATATYPE_WEAKCLASS: + { + CLR_RT_HeapBlock_WeakReference* weak = (CLR_RT_HeapBlock_WeakReference*)obj; + + if(weak->m_identity.m_flags & CLR_RT_HeapBlock_WeakReference::WR_ExtendedType) + { + cls = &g_CLR_RT_WellKnownTypes.m_ExtendedWeakReference; + } + else + { + cls = &g_CLR_RT_WellKnownTypes.m_WeakReference; + } + } + break; + + //--// + + case DATATYPE_REFLECTION: + reflex = &(obj->ReflectionDataConst()); + + switch(reflex->m_kind) + { + case REFLECTION_ASSEMBLY : cls = &g_CLR_RT_WellKnownTypes.m_Assembly ; break; + case REFLECTION_TYPE : cls = &g_CLR_RT_WellKnownTypes.m_Type ; break; + case REFLECTION_TYPE_DELAYED: cls = &g_CLR_RT_WellKnownTypes.m_Type ; break; + case REFLECTION_CONSTRUCTOR : cls = &g_CLR_RT_WellKnownTypes.m_ConstructorInfo; break; + case REFLECTION_METHOD : cls = &g_CLR_RT_WellKnownTypes.m_MethodInfo ; break; + case REFLECTION_FIELD : cls = &g_CLR_RT_WellKnownTypes.m_FieldInfo ; break; + } + + break; + + //--// + + case DATATYPE_ARRAY_BYREF: + { + CLR_RT_HeapBlock_Array* array = obj->Array(); FAULT_ON_NULL(array); + + if(array->m_fReference) + { + obj = (CLR_RT_HeapBlock*)array->GetElement( obj->ArrayIndex() ); + + TINYCLR_SET_AND_LEAVE(InitializeFromObject( *obj )); + } + + reflex = &array->ReflectionDataConst(); + cls = &reflex->m_data.m_type; + } + break; + + //--// + + default: + TINYCLR_SET_AND_LEAVE(InitializeFromDataType( dt )); + } + + if(cls) + { + TINYCLR_CHECK_HRESULT(InitializeFromType( *cls )); + } + + if(reflex) + { + m_reflex = *reflex; + } + + if(dt == DATATYPE_SZARRAY) + { + ConvertToArray(); + } + } + + TINYCLR_NOCLEANUP(); +} + +//////////////////////////////////////// + +void CLR_RT_TypeDescriptor::ConvertToArray() +{ + NATIVE_PROFILE_CLR_CORE(); + m_flags &= CLR_RT_DataTypeLookup::c_SemanticMask; + m_flags |= CLR_RT_DataTypeLookup::c_Array; + + m_handlerCls.InitializeFromIndex( g_CLR_RT_WellKnownTypes.m_Array ); +} + +bool CLR_RT_TypeDescriptor::ShouldEmitHash() +{ + NATIVE_PROFILE_CLR_CORE(); + if(m_flags & (CLR_RT_DataTypeLookup::c_Array | CLR_RT_DataTypeLookup::c_ArrayList)) + { + return true; + } + + if(m_flags & (CLR_RT_DataTypeLookup::c_Primitive | CLR_RT_DataTypeLookup::c_ValueType | CLR_RT_DataTypeLookup::c_Enum)) + { + return false; + } + + if(m_handlerCls.CrossReference().m_hash != 0) + { + return true; + } + + return false; +} + +bool CLR_RT_TypeDescriptor::GetElementType( CLR_RT_TypeDescriptor& sub ) +{ + NATIVE_PROFILE_CLR_CORE(); + switch(m_reflex.m_levels) + { + case 0: + return false; + + case 1: + sub.InitializeFromType( m_reflex.m_data.m_type ); + break; + + default: + sub = *this; + sub.m_reflex.m_levels--; + break; + } + + return true; +} + +//////////////////////////////////////// + +HRESULT CLR_RT_TypeDescriptor::ExtractObjectAndDataType( CLR_RT_HeapBlock*& ref, CLR_DataType& dt ) +{ + NATIVE_PROFILE_CLR_CORE(); + + TINYCLR_HEADER(); + + while(true) + { + dt = (CLR_DataType)ref->DataType(); + + if(dt == DATATYPE_BYREF || + dt == DATATYPE_OBJECT ) + { + ref = ref->Dereference(); FAULT_ON_NULL(ref); + } + else + { + break; + } + } + + TINYCLR_NOCLEANUP(); +} + + +HRESULT CLR_RT_TypeDescriptor::ExtractTypeIndexFromObject( const CLR_RT_HeapBlock& ref, CLR_RT_TypeDef_Index& res ) +{ + NATIVE_PROFILE_CLR_CORE(); + + TINYCLR_HEADER(); + + CLR_RT_HeapBlock* obj = (CLR_RT_HeapBlock*)&ref; + CLR_DataType dt; + + TINYCLR_CHECK_HRESULT(CLR_RT_TypeDescriptor::ExtractObjectAndDataType(obj, dt)); + + if(dt == DATATYPE_VALUETYPE || dt == DATATYPE_CLASS) + { + res = obj->ObjectCls(); + } + else + { + const CLR_RT_DataTypeLookup& dtl = c_CLR_RT_DataTypeLookup[ dt ]; + + if(dtl.m_cls) + { + res = *dtl.m_cls; + } + else + { + res.Clear(); + } + } + + if(TINYCLR_INDEX_IS_INVALID(res)) + { + CLR_RT_TypeDescriptor desc; + + TINYCLR_CHECK_HRESULT(desc.InitializeFromObject( ref )) + + // If desc.InitializeFromObject( ref ) call succeded, then we use m_handlerCls for res + res = desc.m_handlerCls; + + if(TINYCLR_INDEX_IS_INVALID(res)) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + + TINYCLR_NOCLEANUP(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +// +// Keep these strings less than 8-character long!! They are stuffed into an 8-byte structure. +// +static const char c_MARKER_ASSEMBLY_V1[] = "MSSpot1"; + +bool CLR_RECORD_ASSEMBLY::GoodHeader() const +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RECORD_ASSEMBLY header = *this; header.headerCRC = 0; + + if ( (header.flags & CLR_RECORD_ASSEMBLY::c_Flags_BigEndian) == CLR_RECORD_ASSEMBLY::c_Flags_BigEndian) + { + // Incorrect endianness + return false; + } + + if(SUPPORT_ComputeCRC( &header, sizeof(header), 0 ) != this->headerCRC) return false; + + if(this->stringTableVersion != c_CLR_StringTable_Version) return false; + + return memcmp( marker, c_MARKER_ASSEMBLY_V1, sizeof(marker) ) == 0; +} + +bool CLR_RECORD_ASSEMBLY::GoodAssembly() const +{ + NATIVE_PROFILE_CLR_CORE(); + if(!GoodHeader()) return false; + return SUPPORT_ComputeCRC( &this[ 1 ], this->TotalSize() - sizeof(*this), 0 ) == this->assemblyCRC; +} + +#if defined(WIN32) + +void CLR_RECORD_ASSEMBLY::ComputeCRC() +{ + NATIVE_PROFILE_CLR_CORE(); + memcpy( marker, c_MARKER_ASSEMBLY_V1, sizeof(marker) ); + + headerCRC = 0; + assemblyCRC = SUPPORT_ComputeCRC( &this[ 1 ], this->TotalSize() - sizeof(*this), 0 ); + headerCRC = SUPPORT_ComputeCRC( this , sizeof(*this), 0 ); +} + +#endif + +CLR_UINT32 CLR_RECORD_ASSEMBLY::ComputeAssemblyHash( LPCSTR name, const CLR_RECORD_VERSION& ver ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_UINT32 assemblyHASH; + + assemblyHASH = SUPPORT_ComputeCRC( name, (int)hal_strlen_s( name ), 0 ); + assemblyHASH = SUPPORT_ComputeCRC( &ver, sizeof( ver ), assemblyHASH ); + + return assemblyHASH; +} + +//--// + +CLR_PMETADATA CLR_RECORD_EH::ExtractEhFromByteCode( CLR_PMETADATA ipEnd, const CLR_RECORD_EH*& ptrEh, CLR_UINT32& numEh ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_UINT32 num = *(--ipEnd); ipEnd -= sizeof(CLR_RECORD_EH) * num; + + numEh = num; + ptrEh = (const CLR_RECORD_EH*)ipEnd; + + return ipEnd; +} + +CLR_UINT32 CLR_RECORD_EH::GetToken() const +{ + NATIVE_PROFILE_CLR_CORE(); + if(classToken & 0x8000) + { + return CLR_TkFromType( TBL_TypeRef, classToken & 0x7FFF ); + } + else + { + return CLR_TkFromType( TBL_TypeDef, classToken ); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +bool CLR_RT_ExceptionHandler::ConvertFromEH( const CLR_RT_MethodDef_Instance& owner, CLR_PMETADATA ipStart, const CLR_RECORD_EH* ehPtr ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RECORD_EH eh; memcpy( &eh, ehPtr, sizeof(eh) ); + + switch(eh.mode) + { + case CLR_RECORD_EH::EH_Finally: + m_typeFilter.Clear(); + break; + + case CLR_RECORD_EH::EH_Filter: + m_userFilterStart = ipStart + eh.filterStart; + break; + + case CLR_RECORD_EH::EH_CatchAll: + m_typeFilter = g_CLR_RT_WellKnownTypes.m_Object; + break; + + case CLR_RECORD_EH::EH_Catch: + { + CLR_RT_TypeDef_Instance cls; + if(cls.ResolveToken( eh.GetToken(), owner.m_assm ) == false) return false; + m_typeFilter = cls; + } + break; + + default: + return false; + } + + if(owner.m_target->RVA == CLR_EmptyIndex) return false; + + m_ehType = eh.mode; + m_tryStart = ipStart + eh.tryStart; + m_tryEnd = ipStart + eh.tryEnd; + m_handlerStart = ipStart + eh.handlerStart; + m_handlerEnd = ipStart + eh.handlerEnd; + + return true; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + + +bool CLR_RT_Assembly::IsSameAssembly( const CLR_RT_Assembly& assm ) const +{ + if( + m_header->headerCRC == assm.m_header->headerCRC && + m_header->assemblyCRC == assm.m_header->assemblyCRC + ) + { + return true; + } + + return false; +} + +void CLR_RT_Assembly::Assembly_Initialize( CLR_RT_Assembly::Offsets& offsets ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_UINT8* buffer = (CLR_UINT8*)this; + int i; + + m_szName = GetString( m_header->assemblyName ); + + //--// + buffer += offsets.iBase ; + m_pCrossReference_AssemblyRef = (CLR_RT_AssemblyRef_CrossReference*)buffer; buffer += offsets.iAssemblyRef ; + m_pCrossReference_TypeRef = (CLR_RT_TypeRef_CrossReference *)buffer; buffer += offsets.iTypeRef ; + m_pCrossReference_FieldRef = (CLR_RT_FieldRef_CrossReference *)buffer; buffer += offsets.iFieldRef ; + m_pCrossReference_MethodRef = (CLR_RT_MethodRef_CrossReference *)buffer; buffer += offsets.iMethodRef ; + m_pCrossReference_TypeDef = (CLR_RT_TypeDef_CrossReference *)buffer; buffer += offsets.iTypeDef ; + m_pCrossReference_FieldDef = (CLR_RT_FieldDef_CrossReference *)buffer; buffer += offsets.iFieldDef ; + m_pCrossReference_MethodDef = (CLR_RT_MethodDef_CrossReference *)buffer; buffer += offsets.iMethodDef ; + +#if !defined(TINYCLR_APPDOMAINS) + m_pStaticFields = (CLR_RT_HeapBlock *)buffer; buffer += offsets.iStaticFields ; + + memset( m_pStaticFields, 0, offsets.iStaticFields ); +#endif + + //--// + + { + ITERATE_THROUGH_RECORDS(this,i,TypeDef,TYPEDEF) + { + dst->m_flags = 0; + dst->m_totalFields = 0; + dst->m_hash = 0; + } + } + + { + ITERATE_THROUGH_RECORDS(this,i,FieldDef,FIELDDEF) + { + dst->m_offset = CLR_EmptyIndex; + } + } + + { + ITERATE_THROUGH_RECORDS(this,i,MethodDef,METHODDEF) + { + dst->m_data = CLR_EmptyIndex; + } + } + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + { + m_pDebuggingInfo_MethodDef = (CLR_RT_MethodDef_DebuggingInfo*)buffer; buffer += offsets.iDebuggingInfoMethods; + + memset( m_pDebuggingInfo_MethodDef, 0, offsets.iDebuggingInfoMethods ); + } +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) +} + +HRESULT CLR_RT_Assembly::CreateInstance( const CLR_RECORD_ASSEMBLY* header, CLR_RT_Assembly*& assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + // + // We have to use this trick, otherwise the C++ compiler will try to all the constructor for Assembly. + // + TINYCLR_HEADER(); + + CLR_UINT8 buf[ sizeof(CLR_RT_Assembly) ]; + CLR_RT_Assembly* skeleton = (CLR_RT_Assembly*)buf; + + TINYCLR_CLEAR(*skeleton); + + if(header->GoodAssembly() == false) TINYCLR_SET_AND_LEAVE(CLR_E_FAIL); + + skeleton->m_header = header; + + + // + // Compute overall size for assembly data structure. + // + { + for(int i=0; im_pTablesSize)-1; i++) + { + skeleton->m_pTablesSize[ i ] = header->SizeOfTable ( (CLR_TABLESENUM)i ); + } + + skeleton->m_pTablesSize[ TBL_AssemblyRef ] /= sizeof(CLR_RECORD_ASSEMBLYREF ); + skeleton->m_pTablesSize[ TBL_TypeRef ] /= sizeof(CLR_RECORD_TYPEREF ); + skeleton->m_pTablesSize[ TBL_FieldRef ] /= sizeof(CLR_RECORD_FIELDREF ); + skeleton->m_pTablesSize[ TBL_MethodRef ] /= sizeof(CLR_RECORD_METHODREF ); + skeleton->m_pTablesSize[ TBL_TypeDef ] /= sizeof(CLR_RECORD_TYPEDEF ); + skeleton->m_pTablesSize[ TBL_FieldDef ] /= sizeof(CLR_RECORD_FIELDDEF ); + skeleton->m_pTablesSize[ TBL_MethodDef ] /= sizeof(CLR_RECORD_METHODDEF ); + skeleton->m_pTablesSize[ TBL_Attributes ] /= sizeof(CLR_RECORD_ATTRIBUTE ); + skeleton->m_pTablesSize[ TBL_TypeSpec ] /= sizeof(CLR_RECORD_TYPESPEC ); + skeleton->m_pTablesSize[ TBL_Resources ] /= sizeof(CLR_RECORD_RESOURCE ); + skeleton->m_pTablesSize[ TBL_ResourcesFiles ] /= sizeof(CLR_RECORD_RESOURCE_FILE); + } + + //--// + + // + // Count static fields. + // + { + const CLR_RECORD_TYPEDEF* src = (const CLR_RECORD_TYPEDEF*)skeleton->GetTable( TBL_TypeDef ); + + for(int i=0; im_pTablesSize[ TBL_TypeDef ]; i++, src++) + { + skeleton->m_iStaticFields += src->sFields_Num; + } + } + + //--// + + { + CLR_RT_Assembly::Offsets offsets; + + offsets.iBase = ROUNDTOMULTIPLE(sizeof(CLR_RT_Assembly) , CLR_UINT32); + offsets.iAssemblyRef = ROUNDTOMULTIPLE(skeleton->m_pTablesSize[ TBL_AssemblyRef ] * sizeof(CLR_RT_AssemblyRef_CrossReference), CLR_UINT32); + offsets.iTypeRef = ROUNDTOMULTIPLE(skeleton->m_pTablesSize[ TBL_TypeRef ] * sizeof(CLR_RT_TypeRef_CrossReference ), CLR_UINT32); + offsets.iFieldRef = ROUNDTOMULTIPLE(skeleton->m_pTablesSize[ TBL_FieldRef ] * sizeof(CLR_RT_FieldRef_CrossReference ), CLR_UINT32); + offsets.iMethodRef = ROUNDTOMULTIPLE(skeleton->m_pTablesSize[ TBL_MethodRef ] * sizeof(CLR_RT_MethodRef_CrossReference ), CLR_UINT32); + offsets.iTypeDef = ROUNDTOMULTIPLE(skeleton->m_pTablesSize[ TBL_TypeDef ] * sizeof(CLR_RT_TypeDef_CrossReference ), CLR_UINT32); + offsets.iFieldDef = ROUNDTOMULTIPLE(skeleton->m_pTablesSize[ TBL_FieldDef ] * sizeof(CLR_RT_FieldDef_CrossReference ), CLR_UINT32); + offsets.iMethodDef = ROUNDTOMULTIPLE(skeleton->m_pTablesSize[ TBL_MethodDef ] * sizeof(CLR_RT_MethodDef_CrossReference ), CLR_UINT32); + + if(skeleton->m_header->numOfPatchedMethods > 0) + { + TINYCLR_SET_AND_LEAVE(CLR_E_ASSM_PATCHING_NOT_SUPPORTED); + } + +#if !defined(TINYCLR_APPDOMAINS) + offsets.iStaticFields = ROUNDTOMULTIPLE(skeleton->m_iStaticFields * sizeof(CLR_RT_HeapBlock ), CLR_UINT32); +#endif + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + offsets.iDebuggingInfoMethods = ROUNDTOMULTIPLE(skeleton->m_pTablesSize[ TBL_MethodDef ] * sizeof(CLR_RT_MethodDef_DebuggingInfo ), CLR_UINT32); +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + size_t iTotalRamSize = offsets.iBase + + offsets.iAssemblyRef + + offsets.iTypeRef + + offsets.iFieldRef + + offsets.iMethodRef + + offsets.iTypeDef + + offsets.iFieldDef + + offsets.iMethodDef; + +#if !defined(TINYCLR_APPDOMAINS) + iTotalRamSize += offsets.iStaticFields; +#endif + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + iTotalRamSize += offsets.iDebuggingInfoMethods; +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + //--// + + assm = EVENTCACHE_EXTRACT_NODE_AS_BYTES(g_CLR_RT_EventCache,CLR_RT_Assembly,DATATYPE_ASSEMBLY,0,(CLR_UINT32)iTotalRamSize); CHECK_ALLOCATION(assm); + + { + // + // We don't want to blow away the block header... + // + CLR_RT_HeapBlock* src = skeleton; + CLR_RT_HeapBlock* dst = assm; + + memset( &dst[ 1 ], 0, iTotalRamSize-sizeof(CLR_RT_HeapBlock) ); + memcpy( &dst[ 1 ], &src[ 1 ], sizeof(*assm)-sizeof(CLR_RT_HeapBlock) ); + } + + assm->Assembly_Initialize( offsets ); + +#if !defined(BUILD_RTM) + CLR_Debug::Printf( " Assembly: %s (%d.%d.%d.%d) ", assm->m_szName, header->version.iMajorVersion, header->version.iMinorVersion, header->version.iBuildNumber, header->version.iRevisionNumber ); + + if(s_CLR_RT_fTrace_AssemblyOverhead >= c_CLR_RT_Trace_Info) + { + size_t iMetaData = header->SizeOfTable( TBL_AssemblyRef ) + + header->SizeOfTable( TBL_TypeRef ) + + header->SizeOfTable( TBL_FieldRef ) + + header->SizeOfTable( TBL_MethodRef ) + + header->SizeOfTable( TBL_TypeDef ) + + header->SizeOfTable( TBL_FieldDef ) + + header->SizeOfTable( TBL_MethodDef ) + + header->SizeOfTable( TBL_Attributes ) + + header->SizeOfTable( TBL_TypeSpec ) + + header->SizeOfTable( TBL_Signatures ); + + CLR_Debug::Printf( " (%d RAM - %d ROM - %d METADATA)\r\n\r\n", iTotalRamSize, header->TotalSize(), iMetaData ); + + CLR_Debug::Printf( " AssemblyRef = %8d bytes (%8d elements)\r\n", offsets.iAssemblyRef , skeleton->m_pTablesSize[ TBL_AssemblyRef ] ); + CLR_Debug::Printf( " TypeRef = %8d bytes (%8d elements)\r\n", offsets.iTypeRef , skeleton->m_pTablesSize[ TBL_TypeRef ] ); + CLR_Debug::Printf( " FieldRef = %8d bytes (%8d elements)\r\n", offsets.iFieldRef , skeleton->m_pTablesSize[ TBL_FieldRef ] ); + CLR_Debug::Printf( " MethodRef = %8d bytes (%8d elements)\r\n", offsets.iMethodRef , skeleton->m_pTablesSize[ TBL_MethodRef ] ); + CLR_Debug::Printf( " TypeDef = %8d bytes (%8d elements)\r\n", offsets.iTypeDef , skeleton->m_pTablesSize[ TBL_TypeDef ] ); + CLR_Debug::Printf( " FieldDef = %8d bytes (%8d elements)\r\n", offsets.iFieldDef , skeleton->m_pTablesSize[ TBL_FieldDef ] ); + CLR_Debug::Printf( " MethodDef = %8d bytes (%8d elements)\r\n", offsets.iMethodDef , skeleton->m_pTablesSize[ TBL_MethodDef ] ); +#if !defined(TINYCLR_APPDOMAINS) + CLR_Debug::Printf( " StaticFields = %8d bytes (%8d elements)\r\n", offsets.iStaticFields , skeleton->m_iStaticFields ); +#endif + CLR_Debug::Printf( "\r\n" ); + + CLR_Debug::Printf( " Attributes = %8d bytes (%8d elements)\r\n", skeleton->m_pTablesSize[ TBL_Attributes ] * sizeof(CLR_RECORD_ATTRIBUTE), skeleton->m_pTablesSize[ TBL_Attributes ] ); + CLR_Debug::Printf( " TypeSpec = %8d bytes (%8d elements)\r\n", skeleton->m_pTablesSize[ TBL_TypeSpec ] * sizeof(CLR_RECORD_TYPESPEC ), skeleton->m_pTablesSize[ TBL_TypeSpec ] ); + CLR_Debug::Printf( " Resources = %8d bytes (%8d elements)\r\n", skeleton->m_pTablesSize[ TBL_Resources ] * sizeof(CLR_RECORD_RESOURCE ), skeleton->m_pTablesSize[ TBL_Resources ] ); + CLR_Debug::Printf( " Resources Files = %8d bytes (%8d elements)\r\n", skeleton->m_pTablesSize[ TBL_ResourcesFiles ] * sizeof(CLR_RECORD_RESOURCE ), skeleton->m_pTablesSize[ TBL_ResourcesFiles ] ); + CLR_Debug::Printf( " Resources Data = %8d bytes\r\n" , skeleton->m_pTablesSize[ TBL_ResourcesData ] ); + CLR_Debug::Printf( " Strings = %8d bytes\r\n" , skeleton->m_pTablesSize[ TBL_Strings ] ); + CLR_Debug::Printf( " Signatures = %8d bytes\r\n" , skeleton->m_pTablesSize[ TBL_Signatures ] ); + CLR_Debug::Printf( " ByteCode = %8d bytes\r\n" , skeleton->m_pTablesSize[ TBL_ByteCode ] ); + CLR_Debug::Printf( "\r\n\r\n" ); + } +#endif + } + + TINYCLR_NOCLEANUP(); +} + + +#if defined(WIN32) +HRESULT CLR_RT_Assembly::CreateInstance( const CLR_RECORD_ASSEMBLY* header, CLR_RT_Assembly*& assm, LPCWSTR szName ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + std::string strPath; + + TINYCLR_CHECK_HRESULT(CLR_RT_Assembly::CreateInstance( header, assm )); + + if(szName != NULL) + { + CLR_RT_UnicodeHelper::ConvertToUTF8( szName, strPath ); + + assm->m_strPath = new std::string( strPath ); + } + + TINYCLR_NOCLEANUP(); +} +#endif + +bool CLR_RT_Assembly::Resolve_AssemblyRef( bool fOutput ) +{ + NATIVE_PROFILE_CLR_CORE(); + bool fGot = true; + int i; + + ITERATE_THROUGH_RECORDS(this,i,AssemblyRef,ASSEMBLYREF) + { + LPCSTR szName = GetString( src->name ); + + if(dst->m_target == NULL) + { + bool fExact = true; + + // + // Exact matching if this is a patch and the reference is toward the patched assembly. + // + if(m_header->flags & CLR_RECORD_ASSEMBLY::c_Flags_Patch) + { + if(!strcmp( szName, m_szName )) + { + fExact = true; + } + } + + CLR_RT_Assembly* target = g_CLR_RT_TypeSystem.FindAssembly( szName, &src->version, fExact ); + + if(target == NULL || (target->m_flags & CLR_RT_Assembly::c_Resolved) == 0) + { +#if !defined(BUILD_RTM) + if(fOutput) + { + CLR_Debug::Printf( "Assembly: %s (%d.%d.%d.%d)", m_szName, m_header->version.iMajorVersion, m_header->version.iMinorVersion, m_header->version.iBuildNumber, m_header->version.iRevisionNumber ); + + CLR_Debug::Printf( " needs assembly '%s' (%d.%d.%d.%d)\r\n", szName, src->version.iMajorVersion, src->version.iMinorVersion, src->version.iBuildNumber, src->version.iRevisionNumber ); + } +#endif + + fGot = false; + } + else + { + dst->m_target = target; + } + } + } + + return fGot; +} + +void CLR_RT_Assembly::DestroyInstance() +{ + NATIVE_PROFILE_CLR_CORE(); + if(m_idx) + { + g_CLR_RT_TypeSystem.m_assemblies[ m_idx-1 ] = NULL; + } + +#if defined(WIN32) + if(this->m_strPath != NULL) + { + delete this->m_strPath; + this->m_strPath = NULL; + } +#endif + + //--// + + g_CLR_RT_EventCache.Append_Node( this ); +} + +//--// +HRESULT CLR_RT_Assembly::Resolve_TypeRef() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + int i; + + ITERATE_THROUGH_RECORDS(this,i,TypeRef,TYPEREF) + { + if(src->scope & 0x8000) // Flag for TypeRef + { + CLR_RT_TypeDef_Instance inst; + + if(inst.InitializeFromIndex( m_pCrossReference_TypeRef[ src->scope & 0x7FFF ].m_target ) == false) + { +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Resolve: unknown scope: %08x\r\n", src->scope ); +#endif + TINYCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + LPCSTR szName = GetString( src->name ); + if(inst.m_assm->FindTypeDef( szName, inst.Type(), dst->m_target ) == false) + { +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Resolve: unknown type: %s\r\n", szName ); +#endif + + TINYCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + } + else + { + CLR_RT_Assembly* assm = m_pCrossReference_AssemblyRef[ src->scope ].m_target; + if(assm == NULL) + { + TINYCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + LPCSTR szNameSpace = GetString( src->nameSpace ); + LPCSTR szName = GetString( src->name ); + if(assm->FindTypeDef( szName, szNameSpace, dst->m_target ) == false) + { +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Resolve: unknown type: %s.%s\r\n", szNameSpace, szName ); +#endif + + TINYCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + } + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_Assembly::Resolve_FieldRef() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + int i; + + ITERATE_THROUGH_RECORDS(this,i,FieldRef,FIELDREF) + { + CLR_RT_TypeDef_Instance inst; + + if(inst.InitializeFromIndex( m_pCrossReference_TypeRef[ src->container ].m_target ) == false) + { +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Resolve Field: unknown scope: %08x\r\n", src->container ); +#endif + + TINYCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + LPCSTR szName = GetString( src->name ); + + if(inst.m_assm->FindFieldDef( inst.m_target, szName, this, src->sig, dst->m_target ) == false) + { +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Resolve: unknown field: %s\r\n", szName ); +#endif + + TINYCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_Assembly::Resolve_MethodRef() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + int i; + + ITERATE_THROUGH_RECORDS(this,i,MethodRef,METHODREF) + { + CLR_RT_TypeDef_Instance inst; + + if(inst.InitializeFromIndex( m_pCrossReference_TypeRef[ src->container ].m_target ) == false) + { +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Resolve Field: unknown scope: %08x\r\n", src->container ); +#endif + + TINYCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + LPCSTR name = GetString( src->name ); + bool fGot = false; + + while(TINYCLR_INDEX_IS_VALID(inst)) + { + if(inst.m_assm->FindMethodDef( inst.m_target, name, this, src->sig, dst->m_target )) + { + fGot = true; + break; + } + + inst.SwitchToParent(); + } + + if(fGot == false) + { + inst.InitializeFromIndex( m_pCrossReference_TypeRef[ src->container ].m_target ); + + const CLR_RECORD_TYPEDEF* qTD = inst.m_target; + CLR_RT_Assembly* qASSM = inst.m_assm; + +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Resolve: unknown method: %s.%s.%s\r\n", qASSM->GetString( qTD->nameSpace ), qASSM->GetString( qTD->name ), name ); +#endif + + TINYCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + } + + TINYCLR_NOCLEANUP(); +} + +void CLR_RT_Assembly::Resolve_Link() +{ + NATIVE_PROFILE_CLR_CORE(); + int iStaticFields = 0; + int idxType; + + ITERATE_THROUGH_RECORDS(this,idxType,TypeDef,TYPEDEF) + { + int num; + int i; + + // + // Link static fields. + // + { + CLR_RT_FieldDef_CrossReference* fd = &m_pCrossReference_FieldDef[ src->sFields_First ]; + + num = src->sFields_Num; + + for(; num; num--, fd++) + { + fd->m_offset = iStaticFields++; + } + } + + // + // Link instance fields. + // + { + CLR_RT_TypeDef_Index idx ; idx.Set( m_idx, idxType ); + CLR_RT_TypeDef_Instance inst; inst.InitializeFromIndex( idx ); + CLR_IDX tot = 0; + + do + { + if(inst.m_target->flags & CLR_RECORD_TYPEDEF::TD_HasFinalizer) + { + dst->m_flags |= CLR_RT_TypeDef_CrossReference::TD_CR_HasFinalizer; + } + +#if defined(TINYCLR_APPDOMAINS) + if(inst.m_data == g_CLR_RT_WellKnownTypes.m_MarshalByRefObject.m_data) + { + dst->m_flags |= CLR_RT_TypeDef_CrossReference::TD_CR_IsMarshalByRefObject; + } +#endif + + tot += inst.m_target->iFields_Num; + } + while(inst.SwitchToParent()); + + dst->m_totalFields = tot; + + //--// + + CLR_RT_FieldDef_CrossReference* fd = &m_pCrossReference_FieldDef[ src->iFields_First ]; + + num = src->iFields_Num; + i = tot - num + CLR_RT_HeapBlock::HB_Object_Fields_Offset; // Take into account the offset from the beginning of the object. + + for(; num; num--, i++, fd++) + { + fd->m_offset = i; + } + } + + // + // Link methods. + // + { + CLR_RT_MethodDef_CrossReference* md = &m_pCrossReference_MethodDef[ src->methods_First ]; + + int num = src->vMethods_Num + src->iMethods_Num + src->sMethods_Num; + + for(; num; num--, md++) + { + md->m_data = idxType; + } + } + } +} + +//--// + +#if defined(TINYCLR_APPDOMAINS) + +HRESULT CLR_RT_AppDomain::CreateInstance( LPCSTR szName, CLR_RT_AppDomain*& appDomain ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + CLR_RT_HeapBlock name; name.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( name ); + + if(!szName || szName[ 0 ] == '\0') TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + //Check to see that the name does not already exist. + TINYCLR_FOREACH_NODE(CLR_RT_AppDomain,appDomain,g_CLR_RT_ExecutionEngine.m_appDomains) + { + if(!strcmp( appDomain->m_strName->StringText(), szName )) TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + TINYCLR_FOREACH_NODE_END(); + + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( name, szName )); + + appDomain = EVENTCACHE_EXTRACT_NODE(g_CLR_RT_EventCache,CLR_RT_AppDomain,DATATYPE_APPDOMAIN_HEAD); CHECK_ALLOCATION(appDomain); + + appDomain->AppDomain_Initialize(); + + appDomain->m_strName = name.DereferenceString(); + + g_CLR_RT_ExecutionEngine.m_appDomains.LinkAtBack( appDomain ); + + TINYCLR_NOCLEANUP(); +} + +void CLR_RT_AppDomain::RecoverFromGC() +{ + NATIVE_PROFILE_CLR_CORE(); + CheckAll(); + + /* + AppDomains can be zombied and stay around forever. It is worth looking into cleaning up dead AppDomains, but this + needs to be done with great care. First, enumerations of AppDomains must not be allowed. Second, the AppDomain must really be dead. + This is much harder to ensure. Everything that is needed to be checked for explicit AD unloading (stack frames, finalizable objects) + must be checked, but also other things that can cause the AppDomain to be alive, like timers, manaaged drivers, transparent proxies, etc.. + */ + + if(m_state == CLR_RT_AppDomain::AppDomainState_Unloaded) + { + //We could actually clean up here. Since the AppDomain is now officially loaded, + //we can remove all object_to_event_dst references, and null out the + //pointers in the managed AppDomain class, provided that calling any method on the + //AppDomain will result in a AppDomainDisposed exception. However, it's probably + //not worth the effort, the majority of the resources have been already cleaned + //up, from AppDomain_Uninitialize + + if(IsReadyForRelease()) + { + DestroyInstance(); + } + } +} + +void CLR_RT_AppDomain::AppDomain_Initialize() +{ + NATIVE_PROFILE_CLR_CORE(); + Initialize(); + + m_appDomainAssemblies.DblLinkedList_Initialize(); + + m_state = CLR_RT_AppDomain::AppDomainState_Loaded; + m_id = g_CLR_RT_ExecutionEngine.m_appDomainIdNext++; + m_globalLock = NULL; + m_strName = NULL; + m_outOfMemoryException = NULL; + m_appDomainAssemblyLastAccess = NULL; +} + +void CLR_RT_AppDomain::AppDomain_Uninitialize() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_FOREACH_NODE(CLR_RT_AppDomainAssembly,appDomainAssembly,m_appDomainAssemblies) + { + appDomainAssembly->DestroyInstance(); + } + TINYCLR_FOREACH_NODE_END(); +} + +void CLR_RT_AppDomain::DestroyInstance() +{ + NATIVE_PROFILE_CLR_CORE(); + AppDomain_Uninitialize(); + + Unlink(); + + g_CLR_RT_EventCache.Append_Node( this ); +} + +HRESULT CLR_RT_AppDomain::LoadAssembly( CLR_RT_Assembly* assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_AppDomain* appDomainSav = g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( this ); + CLR_RT_AppDomainAssembly* appDomainAssembly = NULL; + int i; + + FAULT_ON_NULL( assm ); + + //check to make sure the assembly is not already loaded + if(FindAppDomainAssembly( assm ) != NULL) TINYCLR_SET_AND_LEAVE(S_OK); + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + g_CLR_RT_ExecutionEngine.Breakpoint_Assemblies_Loaded(); +#endif + + //Next, make sure that all dependent assemblies are loaded. + { + ITERATE_THROUGH_RECORDS(assm,i,AssemblyRef,ASSEMBLYREF) + { + TINYCLR_CHECK_HRESULT(LoadAssembly( dst->m_target )); + } + } + + TINYCLR_CHECK_HRESULT(CLR_RT_AppDomainAssembly::CreateInstance( this, assm, appDomainAssembly )); + + if(m_outOfMemoryException == NULL) + { + //Allocate an out of memory exception. We should never get into a case where an out of memory exception + //cannot be thrown. + CLR_RT_HeapBlock exception; + + _ASSERTE(!strcmp( assm->m_szName, "mscorlib" )); //always the first assembly to be loaded + + TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex( exception, g_CLR_RT_WellKnownTypes.m_OutOfMemoryException )); + + m_outOfMemoryException = exception.Dereference(); + } + + TINYCLR_CLEANUP(); + + if(FAILED(hr)) + { + if(appDomainAssembly) + { + appDomainAssembly->DestroyInstance(); + } + } + + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomainSav ); + + TINYCLR_CLEANUP_END(); +} + + +HRESULT CLR_RT_AppDomain::GetManagedObject( CLR_RT_HeapBlock& res ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_AppDomain* appDomainSav = g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( this ); + + res.SetObjectReference( NULL ); + + //Check if a managed object is already present, and use it + TINYCLR_FOREACH_NODE(CLR_RT_ObjectToEvent_Source,ref,m_references) + { + CLR_RT_HeapBlock* obj = ref->m_objectPtr; + + _ASSERTE(FIMPLIES(obj, obj->DataType() == DATATYPE_CLASS || obj->DataType() == DATATYPE_VALUETYPE)); + + if(obj && obj->ObjectCls().m_data == g_CLR_RT_WellKnownTypes.m_AppDomain.m_data) + { + //managed appDomain is found. Use it. + res.SetObjectReference( ref->m_objectPtr ); + + TINYCLR_SET_AND_LEAVE(S_OK); + } + } + TINYCLR_FOREACH_NODE_END(); + + { + //Create the managed AppDomain in the destination AppDomain + CLR_RT_HeapBlock* pRes; + CLR_RT_ProtectFromGC gc( res ); + + TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex( res, g_CLR_RT_WellKnownTypes.m_AppDomain )); + + pRes = res.Dereference(); + + TINYCLR_CHECK_HRESULT(CLR_RT_ObjectToEvent_Source::CreateInstance( this, *pRes, pRes[ Library_corlib_native_System_AppDomain::FIELD__m_appDomain ] )); + + pRes[ Library_corlib_native_System_AppDomain::FIELD__m_friendlyName ].SetObjectReference( m_strName ); + } + + TINYCLR_CLEANUP(); + + g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomainSav ); + + TINYCLR_CLEANUP_END(); +} + +CLR_RT_AppDomainAssembly* CLR_RT_AppDomain::FindAppDomainAssembly( CLR_RT_Assembly* assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(m_appDomainAssemblyLastAccess != NULL && m_appDomainAssemblyLastAccess->m_assembly == assm) + { + return m_appDomainAssemblyLastAccess; + } + + TINYCLR_FOREACH_NODE(CLR_RT_AppDomainAssembly,appDomainAssembly,m_appDomainAssemblies) + { + if(appDomainAssembly->m_assembly == assm) + { + m_appDomainAssemblyLastAccess = appDomainAssembly; + + return appDomainAssembly; + } + } + TINYCLR_FOREACH_NODE_END(); + + return NULL; +} + +void CLR_RT_AppDomain::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_globalLock ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_strName ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_outOfMemoryException ); +} + +HRESULT CLR_RT_AppDomain::VerifyTypeIsLoaded( const CLR_RT_TypeDef_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_TypeDef_Instance inst; + + if(!inst.InitializeFromIndex( idx )) TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER ); + if(!FindAppDomainAssembly ( inst.m_assm )) TINYCLR_SET_AND_LEAVE(CLR_E_APPDOMAIN_MARSHAL_EXCEPTION); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_AppDomain::MarshalObject( CLR_RT_HeapBlock& src, CLR_RT_HeapBlock& dst, CLR_RT_AppDomain* appDomainSrc ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + //This function marshals an object from appDomainSrc to 'this' AppDomain + //If appDomainSrc == NULL, this uses the current AppDomain + + CLR_RT_AppDomain* appDomainDst = this; + CLR_RT_HeapBlock* proxySrc = NULL; + CLR_RT_HeapBlock* mbroSrc = NULL; + bool fSimpleAssign = false; + CLR_RT_TypeDef_Index idxVerify = g_CLR_RT_WellKnownTypes.m_Object; + CLR_DataType dtSrc = src.DataType(); + CLR_RT_AppDomain* appDomainSav = g_CLR_RT_ExecutionEngine.GetCurrentAppDomain(); + + if(!appDomainSrc) + { + appDomainSrc = appDomainSav; + } + + // + //DATATYPE_LAST_PRIMITIVE_TO_MARSHAL note + //We should think about allowing STRINGS to be shared across AD boundaries + //Strings are read-only and it is safe to do this with some small restrictions + //First, as with the Assembly unloading, some strings can actually point within an + //assembly. If we allow assemblies to be unloaded (and why shouldn't we, if they are + //not in any AppDomain, than we need to deal with this case). If we just + //get copy the string on constructor, then we do not need to marshal strings + //across AD boundaries. + // + fSimpleAssign = (appDomainSrc == appDomainDst); + fSimpleAssign = fSimpleAssign || (dtSrc <= DATATYPE_LAST_PRIMITIVE_TO_MARSHAL); + fSimpleAssign = fSimpleAssign || (dtSrc == DATATYPE_OBJECT && src.Dereference() == NULL); + +#if !defined(TINYCLR_NO_ASSEMBLY_STRINGS) + fSimpleAssign = fSimpleAssign || (dtSrc == DATATYPE_STRING && !src.StringAssembly()); +#endif + + if(!fSimpleAssign) + { + if(dtSrc == DATATYPE_OBJECT) + { + CLR_RT_HeapBlock* ptr = src.Dereference(); + + switch(ptr->DataType()) + { + case DATATYPE_TRANSPARENT_PROXY: + { + proxySrc = ptr; + + TINYCLR_CHECK_HRESULT(proxySrc->TransparentProxyValidate()); + + idxVerify = proxySrc->TransparentProxyDereference()->ObjectCls(); + + if(proxySrc->TransparentProxyAppDomain() != appDomainDst) + { + //marshalling a transparent proxy object to a third AppDomain + //This makes the marshaling a simple assign of the DATATYPE_TRANSPARENT_PROXY heapblock + fSimpleAssign = true; + } + } + break; + case DATATYPE_CLASS: + { + CLR_RT_TypeDef_Instance inst; + + if(inst.InitializeFromIndex( ptr->ObjectCls() )) + { + if((inst.CrossReference().m_flags & CLR_RT_TypeDef_CrossReference::TD_CR_IsMarshalByRefObject) != 0) + { + idxVerify = inst; + + mbroSrc = ptr; + } + } + } + break; + } + } + } + + TINYCLR_CHECK_HRESULT(appDomainDst->VerifyTypeIsLoaded( idxVerify )); + + if(fSimpleAssign) + { + dst.Assign( src ); + } + else if(proxySrc != NULL) + { + //src is OBJECT->TRANSPARENT_PROXY->CLASS, and we are marshalling into 'this' appDomain + //dst is OBJECT->CLASS + _ASSERTE(proxySrc->TransparentProxyAppDomain() == appDomainDst); + + dst.SetObjectReference( proxySrc->TransparentProxyDereference() ); + } + else if(mbroSrc != NULL) + { + //src is a MarshalByRefObject that we are marshalling outside of its AppDomain + //src is OBJECT->CLASS + //dst is OBJECT->TRANSPARENT_PROXY->CLASS + + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomainDst ); + CLR_RT_HeapBlock* proxyDst = g_CLR_RT_ExecutionEngine.ExtractHeapBlocksForObjects( DATATYPE_TRANSPARENT_PROXY, 0, 1 ); CHECK_ALLOCATION(proxyDst); + + proxyDst->SetTransparentProxyReference( appDomainSrc, mbroSrc ); + dst.SetObjectReference( proxyDst ); + } + else + { + CLR_RT_HeapBlock blk; blk.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( blk ); + bool fNoCompaction = CLR_EE_DBG_IS(NoCompaction); + + //Need to prevent compaction between serialization/deserialization. + //Doesn't seem that currently compaction can actually occur during this time, + //but just to be safe, we should prevent it. + + CLR_EE_DBG_SET(NoCompaction); + TINYCLR_CHECK_HRESULT(CLR_RT_BinaryFormatter::Serialize( blk, src, NULL, CLR_RT_BinaryFormatter::c_Flags_Marshal )); + + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomainDst ); + hr = CLR_RT_BinaryFormatter::Deserialize( dst, blk, NULL, NULL, CLR_RT_BinaryFormatter::c_Flags_Marshal ); + + CLR_EE_DBG_RESTORE(NoCompaction,fNoCompaction); + } + + TINYCLR_CLEANUP(); + + (void)g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomainSav ); + + TINYCLR_CLEANUP_END(); +} + +HRESULT CLR_RT_AppDomain::MarshalParameters( CLR_RT_HeapBlock* callerArgs, CLR_RT_HeapBlock* calleeArgs, int count, bool fOnReturn, CLR_RT_AppDomain* appDomainSrc ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock* src = fOnReturn ? calleeArgs : callerArgs; + CLR_RT_HeapBlock* dst = fOnReturn ? callerArgs : calleeArgs; + + while(count-- > 0) + { + CLR_DataType dtSrc = src->DataType(); + CLR_DataType dtDst = dst->DataType(); + + if(dtSrc == DATATYPE_BYREF || dtSrc == DATATYPE_ARRAY_BYREF) + { + CLR_RT_HeapBlock srcObj; + CLR_RT_HeapBlock dstObj; + + if(fOnReturn) + { + srcObj.Assign( *src->Dereference() ); + + TINYCLR_CHECK_HRESULT(MarshalObject( srcObj, dstObj, appDomainSrc )); + + //Move the marshaled object back into dst heapblock + if(dtDst == DATATYPE_BYREF) + { + dst->Dereference()->Assign( dstObj ); + } + else + { + dstObj.StoreToReference( *dst, 0 ); + } + } + else //!fOnReturn + { + CLR_RT_HeapBlock* dstPtr = NULL; + + if(dtSrc == DATATYPE_BYREF) + { + srcObj.Assign( *src->Dereference() ); + } + else + { + srcObj.LoadFromReference( *src ); + } + + TINYCLR_CHECK_HRESULT(MarshalObject( srcObj, dstObj, appDomainSrc )); + + //Need to copy DstObj onto the heap. + dstPtr = g_CLR_RT_ExecutionEngine.ExtractHeapBlocksForObjects( DATATYPE_OBJECT, 0, 1 ); FAULT_ON_NULL(dstPtr); + + _ASSERTE(c_CLR_RT_DataTypeLookup[ dstObj.DataType() ].m_sizeInBytes != CLR_RT_DataTypeLookup::c_NA); + + dstPtr->Assign( dstObj ); + + //Turn the OBJECT back into a BYREF + dst->SetReference( *dstPtr ); + } + } + else //Not BYREF + { + if(!fOnReturn) + { + TINYCLR_CHECK_HRESULT(MarshalObject( *src, *dst, appDomainSrc )); + } + } + + src++; + dst++; + } + + TINYCLR_NOCLEANUP(); +} + + +HRESULT CLR_RT_AppDomain::GetAssemblies( CLR_RT_HeapBlock& ref ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + int count = 0; + CLR_RT_HeapBlock* pArray = NULL; + + for(int pass=0; pass<2; pass++) + { + TINYCLR_FOREACH_ASSEMBLY_IN_APPDOMAIN( this ) + { + if(pASSM->m_header->flags & CLR_RECORD_ASSEMBLY::c_Flags_Patch) continue; + + if(pass == 0) + { + count++; + } + else + { + CLR_RT_HeapBlock* hbObj; + CLR_RT_Assembly_Index idx; idx.Set( pASSM->m_idx ); + + TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex(*pArray, g_CLR_RT_WellKnownTypes.m_Assembly)); + hbObj = pArray->Dereference(); + + hbObj->SetReflection( idx ); + + pArray++; + } + } + TINYCLR_FOREACH_ASSEMBLY_IN_APPDOMAIN_END(); + + if(pass == 0) + { + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( ref, count, g_CLR_RT_WellKnownTypes.m_Assembly )); + + pArray = (CLR_RT_HeapBlock*)ref.DereferenceArray()->GetFirstElement(); + } + } + + TINYCLR_NOCLEANUP(); +} + +bool CLR_RT_AppDomain::IsLoaded() +{ + NATIVE_PROFILE_CLR_CORE(); + return m_state == CLR_RT_AppDomain::AppDomainState_Loaded; +} + +//--// + +HRESULT CLR_RT_AppDomainAssembly::CreateInstance( CLR_RT_AppDomain* appDomain, CLR_RT_Assembly* assm, CLR_RT_AppDomainAssembly*& appDomainAssembly ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + int size = CONVERTFROMSIZETOHEAPBLOCKS(sizeof(CLR_RT_AppDomainAssembly)) + assm->m_iStaticFields; + + appDomainAssembly = EVENTCACHE_EXTRACT_NODE_AS_BLOCKS(g_CLR_RT_EventCache,CLR_RT_AppDomainAssembly,DATATYPE_APPDOMAIN_ASSEMBLY,CLR_RT_HeapBlock::HB_InitializeToZero,size); CHECK_ALLOCATION(appDomainAssembly); + + TINYCLR_CHECK_HRESULT(appDomainAssembly->AppDomainAssembly_Initialize( appDomain, assm )); + + TINYCLR_CLEANUP(); + + if(FAILED(hr)) + { + if(appDomainAssembly) + { + appDomainAssembly->DestroyInstance(); + } + } + + TINYCLR_CLEANUP_END(); +} + +HRESULT CLR_RT_AppDomainAssembly::AppDomainAssembly_Initialize( CLR_RT_AppDomain* appDomain, CLR_RT_Assembly* assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_AppDomain* appDomainSav = g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomain ); + + m_appDomain = appDomain; + m_assembly = assm; + m_flags = 0; + m_pStaticFields = (CLR_RT_HeapBlock*)&this[ 1 ]; + + /* + The AppDomainAssembly gets linked before it is actually initialized, for two reasons. First, it needs to be + attached to the AppDomain in case a GC runs during the allocation of fields. Second, this assembly needs to be + loaded in the AppDomain when the static constructors are run. + */ + + appDomain->m_appDomainAssemblies.LinkAtBack( this ); + + TINYCLR_CHECK_HRESULT(assm->Resolve_AllocateStaticFields( m_pStaticFields )); + + if(!CLR_EE_DBG_IS_MASK(State_Initialize,State_Mask)) + { + //Only in the non-boot case should we do this. Otherwise, debug events can occur out of order (thread creation of the + //static constructor before thread creation of the main thread. + g_CLR_RT_ExecutionEngine.SpawnStaticConstructor( g_CLR_RT_ExecutionEngine.m_cctorThread ); + } + + TINYCLR_CLEANUP(); + + if(FAILED(hr)) + { + Unlink(); + } + + g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomainSav ); + + TINYCLR_CLEANUP_END(); +} + +void CLR_RT_AppDomainAssembly::DestroyInstance() +{ + NATIVE_PROFILE_CLR_CORE(); + Unlink(); + + g_CLR_RT_EventCache.Append_Node( this ); +} + +void CLR_RT_AppDomainAssembly::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_GarbageCollector::Heap_Relocate( m_pStaticFields, m_assembly->m_iStaticFields ); +} + +#endif //TINYCLR_APPDOMAINS + +//--// + + +struct TypeIndexLookup +{ + LPCSTR nameSpace; + LPCSTR name; + CLR_RT_TypeDef_Index* ptr; +}; + +static const TypeIndexLookup c_TypeIndexLookup[] = +{ +#define TIL(ns,nm,fld) { ns, nm, &g_CLR_RT_WellKnownTypes.fld } + TIL( "System" , "Boolean" , m_Boolean ), + TIL( "System" , "Char" , m_Char ), + TIL( "System" , "SByte" , m_Int8 ), + TIL( "System" , "Byte" , m_UInt8 ), + TIL( "System" , "Int16" , m_Int16 ), + TIL( "System" , "UInt16" , m_UInt16 ), + TIL( "System" , "Int32" , m_Int32 ), + TIL( "System" , "UInt32" , m_UInt32 ), + TIL( "System" , "Int64" , m_Int64 ), + TIL( "System" , "UInt64" , m_UInt64 ), + TIL( "System" , "Single" , m_Single ), + TIL( "System" , "Double" , m_Double ), + TIL( "System" , "DateTime" , m_DateTime ), + TIL( "System" , "TimeSpan" , m_TimeSpan ), + TIL( "System" , "String" , m_String ), + + TIL( "System" , "Void" , m_Void ), + TIL( "System" , "Object" , m_Object ), + TIL( "System" , "ValueType" , m_ValueType ), + TIL( "System" , "Enum" , m_Enum ), + + TIL( "System" , "AppDomainUnloadedException" , m_AppDomainUnloadedException ), + TIL( "System" , "ArgumentNullException" , m_ArgumentNullException ), + TIL( "System" , "ArgumentException" , m_ArgumentException ), + TIL( "System" , "ArgumentOutOfRangeException" , m_ArgumentOutOfRangeException ), + TIL( "System" , "Exception" , m_Exception ), + TIL( "System" , "IndexOutOfRangeException" , m_IndexOutOfRangeException ), + TIL( "System" , "InvalidCastException" , m_InvalidCastException ), + TIL( "System" , "InvalidOperationException" , m_InvalidOperationException ), + TIL( "System" , "NotSupportedException" , m_NotSupportedException ), + TIL( "System" , "NotImplementedException" , m_NotImplementedException ), + TIL( "System" , "NullReferenceException" , m_NullReferenceException ), + TIL( "System" , "OutOfMemoryException" , m_OutOfMemoryException ), + TIL( "System" , "ObjectDisposedException" , m_ObjectDisposedException ), + TIL( "System.IO" , "IOException" , m_IOException ), + TIL( "System.Threading" , "ThreadAbortException" , m_ThreadAbortException ), + TIL( "Microsoft.SPOT" , "ConstraintException" , m_ConstraintException ), + TIL( "Microsoft.SPOT" , "UnknownTypeException" , m_UnknownTypeException ), + + TIL( "System" , "Delegate" , m_Delegate ), + TIL( "System" , "MulticastDelegate" , m_MulticastDelegate ), + + TIL( "System" , "Array" , m_Array ), + TIL( "System.Collections" , "ArrayList" , m_ArrayList ), + TIL( "System" , "ICloneable" , m_ICloneable ), + TIL( "System.Collections" , "IList" , m_IList ), + + TIL( "System.Reflection" , "Assembly" , m_Assembly ), + TIL( "System" , "Type" , m_TypeStatic ), + TIL( "System" , "RuntimeType" , m_Type ), + TIL( "System.Reflection" , "RuntimeConstructorInfo" , m_ConstructorInfo ), + TIL( "System.Reflection" , "RuntimeMethodInfo" , m_MethodInfo ), + TIL( "System.Reflection" , "RuntimeFieldInfo" , m_FieldInfo ), + + TIL( "System" , "WeakReference" , m_WeakReference ), + TIL( "Microsoft.SPOT" , "ExtendedWeakReference" , m_ExtendedWeakReference ), + + TIL( "Microsoft.SPOT" , "SerializationHintsAttribute" , m_SerializationHintsAttribute ), + + TIL( "Microsoft.SPOT" , "ExtendedTimeZone" , m_ExtendedTimeZone ), + + TIL( "Microsoft.SPOT" , "Bitmap" , m_Bitmap ), + TIL( "Microsoft.SPOT" , "Font" , m_Font ), + + TIL( "Microsoft.SPOT.Touch" , "TouchEvent" , m_TouchEvent ), + TIL( "Microsoft.SPOT.Touch" , "TouchInput" , m_TouchInput ), + + TIL( "Microsoft.SPOT.Messaging", "Message" , m_Message ), + + TIL( "Microsoft.SPOT.Hardware" , "ScreenMetrics" , m_ScreenMetrics ), + + TIL( "Microsoft.SPOT.Hardware" , "WatchdogException" , m_WatchdogException ), + + TIL( "Microsoft.SPOT.Hardware" , "I2CDevice" , m_I2CDevice ), + TIL( NULL , "I2CReadTransaction" , m_I2CDevice__I2CReadTransaction ), + TIL( NULL , "I2CWriteTransaction" , m_I2CDevice__I2CWriteTransaction ), + + TIL( "Microsoft.SPOT.Hardware.UsbClient", "Configuration" , m_UsbClientConfiguration ), + TIL( NULL , "Descriptor" , m_UsbClientConfiguration__Descriptor ), + TIL( NULL , "DeviceDescriptor" , m_UsbClientConfiguration__DeviceDescriptor ), + TIL( NULL , "ClassDescriptor" , m_UsbClientConfiguration__ClassDescriptor ), + TIL( NULL , "Endpoint" , m_UsbClientConfiguration__Endpoint ), + TIL( NULL , "UsbInterface" , m_UsbClientConfiguration__UsbInterface ), + TIL( NULL , "ConfigurationDescriptor" , m_UsbClientConfiguration__ConfigurationDescriptor ), + TIL( NULL , "StringDescriptor" , m_UsbClientConfiguration__StringDescriptor ), + TIL( NULL , "GenericDescriptor" , m_UsbClientConfiguration__GenericDescriptor ), + + TIL( "Microsoft.SPOT.Net.NetworkInformation", "NetworkInterface" , m_NetworkInterface ), + TIL( "Microsoft.SPOT.Net.NetworkInformation", "Wireless80211" , m_Wireless80211 ), + + TIL( "Microsoft.SPOT.Time" , "TimeServiceSettings" , m_TimeServiceSettings ), + TIL( "Microsoft.SPOT.Time" , "TimeServiceStatus" , m_TimeServiceStatus ), + +#if defined(TINYCLR_APPDOMAINS) + TIL( "System" , "AppDomain" , m_AppDomain ), + TIL( "System" , "MarshalByRefObject" , m_MarshalByRefObject ), +#endif + + TIL( "System.Threading" , "Thread" , m_Thread ), + TIL( "System.Resources" , "ResourceManager" , m_ResourceManager ), + + TIL( "System.Net.Sockets" , "SocketException" , m_SocketException ), + + TIL( "Microsoft.SPOT.IO" , "NativeFileInfo" , m_NativeFileInfo ), + TIL( "Microsoft.SPOT.IO" , "VolumeInfo" , m_VolumeInfo ), + + TIL( "System.Xml" , "XmlNameTable_Entry" , m_XmlNameTable_Entry ), + TIL( "System.Xml" , "XmlReader_XmlNode" , m_XmlReader_XmlNode ), + TIL( "System.Xml" , "XmlReader_XmlAttribute" , m_XmlReader_XmlAttribute ), + TIL( "System.Xml" , "XmlReader_NamespaceEntry" , m_XmlReader_NamespaceEntry ), + + TIL( "System.Security.Cryptography", "CryptoKey" , m_CryptoKey ), + TIL( "Microsoft.SPOT.Cryptoki" , "CryptokiObject" , m_CryptokiObject ), + TIL( "Microsoft.SPOT.Cryptoki" , "Session" , m_CryptokiSession ), + TIL( "Microsoft.SPOT.Cryptoki" , "Slot" , m_CryptokiSlot ), + TIL( "Microsoft.SPOT.Cryptoki" , "MechanismType" , m_CryptokiMechanismType ), + TIL( "System.Security.Cryptography", "CryptographicException" , m_CryptoException ), + TIL( "Microsoft.SPOT.Cryptoki" , "CryptokiCertificate" , m_CryptokiCertificate ), + +#undef TIL +}; + + +//--// + + +struct MethodIndexLookup +{ + LPCSTR name; + CLR_RT_TypeDef_Index* type; + CLR_RT_MethodDef_Index* method; +}; + +static const MethodIndexLookup c_MethodIndexLookup[] = +{ + #define MIL(nm,type,method) { nm, &g_CLR_RT_WellKnownTypes.type, &g_CLR_RT_WellKnownMethods.method } + + MIL( "GetObjectFromId" , m_ResourceManager, m_ResourceManager_GetObjectFromId ), + MIL( "GetObjectChunkFromId", m_ResourceManager, m_ResourceManager_GetObjectChunkFromId ), + + #undef MIL +}; + +void CLR_RT_Assembly::Resolve_TypeDef() +{ + NATIVE_PROFILE_CLR_CORE(); + const TypeIndexLookup* tilOuterClass = NULL; + const TypeIndexLookup* til = c_TypeIndexLookup; + + for(size_t i=0; iptr; + + if(TINYCLR_INDEX_IS_INVALID(dst)) + { + if(til->nameSpace == NULL) + { + if(tilOuterClass) + { + FindTypeDef( til->name, tilOuterClass->ptr->Type(), dst ); + } + } + else + { + FindTypeDef( til->name, til->nameSpace, dst ); + } + } + + if(til->nameSpace != NULL) + { + tilOuterClass = til; + } + } +} + +void CLR_RT_Assembly::Resolve_MethodDef() +{ + NATIVE_PROFILE_CLR_CORE(); + const CLR_RECORD_METHODDEF* md = GetMethodDef( 0 ); + + for(int i=0; itype; + CLR_RT_MethodDef_Index& idxMethod = *mil->method; + + if(TINYCLR_INDEX_IS_VALID(idxType) && TINYCLR_INDEX_IS_INVALID(idxMethod)) + { + CLR_RT_TypeDef_Instance instType; + + _SIDE_ASSERTE(instType.InitializeFromIndex( idxType )); + + if(instType.m_assm == this) + { + if(!strcmp( GetString(md->name), mil->name )) + { + idxMethod.m_data = idx.m_data; + } + } + } + } + + if(md->flags & CLR_RECORD_METHODDEF::MD_EntryPoint) + { + g_CLR_RT_TypeSystem.m_entryPoint = idx; + } + } +} + +HRESULT CLR_RT_Assembly::Resolve_AllocateStaticFields( CLR_RT_HeapBlock* pStaticFields ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + const CLR_RECORD_FIELDDEF* fd = GetFieldDef( 0 ); + + for(int i=0; iflags & CLR_RECORD_FIELDDEF::FD_Static) + { + CLR_RT_FieldDef_CrossReference& res = m_pCrossReference_FieldDef[ i ]; + + TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.InitializeReference( pStaticFields[ res.m_offset ], fd, this )); + } + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_Assembly::PrepareForExecution() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + if((m_flags & CLR_RT_Assembly::c_PreparingForExecution) != 0) + { + //Circular dependency + _ASSERTE(FALSE); + + TINYCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + if((m_flags & CLR_RT_Assembly::c_PreparedForExecution) == 0) + { + int i; + + m_flags |= CLR_RT_Assembly::c_PreparingForExecution; + + ITERATE_THROUGH_RECORDS(this,i,AssemblyRef,ASSEMBLYREF) + { + _ASSERTE(dst->m_target != NULL); + + if(dst->m_target != NULL) + { + TINYCLR_CHECK_HRESULT(dst->m_target->PrepareForExecution()); + } + } + + if(m_header->patchEntryOffset != 0xFFFFFFFF) + { + CLR_PMETADATA ptr = GetResourceData( m_header->patchEntryOffset ); + +#if defined(WIN32) + CLR_Debug::Printf( "Simulating jump into patch code...\r\n" ); +#else + ((void (*)())ptr)(); +#endif + } + +#if defined(TINYCLR_APPDOMAINS) + //Temporary solution. All Assemblies get added to the current AppDomain + //Which assemblies get loaded at boot, and when assemblies get added to AppDomain at runtime is + //not yet determined/implemented + + TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.GetCurrentAppDomain()->LoadAssembly( this )); +#endif + } + + TINYCLR_CLEANUP(); + + //Only try once. If this fails, then what? + m_flags |= CLR_RT_Assembly::c_PreparedForExecution; + m_flags &= ~CLR_RT_Assembly::c_PreparingForExecution; + + TINYCLR_CLEANUP_END(); +} + +//--// + +CLR_UINT32 CLR_RT_Assembly::ComputeAssemblyHash() +{ + NATIVE_PROFILE_CLR_CORE(); + return m_header->ComputeAssemblyHash( m_szName, m_header->version ); +} + +CLR_UINT32 CLR_RT_Assembly::ComputeAssemblyHash( const CLR_RECORD_ASSEMBLYREF* ar ) +{ + NATIVE_PROFILE_CLR_CORE(); + return m_header->ComputeAssemblyHash( GetString( ar->name ), ar->version ); +} + +//--// + +bool CLR_RT_Assembly::FindTypeDef( LPCSTR name, LPCSTR nameSpace, CLR_RT_TypeDef_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + const CLR_RECORD_TYPEDEF* target = GetTypeDef( 0 ); + int tblSize = m_pTablesSize[ TBL_TypeDef ]; + + for(int i=0; ienclosingType == CLR_EmptyIndex) + { + LPCSTR szNameSpace = GetString( target->nameSpace ); + LPCSTR szName = GetString( target->name ); + + if(!strcmp( szName, name ) && !strcmp( szNameSpace, nameSpace )) + { + idx.Set( m_idx, i ); + + return true; + } + } + } + + idx.Clear(); + + return false; +} + +bool CLR_RT_Assembly::FindTypeDef( LPCSTR name, CLR_IDX scope, CLR_RT_TypeDef_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + const CLR_RECORD_TYPEDEF* target = GetTypeDef( 0 ); + int tblSize = m_pTablesSize[ TBL_TypeDef ]; + + for(int i=0; ienclosingType == scope) + { + LPCSTR szName = GetString( target->name ); + + if(!strcmp( szName, name )) + { + idx.Set( m_idx, i ); + + return true; + } + } + } + + idx.Clear(); + + return false; +} + +bool CLR_RT_Assembly::FindTypeDef( CLR_UINT32 hash, CLR_RT_TypeDef_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_TypeDef_CrossReference* p = m_pCrossReference_TypeDef; + CLR_UINT32 tblSize = m_pTablesSize[ TBL_TypeDef ]; + CLR_UINT32 i; + + for(i=0; im_hash == hash) break; + } + + if(i != tblSize) + { + idx.Set( m_idx, i ); + + return true; + } + else + { + idx.Clear(); + + return false; + } +} + +//--// + +static bool local_FindFieldDef( CLR_RT_Assembly* assm, CLR_UINT32 first, CLR_UINT32 num, LPCSTR szText, CLR_RT_Assembly* base, CLR_IDX sig, CLR_RT_FieldDef_Index& res ) +{ + NATIVE_PROFILE_CLR_CORE(); + const CLR_RECORD_FIELDDEF* fd = assm->GetFieldDef( first ); + + for(CLR_UINT32 i=0; iGetString( fd->name ); + + if(!strcmp( fieldName, szText )) + { + if(base) + { + CLR_RT_SignatureParser parserLeft ; parserLeft .Initialize_FieldDef( assm, fd ); + CLR_RT_SignatureParser parserRight; parserRight.Initialize_FieldDef( base, base->GetSignature( sig ) ); + + if(CLR_RT_TypeSystem::MatchSignature( parserLeft, parserRight ) == false) continue; + } + + res.Set( assm->m_idx, first + i ); + + return true; + } + } + + res.Clear(); + + return false; +} + +bool CLR_RT_Assembly::FindFieldDef( const CLR_RECORD_TYPEDEF* td, LPCSTR name, CLR_RT_Assembly* base, CLR_IDX sig, CLR_RT_FieldDef_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(local_FindFieldDef( this, td->iFields_First, td->iFields_Num, name, base, sig, idx )) return true; + if(local_FindFieldDef( this, td->sFields_First, td->sFields_Num, name, base, sig, idx )) return true; + + idx.Clear(); + + return false; +} + +bool CLR_RT_Assembly::FindMethodDef( const CLR_RECORD_TYPEDEF* td, LPCSTR name, CLR_RT_Assembly* base, CLR_SIG sig, CLR_RT_MethodDef_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + int i; + int num = td->vMethods_Num + td->iMethods_Num + td->sMethods_Num; + const CLR_RECORD_METHODDEF* md = GetMethodDef( td->methods_First ); + + for(i=0; iname ); + + if(!strcmp( methodName, name )) + { + bool fMatch = true; + + if(CLR_SIG_INVALID != sig) + { + CLR_RT_SignatureParser parserLeft ; parserLeft .Initialize_MethodSignature( this, md ); + CLR_RT_SignatureParser parserRight; parserRight.Initialize_MethodSignature( base, base->GetSignature( sig ) ); + + fMatch = CLR_RT_TypeSystem::MatchSignature( parserLeft, parserRight ); + } + + if(fMatch) + { + idx.Set( m_idx, i + td->methods_First ); + + return true; + } + } + } + + idx.Clear(); + + return false; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +bool CLR_RT_Assembly::FindMethodBoundaries( CLR_IDX i, CLR_OFFSET& start, CLR_OFFSET& end ) +{ + NATIVE_PROFILE_CLR_CORE(); + const CLR_RECORD_METHODDEF* p = GetMethodDef( i ); + + if(p->RVA == CLR_EmptyIndex) return false; + + start = p->RVA; + + while(true) + { + p++; + i++; + + if(i == m_pTablesSize[ TBL_MethodDef ]) + { + end = m_pTablesSize[ TBL_ByteCode ]; + break; + } + + if(p->RVA != CLR_EmptyIndex) + { + end = p->RVA; + break; + } + } + + return true; +} + +bool CLR_RT_Assembly::FindNextStaticConstructor( CLR_RT_MethodDef_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + _ASSERTE(m_idx == idx.Assembly()); + + for(int i=idx.Method(); iflags & CLR_RECORD_METHODDEF::MD_StaticConstructor) + { + return true; + } + } + + idx.Clear(); + return false; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_Assembly::Resolve_ComputeHashes() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + const CLR_RECORD_TYPEDEF* src = GetTypeDef( 0 ); + CLR_RT_TypeDef_CrossReference* dst = m_pCrossReference_TypeDef; + + for(int i=0; iGetFieldDef( target->iFields_First ); + + for(int j=0; jiFields_Num; j++, fd++) + { + if((fd->flags & CLR_RECORD_FIELDDEF::FD_NotSerialized) == 0) + { + CLR_RT_SignatureParser parser; parser.Initialize_FieldDef( inst.m_assm, fd ); + CLR_RT_SignatureParser::Element res; + + TINYCLR_CHECK_HRESULT(parser.Advance( res )); + + while(res.m_levels-- > 0) + { + hash = ComputeHashForType( DATATYPE_SZARRAY, hash ); + } + + hash = ComputeHashForType( res.m_dt, hash ); + + switch(res.m_dt) + { + case DATATYPE_VALUETYPE: + case DATATYPE_CLASS : + hash = ComputeHashForName( res.m_cls, hash ); + break; + } + + LPCSTR fieldName = inst.m_assm->GetString( fd->name ); + + hash = SUPPORT_ComputeCRC( fieldName, (CLR_UINT32)hal_strlen_s(fieldName), hash ); + } + } + + inst.SwitchToParent(); + } + + dst->m_hash = hash ? hash : 0xFFFFFFFF; // Don't allow zero as an hash value!! + } + + TINYCLR_NOCLEANUP(); +} + +CLR_UINT32 CLR_RT_Assembly::ComputeHashForName( const CLR_RT_TypeDef_Index& td, CLR_UINT32 hash ) +{ + NATIVE_PROFILE_CLR_CORE(); + char rgBuffer[ 512 ]; + LPSTR szBuffer = rgBuffer; + size_t iBuffer = MAXSTRLEN(rgBuffer); + + g_CLR_RT_TypeSystem.BuildTypeName( td, szBuffer, iBuffer ); + + CLR_UINT32 hashPost = SUPPORT_ComputeCRC( rgBuffer, (int)(MAXSTRLEN(rgBuffer) - iBuffer), hash ); + + return hashPost; +} + +CLR_UINT32 CLR_RT_Assembly::ComputeHashForType( CLR_DataType et, CLR_UINT32 hash ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_UINT8 val = (CLR_UINT8)CLR_RT_TypeSystem::MapDataTypeToElementType( et ); + + CLR_UINT32 hashPost = SUPPORT_ComputeCRC( &val, sizeof(val), hash ); + + return hashPost; +} + +//--// + +CLR_RT_HeapBlock* CLR_RT_Assembly::GetStaticField( const int index ) +{ + NATIVE_PROFILE_CLR_CORE(); + +#if defined(TINYCLR_APPDOMAINS) + + CLR_RT_AppDomainAssembly* adAssm = g_CLR_RT_ExecutionEngine.GetCurrentAppDomain()->FindAppDomainAssembly( this ); + + _ASSERTE(adAssm); + + return &adAssm->m_pStaticFields[ index ]; + +#else + + return &m_pStaticFields[ index ]; + +#endif +} + +//--// + +void CLR_RT_Assembly::Relocate() +{ + NATIVE_PROFILE_CLR_CORE(); + +#if !defined(TINYCLR_APPDOMAINS) + CLR_RT_GarbageCollector::Heap_Relocate( m_pStaticFields, m_iStaticFields ); +#endif + + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_header ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_szName ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_pFile ); + CLR_RT_GarbageCollector::Heap_Relocate( (void**)&m_nativeCode ); +} + +HRESULT CLR_RT_Assembly::VerifyEndian(CLR_RECORD_ASSEMBLY* header) +{ + UINT32 u = 0x1234567; + UINT8 *t = (UINT8*)&u; + BOOL localIsBE=false; + BOOL assyIsBE=false; + + TINYCLR_HEADER(); + + // Is this a Big Endian system? + if ( 0x12!=*t) + { + localIsBE=true; + } + + if( (header->flags & CLR_RECORD_ASSEMBLY::c_Flags_BigEndian) == CLR_RECORD_ASSEMBLY::c_Flags_BigEndian ) + { + assyIsBE=true; + } + + if (assyIsBE==localIsBE) + { + TINYCLR_SET_AND_LEAVE(S_OK); + } + else + { + TINYCLR_SET_AND_LEAVE(S_FALSE); + } + + TINYCLR_NOCLEANUP(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_TypeSystem::TypeSystem_Initialize() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_CLEAR(g_CLR_RT_TypeSystem); + TINYCLR_CLEAR(g_CLR_RT_WellKnownTypes); +} + +void CLR_RT_TypeSystem::TypeSystem_Cleanup() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_FOREACH_ASSEMBLY(*this) + { + pASSM->DestroyInstance(); + + *ppASSM = NULL; + } + TINYCLR_FOREACH_ASSEMBLY_END(); + + m_assembliesMax = 0; +} + +//--// + +void CLR_RT_TypeSystem::Link( CLR_RT_Assembly* assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_FOREACH_ASSEMBLY_NULL(*this) + { + *ppASSM = assm; + + assm->m_idx = idx; + + PostLinkageProcessing( assm ); + + if(m_assembliesMax < idx) m_assembliesMax = idx; + + return; + } + TINYCLR_FOREACH_ASSEMBLY_NULL_END(); +} + +void CLR_RT_TypeSystem::PostLinkageProcessing( CLR_RT_Assembly* assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(!strcmp( assm->m_szName, "mscorlib" )) + { + m_assemblyMscorlib = assm; + } + if(!strcmp( assm->m_szName, "Microsoft.SPOT.Native" )) + { + m_assemblyNative = assm; + } +} + +CLR_RT_Assembly* CLR_RT_TypeSystem::FindAssembly( LPCSTR szName, const CLR_RECORD_VERSION* ver, bool fExact ) +{ + NATIVE_PROFILE_CLR_CORE(); + + TINYCLR_FOREACH_ASSEMBLY(*this) + { + if(!strcmp(pASSM->m_szName, szName)) + { + // if there is no version information, anything goes + if(NULL == ver) + { + return pASSM; + } + // exact match must take into accoutn all numbers + else if(fExact) + { + if(0 == memcmp( &pASSM->m_header->version, ver, sizeof(*ver) )) + { + return pASSM; + } + } + // if excet match is not required but still we have version we will enforce only the first two number because by convention + // we increse the minor numbers when native assemblies change CRC + else if( + ver->iMajorVersion == pASSM->m_header->version.iMajorVersion && + ver->iMinorVersion == pASSM->m_header->version.iMinorVersion + ) + { + return pASSM; + } + } + } + TINYCLR_FOREACH_ASSEMBLY_END(); + + return NULL; +} + +bool CLR_RT_TypeSystem::FindTypeDef( LPCSTR name, LPCSTR nameSpace, CLR_RT_Assembly* assm, CLR_RT_TypeDef_Index& res ) +{ + NATIVE_PROFILE_CLR_CORE(); + + if(assm) + { + TINYCLR_FOREACH_ASSEMBLY_IN_CURRENT_APPDOMAIN(*this) + { + if(pASSM->IsSameAssembly( *assm ) && pASSM->FindTypeDef( name, nameSpace, res )) return true; + } + TINYCLR_FOREACH_ASSEMBLY_IN_CURRENT_APPDOMAIN_END(); + + res.Clear(); + + return false; + } + + return FindTypeDef( name, nameSpace, res); +} + +bool CLR_RT_TypeSystem::FindTypeDef( LPCSTR name, LPCSTR nameSpace, CLR_RT_TypeDef_Index& res ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_FOREACH_ASSEMBLY_IN_CURRENT_APPDOMAIN(*this) + { + if(pASSM->FindTypeDef( name, nameSpace, res )) return true; + } + TINYCLR_FOREACH_ASSEMBLY_IN_CURRENT_APPDOMAIN_END(); + + res.Clear(); + return false; +} + +bool CLR_RT_TypeSystem::FindTypeDef( CLR_UINT32 hash, CLR_RT_TypeDef_Index& res ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_FOREACH_ASSEMBLY_IN_CURRENT_APPDOMAIN(*this) + { + if(pASSM->FindTypeDef( hash, res )) return true; + } + TINYCLR_FOREACH_ASSEMBLY_IN_CURRENT_APPDOMAIN_END(); + + res.Clear(); + return false; +} + +bool CLR_RT_TypeSystem::FindTypeDef( LPCSTR szClass, CLR_RT_Assembly* assm, CLR_RT_TypeDef_Index& res ) +{ + NATIVE_PROFILE_CLR_CORE(); + char rgName [ MAXTYPENAMELEN ]; + char rgNamespace[ MAXTYPENAMELEN ]; + + if(hal_strlen_s(szClass) < ARRAYSIZE(rgNamespace)) + { + LPCSTR szPtr = szClass; + LPCSTR szPtr_LastDot = NULL; + LPCSTR szPtr_FirstSubType = NULL; + char c; + size_t len; + + while(true) + { + c = szPtr[ 0 ]; if(!c) break; + + if(c == '.') + { + szPtr_LastDot = szPtr; + } + else if(c == '+') + { + szPtr_FirstSubType = szPtr; + break; + } + + szPtr++; + } + + if(szPtr_LastDot) + { + len = szPtr_LastDot++ - szClass ; hal_strncpy_s( rgNamespace, ARRAYSIZE(rgNamespace), szClass , len ); + len = szPtr - szPtr_LastDot; hal_strncpy_s( rgName , ARRAYSIZE(rgName ), szPtr_LastDot, len ); + } + else + { + rgNamespace[ 0 ] = 0; + hal_strcpy_s( rgName, ARRAYSIZE(rgName), szClass ); + } + + + if(FindTypeDef( rgName, rgNamespace, assm, res )) + { + // + // Found the containing type, let's look for the nested type. + // + if(szPtr_FirstSubType) + { + CLR_RT_TypeDef_Instance inst; + + do + { + szPtr = ++szPtr_FirstSubType; + + while(true) + { + c = szPtr_FirstSubType[ 0 ]; if(!c) break; + + if(c == '+') break; + + szPtr_FirstSubType++; + } + + len = szPtr_FirstSubType - szPtr; hal_strncpy_s( rgName, ARRAYSIZE(rgName), szPtr, len ); + + inst.InitializeFromIndex( res ); + + if(inst.m_assm->FindTypeDef( rgName, res.Type(), res ) == false) + { + return false; + } + + } while(c == '+'); + } + + return true; + } + } + + res.Clear(); + + return false; +} + +bool CLR_RT_TypeSystem::FindTypeDef( LPCSTR szClass, CLR_RT_Assembly* assm, CLR_RT_ReflectionDef_Index& reflex ) +{ + NATIVE_PROFILE_CLR_CORE(); + char rgName [ MAXTYPENAMELEN ]; + char rgNamespace[ MAXTYPENAMELEN ]; + CLR_RT_TypeDef_Index res; + + if(hal_strlen_s(szClass) < ARRAYSIZE(rgNamespace)) + { + LPCSTR szPtr = szClass; + LPCSTR szPtr_LastDot = NULL; + LPCSTR szPtr_FirstSubType = NULL; + char c; + size_t len; + bool arrayType = false; + + while(true) + { + c = szPtr[ 0 ]; if(!c) break; + + if(c == '.') + { + szPtr_LastDot = szPtr; + } + else if(c == '+') + { + szPtr_FirstSubType = szPtr; + break; + } + else if(c == '[') + { + char ch = szPtr[ 1 ]; + if (ch == ']') + { + arrayType = true; + break; + } + } + + szPtr++; + } + + if(szPtr_LastDot) + { + len = szPtr_LastDot++ - szClass ; hal_strncpy_s( rgNamespace, ARRAYSIZE(rgNamespace), szClass , len ); + len = szPtr - szPtr_LastDot; hal_strncpy_s( rgName , ARRAYSIZE(rgName ), szPtr_LastDot, len ); + } + else + { + rgNamespace[ 0 ] = 0; + hal_strcpy_s( rgName, ARRAYSIZE(rgName), szClass ); + } + + if(FindTypeDef( rgName, rgNamespace, assm, res )) + { + // + // Found the containing type, let's look for the nested type. + // + if(szPtr_FirstSubType) + { + CLR_RT_TypeDef_Instance inst; + + do + { + szPtr = ++szPtr_FirstSubType; + + while(true) + { + c = szPtr_FirstSubType[ 0 ]; if(!c) break; + + if(c == '+') break; + + szPtr_FirstSubType++; + } + + len = szPtr_FirstSubType - szPtr; hal_strncpy_s( rgName, ARRAYSIZE(rgName), szPtr, len ); + + inst.InitializeFromIndex( res ); + + if(inst.m_assm->FindTypeDef( rgName, res.Type(), res ) == false) + { + return false; + } + + } while(c == '+'); + } + + reflex.m_kind = REFLECTION_TYPE; + // make sure this works for multidimensional arrays. + reflex.m_levels = arrayType ? 1 : 0; + reflex.m_data.m_type = res; + return true; + } + } + + res.Clear(); + + return false; +} + +//--// + +int +#if defined(_MSC_VER) +__cdecl +#endif +CompareResource( const void* p1, const void* p2 ) +{ + NATIVE_PROFILE_CLR_CORE(); + const CLR_RECORD_RESOURCE* resource1 = (const CLR_RECORD_RESOURCE*)p1; + const CLR_RECORD_RESOURCE* resource2 = (const CLR_RECORD_RESOURCE*)p2; + + return (int)resource1->id - (int)resource2->id; +} + +HRESULT CLR_RT_TypeSystem::LocateResourceFile( CLR_RT_Assembly_Instance assm, LPCSTR name, CLR_INT32& idxResourceFile ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_Assembly* pAssm = assm.m_assm; + + for(idxResourceFile = 0; idxResourceFile < pAssm->m_pTablesSize[ TBL_ResourcesFiles ]; idxResourceFile++) + { + const CLR_RECORD_RESOURCE_FILE* resourceFile = pAssm->GetResourceFile( idxResourceFile ); + + if(!strcmp( pAssm->GetString( resourceFile->name ), name )) + { + TINYCLR_SET_AND_LEAVE(S_OK); + } + } + + idxResourceFile = -1; + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_TypeSystem::LocateResource( CLR_RT_Assembly_Instance assm, CLR_INT32 idxResourceFile, CLR_INT16 id, const CLR_RECORD_RESOURCE*& res, CLR_UINT32& size ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_Assembly* pAssm = assm.m_assm; + const CLR_RECORD_RESOURCE_FILE* resourceFile; + CLR_RECORD_RESOURCE resourceT; + const CLR_RECORD_RESOURCE* resNext; + const CLR_RECORD_RESOURCE* resZero; + + res = NULL; + size = 0; + + if(idxResourceFile < 0 || idxResourceFile >= pAssm->m_pTablesSize[ TBL_ResourcesFiles ]) TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + resourceFile = pAssm->GetResourceFile( idxResourceFile ); + + _ASSERTE(resourceFile->numberOfResources > 0); + + resZero = pAssm->GetResource( resourceFile->offset ); + + resourceT.id = id; + + res = (const CLR_RECORD_RESOURCE*)bsearch( &resourceT, resZero, resourceFile->numberOfResources, sizeof(CLR_RECORD_RESOURCE), CompareResource ); + + if(res != NULL) + { + //compute size here... + //assert not the last resource + _ASSERTE(res + 1 <= pAssm->GetResource( pAssm->m_pTablesSize[ TBL_Resources ] - 1)); + resNext = res+1; + + size = resNext->offset - res->offset; + + //deal with alignment. + size -= (resNext->flags & CLR_RECORD_RESOURCE::FLAGS_PaddingMask); + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_TypeSystem::ResolveAll() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + bool fOutput = false; + + while(true) + { + bool fGot = false; + bool fNeedResolution = false; + + TINYCLR_FOREACH_ASSEMBLY(*this) + { + if((pASSM->m_flags & CLR_RT_Assembly::c_Resolved) == 0) + { + fNeedResolution = true; + + if(pASSM->Resolve_AssemblyRef( fOutput )) + { + fGot = true; + + pASSM->m_flags |= CLR_RT_Assembly::c_Resolved; + + TINYCLR_CHECK_HRESULT(pASSM->Resolve_TypeRef ()); + TINYCLR_CHECK_HRESULT(pASSM->Resolve_FieldRef ()); + TINYCLR_CHECK_HRESULT(pASSM->Resolve_MethodRef ()); + /********************/pASSM->Resolve_TypeDef () ; + /********************/pASSM->Resolve_MethodDef () ; + /********************/pASSM->Resolve_Link () ; + TINYCLR_CHECK_HRESULT(pASSM->Resolve_ComputeHashes ()); + +#if !defined(TINYCLR_APPDOMAINS) + TINYCLR_CHECK_HRESULT(pASSM->Resolve_AllocateStaticFields( pASSM->m_pStaticFields )); +#endif + + pASSM->m_flags |= CLR_RT_Assembly::c_ResolutionCompleted; + } + } + } + TINYCLR_FOREACH_ASSEMBLY_END(); + + if(fOutput == true) + { + TINYCLR_SET_AND_LEAVE(CLR_E_TYPE_UNAVAILABLE); + } + + if(fGot == false) + { + if(fNeedResolution) + { +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Link failure: some assembly references cannot be resolved!!\r\n\r\n" ); +#endif + + fOutput = true; + } + else + { + break; + } + } + } + +#if !defined(BUILD_RTM) + + if(s_CLR_RT_fTrace_AssemblyOverhead >= c_CLR_RT_Trace_Info) + { + { + int pTablesSize[ TBL_Max ]; memset( pTablesSize, 0, sizeof(pTablesSize) ); + CLR_RT_Assembly::Offsets offsets ; memset( &offsets , 0, sizeof(offsets ) ); + + size_t iStaticFields = 0 ; + size_t iTotalRamSize = 0 ; + size_t iTotalRomSize = 0 ; + size_t iMetaData = 0 ; + + TINYCLR_FOREACH_ASSEMBLY(*this) + { + offsets.iBase += ROUNDTOMULTIPLE(sizeof(CLR_RT_Assembly) , CLR_UINT32); + offsets.iAssemblyRef += ROUNDTOMULTIPLE(pASSM->m_pTablesSize[ TBL_AssemblyRef ] * sizeof(CLR_RT_AssemblyRef_CrossReference), CLR_UINT32); + offsets.iTypeRef += ROUNDTOMULTIPLE(pASSM->m_pTablesSize[ TBL_TypeRef ] * sizeof(CLR_RT_TypeRef_CrossReference ), CLR_UINT32); + offsets.iFieldRef += ROUNDTOMULTIPLE(pASSM->m_pTablesSize[ TBL_FieldRef ] * sizeof(CLR_RT_FieldRef_CrossReference ), CLR_UINT32); + offsets.iMethodRef += ROUNDTOMULTIPLE(pASSM->m_pTablesSize[ TBL_MethodRef ] * sizeof(CLR_RT_MethodRef_CrossReference ), CLR_UINT32); + offsets.iTypeDef += ROUNDTOMULTIPLE(pASSM->m_pTablesSize[ TBL_TypeDef ] * sizeof(CLR_RT_TypeDef_CrossReference ), CLR_UINT32); + offsets.iFieldDef += ROUNDTOMULTIPLE(pASSM->m_pTablesSize[ TBL_FieldDef ] * sizeof(CLR_RT_FieldDef_CrossReference ), CLR_UINT32); + offsets.iMethodDef += ROUNDTOMULTIPLE(pASSM->m_pTablesSize[ TBL_MethodDef ] * sizeof(CLR_RT_MethodDef_CrossReference ), CLR_UINT32); + +#if !defined(TINYCLR_APPDOMAINS) + offsets.iStaticFields += ROUNDTOMULTIPLE(pASSM->m_iStaticFields * sizeof(CLR_RT_HeapBlock ), CLR_UINT32); +#endif + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + offsets.iDebuggingInfoMethods += ROUNDTOMULTIPLE(pASSM->m_pTablesSize[ TBL_MethodDef ] * sizeof(CLR_RT_MethodDef_DebuggingInfo ), CLR_UINT32); +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + iMetaData += pASSM->m_header->SizeOfTable( TBL_AssemblyRef ) + + pASSM->m_header->SizeOfTable( TBL_TypeRef ) + + pASSM->m_header->SizeOfTable( TBL_FieldRef ) + + pASSM->m_header->SizeOfTable( TBL_MethodRef ) + + pASSM->m_header->SizeOfTable( TBL_TypeDef ) + + pASSM->m_header->SizeOfTable( TBL_FieldDef ) + + pASSM->m_header->SizeOfTable( TBL_MethodDef ) + + pASSM->m_header->SizeOfTable( TBL_Attributes ) + + pASSM->m_header->SizeOfTable( TBL_TypeSpec ) + + pASSM->m_header->SizeOfTable( TBL_Signatures ); + + for(int tbl=0; tblm_pTablesSize[ tbl ]; + } + + iTotalRomSize += pASSM->m_header->TotalSize(); + + iStaticFields += pASSM->m_iStaticFields; + } + TINYCLR_FOREACH_ASSEMBLY_END(); + + iTotalRamSize = offsets.iBase + + offsets.iAssemblyRef + + offsets.iTypeRef + + offsets.iFieldRef + + offsets.iMethodRef + + offsets.iTypeDef + + offsets.iFieldDef + + offsets.iMethodDef; + +#if !defined(TINYCLR_APPDOMAINS) + iTotalRamSize += offsets.iStaticFields; +#endif + + CLR_Debug::Printf( "\r\nTotal: (%d RAM - %d ROM - %d METADATA)\r\n\r\n", iTotalRamSize, iTotalRomSize, iMetaData ); + + CLR_Debug::Printf( " AssemblyRef = %8d bytes (%8d elements)\r\n", offsets.iAssemblyRef , pTablesSize[TBL_AssemblyRef] ); + CLR_Debug::Printf( " TypeRef = %8d bytes (%8d elements)\r\n", offsets.iTypeRef , pTablesSize[TBL_TypeRef ] ); + CLR_Debug::Printf( " FieldRef = %8d bytes (%8d elements)\r\n", offsets.iFieldRef , pTablesSize[TBL_FieldRef ] ); + CLR_Debug::Printf( " MethodRef = %8d bytes (%8d elements)\r\n", offsets.iMethodRef , pTablesSize[TBL_MethodRef ] ); + CLR_Debug::Printf( " TypeDef = %8d bytes (%8d elements)\r\n", offsets.iTypeDef , pTablesSize[TBL_TypeDef ] ); + CLR_Debug::Printf( " FieldDef = %8d bytes (%8d elements)\r\n", offsets.iFieldDef , pTablesSize[TBL_FieldDef ] ); + CLR_Debug::Printf( " MethodDef = %8d bytes (%8d elements)\r\n", offsets.iMethodDef , pTablesSize[TBL_MethodDef ] ); + +#if !defined(TINYCLR_APPDOMAINS) + CLR_Debug::Printf( " StaticFields = %8d bytes (%8d elements)\r\n", offsets.iStaticFields , iStaticFields ); +#endif + + CLR_Debug::Printf( "\r\n" ); + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + CLR_Debug::Printf( " DebuggingInfo = %8d bytes\r\n", offsets.iDebuggingInfoMethods ); + CLR_Debug::Printf( "\r\n" ); +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + CLR_Debug::Printf( " Attributes = %8d bytes (%8d elements)\r\n", pTablesSize[ TBL_Attributes ] * sizeof(CLR_RECORD_ATTRIBUTE ), pTablesSize[ TBL_Attributes ] ); + CLR_Debug::Printf( " TypeSpec = %8d bytes (%8d elements)\r\n", pTablesSize[ TBL_TypeSpec ] * sizeof(CLR_RECORD_TYPESPEC ), pTablesSize[ TBL_TypeSpec ] ); + CLR_Debug::Printf( " Resources Files = %8d bytes (%8d elements)\r\n", pTablesSize[ TBL_ResourcesFiles ] * sizeof(CLR_RECORD_RESOURCE_FILE ), pTablesSize[ TBL_ResourcesFiles ] ); + CLR_Debug::Printf( " Resources = %8d bytes (%8d elements)\r\n", pTablesSize[ TBL_Resources ] * sizeof(CLR_RECORD_RESOURCE ), pTablesSize[ TBL_Resources ] ); + CLR_Debug::Printf( " Resources Data = %8d bytes\r\n" , pTablesSize[ TBL_ResourcesData ] ); + CLR_Debug::Printf( " Strings = %8d bytes\r\n" , pTablesSize[ TBL_Strings ] ); + CLR_Debug::Printf( " Signatures = %8d bytes\r\n" , pTablesSize[ TBL_Signatures ] ); + CLR_Debug::Printf( " ByteCode = %8d bytes\r\n" , pTablesSize[ TBL_ByteCode ] ); + CLR_Debug::Printf( "\r\n\r\n" ); + } + } + +#endif + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_TypeSystem::PrepareForExecutionHelper( LPCSTR szAssembly ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + TINYCLR_FOREACH_ASSEMBLY(*this) + { + if(!strcmp( szAssembly, pASSM->m_szName )) + { + TINYCLR_CHECK_HRESULT(pASSM->PrepareForExecution()); + } + } + + TINYCLR_FOREACH_ASSEMBLY_END(); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_TypeSystem::PrepareForExecution() +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + CLR_EE_DBG_SET(BreakpointsDisabled); +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + +#if !defined(TINYCLR_APPDOMAINS) + if(g_CLR_RT_ExecutionEngine.m_outOfMemoryException == NULL) + { + CLR_RT_HeapBlock exception; + + TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex( exception, g_CLR_RT_WellKnownTypes.m_OutOfMemoryException )); + + g_CLR_RT_ExecutionEngine.m_outOfMemoryException = exception.Dereference(); + } +#endif + + //Load Native to ensure that CultureInfo gets properly initialized + TINYCLR_CHECK_HRESULT(PrepareForExecutionHelper( "Microsoft.SPOT.Native" )); + + TINYCLR_FOREACH_ASSEMBLY(*this) + { + TINYCLR_CHECK_HRESULT(pASSM->PrepareForExecution()); + } + TINYCLR_FOREACH_ASSEMBLY_END(); + + TINYCLR_CLEANUP(); + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + CLR_EE_DBG_CLR(BreakpointsDisabled); + + g_CLR_RT_ExecutionEngine.Breakpoint_Assemblies_Loaded(); +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + TINYCLR_CLEANUP_END(); +} + +//--// + +bool CLR_RT_TypeSystem::MatchSignature( CLR_RT_SignatureParser& parserLeft, CLR_RT_SignatureParser& parserRight ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(parserLeft.m_type != parserRight.m_type ) return false; + if(parserLeft.m_flags != parserRight.m_flags) return false; + + return MatchSignatureDirect( parserLeft, parserRight, false ); +} + +bool CLR_RT_TypeSystem::MatchSignatureDirect( CLR_RT_SignatureParser& parserLeft, CLR_RT_SignatureParser& parserRight, bool fIsInstanceOfOK ) +{ + NATIVE_PROFILE_CLR_CORE(); + while(true) + { + int iAvailLeft = parserLeft .Available(); + int iAvailRight = parserRight.Available(); + + if(iAvailLeft != iAvailRight) return false; + + if(!iAvailLeft) return true; + + CLR_RT_SignatureParser::Element resLeft; if(FAILED(parserLeft .Advance( resLeft ))) return false; + CLR_RT_SignatureParser::Element resRight; if(FAILED(parserRight.Advance( resRight ))) return false; + + if(!MatchSignatureElement( resLeft, resRight, fIsInstanceOfOK )) return false; + } + + return true; +} + +bool CLR_RT_TypeSystem::MatchSignatureElement( CLR_RT_SignatureParser::Element& resLeft, CLR_RT_SignatureParser::Element& resRight, bool fIsInstanceOfOK ) +{ + NATIVE_PROFILE_CLR_CORE(); + if(fIsInstanceOfOK) + { + CLR_RT_ReflectionDef_Index idxLeft ; CLR_RT_TypeDescriptor descLeft; + CLR_RT_ReflectionDef_Index idxRight; CLR_RT_TypeDescriptor descRight; + + idxLeft.m_kind = REFLECTION_TYPE; + idxLeft.m_levels = resLeft.m_levels; + idxLeft.m_data.m_type = resLeft.m_cls; + + idxRight.m_kind = REFLECTION_TYPE; + idxRight.m_levels = resRight.m_levels; + idxRight.m_data.m_type = resRight.m_cls; + + if(FAILED(descLeft .InitializeFromReflection( idxLeft ))) return false; + if(FAILED(descRight.InitializeFromReflection( idxRight ))) return false; + + if(!CLR_RT_ExecutionEngine::IsInstanceOf( descRight, descLeft )) return false; + } + else + { + if(resLeft.m_fByRef != resRight.m_fByRef ) return false; + if(resLeft.m_levels != resRight.m_levels ) return false; + if(resLeft.m_dt != resRight.m_dt ) return false; + if(resLeft.m_cls.m_data != resRight.m_cls.m_data) return false; + } + + return true; +} + +//--// + +HRESULT CLR_RT_TypeSystem::QueueStringToBuffer( LPSTR& szBuffer, size_t& iBuffer, LPCSTR szText ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + if(szText) + { + if(CLR_SafeSprintf( szBuffer, iBuffer, "%s", szText ) == false) + { + TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + } + else + { + szBuffer[ 0 ] = 0; + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_TypeSystem::BuildTypeName( const CLR_RT_TypeDef_Index& cls, LPSTR& szBuffer, size_t& iBuffer ) +{ + NATIVE_PROFILE_CLR_CORE(); + return BuildTypeName( cls, szBuffer, iBuffer, CLR_RT_TypeSystem::TYPENAME_FLAGS_FULL, 0 ); +} + +HRESULT CLR_RT_TypeSystem::BuildTypeName ( const CLR_RT_TypeDef_Index& cls, LPSTR& szBuffer, size_t& iBuffer, CLR_UINT32 flags, CLR_UINT32 levels ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_TypeDef_Instance inst; + CLR_RT_Assembly* assm; + const CLR_RECORD_TYPEDEF* td; + bool fFullName; + + if(inst.InitializeFromIndex( cls ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + assm = inst.m_assm; + td = inst.m_target; + fFullName = flags & CLR_RT_TypeSystem::TYPENAME_FLAGS_FULL; + + if(fFullName && td->enclosingType != CLR_EmptyIndex) + { + CLR_RT_TypeDef_Index clsSub; clsSub.Set( inst.Assembly(), td->enclosingType ); + + TINYCLR_CHECK_HRESULT(BuildTypeName( clsSub, szBuffer, iBuffer, flags, 0 )); + + TINYCLR_CHECK_HRESULT(QueueStringToBuffer( szBuffer, iBuffer, (flags & CLR_RT_TypeSystem::TYPENAME_NESTED_SEPARATOR_DOT) ? "." : "+" )); + } + + if(fFullName && td->nameSpace != CLR_EmptyIndex) + { + LPCSTR szNameSpace = assm->GetString( td->nameSpace ); + + if(szNameSpace[ 0 ]) + { + TINYCLR_CHECK_HRESULT(QueueStringToBuffer( szBuffer, iBuffer, szNameSpace )); + TINYCLR_CHECK_HRESULT(QueueStringToBuffer( szBuffer, iBuffer, "." )); + } + } + + TINYCLR_CHECK_HRESULT(QueueStringToBuffer( szBuffer, iBuffer, assm->GetString( td->name ) )); + + while(levels-- > 0) + { + TINYCLR_CHECK_HRESULT(QueueStringToBuffer( szBuffer, iBuffer, "[]" )); + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_TypeSystem::BuildMethodName( const CLR_RT_MethodDef_Index& md, LPSTR& szBuffer, size_t& iBuffer ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_MethodDef_Instance inst; + CLR_RT_TypeDef_Instance instOwner; + + if(inst .InitializeFromIndex ( md ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + if(instOwner.InitializeFromMethod( inst ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + TINYCLR_CHECK_HRESULT(BuildTypeName( instOwner, szBuffer, iBuffer )); + + CLR_SafeSprintf( szBuffer, iBuffer, "::%s", inst.m_assm->GetString( inst.m_target->name ) ); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_TypeSystem::BuildFieldName( const CLR_RT_FieldDef_Index& fd, LPSTR& szBuffer, size_t& iBuffer ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_FieldDef_Instance inst; + CLR_RT_TypeDef_Instance instOwner; + + if(inst .InitializeFromIndex( fd ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + if(instOwner.InitializeFromField( inst ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + + TINYCLR_CHECK_HRESULT(BuildTypeName( instOwner, szBuffer, iBuffer )); + + CLR_SafeSprintf( szBuffer, iBuffer, "::%s", inst.m_assm->GetString( inst.m_target->name ) ); + + TINYCLR_NOCLEANUP(); +} + +//--// + +bool CLR_RT_TypeSystem::FindVirtualMethodDef( const CLR_RT_TypeDef_Index& cls, const CLR_RT_MethodDef_Index& calleeMD, CLR_RT_MethodDef_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_MethodDef_Instance calleeInst; + + if(calleeInst.InitializeFromIndex( calleeMD )) + { + LPCSTR calleeName = calleeInst.m_assm->GetString( calleeInst.m_target->name ); + + CLR_RT_TypeDef_Instance inst; inst.InitializeFromMethod( calleeInst ); + + if((inst.m_target->flags & CLR_RECORD_TYPEDEF::TD_Semantics_Mask) == CLR_RECORD_TYPEDEF::TD_Semantics_Interface) + { + // + // It's an interface method, it could be that the class is implementing explicitly the method. + // Prepend the Interface name to the method name and try again. + // + char rgBuffer[ 512 ]; + LPSTR szBuffer = rgBuffer; + size_t iBuffer = MAXSTRLEN(rgBuffer); + + BuildTypeName ( inst, szBuffer, iBuffer, CLR_RT_TypeSystem::TYPENAME_FLAGS_FULL | CLR_RT_TypeSystem::TYPENAME_NESTED_SEPARATOR_DOT, 0 ); + QueueStringToBuffer( szBuffer, iBuffer, "." ); + QueueStringToBuffer( szBuffer, iBuffer, calleeName ); + + if(FindVirtualMethodDef( cls, calleeMD, rgBuffer, idx )) return true; + } + + if(FindVirtualMethodDef( cls, calleeMD, calleeName, idx )) return true; + } + + idx.Clear(); + + return false; +} + +bool CLR_RT_TypeSystem::FindVirtualMethodDef( const CLR_RT_TypeDef_Index& cls, const CLR_RT_MethodDef_Index& calleeMD, LPCSTR calleeName, CLR_RT_MethodDef_Index& idx ) +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_RT_TypeDef_Instance clsInst ; clsInst .InitializeFromIndex( cls ); + CLR_RT_MethodDef_Instance calleeInst; calleeInst.InitializeFromIndex( calleeMD ); + + CLR_RT_Assembly* calleeAssm = calleeInst.m_assm; + const CLR_RECORD_METHODDEF* calleeMDR = calleeInst.m_target; + CLR_UINT8 calleeNumArgs = calleeMDR->numArgs; + + while(TINYCLR_INDEX_IS_VALID(clsInst)) + { + CLR_RT_Assembly* targetAssm = clsInst.m_assm; + const CLR_RECORD_TYPEDEF* targetTDR = clsInst.m_target; + const CLR_RECORD_METHODDEF* targetMDR = targetAssm->GetMethodDef( targetTDR->methods_First ); + int num = targetTDR->vMethods_Num + targetTDR->iMethods_Num; + + for(int i=0; inumArgs == calleeNumArgs && (targetMDR->flags & CLR_RECORD_METHODDEF::MD_Abstract) == 0) + { + LPCSTR targetName = targetAssm->GetString( targetMDR->name ); + + if(!strcmp( targetName, calleeName )) + { + CLR_RT_SignatureParser parserLeft ; parserLeft .Initialize_MethodSignature( calleeAssm, calleeMDR ); + CLR_RT_SignatureParser parserRight; parserRight.Initialize_MethodSignature( targetAssm, targetMDR ); + + if(CLR_RT_TypeSystem::MatchSignature( parserLeft, parserRight )) + { + idx.Set( targetAssm->m_idx, i + targetTDR->methods_First ); + + return true; + } + } + } + } + + clsInst.SwitchToParent(); + } + + idx.Clear(); + + return false; +} + +CLR_DataType CLR_RT_TypeSystem::MapElementTypeToDataType( CLR_UINT32 et ) +{ + NATIVE_PROFILE_CLR_CORE(); + const CLR_RT_DataTypeLookup* ptr = c_CLR_RT_DataTypeLookup; + + for(CLR_UINT32 num = 0; numm_convertToElementType == et) return (CLR_DataType)num; + } + + if(et == ELEMENT_TYPE_I) return DATATYPE_I4; + if(et == ELEMENT_TYPE_U) return DATATYPE_U4; + + return DATATYPE_FIRST_INVALID; +} + +CLR_UINT32 CLR_RT_TypeSystem::MapDataTypeToElementType( CLR_DataType dt ) +{ + NATIVE_PROFILE_CLR_CORE(); + return c_CLR_RT_DataTypeLookup[ dt ].m_convertToElementType; +} + +//--// + +void CLR_RT_AttributeEnumerator::Initialize( CLR_RT_Assembly* assm ) +{ + NATIVE_PROFILE_CLR_CORE(); + m_assm = assm; // CLR_RT_Assembly* m_assm; + m_ptr = NULL; // const CLR_RECORD_ATTRIBUTE* m_ptr; + m_num = 0; // int m_num; + // CLR_RECORD_ATTRIBUTE m_data; + m_match.Clear(); // CLR_RT_MethodDef_Index m_match; +} + +void CLR_RT_AttributeEnumerator::Initialize( const CLR_RT_TypeDef_Instance& inst ) +{ + NATIVE_PROFILE_CLR_CORE(); + m_data.ownerType = TBL_TypeDef; + m_data.ownerIdx = inst.Type(); + + Initialize( inst.m_assm ); +} + +void CLR_RT_AttributeEnumerator::Initialize( const CLR_RT_FieldDef_Instance& inst ) +{ + NATIVE_PROFILE_CLR_CORE(); + m_data.ownerType = TBL_FieldDef; + m_data.ownerIdx = inst.Field(); + + Initialize( inst.m_assm ); +} + +void CLR_RT_AttributeEnumerator::Initialize( const CLR_RT_MethodDef_Instance& inst ) +{ + NATIVE_PROFILE_CLR_CORE(); + m_data.ownerType = TBL_FieldDef; + m_data.ownerIdx = inst.Method(); + + Initialize( inst.m_assm ); +} + +bool CLR_RT_AttributeEnumerator::Advance() +{ + NATIVE_PROFILE_CLR_CORE(); + const CLR_RECORD_ATTRIBUTE* ptr = m_ptr; + int num = m_num; + CLR_UINT32 key = m_data.Key(); + bool fRes = false; + + if(ptr == NULL) + { + ptr = m_assm->GetAttribute( 0 ) - 1; + num = m_assm->m_pTablesSize[ TBL_Attributes ]; + } + + while(num) + { + ptr++; + num--; + + if(ptr->Key() == key) + { + CLR_IDX tk = ptr->constructor; + if(tk & 0x8000) + { + m_match = m_assm->m_pCrossReference_MethodRef[ tk & 0x7FFF ].m_target; + } + else + { + m_match.Set( m_assm->m_idx, tk ); + } + + m_blob = m_assm->GetSignature( ptr->data ); + + fRes = true; + break; + } + } + + m_ptr = ptr; + m_num = num; + + return fRes; +} + +bool CLR_RT_AttributeEnumerator::MatchNext( const CLR_RT_TypeDef_Instance* instTD, const CLR_RT_MethodDef_Instance* instMD ) +{ + NATIVE_PROFILE_CLR_CORE(); + while(Advance()) + { + if(instMD) + { + if(m_match.m_data != instMD->m_data) continue; + } + + if(instTD) + { + CLR_RT_MethodDef_Instance md; + CLR_RT_TypeDef_Instance td; + + md.InitializeFromIndex ( m_match ); + td.InitializeFromMethod( md ); + + if(td.m_data != instTD->m_data) continue; + } + + return true; + } + + return false; +} + +//--// + +HRESULT CLR_RT_AttributeParser::Initialize( const CLR_RT_AttributeEnumerator& en ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + if(m_md.InitializeFromIndex ( en.m_match ) == false || + m_td.InitializeFromMethod( m_md ) == false ) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + m_parser.Initialize_MethodSignature( m_md.m_assm, m_md.m_target ); + m_parser.Advance( m_res ); // Skip return value. + + m_assm = en.m_assm; + m_blob = en.m_blob; + + m_currentPos = 0; + m_fixed_Count = m_md.m_target->numArgs - 1; + m_named_Count = -1; + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_AttributeParser::Next( Value*& res ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + if(m_currentPos == m_fixed_Count) + { + TINYCLR_READ_UNALIGNED_UINT16(m_named_Count,m_blob); + } + + if(m_currentPos < m_fixed_Count) + { + m_lastValue.m_mode = Value::c_ConstructorArgument; + m_lastValue.m_name = NULL; + + // + // attribute contructor support is currently not implemented + // + TINYCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + } + else if(m_currentPos < m_fixed_Count + m_named_Count) + { + CLR_UINT32 kind; TINYCLR_READ_UNALIGNED_UINT8(kind,m_blob); + + m_lastValue.m_name = GetString(); + + if(kind == SERIALIZATION_TYPE_FIELD) + { + CLR_RT_FieldDef_Index fd; + CLR_RT_FieldDef_Instance inst; + + m_lastValue.m_mode = Value::c_NamedField; + + TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.FindFieldDef( m_td, m_lastValue.m_name, fd )); + + inst.InitializeFromIndex( fd ); + + m_parser.Initialize_FieldDef( inst.m_assm, inst.m_target ); + } + else + { + m_lastValue.m_mode = Value::c_NamedProperty; + + // + //attribute contructor support is currently not implemented + // + TINYCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + } + } + else + { + res = NULL; + TINYCLR_SET_AND_LEAVE(S_OK); + } + + + TINYCLR_CHECK_HRESULT(m_parser.Advance( m_res )); + + res = &m_lastValue; + + // + // Check for Enums. + // + if(m_res.m_dt == DATATYPE_VALUETYPE) + { + CLR_RT_TypeDef_Instance td; td.InitializeFromIndex( m_res.m_cls ); + + if((td.m_target->flags & CLR_RECORD_TYPEDEF::TD_Semantics_Mask) == CLR_RECORD_TYPEDEF::TD_Semantics_Enum) + { + m_res.m_dt = (CLR_DataType)td.m_target->dataType; + } + } + + // + // Skip value info. + // + m_blob += sizeof(CLR_UINT8); + + { + const CLR_RT_DataTypeLookup& dtl = c_CLR_RT_DataTypeLookup[ m_res.m_dt ]; + + if(dtl.m_flags & CLR_RT_DataTypeLookup::c_Numeric) + { + m_lastValue.m_value.SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(m_res.m_dt, 0, 1) ); + + CLR_UINT32 size = (dtl.m_sizeInBits + 7) / 8; + +// FIXME GJS - the numeric values, what is their endiannes??? In the MSTV code there is a BIG endian fix but it looks like it will not work, so was it ever used? + memcpy( &m_lastValue.m_value.NumericByRef(), m_blob, size ); m_blob += size; + } + else if(m_res.m_dt == DATATYPE_STRING) + { + CLR_UINT32 tk; TINYCLR_READ_UNALIGNED_UINT16(tk,m_blob); + + CLR_RT_HeapBlock_String::CreateInstance( m_lastValue.m_value, CLR_TkFromType( TBL_Strings, tk ), m_assm ); + } + else + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + + m_lastValue.m_pos = m_currentPos++; + + TINYCLR_NOCLEANUP(); +} + +LPCSTR CLR_RT_AttributeParser::GetString() +{ + NATIVE_PROFILE_CLR_CORE(); + CLR_UINT32 tk; TINYCLR_READ_UNALIGNED_UINT16(tk,m_blob); + + return m_assm->GetString( tk ); +} diff --git a/src/CLR/Core/TypeSystemLookup.cpp b/src/CLR/Core/TypeSystemLookup.cpp new file mode 100644 index 0000000000..caf3c52f8f --- /dev/null +++ b/src/CLR/Core/TypeSystemLookup.cpp @@ -0,0 +1,1775 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" +#include "corhdr_private.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#define DT_NA CLR_RT_DataTypeLookup::c_NA +#define DT_VS CLR_RT_DataTypeLookup::c_VariableSize + +#define DT_PRIM CLR_RT_DataTypeLookup::c_Primitive +#define DT_ITF CLR_RT_DataTypeLookup::c_Interface +#define DT_CLASS CLR_RT_DataTypeLookup::c_Class +#define DT_VALUE CLR_RT_DataTypeLookup::c_ValueType +#define DT_ENUM CLR_RT_DataTypeLookup::c_Enum + +#define DT_ARRAY CLR_RT_DataTypeLookup::c_Array +#define DT_ARLST CLR_RT_DataTypeLookup::c_ArrayList + +#define DT_REF CLR_RT_DataTypeLookup::c_Reference +#define DT_NUM CLR_RT_DataTypeLookup::c_Numeric +#define DT_INT CLR_RT_DataTypeLookup::c_Integer +#define DT_SGN CLR_RT_DataTypeLookup::c_Signed +#define DT_DIR CLR_RT_DataTypeLookup::c_Direct +#define DT_OPT CLR_RT_DataTypeLookup::c_OptimizedValueType +#define DT_MT CLR_RT_DataTypeLookup::c_ManagedType + +#define DT_U1 sizeof(CLR_UINT8) +#define DT_I1 sizeof(CLR_INT8) +#define DT_U2 sizeof(CLR_UINT16) +#define DT_I2 sizeof(CLR_INT16) +#define DT_U4 sizeof(CLR_UINT32) +#define DT_I4 sizeof(CLR_INT32) +#define DT_U8 sizeof(CLR_UINT64) +#define DT_I8 sizeof(CLR_INT64) +#define DT_BL sizeof(CLR_RT_HeapBlock) + +#define DT_T(x) (CLR_UINT8)DATATYPE_##x +#define DT_CNV(x) (CLR_UINT8)ELEMENT_TYPE_##x +#define DT_CLS(x) &g_CLR_RT_WellKnownTypes.x + +#define DT_NOREL(x) NULL +#define DT_REL(x) (CLR_RT_HeapBlockRelocate)&x + +#if defined(WIN32) || defined(TINYCLR_TRACE_MEMORY_STATS) +#define DT_OPT_NAME(x) , #x +#else +#define DT_OPT_NAME(x) +#endif + +#define DATATYPE_NOT_SUPPORTED { DT_NA, DT_NA, DT_NA, DT_T(FIRST_INVALID), DT_CNV(END), NULL, DT_NOREL(CLR_RT_HeapBlock) DT_OPT_NAME(NOT_SUPPORTED) }, + +const CLR_RT_DataTypeLookup c_CLR_RT_DataTypeLookup[] = +{ +//// m_flags, m_sizeInBits, m_sizeInBytes, m_promoteTo, m_convertToElementType, m_cls, m_relocate, m_name +//// +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + { DT_NA , DT_NA, DT_NA, DT_T(VOID ), DT_CNV(VOID ), NULL , DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(VOID ) }, // DATATYPE_VOID + // + { DT_NUM | DT_INT | DT_PRIM | DT_DIR | DT_OPT | DT_MT, 1, DT_U1, DT_T(I4 ), DT_CNV(BOOLEAN ), DT_CLS(m_Boolean ), DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(BOOLEAN ) }, // DATATYPE_BOOLEAN + { DT_NUM | DT_INT | DT_SGN | DT_PRIM | DT_DIR | DT_OPT | DT_MT, 8, DT_I1, DT_T(I4 ), DT_CNV(I1 ), DT_CLS(m_Int8 ), DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(I1 ) }, // DATATYPE_I1 + { DT_NUM | DT_INT | DT_PRIM | DT_DIR | DT_OPT | DT_MT, 8, DT_U1, DT_T(I4 ), DT_CNV(U1 ), DT_CLS(m_UInt8 ), DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(U1 ) }, // DATATYPE_U1 + // + { DT_NUM | DT_INT | DT_PRIM | DT_DIR | DT_OPT | DT_MT, 16, DT_U2, DT_T(I4 ), DT_CNV(CHAR ), DT_CLS(m_Char ), DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(CHAR ) }, // DATATYPE_CHAR + { DT_NUM | DT_INT | DT_SGN | DT_PRIM | DT_DIR | DT_OPT | DT_MT, 16, DT_I2, DT_T(I4 ), DT_CNV(I2 ), DT_CLS(m_Int16 ), DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(I2 ) }, // DATATYPE_I2 + { DT_NUM | DT_INT | DT_PRIM | DT_DIR | DT_OPT | DT_MT, 16, DT_U2, DT_T(I4 ), DT_CNV(U2 ), DT_CLS(m_UInt16 ), DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(U2 ) }, // DATATYPE_U2 + // + { DT_NUM | DT_INT | DT_SGN | DT_PRIM | DT_DIR | DT_OPT | DT_MT, 32, DT_I4, DT_T(I4 ), DT_CNV(I4 ), DT_CLS(m_Int32 ), DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(I4 ) }, // DATATYPE_I4 + { DT_NUM | DT_INT | DT_PRIM | DT_DIR | DT_OPT | DT_MT, 32, DT_U4, DT_T(I4 ), DT_CNV(U4 ), DT_CLS(m_UInt32 ), DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(U4 ) }, // DATATYPE_U4 + { DT_NUM | DT_SGN | DT_PRIM | DT_DIR | DT_OPT | DT_MT, 32, DT_I4, DT_T(R4 ), DT_CNV(R4 ), DT_CLS(m_Single ), DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(R4 ) }, // DATATYPE_R4 + // + { DT_NUM | DT_INT | DT_SGN | DT_PRIM | DT_DIR | DT_OPT | DT_MT, 64, DT_I8, DT_T(I8 ), DT_CNV(I8 ), DT_CLS(m_Int64 ), DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(I8 ) }, // DATATYPE_I8 + { DT_NUM | DT_INT | DT_PRIM | DT_DIR | DT_OPT | DT_MT, 64, DT_U8, DT_T(I8 ), DT_CNV(U8 ), DT_CLS(m_UInt64 ), DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(U8 ) }, // DATATYPE_U8 + { DT_NUM | DT_SGN | DT_PRIM | DT_DIR | DT_OPT | DT_MT, 64, DT_I8, DT_T(R8 ), DT_CNV(R8 ), DT_CLS(m_Double ), DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(R8 ) }, // DATATYPE_R8 + { DT_INT | DT_SGN | DT_VALUE | DT_DIR | DT_OPT | DT_MT, 64, DT_BL, DT_T(DATETIME ), DT_CNV(END ), DT_CLS(m_DateTime ), DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(DATETIME ) }, // DATATYPE_DATETIME + { DT_INT | DT_SGN | DT_VALUE | DT_DIR | DT_OPT | DT_MT, 64, DT_BL, DT_T(TIMESPAN ), DT_CNV(END ), DT_CLS(m_TimeSpan ), DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(TIMESPAN ) }, // DATATYPE_TIMESPAN + { DT_REF | DT_PRIM | DT_DIR | DT_MT, DT_VS, DT_BL, DT_T(STRING ), DT_CNV(STRING ), DT_CLS(m_String ), DT_REL (CLR_RT_HeapBlock ::Relocate_String ) DT_OPT_NAME(STRING ) }, // DATATYPE_STRING + // + { DT_REF | DT_DIR | DT_MT, DT_NA, DT_BL, DT_T(OBJECT ), DT_CNV(OBJECT ), DT_CLS(m_Object ), DT_REL (CLR_RT_HeapBlock ::Relocate_Obj ) DT_OPT_NAME(OBJECT ) }, // DATATYPE_OBJECT + { DT_REF | DT_CLASS | DT_MT, DT_NA, DT_BL, DT_T(CLASS ), DT_CNV(CLASS ), NULL , DT_REL (CLR_RT_HeapBlock ::Relocate_Cls ) DT_OPT_NAME(CLASS ) }, // DATATYPE_CLASS + { DT_REF | DT_VALUE | DT_MT, DT_NA, DT_BL, DT_T(VALUETYPE ), DT_CNV(VALUETYPE), NULL , DT_REL (CLR_RT_HeapBlock ::Relocate_Cls ) DT_OPT_NAME(VALUETYPE ) }, // DATATYPE_VALUETYPE + { DT_REF | DT_CLASS | DT_ARRAY | DT_MT, DT_NA, DT_BL, DT_T(SZARRAY ), DT_CNV(SZARRAY ), DT_CLS(m_Array ), DT_REL (CLR_RT_HeapBlock_Array ::Relocate ) DT_OPT_NAME(SZARRAY ) }, // DATATYPE_SZARRAY + { DT_REF | DT_MT, DT_NA, DT_NA, DT_T(BYREF ), DT_CNV(BYREF ), NULL , DT_REL (CLR_RT_HeapBlock ::Relocate_Ref ) DT_OPT_NAME(BYREF ) }, // DATATYPE_BYREF + // + //////////////////////////////////// + // + { DT_NA , DT_NA, DT_NA, DT_T(FREEBLOCK ), DT_CNV(END ), NULL , DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(FREEBLOCK ) }, // DATATYPE_FREEBLOCK + { DT_NA , DT_NA, DT_NA, DT_T(CACHEDBLOCK ), DT_CNV(END ), NULL , DT_NOREL(CLR_RT_HeapBlock_Node ) DT_OPT_NAME(CACHEDBLOCK ) }, // DATATYPE_CACHEDBLOCK + { DT_REF , DT_NA, DT_NA, DT_T(ASSEMBLY ), DT_CNV(END ), NULL , DT_REL (CLR_RT_Assembly ::Relocate ) DT_OPT_NAME(ASSEMBLY ) }, // DATATYPE_ASSEMBLY + { DT_REF | DT_MT, DT_NA, DT_BL, DT_T(WEAKCLASS ), DT_CNV(END ), NULL , DT_REL (CLR_RT_HeapBlock_WeakReference::Relocate ) DT_OPT_NAME(WEAKCLASS ) }, // DATATYPE_WEAKCLASS + { DT_MT, DT_NA, DT_NA, DT_T(REFLECTION ), DT_CNV(END ), NULL , DT_NOREL(CLR_RT_HeapBlock ) DT_OPT_NAME(REFLECTION ) }, // DATATYPE_REFLECTION + { DT_MT, DT_NA, DT_NA, DT_T(ARRAY_BYREF ), DT_CNV(END ), NULL , DT_REL (CLR_RT_HeapBlock ::Relocate_ArrayRef) DT_OPT_NAME(ARRAY_BYREF ) }, // DATATYPE_ARRAY_BYREF + { DT_REF | DT_MT, DT_NA, DT_BL, DT_T(DELEGATE_HEAD ), DT_CNV(END ), NULL , DT_REL (CLR_RT_HeapBlock_Delegate ::Relocate ) DT_OPT_NAME(DELEGATE_HEAD ) }, // DATATYPE_DELEGATE_HEAD + { DT_REF | DT_MT, DT_NA, DT_NA, DT_T(DELEGATELIST_HEAD ), DT_CNV(END ), NULL , DT_REL (CLR_RT_HeapBlock_Delegate_List::Relocate ) DT_OPT_NAME(DELEGATELIST_HEAD ) }, // DATATYPE_DELEGATELIST_HEAD + { DT_REF , DT_NA, DT_NA, DT_T(OBJECT_TO_EVENT ), DT_CNV(END ), NULL , DT_REL (CLR_RT_ObjectToEvent_Source ::Relocate ) DT_OPT_NAME(OBJECT_TO_EVENT ) }, // DATATYPE_OBJECT_TO_EVENT + { DT_REF , DT_NA, DT_NA, DT_T(BINARY_BLOB_HEAD ), DT_CNV(END ), NULL , DT_REL (CLR_RT_HeapBlock_BinaryBlob ::Relocate ) DT_OPT_NAME(BINARY_BLOB_HEAD ) }, // DATATYPE_BINARY_BLOB_HEAD + // + { DT_REF , DT_NA, DT_NA, DT_T(THREAD ), DT_CNV(END ), NULL , DT_REL (CLR_RT_Thread ::Relocate ) DT_OPT_NAME(THREAD ) }, // DATATYPE_THREAD + { DT_REF , DT_NA, DT_NA, DT_T(SUBTHREAD ), DT_CNV(END ), NULL , DT_REL (CLR_RT_SubThread ::Relocate ) DT_OPT_NAME(SUBTHREAD ) }, // DATATYPE_SUBTHREAD + { DT_REF , DT_NA, DT_NA, DT_T(STACK_FRAME ), DT_CNV(END ), NULL , DT_REL (CLR_RT_StackFrame ::Relocate ) DT_OPT_NAME(STACK_FRAME ) }, // DATATYPE_STACK_FRAME + { DT_REF , DT_NA, DT_NA, DT_T(TIMER_HEAD ), DT_CNV(END ), NULL , DT_NOREL(CLR_RT_HeapBlock_Timer ) DT_OPT_NAME(TIMER_HEAD ) }, // DATATYPE_TIMER_HEAD + { DT_REF , DT_NA, DT_NA, DT_T(LOCK_HEAD ), DT_CNV(END ), NULL , DT_REL (CLR_RT_HeapBlock_Lock ::Relocate ) DT_OPT_NAME(LOCK_HEAD ) }, // DATATYPE_LOCK_HEAD + { DT_REF , DT_NA, DT_NA, DT_T(LOCK_OWNER_HEAD ), DT_CNV(END ), NULL , DT_REL (CLR_RT_HeapBlock_Lock ::Relocate_Owner ) DT_OPT_NAME(LOCK_OWNER_HEAD ) }, // DATATYPE_LOCK_OWNER_HEAD + { DT_REF , DT_NA, DT_NA, DT_T(LOCK_REQUEST_HEAD ), DT_CNV(END ), NULL , DT_REL (CLR_RT_HeapBlock_LockRequest ::Relocate ) DT_OPT_NAME(LOCK_REQUEST_HEAD ) }, // DATATYPE_LOCK_REQUEST_HEAD + { DT_REF , DT_NA, DT_NA, DT_T(WAIT_FOR_OBJECT_HEAD), DT_CNV(END ), NULL , DT_REL (CLR_RT_HeapBlock_WaitForObject::Relocate ) DT_OPT_NAME(WAIT_FOR_OBJECT_HEAD) }, // DATATYPE_WAIT_FOR_OBJECT_HEAD + { DT_REF , DT_NA, DT_NA, DT_T(FINALIZER_HEAD ), DT_CNV(END ), NULL , DT_REL (CLR_RT_HeapBlock_Finalizer ::Relocate ) DT_OPT_NAME(FINALIZER_HEAD ) }, // DATATYPE_FINALIZER_HEAD + { DT_NA , DT_NA, DT_NA, DT_T(MEMORY_STREAM_HEAD ), DT_CNV(END ), NULL , DT_NOREL(CLR_RT_HeapBlock_MemoryStream ) DT_OPT_NAME(MEMORY_STREAM_HEAD ) }, // DATATYPE_MEMORY_STREAM_HEAD + { DT_NA , DT_NA, DT_NA, DT_T(MEMORY_STREAM_DATA ), DT_CNV(END ), NULL , DT_NOREL(CLR_RT_HeapBlock_MemoryStream ) DT_OPT_NAME(MEMORY_STREAM_DATA ) }, // DATATYPE_MEMORY_STREAM_DATA + // + { DT_NA , DT_NA, DT_NA, DT_T(SERIALIZER_HEAD ), DT_CNV(END ), NULL , DT_NOREL(CLR_RT_BinaryFormatter ) DT_OPT_NAME(SERIALIZER_HEAD ) }, // DATATYPE_SERIALIZER_HEAD + { DT_NA , DT_NA, DT_NA, DT_T(SERIALIZER_DUPLICATE), DT_CNV(END ), NULL , DT_NOREL(CLR_RT_BinaryFormatter ) DT_OPT_NAME(SERIALIZER_DUPLICATE) }, // DATATYPE_SERIALIZER_DUPLICATE + { DT_NA , DT_NA, DT_NA, DT_T(SERIALIZER_STATE ), DT_CNV(END ), NULL , DT_NOREL(CLR_RT_BinaryFormatter ) DT_OPT_NAME(SERIALIZER_STATE ) }, // DATATYPE_SERIALIZER_STATE + // + { DT_REF , DT_NA, DT_NA, DT_T(ENDPOINT_HEAD ), DT_CNV(END ), NULL , DT_NOREL(CLR_RT_HeapBlock_EndPoint ) DT_OPT_NAME(ENDPOINT_HEAD ) }, // DATATYPE_ENDPOINT_HEAD + // + DATATYPE_NOT_SUPPORTED + DATATYPE_NOT_SUPPORTED + DATATYPE_NOT_SUPPORTED + + { DT_REF , DT_NA, DT_NA, DT_T(IO_PORT ), DT_CNV(END ), NULL , DT_NOREL(CLR_RT_HeapBlock_NativeEventDispatcher ) DT_OPT_NAME(IO_PORT ) }, // DATATYPE_IO_PORT + + DATATYPE_NOT_SUPPORTED //VTU_PORT + + { DT_REF , DT_NA, DT_NA, DT_T(I2C_XACTION ), DT_CNV(END ), NULL , DT_NOREL(CLR_RT_HeapBlock_I2CXAction ) DT_OPT_NAME(I2C_XACTION ) }, // DATATYPE_I2C_XACTION + +#if defined(TINYCLR_APPDOMAINS) + { DT_REF , DT_NA, DT_NA, DT_T(APPDOMAIN_HEAD ), DT_CNV(END ), NULL , DT_REL (CLR_RT_AppDomain::Relocate ) DT_OPT_NAME(APPDOMAIN_HEAD ) }, // DATATYPE_APPDOMAIN_HEAD + { DT_REF | DT_MT, DT_NA, DT_NA, DT_T(TRANSPARENT_PROXY ), DT_CNV(END ), NULL , DT_REL (CLR_RT_HeapBlock::Relocate_TransparentProxy ) DT_OPT_NAME(TRANSPARENT_PROXY ) }, // DATATYPE_TRANSPARENT_PROXY + { DT_REF , DT_NA, DT_NA, DT_T(APPDOMAIN_ASSEMBLY ), DT_CNV(END ), NULL , DT_REL (CLR_RT_AppDomainAssembly::Relocate ) DT_OPT_NAME(APPDOMAIN_ASSEMBLY ) }, // DATATYPE_APPDOMAIN_ASSEMBLY +#else + DATATYPE_NOT_SUPPORTED + DATATYPE_NOT_SUPPORTED + DATATYPE_NOT_SUPPORTED +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#define InlineBrTarget CLR_OpcodeParam_BrTarget +#define InlineField CLR_OpcodeParam_Field +#define InlineI CLR_OpcodeParam_I +#define InlineI8 CLR_OpcodeParam_I8 +#define InlineMethod CLR_OpcodeParam_Method +#define InlineNone CLR_OpcodeParam_None +#define InlineR CLR_OpcodeParam_R +#define InlineSig CLR_OpcodeParam_Sig +#define InlineString CLR_OpcodeParam_String +#define InlineSwitch CLR_OpcodeParam_Switch +#define InlineTok CLR_OpcodeParam_Tok +#define InlineType CLR_OpcodeParam_Type +#define InlineVar CLR_OpcodeParam_Var +#define ShortInlineBrTarget CLR_OpcodeParam_ShortBrTarget +#define ShortInlineI CLR_OpcodeParam_ShortI +#define ShortInlineR CLR_OpcodeParam_ShortR +#define ShortInlineVar CLR_OpcodeParam_ShortVar + +#define Pop0 0 +#define Pop1 1 +#define PopI 1 +#define PopI8 1 +#define PopR4 1 +#define PopR8 1 +#define PopRef 1 + +#define Push0 0 +#define Push1 1 +#define PushI 1 +#define PushI8 1 +#define PushR4 1 +#define PushR8 1 +#define PushRef 1 + +#define VarPop 0 +#define VarPush 0 + +#if defined(TINYCLR_OPCODE_NAMES) +#define OPDEF_NAME(name) name, +#else +#define OPDEF_NAME(name) +#endif + +#if defined(TINYCLR_OPCODE_STACKCHANGES) +#define OPDEF_STACKCHANGE(pop,push) ((pop) << 4) | (push), +#else +#define OPDEF_STACKCHANGE(pop,push) +#endif + +#if defined(TINYCLR_OPCODE_PARSER) +#define OPDEF_EX(lo,dt,index,flags) , lo, dt, index, flags +#else +#define OPDEF_EX(lo,dt,index,flags) +#endif + +#define OPDEF(name,string,pop,push,oprType,opcType,l,s1,s2,ctrl) OPDEF_NAME(string) OPDEF_STACKCHANGE(pop,push) oprType + +//--// + +const CLR_RT_OpcodeLookup c_CLR_RT_OpcodeLookup[] = +{ + { + OPDEF(CEE_NOP, "nop", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x00, NEXT) + + OPDEF_EX(LO_Nop, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_BREAK, "break", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x01, BREAK) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_LDARG_0, "ldarg.0", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x02, NEXT) + + OPDEF_EX(LO_LoadArgument, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LDARG_1, "ldarg.1", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x03, NEXT) + + OPDEF_EX(LO_LoadArgument, DATATYPE_FIRST_INVALID, 1, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LDARG_2, "ldarg.2", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x04, NEXT) + + OPDEF_EX(LO_LoadArgument, DATATYPE_FIRST_INVALID, 2, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LDARG_3, "ldarg.3", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x05, NEXT) + + OPDEF_EX(LO_LoadArgument, DATATYPE_FIRST_INVALID, 3, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LDLOC_0, "ldloc.0", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x06, NEXT) + + OPDEF_EX(LO_LoadLocal, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LDLOC_1, "ldloc.1", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x07, NEXT) + + OPDEF_EX(LO_LoadLocal, DATATYPE_FIRST_INVALID, 1, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LDLOC_2, "ldloc.2", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x08, NEXT) + + OPDEF_EX(LO_LoadLocal, DATATYPE_FIRST_INVALID, 2, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LDLOC_3, "ldloc.3", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x09, NEXT) + + OPDEF_EX(LO_LoadLocal, DATATYPE_FIRST_INVALID, 3, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_STLOC_0, "stloc.0", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0A, NEXT) + + OPDEF_EX(LO_StoreLocal, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_STLOC_1, "stloc.1", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0B, NEXT) + + OPDEF_EX(LO_StoreLocal, DATATYPE_FIRST_INVALID, 1, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_STLOC_2, "stloc.2", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0C, NEXT) + + OPDEF_EX(LO_StoreLocal, DATATYPE_FIRST_INVALID, 2, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_STLOC_3, "stloc.3", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0D, NEXT) + + OPDEF_EX(LO_StoreLocal, DATATYPE_FIRST_INVALID, 3, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LDARG_S, "ldarg.s", Pop0, Push1, ShortInlineVar, IMacro, 1, 0xFF, 0x0E, NEXT) + + OPDEF_EX(LO_LoadArgument, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LDARGA_S, "ldarga.s", Pop0, PushI, ShortInlineVar, IMacro, 1, 0xFF, 0x0F, NEXT) + + OPDEF_EX(LO_LoadArgumentAddress, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_STARG_S, "starg.s", Pop1, Push0, ShortInlineVar, IMacro, 1, 0xFF, 0x10, NEXT) + + OPDEF_EX(LO_StoreArgument, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LDLOC_S, "ldloc.s", Pop0, Push1, ShortInlineVar, IMacro, 1, 0xFF, 0x11, NEXT) + + OPDEF_EX(LO_LoadLocal, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LDLOCA_S, "ldloca.s", Pop0, PushI, ShortInlineVar, IMacro, 1, 0xFF, 0x12, NEXT) + + OPDEF_EX(LO_LoadLocalAddress, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_STLOC_S, "stloc.s", Pop1, Push0, ShortInlineVar, IMacro, 1, 0xFF, 0x13, NEXT) + + OPDEF_EX(LO_StoreLocal, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LDNULL, "ldnull", Pop0, PushRef, InlineNone, IPrimitive, 1, 0xFF, 0x14, NEXT) + + OPDEF_EX(LO_LoadNull, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_LDC_I4_M1, "ldc.i4.m1", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x15, NEXT) + + OPDEF_EX(LO_LoadConstant_I4, DATATYPE_FIRST_INVALID, -1, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_I4) + }, + { + OPDEF(CEE_LDC_I4_0, "ldc.i4.0", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x16, NEXT) + + OPDEF_EX(LO_LoadConstant_I4, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_I4) + }, + { + OPDEF(CEE_LDC_I4_1, "ldc.i4.1", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x17, NEXT) + + OPDEF_EX(LO_LoadConstant_I4, DATATYPE_FIRST_INVALID, 1, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_I4) + }, + { + OPDEF(CEE_LDC_I4_2, "ldc.i4.2", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x18, NEXT) + + OPDEF_EX(LO_LoadConstant_I4, DATATYPE_FIRST_INVALID, 2, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_I4) + }, + { + OPDEF(CEE_LDC_I4_3, "ldc.i4.3", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x19, NEXT) + + OPDEF_EX(LO_LoadConstant_I4, DATATYPE_FIRST_INVALID, 3, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_I4) + }, + { + OPDEF(CEE_LDC_I4_4, "ldc.i4.4", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1A, NEXT) + + OPDEF_EX(LO_LoadConstant_I4, DATATYPE_FIRST_INVALID, 4, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_I4) + }, + { + OPDEF(CEE_LDC_I4_5, "ldc.i4.5", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1B, NEXT) + + OPDEF_EX(LO_LoadConstant_I4, DATATYPE_FIRST_INVALID, 5, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_I4) + }, + { + OPDEF(CEE_LDC_I4_6, "ldc.i4.6", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1C, NEXT) + + OPDEF_EX(LO_LoadConstant_I4, DATATYPE_FIRST_INVALID, 6, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_I4) + }, + { + OPDEF(CEE_LDC_I4_7, "ldc.i4.7", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1D, NEXT) + + OPDEF_EX(LO_LoadConstant_I4, DATATYPE_FIRST_INVALID, 7, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_I4) + }, + { + OPDEF(CEE_LDC_I4_8, "ldc.i4.8", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1E, NEXT) + + OPDEF_EX(LO_LoadConstant_I4, DATATYPE_FIRST_INVALID, 8, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_I4) + }, + { + OPDEF(CEE_LDC_I4_S, "ldc.i4.s", Pop0, PushI, ShortInlineI, IMacro, 1, 0xFF, 0x1F, NEXT) + + OPDEF_EX(LO_LoadConstant_I4, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_I4) + }, + { + OPDEF(CEE_LDC_I4, "ldc.i4", Pop0, PushI, InlineI, IPrimitive, 1, 0xFF, 0x20, NEXT) + + OPDEF_EX(LO_LoadConstant_I4, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_I4) + }, + { + OPDEF(CEE_LDC_I8, "ldc.i8", Pop0, PushI8, InlineI8, IPrimitive, 1, 0xFF, 0x21, NEXT) + + OPDEF_EX(LO_LoadConstant_I8, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_I8) + }, + { + OPDEF(CEE_LDC_R4, "ldc.r4", Pop0, PushR4, ShortInlineR, IPrimitive, 1, 0xFF, 0x22, NEXT) + + OPDEF_EX(LO_LoadConstant_R4, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_R4) + }, + { + OPDEF(CEE_LDC_R8, "ldc.r8", Pop0, PushR8, InlineR, IPrimitive, 1, 0xFF, 0x23, NEXT) + + OPDEF_EX(LO_LoadConstant_R8, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_R8) + }, + { + OPDEF(CEE_UNUSED49, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x24, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_DUP, "dup", Pop1, Push1+Push1, InlineNone, IPrimitive, 1, 0xFF, 0x25, NEXT) + + OPDEF_EX(LO_Dup, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_POP, "pop", Pop1, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x26, NEXT) + + OPDEF_EX(LO_Pop, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_JMP, "jmp", Pop0, Push0, InlineMethod, IPrimitive, 1, 0xFF, 0x27, CALL) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_CALL, "call", VarPop, VarPush, InlineMethod, IPrimitive, 1, 0xFF, 0x28, CALL) + + OPDEF_EX(LO_Call, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_CALLI, "calli", VarPop, VarPush, InlineSig, IPrimitive, 1, 0xFF, 0x29, CALL) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_RET, "ret", VarPop, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x2A, RETURN) + + OPDEF_EX(LO_Ret, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_ALWAYS) + }, + { + OPDEF(CEE_BR_S, "br.s", Pop0, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2B, BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_ALWAYS | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BRFALSE_S, "brfalse.s", PopI, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2C, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFFALSE | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BRTRUE_S, "brtrue.s", PopI, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2D, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFTRUE | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BEQ_S, "beq.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2E, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFEQUAL | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BGE_S, "bge.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2F, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFGREATEROREQUAL | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BGT_S, "bgt.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x30, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFGREATER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BLE_S, "ble.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x31, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFLESSOREQUAL | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BLT_S, "blt.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x32, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFLESS | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BNE_UN_S, "bne.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x33, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFNOTEQUAL | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BGE_UN_S, "bge.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x34, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFGREATEROREQUAL | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BGT_UN_S, "bgt.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x35, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFGREATER | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BLE_UN_S, "ble.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x36, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFLESSOREQUAL | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BLT_UN_S, "blt.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x37, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFLESS | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BR, "br", Pop0, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0x38, BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_ALWAYS | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BRFALSE, "brfalse", PopI, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0x39, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFFALSE | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BRTRUE, "brtrue", PopI, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0x3A, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFTRUE | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BEQ, "beq", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3B, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFEQUAL | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BGE, "bge", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3C, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFGREATEROREQUAL | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BGT, "bgt", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3D, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFGREATER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BLE, "ble", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3E, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFLESSOREQUAL | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BLT, "blt", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3F, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFLESS | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BNE_UN, "bne.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x40, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFNOTEQUAL | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BGE_UN, "bge.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x41, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFGREATEROREQUAL | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BGT_UN, "bgt.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x42, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFGREATER | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BLE_UN, "ble.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x43, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFLESSOREQUAL | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_BLT_UN, "blt.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x44, COND_BRANCH) + + OPDEF_EX(LO_Branch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFLESS | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_SWITCH, "switch", PopI, Push0, InlineSwitch, IPrimitive, 1, 0xFF, 0x45, COND_BRANCH) + + OPDEF_EX(LO_Switch, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFMATCH | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET) + }, + { + OPDEF(CEE_LDIND_I1, "ldind.i1", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x46, NEXT) + + OPDEF_EX(LO_LoadIndirect, DATATYPE_I1, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDIND_U1, "ldind.u1", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x47, NEXT) + + OPDEF_EX(LO_LoadIndirect, DATATYPE_U1, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDIND_I2, "ldind.i2", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x48, NEXT) + + OPDEF_EX(LO_LoadIndirect, DATATYPE_U2, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDIND_U2, "ldind.u2", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x49, NEXT) + + OPDEF_EX(LO_LoadIndirect, DATATYPE_U2, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDIND_I4, "ldind.i4", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x4A, NEXT) + + OPDEF_EX(LO_LoadIndirect, DATATYPE_I4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDIND_U4, "ldind.u4", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x4B, NEXT) + + OPDEF_EX(LO_LoadIndirect, DATATYPE_U4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDIND_I8, "ldind.i8", PopI, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x4C, NEXT) + + OPDEF_EX(LO_LoadIndirect, DATATYPE_I8, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDIND_I, "ldind.i", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x4D, NEXT) + + OPDEF_EX(LO_LoadIndirect, DATATYPE_I4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDIND_R4, "ldind.r4", PopI, PushR4, InlineNone, IPrimitive, 1, 0xFF, 0x4E, NEXT) + + OPDEF_EX(LO_LoadIndirect, DATATYPE_R4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDIND_R8, "ldind.r8", PopI, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0x4F, NEXT) + + OPDEF_EX(LO_LoadIndirect, DATATYPE_R8, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDIND_REF, "ldind.ref", PopI, PushRef, InlineNone, IPrimitive, 1, 0xFF, 0x50, NEXT) + + OPDEF_EX(LO_LoadIndirect, DATATYPE_OBJECT, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_STIND_REF, "stind.ref", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x51, NEXT) + + OPDEF_EX(LO_StoreIndirect, DATATYPE_OBJECT, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_STIND_I1, "stind.i1", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x52, NEXT) + + OPDEF_EX(LO_StoreIndirect, DATATYPE_I1, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_STIND_I2, "stind.i2", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x53, NEXT) + + OPDEF_EX(LO_StoreIndirect, DATATYPE_I2, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_STIND_I4, "stind.i4", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x54, NEXT) + + OPDEF_EX(LO_StoreIndirect, DATATYPE_I4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_STIND_I8, "stind.i8", PopI+PopI8, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x55, NEXT) + + OPDEF_EX(LO_StoreIndirect, DATATYPE_I8, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_STIND_R4, "stind.r4", PopI+PopR4, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x56, NEXT) + + OPDEF_EX(LO_StoreIndirect, DATATYPE_R4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_STIND_R8, "stind.r8", PopI+PopR8, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x57, NEXT) + + OPDEF_EX(LO_StoreIndirect, DATATYPE_R8, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_ADD, "add", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x58, NEXT) + + OPDEF_EX(LO_Add, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_SUB, "sub", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x59, NEXT) + + OPDEF_EX(LO_Sub, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_MUL, "mul", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5A, NEXT) + + OPDEF_EX(LO_Mul, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_DIV, "div", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5B, NEXT) + + OPDEF_EX(LO_Div, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_DIV_UN, "div.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5C, NEXT) + + OPDEF_EX(LO_Div, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_UNSIGNED) + }, + { + OPDEF(CEE_REM, "rem", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5D, NEXT) + + OPDEF_EX(LO_Rem, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_REM_UN, "rem.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5E, NEXT) + + OPDEF_EX(LO_Rem, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_UNSIGNED) + }, + { + OPDEF(CEE_AND, "and", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5F, NEXT) + + OPDEF_EX(LO_And, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_OR, "or", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x60, NEXT) + + OPDEF_EX(LO_Or, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_XOR, "xor", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x61, NEXT) + + OPDEF_EX(LO_Xor, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_SHL, "shl", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x62, NEXT) + + OPDEF_EX(LO_Shl, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_SHR, "shr", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x63, NEXT) + + OPDEF_EX(LO_Shr, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_SHR_UN, "shr.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x64, NEXT) + + OPDEF_EX(LO_Shr, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_UNSIGNED) + }, + { + OPDEF(CEE_NEG, "neg", Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x65, NEXT) + + OPDEF_EX(LO_Neg, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_NOT, "not", Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x66, NEXT) + + OPDEF_EX(LO_Not, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_CONV_I1, "conv.i1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x67, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_I1, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_I2, "conv.i2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x68, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_I2, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_I4, "conv.i4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x69, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_I4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_I8, "conv.i8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x6A, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_I8, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_R4, "conv.r4", Pop1, PushR4, InlineNone, IPrimitive, 1, 0xFF, 0x6B, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_R4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_R8, "conv.r8", Pop1, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0x6C, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_R8, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_U4, "conv.u4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x6D, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_U4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_U8, "conv.u8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x6E, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_U8, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CALLVIRT, "callvirt", VarPop, VarPush, InlineMethod, IObjModel, 1, 0xFF, 0x6F, CALL) + + OPDEF_EX(LO_CallVirt, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_CPOBJ, "cpobj", PopI+PopI, Push0, InlineType, IObjModel, 1, 0xFF, 0x70, NEXT) + + OPDEF_EX(LO_CopyObject, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_LDOBJ, "ldobj", PopI, Push1, InlineType, IObjModel, 1, 0xFF, 0x71, NEXT) + + OPDEF_EX(LO_LoadObject, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_LDSTR, "ldstr", Pop0, PushRef, InlineString, IObjModel, 1, 0xFF, 0x72, NEXT) + + OPDEF_EX(LO_LoadString, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_NEWOBJ, "newobj", VarPop, PushRef, InlineMethod, IObjModel, 1, 0xFF, 0x73, CALL) + + OPDEF_EX(LO_NewObject, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_CASTCLASS, "castclass", PopRef, PushRef, InlineType, IObjModel, 1, 0xFF, 0x74, NEXT) + + OPDEF_EX(LO_CastClass, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_ISINST, "isinst", PopRef, PushI, InlineType, IObjModel, 1, 0xFF, 0x75, NEXT) + + OPDEF_EX(LO_IsInst, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_CONV_R_UN, "conv.r.un", Pop1, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0x76, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_R4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_UNUSED58, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x77, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED1, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x78, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNBOX, "unbox", PopRef, PushI, InlineType, IPrimitive, 1, 0xFF, 0x79, NEXT) + + OPDEF_EX(LO_Unbox, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_THROW, "throw", PopRef, Push0, InlineNone, IObjModel, 1, 0xFF, 0x7A, THROW) + + OPDEF_EX(LO_Throw, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_ALWAYS | CLR_RT_OpcodeLookup::STACK_RESET) + }, + { + OPDEF(CEE_LDFLD, "ldfld", PopRef, Push1, InlineField, IObjModel, 1, 0xFF, 0x7B, NEXT) + + OPDEF_EX(LO_LoadField, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_LDFLDA, "ldflda", PopRef, PushI, InlineField, IObjModel, 1, 0xFF, 0x7C, NEXT) + + OPDEF_EX(LO_LoadFieldAddress, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_STFLD, "stfld", PopRef+Pop1, Push0, InlineField, IObjModel, 1, 0xFF, 0x7D, NEXT) + + OPDEF_EX(LO_StoreField, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_LDSFLD, "ldsfld", Pop0, Push1, InlineField, IObjModel, 1, 0xFF, 0x7E, NEXT) + + OPDEF_EX(LO_LoadStaticField, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_LDSFLDA, "ldsflda", Pop0, PushI, InlineField, IObjModel, 1, 0xFF, 0x7F, NEXT) + + OPDEF_EX(LO_LoadStaticFieldAddress, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_STSFLD, "stsfld", Pop1, Push0, InlineField, IObjModel, 1, 0xFF, 0x80, NEXT) + + OPDEF_EX(LO_StoreStaticField, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_STOBJ, "stobj", PopI+Pop1, Push0, InlineType, IPrimitive, 1, 0xFF, 0x81, NEXT) + + OPDEF_EX(LO_StoreObject, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_CONV_OVF_I1_UN, "conv.ovf.i1.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x82, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_I1, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_I2_UN, "conv.ovf.i2.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x83, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_I2, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_I4_UN, "conv.ovf.i4.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x84, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_I4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_I8_UN, "conv.ovf.i8.un", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x85, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_I8, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_U1_UN, "conv.ovf.u1.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x86, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_U1, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_U2_UN, "conv.ovf.u2.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x87, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_U2, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_U4_UN, "conv.ovf.u4.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x88, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_U4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_U8_UN, "conv.ovf.u8.un", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x89, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_U8, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_I_UN, "conv.ovf.i.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x8A, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_I4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_U_UN, "conv.ovf.u.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x8B, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_U4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::COND_UNSIGNED | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_BOX, "box", Pop1, PushRef, InlineType, IPrimitive, 1, 0xFF, 0x8C, NEXT) + + OPDEF_EX(LO_Box, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_NEWARR, "newarr", PopI, PushRef, InlineType, IObjModel, 1, 0xFF, 0x8D, NEXT) + + OPDEF_EX(LO_NewArray, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_LDLEN, "ldlen", PopRef, PushI, InlineNone, IObjModel, 1, 0xFF, 0x8E, NEXT) + + OPDEF_EX(LO_LoadLength, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER) + }, + { + OPDEF(CEE_LDELEMA, "ldelema", PopRef+PopI, PushI, InlineType, IObjModel, 1, 0xFF, 0x8F, NEXT) + + OPDEF_EX(LO_LoadElementAddress, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_LDELEM_I1, "ldelem.i1", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x90, NEXT) + + OPDEF_EX(LO_LoadElement, DATATYPE_I1, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDELEM_U1, "ldelem.u1", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x91, NEXT) + + OPDEF_EX(LO_LoadElement, DATATYPE_U1, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDELEM_I2, "ldelem.i2", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x92, NEXT) + + OPDEF_EX(LO_LoadElement, DATATYPE_I2, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDELEM_U2, "ldelem.u2", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x93, NEXT) + + OPDEF_EX(LO_LoadElement, DATATYPE_U2, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDELEM_I4, "ldelem.i4", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x94, NEXT) + + OPDEF_EX(LO_LoadElement, DATATYPE_I4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDELEM_U4, "ldelem.u4", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x95, NEXT) + + OPDEF_EX(LO_LoadElement, DATATYPE_U4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDELEM_I8, "ldelem.i8", PopRef+PopI, PushI8, InlineNone, IObjModel, 1, 0xFF, 0x96, NEXT) + + OPDEF_EX(LO_LoadElement, DATATYPE_I8, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDELEM_I, "ldelem.i", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x97, NEXT) + + OPDEF_EX(LO_LoadElement, DATATYPE_I4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDELEM_R4, "ldelem.r4", PopRef+PopI, PushR4, InlineNone, IObjModel, 1, 0xFF, 0x98, NEXT) + + OPDEF_EX(LO_LoadElement, DATATYPE_R4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDELEM_R8, "ldelem.r8", PopRef+PopI, PushR8, InlineNone, IObjModel, 1, 0xFF, 0x99, NEXT) + + OPDEF_EX(LO_LoadElement, DATATYPE_R8, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDELEM_REF, "ldelem.ref", PopRef+PopI, PushRef, InlineNone, IObjModel, 1, 0xFF, 0x9A, NEXT) + + OPDEF_EX(LO_LoadElement, DATATYPE_OBJECT, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_STELEM_I, "stelem.i", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9B, NEXT) + + OPDEF_EX(LO_StoreElement, DATATYPE_I4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_STELEM_I1, "stelem.i1", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9C, NEXT) + + OPDEF_EX(LO_StoreElement, DATATYPE_I1, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_STELEM_I2, "stelem.i2", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9D, NEXT) + + OPDEF_EX(LO_StoreElement, DATATYPE_I2, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_STELEM_I4, "stelem.i4", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9E, NEXT) + + OPDEF_EX(LO_StoreElement, DATATYPE_I4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_STELEM_I8, "stelem.i8", PopRef+PopI+PopI8, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9F, NEXT) + + OPDEF_EX(LO_StoreElement, DATATYPE_I8, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_STELEM_R4, "stelem.r4", PopRef+PopI+PopR4, Push0, InlineNone, IObjModel, 1, 0xFF, 0xA0, NEXT) + + OPDEF_EX(LO_StoreElement, DATATYPE_R4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_STELEM_R8, "stelem.r8", PopRef+PopI+PopR8, Push0, InlineNone, IObjModel, 1, 0xFF, 0xA1, NEXT) + + OPDEF_EX(LO_StoreElement, DATATYPE_R8, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_STELEM_REF, "stelem.ref", PopRef+PopI+PopRef, Push0, InlineNone, IObjModel, 1, 0xFF, 0xA2, NEXT) + + OPDEF_EX(LO_StoreElement, DATATYPE_OBJECT, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_LDELEM, "ldelem", PopRef+PopI, Push1, InlineType, IObjModel, 1, 0xFF, 0xA3, NEXT) + OPDEF_EX(LO_LoadElement, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_STELEM, "stelem", PopRef+PopI+Pop1, Push0, InlineType, IObjModel, 1, 0xFF, 0xA4, NEXT) + + OPDEF_EX(LO_StoreElement, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_UNBOX_ANY, "unbox.any", PopRef, Push1, InlineType, IObjModel, 1, 0xFF, 0xA5, NEXT) + + OPDEF_EX(LO_Unbox, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_UNUSED5, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xA6, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED6, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xA7, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED7, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xA8, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED8, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xA9, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED9, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAA, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED10, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAB, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED11, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAC, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED12, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAD, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED13, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAE, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED14, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAF, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED15, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xB0, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED16, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xB1, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED17, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xB2, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_CONV_OVF_I1, "conv.ovf.i1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB3, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_I1, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_U1, "conv.ovf.u1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB4, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_U1, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_I2, "conv.ovf.i2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB5, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_I2, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_U2, "conv.ovf.u2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB6, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_U2, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_I4, "conv.ovf.i4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB7, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_I4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_U4, "conv.ovf.u4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB8, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_U4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_I8, "conv.ovf.i8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0xB9, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_I8, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_U8, "conv.ovf.u8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0xBA, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_U8, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_UNUSED50, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBB, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED18, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBC, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED19, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBD, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED20, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBE, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED21, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBF, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED22, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC0, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED23, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC1, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_REFANYVAL, "refanyval", Pop1, PushI, InlineType, IPrimitive, 1, 0xFF, 0xC2, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_CKFINITE, "ckfinite", Pop1, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0xC3, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED24, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC4, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED25, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC5, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_MKREFANY, "mkrefany", PopI, Push1, InlineType, IPrimitive, 1, 0xFF, 0xC6, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED59, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC7, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED60, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC8, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED61, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC9, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED62, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCA, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED63, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCB, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED64, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCC, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED65, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCD, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED66, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCE, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED67, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCF, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_LDTOKEN, "ldtoken", Pop0, PushI, InlineTok, IPrimitive, 1, 0xFF, 0xD0, NEXT) + + OPDEF_EX(LO_LoadToken, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_CONV_U2, "conv.u2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD1, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_U2, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_U1, "conv.u1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD2, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_U1, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_I, "conv.i", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD3, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_I4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_I, "conv.ovf.i", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD4, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_I4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_OVF_U, "conv.ovf.u", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD5, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_U4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_ADD_OVF, "add.ovf", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD6, NEXT) + + OPDEF_EX(LO_Add, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW) + }, + { + OPDEF(CEE_ADD_OVF_UN, "add.ovf.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD7, NEXT) + + OPDEF_EX(LO_Add, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::COND_UNSIGNED) + }, + { + OPDEF(CEE_MUL_OVF, "mul.ovf", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD8, NEXT) + + OPDEF_EX(LO_Mul, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW) + }, + { + OPDEF(CEE_MUL_OVF_UN, "mul.ovf.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD9, NEXT) + + OPDEF_EX(LO_Mul, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::COND_UNSIGNED) + }, + { + OPDEF(CEE_SUB_OVF, "sub.ovf", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xDA, NEXT) + + OPDEF_EX(LO_Sub, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW) + }, + { + OPDEF(CEE_SUB_OVF_UN, "sub.ovf.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xDB, NEXT) + + OPDEF_EX(LO_Sub, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::COND_OVERFLOW | CLR_RT_OpcodeLookup::COND_UNSIGNED) + }, + { + OPDEF(CEE_ENDFINALLY, "endfinally", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xDC, RETURN) + + OPDEF_EX(LO_EndFinally, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_ALWAYS | CLR_RT_OpcodeLookup::STACK_RESET) + }, + { + OPDEF(CEE_LEAVE, "leave", Pop0, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0xDD, BRANCH) + + OPDEF_EX(LO_Leave, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_ALWAYS | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET | CLR_RT_OpcodeLookup::STACK_RESET) + }, + { + OPDEF(CEE_LEAVE_S, "leave.s", Pop0, Push0, ShortInlineBrTarget,IPrimitive, 1, 0xFF, 0xDE, BRANCH) + + OPDEF_EX(LO_Leave, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_ALWAYS | CLR_RT_OpcodeLookup::ATTRIB_HAS_TARGET | CLR_RT_OpcodeLookup::STACK_RESET) + }, + { + OPDEF(CEE_STIND_I, "stind.i", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xDF, NEXT) + + OPDEF_EX(LO_StoreIndirect, DATATYPE_I4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_CONV_U, "conv.u", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xE0, NEXT) + + OPDEF_EX(LO_Convert, DATATYPE_U4, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_DT) + }, + { + OPDEF(CEE_UNUSED26, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE1, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED27, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE2, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED28, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE3, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED29, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE4, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED30, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE5, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED31, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE6, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED32, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE7, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED33, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE8, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED34, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE9, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED35, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEA, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED36, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEB, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED37, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEC, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED38, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xED, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED39, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEE, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED40, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEF, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED41, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF0, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED42, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF1, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED43, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF2, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED44, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF3, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED45, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF4, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED46, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF5, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED47, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF6, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED48, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF7, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_PREFIX7, "prefix7", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xF8, META) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_PREFIX6, "prefix6", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xF9, META) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_PREFIX5, "prefix5", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFA, META) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_PREFIX4, "prefix4", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFB, META) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_PREFIX3, "prefix3", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFC, META) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_PREFIX2, "prefix2", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFD, META) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_PREFIX1, "prefix1", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFE, META) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_PREFIXREF, "prefixref", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFF, META) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_ARGLIST, "arglist", Pop0, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x00, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_CEQ, "ceq", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x01, NEXT) + + OPDEF_EX(LO_Set, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFEQUAL) + }, + { + OPDEF(CEE_CGT, "cgt", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x02, NEXT) + + OPDEF_EX(LO_Set, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFGREATER) + }, + { + OPDEF(CEE_CGT_UN, "cgt.un", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x03, NEXT) + + OPDEF_EX(LO_Set, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFGREATER | CLR_RT_OpcodeLookup::COND_UNSIGNED) + }, + { + OPDEF(CEE_CLT, "clt", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x04, NEXT) + + OPDEF_EX(LO_Set, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFLESS) + }, + { + OPDEF(CEE_CLT_UN, "clt.un", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x05, NEXT) + + OPDEF_EX(LO_Set, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_IFLESS | CLR_RT_OpcodeLookup::COND_UNSIGNED) + }, + { + OPDEF(CEE_LDFTN, "ldftn", Pop0, PushI, InlineMethod, IPrimitive, 2, 0xFE, 0x06, NEXT) + + OPDEF_EX(LO_LoadFunction, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_LDVIRTFTN, "ldvirtftn", PopRef, PushI, InlineMethod, IPrimitive, 2, 0xFE, 0x07, NEXT) + + OPDEF_EX(LO_LoadVirtFunction, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_UNUSED56, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x08, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_LDARG, "ldarg", Pop0, Push1, InlineVar, IPrimitive, 2, 0xFE, 0x09, NEXT) + + OPDEF_EX(LO_LoadArgument, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LDARGA, "ldarga", Pop0, PushI, InlineVar, IPrimitive, 2, 0xFE, 0x0A, NEXT) + + OPDEF_EX(LO_LoadArgumentAddress, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_STARG, "starg", Pop1, Push0, InlineVar, IPrimitive, 2, 0xFE, 0x0B, NEXT) + + OPDEF_EX(LO_StoreArgument, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LDLOC, "ldloc", Pop0, Push1, InlineVar, IPrimitive, 2, 0xFE, 0x0C, NEXT) + + OPDEF_EX(LO_LoadLocal, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LDLOCA, "ldloca", Pop0, PushI, InlineVar, IPrimitive, 2, 0xFE, 0x0D, NEXT) + + OPDEF_EX(LO_LoadLocalAddress, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_STLOC, "stloc", Pop1, Push0, InlineVar, IPrimitive, 2, 0xFE, 0x0E, NEXT) + + OPDEF_EX(LO_StoreLocal, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) + }, + { + OPDEF(CEE_LOCALLOC, "localloc", PopI, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x0F, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED57, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x10, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_ENDFILTER, "endfilter", PopI, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x11, RETURN) + + OPDEF_EX(LO_EndFilter, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_ALWAYS | CLR_RT_OpcodeLookup::STACK_RESET) + }, + { + OPDEF(CEE_UNALIGNED, "unaligned.", Pop0, Push0, ShortInlineI, IPrefix, 2, 0xFE, 0x12, META) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_VOLATILE, "volatile.", Pop0, Push0, InlineNone, IPrefix, 2, 0xFE, 0x13, META) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_TAILCALL, "tail.", Pop0, Push0, InlineNone, IPrefix, 2, 0xFE, 0x14, META) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_INITOBJ, "initobj", PopI, Push0, InlineType, IObjModel, 2, 0xFE, 0x15, NEXT) + + OPDEF_EX(LO_InitObject, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_CONSTRAINED, "constrained.", Pop0, Push0, InlineType, IPrefix, 2, 0xFE, 0x16, META) + + OPDEF_EX(LO_Nop, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_NEVER | CLR_RT_OpcodeLookup::ATTRIB_HAS_TOKEN) + }, + { + OPDEF(CEE_CPBLK, "cpblk", PopI+PopI+PopI, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x17, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_INITBLK, "initblk", PopI+PopI+PopI, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x18, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED69, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x19, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_RETHROW, "rethrow", Pop0, Push0, InlineNone, IObjModel, 2, 0xFE, 0x1A, THROW) + + OPDEF_EX(LO_Rethrow, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_ALWAYS) + }, + { + OPDEF(CEE_UNUSED51, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x1B, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_SIZEOF, "sizeof", Pop0, PushI, InlineType, IPrimitive, 2, 0xFE, 0x1C, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_REFANYTYPE, "refanytype", Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x1D, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_READONLY, "readonly.", Pop0, Push0, InlineNone, IPrefix, 2, 0xFE, 0x1E, META) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED53, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x1F, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED54, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x20, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED55, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x21, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, + { + OPDEF(CEE_UNUSED70, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x22, NEXT) + + OPDEF_EX(LO_Unsupported, DATATYPE_FIRST_INVALID, 0, CLR_RT_OpcodeLookup::COND_BRANCH_THROW) + }, +}; + +#undef OPDEF_NAME +#undef OPDEF_STACKCHANGE +#undef OPDEF_EX +#undef OPDEF + +//--// + +#undef LoadString // Legacy Windows macro, whatever... + +#if defined(TINYCLR_OPCODE_NAMES) +#define OPDEF_NAME(name) #name, +#else +#define OPDEF_NAME(name) +#endif + +#define OPDEF(name,flags) OPDEF_NAME(name) flags + +#define VAL_NONE 0 +#define VAL_RP CLR_RT_LogicalOpcodeLookup::RESTARTPOINT_NEXT +#define VAL_EX CLR_RT_LogicalOpcodeLookup::EXCEPTION +#define VAL_EX_ZERO CLR_RT_LogicalOpcodeLookup::EXCEPTION_IF_ZERO +#define VAL_EX_OVF CLR_RT_LogicalOpcodeLookup::EXCEPTION_IF_OVERFLOW + +const CLR_RT_LogicalOpcodeLookup c_CLR_RT_LogicalOpcodeLookup[] = +{ + OPDEF(Not , VAL_NONE ), // LO_Not = 0x00, + OPDEF(And , VAL_NONE ), // LO_And = 0x01, + OPDEF(Or , VAL_NONE ), // LO_Or = 0x02, + OPDEF(Xor , VAL_NONE ), // LO_Xor = 0x03, + OPDEF(Shl , VAL_NONE ), // LO_Shl = 0x04, + OPDEF(Shr , VAL_NONE ), // LO_Shr = 0x05, + + OPDEF(Neg , VAL_NONE ), // LO_Neg = 0x06, + OPDEF(Add , VAL_EX_OVF ), // LO_Add = 0x07, + OPDEF(Sub , VAL_EX_OVF ), // LO_Sub = 0x08, + OPDEF(Mul , VAL_EX_OVF ), // LO_Mul = 0x09, + OPDEF(Div , VAL_EX_ZERO ), // LO_Div = 0x0A, + OPDEF(Rem , VAL_EX_ZERO ), // LO_Rem = 0x0B, + + OPDEF(Box , VAL_EX ), // LO_Box = 0x0C, + OPDEF(Unbox , VAL_EX ), // LO_Unbox = 0x0D, + + OPDEF(Branch , VAL_NONE ), // LO_Branch = 0x0E, + OPDEF(Set , VAL_NONE ), // LO_Set = 0x0F, + OPDEF(Switch , VAL_NONE ), // LO_Switch = 0x10, + + OPDEF(LoadFunction , VAL_EX ), // LO_LoadFunction = 0x11, + OPDEF(LoadVirtFunction , VAL_EX ), // LO_LoadVirtFunction = 0x12, + + OPDEF(Call , VAL_EX | VAL_RP), // LO_Call = 0x13, + OPDEF(CallVirt , VAL_EX | VAL_RP), // LO_CallVirt = 0x14, + OPDEF(Ret , VAL_NONE ), // LO_Ret = 0x15, + + OPDEF(NewObject , VAL_EX | VAL_RP), // LO_NewObject = 0x16, + OPDEF(CastClass , VAL_EX ), // LO_CastClass = 0x17, + OPDEF(IsInst , VAL_NONE ), // LO_IsInst = 0x18, + + OPDEF(Dup , VAL_NONE ), // LO_Dup = 0x19, + OPDEF(Pop , VAL_NONE ), // LO_Pop = 0x1A, + + OPDEF(Throw , VAL_EX ), // LO_Throw = 0x1B, + OPDEF(Rethrow , VAL_EX ), // LO_Rethrow = 0x1C, + OPDEF(Leave , VAL_NONE ), // LO_Leave = 0x1D, + OPDEF(EndFinally , VAL_EX ), // LO_EndFinally = 0x1E, + + OPDEF(Convert , VAL_EX_OVF ), // LO_Convert = 0x1F, + + OPDEF(StoreArgument , VAL_NONE ), // LO_StoreArgument = 0x20, + OPDEF(LoadArgument , VAL_NONE ), // LO_LoadArgument = 0x21, + OPDEF(LoadArgumentAddress , VAL_NONE ), // LO_LoadArgumentAddress = 0x22, + + OPDEF(StoreLocal , VAL_NONE ), // LO_StoreLocal = 0x23, + OPDEF(LoadLocal , VAL_NONE ), // LO_LoadLocal = 0x24, + OPDEF(LoadLocalAddress , VAL_NONE ), // LO_LoadLocalAddress = 0x25, + + OPDEF(LoadConstant_I4 , VAL_NONE ), // LO_LoadConstant_I4 = 0x26, + OPDEF(LoadConstant_I8 , VAL_NONE ), // LO_LoadConstant_I8 = 0x27, + OPDEF(LoadConstant_R4 , VAL_NONE ), // LO_LoadConstant_R4 = 0x28, + OPDEF(LoadConstant_R8 , VAL_NONE ), // LO_LoadConstant_R8 = 0x29, + + OPDEF(LoadNull , VAL_NONE ), // LO_LoadNull = 0x2A, + OPDEF(LoadString , VAL_EX ), // LO_LoadString = 0x2B, + OPDEF(LoadToken , VAL_NONE ), // LO_LoadToken = 0x2C, + + OPDEF(NewArray , VAL_EX ), // LO_NewArray = 0x2D, + OPDEF(LoadLength , VAL_EX ), // LO_LoadLength = 0x2E, + + OPDEF(StoreElement , VAL_EX ), // LO_StoreElement = 0x2F, + OPDEF(LoadElement , VAL_EX ), // LO_LoadElement = 0x30, + OPDEF(LoadElementAddress , VAL_EX ), // LO_LoadElementAddress = 0x31, + + OPDEF(StoreField , VAL_EX ), // LO_StoreField = 0x32, + OPDEF(LoadField , VAL_EX ), // LO_LoadField = 0x33, + OPDEF(LoadFieldAddress , VAL_EX ), // LO_LoadFieldAddress = 0x34, + + OPDEF(StoreStaticField , VAL_NONE ), // LO_StoreStaticField = 0x35, + OPDEF(LoadStaticField , VAL_NONE ), // LO_LoadStaticField = 0x36, + OPDEF(LoadStaticFieldAddress, VAL_NONE ), // LO_LoadStaticFieldAddress = 0x37, + + OPDEF(StoreIndirect , VAL_EX ), // LO_StoreIndirect = 0x38, + OPDEF(LoadIndirect , VAL_EX ), // LO_LoadIndirect = 0x39, + + OPDEF(InitObject , VAL_NONE ), // LO_InitObject = 0x3A, + OPDEF(LoadObject , VAL_EX ), // LO_LoadObject = 0x3B, + OPDEF(CopyObject , VAL_EX ), // LO_CopyObject = 0x3C, + OPDEF(StoreObject , VAL_EX ), // LO_StoreObject = 0x3D, + + OPDEF(Nop , VAL_NONE ), // LO_Nop = 0x3E, + + OPDEF(EndFilter , VAL_EX ), // LO_EndFilter = 0x3F, + + OPDEF(Unsupported , VAL_NONE ), // LO_Unsupported = 0x40, +}; diff --git a/src/CLR/Core/Various.cpp b/src/CLR/Core/Various.cpp new file mode 100644 index 0000000000..82ffb6459e --- /dev/null +++ b/src/CLR/Core/Various.cpp @@ -0,0 +1,125 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Core.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_RT_GetVersion( UINT16* pMajor, UINT16* pMinor, UINT16* pBuild, UINT16* pRevision ) +{ + NATIVE_PROFILE_CLR_CORE(); + if (pMajor) *pMajor = VERSION_MAJOR; + if (pMinor) *pMinor = VERSION_MINOR; + if (pBuild) *pBuild = VERSION_BUILD; + if (pRevision) *pRevision = VERSION_REVISION; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_ArrayListHelper::PrepareArrayList( CLR_RT_HeapBlock& thisRef, int count, int capacity ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock* pThis = thisRef.Dereference(); FAULT_ON_NULL(pThis); + + if(count > capacity || capacity < 1) + { + TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); + } + + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( pThis[ FIELD__m_items ], capacity, g_CLR_RT_WellKnownTypes.m_Object )); + + pThis[ FIELD__m_size ].NumericByRef().s4 = count; + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ArrayListHelper::ExtractArrayFromArrayList( CLR_RT_HeapBlock & thisRef, CLR_RT_HeapBlock_Array* & array, int& count, int& capacity ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock* pThis; + CLR_RT_HeapBlock* items; + + pThis = thisRef.Dereference(); FAULT_ON_NULL(pThis); + items = &pThis[ FIELD__m_items ]; + + if(items->DataType() != DATATYPE_OBJECT) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + array = items->DereferenceArray(); FAULT_ON_NULL(array); + + if(array->DataType() != DATATYPE_SZARRAY) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + capacity = array->m_numOfElements; + count = pThis[ FIELD__m_size ].NumericByRef().s4; + + TINYCLR_NOCLEANUP(); +} + +//--// + +HRESULT CLR_RT_ByteArrayReader::Init( const UINT8* src, UINT32 srcSize ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + if (src == NULL || srcSize == 0) TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + + source = src; + sourceSize = srcSize; + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ByteArrayReader::Read( void* dst, UINT32 size ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + if (size > sourceSize) TINYCLR_SET_AND_LEAVE(CLR_E_FAIL); + + memcpy( dst, source, size ); + + source += size; + sourceSize -= size; + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ByteArrayReader::Read1Byte( void* dst ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + if (1 > sourceSize) TINYCLR_SET_AND_LEAVE(CLR_E_FAIL); + + *(UINT8*)dst = *source; + + source++; + sourceSize--; + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ByteArrayReader::Skip( UINT32 size ) +{ + NATIVE_PROFILE_CLR_CORE(); + TINYCLR_HEADER(); + + if (size > sourceSize) TINYCLR_SET_AND_LEAVE(CLR_E_FAIL); + + source += size; + sourceSize -= size; + + TINYCLR_NOCLEANUP(); +} diff --git a/src/CLR/Core/corhdr_private.h b/src/CLR/Core/corhdr_private.h new file mode 100644 index 0000000000..a6943b7274 --- /dev/null +++ b/src/CLR/Core/corhdr_private.h @@ -0,0 +1,110 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _TINYCLR_CORHDR_H_ +#define _TINYCLR_CORHDR_H_ + +///////////////////////////////////////////////////////////////////////////// +// +// !!!! Lifted verbatim from corhdr.h !!!!! +// https://github.com/dotnet/coreclr/blob/master/src/inc/corhdr.h +// + +//***************************************************************************** +// +// Element type for Cor signature +// +//***************************************************************************** + +typedef enum CorElementType +{ + ELEMENT_TYPE_END = 0x0, + ELEMENT_TYPE_VOID = 0x1, + ELEMENT_TYPE_BOOLEAN = 0x2, + ELEMENT_TYPE_CHAR = 0x3, + ELEMENT_TYPE_I1 = 0x4, + ELEMENT_TYPE_U1 = 0x5, + ELEMENT_TYPE_I2 = 0x6, + ELEMENT_TYPE_U2 = 0x7, + ELEMENT_TYPE_I4 = 0x8, + ELEMENT_TYPE_U4 = 0x9, + ELEMENT_TYPE_I8 = 0xa, + ELEMENT_TYPE_U8 = 0xb, + ELEMENT_TYPE_R4 = 0xc, + ELEMENT_TYPE_R8 = 0xd, + ELEMENT_TYPE_STRING = 0xe, + + // every type above PTR will be simple type + ELEMENT_TYPE_PTR = 0xf, // PTR + ELEMENT_TYPE_BYREF = 0x10, // BYREF + + // Please use ELEMENT_TYPE_VALUETYPE. ELEMENT_TYPE_VALUECLASS is deprecated. + ELEMENT_TYPE_VALUETYPE = 0x11, // VALUETYPE + ELEMENT_TYPE_CLASS = 0x12, // CLASS + ELEMENT_TYPE_VAR = 0x13, // a class type variable VAR + ELEMENT_TYPE_ARRAY = 0x14, // MDARRAY ... ... + ELEMENT_TYPE_GENERICINST = 0x15, // instantiated type + ELEMENT_TYPE_TYPEDBYREF = 0x16, // This is a simple type. + + ELEMENT_TYPE_I = 0x18, // native integer size + ELEMENT_TYPE_U = 0x19, // native unsigned integer size + ELEMENT_TYPE_FNPTR = 0x1B, // FNPTR + ELEMENT_TYPE_OBJECT = 0x1C, // Shortcut for System.Object + ELEMENT_TYPE_SZARRAY = 0x1D, // Shortcut for single dimension zero lower bound array + // SZARRAY + ELEMENT_TYPE_MVAR = 0x1e, // a method type variable MVAR + + // This is only for binding + ELEMENT_TYPE_CMOD_REQD = 0x1F, // required C modifier : E_T_CMOD_REQD + ELEMENT_TYPE_CMOD_OPT = 0x20, // optional C modifier : E_T_CMOD_OPT + + // This is for signatures generated internally (which will not be persisted in any way). + ELEMENT_TYPE_INTERNAL = 0x21, // INTERNAL + + // Note that this is the max of base type excluding modifiers + ELEMENT_TYPE_MAX = 0x22, // first invalid element type + + + ELEMENT_TYPE_MODIFIER = 0x40, + ELEMENT_TYPE_SENTINEL = 0x01 | ELEMENT_TYPE_MODIFIER, // sentinel for varargs + ELEMENT_TYPE_PINNED = 0x05 | ELEMENT_TYPE_MODIFIER, + ELEMENT_TYPE_R4_HFA = 0x06 | ELEMENT_TYPE_MODIFIER, // used only internally for R4 HFA types + ELEMENT_TYPE_R8_HFA = 0x07 | ELEMENT_TYPE_MODIFIER, // used only internally for R8 HFA types + +} CorElementType; + +//***************************************************************************** +// +// Serialization types for Custom attribute support +// +//***************************************************************************** + +typedef enum CorSerializationType +{ + SERIALIZATION_TYPE_UNDEFINED = 0, + SERIALIZATION_TYPE_BOOLEAN = ELEMENT_TYPE_BOOLEAN, + SERIALIZATION_TYPE_CHAR = ELEMENT_TYPE_CHAR, + SERIALIZATION_TYPE_I1 = ELEMENT_TYPE_I1, + SERIALIZATION_TYPE_U1 = ELEMENT_TYPE_U1, + SERIALIZATION_TYPE_I2 = ELEMENT_TYPE_I2, + SERIALIZATION_TYPE_U2 = ELEMENT_TYPE_U2, + SERIALIZATION_TYPE_I4 = ELEMENT_TYPE_I4, + SERIALIZATION_TYPE_U4 = ELEMENT_TYPE_U4, + SERIALIZATION_TYPE_I8 = ELEMENT_TYPE_I8, + SERIALIZATION_TYPE_U8 = ELEMENT_TYPE_U8, + SERIALIZATION_TYPE_R4 = ELEMENT_TYPE_R4, + SERIALIZATION_TYPE_R8 = ELEMENT_TYPE_R8, + SERIALIZATION_TYPE_STRING = ELEMENT_TYPE_STRING, + SERIALIZATION_TYPE_SZARRAY = ELEMENT_TYPE_SZARRAY, // Shortcut for single dimension zero lower bound array + SERIALIZATION_TYPE_TYPE = 0x50, + SERIALIZATION_TYPE_TAGGED_OBJECT= 0x51, + SERIALIZATION_TYPE_FIELD = 0x53, + SERIALIZATION_TYPE_PROPERTY = 0x54, + SERIALIZATION_TYPE_ENUM = 0x55 +} CorSerializationType; + +///////////////////////////////////////////////////////////////////////////// + +#endif // _TINYCLR_CORHDR_H_ diff --git a/src/CLR/Debugger/Debugger.cpp b/src/CLR/Debugger/Debugger.cpp new file mode 100644 index 0000000000..89f1ab8a27 --- /dev/null +++ b/src/CLR/Debugger/Debugger.cpp @@ -0,0 +1,3264 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include +#include + +#include + +#if 0 +#define TRACE0( msg, ...) debug_printf( msg ) +#define TRACE( msg, ...) debug_printf( msg, __VA_ARGS__ ) +char const* const AccessMemoryModeNames[] = { +"AccessMemory_Check", +"AccessMemory_Read", +"AccessMemory_Write", +"AccessMemory_Erase" +}; +#else +#define TRACE0(msg,...) +#define TRACE(msg,...) +#endif + +//--// + +BlockStorageDevice* CLR_DBG_Debugger::m_deploymentStorageDevice = NULL; + +//--// + +void CLR_DBG_Debugger::Debugger_WaitForCommands() +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + +#if !defined(BUILD_RTM) + // UNDONE: FIXME: hal_fprintf(STREAM_LCD, "\r\nWaiting for debug commands...\r\n"); + CLR_Debug::Printf( "Waiting for debug commands...\r\n" ); +#endif + + while( !CLR_EE_DBG_IS(RebootPending) && !CLR_EE_DBG_IS(ExitPending) ) + { + g_CLR_RT_ExecutionEngine.DebuggerLoop(); + } +} + +void CLR_DBG_Debugger::Debugger_Discovery() +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_INT32 wait_sec = 5; + + CLR_INT64 expire = Time_GetMachineTime() + (wait_sec * TIME_CONVERSION__TO_SECONDS); + + // + // Send "presence" ping. + // + CLR_DBG_Commands::Monitor_Ping cmd; + + cmd.m_source = CLR_DBG_Commands::Monitor_Ping::c_Ping_Source_TinyCLR; + + while(true) + { + CLR_EE_DBG_EVENT_BROADCAST(CLR_DBG_Commands::c_Monitor_Ping, sizeof(cmd), &cmd, WP_Flags::c_NoCaching | WP_Flags::c_NonCritical); + + // if we support soft reboot and the debugger is not stopped then we don't need to connect the debugger + if(!CLR_EE_DBG_IS(Stopped) && ::CPU_IsSoftRebootSupported()) + { + break; + } + + g_CLR_RT_ExecutionEngine.DebuggerLoop(); + + if(CLR_EE_DBG_IS(Enabled)) + { + // + // Debugger on the other side, let's exit the discovery loop. + // + CLR_Debug::Printf( "Found debugger!\r\n" ); + break; + } + + CLR_INT64 now = Time_GetMachineTime(); + + if(expire < now) + { + // + // No response in time... + // + CLR_Debug::Printf( "No debugger!\r\n" ); + break; + } + } + + g_CLR_RT_ExecutionEngine.WaitForDebugger(); +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_DBG_Debugger::CreateInstance() +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + TINYCLR_HEADER(); + + int iDebugger = 0; + + g_CLR_DBG_Debuggers = (CLR_DBG_Debugger*)&g_scratchDebugger[ 0 ]; + + CLR_RT_Memory::ZeroFill( g_scratchDebuggerMessaging, sizeof(CLR_Messaging) * NUM_DEBUGGERS ); + + CLR_RT_Memory::ZeroFill( g_CLR_DBG_Debuggers, sizeof(CLR_DBG_Debugger) * NUM_DEBUGGERS ); + + TINYCLR_FOREACH_DEBUGGER_NO_TEMP() + { + if(HalSystemConfig.DebuggerPorts[ iDebugger ] == HalSystemConfig.MessagingPorts[ 0 ]) + { + g_CLR_DBG_Debuggers[ iDebugger ].m_messaging = &g_CLR_Messaging[ 0 ]; + } + else + { + g_CLR_DBG_Debuggers[iDebugger].m_messaging = (CLR_Messaging*)&g_scratchDebuggerMessaging[ iDebugger ]; + } + + TINYCLR_CHECK_HRESULT(g_CLR_DBG_Debuggers[ iDebugger ].Debugger_Initialize( HalSystemConfig.DebuggerPorts[ iDebugger ] )); + iDebugger++; + } + TINYCLR_FOREACH_DEBUGGER_END(); + + BlockStorageStream stream; + + if (stream.Initialize( BlockUsage::DEPLOYMENT )) + { + m_deploymentStorageDevice = stream.Device; + } + else + { + m_deploymentStorageDevice = NULL; + } + + // UNDONE: FIXME: MFUpdate_Initialize(); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_DBG_Debugger::Debugger_Initialize( COM_HANDLE port ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + TINYCLR_HEADER(); + + m_messaging->Initialize( port, c_Debugger_Lookup_Request, c_Debugger_Lookup_Request_count, c_Debugger_Lookup_Reply, c_Debugger_Lookup_Reply_count, (void*)this ); + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +//--// + +HRESULT CLR_DBG_Debugger::DeleteInstance() +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + TINYCLR_HEADER(); + + TINYCLR_FOREACH_DEBUGGER(dbg) + { + dbg.Debugger_Cleanup(); + } + TINYCLR_FOREACH_DEBUGGER_END(); + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +void CLR_DBG_Debugger::Debugger_Cleanup() +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + m_messaging->Cleanup(); +} + +//--// + +void CLR_DBG_Debugger::ProcessCommands() +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + m_messaging->m_controller.AdvanceState(); +} + +void CLR_DBG_Debugger::PurgeCache() +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + m_messaging->PurgeCache(); +} + +void CLR_DBG_Debugger::BroadcastEvent( UINT32 cmd, UINT32 payloadSize, UINT8* payload, UINT32 flags ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + TINYCLR_FOREACH_DEBUGGER(dbg) + { + dbg.m_messaging->SendEvent( cmd, payloadSize, payload, flags ); + } + TINYCLR_FOREACH_DEBUGGER_END(); +} + +//--// + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + +#if defined(TINYCLR_APPDOMAINS) + +CLR_RT_AppDomain* CLR_DBG_Debugger::GetAppDomainFromID( CLR_UINT32 id ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + TINYCLR_FOREACH_NODE(CLR_RT_AppDomain, appDomain, g_CLR_RT_ExecutionEngine.m_appDomains) + { + if(appDomain->m_id == id) return appDomain; + } + TINYCLR_FOREACH_NODE_END(); + + return NULL; +} +#endif //TINYCLR_APPDOMAINS + +CLR_RT_Thread* CLR_DBG_Debugger::GetThreadFromPid( CLR_UINT32 pid ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + TINYCLR_FOREACH_NODE(CLR_RT_Thread,th,g_CLR_RT_ExecutionEngine.m_threadsReady) + { + if(th->m_pid == pid) return th; + } + TINYCLR_FOREACH_NODE_END(); + + TINYCLR_FOREACH_NODE(CLR_RT_Thread,th,g_CLR_RT_ExecutionEngine.m_threadsWaiting) + { + if(th->m_pid == pid) return th; + } + TINYCLR_FOREACH_NODE_END(); + + return NULL; +} + +HRESULT CLR_DBG_Debugger::CreateListOfThreads( CLR_DBG_Commands::Debugging_Thread_List::Reply*& cmdReply, int& totLen ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + TINYCLR_HEADER(); + + CLR_UINT32* pidDst; + int num; + + num = g_CLR_RT_ExecutionEngine.m_threadsReady .NumOfNodes() + + g_CLR_RT_ExecutionEngine.m_threadsWaiting.NumOfNodes(); + + totLen = sizeof(*cmdReply) + (num-1) * sizeof(CLR_UINT32); + + cmdReply = (CLR_DBG_Commands::Debugging_Thread_List::Reply*)CLR_RT_Memory::Allocate_And_Erase( totLen, true ); CHECK_ALLOCATION(cmdReply); + + cmdReply->m_num = num; + + pidDst = cmdReply->m_pids; + + TINYCLR_FOREACH_NODE(CLR_RT_Thread,thSrc,g_CLR_RT_ExecutionEngine.m_threadsReady) + { + *pidDst++ = thSrc->m_pid; + } + TINYCLR_FOREACH_NODE_END(); + + TINYCLR_FOREACH_NODE(CLR_RT_Thread,thSrc,g_CLR_RT_ExecutionEngine.m_threadsWaiting) + { + *pidDst++ = thSrc->m_pid; + } + TINYCLR_FOREACH_NODE_END(); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_DBG_Debugger::CreateListOfCalls( CLR_UINT32 pid, CLR_DBG_Commands::Debugging_Thread_Stack::Reply*& cmdReply, int& totLen ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + TINYCLR_HEADER(); + + CLR_RT_Thread* th = GetThreadFromPid( pid ); FAULT_ON_NULL(th); + + for(int pass=0; pass<2; pass++) + { + int num = 0; + + TINYCLR_FOREACH_NODE(CLR_RT_StackFrame,call,th->m_stackFrames) + { + if(pass == 1) + { + int tmp = num; + +#ifndef TINYCLR_NO_IL_INLINE + if(call->m_inlineFrame) + { + CLR_DBG_Commands::Debugging_Thread_Stack::Reply::Call& dst = cmdReply->m_data[ tmp++ ]; + + dst.m_md = call->m_inlineFrame->m_frame.m_call; + dst.m_IP = (CLR_UINT32)(call->m_inlineFrame->m_frame.m_IP - call->m_inlineFrame->m_frame.m_IPStart); +#if defined(TINYCLR_APPDOMAINS) + dst.m_appDomainID = call->m_appDomain->m_id; + dst.m_flags = call->m_flags; +#endif + } +#endif + CLR_DBG_Commands::Debugging_Thread_Stack::Reply::Call& dst = cmdReply->m_data[ tmp ]; + + dst.m_md = call->m_call; + dst.m_IP = (CLR_UINT32)(call->m_IP - call->m_IPstart); + + if(dst.m_IP && call != th->CurrentFrame()) + { + //With the exception of when the IP is 0, for a breakpoint on Push, + //The call->m_IP is the next instruction to execute, not the currently executing one. + //For non-leaf frames, this will return the IP within the call. + dst.m_IP--; + } + +#if defined(TINYCLR_APPDOMAINS) + dst.m_appDomainID = call->m_appDomain->m_id; + dst.m_flags = call->m_flags; +#endif + } + +#ifndef TINYCLR_NO_IL_INLINE + if(call->m_inlineFrame) + { + num++; + } +#endif + + num++; + } + TINYCLR_FOREACH_NODE_END(); + + if(pass == 0) + { + totLen = sizeof(*cmdReply) + (num-1) * sizeof(CLR_DBG_Commands::Debugging_Thread_Stack::Reply::Call); + + cmdReply = (CLR_DBG_Commands::Debugging_Thread_Stack::Reply*)CLR_RT_Memory::Allocate_And_Erase( totLen, CLR_RT_HeapBlock::HB_CompactOnFailure ); CHECK_ALLOCATION(cmdReply); + + cmdReply->m_num = num; + cmdReply->m_status = th->m_status; + cmdReply->m_flags = th->m_flags; + } + } + + TINYCLR_NOCLEANUP(); +} + +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +bool CLR_DBG_Debugger::Monitor_Ping( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + bool fStopOnBoot = true; + + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + + // + // There's someone on the other side!! + // + CLR_EE_DBG_SET( Enabled ); + + if((msg->m_header.m_flags & WP_Flags::c_Reply ) == 0) + { + CLR_DBG_Commands::Monitor_Ping::Reply cmdReply; + CLR_DBG_Commands::Monitor_Ping *cmd = (CLR_DBG_Commands::Monitor_Ping*)msg->m_payload; + + // default is to stop the debugger (backwards compatibility) + fStopOnBoot = (cmd != NULL) && (cmd->m_dbg_flags & CLR_DBG_Commands::Monitor_Ping::c_Ping_DbgFlag_Stop); + + cmdReply.m_source = CLR_DBG_Commands::Monitor_Ping::c_Ping_Source_TinyCLR; + + cmdReply.m_dbg_flags = CLR_EE_DBG_IS(State_ProgramExited) != 0 ? CLR_DBG_Commands::Monitor_Ping::c_Ping_DbgFlag_AppExit : 0; + + dbg->m_messaging->ReplyToCommand( msg, true, false, &cmdReply, sizeof(cmdReply) ); + } + else + { + CLR_DBG_Commands::Monitor_Ping::Reply *cmdReply = (CLR_DBG_Commands::Monitor_Ping::Reply*)msg->m_payload; + + // default is to stop the debugger (backwards compatibility) + fStopOnBoot = (cmdReply != NULL) && (cmdReply->m_dbg_flags & CLR_DBG_Commands::Monitor_Ping::c_Ping_DbgFlag_Stop); + } + + if(CLR_EE_DBG_IS_MASK(State_Initialize, State_Mask)) + { + if(fStopOnBoot) CLR_EE_DBG_SET(Stopped); + else CLR_EE_DBG_CLR(Stopped); + } + + return true; +} + +bool CLR_DBG_Debugger::Monitor_FlashSectorMap( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + + if((msg->m_header.m_flags & WP_Flags::c_Reply) == 0) + { + struct Flash_Sector + { + UINT32 Start; + UINT32 Length; + UINT32 Usage; + + } *pData = NULL; + + UINT32 rangeCount = 0; + UINT32 rangeIndex = 0; + + for(int cnt = 0; cnt < 2; cnt++) + { + BlockStorageDevice* device = BlockStorageList::GetFirstDevice(); + + if(device == NULL) + { + dbg->m_messaging->ReplyToCommand( msg, true, false, NULL, 0 ); + return false; + } + + if(cnt == 1) + { + pData = (struct Flash_Sector*)private_malloc(rangeCount * sizeof(struct Flash_Sector)); + + if(pData == NULL) + { + dbg->m_messaging->ReplyToCommand( msg, true, false, NULL, 0 ); + return false; + } + } + + do + { + const BlockDeviceInfo* deviceInfo = device->GetDeviceInfo(); + + for(UINT32 i = 0; i < deviceInfo->NumRegions; i++) + { + const BlockRegionInfo* pRegion = &deviceInfo->Regions[ i ]; + + for(UINT32 j = 0; j < pRegion->NumBlockRanges; j++) + { + + if(cnt == 0) + { + rangeCount++; + } + else + { + pData[ rangeIndex ].Start = pRegion->BlockAddress(pRegion->BlockRanges[ j ].StartBlock); + pData[ rangeIndex ].Length = pRegion->BlockRanges[ j ].GetBlockCount() * pRegion->BytesPerBlock; + pData[ rangeIndex ].Usage = pRegion->BlockRanges[ j ].RangeType & BlockRange::USAGE_MASK; + rangeIndex++; + } + } + } + } + while(NULL != (device = BlockStorageList::GetNextDevice( *device ))); + } + + + dbg->m_messaging->ReplyToCommand( msg, true, false, (void*)pData, rangeCount * sizeof (struct Flash_Sector) ); + + private_free(pData); + } + + return true; + +} + +//--// + +static const int AccessMemory_Check = 0; +static const int AccessMemory_Read = 1; +static const int AccessMemory_Write = 2; +static const int AccessMemory_Erase = 3; + + +bool CLR_DBG_Debugger::CheckPermission( ByteAddress address, int mode ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + bool hasPermission = false; + UINT32 regionIndex, rangeIndex; + + m_deploymentStorageDevice->FindRegionFromAddress( address, regionIndex, rangeIndex ); + const BlockRange& range = m_deploymentStorageDevice->GetDeviceInfo()->Regions[ regionIndex ].BlockRanges[ rangeIndex ]; + + + switch(mode) + { + case AccessMemory_Check: + hasPermission = true; + break; + case AccessMemory_Read: +#if defined(BUILD_RTM) + if(!DebuggerPort_IsUsingSsl(HalSystemConfig.DebuggerPorts[ 0 ])) + break; +#endif + switch(range.RangeType) + { + case BlockRange::BLOCKTYPE_CONFIG: // fall through + case BlockRange::BLOCKTYPE_DIRTYBIT: // fall through + case BlockRange::BLOCKTYPE_DEPLOYMENT: // fall through + case BlockRange::BLOCKTYPE_FILESYSTEM: // fall through + case BlockRange::BLOCKTYPE_STORAGE_A: // fall through + case BlockRange::BLOCKTYPE_STORAGE_B: + case BlockRange::BLOCKTYPE_SIMPLE_A: + case BlockRange::BLOCKTYPE_SIMPLE_B: + case BlockRange::BLOCKTYPE_UPDATE: + + hasPermission = true; + break; + } + break; + case AccessMemory_Write: +#if defined(BUILD_RTM) + if(!DebuggerPort_IsUsingSsl(HalSystemConfig.DebuggerPorts[ 0 ])) + break; +#endif + if(range.IsDeployment() || range.IsConfig()) + { + hasPermission = true; + } + else + { + hasPermission = DebuggerPort_IsUsingSsl(HalSystemConfig.DebuggerPorts[ 0 ]) == TRUE; + } + break; + case AccessMemory_Erase: +#if defined(BUILD_RTM) + if(!DebuggerPort_IsUsingSsl(HalSystemConfig.DebuggerPorts[ 0 ])) + break; +#endif + switch(range.RangeType) + { + case BlockRange::BLOCKTYPE_DEPLOYMENT: + case BlockRange::BLOCKTYPE_FILESYSTEM: + case BlockRange::BLOCKTYPE_STORAGE_A: + case BlockRange::BLOCKTYPE_STORAGE_B: + case BlockRange::BLOCKTYPE_SIMPLE_A: + case BlockRange::BLOCKTYPE_SIMPLE_B: + case BlockRange::BLOCKTYPE_UPDATE: + case BlockRange::BLOCKTYPE_CONFIG: + hasPermission = true; + break; + } + break; + default: + hasPermission = false; + break; + } + + return hasPermission; +} + +bool CLR_DBG_Debugger::AccessMemory( CLR_UINT32 location, UINT32 lengthInBytes, BYTE* buf, int mode ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + TRACE("AccessMemory( 0x%08X, 0x%08x, 0x%08X, %s)\n", location, lengthInBytes, buf, AccessMemoryModeNames[mode] ); + + //--// + UINT32 iRegion, iRange; + + if (m_deploymentStorageDevice->FindRegionFromAddress( location, iRegion, iRange )) + { + const BlockDeviceInfo* deviceInfo = m_deploymentStorageDevice->GetDeviceInfo() ; + + // start from the block where the sector sits. + ByteAddress accessAddress = location; + + BYTE* bufPtr = buf; + BOOL success = TRUE; + INT32 accessLenInBytes = lengthInBytes; + INT32 blockOffset = deviceInfo->Regions[ iRegion ].OffsetFromBlock( accessAddress ); + + for(;iRegion < deviceInfo->NumRegions; iRegion++) + { + const BlockRegionInfo *pRegion = &deviceInfo->Regions[ iRegion ]; + + UINT32 RangeBaseAddress = pRegion->BlockAddress( pRegion->BlockRanges[ iRange ].StartBlock ); + UINT32 blockIndex = pRegion->BlockIndexFromAddress( accessAddress ); + UINT32 accessMaxLength = pRegion->BytesPerBlock - blockOffset; + + blockOffset = 0; + + for(;blockIndex < pRegion->NumBlocks; blockIndex++) + { + //accessMaxLength =the current largest number of bytes can be read from the block from the address to its block boundary. + UINT32 NumOfBytes = __min(accessMaxLength, (UINT32)accessLenInBytes); + + accessMaxLength = pRegion->BytesPerBlock; + + if(blockIndex > pRegion->BlockRanges[ iRange ].EndBlock) + { + iRange++; + + if(iRange >= pRegion->NumBlockRanges) + { + ASSERT(FALSE); + break; + } + } + + // since AccessMemory_Check is always true and will not break from here, no need to check AccessMemory_Check to free memory. + if(!CheckPermission( accessAddress, mode )) + { + TRACE0("=> Permission check failed!\n"); + return false; + } + + switch(mode) + { + case AccessMemory_Check: + case AccessMemory_Read: + if(deviceInfo->Attribute.SupportsXIP) + { + memcpy( (BYTE*)bufPtr, (const void*)accessAddress, NumOfBytes ); + success = TRUE; + } + else + { + if (mode == AccessMemory_Check) + { + bufPtr = (BYTE*) CLR_RT_Memory::Allocate( lengthInBytes, true ); + + if(!bufPtr) + { + TRACE0( "=> Failed to allocate data buffer\n"); + return false; + } + } + + success = m_deploymentStorageDevice->Read( accessAddress , NumOfBytes, (BYTE *)bufPtr ); + + if (mode == AccessMemory_Check) + { + *(UINT32*)buf = SUPPORT_ComputeCRC( bufPtr, NumOfBytes, *(UINT32*)buf ); + + CLR_RT_Memory::Release( bufPtr ); + } + } + break; + + case AccessMemory_Write: + success = m_deploymentStorageDevice->Write( accessAddress , NumOfBytes, (BYTE *)bufPtr, FALSE ); + break; + + case AccessMemory_Erase: + if (!m_deploymentStorageDevice->IsBlockErased( accessAddress, NumOfBytes )) + { + success = m_deploymentStorageDevice->EraseBlock( accessAddress ); + } + break; + + default: + break; + } + + + if(!success) + { + break; + } + + accessLenInBytes -= NumOfBytes; + + if (accessLenInBytes <= 0) + { + break; + } + + bufPtr += NumOfBytes; + accessAddress += NumOfBytes; + } + + blockIndex = 0; + iRange = 0; + + if ((accessLenInBytes <= 0) || (!success)) + break; + } + + } + else + { + //--// RAM write + ByteAddress sectAddr = location; + +#if defined(_WIN32) + + bool proceed = false; + void * temp; + temp = (void *) sectAddr; + + switch(mode) + { + case AccessMemory_Check: + break; + + case AccessMemory_Read: + proceed = IsBadReadPtr( temp, lengthInBytes ) == false; + break; + + case AccessMemory_Write: + proceed = IsBadWritePtr( temp, lengthInBytes ) == false; + break; + } + + if(proceed) +#else + + UINT32 sectAddrEnd = sectAddr + lengthInBytes; + UINT32 ramStartAddress = HalSystemConfig.RAM1.Base; + UINT32 ramEndAddress = ramStartAddress + HalSystemConfig.RAM1.Size ; + + if((sectAddr =ramEndAddress) || (sectAddrEnd >ramEndAddress) ) + { + TRACE(" Invalid address %x and range %x Ram Start %x, Ram end %x\r\n", sectAddr, lengthInBytes, ramStartAddress, ramEndAddress); + return FALSE; + } + else +#endif + { + switch(mode) + { + case AccessMemory_Check: + break; + + case AccessMemory_Read: + memcpy( buf, (const void*)sectAddr, lengthInBytes ); + break; + + case AccessMemory_Write: + BYTE * memPtr; + memPtr = (BYTE*)sectAddr; + memcpy( memPtr, buf, lengthInBytes ); + break; + + case AccessMemory_Erase: + memPtr = (BYTE*)sectAddr; + if (lengthInBytes !=0) + memset( memPtr, 0xFF, lengthInBytes ); + break; + + default: + break; + } + } + } + TRACE0( "=> SUCCESS\n"); + return true; +} + +bool CLR_DBG_Debugger::Monitor_ReadMemory( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + + CLR_DBG_Commands::Monitor_ReadMemory* cmd = (CLR_DBG_Commands::Monitor_ReadMemory*)msg->m_payload; + UINT8 buf[ 1024 ]; + UINT32 len = cmd->m_length; if(len > sizeof(buf)) len = sizeof(buf); + + if (m_deploymentStorageDevice == NULL) return false; + dbg->AccessMemory( cmd->m_address, len, buf, AccessMemory_Read ); + + dbg->m_messaging->ReplyToCommand( msg, true, false, buf, len ); + + return true; + +} + +bool CLR_DBG_Debugger::Monitor_WriteMemory( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + bool fRet; + + CLR_DBG_Debugger * dbg = (CLR_DBG_Debugger*)owner; + + CLR_DBG_Commands::Monitor_WriteMemory* cmd = (CLR_DBG_Commands::Monitor_WriteMemory*)msg->m_payload; + + if (m_deploymentStorageDevice == NULL) return false; + + fRet = dbg->AccessMemory( cmd->m_address, cmd->m_length, cmd->m_data, AccessMemory_Write ); + + dbg->m_messaging->ReplyToCommand( msg, fRet, false ); + + return fRet; +} + +bool CLR_DBG_Debugger::Monitor_CheckMemory( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + + CLR_DBG_Commands::Monitor_CheckMemory* cmd = (CLR_DBG_Commands::Monitor_CheckMemory*)msg->m_payload; + CLR_DBG_Commands::Monitor_CheckMemory::Reply cmdReply; + + dbg->AccessMemory( cmd->m_address, cmd->m_length, (UINT8*)&cmdReply.m_crc, AccessMemory_Check ); + + dbg->m_messaging->ReplyToCommand( msg, true, false, &cmdReply, sizeof(cmdReply) ); + + return true; + +} + +bool CLR_DBG_Debugger::Monitor_EraseMemory( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + bool fRet; + + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + + CLR_DBG_Commands::Monitor_EraseMemory* cmd = (CLR_DBG_Commands::Monitor_EraseMemory*)msg->m_payload; + + if (m_deploymentStorageDevice == NULL) return false; + + fRet = dbg->AccessMemory( cmd->m_address, cmd->m_length, NULL, AccessMemory_Erase ); + + dbg->m_messaging->ReplyToCommand( msg, fRet, false ); + + return fRet; +} + +bool CLR_DBG_Debugger::Monitor_Execute( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + + CLR_DBG_Commands::Monitor_Execute* cmd = (CLR_DBG_Commands::Monitor_Execute*)msg->m_payload; + +#if defined(BUILD_RTM) + if(!DebuggerPort_IsUsingSsl(HalSystemConfig.DebuggerPorts[ 0 ])) + return false; +#endif + + dbg->m_messaging->ReplyToCommand( msg, true, false ); + + ((void (*)())(size_t)cmd->m_address)(); + + return true; +} + +bool CLR_DBG_Debugger::Monitor_Reboot( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Monitor_Reboot* cmd = (CLR_DBG_Commands::Monitor_Reboot*)msg->m_payload; + +#if defined(BUILD_RTM) + if(COM_IsSock(dbg->m_messaging->m_port)) + { + if(!DebuggerPort_IsUsingSsl(HalSystemConfig.DebuggerPorts[ 0 ])) + return false; + } +#endif + + if(NULL != cmd) + { + if(CLR_DBG_Commands::Monitor_Reboot::c_EnterBootloader == (cmd->m_flags & CLR_DBG_Commands::Monitor_Reboot::c_EnterBootloader)) + { + dbg->m_messaging->ReplyToCommand( msg, true, false ); + + Events_WaitForEvents( 0, 100 ); // give message a little time to be flushed + + HAL_EnterBooterMode(); + } + + if(::CPU_IsSoftRebootSupported ()) + { + if((CLR_DBG_Commands::Monitor_Reboot::c_ClrRebootOnly == (cmd->m_flags & CLR_DBG_Commands::Monitor_Reboot::c_ClrRebootOnly))) + { + CLR_EE_REBOOT_SET(ClrOnly); + } + else if((CLR_DBG_Commands::Monitor_Reboot::c_ClrStopDebugger == (cmd->m_flags & CLR_DBG_Commands::Monitor_Reboot::c_ClrStopDebugger))) + { + CLR_EE_REBOOT_SET(ClrOnlyStopDebugger); + } + } + } + + CLR_EE_DBG_SET( RebootPending ); + + dbg->m_messaging->ReplyToCommand( msg, true, false ); + + return true; +} + +bool CLR_DBG_Debugger::Monitor_MemoryMap( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Monitor_MemoryMap::Range map[ 2 ]; + + map[0].m_address = HalSystemConfig.RAM1.Base; + map[0].m_length = HalSystemConfig.RAM1.Size; + map[0].m_flags = CLR_DBG_Commands::Monitor_MemoryMap::c_RAM; + + map[1].m_address = HalSystemConfig.FLASH.Base; + map[1].m_length = HalSystemConfig.FLASH.Size; + map[1].m_flags = CLR_DBG_Commands::Monitor_MemoryMap::c_FLASH; + + dbg->m_messaging->ReplyToCommand( msg, true, false, map, sizeof(map) ); + + return true; +} + + + +bool CLR_DBG_Debugger::Monitor_DeploymentMap( WP_Message* msg, void* owner ) +{ + return true; +} + + + +//--// + +bool CLR_DBG_Debugger::Debugging_Execution_BasePtr( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Execution_BasePtr::Reply cmdReply; + + cmdReply.m_EE = (CLR_UINT32)(size_t)&g_CLR_RT_ExecutionEngine; + + dbg->m_messaging->ReplyToCommand( msg, true, false, &cmdReply, sizeof(cmdReply) ); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Execution_ChangeConditions( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Execution_ChangeConditions* cmd = (CLR_DBG_Commands::Debugging_Execution_ChangeConditions*)msg->m_payload; + + g_CLR_RT_ExecutionEngine.m_iDebugger_Conditions |= cmd->m_set; + g_CLR_RT_ExecutionEngine.m_iDebugger_Conditions &= ~cmd->m_reset; + + if((msg->m_header.m_flags & WP_Flags::c_NonCritical) == 0) + { + CLR_DBG_Commands::Debugging_Execution_ChangeConditions::Reply cmdReply; + + cmdReply.m_current = g_CLR_RT_ExecutionEngine.m_iDebugger_Conditions; + + dbg->m_messaging->ReplyToCommand( msg, true, false, &cmdReply, sizeof(cmdReply) ); + } + + // UNDONE: FIXME: CLR_RT_EmulatorHooks::Notify_ExecutionStateChanged(); + + return true; +} + +//--// + +static void GetClrReleaseInfo(CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::ClrInfo& clrInfo) +{ +#if defined(PLATFORM_SH) +#undef OEMSTR(str) +#define OEMSTR(str) # str +MfReleaseInfo::Init( clrInfo.m_clrReleaseInfo, VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, VERSION_REVISION, OEMSTR(OEMSYSTEMINFOSTRING), hal_strlen_s(OEMSTR(OEMSYSTEMINFOSTRING)) ); +#undef OEMSTR(str) +#else + MfReleaseInfo::Init( clrInfo.m_clrReleaseInfo, VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, VERSION_REVISION, OEMSYSTEMINFOSTRING, hal_strlen_s(OEMSYSTEMINFOSTRING) ); +#endif + + if ( g_CLR_RT_TypeSystem.m_assemblyMscorlib && + g_CLR_RT_TypeSystem.m_assemblyMscorlib->m_header) + { + const CLR_RECORD_VERSION* mscorlibVer = & (g_CLR_RT_TypeSystem.m_assemblyMscorlib->m_header->version); + MFVersion::Init( clrInfo.m_TargetFrameworkVersion, + mscorlibVer->iMajorVersion, mscorlibVer->iMinorVersion, + mscorlibVer->iBuildNumber, mscorlibVer->iRevisionNumber + ); + } + else + { + MFVersion::Init( clrInfo.m_TargetFrameworkVersion, 0, 0, 0, 0 ); + } +} + + +void MfReleaseInfo::Init(MfReleaseInfo& mfReleaseInfo, UINT16 major, UINT16 minor, UINT16 build, UINT16 revision, const char *info, size_t infoLen) +{ + MFVersion::Init( mfReleaseInfo.version, major, minor, build, revision ); + mfReleaseInfo.infoString[ 0 ] = 0; + if ( NULL != info && infoLen > 0 ) + { + const size_t len = MIN(infoLen, sizeof(mfReleaseInfo.infoString)-1); + hal_strncpy_s( (char*)&mfReleaseInfo.infoString[ 0 ], sizeof(mfReleaseInfo.infoString), info, len ); + } +} + +//--// + +bool CLR_DBG_Debugger::Debugging_Execution_QueryCLRCapabilities( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities* cmd = (CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities*)msg->m_payload; + + CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::ReplyUnion reply; + reply.u_capsFlags = 0; + + CLR_UINT8* data = NULL; + int size = 0; + bool fSuccess = true; + + memset(&reply, 0, sizeof(reply)); + + switch(cmd->m_cmd) + { + case CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityFlags: + +#if !defined(TINYCLR_EMULATED_FLOATINGPOINT) + reply.u_capsFlags |= CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityFlags_FloatingPoint; +#endif + + reply.u_capsFlags |= CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityFlags_ExceptionFilters; + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + reply.u_capsFlags |= CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityFlags_SourceLevelDebugging; + reply.u_capsFlags |= CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityFlags_IncrementalDeployment; + reply.u_capsFlags |= CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityFlags_ThreadCreateEx; +#endif + +#if defined(TINYCLR_PROFILE_NEW) + reply.u_capsFlags |= CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityFlags_Profiling; +#if defined(TINYCLR_PROFILE_NEW_CALLS) + reply.u_capsFlags |= CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityFlags_Profiling_Calls; +#endif +#if defined(TINYCLR_PROFILE_NEW_ALLOCATIONS) + reply.u_capsFlags |= CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityFlags_Profiling_Allocations; +#endif +#endif + +#if defined(TINYCLR_APPDOMAINS) + reply.u_capsFlags |= CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityFlags_AppDomains; +#endif + + if (::CPU_IsSoftRebootSupported ()) + { + reply.u_capsFlags |= CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityFlags_SoftReboot; + } + + data = (CLR_UINT8*)&reply.u_capsFlags; + size = sizeof(reply.u_capsFlags); + break; + + // UNDONE: FIXME: case CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityLCD: + //reply.u_LCD.m_width = LCD_SCREEN_WIDTH; + //reply.u_LCD.m_height = LCD_SCREEN_HEIGHT; + //reply.u_LCD.m_bpp = LCD_SCREEN_BPP; + + //data = (CLR_UINT8*)&reply.u_LCD; + //size = sizeof(reply.u_LCD); + //break; + + case CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityVersion: +#if defined(__GNUC__) + reply.u_SoftwareVersion.m_compilerVersion = __GNUC__; +#elif defined(__ARMCC_VERSION) + reply.u_SoftwareVersion.m_compilerVersion = __ARMCC_VERSION; +#elif defined(_ARCVER) + reply.u_SoftwareVersion.m_compilerVersion = _ARCVER; +#elif defined(__RENESAS__) + reply.u_SoftwareVersion.m_compilerVersion = __RENESAS_VERSION__; +#else + reply.u_SoftwareVersion.m_compilerVersion = -1; +#endif + +#if defined(__DATE__) + hal_strncpy_s( reply.u_SoftwareVersion.m_buildDate, sizeof(reply.u_SoftwareVersion.m_buildDate), __DATE__, hal_strlen_s(__DATE__) ); +#else + hal_strncpy_s( reply.u_SoftwareVersion.m_buildDate, sizeof(reply.u_SoftwareVersion.m_buildDate), "UNKNOWN", hal_strlen_s("UNKNOWN") ); +#endif + data = (CLR_UINT8*)&reply.u_SoftwareVersion; + size = sizeof(reply.u_SoftwareVersion); + break; + + case CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_HalSystemInfo: + if(GetHalSystemInfo( reply.u_HalSystemInfo ) == TRUE) + { + data = (CLR_UINT8*)&reply.u_HalSystemInfo; + size = sizeof(reply.u_HalSystemInfo); + } + else + { + fSuccess = false; + } + break; + + case CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_ClrInfo: + GetClrReleaseInfo(reply.u_ClrInfo); + data = (CLR_UINT8*)&reply.u_ClrInfo; + size = sizeof(reply.u_ClrInfo); + break; + + case CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_SolutionReleaseInfo: + if(Solution_GetReleaseInfo(reply.u_SolutionReleaseInfo) == TRUE) + { + data = (CLR_UINT8*)&reply.u_SolutionReleaseInfo; + size = sizeof(reply.u_SolutionReleaseInfo); + } + else + { + fSuccess = false; + } + break; + + default: + fSuccess = false; + break; + } + + dbg->m_messaging->ReplyToCommand( msg, fSuccess, false, data, size ); + + return true; +} + + +bool CLR_DBG_Debugger::Debugging_Execution_Allocate( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Execution_Allocate* cmd = (CLR_DBG_Commands::Debugging_Execution_Allocate*)msg->m_payload; + CLR_DBG_Commands::Debugging_Execution_Allocate::Reply reply; + + reply.m_address = (CLR_UINT32)(size_t)CLR_RT_Memory::Allocate( cmd->m_size, CLR_RT_HeapBlock::HB_CompactOnFailure ); + + if(!reply.m_address) return false; + + dbg->m_messaging->ReplyToCommand( msg, true, false, &reply, sizeof(reply) ); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_UpgradeToSsl(WP_Message* msg, void* owner ) +{ + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_UpgradeToSsl* cmd = (CLR_DBG_Commands::Debugging_UpgradeToSsl*)msg->m_payload; + CLR_DBG_Commands::Debugging_UpgradeToSsl::Reply reply; + + if(!DebuggerPort_IsSslSupported(HalSystemConfig.DebuggerPorts[0])) + { + return false; + } + + reply.m_success = 1; + + dbg->m_messaging->ReplyToCommand( msg, true, true, &reply, sizeof(reply) ); + + Events_WaitForEvents(0, 300); + + return TRUE == DebuggerPort_UpgradeToSsl(HalSystemConfig.DebuggerPorts[0], cmd->m_flags); +} + +static CLR_UINT32 s_missingPkts[64]; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + +static bool FillValues( CLR_RT_HeapBlock* ptr, CLR_DBG_Commands::Debugging_Value*& array, size_t num, CLR_RT_HeapBlock* reference, CLR_RT_TypeDef_Instance* pTD ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + if(!ptr) return true; + + if(!array || num == 0) return false; + + CLR_DBG_Commands::Debugging_Value* dst = array++; num--; + CLR_RT_TypeDescriptor desc; + + memset( dst, 0, sizeof(*dst) ); + + dst->m_referenceID = (reference != NULL) ? reference : ptr; + dst->m_dt = ptr->DataType (); + dst->m_flags = ptr->DataFlags(); + dst->m_size = ptr->DataSize (); + + if(pTD != NULL) + { + dst->m_td = *pTD; + } + else if(SUCCEEDED(desc.InitializeFromObject( *ptr ))) + { + dst->m_td = desc.m_handlerCls; + } + + switch(dst->m_dt) + { + case DATATYPE_BOOLEAN : + case DATATYPE_I1 : + case DATATYPE_U1 : + + case DATATYPE_CHAR : + case DATATYPE_I2 : + case DATATYPE_U2 : + + case DATATYPE_I4 : + case DATATYPE_U4 : + case DATATYPE_R4 : + + case DATATYPE_I8 : + case DATATYPE_U8 : + case DATATYPE_R8 : + case DATATYPE_DATETIME : + case DATATYPE_TIMESPAN : + case DATATYPE_REFLECTION: + // + // Primitives or optimized value types. + // + memcpy( dst->m_builtinValue, (void*)&ptr->NumericByRefConst().u1, 8 ); + break; + + case DATATYPE_STRING: + { + LPCSTR text = ptr->StringText(); + + if(text != NULL) + { + dst->m_charsInString = text; + dst->m_bytesInString = (CLR_UINT32)hal_strlen_s( text ); + + hal_strncpy_s( (char*)dst->m_builtinValue, ARRAYSIZE(dst->m_builtinValue), text, __min(dst->m_bytesInString, MAXSTRLEN(dst->m_builtinValue)) ); + } + else + { + dst->m_charsInString = NULL; + dst->m_bytesInString = 0; + dst->m_builtinValue[0] = 0; + } + } + break; + + + case DATATYPE_OBJECT: + case DATATYPE_BYREF : + return FillValues( ptr->Dereference(), array, num, NULL, pTD ); + + + case DATATYPE_CLASS : + case DATATYPE_VALUETYPE: + dst->m_td = ptr->ObjectCls(); + break; + + case DATATYPE_SZARRAY: + { + CLR_RT_HeapBlock_Array* ptr2 = (CLR_RT_HeapBlock_Array*)ptr; + + dst->m_array_numOfElements = ptr2->m_numOfElements; + dst->m_array_depth = ptr2->ReflectionDataConst().m_levels; + dst->m_array_typeIndex = ptr2->ReflectionDataConst().m_data.m_type; + } + break; + + //////////////////////////////////////// + + case DATATYPE_WEAKCLASS : + break; + + case DATATYPE_ARRAY_BYREF : + dst->m_arrayref_referenceID = ptr->Array (); + dst->m_arrayref_index = ptr->ArrayIndex(); + + break; + + case DATATYPE_DELEGATE_HEAD : + break; + + case DATATYPE_DELEGATELIST_HEAD : + break; + + case DATATYPE_FREEBLOCK : + case DATATYPE_CACHEDBLOCK : + case DATATYPE_ASSEMBLY : + case DATATYPE_OBJECT_TO_EVENT : + case DATATYPE_BINARY_BLOB_HEAD : + + case DATATYPE_THREAD : + case DATATYPE_SUBTHREAD : + case DATATYPE_STACK_FRAME : + case DATATYPE_TIMER_HEAD : + case DATATYPE_LOCK_HEAD : + case DATATYPE_LOCK_OWNER_HEAD : + case DATATYPE_LOCK_REQUEST_HEAD : + case DATATYPE_WAIT_FOR_OBJECT_HEAD : + case DATATYPE_FINALIZER_HEAD : + case DATATYPE_MEMORY_STREAM_HEAD : + case DATATYPE_MEMORY_STREAM_DATA : + + case DATATYPE_SERIALIZER_HEAD : + case DATATYPE_SERIALIZER_DUPLICATE : + case DATATYPE_SERIALIZER_STATE : + + case DATATYPE_ENDPOINT_HEAD : + +#if defined(TINYCLR_APPDOMAINS) + case DATATYPE_APPDOMAIN_HEAD : + case DATATYPE_TRANSPARENT_PROXY : + case DATATYPE_APPDOMAIN_ASSEMBLY : +#endif + + break; + } + + return true; +} + +bool CLR_DBG_Debugger::GetValue( WP_Message* msg, CLR_RT_HeapBlock* ptr, CLR_RT_HeapBlock* reference, CLR_RT_TypeDef_Instance *pTD ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Commands::Debugging_Value reply[ 4 ]; + CLR_DBG_Commands::Debugging_Value* array = reply; + + if(FillValues( ptr, array, ARRAYSIZE(reply), reference, pTD )) + { + m_messaging->ReplyToCommand( msg, true, false, reply, (int)((size_t)array - (size_t)reply) ); + + return true; + } + + m_messaging->ReplyToCommand( msg, false, false ); + + return false; +} + +//--// + +bool CLR_DBG_Debugger::Debugging_Execution_SetCurrentAppDomain( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); +#if defined(TINYCLR_APPDOMAINS) + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Execution_SetCurrentAppDomain* cmd = (CLR_DBG_Commands::Debugging_Execution_SetCurrentAppDomain*)msg->m_payload; + CLR_RT_AppDomain* appDomain = dbg->GetAppDomainFromID( cmd->m_id ); + + if(appDomain) + { + g_CLR_RT_ExecutionEngine.SetCurrentAppDomain( appDomain ); + } + + dbg->m_messaging->ReplyToCommand( msg, appDomain != NULL, false ); + + return true; +#else + return false; +#endif +} + +bool CLR_DBG_Debugger::Debugging_Execution_Breakpoints( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Execution_Breakpoints* cmd = (CLR_DBG_Commands::Debugging_Execution_Breakpoints*)msg->m_payload; + + g_CLR_RT_ExecutionEngine.InstallBreakpoints( cmd->m_data, (msg->m_header.m_size - sizeof(cmd->m_flags)) / sizeof(CLR_DBG_Commands::Debugging_Execution_BreakpointDef) ); + + dbg->m_messaging->ReplyToCommand( msg, true, false ); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Execution_BreakpointStatus( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Execution_BreakpointStatus::Reply reply; + + if(g_CLR_RT_ExecutionEngine.DequeueActiveBreakpoint( reply.m_lastHit ) == false) + { + memset( &reply.m_lastHit, 0, sizeof(reply.m_lastHit) ); + } + + dbg->m_messaging->ReplyToCommand( msg, true, false, &reply, sizeof(reply) ); + + return true; +} + +//--// + +CLR_RT_Assembly* CLR_DBG_Debugger::IsGoodAssembly( CLR_IDX idxAssm ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + TINYCLR_FOREACH_ASSEMBLY(g_CLR_RT_TypeSystem) + { + if(pASSM->m_idx == idxAssm) return pASSM; + } + TINYCLR_FOREACH_ASSEMBLY_END(); + + return NULL; +} + +bool CLR_DBG_Debugger::CheckTypeDef( const CLR_RT_TypeDef_Index& td, CLR_RT_TypeDef_Instance& inst ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_RT_Assembly* assm = IsGoodAssembly( td.Assembly() ); + + if(assm && td.Type() < assm->m_pTablesSize[ TBL_TypeDef ]) + { + return inst.InitializeFromIndex( td ); + } + + return false; +} + +bool CLR_DBG_Debugger::CheckFieldDef( const CLR_RT_FieldDef_Index& fd, CLR_RT_FieldDef_Instance& inst ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_RT_Assembly* assm = IsGoodAssembly( fd.Assembly() ); + + if(assm && fd.Field() < assm->m_pTablesSize[ TBL_FieldDef ]) + { + return inst.InitializeFromIndex( fd ); + } + + return false; +} + +bool CLR_DBG_Debugger::CheckMethodDef( const CLR_RT_MethodDef_Index& md, CLR_RT_MethodDef_Instance& inst ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_RT_Assembly* assm = IsGoodAssembly( md.Assembly() ); + + if(assm && md.Method() < assm->m_pTablesSize[ TBL_MethodDef ]) + { + return inst.InitializeFromIndex( md ); + } + + return false; +} + +CLR_RT_StackFrame* CLR_DBG_Debugger::CheckStackFrame( CLR_UINT32 pid, CLR_UINT32 depth, bool& isInline ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_RT_Thread* th = GetThreadFromPid( pid ); + + isInline = false; + + if(th) + { + TINYCLR_FOREACH_NODE(CLR_RT_StackFrame,call,th->m_stackFrames) + { +#ifndef TINYCLR_NO_IL_INLINE + if(call->m_inlineFrame) + { + if(depth-- == 0) + { + isInline = true; + return call; + } + } +#endif + + if(depth-- == 0) return call; + } + TINYCLR_FOREACH_NODE_END(); + } + + return NULL; +} + +//--// + +static HRESULT Debugging_Thread_Create_Helper( CLR_RT_MethodDef_Index& md, CLR_RT_Thread*& th, CLR_UINT32 pid ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + TINYCLR_HEADER(); + + CLR_RT_HeapBlock ref; ref.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( ref ); + CLR_RT_Thread* realThread = (pid != 0) ? CLR_DBG_Debugger::GetThreadFromPid( pid ) : NULL; + + th = NULL; + + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Delegate::CreateInstance( ref, md, NULL )); + + TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewThread( th, ref.DereferenceDelegate(), ThreadPriority::Highest, -1 )); + + + if (realThread) + { + th->m_realThread = realThread; + } + + { + CLR_RT_StackFrame* stack = th->CurrentFrame(); + const CLR_RECORD_METHODDEF* target = stack->m_call.m_target; + CLR_UINT8 numArgs = target->numArgs; + + if(numArgs) + { + CLR_RT_SignatureParser parser; parser.Initialize_MethodSignature( stack->m_call.m_assm, target ); + CLR_RT_SignatureParser::Element res; + CLR_RT_HeapBlock* args = stack->m_arguments; + + if(parser.m_flags & PIMAGE_CEE_CS_CALLCONV_HASTHIS) + { + args->SetObjectReference( NULL ); + + numArgs--; + args++; + } + + // + // Skip return value. + // + TINYCLR_CHECK_HRESULT(parser.Advance( res )); + + // + // None of the arguments can be ByRef. + // + { + CLR_RT_SignatureParser parser2 = parser; + + for(;parser2.Available() > 0;) + { + TINYCLR_CHECK_HRESULT(parser2.Advance( res )); + + if(res.m_fByRef) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + } + } + + for(CLR_UINT8 i=0; iTerminate(); + th = NULL; + } + } + + TINYCLR_CLEANUP_END(); +} + +bool CLR_DBG_Debugger::Debugging_Thread_CreateEx( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Thread_CreateEx* cmd = (CLR_DBG_Commands::Debugging_Thread_CreateEx*)msg->m_payload; + CLR_DBG_Commands::Debugging_Thread_CreateEx::Reply cmdReply; + CLR_RT_Thread* th; + + if(SUCCEEDED(Debugging_Thread_Create_Helper( cmd->m_md, th, cmd->m_pid ))) + { + th->m_scratchPad = cmd->m_scratchPad; + + cmdReply.m_pid = th->m_pid; + } + else + { + cmdReply.m_pid = (CLR_UINT32)-1; + } + + dbg->m_messaging->ReplyToCommand( msg, true, false, &cmdReply, sizeof(cmdReply) ); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Thread_List( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Thread_List::Reply* cmdReply = NULL; + int len = 0; + + if(FAILED(dbg->CreateListOfThreads( cmdReply, len ))) + { + dbg->m_messaging->ReplyToCommand( msg, false, false ); + } + else + { + dbg->m_messaging->ReplyToCommand( msg, true, false, cmdReply, len ); + } + + CLR_RT_Memory::Release( cmdReply ); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Thread_Stack( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Thread_Stack* cmd = (CLR_DBG_Commands::Debugging_Thread_Stack*)msg->m_payload; + CLR_DBG_Commands::Debugging_Thread_Stack::Reply* cmdReply = NULL; + int len = 0; + + if(FAILED(dbg->CreateListOfCalls( cmd->m_pid, cmdReply, len ))) + { + dbg->m_messaging->ReplyToCommand( msg, false, false ); + } + else + { + dbg->m_messaging->ReplyToCommand( msg, true, false, cmdReply, len ); + } + + CLR_RT_Memory::Release( cmdReply ); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Thread_Kill( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Thread_Kill* cmd = (CLR_DBG_Commands::Debugging_Thread_Kill*)msg->m_payload; + CLR_DBG_Commands::Debugging_Thread_Kill::Reply cmdReply; + CLR_RT_Thread* th = dbg->GetThreadFromPid( cmd->m_pid ); + + if(th) + { + th->Terminate(); + + cmdReply.m_result = 1; + } + else + { + cmdReply.m_result = 0; + } + + dbg->m_messaging->ReplyToCommand( msg, true, false, &cmdReply, sizeof(cmdReply) ); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Thread_Suspend( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Thread_Suspend* cmd = (CLR_DBG_Commands::Debugging_Thread_Suspend*)msg->m_payload; + CLR_RT_Thread* th = dbg->GetThreadFromPid( cmd->m_pid ); + + if(th) + { + th->Suspend(); + } + + dbg->m_messaging->ReplyToCommand( msg, th != NULL, false ); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Thread_Resume( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Thread_Resume* cmd = (CLR_DBG_Commands::Debugging_Thread_Resume*)msg->m_payload; + CLR_RT_Thread* th = dbg->GetThreadFromPid( cmd->m_pid ); + + if(th) + { + th->Resume(); + } + + dbg->m_messaging->ReplyToCommand( msg, th != NULL, false ); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Thread_Get( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Thread_Get* cmd = (CLR_DBG_Commands::Debugging_Thread_Get*)msg->m_payload; + CLR_RT_Thread* th = dbg->GetThreadFromPid( cmd->m_pid ); + CLR_RT_HeapBlock* pThread; + bool fFound = false; + + if(th == NULL) return false; + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + //If we are a thread spawned by the debugger to perform evaluations, + //return the thread object that correspond to thread that has focus in debugger. + th = th->m_realThread; +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + //Find an existing managed thread, if it exists + //making sure to only return the managed object association with the current appdomain + //to prevent leaking of managed Thread objects across AD boundaries. + + TINYCLR_FOREACH_NODE(CLR_RT_ObjectToEvent_Source,src,th->m_references) + { + CLR_RT_HeapBlock* pManagedThread = src->m_objectPtr; + _ASSERTE(pManagedThread != NULL); + +#if defined(TINYCLR_APPDOMAINS) + { + CLR_RT_ObjectToEvent_Source* appDomainSrc = CLR_RT_ObjectToEvent_Source::ExtractInstance( pManagedThread[ Library_corlib_native_System_Threading_Thread::FIELD__m_AppDomain ] ); + + if(appDomainSrc == NULL) break; + + fFound = (appDomainSrc->m_eventPtr == g_CLR_RT_ExecutionEngine.GetCurrentAppDomain()); + } +#else + fFound = true; +#endif + + if(fFound) + { + pThread = pManagedThread; + + break; + } + } + TINYCLR_FOREACH_NODE_END(); + + if(!fFound) + { + pThread = (CLR_RT_HeapBlock*)private_malloc(sizeof(CLR_RT_HeapBlock)); + + //Create the managed thread. + //This implies that there is no state in the managed object. This is not exactly true, as the managed thread + //contains the priority as well as the delegate to start. However, that state is really just used as a placeholder for + //the data before the thread is started. Once the thread is started, they are copied over to the unmanaged thread object + //and no longer used. The managed object is then used simply as a wrapper for the unmanaged thread. Therefore, it is safe + //to simply make another managed thread here. + if(SUCCEEDED(g_CLR_RT_ExecutionEngine.NewObjectFromIndex( *pThread, g_CLR_RT_WellKnownTypes.m_Thread ))) + { + CLR_RT_HeapBlock* pRes = pThread->Dereference(); + + int pri = th->GetThreadPriority(); + + pRes[Library_corlib_native_System_Threading_Thread::FIELD__m_Priority].NumericByRef().s4 = pri; + + if(SUCCEEDED(CLR_RT_ObjectToEvent_Source::CreateInstance( th, *pRes, pRes[ Library_corlib_native_System_Threading_Thread::FIELD__m_Thread ] ))) + { +#if defined(TINYCLR_APPDOMAINS) + CLR_RT_ObjectToEvent_Source::CreateInstance( g_CLR_RT_ExecutionEngine.GetCurrentAppDomain(), *pRes, pRes[ Library_corlib_native_System_Threading_Thread::FIELD__m_AppDomain ] ); +#endif + fFound = true; + } + + } + } + + if(!fFound) return false; + + return dbg->GetValue( msg, pThread, NULL, NULL ); +} + +bool CLR_DBG_Debugger::Debugging_Thread_GetException( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Thread_GetException* cmd = (CLR_DBG_Commands::Debugging_Thread_GetException*)msg->m_payload; + CLR_RT_Thread* th = dbg->GetThreadFromPid( cmd->m_pid ); + CLR_RT_HeapBlock* blk = NULL; + + if(th) + { + blk = &th->m_currentException; + } + + return dbg->GetValue( msg, blk, NULL, NULL ); +} + +bool CLR_DBG_Debugger::Debugging_Thread_Unwind( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Thread_Unwind* cmd = (CLR_DBG_Commands::Debugging_Thread_Unwind*)msg->m_payload; + CLR_RT_StackFrame* call; + CLR_RT_Thread* th; + bool isInline = false; + + if((call = dbg->CheckStackFrame( cmd->m_pid, cmd->m_depth, isInline )) != NULL) + { + _ASSERTE((call->m_flags & CLR_RT_StackFrame::c_MethodKind_Native) == 0); + + th = call->m_owningThread; + _ASSERTE(th->m_nestedExceptionsPos); + + CLR_RT_Thread::UnwindStack& us = th->m_nestedExceptions[ th->m_nestedExceptionsPos - 1 ]; + _ASSERTE(th->m_currentException.Dereference() == us.m_exception); + _ASSERTE(us.m_flags & CLR_RT_Thread::UnwindStack::c_ContinueExceptionHandler); + + us.m_handlerStack = call; + us.m_flags |= CLR_RT_Thread::UnwindStack::c_MagicCatchForInteceptedException; + + us.SetPhase(CLR_RT_Thread::UnwindStack::p_2_RunningFinallys_0); + } + + return true; +} + +//--// + +bool CLR_DBG_Debugger::Debugging_Stack_Info( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Stack_Info* cmd = (CLR_DBG_Commands::Debugging_Stack_Info*)msg->m_payload; + CLR_DBG_Commands::Debugging_Stack_Info::Reply cmdReply; + CLR_RT_StackFrame* call; + bool isInline = false; + + if((call = dbg->CheckStackFrame( cmd->m_pid, cmd->m_depth, isInline )) != NULL) + { +#ifndef TINYCLR_NO_IL_INLINE + if(isInline) + { + cmdReply.m_md = call->m_inlineFrame->m_frame.m_call; + cmdReply.m_IP = (CLR_UINT32)(call->m_inlineFrame->m_frame.m_IP - call->m_inlineFrame->m_frame.m_IPStart); + cmdReply.m_numOfArguments = call->m_inlineFrame->m_frame.m_call.m_target->numArgs; + cmdReply.m_numOfLocals = call->m_inlineFrame->m_frame.m_call.m_target->numLocals; + cmdReply.m_depthOfEvalStack = (CLR_UINT32)(call->m_evalStack - call->m_inlineFrame->m_frame.m_evalStack); + } + else +#endif + { + cmdReply.m_md = call->m_call; + cmdReply.m_IP = (CLR_UINT32)(call->m_IP - call->m_IPstart); + cmdReply.m_numOfArguments = call->m_call.m_target->numArgs; + cmdReply.m_numOfLocals = call->m_call.m_target->numLocals; + cmdReply.m_depthOfEvalStack = (CLR_UINT32) call->TopValuePosition(); + } + + dbg->m_messaging->ReplyToCommand( msg, true, false, &cmdReply, sizeof(cmdReply) ); + + return true; + } + + dbg->m_messaging->ReplyToCommand( msg, false, false ); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Stack_SetIP( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Stack_SetIP* cmd = (CLR_DBG_Commands::Debugging_Stack_SetIP*)msg->m_payload; + CLR_RT_StackFrame* call; + bool isInline = false; + + if((call = dbg->CheckStackFrame( cmd->m_pid, cmd->m_depth, isInline )) != NULL) + { +#ifndef TINYCLR_NO_IL_INLINE + if(isInline) + { + dbg->m_messaging->ReplyToCommand( msg, false, false ); + + return true; + } + else +#endif + { + call->m_IP = call->m_IPstart + cmd->m_IP; + call->m_evalStackPos = call->m_evalStack + cmd->m_depthOfEvalStack; + } + + call->m_flags &= ~CLR_RT_StackFrame::c_InvalidIP; + + dbg->m_messaging->ReplyToCommand( msg, true, false ); + + return true; + } + + dbg->m_messaging->ReplyToCommand( msg, false, false ); + + return true; +} + +//--// + +static bool IsBlockEnumMaybe( CLR_RT_HeapBlock* blk ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + const CLR_UINT32 c_MaskForPrimitive = CLR_RT_DataTypeLookup::c_Integer | CLR_RT_DataTypeLookup::c_Numeric; + + CLR_RT_TypeDescriptor desc; + + if(FAILED(desc.InitializeFromObject( *blk ))) return false; + + const CLR_RT_DataTypeLookup& dtl = c_CLR_RT_DataTypeLookup[ desc.m_handlerCls.m_target->dataType ]; + + return (dtl.m_flags & c_MaskForPrimitive) == c_MaskForPrimitive; +} + +static bool SetBlockHelper( CLR_RT_HeapBlock* blk, CLR_DataType dt, CLR_UINT8* builtinValue ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + bool fCanAssign = false; + + if(blk) + { + CLR_DataType dtDst; + CLR_RT_HeapBlock src; + + dtDst = blk->DataType(); + + src.SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(dt, 0, 1) ); + memcpy( (void*)&src.NumericByRef().u1, builtinValue, sizeof(CLR_UINT64) ); + + if(dtDst == dt) + { + fCanAssign = true; + } + else + { + if(dt == DATATYPE_REFLECTION) + { + fCanAssign = (dtDst == DATATYPE_OBJECT && blk->Dereference() == NULL); + } + else if(dt == DATATYPE_OBJECT) + { + fCanAssign = (src .Dereference() == NULL && dtDst == DATATYPE_REFLECTION); + } + else + { + _ASSERTE(c_CLR_RT_DataTypeLookup[ dtDst ].m_flags & CLR_RT_DataTypeLookup::c_Numeric); + + if(c_CLR_RT_DataTypeLookup[ dtDst ].m_sizeInBytes == sizeof(CLR_INT32) && + c_CLR_RT_DataTypeLookup[ dt ].m_sizeInBytes < sizeof(CLR_INT32)) + { + dt = dtDst; + fCanAssign = true; + } + } + } + + if(fCanAssign) + { + blk->ChangeDataType( dt ); + memcpy( (void*)&blk->NumericByRef().u1, builtinValue, sizeof(CLR_UINT64) ); + } + } + + return fCanAssign; +} + +static CLR_RT_HeapBlock* GetScratchPad_Helper( int idx ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_RT_HeapBlock_Array* array = g_CLR_RT_ExecutionEngine.m_scratchPadArray; + CLR_RT_HeapBlock tmp; + CLR_RT_HeapBlock ref; + + tmp.SetObjectReference( array ); + + if(SUCCEEDED(ref.InitializeArrayReference( tmp, idx ))) + { + return (CLR_RT_HeapBlock*)array->GetElement( idx ); + } + + return NULL; +} + +//--// + +bool CLR_DBG_Debugger::Debugging_Value_ResizeScratchPad( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Value_ResizeScratchPad* cmd = (CLR_DBG_Commands::Debugging_Value_ResizeScratchPad*)msg->m_payload; + CLR_RT_HeapBlock ref; + bool fRes = true; + + if(cmd->m_size == 0) + { + g_CLR_RT_ExecutionEngine.m_scratchPadArray = NULL; + } + else + { + if(SUCCEEDED(CLR_RT_HeapBlock_Array::CreateInstance( ref, cmd->m_size, g_CLR_RT_WellKnownTypes.m_Object ))) + { + CLR_RT_HeapBlock_Array* pOld = g_CLR_RT_ExecutionEngine.m_scratchPadArray; + CLR_RT_HeapBlock_Array* pNew = ref.DereferenceArray(); + + if(pOld) + { + memcpy( pNew->GetFirstElement(), pOld->GetFirstElement(), sizeof(CLR_RT_HeapBlock) * __min( pNew->m_numOfElements, pOld->m_numOfElements ) ); + } + + g_CLR_RT_ExecutionEngine.m_scratchPadArray = pNew; + } + else + { + fRes = false; + } + } + + dbg->m_messaging->ReplyToCommand( msg, fRes, false ); + + return false; +} + +bool CLR_DBG_Debugger::Debugging_Value_GetStack( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Value_GetStack* cmd = (CLR_DBG_Commands::Debugging_Value_GetStack*)msg->m_payload; + CLR_RT_StackFrame* call; + bool isInline = false; + + if((call = dbg->CheckStackFrame( cmd->m_pid, cmd->m_depth, isInline )) != NULL) + { + CLR_RT_HeapBlock* array; + CLR_UINT32 num; +#ifndef TINYCLR_NO_IL_INLINE + CLR_RT_MethodDef_Instance& md = isInline ? call->m_inlineFrame->m_frame.m_call : call->m_call; +#else + CLR_RT_MethodDef_Instance& md = call->m_call; +#endif + + switch(cmd->m_kind) + { + case CLR_DBG_Commands::Debugging_Value_GetStack::c_Argument: +#ifndef TINYCLR_NO_IL_INLINE + array = isInline ? call->m_inlineFrame->m_frame.m_args : call->m_arguments; + num = isInline ? md.m_target->numArgs : md.m_target->numArgs; +#else + array = call->m_arguments; + num = call->m_call.m_target->numArgs; +#endif + break; + + case CLR_DBG_Commands::Debugging_Value_GetStack::c_Local: +#ifndef TINYCLR_NO_IL_INLINE + array = isInline ? call->m_inlineFrame->m_frame.m_locals : call->m_locals; + num = isInline ? md.m_target->numLocals : md.m_target->numLocals; +#else + array = call->m_locals; + num = call->m_call.m_target->numLocals; +#endif + break; + + case CLR_DBG_Commands::Debugging_Value_GetStack::c_EvalStack: +#ifndef TINYCLR_NO_IL_INLINE + array = isInline ? call->m_inlineFrame->m_frame.m_evalStack : call->m_evalStack; + num = isInline ? (CLR_UINT32)(call->m_evalStack - call->m_inlineFrame->m_frame.m_evalStack) : (CLR_UINT32)call->TopValuePosition(); +#else + array = call->m_evalStack; + num = (CLR_UINT32)call->TopValuePosition(); +#endif + break; + + default: + return false; + } + + if(cmd->m_index >= num) return false; + + CLR_RT_HeapBlock* blk = &array[ cmd->m_index ]; + CLR_RT_HeapBlock* reference = NULL; + CLR_RT_HeapBlock tmp; + CLR_RT_TypeDef_Instance* pTD = NULL; + CLR_RT_TypeDef_Instance td; + + if(cmd->m_kind != CLR_DBG_Commands::Debugging_Value_GetStack::c_EvalStack && IsBlockEnumMaybe( blk )) + { + CLR_UINT32 iElement = cmd->m_index; + CLR_RT_SignatureParser parser; + CLR_RT_SignatureParser::Element res; + CLR_RT_TypeDescriptor desc; + + if(cmd->m_kind == CLR_DBG_Commands::Debugging_Value_GetStack::c_Argument) + { + parser.Initialize_MethodSignature( md.m_assm, md.m_target ); + + iElement++; // Skip the return value, always at the head of the signature. + + if(parser.m_flags & PIMAGE_CEE_CS_CALLCONV_HASTHIS) + { + if(iElement == 0) return false; // The requested argument is the "this" argument, it can never be a primitive. + + iElement--; + } + } + else + { + parser.Initialize_MethodLocals( md.m_assm, md.m_target ); + } + + do + { + parser.Advance( res ); + } + while(iElement--); + + // + // Arguments to a methods come from the eval stack and we don't fix up the eval stack for each call. + // So some arguments have the wrong datatype, since an eval stack push always promotes to 32 bits. + // + if(c_CLR_RT_DataTypeLookup[ blk->DataType() ].m_sizeInBytes == sizeof(CLR_INT32) && + c_CLR_RT_DataTypeLookup[ res.m_dt ].m_sizeInBytes < sizeof(CLR_INT32) ) + { + tmp.Assign ( *blk ); + tmp.ChangeDataType( res.m_dt ); + + reference = blk; blk = &tmp; + } + + // + // Check for enum. + // + desc.InitializeFromType( res.m_cls ); + + if(desc.m_handlerCls.m_target->IsEnum()) + { + td = desc.m_handlerCls; pTD = &td; + } + } + + return dbg->GetValue( msg, blk, reference, pTD ); + } + + return false; +} + +bool CLR_DBG_Debugger::Debugging_Value_GetField( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Value_GetField* cmd = (CLR_DBG_Commands::Debugging_Value_GetField*)msg->m_payload; + CLR_RT_HeapBlock* blk = cmd->m_heapblock; + CLR_RT_HeapBlock* reference = NULL; + CLR_RT_HeapBlock tmp; + CLR_RT_TypeDescriptor desc; + CLR_RT_TypeDef_Instance td; + CLR_RT_TypeDef_Instance* pTD = NULL; + CLR_RT_FieldDef_Instance inst; + CLR_UINT32 offset; + + if(blk != NULL && cmd->m_offset > 0) + { + if(FAILED(desc.InitializeFromObject( *blk ))) return false; + + td = desc.m_handlerCls; + offset = cmd->m_offset - 1; + + while(true) + { + CLR_UINT32 iFields = td.m_target->iFields_Num; + CLR_UINT32 totalFields = td.CrossReference().m_totalFields; + CLR_UINT32 dFields = totalFields - iFields; + + if(offset >= dFields) + { + offset -= dFields; + break; + } + + if(!td.SwitchToParent()) return false; + } + + cmd->m_fd.Set( td.Assembly(), td.m_target->iFields_First + offset ); + } + + if(!dbg->CheckFieldDef( cmd->m_fd, inst )) return false; + + if(blk == NULL) + { + blk = CLR_RT_ExecutionEngine::AccessStaticField( cmd->m_fd ); + } + else + { + if(cmd->m_offset == 0) + { + cmd->m_offset = inst.CrossReference().m_offset; + } + + if(cmd->m_offset == 0) return false; + + switch(blk->DataType()) + { + case DATATYPE_CLASS : + case DATATYPE_VALUETYPE: + break; + + default: + if(FAILED(blk->EnsureObjectReference( blk ))) return false; + break; + } + + switch(blk->DataType()) + { + case DATATYPE_DATETIME: // Special case. + case DATATYPE_TIMESPAN: // Special case. + tmp.SetInteger( (CLR_INT64)blk->NumericByRefConst().s8 ); + reference = blk; blk = &tmp; + break; + + default: + blk = &blk[ cmd->m_offset ]; + break; + } + } + + if(IsBlockEnumMaybe( blk )) + { + if(SUCCEEDED(desc.InitializeFromFieldDefinition( inst ))) + { + if(desc.m_handlerCls.m_target->IsEnum()) + { + pTD = &desc.m_handlerCls; + } + } + } + + return dbg->GetValue( msg, blk, reference, pTD ); +} + +bool CLR_DBG_Debugger::Debugging_Value_GetArray( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Value_GetArray* cmd = (CLR_DBG_Commands::Debugging_Value_GetArray*)msg->m_payload; + CLR_RT_HeapBlock* blk = NULL; + CLR_RT_HeapBlock* reference = NULL; + CLR_RT_HeapBlock tmp; + CLR_RT_HeapBlock ref; + CLR_RT_TypeDef_Instance* pTD = NULL; + CLR_RT_TypeDef_Instance td; + + tmp.SetObjectReference( cmd->m_heapblock ); + + if(SUCCEEDED(ref.InitializeArrayReference( tmp, cmd->m_index ))) + { + CLR_RT_HeapBlock_Array* array = ref.Array(); + + if(array->m_fReference) + { + blk = (CLR_RT_HeapBlock*)array->GetElement( cmd->m_index ); + } + else + { + if(FAILED(tmp.LoadFromReference( ref ))) return false; + + blk = &tmp; reference = (CLR_RT_HeapBlock*)-1; + } + + if(IsBlockEnumMaybe( blk )) + { + if(td.InitializeFromIndex( array->ReflectionDataConst().m_data.m_type )) + { + if(td.m_target->IsEnum()) + { + pTD = &td; + } + } + } + } + + return dbg->GetValue( msg, blk, reference, pTD ); +} + +bool CLR_DBG_Debugger::Debugging_Value_GetBlock( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Value_GetBlock* cmd = (CLR_DBG_Commands::Debugging_Value_GetBlock*)msg->m_payload; + CLR_RT_HeapBlock* blk = cmd->m_heapblock; + + return dbg->GetValue( msg, blk, NULL, NULL ); +} + +bool CLR_DBG_Debugger::Debugging_Value_GetScratchPad( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Value_GetScratchPad* cmd = (CLR_DBG_Commands::Debugging_Value_GetScratchPad*)msg->m_payload; + CLR_RT_HeapBlock* blk = GetScratchPad_Helper( cmd->m_idx ); + + return dbg->GetValue( msg, blk, NULL, NULL ); +} + +bool CLR_DBG_Debugger::Debugging_Value_SetBlock( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Value_SetBlock* cmd = (CLR_DBG_Commands::Debugging_Value_SetBlock*)msg->m_payload; + CLR_RT_HeapBlock* blk = cmd->m_heapblock; + + dbg->m_messaging->ReplyToCommand( msg, SetBlockHelper( blk, (CLR_DataType)cmd->m_dt, cmd->m_builtinValue ), false ); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Value_SetArray( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Value_SetArray* cmd = (CLR_DBG_Commands::Debugging_Value_SetArray*)msg->m_payload; + CLR_RT_HeapBlock_Array* array = cmd->m_heapblock; + CLR_RT_HeapBlock tmp; + bool fSuccess = false; + + tmp.SetObjectReference( cmd->m_heapblock ); + + // + // We can only set values in arrays of primitive types. + // + if(array != NULL && !array->m_fReference) + { + CLR_RT_HeapBlock ref; + + if(SUCCEEDED(ref.InitializeArrayReference( tmp, cmd->m_index ))) + { + if(SUCCEEDED(tmp.LoadFromReference( ref ))) + { + if(SetBlockHelper( &tmp, tmp.DataType(), cmd->m_builtinValue )) + { + if(SUCCEEDED(tmp.StoreToReference( ref, 0 ))) + { + fSuccess = true; + } + } + } + } + } + + dbg->m_messaging->ReplyToCommand( msg, fSuccess, false ); + + return true; +} + +//--// + +bool CLR_DBG_Debugger::Debugging_Value_AllocateObject( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Value_AllocateObject* cmd = (CLR_DBG_Commands::Debugging_Value_AllocateObject*)msg->m_payload; + CLR_RT_HeapBlock* blk = NULL; + CLR_RT_HeapBlock* ptr = GetScratchPad_Helper( cmd->m_index ); + + if(ptr) + { + if(SUCCEEDED(g_CLR_RT_ExecutionEngine.NewObjectFromIndex( *ptr, cmd->m_td ))) + { + blk = ptr; + } + } + + return dbg->GetValue( msg, blk, NULL, NULL ); +} + +bool CLR_DBG_Debugger::Debugging_Value_AllocateString( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Value_AllocateString* cmd = (CLR_DBG_Commands::Debugging_Value_AllocateString*)msg->m_payload; + CLR_RT_HeapBlock* blk = NULL; + CLR_RT_HeapBlock* ptr = GetScratchPad_Helper( cmd->m_index ); + + if(ptr) + { + CLR_RT_HeapBlock_String* str = CLR_RT_HeapBlock_String::CreateInstance( *ptr, cmd->m_size ); + + if(str) + { + LPSTR dst = (LPSTR)str->StringText(); + + // + // Fill the string with spaces, it will be set at a later stage. + // + memset( dst, ' ', cmd->m_size ); dst[ cmd->m_size ] = 0; + + blk = ptr; + } + } + + return dbg->GetValue( msg, blk, NULL, NULL ); +} + +bool CLR_DBG_Debugger::Debugging_Value_AllocateArray( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Value_AllocateArray* cmd = (CLR_DBG_Commands::Debugging_Value_AllocateArray*)msg->m_payload; + CLR_RT_HeapBlock* blk = NULL; + CLR_RT_HeapBlock* ptr = GetScratchPad_Helper( cmd->m_index ); + + if(ptr) + { + CLR_RT_ReflectionDef_Index reflex; + + reflex.m_kind = REFLECTION_TYPE; + reflex.m_levels = cmd->m_depth; + reflex.m_data.m_type = cmd->m_td; + + if(SUCCEEDED(CLR_RT_HeapBlock_Array::CreateInstance( *ptr, cmd->m_numOfElements, reflex ))) + { + blk = ptr; + } + } + + return dbg->GetValue( msg, blk, NULL, NULL ); +} + +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + +#if defined(TINYCLR_PROFILE_NEW) +bool CLR_DBG_Debugger::Profiling_Command( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Profiling_Command* cmd = (CLR_DBG_Commands::Profiling_Command*)msg->m_payload; + CLR_UINT8 command = cmd->m_command; + + switch(command) + { + case CLR_DBG_Commands::Profiling_Command::c_Command_ChangeConditions: + return dbg->Profiling_ChangeConditions( msg ); + + case CLR_DBG_Commands::Profiling_Command::c_Command_FlushStream: + return dbg->Profiling_FlushStream( msg ); + + default: + return false; + } +} + +bool CLR_DBG_Debugger::Profiling_ChangeConditions( WP_Message* msg ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Commands::Profiling_Command* parent_cmd = (CLR_DBG_Commands::Profiling_Command*)msg->m_payload; + CLR_DBG_Commands::Profiling_ChangeConditions* cmd = (CLR_DBG_Commands::Profiling_ChangeConditions*)&parent_cmd[1]; + + g_CLR_RT_ExecutionEngine.m_iProfiling_Conditions |= cmd->m_set; + g_CLR_RT_ExecutionEngine.m_iProfiling_Conditions &= ~cmd->m_reset; + + CLR_DBG_Commands::Profiling_Command::Reply cmdReply; + + cmdReply.m_raw = g_CLR_RT_ExecutionEngine.m_iProfiling_Conditions; + + m_messaging->ReplyToCommand( msg, true, false, &cmdReply, sizeof(cmdReply) ); + + _ASSERTE(FIMPLIES(CLR_EE_PRF_IS(Allocations), CLR_EE_PRF_IS(Enabled))); + _ASSERTE(FIMPLIES(CLR_EE_PRF_IS(Calls) , CLR_EE_PRF_IS(Enabled))); + + if((cmd->m_set & CLR_RT_ExecutionEngine::c_fProfiling_Enabled) != 0) + { + g_CLR_PRF_Profiler.SendMemoryLayout(); + } + + return true; +} + +bool CLR_DBG_Debugger::Profiling_FlushStream( WP_Message* msg ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Commands::Profiling_Command::Reply cmdReply; + + g_CLR_PRF_Profiler.Stream_Flush(); + + cmdReply.m_raw = 0; + + m_messaging->ReplyToCommand( msg, true, false, &cmdReply, sizeof(cmdReply) ); + + return true; +} + +#endif //#if defined(TINYCLR_PROFILE_NEW) + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + +//--// + +struct AnalyzeObject +{ + CLR_RT_HeapBlock* m_ptr; + bool m_fNull; + bool m_fBoxed; + bool m_fCanBeNull; + CLR_RT_TypeDescriptor m_desc; + CLR_RT_HeapBlock m_value; +}; + +static HRESULT AnalyzeObject_Helper( CLR_RT_HeapBlock* ptr, AnalyzeObject& ao ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + TINYCLR_HEADER(); + + if(ptr && ptr->DataType() == DATATYPE_BYREF) ptr = ptr->Dereference(); + + ao.m_ptr = ptr; + + if(ptr == NULL || (ptr->DataType() == DATATYPE_OBJECT && ptr->Dereference() == NULL)) + { + ao.m_fNull = true; + ao.m_fBoxed = false; + ao.m_fCanBeNull = true; + } + else + { + TINYCLR_CHECK_HRESULT(ao.m_desc.InitializeFromObject( *ptr )); + + ao.m_fNull = false; + ao.m_fBoxed = (ptr->DataType() == DATATYPE_OBJECT && ptr->Dereference()->IsBoxed()); + + switch(ao.m_desc.m_flags & CLR_RT_DataTypeLookup::c_SemanticMask2 & ~CLR_RT_DataTypeLookup::c_SemanticMask) + { + case CLR_RT_DataTypeLookup::c_Array: + case CLR_RT_DataTypeLookup::c_ArrayList: + ao.m_fCanBeNull = true; + break; + default: + { + switch(ao.m_desc.m_flags & CLR_RT_DataTypeLookup::c_SemanticMask) + { + case CLR_RT_DataTypeLookup::c_Primitive: + case CLR_RT_DataTypeLookup::c_ValueType: + case CLR_RT_DataTypeLookup::c_Enum: + ao.m_fCanBeNull = ao.m_fBoxed || (ao.m_desc.m_handlerCls.m_data == g_CLR_RT_WellKnownTypes.m_String.m_data); + break; + + default: + ao.m_fCanBeNull = true; + break; + } + + break; + } + } + } + + TINYCLR_NOCLEANUP(); +} + +static HRESULT Assign_Helper( CLR_RT_HeapBlock* blkDst, CLR_RT_HeapBlock* blkSrc ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + TINYCLR_HEADER(); + + AnalyzeObject aoDst; + AnalyzeObject aoSrc; + CLR_RT_HeapBlock srcVal; srcVal.SetObjectReference( NULL ); + CLR_RT_ProtectFromGC gc( srcVal ); + + TINYCLR_CHECK_HRESULT(AnalyzeObject_Helper( blkDst, aoDst )); + TINYCLR_CHECK_HRESULT(AnalyzeObject_Helper( blkSrc, aoSrc )); + + if(aoSrc.m_fNull) + { + if(aoDst.m_fCanBeNull == false) + { + TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); + } + + TINYCLR_CHECK_HRESULT(srcVal.StoreToReference( *blkDst, 0 )); + } + else + { + TINYCLR_CHECK_HRESULT(srcVal.LoadFromReference( *blkSrc )); + + if(aoDst.m_fNull) + { + if(aoSrc.m_fCanBeNull == false) + { + TINYCLR_CHECK_HRESULT(srcVal.PerformBoxing( aoSrc.m_desc.m_handlerCls )); + } + + blkDst->Assign( srcVal ); + } + else + { + if(srcVal.IsAValueType()) + { + if(blkDst->IsAValueType() == false) + { + TINYCLR_CHECK_HRESULT(srcVal.PerformBoxing( aoSrc.m_desc.m_handlerCls )); + } + } + else + { + if(blkDst->IsAValueType() == true) + { + TINYCLR_CHECK_HRESULT(srcVal.PerformUnboxing( aoSrc.m_desc.m_handlerCls )); + } + } + + TINYCLR_CHECK_HRESULT(blkDst->Reassign( srcVal )); + } + } + + TINYCLR_NOCLEANUP(); +} + + +bool CLR_DBG_Debugger::Debugging_Value_Assign( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Value_Assign* cmd = (CLR_DBG_Commands::Debugging_Value_Assign*)msg->m_payload; + CLR_RT_HeapBlock* blkDst = cmd->m_heapblockDst; + CLR_RT_HeapBlock* blkSrc = cmd->m_heapblockSrc; + + if(blkDst && FAILED(Assign_Helper( blkDst, blkSrc ))) + { + blkDst = NULL; + } + + return dbg->GetValue( msg, blkDst, NULL, NULL ); +} + +//--// + +bool CLR_DBG_Debugger::Debugging_TypeSys_Assemblies( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_RT_Assembly_Index assemblies[ CLR_RT_TypeSystem::c_MaxAssemblies ]; + int num = 0; + + TINYCLR_FOREACH_ASSEMBLY(g_CLR_RT_TypeSystem) + { + assemblies[ num++ ].Set( pASSM->m_idx ); + } + TINYCLR_FOREACH_ASSEMBLY_END(); + + dbg->m_messaging->ReplyToCommand( msg, true, false, assemblies, sizeof(CLR_RT_Assembly_Index) * num ); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_TypeSys_AppDomains( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); +#if defined(TINYCLR_APPDOMAINS) + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + int num = 0; + CLR_UINT32 appDomainIDs[ 256 ]; + + TINYCLR_FOREACH_NODE(CLR_RT_AppDomain, appDomain, g_CLR_RT_ExecutionEngine.m_appDomains) + { + appDomainIDs[ num++ ] = appDomain->m_id; + + if(num >= ARRAYSIZE(appDomainIDs)) break; + } + TINYCLR_FOREACH_NODE_END(); + + dbg->m_messaging->ReplyToCommand( msg, true, false, appDomainIDs, sizeof(CLR_UINT32) * num ); + + return true; +#else + return false; +#endif +} + +//--// + +bool CLR_DBG_Debugger::Debugging_Resolve_AppDomain( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); +#if defined(TINYCLR_APPDOMAINS) + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Resolve_AppDomain* cmd = (CLR_DBG_Commands::Debugging_Resolve_AppDomain*)msg->m_payload; + CLR_RT_AppDomain* appDomain = dbg->GetAppDomainFromID( cmd->m_id ); + CLR_UINT32 numAssemblies = 0; + CLR_DBG_Commands::Debugging_Resolve_AppDomain::Reply* cmdReply; + CLR_UINT8 buf[ sizeof(CLR_DBG_Commands::Debugging_Resolve_AppDomain::Reply) + sizeof(CLR_RT_Assembly_Index)*CLR_RT_TypeSystem::c_MaxAssemblies ]; + size_t count; + LPCSTR name; + CLR_RT_Assembly_Index* pAssemblyIndex; + + if(appDomain) + { + cmdReply = (CLR_DBG_Commands::Debugging_Resolve_AppDomain::Reply*)&buf; + + cmdReply->m_state = appDomain->m_state; + + name = appDomain->m_strName->StringText(); + count = __min( hal_strlen_s( name ) + 1, sizeof(cmdReply->m_szName) - 1 ); + + hal_strncpy_s( cmdReply->m_szName, ARRAYSIZE(cmdReply->m_szName), name, count ); + + pAssemblyIndex = (CLR_RT_Assembly_Index*)(&cmdReply->m_assemblies); + + TINYCLR_FOREACH_ASSEMBLY_IN_APPDOMAIN(appDomain) + { + pAssemblyIndex->Set( pASSM->m_idx ); + pAssemblyIndex++; + numAssemblies++; + } + TINYCLR_FOREACH_ASSEMBLY_IN_APPDOMAIN_END(); + + dbg->m_messaging->ReplyToCommand( msg, true, false, cmdReply, sizeof(*cmdReply) + sizeof(CLR_RT_Assembly_Index) * (numAssemblies - 1) ); + } + else + { + dbg->m_messaging->ReplyToCommand( msg, false, false ); + } + + return true; +#else + return false; +#endif +} + +bool CLR_DBG_Debugger::Debugging_Resolve_Assembly( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Resolve_Assembly* cmd = (CLR_DBG_Commands::Debugging_Resolve_Assembly*)msg->m_payload; + CLR_DBG_Commands::Debugging_Resolve_Assembly::Reply cmdReply; + CLR_RT_Assembly* assm = dbg->IsGoodAssembly( cmd->m_idx.Assembly() ); + + if(assm) + { +#if defined(_WIN32) + //append path + if(assm->m_strPath != NULL) + { + sprintf_s( cmdReply.m_szName, ARRAYSIZE(cmdReply.m_szName), "%s,%s", assm->m_szName, assm->m_strPath->c_str() ); + } + else +#endif + { + hal_strncpy_s( cmdReply.m_szName, ARRAYSIZE(cmdReply.m_szName), assm->m_szName, MAXSTRLEN(cmdReply.m_szName) ); + } + + cmdReply.m_flags = assm->m_flags; + cmdReply.m_version = assm->m_header->version; + + dbg->m_messaging->ReplyToCommand( msg, true, false, &cmdReply, sizeof(cmdReply) ); + + return true; + } + + dbg->m_messaging->ReplyToCommand( msg, false, false ); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Resolve_Type( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Resolve_Type* cmd = (CLR_DBG_Commands::Debugging_Resolve_Type*)msg->m_payload; + CLR_DBG_Commands::Debugging_Resolve_Type::Reply cmdReply; + CLR_RT_TypeDef_Instance inst; + + if(dbg->CheckTypeDef( cmd->m_td, inst )) + { + LPSTR szBuffer = cmdReply.m_type; + size_t iBuffer = MAXSTRLEN(cmdReply.m_type); + + if(SUCCEEDED(g_CLR_RT_TypeSystem.BuildTypeName( inst, szBuffer, iBuffer ))) + { + dbg->m_messaging->ReplyToCommand( msg, true, false, &cmdReply, sizeof(cmdReply) ); + + return true; + } + } + + dbg->m_messaging->ReplyToCommand( msg, false, false ); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Resolve_Field( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Resolve_Field* cmd = (CLR_DBG_Commands::Debugging_Resolve_Field*)msg->m_payload; + CLR_DBG_Commands::Debugging_Resolve_Field::Reply cmdReply; + CLR_RT_FieldDef_Instance inst; + + if(dbg->CheckFieldDef( cmd->m_fd, inst )) + { + LPSTR szBuffer = cmdReply.m_name; + size_t iBuffer = MAXSTRLEN(cmdReply.m_name); + + if(SUCCEEDED(g_CLR_RT_TypeSystem.BuildFieldName( inst, szBuffer, iBuffer ))) + { + CLR_RT_TypeDef_Instance instClass; instClass.InitializeFromField( inst ); + + cmdReply.m_td = instClass; + cmdReply.m_index = inst.CrossReference().m_offset; + + dbg->m_messaging->ReplyToCommand( msg, true, false, &cmdReply, sizeof(cmdReply) ); + + return true; + } + } + + dbg->m_messaging->ReplyToCommand( msg, false, false ); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Resolve_Method( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Resolve_Method* cmd = (CLR_DBG_Commands::Debugging_Resolve_Method*)msg->m_payload; + CLR_DBG_Commands::Debugging_Resolve_Method::Reply cmdReply; + CLR_RT_MethodDef_Instance inst; + CLR_RT_TypeDef_Instance instOwner; + + if(dbg->CheckMethodDef( cmd->m_md, inst ) && instOwner.InitializeFromMethod( inst )) + { + LPSTR szBuffer = cmdReply.m_method; + size_t iBuffer = MAXSTRLEN(cmdReply.m_method); + + cmdReply.m_td = instOwner; + + CLR_SafeSprintf( szBuffer, iBuffer, "%s", inst.m_assm->GetString( inst.m_target->name ) ); + + dbg->m_messaging->ReplyToCommand( msg, true, false, &cmdReply, sizeof(cmdReply) ); + + return true; + } + + dbg->m_messaging->ReplyToCommand( msg, false, false ); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Resolve_VirtualMethod( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Resolve_VirtualMethod* cmd = (CLR_DBG_Commands::Debugging_Resolve_VirtualMethod*)msg->m_payload; + CLR_DBG_Commands::Debugging_Resolve_VirtualMethod::Reply cmdReply; + CLR_RT_TypeDef_Index cls; + CLR_RT_MethodDef_Index md; + + cmdReply.m_md.Clear(); + + if(SUCCEEDED(CLR_RT_TypeDescriptor::ExtractTypeIndexFromObject( *cmd->m_obj, cls ))) + { + if(g_CLR_RT_EventCache.FindVirtualMethod( cls, cmd->m_md, md )) + { + cmdReply.m_md = md; + } + } + + dbg->m_messaging->ReplyToCommand( msg, true, false, &cmdReply, sizeof(cmdReply) ); + + return true; +} + + +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + +//--// + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + +bool CLR_DBG_Debugger::Debugging_Deployment_Status( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Deployment_Status::Reply* cmdReply; + CLR_UINT32 totLength; + CLR_UINT32 deploySectorsNum = 0; + CLR_UINT32 deploySectorStart = 0; + CLR_UINT32 deployLength = 0; + + const BlockDeviceInfo* deviceInfo; + + // find the first device in list with DEPLOYMENT blocks + if (m_deploymentStorageDevice != NULL) + { + BlockStorageStream stream; + + if(stream.Initialize( BlockUsage::DEPLOYMENT, m_deploymentStorageDevice )) + { + do + { + if(deploySectorsNum == 0) + { + deploySectorStart = stream.CurrentAddress(); + } + deployLength += stream.Length; + deploySectorsNum ++; + } + while(stream.NextStream() && stream.BaseAddress == (deploySectorStart + deployLength)); + } + + deviceInfo = m_deploymentStorageDevice->GetDeviceInfo(); + + totLength = sizeof(CLR_DBG_Commands::Debugging_Deployment_Status::Reply) + (deploySectorsNum) * sizeof(CLR_DBG_Commands::Debugging_Deployment_Status::FlashSector); + + cmdReply = (CLR_DBG_Commands::Debugging_Deployment_Status::Reply*)CLR_RT_Memory::Allocate( totLength, true ); + + if(!cmdReply) return false; + + CLR_RT_Memory::ZeroFill( cmdReply, totLength ); + + cmdReply->m_entryPoint = g_CLR_RT_TypeSystem.m_entryPoint.m_data; + cmdReply->m_storageStart = deploySectorStart; + cmdReply->m_storageLength = deployLength; + cmdReply->m_eraseWord = 0xffffffff; //Is this true for all current devices? + cmdReply->m_maxSectorErase_uSec = m_deploymentStorageDevice->MaxBlockErase_uSec(); + cmdReply->m_maxWordWrite_uSec = m_deploymentStorageDevice->MaxSectorWrite_uSec(); + + int index = 0; + + bool fDone = false; + + if(stream.Initialize( BlockUsage::DEPLOYMENT, m_deploymentStorageDevice )) + { + do + { + FLASH_WORD * dataBuf = NULL; + CLR_UINT32 crc=0; + + if (!(deviceInfo->Attribute.SupportsXIP)) + { + // length for each block can be different, so should malloc and free at each block + dataBuf = (FLASH_WORD* )CLR_RT_Memory::Allocate( stream.BlockLength, true ); if(!dataBuf) return false; + } + + //or should the PC have to calculate this?? + // need to read the data to a buffer first. + if (m_deploymentStorageDevice->IsBlockErased( stream.CurrentAddress(), stream.Length )) + { + crc = CLR_DBG_Commands::Monitor_DeploymentMap::c_CRC_Erased_Sentinel; + } + else + { + int len = stream.Length; + while(len > 0) + { + stream.Read( (BYTE **)&dataBuf, stream.BlockLength ); + + crc = SUPPORT_ComputeCRC( dataBuf, stream.BlockLength, crc ); + + len -= stream.BlockLength; + } + } + + if (!(deviceInfo->Attribute.SupportsXIP)) + { + CLR_RT_Memory::Release( dataBuf ); + } + + // need real address + cmdReply->m_data[ index ].m_start = stream.BaseAddress; + cmdReply->m_data[ index ].m_length = stream.Length; + cmdReply->m_data[ index ].m_crc = crc; + index ++; + + if(index >= (INT32)deploySectorsNum) + { + fDone = true; + break; + } + + } + while(stream.NextStream()); + } + + dbg->m_messaging->ReplyToCommand( msg, true, false, cmdReply, totLength ); + + CLR_RT_Memory::Release( cmdReply ); + + return true; + } + else + { + dbg->m_messaging->ReplyToCommand( msg, false, false, NULL, 0 ); + return false; + } +} + +bool CLR_DBG_Debugger::Debugging_Info_SetJMC_Method( const CLR_RT_MethodDef_Index& idx, bool fJMC ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_RT_MethodDef_Instance inst; + + if(!CheckMethodDef( idx, inst ) ) return false; + if(inst.m_target->RVA == CLR_EmptyIndex) return false; + + inst.DebuggingInfo().SetJMC( fJMC ); + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Info_SetJMC_Type( const CLR_RT_TypeDef_Index& idx, bool fJMC ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + const CLR_RECORD_TYPEDEF* td; + CLR_RT_TypeDef_Instance inst; + int totMethods; + CLR_RT_MethodDef_Index md; + + if(!CheckTypeDef( idx, inst )) return false; + + td = inst.m_target; + totMethods = td->vMethods_Num + td->iMethods_Num + td->sMethods_Num; + + for(int i=0; imethods_First + i ); + + Debugging_Info_SetJMC_Method( md, fJMC ); + } + + return true; +} + +bool CLR_DBG_Debugger::Debugging_Info_SetJMC( WP_Message* msg, void* owner ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + CLR_DBG_Debugger* dbg = (CLR_DBG_Debugger*)owner; + CLR_DBG_Commands::Debugging_Info_SetJMC* cmd = (CLR_DBG_Commands::Debugging_Info_SetJMC*)msg->m_payload; + bool fJMC = (cmd->m_fIsJMC != 0); + + switch(cmd->m_kind) + { + case REFLECTION_ASSEMBLY: + { + CLR_RT_Assembly* assm = dbg->IsGoodAssembly( cmd->m_data.m_assm.Assembly() ); + + if(!assm) return false; + + for(int i=0; im_pTablesSize[ TBL_TypeDef ]; i++) + { + CLR_RT_TypeDef_Index idx; + + idx.Set( cmd->m_data.m_assm.Assembly(), i ); + + dbg->Debugging_Info_SetJMC_Type( idx, fJMC ); + } + + return true; + } + + case REFLECTION_TYPE: + return dbg->Debugging_Info_SetJMC_Type( cmd->m_data.m_type, fJMC ); + + case REFLECTION_METHOD: + return dbg->Debugging_Info_SetJMC_Method( cmd->m_data.m_method, fJMC ); + + default: + return false; + } +} + +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) diff --git a/src/CLR/Debugger/Debugger.vcxproj b/src/CLR/Debugger/Debugger.vcxproj new file mode 100644 index 0000000000..520679756a --- /dev/null +++ b/src/CLR/Debugger/Debugger.vcxproj @@ -0,0 +1,166 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + {58e950cc-2ff6-423c-b006-a70a19272f20} + false + false + + + + {DD397EC4-844B-4B59-A67B-CAD6B46F1F00} + Win32Proj + Debugger + 10.0.14393.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\Include;..\CorLib + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\Include;..\CorLib + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\Include;..\CorLib + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\Include;..\CorLib + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/src/CLR/Debugger/Debugger.vcxproj.filters b/src/CLR/Debugger/Debugger.vcxproj.filters new file mode 100644 index 0000000000..808f2bd0fe --- /dev/null +++ b/src/CLR/Debugger/Debugger.vcxproj.filters @@ -0,0 +1,25 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/src/CLR/Debugger/Debugger_full.cpp b/src/CLR/Debugger/Debugger_full.cpp new file mode 100644 index 0000000000..92a951ec33 --- /dev/null +++ b/src/CLR/Debugger/Debugger_full.cpp @@ -0,0 +1,107 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include +#include + +#define DEFINE_CMD(cmd) { CLR_DBG_Debugger::Debugging_##cmd, CLR_DBG_Commands::c_Debugging_##cmd } +#define DEFINE_CMD2(cmd) { CLR_DBG_Debugger::Monitor_##cmd , CLR_DBG_Commands::c_Monitor_##cmd } +#define DEFINE_CMD3(cmd) { &CLR_DBG_Debugger::Profiling_##cmd, CLR_DBG_Commands::c_Profiling_##cmd } + +const CLR_Messaging_CommandHandlerLookup c_Debugger_Lookup_Request[] = +{ + DEFINE_CMD(Execution_QueryCLRCapabilities), + DEFINE_CMD2(Ping ), + DEFINE_CMD2(ReadMemory ), + DEFINE_CMD2(WriteMemory), + DEFINE_CMD2(CheckMemory), + DEFINE_CMD2(EraseMemory), + // + DEFINE_CMD2(Execute ), + DEFINE_CMD2(Reboot ), + DEFINE_CMD2(MemoryMap ), + DEFINE_CMD2(FlashSectorMap), + DEFINE_CMD2(DeploymentMap), + + // + DEFINE_CMD(Execution_BasePtr ), + DEFINE_CMD(Execution_ChangeConditions), + // + DEFINE_CMD(Execution_Allocate ), + + DEFINE_CMD(UpgradeToSsl), + + + + + + + + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + DEFINE_CMD(Execution_SetCurrentAppDomain), + DEFINE_CMD(Execution_Breakpoints ), + DEFINE_CMD(Execution_BreakpointStatus ), + // + DEFINE_CMD(Thread_CreateEx ), + DEFINE_CMD(Thread_List ), + DEFINE_CMD(Thread_Stack ), + DEFINE_CMD(Thread_Kill ), + DEFINE_CMD(Thread_Suspend ), + DEFINE_CMD(Thread_Resume ), + DEFINE_CMD(Thread_GetException ), + DEFINE_CMD(Thread_Unwind ), + DEFINE_CMD(Thread_Get ), + // + DEFINE_CMD(Stack_Info ), + DEFINE_CMD(Stack_SetIP ), + // + DEFINE_CMD(Value_ResizeScratchPad ), + DEFINE_CMD(Value_GetStack ), + DEFINE_CMD(Value_GetField ), + DEFINE_CMD(Value_GetArray ), + DEFINE_CMD(Value_GetBlock ), + DEFINE_CMD(Value_GetScratchPad ), + DEFINE_CMD(Value_SetBlock ), + DEFINE_CMD(Value_SetArray ), + DEFINE_CMD(Value_AllocateObject ), + DEFINE_CMD(Value_AllocateString ), + DEFINE_CMD(Value_AllocateArray ), + DEFINE_CMD(Value_Assign ), + // + DEFINE_CMD(TypeSys_Assemblies ), + DEFINE_CMD(TypeSys_AppDomains ), + // + DEFINE_CMD(Resolve_AppDomain ), + DEFINE_CMD(Resolve_Assembly ), + DEFINE_CMD(Resolve_Type ), + DEFINE_CMD(Resolve_Field ), + DEFINE_CMD(Resolve_Method ), + DEFINE_CMD(Resolve_VirtualMethod ), +#endif + // +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + DEFINE_CMD(Deployment_Status ), + DEFINE_CMD(Info_SetJMC ), +#endif + // +#if defined(TINYCLR_PROFILE_NEW) + DEFINE_CMD3(Command), +#endif + // +}; + +const CLR_Messaging_CommandHandlerLookup c_Debugger_Lookup_Reply[] = +{ + DEFINE_CMD2(Ping), +}; + +#undef DEFINE_CMD +#undef DEFINE_CMD2 +#undef DEFINE_CMD3 + +const CLR_UINT32 c_Debugger_Lookup_Request_count = ARRAYSIZE(c_Debugger_Lookup_Request); +const CLR_UINT32 c_Debugger_Lookup_Reply_count = ARRAYSIZE(c_Debugger_Lookup_Reply); + diff --git a/src/CLR/Debugger/Debugger_stub.cpp b/src/CLR/Debugger/Debugger_stub.cpp new file mode 100644 index 0000000000..dcdd0070c9 --- /dev/null +++ b/src/CLR/Debugger/Debugger_stub.cpp @@ -0,0 +1,61 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void CLR_DBG_Debugger::Debugger_WaitForCommands() +{ + NATIVE_PROFILE_CLR_DEBUGGER(); +} + +void CLR_DBG_Debugger::Debugger_Discovery() +{ + NATIVE_PROFILE_CLR_DEBUGGER(); +} + +void CLR_DBG_Debugger::ProcessCommands() +{ + NATIVE_PROFILE_CLR_DEBUGGER(); +} + +void CLR_DBG_Debugger::PurgeCache() +{ + NATIVE_PROFILE_CLR_DEBUGGER(); +} + +HRESULT CLR_DBG_Debugger::CreateInstance() +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + g_CLR_DBG_Debuggers = (CLR_DBG_Debugger*)&g_scratchDebugger[0]; + TINYCLR_SYSTEM_STUB_RETURN(); +} + +//--// + +HRESULT CLR_DBG_Debugger::DeleteInstance() +{ + NATIVE_PROFILE_CLR_DEBUGGER(); + TINYCLR_SYSTEM_STUB_RETURN(); +} + +void CLR_DBG_Debugger::BroadcastEvent( UINT32 cmd, UINT32 payloadSize, UINT8* payload, UINT32 flags ) +{ + NATIVE_PROFILE_CLR_DEBUGGER(); +} + +void MfReleaseInfo::Init( MfReleaseInfo& mfReleaseInfo, UINT16 major, UINT16 minor, UINT16 build, UINT16 revision, const char *info, size_t infoLen ) +{ + MFVersion::Init( mfReleaseInfo.version, major, minor, build, revision ); + mfReleaseInfo.infoString[ 0 ] = 0; + if ( NULL != info && infoLen > 0 ) + { + const size_t len = MIN(infoLen, sizeof(mfReleaseInfo.infoString)-1); + hal_strncpy_s( (char*)&mfReleaseInfo.infoString[0], sizeof(mfReleaseInfo.infoString), info, len ); + } +} + diff --git a/src/CLR/Debugger/Debugger_stub.vcxproj b/src/CLR/Debugger/Debugger_stub.vcxproj new file mode 100644 index 0000000000..077ad003a9 --- /dev/null +++ b/src/CLR/Debugger/Debugger_stub.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + {6DABCBF1-245A-4E76-BD36-8BC300C7DD82} + Win32Proj + Debugger_stub + 10.0.14393.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\Include + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\Include + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/src/CLR/Debugger/Debugger_stub.vcxproj.filters b/src/CLR/Debugger/Debugger_stub.vcxproj.filters new file mode 100644 index 0000000000..3397cd3fd1 --- /dev/null +++ b/src/CLR/Debugger/Debugger_stub.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/src/CLR/Diagnostics/Diagnostics.h b/src/CLR/Diagnostics/Diagnostics.h new file mode 100644 index 0000000000..1db9da385c --- /dev/null +++ b/src/CLR/Diagnostics/Diagnostics.h @@ -0,0 +1,14 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include +#include +//#include +//#include +//#include +//#include + +#include +//#include diff --git a/src/CLR/Diagnostics/Diagnostics.vcxproj b/src/CLR/Diagnostics/Diagnostics.vcxproj new file mode 100644 index 0000000000..e5b8c7934a --- /dev/null +++ b/src/CLR/Diagnostics/Diagnostics.vcxproj @@ -0,0 +1,160 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B} + Win32Proj + Diagnostics + 10.0.14393.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\Include;..\CorLib + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/src/CLR/Diagnostics/Diagnostics.vcxproj.filters b/src/CLR/Diagnostics/Diagnostics.vcxproj.filters new file mode 100644 index 0000000000..b221969501 --- /dev/null +++ b/src/CLR/Diagnostics/Diagnostics.vcxproj.filters @@ -0,0 +1,33 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/src/CLR/Diagnostics/Diagnostics_stub.cpp b/src/CLR/Diagnostics/Diagnostics_stub.cpp new file mode 100644 index 0000000000..183f38ebb9 --- /dev/null +++ b/src/CLR/Diagnostics/Diagnostics_stub.cpp @@ -0,0 +1,480 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Diagnostics.h" + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(_WIN32) + +void CLR_Debug::RedirectToString( std::string* str ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +#endif + +HRESULT TINYCLR_DEBUG_PROCESS_EXCEPTION( HRESULT hr, LPCSTR szFunc, LPCSTR szFile, int line ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return hr; +} + +bool CLR_SafeSprintfV( LPSTR& szBuffer, size_t& iBuffer, LPCSTR format, va_list arg ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + int chars = hal_vsnprintf( szBuffer, iBuffer, format, arg ); + bool fRes = (chars >= 0); + + if(fRes == false) chars = (int)iBuffer; + + szBuffer += chars; szBuffer[ 0 ] = 0; + iBuffer -= chars; + + return fRes; +} + +bool CLR_SafeSprintf( LPSTR& szBuffer, size_t& iBuffer, LPCSTR format, ... ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + va_list arg; + bool fRes; + + va_start( arg, format ); + + fRes = CLR_SafeSprintfV( szBuffer, iBuffer, format, arg ); + + va_end( arg ); + + return fRes; +} + +//--// + +void CLR_Debug::Flush() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +void CLR_Debug::Emit( const char *text, int len ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +int CLR_Debug::PrintfV( const char *format, va_list arg ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return 0; +} + +int CLR_Debug::Printf( const char *format, ... ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return 0; +} + +//--// + +CLR_UINT32 CLR_ReadTokenCompressed( const CLR_UINT8*& ip, CLR_OPCODE opcode ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return 0; +} + +const CLR_UINT8* CLR_SkipBodyOfOpcode( const CLR_UINT8* ip, CLR_OPCODE opcode ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return 0; +} + +const CLR_UINT8* CLR_SkipBodyOfOpcodeCompressed( const CLR_UINT8* ip, CLR_OPCODE opcode ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return 0; +} + +#if defined(TINYCLR_TRACE_INSTRUCTIONS) + +void CLR_RT_Assembly::DumpToken( CLR_UINT32 tk ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +void CLR_RT_Assembly::DumpSignature( CLR_SIG sig ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +void CLR_RT_Assembly::DumpSignature( const CLR_UINT8*& p ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +void CLR_RT_Assembly::DumpSignatureToken( const CLR_UINT8*& p ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +//--// + +void CLR_RT_Assembly::DumpOpcode( CLR_RT_StackFrame* stack, CLR_PMETADATA ip ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +void CLR_RT_Assembly::DumpOpcodeDirect( CLR_RT_MethodDef_Instance& call, CLR_PMETADATA ip, CLR_PMETADATA ipStart, int pid ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +#endif + +#if defined(TINYCLR_TRACE_CALLS) + +void CLR_RT_Assembly::DumpCall( CLR_RT_StackFrame& stack, bool fPush ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +void CLR_RT_Assembly::DumpCall( CLR_RT_MethodDef_Instance& md, LPCSTR szPrefix ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(TINYCLR_TRACE_ERRORS) + +void CLR_RT_DUMP::TYPE( const CLR_RT_TypeDef_Index& cls ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +void CLR_RT_DUMP::TYPE( const CLR_RT_ReflectionDef_Index& reflex ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +void CLR_RT_DUMP::METHOD( const CLR_RT_MethodDef_Index& method ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +void CLR_RT_DUMP::FIELD( const CLR_RT_FieldDef_Index& field ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +void CLR_RT_DUMP::OBJECT( CLR_RT_HeapBlock* ptr, LPCSTR text ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +#endif + +//--// + +#if defined(TINYCLR_TRACE_EXCEPTIONS) + +void CLR_RT_DUMP::EXCEPTION( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock& ref ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +void CLR_RT_DUMP::POST_PROCESS_EXCEPTION( CLR_RT_HeapBlock& ref ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +#endif + +//--// + +LPCSTR CLR_RT_DUMP::GETERRORMESSAGE( HRESULT hrError ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return NULL; +} + +//--// + +#if defined(TINYCLR_PROFILE_NEW_CALLS) + +void* CLR_PROF_CounterCallChain::Prepare( CLR_PROF_Handler* handler ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return NULL; +} + +void CLR_PROF_CounterCallChain::Complete( CLR_UINT64& t, CLR_PROF_Handler* handler ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +void CLR_PROF_CounterCallChain::Enter( CLR_RT_StackFrame* stack ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +void CLR_PROF_CounterCallChain::Leave() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} +#endif + +//--// + +#if defined(TINYCLR_PROFILE_HANDLER) + +void CLR_PROF_Handler::Constructor() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +#if defined(TINYCLR_PROFILE_NEW_CALLS) +void CLR_PROF_Handler::Constructor( CLR_PROF_CounterCallChain& target ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} +#endif + +void CLR_PROF_Handler::Destructor() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + + +void CLR_PROF_Handler::Init( void* target ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + + +//--// + +void CLR_PROF_Handler::Calibrate() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +void CLR_PROF_Handler::SuspendTime() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +CLR_UINT64 CLR_PROF_Handler::GetFrozenTime() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return 0; +} + +CLR_UINT64 CLR_PROF_Handler::ResumeTime() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return 0; +} + +CLR_UINT64 CLR_PROF_Handler::ResumeTime( CLR_INT64 t ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return 0; +} + +#endif //#if defined(TINYCLR_PROFILE_HANDLER) + +//////////////////////////////////////////////////////////////////////////////// + +//--// + +#if defined(TINYCLR_PROFILE_NEW) + +CLR_PRF_Profiler g_CLR_PRF_Profiler; + +HRESULT CLR_PRF_Profiler::CreateInstance() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return S_OK; +} + +HRESULT CLR_PRF_Profiler::DeleteInstance() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return S_OK; +} + +HRESULT CLR_PRF_Profiler::Profiler_Cleanup() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return S_OK; +} + +void CLR_PRF_Profiler::SendMemoryLayout() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +HRESULT CLR_PRF_Profiler::DumpHeap() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return S_OK; +} + +HRESULT CLR_PRF_Profiler::DumpRoots() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return S_OK; +} + +void CLR_PRF_Profiler::DumpRoot(CLR_RT_HeapBlock* root, CLR_UINT32 type, CLR_UINT32 flags, CLR_RT_MethodDef_Index* source) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +void CLR_PRF_Profiler::DumpObject(CLR_RT_HeapBlock* ptr) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +CLR_RT_HeapBlock* CLR_PRF_Profiler::FindReferencedObject(CLR_RT_HeapBlock* ref) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return NULL; +} + +void CLR_PRF_Profiler::DumpEndOfRefsList() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +void CLR_PRF_Profiler::DumpPointer(void* ptr) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +void CLR_PRF_Profiler::DumpSingleReference(CLR_RT_HeapBlock* ptr) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +void CLR_PRF_Profiler::DumpListOfReferences(CLR_RT_HeapBlock* firstItem, CLR_UINT16 count) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +void CLR_PRF_Profiler::DumpListOfReferences(CLR_RT_DblLinkedList& list) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +//--// + +void CLR_PRF_Profiler::Timestamp() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +//--// + +HRESULT CLR_PRF_Profiler::RecordContextSwitch(CLR_RT_Thread* nextThread) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return S_OK; +} + +HRESULT CLR_PRF_Profiler::RecordFunctionCall(CLR_RT_Thread* th, CLR_RT_MethodDef_Index md) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return S_OK; +} + +HRESULT CLR_PRF_Profiler::RecordFunctionReturn(CLR_RT_Thread* th, CLR_PROF_CounterCallChain& prof) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return S_OK; +} + +//--// + +void CLR_PRF_Profiler::TrackObjectCreation( CLR_RT_HeapBlock* ptr ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +void CLR_PRF_Profiler::TrackObjectDeletion( CLR_RT_HeapBlock* ptr ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +void CLR_PRF_Profiler::TrackObjectRelocation() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +void CLR_PRF_Profiler::RecordGarbageCollectionBegin() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +void CLR_PRF_Profiler::RecordGarbageCollectionEnd() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +void CLR_PRF_Profiler::RecordHeapCompactionBegin() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +void CLR_PRF_Profiler::RecordHeapCompactionEnd() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +//--// + +void CLR_PRF_Profiler::SendTrue() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +void CLR_PRF_Profiler::SendFalse() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +void CLR_PRF_Profiler::PackAndWriteBits(CLR_UINT32 value) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +void CLR_PRF_Profiler::PackAndWriteBits(const CLR_RT_TypeDef_Index& typeDef) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +void CLR_PRF_Profiler::PackAndWriteBits(const CLR_RT_MethodDef_Index& methodDef) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +} + +//--// + +HRESULT CLR_PRF_Profiler::Stream_Send() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return S_OK; +} + +HRESULT CLR_PRF_Profiler::Stream_Flush() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return S_OK; +} + +#endif //#if defined(TINYCLR_PROFILE_NEW) + diff --git a/src/CLR/Diagnostics/Diagnostics_stub.vcxproj b/src/CLR/Diagnostics/Diagnostics_stub.vcxproj new file mode 100644 index 0000000000..6f3bac2b34 --- /dev/null +++ b/src/CLR/Diagnostics/Diagnostics_stub.vcxproj @@ -0,0 +1,161 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + {C97A9845-02DC-46E4-B219-BF5EA8FB28E3} + Win32Proj + Diagnostics_stub + 10.0.14393.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\Include;..\CorLib + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\Include;..\CorLib + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\Include;..\CorLib + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\Include;..\CorLib + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/src/CLR/Diagnostics/Diagnostics_stub.vcxproj.filters b/src/CLR/Diagnostics/Diagnostics_stub.vcxproj.filters new file mode 100644 index 0000000000..0059012f6e --- /dev/null +++ b/src/CLR/Diagnostics/Diagnostics_stub.vcxproj.filters @@ -0,0 +1,27 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/src/CLR/Diagnostics/Info.cpp b/src/CLR/Diagnostics/Info.cpp new file mode 100644 index 0000000000..1c8e5b1fc6 --- /dev/null +++ b/src/CLR/Diagnostics/Info.cpp @@ -0,0 +1,834 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Diagnostics.h" + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(_WIN32) + +static std::string* s_redirectedString = NULL; + +void CLR_Debug::RedirectToString( std::string* str ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + s_redirectedString = str; +} + +HRESULT TINYCLR_DEBUG_PROCESS_EXCEPTION( HRESULT hr, LPCSTR szFunc, LPCSTR szFile, int line ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + switch(hr) + { + case CLR_E_ENTRY_NOT_FOUND: + case CLR_E_PROCESS_EXCEPTION: + case CLR_E_THREAD_WAITING: + case CLR_E_RESTART_EXECUTION: + case CLR_E_RESCHEDULE: + case CLR_E_OUT_OF_MEMORY: + return hr; + } + + if(s_CLR_RT_fTrace_StopOnFAILED >= c_CLR_RT_Trace_Info) + { + if(::IsDebuggerPresent()) + { + ::DebugBreak(); + } + } + return hr; +} + +#else + +#if defined(TINYCLR_TRACE_HRESULT) +HRESULT TINYCLR_DEBUG_PROCESS_EXCEPTION( HRESULT hr, LPCSTR szFunc, LPCSTR szFile, int line ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + switch(hr) + { + case CLR_E_ENTRY_NOT_FOUND: + + case CLR_E_PROCESS_EXCEPTION: + case CLR_E_THREAD_WAITING: + case CLR_E_RESTART_EXECUTION: + return hr; + } + + CLR_Debug::Printf( "HRESULT %08x: %s %s:%d\r\n", hr, szFunc, szFile, line ); + return hr; +} +#endif + +#endif + +//--// + +bool CLR_SafeSprintfV( LPSTR& szBuffer, size_t& iBuffer, LPCSTR format, va_list arg ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + int chars = hal_vsnprintf( szBuffer, iBuffer, format, arg ); + bool fRes = (chars >= 0); + + if(fRes == false) chars = (int)iBuffer; + + szBuffer += chars; szBuffer[ 0 ] = 0; + iBuffer -= chars; + + return fRes; +} + +bool CLR_SafeSprintf( LPSTR& szBuffer, size_t& iBuffer, LPCSTR format, ... ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + va_list arg; + bool fRes; + + va_start( arg, format ); + + fRes = CLR_SafeSprintfV( szBuffer, iBuffer, format, arg ); + + va_end( arg ); + + return fRes; +} + + +//--// + +void CLR_Debug::Flush() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + DebuggerPort_Flush( HalSystemConfig.DebugTextPort ); +} + +void CLR_Debug::Emit( const char *text, int len ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + static char s_buffer[ 128 ]; + static int s_chars = 0; + + if(CLR_EE_DBG_IS( RebootPending)) return; + + if(len == -1) len = (int)hal_strlen_s( text ); + +#if defined(_WIN32) + if(s_redirectedString) + { + s_redirectedString->append( text, len ); + return; + } + + if(s_CLR_RT_fTrace_RedirectOutput.size()) + { + static HANDLE hFile = INVALID_HANDLE_VALUE; + static int lines = 0; + static int num = 0; + + if(hFile == INVALID_HANDLE_VALUE) + { + std::wstring file = s_CLR_RT_fTrace_RedirectOutput; + + if(s_CLR_RT_fTrace_RedirectLinesPerFile) + { + WCHAR rgBuf[ 64 ]; + + swprintf( rgBuf, ARRAYSIZE(rgBuf), L".%08d", num++ ); + + file.append( rgBuf ); + } + + hFile = ::CreateFileW( file.c_str(), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_ALWAYS, 0, 0 ); + + lines = 0; + } + + if(hFile != INVALID_HANDLE_VALUE) + { + DWORD dwWritten; + + ::WriteFile( hFile, text, (DWORD)len, &dwWritten, NULL ); + + if(s_CLR_RT_fTrace_RedirectLinesPerFile) + { + while((text = strchr( text, '\n' )) != NULL) + { + lines++; + text++; + + if(text[ 0 ] == 0) + { + if(lines > s_CLR_RT_fTrace_RedirectLinesPerFile) + { + ::CloseHandle( hFile ); hFile = INVALID_HANDLE_VALUE; + } + + break; + } + } + } + + return; + } + } +#endif + + while(len > 0) + { + int avail = MAXSTRLEN(s_buffer) - s_chars; + + if(len < avail) avail = len; + + memcpy( &s_buffer[ s_chars ], text, avail ); + + s_chars += avail; + text += avail; + len -= avail; + s_buffer[ s_chars ] = 0; + + if(s_chars > 80 || strchr( s_buffer, '\n' )) + { + ::Watchdog_ResetCounter(); + +#if defined(PLATFORM_WINDOWS_EMULATOR) + HAL_Windows_Debug_Print( s_buffer ); +#endif + + if(CLR_EE_DBG_IS( Enabled ) && !CLR_EE_DBG_IS( Quiet )) + { + CLR_EE_DBG_EVENT_BROADCAST( CLR_DBG_Commands::c_Monitor_Message, s_chars, s_buffer, WP_Flags::c_NonCritical | WP_Flags::c_NoCaching ); + } + + if(!CLR_EE_DBG_IS( Enabled ) || HalSystemConfig.DebugTextPort != HalSystemConfig.DebuggerPorts[ 0 ]) + { +//#if !defined(PLATFORM_TOOLS) +// TODO: Fix the build so that PLATFORM_TOOLS can work here +// (or eliminate the use of native code from the CLR in the tools by converting them all to managed) +// This entire function could be moved to info_win32.cpp to help. +// The problem is that the build doesn't distinguish between building the diagnostics lib for +// desktop tools, X86, WIN32 or the emulator platforms. And this code was written to assume +// an equivalence for all - as the idea of a non-win32 emulator port to an x86 device wasn't +// considered a reality. However, for testing and development purposes a pure non-emulator x86 +// build is useful, not to mention the potential of Quark and Edison x86 family of chip sets +// targeting IoT. Thus, this needs some re-thinking as DebuggerPort_Write etc... aren't available +// when building the desktop tools, but should be available when building a WIN32 based test +// platform +#if !defined(_WIN32) + DebuggerPort_Write( HalSystemConfig.DebugTextPort, s_buffer, s_chars, 0 ); // skip null terminator and don't bother retrying + DebuggerPort_Flush( HalSystemConfig.DebugTextPort ); // skip null terminator +#endif + } + + s_chars = 0; + } + } +} + +int CLR_Debug::PrintfV( const char *format, va_list arg ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + + char buffer[512]; + + LPSTR szBuffer = buffer; + size_t iBuffer = MAXSTRLEN(buffer); + + bool fRes = CLR_SafeSprintfV( szBuffer, iBuffer, format, arg ); + + _ASSERTE(fRes); + + iBuffer = MAXSTRLEN(buffer) - iBuffer; + + Emit( buffer, (int)iBuffer ); + + return (int)iBuffer; +} + +int CLR_Debug::Printf( const char *format, ... ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + va_list arg; + int chars; + + va_start( arg, format ); + + chars = CLR_Debug::PrintfV( format, arg ); + + va_end( arg ); + + return chars; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(_WIN32) + +const CLR_UINT8 c_CLR_opParamSize[] = +{ + 4, // CLR_OpcodeParam_Field + 4, // CLR_OpcodeParam_Method + 4, // CLR_OpcodeParam_Type + 4, // CLR_OpcodeParam_String + 4, // CLR_OpcodeParam_Tok + 4, // CLR_OpcodeParam_Sig + 4, // CLR_OpcodeParam_BrTarget + 1, // CLR_OpcodeParam_ShortBrTarget + 4, // CLR_OpcodeParam_I + 8, // CLR_OpcodeParam_I8 + 0, // CLR_OpcodeParam_None + 8, // CLR_OpcodeParam_R + 4, // CLR_OpcodeParam_Switch + 2, // CLR_OpcodeParam_Var + 1, // CLR_OpcodeParam_ShortI + 4, // CLR_OpcodeParam_ShortR + 1, // CLR_OpcodeParam_ShortVar +}; + +const CLR_UINT8 c_CLR_opParamSizeCompressed[] = +{ + 2, // CLR_OpcodeParam_Field + 2, // CLR_OpcodeParam_Method + 2, // CLR_OpcodeParam_Type + 2, // CLR_OpcodeParam_String + 4, // CLR_OpcodeParam_Tok + 4, // CLR_OpcodeParam_Sig + 2, // CLR_OpcodeParam_BrTarget + 1, // CLR_OpcodeParam_ShortBrTarget + 4, // CLR_OpcodeParam_I + 8, // CLR_OpcodeParam_I8 + 0, // CLR_OpcodeParam_None + 8, // CLR_OpcodeParam_R + 1, // CLR_OpcodeParam_Switch + 2, // CLR_OpcodeParam_Var + 1, // CLR_OpcodeParam_ShortI + 4, // CLR_OpcodeParam_ShortR + 1, // CLR_OpcodeParam_ShortVar +}; + +CLR_UINT32 CLR_ReadTokenCompressed( const CLR_UINT8*& ip, CLR_OPCODE opcode ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + CLR_UINT32 arg; + const CLR_UINT8* ptr = ip; + + switch(c_CLR_RT_OpcodeLookup[ opcode ].m_opParam) + { + case CLR_OpcodeParam_Field : TINYCLR_READ_UNALIGNED_COMPRESSED_FIELDTOKEN ( arg, ptr ); break; + case CLR_OpcodeParam_Method: TINYCLR_READ_UNALIGNED_COMPRESSED_METHODTOKEN( arg, ptr ); break; + case CLR_OpcodeParam_Type : TINYCLR_READ_UNALIGNED_COMPRESSED_TYPETOKEN ( arg, ptr ); break; + case CLR_OpcodeParam_String: TINYCLR_READ_UNALIGNED_COMPRESSED_STRINGTOKEN( arg, ptr ); break; + case CLR_OpcodeParam_Tok : + case CLR_OpcodeParam_Sig : TINYCLR_READ_UNALIGNED_UINT32 ( arg, ptr ); break; + default : arg = 0; break; + } + + ip = ptr; + + return arg; +} + +// +// SkipBodyOfOpcode skips past the opcode argument & returns the address of the +// next instruction in the instruction stream. Note that this is +// not necessarily the next instruction which will be executed. +// +// ip -> address of argument for the opcode specified in +// the instruction stream. Note that this is not an +// instruction boundary, it is past the opcode. +// +const CLR_UINT8* CLR_SkipBodyOfOpcode( const CLR_UINT8* ip, CLR_OPCODE opcode ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + CLR_OpcodeParam opParam = c_CLR_RT_OpcodeLookup[ opcode ].m_opParam; + + if(opParam == CLR_OpcodeParam_Switch) + { + CLR_UINT32 numcases; TINYCLR_READ_UNALIGNED_UINT32( numcases, ip ); + + ip += numcases * sizeof(CLR_UINT32); + } + else + { + ip += c_CLR_opParamSize[ opParam ]; + } + + return ip; +} + +const CLR_UINT8* CLR_SkipBodyOfOpcodeCompressed( const CLR_UINT8* ip, CLR_OPCODE opcode ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + CLR_OpcodeParam opParam = c_CLR_RT_OpcodeLookup[ opcode ].m_opParam; + + if(opParam == CLR_OpcodeParam_Switch) + { + CLR_UINT32 numcases; TINYCLR_READ_UNALIGNED_UINT8(numcases, ip); + + ip += numcases * sizeof(CLR_UINT16); + } + else + { + ip += c_CLR_opParamSizeCompressed[ opParam ]; + } + + return ip; +} + +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// +#define LOOKUP_ELEMENT(idx,tblName,tblNameUC) \ + const CLR_RECORD_##tblNameUC* p = Get##tblName( idx ) + +#define LOOKUP_ELEMENT_REF(idx,tblName,tblNameUC,tblName2) \ + const CLR_RECORD_##tblNameUC* p = Get##tblName( idx );\ + const CLR_RT_##tblName2##_Index* s = &m_pCrossReference_##tblName[ idx ].m_target; if(s->m_data == 0) s = NULL + +#define LOOKUP_ELEMENT_IDX(idx,tblName,tblNameUC) \ + const CLR_RECORD_##tblNameUC* p = Get##tblName( idx );\ + CLR_RT_##tblName##_Index s; s.Set( m_idx, idx ) + +#if defined(TINYCLR_TRACE_INSTRUCTIONS) + +void CLR_RT_Assembly::DumpToken( CLR_UINT32 tk ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + CLR_UINT32 idx = CLR_DataFromTk( tk ); + + switch(CLR_TypeFromTk(tk)) + { + case TBL_AssemblyRef: { LOOKUP_ELEMENT ( idx, AssemblyRef, ASSEMBLYREF ); { CLR_Debug::Printf( "[%s]" , GetString( p->name ) ); } break; } + case TBL_TypeRef : { LOOKUP_ELEMENT_REF( idx, TypeRef , TYPEREF , TypeDef ); if(s) { CLR_RT_DUMP::TYPE ( *s ); } else { CLR_Debug::Printf( "%s.%s", GetString( p->nameSpace ), GetString( p->name ) ); } break; } + case TBL_FieldRef : { LOOKUP_ELEMENT_REF( idx, FieldRef , FIELDREF , FieldDef ); if(s) { CLR_RT_DUMP::FIELD ( *s ); } else { CLR_Debug::Printf( "%s" , GetString( p->name ) ); } break; } + case TBL_MethodRef : { LOOKUP_ELEMENT_REF( idx, MethodRef , METHODREF , MethodDef); if(s) { CLR_RT_DUMP::METHOD( *s ); } else { CLR_Debug::Printf( "%s" , GetString( p->name ) ); } break; } + case TBL_TypeDef : { LOOKUP_ELEMENT_IDX( idx, TypeDef , TYPEDEF ); CLR_RT_DUMP::TYPE ( s ); break; } + case TBL_FieldDef : { LOOKUP_ELEMENT_IDX( idx, FieldDef , FIELDDEF ); CLR_RT_DUMP::FIELD ( s ); break; } + case TBL_MethodDef : { LOOKUP_ELEMENT_IDX( idx, MethodDef , METHODDEF ); CLR_RT_DUMP::METHOD( s ); break; } + case TBL_Strings : { LPCSTR p = GetString( idx ); CLR_Debug::Printf( "'%s'" , p ); break; } + + default: + CLR_Debug::Printf( "[%08x]", tk ); + } +} + +void CLR_RT_Assembly::DumpSignature( CLR_SIG sig ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + const CLR_UINT8* p = GetSignature( sig ); + CLR_UINT32 len; + + CLR_CorCallingConvention cc = (CLR_CorCallingConvention)*p++; + + switch(cc & PIMAGE_CEE_CS_CALLCONV_MASK) + { + case PIMAGE_CEE_CS_CALLCONV_FIELD: + CLR_Debug::Printf( "FIELD " ); + DumpSignature( p ); + break; + + case PIMAGE_CEE_CS_CALLCONV_LOCAL_SIG: + break; + + case PIMAGE_CEE_CS_CALLCONV_DEFAULT: + len = *p++; + + CLR_Debug::Printf( "METHOD " ); + DumpSignature( p ); + CLR_Debug::Printf( "(" ); + + while(len-- > 0) + { + CLR_Debug::Printf( " " ); + DumpSignature( p ); + if(len) CLR_Debug::Printf( "," ); + else CLR_Debug::Printf( " " ); + } + CLR_Debug::Printf( ")" ); + break; + } +} + +void CLR_RT_Assembly::DumpSignature( const CLR_UINT8*& p ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + CLR_DataType opt = CLR_UncompressElementType( p ); + + switch(opt) + { + case DATATYPE_VOID : CLR_Debug::Printf( "VOID" ); break; + case DATATYPE_BOOLEAN : CLR_Debug::Printf( "BOOLEAN" ); break; + case DATATYPE_CHAR : CLR_Debug::Printf( "CHAR" ); break; + case DATATYPE_I1 : CLR_Debug::Printf( "I1" ); break; + case DATATYPE_U1 : CLR_Debug::Printf( "U1" ); break; + case DATATYPE_I2 : CLR_Debug::Printf( "I2" ); break; + case DATATYPE_U2 : CLR_Debug::Printf( "U2" ); break; + case DATATYPE_I4 : CLR_Debug::Printf( "I4" ); break; + case DATATYPE_U4 : CLR_Debug::Printf( "U4" ); break; + case DATATYPE_I8 : CLR_Debug::Printf( "I8" ); break; + case DATATYPE_U8 : CLR_Debug::Printf( "U8" ); break; + case DATATYPE_R4 : CLR_Debug::Printf( "R4" ); break; + case DATATYPE_R8 : CLR_Debug::Printf( "R8" ); break; + case DATATYPE_STRING : CLR_Debug::Printf( "STRING" ); break; + case DATATYPE_BYREF : CLR_Debug::Printf( "BYREF " ); DumpSignature ( p ); break; + case DATATYPE_VALUETYPE : CLR_Debug::Printf( "VALUETYPE " ); DumpSignatureToken( p ); break; + case DATATYPE_CLASS : CLR_Debug::Printf( "CLASS " ); DumpSignatureToken( p ); break; + case DATATYPE_OBJECT : CLR_Debug::Printf( "OBJECT" ); break; + case DATATYPE_SZARRAY : CLR_Debug::Printf( "SZARRAY " ); DumpSignature ( p ); break; + + default : CLR_Debug::Printf( "[UNKNOWN: %08x]", opt ); break; + } + +} + +void CLR_RT_Assembly::DumpSignatureToken( const CLR_UINT8*& p ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + CLR_UINT32 tk = CLR_TkFromStream( p ); + + CLR_Debug::Printf( "[%08x]", tk ); +} + +//--// + +void CLR_RT_Assembly::DumpOpcode( CLR_RT_StackFrame* stack, CLR_PMETADATA ip ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + if(s_CLR_RT_fTrace_Instructions < c_CLR_RT_Trace_Info) return; + + CLR_RT_MethodDef_Instance inst; + + if(s_CLR_RT_fTrace_Instructions >= c_CLR_RT_Trace_Verbose) + { + inst = stack->m_call; + } + else + { + inst.Clear(); + } + + DumpOpcodeDirect( inst, ip, stack->m_IPstart, stack->m_owningThread->m_pid ); +} + +void CLR_RT_Assembly::DumpOpcodeDirect( CLR_RT_MethodDef_Instance& call, CLR_PMETADATA ip, CLR_PMETADATA ipStart, int pid ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + CLR_Debug::Printf( " [%04x:%04x:%08x", pid, (int)(ip - ipStart), (size_t)ip ); + + if(TINYCLR_INDEX_IS_VALID(call)) + { + CLR_Debug::Printf( ":" ); + CLR_RT_DUMP::METHOD( call ); + } + + CLR_OPCODE op = CLR_ReadNextOpcodeCompressed( ip ); + CLR_OpcodeParam opParam = c_CLR_RT_OpcodeLookup[ op ].m_opParam; + + CLR_Debug::Printf( "] %-12s", c_CLR_RT_OpcodeLookup[ op ].m_name ); + + if(IsOpParamToken( opParam )) + { + DumpToken( CLR_ReadTokenCompressed( ip, op ) ); + } + else + { + CLR_UINT32 argLo; + CLR_UINT32 argHi; + + switch(c_CLR_opParamSizeCompressed[ opParam ]) + { + case 8: TINYCLR_READ_UNALIGNED_UINT32( argLo, ip ); TINYCLR_READ_UNALIGNED_UINT32( argHi, ip ); CLR_Debug::Printf( "%08X,%08X", argHi, argLo ); break; + case 4: TINYCLR_READ_UNALIGNED_UINT32( argLo, ip ); CLR_Debug::Printf( "%08X" , argLo ); break; + case 2: TINYCLR_READ_UNALIGNED_UINT16( argLo, ip ); CLR_Debug::Printf( "%04X" , argLo ); break; + case 1: TINYCLR_READ_UNALIGNED_UINT8 ( argLo, ip ); CLR_Debug::Printf( "%02X" , argLo ); break; + } + } + + CLR_Debug::Printf( "\r\n" ); +} + +#endif // defined(TINYCLR_TRACE_INSTRUCTIONS) + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(TINYCLR_TRACE_ERRORS) + +void CLR_RT_DUMP::TYPE( const CLR_RT_TypeDef_Index& cls ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + char rgBuffer[ 512 ]; + LPSTR szBuffer = rgBuffer; + size_t iBuffer = MAXSTRLEN(rgBuffer); + + g_CLR_RT_TypeSystem.BuildTypeName( cls, szBuffer, iBuffer ); rgBuffer[ MAXSTRLEN(rgBuffer) ] = 0; + + CLR_Debug::Printf( "%s", rgBuffer ); +} + +void CLR_RT_DUMP::TYPE( const CLR_RT_ReflectionDef_Index& reflex ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + CLR_RT_TypeDef_Instance inst; + CLR_UINT32 levels; + + if(inst.InitializeFromReflection( reflex, &levels )) + { + CLR_RT_DUMP::TYPE( inst ); + + while(levels-- > 0) + { + CLR_Debug::Printf( "[]" ); + } + } +} + +void CLR_RT_DUMP::METHOD( const CLR_RT_MethodDef_Index& method ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + char rgBuffer[ 512 ]; + LPSTR szBuffer = rgBuffer; + size_t iBuffer = MAXSTRLEN(rgBuffer); + + g_CLR_RT_TypeSystem.BuildMethodName( method, szBuffer, iBuffer ); + + CLR_Debug::Printf( "%s", rgBuffer ); +} + +void CLR_RT_DUMP::FIELD( const CLR_RT_FieldDef_Index& field ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + char rgBuffer[ 512 ]; + LPSTR szBuffer = rgBuffer; + size_t iBuffer = MAXSTRLEN(rgBuffer); + + g_CLR_RT_TypeSystem.BuildFieldName( field, szBuffer, iBuffer ); + + CLR_Debug::Printf( "%s", rgBuffer ); +} + +void CLR_RT_DUMP::OBJECT( CLR_RT_HeapBlock* ptr, LPCSTR text ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +#define PELEMENT_TO_STRING(elem) case DATATYPE_##elem: CLR_Debug::Printf( "%s", #elem ); break + + CLR_Debug::Printf( "%s - ", text ); + + while(ptr->DataType() == DATATYPE_OBJECT && ptr->Dereference()) + { + ptr = ptr->Dereference(); + + CLR_Debug::Printf( "PTR " ); + } + + CLR_Debug::Printf( "%04x blocks at %08x [%02x] ", ptr->DataSize(), (int)(size_t)ptr, ptr->DataType() ); + + switch(ptr->DataType()) + { + case DATATYPE_CLASS: + case DATATYPE_VALUETYPE: + { + CLR_RT_DUMP::TYPE( ptr->ObjectCls() ); + } + break; + + case DATATYPE_STRING: + { + CLR_Debug::Printf( "'%s'", ptr->StringText() ); + } + break; + + case DATATYPE_SZARRAY: + { + CLR_RT_HeapBlock_Array* array = (CLR_RT_HeapBlock_Array*)ptr; + + CLR_RT_DUMP::TYPE( array->ReflectionData() ); + } + break; + + case DATATYPE_DELEGATE_HEAD: + { + CLR_RT_HeapBlock_Delegate* dlg = (CLR_RT_HeapBlock_Delegate*)ptr; + + CLR_RT_DUMP::METHOD( dlg->DelegateFtn() ); + } + break; + + + PELEMENT_TO_STRING(BOOLEAN); + PELEMENT_TO_STRING(CHAR ); + PELEMENT_TO_STRING(I1 ); + PELEMENT_TO_STRING(U1 ); + PELEMENT_TO_STRING(I2 ); + PELEMENT_TO_STRING(U2 ); + PELEMENT_TO_STRING(I4 ); + PELEMENT_TO_STRING(U4 ); + PELEMENT_TO_STRING(I8 ); + PELEMENT_TO_STRING(U8 ); + PELEMENT_TO_STRING(R4 ); + PELEMENT_TO_STRING(R8 ); + + PELEMENT_TO_STRING(FREEBLOCK ); + PELEMENT_TO_STRING(CACHEDBLOCK ); + PELEMENT_TO_STRING(ASSEMBLY ); + PELEMENT_TO_STRING(WEAKCLASS ); + PELEMENT_TO_STRING(REFLECTION ); + PELEMENT_TO_STRING(ARRAY_BYREF ); + PELEMENT_TO_STRING(DELEGATELIST_HEAD ); + PELEMENT_TO_STRING(OBJECT_TO_EVENT ); + PELEMENT_TO_STRING(BINARY_BLOB_HEAD ); + + PELEMENT_TO_STRING(THREAD ); + PELEMENT_TO_STRING(SUBTHREAD ); + PELEMENT_TO_STRING(STACK_FRAME ); + PELEMENT_TO_STRING(TIMER_HEAD ); + PELEMENT_TO_STRING(LOCK_HEAD ); + PELEMENT_TO_STRING(LOCK_OWNER_HEAD ); + PELEMENT_TO_STRING(LOCK_REQUEST_HEAD ); + PELEMENT_TO_STRING(WAIT_FOR_OBJECT_HEAD ); + PELEMENT_TO_STRING(FINALIZER_HEAD ); + PELEMENT_TO_STRING(MEMORY_STREAM_HEAD ); + PELEMENT_TO_STRING(MEMORY_STREAM_DATA ); + + } + + CLR_Debug::Printf( "\r\n" ); + +#undef PELEMENT_TO_STRING +} + +#endif // defined(TINYCLR_TRACE_ERRORS) + +//--// + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(TINYCLR_TRACE_EXCEPTIONS) + +void CLR_RT_DUMP::EXCEPTION( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock& ref ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + LPCSTR msg; + + CLR_RT_HeapBlock* obj = Library_corlib_native_System_Exception::GetTarget( ref ); if(!obj) return; + + CLR_Debug::Printf( " #### Exception " ); CLR_RT_DUMP::TYPE( obj->ObjectCls() ); CLR_Debug::Printf( " - %s (%d) ####\r\n", CLR_RT_DUMP::GETERRORMESSAGE( Library_corlib_native_System_Exception::GetHResult( obj ) ), stack.m_owningThread->m_pid ); + + msg = Library_corlib_native_System_Exception::GetMessage( obj ); + + CLR_Debug::Printf( " #### Message: %s\r\n", msg == NULL ? "" : msg ); + + CLR_UINT32 depth; + Library_corlib_native_System_Exception::StackTrace* stackTrace = Library_corlib_native_System_Exception::GetStackTrace( obj, depth ); if(!stackTrace) return; + + while(depth-- > 0) + { + CLR_Debug::Printf( " #### " ); CLR_RT_DUMP::METHOD( stackTrace->m_md ); CLR_Debug::Printf( " [IP: %04x] ####\r\n", stackTrace->m_IP ); + + stackTrace++; + } +} + +void CLR_RT_DUMP::POST_PROCESS_EXCEPTION( CLR_RT_HeapBlock& ref ) +{ + // socket exceptions have an extra field (ErrorCode), so lets display that as well + if (CLR_RT_ExecutionEngine::IsInstanceOf( ref, g_CLR_RT_WellKnownTypes.m_SocketException )) + { + CLR_RT_HeapBlock* obj = ref.Dereference(); + if(obj != NULL) + { + // UNDONE: FIXME: CLR_INT32 errorCode = obj[ Library_system_sockets_System_Net_Sockets_SocketException::FIELD___errorCode ].NumericByRef().s4; + // UNDONE: FIXME: CLR_Debug::Printf( " #### SocketException ErrorCode = %d\r\n", errorCode ); + } + } + else if(CLR_RT_ExecutionEngine::IsInstanceOf( ref, g_CLR_RT_WellKnownTypes.m_CryptoException )) + { + CLR_RT_HeapBlock* obj = ref.Dereference(); + if(obj != NULL) + { + // m_errorCode field + CLR_INT32 errorCode = obj[5].NumericByRef().s4; + CLR_Debug::Printf( " #### CryptoException ErrorCode = %d\r\n", errorCode ); + } + } +} + +LPCSTR CLR_RT_DUMP::GETERRORMESSAGE( HRESULT hrError ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +#define CASE_HRESULT_TO_STRING(hr) case hr: return #hr + switch(hrError) + { + CASE_HRESULT_TO_STRING(CLR_E_UNKNOWN_INSTRUCTION); + CASE_HRESULT_TO_STRING(CLR_E_UNSUPPORTED_INSTRUCTION); + CASE_HRESULT_TO_STRING(CLR_E_STACK_OVERFLOW); + CASE_HRESULT_TO_STRING(CLR_E_STACK_UNDERFLOW); + CASE_HRESULT_TO_STRING(CLR_E_ENTRY_NOT_FOUND); + CASE_HRESULT_TO_STRING(CLR_E_ASSM_WRONG_CHECKSUM); + CASE_HRESULT_TO_STRING(CLR_E_ASSM_PATCHING_NOT_SUPPORTED); + CASE_HRESULT_TO_STRING(CLR_E_SHUTTING_DOWN); + CASE_HRESULT_TO_STRING(CLR_E_OBJECT_DISPOSED); + CASE_HRESULT_TO_STRING(CLR_E_WATCHDOG_TIMEOUT); + CASE_HRESULT_TO_STRING(CLR_E_NULL_REFERENCE); + CASE_HRESULT_TO_STRING(CLR_E_WRONG_TYPE); + CASE_HRESULT_TO_STRING(CLR_E_TYPE_UNAVAILABLE); + CASE_HRESULT_TO_STRING(CLR_E_INVALID_CAST); + CASE_HRESULT_TO_STRING(CLR_E_OUT_OF_RANGE); + CASE_HRESULT_TO_STRING(CLR_E_SERIALIZATION_VIOLATION); + CASE_HRESULT_TO_STRING(CLR_E_SERIALIZATION_BADSTREAM); + CASE_HRESULT_TO_STRING(CLR_E_DIVIDE_BY_ZERO); + CASE_HRESULT_TO_STRING(CLR_E_BUSY); + CASE_HRESULT_TO_STRING(CLR_E_PROCESS_EXCEPTION); + CASE_HRESULT_TO_STRING(CLR_E_THREAD_WAITING); + CASE_HRESULT_TO_STRING(CLR_E_LOCK_SYNCHRONIZATION_EXCEPTION); + CASE_HRESULT_TO_STRING(CLR_E_APPDOMAIN_EXITED); + CASE_HRESULT_TO_STRING(CLR_E_APPDOMAIN_MARSHAL_EXCEPTION); + CASE_HRESULT_TO_STRING(CLR_E_UNKNOWN_TYPE); + CASE_HRESULT_TO_STRING(CLR_E_ARGUMENT_NULL); + CASE_HRESULT_TO_STRING(CLR_E_IO); + CASE_HRESULT_TO_STRING(CLR_E_ENTRYPOINT_NOT_FOUND); + CASE_HRESULT_TO_STRING(CLR_E_DRIVER_NOT_REGISTERED); + CASE_HRESULT_TO_STRING(CLR_E_PIN_UNAVAILABLE); + CASE_HRESULT_TO_STRING(CLR_E_PIN_DEAD); + CASE_HRESULT_TO_STRING(CLR_E_INVALID_OPERATION); + CASE_HRESULT_TO_STRING(CLR_E_WRONG_INTERRUPT_TYPE); + CASE_HRESULT_TO_STRING(CLR_E_NO_INTERRUPT); + CASE_HRESULT_TO_STRING(CLR_E_DISPATCHER_ACTIVE); + CASE_HRESULT_TO_STRING(CLR_E_FILE_IO); + CASE_HRESULT_TO_STRING(CLR_E_INVALID_DRIVER); + CASE_HRESULT_TO_STRING(CLR_E_FILE_NOT_FOUND); + CASE_HRESULT_TO_STRING(CLR_E_DIRECTORY_NOT_FOUND); + CASE_HRESULT_TO_STRING(CLR_E_VOLUME_NOT_FOUND); + CASE_HRESULT_TO_STRING(CLR_E_PATH_TOO_LONG); + CASE_HRESULT_TO_STRING(CLR_E_DIRECTORY_NOT_EMPTY); + CASE_HRESULT_TO_STRING(CLR_E_UNAUTHORIZED_ACCESS); + CASE_HRESULT_TO_STRING(CLR_E_PATH_ALREADY_EXISTS); + CASE_HRESULT_TO_STRING(CLR_E_TOO_MANY_OPEN_HANDLES); + CASE_HRESULT_TO_STRING(CLR_E_NOT_SUPPORTED); + CASE_HRESULT_TO_STRING(CLR_E_RESCHEDULE); + CASE_HRESULT_TO_STRING(CLR_E_OUT_OF_MEMORY); + CASE_HRESULT_TO_STRING(CLR_E_RESTART_EXECUTION); + CASE_HRESULT_TO_STRING(CLR_E_TIMEOUT); + CASE_HRESULT_TO_STRING(CLR_E_FAIL); + //--// + CASE_HRESULT_TO_STRING(CLR_S_THREAD_EXITED); + CASE_HRESULT_TO_STRING(CLR_S_QUANTUM_EXPIRED); + CASE_HRESULT_TO_STRING(CLR_S_NO_READY_THREADS); + CASE_HRESULT_TO_STRING(CLR_S_NO_THREADS); + CASE_HRESULT_TO_STRING(CLR_S_RESTART_EXECUTION); + } +#undef CASE_HRESULT_TO_STRING + + static char s_tmp[ 32 ]; + + hal_snprintf( s_tmp, MAXSTRLEN(s_tmp), "0x%08x", hrError ); + + return s_tmp; +} + +#endif // defined(TINYCLR_TRACE_EXCEPTIONS) + +//--// + diff --git a/src/CLR/Diagnostics/Profile.cpp b/src/CLR/Diagnostics/Profile.cpp new file mode 100644 index 0000000000..4faa074460 --- /dev/null +++ b/src/CLR/Diagnostics/Profile.cpp @@ -0,0 +1,268 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Diagnostics.h" + +//--// + +#if defined(TINYCLR_PROFILE_NEW_CALLS) + +void* CLR_PROF_CounterCallChain::Prepare( CLR_PROF_Handler* handler ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + if(m_owningHandler) + { + CLR_UINT64 t = handler->GetFrozenTime() - m_owningHandler->m_time_start; + + Complete( t, m_owningHandler ); + + handler->m_target_Mode = CLR_PROF_Handler::c_Mode_Ignore; + + return NULL; + } + else + { + m_owningHandler = handler; + + handler->m_target_Mode = CLR_PROF_Handler::c_Mode_CallChain; + + return this; + } +} + +void CLR_PROF_CounterCallChain::Complete( CLR_UINT64& t, CLR_PROF_Handler* handler ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + if(m_owningHandler) + { + m_time_exclusive += t; + + m_owningHandler->m_target = NULL; + m_owningHandler = NULL; + } +} + +void CLR_PROF_CounterCallChain::Enter( CLR_RT_StackFrame* stack ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + CLR_PROF_Handler::SuspendTime(); + + TINYCLR_CLEAR(*this); + + m_owningStackFrame = stack; + + CLR_PROF_Handler::ResumeTime(); +} + +void CLR_PROF_CounterCallChain::Leave() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + CLR_PROF_Handler::SuspendTime(); + CLR_PROF_Handler::ResumeTime(); +} + +#endif + +//--// + +#if defined(TINYCLR_PROFILE_HANDLER) + + bool CLR_PROF_Handler::s_initialized; + CLR_PROF_Handler* CLR_PROF_Handler::s_current; +volatile CLR_UINT64 CLR_PROF_Handler::s_time_overhead; +volatile CLR_UINT64 CLR_PROF_Handler::s_time_freeze; +volatile CLR_UINT64 CLR_PROF_Handler::s_time_adjusted; + +//--// + + +// TODO: roll this entire function into the HAL so that +// hardware with a HighRes counter can be used, this +// implementation is easy enough to move to the HAL as +// a support function for systems with only a lowres +// counter +static CLR_UINT64 GetPerformanceCounter() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +#if defined(_WIN32) + return 0; // UNDONE: FIXME: return HAL_Windows_GetPerformanceTicks(); +#else + static CLR_UINT32 rollover = 0; + static CLR_UINT32 lastValue = 0; + + CLR_UINT32 value = ::Time_PerformanceCounter(); + + if(lastValue > value) rollover++; + + lastValue = value; + + return ((CLR_UINT64)rollover << 32) | (CLR_UINT64)value; +#endif +} + +//--// + +void CLR_PROF_Handler::Constructor() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + SuspendTime(); + + m_target_Mode = c_Mode_Ignore; + + Init( NULL ); +} + +#if defined(TINYCLR_PROFILE_NEW_CALLS) +void CLR_PROF_Handler::Constructor( CLR_PROF_CounterCallChain& target ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + SuspendTime(); + + Init( target.Prepare( this ) ); +} +#endif + +void CLR_PROF_Handler::Destructor() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + SuspendTime(); + + CLR_UINT64 t = GetFrozenTime() - m_time_start; + + if(m_target_Mode == c_Mode_Ignore) + { + s_time_adjusted += t; + } + else + { + if(m_containing) + { + m_containing->m_time_correction += t; + } + + if(m_target) + { + switch(m_target_Mode) + { +#if defined(TINYCLR_PROFILE_NEW_CALLS) + case c_Mode_CallChain: ((CLR_PROF_CounterCallChain*)m_target)->Complete( t, this ); break; +#endif + } + } + } + + s_current = m_containing; + + ResumeTime(); +} + + +void CLR_PROF_Handler::Init( void* target ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + m_target = target; + m_containing = s_current; s_current = this; + + if(m_target) + { + if(m_containing && m_containing->m_target == NULL) + { + m_target = NULL; + } + } + + if(m_target == NULL) + { + m_target_Mode = c_Mode_Ignore; + } + + m_time_correction = 0; + m_time_start = ResumeTime(); +} + +static void TestCalibrate( CLR_PROF_CounterCallChain& cnt ) +{ + CLR_PROF_Handler c( cnt ); +} + +void CLR_PROF_Handler::Calibrate() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); +#if defined(PLATFORM_ARM) + const int c_training = 10; +#else + const int c_training = 1024; +#endif + + if(s_initialized) return; + + s_current = NULL; + s_time_overhead = 0; + s_time_freeze = 0; + s_time_adjusted = 0; + +#if defined(PLATFORM_ARM) + ::Time_PerformanceCounter_Initialize(); +#endif + + int i; + CLR_PROF_CounterCallChain tmp; + + for(i=0; i 100 && i > c_training/2) + { + i--; + continue; + } + + s_time_overhead += diff; + } + + s_time_adjusted = GetPerformanceCounter(); + + s_initialized = true; +} + +void CLR_PROF_Handler::SuspendTime() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + s_time_freeze = GetPerformanceCounter(); +} + +CLR_UINT64 CLR_PROF_Handler::GetFrozenTime() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return s_time_freeze - s_time_adjusted; +} + +CLR_UINT64 CLR_PROF_Handler::ResumeTime() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + CLR_UINT64 res = GetFrozenTime(); + + s_time_adjusted = (GetPerformanceCounter() - res) + s_time_overhead; + + return res; +} + +CLR_UINT64 CLR_PROF_Handler::ResumeTime( CLR_INT64 t ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + s_time_adjusted += t; + + return ResumeTime(); +} +#endif //defined(TINYCLR_PROFILE_HANDLER) + +//--// + diff --git a/src/CLR/Diagnostics/Profiler.cpp b/src/CLR/Diagnostics/Profiler.cpp new file mode 100644 index 0000000000..7a1e5e16f9 --- /dev/null +++ b/src/CLR/Diagnostics/Profiler.cpp @@ -0,0 +1,874 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "Diagnostics.h" + +#if defined(TINYCLR_PROFILE_NEW) + +CLR_PRF_Profiler g_CLR_PRF_Profiler; + +HRESULT CLR_PRF_Profiler::CreateInstance() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + TINYCLR_HEADER(); + + g_CLR_PRF_Profiler.m_packetSeqId = 0; + g_CLR_PRF_Profiler.m_stream = NULL; + g_CLR_PRF_Profiler.m_lastTimestamp = (CLR_UINT32)((CLR_UINT64)(Time_GetMachineTime() + ((1ull << CLR_PRF_CMDS::Bits::TimestampShift) - 1)) + >> CLR_PRF_CMDS::Bits::TimestampShift); + g_CLR_PRF_Profiler.m_currentAssembly = 0; + g_CLR_PRF_Profiler.m_currentThreadPID = 0; + TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_MemoryStream::CreateInstance(g_CLR_PRF_Profiler.m_stream, NULL, 0)); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_PRF_Profiler::DeleteInstance() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + return g_CLR_PRF_Profiler.Profiler_Cleanup(); +} + +HRESULT CLR_PRF_Profiler::Profiler_Cleanup() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + CLR_RT_HeapBlock_MemoryStream::DeleteInstance(m_stream); + return S_OK; +} + +void CLR_PRF_Profiler::SendMemoryLayout() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + //Send Memory Layout + m_stream->WriteBits( CLR_PRF_CMDS::c_Profiling_Memory_Layout, CLR_PRF_CMDS::Bits::CommandHeader ); + PackAndWriteBits( 0 ); + PackAndWriteBits(s_CLR_RT_Heap.m_size); + Stream_Send(); +} + +HRESULT CLR_PRF_Profiler::DumpHeap() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + TINYCLR_HEADER(); + + CLR_PROF_HANDLER_CALLCHAIN_VOID(perf); + + CLR_UINT32 heapSize = 0; + + if(CLR_EE_PRF_IS_NOT(Enabled)) { TINYCLR_SET_AND_LEAVE(S_OK); } + + { + //Send HeapDump Begin Marker + m_stream->WriteBits( CLR_PRF_CMDS::c_Profiling_HeapDump_Start, CLR_PRF_CMDS::Bits::CommandHeader ); + TINYCLR_CHECK_HRESULT(Stream_Send()); + } + + DumpRoots(); + + TINYCLR_FOREACH_NODE(CLR_RT_HeapCluster,hc,g_CLR_RT_ExecutionEngine.m_heap) + { + CLR_RT_HeapBlock_Node* ptr; + CLR_UINT32 size; + CLR_RT_HeapBlock_Node* end = hc->m_payloadEnd; + + for(ptr = hc->m_payloadStart, size = ptr->DataSize(); ptr < end; ptr+= size, size = ptr->DataSize()) + { + if(ptr->DataType() != DATATYPE_FREEBLOCK && ptr->DataType() != DATATYPE_CACHEDBLOCK) + { + heapSize += ptr->DataSize(); + } + DumpObject(ptr); + //Don't let the stream get too big. + TINYCLR_CHECK_HRESULT(Stream_Send()); + } + } + TINYCLR_FOREACH_NODE_END(); + + { + //Send HeapDump End Marker + m_stream->WriteBits( CLR_PRF_CMDS::c_Profiling_HeapDump_Stop, CLR_PRF_CMDS::Bits::CommandHeader ); + PackAndWriteBits( heapSize ); + TINYCLR_CHECK_HRESULT(Stream_Send()); + } + + TINYCLR_CLEANUP(); + + //Flush out all data we've collected. Stopping the device without informing the program is a bad idea. + Stream_Flush(); + + TINYCLR_CLEANUP_END(); +} + +HRESULT CLR_PRF_Profiler::DumpRoots() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + TINYCLR_HEADER(); + + //Root proto: + //8bits: CLR_PRF_CMDS::c_Profiling_HeapDump_Root + //32bits: Address of Root + //3bits: Source of Root: Finalizer, AppDomain, Assembly, Thread, Stack? + //Only when source is Stack??: 32bits: CLR_RT_MethodDef_Index + + //Iterate through all the finalizers + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_Finalizer,fin,g_CLR_RT_ExecutionEngine.m_finalizersPending) + { + _ASSERTE(fin->m_object); + _ASSERTE(fin->m_object->DataType() != DATATYPE_FREEBLOCK); + _ASSERTE(fin->m_object->DataType() != DATATYPE_CACHEDBLOCK); + + DumpRoot(fin->m_object, CLR_PRF_CMDS::RootTypes::Root_Finalizer, 0, NULL); + } + TINYCLR_FOREACH_NODE_END(); + + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_Finalizer,fin,g_CLR_RT_ExecutionEngine.m_finalizersAlive) + { + _ASSERTE(fin->m_object); + _ASSERTE(fin->m_object->DataType() != DATATYPE_FREEBLOCK); + _ASSERTE(fin->m_object->DataType() != DATATYPE_CACHEDBLOCK); + + DumpRoot(fin->m_object, CLR_PRF_CMDS::RootTypes::Root_Finalizer, 0, NULL); + } + TINYCLR_FOREACH_NODE_END(); + +#if defined(TINYCLR_APPDOMAINS) + //Iterate through all the appdomains + TINYCLR_FOREACH_NODE(CLR_RT_AppDomain,appDomain,g_CLR_RT_ExecutionEngine.m_appDomains) + { + DumpRoot(appDomain, CLR_PRF_CMDS::RootTypes::Root_AppDomain, 0, NULL); + } + TINYCLR_FOREACH_NODE_END(); +#endif + + //Iterate through all the assemblies. + TINYCLR_FOREACH_ASSEMBLY(g_CLR_RT_TypeSystem) + { + DumpRoot( pASSM, CLR_PRF_CMDS::RootTypes::Root_Assembly, 0, NULL ); + } + TINYCLR_FOREACH_ASSEMBLY_END(); + + { //Iterate through all threads. + CLR_RT_DblLinkedList* threadLists[ 2 ] = { &g_CLR_RT_ExecutionEngine.m_threadsReady, &g_CLR_RT_ExecutionEngine.m_threadsWaiting }; + for(int list = 0; list < 2; list++) + { + TINYCLR_FOREACH_NODE(CLR_RT_Thread,th,*threadLists[ list ]) + { + DumpRoot( th, CLR_PRF_CMDS::RootTypes::Root_Thread, 0, NULL ); + } + TINYCLR_FOREACH_NODE_END(); + } + } + + TINYCLR_CHECK_HRESULT(Stream_Send()); + + TINYCLR_NOCLEANUP(); +} + +void CLR_PRF_Profiler::DumpRoot( CLR_RT_HeapBlock* root, CLR_UINT32 type, CLR_UINT32 flags, CLR_RT_MethodDef_Index* source ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + m_stream->WriteBits( CLR_PRF_CMDS::c_Profiling_HeapDump_Root, CLR_PRF_CMDS::Bits::CommandHeader ); + DumpPointer( root ); + m_stream->WriteBits( type, CLR_PRF_CMDS::Bits::RootTypes ); + + _ASSERTE(!flags); + if(type == CLR_PRF_CMDS::RootTypes::Root_Stack) + { + PackAndWriteBits(*source); + } else { + _ASSERTE(source == NULL); + } +} + +void CLR_PRF_Profiler::DumpObject( CLR_RT_HeapBlock* ptr ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + //Object Proto: + // Free blocked and cached blocks are considered free memory and are not dumped. + // All other types: + // 8 bits - Profiling_HeapDump_Object + // 32 bit pointer + // 16 bit size + // 8 bit - DataType() const + // 32 bits are TypeDef info >>>> iff DataType == CLASSTYPE || DataType == VALUETYPE || DataType == SZARRAY <<<< + // 16 bits are Array Level info >>>> iff DataType == SZARRAY <<<< + // 1 bit - Reference Follows + // 0 - No more references. End of Packet + // 1 - 32-bit pointer to reference follows. Repeat. + + CLR_DataType dt = ptr->DataType(); + _ASSERTE(dt < DATATYPE_FIRST_INVALID); + _ASSERTE(sizeof(CLR_RT_HeapBlock) == 12); //HeapBlockObjectPacket in ProfilerPackets.cs assumes sizeof(CLR_RT_HeapBlock) == 12 + + if(dt != DATATYPE_FREEBLOCK && dt != DATATYPE_CACHEDBLOCK) + { + m_stream->WriteBits( CLR_PRF_CMDS::c_Profiling_HeapDump_Object, CLR_PRF_CMDS::Bits::CommandHeader ); + DumpPointer( ptr ); + PackAndWriteBits( ptr->DataSize() ); + m_stream->WriteBits( (CLR_UINT32)dt,CLR_PRF_CMDS::Bits::DataType ); + + switch(dt) + { + case DATATYPE_BOOLEAN: + case DATATYPE_I1: + case DATATYPE_U1: + case DATATYPE_CHAR: + case DATATYPE_I2: + case DATATYPE_U2: + case DATATYPE_I4: + case DATATYPE_U4: + case DATATYPE_R4: + case DATATYPE_I8: + case DATATYPE_U8: + case DATATYPE_R8: + case DATATYPE_DATETIME: + case DATATYPE_TIMESPAN: + case DATATYPE_STRING: + //Boxed primitives.. All are non-pointer types -- no references. + case DATATYPE_REFLECTION: + //Has a reference to an assembly, but it's unlikely to be the only thing keeping the assembly alive. + case DATATYPE_BINARY_BLOB_HEAD: + //Unknown/unmanaged data-type. No references. + case DATATYPE_SUBTHREAD: + //Owned by a DATATYPE_THREAD; Don't dump back-reference. + case DATATYPE_MEMORY_STREAM_DATA: + //No references at all -- usually, and when not, its a pointer to an externally shown character buffer used for deserialization. + case DATATYPE_IO_PORT: + //No references for normal GPIO; there is a structure for interrupts, but that doesn't seem to be stored on the managed heap. + case DATATYPE_TIMER_HEAD: + case DATATYPE_LOCK_OWNER_HEAD: + case DATATYPE_LOCK_REQUEST_HEAD: + case DATATYPE_SERIALIZER_DUPLICATE: + case DATATYPE_SERIALIZER_STATE: + //No unique forward-looking references. + break; + + case DATATYPE_OBJECT: + case DATATYPE_BYREF: + case DATATYPE_ARRAY_BYREF: +#if defined(TINYCLR_APPDOMAINS) + case DATATYPE_TRANSPARENT_PROXY: +#endif + { + DumpSingleReference( ptr ); + break; + } + + case DATATYPE_CLASS: + case DATATYPE_VALUETYPE: + { + CLR_RT_TypeDef_Index idx = ptr->ObjectCls(); + _ASSERTE(TINYCLR_INDEX_IS_VALID(idx)); + PackAndWriteBits( idx ); + DumpSingleReference( ptr->ObjectLock() ); + DumpListOfReferences( ptr + 1, ptr->DataSize() - 1 ); //All items in list should have DataSize() == 1 therefore ptr->DataSize() - 1 == number of items in list. + break; + } + + case DATATYPE_SZARRAY: + { + //Special case needed to dump out array data type and levels. + CLR_RT_HeapBlock_Array* array = (CLR_RT_HeapBlock_Array*)ptr; + + PackAndWriteBits( array->ReflectionDataConst().m_data.m_type ); + PackAndWriteBits( array->ReflectionDataConst().m_levels ); + + if(array->m_fReference) + { + DumpListOfReferences( (CLR_RT_HeapBlock*)array->GetFirstElement(), array->m_numOfElements ); + } + break; + } + + case DATATYPE_ASSEMBLY: + { + CLR_RT_Assembly* assembly = (CLR_RT_Assembly*)ptr; + DumpSingleReference( assembly->m_pFile ); +#if !defined(TINYCLR_APPDOMAINS) + DumpListOfReferences( assembly->m_pStaticFields, assembly->m_iStaticFields ); +#endif + break; + } + + case DATATYPE_WEAKCLASS: + { + CLR_RT_HeapBlock_WeakReference* wr = (CLR_RT_HeapBlock_WeakReference*)ptr; + DumpSingleReference( wr->m_targetDirect ); + break; + } + + case DATATYPE_DELEGATE_HEAD: + { + CLR_RT_HeapBlock_Delegate* dlg = (CLR_RT_HeapBlock_Delegate*)ptr; + DumpSingleReference( &dlg->m_object ); + break; + } + + case DATATYPE_DELEGATELIST_HEAD: + { + CLR_RT_HeapBlock_Delegate_List* dlgList = (CLR_RT_HeapBlock_Delegate_List*)ptr; + DumpListOfReferences( dlgList->GetDelegates(), dlgList->m_length ); + break; + } + + case DATATYPE_THREAD: + { + CLR_RT_Thread* th = (CLR_RT_Thread*)ptr; + + DumpSingleReference( th->m_dlg ); + DumpSingleReference( th->m_currentException.Dereference() ); + + for(int i=0; im_nestedExceptionsPos; i++) + { + CLR_RT_HeapBlock* except = th->m_nestedExceptions[ i ].m_exception; + _ASSERTE(!except || except->DataType() == DATATYPE_CLASS || except->DataType() == DATATYPE_OBJECT); + DumpSingleReference( except ); + } + + DumpListOfReferences( th->m_locks); + DumpSingleReference ( th->m_waitForObject ); + DumpListOfReferences( th->m_stackFrames ); + DumpListOfReferences( th->m_subThreads ); + break; + } + + case DATATYPE_STACK_FRAME: + { + CLR_RT_StackFrame* stack = (CLR_RT_StackFrame*)ptr; + DumpListOfReferences( stack->m_arguments, stack->m_call.m_target->numArgs ); + DumpListOfReferences( stack->m_locals , stack->m_call.m_target->numLocals ); + DumpListOfReferences( stack->m_evalStack, stack->TopValuePosition() ); + break; + } + + case DATATYPE_OBJECT_TO_EVENT: + { + CLR_RT_ObjectToEvent_Source* otes = (CLR_RT_ObjectToEvent_Source*)ptr; + DumpSingleReference( otes->m_eventPtr ); //The managed object should reference this obj, which references the event. + break; + } + + case DATATYPE_LOCK_HEAD: + { + //Object points to Lock Head, Thread points to Lock Head, Lock Head points to list of lock owners and requests + CLR_RT_HeapBlock_Lock* lock = (CLR_RT_HeapBlock_Lock*)ptr; + DumpListOfReferences( lock->m_owners ); + DumpListOfReferences( lock->m_requests ); + break; + } + + case DATATYPE_ENDPOINT_HEAD: + { + CLR_RT_HeapBlock_EndPoint* ep = (CLR_RT_HeapBlock_EndPoint*)ptr; + DumpListOfReferences( ep->m_messages ); + break; + } + + case DATATYPE_WAIT_FOR_OBJECT_HEAD: + { + CLR_RT_HeapBlock_WaitForObject* wfo = (CLR_RT_HeapBlock_WaitForObject*)ptr; + DumpListOfReferences(wfo->GetWaitForObjects(), wfo->m_cObjects); + break; + } + + case DATATYPE_FINALIZER_HEAD: + { + CLR_RT_HeapBlock_Finalizer* f = (CLR_RT_HeapBlock_Finalizer*)ptr; + DumpSingleReference( f->m_object ); + break; + } + + case DATATYPE_MEMORY_STREAM_HEAD: + { + CLR_RT_HeapBlock_MemoryStream* ms = (CLR_RT_HeapBlock_MemoryStream*)ptr; + DumpListOfReferences( ms->m_buffers ); + break; + } + + case DATATYPE_SERIALIZER_HEAD: + { + CLR_RT_BinaryFormatter* bf = (CLR_RT_BinaryFormatter*)ptr; + DumpSingleReference ( bf->m_stream ); + DumpListOfReferences( bf->m_duplicates ); + DumpListOfReferences( bf->m_states ); + break; + } + + // UNDONE: case DATATYPE_I2C_XACTION: + // { + // CLR_RT_HeapBlock_I2CXAction* ixa = (CLR_RT_HeapBlock_I2CXAction*)ptr; + // size_t index; + + // //These are unmanaged pointers; we need to get the pointer to the BinaryBlob via + // if(ixa->m_HalXAction) { DumpSingleReference( CLR_RT_HeapBlock_BinaryBlob::GetBlob( ixa->m_HalXAction ) ); } + // if(ixa->m_dataBuffers) { DumpSingleReference( CLR_RT_HeapBlock_BinaryBlob::GetBlob( ixa->m_dataBuffers ) ); } + // if(ixa->m_HalXActionUnits) { DumpSingleReference( CLR_RT_HeapBlock_BinaryBlob::GetBlob( ixa->m_HalXActionUnits ) ); } + // for(index = 0; index < ixa->m_xActionUnits; ++index) + // { + // DumpSingleReference( CLR_RT_HeapBlock_BinaryBlob::GetBlob( ixa->m_HalXActionUnits[ index ] ) ); + // } + // break; + // } + + +#if defined(TINYCLR_APPDOMAINS) + case DATATYPE_APPDOMAIN_HEAD: + { + CLR_RT_AppDomain* appDomain = (CLR_RT_AppDomain*)ptr; + DumpListOfReferences( appDomain->m_appDomainAssemblies ); + DumpSingleReference ( appDomain->m_globalLock ); + DumpSingleReference ( appDomain->m_strName ); + DumpSingleReference ( appDomain->m_outOfMemoryException ); + break; + } + + case DATATYPE_APPDOMAIN_ASSEMBLY: + { + CLR_RT_AppDomainAssembly* appDomainAssembly = (CLR_RT_AppDomainAssembly*)ptr; + DumpListOfReferences( appDomainAssembly->m_pStaticFields, appDomainAssembly->m_assembly->m_iStaticFields ); + break; + } +#endif + + default: + _ASSERTE(false); + break; + } + DumpEndOfRefsList(); + } //if(dt != DATATYPE_FREEBLOCK && dt != DATATYPE_CACHEDBLOCK) +} + +CLR_RT_HeapBlock* CLR_PRF_Profiler::FindReferencedObject(CLR_RT_HeapBlock* ref) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + while(ref) + { + CLR_DataType dt = ref->DataType(); + switch(dt) + { + case DATATYPE_BYREF: + case DATATYPE_OBJECT: + ref = ref->Dereference(); + break; +#if defined(TINYCLR_APPDOMAINS) + case DATATYPE_TRANSPARENT_PROXY: + ref = ref->TransparentProxyDereference(); + break; +#endif + case DATATYPE_ARRAY_BYREF: + ref = ref->Array(); + default: + return ref; + } + } + return NULL; +} + +void CLR_PRF_Profiler::DumpEndOfRefsList() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + SendFalse(); +} + +void CLR_PRF_Profiler::DumpPointer(void* ptr) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + PackAndWriteBits( (CLR_UINT32)((CLR_UINT8*)ptr - s_CLR_RT_Heap.m_location) ); +} + +void CLR_PRF_Profiler::DumpSingleReference(CLR_RT_HeapBlock* ptr) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + ptr = FindReferencedObject(ptr); + if(ptr) + { + SendTrue(); + DumpPointer(ptr); + } +} + +void CLR_PRF_Profiler::DumpListOfReferences(CLR_RT_HeapBlock* firstItem, CLR_UINT16 count) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + CLR_RT_HeapBlock* ptr; + for(ptr = firstItem; count > 0; ptr += ptr->DataSize(), count--) + { + DumpSingleReference(ptr); + } +} + +void CLR_PRF_Profiler::DumpListOfReferences(CLR_RT_DblLinkedList& list) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_Node, ptr, list) + { + DumpSingleReference(ptr); + } + TINYCLR_FOREACH_NODE_END(); +} + +//--// + +void CLR_PRF_Profiler::Timestamp() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + //Send Profiling Timestamp + CLR_UINT32 time = (CLR_UINT32)((Time_GetMachineTime() + ((CLR_UINT64)((1ull << CLR_PRF_CMDS::Bits::TimestampShift) - 1))) + >> CLR_PRF_CMDS::Bits::TimestampShift); + if(time > m_lastTimestamp) + { + m_stream->WriteBits(CLR_PRF_CMDS::c_Profiling_Timestamp, CLR_PRF_CMDS::Bits::CommandHeader); + PackAndWriteBits(time - m_lastTimestamp); + Stream_Send(); + m_lastTimestamp = time; + } +} + +//--// + +#if defined(TINYCLR_PROFILE_NEW_CALLS) +HRESULT CLR_PRF_Profiler::RecordContextSwitch(CLR_RT_Thread* nextThread) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + TINYCLR_HEADER(); + _ASSERTE(nextThread); + + CLR_PROF_HANDLER_CALLCHAIN_VOID(perf); + + if(CLR_EE_PRF_IS(Calls)) + { + Timestamp(); + m_stream->WriteBits( CLR_PRF_CMDS::c_Profiling_Calls_CtxSwitch, CLR_PRF_CMDS::Bits::CommandHeader ); + PackAndWriteBits( nextThread->m_pid ); + m_currentThreadPID = nextThread->m_pid; + TINYCLR_CHECK_HRESULT(Stream_Send()); + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_PRF_Profiler::RecordFunctionCall(CLR_RT_Thread* th, CLR_RT_MethodDef_Index md) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + TINYCLR_HEADER(); + _ASSERTE(th); + + if(CLR_EE_PRF_IS(Calls)) + { + CLR_PROF_HANDLER_CALLCHAIN_VOID(perf); + + if(th->m_pid != m_currentThreadPID) + { + TINYCLR_CHECK_HRESULT(RecordContextSwitch( th )); + } + else + { + Timestamp(); + } + + _ASSERTE(th->m_pid == m_currentThreadPID); + + m_stream->WriteBits(CLR_PRF_CMDS::c_Profiling_Calls_Call, CLR_PRF_CMDS::Bits::CommandHeader); + + if(md.Assembly() == m_currentAssembly) + { + SendFalse(); + } + else + { + SendTrue(); + m_currentAssembly = md.Assembly(); + PackAndWriteBits(m_currentAssembly); + } + PackAndWriteBits(md.Method()); + TINYCLR_CHECK_HRESULT(Stream_Send()); + } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_PRF_Profiler::RecordFunctionReturn(CLR_RT_Thread* th, CLR_PROF_CounterCallChain& prof) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + TINYCLR_HEADER(); + _ASSERTE(th); + + if(CLR_EE_PRF_IS(Calls)) + { + CLR_PROF_HANDLER_CALLCHAIN_VOID(perf); + + if(th->m_pid != m_currentThreadPID) + { + TINYCLR_CHECK_HRESULT(RecordContextSwitch( th )); + } + else + { + Timestamp(); + } + + _ASSERTE(th->m_pid == m_currentThreadPID); + + m_stream->WriteBits(CLR_PRF_CMDS::c_Profiling_Calls_Return, CLR_PRF_CMDS::Bits::CommandHeader); + PackAndWriteBits((CLR_UINT32)(prof.m_time_exclusive >> CLR_PRF_CMDS::Bits::CallTimingShift)); + TINYCLR_CHECK_HRESULT(Stream_Send()); + } + + TINYCLR_NOCLEANUP(); +} +#endif + +//--// + +#if defined(TINYCLR_PROFILE_NEW_ALLOCATIONS) + +void CLR_PRF_Profiler::TrackObjectCreation( CLR_RT_HeapBlock* ptr ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + _ASSERTE(ptr); + if(CLR_EE_PRF_IS(Allocations)) + { + CLR_PROF_HANDLER_CALLCHAIN_VOID(perf); + + CLR_UINT8 dt = ptr->DataType(); + if(dt != DATATYPE_STACK_FRAME && dt != DATATYPE_BINARY_BLOB_HEAD) + { + Timestamp(); + m_stream->WriteBits( CLR_PRF_CMDS::c_Profiling_Allocs_Alloc, CLR_PRF_CMDS::Bits::CommandHeader ); + DumpPointer( ptr ); + PackAndWriteBits( ptr->DataSize() ); + m_stream->WriteBits( (CLR_UINT32)dt, CLR_PRF_CMDS::Bits::DataType ); + if(dt == DATATYPE_CLASS || dt == DATATYPE_VALUETYPE) + { + PackAndWriteBits( ptr->ObjectCls() ); + } + else if(dt == DATATYPE_SZARRAY) + { + CLR_RT_HeapBlock_Array* array = (CLR_RT_HeapBlock_Array*)ptr; + PackAndWriteBits( array->ReflectionDataConst().m_data.m_type ); + PackAndWriteBits( array->ReflectionDataConst().m_levels ); + } + Stream_Send(); + } + } +} + +void CLR_PRF_Profiler::TrackObjectDeletion( CLR_RT_HeapBlock* ptr ) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + _ASSERTE(ptr); + + if(CLR_EE_PRF_IS(Allocations)) + { + CLR_PROF_HANDLER_CALLCHAIN_VOID(perf); + + CLR_UINT8 dt = ptr->DataType(); + if(dt != DATATYPE_STACK_FRAME && dt != DATATYPE_CACHEDBLOCK ) + { + Timestamp(); + m_stream->WriteBits( CLR_PRF_CMDS::c_Profiling_Allocs_Delete, CLR_PRF_CMDS::Bits::CommandHeader ); + DumpPointer( ptr ); + Stream_Send(); + } + } +} + +void CLR_PRF_Profiler::TrackObjectRelocation() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + if(CLR_EE_PRF_IS(Allocations)) + { + CLR_PROF_HANDLER_CALLCHAIN_VOID(perf); + + CLR_RT_GarbageCollector::RelocationRegion* relocBlocks = g_CLR_RT_GarbageCollector.m_relocBlocks; + size_t relocCount = g_CLR_RT_GarbageCollector.m_relocCount; + + Timestamp(); + m_stream->WriteBits(CLR_PRF_CMDS::c_Profiling_Allocs_Relloc, CLR_PRF_CMDS::Bits::CommandHeader); + PackAndWriteBits(( CLR_UINT32)relocCount ); + + for(size_t i = 0; i < relocCount; i++) + { + DumpPointer( relocBlocks[ i ].m_start); + DumpPointer( relocBlocks[ i ].m_end ); + PackAndWriteBits( relocBlocks[i].m_offset ); + } + } +} + +void CLR_PRF_Profiler::RecordGarbageCollectionBegin() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + if(CLR_EE_PRF_IS(Allocations)) + { + CLR_PROF_HANDLER_CALLCHAIN_VOID(perf); + + Timestamp(); + m_stream->WriteBits( CLR_PRF_CMDS::c_Profiling_GarbageCollect_Begin, CLR_PRF_CMDS::Bits::CommandHeader ); + PackAndWriteBits( g_CLR_RT_GarbageCollector.m_freeBytes ); + Stream_Send(); + } +} + +void CLR_PRF_Profiler::RecordGarbageCollectionEnd() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + if(CLR_EE_PRF_IS(Allocations)) + { + CLR_PROF_HANDLER_CALLCHAIN_VOID(perf); + + Timestamp(); + m_stream->WriteBits( CLR_PRF_CMDS::c_Profiling_GarbageCollect_End, CLR_PRF_CMDS::Bits::CommandHeader ); + PackAndWriteBits( g_CLR_RT_GarbageCollector.m_freeBytes ); + Stream_Send(); + } +} + +void CLR_PRF_Profiler::RecordHeapCompactionBegin() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + if(CLR_EE_PRF_IS(Allocations)) + { + CLR_PROF_HANDLER_CALLCHAIN_VOID(perf); + + Timestamp(); + m_stream->WriteBits( CLR_PRF_CMDS::c_Profiling_HeapCompact_Begin, CLR_PRF_CMDS::Bits::CommandHeader ); + PackAndWriteBits( g_CLR_RT_GarbageCollector.m_freeBytes ); + Stream_Send(); + } +} + +void CLR_PRF_Profiler::RecordHeapCompactionEnd() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + if(CLR_EE_PRF_IS(Allocations)) + { + CLR_PROF_HANDLER_CALLCHAIN_VOID(perf); + + Timestamp(); + m_stream->WriteBits( CLR_PRF_CMDS::c_Profiling_HeapCompact_End, CLR_PRF_CMDS::Bits::CommandHeader ); + PackAndWriteBits( g_CLR_RT_GarbageCollector.m_freeBytes ); + Stream_Send(); + } +} + +#endif + +//--// + +void CLR_PRF_Profiler::SendTrue() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + m_stream->WriteBits( (CLR_UINT32)1, 1 ); +} + +void CLR_PRF_Profiler::SendFalse() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + m_stream->WriteBits( (CLR_UINT32)0, 1 ); +} + +void CLR_PRF_Profiler::PackAndWriteBits(CLR_UINT32 value) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + /* In three different scenarios tested, sending nibbles instead of bytes and 2-bit hunks resulted + * in the most efficiency over the wire. It also involves less code than 2-bit hunks that I expected to win, + * so that's the method used. + */ + _ASSERTE(sizeof(CLR_UINT32) == 4); + + const CLR_UINT32 SHIFT_PER_NIBBLE = 2; //2^2 = 4 bits per nibble + CLR_UINT32 nibbles = 1; + if( value & 0xF0000000) { nibbles = 8; } + else if(value & 0x0F000000) { nibbles = 7; } + else if(value & 0x00F00000) { nibbles = 6; } + else if(value & 0x000F0000) { nibbles = 5; } + else if(value & 0x0000F000) { nibbles = 4; } + else if(value & 0x00000F00) { nibbles = 3; } + else if(value & 0x000000F0) { nibbles = 2; } + + m_stream->WriteBits( nibbles - 1, CLR_PRF_CMDS::Bits::NibbleCount ); + m_stream->WriteBits( value, nibbles << SHIFT_PER_NIBBLE ); +} + +void CLR_PRF_Profiler::PackAndWriteBits(const CLR_RT_TypeDef_Index& typeDef) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + PackAndWriteBits( typeDef.Assembly() ); + PackAndWriteBits( typeDef.Type() ); +} + +void CLR_PRF_Profiler::PackAndWriteBits(const CLR_RT_MethodDef_Index& methodDef) +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + PackAndWriteBits( methodDef.Assembly() ); + PackAndWriteBits( methodDef.Method() ); +} + +//--// + +HRESULT CLR_PRF_Profiler::Stream_Send() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + TINYCLR_HEADER(); + + const int BUFFER_THRESHOLD_BYTES = CLR_RT_HeapBlock_MemoryStream::Buffer::c_PayloadSize * 2 / 3; + const int BUFFER_THRESHOLD_BITS = BUFFER_THRESHOLD_BYTES << 3; + + if(m_stream->BitsWritten() >= BUFFER_THRESHOLD_BITS) + { + TINYCLR_CHECK_HRESULT(Stream_Flush()); + } + //else { Stream isn't above threshold; allow to cache. } + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_PRF_Profiler::Stream_Flush() +{ + NATIVE_PROFILE_CLR_DIAGNOSTICS(); + TINYCLR_HEADER(); + + //These need to be paired; If this function is ever used to send multiple stream types, each should get their own packet sequence id. + const CLR_UINT32 messageType = CLR_DBG_Commands::c_Profiling_Stream; + + CLR_UINT8 buffer[ 2*sizeof(CLR_UINT16) + CLR_RT_HeapBlock_MemoryStream::Buffer::c_PayloadSize ]; + CLR_DBG_Commands::Profiling_Stream* packet = (CLR_DBG_Commands::Profiling_Stream*)buffer; + + TINYCLR_FOREACH_NODE(CLR_RT_HeapBlock_MemoryStream::Buffer, ptr, m_stream->m_buffers) + { + int payloadLength = ptr->m_length; + if(payloadLength > 0) + { + _ASSERTE(sizeof(ptr->m_payload) == CLR_RT_HeapBlock_MemoryStream::Buffer::c_PayloadSize); + + int bitLength = payloadLength * 8; + if(ptr == m_stream->m_current) + { + bitLength -= m_stream->m_avail; + } + + packet->m_bitLen = bitLength; + packet->m_seqId = m_packetSeqId++; + memcpy(&packet[ 1 ], ptr->m_payload, payloadLength); + + int packetLength = sizeof(CLR_DBG_Commands::Profiling_Stream) + payloadLength; + if(!CLR_EE_DBG_EVENT_SEND(messageType, packetLength, buffer, WP_Flags::c_NonCritical)) + { + _ASSERTE(FALSE); + TINYCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + } + + //Don't go past the cursor. + if(ptr == m_stream->m_current) { break; } + } + TINYCLR_FOREACH_NODE_END(); + + m_stream->Reset(); + + TINYCLR_NOCLEANUP(); +} + +#endif //#if defined(TINYCLR_PROFILE_NEW) diff --git a/src/CLR/Include/BlockStorage_decl.h b/src/CLR/Include/BlockStorage_decl.h new file mode 100644 index 0000000000..13c67a6ed9 --- /dev/null +++ b/src/CLR/Include/BlockStorage_decl.h @@ -0,0 +1,922 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _DRIVERS_PAL_BLOCKSTORAGE_H_ +#define _DRIVERS_PAL_BLOCKSTORAGE_H_ 1 + +//--// + +#if defined(__GNUC__) +#define HAL_Time_Sleep_MicroSeconds_BS(x) HAL_Time_Sleep_MicroSeconds_InRam(x) + +#else +#define HAL_Time_Sleep_MicroSeconds_BS(x) HAL_Time_Sleep_MicroSeconds(x) + +#endif + + + + +// for convert byte size to storage sector size +#define CONVERTBYTETOSECTORSIZE(x,y) ( (size_t)x + (size_t)y-1)/(size_t)y + +#define CONVERTBYTETOSECTORSIZE_2(x,y,z) ( (size_t)x + (size_t)y-1)/(size_t)z + +///////////////////////////////////////////////////////// +// Description: +// Definitions for the Block Storage device interface +// for the .NET Micro Framework +// +// Remarks: +// The general design of the API is strongly influenced +// by the Windows Embedded CE Flash Media Driver (FMD) +// API. However, It is not intended to be a direct port +// of the FMD architecture to the .NET MF. This design +// overcomes some of the limitations of the CE design +// and includes functionalty an support that is specific +// to the .NET MF. +// +// In particular this design adds the following: +// * Generalized block storage rather than assuming +// a Resident Flash Array (RFA) +// * Support for multiple instances of block storage +// devices instead of only one +// * Support for legacy CLR Block usage information to +// Identify for the system where various types of +// information reside in the storage device. +// * Support for direct use of NOR flash without forcing +// additional layering for metadata if an FS is not +// needed or desired on the NOR flash. +// * Support for XIP storage media like NOR and ROM. +// * Use of an interface (as a structure of function +// pointers) to allow layering and standardized support +// for various common functionality. (e.g. treating +// NOR flash with varying sized sectors and no metadata +// as if it was NAND with fixed sized sectors including +// metadata. Thus this kind functionality need only be +// implemented once) +// +// Terminology: +// Block Storage Device - device that stores data addressable +// as a chunk as opposed to byte or WORD level +// +// Sector - smallest unit of storage for a Block device. Data is +// read or written as a complete sector(unless the device +// supports XIP which allows byte addresssing and reading +// directly from the processor memory bus) +// +// Block - smallest eraseable unit of the storage device. A block +// contains one or more sectors that are erased as a whole. +// All sectors within a block are always the same size. +// +// Region - Group of adjacent blocks that all contain sectors of the +// same size. +// +// Execute-In-Place (XIP) - Attribute of some storage types, NOR, ROM, +// RAM, that allows direct execution of code from the device. +// XIP capable devices are at least read-only and byte addresable +// on the CPU memory bus. +// + + +///////////////////////////////////////////////////////// +// Description: +// Defines a Logical Sector Address +// +// Remarks: +// This is a typedef in case we want to support +// larger devices in the future. +// +// The Logical Sector Address is the address of a +// sector on the device independent of geometry. That is +// the address for the first sector on the device is 0, +// the next is 1 etc... crossing over any geometry +// boundaries. The exact mapping of logical sector +// addresses to a physical sector on the storage device +// is driver implementation defined. Many storage media +// types, like hard drives, have industry standard +// mappings for interoperability since file systems deal +// with logical addresses only. +// +// NOTE: +// Some systems (especially hard disks) refer to this +// as a Logical Block Address (LBA). Since the block and +// sector on a hard driver are essentially the same thing +// there is little confusion. However, with flash media +// the distinction between a block and a sector is important +// so we define the sector address to make it clear. +// +typedef UINT32 ByteAddress; +typedef UINT32 SectorAddress; + +////////////////////////////////////////////////////////// +// Description: +// Flags to Indicate the status of a particular block in +// flash. ALL sectors for a block *MUST* share the same +// status. +// +// Remarks: +// When the block is reserved the lower 16 bits specifies a +// USAGE_XXXX value to indicate the purpose of the block. +// +// The BlockRange information is technically dynamic in the +// sense that it is not fixed or defined in hardware. Rather, +// it is defined by the system designer. However, the BlockRange +// info does not and *MUST* not change at run-time. The only +// exceptions to this rule is in the boot loader where the +// storage device is being formated or re-laid out as part +// of an update etc... and when an FS discovers a bad block +// it should mark it as bad. WIthout this restriction +// implementing an FS is virtually impossible since the FS +// would have to deal with the possibility that the usage for +// a Block could change at any point in time. +// +struct BlockUsage +{ + static const UINT32 BOOTSTRAP = 0x0010; + static const UINT32 CODE = 0x0020; + static const UINT32 CONFIG = 0x0030; + static const UINT32 FILESYSTEM = 0x0040; + + static const UINT32 DEPLOYMENT = 0x0050; + + static const UINT32 UPDATE = 0x0060; + + static const UINT32 SIMPLE_A = 0x0090; + static const UINT32 SIMPLE_B = 0x00A0; + + static const UINT32 STORAGE_A = 0x00E0; + static const UINT32 STORAGE_B = 0x00F0; + + + static const UINT32 ANY = 0x0000; +}; + +struct BlockRange +{ + + // upper 4 bits of USAGE_XXXX identifies the base type of info stored in the block + // using these values it is possible to scan a device for all managed code or all + // native code without worrying about the finer details of what it's for. + +private: + static const UINT32 DATATYPE_NATIVECODE = 0x1000; // Block contains XIP system native code + static const UINT32 DATATYPE_MANAGEDCODE = 0x2000; // Block contains managed code assemblies + static const UINT32 DATATYPE_RAW = 0x4000; // Block contains raw data + + static const UINT32 ATTRIB_PRIMARY = 0x10000; // use to mark the block is used for special purpose + + + static const UINT32 EXECUTABLE = 0x80000000; + static const UINT32 RESERVED = 0x40000000; + static const UINT32 READONLY = 0x20000000; + + +public: + // Values for the Usage information (This helps map the new storage APIs to the needs of existing code) + static const UINT32 ALL_MASK = 0xFFFFFFFF; + static const UINT32 USAGE_MASK = 0x000000FF; + static const UINT32 NON_USAGE_MASK = 0xFFFFFF00; + + static const UINT32 BLOCKTYPE_RESERVED = RESERVED; + static const UINT32 BLOCKTYPE_DIRTYBIT = RESERVED | DATATYPE_RAW | BlockUsage::CONFIG; // for secondary devices to set dirtybits + static const UINT32 BLOCKTYPE_CONFIG = ATTRIB_PRIMARY | RESERVED | DATATYPE_RAW | BlockUsage::CONFIG; // Configuration data that contains all the unique data + + static const UINT32 BLOCKTYPE_BOOTSTRAP = EXECUTABLE | RESERVED | DATATYPE_NATIVECODE | BlockUsage::BOOTSTRAP; // Boot loader and boot strap code + static const UINT32 BLOCKTYPE_CODE = EXECUTABLE | RESERVED | DATATYPE_NATIVECODE | BlockUsage::CODE; // CLR or other native code "application" + static const UINT32 BLOCKTYPE_DEPLOYMENT = RESERVED | DATATYPE_MANAGEDCODE | BlockUsage::DEPLOYMENT; // Deployment area for MFdeploy & Visual Studio + static const UINT32 BLOCKTYPE_SIMPLE_A = RESERVED | DATATYPE_RAW | BlockUsage::SIMPLE_A; // Part A of Simple Storage + static const UINT32 BLOCKTYPE_SIMPLE_B = RESERVED | DATATYPE_RAW | BlockUsage::SIMPLE_B; // Part B of Simple Storage + static const UINT32 BLOCKTYPE_STORAGE_A = RESERVED | DATATYPE_RAW | BlockUsage::STORAGE_A; // Part A of EWR Storage + static const UINT32 BLOCKTYPE_STORAGE_B = RESERVED | DATATYPE_RAW | BlockUsage::STORAGE_B; // Part B of EWR Storage + static const UINT32 BLOCKTYPE_FILESYSTEM = DATATYPE_RAW | BlockUsage::FILESYSTEM; // File System + static const UINT32 BLOCKTYPE_UPDATE = RESERVED | DATATYPE_RAW | BlockUsage::UPDATE; // Used for MFUpdate for firmware/assembly/etc updates + + static BOOL IsBlockTinyBooterAgnostic( UINT32 BlockType ) + { + // The only blocks that should be distinguished by TinyBooter are CONFIG, + // Bootstrap and reserved blocks (DirtyBit is another version of CONFIG). + if( BlockType == BlockRange::BLOCKTYPE_BOOTSTRAP || + BlockType == BlockRange::BLOCKTYPE_CONFIG || + BlockType == BlockRange::BLOCKTYPE_RESERVED || + BlockType == BlockRange::BLOCKTYPE_DIRTYBIT) + { + return FALSE; + } + + return TRUE; + } + + BOOL IsReserved() const { return ((RangeType & RESERVED) == RESERVED); } + BOOL IsReadOnly() const { return ((RangeType & READONLY) == READONLY); } + + BOOL IsReservedData() const { return ((RangeType & (RESERVED | DATATYPE_RAW )) == (RESERVED | DATATYPE_RAW )); } + BOOL HasManagedCode() const { return ((RangeType & (DATATYPE_MANAGEDCODE )) == (DATATYPE_MANAGEDCODE )); } + + BOOL IsCode() const { return ((RangeType & USAGE_MASK) == BlockUsage::CODE); } + BOOL IsBootstrap() const { return ((RangeType & USAGE_MASK) == BlockUsage::BOOTSTRAP);} + BOOL IsDirtyBit() const { return ((RangeType & BLOCKTYPE_CONFIG) == BLOCKTYPE_DIRTYBIT);} + BOOL IsConfig() const { return ((RangeType & BLOCKTYPE_CONFIG) == BLOCKTYPE_CONFIG); } + BOOL IsDeployment() const { return ((RangeType & USAGE_MASK) == BlockUsage::DEPLOYMENT);} + BOOL IsFileSystem() const { return ((RangeType & USAGE_MASK) == BlockUsage::FILESYSTEM); } + UINT32 GetBlockCount() const { return (EndBlock - StartBlock + 1); } + + // NOTE: This is the application native code only (not including the managed DAT section) + // and thus is different from the old MEMORY_USAGE_CODE which contained both + // the Native code application and the DAT section. Obviously these inlines can be + // altered or added upon to test for any combination of the flags as desired but seperating + // the DAT region out on it's own allows for locating ANY managed code sections of storage + BOOL IsLegacyCode() const { return (IsCode()); } + UINT32 GetBlockUsage() const { return (RangeType & USAGE_MASK); } + + + /* + Due to the lack of a defined bit ordering for bit fields in the C/C++ + languages a bit field structure isn't actually used but this should + help clarify the layout and intent of the constant declarations below. + + //MSB + unsigned EXECUTABLE:1; + unsigned RESERVED:1; + unsigned READONLY:1; + unsigned UNUSEDBITS:13; + + // The lower 16 bits are used to define the specific + // usage for blocks when the RESERVED bit set + unsigned BlockType:4 + unsigned Usage:12; + //LSB + */ + UINT32 RangeType; + UINT32 StartBlock; + UINT32 EndBlock; +}; + +///////////////////////////////////////////////////////// +// Description: +// This structure defines characteristics of a particular +// region of a block device. +// +// Remarks: +// There is often more than one instance of this structure for each +// block device. +// +// The BytesPerBlock value is an optimization to prevent the need +// to routinely caclulate it from SectorsPerBlock * DataBytesPerSector +// +struct BlockRegionInfo +{ + UINT32 Size() const { return (NumBlocks * BytesPerBlock); } + ByteAddress BlockAddress(UINT32 blockIndex) const { return (Start + (blockIndex * BytesPerBlock)); } + UINT32 OffsetFromBlock(UINT32 Address) const { return ((Address - Start) % BytesPerBlock); } + UINT32 BlockIndexFromAddress(UINT32 Address) const { return ((Address - Start) / BytesPerBlock); } + + ByteAddress Start; // Starting Sector address + UINT32 NumBlocks; // total number of blocks in this region + UINT32 BytesPerBlock; // Total number of bytes per block + + UINT32 NumBlockRanges; + const BlockRange *BlockRanges; +}; + +///////////////////////////////////////////////////////// +// Description: +// This structure defines characteristics of a particular +// block device. +// +// Remarks: +// THere is only one instance of this structure for each +// block device. +// + +struct MediaAttribute +{ + BOOL Removable :1; + BOOL SupportsXIP:1; + BOOL WriteProtected:1; + BOOL SupportsCopyBack:1; + BOOL ErasedBitsAreZero:1; +}; + +/////////////////////////////////////////////////////////// + +struct BlockDeviceInfo +{ + // indicates if the storage media is removeable + + MediaAttribute Attribute; + + // Maximum Sector Write Time. + UINT32 MaxSectorWrite_uSec; + + // Maximum erase time for the a block + UINT32 MaxBlockErase_uSec; + + // Bytes Per Sector + UINT32 BytesPerSector; + + // Total Size + ByteAddress Size; + + // count of regions in the flash. + UINT32 NumRegions; + + // pointer to an array (NumRegions long) of region information + const BlockRegionInfo *Regions; + + SectorAddress PhysicalToSectorAddress( const BlockRegionInfo* pRegion, ByteAddress phyAddress ) const; + + BOOL FindRegionFromAddress(ByteAddress Address, UINT32 &BlockRegionIndex, UINT32 &BlockRangeIndex ) const; + + BOOL FindForBlockUsage(UINT32 BlockUsage, ByteAddress &Address, UINT32 &BlockRegionIndex, UINT32 &BlockRangeIndex ) const; + + BOOL FindNextUsageBlock(UINT32 BlockUsage, ByteAddress &Address, UINT32 &BlockRegionIndex, UINT32 &BlockRangeIndex ) const; +}; + +/////////////////////////////////////////////////////////////// +// Description: +// This structure describes the sector Metadata used for wear +// leveling. +// +// Remarks: +// This structure emulates the typical physical layout of the +// extra area of flash. The wear leveling layer for NAND and +// NOR flash supplied by Microsoft for Windows CE makes use +// of 8 bytes of the Sector Extra Info area. +// +// This information is designed to match that used in +// Windows Embedded CE systems so that the FAL algorithms from +// CE can be more easily ported to the .NET MF. +// +// The following is a typical representation of how the extra area +// is utilized: +//- - - - - - - - - - - - - - - - +//|R|R|R|R|O|V|R|R|E|E|E|E|E|E|E|E| +//- - - - - - - - - - - - - - - - +// +//The following table describes each element. +// +//Element Description +// R Reserved bytes used by the FAL +// O Byte for use by the OEM +// V Byte indicating if the block is valid (a.k.a. bad) +// E Bytes typically used for by a NAND driver for ECC +// +ADS_PACKED +struct GNU_PACKED SectorMetadata +{ + DWORD dwReserved1; // Used by the FAL to hold the logical to physical sector mapping information. + BYTE bOEMReserved; // For use by OEM. See OEMReservedBits for more information. + BYTE bBadBlock; // Indicates if a block is bad. + WORD wReserved2; // Used by the FAL to maintain state information about the sector. + + // TODO: Check ECC algorithm implementations on CE to see what data type works most conveniently for this + UINT32 ECC[2]; // Error Correction Code [Should be all 0xFF if not used] + + // Remarks: + // Any sectors that the OEM does not want the wear leveling + // code to touch should have both of these bits set. This + // includes the sectors that include the boot loader and any + // other flash data that exists at fixed locations. + // + // Note: + // Because only full blocks can be erased, all sectors within + // a block should have the same values for these flags. + // + static const BYTE OEM_BLOCK_RESERVED = 0x01; + static const BYTE OEM_BLOCK_READONLY = 0x02; +}; + +//--// + +struct BLOCK_CONFIG +{ + GPIO_FLAG WriteProtectionPin; + const BlockDeviceInfo* BlockDeviceInformation; +}; + +// UNDONE: FIXME: struct MEMORY_MAPPED_NOR_BLOCK_CONFIG +//{ +// BLOCK_CONFIG BlockConfig; +// CPU_MEMORY_CONFIG Memory; +// UINT32 ChipProtection; +// UINT32 ManufacturerCode; +// UINT32 DeviceCode; +//}; + +///////////////////////////////////////////////////////// +// Description: +// This structure defines an interface for block devices +// +// Remarks: +// It is possible a given system might have more than one +// storage device type. This interface abstracts the +// hardware sepcifics from the rest of the system. +// +// All of the functions take at least one void* parameter +// that normally points to a driver specific data structure +// containing hardware specific settings to use. This +// allows a single driver to support multiple instances of +// the same type of storage device in the system. +// +// The sector read and write functions provide a parameter +// for Sector Metadata. The metadata is used for flash arrays +// without special controllers to manage wear leveling etc... +// (mostly for directly attached NOR and NAND). The metadata +// is used by upper layers for wear leveling to ensure that +// data is moved around on the flash when writing to prevent +// failure of the device from too many erase cycles on a sector. +// +// TODO: +// Define standard method of notification that media is +// removed for all removeable media. This will likely +// be a continuation so that the FS Manager can mount +// an FS and then notify the managed app of the new FS. +// +struct IBlockStorageDevice +{ + ///////////////////////////////////////////////////////// + // Description: + // Initializes a given block device for use + // + // Input: + // + // Returns: + // true if succesful; false if not + // + // Remarks: + // No other functions in this interface may be called + // until after Init returns. + // + BOOL (*InitializeDevice)(void*); + + ///////////////////////////////////////////////////////// + // Description: + // Initializes a given block device for use + // + // Returns: + // true if succesful; false if not + // + // Remarks: + // De initializes the device when no longer needed + // + BOOL (*UninitializeDevice)(void*); + + ///////////////////////////////////////////////////////// + // Description: + // Gets the information describing the device + // + const BlockDeviceInfo* (*GetDeviceInfo)(void*); + + ///////////////////////////////////////////////////////// + // Description: + // Reads data from a set of sectors + // + // Input: + // StartSector - Starting Sector for the read + // NumSectors - Number of sectors to read + // pSectorBuff - pointer to buffer to read the data into. + // Must be large enough to hold all of the data + // being read. + // + // pSectorMetadata - pointer to an array of structured (one for each sector) + // for the extra sector information. + // + // Returns: + // true if succesful; false if not + // + // Remarks: + // This function reads the number of sectors specified from the device. + // + // pSectorBuff may be NULL. This is to allow for reading just the metadata. + // + // pSectorMetadata can be set to NULL if the caller does not need the extra + // data. + // + // If the device does not support sector Metadata it should fail if the + // pSectorMetadata parameter is not NULL. + // + BOOL (*Read)(void*, ByteAddress StartSector, UINT32 NumBytes, BYTE* pSectorBuff); + + ///////////////////////////////////////////////////////// + // Description: + // Writes data to a set of sectors + // + // Input: + // StartSector - Starting Sector for the write + // NumSectors - Number of sectors to write + // pSectorBuff - pointer to data to write. + // Must be large enough to hold complete sectors + // for the number of sectors being written. + // + // pSectorMetadata - pointer to an array of structures (one for each sector) + // for the extra sector information. + // + // Returns: + // true if succesful; false if not + // + // Remarks: + // This function reads the number of sectors specified from the device. + // The SectorMetadata is used for flash arrays without special controllers + // to manage wear leveling etc... (mostly for NOR and NAND). The metadata + // is used by upper layers to ensure that data is moved around on the flash + // when writing to prevent failure of the device from too many erase cycles + // on a sector. + // + // If the device does not support sector Metadata it should fail if the + // pSectorMetadata parameter is not NULL. + // + // pSectorMetadata can be set to NULL if the caller does not need the extra + // data. Implementations must not attempt to write data through a NULL pointer! + // + BOOL (*Write)(void*, ByteAddress Address, UINT32 NumBytes, BYTE* pSectorBuf, BOOL ReadModifyWrite); + + BOOL (*Memset)(void*, ByteAddress Address, UINT8 Data, UINT32 NumBytes); + + BOOL (*GetSectorMetadata)(void*, ByteAddress SectorStart, SectorMetadata* pSectorMetadata); + + BOOL (*SetSectorMetadata)(void*, ByteAddress SectorStart, SectorMetadata* pSectorMetadata); + + ///////////////////////////////////////////////////////// + // Description: + // Check a block is erased or not. + // + // Input: + // BlockStartAddress - Logical Sector Address + // + // Returns: + // true if it is erassed, otherwise false + // + // Remarks: + // Check the block containing the sector address specified. + // + BOOL (*IsBlockErased)(void*, ByteAddress BlockStartAddress, UINT32 BlockLength); + + ///////////////////////////////////////////////////////// + // Description: + // Erases a block + // + // Input: + // Address - Logical Sector Address + // + // Returns: + // true if succesful; false if not + // + // Remarks: + // Erases the block containing the sector address specified. + // + BOOL (*EraseBlock)(void*, ByteAddress Address); + + ///////////////////////////////////////////////////////// + // Description: + // Changes the power state of the device + // + // Input: + // State - true= power on; false = power off + // + // Remarks: + // This function allows systems to conserve power by + // shutting down the hardware when the system is + // going into low power states. + // + void (*SetPowerState)(void*, UINT32 State); + + UINT32 (*MaxSectorWrite_uSec)(void*); + + UINT32 (*MaxBlockErase_uSec)(void*); +}; + + +//////////////////////////////////////////////// +// Description: +// Binding context for a driver and the physical device +// +// Remarks: +// The design pattern here effectively mimics a C++ class +// with virtuals. The reason virtuals are not used is that +// the .NET MF supports a wide variety of compiler/Linker +// tool chains and some of them bring in a large Run-time +// library footprint when Certain C++ language features are +// used. Since a major goal of the .NET MF is to reduce +// code footprint we avoid anything that brings in additional +// library code. +// + +struct BlockStorageDevice : public HAL_DblLinkedNode +{ + +public: + + ///////////////////////////////////////////////////////// + // Description: + // Initializes a given block device for use + // + // Returns: + // true if succesful; false if not + // + // Remarks: + // No other functions in this interface may be called + // until after Init returns. + // + BOOL InitializeDevice() { return this->m_BSD->InitializeDevice( this->m_context ); } + + ///////////////////////////////////////////////////////// + // Description: + // Initializes a given block device for use + // + // Returns: + // true if succesful; false if not + // + // Remarks: + // De initializes the device when no longer needed + // + BOOL UninitializeDevice() { return this->m_BSD->UninitializeDevice( this->m_context ); } + + ///////////////////////////////////////////////////////// + // Description: + // Gets the information describing the device + // + const BlockDeviceInfo* GetDeviceInfo() { return this->m_BSD->GetDeviceInfo( this->m_context ); } + + ///////////////////////////////////////////////////////// + // Description: + // Reads data from a set of sectors + // + // Input: + // StartSector - Starting Sector for the read + // NumSectors - Number of sectors to read + // pSectorBuff - pointer to buffer to read the data into. + // Must be large enough to hold all of the data + // being read. + // + // pSectorMetadata - pointer to an array of structured (one for each sector) + // for the extra sector information. + // + // Returns: + // true if succesful; false if not + // + // Remarks: + // This function reads the number of sectors specified from the device. + // + // pSectorBuff may be NULL. This is to allow for reading just the metadata. + // + // pSectorMetadata can be set to NULL if the caller does not need the extra + // data. + // + // If the device does not support sector Metadata it should fail if the + // pSectorMetadata parameter is not NULL. + // + BOOL Read(ByteAddress Address, UINT32 NumBytes, BYTE* pSectorBuff) + { + return this->m_BSD->Read(this->m_context, Address, NumBytes, pSectorBuff); + } + + ///////////////////////////////////////////////////////// + // Description: + // Writes data to a set of sectors + // + // Input: + // StartSector - Starting Sector for the write + // NumSectors - Number of sectors to write + // pSectorBuff - pointer to data to write. + // Must be large enough to hold complete sectors + // for the number of sectors being written. + // + // pSectorMetadata - pointer to an array of structures (one for each sector) + // for the extra sector information. + // + // Returns: + // true if succesful; false if not + // + // Remarks: + // This function reads the number of sectors specified from the device. + // The SectorMetadata is used for flash arrays without special controllers + // to manage wear leveling etc... (mostly for NOR and NAND). The metadata + // is used by upper layers to ensure that data is moved around on the flash + // when writing to prevent failure of the device from too many erase cycles + // on a sector. + // + // If the device does not support sector Metadata it should fail if the + // pSectorMetadata parameter is not NULL. + // + // pSectorMetadata can be set to NULL if the caller does not need the extra + // data. Implementations must not attempt to write data through a NULL pointer! + // + BOOL Write(ByteAddress Address, UINT32 NumBytes, BYTE* pSectorBuf, BOOL ReadModifyWrite) + { + return this->m_BSD->Write(this->m_context, Address, NumBytes, pSectorBuf, ReadModifyWrite); + } + + BOOL Memset(ByteAddress Address, UINT8 Data, UINT32 NumBytes) + { + return this->m_BSD->Memset(this->m_context, Address, Data, NumBytes); + } + + BOOL GetSectorMetadata(ByteAddress SectorStart, SectorMetadata* pSectorMetadata) + { + return this->m_BSD->GetSectorMetadata(this->m_context, SectorStart, pSectorMetadata); + } + + BOOL SetSectorMetadata(ByteAddress SectorStart, SectorMetadata* pSectorMetadata) + { + return this->m_BSD->SetSectorMetadata(this->m_context, SectorStart, pSectorMetadata); + } + + ///////////////////////////////////////////////////////// + // Description: + // Check a block is erased or not + // + // Input: + // Address - Logical Sector Address + // + // Returns: + // true it is erased; false if not + // + // Remarks: + // check the block containing the sector address specified. + // + BOOL IsBlockErased(ByteAddress BlockStartAddress, UINT32 BlockLength) { return this->m_BSD->IsBlockErased(this->m_context, BlockStartAddress, BlockLength); } + + + ///////////////////////////////////////////////////////// + // Description: + // Erases a block + // + // Input: + // Address - Logical Sector Address + // + // Returns: + // true if succesful; false if not + // + // Remarks: + // Erases the block containing the sector address specified. + // + BOOL EraseBlock(ByteAddress Address) const { return this->m_BSD->EraseBlock(this->m_context, Address); } + + + ///////////////////////////////////////////////////////// + // Description: + // Changes the power state of the device + // + // Input: + // State - true= power on; false = power off + // + // Remarks: + // This function allows systems to conserve power by + // shutting down the hardware when the system is + // going into low power states. + // + void SetPowerState( UINT32 State ) { this->m_BSD->SetPowerState(this->m_context, State); } + + BOOL FindRegionFromAddress(ByteAddress Address, UINT32 &BlockRegionIndex, UINT32 &BlockRangeIndex ) + { + const BlockDeviceInfo* pDevInfo = GetDeviceInfo(); + + return pDevInfo->FindRegionFromAddress( Address, BlockRegionIndex, BlockRangeIndex ); + } + + BOOL FindForBlockUsage(UINT32 blockUsage, ByteAddress &Address, UINT32 &BlockRegionIndex, UINT32 &BlockRangeIndex ) + { + const BlockDeviceInfo* pDevInfo = GetDeviceInfo(); + + return pDevInfo->FindForBlockUsage( blockUsage, Address, BlockRegionIndex, BlockRangeIndex ); + } + + BOOL FindNextUsageBlock(UINT32 blockUsage, ByteAddress &Address, UINT32 &BlockRegionIndex, UINT32 &BlockRangeIndex ) + { + const BlockDeviceInfo* pDevInfo = GetDeviceInfo(); + + return pDevInfo->FindNextUsageBlock( blockUsage, Address, BlockRegionIndex, BlockRangeIndex ); + } + + + UINT32 MaxSectorWrite_uSec() + { + return this->m_BSD->MaxSectorWrite_uSec(this->m_context); + } + + UINT32 MaxBlockErase_uSec() + { + return this->m_BSD->MaxBlockErase_uSec(this->m_context); + } + + IBlockStorageDevice* m_BSD; // Vtable for this device + void* m_context; // configuration for this instance of this driver + +}; + + +struct BlockStorageStream +{ + static const INT32 STREAM_SEEK_NEXT_BLOCK = 0x7FFFFFFF; + static const INT32 STREAM_SEEK_PREV_BLOCK = 0x7FFFFFFE; + + static const UINT32 c_BlockStorageStream__XIP = 0x00000001; + static const UINT32 c_BlockStorageStream__ReadModWrite = 0x00000002; + + enum SeekOrigin + { + SeekBegin = 0, + SeekCurrent = 1, + SeekEnd = 2, + }; + + + //--// + + ByteAddress BaseAddress; + UINT32 CurrentIndex; + UINT32 Length; + UINT32 BlockLength; + UINT32 Usage; + UINT32 RegionIndex; + UINT32 RangeIndex; + UINT32 Flags; + UINT32 CurrentUsage; + BlockStorageDevice *Device; + + //--// + + BOOL IsXIP() { return 0 != (Flags & c_BlockStorageStream__XIP); } + BOOL IsReadModifyWrite() { return 0 != (Flags & c_BlockStorageStream__ReadModWrite); } + void SetReadModifyWrite(){ Flags |= c_BlockStorageStream__ReadModWrite; } + + BOOL Initialize(UINT32 blockUsage); + BOOL Initialize(UINT32 blockUsage, BlockStorageDevice* pDevice); + BOOL NextStream(); + BOOL PrevStream(); + BOOL Seek( INT32 offset, SeekOrigin origin = SeekCurrent ); + BOOL Write( UINT8* data , UINT32 length ); + BOOL Erase( UINT32 length ); + BOOL ReadIntoBuffer( UINT8* pBuffer, UINT32 length ); + BOOL Read( UINT8** ppBuffer, UINT32 length ); + UINT32 CurrentAddress(); + BOOL IsErased( UINT32 length ); +}; + +// -- global List + +struct BlockStorageList +{ + // initailize the storage + static void Initialize(); + + // walk through list of devices and calls Init() function + static BOOL InitializeDevices(); + + // walk through list of devices and calls UnInit() function + static BOOL UnInitializeDevices(); + + // add pBSD to the list + // If Init=true, the Init() will be called. + static BOOL AddDevice( BlockStorageDevice* pBSD, IBlockStorageDevice* vtable, void* config, BOOL Init); + + // remove pBSD from the list + // Uninit = true, UnInit() will be called. + static BOOL RemoveDevice( BlockStorageDevice* pBSD, BOOL UnInit); + + // Find the right Device with the corresponding phyiscal address. + // + static BOOL FindDeviceForPhysicalAddress( BlockStorageDevice** pBSD, UINT32 PhysicalAddress, ByteAddress &BlockAddress); + + static BlockStorageDevice* GetFirstDevice(); + + static BlockStorageDevice* GetNextDevice( BlockStorageDevice& device ); + + // returns number of devices has been declared in the system + static UINT32 GetNumDevices(); + + // pointer to the BlockStorageDevice which is the primary device with CONFIG block + static BlockStorageDevice* s_primaryDevice; + +private: + // global pointer of all the storage devices + static HAL_DblLinkedList s_deviceList; + + static BOOL s_Initialized; +}; + +//////////////////////////////////////////////////////////////////////////////// + +// functions to included all the devices to be added in the system +void BlockStorage_AddDevices(); + +/////////////////////////////////////////////////////////////////////////////// + +#define FLASH_PROTECTION_KEY 0x1055AADD + + + +#define FLASH_BEGIN_PROGRAMMING_FAST() { GLOBAL_LOCK(FlashIrq) +#define FLASH_BEGIN_PROGRAMMING(x) { UINT32 FlashOperationStatus = Flash_StartOperation( x ) +#define FLASH_SLEEP_IF_INTERRUPTS_ENABLED(u) if(!FlashOperationStatus) { Events_WaitForEventsInternal( 0, u/1000 ); } +#define FLASH_END_PROGRAMMING(banner,address) Flash_EndOperation( FlashOperationStatus ); } +#define FLASH_END_PROGRAMMING_FAST(banner,address) } + + +//--// + +#endif // #if define _DRIVERS_PAL_BLOCKSTORAGE_H_ + diff --git a/src/CLR/Include/TinyCLR_Application.h b/src/CLR/Include/TinyCLR_Application.h new file mode 100644 index 0000000000..c344e6a424 --- /dev/null +++ b/src/CLR/Include/TinyCLR_Application.h @@ -0,0 +1,20 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _TINYCLR_APPLICATION_H_ +#define _TINYCLR_APPLICATION_H_ + +struct CLR_SETTINGS +{ + unsigned short MaxContextSwitches; + bool WaitForDebugger; + bool EnterDebuggerLoopAfterExit; +}; + +extern void ClrStartup(CLR_SETTINGS params); + +extern void ClrExit(); + +#endif diff --git a/src/CLR/Include/TinyCLR_Checks.h b/src/CLR/Include/TinyCLR_Checks.h new file mode 100644 index 0000000000..dcf0e6f427 --- /dev/null +++ b/src/CLR/Include/TinyCLR_Checks.h @@ -0,0 +1,57 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _TINYCLR_CHECKS_H_ +#define _TINYCLR_CHECKS_H_ + +#include + +struct CLR_RT_DUMP +{ +#undef DECL_POSTFIX +#if defined(TINYCLR_TRACE_ERRORS) +#define DECL_POSTFIX +#else +#define DECL_POSTFIX {} +#endif + + static void TYPE ( const CLR_RT_TypeDef_Index& cls ) DECL_POSTFIX; + static void TYPE ( const CLR_RT_ReflectionDef_Index& reflex ) DECL_POSTFIX; + static void METHOD( const CLR_RT_MethodDef_Index& method ) DECL_POSTFIX; + static void FIELD ( const CLR_RT_FieldDef_Index& field ) DECL_POSTFIX; + static void OBJECT( CLR_RT_HeapBlock* ptr , LPCSTR text ) DECL_POSTFIX; + + //--// + +#undef DECL_POSTFIX +#if defined(TINYCLR_TRACE_EXCEPTIONS) +#define DECL_POSTFIX +#else +#define DECL_POSTFIX {} +#endif + static void EXCEPTION ( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock& ref ) DECL_POSTFIX; + static void POST_PROCESS_EXCEPTION( CLR_RT_HeapBlock& ref ) DECL_POSTFIX; + + static LPCSTR GETERRORMESSAGE( HRESULT hrError ); +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +struct CLR_Checks +{ + static HRESULT VerifyStackOK( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock* top, int num ) { return S_OK; } + + static HRESULT VerifyObject ( CLR_RT_HeapBlock& top ); + + static HRESULT VerifyArrayReference ( CLR_RT_HeapBlock& ref ); + + static HRESULT VerifyUnknownInstruction ( CLR_OPCODE op ); + static HRESULT VerifyUnsupportedInstruction( CLR_OPCODE op ); +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#endif // _TINYCLR_CHECKS_H_ + diff --git a/src/CLR/Include/TinyCLR_Debugging.h b/src/CLR/Include/TinyCLR_Debugging.h new file mode 100644 index 0000000000..5223f59204 --- /dev/null +++ b/src/CLR/Include/TinyCLR_Debugging.h @@ -0,0 +1,1174 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _TINYCLR_DEBUGGING_H_ +#define _TINYCLR_DEBUGGING_H_ + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if NUM_DEBUGGERS > 1 + #define TINYCLR_FOREACH_DEBUGGER(ptr) \ + for(int iDebuggerT = 0; iDebuggerT < NUM_DEBUGGERS; iDebuggerT++) \ + { \ + CLR_DBG_Debugger& ptr = g_CLR_DBG_Debuggers[ iDebuggerT ]; + +#define TINYCLR_FOREACH_DEBUGGER_NO_TEMP() \ + for(int iDebuggerT = 0; iDebuggerT < NUM_DEBUGGERS; iDebuggerT++) \ + { +#else + #define TINYCLR_FOREACH_DEBUGGER(ptr) \ + { \ + CLR_DBG_Debugger& ptr = g_CLR_DBG_Debuggers[ 0 ]; + + #define TINYCLR_FOREACH_DEBUGGER_NO_TEMP() \ + { +#endif + +#define TINYCLR_FOREACH_DEBUGGER_END() \ + } + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +struct CLR_DBG_Commands +{ + static const UINT32 c_Monitor_Ping = 0x00000000; // The payload is empty, this command is used to let the other side know we are here... + static const UINT32 c_Monitor_Message = 0x00000001; // The payload is composed of the string characters, no zero at the end. + static const UINT32 c_Monitor_ReadMemory = 0x00000002; + static const UINT32 c_Monitor_WriteMemory = 0x00000003; + static const UINT32 c_Monitor_CheckMemory = 0x00000004; + static const UINT32 c_Monitor_EraseMemory = 0x00000005; + static const UINT32 c_Monitor_Execute = 0x00000006; + static const UINT32 c_Monitor_Reboot = 0x00000007; + static const UINT32 c_Monitor_MemoryMap = 0x00000008; + static const UINT32 c_Monitor_ProgramExit = 0x00000009; // The payload is empty, this command is used to tell the PC of a program termination + static const UINT32 c_Monitor_CheckSignature = 0x0000000A; + static const UINT32 c_Monitor_DeploymentMap = 0x0000000B; + static const UINT32 c_Monitor_FlashSectorMap = 0x0000000C; + static const UINT32 c_Monitor_SignatureKeyUpdate = 0x0000000D; + static const UINT32 c_Monitor_OemInfo = 0x0000000E; + + //--// + + struct Monitor_Ping + { + static const UINT32 c_Ping_Source_TinyCLR = 0x00000000; + static const UINT32 c_Ping_Source_TinyBooter = 0x00000001; + static const UINT32 c_Ping_Source_Host = 0x00000002; + + static const UINT32 c_Ping_DbgFlag_Stop = 0x00000001; + static const UINT32 c_Ping_DbgFlag_BigEndian = 0x02000002; + static const UINT32 c_Ping_DbgFlag_AppExit = 0x00000004; + + UINT32 m_source; + UINT32 m_dbg_flags; + + struct Reply + { + UINT32 m_source; + UINT32 m_dbg_flags; + }; + }; + + struct Monitor_OemInfo + { + struct Reply + { + MfReleaseInfo m_releaseInfo; + }; + }; + + struct Monitor_Reboot + { + static const UINT32 c_NormalReboot = 0; + static const UINT32 c_EnterBootloader = 1; + static const UINT32 c_ClrRebootOnly = 2; + static const UINT32 c_ClrStopDebugger = 4; + + UINT32 m_flags; + }; + + struct Monitor_ReadMemory + { + UINT32 m_address; + UINT32 m_length; + + struct Reply + { + UINT8 m_data[ 1 ]; + }; + }; + + struct Monitor_WriteMemory + { + UINT32 m_address; + UINT32 m_length; + UINT8 m_data[ 1 ]; + }; + + struct Monitor_Signature + { + UINT32 m_keyIndex; + UINT32 m_length; + UINT8 m_signature[ 1 ]; + }; + + struct Monitor_CheckMemory + { + UINT32 m_address; + UINT32 m_length; + + struct Reply + { + UINT32 m_crc; + }; + }; + + struct Monitor_EraseMemory + { + UINT32 m_address; + UINT32 m_length; + }; + + struct Monitor_Execute + { + UINT32 m_address; + }; + + struct Monitor_MemoryMap + { + static const UINT32 c_RAM = 0x00000001; + static const UINT32 c_FLASH = 0x00000002; + + struct Range + { + UINT32 m_address; + UINT32 m_length; + UINT32 m_flags; + }; + + Range m_map[ 1 ]; + }; + + + struct Monitor_DeploymentMap + { + static const CLR_UINT32 c_CRC_Erased_Sentinel = 0x0; + + struct FlashSector + { + CLR_UINT32 m_start; + CLR_UINT32 m_length; + + CLR_UINT32 m_crc; + }; + + struct Reply + { + + FlashSector m_data[ 1 ]; + }; + }; + + + + + struct Monitor_SignatureKeyUpdate + { + UINT32 m_keyIndex; + UINT8 m_newKeySignature[ 128 ]; + UINT8 m_newKey[ 260 ]; + UINT32 m_reserveLength; + UINT8 m_reserveData[ 1 ]; + }; + + //--------------------------------------------------------------// + + static const UINT32 c_Debugging_Execution_BasePtr = 0x00020000; // Returns the pointer for the ExecutionEngine object. + static const UINT32 c_Debugging_Execution_ChangeConditions = 0x00020001; // Sets/resets the state of the debugger. + static const UINT32 c_Debugging_Execution_SecurityKey = 0x00020002; // Sets security key. + static const UINT32 c_Debugging_Execution_Unlock = 0x00020003; // Unlock the low-level command, for mfg. test programs. + static const UINT32 c_Debugging_Execution_Allocate = 0x00020004; // Permanently allocate some memory. + static const UINT32 c_Debugging_Execution_Breakpoints = 0x00020005; // Sets breakpoints. + static const UINT32 c_Debugging_Execution_BreakpointHit = 0x00020006; // Notification that a breakpoint was hit. + static const UINT32 c_Debugging_Execution_BreakpointStatus = 0x00020007; // Queries last breakpoint hit. + static const UINT32 c_Debugging_Execution_QueryCLRCapabilities = 0x00020008; // Queries capabilities of the CLR. + static const UINT32 c_Debugging_Execution_SetCurrentAppDomain = 0x00020009; // Sets the current AppDomain. This is required before + // performing certain debugging operations, such as + // accessing a static field, or doing function evaluation, + + static const UINT32 c_Debugging_Thread_Create = 0x00020010; // OBSOLETE - Use c_Debugging_Thread_CreateEx instead. + static const UINT32 c_Debugging_Thread_List = 0x00020011; // Lists the active/waiting threads. + static const UINT32 c_Debugging_Thread_Stack = 0x00020012; // Lists the call stack for a thread. + static const UINT32 c_Debugging_Thread_Kill = 0x00020013; // Kills a thread. + static const UINT32 c_Debugging_Thread_Suspend = 0x00020014; // Suspends the execution of a thread. + static const UINT32 c_Debugging_Thread_Resume = 0x00020015; // Resumes the execution of a thread. + static const UINT32 c_Debugging_Thread_GetException = 0x00020016; // Gets the current exception. + static const UINT32 c_Debugging_Thread_Unwind = 0x00020017; // Unwinds to given stack frame. + static const UINT32 c_Debugging_Thread_CreateEx = 0x00020018; // Creates a new thread but Thread.CurrentThread will return the identity of the passed thread. + static const UINT32 c_Debugging_Thread_Get = 0x00021000; // Gets the current thread. + + static const UINT32 c_Debugging_Stack_Info = 0x00020020; // Gets more info on a stack frame. + static const UINT32 c_Debugging_Stack_SetIP = 0x00020021; // Sets the IP on a given thread. + + static const UINT32 c_Debugging_Value_ResizeScratchPad = 0x00020030; // Resizes the scratchpad area. + static const UINT32 c_Debugging_Value_GetStack = 0x00020031; // Reads a value from the stack frame. + static const UINT32 c_Debugging_Value_GetField = 0x00020032; // Reads a value from an object's field. + static const UINT32 c_Debugging_Value_GetArray = 0x00020033; // Reads a value from an array's element. + static const UINT32 c_Debugging_Value_GetBlock = 0x00020034; // Reads a value from a heap block. + static const UINT32 c_Debugging_Value_GetScratchPad = 0x00020035; // Reads a value from the scratchpad area. + static const UINT32 c_Debugging_Value_SetBlock = 0x00020036; // Writes a value to a heap block. + static const UINT32 c_Debugging_Value_SetArray = 0x00020037; // Writes a value to an array's element. + static const UINT32 c_Debugging_Value_AllocateObject = 0x00020038; // Creates a new instance of an object. + static const UINT32 c_Debugging_Value_AllocateString = 0x00020039; // Creates a new instance of a string. + static const UINT32 c_Debugging_Value_AllocateArray = 0x0002003A; // Creates a new instance of an array. + static const UINT32 c_Debugging_Value_Assign = 0x0002003B; // Assigns a value to another value. + + static const UINT32 c_Debugging_TypeSys_Assemblies = 0x00020040; // Lists all the assemblies in the system. + static const UINT32 c_Debugging_TypeSys_AppDomains = 0x00020044; // Lists all the AppDomans loaded. + + static const UINT32 c_Debugging_Resolve_Assembly = 0x00020050; // Resolves an assembly. + static const UINT32 c_Debugging_Resolve_Type = 0x00020051; // Resolves a type to a string. + static const UINT32 c_Debugging_Resolve_Field = 0x00020052; // Resolves a field to a string. + static const UINT32 c_Debugging_Resolve_Method = 0x00020053; // Resolves a method to a string. + static const UINT32 c_Debugging_Resolve_VirtualMethod = 0x00020054; // Resolves a virtual method to the actual implementation. + static const UINT32 c_Debugging_Resolve_AppDomain = 0x00020055; // Resolves an AppDomain to it's name, and list its loaded assemblies. + + + + + + + + + + static const UINT32 c_Debugging_UpgradeToSsl = 0x00020069; // + + //--// + + static const UINT32 c_Debugging_Lcd_NewFrame = 0x00020070; // Reports a new frame sent to the LCD. + static const UINT32 c_Debugging_Lcd_NewFrameData = 0x00020071; // Reports a new frame sent to the LCD, with its contents. + static const UINT32 c_Debugging_Lcd_GetFrame = 0x00020072; // Requests the current frame. + + static const UINT32 c_Debugging_Button_Report = 0x00020080; // Reports a button press/release. + static const UINT32 c_Debugging_Button_Inject = 0x00020081; // Injects a button press/release. + + static const UINT32 c_Debugging_Deployment_Status = 0x000200B0; // Returns entryPoint and boundary of deployment area. + + static const UINT32 c_Debugging_Info_SetJMC = 0x000200C0; // Sets code to be flagged as JMC (Just my code). + + static const UINT32 c_Profiling_Command = 0x00030000; // Various incoming commands regarding profiling + static const UINT32 c_Profiling_Stream = 0x00030001; // Stream for MFProfiler information. + + //--// + + struct Debugging_Execution_Unlock + { + UINT8 m_command[ 128 ]; + UINT8 m_hash [ 128 ]; + }; + + struct Debugging_Execution_QueryCLRCapabilities + { + static const CLR_UINT32 c_CapabilityFlags = 1; + static const CLR_UINT32 c_CapabilityLCD = 2; + static const CLR_UINT32 c_CapabilityVersion = 3; + static const CLR_UINT32 c_HalSystemInfo = 5; + static const CLR_UINT32 c_ClrInfo = 6; + static const CLR_UINT32 c_SolutionReleaseInfo = 7; + + static const CLR_UINT32 c_CapabilityFlags_FloatingPoint = 0x00000001; + static const CLR_UINT32 c_CapabilityFlags_SourceLevelDebugging = 0x00000002; + static const CLR_UINT32 c_CapabilityFlags_AppDomains = 0x00000004; + static const CLR_UINT32 c_CapabilityFlags_ExceptionFilters = 0x00000008; + static const CLR_UINT32 c_CapabilityFlags_IncrementalDeployment = 0x00000010; + static const CLR_UINT32 c_CapabilityFlags_SoftReboot = 0x00000020; + static const CLR_UINT32 c_CapabilityFlags_Profiling = 0x00000040; + static const CLR_UINT32 c_CapabilityFlags_Profiling_Allocations = 0x00000080; + static const CLR_UINT32 c_CapabilityFlags_Profiling_Calls = 0x00000100; + static const CLR_UINT32 c_CapabilityFlags_ThreadCreateEx = 0x00000400; + + CLR_UINT32 m_cmd; + + struct LCD + { + CLR_UINT32 m_width; + CLR_UINT32 m_height; + CLR_UINT32 m_bpp; + }; + + struct SoftwareVersion + { + char m_buildDate[ 20 ]; + UINT32 m_compilerVersion; + }; + + struct ClrInfo + { + MfReleaseInfo m_clrReleaseInfo; + MFVersion m_TargetFrameworkVersion; + }; + + union ReplyUnion + { + CLR_UINT32 u_capsFlags; + LCD u_LCD; + SoftwareVersion u_SoftwareVersion; + HalSystemInfo u_HalSystemInfo; + ClrInfo u_ClrInfo; + MfReleaseInfo u_SolutionReleaseInfo; + }; + }; + + //--// + + struct Debugging_Messaging_Query + { + CLR_RT_HeapBlock_EndPoint::Address m_addr; + + struct Reply + { + CLR_UINT32 m_found; + CLR_RT_HeapBlock_EndPoint::Address m_addr; + }; + }; + + struct Debugging_Messaging_Send + { + CLR_RT_HeapBlock_EndPoint::Address m_addr; + UINT8 m_data[ 1 ]; + + struct Reply + { + CLR_UINT32 m_found; + CLR_RT_HeapBlock_EndPoint::Address m_addr; + }; + }; + + struct Debugging_Messaging_Reply + { + CLR_RT_HeapBlock_EndPoint::Address m_addr; + UINT8 m_data[ 1 ]; + + struct Reply + { + CLR_UINT32 m_found; + CLR_RT_HeapBlock_EndPoint::Address m_addr; + }; + }; + + //--// + + + struct Debugging_Execution_BasePtr + { + struct Reply + { + CLR_UINT32 m_EE; + }; + }; + + struct Debugging_Execution_ChangeConditions + { + CLR_UINT32 m_set; + CLR_UINT32 m_reset; + + struct Reply + { + CLR_UINT32 m_current; + }; + }; + + struct Debugging_Execution_SecurityKey + { + CLR_UINT8 m_key[ 32 ]; + }; + + struct Debugging_Execution_Allocate + { + CLR_UINT32 m_size; + + struct Reply + { + CLR_UINT32 m_address; + }; + }; + + struct Debugging_UpgradeToSsl + { + CLR_UINT32 m_flags; + + struct Reply + { + CLR_UINT32 m_success; + }; + }; + + + //struct Debugging_MFUpdate_Start + //{ + // char m_provider[64]; + // CLR_UINT32 m_updateId; + // CLR_UINT32 m_updateType; + // CLR_UINT32 m_updateSubType; + // CLR_UINT32 m_updateSize; + // CLR_UINT32 m_updatePacketSize; + // CLR_UINT16 m_versionMajor; + // CLR_UINT16 m_versionMinor; + + // struct Reply + // { + // CLR_INT32 m_updateHandle; + // }; + //}; + + //struct Debugging_MFUpdate_AuthCommand + //{ + // CLR_UINT32 m_updateHandle; + // CLR_UINT32 m_authCommand; + // CLR_UINT32 m_authArgsSize; + // CLR_UINT8 m_authArgs[1]; + + // struct Reply + // { + // CLR_INT32 m_success; + // CLR_UINT32 m_responseSize; + // CLR_UINT8 m_response[1]; + // }; + //}; + + //struct Debugging_MFUpdate_Authenticate + //{ + // CLR_UINT32 m_updateHandle; + // CLR_UINT32 m_authenticationLen; + // CLR_UINT8 m_authenticationData[1]; + + // struct Reply + // { + // CLR_INT32 m_success; + // }; + //}; + + //struct Debugging_MFUpdate_GetMissingPkts + //{ + // CLR_UINT32 m_updateHandle; + // + // struct Reply + // { + // CLR_INT32 m_success; + // CLR_INT32 m_missingPktCount; + // CLR_UINT32 m_missingPkts[1]; + // }; + //}; + + //struct Debugging_MFUpdate_AddPacket + //{ + // CLR_INT32 m_updateHandle; + // CLR_UINT32 m_packetIndex; + // CLR_UINT32 m_packetValidation; + // CLR_UINT32 m_packetLength; + // CLR_UINT8 m_packetData[1]; + + // struct Reply + // { + // CLR_UINT32 m_success; + // }; + //}; + + //struct Debugging_MFUpdate_Install + //{ + // CLR_INT32 m_updateHandle; + // CLR_UINT32 m_updateValidationSize; + // CLR_UINT8 m_updateValidation[1]; + + // struct Reply + // { + // CLR_UINT32 m_success; + // }; + //}; + + + struct Debugging_Execution_BreakpointDef + { + static const CLR_UINT16 c_STEP_IN = 0x0001; + static const CLR_UINT16 c_STEP_OVER = 0x0002; + static const CLR_UINT16 c_STEP_OUT = 0x0004; + static const CLR_UINT16 c_HARD = 0x0008; + static const CLR_UINT16 c_EXCEPTION_THROWN = 0x0010; + static const CLR_UINT16 c_EXCEPTION_CAUGHT = 0x0020; + static const CLR_UINT16 c_EXCEPTION_UNCAUGHT = 0x0040; + static const CLR_UINT16 c_THREAD_TERMINATED = 0x0080; + static const CLR_UINT16 c_THREAD_CREATED = 0x0100; + static const CLR_UINT16 c_ASSEMBLIES_LOADED = 0x0200; + static const CLR_UINT16 c_LAST_BREAKPOINT = 0x0400; + static const CLR_UINT16 c_STEP_JMC = 0x0800; + static const CLR_UINT16 c_BREAK = 0x1000; + static const CLR_UINT16 c_EVAL_COMPLETE = 0x2000; + static const CLR_UINT16 c_EXCEPTION_UNWIND = 0x4000; + static const CLR_UINT16 c_EXCEPTION_FINALLY = 0x8000; + + static const CLR_UINT16 c_STEP = c_STEP_IN | c_STEP_OVER | c_STEP_OUT; + + static const CLR_UINT32 c_PID_ANY = 0xFFFFFFFF; + + static const CLR_UINT32 c_DEPTH_EXCEPTION_FIRST_CHANCE = 0x00000000; + static const CLR_UINT32 c_DEPTH_EXCEPTION_USERS_CHANCE = 0x00000001; + static const CLR_UINT32 c_DEPTH_EXCEPTION_HANDLER_FOUND = 0x00000002; + + static const CLR_UINT32 c_DEPTH_STEP_NORMAL = 0x00000010; + static const CLR_UINT32 c_DEPTH_STEP_RETURN = 0x00000020; + static const CLR_UINT32 c_DEPTH_STEP_CALL = 0x00000030; + static const CLR_UINT32 c_DEPTH_STEP_EXCEPTION_FILTER = 0x00000040; + static const CLR_UINT32 c_DEPTH_STEP_EXCEPTION_HANDLER = 0x00000050; + static const CLR_UINT32 c_DEPTH_STEP_INTERCEPT = 0x00000060; + static const CLR_UINT32 c_DEPTH_STEP_EXIT = 0x00000070; + + static const CLR_UINT32 c_DEPTH_UNCAUGHT = 0xFFFFFFFF; + + + CLR_UINT16 m_id; + CLR_UINT16 m_flags; + + CLR_UINT32 m_pid; + CLR_UINT32 m_depth; + + // + // m_IPStart, m_IPEnd are used for optimizing stepping operations. + // A STEP_IN | STEP_OVER breakpoint will be hit in the given stack frame + // only if the IP is outside of the given range [m_IPStart m_IPEnd). + // + CLR_UINT32 m_IPStart; + CLR_UINT32 m_IPEnd; + + CLR_RT_MethodDef_Index m_md; + CLR_UINT32 m_IP; + + CLR_RT_TypeDef_Index m_td; + + CLR_UINT32 m_depthExceptionHandler; + }; + + struct Debugging_Execution_Breakpoints + { + CLR_UINT32 m_flags; + + Debugging_Execution_BreakpointDef m_data[ 1 ]; + }; + + struct Debugging_Execution_BreakpointHit + { + Debugging_Execution_BreakpointDef m_hit; + }; + + struct Debugging_Execution_BreakpointStatus + { + struct Reply + { + Debugging_Execution_BreakpointDef m_lastHit; + }; + }; + + struct Debugging_Execution_SetCurrentAppDomain + { + CLR_UINT32 m_id; + }; + + //--//--// + + struct Debugging_Thread_CreateEx + { + CLR_RT_MethodDef_Index m_md; + int m_scratchPad; + CLR_UINT32 m_pid; + + struct Reply + { + CLR_UINT32 m_pid; + }; + }; + + //--// + + struct Debugging_Thread_List + { + struct Reply + { + CLR_UINT32 m_num; + CLR_UINT32 m_pids[ 1 ]; + }; + }; + + //--// + + struct Debugging_Thread_Stack + { + CLR_UINT32 m_pid; + + struct Reply + { + struct Call + { + CLR_RT_MethodDef_Index m_md; + CLR_UINT32 m_IP; +#if defined(TINYCLR_APPDOMAINS) + CLR_UINT32 m_appDomainID; + CLR_UINT32 m_flags; +#endif + + }; + + CLR_UINT32 m_num; + CLR_UINT32 m_status; + CLR_UINT32 m_flags; + Call m_data[ 1 ]; + }; + }; + + struct Debugging_Thread_Kill + { + CLR_UINT32 m_pid; + + struct Reply + { + int m_result; + }; + }; + + struct Debugging_Thread_Suspend + { + CLR_UINT32 m_pid; + }; + + struct Debugging_Thread_Resume + { + CLR_UINT32 m_pid; + }; + + struct Debugging_Thread_Get + { + CLR_UINT32 m_pid; + + // + // The reply is an array of Debugging_Value + // + }; + + struct Debugging_Thread_GetException + { + CLR_UINT32 m_pid; + + // + // The reply is an array of Debugging_Value + // + }; + + struct Debugging_Thread_Unwind + { + CLR_UINT32 m_pid; + CLR_UINT32 m_depth; + }; + + //--// + + struct Debugging_Stack_Info + { + CLR_UINT32 m_pid; + CLR_UINT32 m_depth; + + struct Reply + { + CLR_RT_MethodDef_Index m_md; + CLR_UINT32 m_IP; + CLR_UINT32 m_numOfArguments; + CLR_UINT32 m_numOfLocals; + CLR_UINT32 m_depthOfEvalStack; + }; + }; + + struct Debugging_Stack_SetIP + { + CLR_UINT32 m_pid; + CLR_UINT32 m_depth; + + CLR_UINT32 m_IP; + CLR_UINT32 m_depthOfEvalStack; + }; + + //--// + + struct Debugging_Value + { + CLR_RT_HeapBlock* m_referenceID; + CLR_UINT32 m_dt; // CLR_RT_HeapBlock::DataType () + CLR_UINT32 m_flags; // CLR_RT_HeapBlock::DataFlags() + CLR_UINT32 m_size; // CLR_RT_HeapBlock::DataSize () + + // + // For primitive types + // + CLR_UINT8 m_builtinValue[ 128 ]; // Space for string preview... + + // + // For DATATYPE_STRING + // + CLR_UINT32 m_bytesInString; + LPCSTR m_charsInString; + + // + // For DATATYPE_VALUETYPE or DATATYPE_CLASSTYPE + // + CLR_RT_TypeDef_Index m_td; + + // + // For DATATYPE_SZARRAY + // + CLR_UINT32 m_array_numOfElements; + CLR_UINT32 m_array_depth; + CLR_RT_TypeDef_Index m_array_typeIndex; + + // + // For values from an array. + // + CLR_RT_HeapBlock_Array* m_arrayref_referenceID; + CLR_UINT32 m_arrayref_index; + }; + + struct Debugging_Value_ResizeScratchPad + { + CLR_UINT32 m_size; + }; + + struct Debugging_Value_GetStack + { + static const CLR_UINT32 c_Local = 0; + static const CLR_UINT32 c_Argument = 1; + static const CLR_UINT32 c_EvalStack = 2; + + CLR_UINT32 m_pid; + CLR_UINT32 m_depth; + CLR_UINT32 m_kind; + CLR_UINT32 m_index; + + + // + // The reply is an array of Debugging_Value + // + }; + + struct Debugging_Value_GetField + { + CLR_RT_HeapBlock* m_heapblock; + CLR_UINT32 m_offset; + CLR_RT_FieldDef_Index m_fd; + + + // + // The reply is an array of Debugging_Value + // + }; + + struct Debugging_Value_GetArray + { + CLR_RT_HeapBlock* m_heapblock; + CLR_UINT32 m_index; + + + // + // The reply is an array of Debugging_Value + // + }; + + struct Debugging_Value_GetBlock + { + CLR_RT_HeapBlock* m_heapblock; + + + // + // The reply is an array of Debugging_Value + // + }; + + struct Debugging_Value_GetScratchPad + { + CLR_UINT32 m_idx; + + + // + // The reply is an array of Debugging_Value + // + }; + + struct Debugging_Value_SetBlock + { + CLR_RT_HeapBlock* m_heapblock; + CLR_UINT32 m_dt; // CLR_RT_HeapBlock::DataType () + CLR_UINT8 m_builtinValue[ 8 ]; + }; + + struct Debugging_Value_SetArray + { + CLR_RT_HeapBlock_Array* m_heapblock; + CLR_UINT32 m_index; + CLR_UINT8 m_builtinValue[ 8 ]; + }; + + //--// + + struct Debugging_Value_AllocateObject + { + int m_index; + CLR_RT_TypeDef_Index m_td; + + // + // The reply is an array of Debugging_Value + // + }; + + struct Debugging_Value_AllocateString + { + int m_index; + CLR_UINT32 m_size; + + // + // The reply is an array of Debugging_Value + // + }; + + struct Debugging_Value_AllocateArray + { + int m_index; + CLR_RT_TypeDef_Index m_td; + CLR_UINT32 m_depth; + CLR_UINT32 m_numOfElements; + + // + // The reply is an array of Debugging_Value + // + }; + + struct Debugging_Value_Assign + { + CLR_RT_HeapBlock* m_heapblockSrc; + CLR_RT_HeapBlock* m_heapblockDst; + + // + // The reply is an array of Debugging_Value + // + }; + + //--// + + struct Debugging_TypeSys_Assemblies + { + // + // The reply is just an array of CLR_RT_Assembly_Index. + // + }; + + struct Debugging_TypeSys_AppDomains + { + // + // The reply is just an array of AppDomainIDs + // + }; + + //--// + + struct Debugging_Resolve_AppDomain + { + CLR_UINT32 m_id; + + struct Reply + { + CLR_UINT32 m_state; + char m_szName[ 512 ]; + CLR_UINT32 m_assemblies[ 1 ]; //Array of CLR_RT_Assembly_Index + }; + }; + + struct Debugging_Resolve_Assembly + { + CLR_RT_Assembly_Index m_idx; + + struct Reply + { + CLR_UINT32 m_flags; + CLR_RECORD_VERSION m_version; + char m_szName[ 512 ]; + }; + }; + + struct Debugging_Resolve_Type + { + CLR_RT_TypeDef_Index m_td; + + struct Reply + { + char m_type[ 512 ]; + }; + }; + + struct Debugging_Resolve_Field + { + CLR_RT_FieldDef_Index m_fd; + + struct Reply + { + CLR_RT_TypeDef_Index m_td; + CLR_UINT32 m_index; + char m_name[ 512 ]; + }; + }; + + struct Debugging_Resolve_Method + { + CLR_RT_MethodDef_Index m_md; + + struct Reply + { + CLR_RT_TypeDef_Index m_td; + char m_method[ 512 ]; + }; + }; + + struct Debugging_Resolve_VirtualMethod + { + CLR_RT_MethodDef_Index m_md; + CLR_RT_HeapBlock* m_obj; + + struct Reply + { + CLR_RT_MethodDef_Index m_md; + }; + }; + + //--// + + struct Debugging_Deployment_Status + { + static const CLR_UINT32 c_CRC_Erased_Sentinel = 0x0; + + struct FlashSector + { + CLR_UINT32 m_start; + CLR_UINT32 m_length; + + CLR_UINT32 m_crc; + }; + + struct Reply + { + CLR_UINT32 m_entryPoint; + CLR_UINT32 m_storageStart; + CLR_UINT32 m_storageLength; + + CLR_UINT32 m_eraseWord; + CLR_UINT32 m_maxSectorErase_uSec; + CLR_UINT32 m_maxWordWrite_uSec; + FlashSector m_data[ 1 ]; + }; + }; + + //--// + + struct Debugging_Info_SetJMC + { + CLR_UINT32 m_fIsJMC; + CLR_UINT32 m_kind; // CLR_ReflectionType + + union + { + CLR_RT_Assembly_Index m_assm; + CLR_RT_TypeDef_Index m_type; + CLR_RT_MethodDef_Index m_method; + CLR_UINT32 m_raw; + } m_data; + }; + + struct Profiling_Command + { + static const CLR_UINT8 c_Command_ChangeConditions = 0x01; + static const CLR_UINT8 c_Command_FlushStream = 0x02; + + CLR_UINT8 m_command; + + struct Reply + { + CLR_UINT32 m_raw; + }; + }; + + struct Profiling_ChangeConditions + { + CLR_UINT32 m_set; + CLR_UINT32 m_reset; + }; + + struct Profiling_Stream + { + CLR_UINT16 m_seqId; + CLR_UINT16 m_bitLen; + }; + +}; + +struct CLR_DBG_Debugger +{ + CLR_Messaging* m_messaging; + static BlockStorageDevice* m_deploymentStorageDevice; + + + //--// + + static void Debugger_Discovery(); + static void Debugger_WaitForCommands(); + + static HRESULT CreateInstance(); + + HRESULT Debugger_Initialize( COM_HANDLE port ); + + static HRESULT DeleteInstance(); + + void Debugger_Cleanup(); + + static void BroadcastEvent( UINT32 cmd, UINT32 payloadSize, UINT8* payload, UINT32 flags ); + + void ProcessCommands(); + void PurgeCache (); + +private: + + bool CheckPermission( ByteAddress address, int mode ); + + bool AccessMemory( CLR_UINT32 location, UINT32 lengthInBytes, BYTE* buf, int mode ); + +#if defined(TINYCLR_APPDOMAINS) + CLR_RT_AppDomain* GetAppDomainFromID ( CLR_UINT32 id ); +#endif + + CLR_RT_StackFrame* CheckStackFrame ( CLR_UINT32 pid, CLR_UINT32 depth, bool& isInline ); + HRESULT CreateListOfThreads( CLR_DBG_Commands::Debugging_Thread_List ::Reply*& cmdReply, int& totLen ); + HRESULT CreateListOfCalls ( CLR_UINT32 pid, CLR_DBG_Commands::Debugging_Thread_Stack::Reply*& cmdReply, int& totLen ); + + CLR_RT_Assembly* IsGoodAssembly( CLR_IDX idxAssm ); + bool CheckTypeDef ( const CLR_RT_TypeDef_Index& td , CLR_RT_TypeDef_Instance& inst ); + bool CheckFieldDef ( const CLR_RT_FieldDef_Index& fd , CLR_RT_FieldDef_Instance& inst ); + bool CheckMethodDef( const CLR_RT_MethodDef_Index& md , CLR_RT_MethodDef_Instance& inst ); + + bool GetValue( WP_Message* msg, CLR_RT_HeapBlock* ptr, CLR_RT_HeapBlock* reference, CLR_RT_TypeDef_Instance* pTD ); + + bool AllocateAndQueueMessage( CLR_UINT32 cmd, UINT32 length, UINT8* data, CLR_RT_HeapBlock_EndPoint::Port port, CLR_RT_HeapBlock_EndPoint::Address addr, CLR_UINT32 found ); + + bool ProcessHeader ( WP_Message* msg ); + bool ProcessPayload ( WP_Message* msg ); + + +public: + static CLR_RT_Thread* GetThreadFromPid ( CLR_UINT32 pid ); + + static bool Monitor_Ping ( WP_Message* msg, void* owner ); + static bool Monitor_Reboot ( WP_Message* msg, void* owner ); + static bool Debugging_Execution_QueryCLRCapabilities( WP_Message* msg, void* owner ); + + static bool Monitor_ReadMemory ( WP_Message* msg, void* owner ); + static bool Monitor_WriteMemory ( WP_Message* msg, void* owner ); + static bool Monitor_CheckMemory ( WP_Message* msg, void* owner ); + static bool Monitor_EraseMemory ( WP_Message* msg, void* owner ); + static bool Monitor_Execute ( WP_Message* msg, void* owner ); + static bool Monitor_MemoryMap ( WP_Message* msg, void* owner ); + static bool Monitor_FlashSectorMap ( WP_Message* msg, void* owner ); + static bool Monitor_DeploymentMap ( WP_Message* msg, void* owner ); + + + static bool Debugging_Execution_BasePtr ( WP_Message* msg, void* owner ); + static bool Debugging_Execution_ChangeConditions ( WP_Message* msg, void* owner ); + + static bool Debugging_Execution_Allocate ( WP_Message* msg, void* owner ); + + static bool Debugging_UpgradeToSsl ( WP_Message* msg, void* owner ); + + + + + + + + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + static bool Debugging_Execution_Breakpoints ( WP_Message* msg, void* owner ); + static bool Debugging_Execution_BreakpointStatus ( WP_Message* msg, void* owner ); + static bool Debugging_Execution_SetCurrentAppDomain ( WP_Message* msg, void* owner ); + + static bool Debugging_Thread_CreateEx ( WP_Message* msg, void* owner ); + static bool Debugging_Thread_List ( WP_Message* msg, void* owner ); + static bool Debugging_Thread_Stack ( WP_Message* msg, void* owner ); + static bool Debugging_Thread_Kill ( WP_Message* msg, void* owner ); + static bool Debugging_Thread_Suspend ( WP_Message* msg, void* owner ); + static bool Debugging_Thread_Resume ( WP_Message* msg, void* owner ); + static bool Debugging_Thread_GetException ( WP_Message* msg, void* owner ); + static bool Debugging_Thread_Unwind ( WP_Message* msg, void* owner ); + static bool Debugging_Thread_Get ( WP_Message* msg, void* owner ); + + static bool Debugging_Stack_Info ( WP_Message* msg, void* owner ); + static bool Debugging_Stack_SetIP ( WP_Message* msg, void* owner ); + + static bool Debugging_Value_ResizeScratchPad ( WP_Message* msg, void* owner ); + static bool Debugging_Value_GetStack ( WP_Message* msg, void* owner ); + static bool Debugging_Value_GetField ( WP_Message* msg, void* owner ); + static bool Debugging_Value_GetArray ( WP_Message* msg, void* owner ); + static bool Debugging_Value_GetBlock ( WP_Message* msg, void* owner ); + static bool Debugging_Value_GetScratchPad ( WP_Message* msg, void* owner ); + static bool Debugging_Value_SetBlock ( WP_Message* msg, void* owner ); + static bool Debugging_Value_SetArray ( WP_Message* msg, void* owner ); + static bool Debugging_Value_AllocateObject ( WP_Message* msg, void* owner ); + static bool Debugging_Value_AllocateString ( WP_Message* msg, void* owner ); + static bool Debugging_Value_AllocateArray ( WP_Message* msg, void* owner ); + static bool Debugging_Value_Assign ( WP_Message* msg, void* owner ); + + static bool Debugging_TypeSys_Assemblies ( WP_Message* msg, void* owner ); + static bool Debugging_TypeSys_AppDomains ( WP_Message* msg, void* owner ); + + static bool Debugging_Resolve_AppDomain ( WP_Message* msg, void* owner ); + static bool Debugging_Resolve_Assembly ( WP_Message* msg, void* owner ); + static bool Debugging_Resolve_Type ( WP_Message* msg, void* owner ); + static bool Debugging_Resolve_Field ( WP_Message* msg, void* owner ); + static bool Debugging_Resolve_Method ( WP_Message* msg, void* owner ); + static bool Debugging_Resolve_VirtualMethod ( WP_Message* msg, void* owner ); +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + static bool Debugging_Deployment_Status ( WP_Message* msg, void* owner ); + static bool Debugging_Info_SetJMC ( WP_Message* msg, void* owner ); + + bool Debugging_Info_SetJMC_Type ( const CLR_RT_TypeDef_Index& idx, bool fJMC ); + bool Debugging_Info_SetJMC_Method ( const CLR_RT_MethodDef_Index& idx, bool fJMC ); +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + static bool Profiling_Command ( WP_Message* msg, void* owner ); + bool Profiling_ChangeConditions ( WP_Message* msg ); + bool Profiling_FlushStream ( WP_Message* msg ); +}; + +//--// + +extern CLR_UINT32 g_scratchDebugger[]; +extern CLR_UINT32 g_scratchDebuggerMessaging[]; +extern CLR_DBG_Debugger *g_CLR_DBG_Debuggers; + +//--// + +extern const CLR_Messaging_CommandHandlerLookup c_Debugger_Lookup_Request[]; +extern const CLR_Messaging_CommandHandlerLookup c_Debugger_Lookup_Reply[]; +extern const CLR_UINT32 c_Debugger_Lookup_Request_count; +extern const CLR_UINT32 c_Debugger_Lookup_Reply_count; + +//--// + +#endif // _TINYCLR_DEBUGGING_H_ + diff --git a/src/CLR/Include/TinyCLR_ErrorCodes.h b/src/CLR/Include/TinyCLR_ErrorCodes.h new file mode 100644 index 0000000000..25ffe3c0a7 --- /dev/null +++ b/src/CLR/Include/TinyCLR_ErrorCodes.h @@ -0,0 +1,26 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _TINYCLR_ERRORCODES_H_ +#define _TINYCLR_ERRORCODES_H_ +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#include + +// +// PARSER error codes. +// +#define CLR_E_PARSER_BAD_TEXT_SIGNATURE MAKE_HRESULT(SEVERITY_ERROR, 0x0101, 0x0001) +#define CLR_E_PARSER_BAD_CUSTOM_ATTRIBUTE MAKE_HRESULT(SEVERITY_ERROR, 0x0101, 0x0002) +#define CLR_E_PARSER_UNSUPPORTED_MULTIDIM_ARRAY MAKE_HRESULT(SEVERITY_ERROR, 0x0101, 0x0003) +#define CLR_E_PARSER_UNKNOWN_MEMBER_REF MAKE_HRESULT(SEVERITY_ERROR, 0x0101, 0x0004) +#define CLR_E_PARSER_MISSING_FIELD MAKE_HRESULT(SEVERITY_ERROR, 0x0101, 0x0005) +#define CLR_E_PARSER_MISSING_METHOD MAKE_HRESULT(SEVERITY_ERROR, 0x0101, 0x0006) +#define CLR_E_PARSER_MISSING_INTERFACE MAKE_HRESULT(SEVERITY_ERROR, 0x0101, 0x0007) +#define CLR_E_PARSER_MISSING_TOKEN MAKE_HRESULT(SEVERITY_ERROR, 0x0101, 0x0008) +#define CLR_E_PARSER_UNSUPPORTED_GENERICS MAKE_HRESULT(SEVERITY_ERROR, 0x0101, 0x0009) + + +#endif // _TINYCLR_ERRORCODES_H_ diff --git a/src/CLR/Include/TinyCLR_Hardware.h b/src/CLR/Include/TinyCLR_Hardware.h new file mode 100644 index 0000000000..d9dad90a9c --- /dev/null +++ b/src/CLR/Include/TinyCLR_Hardware.h @@ -0,0 +1,145 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _TINYCLR_HARDWARE_H_ +#define _TINYCLR_HARDWARE_H_ + +#include +#include +//#include + +//--// + +// +// THIS HAS TO MATCH THE ENUM Microsoft.SPOT.Hardware.ButtonCode!!!! +// +// UNDONE: FIXME: static const int c_CLR_HW_Button_Up = 0; +//static const int c_CLR_HW_Button_Down = 1; +//static const int c_CLR_HW_Button_Spare = 2; +//static const int c_CLR_HW_Button_Select = 3; +//static const int c_CLR_HW_Button_Channel = 4; +//static const int c_CLR_HW_Button_Backlight = 5; +// +//static const int c_CLR_HW_Button_Raw_B0 = 10; +//static const int c_CLR_HW_Button_Raw_B1 = 11; +//static const int c_CLR_HW_Button_Raw_B2 = 12; +//static const int c_CLR_HW_Button_Raw_B3 = 13; +//static const int c_CLR_HW_Button_Raw_B4 = 14; +//static const int c_CLR_HW_Button_Raw_B5 = 15; +//static const int c_CLR_HW_Button_Raw_B6 = 16; +//static const int c_CLR_HW_Button_Raw_B7 = 17; +//static const int c_CLR_HW_Button_Raw_B8 = 18; +//static const int c_CLR_HW_Button_Raw_B9 = 19; +// +//static const int c_CLR_HW_Button_MAX = 32; + +#if defined(_WIN32) +#include "TinyCLR_Win32.h" +#endif + +//--// + +struct CLR_HW_Hardware +{ + enum PowerLevel + { + PowerLevel__Active, + PowerLevel__SelectiveOff, + PowerLevel__Sleep, + PowerLevel__DeepSleep, + PowerLevel__Off + }; + + //--// + + static const CLR_UINT32 c_Default_PowerLevel = PowerLevel__Sleep; + static const CLR_UINT32 c_Default_WakeupEvents = SYSTEM_EVENT_FLAG_COM_IN | + SYSTEM_EVENT_FLAG_COM_OUT | + SYSTEM_EVENT_FLAG_USB_IN | + SYSTEM_EVENT_FLAG_SYSTEM_TIMER | + SYSTEM_EVENT_HW_INTERRUPT | + // UNDONE: FIXME: SYSTEM_EVENT_I2C_XACTION | + SYSTEM_EVENT_FLAG_SOCKET | + // UNDONE: FIXME: SYSTEM_EVENT_FLAG_CHARGER_CHANGE | + SYSTEM_EVENT_FLAG_DEBUGGER_ACTIVITY | + SYSTEM_EVENT_FLAG_MESSAGING_ACTIVITY| + SYSTEM_EVENT_FLAG_IO ; + + //--// + + struct HalInterruptRecord + { + CLR_INT64 m_time; + CLR_RT_HeapBlock_Node* m_context; + + CLR_UINT32 m_data1; + CLR_UINT32 m_data2; + CLR_UINT32 m_data3; + + void AssignFrom( const HalInterruptRecord &recFrom ) + { + m_time = recFrom.m_time; + m_context = recFrom.m_context; + m_data1 = recFrom.m_data1; + m_data2 = recFrom.m_data2; + } + }; + + struct InterruptData + { + Hal_Queue_UnknownSize m_HalQueue; + CLR_RT_DblLinkedList m_applicationQueue; + CLR_UINT32 m_queuedInterrupts; + }; + + //--// + + bool m_fInitialized; + + InterruptData m_interruptData; + + CLR_UINT32 m_DebuggerEventsMask; + CLR_UINT32 m_MessagingEventsMask; + + CLR_UINT32 m_powerLevel; + CLR_UINT32 m_wakeupEvents; + + //--// + + static HRESULT CreateInstance(); + + HRESULT Hardware_Initialize(); + + static HRESULT DeleteInstance(); + + void Hardware_Cleanup(); + + void PrepareForGC (); + void ProcessActivity(); + + HRESULT ManagedHardware_Initialize(); + HRESULT ProcessInterrupts(); + HRESULT SpawnDispatcher(); + HRESULT TransferAllInterruptsToApplicationQueue(); + + // UNDONE: FIXME: void Screen_Flush( CLR_GFX_Bitmap& bitmap, CLR_UINT16 x, CLR_UINT16 y, CLR_UINT16 width, CLR_UINT16 height ); +}; + +extern CLR_HW_Hardware g_CLR_HW_Hardware; + +//--// + + +//////////////////////////////////////////////////////////////////////////////////////// +// keep under control the size of the HalInterruptRecord, since we will use externally +// defined arrays to handle those data structures in the interrupt dispatching + +CT_ASSERT(sizeof(CLR_HW_Hardware::HalInterruptRecord) == 24) + +//////////////////////////////////////////////////////////////////////////////////////// + +//--// + +#endif // _TINYCLR_HARDWARE_H_ diff --git a/src/CLR/Include/TinyCLR_Interop.h b/src/CLR/Include/TinyCLR_Interop.h new file mode 100644 index 0000000000..253a98ed2a --- /dev/null +++ b/src/CLR/Include/TinyCLR_Interop.h @@ -0,0 +1,461 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _TINYCLR_INTEROP_H_ +#define _TINYCLR_INTEROP_H_ + +#include + + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +extern HRESULT TINYCLR_DEBUG_PROCESS_EXCEPTION( HRESULT hr, LPCSTR szFunc, LPCSTR szFile, int line ); + +#if defined(_WIN32) + +#define TINYCLR_LEAVE() { if(FAILED(hr)) TINYCLR_DEBUG_PROCESS_EXCEPTION( hr, NULL, NULL, 0 ); goto TinyCLR_Cleanup; } +#define TINYCLR_RETURN() return hr + +#else + +#if defined(TINYCLR_TRACE_HRESULT) + +#define TINYCLR_LEAVE() { if(FAILED(hr)) TINYCLR_DEBUG_PROCESS_EXCEPTION( hr, __func__, __FILE__, __LINE__ ); goto TinyCLR_Cleanup; } +#define TINYCLR_RETURN() return hr + +#else + +#define TINYCLR_LEAVE() goto TinyCLR_Cleanup +#define TINYCLR_RETURN() return hr + +#endif + +#endif + + +#define TINYCLR_HEADER() HRESULT hr +#define TINYCLR_CHECK_HRESULT(expr) { if(FAILED(hr = (expr))) TINYCLR_LEAVE(); } +#define TINYCLR_EXIT_ON_SUCCESS(expr) { if(SUCCEEDED(hr = (expr))) TINYCLR_LEAVE(); } +#define TINYCLR_SET_AND_LEAVE(expr) { hr = (expr); TINYCLR_LEAVE(); } +#define TINYCLR_CLEANUP() hr = S_OK; TinyCLR_Cleanup: +#define TINYCLR_CLEANUP_END() TINYCLR_RETURN() +#define TINYCLR_NOCLEANUP() TINYCLR_CLEANUP(); TINYCLR_CLEANUP_END() +#define TINYCLR_NOCLEANUP_NOLABEL() hr = S_OK; TINYCLR_RETURN() +#define FAULT_ON_NULL(ptr) if(!(ptr)) TINYCLR_SET_AND_LEAVE(CLR_E_NULL_REFERENCE) +#define FAULT_ON_NULL_ARG(ptr) if(!(ptr)) TINYCLR_SET_AND_LEAVE(CLR_E_ARGUMENT_NULL) + + +// Correspondence between CLR C# and C++ native types: +// CLR Type C/C++ type C/C++ Ref Type + +// System.Byte UINT8 UINT8& +// System.UInt16 UINT16 UINT16& +// System.UInt32 UINT32 UINT32& +// System.UInt64 UINT64 UINT64& +// System.Char CHAR CHAR & +// System.SByte INT8 INT8 & +// System.Int16 INT16 INT16& +// System.Int32 INT32 INT32& +// System.Int64 INT64 INT64& +// System.Single float float& +// System.Double double double& +// System.String const CHAR * CHAR * +// System.Byte[] UINT8 * Same as C/C++ type + +// Forward declaration for managed stack frame. +// This is internal CLR type, reference to managed stack frame is exposed to marshaling code. +struct CLR_RT_StackFrame; +/********************************************************************** +** +** Forward structure declarations . +** CLR_RT_HeapBlock - generic structure that keeps C# basic types +** CLR_RT_HeapBlock_NativeEventDispatcher - Object that supports managed callback initiated by Interrupts +**********************************************************************/ +struct CLR_RT_HeapBlock; +struct CLR_RT_HeapBlock_NativeEventDispatcher; + +// Do not support marshaling of struct and class. For these types we create params of CLR_RT_HeapBlock* +// and then set it to zero. +typedef CLR_RT_HeapBlock* UNSUPPORTED_TYPE; + +#define CLR_RT_HEAP_BLOCK_SIZE 12 + +#define TINYCLR_NATIVE_DECLARE(mtd) static HRESULT mtd( CLR_RT_StackFrame& stack ) + +typedef HRESULT (*CLR_RT_MethodHandler)( CLR_RT_StackFrame& stack ); + +struct CLR_RT_NativeAssemblyData + +{ // Assembly name or static name provided by driver developer to enable interrups. + const char *m_szAssemblyName; + + // Check sum for the assembly. + UINT32 m_checkSum; + + // Pointer to array of functions that implement native methods. + // It could be different type of the function depending if it is assembly Interop Method + // or function enabling Interrupts by user driver. + const void *m_pNativeMethods; +}; + +// Looks up in interop assemblies table for assembly with specified name. +const CLR_RT_NativeAssemblyData *GetAssemblyNativeData( const char *lpszAssemblyName ); + +// C++ by value parameters ( not reference types ). +/********************************************************************** +** +** Functions: Interop_Marshal_* +** +** Synopsis: This group of functions retrienves by value parameters ( not reference types ) +** Each function gets reference to managed stack frame in index of parameter to extract. +** The C++ value is returned in "param". +** +** Arguments: [stackFrame] - Reference to the managed stack frame. +** [paramIndex] - Index of parameter passed from managed code. This parameter will be updated now. +** [param] - Reference to native C++ variable. Filled by the function. +** This variable is filled with value passed from managed code. +** +** Returns: S_OK on success or error in case of paramter mismatch or invalid data passed from managed code. +**********************************************************************/ + +HRESULT Interop_Marshal_bool ( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, bool ¶m ); +HRESULT Interop_Marshal_UINT8 ( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, UINT8 ¶m ); +HRESULT Interop_Marshal_UINT16( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, UINT16 ¶m ); +HRESULT Interop_Marshal_UINT32( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, UINT32 ¶m ); +HRESULT Interop_Marshal_UINT64( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, UINT64 ¶m ); +HRESULT Interop_Marshal_CHAR ( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, CHAR ¶m ); +HRESULT Interop_Marshal_INT8 ( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, INT8 ¶m ); +HRESULT Interop_Marshal_INT16 ( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, INT16 ¶m ); +HRESULT Interop_Marshal_INT32 ( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, INT32 ¶m ); +HRESULT Interop_Marshal_INT64 ( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, INT64 ¶m ); +#if !defined(TINYCLR_EMULATED_FLOATINGPOINT) +HRESULT Interop_Marshal_float ( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, float ¶m ); +HRESULT Interop_Marshal_double( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, double ¶m ); + +#else +HRESULT Interop_Marshal_float ( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, INT32 ¶m ); +HRESULT Interop_Marshal_double( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, INT64 ¶m ); +#endif + +HRESULT Interop_Marshal_LPCSTR( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, LPCSTR ¶m ); +// For unsupported types we set param to NULL. +HRESULT Interop_Marshal_UNSUPPORTED_TYPE( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, UNSUPPORTED_TYPE ¶m ); +/********************************************************************** +** +** Functions: Interop_Marshal_*_ARRAY +** +** Synopsis: This group of functions retrienves C++ by value parameters ( not reference types ) +** Each function gets reference to managed stack frame in index of parameter to extract. +** The C++ value is returned in "param". +** +** Arguments: [stackFrame] - Reference to the managed stack frame. +** [paramIndex] - Index of parameter passed from managed code. This parameter will be updated now. +** [pByteParam] - Reference to pointer filled by the function. +** On return pParam points to native C++ array with values passed from managed code. +** This variable is filled with value passed from managed code. +** [arraySize] - Count of elements in array. Filled by the function. +** +** Returns: S_OK on success or error in case of paramter mismatch or invalid data passed from managed code. +**********************************************************************/ + + +template class CLR_RT_TypedArray + +{ + T *m_pData; + UINT32 m_ElemCount; + +friend HRESULT Interop_Marshal_bool_ARRAY ( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, CLR_RT_TypedArray &typedArray ); +friend HRESULT Interop_Marshal_UINT8_ARRAY ( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, CLR_RT_TypedArray &typedArray ); +friend HRESULT Interop_Marshal_UINT16_ARRAY( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, CLR_RT_TypedArray &typedArray ); +friend HRESULT Interop_Marshal_UINT32_ARRAY( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, CLR_RT_TypedArray &typedArray ); +friend HRESULT Interop_Marshal_UINT64_ARRAY( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, CLR_RT_TypedArray &typedArray ); +friend HRESULT Interop_Marshal_CHAR_ARRAY ( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, CLR_RT_TypedArray &typedArray ); +friend HRESULT Interop_Marshal_INT8_ARRAY ( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, CLR_RT_TypedArray &typedArray ); +friend HRESULT Interop_Marshal_INT16_ARRAY ( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, CLR_RT_TypedArray &typedArray ); +friend HRESULT Interop_Marshal_INT32_ARRAY ( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, CLR_RT_TypedArray &typedArray ); +friend HRESULT Interop_Marshal_INT64_ARRAY ( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, CLR_RT_TypedArray &typedArray ); + +#if !defined(TINYCLR_EMULATED_FLOATINGPOINT) +friend HRESULT Interop_Marshal_float_ARRAY ( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, CLR_RT_TypedArray &typedArray ); +friend HRESULT Interop_Marshal_double_ARRAY( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, CLR_RT_TypedArray &typedArray ); +#else +friend HRESULT Interop_Marshal_float_ARRAY ( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, CLR_RT_TypedArray &typedArray ); +friend HRESULT Interop_Marshal_double_ARRAY( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, CLR_RT_TypedArray &typedArray ); + +#endif + + +public : + CLR_RT_TypedArray() { m_pData = NULL; m_ElemCount = 0; } + + T GetValue( UINT32 i ) { return m_pData[ i ];} + void SetValue( UINT32 i, T &val ) { m_pData[ i ] = val; } + T& operator[]( UINT32 i ) { return m_pData[ i ];} + + UINT32 GetSize() { return m_ElemCount; } + + // Direct access to buffer is provided for cases when other + // native functions require access to buffer and cannot use CLR_RT_TypedArray object + T *GetBuffer() { return m_pData; } + + }; + +typedef CLR_RT_TypedArray CLR_RT_TypedArray_CHAR; +typedef CLR_RT_TypedArray CLR_RT_TypedArray_UINT8; +typedef CLR_RT_TypedArray CLR_RT_TypedArray_UINT16; +typedef CLR_RT_TypedArray CLR_RT_TypedArray_UINT32; +typedef CLR_RT_TypedArray CLR_RT_TypedArray_UINT64; +typedef CLR_RT_TypedArray CLR_RT_TypedArray_INT8; +typedef CLR_RT_TypedArray CLR_RT_TypedArray_INT16; +typedef CLR_RT_TypedArray CLR_RT_TypedArray_INT32; +typedef CLR_RT_TypedArray CLR_RT_TypedArray_INT64; +#if !defined(TINYCLR_EMULATED_FLOATINGPOINT) +typedef CLR_RT_TypedArray CLR_RT_TypedArray_float; +typedef CLR_RT_TypedArray CLR_RT_TypedArray_double; +#else +typedef CLR_RT_TypedArray CLR_RT_TypedArray_float; +typedef CLR_RT_TypedArray CLR_RT_TypedArray_double; + + +#endif + +HRESULT Interop_Marshal_bool_ARRAY ( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, CLR_RT_TypedArray_UINT8 &typedArray ); +HRESULT Interop_Marshal_UINT8_ARRAY ( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, CLR_RT_TypedArray_UINT8 &typedArray ); +HRESULT Interop_Marshal_UINT16_ARRAY( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, CLR_RT_TypedArray_UINT16 &typedArray ); +HRESULT Interop_Marshal_UINT32_ARRAY( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, CLR_RT_TypedArray_UINT32 &typedArray ); +HRESULT Interop_Marshal_UINT64_ARRAY( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, CLR_RT_TypedArray_UINT64 &typedArray ); +HRESULT Interop_Marshal_CHAR_ARRAY ( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, CLR_RT_TypedArray_CHAR &typedArray ); +HRESULT Interop_Marshal_INT8_ARRAY ( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, CLR_RT_TypedArray_INT8 &typedArray ); +HRESULT Interop_Marshal_INT16_ARRAY ( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, CLR_RT_TypedArray_INT16 &typedArray ); +HRESULT Interop_Marshal_INT32_ARRAY ( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, CLR_RT_TypedArray_INT32 &typedArray ); +HRESULT Interop_Marshal_INT64_ARRAY ( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, CLR_RT_TypedArray_INT64 &typedArray ); +HRESULT Interop_Marshal_float_ARRAY ( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, CLR_RT_TypedArray_float &typedArray ); +HRESULT Interop_Marshal_double_ARRAY( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, CLR_RT_TypedArray_double &typedArray ); + +/********************************************************************** +** +** Functions: SetResult_* +** +** Synopsis: This group of functions set value returned by managed method call. +** Value passed to this function will be the return value of the managed function. +** +** Arguments: [stackFrame] - Reference to the managed stack frame. +** [value] - Return value. This value is stored on managed stack frame and passed to managed code. +**********************************************************************/ + +void SetResult_bool ( CLR_RT_StackFrame &stackFrame, bool value ); +void SetResult_CHAR ( CLR_RT_StackFrame &stackFrame, CHAR value ); +void SetResult_INT8 ( CLR_RT_StackFrame &stackFrame, INT8 value ); +void SetResult_INT16 ( CLR_RT_StackFrame &stackFrame, INT16 value ); +void SetResult_INT32 ( CLR_RT_StackFrame &stackFrame, INT32 value ); +void SetResult_INT64 ( CLR_RT_StackFrame &stackFrame, INT64 value ); +void SetResult_UINT8 ( CLR_RT_StackFrame &stackFrame, UINT8 value ); +void SetResult_UINT16( CLR_RT_StackFrame &stackFrame, UINT16 value ); +void SetResult_UINT32( CLR_RT_StackFrame &stackFrame, UINT32 value ); +void SetResult_UINT64( CLR_RT_StackFrame &stackFrame, UINT64 value ); +#if !defined(TINYCLR_EMULATED_FLOATINGPOINT) +void SetResult_float ( CLR_RT_StackFrame &stackFrame, float value ); +void SetResult_double( CLR_RT_StackFrame &stackFrame, double value ); +#else +void SetResult_float ( CLR_RT_StackFrame &stackFrame, INT32 value ); +void SetResult_double( CLR_RT_StackFrame &stackFrame, INT64 value ); + +#endif + +void SetResult_LPCSTR( CLR_RT_StackFrame &stackFrame, LPCSTR value ); + +/********************************************************************** +** +** Functions: Interop_Marshal_LoadRef_* +** +** Synopsis: This group of functions pointer to reference parameter passed from managed code. +** On return of this function pParam points to reference parameter of managed code. +** Native code can retrieve and modidy the reference parameter using pParam +** +** Arguments: [stackFrame] - Reference to the managed stack frame. +** [paramIndex] - Index of parameter passed from managed code. This parameter will be updated now. +** [pByteParam] - Reference to pointer filled by the function. +** On return pParam points to native C++ array with values passed from managed code. +** This variable is filled with value passed from managed code. +** [pParam] - Address of reference parameter passed from managed code. Filled by the function. +** +** Returns: S_OK on success or error in case of paramter mismatch or invalid data passed from managed code. +**********************************************************************/ +HRESULT Interop_Marshal_bool_ByRef ( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, UINT32 paramIndex, UINT8 *&pParam ); +HRESULT Interop_Marshal_UINT8_ByRef ( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, UINT32 paramIndex, UINT8 *&pParam ); +HRESULT Interop_Marshal_UINT16_ByRef( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, UINT32 paramIndex, UINT16 *&pParam ); +HRESULT Interop_Marshal_UINT32_ByRef( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, UINT32 paramIndex, UINT32 *&pParam ); +HRESULT Interop_Marshal_UINT64_ByRef( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, UINT32 paramIndex, UINT64 *&pParam ); +HRESULT Interop_Marshal_CHAR_ByRef ( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, UINT32 paramIndex, CHAR *&pParam ); +HRESULT Interop_Marshal_INT8_ByRef ( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, UINT32 paramIndex, INT8 *&pParam ); +HRESULT Interop_Marshal_INT16_ByRef ( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, UINT32 paramIndex, INT16 *&pParam ); +HRESULT Interop_Marshal_INT32_ByRef ( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, UINT32 paramIndex, INT32 *&pParam ); +HRESULT Interop_Marshal_INT64_ByRef ( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, UINT32 paramIndex, INT64 *&pParam ); +#if !defined(TINYCLR_EMULATED_FLOATINGPOINT) +HRESULT Interop_Marshal_float_ByRef ( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, UINT32 paramIndex, float *&pParam ); +HRESULT Interop_Marshal_double_ByRef( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, UINT32 paramIndex, double *&pParam ); +#else +HRESULT Interop_Marshal_float_ByRef ( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, UINT32 paramIndex, INT32 *&pParam ); +HRESULT Interop_Marshal_double_ByRef( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, UINT32 paramIndex, INT64 *&pParam ); + +#endif + + +// For unsuppoted types return NULL reference + +HRESULT Interop_Marshal_UNSUPPORTED_TYPE_ByRef( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, UINT32 paramIndex, UNSUPPORTED_TYPE *&pParam ); +/********************************************************************** +** +** Function: Interop_Marshal_StoreRef +** +** Synopsis: This function is used to store updated parameter or basic type passed by reference from managed code. +** It stores data from heap block pointed by pVoidHeapBlock back to the managed stack frame. +** +** Arguments: [stackFrame] - Reference to the managed stack frame. +** [pVoidHeapBlock] - Pointer to heap block that keeps updated basic type value +** [paramIndex] - Index of parameter passed from managed code. This parameter will be updated now. +** +** Returns: S_OK on success or error from StoreToReference. Error return would cause exception thrown in managed code. +**********************************************************************/ +HRESULT Interop_Marshal_StoreRef( CLR_RT_StackFrame &stackFrame, void *pVoidHeapBlock, UINT32 paramIndex ); + +/********************************************************************** +** +** Function: Interop_Marshal_RetrieveManagedObject +** +** Synopsis: Retrieves pointer to managed object from managed stack frame. +** +** Arguments: [stackFrame] - Reference to the managed stack frame. +** +** Returns: Pointer to managed object or NULL in case of error. +**********************************************************************/ +CLR_RT_HeapBlock* Interop_Marshal_RetrieveManagedObject( CLR_RT_StackFrame &stackFrame ); + +/********************************************************************** +** +** Functions: Interop_Marshal_GetField_ +** +** Synopsis: Retrieves C++ reference ( pointer ) to the field in managed object. +** +** Arguments: [pThis] - Pointer to the managed object retrieved by Interop_Marshal_RetrieveManagedObject. +** [fieldIndex] - Field index. +** +** Returns: Reference to the field. +**********************************************************************/ +UINT8 &Interop_Marshal_GetField_bool ( CLR_RT_HeapBlock *pThis, UINT32 fieldIndex ); +UINT8 &Interop_Marshal_GetField_UINT8 ( CLR_RT_HeapBlock *pThis, UINT32 fieldIndex ); +UINT16 &Interop_Marshal_GetField_UINT16( CLR_RT_HeapBlock *pThis, UINT32 fieldIndex ); +UINT32 &Interop_Marshal_GetField_UINT32( CLR_RT_HeapBlock *pThis, UINT32 fieldIndex ); +UINT64 &Interop_Marshal_GetField_UINT64( CLR_RT_HeapBlock *pThis, UINT32 fieldIndex ); +CHAR &Interop_Marshal_GetField_CHAR ( CLR_RT_HeapBlock *pThis, UINT32 fieldIndex ); +INT8 &Interop_Marshal_GetField_INT8 ( CLR_RT_HeapBlock *pThis, UINT32 fieldIndex ); +INT16 &Interop_Marshal_GetField_INT16 ( CLR_RT_HeapBlock *pThis, UINT32 fieldIndex ); +INT32 &Interop_Marshal_GetField_INT32 ( CLR_RT_HeapBlock *pThis, UINT32 fieldIndex ); +INT64 &Interop_Marshal_GetField_INT64 ( CLR_RT_HeapBlock *pThis, UINT32 fieldIndex ); +//----------------- Float point types - float and double +#if !defined(TINYCLR_EMULATED_FLOATINGPOINT) +float &Interop_Marshal_GetField_float ( CLR_RT_HeapBlock *pThis, UINT32 fieldIndex ); +double &Interop_Marshal_GetField_double( CLR_RT_HeapBlock *pThis, UINT32 fieldIndex ); +#else +INT32 &Interop_Marshal_GetField_float ( CLR_RT_HeapBlock *pThis, UINT32 fieldIndex ); +INT64 &Interop_Marshal_GetField_double( CLR_RT_HeapBlock *pThis, UINT32 fieldIndex ); +#endif + +// For all other unsupported types we always return NULL reference. +UNSUPPORTED_TYPE &Interop_Marshal_GetField_UNSUPPORTED_TYPE( CLR_RT_HeapBlock *pThis, UINT32 fieldIndex ); + +/********************************************************************** +** +** Function Signatures that should be supported by drivers to enable managed callbacks. +** +** InitializeInterruptsProc +** This driver function is called in native code by constructor of managed NativeEventDispatcher object. +** Parameters: +** [pContext] - Pointer to the context that should be passed to the ISR ( INterrupt Service Routine ). +** [userData] - User data passed to constructor of NativeEventDispatcher. +**********************************************************************/ +typedef HRESULT (*InitializeInterruptsProc )( CLR_RT_HeapBlock_NativeEventDispatcher *pContext, UINT64 userData ); + +/********************************************************************** +** EnableorDisableInterruptsProc +** This function is called by EnableInterrupt/DisableInterrupt functions of managed NativeEventDispatcher object. +** It should enable or disable HW interrupts. +** [pContext] - Pointer to the context, same as passed to InitializeInterruptsProc +** [fEnable] - If "true" - enable interrupts +** If "false" - disable interrupts +**********************************************************************/ +typedef HRESULT (*EnableorDisableInterruptsProc)( CLR_RT_HeapBlock_NativeEventDispatcher *pContext, bool fEnable ); + +/********************************************************************** +** +** CleanupInterruptsProc +** This function is called to release hardware that generates interrups and release associated resources +** [pContext] - Pointer to the context, same as passed to InitializeInterruptsProc +** +**********************************************************************/ +typedef HRESULT (*CleanupInterruptsProc)( CLR_RT_HeapBlock_NativeEventDispatcher *pContext ); + +/********************************************************************** +** +** InterruptServiceProc +** This is the prototype for the interrupt service routie. +** [pContext] - Pointer to the context, same as passed to InitializeInterruptsProc +** +** This function should call SaveNativeEventToHALQueue in order to create managed callback. +** The minimal implementation for this function would be: +** static void ISR_TestProc( CLR_RT_HeapBlock_NativeEventDispatcher *pContext ) +** +** { +** GLOBAL_LOCK(irq); +** // To do - Initialize userData1 and userData2 to userData. +** UINT32 userData1; +** UINT32 userData2; +** // Saves data to queue. Each call to SaveNativeEventToHALQueue initiates managed callback. +** SaveNativeEventToHALQueue( pContext, userData1, userData2 ); +** } +**********************************************************************/ +typedef HRESULT (*InterruptServiceProc)( CLR_RT_HeapBlock_NativeEventDispatcher *pContext ); + + + +/********************************************************************** +** +** Structure that keeps pointers to driver functions. +** The driver functions are accessed by CLR through global instance of this structure. +** See Spot_InteropSample_Native_Microsoft_SPOT_Interop_TestCallback.cpp file for use of this structure. +** +**********************************************************************/ +struct CLR_RT_DriverInterruptMethods + +{ + InitializeInterruptsProc m_InitProc; + EnableorDisableInterruptsProc m_EnableProc; + CleanupInterruptsProc m_CleanupProc; +}; + +// Randomly generated 32 bit number. +// This check sum validates that m_pNativeMethods points to CLR_RT_DriverInterruptMethods structure +#define DRIVER_INTERRUPT_METHODS_CHECKSUM 0xf32f4c3e + +// Creates instance of CLR_RT_HeapBlock_NativeEventDispatcher. +CLR_RT_HeapBlock_NativeEventDispatcher *CreateNativeEventInstance( CLR_RT_StackFrame& stack ); + +// Saves data from ISR. The data from this queue is used to call managed callbacks. +// Should be called from ISR. +void SaveNativeEventToHALQueue( CLR_RT_HeapBlock_NativeEventDispatcher *pContext, UINT32 data1, UINT32 data2 ); + +// Cleans up the data in the queue after interrupts were closed and no managed callbacks are expected. +void CleanupNativeEventsFromHALQueue( CLR_RT_HeapBlock_NativeEventDispatcher *pContext ); + +void CLR_RetrieveCurrentMethod( UINT32& assmIdx, UINT32& methodIdx ); + +void CLR_SoftReboot(); + +void CLR_DebuggerBreak(); + +#endif // _TINYCLR_INTEROP_H_ + + diff --git a/src/CLR/Include/TinyCLR_Messaging.h b/src/CLR/Include/TinyCLR_Messaging.h index 558f564671..c30b765804 100644 --- a/src/CLR/Include/TinyCLR_Messaging.h +++ b/src/CLR/Include/TinyCLR_Messaging.h @@ -1,6 +1,6 @@ // // Copyright (c) 2017 The nanoFramework project contributors -// Copyright (c) Microsoft Corporation. All rights reserved. +// Portions Copyright (c) Microsoft Corporation. All rights reserved. // See LICENSE file in the project root for full license information. // #ifndef _TINYCLR_MESSAGING_H_ @@ -171,12 +171,6 @@ struct CLR_Messaging static bool Messaging_Send__Reply ( WP_Message* msg, void* owner ); static bool Messaging_Reply ( WP_Message* msg, void* owner ); static bool Messaging_Reply__Reply ( WP_Message* msg, void* owner ); -#if defined(NETMF_TARGET_BIG_ENDIAN) -public: - static void SwapDebuggingValue ( UINT8* &msg, UINT32 size ); - static void SwapEndian ( WP_Message* msg, void* ptr, int size, bool fReply ); - static UINT32 SwapEndianPattern ( UINT8* &buffer, UINT32 size, UINT32 count=1 ); -#endif }; //--// diff --git a/src/CLR/Include/TinyCLR_PlatformDef.h b/src/CLR/Include/TinyCLR_PlatformDef.h new file mode 100644 index 0000000000..32f1c0ad60 --- /dev/null +++ b/src/CLR/Include/TinyCLR_PlatformDef.h @@ -0,0 +1,293 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _TINYCLR_PLATFORMDEF_H_ +#define _TINYCLR_PLATFORMDEF_H_ + +//#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// PLATFORMS GENERAL DEFINITIONS +#if defined(_WIN32_WCE) +#define PLATFORM_WINCE +#define TINYCLR_STOP() ::DebugBreak() +#elif defined(_WIN32) +#define TINYCLR_STOP() ::DebugBreak() +#pragma warning( error : 4706 ) // error C4706: assignment within conditional expression +#elif defined(arm) || defined(__arm) || defined(__GNUC__) + +#define PLATFORM_ARM +#define TINYCLR_STOP() HARD_BREAKPOINT() +#elif defined(__ADSPBLACKFIN__) +#define TINYCLR_STOP() +#define PLATFORM_BLACKFIN +#elif defined(__RENESAS__) +#define TINYCLR_STOP() +#define PLATFORM_SH +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// DEFINITIONS +#define TINYCLR_VALIDATE_HEAP_0_None 0 // No Trace +#define TINYCLR_VALIDATE_HEAP_1_HeapBlocksAndUnlink 1 // Validate HeapBlocks and Unlink. +#define TINYCLR_VALIDATE_HEAP_2_DblLinkedList 2 // Validate a DblLinkedList before each operation. +#define TINYCLR_VALIDATE_HEAP_3_Compaction 3 // Trace Compaction +#define TINYCLR_VALIDATE_HEAP_4_CompactionPlus 4 // Trace Compaction Plus + +#define TINYCLR_MAX_ASSEMBLY_NAME 128 + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// FEATURES + + +#if defined(PLATFORM_EMULATED_FLOATINGPOINT) +#define TINYCLR_EMULATED_FLOATINGPOINT // use the fixed point floating point notation in the clr ocdes +#endif + +#if !defined(TINYCLR_NO_APPDOMAINS) +#define TINYCLR_APPDOMAINS // enables application doman support +#endif +#define TINYCLR_TRACE_EXCEPTIONS // enables exception dump support +#define TINYCLR_TRACE_ERRORS // enables rich exception dump support +#if defined(DEBUG) || defined(_DEBUG) +#define TINYCLR_TRACE_STACK // enables rich eval stack tracing +#endif +//#define TINYCLR_TRACE_HRESULT // enable tracing of HRESULTS from interop libraries + +//-o-//-o-//-o-//-o-//-o-//-o-// +// PLATFORMS +//-o-//-o-//-o-//-o-//-o-//-o-// + + +//--// +// Setting the threshold value to start Garbagge collector +// PLATFORM_DEPENDENT_HEAP_SIZE_THRESHOLD should set in the file platform.settings file, eg sam7x_ek.settings. +// defaults are 32Kb and 48 kb for lower and upper threshold respectively + +#ifdef PLATFORM_DEPENDENT_HEAP_SIZE_THRESHOLD +#define HEAP_SIZE_THRESHOLD PLATFORM_DEPENDENT_HEAP_SIZE_THRESHOLD +#else +#define HEAP_SIZE_THRESHOLD 48 * 1024 +#endif + +#ifdef PLATFORM_DEPENDENT_HEAP_SIZE_THRESHOLD_UPPER +#define HEAP_SIZE_THRESHOLD_UPPER PLATFORM_DEPENDENT_HEAP_SIZE_THRESHOLD_UPPER +#else +#define HEAP_SIZE_THRESHOLD_UPPER HEAP_SIZE_THRESHOLD + 16 * 1024 +#endif + +//--// + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// WINDOWS +#if defined(_WIN32) +#define TINYCLR_GC_VERBOSE +#define TINYCLR_TRACE_MEMORY_STATS +#define TINYCLR_PROFILE_NEW +#define TINYCLR_PROFILE_NEW_CALLS +#define TINYCLR_PROFILE_NEW_ALLOCATIONS +#if defined(DEBUG) || defined(_DEBUG) +#define TINYCLR_VALIDATE_HEAP TINYCLR_VALIDATE_HEAP_2_DblLinkedList +//#define TINYCLR_TRACE_MALLOC +#define TINYCLR_FILL_MEMORY_WITH_DIRTY_PATTERN +#define TINYCLR_TRACE_EARLYCOLLECTION +#define TINYCLR_DELEGATE_PRESERVE_STACK +#define TINYCLR_VALIDATE_APPDOMAIN_ISOLATION +#define TINYCLR_TRACE_HRESULT // enable tracing of HRESULTS from interop libraries +#else //RELEASE +#define TINYCLR_VALIDATE_HEAP TINYCLR_VALIDATE_HEAP_0_None +#endif +#define TINYCLR_ENABLE_SOURCELEVELDEBUGGING +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// ARM +#if defined(PLATFORM_ARM) +#define TINYCLR_TRACE_MEMORY_STATS +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// BLACKFIN +#if defined(PLATFORM_BLACKFIN) +#define TINYCLR_TRACE_MEMORY_STATS +#endif + + +// RENESAS +#if defined(PLATFORM_SH) +#define TINYCLR_TRACE_MEMORY_STATS +#endif + +//-o-//-o-//-o-//-o-//-o-//-o-// +// RULES AND DEPENDENCIES +//-o-//-o-//-o-//-o-//-o-//-o-// + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// GENERAL RTM RULES +#if defined(BUILD_RTM) || defined(PLATFORM_NO_CLR_TRACE) +#undef TINYCLR_TRACE_MEMORY_STATS +#undef TINYCLR_TRACE_EXCEPTIONS +#undef TINYCLR_TRACE_ERRORS +#undef TINYCLR_TRACE_EARLYCOLLECTION +#undef TINYCLR_VALIDATE_HEAP +#undef TINYCLR_FILL_MEMORY_WITH_DIRTY_PATTERN +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// TRACE DEPENDENCIES +#if defined(_WIN32) +#define TINYCLR_OPCODE_NAMES +#define TINYCLR_OPCODE_PARSER +#define TINYCLR_OPCODE_STACKCHANGES +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if !defined(TINYCLR_VALIDATE_HEAP) +#define TINYCLR_VALIDATE_HEAP TINYCLR_VALIDATE_HEAP_0_None +#endif + +#if defined(TINYCLR_PROFILE_NEW_CALLS) && !defined(TINYCLR_PROFILE_HANDLER) +#define TINYCLR_PROFILE_HANDLER +#endif + +//-o-//-o-//-o-//-o-//-o-//-o-// +// CODE +//-o-//-o-//-o-//-o-//-o-//-o-// + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// LANGUAGE +#if defined(_WIN32) +#define PROHIBIT_ALL_CONSTRUCTORS(cls) \ + private: \ + cls(); \ + cls( cls& ); \ + cls& operator=( const cls& ) + +#define PROHIBIT_COPY_CONSTRUCTORS(cls) \ + public: \ + cls() {} \ + private: \ + cls( cls& ); \ + cls& operator=( const cls& ) + +#define PROHIBIT_COPY_CONSTRUCTORS2(cls) \ + private: \ + cls( cls& ); \ + cls& operator=( const cls& ) + +#define LONGLONGCONSTANT(v) (v##I64) +#define ULONGLONGCONSTANT(v) (v##UI64) +#endif + +#if defined(PLATFORM_ARM) || defined(PLATFORM_BLACKFIN) || defined(PLATFORM_SH) +#define PROHIBIT_ALL_CONSTRUCTORS(cls) \ + private: \ + cls(); \ + cls( cls& ); \ + cls& operator=( const cls& ) + +#define PROHIBIT_COPY_CONSTRUCTORS(cls) \ + public: \ + cls() {} \ + private: \ + cls( cls& ); \ + cls& operator=( const cls& ) + +#define PROHIBIT_COPY_CONSTRUCTORS2(cls) \ + private: \ + cls( cls& ); \ + cls& operator=( const cls& ) + +#define LONGLONGCONSTANT(v) (v##ll) +#define ULONGLONGCONSTANT(v) (v##ull) +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +// INCLUDES +#if defined(_WIN32) + +#if !defined(PLATFORM_WINCE) +#define _WIN32_WINNT 0x0501 +#endif + +//Unsafe string functions be avoided, but there isn't a safe crt for the arm, so +//a bunch of macros, cleanup code needs to be done first + +#include +#include +#include + +#if !defined(PLATFORM_WINCE) +#include +#endif + +#include +#include +#include +#include + +#else + +#include + +#include +#include +#include +#include + +#ifndef MAKE_HRESULT +#define MAKE_HRESULT(sev,fac,code) \ + ((HRESULT) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) ) +#endif + +#ifndef SEVERITY_SUCCESS +#define SEVERITY_SUCCESS 0 +#endif + +#ifndef SEVERITY_ERROR +#define SEVERITY_ERROR 1 +#endif + +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#include + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(TINYCLR_PROFILE_NEW_CALLS) && !defined(TINYCLR_PROFILE_NEW) +!ERROR "TINYCLR_PROFILER_NEW is required for TINYCLR_PROFILE_NEW_CALLS" +#endif + +#if defined(TINYCLR_PROFILE_NEW_ALLOCATIONS) && !defined(TINYCLR_PROFILE_NEW) +!ERROR "TINYCLR_PROFILER_NEW is required for TINYCLR_PROFILE_NEW_ALLOCATIONS" +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(_WIN32_WCE) + +#if (_WIN32_WCE == 0x420) +#define ENUMLOGFONTEXW ENUMLOGFONT +struct OUTLINETEXTMETRICW; +#endif //(_WIN32_WCE == 0x420) + +extern BOOL IsDebuggerPresent(); +#define swscanf_s(buf,format, ...) swscanf( buf, format, __VA_ARGS__ ) +#define wcstok_s(strToken, strDelimit, context) wcstok( strToken,strDelimit ) +extern void *bsearch( const void *key, const void *base, size_t num, size_t width, int (*compare)( const void *, const void * ) ); +#endif //#if defined(PLATFORM_WINCE) + + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#endif // _TINYCLR_PLATFORMDEF_H_ + diff --git a/src/CLR/Include/TinyCLR_Profiling.h b/src/CLR/Include/TinyCLR_Profiling.h new file mode 100644 index 0000000000..ed336180c7 --- /dev/null +++ b/src/CLR/Include/TinyCLR_Profiling.h @@ -0,0 +1,219 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _TINYCLR_PROFILING_H_ +#define _TINYCLR_PROFILING_H_ + +#if defined(TINYCLR_PROFILE_NEW) + +/* + * See RFC2234 for Augmented Backus Naur form documentation. + * All terminal literals are bits, not ASCII characters. + * Bits are packed such that the first bit goes to the most significant bit, + * the second goes to the second-most significant, etc. + +short = 16BIT +int = 32BIT +long = 64BIT +pointer = 32BIT +datatype = 8BIT +typedef-idx = 32BIT +method-idx = 32BIT + TinyCLR Method_Idx value for identifying a specific function + +stream-packet = sequence-id length stream-payload + A chunk of data sent out over the WireProtocol. + +sequence-id = short + Number used to order the packets + +length = short + Number in bits in stream-payload + +stream-payload = *profiler-packet + Payload is a sequence of profiler packets. + +profiling-stream = *stream-payload + The reconstructed stream of data to be processed. + +profiler-packet = timestamp-packet / memory-layout-packet heapdump-start-packet / heapdump-root-packet / + heapdump-object-packet / heapdump-stop-packet + +timestamp-header = "0000001" +timestamp-time = long +timestamp-packet = timestamp-header timestamp-time + Marks time intervals to allow object lifetime estimates and histograms + +memory-layout-packet = memory-layout-header memory-layout-heap-address memory-layout-heap-length +memory-layout-header = "00000010" +memory-layout-heap-address = pointer +memory-layout-heap-length = int + Contains heap layout information useful for showing memory usage statistics. + +heapdump = heapdump-start-packet *heapdump-root-packet *heapdump-object-packet heapdump-stop-packet + Heapdumps always occur in this form. All roots are listed before all objects, and both roots and objects fall between + a pair of 'start' and 'stop' packets. Heap dumps may be split up across stream-payload boundaries, but they may not be + nested, and packets may not be sent in any other order. + +heapdump-start-header = "00000011" +heapdump-start-packet = heapdump-start-header + Marks the beginning of a heap dump. Multiple can exist in the same profiling-stream + if and only if there is a heapdump-stop-packet between every pair of heapdump-start-packets. + +heapdump-root-packet = heapdump-root-header ( heapdump-root-stack / heapdump-root-other ) +heapdump-root-header = "00000011" + +heapdump-root-stack = heapdump-root-stack-header method-idx +heapdump-root-stack-header = "101" + +heapdump-root-other = heapdump-root-finalizer / heapdump-root-appdomain / heapdump-root-assembly / heapdump-root-thread +heapdump-root-finalizer = "001" +heapdump-root-appdomain = "010" +heapdump-root-assembly = "011" +heapdump-root-thread = "100" + +heapdump-object-packet = heapdump-object-header heapdump-object-type heapdump-object-references +heapdump-object-header = heapdump-object-address heapdump-object-size +heapdump-object-address = pointer +heapdump-object-size = short + Size is the number of HeapBlock chunks used, not the number of bytes used. + +heapdump-object-type = heapdump-object-classvaluetype / heapdump-object-array / heapdump-object-other + +heapdump-object-classvaluetype = heapdump-object-classvaluetype-header heapdump-object-classvaluetype-typedef +heapdump-object-classvaluetype-header = "00010001" / "00010010" +heapdump-object-classvaluetype-typedef = typedef-idx + +heapdump-object-array = heapdump-object-array-header heapdump-object-array-datatype heapdump-object-array-levels +heapdump-object-array-header = "00010011" +heapdump-object-array-typedef = typedef-idx +heapdump-object-array-levels = short + Rank of the array + +heapdump-object-special-cases = heapdump-object-classvaluetype-header / heapdump-object-array-header +heapdump-object-other = datatype + datatype must not be one of ; If it is, the appropriate special case should be used instead. + +heapdump-object-references = *heapdump-object-reference heapdump-object-end-of-references +heapdump-object-reference = "1" pointer +heapdump-object-end-of-references = "0" + +heapdump-stop-packet = heapdump-stop-header heapdump-stop-blocks-used + Used to mark the end of a specific heap-dump. Must not follow another + unless another came first. + +heapdump-stop-header = "00000110" +heapdump-stop-blocks-used = int + Reports how many heap-blocks were used by objects, including objects that might have been filtered out from reporting. + + */ + +class CLR_PRF_CMDS +{ + public: + static const CLR_UINT32 c_Profiling_Timestamp = 0x01; + static const CLR_UINT32 c_Profiling_Memory_Layout = 0x02; + + static const CLR_UINT32 c_Profiling_HeapDump_Start = 0x03; + static const CLR_UINT32 c_Profiling_HeapDump_Root = 0x04; + static const CLR_UINT32 c_Profiling_HeapDump_Object = 0x05; + static const CLR_UINT32 c_Profiling_HeapDump_Stop = 0x06; + + static const CLR_UINT32 c_Profiling_Calls_Call = 0x07; + static const CLR_UINT32 c_Profiling_Calls_Return = 0x08; + static const CLR_UINT32 c_Profiling_Calls_CtxSwitch = 0x09; + + static const CLR_UINT32 c_Profiling_Allocs_Alloc = 0x0a; + static const CLR_UINT32 c_Profiling_Allocs_Relloc = 0x0b; + static const CLR_UINT32 c_Profiling_Allocs_Delete = 0x0c; + + static const CLR_UINT32 c_Profiling_GarbageCollect_Begin = 0x0d; + static const CLR_UINT32 c_Profiling_GarbageCollect_End = 0x0e; + + static const CLR_UINT32 c_Profiling_HeapCompact_Begin = 0x0f; + static const CLR_UINT32 c_Profiling_HeapCompact_End = 0x10; + + class Bits + { + public: + static const CLR_UINT32 CommandHeader = 8; + static const CLR_UINT32 DataType = 8; + static const CLR_UINT32 NibbleCount = 3; + static const CLR_UINT32 RootTypes = 3; + static const CLR_UINT32 TimestampShift = 8; + static const CLR_UINT32 CallTimingShift = 4; + }; + + class RootTypes + { + public: + static const CLR_UINT32 Root_Finalizer = 0x01; + static const CLR_UINT32 Root_AppDomain = 0x02; + static const CLR_UINT32 Root_Assembly = 0x03; + static const CLR_UINT32 Root_Thread = 0x04; + static const CLR_UINT32 Root_Stack = 0x05; + }; +}; + +struct CLR_PRF_Profiler +{ + // This is not implemented: + // Write formatter functions to send only as many bits as needed for uint32,uint64 numbers, cast bytes, etc. + static HRESULT CreateInstance(); + static HRESULT DeleteInstance(); + + HRESULT Stream_Send(); + HRESULT Stream_Flush(); + + HRESULT Profiler_Cleanup(); + HRESULT DumpHeap(); + +#if defined(TINYCLR_PROFILE_NEW_CALLS) + HRESULT RecordContextSwitch( CLR_RT_Thread* nextThread ); + HRESULT RecordFunctionCall( CLR_RT_Thread* th, CLR_RT_MethodDef_Index md ); + HRESULT RecordFunctionReturn( CLR_RT_Thread* th, CLR_PROF_CounterCallChain& prof ); +#endif + +#if defined(TINYCLR_PROFILE_NEW_ALLOCATIONS) + void TrackObjectCreation( CLR_RT_HeapBlock* ptr ); + void TrackObjectDeletion( CLR_RT_HeapBlock* ptr ); + void TrackObjectRelocation(); + void RecordGarbageCollectionBegin(); + void RecordGarbageCollectionEnd(); + void RecordHeapCompactionBegin(); + void RecordHeapCompactionEnd(); +#endif + + void SendMemoryLayout(); + +private: + void SendTrue(); + void SendFalse(); + void Timestamp(); + void PackAndWriteBits( CLR_UINT32 value ); + void PackAndWriteBits( const CLR_RT_TypeDef_Index& typeDef ); + void PackAndWriteBits( const CLR_RT_MethodDef_Index& methodDef ); + CLR_RT_HeapBlock* FindReferencedObject( CLR_RT_HeapBlock* ref ); + HRESULT DumpRoots(); + void DumpRoot( CLR_RT_HeapBlock* root, CLR_UINT32 type, CLR_UINT32 flags, CLR_RT_MethodDef_Index* source ); + void DumpObject( CLR_RT_HeapBlock* ptr ); + void DumpEndOfRefsList(); + void DumpPointer( void* ref ); + void DumpSingleReference( CLR_RT_HeapBlock* ptr ); + void DumpListOfReferences( CLR_RT_DblLinkedList& list ); + void DumpListOfReferences( CLR_RT_HeapBlock* firstItem, CLR_UINT16 count ); + + CLR_RT_HeapBlock_MemoryStream* m_stream; + CLR_UINT16 m_packetSeqId; + CLR_UINT32 m_lastTimestamp; + CLR_IDX m_currentAssembly; + int m_currentThreadPID; +}; + +extern CLR_PRF_Profiler g_CLR_PRF_Profiler; + +#endif //defined(TINYCLR_PROFILE_NEW) +#endif // _TINYCLR_PROFILING_H_ + diff --git a/src/CLR/Include/TinyCLR_Runtime.h b/src/CLR/Include/TinyCLR_Runtime.h new file mode 100644 index 0000000000..458e8117e4 --- /dev/null +++ b/src/CLR/Include/TinyCLR_Runtime.h @@ -0,0 +1,3270 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _TINYCLR_RUNTIME_H_ +#define _TINYCLR_RUNTIME_H_ + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +struct CLR_RADIAN +{ + short cos; + short sin; +}; + +extern const CLR_RADIAN c_CLR_radians[]; + +#if defined(PLATFORM_WINCE) +#include // Required to import WinCE / XMLDOM stuff.... +#endif + +//--// + +#if defined(_WIN32) + +#include +#include +#include +#include +#include +#include +#include + +typedef std::set< std::wstring > CLR_RT_StringSet; +typedef CLR_RT_StringSet::iterator CLR_RT_StringSetIter; + +typedef std::map< std::string,int > CLR_RT_StringMap; +typedef CLR_RT_StringMap::iterator CLR_RT_StringMapIter; + +typedef std::vector< std::wstring > CLR_RT_StringVector; +typedef CLR_RT_StringVector::iterator CLR_RT_StringVectorIter; + +typedef std::map< std::wstring, CLR_UINT32 > CLR_RT_SymbolToAddressMap; +typedef CLR_RT_SymbolToAddressMap::iterator CLR_RT_SymbolToAddressMapIter; + +typedef std::map< CLR_UINT32, std::wstring > CLR_RT_AddressToSymbolMap; +typedef CLR_RT_AddressToSymbolMap::iterator CLR_RT_AddressToSymbolMapIter; +#endif + +#if defined(_MSC_VER) +#pragma pack(push, TINYCLR_RUNTIME_H, 4) +#endif + +#if defined(_WIN32) +//--// + +#define _COM_SMRT_PTR(i) typedef _com_ptr_t<_com_IIID> i ## Ptr +#define _COM_SMRT_PTR_2(i,u) typedef _com_ptr_t<_com_IIID> i ## Ptr + + +_COM_SMRT_PTR(IXMLDOMDocument); +_COM_SMRT_PTR(IXMLDOMNode); + +class CLR_XmlUtil +{ + IXMLDOMDocumentPtr m_xddDoc; + IXMLDOMNodePtr m_xdnRoot; + HANDLE m_hEvent; // Used to abort a download. + DWORD m_dwTimeout; // Used to limit a download. + + void Init (); + void Clean(); + + HRESULT LoadPost( /*[in] */ LPCWSTR szRootTag , + /*[out]*/ bool& fLoaded , + /*[out]*/ bool* fFound ); + + HRESULT CreateParser(); + +public: + CLR_XmlUtil( /*[in]*/ const CLR_XmlUtil& xml ); + CLR_XmlUtil( /*[in]*/ IXMLDOMDocument* xddDoc , /*[in]*/ LPCWSTR szRootTag = NULL ); + CLR_XmlUtil( /*[in]*/ IXMLDOMNode* xdnRoot = NULL, /*[in]*/ LPCWSTR szRootTag = NULL ); + + ~CLR_XmlUtil(); + + + CLR_XmlUtil& operator=( /*[in]*/ const CLR_XmlUtil& xml ); + CLR_XmlUtil& operator=( /*[in]*/ IXMLDOMNode* xdnRoot ); + + HRESULT DumpError(); + + HRESULT New ( /*[in]*/ IXMLDOMNode* xdnRoot , /*[in] */ BOOL fDeep = false ); + HRESULT New ( /*[in]*/ LPCWSTR szRootTag, /*[in] */ LPCWSTR szEncoding = L"utf-8" /*L"unicode"*/ ); + HRESULT Load ( /*[in ]*/ LPCWSTR szFile , /*[in]*/ LPCWSTR szRootTag, /*[out]*/ bool& fLoaded, /*[out]*/ bool* fFound = NULL ); + HRESULT LoadAsStream( /*[in ]*/ IUnknown* pStream , /*[in]*/ LPCWSTR szRootTag, /*[out]*/ bool& fLoaded, /*[out]*/ bool* fFound = NULL ); + HRESULT LoadAsString( /*[in ]*/ BSTR bstrData, /*[in]*/ LPCWSTR szRootTag, /*[out]*/ bool& fLoaded, /*[out]*/ bool* fFound = NULL ); + HRESULT Save ( /*[in ]*/ LPCWSTR szFile ); + HRESULT SaveAsStream( /*[out]*/ IUnknown* *ppStream ); + HRESULT SaveAsString( /*[out]*/ BSTR *pbstrData ); + + HRESULT SetTimeout( /*[in]*/ DWORD dwTimeout ); + HRESULT Abort ( ); + + HRESULT SetVersionAndEncoding( /*[in]*/ LPCWSTR szVersion, /*[in]*/ LPCWSTR szEncoding ); + + HRESULT GetDocument ( /*[out]*/ IXMLDOMDocument* * pVal ) const; + HRESULT GetRoot ( /*[out]*/ IXMLDOMNode* * pVal ) const; + HRESULT GetNodes ( /*[in]*/ LPCWSTR szTag, /*[out]*/ IXMLDOMNodeList* * pVal ) const; + HRESULT GetNode ( /*[in]*/ LPCWSTR szTag, /*[out]*/ IXMLDOMNode* * pVal ) const; + HRESULT CreateNode ( /*[in]*/ LPCWSTR szTag, /*[out]*/ IXMLDOMNode* * pVal, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + + HRESULT GetAttribute ( /*[in]*/ LPCWSTR szTag, /*[in]*/ LPCWSTR szAttr, /*[out]*/ IXMLDOMAttribute* * pValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT GetAttribute ( /*[in]*/ LPCWSTR szTag, /*[in]*/ LPCWSTR szAttr, /*[out]*/ _bstr_t& bstrValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT GetAttribute ( /*[in]*/ LPCWSTR szTag, /*[in]*/ LPCWSTR szAttr, /*[out]*/ std::wstring& szValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT GetAttribute ( /*[in]*/ LPCWSTR szTag, /*[in]*/ LPCWSTR szAttr, /*[out]*/ LONG& lValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT GetValue ( /*[in]*/ LPCWSTR szTag, /*[out]*/ _variant_t& vValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT GetValue ( /*[in]*/ LPCWSTR szTag, /*[out]*/ _bstr_t& bstrValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT GetValue ( /*[in]*/ LPCWSTR szTag, /*[out]*/ std::wstring& szValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + + HRESULT ModifyAttribute( /*[in]*/ LPCWSTR szTag, /*[in]*/ LPCWSTR szAttr, /*[in] */ const _bstr_t& bstrValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT ModifyAttribute( /*[in]*/ LPCWSTR szTag, /*[in]*/ LPCWSTR szAttr, /*[in] */ const std::wstring& szValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT ModifyAttribute( /*[in]*/ LPCWSTR szTag, /*[in]*/ LPCWSTR szAttr, /*[in] */ LPCWSTR szValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT ModifyAttribute( /*[in]*/ LPCWSTR szTag, /*[in]*/ LPCWSTR szAttr, /*[in] */ LONG lValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT ModifyValue ( /*[in]*/ LPCWSTR szTag, /*[in] */ const _variant_t& vValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT ModifyValue ( /*[in]*/ LPCWSTR szTag, /*[in] */ const _bstr_t& bstrValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT ModifyValue ( /*[in]*/ LPCWSTR szTag, /*[in] */ const std::wstring& szValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + + HRESULT PutAttribute ( /*[in]*/ LPCWSTR szTag, /*[in]*/ LPCWSTR szAttr, /*[in] */ IXMLDOMAttribute* * pValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT PutAttribute ( /*[in]*/ LPCWSTR szTag, /*[in]*/ LPCWSTR szAttr, /*[in] */ const _bstr_t& bstrValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT PutAttribute ( /*[in]*/ LPCWSTR szTag, /*[in]*/ LPCWSTR szAttr, /*[in] */ const std::wstring& szValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT PutAttribute ( /*[in]*/ LPCWSTR szTag, /*[in]*/ LPCWSTR szAttr, /*[in] */ LPCWSTR szValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT PutAttribute ( /*[in]*/ LPCWSTR szTag, /*[in]*/ LPCWSTR szAttr, /*[in] */ LONG lValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT PutValue ( /*[in]*/ LPCWSTR szTag, /*[in] */ const _variant_t& vValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT PutValue ( /*[in]*/ LPCWSTR szTag, /*[in] */ const _bstr_t& bstrValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT PutValue ( /*[in]*/ LPCWSTR szTag, /*[in] */ const std::wstring& szValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT PutValue ( /*[in]*/ LPCWSTR szTag, /*[in] */ LPCWSTR szValue, /*[out]*/ bool& fFound, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + + HRESULT RemoveAttribute( /*[in]*/ LPCWSTR szTag, /*[in]*/ LPCWSTR szAttr, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT RemoveValue ( /*[in]*/ LPCWSTR szTag, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); + HRESULT RemoveNode ( /*[in]*/ LPCWSTR szTag, /*[in]*/ IXMLDOMNode* pxdnNode = NULL ); +}; + +//--// + + +typedef std::vector< CLR_UINT8 > CLR_RT_Buffer; + +struct CLR_RT_FileStore +{ + static HRESULT LoadFile( LPCWSTR szFile, CLR_RT_Buffer& vec ); + static HRESULT SaveFile( LPCWSTR szFile, const CLR_RT_Buffer& vec ); + static HRESULT SaveFile( LPCWSTR szFile, const CLR_UINT8* buf, size_t size ); + + static HRESULT ExtractTokensFromFile( LPCWSTR szFileName, CLR_RT_StringVector& vec, LPCWSTR separators = L" \t", bool fNoComments = true ); + + static void ExtractTokens ( const CLR_RT_Buffer& buf , CLR_RT_StringVector& vec, LPCWSTR separators = L" \t", bool fNoComments = true ); + static void ExtractTokensFromBuffer( LPWSTR szLine, CLR_RT_StringVector& vec, LPCWSTR separators = L" \t", bool fNoComments = true ); + static void ExtractTokensFromString( LPCWSTR szLine, CLR_RT_StringVector& vec, LPCWSTR separators = L" \t" ); +}; + +#endif + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#define MAX(a,b) (a > b ? a : b) +#define MIN(a,b) (a < b ? a : b) +#define ABS(x) (x > 0 ? x : (-x)) +#define FLOOR32(x) ((CLR_INT32)x) +#define FRAC(x) (x - FLOOR32(x)) + +//////////////////////////////////////////////////////////////////////////////////////////////////// + + +struct CLR_RT_HeapBlock; +struct CLR_RT_HeapBlock_Node; + +struct CLR_RT_HeapBlock_WeakReference; +struct CLR_RT_HeapBlock_String; +struct CLR_RT_HeapBlock_Array; +struct CLR_RT_HeapBlock_Delegate; +struct CLR_RT_HeapBlock_Delegate_List; +struct CLR_RT_HeapBlock_BinaryBlob; + +struct CLR_RT_HeapBlock_Button; +struct CLR_RT_HeapBlock_Lock; +struct CLR_RT_HeapBlock_LockRequest; +struct CLR_RT_HeapBlock_Timer; +struct CLR_RT_HeapBlock_WaitForObject; +struct CLR_RT_HeapBlock_Finalizer; +struct CLR_RT_HeapBlock_MemoryStream; + +struct CLR_RT_HeapCluster; +struct CLR_RT_GarbageCollector; + +struct CLR_RT_DblLinkedList; + +#if defined(TINYCLR_APPDOMAINS) +struct CLR_RT_AppDomain; +struct CLR_RT_AppDomainAssembly; +#endif //TINYCLR_APPDOMAINS + +struct CLR_RT_Assembly; +struct CLR_RT_TypeSystem; +struct CLR_RT_TypeDescriptor; + +struct CLR_RT_Assembly_Instance; +struct CLR_RT_TypeSpec_Instance; +struct CLR_RT_TypeDef_Instance; +struct CLR_RT_MethodDef_Instance; +struct CLR_RT_FieldDef_Instance; + +struct CLR_RT_StackFrame; +struct CLR_RT_SubThread; +struct CLR_RT_Thread; +struct CLR_RT_ExecutionEngine; + +struct CLR_RT_ExecutionEngine_PerfCounters; + +struct CLR_HW_Hardware; + +typedef void (*CLR_RT_MarkingHandler )( CLR_RT_HeapBlock_BinaryBlob* ptr ); +typedef void (*CLR_RT_RelocationHandler)( CLR_RT_HeapBlock_BinaryBlob* ptr ); +typedef void (*CLR_RT_HardwareHandler )(); + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(TINYCLR_PROFILE_HANDLER) + +struct CLR_PROF_CounterSimple; +struct CLR_PROF_Counter; +struct CLR_PROF_Counter_Value; +struct CLR_PROF_Counter_Value2; +struct CLR_PROF_Handler; + +#if defined(TINYCLR_PROFILE_NEW_CALLS) + +struct CLR_PROF_CounterCallChain +{ + CLR_UINT64 m_time_exclusive; + CLR_RT_StackFrame* m_owningStackFrame; + CLR_PROF_Handler* m_owningHandler; + + + //--// + + void* Prepare ( CLR_PROF_Handler* handler ); + void Complete( CLR_UINT64& t, CLR_PROF_Handler* handler ); + + void Enter( CLR_RT_StackFrame* stack ); + void Leave( ); + + //--// + + PROHIBIT_COPY_CONSTRUCTORS(CLR_PROF_CounterCallChain); +}; +#endif + +//--// + +struct CLR_PROF_Handler +{ + static const int c_Mode_Ignore = 0; + static const int c_Mode_Plain = 1; + static const int c_Mode_Simple = 2; +#if defined(TINYCLR_PROFILE_NEW_CALLS) + static const int c_Mode_CallChain = 3; +#endif + + static bool s_initialized; + static CLR_PROF_Handler* s_current; + static volatile CLR_UINT64 s_time_overhead; + static volatile CLR_UINT64 s_time_freeze; + static volatile CLR_UINT64 s_time_adjusted; + + int m_target_Mode; + void* m_target; + + CLR_PROF_Handler* m_containing; + CLR_UINT64 m_time_correction; + CLR_UINT64 m_time_start; + + //--// + + CLR_PROF_Handler( ) { Constructor( ); } + +#if defined(TINYCLR_PROFILE_NEW_CALLS) + CLR_PROF_Handler( CLR_PROF_CounterCallChain& target ) { Constructor( target ); } +#endif + + ~CLR_PROF_Handler() { Destructor(); } + + //--// + + static void Calibrate ( ); + static void SuspendTime ( ); + static CLR_UINT64 GetFrozenTime( ); + static CLR_UINT64 ResumeTime ( ); + static CLR_UINT64 ResumeTime ( CLR_INT64 t ); + + //--// + +private: + void Constructor( ); +#if defined(TINYCLR_PROFILE_NEW_CALLS) + void Constructor( CLR_PROF_CounterCallChain& target ); +#endif + + void Destructor(); + + void Init( void* target ); + + PROHIBIT_COPY_CONSTRUCTORS2(CLR_PROF_Handler); +}; + +//--// + +#define CLR_PROF_HANDLER_SUSPEND_TIME() CLR_PROF_Handler::SuspendTime() +#define CLR_PROF_HANDLER_RESUME_TIME() CLR_PROF_Handler::ResumeTime() + +#else + +#define CLR_PROF_HANDLER_SUSPEND_TIME() +#define CLR_PROF_HANDLER_RESUME_TIME() + +#endif + +#if defined(TINYCLR_PROFILE_NEW_CALLS) + +#define CLR_PROF_HANDLER_CALLCHAIN_VOID(v) CLR_PROF_Handler v +#define CLR_PROF_HANDLER_CALLCHAIN(v,t) CLR_PROF_Handler v( t ) + +#else + +#define CLR_PROF_HANDLER_CALLCHAIN_VOID(v) +#define CLR_PROF_HANDLER_CALLCHAIN(v,t) + +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +struct CLR_RT_MemoryRange +{ + UINT8* m_location; + UINT32 m_size; + + bool LimitToRange( CLR_RT_MemoryRange& filtered, UINT8* address, UINT32 length ) const; +}; + +extern CLR_RT_MemoryRange s_CLR_RT_Heap; + +//--// + +struct CLR_RT_Memory +{ + static void ZeroFill( void* buf, size_t len ) { memset( buf, 0, len ); } + + //--// + + static void Reset ( ); + static void* SubtractFromSystem( size_t len ); + static void Release ( void* ptr ); + static void* Allocate ( size_t len, CLR_UINT32 flags = 0 ); + static void* ReAllocate ( void* ptr, size_t len ); + static void* Allocate_And_Erase( size_t len, CLR_UINT32 flags = 0 ); +}; + +//--// + +struct CLR_RT_Random +{ +private: + int m_next; + +public: + void Initialize(); + void Initialize( int seed ); + + int Next(); + +#if !defined(TINYCLR_EMULATED_FLOATINGPOINT) + double NextDouble(); +#else + CLR_INT64 NextDouble(); +#endif + void NextBytes( BYTE* buffer, UINT32 count ); +}; + +//--// + +extern void CLR_RT_GetVersion( UINT16* pMajor, UINT16* pMinor, UINT16* pBuild, UINT16* pRevision ); + +#define TINYCLR_CLEAR(ref) CLR_RT_Memory::ZeroFill( &ref, sizeof(ref) ) + +//--// + +static const int c_CLR_RT_Trace_None = 0; +static const int c_CLR_RT_Trace_Info = 1; +static const int c_CLR_RT_Trace_Verbose = 2; +static const int c_CLR_RT_Trace_Annoying = 3; +static const int c_CLR_RT_Trace_Obnoxious = 4; + +extern int s_CLR_RT_fTrace_Errors; +extern int s_CLR_RT_fTrace_Exceptions; +extern int s_CLR_RT_fTrace_Instructions; +extern int s_CLR_RT_fTrace_Memory; +extern int s_CLR_RT_fTrace_MemoryStats; +extern int s_CLR_RT_fTrace_StopOnFAILED; +extern int s_CLR_RT_fTrace_GC; +extern int s_CLR_RT_fTrace_GC_Depth; +extern int s_CLR_RT_fTrace_SimulateSpeed; +extern int s_CLR_RT_fTrace_AssemblyOverhead; + +#if defined(_WIN32) +extern int s_CLR_RT_fTrace_ARM_Execution; + +extern int s_CLR_RT_fTrace_RedirectLinesPerFile; +extern std::wstring s_CLR_RT_fTrace_RedirectOutput; +extern std::wstring s_CLR_RT_fTrace_RedirectCallChain; + +extern std::wstring s_CLR_RT_fTrace_HeapDump_FilePrefix; +extern bool s_CLR_RT_fTrace_HeapDump_IncludeCreators; + +extern bool s_CLR_RT_fTimeWarp; + +#endif + +static const int MAXHOSTNAMELEN = 256; // Typical of many sockets implementations, incl. Windows +static const int MAXTYPENAMELEN = 256; // Including terminating null byte. Enforced in MetadataProcessor. The standard imposes no limit, but we necessarily do. + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#define TINYCLR_INDEX_IS_VALID(idx) ((idx).m_data != 0) +#define TINYCLR_INDEX_IS_INVALID(idx) ((idx).m_data == 0) + +// +// IMPORTANT: THE ASSEMBLY IDX IN ALL THE CLR_RT_*_Index STRUCTURES SHOULD ALWAYS BE ENCODED THE SAME WAY!!! +// +// For details, go to "bool CLR_RT_GarbageCollector::ComputeReachabilityGraphForMultipleBlocks( CLR_RT_HeapBlock* lstExt, CLR_UINT32 numExt )" +// + +struct CLR_RT_Assembly_Index +{ + CLR_UINT32 m_data; + + //--// + + void Clear() + { + m_data = 0; + } + + void Set( CLR_UINT32 idxAssm ) + { + m_data = idxAssm << 16; + } + + //--// + + CLR_IDX Assembly() const { return (CLR_IDX)(m_data >> 16); } +}; + +struct CLR_RT_TypeSpec_Index +{ + CLR_UINT32 m_data; + + //--// + + void Clear() + { + m_data = 0; + } + + void Set( CLR_UINT32 idxAssm, CLR_UINT32 idxType ) + { + m_data = idxAssm << 16 | idxType; + } + + //--// + + CLR_IDX Assembly() const { return (CLR_IDX)(m_data >> 16); } + CLR_IDX TypeSpec() const { return (CLR_IDX)(m_data ); } +}; + +struct CLR_RT_TypeDef_Index +{ + CLR_UINT32 m_data; + + //--// + + void Clear() + { + m_data = 0; + } + + void Set( CLR_UINT32 idxAssm, CLR_UINT32 idxType ) + { + m_data = idxAssm << 16 | idxType; + } + + //--// + + CLR_IDX Assembly() const { return (CLR_IDX)(m_data >> 16); } + CLR_IDX Type () const { return (CLR_IDX)(m_data ); } +}; + +struct CLR_RT_FieldDef_Index +{ + CLR_UINT32 m_data; + + //--// + + void Clear() + { + m_data = 0; + } + + void Set( CLR_UINT32 idxAssm, CLR_UINT32 idxField ) + { + m_data = idxAssm << 16 | idxField; + } + + //--// + + CLR_IDX Assembly() const { return (CLR_IDX)(m_data >> 16); } + CLR_IDX Field () const { return (CLR_IDX)(m_data ); } +}; + +struct CLR_RT_MethodDef_Index +{ + CLR_UINT32 m_data; + + //--// + + void Clear() + { + m_data = 0; + } + + void Set( CLR_UINT32 idxAssm, CLR_UINT32 idxMethod ) + { + m_data = idxAssm << 16 | idxMethod; + } + + //--// + + CLR_IDX Assembly() const { return (CLR_IDX)(m_data >> 16); } + CLR_IDX Method () const { return (CLR_IDX)(m_data ); } +}; + +struct CLR_RT_ReflectionDef_Index +{ + CLR_UINT16 m_kind; // CLR_ReflectionType + CLR_UINT16 m_levels; + + union + { + CLR_RT_Assembly_Index m_assm; + CLR_RT_TypeDef_Index m_type; + CLR_RT_MethodDef_Index m_method; + CLR_RT_FieldDef_Index m_field; + CLR_UINT32 m_raw; + } m_data; + + //--// + + void Clear(); + + CLR_UINT32 GetTypeHash() const; + + void InitializeFromHash( CLR_UINT32 hash ); + + CLR_UINT64 GetRawData( ) const; + void SetRawData( CLR_UINT64 data ); + + //--// + + static bool Convert( CLR_RT_HeapBlock& ref, CLR_RT_Assembly_Instance& inst ); + static bool Convert( CLR_RT_HeapBlock& ref, CLR_RT_TypeDef_Instance& inst, CLR_UINT32* levels ); + static bool Convert( CLR_RT_HeapBlock& ref, CLR_RT_MethodDef_Instance& inst ); + static bool Convert( CLR_RT_HeapBlock& ref, CLR_RT_FieldDef_Instance& inst ); + static bool Convert( CLR_RT_HeapBlock& ref, CLR_UINT32& hash ); +}; + + +//--// + +struct CLR_RT_AssemblyRef_CrossReference +{ + CLR_RT_Assembly* m_target; // EVENT HEAP - NO RELOCATION - +}; + +struct CLR_RT_TypeRef_CrossReference +{ + CLR_RT_TypeDef_Index m_target; +}; + +struct CLR_RT_FieldRef_CrossReference +{ + CLR_RT_FieldDef_Index m_target; +}; + +struct CLR_RT_MethodRef_CrossReference +{ + CLR_RT_MethodDef_Index m_target; +}; + +struct CLR_RT_FieldDef_CrossReference +{ + CLR_IDX m_offset; +}; + +struct CLR_RT_TypeDef_CrossReference +{ + static const CLR_UINT32 TD_CR_StaticConstructorCalled = 0x0001; + static const CLR_UINT32 TD_CR_HasFinalizer = 0x0002; + static const CLR_UINT32 TD_CR_IsMarshalByRefObject = 0x0004; + + CLR_UINT16 m_flags; + CLR_IDX m_totalFields; + CLR_UINT32 m_hash; +}; + +struct CLR_RT_MethodDef_CrossReference +{ + static const CLR_UINT16 MD_CR_Patched = 0x8000; + static const CLR_UINT16 MD_CR_OwnerMask = 0x7FFF; + + CLR_UINT16 m_data; + + CLR_IDX GetOwner () const { return (CLR_IDX)(m_data); } +}; + +struct CLR_RT_MethodDef_Patch +{ + CLR_IDX m_orig; + CLR_IDX m_patched; +}; + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + +struct CLR_RT_MethodDef_DebuggingInfo +{ + static const CLR_UINT8 MD_DI_JustMyCode = 0x01; + static const CLR_UINT8 MD_DI_HasBreakpoint = 0x02; + + CLR_UINT8 m_flags; + + bool IsJMC () const { return IsFlagSet( MD_DI_JustMyCode ) ; } + bool HasBreakpoint() const { return IsFlagSet( MD_DI_HasBreakpoint ); } + + void SetJMC ( bool b ) { SetResetFlags( b, MD_DI_JustMyCode ); } + void SetBreakpoint( bool b ) { SetResetFlags( b, MD_DI_HasBreakpoint ); } + +private: + void SetFlags ( CLR_UINT8 flags ) { m_flags |= flags ; } + void ResetFlags ( CLR_UINT8 flags ) { m_flags &= ~flags ; } + bool IsFlagSet ( CLR_UINT8 flags ) const { return (m_flags & flags) != 0 ; } + void SetResetFlags( bool b, CLR_UINT8 flags ) { if(b) SetFlags( flags ); else ResetFlags( flags ); } +}; + +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#include + +//TODO: Change this to an extern method that is defined in the HAL +#if defined(PLATFORM_WINDOWS_EMULATOR) + #define SYSTEM_CLOCK_HZ g_HAL_Configuration_Windows.SystemClock + #define SLOW_CLOCKS_PER_SECOND g_HAL_Configuration_Windows.SlowClockPerSecond +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +struct CLR_RT_UnicodeHelper +{ + static const CLR_UINT32 SURROGATE_HALFSHIFT = 10; + static const CLR_UINT32 SURROGATE_HALFBASE = 0x00010000; + static const CLR_UINT32 SURROGATE_HALFMASK = 0x000003FF; + +#ifdef HIGH_SURROGATE_START +#undef HIGH_SURROGATE_START +#undef HIGH_SURROGATE_END +#undef LOW_SURROGATE_START +#undef LOW_SURROGATE_END +#endif + static const CLR_UINT16 HIGH_SURROGATE_START = 0xD800; + static const CLR_UINT16 HIGH_SURROGATE_END = 0xDBFF; + static const CLR_UINT16 LOW_SURROGATE_START = 0xDC00; + static const CLR_UINT16 LOW_SURROGATE_END = 0xDFFF; + + const CLR_UINT8* m_inputUTF8; + const CLR_UINT16* m_inputUTF16; + + CLR_UINT8* m_outputUTF8; + int m_outputUTF8_size; + + CLR_UINT16* m_outputUTF16; + int m_outputUTF16_size; + + //--// + + void SetInputUTF8 ( LPCSTR src ) { m_inputUTF8 = (const CLR_UINT8*)src; } + void SetInputUTF16( const CLR_UINT16* src ) { m_inputUTF16 = src; } + + int CountNumberOfCharacters( int max = -1 ); + int CountNumberOfBytes ( int max = -1 ); + + //--// + + bool ConvertFromUTF8( int iMaxChars, bool fJustMove, int iMaxBytes = -1 ); + bool ConvertToUTF8 ( int iMaxChars, bool fJustMove ); + +#if defined(_WIN32) + static void ConvertToUTF8 ( const std::wstring& src, std:: string& dst ); + static void ConvertFromUTF8( const std:: string& src, std::wstring& dst ); +#endif +}; + +class UnicodeString +{ +private: + CLR_RT_UnicodeHelper m_unicodeHelper; + CLR_RT_HeapBlock m_uHeapBlock; + CLR_UINT16* m_wCharArray; + int m_length; /// Length in wide characters (not bytes). + +public: + UnicodeString(); + ~UnicodeString(); + + HRESULT Assign( LPCSTR string ); + operator LPCWSTR() { return (LPCWSTR)m_wCharArray; } + UINT32 Length(){ return m_length; } + +private: + void Release(); +}; + +//--// + +struct CLR_RT_ArrayListHelper +{ + static const int c_defaultCapacity = 2; + + static const int FIELD__m_items = 1; + static const int FIELD__m_size = 2; + + //--// + + static HRESULT PrepareArrayList ( CLR_RT_HeapBlock& pThisRef, int count, int capacity ); + static HRESULT ExtractArrayFromArrayList( CLR_RT_HeapBlock& pThisRef, CLR_RT_HeapBlock_Array* & array, int& count, int& capacity ); +}; + +//--// + +struct CLR_RT_ByteArrayReader +{ + HRESULT Init( const UINT8* src, UINT32 srcSize ); + + HRESULT Read( void* dst, UINT32 size ); + HRESULT Read1Byte( void* dst ); + + HRESULT Skip( UINT32 size ); + + bool IsValid() { return (source && sourceSize > 0); } + + const UINT8* source; + UINT32 sourceSize; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +struct CLR_RT_SignatureParser +{ + static const int c_TypeSpec = 0; + static const int c_Interfaces = 1; + static const int c_Field = 2; + static const int c_Method = 3; + static const int c_Locals = 4; + static const int c_Object = 5; + + struct Element + { + bool m_fByRef; + int m_levels; + CLR_DataType m_dt; + CLR_RT_TypeDef_Index m_cls; + }; + + CLR_RT_HeapBlock* m_lst; + CLR_RT_Assembly* m_assm; + CLR_PMETADATA m_sig; + + int m_type; + CLR_UINT32 m_flags; + int m_count; + + //--// + + void Initialize_TypeSpec ( CLR_RT_Assembly* assm, const CLR_RECORD_TYPESPEC* ts ); + void Initialize_Interfaces ( CLR_RT_Assembly* assm, const CLR_RECORD_TYPEDEF* td ); + void Initialize_FieldDef ( CLR_RT_Assembly* assm, const CLR_RECORD_FIELDDEF* fd ); + void Initialize_MethodSignature( CLR_RT_Assembly* assm, const CLR_RECORD_METHODDEF* md ); + void Initialize_MethodLocals ( CLR_RT_Assembly* assm, const CLR_RECORD_METHODDEF* md ); + + void Initialize_TypeSpec ( CLR_RT_Assembly* assm, CLR_PMETADATA ts ); + void Initialize_FieldDef ( CLR_RT_Assembly* assm, CLR_PMETADATA fd ); + void Initialize_MethodSignature( CLR_RT_Assembly* assm, CLR_PMETADATA md ); + + void Initialize_Objects ( CLR_RT_HeapBlock* lst, int count, bool fTypes ); + + int Available() const { return m_count; } + + HRESULT Advance( Element& res ); +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#define TINYCLR_FOREACH_ASSEMBLY(ts) \ + { \ + CLR_RT_Assembly** ppASSM = (ts).m_assemblies; \ + size_t iASSM = (ts).m_assembliesMax; \ + for( ;iASSM--; ppASSM++) \ + { \ + CLR_RT_Assembly* pASSM = *ppASSM; \ + if(pASSM) + +#define TINYCLR_FOREACH_ASSEMBLY_END() \ + } \ + } + +#define TINYCLR_FOREACH_ASSEMBLY_NULL(ts) \ + { \ + CLR_RT_Assembly** ppASSM = (ts).m_assemblies; \ + size_t iASSM = ARRAYSIZE((ts).m_assemblies); \ + CLR_IDX idx = 1; \ + for( ;iASSM--; ppASSM++,idx++) \ + { \ + if(*ppASSM == NULL) + +#define TINYCLR_FOREACH_ASSEMBLY_NULL_END() \ + } \ + } + +#if defined(TINYCLR_APPDOMAINS) + #define TINYCLR_FOREACH_ASSEMBLY_IN_APPDOMAIN(ad) \ + TINYCLR_FOREACH_NODE(CLR_RT_AppDomainAssembly, appDomainAssembly, (ad)->m_appDomainAssemblies) \ + { \ + CLR_RT_Assembly* pASSM = appDomainAssembly->m_assembly; + + #define TINYCLR_FOREACH_ASSEMBLY_IN_APPDOMAIN_END() \ + } \ + TINYCLR_FOREACH_NODE_END() + + #define TINYCLR_FOREACH_ASSEMBLY_IN_CURRENT_APPDOMAIN(ts) TINYCLR_FOREACH_ASSEMBLY_IN_APPDOMAIN(g_CLR_RT_ExecutionEngine.GetCurrentAppDomain()) + #define TINYCLR_FOREACH_ASSEMBLY_IN_CURRENT_APPDOMAIN_END() TINYCLR_FOREACH_ASSEMBLY_IN_APPDOMAIN_END() +#else + #define TINYCLR_FOREACH_ASSEMBLY_IN_APPDOMAIN(ts, ad) TINYCLR_FOREACH_ASSEMBLY(ts) + #define TINYCLR_FOREACH_ASSEMBLY_IN_APPDOMAIN_END() TINYCLR_FOREACH_ASSEMBLY_END() + #define TINYCLR_FOREACH_ASSEMBLY_IN_CURRENT_APPDOMAIN(ts) TINYCLR_FOREACH_ASSEMBLY(ts) + #define TINYCLR_FOREACH_ASSEMBLY_IN_CURRENT_APPDOMAIN_END() TINYCLR_FOREACH_ASSEMBLY_END() +#endif +// This type is needed on PC only for Interop code generation. For device code forward declaration only +class CLR_RT_VectorOfManagedElements; + +struct CLR_RT_Assembly : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - +{ + struct Offsets + { + size_t iBase; + size_t iAssemblyRef; + size_t iTypeRef; + size_t iFieldRef; + size_t iMethodRef; + size_t iTypeDef; + size_t iFieldDef; + size_t iMethodDef; + +#if !defined(TINYCLR_APPDOMAINS) + size_t iStaticFields; +#endif + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + size_t iDebuggingInfoMethods; +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + }; + + //--// + + static const CLR_UINT32 c_Resolved = 0x00000001; + static const CLR_UINT32 c_ResolutionCompleted = 0x00000002; + static const CLR_UINT32 c_PreparedForExecution = 0x00000004; + static const CLR_UINT32 c_Deployed = 0x00000008; + static const CLR_UINT32 c_PreparingForExecution = 0x00000010; + static const CLR_UINT32 c_StaticConstructorsExecuted = 0x00000020; + + CLR_UINT32 m_idx; // Relative to the type system (for static fields access). + CLR_UINT32 m_flags; + + const CLR_RECORD_ASSEMBLY* m_header; // ANY HEAP - DO RELOCATION - + LPCSTR m_szName; // ANY HEAP - DO RELOCATION - + + const CLR_RT_MethodHandler* m_nativeCode; + + int m_pTablesSize[ TBL_Max ]; + +#if !defined(TINYCLR_APPDOMAINS) + CLR_RT_HeapBlock* m_pStaticFields; // EVENT HEAP - NO RELOCATION - (but the data they point to has to be relocated) +#endif + + int m_iStaticFields; + + CLR_RT_HeapBlock_Array* m_pFile; // ANY HEAP - DO RELOCATION - + + CLR_RT_AssemblyRef_CrossReference* m_pCrossReference_AssemblyRef; // EVENT HEAP - NO RELOCATION - (but the data they point to has to be relocated) + CLR_RT_TypeRef_CrossReference * m_pCrossReference_TypeRef ; // EVENT HEAP - NO RELOCATION - (but the data they point to has to be relocated) + CLR_RT_FieldRef_CrossReference * m_pCrossReference_FieldRef ; // EVENT HEAP - NO RELOCATION - (but the data they point to has to be relocated) + CLR_RT_MethodRef_CrossReference * m_pCrossReference_MethodRef ; // EVENT HEAP - NO RELOCATION - (but the data they point to has to be relocated) + CLR_RT_TypeDef_CrossReference * m_pCrossReference_TypeDef ; // EVENT HEAP - NO RELOCATION - (but the data they point to has to be relocated) + CLR_RT_FieldDef_CrossReference * m_pCrossReference_FieldDef ; // EVENT HEAP - NO RELOCATION - (but the data they point to has to be relocated) + CLR_RT_MethodDef_CrossReference * m_pCrossReference_MethodDef ; // EVENT HEAP - NO RELOCATION - (but the data they point to has to be relocated) + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + CLR_RT_MethodDef_DebuggingInfo * m_pDebuggingInfo_MethodDef ; //EVENT HEAP - NO RELOCATION - (but the data they point to has to be relocated) +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + +#if defined(TINYCLR_TRACE_STACK_HEAVY) && defined(_WIN32) + int m_maxOpcodes; + int* m_stackDepth; +#endif + + +#if defined(_WIN32) + std::string* m_strPath; +#endif + + //--// + + static void InitString(); + + bool IsSameAssembly( const CLR_RT_Assembly& assm ) const; + +#if defined(_WIN32) + + static void InitString( std::map& map ); + static HRESULT CreateInstance ( const CLR_RECORD_ASSEMBLY* data, CLR_RT_Assembly*& assm, LPCWSTR szName ); + +#endif + + //--// + + static HRESULT CreateInstance ( const CLR_RECORD_ASSEMBLY* data, CLR_RT_Assembly*& assm ); + void DestroyInstance( ); + + void Assembly_Initialize( CLR_RT_Assembly::Offsets& offsets ); + + bool Resolve_AssemblyRef ( bool fOutput ); + HRESULT Resolve_TypeRef ( ); + HRESULT Resolve_FieldRef ( ); + HRESULT Resolve_MethodRef ( ); + void Resolve_TypeDef ( ); + void Resolve_MethodDef ( ); + void Resolve_Link ( ); + HRESULT Resolve_ComputeHashes ( ); + HRESULT Resolve_AllocateStaticFields ( CLR_RT_HeapBlock* pStaticFields ); + + static HRESULT VerifyEndian(CLR_RECORD_ASSEMBLY* header); + + HRESULT PrepareForExecution(); + + CLR_UINT32 ComputeAssemblyHash( ); + CLR_UINT32 ComputeAssemblyHash( const CLR_RECORD_ASSEMBLYREF* ar ); + + + bool FindTypeDef ( LPCSTR name, LPCSTR nameSpace , CLR_RT_TypeDef_Index& idx ); + bool FindTypeDef ( LPCSTR name, CLR_IDX scope , CLR_RT_TypeDef_Index& idx ); + bool FindTypeDef ( CLR_UINT32 hash , CLR_RT_TypeDef_Index& idx ); + + bool FindFieldDef ( const CLR_RECORD_TYPEDEF* src, LPCSTR name, CLR_RT_Assembly* base, CLR_SIG sig, CLR_RT_FieldDef_Index& idx ); + bool FindMethodDef( const CLR_RECORD_TYPEDEF* src, LPCSTR name, CLR_RT_Assembly* base, CLR_SIG sig, CLR_RT_MethodDef_Index& idx ); + + bool FindNextStaticConstructor( CLR_RT_MethodDef_Index& idx ); + + bool FindMethodBoundaries( CLR_IDX i, CLR_OFFSET& start, CLR_OFFSET& end ); + + void Relocate(); + + //--// + + CLR_RT_HeapBlock* GetStaticField( const int index ); + + //--// + + CLR_PMETADATA GetTable( CLR_TABLESENUM tbl ) { return (CLR_PMETADATA)m_header + m_header->startOfTables[ tbl ]; } + +#define TINYCLR_ASSEMBLY_RESOLVE(cls,tbl,idx) (const cls *)((CLR_UINT8*)m_header + m_header->startOfTables[ tbl ] + (sizeof(cls) * idx)) + const CLR_RECORD_ASSEMBLYREF * GetAssemblyRef ( CLR_IDX i ) { return TINYCLR_ASSEMBLY_RESOLVE(CLR_RECORD_ASSEMBLYREF , TBL_AssemblyRef , i); } + const CLR_RECORD_TYPEREF * GetTypeRef ( CLR_IDX i ) { return TINYCLR_ASSEMBLY_RESOLVE(CLR_RECORD_TYPEREF , TBL_TypeRef , i); } + const CLR_RECORD_FIELDREF * GetFieldRef ( CLR_IDX i ) { return TINYCLR_ASSEMBLY_RESOLVE(CLR_RECORD_FIELDREF , TBL_FieldRef , i); } + const CLR_RECORD_METHODREF * GetMethodRef ( CLR_IDX i ) { return TINYCLR_ASSEMBLY_RESOLVE(CLR_RECORD_METHODREF , TBL_MethodRef , i); } + const CLR_RECORD_TYPEDEF * GetTypeDef ( CLR_IDX i ) { return TINYCLR_ASSEMBLY_RESOLVE(CLR_RECORD_TYPEDEF , TBL_TypeDef , i); } + const CLR_RECORD_FIELDDEF * GetFieldDef ( CLR_IDX i ) { return TINYCLR_ASSEMBLY_RESOLVE(CLR_RECORD_FIELDDEF , TBL_FieldDef , i); } + const CLR_RECORD_METHODDEF * GetMethodDef ( CLR_IDX i ) { return TINYCLR_ASSEMBLY_RESOLVE(CLR_RECORD_METHODDEF , TBL_MethodDef , i); } + const CLR_RECORD_ATTRIBUTE * GetAttribute ( CLR_IDX i ) { return TINYCLR_ASSEMBLY_RESOLVE(CLR_RECORD_ATTRIBUTE , TBL_Attributes , i); } + const CLR_RECORD_TYPESPEC * GetTypeSpec ( CLR_IDX i ) { return TINYCLR_ASSEMBLY_RESOLVE(CLR_RECORD_TYPESPEC , TBL_TypeSpec , i); } + const CLR_RECORD_RESOURCE_FILE* GetResourceFile( CLR_IDX i ) { return TINYCLR_ASSEMBLY_RESOLVE(CLR_RECORD_RESOURCE_FILE, TBL_ResourcesFiles, i); } + const CLR_RECORD_RESOURCE * GetResource ( CLR_IDX i ) { return TINYCLR_ASSEMBLY_RESOLVE(CLR_RECORD_RESOURCE , TBL_Resources , i); } + CLR_PMETADATA GetResourceData( CLR_UINT32 i ) { return TINYCLR_ASSEMBLY_RESOLVE(CLR_UINT8 , TBL_ResourcesData , i); } + LPCSTR GetString ( CLR_STRING i ); + CLR_PMETADATA GetSignature ( CLR_SIG i ) { return TINYCLR_ASSEMBLY_RESOLVE(CLR_UINT8 , TBL_Signatures , i); } + CLR_PMETADATA GetByteCode ( CLR_OFFSET i ) { return TINYCLR_ASSEMBLY_RESOLVE(CLR_UINT8 , TBL_ByteCode , i); } +#undef TINYCLR_ASSEMBLY_RESOLVE + + //--// + +#undef DECL_POSTFIX +#if defined(TINYCLR_TRACE_INSTRUCTIONS) +#define DECL_POSTFIX +#else +#define DECL_POSTFIX {} +#endif +public: + void DumpOpcode ( CLR_RT_StackFrame* stack, CLR_PMETADATA ip ) DECL_POSTFIX; + void DumpOpcodeDirect( CLR_RT_MethodDef_Instance& call , CLR_PMETADATA ip, CLR_PMETADATA ipStart, int pid ) DECL_POSTFIX; + +private: + void DumpToken ( CLR_UINT32 tk ) DECL_POSTFIX; + void DumpSignature ( CLR_SIG sig ) DECL_POSTFIX; + void DumpSignature ( CLR_PMETADATA& p ) DECL_POSTFIX; + void DumpSignatureToken( CLR_PMETADATA& p ) DECL_POSTFIX; + + //--// + +#if defined(_WIN32) + static FILE* s_output; + static FILE* s_toclose; + +public: + static void Dump_SetDevice ( FILE *&outputDeviceFile, LPCWSTR szFileName ); + static void Dump_SetDevice ( LPCWSTR szFileName ); + + static void Dump_CloseDevice( FILE *&outputDeviceFile); + static void Dump_CloseDevice( ); + + static void Dump_Printf ( FILE *outputDeviceFile, const char *format, ... ); + static void Dump_Printf ( const char *format, ... ); + + static void Dump_Indent( const CLR_RECORD_METHODDEF* md, size_t offset, size_t level ); + + void Dump( bool fNoByteCode ); + + UINT32 GenerateSignatureForNativeMethods(); + + bool AreInternalMethodsPresent( const CLR_RECORD_TYPEDEF* td ); + void GenerateSkeleton( LPCWSTR szFileName, LPCWSTR szProjectName ); + void GenerateSkeletonFromComplientNames( LPCWSTR szFileName, LPCWSTR szProjectName ); + + void BuildParametersList( CLR_PMETADATA pMetaData, CLR_RT_VectorOfManagedElements &elemPtrArray ); + void GenerateSkeletonStubFieldsDef( const CLR_RECORD_TYPEDEF *pClsType, FILE *pFileStubHead, std::string strIndent, std::string strMngClassName ); + void GenerateSkeletonStubCode( LPCWSTR szFilePath, FILE *pFileDotNetProj ); + + void BuildMethodName_Legacy( const CLR_RECORD_METHODDEF* md, std::string& name, CLR_RT_StringMap& mapMethods ); + void GenerateSkeleton_Legacy( LPCWSTR szFileName, LPCWSTR szProjectName ); + + + void BuildMethodName( const CLR_RECORD_METHODDEF* md, std::string& name , CLR_RT_StringMap& mapMethods ); + void BuildClassName ( const CLR_RECORD_TYPEREF* tr, std::string& cls_name, bool fEscape ); + void BuildClassName ( const CLR_RECORD_TYPEDEF* td, std::string& cls_name, bool fEscape ); + void BuildTypeName ( const CLR_RECORD_TYPEDEF* td, std::string& type_name ); + +#endif +private: + +#if defined(_WIN32) + void Dump_Token ( CLR_UINT32 tk ); + void Dump_FieldOwner ( CLR_UINT32 idx ); + void Dump_MethodOwner ( CLR_UINT32 idx ); + void Dump_Signature ( CLR_SIG sig ); + void Dump_Signature ( CLR_PMETADATA& p ); + void Dump_SignatureToken( CLR_PMETADATA& p ); +#endif + + //--// + + PROHIBIT_ALL_CONSTRUCTORS(CLR_RT_Assembly); + + //--// + +private: + + CLR_UINT32 ComputeHashForName( const CLR_RT_TypeDef_Index& td, CLR_UINT32 hash ); + + static CLR_UINT32 ComputeHashForType( CLR_DataType dt, CLR_UINT32 hash ); +}; + +//--// + +#if defined(TINYCLR_APPDOMAINS) + +struct CLR_RT_AppDomain : public CLR_RT_ObjectToEvent_Destination // EVENT HEAP - NO RELOCATION - +{ + enum AppDomainState + { + AppDomainState_Loaded, + AppDomainState_Unloading, + AppDomainState_Unloaded + }; + + AppDomainState m_state; + int m_id; + CLR_RT_DblLinkedList m_appDomainAssemblies; + CLR_RT_HeapBlock* m_globalLock; // OBJECT HEAP - DO RELOCATION - + CLR_RT_HeapBlock_String* m_strName; // OBJECT HEAP - DO RELOCATION - + CLR_RT_HeapBlock* m_outOfMemoryException; // OBJECT HEAP - DO RELOCATION - + CLR_RT_AppDomainAssembly* m_appDomainAssemblyLastAccess; // EVENT HEAP - NO RELOCATION - + bool m_fCanBeUnloaded; + + static HRESULT CreateInstance ( LPCSTR szName, CLR_RT_AppDomain*& appDomain); + + void DestroyInstance (); + void AppDomain_Initialize (); + void AppDomain_Uninitialize(); + bool IsLoaded (); + + void Relocate (); + void RecoverFromGC(); + + CLR_RT_AppDomainAssembly* FindAppDomainAssembly( CLR_RT_Assembly* assm ); + + HRESULT MarshalObject ( CLR_RT_HeapBlock& src , CLR_RT_HeapBlock& dst, CLR_RT_AppDomain* appDomainSrc = NULL ); + HRESULT MarshalParameters( CLR_RT_HeapBlock* callerArgs, CLR_RT_HeapBlock* calleeArgs, int count, bool fOnReturn, CLR_RT_AppDomain* appDomainSrc = NULL ); + + HRESULT VerifyTypeIsLoaded( const CLR_RT_TypeDef_Index& idx ); + HRESULT GetAssemblies ( CLR_RT_HeapBlock& ref ); + HRESULT LoadAssembly ( CLR_RT_Assembly* assm ); + HRESULT GetManagedObject ( CLR_RT_HeapBlock& obj ); +}; + +struct CLR_RT_AppDomainAssembly : public CLR_RT_HeapBlock_Node //EVENT HEAP - NO RELOCATION - +{ + static const CLR_UINT32 c_StaticConstructorsExecuted = 0x00000001; + + CLR_UINT32 m_flags; + CLR_RT_AppDomain* m_appDomain; // EVENT HEAP - NO RELOCATION - + CLR_RT_Assembly* m_assembly; // EVENT HEAP - NO RELOCATION - + CLR_RT_HeapBlock* m_pStaticFields; // EVENT HEAP - NO RELOCATION - (but the data they point to has to be relocated) + + + static HRESULT CreateInstance( CLR_RT_AppDomain* appDomain, CLR_RT_Assembly* assm, CLR_RT_AppDomainAssembly*& appDomainAssembly ); + + void DestroyInstance(); + HRESULT AppDomainAssembly_Initialize( CLR_RT_AppDomain* appDomain, CLR_RT_Assembly* assm ); + + void Relocate(); +}; + +#endif //TINYCLR_APPDOMAINS + +//--// + +struct CLR_RT_WellKnownTypes +{ + CLR_RT_TypeDef_Index m_Boolean; + CLR_RT_TypeDef_Index m_Int8; + CLR_RT_TypeDef_Index m_UInt8; + + CLR_RT_TypeDef_Index m_Char; + CLR_RT_TypeDef_Index m_Int16; + CLR_RT_TypeDef_Index m_UInt16; + + CLR_RT_TypeDef_Index m_Int32; + CLR_RT_TypeDef_Index m_UInt32; + CLR_RT_TypeDef_Index m_Single; + + CLR_RT_TypeDef_Index m_Int64; + CLR_RT_TypeDef_Index m_UInt64; + CLR_RT_TypeDef_Index m_Double; + CLR_RT_TypeDef_Index m_DateTime; + CLR_RT_TypeDef_Index m_TimeSpan; + CLR_RT_TypeDef_Index m_String; + + CLR_RT_TypeDef_Index m_Void; + CLR_RT_TypeDef_Index m_Object; + CLR_RT_TypeDef_Index m_ValueType; + CLR_RT_TypeDef_Index m_Enum; + + CLR_RT_TypeDef_Index m_AppDomainUnloadedException; + CLR_RT_TypeDef_Index m_ArgumentNullException; + CLR_RT_TypeDef_Index m_ArgumentException; + CLR_RT_TypeDef_Index m_ArgumentOutOfRangeException; + CLR_RT_TypeDef_Index m_Exception; + CLR_RT_TypeDef_Index m_IndexOutOfRangeException; + CLR_RT_TypeDef_Index m_ThreadAbortException; + CLR_RT_TypeDef_Index m_IOException; + CLR_RT_TypeDef_Index m_InvalidOperationException; + CLR_RT_TypeDef_Index m_InvalidCastException; + CLR_RT_TypeDef_Index m_NotSupportedException; + CLR_RT_TypeDef_Index m_NotImplementedException; + CLR_RT_TypeDef_Index m_NullReferenceException; + CLR_RT_TypeDef_Index m_OutOfMemoryException; + CLR_RT_TypeDef_Index m_ObjectDisposedException; + CLR_RT_TypeDef_Index m_UnknownTypeException; + CLR_RT_TypeDef_Index m_ConstraintException; + CLR_RT_TypeDef_Index m_WatchdogException; + + CLR_RT_TypeDef_Index m_Delegate; + CLR_RT_TypeDef_Index m_MulticastDelegate; + + CLR_RT_TypeDef_Index m_Array; + CLR_RT_TypeDef_Index m_ArrayList; + CLR_RT_TypeDef_Index m_ICloneable; + CLR_RT_TypeDef_Index m_IList; + + CLR_RT_TypeDef_Index m_Assembly; + CLR_RT_TypeDef_Index m_TypeStatic; + CLR_RT_TypeDef_Index m_Type; + CLR_RT_TypeDef_Index m_ConstructorInfo; + CLR_RT_TypeDef_Index m_MethodInfo; + CLR_RT_TypeDef_Index m_FieldInfo; + + CLR_RT_TypeDef_Index m_WeakReference; + CLR_RT_TypeDef_Index m_ExtendedWeakReference; + + CLR_RT_TypeDef_Index m_SerializationHintsAttribute; + + CLR_RT_TypeDef_Index m_ExtendedTimeZone; + + CLR_RT_TypeDef_Index m_Bitmap; + CLR_RT_TypeDef_Index m_Font; + + CLR_RT_TypeDef_Index m_TouchEvent; + CLR_RT_TypeDef_Index m_TouchInput; + + CLR_RT_TypeDef_Index m_Message; + + CLR_RT_TypeDef_Index m_ScreenMetrics; + + CLR_RT_TypeDef_Index m_I2CDevice; + CLR_RT_TypeDef_Index m_I2CDevice__I2CReadTransaction; + CLR_RT_TypeDef_Index m_I2CDevice__I2CWriteTransaction; + + CLR_RT_TypeDef_Index m_UsbClientConfiguration; + CLR_RT_TypeDef_Index m_UsbClientConfiguration__Descriptor; + CLR_RT_TypeDef_Index m_UsbClientConfiguration__DeviceDescriptor; + CLR_RT_TypeDef_Index m_UsbClientConfiguration__ClassDescriptor; + CLR_RT_TypeDef_Index m_UsbClientConfiguration__Endpoint; + CLR_RT_TypeDef_Index m_UsbClientConfiguration__UsbInterface; + CLR_RT_TypeDef_Index m_UsbClientConfiguration__ConfigurationDescriptor; + CLR_RT_TypeDef_Index m_UsbClientConfiguration__StringDescriptor; + CLR_RT_TypeDef_Index m_UsbClientConfiguration__GenericDescriptor; + + CLR_RT_TypeDef_Index m_NetworkInterface; + CLR_RT_TypeDef_Index m_Wireless80211; + + CLR_RT_TypeDef_Index m_TimeServiceSettings; + CLR_RT_TypeDef_Index m_TimeServiceStatus; + +#if defined(TINYCLR_APPDOMAINS) + CLR_RT_TypeDef_Index m_AppDomain; + CLR_RT_TypeDef_Index m_MarshalByRefObject; +#endif + + CLR_RT_TypeDef_Index m_Thread; + CLR_RT_TypeDef_Index m_ResourceManager; + + CLR_RT_TypeDef_Index m_SocketException; + + CLR_RT_TypeDef_Index m_NativeFileInfo; + CLR_RT_TypeDef_Index m_VolumeInfo; + + CLR_RT_TypeDef_Index m_XmlNameTable_Entry; + CLR_RT_TypeDef_Index m_XmlReader_XmlNode; + CLR_RT_TypeDef_Index m_XmlReader_XmlAttribute; + CLR_RT_TypeDef_Index m_XmlReader_NamespaceEntry; + + CLR_RT_TypeDef_Index m_CryptoKey; + CLR_RT_TypeDef_Index m_CryptokiObject; + CLR_RT_TypeDef_Index m_CryptokiSession; + CLR_RT_TypeDef_Index m_CryptokiSlot; + CLR_RT_TypeDef_Index m_CryptokiMechanismType; + CLR_RT_TypeDef_Index m_CryptoException; + CLR_RT_TypeDef_Index m_CryptokiCertificate; + + PROHIBIT_COPY_CONSTRUCTORS(CLR_RT_WellKnownTypes); +}; + +extern CLR_RT_WellKnownTypes g_CLR_RT_WellKnownTypes; + +struct CLR_RT_WellKnownMethods +{ + CLR_RT_MethodDef_Index m_ResourceManager_GetObjectFromId; + CLR_RT_MethodDef_Index m_ResourceManager_GetObjectChunkFromId; + + PROHIBIT_COPY_CONSTRUCTORS(CLR_RT_WellKnownMethods); +}; + +extern CLR_RT_WellKnownMethods g_CLR_RT_WellKnownMethods; + +//--// + +typedef void (CLR_RT_HeapBlock::*CLR_RT_HeapBlockRelocate)(); + +struct CLR_RT_DataTypeLookup +{ + static const CLR_UINT8 c_NA = 0x00; + static const CLR_UINT8 c_VariableSize = 0xFF; + + static const CLR_UINT32 c_Primitive = 0x00000001; + static const CLR_UINT32 c_Interface = 0x00000002; + static const CLR_UINT32 c_Class = 0x00000004; + static const CLR_UINT32 c_ValueType = 0x00000008; + static const CLR_UINT32 c_Enum = 0x00000010; + static const CLR_UINT32 c_SemanticMask = 0x0000001F; + + static const CLR_UINT32 c_Array = 0x00000020; + static const CLR_UINT32 c_ArrayList = 0x00000040; + static const CLR_UINT32 c_SemanticMask2 = 0x0000007F; + + static const CLR_UINT32 c_Reference = 0x00010000; + static const CLR_UINT32 c_Numeric = 0x00020000; + static const CLR_UINT32 c_Integer = 0x00040000; + static const CLR_UINT32 c_Signed = 0x00080000; + static const CLR_UINT32 c_Direct = 0x00100000; // This isn't an indirect reference. + static const CLR_UINT32 c_OptimizedValueType = 0x00200000; // A value type that is kept in a single HeapBlock. + static const CLR_UINT32 c_ManagedType = 0x00400000; // this dt represents a managed type, or a pointer to a managed type + // More specificly, TypeDescriptor::InitializeFromObject will succeed + // when starting from an object of with this dt + + CLR_UINT32 m_flags; + CLR_UINT8 m_sizeInBits; + CLR_UINT8 m_sizeInBytes; + CLR_UINT8 m_promoteTo; + CLR_UINT8 m_convertToElementType; + + CLR_RT_TypeDef_Index* m_cls; + CLR_RT_HeapBlockRelocate m_relocate; + +#if defined(_WIN32) || defined(TINYCLR_TRACE_MEMORY_STATS) + LPCSTR m_name; +#endif +}; + +extern const CLR_RT_DataTypeLookup c_CLR_RT_DataTypeLookup[]; + +//--// + +struct CLR_RT_OpcodeLookup +{ + static const CLR_UINT16 COND_BRANCH_NEVER = 0x0000; + static const CLR_UINT16 COND_BRANCH_ALWAYS = 0x0001; + static const CLR_UINT16 COND_BRANCH_IFTRUE = 0x0002; + static const CLR_UINT16 COND_BRANCH_IFFALSE = 0x0003; + static const CLR_UINT16 COND_BRANCH_IFEQUAL = 0x0004; + static const CLR_UINT16 COND_BRANCH_IFNOTEQUAL = 0x0005; + static const CLR_UINT16 COND_BRANCH_IFGREATER = 0x0006; + static const CLR_UINT16 COND_BRANCH_IFGREATEROREQUAL = 0x0007; + static const CLR_UINT16 COND_BRANCH_IFLESS = 0x0008; + static const CLR_UINT16 COND_BRANCH_IFLESSOREQUAL = 0x0009; + static const CLR_UINT16 COND_BRANCH_IFMATCH = 0x000A; + static const CLR_UINT16 COND_BRANCH_THROW = 0x000B; + static const CLR_UINT16 COND_BRANCH_MASK = 0x000F; + + static const CLR_UINT16 COND_OVERFLOW = 0x0010; + static const CLR_UINT16 COND_UNSIGNED = 0x0020; + + static const CLR_UINT16 STACK_RESET = 0x0080; + + static const CLR_UINT16 ATTRIB_HAS_TARGET = 0x0100; + static const CLR_UINT16 ATTRIB_HAS_DT = 0x0200; + static const CLR_UINT16 ATTRIB_HAS_INDEX = 0x0400; + static const CLR_UINT16 ATTRIB_HAS_TOKEN = 0x0800; + static const CLR_UINT16 ATTRIB_HAS_I4 = 0x1000; + static const CLR_UINT16 ATTRIB_HAS_R4 = 0x2000; + static const CLR_UINT16 ATTRIB_HAS_I8 = 0x4000; + static const CLR_UINT16 ATTRIB_HAS_R8 = 0x8000; + +#if defined(TINYCLR_OPCODE_NAMES) + LPCSTR m_name; +#endif + +#if defined(TINYCLR_OPCODE_STACKCHANGES) + CLR_UINT8 m_stackChanges; +#endif + + CLR_OpcodeParam m_opParam; + + //--// + +#if defined(TINYCLR_OPCODE_PARSER) + CLR_LOGICAL_OPCODE m_logicalOpcode; + CLR_DataType m_dt; + CLR_INT8 m_index; + CLR_UINT16 m_flags; +#endif +#if defined(TINYCLR_OPCODE_STACKCHANGES) + CLR_UINT32 StackPop () const { return m_stackChanges >> 4; } + CLR_UINT32 StackPush () const { return m_stackChanges & 0xF; } + CLR_INT32 StackChanges() const { return StackPush() - StackPop(); } +#endif + +#if defined(TINYCLR_OPCODE_NAMES) + LPCSTR Name() const { return m_name; } +#else + LPCSTR Name() const { return ""; } +#endif +}; + +extern const CLR_RT_OpcodeLookup c_CLR_RT_OpcodeLookup[]; + +//--// + +struct CLR_RT_LogicalOpcodeLookup +{ + static const CLR_UINT32 RESTARTPOINT_NEXT = 0x00000001; + static const CLR_UINT32 EXCEPTION = 0x00000002; + static const CLR_UINT32 EXCEPTION_IF_OVERFLOW = 0x00000010; + static const CLR_UINT32 EXCEPTION_IF_ZERO = 0x00000020; + static const CLR_UINT32 EXCEPTION_ON_CAST = 0x00000040; + +#if defined(TINYCLR_OPCODE_NAMES) + LPCSTR m_name; +#endif + + CLR_UINT32 m_flags; + + +#if defined(TINYCLR_OPCODE_NAMES) + LPCSTR Name() const { return m_name; } +#else + LPCSTR Name() const { return ""; } +#endif +}; + +extern const CLR_RT_LogicalOpcodeLookup c_CLR_RT_LogicalOpcodeLookup[]; + +//--// + + +struct CLR_RT_TypeSystem // EVENT HEAP - NO RELOCATION - +{ + struct CompatibilityLookup + { + LPCSTR name; + CLR_RECORD_VERSION version; + }; + + //--// + + static const int c_MaxAssemblies = 64; + + //--// + + static const CLR_UINT32 TYPENAME_FLAGS_FULL = 0x1; + static const CLR_UINT32 TYPENAME_NESTED_SEPARATOR_DOT = 0x2; + + //--// + + CLR_RT_Assembly* m_assemblies[ c_MaxAssemblies ]; // EVENT HEAP - NO RELOCATION - array of CLR_RT_Assembly + size_t m_assembliesMax; + CLR_RT_Assembly* m_assemblyMscorlib; + CLR_RT_Assembly* m_assemblyNative; + + CLR_RT_MethodDef_Index m_entryPoint; + + //--// + + void TypeSystem_Initialize(); + void TypeSystem_Cleanup(); + + void Link ( CLR_RT_Assembly* assm ); + void PostLinkageProcessing( CLR_RT_Assembly* assm ); + + HRESULT ResolveAll ( ); + HRESULT PrepareForExecution ( ); + HRESULT PrepareForExecutionHelper( LPCSTR szAssembly ); + + CLR_RT_Assembly* FindAssembly( LPCSTR name, const CLR_RECORD_VERSION* ver, bool fExact ); + + bool FindTypeDef ( LPCSTR name, LPCSTR nameSpace, CLR_RT_Assembly* assm, CLR_RT_TypeDef_Index& res ); + bool FindTypeDef ( LPCSTR name, CLR_RT_Assembly* assm, CLR_RT_TypeDef_Index& res ); + bool FindTypeDef ( LPCSTR name, LPCSTR nameSpace, CLR_RT_TypeDef_Index& res ); + bool FindTypeDef ( CLR_UINT32 hash , CLR_RT_TypeDef_Index& res ); + bool FindTypeDef ( LPCSTR name , CLR_RT_TypeDef_Index& res ); + bool FindTypeDef ( LPCSTR name , CLR_RT_Assembly* assm, CLR_RT_ReflectionDef_Index& reflex ); + + HRESULT LocateResourceFile( CLR_RT_Assembly_Instance assm, LPCSTR name, CLR_INT32& idxResourceFile ); + HRESULT LocateResource ( CLR_RT_Assembly_Instance assm, CLR_INT32 idxResourceFile, CLR_INT16 id, const CLR_RECORD_RESOURCE*& res, CLR_UINT32& size ); + + HRESULT BuildTypeName ( const CLR_RT_TypeDef_Index& cls, LPSTR& szBuffer, size_t& size, CLR_UINT32 flags, CLR_UINT32 levels ); + HRESULT BuildTypeName ( const CLR_RT_TypeDef_Index& cls, LPSTR& szBuffer, size_t& size ); + HRESULT BuildMethodName ( const CLR_RT_MethodDef_Index& md , LPSTR& szBuffer, size_t& size ); + HRESULT BuildFieldName ( const CLR_RT_FieldDef_Index& fd , LPSTR& szBuffer, size_t& size ); + HRESULT QueueStringToBuffer( LPSTR& szBuffer, size_t& size, LPCSTR szText ); + + bool FindVirtualMethodDef( const CLR_RT_TypeDef_Index& cls, const CLR_RT_MethodDef_Index& calleeMD , CLR_RT_MethodDef_Index& idx ); + bool FindVirtualMethodDef( const CLR_RT_TypeDef_Index& cls, const CLR_RT_MethodDef_Index& calleeMD, LPCSTR calleeName, CLR_RT_MethodDef_Index& idx ); + + static bool MatchSignature ( CLR_RT_SignatureParser& parserLeft , CLR_RT_SignatureParser& parserRight ); + static bool MatchSignatureDirect ( CLR_RT_SignatureParser& parserLeft , CLR_RT_SignatureParser& parserRight , bool fIsInstanceOfOK ); + static bool MatchSignatureElement( CLR_RT_SignatureParser::Element& resLeft, CLR_RT_SignatureParser::Element& resRight, bool fIsInstanceOfOK ); + + static CLR_DataType MapElementTypeToDataType( CLR_UINT32 et ); + static CLR_UINT32 MapDataTypeToElementType( CLR_DataType dt ); + +#if defined(_WIN32) + void Dump( LPCWSTR szFileName, bool fNoByteCode ); +#endif + + //--// + + PROHIBIT_COPY_CONSTRUCTORS(CLR_RT_TypeSystem); +}; + +extern CLR_RT_TypeSystem g_CLR_RT_TypeSystem; + +//--// + +struct CLR_RT_Assembly_Instance : public CLR_RT_Assembly_Index +{ + CLR_RT_Assembly* m_assm; + + //--// + + bool InitializeFromIndex( const CLR_RT_Assembly_Index& idx ); + void Clear ( ); +}; + +struct CLR_RT_TypeSpec_Instance : public CLR_RT_TypeSpec_Index +{ + CLR_RT_Assembly* m_assm; + CLR_PMETADATA m_target; + + //--// + + bool InitializeFromIndex( const CLR_RT_TypeSpec_Index& idx ); + void Clear ( ); + + bool ResolveToken( CLR_UINT32 tk, CLR_RT_Assembly* assm ); +}; + +//--// + +struct CLR_RT_TypeDef_Instance : public CLR_RT_TypeDef_Index +{ + CLR_RT_Assembly* m_assm; + const CLR_RECORD_TYPEDEF* m_target; + + //--// + + bool InitializeFromReflection ( const CLR_RT_ReflectionDef_Index& reflex, CLR_UINT32* levels ); + bool InitializeFromIndex ( const CLR_RT_TypeDef_Index& idx ); + bool InitializeFromMethod ( const CLR_RT_MethodDef_Instance& md ); + bool InitializeFromField ( const CLR_RT_FieldDef_Instance& fd ); + + void Clear ( ); + + bool ResolveToken( CLR_UINT32 tk, CLR_RT_Assembly* assm ); + + //--// + + CLR_RT_TypeDef_CrossReference& CrossReference() const { return m_assm->m_pCrossReference_TypeDef[ Type() ]; } + + bool SwitchToParent(); + bool HasFinalizer () const; + + bool IsATypeHandler(); +}; + +//--// + +struct CLR_RT_FieldDef_Instance : public CLR_RT_FieldDef_Index +{ + CLR_RT_Assembly* m_assm; + const CLR_RECORD_FIELDDEF* m_target; + + //--// + + bool InitializeFromIndex( const CLR_RT_FieldDef_Index& idx ); + void Clear ( ); + + bool ResolveToken( CLR_UINT32 tk, CLR_RT_Assembly* assm ); + + //--// + + CLR_RT_FieldDef_CrossReference& CrossReference() const { return m_assm->m_pCrossReference_FieldDef[ Field() ]; } +}; + +//--// + +struct CLR_RT_MethodDef_Instance : public CLR_RT_MethodDef_Index +{ + CLR_RT_Assembly* m_assm; + const CLR_RECORD_METHODDEF* m_target; + + //--// + + bool InitializeFromIndex( const CLR_RT_MethodDef_Index& idx ); + void Clear ( ); + + bool ResolveToken( CLR_UINT32 tk, CLR_RT_Assembly* assm ); + + //--// + + CLR_RT_MethodDef_CrossReference& CrossReference() const { return m_assm->m_pCrossReference_MethodDef[ Method() ]; } + CLR_UINT32 Hits() const { return 0; } + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + CLR_RT_MethodDef_DebuggingInfo& DebuggingInfo() const { return m_assm->m_pDebuggingInfo_MethodDef[ Method() ]; } +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) +}; + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +struct CLR_RT_AttributeEnumerator +{ + CLR_RT_Assembly* m_assm; + const CLR_RECORD_ATTRIBUTE* m_ptr; + int m_num; + CLR_RECORD_ATTRIBUTE m_data; + + CLR_RT_MethodDef_Index m_match; + CLR_PMETADATA m_blob; + + void Initialize( const CLR_RT_TypeDef_Instance & inst ); + void Initialize( const CLR_RT_FieldDef_Instance & inst ); + void Initialize( const CLR_RT_MethodDef_Instance& inst ); + + bool Advance(); + + bool MatchNext( const CLR_RT_TypeDef_Instance* instTD, const CLR_RT_MethodDef_Instance* instMD ); + +private: + void Initialize( CLR_RT_Assembly* assm ); +}; + +struct CLR_RT_AttributeParser +{ + struct Value + { + static const int c_ConstructorArgument = 1; + static const int c_NamedField = 2; + static const int c_NamedProperty = 3; + + int m_mode; + CLR_RT_HeapBlock m_value; + + int m_pos; + LPCSTR m_name; + }; + + //--// + + CLR_RT_Assembly* m_assm; + CLR_PMETADATA m_blob; + + CLR_RT_MethodDef_Instance m_md; + CLR_RT_TypeDef_Instance m_td; + CLR_RT_SignatureParser m_parser; + CLR_RT_SignatureParser::Element m_res; + + int m_currentPos; + int m_fixed_Count; + int m_named_Count; + Value m_lastValue; + + //--// + + HRESULT Initialize( const CLR_RT_AttributeEnumerator& en ); + + HRESULT Next( Value*& res ); + +private: + LPCSTR GetString(); +}; + +//////////////////////////////////////////////////////////////////////////////// + +struct CLR_RT_TypeDescriptor +{ + CLR_UINT32 m_flags; + CLR_RT_TypeDef_Instance m_handlerCls; + + CLR_RT_ReflectionDef_Index m_reflex; + + CLR_DataType GetDataType() const { return (CLR_DataType)m_handlerCls.m_target->dataType; } + + //--// + + void TypeDescriptor_Initialize(); + + HRESULT InitializeFromDataType ( CLR_DataType dt ); + HRESULT InitializeFromReflection ( const CLR_RT_ReflectionDef_Index& reflex ); + HRESULT InitializeFromTypeSpec ( const CLR_RT_TypeSpec_Index& sig ); + HRESULT InitializeFromType ( const CLR_RT_TypeDef_Index& cls ); + HRESULT InitializeFromFieldDefinition( const CLR_RT_FieldDef_Instance& fd ); + HRESULT InitializeFromSignatureParser( CLR_RT_SignatureParser& parser ); + HRESULT InitializeFromObject ( const CLR_RT_HeapBlock& ref ); + + void ConvertToArray(); + bool ShouldEmitHash(); + + bool GetElementType( CLR_RT_TypeDescriptor& sub ); + + static HRESULT ExtractTypeIndexFromObject( const CLR_RT_HeapBlock& ref, CLR_RT_TypeDef_Index& res ); + static HRESULT ExtractObjectAndDataType( CLR_RT_HeapBlock*& ref, CLR_DataType& dt ); +}; + +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +struct CLR_RT_HeapCluster : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - +{ + CLR_RT_DblLinkedList m_freeList; // list of CLR_RT_HeapBlock_Node + CLR_RT_HeapBlock_Node* m_payloadStart; + CLR_RT_HeapBlock_Node* m_payloadEnd; + + //--// + + void HeapCluster_Initialize( CLR_UINT32 size, CLR_UINT32 blockSize ); // Memory is not erased by the caller. + + CLR_RT_HeapBlock* ExtractBlocks( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 length ); + + void RecoverFromGC(); + + CLR_RT_HeapBlock_Node* InsertInOrder( CLR_RT_HeapBlock_Node* node, CLR_UINT32 size ); + + //--// + +#undef DECL_POSTFIX +#if TINYCLR_VALIDATE_HEAP >= TINYCLR_VALIDATE_HEAP_1_HeapBlocksAndUnlink +#define DECL_POSTFIX +#else +#define DECL_POSTFIX {} +#endif + void ValidateBlock( CLR_RT_HeapBlock* ptr ) DECL_POSTFIX; + + //--// + + PROHIBIT_ALL_CONSTRUCTORS(CLR_RT_HeapCluster); +}; + +//--// + +#ifndef TINYCLR_NO_IL_INLINE +struct CLR_RT_InlineFrame +{ + CLR_RT_HeapBlock* m_locals; + CLR_RT_HeapBlock* m_args; + CLR_RT_HeapBlock* m_evalStack; + CLR_RT_HeapBlock* m_evalPos; + CLR_RT_MethodDef_Instance m_call; + CLR_PMETADATA m_IP; + CLR_PMETADATA m_IPStart; +}; + +struct CLR_RT_InlineBuffer +{ + union + { + CLR_RT_InlineBuffer* m_pNext; + + CLR_RT_InlineFrame m_frame; + }; +}; +#endif + +struct CLR_RT_StackFrame : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - +{ + static const int c_OverheadForNewObjOrInteropMethod = 2; // We need to have more slots in the stack to process a 'newobj' opcode. + static const int c_MinimumStack = 10; + + + static const CLR_UINT32 c_MethodKind_Native = 0x00000000; + static const CLR_UINT32 c_MethodKind_Interpreted = 0x00000001; + static const CLR_UINT32 c_UNUSED_00000002 = 0x00000002; // c_MethodKind_Jitted + static const CLR_UINT32 c_MethodKind_Mask = 0x00000003; + + static const CLR_UINT32 c_NativeProfiled = 0x00000004; + static const CLR_UINT32 c_MethodKind_Inlined = 0x00000008; + + static const CLR_UINT32 c_ExecutingConstructor = 0x00000010; + static const CLR_UINT32 c_CompactAndRestartOnOutOfMemory = 0x00000020; + static const CLR_UINT32 c_CallOnPop = 0x00000040; + static const CLR_UINT32 c_CalledOnPop = 0x00000080; + + static const CLR_UINT32 c_NeedToSynchronize = 0x00000100; + static const CLR_UINT32 c_PendingSynchronize = 0x00000200; + static const CLR_UINT32 c_Synchronized = 0x00000400; + static const CLR_UINT32 c_UNUSED_00000800 = 0x00000800; + + static const CLR_UINT32 c_NeedToSynchronizeGlobally = 0x00001000; + static const CLR_UINT32 c_PendingSynchronizeGlobally = 0x00002000; + static const CLR_UINT32 c_SynchronizedGlobally = 0x00004000; + static const CLR_UINT32 c_UNUSED_00008000 = 0x00008000; + + static const CLR_UINT32 c_ExecutingIL = 0x00010000; + static const CLR_UINT32 c_CallerIsCompatibleForCall = 0x00020000; + static const CLR_UINT32 c_CallerIsCompatibleForRet = 0x00040000; + static const CLR_UINT32 c_PseudoStackFrameForFilter = 0x00080000; + + static const CLR_UINT32 c_InlineMethodHasReturnValue = 0x00100000; + static const CLR_UINT32 c_UNUSED_00200000 = 0x00200000; + static const CLR_UINT32 c_UNUSED_00400000 = 0x00400000; + static const CLR_UINT32 c_UNUSED_00800000 = 0x00800000; + + static const CLR_UINT32 c_UNUSED_01000000 = 0x01000000; + static const CLR_UINT32 c_UNUSED_02000000 = 0x02000000; + + static const CLR_UINT32 c_AppDomainMethodInvoke = 0x04000000; + static const CLR_UINT32 c_AppDomainInjectException = 0x08000000; + static const CLR_UINT32 c_AppDomainTransition = 0x10000000; + static const CLR_UINT32 c_InvalidIP = 0x20000000; + static const CLR_UINT32 c_UNUSED_40000000 = 0x40000000; + static const CLR_UINT32 c_HasBreakpoint = 0x80000000; + + static const CLR_UINT32 c_ProcessSynchronize = c_NeedToSynchronize | c_PendingSynchronize | + c_NeedToSynchronizeGlobally | c_PendingSynchronizeGlobally ; + + //--// + + /////////////////////////////////////////////////////////////////////////////////////////// + // + // These fields have to be aligned + // + CLR_RT_Thread* m_owningThread; // EVENT HEAP - NO RELOCATION - + CLR_RT_HeapBlock* m_evalStack; // EVENT HEAP - NO RELOCATION - + CLR_RT_HeapBlock* m_arguments; // EVENT HEAP - NO RELOCATION - + CLR_RT_HeapBlock* m_locals; // EVENT HEAP - NO RELOCATION - + CLR_PMETADATA m_IP; // ANY HEAP - DO RELOCATION - + // + /////////////////////////////////////////////////////////////////////////////////////////// + + CLR_RT_SubThread* m_owningSubThread; // EVENT HEAP - NO RELOCATION - + CLR_UINT32 m_flags; + + CLR_RT_MethodDef_Instance m_call; + + CLR_RT_MethodHandler m_nativeMethod; + CLR_PMETADATA m_IPstart; // ANY HEAP - DO RELOCATION - + + CLR_RT_HeapBlock* m_evalStackPos; // EVENT HEAP - NO RELOCATION - + CLR_RT_HeapBlock* m_evalStackEnd; // EVENT HEAP - NO RELOCATION - + + union + { + CLR_UINT32 m_customState; + void* m_customPointer; + }; + + +#ifndef TINYCLR_NO_IL_INLINE + CLR_RT_InlineBuffer* m_inlineFrame; +#endif + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + CLR_UINT32 m_depth; +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + +#if defined(TINYCLR_PROFILE_NEW_CALLS) + CLR_PROF_CounterCallChain m_callchain; +#endif + +#if defined(TINYCLR_APPDOMAINS) + CLR_RT_AppDomain* m_appDomain; +#endif + +#if defined(ENABLE_NATIVE_PROFILER) + bool m_fNativeProfiled; +#endif + + CLR_RT_HeapBlock m_extension[ 1 ]; + + //////////////////////////////////////// + + static HRESULT Push( CLR_RT_Thread* th, const CLR_RT_MethodDef_Instance& callInst, CLR_INT32 extraBlocks ); + + void Pop(); + +#ifndef TINYCLR_NO_IL_INLINE + bool PushInline( CLR_PMETADATA& ip, CLR_RT_Assembly*& assm, CLR_RT_HeapBlock*& evalPos, CLR_RT_MethodDef_Instance& calleeInst, CLR_RT_HeapBlock* pThis); + void PopInline ( ); + + void RestoreFromInlineStack(); + void RestoreStack(CLR_RT_InlineFrame& frame); + void SaveStack(CLR_RT_InlineFrame& frame); +#endif + + +#if defined(TINYCLR_APPDOMAINS) + static HRESULT PushAppDomainTransition( CLR_RT_Thread* th, const CLR_RT_MethodDef_Instance& callInst, CLR_RT_HeapBlock* pThis, CLR_RT_HeapBlock* pArgs ); + HRESULT PopAppDomainTransition( ); +#endif + + HRESULT FixCall(); + HRESULT MakeCall ( CLR_RT_MethodDef_Instance md, CLR_RT_HeapBlock* blkThis, CLR_RT_HeapBlock* blkArgs, int nArgs ); + + HRESULT HandleSynchronized( bool fAcquire, bool fGlobal ); + + void SetResult ( CLR_INT32 val, CLR_DataType dataType ); + void SetResult_I4 ( CLR_INT32 val ); + void SetResult_I8 ( CLR_INT64& val ); + void SetResult_U4 ( CLR_UINT32 val ); + void SetResult_U8 ( CLR_UINT64& val ); + +#if !defined(TINYCLR_EMULATED_FLOATINGPOINT) + void SetResult_R4 ( float val ); + void SetResult_R8 ( double val ); +#else + void SetResult_R4 ( CLR_INT32 val ); + void SetResult_R8 ( CLR_INT64 val ); +#endif + + void SetResult_Boolean( bool val ); + void SetResult_Object ( CLR_RT_HeapBlock* val ); + HRESULT SetResult_String ( LPCSTR val ); + + HRESULT SetupTimeout( CLR_RT_HeapBlock& input, CLR_INT64*& output ); + + void ConvertResultToBoolean(); + void NegateResult (); + + HRESULT NotImplementedStub(); + + void Relocate(); + + //////////////////////////////////////// + + CLR_RT_HeapBlock& ThisRef() const { return m_arguments[ 0 ]; } + CLR_RT_HeapBlock* This() const { return ThisRef().Dereference(); } + + CLR_RT_HeapBlock& Arg0() const { return m_arguments[ 0 ]; } + CLR_RT_HeapBlock& Arg1() const { return m_arguments[ 1 ]; } + CLR_RT_HeapBlock& Arg2() const { return m_arguments[ 2 ]; } + CLR_RT_HeapBlock& Arg3() const { return m_arguments[ 3 ]; } + CLR_RT_HeapBlock& Arg4() const { return m_arguments[ 4 ]; } + CLR_RT_HeapBlock& Arg5() const { return m_arguments[ 5 ]; } + CLR_RT_HeapBlock& Arg6() const { return m_arguments[ 6 ]; } + CLR_RT_HeapBlock& Arg7() const { return m_arguments[ 7 ]; } + + CLR_RT_HeapBlock& ArgN( CLR_INT32 n ) const { return m_arguments[ n ]; } + + CLR_RT_HeapBlock& TopValue () { return m_evalStackPos[ -1 ]; } + CLR_RT_HeapBlock& PushValue () { _ASSERTE(m_evalStackPos < m_evalStackEnd); return * m_evalStackPos++; } + CLR_RT_HeapBlock& PopValue () { _ASSERTE(m_evalStackPos > m_evalStack ); return *--m_evalStackPos; } + void ResetStack () { m_evalStackPos = m_evalStack ; } + int TopValuePosition () { return (int)(m_evalStackPos - m_evalStack); } + + CLR_RT_MethodDef_Instance& MethodCall() { return m_call; } + + CLR_RT_HeapBlock& PushValueAndClear() + { + CLR_RT_HeapBlock& val = PushValue(); + + val.SetObjectReference( NULL ); + + return val; + } + + CLR_RT_HeapBlock& PushValueAndAssign( const CLR_RT_HeapBlock& value ) + { + CLR_RT_HeapBlock& top = PushValue(); + + top.Assign( value ); + + return top; + } + + + inline void PushValueI4( CLR_INT32 val ) { SetResult_I4( val ); } + + //--// + + CLR_RT_StackFrame* Caller() { return (CLR_RT_StackFrame*)Prev(); } + CLR_RT_StackFrame* Callee() { return (CLR_RT_StackFrame*)Next(); } + + PROHIBIT_ALL_CONSTRUCTORS(CLR_RT_StackFrame); +}; + +// +// This CT_ASSERT macro generates a compiler error in case these fields get out of alignment. +// + + +CT_ASSERT( offsetof(CLR_RT_StackFrame,m_owningThread) + sizeof(CLR_UINT32) == offsetof(CLR_RT_StackFrame,m_evalStack ) ) +CT_ASSERT( offsetof(CLR_RT_StackFrame,m_evalStack ) + sizeof(CLR_UINT32) == offsetof(CLR_RT_StackFrame,m_arguments ) ) +CT_ASSERT( offsetof(CLR_RT_StackFrame,m_arguments ) + sizeof(CLR_UINT32) == offsetof(CLR_RT_StackFrame,m_locals ) ) +CT_ASSERT( offsetof(CLR_RT_StackFrame,m_locals ) + sizeof(CLR_UINT32) == offsetof(CLR_RT_StackFrame,m_IP ) ) + +//////////////////////////////////////////////////////////////////////////////// + +struct CLR_RT_ProtectFromGC +{ + static const CLR_UINT32 c_Generic = 0x00000001; + static const CLR_UINT32 c_HeapBlock = 0x00000002; + static const CLR_UINT32 c_ResetKeepAlive = 0x00000004; + + typedef void (*Callback)( void* state ); + + static CLR_RT_ProtectFromGC* s_first; + + CLR_RT_ProtectFromGC* m_next; + void** m_data; + Callback m_fpn; + CLR_UINT32 m_flags; + + CLR_RT_ProtectFromGC ( CLR_RT_HeapBlock& ref ) { Initialize( ref ); } + CLR_RT_ProtectFromGC ( void** data, Callback fpn ) { Initialize( data, fpn ); } + ~CLR_RT_ProtectFromGC( ) { Cleanup ( ); } + + static void InvokeAll(); + +private: + void Initialize( CLR_RT_HeapBlock& ref ); + void Initialize( void** data, Callback fpn ); + void Cleanup ( ); + + void Invoke(); +}; + +//////////////////////////////////////// + +#if defined(TINYCLR_TRACE_EARLYCOLLECTION) + +struct CLR_RT_AssertEarlyCollection +{ + static CLR_RT_AssertEarlyCollection* s_first; + + CLR_RT_AssertEarlyCollection* m_next; + CLR_RT_HeapBlock* m_ptr; + + CLR_RT_AssertEarlyCollection( CLR_RT_HeapBlock* ptr ); + ~CLR_RT_AssertEarlyCollection(); + + void Cancel(); + + static void CheckAll( CLR_RT_HeapBlock* ptr ); +}; + +#define TINYCLR_FAULT_ON_EARLY_COLLECTION(ptr) CLR_RT_AssertEarlyCollection aec##ptr( ptr ) +#define TINYCLR_CANCEL_EARLY_COLLECTION(ptr) aec##ptr.Cancel() +#define TINYCLR_CHECK_EARLY_COLLECTION(ptr) CLR_RT_AssertEarlyCollection::CheckAll( ptr ) + +#else + +#define TINYCLR_FAULT_ON_EARLY_COLLECTION(ptr) +#define TINYCLR_CANCEL_EARLY_COLLECTION(ptr) +#define TINYCLR_CHECK_EARLY_COLLECTION(ptr) + +#endif + +//////////////////////////////////////// + +struct CLR_RT_GarbageCollector +{ + typedef bool (*MarkSingleFtn )( CLR_RT_HeapBlock** ptr ); + typedef bool (*MarkMultipleFtn)( CLR_RT_HeapBlock* lstExt, CLR_UINT32 numExt ); + typedef bool (*RelocateFtn )( void** ref ); + + struct MarkStackElement + { + CLR_RT_HeapBlock* ptr; + CLR_UINT32 num; +#if defined(TINYCLR_VALIDATE_APPDOMAIN_ISOLATION) + CLR_RT_AppDomain* appDomain; +#endif + }; + + struct MarkStack : CLR_RT_HeapBlock_Node + { + MarkStackElement* m_last; + MarkStackElement* m_top; + + void Initialize( MarkStackElement* ptr, size_t num ); + }; + + struct RelocationRegion + { + CLR_UINT8* m_start; + CLR_UINT8* m_end; + CLR_UINT8* m_destination; + CLR_UINT32 m_offset; + }; + + //--// + + static const int c_minimumSpaceForGC = 128; + static const int c_minimumSpaceForCompact = 128; + static const CLR_UINT32 c_pressureThreshold = 10; + static const CLR_UINT32 c_memoryThreshold = HEAP_SIZE_THRESHOLD; + static const CLR_UINT32 c_memoryThreshold2 = HEAP_SIZE_THRESHOLD_UPPER; + + static const CLR_UINT32 c_StartGraphEvent = 0x00000001; + static const CLR_UINT32 c_StopGraphEvent = 0x00000002; + static const CLR_UINT32 c_DumpGraphHeapEvent = 0x00000004; + static const CLR_UINT32 c_DumpPerfCountersEvent = 0x00000008; + + CLR_UINT32 m_numberOfGarbageCollections; + CLR_UINT32 m_numberOfCompactions; + + CLR_RT_DblLinkedList m_weakDelegates_Reachable; // list of CLR_RT_HeapBlock_Delegate_List + + + CLR_UINT32 m_totalBytes; + CLR_UINT32 m_freeBytes; + CLR_UINT32 m_pressureCounter; + + CLR_RT_DblLinkedList* m_markStackList; + MarkStack* m_markStack; + + RelocationRegion* m_relocBlocks; + size_t m_relocTotal; + size_t m_relocCount; + CLR_UINT8* m_relocMinimum; + CLR_UINT8* m_relocMaximum; +#if TINYCLR_VALIDATE_HEAP > TINYCLR_VALIDATE_HEAP_0_None + RelocateFtn m_relocWorker; +#endif + + MarkSingleFtn m_funcSingleBlock; + MarkMultipleFtn m_funcMultipleBlocks; + + bool m_fOutOfStackSpaceForGC; + +#if defined(_WIN32) + CLR_UINT32 m_events; +#endif + + //--// + + CLR_UINT32 ExecuteGarbageCollection(); + CLR_UINT32 ExecuteCompaction (); + + void Mark (); + void MarkWeak (); + void Sweep (); + void CheckMemoryPressure(); + +#if defined(TINYCLR_APPDOMAINS) + void AppDomain_Mark(); +#endif + + void Assembly_Mark(); + + void Thread_Mark( CLR_RT_DblLinkedList& threads ); + void Thread_Mark( CLR_RT_Thread* thread ); + + void Heap_Compact (); + CLR_UINT32 Heap_ComputeAliveVsDeadRatio(); + + void RecoverEventsFromGC(); + + void Heap_Relocate_Prepare ( RelocationRegion* blocks, size_t total ); + void Heap_Relocate_AddBlock( CLR_UINT8* dst, CLR_UINT8* src, CLR_UINT32 length ); + void Heap_Relocate ( ); + + //--// + + static void Heap_Relocate( CLR_RT_HeapBlock* lst, CLR_UINT32 len ); + static void Heap_Relocate( void** ref ); + + //--// + +#if TINYCLR_VALIDATE_HEAP >= TINYCLR_VALIDATE_HEAP_3_Compaction + + static bool Relocation_JustCheck( void** ref ); + + void ValidatePointers() { Heap_Relocate_Pass( Relocation_JustCheck ); } + + static void ValidateCluster ( CLR_RT_HeapCluster* hc ); + static void ValidateHeap ( CLR_RT_DblLinkedList& lst ); + static void ValidateBlockNotInFreeList( CLR_RT_DblLinkedList& lst, CLR_RT_HeapBlock_Node* dst ); + static bool IsBlockInFreeList ( CLR_RT_DblLinkedList& lst, CLR_RT_HeapBlock_Node* dst, bool fExact ); + static bool IsBlockInHeap ( CLR_RT_DblLinkedList& lst, CLR_RT_HeapBlock_Node* dst ); + +#else + + void ValidatePointers() {} + + static void ValidateCluster ( CLR_RT_HeapCluster* hc ) {} + static void ValidateHeap ( CLR_RT_DblLinkedList& lst ) {} + static void ValidateBlockNotInFreeList( CLR_RT_DblLinkedList& lst, CLR_RT_HeapBlock_Node* dst ) {} + +#endif + +#if TINYCLR_VALIDATE_HEAP >= TINYCLR_VALIDATE_HEAP_4_CompactionPlus + + struct RelocationRecord + { + void** oldRef; + CLR_UINT32* oldPtr; + + void** newRef; + CLR_UINT32* newPtr; + + CLR_UINT32 data; + }; + + typedef std::list Rel_List; + typedef Rel_List::iterator Rel_List_Iter; + + typedef std::map< void**, RelocationRecord* > Rel_Map; + typedef Rel_Map::iterator Rel_Map_Iter; + + static Rel_List s_lstRecords; + static Rel_Map s_mapOldToRecord; + static Rel_Map s_mapNewToRecord; + + + static bool TestPointers_PopulateOld_Worker( void** ref ); + static bool TestPointers_PopulateNew_Worker( void** ref ); + + void TestPointers_PopulateOld(); + void TestPointers_Remap (); + void TestPointers_PopulateNew(); + +#else + + void TestPointers_PopulateOld() {} + void TestPointers_Remap () {} + void TestPointers_PopulateNew() {} + +#endif + + //--// + +#if defined(TINYCLR_GC_VERBOSE) + + void GC_Stats( int& resNumberObjects, int& resSizeObjects, int& resNumberEvents, int& resSizeEvents ); + + void DumpThreads ( ); + +#else + + void GC_Stats( int& resNumberObjects, int& resSizeObjects, int& resNumberEvents, int& resSizeEvents ) + { + resNumberObjects = 0; + resSizeObjects = 0; + resNumberEvents = 0; + resSizeEvents = 0; + } + + void DumpThreads ( ) {} + +#endif + + //--// + + bool CheckSingleBlock( CLR_RT_HeapBlock** ptr ) { return m_funcSingleBlock( ( CLR_RT_HeapBlock* *)ptr ); } + bool CheckSingleBlock( CLR_RT_HeapBlock_Array** ptr ) { return m_funcSingleBlock( (CLR_RT_HeapBlock* *)ptr ); } + bool CheckSingleBlock( CLR_RT_HeapBlock_Delegate** ptr ) { return m_funcSingleBlock( (CLR_RT_HeapBlock* *)ptr ); } + + bool CheckSingleBlock_Force( CLR_RT_HeapBlock* ptr ) { return ptr ? m_funcMultipleBlocks( ptr, 1 ) : true; } + bool CheckMultipleBlocks ( CLR_RT_HeapBlock* lst, CLR_UINT32 num ) { return lst ? m_funcMultipleBlocks( lst, num ) : true; } + + //--// + + static bool ComputeReachabilityGraphForSingleBlock ( CLR_RT_HeapBlock** ptr ); + static bool ComputeReachabilityGraphForMultipleBlocks( CLR_RT_HeapBlock* lst, CLR_UINT32 num ); + + //--// + + PROHIBIT_COPY_CONSTRUCTORS(CLR_RT_GarbageCollector); + + //--// + +private: + + void Heap_Relocate_Pass( RelocateFtn ftn ); + + void MarkSlow(); +}; + +extern CLR_RT_GarbageCollector g_CLR_RT_GarbageCollector; + +//--// + +struct CLR_RT_SubThread : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - +{ + static const int MODE_IncludeSelf = 0x00000001; + static const int MODE_CheckLocks = 0x00000002; + + static const int STATUS_Triggered = 0x00000001; + + CLR_RT_Thread* m_owningThread; // EVENT HEAP - NO RELOCATION - + CLR_RT_StackFrame* m_owningStackFrame; + CLR_UINT32 m_lockRequestsCount; + + int m_priority; + CLR_INT64 m_timeConstraint; + CLR_UINT32 m_status; + + //--// + + static HRESULT CreateInstance ( CLR_RT_Thread* th, CLR_RT_StackFrame* stack , int priority, CLR_RT_SubThread*& sth ); + static void DestroyInstance( CLR_RT_Thread* th, CLR_RT_SubThread* sthBase, int flags ); + + bool ChangeLockRequestCount( int diff ); + + //--// + + PROHIBIT_ALL_CONSTRUCTORS(CLR_RT_SubThread); +}; + +//--// + +struct CLR_RT_ExceptionHandler +{ + union { + CLR_RT_TypeDef_Index m_typeFilter; + CLR_PMETADATA m_userFilterStart; + }; + CLR_PMETADATA m_tryStart; + CLR_PMETADATA m_tryEnd; + CLR_PMETADATA m_handlerStart; + CLR_PMETADATA m_handlerEnd; + + CLR_UINT16 m_ehType; + //--// + + bool ConvertFromEH( const CLR_RT_MethodDef_Instance& owner, CLR_PMETADATA ipStart, const CLR_RECORD_EH* ehPtr ); + + bool IsCatch() const { return m_ehType == CLR_RECORD_EH::EH_Catch ; } + bool IsCatchAll() const { return m_ehType == CLR_RECORD_EH::EH_CatchAll ; } + bool IsFilter() const { return m_ehType == CLR_RECORD_EH::EH_Filter ; } + bool IsFinally() const { return m_ehType == CLR_RECORD_EH::EH_Finally ; } + +}; + + +// +// Directly from the .NET enumerator. +// +struct ThreadPriority +{ + /*========================================================================= + ** Constants for thread priorities. + =========================================================================*/ + static const int Lowest = 0; + static const int BelowNormal = 1; + static const int Normal = 2; + static const int AboveNormal = 3; + static const int Highest = 4; + // One more priority for internal creation of managed code threads. + // We do not expose this priority to C# applications. + static const int System_Highest = 5; +}; + +struct CLR_RT_Thread : public CLR_RT_ObjectToEvent_Destination // EVENT HEAP - NO RELOCATION - +{ + typedef void (*ThreadTerminationCallback)( void* arg ); + + struct UnwindStack + { + CLR_RT_StackFrame* m_stack; + CLR_RT_HeapBlock* m_exception; + CLR_PMETADATA m_ip; + + CLR_PMETADATA m_currentBlockStart; + CLR_PMETADATA m_currentBlockEnd; + CLR_PMETADATA m_handlerBlockStart; + CLR_PMETADATA m_handlerBlockEnd; + + CLR_RT_StackFrame* m_handlerStack; + CLR_UINT8 m_flags; + + static const CLR_UINT8 p_Phase_Mask = 0x07; + static const CLR_UINT8 p_1_SearchingForHandler_0 = 0x01; + static const CLR_UINT8 p_1_SearchingForHandler_1_SentFirstChance = 0x02; + static const CLR_UINT8 p_1_SearchingForHandler_2_SentUsersChance = 0x03; + static const CLR_UINT8 p_2_RunningFinallys_0 = 0x04; + static const CLR_UINT8 p_2_RunningFinallys_1_SentUnwindBegin = 0x05; + static const CLR_UINT8 p_3_RunningHandler = 0x06; + static const CLR_UINT8 p_4_NormalCleanup = 0x07; + + static const CLR_UINT8 c_MagicCatchForInline = 0x20; + static const CLR_UINT8 c_MagicCatchForInteceptedException = 0x40; + static const CLR_UINT8 c_ContinueExceptionHandler = 0x80; + + CLR_UINT8 inline GetPhase() { return m_flags & p_Phase_Mask; } + void inline SetPhase(CLR_UINT8 phase) + { + _ASSERTE((phase & ~p_Phase_Mask) == 0); + m_flags = (m_flags & ~p_Phase_Mask) | phase; + } + + }; + + static const CLR_UINT32 TH_S_Ready = 0x00000000; + static const CLR_UINT32 TH_S_Waiting = 0x00000001; + static const CLR_UINT32 TH_S_Terminated = 0x00000002; + static const CLR_UINT32 TH_S_Unstarted = 0x00000003; + + static const CLR_UINT32 TH_F_Suspended = 0x00000001; + static const CLR_UINT32 TH_F_Aborted = 0x00000002; + static const CLR_UINT32 TH_F_System = 0x00000004; + static const CLR_UINT32 TH_F_ContainsDoomedAppDomain = 0x00000008; + + static const CLR_INT32 TH_WAIT_RESULT_INIT = -1; + static const CLR_INT32 TH_WAIT_RESULT_HANDLE_0 = 0; + static const CLR_INT32 TH_WAIT_RESULT_TIMEOUT = 0x102; //WaitHandle.WaitTimeout + static const CLR_INT32 TH_WAIT_RESULT_HANDLE_ALL = 0x103; + + static const CLR_UINT32 c_TimeQuantum_Milliseconds = 20; + static const int c_MaxStackUnwindDepth = 6; + + int m_pid; + CLR_UINT32 m_status; + CLR_UINT32 m_flags; + int m_executionCounter; + volatile BOOL m_timeQuantumExpired; + + CLR_RT_HeapBlock_Delegate* m_dlg; // OBJECT HEAP - DO RELOCATION - + CLR_RT_HeapBlock m_currentException; // OBJECT HEAP - DO RELOCATION - + UnwindStack m_nestedExceptions[ c_MaxStackUnwindDepth ]; + int m_nestedExceptionsPos; + + //--// + + // + // For example, timers are implemented in terms of Threads. If not NULL, this is a worker thread for a timer. + // + ThreadTerminationCallback m_terminationCallback; + void* m_terminationParameter; // EVENT HEAP - NO RELOCATION - + + CLR_UINT32 m_waitForEvents; + CLR_INT64 m_waitForEvents_Timeout; + CLR_INT64 m_waitForEvents_IdleTimeWorkItem; + + CLR_RT_DblLinkedList m_locks; // EVENT HEAP - NO RELOCATION - list of CLR_RT_HeapBlock_Lock + CLR_UINT32 m_lockRequestsCount; + + CLR_RT_HeapBlock_WaitForObject* m_waitForObject; // EVENT HEAP - NO RELOCATION, but the objects they point to do + CLR_INT32 m_waitForObject_Result; + + CLR_RT_DblLinkedList m_stackFrames; // EVENT HEAP - NO RELOCATION - list of CLR_RT_StackFrame + + CLR_RT_DblLinkedList m_subThreads; // EVENT HEAP - NO RELOCATION - list of CLR_RT_SubThread + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + int m_scratchPad; + bool m_fHasJMCStepper; + + CLR_RT_Thread* m_realThread; // Normally, this points to the CLR_RT_Thread object that contains it. + // However, if this thread was spawned on behalf of the debugger to evaluate + // a property or function call, it points to the object coresponding to the + // thread that is currently selected in the debugger. +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + +#if defined(ENABLE_NATIVE_PROFILER) + bool m_fNativeProfiled; +#endif + + //--// + + static HRESULT CreateInstance( int pid, CLR_RT_HeapBlock_Delegate* pDelegate, int priority, CLR_RT_Thread*& th, CLR_UINT32 flags ); + static HRESULT CreateInstance( int pid, int priority, CLR_RT_Thread*& th, CLR_UINT32 flags ); + HRESULT PushThreadProcDelegate( CLR_RT_HeapBlock_Delegate* pDelegate ); + + void DestroyInstance(); + + HRESULT Execute (); + + HRESULT Suspend (); + HRESULT Resume (); + HRESULT Terminate(); + HRESULT Abort (); + + void Restart( bool fDeleteEvent ); + + void Passivate(); + + bool CouldBeActivated(); + + void RecoverFromGC(); + + void Relocate(); + + UnwindStack* PushEH ( ); + void PopEH_Inner( CLR_RT_StackFrame* stack, CLR_PMETADATA ip ); + bool FindEhBlock( CLR_RT_StackFrame* stack, CLR_PMETADATA from, CLR_PMETADATA to, CLR_RT_ExceptionHandler& eh, bool onlyFinallys ); + + + HRESULT ProcessException ( ); + HRESULT ProcessException_EndFilter ( ); + HRESULT ProcessException_EndFinally ( ); + HRESULT ProcessException_Phase1 ( ); + HRESULT ProcessException_Phase2 ( ); + void ProcessException_FilterPseudoFrameCopyVars(CLR_RT_StackFrame* to, CLR_RT_StackFrame* from); + + static void ProtectFromGCCallback( void* state ); + + static HRESULT Execute_DelegateInvoke( CLR_RT_StackFrame* stack ); + static HRESULT Execute_IL ( CLR_RT_StackFrame* stack ); + + //--// + + CLR_RT_StackFrame* FirstFrame () const { return (CLR_RT_StackFrame*)m_stackFrames.FirstNode(); } + CLR_RT_StackFrame* CurrentFrame() const { return (CLR_RT_StackFrame*)m_stackFrames.LastNode (); } + + CLR_RT_SubThread* CurrentSubThread() const { return (CLR_RT_SubThread*)m_subThreads.LastNode(); } + +#if defined(TINYCLR_APPDOMAINS) + CLR_RT_AppDomain* CurrentAppDomain() const { CLR_RT_StackFrame* stack = CurrentFrame(); return stack->Prev() ? stack->m_appDomain : NULL; } +#endif + + // Just return priority, no way to set it through this function. + int GetThreadPriority() const { return CurrentSubThread()->m_priority; } + // Here we set it. This function is called if managed code changes thread priority. + void SetThreadPriority( int threadPri ) { CurrentSubThread()->m_priority = threadPri; } + + int GetExecutionCounter() const { return CurrentSubThread()->m_priority + m_executionCounter; } + + // QuantumDebit is update for execution counter for each quantum: + // System_Highest - 1 + // Highest - 2 + // Above Normal - 4 + // Normal - 8 + // Below Normal - 16 + // Lowest - 32 + int GetQuantumDebit() const { return 1 << ( ThreadPriority::System_Highest - GetThreadPriority() ); } + + // If thread was sleeping and get too far behind on updating of m_executionCounter + // Then we make m_executionCounter 4 quantums above m_GlobalExecutionCounter; + void BringExecCounterToDate( int iGlobalExecutionCounter, int iDebitForEachRun ); + + void PopEH( CLR_RT_StackFrame* stack, CLR_PMETADATA ip ) { if(m_nestedExceptionsPos) PopEH_Inner( stack, ip ); } + +#if defined(TINYCLR_TRACE_CALLS) + void DumpStack(); +#else + void DumpStack() {} +#endif + + bool IsFinalizerThread(); + bool ReleaseWhenDeadEx(); + void OnThreadTerminated(); + bool CanThreadBeReused(); + + //--// + + PROHIBIT_ALL_CONSTRUCTORS(CLR_RT_Thread); + + //--// + +private: + + HRESULT Execute_Inner(); +}; + +//////////////////////////////////////////////////////////////////////////////// + +extern size_t LinkArraySize (); +extern size_t LinkMRUArraySize(); +extern size_t PayloadArraySize(); +extern size_t InterruptRecords(); +#ifndef TINYCLR_NO_IL_INLINE +extern size_t InlineBufferCount(); +#endif + + +extern CLR_UINT32 g_scratchVirtualMethodTableLink []; +extern CLR_UINT32 g_scratchVirtualMethodTableLinkMRU []; +extern CLR_UINT32 g_scratchVirtualMethodPayload []; +extern CLR_UINT32 g_scratchInterruptDispatchingStorage[]; +#ifndef TINYCLR_NO_IL_INLINE +extern CLR_UINT32 g_scratchInlineBuffer []; +#endif + +//////////////////////////////////////////////////////////////////////////////// + +struct CLR_RT_EventCache +{ + struct BoundedList + { + CLR_RT_DblLinkedList m_blocks; + }; + +#if defined(TINYCLR_USE_AVLTREE_FOR_METHODLOOKUP) + + struct Payload + { + // + // The first two fields compose the key, the last field is the value. + // + CLR_RT_MethodDef_Index m_mdVirtual; // The definition of the virtual method. + CLR_RT_TypeDef_Index m_cls; // The class of the instance we need to resolve. + CLR_RT_MethodDef_Index m_md; // The actual implementation of the virtual method. + + //--// + + int Compare( Payload& right ) + { + if(m_mdVirtual.m_data == right.m_mdVirtual.m_data) + { + if(m_cls.m_data == right.m_cls.m_data) return 0; + + return m_cls.m_data < right.m_cls.m_data ? -1 : 1; + } + + return m_mdVirtual.m_data < right.m_mdVirtual.m_data ? -1 : 1; + } + }; + + struct LookupEntry : public CLR_RT_AVLTree::Entry + { + Payload m_payload; + + //--// + + static int Callback_Compare( void* state, CLR_RT_AVLTree::Entry* left, CLR_RT_AVLTree::Entry* right ); + }; + + struct VirtualMethodTable + { + CLR_RT_AVLTree m_tree; + LookupEntry* m_entries; + + CLR_RT_DblLinkedList m_list_freeItems; // list of CLR_RT_EventCache::LookupEntry + CLR_RT_DblLinkedList m_list_inUse; // list of CLR_RT_EventCache::LookupEntry + + //--// + + void Initialize(); + + bool FindVirtualMethod( const CLR_RT_TypeDef_Index& cls, const CLR_RT_MethodDef_Index& mdVirtual, CLR_RT_MethodDef_Index& md ); + + //--// + + static CLR_RT_AVLTree::Entry* Callback_NewNode ( void* state, CLR_RT_AVLTree::Entry* payload ); + static void Callback_FreeNode( void* state, CLR_RT_AVLTree::Entry* node ); + static void Callback_Reassign( void* state, CLR_RT_AVLTree::Entry* from, CLR_RT_AVLTree::Entry* to ); + + //--// + +#if defined(_WIN32) + void DumpTree ( ); + bool ConsistencyCheck( ); + bool ConsistencyCheck( LookupEntry* node, int& depth ); +#else + void DumpTree () { } + bool ConsistencyCheck() { return true; } +#endif + }; + +#else + + struct Link + { + CLR_UINT16 m_next; + CLR_UINT16 m_prev; + }; + + struct Payload + { + struct Key + { + CLR_RT_MethodDef_Index m_mdVirtual; // The definition of the virtual method. + CLR_RT_TypeDef_Index m_cls; // The class of the instance we need to resolve. + }; + + Key m_key; + CLR_RT_MethodDef_Index m_md; // The actual implementation of the virtual method. + }; + + struct VirtualMethodTable + { + Link* m_entries; + Link* m_entriesMRU; + Payload* m_payloads; + + //--// + + void Initialize(); + + bool FindVirtualMethod( const CLR_RT_TypeDef_Index& cls, const CLR_RT_MethodDef_Index& mdVirtual, CLR_RT_MethodDef_Index& md ); + + private: + + CLR_UINT32 GetNewEntry() { return m_entriesMRU[ LinkMRUArraySize() - 1 ].m_prev; } + + static void MoveEntryToTop( Link* entries, CLR_UINT32 slot, CLR_UINT32 idx ); + }; +#endif + + //--// + + static const CLR_UINT16 c_maxFastLists = 40; + + // the scratch array is used to avoid bringing in arm ABI methods (for semihosting) + // struct arrays require initialization with the v3.0 compiler and this is done with ABI methods, + // unless of course you provide a work around lik this ;-) + UINT32 m_scratch[ (sizeof(BoundedList) * c_maxFastLists + 3) / sizeof(UINT32) ]; + BoundedList* m_events; + + VirtualMethodTable m_lookup_VirtualMethod; +#ifndef TINYCLR_NO_IL_INLINE + CLR_RT_InlineBuffer* m_inlineBufferStart; +#endif + + //--// + + void EventCache_Initialize(); + CLR_UINT32 EventCache_Cleanup (); + + void Append_Node ( CLR_RT_HeapBlock* node ); + CLR_RT_HeapBlock* Extract_Node_Slow ( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 blocks ); + CLR_RT_HeapBlock* Extract_Node_Fast ( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 blocks ); + CLR_RT_HeapBlock* Extract_Node_Bytes( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 bytes ); + CLR_RT_HeapBlock* Extract_Node ( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 blocks ); + + bool FindVirtualMethod( const CLR_RT_TypeDef_Index& cls, const CLR_RT_MethodDef_Index& mdVirtual, CLR_RT_MethodDef_Index& md ); + +#ifndef TINYCLR_NO_IL_INLINE + bool GetInlineFrameBuffer(CLR_RT_InlineBuffer** ppBuffer); + bool FreeInlineBuffer(CLR_RT_InlineBuffer* pBuffer); +#endif + + //--// + +#define EVENTCACHE_EXTRACT_NODE_AS_BYTES(ev,cls,type,flags,size) (cls*)((ev).Extract_Node_Bytes( type, flags, size )) +#define EVENTCACHE_EXTRACT_NODE_AS_BLOCKS(ev,cls,type,flags,size) (cls*)((ev).Extract_Node( type, flags, size )) +#define EVENTCACHE_EXTRACT_NODE(ev,cls,type) EVENTCACHE_EXTRACT_NODE_AS_BLOCKS(ev,cls,type, 0,CONVERTFROMSIZETOHEAPBLOCKS(sizeof(cls))) +#define EVENTCACHE_EXTRACT_NODE_NOALLOC(ev,cls,type) EVENTCACHE_EXTRACT_NODE_AS_BLOCKS(ev,cls,type,CLR_RT_HeapBlock::HB_NoGcOnFailure ,CONVERTFROMSIZETOHEAPBLOCKS(sizeof(cls))) +#define EVENTCACHE_EXTRACT_NODE_INITTOZERO(ev,cls,type) EVENTCACHE_EXTRACT_NODE_AS_BLOCKS(ev,cls,type,CLR_RT_HeapBlock::HB_InitializeToZero,CONVERTFROMSIZETOHEAPBLOCKS(sizeof(cls))) + + //--// + + PROHIBIT_COPY_CONSTRUCTORS(CLR_RT_EventCache); +}; + +extern CLR_RT_EventCache g_CLR_RT_EventCache; + +////////////////////////////////////////////////////////////////////////////////////// +// keep under control the size of the Link and Payload, since we will use externally +// defined arrays to handle those data structures in the Virtual Method cache + +#if defined(TINYCLR_USE_AVLTREE_FOR_METHODLOOKUP) +CT_ASSERT( sizeof(CLR_RT_EventCache::LookupEntry) == 12 ) +#else +CT_ASSERT( sizeof(CLR_RT_EventCache::Link) == 4 ) +CT_ASSERT( sizeof(CLR_RT_EventCache::Payload) == 12 ) +#endif + +////////////////////////////////////////////////////////////////////////////////////// + +//--// + +#include +#include +//#include + +//--// + +#if defined(TINYCLR_TRACE_STACK) + +// +// If this is set, no memory allocation should be allowed, it could lead to a GC while in an inconsistent state!! +// +extern bool g_CLR_RT_fBadStack; + +#endif + +//--// + +struct CLR_RT_ExecutionEngine +{ + static const CLR_UINT32 c_Event_SerialPort = 0x00000002; + static const CLR_UINT32 c_Event_Battery = 0x00000008; + static const CLR_UINT32 c_Event_AirPressure = 0x00000010; + static const CLR_UINT32 c_Event_HeartRate = 0x00000020; + static const CLR_UINT32 c_Event_I2C = 0x00000040; + static const CLR_UINT32 c_Event_IO = 0x00000080; + static const CLR_UINT32 c_Event_EndPoint = 0x01000000; + static const CLR_UINT32 c_Event_AppDomain = 0x02000000; + static const CLR_UINT32 c_Event_Socket = 0x20000000; + static const CLR_UINT32 c_Event_IdleCPU = 0x40000000; + static const CLR_UINT32 c_Event_LowMemory = 0x80000000; // Wait for a low-memory condition. + + + //////////////////////////////////////////////////////////////////////////////////////////////// + + static const CLR_UINT32 c_Compile_CPP = 0x00000001; + static const CLR_UINT32 c_Compile_ARM = 0x00000002; + + //////////////////////////////////////////////////////////////////////////////////////////////// + + static const int c_HeapState_Normal = 0x00000000; + static const int c_HeapState_UnderGC = 0x00000001; + + //////////////////////////////////////////////////////////////////////////////////////////////// + + static const int c_fDebugger_Unused00000001 = 0x00000001; + static const int c_fDebugger_Unused00000002 = 0x00000002; + static const int c_fDebugger_Unused00000004 = 0x00000004; + // + static const int c_fDebugger_LcdSendFrame = 0x00000100; + static const int c_fDebugger_LcdSendFrameNotification = 0x00000200; + // + static const int c_fDebugger_State_Initialize = 0x00000000; + static const int c_fDebugger_State_ProgramRunning = 0x00000400; + static const int c_fDebugger_State_ProgramExited = 0x00000800; + static const int c_fDebugger_State_Mask = 0x00000c00; + // + static const int c_fDebugger_BreakpointsDisabled = 0x00001000; + // + static const int c_fDebugger_Quiet = 0x00010000; // Do not spew debug text to the debugger + static const int c_fDebugger_ExitPending = 0x00020000; + // + static const int c_fDebugger_PauseTimers = 0x04000000; // Threads associated with timers are created in "suspended" mode. + static const int c_fDebugger_NoCompaction = 0x08000000; // Don't perform compaction during execution. + // + static const int c_fDebugger_SourceLevelDebugging = 0x10000000; + static const int c_fDebugger_RebootPending = 0x20000000; + static const int c_fDebugger_Enabled = 0x40000000; + static const int c_fDebugger_Stopped = 0x80000000; + + volatile int m_iDebugger_Conditions; + + //////////////////////////////////////////////////////////////////////////////////////////////// + + static const int c_fExecution_GC_Pending = 0x00000001; //Not currently used + static const int c_fExecution_Compaction_Pending = 0x00000002; +#if defined(TINYCLR_APPDOMAINS) + static const int c_fExecution_UnloadingAppDomain = 0x00000004; +#endif + + int m_iExecution_Conditions; + + static const int c_fReboot_Normal = 0x00000000; + static const int c_fReboot_ClrOnly = 0x00000001; + static const int c_fReboot_EnterBootLoader = 0x00000002; + static const int c_fReboot_ClrOnlyStopDebugger = 0x00000004 | c_fReboot_ClrOnly; + + int m_iReboot_Options; + + //////////////////////////////////////////////////////////////////////////////////////////////// + + static const int c_fProfiling_Enabled = 0x00000001; + static const int c_fProfiling_Allocations = 0x00000002; + static const int c_fProfiling_Calls = 0x00000004; + static const int c_fProfiling_TinyCLRTypes = 0x00000008; //Don't dump out certain types, like ASSEMBLY, or THREAD, or BINARY_BLOB, etc. + int m_iProfiling_Conditions; + + enum + { EXECUTION_COUNTER_MAXIMUM = 0x70000000, // Threshold value when we increase all execution counters to avoid overflow + EXECUTION_COUNTER_ADJUSTMENT = 0x60000000 // The update ( increase ) value for all executioin counters after threshold is reached. + }; + //////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + static const int c_MaxBreakpointsActive = 5; + + size_t m_breakpointsNum; + CLR_DBG_Commands::Debugging_Execution_BreakpointDef* m_breakpoints; + CLR_DBG_Commands::Debugging_Execution_BreakpointDef m_breakpointsActive[ c_MaxBreakpointsActive ]; + size_t m_breakpointsActiveNum; +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + +#if !defined(BUILD_RTM) || defined(_WIN32) + bool m_fPerformGarbageCollection; //Should the EE do a GC every context switch + bool m_fPerformHeapCompaction; //Should the EE do a Compaction following every GC +#endif + +#if defined(TINYCLR_APPDOMAINS) + static const int c_AppDomainId_Invalid = 0; + + CLR_RT_DblLinkedList m_appDomains; + CLR_RT_AppDomain* m_appDomainCurrent; + int m_appDomainIdNext; + + CLR_RT_AppDomain* SetCurrentAppDomain( CLR_RT_AppDomain* appDomain ); + CLR_RT_AppDomain* GetCurrentAppDomain( ); + + HRESULT UnloadAppDomain ( CLR_RT_AppDomain* appDomain, CLR_RT_Thread* th ); + void PrepareThreadsForAppDomainUnload( CLR_RT_AppDomain* appDomain, CLR_RT_DblLinkedList& threads ); + + void TryToUnloadAppDomains_Helper_Threads ( CLR_RT_DblLinkedList& threads ); + void TryToUnloadAppDomains_Helper_Finalizers( CLR_RT_DblLinkedList& finalizers, bool fAlive ); + bool TryToUnloadAppDomains ( ); +#endif //TINYCLR_APPDOMAINS + +#define CLR_EE_DBG_IS( Cond ) ((g_CLR_RT_ExecutionEngine.m_iDebugger_Conditions & CLR_RT_ExecutionEngine::c_fDebugger_##Cond) != 0) +#define CLR_EE_DBG_IS_NOT( Cond ) ((g_CLR_RT_ExecutionEngine.m_iDebugger_Conditions & CLR_RT_ExecutionEngine::c_fDebugger_##Cond) == 0) +#define CLR_EE_DBG_SET( Cond ) g_CLR_RT_ExecutionEngine.m_iDebugger_Conditions |= CLR_RT_ExecutionEngine::c_fDebugger_##Cond +#define CLR_EE_DBG_CLR( Cond ) g_CLR_RT_ExecutionEngine.m_iDebugger_Conditions &= ~CLR_RT_ExecutionEngine::c_fDebugger_##Cond +#define CLR_EE_DBG_SET_MASK( Cond, Mask ) CLR_EE_DBG_CLR( Mask ); CLR_EE_DBG_SET( Cond ); +#define CLR_EE_DBG_RESTORE( Cond, f ) ((f) ? CLR_EE_DBG_SET( Cond ) : CLR_EE_DBG_CLR( Cond ) ) +#define CLR_EE_DBG_IS_MASK( Cond, Mask ) ((g_CLR_RT_ExecutionEngine.m_iDebugger_Conditions & CLR_RT_ExecutionEngine::c_fDebugger_##Mask) == CLR_RT_ExecutionEngine::c_fDebugger_##Cond) + +#define CLR_EE_PRF_IS( Cond ) ((g_CLR_RT_ExecutionEngine.m_iProfiling_Conditions & CLR_RT_ExecutionEngine::c_fProfiling_##Cond) != 0) +#define CLR_EE_PRF_IS_NOT( Cond ) ((g_CLR_RT_ExecutionEngine.m_iProfiling_Conditions & CLR_RT_ExecutionEngine::c_fProfiling_##Cond) == 0) + +#define CLR_EE_IS( Cond ) ((g_CLR_RT_ExecutionEngine.m_iExecution_Conditions & CLR_RT_ExecutionEngine::c_fExecution_##Cond) != 0) +#define CLR_EE_IS_NOT( Cond ) ((g_CLR_RT_ExecutionEngine.m_iExecution_Conditions & CLR_RT_ExecutionEngine::c_fExecution_##Cond) == 0) +#define CLR_EE_SET( Cond ) g_CLR_RT_ExecutionEngine.m_iExecution_Conditions |= CLR_RT_ExecutionEngine::c_fExecution_##Cond +#define CLR_EE_CLR( Cond ) g_CLR_RT_ExecutionEngine.m_iExecution_Conditions &= ~CLR_RT_ExecutionEngine::c_fExecution_##Cond + +#define CLR_EE_REBOOT_IS( Cond ) ((g_CLR_RT_ExecutionEngine.m_iReboot_Options & CLR_RT_ExecutionEngine::c_fReboot_##Cond) == CLR_RT_ExecutionEngine::c_fReboot_##Cond) +#define CLR_EE_REBOOT_SET( Cond ) g_CLR_RT_ExecutionEngine.m_iReboot_Options |= CLR_RT_ExecutionEngine::c_fReboot_##Cond +#define CLR_EE_REBOOT_CLR( Cond ) g_CLR_RT_ExecutionEngine.m_iReboot_Options &= ~CLR_RT_ExecutionEngine::c_fReboot_##Cond + +#define CLR_EE_DBG_EVENT_SEND( cmd, size, payload, flags ) ((g_CLR_DBG_Debuggers[ DEBUGGER_PORT_INDEX ].m_messaging != NULL) ? g_CLR_DBG_Debuggers[ DEBUGGER_PORT_INDEX ].m_messaging->SendEvent( cmd, size, (UINT8*)payload, flags ) : false) + +#if NUM_MESSAGING == 1 + #define CLR_EE_MSG_EVENT_RPC( cmd, size, payload, flags ) g_CLR_Messaging[ 0 ].SendEvent( cmd, size, (UINT8*)payload, flags ) +#else + #define CLR_EE_MSG_EVENT_RPC( cmd, size, payload, flags ) CLR_Messaging::BroadcastEvent( cmd, size, (UINT8*)payload, flags ) +#endif + +#if NUM_DEBUGGERS == 1 + #define CLR_EE_DBG_EVENT_BROADCAST( cmd, size, payload, flags ) CLR_EE_DBG_EVENT_SEND( cmd, size, payload, flags ) +#else + #define CLR_EE_DBG_EVENT_BROADCAST( cmd, size, payload, flags ) CLR_DBG_Debugger::BroadcastEvent( cmd, size, (UINT8*)payload, flags ) +#endif + + //////////////////////////////////////////////////////////////////////////////////////////////// + + // + // Used to subtract system time (GC, compaction, other) from ExecutionConstraint checks. + // + struct ExecutionConstraintCompensation + { + CLR_INT32 m_recursion; + CLR_INT64 m_start; + CLR_INT64 m_cumulative; + + void Suspend() + { + if(m_recursion++ == 0) + { + m_start = HAL_Time_CurrentTicks(); + } + } + + void Resume() + { + if(m_recursion) + { + if(--m_recursion == 0) + { + m_cumulative += (HAL_Time_CurrentTicks() - m_start); + } + } + } + + CLR_INT64 Adjust( CLR_INT64 time ) const + { + return time + ::HAL_Time_TicksToTime( m_cumulative ); + } + }; + + static ExecutionConstraintCompensation s_compensation; + + //--// + + CLR_INT64 m_maximumTimeToActive; + + //--// + + CLR_INT64 m_currentMachineTime; + CLR_INT64 m_currentLocalTime; + CLR_INT64 m_startTime; + CLR_INT32 m_lastTimeZoneOffset; + CLR_INT64 m_currentNextActivityTime; + bool m_timerCache; + CLR_INT64 m_timerCacheNextTimeout; + + CLR_RT_DblLinkedList m_heap; // list of CLR_RT_HeapCluster + CLR_RT_HeapCluster* m_lastHcUsed; + int m_heapState; + + CLR_RT_DblLinkedList m_weakReferences; // OBJECT HEAP - DO RELOCATION - list of CLR_RT_HeapBlock_WeakReference + + CLR_RT_DblLinkedList m_timers; // EVENT HEAP - NO RELOCATION - list of CLR_RT_HeapBlock_Timer + CLR_UINT32 m_raisedEvents; + + CLR_RT_DblLinkedList m_threadsReady; // EVENT HEAP - NO RELOCATION - list of CLR_RT_Thread + CLR_RT_DblLinkedList m_threadsWaiting; // EVENT HEAP - NO RELOCATION - list of CLR_RT_Thread + CLR_RT_DblLinkedList m_threadsZombie; // EVENT HEAP - NO RELOCATION - list of CLR_RT_Thread + int m_lastPid; + CLR_RT_Thread* m_currentThread; + + CLR_RT_DblLinkedList m_finalizersAlive; // EVENT HEAP - NO RELOCATION - list of CLR_RT_HeapBlock_Finalizer + CLR_RT_DblLinkedList m_finalizersPending; // EVENT HEAP - NO RELOCATION - list of CLR_RT_HeapBlock_Finalizer + CLR_RT_Thread* m_finalizerThread; // EVENT HEAP - NO RELOCATION - + CLR_RT_Thread* m_cctorThread; // EVENT HEAP - NO RELOCATION - + +#if !defined(TINYCLR_APPDOMAINS) + CLR_RT_HeapBlock* m_globalLock; // OBJECT HEAP - DO RELOCATION - + CLR_RT_HeapBlock* m_outOfMemoryException; // OBJECT HEAP - DO RELOCATION - +#endif + + CLR_RT_HeapBlock* m_currentUICulture; // OBJECT HEAP - DO RELOCATION - + + //--// + + CLR_RT_Thread* m_interruptThread; // EVENT HEAP - NO RELOCATION + CLR_RT_Thread* m_timerThread; // EVENT HEAP - NO RELOCATION + + //--// + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + CLR_RT_HeapBlock_Array* m_scratchPadArray; // OBJECT HEAP - DO RELOCATION - +#endif + + bool m_fShuttingDown; + + //--// + + static HRESULT CreateInstance(); + + HRESULT ExecutionEngine_Initialize(); + + static HRESULT DeleteInstance(); + + void ExecutionEngine_Cleanup(); + + HRESULT StartHardware(); + + static void Reboot( bool fHard ); + + void JoinAllThreadsAndExecuteFinalizer(); + + void LoadDownloadedAssemblies(); + + static void ExecutionConstraint_Suspend(); + static void ExecutionConstraint_Resume (); + + CLR_UINT32 PerformGarbageCollection(); + void PerformHeapCompaction (); + + void Relocate(); + + HRESULT ScheduleThreads( int maxContextSwitch ); + + CLR_UINT32 WaitForActivity( CLR_UINT32 powerLevel, CLR_UINT32 events, CLR_INT64 timeout_ms ); + CLR_UINT32 WaitForActivity( ); + + HRESULT Execute ( LPWSTR entryPointArgs, int maxContextSwitch ); + + HRESULT WaitForDebugger(); + + static CLR_RT_HeapBlock* AccessStaticField( const CLR_RT_FieldDef_Index& fd ); + + void ProcessTimeEvent( CLR_UINT32 event ); + + static void InvalidateTimerCache(); + + static CLR_INT64 GetUptime(); + + CLR_RT_HeapBlock* ExtractHeapBlocksForArray( CLR_RT_TypeDef_Instance& inst, CLR_UINT32 length, const CLR_RT_ReflectionDef_Index& reflex ); + CLR_RT_HeapBlock* ExtractHeapBlocksForClassOrValueTypes( CLR_UINT32 dataType, CLR_UINT32 flags, const CLR_RT_TypeDef_Index& cls, CLR_UINT32 length ); + CLR_RT_HeapBlock* ExtractHeapBytesForObjects ( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 length ); + CLR_RT_HeapBlock* ExtractHeapBlocksForObjects ( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 length ); + CLR_RT_HeapBlock_Node* ExtractHeapBlocksForEvents ( CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 length ); + + HRESULT NewThread ( CLR_RT_Thread*& th, CLR_RT_HeapBlock_Delegate* pDelegate, int priority, CLR_INT32 id, CLR_UINT32 flags = 0 ); + void PutInProperList( CLR_RT_Thread* th ); + CLR_INT32 GetNextThreadId( ); + + HRESULT InitializeReference( CLR_RT_HeapBlock& ref, CLR_RT_SignatureParser& parser ); + HRESULT InitializeReference( CLR_RT_HeapBlock& ref, const CLR_RECORD_FIELDDEF* target, CLR_RT_Assembly* assm ); + + HRESULT InitializeLocals( CLR_RT_HeapBlock* locals, CLR_RT_Assembly* assm, const CLR_RECORD_METHODDEF* md ); + + HRESULT NewObjectFromIndex( CLR_RT_HeapBlock& reference, const CLR_RT_TypeDef_Index& cls ); + HRESULT NewObject ( CLR_RT_HeapBlock& reference, const CLR_RT_TypeDef_Instance& inst ); + HRESULT NewObject ( CLR_RT_HeapBlock& reference, CLR_UINT32 token, CLR_RT_Assembly* assm ); + + HRESULT CloneObject ( CLR_RT_HeapBlock& reference , const CLR_RT_HeapBlock& source ); + HRESULT CopyValueType( CLR_RT_HeapBlock* destination, const CLR_RT_HeapBlock* source ); + + HRESULT NewArrayList ( CLR_RT_HeapBlock& ref, int size, CLR_RT_HeapBlock_Array*& array ); + + + HRESULT FindFieldDef( CLR_RT_TypeDef_Instance& inst , LPCSTR szText , CLR_RT_FieldDef_Index& res ); + HRESULT FindFieldDef( CLR_RT_HeapBlock& reference, LPCSTR szText , CLR_RT_FieldDef_Index& res ); + HRESULT FindField ( CLR_RT_HeapBlock& reference, LPCSTR szText, CLR_RT_HeapBlock*& field ); + HRESULT SetField ( CLR_RT_HeapBlock& reference, LPCSTR szText, CLR_RT_HeapBlock& value ); + HRESULT GetField ( CLR_RT_HeapBlock& reference, LPCSTR szText, CLR_RT_HeapBlock& value ); + + + HRESULT LockObject ( CLR_RT_HeapBlock& reference, CLR_RT_SubThread* sth, const CLR_INT64& timeExpire, bool fForce ); + HRESULT UnlockObject ( CLR_RT_HeapBlock& reference, CLR_RT_SubThread* sth ); + void DeleteLockRequests( CLR_RT_Thread* thTarget , CLR_RT_SubThread* sthTarget ); + + HRESULT Sleep( CLR_RT_Thread* caller, const CLR_INT64& timeExpire ); + + HRESULT WaitEvents ( CLR_RT_Thread* caller, const CLR_INT64& timeExpire, CLR_UINT32 events, bool& fSuccess ); + void SignalEvents( CLR_RT_DblLinkedList& threads, CLR_UINT32 events ); + void SignalEvents( CLR_UINT32 events ); + + + HRESULT InitTimeout( CLR_INT64& timeExpire, const CLR_INT64& timeout ); + HRESULT InitTimeout( CLR_INT64& timeExpire, CLR_INT32 timeout ); + + static bool IsInstanceOf( CLR_RT_TypeDescriptor& desc, CLR_RT_TypeDescriptor& descTarget ); + static bool IsInstanceOf( const CLR_RT_TypeDef_Index& cls , const CLR_RT_TypeDef_Index& clsTarget ); + static bool IsInstanceOf( CLR_RT_HeapBlock& obj , const CLR_RT_TypeDef_Index& clsTarget ); + static bool IsInstanceOf( CLR_RT_HeapBlock& obj , CLR_RT_Assembly* assm, CLR_UINT32 token ); + + static HRESULT CastToType( CLR_RT_HeapBlock& ref, CLR_UINT32 tk, CLR_RT_Assembly* assm, bool fUpdate ); + + void DebuggerLoop(); + +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + void SetDebuggingInfoBreakpoints( bool fSet ); + void InstallBreakpoints ( CLR_DBG_Commands::Debugging_Execution_BreakpointDef* data, size_t num ); + void StopOnBreakpoint ( CLR_DBG_Commands::Debugging_Execution_BreakpointDef& def , CLR_RT_Thread* th ); + void StopOnBreakpoint ( CLR_DBG_Commands::Debugging_Execution_BreakpointDef& def , CLR_RT_StackFrame* stack, CLR_PMETADATA ip ); + void Breakpoint_System_Event ( CLR_DBG_Commands::Debugging_Execution_BreakpointDef& def , CLR_UINT16 event, CLR_RT_Thread* th, CLR_RT_StackFrame* stack, CLR_PMETADATA ip ); + bool DequeueActiveBreakpoint ( CLR_DBG_Commands::Debugging_Execution_BreakpointDef& def ); + + void Breakpoint_Assemblies_Loaded(); + + void Breakpoint_Threads_Prepare ( CLR_RT_DblLinkedList& threads ); + void Breakpoint_Thread_Terminated( CLR_RT_Thread* th ); + void Breakpoint_Thread_Created ( CLR_RT_Thread* th ); + + void Breakpoint_StackFrame_Break ( CLR_RT_StackFrame* stack ); + void Breakpoint_StackFrame_Push ( CLR_RT_StackFrame* stack, CLR_UINT32 reason ); + void Breakpoint_StackFrame_Pop ( CLR_RT_StackFrame* stack, bool stepEH ); + void Breakpoint_StackFrame_Step ( CLR_RT_StackFrame* stack, CLR_PMETADATA ip ); + void Breakpoint_StackFrame_Hard ( CLR_RT_StackFrame* stack, CLR_PMETADATA ip ); + + void Breakpoint_Exception ( CLR_RT_StackFrame* stack, CLR_UINT32 reason, CLR_PMETADATA ip ); + void Breakpoint_Exception_Intercepted( CLR_RT_StackFrame* stack ); + void Breakpoint_Exception_Uncaught ( CLR_RT_Thread* th ); +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + //--// + + bool IsTimeExpired( const CLR_INT64& timeExpire, CLR_INT64& timeoutMin, bool fAbsolute ); + + bool IsThereEnoughIdleTime( CLR_UINT32 expectedMsec ); + + void SpawnTimer(); + void SpawnFinalizer(); + void SpawnStaticConstructor( CLR_RT_Thread *&pCctorThread ); +#if defined(TINYCLR_APPDOMAINS) + bool SpawnStaticConstructorHelper( CLR_RT_AppDomain* appDomain, CLR_RT_AppDomainAssembly* appDomainAssembly, const CLR_RT_MethodDef_Index& idx ); +#else + bool SpawnStaticConstructorHelper( CLR_RT_Assembly* assembly, const CLR_RT_MethodDef_Index& idx ); +#endif + static void FinalizerTerminationCallback( void* arg ); + static void StaticConstructorTerminationCallback( void* arg ); + bool EnsureSystemThread( CLR_RT_Thread*& thread, int priority ); + + CLR_INT64 ProcessTimer(); + + //--// + + PROHIBIT_COPY_CONSTRUCTORS(CLR_RT_ExecutionEngine); + + //--// + +private: + + HRESULT AllocateHeaps(); + + void DeleteLockRequests( CLR_RT_Thread* thTarget, CLR_RT_SubThread* sthTarget, CLR_RT_DblLinkedList& threads ); + + CLR_RT_HeapBlock* ExtractHeapBlocks ( CLR_RT_DblLinkedList& heap, CLR_UINT32 dataType, CLR_UINT32 flags, CLR_UINT32 length ); + + CLR_RT_HeapBlock_Lock* FindLockObject( CLR_RT_DblLinkedList& threads, CLR_RT_HeapBlock& object ); + CLR_RT_HeapBlock_Lock* FindLockObject( CLR_RT_HeapBlock& object ); + + void CheckTimers ( CLR_INT64& timeoutMin ); + void CheckThreads ( CLR_INT64& timeoutMin, CLR_RT_DblLinkedList& threads ); + + void ProcessHardware(); + + + void ReleaseAllThreads( CLR_RT_DblLinkedList& threads ); + void AbortAllThreads ( CLR_RT_DblLinkedList& threads ); + + void InsertThreadRoundRobin( CLR_RT_DblLinkedList& threads, CLR_RT_Thread* th ); + + void UpdateTime ( ); + + CLR_UINT32 WaitSystemEvents( CLR_UINT32 powerLevel, CLR_UINT32 events, CLR_INT64 timeExpire ); + +#if defined(_WIN32) + HRESULT CreateEntryPointArgs( CLR_RT_HeapBlock& args, LPWSTR szCommandLineArgs ); +#endif + + // The lowest value for execution counter in threads. + int m_GlobalExecutionCounter; + + // Increase the value of m_executionCounter for all threads by iUpdateValue. + // This ensures that counter does not underflow. + void AdjustExecutionCounter( CLR_RT_DblLinkedList &threadList, int iUpdateValue ); +public : + + // This function updates execution counter in pThread and makes it last to execute. + // It is used to Thread.Sleep(0) imlementation. The thread is still ready, but is last to execute. + void UpdateToLowestExecutionCounter( CLR_RT_Thread *pThread ) const; + + void RetrieveCurrentMethod( CLR_UINT32& assmIdx, CLR_UINT32& methodIdx ); +}; + +extern CLR_RT_ExecutionEngine g_CLR_RT_ExecutionEngine; +extern CLR_UINT32 g_buildCRC; + +//--// + +// +// CT_ASSERT macro generates a compiler error in case the size of any structure changes. +// +CT_ASSERT( sizeof(CLR_RT_HeapBlock) == 12 ) +CT_ASSERT( sizeof(CLR_RT_HeapBlock_Raw) == sizeof(CLR_RT_HeapBlock) ) + +#if defined(TINYCLR_TRACE_MEMORY_STATS) +#define TINYCLR_TRACE_MEMORY_STATS_EXTRA_SIZE 4 +#else +#define TINYCLR_TRACE_MEMORY_STATS_EXTRA_SIZE 0 +#endif + +#if defined(ARM_V3_0) || defined(ARM_V3_1) // arm 3.0 compiler uses 8 bytes for a function pointer + CT_ASSERT( sizeof(CLR_RT_DataTypeLookup) == 20 + TINYCLR_TRACE_MEMORY_STATS_EXTRA_SIZE ) + +#elif defined(ARM_V1_2) + CT_ASSERT( sizeof(CLR_RT_DataTypeLookup) == 16 + TINYCLR_TRACE_MEMORY_STATS_EXTRA_SIZE ) + +#elif defined(GCC) // Gcc compiler uses 8 bytes for a function pointer + CT_ASSERT( sizeof(CLR_RT_DataTypeLookup) == 20 + TINYCLR_TRACE_MEMORY_STATS_EXTRA_SIZE ) + +#elif defined(GCCOP) // GccOP compiler uses 8 bytes for a function pointer + CT_ASSERT( sizeof(CLR_RT_DataTypeLookup) == 20 + TINYCLR_TRACE_MEMORY_STATS_EXTRA_SIZE ) + +#elif defined(PLATFORM_BLACKFIN) // 8 bytes for function pointer + CT_ASSERT( sizeof(CLR_RT_DataTypeLookup) == 20 + TINYCLR_TRACE_MEMORY_STATS_EXTRA_SIZE ) + +#elif defined(PLATFORM_SH) // SH.compiler uses 12 bytes for a function pointer + CT_ASSERT( sizeof(CLR_RT_DataTypeLookup) == 24 + TINYCLR_TRACE_MEMORY_STATS_EXTRA_SIZE ) + +#elif defined(PLATFORM_WINDOWS_EMULATOR) || defined(TINYCLR_TRACE_MEMORY_STATS) + CT_ASSERT( sizeof(CLR_RT_DataTypeLookup) == 16 + 4 ) + +#elif defined(PLATFORM_WINCE) + CT_ASSERT( sizeof(CLR_RT_DataTypeLookup) == 16 ) + + +#else + +! ERROR + +#endif + +//--// + +#if defined(_MSC_VER) +#pragma pack(pop, TINYCLR_RUNTIME_H) +#endif + +#endif // _TINYCLR_RUNTIME_H_ diff --git a/src/CLR/Include/TinyCLR_Runtime__HeapBlock.h b/src/CLR/Include/TinyCLR_Runtime__HeapBlock.h new file mode 100644 index 0000000000..84ede1fd4c --- /dev/null +++ b/src/CLR/Include/TinyCLR_Runtime__HeapBlock.h @@ -0,0 +1,2409 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _TINYCLR_RUNTIME__HEAPBLOCK_H_ +#define _TINYCLR_RUNTIME__HEAPBLOCK_H_ + +#ifdef __arm__ +// ARM compiler does not allow anonymous structs by default +#pragma anon_unions +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#define CLR_RT_HEAPBLOCK_RAW_ID( dataType, flags, size ) ( (dataType & 0x000000FF) | ((flags & 0x000000FF) << 8) | ((size & 0x0000FFFF) << 16)) +#define CLR_RT_HEAPBLOCK_ASSIGN_INTEGER32_SIGNED( dataType, num ) { m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID( dataType, 0, 1 ); m_data.numeric.s4 = (CLR_INT32)num; } +#define CLR_RT_HEAPBLOCK_ASSIGN_INTEGER64_SIGNED( dataType, num ) { m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID( dataType, 0, 1 ); m_data.numeric.s8 = num; } + +#define CLR_RT_HEAPBLOCK_ASSIGN_INTEGER32_UNSIGNED(dataType,num) { m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID( dataType, 0, 1 ); m_data.numeric.u4 = (CLR_UINT32)num; } +#define CLR_RT_HEAPBLOCK_ASSIGN_INTEGER64_UNSIGNED(dataType,num) { m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID( dataType, 0, 1 ); m_data.numeric.u8 = num; } + +#define CLR_RT_HEAPBLOCK_ASSIGN_FLOAT32(dataType,num) { m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID( dataType, 0, 1 ); m_data.numeric.r4 = num; } +#define CLR_RT_HEAPBLOCK_ASSIGN_FLOAT64(dataType,num) { m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID( dataType, 0, 1 ); m_data.numeric.r8 = num; } + +//////////////////////////////////////////////////////////// + +#define CLR_RT_HEAPBLOCK_RELOCATE(ptr) \ +{ \ + CLR_DataType dt = ptr->DataType(); \ + \ + if(dt > DATATYPE_LAST_NONPOINTER && dt < DATATYPE_FIRST_INVALID) \ + { \ + CLR_RT_HeapBlockRelocate rel = c_CLR_RT_DataTypeLookup[ dt ].m_relocate; \ + if(rel) \ + { \ + (ptr->*rel)(); \ + } \ + } \ +} + + +//////////////////////////////////////////////////////////// + +// +// This is used in memory move operations. +// +struct CLR_RT_HeapBlock_Raw +{ + CLR_UINT32 data[ 3 ]; +}; + +struct CLR_RT_HeapBlock +{ + friend struct CLR_RT_HeapBlock_Node; + friend struct CLR_RT_DblLinkedList; + + friend struct MethodCompiler; + //--// + +#if defined(TINYCLR_EMULATED_FLOATINGPOINT) +/*********************************************************/ +// Keep in Sync with tinyhal.h +//#define HAL_FLOAT_SHIFT 10 +//#define HAL_FLOAT_PRECISION 1000 +//#define HAL_DOUBLE_SHIFT 16 +//#define HAL_DOUBLE_PRECISION 10000 +/*********************************************************/ + + static const int HB_FloatShift = 10; + static const int HB_DoubleShift = 16; + + static const CLR_INT32 HB_FloatUnit = (1 << HB_FloatShift ); + static const CLR_INT64 HB_DoubleUnit = (ULONGLONGCONSTANT(1) << HB_DoubleShift); + + static const CLR_INT32 HB_FloatMask = ((1 << HB_FloatShift) - 1); + static const CLR_INT64 HB_DoubleMask = ((ULONGLONGCONSTANT(1) << HB_DoubleShift) - 1); + +#endif + + + + static const CLR_UINT32 HB_Alive = 0x01; + static const CLR_UINT32 HB_KeepAlive = 0x02; + static const CLR_UINT32 HB_Event = 0x04; + static const CLR_UINT32 HB_Pinned = 0x08; + static const CLR_UINT32 HB_Boxed = 0x10; + static const CLR_UINT32 HB_Unused20 = 0x20; + //If more bits are needed, HB_Signaled and HB_SignalAutoReset can be freed for use with a little work. + //It is not necessary that any heapblock can be waited upon. Currently, only Threads (Thread.Join), + //ManualResetEvent, and AutoResetEvent are waitable objects. + static const CLR_UINT32 HB_Signaled = 0x40; + static const CLR_UINT32 HB_SignalAutoReset = 0x80; + + static const CLR_UINT32 HB_Unmovable = HB_Pinned | HB_Event; + + // + // These are special flags used to control allocation. + // + static const CLR_UINT32 HB_InitializeToZero = 0x00100; + static const CLR_UINT32 HB_NoGcOnFailure = 0x00200; + static const CLR_UINT32 HB_SpecialGCAllocation = 0x00400; + static const CLR_UINT32 HB_CompactOnFailure = 0x00800; + + static const CLR_UINT32 HB_NoGcOnFailedAllocation = HB_SpecialGCAllocation | HB_NoGcOnFailure; + static const CLR_UINT32 HB_MaxSize = 0x0000FFFF; + + static const CLR_UINT32 HB_Object_Fields_Offset = 1; + + //--// + +private: + + union CLR_RT_HeapBlock_Id + { + struct Type + { + CLR_UINT8 dataType; // CLR_DataType + CLR_UINT8 flags; // HB_* + CLR_UINT16 size; + } type; + + CLR_UINT32 raw; + } m_id; + + union CLR_RT_HeapBlock_AtomicData + { + struct NodeLink + { + CLR_RT_HeapBlock_Node* nextBlock; + CLR_RT_HeapBlock_Node* prevBlock; + } nodeLink; + + union Numeric + { + CLR_UINT8 u1; + CLR_UINT16 u2; + CLR_UINT32 u4; + + struct U8 + { + CLR_UINT32 _L; + CLR_UINT32 _H; + + operator CLR_UINT64() const + { + return ((CLR_UINT64)_H << 32 | (CLR_UINT64)_L ); + } + + U8& operator=( const CLR_UINT64 num ) + { + _L = (CLR_UINT32)((ULONGLONGCONSTANT(0x00000000FFFFFFFF) & num) ); + _H = (CLR_UINT32)((ULONGLONGCONSTANT(0xFFFFFFFF00000000) & num) >> 32); + return *this; + } + U8& operator+=( const U8& num ) + { + CLR_UINT64 value = (CLR_UINT64)*this; // uses conversion + value += (CLR_UINT64)num; // uses conversion and then built-in type __int64 + *this = value; // uses assignment operator (operator=) + return *this; + } + + U8& operator-=( const U8& num ) + { + CLR_UINT64 value = (CLR_UINT64)*this; // uses conversion + value -= (CLR_UINT64)num; // uses conversion and then built-in type __int64 + *this = value; // uses assignment operator (operator=) + return *this; + } + + + U8 operator*( const U8& num) + { + CLR_UINT64 value = (CLR_UINT64)*this; + U8 ret_value; + value *= (CLR_UINT64)num; // uses conversion and then built-in type __int64 + ret_value = value; + return ret_value; + } + + U8 operator/( const U8& num ) + { + CLR_UINT64 value = (CLR_UINT64)*this; + U8 ret_value; + value /= (CLR_UINT64)num; // uses conversion and then built-in type __int64 + ret_value = value; + return ret_value; + } + + U8 operator~( ) + { + U8 ret_value; + ret_value._L = ~_L; + ret_value._H = ~_H; + return ret_value; + } + + + U8& operator%=( const U8& num ) + { + CLR_UINT64 value = (CLR_UINT64)*this; // uses conversion + value %= (CLR_UINT64)num; // uses conversion and then built-in type __int64 + *this = value; // uses assignment operator (operator=) + return *this; + } + + U8& operator&=( const U8& num ) + { + _L &= num._L; + _H &= num._H; + return *this; + } + + U8& operator|=( const U8& num ) + { + _L |= num._L; + _H |= num._H; + return *this; + } + + U8& operator^=( const U8& num ) + { + _L ^= num._L; + _H ^= num._H; + return *this; + } + + U8& operator>>=( const CLR_UINT32 num ) + { + + CLR_UINT64 value = (CLR_UINT64)*this; // uses conversion + value >>= num; // uses conversion and then built-in type __int64 + *this = value; // uses assignment operator (operator=) + return *this; + } + + U8& operator<<=( const CLR_UINT32 num ) + { + CLR_UINT64 value = (CLR_UINT64)*this; // uses conversion + value <<= num; // uses conversion and then built-in type __int64 + *this = value; // uses assignment operator (operator=) + return *this; + } + + bool operator<( const U8& num ) + { + CLR_UINT64 value = (CLR_UINT64)*this; // uses conversion + return ( value < (CLR_UINT64)num ); + } + + bool operator>( const U8& num ) + { + CLR_UINT64 value = (CLR_UINT64)*this; // uses conversion + return ( value > (CLR_UINT64)num ); + } + + bool operator==( const U8& num ) + { + CLR_UINT64 value = (CLR_UINT64)*this; // uses conversion + return ( value ==(CLR_UINT64)num ); + } + + bool operator==( const CLR_UINT64 num ) + { + CLR_UINT64 value = (CLR_UINT64)*this; // uses conversion + return ( value == num ); + } + + } u8; + // + CLR_INT8 s1; + CLR_INT16 s2; + CLR_INT32 s4; + + struct S8 + { + CLR_UINT32 _L; + CLR_UINT32 _H; + + operator CLR_INT64() const + { + return (((CLR_UINT64)_H) << 32 | (CLR_UINT64)_L); + } + + S8& operator=( const CLR_INT64 num ) + { + _L = (CLR_UINT32) (( ULONGLONGCONSTANT(0x00000000FFFFFFFF) & num) ); + _H = (CLR_UINT32) (( ULONGLONGCONSTANT(0xFFFFFFFF00000000) & num) >> 32 ); + return *this; + } + + S8& operator+=( const S8& num ) + { + CLR_INT64 value = (CLR_INT64)*this; // uses conversion + value += (CLR_INT64)num; // uses conversion and then built-in type __int64 + *this = value; // uses assignment operator (operator=) + return *this; + } + + S8& operator-=( const S8& num ) + { + CLR_INT64 value = (CLR_INT64)*this; // uses conversion + value -= (CLR_INT64)num; // uses conversion and then built-in type __int64 + *this = value; // uses assignment operator (operator=) + return *this; + } + + S8 operator*( const S8& num) + { + CLR_INT64 value = (CLR_INT64)*this; + S8 ret_value; + value *= (CLR_INT64)num; // uses conversion and then built-in type __int64 + ret_value = value; + return ret_value; + } + + S8 operator/( const S8& num ) + { + CLR_INT64 value = (CLR_INT64)*this; + S8 ret_value; + value /= (CLR_INT64)num; // uses conversion and then built-in type __int64 + ret_value = value; + return ret_value; + } + + S8 operator~() + { + S8 ret_value; + ret_value._L = ~_L; + ret_value._H = ~_H; + return ret_value; + } + + + + S8& operator%=( const S8& num ) + { + CLR_INT64 value = (CLR_INT64)*this; // uses conversion + value %= (CLR_INT64)num; // uses conversion and then built-in type __int64 + *this = value; // uses assignment operator (operator=) + return *this; + } + + S8& operator&=( const S8& num ) + { + _L &= num._L; + _H &= num._H; + return *this; + } + + S8& operator|=( const S8& num ) + { + _L |= num._L; + _H |= num._H; + return *this; + } + + S8& operator^=( const S8& num ) + { + _L ^= num._L; + _H ^= num._H; + return *this; + } + + S8& operator>>=( const CLR_UINT32 num ) + { + CLR_INT64 value = (CLR_INT64)*this; // uses conversion + value >>= num; // uses conversion and then built-in type __int64 + *this = value; // uses assignment operator (operator=) + return *this; + } + + S8& operator<<=( const CLR_UINT32 num ) + { + CLR_INT64 value = (CLR_INT64)*this; // uses conversion + value <<= num; // uses conversion and then built-in type __int64 + *this = value; // uses assignment operator (operator=) + return *this; + } + + bool operator<( const S8& num ) + { + CLR_INT64 value = (CLR_INT64)*this; // uses conversion + return ( value < (CLR_INT64)num ); + } + + bool operator>( const S8& num ) + { + CLR_INT64 value = (CLR_INT64)*this; // uses conversion + return ( value > (CLR_INT64)num ); + } + + bool operator==( const S8& num ) + { + CLR_INT64 value = (CLR_INT64)*this; // uses conversion + return ( value == (CLR_INT64)num ); + } + + + bool operator==( const CLR_INT64 num ) + { + CLR_INT64 value = (CLR_INT64)*this; // uses conversion + return ( value == num ); + } + + } s8; + // + +#if !defined(TINYCLR_EMULATED_FLOATINGPOINT) + + float r4; + + struct R8 + { + CLR_UINT32 _L; + CLR_UINT32 _H; + + operator double() const + { + double ret_val; + +#if defined(__GNUC__) +/// +/// UNDONE: FIXME: This code fixes an optimization problem with the gcc compiler. +/// When the optimization level is greater than zero, the gcc compiler +/// code will not work with the UINT32* conversion, it requires you +/// to copy byte by byte. +/// + CLR_UINT8* tmp = (CLR_UINT8*)&ret_val; + CLR_UINT8* src = (CLR_UINT8*)&_L; + int i; + + for(i=0; i( const R8& num ) + { + double value = (double)*this; // uses conversion + return ( value > (double)num ); + } + + bool operator==( const R8& num ) + { + double value = (double)*this; // uses conversion + return ( value == (double)num ); + } + + bool operator==( const double num ) + { + double value = (double)*this; // uses conversion + return ( value == num ); + } + + } r8; + +#else + /// not using floating point lib, emulated one + + struct R4 { + + CLR_INT32 _L; + + operator CLR_INT32 () const + { + return _L; + } + + R4& operator=( const CLR_INT32 num ) + { + _L = num; + return *this; + } + R4& operator+=( const R4& num ) + { + _L += num._L; + return *this; + } + + R4& operator-=( const R4& num ) + { + _L -= num._L; + return *this; + } + + + R4& operator%=( const R4& num ) + { + _L %= num._L; + return *this; + } + + + R4 operator*( const R4& num ) + { + R4 ret_value; + ret_value._L = (CLR_INT32)(((CLR_INT64)_L * (CLR_INT64)num._L) >> HB_FloatShift ); + return ret_value; + } + + R4 operator/( const R4& num ) + { + R4 ret_value; + ret_value._L = (CLR_INT32)((((CLR_INT64)_L) << HB_FloatShift) / (CLR_INT64)num._L); + return ret_value; + } + + } r4; + + struct R8 + { + CLR_UINT32 _L; + CLR_UINT32 _H; + + operator CLR_INT64() const + { + return ((CLR_INT64)_H << 32 | (CLR_INT64)_L ); + } + + R8& operator=( const CLR_INT64 num ) + { + _L = (CLR_UINT32) (( ULONGLONGCONSTANT(0x00000000FFFFFFFF) & num) ); + _H = (CLR_UINT32) (( ULONGLONGCONSTANT(0xFFFFFFFF00000000) & num) >> 32 ); + return *this; + } + + R8& operator+=( const R8& num ) + { + CLR_INT64 value = (CLR_INT64)*this; // uses conversion + value += (CLR_INT64)num; + *this = value; + return *this; + } + + R8& operator-=( const R8& num ) + { + CLR_INT64 value = (CLR_INT64)*this; // uses conversion + value -= (CLR_INT64)num; + *this = value; + return *this; + } + + R8 operator*( const R8& num) + { + CLR_UINT64 op1 = (CLR_INT64) *this; + CLR_UINT64 op2 = (CLR_INT64) num; + CLR_UINT64 res = 0; + R8 ret_value; + + bool fNegate = false; + + if((CLR_INT64)op1 < (CLR_INT64)res) + { + op1 = -(CLR_INT64)op1; + fNegate = !fNegate; + } + + if((CLR_INT64)op2 < (CLR_INT64)res) + { + op2 = -(CLR_INT64)op2; + fNegate = !fNegate; + } + + CLR_UINT64 v; + +#define ACCUMULATE(res,op,part) v = op1 * (CLR_UINT16)(op2 >> (16 * part)); res += (16 * part - HB_DoubleShift >= 0) ? (v << (16 * part - HB_DoubleShift)) : (v >> (HB_DoubleShift - 16 * part)) + + ACCUMULATE(res,+=,0); + ACCUMULATE(res,+=,1); + ACCUMULATE(res,+=,2); + ACCUMULATE(res,+=,3); + +#undef ACCUMULATE + + ret_value = (CLR_INT64)res; + + if(fNegate && (CLR_INT64)ret_value != 0) + { + ret_value = -(CLR_INT64)ret_value; + } + + return ret_value; + } + + R8 operator/( const R8& num ) + { + CLR_INT64 value = (CLR_INT64)*this; + R8 ret_value; + + value = (value / num) << HB_DoubleShift; + + ret_value = value; + + return ret_value; + } + + bool operator==( const R8& num ) + { + CLR_INT64 value = (CLR_INT64)*this; // uses conversion + return ( value == (CLR_INT64)num ); + } + + + bool operator==( const CLR_INT64 num ) + { + CLR_INT64 value = (CLR_INT64)*this; // uses conversion + return ( value == num ); + } + R8& operator%=( const R8& num ) + { + CLR_INT64 value = (CLR_INT64)*this; // uses conversion + + value = (CLR_INT64)((value % (CLR_INT64)num)) ; // uses conversion and then built-in type double + *this = value; // uses assignment operator (operator=) + + return *this; + } + + } r8; + +#endif + } numeric; + + // The macro CT_ASSERT is used to validate that members of Numeric union start at zero offset in union. + // This presumption is used in CRL_RT_Interop code. + // This macro does not add any code or data member, it is pure compiler time validation. + // This is not a valid check for Big Endian. + // Addr: 0011223344556677 Number: 0xAABBCCDD + // MemBE: AABBCCDD + // MemLE: DDCCBBAA + // So for LE DD,Addr 00 is the low byte. + // For BE it is certainly not true, hence this check will not work. Will Interop? FIXME GJS - verify interop + CT_ASSERT_UNIQUE_NAME( offsetof( Numeric, s1 ) == 0, s1 ) + CT_ASSERT_UNIQUE_NAME( offsetof( Numeric, s2 ) == 0, s2 ) + CT_ASSERT_UNIQUE_NAME( offsetof( Numeric, s4 ) == 0, s4 ) + CT_ASSERT_UNIQUE_NAME( offsetof( Numeric, u1 ) == 0, u1 ) + CT_ASSERT_UNIQUE_NAME( offsetof( Numeric, u2 ) == 0, u2 ) + CT_ASSERT_UNIQUE_NAME( offsetof( Numeric, u4 ) == 0, u4 ) + CT_ASSERT_UNIQUE_NAME( offsetof( Numeric, r4 ) == 0, r4 ) + CT_ASSERT_UNIQUE_NAME( offsetof( Numeric, s8 ) == 0, s8 ) + CT_ASSERT_UNIQUE_NAME( offsetof( Numeric, u8 ) == 0, u8 ) + CT_ASSERT_UNIQUE_NAME( offsetof( Numeric, r8 ) == 0, r8 ) + + struct String + { + LPCSTR m_text; +#if !defined(TINYCLR_NO_ASSEMBLY_STRINGS) + CLR_RT_Assembly* m_assm; +#endif + } string; + + //--// + + struct ObjectReference + { + CLR_RT_HeapBlock* ptr; + } objectReference; + + struct ArrayReference + { + CLR_RT_HeapBlock_Array* array; + CLR_UINT32 index; + } arrayReference; + + struct ObjectHeader + { + CLR_RT_TypeDef_Index cls; + CLR_RT_HeapBlock_Lock* lock; + } objectHeader; + +#if defined(TINYCLR_APPDOMAINS) + struct TransparentProxy + { + CLR_RT_HeapBlock* ptr; //points to a DATATYPE_CLASS derived from MBRO + CLR_RT_AppDomain* appDomain; //EVENT HEAP -- NO RELOCATION + } transparentProxy; +#endif + + //--// + + CLR_RT_ReflectionDef_Index reflection; + + //--// + + struct BinaryBlob + { + CLR_RT_MarkingHandler m_mark; + CLR_RT_RelocationHandler m_relocate; + } binaryBlob; + + } m_data; + +public: + + //--// + + void InitializeToZero(); + + //--// + + CLR_DataType DataType () const { return (CLR_DataType)m_id.type.dataType; } + CLR_UINT8 DataFlags() const { return m_id.type.flags ; } + CLR_UINT16 DataSize () const { return m_id.type.size ; } + + // Returns number of bytes actually used in CLR_RT_HeapBlock_AtomicData + CLR_UINT32 GetAtomicDataUsedBytes() const; + + void SetDataId ( CLR_UINT32 id ) { m_id.raw = id; } + void ChangeDataType ( CLR_UINT32 dataType ) { m_id.type.dataType = dataType; } + void ChangeDataFlags( CLR_UINT32 flags ) { m_id.type.flags = flags; } + + void ClearData() + { + m_data.nodeLink.nextBlock = NULL; + m_data.nodeLink.prevBlock = NULL; + } + + void SetFlags ( CLR_UINT8 flags ) { m_id.type.flags |= flags ; } + void ResetFlags( CLR_UINT8 flags ) { m_id.type.flags &= ~flags ; } + bool IsFlagSet ( CLR_UINT8 flags ) const { return (m_id.type.flags & flags) != 0; } + + //--// + +#if defined(TINYCLR_FILL_MEMORY_WITH_DIRTY_PATTERN) + + void Debug_ClearBlock ( int data ); + void Debug_CheckPointer( ) const; + static void Debug_CheckPointer( void* ptr ); + +#else + + void Debug_ClearBlock ( int data ) {} + void Debug_CheckPointer( ) const {} + static void Debug_CheckPointer( void* ptr ) {} + +#endif + + //--// + + bool IsAlive () const { return IsFlagSet ( HB_Alive ); } + bool IsEvent () const { return IsFlagSet ( HB_Event ); } + bool IsForcedAlive () const { return IsFlagSet ( HB_KeepAlive ); } + + bool IsPinned () const { return IsFlagSet ( HB_Pinned ); } + void Pin () { SetFlags ( HB_Pinned ); } + void Unpin () { ResetFlags( HB_Pinned ); } + + void MarkDead () { ResetFlags( HB_Alive ); } + void MarkAlive () { SetFlags ( HB_Alive ); } + + void MarkForcedAlive () { SetFlags ( HB_KeepAlive ); } + void UnmarkForcedAlive() { ResetFlags( HB_KeepAlive ); } + + bool IsBoxed () const { return IsFlagSet ( HB_Boxed ); } + void Box () { SetFlags ( HB_Boxed ); } + void Unbox () { ResetFlags( HB_Boxed ); } + + //--// + + void SetBoolean( bool val ) { CLR_RT_HEAPBLOCK_ASSIGN_INTEGER32_SIGNED( DATATYPE_BOOLEAN, val ? 1 : 0 ); } + void SetInteger( const CLR_INT32 num, CLR_UINT8 dataType ) { CLR_RT_HEAPBLOCK_ASSIGN_INTEGER32_SIGNED( dataType , num ); } + + void SetInteger( const CLR_INT8 num ) { CLR_RT_HEAPBLOCK_ASSIGN_INTEGER32_SIGNED (DATATYPE_I1, num); } + void SetInteger( const CLR_INT16 num ) { CLR_RT_HEAPBLOCK_ASSIGN_INTEGER32_SIGNED (DATATYPE_I2, num); } + void SetInteger( const CLR_INT32 num ) { CLR_RT_HEAPBLOCK_ASSIGN_INTEGER32_SIGNED (DATATYPE_I4, num); } + void SetInteger( const CLR_INT64& num ) { CLR_RT_HEAPBLOCK_ASSIGN_INTEGER64_SIGNED (DATATYPE_I8, num); } + void SetInteger( const CLR_UINT8 num ) { CLR_RT_HEAPBLOCK_ASSIGN_INTEGER32_UNSIGNED(DATATYPE_U1, num); } + void SetInteger( const CLR_UINT16 num ) { CLR_RT_HEAPBLOCK_ASSIGN_INTEGER32_UNSIGNED(DATATYPE_U2, num); } + void SetInteger( const CLR_UINT32 num ) { CLR_RT_HEAPBLOCK_ASSIGN_INTEGER32_UNSIGNED(DATATYPE_U4, num); } + void SetInteger( const CLR_UINT64& num ) { CLR_RT_HEAPBLOCK_ASSIGN_INTEGER64_UNSIGNED(DATATYPE_U8, num); } + +#if !defined(TINYCLR_EMULATED_FLOATINGPOINT) + void SetFloat ( const float num ) { CLR_RT_HEAPBLOCK_ASSIGN_FLOAT32 (DATATYPE_R4, num); } + void SetDouble ( const double num ) { CLR_RT_HEAPBLOCK_ASSIGN_FLOAT64 (DATATYPE_R8, num); } + void SetFloatFromBits ( const CLR_UINT32 num ) { SetFloat ( *(const float *)&num ); } + void SetDoubleFromBits( const CLR_UINT64& num ) { SetDouble( *(const double*)&num ); } +#else + void SetFloat ( const CLR_INT32 num ) { CLR_RT_HEAPBLOCK_ASSIGN_FLOAT32 (DATATYPE_R4, num); } + void SetDouble ( const CLR_INT64& num ) { CLR_RT_HEAPBLOCK_ASSIGN_FLOAT64 (DATATYPE_R8, num); } + HRESULT SetFloatIEEE754 ( const CLR_UINT32 num ); + HRESULT SetDoubleIEEE754( const CLR_UINT64& num ); +#endif + + + void SetObjectReference( const CLR_RT_HeapBlock* ptr ) + { + m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_OBJECT, 0, 1); + m_data.objectReference.ptr = (CLR_RT_HeapBlock*)ptr; + } + +#if defined(TINYCLR_APPDOMAINS) + CLR_RT_AppDomain* TransparentProxyAppDomain () const { return m_data.transparentProxy.appDomain; } + CLR_RT_HeapBlock* TransparentProxyDereference() const { return Dereference() ; } + + void SetTransparentProxyReference( CLR_RT_AppDomain* appDomain, CLR_RT_HeapBlock* ptr ); + HRESULT TransparentProxyValidate() const; + + bool IsTransparentProxy() const { return IsAReferenceOfThisType( DATATYPE_TRANSPARENT_PROXY ); } +#endif + + void SetReference( CLR_RT_HeapBlock& dst ) + { + CLR_RT_HeapBlock* obj; + + // + // ValueTypes are implemented as pointers to objects, + // so getting a reference to a ValueType has to be treated like getting a reference to object, not to its holder! + // + if(dst.IsAValueType()) + { + obj = dst.Dereference(); + } + else + { + obj = &dst; + } + + m_id.raw = CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_BYREF, 0, 1); + m_data.objectReference.ptr = obj; + } + + bool IsAReferenceOfThisType( CLR_DataType dataType ) const + { + if(DataType() == DATATYPE_OBJECT) + { + CLR_RT_HeapBlock* obj = Dereference(); + + if(obj && obj->DataType() == dataType) return true; + } + + return false; + } + + bool IsAValueType() const + { + if(DataType() == DATATYPE_OBJECT) + { + CLR_RT_HeapBlock* obj = Dereference(); + + if(obj && obj->DataType() == DATATYPE_VALUETYPE && obj->IsBoxed() == false) return true; + } + + return false; + } + + bool SameHeader( const CLR_RT_HeapBlock& right ) const + { + return this->m_data.numeric.u8 == right.m_data.numeric.u8; + } + + //--// + + CLR_RT_HeapBlock_Array* RecoverArrayHeader() const + { + return (DataType() == DATATYPE_ARRAY_BYREF) ? m_data.arrayReference.array : NULL; + } + + //--// + + LPCSTR RecoverString() const + { + if(DataType() == DATATYPE_OBJECT) + { + const CLR_RT_HeapBlock* ptr = m_data.objectReference.ptr; + + if(ptr) + { + return ptr->StringText(); + } + } + + return NULL; + } + + //--// + const CLR_RT_HeapBlock_AtomicData& DataByRefConst() const { return m_data; } + + CLR_RT_HeapBlock_AtomicData::Numeric& NumericByRef () { return m_data.numeric; } + const CLR_RT_HeapBlock_AtomicData::Numeric& NumericByRefConst() const { return m_data.numeric; } + + //--// + + LPCSTR StringText() const { return m_data.string.m_text; } + +#if defined(TINYCLR_NO_ASSEMBLY_STRINGS) + void SetStringText( LPCSTR szText ) + { + m_data.string.m_text = szText; + } +#else + void SetStringText( LPCSTR szText, CLR_RT_Assembly* assm ) + { + m_data.string.m_text = szText; + m_data.string.m_assm = assm; + } + + CLR_RT_Assembly* StringAssembly() const { return m_data.string.m_assm; } +#endif + + //--// + + const CLR_RT_TypeDef_Index& ObjectCls ( ) const { return m_data.objectHeader.cls ; } + CLR_RT_HeapBlock_Lock* ObjectLock ( ) const { return m_data.objectHeader.lock ; } + void SetObjectLock( CLR_RT_HeapBlock_Lock* lock ) { m_data.objectHeader.lock = lock; } + + HRESULT SetObjectCls( const CLR_RT_TypeDef_Index& cls ); + + //--// + + const CLR_RT_ReflectionDef_Index& ReflectionDataConst() const { return m_data.reflection; } + CLR_RT_ReflectionDef_Index& ReflectionData () { return m_data.reflection; } + + //--// + + CLR_RT_HeapBlock_Array* Array () const { return m_data.arrayReference.array ; } + CLR_UINT32 ArrayIndex () const { return m_data.arrayReference.index ; } + void ArrayIndexIncrement() { m_data.arrayReference.index++; } + + //--// + + CLR_RT_MarkingHandler BinaryBlobMarkingHandler () const { return m_data.binaryBlob.m_mark ; } + CLR_RT_RelocationHandler BinaryBlobRelocationHandler() const { return m_data.binaryBlob.m_relocate; } + + void SetBinaryBlobHandlers( CLR_RT_MarkingHandler mark, CLR_RT_RelocationHandler relocate ) + { + m_data.binaryBlob.m_mark = mark ; + m_data.binaryBlob.m_relocate = relocate; + } + + //--// + //--// + + CLR_RT_HeapBlock* Dereference() const { return m_data.objectReference.ptr; } + + CLR_RT_HeapBlock_WeakReference* DereferenceWeakReference() const { return (CLR_RT_HeapBlock_WeakReference*)Dereference(); } + CLR_RT_HeapBlock_String * DereferenceString () const { return (CLR_RT_HeapBlock_String *)Dereference(); } + CLR_RT_HeapBlock_Array * DereferenceArray () const { return (CLR_RT_HeapBlock_Array *)Dereference(); } + CLR_RT_HeapBlock_Delegate * DereferenceDelegate () const { return (CLR_RT_HeapBlock_Delegate *)Dereference(); } + CLR_RT_HeapBlock_Delegate_List* DereferenceDelegateList () const { return (CLR_RT_HeapBlock_Delegate_List*)Dereference(); } + CLR_RT_HeapBlock_BinaryBlob * DereferenceBinaryBlob () const { return (CLR_RT_HeapBlock_BinaryBlob *)Dereference(); } + + //--// + + void AssignId( const CLR_RT_HeapBlock& value ) + { + _ASSERTE(value.DataSize() == 1); + + m_id = value.m_id; + } + + void AssignData( const CLR_RT_HeapBlock& value ) + { + _ASSERTE(value.DataSize() == 1); + + m_data = value.m_data; + } + + void Assign( const CLR_RT_HeapBlock& value ) + { + _ASSERTE(value.DataSize() == 1); + + value.Debug_CheckPointer(); + + CLR_RT_HeapBlock_Raw* src = (CLR_RT_HeapBlock_Raw*) this; + CLR_RT_HeapBlock_Raw* dst = (CLR_RT_HeapBlock_Raw*)&value; + + *src = *dst; + } + + void AssignAndPreserveType( const CLR_RT_HeapBlock& value ) + { + _ASSERTE(value.DataSize() == 1); + + this->m_data = value.m_data; + + if(this->DataType() > DATATYPE_LAST_PRIMITIVE_TO_PRESERVE) this->m_id = value.m_id; + } + + void AssignPreserveTypeCheckPinned( const CLR_RT_HeapBlock& value ) + { + _ASSERTE(value.DataSize() == 1); + + + { // If local variable does not have pinned type - move source data into it + if (!IsPinned()) + { + AssignAndPreserveType( value ); + } + else // IsPinned() is true; + { AssignAndPinReferencedObject( value ); + } + } + } + + // This function is called for assigning to "pinned" reference variables. + // Since it is rare case, the code is not inlined to save code size. + void AssignAndPinReferencedObject( const CLR_RT_HeapBlock& value ); + + HRESULT Convert( CLR_DataType et, bool fOverflow, bool fUnsigned ) + { + // + // For V1, we don't throw on overflow. + // + return Convert_Internal( et ); + } + + bool InitObject(); + + //--// + + static CLR_INT32 Compare_Unsigned_Values( const CLR_RT_HeapBlock& left, const CLR_RT_HeapBlock& right ) { return Compare_Values( left, right, false ); } + static CLR_INT32 Compare_Signed_Values ( const CLR_RT_HeapBlock& left, const CLR_RT_HeapBlock& right ) { return Compare_Values( left, right, true ); } + + //--// + + + HRESULT SetReflection( const CLR_RT_ReflectionDef_Index& reflex ); + HRESULT SetReflection( const CLR_RT_Assembly_Index& assm ); + HRESULT SetReflection( const CLR_RT_TypeSpec_Index& sig ); + HRESULT SetReflection( const CLR_RT_TypeDef_Index& cls ); + HRESULT SetReflection( const CLR_RT_FieldDef_Index& fd ); + HRESULT SetReflection( const CLR_RT_MethodDef_Index& md ); + + + HRESULT InitializeArrayReference ( CLR_RT_HeapBlock& ref , int index ); + void InitializeArrayReferenceDirect( CLR_RT_HeapBlock_Array& array, int index ); + void FixArrayReferenceForValueTypes( ); + + HRESULT LoadFromReference ( CLR_RT_HeapBlock& ref ); + HRESULT StoreToReference ( CLR_RT_HeapBlock& ref, int size ); + HRESULT Reassign ( const CLR_RT_HeapBlock& value ); + HRESULT PerformBoxingIfNeeded( ); + HRESULT PerformBoxing ( const CLR_RT_TypeDef_Instance& cls ); + HRESULT PerformUnboxing ( const CLR_RT_TypeDef_Instance& cls ); + CLR_RT_HeapBlock* FixBoxingReference ( ); + HRESULT EnsureObjectReference( CLR_RT_HeapBlock*& obj ); + + //--// + + bool IsZero () const; + void Promote(); + + static CLR_UINT32 GetHashCode ( CLR_RT_HeapBlock* ptr, bool fRecurse, CLR_UINT32 crc ); + static bool ObjectsEqual ( const CLR_RT_HeapBlock& left, const CLR_RT_HeapBlock& right, bool fSameReference ); + + static CLR_INT32 Compare_Values( const CLR_RT_HeapBlock& left, const CLR_RT_HeapBlock& right, bool fSigned ); + + HRESULT Convert_Internal( CLR_DataType et ); + HRESULT NumericAdd ( const CLR_RT_HeapBlock& right ); + HRESULT NumericSub ( const CLR_RT_HeapBlock& right ); + HRESULT NumericMul ( const CLR_RT_HeapBlock& right ); + HRESULT NumericDiv ( const CLR_RT_HeapBlock& right ); + HRESULT NumericDivUn ( const CLR_RT_HeapBlock& right ); + HRESULT NumericRem ( const CLR_RT_HeapBlock& right ); + HRESULT NumericRemUn ( const CLR_RT_HeapBlock& right ); + HRESULT NumericShl ( const CLR_RT_HeapBlock& right ); + HRESULT NumericShr ( const CLR_RT_HeapBlock& right ); + HRESULT NumericShrUn ( const CLR_RT_HeapBlock& right ); + HRESULT NumericNeg ( ); + + CLR_RT_HeapBlock* ExtractValueBlock( int offset ); + void ReadValue ( CLR_INT64& val, int offset ); + void WriteValue ( const CLR_INT64& val, int offset ); + + void Relocate__HeapBlock(); + void Relocate_String (); + void Relocate_Obj (); + void Relocate_Cls (); + void Relocate_Ref (); + void Relocate_ArrayRef (); + +#if defined(TINYCLR_APPDOMAINS) + void Relocate_TransparentProxy(); +#endif + +private: + CLR_RT_HeapBlock& operator=( const CLR_RT_HeapBlock& ); + + +}; + +//--// + +#define TINYCLR_FOREACH_NODE(cls,ptr,lst) \ + { \ + cls* ptr; \ + cls* ptr##Next; \ + \ + for(ptr = (cls*)(lst).FirstNode(); (ptr##Next = (cls*)ptr->Next()) != NULL; ptr = ptr##Next) \ + { TINYCLR_FAULT_ON_EARLY_COLLECTION( ptr##Next ); + +#define TINYCLR_FOREACH_NODE__NODECL(cls,ptr,lst) \ + { \ + cls* ptr##Next; \ + \ + for(ptr = (cls*)(lst).FirstNode(); (ptr##Next = (cls*)ptr->Next()) != NULL; ptr = ptr##Next) \ + { TINYCLR_FAULT_ON_EARLY_COLLECTION( ptr##Next ); + +#define TINYCLR_FOREACH_NODE__DIRECT(cls,ptr,startNode) \ + { \ + cls* ptr; \ + cls* ptr##Next; \ + \ + for(ptr = (cls*)(startNode); (ptr##Next = (cls*)ptr->Next()) != NULL; ptr = ptr##Next) \ + { TINYCLR_FAULT_ON_EARLY_COLLECTION( ptr##Next ); + +#define TINYCLR_FOREACH_NODE_PREPARE_RELOAD(ptr) \ + TINYCLR_CANCEL_EARLY_COLLECTION(ptr##Next) + +#define TINYCLR_FOREACH_NODE_RELOAD(cls,ptr) \ + ptr##Next = (cls*)ptr->Next() + +#define TINYCLR_FOREACH_NODE_RESTART(cls,ptr,lst) \ + ptr##Next = (cls*)(lst).FirstNode(); continue + +#define TINYCLR_FOREACH_NODE_END() \ + } \ + } + + +#define TINYCLR_FOREACH_NODE_BACKWARD(cls,ptr,lst) \ + { \ + cls* ptr; \ + cls* ptr##Prev; \ + \ + for(ptr = (cls*)(lst).LastNode(); (ptr##Prev = (cls*)ptr->Prev()) != NULL; ptr = ptr##Prev) \ + { TINYCLR_FAULT_ON_EARLY_COLLECTION( ptr##Prev ); + +#define TINYCLR_FOREACH_NODE_BACKWARD__NODECL(cls,ptr,lst) \ + { \ + cls* ptr##Prev; \ + \ + for(ptr = (cls*)(lst).LastNode(); (ptr##Prev = (cls*)ptr->Prev()) != NULL; ptr = ptr##Prev) \ + { TINYCLR_FAULT_ON_EARLY_COLLECTION( ptr##Prev ); + +#define TINYCLR_FOREACH_NODE_BACKWARD__DIRECT(cls,ptr,startNode) \ + { \ + cls* ptr; \ + cls* ptr##Prev; \ + \ + for(ptr = (cls*)(startNode); (ptr##Prev = (cls*)ptr->Prev()) != NULL; ptr = ptr##Prev) \ + { TINYCLR_FAULT_ON_EARLY_COLLECTION( ptr##Prev ); + +#define TINYCLR_FOREACH_NODE_BACKWARD_RESTART(cls,ptr,lst) \ + ptr##Prev = (cls*)(lst).LastNode(); continue + +#define TINYCLR_FOREACH_NODE_BACKWARD_PREPARE_RELOAD(ptr) \ + TINYCLR_CANCEL_EARLY_COLLECTION(ptr##Prev) + +#define TINYCLR_FOREACH_NODE_BACKWARD_RELOAD(cls,ptr) \ + ptr##Prev = (cls*)ptr->Prev() + +#define TINYCLR_FOREACH_NODE_BACKWARD_END() \ + } \ + } + + + +struct CLR_RT_HeapBlock_Node : public CLR_RT_HeapBlock +{ + friend struct CLR_RT_DblLinkedList; + + void GenericNode_Initialize() + { + ClearData(); + } + + CLR_RT_HeapBlock_Node* Next () const { return m_data.nodeLink.nextBlock; } + CLR_RT_HeapBlock_Node* Prev () const { return m_data.nodeLink.prevBlock; } + + void SetNext( CLR_RT_HeapBlock_Node* next ) { m_data.nodeLink.nextBlock = next; } + void SetPrev( CLR_RT_HeapBlock_Node* prev ) { m_data.nodeLink.prevBlock = prev; } + + // + // The ARM compiler cannot inline these methods, + // it keeps injecting a call to a 4 instruction-long function (arg!!). + // + // So we'll have to use the explicit check... + // + //bool IsValidForward () const { return Next() != NULL; } + //bool IsValidBackward() const { return Prev() != NULL; } + + //--// + +#if TINYCLR_VALIDATE_HEAP >= TINYCLR_VALIDATE_HEAP_1_HeapBlocksAndUnlink + void ConsistencyCheck_Nodes( CLR_RT_HeapBlock_Node* prev, CLR_RT_HeapBlock_Node* next ) + { + if( prev && next) return; + if(!prev && !next) return; + + CLR_Debug::Printf( "Bad node!!\r\n" ); + + TINYCLR_DEBUG_STOP(); + } + +#else + + void ConsistencyCheck_Nodes( CLR_RT_HeapBlock_Node* prev, CLR_RT_HeapBlock_Node* next ) {} + +#endif + + void RemoveFromList() + { + CLR_RT_HeapBlock_Node* prev = m_data.nodeLink.prevBlock; + CLR_RT_HeapBlock_Node* next = m_data.nodeLink.nextBlock; + + ConsistencyCheck_Nodes( prev, next ); + + if(prev) prev->m_data.nodeLink.nextBlock = next; + if(next) next->m_data.nodeLink.prevBlock = prev; + } + + void Unlink() + { + CLR_RT_HeapBlock_Node* prev = m_data.nodeLink.prevBlock; + CLR_RT_HeapBlock_Node* next = m_data.nodeLink.nextBlock; + + ConsistencyCheck_Nodes( prev, next ); + + if(prev) prev->m_data.nodeLink.nextBlock = next; + if(next) next->m_data.nodeLink.prevBlock = prev; + + m_data.nodeLink.prevBlock = NULL; + m_data.nodeLink.nextBlock = NULL; + } + + //--// + + void Relocate(); +}; + +struct CLR_RT_DblLinkedList +{ +private: + // + // Logically, a list starts with a CLR_RT_HeapBlock_Node with only the Next() set and ends with a node with only Prev() set. + // This can be collapsed to have the two nodes overlap. + // + CLR_RT_HeapBlock_Node* m_first; // ANY HEAP - DO RELOCATION - + CLR_RT_HeapBlock_Node* m_null; + CLR_RT_HeapBlock_Node* m_last; // ANY HEAP - DO RELOCATION - + + //--// + +public: + void DblLinkedList_Initialize (); + void DblLinkedList_PushToCache(); + void DblLinkedList_Release (); + + int NumOfNodes (); + + void Relocate (); + + //--// + + CLR_RT_HeapBlock_Node* FirstNode () const { return m_first ; } + CLR_RT_HeapBlock_Node* LastNode () const { return m_last ; } + bool IsEmpty () const { return m_first == Tail(); } + + CLR_RT_HeapBlock_Node* FirstValidNode() const { CLR_RT_HeapBlock_Node* res = m_first; return res->Next() ? res : NULL; } + CLR_RT_HeapBlock_Node* LastValidNode () const { CLR_RT_HeapBlock_Node* res = m_last ; return res->Prev() ? res : NULL; } + + // Check that node pNode is not "dummy" tail or head node. + static bool IsValidListNode( CLR_RT_HeapBlock_Node* pNode ) + { + return pNode->m_data.nodeLink.nextBlock != NULL && pNode->m_data.nodeLink.prevBlock != NULL; + } + + CLR_RT_HeapBlock_Node* Head() const { return (CLR_RT_HeapBlock_Node*)((size_t)&m_first - offsetof(CLR_RT_HeapBlock, m_data.nodeLink.nextBlock)); } + CLR_RT_HeapBlock_Node* Tail() const { return (CLR_RT_HeapBlock_Node*)((size_t)&m_last - offsetof(CLR_RT_HeapBlock, m_data.nodeLink.prevBlock)); } + +#if TINYCLR_VALIDATE_HEAP >= TINYCLR_VALIDATE_HEAP_2_DblLinkedList + void ValidateList(); +#else + void ValidateList() {}; +#endif + + //--// + +private: + void Insert( CLR_RT_HeapBlock_Node* prev, CLR_RT_HeapBlock_Node* next, CLR_RT_HeapBlock_Node* node ) + { + node->m_data.nodeLink.nextBlock = next; + node->m_data.nodeLink.prevBlock = prev; + + next->m_data.nodeLink.prevBlock = node; + prev->m_data.nodeLink.nextBlock = node; + } + +public: + void InsertBeforeNode( CLR_RT_HeapBlock_Node* node, CLR_RT_HeapBlock_Node* nodeNew ) + { + ValidateList(); + + if(node && nodeNew && node != nodeNew) + { + nodeNew->RemoveFromList(); + + Insert( node->Prev(), node, nodeNew ); + } + } + + void InsertAfterNode( CLR_RT_HeapBlock_Node* node, CLR_RT_HeapBlock_Node* nodeNew ) + { + ValidateList(); + + if(node && nodeNew && node != nodeNew) + { + nodeNew->RemoveFromList(); + + Insert( node, node->Next(), nodeNew ); + } + } + + void LinkAtFront( CLR_RT_HeapBlock_Node* node ) + { + InsertAfterNode( Head(), node ); + } + + void LinkAtBack( CLR_RT_HeapBlock_Node* node ) + { + InsertBeforeNode( Tail(), node ); + } + + CLR_RT_HeapBlock_Node* ExtractFirstNode() + { + ValidateList(); + + CLR_RT_HeapBlock_Node* node = FirstValidNode(); + + if(node) node->Unlink(); + + return node; + } + + CLR_RT_HeapBlock_Node* ExtractLastNode() + { + ValidateList(); + + CLR_RT_HeapBlock_Node* node = LastValidNode(); + + if(node) node->Unlink(); + + return node; + } + + //--// + + PROHIBIT_COPY_CONSTRUCTORS(CLR_RT_DblLinkedList); +}; + + +struct CLR_RT_AVLTree +{ + struct Owner; + + enum Skew + { + SKEW_LEFT = -1, + SKEW_NONE = 0, + SKEW_RIGHT = 1, + }; + + enum Result + { + RES_OK = 0, + RES_BALANCE = 1, + RES_NOTFOUND = 2, + RES_DUPLICATE = 3, + RES_ERROR = 4, + }; + + struct Entry : public CLR_RT_HeapBlock_Node + { + Entry* m_left; + Entry* m_right; + Skew m_skew; + }; + + typedef int (*ComparerFtn)( void* state, Entry* left, Entry* right ); + typedef Entry* (*NewNodeFtn )( void* state, Entry* payload ); + typedef void (*FreeNodeFtn)( void* state, Entry* node ); + typedef void (*ReassignFtn)( void* state, Entry* from, Entry* to ); + + struct OwnerInfo + { + ComparerFtn m_ftn_compare; + NewNodeFtn m_ftn_newNode; + FreeNodeFtn m_ftn_freeNode; + ReassignFtn m_ftn_reassignNode; + void* m_state; + }; + + //--// + + Entry* m_root; + OwnerInfo m_owner; + + //--// + + void Initialize(); + + Result Insert( Entry* newDatum ); + Result Remove( Entry* oldDatum ); + Entry* Find ( Entry* srcDatum ); + +private: + static void RotateLeft ( Entry*& n ); + static void RotateRight ( Entry*& n ); + + static Result LeftGrown ( Entry*& n ); + static Result RightGrown ( Entry*& n ); + + static Result LeftShrunk ( Entry*& n ); + static Result RightShrunk ( Entry*& n ); + + bool FindHighest ( Entry*& n, Entry* target, Result& res ); + bool FindLowest ( Entry*& n, Entry* target, Result& res ); + + Result Insert( Entry*& n, Entry* newDatum ); + Result Remove( Entry*& n, Entry* oldDatum ); +}; + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +struct CLR_RT_HeapBlock_String : public CLR_RT_HeapBlock +{ + static CLR_RT_HeapBlock_String* CreateInstance( CLR_RT_HeapBlock& reference, CLR_UINT32 length ); + static HRESULT CreateInstance( CLR_RT_HeapBlock& reference, LPCSTR szText ); + static HRESULT CreateInstance( CLR_RT_HeapBlock& reference, LPCSTR szText, CLR_UINT32 length ); + static HRESULT CreateInstance( CLR_RT_HeapBlock& reference, CLR_UINT32 token , CLR_RT_Assembly* assm ); + static HRESULT CreateInstance( CLR_RT_HeapBlock& reference, LPCSTR szText, CLR_RT_Assembly* assm ); + static HRESULT CreateInstance( CLR_RT_HeapBlock& reference, CLR_UINT16* szText, CLR_UINT32 length ); + + static CLR_RT_HeapBlock_String* GetStringEmpty(); +}; + +struct CLR_RT_HeapBlock_Array : public CLR_RT_HeapBlock +{ + CLR_UINT32 m_numOfElements; + CLR_UINT8 m_typeOfElement; + CLR_UINT8 m_sizeOfElement; + CLR_UINT8 m_fReference; + CLR_UINT8 m_pad; + + //--// + + static HRESULT CreateInstance( CLR_RT_HeapBlock& reference, CLR_UINT32 length, const CLR_RT_ReflectionDef_Index& reflex ); + static HRESULT CreateInstance( CLR_RT_HeapBlock& reference, CLR_UINT32 length, const CLR_RT_TypeDef_Index& cls ); + static HRESULT CreateInstance( CLR_RT_HeapBlock& reference, CLR_UINT32 length, CLR_RT_Assembly* assm , CLR_UINT32 tk ); + + CLR_UINT8* GetFirstElement() { return ((CLR_UINT8*)&this[ 1 ]); } + + CLR_UINT8* GetElement( CLR_UINT32 index ) { return GetFirstElement() + m_sizeOfElement * index; } + + HRESULT ClearElements( int index, int length ); + + //--// + + void Relocate(); + + //--// + + static bool CheckRange( int index, int length, int numOfElements ); + + static HRESULT IndexOf( CLR_RT_HeapBlock_Array* array, CLR_RT_HeapBlock& match, int start, int stop, bool fForward, int& index ); + static HRESULT Copy( CLR_RT_HeapBlock_Array* arraySrc, int indexSrc, CLR_RT_HeapBlock_Array* arrayDst, int indexDst, int length ); +}; + +struct CLR_RT_HeapBlock_Delegate : public CLR_RT_HeapBlock_Node // OBJECT HEAP - DO RELOCATION - +{ + CLR_RT_TypeDef_Index m_cls; + CLR_RT_MethodDef_Index m_ftn; +#if defined(TINYCLR_DELEGATE_PRESERVE_STACK) + CLR_UINT32 m_numOfStackFrames; +#endif + CLR_RT_HeapBlock m_object; // ANY HEAP - DO RELOCATION - + +#if defined(TINYCLR_APPDOMAINS) + CLR_RT_AppDomain* m_appDomain; +#endif + + //--// + + const CLR_RT_MethodDef_Index& DelegateFtn () const { return m_ftn ; } +#if defined(TINYCLR_DELEGATE_PRESERVE_STACK) + CLR_UINT32 DelegateNumOfStackFrames() const { return m_numOfStackFrames ; } + CLR_RT_MethodDef_Index* GetStackFrames() { return (CLR_RT_MethodDef_Index*)&this[ 1 ]; } +#endif + //--// + + static HRESULT CreateInstance( CLR_RT_HeapBlock& reference, const CLR_RT_MethodDef_Index& ftn, CLR_RT_StackFrame* call ); + + void Relocate(); +}; + +struct CLR_RT_HeapBlock_Delegate_List : public CLR_RT_HeapBlock_Node // OBJECT HEAP - DO RELOCATION - +{ + static const CLR_UINT32 c_Weak = 0x00000001; + + CLR_RT_TypeDef_Index m_cls; + CLR_UINT32 m_length; + CLR_UINT32 m_flags; + + CLR_RT_HeapBlock* GetDelegates() { return &this[ 1 ]; } // ANY HEAP - DO RELOCATION - + + //--// + + static HRESULT CreateInstance( CLR_RT_HeapBlock_Delegate_List*& list, CLR_UINT32 length ); + + static HRESULT Combine( CLR_RT_HeapBlock& reference, CLR_RT_HeapBlock& delegateSrc, CLR_RT_HeapBlock& delegateNew, bool fWeak ); + static HRESULT Remove ( CLR_RT_HeapBlock& reference, CLR_RT_HeapBlock& delegateSrc, CLR_RT_HeapBlock& delegateOld ); + + void Relocate(); + +private: + + static HRESULT Change( CLR_RT_HeapBlock& reference, CLR_RT_HeapBlock& delegateSrc, CLR_RT_HeapBlock& delegateTarget, bool fCombine, bool fWeak ); + + CLR_RT_HeapBlock* CopyAndCompress( CLR_RT_HeapBlock* src, CLR_RT_HeapBlock* dst, CLR_UINT32 num ); +}; + +//--// + +struct CLR_RT_HeapBlock_BinaryBlob : public CLR_RT_HeapBlock +{ + friend struct CLR_RT_Memory; + + //--// + + CLR_RT_Assembly* m_assembly; + + void* GetData( ) { return (void*)&this[ 1 ] ; } + static CLR_RT_HeapBlock_BinaryBlob* GetBlob( void* data ) { return (CLR_RT_HeapBlock_BinaryBlob*)data - 1; } + + //--// + + static HRESULT CreateInstance( CLR_RT_HeapBlock& reference, CLR_UINT32 length, CLR_RT_MarkingHandler mark, CLR_RT_RelocationHandler relocate, CLR_UINT32 flags ); + + void Release( bool fEvent ); + + void Relocate(); + +private: + static CLR_RT_HeapBlock_BinaryBlob* Allocate( CLR_UINT32 length, CLR_UINT32 flags ); +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +struct CLR_RT_ObjectToEvent_Destination : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - +{ + CLR_RT_DblLinkedList m_references; // EVENT HEAP - NO RELOCATION - list of CLR_RT_ObjectToEvent_Source + + //--// + + void Initialize (); + void CheckAll (); + void SignalAll (); + void DetachAll (); + bool IsReadyForRelease(); + bool ReleaseWhenDead (); +}; + +struct CLR_RT_ObjectToEvent_Source : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - +{ + CLR_RT_ObjectToEvent_Destination* m_eventPtr; // EVENT HEAP - NO RELOCATION - Pointer to the event referenced. + + CLR_RT_HeapBlock* m_objectPtr; // OBJECT HEAP - DO RELOCATION - Pointer to the object to keep alive. + CLR_RT_HeapBlock* m_referencePtr; // OBJECT HEAP - DO RELOCATION - Pointer to the HeapBlock referencing this structure. + + //--// + + static HRESULT CreateInstance ( CLR_RT_ObjectToEvent_Destination* event, CLR_RT_HeapBlock& object, CLR_RT_HeapBlock& reference ); + static CLR_RT_ObjectToEvent_Source* ExtractInstance( CLR_RT_HeapBlock& reference ); + + void EnsureObjectIsAlive(); + void Detach (); + + void Relocate (); +}; + +//////////////////////////////////////// + +struct CLR_RT_HeapBlock_Button : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - +{ + int m_key; + bool m_fPressed; +}; + +//--// + +struct CLR_RT_HeapBlock_Lock : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - +{ + struct Owner : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - + { + CLR_RT_SubThread* m_owningSubThread; // EVENT HEAP - NO RELOCATION - + CLR_UINT32 m_recursion; + }; + + CLR_RT_Thread* m_owningThread; // EVENT HEAP - NO RELOCATION - + + CLR_RT_HeapBlock m_resource; // OBJECT HEAP - DO RELOCATION - + +#if defined(TINYCLR_APPDOMAINS) + CLR_RT_AppDomain* m_appDomain; // EVENT HEAP - NO RELOCATION - +#endif + + CLR_RT_DblLinkedList m_owners; // EVENT HEAP - NO RELOCATION - list of CLR_RT_HeapBlock_Lock::Owner + CLR_RT_DblLinkedList m_requests; // EVENT HEAP - NO RELOCATION - list of CLR_RT_HeapBlock_LockRequest + + //--// + + static HRESULT CreateInstance ( CLR_RT_HeapBlock_Lock*& lock, CLR_RT_Thread* th, CLR_RT_HeapBlock& resource ); + static HRESULT IncrementOwnership( CLR_RT_HeapBlock_Lock* lock, CLR_RT_SubThread* sth, const CLR_INT64& timeExpire, bool fForce ); + static HRESULT DecrementOwnership( CLR_RT_HeapBlock_Lock* lock, CLR_RT_SubThread* sth ); + + void DestroyOwner( CLR_RT_SubThread* sth ); + void ChangeOwner ( ); + + void Relocate (); + void Relocate_Owner(); +}; + +struct CLR_RT_HeapBlock_LockRequest : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - +{ + CLR_RT_SubThread* m_subthreadWaiting; // EVENT HEAP - NO RELOCATION - + CLR_INT64 m_timeExpire; + bool m_fForce; + + //--// + + static HRESULT CreateInstance( CLR_RT_HeapBlock_Lock* lock, CLR_RT_SubThread* sth, const CLR_INT64& timeExpire, bool fForce ); +}; + +struct CLR_RT_HeapBlock_Timer : public CLR_RT_ObjectToEvent_Destination // EVENT HEAP - NO RELOCATION - +{ + static const CLR_UINT32 c_NoFixedChange = 0x00000000; + static const CLR_UINT32 c_SecondChange = 0x00000001; + static const CLR_UINT32 c_MinuteChange = 0x00000002; + static const CLR_UINT32 c_HourChange = 0x00000003; + static const CLR_UINT32 c_DayChange = 0x00000004; + static const CLR_UINT32 c_TimeZoneChange = 0x00000005; + static const CLR_UINT32 c_SetTimeChange = 0x00000006; + static const CLR_UINT32 c_AnyChange = 0x0000000F; + + static const CLR_UINT32 c_Triggered = 0x00000010; + static const CLR_UINT32 c_Executing = 0x00000020; + + static const CLR_UINT32 c_ACTION_Create = 0x00010000; + static const CLR_UINT32 c_ACTION_Change = 0x00020000; + static const CLR_UINT32 c_ACTION_Destroy = 0x00040000; + static const CLR_UINT32 c_UNUSED_00080000 = 0x00080000; + + static const CLR_UINT32 c_INPUT_Int32 = 0x00100000; + static const CLR_UINT32 c_INPUT_TimeSpan = 0x00200000; + static const CLR_UINT32 c_INPUT_Absolute = 0x00400000; + + static const CLR_UINT32 c_UNUSED_10000000 = 0x10000000; + static const CLR_UINT32 c_AbsoluteTimer = 0x20000000; + static const CLR_UINT32 c_Recurring = 0x40000000; + static const CLR_UINT32 c_EnabledTimer = 0x80000000; + + //--// + + static const CLR_INT32 c_TickPerMillisecond = 10000; + //--// + + CLR_UINT32 m_flags; + CLR_INT64 m_timeExpire; + CLR_INT64 m_timeFrequency; + CLR_INT64 m_timeLastExpiration; + CLR_INT64 m_ticksLastExpiration; + + //--// + + static HRESULT CreateInstance ( CLR_UINT32 flags, CLR_RT_HeapBlock& owner, CLR_RT_HeapBlock& tmRef ); + static HRESULT ExtractInstance( CLR_RT_HeapBlock& ref , CLR_RT_HeapBlock_Timer*& timer ); + static HRESULT ConfigureObject( CLR_RT_StackFrame& stack, CLR_UINT32 flags ); + static bool CheckDisposed ( CLR_RT_StackFrame& stack ); + + void AdjustNextFixedExpire( const SYSTEMTIME& systemTime, bool fNext ); + + void Trigger (); + void Reschedule (); + void RecoverFromGC(); + void SpawnTimer ( CLR_RT_Thread* thread ); + + static void ThreadTerminationCallback( void* param ); +}; + +struct CLR_RT_HeapBlock_EndPoint : public CLR_RT_ObjectToEvent_Destination // EVENT HEAP - NO RELOCATION - +{ + struct Port + { + CLR_UINT32 m_type; + CLR_UINT32 m_id; + + bool Compare( const Port& port ); + }; + + struct Address + { + CLR_UINT32 m_seq; + Port m_from; + Port m_to; + }; + + + struct Message : public CLR_RT_HeapBlock_Node + { + CLR_UINT32 m_cmd; + Address m_addr; + + CLR_UINT32 m_found; + CLR_UINT32 m_length; + + CLR_UINT8 m_data[ 1 ]; + }; + + Port m_addr; + CLR_RT_DblLinkedList m_messages; + CLR_UINT32 m_seq; + + //--// + + static CLR_RT_DblLinkedList m_endPoints; + + static void HandlerMethod_Initialize (); + static void HandlerMethod_RecoverFromGC(); + static void HandlerMethod_CleanUp (); + + static CLR_RT_HeapBlock_EndPoint* FindEndPoint( const CLR_RT_HeapBlock_EndPoint::Port& port ); + + static HRESULT CreateInstance ( const CLR_RT_HeapBlock_EndPoint::Port& port, CLR_RT_HeapBlock& owner, CLR_RT_HeapBlock& epRef ); + static HRESULT ExtractInstance( CLR_RT_HeapBlock& ref , CLR_RT_HeapBlock_EndPoint*& endPoint ); + + bool ReleaseWhenDeadEx(); + void RecoverFromGC (); + + Message* FindMessage( CLR_UINT32 cmd, const CLR_UINT32* seq ); +}; + +//--// + +struct CLR_RT_HeapBlock_WaitForObject : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - +{ + CLR_INT64 m_timeExpire; + CLR_UINT32 m_cObjects; + bool m_fWaitAll; + + CLR_RT_HeapBlock* GetWaitForObjects() { return &this[ 1 ]; } // EVENT HEAP - DO RELOCATION - + + //--// + + static HRESULT WaitForSignal ( CLR_RT_StackFrame& stack, const CLR_INT64& timeExpire, CLR_RT_HeapBlock& object ); + static HRESULT WaitForSignal ( CLR_RT_StackFrame& stack, const CLR_INT64& timeExpire, CLR_RT_HeapBlock* objects, CLR_UINT32 cObjects, bool fWaitAll ); + static void SignalObject ( CLR_RT_HeapBlock& object ); + + void Relocate(); + +private: + static bool TryWaitForSignal ( CLR_RT_Thread* caller, CLR_RT_HeapBlock* objects, CLR_UINT32 cObjects, bool fWaitAll ); + static void TryWaitForSignal ( CLR_RT_Thread* caller ); + static HRESULT CreateInstance ( CLR_RT_Thread* caller, const CLR_INT64& timeExpire, CLR_RT_HeapBlock* objects, CLR_UINT32 cObjects, bool fWaitAll ); +}; + +//--// + +struct CLR_RT_HeapBlock_Finalizer : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - +{ + CLR_RT_HeapBlock* m_object; // OBJECT HEAP - DO RELOCATION - + CLR_RT_MethodDef_Index m_md; + +#if defined(TINYCLR_APPDOMAINS) + CLR_RT_AppDomain* m_appDomain; +#endif + + //--// + + static HRESULT CreateInstance( CLR_RT_HeapBlock* object, const CLR_RT_TypeDef_Instance& inst ); + + void Relocate(); + + static void SuppressFinalize( CLR_RT_HeapBlock* object ); + +private: + static void RemoveInstance( CLR_RT_HeapBlock* object, CLR_RT_DblLinkedList& lst ); +}; + +//--// + +struct CLR_RT_HeapBlock_MemoryStream : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - +{ + struct Buffer : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - + { + static const int c_NumOfBlocks = 32; + static const int c_PayloadSize = c_NumOfBlocks * sizeof(CLR_RT_HeapBlock) - sizeof(CLR_UINT8*) - sizeof(int); + + CLR_UINT8* m_data; + int m_length; + CLR_UINT8 m_payload[ c_PayloadSize ]; + }; + + //--// + + CLR_RT_DblLinkedList m_buffers; // EVENT HEAP - NO RELOCATION - list of CLR_RT_HeapBlock_MemoryStream::Buffer + + Buffer* m_current; + int m_pos; + CLR_UINT32 m_avail; + + //--// + + static HRESULT CreateInstance( CLR_RT_HeapBlock_MemoryStream*& stream, CLR_UINT8* buf, int len ); + static void DeleteInstance( CLR_RT_HeapBlock_MemoryStream*& stream ); + + void Release(); + + void Rewind(); + void Reset(); + + HRESULT ToArray ( CLR_RT_HeapBlock& ref ); + + int BitsAvailable(); + int BitsWritten (); + + HRESULT ReadBits ( CLR_UINT32& val, CLR_UINT32 bits ); + HRESULT WriteBits ( CLR_UINT32 val, CLR_UINT32 bits ); + + HRESULT ReadBits ( CLR_UINT64& val, CLR_UINT32 bits ); + HRESULT WriteBits ( CLR_UINT64 val, CLR_UINT32 bits ); + + HRESULT ReadArray ( CLR_UINT8* buf, CLR_UINT32 bytes ); + HRESULT WriteArray( const CLR_UINT8* buf, CLR_UINT32 bytes ); + +private: + + HRESULT Initialize( CLR_UINT8* buf, CLR_UINT32 len ); + + Buffer* NewBuffer(); +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +struct CLR_RT_HeapBlock_WeakReference_Identity +{ + CLR_UINT32 m_crc; + CLR_UINT32 m_flags; + CLR_UINT32 m_length; + + CLR_UINT32 m_selectorHash; + CLR_UINT32 m_id; + CLR_INT32 m_priority; + + CLR_UINT32 ComputeCRC( const CLR_UINT8* ptr, CLR_UINT32 len ) const; +}; + +struct CLR_RT_HeapBlock_WeakReference : public CLR_RT_HeapBlock_Node // OBJECT HEAP - DO RELOCATION - +{ + static const CLR_UINT32 WR_SurviveBoot = 0x00000001; + static const CLR_UINT32 WR_SurvivePowerdown = 0x00000002; + static const CLR_UINT32 WR_ArrayOfBytes = 0x00000004; + static const CLR_UINT32 WR_Unused_00000008 = 0x00000008; + static const CLR_UINT32 WR_Unused_00000010 = 0x00000010; + static const CLR_UINT32 WR_Unused_00000020 = 0x00000020; + static const CLR_UINT32 WR_Unused_00000040 = 0x00000040; + static const CLR_UINT32 WR_Unused_00000080 = 0x00000080; + static const CLR_UINT32 WR_Unused_00000100 = 0x00000100; + static const CLR_UINT32 WR_Unused_00000200 = 0x00000200; + static const CLR_UINT32 WR_Unused_00000400 = 0x00000400; + static const CLR_UINT32 WR_Unused_00000800 = 0x00000800; + static const CLR_UINT32 WR_Unused_00001000 = 0x00001000; + static const CLR_UINT32 WR_Unused_00002000 = 0x00002000; + static const CLR_UINT32 WR_Unused_00004000 = 0x00004000; + static const CLR_UINT32 WR_Unused_00008000 = 0x00008000; + static const CLR_UINT32 WR_Unused_00010000 = 0x00010000; + static const CLR_UINT32 WR_Unused_00020000 = 0x00020000; + static const CLR_UINT32 WR_Unused_00040000 = 0x00040000; + static const CLR_UINT32 WR_Unused_00080000 = 0x00080000; + static const CLR_UINT32 WR_Unused_00100000 = 0x00100000; + static const CLR_UINT32 WR_Unused_00200000 = 0x00200000; + static const CLR_UINT32 WR_Unused_00400000 = 0x00400000; + static const CLR_UINT32 WR_Unused_00800000 = 0x00800000; + static const CLR_UINT32 WR_Unused_01000000 = 0x01000000; + static const CLR_UINT32 WR_Unused_02000000 = 0x02000000; + static const CLR_UINT32 WR_Unused_04000000 = 0x04000000; + static const CLR_UINT32 WR_Unused_08000000 = 0x08000000; + static const CLR_UINT32 WR_Unused_10000000 = 0x10000000; + static const CLR_UINT32 WR_Persisted = 0x20000000; + static const CLR_UINT32 WR_Restored = 0x40000000; + static const CLR_UINT32 WR_ExtendedType = 0x80000000; + + static const CLR_UINT32 WR_MaskForStorage = WR_SurviveBoot | WR_SurvivePowerdown | WR_ArrayOfBytes | WR_ExtendedType; + + //--// + + CLR_RT_HeapBlock_WeakReference_Identity m_identity; + + CLR_RT_HeapBlock* m_targetDirect; // OBJECT HEAP - DO RELOCATION - + CLR_RT_HeapBlock_Array* m_targetSerialized; // OBJECT HEAP - DO RELOCATION - + CLR_RT_HeapBlock_Array* m_targetCopied; // OBJECT HEAP - NO RELOCATION - + + //--// + + static HRESULT CreateInstance( CLR_RT_HeapBlock_WeakReference*& weakref ); + + static void RecoverObjects ( CLR_RT_DblLinkedList& lstHeap ); + static bool PrepareForRecovery( CLR_RT_HeapBlock_Node* ptr, CLR_RT_HeapBlock_Node* end, CLR_UINT32 blockSize ); + + HRESULT SetTarget( CLR_RT_HeapBlock& targetReference ); + HRESULT GetTarget( CLR_RT_HeapBlock& targetReference ); + + void InsertInPriorityOrder(); + + void Relocate(); +}; + +//--// + +struct CLR_RT_Persistence_Manager +{ + static const CLR_UINT32 c_Erased = 0xFFFFFFFF; + + struct ObjectHeader + { + static const CLR_UINT32 c_Version = 0x504F5631; // POV1 = Persisted Object V1 + + static const CLR_UINT32 c_InUseBlock = 0xFFFFFFFF; + static const CLR_UINT32 c_DeletedBlock = 0x00000000; + + CLR_UINT32 m_signature; + CLR_UINT32 m_status; + + CLR_UINT32 m_crcIdentity; + CLR_RT_HeapBlock_WeakReference_Identity m_identity; + + CLR_RT_HeapBlock_Array m_object; + + //--// + + static ObjectHeader* Find( FLASH_WORD* start, FLASH_WORD* end ); + + bool Initialize( CLR_RT_HeapBlock_WeakReference* ref ); + + bool HasGoodSignature() const { return m_signature == c_Version ; } + bool IsInUse () const { return m_status == c_InUseBlock; } + + bool IsGood( bool fIncludeData ) const; + + void Delete(); + + CLR_UINT32 Length( ) const; + static CLR_UINT32 Length( const CLR_RT_HeapBlock_WeakReference* ref ); + static CLR_UINT32 Length( CLR_UINT32 data ); + + ObjectHeader* Next() const; + + private: + CLR_UINT32 ComputeCRC() const; + + //--// + }; + + struct BankHeader + { + static const CLR_UINT32 c_Version = 0x50535631; // PSV1 = Persisted Storage V1 + + static const CLR_UINT32 c_InUseBank = 0xFFFFFFFF; + static const CLR_UINT32 c_DeletedBank = 0x00000000; + + CLR_UINT32 m_signature; + CLR_UINT32 m_status; + + CLR_UINT32 m_sequenceNumber; + + //--// + + static BankHeader* Find( FLASH_WORD* start, FLASH_WORD* end ); + + void Initialize(); + + bool HasGoodSignature() const { return m_signature == c_Version; } + bool IsInUse () const { return m_status == c_InUseBank; } + + bool IsGood() const; + + void Delete(); + + ObjectHeader* FirstObjectHeader() const { return (ObjectHeader*)&this[ 1 ]; } + }; + + struct Bank + { + static const CLR_UINT32 c_SafetyMargin = 10; + + static const FLASH_WORD c_Erased = 0xFFFFFFFF; + static const FLASH_WORD c_Invalidated = 0x00000000; + + //--// + + CLR_UINT32 m_totalBytes; + CLR_UINT32 m_totalSafeBytes; + + BlockStorageStream m_stream; + + BankHeader* m_bankHeader; + + FLASH_WORD* m_start; + FLASH_WORD* m_end; + + FLASH_WORD* m_current; + + //--// + + bool IsGood() const; + + bool Initialize( UINT32 kind ); + + bool Erase ( int& sectorIndex ); + void EraseAll( ); + + bool Format ( ); + bool SetSequence( CLR_UINT32 sequenceNumber ); + + void Switch( Bank& other ); + + CLR_RT_Persistence_Manager::ObjectHeader* RecoverHeader( CLR_RT_HeapBlock_WeakReference* ref ); + bool WriteHeader ( CLR_RT_HeapBlock_WeakReference* ref, ObjectHeader*& pOH, FLASH_WORD*& pData ); + + //--// + + BankHeader* GetBankHeader() const { return m_bankHeader; } + + //--// + + void ReloadNonXIPBufferData(); + + bool WriteNonXIPData(FLASH_WORD* dst, CLR_UINT32 length); + + static bool FindBankWriteNonXIPData(FLASH_WORD* dst, CLR_UINT32 length); + //--// + + static bool CanWrite ( FLASH_WORD* dst, CLR_UINT32 length ); + static bool Write ( FLASH_WORD* dst, const FLASH_WORD* src , CLR_UINT32 length ); + static void Invalidate( FLASH_WORD* dst, FLASH_WORD match, CLR_UINT32 length ); + + static FLASH_WORD* IncrementPointer( FLASH_WORD* ptr, CLR_UINT32 length ) + { + return (FLASH_WORD*)((CLR_UINT8*)ptr + length); + } + static FLASH_WORD* DecrementPointer( FLASH_WORD* ptr, CLR_UINT32 length ) { return (FLASH_WORD*)((CLR_UINT8*)ptr - length); } + }; + + //--// + + static const CLR_UINT32 STATE_FlushNextObject = 0; + static const CLR_UINT32 STATE_Idle = 1; + static const CLR_UINT32 STATE_Erase = 2; + static const CLR_UINT32 STATE_EraseSector = 3; + static const CLR_UINT32 STATE_CopyToOtherBank = 4; + static const CLR_UINT32 STATE_CopyBackToRam = 5; + static const CLR_UINT32 STATE_SwitchBank = 6; + + static const CLR_UINT32 c_MaxWriteBurst = 128; + + //--// + + HAL_COMPLETION m_completion; + + UINT32 m_margin_BurstWrite; + UINT32 m_margin_BlockErase; + + Bank m_bankA; + Bank m_bankB; + + CLR_UINT32 m_state; + + CLR_RT_HeapBlock_WeakReference* m_pending_object; + ObjectHeader* m_pending_header; + CLR_UINT32 m_pending_size; + FLASH_WORD* m_pending_src; + FLASH_WORD* m_pending_dst; + + int m_eraseIndex; + + //--// + + void Initialize(); + void Uninitialize(); + void EraseAll (); + + void InvalidateEntry( CLR_RT_HeapBlock_WeakReference* weak ); + + void Relocate(); + + ObjectHeader* RecoverHeader( CLR_RT_HeapBlock_WeakReference* ref ); + + static void Callback( void* arg ); + +#if !defined(BUILD_RTM) + void GenerateStatistics( CLR_UINT32& totalSize, CLR_UINT32& inUse ); +#endif + + void Flush(); + + //--// + +#undef DECL_POSTFIX +#if defined(TINYCLR_TRACE_PERSISTENCE) +#define DECL_POSTFIX +#else +#define DECL_POSTFIX {} +#endif + + static void Trace_Emit( LPSTR szText ) DECL_POSTFIX; + + static void Trace_Printf( LPCSTR format, ... ) DECL_POSTFIX; + + static void Trace_DumpIdentity( LPSTR& szBuffer, size_t& iBuffer, CLR_RT_HeapBlock_WeakReference_Identity* identity ) DECL_POSTFIX; + + static void Trace_DumpState( LPCSTR szText, FLASH_WORD* dst, ObjectHeader* oh, CLR_RT_HeapBlock_WeakReference* wr ) DECL_POSTFIX; + + //--// + +private: + + bool AdvanceState( bool force ); + + void EnqueueNextCallback(); +}; + +extern CLR_RT_Persistence_Manager g_CLR_RT_Persistence_Manager; + +//--// + + +struct CLR_RT_ApplicationInterrupt; + +//--// + +//struct GPIO_PortParams +//{ +// GPIO_INT_EDGE m_interruptMode; +// GPIO_RESISTOR m_resistorMode; +// bool m_glitchFilterEnable; +// bool m_initialState; +// bool m_initialDirectionOutput; +// +// //--// +// +// static const CLR_UINT8 c_Input = 0x01; // GPIO_ATTRIBUTE_INPUT +// static const CLR_UINT8 c_Output = 0x02; // GPIO_ATTRIBUTE_OUTPUT +// static const CLR_UINT8 c_AlternateA = 0x04; // GPIO_ATTRIBUTE_ALTERNATE_A +// static const CLR_UINT8 c_AlternateB = 0x08; // GPIO_ATTRIBUTE_ALTERNATE_B +// +// static const CLR_UINT8 c_InterruptDisabled = 0x10; +// static const CLR_UINT8 c_Disposed = 0x20; +//}; + + +struct CLR_RT_HeapBlock_NativeEventDispatcher : public CLR_RT_ObjectToEvent_Destination // EVENT HEAP - NO RELOCATION - +{ + static void HandlerMethod_Initialize (); + static void HandlerMethod_RecoverFromGC (); + static void HandlerMethod_CleanUp (); + + static CLR_RT_DblLinkedList m_ioPorts; + + + struct InterruptPortInterrupt + { + CLR_INT64 m_time; + CLR_RT_HeapBlock_NativeEventDispatcher* m_context; + CLR_UINT32 m_data1; + CLR_UINT32 m_data2; + CLR_UINT32 m_data3; + }; + + // Pointer to Hardware driver methods + CLR_RT_DriverInterruptMethods *m_DriverMethods; + //--// + // Poiner to custom data used by device drivers. + void *m_pDrvCustomData; + + + + //--// + + static HRESULT CreateInstance ( CLR_RT_HeapBlock& owner, CLR_RT_HeapBlock& portRef ); + static HRESULT ExtractInstance( CLR_RT_HeapBlock& ref, CLR_RT_HeapBlock_NativeEventDispatcher*& port ); + + HRESULT StartDispatch ( CLR_RT_ApplicationInterrupt* interrupt, CLR_RT_Thread* th ); + HRESULT RecoverManagedObject( CLR_RT_HeapBlock*& port ); + + static void ThreadTerminationCallback( void* arg ); + void SaveToHALQueue( UINT32 data1, UINT32 data2 ); + void RemoveFromHALQueue(); + + void RecoverFromGC (); + bool ReleaseWhenDeadEx(); +}; + +//--// + +struct CLR_RT_ApplicationInterrupt : public CLR_RT_HeapBlock_Node +{ + CLR_RT_HeapBlock_NativeEventDispatcher ::InterruptPortInterrupt m_interruptPortInterrupt; +}; + +//--// + +#define Library_corlib_native_System_Collections_ArrayList__FIELD___items 1 +#define Library_corlib_native_System_Collections_ArrayList__FIELD___size 2 + +struct CLR_RT_HeapBlock_ArrayList : public CLR_RT_HeapBlock +{ +public: + HRESULT GetItem( CLR_INT32 index, CLR_RT_HeapBlock*& value ); + HRESULT SetItem( CLR_INT32 index, CLR_RT_HeapBlock* value ); + + HRESULT Add( CLR_RT_HeapBlock* value, CLR_INT32& index ); + HRESULT Clear(); + HRESULT Insert( CLR_INT32 index, CLR_RT_HeapBlock* value ); + HRESULT RemoveAt( CLR_INT32 index ); + HRESULT SetCapacity( CLR_INT32 newCapacity ); + + //--// + + __inline CLR_INT32 GetSize() { return ((CLR_RT_HeapBlock*)this)[ Library_corlib_native_System_Collections_ArrayList__FIELD___size ].NumericByRef().s4; } + +private: + + // Keep in-sync with _defaultCapacity in System.Collections.ArrayList class in ArrayList.cs + static const CLR_INT32 c_DefaultCapacity = 4; + + HRESULT EnsureCapacity( CLR_INT32 min, CLR_INT32 currentCapacity ); + + __inline CLR_RT_HeapBlock_Array* GetItems() { return ((CLR_RT_HeapBlock*)this)[ Library_corlib_native_System_Collections_ArrayList__FIELD___items ].DereferenceArray(); } + + __inline void SetItems( CLR_RT_HeapBlock_Array* items ) { ((CLR_RT_HeapBlock*)this)[ Library_corlib_native_System_Collections_ArrayList__FIELD___items ].SetObjectReference( items ); } + __inline void SetSize ( CLR_INT32 size ) { ((CLR_RT_HeapBlock*)this)[ Library_corlib_native_System_Collections_ArrayList__FIELD___size ].SetInteger ( size ); } +}; + + +#define Library_corlib_native_System_Collections_Queue__FIELD___array 1 +#define Library_corlib_native_System_Collections_Queue__FIELD___head 2 +#define Library_corlib_native_System_Collections_Queue__FIELD___tail 3 +#define Library_corlib_native_System_Collections_Queue__FIELD___size 4 + +struct CLR_RT_HeapBlock_Queue : public CLR_RT_HeapBlock +{ +public: + HRESULT Dequeue( CLR_RT_HeapBlock*& value ); + HRESULT Enqueue( CLR_RT_HeapBlock* value ); + + HRESULT Peek( CLR_RT_HeapBlock*& value ); + HRESULT Clear(); + + HRESULT CopyTo( CLR_RT_HeapBlock_Array* toArray, CLR_INT32 index ); + + //--// + + __inline CLR_INT32 GetSize() { return ((CLR_RT_HeapBlock*)this)[ Library_corlib_native_System_Collections_Queue__FIELD___size ].NumericByRef().s4; } + +private: + + // Keep in-sync with _defaultCapacity in System.Collections.Queue class in Queue.cs + static const CLR_INT32 c_DefaultCapacity = 4; + + static HRESULT ObjArrayMemcpy( CLR_RT_HeapBlock_Array* arraySrc, int indexSrc, CLR_RT_HeapBlock_Array* arrayDst, int indexDst, int length ); + + __inline CLR_RT_HeapBlock_Array* GetArray() { return ((CLR_RT_HeapBlock*)this)[ Library_corlib_native_System_Collections_Queue__FIELD___array ].DereferenceArray(); } + __inline CLR_INT32 Head () { return ((CLR_RT_HeapBlock*)this)[ Library_corlib_native_System_Collections_Queue__FIELD___head ].NumericByRef().s4; } + __inline CLR_INT32 GetTail () { return ((CLR_RT_HeapBlock*)this)[ Library_corlib_native_System_Collections_Queue__FIELD___tail ].NumericByRef().s4; } + + __inline void SetArray( CLR_RT_HeapBlock_Array* array ) { ((CLR_RT_HeapBlock*)this)[ Library_corlib_native_System_Collections_Queue__FIELD___array ].SetObjectReference( array ); } + __inline void SetHead ( CLR_INT32 head ) { ((CLR_RT_HeapBlock*)this)[ Library_corlib_native_System_Collections_Queue__FIELD___head ].SetInteger ( head ); } + __inline void SetTail ( CLR_INT32 tail ) { ((CLR_RT_HeapBlock*)this)[ Library_corlib_native_System_Collections_Queue__FIELD___tail ].SetInteger ( tail ); } + __inline void SetSize ( CLR_INT32 size ) { ((CLR_RT_HeapBlock*)this)[ Library_corlib_native_System_Collections_Queue__FIELD___size ].SetInteger ( size ); } +}; + + +#define Library_corlib_native_System_Collections_Stack__FIELD___array 1 +#define Library_corlib_native_System_Collections_Stack__FIELD___size 2 + +struct CLR_RT_HeapBlock_Stack : public CLR_RT_HeapBlock +{ +public: + HRESULT Pop( CLR_RT_HeapBlock*& value ); + HRESULT Push( CLR_RT_HeapBlock* value ); + + HRESULT Peek( CLR_RT_HeapBlock*& value ); + HRESULT Clear(); + + //--// + + __inline CLR_INT32 GetSize() { return ((CLR_RT_HeapBlock*)this)[ Library_corlib_native_System_Collections_Stack__FIELD___size ].NumericByRef().s4; } + +protected: + + // Keep in-sync with _defaultCapacity in System.Collections.Stack class in Stack.cs + static const CLR_INT32 c_DefaultCapacity = 4; + + __inline CLR_RT_HeapBlock_Array* GetArray() { return ((CLR_RT_HeapBlock*)this)[ Library_corlib_native_System_Collections_Stack__FIELD___array ].DereferenceArray(); } + + __inline void SetArray( CLR_RT_HeapBlock_Array* array ) { ((CLR_RT_HeapBlock*)this)[ Library_corlib_native_System_Collections_Stack__FIELD___array ].SetObjectReference( array ); } + __inline void SetSize ( CLR_INT32 size ) { ((CLR_RT_HeapBlock*)this)[ Library_corlib_native_System_Collections_Stack__FIELD___size ].SetInteger ( size ); } +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#endif // _TINYCLR_RUNTIME__HEAPBLOCK_H_ diff --git a/src/CLR/Include/TinyCLR_Runtime__Serialization.h b/src/CLR/Include/TinyCLR_Runtime__Serialization.h new file mode 100644 index 0000000000..281b4607ab --- /dev/null +++ b/src/CLR/Include/TinyCLR_Runtime__Serialization.h @@ -0,0 +1,284 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _TINYCLR_RUNTIME__SERIALIZATION_H_ +#define _TINYCLR_RUNTIME__SERIALIZATION_H_ + +struct CLR_RT_BinaryFormatter : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - +{ + ////////////////////////////////////////////////////////////////// + // + // Keep in sync with definitions in Reflection.cs!!!! + // Keep in sync with definitions in Reflection.cs!!!! + // Keep in sync with definitions in Reflection.cs!!!! + // + static const int TE_L1 = 2; + static const CLR_UINT32 TE_L1_Null = 0x00000000; + static const CLR_UINT32 TE_L1_Duplicate = 0x00000001; // N bits for the duplicate id. + static const CLR_UINT32 TE_L1_Reference = 0x00000002; // 32 bits for the type. + static const CLR_UINT32 TE_L1_Other = 0x00000003; + + static const int TE_L2 = 2; + static const CLR_UINT32 TE_L2_Primitive = 0x00000000; // 4 bits for the type. + static const CLR_UINT32 TE_L2_Array = 0x00000001; + static const CLR_UINT32 TE_L2_ArrayList = 0x00000002; + static const CLR_UINT32 TE_L2_Other = 0x00000003; + + static const int TE_L3 = 4; + static const CLR_UINT32 TE_L3_Type = 0x00000000; // 32 bits for the type. + static const CLR_UINT32 TE_L3_Reflection = 0x00000001; // CLR_RT_ReflectionDef_Index. Valid in marshaling only. + static const CLR_UINT32 TE_L3_MBRO = 0x00000002; // 32 bits for the pointer to the MBRO class, 32 bits for the pointer to the AppDomain + + static const int TE_ElementType = 4; + static const int TE_ArrayDepth = 4; + + static const CLR_UINT32 c_Flags_None = 0x00000000; + static const CLR_UINT32 c_Flags_Marshal = 0x00000001; + + // + //--// + // + enum SerializationFlags + { + SF_Encrypted = 0x00000001, + SF_Compressed = 0x00000002, // Value uses range compression (max 2^30 values). + SF_Optional = 0x00000004, // If the value cannot be deserialized, skip it. + + SF_PointerNeverNull = 0x00000010, + SF_ElementsNeverNull = 0x00000020, + + SF_FixedType = 0x00000100, + }; + // + struct SerializationHintsAttribute + { + SerializationFlags m_flags; + + int m_arraySize; // -1 == extend to the end of the stream. + + int m_bitPacked; // In bits. + CLR_INT64 m_rangeBias; + CLR_UINT64 m_scale; // For time, it's in ticks. + }; + // + ////////////////////////////////////////////////////////////////// + + struct TypeHandler + { + // + // Type of signatures: + // + // 1) NULL + // + // Invalid for NeverNull + // + // 2) DUPLICATE + // + // Invalid for Sealed/FixedType + NeverNull + // + // 3) PRIMITIVE + // + // optional for FixedType + // PRIMITIVE optional for FixedType + NeverNull + // + // 4) REFERENCE + // + // optional for Sealed/FixedType + // REFERENCE optional for Sealed/FixedType + NeverNull + // + // 5) ARRAYLIST + // + // optional for FixedSize + // ARRAYLIST optional for FixedType + NeverNull + // + // 6) ARRAY + // + // optional for FixedSize + // optional for FixedType + // ARRAY optional for FixedType + NeverNull + // + // 7) REFLECTION + // + // only valid for marshaling + // + // 8) MBRO + // pointer to the DATATYPE_CLASS of the MarshalByRefObject on the object heap + // It is the responsibility of the caller (CLR_RT_AppDomain::MarshalObject) to ensure that + // this pointer is kept alive, and not moved during the marshaling process + // pointer to the AppDomain that this MBRO object lives in. + // It is the responsiblity of the caller (CLR_RT_AppDomain::MarshalObject) to ensure that + // the AppDomain does not get unloaded during the marshaling process. + // + + // Always match type if FixedTyped is specified. + // + static const int c_Signature_Header = 0x01; + static const int c_Signature_Type = 0x02; + static const int c_Signature_Length = 0x04; + + static const int c_Action_None = 0; + static const int c_Action_ObjectData = 1; + static const int c_Action_ObjectFields = 2; + static const int c_Action_ObjectElements = 3; + + //--// + + CLR_RT_HeapBlock* m_value; + SerializationHintsAttribute m_hints; + CLR_RT_TypeDescriptor* m_type; + + CLR_RT_TypeDescriptor* m_typeExpected; + CLR_RT_TypeDescriptor* m_typeForced; + + CLR_RT_BinaryFormatter* m_bf; + + CLR_RT_HeapBlock m_value_tmp; + CLR_RT_TypeDescriptor m_type_tmp; + CLR_RT_TypeDescriptor m_typeExpected_tmp; + CLR_RT_TypeDescriptor m_typeForced_tmp; + +#if defined(TINYCLR_APPDOMAINS) + bool m_fIsMarshalByRefObject; +#endif + + //--// + + HRESULT TypeHandler_Initialize( CLR_RT_BinaryFormatter* bf, SerializationHintsAttribute* hints, CLR_RT_TypeDescriptor* expected ); + + HRESULT SetValue( CLR_RT_HeapBlock* v ); + + //--// + + int SignatureRequirements(); + + bool CompareTypes( CLR_RT_TypeDescriptor* left, CLR_RT_TypeDescriptor* right ); + + static CLR_DataType GetDataType ( CLR_RT_TypeDescriptor* type ); + static CLR_UINT32 GetSizeOfType( CLR_RT_TypeDescriptor* type ); + static bool GetSignOfType( CLR_RT_TypeDescriptor* type ); + + static CLR_RT_HeapBlock* FixDereference( CLR_RT_HeapBlock* v ); + static CLR_RT_HeapBlock* FixNull ( CLR_RT_HeapBlock* v ); + + //--// + + HRESULT EmitSignature ( int& res ); + HRESULT EmitSignature_Inner( int mask, CLR_RT_TypeDescriptor* type, CLR_RT_HeapBlock* value ); + HRESULT ReadSignature ( int& res ); + HRESULT EmitValue ( int& res ); + HRESULT ReadValue ( int& res ); + + HRESULT TrackObject ( int& res ); + }; + + struct State : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - + { + CLR_RT_BinaryFormatter* m_parent; + + bool m_value_NeedProcessing; + TypeHandler m_value; + + bool m_fields_NeedProcessing; + CLR_RT_TypeDef_Instance m_fields_CurrentClass; + int m_fields_CurrentField; + CLR_RT_HeapBlock* m_fields_Pointer; + + bool m_array_NeedProcessing; + CLR_RT_TypeDescriptor* m_array_ExpectedType; + CLR_RT_TypeDescriptor m_array_ExpectedType_Tmp; + CLR_RT_HeapBlock_Array* m_array; + int m_array_CurrentPos; + int m_array_LastPos; + + //--// + + static HRESULT CreateInstance( CLR_RT_BinaryFormatter* parent, SerializationHintsAttribute* hints, CLR_RT_HeapBlock* type ); + static HRESULT CreateInstance( CLR_RT_BinaryFormatter* parent, SerializationHintsAttribute* hints, CLR_RT_TypeDescriptor* type ); + + void DestroyInstance(); + + HRESULT FindHints( SerializationHintsAttribute& hints, const CLR_RT_TypeDef_Instance& cls ); + HRESULT FindHints( SerializationHintsAttribute& hints, const CLR_RT_FieldDef_Instance& fld ); + + //--// + + HRESULT AssignAndFixBoxing( CLR_RT_HeapBlock& dst ); + + HRESULT GetValue (); + HRESULT SetValueAndDestroyInstance(); + + //--// + + HRESULT Advance (); + HRESULT AdvanceToTheNextField (); + HRESULT AdvanceToTheNextElement(); + }; + + + struct DuplicateTracker : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOCATION - + { + CLR_RT_HeapBlock* m_ptr; + CLR_UINT32 m_idx; + }; + + //--// + + CLR_RT_HeapBlock_MemoryStream* m_stream; + CLR_UINT32 m_idx; + CLR_UINT32 m_lastTypeRead; + CLR_RT_DblLinkedList m_duplicates; // EVENT HEAP - NO RELOCATION - list of CLR_RT_BinaryFormatter::DuplicateTracker + CLR_RT_DblLinkedList m_states; // EVENT HEAP - NO RELOCATION - list of CLR_RT_BinaryFormatter::State + + bool m_fDeserialize; + CLR_RT_HeapBlock m_value; + CLR_RT_TypeDescriptor m_value_desc; + + CLR_UINT32 m_flags; + + //--// + + static bool SerializationEnabled(); + + static HRESULT CreateInstance( CLR_UINT8* buf, int len, CLR_RT_BinaryFormatter*& res ); + + void DestroyInstance(); + HRESULT Advance (); + + static HRESULT Serialize ( CLR_RT_HeapBlock& refData, CLR_RT_HeapBlock& object , CLR_RT_HeapBlock* cls , CLR_UINT32 flags ); + static HRESULT Deserialize( CLR_RT_HeapBlock& refData, CLR_RT_HeapBlock& object , CLR_RT_HeapBlock* cls, CLR_UINT32* unknownType, CLR_UINT32 flags ); + static HRESULT Deserialize( CLR_RT_HeapBlock& refData, CLR_UINT8* data, CLR_UINT32 size, CLR_RT_HeapBlock* cls, CLR_UINT32* unknownType, CLR_UINT32 flags ); + + HRESULT TrackDuplicate ( CLR_RT_HeapBlock* object ); + CLR_UINT32 SearchDuplicate( CLR_RT_HeapBlock* object ); + CLR_RT_HeapBlock* GetDuplicate ( CLR_UINT32 idx ); + + //--// + + int BitsAvailable ( ); + + HRESULT ReadBits ( CLR_UINT32& val, int bits ); + HRESULT WriteBits ( CLR_UINT32 val, int bits ); + + HRESULT ReadBits ( CLR_UINT64& val, int bits ); + HRESULT WriteBits ( CLR_UINT64 val, int bits ); + + HRESULT ReadArray ( CLR_UINT8* buf, int bytes ); + HRESULT WriteArray ( const CLR_UINT8* buf, int bytes ); + + HRESULT ReadCompressedUnsigned ( CLR_UINT32& val ); + HRESULT WriteCompressedUnsigned( CLR_UINT32 val ); + + HRESULT ReadType ( CLR_RT_ReflectionDef_Index& val ); + HRESULT WriteType ( const CLR_RT_ReflectionDef_Index& val ); + HRESULT WriteType ( CLR_UINT32 val ); + + //--// + +private: + + static void PrepareForGC( void* data ); +}; + +#endif // _TINYCLR_RUNTIME__SERIALIZATION_H_ diff --git a/src/CLR/Include/TinyCLR_Types.h b/src/CLR/Include/TinyCLR_Types.h new file mode 100644 index 0000000000..0af9a0a150 --- /dev/null +++ b/src/CLR/Include/TinyCLR_Types.h @@ -0,0 +1,1149 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _TINYCLR_TYPES_H_ +#define _TINYCLR_TYPES_H_ + +#include + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#define FAULT_ON_NULL_HR(ptr,hr) if(!(ptr) ) TINYCLR_SET_AND_LEAVE((hr) ) +#define CHECK_ALLOCATION(ptr) if(!(ptr) ) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY) +#define CHECK_SIZE_RANGE(len) if( len > CLR_RT_HeapBlock::HB_MaxSize) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE ) + +#define FIMPLIES(x,y) ((!(x)) || (y)) +#define FINRANGE(val,lo,hi) (((val) >= (lo)) && ((val) <= (hi))) + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#define TINYCLR_INTEROP_STUB_RETURN(stack) return stack.NotImplementedStub() +#define TINYCLR_SYSTEM_STUB_RETURN() return S_OK +#define TINYCLR_FEATURE_STUB_RETURN() return CLR_E_NOTIMPL + +////////////////////////////////////////////////// + +#define TINYCLR_PARAMCHECK_BEGIN() \ +{ \ + HRESULT hrInner = S_OK; + +#define TINYCLR_PARAMCHECK_POINTER(ptr) \ + { \ + if(ptr == NULL) \ + { \ + hrInner = CLR_E_NULL_REFERENCE; \ + } \ + } + +#define TINYCLR_PARAMCHECK_POINTER_AND_SET(ptr,val) \ + { \ + if(ptr == NULL) \ + { \ + hrInner = CLR_E_NULL_REFERENCE; \ + } \ + else \ + { \ + *ptr = val; \ + } \ + } + +#define TINYCLR_PARAMCHECK_NOTNULL(ptr) \ + { \ + if(ptr == NULL) \ + { \ + hrInner = CLR_E_INVALID_PARAMETER; \ + } \ + } + +#define TINYCLR_PARAMCHECK_STRING_NOT_EMPTY(ptr) \ + { \ + if(ptr == NULL || ptr[ 0 ] == 0) \ + { \ + hrInner = CLR_E_INVALID_PARAMETER; \ + } \ + } + +#define TINYCLR_PARAMCHECK_END() \ + { TINYCLR_CHECK_HRESULT(hrInner); } \ +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(_MSC_VER) +#pragma pack(push, TINYCLR_TYPES_H, 4) +#endif + +enum CLR_OPCODE +{ +#define OPDEF(c,s,pop,push,args,type,l,s1,s2,ctrl) c, +#include "opcode.def" +#undef OPDEF +CEE_COUNT, /* number of instructions and macros pre-defined */ +}; + +#if defined(__ADSPBLACKFIN__) || defined (__GNUC__) || defined(_ARC) || defined(__RENESAS__) +#define __int64 long long +#endif + +typedef unsigned char CLR_UINT8; +typedef unsigned short CLR_UINT16; +typedef unsigned int CLR_UINT32; +typedef unsigned __int64 CLR_UINT64; +typedef signed char CLR_INT8; +typedef signed short CLR_INT16; +typedef signed int CLR_INT32; +typedef signed __int64 CLR_INT64; + +typedef CLR_UINT16 CLR_OFFSET; +typedef CLR_UINT32 CLR_OFFSET_LONG; +typedef CLR_UINT16 CLR_IDX; +typedef CLR_UINT16 CLR_STRING; +typedef CLR_UINT16 CLR_SIG; +typedef const CLR_UINT8* CLR_PMETADATA; + + +//--// +//may need to change later +typedef CLR_INT64 CLR_INT64_TEMP_CAST; +typedef CLR_UINT64 CLR_UINT64_TEMP_CAST; + +#if !defined(TINYCLR_EMULATED_FLOATINGPOINT) +typedef double CLR_DOUBLE_TEMP_CAST; +#else +typedef CLR_INT64 CLR_DOUBLE_TEMP_CAST; +#endif + +#define CLR_SIG_INVALID 0xFFFF + +enum CLR_LOGICAL_OPCODE +{ + LO_Not = 0x00, + LO_And = 0x01, + LO_Or = 0x02, + LO_Xor = 0x03, + LO_Shl = 0x04, + LO_Shr = 0x05, + + LO_Neg = 0x06, + LO_Add = 0x07, + LO_Sub = 0x08, + LO_Mul = 0x09, + LO_Div = 0x0A, + LO_Rem = 0x0B, + + LO_Box = 0x0C, + LO_Unbox = 0x0D, + + LO_Branch = 0x0E, + LO_Set = 0x0F, + LO_Switch = 0x10, + + LO_LoadFunction = 0x11, + LO_LoadVirtFunction = 0x12, + + LO_Call = 0x13, + LO_CallVirt = 0x14, + LO_Ret = 0x15, + + LO_NewObject = 0x16, + LO_CastClass = 0x17, + LO_IsInst = 0x18, + + LO_Dup = 0x19, + LO_Pop = 0x1A, + + LO_Throw = 0x1B, + LO_Rethrow = 0x1C, + LO_Leave = 0x1D, + LO_EndFinally = 0x1E, + + LO_Convert = 0x1F, + + LO_StoreArgument = 0x20, + LO_LoadArgument = 0x21, + LO_LoadArgumentAddress = 0x22, + + LO_StoreLocal = 0x23, + LO_LoadLocal = 0x24, + LO_LoadLocalAddress = 0x25, + + LO_LoadConstant_I4 = 0x26, + LO_LoadConstant_I8 = 0x27, + LO_LoadConstant_R4 = 0x28, + LO_LoadConstant_R8 = 0x29, + + LO_LoadNull = 0x2A, + LO_LoadString = 0x2B, + LO_LoadToken = 0x2C, + + LO_NewArray = 0x2D, + LO_LoadLength = 0x2E, + + LO_StoreElement = 0x2F, + LO_LoadElement = 0x30, + LO_LoadElementAddress = 0x31, + + LO_StoreField = 0x32, + LO_LoadField = 0x33, + LO_LoadFieldAddress = 0x34, + + LO_StoreStaticField = 0x35, + LO_LoadStaticField = 0x36, + LO_LoadStaticFieldAddress = 0x37, + + LO_StoreIndirect = 0x38, + LO_LoadIndirect = 0x39, + + LO_InitObject = 0x3A, + LO_LoadObject = 0x3B, + LO_CopyObject = 0x3C, + LO_StoreObject = 0x3D, + + LO_Nop = 0x3E, + + LO_EndFilter = 0x3F, + + LO_Unsupported = 0x40, + + LO_FIRST = LO_Not, + LO_LAST = LO_EndFilter, +}; + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +static const CLR_IDX CLR_EmptyIndex = 0xFFFF; +static const CLR_UINT32 CLR_EmptyToken = 0xFFFFFFFF; +static const size_t CLR_MaxStreamSize_AssemblyRef = 0x0000FFFF; +static const size_t CLR_MaxStreamSize_TypeRef = 0x0000FFFF; +static const size_t CLR_MaxStreamSize_FieldRef = 0x0000FFFF; +static const size_t CLR_MaxStreamSize_MethodRef = 0x0000FFFF; +static const size_t CLR_MaxStreamSize_TypeDef = 0x0000FFFF; +static const size_t CLR_MaxStreamSize_FieldDef = 0x0000FFFF; +static const size_t CLR_MaxStreamSize_MethodDef = 0x0000FFFF; +static const size_t CLR_MaxStreamSize_Attributes = 0x0000FFFF; +static const size_t CLR_MaxStreamSize_TypeSpec = 0x0000FFFF; +static const size_t CLR_MaxStreamSize_Resources = 0x0000FFFF; +static const size_t CLR_MaxStreamSize_ResourcesData = 0xFFFFFFFF; +static const size_t CLR_MaxStreamSize_Strings = 0x0000FFFF; +static const size_t CLR_MaxStreamSize_Signatures = 0x0000FFFF; +static const size_t CLR_MaxStreamSize_ByteCode = 0x0000FFFF; +static const size_t CLR_MaxStreamSize_ResourcesFiles = 0x0000FFFF; + +enum CLR_OpcodeParam +{ + CLR_OpcodeParam_Field = 0, + CLR_OpcodeParam_Method = 1, + CLR_OpcodeParam_Type = 2, + CLR_OpcodeParam_String = 3, + CLR_OpcodeParam_Tok = 4, + CLR_OpcodeParam_Sig = 5, + CLR_OpcodeParam_BrTarget = 6, + CLR_OpcodeParam_ShortBrTarget = 7, + CLR_OpcodeParam_I = 8, + CLR_OpcodeParam_I8 = 9, + CLR_OpcodeParam_None = 10, + CLR_OpcodeParam_R = 11, + CLR_OpcodeParam_Switch = 12, + CLR_OpcodeParam_Var = 13, + CLR_OpcodeParam_ShortI = 14, + CLR_OpcodeParam_ShortR = 15, + CLR_OpcodeParam_ShortVar = 16, +}; + +#define CanCompressOpParamToken(opParam) (opParam >= CLR_OpcodeParam_Field && opParam <= CLR_OpcodeParam_String) +#define IsOpParamToken(opParam) (opParam >= CLR_OpcodeParam_Field && opParam <= CLR_OpcodeParam_Sig) + +//--// + +enum CLR_FlowControl +{ + CLR_FlowControl_NEXT = 0, + CLR_FlowControl_CALL = 1, + CLR_FlowControl_RETURN = 2, + CLR_FlowControl_BRANCH = 3, + CLR_FlowControl_COND_BRANCH = 4, + CLR_FlowControl_THROW = 5, + CLR_FlowControl_BREAK = 6, + CLR_FlowControl_META = 7, +}; + +//--// + +#define c_CLR_StringTable_Version 1 + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +enum CLR_TABLESENUM +{ + TBL_AssemblyRef = 0x00000000, + TBL_TypeRef = 0x00000001, + TBL_FieldRef = 0x00000002, + TBL_MethodRef = 0x00000003, + TBL_TypeDef = 0x00000004, + TBL_FieldDef = 0x00000005, + TBL_MethodDef = 0x00000006, + TBL_Attributes = 0x00000007, + TBL_TypeSpec = 0x00000008, + TBL_Resources = 0x00000009, + TBL_ResourcesData = 0x0000000A, + TBL_Strings = 0x0000000B, + TBL_Signatures = 0x0000000C, + TBL_ByteCode = 0x0000000D, + TBL_ResourcesFiles = 0x0000000E, + TBL_EndOfAssembly = 0x0000000F, + TBL_Max = 0x00000010, +}; + +enum CLR_CorCallingConvention +{ + ///////////////////////////////////////////////////////////////////////////////////////////// + // + // This is based on CorCallingConvention. + // + PIMAGE_CEE_CS_CALLCONV_DEFAULT = 0x0, + + PIMAGE_CEE_CS_CALLCONV_VARARG = 0x5, + PIMAGE_CEE_CS_CALLCONV_FIELD = 0x6, + PIMAGE_CEE_CS_CALLCONV_LOCAL_SIG = 0x7, + PIMAGE_CEE_CS_CALLCONV_PROPERTY = 0x8, + PIMAGE_CEE_CS_CALLCONV_UNMGD = 0x9, + PIMAGE_CEE_CS_CALLCONV_GENERICINST = 0xa, // generic method instantiation + PIMAGE_CEE_CS_CALLCONV_NATIVEVARARG = 0xb, // used ONLY for 64bit vararg PInvoke calls + PIMAGE_CEE_CS_CALLCONV_MAX = 0xc, // first invalid calling convention + + // The high bits of the calling convention convey additional info + PIMAGE_CEE_CS_CALLCONV_MASK = 0x0f, // Calling convention is bottom 4 bits + PIMAGE_CEE_CS_CALLCONV_HASTHIS = 0x20, // Top bit indicates a 'this' parameter + PIMAGE_CEE_CS_CALLCONV_EXPLICITTHIS = 0x40, // This parameter is explicitly in the signature + PIMAGE_CEE_CS_CALLCONV_GENERIC = 0x10, // Generic method sig with explicit number of type arguments (precedes ordinary parameter count) + // + // End of overlap with CorCallingConvention. + // + ///////////////////////////////////////////////////////////////////////////////////////////// +}; + +enum CLR_DataType // KEEP IN SYNC WITH Microsoft.SPOT.DataType!! +{ + DATATYPE_VOID , // 0 bytes + + DATATYPE_BOOLEAN , // 1 byte + DATATYPE_I1 , // 1 byte + DATATYPE_U1 , // 1 byte + + DATATYPE_CHAR , // 2 bytes + DATATYPE_I2 , // 2 bytes + DATATYPE_U2 , // 2 bytes + + DATATYPE_I4 , // 4 bytes + DATATYPE_U4 , // 4 bytes + DATATYPE_R4 , // 4 bytes + + DATATYPE_I8 , // 8 bytes + DATATYPE_U8 , // 8 bytes + DATATYPE_R8 , // 8 bytes + DATATYPE_DATETIME , // 8 bytes // Shortcut for System.DateTime + DATATYPE_TIMESPAN , // 8 bytes // Shortcut for System.TimeSpan + DATATYPE_STRING , + + DATATYPE_LAST_NONPOINTER = DATATYPE_TIMESPAN, // This is the last type that doesn't need to be relocated. + DATATYPE_LAST_PRIMITIVE_TO_PRESERVE = DATATYPE_R8 , // All the above types don't need fix-up on assignment. +#if defined(TINYCLR_NO_ASSEMBLY_STRINGS) + DATATYPE_LAST_PRIMITIVE_TO_MARSHAL = DATATYPE_STRING, // All the above types can be marshaled by assignment. +#else + DATATYPE_LAST_PRIMITIVE_TO_MARSHAL = DATATYPE_TIMESPAN, // All the above types can be marshaled by assignment. +#endif + DATATYPE_LAST_PRIMITIVE = DATATYPE_STRING , // All the above types don't need fix-up on assignment. + + DATATYPE_OBJECT , // Shortcut for System.Object + DATATYPE_CLASS , // CLASS + DATATYPE_VALUETYPE , // VALUETYPE + DATATYPE_SZARRAY , // Shortcut for single dimension zero lower bound array SZARRAY + DATATYPE_BYREF , // BYREF + + //////////////////////////////////////// + + DATATYPE_FREEBLOCK , + DATATYPE_CACHEDBLOCK , + DATATYPE_ASSEMBLY , + DATATYPE_WEAKCLASS , + DATATYPE_REFLECTION , + DATATYPE_ARRAY_BYREF , + DATATYPE_DELEGATE_HEAD , + DATATYPE_DELEGATELIST_HEAD , + DATATYPE_OBJECT_TO_EVENT , + DATATYPE_BINARY_BLOB_HEAD , + + DATATYPE_THREAD , + DATATYPE_SUBTHREAD , + DATATYPE_STACK_FRAME , + DATATYPE_TIMER_HEAD , + DATATYPE_LOCK_HEAD , + DATATYPE_LOCK_OWNER_HEAD , + DATATYPE_LOCK_REQUEST_HEAD , + DATATYPE_WAIT_FOR_OBJECT_HEAD , + DATATYPE_FINALIZER_HEAD , + DATATYPE_MEMORY_STREAM_HEAD , // SubDataType? + DATATYPE_MEMORY_STREAM_DATA , // SubDataType? + + DATATYPE_SERIALIZER_HEAD , // SubDataType? + DATATYPE_SERIALIZER_DUPLICATE , // SubDataType? + DATATYPE_SERIALIZER_STATE , // SubDataType? + + DATATYPE_ENDPOINT_HEAD , + + //These constants are shared by Debugger.dll, and cannot be conditionally compiled away. + //This adds a couple extra bytes to the lookup table. But frankly, the lookup table should probably + //be shrunk to begin with. Most of the datatypes are used just to tag memory. + //For those datatypes, perhaps we should use a subDataType instead (probably what the comments above are about). + + DATATYPE_RADIO_LAST = DATATYPE_ENDPOINT_HEAD + 3, + + DATATYPE_IO_PORT , + DATATYPE_IO_PORT_LAST = DATATYPE_RADIO_LAST + 1, + + DATATYPE_VTU_PORT_LAST = DATATYPE_IO_PORT_LAST + 1, + + DATATYPE_I2C_XACTION , + DATATYPE_I2C_XACTION_LAST = DATATYPE_VTU_PORT_LAST + 1, + +#if defined(TINYCLR_APPDOMAINS) + DATATYPE_APPDOMAIN_HEAD , + DATATYPE_TRANSPARENT_PROXY , + DATATYPE_APPDOMAIN_ASSEMBLY , +#endif + DATATYPE_APPDOMAIN_LAST = DATATYPE_I2C_XACTION_LAST + 3, + + DATATYPE_FIRST_INVALID , + + // Type modifies. This is exact copy of VALUES ELEMENT_TYPE_* from CorHdr.h + // + + DATATYPE_TYPE_MODIFIER = 0x40, + DATATYPE_TYPE_SENTINEL = 0x01 | DATATYPE_TYPE_MODIFIER, // sentinel for varargs + DATATYPE_TYPE_PINNED = 0x05 | DATATYPE_TYPE_MODIFIER, + DATATYPE_TYPE_R4_HFA = 0x06 | DATATYPE_TYPE_MODIFIER, // used only internally for R4 HFA types + DATATYPE_TYPE_R8_HFA = 0x07 | DATATYPE_TYPE_MODIFIER, // used only internally for R8 HFA types +}; + +enum CLR_ReflectionType +{ + REFLECTION_INVALID = 0x00, + REFLECTION_ASSEMBLY = 0x01, + REFLECTION_TYPE = 0x02, + REFLECTION_TYPE_DELAYED = 0x03, + REFLECTION_CONSTRUCTOR = 0x04, + REFLECTION_METHOD = 0x05, + REFLECTION_FIELD = 0x06, +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +inline CLR_UINT32 CLR_DataFromTk( CLR_UINT32 tk ) { return tk & 0x00FFFFFF; } +inline CLR_TABLESENUM CLR_TypeFromTk( CLR_UINT32 tk ) { return (CLR_TABLESENUM)(tk >> 24); } +inline CLR_UINT32 CLR_TkFromType( CLR_TABLESENUM tbl, CLR_UINT32 data ) { return ((((CLR_UINT32)tbl) << 24) & 0xFF000000) | (data & 0x00FFFFFF); } +#if 0 +// Used on LE host to target BE +inline CLR_UINT32 CLR_TkFromType( CLR_TABLESENUM tbl, CLR_UINT32 data ) { return ( ((CLR_UINT32)(tbl) & 0xFF) | (data & 0xFFFFFF00)); } +inline CLR_UINT32 CLR_DataFromTk( CLR_UINT32 tk ) { return tk & 0xFFFFFF00; } +inline CLR_TABLESENUM CLR_TypeFromTk( CLR_UINT32 tk ) { return (CLR_TABLESENUM)(tk&0xFF); } +#endif +//--// + +inline CLR_UINT32 CLR_UncompressStringToken( CLR_UINT32 tk ) +{ + return CLR_TkFromType( TBL_Strings, tk ); +} + +inline CLR_UINT32 CLR_UncompressTypeToken( CLR_UINT32 tk ) +{ + static const CLR_TABLESENUM c_lookup[3] = { TBL_TypeDef, TBL_TypeRef, TBL_TypeSpec }; + return CLR_TkFromType( c_lookup[(tk >> 14) & 3], 0x3fff & tk ); +} + +inline CLR_UINT32 CLR_UncompressFieldToken( CLR_UINT32 tk ) +{ + static const CLR_TABLESENUM c_lookup[2] = { TBL_FieldDef, TBL_FieldRef }; + return CLR_TkFromType( c_lookup[(tk >> 15) & 1], 0x7fff & tk ); +} + +inline CLR_UINT32 CLR_UncompressMethodToken( CLR_UINT32 tk ) +{ + static const CLR_TABLESENUM c_lookup[ 2 ] = { TBL_MethodDef, TBL_MethodRef }; + return CLR_TkFromType( c_lookup[ (tk >> 15) & 1 ], 0x7fff & tk ); +} + +#if defined(_WIN32) + +CLR_UINT32 CLR_ReadTokenCompressed( CLR_PMETADATA& ip, CLR_OPCODE opcode ); + +#endif + +//--// + +HRESULT CLR_CompressTokenHelper( const CLR_TABLESENUM *tables, CLR_UINT16 cTables, CLR_UINT32& tk); + +inline HRESULT CLR_CompressStringToken( CLR_UINT32& tk) +{ + static const CLR_TABLESENUM c_lookup[ 1 ] = { TBL_Strings }; + + return CLR_CompressTokenHelper( c_lookup, ARRAYSIZE(c_lookup), tk ); +} + +inline HRESULT CLR_CompressTypeToken( CLR_UINT32& tk ) +{ + static const CLR_TABLESENUM c_lookup[ 3 ] = { TBL_TypeDef, TBL_TypeRef, TBL_TypeSpec }; + + return CLR_CompressTokenHelper( c_lookup, ARRAYSIZE(c_lookup), tk ); +} + +inline HRESULT CLR_CompressFieldToken( CLR_UINT32& tk ) +{ + static const CLR_TABLESENUM c_lookup[ 2 ] = { TBL_FieldDef, TBL_FieldRef }; + + return CLR_CompressTokenHelper( c_lookup, ARRAYSIZE(c_lookup), tk ); +} + +inline HRESULT CLR_CompressMethodToken( CLR_UINT32& tk ) +{ + static const CLR_TABLESENUM c_lookup[ 2 ] = { TBL_MethodDef, TBL_MethodRef }; + + return CLR_CompressTokenHelper( c_lookup, ARRAYSIZE(c_lookup), tk ); +} + +//--// + +inline bool CLR_CompressData( CLR_UINT32 val, CLR_UINT8*& p ) +{ + CLR_UINT8* ptr = p; + + if(val <= 0x7F) + { + *ptr++ = (CLR_UINT8)(val); + } + else if(val <= 0x3FFF) + { + *ptr++ = (CLR_UINT8)((val >> 8) | 0x80); + *ptr++ = (CLR_UINT8)((val ) ); + } + else if(val <= 0x1FFFFFFF) + { + *ptr++ = (CLR_UINT8)((val >> 24) | 0xC0); + *ptr++ = (CLR_UINT8)((val >> 16) ); + *ptr++ = (CLR_UINT8)((val >> 8) ); + *ptr++ = (CLR_UINT8)((val ) ); + } + else + { + return false; + } + + p = ptr; + + return true; +} + +inline CLR_UINT32 CLR_UncompressData( const CLR_UINT8*& p ) +{ + CLR_PMETADATA ptr = p; + CLR_UINT32 val = *ptr++; + // Handle smallest data inline. + if((val & 0x80) == 0x00) // 0??? ???? + { + } + else if((val & 0xC0) == 0x80) // 10?? ???? + { + val = (val & 0x3F) << 8; + val |= (CLR_UINT32)*ptr++ ; + } + else // 110? ???? + { + val = (val & 0x1F) << 24; + val |= (CLR_UINT32)*ptr++ << 16; + val |= (CLR_UINT32)*ptr++ << 8; + val |= (CLR_UINT32)*ptr++ << 0; + } +#if 0 + // Handle smallest data inline. + if((val & 0x80) == 0x00) // 0??? ???? + { + } + else if((val & 0xC0) == 0x80) // 10?? ???? + { + val = (val & 0x3F); + val |= ((CLR_UINT32)*ptr++ <<8); + } + else // 110? ???? + { + val = (val & 0x1F) ; + val |= (CLR_UINT32)*ptr++ << 8; + val |= (CLR_UINT32)*ptr++ << 16; + val |= (CLR_UINT32)*ptr++ << 24; + } + +#endif + + p = ptr; + + return val; +} + +inline CLR_DataType CLR_UncompressElementType( const CLR_UINT8*& p ) +{ + return (CLR_DataType)*p++; +} + +inline CLR_UINT32 CLR_TkFromStream( const CLR_UINT8*& p ) +{ + static const CLR_TABLESENUM c_lookup[ 4 ] = { TBL_TypeDef, TBL_TypeRef, TBL_TypeSpec, TBL_Max }; + + CLR_UINT32 data = CLR_UncompressData( p ); + + return CLR_TkFromType( c_lookup[ data & 3 ], data >> 2 ); +} + +//--//--//--// + +#if defined(PLATFORM_BLACKFIN) || defined(__GNUC__) || defined(__RENESAS__) + +#define TINYCLR_READ_UNALIGNED_UINT8(arg,ip) arg = *(const CLR_UINT8 *)ip; ip += sizeof(CLR_UINT8 ) +template __inline void TINYCLR_READ_UNALIGNED_UINT16(T& arg, CLR_PMETADATA& ip) +{ + arg = (CLR_UINT16)(*(const CLR_UINT8 *)ip) ; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT16)(*(const CLR_UINT8 *)ip) << 8; ip += sizeof(CLR_UINT8); +} +template __inline void TINYCLR_READ_UNALIGNED_UINT32(T& arg, CLR_PMETADATA& ip) +{ + arg = (CLR_UINT32)(*(const CLR_UINT8 *)ip) ; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT32)(*(const CLR_UINT8 *)ip) << 8; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT32)(*(const CLR_UINT8 *)ip) << 16; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT32)(*(const CLR_UINT8 *)ip) << 24; ip += sizeof(CLR_UINT8); +} +template __inline void TINYCLR_READ_UNALIGNED_UINT64(T& arg, CLR_PMETADATA& ip) +{ + arg = (CLR_UINT64)(*(const CLR_UINT8 *)ip) ; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT64)(*(const CLR_UINT8 *)ip) << 8; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT64)(*(const CLR_UINT8 *)ip) << 16; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT64)(*(const CLR_UINT8 *)ip) << 24; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT64)(*(const CLR_UINT8 *)ip) << 32; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT64)(*(const CLR_UINT8 *)ip) << 40; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT64)(*(const CLR_UINT8 *)ip) << 48; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT64)(*(const CLR_UINT8 *)ip) << 56; ip += sizeof(CLR_UINT8); +} + +#define TINYCLR_READ_UNALIGNED_INT8(arg,ip) arg = *(const CLR_INT8 * )ip; ip += sizeof(CLR_INT8 ) +template __inline void TINYCLR_READ_UNALIGNED_INT16(T& arg, CLR_PMETADATA& ip) +{ + arg = (CLR_UINT16)(*(const CLR_UINT8 *)ip) ; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT16)(*(const CLR_UINT8 *)ip) << 8; ip += sizeof(CLR_UINT8); + arg = (CLR_INT16)arg; +} +template __inline void TINYCLR_READ_UNALIGNED_INT32(T& arg, CLR_PMETADATA& ip) +{ + arg = (CLR_UINT32)(*(const CLR_UINT8 *)ip) ; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT32)(*(const CLR_UINT8 *)ip) << 8; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT32)(*(const CLR_UINT8 *)ip) << 16; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT32)(*(const CLR_UINT8 *)ip) << 24; ip += sizeof(CLR_UINT8); + arg = (CLR_INT32)arg; +} +template __inline void TINYCLR_READ_UNALIGNED_INT64(T& arg, CLR_PMETADATA& ip) +{ + arg = (CLR_UINT64)(*(const CLR_UINT8 *)ip) ; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT64)(*(const CLR_UINT8 *)ip) << 8; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT64)(*(const CLR_UINT8 *)ip) << 16; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT64)(*(const CLR_UINT8 *)ip) << 24; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT64)(*(const CLR_UINT8 *)ip) << 32; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT64)(*(const CLR_UINT8 *)ip) << 40; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT64)(*(const CLR_UINT8 *)ip) << 48; ip += sizeof(CLR_UINT8); + arg |= (CLR_UINT64)(*(const CLR_UINT8 *)ip) << 56; ip += sizeof(CLR_UINT8); + arg = (CLR_INT64)arg; +} + + +#elif defined(_MSC_VER) + +#define TINYCLR_READ_UNALIGNED_UINT8(arg,ip) arg = *(__declspec(align(1)) const CLR_UINT8 *)ip; ip += sizeof(CLR_UINT8 ) +#define TINYCLR_READ_UNALIGNED_UINT16(arg,ip) arg = *(__declspec(align(1)) const CLR_UINT16*)ip; ip += sizeof(CLR_UINT16) +#define TINYCLR_READ_UNALIGNED_UINT32(arg,ip) arg = *(__declspec(align(1)) const CLR_UINT32*)ip; ip += sizeof(CLR_UINT32) +#define TINYCLR_READ_UNALIGNED_UINT64(arg,ip) arg = *(__declspec(align(1)) const CLR_UINT64*)ip; ip += sizeof(CLR_UINT64) + +#define TINYCLR_READ_UNALIGNED_INT8(arg,ip) arg = *(__declspec(align(1)) const CLR_INT8 * )ip; ip += sizeof(CLR_INT8 ) +#define TINYCLR_READ_UNALIGNED_INT16(arg,ip) arg = *(__declspec(align(1)) const CLR_INT16* )ip; ip += sizeof(CLR_INT16 ) +#define TINYCLR_READ_UNALIGNED_INT32(arg,ip) arg = *(__declspec(align(1)) const CLR_INT32* )ip; ip += sizeof(CLR_INT32 ) +#define TINYCLR_READ_UNALIGNED_INT64(arg,ip) arg = *(__declspec(align(1)) const CLR_INT64* )ip; ip += sizeof(CLR_INT64 ) + +//--// + +#define TINYCLR_WRITE_UNALIGNED_UINT8(ip,arg) *(__declspec(align(1)) CLR_UINT8 *)ip = arg; ip += sizeof(CLR_UINT8 ) +#define TINYCLR_WRITE_UNALIGNED_UINT16(ip,arg) *(__declspec(align(1)) CLR_UINT16*)ip = arg; ip += sizeof(CLR_UINT16) +#define TINYCLR_WRITE_UNALIGNED_UINT32(ip,arg) *(__declspec(align(1)) CLR_UINT32*)ip = arg; ip += sizeof(CLR_UINT32) +#define TINYCLR_WRITE_UNALIGNED_UINT64(ip,arg) *(__declspec(align(1)) CLR_UINT64*)ip = arg; ip += sizeof(CLR_UINT64) + +#define TINYCLR_WRITE_UNALIGNED_INT8(ip,arg) *(__declspec(align(1)) CLR_INT8 * )ip = arg; ip += sizeof(CLR_INT8 ) +#define TINYCLR_WRITE_UNALIGNED_INT16(ip,arg) *(__declspec(align(1)) CLR_INT16* )ip = arg; ip += sizeof(CLR_INT16 ) +#define TINYCLR_WRITE_UNALIGNED_INT32(ip,arg) *(__declspec(align(1)) CLR_INT32* )ip = arg; ip += sizeof(CLR_INT32 ) +#define TINYCLR_WRITE_UNALIGNED_INT64(ip,arg) *(__declspec(align(1)) CLR_INT64* )ip = arg; ip += sizeof(CLR_INT64 ) + +#else // TODO: __packed is compiler specific... Which compiler is this for? + +#define TINYCLR_READ_UNALIGNED_UINT8(arg,ip) arg = *(__packed CLR_UINT8 *)ip; ip += sizeof(CLR_UINT8 ) +#define TINYCLR_READ_UNALIGNED_UINT16(arg,ip) arg = *(__packed CLR_UINT16*)ip; ip += sizeof(CLR_UINT16) +#define TINYCLR_READ_UNALIGNED_UINT32(arg,ip) arg = *(__packed CLR_UINT32*)ip; ip += sizeof(CLR_UINT32) +#define TINYCLR_READ_UNALIGNED_UINT64(arg,ip) arg = *(__packed CLR_UINT64*)ip; ip += sizeof(CLR_UINT64) +#define TINYCLR_READ_UNALIGNED_INT8(arg,ip) arg = *(__packed CLR_INT8 * )ip; ip += sizeof(CLR_INT8 ) +#define TINYCLR_READ_UNALIGNED_INT16(arg,ip) arg = *(__packed CLR_INT16* )ip; ip += sizeof(CLR_INT16 ) +#define TINYCLR_READ_UNALIGNED_INT32(arg,ip) arg = *(__packed CLR_INT32* )ip; ip += sizeof(CLR_INT32 ) +#define TINYCLR_READ_UNALIGNED_INT64(arg,ip) arg = *(__packed CLR_INT64* )ip; ip += sizeof(CLR_INT64 ) + +//--// + +#define TINYCLR_WRITE_UNALIGNED_UINT8(ip,arg) *(__packed CLR_UINT8 *)ip = arg; ip += sizeof(CLR_UINT8 ) +#define TINYCLR_WRITE_UNALIGNED_UINT16(ip,arg) *(__packed CLR_UINT16*)ip = arg; ip += sizeof(CLR_UINT16) +#define TINYCLR_WRITE_UNALIGNED_UINT32(ip,arg) *(__packed CLR_UINT32*)ip = arg; ip += sizeof(CLR_UINT32) +#define TINYCLR_WRITE_UNALIGNED_UINT64(ip,arg) *(__packed CLR_UINT64*)ip = arg; ip += sizeof(CLR_UINT64) + +#define TINYCLR_WRITE_UNALIGNED_INT8(ip,arg) *(__packed CLR_INT8 * )ip = arg; ip += sizeof(CLR_INT8 ) +#define TINYCLR_WRITE_UNALIGNED_INT16(ip,arg) *(__packed CLR_INT16* )ip = arg; ip += sizeof(CLR_INT16 ) +#define TINYCLR_WRITE_UNALIGNED_INT32(ip,arg) *(__packed CLR_INT32* )ip = arg; ip += sizeof(CLR_INT32 ) +#define TINYCLR_WRITE_UNALIGNED_INT64(ip,arg) *(__packed CLR_INT64* )ip = arg; ip += sizeof(CLR_INT64 ) + +#endif + +//--// +#define TINYCLR_READ_UNALIGNED_OPCODE(op,ip) op = CLR_OPCODE(*ip++); if(op == CEE_PREFIX1) { opcode = CLR_OPCODE(*ip++ + 256); } + +#define TINYCLR_READ_UNALIGNED_COMPRESSED_FIELDTOKEN(arg,ip) TINYCLR_READ_UNALIGNED_UINT16( arg, ip ); arg = CLR_UncompressFieldToken ( arg ) +#define TINYCLR_READ_UNALIGNED_COMPRESSED_METHODTOKEN(arg,ip) TINYCLR_READ_UNALIGNED_UINT16( arg, ip ); arg = CLR_UncompressMethodToken( arg ) +#define TINYCLR_READ_UNALIGNED_COMPRESSED_TYPETOKEN(arg,ip) TINYCLR_READ_UNALIGNED_UINT16( arg, ip ); arg = CLR_UncompressTypeToken ( arg ) +#define TINYCLR_READ_UNALIGNED_COMPRESSED_STRINGTOKEN(arg,ip) TINYCLR_READ_UNALIGNED_UINT16( arg, ip ); arg = CLR_UncompressStringToken( arg ) + + +//--// + +inline CLR_OPCODE CLR_ReadNextOpcode( CLR_PMETADATA& ip ) +{ + CLR_PMETADATA ptr = ip; + CLR_OPCODE opcode = CLR_OPCODE(*ptr++); + + if(opcode == CEE_PREFIX1) + { + opcode = CLR_OPCODE(*ptr++ + 256); + } + + ip = ptr; + + return opcode; +} + +inline CLR_OPCODE CLR_ReadNextOpcodeCompressed( CLR_PMETADATA& ip ) +{ + CLR_PMETADATA ptr = ip; + CLR_OPCODE opcode = CLR_OPCODE(*ptr++); + + if(opcode == CEE_PREFIX1) + { + opcode = CLR_OPCODE(*ptr++ + 256); + } + + ip = ptr; + + return opcode; +} + +//--// + +#define FETCH_ARG_UINT8(arg,ip) CLR_UINT32 arg; TINYCLR_READ_UNALIGNED_UINT8 ( arg, ip ) +#define FETCH_ARG_UINT16(arg,ip) CLR_UINT32 arg; TINYCLR_READ_UNALIGNED_UINT16( arg, ip ) +#define FETCH_ARG_UINT32(arg,ip) CLR_UINT32 arg; TINYCLR_READ_UNALIGNED_UINT32( arg, ip ) +#define FETCH_ARG_UINT64(arg,ip) CLR_UINT64 arg; TINYCLR_READ_UNALIGNED_UINT64( arg, ip ) + +#define FETCH_ARG_INT8(arg,ip) CLR_INT32 arg; TINYCLR_READ_UNALIGNED_INT8 ( arg, ip ) +#define FETCH_ARG_INT16(arg,ip) CLR_INT32 arg; TINYCLR_READ_UNALIGNED_INT16( arg, ip ) +#define FETCH_ARG_INT32(arg,ip) CLR_INT32 arg; TINYCLR_READ_UNALIGNED_INT32( arg, ip ) +#define FETCH_ARG_INT64(arg,ip) CLR_INT64 arg; TINYCLR_READ_UNALIGNED_INT64( arg, ip ) + +#define FETCH_ARG_COMPRESSED_STRINGTOKEN(arg,ip) CLR_UINT32 arg; TINYCLR_READ_UNALIGNED_COMPRESSED_STRINGTOKEN( arg, ip ) +#define FETCH_ARG_COMPRESSED_FIELDTOKEN(arg,ip) CLR_UINT32 arg; TINYCLR_READ_UNALIGNED_COMPRESSED_FIELDTOKEN ( arg, ip ) +#define FETCH_ARG_COMPRESSED_TYPETOKEN(arg,ip) CLR_UINT32 arg; TINYCLR_READ_UNALIGNED_COMPRESSED_TYPETOKEN ( arg, ip ) +#define FETCH_ARG_COMPRESSED_METHODTOKEN(arg,ip) CLR_UINT32 arg; TINYCLR_READ_UNALIGNED_COMPRESSED_METHODTOKEN( arg, ip ) +#define FETCH_ARG_TOKEN(arg,ip) CLR_UINT32 arg; TINYCLR_READ_UNALIGNED_UINT32 ( arg, ip ) + +//--// + +#if defined(_WIN32) + +CLR_PMETADATA CLR_SkipBodyOfOpcode ( CLR_PMETADATA ip, CLR_OPCODE opcode ); +CLR_PMETADATA CLR_SkipBodyOfOpcodeCompressed( CLR_PMETADATA ip, CLR_OPCODE opcode ); + +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +extern bool CLR_SafeSprintfV( LPSTR& szBuffer, size_t& iBuffer, LPCSTR format, va_list arg ); +extern bool CLR_SafeSprintf ( LPSTR& szBuffer, size_t& iBuffer, LPCSTR format, ... ); + +#if !defined(BUILD_RTM) + +#define TINYCLR_DEBUG_STOP() _ASSERTE(FALSE) + +#else + +#define TINYCLR_DEBUG_STOP() CPU_Reset() + +#endif + +//--// + +struct CLR_Debug +{ + static int PrintfV( const char *format, va_list arg ); + static int Printf ( const char *format, ... ); + static void Emit ( const char *text, int len ); + static void Flush ( ); + + //--// + + typedef int (*OutputHandler)( const char *format, ... ); + +#if defined(_WIN32) + static void RedirectToString( std::string* str ); +#endif +}; + +//////////////////////////////////////////////////////////////////////////////// + +struct CLR_RECORD_VERSION +{ + CLR_UINT16 iMajorVersion; + CLR_UINT16 iMinorVersion; + CLR_UINT16 iBuildNumber; + CLR_UINT16 iRevisionNumber; +}; + +struct CLR_RECORD_ASSEMBLY +{ + static const CLR_UINT32 c_Flags_NeedReboot = 0x00000001; + static const CLR_UINT32 c_Flags_Patch = 0x00000002; + static const CLR_UINT32 c_Flags_BigEndian = 0x80000080; + + CLR_UINT8 marker[ 8 ]; + // + CLR_UINT32 headerCRC; + CLR_UINT32 assemblyCRC; + CLR_UINT32 flags; + // + CLR_UINT32 nativeMethodsChecksum; + CLR_UINT32 patchEntryOffset; + // + CLR_RECORD_VERSION version; + // + CLR_STRING assemblyName; // TBL_Strings + CLR_UINT16 stringTableVersion; + // + CLR_OFFSET_LONG startOfTables[ TBL_Max ]; + CLR_UINT32 numOfPatchedMethods; + // + //For every table, a number of bytes that were padded to the end of the table + //to align to DWORD. Each table starts at a DWORD boundary, and ends + //at a DWORD boundary. Some of these tables will, by construction, have + //no padding, and all will have values in the range [0-3]. This isn't the most + //compact form to hold this information, but it only costs 16 bytes/assembly. + //Trying to only align some of the tables is just much more hassle than it's worth. + //And, of course, this field also has to be DWORD-aligned. + CLR_UINT8 paddingOfTables[ ((TBL_Max-1)+3)/4*4 ]; + //--// + + bool GoodHeader () const; + bool GoodAssembly() const; + +#if defined(_WIN32) + void ComputeCRC(); +#endif + + CLR_OFFSET_LONG SizeOfTable( CLR_TABLESENUM tbl ) const { return startOfTables[ tbl+1 ] - startOfTables[ tbl ] - paddingOfTables[ tbl ]; } + + CLR_OFFSET_LONG TotalSize() const { return startOfTables[ TBL_EndOfAssembly ]; } + + //--// + + static CLR_UINT32 ComputeAssemblyHash( LPCSTR name, const CLR_RECORD_VERSION& ver ); +}; + +struct CLR_RECORD_ASSEMBLYREF +{ + CLR_STRING name; // TBL_Strings + CLR_UINT16 pad; + // + CLR_RECORD_VERSION version; +}; + +struct CLR_RECORD_TYPEREF +{ + CLR_STRING name; // TBL_Strings + CLR_STRING nameSpace; // TBL_Strings + // + CLR_IDX scope; // TBL_AssemblyRef | TBL_TypeRef // 0x8000 + CLR_UINT16 pad; +}; + +struct CLR_RECORD_FIELDREF +{ + CLR_STRING name; // TBL_Strings + CLR_IDX container; // TBL_TypeRef + // + CLR_SIG sig; // TBL_Signatures + CLR_UINT16 pad; +}; + +struct CLR_RECORD_METHODREF +{ + CLR_STRING name; // TBL_Strings + CLR_IDX container; // TBL_TypeRef + // + CLR_SIG sig; // TBL_Signatures + CLR_UINT16 pad; +}; + +struct CLR_RECORD_TYPEDEF +{ + static const CLR_UINT16 TD_Scope_Mask = 0x0007; + static const CLR_UINT16 TD_Scope_NotPublic = 0x0000; // Class is not public scope. + static const CLR_UINT16 TD_Scope_Public = 0x0001; // Class is public scope. + static const CLR_UINT16 TD_Scope_NestedPublic = 0x0002; // Class is nested with public visibility. + static const CLR_UINT16 TD_Scope_NestedPrivate = 0x0003; // Class is nested with private visibility. + static const CLR_UINT16 TD_Scope_NestedFamily = 0x0004; // Class is nested with family visibility. + static const CLR_UINT16 TD_Scope_NestedAssembly = 0x0005; // Class is nested with assembly visibility. + static const CLR_UINT16 TD_Scope_NestedFamANDAssem = 0x0006; // Class is nested with family and assembly visibility. + static const CLR_UINT16 TD_Scope_NestedFamORAssem = 0x0007; // Class is nested with family or assembly visibility. + + static const CLR_UINT16 TD_Serializable = 0x0008; + + static const CLR_UINT16 TD_Semantics_Mask = 0x0030; + static const CLR_UINT16 TD_Semantics_Class = 0x0000; + static const CLR_UINT16 TD_Semantics_ValueType = 0x0010; + static const CLR_UINT16 TD_Semantics_Interface = 0x0020; + static const CLR_UINT16 TD_Semantics_Enum = 0x0030; + + static const CLR_UINT16 TD_Abstract = 0x0040; + static const CLR_UINT16 TD_Sealed = 0x0080; + + static const CLR_UINT16 TD_SpecialName = 0x0100; + static const CLR_UINT16 TD_Delegate = 0x0200; + static const CLR_UINT16 TD_MulticastDelegate = 0x0400; + + static const CLR_UINT16 TD_Patched = 0x0800; + + static const CLR_UINT16 TD_BeforeFieldInit = 0x1000; + static const CLR_UINT16 TD_HasSecurity = 0x2000; + static const CLR_UINT16 TD_HasFinalizer = 0x4000; + static const CLR_UINT16 TD_HasAttributes = 0x8000; + + + CLR_STRING name; // TBL_Strings + CLR_STRING nameSpace; // TBL_Strings + // + CLR_IDX extends; // TBL_TypeDef | TBL_TypeRef // 0x8000 + CLR_IDX enclosingType; // TBL_TypeDef + // + CLR_SIG interfaces; // TBL_Signatures + CLR_IDX methods_First; // TBL_MethodDef + // + CLR_UINT8 vMethods_Num; + CLR_UINT8 iMethods_Num; + CLR_UINT8 sMethods_Num; + CLR_UINT8 dataType; + // + CLR_IDX sFields_First; // TBL_FieldDef + CLR_IDX iFields_First; // TBL_FieldDef + // + CLR_UINT8 sFields_Num; + CLR_UINT8 iFields_Num; + CLR_UINT16 flags; + + //--// + + bool IsEnum () const { return (flags & (TD_Semantics_Mask )) == TD_Semantics_Enum; } + bool IsDelegate() const { return (flags & (TD_Delegate | TD_MulticastDelegate)) != 0 ; } +}; + +struct CLR_RECORD_FIELDDEF +{ + static const CLR_UINT16 FD_Scope_Mask = 0x0007; + static const CLR_UINT16 FD_Scope_PrivateScope = 0x0000; // Member not referenceable. + static const CLR_UINT16 FD_Scope_Private = 0x0001; // Accessible only by the parent type. + static const CLR_UINT16 FD_Scope_FamANDAssem = 0x0002; // Accessible by sub-types only in this Assembly. + static const CLR_UINT16 FD_Scope_Assembly = 0x0003; // Accessibly by anyone in the Assembly. + static const CLR_UINT16 FD_Scope_Family = 0x0004; // Accessible only by type and sub-types. + static const CLR_UINT16 FD_Scope_FamORAssem = 0x0005; // Accessibly by sub-types anywhere, plus anyone in assembly. + static const CLR_UINT16 FD_Scope_Public = 0x0006; // Accessibly by anyone who has visibility to this scope. + + static const CLR_UINT16 FD_NotSerialized = 0x0008; // Field does not have to be serialized when type is remoted. + + static const CLR_UINT16 FD_Static = 0x0010; // Defined on type, else per instance. + static const CLR_UINT16 FD_InitOnly = 0x0020; // Field may only be initialized, not written to after init. + static const CLR_UINT16 FD_Literal = 0x0040; // Value is compile time constant. + + static const CLR_UINT16 FD_SpecialName = 0x0100; // field is special. Name describes how. + static const CLR_UINT16 FD_HasDefault = 0x0200; // Field has default. + static const CLR_UINT16 FD_HasFieldRVA = 0x0400; // Field has RVA. + + static const CLR_UINT16 FD_NoReflection = 0x0800; // field does not allow reflection + + static const CLR_UINT16 FD_HasAttributes = 0x8000; + + + CLR_STRING name; // TBL_Strings + CLR_SIG sig; // TBL_Signatures + // + CLR_SIG defaultValue; // TBL_Signatures + CLR_UINT16 flags; +}; + +struct CLR_RECORD_METHODDEF +{ + static const CLR_UINT32 MD_Scope_Mask = 0x00000007; + static const CLR_UINT32 MD_Scope_PrivateScope = 0x00000000; // Member not referenceable. + static const CLR_UINT32 MD_Scope_Private = 0x00000001; // Accessible only by the parent type. + static const CLR_UINT32 MD_Scope_FamANDAssem = 0x00000002; // Accessible by sub-types only in this Assembly. + static const CLR_UINT32 MD_Scope_Assem = 0x00000003; // Accessibly by anyone in the Assembly. + static const CLR_UINT32 MD_Scope_Family = 0x00000004; // Accessible only by type and sub-types. + static const CLR_UINT32 MD_Scope_FamORAssem = 0x00000005; // Accessibly by sub-types anywhere, plus anyone in assembly. + static const CLR_UINT32 MD_Scope_Public = 0x00000006; // Accessibly by anyone who has visibility to this scope. + + static const CLR_UINT32 MD_Static = 0x00000010; // Defined on type, else per instance. + static const CLR_UINT32 MD_Final = 0x00000020; // Method may not be overridden. + static const CLR_UINT32 MD_Virtual = 0x00000040; // Method virtual. + static const CLR_UINT32 MD_HideBySig = 0x00000080; // Method hides by name+sig, else just by name. + + static const CLR_UINT32 MD_VtableLayoutMask = 0x00000100; + static const CLR_UINT32 MD_ReuseSlot = 0x00000000; // The default. + static const CLR_UINT32 MD_NewSlot = 0x00000100; // Method always gets a new slot in the vtable. + static const CLR_UINT32 MD_Abstract = 0x00000200; // Method does not provide an implementation. + static const CLR_UINT32 MD_SpecialName = 0x00000400; // Method is special. Name describes how. + static const CLR_UINT32 MD_NativeProfiled = 0x00000800; + + static const CLR_UINT32 MD_Constructor = 0x00001000; + static const CLR_UINT32 MD_StaticConstructor = 0x00002000; + static const CLR_UINT32 MD_Finalizer = 0x00004000; + + static const CLR_UINT32 MD_DelegateConstructor = 0x00010000; + static const CLR_UINT32 MD_DelegateInvoke = 0x00020000; + static const CLR_UINT32 MD_DelegateBeginInvoke = 0x00040000; + static const CLR_UINT32 MD_DelegateEndInvoke = 0x00080000; + + static const CLR_UINT32 MD_Synchronized = 0x01000000; + static const CLR_UINT32 MD_GloballySynchronized = 0x02000000; + static const CLR_UINT32 MD_Patched = 0x04000000; + static const CLR_UINT32 MD_EntryPoint = 0x08000000; + static const CLR_UINT32 MD_RequireSecObject = 0x10000000; // Method calls another method containing security code. + static const CLR_UINT32 MD_HasSecurity = 0x20000000; // Method has security associate with it. + static const CLR_UINT32 MD_HasExceptionHandlers = 0x40000000; + static const CLR_UINT32 MD_HasAttributes = 0x80000000; + + + CLR_STRING name; // TBL_Strings + CLR_OFFSET RVA; + // + CLR_UINT32 flags; + // + CLR_UINT8 retVal; + CLR_UINT8 numArgs; + CLR_UINT8 numLocals; + CLR_UINT8 lengthEvalStack; + // + CLR_SIG locals; // TBL_Signatures + CLR_SIG sig; // TBL_Signatures +}; + +struct CLR_RECORD_ATTRIBUTE +{ + CLR_UINT16 ownerType; // one of TBL_TypeDef, TBL_MethodDef, or TBL_FieldDef. + CLR_UINT16 ownerIdx; // TBL_TypeDef | TBL_MethodDef | TBL_FielfDef + CLR_UINT16 constructor; + CLR_SIG data; // TBL_Signatures + + CLR_UINT32 Key() const { return *(CLR_UINT32*)&ownerType; } +}; + +struct CLR_RECORD_TYPESPEC +{ + CLR_SIG sig; // TBL_Signatures + CLR_UINT16 pad; +}; + +struct CLR_RECORD_EH +{ + static const CLR_UINT16 EH_Catch = 0x0000; + static const CLR_UINT16 EH_CatchAll = 0x0001; + static const CLR_UINT16 EH_Finally = 0x0002; + static const CLR_UINT16 EH_Filter = 0x0003; + + //--// + + CLR_UINT16 mode; + union { + CLR_IDX classToken; // TBL_TypeDef | TBL_TypeRef + CLR_OFFSET filterStart; + }; + CLR_OFFSET tryStart; + CLR_OFFSET tryEnd; + CLR_OFFSET handlerStart; + CLR_OFFSET handlerEnd; + + //--// + + static CLR_PMETADATA ExtractEhFromByteCode( CLR_PMETADATA ipEnd, const CLR_RECORD_EH*& ptrEh, CLR_UINT32& numEh ); + + CLR_UINT32 GetToken() const; +}; + +CT_ASSERT_UNIQUE_NAME( sizeof(CLR_RECORD_EH) == 12, CLR_RECORD_EH ) + +struct CLR_RECORD_RESOURCE_FILE +{ + static const CLR_UINT32 CURRENT_VERSION = 2; + + CLR_UINT32 version; + CLR_UINT32 sizeOfHeader; + CLR_UINT32 sizeOfResourceHeader; + CLR_UINT32 numberOfResources; + CLR_STRING name; // TBL_Strings + CLR_UINT16 pad; + CLR_UINT32 offset; // TBL_Resource +}; + +struct CLR_RECORD_RESOURCE +{ + static const CLR_UINT8 RESOURCE_Invalid = 0x00; + static const CLR_UINT8 RESOURCE_Bitmap = 0x01; + static const CLR_UINT8 RESOURCE_Font = 0x02; + static const CLR_UINT8 RESOURCE_String = 0x03; + static const CLR_UINT8 RESOURCE_Binary = 0x04; + + static const CLR_UINT8 FLAGS_PaddingMask = 0x03; + static const CLR_INT16 SENTINEL_ID = 0x7FFF; + + // + // Sorted on id + // + CLR_INT16 id; + CLR_UINT8 kind; + CLR_UINT8 flags; + CLR_UINT32 offset; +}; + + +#if defined(_MSC_VER) +#pragma pack(pop, TINYCLR_TYPES_H) +#endif + +#if defined(GCCOP_V4_2) + +extern double fmod(double x, double y); +extern double floor (double x); + +extern void *bsearch(const void *key, const void *base, size_t num, size_t width, int (*compare)(const void *, const void *)) ; +#endif + +#endif // _TINYCLR_TYPES_H_ diff --git a/src/CLR/Include/TinyCLR_Win32.h b/src/CLR/Include/TinyCLR_Win32.h new file mode 100644 index 0000000000..ce486e3e08 --- /dev/null +++ b/src/CLR/Include/TinyCLR_Win32.h @@ -0,0 +1,41 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _TINYCLR_WIN32_H_ +#define _TINYCLR_WIN32_H_ + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void HAL_Windows_FastSleep( INT64 ticks ); + +BOOL HAL_Windows_IsShutdownPending(); + +void HAL_Windows_AcquireGlobalLock(); +void HAL_Windows_ReleaseGlobalLock(); +BOOL HAL_Windows_HasGlobalLock(); + +UINT64 HAL_Windows_GetPerformanceTicks(); + +void HAL_Windows_Debug_Print( LPSTR szText ); + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +class HAL_Mutex +{ + CRITICAL_SECTION m_data; + +public: + HAL_Mutex(); + ~HAL_Mutex(); + + //--// + + void Lock (); + void Unlock(); +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#endif // _TINYCLR_WIN32_H_ \ No newline at end of file diff --git a/src/CLR/Include/TinyHAL.h b/src/CLR/Include/TinyHAL.h new file mode 100644 index 0000000000..ccbb11bbad --- /dev/null +++ b/src/CLR/Include/TinyHAL.h @@ -0,0 +1,1627 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _TINYHAL_H_ +#define _TINYHAL_H_ 1 + +#include +#include +#include + + + + + + + + + + + + + + + + + + + + + + + +#include +#include + +//#if !defined(_WIN32) && !defined(FIQ_SAMPLING_PROFILER) && !defined(HAL_REDUCESIZE) && defined(PROFILE_BUILD) +//#define ENABLE_NATIVE_PROFILER +//#endif + +//#include "..\pal\Diagnostics\Native_Profiler.h" + +#define NATIVE_PROFILE_CLR_DEBUGGER() +#define NATIVE_PROFILE_CLR_UTF8_DECODER() +#define NATIVE_PROFILE_CLR_CORE() +#define NATIVE_PROFILE_CLR_MESSAGING() +#define NATIVE_PROFILE_CLR_SERIALIZATION() +#define NATIVE_PROFILE_CLR_NETWORK() +#define NATIVE_PROFILE_CLR_I2C() +#define NATIVE_PROFILE_CLR_DIAGNOSTICS() +#define NATIVE_PROFILE_CLR_HARDWARE() +#define NATIVE_PROFILE_CLR_GRAPHICS() +#define NATIVE_PROFILE_CLR_STARTUP() +#define NATIVE_PROFILE_CLR_HEAP_PERSISTENCE() +#define NATIVE_PROFILE_CLR_IOPORT() +#define NATIVE_PROFILE_CLR_IO() + + +#if defined(_MSC_VER) + +#define ADS_PACKED +#define GNU_PACKED + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +#else +!ERROR +#endif + +//--// + + + + + + + + + + + + + + + + +//--// + +typedef UINT32 GPIO_PIN; + +//--// + +struct GPIO_FLAG +{ + GPIO_PIN Pin; + BOOL ActiveState; +}; + +//--// + + + + + + + + +// COM_HANDLE Defines a type representing both a port type or "transport" and a port number +// The COM_HANDLE is a multi bit field value with the following bit fields usage +// |--------+--------+--------+--------| +// |33222222|22221111|111111 | | +// |10987654|32109876|54321098|76543210| bit position +// |--------+--------+--------+--------| +// |00000000|00000000|TTTTTTTT|pppppppp| ( transport != USB_TRANSPORT ) +// |--------+--------+--------+--------| +// |00000000|00000000|TTTTTTTT|cccppppp| ( transport == USB_TRANSPORT ) +// |--------+--------+--------+--------| +// +// where: +// T => Transport type +// USART_TRANSPORT => 1 +// USB_TRANSPORT => 2 +// SOCKET_TRANSPORT => 3 +// DEBUG_TRANSPORT => 4 +// LCD_TRANSPORT => 5 +// FLASH_WRITE_TRANSPORT => 6 +// MESSAGING_TRANSPORT => 7 +// GENERIC_TRANSPORT => 8 +// p => port instance number +// Port instances in the handle are 1 based. (e.g. p == 0 is invalid except when T == 0 ) +// c -> Controller instance number ( USB_TRANSPORT only ) +// +// NULL_PORT => T==0 && p == 0 +// +// GENERIC_TRANSPORT is any custom port that isn't one of the above, they +// are implemented for the DebugPort_xxxx APIs and the port number is +// an index into a const global table of port interfaces (structure of +// function pointers) These allow custom extensions to the normal transports +// without needing to continue defining additional transport types and modifying +// switch on transport code. To keep compatibility high and code churn low, the +// previous legacy transports remain though they should be considered deprecated. +typedef INT32 COM_HANDLE; + +#define TRANSPORT_SHIFT 8 +#define TRANSPORT_MASK (0xFF << TRANSPORT_SHIFT) +#define PORT_NUMBER_MASK 0x00FF + +// Macro to extract the transport type from a COM_HANDLE +#define ExtractTransport(x) ((UINT32)(x) & TRANSPORT_MASK) + +// Macro to extract well-known system event flag ids from a COM_HANDLE +#define ExtractEventFromTransport(x) (ExtractTransport(x) == USART_TRANSPORT ? SYSTEM_EVENT_FLAG_COM_IN: \ + ExtractTransport(x) == USB_TRANSPORT ? SYSTEM_EVENT_FLAG_USB_IN: \ + ExtractTransport(x) == SOCKET_TRANSPORT ? SYSTEM_EVENT_FLAG_SOCKET: \ + ExtractTransport(x) == GENERIC_TRANSPORT ? SYSTEM_EVENT_FLAG_GENERIC_PORT: \ + ExtractTransport(x) == DEBUG_TRANSPORT ? SYSTEM_EVENT_FLAG_DEBUGGER_ACTIVITY: \ + ExtractTransport(x) == MESSAGING_TRANSPORT ? SYSTEM_EVENT_FLAG_MESSAGING_ACTIVITY: \ + 0) \ + +#define USART_TRANSPORT (1 << TRANSPORT_SHIFT) +//#define COM_NULL ((COM_HANDLE)(USART_TRANSPORT)) + +#define USB_TRANSPORT (2 << TRANSPORT_SHIFT) +//#define USB_CONTROLLER_SHIFT 5 +//#define USB_CONTROLLER_MASK 0xE0 +//#define USB_STREAM_MASK 0x00FF +//#define USB_STREAM_INDEX_MASK 0x001F + +#define SOCKET_TRANSPORT (3 << TRANSPORT_SHIFT) +#define COM_SOCKET_DBG ((COM_HANDLE)(SOCKET_TRANSPORT + 1)) + +#define DEBUG_TRANSPORT (4 << TRANSPORT_SHIFT) + + + + + + + +#define MESSAGING_TRANSPORT (7 << TRANSPORT_SHIFT) + +#define GENERIC_TRANSPORT (8 << TRANSPORT_SHIFT) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// Creates a COM_HANDLE value for a platform specific port number +#define ConvertCOM_DebugHandle(x) ((COM_HANDLE)((x) + DEBUG_TRANSPORT + 1)) + + + + + + + +typedef UINT32 FLASH_WORD; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +struct HAL_DRIVER_CONFIG_HEADER +{ + UINT32 Enable; +}; + +struct HAL_SYSTEM_MEMORY_CONFIG +{ + UINT32 Base; + UINT32 Size; +}; + +struct HAL_SYSTEM_CONFIG +{ + static const UINT32 c_MaxDebuggers = 1; + static const UINT32 c_MaxMessaging = 1; + + HAL_DRIVER_CONFIG_HEADER Header; + + //--// + + COM_HANDLE DebuggerPorts[c_MaxDebuggers]; + COM_HANDLE MessagingPorts[c_MaxMessaging]; + // communication channel for debug messages in the debugger + // which may be VS, MFDEPLOY, etc... Accessed via debug_printf + // in the HAL/PAL and System.Diagnostics.Debug.Print() in managed + // applications + COM_HANDLE DebugTextPort; + + UINT32 USART_DefaultBaudRate; + // internal HAL/PAL debug/tracing channel, this is separate + // to allow tracing messages in the driver that implements + // the transport for the Debugger and DebugTextPort. This + // channel is accessed via hal_printf() in the HAL/PAL + COM_HANDLE stdio; + + HAL_SYSTEM_MEMORY_CONFIG RAM1; + HAL_SYSTEM_MEMORY_CONFIG FLASH; + + //--// + + static LPCSTR GetDriverName() { return "HAL_SYSTEM"; } +}; + + +extern HAL_SYSTEM_CONFIG HalSystemConfig; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +//--// +// Function macros + +void HAL_Assert ( LPCSTR Func, int Line, LPCSTR File ); +// HAL_AssertEx is defined in the processor or platform selector files. +extern void HAL_AssertEx(); + +#if defined(PLATFORM_ARM) + #if !defined(BUILD_RTM) + #define ASSERT(i) { if(!(i)) HAL_AssertEx(); } + #define _SIDE_ASSERTE(i) { if(!(i)) HAL_AssertEx(); } + #endif +#else + #if defined(_DEBUG) && !defined(_WIN32_WCE) && !defined(__RENESAS__) +#if !defined _ASSERTE +#error +#endif + #define ASSERT(i) _ASSERTE(i) + #define _SIDE_ASSERTE(i) _ASSERTE(i) + #endif +#endif + +#ifndef ASSERT +#define ASSERT(i) +#endif + +#ifndef _ASSERTE +#define _ASSERTE(expr) ASSERT(expr) +#endif + +#ifndef _SIDE_ASSERTE +#define _SIDE_ASSERTE(expr) (expr) +#endif + +#if STATIC_ASSERT_SUPPORTED +#define CT_ASSERT_STRING( x ) #x +#define CT_ASSERT_UNIQUE_NAME(e,name)static_assert( (e), CT_ASSERT_STRING( name ) "@" __FILE__ CT_ASSERT_STRING(__LINE__) ); +#define CT_ASSERT(e) static_assert( (e), __FILE__ CT_ASSERT_STRING(__LINE__) ); +#else +// CT_ASSERT (compile-time assert) macro is used to test condition at compiler time and generate +// compiler error if condition is FALSE. +// Example: CT_ASSERT( sizeof( UINT32 ) == 2 ) would cause compilation error. +// CT_ASSERT( sizeof( UINT32 ) == 4 ) compiles without error. +// Since this declaration is just typedef - it does not create any CPU code. +// +// Reason for CT_ASSERT_UNIQUE_NAME +// The possible problem with the macro - it creates multiple identical typedefs. +// It is not a problem in global scope, but if macro is used inside of struct - it generates warnings. +// CT_ASSERT_UNIQUE_NAME is the same in essence, but it provides a way to customize the name of the type. +#define CT_ASSERT_UNIQUE_NAME(e,name) typedef char __CT_ASSERT__##name[(e)?1:-1]; +#define CT_ASSERT(e) CT_ASSERT_UNIQUE_NAME(e,tinyclr) +#endif + + + + + + + + + + + + + + + + + + +//--// + +//These events match emulator events in Framework\Tools\Emulator\Events.cs + +#define SYSTEM_EVENT_FLAG_COM_IN 0x00000001 +#define SYSTEM_EVENT_FLAG_COM_OUT 0x00000002 +#define SYSTEM_EVENT_FLAG_USB_IN 0x00000004 +//#define SYSTEM_EVENT_FLAG_USB_OUT 0x00000008 +#define SYSTEM_EVENT_FLAG_SYSTEM_TIMER 0x00000010 +//#define SYSTEM_EVENT_FLAG_TIMER1 0x00000020 +//#define SYSTEM_EVENT_FLAG_TIMER2 0x00000040 +//#define SYSTEM_EVENT_FLAG_BUTTON 0x00000080 +#define SYSTEM_EVENT_FLAG_GENERIC_PORT 0x00000100 +//#define SYSTEM_EVENT_FLAG_UNUSED_0x00000200 0x00000200 +//#define SYSTEM_EVENT_FLAG_UNUSED_0x00000400 0x00000400 +//#define SYSTEM_EVENT_FLAG_NETWORK 0x00000800 +//#define SYSTEM_EVENT_FLAG_TONE_COMPLETE 0x00001000 +//#define SYSTEM_EVENT_FLAG_TONE_BUFFER_EMPTY 0x00002000 +#define SYSTEM_EVENT_FLAG_SOCKET 0x00004000 +//#define SYSTEM_EVENT_FLAG_SPI 0x00008000 +//#define SYSTEM_EVENT_FLAG_CHARGER_CHANGE 0x00010000 +//#define SYSTEM_EVENT_FLAG_OEM_RESERVED_1 0x00020000 +//#define SYSTEM_EVENT_FLAG_OEM_RESERVED_2 0x00040000 +#define SYSTEM_EVENT_FLAG_IO 0x00080000 +//#define SYSTEM_EVENT_FLAG_UNUSED_0x00100000 0x00100000 + + + + + + + +//#define SYSTEM_EVENT_FLAG_UNUSED_0x00200000 0x00200000 +//#define SYSTEM_EVENT_FLAG_UNUSED_0x00400000 0x00400000 +//#define SYSTEM_EVENT_FLAG_UNUSED_0x00800000 0x00800000 +//#define SYSTEM_EVENT_FLAG_UNUSED_0x01000000 0x01000000 +//#define SYSTEM_EVENT_FLAG_UNUSED_0x02000000 0x02000000 +//#define SYSTEM_EVENT_FLAG_UNUSED_0x04000000 0x04000000 +#define SYSTEM_EVENT_HW_INTERRUPT 0x08000000 +//#define SYSTEM_EVENT_I2C_XACTION 0x10000000 +#define SYSTEM_EVENT_FLAG_DEBUGGER_ACTIVITY 0x20000000 +#define SYSTEM_EVENT_FLAG_MESSAGING_ACTIVITY 0x40000000 +//#define SYSTEM_EVENT_FLAG_UNUSED_0x80000000 0x80000000 +#define SYSTEM_EVENT_FLAG_ALL 0xFFFFFFFF + + + +//--// + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +template class HAL_DblLinkedList; + +template class HAL_DblLinkedNode +{ + T* m_nextNode; + T* m_prevNode; + + friend class HAL_DblLinkedList; + +public: + void Initialize() + { + m_nextNode = NULL; + m_prevNode = NULL; + } + + T* Next() const { return m_nextNode; } + T* Prev() const { return m_prevNode; } + + void SetNext( T* next ) { m_nextNode = next; } + void SetPrev( T* prev ) { m_prevNode = prev; } + + bool IsLinked() const { return m_nextNode != NULL; } + + //--// + + void RemoveFromList() + { + T* next = m_nextNode; + T* prev = m_prevNode; + + if(prev) prev->m_nextNode = next; + if(next) next->m_prevNode = prev; + } + + void Unlink() + { + T* next = m_nextNode; + T* prev = m_prevNode; + + if(prev) prev->m_nextNode = next; + if(next) next->m_prevNode = prev; + + m_nextNode = NULL; + m_prevNode = NULL; + } +}; + +//--// + +template class HAL_DblLinkedList +{ + // + // Logically, a list starts with a HAL_DblLinkedNode with only the Next() set and ends with a node with only Prev() set. + // This can be collapsed to have the two nodes overlap. + // + T* m_first; + T* m_null; + T* m_last; + + //--// + +public: + void Initialize() + { + m_first = Tail(); + m_null = NULL; + m_last = Head(); + } + + int NumOfNodes() + { + T* ptr; + T* ptrNext; + int num = 0; + + for(ptr = FirstNode(); (ptrNext = ptr->Next()) != NULL; ptr = ptrNext) + { + num++; + } + + return num; + } + + //--// + + T* FirstNode() const { return m_first ; } + T* LastNode () const { return m_last ; } + bool IsEmpty () const { return m_first == Tail(); } + + T* FirstValidNode() const { T* res = m_first; return res->Next() ? res : NULL; } + T* LastValidNode () const { T* res = m_last ; return res->Prev() ? res : NULL; } + + T* Head() const { return (T*)((size_t)&m_first - offsetof(T, m_nextNode)); } + T* Tail() const { return (T*)((size_t)&m_last - offsetof(T, m_prevNode)); } + + //--// + +private: + + void Insert( T* prev, T* next, T* node ) + { + node->m_nextNode = next; + node->m_prevNode = prev; + + next->m_prevNode = node; + prev->m_nextNode = node; + } + +public: +#if defined(_DEBUG) + BOOL Exists( T* searchNode ) + { + T* node = FirstValidNode(); + while( node != NULL && node != searchNode ) + { + if (node == node->Next()) + { + ASSERT(FALSE); + } + node = node->Next(); + } + return (node == NULL? FALSE: TRUE); + } +#endif + + void InsertBeforeNode( T* node, T* nodeNew ) + { + if(node && nodeNew && node != nodeNew) + { + nodeNew->RemoveFromList(); + + Insert( node->Prev(), node, nodeNew ); + } + } + + void InsertAfterNode( T* node, T* nodeNew ) + { + if(node && nodeNew && node != nodeNew) + { + nodeNew->RemoveFromList(); + + Insert( node, node->Next(), nodeNew ); + } + } + + void LinkAtFront( T* node ) + { + InsertAfterNode( Head(), node ); + } + + void LinkAtBack( T* node ) + { + InsertBeforeNode( Tail(), node ); + } + + T* ExtractFirstNode() + { + T* node = FirstValidNode(); + + if(node) node->Unlink(); + + return node; + } + + T* ExtractLastNode() + { + T* node = LastValidNode(); + + if(node) node->Unlink(); + + return node; + } +}; + +//--// + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +template class Hal_Queue_UnknownSize +{ + size_t m_writer; + size_t m_reader; + size_t m_size; + BOOL m_full; + T* m_data; + +public: + void Initialize( T* data, size_t size ) + { + m_writer = 0; + m_reader = 0; + m_size = size; + m_data = data; + m_full = FALSE; + } + + size_t NumberOfElements() + { + if(m_writer < m_reader) return m_size + m_writer - m_reader; + else if(m_full) return m_size; + else return m_writer - m_reader; + } + + BOOL IsEmpty() + { + return (m_writer == m_reader && !m_full); + } + + BOOL IsFull() + { + return m_full; + } + + T* operator[](int index) + { + if(index < 0 || index >= NumberOfElements()) return NULL; + + return &m_data[(m_reader + index) % m_size]; + } + + T* Push() + { + size_t oldWriter = m_writer; + + if(m_full) return NULL; + + m_writer++; if(m_writer == m_size) m_writer = 0; + + if(m_writer == m_reader) m_full = TRUE; + + return &m_data[oldWriter]; + } + + T* Peek() + { + if(m_writer == m_reader && !m_full) return NULL; + + return &m_data[m_reader]; + } + + T* Pop() + { + size_t oldReader = m_reader; + + if(m_reader == m_writer && !m_full) return (T*)NULL; + + m_reader++; if(m_reader == m_size) m_reader = 0; + + m_full = FALSE; + + return &m_data[oldReader]; + } + + T* Push( size_t &nElements ) + { + size_t oldWriter = m_writer; + size_t max = 0; + + if(m_full || (nElements == 0)) + { + nElements = 0; + return NULL; + } + + if(m_writer < m_reader) max = m_reader - m_writer; + else max = m_size - m_writer; + + nElements = (max < nElements? max: nElements); + + m_writer += nElements; if(m_writer == m_size) m_writer = 0; + + if(m_writer == m_reader) m_full = TRUE; + + return &m_data[oldWriter]; + } + + T* Pop( size_t &nElements ) + { + size_t oldReader = m_reader; + size_t max = 0; + + if(nElements == 0) return NULL; + + if((m_reader == m_writer) && !m_full) + { + nElements = 0; + // reset the reader/writer to maximize push potential + m_reader = 0; + m_writer = 0; + return NULL; + } + + if(m_writer <= m_reader) max = m_size - m_reader; + else max = m_writer - m_reader; + + nElements = (max < nElements? max: nElements); + + m_reader += nElements; if(m_reader == m_size) m_reader = 0; + + m_full = FALSE; + + return &m_data[oldReader]; + } + + T* Storage() { return m_data; } +}; + +//--// + +//#include <..\Initialization\MasterConfig.h> + +#define NUM_DEBUGGERS 1 // UNDONE: Remove +#define NUM_MESSAGING 1 // UNDONE: Remove + +#define DEBUGGER_PORT_INDEX 0 // UNDONE: Remove + +//--// + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +void HAL_EnterBooterMode(); + +typedef void (*ON_SOFT_REBOOT_HANDLER)(void); + +void HAL_AddSoftRebootHandler(ON_SOFT_REBOOT_HANDLER handler); + +//--// + + +// +// This has to be extern "C" because the Crypto library has C-linkage. +// +extern "C" { + +void* private_malloc ( size_t len ); +void private_free ( void* ptr ); +void* private_realloc( void* ptr, size_t len ); + +} + + + + + + + + + + + + + +//--// + + + +//--// + +#define HAL_DECLARE_CUSTOM_HEAP(allocFtn,freeFtn,reallocFtn) \ + extern "C" { \ + void* private_malloc ( size_t len ) { return allocFtn ( len ); } \ + void private_free ( void* ptr ) { freeFtn ( ptr ); } \ + void* private_realloc( void* ptr, size_t len ) { return reallocFtn( ptr, len ); } \ + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +//--// + +extern bool g_fDoNotUninitializeDebuggerPort; + +//--// + + +#include +//#include + +///////////////////////////////////////////////////////////////////// +// +// Chipset +// + +//// boot +//#include +// +//// Cache driver +//#include +// +//// Cache driver +//#include +// +//// Gp I/O driver +//#include +// +//// Gp I/O driver +//#include +// + +//// Watchdog driver +//#include + +/// +/// Resets the watchdog timer. This method is called periodically by the system to ensure that the watchdog event does not occur, unless the +/// system is in a stalled state. +/// +void Watchdog_ResetCounter( ); + +/// +/// Gets or sets the watchdog enable state. +/// +/// Sets the watchdog enabled state when fSet is true; otherwise this parameter is ignored +/// Determines if this call is getting or setting the enabled state +/// Returns the current enabled state of the watchdog +BOOL Watchdog_GetSetEnabled ( BOOL enabled, BOOL fSet ); + +// +//// SPI driver +//#include +// +//// External bus interface driver +//#include +// +//// Power control unit +//#include +// +//// Clock management unit driver +//#include +// +//// DMA driver +//#include +// +//#include +// +//// Virtual Key +//#include +// + +//// Power API +//#include + +void CPU_Reset(); + + +// +// Chipset +// +///////////////////////////////////////////////////////////////////// + +//#include + + +// platform_selector.h (from MasterConfig.h) + +#if defined(_WIN32) + +#define GLOBAL_LOCK(x) // UNDONE: FIXME: SmartPtr_IRQ x +//#define DISABLE_INTERRUPTS() SmartPtr_IRQ::ForceDisabled() +//#define ENABLE_INTERRUPTS() SmartPtr_IRQ::ForceEnabled() +//#define INTERRUPTS_ENABLED_STATE() SmartPtr_IRQ::GetState() +//#define GLOBAL_LOCK_SOCKETS(x) // UNDONE: FIXME: SmartPtr_IRQ x + +#if defined(_DEBUG) +#define ASSERT_IRQ_MUST_BE_OFF() ASSERT( HAL_Windows_HasGlobalLock()) +#define ASSERT_IRQ_MUST_BE_ON() ASSERT(!HAL_Windows_HasGlobalLock()) +#else +#define ASSERT_IRQ_MUST_BE_OFF() +#define ASSERT_IRQ_MUST_BE_ON() +#endif + +#else +#error Unsupported platform +#endif + +// UNDONE: FIXME: VERSION_XXX +#define VERSION_MAJOR 0 +#define VERSION_MINOR 1 +#define VERSION_BUILD 0 +#define VERSION_REVISION 0 + +#define OEMSYSTEMINFOSTRING "OEM" // UNDONE: FIXME: OEMSYSTEMINFOSTRING + +#endif // _TINYHAL_H_ diff --git a/src/CLR/Include/TinyHAL_ReleaseInfo.h b/src/CLR/Include/TinyHAL_ReleaseInfo.h new file mode 100644 index 0000000000..d638ebd871 --- /dev/null +++ b/src/CLR/Include/TinyHAL_ReleaseInfo.h @@ -0,0 +1,73 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _TINYHAL_RELEASEINFO_H_ +#define _TINYHAL_RELEASEINFO_H_ 1 + + +struct MFVersion +{ + unsigned short usMajor; + unsigned short usMinor; + unsigned short usBuild; + unsigned short usRevision; + + // Version & MfReleaseInfo participate in a union in the debugging support, + // and therefore cannot have real constructors, though that would be better + // style otherwise. + static void Init(MFVersion& version, unsigned short major=0, unsigned short minor=0, unsigned short build=0, unsigned short revision=0) + { + version.usMajor = major; + version.usMinor = minor; + version.usBuild = build; + version.usRevision = revision; + } +}; + +struct MfReleaseInfo +{ + MFVersion version; + unsigned char infoString[64-sizeof(MFVersion)]; + + static void Init(MfReleaseInfo& releaseInfo, unsigned short major=0, unsigned short minor=0, unsigned short build=0, unsigned short revision=0, const char *info=(const char *)NULL, size_t infoLen=0); +}; + +struct OEM_MODEL_SKU +{ + unsigned char OEM; + unsigned char Model; + unsigned short SKU; +}; + +struct OEM_SERIAL_NUMBERS +{ + unsigned char module_serial_number[32]; + unsigned char system_serial_number[16]; +}; + +struct HalSystemInfo +{ + MfReleaseInfo m_releaseInfo; + OEM_MODEL_SKU m_OemModelInfo; + OEM_SERIAL_NUMBERS m_OemSerialNumbers; +}; + +//--// + +// GetHalSystemInfo() is defined in DeviceCode\pal\configuration\, and is provided +// to allow convenient access to configuration and build information to the debugging +// system and to managed code. +unsigned int GetHalSystemInfo(HalSystemInfo& systemInfo); + +// Solution-specific function; see TinyBooterEntry.cpp in your solution's TinyBooter directory for implementation. +unsigned int TinyBooter_GetReleaseInfo(MfReleaseInfo& releaseInfo); + +// Solution-specific function, provide this to allow access to a vendor-provided +// informative string and build-time version information. +unsigned int Solution_GetReleaseInfo(MfReleaseInfo&); + +//--// + +#endif // _TINYHAL_RELEASEINFO_H_ diff --git a/src/CLR/Include/TinyHAL_Types.h b/src/CLR/Include/TinyHAL_Types.h new file mode 100644 index 0000000000..394f9f8d94 --- /dev/null +++ b/src/CLR/Include/TinyHAL_Types.h @@ -0,0 +1,93 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _HAL_TYPES_H_ +#define _HAL_TYPES_H_ 1 + +#include + +#include + +#if defined(__ADSPBLACKFIN__) || defined (__GNUC__) || defined(_ARC) || defined(__RENESAS__) +#define __int64 long long +#undef NULL +#endif + +#if defined(__ADSPBLACKFIN__) +#define PLATFORM_BLACKFIN +#endif + +#if defined(__arm) || defined(PLATFORM_BLACKFIN) || defined(__GNUC__) || defined(_ARC) || defined(__RENESAS__) + +#undef UNICODE + +typedef unsigned int BOOL; + +#define TRUE 1 +#define FALSE 0 + +typedef unsigned char BYTE; +typedef unsigned char* PBYTE; + +typedef unsigned char UINT8; +typedef signed char INT8; + +typedef unsigned short int UINT16; +typedef signed short int INT16; + +typedef unsigned int UINT32; +typedef signed int INT32; + +typedef unsigned int ULONG; +typedef signed int LONG; + +typedef unsigned __int64 UINT64; +typedef signed __int64 INT64; + +#define NULL 0 + +typedef char CHAR; +typedef char* LPSTR; +typedef const char* LPCSTR; +typedef unsigned short WORD; +typedef unsigned long DWORD; + + +#if defined (__RENESAS__) +typedef unsigned short wchar_t; +#endif + +typedef wchar_t WCHAR; +typedef WCHAR* LPWSTR; +typedef const WCHAR* LPCWSTR; + +#endif //defined(__arm) || defined(PLATFORM_BLACKFIN) || defined(__GNUC__) || defined(_ARC) || defined(__RENESAS__) + +#define ARRAYSIZE_CONST_EXPR(x) (sizeof(x)/sizeof(x[0])) +#if (!defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE)) +#define ARRAYSIZE(x) ARRAYSIZE_CONST_EXPR(x) +#endif +#define MAXSTRLEN(x) (ARRAYSIZE(x)-1) +#define ROUNDTOMULTIPLE(x,y) ((x + sizeof(y) - 1) & ~(sizeof(y)-1)) // Only works with powers of 2. +#define CONVERTFROMSIZETOELEMENTS(x,y) ((x + sizeof(y) - 1) / sizeof(y)) +#define CONVERTFROMSIZETOHEAPBLOCKS(x) CONVERTFROMSIZETOELEMENTS(x,CLR_RT_HeapBlock) + +//--// + +#if !(defined(_WIN32) || defined(WIN32) || defined(_WIN32_WCE)) +struct SYSTEMTIME +{ + WORD wYear; + WORD wMonth; + WORD wDayOfWeek; + WORD wDay; + WORD wHour; + WORD wMinute; + WORD wSecond; + WORD wMilliseconds; +}; +#endif + +#endif // _HAL_TYPES_H_ diff --git a/src/CLR/Include/TinyPAL.h b/src/CLR/Include/TinyPAL.h new file mode 100644 index 0000000000..f0b0f8c73d --- /dev/null +++ b/src/CLR/Include/TinyPAL.h @@ -0,0 +1,392 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _TINYPAL_H_ +#define _TINYPAL_H_ 1 + +//#include + +//#include + +typedef void (*HAL_CALLBACK_FPN)( void* arg ); + +struct HAL_CALLBACK +{ +public: + HAL_CALLBACK_FPN EntryPoint; + void* Argument; + +public: + void Initialize( HAL_CALLBACK_FPN EntryPoint, void* Argument ) + { + this->EntryPoint = EntryPoint; + this->Argument = Argument; + } + + void SetArgument( void* Argument ) + { + this->Argument = Argument; + } + + HAL_CALLBACK_FPN GetEntryPoint() const { return this->EntryPoint; } + void* GetArgument () const { return this->Argument ; } + + void Execute() const + { + HAL_CALLBACK_FPN EntryPoint = this->EntryPoint; + void* Argument = this->Argument; + + if(EntryPoint) + { + EntryPoint( Argument ); + } + } +}; + + +struct HAL_CONTINUATION : public HAL_DblLinkedNode +{ + +private: + HAL_CALLBACK Callback; + +public: + void InitializeCallback( HAL_CALLBACK_FPN EntryPoint, void* Argument = NULL ); + + void SetArgument( void* Argument ) + { + Callback.SetArgument( Argument ); + } + + HAL_CALLBACK_FPN GetEntryPoint() const { return Callback.GetEntryPoint(); } + void* GetArgument () const { return Callback.GetArgument (); } + + void Execute() const { Callback.Execute(); } + + bool IsLinked(); + void Enqueue(); + void Abort (); + + //--// + + static void Uninitialize(); + + static void InitializeList(); + + static BOOL Dequeue_And_Execute(); +}; + +//--// + +struct HAL_COMPLETION : public HAL_CONTINUATION +{ + UINT64 EventTimeTicks; + BOOL ExecuteInISR; + +#if defined(_DEBUG) + UINT64 Start_RTC_Ticks; +#endif + + void InitializeForISR( HAL_CALLBACK_FPN EntryPoint, void* Argument = NULL ) + { + ExecuteInISR = TRUE; + + InitializeCallback( EntryPoint, Argument ); + } + + void InitializeForUserMode( HAL_CALLBACK_FPN EntryPoint, void* Argument = NULL ) + { + ExecuteInISR = FALSE; + + InitializeCallback( EntryPoint, Argument ); + } + + void EnqueueTicks ( UINT64 EventTimeTicks ); + void EnqueueDelta64 ( UINT64 uSecFromNow ); + void EnqueueDelta ( UINT32 uSecFromNow ); + + void Abort(); + + void Execute(); + + //--// + + static void Uninitialize(); + + static void InitializeList(); + + static void DequeueAndExec(); + + static void WaitForInterrupts( UINT64 Expire, UINT32 sleepLevel, UINT64 wakeEvents ); +}; + +//--// + +//#include +//#include +//#include +//#include + +//#include +BOOL DebuggerPort_Initialize(COM_HANDLE ComPortNum); +BOOL DebuggerPort_Uninitialize(COM_HANDLE ComPortNum); + +// max retries is the number of retries if the first attempt fails, thus the maximum +// total number of attempts is maxRretries + 1 since it always tries at least once. +int DebuggerPort_Write(COM_HANDLE ComPortNum, const char* Data, size_t size, int maxRetries = 99); +int DebuggerPort_Read(COM_HANDLE ComPortNum, char* Data, size_t size); +BOOL DebuggerPort_Flush(COM_HANDLE ComPortNum); +BOOL DebuggerPort_IsSslSupported(COM_HANDLE ComPortNum); +BOOL DebuggerPort_UpgradeToSsl(COM_HANDLE ComPortNum, UINT32 flags); +BOOL DebuggerPort_IsUsingSsl(COM_HANDLE ComPortNum); + +// +//#include + +//#include (must be before events_decl.h) + +// +// !!! KEEP IN SYNC WITH Microsoft.SPOT.Hardware.SleepLevel !!! +// +enum SLEEP_LEVEL +{ + SLEEP_LEVEL__AWAKE = 0x00, + SLEEP_LEVEL__SELECTIVE_OFF = 0x10, + SLEEP_LEVEL__SLEEP = 0x20, + SLEEP_LEVEL__DEEP_SLEEP = 0x30, + SLEEP_LEVEL__OFF = 0x40, +}; + + +//#include + +// destructive read system event flags +UINT32 Events_Get( UINT32 EventsOfInterest ); + +// non-destructive read system event flags +UINT32 Events_MaskedRead( UINT32 EventsOfInterest ); + + +// returns 0 for timeout, non-zero are events that have happened and were asked to be waiting on (non-destructive read) +// timeout limit is about 3034 milliseconds currently +// values greater than this are capped to this + +// sleep relative time into the future, or until a SystemEvent occurs, which occurs first +// timeout is a non-negative number of 1mSec ticks, or -1 (any negative value) to sleep forever until a SystemEvent occurs + +// Events_WaitForEvents(0, n), sleeps for n milliseconds independent of events +// Events_WaitForEvents(0, EVENTS_TIMEOUT_INFINITE) sleeps forever. Don't do that. +// Events_WaitForEvents(flags, EVENTS_TIMEOUT_INFINITE) waits forever for that event. + +#define EVENTS_TIMEOUT_INFINITE 0xFFFFFFFF + +UINT32 Events_WaitForEvents ( UINT32 sleepLevel, UINT32 WakeupSystemEvents, UINT32 Timeout_Milliseconds ); +UINT32 Events_WaitForEventsInternal( UINT32 sleepLevel, UINT32 WakeupSystemEvents, UINT32 Timeout_Milliseconds ); + +__inline UINT32 Events_WaitForEvents( UINT32 WakeupSystemEvents, UINT32 Timeout_Milliseconds ) +{ + return Events_WaitForEvents( SLEEP_LEVEL__SLEEP, WakeupSystemEvents, Timeout_Milliseconds ); +} + +void Events_SetBoolTimer(BOOL* TimerCompleteFlag, UINT32 MillisecondsFromNow); + + +//#include + +//#include + +// This function returns location of the CLR heap. +void HeapLocation(UINT8*& BaseAddress, UINT32& SizeInBytes); + + +//#include +//#include +// +//#include +// +//#include +//#include +//#include +// +//#include +// +//#include +//#include +// + +//#include + +// +// !!! KEEP IN SYNC WITH Microsoft.SPOT.Hardware.PowerLevel !!! +// +enum POWER_LEVEL +{ + POWER_LEVEL__HIGH_POWER = 0x10, + POWER_LEVEL__MID_POWER = 0x20, + POWER_LEVEL__LOW_POWER = 0x30, +}; + +BOOL CPU_IsSoftRebootSupported(); + + +//#include +//#include + +//#include + +#define TIME INT64 + +#define TIME_CONVERSION__TO_MILLISECONDS 10000 +#define TIME_CONVERSION__TO_SECONDS 10000000 +#define TIME_CONVERSION__TICKUNITS 10000 +#define TIME_CONVERSION__ONESECOND 1 +#define TIME_CONVERSION__ONEMINUTE 60 +#define TIME_CONVERSION__ONEHOUR 3600 +#define TIME_CONVERSION__ONEDAY 86400 + +#define TIMEOUT_ZERO LONGLONGCONSTANT(0x0000000000000000) +#define TIMEOUT_INFINITE LONGLONGCONSTANT(0x7FFFFFFFFFFFFFFF) + +#define TIME_ZONE_OFFSET ((INT64)Time_GetTimeZoneOffset() * 600000000) + +/// +/// Initializes PAL Time drivers, must be called before any of the Time_* PAL +/// methods could be used. +/// +HRESULT Time_Initialize ( ); + +/// +/// UTC time according to this system. +/// +/// Returns current UTC time in 100ns elapsed since 1/1/1601:00:00:00.000 UTC. +INT64 Time_GetUtcTime(); + +/// +/// Local time according to the Time subsystem. +/// +/// Local time in 100ns elapsed since 1/1/1601:00:00:00.000 local time. +INT64 Time_GetLocalTime(); + +/// +/// Offset from GMT. +/// +/// In minutes, for example Pacific Time would be GMT-8 = -480. +INT32 Time_GetTimeZoneOffset(); + +/// +/// Retrieves time since device was booted. +/// +/// Time in 100ns. +INT64 Time_GetMachineTime(); + +/// +/// Converts 64bit time value to SystemTime structure. 64bit time is assumed as an offset from 1/1/1601:00:00:00.000 in 100ns. +/// +/// True if conversion is successful. +BOOL Time_ToSystemTime(TIME time, SYSTEMTIME* systemTime); + +/// +/// Retrieves number of days given a month and a year. Calculates for leap years. +/// +/// S_OK if successful. +HRESULT Time_DaysInMonth(INT32 year, INT32 month, INT32* days); + +/// +/// Retrieves number of days since the beginning of the year given a month and a year. Calculates for leap years. +/// +/// S_OK if successful. +HRESULT Time_AccDaysInMonth(INT32 year, INT32 month, INT32* days); + +/// +/// Converts SystemTime structure to 64bit time, which is assumed as an offset from 1/1/1601:00:00:00.000 in 100ns. +/// +/// Time value. +TIME Time_FromSystemTime(const SYSTEMTIME* systemTime); + +/// APIs to convert between types +BOOL Time_TimeSpanToStringEx(const INT64& ticks, LPSTR& buf, size_t& len); +LPCSTR Time_CurrentDateTimeToString(); + + +INT64 HAL_Time_TicksToTime(UINT64 Ticks); +INT64 HAL_Time_CurrentTime(); + +extern "C" +{ + UINT64 HAL_Time_CurrentTicks(); +} + +//#include +//#include + +//#include + +#if defined(PLATFORM_ARM) +#pragma check_printf_formats /* hint to the compiler to check f/s/printf format */ +#endif +int hal_vprintf( const char* format, va_list arg ); + +#if defined(PLATFORM_ARM) +#pragma check_printf_formats /* hint to the compiler to check f/s/printf format */ +#endif +int hal_vfprintf( COM_HANDLE stream, const char* format, va_list arg ); + +#if defined(PLATFORM_ARM) +#pragma check_printf_formats /* hint to the compiler to check f/s/printf format */ +#endif +int hal_snprintf( char* buffer, size_t len, const char* format, ... ); + +int hal_vsnprintf( char* buffer, size_t len, const char* format, va_list arg ); + +#if defined(PLATFORM_ARM) || defined(PLATFORM_SH) +#define printf DoNotUse_*printf [] +#define sprintf DoNotUse_*printf [] +#define fprintf DoNotUse_*printf [] + +#define _printf DoNotUse_*printf [] +#define _sprintf DoNotUse_*printf [] +#define _fprintf DoNotUse_*printf [] + +#define snprintf DoNotUse_*printf [] +#define vsnprintf DoNotUse_*printf [] + +#define _snprintf DoNotUse_*printf [] +#define _vsnprintf DoNotUse_*printf [] + +#define strcpy DoNotUse_*strcpy [] +#define strncpy DoNotUse_*strcpy [] +#define strlen DoNotUse_*strlen [] +#define strncmp DoNotUse_*strncmp [] + + +int hal_strcpy_s ( char* strDst, size_t sizeInBytes, const char* strSrc ); +int hal_strncpy_s( char* strDst, size_t sizeInBytes, const char* strSrc, size_t count ); +size_t hal_strlen_s (const char * str); +int hal_strncmp_s( const char* str1, const char* str2, size_t num ); + +#elif defined(_WIN32) + +#define hal_strcpy_s(strDst, sizeInBytes, strSrc) strcpy_s(strDst, sizeInBytes, strSrc) +#define hal_strncpy_s(strDst, sizeInBytes, strSrc, count) strncpy_s(strDst, sizeInBytes, strSrc, count) +#define hal_strlen_s(str) strlen(str) +#define hal_strncmp_s(str1, str2, num) strncmp(str1, str2, num) + +#else +!ERROR +#endif + + +//#include +//#include +//#include +//#include +//#include +// +#include "Blockstorage_decl.h" + +//#include + +#endif // _TINYPAL_H_ + diff --git a/src/CLR/Include/TinySupport.h b/src/CLR/Include/TinySupport.h new file mode 100644 index 0000000000..f8085caef1 --- /dev/null +++ b/src/CLR/Include/TinySupport.h @@ -0,0 +1,25 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _SUPPORT_TINYSUPPORT_H_ +#define _SUPPORT_TINYSUPPORT_H_ + +UINT32 SUPPORT_ComputeCRC(const void* rgBlock, int nLength, UINT32 crc); + +//typedef BOOL (*WRITE_MEMORY_FUNCT)( UINT32 Address, UINT32 NumBytes, const BYTE * pSectorBuff ); +//typedef BOOL (*READ_MEMORY_FUNCT) ( UINT32 Address, UINT32 NumBytes, BYTE * pSectorBuff ); +// +//int LZ77_Decompress( UINT8* inBuf, int inSize, UINT8* outBuf, int outSize ); +//int LZ77_Decompress( UINT8* inBuf, int inSize, UINT8* outBuf, int outSize, WRITE_MEMORY_FUNCT writeMem, READ_MEMORY_FUNCT readMem ); + +//--// + +#if defined(_WIN32) || defined(WIN32) || defined(_WIN32_WCE) + +bool LZ77_Compress(LPCWSTR inFileText, LPCWSTR outFileText, UINT8* prefix, size_t prefixLength); + +#endif + +#endif // _SUPPORT_TINYSUPPORT_H_ diff --git a/src/CLR/Include/WireProtocol.h b/src/CLR/Include/WireProtocol.h index e880a497e1..707aef998d 100644 --- a/src/CLR/Include/WireProtocol.h +++ b/src/CLR/Include/WireProtocol.h @@ -1,6 +1,6 @@ // // Copyright (c) 2017 The nanoFramework project contributors -// Copyright (c) Microsoft Corporation. All rights reserved. +// Portions Copyright (c) Microsoft Corporation. All rights reserved. // See LICENSE file in the project root for full license information. // #ifndef _SUPPORT_WIREPROTOCOL_H_ diff --git a/src/CLR/Include/netmf_errors.h b/src/CLR/Include/netmf_errors.h new file mode 100644 index 0000000000..89400f13fe --- /dev/null +++ b/src/CLR/Include/netmf_errors.h @@ -0,0 +1,170 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef __NETMF_ERRORS_H__ +#define __NETMF_ERRORS_H__ + +#if !defined(WIN32) && !defined(_WIN32) + +typedef int HRESULT; + +// +// Severity values +// + +#define SEVERITY_SUCCESS 0 +#define SEVERITY_ERROR 1 + + +// +// Generic test for success on any status value (non-negative numbers +// indicate success). +// + +#define SUCCEEDED(Status) ((HRESULT)(Status) >= 0) + +// +// and the inverse +// + +#define FAILED(Status) ((HRESULT)(Status)<0) + + +// +// Success codes +// +#define S_OK ((HRESULT)0x00000000L) +#define S_FALSE ((HRESULT)0x00000001L) + + +// +// Return the code +// + +#define HRESULT_CODE(hr) ((hr) & 0xFFFF) + +// +// Return the facility +// + +#define HRESULT_FACILITY(hr) (((hr) >> 16) & 0x1fff) + +// +// Return the severity +// + +#define HRESULT_SEVERITY(hr) (((hr) >> 31) & 0x1) + +// +// Create an HRESULT value from component pieces +// + +#define MAKE_HRESULT(sev,fac,code) ((HRESULT) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) ) + +#endif // !defined(WIN32) && !defined(_WIN32) + +//--// + +// +// These are denormalized HRESULTs, only the 8 most significant bits are set, to allow use of MOV ,# by the compiler. +// + +#define CLR_E_UNKNOWN_INSTRUCTION MAKE_HRESULT( SEVERITY_ERROR , 0x0100, 0x0000 ) +#define CLR_E_UNSUPPORTED_INSTRUCTION MAKE_HRESULT( SEVERITY_ERROR , 0x0200, 0x0000 ) + +#define CLR_E_STACK_OVERFLOW MAKE_HRESULT( SEVERITY_ERROR , 0x1100, 0x0000 ) +#define CLR_E_STACK_UNDERFLOW MAKE_HRESULT( SEVERITY_ERROR , 0x1200, 0x0000 ) + +#define CLR_E_ENTRY_NOT_FOUND MAKE_HRESULT( SEVERITY_ERROR , 0x1500, 0x0000 ) +#define CLR_E_ASSM_WRONG_CHECKSUM MAKE_HRESULT( SEVERITY_ERROR , 0x1600, 0x0000 ) +#define CLR_E_ASSM_PATCHING_NOT_SUPPORTED MAKE_HRESULT( SEVERITY_ERROR , 0x1700, 0x0000 ) +#define CLR_E_SHUTTING_DOWN MAKE_HRESULT( SEVERITY_ERROR , 0x1800, 0x0000 ) +#define CLR_E_OBJECT_DISPOSED MAKE_HRESULT( SEVERITY_ERROR , 0x1900, 0x0000 ) +#define CLR_E_WATCHDOG_TIMEOUT MAKE_HRESULT( SEVERITY_ERROR , 0x1A00, 0x0000 ) + +#define CLR_E_NULL_REFERENCE MAKE_HRESULT( SEVERITY_ERROR , 0x2100, 0x0000 ) +#define CLR_E_WRONG_TYPE MAKE_HRESULT( SEVERITY_ERROR , 0x2200, 0x0000 ) +#define CLR_E_TYPE_UNAVAILABLE MAKE_HRESULT( SEVERITY_ERROR , 0x2300, 0x0000 ) +#define CLR_E_INVALID_CAST MAKE_HRESULT( SEVERITY_ERROR , 0x2400, 0x0000 ) +#define CLR_E_OUT_OF_RANGE MAKE_HRESULT( SEVERITY_ERROR , 0x2500, 0x0000 ) + +#define CLR_E_SERIALIZATION_VIOLATION MAKE_HRESULT( SEVERITY_ERROR , 0x2700, 0x0000 ) +#define CLR_E_SERIALIZATION_BADSTREAM MAKE_HRESULT( SEVERITY_ERROR , 0x2800, 0x0000 ) +#define CLR_E_INDEX_OUT_OF_RANGE MAKE_HRESULT( SEVERITY_ERROR , 0x2900, 0x0000 ) + +#define CLR_E_DIVIDE_BY_ZERO MAKE_HRESULT( SEVERITY_ERROR , 0x3100, 0x0000 ) + +#define CLR_E_BUSY MAKE_HRESULT( SEVERITY_ERROR , 0x3300, 0x0000 ) + +#define CLR_E_PROCESS_EXCEPTION MAKE_HRESULT( SEVERITY_ERROR , 0x4100, 0x0000 ) + +#define CLR_E_THREAD_WAITING MAKE_HRESULT( SEVERITY_ERROR , 0x4200, 0x0000 ) + +#define CLR_E_LOCK_SYNCHRONIZATION_EXCEPTION MAKE_HRESULT( SEVERITY_ERROR , 0x4400, 0x0000 ) + +#define CLR_E_APPDOMAIN_EXITED MAKE_HRESULT( SEVERITY_ERROR , 0x4800, 0x0000 ) +#define CLR_E_APPDOMAIN_MARSHAL_EXCEPTION MAKE_HRESULT( SEVERITY_ERROR , 0x4900, 0x0000 ) +#define CLR_E_NOTIMPL MAKE_HRESULT( SEVERITY_ERROR , 0x4a00, 0x0000 ) + +#define CLR_E_UNKNOWN_TYPE MAKE_HRESULT( SEVERITY_ERROR , 0x4d00, 0x0000 ) +#define CLR_E_ARGUMENT_NULL MAKE_HRESULT( SEVERITY_ERROR , 0x4e00, 0x0000 ) +#define CLR_E_IO MAKE_HRESULT( SEVERITY_ERROR , 0x4f00, 0x0000 ) + +#define CLR_E_ENTRYPOINT_NOT_FOUND MAKE_HRESULT( SEVERITY_ERROR , 0x5000, 0x0000 ) +#define CLR_E_DRIVER_NOT_REGISTERED MAKE_HRESULT( SEVERITY_ERROR , 0x5100, 0x0000 ) + + +// +// Gp IO error codes +// +#define CLR_E_PIN_UNAVAILABLE MAKE_HRESULT( SEVERITY_ERROR , 0x5400, 0x0000 ) +#define CLR_E_PIN_DEAD MAKE_HRESULT( SEVERITY_ERROR , 0x5500, 0x0000 ) +#define CLR_E_INVALID_OPERATION MAKE_HRESULT( SEVERITY_ERROR , 0x5600, 0x0000 ) +#define CLR_E_WRONG_INTERRUPT_TYPE MAKE_HRESULT( SEVERITY_ERROR , 0x5700, 0x0000 ) +#define CLR_E_NO_INTERRUPT MAKE_HRESULT( SEVERITY_ERROR , 0x5800, 0x0000 ) +#define CLR_E_DISPATCHER_ACTIVE MAKE_HRESULT( SEVERITY_ERROR , 0x5900, 0x0000 ) + +// +// IO error codes +// (Keep in-sync with IOExceptionErrorCode enum in IOException.cs) +// +#define CLR_E_FILE_IO MAKE_HRESULT( SEVERITY_ERROR , 0x6000, 0x0000 ) +#define CLR_E_INVALID_DRIVER MAKE_HRESULT( SEVERITY_ERROR , 0x6100, 0x0000 ) +#define CLR_E_FILE_NOT_FOUND MAKE_HRESULT( SEVERITY_ERROR , 0x6200, 0x0000 ) +#define CLR_E_DIRECTORY_NOT_FOUND MAKE_HRESULT( SEVERITY_ERROR , 0x6300, 0x0000 ) +#define CLR_E_VOLUME_NOT_FOUND MAKE_HRESULT( SEVERITY_ERROR , 0x6400, 0x0000 ) +#define CLR_E_PATH_TOO_LONG MAKE_HRESULT( SEVERITY_ERROR , 0x6500, 0x0000 ) +#define CLR_E_DIRECTORY_NOT_EMPTY MAKE_HRESULT( SEVERITY_ERROR , 0x6600, 0x0000 ) +#define CLR_E_UNAUTHORIZED_ACCESS MAKE_HRESULT( SEVERITY_ERROR , 0x6700, 0x0000 ) +#define CLR_E_PATH_ALREADY_EXISTS MAKE_HRESULT( SEVERITY_ERROR , 0x6800, 0x0000 ) +#define CLR_E_TOO_MANY_OPEN_HANDLES MAKE_HRESULT( SEVERITY_ERROR , 0x6900, 0x0000 ) + +// +// General error codes +// + +#define CLR_E_NOT_FOUND MAKE_HRESULT( SEVERITY_ERROR , 0x7500, 0x0000 ) +#define CLR_E_BUFFER_TOO_SMALL MAKE_HRESULT( SEVERITY_ERROR , 0x7600, 0x0000 ) +#define CLR_E_NOT_SUPPORTED MAKE_HRESULT( SEVERITY_ERROR , 0x7700, 0x0000 ) +#define CLR_E_HMAC_NOT_SUPPORTED MAKE_HRESULT( SEVERITY_ERROR , 0x7701, 0x0000 ) +#define CLR_E_RESCHEDULE MAKE_HRESULT( SEVERITY_ERROR , 0x7800, 0x0000 ) + +#define CLR_E_OUT_OF_MEMORY MAKE_HRESULT( SEVERITY_ERROR , 0x7A00, 0x0000 ) +#define CLR_E_RESTART_EXECUTION MAKE_HRESULT( SEVERITY_ERROR , 0x7B00, 0x0000 ) + +#define CLR_E_INVALID_PARAMETER MAKE_HRESULT( SEVERITY_ERROR , 0x7D00, 0x0000 ) +#define CLR_E_TIMEOUT MAKE_HRESULT( SEVERITY_ERROR , 0x7E00, 0x0000 ) +#define CLR_E_FAIL MAKE_HRESULT( SEVERITY_ERROR , 0x7F00, 0x0000 ) + +//--// + +#define CLR_S_THREAD_EXITED MAKE_HRESULT( SEVERITY_SUCCESS, 0x0100, 0x0000 ) +#define CLR_S_QUANTUM_EXPIRED MAKE_HRESULT( SEVERITY_SUCCESS, 0x0200, 0x0000 ) +#define CLR_S_NO_READY_THREADS MAKE_HRESULT( SEVERITY_SUCCESS, 0x0300, 0x0000 ) +#define CLR_S_NO_THREADS MAKE_HRESULT( SEVERITY_SUCCESS, 0x0400, 0x0000 ) +#define CLR_S_RESTART_EXECUTION MAKE_HRESULT( SEVERITY_SUCCESS, 0x0500, 0x0000 ) + + +#endif // __NETMF_ERRORS_H__ diff --git a/src/CLR/Include/opcode.def b/src/CLR/Include/opcode.def new file mode 100644 index 0000000000..9f909fc380 --- /dev/null +++ b/src/CLR/Include/opcode.def @@ -0,0 +1,359 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +/***************************************************************************** + ** ** + ** Opcode.def - COM+ Intrinsic Opcodes and Macros. ** + ** ** + ** This is the master table from which all opcode lists ** + ** are derived. New instructions must be added to this ** + ** table and generators run to produce the lookup tables ** + ** used by the interpreter loop. ** + ** ** + ** Stack Behaviour is describing the number of 4 byte ** + ** slots pushed and Poped. ** + ** ** + *****************************************************************************/ + + +#ifndef __OPCODE_DEF_ +#define __OPCODE_DEF_ + +#define MOOT 0x00 // Marks unused second byte when encoding single +#define STP1 0xFE // Prefix code 1 for Standard Map +#define REFPRE 0xFF // Prefix for Reference Code Encoding +#define RESERVED_PREFIX_START 0xF7 + +#endif + +// If the first byte of the standard encoding is 0xFF, then +// the second byte can be used as 1 byte encoding. Otherwise l b b +// the encoding is two bytes. e y y +// n t t +// g e e +// (unused) t +// Canonical Name String Name Stack Behaviour Operand Params Opcode Kind h 1 2 Control Flow +// ------------------------------------------------------------------------------------------------------------------------------------------------------- +OPDEF(CEE_NOP, "nop", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x00, NEXT) +OPDEF(CEE_BREAK, "break", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x01, BREAK) +OPDEF(CEE_LDARG_0, "ldarg.0", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x02, NEXT) +OPDEF(CEE_LDARG_1, "ldarg.1", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x03, NEXT) +OPDEF(CEE_LDARG_2, "ldarg.2", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x04, NEXT) +OPDEF(CEE_LDARG_3, "ldarg.3", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x05, NEXT) +OPDEF(CEE_LDLOC_0, "ldloc.0", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x06, NEXT) +OPDEF(CEE_LDLOC_1, "ldloc.1", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x07, NEXT) +OPDEF(CEE_LDLOC_2, "ldloc.2", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x08, NEXT) +OPDEF(CEE_LDLOC_3, "ldloc.3", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x09, NEXT) +OPDEF(CEE_STLOC_0, "stloc.0", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0A, NEXT) +OPDEF(CEE_STLOC_1, "stloc.1", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0B, NEXT) +OPDEF(CEE_STLOC_2, "stloc.2", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0C, NEXT) +OPDEF(CEE_STLOC_3, "stloc.3", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0D, NEXT) +OPDEF(CEE_LDARG_S, "ldarg.s", Pop0, Push1, ShortInlineVar, IMacro, 1, 0xFF, 0x0E, NEXT) +OPDEF(CEE_LDARGA_S, "ldarga.s", Pop0, PushI, ShortInlineVar, IMacro, 1, 0xFF, 0x0F, NEXT) +OPDEF(CEE_STARG_S, "starg.s", Pop1, Push0, ShortInlineVar, IMacro, 1, 0xFF, 0x10, NEXT) +OPDEF(CEE_LDLOC_S, "ldloc.s", Pop0, Push1, ShortInlineVar, IMacro, 1, 0xFF, 0x11, NEXT) +OPDEF(CEE_LDLOCA_S, "ldloca.s", Pop0, PushI, ShortInlineVar, IMacro, 1, 0xFF, 0x12, NEXT) +OPDEF(CEE_STLOC_S, "stloc.s", Pop1, Push0, ShortInlineVar, IMacro, 1, 0xFF, 0x13, NEXT) +OPDEF(CEE_LDNULL, "ldnull", Pop0, PushRef, InlineNone, IPrimitive, 1, 0xFF, 0x14, NEXT) +OPDEF(CEE_LDC_I4_M1, "ldc.i4.m1", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x15, NEXT) +OPDEF(CEE_LDC_I4_0, "ldc.i4.0", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x16, NEXT) +OPDEF(CEE_LDC_I4_1, "ldc.i4.1", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x17, NEXT) +OPDEF(CEE_LDC_I4_2, "ldc.i4.2", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x18, NEXT) +OPDEF(CEE_LDC_I4_3, "ldc.i4.3", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x19, NEXT) +OPDEF(CEE_LDC_I4_4, "ldc.i4.4", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1A, NEXT) +OPDEF(CEE_LDC_I4_5, "ldc.i4.5", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1B, NEXT) +OPDEF(CEE_LDC_I4_6, "ldc.i4.6", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1C, NEXT) +OPDEF(CEE_LDC_I4_7, "ldc.i4.7", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1D, NEXT) +OPDEF(CEE_LDC_I4_8, "ldc.i4.8", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1E, NEXT) +OPDEF(CEE_LDC_I4_S, "ldc.i4.s", Pop0, PushI, ShortInlineI, IMacro, 1, 0xFF, 0x1F, NEXT) +OPDEF(CEE_LDC_I4, "ldc.i4", Pop0, PushI, InlineI, IPrimitive, 1, 0xFF, 0x20, NEXT) +OPDEF(CEE_LDC_I8, "ldc.i8", Pop0, PushI8, InlineI8, IPrimitive, 1, 0xFF, 0x21, NEXT) +OPDEF(CEE_LDC_R4, "ldc.r4", Pop0, PushR4, ShortInlineR, IPrimitive, 1, 0xFF, 0x22, NEXT) +OPDEF(CEE_LDC_R8, "ldc.r8", Pop0, PushR8, InlineR, IPrimitive, 1, 0xFF, 0x23, NEXT) +OPDEF(CEE_UNUSED49, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x24, NEXT) +OPDEF(CEE_DUP, "dup", Pop1, Push1+Push1, InlineNone, IPrimitive, 1, 0xFF, 0x25, NEXT) +OPDEF(CEE_POP, "pop", Pop1, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x26, NEXT) +OPDEF(CEE_JMP, "jmp", Pop0, Push0, InlineMethod, IPrimitive, 1, 0xFF, 0x27, CALL) +OPDEF(CEE_CALL, "call", VarPop, VarPush, InlineMethod, IPrimitive, 1, 0xFF, 0x28, CALL) +OPDEF(CEE_CALLI, "calli", VarPop, VarPush, InlineSig, IPrimitive, 1, 0xFF, 0x29, CALL) +OPDEF(CEE_RET, "ret", VarPop, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x2A, RETURN) +OPDEF(CEE_BR_S, "br.s", Pop0, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2B, BRANCH) +OPDEF(CEE_BRFALSE_S, "brfalse.s", PopI, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2C, COND_BRANCH) +OPDEF(CEE_BRTRUE_S, "brtrue.s", PopI, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2D, COND_BRANCH) +OPDEF(CEE_BEQ_S, "beq.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2E, COND_BRANCH) +OPDEF(CEE_BGE_S, "bge.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2F, COND_BRANCH) +OPDEF(CEE_BGT_S, "bgt.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x30, COND_BRANCH) +OPDEF(CEE_BLE_S, "ble.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x31, COND_BRANCH) +OPDEF(CEE_BLT_S, "blt.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x32, COND_BRANCH) +OPDEF(CEE_BNE_UN_S, "bne.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x33, COND_BRANCH) +OPDEF(CEE_BGE_UN_S, "bge.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x34, COND_BRANCH) +OPDEF(CEE_BGT_UN_S, "bgt.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x35, COND_BRANCH) +OPDEF(CEE_BLE_UN_S, "ble.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x36, COND_BRANCH) +OPDEF(CEE_BLT_UN_S, "blt.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x37, COND_BRANCH) +OPDEF(CEE_BR, "br", Pop0, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0x38, BRANCH) +OPDEF(CEE_BRFALSE, "brfalse", PopI, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0x39, COND_BRANCH) +OPDEF(CEE_BRTRUE, "brtrue", PopI, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0x3A, COND_BRANCH) +OPDEF(CEE_BEQ, "beq", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3B, COND_BRANCH) +OPDEF(CEE_BGE, "bge", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3C, COND_BRANCH) +OPDEF(CEE_BGT, "bgt", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3D, COND_BRANCH) +OPDEF(CEE_BLE, "ble", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3E, COND_BRANCH) +OPDEF(CEE_BLT, "blt", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3F, COND_BRANCH) +OPDEF(CEE_BNE_UN, "bne.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x40, COND_BRANCH) +OPDEF(CEE_BGE_UN, "bge.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x41, COND_BRANCH) +OPDEF(CEE_BGT_UN, "bgt.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x42, COND_BRANCH) +OPDEF(CEE_BLE_UN, "ble.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x43, COND_BRANCH) +OPDEF(CEE_BLT_UN, "blt.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x44, COND_BRANCH) +OPDEF(CEE_SWITCH, "switch", PopI, Push0, InlineSwitch, IPrimitive, 1, 0xFF, 0x45, COND_BRANCH) +OPDEF(CEE_LDIND_I1, "ldind.i1", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x46, NEXT) +OPDEF(CEE_LDIND_U1, "ldind.u1", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x47, NEXT) +OPDEF(CEE_LDIND_I2, "ldind.i2", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x48, NEXT) +OPDEF(CEE_LDIND_U2, "ldind.u2", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x49, NEXT) +OPDEF(CEE_LDIND_I4, "ldind.i4", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x4A, NEXT) +OPDEF(CEE_LDIND_U4, "ldind.u4", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x4B, NEXT) +OPDEF(CEE_LDIND_I8, "ldind.i8", PopI, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x4C, NEXT) +OPDEF(CEE_LDIND_I, "ldind.i", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x4D, NEXT) +OPDEF(CEE_LDIND_R4, "ldind.r4", PopI, PushR4, InlineNone, IPrimitive, 1, 0xFF, 0x4E, NEXT) +OPDEF(CEE_LDIND_R8, "ldind.r8", PopI, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0x4F, NEXT) +OPDEF(CEE_LDIND_REF, "ldind.ref", PopI, PushRef, InlineNone, IPrimitive, 1, 0xFF, 0x50, NEXT) +OPDEF(CEE_STIND_REF, "stind.ref", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x51, NEXT) +OPDEF(CEE_STIND_I1, "stind.i1", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x52, NEXT) +OPDEF(CEE_STIND_I2, "stind.i2", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x53, NEXT) +OPDEF(CEE_STIND_I4, "stind.i4", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x54, NEXT) +OPDEF(CEE_STIND_I8, "stind.i8", PopI+PopI8, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x55, NEXT) +OPDEF(CEE_STIND_R4, "stind.r4", PopI+PopR4, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x56, NEXT) +OPDEF(CEE_STIND_R8, "stind.r8", PopI+PopR8, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x57, NEXT) +OPDEF(CEE_ADD, "add", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x58, NEXT) +OPDEF(CEE_SUB, "sub", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x59, NEXT) +OPDEF(CEE_MUL, "mul", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5A, NEXT) +OPDEF(CEE_DIV, "div", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5B, NEXT) +OPDEF(CEE_DIV_UN, "div.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5C, NEXT) +OPDEF(CEE_REM, "rem", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5D, NEXT) +OPDEF(CEE_REM_UN, "rem.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5E, NEXT) +OPDEF(CEE_AND, "and", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5F, NEXT) +OPDEF(CEE_OR, "or", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x60, NEXT) +OPDEF(CEE_XOR, "xor", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x61, NEXT) +OPDEF(CEE_SHL, "shl", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x62, NEXT) +OPDEF(CEE_SHR, "shr", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x63, NEXT) +OPDEF(CEE_SHR_UN, "shr.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x64, NEXT) +OPDEF(CEE_NEG, "neg", Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x65, NEXT) +OPDEF(CEE_NOT, "not", Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x66, NEXT) +OPDEF(CEE_CONV_I1, "conv.i1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x67, NEXT) +OPDEF(CEE_CONV_I2, "conv.i2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x68, NEXT) +OPDEF(CEE_CONV_I4, "conv.i4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x69, NEXT) +OPDEF(CEE_CONV_I8, "conv.i8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x6A, NEXT) +OPDEF(CEE_CONV_R4, "conv.r4", Pop1, PushR4, InlineNone, IPrimitive, 1, 0xFF, 0x6B, NEXT) +OPDEF(CEE_CONV_R8, "conv.r8", Pop1, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0x6C, NEXT) +OPDEF(CEE_CONV_U4, "conv.u4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x6D, NEXT) +OPDEF(CEE_CONV_U8, "conv.u8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x6E, NEXT) +OPDEF(CEE_CALLVIRT, "callvirt", VarPop, VarPush, InlineMethod, IObjModel, 1, 0xFF, 0x6F, CALL) +OPDEF(CEE_CPOBJ, "cpobj", PopI+PopI, Push0, InlineType, IObjModel, 1, 0xFF, 0x70, NEXT) +OPDEF(CEE_LDOBJ, "ldobj", PopI, Push1, InlineType, IObjModel, 1, 0xFF, 0x71, NEXT) +OPDEF(CEE_LDSTR, "ldstr", Pop0, PushRef, InlineString, IObjModel, 1, 0xFF, 0x72, NEXT) +OPDEF(CEE_NEWOBJ, "newobj", VarPop, PushRef, InlineMethod, IObjModel, 1, 0xFF, 0x73, CALL) +OPDEF(CEE_CASTCLASS, "castclass", PopRef, PushRef, InlineType, IObjModel, 1, 0xFF, 0x74, NEXT) +OPDEF(CEE_ISINST, "isinst", PopRef, PushI, InlineType, IObjModel, 1, 0xFF, 0x75, NEXT) +OPDEF(CEE_CONV_R_UN, "conv.r.un", Pop1, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0x76, NEXT) +OPDEF(CEE_UNUSED58, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x77, NEXT) +OPDEF(CEE_UNUSED1, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x78, NEXT) +OPDEF(CEE_UNBOX, "unbox", PopRef, PushI, InlineType, IPrimitive, 1, 0xFF, 0x79, NEXT) +OPDEF(CEE_THROW, "throw", PopRef, Push0, InlineNone, IObjModel, 1, 0xFF, 0x7A, THROW) +OPDEF(CEE_LDFLD, "ldfld", PopRef, Push1, InlineField, IObjModel, 1, 0xFF, 0x7B, NEXT) +OPDEF(CEE_LDFLDA, "ldflda", PopRef, PushI, InlineField, IObjModel, 1, 0xFF, 0x7C, NEXT) +OPDEF(CEE_STFLD, "stfld", PopRef+Pop1, Push0, InlineField, IObjModel, 1, 0xFF, 0x7D, NEXT) +OPDEF(CEE_LDSFLD, "ldsfld", Pop0, Push1, InlineField, IObjModel, 1, 0xFF, 0x7E, NEXT) +OPDEF(CEE_LDSFLDA, "ldsflda", Pop0, PushI, InlineField, IObjModel, 1, 0xFF, 0x7F, NEXT) +OPDEF(CEE_STSFLD, "stsfld", Pop1, Push0, InlineField, IObjModel, 1, 0xFF, 0x80, NEXT) +OPDEF(CEE_STOBJ, "stobj", PopI+Pop1, Push0, InlineType, IPrimitive, 1, 0xFF, 0x81, NEXT) +OPDEF(CEE_CONV_OVF_I1_UN, "conv.ovf.i1.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x82, NEXT) +OPDEF(CEE_CONV_OVF_I2_UN, "conv.ovf.i2.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x83, NEXT) +OPDEF(CEE_CONV_OVF_I4_UN, "conv.ovf.i4.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x84, NEXT) +OPDEF(CEE_CONV_OVF_I8_UN, "conv.ovf.i8.un", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x85, NEXT) +OPDEF(CEE_CONV_OVF_U1_UN, "conv.ovf.u1.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x86, NEXT) +OPDEF(CEE_CONV_OVF_U2_UN, "conv.ovf.u2.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x87, NEXT) +OPDEF(CEE_CONV_OVF_U4_UN, "conv.ovf.u4.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x88, NEXT) +OPDEF(CEE_CONV_OVF_U8_UN, "conv.ovf.u8.un", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x89, NEXT) +OPDEF(CEE_CONV_OVF_I_UN, "conv.ovf.i.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x8A, NEXT) +OPDEF(CEE_CONV_OVF_U_UN, "conv.ovf.u.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x8B, NEXT) +OPDEF(CEE_BOX, "box", Pop1, PushRef, InlineType, IPrimitive, 1, 0xFF, 0x8C, NEXT) +OPDEF(CEE_NEWARR, "newarr", PopI, PushRef, InlineType, IObjModel, 1, 0xFF, 0x8D, NEXT) +OPDEF(CEE_LDLEN, "ldlen", PopRef, PushI, InlineNone, IObjModel, 1, 0xFF, 0x8E, NEXT) +OPDEF(CEE_LDELEMA, "ldelema", PopRef+PopI, PushI, InlineType, IObjModel, 1, 0xFF, 0x8F, NEXT) +OPDEF(CEE_LDELEM_I1, "ldelem.i1", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x90, NEXT) +OPDEF(CEE_LDELEM_U1, "ldelem.u1", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x91, NEXT) +OPDEF(CEE_LDELEM_I2, "ldelem.i2", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x92, NEXT) +OPDEF(CEE_LDELEM_U2, "ldelem.u2", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x93, NEXT) +OPDEF(CEE_LDELEM_I4, "ldelem.i4", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x94, NEXT) +OPDEF(CEE_LDELEM_U4, "ldelem.u4", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x95, NEXT) +OPDEF(CEE_LDELEM_I8, "ldelem.i8", PopRef+PopI, PushI8, InlineNone, IObjModel, 1, 0xFF, 0x96, NEXT) +OPDEF(CEE_LDELEM_I, "ldelem.i", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x97, NEXT) +OPDEF(CEE_LDELEM_R4, "ldelem.r4", PopRef+PopI, PushR4, InlineNone, IObjModel, 1, 0xFF, 0x98, NEXT) +OPDEF(CEE_LDELEM_R8, "ldelem.r8", PopRef+PopI, PushR8, InlineNone, IObjModel, 1, 0xFF, 0x99, NEXT) +OPDEF(CEE_LDELEM_REF, "ldelem.ref", PopRef+PopI, PushRef, InlineNone, IObjModel, 1, 0xFF, 0x9A, NEXT) +OPDEF(CEE_STELEM_I, "stelem.i", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9B, NEXT) +OPDEF(CEE_STELEM_I1, "stelem.i1", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9C, NEXT) +OPDEF(CEE_STELEM_I2, "stelem.i2", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9D, NEXT) +OPDEF(CEE_STELEM_I4, "stelem.i4", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9E, NEXT) +OPDEF(CEE_STELEM_I8, "stelem.i8", PopRef+PopI+PopI8, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9F, NEXT) +OPDEF(CEE_STELEM_R4, "stelem.r4", PopRef+PopI+PopR4, Push0, InlineNone, IObjModel, 1, 0xFF, 0xA0, NEXT) +OPDEF(CEE_STELEM_R8, "stelem.r8", PopRef+PopI+PopR8, Push0, InlineNone, IObjModel, 1, 0xFF, 0xA1, NEXT) +OPDEF(CEE_STELEM_REF, "stelem.ref", PopRef+PopI+PopRef, Push0, InlineNone, IObjModel, 1, 0xFF, 0xA2, NEXT) +OPDEF(CEE_LDELEM, "ldelem", PopRef+PopI, Push1, InlineType, IObjModel, 1, 0xFF, 0xA3, NEXT) +OPDEF(CEE_STELEM, "stelem", PopRef+PopI+Pop1, Push0, InlineType, IObjModel, 1, 0xFF, 0xA4, NEXT) +OPDEF(CEE_UNBOX_ANY, "unbox.any", PopRef, Push1, InlineType, IObjModel, 1, 0xFF, 0xA5, NEXT) +OPDEF(CEE_UNUSED5, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xA6, NEXT) +OPDEF(CEE_UNUSED6, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xA7, NEXT) +OPDEF(CEE_UNUSED7, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xA8, NEXT) +OPDEF(CEE_UNUSED8, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xA9, NEXT) +OPDEF(CEE_UNUSED9, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAA, NEXT) +OPDEF(CEE_UNUSED10, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAB, NEXT) +OPDEF(CEE_UNUSED11, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAC, NEXT) +OPDEF(CEE_UNUSED12, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAD, NEXT) +OPDEF(CEE_UNUSED13, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAE, NEXT) +OPDEF(CEE_UNUSED14, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAF, NEXT) +OPDEF(CEE_UNUSED15, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xB0, NEXT) +OPDEF(CEE_UNUSED16, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xB1, NEXT) +OPDEF(CEE_UNUSED17, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xB2, NEXT) +OPDEF(CEE_CONV_OVF_I1, "conv.ovf.i1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB3, NEXT) +OPDEF(CEE_CONV_OVF_U1, "conv.ovf.u1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB4, NEXT) +OPDEF(CEE_CONV_OVF_I2, "conv.ovf.i2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB5, NEXT) +OPDEF(CEE_CONV_OVF_U2, "conv.ovf.u2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB6, NEXT) +OPDEF(CEE_CONV_OVF_I4, "conv.ovf.i4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB7, NEXT) +OPDEF(CEE_CONV_OVF_U4, "conv.ovf.u4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB8, NEXT) +OPDEF(CEE_CONV_OVF_I8, "conv.ovf.i8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0xB9, NEXT) +OPDEF(CEE_CONV_OVF_U8, "conv.ovf.u8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0xBA, NEXT) +OPDEF(CEE_UNUSED50, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBB, NEXT) +OPDEF(CEE_UNUSED18, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBC, NEXT) +OPDEF(CEE_UNUSED19, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBD, NEXT) +OPDEF(CEE_UNUSED20, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBE, NEXT) +OPDEF(CEE_UNUSED21, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBF, NEXT) +OPDEF(CEE_UNUSED22, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC0, NEXT) +OPDEF(CEE_UNUSED23, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC1, NEXT) +OPDEF(CEE_REFANYVAL, "refanyval", Pop1, PushI, InlineType, IPrimitive, 1, 0xFF, 0xC2, NEXT) +OPDEF(CEE_CKFINITE, "ckfinite", Pop1, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0xC3, NEXT) +OPDEF(CEE_UNUSED24, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC4, NEXT) +OPDEF(CEE_UNUSED25, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC5, NEXT) +OPDEF(CEE_MKREFANY, "mkrefany", PopI, Push1, InlineType, IPrimitive, 1, 0xFF, 0xC6, NEXT) +OPDEF(CEE_UNUSED59, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC7, NEXT) +OPDEF(CEE_UNUSED60, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC8, NEXT) +OPDEF(CEE_UNUSED61, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC9, NEXT) +OPDEF(CEE_UNUSED62, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCA, NEXT) +OPDEF(CEE_UNUSED63, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCB, NEXT) +OPDEF(CEE_UNUSED64, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCC, NEXT) +OPDEF(CEE_UNUSED65, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCD, NEXT) +OPDEF(CEE_UNUSED66, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCE, NEXT) +OPDEF(CEE_UNUSED67, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCF, NEXT) +OPDEF(CEE_LDTOKEN, "ldtoken", Pop0, PushI, InlineTok, IPrimitive, 1, 0xFF, 0xD0, NEXT) +OPDEF(CEE_CONV_U2, "conv.u2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD1, NEXT) +OPDEF(CEE_CONV_U1, "conv.u1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD2, NEXT) +OPDEF(CEE_CONV_I, "conv.i", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD3, NEXT) +OPDEF(CEE_CONV_OVF_I, "conv.ovf.i", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD4, NEXT) +OPDEF(CEE_CONV_OVF_U, "conv.ovf.u", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD5, NEXT) +OPDEF(CEE_ADD_OVF, "add.ovf", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD6, NEXT) +OPDEF(CEE_ADD_OVF_UN, "add.ovf.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD7, NEXT) +OPDEF(CEE_MUL_OVF, "mul.ovf", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD8, NEXT) +OPDEF(CEE_MUL_OVF_UN, "mul.ovf.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD9, NEXT) +OPDEF(CEE_SUB_OVF, "sub.ovf", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xDA, NEXT) +OPDEF(CEE_SUB_OVF_UN, "sub.ovf.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xDB, NEXT) +OPDEF(CEE_ENDFINALLY, "endfinally", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xDC, RETURN) +OPDEF(CEE_LEAVE, "leave", Pop0, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0xDD, BRANCH) +OPDEF(CEE_LEAVE_S, "leave.s", Pop0, Push0, ShortInlineBrTarget,IPrimitive, 1, 0xFF, 0xDE, BRANCH) +OPDEF(CEE_STIND_I, "stind.i", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xDF, NEXT) +OPDEF(CEE_CONV_U, "conv.u", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xE0, NEXT) +OPDEF(CEE_UNUSED26, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE1, NEXT) +OPDEF(CEE_UNUSED27, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE2, NEXT) +OPDEF(CEE_UNUSED28, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE3, NEXT) +OPDEF(CEE_UNUSED29, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE4, NEXT) +OPDEF(CEE_UNUSED30, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE5, NEXT) +OPDEF(CEE_UNUSED31, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE6, NEXT) +OPDEF(CEE_UNUSED32, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE7, NEXT) +OPDEF(CEE_UNUSED33, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE8, NEXT) +OPDEF(CEE_UNUSED34, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE9, NEXT) +OPDEF(CEE_UNUSED35, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEA, NEXT) +OPDEF(CEE_UNUSED36, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEB, NEXT) +OPDEF(CEE_UNUSED37, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEC, NEXT) +OPDEF(CEE_UNUSED38, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xED, NEXT) +OPDEF(CEE_UNUSED39, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEE, NEXT) +OPDEF(CEE_UNUSED40, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEF, NEXT) +OPDEF(CEE_UNUSED41, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF0, NEXT) +OPDEF(CEE_UNUSED42, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF1, NEXT) +OPDEF(CEE_UNUSED43, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF2, NEXT) +OPDEF(CEE_UNUSED44, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF3, NEXT) +OPDEF(CEE_UNUSED45, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF4, NEXT) +OPDEF(CEE_UNUSED46, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF5, NEXT) +OPDEF(CEE_UNUSED47, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF6, NEXT) +OPDEF(CEE_UNUSED48, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF7, NEXT) +OPDEF(CEE_PREFIX7, "prefix7", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xF8, META) +OPDEF(CEE_PREFIX6, "prefix6", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xF9, META) +OPDEF(CEE_PREFIX5, "prefix5", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFA, META) +OPDEF(CEE_PREFIX4, "prefix4", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFB, META) +OPDEF(CEE_PREFIX3, "prefix3", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFC, META) +OPDEF(CEE_PREFIX2, "prefix2", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFD, META) +OPDEF(CEE_PREFIX1, "prefix1", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFE, META) +OPDEF(CEE_PREFIXREF, "prefixref", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFF, META) + +OPDEF(CEE_ARGLIST, "arglist", Pop0, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x00, NEXT) +OPDEF(CEE_CEQ, "ceq", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x01, NEXT) +OPDEF(CEE_CGT, "cgt", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x02, NEXT) +OPDEF(CEE_CGT_UN, "cgt.un", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x03, NEXT) +OPDEF(CEE_CLT, "clt", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x04, NEXT) +OPDEF(CEE_CLT_UN, "clt.un", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x05, NEXT) +OPDEF(CEE_LDFTN, "ldftn", Pop0, PushI, InlineMethod, IPrimitive, 2, 0xFE, 0x06, NEXT) +OPDEF(CEE_LDVIRTFTN, "ldvirtftn", PopRef, PushI, InlineMethod, IPrimitive, 2, 0xFE, 0x07, NEXT) +OPDEF(CEE_UNUSED56, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x08, NEXT) +OPDEF(CEE_LDARG, "ldarg", Pop0, Push1, InlineVar, IPrimitive, 2, 0xFE, 0x09, NEXT) +OPDEF(CEE_LDARGA, "ldarga", Pop0, PushI, InlineVar, IPrimitive, 2, 0xFE, 0x0A, NEXT) +OPDEF(CEE_STARG, "starg", Pop1, Push0, InlineVar, IPrimitive, 2, 0xFE, 0x0B, NEXT) +OPDEF(CEE_LDLOC, "ldloc", Pop0, Push1, InlineVar, IPrimitive, 2, 0xFE, 0x0C, NEXT) +OPDEF(CEE_LDLOCA, "ldloca", Pop0, PushI, InlineVar, IPrimitive, 2, 0xFE, 0x0D, NEXT) +OPDEF(CEE_STLOC, "stloc", Pop1, Push0, InlineVar, IPrimitive, 2, 0xFE, 0x0E, NEXT) +OPDEF(CEE_LOCALLOC, "localloc", PopI, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x0F, NEXT) +OPDEF(CEE_UNUSED57, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x10, NEXT) +OPDEF(CEE_ENDFILTER, "endfilter", PopI, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x11, RETURN) +OPDEF(CEE_UNALIGNED, "unaligned.", Pop0, Push0, ShortInlineI, IPrefix, 2, 0xFE, 0x12, META) +OPDEF(CEE_VOLATILE, "volatile.", Pop0, Push0, InlineNone, IPrefix, 2, 0xFE, 0x13, META) +OPDEF(CEE_TAILCALL, "tail.", Pop0, Push0, InlineNone, IPrefix, 2, 0xFE, 0x14, META) +OPDEF(CEE_INITOBJ, "initobj", PopI, Push0, InlineType, IObjModel, 2, 0xFE, 0x15, NEXT) +OPDEF(CEE_CONSTRAINED, "constrained.", Pop0, Push0, InlineType, IPrefix, 2, 0xFE, 0x16, META) +OPDEF(CEE_CPBLK, "cpblk", PopI+PopI+PopI, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x17, NEXT) +OPDEF(CEE_INITBLK, "initblk", PopI+PopI+PopI, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x18, NEXT) +OPDEF(CEE_UNUSED69, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x19, NEXT) +OPDEF(CEE_RETHROW, "rethrow", Pop0, Push0, InlineNone, IObjModel, 2, 0xFE, 0x1A, THROW) +OPDEF(CEE_UNUSED51, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x1B, NEXT) +OPDEF(CEE_SIZEOF, "sizeof", Pop0, PushI, InlineType, IPrimitive, 2, 0xFE, 0x1C, NEXT) +OPDEF(CEE_REFANYTYPE, "refanytype", Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x1D, NEXT) +OPDEF(CEE_READONLY, "readonly.", Pop0, Push0, InlineNone, IPrefix, 2, 0xFE, 0x1E, META) +OPDEF(CEE_UNUSED53, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x1F, NEXT) +OPDEF(CEE_UNUSED54, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x20, NEXT) +OPDEF(CEE_UNUSED55, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x21, NEXT) +OPDEF(CEE_UNUSED70, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x22, NEXT) + +// These are not real opcodes, but they are handy internally in the EE + +OPDEF(CEE_ILLEGAL, "illegal", Pop0, Push0, InlineNone, IInternal, 0, MOOT, MOOT, META) +OPDEF(CEE_MACRO_END, "endmac", Pop0, Push0, InlineNone, IInternal, 0, MOOT, MOOT, META) + +#ifndef OPALIAS +#define _OPALIAS_DEFINED_ +#define OPALIAS(canonicalName, stringName, realOpcode) +#endif + +OPALIAS(CEE_BRNULL, "brnull", CEE_BRFALSE) +OPALIAS(CEE_BRNULL_S, "brnull.s", CEE_BRFALSE_S) +OPALIAS(CEE_BRZERO, "brzero", CEE_BRFALSE) +OPALIAS(CEE_BRZERO_S, "brzero.s", CEE_BRFALSE_S) +OPALIAS(CEE_BRINST, "brinst", CEE_BRTRUE) +OPALIAS(CEE_BRINST_S, "brinst.s", CEE_BRTRUE_S) +OPALIAS(CEE_LDIND_U8, "ldind.u8", CEE_LDIND_I8) +OPALIAS(CEE_LDELEM_U8, "ldelem.u8", CEE_LDELEM_I8) +OPALIAS(CEE_LDELEM_ANY, "ldelem.any", CEE_LDELEM) +OPALIAS(CEE_STELEM_ANY, "stelem.any", CEE_STELEM) +OPALIAS(CEE_LDC_I4_M1x, "ldc.i4.M1", CEE_LDC_I4_M1) +OPALIAS(CEE_ENDFAULT, "endfault", CEE_ENDFINALLY) + +#ifdef _OPALIAS_DEFINED_ +#undef OPALIAS +#undef _OPALIAS_DEFINED_ +#endif + diff --git a/src/CLR/Messaging/Messaging.cpp b/src/CLR/Messaging/Messaging.cpp index ff4fb75e16..2ce062b8b3 100644 --- a/src/CLR/Messaging/Messaging.cpp +++ b/src/CLR/Messaging/Messaging.cpp @@ -1,13 +1,10 @@ // // Copyright (c) 2017 The nanoFramework project contributors -// Copyright (c) Microsoft Corporation. All rights reserved. +// Portions Copyright (c) Microsoft Corporation. All rights reserved. // See LICENSE file in the project root for full license information. // -#include "..\core\Core.h" -#include -#include - -#include +#include +#include //////////////////////////////////////////////////////////////////////////////////////////////////// #if 0 @@ -417,9 +414,7 @@ bool CLR_Messaging::ProcessPayload( WP_Message* msg ) } //--// -#if defined(NETMF_TARGET_BIG_ENDIAN) - SwapEndian( msg, msg->m_payload, msg->m_header.m_size, false ); -#endif + const CLR_Messaging_CommandHandlerLookups* tables; int tableCount = 0; @@ -532,13 +527,8 @@ bool CLR_Messaging::TransmitMessage( const WP_Message* msg, bool fQueue ) UINT32 payloadSize; UINT32 flags; -#if !defined(NETMF_TARGET_BIG_ENDIAN) payloadSize = msg->m_header.m_size; flags = msg->m_header.m_flags; -#else - payloadSize = ::SwapEndian( msg->m_header.m_size ); - flags = ::SwapEndian( msg->m_header.m_flags ); -#endif if(DebuggerPort_Write( m_port, (char*)&msg->m_header, sizeof(msg->m_header) ) != sizeof(msg->m_header)) return false; @@ -651,11 +641,7 @@ void CLR_Messaging::ReplyToCommand( WP_Message* msg, bool fSuccess, bool fCritic size = 0; } - msgReply.Initialize( &m_controller ); -#if defined(NETMF_TARGET_BIG_ENDIAN) - SwapEndian( msg, ptr, size, true ); -#endif msgReply.PrepareReply( msg->m_header, flags, size, (UINT8*)ptr ); @@ -667,402 +653,3 @@ void CLR_Messaging::ReplyToCommand( WP_Message* msg, bool fSuccess, bool fCritic NATIVE_PROFILE_CLR_MESSAGING(); ReplyToCommand( msg, fSuccess, fCritical, NULL, 0 ); } - -//--// -#if defined(NETMF_TARGET_BIG_ENDIAN) -UINT32 CLR_Messaging::SwapEndianPattern( UINT8* &buffer, UINT32 size, UINT32 count ) -{ - UINT32 consumed=0; - - if (1==size) - { - // Do no swapping, just increment pointer - buffer += (size*count); - consumed = size*count; - } - else - { - while (count--) - { - switch ( size ) - { - case 1 : - - break; - case 2 : - { - UINT16 *p16 = (UINT16 *)buffer; - *p16 = ::SwapEndian( *p16 ); - } - break; - case 4 : - { - UINT32 *p32 = (UINT32 *)buffer; - *p32 = ::SwapEndian( *p32 ); - } - break; - case 8 : - { - UINT64 *p64 = (UINT64 *)buffer; - *p64 = ::SwapEndian( *p64 ); - } - break; - } - buffer += size; - consumed += size; - } - } - return consumed; -} -void CLR_Messaging::SwapDebuggingValue( UINT8* &payload, UINT32 payloadSize ) -{ - UINT32 count = payloadSize / sizeof(CLR_DBG_Commands::Debugging_Value); - while (count--) - { - SwapEndianPattern( payload, sizeof(UINT32), 4); - SwapEndianPattern( payload, 1, 128 ); - SwapEndianPattern( payload, sizeof(UINT32), 2); - SwapEndianPattern( payload, sizeof(UINT32), 1); - SwapEndianPattern( payload, sizeof(UINT32), 2); - SwapEndianPattern( payload, sizeof(UINT32), 1); - SwapEndianPattern( payload, sizeof(UINT32), 2); - } -} - -void CLR_Messaging::SwapEndian( WP_Message* msg, void* ptr, int size, bool fReply ) -{ - - UINT8 *payload = (UINT8*)ptr; - UINT32 payloadSize = size ; - - ASSERT(sizeof(int)==sizeof(UINT32)); - - // Some commands may have a zero payload if not supproted, protect here. - if (NULL==ptr) return; - - switch ( msg->m_header.m_cmd ) - { - case CLR_DBG_Commands::c_Monitor_Ping : - SwapEndianPattern( payload, sizeof(UINT32), 2 ); - break; - - case CLR_DBG_Commands::c_Monitor_Message : - // string (no NULL termination) - nothing to do - break; - case CLR_DBG_Commands::c_Monitor_ReadMemory : - SwapEndianPattern( payload, sizeof(UINT32), fReply?0:2 ); - break; - case CLR_DBG_Commands::c_Monitor_WriteMemory : - SwapEndianPattern( payload, sizeof(UINT32), fReply?0:2 ); - break; - case CLR_DBG_Commands::c_Monitor_CheckMemory : - SwapEndianPattern( payload, sizeof(UINT32), fReply?1:2 ); - break; - case CLR_DBG_Commands::c_Monitor_EraseMemory : - SwapEndianPattern( payload, sizeof(UINT32), fReply?0:2 ); - break; - case CLR_DBG_Commands::c_Monitor_Execute : - SwapEndianPattern( payload, sizeof(UINT32), fReply?0:1 ); - break; - case CLR_DBG_Commands::c_Monitor_Reboot : - SwapEndianPattern( payload, sizeof(UINT32), fReply?0:1 ); - break; - case CLR_DBG_Commands::c_Monitor_MemoryMap : - // do for each range entry - SwapEndianPattern( payload, sizeof(UINT32), payloadSize/sizeof(UINT32) ); - break; - case CLR_DBG_Commands::c_Monitor_ProgramExit : - // no payload - break; - case CLR_DBG_Commands::c_Monitor_CheckSignature : - // Monitor_Signature struct - SwapEndianPattern( payload, sizeof(UINT32), fReply?0:2 ); - break; - case CLR_DBG_Commands::c_Monitor_DeploymentMap : - if (fReply) - { - SwapEndianPattern( payload, sizeof(UINT32), 3 ); - } - break; - case CLR_DBG_Commands::c_Monitor_FlashSectorMap : - SwapEndianPattern( payload, sizeof(UINT32), fReply?payloadSize/sizeof(UINT32):0 ); - break; - case CLR_DBG_Commands::c_Monitor_SignatureKeyUpdate : - if (!fReply) - { - SwapEndianPattern( payload, sizeof(UINT32), 1 ); - SwapEndianPattern( payload, 1, 128 ); - SwapEndianPattern( payload, 1, 260 ); - SwapEndianPattern( payload, sizeof(UINT32), 1 ); - } - break; - case CLR_DBG_Commands::c_Monitor_OemInfo : - // swap the version, leave the rest - SwapEndianPattern( payload, sizeof(UINT16), fReply?4:0 ); - break; - - case CLR_DBG_Commands::c_Debugging_Execution_BasePtr : - SwapEndianPattern( payload, sizeof(UINT32), fReply?1:0 ); - break; - case CLR_DBG_Commands::c_Debugging_Execution_ChangeConditions : - SwapEndianPattern( payload, sizeof(UINT32), fReply?1:2 ); - break; - case CLR_DBG_Commands::c_Debugging_Execution_SecurityKey : - // NOP - break; - case CLR_DBG_Commands::c_Debugging_Execution_Unlock : - // NOP - break; - case CLR_DBG_Commands::c_Debugging_Execution_Allocate : - SwapEndianPattern( payload, sizeof(UINT32), fReply?1:1 ); - break; - - case CLR_DBG_Commands::c_Debugging_UpgradeToSsl: - SwapEndianPattern( payload, sizeof(UINT32), 1 ); - break; - - case CLR_DBG_Commands::c_Debugging_MFUpdate_Start: - if(!fReply) - { - SwapEndianPattern( payload, 1, 64 ); - SwapEndianPattern( payload, sizeof(UINT32), 5 ); - SwapEndianPattern( payload, sizeof(UINT16), 2 ); - } - else - { - SwapEndianPattern( payload, sizeof(UINT32), 1 ); - } - break; - case CLR_DBG_Commands::c_Debugging_MFUpdate_AuthCommand: - SwapEndianPattern( payload, sizeof(UINT32), fReply ? 2 : 3 ); - break; - case CLR_DBG_Commands::c_Debugging_MFUpdate_Authenticate: - SwapEndianPattern( payload, sizeof(UINT32), fReply ? 1 : 2 ); - break; - case CLR_DBG_Commands::c_Debugging_MFUpdate_AddPacket: - SwapEndianPattern( payload, sizeof(UINT32), fReply?4:1 ); - break; - case CLR_DBG_Commands::c_Debugging_MFUpdate_GetMissingPkts: - SwapEndianPattern( payload, sizeof(UINT32), fReply ? 2 : 1 ); - break; - case CLR_DBG_Commands::c_Debugging_MFUpdate_Install: - SwapEndianPattern( payload, sizeof(UINT32), fReply?2:1 ); - break; - - case CLR_DBG_Commands::c_Debugging_Execution_Breakpoints : - if (!fReply) - { - payloadSize -= SwapEndianPattern( payload, sizeof(UINT32), 1 ); - while (payloadSize) - { - payloadSize -= SwapEndianPattern( payload, sizeof(UINT16), 2 ); - payloadSize -= SwapEndianPattern( payload, sizeof(UINT32), 8 ); - } - } - break; - case CLR_DBG_Commands::c_Debugging_Execution_BreakpointHit : - if (!fReply) - { - SwapEndianPattern( payload, sizeof(UINT16), 2 ); - SwapEndianPattern( payload, sizeof(UINT32), 8 ); - } - break; - case CLR_DBG_Commands::c_Debugging_Execution_BreakpointStatus : - if (fReply) - { - SwapEndianPattern( payload, sizeof(UINT16), 2 ); - SwapEndianPattern( payload, sizeof(UINT32), 8 ); - } - break; - case CLR_DBG_Commands::c_Debugging_Execution_QueryCLRCapabilities : - { - if (!fReply) - { - SwapEndianPattern( payload, sizeof(UINT32), 1 ); - } - else - { - CLR_UINT32 cmd = ((CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities*)msg->m_payload)->m_cmd; - // Swap the union according to the cmd - if (CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityFlags==cmd) { SwapEndianPattern( payload, sizeof(UINT32), 1 ); } - if (CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityLCD==cmd) { SwapEndianPattern( payload, sizeof(UINT32), 3 ); } - if (CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_ClrInfo==cmd) - { - SwapEndianPattern( payload, sizeof(UINT16), 4 ); - SwapEndianPattern( payload, 1, 64-sizeof(MFVersion) ); - SwapEndianPattern( payload, sizeof(UINT16), 4 ); - } - if (CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_SolutionReleaseInfo==cmd) - { - SwapEndianPattern( payload, sizeof(UINT16), 4 ); - } - if (CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_CapabilityVersion==cmd) - { - SwapEndianPattern( payload, 1, 20 ); - SwapEndianPattern( payload, sizeof(UINT32), 1 ); - } - if (CLR_DBG_Commands::Debugging_Execution_QueryCLRCapabilities::c_HalSystemInfo==cmd) - { - SwapEndianPattern( payload, sizeof(UINT16), 4 ); - SwapEndianPattern( payload, 1, 64-sizeof(MFVersion) ); - SwapEndianPattern( payload, 1, 2 ); - SwapEndianPattern( payload, sizeof(UINT16), 1 ); - } - } - } - break; -#if 0 - case CLR_DBG_Commands::c_Debugging_Messaging_Query : - SwapEndianPattern( payload, sizeof(UINT32), fReply?6:5 ); - break; - case CLR_DBG_Commands::c_Debugging_Messaging_Send : - SwapEndianPattern( payload, sizeof(UINT32), fReply?6:5 ); - break; - case CLR_DBG_Commands::c_Debugging_Messaging_Reply : - SwapEndianPattern( payload, sizeof(UINT32), fReply?6:5 ); - break; -#endif - case CLR_DBG_Commands::c_Debugging_Execution_SetCurrentAppDomain : - SwapEndianPattern( payload, sizeof(UINT32), fReply?0:1 ); - break; - case CLR_DBG_Commands::c_Debugging_Thread_Create : - SwapEndianPattern( payload, sizeof(UINT32), fReply?1:3 ); - break; - case CLR_DBG_Commands::c_Debugging_Thread_List : - SwapEndianPattern( payload, sizeof(UINT32), fReply?payloadSize/sizeof(UINT32):0 ); - break; - case CLR_DBG_Commands::c_Debugging_Thread_Stack : - SwapEndianPattern( payload, sizeof(UINT32), fReply?payloadSize/sizeof(UINT32):1 ); - break; - case CLR_DBG_Commands::c_Debugging_Thread_Kill : - SwapEndianPattern( payload, sizeof(UINT32), fReply?1:1 ); - break; - case CLR_DBG_Commands::c_Debugging_Thread_Suspend : - SwapEndianPattern( payload, sizeof(UINT32), fReply?0:1 ); - break; - case CLR_DBG_Commands::c_Debugging_Thread_Resume : - SwapEndianPattern( payload, sizeof(UINT32), fReply?0:1 ); - break; - case CLR_DBG_Commands::c_Debugging_Thread_GetException : - if (!fReply) SwapEndianPattern( payload, sizeof(UINT32), 1 ); - else SwapDebuggingValue( payload, payloadSize ); - break; - case CLR_DBG_Commands::c_Debugging_Thread_Unwind : - SwapEndianPattern( payload, sizeof(UINT32), fReply?0:2 ); - break; - case CLR_DBG_Commands::c_Debugging_Thread_CreateEx : - SwapEndianPattern( payload, sizeof(UINT32), fReply?1:3 ); - break; - case CLR_DBG_Commands::c_Debugging_Stack_Info : - SwapEndianPattern( payload, sizeof(UINT32), fReply?0:2 ); - SwapEndianPattern( payload, sizeof(UINT32), fReply?5:0 ); - break; - case CLR_DBG_Commands::c_Debugging_Stack_SetIP : - SwapEndianPattern( payload, sizeof(UINT32), fReply?0:4 ); - break; - case CLR_DBG_Commands::c_Debugging_Value_ResizeScratchPad : - SwapEndianPattern( payload, sizeof(UINT32), fReply?0:1 ); - break; - case CLR_DBG_Commands::c_Debugging_Value_GetStack : - if (!fReply) SwapEndianPattern( payload, sizeof(UINT32), 4 ); - else SwapDebuggingValue( payload, payloadSize ); - break; - case CLR_DBG_Commands::c_Debugging_Value_GetField : - if (!fReply) SwapEndianPattern( payload, sizeof(UINT32), 3 ); - else SwapDebuggingValue( payload, payloadSize ); - break; - case CLR_DBG_Commands::c_Debugging_Value_GetArray : - if (!fReply) SwapEndianPattern( payload, sizeof(UINT32), 2 ); - else SwapDebuggingValue( payload, payloadSize ); - break; - case CLR_DBG_Commands::c_Debugging_Value_GetBlock : - if (!fReply) SwapEndianPattern( payload, sizeof(UINT32), 1 ); - else SwapDebuggingValue( payload, payloadSize ); - break; - case CLR_DBG_Commands::c_Debugging_Value_GetScratchPad : - if (!fReply) SwapEndianPattern( payload, sizeof(UINT32), 1 ); - else SwapDebuggingValue( payload, payloadSize ); - break; - case CLR_DBG_Commands::c_Debugging_Value_SetBlock : - SwapEndianPattern( payload, sizeof(UINT32), fReply?0:2 ); - break; - case CLR_DBG_Commands::c_Debugging_Value_SetArray : - SwapEndianPattern( payload, sizeof(UINT32), fReply?0:2 ); - break; - case CLR_DBG_Commands::c_Debugging_Value_AllocateObject : - if (!fReply) SwapEndianPattern( payload, sizeof(UINT32), 2 ); - else SwapDebuggingValue( payload, payloadSize ); - break; - case CLR_DBG_Commands::c_Debugging_Value_AllocateString : - if (!fReply) SwapEndianPattern( payload, sizeof(UINT32), 2 ); - else SwapDebuggingValue( payload, payloadSize ); - break; - case CLR_DBG_Commands::c_Debugging_Value_AllocateArray : - if (!fReply) SwapEndianPattern( payload, sizeof(UINT32), 4 ); - else SwapDebuggingValue( payload, payloadSize ); - break; - case CLR_DBG_Commands::c_Debugging_Value_Assign : - if (!fReply) SwapEndianPattern( payload, sizeof(UINT32), 2 ); - else SwapDebuggingValue( payload, payloadSize ); - break; - case CLR_DBG_Commands::c_Debugging_TypeSys_Assemblies : - SwapEndianPattern( payload, sizeof(UINT32), fReply?payloadSize/sizeof(UINT32):0 ); - break; - case CLR_DBG_Commands::c_Debugging_TypeSys_AppDomains : - SwapEndianPattern( payload, sizeof(int), fReply?(payloadSize)/sizeof(int):0 ); - break; - case CLR_DBG_Commands::c_Debugging_Resolve_Assembly : - SwapEndianPattern( payload, sizeof(UINT32), fReply?1:1 ); - SwapEndianPattern( payload, sizeof(UINT16), fReply?4:0 ); - break; - case CLR_DBG_Commands::c_Debugging_Resolve_Type : - SwapEndianPattern( payload, sizeof(UINT32), fReply?0:1 ); - break; - case CLR_DBG_Commands::c_Debugging_Resolve_Field : - SwapEndianPattern( payload, sizeof(UINT32), fReply?2:1 ); - break; - case CLR_DBG_Commands::c_Debugging_Resolve_Method : - SwapEndianPattern( payload, sizeof(UINT32), fReply?1:1 ); - break; - case CLR_DBG_Commands::c_Debugging_Resolve_VirtualMethod : - SwapEndianPattern( payload, sizeof(UINT32), fReply?1:2 ); - break; - case CLR_DBG_Commands::c_Debugging_Resolve_AppDomain : - payloadSize -= SwapEndianPattern( payload, sizeof(UINT32), fReply?1:1 ); - payloadSize -= SwapEndianPattern( payload, 1, fReply?512:0 ); - SwapEndianPattern( payload, sizeof(UINT32), fReply?(payloadSize/sizeof(UINT32)):0 ); - break; - case CLR_DBG_Commands::c_Debugging_Deployment_Status : - SwapEndianPattern( payload, sizeof(UINT32), fReply?payloadSize/sizeof(UINT32):0 ); - break; - case CLR_DBG_Commands::c_Debugging_Info_SetJMC : - SwapEndianPattern( payload, sizeof(UINT32), fReply?0:3 ); - break; - case CLR_DBG_Commands::c_Profiling_Command : - if ( !fReply ) - { - // FIXME GJS are these structs packed on the wire? - UINT32 data[2]; - UINT8* dp = (UINT8*)data; - - payloadSize -= SwapEndianPattern( payload, sizeof(UINT8), 1 ); - if ( payloadSize > sizeof(data) ) - { - memcpy(data, payload, payloadSize); - SwapEndianPattern( dp, sizeof(UINT32), payloadSize/sizeof(UINT32) ); - memcpy(payload, data, payloadSize); - } - } - else - { - SwapEndianPattern( payload, sizeof(UINT32), 1 ); - } - - break; - case CLR_DBG_Commands::c_Profiling_Stream : - SwapEndianPattern( payload, sizeof(UINT16), fReply?0:2 ); - break; - } -} -#endif - diff --git a/src/CLR/Messaging/Messaging.vcxproj b/src/CLR/Messaging/Messaging.vcxproj new file mode 100644 index 0000000000..03387913f4 --- /dev/null +++ b/src/CLR/Messaging/Messaging.vcxproj @@ -0,0 +1,162 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + {2337c4a4-3ab4-4014-9c29-9ebe32f4510e} + false + false + + + + {131001E3-0201-451F-A87B-951D1C5C3EEE} + Win32Proj + Messaging + 10.0.14393.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\Include;..\CorLib + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/src/CLR/Messaging/Messaging.vcxproj.filters b/src/CLR/Messaging/Messaging.vcxproj.filters new file mode 100644 index 0000000000..2056f14821 --- /dev/null +++ b/src/CLR/Messaging/Messaging.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/src/CLR/Messaging/Messaging_stub.cpp b/src/CLR/Messaging/Messaging_stub.cpp new file mode 100644 index 0000000000..4d16f36eaf --- /dev/null +++ b/src/CLR/Messaging/Messaging_stub.cpp @@ -0,0 +1,66 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +CLR_Messaging *g_CLR_Messaging; + +CLR_UINT32 g_scratchMessaging[sizeof(CLR_Messaging) * NUM_MESSAGING / sizeof(UINT32) + 1]; + +HRESULT CLR_Messaging::CreateInstance() +{ + NATIVE_PROFILE_CLR_MESSAGING(); + g_CLR_Messaging = (CLR_Messaging*)&g_scratchMessaging[0]; + TINYCLR_SYSTEM_STUB_RETURN(); +} + +HRESULT CLR_Messaging::DeleteInstance() +{ + NATIVE_PROFILE_CLR_MESSAGING(); + TINYCLR_SYSTEM_STUB_RETURN(); +} + +bool CLR_Messaging::SendEvent( UINT32 cmd, UINT32 payloadSize, UINT8* payload, UINT32 flags ) +{ + NATIVE_PROFILE_CLR_MESSAGING(); + return true; +} + +void CLR_Messaging::PurgeCache() +{ + NATIVE_PROFILE_CLR_MESSAGING(); +} + +void CLR_Messaging::PurgeCache( CLR_RT_DblLinkedList& lst, CLR_INT64 oldest ) +{ + NATIVE_PROFILE_CLR_MESSAGING(); +} + +void CLR_Messaging::ProcessCommands() +{ + NATIVE_PROFILE_CLR_MESSAGING(); +} + +void CLR_Messaging::Initialize(COM_HANDLE port, const CLR_Messaging_CommandHandlerLookup* requestLookup, const CLR_UINT32 requestLookupCount, const CLR_Messaging_CommandHandlerLookup* replyLookup, const CLR_UINT32 replyLookupCount, void* owner ) +{ + NATIVE_PROFILE_CLR_MESSAGING(); +} + +void CLR_Messaging::ReplyToCommand( WP_Message* msg, bool fSuccess, bool fCritical ) +{ + NATIVE_PROFILE_CLR_MESSAGING(); +} + +void CLR_Messaging::ReplyToCommand( WP_Message* msg, bool fSuccess, bool fCritical, void* ptr, int size ) +{ + NATIVE_PROFILE_CLR_MESSAGING(); +} + +void CLR_Messaging::Cleanup() +{ + NATIVE_PROFILE_CLR_MESSAGING(); +} diff --git a/src/CLR/Messaging/Messaging_stub.vcxproj b/src/CLR/Messaging/Messaging_stub.vcxproj new file mode 100644 index 0000000000..e2a61891ae --- /dev/null +++ b/src/CLR/Messaging/Messaging_stub.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + {8ACD05E8-42FB-4A49-9D8B-79239F0EED25} + Win32Proj + Messaging_stub + 10.0.14393.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\Include + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\Include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\Include + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/src/CLR/Messaging/Messaging_stub.vcxproj.filters b/src/CLR/Messaging/Messaging_stub.vcxproj.filters new file mode 100644 index 0000000000..ca8c8999aa --- /dev/null +++ b/src/CLR/Messaging/Messaging_stub.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/src/CLR/StartUp/CLRStartup.cpp b/src/CLR/StartUp/CLRStartup.cpp new file mode 100644 index 0000000000..ef7c54f205 --- /dev/null +++ b/src/CLR/StartUp/CLRStartup.cpp @@ -0,0 +1,20 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "CLRStartup.h" + + +void ClrExit() +{ + NATIVE_PROFILE_CLR_STARTUP(); + CLR_EE_DBG_SET(ExitPending); +} + +void ClrReboot() +{ + NATIVE_PROFILE_CLR_STARTUP(); + CLR_EE_REBOOT_SET(ClrOnly); + CLR_EE_DBG_SET(RebootPending); +} diff --git a/src/CLR/StartUp/CLRStartup.h b/src/CLR/StartUp/CLRStartup.h new file mode 100644 index 0000000000..9748bbd480 --- /dev/null +++ b/src/CLR/StartUp/CLRStartup.h @@ -0,0 +1,27 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef __CLRSTARTUP_H__ +#define __CLRSTARTUP_H__ + +///////////////////////////////////////////////////////////////////////////// + +#include +#include +//#include +//#include +//#include +#include +// +//#include +// +//#include +//#include +//#include +//#include +//#include +//#include + +#endif // __CLRSTARTUP_H__ diff --git a/src/CLR/StartUp/StartUp.vcxproj b/src/CLR/StartUp/StartUp.vcxproj new file mode 100644 index 0000000000..e9d2f0f17b --- /dev/null +++ b/src/CLR/StartUp/StartUp.vcxproj @@ -0,0 +1,166 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + {89cf8bdb-9c8a-4d18-bc3e-4312c5bd34b1} + false + false + false + + + + {2A840DC3-FFA8-4562-BD13-AB2B0BA02CB6} + Win32Proj + StartUp + 10.0.14393.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/src/CLR/StartUp/StartUp.vcxproj.filters b/src/CLR/StartUp/StartUp.vcxproj.filters new file mode 100644 index 0000000000..3c321f8010 --- /dev/null +++ b/src/CLR/StartUp/StartUp.vcxproj.filters @@ -0,0 +1,27 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/src/CLR/WireProtocol/WireProtocol.cpp b/src/CLR/WireProtocol/WireProtocol.cpp index b4512e5db9..68cdea0c25 100644 --- a/src/CLR/WireProtocol/WireProtocol.cpp +++ b/src/CLR/WireProtocol/WireProtocol.cpp @@ -1,6 +1,6 @@ // // Copyright (c) 2017 The nanoFramework project contributors -// Copyright (c) Microsoft Corporation. All rights reserved. +// Portions Copyright (c) Microsoft Corporation. All rights reserved. // See LICENSE file in the project root for full license information. // diff --git a/src/CLR/WireProtocol/WireProtocol.vcxproj b/src/CLR/WireProtocol/WireProtocol.vcxproj new file mode 100644 index 0000000000..aaed31ebb9 --- /dev/null +++ b/src/CLR/WireProtocol/WireProtocol.vcxproj @@ -0,0 +1,155 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E} + Win32Proj + WireProtocol + 10.0.14393.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + $(BinDir) + $(IntDir) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\Include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/src/CLR/WireProtocol/WireProtocol.vcxproj.filters b/src/CLR/WireProtocol/WireProtocol.vcxproj.filters new file mode 100644 index 0000000000..cbfd2e82ae --- /dev/null +++ b/src/CLR/WireProtocol/WireProtocol.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/targets/os/mbed-os/nanoBooter/TinyCLR_Messaging.h b/targets/os/mbed-os/nanoBooter/TinyCLR_Messaging.h index 75aec5305d..a273263c58 100644 --- a/targets/os/mbed-os/nanoBooter/TinyCLR_Messaging.h +++ b/targets/os/mbed-os/nanoBooter/TinyCLR_Messaging.h @@ -1,6 +1,6 @@ // // Copyright (c) 2017 The nanoFramework project contributors -// Copyright (c) Microsoft Corporation. All rights reserved. +// Portions Copyright (c) Microsoft Corporation. All rights reserved. // See LICENSE file in the project root for full license information. // diff --git a/targets/os/mbed-os/nanoBooter/WireProtocol.cpp b/targets/os/mbed-os/nanoBooter/WireProtocol.cpp index 940ae46815..de5ca8a960 100644 --- a/targets/os/mbed-os/nanoBooter/WireProtocol.cpp +++ b/targets/os/mbed-os/nanoBooter/WireProtocol.cpp @@ -1,6 +1,6 @@ // // Copyright (c) 2017 The nanoFramework project contributors -// Copyright (c) Microsoft Corporation. All rights reserved. +// Portions Copyright (c) Microsoft Corporation. All rights reserved. // See LICENSE file in the project root for full license information. // diff --git a/targets/os/mbed-os/nanoBooter/WireProtocol.h b/targets/os/mbed-os/nanoBooter/WireProtocol.h index 39b4ce0643..2c01c6a0f0 100644 --- a/targets/os/mbed-os/nanoBooter/WireProtocol.h +++ b/targets/os/mbed-os/nanoBooter/WireProtocol.h @@ -1,6 +1,6 @@ // // Copyright (c) 2017 The nanoFramework project contributors -// Copyright (c) Microsoft Corporation. All rights reserved. +// Portions Copyright (c) Microsoft Corporation. All rights reserved. // See LICENSE file in the project root for full license information. // diff --git a/targets/os/win32/nanoCLR.sln b/targets/os/win32/nanoCLR.sln new file mode 100644 index 0000000000..70a1d7dd4f --- /dev/null +++ b/targets/os/win32/nanoCLR.sln @@ -0,0 +1,280 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26020.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nanoCLR", "nanoCLR\nanoCLR.vcxproj", "{B5515C8A-B056-4320-8EA4-8CACE21A7D2E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "nanoCLR", "nanoCLR", "{11C6630D-C836-44FA-8A79-7574F175DAF2}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Core", "..\..\..\src\CLR\Core\Core.vcxproj", "{89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CorLib", "..\..\..\src\CLR\CorLib\CorLib.vcxproj", "{58E950CC-2FF6-423C-B006-A70A19272F20}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Diagnostics", "..\..\..\src\CLR\Diagnostics\Diagnostics.vcxproj", "{A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StartUp", "..\..\..\src\CLR\StartUp\StartUp.vcxproj", "{2A840DC3-FFA8-4562-BD13-AB2B0BA02CB6}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Messaging", "..\..\..\src\CLR\Messaging\Messaging.vcxproj", "{131001E3-0201-451F-A87B-951D1C5C3EEE}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Debugger", "..\..\..\src\CLR\Debugger\Debugger.vcxproj", "{DD397EC4-844B-4B59-A67B-CAD6B46F1F00}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WireProtocol", "..\..\..\src\CLR\WireProtocol\WireProtocol.vcxproj", "{2337C4A4-3AB4-4014-9C29-9EBE32F4510E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Hardware", "..\..\..\src\CLR\Core\Hardware\Hardware.vcxproj", "{5D50772E-DAC8-407D-972F-37DEB4450B72}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HeapPersistence", "..\..\..\src\CLR\Core\HeapPersistence\HeapPersistence.vcxproj", "{BC2245B0-32E0-410E-B3F2-E2BFA0B503B3}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InterruptHandler", "..\..\..\src\CLR\Core\InterruptHandler\InterruptHandler.vcxproj", "{D32EE397-7E49-452D-AC95-AFCB3C962E3D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IOPort", "..\..\..\src\CLR\Core\IOPort\IOPort.vcxproj", "{6DD5CA4F-2AE9-44D3-B9D7-A2A4A35FC5B2}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RPC", "..\..\..\src\CLR\Core\RPC\RPC.vcxproj", "{ED4C887A-EC09-465B-B5D9-075450ADC52D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Serialization", "..\..\..\src\CLR\Core\Serialization\Serialization.vcxproj", "{16BF6131-A3B8-4B97-B867-E45669FB48BD}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Features", "Features", "{76169580-0DE3-48D0-9545-8FC438C54094}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Stubs", "Stubs", "{2662E293-2538-40C2-9472-D936B1220EC2}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Debugger_stub", "..\..\..\src\CLR\Debugger\Debugger_stub.vcxproj", "{6DABCBF1-245A-4E76-BD36-8BC300C7DD82}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Diagnostics_stub", "..\..\..\src\CLR\Diagnostics\Diagnostics_stub.vcxproj", "{C97A9845-02DC-46E4-B219-BF5EA8FB28E3}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Hardware_stub", "..\..\..\src\CLR\Core\Hardware\Hardware_stub.vcxproj", "{31253D7F-147E-49A3-BC0D-E0ADE6CF040B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HeapPersistence_stub", "..\..\..\src\CLR\Core\HeapPersistence\HeapPersistence_stub.vcxproj", "{4646F661-9505-45C2-9573-8409A9DD1149}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InterruptHandler_stub", "..\..\..\src\CLR\Core\InterruptHandler\InterruptHandler_stub.vcxproj", "{5772D362-7277-49CF-9B49-42335A3154BD}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IOPort_stub", "..\..\..\src\CLR\Core\IOPort\IOPort_stub.vcxproj", "{5406EB0C-2243-47E1-9F21-F2D7CA277092}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Messaging_stub", "..\..\..\src\CLR\Messaging\Messaging_stub.vcxproj", "{8ACD05E8-42FB-4A49-9D8B-79239F0EED25}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RPC_stub", "..\..\..\src\CLR\Core\RPC\RPC_stub.vcxproj", "{D0B2ADFE-3347-4D73-9364-9C36935D12F8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Serialization_stub", "..\..\..\src\CLR\Core\Serialization\Serialization_stub.vcxproj", "{C337041D-344D-49FE-AD99-B137E7FD0188}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B5515C8A-B056-4320-8EA4-8CACE21A7D2E}.Debug|x64.ActiveCfg = Debug|x64 + {B5515C8A-B056-4320-8EA4-8CACE21A7D2E}.Debug|x64.Build.0 = Debug|x64 + {B5515C8A-B056-4320-8EA4-8CACE21A7D2E}.Debug|x86.ActiveCfg = Debug|Win32 + {B5515C8A-B056-4320-8EA4-8CACE21A7D2E}.Debug|x86.Build.0 = Debug|Win32 + {B5515C8A-B056-4320-8EA4-8CACE21A7D2E}.Release|x64.ActiveCfg = Release|x64 + {B5515C8A-B056-4320-8EA4-8CACE21A7D2E}.Release|x64.Build.0 = Release|x64 + {B5515C8A-B056-4320-8EA4-8CACE21A7D2E}.Release|x86.ActiveCfg = Release|Win32 + {B5515C8A-B056-4320-8EA4-8CACE21A7D2E}.Release|x86.Build.0 = Release|Win32 + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Debug|x64.ActiveCfg = Debug|x64 + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Debug|x64.Build.0 = Debug|x64 + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Debug|x86.ActiveCfg = Debug|Win32 + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Debug|x86.Build.0 = Debug|Win32 + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Release|x64.ActiveCfg = Release|x64 + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Release|x64.Build.0 = Release|x64 + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Release|x86.ActiveCfg = Release|Win32 + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1}.Release|x86.Build.0 = Release|Win32 + {58E950CC-2FF6-423C-B006-A70A19272F20}.Debug|x64.ActiveCfg = Debug|x64 + {58E950CC-2FF6-423C-B006-A70A19272F20}.Debug|x64.Build.0 = Debug|x64 + {58E950CC-2FF6-423C-B006-A70A19272F20}.Debug|x86.ActiveCfg = Debug|Win32 + {58E950CC-2FF6-423C-B006-A70A19272F20}.Debug|x86.Build.0 = Debug|Win32 + {58E950CC-2FF6-423C-B006-A70A19272F20}.Release|x64.ActiveCfg = Release|x64 + {58E950CC-2FF6-423C-B006-A70A19272F20}.Release|x64.Build.0 = Release|x64 + {58E950CC-2FF6-423C-B006-A70A19272F20}.Release|x86.ActiveCfg = Release|Win32 + {58E950CC-2FF6-423C-B006-A70A19272F20}.Release|x86.Build.0 = Release|Win32 + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Debug|x64.ActiveCfg = Debug|x64 + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Debug|x64.Build.0 = Debug|x64 + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Debug|x86.ActiveCfg = Debug|Win32 + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Debug|x86.Build.0 = Debug|Win32 + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Release|x64.ActiveCfg = Release|x64 + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Release|x64.Build.0 = Release|x64 + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Release|x86.ActiveCfg = Release|Win32 + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B}.Release|x86.Build.0 = Release|Win32 + {2A840DC3-FFA8-4562-BD13-AB2B0BA02CB6}.Debug|x64.ActiveCfg = Debug|x64 + {2A840DC3-FFA8-4562-BD13-AB2B0BA02CB6}.Debug|x64.Build.0 = Debug|x64 + {2A840DC3-FFA8-4562-BD13-AB2B0BA02CB6}.Debug|x86.ActiveCfg = Debug|Win32 + {2A840DC3-FFA8-4562-BD13-AB2B0BA02CB6}.Debug|x86.Build.0 = Debug|Win32 + {2A840DC3-FFA8-4562-BD13-AB2B0BA02CB6}.Release|x64.ActiveCfg = Release|x64 + {2A840DC3-FFA8-4562-BD13-AB2B0BA02CB6}.Release|x64.Build.0 = Release|x64 + {2A840DC3-FFA8-4562-BD13-AB2B0BA02CB6}.Release|x86.ActiveCfg = Release|Win32 + {2A840DC3-FFA8-4562-BD13-AB2B0BA02CB6}.Release|x86.Build.0 = Release|Win32 + {131001E3-0201-451F-A87B-951D1C5C3EEE}.Debug|x64.ActiveCfg = Debug|x64 + {131001E3-0201-451F-A87B-951D1C5C3EEE}.Debug|x64.Build.0 = Debug|x64 + {131001E3-0201-451F-A87B-951D1C5C3EEE}.Debug|x86.ActiveCfg = Debug|Win32 + {131001E3-0201-451F-A87B-951D1C5C3EEE}.Debug|x86.Build.0 = Debug|Win32 + {131001E3-0201-451F-A87B-951D1C5C3EEE}.Release|x64.ActiveCfg = Release|x64 + {131001E3-0201-451F-A87B-951D1C5C3EEE}.Release|x64.Build.0 = Release|x64 + {131001E3-0201-451F-A87B-951D1C5C3EEE}.Release|x86.ActiveCfg = Release|Win32 + {131001E3-0201-451F-A87B-951D1C5C3EEE}.Release|x86.Build.0 = Release|Win32 + {DD397EC4-844B-4B59-A67B-CAD6B46F1F00}.Debug|x64.ActiveCfg = Debug|x64 + {DD397EC4-844B-4B59-A67B-CAD6B46F1F00}.Debug|x64.Build.0 = Debug|x64 + {DD397EC4-844B-4B59-A67B-CAD6B46F1F00}.Debug|x86.ActiveCfg = Debug|Win32 + {DD397EC4-844B-4B59-A67B-CAD6B46F1F00}.Debug|x86.Build.0 = Debug|Win32 + {DD397EC4-844B-4B59-A67B-CAD6B46F1F00}.Release|x64.ActiveCfg = Release|x64 + {DD397EC4-844B-4B59-A67B-CAD6B46F1F00}.Release|x64.Build.0 = Release|x64 + {DD397EC4-844B-4B59-A67B-CAD6B46F1F00}.Release|x86.ActiveCfg = Release|Win32 + {DD397EC4-844B-4B59-A67B-CAD6B46F1F00}.Release|x86.Build.0 = Release|Win32 + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Debug|x64.ActiveCfg = Debug|x64 + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Debug|x64.Build.0 = Debug|x64 + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Debug|x86.ActiveCfg = Debug|Win32 + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Debug|x86.Build.0 = Debug|Win32 + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Release|x64.ActiveCfg = Release|x64 + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Release|x64.Build.0 = Release|x64 + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Release|x86.ActiveCfg = Release|Win32 + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E}.Release|x86.Build.0 = Release|Win32 + {5D50772E-DAC8-407D-972F-37DEB4450B72}.Debug|x64.ActiveCfg = Debug|x64 + {5D50772E-DAC8-407D-972F-37DEB4450B72}.Debug|x64.Build.0 = Debug|x64 + {5D50772E-DAC8-407D-972F-37DEB4450B72}.Debug|x86.ActiveCfg = Debug|Win32 + {5D50772E-DAC8-407D-972F-37DEB4450B72}.Debug|x86.Build.0 = Debug|Win32 + {5D50772E-DAC8-407D-972F-37DEB4450B72}.Release|x64.ActiveCfg = Release|x64 + {5D50772E-DAC8-407D-972F-37DEB4450B72}.Release|x64.Build.0 = Release|x64 + {5D50772E-DAC8-407D-972F-37DEB4450B72}.Release|x86.ActiveCfg = Release|Win32 + {5D50772E-DAC8-407D-972F-37DEB4450B72}.Release|x86.Build.0 = Release|Win32 + {BC2245B0-32E0-410E-B3F2-E2BFA0B503B3}.Debug|x64.ActiveCfg = Debug|x64 + {BC2245B0-32E0-410E-B3F2-E2BFA0B503B3}.Debug|x64.Build.0 = Debug|x64 + {BC2245B0-32E0-410E-B3F2-E2BFA0B503B3}.Debug|x86.ActiveCfg = Debug|Win32 + {BC2245B0-32E0-410E-B3F2-E2BFA0B503B3}.Debug|x86.Build.0 = Debug|Win32 + {BC2245B0-32E0-410E-B3F2-E2BFA0B503B3}.Release|x64.ActiveCfg = Release|x64 + {BC2245B0-32E0-410E-B3F2-E2BFA0B503B3}.Release|x64.Build.0 = Release|x64 + {BC2245B0-32E0-410E-B3F2-E2BFA0B503B3}.Release|x86.ActiveCfg = Release|Win32 + {BC2245B0-32E0-410E-B3F2-E2BFA0B503B3}.Release|x86.Build.0 = Release|Win32 + {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Debug|x64.ActiveCfg = Debug|x64 + {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Debug|x64.Build.0 = Debug|x64 + {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Debug|x86.ActiveCfg = Debug|Win32 + {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Debug|x86.Build.0 = Debug|Win32 + {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Release|x64.ActiveCfg = Release|x64 + {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Release|x64.Build.0 = Release|x64 + {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Release|x86.ActiveCfg = Release|Win32 + {D32EE397-7E49-452D-AC95-AFCB3C962E3D}.Release|x86.Build.0 = Release|Win32 + {6DD5CA4F-2AE9-44D3-B9D7-A2A4A35FC5B2}.Debug|x64.ActiveCfg = Debug|x64 + {6DD5CA4F-2AE9-44D3-B9D7-A2A4A35FC5B2}.Debug|x64.Build.0 = Debug|x64 + {6DD5CA4F-2AE9-44D3-B9D7-A2A4A35FC5B2}.Debug|x86.ActiveCfg = Debug|Win32 + {6DD5CA4F-2AE9-44D3-B9D7-A2A4A35FC5B2}.Debug|x86.Build.0 = Debug|Win32 + {6DD5CA4F-2AE9-44D3-B9D7-A2A4A35FC5B2}.Release|x64.ActiveCfg = Release|x64 + {6DD5CA4F-2AE9-44D3-B9D7-A2A4A35FC5B2}.Release|x64.Build.0 = Release|x64 + {6DD5CA4F-2AE9-44D3-B9D7-A2A4A35FC5B2}.Release|x86.ActiveCfg = Release|Win32 + {6DD5CA4F-2AE9-44D3-B9D7-A2A4A35FC5B2}.Release|x86.Build.0 = Release|Win32 + {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Debug|x64.ActiveCfg = Debug|x64 + {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Debug|x64.Build.0 = Debug|x64 + {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Debug|x86.ActiveCfg = Debug|Win32 + {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Debug|x86.Build.0 = Debug|Win32 + {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Release|x64.ActiveCfg = Release|x64 + {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Release|x64.Build.0 = Release|x64 + {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Release|x86.ActiveCfg = Release|Win32 + {ED4C887A-EC09-465B-B5D9-075450ADC52D}.Release|x86.Build.0 = Release|Win32 + {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Debug|x64.ActiveCfg = Debug|x64 + {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Debug|x64.Build.0 = Debug|x64 + {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Debug|x86.ActiveCfg = Debug|Win32 + {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Debug|x86.Build.0 = Debug|Win32 + {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Release|x64.ActiveCfg = Release|x64 + {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Release|x64.Build.0 = Release|x64 + {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Release|x86.ActiveCfg = Release|Win32 + {16BF6131-A3B8-4B97-B867-E45669FB48BD}.Release|x86.Build.0 = Release|Win32 + {6DABCBF1-245A-4E76-BD36-8BC300C7DD82}.Debug|x64.ActiveCfg = Debug|x64 + {6DABCBF1-245A-4E76-BD36-8BC300C7DD82}.Debug|x64.Build.0 = Debug|x64 + {6DABCBF1-245A-4E76-BD36-8BC300C7DD82}.Debug|x86.ActiveCfg = Debug|Win32 + {6DABCBF1-245A-4E76-BD36-8BC300C7DD82}.Debug|x86.Build.0 = Debug|Win32 + {6DABCBF1-245A-4E76-BD36-8BC300C7DD82}.Release|x64.ActiveCfg = Release|x64 + {6DABCBF1-245A-4E76-BD36-8BC300C7DD82}.Release|x64.Build.0 = Release|x64 + {6DABCBF1-245A-4E76-BD36-8BC300C7DD82}.Release|x86.ActiveCfg = Release|Win32 + {6DABCBF1-245A-4E76-BD36-8BC300C7DD82}.Release|x86.Build.0 = Release|Win32 + {C97A9845-02DC-46E4-B219-BF5EA8FB28E3}.Debug|x64.ActiveCfg = Debug|x64 + {C97A9845-02DC-46E4-B219-BF5EA8FB28E3}.Debug|x64.Build.0 = Debug|x64 + {C97A9845-02DC-46E4-B219-BF5EA8FB28E3}.Debug|x86.ActiveCfg = Debug|Win32 + {C97A9845-02DC-46E4-B219-BF5EA8FB28E3}.Debug|x86.Build.0 = Debug|Win32 + {C97A9845-02DC-46E4-B219-BF5EA8FB28E3}.Release|x64.ActiveCfg = Release|x64 + {C97A9845-02DC-46E4-B219-BF5EA8FB28E3}.Release|x64.Build.0 = Release|x64 + {C97A9845-02DC-46E4-B219-BF5EA8FB28E3}.Release|x86.ActiveCfg = Release|Win32 + {C97A9845-02DC-46E4-B219-BF5EA8FB28E3}.Release|x86.Build.0 = Release|Win32 + {31253D7F-147E-49A3-BC0D-E0ADE6CF040B}.Debug|x64.ActiveCfg = Debug|x64 + {31253D7F-147E-49A3-BC0D-E0ADE6CF040B}.Debug|x64.Build.0 = Debug|x64 + {31253D7F-147E-49A3-BC0D-E0ADE6CF040B}.Debug|x86.ActiveCfg = Debug|Win32 + {31253D7F-147E-49A3-BC0D-E0ADE6CF040B}.Debug|x86.Build.0 = Debug|Win32 + {31253D7F-147E-49A3-BC0D-E0ADE6CF040B}.Release|x64.ActiveCfg = Release|x64 + {31253D7F-147E-49A3-BC0D-E0ADE6CF040B}.Release|x64.Build.0 = Release|x64 + {31253D7F-147E-49A3-BC0D-E0ADE6CF040B}.Release|x86.ActiveCfg = Release|Win32 + {31253D7F-147E-49A3-BC0D-E0ADE6CF040B}.Release|x86.Build.0 = Release|Win32 + {4646F661-9505-45C2-9573-8409A9DD1149}.Debug|x64.ActiveCfg = Debug|x64 + {4646F661-9505-45C2-9573-8409A9DD1149}.Debug|x64.Build.0 = Debug|x64 + {4646F661-9505-45C2-9573-8409A9DD1149}.Debug|x86.ActiveCfg = Debug|Win32 + {4646F661-9505-45C2-9573-8409A9DD1149}.Debug|x86.Build.0 = Debug|Win32 + {4646F661-9505-45C2-9573-8409A9DD1149}.Release|x64.ActiveCfg = Release|x64 + {4646F661-9505-45C2-9573-8409A9DD1149}.Release|x64.Build.0 = Release|x64 + {4646F661-9505-45C2-9573-8409A9DD1149}.Release|x86.ActiveCfg = Release|Win32 + {4646F661-9505-45C2-9573-8409A9DD1149}.Release|x86.Build.0 = Release|Win32 + {5772D362-7277-49CF-9B49-42335A3154BD}.Debug|x64.ActiveCfg = Debug|x64 + {5772D362-7277-49CF-9B49-42335A3154BD}.Debug|x64.Build.0 = Debug|x64 + {5772D362-7277-49CF-9B49-42335A3154BD}.Debug|x86.ActiveCfg = Debug|Win32 + {5772D362-7277-49CF-9B49-42335A3154BD}.Debug|x86.Build.0 = Debug|Win32 + {5772D362-7277-49CF-9B49-42335A3154BD}.Release|x64.ActiveCfg = Release|x64 + {5772D362-7277-49CF-9B49-42335A3154BD}.Release|x64.Build.0 = Release|x64 + {5772D362-7277-49CF-9B49-42335A3154BD}.Release|x86.ActiveCfg = Release|Win32 + {5772D362-7277-49CF-9B49-42335A3154BD}.Release|x86.Build.0 = Release|Win32 + {5406EB0C-2243-47E1-9F21-F2D7CA277092}.Debug|x64.ActiveCfg = Debug|x64 + {5406EB0C-2243-47E1-9F21-F2D7CA277092}.Debug|x64.Build.0 = Debug|x64 + {5406EB0C-2243-47E1-9F21-F2D7CA277092}.Debug|x86.ActiveCfg = Debug|Win32 + {5406EB0C-2243-47E1-9F21-F2D7CA277092}.Debug|x86.Build.0 = Debug|Win32 + {5406EB0C-2243-47E1-9F21-F2D7CA277092}.Release|x64.ActiveCfg = Release|x64 + {5406EB0C-2243-47E1-9F21-F2D7CA277092}.Release|x64.Build.0 = Release|x64 + {5406EB0C-2243-47E1-9F21-F2D7CA277092}.Release|x86.ActiveCfg = Release|Win32 + {5406EB0C-2243-47E1-9F21-F2D7CA277092}.Release|x86.Build.0 = Release|Win32 + {8ACD05E8-42FB-4A49-9D8B-79239F0EED25}.Debug|x64.ActiveCfg = Debug|x64 + {8ACD05E8-42FB-4A49-9D8B-79239F0EED25}.Debug|x64.Build.0 = Debug|x64 + {8ACD05E8-42FB-4A49-9D8B-79239F0EED25}.Debug|x86.ActiveCfg = Debug|Win32 + {8ACD05E8-42FB-4A49-9D8B-79239F0EED25}.Debug|x86.Build.0 = Debug|Win32 + {8ACD05E8-42FB-4A49-9D8B-79239F0EED25}.Release|x64.ActiveCfg = Release|x64 + {8ACD05E8-42FB-4A49-9D8B-79239F0EED25}.Release|x64.Build.0 = Release|x64 + {8ACD05E8-42FB-4A49-9D8B-79239F0EED25}.Release|x86.ActiveCfg = Release|Win32 + {8ACD05E8-42FB-4A49-9D8B-79239F0EED25}.Release|x86.Build.0 = Release|Win32 + {D0B2ADFE-3347-4D73-9364-9C36935D12F8}.Debug|x64.ActiveCfg = Debug|x64 + {D0B2ADFE-3347-4D73-9364-9C36935D12F8}.Debug|x64.Build.0 = Debug|x64 + {D0B2ADFE-3347-4D73-9364-9C36935D12F8}.Debug|x86.ActiveCfg = Debug|Win32 + {D0B2ADFE-3347-4D73-9364-9C36935D12F8}.Debug|x86.Build.0 = Debug|Win32 + {D0B2ADFE-3347-4D73-9364-9C36935D12F8}.Release|x64.ActiveCfg = Release|x64 + {D0B2ADFE-3347-4D73-9364-9C36935D12F8}.Release|x64.Build.0 = Release|x64 + {D0B2ADFE-3347-4D73-9364-9C36935D12F8}.Release|x86.ActiveCfg = Release|Win32 + {D0B2ADFE-3347-4D73-9364-9C36935D12F8}.Release|x86.Build.0 = Release|Win32 + {C337041D-344D-49FE-AD99-B137E7FD0188}.Debug|x64.ActiveCfg = Debug|x64 + {C337041D-344D-49FE-AD99-B137E7FD0188}.Debug|x64.Build.0 = Debug|x64 + {C337041D-344D-49FE-AD99-B137E7FD0188}.Debug|x86.ActiveCfg = Debug|Win32 + {C337041D-344D-49FE-AD99-B137E7FD0188}.Debug|x86.Build.0 = Debug|Win32 + {C337041D-344D-49FE-AD99-B137E7FD0188}.Release|x64.ActiveCfg = Release|x64 + {C337041D-344D-49FE-AD99-B137E7FD0188}.Release|x64.Build.0 = Release|x64 + {C337041D-344D-49FE-AD99-B137E7FD0188}.Release|x86.ActiveCfg = Release|Win32 + {C337041D-344D-49FE-AD99-B137E7FD0188}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {89CF8BDB-9C8A-4D18-BC3E-4312C5BD34B1} = {11C6630D-C836-44FA-8A79-7574F175DAF2} + {58E950CC-2FF6-423C-B006-A70A19272F20} = {11C6630D-C836-44FA-8A79-7574F175DAF2} + {A5E9AE41-F4FA-40CE-AD82-A7861EBA007B} = {76169580-0DE3-48D0-9545-8FC438C54094} + {2A840DC3-FFA8-4562-BD13-AB2B0BA02CB6} = {11C6630D-C836-44FA-8A79-7574F175DAF2} + {131001E3-0201-451F-A87B-951D1C5C3EEE} = {76169580-0DE3-48D0-9545-8FC438C54094} + {DD397EC4-844B-4B59-A67B-CAD6B46F1F00} = {76169580-0DE3-48D0-9545-8FC438C54094} + {2337C4A4-3AB4-4014-9C29-9EBE32F4510E} = {76169580-0DE3-48D0-9545-8FC438C54094} + {5D50772E-DAC8-407D-972F-37DEB4450B72} = {76169580-0DE3-48D0-9545-8FC438C54094} + {BC2245B0-32E0-410E-B3F2-E2BFA0B503B3} = {76169580-0DE3-48D0-9545-8FC438C54094} + {D32EE397-7E49-452D-AC95-AFCB3C962E3D} = {76169580-0DE3-48D0-9545-8FC438C54094} + {6DD5CA4F-2AE9-44D3-B9D7-A2A4A35FC5B2} = {76169580-0DE3-48D0-9545-8FC438C54094} + {ED4C887A-EC09-465B-B5D9-075450ADC52D} = {76169580-0DE3-48D0-9545-8FC438C54094} + {16BF6131-A3B8-4B97-B867-E45669FB48BD} = {76169580-0DE3-48D0-9545-8FC438C54094} + {76169580-0DE3-48D0-9545-8FC438C54094} = {11C6630D-C836-44FA-8A79-7574F175DAF2} + {2662E293-2538-40C2-9472-D936B1220EC2} = {11C6630D-C836-44FA-8A79-7574F175DAF2} + {6DABCBF1-245A-4E76-BD36-8BC300C7DD82} = {2662E293-2538-40C2-9472-D936B1220EC2} + {C97A9845-02DC-46E4-B219-BF5EA8FB28E3} = {2662E293-2538-40C2-9472-D936B1220EC2} + {31253D7F-147E-49A3-BC0D-E0ADE6CF040B} = {2662E293-2538-40C2-9472-D936B1220EC2} + {4646F661-9505-45C2-9573-8409A9DD1149} = {2662E293-2538-40C2-9472-D936B1220EC2} + {5772D362-7277-49CF-9B49-42335A3154BD} = {2662E293-2538-40C2-9472-D936B1220EC2} + {5406EB0C-2243-47E1-9F21-F2D7CA277092} = {2662E293-2538-40C2-9472-D936B1220EC2} + {8ACD05E8-42FB-4A49-9D8B-79239F0EED25} = {2662E293-2538-40C2-9472-D936B1220EC2} + {D0B2ADFE-3347-4D73-9364-9C36935D12F8} = {2662E293-2538-40C2-9472-D936B1220EC2} + {C337041D-344D-49FE-AD99-B137E7FD0188} = {2662E293-2538-40C2-9472-D936B1220EC2} + EndGlobalSection +EndGlobal diff --git a/targets/os/win32/nanoCLR/CLRStartup.cpp b/targets/os/win32/nanoCLR/CLRStartup.cpp new file mode 100644 index 0000000000..f639ece4a6 --- /dev/null +++ b/targets/os/win32/nanoCLR/CLRStartup.cpp @@ -0,0 +1,702 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "stdafx.h" + +#if defined(_WIN32) + + +#endif + +//////////////////////////////////////////////////////////////////////////////// + +struct Settings +#if defined(_WIN32) +: CLR_RT_ParseOptions +#endif +{ + CLR_SETTINGS m_clrOptions; +#if defined(_WIN32) + CLR_RT_ParseOptions::BufferMap m_assemblies; +#endif + bool m_fInitialized; + + //--// + + HRESULT Initialize(CLR_SETTINGS params) + { + TINYCLR_HEADER(); + + m_clrOptions = params; + +#if defined(PLATFORM_WINDOWS_EMULATOR) + g_CLR_RT_ExecutionEngine.m_fPerformGarbageCollection = params.PerformGarbageCollection; + g_CLR_RT_ExecutionEngine.m_fPerformHeapCompaction = params.PerformHeapCompaction; + + CLR_UINT32 clockFrequencyBaseline = 27000000; + CLR_UINT32 clockFrequency = CPU_SystemClock(); + double clockFrequencyRatio = 1; + + if(clockFrequency > 0) + { + clockFrequencyRatio = (double)clockFrequencyBaseline / (double)clockFrequency; + } + + g_HAL_Configuration_Windows.ProductType = HAL_Configuration_Windows::Product_Aux; + g_HAL_Configuration_Windows.SlowClockPerSecond = 32768; + g_HAL_Configuration_Windows.TicksPerMethodCall = (CLR_UINT64)(45.0*clockFrequencyRatio); + g_HAL_Configuration_Windows.TicksPerOpcode = (CLR_UINT64)( 5.0*clockFrequencyRatio); + g_HAL_Configuration_Windows.GraphHeapEnabled = false; +#endif + + TINYCLR_CHECK_HRESULT(CLR_RT_ExecutionEngine::CreateInstance()); +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Created EE.\r\n" ); +#endif + +#if !defined(BUILD_RTM) + if(params.WaitForDebugger) + { +#if defined(_WIN32) + CLR_EE_DBG_SET( Enabled ); +#endif + CLR_EE_DBG_SET( Stopped ); + } +#endif + + TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.StartHardware()); +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Started Hardware.\r\n" ); +#endif + + CLR_DBG_Debugger::Debugger_Discovery(); + + m_fInitialized = true; + + + TINYCLR_NOCLEANUP(); + } + + + HRESULT LoadAssembly( const CLR_RECORD_ASSEMBLY* header, CLR_RT_Assembly*& assm ) + { + TINYCLR_HEADER(); + + const CLR_RT_NativeAssemblyData *pNativeAssmData; + + TINYCLR_CHECK_HRESULT(CLR_RT_Assembly::CreateInstance( header, assm )); + + // Get handlers for native functions in assembly + pNativeAssmData = GetAssemblyNativeData( assm->m_szName ); + + // If pNativeAssmData not NULL- means this assembly has native calls and there is pointer to table with native calls. + if ( pNativeAssmData != NULL ) + { + // First verify that check sum in assembly object matches hardcoded check sum. + if ( assm->m_header->nativeMethodsChecksum != pNativeAssmData->m_checkSum ) + { + CLR_Debug::Printf("***********************************************************************\r\n"); + CLR_Debug::Printf("* *\r\n"); + CLR_Debug::Printf("* ERROR!!!! Firmware version does not match managed code version!!!! *\r\n"); + CLR_Debug::Printf("* *\r\n"); + CLR_Debug::Printf("* *\r\n"); + CLR_Debug::Printf("* Invalid native checksum: %s 0x%08X!=0x%08X *\r\n", + assm->m_szName, + assm->m_header->nativeMethodsChecksum, + pNativeAssmData->m_checkSum + ); + CLR_Debug::Printf("* *\r\n"); + CLR_Debug::Printf("***********************************************************************\r\n"); + + TINYCLR_SET_AND_LEAVE(CLR_E_ASSM_WRONG_CHECKSUM); + } + + // Assembly has valid pointer to table with native methods. Save it. + assm->m_nativeCode = (const CLR_RT_MethodHandler *)pNativeAssmData->m_pNativeMethods; + } + g_CLR_RT_TypeSystem.Link( assm ); + TINYCLR_NOCLEANUP(); + } + + + HRESULT Load() + { + TINYCLR_HEADER(); + +#if defined(_WIN32) + CLR_RT_StringVector vec; + + vec.push_back(L"-load"); + vec.push_back(L"..\\netmf\\MFConsoleApplication\\bin\\Release\\le\\MFConsoleApplication.pe"); + + vec.push_back(L"-load"); + vec.push_back(L"C:\\Program Files (x86)\\Microsoft .NET Micro Framework\\v4.4\\Assemblies\\le\\mscorlib.pe"); + + vec.push_back(L"-load"); + vec.push_back(L"C:\\Program Files (x86)\\Microsoft .NET Micro Framework\\v4.4\\Assemblies\\le\\Microsoft.SPOT.Native.pe"); + + //WCHAR* pContext = NULL; + //WCHAR* pch = wcstok_s(emulatorArgs, L" ", &pContext); // UNDONE: FIXME: wcstok_s(this->m_clrOptions.EmulatorArgs, L" ", &pContext); + + //while (pch != NULL) + //{ + // //printf ("%s\n",pch); + // vec.push_back(pch); + + // pch = wcstok_s(NULL, L" ", &pContext); + //} + + ProcessOptions(vec); + + for(CLR_RT_ParseOptions::BufferMapIter it = m_assemblies.begin(); it != m_assemblies.end(); it++) + { + CLR_RT_Assembly* assm; + const CLR_RT_Buffer* buffer = (const CLR_RT_Buffer*)it->second; + const CLR_RECORD_ASSEMBLY* header = (CLR_RECORD_ASSEMBLY*)&(*buffer)[0]; + + // Creates instance of assembly, sets pointer to native functions, links to g_CLR_RT_TypeSystem + TINYCLR_CHECK_HRESULT( LoadAssembly( header, assm ) ); + } +#else + +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Create TS.\r\n" ); +#endif + + TINYCLR_CHECK_HRESULT(LoadKnownAssemblies( TinyClr_Dat_Start, TinyClr_Dat_End )); + +#endif // defined(PLATFORM_WINDOWS_EMULATOR) || defined(PLATFORM_WINCE) + +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Loading Deployment Assemblies.\r\n" ); +#endif + + LoadDeploymentAssemblies( BlockUsage::DEPLOYMENT ); + + //--// + +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Resolving.\r\n" ); +#endif + TINYCLR_CHECK_HRESULT(g_CLR_RT_TypeSystem.ResolveAll()); + + g_CLR_RT_Persistence_Manager.Initialize(); + + TINYCLR_CHECK_HRESULT(g_CLR_RT_TypeSystem.PrepareForExecution()); + +#if defined(TINYCLR_PROFILE_HANDLER) + CLR_PROF_Handler::Calibrate(); +#endif + + TINYCLR_CLEANUP(); + +#if !defined(BUILD_RTM) + if(FAILED(hr)) CLR_Debug::Printf( "Error: %08x\r\n", hr ); +#endif + + TINYCLR_CLEANUP_END(); + } + + HRESULT CheckKnownAssembliesForNonXIP( char** start, char** end ) + { + //--// + TINYCLR_HEADER(); + + BlockStorageDevice *device; + ByteAddress datByteAddress; + UINT32 datSize = ROUNDTOMULTIPLE((UINT32)(*end)- (UINT32)(*start), CLR_UINT32); + + if (BlockStorageList::FindDeviceForPhysicalAddress( &device, (UINT32)(*start), datByteAddress ) && device != NULL) + { + const BlockDeviceInfo * deviceInfo=device->GetDeviceInfo(); + + if (!deviceInfo->Attribute.SupportsXIP) + { + BYTE * datAssembliesBuffer = (BYTE*)CLR_RT_Memory::Allocate_And_Erase( datSize, CLR_RT_HeapBlock ::HB_Unmovable ); CHECK_ALLOCATION(datAssembliesBuffer); + + if ( !device->Read( datByteAddress, datSize, datAssembliesBuffer )) + { + TINYCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + } + *start = (char *)datAssembliesBuffer; + *end = (char *)((UINT32) datAssembliesBuffer + (UINT32)datSize); + + } + } + + // else data in RAM + TINYCLR_NOCLEANUP(); + } + + + HRESULT LoadKnownAssemblies( char* start, char* end ) + { + //--// + TINYCLR_HEADER(); + char *assStart = start; + char *assEnd = end; + const CLR_RECORD_ASSEMBLY* header; + + TINYCLR_CHECK_HRESULT(CheckKnownAssembliesForNonXIP( &assStart, &assEnd )); +#if !defined(BUILD_RTM) + CLR_Debug::Printf(" Loading start at %x, end %x\r\n", (UINT32)assStart, (UINT32)assEnd); +#endif + + g_buildCRC = SUPPORT_ComputeCRC( assStart, (UINT32)assEnd -(UINT32) assStart, 0 ); + + + header = (const CLR_RECORD_ASSEMBLY*)assStart; + + while((char*)header + sizeof(CLR_RECORD_ASSEMBLY) < assEnd && header->GoodAssembly()) + { + CLR_RT_Assembly* assm; + + // Creates instance of assembly, sets pointer to native functions, links to g_CLR_RT_TypeSystem + TINYCLR_CHECK_HRESULT(LoadAssembly( header, assm )); + + header = (const CLR_RECORD_ASSEMBLY*)ROUNDTOMULTIPLE((size_t)header + header->TotalSize(), CLR_UINT32); + } + + TINYCLR_NOCLEANUP(); + } + + + HRESULT ContiguousBlockAssemblies( BlockStorageStream stream, BOOL isXIP ) + { + TINYCLR_HEADER(); + + const CLR_RECORD_ASSEMBLY* header; + BYTE * assembliesBuffer ; + INT32 headerInBytes = sizeof(CLR_RECORD_ASSEMBLY); + BYTE * headerBuffer = NULL; + + if(!isXIP) + { + headerBuffer = (BYTE*)CLR_RT_Memory::Allocate( headerInBytes, true ); CHECK_ALLOCATION(headerBuffer); + CLR_RT_Memory::ZeroFill( headerBuffer, headerInBytes ); + } + + while(TRUE) + { + if(!stream.Read( &headerBuffer, headerInBytes )) break; + + header = (const CLR_RECORD_ASSEMBLY*)headerBuffer; + + // check header first before read + if(!header->GoodHeader()) + { + break; + } + + UINT32 AssemblySizeInByte = ROUNDTOMULTIPLE(header->TotalSize(), CLR_UINT32); + + if(!isXIP) + { + // read the assemblies + assembliesBuffer = (BYTE*)CLR_RT_Memory::Allocate_And_Erase( AssemblySizeInByte, CLR_RT_HeapBlock ::HB_Unmovable ); + + if (!assembliesBuffer) + { + // release the headerbuffer which has being used and leave + CLR_RT_Memory::Release( headerBuffer ); + + TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_MEMORY); + } + } + + stream.Seek( -headerInBytes ); + + if(!stream.Read( &assembliesBuffer, AssemblySizeInByte )) break; + + header = (const CLR_RECORD_ASSEMBLY*)assembliesBuffer; + + if(!header->GoodAssembly()) + { + if(!isXIP) CLR_RT_Memory::Release( assembliesBuffer ); + break; + } + + // we have good Assembly + + CLR_RT_Assembly* assm; + + CLR_Debug::Printf( "Attaching deployed file.\r\n" ); + + // Creates instance of assembly, sets pointer to native functions, links to g_CLR_RT_TypeSystem + if (FAILED(LoadAssembly( header, assm ) )) + { + if(!isXIP) CLR_RT_Memory::Release( assembliesBuffer ); + break; + } + assm->m_flags |= CLR_RT_Assembly::c_Deployed; + } + if(!isXIP) CLR_RT_Memory::Release( headerBuffer ); + + TINYCLR_NOCLEANUP(); + } + + + HRESULT LoadDeploymentAssemblies( UINT32 memoryUsage ) + { + TINYCLR_HEADER(); + + BlockStorageStream stream; + const BlockDeviceInfo* deviceInfo; + + // find the block + if (!stream.Initialize( memoryUsage )) + { +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "ERROR: Could not find device for DEPLOYMENT usage\r\n" ); +#endif + TINYCLR_SET_AND_LEAVE(CLR_E_NOT_SUPPORTED); + } + + do + { + deviceInfo = stream.Device->GetDeviceInfo(); + + ContiguousBlockAssemblies( stream, deviceInfo->Attribute.SupportsXIP ); + } + while(stream.NextStream()); + + TINYCLR_NOCLEANUP(); + } + + void Cleanup() + { + g_CLR_RT_Persistence_Manager.Uninitialize(); + + CLR_RT_ExecutionEngine::DeleteInstance(); + +#if defined(_WIN32) + memset( &g_CLR_RT_Persistence_Manager, 0, sizeof(g_CLR_RT_Persistence_Manager) ); + memset( &g_CLR_RT_ExecutionEngine, 0, sizeof(g_CLR_RT_ExecutionEngine)); + memset( &g_CLR_RT_WellKnownTypes, 0, sizeof(g_CLR_RT_WellKnownTypes)); + + memset( &g_CLR_RT_WellKnownMethods, 0, sizeof(g_CLR_RT_WellKnownMethods)); + memset( &g_CLR_RT_TypeSystem, 0, sizeof(g_CLR_RT_TypeSystem)); + memset( &g_CLR_RT_EventCache, 0, sizeof(g_CLR_RT_EventCache)); + memset( &g_CLR_RT_GarbageCollector, 0, sizeof(g_CLR_RT_GarbageCollector)); + memset( &g_CLR_HW_Hardware, 0, sizeof(g_CLR_HW_Hardware)); +#endif + + m_fInitialized = false; + } + + Settings() + { + m_fInitialized = false; +#if defined(_WIN32) + BuildOptions(); +#endif + } + +#if defined(_WIN32) + ~Settings() + { + for(CLR_RT_ParseOptions::BufferMapIter it = m_assemblies.begin(); it != m_assemblies.end(); it++) + { + delete it->second; + } + + m_assemblies.clear(); // CLR_RT_ParseOptions::BufferMap m_assemblies; + } + + struct Command_Call : CLR_RT_ParseOptions::Command + { + typedef HRESULT (Settings::*FPN)( CLR_RT_ParseOptions::ParameterList* params ); + + Settings& m_parent; + FPN m_call; + + Command_Call( Settings& parent, FPN call, LPCWSTR szName, LPCWSTR szDescription ) + : CLR_RT_ParseOptions::Command( szName, szDescription ), m_parent(parent), m_call(call) + { + } + + virtual HRESULT Execute() + { + return (m_parent.*m_call)( &m_params ); + } + }; + +#define PARAM_GENERIC(parm1Name,parm1Desc) param = new CLR_RT_ParseOptions::Parameter_Generic( parm1Name, parm1Desc ); cmd->m_params.push_back( param ) +#define OPTION_CALL(fpn,optName,optDesc) cmd = new Command_Call( *this, &Settings::fpn, optName, optDesc ); m_commands.push_back( cmd ) +#define PARAM_EXTRACT_STRING(lst,idx) ((CLR_RT_ParseOptions::Parameter_Generic*)(*lst)[idx])->m_data.c_str() + + void BuildOptions() + { + CLR_RT_ParseOptions::Command* cmd; + CLR_RT_ParseOptions::Parameter* param; + + OPTION_CALL( Cmd_Load, L"-load", L"Loads an assembly formatted for TinyCLR" ); + PARAM_GENERIC( L"", L"File to load" ); + + OPTION_CALL( Cmd_LoadDatabase, L"-loadDatabase", L"Loads a set of assemblies" ); + PARAM_GENERIC( L"", L"Image to load" ); + + OPTION_CALL( Cmd_Resolve, L"-resolve", L"Tries to resolve cross-assembly references" ); + } + + HRESULT CheckAssemblyFormat( CLR_RECORD_ASSEMBLY* header, LPCWSTR src ) + { + TINYCLR_HEADER(); + + if(header->GoodAssembly() == false) + { + wprintf( L"Invalid assembly format for '%s': ", src ); + for(int i=0; imarker); i++) + { + wprintf( L"%02x", header->marker[i] ); + } + wprintf( L"\n" ); + + TINYCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + TINYCLR_NOCLEANUP(); + } + + HRESULT Cmd_Load( CLR_RT_ParseOptions::ParameterList* params = NULL ) + { + TINYCLR_HEADER(); + + LPCWSTR szName = PARAM_EXTRACT_STRING( params, 0 ); + CLR_RT_Buffer* buffer = new CLR_RT_Buffer(); + CLR_RECORD_ASSEMBLY* header; + + TINYCLR_CHECK_HRESULT(CLR_RT_FileStore::LoadFile( szName, *buffer )); + + header = (CLR_RECORD_ASSEMBLY*)&(*buffer)[0]; TINYCLR_CHECK_HRESULT(CheckAssemblyFormat( header, szName )); + + m_assemblies[szName] = buffer; + + TINYCLR_CLEANUP(); + + if(FAILED(hr)) + { + delete buffer; + } + + TINYCLR_CLEANUP_END(); + } + + + HRESULT Cmd_LoadDatabase( CLR_RT_ParseOptions::ParameterList* params = NULL ) + { + TINYCLR_HEADER(); + + if(!m_fInitialized) + { + CLR_RT_ExecutionEngine::CreateInstance(); + } + + { + LPCWSTR szFile = PARAM_EXTRACT_STRING( params, 0 ); + CLR_RT_Buffer buffer; + CLR_RECORD_ASSEMBLY* header; + CLR_RECORD_ASSEMBLY* headerEnd; + std::wstring strName; + + TINYCLR_CHECK_HRESULT(CLR_RT_FileStore::LoadFile( szFile, buffer )); + + header = (CLR_RECORD_ASSEMBLY*)&buffer[0 ]; + headerEnd = (CLR_RECORD_ASSEMBLY*)&buffer[buffer.size()-1]; + + while(header + 1 <= headerEnd && header->GoodAssembly()) + { + CLR_RT_Buffer* bufferSub = new CLR_RT_Buffer(); + CLR_RECORD_ASSEMBLY* headerSub; + CLR_RT_Assembly* assm; + + bufferSub->resize( header->TotalSize() ); + + headerSub = (CLR_RECORD_ASSEMBLY*)&(*bufferSub)[0]; + + if((CLR_UINT8*)header + header->TotalSize() > (CLR_UINT8*)headerEnd) + { + //checksum passed, but not enough data in assembly + _ASSERTE(FALSE); + delete bufferSub; + break; + } + memcpy( headerSub, header, header->TotalSize() ); + + m_assemblies[strName] = bufferSub; + + if(FAILED(hr = CLR_RT_Assembly::CreateInstance( headerSub, assm ))) + { + delete bufferSub; + break; + } + + CLR_RT_UnicodeHelper::ConvertFromUTF8( assm->m_szName, strName ); m_assemblies[strName] = bufferSub; + + assm->DestroyInstance(); + + header = (CLR_RECORD_ASSEMBLY*)ROUNDTOMULTIPLE( (size_t)header + header->TotalSize(), CLR_UINT32 ); + } + } + + TINYCLR_CLEANUP(); + + if(!m_fInitialized) + { + CLR_RT_ExecutionEngine::DeleteInstance(); + } + + TINYCLR_CLEANUP_END(); + } + + HRESULT Cmd_Resolve( CLR_RT_ParseOptions::ParameterList* params = NULL ) + { + TINYCLR_HEADER(); + + bool fError = false; + + TINYCLR_FOREACH_ASSEMBLY(g_CLR_RT_TypeSystem) + { + const CLR_RECORD_ASSEMBLYREF* src = (const CLR_RECORD_ASSEMBLYREF*)pASSM->GetTable( TBL_AssemblyRef ); + for(int i=0; im_pTablesSize[TBL_AssemblyRef]; i++, src++) + { + LPCSTR szName = pASSM->GetString( src->name ); + + if(g_CLR_RT_TypeSystem.FindAssembly( szName, &src->version, true ) == NULL) + { + printf( "Missing assembly: %s (%d.%d.%d.%d)\n", szName, src->version.iMajorVersion, src->version.iMinorVersion, src->version.iBuildNumber, src->version.iRevisionNumber ); + + fError = true; + } + } + } + TINYCLR_FOREACH_ASSEMBLY_END(); + + if(fError) TINYCLR_SET_AND_LEAVE(CLR_E_ENTRY_NOT_FOUND); + + TINYCLR_CHECK_HRESULT(g_CLR_RT_TypeSystem.ResolveAll()); + + TINYCLR_NOCLEANUP(); + } +#endif //#if defined(_WIN32) + +}; + +static Settings s_ClrSettings; + +//--// + +#if defined(_WIN32) +HRESULT ClrLoadPE( LPCWSTR szPeFilePath ) +{ + CLR_RT_StringVector vec; + + vec.push_back(L"-load"); + + vec.push_back(szPeFilePath); + + return s_ClrSettings.ProcessOptions(vec); +} + +HRESULT ClrLoadDAT( LPCWSTR szDatFilePath ) +{ + CLR_RT_StringVector vec; + + vec.push_back(L"-loadDatabase"); + + vec.push_back(szDatFilePath); + + return s_ClrSettings.ProcessOptions(vec); +} +#endif + + +void ClrStartup( CLR_SETTINGS params ) +{ + NATIVE_PROFILE_CLR_STARTUP(); + //Settings settings; + ASSERT(sizeof(CLR_RT_HeapBlock_Raw) == sizeof(CLR_RT_HeapBlock)); + bool softReboot; + + do + { + softReboot = false; + + CLR_RT_Assembly::InitString(); + +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "\r\nTinyCLR (Build %d.%d.%d.%d)\r\n\r\n", VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, VERSION_REVISION ); +#endif + + CLR_RT_Memory::Reset (); + +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Starting...\r\n" ); +#endif + + HRESULT hr; + + if(SUCCEEDED(hr = s_ClrSettings.Initialize(params))) + { + if(SUCCEEDED(hr = s_ClrSettings.Load())) + { +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Ready.\r\n" ); +#endif + +//#if defined(_WIN32) +// (void)g_CLR_RT_ExecutionEngine.Execute( params.EmulatorArgs, params.MaxContextSwitches ); +//#else + (void)g_CLR_RT_ExecutionEngine.Execute( NULL, params.MaxContextSwitches ); +//#endif + +#if !defined(BUILD_RTM) + CLR_Debug::Printf( "Done.\r\n" ); +#endif + } + } + + if( CLR_EE_DBG_IS_NOT( RebootPending )) + { +#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + CLR_EE_DBG_SET_MASK(State_ProgramExited, State_Mask); + CLR_EE_DBG_EVENT_BROADCAST(CLR_DBG_Commands::c_Monitor_ProgramExit, 0, NULL, WP_Flags::c_NonCritical); +#endif //#if defined(TINYCLR_ENABLE_SOURCELEVELDEBUGGING) + + if(params.EnterDebuggerLoopAfterExit) + { + CLR_DBG_Debugger::Debugger_WaitForCommands(); + } + } + + // DO NOT USE 'ELSE IF' here because the state can change in Debugger_WaitForCommands() call + + if( CLR_EE_DBG_IS( RebootPending )) + { + if(CLR_EE_REBOOT_IS( ClrOnly )) + { + softReboot = true; + + params.WaitForDebugger = CLR_EE_REBOOT_IS(ClrOnlyStopDebugger); + + s_ClrSettings.Cleanup(); + + // UNDONE: FIXME: HAL_Uninitialize(); + + // UNDONE: FIXME: SmartPtr_IRQ::ForceDisabled(); + + //re-init the hal for the reboot (initially it is called in bootentry) + // UNDONE: FIXME: HAL_Initialize(); + + // make sure interrupts are back on + // UNDONE: FIXME: SmartPtr_IRQ::ForceEnabled(); + } + else + { + CPU_Reset(); + } + } + } while( softReboot ); +} diff --git a/targets/os/win32/nanoCLR/Events.cpp b/targets/os/win32/nanoCLR/Events.cpp new file mode 100644 index 0000000000..bb5d0790d1 --- /dev/null +++ b/targets/os/win32/nanoCLR/Events.cpp @@ -0,0 +1,57 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "stdafx.h" + +//using namespace Microsoft::SPOT::Emulator; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +//--// + +BOOL Events_Initialize() +{ + return TRUE; // UNDONE: FIXME: EmulatorNative::GetIEventsDriver()->Initialize(); +} + +BOOL Events_Uninitialize() +{ + return TRUE; // UNDONE: FIXME: EmulatorNative::GetIEventsDriver()->Uninitialize(); +} + +void Events_Set( UINT32 Events ) +{ + // UNDONE: FIXME: EmulatorNative::GetIEventsDriver()->Set( Events ); +} + +UINT32 Events_Get( UINT32 EventsOfInterest ) +{ + return 0; // UNDONE: FIXME: EmulatorNative::GetIEventsDriver()->Get( EventsOfInterest ); +} + +void Events_Clear( UINT32 Events ) +{ + // UNDONE: FIXME: return EmulatorNative::GetIEventsDriver()->Clear( Events ); +} + +UINT32 Events_MaskedRead( UINT32 Events ) +{ + return 0; // UNDONE: FIXME: EmulatorNative::GetIEventsDriver()->MaskedRead( Events ); +} + +UINT32 Events_WaitForEvents( UINT32 powerLevel, UINT32 WakeupSystemEvents, UINT32 Timeout_Milliseconds ) +{ + return 0; // UNDONE: FIXME: EmulatorNative::GetIEventsDriver()->WaitForEvents( powerLevel, WakeupSystemEvents, Timeout_Milliseconds ); +} + +void Events_SetBoolTimer( BOOL* TimerCompleteFlag, UINT32 MillisecondsFromNow ) +{ + // UNDONE: FIXME: return EmulatorNative::GetIEventsDriver()->SetBoolTimer( (IntPtr)TimerCompleteFlag, MillisecondsFromNow ); +} + +//void Events_SetCallback( set_Event_Callback pfn, void* arg ) +//{ +// _ASSERTE(FALSE); +//} diff --git a/targets/os/win32/nanoCLR/FileStore_Win32.cpp b/targets/os/win32/nanoCLR/FileStore_Win32.cpp new file mode 100644 index 0000000000..c9bc8057bd --- /dev/null +++ b/targets/os/win32/nanoCLR/FileStore_Win32.cpp @@ -0,0 +1,253 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "stdafx.h" + + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT CLR_RT_FileStore::LoadFile( LPCWSTR szFile, CLR_RT_Buffer& vec ) +{ + TINYCLR_HEADER(); + + FILE* stream; +#if defined(PLATFORM_WINCE) + if((stream=_wfopen(szFile, L"rb"))==0) +#else + if(_wfopen_s(&stream, szFile, L"rb" ) != 0) +#endif + { + wprintf( L"Cannot open '%s'!\n", szFile ); + TINYCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + /*********/ fseek( stream, 0, SEEK_END ); + long size = ftell( stream ); + /*********/ fseek( stream, 0, SEEK_SET ); + + vec.resize( size ); + + if(vec.size() && fread( &vec[ 0 ], vec.size(), 1, stream ) != 1) + { + TINYCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + + TINYCLR_CLEANUP(); + + if(stream) + { + fclose( stream ); + } + + TINYCLR_CLEANUP_END(); +} + +HRESULT CLR_RT_FileStore::SaveFile( LPCWSTR szFile, const CLR_RT_Buffer& vec ) +{ + TINYCLR_HEADER(); + + const CLR_UINT8* buf = NULL; + size_t size = vec.size(); + + if(size > 0) + { + buf = &vec[ 0 ]; + } + + TINYCLR_SET_AND_LEAVE(SaveFile( szFile, buf, size )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_FileStore::SaveFile( LPCWSTR szFile, const CLR_UINT8* buf, size_t size ) +{ + TINYCLR_HEADER(); + FILE* stream; + +#if defined(PLATFORM_WINCE) + if((stream=_wfopen(szFile, L"wb"))==0) +#else + if(_wfopen_s(&stream, szFile, L"wb" ) != 0) +#endif + { + wprintf( L"Cannot open '%s' for writing!\n", szFile ); + TINYCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + + if(buf != NULL && size != 0) + { + if(fwrite( buf, size, 1, stream ) != 1) + { + TINYCLR_SET_AND_LEAVE(CLR_E_FAIL); + } + } + + TINYCLR_CLEANUP(); + + if(stream) + { + fclose( stream ); + } + + TINYCLR_CLEANUP_END(); +} + +//--// + +HRESULT CLR_RT_FileStore::ExtractTokensFromFile( LPCWSTR szFileName, std::vector< std::wstring >& vec, LPCWSTR separators, bool fNoComments ) +{ + TINYCLR_HEADER(); + + CLR_RT_Buffer buf; + + TINYCLR_CHECK_HRESULT(LoadFile( szFileName, buf )); + + ExtractTokens( buf, vec, separators, fNoComments ); + + TINYCLR_NOCLEANUP(); +} + +void CLR_RT_FileStore::ExtractTokens( const CLR_RT_Buffer& buf, CLR_RT_StringVector& vec, LPCWSTR separators, bool fNoComments ) +{ + std::wstring tmp; + LPSTR szBufA = NULL; + LPWSTR szBufW = NULL; + LPCWSTR src; + size_t len; + + if (buf.size() == 0) { return; } + else if(buf.size() >= 2 && buf[ 0 ] == 0xFF && buf[ 1 ] == 0xFE) + { + len = (buf.size() - 2) / sizeof(WCHAR); + + src = (LPCWSTR)&buf[ 2 ]; + } + else + { + len = buf.size() / sizeof(CHAR); + + szBufA = new CHAR[ len+1 ]; memcpy( szBufA, &buf[ 0 ], len ); szBufA[ len ] = 0; + CLR_RT_UnicodeHelper::ConvertFromUTF8( szBufA, tmp ); + + src = tmp.c_str(); + len = tmp.size(); + } + + //--// + + szBufW = new WCHAR[ len+1 ]; memcpy( szBufW, src, len * sizeof(WCHAR) ); szBufW[ len ] = 0; + + vec.reserve( len / 60 ); + + ExtractTokensFromBuffer( szBufW, vec, separators, fNoComments ); + + //--// + + delete[] szBufW; + delete[] szBufA; +} + +void CLR_RT_FileStore::ExtractTokensFromBuffer( LPWSTR szLine, CLR_RT_StringVector& vec, LPCWSTR separators, bool fNoComments ) +{ + while(*szLine) + { + LPWSTR szNextLine = szLine; + + while(*szNextLine) + { + if(*szNextLine == '\r' || *szNextLine == '\n') + { + while(*szNextLine == '\r' || *szNextLine == '\n') + { + *szNextLine++ = 0; + } + + break; + } + + szNextLine++; + } + + if(fNoComments == false || szLine[ 0 ] != '#') + { + CLR_RT_FileStore::ExtractTokensFromString( szLine, vec, separators ); + } + + szLine = szNextLine; + } +} + +void CLR_RT_FileStore::ExtractTokensFromString( LPCWSTR szLine, CLR_RT_StringVector& vec, LPCWSTR separators ) +{ + if(separators) + { + while(szLine[ 0 ] && wcschr( separators, szLine[0] )) szLine++; + + while(szLine[ 0 ]) + { + WCHAR token [ 2048 ]; +#if !defined(PLATFORM_WINCE) + WCHAR tokenExpanded[ 2048 ]; +#endif + bool fQuote = false; + size_t pos; + + for(pos=0; pos +#include +#include + +#define NATIVE_PROFILE_PAL_COM() + +////////////////////////////////////////////////////////////////////////////////// + +BOOL DebuggerPort_Initialize( COM_HANDLE ComPortNum ) +{ + NATIVE_PROFILE_PAL_COM(); + return true; +} + +BOOL DebuggerPort_Uninitialize( COM_HANDLE ComPortNum ) +{ + NATIVE_PROFILE_PAL_COM(); + return true; +} + + +int DebuggerPort_Write( COM_HANDLE ComPortNum, const char* Data, size_t size, int maxRetries ) +{ + NATIVE_PROFILE_PAL_COM(); + return 0; +} + + +int DebuggerPort_Read( COM_HANDLE ComPortNum, char* Data, size_t size ) +{ + NATIVE_PROFILE_PAL_COM(); + return 0; +} + +BOOL DebuggerPort_Flush( COM_HANDLE ComPortNum ) +{ + NATIVE_PROFILE_PAL_COM(); + return true; +} + +BOOL DebuggerPort_IsSslSupported( COM_HANDLE ComPortNum ) +{ + NATIVE_PROFILE_PAL_COM(); + return FALSE; +} + +BOOL DebuggerPort_UpgradeToSsl( COM_HANDLE ComPortNum, UINT32 flags ) +{ + NATIVE_PROFILE_PAL_COM(); + return FALSE; +} + +BOOL DebuggerPort_IsUsingSsl( COM_HANDLE ComPortNum ) +{ + NATIVE_PROFILE_PAL_COM(); + return FALSE; +} + +////////////////////////////////////////////////////////////////////////////////// + +void CPU_InitializeCommunication() +{ + NATIVE_PROFILE_PAL_COM(); +} + +void CPU_UninitializeCommunication() +{ + NATIVE_PROFILE_PAL_COM(); +} + + +void CPU_ProtectCommunicationGPIOs( BOOL On ) +{ + NATIVE_PROFILE_PAL_COM(); +} diff --git a/targets/os/win32/nanoCLR/PAL/ConfigHelper_stubs.cpp b/targets/os/win32/nanoCLR/PAL/ConfigHelper_stubs.cpp new file mode 100644 index 0000000000..b2171d50d9 --- /dev/null +++ b/targets/os/win32/nanoCLR/PAL/ConfigHelper_stubs.cpp @@ -0,0 +1,85 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "stdafx.h" + +//--// + +//BOOL HAL_CONFIG_BLOCK::IsGoodBlock() const +//{ +// return TRUE; +//} +// +//BOOL HAL_CONFIG_BLOCK::IsGoodData() const +//{ +// return TRUE; +//} +// +//BOOL HAL_CONFIG_BLOCK::IsGood() const +//{ +// return TRUE; +//} +// +//const HAL_CONFIG_BLOCK* HAL_CONFIG_BLOCK::Next() const +//{ +// return NULL; +//} +// +//const void* HAL_CONFIG_BLOCK::Data() const +//{ +// return NULL; +//} +// +////--// +// +//BOOL HAL_CONFIG_BLOCK::Prepare( const char* Name, void* Data, UINT32 Size ) +//{ +// return TRUE; +//} +// +////--// +// +//const HAL_CONFIG_BLOCK* HAL_CONFIG_BLOCK::Find( const char* Name, BOOL fSkipCurrent, BOOL fAppend ) const +//{ +// return NULL; +//} +// +////--// +// +//BOOL HAL_CONFIG_BLOCK::GetConfigSectorAddress(HAL_CONFIG_BLOCK_STORAGE_DATA& blData) +//{ +// return FALSE; +//} +// +//BOOL HAL_CONFIG_BLOCK::CompactBlock(HAL_CONFIG_BLOCK_STORAGE_DATA& blData, const ConfigurationSector* cfgStatic, const HAL_CONFIG_BLOCK* cfgEnd) +//{ +// return FALSE; +//} +// +// +//BOOL HAL_CONFIG_BLOCK::UpdateBlock( const HAL_CONFIG_BLOCK_STORAGE_DATA &blData, const void* pAddress, const HAL_CONFIG_BLOCK *Header, void* Data, size_t Length, const void* LastConfigAddress, BOOL isChipRO ) +//{ +// return FALSE; +//} +// +//BOOL HAL_CONFIG_BLOCK::UpdateBlockWithName( const char* Name, void* Data, size_t Length, BOOL isChipRO ) +//{ +// return FALSE; +//} +// +//BOOL HAL_CONFIG_BLOCK::ApplyConfig( const char* Name, void* Address, size_t Length ) +//{ +// return FALSE; +//} +//BOOL HAL_CONFIG_BLOCK::ApplyConfig( const char* Name, void* Address, size_t Length, void** newAlloc ) +//{ +// return FALSE; +//} + +unsigned int /* ie, BOOL */ GetHalSystemInfo(HalSystemInfo& systemInfo) +{ + return FALSE; +} + diff --git a/targets/os/win32/nanoCLR/PAL/Watchdog_stubs.cpp b/targets/os/win32/nanoCLR/PAL/Watchdog_stubs.cpp new file mode 100644 index 0000000000..3c45cb441d --- /dev/null +++ b/targets/os/win32/nanoCLR/PAL/Watchdog_stubs.cpp @@ -0,0 +1,28 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "stdafx.h" + +//--// + +BOOL Watchdog_GetSetEnabled( BOOL enabled, BOOL fSet ) +{ + return FALSE; +} + +UINT32 Watchdog_GetSetTimeout( INT32 timeout_ms , BOOL fSet ) +{ + return 0; +} + +//Watchdog_Behavior Watchdog_GetSetBehavior( Watchdog_Behavior behavior, BOOL fSet ) +//{ +// return Watchdog_Behavior__None; +//} + +BOOL Watchdog_LastOccurence( INT64& time, INT64& timeout, UINT32& assembly, UINT32& method, BOOL fSet ) +{ + return FALSE; +} diff --git a/targets/os/win32/nanoCLR/PAL/blockstorageList_stubs.cpp b/targets/os/win32/nanoCLR/PAL/blockstorageList_stubs.cpp new file mode 100644 index 0000000000..2ba364f9b0 --- /dev/null +++ b/targets/os/win32/nanoCLR/PAL/blockstorageList_stubs.cpp @@ -0,0 +1,136 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "stdafx.h" + +//--// + +HAL_DblLinkedList BlockStorageList::s_deviceList; +BlockStorageDevice* BlockStorageList::s_primaryDevice = NULL; + +//--// + +void BlockStorageList::Initialize() +{ +} + +BOOL BlockStorageList::InitializeDevices() +{ + return TRUE; +} + +BOOL BlockStorageList::UnInitializeDevices() +{ + return TRUE; +} + +BOOL BlockStorageList::AddDevice( BlockStorageDevice* pBSD, IBlockStorageDevice* vtable, void* config, BOOL Init) +{ + return TRUE; +} + +BOOL BlockStorageList::RemoveDevice( BlockStorageDevice* pBSD, BOOL UnInit) +{ + return TRUE; +} + +BlockStorageDevice* BlockStorageList::GetFirstDevice() +{ + return NULL; +} + +BlockStorageDevice* BlockStorageList::GetNextDevice( BlockStorageDevice& device ) +{ + return NULL; +} + +UINT32 BlockStorageList::GetNumDevices() +{ + return 0; +} + +BOOL BlockStorageList::FindDeviceForPhysicalAddress( BlockStorageDevice** pBSD, UINT32 PhysicalAddress, ByteAddress &SectAddress) +{ + *pBSD = NULL; + return FALSE; +} + +BOOL BlockStorageStream::Initialize(UINT32 blockUsage) +{ + return FALSE; +} + +BOOL BlockStorageStream::Initialize(UINT32 usage, BlockStorageDevice* pDevice) +{ + return FALSE; +} + + +UINT32 BlockStorageStream::CurrentAddress() +{ + return 0xFFFFFFFF; +} + +BOOL BlockStorageStream::PrevStream() +{ + return FALSE; +} + +BOOL BlockStorageStream::NextStream() +{ + return FALSE; +} + +BOOL BlockStorageStream::Seek( INT32 offset, SeekOrigin origin ) +{ + return TRUE; +} + +BOOL BlockStorageStream::Erase( UINT32 length ) +{ + return TRUE; +} + +BOOL BlockStorageStream::Write( UINT8* data , UINT32 length ) +{ + return TRUE; +} + +BOOL BlockStorageStream::ReadIntoBuffer( UINT8* pBuffer, UINT32 length ) +{ + return TRUE; +} + +BOOL BlockStorageStream::Read( UINT8** ppBuffer, UINT32 length ) +{ + return TRUE; +} + + +//--// + +SectorAddress BlockDeviceInfo::PhysicalToSectorAddress( const BlockRegionInfo* pRegion, ByteAddress phyAddress ) const +{ + return phyAddress; +} + +BOOL BlockDeviceInfo::FindRegionFromAddress(ByteAddress Address, UINT32 &BlockRegionIndex, UINT32 &BlockRangeIndex ) const +{ + return FALSE; +} + +BOOL BlockDeviceInfo::FindNextUsageBlock(UINT32 BlockUsage, ByteAddress &Address, UINT32 &BlockRegionIndex, UINT32 &BlockRangeIndex ) const +{ + return FALSE; +} + +BOOL BlockDeviceInfo::FindForBlockUsage(UINT32 BlockUsage, ByteAddress &Address, UINT32 &BlockRegionIndex, UINT32 &BlockRangeIndex ) const +{ + return FALSE; +} + + +//--// + diff --git a/targets/os/win32/nanoCLR/PAL/time_stubs.cpp b/targets/os/win32/nanoCLR/PAL/time_stubs.cpp new file mode 100644 index 0000000000..8b49b005e1 --- /dev/null +++ b/targets/os/win32/nanoCLR/PAL/time_stubs.cpp @@ -0,0 +1,107 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "stdafx.h" + +HRESULT Time_Initialize() +{ + return CLR_E_NOTIMPL; +} + +HRESULT Time_Uninitialize() +{ + return CLR_E_NOTIMPL; +} + +INT64 Time_GetUtcTime() +{ + return 0; +} + +INT64 Time_SetUtcTime( INT64 UtcTime, bool calibrate ) +{ + return 0; +} + +INT64 Time_GetLocalTime() +{ + return 0; +} + +INT32 Time_GetTimeZoneOffset() +{ + return 0; +} + +INT32 Time_SetTimeZoneOffset(INT32 offset) +{ + return 0; +} + +INT64 Time_GetTickCount() +{ + return 0; +} + +INT64 Time_GetMachineTime() +{ + return 0; +} + +BOOL Time_ToSystemTime(INT64 time, SYSTEMTIME* systemTime) +{ + return FALSE; +} + +INT64 Time_FromSystemTime(const SYSTEMTIME* systemTime) +{ + return 0; +} + +HRESULT Time_DaysInMonth(INT32 year, INT32 month, INT32* days) +{ + return CLR_E_NOTIMPL; +} + +HRESULT Time_AccDaysInMonth(INT32 year, INT32 month, INT32* days) +{ + return CLR_E_NOTIMPL; +} + +BOOL Utility_SafeSprintfV( LPSTR& szBuffer, size_t& iBuffer, LPCSTR format, va_list arg ) +{ + return FALSE; +} + +BOOL Utility_SafeSprintf( LPSTR& szBuffer, size_t& iBuffer, LPCSTR format, ... ) +{ + return FALSE; +} + +BOOL Time_TimeSpanToStringEx( const INT64& ticks, LPSTR& buf, size_t& len ) +{ + return FALSE; +} + +LPCSTR Time_TimeSpanToString( const INT64& ticks ) +{ + return NULL; +} + +BOOL Time_DateTimeToStringEx( const INT64& time, LPSTR& buf, size_t& len ) +{ + return FALSE; +} + +LPCSTR Time_DateTimeToString( const INT64& time) +{ + return NULL; +} + +LPCSTR Time_CurrentDateTimeToString() +{ + return NULL; +} + diff --git a/targets/os/win32/nanoCLR/ParseOptions_Win32.cpp b/targets/os/win32/nanoCLR/ParseOptions_Win32.cpp new file mode 100644 index 0000000000..dc2fea17b0 --- /dev/null +++ b/targets/os/win32/nanoCLR/ParseOptions_Win32.cpp @@ -0,0 +1,316 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "stdafx.h" + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +CLR_RT_ParseOptions::Parameter::Parameter( LPCWSTR szName, LPCWSTR szDescription ) +{ + m_szName = szName; + m_szDescription = szDescription; +} + +//--// + +CLR_RT_ParseOptions::Parameter_Generic::Parameter_Generic( LPCWSTR szName, LPCWSTR szDescription ) : CLR_RT_ParseOptions::Parameter( szName, szDescription ) +{ +} + +bool CLR_RT_ParseOptions::Parameter_Generic::Parse( LPCWSTR arg ) +{ + m_data = arg; + + return true; +} + +//--// + +CLR_RT_ParseOptions::Parameter_String::Parameter_String( std::wstring* data, LPCWSTR szName, LPCWSTR szDescription ) : CLR_RT_ParseOptions::Parameter( szName, szDescription ) +{ + m_dataPtr = data ? data : &m_dataParsed; +} + +bool CLR_RT_ParseOptions::Parameter_String::Parse( LPCWSTR arg ) +{ + *m_dataPtr = arg; + + return true; +} + +//--// + +CLR_RT_ParseOptions::Parameter_Boolean::Parameter_Boolean( bool* data, LPCWSTR szName, LPCWSTR szDescription ) : CLR_RT_ParseOptions::Parameter( szName, szDescription ) +{ + m_dataPtr = data ? data : &m_dataParsed; +} + +bool CLR_RT_ParseOptions::Parameter_Boolean::Parse( LPCWSTR arg ) +{ + int num; + + if(!_wcsicmp( arg, L"true" ) || + !_wcsicmp( arg, L"on" ) ) + { + *m_dataPtr = true; + return true; + } + + if(!_wcsicmp( arg, L"false" ) || + !_wcsicmp( arg, L"off" ) ) + { + *m_dataPtr = false; + return true; + } + + if(swscanf_s( arg, L"%d", &num ) == 0) + { + wprintf( L"Expecting a boolean for parameter '%s': %s\n\n", m_szName, arg ); + return false; + } + + *m_dataPtr = (num != 0); + return true; +} + +//--// + +CLR_RT_ParseOptions::Parameter_Integer::Parameter_Integer( int* data, LPCWSTR szName, LPCWSTR szDescription ) : CLR_RT_ParseOptions::Parameter( szName, szDescription ) +{ + m_dataPtr = data ? data : &m_dataParsed; +} + +bool CLR_RT_ParseOptions::Parameter_Integer::Parse( LPCWSTR arg ) +{ + if(swscanf_s( arg, L"%d", m_dataPtr ) == 0) + { + wprintf( L"Expecting a number for parameter '%s': %s\n\n", m_szName, arg ); + return false; + } + + return true; +} + +//--// + +CLR_RT_ParseOptions::Parameter_Float::Parameter_Float( float* data, LPCWSTR szName, LPCWSTR szDescription ) : CLR_RT_ParseOptions::Parameter( szName, szDescription ) +{ + m_dataPtr = data ? data : &m_dataParsed; +} + +bool CLR_RT_ParseOptions::Parameter_Float::Parse( LPCWSTR arg ) +{ + if(swscanf_s( arg, L"%f", m_dataPtr ) == 0) + { + wprintf( L"Expecting a number for parameter '%s': %s\n\n", m_szName, arg ); + return false; + } + + return true; +} + +//--// + +CLR_RT_ParseOptions::Command::Command( LPCWSTR szName, LPCWSTR szDescription ) +{ + m_szName = szName; + m_szDescription = szDescription; +} + +bool CLR_RT_ParseOptions::Command::Parse( CLR_RT_StringVector& argv, size_t& pos, CLR_RT_ParseOptions& options ) +{ + size_t argc = argv.size(); + + for(ParameterListIter it = m_params.begin(); it != m_params.end(); it++) + { + Parameter* param = *it; + + if(pos >= argc) + { + if(options.m_commands.size() > 1) + { + wprintf( L"Missing parameter for option '%s': %s\n\n", m_szName, param->m_szName ); + } + else + { + wprintf( L"Missing parameter for option '%s'\n\n", param->m_szName ); + } + + return false; + } + else + { + if(param->Parse( argv[ pos++ ].c_str() ) == false) + { + return false; + } + } + } + + return true; +} + +HRESULT CLR_RT_ParseOptions::Command::Execute() +{ + TINYCLR_HEADER(); + + TINYCLR_NOCLEANUP_NOLABEL(); +} + +//--// + +CLR_RT_ParseOptions::Command_SetFlag::Command_SetFlag( bool* data, LPCWSTR szName, LPCWSTR szDescription ) : CLR_RT_ParseOptions::Command( szName, szDescription ) +{ + m_dataPtr = data ? data : &m_dataParsed; +} + +bool CLR_RT_ParseOptions::Command_SetFlag::Parse( CLR_RT_StringVector& argv, size_t& pos, CLR_RT_ParseOptions& options) +{ + *m_dataPtr = true; + return true; +} + +//--// + +CLR_RT_ParseOptions::CLR_RT_ParseOptions() +{ + m_fVerbose = false; +} + +HRESULT CLR_RT_ParseOptions::ExtractOptionsFromFile( LPCWSTR szFileName ) +{ + TINYCLR_HEADER(); + + CLR_RT_StringVector vec; + + TINYCLR_CHECK_HRESULT(CLR_RT_FileStore::ExtractTokensFromFile( szFileName, vec )); + + TINYCLR_CHECK_HRESULT(ProcessOptions( vec )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ParseOptions::ReprocessOptions() +{ + TINYCLR_HEADER(); + + if(CommandLineArgs.size() == 0) + { + TINYCLR_SET_AND_LEAVE(CLR_E_NULL_REFERENCE); + } + + TINYCLR_SET_AND_LEAVE(ProcessOptions( CommandLineArgs )); + + TINYCLR_NOCLEANUP(); +} + +HRESULT CLR_RT_ParseOptions::ProcessOptions( CLR_RT_StringVector& argv ) +{ + TINYCLR_HEADER(); + + if(CommandLineArgs.size() == 0) + { + CommandLineArgs = CLR_RT_StringVector(argv); + } + + size_t argc = argv.size(); + + for(size_t i=0; im_szName )) + { + if(m_fVerbose) + { + size_t len = cmd->m_params.size(); + size_t pos = i; + + wprintf( L"Processing" ); + + wprintf( L" %s", arg ); + while(len-- > 0 && pos < argc) wprintf( L" %s", argv[ ++pos ].c_str() ); + wprintf( L"\n" ); + } + + i++; + + if(cmd->Parse( argv, i, *this ) == false) + { + Usage(); + TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + + + TINYCLR_CHECK_HRESULT(cmd->Execute()); + break; + } + } + + if(it == m_commands.end()) + { + wprintf( L"Unknown option '%s'\n\n", arg ); + + Usage(); + TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER); + } + } + + TINYCLR_NOCLEANUP(); +} + +void CLR_RT_ParseOptions::Usage() +{ + CommandListIter it; + ParameterListIter it2; + size_t maxCmdLen = 0; + + for(it = m_commands.begin(); it != m_commands.end(); it++) + { + Command* cmd = *it; + std::wstring option = cmd->m_szName; + size_t cmdLen = wcslen( cmd->m_szName ); + size_t maxLen = 0; + + wprintf( L" %s\n", cmd->m_szDescription ); + for(it2 = cmd->m_params.begin(); it2 != cmd->m_params.end(); it2++) + { + Parameter* param = *it2; + size_t len = wcslen( param->m_szName ); + + option += L" "; + option += param->m_szName; + + if(maxLen < len) maxLen = len; + } + + if(m_commands.size() > 1) + { + wprintf( L" %s\n", option.c_str()); + } + + for(it2 = cmd->m_params.begin(); it2 != cmd->m_params.end(); it2++) + { + Parameter* param = *it2; + + wprintf( L" %-*s = %s\n", maxLen, param->m_szName, param->m_szDescription ); + } + wprintf( L"\n" ); + } +} + +void CLR_RT_ParseOptions::PushArguments( int argc, LPWSTR argv[], CLR_RT_StringVector& vec ) +{ + for(int i=0; iSleep_MicroSeconds( uSec ); +} + +void HAL_Time_Sleep_MicroSeconds_InterruptEnabled( UINT32 uSec ) +{ + // UNDONE: FIXME: return EmulatorNative::GetITimeDriver()->Sleep_MicroSecondsInterruptsEnabled( uSec ); +} + +UINT64 HAL_Time_CurrentTicks() +{ + return 0; // UNDONE: FIXME: EmulatorNative::GetITimeDriver()->CurrentTicks(); +} + +INT64 HAL_Time_TicksToTime( UINT64 Ticks ) +{ + _ASSERTE(Ticks <= 0x7FFFFFFFFFFFFFFF); + + //No need to go to managed code just to return Time. + + return Ticks; +} + +INT64 HAL_Time_CurrentTime() +{ + return 0; // UNDONE: FIXME: EmulatorNative::GetITimeDriver()->CurrentTime(); +} + +void HAL_Time_GetDriftParameters ( INT32* a, INT32* b, INT64* c ) +{ + *a = 1; + *b = 1; + *c = 0; +} + +UINT32 CPU_SystemClock() +{ + return 0; // UNDONE: FIXME: EmulatorNative::GetITimeDriver()->SystemClock; +} + +UINT32 CPU_TicksPerSecond() +{ + return 0; // UNDONE: FIXME: EmulatorNative::GetITimeDriver()->TicksPerSecond; +} + +//Completions + +void HAL_COMPLETION::EnqueueDelta( UINT32 uSecFromNow ) +{ + // UNDONE: FIXME: EmulatorNative::GetITimeDriver()->EnqueueCompletion( (IntPtr)this, uSecFromNow ); +} + +void HAL_COMPLETION::EnqueueTicks( UINT64 EventTimeTicks ) +{ + _ASSERTE(FALSE); +} + +void HAL_COMPLETION::Abort() +{ + // UNDONE: FIXME: EmulatorNative::GetITimeDriver()->AbortCompletion( (IntPtr)this ); +} + +void HAL_COMPLETION::Execute() +{ + if(this->ExecuteInISR) + { + HAL_CONTINUATION* cont = this; + + cont->Execute(); + } + else + { + this->Enqueue(); + } +} + +//Continuations + +bool HAL_CONTINUATION::IsLinked() +{ + return false; // UNDONE: FIXME: EmulatorNative::GetITimeDriver()->IsLinked( (IntPtr)this ); +} + +BOOL HAL_CONTINUATION::Dequeue_And_Execute() +{ + return 0; // UNDONE: FIXME: EmulatorNative::GetITimeDriver()->DequeueAndExecuteContinuation(); +} + +void HAL_CONTINUATION::InitializeCallback( HAL_CALLBACK_FPN EntryPoint, void* Argument ) +{ + Initialize(); + + Callback.Initialize( EntryPoint, Argument ); +} + +void HAL_CONTINUATION::Enqueue() +{ + _ASSERTE(this->GetEntryPoint() != NULL); + + // UNDONE: FIXME: EmulatorNative::GetITimeDriver()->EnqueueContinuation( (IntPtr) this ); +} + +void HAL_CONTINUATION::Abort() +{ + // UNDONE: FIXME: EmulatorNative::GetITimeDriver()->AbortContinuation( (IntPtr) this ); +} + +//various + +//void CLR_RT_EmulatorHooks::Notify_ExecutionStateChanged() +//{ +// // UNDONE: FIXME: EmulatorNative::GetITimeDriver()->IsExecutionPaused = ClrIsDebuggerStopped(); +//} diff --git a/targets/os/win32/nanoCLR/TinyCLR_ParseOptions.h b/targets/os/win32/nanoCLR/TinyCLR_ParseOptions.h new file mode 100644 index 0000000000..d5e05c0e20 --- /dev/null +++ b/targets/os/win32/nanoCLR/TinyCLR_ParseOptions.h @@ -0,0 +1,136 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _TINYCLR_PARSEOPTIONS_H_ +#define _TINYCLR_PARSEOPTIONS_H_ + +//#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(_WIN32) + +struct CLR_RT_ParseOptions +{ + typedef std::map< std::wstring, CLR_RT_Buffer* > BufferMap; + typedef BufferMap::iterator BufferMapIter; + + struct Parameter + { + LPCWSTR m_szName; + LPCWSTR m_szDescription; + + Parameter( LPCWSTR szName, LPCWSTR szDescription ); + + virtual bool Parse( LPCWSTR val ) = 0; + }; + + typedef std::vector< Parameter* > ParameterList; + typedef ParameterList::iterator ParameterListIter; + + CLR_RT_StringVector CommandLineArgs; + + //--// + + struct Parameter_Generic : Parameter + { + std::wstring m_data; + + Parameter_Generic( LPCWSTR szName, LPCWSTR szDescription ); + + virtual bool Parse( LPCWSTR arg ); + }; + + struct Parameter_String : Parameter + { + std::wstring m_dataParsed; + std::wstring* m_dataPtr; + + Parameter_String( std::wstring* data, LPCWSTR szName, LPCWSTR szDescription ); + + virtual bool Parse( LPCWSTR arg ); + }; + + struct Parameter_Boolean : Parameter + { + bool m_dataParsed; + bool* m_dataPtr; + + Parameter_Boolean( bool* data, LPCWSTR szName, LPCWSTR szDescription ); + + virtual bool Parse( LPCWSTR arg ); + }; + + struct Parameter_Integer : Parameter + { + int m_dataParsed; + int* m_dataPtr; + + Parameter_Integer( int* data, LPCWSTR szName, LPCWSTR szDescription ); + + virtual bool Parse( LPCWSTR arg ); + }; + + struct Parameter_Float : Parameter + { + float m_dataParsed; + float* m_dataPtr; + + Parameter_Float( float* data, LPCWSTR szName, LPCWSTR szDescription ); + + virtual bool Parse( LPCWSTR arg ); + }; + + //--// + + struct Command + { + LPCWSTR m_szName; + LPCWSTR m_szDescription; + ParameterList m_params; + + Command( LPCWSTR szName, LPCWSTR szDescription ); + + virtual bool Parse( CLR_RT_StringVector& argv, size_t& pos, CLR_RT_ParseOptions& options ); + + virtual HRESULT Execute(); + }; + + typedef std::list< Command* > CommandList; + typedef CommandList::iterator CommandListIter; + + //--// + + struct Command_SetFlag : Command + { + bool m_dataParsed; + bool* m_dataPtr; + + Command_SetFlag( bool* data, LPCWSTR szName, LPCWSTR szDescription ); + + virtual bool Parse( CLR_RT_StringVector& argv, size_t& pos, CLR_RT_ParseOptions& options ); + }; + + //--// + + bool m_fVerbose; + CommandList m_commands; + + //--// + + CLR_RT_ParseOptions(); + + HRESULT ExtractOptionsFromFile( LPCWSTR szFileName ); + + HRESULT ReprocessOptions(); + HRESULT ProcessOptions( CLR_RT_StringVector& vec ); + void PushArguments ( int argc, LPWSTR argv[], CLR_RT_StringVector& vec ); + + virtual void Usage(); +}; + +#endif + +#endif // _TINYCLR_PARSEOPTIONS_H_ diff --git a/targets/os/win32/nanoCLR/Various.cpp b/targets/os/win32/nanoCLR/Various.cpp new file mode 100644 index 0000000000..856a32100d --- /dev/null +++ b/targets/os/win32/nanoCLR/Various.cpp @@ -0,0 +1,614 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "stdafx.h" + +#include "platform_selector.h" +//--// + +//using namespace System; +//using namespace System::Diagnostics; +//using namespace Microsoft::SPOT::Emulator; + +BOOL HAL_Windows_IsShutdownPending() +{ + return FALSE; //return EmulatorNative::GetEmulatorNative()->IsShuttingDown(); +} + +void HAL_Windows_AcquireGlobalLock() +{ + // UNDONE: FIXME: EmulatorNative::GetEmulatorNative()->DisableInterrupts(); +} + +void HAL_Windows_ReleaseGlobalLock() +{ + // UNDONE: FIXME: EmulatorNative::GetEmulatorNative()->EnableInterrupts(); +} + +BOOL HAL_Windows_HasGlobalLock() +{ + return FALSE; // UNDONE: FIXME: !EmulatorNative::GetEmulatorNative()->AreInterruptsEnabled(); +} + +UINT64 HAL_Windows_GetPerformanceTicks() +{ + return 0; // UNDONE: FIXME: return EmulatorNative::GetEmulatorNative()->GetCurrentTicks(); +} + +void HAL_Windows_Debug_Print( LPSTR szText ) +{ + // UNDONE: FIXME: System::Diagnostics::Debug::Print( gcnew System::String(szText) ); +} + + +//HAL_Configuration_Windows g_HAL_Configuration_Windows; + +//UINT32 LOAD_IMAGE_CalcCRC; + +//OEM_MODEL_SKU OEM_Model_SKU = { 1, 2, 3 }; + +HAL_SYSTEM_CONFIG HalSystemConfig = +{ + { TRUE }, // HAL_DRIVER_CONFIG_HEADER Header; + + //--// + + { // UINT32 DebuggerPorts[MAX_DEBUGGERS]; + DEBUGGER_PORT, + }, + + { + MESSAGING_PORT, + }, + + DEBUG_TEXT_PORT, + 115200, + 0, // STDIO = COM2 or COM1 + + { 0, 0 }, // { SRAM1_MEMORY_Base, SRAM1_MEMORY_Size }, + { 0, 0 }, // { FLASH_MEMORY_Base, FLASH_MEMORY_Size }, +}; + +//const ConfigurationSector g_ConfigurationSector = +//{ +// // ConfigurationLength +// offsetof(ConfigurationSector, FirstConfigBlock), +// +// //CONFIG_SECTOR_VERSION +// { +// ConfigurationSector::c_CurrentVersionMajor, +// ConfigurationSector::c_CurrentVersionMinor, +// ConfigurationSector::c_CurrentVersionTinyBooter, +// 0, // extra +// }, +// +// // backwards compatibility buffer (88 bytes to put booterflagarray at offset 96) +// { +// 0x0, +// }, +// +// // BooterFlagArray - determines if we enter the tinybooter or not +// { +// 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, +// 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, +// 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, +// 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, +// 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, +// }, +// +// // UINT32 SectorSignatureCheck[9*8]; // 287 sectors max * 8 changes before erase +// { +// 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, +// 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, +// 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, +// 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, +// 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, +// 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, +// 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, +// 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, +// }, +// +// //TINYBOOTER_KEY_CONFIG DeploymentKey = +// { +// {// ODM key configuration for programming firmware (non deployment sectors) +// { // ODM public key for firware sectors +// // exponent length +// 0xFF,0xFF,0xFF, 0xFF, +// +// // module +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// +// // exponent +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// } +// }, +// {// OEM key configuration for programming Deployment sector +// { // OEM public key for Deployment sector +// // exponent length +// 0xFF,0xFF,0xFF, 0xFF, +// +// // module +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// +// // exponent +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +// } +// } +// }, +// +// //--//--//--// +// +// // OEM_MODEL_SKU OEM_Model_SKU; +// { +// 1, // UINT8 OEM; +// 2, // UINT8 Model; +// 3, // UINT16 SKU; +// }, +// +// //--//--//--// +// +// // OEM_SERIAL_NUMBERS OemSerialNumbers +// { +// { 0, }, +// { 0, } // UINT8 system_serial_number[16]; +// }, +// +// // CLR Config Data +// { +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +// }, +// +// //--//--//--// +// +// // HAL_CONFIG_BLOCK FirstConfigBlock; +// { +// HAL_CONFIG_BLOCK::c_Version_V2, // UINT32 Signature; +// 0x8833794c, // UINT32 HeaderCRC; +// 0x00000000, // UINT32 DataCRC; +// 0x00000000, // UINT32 Size; +// // char DriverName[64]; +// }, +//}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +static ON_SOFT_REBOOT_HANDLER s_rebootHandlers[5] = {NULL, NULL, NULL, NULL, NULL}; + +void __cdecl HAL_AddSoftRebootHandler(ON_SOFT_REBOOT_HANDLER handler) +{ + for(int i=0; i 0) + { + ::QueryPerformanceFrequency( &frequency ); + + ::QueryPerformanceCounter ( &countStart ); + + double ratio = (double)TIME_CONVERSION__TO_SECONDS / (double)frequency.QuadPart; + + countEnd.QuadPart = (INT64)(((countStart.QuadPart * ratio) + ticks) / ratio); + + while(countStart.QuadPart < countEnd.QuadPart) + { + ::QueryPerformanceCounter( &countStart ); + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma managed(push, off) + +void debug_printf( char const* format, ... ) +{ + va_list arg_ptr; + + va_start( arg_ptr, format ); + + int chars = hal_vprintf( format, arg_ptr ); + + va_end( arg_ptr ); +} + +void lcd_printf( char const * format, ... ) +{ + va_list arg_ptr; + + va_start( arg_ptr, format ); + + int chars = hal_vprintf( format, arg_ptr ); + + va_end( arg_ptr ); +} + +int hal_printf( const char* format, ... ) +{ + va_list arg_ptr; + + va_start(arg_ptr, format); + + int chars = hal_vprintf( format, arg_ptr ); + + va_end( arg_ptr ); + + return chars; +} + +int hal_vprintf( const char* format, va_list arg ) +{ + return vprintf( format, arg ); +} + + +int hal_fprintf( COM_HANDLE stream, const char* format, ... ) +{ + va_list arg_ptr; + int chars; + + va_start( arg_ptr, format ); + + chars = hal_vfprintf( stream, format, arg_ptr ); + + va_end( arg_ptr ); + + return chars; +} + +int hal_vfprintf( COM_HANDLE stream, const char* format, va_list arg ) +{ + char buffer[512]; + int chars = 0; + + chars = hal_vsnprintf( buffer, sizeof(buffer), format, arg ); + + //switch(ExtractTransport(stream)) + //{ + //default: + DebuggerPort_Write( stream, buffer, chars, 0 ); // skip null terminator + // break; + + //case LCD_TRANSPORT: + // break; + + //case FLASH_WRITE_TRANSPORT: + // _ASSERTE(FALSE); + //} + + return chars; +} + +int hal_snprintf( char* buffer, size_t len, const char* format, ... ) +{ + va_list arg_ptr; + int chars; + + va_start( arg_ptr, format ); + + chars = hal_vsnprintf( buffer, len, format, arg_ptr ); + + va_end( arg_ptr ); + + return chars; +} + +int hal_vsnprintf( char* buffer, size_t len, const char* format, va_list arg ) +{ + return _vsnprintf_s( buffer, len, len-1/* force space for trailing zero*/, format, arg ); +} + +#pragma managed(pop) + +/////////////////////////////////////////////////////////////// + +size_t CPU_GetCachableAddress( size_t address ) +{ + return address; +} + +//--// + +size_t CPU_GetUncachableAddress( size_t address ) +{ + return address; +} + +/////////////////////////////////////////////////////////////// + +BOOL Charger_Status( UINT32& Status ) +{ + return TRUE; +} + +/////////////////////////////////////////////////////////////// + +//SmartPtr_IRQ::SmartPtr_IRQ(void* context) +//{ +// m_context = context; +// Disable(); +//} +// +//SmartPtr_IRQ::~SmartPtr_IRQ() +//{ +// Restore(); +//} +// +//void SmartPtr_IRQ::Release() +//{ +// HAL_Windows_ReleaseGlobalLock(); +//} +// +//void SmartPtr_IRQ::Disable() +//{ +// HAL_Windows_AcquireGlobalLock(); +//} +// +//void SmartPtr_IRQ::Restore() +//{ +// HAL_Windows_ReleaseGlobalLock(); +//} +// +//BOOL SmartPtr_IRQ::ForceDisabled(void* context) +//{ +// BOOL ret = GetState(); +// +// HAL_Windows_AcquireGlobalLock(); +// +// return ret; +//} +// +//BOOL SmartPtr_IRQ::ForceEnabled(void* context) +//{ +// BOOL ret = GetState(); +// +// HAL_Windows_ReleaseGlobalLock(); +// +// return ret; +//} +// +// +//BOOL SmartPtr_IRQ::GetState(void* context) +//{ +// return HAL_Windows_HasGlobalLock(); +//} diff --git a/targets/os/win32/nanoCLR/WatchDog.cpp b/targets/os/win32/nanoCLR/WatchDog.cpp new file mode 100644 index 0000000000..a849a416f0 --- /dev/null +++ b/targets/os/win32/nanoCLR/WatchDog.cpp @@ -0,0 +1,29 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#include "stdafx.h" + +//--// + +//HRESULT Watchdog_Enable( UINT32 TimeoutMilliseconds, WATCHDOG_INTERRUPT_CALLBACK callback, void* context ) +//{ +// return S_OK; // UNDONE: FIXME: return EmulatorNative::GetIWatchdogDriver()->Enable( TimeoutMilliseconds ); +//} + +void Watchdog_Disable() +{ + // UNDONE: FIXME: EmulatorNative::GetIWatchdogDriver()->Disable(); +} + +void Watchdog_ResetCpu() +{ + // UNDONE: FIXME: EmulatorNative::GetIWatchdogDriver()->ResetCpu(); +} + +void Watchdog_ResetCounter() +{ + // UNDONE: FIXME: EmulatorNative::GetIWatchdogDriver()->ResetCounter(); +} + diff --git a/targets/os/win32/nanoCLR/main.cpp b/targets/os/win32/nanoCLR/main.cpp new file mode 100644 index 0000000000..8fd9ecd4eb --- /dev/null +++ b/targets/os/win32/nanoCLR/main.cpp @@ -0,0 +1,88 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// +#include "stdafx.h" + +#include + + +// +// UNDONE: Feature configuration +// + +#define NF_CLR_FEATURE_ALL + +#if defined(NF_CLR_FEATURE_ALL) + +#pragma comment(lib, "WireProtocol.lib") + +#pragma comment(lib, "Debugger.lib") +#pragma comment(lib, "Diagnostics.lib") +#pragma comment(lib, "Hardware.lib") +#pragma comment(lib, "HeapPersistence.lib") +#pragma comment(lib, "InterruptHandler.lib") +#pragma comment(lib, "Messaging.lib") +#pragma comment(lib, "RPC.lib") +#pragma comment(lib, "Serialization.lib") + +#else + +#pragma comment(lib, "WireProtocol.lib") // UNDONE: FIXME: SUPPORT_ComputeCRC required by TypeSystem.cpp, CLR_RT_HeapBlock + +#pragma comment(lib, "Debugger_stub.lib") +#pragma comment(lib, "Diagnostics_stub.lib") +#pragma comment(lib, "Hardware_stub.lib") +#pragma comment(lib, "HeapPersistence_stub.lib") +#pragma comment(lib, "InterruptHandler_stub.lib") +#pragma comment(lib, "IOPort_stub.lib") +#pragma comment(lib, "Messaging_stub.lib") +#pragma comment(lib, "RPC_stub.lib") +#pragma comment(lib, "Serialization_stub.lib") + + +#endif + + + + + + + +///////////////////////////////////////////////////////////////////////////// + + +// All solutions are expected to provide an implementation of this +unsigned int Solution_GetReleaseInfo(MfReleaseInfo& releaseInfo) +{ + MfReleaseInfo::Init(releaseInfo, + VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, VERSION_REVISION, + OEMSYSTEMINFOSTRING, hal_strlen_s(OEMSYSTEMINFOSTRING) + ); + return TRUE; // alternatively, return false if you didn't initialize the releaseInfo structure. +} + +///////////////////////////////////////////////////////////////////////////// +// + +int main() +{ + //void ApplicationEntryPoint() + + CLR_SETTINGS clrSettings; + ZeroMemory(&clrSettings, sizeof(clrSettings)); + + clrSettings.MaxContextSwitches = 50; + clrSettings.WaitForDebugger = false; + clrSettings.EnterDebuggerLoopAfterExit = true; + + ClrStartup(clrSettings); + +//#if !defined(BUILD_RTM) +// debug_printf( "Exiting.\r\n" ); +//#else + //::CPU_Reset(); +//#endif + + return 0; +} diff --git a/targets/os/win32/nanoCLR/nanoCLR.vcxproj b/targets/os/win32/nanoCLR/nanoCLR.vcxproj new file mode 100644 index 0000000000..599b078b65 --- /dev/null +++ b/targets/os/win32/nanoCLR/nanoCLR.vcxproj @@ -0,0 +1,314 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {B5515C8A-B056-4320-8EA4-8CACE21A7D2E} + Win32Proj + nanoCLR + 10.0.14393.0 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + true + $(BinDir) + $(IntDir) + + + true + $(BinDir) + $(IntDir) + + + false + $(BinDir) + $(IntDir) + + + false + $(BinDir) + $(IntDir) + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..\..\..\src\CLR\Include + + + Console + $(BinDir) + + + + + Use + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + $(BinDir) + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + $(BinDir) + + + + + Level3 + Use + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + $(BinDir) + + + + + + + + + + + + + + + + + NotUsing + + + + + + + Create + Create + Create + Create + + + + + Use + + + + + + {89cf8bdb-9c8a-4d18-bc3e-4312c5bd34b1} + + + {5d50772e-dac8-407d-972f-37deb4450b72} + false + false + false + + + {31253d7f-147e-49a3-bc0d-e0ade6cf040b} + false + false + false + + + {bc2245b0-32e0-410e-b3f2-e2bfa0b503b3} + false + false + false + + + {4646f661-9505-45c2-9573-8409a9dd1149} + false + false + false + + + {d32ee397-7e49-452d-ac95-afcb3c962e3d} + false + false + false + + + {5772d362-7277-49cf-9b49-42335a3154bd} + false + false + false + + + {6dd5ca4f-2ae9-44d3-b9d7-a2a4a35fc5b2} + false + false + false + + + {5406eb0c-2243-47e1-9f21-f2d7ca277092} + false + false + false + + + {ed4c887a-ec09-465b-b5d9-075450adc52d} + false + false + false + + + {d0b2adfe-3347-4d73-9364-9c36935d12f8} + false + false + false + + + {16bf6131-a3b8-4b97-b867-e45669fb48bd} + false + false + false + + + {c337041d-344d-49fe-ad99-b137e7fd0188} + false + false + false + + + {58e950cc-2ff6-423c-b006-a70a19272f20} + + + {dd397ec4-844b-4b59-a67b-cad6b46f1f00} + false + false + false + + + {6dabcbf1-245a-4e76-bd36-8bc300c7dd82} + false + false + false + + + {a5e9ae41-f4fa-40ce-ad82-a7861eba007b} + false + false + false + + + {c97a9845-02dc-46e4-b219-bf5ea8fb28e3} + false + false + false + + + {131001e3-0201-451f-a87b-951d1c5c3eee} + false + false + false + + + {8acd05e8-42fb-4a49-9d8b-79239f0eed25} + false + false + false + + + {2a840dc3-ffa8-4562-bd13-ab2b0ba02cb6} + + + {2337c4a4-3ab4-4014-9c29-9ebe32f4510e} + false + false + false + + + + + + \ No newline at end of file diff --git a/targets/os/win32/nanoCLR/nanoCLR.vcxproj.filters b/targets/os/win32/nanoCLR/nanoCLR.vcxproj.filters new file mode 100644 index 0000000000..ceec54a3fc --- /dev/null +++ b/targets/os/win32/nanoCLR/nanoCLR.vcxproj.filters @@ -0,0 +1,87 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {4a8f1020-5d97-4a6f-b9c1-1460ae41f71b} + + + {917f0887-d239-439f-b246-e18c1f726304} + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files\PAL + + + Source Files\PAL + + + Source Files\PAL + + + Source Files\PAL + + + Source Files\PAL + + + Source Files + + + Source Files + + + Source Files + + + Source Files\Generated + + + Source Files + + + \ No newline at end of file diff --git a/targets/os/win32/nanoCLR/platform_selector.h b/targets/os/win32/nanoCLR/platform_selector.h new file mode 100644 index 0000000000..a20de293ca --- /dev/null +++ b/targets/os/win32/nanoCLR/platform_selector.h @@ -0,0 +1,83 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#ifndef _PLATFORM_WINDOWS_SELECTOR_H_ +#define _PLATFORM_WINDOWS_SELECTOR_H_ 1 + +#define PLATFORM_WINDOWS_EMULATOR 1 + +///////////////////////////////////////////////////////// +// +// macros +// + +#define FAT_FS__VALIDATE_READONLY_CACHELINE 1 +//#define FAT_FS__DO_NOT_UPDATE_FILE_ACCESS_TIME 1 +#define FAT_FS__CACHE_FLUSH_TIMEOUT_USEC (5*1000*1000) + +// UNDONE: FIXME: TinyHAL.h +//#define GLOBAL_LOCK(x) SmartPtr_IRQ x +////#define DISABLE_INTERRUPTS() SmartPtr_IRQ::ForceDisabled() +////#define ENABLE_INTERRUPTS() SmartPtr_IRQ::ForceEnabled() +////#define INTERRUPTS_ENABLED_STATE() SmartPtr_IRQ::GetState() +//#define GLOBAL_LOCK_SOCKETS(x) SmartPtr_IRQ x +// +//#if defined(_DEBUG) +//#define ASSERT_IRQ_MUST_BE_OFF() ASSERT( HAL_Windows_HasGlobalLock()) +//#define ASSERT_IRQ_MUST_BE_ON() ASSERT(!HAL_Windows_HasGlobalLock()) +//#else +//#define ASSERT_IRQ_MUST_BE_OFF() +//#define ASSERT_IRQ_MUST_BE_ON() +//#endif + +// +// macros +// +///////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////// +// +// constants +// +#define PRODUCT_WATCH 1 +#define PRODUCT_AUXDISPLAY 1 + +// Port definitions +#define TOTAL_USART_PORT 2 +#define COM1 ConvertCOM_ComHandle(0) +#define COM2 ConvertCOM_ComHandle(1) + +#define TOTAL_USB_CONTROLLER 1 +#define USB1 ConvertCOM_UsbHandle(0) + +#define TOTAL_DEBUG_PORT 1 +#define COM_DEBUG ConvertCOM_DebugHandle(0) + +#define TOTAL_MESSAGING_PORT 1 +#define COM_MESSAGING ConvertCOM_MessagingHandle(0) + +#define DEBUG_TEXT_PORT COM_DEBUG +#define DEBUGGER_PORT COM_DEBUG +#define MESSAGING_PORT COM_DEBUG + +#define PLATFORM_DEPENDENT_TX_USART_BUFFER_SIZE 512 // there is one TX for each usart port +#define PLATFORM_DEPENDENT_RX_USART_BUFFER_SIZE 512 // there is one RX for each usart port +#define PLATFORM_DEPENDENT_USB_QUEUE_PACKET_COUNT 2 // there is one queue for each pipe of each endpoint and the size of a single packet is sizeof(USB_PACKET64) == 68 bytes + + +// These are configuration for FATFS, uncomment if non-default values are needed +//#define PLATFORM_DEPENDENT_FATFS_SECTORCACHE_MAXSIZE 8 +//#define PLATFORM_DEPENDENT_FATFS_SECTORCACHE_LINESIZE 2048 +//#define PLATFORM_DEPENDENT_FATFS_MAX_OPEN_HANDLES 8 +#define PLATFORM_DEPENDENT_FATFS_MAX_VOLUMES 8 +// +// constants +// +///////////////////////////////////////////////////////// + +//#include + +#endif // _PLATFORM_WINDOWS_SELECTOR_H_ 1 + diff --git a/targets/os/win32/nanoCLR/stdafx.cpp b/targets/os/win32/nanoCLR/stdafx.cpp new file mode 100644 index 0000000000..13fac94279 --- /dev/null +++ b/targets/os/win32/nanoCLR/stdafx.cpp @@ -0,0 +1,12 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// +// stdafx.cpp : source file that includes just the standard includes +// test.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/targets/os/win32/nanoCLR/stdafx.h b/targets/os/win32/nanoCLR/stdafx.h new file mode 100644 index 0000000000..eb4861d408 --- /dev/null +++ b/targets/os/win32/nanoCLR/stdafx.h @@ -0,0 +1,26 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" + +#include +#include + +//#include + +// TODO: reference additional headers your program requires here + +#include +#include +#include +#include + +#include "TinyCLR_ParseOptions.h" diff --git a/targets/os/win32/nanoCLR/targetver.h b/targets/os/win32/nanoCLR/targetver.h new file mode 100644 index 0000000000..a392d7e3fa --- /dev/null +++ b/targets/os/win32/nanoCLR/targetver.h @@ -0,0 +1,12 @@ +// +// Copyright (c) 2017 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include diff --git a/targets/os/win32/netmf/MFConsoleApplication/MFConsoleApplication.csproj b/targets/os/win32/netmf/MFConsoleApplication/MFConsoleApplication.csproj new file mode 100644 index 0000000000..3d6895f5f2 --- /dev/null +++ b/targets/os/win32/netmf/MFConsoleApplication/MFConsoleApplication.csproj @@ -0,0 +1,44 @@ + + + + MFConsoleApplication + Exe + MFConsoleApplication + {b69e3092-b931-443c-abe7-7e7b65f2a37f};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 9.0.21022 + 2.0 + {F2568B98-AA05-441C-BAFE-9AA5C01F1B65} + v4.4 + $(MSBuildExtensionsPath32)\Microsoft\.NET Micro Framework\ + SAK + SAK + SAK + SAK + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + \ No newline at end of file diff --git a/targets/os/win32/netmf/MFConsoleApplication/MFConsoleApplication.sln b/targets/os/win32/netmf/MFConsoleApplication/MFConsoleApplication.sln new file mode 100644 index 0000000000..d7f72877dd --- /dev/null +++ b/targets/os/win32/netmf/MFConsoleApplication/MFConsoleApplication.sln @@ -0,0 +1,24 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MFConsoleApplication", "MFConsoleApplication.csproj", "{F2568B98-AA05-441C-BAFE-9AA5C01F1B65}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F2568B98-AA05-441C-BAFE-9AA5C01F1B65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F2568B98-AA05-441C-BAFE-9AA5C01F1B65}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F2568B98-AA05-441C-BAFE-9AA5C01F1B65}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {F2568B98-AA05-441C-BAFE-9AA5C01F1B65}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F2568B98-AA05-441C-BAFE-9AA5C01F1B65}.Release|Any CPU.Build.0 = Release|Any CPU + {F2568B98-AA05-441C-BAFE-9AA5C01F1B65}.Release|Any CPU.Deploy.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/targets/os/win32/netmf/MFConsoleApplication/Program.cs b/targets/os/win32/netmf/MFConsoleApplication/Program.cs new file mode 100644 index 0000000000..2cd8123b27 --- /dev/null +++ b/targets/os/win32/netmf/MFConsoleApplication/Program.cs @@ -0,0 +1,13 @@ +using System; +using Microsoft.SPOT; + +namespace MFConsoleApplication +{ + public class Program + { + public static void Main() + { + Debug.Print("Hello World"); + } + } +} diff --git a/targets/os/win32/netmf/MFConsoleApplication/Properties/AssemblyInfo.cs b/targets/os/win32/netmf/MFConsoleApplication/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..f97f80692b --- /dev/null +++ b/targets/os/win32/netmf/MFConsoleApplication/Properties/AssemblyInfo.cs @@ -0,0 +1,23 @@ +using System.Reflection; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("MFConsoleApplication")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("MFConsoleApplication")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")]