From 0dcb6ee24ca4d7c959ee55e09abc34c727799fb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20K=C3=B6plinger?= Date: Sat, 6 Dec 2025 00:29:09 +0100 Subject: [PATCH 1/4] Fix BuildOS when cross-building from linux-musl (#3702) --- eng/RuntimeIdentifier.props | 1 + 1 file changed, 1 insertion(+) diff --git a/eng/RuntimeIdentifier.props b/eng/RuntimeIdentifier.props index bd5d12e8fbda..7f4e993f9836 100644 --- a/eng/RuntimeIdentifier.props +++ b/eng/RuntimeIdentifier.props @@ -2,6 +2,7 @@ linux + linux-musl osx freebsd netbsd From 0acbd55b3012879aa3b84d39b9bf714553c95e47 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Sat, 6 Dec 2025 15:42:28 +0000 Subject: [PATCH 2/4] [main] Source code updates from dotnet/runtime (#3722) [main] Source code updates from dotnet/runtime --- src/runtime/eng/Subsets.props | 4 +- src/runtime/eng/Version.Details.props | 2 +- src/runtime/eng/Version.Details.xml | 4 +- .../runtime-extra-platforms-wasm.yml | 9 +- src/runtime/eng/pipelines/runtime.yml | 2 + .../SupportFiles/Directory.Build.targets | 5 +- .../testing/linker/project.csproj.template | 4 + .../eng/testing/linker/trimmingTests.targets | 6 +- src/runtime/eng/testing/tests.browser.targets | 183 ++++-- src/runtime/eng/testing/tests.mobile.targets | 4 +- src/runtime/eng/testing/tests.wasi.targets | 1 - src/runtime/eng/testing/tests.wasm.targets | 9 +- .../RuntimeHelpers.CoreCLR.cs | 45 +- .../src/coreclr/binder/bindertracing.cpp | 4 +- src/runtime/src/coreclr/debug/di/process.cpp | 1 - .../src/coreclr/debug/di/rsappdomain.cpp | 1 - .../src/coreclr/debug/di/rsassembly.cpp | 1 - src/runtime/src/coreclr/debug/di/rsmain.cpp | 1 - src/runtime/src/coreclr/debug/ee/debugger.cpp | 1 - .../coreclr/debug/ee/debuggermessagebox.cpp | 1 - src/runtime/src/coreclr/debug/ee/funceval.cpp | 1 - .../dlls/mscoree/coreclr/CMakeLists.txt | 2 +- .../src/coreclr/dlls/mscorrc/CMakeLists.txt | 15 +- .../src/coreclr/dlls/mscorrc/mscorrc.rc | 7 - src/runtime/src/coreclr/inc/sstring.h | 4 +- src/runtime/src/coreclr/inc/utilcode.h | 118 +--- .../src/coreclr/interpreter/compiler.cpp | 36 +- src/runtime/src/coreclr/jit/emit.h | 11 - src/runtime/src/coreclr/jit/emitpub.h | 1 - src/runtime/src/coreclr/jit/emitwasm.cpp | 24 +- src/runtime/src/coreclr/jit/gentree.cpp | 17 +- src/runtime/src/coreclr/jit/instrswasm.h | 2 - src/runtime/src/coreclr/jit/lower.cpp | 49 +- src/runtime/src/coreclr/jit/lower.h | 1 + .../src/coreclr/jit/registeropswasm.cpp | 12 - src/runtime/src/coreclr/jit/registeropswasm.h | 2 - src/runtime/src/coreclr/jit/scev.cpp | 2 +- src/runtime/src/coreclr/jit/targetwasm.cpp | 3 +- .../nativeaot/Bootstrap/CMakeLists.txt | 11 +- .../RuntimeHelpers.NativeAot.cs | 45 +- .../ILVerification.Tests}/ILMethodTester.cs | 0 .../ILTests/AccessTests.il | 0 .../ILTests/AccessTests.ilproj} | 3 - .../ILTests/AccessTestsExtern.il | 0 .../ILTests/AccessTestsExtern.ilproj | 9 + .../ILTests/AccessTestsFriend.il | 0 .../ILTests/AccessTestsFriend.ilproj | 9 + .../ILTests/ArrayTests.il | 0 .../ILTests/ArrayTests.ilproj | 9 + .../ILTests/BasicArithmeticTests.il | 0 .../ILTests/BasicArithmeticTests.ilproj | 9 + .../ILTests/BranchingTests.il | 0 .../ILTests/BranchingTests.ilproj | 9 + .../ILTests/CallTests.il | 0 .../ILTests/CallTests.ilproj | 9 + .../ILTests/CastingTests.il | 0 .../ILTests/CastingTests.ilproj | 9 + .../ILTests/ComparisonTests.il | 0 .../ILTests/ComparisonTests.ilproj | 9 + .../ILTests/DefaultInterfaceMethod.il | 0 .../ILTests/DefaultInterfaceMethod.ilproj | 9 + .../ILTests/DelegateTests.il | 0 .../ILTests/DelegateTests.ilproj | 9 + .../ILTests/Directory.Build.props | 7 + .../ILTests/ExceptionRegionTests.il | 0 .../ILTests/ExceptionRegionTests.ilproj | 9 + .../ILTests/FieldTests.il | 0 .../ILTests/FieldTests.ilproj | 9 + .../ILVerification.Tests}/ILTests/FtnTests.il | 0 .../ILTests/FtnTests.ilproj | 9 + .../ILTests/FunctionPointerTests.il | 0 .../ILTests/FunctionPointerTests.ilproj | 9 + .../ILTests/GenericInterface.il | 0 .../ILTests/GenericInterface.ilproj | 9 + .../ILTests/InterfaceDefinition.il | 0 .../ILTests/InterfaceDefinition.ilproj | 9 + .../ILTests/InterfaceImplementation.il | 0 .../ILTests/InterfaceImplementation.ilproj | 9 + .../ILTests/LoadStoreIndirectTests.il | 0 .../ILTests/LoadStoreIndirectTests.ilproj | 9 + .../ILTests/LocalAllocTests.il | 0 .../ILTests/LocalAllocTests.ilproj | 9 + .../ILTests/NewobjTests.il | 0 .../ILTests/NewobjTests.ilproj | 9 + .../ILTests/PrefixTests.il | 0 .../ILTests/PrefixTests.ilproj | 9 + .../ILTests/ReturnTests.il | 0 .../ILTests/ReturnTests.ilproj | 9 + .../ILTests/RuntimeAsyncTests.il | 0 .../ILTests/RuntimeAsyncTests.ilproj | 9 + .../ILTests/ShiftTests.il | 0 .../ILTests/ShiftTests.ilproj | 9 + .../ILTests/SwitchTests.il | 0 .../ILTests/ThisStateTests.il | 0 .../ILTests/ThisStateTests.ilproj | 9 + .../ILTests/ValueTypeTests.il | 0 .../ILTests/ValueTypeTests.ilproj | 9 + .../ILTypeVerificationTester.cs | 0 .../ILVerification.Tests.csproj | 25 + .../tools/ILVerification.Tests/JsonContext.cs | 15 + .../ILVerification.Tests}/TestDataLoader.cs | 22 +- .../src/coreclr/tools/ILVerify/README.md | 37 +- .../src/coreclr/tools/r2rtest/BuildFolder.cs | 14 +- src/runtime/src/coreclr/utilcode/ccomprc.cpp | 402 +------------ src/runtime/src/coreclr/utilcode/ex.cpp | 4 +- .../src/coreclr/utilcode/posterror.cpp | 47 +- .../src/coreclr/utilcode/sstring_com.cpp | 77 ++- src/runtime/src/coreclr/vm/assemblynative.cpp | 2 +- .../src/coreclr/vm/callstubgenerator.h | 1 - src/runtime/src/coreclr/vm/clrex.cpp | 2 +- src/runtime/src/coreclr/vm/comutilnative.cpp | 6 +- src/runtime/src/coreclr/vm/eepolicy.cpp | 2 +- src/runtime/src/coreclr/vm/eventreporter.cpp | 30 +- src/runtime/src/coreclr/vm/excep.cpp | 18 +- src/runtime/src/coreclr/vm/interoputil.cpp | 40 +- src/runtime/src/coreclr/vm/interpexec.cpp | 66 ++- src/runtime/src/coreclr/vm/mlinfo.cpp | 4 +- .../src/coreclr/vm/profilinghelper.cpp | 2 - .../src/coreclr/vm/qcallentrypoints.cpp | 1 + src/runtime/src/coreclr/vm/runtimehandles.cpp | 26 + src/runtime/src/coreclr/vm/runtimehandles.h | 1 + src/runtime/src/coreclr/vm/stackwalk.cpp | 24 + .../vm/wasm/callhelpers-interp-to-managed.cpp | 1 - .../coreclr/vm/wasm/callhelpers-reverse.cpp | 222 ++++++- .../src/coreclr/vm/wasm/callhelpers.hpp | 1 + src/runtime/src/coreclr/vm/wasm/helpers.cpp | 77 ++- .../src/installer/tests/Directory.Build.props | 2 +- .../Net/Prerequisites/LocalEchoServer.props | 9 +- .../System.Net.Http.Functional.Tests.csproj | 4 +- .../System.Net.WebSockets.Client.Tests.csproj | 4 +- .../Arm/Sve2.PlatformNotSupported.cs | 66 +-- .../src/System/Runtime/Intrinsics/Arm/Sve2.cs | 66 +-- .../src/System/TypeLoadException.cs | 2 +- ...me.InteropServices.JavaScript.Tests.csproj | 9 +- .../ComClassGenerator.cs | 4 +- .../ComClassGeneratorOutputShape.cs | 21 + .../ref/System.Runtime.Intrinsics.cs | 66 +-- .../tests/System.Runtime.Loader.Tests.csproj | 10 - .../System.Runtime/ref/System.Runtime.cs | 1 + .../System.IO.FileSystem.Tests.csproj | 2 +- .../CompilerServices/RuntimeHelpersTests.cs | 40 ++ .../src/libraries/sendtohelix-browser.targets | 3 + src/runtime/src/libraries/tests.proj | 20 +- .../CompilerServices/RuntimeHelpers.Mono.cs | 38 ++ .../mono/browser/build/BrowserWasmApp.props | 1 - .../mono/browser/build/BrowserWasmApp.targets | 128 +--- src/runtime/src/mono/browser/build/README.md | 1 - .../mono/browser/build/WasmApp.InTree.props | 16 + .../mono/browser/build/WasmApp.InTree.targets | 28 +- src/runtime/src/mono/browser/test-index.html | 2 + src/runtime/src/mono/mono/mini/aot-runtime.c | 5 +- .../src/mono/mono/utils/mono-utility-thread.c | 2 +- .../apple/build/AppleBuild.InTree.targets | 15 - .../apple/build/AppleBuild.ReadyToRun.targets | 17 + .../mono/msbuild/apple/build/AppleBuild.props | 18 + .../Sdk/Sdk.props | 1 - ...rosoft.NET.Sdk.WebAssembly.Browser.targets | 102 ++-- .../WorkloadManifest.targets.in | 2 - .../src/mono/sample/iOS/Program.csproj | 13 - .../mono/sample/mbr/browser/WasmDelta.csproj | 4 - .../mbr/browser/{ => wwwroot}/index.html | 0 .../sample/mbr/browser/{ => wwwroot}/main.js | 0 .../sample/wasm/DefaultBrowserSample.targets | 4 - .../mono/sample/wasm/Directory.Build.props | 13 +- .../mono/sample/wasm/Directory.Build.targets | 16 +- .../Wasm.Advanced.Sample.csproj | 4 - .../advanced-sample.lib.module.js | 0 .../browser-advanced/{ => wwwroot}/index.html | 0 .../browser-advanced/{ => wwwroot}/main.js | 7 +- .../Wasm.Browser.Bench.Sample.csproj | 13 +- .../{ => wwwroot}/appstart-frame.html | 7 +- .../browser-bench/{ => wwwroot}/frame-main.js | 2 +- .../browser-bench/{ => wwwroot}/index.html | 0 .../wasm/browser-bench/{ => wwwroot}/main.js | 2 +- .../browser-bench/{ => wwwroot}/style.css | 0 .../Wasm.Browser.EventPipe.Sample.csproj | 3 - .../{ => wwwroot}/index.html | 0 .../browser-eventpipe/{ => wwwroot}/main.js | 0 .../Wasm.BrowserLogProfile.Sample.csproj | 5 - .../{ => wwwroot}/index.html | 0 .../browser-logprofile/{ => wwwroot}/main.js | 0 .../wasm/browser-minimal-config/Program.cs | 18 - .../Wasm.Browser.Config.Sample.csproj | 9 - .../wasm/browser-minimal-config/index.html | 17 - .../wasm/browser-minimal-config/main.js | 86 --- .../Wasm.BrowserProfile.Sample.csproj | 6 - .../browser-profile/{ => wwwroot}/index.html | 0 .../browser-profile/{ => wwwroot}/main.js | 0 .../Wasm.Browser.Shutdown.Sample.csproj | 3 - .../browser-shutdown/{ => wwwroot}/index.html | 0 .../browser-shutdown/{ => wwwroot}/main.js | 0 .../Wasm.Browser.Threads.Sample.csproj | 4 - .../browser-threads/{ => wwwroot}/index.html | 0 .../browser-threads/{ => wwwroot}/main.js | 0 .../wasm/browser/Wasm.Browser.Sample.csproj | 3 - .../wasm/browser/{ => wwwroot}/index.html | 0 .../sample/wasm/browser/{ => wwwroot}/main.js | 0 .../Wasm.Console.Node.Sample.csproj | 4 - .../wasm/console-node/{ => wwwroot}/main.mjs | 0 .../console-node/{ => wwwroot}/package.json | 0 .../wasm/simple-raytracer/RayTracer.csproj | 5 - .../simple-raytracer/{ => wwwroot}/index.html | 0 .../simple-raytracer/{ => wwwroot}/main.js | 0 src/runtime/src/mono/sample/wasm/wasm.mk | 8 +- src/runtime/src/mono/wasm/build/README.md | 1 - .../src/mono/wasm/build/WasmApp.Common.props | 1 - .../mono/wasm/build/WasmApp.Common.targets | 7 +- .../aot-tests/ProxyProjectForAOTOnHelix.proj | 2 +- .../App/WasmBasicTestApp.csproj | 1 - .../AssetsComputingHelper.cs | 1 + .../ComputeWasmBuildAssets.cs | 9 + .../GenerateWasmBootJson.cs | 4 +- .../tasks/WasmAppBuilder/WasmAppBuilder.cs | 522 ----------------- .../WasmAppBuilder/WasmAppBuilder.csproj | 18 +- .../coreclr/PInvokeCollector.cs | 284 +++++++++ .../coreclr/PInvokeTableGenerator.cs | 547 ++++++++++++++++++ .../WasmAppBuilder/coreclr/SignatureMapper.cs | 15 +- .../{ => mono}/PInvokeCollector.cs | 0 .../{ => mono}/PInvokeTableGenerator.cs | 0 .../WasmBuildTasks/LinkContentToWwwroot.cs | 123 ++++ .../Common/CLRTest.Execute.Batch.targets | 1 - .../src/tests/Common/Directory.Build.targets | 1 - .../tests/Common/helixpublishwitharcade.proj | 24 +- .../wasm-test-runner/WasmTestRunner.proj | 3 - .../StartupHookForFunctionalTest.csproj | 1 + .../WebAssembly/Directory.Build.props | 5 +- .../iOS/Device/Directory.Build.props | 2 +- .../Program.cs | 0 .../iOS.CoreCLR.Interpreter.Test.csproj} | 6 +- .../CoreCLR/iOS.CoreCLR.R2R.Test.csproj | 19 + .../ConsumeNETServer/ConsumeNETServer.csproj | 1 + .../NETClients/ConsumeNETServer/Program.cs | 56 +- .../Interop/common/ComActivationHelpers.cs | 82 +++ .../JIT/Methodical/Methodical_others.csproj | 1 + .../Methodical/delegate/DelegateToDelegate.cs | 31 + .../JitBlue/Runtime_122138/Runtime_122138.cs | 28 + .../JIT/Regression/Regression_ro_1.csproj | 1 + src/runtime/src/tests/build.proj | 6 +- .../tests/ilverify/ILTests/AccessTests.ilproj | 3 - .../ilverify/ILTests/AccessTestsExtern.ilproj | 3 - .../ilverify/ILTests/AccessTestsFriend.ilproj | 3 - .../tests/ilverify/ILTests/ArrayTests.ilproj | 3 - .../ILTests/BasicArithmeticTests.ilproj | 3 - .../ilverify/ILTests/BranchingTests.ilproj | 3 - .../tests/ilverify/ILTests/CallTests.ilproj | 3 - .../ilverify/ILTests/CastingTests.ilproj | 3 - .../ilverify/ILTests/ComparisonTests.ilproj | 3 - .../ILTests/DefaultInterfaceMethod.ilproj | 3 - .../ilverify/ILTests/DelegateTests.ilproj | 3 - .../ILTests/ExceptionRegionTests.ilproj | 3 - .../tests/ilverify/ILTests/FieldTests.ilproj | 3 - .../tests/ilverify/ILTests/FtnTests.ilproj | 3 - .../ILTests/FunctionPointerTests.ilproj | 3 - .../ilverify/ILTests/GenericInterface.ilproj | 3 - .../ILTests/InterfaceDefinition.ilproj | 3 - .../ILTests/InterfaceImplementation.ilproj | 3 - .../ILTests/LoadStoreIndirectTests.ilproj | 3 - .../ilverify/ILTests/LocalAllocTests.ilproj | 3 - .../tests/ilverify/ILTests/NewobjTests.ilproj | 3 - .../tests/ilverify/ILTests/PrefixTests.ilproj | 3 - .../tests/ilverify/ILTests/ReturnTests.ilproj | 3 - .../ilverify/ILTests/RuntimeAsyncTests.ilproj | 3 - .../tests/ilverify/ILTests/ShiftTests.ilproj | 3 - .../ilverify/ILTests/ThisStateTests.ilproj | 3 - .../ilverify/ILTests/ValueTypeTests.ilproj | 3 - .../tests/ilverify/ILVerificationTests.csproj | 30 - src/source-manifest.json | 4 +- 267 files changed, 2767 insertions(+), 2176 deletions(-) rename src/runtime/src/{tests/ilverify => coreclr/tools/ILVerification.Tests}/ILMethodTester.cs (100%) rename src/runtime/src/{tests/ilverify => coreclr/tools/ILVerification.Tests}/ILTests/AccessTests.il (100%) rename src/runtime/src/{tests/ilverify/ILTests/ILTests.targets => coreclr/tools/ILVerification.Tests/ILTests/AccessTests.ilproj} (59%) rename src/runtime/src/{tests/ilverify => coreclr/tools/ILVerification.Tests}/ILTests/AccessTestsExtern.il (100%) create mode 100644 src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/AccessTestsExtern.ilproj rename src/runtime/src/{tests/ilverify => coreclr/tools/ILVerification.Tests}/ILTests/AccessTestsFriend.il (100%) create mode 100644 src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/AccessTestsFriend.ilproj rename src/runtime/src/{tests/ilverify => coreclr/tools/ILVerification.Tests}/ILTests/ArrayTests.il (100%) create mode 100644 src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ArrayTests.ilproj rename src/runtime/src/{tests/ilverify => coreclr/tools/ILVerification.Tests}/ILTests/BasicArithmeticTests.il (100%) create mode 100644 src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/BasicArithmeticTests.ilproj rename src/runtime/src/{tests/ilverify => coreclr/tools/ILVerification.Tests}/ILTests/BranchingTests.il (100%) create mode 100644 src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/BranchingTests.ilproj rename src/runtime/src/{tests/ilverify => coreclr/tools/ILVerification.Tests}/ILTests/CallTests.il (100%) create mode 100644 src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/CallTests.ilproj rename src/runtime/src/{tests/ilverify => coreclr/tools/ILVerification.Tests}/ILTests/CastingTests.il (100%) create mode 100644 src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/CastingTests.ilproj rename src/runtime/src/{tests/ilverify => coreclr/tools/ILVerification.Tests}/ILTests/ComparisonTests.il (100%) create mode 100644 src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ComparisonTests.ilproj rename src/runtime/src/{tests/ilverify => coreclr/tools/ILVerification.Tests}/ILTests/DefaultInterfaceMethod.il (100%) create mode 100644 src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/DefaultInterfaceMethod.ilproj rename src/runtime/src/{tests/ilverify => coreclr/tools/ILVerification.Tests}/ILTests/DelegateTests.il (100%) create mode 100644 src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/DelegateTests.ilproj create mode 100644 src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/Directory.Build.props rename src/runtime/src/{tests/ilverify => coreclr/tools/ILVerification.Tests}/ILTests/ExceptionRegionTests.il (100%) create mode 100644 src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ExceptionRegionTests.ilproj rename src/runtime/src/{tests/ilverify => coreclr/tools/ILVerification.Tests}/ILTests/FieldTests.il (100%) create mode 100644 src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/FieldTests.ilproj rename src/runtime/src/{tests/ilverify => coreclr/tools/ILVerification.Tests}/ILTests/FtnTests.il (100%) create mode 100644 src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/FtnTests.ilproj rename src/runtime/src/{tests/ilverify => coreclr/tools/ILVerification.Tests}/ILTests/FunctionPointerTests.il (100%) create mode 100644 src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/FunctionPointerTests.ilproj rename src/runtime/src/{tests/ilverify => coreclr/tools/ILVerification.Tests}/ILTests/GenericInterface.il (100%) create mode 100644 src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/GenericInterface.ilproj rename src/runtime/src/{tests/ilverify => coreclr/tools/ILVerification.Tests}/ILTests/InterfaceDefinition.il (100%) create mode 100644 src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/InterfaceDefinition.ilproj rename src/runtime/src/{tests/ilverify => coreclr/tools/ILVerification.Tests}/ILTests/InterfaceImplementation.il (100%) create mode 100644 src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/InterfaceImplementation.ilproj rename src/runtime/src/{tests/ilverify => coreclr/tools/ILVerification.Tests}/ILTests/LoadStoreIndirectTests.il (100%) create mode 100644 src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/LoadStoreIndirectTests.ilproj rename src/runtime/src/{tests/ilverify => coreclr/tools/ILVerification.Tests}/ILTests/LocalAllocTests.il (100%) create mode 100644 src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/LocalAllocTests.ilproj rename src/runtime/src/{tests/ilverify => coreclr/tools/ILVerification.Tests}/ILTests/NewobjTests.il (100%) create mode 100644 src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/NewobjTests.ilproj rename src/runtime/src/{tests/ilverify => coreclr/tools/ILVerification.Tests}/ILTests/PrefixTests.il (100%) create mode 100644 src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/PrefixTests.ilproj rename src/runtime/src/{tests/ilverify => coreclr/tools/ILVerification.Tests}/ILTests/ReturnTests.il (100%) create mode 100644 src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ReturnTests.ilproj rename src/runtime/src/{tests/ilverify => coreclr/tools/ILVerification.Tests}/ILTests/RuntimeAsyncTests.il (100%) create mode 100644 src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/RuntimeAsyncTests.ilproj rename src/runtime/src/{tests/ilverify => coreclr/tools/ILVerification.Tests}/ILTests/ShiftTests.il (100%) create mode 100644 src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ShiftTests.ilproj rename src/runtime/src/{tests/ilverify => coreclr/tools/ILVerification.Tests}/ILTests/SwitchTests.il (100%) rename src/runtime/src/{tests/ilverify => coreclr/tools/ILVerification.Tests}/ILTests/ThisStateTests.il (100%) create mode 100644 src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ThisStateTests.ilproj rename src/runtime/src/{tests/ilverify => coreclr/tools/ILVerification.Tests}/ILTests/ValueTypeTests.il (100%) create mode 100644 src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ValueTypeTests.ilproj rename src/runtime/src/{tests/ilverify => coreclr/tools/ILVerification.Tests}/ILTypeVerificationTester.cs (100%) create mode 100644 src/runtime/src/coreclr/tools/ILVerification.Tests/ILVerification.Tests.csproj create mode 100644 src/runtime/src/coreclr/tools/ILVerification.Tests/JsonContext.cs rename src/runtime/src/{tests/ilverify => coreclr/tools/ILVerification.Tests}/TestDataLoader.cs (95%) create mode 100644 src/runtime/src/mono/browser/test-index.html create mode 100644 src/runtime/src/mono/msbuild/apple/build/AppleBuild.ReadyToRun.targets rename src/runtime/src/mono/sample/mbr/browser/{ => wwwroot}/index.html (100%) rename src/runtime/src/mono/sample/mbr/browser/{ => wwwroot}/main.js (100%) rename src/runtime/src/mono/sample/wasm/browser-advanced/{ => wwwroot}/advanced-sample.lib.module.js (100%) rename src/runtime/src/mono/sample/wasm/browser-advanced/{ => wwwroot}/index.html (100%) rename src/runtime/src/mono/sample/wasm/browser-advanced/{ => wwwroot}/main.js (96%) rename src/runtime/src/mono/sample/wasm/browser-bench/{ => wwwroot}/appstart-frame.html (60%) rename src/runtime/src/mono/sample/wasm/browser-bench/{ => wwwroot}/frame-main.js (96%) rename src/runtime/src/mono/sample/wasm/browser-bench/{ => wwwroot}/index.html (100%) rename src/runtime/src/mono/sample/wasm/browser-bench/{ => wwwroot}/main.js (99%) rename src/runtime/src/mono/sample/wasm/browser-bench/{ => wwwroot}/style.css (100%) rename src/runtime/src/mono/sample/wasm/browser-eventpipe/{ => wwwroot}/index.html (100%) rename src/runtime/src/mono/sample/wasm/browser-eventpipe/{ => wwwroot}/main.js (100%) rename src/runtime/src/mono/sample/wasm/browser-logprofile/{ => wwwroot}/index.html (100%) rename src/runtime/src/mono/sample/wasm/browser-logprofile/{ => wwwroot}/main.js (100%) delete mode 100644 src/runtime/src/mono/sample/wasm/browser-minimal-config/Program.cs delete mode 100644 src/runtime/src/mono/sample/wasm/browser-minimal-config/Wasm.Browser.Config.Sample.csproj delete mode 100644 src/runtime/src/mono/sample/wasm/browser-minimal-config/index.html delete mode 100644 src/runtime/src/mono/sample/wasm/browser-minimal-config/main.js rename src/runtime/src/mono/sample/wasm/browser-profile/{ => wwwroot}/index.html (100%) rename src/runtime/src/mono/sample/wasm/browser-profile/{ => wwwroot}/main.js (100%) rename src/runtime/src/mono/sample/wasm/browser-shutdown/{ => wwwroot}/index.html (100%) rename src/runtime/src/mono/sample/wasm/browser-shutdown/{ => wwwroot}/main.js (100%) rename src/runtime/src/mono/sample/wasm/browser-threads/{ => wwwroot}/index.html (100%) rename src/runtime/src/mono/sample/wasm/browser-threads/{ => wwwroot}/main.js (100%) rename src/runtime/src/mono/sample/wasm/browser/{ => wwwroot}/index.html (100%) rename src/runtime/src/mono/sample/wasm/browser/{ => wwwroot}/main.js (100%) rename src/runtime/src/mono/sample/wasm/console-node/{ => wwwroot}/main.mjs (100%) rename src/runtime/src/mono/sample/wasm/console-node/{ => wwwroot}/package.json (100%) rename src/runtime/src/mono/sample/wasm/simple-raytracer/{ => wwwroot}/index.html (100%) rename src/runtime/src/mono/sample/wasm/simple-raytracer/{ => wwwroot}/main.js (100%) delete mode 100644 src/runtime/src/tasks/WasmAppBuilder/WasmAppBuilder.cs create mode 100644 src/runtime/src/tasks/WasmAppBuilder/coreclr/PInvokeCollector.cs create mode 100644 src/runtime/src/tasks/WasmAppBuilder/coreclr/PInvokeTableGenerator.cs rename src/runtime/src/tasks/WasmAppBuilder/{ => mono}/PInvokeCollector.cs (100%) rename src/runtime/src/tasks/WasmAppBuilder/{ => mono}/PInvokeTableGenerator.cs (100%) create mode 100644 src/runtime/src/tasks/WasmBuildTasks/LinkContentToWwwroot.cs rename src/runtime/src/tests/FunctionalTests/iOS/Simulator/{CoreCLR.Interpreter => CoreCLR}/Program.cs (100%) rename src/runtime/src/tests/FunctionalTests/iOS/Simulator/{CoreCLR.Interpreter/iOS.Simulator.CoreCLR.Interpreter.Test.csproj => CoreCLR/iOS.CoreCLR.Interpreter.Test.csproj} (76%) create mode 100644 src/runtime/src/tests/FunctionalTests/iOS/Simulator/CoreCLR/iOS.CoreCLR.R2R.Test.csproj create mode 100644 src/runtime/src/tests/Interop/common/ComActivationHelpers.cs create mode 100644 src/runtime/src/tests/JIT/Methodical/delegate/DelegateToDelegate.cs create mode 100644 src/runtime/src/tests/JIT/Regression/JitBlue/Runtime_122138/Runtime_122138.cs delete mode 100644 src/runtime/src/tests/ilverify/ILTests/AccessTests.ilproj delete mode 100644 src/runtime/src/tests/ilverify/ILTests/AccessTestsExtern.ilproj delete mode 100644 src/runtime/src/tests/ilverify/ILTests/AccessTestsFriend.ilproj delete mode 100644 src/runtime/src/tests/ilverify/ILTests/ArrayTests.ilproj delete mode 100644 src/runtime/src/tests/ilverify/ILTests/BasicArithmeticTests.ilproj delete mode 100644 src/runtime/src/tests/ilverify/ILTests/BranchingTests.ilproj delete mode 100644 src/runtime/src/tests/ilverify/ILTests/CallTests.ilproj delete mode 100644 src/runtime/src/tests/ilverify/ILTests/CastingTests.ilproj delete mode 100644 src/runtime/src/tests/ilverify/ILTests/ComparisonTests.ilproj delete mode 100644 src/runtime/src/tests/ilverify/ILTests/DefaultInterfaceMethod.ilproj delete mode 100644 src/runtime/src/tests/ilverify/ILTests/DelegateTests.ilproj delete mode 100644 src/runtime/src/tests/ilverify/ILTests/ExceptionRegionTests.ilproj delete mode 100644 src/runtime/src/tests/ilverify/ILTests/FieldTests.ilproj delete mode 100644 src/runtime/src/tests/ilverify/ILTests/FtnTests.ilproj delete mode 100644 src/runtime/src/tests/ilverify/ILTests/FunctionPointerTests.ilproj delete mode 100644 src/runtime/src/tests/ilverify/ILTests/GenericInterface.ilproj delete mode 100644 src/runtime/src/tests/ilverify/ILTests/InterfaceDefinition.ilproj delete mode 100644 src/runtime/src/tests/ilverify/ILTests/InterfaceImplementation.ilproj delete mode 100644 src/runtime/src/tests/ilverify/ILTests/LoadStoreIndirectTests.ilproj delete mode 100644 src/runtime/src/tests/ilverify/ILTests/LocalAllocTests.ilproj delete mode 100644 src/runtime/src/tests/ilverify/ILTests/NewobjTests.ilproj delete mode 100644 src/runtime/src/tests/ilverify/ILTests/PrefixTests.ilproj delete mode 100644 src/runtime/src/tests/ilverify/ILTests/ReturnTests.ilproj delete mode 100644 src/runtime/src/tests/ilverify/ILTests/RuntimeAsyncTests.ilproj delete mode 100644 src/runtime/src/tests/ilverify/ILTests/ShiftTests.ilproj delete mode 100644 src/runtime/src/tests/ilverify/ILTests/ThisStateTests.ilproj delete mode 100644 src/runtime/src/tests/ilverify/ILTests/ValueTypeTests.ilproj delete mode 100644 src/runtime/src/tests/ilverify/ILVerificationTests.csproj diff --git a/src/runtime/eng/Subsets.props b/src/runtime/eng/Subsets.props index 64079deecc48..5243a41b59f6 100644 --- a/src/runtime/eng/Subsets.props +++ b/src/runtime/eng/Subsets.props @@ -502,6 +502,8 @@ Test="true" Category="clr" Condition="'$(DotNetBuildSourceOnly)' != 'true' and '$(NativeAotSupported)' == 'true'"/> + @@ -510,7 +512,7 @@ - + - + https://github.com/dotnet/icu - 405615f119c1554d366b441870e29747e66c4dea + f30459348023443026d006825c234914fd57589a https://github.com/dotnet/wcf diff --git a/src/runtime/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml b/src/runtime/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml index e726bd873256..0c66abfa042d 100644 --- a/src/runtime/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml +++ b/src/runtime/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml @@ -26,9 +26,11 @@ jobs: platforms: - browser_wasm - browser_wasm_win - nameSuffix: _AOT + nameSuffix: _Smoke_AOT extraBuildArgs: /p:AotHostArchitecture=x64 /p:AotHostOS=$(_hostedOS) runAOT: true + buildAOTOnHelix: false + shouldRunSmokeOnly: true alwaysRun: true # AOT Library tests - wasi_wasm @@ -99,6 +101,7 @@ jobs: nameSuffix: _EAT extraBuildArgs: /p:AotHostArchitecture=x64 /p:AotHostOS=$(_hostedOS) /maxcpucount:1 runAOT: false + buildAOTOnHelix: false isExtraPlatformsBuild: ${{ parameters.isExtraPlatformsBuild }} isWasmOnlyBuild: ${{ parameters.isWasmOnlyBuild }} @@ -108,9 +111,11 @@ jobs: platforms: - browser_wasm - browser_wasm_win - nameSuffix: _AOT + nameSuffix: _Smoke_AOT extraBuildArgs: /p:AotHostArchitecture=x64 /p:AotHostOS=$(_hostedOS) runAOT: true + buildAOTOnHelix: false + shouldRunSmokeOnly: true isExtraPlatformsBuild: ${{ parameters.isExtraPlatformsBuild }} isWasmOnlyBuild: ${{ parameters.isWasmOnlyBuild }} alwaysRun: ${{ parameters.isWasmOnlyBuild }} diff --git a/src/runtime/eng/pipelines/runtime.yml b/src/runtime/eng/pipelines/runtime.yml index 54886c99b81f..199bf1899641 100644 --- a/src/runtime/eng/pipelines/runtime.yml +++ b/src/runtime/eng/pipelines/runtime.yml @@ -854,6 +854,7 @@ extends: platforms: - browser_wasm nameSuffix: _EAT + buildAOTOnHelix: false runAOT: false shouldRunSmokeOnly: false alwaysRun: ${{ variables.isRollingBuild }} @@ -867,6 +868,7 @@ extends: - browser_wasm_win nameSuffix: _Smoke_AOT runAOT: true + buildAOTOnHelix: false shouldRunSmokeOnly: true alwaysRun: ${{ variables.isRollingBuild }} extraBuildArgs: /p:AotHostArchitecture=x64 /p:AotHostOS=$(_hostedOS) diff --git a/src/runtime/eng/testing/linker/SupportFiles/Directory.Build.targets b/src/runtime/eng/testing/linker/SupportFiles/Directory.Build.targets index 1ba8ed737f4d..9687763d2fde 100644 --- a/src/runtime/eng/testing/linker/SupportFiles/Directory.Build.targets +++ b/src/runtime/eng/testing/linker/SupportFiles/Directory.Build.targets @@ -3,13 +3,14 @@ - $([MSBuild]::NormalizeDirectory('$(MSBuildProjectDirectory)', '$(OutputPath)', 'AppBundle')) + $([MSBuild]::NormalizeDirectory('$(MSBuildProjectDirectory)', '$(OutputPath)', 'publish', 'wwwroot')) project.dll + true diff --git a/src/runtime/eng/testing/linker/project.csproj.template b/src/runtime/eng/testing/linker/project.csproj.template index 7498d355dfce..bee554760c7e 100644 --- a/src/runtime/eng/testing/linker/project.csproj.template +++ b/src/runtime/eng/testing/linker/project.csproj.template @@ -41,6 +41,10 @@ {WasmAppBuilderTasksAssemblyPath} {MonoTargetsTasksAssemblyPath} {MicrosoftNetCoreAppRuntimePackRidDir} + <_WebAssemblyPropsFile>{WasmSdkPackBuildPath}Microsoft.NET.Sdk.WebAssembly.Browser.props + <_WebAssemblyTargetsFile>{WasmSdkPackBuildPath}Microsoft.NET.Sdk.WebAssembly.Browser.targets + <_WebAssemblySdkToolsDirectory>{WasmSdkPackTasksPath} + true {ProductVersion} diff --git a/src/runtime/eng/testing/linker/trimmingTests.targets b/src/runtime/eng/testing/linker/trimmingTests.targets index 8454ef52940f..0418d28da14d 100644 --- a/src/runtime/eng/testing/linker/trimmingTests.targets +++ b/src/runtime/eng/testing/linker/trimmingTests.targets @@ -30,9 +30,9 @@ %(ProjectDir)project.csproj $([MSBuild]::NormalizePath('%(ProjectDir)', 'bin', '$(Configuration)', '%(TargetFramework)', '%(TestRuntimeIdentifier)', 'publish', 'project')) - $([MSBuild]::NormalizePath('%(ProjectDir)', 'bin', '$(Configuration)', '%(TargetFramework)', '%(TestRuntimeIdentifier)', 'AppBundle', 'run-v8.sh')) + $([MSBuild]::NormalizePath('%(ProjectDir)', 'bin', '$(Configuration)', '%(TargetFramework)', '%(TestRuntimeIdentifier)', 'publish', 'wwwroot', 'run-v8.sh')) $([MSBuild]::NormalizeDirectory('%(ProjectDir)', 'bin', '$(Configuration)', '%(TargetFramework)', '%(TestRuntimeIdentifier)', 'publish')) - $([MSBuild]::NormalizeDirectory('%(ProjectDir)', 'bin', '$(Configuration)', '%(TargetFramework)', '%(TestRuntimeIdentifier)', 'AppBundle')) + $([MSBuild]::NormalizeDirectory('%(ProjectDir)', 'bin', '$(Configuration)', '%(TargetFramework)', '%(TestRuntimeIdentifier)', 'publish', 'wwwroot')) @@ -114,6 +114,8 @@ .Replace('{MonoTargetsTasksAssemblyPath}', '$(MonoTargetsTasksAssemblyPath)') .Replace('{WasmAppBuilderTasksAssemblyPath}', '$(WasmAppBuilderTasksAssemblyPath)') .Replace('{MicrosoftNetCoreAppRuntimePackRidDir}', '$(MicrosoftNetCoreAppRuntimePackRidDir)') + .Replace('{WasmSdkPackBuildPath}', '$(MonoProjectRoot)nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/') + .Replace('{WasmSdkPackTasksPath}', '$(ArtifactsBinDir)Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/$(RuntimeConfiguration)/') .Replace('{ProductVersion}', '$(ProductVersion)') .Replace('{NetCoreAppCurrent}', '$(NetCoreAppCurrent)') .Replace('{NetCoreAppToolCurrent}', '$(NetCoreAppToolCurrent)') diff --git a/src/runtime/eng/testing/tests.browser.targets b/src/runtime/eng/testing/tests.browser.targets index 2d8abf40465c..5e88f3b4922c 100644 --- a/src/runtime/eng/testing/tests.browser.targets +++ b/src/runtime/eng/testing/tests.browser.targets @@ -7,6 +7,19 @@ true + false + false + true + false + true + <_WasmInTreeDefaults>false + + + $(ResolveWasmOutputsDependsOn); + WasmTriggerPublishApp; + ReadWasmNativeAssetsFromFileSystem; + UpdateWasmNativeAssetOriginalItemSpec + $([MSBuild]::NormalizeDirectory($(BrowserProjectRoot), 'emsdk')) @@ -36,6 +49,11 @@ true + + + + + @@ -44,6 +62,11 @@ true + + false + true + + $(_AOTBuildCommand) $(_ShellCommandSeparator) $(RunScriptCommand) - - + + Condition="'$(BuildAOTTestsOn)' == 'local' and '$(IsWasmProject)' != 'false'" /> @@ -145,55 +167,142 @@ PrepareForWasmBuildApp;$(WasmNestedPublishAppDependsOn) - + - + + + %(Identity) + - - - $(BundleDir) - WasmTestRunner.dll - $(MonoProjectRoot)\browser\test-main.js - $([System.IO.Path]::GetFileName('$(WasmMainJSPath)')) - $(PublishDir)index.html - $(InvariantGlobalization) - true - + + + + + + + + + + + + + + + + + + + + <_WasmFilesForVfs Include="$(PublishDir)%(WasmFilesToIncludeFromPublishDir.Identity)" + TargetPath="%(WasmFilesToIncludeFromPublishDir.TargetDir)/%(WasmFilesToIncludeFromPublishDir.Identity)" + CopyToOutputDirectory="PreserveNewest" + Condition="'%(WasmFilesToIncludeFromPublishDir.Identity)' != '' and '%(WasmFilesToIncludeFromPublishDir.TargetDir)' != ''" /> + <_WasmFilesForVfs Include="$(PublishDir)%(WasmFilesToIncludeFromPublishDir.Identity)" + TargetPath="%(WasmFilesToIncludeFromPublishDir.Identity)" + CopyToOutputDirectory="PreserveNewest" + Condition="'%(WasmFilesToIncludeFromPublishDir.Identity)' != '' and '%(WasmFilesToIncludeFromPublishDir.TargetDir)' == ''" /> + + <_WasmFilesForVfs Include="@(AllItemsFullPathWithTargetPath)" Condition="$([System.String]::new('%(AllItemsFullPathWithTargetPath.Identity)').EndsWith('.dmeta'))" /> + <_WasmFilesForVfs Include="@(AllItemsFullPathWithTargetPath)" Condition="$([System.String]::new('%(AllItemsFullPathWithTargetPath.Identity)').EndsWith('.dil'))" /> + <_WasmFilesForVfs Include="@(AllItemsFullPathWithTargetPath)" Condition="$([System.String]::new('%(AllItemsFullPathWithTargetPath.Identity)').EndsWith('.dpdb'))" /> + <_WasmFilesForVfs Include="@(_WasmBuildAssetCandidates)" Condition="'%(_WasmBuildAssetCandidates.BuildReference)' == 'true' and $([System.String]::new('%(_WasmBuildAssetCandidates.Identity)').EndsWith('.dll')) and !$([System.String]::new('%(_WasmBuildAssetCandidates.Identity)').EndsWith('.resources.dll'))" /> + <_SatelliteAssemblies Include="$(PublishDir)*\*.resources.dll" /> <_SatelliteAssemblies CultureName="$([System.IO.Directory]::GetParent('%(Identity)').Name)" /> <_SatelliteAssemblies TargetPath="%(CultureName)\%(FileName)%(Extension)" /> - + <_WasmFilesForVfs Include="@(_SatelliteAssemblies)" /> + + <_WasmFilesForVfs CopyToOutputDirectory="PreserveNewest" /> + + + + + + + + + + + + + + + + + + + + + <_HasDotnetWasm Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.native.wasm'">true + <_HasDotnetJsWorker Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.native.worker.mjs'">true + <_HasDotnetJsSymbols Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.native.js.symbols'">true + <_HasDotnetNativeJs Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.native.js'">true + <_WasmIcuDataFileName Condition="'$(WasmIcuDataFileName)' != '' and Exists('$(WasmIcuDataFileName)')">$(WasmIcuDataFileName) + <_WasmIcuDataFileName Condition="'$(WasmIcuDataFileName)' != '' and !Exists('$(WasmIcuDataFileName)')">$(MicrosoftNetCoreAppRuntimePackRidNativeDir)$(WasmIcuDataFileName) + - - + + + + + + + + + + + + + - - - - <_CopyLocalPaths - Include="@(PublishItemsOutputGroupOutputs)" - Condition="'%(PublishItemsOutputGroupOutputs.BuildReference)' == 'true' and - !$([System.String]::new('%(PublishItemsOutputGroupOutputs.Identity)').EndsWith('.resources.dll'))" /> - - <_CopyLocalPaths TargetPath="%(_CopyLocalPaths.RelativePath)" Condition="'%(_CopyLocalPaths.RelativePath)' != ''" /> - <_CopyLocalPaths TargetPath="%(FileName)%(Extension)" Condition="'%(_CopyLocalPaths.RelativePath)' == ''" /> - - - - + + <_IcuAvailableDataFiles Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)icudt_*" Exclude="$(_WasmIcuDataFileName)"/> + + + + + - + + + $(BundleDir) + WasmTestRunner.dll + $(MonoProjectRoot)\browser\test-main.js + $([System.IO.Path]::GetFileName('$(WasmMainJSPath)')) + true + + + + + + diff --git a/src/runtime/eng/testing/tests.mobile.targets b/src/runtime/eng/testing/tests.mobile.targets index 1c0ed5772ab6..bdae65323dba 100644 --- a/src/runtime/eng/testing/tests.mobile.targets +++ b/src/runtime/eng/testing/tests.mobile.targets @@ -1,7 +1,8 @@ - $([MSBuild]::NormalizeDirectory('$(OutDir)', 'AppBundle')) + $([MSBuild]::NormalizeDirectory('$(OutDir)', 'AppBundle')) + $([MSBuild]::NormalizeDirectory('$(OutDir)', 'wwwroot')) $(AppBundleRoot)tests\$(AssemblyName) $(AppBundleRoot)runonly\$(AssemblyName) $([MSBuild]::NormalizeDirectory('$(PublishDir)', 'AppBundle')) @@ -136,6 +137,7 @@ <_runnerFilesToPublishToFileName Remove="@(_resolvedFilesToPublishToFileName)" /> + diff --git a/src/runtime/eng/testing/tests.wasi.targets b/src/runtime/eng/testing/tests.wasi.targets index 83a1da8252bd..5c53d1db11d1 100644 --- a/src/runtime/eng/testing/tests.wasi.targets +++ b/src/runtime/eng/testing/tests.wasi.targets @@ -95,7 +95,6 @@ $(BundleDir) - $(InvariantGlobalization) diff --git a/src/runtime/eng/testing/tests.wasm.targets b/src/runtime/eng/testing/tests.wasm.targets index f0d99fa6d287..5cded7ee6740 100644 --- a/src/runtime/eng/testing/tests.wasm.targets +++ b/src/runtime/eng/testing/tests.wasm.targets @@ -2,7 +2,6 @@ true - true false $(BundleTestAppTargets);BundleTestWasmApp true @@ -90,12 +89,12 @@ - - - + + + - + diff --git a/src/runtime/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs b/src/runtime/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs index 9fa1f1f004d9..7cf1e9cc28a7 100644 --- a/src/runtime/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs +++ b/src/runtime/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs @@ -4,6 +4,7 @@ using System.Buffers.Binary; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Numerics; using System.Reflection; using System.Runtime.InteropServices; using System.Runtime.Serialization; @@ -467,26 +468,56 @@ internal static unsafe bool ObjectHasComponentSize(object obj) [return: MarshalAs(UnmanagedType.Bool)] internal static unsafe partial bool AreTypesEquivalent(MethodTable* pMTa, MethodTable* pMTb); - /// - /// Allocate memory that is associated with the and - /// will be freed if and when the is unloaded. - /// - /// Type associated with the allocated memory. - /// Amount of memory in bytes to allocate. - /// The allocated memory + /// Allocates memory that's associated with the and is freed if and when the is unloaded. + /// The type associated with the allocated memory. + /// The amount of memory to allocate, in bytes. + /// The allocated memory. + /// must be a type provided by the runtime. + /// is negative. public static IntPtr AllocateTypeAssociatedMemory(Type type, int size) { if (type is not RuntimeType rt) + { throw new ArgumentException(SR.Arg_MustBeType, nameof(type)); + } ArgumentOutOfRangeException.ThrowIfNegative(size); return AllocateTypeAssociatedMemory(new QCallTypeHandle(ref rt), (uint)size); } + /// Allocates aligned memory that's associated with the and is freed if and when the is unloaded. + /// The type associated with the allocated memory. + /// The amount of memory to allocate, in bytes. + /// The alignment, in bytes, of the memory to allocate. This must be a power of 2. + /// The allocated aligned memory. + /// must be a type provided by the runtime. + /// is negative. + /// is not a power of 2. + public static IntPtr AllocateTypeAssociatedMemory(Type type, int size, int alignment) + { + if (type is not RuntimeType rt) + { + throw new ArgumentException(SR.Arg_MustBeType, nameof(type)); + } + + ArgumentOutOfRangeException.ThrowIfNegative(size); + + if (!BitOperations.IsPow2(alignment)) + { + // The C standard doesn't define what a valid alignment is, however Windows and POSIX implementation requires a power of 2 + ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AlignmentMustBePow2); + } + + return AllocateTypeAssociatedMemoryAligned(new QCallTypeHandle(ref rt), (uint)size, (uint)alignment); + } + [LibraryImport(QCall, EntryPoint = "RuntimeTypeHandle_AllocateTypeAssociatedMemory")] private static partial IntPtr AllocateTypeAssociatedMemory(QCallTypeHandle type, uint size); + [LibraryImport(QCall, EntryPoint = "RuntimeTypeHandle_AllocateTypeAssociatedMemoryAligned")] + private static partial IntPtr AllocateTypeAssociatedMemoryAligned(QCallTypeHandle type, uint size, uint alignment); + [MethodImpl(MethodImplOptions.InternalCall)] private static extern unsafe TailCallArgBuffer* GetTailCallArgBuffer(); diff --git a/src/runtime/src/coreclr/binder/bindertracing.cpp b/src/runtime/src/coreclr/binder/bindertracing.cpp index 5a0f1a9470a3..b52f75878a09 100644 --- a/src/runtime/src/coreclr/binder/bindertracing.cpp +++ b/src/runtime/src/coreclr/binder/bindertracing.cpp @@ -219,9 +219,9 @@ namespace BinderTracing if (mvidMismatch) { StackSString format; - format.LoadResource(CCompRC::Error, IDS_EE_FILELOAD_ERROR_GENERIC); + format.LoadResource(IDS_EE_FILELOAD_ERROR_GENERIC); StackSString details; - details.LoadResource(CCompRC::Error, IDS_HOST_ASSEMBLY_RESOLVER_ASSEMBLY_ALREADY_LOADED_IN_CONTEXT); + details.LoadResource(IDS_HOST_ASSEMBLY_RESOLVER_ASSEMBLY_ALREADY_LOADED_IN_CONTEXT); errorMsg.FormatMessage(FORMAT_MESSAGE_FROM_STRING, format.GetUnicode(), 0, 0, m_assemblyName, details); } diff --git a/src/runtime/src/coreclr/debug/di/process.cpp b/src/runtime/src/coreclr/debug/di/process.cpp index 0d5de9081d6e..79129e6cefe1 100644 --- a/src/runtime/src/coreclr/debug/di/process.cpp +++ b/src/runtime/src/coreclr/debug/di/process.cpp @@ -18,7 +18,6 @@ #include "corpriv.h" #include "corexcep.h" -#include "../../dlls/mscorrc/resource.h" #include #include diff --git a/src/runtime/src/coreclr/debug/di/rsappdomain.cpp b/src/runtime/src/coreclr/debug/di/rsappdomain.cpp index a4a59d09ffbd..221c0791f532 100644 --- a/src/runtime/src/coreclr/debug/di/rsappdomain.cpp +++ b/src/runtime/src/coreclr/debug/di/rsappdomain.cpp @@ -17,7 +17,6 @@ #endif #include "corpriv.h" -#include "../../dlls/mscorrc/resource.h" #include diff --git a/src/runtime/src/coreclr/debug/di/rsassembly.cpp b/src/runtime/src/coreclr/debug/di/rsassembly.cpp index 05f22a0006e5..991d44c06cb7 100644 --- a/src/runtime/src/coreclr/debug/di/rsassembly.cpp +++ b/src/runtime/src/coreclr/debug/di/rsassembly.cpp @@ -17,7 +17,6 @@ #endif #include "corpriv.h" -#include "../../dlls/mscorrc/resource.h" #include diff --git a/src/runtime/src/coreclr/debug/di/rsmain.cpp b/src/runtime/src/coreclr/debug/di/rsmain.cpp index 9a2de7bf4200..35aa3a1b518b 100644 --- a/src/runtime/src/coreclr/debug/di/rsmain.cpp +++ b/src/runtime/src/coreclr/debug/di/rsmain.cpp @@ -19,7 +19,6 @@ #endif #include "corpriv.h" -#include "../../dlls/mscorrc/resource.h" #include diff --git a/src/runtime/src/coreclr/debug/ee/debugger.cpp b/src/runtime/src/coreclr/debug/ee/debugger.cpp index eb5bc42d206f..ad0d9a3129a6 100644 --- a/src/runtime/src/coreclr/debug/ee/debugger.cpp +++ b/src/runtime/src/coreclr/debug/ee/debugger.cpp @@ -13,7 +13,6 @@ #include "debugdebugger.h" #include "../inc/common.h" #include "eeconfig.h" // This is here even for retail & free builds... -#include "../../dlls/mscorrc/resource.h" #include "vars.hpp" #include diff --git a/src/runtime/src/coreclr/debug/ee/debuggermessagebox.cpp b/src/runtime/src/coreclr/debug/ee/debuggermessagebox.cpp index af86529d3c54..19c6da84fa2a 100644 --- a/src/runtime/src/coreclr/debug/ee/debuggermessagebox.cpp +++ b/src/runtime/src/coreclr/debug/ee/debuggermessagebox.cpp @@ -9,7 +9,6 @@ #include // Utility helpers. #include #include -#include "../../dlls/mscorrc/resource.h" // Output printf-style formatted text to the debugger if it's present or stdout otherwise. static void DbgPrintf(const LPCSTR szFormat, ...) diff --git a/src/runtime/src/coreclr/debug/ee/funceval.cpp b/src/runtime/src/coreclr/debug/ee/funceval.cpp index 7b1dd71070c4..652ec434f1f0 100644 --- a/src/runtime/src/coreclr/debug/ee/funceval.cpp +++ b/src/runtime/src/coreclr/debug/ee/funceval.cpp @@ -16,7 +16,6 @@ #include "debugdebugger.h" #include "../inc/common.h" #include "eeconfig.h" // This is here even for retail & free builds... -#include "../../dlls/mscorrc/resource.h" #include "vars.hpp" #include "threads.h" diff --git a/src/runtime/src/coreclr/dlls/mscoree/coreclr/CMakeLists.txt b/src/runtime/src/coreclr/dlls/mscoree/coreclr/CMakeLists.txt index 8d9d152ce7f9..f6a5b7ec9285 100644 --- a/src/runtime/src/coreclr/dlls/mscoree/coreclr/CMakeLists.txt +++ b/src/runtime/src/coreclr/dlls/mscoree/coreclr/CMakeLists.txt @@ -82,6 +82,7 @@ endif (CLR_CMAKE_HOST_UNIX AND NOT CLR_CMAKE_TARGET_ARCH_WASM) # order dependent and changing the order can result in undefined symbols in the shared # library. set(CORECLR_LIBRARIES + mscorrc utilcode ${START_LIBRARY_GROUP} # Start group of libraries that have circular references ${LIB_CORDBEE} @@ -137,7 +138,6 @@ if(CLR_CMAKE_TARGET_WIN32) else() list(APPEND CORECLR_LIBRARIES coreclrpal - mscorrc ) endif(CLR_CMAKE_TARGET_WIN32) diff --git a/src/runtime/src/coreclr/dlls/mscorrc/CMakeLists.txt b/src/runtime/src/coreclr/dlls/mscorrc/CMakeLists.txt index 16894714a4a6..9d704e9abf27 100644 --- a/src/runtime/src/coreclr/dlls/mscorrc/CMakeLists.txt +++ b/src/runtime/src/coreclr/dlls/mscorrc/CMakeLists.txt @@ -1,22 +1,9 @@ include_directories("../../pal/prebuilt/corerror") -add_definitions(-DFX_VER_INTERNALNAME_STR=mscorrc.dll) - if(CLR_CMAKE_HOST_WIN32) - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /NOENTRY") - - # remove /guard:cf, /guard:ehcont, and /CETCOMPAT from resource-only libraries - set_property(DIRECTORY PROPERTY CLR_CONTROL_FLOW_GUARD OFF) - - if (CLR_CMAKE_HOST_ARCH_AMD64) - set_property(DIRECTORY PROPERTY CLR_EH_CONTINUATION OFF) - string(REPLACE "/CETCOMPAT" "" CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS}) - endif (CLR_CMAKE_HOST_ARCH_AMD64) - - add_library_clr(mscorrc SHARED + add_library_clr(mscorrc OBJECT include.rc ) - install_clr(TARGETS mscorrc DESTINATIONS . sharedFramework COMPONENT runtime) else() build_resources(${CMAKE_CURRENT_SOURCE_DIR}/include.rc mscorrc TARGET_CPP_FILE) diff --git a/src/runtime/src/coreclr/dlls/mscorrc/mscorrc.rc b/src/runtime/src/coreclr/dlls/mscorrc/mscorrc.rc index abd530f5836d..f11fe9431c8d 100644 --- a/src/runtime/src/coreclr/dlls/mscorrc/mscorrc.rc +++ b/src/runtime/src/coreclr/dlls/mscorrc/mscorrc.rc @@ -12,13 +12,6 @@ #include -#ifndef FX_VER_FILEDESCRIPTION_STR -#define FX_VER_FILEDESCRIPTION_STR ".NET Runtime resources" -#endif - -#include -#include - ///////////////////////////////////////////////////////////////////////////// // English (U.S.) resources diff --git a/src/runtime/src/coreclr/inc/sstring.h b/src/runtime/src/coreclr/inc/sstring.h index 9ca98ada6362..82463acc6546 100644 --- a/src/runtime/src/coreclr/inc/sstring.h +++ b/src/runtime/src/coreclr/inc/sstring.h @@ -572,8 +572,8 @@ class EMPTY_BASES_DECL SString : private SBuffer void AppendVPrintf(const CHAR *format, va_list args); public: - BOOL LoadResource(CCompRC::ResourceCategory eCategory, int resourceID); - HRESULT LoadResourceAndReturnHR(CCompRC::ResourceCategory eCategory, int resourceID); + BOOL LoadResource(int resourceID); + HRESULT LoadResourceAndReturnHR(int resourceID); BOOL FormatMessage(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, const SString &arg1 = Empty(), const SString &arg2 = Empty(), const SString &arg3 = Empty(), const SString &arg4 = Empty(), diff --git a/src/runtime/src/coreclr/inc/utilcode.h b/src/runtime/src/coreclr/inc/utilcode.h index b6bffb5f4fb8..280c26569c19 100644 --- a/src/runtime/src/coreclr/inc/utilcode.h +++ b/src/runtime/src/coreclr/inc/utilcode.h @@ -348,9 +348,6 @@ HMODULE CLRLoadLibraryEx(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); BOOL CLRFreeLibrary(HMODULE hModule); -// Load a string using the resources for the current module. -STDAPI UtilLoadStringRC(UINT iResourceID, _Out_writes_ (iMax) LPWSTR szBuffer, int iMax, int bQuiet=FALSE); - //***************************************************************************** // Use this class by privately deriving from noncopyable to disallow copying of // your class. @@ -369,126 +366,15 @@ class noncopyable }; //***************************************************************************** -// Must associate each handle to an instance of a resource dll with the int -// that it represents -//***************************************************************************** -typedef HINSTANCE HRESOURCEDLL; - - -class CCulturedHInstance -{ - HRESOURCEDLL m_hInst; - BOOL m_fMissing; - -public: - CCulturedHInstance() - { - LIMITED_METHOD_CONTRACT; - m_hInst = NULL; - m_fMissing = FALSE; - } - - HRESOURCEDLL GetLibraryHandle() - { - return m_hInst; - } - - BOOL IsSet() - { - return m_hInst != NULL; - } - - BOOL IsMissing() - { - return m_fMissing; - } - - void SetMissing() - { - _ASSERTE(m_hInst == NULL); - m_fMissing = TRUE; - } - - void Set(HRESOURCEDLL hInst) - { - _ASSERTE(m_hInst == NULL); - _ASSERTE(m_fMissing == FALSE); - m_hInst = hInst; - } - }; - -//***************************************************************************** -// CCompRC manages string Resource access for CLR. This includes loading -// the MsCorRC.dll for resources. No localization is supported. +// CCompRC manages string Resource access for CLR. //***************************************************************************** class CCompRC { public: - enum ResourceCategory - { - // must be present - Required, - - // present in Desktop CLR and Core CLR + debug pack, an error - // If missing, get a generic error message instead - Error, - - // present in Desktop CLR and Core CLR + debug pack, normal operation (e.g tracing) - // if missing, get a generic "resource not found" message instead - Debugging, - - // present in Desktop CLR, optional for CoreCLR - DesktopCLR, - - // might not be present, non essential - Optional - }; - - CCompRC() - { - // This constructor will be fired up on startup. Make sure it doesn't - // do anything besides zero-out out values. - m_csMap = NULL; - m_pResourceFile = NULL; - }// CCompRC - - HRESULT Init(LPCWSTR pResourceFile); - void Destroy(); - - HRESULT LoadString(ResourceCategory eCategory, UINT iResourceID, _Out_writes_ (iMax) LPWSTR szBuffer, int iMax , int *pcwchUsed=NULL); - - // Get the default resource location (mscorrc.dll) - static CCompRC* GetDefaultResourceDll(); - -private: -// String resources packaged as PE files only exist on Windows -#ifdef HOST_WINDOWS - HRESULT GetLibrary(HRESOURCEDLL* phInst); -#ifndef DACCESS_COMPILE - HRESULT LoadLibraryHelper(HRESOURCEDLL *pHInst, - SString& rcPath); - HRESULT LoadLibraryThrows(HRESOURCEDLL * pHInst); - HRESULT LoadLibrary(HRESOURCEDLL * pHInst); - HRESULT LoadResourceFile(HRESOURCEDLL * pHInst, LPCWSTR lpFileName); -#endif // DACCESS_COMPILE -#endif // HOST_WINDOWS - - // We do not have global constructors any more - static LONG m_dwDefaultInitialized; - static CCompRC m_DefaultResourceDll; - static LPCWSTR m_pDefaultResource; - - // Use a singleton since we don't support localization any more. - CCulturedHInstance m_Primary; - - CRITSEC_COOKIE m_csMap; - - LPCWSTR m_pResourceFile; + static HRESULT LoadString(UINT iResourceID, _Out_writes_ (iMax) LPWSTR szBuffer, int iMax , int *pcwchUsed=NULL); }; -HRESULT UtilLoadResourceString(CCompRC::ResourceCategory eCategory, UINT iResourceID, _Out_writes_ (iMax) LPWSTR szBuffer, int iMax); - // The HRESULT_FROM_WIN32 macro evaluates its arguments three times. // TODO: All HRESULT_FROM_WIN32(GetLastError()) should be replaced by calls to // this helper function avoid code bloat diff --git a/src/runtime/src/coreclr/interpreter/compiler.cpp b/src/runtime/src/coreclr/interpreter/compiler.cpp index e578f3ed742f..fe416738fa50 100644 --- a/src/runtime/src/coreclr/interpreter/compiler.cpp +++ b/src/runtime/src/coreclr/interpreter/compiler.cpp @@ -586,7 +586,7 @@ void InterpCompiler::EmitBBEndVarMoves(InterpBasicBlock *pTargetBB) } #ifdef TARGET_64BIT // nint and int32 can be used interchangeably. Add implicit conversions. - else if (interpType == InterpTypeI4 && interpDestType == InterpTypeI8) + else if (interpType == InterpTypeI4 && ((interpDestType == InterpTypeI8) || (interpDestType == InterpTypeByRef))) { movOp = INTOP_CONV_I8_I4; } @@ -4542,6 +4542,8 @@ void InterpCompiler::EmitCall(CORINFO_RESOLVED_TOKEN* pConstrainedToken, bool re int32_t vtsize = 0; bool injectRet = false; + bool resultIsNewObjToVTWithCopy = false; + if (newObjThisArgLocation != INT_MAX) { ctorType = GetInterpType(m_compHnd->asCorInfoType(resolvedCallToken.hClass)); @@ -4575,6 +4577,14 @@ void InterpCompiler::EmitCall(CORINFO_RESOLVED_TOKEN* pConstrainedToken, bool re AddIns(INTOP_DEF); m_pLastNewIns->SetDVar(newObjThisVar); + if (ctorType == InterpTypeVT) + { + resultIsNewObjToVTWithCopy = true; + AllocGlobalVarOffset(newObjDVar); + m_pVars[newObjDVar].global = true; + INTERP_DUMP("alloc global var %d to offset %d of size %d\n", newObjDVar, m_pVars[newObjDVar].offset, m_pVars[newObjDVar].size); + } + callArgs[newObjThisArgLocation] = newObjThisVar; } @@ -4950,6 +4960,30 @@ void InterpCompiler::EmitCall(CORINFO_RESOLVED_TOKEN* pConstrainedToken, bool re } } + if (resultIsNewObjToVTWithCopy) + { + // For compliance with the exact letter of the ECMA spec, the result of a newobj to a valuetype must be computed + // by creating an instance of the valuetype, calling the constructor on that instance, and then copying the initialized + // value to the logical IL stack. This is done in case the constructor for the valuetype exposes the `this` pointer, and + // then something else captures that this pointer, and mutates the valuetype after the constructor returns. To prevent this + // from being generally unsafe, we need to make the temporary initial copy of the valuetype to be in a variable which has + // memory which will always be an instance of the newobj type, and to match RyuJit behavior that it is never possible to modify + // a valuetype on the IL evaluation stack we need to copy from there to the evaluation stack after running the constructor. + + assert(m_pStackPointer[-1].var == newObjDVar); + assert(m_pVars[newObjDVar].global); + + // For newobj to VT with copy, we need to copy the value type from the global var to the stack + m_pStackPointer--; + + assert(m_pVars[newObjDVar].interpType == InterpTypeVT); + PushTypeVT(m_pVars[newObjDVar].clsHnd, m_pVars[newObjDVar].size); + AddIns(InterpGetMovForType(InterpTypeVT, true)); + m_pLastNewIns->SetSVar(newObjDVar); + m_pLastNewIns->SetDVar(m_pStackPointer[-1].var); + m_pLastNewIns->data[0] = m_pVars[newObjDVar].size; + } + if (callInfo.sig.isAsyncCall() && m_methodInfo->args.isAsyncCall()) // Async2 functions may need to suspend { EmitSuspend(callInfo, continuationContextHandling); diff --git a/src/runtime/src/coreclr/jit/emit.h b/src/runtime/src/coreclr/jit/emit.h index 0dc7710dc321..4418dc4c2e93 100644 --- a/src/runtime/src/coreclr/jit/emit.h +++ b/src/runtime/src/coreclr/jit/emit.h @@ -3826,17 +3826,6 @@ inline UNATIVE_OFFSET emitter::emitDataSize() return emitConsDsc.dsdOffs; } -/***************************************************************************** - * - * Return a handle to the current position in the output stream. This can - * be later converted to an actual code offset in bytes. - */ - -inline void* emitter::emitCurBlock() -{ - return emitCurIG; -} - /***************************************************************************** * * The emitCurOffset() method returns a cookie that identifies the current diff --git a/src/runtime/src/coreclr/jit/emitpub.h b/src/runtime/src/coreclr/jit/emitpub.h index 389328b8c4f0..67876fbf348b 100644 --- a/src/runtime/src/coreclr/jit/emitpub.h +++ b/src/runtime/src/coreclr/jit/emitpub.h @@ -65,7 +65,6 @@ void emitFinishPrologEpilogGeneration(); /* Record a code position and later convert it to offset */ /************************************************************************/ -void* emitCurBlock(); unsigned emitCurOffset(); unsigned emitSpecifiedOffset(unsigned insCount, unsigned igSize); diff --git a/src/runtime/src/coreclr/jit/emitwasm.cpp b/src/runtime/src/coreclr/jit/emitwasm.cpp index c020eded1465..a3276ef5097c 100644 --- a/src/runtime/src/coreclr/jit/emitwasm.cpp +++ b/src/runtime/src/coreclr/jit/emitwasm.cpp @@ -14,12 +14,6 @@ #define INST(id, nm, info, fmt, opcode) info, #include "instrs.h" }; - -static const uint8_t insOpcodes[] -{ - #define INST(id, nm, info, fmt, opcode) static_cast(opcode), - #include "instrs.h" -}; // clang-format on void emitter::emitIns(instruction ins) @@ -93,21 +87,25 @@ bool emitter::emitInsIsStore(instruction ins) emitter::insFormat emitter::emitInsFormat(instruction ins) { - // clang-format off - const static insFormat insFormats[] = - { - #define INST(id, nm, info, fmt, opcode) fmt, - #include "instrs.h" + static_assert(IF_COUNT < 255); + + const static uint8_t insFormats[] = { +#define INST(id, nm, info, fmt, opcode) fmt, +#include "instrs.h" }; - // clang-format on assert(ins < ArrLen(insFormats)); assert((insFormats[ins] != IF_NONE)); - return insFormats[ins]; + return static_cast(insFormats[ins]); } static unsigned GetInsOpcode(instruction ins) { + static const uint8_t insOpcodes[] = { +#define INST(id, nm, info, fmt, opcode) static_cast(opcode), +#include "instrs.h" + }; + assert(ins < ArrLen(insOpcodes)); return insOpcodes[ins]; } diff --git a/src/runtime/src/coreclr/jit/gentree.cpp b/src/runtime/src/coreclr/jit/gentree.cpp index 9682ba4a42df..0e2ee29316ce 100644 --- a/src/runtime/src/coreclr/jit/gentree.cpp +++ b/src/runtime/src/coreclr/jit/gentree.cpp @@ -19919,6 +19919,11 @@ bool GenTree::IsArrayAddr(GenTreeArrAddr** pArrAddr) // bool GenTree::SupportsSettingZeroFlag() { + if (SupportsSettingFlagsAsCompareToZero()) + { + return true; + } + #if defined(TARGET_XARCH) if (OperIs(GT_LSH, GT_RSH, GT_RSZ, GT_ROL, GT_ROR)) { @@ -19938,11 +19943,6 @@ bool GenTree::SupportsSettingZeroFlag() } #endif #elif defined(TARGET_ARM64) - if (OperIs(GT_AND, GT_AND_NOT)) - { - return true; - } - // We do not support setting zero flag for madd/msub. if (OperIs(GT_NEG) && (!gtGetOp1()->OperIs(GT_MUL) || !gtGetOp1()->isContained())) { @@ -19959,12 +19959,13 @@ bool GenTree::SupportsSettingZeroFlag() } //------------------------------------------------------------------------ -// SupportsSettingFlagsAsCompareToZero: Returns true if we support setting -// flags for compare to zero operations. +// SupportsSettingFlagsAsCompareToZero: +// Returns true if this operation supports setting the flags as if the result +// was a compare to zero. // bool GenTree::SupportsSettingFlagsAsCompareToZero() { -#if defined(TARGET_ARMARCH) +#if defined(TARGET_ARM64) return OperIs(GT_AND, GT_AND_NOT); #else return false; diff --git a/src/runtime/src/coreclr/jit/instrswasm.h b/src/runtime/src/coreclr/jit/instrswasm.h index b892290f1ad3..7b204d189a0d 100644 --- a/src/runtime/src/coreclr/jit/instrswasm.h +++ b/src/runtime/src/coreclr/jit/instrswasm.h @@ -20,8 +20,6 @@ #error INST must be defined before including this file. #endif -// TODO-WASM: fill out with more instructions (and everything else needed). -// // clang-format off // control flow diff --git a/src/runtime/src/coreclr/jit/lower.cpp b/src/runtime/src/coreclr/jit/lower.cpp index 4018117fce29..0f02d542659c 100644 --- a/src/runtime/src/coreclr/jit/lower.cpp +++ b/src/runtime/src/coreclr/jit/lower.cpp @@ -3239,11 +3239,11 @@ void Lowering::LowerFastTailCall(GenTreeCall* call) if (!putargs.Empty()) { GenTree* firstPutargStk = putargs.Bottom(0); - GenTree* firstPutargStkOp = firstPutargStk->gtGetOp1(); + GenTree* firstPutargStkOp = FirstOperand(firstPutargStk); for (int i = 1; i < putargs.Height(); i++) { firstPutargStk = LIR::FirstNode(firstPutargStk, putargs.Bottom(i)); - firstPutargStkOp = LIR::FirstNode(firstPutargStkOp, putargs.Bottom(i)->gtGetOp1()); + firstPutargStkOp = LIR::FirstNode(firstPutargStkOp, FirstOperand(putargs.Bottom(i))); } // Since this is a fast tailcall each PUTARG_STK will place the argument in the // _incoming_ arg space area. This will effectively overwrite our already existing @@ -3279,6 +3279,10 @@ void Lowering::LowerFastTailCall(GenTreeCall* call) continue; } + JITDUMP( + "PUTARG_STK [%06u] overwrites [%06u..%06u); parameter V%03u lives in [%06u..%06u); may need defensive copies\n", + Compiler::dspTreeID(put), overwrittenStart, overwrittenEnd, callerArgLclNum, argStart, argEnd); + // Codegen cannot handle a partially overlapping copy. For // example, if we have // bar(S16 stack, S32 stack2) @@ -3287,10 +3291,11 @@ void Lowering::LowerFastTailCall(GenTreeCall* call) // ahead. It is possible that this PUTARG_STK is the only use, // in which case we will need to introduce a temp, so look for // uses starting from it. Note that we assume that in-place - // copies are OK. + // copies are ok provided the source is a scalar value. GenTree* lookForUsesFrom = put->gtNext; - if (overwrittenStart != argStart) + if ((overwrittenStart != argStart) || put->gtGetOp1()->OperIsFieldList()) { + JITDUMP("Non-atomic copy may be self-interfering. Expanding search...\n"); lookForUsesFrom = firstPutargStkOp; } @@ -3354,7 +3359,43 @@ void Lowering::LowerFastTailCall(GenTreeCall* call) unreached(); #endif } + +//------------------------------------------------------------------------ +// FirstOperand: +// Find the earliest operand of a node. +// +// Arguments: +// node - The node // +// Returns: +// The earliest evaluated operand. +// +GenTree* Lowering::FirstOperand(GenTree* node) +{ + struct Helper + { + GenTree* Result = nullptr; + + void Visit(GenTree* node) + { + node->VisitOperands([=](GenTree* op) { + Result = Result == nullptr ? op : LIR::FirstNode(Result, op); + + if (op->isContained()) + { + Visit(op); + } + + return GenTree::VisitResult::Continue; + }); + } + }; + + Helper helper; + helper.Visit(node); + return helper.Result; +} + //------------------------------------------------------------------------ // RehomeArgForFastTailCall: Introduce temps for args that may be overwritten // during fast tailcall sequence. diff --git a/src/runtime/src/coreclr/jit/lower.h b/src/runtime/src/coreclr/jit/lower.h index 8f5d18e16f9e..a09f858a2a5f 100644 --- a/src/runtime/src/coreclr/jit/lower.h +++ b/src/runtime/src/coreclr/jit/lower.h @@ -202,6 +202,7 @@ class Lowering final : public Phase GenTree* LowerNonvirtPinvokeCall(GenTreeCall* call); GenTree* LowerTailCallViaJitHelper(GenTreeCall* callNode, GenTree* callTarget); void LowerFastTailCall(GenTreeCall* callNode); + GenTree* FirstOperand(GenTree* node); void RehomeArgForFastTailCall(unsigned int lclNum, GenTree* insertTempBefore, GenTree* lookForUsesStart, diff --git a/src/runtime/src/coreclr/jit/registeropswasm.cpp b/src/runtime/src/coreclr/jit/registeropswasm.cpp index 8e87aac66b86..724c69154faf 100644 --- a/src/runtime/src/coreclr/jit/registeropswasm.cpp +++ b/src/runtime/src/coreclr/jit/registeropswasm.cpp @@ -124,18 +124,6 @@ bool genIsValidFloatReg(regNumber reg) return (type == WasmValueType::F32) || (type == WasmValueType::F64); } -bool isValidIntArgReg(regNumber reg, CorInfoCallConvExtension callConv) -{ - NYI_WASM("isValidIntArgReg"); - return false; -} - -bool isValidFloatArgReg(regNumber reg) -{ - NYI_WASM("isValidFloatArgReg"); - return false; -} - const char* getRegName(regNumber reg) { if (reg == REG_NA) diff --git a/src/runtime/src/coreclr/jit/registeropswasm.h b/src/runtime/src/coreclr/jit/registeropswasm.h index 1af36e34d316..1bb8bd79b016 100644 --- a/src/runtime/src/coreclr/jit/registeropswasm.h +++ b/src/runtime/src/coreclr/jit/registeropswasm.h @@ -24,5 +24,3 @@ bool genIsValidReg(regNumber reg); bool genIsValidIntReg(regNumber reg); bool genIsValidIntOrFakeReg(regNumber reg); bool genIsValidFloatReg(regNumber reg); -bool isValidIntArgReg(regNumber reg, CorInfoCallConvExtension callConv); -bool isValidFloatArgReg(regNumber reg); diff --git a/src/runtime/src/coreclr/jit/scev.cpp b/src/runtime/src/coreclr/jit/scev.cpp index 5a11e81e85a5..7425f8f3e1a4 100644 --- a/src/runtime/src/coreclr/jit/scev.cpp +++ b/src/runtime/src/coreclr/jit/scev.cpp @@ -688,7 +688,7 @@ Scev* ScalarEvolutionContext::AnalyzeNew(BasicBlock* block, GenTree* tree, int d case GT_CAST: { GenTreeCast* cast = tree->AsCast(); - if (cast->gtCastType != TYP_LONG) + if ((cast->gtCastType != TYP_LONG) && (cast->gtCastType != TYP_ULONG)) { return nullptr; } diff --git a/src/runtime/src/coreclr/jit/targetwasm.cpp b/src/runtime/src/coreclr/jit/targetwasm.cpp index f459b8950ae2..56f342f3af38 100644 --- a/src/runtime/src/coreclr/jit/targetwasm.cpp +++ b/src/runtime/src/coreclr/jit/targetwasm.cpp @@ -51,8 +51,7 @@ ABIPassingInformation WasmClassifier::Classify(Compiler* comp, NYI_WASM("WasmClassifier::Classify - structs"); } - type = genActualType(type); - regNumber reg = MakeWasmReg(m_localIndex++, type); + regNumber reg = MakeWasmReg(m_localIndex++, genActualType(type)); ABIPassingSegment seg = ABIPassingSegment::InRegister(reg, 0, genTypeSize(type)); return ABIPassingInformation::FromSegmentByValue(comp, seg); } diff --git a/src/runtime/src/coreclr/nativeaot/Bootstrap/CMakeLists.txt b/src/runtime/src/coreclr/nativeaot/Bootstrap/CMakeLists.txt index 889c73156cfc..ad42132a2f77 100644 --- a/src/runtime/src/coreclr/nativeaot/Bootstrap/CMakeLists.txt +++ b/src/runtime/src/coreclr/nativeaot/Bootstrap/CMakeLists.txt @@ -2,15 +2,14 @@ function(install_bootstrapper_object targetName destination) add_dependencies(nativeaot ${targetName}) if (MSVC) - set_target_properties(${targetName} PROPERTIES COMPILE_PDB_NAME ${targetName}) + set_target_properties(${targetName} PROPERTIES + COMPILE_PDB_NAME ${targetName} + COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/$" + ) endif() if (MSVC) install (FILES $ DESTINATION ${destination} COMPONENT nativeaot RENAME ${targetName}.obj) - if (CMAKE_GENERATOR MATCHES "Visual Studio") - install (FILES ${CMAKE_CURRENT_BINARY_DIR}/$/${targetName}.pdb DESTINATION ${destination} COMPONENT nativeaot) - else() - install (FILES ${CMAKE_CURRENT_BINARY_DIR}/${targetName}.pdb DESTINATION ${destination} COMPONENT nativeaot) - endif() + install (FILES ${CMAKE_CURRENT_BINARY_DIR}/$/${targetName}.pdb DESTINATION ${destination} COMPONENT nativeaot) else() install (FILES $ DESTINATION ${destination} COMPONENT nativeaot RENAME lib${targetName}.o) endif() diff --git a/src/runtime/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.NativeAot.cs b/src/runtime/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.NativeAot.cs index 541f62969ab5..5d25312088a7 100644 --- a/src/runtime/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.NativeAot.cs +++ b/src/runtime/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.NativeAot.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics.CodeAnalysis; +using System.Numerics; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Threading; @@ -224,17 +225,18 @@ public static void PrepareMethod(RuntimeMethodHandle method, RuntimeTypeHandle[] throw new ArgumentException(SR.InvalidOperation_HandleIsNotInitialized, nameof(method)); } - /// - /// Allocate memory that is associated with the and - /// will be freed if and when the is unloaded. - /// - /// Type associated with the allocated memory. - /// Amount of memory in bytes to allocate. - /// The allocated memory + /// Allocates memory that's associated with the and is freed if and when the is unloaded. + /// The type associated with the allocated memory. + /// The amount of memory to allocate, in bytes. + /// The allocated memory. + /// must be a type provided by the runtime. + /// is negative. public static unsafe IntPtr AllocateTypeAssociatedMemory(Type type, int size) { if (type is not RuntimeType) + { throw new ArgumentException(SR.Arg_MustBeType, nameof(type)); + } ArgumentOutOfRangeException.ThrowIfNegative(size); @@ -242,6 +244,35 @@ public static unsafe IntPtr AllocateTypeAssociatedMemory(Type type, int size) return (IntPtr)NativeMemory.AllocZeroed((uint)size); } + /// Allocates aligned memory that's associated with the and is freed if and when the is unloaded. + /// The type associated with the allocated memory. + /// The amount of memory to allocate, in bytes. + /// The alignment, in bytes, of the memory to allocate. This must be a power of 2. + /// The allocated aligned memory. + /// must be a type provided by the runtime. + /// is negative. + /// is not a power of 2. + public static unsafe IntPtr AllocateTypeAssociatedMemory(Type type, int size, int alignment) + { + if (type is not RuntimeType) + { + throw new ArgumentException(SR.Arg_MustBeType, nameof(type)); + } + + ArgumentOutOfRangeException.ThrowIfNegative(size); + + if (!BitOperations.IsPow2(alignment)) + { + // The C standard doesn't define what a valid alignment is, however Windows and POSIX implementation requires a power of 2 + ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AlignmentMustBePow2); + } + + // We don't support unloading; the memory will never be freed. + void* result = NativeMemory.AlignedAlloc((uint)size, (uint)alignment); + NativeMemory.Clear(result, (uint)size); + return (IntPtr)result; + } + public static void PrepareDelegate(Delegate d) { } diff --git a/src/runtime/src/tests/ilverify/ILMethodTester.cs b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILMethodTester.cs similarity index 100% rename from src/runtime/src/tests/ilverify/ILMethodTester.cs rename to src/runtime/src/coreclr/tools/ILVerification.Tests/ILMethodTester.cs diff --git a/src/runtime/src/tests/ilverify/ILTests/AccessTests.il b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/AccessTests.il similarity index 100% rename from src/runtime/src/tests/ilverify/ILTests/AccessTests.il rename to src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/AccessTests.il diff --git a/src/runtime/src/tests/ilverify/ILTests/ILTests.targets b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/AccessTests.ilproj similarity index 59% rename from src/runtime/src/tests/ilverify/ILTests/ILTests.targets rename to src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/AccessTests.ilproj index cf461072441c..356b4dcc7789 100644 --- a/src/runtime/src/tests/ilverify/ILTests/ILTests.targets +++ b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/AccessTests.ilproj @@ -1,9 +1,6 @@ - Library - SharedLibrary $(MSBuildProjectName) - $(BaseOutputPathWithConfig)ilverify\Tests diff --git a/src/runtime/src/tests/ilverify/ILTests/AccessTestsExtern.il b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/AccessTestsExtern.il similarity index 100% rename from src/runtime/src/tests/ilverify/ILTests/AccessTestsExtern.il rename to src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/AccessTestsExtern.il diff --git a/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/AccessTestsExtern.ilproj b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/AccessTestsExtern.ilproj new file mode 100644 index 000000000000..356b4dcc7789 --- /dev/null +++ b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/AccessTestsExtern.ilproj @@ -0,0 +1,9 @@ + + + $(MSBuildProjectName) + + + + + + diff --git a/src/runtime/src/tests/ilverify/ILTests/AccessTestsFriend.il b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/AccessTestsFriend.il similarity index 100% rename from src/runtime/src/tests/ilverify/ILTests/AccessTestsFriend.il rename to src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/AccessTestsFriend.il diff --git a/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/AccessTestsFriend.ilproj b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/AccessTestsFriend.ilproj new file mode 100644 index 000000000000..356b4dcc7789 --- /dev/null +++ b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/AccessTestsFriend.ilproj @@ -0,0 +1,9 @@ + + + $(MSBuildProjectName) + + + + + + diff --git a/src/runtime/src/tests/ilverify/ILTests/ArrayTests.il b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ArrayTests.il similarity index 100% rename from src/runtime/src/tests/ilverify/ILTests/ArrayTests.il rename to src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ArrayTests.il diff --git a/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ArrayTests.ilproj b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ArrayTests.ilproj new file mode 100644 index 000000000000..356b4dcc7789 --- /dev/null +++ b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ArrayTests.ilproj @@ -0,0 +1,9 @@ + + + $(MSBuildProjectName) + + + + + + diff --git a/src/runtime/src/tests/ilverify/ILTests/BasicArithmeticTests.il b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/BasicArithmeticTests.il similarity index 100% rename from src/runtime/src/tests/ilverify/ILTests/BasicArithmeticTests.il rename to src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/BasicArithmeticTests.il diff --git a/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/BasicArithmeticTests.ilproj b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/BasicArithmeticTests.ilproj new file mode 100644 index 000000000000..356b4dcc7789 --- /dev/null +++ b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/BasicArithmeticTests.ilproj @@ -0,0 +1,9 @@ + + + $(MSBuildProjectName) + + + + + + diff --git a/src/runtime/src/tests/ilverify/ILTests/BranchingTests.il b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/BranchingTests.il similarity index 100% rename from src/runtime/src/tests/ilverify/ILTests/BranchingTests.il rename to src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/BranchingTests.il diff --git a/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/BranchingTests.ilproj b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/BranchingTests.ilproj new file mode 100644 index 000000000000..356b4dcc7789 --- /dev/null +++ b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/BranchingTests.ilproj @@ -0,0 +1,9 @@ + + + $(MSBuildProjectName) + + + + + + diff --git a/src/runtime/src/tests/ilverify/ILTests/CallTests.il b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/CallTests.il similarity index 100% rename from src/runtime/src/tests/ilverify/ILTests/CallTests.il rename to src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/CallTests.il diff --git a/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/CallTests.ilproj b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/CallTests.ilproj new file mode 100644 index 000000000000..356b4dcc7789 --- /dev/null +++ b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/CallTests.ilproj @@ -0,0 +1,9 @@ + + + $(MSBuildProjectName) + + + + + + diff --git a/src/runtime/src/tests/ilverify/ILTests/CastingTests.il b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/CastingTests.il similarity index 100% rename from src/runtime/src/tests/ilverify/ILTests/CastingTests.il rename to src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/CastingTests.il diff --git a/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/CastingTests.ilproj b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/CastingTests.ilproj new file mode 100644 index 000000000000..356b4dcc7789 --- /dev/null +++ b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/CastingTests.ilproj @@ -0,0 +1,9 @@ + + + $(MSBuildProjectName) + + + + + + diff --git a/src/runtime/src/tests/ilverify/ILTests/ComparisonTests.il b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ComparisonTests.il similarity index 100% rename from src/runtime/src/tests/ilverify/ILTests/ComparisonTests.il rename to src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ComparisonTests.il diff --git a/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ComparisonTests.ilproj b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ComparisonTests.ilproj new file mode 100644 index 000000000000..356b4dcc7789 --- /dev/null +++ b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ComparisonTests.ilproj @@ -0,0 +1,9 @@ + + + $(MSBuildProjectName) + + + + + + diff --git a/src/runtime/src/tests/ilverify/ILTests/DefaultInterfaceMethod.il b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/DefaultInterfaceMethod.il similarity index 100% rename from src/runtime/src/tests/ilverify/ILTests/DefaultInterfaceMethod.il rename to src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/DefaultInterfaceMethod.il diff --git a/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/DefaultInterfaceMethod.ilproj b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/DefaultInterfaceMethod.ilproj new file mode 100644 index 000000000000..356b4dcc7789 --- /dev/null +++ b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/DefaultInterfaceMethod.ilproj @@ -0,0 +1,9 @@ + + + $(MSBuildProjectName) + + + + + + diff --git a/src/runtime/src/tests/ilverify/ILTests/DelegateTests.il b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/DelegateTests.il similarity index 100% rename from src/runtime/src/tests/ilverify/ILTests/DelegateTests.il rename to src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/DelegateTests.il diff --git a/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/DelegateTests.ilproj b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/DelegateTests.ilproj new file mode 100644 index 000000000000..356b4dcc7789 --- /dev/null +++ b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/DelegateTests.ilproj @@ -0,0 +1,9 @@ + + + $(MSBuildProjectName) + + + + + + diff --git a/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/Directory.Build.props b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/Directory.Build.props new file mode 100644 index 000000000000..2d233f4468da --- /dev/null +++ b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/Directory.Build.props @@ -0,0 +1,7 @@ + + + + $(NetCoreAppToolCurrent) + false + + diff --git a/src/runtime/src/tests/ilverify/ILTests/ExceptionRegionTests.il b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ExceptionRegionTests.il similarity index 100% rename from src/runtime/src/tests/ilverify/ILTests/ExceptionRegionTests.il rename to src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ExceptionRegionTests.il diff --git a/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ExceptionRegionTests.ilproj b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ExceptionRegionTests.ilproj new file mode 100644 index 000000000000..356b4dcc7789 --- /dev/null +++ b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ExceptionRegionTests.ilproj @@ -0,0 +1,9 @@ + + + $(MSBuildProjectName) + + + + + + diff --git a/src/runtime/src/tests/ilverify/ILTests/FieldTests.il b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/FieldTests.il similarity index 100% rename from src/runtime/src/tests/ilverify/ILTests/FieldTests.il rename to src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/FieldTests.il diff --git a/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/FieldTests.ilproj b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/FieldTests.ilproj new file mode 100644 index 000000000000..356b4dcc7789 --- /dev/null +++ b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/FieldTests.ilproj @@ -0,0 +1,9 @@ + + + $(MSBuildProjectName) + + + + + + diff --git a/src/runtime/src/tests/ilverify/ILTests/FtnTests.il b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/FtnTests.il similarity index 100% rename from src/runtime/src/tests/ilverify/ILTests/FtnTests.il rename to src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/FtnTests.il diff --git a/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/FtnTests.ilproj b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/FtnTests.ilproj new file mode 100644 index 000000000000..356b4dcc7789 --- /dev/null +++ b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/FtnTests.ilproj @@ -0,0 +1,9 @@ + + + $(MSBuildProjectName) + + + + + + diff --git a/src/runtime/src/tests/ilverify/ILTests/FunctionPointerTests.il b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/FunctionPointerTests.il similarity index 100% rename from src/runtime/src/tests/ilverify/ILTests/FunctionPointerTests.il rename to src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/FunctionPointerTests.il diff --git a/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/FunctionPointerTests.ilproj b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/FunctionPointerTests.ilproj new file mode 100644 index 000000000000..356b4dcc7789 --- /dev/null +++ b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/FunctionPointerTests.ilproj @@ -0,0 +1,9 @@ + + + $(MSBuildProjectName) + + + + + + diff --git a/src/runtime/src/tests/ilverify/ILTests/GenericInterface.il b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/GenericInterface.il similarity index 100% rename from src/runtime/src/tests/ilverify/ILTests/GenericInterface.il rename to src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/GenericInterface.il diff --git a/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/GenericInterface.ilproj b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/GenericInterface.ilproj new file mode 100644 index 000000000000..356b4dcc7789 --- /dev/null +++ b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/GenericInterface.ilproj @@ -0,0 +1,9 @@ + + + $(MSBuildProjectName) + + + + + + diff --git a/src/runtime/src/tests/ilverify/ILTests/InterfaceDefinition.il b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/InterfaceDefinition.il similarity index 100% rename from src/runtime/src/tests/ilverify/ILTests/InterfaceDefinition.il rename to src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/InterfaceDefinition.il diff --git a/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/InterfaceDefinition.ilproj b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/InterfaceDefinition.ilproj new file mode 100644 index 000000000000..356b4dcc7789 --- /dev/null +++ b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/InterfaceDefinition.ilproj @@ -0,0 +1,9 @@ + + + $(MSBuildProjectName) + + + + + + diff --git a/src/runtime/src/tests/ilverify/ILTests/InterfaceImplementation.il b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/InterfaceImplementation.il similarity index 100% rename from src/runtime/src/tests/ilverify/ILTests/InterfaceImplementation.il rename to src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/InterfaceImplementation.il diff --git a/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/InterfaceImplementation.ilproj b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/InterfaceImplementation.ilproj new file mode 100644 index 000000000000..356b4dcc7789 --- /dev/null +++ b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/InterfaceImplementation.ilproj @@ -0,0 +1,9 @@ + + + $(MSBuildProjectName) + + + + + + diff --git a/src/runtime/src/tests/ilverify/ILTests/LoadStoreIndirectTests.il b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/LoadStoreIndirectTests.il similarity index 100% rename from src/runtime/src/tests/ilverify/ILTests/LoadStoreIndirectTests.il rename to src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/LoadStoreIndirectTests.il diff --git a/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/LoadStoreIndirectTests.ilproj b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/LoadStoreIndirectTests.ilproj new file mode 100644 index 000000000000..356b4dcc7789 --- /dev/null +++ b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/LoadStoreIndirectTests.ilproj @@ -0,0 +1,9 @@ + + + $(MSBuildProjectName) + + + + + + diff --git a/src/runtime/src/tests/ilverify/ILTests/LocalAllocTests.il b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/LocalAllocTests.il similarity index 100% rename from src/runtime/src/tests/ilverify/ILTests/LocalAllocTests.il rename to src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/LocalAllocTests.il diff --git a/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/LocalAllocTests.ilproj b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/LocalAllocTests.ilproj new file mode 100644 index 000000000000..356b4dcc7789 --- /dev/null +++ b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/LocalAllocTests.ilproj @@ -0,0 +1,9 @@ + + + $(MSBuildProjectName) + + + + + + diff --git a/src/runtime/src/tests/ilverify/ILTests/NewobjTests.il b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/NewobjTests.il similarity index 100% rename from src/runtime/src/tests/ilverify/ILTests/NewobjTests.il rename to src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/NewobjTests.il diff --git a/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/NewobjTests.ilproj b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/NewobjTests.ilproj new file mode 100644 index 000000000000..356b4dcc7789 --- /dev/null +++ b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/NewobjTests.ilproj @@ -0,0 +1,9 @@ + + + $(MSBuildProjectName) + + + + + + diff --git a/src/runtime/src/tests/ilverify/ILTests/PrefixTests.il b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/PrefixTests.il similarity index 100% rename from src/runtime/src/tests/ilverify/ILTests/PrefixTests.il rename to src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/PrefixTests.il diff --git a/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/PrefixTests.ilproj b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/PrefixTests.ilproj new file mode 100644 index 000000000000..356b4dcc7789 --- /dev/null +++ b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/PrefixTests.ilproj @@ -0,0 +1,9 @@ + + + $(MSBuildProjectName) + + + + + + diff --git a/src/runtime/src/tests/ilverify/ILTests/ReturnTests.il b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ReturnTests.il similarity index 100% rename from src/runtime/src/tests/ilverify/ILTests/ReturnTests.il rename to src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ReturnTests.il diff --git a/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ReturnTests.ilproj b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ReturnTests.ilproj new file mode 100644 index 000000000000..356b4dcc7789 --- /dev/null +++ b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ReturnTests.ilproj @@ -0,0 +1,9 @@ + + + $(MSBuildProjectName) + + + + + + diff --git a/src/runtime/src/tests/ilverify/ILTests/RuntimeAsyncTests.il b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/RuntimeAsyncTests.il similarity index 100% rename from src/runtime/src/tests/ilverify/ILTests/RuntimeAsyncTests.il rename to src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/RuntimeAsyncTests.il diff --git a/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/RuntimeAsyncTests.ilproj b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/RuntimeAsyncTests.ilproj new file mode 100644 index 000000000000..356b4dcc7789 --- /dev/null +++ b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/RuntimeAsyncTests.ilproj @@ -0,0 +1,9 @@ + + + $(MSBuildProjectName) + + + + + + diff --git a/src/runtime/src/tests/ilverify/ILTests/ShiftTests.il b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ShiftTests.il similarity index 100% rename from src/runtime/src/tests/ilverify/ILTests/ShiftTests.il rename to src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ShiftTests.il diff --git a/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ShiftTests.ilproj b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ShiftTests.ilproj new file mode 100644 index 000000000000..356b4dcc7789 --- /dev/null +++ b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ShiftTests.ilproj @@ -0,0 +1,9 @@ + + + $(MSBuildProjectName) + + + + + + diff --git a/src/runtime/src/tests/ilverify/ILTests/SwitchTests.il b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/SwitchTests.il similarity index 100% rename from src/runtime/src/tests/ilverify/ILTests/SwitchTests.il rename to src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/SwitchTests.il diff --git a/src/runtime/src/tests/ilverify/ILTests/ThisStateTests.il b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ThisStateTests.il similarity index 100% rename from src/runtime/src/tests/ilverify/ILTests/ThisStateTests.il rename to src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ThisStateTests.il diff --git a/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ThisStateTests.ilproj b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ThisStateTests.ilproj new file mode 100644 index 000000000000..356b4dcc7789 --- /dev/null +++ b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ThisStateTests.ilproj @@ -0,0 +1,9 @@ + + + $(MSBuildProjectName) + + + + + + diff --git a/src/runtime/src/tests/ilverify/ILTests/ValueTypeTests.il b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ValueTypeTests.il similarity index 100% rename from src/runtime/src/tests/ilverify/ILTests/ValueTypeTests.il rename to src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ValueTypeTests.il diff --git a/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ValueTypeTests.ilproj b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ValueTypeTests.ilproj new file mode 100644 index 000000000000..356b4dcc7789 --- /dev/null +++ b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTests/ValueTypeTests.ilproj @@ -0,0 +1,9 @@ + + + $(MSBuildProjectName) + + + + + + diff --git a/src/runtime/src/tests/ilverify/ILTypeVerificationTester.cs b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILTypeVerificationTester.cs similarity index 100% rename from src/runtime/src/tests/ilverify/ILTypeVerificationTester.cs rename to src/runtime/src/coreclr/tools/ILVerification.Tests/ILTypeVerificationTester.cs diff --git a/src/runtime/src/coreclr/tools/ILVerification.Tests/ILVerification.Tests.csproj b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILVerification.Tests.csproj new file mode 100644 index 000000000000..09923f87e723 --- /dev/null +++ b/src/runtime/src/coreclr/tools/ILVerification.Tests/ILVerification.Tests.csproj @@ -0,0 +1,25 @@ + + + true + $(NetCoreAppToolCurrent) + false + + + + + + + + + + + + + + false + Content + PreserveNewest + Tests\%(Filename).dll + + + diff --git a/src/runtime/src/coreclr/tools/ILVerification.Tests/JsonContext.cs b/src/runtime/src/coreclr/tools/ILVerification.Tests/JsonContext.cs new file mode 100644 index 000000000000..8ab954e3fd58 --- /dev/null +++ b/src/runtime/src/coreclr/tools/ILVerification.Tests/JsonContext.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Text.Json.Serialization; +using ILVerify; + +namespace ILVerification.Tests +{ + [JsonSourceGenerationOptions(WriteIndented = false)] + [JsonSerializable(typeof(List))] + internal partial class JsonContext : JsonSerializerContext + { + } +} diff --git a/src/runtime/src/tests/ilverify/TestDataLoader.cs b/src/runtime/src/coreclr/tools/ILVerification.Tests/TestDataLoader.cs similarity index 95% rename from src/runtime/src/tests/ilverify/TestDataLoader.cs rename to src/runtime/src/coreclr/tools/ILVerification.Tests/TestDataLoader.cs index ea490973255d..bcd0f240b0c5 100644 --- a/src/runtime/src/tests/ilverify/TestDataLoader.cs +++ b/src/runtime/src/coreclr/tools/ILVerification.Tests/TestDataLoader.cs @@ -11,7 +11,7 @@ using System.Text; using ILVerify; using Internal.TypeSystem.Ecma; -using Newtonsoft.Json; +using System.Text.Json; using Xunit; using Xunit.Abstractions; @@ -36,7 +36,7 @@ class TestDataLoader /// [FriendlyName]_ValidType_Valid /// /// - public static IEnumerable GetTypesWithValidType() + public static IEnumerable GetTypesWithValidType() { var typeSelector = new Func((mparams, typeDefinitionHandle) => { @@ -54,7 +54,7 @@ public static IEnumerable GetTypesWithValidType() /// [FriendlyName]_InvalidType_[ExpectedVerifierError1]@[ExpectedVerifierError2]....[ExpectedVerifierErrorN] /// /// - public static IEnumerable GetTypesWithInvalidType() + public static IEnumerable GetTypesWithInvalidType() { var typeSelector = new Func((mparams, typeDefinitionHandle) => { @@ -110,7 +110,7 @@ private static List GetTestTypeFromDll(Func - public static IEnumerable GetMethodsWithValidIL() + public static IEnumerable GetMethodsWithValidIL() { var methodSelector = new Func((mparams, methodHandle) => { @@ -132,7 +132,7 @@ public static IEnumerable GetMethodsWithValidIL() /// 3. part: the expected VerifierErrors as string separated by '.'. /// E.g.: SimpleAdd_Invalid_ExpectedNumericType /// - public static IEnumerable GetMethodsWithInvalidIL() + public static IEnumerable GetMethodsWithInvalidIL() { var methodSelector = new Func((mparams, methodHandle) => { @@ -306,6 +306,10 @@ public PEReader Resolve(string simpleName) public abstract class TestCase : IXunitSerializable { + public TestCase() + { + } + public string TestName { get; set; } public string TypeName { get; set; } public string MethodName { get; set; } @@ -351,7 +355,7 @@ public class InvalidILTestCase : TestCase public override void Serialize(IXunitSerializationInfo info) { base.Serialize(info); - var serializedExpectedErrors = JsonConvert.SerializeObject(ExpectedVerifierErrors); + var serializedExpectedErrors = JsonSerializer.Serialize(ExpectedVerifierErrors, JsonContext.Default.ListVerifierError); info.AddValue(nameof(ExpectedVerifierErrors), serializedExpectedErrors); } @@ -359,7 +363,7 @@ public override void Deserialize(IXunitSerializationInfo info) { base.Deserialize(info); var serializedExpectedErrors = info.GetValue(nameof(ExpectedVerifierErrors)); - ExpectedVerifierErrors = JsonConvert.DeserializeObject>(serializedExpectedErrors); + ExpectedVerifierErrors = JsonSerializer.Deserialize(serializedExpectedErrors, JsonContext.Default.ListVerifierError); } public override string ToString() @@ -393,7 +397,7 @@ public class InvalidTypeTestCase : TestCase public override void Serialize(IXunitSerializationInfo info) { base.Serialize(info); - var serializedExpectedErrors = JsonConvert.SerializeObject(ExpectedVerifierErrors); + var serializedExpectedErrors = JsonSerializer.Serialize(ExpectedVerifierErrors, JsonContext.Default.ListVerifierError); info.AddValue(nameof(ExpectedVerifierErrors), serializedExpectedErrors); } @@ -401,7 +405,7 @@ public override void Deserialize(IXunitSerializationInfo info) { base.Deserialize(info); var serializedExpectedErrors = info.GetValue(nameof(ExpectedVerifierErrors)); - ExpectedVerifierErrors = JsonConvert.DeserializeObject>(serializedExpectedErrors); + ExpectedVerifierErrors = JsonSerializer.Deserialize(serializedExpectedErrors, JsonContext.Default.ListVerifierError); } public override string ToString() diff --git a/src/runtime/src/coreclr/tools/ILVerify/README.md b/src/runtime/src/coreclr/tools/ILVerify/README.md index ec92aad8b9ba..8b7c2c5df219 100644 --- a/src/runtime/src/coreclr/tools/ILVerify/README.md +++ b/src/runtime/src/coreclr/tools/ILVerify/README.md @@ -40,44 +40,13 @@ The code is split into three projects: ## Tests -To test the ILVerification library we have small methods checked in as .il files testing specific verification scenarios. These tests live under [src/tests/ilverify/ILTests](../../../tests/ilverify/ILTests). Tests are grouped into .il files based on functionalities they test. There is no strict policy here, the goal is to have a few dozen .il files instead of thousands containing each only a single method. +To test the ILVerification library we have small methods checked in as .il files testing specific verification scenarios. These tests live under [src/coreclr/tools/ILVerification.Tests/ILTests](../ILVerification.Tests/ILTests). Tests are grouped into .il files based on functionalities they test. There is no strict policy here, the goal is to have a few dozen .il files instead of thousands containing each only a single method. -The test project itself is under [src/tests/ilverify](../../../tests/ilverify) +The test project itself is under [src/coreclr/tools/ILVerification.Tests](../ILVerification.Tests) ### Building and Running Tests -General instructions to build this library can be found [here](https://github.com/dotnet/runtime/blob/main/docs/workflow/testing/coreclr/testing.md). - -As quick snippet which should be enough to build CoreCLR -``` -./build.cmd -s clr+libs -c release -``` - -As the test project is marked with priority=1, simply building the test projects from the root of the project is not enough. Run the following to build ilverify tests: - -```shell -src/tests/build.(cmd/sh) release tree ilverify -``` - -It is important to not attempt to build the test project using `dotnet build` or `dotnet test`, as this will invalidate the state of the build and requires a full rebuild of both (see this [issue](https://github.com/dotnet/runtime/issues/43967)). - -To incrementally build the ILVerify tests in isolation, run the following: - -```sh -dotnet.(cmd/sh) msbuild ./src/tests/ilverify/ILVerificationTests.csproj /p:Configuration=Release -``` - -In order to run the tests, execute: - -on Linux -```sh -artifacts/tests/coreclr/linux.x64.Release/ilverify/ILVerificationTests.sh -coreroot=artifacts/tests/coreclr/linux.x64.Release/Tests/Core_Root -``` -on Windows -```shell -artifacts\tests\coreclr\windows.x64.Release\ilverify\ILVerificationTests.cmd -coreroot=artifacts\tests\coreclr\windows.x64.Release\Tests\Core_Root -``` - +To run tests, you can run `./dotnet[.cmd|.sh] test src/coreclr/tools/ILVerification.Tests/ILVerification.Tests.csproj` from the root of the repository. ### Defining Tests diff --git a/src/runtime/src/coreclr/tools/r2rtest/BuildFolder.cs b/src/runtime/src/coreclr/tools/r2rtest/BuildFolder.cs index d3a3da4cd84f..d65d48e99cfc 100644 --- a/src/runtime/src/coreclr/tools/r2rtest/BuildFolder.cs +++ b/src/runtime/src/coreclr/tools/r2rtest/BuildFolder.cs @@ -24,11 +24,6 @@ public class BuildFolder "mscordbi", }; - private static string[] s_runtimeWindowsOnlyLibraries = - { - "mscorrc", - }; - private List _compilationInputFiles; private List _mainExecutables; @@ -172,14 +167,7 @@ public static BuildFolder FromDirectory(string inputDirectory, IEnumerable // External prototypes. extern void* GetClrModuleBase(); -//***************************************************************************** -// Initialize -//***************************************************************************** -LPCWSTR CCompRC::m_pDefaultResource = W("mscorrc.dll"); - -HRESULT CCompRC::Init(LPCWSTR pResourceFile) -{ - CONTRACTL - { - GC_NOTRIGGER; - NOTHROW; - INJECT_FAULT(return E_OUTOFMEMORY;); - } - CONTRACTL_END; - - // This function is called during Watson process. We need to make sure - // that this function is restartable. - // - // Make sure to NEVER null out the function callbacks in the Init - // function. They get set for the "Default CCompRC" during EEStartup - // and we want to make sure we don't wipe them out. - - if (m_pResourceFile == NULL) - { - if(pResourceFile) - { - NewArrayHolder pwszResourceFile(NULL); - - DWORD lgth = (DWORD) u16_strlen(pResourceFile) + 1; - pwszResourceFile = new(nothrow) WCHAR[lgth]; - if (pwszResourceFile) - { - wcscpy_s(pwszResourceFile, lgth, pResourceFile); - LPCWSTR pFile = pwszResourceFile.Extract(); - if (InterlockedCompareExchangeT(&m_pResourceFile, pFile, NULL) != NULL) - { - delete [] pFile; - } - } - } - else - InterlockedCompareExchangeT(&m_pResourceFile, m_pDefaultResource, NULL); - } - - if (m_pResourceFile == NULL) - { - return E_OUTOFMEMORY; - } - - if (m_csMap == NULL) - { - // NOTE: there are times when the debugger's helper thread is asked to do a favor for another thread in the - // process. Typically, this favor involves putting up a dialog for the user. Putting up a dialog usually ends - // up involving the CCompRC code since (of course) the strings in the dialog are in a resource file. Thus, the - // debugger's helper thread will attempt to acquire this CRST. This is okay, since the helper thread only does - // these favors for other threads when there is no debugger attached. Thus, there are no deadlock hazards with - // this lock, and its safe for the helper thread to take, so this CRST is marked with CRST_DEBUGGER_THREAD. - CRITSEC_COOKIE csMap = ClrCreateCriticalSection(CrstCCompRC, - (CrstFlags)(CRST_UNSAFE_ANYMODE | CRST_DEBUGGER_THREAD | CRST_TAKEN_DURING_SHUTDOWN)); - - if (csMap) - { - if (InterlockedCompareExchangeT(&m_csMap, csMap, NULL) != NULL) - { - ClrDeleteCriticalSection(csMap); - } - } - } - - if (m_csMap == NULL) - return E_OUTOFMEMORY; - - return S_OK; -} - -void CCompRC::Destroy() +HRESULT CCompRC::LoadString(UINT iResourceID, _Out_writes_(iMax) LPWSTR szBuffer, int iMax, int *pcwchUsed) { - CONTRACTL - { - GC_NOTRIGGER; - NOTHROW; -#ifdef MODE_PREEMPTIVE - MODE_PREEMPTIVE; -#endif - } - CONTRACTL_END; - - // Free all resource libraries - - //***************************************************************************** - // Free the loaded library if we ever loaded it. This is done - // only in debug mode to make coverage runs accurate. - //***************************************************************************** - -#if defined(_DEBUG) - if (m_Primary.GetLibraryHandle()) { - ::FreeLibrary(m_Primary.GetLibraryHandle()); - } -#endif - - // destroy map structure - if(m_pResourceFile != m_pDefaultResource) - delete [] m_pResourceFile; - m_pResourceFile = NULL; - - if(m_csMap) { - ClrDeleteCriticalSection(m_csMap); - ZeroMemory(&(m_csMap), sizeof(CRITSEC_COOKIE)); - } -} - - -//***************************************************************************** -// Initialization is done lazily, for backwards compatibility "mscorrc.dll" -// is consider the default location for all strings that use CCompRC. -// An instance value for CCompRC can be created to load resources from a different -// resource dll. -//***************************************************************************** -LONG CCompRC::m_dwDefaultInitialized = 0; -CCompRC CCompRC::m_DefaultResourceDll; - -CCompRC* CCompRC::GetDefaultResourceDll() -{ - CONTRACTL - { - GC_NOTRIGGER; - NOTHROW; -#ifdef MODE_PREEMPTIVE - MODE_PREEMPTIVE; -#endif - } - CONTRACTL_END; - - if (m_dwDefaultInitialized) - return &m_DefaultResourceDll; - - if(FAILED(m_DefaultResourceDll.Init(NULL))) - { - return NULL; - } - m_dwDefaultInitialized = 1; - - return &m_DefaultResourceDll; -} - -//***************************************************************************** -//***************************************************************************** - -// String resources packaged as PE files only exist on Windows -#ifdef HOST_WINDOWS -HRESULT CCompRC::GetLibrary(HRESOURCEDLL* phInst) -{ - CONTRACTL - { - GC_NOTRIGGER; - NOTHROW; -#ifdef MODE_PREEMPTIVE - MODE_PREEMPTIVE; -#endif - PRECONDITION(phInst != NULL); - } - CONTRACTL_END; - - HRESULT hr = E_FAIL; - HRESOURCEDLL hInst = 0; -#ifndef DACCESS_COMPILE - HRESOURCEDLL hLibInst = 0; //Holds early library instance - BOOL fLibAlreadyOpen = FALSE; //Determine if we can close the opened library. -#endif - - // Try to match the primary entry, or else use the primary if we don't care. - if (m_Primary.IsSet()) - { - hInst = m_Primary.GetLibraryHandle(); - hr = S_OK; - } - else if(m_Primary.IsMissing()) - { - // If primary is missing then the hash will not have anything either - hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); - } -#ifndef DACCESS_COMPILE - // If this is the first visit, we must set the primary entry - else - { - // Don't immediately return if LoadLibrary fails so we can indicate the file was missing - hr = LoadLibrary(&hLibInst); - // If it's a transient failure, don't cache the failure - if (FAILED(hr) && Exception::IsTransient(hr)) - { - return hr; - } - - CRITSEC_Holder csh (m_csMap); - // As we expected - if (!m_Primary.IsSet() && !m_Primary.IsMissing()) - { - hInst = hLibInst; - if (SUCCEEDED(hr)) - { - m_Primary.Set(hLibInst); - } - else - { - m_Primary.SetMissing(); - } - } - - // Someone got into this critical section before us and set the primary already - else - { - hInst = m_Primary.GetLibraryHandle(); - fLibAlreadyOpen = TRUE; - } - - IfFailRet(hr); - - if (fLibAlreadyOpen) - { - FreeLibrary(hLibInst); - fLibAlreadyOpen = FALSE; - } - } -#endif - - _ASSERTE(SUCCEEDED(hr) || hInst == NULL); - *phInst = hInst; - return hr; -} -#endif // HOST_WINDOWS - -//***************************************************************************** -// Load the string -// We load the localized libraries and cache the handle for future use. -// Mutliple threads may call this, so the cache structure is thread safe. -//***************************************************************************** -HRESULT CCompRC::LoadString(ResourceCategory eCategory, UINT iResourceID, _Out_writes_(iMax) LPWSTR szBuffer, int iMax, int *pcwchUsed) -{ -#ifdef DBI_COMPONENT_MONO +#ifdef DACCESS_COMPILE return E_NOTIMPL; #else CONTRACTL @@ -273,30 +34,21 @@ HRESULT CCompRC::LoadString(ResourceCategory eCategory, UINT iResourceID, _Out_w #ifdef HOST_WINDOWS HRESULT hr; - HRESOURCEDLL hInst = 0; //instance of cultured resource dll int length; - hr = GetLibrary(&hInst); - - if (SUCCEEDED(hr)) + length = ::LoadString((HINSTANCE)GetClrModuleBase(), iResourceID, szBuffer, iMax); + if(length > 0) { - // Now that we have the proper dll handle, load the string - _ASSERTE(hInst != NULL); - - length = ::LoadString(hInst, iResourceID, szBuffer, iMax); - if(length > 0) + if(pcwchUsed) { - if(pcwchUsed) - { - *pcwchUsed = length; - } - return (S_OK); + *pcwchUsed = length; } - if(GetLastError()==ERROR_SUCCESS) - hr=HRESULT_FROM_WIN32(ERROR_NOT_FOUND); - else - hr=HRESULT_FROM_GetLastError(); + return (S_OK); } + if(SUCCEEDED(GetLastError())) + hr=HRESULT_FROM_WIN32(ERROR_NOT_FOUND); + else + hr=HRESULT_FROM_GetLastError(); // Return an empty string to save the people with a bad error handling if (szBuffer && iMax) @@ -309,135 +61,3 @@ HRESULT CCompRC::LoadString(ResourceCategory eCategory, UINT iResourceID, _Out_w #endif // HOST_WINDOWS #endif } - -#ifndef DACCESS_COMPILE - -// String resources packaged as PE files only exist on Windows -#ifdef HOST_WINDOWS -HRESULT CCompRC::LoadResourceFile(HRESOURCEDLL * pHInst, LPCWSTR lpFileName) -{ - DWORD dwLoadLibraryFlags; - if(m_pResourceFile == m_pDefaultResource) - { - dwLoadLibraryFlags = LOAD_LIBRARY_AS_DATAFILE; - } - else - { - dwLoadLibraryFlags = 0; - } - - if((*pHInst = WszLoadLibrary(lpFileName, NULL, dwLoadLibraryFlags)) == NULL) - { - return HRESULT_FROM_GetLastError(); - } - return S_OK; -} - -//***************************************************************************** -// Load the library from root path (\mscorrc.dll). No locale support. -//***************************************************************************** -HRESULT CCompRC::LoadLibraryHelper(HRESOURCEDLL *pHInst, - SString& rcPath) -{ - CONTRACTL - { - GC_NOTRIGGER; - NOTHROW; -#ifdef MODE_PREEMPTIVE - MODE_PREEMPTIVE; -#endif - } - CONTRACTL_END; - - HRESULT hr = E_FAIL; - - - _ASSERTE(m_pResourceFile != NULL); - - // must initialize before calling SString::Empty() - SString::Startup(); - - EX_TRY - { - PathString rcPathName(rcPath); - - if (!rcPathName.EndsWith(SL(W("\\")))) - { - rcPathName.Append(W("\\")); - } - - { - rcPathName.Append(m_pResourceFile); - } - - // Load the resource library as a data file, so that the OS doesn't have - // to allocate it as code. This only works so long as the file contains - // only strings. - hr = LoadResourceFile(pHInst, rcPathName); - } - EX_CATCH_HRESULT(hr); - - return hr; -} - -// Two-stage approach: -// First try module directory, then try CORSystemDirectory for default resource -HRESULT CCompRC::LoadLibraryThrows(HRESOURCEDLL * pHInst) -{ - CONTRACTL - { - GC_NOTRIGGER; - THROWS; -#ifdef MODE_PREEMPTIVE - MODE_PREEMPTIVE; -#endif - } - CONTRACTL_END; - - HRESULT hr = S_OK; - - _ASSERTE(pHInst != NULL); - - -#ifdef SELF_NO_HOST - _ASSERTE(!"CCompRC::LoadLibraryThrows not implemented for SELF_NO_HOST"); - hr = E_NOTIMPL; -#else // SELF_NO_HOST - PathString rcPath; // Path to resource DLL. - - // Try first in the same directory as this dll. - - hr = GetClrModuleDirectory(rcPath); - if (FAILED(hr)) - return hr; - - hr = LoadLibraryHelper(pHInst, rcPath); -#endif - - - return hr; -} - -HRESULT CCompRC::LoadLibrary(HRESOURCEDLL * pHInst) -{ - CONTRACTL - { - GC_NOTRIGGER; - NOTHROW; -#ifdef MODE_PREEMPTIVE - MODE_PREEMPTIVE; -#endif - } - CONTRACTL_END; - - HRESULT hr = S_OK; - EX_TRY - { - hr = LoadLibraryThrows(pHInst); - } - EX_CATCH_HRESULT(hr); - - return hr; -} -#endif // DACCESS_COMPILE -#endif //HOST_WINDOWS diff --git a/src/runtime/src/coreclr/utilcode/ex.cpp b/src/runtime/src/coreclr/utilcode/ex.cpp index c1db6294af76..efef912129e3 100644 --- a/src/runtime/src/coreclr/utilcode/ex.cpp +++ b/src/runtime/src/coreclr/utilcode/ex.cpp @@ -1005,7 +1005,7 @@ void DECLSPEC_NORETURN ThrowHR(HRESULT hr, UINT uText) // We won't check the return value here. If it fails, we'll just // throw the HR - sExceptionText.LoadResource(CCompRC::Error, uText); + sExceptionText.LoadResource(uText); EX_THROW(HRMsgException, (hr, sExceptionText)); } @@ -1156,7 +1156,7 @@ void GetHRMsg(HRESULT hr, SString &result, BOOL bNoGeekStuff/* = FALSE*/) if (FAILED(hr) && HRESULT_FACILITY(hr) == FACILITY_URT && HRESULT_CODE(hr) < MAX_URT_HRESULT_CODE) { - fHaveDescr = strDescr.LoadResource(CCompRC::Error, MSG_FOR_URT_HR(hr)); + fHaveDescr = strDescr.LoadResource(MSG_FOR_URT_HR(hr)); } else { diff --git a/src/runtime/src/coreclr/utilcode/posterror.cpp b/src/runtime/src/coreclr/utilcode/posterror.cpp index 3de8b3f5158e..42011a513bbe 100644 --- a/src/runtime/src/coreclr/utilcode/posterror.cpp +++ b/src/runtime/src/coreclr/utilcode/posterror.cpp @@ -23,51 +23,6 @@ // Local prototypes. HRESULT FillErrorInfo(LPCWSTR szMsg, DWORD dwHelpContext); -//***************************************************************************** -// Public function to load a resource string -//***************************************************************************** -STDAPI UtilLoadStringRC( - UINT iResourceID, - _Out_writes_(iMax) LPWSTR szBuffer, - int iMax, - int bQuiet -) -{ - WRAPPER_NO_CONTRACT; - return UtilLoadResourceString(bQuiet? CCompRC::Optional : CCompRC::Required,iResourceID, szBuffer, iMax); -} - -HRESULT UtilLoadResourceString(CCompRC::ResourceCategory eCategory, UINT iResourceID, _Out_writes_ (iMax) LPWSTR szBuffer, int iMax) -{ - CONTRACTL - { - DISABLED(NOTHROW); - GC_NOTRIGGER; - } - CONTRACTL_END; - - HRESULT retVal = E_OUTOFMEMORY; - - SString::Startup(); - EX_TRY - { - CCompRC *pResourceDLL = CCompRC::GetDefaultResourceDll(); - - if (pResourceDLL != NULL) - { - retVal = pResourceDLL->LoadString(eCategory, iResourceID, szBuffer, iMax); - } - } - EX_CATCH - { - // Catch any errors and return E_OUTOFMEMORY; - retVal = E_OUTOFMEMORY; - } - EX_END_CATCH - - return retVal; -} - //***************************************************************************** // Format a Runtime Error message. //***************************************************************************** @@ -94,7 +49,7 @@ static HRESULT FormatRuntimeErrorVA( // If this is one of our errors or if it is simply a resource ID, then grab the error from the rc file. if ((HRESULT_FACILITY(hrRpt) == FACILITY_URT) || (HIWORD(hrRpt) == 0)) { - hr = UtilLoadStringRC(LOWORD(hrRpt), rcBuf, ARRAY_SIZE(rcBuf), true); + hr = CCompRC::LoadString(LOWORD(hrRpt), rcBuf, ARRAY_SIZE(rcBuf)); if (hr == S_OK) { hr = E_OUTOFMEMORY; // Out of memory is possible diff --git a/src/runtime/src/coreclr/utilcode/sstring_com.cpp b/src/runtime/src/coreclr/utilcode/sstring_com.cpp index 855b7c0620bf..bc9c69c14810 100644 --- a/src/runtime/src/coreclr/utilcode/sstring_com.cpp +++ b/src/runtime/src/coreclr/utilcode/sstring_com.cpp @@ -15,12 +15,12 @@ //---------------------------------------------------------------------------- // Load the string resource into this string. //---------------------------------------------------------------------------- -BOOL SString::LoadResource(CCompRC::ResourceCategory eCategory, int resourceID) +BOOL SString::LoadResource(int resourceID) { - return SUCCEEDED(LoadResourceAndReturnHR(eCategory, resourceID)); + return SUCCEEDED(LoadResourceAndReturnHR(resourceID)); } -HRESULT SString::LoadResourceAndReturnHR(CCompRC::ResourceCategory eCategory, int resourceID) +HRESULT SString::LoadResourceAndReturnHR(int resourceID) { CONTRACT(HRESULT) { @@ -32,59 +32,54 @@ HRESULT SString::LoadResourceAndReturnHR(CCompRC::ResourceCategory eCategory, in HRESULT hr = E_FAIL; #ifndef FEATURE_UTILCODE_NO_DEPENDENCIES - CCompRC* pResourceDLL = CCompRC::GetDefaultResourceDll(); - if (pResourceDLL != NULL) - { + int size = 0; - int size = 0; + EX_TRY + { + if (GetRawCount() == 0) + Resize(DEFAULT_RESOURCE_STRING_SIZE, REPRESENTATION_UNICODE); - EX_TRY + while (TRUE) { - if (GetRawCount() == 0) - Resize(DEFAULT_RESOURCE_STRING_SIZE, REPRESENTATION_UNICODE); + // First try and load the string in the amount of space that we have. + // In fatal error reporting scenarios, we may not have enough memory to + // allocate a larger buffer. - while (TRUE) + hr = CCompRC::LoadString(resourceID, GetRawUnicode(), GetRawCount()+1, &size); + if (hr != HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) { - // First try and load the string in the amount of space that we have. - // In fatal error reporting scenarios, we may not have enough memory to - // allocate a larger buffer. - - hr = pResourceDLL->LoadString(eCategory, resourceID, GetRawUnicode(), GetRawCount()+1, &size); - if (hr != HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) + if (FAILED(hr)) { - if (FAILED(hr)) - { - Clear(); - break; - } - - // Although we cannot generally detect truncation, we can tell if we - // used up all the space (in which case we will assume truncation.) - if (size < (int)GetRawCount()) - { - break; - } + Clear(); + break; } - // Double the size and try again. - Resize(size*2, REPRESENTATION_UNICODE); - - } - - if (SUCCEEDED(hr)) - { - Truncate(Begin() + (COUNT_T) u16_strlen(GetRawUnicode())); + // Although we cannot generally detect truncation, we can tell if we + // used up all the space (in which case we will assume truncation.) + if (size < (int)GetRawCount()) + { + break; + } } - Normalize(); + // Double the size and try again. + Resize(size*2, REPRESENTATION_UNICODE); } - EX_CATCH + + if (SUCCEEDED(hr)) { - hr = E_FAIL; + Truncate(Begin() + (COUNT_T) u16_strlen(GetRawUnicode())); } - EX_END_CATCH + + Normalize(); + + } + EX_CATCH + { + hr = E_FAIL; } + EX_END_CATCH #endif //!FEATURE_UTILCODE_NO_DEPENDENCIES RETURN hr; diff --git a/src/runtime/src/coreclr/vm/assemblynative.cpp b/src/runtime/src/coreclr/vm/assemblynative.cpp index 26f35709a786..a962e22b5fe3 100644 --- a/src/runtime/src/coreclr/vm/assemblynative.cpp +++ b/src/runtime/src/coreclr/vm/assemblynative.cpp @@ -157,7 +157,7 @@ Assembly* AssemblyNative::LoadFromPEImage(AssemblyBinder* pBinder, PEImage *pIma // Give a more specific message for the case when we found the assembly with the same name already loaded. // Show the assembly name, since we know the error is about the assembly name. StackSString errorString; - errorString.LoadResource(CCompRC::Error, IDS_HOST_ASSEMBLY_RESOLVER_ASSEMBLY_ALREADY_LOADED_IN_CONTEXT); + errorString.LoadResource(IDS_HOST_ASSEMBLY_RESOLVER_ASSEMBLY_ALREADY_LOADED_IN_CONTEXT); COMPlusThrow(kFileLoadException, IDS_EE_FILELOAD_ERROR_GENERIC, name, errorString); } else diff --git a/src/runtime/src/coreclr/vm/callstubgenerator.h b/src/runtime/src/coreclr/vm/callstubgenerator.h index dab828a43a5a..47cc34a14c3c 100644 --- a/src/runtime/src/coreclr/vm/callstubgenerator.h +++ b/src/runtime/src/coreclr/vm/callstubgenerator.h @@ -43,7 +43,6 @@ struct CallStubHeader { LIMITED_METHOD_CONTRACT; - _ASSERTE(target != 0); VolatileStore(&Routines[NumRoutines - 1], target); } diff --git a/src/runtime/src/coreclr/vm/clrex.cpp b/src/runtime/src/coreclr/vm/clrex.cpp index d4361419d14e..ca64a95aebd3 100644 --- a/src/runtime/src/coreclr/vm/clrex.cpp +++ b/src/runtime/src/coreclr/vm/clrex.cpp @@ -1050,7 +1050,7 @@ BOOL EEException::GetResourceMessage(UINT iResourceID, SString &result, BOOL ok; StackSString temp; - ok = temp.LoadResource(CCompRC::Error, iResourceID); + ok = temp.LoadResource(iResourceID); if (ok) result.FormatMessage(FORMAT_MESSAGE_FROM_STRING, diff --git a/src/runtime/src/coreclr/vm/comutilnative.cpp b/src/runtime/src/coreclr/vm/comutilnative.cpp index 4615f23cea66..c327f21631ce 100644 --- a/src/runtime/src/coreclr/vm/comutilnative.cpp +++ b/src/runtime/src/coreclr/vm/comutilnative.cpp @@ -376,21 +376,21 @@ extern "C" void QCALLTYPE ExceptionNative_GetMessageFromNativeResources(Exceptio switch(kind) { case ExceptionMessageKind::ThreadAbort: - hr = buffer.LoadResourceAndReturnHR(CCompRC::Error, IDS_EE_THREAD_ABORT); + hr = buffer.LoadResourceAndReturnHR(IDS_EE_THREAD_ABORT); if (FAILED(hr)) { wszFallbackString = W("Thread was being aborted."); } break; case ExceptionMessageKind::ThreadInterrupted: - hr = buffer.LoadResourceAndReturnHR(CCompRC::Error, IDS_EE_THREAD_INTERRUPTED); + hr = buffer.LoadResourceAndReturnHR(IDS_EE_THREAD_INTERRUPTED); if (FAILED(hr)) { wszFallbackString = W("Thread was interrupted from a waiting state."); } break; case ExceptionMessageKind::OutOfMemory: - hr = buffer.LoadResourceAndReturnHR(CCompRC::Error, IDS_EE_OUT_OF_MEMORY); + hr = buffer.LoadResourceAndReturnHR(IDS_EE_OUT_OF_MEMORY); if (FAILED(hr)) { wszFallbackString = W("Insufficient memory to continue the execution of the program."); } diff --git a/src/runtime/src/coreclr/vm/eepolicy.cpp b/src/runtime/src/coreclr/vm/eepolicy.cpp index 9c8f1c460c90..0e22b1e39ad2 100644 --- a/src/runtime/src/coreclr/vm/eepolicy.cpp +++ b/src/runtime/src/coreclr/vm/eepolicy.cpp @@ -304,7 +304,7 @@ inline void LogCallstackForLogWorker(Thread* pThread, PEXCEPTION_POINTERS pExcep SmallStackSString WordAt; - if (!WordAt.LoadResource(CCompRC::Optional, IDS_ER_WORDAT)) + if (!WordAt.LoadResource(IDS_ER_WORDAT)) { WordAt.Set(W(" at")); } diff --git a/src/runtime/src/coreclr/vm/eventreporter.cpp b/src/runtime/src/coreclr/vm/eventreporter.cpp index 77db465e801b..6affcbb19d9e 100644 --- a/src/runtime/src/coreclr/vm/eventreporter.cpp +++ b/src/runtime/src/coreclr/vm/eventreporter.cpp @@ -49,7 +49,7 @@ EventReporter::EventReporter(EventReporterType type) InlineSString<256> ssMessage; - if(!ssMessage.LoadResource(CCompRC::Optional, IDS_ER_APPLICATION)) + if(!ssMessage.LoadResource(IDS_ER_APPLICATION)) m_Description.Append(W("Application: ")); else { @@ -68,7 +68,7 @@ EventReporter::EventReporter(EventReporterType type) else { ssMessage.Clear(); - if(!ssMessage.LoadResource(CCompRC::Optional, IDS_ER_UNKNOWN)) + if(!ssMessage.LoadResource(IDS_ER_UNKNOWN)) m_Description.Append(W("unknown\n")); else { @@ -78,7 +78,7 @@ EventReporter::EventReporter(EventReporterType type) } ssMessage.Clear(); - if(!ssMessage.LoadResource(CCompRC::Optional, IDS_ER_FRAMEWORK_VERSION)) + if(!ssMessage.LoadResource(IDS_ER_FRAMEWORK_VERSION)) m_Description.Append(W("CoreCLR Version: ")); else { @@ -96,7 +96,7 @@ EventReporter::EventReporter(EventReporterType type) switch(m_eventType) { case ERT_UnhandledException: - if(!ssMessage.LoadResource(CCompRC::Optional, IDS_ER_UNHANDLEDEXCEPTION)) + if(!ssMessage.LoadResource(IDS_ER_UNHANDLEDEXCEPTION)) m_Description.Append(W("Description: The process was terminated due to an unhandled exception.")); else { @@ -106,7 +106,7 @@ EventReporter::EventReporter(EventReporterType type) break; case ERT_ManagedFailFast: - if(!ssMessage.LoadResource(CCompRC::Optional, IDS_ER_MANAGEDFAILFAST)) + if(!ssMessage.LoadResource(IDS_ER_MANAGEDFAILFAST)) m_Description.Append(W("Description: The application requested process termination through System.Environment.FailFast.")); else { @@ -116,7 +116,7 @@ EventReporter::EventReporter(EventReporterType type) break; case ERT_UnmanagedFailFast: - if(!ssMessage.LoadResource(CCompRC::Optional, IDS_ER_UNMANAGEDFAILFAST)) + if(!ssMessage.LoadResource(IDS_ER_UNMANAGEDFAILFAST)) m_Description.Append(W("Description: The process was terminated due to an internal error in the .NET Runtime ")); else { @@ -126,7 +126,7 @@ EventReporter::EventReporter(EventReporterType type) case ERT_StackOverflow: // Fetch the localized Stack Overflow Error text or fall back on a hardcoded variant if things get dire. - if(!ssMessage.LoadResource(CCompRC::Optional, IDS_ER_STACK_OVERFLOW)) + if(!ssMessage.LoadResource(IDS_ER_STACK_OVERFLOW)) m_Description.Append(W("Description: The process was terminated due to a stack overflow.")); else { @@ -136,7 +136,7 @@ EventReporter::EventReporter(EventReporterType type) break; case ERT_CodeContractFailed: - if(!ssMessage.LoadResource(CCompRC::Optional, IDS_ER_CODECONTRACT_FAILED)) + if(!ssMessage.LoadResource(IDS_ER_CODECONTRACT_FAILED)) m_Description.Append(W("Description: The application encountered a bug. A managed code contract (precondition, postcondition, object invariant, or assert) failed.")); else { @@ -199,7 +199,7 @@ void EventReporter::AddDescription(SString& s) if (m_eventType == ERT_ManagedFailFast) { SmallStackSString ssMessage; - if(!ssMessage.LoadResource(CCompRC::Optional, IDS_ER_MANAGEDFAILFASTMSG)) + if(!ssMessage.LoadResource(IDS_ER_MANAGEDFAILFASTMSG)) m_Description.Append(W("Message: ")); else { @@ -209,7 +209,7 @@ void EventReporter::AddDescription(SString& s) else if (m_eventType == ERT_UnhandledException) { SmallStackSString ssMessage; - if (!ssMessage.LoadResource(CCompRC::Optional, IDS_ER_UNHANDLEDEXCEPTIONMSG)) + if (!ssMessage.LoadResource(IDS_ER_UNHANDLEDEXCEPTIONMSG)) { m_Description.Append(W("Exception Info: ")); } @@ -221,7 +221,7 @@ void EventReporter::AddDescription(SString& s) else if (m_eventType == ERT_CodeContractFailed) { SmallStackSString ssMessage; - if (!ssMessage.LoadResource(CCompRC::Optional, IDS_ER_CODECONTRACT_DETAILMSG)) + if (!ssMessage.LoadResource(IDS_ER_CODECONTRACT_DETAILMSG)) m_Description.Append(W("Contract details: ")); else m_Description.Append(ssMessage); @@ -251,7 +251,7 @@ void EventReporter::BeginStackTrace() CONTRACTL_END; _ASSERTE (m_eventType == ERT_UnhandledException || m_eventType == ERT_ManagedFailFast || m_eventType == ERT_CodeContractFailed); InlineSString<80> ssMessage; - if(!ssMessage.LoadResource(CCompRC::Optional, IDS_ER_STACK)) + if(!ssMessage.LoadResource(IDS_ER_STACK)) m_Description.Append(W("Stack:\n")); else { @@ -289,7 +289,7 @@ void EventReporter::AddStackTrace(SString& s) { // Load the truncation message StackSString truncate; - if (!truncate.LoadResource(CCompRC::Optional, IDS_ER_MESSAGE_TRUNCATE)) + if (!truncate.LoadResource(IDS_ER_MESSAGE_TRUNCATE)) { truncate.Set(W("The remainder of the message was truncated.")); } @@ -345,7 +345,7 @@ void EventReporter::AddFailFastStackTrace(SString& s) _ASSERTE(m_eventType == ERT_ManagedFailFast); InlineSString<80> ssMessage; - if (!ssMessage.LoadResource(CCompRC::Optional, IDS_ER_UNHANDLEDEXCEPTION)) + if (!ssMessage.LoadResource(IDS_ER_UNHANDLEDEXCEPTION)) { m_Description.Append(W("Exception stack:\n")); } @@ -546,7 +546,7 @@ void LogCallstackForEventReporterWorker(EventReporter& reporter) Thread* pThread = GetThread(); SmallStackSString WordAt; - if (!WordAt.LoadResource(CCompRC::Optional, IDS_ER_WORDAT)) + if (!WordAt.LoadResource(IDS_ER_WORDAT)) { WordAt.Set(W(" at")); } diff --git a/src/runtime/src/coreclr/vm/excep.cpp b/src/runtime/src/coreclr/vm/excep.cpp index d285f2b1f184..7b694e634a7e 100644 --- a/src/runtime/src/coreclr/vm/excep.cpp +++ b/src/runtime/src/coreclr/vm/excep.cpp @@ -4766,7 +4766,7 @@ DefaultCatchHandlerExceptionMessageWorker(Thread* pThread, GCPROTECT_BEGIN(throwable); if (throwable != NULL) { - if (FAILED(UtilLoadResourceString(CCompRC::Error, IDS_EE_UNHANDLED_EXCEPTION, buf, buf_size))) + if (FAILED(CCompRC::LoadString(IDS_EE_UNHANDLED_EXCEPTION, buf, buf_size))) { wcsncpy_s(buf, buf_size, SZ_UNHANDLED_EXCEPTION, SZ_UNHANDLED_EXCEPTION_CHARLEN); } @@ -4961,7 +4961,7 @@ DefaultCatchHandler(PEXCEPTION_POINTERS pExceptionPointers, _ASSERTE(buf_size > 6); wcscpy_s(buf, buf_size, W("\n ")); - UtilLoadStringRC(IDS_EE_EXCEPTION_TOSTRING_FAILED, buf + 4, buf_size - 6); + CCompRC::LoadString(IDS_EE_EXCEPTION_TOSTRING_FAILED, buf + 4, buf_size - 6); wcscat_s(buf, buf_size, W("\n")); PrintToStdErrW(buf); @@ -5189,12 +5189,12 @@ LONG CallOutFilter(PEXCEPTION_POINTERS pExceptionInfo, PVOID pv) // Note: This is not general purpose routine. It handles only cases found // in TypeLoadException and FileLoadException. //========================================================================== -static BOOL GetManagedFormatStringForResourceID(CCompRC::ResourceCategory eCategory, UINT32 resId, SString & converted) +static BOOL GetManagedFormatStringForResourceID(UINT32 resId, SString & converted) { STANDARD_VM_CONTRACT; StackSString temp; - if (!temp.LoadResource(eCategory, resId)) + if (!temp.LoadResource(resId)) return FALSE; SString::Iterator itr = temp.Begin(); @@ -5243,7 +5243,7 @@ extern "C" void QCALLTYPE GetTypeLoadExceptionMessage(UINT32 resId, QCall::Strin BEGIN_QCALL; StackSString format; - GetManagedFormatStringForResourceID(CCompRC::Error, resId ? resId : IDS_CLASSLOAD_GENERAL, format); + GetManagedFormatStringForResourceID(resId ? resId : IDS_CLASSLOAD_GENERAL, format); retString.Set(format); END_QCALL; @@ -5262,7 +5262,7 @@ extern "C" void QCALLTYPE GetFileLoadExceptionMessage(UINT32 hr, QCall::StringHa BEGIN_QCALL; StackSString format; - GetManagedFormatStringForResourceID(CCompRC::Error, GetResourceIDForFileLoadExceptionHR(hr), format); + GetManagedFormatStringForResourceID(GetResourceIDForFileLoadExceptionHR(hr), format); retString.Set(format); END_QCALL; @@ -10532,16 +10532,16 @@ VOID ThrowBadFormatWorker(UINT resID, LPCWSTR imageName DEBUGARG(_In_z_ const ch SString msgStr; SString resStr; - if (resID == 0 || !resStr.LoadResource(CCompRC::Optional, resID)) + if (resID == 0 || !resStr.LoadResource(resID)) { - resStr.LoadResource(CCompRC::Error, BFA_BAD_IL); // "Bad IL format." + resStr.LoadResource(BFA_BAD_IL); // "Bad IL format." } msgStr.Append(resStr); if ((imageName != NULL) && (imageName[0] != 0)) { SString suffixResStr; - if (suffixResStr.LoadResource(CCompRC::Optional, COR_E_BADIMAGEFORMAT)) // "The format of the file '%1' is invalid." + if (suffixResStr.LoadResource(COR_E_BADIMAGEFORMAT)) // "The format of the file '%1' is invalid." { SString suffixMsgStr; suffixMsgStr.FormatMessage(FORMAT_MESSAGE_FROM_STRING, (LPCWSTR)suffixResStr, 0, 0, SString{ SString::Literal, imageName }); diff --git a/src/runtime/src/coreclr/vm/interoputil.cpp b/src/runtime/src/coreclr/vm/interoputil.cpp index a8f58ead1b36..049e8854c13a 100644 --- a/src/runtime/src/coreclr/vm/interoputil.cpp +++ b/src/runtime/src/coreclr/vm/interoputil.cpp @@ -3090,19 +3090,49 @@ void IUInvokeDispMethod( } } - // // Retrieve the IDispatch interface that will be invoked on. // if (pInvokedMT->IsInterface()) { - // The invoked type is a dispatch or dual interface so we will make the - // invocation on it. - pUnk = ComObject::GetComIPFromRCWThrowing(pTarget, pInvokedMT); - hr = SafeQueryInterface(pUnk, IID_IDispatch, (IUnknown**)&pDisp); + // COMPAT: We must invoke any methods on this specific IDispatch implementation, + // as the canonical implementation (returned by QueryInterface) may not + // expose all members. + // This can occur when pTarget is a CCW for a .NET object and that object's class + // has a custom default interface (specified by the System.Runtime.InteropServices.ComDefaultInterfaceAttribute attribute). + // In that case, the default IDispatch pointer will only resolve members defined on that interface, + // not all members defined on the class. + // + // We will still do the QI here because we want to protect the user from the following scenario: + // - The user has a COM object that implements one IUnknown interface, which we'll call ICallback. + // - The user defines a managed interface (represented by pInvokedMT)to represent ICallback + // - The user incorrectly marks ICallback as "implements IDispatch and not dual". + // - The user tries to call a method on ICallback. + // + // In this case, pInvokedMT will represent the managed ICallback definition. + // The underlying COM object will not implement IDispatch. + // + // We cannot verify that the vtable of the COM object returned by pInvokedMT will have the IDispatch methods, + // but we must use that IDispatch implementation (see above). + // To catch the simple case above (where there is no IDispatch implementation at all), + // we do a QI for IDispatch and throw away the result just to make sure we don't try to invoke on an object that doesn't implement IDispatch. + // + // If the underlying COM object implements IDispatch but the COM interface represented by pInvokedMT is not dispatch or dual, + // we will not correctly detect that the user did something wrong and will crash. + // This is a known issue with no solution. + // Our check here is best effort to catch the simple case where a user may make a mistake. + SafeComHolder pInvokedMTUnknown = ComObject::GetComIPFromRCWThrowing(pTarget, pInvokedMT); + + // QI for IDispatch to catch the simple error case (COM object has no IDispatch but pInvokedMT is specified as a dispatch or dual interface) + SafeComHolder pCanonicalDisp; + hr = SafeQueryInterface(pInvokedMTUnknown, IID_IDispatch, &pCanonicalDisp); if (FAILED(hr)) COMPlusThrow(kTargetException, W("TargetInvocation_TargetDoesNotImplementIDispatch")); + + _ASSERTE(IsDispatchBasedItf(pInvokedMT->GetComInterfaceType())); + // Extract the IDispatch pointer that is associated with pInvokedMT specifically. + pDisp = (IDispatch*)pInvokedMTUnknown.Extract(); } else { diff --git a/src/runtime/src/coreclr/vm/interpexec.cpp b/src/runtime/src/coreclr/vm/interpexec.cpp index 4f5a9c401f15..9e26575fda40 100644 --- a/src/runtime/src/coreclr/vm/interpexec.cpp +++ b/src/runtime/src/coreclr/vm/interpexec.cpp @@ -274,7 +274,7 @@ void InvokeDelegateInvokeMethod(MethodDesc *pMDDelegateInvoke, int8_t *pArgs, in CallStubHeader *stubHeaderTemplate = pMDDelegateInvoke->GetCallStub(); if (stubHeaderTemplate == NULL) { - stubHeaderTemplate = UpdateCallStubForMethod(pMDDelegateInvoke, (PCODE)NULL); + stubHeaderTemplate = UpdateCallStubForMethod(pMDDelegateInvoke, (PCODE)pMDDelegateInvoke->GetMultiCallableAddrOfCode(CORINFO_ACCESS_ANY)); } // CallStubHeaders encode their destination addresses in the Routines array, so they need to be @@ -841,6 +841,31 @@ void AsyncHelpers_ResumeInterpreterContinuation(QCall::ObjectHandleOnStack cont, END_QCALL; } +static void DECLSPEC_NORETURN HandleInterpreterStackOverflow(InterpreterFrame* pInterpreterFrame) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + MODE_COOPERATIVE; + } + CONTRACTL_END + + CONTEXT ctx; + memset(&ctx, 0, sizeof(CONTEXT)); + pInterpreterFrame->SetIsFaulting(true); + pInterpreterFrame->SetContextToInterpMethodContextFrame(&ctx); + + EXCEPTION_RECORD exceptionRecord; + memset(&exceptionRecord, 0, sizeof(EXCEPTION_RECORD)); + exceptionRecord.ExceptionCode = STATUS_STACK_OVERFLOW; + exceptionRecord.ExceptionAddress = (PVOID)GetIP(&ctx); + + EXCEPTION_POINTERS exceptionInfo = { &exceptionRecord, &ctx }; + EEPolicy::HandleFatalStackOverflow(&exceptionInfo); +} + + void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFrame *pFrame, InterpThreadContext *pThreadContext, ExceptionClauseArgs *pExceptionClauseArgs) { CONTRACTL @@ -860,15 +885,28 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr InterpMethod *pMethod = pFrame->startIp->Method; _ASSERTE(pMethod->CheckIntegrity()); - pThreadContext->pStackPointer = pFrame->pStack + pMethod->allocaSize; - stack = pFrame->pStack; - if (pExceptionClauseArgs == NULL) { // Start executing at the beginning of the method ip = pFrame->startIp->GetByteCodes(); } else + { + // Start executing at the beginning of the exception clause + ip = pExceptionClauseArgs->ip; + } + + if (pFrame->pStack + pMethod->allocaSize > pThreadContext->pStackEnd) + { + pFrame->ip = ip; + HandleInterpreterStackOverflow(pInterpreterFrame); + UNREACHABLE(); + } + + pThreadContext->pStackPointer = pFrame->pStack + pMethod->allocaSize; + stack = pFrame->pStack; + + if ((pExceptionClauseArgs != NULL) && pExceptionClauseArgs->isFilter) { // * Filter funclets are executed in the current frame, because they are executed // in the first pass of EH when the frames between the current frame and the @@ -876,15 +914,9 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr // in this case use the pExceptionClauseArgs->pFrame->pStack as a frame pointer. // * Catch and finally funclets are running in the parent frame directly - if (pExceptionClauseArgs->isFilter) - { - // Since filters run in their own frame, we need to clear the global variables - // so that GC doesn't pick garbage in variables that were not yet written to. - memset(pFrame->pStack, 0, pMethod->allocaSize); - } - - // Start executing at the beginning of the exception clause - ip = pExceptionClauseArgs->ip; + // Since filters run in their own frame, we need to clear the global variables + // so that GC doesn't pick garbage in variables that were not yet written to. + memset(pFrame->pStack, 0, pMethod->allocaSize); } int32_t returnOffset, callArgsOffset, methodSlot; @@ -2908,6 +2940,13 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr _ASSERTE(pMethod->CheckIntegrity()); stack = pFrame->pStack; ip = pFrame->startIp->GetByteCodes(); + + if (stack + pMethod->allocaSize > pThreadContext->pStackEnd) + { + pFrame->ip = ip; + HandleInterpreterStackOverflow(pInterpreterFrame); + UNREACHABLE(); + } pThreadContext->pStackPointer = stack + pMethod->allocaSize; break; } @@ -4091,6 +4130,7 @@ do \ stack = pFrame->pStack; pMethod = pFrame->startIp->Method; _ASSERTE(pMethod->CheckIntegrity()); + pThreadContext->pStackPointer = pFrame->pStack + pMethod->allocaSize; pInterpreterFrame->SetIsFaulting(false); diff --git a/src/runtime/src/coreclr/vm/mlinfo.cpp b/src/runtime/src/coreclr/vm/mlinfo.cpp index 780125df3d25..6b231803d580 100644 --- a/src/runtime/src/coreclr/vm/mlinfo.cpp +++ b/src/runtime/src/coreclr/vm/mlinfo.cpp @@ -331,7 +331,7 @@ VOID ThrowInteropParamException(UINT resID, UINT paramIdx) paramString.Printf("parameter #%u", paramIdx); SString errorString(W("Unknown error.")); - errorString.LoadResource(CCompRC::Error, resID); + errorString.LoadResource(resID); COMPlusThrow(kMarshalDirectiveException, IDS_EE_BADMARSHAL_ERROR_MSG, paramString.GetUnicode(), errorString.GetUnicode()); } @@ -2107,7 +2107,7 @@ void MarshalInfo::ThrowTypeLoadExceptionForInvalidFieldMarshal(FieldDesc* pField StackSString ssFieldName(SString::Utf8, pFieldDesc->GetName()); StackSString errorString(W("Unknown error.")); - errorString.LoadResource(CCompRC::Error, resID); + errorString.LoadResource(resID); COMPlusThrow(kTypeLoadException, IDS_EE_BADMARSHALFIELD_ERROR_MSG, GetFullyQualifiedNameForClassW(pFieldDesc->GetEnclosingMethodTable()), diff --git a/src/runtime/src/coreclr/vm/profilinghelper.cpp b/src/runtime/src/coreclr/vm/profilinghelper.cpp index ccf23ed65ef1..4bee4177dbf5 100644 --- a/src/runtime/src/coreclr/vm/profilinghelper.cpp +++ b/src/runtime/src/coreclr/vm/profilinghelper.cpp @@ -250,7 +250,6 @@ void ProfilingAPIUtility::AppendSupplementaryInformation(int iStringResource, SS StackSString supplementaryInformation; if (!supplementaryInformation.LoadResource( - CCompRC::Debugging, IDS_PROF_SUPPLEMENTARY_INFO )) { @@ -302,7 +301,6 @@ void ProfilingAPIUtility::LogProfEventVA( StackSString messageFromResource; if (!messageFromResource.LoadResource( - CCompRC::Debugging, iStringResourceID )) { diff --git a/src/runtime/src/coreclr/vm/qcallentrypoints.cpp b/src/runtime/src/coreclr/vm/qcallentrypoints.cpp index 0adc704306eb..960b68ef921f 100644 --- a/src/runtime/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/runtime/src/coreclr/vm/qcallentrypoints.cpp @@ -162,6 +162,7 @@ static const Entry s_QCall[] = DllImportEntry(RuntimeTypeHandle_InternalAlloc) DllImportEntry(RuntimeTypeHandle_InternalAllocNoChecks) DllImportEntry(RuntimeTypeHandle_AllocateTypeAssociatedMemory) + DllImportEntry(RuntimeTypeHandle_AllocateTypeAssociatedMemoryAligned) DllImportEntry(RuntimeTypeHandle_RegisterCollectibleTypeDependency) DllImportEntry(MethodBase_GetCurrentMethod) DllImportEntry(RuntimeMethodHandle_InvokeMethod) diff --git a/src/runtime/src/coreclr/vm/runtimehandles.cpp b/src/runtime/src/coreclr/vm/runtimehandles.cpp index a6e8b8660115..cd76192d29db 100644 --- a/src/runtime/src/coreclr/vm/runtimehandles.cpp +++ b/src/runtime/src/coreclr/vm/runtimehandles.cpp @@ -1233,6 +1233,32 @@ extern "C" void* QCALLTYPE RuntimeTypeHandle_AllocateTypeAssociatedMemory(QCall: return allocatedMemory; } +extern "C" void* QCALLTYPE RuntimeTypeHandle_AllocateTypeAssociatedMemoryAligned(QCall::TypeHandle type, uint32_t size, uint32_t alignment) +{ + QCALL_CONTRACT; + + void *allocatedMemory = nullptr; + + BEGIN_QCALL; + + TypeHandle typeHandle = type.AsTypeHandle(); + _ASSERTE(!typeHandle.IsNull()); + + _ASSERTE(alignment != 0); + _ASSERTE(0 == (alignment & (alignment - 1))); // require power of 2 + + // Get the loader allocator for the associated type. + // Allocating using the type's associated loader allocator means + // that the memory will be freed when the type is unloaded. + PTR_LoaderAllocator loaderAllocator = typeHandle.GetMethodTable()->GetLoaderAllocator(); + LoaderHeap* loaderHeap = loaderAllocator->GetHighFrequencyHeap(); + allocatedMemory = loaderHeap->AllocAlignedMem(size, alignment); + + END_QCALL; + + return allocatedMemory; +} + extern "C" void QCALLTYPE RuntimeTypeHandle_RegisterCollectibleTypeDependency(QCall::TypeHandle pTypeHandle, QCall::AssemblyHandle pAssembly) { QCALL_CONTRACT; diff --git a/src/runtime/src/coreclr/vm/runtimehandles.h b/src/runtime/src/coreclr/vm/runtimehandles.h index 7d155046577d..fb3bbf2b475c 100644 --- a/src/runtime/src/coreclr/vm/runtimehandles.h +++ b/src/runtime/src/coreclr/vm/runtimehandles.h @@ -141,6 +141,7 @@ extern "C" void QCALLTYPE RuntimeTypeHandle_InternalAlloc(MethodTable* pMT, QCal extern "C" void QCALLTYPE RuntimeTypeHandle_InternalAllocNoChecks(MethodTable* pMT, QCall::ObjectHandleOnStack allocated); extern "C" void* QCALLTYPE RuntimeTypeHandle_AllocateTypeAssociatedMemory(QCall::TypeHandle type, uint32_t size); +extern "C" void* QCALLTYPE RuntimeTypeHandle_AllocateTypeAssociatedMemoryAligned(QCall::TypeHandle type, uint32_t size, uint32_t alignment); extern "C" PVOID QCALLTYPE QCall_GetGCHandleForTypeHandle(QCall::TypeHandle pTypeHandle, INT32 handleType); extern "C" void QCALLTYPE QCall_FreeGCHandleForTypeHandle(QCall::TypeHandle pTypeHandle, OBJECTHANDLE objHandle); diff --git a/src/runtime/src/coreclr/vm/stackwalk.cpp b/src/runtime/src/coreclr/vm/stackwalk.cpp index ae469f698ae7..d7bd9429af33 100644 --- a/src/runtime/src/coreclr/vm/stackwalk.cpp +++ b/src/runtime/src/coreclr/vm/stackwalk.cpp @@ -716,11 +716,35 @@ UINT_PTR Thread::VirtualUnwindToFirstManagedCallFrame(T_CONTEXT* pContext) CONTRACTL_END; PCODE uControlPc = GetIP(pContext); + Thread *pThread = GetThread(); + +#ifdef FEATURE_INTERPRETER + Frame *pFrame = pThread->GetFrame(); + while (pFrame != FRAME_TOP && (pFrame->GetFrameIdentifier() != FrameIdentifier::InterpreterFrame)) + { + pFrame = pFrame->PtrNextFrame(); + } + InterpreterFrame *pInterpreterFrame = (pFrame != FRAME_TOP) ? (InterpreterFrame *)pFrame : NULL; +#endif // FEATURE_INTERPRETER // unwind out of this function and out of our caller to // get our caller's PSP, or our caller's caller's SP. while (!ExecutionManager::IsManagedCode(uControlPc)) { +#ifdef FEATURE_INTERPRETER + // Check if we are past the topmost interpreter frame + if ((pInterpreterFrame != NULL) && (GetSP(pContext) > (TADDR)pFrame)) + { + InterpMethodContextFrame *pInterpMethodContextFrame = pInterpreterFrame->GetTopInterpMethodContextFrame(); + if (pInterpMethodContextFrame != NULL) + { + pInterpreterFrame->SetContextToInterpMethodContextFrame(pContext); + uControlPc = GetIP(pContext); + break; + } + } +#endif // FEATURE_INTERPRETER + if (IsIPInWriteBarrierCodeCopy(uControlPc)) { // Pretend we were executing the barrier function at its original location so that the unwinder can unwind the frame diff --git a/src/runtime/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp b/src/runtime/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp index 1e1a0ababe75..91cd17b5a2de 100644 --- a/src/runtime/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp +++ b/src/runtime/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp @@ -638,7 +638,6 @@ const StringToWasmSigThunk g_wasmThunks[] = { { "viiinni", (void*)&CallFunc_I32_I32_I32_IND_IND_I32_RetVoid }, { "viin", (void*)&CallFunc_I32_I32_IND_RetVoid }, { "viinni", (void*)&CallFunc_I32_I32_IND_IND_I32_RetVoid }, - { "viin", (void*)&CallFunc_I32_I32_IND_RetVoid }, { "viinnii", (void*)&CallFunc_I32_I32_IND_IND_I32_I32_RetVoid }, { "vin", (void*)&CallFunc_I32_IND_RetVoid }, { "vini", (void*)&CallFunc_I32_IND_I32_RetVoid }, diff --git a/src/runtime/src/coreclr/vm/wasm/callhelpers-reverse.cpp b/src/runtime/src/coreclr/vm/wasm/callhelpers-reverse.cpp index 478c5fec794c..8e769acfae0d 100644 --- a/src/runtime/src/coreclr/vm/wasm/callhelpers-reverse.cpp +++ b/src/runtime/src/coreclr/vm/wasm/callhelpers-reverse.cpp @@ -2,69 +2,249 @@ // The .NET Foundation licenses this file to you under the MIT license. // -#include - -// Define reverse thunks here +// +// GENERATED FILE, DON'T EDIT +// Generated by coreclr InterpToNativeGenerator +// -// Entry point for interpreted method execution from unmanaged code -class MethodDesc; +#include // WASM-TODO: The method lookup would ideally be fully qualified assembly and then methodDef token. // The current approach has limitations with overloaded methods. extern "C" void LookupMethodByName(const char* fullQualifiedTypeName, const char* methodName, MethodDesc** ppMD); extern "C" void ExecuteInterpretedMethodFromUnmanaged(MethodDesc* pMD, int8_t* args, size_t argSize, int8_t* ret, PCODE callerIp); +static MethodDesc* MD_System_Private_CoreLib_System_GC__RegisterNoGCRegionCallback_g__Callback_7C_72_0_I32_RetVoid = nullptr; +static void Call_System_Private_CoreLib_System_GC__RegisterNoGCRegionCallback_g__Callback_7C_72_0_I32_RetVoid(void * arg0) +{ + int64_t args[1] = { (int64_t)arg0 }; + + // Lazy lookup of MethodDesc for the function export scenario. + if (!MD_System_Private_CoreLib_System_GC__RegisterNoGCRegionCallback_g__Callback_7C_72_0_I32_RetVoid) + { + LookupMethodByName("System.GC, System.Private.CoreLib", "g__Callback|72_0", &MD_System_Private_CoreLib_System_GC__RegisterNoGCRegionCallback_g__Callback_7C_72_0_I32_RetVoid); + } + ExecuteInterpretedMethodFromUnmanaged(MD_System_Private_CoreLib_System_GC__RegisterNoGCRegionCallback_g__Callback_7C_72_0_I32_RetVoid, (int8_t*)args, sizeof(args), nullptr, (PCODE)&Call_System_Private_CoreLib_System_GC__RegisterNoGCRegionCallback_g__Callback_7C_72_0_I32_RetVoid); +} + static MethodDesc* MD_System_Private_CoreLib_System_Threading_ThreadPool_BackgroundJobHandler_Void_RetVoid = nullptr; -static void Call_System_Private_CoreLib_System_Threading_ThreadPool_BackgroundJobHandler() +static void Call_System_Private_CoreLib_System_Threading_ThreadPool_BackgroundJobHandler_Void_RetVoid() { // Lazy lookup of MethodDesc for the function export scenario. if (!MD_System_Private_CoreLib_System_Threading_ThreadPool_BackgroundJobHandler_Void_RetVoid) { LookupMethodByName("System.Threading.ThreadPool, System.Private.CoreLib", "BackgroundJobHandler", &MD_System_Private_CoreLib_System_Threading_ThreadPool_BackgroundJobHandler_Void_RetVoid); } - ExecuteInterpretedMethodFromUnmanaged(MD_System_Private_CoreLib_System_Threading_ThreadPool_BackgroundJobHandler_Void_RetVoid, nullptr, 0, nullptr, (PCODE)&Call_System_Private_CoreLib_System_Threading_ThreadPool_BackgroundJobHandler); + ExecuteInterpretedMethodFromUnmanaged(MD_System_Private_CoreLib_System_Threading_ThreadPool_BackgroundJobHandler_Void_RetVoid, nullptr, 0, nullptr, (PCODE)&Call_System_Private_CoreLib_System_Threading_ThreadPool_BackgroundJobHandler_Void_RetVoid); } extern "C" void SystemJS_ExecuteBackgroundJobCallback() { - Call_System_Private_CoreLib_System_Threading_ThreadPool_BackgroundJobHandler(); + Call_System_Private_CoreLib_System_Threading_ThreadPool_BackgroundJobHandler_Void_RetVoid(); +} + +static MethodDesc* MD_System_Private_CoreLib_System_GC_ConfigCallback_I32_I32_I32_I32_I64_RetVoid = nullptr; +static void Call_System_Private_CoreLib_System_GC_ConfigCallback_I32_I32_I32_I32_I64_RetVoid(void * arg0, void * arg1, void * arg2, int32_t arg3, int64_t arg4) +{ + int64_t args[5] = { (int64_t)arg0, (int64_t)arg1, (int64_t)arg2, (int64_t)arg3, (int64_t)arg4 }; + + // Lazy lookup of MethodDesc for the function export scenario. + if (!MD_System_Private_CoreLib_System_GC_ConfigCallback_I32_I32_I32_I32_I64_RetVoid) + { + LookupMethodByName("System.GC, System.Private.CoreLib", "ConfigCallback", &MD_System_Private_CoreLib_System_GC_ConfigCallback_I32_I32_I32_I32_I64_RetVoid); + } + ExecuteInterpretedMethodFromUnmanaged(MD_System_Private_CoreLib_System_GC_ConfigCallback_I32_I32_I32_I32_I64_RetVoid, (int8_t*)args, sizeof(args), nullptr, (PCODE)&Call_System_Private_CoreLib_System_GC_ConfigCallback_I32_I32_I32_I32_I64_RetVoid); +} + +static MethodDesc* MD_System_Private_CoreLib_System_Globalization_CalendarData_EnumCalendarInfoCallback_I32_I32_RetVoid = nullptr; +static void Call_System_Private_CoreLib_System_Globalization_CalendarData_EnumCalendarInfoCallback_I32_I32_RetVoid(void * arg0, void * arg1) +{ + int64_t args[2] = { (int64_t)arg0, (int64_t)arg1 }; + + // Lazy lookup of MethodDesc for the function export scenario. + if (!MD_System_Private_CoreLib_System_Globalization_CalendarData_EnumCalendarInfoCallback_I32_I32_RetVoid) + { + LookupMethodByName("System.Globalization.CalendarData, System.Private.CoreLib", "EnumCalendarInfoCallback", &MD_System_Private_CoreLib_System_Globalization_CalendarData_EnumCalendarInfoCallback_I32_I32_RetVoid); + } + ExecuteInterpretedMethodFromUnmanaged(MD_System_Private_CoreLib_System_Globalization_CalendarData_EnumCalendarInfoCallback_I32_I32_RetVoid, (int8_t*)args, sizeof(args), nullptr, (PCODE)&Call_System_Private_CoreLib_System_Globalization_CalendarData_EnumCalendarInfoCallback_I32_I32_RetVoid); +} + +static MethodDesc* MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComActivator_GetClassFactoryForTypeInternal_I32_RetI32 = nullptr; +static int32_t Call_System_Private_CoreLib_Internal_Runtime_InteropServices_ComActivator_GetClassFactoryForTypeInternal_I32_RetI32(void * arg0) +{ + int64_t args[1] = { (int64_t)arg0 }; + + // Lazy lookup of MethodDesc for the function export scenario. + if (!MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComActivator_GetClassFactoryForTypeInternal_I32_RetI32) + { + LookupMethodByName("Internal.Runtime.InteropServices.ComActivator, System.Private.CoreLib", "GetClassFactoryForTypeInternal", &MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComActivator_GetClassFactoryForTypeInternal_I32_RetI32); + } + + int32_t result; + ExecuteInterpretedMethodFromUnmanaged(MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComActivator_GetClassFactoryForTypeInternal_I32_RetI32, (int8_t*)args, sizeof(args), (int8_t*)&result, (PCODE)&Call_System_Private_CoreLib_Internal_Runtime_InteropServices_ComActivator_GetClassFactoryForTypeInternal_I32_RetI32); + return result; +} + +static MethodDesc* MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_GetFunctionPointer_I32_I32_I32_I32_I32_I32_RetI32 = nullptr; +static int32_t Call_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_GetFunctionPointer_I32_I32_I32_I32_I32_I32_RetI32(void * arg0, void * arg1, void * arg2, void * arg3, void * arg4, void * arg5) +{ + int64_t args[6] = { (int64_t)arg0, (int64_t)arg1, (int64_t)arg2, (int64_t)arg3, (int64_t)arg4, (int64_t)arg5 }; + + // Lazy lookup of MethodDesc for the function export scenario. + if (!MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_GetFunctionPointer_I32_I32_I32_I32_I32_I32_RetI32) + { + LookupMethodByName("Internal.Runtime.InteropServices.ComponentActivator, System.Private.CoreLib", "GetFunctionPointer", &MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_GetFunctionPointer_I32_I32_I32_I32_I32_I32_RetI32); + } + + int32_t result; + ExecuteInterpretedMethodFromUnmanaged(MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_GetFunctionPointer_I32_I32_I32_I32_I32_I32_RetI32, (int8_t*)args, sizeof(args), (int8_t*)&result, (PCODE)&Call_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_GetFunctionPointer_I32_I32_I32_I32_I32_I32_RetI32); + return result; +} + +static MethodDesc* MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_LoadAssembly_I32_I32_I32_RetI32 = nullptr; +static int32_t Call_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_LoadAssembly_I32_I32_I32_RetI32(void * arg0, void * arg1, void * arg2) +{ + int64_t args[3] = { (int64_t)arg0, (int64_t)arg1, (int64_t)arg2 }; + + // Lazy lookup of MethodDesc for the function export scenario. + if (!MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_LoadAssembly_I32_I32_I32_RetI32) + { + LookupMethodByName("Internal.Runtime.InteropServices.ComponentActivator, System.Private.CoreLib", "LoadAssembly", &MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_LoadAssembly_I32_I32_I32_RetI32); + } + + int32_t result; + ExecuteInterpretedMethodFromUnmanaged(MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_LoadAssembly_I32_I32_I32_RetI32, (int8_t*)args, sizeof(args), (int8_t*)&result, (PCODE)&Call_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_LoadAssembly_I32_I32_I32_RetI32); + return result; +} + +static MethodDesc* MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_LoadAssemblyAndGetFunctionPointer_I32_I32_I32_I32_I32_I32_RetI32 = nullptr; +static int32_t Call_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_LoadAssemblyAndGetFunctionPointer_I32_I32_I32_I32_I32_I32_RetI32(void * arg0, void * arg1, void * arg2, void * arg3, void * arg4, void * arg5) +{ + int64_t args[6] = { (int64_t)arg0, (int64_t)arg1, (int64_t)arg2, (int64_t)arg3, (int64_t)arg4, (int64_t)arg5 }; + + // Lazy lookup of MethodDesc for the function export scenario. + if (!MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_LoadAssemblyAndGetFunctionPointer_I32_I32_I32_I32_I32_I32_RetI32) + { + LookupMethodByName("Internal.Runtime.InteropServices.ComponentActivator, System.Private.CoreLib", "LoadAssemblyAndGetFunctionPointer", &MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_LoadAssemblyAndGetFunctionPointer_I32_I32_I32_I32_I32_I32_RetI32); + } + + int32_t result; + ExecuteInterpretedMethodFromUnmanaged(MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_LoadAssemblyAndGetFunctionPointer_I32_I32_I32_I32_I32_I32_RetI32, (int8_t*)args, sizeof(args), (int8_t*)&result, (PCODE)&Call_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_LoadAssemblyAndGetFunctionPointer_I32_I32_I32_I32_I32_I32_RetI32); + return result; +} + +static MethodDesc* MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_LoadAssemblyBytes_I32_I32_I32_I32_I32_I32_RetI32 = nullptr; +static int32_t Call_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_LoadAssemblyBytes_I32_I32_I32_I32_I32_I32_RetI32(void * arg0, void * arg1, void * arg2, void * arg3, void * arg4, void * arg5) +{ + int64_t args[6] = { (int64_t)arg0, (int64_t)arg1, (int64_t)arg2, (int64_t)arg3, (int64_t)arg4, (int64_t)arg5 }; + + // Lazy lookup of MethodDesc for the function export scenario. + if (!MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_LoadAssemblyBytes_I32_I32_I32_I32_I32_I32_RetI32) + { + LookupMethodByName("Internal.Runtime.InteropServices.ComponentActivator, System.Private.CoreLib", "LoadAssemblyBytes", &MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_LoadAssemblyBytes_I32_I32_I32_I32_I32_I32_RetI32); + } + + int32_t result; + ExecuteInterpretedMethodFromUnmanaged(MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_LoadAssemblyBytes_I32_I32_I32_I32_I32_I32_RetI32, (int8_t*)args, sizeof(args), (int8_t*)&result, (PCODE)&Call_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_LoadAssemblyBytes_I32_I32_I32_I32_I32_I32_RetI32); + return result; +} + +static MethodDesc* MD_System_Private_CoreLib_System_Runtime_InteropServices_TypeMapLazyDictionary_NewExternalTypeEntry_I32_I32_RetI32 = nullptr; +static int32_t Call_System_Private_CoreLib_System_Runtime_InteropServices_TypeMapLazyDictionary_NewExternalTypeEntry_I32_I32_RetI32(void * arg0, void * arg1) +{ + int64_t args[2] = { (int64_t)arg0, (int64_t)arg1 }; + + // Lazy lookup of MethodDesc for the function export scenario. + if (!MD_System_Private_CoreLib_System_Runtime_InteropServices_TypeMapLazyDictionary_NewExternalTypeEntry_I32_I32_RetI32) + { + LookupMethodByName("System.Runtime.InteropServices.TypeMapLazyDictionary, System.Private.CoreLib", "NewExternalTypeEntry", &MD_System_Private_CoreLib_System_Runtime_InteropServices_TypeMapLazyDictionary_NewExternalTypeEntry_I32_I32_RetI32); + } + + int32_t result; + ExecuteInterpretedMethodFromUnmanaged(MD_System_Private_CoreLib_System_Runtime_InteropServices_TypeMapLazyDictionary_NewExternalTypeEntry_I32_I32_RetI32, (int8_t*)args, sizeof(args), (int8_t*)&result, (PCODE)&Call_System_Private_CoreLib_System_Runtime_InteropServices_TypeMapLazyDictionary_NewExternalTypeEntry_I32_I32_RetI32); + return result; +} + +static MethodDesc* MD_System_Private_CoreLib_System_Runtime_InteropServices_TypeMapLazyDictionary_NewProxyTypeEntry_I32_I32_RetI32 = nullptr; +static int32_t Call_System_Private_CoreLib_System_Runtime_InteropServices_TypeMapLazyDictionary_NewProxyTypeEntry_I32_I32_RetI32(void * arg0, void * arg1) +{ + int64_t args[2] = { (int64_t)arg0, (int64_t)arg1 }; + + // Lazy lookup of MethodDesc for the function export scenario. + if (!MD_System_Private_CoreLib_System_Runtime_InteropServices_TypeMapLazyDictionary_NewProxyTypeEntry_I32_I32_RetI32) + { + LookupMethodByName("System.Runtime.InteropServices.TypeMapLazyDictionary, System.Private.CoreLib", "NewProxyTypeEntry", &MD_System_Private_CoreLib_System_Runtime_InteropServices_TypeMapLazyDictionary_NewProxyTypeEntry_I32_I32_RetI32); + } + + int32_t result; + ExecuteInterpretedMethodFromUnmanaged(MD_System_Private_CoreLib_System_Runtime_InteropServices_TypeMapLazyDictionary_NewProxyTypeEntry_I32_I32_RetI32, (int8_t*)args, sizeof(args), (int8_t*)&result, (PCODE)&Call_System_Private_CoreLib_System_Runtime_InteropServices_TypeMapLazyDictionary_NewProxyTypeEntry_I32_I32_RetI32); + return result; +} + +static MethodDesc* MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComActivator_RegisterClassForTypeInternal_I32_RetI32 = nullptr; +static int32_t Call_System_Private_CoreLib_Internal_Runtime_InteropServices_ComActivator_RegisterClassForTypeInternal_I32_RetI32(void * arg0) +{ + int64_t args[1] = { (int64_t)arg0 }; + + // Lazy lookup of MethodDesc for the function export scenario. + if (!MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComActivator_RegisterClassForTypeInternal_I32_RetI32) + { + LookupMethodByName("Internal.Runtime.InteropServices.ComActivator, System.Private.CoreLib", "RegisterClassForTypeInternal", &MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComActivator_RegisterClassForTypeInternal_I32_RetI32); + } + + int32_t result; + ExecuteInterpretedMethodFromUnmanaged(MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComActivator_RegisterClassForTypeInternal_I32_RetI32, (int8_t*)args, sizeof(args), (int8_t*)&result, (PCODE)&Call_System_Private_CoreLib_Internal_Runtime_InteropServices_ComActivator_RegisterClassForTypeInternal_I32_RetI32); + return result; } static MethodDesc* MD_System_Private_CoreLib_System_Threading_TimerQueue_TimerHandler_Void_RetVoid = nullptr; -static void Call_System_Private_CoreLib_System_Threading_TimerQueue_TimerHandler() +static void Call_System_Private_CoreLib_System_Threading_TimerQueue_TimerHandler_Void_RetVoid() { // Lazy lookup of MethodDesc for the function export scenario. if (!MD_System_Private_CoreLib_System_Threading_TimerQueue_TimerHandler_Void_RetVoid) { LookupMethodByName("System.Threading.TimerQueue, System.Private.CoreLib", "TimerHandler", &MD_System_Private_CoreLib_System_Threading_TimerQueue_TimerHandler_Void_RetVoid); } - ExecuteInterpretedMethodFromUnmanaged(MD_System_Private_CoreLib_System_Threading_TimerQueue_TimerHandler_Void_RetVoid, nullptr, 0, nullptr, (PCODE)&Call_System_Private_CoreLib_System_Threading_TimerQueue_TimerHandler); + ExecuteInterpretedMethodFromUnmanaged(MD_System_Private_CoreLib_System_Threading_TimerQueue_TimerHandler_Void_RetVoid, nullptr, 0, nullptr, (PCODE)&Call_System_Private_CoreLib_System_Threading_TimerQueue_TimerHandler_Void_RetVoid); } extern "C" void SystemJS_ExecuteTimerCallback() { - Call_System_Private_CoreLib_System_Threading_TimerQueue_TimerHandler(); + Call_System_Private_CoreLib_System_Threading_TimerQueue_TimerHandler_Void_RetVoid(); } -static MethodDesc* MD_CalendarData_EnumCalendarInfoCallback = nullptr; -extern "C" void Call_CalendarData_EnumCalendarInfoCallback(void* arg0, void* arg1) +static MethodDesc* MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComActivator_UnregisterClassForTypeInternal_I32_RetI32 = nullptr; +static int32_t Call_System_Private_CoreLib_Internal_Runtime_InteropServices_ComActivator_UnregisterClassForTypeInternal_I32_RetI32(void * arg0) { + int64_t args[1] = { (int64_t)arg0 }; + // Lazy lookup of MethodDesc for the function export scenario. - if (!MD_CalendarData_EnumCalendarInfoCallback) + if (!MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComActivator_UnregisterClassForTypeInternal_I32_RetI32) { - LookupMethodByName("System.Globalization.CalendarData, System.Private.CoreLib", "EnumCalendarInfoCallback", &MD_CalendarData_EnumCalendarInfoCallback); + LookupMethodByName("Internal.Runtime.InteropServices.ComActivator, System.Private.CoreLib", "UnregisterClassForTypeInternal", &MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComActivator_UnregisterClassForTypeInternal_I32_RetI32); } - int64_t args[2] = { (int64_t)arg0, (int64_t)arg1 }; - - ExecuteInterpretedMethodFromUnmanaged(MD_CalendarData_EnumCalendarInfoCallback, (int8_t*)args, sizeof(args), nullptr, (PCODE)&Call_CalendarData_EnumCalendarInfoCallback); + int32_t result; + ExecuteInterpretedMethodFromUnmanaged(MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComActivator_UnregisterClassForTypeInternal_I32_RetI32, (int8_t*)args, sizeof(args), (int8_t*)&result, (PCODE)&Call_System_Private_CoreLib_Internal_Runtime_InteropServices_ComActivator_UnregisterClassForTypeInternal_I32_RetI32); + return result; } extern const ReverseThunkMapEntry g_ReverseThunks[] = { - { 100678287, { &MD_System_Private_CoreLib_System_Threading_ThreadPool_BackgroundJobHandler_Void_RetVoid, (void*)&Call_System_Private_CoreLib_System_Threading_ThreadPool_BackgroundJobHandler } }, - { 100678363, { &MD_System_Private_CoreLib_System_Threading_TimerQueue_TimerHandler_Void_RetVoid, (void*)&Call_System_Private_CoreLib_System_Threading_TimerQueue_TimerHandler } }, - { 2638826848, { &MD_CalendarData_EnumCalendarInfoCallback, (void*)&Call_CalendarData_EnumCalendarInfoCallback } }, + { 2638833082, 3863938719, { &MD_System_Private_CoreLib_System_GC__RegisterNoGCRegionCallback_g__Callback_7C_72_0_I32_RetVoid, (void*)&Call_System_Private_CoreLib_System_GC__RegisterNoGCRegionCallback_g__Callback_7C_72_0_I32_RetVoid } } /* alternate key source: g__Callback|72_0#1:System.Private.CoreLib:System:GC */, + { 2638830556, 1336557534, { &MD_System_Private_CoreLib_System_Threading_ThreadPool_BackgroundJobHandler_Void_RetVoid, (void*)&Call_System_Private_CoreLib_System_Threading_ThreadPool_BackgroundJobHandler_Void_RetVoid } } /* alternate key source: BackgroundJobHandler#0:System.Private.CoreLib:System.Threading:ThreadPool */, + { 2638833091, 3378852959, { &MD_System_Private_CoreLib_System_GC_ConfigCallback_I32_I32_I32_I32_I64_RetVoid, (void*)&Call_System_Private_CoreLib_System_GC_ConfigCallback_I32_I32_I32_I32_I64_RetVoid } } /* alternate key source: ConfigCallback#5:System.Private.CoreLib:System:GC */, + { 2638826837, 1196551088, { &MD_System_Private_CoreLib_System_Globalization_CalendarData_EnumCalendarInfoCallback_I32_I32_RetVoid, (void*)&Call_System_Private_CoreLib_System_Globalization_CalendarData_EnumCalendarInfoCallback_I32_I32_RetVoid } } /* alternate key source: EnumCalendarInfoCallback#2:System.Private.CoreLib:System.Globalization:CalendarData */, + { 2638856334, 2613312799, { &MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComActivator_GetClassFactoryForTypeInternal_I32_RetI32, (void*)&Call_System_Private_CoreLib_Internal_Runtime_InteropServices_ComActivator_GetClassFactoryForTypeInternal_I32_RetI32 } } /* alternate key source: GetClassFactoryForTypeInternal#1:System.Private.CoreLib:Internal.Runtime.InteropServices:ComActivator */, + { 2638856344, 993231473, { &MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_GetFunctionPointer_I32_I32_I32_I32_I32_I32_RetI32, (void*)&Call_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_GetFunctionPointer_I32_I32_I32_I32_I32_I32_RetI32 } } /* alternate key source: GetFunctionPointer#6:System.Private.CoreLib:Internal.Runtime.InteropServices:ComponentActivator */, + { 2638856347, 3422156547, { &MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_LoadAssembly_I32_I32_I32_RetI32, (void*)&Call_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_LoadAssembly_I32_I32_I32_RetI32 } } /* alternate key source: LoadAssembly#3:System.Private.CoreLib:Internal.Runtime.InteropServices:ComponentActivator */, + { 2638856348, 542185314, { &MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_LoadAssemblyAndGetFunctionPointer_I32_I32_I32_I32_I32_I32_RetI32, (void*)&Call_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_LoadAssemblyAndGetFunctionPointer_I32_I32_I32_I32_I32_I32_RetI32 } } /* alternate key source: LoadAssemblyAndGetFunctionPointer#6:System.Private.CoreLib:Internal.Runtime.InteropServices:ComponentActivator */, + { 2638856345, 3765950975, { &MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_LoadAssemblyBytes_I32_I32_I32_I32_I32_I32_RetI32, (void*)&Call_System_Private_CoreLib_Internal_Runtime_InteropServices_ComponentActivator_LoadAssemblyBytes_I32_I32_I32_I32_I32_I32_RetI32 } } /* alternate key source: LoadAssemblyBytes#6:System.Private.CoreLib:Internal.Runtime.InteropServices:ComponentActivator */, + { 2638812170, 343912841, { &MD_System_Private_CoreLib_System_Runtime_InteropServices_TypeMapLazyDictionary_NewExternalTypeEntry_I32_I32_RetI32, (void*)&Call_System_Private_CoreLib_System_Runtime_InteropServices_TypeMapLazyDictionary_NewExternalTypeEntry_I32_I32_RetI32 } } /* alternate key source: NewExternalTypeEntry#2:System.Private.CoreLib:System.Runtime.InteropServices:TypeMapLazyDictionary */, + { 2638812169, 3327247096, { &MD_System_Private_CoreLib_System_Runtime_InteropServices_TypeMapLazyDictionary_NewProxyTypeEntry_I32_I32_RetI32, (void*)&Call_System_Private_CoreLib_System_Runtime_InteropServices_TypeMapLazyDictionary_NewProxyTypeEntry_I32_I32_RetI32 } } /* alternate key source: NewProxyTypeEntry#2:System.Private.CoreLib:System.Runtime.InteropServices:TypeMapLazyDictionary */, + { 2638856333, 4239234100, { &MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComActivator_RegisterClassForTypeInternal_I32_RetI32, (void*)&Call_System_Private_CoreLib_Internal_Runtime_InteropServices_ComActivator_RegisterClassForTypeInternal_I32_RetI32 } } /* alternate key source: RegisterClassForTypeInternal#1:System.Private.CoreLib:Internal.Runtime.InteropServices:ComActivator */, + { 2638830480, 167179540, { &MD_System_Private_CoreLib_System_Threading_TimerQueue_TimerHandler_Void_RetVoid, (void*)&Call_System_Private_CoreLib_System_Threading_TimerQueue_TimerHandler_Void_RetVoid } } /* alternate key source: TimerHandler#0:System.Private.CoreLib:System.Threading:TimerQueue */, + { 2638856332, 2150642223, { &MD_System_Private_CoreLib_Internal_Runtime_InteropServices_ComActivator_UnregisterClassForTypeInternal_I32_RetI32, (void*)&Call_System_Private_CoreLib_Internal_Runtime_InteropServices_ComActivator_UnregisterClassForTypeInternal_I32_RetI32 } } /* alternate key source: UnregisterClassForTypeInternal#1:System.Private.CoreLib:Internal.Runtime.InteropServices:ComActivator */ }; const size_t g_ReverseThunksCount = sizeof(g_ReverseThunks) / sizeof(g_ReverseThunks[0]); diff --git a/src/runtime/src/coreclr/vm/wasm/callhelpers.hpp b/src/runtime/src/coreclr/vm/wasm/callhelpers.hpp index 66cff3660a19..ed016d770ffe 100644 --- a/src/runtime/src/coreclr/vm/wasm/callhelpers.hpp +++ b/src/runtime/src/coreclr/vm/wasm/callhelpers.hpp @@ -23,6 +23,7 @@ struct ReverseThunkMapValue struct ReverseThunkMapEntry { ULONG key; + ULONG fallbackKey; ReverseThunkMapValue value; }; diff --git a/src/runtime/src/coreclr/vm/wasm/helpers.cpp b/src/runtime/src/coreclr/vm/wasm/helpers.cpp index fc750c90eb07..50227addc826 100644 --- a/src/runtime/src/coreclr/vm/wasm/helpers.cpp +++ b/src/runtime/src/coreclr/vm/wasm/helpers.cpp @@ -623,10 +623,33 @@ namespace if (!GetSignatureKey(sig, keyBuffer, keyBufferLen)) return NULL; - return LookupThunk(keyBuffer); + void* thunk = LookupThunk(keyBuffer); +#ifdef _DEBUG + if (thunk == NULL) + printf("WASM calli missing for key: %s\n", keyBuffer); +#endif + return thunk; + } + + ULONG CreateFallbackKey(MethodDesc* pMD) + { + _ASSERTE(pMD != nullptr); + + // the fallback key is in the form $"{MethodName}#{Method.GetParameters().Length}:{AssemblyName}:{Namespace}:{TypeName}"; + LPCUTF8 pszNamespace = nullptr; + LPCUTF8 pszName = pMD->GetMethodTable()->GetFullyQualifiedNameInfo(&pszNamespace); + MetaSig sig(pMD); + SString strFullName; + strFullName.Printf("%s#%d:%s:%s:%s", + pMD->GetName(), + sig.NumFixedArgs(), + pMD->GetAssembly()->GetSimpleName(), + pszNamespace != nullptr ? pszNamespace : "", + pszName); + + return strFullName.Hash(); } - // TODO: This hashing function should be replaced. ULONG CreateKey(MethodDesc* pMD) { _ASSERTE(pMD != nullptr); @@ -645,30 +668,54 @@ namespace typedef MapSHash HashToReverseThunkHash; HashToReverseThunkHash* reverseThunkCache = nullptr; + HashToReverseThunkHash* reverseThunkFallbackCache = nullptr; + + HashToReverseThunkHash* CreateReverseThunkHashTable(bool fallback) + { + HashToReverseThunkHash* newTable = new HashToReverseThunkHash(); + newTable->Reallocate(g_ReverseThunksCount * HashToReverseThunkHash::s_density_factor_denominator / HashToReverseThunkHash::s_density_factor_numerator + 1); + for (size_t i = 0; i < g_ReverseThunksCount; i++) + { + newTable->Add(fallback ? g_ReverseThunks[i].fallbackKey : g_ReverseThunks[i].key, &g_ReverseThunks[i].value); + } + + HashToReverseThunkHash **ppCache = fallback ? &reverseThunkFallbackCache : &reverseThunkCache; + if (InterlockedCompareExchangeT(ppCache, newTable, nullptr) != nullptr) + { + // Another thread won the race, discard ours + delete newTable; + } + return *ppCache; + } const ReverseThunkMapValue* LookupThunk(MethodDesc* pMD) { HashToReverseThunkHash* table = VolatileLoad(&reverseThunkCache); if (table == nullptr) { - HashToReverseThunkHash* newTable = new HashToReverseThunkHash(); - newTable->Reallocate(g_ReverseThunksCount * HashToReverseThunkHash::s_density_factor_denominator / HashToReverseThunkHash::s_density_factor_numerator + 1); - for (size_t i = 0; i < g_ReverseThunksCount; i++) - { - newTable->Add(g_ReverseThunks[i].key, &g_ReverseThunks[i].value); - } - - if (InterlockedCompareExchangeT(&reverseThunkCache, newTable, nullptr) != nullptr) - { - // Another thread won the race, discard ours - delete newTable; - } - table = reverseThunkCache; + table = CreateReverseThunkHashTable(false /* fallback */); } ULONG key = CreateKey(pMD); + // Try primary key, it is based on Assembly fully qualified name and method token const ReverseThunkMapValue* thunk; + if (table->Lookup(key, &thunk)) + { + return thunk; + } + + // Try fallback key, that is based on method properties and assembly name + // The fallback is used when the assembly is trimmed and the token and assembly fully qualified name + // may change. + table = VolatileLoad(&reverseThunkFallbackCache); + if (table == nullptr) + { + table = CreateReverseThunkHashTable(true /* fallback */); + } + + key = CreateFallbackKey(pMD); + bool success = table->Lookup(key, &thunk); return success ? thunk : nullptr; } diff --git a/src/runtime/src/installer/tests/Directory.Build.props b/src/runtime/src/installer/tests/Directory.Build.props index f0c55d9d5711..e3963dace6f2 100644 --- a/src/runtime/src/installer/tests/Directory.Build.props +++ b/src/runtime/src/installer/tests/Directory.Build.props @@ -8,7 +8,7 @@ --filter-query $(TestCaseFilter) $(TestRunnerAdditionalArguments) --crashdump - $(TestRunnerAdditionalArguments) --hangdump --hangdump-timeout 5m --hangdump-type full + $(TestRunnerAdditionalArguments) --hangdump --hangdump-timeout 8m --hangdump-type full false diff --git a/src/runtime/src/libraries/Common/tests/System/Net/Prerequisites/LocalEchoServer.props b/src/runtime/src/libraries/Common/tests/System/Net/Prerequisites/LocalEchoServer.props index b60990564084..ee75824b7556 100644 --- a/src/runtime/src/libraries/Common/tests/System/Net/Prerequisites/LocalEchoServer.props +++ b/src/runtime/src/libraries/Common/tests/System/Net/Prerequisites/LocalEchoServer.props @@ -17,6 +17,11 @@ $(WasmXHarnessArgs) --set-web-server-https-env=DOTNET_TEST_SECUREWEBSOCKETHOST,DOTNET_TEST_SECUREHTTPHOST,DOTNET_TEST_HTTP2HOST $(WasmXHarnessArgs) --web-server-middleware=$(_RemoteLoopMiddleware)/RemoteLoopServer.dll,RemoteLoopServer.GenericHandler $(WasmXHarnessArgs) --web-server-middleware=$(_TestEchoMiddleware)/NetCoreServer.dll,NetCoreServer.GenericHandler + + + _TargetFrameworkForXHarness=$(_TargetFrameworkForXHarness) + _TargetFrameworkForXHarness=$(_TargetFrameworkForXHarness) + StaticWebAssetsAdditionalBuildProperties=$(StaticWebAssetsAdditionalBuildProperties);StaticWebAssetsAdditionalPublishProperties=$(StaticWebAssetsAdditionalPublishProperties) @@ -26,12 +31,12 @@ diff --git a/src/runtime/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj b/src/runtime/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj index 340819fc688e..a41940d68ce8 100644 --- a/src/runtime/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj +++ b/src/runtime/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj @@ -45,8 +45,8 @@ - - + + diff --git a/src/runtime/src/libraries/System.Net.WebSockets.Client/tests/System.Net.WebSockets.Client.Tests.csproj b/src/runtime/src/libraries/System.Net.WebSockets.Client/tests/System.Net.WebSockets.Client.Tests.csproj index de52d1f91620..f82a72f18c74 100644 --- a/src/runtime/src/libraries/System.Net.WebSockets.Client/tests/System.Net.WebSockets.Client.Tests.csproj +++ b/src/runtime/src/libraries/System.Net.WebSockets.Client/tests/System.Net.WebSockets.Client.Tests.csproj @@ -20,8 +20,8 @@ - - + + diff --git a/src/runtime/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve2.PlatformNotSupported.cs b/src/runtime/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve2.PlatformNotSupported.cs index b416503334b0..9722d809c321 100644 --- a/src/runtime/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve2.PlatformNotSupported.cs +++ b/src/runtime/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve2.PlatformNotSupported.cs @@ -276,13 +276,13 @@ internal Arm64() { } /// svuint32_t svadclb[_u32](svuint32_t op1, svuint32_t op2, svuint32_t op3) /// ADCLB Ztied1.S, Zop2.S, Zop3.S /// - public static unsafe Vector AddCarryWideningEven(Vector op1, Vector op2, Vector op3) { throw new PlatformNotSupportedException(); } + public static unsafe Vector AddCarryWideningEven(Vector left, Vector right, Vector carry) { throw new PlatformNotSupportedException(); } /// /// svuint64_t svadclb[_u64](svuint64_t op1, svuint64_t op2, svuint64_t op3) /// ADCLB Ztied1.D, Zop2.D, Zop3.D /// - public static unsafe Vector AddCarryWideningEven(Vector op1, Vector op2, Vector op3) { throw new PlatformNotSupportedException(); } + public static unsafe Vector AddCarryWideningEven(Vector left, Vector right, Vector carry) { throw new PlatformNotSupportedException(); } // Add with carry long (top) @@ -290,13 +290,13 @@ internal Arm64() { } /// svuint32_t svadclt[_u32](svuint32_t op1, svuint32_t op2, svuint32_t op3) /// ADCLT Ztied1.S, Zop2.S, Zop3.S /// - public static unsafe Vector AddCarryWideningOdd(Vector op1, Vector op2, Vector op3) { throw new PlatformNotSupportedException(); } + public static unsafe Vector AddCarryWideningOdd(Vector left, Vector right, Vector carry) { throw new PlatformNotSupportedException(); } /// /// svuint64_t svadclt[_u64](svuint64_t op1, svuint64_t op2, svuint64_t op3) /// ADCLT Ztied1.D, Zop2.D, Zop3.D /// - public static unsafe Vector AddCarryWideningOdd(Vector op1, Vector op2, Vector op3) { throw new PlatformNotSupportedException(); } + public static unsafe Vector AddCarryWideningOdd(Vector left, Vector right, Vector carry) { throw new PlatformNotSupportedException(); } // Add narrow high part (bottom) @@ -905,19 +905,19 @@ internal Arm64() { } /// svint16_t svaddlbt[_s16](svint8_t op1, svint8_t op2) /// SADDLBT Zresult.H, Zop1.B, Zop2.B /// - public static Vector AddWideningEvenOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector AddWideningEvenOdd(Vector leftEven, Vector rightOdd) { throw new PlatformNotSupportedException(); } /// /// svint32_t svaddlbt[_s32](svint16_t op1, svint16_t op2) /// SADDLBT Zresult.S, Zop1.H, Zop2.H /// - public static Vector AddWideningEvenOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector AddWideningEvenOdd(Vector leftEven, Vector rightOdd) { throw new PlatformNotSupportedException(); } /// /// svint64_t svaddlbt[_s64](svint32_t op1, svint32_t op2) /// SADDLBT Zresult.D, Zop1.S, Zop2.S /// - public static Vector AddWideningEvenOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector AddWideningEvenOdd(Vector leftEven, Vector rightOdd) { throw new PlatformNotSupportedException(); } // Add wide (top) @@ -1485,97 +1485,97 @@ internal Arm64() { } /// svint8_t sveorbt[_s8](svint8_t odd, svint8_t op1, svint8_t op2) /// EORBT Zd.B, Zn.B, Zm.B /// - public static Vector InterleavingXorEvenOdd(Vector odd, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector InterleavingXorEvenOdd(Vector odd, Vector leftEven, Vector rightOdd) { throw new PlatformNotSupportedException(); } /// /// svint16_t sveorbt[_s16](svint16_t odd, svint16_t op1, svint16_t op2) /// EORBT Zd.H, Zn.H, Zm.H /// - public static Vector InterleavingXorEvenOdd(Vector odd, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector InterleavingXorEvenOdd(Vector odd, Vector leftEven, Vector rightOdd) { throw new PlatformNotSupportedException(); } /// /// svint32_t sveorbt[_s32](svint32_t odd, svint32_t op1, svint32_t op2) /// EORBT Zd.S, Zn.S, Zm.S /// - public static Vector InterleavingXorEvenOdd(Vector odd, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector InterleavingXorEvenOdd(Vector odd, Vector leftEven, Vector rightOdd) { throw new PlatformNotSupportedException(); } /// /// svint64_t sveorbt[_s64](svint64_t odd, svint64_t op1, svint64_t op2) /// EORBT Zd.D, Zn.D, Zm.D /// - public static Vector InterleavingXorEvenOdd(Vector odd, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector InterleavingXorEvenOdd(Vector odd, Vector leftEven, Vector rightOdd) { throw new PlatformNotSupportedException(); } /// /// svint8_t sveorbt[_s8](svint8_t odd, svint8_t op1, svint8_t op2) /// EORBT Zd.B, Zn.B, Zm.B /// - public static Vector InterleavingXorEvenOdd(Vector odd, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector InterleavingXorEvenOdd(Vector odd, Vector leftEven, Vector rightOdd) { throw new PlatformNotSupportedException(); } /// /// svint16_t sveorbt[_s16](svint16_t odd, svint16_t op1, svint16_t op2) /// EORBT Zd.H, Zn.H, Zm.H /// - public static Vector InterleavingXorEvenOdd(Vector odd, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector InterleavingXorEvenOdd(Vector odd, Vector leftEven, Vector rightOdd) { throw new PlatformNotSupportedException(); } /// /// svint32_t sveorbt[_s32](svint32_t odd, svint32_t op1, svint32_t op2) /// EORBT Zd.S, Zn.S, Zm.S /// - public static Vector InterleavingXorEvenOdd(Vector odd, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector InterleavingXorEvenOdd(Vector odd, Vector leftEven, Vector rightOdd) { throw new PlatformNotSupportedException(); } /// /// svint64_t sveorbt[_s64](svint64_t odd, svint64_t op1, svint64_t op2) /// EORBT Zd.D, Zn.D, Zm.D /// - public static Vector InterleavingXorEvenOdd(Vector odd, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector InterleavingXorEvenOdd(Vector odd, Vector leftEven, Vector rightOdd) { throw new PlatformNotSupportedException(); } /// /// svint8_t sveortb[_s8](svint8_t even, svint8_t op1, svint8_t op2) /// EORTB Zd.B, Zn.B, Zm.B /// - public static Vector InterleavingXorOddEven(Vector even, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector InterleavingXorOddEven(Vector even, Vector leftOdd, Vector rightEven) { throw new PlatformNotSupportedException(); } /// /// svint16_t sveortb[_s16](svint16_t even, svint16_t op1, svint16_t op2) /// EORTB Zd.H, Zn.H, Zm.H /// - public static Vector InterleavingXorOddEven(Vector even, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector InterleavingXorOddEven(Vector even, Vector leftOdd, Vector rightEven) { throw new PlatformNotSupportedException(); } /// /// svint32_t sveortb[_s32](svint32_t even, svint32_t op1, svint32_t op2) /// EORTB Zd.S, Zn.S, Zm.S /// - public static Vector InterleavingXorOddEven(Vector even, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector InterleavingXorOddEven(Vector even, Vector leftOdd, Vector rightEven) { throw new PlatformNotSupportedException(); } /// /// svint64_t sveortb[_s64](svint64_t even, svint64_t op1, svint64_t op2) /// EORTB Zd.D, Zn.D, Zm.D /// - public static Vector InterleavingXorOddEven(Vector even, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector InterleavingXorOddEven(Vector even, Vector leftOdd, Vector rightEven) { throw new PlatformNotSupportedException(); } /// /// svint8_t sveortb[_s8](svint8_t even, svint8_t op1, svint8_t op2) /// EORTB Zd.B, Zn.B, Zm.B /// - public static Vector InterleavingXorOddEven(Vector even, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector InterleavingXorOddEven(Vector even, Vector leftOdd, Vector rightEven) { throw new PlatformNotSupportedException(); } /// /// svint16_t sveortb[_s16](svint16_t even, svint16_t op1, svint16_t op2) /// EORTB Zd.H, Zn.H, Zm.H /// - public static Vector InterleavingXorOddEven(Vector even, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector InterleavingXorOddEven(Vector even, Vector leftOdd, Vector rightEven) { throw new PlatformNotSupportedException(); } /// /// svint32_t sveortb[_s32](svint32_t even, svint32_t op1, svint32_t op2) /// EORTB Zd.S, Zn.S, Zm.S /// - public static Vector InterleavingXorOddEven(Vector even, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector InterleavingXorOddEven(Vector even, Vector leftOdd, Vector rightEven) { throw new PlatformNotSupportedException(); } /// /// svint64_t sveortb[_s64](svint64_t even, svint64_t op1, svint64_t op2) /// EORTB Zd.D, Zn.D, Zm.D /// - public static Vector InterleavingXorOddEven(Vector even, Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector InterleavingXorOddEven(Vector even, Vector leftOdd, Vector rightEven) { throw new PlatformNotSupportedException(); } // Base 2 logarithm as integer @@ -3840,13 +3840,13 @@ internal Arm64() { } /// svuint32_t svsbclb[_u32](svuint32_t op1, svuint32_t op2, svuint32_t op3) /// SBCLB Ztied1.S, Zop2.S, Zop3.S /// - public static Vector SubtractBorrowWideningEven(Vector op1, Vector op2, Vector op3) { throw new PlatformNotSupportedException(); } + public static Vector SubtractBorrowWideningEven(Vector left, Vector right, Vector borrow) { throw new PlatformNotSupportedException(); } /// /// svuint64_t svsbclb[_u64](svuint64_t op1, svuint64_t op2, svuint64_t op3) /// SBCLB Ztied1.D, Zop2.D, Zop3.D /// - public static Vector SubtractBorrowWideningEven(Vector op1, Vector op2, Vector op3) { throw new PlatformNotSupportedException(); } + public static Vector SubtractBorrowWideningEven(Vector left, Vector right, Vector borrow) { throw new PlatformNotSupportedException(); } // Subtract with borrow long (top) @@ -3855,13 +3855,13 @@ internal Arm64() { } /// svuint32_t svsbclt[_u32](svuint32_t op1, svuint32_t op2, svuint32_t op3) /// SBCLT Ztied1.S, Zop2.S, Zop3.S /// - public static Vector SubtractBorrowWideningOdd(Vector op1, Vector op2, Vector op3) { throw new PlatformNotSupportedException(); } + public static Vector SubtractBorrowWideningOdd(Vector left, Vector right, Vector borrow) { throw new PlatformNotSupportedException(); } /// /// svuint64_t svsbclt[_u64](svuint64_t op1, svuint64_t op2, svuint64_t op3) /// SBCLT Ztied1.D, Zop2.D, Zop3.D /// - public static Vector SubtractBorrowWideningOdd(Vector op1, Vector op2, Vector op3) { throw new PlatformNotSupportedException(); } + public static Vector SubtractBorrowWideningOdd(Vector left, Vector right, Vector borrow) { throw new PlatformNotSupportedException(); } // Subtract narrow high part (bottom) @@ -4195,19 +4195,19 @@ internal Arm64() { } /// svint16_t svsublbt[_s16](svint8_t op1, svint8_t op2) /// SSUBLBT Zresult.H, Zop1.B, Zop2.B /// - public static Vector SubtractWideningEvenOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector SubtractWideningEvenOdd(Vector leftEven, Vector rightOdd) { throw new PlatformNotSupportedException(); } /// /// svint32_t svsublbt[_s32](svint16_t op1, svint16_t op2) /// SSUBLBT Zresult.S, Zop1.H, Zop2.H /// - public static Vector SubtractWideningEvenOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector SubtractWideningEvenOdd(Vector leftEven, Vector rightOdd) { throw new PlatformNotSupportedException(); } /// /// svint64_t svsublbt[_s64](svint32_t op1, svint32_t op2) /// SSUBLBT Zresult.D, Zop1.S, Zop2.S /// - public static Vector SubtractWideningEvenOdd(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector SubtractWideningEvenOdd(Vector leftEven, Vector rightOdd) { throw new PlatformNotSupportedException(); } // Subtract wide (top) @@ -4294,19 +4294,19 @@ internal Arm64() { } /// svint16_t svsubltb[_s16](svint8_t op1, svint8_t op2) /// SSUBLTB Zresult.H, Zop1.B, Zop2.B /// - public static Vector SubtractWideningOddEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector SubtractWideningOddEven(Vector leftOdd, Vector rightEven) { throw new PlatformNotSupportedException(); } /// /// svint32_t svsubltb[_s32](svint16_t op1, svint16_t op2) /// SSUBLTB Zresult.S, Zop1.H, Zop2.H /// - public static Vector SubtractWideningOddEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector SubtractWideningOddEven(Vector leftOdd, Vector rightEven) { throw new PlatformNotSupportedException(); } /// /// svint64_t svsubltb[_s64](svint32_t op1, svint32_t op2) /// SSUBLTB Zresult.D, Zop1.S, Zop2.S /// - public static Vector SubtractWideningOddEven(Vector left, Vector right) { throw new PlatformNotSupportedException(); } + public static Vector SubtractWideningOddEven(Vector leftOdd, Vector rightEven) { throw new PlatformNotSupportedException(); } // Bit vector table lookups diff --git a/src/runtime/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve2.cs b/src/runtime/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve2.cs index 755117c6411e..904ce01689ef 100644 --- a/src/runtime/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve2.cs +++ b/src/runtime/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Arm/Sve2.cs @@ -276,13 +276,13 @@ internal Arm64() { } /// svuint32_t svadclb[_u32](svuint32_t op1, svuint32_t op2, svuint32_t op3) /// ADCLB Ztied1.S, Zop2.S, Zop3.S /// - public static unsafe Vector AddCarryWideningEven(Vector op1, Vector op2, Vector op3) => AddCarryWideningEven(op1, op2, op3); + public static unsafe Vector AddCarryWideningEven(Vector left, Vector right, Vector carry) => AddCarryWideningEven(left, right, carry); /// /// svuint64_t svadclb[_u64](svuint64_t op1, svuint64_t op2, svuint64_t op3) /// ADCLB Ztied1.D, Zop2.D, Zop3.D /// - public static unsafe Vector AddCarryWideningEven(Vector op1, Vector op2, Vector op3) => AddCarryWideningEven(op1, op2, op3); + public static unsafe Vector AddCarryWideningEven(Vector left, Vector right, Vector carry) => AddCarryWideningEven(left, right, carry); // Add with carry long (top) @@ -290,13 +290,13 @@ internal Arm64() { } /// svuint32_t svadclt[_u32](svuint32_t op1, svuint32_t op2, svuint32_t op3) /// ADCLT Ztied1.S, Zop2.S, Zop3.S /// - public static unsafe Vector AddCarryWideningOdd(Vector op1, Vector op2, Vector op3) => AddCarryWideningOdd(op1, op2, op3); + public static unsafe Vector AddCarryWideningOdd(Vector left, Vector right, Vector carry) => AddCarryWideningOdd(left, right, carry); /// /// svuint64_t svadclt[_u64](svuint64_t op1, svuint64_t op2, svuint64_t op3) /// ADCLT Ztied1.D, Zop2.D, Zop3.D /// - public static unsafe Vector AddCarryWideningOdd(Vector op1, Vector op2, Vector op3) => AddCarryWideningOdd(op1, op2, op3); + public static unsafe Vector AddCarryWideningOdd(Vector left, Vector right, Vector carry) => AddCarryWideningOdd(left, right, carry); // Add narrow high part (bottom) @@ -905,19 +905,19 @@ internal Arm64() { } /// svint16_t svaddlbt[_s16](svint8_t op1, svint8_t op2) /// SADDLBT Zresult.H, Zop1.B, Zop2.B /// - public static Vector AddWideningEvenOdd(Vector left, Vector right) => AddWideningEvenOdd(left, right); + public static Vector AddWideningEvenOdd(Vector leftEven, Vector rightOdd) => AddWideningEvenOdd(leftEven, rightOdd); /// /// svint32_t svaddlbt[_s32](svint16_t op1, svint16_t op2) /// SADDLBT Zresult.S, Zop1.H, Zop2.H /// - public static Vector AddWideningEvenOdd(Vector left, Vector right) => AddWideningEvenOdd(left, right); + public static Vector AddWideningEvenOdd(Vector leftEven, Vector rightOdd) => AddWideningEvenOdd(leftEven, rightOdd); /// /// svint64_t svaddlbt[_s64](svint32_t op1, svint32_t op2) /// SADDLBT Zresult.D, Zop1.S, Zop2.S /// - public static Vector AddWideningEvenOdd(Vector left, Vector right) => AddWideningEvenOdd(left, right); + public static Vector AddWideningEvenOdd(Vector leftEven, Vector rightOdd) => AddWideningEvenOdd(leftEven, rightOdd); // Add wide (top) @@ -1485,97 +1485,97 @@ internal Arm64() { } /// svint8_t sveorbt[_s8](svint8_t odd, svint8_t op1, svint8_t op2) /// EORBT Zd.B, Zn.B, Zm.B /// - public static Vector InterleavingXorEvenOdd(Vector odd, Vector left, Vector right) => InterleavingXorEvenOdd(odd, left, right); + public static Vector InterleavingXorEvenOdd(Vector odd, Vector leftEven, Vector rightOdd) => InterleavingXorEvenOdd(odd, leftEven, rightOdd); /// /// svint16_t sveorbt[_s16](svint16_t odd, svint16_t op1, svint16_t op2) /// EORBT Zd.H, Zn.H, Zm.H /// - public static Vector InterleavingXorEvenOdd(Vector odd, Vector left, Vector right) => InterleavingXorEvenOdd(odd, left, right); + public static Vector InterleavingXorEvenOdd(Vector odd, Vector leftEven, Vector rightOdd) => InterleavingXorEvenOdd(odd, leftEven, rightOdd); /// /// svint32_t sveorbt[_s32](svint32_t odd, svint32_t op1, svint32_t op2) /// EORBT Zd.S, Zn.S, Zm.S /// - public static Vector InterleavingXorEvenOdd(Vector odd, Vector left, Vector right) => InterleavingXorEvenOdd(odd, left, right); + public static Vector InterleavingXorEvenOdd(Vector odd, Vector leftEven, Vector rightOdd) => InterleavingXorEvenOdd(odd, leftEven, rightOdd); /// /// svint64_t sveorbt[_s64](svint64_t odd, svint64_t op1, svint64_t op2) /// EORBT Zd.D, Zn.D, Zm.D /// - public static Vector InterleavingXorEvenOdd(Vector odd, Vector left, Vector right) => InterleavingXorEvenOdd(odd, left, right); + public static Vector InterleavingXorEvenOdd(Vector odd, Vector leftEven, Vector rightOdd) => InterleavingXorEvenOdd(odd, leftEven, rightOdd); /// /// svint8_t sveorbt[_s8](svint8_t odd, svint8_t op1, svint8_t op2) /// EORBT Zd.B, Zn.B, Zm.B /// - public static Vector InterleavingXorEvenOdd(Vector odd, Vector left, Vector right) => InterleavingXorEvenOdd(odd, left, right); + public static Vector InterleavingXorEvenOdd(Vector odd, Vector leftEven, Vector rightOdd) => InterleavingXorEvenOdd(odd, leftEven, rightOdd); /// /// svint16_t sveorbt[_s16](svint16_t odd, svint16_t op1, svint16_t op2) /// EORBT Zd.H, Zn.H, Zm.H /// - public static Vector InterleavingXorEvenOdd(Vector odd, Vector left, Vector right) => InterleavingXorEvenOdd(odd, left, right); + public static Vector InterleavingXorEvenOdd(Vector odd, Vector leftEven, Vector rightOdd) => InterleavingXorEvenOdd(odd, leftEven, rightOdd); /// /// svint32_t sveorbt[_s32](svint32_t odd, svint32_t op1, svint32_t op2) /// EORBT Zd.S, Zn.S, Zm.S /// - public static Vector InterleavingXorEvenOdd(Vector odd, Vector left, Vector right) => InterleavingXorEvenOdd(odd, left, right); + public static Vector InterleavingXorEvenOdd(Vector odd, Vector leftEven, Vector rightOdd) => InterleavingXorEvenOdd(odd, leftEven, rightOdd); /// /// svint64_t sveorbt[_s64](svint64_t odd, svint64_t op1, svint64_t op2) /// EORBT Zd.D, Zn.D, Zm.D /// - public static Vector InterleavingXorEvenOdd(Vector odd, Vector left, Vector right) => InterleavingXorEvenOdd(odd, left, right); + public static Vector InterleavingXorEvenOdd(Vector odd, Vector leftEven, Vector rightOdd) => InterleavingXorEvenOdd(odd, leftEven, rightOdd); /// /// svint8_t sveortb[_s8](svint8_t even, svint8_t op1, svint8_t op2) /// EORTB Zd.B, Zn.B, Zm.B /// - public static Vector InterleavingXorOddEven(Vector even, Vector left, Vector right) => InterleavingXorOddEven(even, left, right); + public static Vector InterleavingXorOddEven(Vector even, Vector leftOdd, Vector rightEven) => InterleavingXorOddEven(even, leftOdd, rightEven); /// /// svint16_t sveortb[_s16](svint16_t even, svint16_t op1, svint16_t op2) /// EORTB Zd.H, Zn.H, Zm.H /// - public static Vector InterleavingXorOddEven(Vector even, Vector left, Vector right) => InterleavingXorOddEven(even, left, right); + public static Vector InterleavingXorOddEven(Vector even, Vector leftOdd, Vector rightEven) => InterleavingXorOddEven(even, leftOdd, rightEven); /// /// svint32_t sveortb[_s32](svint32_t even, svint32_t op1, svint32_t op2) /// EORTB Zd.S, Zn.S, Zm.S /// - public static Vector InterleavingXorOddEven(Vector even, Vector left, Vector right) => InterleavingXorOddEven(even, left, right); + public static Vector InterleavingXorOddEven(Vector even, Vector leftOdd, Vector rightEven) => InterleavingXorOddEven(even, leftOdd, rightEven); /// /// svint64_t sveortb[_s64](svint64_t even, svint64_t op1, svint64_t op2) /// EORTB Zd.D, Zn.D, Zm.D /// - public static Vector InterleavingXorOddEven(Vector even, Vector left, Vector right) => InterleavingXorOddEven(even, left, right); + public static Vector InterleavingXorOddEven(Vector even, Vector leftOdd, Vector rightEven) => InterleavingXorOddEven(even, leftOdd, rightEven); /// /// svint8_t sveortb[_s8](svint8_t even, svint8_t op1, svint8_t op2) /// EORTB Zd.B, Zn.B, Zm.B /// - public static Vector InterleavingXorOddEven(Vector even, Vector left, Vector right) => InterleavingXorOddEven(even, left, right); + public static Vector InterleavingXorOddEven(Vector even, Vector leftOdd, Vector rightEven) => InterleavingXorOddEven(even, leftOdd, rightEven); /// /// svint16_t sveortb[_s16](svint16_t even, svint16_t op1, svint16_t op2) /// EORTB Zd.H, Zn.H, Zm.H /// - public static Vector InterleavingXorOddEven(Vector even, Vector left, Vector right) => InterleavingXorOddEven(even, left, right); + public static Vector InterleavingXorOddEven(Vector even, Vector leftOdd, Vector rightEven) => InterleavingXorOddEven(even, leftOdd, rightEven); /// /// svint32_t sveortb[_s32](svint32_t even, svint32_t op1, svint32_t op2) /// EORTB Zd.S, Zn.S, Zm.S /// - public static Vector InterleavingXorOddEven(Vector even, Vector left, Vector right) => InterleavingXorOddEven(even, left, right); + public static Vector InterleavingXorOddEven(Vector even, Vector leftOdd, Vector rightEven) => InterleavingXorOddEven(even, leftOdd, rightEven); /// /// svint64_t sveortb[_s64](svint64_t even, svint64_t op1, svint64_t op2) /// EORTB Zd.D, Zn.D, Zm.D /// - public static Vector InterleavingXorOddEven(Vector even, Vector left, Vector right) => InterleavingXorOddEven(even, left, right); + public static Vector InterleavingXorOddEven(Vector even, Vector leftOdd, Vector rightEven) => InterleavingXorOddEven(even, leftOdd, rightEven); // Base 2 logarithm as integer @@ -3864,13 +3864,13 @@ internal Arm64() { } /// svuint32_t svsbclb[_u32](svuint32_t op1, svuint32_t op2, svuint32_t op3) /// SBCLB Ztied1.S, Zop2.S, Zop3.S /// - public static Vector SubtractBorrowWideningEven(Vector op1, Vector op2, Vector op3) => SubtractBorrowWideningEven(op1, op2, op3); + public static Vector SubtractBorrowWideningEven(Vector left, Vector right, Vector borrow) => SubtractBorrowWideningEven(left, right, borrow); /// /// svuint64_t svsbclb[_u64](svuint64_t op1, svuint64_t op2, svuint64_t op3) /// SBCLB Ztied1.D, Zop2.D, Zop3.D /// - public static Vector SubtractBorrowWideningEven(Vector op1, Vector op2, Vector op3) => SubtractBorrowWideningEven(op1, op2, op3); + public static Vector SubtractBorrowWideningEven(Vector left, Vector right, Vector borrow) => SubtractBorrowWideningEven(left, right, borrow); // Subtract with borrow long (top) @@ -3879,13 +3879,13 @@ internal Arm64() { } /// svuint32_t svsbclt[_u32](svuint32_t op1, svuint32_t op2, svuint32_t op3) /// SBCLT Ztied1.S, Zop2.S, Zop3.S /// - public static Vector SubtractBorrowWideningOdd(Vector op1, Vector op2, Vector op3) => SubtractBorrowWideningOdd(op1, op2, op3); + public static Vector SubtractBorrowWideningOdd(Vector left, Vector right, Vector borrow) => SubtractBorrowWideningOdd(left, right, borrow); /// /// svuint64_t svsbclt[_u64](svuint64_t op1, svuint64_t op2, svuint64_t op3) /// SBCLT Ztied1.D, Zop2.D, Zop3.D /// - public static Vector SubtractBorrowWideningOdd(Vector op1, Vector op2, Vector op3) => SubtractBorrowWideningOdd(op1, op2, op3); + public static Vector SubtractBorrowWideningOdd(Vector left, Vector right, Vector borrow) => SubtractBorrowWideningOdd(left, right, borrow); // Subtract narrow high part (bottom) @@ -4219,19 +4219,19 @@ internal Arm64() { } /// svint16_t svsublbt[_s16](svint8_t op1, svint8_t op2) /// SSUBLBT Zresult.H, Zop1.B, Zop2.B /// - public static Vector SubtractWideningEvenOdd(Vector left, Vector right) => SubtractWideningEvenOdd(left, right); + public static Vector SubtractWideningEvenOdd(Vector leftEven, Vector rightOdd) => SubtractWideningEvenOdd(leftEven, rightOdd); /// /// svint32_t svsublbt[_s32](svint16_t op1, svint16_t op2) /// SSUBLBT Zresult.S, Zop1.H, Zop2.H /// - public static Vector SubtractWideningEvenOdd(Vector left, Vector right) => SubtractWideningEvenOdd(left, right); + public static Vector SubtractWideningEvenOdd(Vector leftEven, Vector rightOdd) => SubtractWideningEvenOdd(leftEven, rightOdd); /// /// svint64_t svsublbt[_s64](svint32_t op1, svint32_t op2) /// SSUBLBT Zresult.D, Zop1.S, Zop2.S /// - public static Vector SubtractWideningEvenOdd(Vector left, Vector right) => SubtractWideningEvenOdd(left, right); + public static Vector SubtractWideningEvenOdd(Vector leftEven, Vector rightOdd) => SubtractWideningEvenOdd(leftEven, rightOdd); // Subtract wide (top) @@ -4318,19 +4318,19 @@ internal Arm64() { } /// svint16_t svsubltb[_s16](svint8_t op1, svint8_t op2) /// SSUBLTB Zresult.H, Zop1.B, Zop2.B /// - public static Vector SubtractWideningOddEven(Vector left, Vector right) => SubtractWideningOddEven(left, right); + public static Vector SubtractWideningOddEven(Vector leftOdd, Vector rightEven) => SubtractWideningOddEven(leftOdd, rightEven); /// /// svint32_t svsubltb[_s32](svint16_t op1, svint16_t op2) /// SSUBLTB Zresult.S, Zop1.H, Zop2.H /// - public static Vector SubtractWideningOddEven(Vector left, Vector right) => SubtractWideningOddEven(left, right); + public static Vector SubtractWideningOddEven(Vector leftOdd, Vector rightEven) => SubtractWideningOddEven(leftOdd, rightEven); /// /// svint64_t svsubltb[_s64](svint32_t op1, svint32_t op2) /// SSUBLTB Zresult.D, Zop1.S, Zop2.S /// - public static Vector SubtractWideningOddEven(Vector left, Vector right) => SubtractWideningOddEven(left, right); + public static Vector SubtractWideningOddEven(Vector leftOdd, Vector rightEven) => SubtractWideningOddEven(leftOdd, rightEven); // Bit vector table lookups diff --git a/src/runtime/src/libraries/System.Private.CoreLib/src/System/TypeLoadException.cs b/src/runtime/src/libraries/System.Private.CoreLib/src/System/TypeLoadException.cs index b269f3913162..7fae1390466c 100644 --- a/src/runtime/src/libraries/System.Private.CoreLib/src/System/TypeLoadException.cs +++ b/src/runtime/src/libraries/System.Private.CoreLib/src/System/TypeLoadException.cs @@ -71,7 +71,7 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont } // If ClassName != null, GetMessage will construct on the fly using it - // and ResourceId (mscorrc.dll). This allows customization of the + // and ResourceId (from mscorrc). This allows customization of the // class name format depending on the language environment. private string? _className; private string? _assemblyName; diff --git a/src/runtime/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System.Runtime.InteropServices.JavaScript.Tests.csproj b/src/runtime/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System.Runtime.InteropServices.JavaScript.Tests.csproj index c978c7bf0f49..c959554c57a7 100644 --- a/src/runtime/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System.Runtime.InteropServices.JavaScript.Tests.csproj +++ b/src/runtime/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System.Runtime.InteropServices.JavaScript.Tests.csproj @@ -41,9 +41,9 @@ - - - + + + @@ -71,9 +71,6 @@ - - - diff --git a/src/runtime/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComClassGenerator.cs b/src/runtime/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComClassGenerator.cs index f2cab6db31b2..1455804b0ba9 100644 --- a/src/runtime/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComClassGenerator.cs +++ b/src/runtime/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComClassGenerator.cs @@ -55,7 +55,9 @@ public void Initialize(IncrementalGeneratorInitializationContext context) writer.WriteLine(classInfoType.ToFullString()); writer.WriteLine(); writer.WriteLine(attribute); - context.AddSource(className, writer.ToString()); + // Replace < and > with { and } to make valid hint names for generic types + string hintName = className.Replace('<', '{').Replace('>', '}'); + context.AddSource(hintName, writer.ToString()); }); } diff --git a/src/runtime/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ComClassGeneratorOutputShape.cs b/src/runtime/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ComClassGeneratorOutputShape.cs index cc3dc85bbe5e..c00ff13aae59 100644 --- a/src/runtime/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ComClassGeneratorOutputShape.cs +++ b/src/runtime/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ComClassGeneratorOutputShape.cs @@ -68,6 +68,27 @@ partial class E : C await VerifySourceGeneratorAsync(source, "C", "D", "E"); } + [Fact] + public async Task GenericComClass() + { + string source = """ + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.Marshalling; + + [GeneratedComInterface] + partial interface INativeAPI + { + } + + [GeneratedComClass] + partial class GenericClass : INativeAPI where T : class, new() + { + } + """; + + await VerifySourceGeneratorAsync(source, "GenericClass`1"); + } + private static async Task VerifySourceGeneratorAsync(string source, params string[] typeNames) { GeneratedShapeTest test = new(typeNames) diff --git a/src/runtime/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs b/src/runtime/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs index 783da0103d47..479501776f2a 100644 --- a/src/runtime/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/runtime/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -6216,10 +6216,10 @@ internal Arm64() { } public static System.Numerics.Vector AbsoluteDifferenceWideningOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector AbsoluteDifferenceWideningOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddCarryWideningEven(System.Numerics.Vector op1, System.Numerics.Vector op2, System.Numerics.Vector op3) { throw null; } - public static System.Numerics.Vector AddCarryWideningEven(System.Numerics.Vector op1, System.Numerics.Vector op2, System.Numerics.Vector op3) { throw null; } - public static System.Numerics.Vector AddCarryWideningOdd(System.Numerics.Vector op1, System.Numerics.Vector op2, System.Numerics.Vector op3) { throw null; } - public static System.Numerics.Vector AddCarryWideningOdd(System.Numerics.Vector op1, System.Numerics.Vector op2, System.Numerics.Vector op3) { throw null; } + public static System.Numerics.Vector AddCarryWideningEven(System.Numerics.Vector left, System.Numerics.Vector right, System.Numerics.Vector carry) { throw null; } + public static System.Numerics.Vector AddCarryWideningEven(System.Numerics.Vector left, System.Numerics.Vector right, System.Numerics.Vector carry) { throw null; } + public static System.Numerics.Vector AddCarryWideningOdd(System.Numerics.Vector left, System.Numerics.Vector right, System.Numerics.Vector carry) { throw null; } + public static System.Numerics.Vector AddCarryWideningOdd(System.Numerics.Vector left, System.Numerics.Vector right, System.Numerics.Vector carry) { throw null; } public static System.Numerics.Vector AddHighNarrowingEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector AddHighNarrowingEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } @@ -6305,9 +6305,9 @@ internal Arm64() { } public static System.Numerics.Vector AddWideningEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector AddWideningEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector AddWideningEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddWideningEvenOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddWideningEvenOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector AddWideningEvenOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector AddWideningEvenOdd(System.Numerics.Vector leftEven, System.Numerics.Vector rightOdd) { throw null; } + public static System.Numerics.Vector AddWideningEvenOdd(System.Numerics.Vector leftEven, System.Numerics.Vector rightOdd) { throw null; } + public static System.Numerics.Vector AddWideningEvenOdd(System.Numerics.Vector leftEven, System.Numerics.Vector rightOdd) { throw null; } public static System.Numerics.Vector AddWideningOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector AddWideningOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector AddWideningOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } @@ -6384,22 +6384,22 @@ internal Arm64() { } public static System.Numerics.Vector FusedSubtractHalving(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector FusedSubtractHalving(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector FusedSubtractHalving(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector InterleavingXorEvenOdd(System.Numerics.Vector odd, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector InterleavingXorEvenOdd(System.Numerics.Vector odd, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector InterleavingXorEvenOdd(System.Numerics.Vector odd, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector InterleavingXorEvenOdd(System.Numerics.Vector odd, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector InterleavingXorEvenOdd(System.Numerics.Vector odd, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector InterleavingXorEvenOdd(System.Numerics.Vector odd, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector InterleavingXorEvenOdd(System.Numerics.Vector odd, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector InterleavingXorEvenOdd(System.Numerics.Vector odd, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector InterleavingXorOddEven(System.Numerics.Vector even, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector InterleavingXorOddEven(System.Numerics.Vector even, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector InterleavingXorOddEven(System.Numerics.Vector even, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector InterleavingXorOddEven(System.Numerics.Vector even, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector InterleavingXorOddEven(System.Numerics.Vector even, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector InterleavingXorOddEven(System.Numerics.Vector even, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector InterleavingXorOddEven(System.Numerics.Vector even, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector InterleavingXorOddEven(System.Numerics.Vector even, System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector InterleavingXorEvenOdd(System.Numerics.Vector odd, System.Numerics.Vector leftEven, System.Numerics.Vector rightOdd) { throw null; } + public static System.Numerics.Vector InterleavingXorEvenOdd(System.Numerics.Vector odd, System.Numerics.Vector leftEven, System.Numerics.Vector rightOdd) { throw null; } + public static System.Numerics.Vector InterleavingXorEvenOdd(System.Numerics.Vector odd, System.Numerics.Vector leftEven, System.Numerics.Vector rightOdd) { throw null; } + public static System.Numerics.Vector InterleavingXorEvenOdd(System.Numerics.Vector odd, System.Numerics.Vector leftEven, System.Numerics.Vector rightOdd) { throw null; } + public static System.Numerics.Vector InterleavingXorEvenOdd(System.Numerics.Vector odd, System.Numerics.Vector leftEven, System.Numerics.Vector rightOdd) { throw null; } + public static System.Numerics.Vector InterleavingXorEvenOdd(System.Numerics.Vector odd, System.Numerics.Vector leftEven, System.Numerics.Vector rightOdd) { throw null; } + public static System.Numerics.Vector InterleavingXorEvenOdd(System.Numerics.Vector odd, System.Numerics.Vector leftEven, System.Numerics.Vector rightOdd) { throw null; } + public static System.Numerics.Vector InterleavingXorEvenOdd(System.Numerics.Vector odd, System.Numerics.Vector leftEven, System.Numerics.Vector rightOdd) { throw null; } + public static System.Numerics.Vector InterleavingXorOddEven(System.Numerics.Vector even, System.Numerics.Vector leftOdd, System.Numerics.Vector rightEven) { throw null; } + public static System.Numerics.Vector InterleavingXorOddEven(System.Numerics.Vector even, System.Numerics.Vector leftOdd, System.Numerics.Vector rightEven) { throw null; } + public static System.Numerics.Vector InterleavingXorOddEven(System.Numerics.Vector even, System.Numerics.Vector leftOdd, System.Numerics.Vector rightEven) { throw null; } + public static System.Numerics.Vector InterleavingXorOddEven(System.Numerics.Vector even, System.Numerics.Vector leftOdd, System.Numerics.Vector rightEven) { throw null; } + public static System.Numerics.Vector InterleavingXorOddEven(System.Numerics.Vector even, System.Numerics.Vector leftOdd, System.Numerics.Vector rightEven) { throw null; } + public static System.Numerics.Vector InterleavingXorOddEven(System.Numerics.Vector even, System.Numerics.Vector leftOdd, System.Numerics.Vector rightEven) { throw null; } + public static System.Numerics.Vector InterleavingXorOddEven(System.Numerics.Vector even, System.Numerics.Vector leftOdd, System.Numerics.Vector rightEven) { throw null; } + public static System.Numerics.Vector InterleavingXorOddEven(System.Numerics.Vector even, System.Numerics.Vector leftOdd, System.Numerics.Vector rightEven) { throw null; } public static System.Numerics.Vector Log2(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector Log2(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector MaxNumberPairwise(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } @@ -6732,10 +6732,10 @@ internal Arm64() { } public static System.Numerics.Vector ShiftRightLogicalRoundedNarrowingSaturateOdd(System.Numerics.Vector even, System.Numerics.Vector value, [ConstantExpected] byte count) { throw null; } public static System.Numerics.Vector ShiftRightLogicalRoundedNarrowingSaturateOdd(System.Numerics.Vector even, System.Numerics.Vector value, [ConstantExpected] byte count) { throw null; } public static System.Numerics.Vector ShiftRightLogicalRoundedNarrowingSaturateOdd(System.Numerics.Vector even, System.Numerics.Vector value, [ConstantExpected] byte count) { throw null; } - public static System.Numerics.Vector SubtractBorrowWideningEven(System.Numerics.Vector op1, System.Numerics.Vector op2, System.Numerics.Vector op3) { throw null; } - public static System.Numerics.Vector SubtractBorrowWideningEven(System.Numerics.Vector op1, System.Numerics.Vector op2, System.Numerics.Vector op3) { throw null; } - public static System.Numerics.Vector SubtractBorrowWideningOdd(System.Numerics.Vector op1, System.Numerics.Vector op2, System.Numerics.Vector op3) { throw null; } - public static System.Numerics.Vector SubtractBorrowWideningOdd(System.Numerics.Vector op1, System.Numerics.Vector op2, System.Numerics.Vector op3) { throw null; } + public static System.Numerics.Vector SubtractBorrowWideningEven(System.Numerics.Vector left, System.Numerics.Vector right, System.Numerics.Vector borrow) { throw null; } + public static System.Numerics.Vector SubtractBorrowWideningEven(System.Numerics.Vector left, System.Numerics.Vector right, System.Numerics.Vector borrow) { throw null; } + public static System.Numerics.Vector SubtractBorrowWideningOdd(System.Numerics.Vector left, System.Numerics.Vector right, System.Numerics.Vector borrow) { throw null; } + public static System.Numerics.Vector SubtractBorrowWideningOdd(System.Numerics.Vector left, System.Numerics.Vector right, System.Numerics.Vector borrow) { throw null; } public static System.Numerics.Vector SubtractHighNarrowingEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector SubtractHighNarrowingEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector SubtractHighNarrowingEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } @@ -6780,9 +6780,9 @@ internal Arm64() { } public static System.Numerics.Vector SubtractWideningEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector SubtractWideningEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector SubtractWideningEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector SubtractWideningEvenOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector SubtractWideningEvenOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector SubtractWideningEvenOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector SubtractWideningEvenOdd(System.Numerics.Vector leftEven, System.Numerics.Vector rightOdd) { throw null; } + public static System.Numerics.Vector SubtractWideningEvenOdd(System.Numerics.Vector leftEven, System.Numerics.Vector rightOdd) { throw null; } + public static System.Numerics.Vector SubtractWideningEvenOdd(System.Numerics.Vector leftEven, System.Numerics.Vector rightOdd) { throw null; } public static System.Numerics.Vector SubtractWideningOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector SubtractWideningOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector SubtractWideningOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } @@ -6795,9 +6795,9 @@ internal Arm64() { } public static System.Numerics.Vector SubtractWideningOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector SubtractWideningOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector SubtractWideningOdd(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector SubtractWideningOddEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector SubtractWideningOddEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } - public static System.Numerics.Vector SubtractWideningOddEven(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static System.Numerics.Vector SubtractWideningOddEven(System.Numerics.Vector leftOdd, System.Numerics.Vector rightEven) { throw null; } + public static System.Numerics.Vector SubtractWideningOddEven(System.Numerics.Vector leftOdd, System.Numerics.Vector rightEven) { throw null; } + public static System.Numerics.Vector SubtractWideningOddEven(System.Numerics.Vector leftOdd, System.Numerics.Vector rightEven) { throw null; } public static System.Numerics.Vector VectorTableLookup((System.Numerics.Vector data1, System.Numerics.Vector data2) table, System.Numerics.Vector indices) { throw null; } public static System.Numerics.Vector VectorTableLookup((System.Numerics.Vector data1, System.Numerics.Vector data2) table, System.Numerics.Vector indices) { throw null; } public static System.Numerics.Vector VectorTableLookup((System.Numerics.Vector data1, System.Numerics.Vector data2) table, System.Numerics.Vector indices) { throw null; } diff --git a/src/runtime/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj b/src/runtime/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj index c557f7e3b4a0..6fa7eb235138 100644 --- a/src/runtime/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj +++ b/src/runtime/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj @@ -107,14 +107,4 @@ - - - - - - - - - - diff --git a/src/runtime/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/runtime/src/libraries/System.Runtime/ref/System.Runtime.cs index 7b7355e58099..82ad6d08c9ed 100644 --- a/src/runtime/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/runtime/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -14127,6 +14127,7 @@ public static partial class RuntimeHelpers [System.ObsoleteAttribute("OffsetToStringData has been deprecated. Use string.GetPinnableReference() instead.")] public static int OffsetToStringData { get { throw null; } } public static System.IntPtr AllocateTypeAssociatedMemory(System.Type type, int size) { throw null; } + public static System.IntPtr AllocateTypeAssociatedMemory(System.Type type, int size, int alignment) { throw null; } public static object? Box(ref byte target, System.RuntimeTypeHandle type) { throw null; } public static System.ReadOnlySpan CreateSpan(System.RuntimeFieldHandle fldHandle) { throw null; } public static void EnsureSufficientExecutionStack() { } diff --git a/src/runtime/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csproj b/src/runtime/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csproj index 82f488a46765..50f683fee3e1 100644 --- a/src/runtime/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csproj +++ b/src/runtime/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/System.IO.FileSystem.Tests.csproj @@ -9,7 +9,7 @@ 1 true - + 01:15:00 diff --git a/src/runtime/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Runtime/CompilerServices/RuntimeHelpersTests.cs b/src/runtime/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Runtime/CompilerServices/RuntimeHelpersTests.cs index 347c01b7a3c4..2076198d225a 100644 --- a/src/runtime/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Runtime/CompilerServices/RuntimeHelpersTests.cs +++ b/src/runtime/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Runtime/CompilerServices/RuntimeHelpersTests.cs @@ -446,9 +446,49 @@ public static void AllocateTypeAssociatedMemoryInvalidArguments() public static unsafe void AllocateTypeAssociatedMemoryValidArguments() { IntPtr memory = RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(RuntimeHelpersTests), 32); + + // Validate that the allocation succeeded + Assert.NotEqual(memory, IntPtr.Zero); + + // Validate that the memory is zeroed out + Assert.True(new Span((void*)memory, 32).SequenceEqual(new byte[32])); + } + + [Fact] + public static void AllocateTypeAssociatedMemoryAlignedInvalidArguments() + { + Assert.Throws(() => { RuntimeHelpers.AllocateTypeAssociatedMemory(null, 10, 1); }); + Assert.Throws(() => { RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(RuntimeHelpersTests), -1, 1); }); + Assert.Throws(() => { RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(RuntimeHelpersTests), 10, 0); }); + Assert.Throws(() => { RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(RuntimeHelpersTests), 10, 3); }); + } + + [Theory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + [InlineData(8)] // .NET largest natural alignment + [InlineData(16)] // V128, typical max_align_t + [InlineData(32)] // V256 + [InlineData(64)] // V512, typical cache line size + [InlineData(128)] // less typical cache line size + [InlineData(512)] // historical disk sector size + [InlineData(4096)] // typical disk sector and page size + [InlineData(16384)] // less typical disk sector and page size + [InlineData(65536)] // typical texture and buffer alignment for GPU + [InlineData(262144)] // typical non-temporal chunk alignment + public static unsafe void AllocateTypeAssociatedMemoryAlignedValidArguments(int alignment) + { + IntPtr memory = RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(RuntimeHelpersTests), 32, alignment); + + // Validate that the allocation succeeded Assert.NotEqual(memory, IntPtr.Zero); + // Validate that the memory is zeroed out Assert.True(new Span((void*)memory, 32).SequenceEqual(new byte[32])); + + // Validate that the memory is aligned + Assert.True((memory % alignment) == 0); } #pragma warning disable CS0649 diff --git a/src/runtime/src/libraries/sendtohelix-browser.targets b/src/runtime/src/libraries/sendtohelix-browser.targets index fe3efe43b7a0..7c37ece04737 100644 --- a/src/runtime/src/libraries/sendtohelix-browser.targets +++ b/src/runtime/src/libraries/sendtohelix-browser.targets @@ -207,6 +207,9 @@ + + + diff --git a/src/runtime/src/libraries/tests.proj b/src/runtime/src/libraries/tests.proj index 944688f50c6c..821f7e0a3245 100644 --- a/src/runtime/src/libraries/tests.proj +++ b/src/runtime/src/libraries/tests.proj @@ -66,10 +66,6 @@ - - - - @@ -296,7 +292,7 @@ - + @@ -330,8 +326,8 @@ - - + + @@ -403,6 +399,10 @@ + + + @@ -536,6 +536,8 @@ + + @@ -629,9 +631,9 @@ - + - + false - - true - .wasm - .dll - true - _framework - full - - <_WasmGenerateAppBundleDependsOn>_GetWasmGenerateAppBundleDependencies;$(_WasmGenerateAppBundleDependsOn) <_ExtraTrimmerArgs Condition="'$(WasmEnableSIMD)' != 'false'">$(_ExtraTrimmerArgs) --substitutions "$(MSBuildThisFileDirectory)ILLink.Substitutions.WasmIntrinsics.xml" <_ExtraTrimmerArgs Condition="'$(WasmEnableSIMD)' == 'false'">$(_ExtraTrimmerArgs) --substitutions "$(MSBuildThisFileDirectory)ILLink.Substitutions.NoWasmIntrinsics.xml" @@ -77,114 +58,6 @@ - - - - - <_HasDotnetWasm Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.native.wasm'">true - <_HasDotnetJsWorker Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.native.worker.mjs'">true - <_HasDotnetJsSymbols Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.native.js.symbols'">true - <_HasDotnetNativeJs Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.native.js'">true - <_WasmIcuDataFileName Condition="'$(WasmIcuDataFileName)' != '' and Exists('$(WasmIcuDataFileName)')">$(WasmIcuDataFileName) - <_WasmIcuDataFileName Condition="'$(WasmIcuDataFileName)' != '' and !Exists('$(WasmIcuDataFileName)')">$(MicrosoftNetCoreAppRuntimePackRidNativeDir)$(WasmIcuDataFileName) - - - - - - - - - - - - - - - - - - <_IcuAvailableDataFiles Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)icudt_*" Exclude="$(_WasmIcuDataFileName)"/> - - - - - - - - - - - - - - - <_WasmPThreadPoolInitialSize Condition="'$(_WasmPThreadPoolInitialSize)' == ''">-1 - <_WasmPThreadPoolUnusedSize Condition="'$(_WasmPThreadPoolUnusedSize)' == ''">-1 - <_WasmIsPublishing Condition="'$(_WasmIsPublishing)' == '' and '$(_IsPublishing)' != ''">$(_IsPublishing) - - <_WasmAppBuilderBootConfigFileName>$(WasmBootConfigFileName) - <_WasmAppBuilderBootConfigFileName Condition="'$(_WasmAppBuilderBootConfigFileName)' == ''">dotnet.boot.js - - - - - - - - - - - - - - - - - - - - @@ -534,6 +407,7 @@ + diff --git a/src/runtime/src/mono/browser/build/README.md b/src/runtime/src/mono/browser/build/README.md index 495e8020b76a..c2c987587057 100644 --- a/src/runtime/src/mono/browser/build/README.md +++ b/src/runtime/src/mono/browser/build/README.md @@ -88,7 +88,6 @@ The various task inputs correspond to properties as: AppDir : $(WasmAppDir) MainAssembly : $(WasmMainAssemblyPath) - InvariantGlobalization : $(WasmInvariantGlobalization) SatelliteAssemblies : @(WasmSatelliteAssemblies) FilesToIncludeInFileSystem : @(WasmFilesToIncludeInFileSystem) DebugLevel : $(WasmDebugLevel) diff --git a/src/runtime/src/mono/browser/build/WasmApp.InTree.props b/src/runtime/src/mono/browser/build/WasmApp.InTree.props index d81cd25b023b..2fef6aa17d99 100644 --- a/src/runtime/src/mono/browser/build/WasmApp.InTree.props +++ b/src/runtime/src/mono/browser/build/WasmApp.InTree.props @@ -1,12 +1,28 @@ + true + $(MSBuildThisFileDirectory) $([MSBuild]::NormalizeDirectory($(MonoProjectRoot), 'wasm', 'build')) + + <_WebAssemblyPropsFile Condition="'$(_WebAssemblyPropsFile)' == ''">$(MonoProjectRoot)\nuget\Microsoft.NET.Sdk.WebAssembly.Pack\build\Microsoft.NET.Sdk.WebAssembly.Browser.props + <_WebAssemblyTargetsFile Condition="'$(_WebAssemblyTargetsFile)' == ''">$(MonoProjectRoot)\nuget\Microsoft.NET.Sdk.WebAssembly.Pack\build\Microsoft.NET.Sdk.WebAssembly.Browser.targets + <_WebAssemblySdkToolsDirectory Condition="'$(_WebAssemblySdkToolsDirectory)' == ''">$(ArtifactsBinDir)\Microsoft.NET.Sdk.WebAssembly.Pack.Tasks\$(RuntimeConfiguration)\ + + + + library + + true + + + + true AnyCPU false diff --git a/src/runtime/src/mono/browser/build/WasmApp.InTree.targets b/src/runtime/src/mono/browser/build/WasmApp.InTree.targets index 76de4a1b9741..fd7704093652 100644 --- a/src/runtime/src/mono/browser/build/WasmApp.InTree.targets +++ b/src/runtime/src/mono/browser/build/WasmApp.InTree.targets @@ -3,38 +3,14 @@ + + - - - - <_WasmMainJSFileName>$([System.IO.Path]::GetFileName('$(WasmMainJSPath)')) - - - - - - - - - - - - - - - - - - + diff --git a/src/runtime/src/mono/mono/mini/aot-runtime.c b/src/runtime/src/mono/mono/mini/aot-runtime.c index 4fee51a0ec0f..3309eb796b0b 100644 --- a/src/runtime/src/mono/mono/mini/aot-runtime.c +++ b/src/runtime/src/mono/mono/mini/aot-runtime.c @@ -1622,6 +1622,7 @@ open_aot_data (MonoAssembly *assembly, MonoAotFileInfo *info, void **ret_handle) data = (guint8*)mono_file_map (info->datafile_size, MONO_MMAP_READ, mono_file_map_fd (map), 0, ret_handle); g_assert (data); + g_free(filename); return data; } @@ -2708,8 +2709,10 @@ mono_aot_get_class_from_name (MonoImage *image, const char *name_space, const ch table_size = amodule->class_name_table [0]; table = amodule->class_name_table + 1; - if (table_size == 0) + if (table_size == 0) { + amodule_unlock (amodule); return FALSE; + } if (name_space [0] == '\0') full_name = g_strdup_printf ("%s", name); diff --git a/src/runtime/src/mono/mono/utils/mono-utility-thread.c b/src/runtime/src/mono/mono/utils/mono-utility-thread.c index 68e9ba4621a7..368230ad7535 100644 --- a/src/runtime/src/mono/mono/utils/mono-utility-thread.c +++ b/src/runtime/src/mono/mono/utils/mono-utility-thread.c @@ -152,7 +152,7 @@ mono_utility_thread_send_sync (MonoUtilityThread *thread, gpointer message) mono_os_sem_init (&sem, 0); UtilityThreadQueueEntry *entry = (UtilityThreadQueueEntry*)mono_lock_free_alloc (&thread->message_allocator); - gboolean done; + gboolean done = FALSE; entry->finished = &done; entry->response_sem = &sem; diff --git a/src/runtime/src/mono/msbuild/apple/build/AppleBuild.InTree.targets b/src/runtime/src/mono/msbuild/apple/build/AppleBuild.InTree.targets index 653c84a59739..37bc5fed8830 100644 --- a/src/runtime/src/mono/msbuild/apple/build/AppleBuild.InTree.targets +++ b/src/runtime/src/mono/msbuild/apple/build/AppleBuild.InTree.targets @@ -33,19 +33,4 @@ - - - - - $([MSBuild]::NormalizePath('$(Crossgen2InBuildDir)', 'crossgen2$(ExeSuffix)')) - - - - - - diff --git a/src/runtime/src/mono/msbuild/apple/build/AppleBuild.ReadyToRun.targets b/src/runtime/src/mono/msbuild/apple/build/AppleBuild.ReadyToRun.targets new file mode 100644 index 000000000000..1bfe6b140f2c --- /dev/null +++ b/src/runtime/src/mono/msbuild/apple/build/AppleBuild.ReadyToRun.targets @@ -0,0 +1,17 @@ + + + + + $([MSBuild]::NormalizePath('$(Crossgen2InBuildDir)', 'crossgen2$(ExeSuffix)')) + + + + + + + diff --git a/src/runtime/src/mono/msbuild/apple/build/AppleBuild.props b/src/runtime/src/mono/msbuild/apple/build/AppleBuild.props index ba3ff16ac723..f798429007f3 100644 --- a/src/runtime/src/mono/msbuild/apple/build/AppleBuild.props +++ b/src/runtime/src/mono/msbuild/apple/build/AppleBuild.props @@ -9,6 +9,24 @@ true + + true + macho + + + + + + + + + + $(AfterMicrosoftNETSdkTargets);$(Crossgen2SdkOverrideTargetsPath) + $(AfterMicrosoftNETSdkTargets);$(MonoProjectRoot)\msbuild\apple\build\AppleBuild.ReadyToRun.targets + + true $(TargetOS)-$(TargetArchitecture.ToLowerInvariant()) diff --git a/src/runtime/src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Sdk/Sdk/Sdk.props b/src/runtime/src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Sdk/Sdk/Sdk.props index 53dfe5e48eac..5cf994ce01a9 100644 --- a/src/runtime/src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Sdk/Sdk/Sdk.props +++ b/src/runtime/src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Sdk/Sdk/Sdk.props @@ -2,7 +2,6 @@ wasm browser - true Exe true diff --git a/src/runtime/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets b/src/runtime/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets index 6f64bf3835ba..bad785110dab 100644 --- a/src/runtime/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets +++ b/src/runtime/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets @@ -55,10 +55,10 @@ Copyright (c) .NET Foundation. All rights reserved. - $(MSBuildThisFileDirectory)..\ + <_WebAssemblySdkToolsDirectory Condition="'$(_WebAssemblySdkToolsDirectory)'==''">$(MSBuildThisFileDirectory)..\tools\ <_WebAssemblySdkTasksTFM Condition=" '$(MSBuildRuntimeType)' == 'Core'">net10.0 <_WebAssemblySdkTasksTFM Condition=" '$(MSBuildRuntimeType)' != 'Core'">net472 - <_WebAssemblySdkTasksAssembly>$(WebAssemblySdkDirectoryRoot)tools\$(_WebAssemblySdkTasksTFM)\Microsoft.NET.Sdk.WebAssembly.Pack.Tasks.dll + <_WebAssemblySdkTasksAssembly Condition="'$(_WebAssemblySdkTasksAssembly)' == ''">$(_WebAssemblySdkToolsDirectory)\$(_WebAssemblySdkTasksTFM)\Microsoft.NET.Sdk.WebAssembly.Pack.Tasks.dll $(CompressionIncludePatterns);_framework\** @@ -141,6 +141,7 @@ Copyright (c) .NET Foundation. All rights reserved. $(GenerateBuildWasmBootJsonDependsOn); GenerateBuildRuntimeConfigurationFiles; + ComputeWasmVfs; ResolveWasmOutputs; _AddWasmDiagnosticPortsEnvironmentVariable; @@ -237,19 +238,52 @@ Copyright (c) .NET Foundation. All rights reserved. - + - - - <_WasmRuntimePackVersion>%(ResolvedRuntimePack.NuGetPackageVersion) - + + + + /%(WasmFilesToIncludeInFileSystem.Identity) + + + + + + + + - + + + + + + + <_WasmFilesToIncludeInFileSystemOriginalAssetsWithChangedIdentity Include="%(_WasmFilesToIncludeInFileSystemStaticWebAsset.OriginalItemSpec)" Condition="'%(_WasmFilesToIncludeInFileSystemStaticWebAsset.OriginalItemSpec)' != '%(_WasmFilesToIncludeInFileSystemStaticWebAsset.Identity)'" /> + + + + + + - + - <_WasmNativeAssetFileNames>;@(WasmNativeAsset->'%(FileName)%(Extension)'); + <_WasmNativeAssetFileNames>;@(WasmNativeAsset->'%(FileName)%(Extension)');@(WasmAssembliesFinal->'%(FileName)%(Extension)'); + <_WasmIntermediateAssemblyFileNames Condition="@(WasmAssembliesFinal->Count()) != 0">;@(IntermediateAssembly->'%(FileName)%(Extension)'); @@ -257,6 +291,14 @@ Copyright (c) .NET Foundation. All rights reserved. + + + <_WasmProjectAssemblyBuild Include="@(WasmAssembliesFinal)" Condition="$(_WasmIntermediateAssemblyFileNames.Contains(';%(FileName)%(Extension);'))" /> + <_WasmProjectAssemblyBuild Include="@(IntermediateAssembly)" Condition="@(_WasmProjectAssemblyBuild->Count()) == 0" /> + <_WasmBuildAssetCandidates Include="@(ReferenceCopyLocalPaths)" /> + <_WasmBuildAssetCandidates Include="@(WasmNativeAsset)" /> + <_WasmBuildAssetCandidates Include="@(WasmAssembliesFinal)" /> + <_WasmBuildAssetCandidates Remove="@(_WasmProjectAssemblyBuild)" /> @@ -265,9 +307,9 @@ Copyright (c) .NET Foundation. All rights reserved. - <_WasmDotnetJsForBuild Include="@(ReferenceCopyLocalPaths)" Condition="'%(FileName)%(Extension)' == 'dotnet.js'" /> + <_WasmDotnetJsForBuild Include="@(_WasmBuildAssetCandidates)" Condition="'%(FileName)%(Extension)' == 'dotnet.js'" /> <_BuildAssetsCandidates Remove="@(_WasmDotnetJsForBuild)" /> @@ -340,43 +382,11 @@ Copyright (c) .NET Foundation. All rights reserved. > - - - - /%(WasmFilesToIncludeInFileSystem.Identity) - - - - - - - - - - - - - - - - @@ -620,7 +630,7 @@ Copyright (c) .NET Foundation. All rights reserved. BeforeTargets="PrepareForPublish" /> - + - - - - $(Crossgen2SdkOverrideTargetsPath) - $(AfterMicrosoftNETSdkTargets);$(MonoProjectRoot)\msbuild\apple\build\AppleBuild.InTree.targets - diff --git a/src/runtime/src/mono/sample/mbr/browser/WasmDelta.csproj b/src/runtime/src/mono/sample/mbr/browser/WasmDelta.csproj index 162a8f9a2ac9..6fbdf7b9c0c4 100644 --- a/src/runtime/src/mono/sample/mbr/browser/WasmDelta.csproj +++ b/src/runtime/src/mono/sample/mbr/browser/WasmDelta.csproj @@ -36,10 +36,6 @@ - - - - diff --git a/src/runtime/src/mono/sample/mbr/browser/index.html b/src/runtime/src/mono/sample/mbr/browser/wwwroot/index.html similarity index 100% rename from src/runtime/src/mono/sample/mbr/browser/index.html rename to src/runtime/src/mono/sample/mbr/browser/wwwroot/index.html diff --git a/src/runtime/src/mono/sample/mbr/browser/main.js b/src/runtime/src/mono/sample/mbr/browser/wwwroot/main.js similarity index 100% rename from src/runtime/src/mono/sample/mbr/browser/main.js rename to src/runtime/src/mono/sample/mbr/browser/wwwroot/main.js diff --git a/src/runtime/src/mono/sample/wasm/DefaultBrowserSample.targets b/src/runtime/src/mono/sample/wasm/DefaultBrowserSample.targets index af224ce9c48a..5ed470f3918a 100644 --- a/src/runtime/src/mono/sample/wasm/DefaultBrowserSample.targets +++ b/src/runtime/src/mono/sample/wasm/DefaultBrowserSample.targets @@ -13,9 +13,5 @@ $(TestArchiveTestsRoot)$(OSPlatformConfig)/ - - - - diff --git a/src/runtime/src/mono/sample/wasm/Directory.Build.props b/src/runtime/src/mono/sample/wasm/Directory.Build.props index ef6268ac4245..7a509c489b84 100644 --- a/src/runtime/src/mono/sample/wasm/Directory.Build.props +++ b/src/runtime/src/mono/sample/wasm/Directory.Build.props @@ -8,13 +8,17 @@ browser-wasm $(NoWarn);IL2121 + + true bin - $(MSBuildProjectDirectory)\bin\$(Configuration)\AppBundle\ + $(MSBuildProjectDirectory)\bin\wwwroot\ + false + true true @@ -35,6 +39,13 @@ + + + + + + + diff --git a/src/runtime/src/mono/sample/wasm/Directory.Build.targets b/src/runtime/src/mono/sample/wasm/Directory.Build.targets index 2711c3345a30..baa756debe46 100644 --- a/src/runtime/src/mono/sample/wasm/Directory.Build.targets +++ b/src/runtime/src/mono/sample/wasm/Directory.Build.targets @@ -48,9 +48,9 @@ $(TargetFileName) " Outputs=" - bin/$(Configuration)/AppBundle/dotnet.native.wasm; - bin/$(Configuration)/AppBundle/dotnet.native.js; - bin/$(Configuration)/AppBundle/$(_WasmMainJSFileName); + bin/$(Configuration)/publish/wwwroot/_framework/dotnet.native.wasm; + bin/$(Configuration)/publish/wwwroot/_framework/dotnet.native.js; + bin/$(Configuration)/publish/wwwroot/$(_WasmMainJSFileName); "> <_ScriptExt Condition="'$(OS)' == 'Windows_NT'">.cmd @@ -79,23 +79,23 @@ - + - + - + - + - + browser:callspec=N:Sample - - ./ <_ExtraTrimmerArgs>$(_ExtraTrimmerArgs) --dump-dependencies - - diff --git a/src/runtime/src/mono/sample/wasm/browser-advanced/advanced-sample.lib.module.js b/src/runtime/src/mono/sample/wasm/browser-advanced/wwwroot/advanced-sample.lib.module.js similarity index 100% rename from src/runtime/src/mono/sample/wasm/browser-advanced/advanced-sample.lib.module.js rename to src/runtime/src/mono/sample/wasm/browser-advanced/wwwroot/advanced-sample.lib.module.js diff --git a/src/runtime/src/mono/sample/wasm/browser-advanced/index.html b/src/runtime/src/mono/sample/wasm/browser-advanced/wwwroot/index.html similarity index 100% rename from src/runtime/src/mono/sample/wasm/browser-advanced/index.html rename to src/runtime/src/mono/sample/wasm/browser-advanced/wwwroot/index.html diff --git a/src/runtime/src/mono/sample/wasm/browser-advanced/main.js b/src/runtime/src/mono/sample/wasm/browser-advanced/wwwroot/main.js similarity index 96% rename from src/runtime/src/mono/sample/wasm/browser-advanced/main.js rename to src/runtime/src/mono/sample/wasm/browser-advanced/wwwroot/main.js index 016a3771aa08..02996c2f0be9 100644 --- a/src/runtime/src/mono/sample/wasm/browser-advanced/main.js +++ b/src/runtime/src/mono/sample/wasm/browser-advanced/wwwroot/main.js @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -import { dotnet, exit } from './dotnet.js' +import { dotnet, exit } from './_framework/dotnet.js' function add(a, b) { return a + b; @@ -40,12 +40,11 @@ try { maxParallelDownloads: 1, resources: { modulesAfterConfigLoaded: [{ - "name": "advanced-sample.lib.module.js" + "name": "../advanced-sample.lib.module.js" }] } }) .withModuleConfig({ - configSrc: "./dotnet.boot.js", onConfigLoaded: (config) => { // This is called during emscripten `dotnet.wasm` instantiation, after we fetched config. console.log('user code Module.onConfigLoaded'); @@ -72,7 +71,7 @@ try { }) .withResourceLoader((type, name, defaultUri, integrity, behavior) => { // loadBootResource could return string with unqualified name of resource. It assumes that we resolve it with document.baseURI - return name; + return `${defaultUri}?v=42`; }); await dotnet.download(); diff --git a/src/runtime/src/mono/sample/wasm/browser-bench/Wasm.Browser.Bench.Sample.csproj b/src/runtime/src/mono/sample/wasm/browser-bench/Wasm.Browser.Bench.Sample.csproj index 01492399d7a6..7fd0700ccad5 100644 --- a/src/runtime/src/mono/sample/wasm/browser-bench/Wasm.Browser.Bench.Sample.csproj +++ b/src/runtime/src/mono/sample/wasm/browser-bench/Wasm.Browser.Bench.Sample.csproj @@ -8,13 +8,13 @@ $(EnableAOTAndTrimming) $(EnableAOTAndTrimming) $(EnableAOTAndTrimming) - ./ + false true - $(MSBuildThisFileDirectory)/bin/$(Configuration)/AppBundle + $(MSBuildThisFileDirectory)/bin/$(Configuration)/publish/wwwroot none false false @@ -35,11 +35,6 @@ - - - - - @@ -110,7 +105,7 @@ + DestinationFolder="$(MSBuildThisFileDirectory)/bin/$(Configuration)/wwwroot/blazor-template/%(RecursiveDir)" /> @@ -147,6 +142,6 @@ + DestinationFolder="$(MSBuildThisFileDirectory)/bin/$(Configuration)/wwwroot/browser-template/%(RecursiveDir)" /> diff --git a/src/runtime/src/mono/sample/wasm/browser-bench/appstart-frame.html b/src/runtime/src/mono/sample/wasm/browser-bench/wwwroot/appstart-frame.html similarity index 60% rename from src/runtime/src/mono/sample/wasm/browser-bench/appstart-frame.html rename to src/runtime/src/mono/sample/wasm/browser-bench/wwwroot/appstart-frame.html index 196f12fa1cef..263a9c5bc8f9 100644 --- a/src/runtime/src/mono/sample/wasm/browser-bench/appstart-frame.html +++ b/src/runtime/src/mono/sample/wasm/browser-bench/wwwroot/appstart-frame.html @@ -8,10 +8,9 @@ - - - - + + + diff --git a/src/runtime/src/mono/sample/wasm/browser-bench/frame-main.js b/src/runtime/src/mono/sample/wasm/browser-bench/wwwroot/frame-main.js similarity index 96% rename from src/runtime/src/mono/sample/wasm/browser-bench/frame-main.js rename to src/runtime/src/mono/sample/wasm/browser-bench/wwwroot/frame-main.js index 14b56fbcb02e..23f76c03dda5 100644 --- a/src/runtime/src/mono/sample/wasm/browser-bench/frame-main.js +++ b/src/runtime/src/mono/sample/wasm/browser-bench/wwwroot/frame-main.js @@ -3,7 +3,7 @@ "use strict"; -import { dotnet, exit } from './dotnet.js' +import { dotnet, exit } from './_framework/dotnet.js' class FrameApp { async init({ getAssemblyExports }) { diff --git a/src/runtime/src/mono/sample/wasm/browser-bench/index.html b/src/runtime/src/mono/sample/wasm/browser-bench/wwwroot/index.html similarity index 100% rename from src/runtime/src/mono/sample/wasm/browser-bench/index.html rename to src/runtime/src/mono/sample/wasm/browser-bench/wwwroot/index.html diff --git a/src/runtime/src/mono/sample/wasm/browser-bench/main.js b/src/runtime/src/mono/sample/wasm/browser-bench/wwwroot/main.js similarity index 99% rename from src/runtime/src/mono/sample/wasm/browser-bench/main.js rename to src/runtime/src/mono/sample/wasm/browser-bench/wwwroot/main.js index 393349c9a020..5c08e83b8db5 100644 --- a/src/runtime/src/mono/sample/wasm/browser-bench/main.js +++ b/src/runtime/src/mono/sample/wasm/browser-bench/wwwroot/main.js @@ -3,7 +3,7 @@ "use strict"; -import { dotnet, exit } from './dotnet.js' +import { dotnet, exit } from './_framework/dotnet.js' let runBenchmark; let setTasks; diff --git a/src/runtime/src/mono/sample/wasm/browser-bench/style.css b/src/runtime/src/mono/sample/wasm/browser-bench/wwwroot/style.css similarity index 100% rename from src/runtime/src/mono/sample/wasm/browser-bench/style.css rename to src/runtime/src/mono/sample/wasm/browser-bench/wwwroot/style.css diff --git a/src/runtime/src/mono/sample/wasm/browser-eventpipe/Wasm.Browser.EventPipe.Sample.csproj b/src/runtime/src/mono/sample/wasm/browser-eventpipe/Wasm.Browser.EventPipe.Sample.csproj index ae39ccb15196..30f6c3e4e41c 100644 --- a/src/runtime/src/mono/sample/wasm/browser-eventpipe/Wasm.Browser.EventPipe.Sample.csproj +++ b/src/runtime/src/mono/sample/wasm/browser-eventpipe/Wasm.Browser.EventPipe.Sample.csproj @@ -12,7 +12,4 @@ false - - - diff --git a/src/runtime/src/mono/sample/wasm/browser-eventpipe/index.html b/src/runtime/src/mono/sample/wasm/browser-eventpipe/wwwroot/index.html similarity index 100% rename from src/runtime/src/mono/sample/wasm/browser-eventpipe/index.html rename to src/runtime/src/mono/sample/wasm/browser-eventpipe/wwwroot/index.html diff --git a/src/runtime/src/mono/sample/wasm/browser-eventpipe/main.js b/src/runtime/src/mono/sample/wasm/browser-eventpipe/wwwroot/main.js similarity index 100% rename from src/runtime/src/mono/sample/wasm/browser-eventpipe/main.js rename to src/runtime/src/mono/sample/wasm/browser-eventpipe/wwwroot/main.js diff --git a/src/runtime/src/mono/sample/wasm/browser-logprofile/Wasm.BrowserLogProfile.Sample.csproj b/src/runtime/src/mono/sample/wasm/browser-logprofile/Wasm.BrowserLogProfile.Sample.csproj index fcc6164c1331..a3bb84fab154 100644 --- a/src/runtime/src/mono/sample/wasm/browser-logprofile/Wasm.BrowserLogProfile.Sample.csproj +++ b/src/runtime/src/mono/sample/wasm/browser-logprofile/Wasm.BrowserLogProfile.Sample.csproj @@ -6,10 +6,5 @@ false - - - - - diff --git a/src/runtime/src/mono/sample/wasm/browser-logprofile/index.html b/src/runtime/src/mono/sample/wasm/browser-logprofile/wwwroot/index.html similarity index 100% rename from src/runtime/src/mono/sample/wasm/browser-logprofile/index.html rename to src/runtime/src/mono/sample/wasm/browser-logprofile/wwwroot/index.html diff --git a/src/runtime/src/mono/sample/wasm/browser-logprofile/main.js b/src/runtime/src/mono/sample/wasm/browser-logprofile/wwwroot/main.js similarity index 100% rename from src/runtime/src/mono/sample/wasm/browser-logprofile/main.js rename to src/runtime/src/mono/sample/wasm/browser-logprofile/wwwroot/main.js diff --git a/src/runtime/src/mono/sample/wasm/browser-minimal-config/Program.cs b/src/runtime/src/mono/sample/wasm/browser-minimal-config/Program.cs deleted file mode 100644 index aeefa0966c4f..000000000000 --- a/src/runtime/src/mono/sample/wasm/browser-minimal-config/Program.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Runtime.InteropServices.JavaScript; -using System.Runtime.InteropServices; - -namespace Sample -{ - public partial class Test - { - public static int Main(string[] args) - { - Console.WriteLine("Hello minimal config"); - return 0; - } - } -} diff --git a/src/runtime/src/mono/sample/wasm/browser-minimal-config/Wasm.Browser.Config.Sample.csproj b/src/runtime/src/mono/sample/wasm/browser-minimal-config/Wasm.Browser.Config.Sample.csproj deleted file mode 100644 index c970c6c11f25..000000000000 --- a/src/runtime/src/mono/sample/wasm/browser-minimal-config/Wasm.Browser.Config.Sample.csproj +++ /dev/null @@ -1,9 +0,0 @@ - - - - false - - - - - diff --git a/src/runtime/src/mono/sample/wasm/browser-minimal-config/index.html b/src/runtime/src/mono/sample/wasm/browser-minimal-config/index.html deleted file mode 100644 index f5f16265cd51..000000000000 --- a/src/runtime/src/mono/sample/wasm/browser-minimal-config/index.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - Wasm Browser Sample - - - - - - - - - - \ No newline at end of file diff --git a/src/runtime/src/mono/sample/wasm/browser-minimal-config/main.js b/src/runtime/src/mono/sample/wasm/browser-minimal-config/main.js deleted file mode 100644 index 702234c984df..000000000000 --- a/src/runtime/src/mono/sample/wasm/browser-minimal-config/main.js +++ /dev/null @@ -1,86 +0,0 @@ -import { dotnet } from "./_framework/dotnet.js"; -import * as runtime from "./_framework/dotnet.runtime.js"; - -async function fetchBinary(url) { - return (await fetch(url, { cache: "no-cache" })).arrayBuffer(); -} - -function fetchWasm(url) { - return { - response: fetch(url, { cache: "no-cache" }), - url, - name: url.substring(url.lastIndexOf("/") + 1) - }; -} - -const assets = [ - { - name: "dotnet.native.js", - // demo dynamic import - moduleExports: import("./_framework/dotnet.native.js"), - behavior: "js-module-native" - }, - { - name: "dotnet.runtime.js", - // demo static import - moduleExports: runtime, - behavior: "js-module-runtime" - }, - { - name: "dotnet.native.wasm", - // demo pending download promise - pendingDownload: fetchWasm("./_framework/dotnet.native.wasm"), - behavior: "dotnetwasm" - }, - { - name: "System.Private.CoreLib.wasm", - behavior: "assembly", - isCore: true, - }, - { - name: "System.Runtime.InteropServices.JavaScript.wasm", - behavior: "assembly", - isCore: true, - }, - { - name: "Wasm.Browser.Config.Sample.wasm", - // demo buffer promise - buffer: fetchBinary("./_framework/Wasm.Browser.Config.Sample.wasm"), - behavior: "assembly" - }, - { - name: "System.Console.wasm", - behavior: "assembly" - }, -]; - -const resources = { - "jsModuleNative": { - "dotnet.native.js": "" - }, - "jsModuleRuntime": { - "dotnet.runtime.js": "" - }, - "wasmNative": { - "dotnet.native.wasm": "" - }, - "coreAssembly": { - "System.Private.CoreLib.wasm": "", - "System.Runtime.InteropServices.JavaScript.wasm": "", - }, - "assembly": { - "System.Console.wasm": "", - "Wasm.Browser.Config.Sample.wasm": "" - }, -}; - -const config = { - "mainAssemblyName": "Wasm.Browser.Config.Sample.dll", - assets, -}; - -await dotnet - .withConfig(config) - .withElementOnExit() - .withExitCodeLogging() - .run(); diff --git a/src/runtime/src/mono/sample/wasm/browser-profile/Wasm.BrowserProfile.Sample.csproj b/src/runtime/src/mono/sample/wasm/browser-profile/Wasm.BrowserProfile.Sample.csproj index 81f03cdc9878..edfead643583 100644 --- a/src/runtime/src/mono/sample/wasm/browser-profile/Wasm.BrowserProfile.Sample.csproj +++ b/src/runtime/src/mono/sample/wasm/browser-profile/Wasm.BrowserProfile.Sample.csproj @@ -3,11 +3,5 @@ true aot; - - - - - - diff --git a/src/runtime/src/mono/sample/wasm/browser-profile/index.html b/src/runtime/src/mono/sample/wasm/browser-profile/wwwroot/index.html similarity index 100% rename from src/runtime/src/mono/sample/wasm/browser-profile/index.html rename to src/runtime/src/mono/sample/wasm/browser-profile/wwwroot/index.html diff --git a/src/runtime/src/mono/sample/wasm/browser-profile/main.js b/src/runtime/src/mono/sample/wasm/browser-profile/wwwroot/main.js similarity index 100% rename from src/runtime/src/mono/sample/wasm/browser-profile/main.js rename to src/runtime/src/mono/sample/wasm/browser-profile/wwwroot/main.js diff --git a/src/runtime/src/mono/sample/wasm/browser-shutdown/Wasm.Browser.Shutdown.Sample.csproj b/src/runtime/src/mono/sample/wasm/browser-shutdown/Wasm.Browser.Shutdown.Sample.csproj index 365ba7276cb0..65bd5641a20f 100644 --- a/src/runtime/src/mono/sample/wasm/browser-shutdown/Wasm.Browser.Shutdown.Sample.csproj +++ b/src/runtime/src/mono/sample/wasm/browser-shutdown/Wasm.Browser.Shutdown.Sample.csproj @@ -1,6 +1,3 @@ - - - diff --git a/src/runtime/src/mono/sample/wasm/browser-shutdown/index.html b/src/runtime/src/mono/sample/wasm/browser-shutdown/wwwroot/index.html similarity index 100% rename from src/runtime/src/mono/sample/wasm/browser-shutdown/index.html rename to src/runtime/src/mono/sample/wasm/browser-shutdown/wwwroot/index.html diff --git a/src/runtime/src/mono/sample/wasm/browser-shutdown/main.js b/src/runtime/src/mono/sample/wasm/browser-shutdown/wwwroot/main.js similarity index 100% rename from src/runtime/src/mono/sample/wasm/browser-shutdown/main.js rename to src/runtime/src/mono/sample/wasm/browser-shutdown/wwwroot/main.js diff --git a/src/runtime/src/mono/sample/wasm/browser-threads/Wasm.Browser.Threads.Sample.csproj b/src/runtime/src/mono/sample/wasm/browser-threads/Wasm.Browser.Threads.Sample.csproj index a080f787cb46..95f97960be06 100644 --- a/src/runtime/src/mono/sample/wasm/browser-threads/Wasm.Browser.Threads.Sample.csproj +++ b/src/runtime/src/mono/sample/wasm/browser-threads/Wasm.Browser.Threads.Sample.csproj @@ -4,10 +4,6 @@ - - - - diff --git a/src/runtime/src/mono/sample/wasm/browser-threads/index.html b/src/runtime/src/mono/sample/wasm/browser-threads/wwwroot/index.html similarity index 100% rename from src/runtime/src/mono/sample/wasm/browser-threads/index.html rename to src/runtime/src/mono/sample/wasm/browser-threads/wwwroot/index.html diff --git a/src/runtime/src/mono/sample/wasm/browser-threads/main.js b/src/runtime/src/mono/sample/wasm/browser-threads/wwwroot/main.js similarity index 100% rename from src/runtime/src/mono/sample/wasm/browser-threads/main.js rename to src/runtime/src/mono/sample/wasm/browser-threads/wwwroot/main.js diff --git a/src/runtime/src/mono/sample/wasm/browser/Wasm.Browser.Sample.csproj b/src/runtime/src/mono/sample/wasm/browser/Wasm.Browser.Sample.csproj index 365ba7276cb0..65bd5641a20f 100644 --- a/src/runtime/src/mono/sample/wasm/browser/Wasm.Browser.Sample.csproj +++ b/src/runtime/src/mono/sample/wasm/browser/Wasm.Browser.Sample.csproj @@ -1,6 +1,3 @@ - - - diff --git a/src/runtime/src/mono/sample/wasm/browser/index.html b/src/runtime/src/mono/sample/wasm/browser/wwwroot/index.html similarity index 100% rename from src/runtime/src/mono/sample/wasm/browser/index.html rename to src/runtime/src/mono/sample/wasm/browser/wwwroot/index.html diff --git a/src/runtime/src/mono/sample/wasm/browser/main.js b/src/runtime/src/mono/sample/wasm/browser/wwwroot/main.js similarity index 100% rename from src/runtime/src/mono/sample/wasm/browser/main.js rename to src/runtime/src/mono/sample/wasm/browser/wwwroot/main.js diff --git a/src/runtime/src/mono/sample/wasm/console-node/Wasm.Console.Node.Sample.csproj b/src/runtime/src/mono/sample/wasm/console-node/Wasm.Console.Node.Sample.csproj index 995e1d3650e2..5e9ae0d965fe 100644 --- a/src/runtime/src/mono/sample/wasm/console-node/Wasm.Console.Node.Sample.csproj +++ b/src/runtime/src/mono/sample/wasm/console-node/Wasm.Console.Node.Sample.csproj @@ -9,9 +9,5 @@ $(ExecXHarnessVar) wasm test --app=. --engine=NodeJS --engine-arg=--stack-trace-limit=1000 --js-file=main.mjs --output-directory=$(XHarnessOutputVar) --expected-exit-code $(ExpectedExitCode) - - - - diff --git a/src/runtime/src/mono/sample/wasm/console-node/main.mjs b/src/runtime/src/mono/sample/wasm/console-node/wwwroot/main.mjs similarity index 100% rename from src/runtime/src/mono/sample/wasm/console-node/main.mjs rename to src/runtime/src/mono/sample/wasm/console-node/wwwroot/main.mjs diff --git a/src/runtime/src/mono/sample/wasm/console-node/package.json b/src/runtime/src/mono/sample/wasm/console-node/wwwroot/package.json similarity index 100% rename from src/runtime/src/mono/sample/wasm/console-node/package.json rename to src/runtime/src/mono/sample/wasm/console-node/wwwroot/package.json diff --git a/src/runtime/src/mono/sample/wasm/simple-raytracer/RayTracer.csproj b/src/runtime/src/mono/sample/wasm/simple-raytracer/RayTracer.csproj index 2930b34255c7..1f5e13af75a2 100644 --- a/src/runtime/src/mono/sample/wasm/simple-raytracer/RayTracer.csproj +++ b/src/runtime/src/mono/sample/wasm/simple-raytracer/RayTracer.csproj @@ -14,9 +14,4 @@ true true - - - - - diff --git a/src/runtime/src/mono/sample/wasm/simple-raytracer/index.html b/src/runtime/src/mono/sample/wasm/simple-raytracer/wwwroot/index.html similarity index 100% rename from src/runtime/src/mono/sample/wasm/simple-raytracer/index.html rename to src/runtime/src/mono/sample/wasm/simple-raytracer/wwwroot/index.html diff --git a/src/runtime/src/mono/sample/wasm/simple-raytracer/main.js b/src/runtime/src/mono/sample/wasm/simple-raytracer/wwwroot/main.js similarity index 100% rename from src/runtime/src/mono/sample/wasm/simple-raytracer/main.js rename to src/runtime/src/mono/sample/wasm/simple-raytracer/wwwroot/main.js diff --git a/src/runtime/src/mono/sample/wasm/wasm.mk b/src/runtime/src/mono/sample/wasm/wasm.mk index c1f2fc6fc534..22db9a0d89fa 100644 --- a/src/runtime/src/mono/sample/wasm/wasm.mk +++ b/src/runtime/src/mono/sample/wasm/wasm.mk @@ -38,14 +38,14 @@ run-browser: echo "The tool dotnet-serve could not be found. Install with: $(DOTNET) tool install --global dotnet-serve"; \ exit 1; \ else \ - $(DOTNET) serve -S -d:bin/$(CONFIG)/AppBundle $(CORS_HEADERS) $(OPEN_BROWSER) -p:8000; \ + $(DOTNET) serve -S -d:bin/$(CONFIG)/wwwroot $(CORS_HEADERS) $(OPEN_BROWSER) -p:8000; \ fi run-console: - cd bin/$(CONFIG)/AppBundle && $(V8_PATH) --stack-trace-limit=1000 --single-threaded $(MAIN_JS) -- $(ARGS) + cd bin/$(CONFIG)/wwwroot && $(V8_PATH) --stack-trace-limit=1000 --single-threaded $(MAIN_JS) -- $(ARGS) run-console-node: - cd bin/$(CONFIG)/AppBundle && node --stack-trace-limit=1000 --single-threaded $(MAIN_JS) $(ARGS) + cd bin/$(CONFIG)/wwwroot && node --stack-trace-limit=1000 --single-threaded $(MAIN_JS) $(ARGS) debug-console-node: - cd bin/$(CONFIG)/AppBundle && node --inspect=9222 --stack-trace-limit=1000 --single-threaded $(MAIN_JS) $(ARGS) \ No newline at end of file + cd bin/$(CONFIG)/wwwroot && node --inspect=9222 --stack-trace-limit=1000 --single-threaded $(MAIN_JS) $(ARGS) \ No newline at end of file diff --git a/src/runtime/src/mono/wasm/build/README.md b/src/runtime/src/mono/wasm/build/README.md index 473ecf376bb5..e759461c8de4 100644 --- a/src/runtime/src/mono/wasm/build/README.md +++ b/src/runtime/src/mono/wasm/build/README.md @@ -88,7 +88,6 @@ The various task inputs correspond to properties as: AppDir : $(WasmAppDir) MainAssembly : $(WasmMainAssemblyPath) - InvariantGlobalization : $(WasmInvariantGlobalization) SatelliteAssemblies : @(WasmSatelliteAssemblies) FilesToIncludeInFileSystem : @(WasmFilesToIncludeInFileSystem) DebugLevel : $(WasmDebugLevel) diff --git a/src/runtime/src/mono/wasm/build/WasmApp.Common.props b/src/runtime/src/mono/wasm/build/WasmApp.Common.props index 9884d97b1d20..ef8a64963d76 100644 --- a/src/runtime/src/mono/wasm/build/WasmApp.Common.props +++ b/src/runtime/src/mono/wasm/build/WasmApp.Common.props @@ -1,7 +1,6 @@ wasm - true diff --git a/src/runtime/src/mono/wasm/build/WasmApp.Common.targets b/src/runtime/src/mono/wasm/build/WasmApp.Common.targets index f990052e8875..1b3fe84a5e2f 100644 --- a/src/runtime/src/mono/wasm/build/WasmApp.Common.targets +++ b/src/runtime/src/mono/wasm/build/WasmApp.Common.targets @@ -913,8 +913,13 @@ + + <_WasmOptPostLinkFileName>$(_WasmOutputFileName) + <_WasmOptPostLinkFileName Condition="'$([System.IO.Path]::IsPathRooted($(_WasmOptPostLinkFileName)))' != 'true'">$([System.IO.Path]::Combine($(_WasmIntermediateOutputPath), $(_WasmOptPostLinkFileName))) + + - diff --git a/src/runtime/src/mono/wasm/data/aot-tests/ProxyProjectForAOTOnHelix.proj b/src/runtime/src/mono/wasm/data/aot-tests/ProxyProjectForAOTOnHelix.proj index f988e1eaa163..b2e6aa06d8da 100644 --- a/src/runtime/src/mono/wasm/data/aot-tests/ProxyProjectForAOTOnHelix.proj +++ b/src/runtime/src/mono/wasm/data/aot-tests/ProxyProjectForAOTOnHelix.proj @@ -62,4 +62,4 @@ - + \ No newline at end of file diff --git a/src/runtime/src/mono/wasm/testassets/WasmBasicTestApp/App/WasmBasicTestApp.csproj b/src/runtime/src/mono/wasm/testassets/WasmBasicTestApp/App/WasmBasicTestApp.csproj index efefe2752921..25a77d37e5b0 100644 --- a/src/runtime/src/mono/wasm/testassets/WasmBasicTestApp/App/WasmBasicTestApp.csproj +++ b/src/runtime/src/mono/wasm/testassets/WasmBasicTestApp/App/WasmBasicTestApp.csproj @@ -27,7 +27,6 @@ - diff --git a/src/runtime/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/AssetsComputingHelper.cs b/src/runtime/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/AssetsComputingHelper.cs index c252142e457e..c5869e14ed77 100644 --- a/src/runtime/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/AssetsComputingHelper.cs +++ b/src/runtime/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/AssetsComputingHelper.cs @@ -54,6 +54,7 @@ public static bool ShouldFilterCandidate( var assetType = candidate.GetMetadata("AssetType"); bool fromMonoPackage = IsFromMonoPackage(candidate); + // A similar logic is in ReadWasmNativeAssetsFromFileSystem target for RuntimeTests reason = extension switch { ".a" when fromMonoPackage => "extension is .a is not supported.", diff --git a/src/runtime/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ComputeWasmBuildAssets.cs b/src/runtime/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ComputeWasmBuildAssets.cs index e35479120284..2eafa7842823 100644 --- a/src/runtime/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ComputeWasmBuildAssets.cs +++ b/src/runtime/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ComputeWasmBuildAssets.cs @@ -66,6 +66,7 @@ public override bool Execute() { var filesToRemove = new List(); var assetCandidates = new List(); + var uniqueFileNames = new HashSet(StringComparer.OrdinalIgnoreCase); try { @@ -151,6 +152,14 @@ public override bool Execute() Log.LogMessage(MessageImportance.Low, "Found satellite assembly '{0}' asset for inferred candidate '{1}' with culture '{2}'", candidate.ItemSpec, relatedAssetPath, culture); } + // Check for unique file name before adding candidate + var candidateFileName = Path.GetFileName(candidate.ItemSpec); + if (!uniqueFileNames.Add(candidateFileName)) + { + Log.LogMessage(MessageImportance.Low, "Skipping duplicate file name '{0}' for candidate '{1}'", candidateFileName, candidate.ItemSpec); + continue; + } + assetCandidates.Add(candidate); } diff --git a/src/runtime/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs b/src/runtime/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs index c5f0417a29a1..f7021c6f6f67 100644 --- a/src/runtime/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs +++ b/src/runtime/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs @@ -359,11 +359,11 @@ private void WriteBootConfig(string entryAssemblyName) { Log.LogMessage(MessageImportance.Low, "Candidate '{0}' is defined as VFS resource '{1}'.", resource.ItemSpec, assetTraitValue); - var targetPath = assetTraitValue.Substring("vfs:".Length); + var targetPath = assetTraitValue.Substring("vfs:".Length).Replace("\\", "/"); resourceData.vfs ??= []; resourceData.vfs[targetPath] = []; - AddResourceToList(resource, resourceData.vfs[targetPath], resourceEndpoint); + AddResourceToList(resource, resourceData.vfs[targetPath], resourceEndpoint.Replace("\\", "/")); } else { diff --git a/src/runtime/src/tasks/WasmAppBuilder/WasmAppBuilder.cs b/src/runtime/src/tasks/WasmAppBuilder/WasmAppBuilder.cs deleted file mode 100644 index 6112ae2a20a6..000000000000 --- a/src/runtime/src/tasks/WasmAppBuilder/WasmAppBuilder.cs +++ /dev/null @@ -1,522 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Diagnostics.CodeAnalysis; -using System.IO; -using System.Linq; -using System.Text; -using System.Text.Encodings.Web; -using System.Text.Json; -using System.Text.Json.Nodes; -using System.Text.Json.Serialization; -using Microsoft.Build.Framework; -using Microsoft.Build.Utilities; -using Microsoft.NET.Sdk.WebAssembly; -using WasmAppBuilder; - -namespace Microsoft.WebAssembly.Build.Tasks; - -public class WasmAppBuilder : WasmAppBuilderBaseTask -{ - public ITaskItem[]? RemoteSources { get; set; } - public bool IncludeThreadsWorker { get; set; } - public int PThreadPoolInitialSize { get; set; } - public int PThreadPoolUnusedSize { get; set; } - public bool UseWebcil { get; set; } - public bool WasmIncludeFullIcuData { get; set; } - public string? WasmIcuDataFileName { get; set; } - public string? RuntimeAssetsLocation { get; set; } - public bool CacheBootResources { get; set; } - public string? DebugLevel { get; set; } - public bool IsPublish { get; set; } - public bool IsAot { get; set; } - public bool IsMultiThreaded { get; set; } - - [Required] - public string ConfigFileName { get; set; } = default!; - - // - // Extra json elements to add to _framework/blazor.boot.json - // - // Metadata: - // - Value: can be a number, bool, quoted string, or json string - // - // Examples: - // - // - // - // - // - public ITaskItem[]? ExtraConfig { get; set; } - - /// - /// Environment variables to set in the boot.json file. - /// - public ITaskItem[]? EnvVariables { get; set; } - - /// - /// List of profilers to use. - /// - public string[]? Profilers { get; set; } - - protected override bool ValidateArguments() - { - if (!base.ValidateArguments()) - return false; - - if (!InvariantGlobalization && (IcuDataFileNames == null || IcuDataFileNames.Length == 0)) - throw new LogAsErrorException($"{nameof(IcuDataFileNames)} property shouldn't be empty when {nameof(InvariantGlobalization)}=false"); - - if (Assemblies.Length == 0) - { - Log.LogError("Cannot build Wasm app without any assemblies"); - return false; - } - - return true; - } - - private GlobalizationMode GetGlobalizationMode() - { - // Invariant has always precedence - if (InvariantGlobalization) - return GlobalizationMode.Invariant; - - // If user provided a path to a custom ICU data file, use it - if (!string.IsNullOrEmpty(WasmIcuDataFileName)) - return GlobalizationMode.Custom; - - // If user requested to include full ICU data, use it - if (WasmIncludeFullIcuData) - return GlobalizationMode.All; - - // Otherwise, use sharded mode - return GlobalizationMode.Sharded; - } - - protected override bool ExecuteInternal() - { - var helper = new BootJsonBuilderHelper(Log, DebugLevel!, IsMultiThreaded, IsPublish); - var logAdapter = new LogAdapter(Log); - - if (!ValidateArguments()) - return false; - - var _assemblies = new List(); - foreach (var asm in Assemblies!) - { - if (!_assemblies.Contains(asm)) - _assemblies.Add(asm); - } - MainAssemblyName = Path.GetFileName(MainAssemblyName); - - var bootConfig = new BootJsonData() - { - mainAssemblyName = MainAssemblyName, - globalizationMode = GetGlobalizationMode().ToString().ToLowerInvariant() - }; - - if (CacheBootResources) - bootConfig.cacheBootResources = CacheBootResources; - - // Create app - var runtimeAssetsPath = !string.IsNullOrEmpty(RuntimeAssetsLocation) - ? Path.Combine(AppDir, RuntimeAssetsLocation) - : AppDir; - - Log.LogMessage(MessageImportance.Low, $"Runtime assets output path {runtimeAssetsPath}"); - - Directory.CreateDirectory(AppDir!); - Directory.CreateDirectory(runtimeAssetsPath); - - if (UseWebcil) - Log.LogMessage(MessageImportance.Normal, "Converting assemblies to Webcil"); - - int baseDebugLevel = helper.GetDebugLevel(false); - - foreach (var assembly in _assemblies) - { - if (UseWebcil) - { - using TempFileName tmpWebcil = new(); - var webcilWriter = Microsoft.WebAssembly.Build.Tasks.WebcilConverter.FromPortableExecutable(inputPath: assembly, outputPath: tmpWebcil.Path, logger: logAdapter); - webcilWriter.ConvertToWebcil(); - var finalWebcil = Path.Combine(runtimeAssetsPath, Path.ChangeExtension(Path.GetFileName(assembly), Utils.WebcilInWasmExtension)); - if (Utils.CopyIfDifferent(tmpWebcil.Path, finalWebcil, useHash: true)) - Log.LogMessage(MessageImportance.Low, $"Generated {finalWebcil} ."); - else - Log.LogMessage(MessageImportance.Low, $"Skipped generating {finalWebcil} as the contents are unchanged."); - _fileWrites.Add(finalWebcil); - } - else - { - FileCopyChecked(assembly, Path.Combine(runtimeAssetsPath, Path.GetFileName(assembly)), "Assemblies"); - } - if (baseDebugLevel != 0) - { - var pdb = assembly; - pdb = Path.ChangeExtension(pdb, ".pdb"); - if (File.Exists(pdb)) - FileCopyChecked(pdb, Path.Combine(runtimeAssetsPath, Path.GetFileName(pdb)), "Assemblies"); - } - } - - foreach (ITaskItem item in NativeAssets) - { - var name = Path.GetFileName(item.ItemSpec); - var dest = Path.Combine(runtimeAssetsPath, name); - if (!FileCopyChecked(item.ItemSpec, dest, "NativeAssets")) - return false; - - if (!IncludeThreadsWorker && name == "dotnet.native.worker.mjs") - continue; - - if (name == "dotnet.runtime.js.map" || name == "dotnet.js.map" || name == "dotnet.diagnostics.js.map") - { - Log.LogMessage(MessageImportance.Low, $"Skipping {item.ItemSpec} from boot config"); - continue; - } - - var itemHash = Utils.ComputeIntegrity(item.ItemSpec); - - Dictionary? resourceList = helper.GetNativeResourceTargetInBootConfig(bootConfig, name); - resourceList?[name] = itemHash; - } - - string packageJsonPath = Path.Combine(AppDir, "package.json"); - if (!File.Exists(packageJsonPath)) - { - var json = @"{ ""type"":""module"" }"; - File.WriteAllText(packageJsonPath, json); - } - - ResourcesData resources = (ResourcesData)bootConfig.resources; - - foreach (var assembly in _assemblies) - { - string assemblyPath = assembly; - var bytes = File.ReadAllBytes(assemblyPath); - // for the is IL IsAssembly check we need to read the bytes from the original DLL - if (!Utils.IsManagedAssembly(bytes)) - { - Log.LogMessage(MessageImportance.Low, "Skipping non-assembly file: " + assemblyPath); - } - else - { - if (UseWebcil) - { - assemblyPath = Path.Combine(runtimeAssetsPath, Path.ChangeExtension(Path.GetFileName(assembly), Utils.WebcilInWasmExtension)); - // For the hash, read the bytes from the webcil file, not the dll file. - bytes = File.ReadAllBytes(assemblyPath); - } - - var assemblyName = Path.GetFileName(assemblyPath); - bool isCoreAssembly = IsAot || helper.IsCoreAssembly(assemblyName); - - var assemblyList = isCoreAssembly ? resources.coreAssembly : resources.assembly; - assemblyList[assemblyName] = Utils.ComputeIntegrity(bytes); - - if (baseDebugLevel != 0) - { - var pdb = Path.ChangeExtension(assembly, ".pdb"); - if (File.Exists(pdb)) - { - if (isCoreAssembly) - resources.corePdb ??= new(); - else - resources.pdb ??= new(); - - var pdbList = isCoreAssembly ? resources.corePdb : resources.pdb; - pdbList[Path.GetFileName(pdb)] = Utils.ComputeIntegrity(pdb); - } - } - } - } - - bootConfig.debugLevel = helper.GetDebugLevel(resources.pdb?.Count > 0); - - ProcessSatelliteAssemblies(args => - { - resources.satelliteResources ??= new(); - - string name = Path.GetFileName(args.fullPath); - string cultureDirectory = Path.Combine(runtimeAssetsPath, args.culture); - Directory.CreateDirectory(cultureDirectory); - if (UseWebcil) - { - using TempFileName tmpWebcil = new(); - var webcilWriter = Microsoft.WebAssembly.Build.Tasks.WebcilConverter.FromPortableExecutable(inputPath: args.fullPath, outputPath: tmpWebcil.Path, logger: logAdapter); - webcilWriter.ConvertToWebcil(); - var finalWebcil = Path.Combine(cultureDirectory, Path.ChangeExtension(name, Utils.WebcilInWasmExtension)); - if (Utils.CopyIfDifferent(tmpWebcil.Path, finalWebcil, useHash: true)) - Log.LogMessage(MessageImportance.Low, $"Generated {finalWebcil} ."); - else - Log.LogMessage(MessageImportance.Low, $"Skipped generating {finalWebcil} as the contents are unchanged."); - _fileWrites.Add(finalWebcil); - - if (!resources.satelliteResources.TryGetValue(args.culture, out var cultureSatelliteResources)) - resources.satelliteResources[args.culture] = cultureSatelliteResources = new(); - - cultureSatelliteResources[Path.GetFileName(finalWebcil)] = Utils.ComputeIntegrity(finalWebcil); - } - else - { - var satellitePath = Path.Combine(cultureDirectory, name); - FileCopyChecked(args.fullPath, satellitePath, "SatelliteAssemblies"); - - if (!resources.satelliteResources.TryGetValue(args.culture, out var cultureSatelliteResources)) - resources.satelliteResources[args.culture] = cultureSatelliteResources = new(); - - cultureSatelliteResources[name] = Utils.ComputeIntegrity(satellitePath); - } - }); - - if (FilesToIncludeInFileSystem.Length > 0) - { - string supportFilesDir = Path.Combine(runtimeAssetsPath, "supportFiles"); - Directory.CreateDirectory(supportFilesDir); - - var i = 0; - StringDictionary targetPathTable = new(); - var vfs = new Dictionary>(); - var coreVfs = new Dictionary>(); - var virtualPathPrefix = !string.IsNullOrEmpty(RuntimeAssetsLocation) ? $"{RuntimeAssetsLocation}/supportFiles" : "supportFiles"; - foreach (var item in FilesToIncludeInFileSystem) - { - string? targetPath = item.GetMetadata("TargetPath"); - string? loadingStage = item.GetMetadata("LoadingStage"); - if (string.IsNullOrEmpty(targetPath)) - { - targetPath = Path.GetFileName(item.ItemSpec); - } - - // We normalize paths from `\` to `/` as MSBuild items could use `\`. - targetPath = targetPath.Replace('\\', '/'); - if (targetPathTable.ContainsKey(targetPath)) - { - string firstPath = Path.GetFullPath(targetPathTable[targetPath]!); - string secondPath = Path.GetFullPath(item.ItemSpec); - - if (firstPath == secondPath) - { - Log.LogWarning(null, "WASM0003", "", "", 0, 0, 0, 0, $"Found identical vfs mappings for target path: {targetPath}, source file: {firstPath}. Ignoring."); - continue; - } - - throw new LogAsErrorException($"Found more than one file mapping to the target VFS path: {targetPath}. Source files: {firstPath}, and {secondPath}"); - } - - targetPathTable[targetPath] = item.ItemSpec; - - var generatedFileName = $"{i++}_{Path.GetFileName(item.ItemSpec)}"; - var vfsPath = Path.Combine(supportFilesDir, generatedFileName); - FileCopyChecked(item.ItemSpec, vfsPath, "FilesToIncludeInFileSystem"); - - var vfsDict = loadingStage switch - { - null => vfs, - "" => vfs, - "Core" => coreVfs, - _ => throw new LogAsErrorException($"The WasmFilesToIncludeInFileSystem '{item.ItemSpec}' has LoadingStage set to unsupported '{loadingStage}' (empty or 'Core' is currently supported).") - }; - vfsDict[targetPath] = new() - { - [$"{virtualPathPrefix}/{generatedFileName}"] = Utils.ComputeIntegrity(vfsPath) - }; - } - - if (vfs.Count > 0) - resources.vfs = vfs; - - if (coreVfs.Count > 0) - resources.coreVfs = coreVfs; - } - - if (!InvariantGlobalization) - { - bool loadRemote = RemoteSources?.Length > 0; - foreach (var idfn in IcuDataFileNames) - { - if (!File.Exists(idfn)) - { - Log.LogError($"Expected the file defined as ICU resource: {idfn} to exist but it does not."); - return false; - } - - resources.icu ??= new(); - resources.icu[Path.GetFileName(idfn)] = Utils.ComputeIntegrity(idfn); - } - } - - - if (RemoteSources?.Length > 0) - { - resources.remoteSources = new(); - foreach (var source in RemoteSources) - if (source != null && source.ItemSpec != null) - resources.remoteSources.Add(source.ItemSpec); - } - - var extraConfiguration = new Dictionary(); - - if (PThreadPoolInitialSize < -1) - { - throw new LogAsErrorException($"PThreadPoolInitialSize must be -1, 0 or positive, but got {PThreadPoolInitialSize}"); - } - else if (PThreadPoolInitialSize > -1) - { - bootConfig.pthreadPoolInitialSize = PThreadPoolInitialSize; - } - - if (PThreadPoolUnusedSize < -1) - { - throw new LogAsErrorException($"PThreadPoolUnusedSize must be -1, 0 or positive, but got {PThreadPoolUnusedSize}"); - } - else if (PThreadPoolUnusedSize > -1) - { - bootConfig.pthreadPoolUnusedSize = PThreadPoolUnusedSize; - } - - foreach (ITaskItem extra in ExtraConfig ?? Enumerable.Empty()) - { - string name = extra.ItemSpec; - if (!TryParseExtraConfigValue(extra, out object? valueObject)) - return false; - - if (string.Equals(name, nameof(BootJsonData.environmentVariables), StringComparison.OrdinalIgnoreCase)) - { - bootConfig.environmentVariables ??= new(); - var envs = (JsonElement)valueObject!; - foreach (var env in envs.EnumerateObject()) - { - bootConfig.environmentVariables[env.Name] = env.Value.GetString()!; - } - } - else if (string.Equals(name, nameof(BootJsonData.diagnosticTracing), StringComparison.OrdinalIgnoreCase)) - { - if (valueObject is bool boolValue || (valueObject is string stringValue && bool.TryParse(stringValue, out boolValue))) - bootConfig.diagnosticTracing = boolValue; - else - throw new LogAsErrorException($"Unsupported value '{valueObject}' of type '{valueObject?.GetType()?.FullName}' for extra config 'diagnosticTracing'."); - } - else - { - extraConfiguration[name] = valueObject; - } - } - - Profilers ??= Array.Empty(); - var browserProfiler = Profilers.FirstOrDefault(p => p.StartsWith("browser:")); - if (browserProfiler != null) - { - bootConfig.environmentVariables ??= new(); - bootConfig.environmentVariables["DOTNET_WasmPerformanceInstrumentation"] = browserProfiler.Substring("browser:".Length); - } - - if (RuntimeConfigJsonPath != null && File.Exists(RuntimeConfigJsonPath)) - { - using var fs = File.OpenRead(RuntimeConfigJsonPath); - var runtimeConfig = JsonSerializer.Deserialize(fs, BootJsonBuilderHelper.JsonOptions); - bootConfig.runtimeConfig = runtimeConfig; - } - - foreach (ITaskItem env in EnvVariables ?? Enumerable.Empty()) - { - bootConfig.environmentVariables ??= new(); - string name = env.ItemSpec; - bootConfig.environmentVariables[name] = env.GetMetadata("Value"); - } - - if (extraConfiguration.Count > 0) - { - bootConfig.extensions = new() - { - ["extra"] = extraConfiguration - }; - } - - using TempFileName tmpConfigPath = new(); - { - helper.ComputeResourcesHash(bootConfig); - helper.TransformResourcesToAssets(bootConfig); - helper.WriteConfigToFile(bootConfig, tmpConfigPath.Path, Path.GetExtension(ConfigFileName)); - } - - string monoConfigPath = Path.Combine(runtimeAssetsPath, ConfigFileName); - Utils.CopyIfDifferent(tmpConfigPath.Path, monoConfigPath, useHash: false); - _fileWrites.Add(monoConfigPath); - - foreach (ITaskItem item in ExtraFilesToDeploy!) - { - string src = item.ItemSpec; - string dst; - - string tgtPath = item.GetMetadata("TargetPath"); - if (!string.IsNullOrEmpty(tgtPath)) - { - dst = Path.Combine(AppDir!, tgtPath); - string? dstDir = Path.GetDirectoryName(dst); - if (!string.IsNullOrEmpty(dstDir) && !Directory.Exists(dstDir)) - Directory.CreateDirectory(dstDir!); - } - else - { - dst = Path.Combine(AppDir!, Path.GetFileName(src)); - } - - if (!FileCopyChecked(src, dst, "ExtraFilesToDeploy")) - return false; - } - - UpdateRuntimeConfigJson(); - return !Log.HasLoggedErrors; - } - - private bool TryParseExtraConfigValue(ITaskItem extraItem, out object? valueObject) - { - valueObject = null; - string? rawValue = extraItem.GetMetadata("Value"); - if (string.IsNullOrEmpty(rawValue)) - return true; - - if (TryConvert(rawValue, typeof(double), out valueObject) || TryConvert(rawValue, typeof(bool), out valueObject)) - return true; - - // Try parsing as a quoted string - if (rawValue!.Length > 1 && rawValue![0] == '"' && rawValue![rawValue!.Length - 1] == '"') - { - valueObject = rawValue!.Substring(1, rawValue!.Length - 2); - return true; - } - - // try parsing as json - try - { - JsonDocument jdoc = JsonDocument.Parse(rawValue); - valueObject = jdoc.RootElement; - return true; - } - catch (JsonException je) - { - Log.LogError($"ExtraConfig: {extraItem.ItemSpec} with Value={rawValue} cannot be parsed as a number, boolean, string, or json object/array: {je.Message}"); - return false; - } - } - - private static bool TryConvert(string str, Type type, out object? value) - { - value = null; - try - { - value = Convert.ChangeType(str, type); - return true; - } - catch (Exception ex) when (ex is FormatException or InvalidCastException or OverflowException) - { - return false; - } - } -} diff --git a/src/runtime/src/tasks/WasmAppBuilder/WasmAppBuilder.csproj b/src/runtime/src/tasks/WasmAppBuilder/WasmAppBuilder.csproj index 3fc33e370b15..af91f960b892 100644 --- a/src/runtime/src/tasks/WasmAppBuilder/WasmAppBuilder.csproj +++ b/src/runtime/src/tasks/WasmAppBuilder/WasmAppBuilder.csproj @@ -1,11 +1,10 @@ - $(NetCoreAppToolCurrent);$(NetFrameworkToolCurrent) + $(NetCoreAppToolCurrent) enable $(NoWarn),CA1050 - $(NoWarn),CS8604,CS8602 - $(NoWarn),CA1850 + $(NoWarn),CA1850 false true true @@ -46,19 +45,14 @@ - - - - - - - + @@ -73,7 +67,7 @@ diff --git a/src/runtime/src/tasks/WasmAppBuilder/coreclr/PInvokeCollector.cs b/src/runtime/src/tasks/WasmAppBuilder/coreclr/PInvokeCollector.cs new file mode 100644 index 000000000000..a16b489a78e6 --- /dev/null +++ b/src/runtime/src/tasks/WasmAppBuilder/coreclr/PInvokeCollector.cs @@ -0,0 +1,284 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System; +using System.Linq; +using System.Diagnostics.CodeAnalysis; +using System.Reflection; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +using Microsoft.Build.Tasks; +using WasmAppBuilder; +using JoinedString; + +#pragma warning disable CA1067 +#pragma warning disable CS0649 +internal sealed class PInvoke : IEquatable +#pragma warning restore CA1067 +{ + public PInvoke(string entryPoint, string module, MethodInfo method, bool wasmLinkage) + { + EntryPoint = entryPoint; + Module = module; + Method = method; + WasmLinkage = wasmLinkage; + } + + public string EntryPoint; + public string Module; + public MethodInfo Method; + public bool Skip; + public bool WasmLinkage; + + public bool Equals(PInvoke? other) + => other != null && + string.Equals(EntryPoint, other.EntryPoint, StringComparison.Ordinal) && + string.Equals(Module, other.Module, StringComparison.Ordinal) && + string.Equals(Method.ToString(), other.Method.ToString(), StringComparison.Ordinal); + + public override string ToString() => $"{{ EntryPoint: {EntryPoint}, Module: {Module}, Method: {Method}, Skip: {Skip} }}"; +} +#pragma warning restore CS0649 + +internal sealed class PInvokeComparer : IEqualityComparer +{ + public bool Equals(PInvoke? x, PInvoke? y) + { + if (x == null && y == null) + return true; + if (x == null || y == null) + return false; + + return x.Equals(y); + } + + public int GetHashCode(PInvoke pinvoke) + => $"{pinvoke.EntryPoint}{pinvoke.Module}{pinvoke.Method}".GetHashCode(); +} + + +internal sealed class PInvokeCollector { + private readonly Dictionary _assemblyDisableRuntimeMarshallingAttributeCache = new(); + private LogAdapter Log { get; init; } + + public PInvokeCollector(LogAdapter log) + { + Log = log; + } + + public void CollectPInvokes(List pinvokes, List callbacks, HashSet signatures, Type type) + { + foreach (var method in type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance)) + { + try + { + CollectPInvokesForMethod(method); + if (DoesMethodHaveCallbacks(method, Log)) + callbacks.Add(new PInvokeCallback(method)); + } + catch (Exception ex) when (ex is not LogAsErrorException) + { + Log.Warning("WASM0001", $"Could not get pinvoke, or callbacks for method '{type.FullName}::{method.Name}' because '{ex}'"); + } + } + + if (HasAttribute(type, "System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute")) + { + var method = type.GetMethod("Invoke"); + + if (method != null) + { + string? signature = SignatureMapper.MethodToSignature(method!, Log); + if (signature == null) + throw new NotSupportedException($"Unsupported parameter type in method '{type.FullName}.{method.Name}'"); + + if (signatures.Add(signature)) + Log.LogMessage(MessageImportance.Low, $"Adding pinvoke signature {signature} for method '{type.FullName}.{method.Name}'"); + } + } + + void CollectPInvokesForMethod(MethodInfo method) + { + if ((method.Attributes & MethodAttributes.PinvokeImpl) != 0) + { + var dllimport = method.CustomAttributes.First(attr => attr.AttributeType.Name == "DllImportAttribute"); + var wasmLinkage = method.CustomAttributes.Any(attr => attr.AttributeType.Name == "WasmImportLinkageAttribute"); + var module = (string)dllimport.ConstructorArguments[0].Value!; + var entrypoint = (string)dllimport.NamedArguments.First(arg => arg.MemberName == "EntryPoint").TypedValue.Value!; + pinvokes.Add(new PInvoke(entrypoint, module, method, wasmLinkage)); + + string? signature = SignatureMapper.MethodToSignature(method, Log); + if (signature == null) + { + throw new NotSupportedException($"Unsupported parameter type in method '{type.FullName}.{method.Name}'"); + } + + if (signatures.Add(signature)) + Log.LogMessage(MessageImportance.Low, $"Adding pinvoke signature {signature} for method '{type.FullName}.{method.Name}'"); + } + } + + bool DoesMethodHaveCallbacks(MethodInfo method, LogAdapter log) + { + if (!MethodHasCallbackAttributes(method)) + return false; + + if (TryIsMethodGetParametersUnsupported(method, out string? reason)) + { + Log.Warning("WASM0001", $"Skipping callback '{method.DeclaringType!.FullName}::{method.Name}' because '{reason}'."); + return false; + } + + if (method.DeclaringType != null && HasAssemblyDisableRuntimeMarshallingAttribute(method.DeclaringType.Assembly)) + return true; + + // No DisableRuntimeMarshalling attribute, so check if the params/ret-type are + // blittable + bool isVoid = method.ReturnType.FullName == "System.Void"; + if (!isVoid && !IsBlittable(method.ReturnType, log)) + Error($"The return type '{method.ReturnType.FullName}' of pinvoke callback method '{method}' needs to be blittable."); + + foreach (var p in method.GetParameters()) + { + if (!IsBlittable(p.ParameterType, log)) + Error("Parameter types of pinvoke callback method '" + method + "' needs to be blittable."); + } + + return true; + } + + static bool MethodHasCallbackAttributes(MethodInfo method) + { + foreach (CustomAttributeData cattr in CustomAttributeData.GetCustomAttributes(method)) + { + try + { + if (cattr.AttributeType.FullName == "System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute" || + cattr.AttributeType.Name == "MonoPInvokeCallbackAttribute") + { + return true; + } + } + catch + { + // Assembly not found, ignore + } + } + + return false; + } + } + + public static bool IsBlittable(Type type, LogAdapter log) => PInvokeTableGenerator.IsBlittable(type, log); + + private static void Error(string msg) => throw new LogAsErrorException(msg); + + internal static bool HasAttribute(MemberInfo element, params string[] attributeNames) => PInvokeTableGenerator.HasAttribute(element, attributeNames); + + private static bool TryIsMethodGetParametersUnsupported(MethodInfo method, [NotNullWhen(true)] out string? reason) + { + try + { + method.GetParameters(); + } + catch (NotSupportedException nse) + { + reason = nse.Message; + return true; + } + catch + { + // not concerned with other exceptions + } + + reason = null; + return false; + } + + private bool HasAssemblyDisableRuntimeMarshallingAttribute(Assembly assembly) + { + if (!_assemblyDisableRuntimeMarshallingAttributeCache.TryGetValue(assembly, out var value)) + { + _assemblyDisableRuntimeMarshallingAttributeCache[assembly] = value = assembly + .GetCustomAttributesData() + .Any(d => d.AttributeType.Name == "DisableRuntimeMarshallingAttribute"); + } + + return value; + } +} + +internal sealed class PInvokeCallbackComparer : IComparer +{ + public int Compare(PInvokeCallback? x, PInvokeCallback? y) + { + int compare = string.Compare(x!.Key, y!.Key, StringComparison.Ordinal); + return compare != 0 ? compare : (int)(x.Token - y.Token); + } +} + +#pragma warning disable CS0649 +internal sealed class PInvokeCallback +{ + public PInvokeCallback(MethodInfo method) + { + Method = method; + var t = method.DeclaringType!; + TypeName = t.Name!; + TypeFullName = t.FullName!; + AssemblyName = t.Module!.Assembly!.GetName()!.Name!; + AssemblyFQName = t.Module!.Assembly!.GetName()!.FullName!; + Namespace = t.Namespace; + MethodName = method.Name!; + ReturnType = method.ReturnType!; + IsVoid = ReturnType.Name == "Void"; + Token = (uint)method.MetadataToken; + + // FIXME: this is a hack, we need to encode this better and allow reflection in the interp case + // but either way it needs to match the key generated in get_native_to_interp since the key is + // used to look up the interp entry function. It must be unique for each callback runtime errors + // can occur since it is used to look up the index in the wasm_native_to_interp_ftndescs and + // the signature of the interp entry function must match the native signature + // + // the key also needs to survive being encoded in C literals, if in doubt + // add something like "\U0001F412" to the key on both the managed and unmanaged side + Key = $"{MethodName}#{Method.GetParameters().Length}:{AssemblyName}:{Namespace}:{TypeName}"; + + IsExport = false; + foreach (var attr in method.CustomAttributes) + { + if (attr.AttributeType.Name == "UnmanagedCallersOnlyAttribute") + { + foreach (var arg in attr.NamedArguments) + { + if (arg.MemberName == "EntryPoint") + { + EntryPoint = arg.TypedValue.Value!.ToString(); + IsExport = true; + return; + } + } + } + } + } + + public string EntryName => $"{AssemblyName}_{Namespace}_{TypeName}_{MethodName}"; + + public ParameterInfo[] Parameters => Method.GetParameters(); + public string? EntryPoint { get; } + public MethodInfo Method { get; } + public string? EntrySymbol { get; set; } + public string AssemblyName { get; } + public string AssemblyFQName { get; } + public string TypeName { get; } + public string TypeFullName { get; } + public string? Namespace { get;} + public string MethodName { get; } + public Type ReturnType { get;} + public bool IsExport { get; } + public bool IsVoid { get; } + public uint Token { get; } + public string Key { get; } +} +#pragma warning restore CS0649 diff --git a/src/runtime/src/tasks/WasmAppBuilder/coreclr/PInvokeTableGenerator.cs b/src/runtime/src/tasks/WasmAppBuilder/coreclr/PInvokeTableGenerator.cs new file mode 100644 index 000000000000..b360c69d70b3 --- /dev/null +++ b/src/runtime/src/tasks/WasmAppBuilder/coreclr/PInvokeTableGenerator.cs @@ -0,0 +1,547 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Reflection; +using System.Runtime.InteropServices; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +using WasmAppBuilder; +using JoinedString; + +internal sealed class PInvokeTableGenerator +{ + private LogAdapter Log { get; set; } + private readonly Func _fixupSymbolName; + private readonly HashSet signatures = new(); + private readonly List pinvokes = new(); + private readonly List callbacks = new(); + private readonly PInvokeCollector _pinvokeCollector; + private readonly bool _isLibraryMode; + + public PInvokeTableGenerator(Func fixupSymbolName, LogAdapter log, bool isLibraryMode = false) + { + Log = log; + _fixupSymbolName = fixupSymbolName; + _pinvokeCollector = new(log); + _isLibraryMode = isLibraryMode; + } + + public void ScanAssembly(Assembly asm) + { + foreach (Type type in asm.GetTypes()) + _pinvokeCollector.CollectPInvokes(pinvokes, callbacks, signatures, type); + } + + public IEnumerable Generate(string[] pinvokeModules, string outputPath) + { + var modules = new SortedDictionary(StringComparer.Ordinal); + foreach (var module in pinvokeModules) + modules[module] = module; + + using TempFileName tmpFileName = new(); + using (var w = new JoinedStringStreamWriter(tmpFileName.Path, false)) + { + // WASM-TODO: the generator is WIP, so we disable pinvoke table generation + // EmitPInvokeTable(w, modules, pinvokes); + EmitNativeToInterp(w, callbacks); + } + + if (Utils.CopyIfDifferent(tmpFileName.Path, outputPath, useHash: false)) + Log.LogMessage(MessageImportance.Low, $"Generating pinvoke table to '{outputPath}'."); + else + Log.LogMessage(MessageImportance.Low, $"PInvoke table in {outputPath} is unchanged."); + + return signatures; + } + + private void EmitPInvokeTable(StreamWriter w, SortedDictionary modules, List pinvokes) + { + foreach (var pinvoke in pinvokes) + { + if (modules.ContainsKey(pinvoke.Module)) + continue; + // Handle special modules, and add them to the list of modules + // otherwise, skip them and throw an exception at runtime if they + // are called. + if (pinvoke.WasmLinkage) + { + // WasmLinkage means we needs to import the module + modules.Add(pinvoke.Module, pinvoke.Module); + Log.LogMessage(MessageImportance.Low, $"Adding module {pinvoke.Module} for WasmImportLinkage"); + } + else if (pinvoke.Module == "*" || pinvoke.Module == "__Internal") + { + // Special case for __Internal and * modules to indicate static linking without specifying the module + modules.Add(pinvoke.Module, pinvoke.Module); + Log.LogMessage(MessageImportance.Low, $"Adding module {pinvoke.Module} for static linking"); + } + else + { + Log.Warning("WASM0066", $"PInvoke module '{pinvoke.Module}' for method '{pinvoke.Method.DeclaringType}::{pinvoke.Method.Name}' is not in the list of allowed modules. It is also not special treated module."); + } + } + + w.WriteLine( + $""" + // GENERATED FILE, DO NOT MODIFY (PInvokeTableGenerator.cs) + """); + + var pinvokesGroupedByEntryPoint = pinvokes + .Where(l => modules.ContainsKey(l.Module)) + .OrderBy(l => l.EntryPoint, StringComparer.Ordinal) + .GroupBy(CEntryPoint, StringComparer.Ordinal); + var comparer = new PInvokeComparer(); + foreach (IGrouping group in pinvokesGroupedByEntryPoint) + { + var candidates = group.Distinct(comparer).ToArray(); + PInvoke first = candidates[0]; + if (ShouldTreatAsVariadic(candidates)) + { + string imports = string.Join(Environment.NewLine, + candidates.Select( + p => $" {p.Method} (in [{p.Method.DeclaringType?.Assembly.GetName().Name}] {p.Method.DeclaringType})")); + Log.Warning("WASM0001", $"Found a native function ({first.EntryPoint}) with varargs in {first.Module}." + + " Calling such functions is not supported, and will fail at runtime." + + $" Managed DllImports: {Environment.NewLine}{imports}"); + + foreach (var c in candidates) + c.Skip = true; + + continue; + } + + var decls = new HashSet(); + foreach (var candidate in candidates) + { + var decl = GenPInvokeDecl(candidate); + if (decl is null || decls.Contains(decl)) + continue; + + w.WriteLine(decl); + decls.Add(decl); + } + } + + var moduleImports = new Dictionary>(); + foreach (var module in modules.Keys) + { + // the order here is not important, because we use hash tables, we want it to be stable though + var imports = pinvokes + .Where(l => l.Module == module && !l.Skip) + .OrderBy(l => l.EntryPoint, StringComparer.Ordinal) + .GroupBy(d => d.EntryPoint, StringComparer.Ordinal) + .Select(l => $"{{\"{EscapeLiteral(l.Key)}\", {CEntryPoint(l.First())}}}, // {ListRefs(l)}{w.NewLine} ") + .ToList(); + + moduleImports[module] = imports; + w.Write( + $$""" + + static PinvokeImport {{_fixupSymbolName(module)}}_imports [] = { + {{string.Join("", imports)}}{NULL, NULL} + }; + + """); + } + + w.Write( + $$""" + + static PinvokeTable pinvoke_tables[] = { + {{modules.Keys.Join($",{w.NewLine} ", m => $"{{\"{EscapeLiteral(m)}\", {_fixupSymbolName(m)}_imports, {moduleImports[m].Count}}}")}} + }; + + """); + + static bool ShouldTreatAsVariadic(PInvoke[] candidates) + { + if (candidates.Length < 2) + return false; + + PInvoke first = candidates[0]; + if (!TryIsMethodGetParametersSupported(first.Method, out _)) + return false; + + int firstNumArgs = first.Method.GetParameters().Length; + return candidates + .Skip(1) + // detect possible vararg entrypoint usage + // where the same entrypoint is used with different + // number of arguments + .Any(c => TryIsMethodGetParametersSupported(c.Method, out _) && + c.Method.GetParameters().Length != firstNumArgs); + } + + static string ListRefs(IGrouping l) => + string.Join(", ", l.Select(c => c.Method.DeclaringType!.Module!.Assembly!.GetName()!.Name!).Distinct().OrderBy(n => n)); + } + + private string CEntryPoint(PInvoke pinvoke) + { + if (pinvoke.WasmLinkage) + { + // We mangle the name to avoid collisions with symbols in other modules + string namespaceName = pinvoke.Method.DeclaringType?.Namespace ?? string.Empty; + return _fixupSymbolName($"{namespaceName}#{pinvoke.Module}#{pinvoke.EntryPoint}"); + } + return _fixupSymbolName(pinvoke.EntryPoint); + } + + private static string MapType(Type t) => t.Name switch + { + "Void" => "void", + nameof(Double) => "double", + nameof(Single) => "float", + nameof(Int64) => "int64_t", + nameof(UInt64) => "uint64_t", + nameof(Int32) => "int32_t", + nameof(UInt32) => "uint32_t", + nameof(Int16) => "int32_t", + nameof(UInt16) => "uint32_t", + nameof(Char) => "int32_t", + nameof(Boolean) => "int32_t", + nameof(SByte) => "int32_t", + nameof(Byte) => "uint32_t", + nameof(IntPtr) => "void *", + nameof(UIntPtr) => "void *", + _ => PickCTypeNameForUnknownType(t) + }; + + private static string PickCTypeNameForUnknownType(Type t) + { + // Pass objects by-reference (their address by-value) + if (!t.IsValueType) + return "void *"; + // Pass pointers and function pointers by-value + else if (t.IsPointer || t.IsFunctionPointer) + return "void *"; + else if (t.IsPrimitive) + throw new NotImplementedException("No native type mapping for type " + t); + + // https://github.com/WebAssembly/tool-conventions/blob/main/BasicCABI.md#function-signatures + // Any struct or union that recursively (including through nested structs, unions, and arrays) + // contains just a single scalar value and is not specified to have greater than natural alignment. + // FIXME: Handle the scenario where there are fields of struct types that contain no members + var fields = t.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + if (fields.Length == 1) + return MapType(fields[0].FieldType); + else + return "void *"; + } + + // FIXME: System.Reflection.MetadataLoadContext can't decode function pointer types + // https://github.com/dotnet/runtime/issues/43791 + private static bool TryIsMethodGetParametersSupported(MethodInfo method, [NotNullWhen(false)] out string? reason) + { + try + { + method.GetParameters(); + } + catch (NotSupportedException nse) + { + reason = nse.Message; + return false; + } + catch + { + // not concerned with other exceptions + } + + reason = null; + return true; + } + + private string? GenPInvokeDecl(PInvoke pinvoke) + { + var method = pinvoke.Method; + + if (!TryIsMethodGetParametersSupported(pinvoke.Method, out string? reason)) + { + // Don't use method.ToString() or any of it's parameters, or return type + // because at least one of those are unsupported, and will throw + Log.Warning("WASM0001", $"Skipping pinvoke '{pinvoke.Method.DeclaringType!.FullName}::{pinvoke.Method.Name}' because '{reason}'."); + + pinvoke.Skip = true; + return null; + } + + var realReturnType = method.ReturnType; + var realParameterTypes = method.GetParameters().Select(p => MapType(p.ParameterType)).ToList(); + + SignatureMapper.TypeToChar(realReturnType, Log, out bool resultIsByRef); + if (resultIsByRef) { + realReturnType = typeof(void); + realParameterTypes.Insert(0, "void *"); + } + + return + $$""" + {{(pinvoke.WasmLinkage ? $"__attribute__((import_module(\"{EscapeLiteral(pinvoke.Module)}\"),import_name(\"{EscapeLiteral(pinvoke.EntryPoint)}\")))" : "")}} + {{(pinvoke.WasmLinkage ? "extern " : "")}}{{MapType(realReturnType)}} {{CEntryPoint(pinvoke)}} ({{string.Join(", ", realParameterTypes)}}); + """; + } + + private static string EscapeLiteral(string? input) + { + if (input == null) + return string.Empty; + + StringBuilder sb = new StringBuilder(); + + for (int i = 0; i < input.Length; i++) + { + char c = input[i]; + + sb.Append(c switch + { + '\\' => "\\\\", + '\"' => "\\\"", + '\n' => "\\n", + '\r' => "\\r", + '\t' => "\\t", + // take special care with surrogate pairs to avoid + // potential decoding issues in generated C literals + _ when char.IsHighSurrogate(c) && i + 1 < input.Length && char.IsLowSurrogate(input[i + 1]) + => $"\\U{char.ConvertToUtf32(c, input[++i]):X8}", + _ when char.IsControl(c) || c > 127 + => $"\\u{(int)c:X4}", + _ => c.ToString() + }); + } + + return sb.ToString(); + } + + // this is eqivalent to `ULONG HashString(LPCWSTR szStr)` in CoreCLR runtime, src/coreclr/inc/utilcode.h + private static uint HashString(string str) + { + uint hash = 5381; + foreach (char c in str) + { + hash = ((hash << 5) + hash) ^ (uint)c; + } + + return hash; + } + + private void EmitNativeToInterp(StreamWriter w, List callbacks) + { + // Generate native->interp entry functions + // These are called by native code, so they need to obtain + // the interp entry function/arg from a global array + // They also need to have a signature matching what the + // native code expects, which is the native signature + // of the delegate invoke in the [MonoPInvokeCallback] + // or [UnmanagedCallersOnly] attribute. + // Only blittable parameter/return types are supposed. + w.Write( + $$""" + // Licensed to the .NET Foundation under one or more agreements. + // The .NET Foundation licenses this file to you under the MIT license. + // + + // + // GENERATED FILE, DON'T EDIT + // Generated by coreclr InterpToNativeGenerator + // + + #include + + // WASM-TODO: The method lookup would ideally be fully qualified assembly and then methodDef token. + // The current approach has limitations with overloaded methods. + extern "C" void LookupMethodByName(const char* fullQualifiedTypeName, const char* methodName, MethodDesc** ppMD); + extern "C" void ExecuteInterpretedMethodFromUnmanaged(MethodDesc* pMD, int8_t* args, size_t argSize, int8_t* ret, PCODE callerIp); + + """); + + var callbackNames = new HashSet(); + var keys = new HashSet(); + int cb_index = 0; + callbacks = callbacks.OrderBy(c => c, new PInvokeCallbackComparer()).ToList(); + foreach (var cb in callbacks) + { + cb.EntrySymbol = FixedSymbolName(cb, Log); + + if (callbackNames.Contains(cb.EntrySymbol)) + { + Error($"Two callbacks with the same symbol '{cb.EntrySymbol}' are not supported."); + } + callbackNames.Add(cb.EntrySymbol); + if (keys.Contains(cb.Key)) + { + Error($"Two callbacks with the same Name and number of arguments '{cb.Key}' are not supported."); + } + keys.Add(cb.Key); + + // The signature of the interp entry function + // This is a gsharedvt_in signature + var entryArgs = new List(); + if (!cb.IsVoid) + { + entryArgs.Add("(int*)&result"); + } + entryArgs.AddRange(cb.Parameters.Select((_, i) => $"(int*)&arg{i}")); + entryArgs.Add($"(int*)wasm_native_to_interp_ftndescs [{cb_index}].arg"); + + var argsArgs = cb.Parameters.Length > 0 ? "(int8_t*)args, sizeof(args)" : "nullptr, 0"; + var argsDeclaration = cb.Parameters.Length > 0 + ? $"\n int64_t args[{cb.Parameters.Length}] = {{ {cb.Parameters.Join(", ", (info, i) => $"(int64_t)arg{i}")} }};\n" + : string.Empty; + var parametersDeclaration = cb.Parameters.Join(", ", (info, i) => $"{MapType(info.ParameterType)} arg{i}"); + var exportFunction = cb.IsExport ? + $$""" + + + extern "C" void {{cb.EntryPoint}}({{parametersDeclaration}}) + { + Call_{{cb.EntrySymbol}}({{cb.Parameters.Join(", ", (info, i) => $"arg{i}")}}); + } + """ : string.Empty; + w.Write( + $$""" + + static MethodDesc* MD_{{cb.EntrySymbol}} = nullptr; + static {{ + MapType(cb.ReturnType)}} Call_{{cb.EntrySymbol}}({{parametersDeclaration}}) + {{{argsDeclaration}} + // Lazy lookup of MethodDesc for the function export scenario. + if (!MD_{{cb.EntrySymbol}}) + { + LookupMethodByName("{{cb.TypeFullName}}, {{cb.AssemblyName}}", "{{cb.MethodName}}", &MD_{{cb.EntrySymbol}}); + }{{ + (!cb.IsVoid ? $"{w.NewLine}{w.NewLine} {MapType(cb.ReturnType)} result;" : "")}} + ExecuteInterpretedMethodFromUnmanaged(MD_{{cb.EntrySymbol}}, {{argsArgs}}, {{(cb.IsVoid ? "nullptr" : "(int8_t*)&result")}}, (PCODE)&Call_{{cb.EntrySymbol}});{{ + (!cb.IsVoid ? $"{w.NewLine} return result;" : "")}} + }{{exportFunction}} + + """); + cb_index++; + } + + w.Write( + $$""" + + extern const ReverseThunkMapEntry g_ReverseThunks[] = + { + {{callbacks.Join($",{w.NewLine}", cb => ThunkMapEntryLine(cb, Log))}} + }; + + const size_t g_ReverseThunksCount = sizeof(g_ReverseThunks) / sizeof(g_ReverseThunks[0]); + + """); + } + + private string FixedSymbolName(PInvokeCallback cb, LogAdapter Log) + { + var paramTypes = cb.Parameters.Length > 0 ? cb.Parameters.Join("_", (info, i) => SignatureMapper.TypeToNameType(info.ParameterType, Log)).ToString() : "Void"; + var sig = $"{paramTypes}_Ret{SignatureMapper.TypeToNameType(cb.ReturnType, Log)}"; + + return _fixupSymbolName($"{cb.EntryName}_{sig}"); + } + + + private string ThunkMapEntryLine(PInvokeCallback cb, LogAdapter Log) + { + var fsName = FixedSymbolName(cb, Log); + + return $" {{ {cb.Token ^ HashString(cb.AssemblyFQName)}, {HashString(cb.Key)}, {{ &MD_{fsName}, (void*)&Call_{cb.EntrySymbol} }} }} /* alternate key source: {cb.Key} */"; + } + + private static readonly Dictionary _blittableCache = new(); + + public static bool IsBlittable(Type type, LogAdapter log) + { + // We maintain a cache of results in order to only produce log messages the first time + // we analyze a given type. Otherwise, each (successful) use of a user-defined type + // in a callback or pinvoke would generate duplicate messages. + lock (_blittableCache) + if (_blittableCache.TryGetValue(type, out bool blittable)) + return blittable; + + bool result = IsBlittableUncached(type, log); + lock (_blittableCache) + _blittableCache[type] = result; + return result; + + static bool IsBlittableUncached(Type type, LogAdapter log) + { + if (type.IsPrimitive || type.IsByRef || type.IsPointer || type.IsEnum) + return true; + + if (type.IsFunctionPointer) + return true; + + // HACK: SkiaSharp has pinvokes that rely on this + if (HasAttribute(type, "System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute")) + return true; + + if (type.Name == "__NonBlittableTypeForAutomatedTests__") + return false; + + if (!type.IsValueType) + { + log.InfoHigh("WASM0060", "Type {0} is not blittable: Not a ValueType", type); + return false; + } + + var fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + + if (!type.IsLayoutSequential && (fields.Length > 1)) + { + log.InfoHigh("WASM0061", "Type {0} is not blittable: LayoutKind is not Sequential", type); + return false; + } + + foreach (var ft in fields) + { + if (!IsBlittable(ft.FieldType, log)) + { + log.InfoHigh("WASM0062", "Type {0} is not blittable: Field {1} is not blittable", type, ft.Name); + return false; + } + // HACK: Skip literals since they're complicated + // Ideally we would block initonly fields too since the callee could mutate them, but + // we rely on being able to pass types like System.Guid which are readonly + if (ft.IsLiteral) + { + log.InfoHigh("WASM0063", "Type {0} is not blittable: Field {1} is literal", type, ft.Name); + return false; + } + } + + return true; + } + } + + public static bool HasAttribute(MemberInfo element, params string[] attributeNames) + { + foreach (CustomAttributeData cattr in CustomAttributeData.GetCustomAttributes(element)) + { + try + { + for (int i = 0; i < attributeNames.Length; ++i) + { + if (cattr.AttributeType.FullName == attributeNames[i] || + cattr.AttributeType.Name == attributeNames[i]) + { + return true; + } + } + } + catch + { + // Assembly not found, ignore + } + } + return false; + } + + private static void Error(string msg) => throw new LogAsErrorException(msg); +} diff --git a/src/runtime/src/tasks/WasmAppBuilder/coreclr/SignatureMapper.cs b/src/runtime/src/tasks/WasmAppBuilder/coreclr/SignatureMapper.cs index 21b47c309f14..69085ff5b17c 100644 --- a/src/runtime/src/tasks/WasmAppBuilder/coreclr/SignatureMapper.cs +++ b/src/runtime/src/tasks/WasmAppBuilder/coreclr/SignatureMapper.cs @@ -1,4 +1,4 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; @@ -63,7 +63,7 @@ internal static class SignatureMapper } else if (t.IsPointer) c = 'i'; - else if (PInvokeTableGenerator.IsFunctionPointer(t)) + else if (t.IsFunctionPointer) c = 'i'; else if (t.IsValueType) { @@ -143,6 +143,17 @@ internal static class SignatureMapper _ => throw new InvalidSignatureCharException(c) }; + public static string TypeToNameType(Type t, LogAdapter log) + { + char? c = TypeToChar(t, log, out _); + if (c == null) + { + throw new InvalidSignatureCharException('?'); + } + + return CharToNameType(c.Value); + } + public static bool IsVoidSignature(string signature) => signature[0] == 'v'; } diff --git a/src/runtime/src/tasks/WasmAppBuilder/PInvokeCollector.cs b/src/runtime/src/tasks/WasmAppBuilder/mono/PInvokeCollector.cs similarity index 100% rename from src/runtime/src/tasks/WasmAppBuilder/PInvokeCollector.cs rename to src/runtime/src/tasks/WasmAppBuilder/mono/PInvokeCollector.cs diff --git a/src/runtime/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs b/src/runtime/src/tasks/WasmAppBuilder/mono/PInvokeTableGenerator.cs similarity index 100% rename from src/runtime/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs rename to src/runtime/src/tasks/WasmAppBuilder/mono/PInvokeTableGenerator.cs diff --git a/src/runtime/src/tasks/WasmBuildTasks/LinkContentToWwwroot.cs b/src/runtime/src/tasks/WasmBuildTasks/LinkContentToWwwroot.cs new file mode 100644 index 000000000000..60603ad40268 --- /dev/null +++ b/src/runtime/src/tasks/WasmBuildTasks/LinkContentToWwwroot.cs @@ -0,0 +1,123 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.IO; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +namespace Microsoft.WebAssembly.Build.Tasks; + +public class LinkContentToWwwroot : Task +{ + // Inputs + [Required] + public ITaskItem[] Content { get; set; } = []; + + [Required] + public string MSBuildProjectDirectory { get; set; } = string.Empty; + + // Outputs + [Output] + public ITaskItem[] WasmFilesToIncludeInFileSystem { get; set; } = []; + + [Output] + public ITaskItem[] ContentOut { get; set; } = []; + + public override bool Execute() + { + var wasmFiles = new List(); + var contentItems = new List(); + + foreach (var item in Content) + { + string copyToOutput = item.GetMetadata("CopyToOutputDirectory") ?? string.Empty; + string targetPath = item.GetMetadata("TargetPath") ?? string.Empty; + string identity = item.ItemSpec ?? string.Empty; + string link = item.GetMetadata("Link") ?? string.Empty; + + bool copyPreserveOrAlways = string.Equals(copyToOutput, "PreserveNewest", StringComparison.OrdinalIgnoreCase) || string.Equals(copyToOutput, "Always", StringComparison.OrdinalIgnoreCase); + if (!copyPreserveOrAlways) + { + Log.LogMessage(MessageImportance.Low, $"Skipping item with Identity '{identity}' (TargetPath '{targetPath}', Link '{link}') because CopyToOutputDirectory is not 'PreserveNewest' or 'Always' ('{copyPreserveOrAlways}')."); + continue; + } + + if (!string.IsNullOrEmpty(link) && item.GetMetadata("BuildReference") == "true" && item.GetMetadata("OriginalItemName") == "WasmAssembliesFinal" && !string.Equals(Path.GetExtension(link), Path.GetExtension(identity), StringComparison.OrdinalIgnoreCase)) + { + Log.LogMessage(MessageImportance.Low, $"Ignoring Link '{link}' for Identity '{identity}', because it has a different extension and is coming from nested publish (WasmAssembliesFinal)."); + link = string.Empty; + } + + // Case 1: use TargetPath when present + if (!string.IsNullOrEmpty(targetPath)) + { + // Add TargetPath to WasmFilesToIncludeInFileSystem + wasmFiles.Add(new TaskItem(targetPath)); + + // Content: ContentRoot = Identity with TargetPath removed, TargetPath = wwwroot\TargetPath + var contentRoot = Path.GetDirectoryName(identity); + + var outItem = new TaskItem(identity, item.CloneCustomMetadata()); + outItem.SetMetadata("ContentRoot", contentRoot); + outItem.SetMetadata("TargetPath", Path.Combine("wwwroot", targetPath)); + contentItems.Add(outItem); + + Log.LogMessage(MessageImportance.Low, $"Adding TargetPath '{targetPath}' and ContentRoot '{contentRoot}' for Identity '{identity}'."); + continue; + } + + // Case 2: use Identity when Link is empty + if (string.IsNullOrEmpty(link)) + { + var isRooted = Path.IsPathRooted(identity); + targetPath = isRooted ? Path.GetFileName(identity) : identity; + var contentRoot = isRooted ? Path.GetDirectoryName(identity) : Path.GetDirectoryName(Path.GetFullPath(identity, MSBuildProjectDirectory)); + + // Add TargetPath to WasmFilesToIncludeInFileSystem + var wasmVfsFile = new TaskItem(targetPath); + wasmFiles.Add(wasmVfsFile); + if (isRooted && identity.StartsWith(MSBuildProjectDirectory, StringComparison.OrdinalIgnoreCase)) + { + var wasmVfsTargetPath = Path.GetRelativePath(MSBuildProjectDirectory, identity); + if (!string.IsNullOrEmpty(wasmVfsTargetPath)) + wasmVfsFile.SetMetadata("TargetPath", wasmVfsTargetPath); + } + + var outItem = new TaskItem(identity, item.CloneCustomMetadata()); + outItem.SetMetadata("ContentRoot", contentRoot); + outItem.SetMetadata("TargetPath", Path.Combine("wwwroot", targetPath)); + contentItems.Add(outItem); + + Log.LogMessage(MessageImportance.Low, $"Adding TargetPath '{targetPath}' and ContentRoot '{contentRoot}' for Identity '{identity}'."); + continue; + } + + // Case 3: update Link to point to wwwroot + if (!string.IsNullOrEmpty(link) && !link.StartsWith("wwwroot")) + { + var isRooted = Path.IsPathRooted(identity); + var contentRoot = isRooted ? Path.GetDirectoryName(identity) : Path.GetDirectoryName(Path.GetFullPath(identity, MSBuildProjectDirectory)); + + // Add Link to WasmFilesToIncludeInFileSystem + wasmFiles.Add(new TaskItem(link)); + + var outItem = new TaskItem(identity, item.CloneCustomMetadata()); + outItem.SetMetadata("ContentRoot", contentRoot); + outItem.SetMetadata("Link", Path.Combine("wwwroot", link)); + contentItems.Add(outItem); + + Log.LogMessage(MessageImportance.Low, $"Adding Link '{link}' and ContentRoot '{contentRoot}' for Identity '{identity}'."); + continue; + } + } + + WasmFilesToIncludeInFileSystem = wasmFiles.ToArray(); + ContentOut = contentItems.ToArray(); + + Log.LogMessage(MessageImportance.Low, $"Produced {WasmFilesToIncludeInFileSystem.Length} VFS files and {ContentOut.Length} content items."); + + return !Log.HasLoggedErrors; + } +} diff --git a/src/runtime/src/tests/Common/CLRTest.Execute.Batch.targets b/src/runtime/src/tests/Common/CLRTest.Execute.Batch.targets index 80b737c59ed9..33b5565f7f1e 100644 --- a/src/runtime/src/tests/Common/CLRTest.Execute.Batch.targets +++ b/src/runtime/src/tests/Common/CLRTest.Execute.Batch.targets @@ -298,7 +298,6 @@ IF defined DoLink ( REM Copy CORECLR native binaries and the test watcher to %LinkBin%, so that we can run the test based on that directory copy %CORE_ROOT%\clrjit.dll %LinkBin% > nul 2> nul copy %CORE_ROOT%\coreclr.dll %LinkBin% > nul 2> nul - copy %CORE_ROOT%\mscorrc.dll %LinkBin% > nul 2> nul copy %CORE_ROOT%\CoreRun.exe %LinkBin% > nul 2> nul copy %CORE_ROOT%\watchdog.exe %LinkBin% > nul 2> nul diff --git a/src/runtime/src/tests/Common/Directory.Build.targets b/src/runtime/src/tests/Common/Directory.Build.targets index 4e1a642f5680..cfd5edad2bdc 100644 --- a/src/runtime/src/tests/Common/Directory.Build.targets +++ b/src/runtime/src/tests/Common/Directory.Build.targets @@ -50,7 +50,6 @@ - diff --git a/src/runtime/src/tests/Common/helixpublishwitharcade.proj b/src/runtime/src/tests/Common/helixpublishwitharcade.proj index fa4ecc1faf92..b6f088410b1c 100644 --- a/src/runtime/src/tests/Common/helixpublishwitharcade.proj +++ b/src/runtime/src/tests/Common/helixpublishwitharcade.proj @@ -74,6 +74,8 @@ $([MSBuild]::NormalizeDirectory($(LegacyPayloadsRootDirectory))) $(TestBinDir)MergedPayloads\ $([MSBuild]::NormalizeDirectory($(MergedPayloadsRootDirectory))) + AppBundle + wwwroot @(_MergedWrapperRunScript->'%(RootDir)%(Directory)publish/*') - $(PublishedMergedPayloadsToExclude);@(_MergedWrapperRunScript->'%(RootDir)%(Directory)AppBundle/**') + $(PublishedMergedPayloadsToExclude);@(_MergedWrapperRunScript->'%(RootDir)%(Directory)$(MobileAppBundleDirName)/**') @@ -345,7 +347,7 @@ <_MergedWrapperMarker Update="@(_MergedWrapperMarker)"> $([System.IO.Path]::ChangeExtension('%(Identity)', '.$(TestScriptExtension)')) - %(RootDir)%(Directory)AppBundle/$(_AppBundleRunScriptName).$(TestScriptExtension) + %(RootDir)%(Directory)$(MobileAppBundleDirName)/$(_AppBundleRunScriptName).$(TestScriptExtension) @@ -490,7 +492,7 @@ <_MergedPayloadGroups Include="$(_MergedWrapperName)"> $(_MergedApkName) - <_MergedPayloadApkFiles Include="@(_MergedPayloadGroups->'$(_MergedWrapperDirectory)AppBundle/bin/%(ApkPackageName).apk')" /> + <_MergedPayloadApkFiles Include="@(_MergedPayloadGroups->'$(_MergedWrapperDirectory)$(MobileAppBundleDirName)/bin/%(ApkPackageName).apk')" /> <_MergedPayloadFiles Include="@(_MergedPayloadApkFiles)" /> <_MergedPayloadFiles Include="$(_MergedWrapperDirectory)ExpectedExitCode.txt" Condition="Exists('$(_MergedWrapperDirectory)ExpectedExitCode.txt')" /> @@ -506,24 +508,24 @@ Outputs="%(_MergedWrapperMarker.FileName)" DependsOnTargets="DiscoverMergedTestWrappers;GetTestExclusionList"> - <_MergedWrapperRunScript Include="@(_MergedWrapperMarker->'%(RootDir)%(Directory)AppBundle/RunTests.$(TestScriptExtension)')" /> + <_MergedWrapperRunScript Include="@(_MergedWrapperMarker->'%(RootDir)%(Directory)$(MobileAppBundleDirName)/RunTests.$(TestScriptExtension)')" /> <_MergedWrapperDirectory>%(_MergedWrapperMarker.RootDir)%(Directory) <_MergedWrapperName>%(_MergedWrapperMarker.FileName) - <_MergedWrapperRunScriptRelative Condition="'%(_MergedWrapperRunScript.Identity)' != ''">$([System.IO.Path]::GetRelativePath('$(_MergedWrapperDirectory)AppBundle', %(_MergedWrapperRunScript.FullPath))) + <_MergedWrapperRunScriptRelative Condition="'%(_MergedWrapperRunScript.Identity)' != ''">$([System.IO.Path]::GetRelativePath('$(_MergedWrapperDirectory)$(MobileAppBundleDirName)', %(_MergedWrapperRunScript.FullPath))) <_MergedWrapperRunScriptRelative Condition="'$(TestWrapperTargetsWindows)' != 'true'">./$(_MergedWrapperRunScriptRelative) <_MergedWrapperRunScriptDirectoryRelative Condition="'$(_MergedWrapperRunScriptRelative)' != ''">$([System.IO.Path]::GetDirectoryName($(_MergedWrapperRunScriptRelative))) <_MergedPayloadGroups Include="$(_MergedWrapperName)" /> - <_MergedPayloadFiles Include="$(_MergedWrapperDirectory)AppBundle/**" /> + <_MergedPayloadFiles Include="$(_MergedWrapperDirectory)$(MobileAppBundleDirName)/**" /> <_MergedPayloadFiles Update="@(_MergedPayloadFiles)"> - $([System.IO.Path]::GetRelativePath('$(_MergedWrapperDirectory)AppBundle', %(FullPath))) + $([System.IO.Path]::GetRelativePath('$(_MergedWrapperDirectory)$(MobileAppBundleDirName)', %(FullPath))) <_TestExclusionListPlaceholder Include="@(_MergedPayloadFiles)" Condition="$([System.String]::new('%(FileName)').EndsWith('TestExclusionList'))" /> @@ -568,11 +570,11 @@ <_MergedPayloadGroups Include="$(_MergedWrapperName)" /> - <_MergedPayloadFiles Include="$(_MergedWrapperDirectory)AppBundle/$(_MergedWrapperName)/$(Configuration)-$(XCodeSdk)/$(_MergedWrapperName).app/**" /> + <_MergedPayloadFiles Include="$(_MergedWrapperDirectory)$(MobileAppBundleDirName)/$(_MergedWrapperName)/$(Configuration)-$(XCodeSdk)/$(_MergedWrapperName).app/**" /> <_MergedPayloadFiles Update="@(_MergedPayloadFiles)"> - $([System.IO.Path]::GetRelativePath('$(_MergedWrapperDirectory)AppBundle/$(_MergedWrapperName)/$(Configuration)-$(XCodeSdk)', %(FullPath))) + $([System.IO.Path]::GetRelativePath('$(_MergedWrapperDirectory)$(MobileAppBundleDirName)/$(_MergedWrapperName)/$(Configuration)-$(XCodeSdk)', %(FullPath))) <_TestExclusionListPlaceholder Include="@(_MergedPayloadFiles)" Condition="$([System.String]::new('%(FileName)').EndsWith('TestExclusionList'))" /> @@ -598,11 +600,11 @@ <_MergedPayloadGroups Include="$(_MergedWrapperName)" /> - <_MergedPayloadFiles Include="$(_MergedWrapperDirectory)AppBundle/**" /> + <_MergedPayloadFiles Include="$(_MergedWrapperDirectory)$(MobileAppBundleDirName)/**" /> <_MergedPayloadFiles Update="@(_MergedPayloadFiles)" Condition="'@(_MergedPayloadFiles)' != ''" > - $([System.IO.Path]::GetRelativePath('$(_MergedWrapperDirectory)AppBundle/', %(FullPath))) + $([System.IO.Path]::GetRelativePath('$(_MergedWrapperDirectory)$(MobileAppBundleDirName)/', %(FullPath))) <_TestExclusionListPlaceholder Include="@(_MergedPayloadFiles)" Condition="$([System.String]::new('%(FileName)').EndsWith('TestExclusionList'))" /> diff --git a/src/runtime/src/tests/Common/wasm-test-runner/WasmTestRunner.proj b/src/runtime/src/tests/Common/wasm-test-runner/WasmTestRunner.proj index 86e54367f65b..ea1b54645096 100644 --- a/src/runtime/src/tests/Common/wasm-test-runner/WasmTestRunner.proj +++ b/src/runtime/src/tests/Common/wasm-test-runner/WasmTestRunner.proj @@ -15,7 +15,6 @@ $(TestBinDir)/WasmApp/ 99.0 true - true $(CORE_ROOT)\WasmAppBuilder\WasmAppBuilder.dll $(CORE_ROOT)\MonoAOTCompiler\MonoAOTCompiler.dll @@ -34,8 +33,6 @@ - - diff --git a/src/runtime/src/tests/FunctionalTests/TestAssets/StartupHookForFunctionalTest/StartupHookForFunctionalTest.csproj b/src/runtime/src/tests/FunctionalTests/TestAssets/StartupHookForFunctionalTest/StartupHookForFunctionalTest.csproj index 4f3961903db6..a7d49181c244 100644 --- a/src/runtime/src/tests/FunctionalTests/TestAssets/StartupHookForFunctionalTest/StartupHookForFunctionalTest.csproj +++ b/src/runtime/src/tests/FunctionalTests/TestAssets/StartupHookForFunctionalTest/StartupHookForFunctionalTest.csproj @@ -5,6 +5,7 @@ false false false + false diff --git a/src/runtime/src/tests/FunctionalTests/WebAssembly/Directory.Build.props b/src/runtime/src/tests/FunctionalTests/WebAssembly/Directory.Build.props index f0095527e9c4..3b55d7daa969 100644 --- a/src/runtime/src/tests/FunctionalTests/WebAssembly/Directory.Build.props +++ b/src/runtime/src/tests/FunctionalTests/WebAssembly/Directory.Build.props @@ -16,9 +16,8 @@ - - - + + diff --git a/src/runtime/src/tests/FunctionalTests/iOS/Device/Directory.Build.props b/src/runtime/src/tests/FunctionalTests/iOS/Device/Directory.Build.props index 680be4c0f552..efef1f3e3a40 100644 --- a/src/runtime/src/tests/FunctionalTests/iOS/Device/Directory.Build.props +++ b/src/runtime/src/tests/FunctionalTests/iOS/Device/Directory.Build.props @@ -7,4 +7,4 @@ - \ No newline at end of file + diff --git a/src/runtime/src/tests/FunctionalTests/iOS/Simulator/CoreCLR.Interpreter/Program.cs b/src/runtime/src/tests/FunctionalTests/iOS/Simulator/CoreCLR/Program.cs similarity index 100% rename from src/runtime/src/tests/FunctionalTests/iOS/Simulator/CoreCLR.Interpreter/Program.cs rename to src/runtime/src/tests/FunctionalTests/iOS/Simulator/CoreCLR/Program.cs diff --git a/src/runtime/src/tests/FunctionalTests/iOS/Simulator/CoreCLR.Interpreter/iOS.Simulator.CoreCLR.Interpreter.Test.csproj b/src/runtime/src/tests/FunctionalTests/iOS/Simulator/CoreCLR/iOS.CoreCLR.Interpreter.Test.csproj similarity index 76% rename from src/runtime/src/tests/FunctionalTests/iOS/Simulator/CoreCLR.Interpreter/iOS.Simulator.CoreCLR.Interpreter.Test.csproj rename to src/runtime/src/tests/FunctionalTests/iOS/Simulator/CoreCLR/iOS.CoreCLR.Interpreter.Test.csproj index 23315975066c..072f8102f157 100644 --- a/src/runtime/src/tests/FunctionalTests/iOS/Simulator/CoreCLR.Interpreter/iOS.Simulator.CoreCLR.Interpreter.Test.csproj +++ b/src/runtime/src/tests/FunctionalTests/iOS/Simulator/CoreCLR/iOS.CoreCLR.Interpreter.Test.csproj @@ -7,15 +7,11 @@ true $(NetCoreAppCurrent) iossimulator - iOS.Simulator.CoreCLR.Interpreter.Test.dll + iOS.CoreCLR.Interpreter.Test.dll false 42 - - - - diff --git a/src/runtime/src/tests/FunctionalTests/iOS/Simulator/CoreCLR/iOS.CoreCLR.R2R.Test.csproj b/src/runtime/src/tests/FunctionalTests/iOS/Simulator/CoreCLR/iOS.CoreCLR.R2R.Test.csproj new file mode 100644 index 000000000000..7afa3b159477 --- /dev/null +++ b/src/runtime/src/tests/FunctionalTests/iOS/Simulator/CoreCLR/iOS.CoreCLR.R2R.Test.csproj @@ -0,0 +1,19 @@ + + + Exe + false + false + false + true + $(NetCoreAppCurrent) + iossimulator + iOS.CoreCLR.R2R.Test.dll + false + 42 + true + + + + + + diff --git a/src/runtime/src/tests/Interop/COM/NETClients/ConsumeNETServer/ConsumeNETServer.csproj b/src/runtime/src/tests/Interop/COM/NETClients/ConsumeNETServer/ConsumeNETServer.csproj index 8902714d19b9..402f04ce472b 100644 --- a/src/runtime/src/tests/Interop/COM/NETClients/ConsumeNETServer/ConsumeNETServer.csproj +++ b/src/runtime/src/tests/Interop/COM/NETClients/ConsumeNETServer/ConsumeNETServer.csproj @@ -14,6 +14,7 @@ + diff --git a/src/runtime/src/tests/Interop/COM/NETClients/ConsumeNETServer/Program.cs b/src/runtime/src/tests/Interop/COM/NETClients/ConsumeNETServer/Program.cs index 2e51444ff211..8427e94e5853 100644 --- a/src/runtime/src/tests/Interop/COM/NETClients/ConsumeNETServer/Program.cs +++ b/src/runtime/src/tests/Interop/COM/NETClients/ConsumeNETServer/Program.cs @@ -1,17 +1,16 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +using TestLibrary; using Xunit; +using Server.Contract; namespace NetClient { - using System; - using System.Collections.Generic; - using System.Runtime.CompilerServices; - using System.Runtime.InteropServices; - - using TestLibrary; - using Xunit; - using Server.Contract; using CoClass = Server.Contract.Servers; @@ -105,7 +104,7 @@ static void Validate_Server_CCW_RCW() } [Fact] - public static int TestEntryPoint() + public static int ConsumeNETServerTests() { // RegFree COM is not supported on Windows Nano if (Utilities.IsWindowsNanoServer) @@ -141,5 +140,44 @@ public static int TestEntryPoint() return 100; } + + [Fact] + public static void Validate_IDispatch_Custom_DefaultInterface() + { + using (ComActivationHelpers.RegisterTypeForActivation()) + { + var myObjectType = Type.GetTypeFromCLSID(typeof(MyObject).GUID, throwOnError: true)!; + object obj = Activator.CreateInstance(myObjectType)!; + var iSecond = (ISecond)obj; + iSecond.Invoke2(); // Verify that we can invoke a method on a non-default IDispatch non-dual interface. + } + } } } + +[ComVisible(true)] +[ProgId("MyCompany.MyObject")] +[Guid("CF824E95-642E-4F8D-8CD1-F67BC588B107")] +[ClassInterface(ClassInterfaceType.None)] +[ComDefaultInterface(typeof(IFirst))] +public sealed class MyObject : IFirst, ISecond +{ + public void Invoke1() { } + public void Invoke2() { } +} + +[ComVisible(true)] +[Guid("59DAED5B-726B-4DDD-8F07-9236382038F7")] +[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] +public interface IFirst +{ + void Invoke1(); +} + +[ComVisible(true)] +[Guid("88C3FF65-0155-48A9-917D-E96DFAC8409B")] +[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] +public interface ISecond +{ + void Invoke2(); +} diff --git a/src/runtime/src/tests/Interop/common/ComActivationHelpers.cs b/src/runtime/src/tests/Interop/common/ComActivationHelpers.cs new file mode 100644 index 000000000000..1cf9bd22c1f0 --- /dev/null +++ b/src/runtime/src/tests/Interop/common/ComActivationHelpers.cs @@ -0,0 +1,82 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.InteropServices; + +public static class ComActivationHelpers +{ + public static IDisposable RegisterTypeForActivation() + where T: new() + { + Factory factory = new(() => new T()); + CoRegisterClassObject( + typeof(T).GUID, + factory, + 1, // CLSCTX_INPROC_SERVER + 1, // REGCLS_MULTIPLEUSE + out uint cookie); + return new RegistrationToken(cookie); + } + + private class RegistrationToken(uint token) : IDisposable + { + public void Dispose() + { + CoRevokeClassObject(token); + } + } + + [DllImport("ole32")] + private static extern int CoRegisterClassObject( + in Guid rclsid, + [MarshalAs(UnmanagedType.Interface)] IClassFactory pUnk, + uint dwClsContext, + uint flags, + out uint lpdwRegister); + + [DllImport("ole32")] + private static extern int CoRevokeClassObject(uint dwRegister); + + [ComImport] + [ComVisible(false)] + [Guid("00000001-0000-0000-C000-000000000046")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + private interface IClassFactory + { + void CreateInstance( + [MarshalAs(UnmanagedType.Interface)] object? pUnkOuter, + in Guid riid, + out nint ppvObject); + + void LockServer([MarshalAs(UnmanagedType.Bool)] bool fLock); + } + + private sealed class Factory(Func factory) : IClassFactory + { + public void CreateInstance(object? pUnkOuter, in Guid riid, out nint ppvObject) + { + if (pUnkOuter != null) + { + const int CLASS_E_NOAGGREGATION = unchecked((int)0x80040110); + Marshal.ThrowExceptionForHR(CLASS_E_NOAGGREGATION); + } + + nint ccw = Marshal.GetIUnknownForObject(factory()); + try + { + int hr = Marshal.QueryInterface(ccw, in riid, out ppvObject); + Marshal.ThrowExceptionForHR(hr); + } + finally + { + Marshal.Release(ccw); + } + } + + public void LockServer(bool fLock) + { + // No-op + } + } +} diff --git a/src/runtime/src/tests/JIT/Methodical/Methodical_others.csproj b/src/runtime/src/tests/JIT/Methodical/Methodical_others.csproj index 9106bfe6c520..dc1a42a69c7b 100644 --- a/src/runtime/src/tests/JIT/Methodical/Methodical_others.csproj +++ b/src/runtime/src/tests/JIT/Methodical/Methodical_others.csproj @@ -22,6 +22,7 @@ + diff --git a/src/runtime/src/tests/JIT/Methodical/delegate/DelegateToDelegate.cs b/src/runtime/src/tests/JIT/Methodical/delegate/DelegateToDelegate.cs new file mode 100644 index 000000000000..fa463d3e315e --- /dev/null +++ b/src/runtime/src/tests/JIT/Methodical/delegate/DelegateToDelegate.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.InteropServices; +using Xunit; + +public class DelegateToDelegate +{ + public delegate string OuterDelegate(); + + private static string InnerMethod() { + return "PASS"; + } + + [Fact] + public static int TestEntryPoint() { + int retVal = 100; + + Func innerDelegate = InnerMethod; + + // The initial issue where we observed a need for this test failed if the inner delegate type was used before we attempted to + innerDelegate(); + + var del = (OuterDelegate)Delegate.CreateDelegate(typeof(OuterDelegate), innerDelegate, typeof(Func).GetMethod ("Invoke")); + if (del() != "PASS") + retVal = 1; + + return retVal; + } +} diff --git a/src/runtime/src/tests/JIT/Regression/JitBlue/Runtime_122138/Runtime_122138.cs b/src/runtime/src/tests/JIT/Regression/JitBlue/Runtime_122138/Runtime_122138.cs new file mode 100644 index 000000000000..ae896d12e8e6 --- /dev/null +++ b/src/runtime/src/tests/JIT/Regression/JitBlue/Runtime_122138/Runtime_122138.cs @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.CompilerServices; +using Xunit; + +public class Runtime_122138 +{ + [MethodImpl(MethodImplOptions.NoOptimization)] + [Fact] + public static void TestEntryPoint() + { + var test = new Runtime_122138(); + test.Method1(0, 0, 0, 999, 999); + } + + private void Method1(int a, int b, int c, int value1, int? value2) + { + Method2(1, 2, 3, value1, value2); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private void Method2(long a, int b, int c, int? value1, int? value2) + { + Assert.Equal(value1, value2); + } +} \ No newline at end of file diff --git a/src/runtime/src/tests/JIT/Regression/Regression_ro_1.csproj b/src/runtime/src/tests/JIT/Regression/Regression_ro_1.csproj index b8858f86f96b..f2db4b637436 100644 --- a/src/runtime/src/tests/JIT/Regression/Regression_ro_1.csproj +++ b/src/runtime/src/tests/JIT/Regression/Regression_ro_1.csproj @@ -76,6 +76,7 @@ + diff --git a/src/runtime/src/tests/build.proj b/src/runtime/src/tests/build.proj index 8ba1b4eb2f3e..6869fcaa4a76 100644 --- a/src/runtime/src/tests/build.proj +++ b/src/runtime/src/tests/build.proj @@ -13,6 +13,8 @@ 1 C# $(TargetRid) + AppBundle + wwwroot @@ -232,7 +234,7 @@ - + @@ -390,7 +392,7 @@ - @(MergedAssemblyMarkerPaths->'%(RootDir)%(Directory)AppBundle/**/*.$(TestScriptExtension)') + @(MergedAssemblyMarkerPaths->'%(RootDir)%(Directory)$(MobileAppBundleDirName)/**/*.$(TestScriptExtension)') diff --git a/src/runtime/src/tests/ilverify/ILTests/AccessTests.ilproj b/src/runtime/src/tests/ilverify/ILTests/AccessTests.ilproj deleted file mode 100644 index 8e8765d14a52..000000000000 --- a/src/runtime/src/tests/ilverify/ILTests/AccessTests.ilproj +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/runtime/src/tests/ilverify/ILTests/AccessTestsExtern.ilproj b/src/runtime/src/tests/ilverify/ILTests/AccessTestsExtern.ilproj deleted file mode 100644 index 8e8765d14a52..000000000000 --- a/src/runtime/src/tests/ilverify/ILTests/AccessTestsExtern.ilproj +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/runtime/src/tests/ilverify/ILTests/AccessTestsFriend.ilproj b/src/runtime/src/tests/ilverify/ILTests/AccessTestsFriend.ilproj deleted file mode 100644 index 8e8765d14a52..000000000000 --- a/src/runtime/src/tests/ilverify/ILTests/AccessTestsFriend.ilproj +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/runtime/src/tests/ilverify/ILTests/ArrayTests.ilproj b/src/runtime/src/tests/ilverify/ILTests/ArrayTests.ilproj deleted file mode 100644 index 8e8765d14a52..000000000000 --- a/src/runtime/src/tests/ilverify/ILTests/ArrayTests.ilproj +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/runtime/src/tests/ilverify/ILTests/BasicArithmeticTests.ilproj b/src/runtime/src/tests/ilverify/ILTests/BasicArithmeticTests.ilproj deleted file mode 100644 index 8e8765d14a52..000000000000 --- a/src/runtime/src/tests/ilverify/ILTests/BasicArithmeticTests.ilproj +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/runtime/src/tests/ilverify/ILTests/BranchingTests.ilproj b/src/runtime/src/tests/ilverify/ILTests/BranchingTests.ilproj deleted file mode 100644 index 8e8765d14a52..000000000000 --- a/src/runtime/src/tests/ilverify/ILTests/BranchingTests.ilproj +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/runtime/src/tests/ilverify/ILTests/CallTests.ilproj b/src/runtime/src/tests/ilverify/ILTests/CallTests.ilproj deleted file mode 100644 index 8e8765d14a52..000000000000 --- a/src/runtime/src/tests/ilverify/ILTests/CallTests.ilproj +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/runtime/src/tests/ilverify/ILTests/CastingTests.ilproj b/src/runtime/src/tests/ilverify/ILTests/CastingTests.ilproj deleted file mode 100644 index 8e8765d14a52..000000000000 --- a/src/runtime/src/tests/ilverify/ILTests/CastingTests.ilproj +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/runtime/src/tests/ilverify/ILTests/ComparisonTests.ilproj b/src/runtime/src/tests/ilverify/ILTests/ComparisonTests.ilproj deleted file mode 100644 index 8e8765d14a52..000000000000 --- a/src/runtime/src/tests/ilverify/ILTests/ComparisonTests.ilproj +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/runtime/src/tests/ilverify/ILTests/DefaultInterfaceMethod.ilproj b/src/runtime/src/tests/ilverify/ILTests/DefaultInterfaceMethod.ilproj deleted file mode 100644 index 8e8765d14a52..000000000000 --- a/src/runtime/src/tests/ilverify/ILTests/DefaultInterfaceMethod.ilproj +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/runtime/src/tests/ilverify/ILTests/DelegateTests.ilproj b/src/runtime/src/tests/ilverify/ILTests/DelegateTests.ilproj deleted file mode 100644 index 8e8765d14a52..000000000000 --- a/src/runtime/src/tests/ilverify/ILTests/DelegateTests.ilproj +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/runtime/src/tests/ilverify/ILTests/ExceptionRegionTests.ilproj b/src/runtime/src/tests/ilverify/ILTests/ExceptionRegionTests.ilproj deleted file mode 100644 index 8e8765d14a52..000000000000 --- a/src/runtime/src/tests/ilverify/ILTests/ExceptionRegionTests.ilproj +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/runtime/src/tests/ilverify/ILTests/FieldTests.ilproj b/src/runtime/src/tests/ilverify/ILTests/FieldTests.ilproj deleted file mode 100644 index 8e8765d14a52..000000000000 --- a/src/runtime/src/tests/ilverify/ILTests/FieldTests.ilproj +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/runtime/src/tests/ilverify/ILTests/FtnTests.ilproj b/src/runtime/src/tests/ilverify/ILTests/FtnTests.ilproj deleted file mode 100644 index 8e8765d14a52..000000000000 --- a/src/runtime/src/tests/ilverify/ILTests/FtnTests.ilproj +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/runtime/src/tests/ilverify/ILTests/FunctionPointerTests.ilproj b/src/runtime/src/tests/ilverify/ILTests/FunctionPointerTests.ilproj deleted file mode 100644 index 8e8765d14a52..000000000000 --- a/src/runtime/src/tests/ilverify/ILTests/FunctionPointerTests.ilproj +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/runtime/src/tests/ilverify/ILTests/GenericInterface.ilproj b/src/runtime/src/tests/ilverify/ILTests/GenericInterface.ilproj deleted file mode 100644 index 8e8765d14a52..000000000000 --- a/src/runtime/src/tests/ilverify/ILTests/GenericInterface.ilproj +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/runtime/src/tests/ilverify/ILTests/InterfaceDefinition.ilproj b/src/runtime/src/tests/ilverify/ILTests/InterfaceDefinition.ilproj deleted file mode 100644 index 8e8765d14a52..000000000000 --- a/src/runtime/src/tests/ilverify/ILTests/InterfaceDefinition.ilproj +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/runtime/src/tests/ilverify/ILTests/InterfaceImplementation.ilproj b/src/runtime/src/tests/ilverify/ILTests/InterfaceImplementation.ilproj deleted file mode 100644 index 8e8765d14a52..000000000000 --- a/src/runtime/src/tests/ilverify/ILTests/InterfaceImplementation.ilproj +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/runtime/src/tests/ilverify/ILTests/LoadStoreIndirectTests.ilproj b/src/runtime/src/tests/ilverify/ILTests/LoadStoreIndirectTests.ilproj deleted file mode 100644 index 8e8765d14a52..000000000000 --- a/src/runtime/src/tests/ilverify/ILTests/LoadStoreIndirectTests.ilproj +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/runtime/src/tests/ilverify/ILTests/LocalAllocTests.ilproj b/src/runtime/src/tests/ilverify/ILTests/LocalAllocTests.ilproj deleted file mode 100644 index 8e8765d14a52..000000000000 --- a/src/runtime/src/tests/ilverify/ILTests/LocalAllocTests.ilproj +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/runtime/src/tests/ilverify/ILTests/NewobjTests.ilproj b/src/runtime/src/tests/ilverify/ILTests/NewobjTests.ilproj deleted file mode 100644 index 8e8765d14a52..000000000000 --- a/src/runtime/src/tests/ilverify/ILTests/NewobjTests.ilproj +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/runtime/src/tests/ilverify/ILTests/PrefixTests.ilproj b/src/runtime/src/tests/ilverify/ILTests/PrefixTests.ilproj deleted file mode 100644 index 8e8765d14a52..000000000000 --- a/src/runtime/src/tests/ilverify/ILTests/PrefixTests.ilproj +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/runtime/src/tests/ilverify/ILTests/ReturnTests.ilproj b/src/runtime/src/tests/ilverify/ILTests/ReturnTests.ilproj deleted file mode 100644 index 8e8765d14a52..000000000000 --- a/src/runtime/src/tests/ilverify/ILTests/ReturnTests.ilproj +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/runtime/src/tests/ilverify/ILTests/RuntimeAsyncTests.ilproj b/src/runtime/src/tests/ilverify/ILTests/RuntimeAsyncTests.ilproj deleted file mode 100644 index 8e8765d14a52..000000000000 --- a/src/runtime/src/tests/ilverify/ILTests/RuntimeAsyncTests.ilproj +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/runtime/src/tests/ilverify/ILTests/ShiftTests.ilproj b/src/runtime/src/tests/ilverify/ILTests/ShiftTests.ilproj deleted file mode 100644 index 8e8765d14a52..000000000000 --- a/src/runtime/src/tests/ilverify/ILTests/ShiftTests.ilproj +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/runtime/src/tests/ilverify/ILTests/ThisStateTests.ilproj b/src/runtime/src/tests/ilverify/ILTests/ThisStateTests.ilproj deleted file mode 100644 index 8e8765d14a52..000000000000 --- a/src/runtime/src/tests/ilverify/ILTests/ThisStateTests.ilproj +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/runtime/src/tests/ilverify/ILTests/ValueTypeTests.ilproj b/src/runtime/src/tests/ilverify/ILTests/ValueTypeTests.ilproj deleted file mode 100644 index 8e8765d14a52..000000000000 --- a/src/runtime/src/tests/ilverify/ILTests/ValueTypeTests.ilproj +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/runtime/src/tests/ilverify/ILVerificationTests.csproj b/src/runtime/src/tests/ilverify/ILVerificationTests.csproj deleted file mode 100644 index f9f7e7521ffa..000000000000 --- a/src/runtime/src/tests/ilverify/ILVerificationTests.csproj +++ /dev/null @@ -1,30 +0,0 @@ - - - $(BaseOutputPathWithConfig)ilverify\ - 1 - - true - true - true - true - - - - - - - - - - - - - - - - - false - Content - - - diff --git a/src/source-manifest.json b/src/source-manifest.json index 84a675f6d9e5..bb1f22788caf 100644 --- a/src/source-manifest.json +++ b/src/source-manifest.json @@ -79,10 +79,10 @@ "commitSha": "a01d6a0838430706cea74ad38e054c2877ffbfa1" }, { - "barId": 293425, + "barId": 293591, "path": "runtime", "remoteUri": "https://github.com/dotnet/runtime", - "commitSha": "8eb90a6dba628a6fbdc470277e64e4b9aa72994f" + "commitSha": "bce6119e41ecfbcf630c369836770669604c22c6" }, { "barId": 291013, From ba856da327400413564bfd32d0f1e96f07503f64 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 8 Dec 2025 08:58:08 +0000 Subject: [PATCH 3/4] [main] Source code updates from dotnet/arcade (#3715) [main] Source code updates from dotnet/arcade --- .../eng/common/core-templates/job/source-index-stage1.yml | 4 ++-- src/source-manifest.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/arcade/eng/common/core-templates/job/source-index-stage1.yml b/src/arcade/eng/common/core-templates/job/source-index-stage1.yml index 58b7a76814e0..76baf5c27258 100644 --- a/src/arcade/eng/common/core-templates/job/source-index-stage1.yml +++ b/src/arcade/eng/common/core-templates/job/source-index-stage1.yml @@ -3,7 +3,7 @@ parameters: sourceIndexBuildCommand: powershell -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "eng/common/build.ps1 -restore -build -binarylog -ci" preSteps: [] binlogPath: artifacts/log/Debug/Build.binlog - condition: '' + condition: eq(variables['Build.SourceBranch'], 'refs/heads/main') dependsOn: '' pool: '' is1ESPipeline: '' @@ -41,4 +41,4 @@ jobs: - template: /eng/common/core-templates/steps/source-index-stage1-publish.yml parameters: - binLogPath: ${{ parameters.binLogPath }} \ No newline at end of file + binLogPath: ${{ parameters.binLogPath }} diff --git a/src/source-manifest.json b/src/source-manifest.json index bb1f22788caf..3b5e64be7c29 100644 --- a/src/source-manifest.json +++ b/src/source-manifest.json @@ -1,10 +1,10 @@ { "repositories": [ { - "barId": 293486, + "barId": 293546, "path": "arcade", "remoteUri": "https://github.com/dotnet/arcade", - "commitSha": "1c09acb26525da819530dd2678a0b7f62c35cbfd" + "commitSha": "65e09c040143048211dcf6b2bd69336cbf27eec6" }, { "barId": 292447, From ce3dea8b1d1c12cf4b85999f834052d942d84a6d Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 8 Dec 2025 09:08:45 +0000 Subject: [PATCH 4/4] [main] Source code updates from dotnet/fsharp (#3718) [main] Source code updates from dotnet/fsharp --- src/fsharp/src/Compiler/Symbols/Exprs.fs | 39 +++- .../Compiler/TypedTree/TypedTreeBasics.fsi | 2 + .../src/Compiler/TypedTree/TypedTreeOps.fsi | 40 +++- .../ExprTests.fs | 190 ++++++++++++++++++ .../FSharpQuotations.fs | 122 ++++++++++- src/source-manifest.json | 4 +- 6 files changed, 388 insertions(+), 9 deletions(-) diff --git a/src/fsharp/src/Compiler/Symbols/Exprs.fs b/src/fsharp/src/Compiler/Symbols/Exprs.fs index 33c87edb597f..3a514db3df78 100644 --- a/src/fsharp/src/Compiler/Symbols/Exprs.fs +++ b/src/fsharp/src/Compiler/Symbols/Exprs.fs @@ -508,14 +508,47 @@ module FSharpExprConvert = and GetWitnessArgs cenv (env: ExprTranslationEnv) (vref: ValRef) m tps tyargs : FSharpExpr list = let g = cenv.g - if g.langVersion.SupportsFeature(Features.LanguageFeature.WitnessPassing) && not env.suppressWitnesses then - let witnessExprs = + if g.langVersion.SupportsFeature(Features.LanguageFeature.WitnessPassing) && not env.suppressWitnesses then + /// There are two *conditional* properties a typar can have: equality and comparison. + /// A generic type having that constraint may be conditional on whether a specific type parameter to that generic has that + /// constraint. + /// This function returns `true` iff after unification, the type definition contains any conditional typars. + /// + /// Note that these conditions are only marked on typars that actually appear in the code, *not* on phantom types. + /// So `hasConditionalTypar` should tell us exactly when the type parameter is actually being used in the type's equality or + /// comparison. + let rec hasConditionalTypar ty = + match stripTyEqns g ty with + | TType_var (tp, _) -> tp.ComparisonConditionalOn || tp.EqualityConditionalOn + | TType_app (_, tinst, _) -> tinst |> List.exists hasConditionalTypar + | _ -> false + + let witnessExprs = match ConstraintSolver.CodegenWitnessesForTyparInst cenv.tcValF g cenv.amap m tps tyargs with // There is a case where optimized code makes expressions that do a shift-left on the 'char' // type. There is no witness for this case. This is due to the code // let inline HashChar (x:char) = (# "or" (# "shl" x 16 : int #) x : int #) - // in FSharp.Core. + // in FSharp.Core. | ErrorResult _ when vref.LogicalName = "op_LeftShift" && List.isSingleton tyargs -> [] + // We don't need a witness either at compile time or runtime when there are conditional typars. + // Attempting to call a comparison operation with the type causes a compile-time check that all the generic type args + // support comparison (thanks to the ComparisonConditionalOn mechanism); the compile-time check doesn't need witnesses, + // it's just pure constraint solving. + // Nor do we need a witness for runtime logic: the compiler generates a `CompareTo` method (see + // `MakeValsForCompareAugmentation`) which handles the comparison by dynamically type-testing, not going through a witness. + // + // So we don't need to generate a witness. + // + // In fact, we *can't* generate a witness, because the constraint on the type parameter is only conditional: a rigid type + // parameter, defined without the `comparison` constraint, cannot have the constraint added to it later (that's what "rigid" + // means). It would change the type signature of the type to add this constraint to the type parameter! + // + // This code path is only reached through the auto-generated comparison/equality code, which only calls single-constraint + // intrinsics: there's exactly one constraint per type parameter in each of those two cases. + // In theory, if a function had an autogenerated `'a : comparison and 'b : SomethingElse`, where the `SomethingElse` was + // not comparison and failed for a different reason, we'd spuriously hide that failure here; but in fact the only code + // paths which get here have no other constraints. + | ErrorResult _ when List.exists hasConditionalTypar tyargs -> [] | res -> CommitOperationResult res let env = { env with suppressWitnesses = true } witnessExprs |> List.map (fun arg -> diff --git a/src/fsharp/src/Compiler/TypedTree/TypedTreeBasics.fsi b/src/fsharp/src/Compiler/TypedTree/TypedTreeBasics.fsi index 2b9372be3de9..4f67c7aa377a 100644 --- a/src/fsharp/src/Compiler/TypedTree/TypedTreeBasics.fsi +++ b/src/fsharp/src/Compiler/TypedTree/TypedTreeBasics.fsi @@ -141,6 +141,8 @@ val tryShortcutSolvedUnitPar: canShortcut: bool -> r: Typar -> Measure val stripUnitEqnsAux: canShortcut: bool -> unt: Measure -> Measure +/// Follows type variable solutions: when a type variable has been solved by unifying it with another type, +/// replaces that type variable with its solution. val stripTyparEqnsAux: nullness0: Nullness -> canShortcut: bool -> ty: TType -> TType val replaceNullnessOfTy: nullness: Nullness -> ty: TType -> TType diff --git a/src/fsharp/src/Compiler/TypedTree/TypedTreeOps.fsi b/src/fsharp/src/Compiler/TypedTree/TypedTreeOps.fsi index 72601a04aad7..a68ffaf8af1b 100755 --- a/src/fsharp/src/Compiler/TypedTree/TypedTreeOps.fsi +++ b/src/fsharp/src/Compiler/TypedTree/TypedTreeOps.fsi @@ -604,9 +604,41 @@ val reduceTyconRefMeasureableOrProvided: TcGlobals -> TyconRef -> TypeInst -> TT val reduceTyconRefAbbrevMeasureable: TyconRef -> Measure -/// set bool to 'true' to allow shortcutting of type parameter equation chains during stripping -val stripTyEqnsA: TcGlobals -> bool -> TType -> TType - +/// +/// Normalizes types. +/// +/// +/// Normalizes a type by: +/// +/// replacing type variables with their solutions found by unification +/// expanding type abbreviations +/// +/// as well as a couple of special-case normalizations: +/// +/// identifying int<1> with int (for any measurable type) +/// identifying byref<'T> with byref<'T, ByRefKinds.InOut> +/// +/// +/// +/// true to allow shortcutting of type parameter equation chains during stripping +/// +val stripTyEqnsA: TcGlobals -> canShortcut: bool -> TType -> TType + +/// +/// Normalizes types. +/// +/// +/// Normalizes a type by: +/// +/// replacing type variables with their solutions found by unification +/// expanding type abbreviations +/// +/// as well as a couple of special-case normalizations: +/// +/// identifying int<1> with int (for any measurable type) +/// identifying byref<'T> with byref<'T, ByRefKinds.InOut> +/// +/// val stripTyEqns: TcGlobals -> TType -> TType val stripTyEqnsAndMeasureEqns: TcGlobals -> TType -> TType @@ -707,6 +739,8 @@ val tcrefOfAppTy: TcGlobals -> TType -> TyconRef val tryTcrefOfAppTy: TcGlobals -> TType -> TyconRef voption +/// Returns ValueSome if this type is a type variable, even after abbreviations are expanded and +/// variables have been solved through unification. val tryDestTyparTy: TcGlobals -> TType -> Typar voption val tryDestFunTy: TcGlobals -> TType -> (TType * TType) voption diff --git a/src/fsharp/tests/FSharp.Compiler.Service.Tests/ExprTests.fs b/src/fsharp/tests/FSharp.Compiler.Service.Tests/ExprTests.fs index 2508675108f0..874c680a89c2 100644 --- a/src/fsharp/tests/FSharp.Compiler.Service.Tests/ExprTests.fs +++ b/src/fsharp/tests/FSharp.Compiler.Service.Tests/ExprTests.fs @@ -3504,3 +3504,193 @@ let ``Test ProjectForWitnesses4 GetWitnessPassingInfo`` () = printfn "actual:\n\n%A" actual actual |> shouldEqual expected + +//--------------------------------------------------------------------------------------------------------- +// Regression tests for ImmediateSubExpressions on generic types with conditional comparison/equality +// https://github.com/dotnet/fsharp/issues/19118 +// +// The bug: FCS crashes when accessing ImmediateSubExpressions on auto-generated comparison code +// for generic DUs/records whose type parameters have ComparisonConditionalOn but not actual +// comparison constraints. This is because GetWitnessArgs tries to generate witnesses for the +// comparison constraint, but fails because the type parameter is rigid and can't have constraints added. + +module internal ProjectForWitnessConditionalComparison = + + /// Helper to walk ALL expressions in a file, including ImmediateSubExpressions + /// This triggers the bug because it forces conversion of auto-generated comparison code + let walkAllExpressions (source : string) = + let fileName1 = System.IO.Path.ChangeExtension(getTemporaryFileName (), ".fs") + try + FileSystem.OpenFileForWriteShim(fileName1).Write(source) + let options = createProjectOptions [source] [] + let exprChecker = FSharpChecker.Create(keepAssemblyContents=true, useTransparentCompiler=CompilerAssertHelpers.UseTransparentCompiler) + let wholeProjectResults = exprChecker.ParseAndCheckProject(options) |> Async.RunImmediate + + if wholeProjectResults.Diagnostics.Length > 0 then + for diag in wholeProjectResults.Diagnostics do + printfn "Diagnostic: %s" diag.Message + + for implFile in wholeProjectResults.AssemblyContents.ImplementationFiles do + // Walk all declarations and their expressions, including ImmediateSubExpressions + let rec walkExpr (e: FSharpExpr) = + // Access ImmediateSubExpressions - this is what triggered #19118 + for subExpr in e.ImmediateSubExpressions do + walkExpr subExpr + + let rec walkDecl d = + match d with + | FSharpImplementationFileDeclaration.Entity (_, subDecls) -> + for subDecl in subDecls do + walkDecl subDecl + | FSharpImplementationFileDeclaration.MemberOrFunctionOrValue (_, _, e) -> + walkExpr e + | FSharpImplementationFileDeclaration.InitAction e -> + walkExpr e + + for decl in implFile.Declarations do + walkDecl decl + finally + try + FileSystem.FileDeleteShim fileName1 + with + | _ -> () + +[] +let ``ImmediateSubExpressions - generic DU with no constraints should not crash`` () = + // This is the core bug repro - a generic DU where the type parameter has + // ComparisonConditionalOn but no actual comparison constraint + let source = """ +module M + +type Bar<'appEvent> = + | Wibble of 'appEvent +""" + // This should not throw. Before the fix, it crashed with ConstraintSolverMissingConstraint. + ProjectForWitnessConditionalComparison.walkAllExpressions source + +[] +let ``ImmediateSubExpressions - generic DU with multiple type parameters should not crash`` () = + let source = """ +module M + +type MultiParam<'a, 'b, 'c> = + | Case1 of 'a + | Case2 of 'b * 'c + | Case3 of 'a * 'b * 'c +""" + ProjectForWitnessConditionalComparison.walkAllExpressions source + +[] +let ``ImmediateSubExpressions - generic record with no constraints should not crash`` () = + let source = """ +module M + +type MyRecord<'t> = { Value: 't; Name: string } +""" + ProjectForWitnessConditionalComparison.walkAllExpressions source + +[] +let ``ImmediateSubExpressions - generic struct DU should not crash`` () = + let source = """ +module M + +[] +type StructDU<'a> = + | StructCase of value: 'a +""" + ProjectForWitnessConditionalComparison.walkAllExpressions source + +[] +let ``ImmediateSubExpressions - nested generic types should not crash`` () = + let source = """ +module M + +type Outer<'a> = + | OuterCase of Inner<'a> + +and Inner<'b> = + | InnerCase of 'b +""" + ProjectForWitnessConditionalComparison.walkAllExpressions source + +[] +let ``ImmediateSubExpressions - generic DU with explicit comparison constraint works`` () = + // When the type parameter has the comparison constraint, witness generation should work; + // no crash occurred even before the bug was fixed. This test is here for completeness. + let source = """ +module M + +type WithConstraint<'a when 'a : comparison> = + | Constrained of 'a +""" + ProjectForWitnessConditionalComparison.walkAllExpressions source + +[] +let ``ImmediateSubExpressions - non-generic DU works`` () = + // Non-generic types always worked fine (no generics = no witness issues). This test is here for completeness. + let source = """ +module M + +type SimpleUnion = + | Case1 of int + | Case2 of string +""" + ProjectForWitnessConditionalComparison.walkAllExpressions source + +[] +let ``ImmediateSubExpressions - generic DU with NoComparison attribute should not crash`` () = + // With NoComparison, no comparison code is generated, so no crash ever occurred even before the bug was fixed. + // This test is here for completeness. + let source = """ +module M + +[] +type NoCompare<'a> = + | NoCompareCase of 'a +""" + ProjectForWitnessConditionalComparison.walkAllExpressions source + +[] +let ``ImmediateSubExpressions - generic DU with NoEquality attribute should not crash`` () = + let source = """ +module M + +[] +type NoEq<'a> = + | NoEqCase of 'a +""" + ProjectForWitnessConditionalComparison.walkAllExpressions source + +[] +let ``ImmediateSubExpressions - generic DU used in function should not crash`` () = + // Test that using the generic DU in actual code still works + let source = """ +module M + +type Option2<'t> = + | Some2 of 't + | None2 + +let mapOption2 f opt = + match opt with + | Some2 x -> Some2 (f x) + | None2 -> None2 +""" + ProjectForWitnessConditionalComparison.walkAllExpressions source + +[] +let ``ImmediateSubExpressions - complex generic type hierarchy should not crash`` () = + let source = """ +module M + +type Result<'ok, 'err> = + | Ok of 'ok + | Error of 'err + +type Validated<'a> = Result<'a, string list> + +let validate pred msg value : Validated<'a> = + if pred value then Ok value + else Error [msg] +""" + ProjectForWitnessConditionalComparison.walkAllExpressions source diff --git a/src/fsharp/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Quotations/FSharpQuotations.fs b/src/fsharp/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Quotations/FSharpQuotations.fs index a8ea2816a739..a61c8a97e2e1 100644 --- a/src/fsharp/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Quotations/FSharpQuotations.fs +++ b/src/fsharp/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Quotations/FSharpQuotations.fs @@ -5,6 +5,8 @@ namespace FSharp.Core.UnitTests.Quotations open System +open FSharp.Core.UnitTests +open FSharp.Core.UnitTests.Collections open FSharp.Core.UnitTests.LibraryTestFx open Xunit open FSharp.Quotations @@ -139,4 +141,122 @@ type FSharpQuotationsTests() = let expr = Expr.NewTuple [ <@@ 1 @@>; <@@ "" @@> ] match expr with | NewStructTuple _ -> Assert.Fail() - | _ -> () \ No newline at end of file + | _ -> () + +/// This fixture is here to test handling of EqualityConditionalOn and ComparisonConditionalOn. +/// We don't generate witnesses for equality and comparison if they're conditional; the tests +/// assert that code gen doesn't fail in those cases. +[] +module TestConditionalConstraints = + open FSharp.Linq.RuntimeHelpers + + let eval q = LeafExpressionConverter.EvaluateQuotation q + + type DiscriminatedUnionWithGeneric<'a> = + | Case of 'a + + [] + type ThingWithNoComparison = + | NoComparison + + [] + type ThingWithNoEquality = + | NoEquality + + override this.ToString () = + "NoEquality" + + let inline compare< ^T when ^T : comparison> (x : ^T) (y : ^T) : bool = + x < y + + let inline equate< ^T when ^T : equality> (x : ^T) (y : ^T) : bool = + x = y + + [] + let ``SRTP quotations can consume conditionally constrained types `` () = + // Just normal calls, no quotation + Assert.False (equate (DiscriminatedUnionWithGeneric.Case 3) (DiscriminatedUnionWithGeneric.Case 4)) + Assert.True (equate (DiscriminatedUnionWithGeneric.Case 3) (DiscriminatedUnionWithGeneric.Case 3)) + Assert.True (compare (DiscriminatedUnionWithGeneric.Case 3) (DiscriminatedUnionWithGeneric.Case 4)) + + // Typed quotation, int + <@ equate (DiscriminatedUnionWithGeneric.Case 3) (DiscriminatedUnionWithGeneric.Case 4) @> + |> eval + |> unbox + |> Assert.False + + <@ equate (DiscriminatedUnionWithGeneric.Case 3) (DiscriminatedUnionWithGeneric.Case 3) @> + |> eval + |> unbox + |> Assert.True + + <@ compare (DiscriminatedUnionWithGeneric.Case 3) (DiscriminatedUnionWithGeneric.Case 4) @> + |> eval + |> unbox + |> Assert.True + + // Untyped quotation, int + <@@ equate (DiscriminatedUnionWithGeneric.Case 3) (DiscriminatedUnionWithGeneric.Case 4) @@> + |> eval + |> unbox + |> Assert.False + + <@@ equate (DiscriminatedUnionWithGeneric.Case 3) (DiscriminatedUnionWithGeneric.Case 3) @@> + |> eval + |> unbox + |> Assert.True + + <@@ compare (DiscriminatedUnionWithGeneric.Case 3) (DiscriminatedUnionWithGeneric.Case 4) @@> + |> eval + |> unbox + |> Assert.True + + // Typed and untyped quotation, ThingWithNoComparison + <@ equate ThingWithNoComparison.NoComparison ThingWithNoComparison.NoComparison @> + |> eval + |> unbox + |> Assert.True + + <@@ equate ThingWithNoComparison.NoComparison ThingWithNoComparison.NoComparison @@> + |> eval + |> unbox + |> Assert.True + + // Typed and untyped quotation, ThingWithNoEquality + <@ (fun x -> x.ToString ()) ThingWithNoEquality.NoEquality @> + |> eval + |> unbox + |> fun s -> Assert.AreEqual (s, "NoEquality") + + <@@ (fun x -> x.ToString ()) ThingWithNoEquality.NoEquality @@> + |> eval + |> unbox + |> fun s -> Assert.AreEqual (s, "NoEquality") + + // This test isn't quotation-related, but it *is* closely related to the quotation test: both are checking + // we can cope without witnesses. + [] + let ``Reflective invocations of conditionally constrained types throw with a reasonable error`` () = + let compare = typeof.DeclaringType.GetMethod "compare" + let compare = compare.MakeGenericMethod([| typeof |]) + let exc = + try + compare.Invoke (null, [|ThingWithNoComparison.NoComparison ; ThingWithNoComparison.NoComparison|]) + |> ignore + None + with + | exc -> + Some exc + + Assert.Contains ("does not implement the System.IComparable interface", exc.Value.InnerException.Message, StringComparison.Ordinal) + + // This test isn't quotation-related, but it *is* closely related to the quotation test: both are checking + // we can cope without witnesses. + [] + let ``We still use Object.ReferenceEquals for non-equatable methods when reflectively invoked`` () = + let equate = typeof.DeclaringType.GetMethod "equate" + let equate = equate.MakeGenericMethod([| typeof |]) + let anotherOne = Activator.CreateInstance (typeof, nonPublic=true) + equate.Invoke (null, [| ThingWithNoEquality.NoEquality ; anotherOne |]) + |> unbox + |> Assert.False diff --git a/src/source-manifest.json b/src/source-manifest.json index 3b5e64be7c29..203579a7d27f 100644 --- a/src/source-manifest.json +++ b/src/source-manifest.json @@ -49,10 +49,10 @@ "commitSha": "f8b85873c9157f00b4951a78977fa87e3ab7c628" }, { - "barId": 293355, + "barId": 293499, "path": "fsharp", "remoteUri": "https://github.com/dotnet/fsharp", - "commitSha": "36868180d30ec3a74659d71fb183897807d60f81" + "commitSha": "89d788641914c5d0b87fddfa11f4df0b5cfaa73d" }, { "barId": 293177,