diff --git a/eng/DotNetBuild.props b/eng/DotNetBuild.props index 67554644b5cf8f..ef11ad4af6ecec 100644 --- a/eng/DotNetBuild.props +++ b/eng/DotNetBuild.props @@ -77,6 +77,7 @@ $(InnerBuildArgs) /p:MonoAOTEnableLLVM=$(DotNetBuildMonoAOTEnableLLVM) $(InnerBuildArgs) /p:MonoBundleLLVMOptimizer=$(DotNetBuildMonoBundleLLVMOptimizer) $(InnerBuildArgs) /p:DotNetBuildMonoCrossAOT=$(DotNetBuildMonoCrossAOT) + $(InnerBuildArgs) /p:DotNetBuildAllRuntimePacks=$(DotNetBuildAllRuntimePacks) $(InnerBuildArgs) $(FlagParameterPrefix)pgoinstrument diff --git a/eng/Publishing.props b/eng/Publishing.props index 9c2866118ede74..05a7d2e907063d 100644 --- a/eng/Publishing.props +++ b/eng/Publishing.props @@ -140,7 +140,7 @@ - - diff --git a/eng/Subsets.props b/eng/Subsets.props index 9c095300d7d7c6..d4621753cb63bd 100644 --- a/eng/Subsets.props +++ b/eng/Subsets.props @@ -25,20 +25,41 @@ + + + <_CoreCLRSupportedOS Condition="'$(TargetsMobile)' != 'true' and '$(TargetsLinuxBionic)' != 'true'">true + <_CoreCLRSupportedArch Condition="'$(TargetArchitecture)' != 'armv6' and '$(TargetArchitecture)' != 'ppc64le' and '$(TargetArchitecture)' != 's390x'">true + true + + + <_MonoSupportedOS>true + <_MonoSupportedArch Condition="!('$(TargetOS)' == 'windows' and '$(TargetArchitecture)' == 'arm64') and !('$(TargetsLinuxMusl)' == 'true' and ('$(TargetArchitecture)' == 'arm' or '$(TargetArchitecture)' == 'arm64')) and !('$(TargetsLinuxBionic)' == 'true' and '$(TargetArchitecture)' == 'arm')">true + true + + + <_MonoAotCrossSupportedOS Condition="'$(TargetsMobile)' != 'true' and '$(TargetsLinuxBionic)' != 'true'">true + <_MonoAotCrossSupportedArch Condition="'$(TargetArchitecture)' == 'x64' or '$(TargetArchitecture)' == 'arm64'">true + true + + + <_IsCommunityCrossArchitecture Condition="'$(CrossBuild)' == 'true' and ('$(TargetArchitecture)' == 'loongarch64' or '$(TargetArchitecture)' == 'riscv64')">true + <_NativeAotSupportedOS Condition="'$(TargetOS)' == 'windows' or '$(TargetOS)' == 'linux' or '$(TargetOS)' == 'osx' or '$(TargetOS)' == 'maccatalyst' or '$(TargetOS)' == 'iossimulator' or '$(TargetOS)' == 'ios' or '$(TargetOS)' == 'tvossimulator' or '$(TargetOS)' == 'tvos' or '$(TargetOS)' == 'freebsd'">true + <_NativeAotSupportedArch Condition="'$(TargetArchitecture)' == 'x64' or '$(TargetArchitecture)' == 'arm64' or '$(TargetArchitecture)' == 'arm' or '$(TargetArchitecture)' == 'loongarch64' or ('$(TargetOS)' == 'windows' and '$(TargetArchitecture)' == 'x86')">true + true + + CoreCLR - Mono - Mono - Mono - Mono - Mono + Mono $(DefaultPrimaryRuntimeFlavor) clr+mono+libs+tools+host+packs mono+libs+packs - mono+libs+host+packs + clr.nativeaotruntime+clr.nativeaotlibs+mono+libs+packs + clr.nativeaotruntime+clr.nativeaotlibs+mono+libs+host+packs + clr.nativeaotruntime+clr.nativeaotlibs+libs+packs clr+libs+tools+host+packs clr.nativeaotlibs+clr.nativeaotruntime+libs+packs @@ -50,16 +71,21 @@ true + + android+browser+wasi + $(MonoCrossAOTTargetOS)+tvos+ios+maccatalyst + + <_subset Condition="'$(Subset)' != ''">+$(Subset.ToLowerInvariant())+ <_subset Condition="'$(Subset)' == ''">+$(DefaultSubsets)+ - + Mono CoreCLR - Mono + Mono $(PrimaryRuntimeFlavor) @@ -82,6 +108,9 @@ $(DefaultMonoSubsets)mono.tools+ $(DefaultMonoSubsets)host.native+ + + mono.aotcross + libs.native+ @@ -95,6 +124,8 @@ $(DefaultHostSubsets)+host.pretest+host.tests host.native + + host.native+host.pkg packs.product $(DefaultPacksSubsets)+packs.installers @@ -120,11 +151,6 @@ - - <_IsCommunityCrossArchitecture Condition="'$(CrossBuild)' == 'true' and ('$(TargetArchitecture)' == 'loongarch64' or '$(TargetArchitecture)' == 'riscv64')">true - <_NativeAotSupportedOS Condition="'$(TargetOS)' == 'windows' or '$(TargetOS)' == 'linux' or '$(TargetOS)' == 'osx' or '$(TargetOS)' == 'maccatalyst' or '$(TargetOS)' == 'iossimulator' or '$(TargetOS)' == 'ios' or '$(TargetOS)' == 'tvossimulator' or '$(TargetOS)' == 'tvos' or '$(TargetOS)' == 'freebsd'">true - <_NativeAotSupportedArch Condition="'$(TargetArchitecture)' == 'x64' or '$(TargetArchitecture)' == 'arm64' or '$(TargetArchitecture)' == 'arm' or '$(TargetArchitecture)' == 'loongarch64' or ('$(TargetOS)' == 'windows' and '$(TargetArchitecture)' == 'x86')">true - true true @@ -517,7 +543,7 @@ - + @@ -532,33 +558,76 @@ - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + <_BuildCoreCLRRuntimePack Condition="'$(RuntimeFlavor)' == 'CoreCLR' and '$(CoreCLRSupported)' == 'true' and '$(BuildNativeAOTRuntimePack)' != 'true'">true + <_BuildMonoRuntimePack Condition="'$(RuntimeFlavor)' == 'Mono' and '$(MonoSupported)' == 'true' and '$(BuildNativeAOTRuntimePack)' != 'true'">true + <_BuildNativeAOTRuntimePack Condition="'$(BuildNativeAOTRuntimePack)' == 'true'">true + <_BuildHostPack Condition="'$(RuntimeFlavor)' == '$(PrimaryRuntimeFlavor)' and '$(TargetsMobile)' != 'true' and '$(BuildNativeAOTRuntimePack)' != 'true'">true + <_BuildBundle Condition="'$(BuildNativeAOTRuntimePack)' != 'true' and '$(RuntimeFlavor)' == '$(PrimaryRuntimeFlavor)' and '$(TargetsMobile)' != 'true'">true + + + + <_BuildCoreCLRRuntimePack Condition="'$(CoreCLRSupported)' == 'true'">true + <_BuildMonoRuntimePack Condition="'$(MonoSupported)' == 'true'">true + + + + + <_BuildCoreCLRRuntimePack Condition="'$(PrimaryRuntimeFlavor)' == 'CoreCLR'">true + <_BuildMonoRuntimePack Condition="'$(PrimaryRuntimeFlavor)' == 'Mono'">true + + + + <_BuildNativeAOTRuntimePack Condition="'$(NativeAOTSupported)' == 'true'">true + <_BuildHostPack Condition="'$(TargetsMobile)' != 'true' and !('$(TargetsLinuxBionic)' == 'true' and '$(TargetArchitecture)' == 'arm')">true + <_BuildBundle Condition="'$(TargetsMobile)' != 'true' and !('$(TargetsLinuxBionic)' == 'true' and '$(TargetArchitecture)' == 'arm')">true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 16ecf6a0ed48c6..aa757faca821db 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -60,14 +60,14 @@ 9e8bd520939ddfee686261267a1646c1b113d9e1 - + https://github.com/dotnet/emsdk - 6ee0290df7381d7b9c4887b440e1a2815dc72407 + 0de3165cb0d56323b6caaf8e9916d4d9e72da32d - + https://github.com/dotnet/emsdk - 6ee0290df7381d7b9c4887b440e1a2815dc72407 + 0de3165cb0d56323b6caaf8e9916d4d9e72da32d @@ -166,57 +166,57 @@ https://github.com/dotnet/arcade e7cb34898a1b610eb2a22591a2178da6f1fb7e3c - + https://github.com/dotnet/runtime-assets - eb4194502b1eb78fe0bda938d633eac5f0968c1d + 6082ed1bb2cfd2d394cdc0ec613c88f3754041f7 - + https://github.com/dotnet/runtime-assets - eb4194502b1eb78fe0bda938d633eac5f0968c1d + 6082ed1bb2cfd2d394cdc0ec613c88f3754041f7 - + https://github.com/dotnet/runtime-assets - eb4194502b1eb78fe0bda938d633eac5f0968c1d + 6082ed1bb2cfd2d394cdc0ec613c88f3754041f7 - + https://github.com/dotnet/runtime-assets - eb4194502b1eb78fe0bda938d633eac5f0968c1d + 6082ed1bb2cfd2d394cdc0ec613c88f3754041f7 - + https://github.com/dotnet/runtime-assets - eb4194502b1eb78fe0bda938d633eac5f0968c1d + 6082ed1bb2cfd2d394cdc0ec613c88f3754041f7 - + https://github.com/dotnet/runtime-assets - eb4194502b1eb78fe0bda938d633eac5f0968c1d + 6082ed1bb2cfd2d394cdc0ec613c88f3754041f7 - + https://github.com/dotnet/runtime-assets - eb4194502b1eb78fe0bda938d633eac5f0968c1d + 6082ed1bb2cfd2d394cdc0ec613c88f3754041f7 - + https://github.com/dotnet/runtime-assets - eb4194502b1eb78fe0bda938d633eac5f0968c1d + 6082ed1bb2cfd2d394cdc0ec613c88f3754041f7 - + https://github.com/dotnet/runtime-assets - eb4194502b1eb78fe0bda938d633eac5f0968c1d + 6082ed1bb2cfd2d394cdc0ec613c88f3754041f7 - + https://github.com/dotnet/runtime-assets - eb4194502b1eb78fe0bda938d633eac5f0968c1d + 6082ed1bb2cfd2d394cdc0ec613c88f3754041f7 - + https://github.com/dotnet/runtime-assets - eb4194502b1eb78fe0bda938d633eac5f0968c1d + 6082ed1bb2cfd2d394cdc0ec613c88f3754041f7 - + https://github.com/dotnet/runtime-assets - eb4194502b1eb78fe0bda938d633eac5f0968c1d + 6082ed1bb2cfd2d394cdc0ec613c88f3754041f7 - + https://github.com/dotnet/runtime-assets - eb4194502b1eb78fe0bda938d633eac5f0968c1d + 6082ed1bb2cfd2d394cdc0ec613c88f3754041f7 https://github.com/dotnet/llvm-project @@ -372,9 +372,9 @@ https://github.com/dotnet/hotreload-utils 7d2f352486b2e39a7829fc7fefa7d6cf825deff5 - + https://github.com/dotnet/runtime-assets - eb4194502b1eb78fe0bda938d633eac5f0968c1d + 6082ed1bb2cfd2d394cdc0ec613c88f3754041f7 https://github.com/dotnet/roslyn @@ -438,41 +438,41 @@ https://github.com/NuGet/NuGet.Client 8fef55f5a55a3b4f2c96cd1a9b5ddc51d4b927f8 - + https://github.com/dotnet/node - a3f38a5efc1ec0104af7aa212451a6a8dba5af8c + 703264f70f553a06adfb330378c96f56b7583273 - + https://github.com/dotnet/node - a3f38a5efc1ec0104af7aa212451a6a8dba5af8c + 703264f70f553a06adfb330378c96f56b7583273 - + https://github.com/dotnet/node - a3f38a5efc1ec0104af7aa212451a6a8dba5af8c + 703264f70f553a06adfb330378c96f56b7583273 - + https://github.com/dotnet/node - a3f38a5efc1ec0104af7aa212451a6a8dba5af8c + 703264f70f553a06adfb330378c96f56b7583273 - + https://github.com/dotnet/node - a3f38a5efc1ec0104af7aa212451a6a8dba5af8c + 703264f70f553a06adfb330378c96f56b7583273 - + https://github.com/dotnet/node - a3f38a5efc1ec0104af7aa212451a6a8dba5af8c + 703264f70f553a06adfb330378c96f56b7583273 - + https://github.com/dotnet/node - a3f38a5efc1ec0104af7aa212451a6a8dba5af8c + 703264f70f553a06adfb330378c96f56b7583273 - + https://github.com/dotnet/node - a3f38a5efc1ec0104af7aa212451a6a8dba5af8c + 703264f70f553a06adfb330378c96f56b7583273 - + https://github.com/dotnet/runtime-assets - eb4194502b1eb78fe0bda938d633eac5f0968c1d + 6082ed1bb2cfd2d394cdc0ec613c88f3754041f7 diff --git a/eng/Versions.props b/eng/Versions.props index a6da06d19e2472..49c75940b4b650 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -142,21 +142,21 @@ 8.0.0 8.0.0 - 10.0.0-beta.25057.1 - 10.0.0-beta.25057.1 - 10.0.0-beta.25057.1 - 10.0.0-beta.25057.1 - 10.0.0-beta.25057.1 - 10.0.0-beta.25057.1 - 10.0.0-beta.25057.1 - 10.0.0-beta.25057.1 - 10.0.0-beta.25057.1 - 10.0.0-beta.25057.1 - 10.0.0-beta.25057.1 - 10.0.0-beta.25057.1 - 10.0.0-beta.25057.1 - 10.0.0-beta.25057.1 - 10.0.0-beta.25057.1 + 10.0.0-beta.25060.2 + 10.0.0-beta.25060.2 + 10.0.0-beta.25060.2 + 10.0.0-beta.25060.2 + 10.0.0-beta.25060.2 + 10.0.0-beta.25060.2 + 10.0.0-beta.25060.2 + 10.0.0-beta.25060.2 + 10.0.0-beta.25060.2 + 10.0.0-beta.25060.2 + 10.0.0-beta.25060.2 + 10.0.0-beta.25060.2 + 10.0.0-beta.25060.2 + 10.0.0-beta.25060.2 + 10.0.0-beta.25060.2 10.0.0-prerelease.24610.1 10.0.0-prerelease.24610.1 @@ -251,7 +251,7 @@ Note: when the name is updated, make sure to update dependency name in eng/pipelines/common/xplat-setup.yml like - DarcDependenciesChanged.Microsoft_NET_Workload_Emscripten_Current_Manifest-10_0_100_Transport --> - 10.0.0-alpha.1.25058.3 + 10.0.0-alpha.1.25059.1 $(MicrosoftNETWorkloadEmscriptenCurrentManifest100100TransportVersion) 1.1.87-gba258badda @@ -270,7 +270,7 @@ 1.0.406601 $(MicrosoftDotNetApiCompatTaskVersion) - 10.0.0-alpha.1.25056.2 + 10.0.0-alpha.1.25057.1 $(MicrosoftNETRuntimeEmscriptenVersion) $(runtimewinx64MicrosoftNETCoreRuntimeWasmNodeTransportPackageVersion) diff --git a/eng/pipelines/common/platform-matrix-multijob.yml b/eng/pipelines/common/platform-matrix-multijob.yml deleted file mode 100644 index 5aa172664bce51..00000000000000 --- a/eng/pipelines/common/platform-matrix-multijob.yml +++ /dev/null @@ -1,13 +0,0 @@ -# Use one list of platforms to create build jobs for multiple templates. Avoids -# platform list duplication. -parameters: - jobTemplates: [] - platforms: [] - -jobs: - -- ${{ each job in parameters.jobTemplates }}: - - template: /eng/pipelines/common/platform-matrix.yml - parameters: - platforms: ${{ parameters.platforms }} - ${{ insert }}: ${{ job }} diff --git a/eng/pipelines/coreclr/perf-non-wasm-jobs.yml b/eng/pipelines/coreclr/perf-non-wasm-jobs.yml index 81f20c32cd076a..9418fb0a517b88 100644 --- a/eng/pipelines/coreclr/perf-non-wasm-jobs.yml +++ b/eng/pipelines/coreclr/perf-non-wasm-jobs.yml @@ -1,5 +1,82 @@ parameters: - perfBranch: 'main' + - name: perfBranch + type: string + default: main + - name: crossgen + type: object + default: + enabled: true + configs: + - windows_x64 + - windows_x86 + - name: viperJitOptRepeat + type: object + default: + enabled: true + configs: + - windows_x64 + - linux_x64 + - name: viperMicro + type: object + default: + enabled: true + configs: + - windows_x64 + - linux_x64 + - name: owlMicro + type: object + default: + enabled: true + configs: + - windows_x64 + - linux_x64 + - name: tigerNoR2R + type: object + default: + enabled: true + configs: + - windows_x64 + - linux_x64 + - name: tigerNoPGO + type: object + default: + enabled: true + configs: + - windows_x64 + - linux_x64 + - name: tigerMicro + type: object + default: + enabled: true + configs: + - windows_x64 + - linux_x64 + - windown_x86 + - linux_musl_x64 + - name: tigerMonoAOT + type: object + default: + enabled: true + configs: + - linux_x64 + - name: tigerMonoInterpreter + type: object + default: + enabled: true + configs: + - linux_x64 + - name: tigerMono + type: object + default: + enabled: true + configs: + - linux_x64 + - name: androidMono + type: object + default: + enabled: true + configs: + - android_arm64 jobs: diff --git a/eng/pipelines/extra-platforms/runtime-extra-platforms-ioslike.yml b/eng/pipelines/extra-platforms/runtime-extra-platforms-ioslike.yml index 9a769124a05dcf..c123ea162e4d08 100644 --- a/eng/pipelines/extra-platforms/runtime-extra-platforms-ioslike.yml +++ b/eng/pipelines/extra-platforms/runtime-extra-platforms-ioslike.yml @@ -39,9 +39,9 @@ jobs: isExtraPlatforms: ${{ parameters.isExtraPlatformsBuild }} # Don't trim tests on rolling builds ${{ if eq(variables['isRollingBuild'], true) }}: - buildArgs: -s mono+libs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:DevTeamProvisioning=- /p:RunAOTCompilation=true $(_runSmokeTestsOnlyArg) /p:BuildTestsOnHelix=true /p:EnableAdditionalTimezoneChecks=true /p:UsePortableRuntimePack=true /p:BuildDarwinFrameworks=true /p:IsManualOrRollingBuild=true /p:EnableAggressiveTrimming=false + buildArgs: -s mono+libs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:DevTeamProvisioning=- /p:RunAOTCompilation=true $(_runSmokeTestsOnlyArg) /p:BuildTestsOnHelix=true /p:EnableAdditionalTimezoneChecks=true /p:UsePortableRuntimePack=false /p:BuildDarwinFrameworks=true /p:IsManualOrRollingBuild=true /p:EnableAggressiveTrimming=false ${{ else }}: - buildArgs: -s mono+libs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:DevTeamProvisioning=- /p:RunAOTCompilation=true $(_runSmokeTestsOnlyArg) /p:BuildTestsOnHelix=true /p:EnableAdditionalTimezoneChecks=true /p:UsePortableRuntimePack=true /p:BuildDarwinFrameworks=true /p:IsManualOrRollingBuild=true /p:EnableAggressiveTrimming=true + buildArgs: -s mono+libs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:DevTeamProvisioning=- /p:RunAOTCompilation=true $(_runSmokeTestsOnlyArg) /p:BuildTestsOnHelix=true /p:EnableAdditionalTimezoneChecks=true /p:UsePortableRuntimePack=false /p:BuildDarwinFrameworks=true /p:IsManualOrRollingBuild=true /p:EnableAggressiveTrimming=true timeoutInMinutes: 480 # extra steps, run tests postBuildSteps: diff --git a/eng/pipelines/libraries/fuzzing/deploy-to-onefuzz.yml b/eng/pipelines/libraries/fuzzing/deploy-to-onefuzz.yml index 2c9d95a807d11b..1f7a53fe649409 100644 --- a/eng/pipelines/libraries/fuzzing/deploy-to-onefuzz.yml +++ b/eng/pipelines/libraries/fuzzing/deploy-to-onefuzz.yml @@ -98,6 +98,14 @@ extends: SYSTEM_ACCESSTOKEN: $(System.AccessToken) displayName: Send HttpHeadersFuzzer to OneFuzz + - task: onefuzz-task@0 + inputs: + onefuzzOSes: 'Windows' + env: + onefuzzDropDirectory: $(fuzzerProject)/deployment/IPAddressFuzzer + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + displayName: Send IPAddressFuzzer to OneFuzz + - task: onefuzz-task@0 inputs: onefuzzOSes: 'Windows' diff --git a/eng/pipelines/libraries/helix-queues-setup.yml b/eng/pipelines/libraries/helix-queues-setup.yml index 42de807c32dbd8..41ae3ed5189361 100644 --- a/eng/pipelines/libraries/helix-queues-setup.yml +++ b/eng/pipelines/libraries/helix-queues-setup.yml @@ -126,7 +126,6 @@ jobs: - ${{ if ne(parameters.jobParameters.testScope, 'outerloop') }}: - (Windows.10.Amd64.ServerRS5.Open)windows.10.amd64.serverrs5.open@mcr.microsoft.com/dotnet-buildtools/prereqs:windowsservercore-ltsc2019-helix-amd64 - ${{ if or(ne(parameters.jobParameters.isExtraPlatformsBuild, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - - Windows.81.Amd64.Open - Windows.Amd64.Server2022.Open - Windows.11.Amd64.Client.Open - ${{ if eq(parameters.jobParameters.testScope, 'outerloop') }}: diff --git a/eng/pipelines/runtime-official.yml b/eng/pipelines/runtime-official.yml index 92ec42cb046514..4604248840acb0 100644 --- a/eng/pipelines/runtime-official.yml +++ b/eng/pipelines/runtime-official.yml @@ -73,7 +73,7 @@ extends: jobParameters: templatePath: 'templates-official' buildArgs: -s clr.runtime+clr.alljits+clr.nativeaotruntime -c $(_BuildConfig) /bl:$(Build.SourcesDirectory)/artifacts/logs/$(_BuildConfig)/CoreClrNativeBuild.binlog - nameSuffix: CoreCLR + nameSuffix: AllRuntimes isOfficialBuild: ${{ variables.isOfficialBuild }} timeoutInMinutes: 120 postBuildSteps: @@ -85,8 +85,8 @@ extends: # Now that we've signed the diagnostic files, do the rest of the build. - template: /eng/pipelines/common/templates/global-build-step.yml parameters: - buildArgs: -s clr.corelib+clr.nativecorelib+clr.nativeaotlibs+clr.tools+clr.packages+libs+host+packs -c $(_BuildConfig) - displayName: Build managed CoreCLR components, all libraries, hosts, and packs + buildArgs: -s clr.corelib+clr.nativecorelib+clr.nativeaotlibs+clr.tools+clr.packages+mono+libs+host+packs -c $(_BuildConfig) /p:DotNetBuildAllRuntimePacks=true + displayName: Build managed CoreCLR components, Mono, all libraries, hosts, and packs # Upload the results. - template: /eng/pipelines/common/upload-intermediate-artifacts-step.yml @@ -94,7 +94,7 @@ extends: name: $(osGroup)$(osSubgroup)_$(archType) # - # Build CoreCLR runtime packs + # Build all runtime packs # Mac x64/arm64 # Sign and entitle createdump and corerun after native build. # @@ -108,7 +108,7 @@ extends: jobParameters: templatePath: 'templates-official' buildArgs: -s clr.runtime+clr.alljits+clr.nativeaotruntime+host.native -c $(_BuildConfig) /bl:$(Build.SourcesDirectory)/artifacts/logs/$(_BuildConfig)/CoreClrNativeBuild.binlog - nameSuffix: CoreCLR + nameSuffix: AllRuntimes isOfficialBuild: ${{ variables.isOfficialBuild }} timeoutInMinutes: 120 postBuildSteps: @@ -136,8 +136,8 @@ extends: # Now that we've entitled and signed createdump, we can build the rest. - template: /eng/pipelines/common/templates/global-build-step.yml parameters: - buildArgs: -s clr.corelib+clr.nativecorelib+clr.nativeaotlibs+clr.tools+clr.packages+libs+host.tools+host.pkg+packs -c $(_BuildConfig) - displayName: Build managed CoreCLR and host components, all libraries, and packs + buildArgs: -s clr.corelib+clr.nativecorelib+clr.nativeaotlibs+clr.tools+clr.packages+mono+libs+host.tools+host.pkg+packs -c $(_BuildConfig) /p:DotNetBuildAllRuntimePacks=true + displayName: Build managed CoreCLR and host components, Mono, all libraries, and packs # Upload the results. - template: /eng/pipelines/common/upload-intermediate-artifacts-step.yml @@ -145,10 +145,8 @@ extends: name: $(osGroup)$(osSubgroup)_$(archType) # - # Build CoreCLR runtime packs - # Linux and Linux_musl - # CoreCLR runtime for CrossDac packaging - # Create Linux installers + # Build all runtime packs for Linux and Linux musl + # Upload CoreCLR runtime for CrossDac packaging # - template: /eng/pipelines/common/platform-matrix.yml parameters: @@ -163,8 +161,8 @@ extends: - linux_musl_arm64 jobParameters: templatePath: 'templates-official' - buildArgs: -s clr.runtime+clr.alljits+clr.corelib+clr.nativecorelib+clr.tools+clr.aot+clr.packages+libs+host+packs -c $(_BuildConfig) - nameSuffix: CoreCLR + buildArgs: -c $(_BuildConfig) /p:DotNetBuildAllRuntimePacks=true + nameSuffix: AllRuntimes isOfficialBuild: ${{ variables.isOfficialBuild }} timeoutInMinutes: 120 postBuildSteps: @@ -235,12 +233,12 @@ extends: parameters: name: windows_x64 dependsOn: - - build_linux_x64_release_CoreCLR - - build_linux_arm_release_CoreCLR - - build_linux_arm64_release_CoreCLR - - build_linux_musl_x64_release_CoreCLR - - build_linux_musl_arm_release_CoreCLR - - build_linux_musl_arm64_release_CoreCLR + - build_linux_x64_release_AllRuntimes + - build_linux_arm_release_AllRuntimes + - build_linux_arm64_release_AllRuntimes + - build_linux_musl_x64_release_AllRuntimes + - build_linux_musl_arm_release_AllRuntimes + - build_linux_musl_arm64_release_AllRuntimes variables: - name: crossDacArtifactsContainer value: CoreCLRCrossDacArtifacts @@ -250,60 +248,13 @@ extends: value: $(crossDacArtifactsBasePath)/$(crossDacArtifactsContainer) # - # Build NativeAOT runtime packs + # Build All runtime packs for mobile platforms # - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/common/global-build-job.yml buildConfig: release platforms: - - osx_x64 - - osx_arm64 - - maccatalyst_x64 - - maccatalyst_arm64 - - tvossimulator_x64 - - tvossimulator_arm64 - - tvos_arm64 - - iossimulator_x64 - - iossimulator_arm64 - - ios_arm64 - - linux_x64 - - linux_arm - - linux_arm64 - - linux_musl_x64 - - linux_musl_arm - - linux_musl_arm64 - - linux_bionic_x64 - - linux_bionic_arm - - linux_bionic_arm64 - - windows_x86 - - windows_x64 - - windows_arm64 - jobParameters: - templatePath: 'templates-official' - buildArgs: -c $(_BuildConfig) /p:DotNetBuildRuntimeNativeAOTRuntimePack=true - nameSuffix: NativeAOT - isOfficialBuild: ${{ variables.isOfficialBuild }} - postBuildSteps: - # delete Microsoft.NETCore.App.Ref package to prevent upload conflict - - task: DeleteFiles@1 - displayName: 'Delete Microsoft.NETCore.App.Ref package' - inputs: - SourceFolder: $(Build.SourcesDirectory)/artifacts/packages/$(_BuildConfig)/Shipping - Contents: 'Microsoft.NETCore.App.Ref.*.nupkg' - - template: /eng/pipelines/common/upload-intermediate-artifacts-step.yml - parameters: - name: NativeAOTRuntimePacks - - # - # Build Mono runtime packs - # - - template: /eng/pipelines/common/platform-matrix.yml - parameters: - jobTemplate: /eng/pipelines/common/global-build-job.yml - buildConfig: release - runtimeFlavor: mono - platforms: - android_x64 - android_x86 - android_arm @@ -316,34 +267,26 @@ extends: - iossimulator_x64 - iossimulator_arm64 - ios_arm64 - - osx_x64 - - osx_arm64 - - linux_x64 - - linux_arm - - linux_arm64 - - linux_musl_x64 - - linux_bionic_arm64 - linux_bionic_x64 - # - linux_musl_arm - # - linux_musl_arm64 - - windows_x64 - - windows_x86 - # - windows_arm64 + - linux_bionic_arm + - linux_bionic_arm64 jobParameters: templatePath: 'templates-official' - buildArgs: -s mono+libs+host+packs -c $(_BuildConfig) /p:BuildMonoAOTCrossCompiler=false - nameSuffix: Mono + buildArgs: -c $(_BuildConfig) /p:BuildMonoAOTCrossCompiler=false /p:DotNetBuildAllRuntimePacks=true + nameSuffix: AllRuntimes isOfficialBuild: ${{ variables.isOfficialBuild }} postBuildSteps: - # delete Microsoft.NETCore.App.Ref package to prevent upload conflict + # delete duplicate RIDless packages to prevent upload conflict - task: DeleteFiles@1 - displayName: 'Delete Microsoft.NETCore.App.Ref package' + displayName: 'Delete Microsoft.NETCore.App.Ref and Microsoft.NETCore.App.HostModel package' inputs: SourceFolder: $(Build.SourcesDirectory)/artifacts/packages/$(_BuildConfig)/Shipping - Contents: 'Microsoft.NETCore.App.Ref.*.nupkg' + Contents: | + 'Microsoft.NETCore.App.Ref.*.nupkg' + 'Microsoft.NET.HostModel.*.nupkg' - template: /eng/pipelines/common/upload-intermediate-artifacts-step.yml parameters: - name: MonoRuntimePacks + name: MobileRuntimePacks - template: /eng/pipelines/common/platform-matrix.yml parameters: @@ -359,15 +302,17 @@ extends: nameSuffix: Mono isOfficialBuild: ${{ variables.isOfficialBuild }} postBuildSteps: - # delete Microsoft.NETCore.App.Ref package to prevent upload conflict + # delete duplicate RIDless packages to prevent upload conflict - task: DeleteFiles@1 - displayName: 'Delete Microsoft.NETCore.App.Ref package' + displayName: 'Delete Microsoft.NETCore.App.Ref and Microsoft.NETCore.App.HostModel package' inputs: SourceFolder: $(Build.SourcesDirectory)/artifacts/packages/$(_BuildConfig)/Shipping - Contents: 'Microsoft.NETCore.App.Ref.*.nupkg' + Contents: | + 'Microsoft.NETCore.App.Ref.*.nupkg' + 'Microsoft.NET.HostModel.*.nupkg' - template: /eng/pipelines/common/upload-intermediate-artifacts-step.yml parameters: - name: MonoRuntimePacks + name: MobileRuntimePacks - template: /eng/pipelines/common/platform-matrix.yml parameters: @@ -383,75 +328,49 @@ extends: isOfficialBuild: ${{ variables.isOfficialBuild }} runtimeVariant: multithread postBuildSteps: - # delete Microsoft.NETCore.App.Ref package to prevent upload conflict + # delete duplicate RIDless packages to prevent upload conflict - task: DeleteFiles@1 - displayName: 'Delete Microsoft.NETCore.App.Ref package' + displayName: 'Delete Microsoft.NETCore.App.Ref and Microsoft.NETCore.App.HostModel package' inputs: SourceFolder: $(Build.SourcesDirectory)/artifacts/packages/$(_BuildConfig)/Shipping - Contents: 'Microsoft.NETCore.App.Ref.*.nupkg' + Contents: | + 'Microsoft.NETCore.App.Ref.*.nupkg' + 'Microsoft.NET.HostModel.*.nupkg' - template: /eng/pipelines/common/upload-intermediate-artifacts-step.yml parameters: - name: MonoRuntimePacks + name: MobileRuntimePacks # - # Build Mono release AOT cross-compilers + # Build Mono LLVM runtime packs # - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/common/global-build-job.yml - runtimeFlavor: mono - buildConfig: release platforms: + - osx_x64 - linux_x64 - - linux_musl_x64 - linux_arm64 - - linux_musl_arm64 - - windows_arm64 - - windows_x64 - - osx_x64 - - osx_arm64 + buildConfig: release + runtimeFlavor: mono jobParameters: templatePath: 'templates-official' - buildArgs: -c $(_BuildConfig) /p:DotNetBuildMonoCrossAOT=true - nameSuffix: CrossAOT_Mono - runtimeVariant: crossaot + buildArgs: -s mono+libs+host+packs -c $(_BuildConfig) + /p:MonoEnableLLVM=true /p:MonoAOTEnableLLVM=true /p:MonoBundleLLVMOptimizer=true + nameSuffix: Mono_LLVMAOT + runtimeVariant: LLVMAOT isOfficialBuild: ${{ variables.isOfficialBuild }} postBuildSteps: + # delete duplicate RIDless packages to prevent upload conflict + - task: DeleteFiles@1 + displayName: 'Delete Microsoft.NETCore.App.Ref and Microsoft.NETCore.App.HostModel package' + inputs: + SourceFolder: $(Build.SourcesDirectory)/artifacts/packages/$(_BuildConfig)/Shipping + Contents: | + 'Microsoft.NETCore.App.Ref.*.nupkg' + 'Microsoft.NET.HostModel.*.nupkg' - template: /eng/pipelines/common/upload-intermediate-artifacts-step.yml parameters: - name: MonoRuntimePacks - - # - # Build Mono LLVM runtime packs - # - - template: /eng/pipelines/common/platform-matrix-multijob.yml - parameters: - platforms: - - osx_x64 - - linux_x64 - # - linux_arm - - linux_arm64 - # - linux_musl_x64 - # - linux_musl_arm64 - # - windows_x64 - # - windows_x86 - # - windows_arm64 - jobTemplates: - #LLVMAOT - - jobTemplate: /eng/pipelines/common/global-build-job.yml - buildConfig: release - runtimeFlavor: mono - jobParameters: - templatePath: 'templates-official' - buildArgs: -s mono+libs+host+packs -c $(_BuildConfig) - /p:MonoEnableLLVM=true /p:MonoAOTEnableLLVM=true /p:MonoBundleLLVMOptimizer=true - nameSuffix: Mono_LLVMAOT - runtimeVariant: LLVMAOT - isOfficialBuild: ${{ variables.isOfficialBuild }} - postBuildSteps: - - template: /eng/pipelines/common/upload-intermediate-artifacts-step.yml - parameters: - name: MonoRuntimePacks + name: $(osGroup)$(osSubgroup)_$(archType) # # Build libraries (all TFMs) and packages @@ -525,36 +444,36 @@ extends: artifact: 'IntermediateArtifacts' path: $(Build.SourcesDirectory)/artifacts/workloadPackages patterns: | - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.AOT.win-x64.Cross.android-*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.AOT.win-arm64.Cross.android-*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.AOT.win-x64.Cross.browser-wasm*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.AOT.win-arm64.Cross.browser-wasm*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.AOT.win-x64.Cross.wasi-wasm*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.AOT.win-arm64.Cross.wasi-wasm*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.android-*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.browser-wasm*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.multithread.browser-wasm*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.ios-*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.iossimulator-*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.maccatalyst-*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.multithread.browser-wasm*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.tvos-*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.tvossimulator-*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.wasi-wasm*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Workload.Mono.ToolChain.Current.Manifest*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Workload.Mono.ToolChain.net6.Manifest*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Workload.Mono.ToolChain.net7.Manifest*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Workload.Mono.ToolChain.net8.Manifest*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Workload.Mono.ToolChain.net9.Manifest*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Runtime.MonoTargets.Sdk*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Runtime.MonoAOTCompiler.Task*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Runtime.WebAssembly.Sdk*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Runtime.WebAssembly.Wasi*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Runtime.WebAssembly.Templates*.nupkg + IntermediateArtifacts/windows_x64/Shipping/Microsoft.NETCore.App.Runtime.AOT.win-x64.Cross.android-*.nupkg + IntermediateArtifacts/windows_arm64/Shipping/Microsoft.NETCore.App.Runtime.AOT.win-arm64.Cross.android-*.nupkg + IntermediateArtifacts/windows_x64/Shipping/Microsoft.NETCore.App.Runtime.AOT.win-x64.Cross.browser-wasm*.nupkg + IntermediateArtifacts/windows_arm64/Shipping/Microsoft.NETCore.App.Runtime.AOT.win-arm64.Cross.browser-wasm*.nupkg + IntermediateArtifacts/windows_x64/Shipping/Microsoft.NETCore.App.Runtime.AOT.win-x64.Cross.wasi-wasm*.nupkg + IntermediateArtifacts/windows_arm64/Shipping/Microsoft.NETCore.App.Runtime.AOT.win-arm64.Cross.wasi-wasm*.nupkg + IntermediateArtifacts/MobileRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.android-*.nupkg + IntermediateArtifacts/MobileRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.browser-wasm*.nupkg + IntermediateArtifacts/MobileRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.multithread.browser-wasm*.nupkg + IntermediateArtifacts/MobileRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.ios-*.nupkg + IntermediateArtifacts/MobileRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.iossimulator-*.nupkg + IntermediateArtifacts/MobileRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.maccatalyst-*.nupkg + IntermediateArtifacts/MobileRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.multithread.browser-wasm*.nupkg + IntermediateArtifacts/MobileRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.tvos-*.nupkg + IntermediateArtifacts/MobileRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.tvossimulator-*.nupkg + IntermediateArtifacts/MobileRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.wasi-wasm*.nupkg + IntermediateArtifacts/MobileRuntimePacks/Shipping/Microsoft.NET.Workload.Mono.ToolChain.Current.Manifest*.nupkg + IntermediateArtifacts/MobileRuntimePacks/Shipping/Microsoft.NET.Workload.Mono.ToolChain.net6.Manifest*.nupkg + IntermediateArtifacts/MobileRuntimePacks/Shipping/Microsoft.NET.Workload.Mono.ToolChain.net7.Manifest*.nupkg + IntermediateArtifacts/MobileRuntimePacks/Shipping/Microsoft.NET.Workload.Mono.ToolChain.net8.Manifest*.nupkg + IntermediateArtifacts/MobileRuntimePacks/Shipping/Microsoft.NET.Workload.Mono.ToolChain.net9.Manifest*.nupkg + IntermediateArtifacts/MobileRuntimePacks/Shipping/Microsoft.NET.Runtime.MonoTargets.Sdk*.nupkg + IntermediateArtifacts/MobileRuntimePacks/Shipping/Microsoft.NET.Runtime.MonoAOTCompiler.Task*.nupkg + IntermediateArtifacts/MobileRuntimePacks/Shipping/Microsoft.NET.Runtime.WebAssembly.Sdk*.nupkg + IntermediateArtifacts/MobileRuntimePacks/Shipping/Microsoft.NET.Runtime.WebAssembly.Wasi*.nupkg + IntermediateArtifacts/MobileRuntimePacks/Shipping/Microsoft.NET.Runtime.WebAssembly.Templates*.nupkg IntermediateArtifacts/windows_arm64/Shipping/Microsoft.NETCore.App.Runtime.win-arm64*.nupkg IntermediateArtifacts/windows_x64/Shipping/Microsoft.NETCore.App.Runtime.win-x64*.nupkg IntermediateArtifacts/windows_x86/Shipping/Microsoft.NETCore.App.Runtime.win-x86*.nupkg - IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Sdk.WebAssembly.Pack*.nupkg + IntermediateArtifacts/MobileRuntimePacks/Shipping/Microsoft.NET.Sdk.WebAssembly.Pack*.nupkg - task: CopyFiles@2 displayName: Flatten packages @@ -566,7 +485,7 @@ extends: flattenFolders: true buildArgs: -s mono.workloads -c $(_BuildConfig) /p:PackageSource=$(Build.SourcesDirectory)/artifacts/workloadPackages /p:WorkloadOutputPath=$(Build.SourcesDirectory)/artifacts/workloads - + postBuildSteps: # Prepare packages wrapping msis - task: CopyFiles@2 @@ -603,25 +522,23 @@ extends: isOfficialBuild: ${{ variables.isOfficialBuild }} timeoutInMinutes: 120 dependsOn: - - Build_android_arm_release_Mono - - Build_android_arm64_release_Mono - - Build_android_x86_release_Mono - - Build_android_x64_release_Mono + - Build_android_arm_release_AllRuntimes + - Build_android_arm64_release_AllRuntimes + - Build_android_x86_release_AllRuntimes + - Build_android_x64_release_AllRuntimes - Build_browser_wasm_Linux_release_Mono - Build_wasi_wasm_linux_release_Mono - - Build_ios_arm64_release_Mono - - Build_iossimulator_x64_release_Mono - - Build_iossimulator_arm64_release_Mono - - Build_maccatalyst_arm64_release_Mono - - Build_maccatalyst_x64_release_Mono - - Build_tvos_arm64_release_Mono - - Build_tvossimulator_arm64_release_Mono - - Build_tvossimulator_x64_release_Mono - - Build_windows_arm64_release_CrossAOT_Mono - - Build_windows_x64_release_CrossAOT_Mono - - Build_windows_x64_release_CoreCLR - - Build_windows_x86_release_CoreCLR - - Build_windows_arm64_release_CoreCLR + - Build_ios_arm64_release_AllRuntimes + - Build_iossimulator_x64_release_AllRuntimes + - Build_iossimulator_arm64_release_AllRuntimes + - Build_maccatalyst_arm64_release_AllRuntimes + - Build_maccatalyst_x64_release_AllRuntimes + - Build_tvos_arm64_release_AllRuntimes + - Build_tvossimulator_arm64_release_AllRuntimes + - Build_tvossimulator_x64_release_AllRuntimes + - Build_windows_x64_release_AllRuntimes + - Build_windows_x86_release_AllRuntimes + - Build_windows_arm64_release_AllRuntimes - ${{ if eq(variables.isOfficialBuild, true) }}: - template: /eng/pipelines/official/stages/publish.yml diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml index 49f615c82c5d23..a7b03da8ddd183 100644 --- a/eng/pipelines/runtime.yml +++ b/eng/pipelines/runtime.yml @@ -973,7 +973,7 @@ extends: jobParameters: testGroup: innerloop nameSuffix: AllSubsets_Mono - buildArgs: -s mono+libs+libs.tests+host+packs -c $(_BuildConfig) /p:ArchiveTests=true /p:DevTeamProvisioning=- /p:RunAOTCompilation=true /p:RunSmokeTestsOnly=true /p:BuildTestsOnHelix=true /p:EnableAdditionalTimezoneChecks=true /p:UsePortableRuntimePack=true /p:BuildDarwinFrameworks=true /p:EnableAggressiveTrimming=true + buildArgs: -s mono+libs+libs.tests+host+packs -c $(_BuildConfig) /p:ArchiveTests=true /p:DevTeamProvisioning=- /p:RunAOTCompilation=true /p:RunSmokeTestsOnly=true /p:BuildTestsOnHelix=true /p:EnableAdditionalTimezoneChecks=true /p:UsePortableRuntimePack=false /p:BuildDarwinFrameworks=true /p:EnableAggressiveTrimming=true timeoutInMinutes: 480 condition: >- or( diff --git a/eng/testing/tests.ioslike.targets b/eng/testing/tests.ioslike.targets index a59cce6c49aeea..e2e36415a31834 100644 --- a/eng/testing/tests.ioslike.targets +++ b/eng/testing/tests.ioslike.targets @@ -16,7 +16,7 @@ <_AOTBuildCommand Condition="'$(ContinuousIntegrationBuild)' != 'true'">$(_AOTBuildCommand) /p:RuntimeSrcDir=$(RepoRoot) /p:RuntimeConfig=$(Configuration) - <_AOTBuildCommand>$(_AOTBuildCommand) /p:XHARNESS_EXECUTION_DIR="$XHARNESS_EXECUTION_DIR" /p:RunAOTCompilation=$(RunAOTCompilation) /p:UseNativeAOTRuntime=$(UseNativeAOTRuntime) /p:TargetOS=$(TargetOS) /p:TargetArchitecture=$(TargetArchitecture) /p:MonoForceInterpreter=$(MonoForceInterpreter) /p:MonoEnableLLVM=true /p:DevTeamProvisioning=$(DevTeamProvisioning) /p:UsePortableRuntimePack=true /p:Configuration=$(Configuration) /p:EnableAggressiveTrimming=$(EnableAggressiveTrimming) + <_AOTBuildCommand>$(_AOTBuildCommand) /p:XHARNESS_EXECUTION_DIR="$XHARNESS_EXECUTION_DIR" /p:RunAOTCompilation=$(RunAOTCompilation) /p:UseNativeAOTRuntime=$(UseNativeAOTRuntime) /p:TargetOS=$(TargetOS) /p:TargetArchitecture=$(TargetArchitecture) /p:MonoForceInterpreter=$(MonoForceInterpreter) /p:MonoEnableLLVM=true /p:DevTeamProvisioning=$(DevTeamProvisioning) /p:UsePortableRuntimePack=$(UsePortableRuntimePack) /p:Configuration=$(Configuration) <_AOTBuildCommand Condition="'$(NativeLib)' != ''">$(_AOTBuildCommand) /p:NativeLib=$(NativeLib) /p:BundlesResources=$(BundlesResources) /p:ForceLibraryModeGenerateAppBundle=$(ForceLibraryModeGenerateAppBundle) <_AOTBuildCommand>$(_AOTBuildCommand) @@ -77,8 +77,6 @@ - @@ -156,12 +154,6 @@ <_AppleItemsToPass Include="@(ReferenceExtraPathFiles->'%(FileName)%(Extension)')" OriginalItemName__="AppleReferenceExtraPathFiles" /> - <_AppleItemsToPass Include="@(RuntimeHostConfigurationOption)" - OriginalItemName__="_AppleUsedRuntimeHostConfigurationOption" /> - - <_AppleItemsToPass Include="@(TrimmerRootAssembly)" - OriginalItemName__="TrimmerRootAssembly" /> - - + + true true $(NoWarn);IL2103;IL2025;IL2111;IL2122 - false false - false - false false - false - - + + false <_DefaultValueAttributeSupport Condition="'$(OverrideDefaultValueAndDesignerHostSupport)' == 'true'">true <_DesignerHostSupport Condition="'$(OverrideDefaultValueAndDesignerHostSupport)' == 'true'">true diff --git a/eng/testing/workloads-browser.targets b/eng/testing/workloads-browser.targets index 8f610916ff9837..ad279f9f506223 100644 --- a/eng/testing/workloads-browser.targets +++ b/eng/testing/workloads-browser.targets @@ -80,7 +80,7 @@ diff --git a/eng/testing/workloads-wasm.targets b/eng/testing/workloads-wasm.targets index cf7776018338ac..c6c5568818a34c 100644 --- a/eng/testing/workloads-wasm.targets +++ b/eng/testing/workloads-wasm.targets @@ -17,11 +17,10 @@ <_PropsForAOTCrossBuild Include="@(_DefaultPropsForNuGetBuild)" /> <_PropsForAOTCrossBuild Include="TestingWorkloads=true" /> <_PropsForAOTCrossBuild Include="RuntimeIdentifier=$(NETCoreSdkRuntimeIdentifier)" /> - <_PropsForAOTCrossBuild Include="TargetCrossRid=$(RIDForWorkload)" /> <_PropsForAOTCrossBuild Include="DisableSourceLink=true" /> diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs index 1bf9c90c514357..17bb50457648f5 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs @@ -200,7 +200,7 @@ private static partial void GetTypeCoreIgnoreCase(QCallAssembly assembly, int nestedTypeNamesLength, ObjectHandleOnStack retType); - internal Type? GetTypeCore(string typeName, ReadOnlySpan nestedTypeNames, bool throwOnError, bool ignoreCase) + internal Type? GetTypeCore(string typeName, ReadOnlySpan nestedTypeNames, bool throwOnFileNotFound, bool ignoreCase) { RuntimeAssembly runtimeAssembly = this; Type? type = null; @@ -224,14 +224,11 @@ private static partial void GetTypeCoreIgnoreCase(QCallAssembly assembly, ObjectHandleOnStack.Create(ref type)); } } - catch (FileNotFoundException) when (!throwOnError) + catch (FileNotFoundException) when (!throwOnFileNotFound) { return null; } - if (type == null && throwOnError) - throw new TypeLoadException(SR.Format(SR.ClassLoad_General /* TypeLoad_TypeNotFoundInAssembly */, typeName, FullName)); - return type; } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.CoreCLR.cs index 78e2422b341044..70b88afc0726bb 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.CoreCLR.cs @@ -213,7 +213,8 @@ internal static RuntimeType GetTypeReferencedByCustomAttribute(string typeName, { throw new TypeLoadException(assembly is null ? SR.Format(SR.TypeLoad_ResolveType, escapedTypeName) : - SR.Format(SR.TypeLoad_ResolveTypeFromAssembly, escapedTypeName, assembly.FullName)); + SR.Format(SR.TypeLoad_ResolveTypeFromAssembly, escapedTypeName, assembly.FullName), + typeName: escapedTypeName); } return null; } @@ -226,7 +227,7 @@ internal static RuntimeType GetTypeReferencedByCustomAttribute(string typeName, { if (_throwOnError) { - throw new TypeLoadException(SR.Format(SR.TypeLoad_ResolveType, escapedTypeName)); + throw new TypeLoadException(SR.Format(SR.TypeLoad_ResolveType, escapedTypeName), typeName: escapedTypeName); } return null; } @@ -235,13 +236,26 @@ internal static RuntimeType GetTypeReferencedByCustomAttribute(string typeName, if (assembly is RuntimeAssembly runtimeAssembly) { - string unescapedTypeName = TypeNameHelpers.Unescape(escapedTypeName); // Compat: Non-extensible parser allows ambiguous matches with ignore case lookup - if (!_extensibleParser || !_ignoreCase) + bool useReflectionForNestedTypes = _extensibleParser && _ignoreCase; + + type = runtimeAssembly.GetTypeCore(TypeNameHelpers.Unescape(escapedTypeName), useReflectionForNestedTypes ? default : nestedTypeNames, + throwOnFileNotFound: _throwOnError, ignoreCase: _ignoreCase); + + if (type is null) { - return runtimeAssembly.GetTypeCore(unescapedTypeName, nestedTypeNames, throwOnError: _throwOnError, ignoreCase: _ignoreCase); + if (_throwOnError) + { + throw new TypeLoadException(SR.Format(SR.TypeLoad_ResolveTypeFromAssembly, parsedName.FullName, runtimeAssembly.FullName), + typeName: parsedName.FullName); + } + return null; + } + + if (!useReflectionForNestedTypes) + { + return type; } - type = runtimeAssembly.GetTypeCore(unescapedTypeName, default, throwOnError: _throwOnError, ignoreCase: _ignoreCase); } else { @@ -268,7 +282,8 @@ internal static RuntimeType GetTypeReferencedByCustomAttribute(string typeName, if (_throwOnError) { throw new TypeLoadException(SR.Format(SR.TypeLoad_ResolveNestedType, - nestedTypeNames[i], (i > 0) ? nestedTypeNames[i - 1] : TypeNameHelpers.Unescape(escapedTypeName))); + nestedTypeNames[i], (i > 0) ? nestedTypeNames[i - 1] : TypeNameHelpers.Unescape(escapedTypeName)), + typeName: parsedName.FullName); } return null; } @@ -282,7 +297,7 @@ internal static RuntimeType GetTypeReferencedByCustomAttribute(string typeName, RuntimeAssembly? requestingAssembly = (RuntimeAssembly?)_requestingAssembly; if (requestingAssembly is not null) { - Type? type = requestingAssembly.GetTypeCore(typeName, nestedTypeNames, throwOnError: false, ignoreCase: _ignoreCase); + Type? type = requestingAssembly.GetTypeCore(typeName, nestedTypeNames, throwOnFileNotFound: false, ignoreCase: _ignoreCase); if (type is not null) return type; } @@ -290,7 +305,7 @@ internal static RuntimeType GetTypeReferencedByCustomAttribute(string typeName, RuntimeAssembly coreLib = (RuntimeAssembly)typeof(object).Assembly; if (requestingAssembly != coreLib) { - Type? type = coreLib.GetTypeCore(typeName, nestedTypeNames, throwOnError: false, ignoreCase: _ignoreCase); + Type? type = coreLib.GetTypeCore(typeName, nestedTypeNames, throwOnFileNotFound: false, ignoreCase: _ignoreCase); if (type is not null) return type; } @@ -298,13 +313,16 @@ internal static RuntimeType GetTypeReferencedByCustomAttribute(string typeName, RuntimeAssembly? resolvedAssembly = AssemblyLoadContext.OnTypeResolve(requestingAssembly, parsedName.FullName); if (resolvedAssembly is not null) { - Type? type = resolvedAssembly.GetTypeCore(typeName, nestedTypeNames, throwOnError: false, ignoreCase: _ignoreCase); + Type? type = resolvedAssembly.GetTypeCore(typeName, nestedTypeNames, throwOnFileNotFound: false, ignoreCase: _ignoreCase); if (type is not null) return type; } if (_throwOnError) - throw new TypeLoadException(SR.Format(SR.TypeLoad_ResolveTypeFromAssembly, parsedName.FullName, (requestingAssembly ?? coreLib).FullName)); + { + throw new TypeLoadException(SR.Format(SR.TypeLoad_ResolveTypeFromAssembly, parsedName.FullName, (requestingAssembly ?? coreLib).FullName), + typeName: parsedName.FullName); + } return null; } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Threading/Thread.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Threading/Thread.CoreCLR.cs index f63c420d7a02bc..c646bada45e01c 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Threading/Thread.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Threading/Thread.CoreCLR.cs @@ -490,5 +490,37 @@ private void ResetFinalizerThreadSlow() Priority = ThreadPriority.Highest; } } + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ThreadNative_PollGC")] + private static partial void ThreadNative_PollGC(); + + // GC Suspension is done by simply dropping into native code via p/invoke, and we reuse the p/invoke + // mechanism for suspension. On all architectures we should have the actual stub used for the check be implemented + // as a small assembly stub which checks the global g_TrapReturningThreads flag and tail-call to this helper + private static unsafe void PollGC() + { + NativeThreadState catchAtSafePoint = ((NativeThreadClass*)Thread.DirectOnThreadLocalData.pNativeThread)->m_State & NativeThreadState.TS_CatchAtSafePoint; + if (catchAtSafePoint != NativeThreadState.None) + { + ThreadNative_PollGC(); + } + } + + [StructLayout(LayoutKind.Sequential)] + private struct NativeThreadClass + { + public NativeThreadState m_State; + } + + private enum NativeThreadState + { + None = 0, + TS_AbortRequested = 0x00000001, // Abort the thread + TS_DebugSuspendPending = 0x00000008, // Is the debugger suspending threads? + TS_GCOnTransitions = 0x00000010, // Force a GC on stub transitions (GCStress only) + + // We require (and assert) that the following bits are less than 0x100. + TS_CatchAtSafePoint = (TS_AbortRequested | TS_DebugSuspendPending | TS_GCOnTransitions), + }; } } diff --git a/src/coreclr/debug/ee/debugger.h b/src/coreclr/debug/ee/debugger.h index 2a5c63200327ae..9da256056f71d0 100644 --- a/src/coreclr/debug/ee/debugger.h +++ b/src/coreclr/debug/ee/debugger.h @@ -3994,6 +3994,8 @@ HANDLE OpenWin32EventOrThrow( // Returns true if the specified IL offset has a special meaning (eg. prolog, etc.) bool DbgIsSpecialILOffset(DWORD offset); +#if defined(TARGET_WINDOWS) void FixupDispatcherContext(T_DISPATCHER_CONTEXT* pDispatcherContext, T_CONTEXT* pContext, PEXCEPTION_ROUTINE pUnwindPersonalityRoutine = NULL); +#endif #endif /* DEBUGGER_H_ */ diff --git a/src/coreclr/dlls/mscoree/coreclr/CMakeLists.txt b/src/coreclr/dlls/mscoree/coreclr/CMakeLists.txt index 6dd42fe2b2538c..aed404b39e5ae2 100644 --- a/src/coreclr/dlls/mscoree/coreclr/CMakeLists.txt +++ b/src/coreclr/dlls/mscoree/coreclr/CMakeLists.txt @@ -186,7 +186,6 @@ if(FEATURE_MERGE_JIT_AND_ENGINE) endif(FEATURE_MERGE_JIT_AND_ENGINE) if (CLR_CMAKE_TARGET_OSX) - include(CMakeFindFrameworks) find_library(FOUNDATION Foundation REQUIRED) endif() diff --git a/src/coreclr/ildasm/dasm.cpp b/src/coreclr/ildasm/dasm.cpp index 7a272cf27ca84a..e30cea034d29e9 100644 --- a/src/coreclr/ildasm/dasm.cpp +++ b/src/coreclr/ildasm/dasm.cpp @@ -1414,7 +1414,7 @@ mdToken ResolveReflectionNotation(BYTE* dataPtr, if(mAsmRefs) { mdToken tkResScope = 0; - mdToken tk=TokenFromRid(mdtAssemblyRef,1), tkmax=TokenFromRid(mdtAssemblyRef,mAsmRefs); + mdToken tk=TokenFromRid(1, mdtAssemblyRef), tkmax=TokenFromRid(mAsmRefs, mdtAssemblyRef); LPCSTR szAsmRefName; // these are dummies const void* pPKT, *pHash; @@ -1914,7 +1914,7 @@ BYTE* PrettyPrintCABlobValue(PCCOR_SIGNATURE &typePtr, for(n=0; n < numElements; n++) { if(n) appendStr(out," "); - sprintf_s(str, 64, "%.*g", 8, (double)(*((float*)dataPtr))); + sprintf_s(str, 64, "%#.8g", (double)(*((float*)dataPtr))); float df = (float)atof(str); // Must compare as underlying bytes, not floating point otherwise optimizer will // try to enregister and compare 80-bit precision number with 32-bit precision number!!!! @@ -1933,7 +1933,7 @@ BYTE* PrettyPrintCABlobValue(PCCOR_SIGNATURE &typePtr, { if(n) appendStr(out," "); char *pch; - sprintf_s(str, 64, "%.*g", 17, *((double*)dataPtr)); + sprintf_s(str, 64, "%#.17g", *((double*)dataPtr)); double df = strtod(str, &pch); // Must compare as underlying bytes, not floating point otherwise optimizer will // try to enregister and compare 80-bit precision number with 64-bit precision number!!!! @@ -2608,7 +2608,7 @@ void DumpDefaultValue(mdToken tok, __inout __nullterminated char* szString, void case ELEMENT_TYPE_R4: { char szf[32]; - sprintf_s(szf, 32, "%.*g", 8, (double)MDDV.m_fltValue); + sprintf_s(szf, 32, "%#.8g", (double)MDDV.m_fltValue); float df = (float)atof(szf); // Must compare as underlying bytes, not floating point otherwise optimizer will // try to enregister and compare 80-bit precision number with 32-bit precision number!!!! @@ -2622,7 +2622,7 @@ void DumpDefaultValue(mdToken tok, __inout __nullterminated char* szString, void case ELEMENT_TYPE_R8: { char szf[32], *pch; - sprintf_s(szf, 32, "%.*g", 17, MDDV.m_dblValue); + sprintf_s(szf, 32, "%#.17g", MDDV.m_dblValue); double df = strtod(szf, &pch); //atof(szf); szf[31]=0; // Must compare as underlying bytes, not floating point otherwise optimizer will diff --git a/src/coreclr/inc/jithelpers.h b/src/coreclr/inc/jithelpers.h index b34f77518b9d98..38114a9bbfcada 100644 --- a/src/coreclr/inc/jithelpers.h +++ b/src/coreclr/inc/jithelpers.h @@ -149,8 +149,8 @@ // GC support DYNAMICJITHELPER(CORINFO_HELP_STOP_FOR_GC, JIT_RareDisableHelper, METHOD__NIL) - JITHELPER(CORINFO_HELP_POLL_GC, JIT_PollGC, METHOD__NIL) - + DYNAMICJITHELPER(CORINFO_HELP_POLL_GC, JIT_PollGC, METHOD__THREAD__POLLGC) + JITHELPER(CORINFO_HELP_CHECK_OBJ, JIT_CheckObj, METHOD__NIL) // GC Write barrier support diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index bad18a06c30584..51220e99b352eb 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -2600,6 +2600,89 @@ AssertionIndex Compiler::optAssertionIsSubtype(GenTree* tree, GenTree* methodTab return NO_ASSERTION_INDEX; } +//------------------------------------------------------------------------------ +// optVNBasedFoldExpr_Call_Memset: Unrolls NI_System_SpanHelpers_Fill for constant length. +// +// Arguments: +// call - NI_System_SpanHelpers_Fill call to unroll +// +// Return Value: +// Returns a new tree or nullptr if nothing is changed. +// +GenTree* Compiler::optVNBasedFoldExpr_Call_Memset(GenTreeCall* call) +{ + assert(call->IsSpecialIntrinsic(this, NI_System_SpanHelpers_Fill)); + + CallArg* dstArg = call->gtArgs.GetUserArgByIndex(0); + CallArg* lenArg = call->gtArgs.GetUserArgByIndex(1); + CallArg* valArg = call->gtArgs.GetUserArgByIndex(2); + + var_types valType = valArg->GetSignatureType(); + unsigned lengthScale = genTypeSize(valType); + + if (lengthScale == 1) + { + // Lower expands it slightly better. + JITDUMP("...value's type is byte - leave it for lower to expand.\n"); + return nullptr; + } + + if (varTypeIsStruct(valType) || varTypeIsGC(valType)) + { + JITDUMP("...value's type is not supported - bail out.\n"); + return nullptr; + } + + ValueNum lenVN = vnStore->VNConservativeNormalValue(lenArg->GetNode()->gtVNPair); + if (!vnStore->IsVNConstant(lenVN)) + { + JITDUMP("...length is not a constant - bail out.\n"); + return nullptr; + } + + size_t len = vnStore->CoercedConstantValue(lenVN); + if ((len > getUnrollThreshold(Memset)) || + // The first condition prevents the overflow in the second condition. + // since both len and lengthScale are expected to be small at this point. + (len * lengthScale) > getUnrollThreshold(Memset)) + { + JITDUMP("...length is too big to unroll - bail out.\n"); + return nullptr; + } + + // Some arbitrary threshold if the value is not a constant, + // since it is unlikely that we can optimize it further. + if (!valArg->GetNode()->OperIsConst() && (len >= 8)) + { + JITDUMP("...length is too big to unroll for non-constant value - bail out.\n"); + return nullptr; + } + + // Spill the side effects directly in the args, we're going to + // pick them up in the following gtExtractSideEffList + GenTree* dst = fgMakeMultiUse(&dstArg->NodeRef()); + GenTree* val = fgMakeMultiUse(&valArg->NodeRef()); + + GenTree* result = nullptr; + gtExtractSideEffList(call, &result, GTF_ALL_EFFECT, true); + + for (size_t offset = 0; offset < len; offset++) + { + // Clone dst and add offset if necessary. + GenTree* offsetNode = gtNewIconNode((ssize_t)(offset * lengthScale), TYP_I_IMPL); + GenTree* currDst = gtNewOperNode(GT_ADD, dst->TypeGet(), gtCloneExpr(dst), offsetNode); + GenTreeStoreInd* storeInd = + gtNewStoreIndNode(valType, currDst, gtCloneExpr(val), GTF_IND_UNALIGNED | GTF_IND_ALLOW_NON_ATOMIC); + + // Merge with the previous result. + result = result == nullptr ? storeInd : gtNewOperNode(GT_COMMA, TYP_VOID, result, storeInd); + } + + JITDUMP("...optimized into STOREIND(s):\n"); + DISPTREE(result); + return result; +} + //------------------------------------------------------------------------------ // optVNBasedFoldExpr_Call_Memmove: Unrolls NI_System_SpanHelpers_Memmove/CORINFO_HELP_MEMCPY // if possible. This function effectively duplicates LowerCallMemmove. @@ -2758,6 +2841,11 @@ GenTree* Compiler::optVNBasedFoldExpr_Call(BasicBlock* block, GenTree* parent, G return optVNBasedFoldExpr_Call_Memmove(call); } + if (call->IsSpecialIntrinsic(this, NI_System_SpanHelpers_Fill)) + { + return optVNBasedFoldExpr_Call_Memset(call); + } + return nullptr; } @@ -4692,6 +4780,19 @@ GenTree* Compiler::optAssertionProp_Cast(ASSERT_VALARG_TP assertions, GenTreeCas return nullptr; } + // Try and see if we can make this cast into a cheaper zero-extending version + // if the input is known to be non-negative. + if (!cast->IsUnsigned() && genActualTypeIsInt(lcl) && cast->TypeIs(TYP_LONG) && (TARGET_POINTER_SIZE == 8)) + { + bool isKnownNonZero; + bool isKnownNonNegative; + optAssertionProp_RangeProperties(assertions, lcl, &isKnownNonZero, &isKnownNonNegative); + if (isKnownNonNegative) + { + cast->SetUnsigned(); + } + } + IntegralRange range = IntegralRange::ForCastInput(cast); AssertionIndex index = optAssertionIsSubrange(lcl, range, assertions); if (index != NO_ASSERTION_INDEX) diff --git a/src/coreclr/jit/codegenarmarch.cpp b/src/coreclr/jit/codegenarmarch.cpp index 07b08c3692a4e5..fb1e738f81451e 100644 --- a/src/coreclr/jit/codegenarmarch.cpp +++ b/src/coreclr/jit/codegenarmarch.cpp @@ -611,8 +611,6 @@ void CodeGen::genEmitGSCookieCheck(bool pushReg) { noway_assert(compiler->gsGlobalSecurityCookieAddr || compiler->gsGlobalSecurityCookieVal); - assert(GetEmitter()->emitGCDisabled()); - // We need two temporary registers, to load the GS cookie values and compare them. We can't use // any argument registers if 'pushReg' is true (meaning we have a JMP call). They should be // callee-trash registers, which should not contain anything interesting at this point. diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index ef5a45a8c7841c..4e5c864d34b631 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -1516,47 +1516,34 @@ void CodeGen::genExitCode(BasicBlock* block) genIPmappingAdd(IPmappingDscKind::Epilog, DebugInfo(), true); bool jmpEpilog = block->HasFlag(BBF_HAS_JMP); - if (compiler->getNeedsGSSecurityCookie()) - { -#ifndef JIT32_GCENCODER - // At this point the gc info that we track in codegen is often incorrect, - // as it could be missing return registers or arg registers (in a case of tail call). - // GS cookie check will emit a call and that will pass our GC info to emit and potentially mess things up. - // While we could infer returns/args and force them to be live and it seems to work in JIT32_GCENCODER case, - // it appears to be nontrivial in more general case. - // So, instead, we just claim that the whole thing is not GC-interruptible. - // Effectively this starts the epilog a few instructions earlier. - // - // CONSIDER: is that a good place to be that codegen loses track of returns/args at this point? - GetEmitter()->emitDisableGC(); -#endif - genEmitGSCookieCheck(jmpEpilog); - -#ifdef JIT32_GCENCODER - if (jmpEpilog) +#ifdef DEBUG + // For returnining epilogs do some validation that the GC info looks right. + if (!jmpEpilog) + { + if (compiler->compMethodReturnsRetBufAddr()) { - // Dev10 642944 - - // The GS cookie check created a temp label that has no live - // incoming GC registers, we need to fix that - - unsigned varNum; - LclVarDsc* varDsc; - - /* Figure out which register parameters hold pointers */ + assert((gcInfo.gcRegByrefSetCur & RBM_INTRET) != RBM_NONE); + } + else + { + const ReturnTypeDesc& retTypeDesc = compiler->compRetTypeDesc; + const unsigned regCount = retTypeDesc.GetReturnRegCount(); - for (varNum = 0, varDsc = compiler->lvaTable; varNum < compiler->lvaCount && varDsc->lvIsRegArg; - varNum++, varDsc++) + for (unsigned i = 0; i < regCount; ++i) { - noway_assert(varDsc->lvIsParam); - - gcInfo.gcMarkRegPtrVal(varDsc->GetArgReg(), varDsc->TypeGet()); + var_types type = retTypeDesc.GetReturnRegType(i); + regNumber reg = retTypeDesc.GetABIReturnReg(i, compiler->info.compCallConv); + assert((type == TYP_BYREF) == ((gcInfo.gcRegByrefSetCur & genRegMask(reg)) != RBM_NONE)); + assert((type == TYP_REF) == ((gcInfo.gcRegGCrefSetCur & genRegMask(reg)) != RBM_NONE)); } - - GetEmitter()->emitThisGCrefRegs = GetEmitter()->emitInitGCrefRegs = gcInfo.gcRegGCrefSetCur; - GetEmitter()->emitThisByrefRegs = GetEmitter()->emitInitByrefRegs = gcInfo.gcRegByrefSetCur; } + } #endif + + if (compiler->getNeedsGSSecurityCookie()) + { + genEmitGSCookieCheck(jmpEpilog); } genReserveEpilog(block); @@ -4711,8 +4698,7 @@ void CodeGen::genReserveProlog(BasicBlock* block) JITDUMP("Reserving prolog IG for block " FMT_BB "\n", block->bbNum); - /* Nothing is live on entry to the prolog */ - + // Nothing is live on entry to the prolog GetEmitter()->emitCreatePlaceholderIG(IGPT_PROLOG, block, VarSetOps::MakeEmpty(compiler), 0, 0, false); } @@ -4723,13 +4709,12 @@ void CodeGen::genReserveProlog(BasicBlock* block) void CodeGen::genReserveEpilog(BasicBlock* block) { + assert(block != nullptr); + JITDUMP("Reserving epilog IG for block " FMT_BB "\n", block->bbNum); - assert(block != nullptr); - // We pass empty GC info, because epilog is always an extend IG and will ignore what we pass. - // Besides, at this point the GC info that we track in CodeGen is often incorrect. - // See comments in genExitCode for more info. - GetEmitter()->emitCreatePlaceholderIG(IGPT_EPILOG, block, VarSetOps::MakeEmpty(compiler), 0, 0, block->IsLast()); + GetEmitter()->emitCreatePlaceholderIG(IGPT_EPILOG, block, VarSetOps::MakeEmpty(compiler), gcInfo.gcRegGCrefSetCur, + gcInfo.gcRegByrefSetCur, block->IsLast()); } /***************************************************************************** @@ -7162,14 +7147,24 @@ void CodeGen::genReturn(GenTree* treeNode) } } + const ReturnTypeDesc& retTypeDesc = compiler->compRetTypeDesc; + + if (compiler->compMethodReturnsRetBufAddr()) + { + gcInfo.gcMarkRegPtrVal(REG_INTRET, TYP_BYREF); + } + else + { + unsigned retRegCount = retTypeDesc.GetReturnRegCount(); + for (unsigned i = 0; i < retRegCount; ++i) + { + gcInfo.gcMarkRegPtrVal(retTypeDesc.GetABIReturnReg(i, compiler->info.compCallConv), + retTypeDesc.GetReturnRegType(i)); + } + } + #ifdef PROFILING_SUPPORTED - // !! Note !! - // TODO-AMD64-Unix: If the profiler hook is implemented on *nix, make sure for 2 register returned structs - // the RAX and RDX needs to be kept alive. Make the necessary changes in lowerxarch.cpp - // in the handling of the GT_RETURN statement. - // Such structs containing GC pointers need to be handled by calling gcInfo.gcMarkRegSetNpt - // for the return registers containing GC refs. - // + // Reason for not materializing Leave callback as a GT_PROF_HOOK node after GT_RETURN: // In flowgraph and other places assert that the last node of a block marked as // BBJ_RETURN is either a GT_RETURN or GT_JMP or a tail call. It would be nice to @@ -7180,46 +7175,7 @@ void CodeGen::genReturn(GenTree* treeNode) // if (treeNode->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET) && compiler->compIsProfilerHookNeeded()) { - // !! NOTE !! - // Since we are invalidating the assumption that we would slip into the epilog - // right after the "return", we need to preserve the return reg's GC state - // across the call until actual method return. - - ReturnTypeDesc retTypeDesc = compiler->compRetTypeDesc; - unsigned retRegCount = retTypeDesc.GetReturnRegCount(); - - if (compiler->compMethodReturnsRetBufAddr()) - { - gcInfo.gcMarkRegPtrVal(REG_INTRET, TYP_BYREF); - } - else - { - for (unsigned i = 0; i < retRegCount; ++i) - { - if (varTypeIsGC(retTypeDesc.GetReturnRegType(i))) - { - gcInfo.gcMarkRegPtrVal(retTypeDesc.GetABIReturnReg(i, compiler->info.compCallConv), - retTypeDesc.GetReturnRegType(i)); - } - } - } - genProfilingLeaveCallback(CORINFO_HELP_PROF_FCN_LEAVE); - - if (compiler->compMethodReturnsRetBufAddr()) - { - gcInfo.gcMarkRegSetNpt(genRegMask(REG_INTRET)); - } - else - { - for (unsigned i = 0; i < retRegCount; ++i) - { - if (varTypeIsGC(retTypeDesc.GetReturnRegType(i))) - { - gcInfo.gcMarkRegSetNpt(genRegMask(retTypeDesc.GetABIReturnReg(i, compiler->info.compCallConv))); - } - } - } } #endif // PROFILING_SUPPORTED @@ -7469,6 +7425,12 @@ void CodeGen::genCallPlaceRegArgs(GenTreeCall* call) /* canSkip */ true); use = use->GetNext(); + + if (call->IsFastTailCall()) + { + // We won't actually consume the register here -- keep it alive into the epilog. + gcInfo.gcMarkRegPtrVal(seg.GetRegister(), putArgRegNode->TypeGet()); + } } assert(use == nullptr); @@ -7493,6 +7455,12 @@ void CodeGen::genCallPlaceRegArgs(GenTreeCall* call) var_types type = argNode->AsPutArgSplit()->GetRegType(regIndex); inst_Mov(genActualType(type), seg.GetRegister(), allocReg, /* canSkip */ true); + if (call->IsFastTailCall()) + { + // We won't actually consume the register here -- keep it alive into the epilog. + gcInfo.gcMarkRegPtrVal(seg.GetRegister(), type); + } + regIndex++; } @@ -7505,6 +7473,12 @@ void CodeGen::genCallPlaceRegArgs(GenTreeCall* call) regNumber argReg = abiInfo.Segment(0).GetRegister(); genConsumeReg(argNode); inst_Mov(genActualType(argNode), argReg, argNode->GetRegNum(), /* canSkip */ true); + + if (call->IsFastTailCall()) + { + // We won't actually consume the register here -- keep it alive into the epilog. + gcInfo.gcMarkRegPtrVal(argReg, argNode->TypeGet()); + } continue; } diff --git a/src/coreclr/jit/codegeninterface.h b/src/coreclr/jit/codegeninterface.h index dccaf724b7f358..800f12c597f1d2 100644 --- a/src/coreclr/jit/codegeninterface.h +++ b/src/coreclr/jit/codegeninterface.h @@ -595,7 +595,7 @@ class CodeGenInterface protected: // Keeps track of how many bytes we've pushed on the processor's stack. - unsigned genStackLevel; + unsigned genStackLevel = 0; public: //-------------------------------------------- diff --git a/src/coreclr/jit/codegenlinear.cpp b/src/coreclr/jit/codegenlinear.cpp index e3dfa8a5695c40..53257afb010b74 100644 --- a/src/coreclr/jit/codegenlinear.cpp +++ b/src/coreclr/jit/codegenlinear.cpp @@ -483,24 +483,34 @@ void CodeGen::genCodeForBBlist() regSet.rsSpillChk(); - /* Make sure we didn't bungle pointer register tracking */ + // Make sure we didn't bungle pointer register tracking regMaskTP ptrRegs = gcInfo.gcRegGCrefSetCur | gcInfo.gcRegByrefSetCur; regMaskTP nonVarPtrRegs = ptrRegs & ~regSet.GetMaskVars(); - // If return is a GC-type, clear it. Note that if a common - // epilog is generated (genReturnBB) it has a void return - // even though we might return a ref. We can't use the compRetType - // as the determiner because something we are tracking as a byref - // might be used as a return value of a int function (which is legal) - GenTree* blockLastNode = block->lastNode(); - if ((blockLastNode != nullptr) && (blockLastNode->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET)) && - (varTypeIsGC(compiler->info.compRetType) || - (blockLastNode->AsOp()->GetReturnValue() != nullptr && - varTypeIsGC(blockLastNode->AsOp()->GetReturnValue()->TypeGet())))) + // If this is a return block then we expect some live GC regs. Clear those. + if (compiler->compMethodReturnsRetBufAddr()) { nonVarPtrRegs &= ~RBM_INTRET; } + else + { + const ReturnTypeDesc& retTypeDesc = compiler->compRetTypeDesc; + const unsigned regCount = retTypeDesc.GetReturnRegCount(); + + for (unsigned i = 0; i < regCount; ++i) + { + regNumber reg = retTypeDesc.GetABIReturnReg(i, compiler->info.compCallConv); + nonVarPtrRegs &= ~genRegMask(reg); + } + } + + // For a tailcall arbitrary argument registers may be live into the + // prolog. Skip validating those. + if (block->HasFlag(BBF_HAS_JMP)) + { + nonVarPtrRegs &= ~fullIntArgRegMask(CorInfoCallConvExtension::Managed); + } if (nonVarPtrRegs) { diff --git a/src/coreclr/jit/codegenloongarch64.cpp b/src/coreclr/jit/codegenloongarch64.cpp index c7fa8df00c4bc0..7f235ee2a1d1d6 100644 --- a/src/coreclr/jit/codegenloongarch64.cpp +++ b/src/coreclr/jit/codegenloongarch64.cpp @@ -4616,8 +4616,6 @@ void CodeGen::genEmitGSCookieCheck(bool pushReg) { noway_assert(compiler->gsGlobalSecurityCookieAddr || compiler->gsGlobalSecurityCookieVal); - assert(GetEmitter()->emitGCDisabled()); - // We need two temporary registers, to load the GS cookie values and compare them. We can't use // any argument registers if 'pushReg' is true (meaning we have a JMP call). They should be // callee-trash registers, which should not contain anything interesting at this point. diff --git a/src/coreclr/jit/codegenriscv64.cpp b/src/coreclr/jit/codegenriscv64.cpp index 6c93a636e0062c..9ce76ae3c0dab9 100644 --- a/src/coreclr/jit/codegenriscv64.cpp +++ b/src/coreclr/jit/codegenriscv64.cpp @@ -4666,8 +4666,6 @@ void CodeGen::genEmitGSCookieCheck(bool pushReg) { noway_assert(compiler->gsGlobalSecurityCookieAddr || compiler->gsGlobalSecurityCookieVal); - assert(GetEmitter()->emitGCDisabled()); - // We need two temporary registers, to load the GS cookie values and compare them. We can't use // any argument registers if 'pushReg' is true (meaning we have a JMP call). They should be // callee-trash registers, which should not contain anything interesting at this point. diff --git a/src/coreclr/jit/codegenxarch.cpp b/src/coreclr/jit/codegenxarch.cpp index bd80187eea6a44..dd843cbfa14a80 100644 --- a/src/coreclr/jit/codegenxarch.cpp +++ b/src/coreclr/jit/codegenxarch.cpp @@ -96,37 +96,6 @@ void CodeGen::genEmitGSCookieCheck(bool pushReg) { noway_assert(compiler->gsGlobalSecurityCookieAddr || compiler->gsGlobalSecurityCookieVal); -#ifdef JIT32_GCENCODER - if (!pushReg) - { - // Make sure that EAX is reported as live GC-ref so that any GC that kicks in while - // executing GS cookie check will not collect the object pointed to by EAX. - if (compiler->compMethodReturnsRetBufAddr()) - { - // This is for returning in an implicit RetBuf. - // If the address of the buffer is returned in REG_INTRET, mark the content of INTRET as ByRef. - - // In case the return is in an implicit RetBuf, the native return type should be a struct - assert(varTypeIsStruct(compiler->info.compRetNativeType)); - - gcInfo.gcMarkRegPtrVal(REG_INTRET, TYP_BYREF); - } - else - { - ReturnTypeDesc retTypeDesc = compiler->compRetTypeDesc; - const unsigned regCount = retTypeDesc.GetReturnRegCount(); - - for (unsigned i = 0; i < regCount; ++i) - { - gcInfo.gcMarkRegPtrVal(retTypeDesc.GetABIReturnReg(i, compiler->info.compCallConv), - retTypeDesc.GetReturnRegType(i)); - } - } - } -#else - assert(GetEmitter()->emitGCDisabled()); -#endif - regNumber regGSCheck; regMaskTP regMaskGSCheck = RBM_NONE; diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index 52975e90bf8854..5aab07895a7b85 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -4779,11 +4779,6 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl // DoPhase(this, PHASE_MORPH_IMPBYREF, &Compiler::fgRetypeImplicitByRefArgs); - // Drop back to just checking profile likelihoods. - // - activePhaseChecks &= ~PhaseChecks::CHECK_PROFILE; - activePhaseChecks |= PhaseChecks::CHECK_LIKELIHOODS; - #ifdef DEBUG // Now that locals have address-taken and implicit byref marked, we can safely apply stress. lvaStressLclFld(); @@ -4819,12 +4814,29 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl // DoPhase(this, PHASE_GS_COOKIE, &Compiler::gsPhase); + // Drop back to just checking profile likelihoods. + // + activePhaseChecks &= ~PhaseChecks::CHECK_PROFILE; + activePhaseChecks |= PhaseChecks::CHECK_LIKELIHOODS; + if (opts.OptimizationEnabled()) { // Compute the block weights // DoPhase(this, PHASE_COMPUTE_BLOCK_WEIGHTS, &Compiler::fgComputeBlockWeights); + // Try again to remove empty try finally/fault clauses + // + DoPhase(this, PHASE_EMPTY_FINALLY_2, &Compiler::fgRemoveEmptyFinally); + + // Remove empty try regions (try/finally) + // + DoPhase(this, PHASE_EMPTY_TRY_2, &Compiler::fgRemoveEmptyTry); + + // Remove empty try regions (try/catch/fault) + // + DoPhase(this, PHASE_EMPTY_TRY_CATCH_FAULT_2, &Compiler::fgRemoveEmptyTryCatchOrTryFault); + // Invert loops // DoPhase(this, PHASE_INVERT_LOOPS, &Compiler::optInvertLoops); @@ -4860,18 +4872,6 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl // DoPhase(this, PHASE_UNROLL_LOOPS, &Compiler::optUnrollLoops); - // Try again to remove empty try finally/fault clauses - // - DoPhase(this, PHASE_EMPTY_FINALLY_2, &Compiler::fgRemoveEmptyFinally); - - // Remove empty try regions (try/finally) - // - DoPhase(this, PHASE_EMPTY_TRY_2, &Compiler::fgRemoveEmptyTry); - - // Remove empty try regions (try/catch/fault) - // - DoPhase(this, PHASE_EMPTY_TRY_CATCH_FAULT_2, &Compiler::fgRemoveEmptyTryCatchOrTryFault); - // Compute dominators and exceptional entry blocks // DoPhase(this, PHASE_COMPUTE_DOMINATORS, &Compiler::fgComputeDominators); diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 626e6edfa38c9a..0e3986969c161e 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -3377,6 +3377,26 @@ class Compiler CorInfoType simdBaseJitType, unsigned simdSize); + GenTree* gtNewSimdIsEvenIntegerNode(var_types type, + GenTree* op1, + CorInfoType simdBaseJitType, + unsigned simdSize); + + GenTree* gtNewSimdIsFiniteNode(var_types type, + GenTree* op1, + CorInfoType simdBaseJitType, + unsigned simdSize); + + GenTree* gtNewSimdIsInfinityNode(var_types type, + GenTree* op1, + CorInfoType simdBaseJitType, + unsigned simdSize); + + GenTree* gtNewSimdIsIntegerNode(var_types type, + GenTree* op1, + CorInfoType simdBaseJitType, + unsigned simdSize); + GenTree* gtNewSimdIsNaNNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, @@ -3387,6 +3407,21 @@ class Compiler CorInfoType simdBaseJitType, unsigned simdSize); + GenTree* gtNewSimdIsNegativeInfinityNode(var_types type, + GenTree* op1, + CorInfoType simdBaseJitType, + unsigned simdSize); + + GenTree* gtNewSimdIsNormalNode(var_types type, + GenTree* op1, + CorInfoType simdBaseJitType, + unsigned simdSize); + + GenTree* gtNewSimdIsOddIntegerNode(var_types type, + GenTree* op1, + CorInfoType simdBaseJitType, + unsigned simdSize); + GenTree* gtNewSimdIsPositiveNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, @@ -3397,6 +3432,11 @@ class Compiler CorInfoType simdBaseJitType, unsigned simdSize); + GenTree* gtNewSimdIsSubnormalNode(var_types type, + GenTree* op1, + CorInfoType simdBaseJitType, + unsigned simdSize); + GenTree* gtNewSimdIsZeroNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, @@ -6276,7 +6316,6 @@ class Compiler Compiler* compiler; PriorityQueue cutPoints; - unsigned* ordinals; BasicBlock** blockOrder; BasicBlock** tempOrder; unsigned numCandidateBlocks; @@ -8091,6 +8130,7 @@ class Compiler GenTree* optVNBasedFoldExpr(BasicBlock* block, GenTree* parent, GenTree* tree); GenTree* optVNBasedFoldExpr_Call(BasicBlock* block, GenTree* parent, GenTreeCall* call); GenTree* optVNBasedFoldExpr_Call_Memmove(GenTreeCall* call); + GenTree* optVNBasedFoldExpr_Call_Memset(GenTreeCall* call); AssertionIndex GetAssertionCount() { diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index df5bbae20bd95b..01ab2f27d2e32b 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -3552,11 +3552,14 @@ void emitter::emitDispInsName( const BYTE* insAdr = addr - writeableOffset; unsigned int opcode = code & 0x7f; - assert((opcode & 0x3) == 0x3); + assert((opcode & 0x3) == 0x3); // only 32-bit encodings supported emitDispInsAddr(insAdr); emitDispInsOffs(insOffset, doffs); + if (emitComp->opts.disCodeBytes && !emitComp->opts.disDiffable) + printf(" %08X ", code); + printf(" "); switch (opcode) @@ -4547,33 +4550,6 @@ void emitter::emitDispInsName( NO_WAY("illegal ins within emitDisInsName!"); } -/***************************************************************************** - * - * Display (optionally) the instruction encoding in hex - */ - -void emitter::emitDispInsHex(instrDesc* id, BYTE* code, size_t sz) -{ - if (!emitComp->opts.disCodeBytes) - { - return; - } - - // We do not display the instruction hex if we want diff-able disassembly - if (!emitComp->opts.disDiffable) - { - if (sz == 4) - { - printf(" %08X ", (*((code_t*)code))); - } - else - { - assert(sz == 0); - printf(" "); - } - } -} - void emitter::emitDispInsInstrNum(const instrDesc* id) const { #ifdef DEBUG @@ -5319,29 +5295,4 @@ const char* emitter::emitRegName(regNumber reg, emitAttr size, bool varName) con } #endif -//------------------------------------------------------------------------ -// IsMovInstruction: Determines whether a give instruction is a move instruction -// -// Arguments: -// ins -- The instruction being checked -// -bool emitter::IsMovInstruction(instruction ins) -{ - switch (ins) - { - case INS_mov: - case INS_fsgnj_s: - case INS_fsgnj_d: - { - return true; - } - - default: - { - return false; - } - } - return false; -} - #endif // defined(TARGET_RISCV64) diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index 6c73f3fe577fc4..446166fbe0e08d 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -85,10 +85,9 @@ void emitOutputInstrJumpDistanceHelper(const insGroup* ig, // Method to do check if mov is redundant with respect to the last instruction. // If yes, the caller of this method can choose to omit current mov instruction. -static bool IsMovInstruction(instruction ins); -bool IsRedundantMov(instruction ins, emitAttr size, regNumber dst, regNumber src, bool canSkip); -bool IsRedundantLdStr( - instruction ins, regNumber reg1, regNumber reg2, ssize_t imm, emitAttr size, insFormat fmt); // New functions end. +bool IsRedundantMov(instruction ins, emitAttr size, regNumber dst, regNumber src, bool canSkip); +bool IsRedundantLdStr( + instruction ins, regNumber reg1, regNumber reg2, ssize_t imm, emitAttr size, insFormat fmt); // New functions end. static code_t insEncodeRTypeInstr( unsigned opcode, unsigned rd, unsigned funct3, unsigned rs1, unsigned rs2, unsigned funct7); diff --git a/src/coreclr/jit/fgbasic.cpp b/src/coreclr/jit/fgbasic.cpp index 652a2d434380b1..a34e2622157ba3 100644 --- a/src/coreclr/jit/fgbasic.cpp +++ b/src/coreclr/jit/fgbasic.cpp @@ -156,14 +156,29 @@ void Compiler::fgConvertBBToThrowBB(BasicBlock* block) } // Scrub this block from the pred lists of any successors - fgRemoveBlockAsPred(block); + bool profileInconsistent = false; + + for (BasicBlock* const succBlock : block->Succs(this)) + { + FlowEdge* const succEdge = fgRemoveAllRefPreds(succBlock, block); + + if (block->hasProfileWeight() && succBlock->hasProfileWeight()) + { + succBlock->decreaseBBProfileWeight(succEdge->getLikelyWeight()); + profileInconsistent |= (succBlock->NumSucc() > 0); + } + } + + if (profileInconsistent) + { + JITDUMP("Flow removal of " FMT_BB " needs to be propagated. Data %s inconsistent.\n", block->bbNum, + fgPgoConsistent ? "is now" : "was already"); + fgPgoConsistent = false; + } // Update jump kind after the scrub. block->SetKindAndTargetEdge(BBJ_THROW); block->RemoveFlags(BBF_RETLESS_CALL); // no longer a BBJ_CALLFINALLY - - // Any block with a throw is rare - block->bbSetRunRarely(); } /***************************************************************************** diff --git a/src/coreclr/jit/fgehopt.cpp b/src/coreclr/jit/fgehopt.cpp index 18fa193db493cc..2c8504ea0a8095 100644 --- a/src/coreclr/jit/fgehopt.cpp +++ b/src/coreclr/jit/fgehopt.cpp @@ -2433,7 +2433,7 @@ PhaseStatus Compiler::fgTailMergeThrows() if (canonicalBlock->hasProfileWeight()) { - canonicalBlock->setBBProfileWeight(canonicalBlock->bbWeight + removedWeight); + canonicalBlock->increaseBBProfileWeight(removedWeight); modifiedProfile = true; // Don't bother updating flow into nonCanonicalBlock, since it is now unreachable @@ -2458,12 +2458,6 @@ PhaseStatus Compiler::fgTailMergeThrows() assert(numCandidates < optNoReturnCallCount); optNoReturnCallCount -= numCandidates; - // If we altered flow, reset fgModified. Given where we sit in the - // phase list, flow-dependent side data hasn't been built yet, so - // nothing needs invalidation. - // - assert(fgModified); - fgModified = false; return PhaseStatus::MODIFIED_EVERYTHING; } diff --git a/src/coreclr/jit/fgopt.cpp b/src/coreclr/jit/fgopt.cpp index 10d381c0caeaa8..d53df9af3597e3 100644 --- a/src/coreclr/jit/fgopt.cpp +++ b/src/coreclr/jit/fgopt.cpp @@ -1355,7 +1355,7 @@ bool Compiler::fgOptimizeBranchToEmptyUnconditional(BasicBlock* block, BasicBloc // if (bDest->hasProfileWeight()) { - bDest->setBBProfileWeight(max(0.0, bDest->bbWeight - removedWeight)); + bDest->decreaseBBProfileWeight(removedWeight); } return true; @@ -1620,7 +1620,7 @@ bool Compiler::fgOptimizeSwitchBranches(BasicBlock* block) if (bDest->hasProfileWeight()) { weight_t const branchThroughWeight = oldEdge->getLikelyWeight(); - bDest->setBBProfileWeight(max(0.0, bDest->bbWeight - branchThroughWeight)); + bDest->decreaseBBProfileWeight(branchThroughWeight); } // Update the switch jump table @@ -4828,7 +4828,7 @@ void Compiler::fgMoveColdBlocks() } }; - BasicBlock* const lastMainBB = fgLastBBInMainFunction(); + BasicBlock* lastMainBB = fgLastBBInMainFunction(); if (lastMainBB->IsFirst()) { return; @@ -4855,15 +4855,41 @@ void Compiler::fgMoveColdBlocks() // We have moved all cold main blocks before lastMainBB to after lastMainBB. // If lastMainBB itself is cold, move it to the end of the method to restore its relative ordering. + // But first, we can't move just the tail of a call-finally pair, + // so point lastMainBB to the pair's head, if necessary. // - if (lastMainBB->isBBWeightCold(this) && !lastMainBB->isBBCallFinallyPairTail()) + if (lastMainBB->isBBCallFinallyPairTail()) { + lastMainBB = lastMainBB->Prev(); + } + + BasicBlock* lastHotBB = nullptr; + if (lastMainBB->isBBWeightCold(this)) + { + // lastMainBB is cold, so the block behind it (if there is one) is the last hot block + // + lastHotBB = lastMainBB->Prev(); + + // Move lastMainBB + // BasicBlock* const newLastMainBB = fgLastBBInMainFunction(); if (lastMainBB != newLastMainBB) { moveBlock(lastMainBB, newLastMainBB); } } + else + { + // lastMainBB isn't cold, so it (or its call-finally pair tail) the last hot block + // + lastHotBB = lastMainBB->isBBCallFinallyPair() ? lastMainBB->Next() : lastMainBB; + } + + // Save the beginning of the cold section for later. + // If lastHotBB is null, there isn't a hot section, + // so there's no point in differentiating between sections for layout purposes. + // + fgFirstColdBlock = (lastHotBB == nullptr) ? nullptr : lastHotBB->Next(); } //----------------------------------------------------------------------------- @@ -4910,7 +4936,6 @@ void Compiler::fgMoveColdBlocks() Compiler::ThreeOptLayout::ThreeOptLayout(Compiler* comp) : compiler(comp) , cutPoints(comp->getAllocator(CMK_FlowEdge), &ThreeOptLayout::EdgeCmp) - , ordinals(new(comp, CMK_Generic) unsigned[comp->fgBBcount]{}) , blockOrder(nullptr) , tempOrder(nullptr) , numCandidateBlocks(0) @@ -5107,10 +5132,6 @@ void Compiler::ThreeOptLayout::ConsiderEdge(FlowEdge* edge) BasicBlock* const srcBlk = edge->getSourceBlock(); BasicBlock* const dstBlk = edge->getDestinationBlock(); - // Any edges under consideration should be between reachable blocks - assert(compiler->m_dfsTree->Contains(srcBlk)); - assert(compiler->m_dfsTree->Contains(dstBlk)); - // Ignore cross-region branches if ((srcBlk->bbTryIndex != currEHRegion) || (dstBlk->bbTryIndex != currEHRegion)) { @@ -5133,13 +5154,13 @@ void Compiler::ThreeOptLayout::ConsiderEdge(FlowEdge* edge) return; } - const unsigned srcPos = ordinals[srcBlk->bbPostorderNum]; - const unsigned dstPos = ordinals[dstBlk->bbPostorderNum]; + const unsigned srcPos = srcBlk->bbPostorderNum; + const unsigned dstPos = dstBlk->bbPostorderNum; + assert(srcPos < compiler->m_dfsTree->GetPostOrderCount()); + assert(dstPos < compiler->m_dfsTree->GetPostOrderCount()); - // Don't consider edges from outside the hot range. - // If 'srcBlk' has an ordinal of zero and it isn't the first block, - // it's not tracked by 'ordinals', so it's not in the hot section. - if ((srcPos == 0) && !srcBlk->IsFirst()) + // Don't consider edges to or from outside the hot range (i.e. ordinal doesn't match 'blockOrder' position). + if ((srcBlk != blockOrder[srcPos]) || (dstBlk != blockOrder[dstPos])) { return; } @@ -5212,19 +5233,19 @@ void Compiler::ThreeOptLayout::AddNonFallthroughPreds(unsigned blockPos) // void Compiler::ThreeOptLayout::Run() { - // Walk backwards through the main method body, looking for the last hot block. // Since we moved all cold blocks to the end of the method already, - // we should have a span of hot blocks to consider reordering at the beginning of the method. - // While doing this, try to get as tight an upper bound for the number of hot blocks as possible. - // For methods without funclet regions, 'numBlocksUpperBound' is exact. - // Otherwise, it's off by the number of handler blocks. - BasicBlock* finalBlock; - unsigned numBlocksUpperBound = compiler->fgBBcount; - for (finalBlock = compiler->fgLastBBInMainFunction(); - !finalBlock->IsFirst() && finalBlock->isBBWeightCold(compiler); finalBlock = finalBlock->Prev()) - { - numBlocksUpperBound--; - } + // we should have a span of hot blocks to consider reordering at the beginning of the method + // (unless none of the blocks are cold relative to the rest of the method, + // in which case we will reorder the whole main method body). + BasicBlock* const finalBlock = (compiler->fgFirstColdBlock != nullptr) ? compiler->fgFirstColdBlock->Prev() + : compiler->fgLastBBInMainFunction(); + + // Reset cold section pointer, in case we decide to do hot/cold splitting later + compiler->fgFirstColdBlock = nullptr; + + // We better have an end block for the hot section, and it better not be the start of a call-finally pair. + assert(finalBlock != nullptr); + assert(!finalBlock->isBBCallFinallyPair()); // For methods with fewer than three candidate blocks, we cannot partition anything if (finalBlock->IsFirst() || finalBlock->Prev()->IsFirst()) @@ -5233,41 +5254,26 @@ void Compiler::ThreeOptLayout::Run() return; } - // If only the first block of a call-finally pair is hot, include the whole pair in the hot section anyway. - // This ensures the call-finally pair won't be split up when swapping partitions. - if (finalBlock->isBBCallFinallyPair()) - { - finalBlock = finalBlock->Next(); - numBlocksUpperBound++; - } - + // Get an upper bound on the number of hot blocks without walking the whole block list. + // We will only consider blocks reachable via normal flow. + const unsigned numBlocksUpperBound = compiler->m_dfsTree->GetPostOrderCount(); assert(numBlocksUpperBound != 0); - blockOrder = new (compiler, CMK_BasicBlock) BasicBlock*[numBlocksUpperBound]; - tempOrder = new (compiler, CMK_BasicBlock) BasicBlock*[numBlocksUpperBound]; - - // Initialize the current block order. - // Note that we default-initialized 'ordinals' with zeros. - // Block reordering shouldn't change the method's entry point, - // so if a block has an ordinal of zero and it's not 'fgFirstBB', - // the block wasn't visited below, so it's not in the range of candidate blocks. - unsigned nextPostorderNum = compiler->m_dfsTree->GetPostOrderCount(); + blockOrder = new (compiler, CMK_BasicBlock) BasicBlock*[numBlocksUpperBound * 2]; + tempOrder = (blockOrder + numBlocksUpperBound); + + // Initialize the current block order for (BasicBlock* const block : compiler->Blocks(compiler->fgFirstBB, finalBlock)) { - assert(numCandidateBlocks < numBlocksUpperBound); - blockOrder[numCandidateBlocks] = tempOrder[numCandidateBlocks] = block; - - // Unreachable blocks should have been pushed out of the candidate set of blocks. - // However, the entries of unreachable EH regions are left in-place to facilitate reestablishing contiguity, - // so it is possible for us to encounter unreachable blocks. - // When we do, assign them postorder numbers that can be used as keys into 'ordinals'. if (!compiler->m_dfsTree->Contains(block)) { - assert(nextPostorderNum < compiler->fgBBcount); - block->bbPostorderNum = nextPostorderNum++; + continue; } - assert(ordinals[block->bbPostorderNum] == 0); - ordinals[block->bbPostorderNum] = numCandidateBlocks++; + assert(numCandidateBlocks < numBlocksUpperBound); + blockOrder[numCandidateBlocks] = tempOrder[numCandidateBlocks] = block; + + // Repurpose 'bbPostorderNum' for the block's ordinal + block->bbPostorderNum = numCandidateBlocks++; // While walking the span of blocks to reorder, // remember where each try region ends within this span. @@ -5291,14 +5297,8 @@ void Compiler::ThreeOptLayout::Run() continue; } - // Ignore try regions unreachable via normal flow - if (!compiler->m_dfsTree->Contains(tryBeg)) - { - continue; - } - - // Only reorder try regions within the candidate span of blocks. - if ((ordinals[tryBeg->bbPostorderNum] != 0) || tryBeg->IsFirst()) + // Only reorder try regions within the candidate span of blocks + if ((tryBeg->bbPostorderNum < numCandidateBlocks) && (blockOrder[tryBeg->bbPostorderNum] == tryBeg)) { JITDUMP("Running 3-opt for try region #%d\n", (currEHRegion - 1)); modified |= RunThreeOptPass(tryBeg, HBtab->ebdTryLast); @@ -5372,8 +5372,8 @@ bool Compiler::ThreeOptLayout::RunGreedyThreeOptPass(unsigned startPos, unsigned BasicBlock* const srcBlk = candidateEdge->getSourceBlock(); BasicBlock* const dstBlk = candidateEdge->getDestinationBlock(); - const unsigned srcPos = ordinals[srcBlk->bbPostorderNum]; - const unsigned dstPos = ordinals[dstBlk->bbPostorderNum]; + const unsigned srcPos = srcBlk->bbPostorderNum; + const unsigned dstPos = dstBlk->bbPostorderNum; // This edge better be between blocks in the current region assert((srcPos >= startPos) && (srcPos <= endPos)); @@ -5393,7 +5393,7 @@ bool Compiler::ThreeOptLayout::RunGreedyThreeOptPass(unsigned startPos, unsigned continue; } - // Before getting any edges, make sure 'ordinals' is accurate + // Before getting any edges, make sure the ordinals are accurate assert(blockOrder[srcPos] == srcBlk); assert(blockOrder[dstPos] == dstBlk); @@ -5505,11 +5505,11 @@ bool Compiler::ThreeOptLayout::RunGreedyThreeOptPass(unsigned startPos, unsigned // Update the ordinals for the blocks we moved for (unsigned i = s2Start; i <= endPos; i++) { - ordinals[blockOrder[i]->bbPostorderNum] = i; + blockOrder[i]->bbPostorderNum = i; } // Ensure this move created fallthrough from 'srcBlk' to 'dstBlk' - assert((ordinals[srcBlk->bbPostorderNum] + 1) == ordinals[dstBlk->bbPostorderNum]); + assert((srcBlk->bbPostorderNum + 1) == dstBlk->bbPostorderNum); // At every cut point is an opportunity to consider more candidate edges. // To the left of each cut point, consider successor edges that don't fall through. @@ -5546,10 +5546,9 @@ bool Compiler::ThreeOptLayout::RunThreeOptPass(BasicBlock* startBlock, BasicBloc assert(startBlock != nullptr); assert(endBlock != nullptr); - const unsigned startPos = ordinals[startBlock->bbPostorderNum]; - const unsigned endPos = ordinals[endBlock->bbPostorderNum]; + const unsigned startPos = startBlock->bbPostorderNum; + const unsigned endPos = endBlock->bbPostorderNum; const unsigned numBlocks = (endPos - startPos + 1); - assert((startPos != 0) || startBlock->IsFirst()); assert(startPos <= endPos); if (numBlocks < 3) @@ -6108,6 +6107,15 @@ bool Compiler::fgUpdateFlowGraph(bool doTailDuplication /* = false */, bool isPh } } while (change); + // OSR entry blocks will frequently have a profile imbalance as original method execution was hijacked at them. + // Mark the profile as inconsistent if we might have propagated the OSR entry weight. + if (modified && opts.IsOSR()) + { + JITDUMP("fgUpdateFlowGraph: Inconsistent OSR entry weight may have been propagated. Data %s consistent.\n", + fgPgoConsistent ? "is now" : "was already"); + fgPgoConsistent = false; + } + #ifdef DEBUG if (!isPhase) { @@ -6624,7 +6632,7 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early) // crossJumpTarget, so the profile update can be done locally. if (crossJumpTarget->hasProfileWeight()) { - crossJumpTarget->setBBProfileWeight(crossJumpTarget->bbWeight + predBlock->bbWeight); + crossJumpTarget->increaseBBProfileWeight(predBlock->bbWeight); } } @@ -6771,12 +6779,6 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early) madeChanges |= fgHeadMerge(block, early); } - // If we altered flow, reset fgModified. Given where we sit in the - // phase list, flow-dependent side data hasn't been built yet, so - // nothing needs invalidation. - // - fgModified = false; - return madeChanges ? PhaseStatus::MODIFIED_EVERYTHING : PhaseStatus::MODIFIED_NOTHING; } diff --git a/src/coreclr/jit/flowgraph.cpp b/src/coreclr/jit/flowgraph.cpp index 6a41de3c7ea34a..282335d1e23947 100644 --- a/src/coreclr/jit/flowgraph.cpp +++ b/src/coreclr/jit/flowgraph.cpp @@ -2989,6 +2989,18 @@ PhaseStatus Compiler::fgCreateFunclets() assert(UsesFunclets()); assert(!fgFuncletsCreated); + // Allocate the PSPSym, if needed. PSPSym is not used by the NativeAOT ABI + if (!IsTargetAbi(CORINFO_NATIVEAOT_ABI)) + { + if (ehNeedsPSPSym()) + { + lvaPSPSym = lvaGrabTempWithImplicitUse(false DEBUGARG("PSPSym")); + LclVarDsc* lclPSPSym = lvaGetDesc(lvaPSPSym); + lclPSPSym->lvType = TYP_I_IMPL; + lvaSetVarDoNotEnregister(lvaPSPSym DEBUGARG(DoNotEnregisterReason::VMNeedsStackAddr)); + } + } + fgCreateFuncletPrologBlocks(); unsigned XTnum; diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 9154da487bd1fa..ba5407c7d02886 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -23560,6 +23560,166 @@ GenTree* Compiler::gtNewSimdGetUpperNode(var_types type, GenTree* op1, CorInfoTy return gtNewSimdHWIntrinsicNode(type, op1, intrinsicId, simdBaseJitType, simdSize); } +//---------------------------------------------------------------------------------------------- +// Compiler::gtNewSimdIsEvenIntegerNode: Creates a new simd IsEvenInteger node +// +// Arguments: +// type - The return type of SIMD node being created +// op1 - The vector to check for even integers +// simdBaseJitType - The base JIT type of SIMD type of the intrinsic +// simdSize - The size of the SIMD type of the intrinsic +// +// Returns: +// The created IsEvenInteger node +// +GenTree* Compiler::gtNewSimdIsEvenIntegerNode(var_types type, + GenTree* op1, + CorInfoType simdBaseJitType, + unsigned simdSize) +{ + assert(IsBaselineSimdIsaSupportedDebugOnly()); + + assert(varTypeIsSIMD(type)); + assert(getSIMDTypeForSize(simdSize) == type); + + assert(op1 != nullptr); + assert(op1->TypeIs(type)); + + var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); + assert(varTypeIsIntegral(simdBaseType)); + + op1 = gtNewSimdBinOpNode(GT_AND, type, op1, gtNewOneConNode(type, simdBaseType), simdBaseJitType, simdSize); + return gtNewSimdIsZeroNode(type, op1, simdBaseJitType, simdSize); +} + +//---------------------------------------------------------------------------------------------- +// Compiler::gtNewSimdIsFiniteNode: Creates a new simd IsFinite node +// +// Arguments: +// type - The return type of SIMD node being created +// op1 - The vector to check for finite values +// simdBaseJitType - The base JIT type of SIMD type of the intrinsic +// simdSize - The size of the SIMD type of the intrinsic +// +// Returns: +// The created IsFinite node +// +GenTree* Compiler::gtNewSimdIsFiniteNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize) +{ + assert(IsBaselineSimdIsaSupportedDebugOnly()); + + assert(varTypeIsSIMD(type)); + assert(getSIMDTypeForSize(simdSize) == type); + + assert(op1 != nullptr); + assert(op1->TypeIs(type)); + + var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); + assert(varTypeIsArithmetic(simdBaseType)); + + if (varTypeIsFloating(simdBaseType)) + { + GenTree* cnsNode; + + if (simdBaseType == TYP_FLOAT) + { + simdBaseType = TYP_INT; + simdBaseJitType = CORINFO_TYPE_UINT; + cnsNode = gtNewIconNode(0x7F800000); + } + else + { + assert(simdBaseType == TYP_DOUBLE); + + simdBaseType = TYP_LONG; + simdBaseJitType = CORINFO_TYPE_ULONG; + cnsNode = gtNewLconNode(0x7FF0000000000000); + } + cnsNode = gtNewSimdCreateBroadcastNode(type, cnsNode, simdBaseJitType, simdSize); + + op1 = gtNewSimdBinOpNode(GT_AND_NOT, type, cnsNode, op1, simdBaseJitType, simdSize); + return gtNewSimdCmpOpNode(GT_NE, type, op1, gtNewZeroConNode(type), simdBaseJitType, simdSize); + } + + assert(varTypeIsIntegral(simdBaseType)); + return gtNewAllBitsSetConNode(type); +} + +//---------------------------------------------------------------------------------------------- +// Compiler::gtNewSimdIsInfinityNode: Creates a new simd IsInfinity node +// +// Arguments: +// type - The return type of SIMD node being created +// op1 - The vector to check for infinities +// simdBaseJitType - The base JIT type of SIMD type of the intrinsic +// simdSize - The size of the SIMD type of the intrinsic +// +// Returns: +// The created IsInfinity node +// +GenTree* Compiler::gtNewSimdIsInfinityNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize) +{ + assert(IsBaselineSimdIsaSupportedDebugOnly()); + + assert(varTypeIsSIMD(type)); + assert(getSIMDTypeForSize(simdSize) == type); + + assert(op1 != nullptr); + assert(op1->TypeIs(type)); + + var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); + assert(varTypeIsArithmetic(simdBaseType)); + + if (varTypeIsFloating(simdBaseType)) + { + op1 = gtNewSimdAbsNode(type, op1, simdBaseJitType, simdSize); + return gtNewSimdIsPositiveInfinityNode(type, op1, simdBaseJitType, simdSize); + } + return gtNewZeroConNode(type); +} + +//---------------------------------------------------------------------------------------------- +// Compiler::gtNewSimdIsIntegerNode: Creates a new simd IsInteger node +// +// Arguments: +// type - The return type of SIMD node being created +// op1 - The vector to check for integers +// simdBaseJitType - The base JIT type of SIMD type of the intrinsic +// simdSize - The size of the SIMD type of the intrinsic +// +// Returns: +// The created IsInteger node +// +GenTree* Compiler::gtNewSimdIsIntegerNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize) +{ + assert(IsBaselineSimdIsaSupportedDebugOnly()); + + assert(varTypeIsSIMD(type)); + assert(getSIMDTypeForSize(simdSize) == type); + + assert(op1 != nullptr); + assert(op1->TypeIs(type)); + + var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); + assert(varTypeIsArithmetic(simdBaseType)); + + if (varTypeIsFloating(simdBaseType)) + { + GenTree* op1Dup1 = fgMakeMultiUse(&op1); + GenTree* op1Dup2 = gtCloneExpr(op1Dup1); + + op1 = gtNewSimdIsFiniteNode(type, op1, simdBaseJitType, simdSize); + + op1Dup1 = gtNewSimdTruncNode(type, op1Dup1, simdBaseJitType, simdSize); + GenTree* op2 = gtNewSimdCmpOpNode(GT_EQ, type, op1Dup1, op1Dup2, simdBaseJitType, simdSize); + + return gtNewSimdBinOpNode(GT_AND, type, op1, op2, simdBaseJitType, simdSize); + } + + assert(varTypeIsIntegral(simdBaseType)); + return gtNewAllBitsSetConNode(type); +} + //---------------------------------------------------------------------------------------------- // Compiler::gtNewSimdIsNaNNode: Creates a new simd IsNaN node // @@ -23598,7 +23758,7 @@ GenTree* Compiler::gtNewSimdIsNaNNode(var_types type, GenTree* op1, CorInfoType // // Arguments: // type - The return type of SIMD node being created -// op1 - The vector to check for Negatives +// op1 - The vector to check for negatives // simdBaseJitType - The base JIT type of SIMD type of the intrinsic // simdSize - The size of the SIMD type of the intrinsic // @@ -23634,12 +23794,159 @@ GenTree* Compiler::gtNewSimdIsNegativeNode(var_types type, GenTree* op1, CorInfo return gtNewSimdCmpOpNode(GT_LT, type, op1, gtNewZeroConNode(type), simdBaseJitType, simdSize); } +//---------------------------------------------------------------------------------------------- +// Compiler::gtNewSimdIsNegativeInfinityNode: Creates a new simd IsNegativeInfinity node +// +// Arguments: +// type - The return type of SIMD node being created +// op1 - The vector to check for negative infinities +// simdBaseJitType - The base JIT type of SIMD type of the intrinsic +// simdSize - The size of the SIMD type of the intrinsic +// +// Returns: +// The created IsNegativeInfinity node +// +GenTree* Compiler::gtNewSimdIsNegativeInfinityNode(var_types type, + GenTree* op1, + CorInfoType simdBaseJitType, + unsigned simdSize) +{ + assert(IsBaselineSimdIsaSupportedDebugOnly()); + + assert(varTypeIsSIMD(type)); + assert(getSIMDTypeForSize(simdSize) == type); + + assert(op1 != nullptr); + assert(op1->TypeIs(type)); + + var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); + assert(varTypeIsArithmetic(simdBaseType)); + + if (varTypeIsFloating(simdBaseType)) + { + GenTree* cnsNode; + + if (simdBaseType == TYP_FLOAT) + { + simdBaseType = TYP_INT; + simdBaseJitType = CORINFO_TYPE_UINT; + cnsNode = gtNewIconNode(0xFF800000); + } + else + { + assert(simdBaseType == TYP_DOUBLE); + + simdBaseType = TYP_LONG; + simdBaseJitType = CORINFO_TYPE_ULONG; + cnsNode = gtNewLconNode(0xFFF0000000000000); + } + cnsNode = gtNewSimdCreateBroadcastNode(type, cnsNode, simdBaseJitType, simdSize); + + return gtNewSimdCmpOpNode(GT_EQ, type, op1, cnsNode, simdBaseJitType, simdSize); + } + return gtNewZeroConNode(type); +} + +//---------------------------------------------------------------------------------------------- +// Compiler::gtNewSimdIsNormalNode: Creates a new simd IsNormal node +// +// Arguments: +// type - The return type of SIMD node being created +// op1 - The vector to check for normal values +// simdBaseJitType - The base JIT type of SIMD type of the intrinsic +// simdSize - The size of the SIMD type of the intrinsic +// +// Returns: +// The created IsNormal node +// +GenTree* Compiler::gtNewSimdIsNormalNode(var_types type, GenTree* op1, CorInfoType simdBaseJitType, unsigned simdSize) +{ + assert(IsBaselineSimdIsaSupportedDebugOnly()); + + assert(varTypeIsSIMD(type)); + assert(getSIMDTypeForSize(simdSize) == type); + + assert(op1 != nullptr); + assert(op1->TypeIs(type)); + + var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); + assert(varTypeIsArithmetic(simdBaseType)); + + if (varTypeIsFloating(simdBaseType)) + { + op1 = gtNewSimdAbsNode(type, op1, simdBaseJitType, simdSize); + + GenTree* cnsNode1; + GenTree* cnsNode2; + + if (simdBaseType == TYP_FLOAT) + { + simdBaseType = TYP_INT; + simdBaseJitType = CORINFO_TYPE_UINT; + + cnsNode1 = gtNewIconNode(0x00800000); + cnsNode2 = gtNewIconNode(0x7F800000 - 0x00800000); + } + else + { + assert(simdBaseType == TYP_DOUBLE); + + simdBaseType = TYP_LONG; + simdBaseJitType = CORINFO_TYPE_ULONG; + + cnsNode1 = gtNewLconNode(0x0010000000000000); + cnsNode2 = gtNewLconNode(0x7FF0000000000000 - 0x0010000000000000); + } + + cnsNode1 = gtNewSimdCreateBroadcastNode(type, cnsNode1, simdBaseJitType, simdSize); + cnsNode2 = gtNewSimdCreateBroadcastNode(type, cnsNode2, simdBaseJitType, simdSize); + + op1 = gtNewSimdBinOpNode(GT_SUB, type, op1, cnsNode1, simdBaseJitType, simdSize); + return gtNewSimdCmpOpNode(GT_LT, type, op1, cnsNode2, simdBaseJitType, simdSize); + } + + assert(varTypeIsIntegral(simdBaseType)); + return gtNewSimdCmpOpNode(GT_NE, type, op1, gtNewZeroConNode(type), simdBaseJitType, simdSize); +} + +//---------------------------------------------------------------------------------------------- +// Compiler::gtNewSimdIsOddIntegerNode: Creates a new simd IsOddInteger node +// +// Arguments: +// type - The return type of SIMD node being created +// op1 - The vector to check for odd integers +// simdBaseJitType - The base JIT type of SIMD type of the intrinsic +// simdSize - The size of the SIMD type of the intrinsic +// +// Returns: +// The created IsOddInteger node +// +GenTree* Compiler::gtNewSimdIsOddIntegerNode(var_types type, + GenTree* op1, + CorInfoType simdBaseJitType, + unsigned simdSize) +{ + assert(IsBaselineSimdIsaSupportedDebugOnly()); + + assert(varTypeIsSIMD(type)); + assert(getSIMDTypeForSize(simdSize) == type); + + assert(op1 != nullptr); + assert(op1->TypeIs(type)); + + var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); + assert(varTypeIsIntegral(simdBaseType)); + + op1 = gtNewSimdBinOpNode(GT_AND, type, op1, gtNewOneConNode(type, simdBaseType), simdBaseJitType, simdSize); + return gtNewSimdCmpOpNode(GT_NE, type, op1, gtNewZeroConNode(type), simdBaseJitType, simdSize); +} + //---------------------------------------------------------------------------------------------- // Compiler::gtNewSimdIsPositiveNode: Creates a new simd IsPositive node // // Arguments: // type - The return type of SIMD node being created -// op1 - The vector to check for Positives +// op1 - The vector to check for positives // simdBaseJitType - The base JIT type of SIMD type of the intrinsic // simdSize - The size of the SIMD type of the intrinsic // @@ -23680,7 +23987,7 @@ GenTree* Compiler::gtNewSimdIsPositiveNode(var_types type, GenTree* op1, CorInfo // // Arguments: // type - The return type of SIMD node being created -// op1 - The vector to check for PositiveInfinities +// op1 - The vector to check for positive infinities // simdBaseJitType - The base JIT type of SIMD type of the intrinsic // simdSize - The size of the SIMD type of the intrinsic // @@ -23705,14 +24012,91 @@ GenTree* Compiler::gtNewSimdIsPositiveInfinityNode(var_types type, if (varTypeIsFloating(simdBaseType)) { - double infinity = BitOperations::UInt64BitsToDouble(0x7FF0000000000000); - GenTree* cnsNode = gtNewDconNode(infinity, simdBaseType); - cnsNode = gtNewSimdCreateBroadcastNode(type, cnsNode, simdBaseJitType, simdSize); + GenTree* cnsNode; + + if (simdBaseType == TYP_FLOAT) + { + simdBaseType = TYP_INT; + simdBaseJitType = CORINFO_TYPE_UINT; + cnsNode = gtNewIconNode(0x7F800000); + } + else + { + assert(simdBaseType == TYP_DOUBLE); + + simdBaseType = TYP_LONG; + simdBaseJitType = CORINFO_TYPE_ULONG; + cnsNode = gtNewLconNode(0x7FF0000000000000); + } + cnsNode = gtNewSimdCreateBroadcastNode(type, cnsNode, simdBaseJitType, simdSize); + return gtNewSimdCmpOpNode(GT_EQ, type, op1, cnsNode, simdBaseJitType, simdSize); } return gtNewZeroConNode(type); } +//---------------------------------------------------------------------------------------------- +// Compiler::gtNewSimdIsSubnormalNode: Creates a new simd IsSubnormal node +// +// Arguments: +// type - The return type of SIMD node being created +// op1 - The vector to check for subnormal values +// simdBaseJitType - The base JIT type of SIMD type of the intrinsic +// simdSize - The size of the SIMD type of the intrinsic +// +// Returns: +// The created IsSubnormal node +// +GenTree* Compiler::gtNewSimdIsSubnormalNode(var_types type, + GenTree* op1, + CorInfoType simdBaseJitType, + unsigned simdSize) +{ + assert(IsBaselineSimdIsaSupportedDebugOnly()); + + assert(varTypeIsSIMD(type)); + assert(getSIMDTypeForSize(simdSize) == type); + + assert(op1 != nullptr); + assert(op1->TypeIs(type)); + + var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); + assert(varTypeIsArithmetic(simdBaseType)); + + if (varTypeIsFloating(simdBaseType)) + { + op1 = gtNewSimdAbsNode(type, op1, simdBaseJitType, simdSize); + + GenTree* cnsNode1; + GenTree* cnsNode2; + + if (simdBaseType == TYP_FLOAT) + { + simdBaseType = TYP_INT; + simdBaseJitType = CORINFO_TYPE_UINT; + + cnsNode2 = gtNewIconNode(0x007FFFFF); + } + else + { + assert(simdBaseType == TYP_DOUBLE); + + simdBaseType = TYP_LONG; + simdBaseJitType = CORINFO_TYPE_ULONG; + + cnsNode2 = gtNewLconNode(0x000FFFFFFFFFFFFF); + } + + cnsNode1 = gtNewOneConNode(type, simdBaseType); + cnsNode2 = gtNewSimdCreateBroadcastNode(type, cnsNode2, simdBaseJitType, simdSize); + + op1 = gtNewSimdBinOpNode(GT_SUB, type, op1, cnsNode1, simdBaseJitType, simdSize); + + return gtNewSimdCmpOpNode(GT_LT, type, op1, cnsNode2, simdBaseJitType, simdSize); + } + return gtNewZeroConNode(type); +} + //---------------------------------------------------------------------------------------------- // Compiler::gtNewSimdIsZeroNode: Creates a new simd IsZero node // diff --git a/src/coreclr/jit/hwintrinsicarm64.cpp b/src/coreclr/jit/hwintrinsicarm64.cpp index fac3e6c6216fe1..be1c577d4bdfaa 100644 --- a/src/coreclr/jit/hwintrinsicarm64.cpp +++ b/src/coreclr/jit/hwintrinsicarm64.cpp @@ -1343,7 +1343,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_op_Equality: { assert(sig->numArgs == 2); - var_types simdType = getSIMDTypeForSize(simdSize); op2 = impSIMDPopStack(); op1 = impSIMDPopStack(); @@ -1356,7 +1355,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_EqualsAny: { assert(sig->numArgs == 2); - var_types simdType = getSIMDTypeForSize(simdSize); op2 = impSIMDPopStack(); op1 = impSIMDPopStack(); @@ -1647,7 +1645,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_GreaterThanAll: { assert(sig->numArgs == 2); - var_types simdType = getSIMDTypeForSize(simdSize); op2 = impSIMDPopStack(); op1 = impSIMDPopStack(); @@ -1660,7 +1657,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_GreaterThanAny: { assert(sig->numArgs == 2); - var_types simdType = getSIMDTypeForSize(simdSize); op2 = impSIMDPopStack(); op1 = impSIMDPopStack(); @@ -1685,7 +1681,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_GreaterThanOrEqualAll: { assert(sig->numArgs == 2); - var_types simdType = getSIMDTypeForSize(simdSize); op2 = impSIMDPopStack(); op1 = impSIMDPopStack(); @@ -1698,7 +1693,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_GreaterThanOrEqualAny: { assert(sig->numArgs == 2); - var_types simdType = getSIMDTypeForSize(simdSize); op2 = impSIMDPopStack(); op1 = impSIMDPopStack(); @@ -1707,12 +1701,54 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } + case NI_Vector64_IsEvenInteger: + case NI_Vector128_IsEvenInteger: + { + assert(sig->numArgs == 1); + + if (varTypeIsFloating(simdBaseType)) + { + // The code for handling floating-point is decently complex but also expected + // to be rare, so we fallback to the managed implementation, which is accelerated + break; + } + + op1 = impSIMDPopStack(); + retNode = gtNewSimdIsEvenIntegerNode(retType, op1, simdBaseJitType, simdSize); + break; + } + + case NI_Vector64_IsFinite: + case NI_Vector128_IsFinite: + { + assert(sig->numArgs == 1); + op1 = impSIMDPopStack(); + retNode = gtNewSimdIsFiniteNode(retType, op1, simdBaseJitType, simdSize); + break; + } + + case NI_Vector64_IsInfinity: + case NI_Vector128_IsInfinity: + { + assert(sig->numArgs == 1); + op1 = impSIMDPopStack(); + retNode = gtNewSimdIsInfinityNode(retType, op1, simdBaseJitType, simdSize); + break; + } + + case NI_Vector64_IsInteger: + case NI_Vector128_IsInteger: + { + assert(sig->numArgs == 1); + op1 = impSIMDPopStack(); + retNode = gtNewSimdIsIntegerNode(retType, op1, simdBaseJitType, simdSize); + break; + } + case NI_Vector64_IsNaN: case NI_Vector128_IsNaN: { assert(sig->numArgs == 1); - var_types simdType = getSIMDTypeForSize(simdSize); - op1 = impSIMDPopStack(); retNode = gtNewSimdIsNaNNode(retType, op1, simdBaseJitType, simdSize); break; @@ -1722,19 +1758,50 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_IsNegative: { assert(sig->numArgs == 1); - var_types simdType = getSIMDTypeForSize(simdSize); - op1 = impSIMDPopStack(); retNode = gtNewSimdIsNegativeNode(retType, op1, simdBaseJitType, simdSize); break; } + case NI_Vector64_IsNegativeInfinity: + case NI_Vector128_IsNegativeInfinity: + { + assert(sig->numArgs == 1); + op1 = impSIMDPopStack(); + retNode = gtNewSimdIsNegativeInfinityNode(retType, op1, simdBaseJitType, simdSize); + break; + } + + case NI_Vector64_IsNormal: + case NI_Vector128_IsNormal: + { + assert(sig->numArgs == 1); + op1 = impSIMDPopStack(); + retNode = gtNewSimdIsNormalNode(retType, op1, simdBaseJitType, simdSize); + break; + } + + case NI_Vector64_IsOddInteger: + case NI_Vector128_IsOddInteger: + { + assert(sig->numArgs == 1); + + if (varTypeIsFloating(simdBaseType)) + { + // The code for handling floating-point is decently complex but also expected + // to be rare, so we fallback to the managed implementation, which is accelerated + break; + } + + op1 = impSIMDPopStack(); + retNode = gtNewSimdIsOddIntegerNode(retType, op1, simdBaseJitType, simdSize); + break; + } + case NI_Vector64_IsPositive: case NI_Vector128_IsPositive: { assert(sig->numArgs == 1); - var_types simdType = getSIMDTypeForSize(simdSize); - op1 = impSIMDPopStack(); retNode = gtNewSimdIsPositiveNode(retType, op1, simdBaseJitType, simdSize); break; @@ -1744,19 +1811,24 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_IsPositiveInfinity: { assert(sig->numArgs == 1); - var_types simdType = getSIMDTypeForSize(simdSize); - op1 = impSIMDPopStack(); retNode = gtNewSimdIsPositiveInfinityNode(retType, op1, simdBaseJitType, simdSize); break; } + case NI_Vector64_IsSubnormal: + case NI_Vector128_IsSubnormal: + { + assert(sig->numArgs == 1); + op1 = impSIMDPopStack(); + retNode = gtNewSimdIsSubnormalNode(retType, op1, simdBaseJitType, simdSize); + break; + } + case NI_Vector64_IsZero: case NI_Vector128_IsZero: { assert(sig->numArgs == 1); - var_types simdType = getSIMDTypeForSize(simdSize); - op1 = impSIMDPopStack(); retNode = gtNewSimdIsZeroNode(retType, op1, simdBaseJitType, simdSize); break; @@ -1778,7 +1850,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_LessThanAll: { assert(sig->numArgs == 2); - var_types simdType = getSIMDTypeForSize(simdSize); op2 = impSIMDPopStack(); op1 = impSIMDPopStack(); @@ -1791,7 +1862,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_LessThanAny: { assert(sig->numArgs == 2); - var_types simdType = getSIMDTypeForSize(simdSize); op2 = impSIMDPopStack(); op1 = impSIMDPopStack(); @@ -1816,7 +1886,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_LessThanOrEqualAll: { assert(sig->numArgs == 2); - var_types simdType = getSIMDTypeForSize(simdSize); op2 = impSIMDPopStack(); op1 = impSIMDPopStack(); @@ -1829,7 +1898,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_LessThanOrEqualAny: { assert(sig->numArgs == 2); - var_types simdType = getSIMDTypeForSize(simdSize); op2 = impSIMDPopStack(); op1 = impSIMDPopStack(); @@ -2068,7 +2136,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_op_Inequality: { assert(sig->numArgs == 2); - var_types simdType = getSIMDTypeForSize(simdSize); op2 = impSIMDPopStack(); op1 = impSIMDPopStack(); @@ -2153,6 +2220,35 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } + case NI_Vector64_ShiftLeft: + case NI_Vector128_ShiftLeft: + { + assert(sig->numArgs == 2); + + if (!varTypeIsSIMD(impStackTop(0).val)) + { + // We just want the inlining profitability boost for the helper intrinsics/ + // that have operator alternatives like `simd << int` + break; + } + + op2 = impSIMDPopStack(); + op1 = impSIMDPopStack(); + + if (simdSize == 8) + { + intrinsic = varTypeIsLong(simdBaseType) ? NI_AdvSimd_ShiftLogicalScalar : NI_AdvSimd_ShiftLogical; + } + else + { + assert(simdSize == 16); + intrinsic = NI_AdvSimd_ShiftLogical; + } + + retNode = gtNewSimdHWIntrinsicNode(retType, op1, op2, intrinsic, simdBaseJitType, simdSize); + break; + } + case NI_Vector64_Shuffle: case NI_Vector128_Shuffle: { @@ -2251,8 +2347,7 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, simdSize = 16; } - var_types simdType = getSIMDTypeForSize(simdSize); - op1 = impPopStack().val; + op1 = impPopStack().val; if (op1->OperIs(GT_CAST) && op1->gtGetOp1()->TypeIs(TYP_BYREF)) { @@ -2269,7 +2364,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_StoreUnsafe: { assert(retType == TYP_VOID); - var_types simdType = getSIMDTypeForSize(simdSize); if (sig->numArgs == 3) { @@ -2321,8 +2415,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } - var_types simdType = getSIMDTypeForSize(simdSize); - impSpillSideEffect(true, stackState.esStackDepth - 2 DEBUGARG("Spilling op1 side effects for HWIntrinsic")); op2 = impPopStack().val; @@ -2353,8 +2445,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } - var_types simdType = getSIMDTypeForSize(simdSize); - impSpillSideEffect(true, stackState.esStackDepth - 2 DEBUGARG("Spilling op1 side effects for HWIntrinsic")); op2 = impPopStack().val; @@ -2486,8 +2576,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector128_Sum: { assert(sig->numArgs == 1); - var_types simdType = getSIMDTypeForSize(simdSize); - op1 = impSIMDPopStack(); retNode = gtNewSimdSumNode(retType, op1, simdBaseJitType, simdSize); break; diff --git a/src/coreclr/jit/hwintrinsiclistarm64.h b/src/coreclr/jit/hwintrinsiclistarm64.h index 3f8c9ebf40dfaa..efad7ee0980253 100644 --- a/src/coreclr/jit/hwintrinsiclistarm64.h +++ b/src/coreclr/jit/hwintrinsiclistarm64.h @@ -60,10 +60,18 @@ HARDWARE_INTRINSIC(Vector64, GreaterThanAny, HARDWARE_INTRINSIC(Vector64, GreaterThanOrEqual, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector64, GreaterThanOrEqualAll, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector64, GreaterThanOrEqualAny, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector64, IsEvenInteger, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, IsFinite, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, IsInfinity, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, IsInteger, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector64, IsNaN, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector64, IsNegative, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, IsNegativeInfinity, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, IsNormal, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, IsOddInteger, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector64, IsPositive, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector64, IsPositiveInfinity, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, IsSubnormal, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector64, IsZero, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector64, LessThan, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector64, LessThanAll, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) @@ -81,7 +89,8 @@ HARDWARE_INTRINSIC(Vector64, MinNative, HARDWARE_INTRINSIC(Vector64, MultiplyAddEstimate, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector64, Narrow, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector64, Round, 8, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) -HARDWARE_INTRINSIC(Vector64, Shuffle, 8, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Vector64, ShiftLeft, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector64, Shuffle, 8, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_CanBenefitFromConstantProp) HARDWARE_INTRINSIC(Vector64, Sqrt, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector64, StoreAligned, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector64, StoreAlignedNonTemporal, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) @@ -173,10 +182,18 @@ HARDWARE_INTRINSIC(Vector128, GreaterThanAny, HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, IsEvenInteger, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, IsFinite, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, IsInfinity, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, IsInteger, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, IsNaN, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, IsNegative, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, IsNegativeInfinity, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, IsNormal, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, IsOddInteger, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, IsPositive, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, IsPositiveInfinity, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, IsSubnormal, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, IsZero, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, LessThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, LessThanAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) @@ -194,7 +211,8 @@ HARDWARE_INTRINSIC(Vector128, MinNative, HARDWARE_INTRINSIC(Vector128, MultiplyAddEstimate, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, Narrow, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, Round, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) -HARDWARE_INTRINSIC(Vector128, Shuffle, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Vector128, ShiftLeft, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, Shuffle, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_CanBenefitFromConstantProp) HARDWARE_INTRINSIC(Vector128, Sqrt, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, StoreAligned, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, StoreAlignedNonTemporal, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) diff --git a/src/coreclr/jit/hwintrinsiclistxarch.h b/src/coreclr/jit/hwintrinsiclistxarch.h index 1ba32f12e0611b..b76781500c56fa 100644 --- a/src/coreclr/jit/hwintrinsiclistxarch.h +++ b/src/coreclr/jit/hwintrinsiclistxarch.h @@ -78,10 +78,18 @@ HARDWARE_INTRINSIC(Vector128, GreaterThanAny, HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector128, IsEvenInteger, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, IsFinite, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, IsInfinity, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, IsInteger, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, IsNaN, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, IsNegative, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, IsNegativeInfinity, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, IsNormal, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, IsOddInteger, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, IsPositive, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, IsPositiveInfinity, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, IsSubnormal, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, IsZero, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, LessThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, LessThanAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) @@ -99,7 +107,8 @@ HARDWARE_INTRINSIC(Vector128, MinNative, HARDWARE_INTRINSIC(Vector128, MultiplyAddEstimate, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, Narrow, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, Round, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) -HARDWARE_INTRINSIC(Vector128, Shuffle, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Vector128, ShiftLeft, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector128, Shuffle, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_CanBenefitFromConstantProp) HARDWARE_INTRINSIC(Vector128, Sqrt, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector128, StoreAligned, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector128, StoreAlignedNonTemporal, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) @@ -188,10 +197,18 @@ HARDWARE_INTRINSIC(Vector256, GreaterThanAny, HARDWARE_INTRINSIC(Vector256, GreaterThanOrEqual, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector256, GreaterThanOrEqualAll, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector256, GreaterThanOrEqualAny, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector256, IsEvenInteger, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, IsFinite, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, IsInfinity, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, IsInteger, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector256, IsNaN, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector256, IsNegative, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, IsNegativeInfinity, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, IsNormal, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, IsOddInteger, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector256, IsPositive, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector256, IsPositiveInfinity, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, IsSubnormal, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector256, IsZero, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector256, LessThan, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector256, LessThanAll, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) @@ -209,7 +226,8 @@ HARDWARE_INTRINSIC(Vector256, MinNative, HARDWARE_INTRINSIC(Vector256, MultiplyAddEstimate, 32, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector256, Narrow, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector256, Round, 32, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) -HARDWARE_INTRINSIC(Vector256, Shuffle, 32, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Vector256, ShiftLeft, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector256, Shuffle, 32, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_CanBenefitFromConstantProp) HARDWARE_INTRINSIC(Vector256, Sqrt, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_AvxOnlyCompatible) HARDWARE_INTRINSIC(Vector256, StoreAligned, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) HARDWARE_INTRINSIC(Vector256, StoreAlignedNonTemporal, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) @@ -299,10 +317,18 @@ HARDWARE_INTRINSIC(Vector512, GreaterThanAny, HARDWARE_INTRINSIC(Vector512, GreaterThanOrEqual, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, GreaterThanOrEqualAll, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector512, GreaterThanOrEqualAny, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(Vector512, IsEvenInteger, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, IsFinite, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, IsInfinity, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, IsInteger, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, IsNaN, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, IsNegative, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, IsNegativeInfinity, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, IsNormal, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, IsOddInteger, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, IsPositive, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, IsPositiveInfinity, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, IsSubnormal, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, IsZero, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, LessThan, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, LessThanAll, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) @@ -320,7 +346,8 @@ HARDWARE_INTRINSIC(Vector512, MinNative, HARDWARE_INTRINSIC(Vector512, MultiplyAddEstimate, 64, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, Narrow, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, Round, 64, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) -HARDWARE_INTRINSIC(Vector512, Shuffle, 64, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Vector512, ShiftLeft, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) +HARDWARE_INTRINSIC(Vector512, Shuffle, 64, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_CanBenefitFromConstantProp) HARDWARE_INTRINSIC(Vector512, Sqrt, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId) HARDWARE_INTRINSIC(Vector512, StoreAligned, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) HARDWARE_INTRINSIC(Vector512, StoreAlignedNonTemporal, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_InvalidNodeId|HW_Flag_BaseTypeFromFirstArg) diff --git a/src/coreclr/jit/hwintrinsicxarch.cpp b/src/coreclr/jit/hwintrinsicxarch.cpp index 55aa44bbca94da..b85dba5c363699 100644 --- a/src/coreclr/jit/hwintrinsicxarch.cpp +++ b/src/coreclr/jit/hwintrinsicxarch.cpp @@ -2782,8 +2782,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, if ((simdSize != 32) || compOpportunisticallyDependsOn(InstructionSet_AVX2)) { - var_types simdType = getSIMDTypeForSize(simdSize); - op2 = impSIMDPopStack(); op1 = impSIMDPopStack(); @@ -2800,8 +2798,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, if ((simdSize != 32) || compOpportunisticallyDependsOn(InstructionSet_AVX2)) { - var_types simdType = getSIMDTypeForSize(simdSize); - op2 = impSIMDPopStack(); op1 = impSIMDPopStack(); @@ -2835,8 +2831,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, if ((simdSize != 32) || compOpportunisticallyDependsOn(InstructionSet_AVX2)) { - var_types simdType = getSIMDTypeForSize(simdSize); - op2 = impSIMDPopStack(); op1 = impSIMDPopStack(); @@ -2853,8 +2847,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, if ((simdSize != 32) || compOpportunisticallyDependsOn(InstructionSet_AVX2)) { - var_types simdType = getSIMDTypeForSize(simdSize); - op2 = impSIMDPopStack(); op1 = impSIMDPopStack(); @@ -2863,13 +2855,71 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } + case NI_Vector128_IsEvenInteger: + case NI_Vector256_IsEvenInteger: + case NI_Vector512_IsEvenInteger: + { + assert(sig->numArgs == 1); + + if (varTypeIsFloating(simdBaseType)) + { + // The code for handling floating-point is decently complex but also expected + // to be rare, so we fallback to the managed implementation, which is accelerated + break; + } + + op1 = impSIMDPopStack(); + retNode = gtNewSimdIsEvenIntegerNode(retType, op1, simdBaseJitType, simdSize); + break; + } + + case NI_Vector128_IsFinite: + case NI_Vector256_IsFinite: + case NI_Vector512_IsFinite: + { + assert(sig->numArgs == 1); + + if ((simdSize != 32) || compOpportunisticallyDependsOn(InstructionSet_AVX2)) + { + op1 = impSIMDPopStack(); + retNode = gtNewSimdIsFiniteNode(retType, op1, simdBaseJitType, simdSize); + } + break; + } + + case NI_Vector128_IsInfinity: + case NI_Vector256_IsInfinity: + case NI_Vector512_IsInfinity: + { + assert(sig->numArgs == 1); + + if ((simdSize != 32) || compOpportunisticallyDependsOn(InstructionSet_AVX2)) + { + op1 = impSIMDPopStack(); + retNode = gtNewSimdIsInfinityNode(retType, op1, simdBaseJitType, simdSize); + } + break; + } + + case NI_Vector128_IsInteger: + case NI_Vector256_IsInteger: + case NI_Vector512_IsInteger: + { + assert(sig->numArgs == 1); + + if ((simdSize != 32) || compOpportunisticallyDependsOn(InstructionSet_AVX2)) + { + op1 = impSIMDPopStack(); + retNode = gtNewSimdIsIntegerNode(retType, op1, simdBaseJitType, simdSize); + } + break; + } + case NI_Vector128_IsNaN: case NI_Vector256_IsNaN: case NI_Vector512_IsNaN: { assert(sig->numArgs == 1); - var_types simdType = getSIMDTypeForSize(simdSize); - op1 = impSIMDPopStack(); retNode = gtNewSimdIsNaNNode(retType, op1, simdBaseJitType, simdSize); break; @@ -2883,13 +2933,58 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, if ((simdSize != 32) || compOpportunisticallyDependsOn(InstructionSet_AVX2)) { - var_types simdType = getSIMDTypeForSize(simdSize); - op1 = impSIMDPopStack(); - retNode = gtNewSimdIsNegativeNode(retType, op1, simdBaseJitType, simdSize); + op1 = impSIMDPopStack(); + retNode = gtNewSimdIsNegativeNode(retType, op1, simdBaseJitType, simdSize); } break; } + case NI_Vector128_IsNegativeInfinity: + case NI_Vector256_IsNegativeInfinity: + case NI_Vector512_IsNegativeInfinity: + { + assert(sig->numArgs == 1); + + if ((simdSize != 32) || compOpportunisticallyDependsOn(InstructionSet_AVX2)) + { + op1 = impSIMDPopStack(); + retNode = gtNewSimdIsNegativeInfinityNode(retType, op1, simdBaseJitType, simdSize); + } + break; + } + + case NI_Vector128_IsNormal: + case NI_Vector256_IsNormal: + case NI_Vector512_IsNormal: + { + assert(sig->numArgs == 1); + + if ((simdSize != 32) || compOpportunisticallyDependsOn(InstructionSet_AVX2)) + { + op1 = impSIMDPopStack(); + retNode = gtNewSimdIsNormalNode(retType, op1, simdBaseJitType, simdSize); + } + break; + } + + case NI_Vector128_IsOddInteger: + case NI_Vector256_IsOddInteger: + case NI_Vector512_IsOddInteger: + { + assert(sig->numArgs == 1); + + if (varTypeIsFloating(simdBaseType)) + { + // The code for handling floating-point is decently complex but also expected + // to be rare, so we fallback to the managed implementation, which is accelerated + break; + } + + op1 = impSIMDPopStack(); + retNode = gtNewSimdIsOddIntegerNode(retType, op1, simdBaseJitType, simdSize); + break; + } + case NI_Vector128_IsPositive: case NI_Vector256_IsPositive: case NI_Vector512_IsPositive: @@ -2898,9 +2993,8 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, if ((simdSize != 32) || compOpportunisticallyDependsOn(InstructionSet_AVX2)) { - var_types simdType = getSIMDTypeForSize(simdSize); - op1 = impSIMDPopStack(); - retNode = gtNewSimdIsPositiveNode(retType, op1, simdBaseJitType, simdSize); + op1 = impSIMDPopStack(); + retNode = gtNewSimdIsPositiveNode(retType, op1, simdBaseJitType, simdSize); } break; } @@ -2910,10 +3004,26 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector512_IsPositiveInfinity: { assert(sig->numArgs == 1); - var_types simdType = getSIMDTypeForSize(simdSize); - op1 = impSIMDPopStack(); - retNode = gtNewSimdIsPositiveInfinityNode(retType, op1, simdBaseJitType, simdSize); + if ((simdSize != 32) || compOpportunisticallyDependsOn(InstructionSet_AVX2)) + { + op1 = impSIMDPopStack(); + retNode = gtNewSimdIsPositiveInfinityNode(retType, op1, simdBaseJitType, simdSize); + } + break; + } + + case NI_Vector128_IsSubnormal: + case NI_Vector256_IsSubnormal: + case NI_Vector512_IsSubnormal: + { + assert(sig->numArgs == 1); + + if ((simdSize != 32) || compOpportunisticallyDependsOn(InstructionSet_AVX2)) + { + op1 = impSIMDPopStack(); + retNode = gtNewSimdIsSubnormalNode(retType, op1, simdBaseJitType, simdSize); + } break; } @@ -2922,8 +3032,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector512_IsZero: { assert(sig->numArgs == 1); - var_types simdType = getSIMDTypeForSize(simdSize); - op1 = impSIMDPopStack(); retNode = gtNewSimdIsZeroNode(retType, op1, simdBaseJitType, simdSize); break; @@ -2954,8 +3062,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, if ((simdSize != 32) || compOpportunisticallyDependsOn(InstructionSet_AVX2)) { - var_types simdType = getSIMDTypeForSize(simdSize); - op2 = impSIMDPopStack(); op1 = impSIMDPopStack(); @@ -2972,8 +3078,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, if ((simdSize != 32) || compOpportunisticallyDependsOn(InstructionSet_AVX2)) { - var_types simdType = getSIMDTypeForSize(simdSize); - op2 = impSIMDPopStack(); op1 = impSIMDPopStack(); @@ -3007,8 +3111,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, if ((simdSize != 32) || compOpportunisticallyDependsOn(InstructionSet_AVX2)) { - var_types simdType = getSIMDTypeForSize(simdSize); - op2 = impSIMDPopStack(); op1 = impSIMDPopStack(); @@ -3025,8 +3127,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, if ((simdSize != 32) || compOpportunisticallyDependsOn(InstructionSet_AVX2)) { - var_types simdType = getSIMDTypeForSize(simdSize); - op2 = impSIMDPopStack(); op1 = impSIMDPopStack(); @@ -3350,8 +3450,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, if ((simdSize != 32) || varTypeIsFloating(simdBaseType) || compOpportunisticallyDependsOn(InstructionSet_AVX2)) { - var_types simdType = getSIMDTypeForSize(simdSize); - op2 = impSIMDPopStack(); op1 = impSIMDPopStack(); @@ -3366,8 +3464,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, if (IsBaselineVector512IsaSupportedOpportunistically()) { - var_types simdType = getSIMDTypeForSize(simdSize); - op2 = impSIMDPopStack(); op1 = impSIMDPopStack(); @@ -3491,6 +3587,39 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } + case NI_Vector128_ShiftLeft: + case NI_Vector256_ShiftLeft: + case NI_Vector512_ShiftLeft: + { + assert(sig->numArgs == 2); + + if (!varTypeIsSIMD(impStackTop(0).val)) + { + // We just want the inlining profitability boost for the helper intrinsics/ + // that have operator alternatives like `simd << int` + break; + } + + if ((simdSize != 16) || compOpportunisticallyDependsOn(InstructionSet_AVX2)) + { + op2 = impSIMDPopStack(); + op1 = impSIMDPopStack(); + + if (simdSize == 64) + { + intrinsic = NI_AVX512F_ShiftLeftLogicalVariable; + } + else + { + assert((simdSize == 16) || (simdSize == 32)); + intrinsic = NI_AVX2_ShiftLeftLogicalVariable; + } + + retNode = gtNewSimdHWIntrinsicNode(retType, op1, op2, intrinsic, simdBaseJitType, simdSize); + } + break; + } + case NI_Vector128_Shuffle: case NI_Vector256_Shuffle: case NI_Vector512_Shuffle: @@ -3553,8 +3682,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, assert(retType == TYP_VOID); assert(sig->numArgs == 2); - var_types simdType = getSIMDTypeForSize(simdSize); - op2 = impSIMDPopStack(); op1 = impPopStack().val; @@ -3573,7 +3700,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector512_StoreUnsafe: { assert(retType == TYP_VOID); - var_types simdType = getSIMDTypeForSize(simdSize); if (sig->numArgs == 3) { @@ -3618,8 +3744,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, assert(sig->numArgs == 2); assert(retType == TYP_VOID); - var_types simdType = getSIMDTypeForSize(simdSize); - impSpillSideEffect(true, stackState.esStackDepth - 2 DEBUGARG("Spilling op1 side effects for HWIntrinsic")); op2 = impPopStack().val; @@ -3643,8 +3767,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, assert(sig->numArgs == 2); assert(retType == TYP_VOID); - var_types simdType = getSIMDTypeForSize(simdSize); - impSpillSideEffect(true, stackState.esStackDepth - 2 DEBUGARG("Spilling op1 side effects for HWIntrinsic")); op2 = impPopStack().val; @@ -3666,7 +3788,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, case NI_Vector512_Sum: { assert(sig->numArgs == 1); - var_types simdType = getSIMDTypeForSize(simdSize); if ((simdSize == 32) && !compOpportunisticallyDependsOn(InstructionSet_AVX2)) { diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index ea6e8030cbadc6..c4efb0a63f8f3f 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -9699,6 +9699,26 @@ void Compiler::impImportBlockCode(BasicBlock* block) /* Push the result of the call on the stack */ impPushOnStack(gtNewLclvNode(lclNum, TYP_REF), tiRetVal); + +#ifdef DEBUG + // Under SPMI, look up info we might ask for if we stack allocate this array + // + if (JitConfig.EnableExtraSuperPmiQueries()) + { + void* pEmbedClsHnd; + info.compCompHnd->embedClassHandle(resolvedToken.hClass, &pEmbedClsHnd); + CORINFO_CLASS_HANDLE elemClsHnd = NO_CLASS_HANDLE; + CorInfoType elemCorType = info.compCompHnd->getChildType(resolvedToken.hClass, &elemClsHnd); + var_types elemType = JITtype2varType(elemCorType); + if (elemType == TYP_STRUCT) + { + typGetObjLayout(elemClsHnd); + info.compCompHnd->isValueClass(elemClsHnd); + } + void* pIndirection; + info.compCompHnd->getHelperFtn(CORINFO_HELP_MEMZERO, &pIndirection); + } +#endif } else { diff --git a/src/coreclr/jit/jitmetadatalist.h b/src/coreclr/jit/jitmetadatalist.h index 7ba0d732ab8645..db0f66f3f2c97e 100644 --- a/src/coreclr/jit/jitmetadatalist.h +++ b/src/coreclr/jit/jitmetadatalist.h @@ -68,6 +68,8 @@ JITMETADATAMETRIC(InlineAttempt, int, 0) JITMETADATAMETRIC(InlineCount, int, 0) JITMETADATAMETRIC(ProfileConsistentBeforeInline, int, 0) JITMETADATAMETRIC(ProfileConsistentAfterInline, int, 0) +JITMETADATAMETRIC(ProfileConsistentBeforeMorph, int, 0) +JITMETADATAMETRIC(ProfileConsistentAfterMorph, int, 0) JITMETADATAMETRIC(ProfileSynthesizedBlendedOrRepaired, int, 0) JITMETADATAMETRIC(ProfileInconsistentInitially, int, 0) JITMETADATAMETRIC(ProfileInconsistentResetLeave, int, 0) diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index 2e212085da8a92..5e41f5cea8ee3c 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -341,6 +341,8 @@ void Compiler::lvaInitArgs(InitVarDscInfo* varDscInfo) #if defined(TARGET_ARM) && defined(PROFILING_SUPPORTED) // Prespill all argument regs on to stack in case of Arm when under profiler. + // We do this as the arm32 CORINFO_HELP_FCN_ENTER helper does not preserve + // these registers, and is called very early. if (compIsProfilerHookNeeded()) { codeGen->regSet.rsMaskPreSpillRegArg |= RBM_ARG_REGS; @@ -4073,6 +4075,13 @@ void Compiler::lvaSortByRefCount() } #endif + // No benefit in tracking the PSPSym (if any) + // + if (lclNum == lvaPSPSym) + { + varDsc->lvTracked = 0; + } + // Are we not optimizing and we have exception handlers? // if so mark all args and locals "do not enregister". // @@ -4747,18 +4756,6 @@ PhaseStatus Compiler::lvaMarkLocalVars() #endif // FEATURE_EH_WINDOWS_X86 - // PSPSym is not used by the NativeAOT ABI - if (!IsTargetAbi(CORINFO_NATIVEAOT_ABI)) - { - if (UsesFunclets() && ehNeedsPSPSym()) - { - lvaPSPSym = lvaGrabTempWithImplicitUse(false DEBUGARG("PSPSym")); - LclVarDsc* lclPSPSym = lvaGetDesc(lvaPSPSym); - lclPSPSym->lvType = TYP_I_IMPL; - lvaSetVarDoNotEnregister(lvaPSPSym DEBUGARG(DoNotEnregisterReason::VMNeedsStackAddr)); - } - } - #ifdef JIT32_GCENCODER // LocAllocSPvar is only required by the implicit frame layout expected by the VM on x86. Whether // a function contains a Localloc is conveyed in the GC information, in the InfoHdrSmall.localloc diff --git a/src/coreclr/jit/loopcloning.cpp b/src/coreclr/jit/loopcloning.cpp index 0f6b681420a6da..b417622a0f38e2 100644 --- a/src/coreclr/jit/loopcloning.cpp +++ b/src/coreclr/jit/loopcloning.cpp @@ -2067,8 +2067,19 @@ void Compiler::optCloneLoop(FlowGraphNaturalLoop* loop, LoopCloneContext* contex // bottomRedirBlk [BBJ_ALWAYS --> bottomNext] // ... slow cloned loop (not yet inserted) // bottomNext - BasicBlock* bottom = loop->GetLexicallyBottomMostBlock(); - BasicBlock* newPred = bottom; + BasicBlock* bottom = loop->GetLexicallyBottomMostBlock(); + BasicBlock* beforeSlowPreheader = bottom; + + // Ensure the slow loop preheader ends up in the same EH region + // as the preheader. + // + bool inTry = false; + unsigned const enclosingRegion = ehGetMostNestedRegionIndex(preheader, &inTry); + if (!BasicBlock::sameEHRegion(beforeSlowPreheader, preheader)) + { + beforeSlowPreheader = fgFindInsertPoint(enclosingRegion, inTry, bottom, /* endBlk */ nullptr, + /* nearBlk */ bottom, /* jumpBlk */ nullptr, /* runRarely */ false); + } // Create a new preheader for the slow loop immediately before the slow // loop itself. All failed conditions will branch to the slow preheader. @@ -2078,22 +2089,20 @@ void Compiler::optCloneLoop(FlowGraphNaturalLoop* loop, LoopCloneContext* contex // The slow preheader needs to go in the same EH region as the preheader. // JITDUMP("Create unique preheader for slow path loop\n"); - const bool extendRegion = BasicBlock::sameEHRegion(bottom, preheader); - BasicBlock* slowPreheader = fgNewBBafter(BBJ_ALWAYS, newPred, extendRegion); - JITDUMP("Adding " FMT_BB " after " FMT_BB "\n", slowPreheader->bbNum, newPred->bbNum); - slowPreheader->bbWeight = newPred->isRunRarely() ? BB_ZERO_WEIGHT : ambientWeight; - slowPreheader->CopyFlags(newPred, (BBF_PROF_WEIGHT | BBF_RUN_RARELY)); + const bool extendRegion = BasicBlock::sameEHRegion(beforeSlowPreheader, preheader); + BasicBlock* slowPreheader = fgNewBBafter(BBJ_ALWAYS, beforeSlowPreheader, extendRegion); + JITDUMP("Adding " FMT_BB " after " FMT_BB "\n", slowPreheader->bbNum, beforeSlowPreheader->bbNum); + slowPreheader->bbWeight = preheader->isRunRarely() ? BB_ZERO_WEIGHT : ambientWeight; + slowPreheader->CopyFlags(preheader, (BBF_PROF_WEIGHT | BBF_RUN_RARELY)); slowPreheader->scaleBBWeight(LoopCloneContext::slowPathWeightScaleFactor); - // If we didn't extend the region above (because the last loop + // If we didn't extend the region above (because the beforeSlowPreheader // block was in some enclosed EH region), put the slow preheader // into the appropriate region, and make appropriate extent updates. // if (!extendRegion) { slowPreheader->copyEHRegion(preheader); - bool isTry = false; - unsigned enclosingRegion = ehGetMostNestedRegionIndex(slowPreheader, &isTry); if (enclosingRegion != 0) { @@ -2111,11 +2120,11 @@ void Compiler::optCloneLoop(FlowGraphNaturalLoop* loop, LoopCloneContext* contex } } } - newPred = slowPreheader; // Now we'll clone the blocks of the loop body. These cloned blocks will be the slow path. - + // BlockToBlockMap* blockMap = new (getAllocator(CMK_LoopClone)) BlockToBlockMap(getAllocator(CMK_LoopClone)); + BasicBlock* newPred = slowPreheader; if (cloneLoopsWithEH) { diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index b11495b8713921..724dd17082a4e3 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -3411,7 +3411,7 @@ void Lowering::RehomeArgForFastTailCall(unsigned int lclNum, //------------------------------------------------------------------------ // LowerTailCallViaJitHelper: lower a call via the tailcall JIT helper. Morph // has already inserted tailcall helper special arguments. This function inserts -// actual data for some placeholders. This function is only used on x86. +// actual data for some placeholders. This function is only used on Windows x86. // // Lower // tail.call(, int numberOfOldStackArgs, int dummyNumberOfNewStackArgs, int flags, void* dummyArg) @@ -9147,8 +9147,9 @@ void Lowering::LowerStoreIndirCoalescing(GenTreeIndir* ind) } // Since we're merging two stores of the same type, the new type is twice wider. - var_types oldType = ind->TypeGet(); - var_types newType; + var_types oldType = ind->TypeGet(); + var_types newType = TYP_UNDEF; + bool tryReusingPrevValue = false; switch (oldType) { case TYP_BYTE: @@ -9200,7 +9201,8 @@ void Lowering::LowerStoreIndirCoalescing(GenTreeIndir* ind) newType = TYP_SIMD32; break; } - return; + tryReusingPrevValue = true; + break; case TYP_SIMD32: if (comp->getPreferredVectorByteLength() >= 64) @@ -9208,8 +9210,14 @@ void Lowering::LowerStoreIndirCoalescing(GenTreeIndir* ind) newType = TYP_SIMD64; break; } - return; -#endif // TARGET_AMD64 + tryReusingPrevValue = true; + break; +#elif defined(TARGET_ARM64) // TARGET_AMD64 + case TYP_SIMD16: + tryReusingPrevValue = true; + break; + +#endif // TARGET_ARM64 #endif // FEATURE_HW_INTRINSICS #endif // TARGET_64BIT @@ -9222,6 +9230,27 @@ void Lowering::LowerStoreIndirCoalescing(GenTreeIndir* ind) return; } + // If we can't merge these two stores into a single store, we can at least + // cache prevData.value to a local and reuse it in currData. + // Normally, LSRA is expected to do this for us, but it's not always the case for SIMD. + if (tryReusingPrevValue) + { +#if defined(FEATURE_HW_INTRINSICS) + LIR::Use use; + if (currData.value->OperIs(GT_CNS_VEC) && GenTree::Compare(prevData.value, currData.value) && + BlockRange().TryGetUse(prevData.value, &use)) + { + GenTree* prevValueTmp = comp->gtNewLclvNode(use.ReplaceWithLclVar(comp), prevData.value->TypeGet()); + BlockRange().InsertBefore(currData.value, prevValueTmp); + BlockRange().Remove(currData.value); + ind->Data() = prevValueTmp; + } +#endif // FEATURE_HW_INTRINSICS + return; + } + + assert(newType != TYP_UNDEF); + // We should not be here for stores requiring write barriers. assert(!comp->codeGen->gcInfo.gcIsWriteBarrierStoreIndNode(ind->AsStoreInd())); assert(!comp->codeGen->gcInfo.gcIsWriteBarrierStoreIndNode(prevInd->AsStoreInd())); diff --git a/src/coreclr/jit/lowerxarch.cpp b/src/coreclr/jit/lowerxarch.cpp index 7ff007ca86a4bb..c80d19e9fdd4f2 100644 --- a/src/coreclr/jit/lowerxarch.cpp +++ b/src/coreclr/jit/lowerxarch.cpp @@ -1330,49 +1330,29 @@ void Lowering::LowerHWIntrinsicCC(GenTreeHWIntrinsic* node, NamedIntrinsic newIn void Lowering::LowerFusedMultiplyAdd(GenTreeHWIntrinsic* node) { assert(node->GetHWIntrinsicId() == NI_FMA_MultiplyAddScalar); - GenTreeHWIntrinsic* createScalarOps[3]; + assert(node->GetOperandCount() == 3); + bool negatedArgs[3] = {}; for (size_t i = 1; i <= 3; i++) { GenTree* arg = node->Op(i); - - if (!arg->OperIsHWIntrinsic() || (arg->AsHWIntrinsic()->GetHWIntrinsicId() != NI_Vector128_CreateScalarUnsafe)) + if (arg->OperIsHWIntrinsic(NI_Vector128_CreateScalarUnsafe)) { - return; + GenTree*& argOp = arg->AsHWIntrinsic()->Op(1); + if (argOp->OperIs(GT_NEG)) + { + BlockRange().Remove(argOp); + argOp = argOp->gtGetOp1(); + argOp->ClearContained(); + ContainCheckHWIntrinsic(arg->AsHWIntrinsic()); + negatedArgs[i - 1] = true; + } } - - createScalarOps[i - 1] = arg->AsHWIntrinsic(); - } - - GenTree* argX = createScalarOps[0]->Op(1); - GenTree* argY = createScalarOps[1]->Op(1); - GenTree* argZ = createScalarOps[2]->Op(1); - - const bool negMul = argX->OperIs(GT_NEG) != argY->OperIs(GT_NEG); - if (argX->OperIs(GT_NEG)) - { - createScalarOps[0]->Op(1) = argX->gtGetOp1(); - BlockRange().Remove(argX); - - createScalarOps[0]->Op(1)->ClearContained(); - ContainCheckHWIntrinsic(createScalarOps[0]); } - if (argY->OperIs(GT_NEG)) - { - createScalarOps[1]->Op(1) = argY->gtGetOp1(); - BlockRange().Remove(argY); - createScalarOps[1]->Op(1)->ClearContained(); - ContainCheckHWIntrinsic(createScalarOps[1]); - } - if (argZ->OperIs(GT_NEG)) + bool negMul = negatedArgs[0] ^ negatedArgs[1]; + if (negatedArgs[2]) { - createScalarOps[2]->Op(1) = argZ->gtGetOp1(); - BlockRange().Remove(argZ); - - createScalarOps[2]->Op(1)->ClearContained(); - ContainCheckHWIntrinsic(createScalarOps[2]); - node->ChangeHWIntrinsicId(negMul ? NI_FMA_MultiplySubtractNegatedScalar : NI_FMA_MultiplySubtractScalar); } else diff --git a/src/coreclr/jit/lsrabuild.cpp b/src/coreclr/jit/lsrabuild.cpp index 72f88864d755a7..21c5847da7c4fb 100644 --- a/src/coreclr/jit/lsrabuild.cpp +++ b/src/coreclr/jit/lsrabuild.cpp @@ -4300,6 +4300,16 @@ int LinearScan::BuildReturn(GenTree* tree) return 1; } } + else + { + // In other cases we require the incoming operand to be in the + // right register(s) when we build the use(s), and thus we do not + // need to model that as a kill. However, in this case we have a + // contained operand. Codegen will move it to the right return + // registers; thus they will be killed. + regMaskTP killedRegs = compiler->compRetTypeDesc.GetABIReturnRegs(compiler->info.compCallConv); + buildKillPositionsForNode(tree, currentLoc + 1, killedRegs); + } // No kills or defs. return 0; diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 8f42dd8743ce4e..8b2269bbd677de 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -5119,11 +5119,6 @@ GenTree* Compiler::fgMorphPotentialTailCall(GenTreeCall* call) // if (isImplicitOrStressTailCall) { - if (varDsc->lvHasLdAddrOp && !lvaIsImplicitByRefLocal(varNum)) - { - failTailCall("Local address taken", varNum); - return nullptr; - } if (varDsc->IsAddressExposed()) { if (lvaIsImplicitByRefLocal(varNum)) @@ -5366,55 +5361,27 @@ GenTree* Compiler::fgMorphPotentialTailCall(GenTreeCall* call) // if (compCurBB->KindIs(BBJ_ALWAYS)) { + BasicBlock* const curBlock = compCurBB; + BasicBlock* const targetBlock = curBlock->GetTarget(); + // Flow no longer reaches the target from here. // - fgRemoveRefPred(compCurBB->GetTargetEdge()); + fgRemoveRefPred(curBlock->GetTargetEdge()); - // Adjust profile weights of the successor blocks. + // Adjust profile weights of the successor block. // // Note if this is a tail call to loop, further updates // are needed once we install the loop edge. // - BasicBlock* curBlock = compCurBB; - if (curBlock->hasProfileWeight()) + if (curBlock->hasProfileWeight() && targetBlock->hasProfileWeight()) { - weight_t weightLoss = curBlock->bbWeight; - BasicBlock* nextBlock = curBlock->GetTarget(); + targetBlock->decreaseBBProfileWeight(curBlock->bbWeight); - while (nextBlock->hasProfileWeight()) + if (targetBlock->NumSucc() > 0) { - // Since we have linear flow we can update the next block weight. - // - weight_t const nextWeight = nextBlock->bbWeight; - weight_t const newNextWeight = nextWeight - weightLoss; - - // If the math would result in a negative weight then there's - // no local repair we can do; just leave things inconsistent. - // - if (newNextWeight >= 0) - { - // Note if we'd already morphed the IR in nextblock we might - // have done something profile sensitive that we should arguably reconsider. - // - JITDUMP("Reducing profile weight of " FMT_BB " from " FMT_WT " to " FMT_WT "\n", nextBlock->bbNum, - nextWeight, newNextWeight); - - nextBlock->setBBProfileWeight(newNextWeight); - } - else - { - JITDUMP("Not reducing profile weight of " FMT_BB " as its weight " FMT_WT - " is less than direct flow pred " FMT_BB " weight " FMT_WT "\n", - nextBlock->bbNum, nextWeight, compCurBB->bbNum, weightLoss); - } - - if (!nextBlock->KindIs(BBJ_ALWAYS)) - { - break; - } - - curBlock = nextBlock; - nextBlock = curBlock->GetTarget(); + JITDUMP("Flow removal out of " FMT_BB " needs to be propagated. Data %s inconsistent.\n", + curBlock->bbNum, fgPgoConsistent ? "is now" : "was already"); + fgPgoConsistent = false; } } } @@ -6319,7 +6286,7 @@ void Compiler::fgMorphTailCallViaJitHelper(GenTreeCall* call) // For the helper-assisted tail calls, we need to push all the arguments // into a single list, and then add a few extra at the beginning or end. // - // For x86, the tailcall helper is defined as: + // For Windows x86, the tailcall helper is defined as: // // JIT_TailCall(, int numberOfOldStackArgsWords, int numberOfNewStackArgsWords, int flags, void* // callTarget) @@ -6755,12 +6722,12 @@ void Compiler::fgMorphRecursiveFastTailCallIntoLoop(BasicBlock* block, GenTreeCa fgRemoveStmt(block, lastStmt); // Set the loop edge. + BasicBlock* entryBB; if (opts.IsOSR()) { // Todo: this may not look like a viable loop header. // Might need the moral equivalent of an init BB. - FlowEdge* const newEdge = fgAddRefPred(fgEntryBB, block); - block->SetKindAndTargetEdge(BBJ_ALWAYS, newEdge); + entryBB = fgEntryBB; } else { @@ -6769,9 +6736,19 @@ void Compiler::fgMorphRecursiveFastTailCallIntoLoop(BasicBlock* block, GenTreeCa // TODO-Cleanup: We should really be expanding tailcalls into loops // much earlier than this, at a place where we do not need to have // hacky workarounds to figure out what the actual IL entry block is. - BasicBlock* firstILBB = fgGetFirstILBlock(); - FlowEdge* const newEdge = fgAddRefPred(firstILBB, block); - block->SetKindAndTargetEdge(BBJ_ALWAYS, newEdge); + entryBB = fgGetFirstILBlock(); + } + + FlowEdge* const newEdge = fgAddRefPred(entryBB, block); + block->SetKindAndTargetEdge(BBJ_ALWAYS, newEdge); + + // Update profile + if (block->hasProfileWeight() && entryBB->hasProfileWeight()) + { + entryBB->increaseBBProfileWeight(block->bbWeight); + JITDUMP("Flow into entry BB " FMT_BB " increased. Data %s inconsistent.\n", entryBB->bbNum, + fgPgoConsistent ? "is now" : "was already"); + fgPgoConsistent = false; } // Finish hooking things up. @@ -12741,10 +12718,11 @@ Compiler::FoldResult Compiler::fgFoldConditional(BasicBlock* block) // modify the flow graph // Find the actual jump target - size_t switchVal = (size_t)cond->AsIntCon()->gtIconVal; - unsigned jumpCnt = block->GetSwitchTargets()->bbsCount; - FlowEdge** jumpTab = block->GetSwitchTargets()->bbsDstTab; - bool foundVal = false; + size_t switchVal = (size_t)cond->AsIntCon()->gtIconVal; + unsigned jumpCnt = block->GetSwitchTargets()->bbsCount; + FlowEdge** jumpTab = block->GetSwitchTargets()->bbsDstTab; + bool foundVal = false; + bool profileInconsistent = false; for (unsigned val = 0; val < jumpCnt; val++, jumpTab++) { @@ -12752,6 +12730,13 @@ Compiler::FoldResult Compiler::fgFoldConditional(BasicBlock* block) assert(curEdge->getDestinationBlock()->countOfInEdges() > 0); + BasicBlock* const targetBlock = curEdge->getDestinationBlock(); + if (block->hasProfileWeight() && targetBlock->hasProfileWeight()) + { + targetBlock->decreaseBBProfileWeight(curEdge->getLikelyWeight()); + profileInconsistent |= (targetBlock->NumSucc() > 0); + } + // If val matches switchVal or we are at the last entry and // we never found the switch value then set the new jump dest @@ -12759,6 +12744,12 @@ Compiler::FoldResult Compiler::fgFoldConditional(BasicBlock* block) { block->SetKindAndTargetEdge(BBJ_ALWAYS, curEdge); foundVal = true; + + if (block->hasProfileWeight() && targetBlock->hasProfileWeight()) + { + targetBlock->increaseBBProfileWeight(block->bbWeight); + profileInconsistent |= (targetBlock->NumSucc() > 0); + } } else { @@ -12767,6 +12758,13 @@ Compiler::FoldResult Compiler::fgFoldConditional(BasicBlock* block) } } + if (profileInconsistent) + { + JITDUMP("Flow change out of " FMT_BB " needs to be propagated. Data %s inconsistent.\n", block->bbNum, + fgPgoConsistent ? "is now" : "was already"); + fgPgoConsistent = false; + } + assert(foundVal); #ifdef DEBUG if (verbose) @@ -13408,6 +13406,11 @@ PhaseStatus Compiler::fgMorphBlocks() // fgGlobalMorph = true; + if (fgPgoConsistent) + { + Metrics.ProfileConsistentBeforeMorph = 1; + } + if (opts.OptimizationEnabled()) { // Local assertion prop is enabled if we are optimizing. @@ -13505,6 +13508,25 @@ PhaseStatus Compiler::fgMorphBlocks() fgEntryBB->bbRefs--; fgEntryBBExtraRefs = 0; + // The original method entry will now be checked for profile consistency. + // If the entry has inconsistent incoming weight, flag the profile as inconsistent. + // + if (fgEntryBB->hasProfileWeight()) + { + weight_t incomingWeight = BB_ZERO_WEIGHT; + for (FlowEdge* const predEdge : fgEntryBB->PredEdges()) + { + incomingWeight += predEdge->getLikelyWeight(); + } + + if (!fgProfileWeightsConsistent(incomingWeight, fgEntryBB->bbWeight)) + { + JITDUMP("OSR: Original method entry " FMT_BB " has inconsistent weight. Data %s inconsistent.\n", + fgPgoConsistent ? "is now" : "was already"); + fgPgoConsistent = false; + } + } + // We don't need to remember this block anymore. fgEntryBB = nullptr; } @@ -13544,6 +13566,11 @@ PhaseStatus Compiler::fgMorphBlocks() // may no longer be canonical. fgCanonicalizeFirstBB(); + if (fgPgoConsistent) + { + Metrics.ProfileConsistentAfterMorph = 1; + } + INDEBUG(fgPostGlobalMorphChecks();) return PhaseStatus::MODIFIED_EVERYTHING; @@ -14263,6 +14290,15 @@ bool Compiler::fgExpandQmarkStmt(BasicBlock* block, Statement* stmt) BasicBlock* condBlock = fgNewBBafter(BBJ_ALWAYS, block, true); BasicBlock* elseBlock = fgNewBBafter(BBJ_ALWAYS, condBlock, true); + // Update flowgraph + fgRedirectTargetEdge(block, condBlock); + condBlock->SetTargetEdge(fgAddRefPred(elseBlock, condBlock)); + elseBlock->SetTargetEdge(fgAddRefPred(remainderBlock, elseBlock)); + + // Propagate flow from block into condBlock. + // Leave flow out of remainderBlock intact, as it will post-dominate block. + condBlock->inheritWeight(block); + // These blocks are only internal if 'block' is (but they've been set as internal by fgNewBBafter). // If they're not internal, mark them as imported to avoid asserts about un-imported blocks. if (!block->HasFlag(BBF_INTERNAL)) @@ -14276,27 +14312,6 @@ bool Compiler::fgExpandQmarkStmt(BasicBlock* block, Statement* stmt) block->RemoveFlags(BBF_NEEDS_GCPOLL); remainderBlock->SetFlags(propagateFlagsToRemainder | propagateFlagsToAll); - condBlock->inheritWeight(block); - - // Make sure remainderBlock gets exactly the same weight as block after split - assert(condBlock->bbWeight == remainderBlock->bbWeight); - - assert(block->KindIs(BBJ_ALWAYS)); - fgRedirectTargetEdge(block, condBlock); - - { - FlowEdge* const newEdge = fgAddRefPred(elseBlock, condBlock); - condBlock->SetTargetEdge(newEdge); - } - - { - FlowEdge* const newEdge = fgAddRefPred(remainderBlock, elseBlock); - elseBlock->SetTargetEdge(newEdge); - } - - assert(condBlock->JumpsToNext()); - assert(elseBlock->JumpsToNext()); - condBlock->SetFlags(propagateFlagsToAll); elseBlock->SetFlags(propagateFlagsToAll); @@ -14311,6 +14326,7 @@ bool Compiler::fgExpandQmarkStmt(BasicBlock* block, Statement* stmt) // +--->--------+ // bbj_cond(true) // + // TODO: Remove unnecessary condition reversal gtReverseCond(condExpr); thenBlock = fgNewBBafter(BBJ_ALWAYS, condBlock, true); @@ -14324,13 +14340,12 @@ bool Compiler::fgExpandQmarkStmt(BasicBlock* block, Statement* stmt) const unsigned thenLikelihood = qmark->ThenNodeLikelihood(); const unsigned elseLikelihood = qmark->ElseNodeLikelihood(); - FlowEdge* const newEdge = fgAddRefPred(remainderBlock, thenBlock); - thenBlock->SetTargetEdge(newEdge); + thenBlock->SetTargetEdge(fgAddRefPred(remainderBlock, thenBlock)); assert(condBlock->TargetIs(elseBlock)); - FlowEdge* const elseEdge = fgAddRefPred(thenBlock, condBlock); - FlowEdge* const thenEdge = condBlock->GetTargetEdge(); - condBlock->SetCond(thenEdge, elseEdge); + FlowEdge* const thenEdge = fgAddRefPred(thenBlock, condBlock); + FlowEdge* const elseEdge = condBlock->GetTargetEdge(); + condBlock->SetCond(elseEdge, thenEdge); thenBlock->inheritWeightPercentage(condBlock, thenLikelihood); elseBlock->inheritWeightPercentage(condBlock, elseLikelihood); thenEdge->setLikelihood(thenLikelihood / 100.0); @@ -14344,6 +14359,7 @@ bool Compiler::fgExpandQmarkStmt(BasicBlock* block, Statement* stmt) // +-->-------------+ // bbj_cond(true) // + // TODO: Remove unnecessary condition reversal gtReverseCond(condExpr); const unsigned thenLikelihood = qmark->ThenNodeLikelihood(); diff --git a/src/coreclr/jit/optimizer.cpp b/src/coreclr/jit/optimizer.cpp index e7ee7c2f230471..2ed5909eab2aa5 100644 --- a/src/coreclr/jit/optimizer.cpp +++ b/src/coreclr/jit/optimizer.cpp @@ -2351,7 +2351,6 @@ bool Compiler::optInvertWhileLoop(BasicBlock* block) PhaseStatus Compiler::optInvertLoops() { noway_assert(opts.OptimizationEnabled()); - noway_assert(fgModified == false); #if defined(OPT_CONFIG) if (!JitConfig.JitDoLoopInversion()) @@ -2387,13 +2386,6 @@ PhaseStatus Compiler::optInvertLoops() } } - if (fgModified) - { - // Reset fgModified here as we've done a consistent set of edits. - // - fgModified = false; - } - return madeChanges ? PhaseStatus::MODIFIED_EVERYTHING : PhaseStatus::MODIFIED_NOTHING; } @@ -2410,7 +2402,6 @@ PhaseStatus Compiler::optInvertLoops() PhaseStatus Compiler::optOptimizeFlow() { noway_assert(opts.OptimizationEnabled()); - noway_assert(fgModified == false); fgUpdateFlowGraph(/* doTailDuplication */ true); fgReorderBlocks(/* useProfile */ false); diff --git a/src/coreclr/jit/targetriscv64.h b/src/coreclr/jit/targetriscv64.h index 768c958a15d3d1..e5dcded3d878f5 100644 --- a/src/coreclr/jit/targetriscv64.h +++ b/src/coreclr/jit/targetriscv64.h @@ -139,7 +139,7 @@ #define REG_WRITE_BARRIER_SRC_BYREF REG_T5 #define RBM_WRITE_BARRIER_SRC_BYREF RBM_T5 - #define RBM_CALLEE_TRASH_NOGC (RBM_T0|RBM_T1|RBM_T2|RBM_T3|RBM_T4|RBM_T5|RBM_T6|RBM_DEFAULT_HELPER_CALL_TARGET) + #define RBM_CALLEE_TRASH_NOGC (RBM_T0|RBM_T1|RBM_T2|RBM_T4|RBM_T6|RBM_DEFAULT_HELPER_CALL_TARGET) // Registers killed by CORINFO_HELP_ASSIGN_REF and CORINFO_HELP_CHECKED_ASSIGN_REF. #define RBM_CALLEE_TRASH_WRITEBARRIER (RBM_WRITE_BARRIER_DST|RBM_CALLEE_TRASH_NOGC) @@ -151,7 +151,7 @@ #define RBM_CALLEE_TRASH_WRITEBARRIER_BYREF (RBM_WRITE_BARRIER_DST_BYREF | RBM_WRITE_BARRIER_SRC_BYREF | RBM_CALLEE_TRASH_NOGC) // Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_BYREF. - // Note that x13 and x14 are still valid byref pointers after this helper call, despite their value being changed. + // Note that t3 and t5 are still valid byref pointers after this helper call, despite their value being changed. #define RBM_CALLEE_GCTRASH_WRITEBARRIER_BYREF RBM_CALLEE_TRASH_NOGC // GenericPInvokeCalliHelper VASigCookie Parameter diff --git a/src/coreclr/md/compiler/filtermanager.cpp b/src/coreclr/md/compiler/filtermanager.cpp index 1219bbeaabbfa1..2e3f3003353dcf 100644 --- a/src/coreclr/md/compiler/filtermanager.cpp +++ b/src/coreclr/md/compiler/filtermanager.cpp @@ -11,7 +11,7 @@ #include "stdafx.h" #include "filtermanager.h" -#define IsGlobalTypeDef(td) ((td) == TokenFromRid(mdtTypeDef, 1)) +#define IsGlobalTypeDef(td) ((td) == COR_GLOBAL_PARENT_TOKEN) //***************************************************************************** // Walk up to the containing tree and diff --git a/src/coreclr/md/compiler/regmeta_emit.cpp b/src/coreclr/md/compiler/regmeta_emit.cpp index dff2a329e5d109..eba625b297ef29 100644 --- a/src/coreclr/md/compiler/regmeta_emit.cpp +++ b/src/coreclr/md/compiler/regmeta_emit.cpp @@ -1202,7 +1202,7 @@ HRESULT RegMeta::_SetImplements( // S_OK or error. i++; - IfFailGo(UpdateENCLog(TokenFromRid(mdtInterfaceImpl, iInterfaceImpl))); + IfFailGo(UpdateENCLog(TokenFromRid(iInterfaceImpl, mdtInterfaceImpl))); } ErrExit: diff --git a/src/coreclr/md/runtime/metamodelro.cpp b/src/coreclr/md/runtime/metamodelro.cpp index 48e1f2e8e4f24f..4850db9833e699 100644 --- a/src/coreclr/md/runtime/metamodelro.cpp +++ b/src/coreclr/md/runtime/metamodelro.cpp @@ -411,7 +411,7 @@ CMiniMd::CommonGetCustomAttributeByNameEx( IfFailGo(GetCustomAttributeRecord(ridStart, &pRec)); IfFailGo(getValueOfCustomAttribute(pRec, reinterpret_cast(ppData), pcbData)); if (ptkCA) - *ptkCA = TokenFromRid(mdtCustomAttribute, ridStart); + *ptkCA = TokenFromRid(ridStart, mdtCustomAttribute); } break; } diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets index d8783480def1f7..0e633f34e3b24f 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets @@ -64,13 +64,7 @@ - - - - - diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets index 970b1debbf46e1..d2fe6e75e1db6f 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets @@ -39,7 +39,7 @@ The .NET Foundation licenses this file to you under the MIT license. $(RuntimeIdentifier) - + $(_targetArchitecture) x86_64 aarch64 arm64 diff --git a/src/coreclr/nativeaot/Runtime/amd64/ExceptionHandling.asm b/src/coreclr/nativeaot/Runtime/amd64/ExceptionHandling.asm index e6356dbe1bfcfd..741b916f00b904 100644 --- a/src/coreclr/nativeaot/Runtime/amd64/ExceptionHandling.asm +++ b/src/coreclr/nativeaot/Runtime/amd64/ExceptionHandling.asm @@ -532,7 +532,7 @@ endif ;; It was the ThreadAbortException, so rethrow it mov rcx, STATUS_REDHAWK_THREAD_ABORT mov rdx, rax ;; rdx <- continuation address as exception RIP - mov rax, RhpThrowHwEx ;; Throw the ThreadAbortException as a special kind of hardware exception + lea rax, [RhpThrowHwEx] ;; Throw the ThreadAbortException as a special kind of hardware exception ;; reset RSP and jump to RAX @@: mov rsp, r8 ;; reset the SP to resume SP value diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Augments/ReflectionAugments.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Augments/ReflectionAugments.cs index 86fbbcba782fe5..4eeda04b49f60c 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Augments/ReflectionAugments.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Augments/ReflectionAugments.cs @@ -93,11 +93,6 @@ internal static unsafe TypeCode GetRuntimeTypeCode(RuntimeType type) return TypeCode.Object; } - public static TypeLoadException CreateTypeLoadException(string message, string typeName) - { - return new TypeLoadException(message, typeName); - } - public static Assembly Load(AssemblyName assemblyRef, bool throwOnFileNotFound) { ArgumentNullException.ThrowIfNull(assemblyRef); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Helpers.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Helpers.cs index b6d019046c3884..946ba3cb736cd2 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Helpers.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Helpers.cs @@ -75,18 +75,10 @@ public static MethodInfo FilterAccessor(this MethodInfo accessor, bool nonPublic return null; } - public static TypeLoadException CreateTypeLoadException(string typeName, Assembly assemblyIfAny) - { - if (assemblyIfAny == null) - throw new TypeLoadException(SR.Format(SR.TypeLoad_TypeNotFound, typeName)); - else - throw Helpers.CreateTypeLoadException(typeName, assemblyIfAny.FullName); - } - public static TypeLoadException CreateTypeLoadException(string typeName, string assemblyName) { - string message = SR.Format(SR.TypeLoad_TypeNotFoundInAssembly, typeName, assemblyName); - return ReflectionAugments.CreateTypeLoadException(message, typeName); + string message = SR.Format(SR.TypeLoad_ResolveTypeFromAssembly, typeName, assemblyName); + return new TypeLoadException(message, typeName); } // Escape identifiers as described in "Specifying Fully Qualified Type Names" on msdn. diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/TypeResolver.NativeFormat.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/TypeResolver.NativeFormat.cs index 3aed59328d5026..3e3eb8fc6ffe84 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/TypeResolver.NativeFormat.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/TypeResolver.NativeFormat.cs @@ -195,7 +195,7 @@ internal static RuntimeTypeInfo ResolveTypeDefinition(this TypeDefinitionHandle Type? resolvedType = outerTypeInfo.GetNestedType(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); if (resolvedType == null) { - exception = Helpers.CreateTypeLoadException(outerTypeInfo.FullName + "+" + name, outerTypeInfo.Assembly); + exception = Helpers.CreateTypeLoadException(outerTypeInfo.FullName + "+" + name, outerTypeInfo.Assembly.FullName); return null; } return resolvedType.ToRuntimeTypeInfo(); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.NativeAot.cs index 51129f0fda74db..e512d04c3ac099 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.NativeAot.cs @@ -146,7 +146,8 @@ internal partial struct TypeNameResolver { throw new TypeLoadException(assembly is null ? SR.Format(SR.TypeLoad_ResolveType, escapedTypeName) : - SR.Format(SR.TypeLoad_ResolveTypeFromAssembly, escapedTypeName, assembly.FullName)); + SR.Format(SR.TypeLoad_ResolveTypeFromAssembly, escapedTypeName, assembly.FullName), + typeName: escapedTypeName); } return null; } @@ -234,7 +235,8 @@ internal partial struct TypeNameResolver if (_throwOnError) { throw new TypeLoadException(SR.Format(SR.TypeLoad_ResolveNestedType, - nestedTypeNames[i], (i > 0) ? nestedTypeNames[i - 1] : TypeNameHelpers.Unescape(escapedTypeName))); + nestedTypeNames[i], (i > 0) ? nestedTypeNames[i - 1] : TypeNameHelpers.Unescape(escapedTypeName)), + typeName: parsedName.FullName); } return null; } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/ThunkPool.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/ThunkPool.cs index 5996a37b81a548..fcfee9b11342f8 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/ThunkPool.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/ThunkPool.cs @@ -35,6 +35,7 @@ // using System.Diagnostics; +using System.Numerics; namespace System.Runtime { @@ -44,8 +45,8 @@ internal static class Constants public static readonly int ThunkCodeSize = RuntimeImports.RhpGetThunkSize(); public static readonly int NumThunksPerBlock = RuntimeImports.RhpGetNumThunksPerBlock(); public static readonly int NumThunkBlocksPerMapping = RuntimeImports.RhpGetNumThunkBlocksPerMapping(); - public static readonly uint ThunkBlockSize = (uint)RuntimeImports.RhpGetThunkBlockSize(); - public static readonly nuint ThunkBlockSizeMask = ThunkBlockSize - 1; + public static readonly uint PageSize = BitOperations.RoundUpToPowerOf2((uint)Math.Max(ThunkCodeSize * NumThunksPerBlock, ThunkDataSize * NumThunksPerBlock + IntPtr.Size)); + public static readonly nuint PageSizeMask = PageSize - 1; } internal class ThunksHeap @@ -97,11 +98,11 @@ private unsafe ThunksHeap(IntPtr commonStubAddress) IntPtr thunkDataBlock = RuntimeImports.RhpGetThunkDataBlockAddress(thunkStubsBlock); // Address of the first thunk data cell should be at the beginning of the thunks data block (page-aligned) - Debug.Assert(((nuint)(nint)thunkDataBlock % Constants.ThunkBlockSize) == 0); + Debug.Assert(((nuint)(nint)thunkDataBlock % Constants.PageSize) == 0); // Update the last pointer value in the thunks data section with the value of the common stub address - *(IntPtr*)(thunkDataBlock + (int)(Constants.ThunkBlockSize - IntPtr.Size)) = commonStubAddress; - Debug.Assert(*(IntPtr*)(thunkDataBlock + (int)(Constants.ThunkBlockSize - IntPtr.Size)) == commonStubAddress); + *(IntPtr*)(thunkDataBlock + (int)(Constants.PageSize - IntPtr.Size)) = commonStubAddress; + Debug.Assert(*(IntPtr*)(thunkDataBlock + (int)(Constants.PageSize - IntPtr.Size)) == commonStubAddress); // Set the head and end of the linked list _nextAvailableThunkPtr = thunkDataBlock; @@ -153,11 +154,11 @@ private unsafe bool ExpandHeap() IntPtr thunkDataBlock = RuntimeImports.RhpGetThunkDataBlockAddress(thunkStubsBlock); // Address of the first thunk data cell should be at the beginning of the thunks data block (page-aligned) - Debug.Assert(((nuint)(nint)thunkDataBlock % Constants.ThunkBlockSize) == 0); + Debug.Assert(((nuint)(nint)thunkDataBlock % Constants.PageSize) == 0); // Update the last pointer value in the thunks data section with the value of the common stub address - *(IntPtr*)(thunkDataBlock + (int)(Constants.ThunkBlockSize - IntPtr.Size)) = _commonStubAddress; - Debug.Assert(*(IntPtr*)(thunkDataBlock + (int)(Constants.ThunkBlockSize - IntPtr.Size)) == _commonStubAddress); + *(IntPtr*)(thunkDataBlock + (int)(Constants.PageSize - IntPtr.Size)) = _commonStubAddress; + Debug.Assert(*(IntPtr*)(thunkDataBlock + (int)(Constants.PageSize - IntPtr.Size)) == _commonStubAddress); // Link the last entry in the old list to the first entry in the new list *((IntPtr*)_lastThunkPtr) = thunkDataBlock; @@ -210,7 +211,7 @@ public unsafe IntPtr AllocateThunk() *((IntPtr*)(nextAvailableThunkPtr + IntPtr.Size)) = IntPtr.Zero; #endif - int thunkIndex = (int)(((nuint)(nint)nextAvailableThunkPtr) - ((nuint)(nint)nextAvailableThunkPtr & ~Constants.ThunkBlockSizeMask)); + int thunkIndex = (int)(((nuint)(nint)nextAvailableThunkPtr) - ((nuint)(nint)nextAvailableThunkPtr & ~Constants.PageSizeMask)); Debug.Assert((thunkIndex % Constants.ThunkDataSize) == 0); thunkIndex /= Constants.ThunkDataSize; @@ -266,7 +267,7 @@ private static IntPtr TryGetThunkDataAddress(IntPtr thunkAddress) nuint thunkAddressValue = (nuint)(nint)ClearThumbBit(thunkAddress); // Compute the base address of the thunk's mapping - nuint currentThunksBlockAddress = thunkAddressValue & ~Constants.ThunkBlockSizeMask; + nuint currentThunksBlockAddress = thunkAddressValue & ~Constants.PageSizeMask; // Make sure the thunk address is valid by checking alignment if ((thunkAddressValue - currentThunksBlockAddress) % (nuint)Constants.ThunkCodeSize != 0) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/TypeLoadException.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/TypeLoadException.NativeAot.cs index 538f41116fd1f2..5c74308e786de1 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/TypeLoadException.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/TypeLoadException.NativeAot.cs @@ -5,13 +5,6 @@ namespace System { public partial class TypeLoadException { - internal TypeLoadException(string message, string typeName) - : base(message) - { - HResult = HResults.COR_E_TYPELOAD; - _className = typeName; - } - private void SetMessageField() { _message ??= SR.Arg_TypeLoadException; diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs index fd9fba5b7d12e4..ace9bda16ba26c 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs @@ -719,7 +719,7 @@ private unsafe bool TryGetMethodForOriginalLdFtnResult_InvokeMap_Inner(NativeFor QTypeDefinition qTypeDefinition = GetMetadataForNamedType(declaringTypeHandleDefinition); MethodHandle nativeFormatMethodHandle = - (((int)HandleType.Method << 24) | (int)entryMethodHandleOrNameAndSigRaw).AsMethodHandle(); + (((int)HandleType.Method << 25) | (int)entryMethodHandleOrNameAndSigRaw).AsMethodHandle(); methodHandle = new QMethodDefinition(qTypeDefinition.NativeFormatReader, nativeFormatMethodHandle); } diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/MetadataReaderExtensions.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/MetadataReaderExtensions.cs index 28493dbc097696..00e67d79e6c588 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/MetadataReaderExtensions.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/MetadataReaderExtensions.cs @@ -19,7 +19,7 @@ public static MethodHandle AsMethodHandle(this int i) { unsafe { - Debug.Assert((HandleType)((uint)i >> 24) == HandleType.Method); + Debug.Assert((HandleType)((uint)i >> 25) == HandleType.Method); return *(MethodHandle*)&i; } } diff --git a/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/Internal/StackTraceMetadata/StackTraceMetadata.cs b/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/Internal/StackTraceMetadata/StackTraceMetadata.cs index 44ebfc5864c6ee..008119ebd10cad 100644 --- a/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/Internal/StackTraceMetadata/StackTraceMetadata.cs +++ b/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/Internal/StackTraceMetadata/StackTraceMetadata.cs @@ -347,7 +347,8 @@ private unsafe void PopulateRvaToTokenMap(TypeManagerHandle handle, byte* pMap, if ((command & StackTraceDataCommand.UpdateOwningType) != 0) { currentOwningType = Handle.FromIntToken((int)NativePrimitiveDecoder.ReadUInt32(ref pCurrent)); - Debug.Assert(currentOwningType.HandleType is HandleType.TypeDefinition or HandleType.TypeReference or HandleType.TypeSpecification); + Debug.Assert((command & StackTraceDataCommand.IsStackTraceHidden) != 0 || + currentOwningType.HandleType is HandleType.TypeDefinition or HandleType.TypeReference or HandleType.TypeSpecification); } if ((command & StackTraceDataCommand.UpdateName) != 0) diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.FieldAccess.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.FieldAccess.cs index f3d9ef3389204a..efe5e92830c6c1 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.FieldAccess.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.FieldAccess.cs @@ -129,7 +129,7 @@ private static unsafe bool TryGetFieldAccessMetadataFromFieldAccessMap( if ((entryFlags & FieldTableFlags.HasMetadataHandle) != 0) { - Handle entryFieldHandle = (((int)HandleType.Field << 24) | (int)entryParser.GetUnsigned()).AsHandle(); + Handle entryFieldHandle = (((int)HandleType.Field << 25) | (int)entryParser.GetUnsigned()).AsHandle(); if (!fieldHandle.Equals(entryFieldHandle)) continue; } diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs index 332b96d54c8474..6c94d937a87382 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs @@ -844,7 +844,7 @@ public void GetNext( if (_moduleHandle != _moduleForMethodHandle) return; - Handle entryMethodHandle = (((uint)HandleType.Method << 24) | entryParser.GetUnsigned()).AsHandle(); + Handle entryMethodHandle = (((uint)HandleType.Method << 25) | entryParser.GetUnsigned()).AsHandle(); if (!_methodHandle.Equals(entryMethodHandle)) return; } diff --git a/src/coreclr/pal/src/file/file.cpp b/src/coreclr/pal/src/file/file.cpp index d0eb9fb3d5d817..8eafaab2476bc9 100644 --- a/src/coreclr/pal/src/file/file.cpp +++ b/src/coreclr/pal/src/file/file.cpp @@ -73,11 +73,6 @@ CObjectType CorUnix::otFile( NULL, // No immutable data cleanup routine sizeof(CFileProcessLocalData), CFileProcessLocalDataCleanupRoutine, - GENERIC_READ|GENERIC_WRITE, // Ignored -- no Win32 object security support - CObjectType::SecuritySupported, - CObjectType::OSPersistedSecurityInfo, - CObjectType::UnnamedObject, - CObjectType::LocalDuplicationOnly, CObjectType::UnwaitableObject, CObjectType::SignalingNotApplicable, CObjectType::ThreadReleaseNotApplicable, diff --git a/src/coreclr/pal/src/include/pal/corunix.hpp b/src/coreclr/pal/src/include/pal/corunix.hpp index dce19f62279799..4ebed32d57659e 100644 --- a/src/coreclr/pal/src/include/pal/corunix.hpp +++ b/src/coreclr/pal/src/include/pal/corunix.hpp @@ -189,24 +189,6 @@ namespace CorUnix // supported generic access rights (e.g., GENERIC_READ) map to the // specific access rights for this object type. // - // If instances of this object may have a security descriptor set on - // them eSecuritySupport should be set to SecuritySupported. If the OS can - // persist security information for the object type (as would be the case - // for, say, files) eSecurityPersistence should be set to - // OSPersistedSecurityInfo. - // - // If the object may have a name eObjectNameSupport should be - // ObjectCanHaveName. A named object can be opened in more than one - // process. - // - // If it is possible to duplicate a handle to an object across process - // boundaries then eHandleDuplicationSupport should be set to - // CrossProcessDuplicationAllowed. Note that it is possible to have - // an object type where eObjectNameSupport is ObjectCanHaveName and - // eHandleDuplicationSupport is LocalDuplicationOnly. For these object - // types an unnamed object instance will only have references from - // the creating process. - // // If the object may be waited on eSynchronizationSupport should be // WaitableObject. (Note that this implies that object type supports // the SYNCHRONIZE access right.) @@ -232,31 +214,6 @@ namespace CorUnix class CObjectType { public: - - enum SecuritySupport - { - SecuritySupported, - SecurityNotSupported - }; - - enum SecurityPersistence - { - OSPersistedSecurityInfo, - SecurityInfoNotPersisted - }; - - enum ObjectNameSupport - { - ObjectCanHaveName, - UnnamedObject - }; - - enum HandleDuplicationSupport - { - CrossProcessDuplicationAllowed, - LocalDuplicationOnly - }; - enum SynchronizationSupport { WaitableObject, @@ -300,12 +257,7 @@ namespace CorUnix OBJECT_IMMUTABLE_DATA_CLEANUP_ROUTINE m_pImmutableDataCleanupRoutine; DWORD m_dwProcessLocalDataSize; OBJECT_PROCESS_LOCAL_DATA_CLEANUP_ROUTINE m_pProcessLocalDataCleanupRoutine; - DWORD m_dwSupportedAccessRights; // Generic access rights mapping - SecuritySupport m_eSecuritySupport; - SecurityPersistence m_eSecurityPersistence; - ObjectNameSupport m_eObjectNameSupport; - HandleDuplicationSupport m_eHandleDuplicationSupport; SynchronizationSupport m_eSynchronizationSupport; SignalingSemantics m_eSignalingSemantics; ThreadReleaseSemantics m_eThreadReleaseSemantics; @@ -321,11 +273,6 @@ namespace CorUnix OBJECT_IMMUTABLE_DATA_CLEANUP_ROUTINE pImmutableDataCleanupRoutine, DWORD dwProcessLocalDataSize, OBJECT_PROCESS_LOCAL_DATA_CLEANUP_ROUTINE pProcessLocalDataCleanupRoutine, - DWORD dwSupportedAccessRights, - SecuritySupport eSecuritySupport, - SecurityPersistence eSecurityPersistence, - ObjectNameSupport eObjectNameSupport, - HandleDuplicationSupport eHandleDuplicationSupport, SynchronizationSupport eSynchronizationSupport, SignalingSemantics eSignalingSemantics, ThreadReleaseSemantics eThreadReleaseSemantics, @@ -339,11 +286,6 @@ namespace CorUnix m_pImmutableDataCleanupRoutine(pImmutableDataCleanupRoutine), m_dwProcessLocalDataSize(dwProcessLocalDataSize), m_pProcessLocalDataCleanupRoutine(pProcessLocalDataCleanupRoutine), - m_dwSupportedAccessRights(dwSupportedAccessRights), - m_eSecuritySupport(eSecuritySupport), - m_eSecurityPersistence(eSecurityPersistence), - m_eObjectNameSupport(eObjectNameSupport), - m_eHandleDuplicationSupport(eHandleDuplicationSupport), m_eSynchronizationSupport(eSynchronizationSupport), m_eSignalingSemantics(eSignalingSemantics), m_eThreadReleaseSemantics(eThreadReleaseSemantics), @@ -433,48 +375,8 @@ namespace CorUnix return m_pProcessLocalDataCleanupRoutine; } - DWORD - GetSupportedAccessRights( - void - ) - { - return m_dwSupportedAccessRights; - }; - // Generic access rights mapping - SecuritySupport - GetSecuritySupport( - void - ) - { - return m_eSecuritySupport; - }; - - SecurityPersistence - GetSecurityPersistence( - void - ) - { - return m_eSecurityPersistence; - }; - - ObjectNameSupport - GetObjectNameSupport( - void - ) - { - return m_eObjectNameSupport; - }; - - HandleDuplicationSupport - GetHandleDuplicationSupport( - void - ) - { - return m_eHandleDuplicationSupport; - }; - SynchronizationSupport GetSynchronizationSupport( void diff --git a/src/coreclr/pal/src/map/map.cpp b/src/coreclr/pal/src/map/map.cpp index 1ffa6d73ab5e0a..090ce7dc1beb95 100644 --- a/src/coreclr/pal/src/map/map.cpp +++ b/src/coreclr/pal/src/map/map.cpp @@ -133,11 +133,6 @@ CObjectType CorUnix::otFileMapping( CFileMappingImmutableDataCleanupRoutine, sizeof(CFileMappingProcessLocalData), NULL, // No process local data cleanup routine - PAGE_READWRITE | PAGE_READONLY | PAGE_WRITECOPY, - CObjectType::SecuritySupported, - CObjectType::SecurityInfoNotPersisted, - CObjectType::UnnamedObject, - CObjectType::LocalDuplicationOnly, CObjectType::UnwaitableObject, CObjectType::SignalingNotApplicable, CObjectType::ThreadReleaseNotApplicable, diff --git a/src/coreclr/pal/src/synchmgr/synchcontrollers.cpp b/src/coreclr/pal/src/synchmgr/synchcontrollers.cpp index ec746d626f66ed..614944198d46bd 100644 --- a/src/coreclr/pal/src/synchmgr/synchcontrollers.cpp +++ b/src/coreclr/pal/src/synchmgr/synchcontrollers.cpp @@ -772,9 +772,7 @@ namespace CorUnix SynchData (e.g. modifying the object signal count accordingly with its thread release semantics) - Note: this method must be called while holding the appropriate - synchronization locks (the local process synch lock if the target - object is local, both local and shared one if the object is shared). + Note: this method must be called while holding the local process synch lock. --*/ PAL_ERROR CSynchData::ReleaseWaiterWithoutBlocking( CPalThread * pthrCurrent, diff --git a/src/coreclr/pal/src/synchobj/event.cpp b/src/coreclr/pal/src/synchobj/event.cpp index 86d6f6623e3252..619a55f28a4595 100644 --- a/src/coreclr/pal/src/synchobj/event.cpp +++ b/src/coreclr/pal/src/synchobj/event.cpp @@ -37,11 +37,6 @@ CObjectType CorUnix::otManualResetEvent( NULL, // No immutable data cleanup routine 0, // No process local data NULL, // No process local data cleanup routine - EVENT_ALL_ACCESS, // Currently ignored (no Win32 security) - CObjectType::SecuritySupported, - CObjectType::SecurityInfoNotPersisted, - CObjectType::UnnamedObject, - CObjectType::LocalDuplicationOnly, CObjectType::WaitableObject, CObjectType::ObjectCanBeUnsignaled, CObjectType::ThreadReleaseHasNoSideEffects, @@ -56,11 +51,6 @@ CObjectType CorUnix::otAutoResetEvent( NULL, // No immutable data cleanup routine 0, // No process local data NULL, // No process local data cleanup routine - EVENT_ALL_ACCESS, // Currently ignored (no Win32 security) - CObjectType::SecuritySupported, - CObjectType::SecurityInfoNotPersisted, - CObjectType::UnnamedObject, - CObjectType::LocalDuplicationOnly, CObjectType::WaitableObject, CObjectType::ObjectCanBeUnsignaled, CObjectType::ThreadReleaseAltersSignalCount, diff --git a/src/coreclr/pal/src/synchobj/mutex.cpp b/src/coreclr/pal/src/synchobj/mutex.cpp index ec0561813295a4..f720fbcfb5fe44 100644 --- a/src/coreclr/pal/src/synchobj/mutex.cpp +++ b/src/coreclr/pal/src/synchobj/mutex.cpp @@ -48,11 +48,6 @@ CObjectType CorUnix::otMutex( NULL, // No immutable data cleanup routine 0, // No process local data NULL, // No process local data cleanup routine - 0, // Should be MUTEX_ALL_ACCESS; currently ignored (no Win32 security) - CObjectType::SecuritySupported, - CObjectType::SecurityInfoNotPersisted, - CObjectType::UnnamedObject, - CObjectType::LocalDuplicationOnly, CObjectType::WaitableObject, CObjectType::ObjectCanBeUnsignaled, CObjectType::ThreadReleaseAltersSignalCount, @@ -69,11 +64,6 @@ CObjectType CorUnix::otNamedMutex( NULL, // No immutable data cleanup routine 0, // No process local data NULL, // No process local data cleanup routine - 0, // Should be MUTEX_ALL_ACCESS; currently ignored (no Win32 security) - CObjectType::SecuritySupported, - CObjectType::SecurityInfoNotPersisted, - CObjectType::UnnamedObject, // PAL's naming infrastructure is not used - CObjectType::LocalDuplicationOnly, CObjectType::UnwaitableObject, // PAL's waiting infrastructure is not used CObjectType::SignalingNotApplicable, // PAL's signaling infrastructure is not used CObjectType::ThreadReleaseNotApplicable, // PAL's signaling infrastructure is not used diff --git a/src/coreclr/pal/src/synchobj/semaphore.cpp b/src/coreclr/pal/src/synchobj/semaphore.cpp index 47d2881fff7860..3ea6fd487691ba 100644 --- a/src/coreclr/pal/src/synchobj/semaphore.cpp +++ b/src/coreclr/pal/src/synchobj/semaphore.cpp @@ -37,11 +37,6 @@ CObjectType CorUnix::otSemaphore( NULL, // No immutable data cleanup routine 0, // No process local data NULL, // No process local data cleanup routine - 0, // Should be SEMAPHORE_ALL_ACCESS; currently ignored (no Win32 security) - CObjectType::SecuritySupported, - CObjectType::SecurityInfoNotPersisted, - CObjectType::UnnamedObject, - CObjectType::LocalDuplicationOnly, CObjectType::WaitableObject, CObjectType::ObjectCanBeUnsignaled, CObjectType::ThreadReleaseAltersSignalCount, diff --git a/src/coreclr/pal/src/thread/process.cpp b/src/coreclr/pal/src/thread/process.cpp index ef7d00f43ba05c..8b51ec971800a8 100644 --- a/src/coreclr/pal/src/thread/process.cpp +++ b/src/coreclr/pal/src/thread/process.cpp @@ -137,11 +137,6 @@ CObjectType CorUnix::otProcess( NULL, // No immutable data cleanup routine sizeof(CProcProcessLocalData), NULL, // No process local data cleanup routine - PROCESS_ALL_ACCESS, - CObjectType::SecuritySupported, - CObjectType::SecurityInfoNotPersisted, - CObjectType::UnnamedObject, - CObjectType::CrossProcessDuplicationAllowed, CObjectType::WaitableObject, CObjectType::SingleTransitionObject, CObjectType::ThreadReleaseHasNoSideEffects, diff --git a/src/coreclr/pal/src/thread/thread.cpp b/src/coreclr/pal/src/thread/thread.cpp index 045b2ecebb9d8a..73203bfa3effe1 100644 --- a/src/coreclr/pal/src/thread/thread.cpp +++ b/src/coreclr/pal/src/thread/thread.cpp @@ -99,11 +99,6 @@ CObjectType CorUnix::otThread( NULL, // No immutable data cleanup routine sizeof(CThreadProcessLocalData), NULL, // No process local data cleanup routine - 0, // THREAD_ALL_ACCESS, - CObjectType::SecuritySupported, - CObjectType::SecurityInfoNotPersisted, - CObjectType::UnnamedObject, - CObjectType::LocalDuplicationOnly, CObjectType::WaitableObject, CObjectType::SingleTransitionObject, CObjectType::ThreadReleaseHasNoSideEffects, diff --git a/src/coreclr/scripts/superpmi.py b/src/coreclr/scripts/superpmi.py index 53cf7f2d21c2aa..229dd3bdfec897 100644 --- a/src/coreclr/scripts/superpmi.py +++ b/src/coreclr/scripts/superpmi.py @@ -1207,6 +1207,9 @@ def map_rsp_argument(line): if line.startswith("--exportsfile:"): arg_path = os.path.join(test_native_directory, os.path.basename(line[len("--exportsfile:"):])) return f"--exportsfile:{arg_path}" + elif line.startswith("--sourcelink:"): + arg_path = os.path.join(test_native_directory, os.path.basename(line[len("--sourcelink:"):])) + return f"--sourcelink:{arg_path}" elif line.startswith("--descriptor:"): arg_path = os.path.join(test_directory, os.path.basename(line[len("--descriptor:"):])) return f"--descriptor:{arg_path}" diff --git a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/Generator/ReaderGen.cs b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/Generator/ReaderGen.cs index c7fc7bec86027a..04f962ebb1c48d 100644 --- a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/Generator/ReaderGen.cs +++ b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/Generator/ReaderGen.cs @@ -128,9 +128,9 @@ private void EmitHandle(RecordDef record) CloseScope(); OpenScope($"internal {handleName}(int value)"); - WriteLine("HandleType hType = (HandleType)(value >> 24);"); - WriteLine($"Debug.Assert(hType == 0 || hType == HandleType.{record.Name} || hType == HandleType.Null);"); - WriteLine($"_value = (value & 0x00FFFFFF) | (((int)HandleType.{record.Name}) << 24);"); + WriteLine("HandleType hType = (HandleType)((uint)value >> 25);"); + WriteLine($"Debug.Assert(hType == HandleType.{record.Name} || hType == HandleType.Null);"); + WriteLine($"_value = (value & 0x01FFFFFF) | (((int)HandleType.{record.Name}) << 25);"); WriteLine("_Validate();"); CloseScope(); @@ -157,18 +157,18 @@ private void EmitHandle(RecordDef record) WriteLine(" => new Handle(handle._value);"); WriteLineIfNeeded(); - WriteLine("internal int Offset => (_value & 0x00FFFFFF);"); + WriteLine("internal int Offset => (_value & 0x01FFFFFF);"); WriteLineIfNeeded(); WriteLine($"public {record.Name} Get{record.Name}(MetadataReader reader)"); WriteLine($" => new {record.Name}(reader, this);"); WriteLineIfNeeded(); - WriteLine("public bool IsNil => (_value & 0x00FFFFFF) == 0;"); + WriteLine("public bool IsNil => (_value & 0x01FFFFFF) == 0;"); WriteScopeAttribute("[System.Diagnostics.Conditional(\"DEBUG\")]"); OpenScope("internal void _Validate()"); - WriteLine($"if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.{record.Name})"); + WriteLine($"if ((HandleType)((uint)_value >> 25) != HandleType.{record.Name})"); WriteLine(" throw new ArgumentException();"); CloseScope("_Validate"); diff --git a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/MdBinaryReader.cs b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/MdBinaryReader.cs index b52493d1b4bb1c..b6697fce3cbe8b 100644 --- a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/MdBinaryReader.cs +++ b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/MdBinaryReader.cs @@ -78,7 +78,7 @@ public static uint Read(this NativeReader reader, uint offset, out Handle handle { uint rawValue; offset = reader.DecodeUnsigned(offset, out rawValue); - handle = new Handle((HandleType)(byte)rawValue, (int)(rawValue >> 8)); + handle = new Handle((HandleType)(rawValue & 0x7F), (int)(rawValue >> 7)); return offset; } diff --git a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeFormatReaderGen.cs b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeFormatReaderGen.cs index 958e605b128249..b2fdce3f0c0cb1 100644 --- a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeFormatReaderGen.cs +++ b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeFormatReaderGen.cs @@ -70,9 +70,9 @@ internal ArraySignatureHandle(Handle handle) : this(handle._value) internal ArraySignatureHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ArraySignature || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ArraySignature) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ArraySignature || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ArraySignature) << 25); _Validate(); } @@ -95,17 +95,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ArraySignatureHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ArraySignature GetArraySignature(MetadataReader reader) => new ArraySignature(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ArraySignature) + if ((HandleType)((uint)_value >> 25) != HandleType.ArraySignature) throw new ArgumentException(); } // _Validate @@ -149,9 +149,9 @@ internal ByReferenceSignatureHandle(Handle handle) : this(handle._value) internal ByReferenceSignatureHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ByReferenceSignature || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ByReferenceSignature) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ByReferenceSignature || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ByReferenceSignature) << 25); _Validate(); } @@ -174,17 +174,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ByReferenceSignatureHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ByReferenceSignature GetByReferenceSignature(MetadataReader reader) => new ByReferenceSignature(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ByReferenceSignature) + if ((HandleType)((uint)_value >> 25) != HandleType.ByReferenceSignature) throw new ArgumentException(); } // _Validate @@ -227,9 +227,9 @@ internal ConstantBooleanArrayHandle(Handle handle) : this(handle._value) internal ConstantBooleanArrayHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantBooleanArray || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantBooleanArray) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ConstantBooleanArray || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ConstantBooleanArray) << 25); _Validate(); } @@ -252,17 +252,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ConstantBooleanArrayHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ConstantBooleanArray GetConstantBooleanArray(MetadataReader reader) => new ConstantBooleanArray(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantBooleanArray) + if ((HandleType)((uint)_value >> 25) != HandleType.ConstantBooleanArray) throw new ArgumentException(); } // _Validate @@ -305,9 +305,9 @@ internal ConstantBooleanValueHandle(Handle handle) : this(handle._value) internal ConstantBooleanValueHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantBooleanValue || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantBooleanValue) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ConstantBooleanValue || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ConstantBooleanValue) << 25); _Validate(); } @@ -330,17 +330,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ConstantBooleanValueHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ConstantBooleanValue GetConstantBooleanValue(MetadataReader reader) => new ConstantBooleanValue(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantBooleanValue) + if ((HandleType)((uint)_value >> 25) != HandleType.ConstantBooleanValue) throw new ArgumentException(); } // _Validate @@ -383,9 +383,9 @@ internal ConstantByteArrayHandle(Handle handle) : this(handle._value) internal ConstantByteArrayHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantByteArray || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantByteArray) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ConstantByteArray || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ConstantByteArray) << 25); _Validate(); } @@ -408,17 +408,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ConstantByteArrayHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ConstantByteArray GetConstantByteArray(MetadataReader reader) => new ConstantByteArray(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantByteArray) + if ((HandleType)((uint)_value >> 25) != HandleType.ConstantByteArray) throw new ArgumentException(); } // _Validate @@ -461,9 +461,9 @@ internal ConstantByteValueHandle(Handle handle) : this(handle._value) internal ConstantByteValueHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantByteValue || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantByteValue) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ConstantByteValue || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ConstantByteValue) << 25); _Validate(); } @@ -486,17 +486,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ConstantByteValueHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ConstantByteValue GetConstantByteValue(MetadataReader reader) => new ConstantByteValue(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantByteValue) + if ((HandleType)((uint)_value >> 25) != HandleType.ConstantByteValue) throw new ArgumentException(); } // _Validate @@ -539,9 +539,9 @@ internal ConstantCharArrayHandle(Handle handle) : this(handle._value) internal ConstantCharArrayHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantCharArray || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantCharArray) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ConstantCharArray || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ConstantCharArray) << 25); _Validate(); } @@ -564,17 +564,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ConstantCharArrayHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ConstantCharArray GetConstantCharArray(MetadataReader reader) => new ConstantCharArray(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantCharArray) + if ((HandleType)((uint)_value >> 25) != HandleType.ConstantCharArray) throw new ArgumentException(); } // _Validate @@ -617,9 +617,9 @@ internal ConstantCharValueHandle(Handle handle) : this(handle._value) internal ConstantCharValueHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantCharValue || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantCharValue) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ConstantCharValue || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ConstantCharValue) << 25); _Validate(); } @@ -642,17 +642,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ConstantCharValueHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ConstantCharValue GetConstantCharValue(MetadataReader reader) => new ConstantCharValue(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantCharValue) + if ((HandleType)((uint)_value >> 25) != HandleType.ConstantCharValue) throw new ArgumentException(); } // _Validate @@ -695,9 +695,9 @@ internal ConstantDoubleArrayHandle(Handle handle) : this(handle._value) internal ConstantDoubleArrayHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantDoubleArray || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantDoubleArray) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ConstantDoubleArray || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ConstantDoubleArray) << 25); _Validate(); } @@ -720,17 +720,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ConstantDoubleArrayHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ConstantDoubleArray GetConstantDoubleArray(MetadataReader reader) => new ConstantDoubleArray(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantDoubleArray) + if ((HandleType)((uint)_value >> 25) != HandleType.ConstantDoubleArray) throw new ArgumentException(); } // _Validate @@ -773,9 +773,9 @@ internal ConstantDoubleValueHandle(Handle handle) : this(handle._value) internal ConstantDoubleValueHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantDoubleValue || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantDoubleValue) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ConstantDoubleValue || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ConstantDoubleValue) << 25); _Validate(); } @@ -798,17 +798,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ConstantDoubleValueHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ConstantDoubleValue GetConstantDoubleValue(MetadataReader reader) => new ConstantDoubleValue(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantDoubleValue) + if ((HandleType)((uint)_value >> 25) != HandleType.ConstantDoubleValue) throw new ArgumentException(); } // _Validate @@ -855,9 +855,9 @@ internal ConstantEnumArrayHandle(Handle handle) : this(handle._value) internal ConstantEnumArrayHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantEnumArray || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantEnumArray) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ConstantEnumArray || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ConstantEnumArray) << 25); _Validate(); } @@ -880,17 +880,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ConstantEnumArrayHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ConstantEnumArray GetConstantEnumArray(MetadataReader reader) => new ConstantEnumArray(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantEnumArray) + if ((HandleType)((uint)_value >> 25) != HandleType.ConstantEnumArray) throw new ArgumentException(); } // _Validate @@ -937,9 +937,9 @@ internal ConstantEnumValueHandle(Handle handle) : this(handle._value) internal ConstantEnumValueHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantEnumValue || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantEnumValue) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ConstantEnumValue || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ConstantEnumValue) << 25); _Validate(); } @@ -962,17 +962,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ConstantEnumValueHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ConstantEnumValue GetConstantEnumValue(MetadataReader reader) => new ConstantEnumValue(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantEnumValue) + if ((HandleType)((uint)_value >> 25) != HandleType.ConstantEnumValue) throw new ArgumentException(); } // _Validate @@ -1015,9 +1015,9 @@ internal ConstantHandleArrayHandle(Handle handle) : this(handle._value) internal ConstantHandleArrayHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantHandleArray || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantHandleArray) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ConstantHandleArray || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ConstantHandleArray) << 25); _Validate(); } @@ -1040,17 +1040,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ConstantHandleArrayHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ConstantHandleArray GetConstantHandleArray(MetadataReader reader) => new ConstantHandleArray(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantHandleArray) + if ((HandleType)((uint)_value >> 25) != HandleType.ConstantHandleArray) throw new ArgumentException(); } // _Validate @@ -1093,9 +1093,9 @@ internal ConstantInt16ArrayHandle(Handle handle) : this(handle._value) internal ConstantInt16ArrayHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantInt16Array || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantInt16Array) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ConstantInt16Array || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ConstantInt16Array) << 25); _Validate(); } @@ -1118,17 +1118,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ConstantInt16ArrayHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ConstantInt16Array GetConstantInt16Array(MetadataReader reader) => new ConstantInt16Array(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantInt16Array) + if ((HandleType)((uint)_value >> 25) != HandleType.ConstantInt16Array) throw new ArgumentException(); } // _Validate @@ -1171,9 +1171,9 @@ internal ConstantInt16ValueHandle(Handle handle) : this(handle._value) internal ConstantInt16ValueHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantInt16Value || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantInt16Value) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ConstantInt16Value || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ConstantInt16Value) << 25); _Validate(); } @@ -1196,17 +1196,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ConstantInt16ValueHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ConstantInt16Value GetConstantInt16Value(MetadataReader reader) => new ConstantInt16Value(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantInt16Value) + if ((HandleType)((uint)_value >> 25) != HandleType.ConstantInt16Value) throw new ArgumentException(); } // _Validate @@ -1249,9 +1249,9 @@ internal ConstantInt32ArrayHandle(Handle handle) : this(handle._value) internal ConstantInt32ArrayHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantInt32Array || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantInt32Array) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ConstantInt32Array || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ConstantInt32Array) << 25); _Validate(); } @@ -1274,17 +1274,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ConstantInt32ArrayHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ConstantInt32Array GetConstantInt32Array(MetadataReader reader) => new ConstantInt32Array(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantInt32Array) + if ((HandleType)((uint)_value >> 25) != HandleType.ConstantInt32Array) throw new ArgumentException(); } // _Validate @@ -1327,9 +1327,9 @@ internal ConstantInt32ValueHandle(Handle handle) : this(handle._value) internal ConstantInt32ValueHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantInt32Value || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantInt32Value) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ConstantInt32Value || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ConstantInt32Value) << 25); _Validate(); } @@ -1352,17 +1352,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ConstantInt32ValueHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ConstantInt32Value GetConstantInt32Value(MetadataReader reader) => new ConstantInt32Value(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantInt32Value) + if ((HandleType)((uint)_value >> 25) != HandleType.ConstantInt32Value) throw new ArgumentException(); } // _Validate @@ -1405,9 +1405,9 @@ internal ConstantInt64ArrayHandle(Handle handle) : this(handle._value) internal ConstantInt64ArrayHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantInt64Array || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantInt64Array) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ConstantInt64Array || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ConstantInt64Array) << 25); _Validate(); } @@ -1430,17 +1430,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ConstantInt64ArrayHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ConstantInt64Array GetConstantInt64Array(MetadataReader reader) => new ConstantInt64Array(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantInt64Array) + if ((HandleType)((uint)_value >> 25) != HandleType.ConstantInt64Array) throw new ArgumentException(); } // _Validate @@ -1483,9 +1483,9 @@ internal ConstantInt64ValueHandle(Handle handle) : this(handle._value) internal ConstantInt64ValueHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantInt64Value || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantInt64Value) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ConstantInt64Value || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ConstantInt64Value) << 25); _Validate(); } @@ -1508,17 +1508,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ConstantInt64ValueHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ConstantInt64Value GetConstantInt64Value(MetadataReader reader) => new ConstantInt64Value(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantInt64Value) + if ((HandleType)((uint)_value >> 25) != HandleType.ConstantInt64Value) throw new ArgumentException(); } // _Validate @@ -1557,9 +1557,9 @@ internal ConstantReferenceValueHandle(Handle handle) : this(handle._value) internal ConstantReferenceValueHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantReferenceValue || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantReferenceValue) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ConstantReferenceValue || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ConstantReferenceValue) << 25); _Validate(); } @@ -1582,17 +1582,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ConstantReferenceValueHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ConstantReferenceValue GetConstantReferenceValue(MetadataReader reader) => new ConstantReferenceValue(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantReferenceValue) + if ((HandleType)((uint)_value >> 25) != HandleType.ConstantReferenceValue) throw new ArgumentException(); } // _Validate @@ -1635,9 +1635,9 @@ internal ConstantSByteArrayHandle(Handle handle) : this(handle._value) internal ConstantSByteArrayHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantSByteArray || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantSByteArray) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ConstantSByteArray || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ConstantSByteArray) << 25); _Validate(); } @@ -1660,17 +1660,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ConstantSByteArrayHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ConstantSByteArray GetConstantSByteArray(MetadataReader reader) => new ConstantSByteArray(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantSByteArray) + if ((HandleType)((uint)_value >> 25) != HandleType.ConstantSByteArray) throw new ArgumentException(); } // _Validate @@ -1713,9 +1713,9 @@ internal ConstantSByteValueHandle(Handle handle) : this(handle._value) internal ConstantSByteValueHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantSByteValue || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantSByteValue) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ConstantSByteValue || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ConstantSByteValue) << 25); _Validate(); } @@ -1738,17 +1738,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ConstantSByteValueHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ConstantSByteValue GetConstantSByteValue(MetadataReader reader) => new ConstantSByteValue(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantSByteValue) + if ((HandleType)((uint)_value >> 25) != HandleType.ConstantSByteValue) throw new ArgumentException(); } // _Validate @@ -1791,9 +1791,9 @@ internal ConstantSingleArrayHandle(Handle handle) : this(handle._value) internal ConstantSingleArrayHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantSingleArray || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantSingleArray) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ConstantSingleArray || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ConstantSingleArray) << 25); _Validate(); } @@ -1816,17 +1816,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ConstantSingleArrayHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ConstantSingleArray GetConstantSingleArray(MetadataReader reader) => new ConstantSingleArray(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantSingleArray) + if ((HandleType)((uint)_value >> 25) != HandleType.ConstantSingleArray) throw new ArgumentException(); } // _Validate @@ -1869,9 +1869,9 @@ internal ConstantSingleValueHandle(Handle handle) : this(handle._value) internal ConstantSingleValueHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantSingleValue || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantSingleValue) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ConstantSingleValue || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ConstantSingleValue) << 25); _Validate(); } @@ -1894,17 +1894,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ConstantSingleValueHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ConstantSingleValue GetConstantSingleValue(MetadataReader reader) => new ConstantSingleValue(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantSingleValue) + if ((HandleType)((uint)_value >> 25) != HandleType.ConstantSingleValue) throw new ArgumentException(); } // _Validate @@ -1948,9 +1948,9 @@ internal ConstantStringArrayHandle(Handle handle) : this(handle._value) internal ConstantStringArrayHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantStringArray || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantStringArray) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ConstantStringArray || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ConstantStringArray) << 25); _Validate(); } @@ -1973,17 +1973,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ConstantStringArrayHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ConstantStringArray GetConstantStringArray(MetadataReader reader) => new ConstantStringArray(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantStringArray) + if ((HandleType)((uint)_value >> 25) != HandleType.ConstantStringArray) throw new ArgumentException(); } // _Validate @@ -2028,9 +2028,9 @@ internal ConstantStringValueHandle(Handle handle) : this(handle._value) internal ConstantStringValueHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantStringValue || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantStringValue) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ConstantStringValue || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ConstantStringValue) << 25); _Validate(); } @@ -2053,17 +2053,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ConstantStringValueHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ConstantStringValue GetConstantStringValue(MetadataReader reader) => new ConstantStringValue(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantStringValue) + if ((HandleType)((uint)_value >> 25) != HandleType.ConstantStringValue) throw new ArgumentException(); } // _Validate @@ -2106,9 +2106,9 @@ internal ConstantUInt16ArrayHandle(Handle handle) : this(handle._value) internal ConstantUInt16ArrayHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantUInt16Array || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantUInt16Array) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ConstantUInt16Array || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ConstantUInt16Array) << 25); _Validate(); } @@ -2131,17 +2131,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ConstantUInt16ArrayHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ConstantUInt16Array GetConstantUInt16Array(MetadataReader reader) => new ConstantUInt16Array(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantUInt16Array) + if ((HandleType)((uint)_value >> 25) != HandleType.ConstantUInt16Array) throw new ArgumentException(); } // _Validate @@ -2184,9 +2184,9 @@ internal ConstantUInt16ValueHandle(Handle handle) : this(handle._value) internal ConstantUInt16ValueHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantUInt16Value || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantUInt16Value) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ConstantUInt16Value || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ConstantUInt16Value) << 25); _Validate(); } @@ -2209,17 +2209,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ConstantUInt16ValueHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ConstantUInt16Value GetConstantUInt16Value(MetadataReader reader) => new ConstantUInt16Value(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantUInt16Value) + if ((HandleType)((uint)_value >> 25) != HandleType.ConstantUInt16Value) throw new ArgumentException(); } // _Validate @@ -2262,9 +2262,9 @@ internal ConstantUInt32ArrayHandle(Handle handle) : this(handle._value) internal ConstantUInt32ArrayHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantUInt32Array || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantUInt32Array) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ConstantUInt32Array || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ConstantUInt32Array) << 25); _Validate(); } @@ -2287,17 +2287,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ConstantUInt32ArrayHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ConstantUInt32Array GetConstantUInt32Array(MetadataReader reader) => new ConstantUInt32Array(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantUInt32Array) + if ((HandleType)((uint)_value >> 25) != HandleType.ConstantUInt32Array) throw new ArgumentException(); } // _Validate @@ -2340,9 +2340,9 @@ internal ConstantUInt32ValueHandle(Handle handle) : this(handle._value) internal ConstantUInt32ValueHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantUInt32Value || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantUInt32Value) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ConstantUInt32Value || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ConstantUInt32Value) << 25); _Validate(); } @@ -2365,17 +2365,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ConstantUInt32ValueHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ConstantUInt32Value GetConstantUInt32Value(MetadataReader reader) => new ConstantUInt32Value(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantUInt32Value) + if ((HandleType)((uint)_value >> 25) != HandleType.ConstantUInt32Value) throw new ArgumentException(); } // _Validate @@ -2418,9 +2418,9 @@ internal ConstantUInt64ArrayHandle(Handle handle) : this(handle._value) internal ConstantUInt64ArrayHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantUInt64Array || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantUInt64Array) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ConstantUInt64Array || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ConstantUInt64Array) << 25); _Validate(); } @@ -2443,17 +2443,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ConstantUInt64ArrayHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ConstantUInt64Array GetConstantUInt64Array(MetadataReader reader) => new ConstantUInt64Array(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantUInt64Array) + if ((HandleType)((uint)_value >> 25) != HandleType.ConstantUInt64Array) throw new ArgumentException(); } // _Validate @@ -2496,9 +2496,9 @@ internal ConstantUInt64ValueHandle(Handle handle) : this(handle._value) internal ConstantUInt64ValueHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ConstantUInt64Value || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ConstantUInt64Value) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ConstantUInt64Value || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ConstantUInt64Value) << 25); _Validate(); } @@ -2521,17 +2521,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ConstantUInt64ValueHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ConstantUInt64Value GetConstantUInt64Value(MetadataReader reader) => new ConstantUInt64Value(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ConstantUInt64Value) + if ((HandleType)((uint)_value >> 25) != HandleType.ConstantUInt64Value) throw new ArgumentException(); } // _Validate @@ -2584,9 +2584,9 @@ internal CustomAttributeHandle(Handle handle) : this(handle._value) internal CustomAttributeHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.CustomAttribute || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.CustomAttribute) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.CustomAttribute || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.CustomAttribute) << 25); _Validate(); } @@ -2609,17 +2609,17 @@ public override bool Equals(object obj) public static implicit operator Handle(CustomAttributeHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public CustomAttribute GetCustomAttribute(MetadataReader reader) => new CustomAttribute(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.CustomAttribute) + if ((HandleType)((uint)_value >> 25) != HandleType.CustomAttribute) throw new ArgumentException(); } // _Validate @@ -2679,9 +2679,9 @@ internal EventHandle(Handle handle) : this(handle._value) internal EventHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.Event || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.Event) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.Event || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.Event) << 25); _Validate(); } @@ -2704,17 +2704,17 @@ public override bool Equals(object obj) public static implicit operator Handle(EventHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public Event GetEvent(MetadataReader reader) => new Event(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.Event) + if ((HandleType)((uint)_value >> 25) != HandleType.Event) throw new ArgumentException(); } // _Validate @@ -2778,9 +2778,9 @@ internal FieldHandle(Handle handle) : this(handle._value) internal FieldHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.Field || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.Field) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.Field || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.Field) << 25); _Validate(); } @@ -2803,17 +2803,17 @@ public override bool Equals(object obj) public static implicit operator Handle(FieldHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public Field GetField(MetadataReader reader) => new Field(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.Field) + if ((HandleType)((uint)_value >> 25) != HandleType.Field) throw new ArgumentException(); } // _Validate @@ -2857,9 +2857,9 @@ internal FieldSignatureHandle(Handle handle) : this(handle._value) internal FieldSignatureHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.FieldSignature || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.FieldSignature) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.FieldSignature || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.FieldSignature) << 25); _Validate(); } @@ -2882,17 +2882,17 @@ public override bool Equals(object obj) public static implicit operator Handle(FieldSignatureHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public FieldSignature GetFieldSignature(MetadataReader reader) => new FieldSignature(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.FieldSignature) + if ((HandleType)((uint)_value >> 25) != HandleType.FieldSignature) throw new ArgumentException(); } // _Validate @@ -2935,9 +2935,9 @@ internal FunctionPointerSignatureHandle(Handle handle) : this(handle._value) internal FunctionPointerSignatureHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.FunctionPointerSignature || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.FunctionPointerSignature) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.FunctionPointerSignature || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.FunctionPointerSignature) << 25); _Validate(); } @@ -2960,17 +2960,17 @@ public override bool Equals(object obj) public static implicit operator Handle(FunctionPointerSignatureHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public FunctionPointerSignature GetFunctionPointerSignature(MetadataReader reader) => new FunctionPointerSignature(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.FunctionPointerSignature) + if ((HandleType)((uint)_value >> 25) != HandleType.FunctionPointerSignature) throw new ArgumentException(); } // _Validate @@ -3034,9 +3034,9 @@ internal GenericParameterHandle(Handle handle) : this(handle._value) internal GenericParameterHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.GenericParameter || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.GenericParameter) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.GenericParameter || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.GenericParameter) << 25); _Validate(); } @@ -3059,17 +3059,17 @@ public override bool Equals(object obj) public static implicit operator Handle(GenericParameterHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public GenericParameter GetGenericParameter(MetadataReader reader) => new GenericParameter(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.GenericParameter) + if ((HandleType)((uint)_value >> 25) != HandleType.GenericParameter) throw new ArgumentException(); } // _Validate @@ -3122,9 +3122,9 @@ internal MemberReferenceHandle(Handle handle) : this(handle._value) internal MemberReferenceHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.MemberReference || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.MemberReference) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.MemberReference || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.MemberReference) << 25); _Validate(); } @@ -3147,17 +3147,17 @@ public override bool Equals(object obj) public static implicit operator Handle(MemberReferenceHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public MemberReference GetMemberReference(MetadataReader reader) => new MemberReference(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.MemberReference) + if ((HandleType)((uint)_value >> 25) != HandleType.MemberReference) throw new ArgumentException(); } // _Validate @@ -3224,9 +3224,9 @@ internal MethodHandle(Handle handle) : this(handle._value) internal MethodHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.Method || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.Method) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.Method || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.Method) << 25); _Validate(); } @@ -3249,17 +3249,17 @@ public override bool Equals(object obj) public static implicit operator Handle(MethodHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public Method GetMethod(MetadataReader reader) => new Method(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.Method) + if ((HandleType)((uint)_value >> 25) != HandleType.Method) throw new ArgumentException(); } // _Validate @@ -3308,9 +3308,9 @@ internal MethodInstantiationHandle(Handle handle) : this(handle._value) internal MethodInstantiationHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.MethodInstantiation || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.MethodInstantiation) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.MethodInstantiation || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.MethodInstantiation) << 25); _Validate(); } @@ -3333,17 +3333,17 @@ public override bool Equals(object obj) public static implicit operator Handle(MethodInstantiationHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public MethodInstantiation GetMethodInstantiation(MetadataReader reader) => new MethodInstantiation(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.MethodInstantiation) + if ((HandleType)((uint)_value >> 25) != HandleType.MethodInstantiation) throw new ArgumentException(); } // _Validate @@ -3390,9 +3390,9 @@ internal MethodSemanticsHandle(Handle handle) : this(handle._value) internal MethodSemanticsHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.MethodSemantics || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.MethodSemantics) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.MethodSemantics || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.MethodSemantics) << 25); _Validate(); } @@ -3415,17 +3415,17 @@ public override bool Equals(object obj) public static implicit operator Handle(MethodSemanticsHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public MethodSemantics GetMethodSemantics(MetadataReader reader) => new MethodSemantics(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.MethodSemantics) + if ((HandleType)((uint)_value >> 25) != HandleType.MethodSemantics) throw new ArgumentException(); } // _Validate @@ -3487,9 +3487,9 @@ internal MethodSignatureHandle(Handle handle) : this(handle._value) internal MethodSignatureHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.MethodSignature || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.MethodSignature) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.MethodSignature || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.MethodSignature) << 25); _Validate(); } @@ -3512,17 +3512,17 @@ public override bool Equals(object obj) public static implicit operator Handle(MethodSignatureHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public MethodSignature GetMethodSignature(MetadataReader reader) => new MethodSignature(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.MethodSignature) + if ((HandleType)((uint)_value >> 25) != HandleType.MethodSignature) throw new ArgumentException(); } // _Validate @@ -3565,9 +3565,9 @@ internal MethodTypeVariableSignatureHandle(Handle handle) : this(handle._value) internal MethodTypeVariableSignatureHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.MethodTypeVariableSignature || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.MethodTypeVariableSignature) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.MethodTypeVariableSignature || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.MethodTypeVariableSignature) << 25); _Validate(); } @@ -3590,17 +3590,17 @@ public override bool Equals(object obj) public static implicit operator Handle(MethodTypeVariableSignatureHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public MethodTypeVariableSignature GetMethodTypeVariableSignature(MetadataReader reader) => new MethodTypeVariableSignature(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.MethodTypeVariableSignature) + if ((HandleType)((uint)_value >> 25) != HandleType.MethodTypeVariableSignature) throw new ArgumentException(); } // _Validate @@ -3653,9 +3653,9 @@ internal ModifiedTypeHandle(Handle handle) : this(handle._value) internal ModifiedTypeHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ModifiedType || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ModifiedType) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ModifiedType || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ModifiedType) << 25); _Validate(); } @@ -3678,17 +3678,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ModifiedTypeHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ModifiedType GetModifiedType(MetadataReader reader) => new ModifiedType(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ModifiedType) + if ((HandleType)((uint)_value >> 25) != HandleType.ModifiedType) throw new ArgumentException(); } // _Validate @@ -3745,9 +3745,9 @@ internal NamedArgumentHandle(Handle handle) : this(handle._value) internal NamedArgumentHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.NamedArgument || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.NamedArgument) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.NamedArgument || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.NamedArgument) << 25); _Validate(); } @@ -3770,17 +3770,17 @@ public override bool Equals(object obj) public static implicit operator Handle(NamedArgumentHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public NamedArgument GetNamedArgument(MetadataReader reader) => new NamedArgument(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.NamedArgument) + if ((HandleType)((uint)_value >> 25) != HandleType.NamedArgument) throw new ArgumentException(); } // _Validate @@ -3840,9 +3840,9 @@ internal NamespaceDefinitionHandle(Handle handle) : this(handle._value) internal NamespaceDefinitionHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.NamespaceDefinition || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.NamespaceDefinition) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.NamespaceDefinition || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.NamespaceDefinition) << 25); _Validate(); } @@ -3865,17 +3865,17 @@ public override bool Equals(object obj) public static implicit operator Handle(NamespaceDefinitionHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public NamespaceDefinition GetNamespaceDefinition(MetadataReader reader) => new NamespaceDefinition(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.NamespaceDefinition) + if ((HandleType)((uint)_value >> 25) != HandleType.NamespaceDefinition) throw new ArgumentException(); } // _Validate @@ -3923,9 +3923,9 @@ internal NamespaceReferenceHandle(Handle handle) : this(handle._value) internal NamespaceReferenceHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.NamespaceReference || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.NamespaceReference) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.NamespaceReference || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.NamespaceReference) << 25); _Validate(); } @@ -3948,17 +3948,17 @@ public override bool Equals(object obj) public static implicit operator Handle(NamespaceReferenceHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public NamespaceReference GetNamespaceReference(MetadataReader reader) => new NamespaceReference(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.NamespaceReference) + if ((HandleType)((uint)_value >> 25) != HandleType.NamespaceReference) throw new ArgumentException(); } // _Validate @@ -4018,9 +4018,9 @@ internal ParameterHandle(Handle handle) : this(handle._value) internal ParameterHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.Parameter || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.Parameter) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.Parameter || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.Parameter) << 25); _Validate(); } @@ -4043,17 +4043,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ParameterHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public Parameter GetParameter(MetadataReader reader) => new Parameter(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.Parameter) + if ((HandleType)((uint)_value >> 25) != HandleType.Parameter) throw new ArgumentException(); } // _Validate @@ -4097,9 +4097,9 @@ internal PointerSignatureHandle(Handle handle) : this(handle._value) internal PointerSignatureHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.PointerSignature || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.PointerSignature) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.PointerSignature || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.PointerSignature) << 25); _Validate(); } @@ -4122,17 +4122,17 @@ public override bool Equals(object obj) public static implicit operator Handle(PointerSignatureHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public PointerSignature GetPointerSignature(MetadataReader reader) => new PointerSignature(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.PointerSignature) + if ((HandleType)((uint)_value >> 25) != HandleType.PointerSignature) throw new ArgumentException(); } // _Validate @@ -4196,9 +4196,9 @@ internal PropertyHandle(Handle handle) : this(handle._value) internal PropertyHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.Property || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.Property) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.Property || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.Property) << 25); _Validate(); } @@ -4221,17 +4221,17 @@ public override bool Equals(object obj) public static implicit operator Handle(PropertyHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public Property GetProperty(MetadataReader reader) => new Property(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.Property) + if ((HandleType)((uint)_value >> 25) != HandleType.Property) throw new ArgumentException(); } // _Validate @@ -4284,9 +4284,9 @@ internal PropertySignatureHandle(Handle handle) : this(handle._value) internal PropertySignatureHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.PropertySignature || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.PropertySignature) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.PropertySignature || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.PropertySignature) << 25); _Validate(); } @@ -4309,17 +4309,17 @@ public override bool Equals(object obj) public static implicit operator Handle(PropertySignatureHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public PropertySignature GetPropertySignature(MetadataReader reader) => new PropertySignature(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.PropertySignature) + if ((HandleType)((uint)_value >> 25) != HandleType.PropertySignature) throw new ArgumentException(); } // _Validate @@ -4366,9 +4366,9 @@ internal QualifiedFieldHandle(Handle handle) : this(handle._value) internal QualifiedFieldHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.QualifiedField || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.QualifiedField) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.QualifiedField || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.QualifiedField) << 25); _Validate(); } @@ -4391,17 +4391,17 @@ public override bool Equals(object obj) public static implicit operator Handle(QualifiedFieldHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public QualifiedField GetQualifiedField(MetadataReader reader) => new QualifiedField(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.QualifiedField) + if ((HandleType)((uint)_value >> 25) != HandleType.QualifiedField) throw new ArgumentException(); } // _Validate @@ -4448,9 +4448,9 @@ internal QualifiedMethodHandle(Handle handle) : this(handle._value) internal QualifiedMethodHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.QualifiedMethod || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.QualifiedMethod) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.QualifiedMethod || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.QualifiedMethod) << 25); _Validate(); } @@ -4473,17 +4473,17 @@ public override bool Equals(object obj) public static implicit operator Handle(QualifiedMethodHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public QualifiedMethod GetQualifiedMethod(MetadataReader reader) => new QualifiedMethod(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.QualifiedMethod) + if ((HandleType)((uint)_value >> 25) != HandleType.QualifiedMethod) throw new ArgumentException(); } // _Validate @@ -4527,9 +4527,9 @@ internal SZArraySignatureHandle(Handle handle) : this(handle._value) internal SZArraySignatureHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.SZArraySignature || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.SZArraySignature) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.SZArraySignature || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.SZArraySignature) << 25); _Validate(); } @@ -4552,17 +4552,17 @@ public override bool Equals(object obj) public static implicit operator Handle(SZArraySignatureHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public SZArraySignature GetSZArraySignature(MetadataReader reader) => new SZArraySignature(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.SZArraySignature) + if ((HandleType)((uint)_value >> 25) != HandleType.SZArraySignature) throw new ArgumentException(); } // _Validate @@ -4665,9 +4665,9 @@ internal ScopeDefinitionHandle(Handle handle) : this(handle._value) internal ScopeDefinitionHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ScopeDefinition || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ScopeDefinition) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ScopeDefinition || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ScopeDefinition) << 25); _Validate(); } @@ -4690,17 +4690,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ScopeDefinitionHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ScopeDefinition GetScopeDefinition(MetadataReader reader) => new ScopeDefinition(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ScopeDefinition) + if ((HandleType)((uint)_value >> 25) != HandleType.ScopeDefinition) throw new ArgumentException(); } // _Validate @@ -4771,9 +4771,9 @@ internal ScopeReferenceHandle(Handle handle) : this(handle._value) internal ScopeReferenceHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.ScopeReference || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.ScopeReference) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.ScopeReference || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.ScopeReference) << 25); _Validate(); } @@ -4796,17 +4796,17 @@ public override bool Equals(object obj) public static implicit operator Handle(ScopeReferenceHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public ScopeReference GetScopeReference(MetadataReader reader) => new ScopeReference(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.ScopeReference) + if ((HandleType)((uint)_value >> 25) != HandleType.ScopeReference) throw new ArgumentException(); } // _Validate @@ -4907,9 +4907,9 @@ internal TypeDefinitionHandle(Handle handle) : this(handle._value) internal TypeDefinitionHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.TypeDefinition || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.TypeDefinition) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.TypeDefinition || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.TypeDefinition) << 25); _Validate(); } @@ -4932,17 +4932,17 @@ public override bool Equals(object obj) public static implicit operator Handle(TypeDefinitionHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public TypeDefinition GetTypeDefinition(MetadataReader reader) => new TypeDefinition(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.TypeDefinition) + if ((HandleType)((uint)_value >> 25) != HandleType.TypeDefinition) throw new ArgumentException(); } // _Validate @@ -4993,9 +4993,9 @@ internal TypeForwarderHandle(Handle handle) : this(handle._value) internal TypeForwarderHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.TypeForwarder || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.TypeForwarder) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.TypeForwarder || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.TypeForwarder) << 25); _Validate(); } @@ -5018,17 +5018,17 @@ public override bool Equals(object obj) public static implicit operator Handle(TypeForwarderHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public TypeForwarder GetTypeForwarder(MetadataReader reader) => new TypeForwarder(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.TypeForwarder) + if ((HandleType)((uint)_value >> 25) != HandleType.TypeForwarder) throw new ArgumentException(); } // _Validate @@ -5077,9 +5077,9 @@ internal TypeInstantiationSignatureHandle(Handle handle) : this(handle._value) internal TypeInstantiationSignatureHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.TypeInstantiationSignature || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.TypeInstantiationSignature) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.TypeInstantiationSignature || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.TypeInstantiationSignature) << 25); _Validate(); } @@ -5102,17 +5102,17 @@ public override bool Equals(object obj) public static implicit operator Handle(TypeInstantiationSignatureHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public TypeInstantiationSignature GetTypeInstantiationSignature(MetadataReader reader) => new TypeInstantiationSignature(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.TypeInstantiationSignature) + if ((HandleType)((uint)_value >> 25) != HandleType.TypeInstantiationSignature) throw new ArgumentException(); } // _Validate @@ -5160,9 +5160,9 @@ internal TypeReferenceHandle(Handle handle) : this(handle._value) internal TypeReferenceHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.TypeReference || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.TypeReference) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.TypeReference || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.TypeReference) << 25); _Validate(); } @@ -5185,17 +5185,17 @@ public override bool Equals(object obj) public static implicit operator Handle(TypeReferenceHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public TypeReference GetTypeReference(MetadataReader reader) => new TypeReference(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.TypeReference) + if ((HandleType)((uint)_value >> 25) != HandleType.TypeReference) throw new ArgumentException(); } // _Validate @@ -5239,9 +5239,9 @@ internal TypeSpecificationHandle(Handle handle) : this(handle._value) internal TypeSpecificationHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.TypeSpecification || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.TypeSpecification) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.TypeSpecification || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.TypeSpecification) << 25); _Validate(); } @@ -5264,17 +5264,17 @@ public override bool Equals(object obj) public static implicit operator Handle(TypeSpecificationHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public TypeSpecification GetTypeSpecification(MetadataReader reader) => new TypeSpecification(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.TypeSpecification) + if ((HandleType)((uint)_value >> 25) != HandleType.TypeSpecification) throw new ArgumentException(); } // _Validate @@ -5317,9 +5317,9 @@ internal TypeVariableSignatureHandle(Handle handle) : this(handle._value) internal TypeVariableSignatureHandle(int value) { - HandleType hType = (HandleType)(value >> 24); - Debug.Assert(hType == 0 || hType == HandleType.TypeVariableSignature || hType == HandleType.Null); - _value = (value & 0x00FFFFFF) | (((int)HandleType.TypeVariableSignature) << 24); + HandleType hType = (HandleType)((uint)value >> 25); + Debug.Assert(hType == HandleType.TypeVariableSignature || hType == HandleType.Null); + _value = (value & 0x01FFFFFF) | (((int)HandleType.TypeVariableSignature) << 25); _Validate(); } @@ -5342,17 +5342,17 @@ public override bool Equals(object obj) public static implicit operator Handle(TypeVariableSignatureHandle handle) => new Handle(handle._value); - internal int Offset => (_value & 0x00FFFFFF); + internal int Offset => (_value & 0x01FFFFFF); public TypeVariableSignature GetTypeVariableSignature(MetadataReader reader) => new TypeVariableSignature(reader, this); - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; [System.Diagnostics.Conditional("DEBUG")] internal void _Validate() { - if ((HandleType)((_value & 0xFF000000) >> 24) != HandleType.TypeVariableSignature) + if ((HandleType)((uint)_value >> 25) != HandleType.TypeVariableSignature) throw new ArgumentException(); } // _Validate diff --git a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeMetadataReader.cs b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeMetadataReader.cs index 91c7b47d3c69c6..39d22fa8d2dd71 100644 --- a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeMetadataReader.cs +++ b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeMetadataReader.cs @@ -89,7 +89,7 @@ internal Handle(int value) internal void Validate(params HandleType[] permittedTypes) { - var myHandleType = (HandleType)(_value >> 24); + var myHandleType = (HandleType)((uint)_value >> 25); foreach (var hType in permittedTypes) { if (myHandleType == hType) @@ -106,14 +106,14 @@ internal void Validate(params HandleType[] permittedTypes) public Handle(HandleType type, int offset) { - _value = (int)type << 24 | (int)offset; + _value = (int)type << 25 | (int)offset; } - public HandleType HandleType => (HandleType)(_value >> 24); + public HandleType HandleType => (HandleType)((uint)_value >> 25); - internal int Offset => _value & 0x00FFFFFF; + internal int Offset => _value & 0x01FFFFFF; - public bool IsNil => (_value & 0x00FFFFFF) == 0; + public bool IsNil => (_value & 0x01FFFFFF) == 0; public int ToIntToken() => _value; @@ -194,7 +194,7 @@ public Handle NullHandle { get { - return new Handle(((int)HandleType.Null) << 24); + return new Handle(((int)HandleType.Null) << 25); } } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 5ac150b37ec474..c635b416708be2 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -1117,9 +1117,9 @@ private uint getMethodAttribsInternal(MethodDesc method) // TODO: Cache inlining hits // Check for an inlining directive. - if (method.IsNoInlining) + if (method.IsNoInlining || method.IsNoOptimization) { - /* Function marked as not inlineable */ + // NoOptimization implies NoInlining. result |= CorInfoFlag.CORINFO_FLG_DONT_INLINE; } else if (method.IsAggressiveInlining) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunHelperNode.cs index 17ba30882e7d5f..b531ea2a02ac2e 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunHelperNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunHelperNode.cs @@ -21,24 +21,17 @@ protected override void EmitCode(NodeFactory factory, ref ARMEmitter encoder, bo { MetadataType target = (MetadataType)Target; bool hasLazyStaticConstructor = factory.PreinitializationManager.HasLazyStaticConstructor(target); - encoder.EmitMOV(encoder.TargetRegister.Result, factory.TypeNonGCStaticsSymbol(target)); if (!hasLazyStaticConstructor) { + encoder.EmitMOV(encoder.TargetRegister.Result, factory.TypeNonGCStaticsSymbol(target)); encoder.EmitRET(); } else { - // We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. - encoder.EmitMOV(encoder.TargetRegister.Arg2, factory.TypeNonGCStaticsSymbol(target)); - encoder.EmitLDR(encoder.TargetRegister.Arg3, encoder.TargetRegister.Arg2, - (short)-NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); - encoder.EmitDMB(); - encoder.EmitCMP(encoder.TargetRegister.Arg3, 0); - encoder.EmitRETIfEqual(); - - encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); - encoder.EmitMOV(encoder.TargetRegister.Arg0/*Result*/, encoder.TargetRegister.Arg2); + // The fast path check is not necessary. It is always expanded by RyuJIT. + encoder.EmitMOV(encoder.TargetRegister.Arg1, factory.TypeNonGCStaticsSymbol(target)); + encoder.EmitMOV(encoder.TargetRegister.Arg0/*Result*/, encoder.TargetRegister.Arg1); encoder.EmitSUB(encoder.TargetRegister.Arg0, NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnNonGCStaticBase)); } @@ -76,23 +69,16 @@ protected override void EmitCode(NodeFactory factory, ref ARMEmitter encoder, bo { MetadataType target = (MetadataType)Target; encoder.EmitMOV(encoder.TargetRegister.Result, factory.TypeGCStaticsSymbol(target)); - encoder.EmitLDR(encoder.TargetRegister.Result, encoder.TargetRegister.Result); if (!factory.PreinitializationManager.HasLazyStaticConstructor(target)) { + encoder.EmitLDR(encoder.TargetRegister.Result, encoder.TargetRegister.Result); encoder.EmitRET(); } else { - // We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. - encoder.EmitMOV(encoder.TargetRegister.Arg2, factory.TypeNonGCStaticsSymbol(target)); - encoder.EmitLDR(encoder.TargetRegister.Arg3, encoder.TargetRegister.Arg2, - (short)-NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); - encoder.EmitDMB(); - encoder.EmitCMP(encoder.TargetRegister.Arg3, 0); - encoder.EmitRETIfEqual(); - - encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); - encoder.EmitMOV(encoder.TargetRegister.Arg0/*Result*/, encoder.TargetRegister.Arg2); + // The fast path check is not necessary. It is always expanded by RyuJIT. + encoder.EmitLDR(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); + encoder.EmitMOV(encoder.TargetRegister.Arg0, factory.TypeNonGCStaticsSymbol(target)); encoder.EmitSUB(encoder.TargetRegister.Arg0, NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnGCStaticBase)); } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM64/ARM64ReadyToRunHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM64/ARM64ReadyToRunHelperNode.cs index bfcea10d71d33c..ec39613a7932f3 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM64/ARM64ReadyToRunHelperNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM64/ARM64ReadyToRunHelperNode.cs @@ -23,23 +23,17 @@ protected override void EmitCode(NodeFactory factory, ref ARM64Emitter encoder, MetadataType target = (MetadataType)Target; bool hasLazyStaticConstructor = factory.PreinitializationManager.HasLazyStaticConstructor(target); - encoder.EmitMOV(encoder.TargetRegister.Result, factory.TypeNonGCStaticsSymbol(target)); if (!hasLazyStaticConstructor) { + encoder.EmitMOV(encoder.TargetRegister.Result, factory.TypeNonGCStaticsSymbol(target)); encoder.EmitRET(); } else { - // We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. - encoder.EmitSUB(encoder.TargetRegister.Arg3, encoder.TargetRegister.Result, NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); - encoder.EmitLDAR(encoder.TargetRegister.Arg2, encoder.TargetRegister.Arg3); - encoder.EmitCMP(encoder.TargetRegister.Arg2, 0); - encoder.EmitRETIfEqual(); - - encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); - encoder.EmitMOV(encoder.TargetRegister.Arg0, encoder.TargetRegister.Arg3); - + // The fast path check is not necessary. It is always expanded by RyuJIT. + encoder.EmitMOV(encoder.TargetRegister.Arg1, factory.TypeNonGCStaticsSymbol(target)); + encoder.EmitSUB(encoder.TargetRegister.Arg0, encoder.TargetRegister.Arg1, NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnNonGCStaticBase)); } } @@ -90,24 +84,18 @@ protected override void EmitCode(NodeFactory factory, ref ARM64Emitter encoder, MetadataType target = (MetadataType)Target; encoder.EmitMOV(encoder.TargetRegister.Result, factory.TypeGCStaticsSymbol(target)); - encoder.EmitLDR(encoder.TargetRegister.Result, encoder.TargetRegister.Result); if (!factory.PreinitializationManager.HasLazyStaticConstructor(target)) { + encoder.EmitLDR(encoder.TargetRegister.Result, encoder.TargetRegister.Result); encoder.EmitRET(); } else { - // We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. - encoder.EmitMOV(encoder.TargetRegister.Arg2, factory.TypeNonGCStaticsSymbol(target)); - encoder.EmitSUB(encoder.TargetRegister.Arg2, NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); - encoder.EmitLDAR(encoder.TargetRegister.Arg3, encoder.TargetRegister.Arg2); - encoder.EmitCMP(encoder.TargetRegister.Arg3, 0); - encoder.EmitRETIfEqual(); - - encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); - encoder.EmitMOV(encoder.TargetRegister.Arg0, encoder.TargetRegister.Arg2); - + // The fast path check is not necessary. It is always expanded by RyuJIT. + encoder.EmitLDR(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); + encoder.EmitMOV(encoder.TargetRegister.Arg0, factory.TypeNonGCStaticsSymbol(target)); + encoder.EmitSUB(encoder.TargetRegister.Arg0, NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnGCStaticBase)); } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_LoongArch64/LoongArch64ReadyToRunHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_LoongArch64/LoongArch64ReadyToRunHelperNode.cs index fee267399ecd7f..f4a80e9be0b571 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_LoongArch64/LoongArch64ReadyToRunHelperNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_LoongArch64/LoongArch64ReadyToRunHelperNode.cs @@ -23,24 +23,17 @@ protected override void EmitCode(NodeFactory factory, ref LoongArch64Emitter enc MetadataType target = (MetadataType)Target; bool hasLazyStaticConstructor = factory.PreinitializationManager.HasLazyStaticConstructor(target); - encoder.EmitMOV(encoder.TargetRegister.Result, factory.TypeNonGCStaticsSymbol(target)); if (!hasLazyStaticConstructor) { + encoder.EmitMOV(encoder.TargetRegister.Result, factory.TypeNonGCStaticsSymbol(target)); encoder.EmitRET(); } else { - // We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. - encoder.EmitADD(encoder.TargetRegister.Arg3, encoder.TargetRegister.Result, -NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); - encoder.EmitLD(encoder.TargetRegister.Arg2, encoder.TargetRegister.Arg3, factory.Target.PointerSize); - encoder.EmitDBAR(); - encoder.EmitXOR(encoder.TargetRegister.IntraProcedureCallScratch1, encoder.TargetRegister.Arg2, 1); - encoder.EmitRETIfEqual(encoder.TargetRegister.IntraProcedureCallScratch1); - - encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); - encoder.EmitMOV(encoder.TargetRegister.Arg0, encoder.TargetRegister.Arg3); - + // The fast path check is not necessary. It is always expanded by RyuJIT. + encoder.EmitMOV(encoder.TargetRegister.Arg1, factory.TypeNonGCStaticsSymbol(target)); + encoder.EmitADD(encoder.TargetRegister.Arg0, encoder.TargetRegister.Arg1, -NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnNonGCStaticBase)); } } @@ -83,25 +76,18 @@ protected override void EmitCode(NodeFactory factory, ref LoongArch64Emitter enc MetadataType target = (MetadataType)Target; encoder.EmitMOV(encoder.TargetRegister.Result, factory.TypeGCStaticsSymbol(target)); - encoder.EmitLD(encoder.TargetRegister.Result, encoder.TargetRegister.Result, 0); if (!factory.PreinitializationManager.HasLazyStaticConstructor(target)) { + encoder.EmitLD(encoder.TargetRegister.Result, encoder.TargetRegister.Result, 0); encoder.EmitRET(); } else { - // We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. - encoder.EmitMOV(encoder.TargetRegister.Arg2, factory.TypeNonGCStaticsSymbol(target)); - encoder.EmitADD(encoder.TargetRegister.Arg2, encoder.TargetRegister.Arg2, -NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); - encoder.EmitLD(encoder.TargetRegister.Arg3, encoder.TargetRegister.Arg2, 0); - encoder.EmitDBAR(); - encoder.EmitXOR(encoder.TargetRegister.IntraProcedureCallScratch1, encoder.TargetRegister.Arg3, 0); - encoder.EmitRETIfEqual(Register.R21); - - encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); - encoder.EmitMOV(encoder.TargetRegister.Arg0, encoder.TargetRegister.Arg2); - + // The fast path check is not necessary. It is always expanded by RyuJIT. + encoder.EmitLD(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result, 0); + encoder.EmitMOV(encoder.TargetRegister.Arg0, factory.TypeNonGCStaticsSymbol(target)); + encoder.EmitADD(encoder.TargetRegister.Arg0, encoder.TargetRegister.Arg0, -NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnGCStaticBase)); } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_RiscV64/RiscV64ReadyToRunHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_RiscV64/RiscV64ReadyToRunHelperNode.cs index c6ad35d1c76add..998efd900846fb 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_RiscV64/RiscV64ReadyToRunHelperNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_RiscV64/RiscV64ReadyToRunHelperNode.cs @@ -23,22 +23,17 @@ protected override void EmitCode(NodeFactory factory, ref RiscV64Emitter encoder MetadataType target = (MetadataType)Target; bool hasLazyStaticConstructor = factory.PreinitializationManager.HasLazyStaticConstructor(target); - encoder.EmitMOV(encoder.TargetRegister.Result, factory.TypeNonGCStaticsSymbol(target)); if (!hasLazyStaticConstructor) { + encoder.EmitMOV(encoder.TargetRegister.Result, factory.TypeNonGCStaticsSymbol(target)); encoder.EmitRET(); } else { - // We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. - encoder.EmitADDI(encoder.TargetRegister.Arg3, encoder.TargetRegister.Result, -NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); - encoder.EmitLD(encoder.TargetRegister.Arg2, encoder.TargetRegister.Arg3, 0); - encoder.EmitRETIfZero(encoder.TargetRegister.Arg2); - - encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); - encoder.EmitMOV(encoder.TargetRegister.Arg0, encoder.TargetRegister.Arg3); - + // The fast path check is not necessary. It is always expanded by RyuJIT. + encoder.EmitMOV(encoder.TargetRegister.Arg1, factory.TypeNonGCStaticsSymbol(target)); + encoder.EmitADDI(encoder.TargetRegister.Arg0, encoder.TargetRegister.Arg1, -NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnNonGCStaticBase)); } } @@ -79,23 +74,18 @@ protected override void EmitCode(NodeFactory factory, ref RiscV64Emitter encoder MetadataType target = (MetadataType)Target; encoder.EmitMOV(encoder.TargetRegister.Result, factory.TypeGCStaticsSymbol(target)); - encoder.EmitLD(encoder.TargetRegister.Result, encoder.TargetRegister.Result, 0); if (!factory.PreinitializationManager.HasLazyStaticConstructor(target)) { + encoder.EmitLD(encoder.TargetRegister.Result, encoder.TargetRegister.Result, 0); encoder.EmitRET(); } else { - // We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. - encoder.EmitMOV(encoder.TargetRegister.Arg2, factory.TypeNonGCStaticsSymbol(target)); - encoder.EmitADDI(encoder.TargetRegister.Arg2, encoder.TargetRegister.Arg2, -NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); - encoder.EmitLD(encoder.TargetRegister.Arg3, encoder.TargetRegister.Arg2, 0); - encoder.EmitRETIfZero(encoder.TargetRegister.Arg3); - - encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); - encoder.EmitMOV(encoder.TargetRegister.Arg0, encoder.TargetRegister.Arg2); - + // The fast path check is not necessary. It is always expanded by RyuJIT. + encoder.EmitLD(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result, 0); + encoder.EmitMOV(encoder.TargetRegister.Arg0, factory.TypeNonGCStaticsSymbol(target)); + encoder.EmitADDI(encoder.TargetRegister.Arg0, encoder.TargetRegister.Arg0, -NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnGCStaticBase)); } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs index 4b1b2d247f44d1..a63deaf80c1dd3 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs @@ -22,22 +22,20 @@ protected override void EmitCode(NodeFactory factory, ref X64Emitter encoder, bo { MetadataType target = (MetadataType)Target; bool hasLazyStaticConstructor = factory.PreinitializationManager.HasLazyStaticConstructor(target); - encoder.EmitLEAQ(encoder.TargetRegister.Result, factory.TypeNonGCStaticsSymbol(target)); if (!hasLazyStaticConstructor) { + encoder.EmitLEAQ(encoder.TargetRegister.Result, factory.TypeNonGCStaticsSymbol(target)); encoder.EmitRET(); } else { - // We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. - encoder.EmitLEAQ(encoder.TargetRegister.Arg0, factory.TypeNonGCStaticsSymbol(target), -NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); + // The fast path check is not necessary. It is always expanded by RyuJIT. + encoder.EmitLEAQ(encoder.TargetRegister.Arg1, factory.TypeNonGCStaticsSymbol(target)); - AddrMode initialized = new AddrMode(encoder.TargetRegister.Arg0, null, 0, 0, AddrModeSize.Int64); - encoder.EmitCMP(ref initialized, 0); - encoder.EmitRETIfEqual(); + AddrMode loadCctor = new AddrMode(encoder.TargetRegister.Arg1, null, -NonGCStaticsNode.GetClassConstructorContextSize(factory.Target), 0, AddrModeSize.Int64); + encoder.EmitLEA(encoder.TargetRegister.Arg0, ref loadCctor); - encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnNonGCStaticBase)); } } @@ -89,24 +87,19 @@ protected override void EmitCode(NodeFactory factory, ref X64Emitter encoder, bo MetadataType target = (MetadataType)Target; encoder.EmitLEAQ(encoder.TargetRegister.Result, factory.TypeGCStaticsSymbol(target)); - AddrMode loadFromRax = new AddrMode(encoder.TargetRegister.Result, null, 0, 0, AddrModeSize.Int64); - encoder.EmitMOV(encoder.TargetRegister.Result, ref loadFromRax); if (!factory.PreinitializationManager.HasLazyStaticConstructor(target)) { + AddrMode loadFromRax = new AddrMode(encoder.TargetRegister.Result, null, 0, 0, AddrModeSize.Int64); + encoder.EmitMOV(encoder.TargetRegister.Result, ref loadFromRax); encoder.EmitRET(); } else { - // We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. + // The fast path check is not necessary. It is always expanded by RyuJIT. + AddrMode loadFromRax = new AddrMode(encoder.TargetRegister.Result, null, 0, 0, AddrModeSize.Int64); + encoder.EmitMOV(encoder.TargetRegister.Arg1, ref loadFromRax); encoder.EmitLEAQ(encoder.TargetRegister.Arg0, factory.TypeNonGCStaticsSymbol(target), -NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); - - AddrMode initialized = new AddrMode(encoder.TargetRegister.Arg0, null, 0, 0, AddrModeSize.Int64); - encoder.EmitCMP(ref initialized, 0); - encoder.EmitRETIfEqual(); - - encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); - encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnGCStaticBase)); } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X86/X86ReadyToRunHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X86/X86ReadyToRunHelperNode.cs index 239bfd338d9c3e..472f628a353393 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X86/X86ReadyToRunHelperNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X86/X86ReadyToRunHelperNode.cs @@ -23,22 +23,17 @@ protected override void EmitCode(NodeFactory factory, ref X86Emitter encoder, bo { MetadataType target = (MetadataType)Target; bool hasLazyStaticConstructor = factory.PreinitializationManager.HasLazyStaticConstructor(target); - encoder.EmitMOV(encoder.TargetRegister.Result, factory.TypeNonGCStaticsSymbol(target)); if (!hasLazyStaticConstructor) { + encoder.EmitMOV(encoder.TargetRegister.Result, factory.TypeNonGCStaticsSymbol(target)); encoder.EmitRET(); } else { - // We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. + // The fast path check is not necessary. It is always expanded by RyuJIT. + encoder.EmitMOV(encoder.TargetRegister.Arg1, factory.TypeNonGCStaticsSymbol(target)); encoder.EmitMOV(encoder.TargetRegister.Arg0, factory.TypeNonGCStaticsSymbol(target), -NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); - - AddrMode initialized = new AddrMode(encoder.TargetRegister.Arg0, null, 0, 0, AddrModeSize.Int32); - encoder.EmitCMP(ref initialized, 0); - encoder.EmitRETIfEqual(); - - encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnNonGCStaticBase)); } } @@ -95,23 +90,19 @@ protected override void EmitCode(NodeFactory factory, ref X86Emitter encoder, bo MetadataType target = (MetadataType)Target; bool hasLazyStaticConstructor = factory.PreinitializationManager.HasLazyStaticConstructor(target); encoder.EmitMOV(encoder.TargetRegister.Result, factory.TypeGCStaticsSymbol(target)); - AddrMode loadFromEax = new AddrMode(encoder.TargetRegister.Result, null, 0, 0, AddrModeSize.Int32); - encoder.EmitMOV(encoder.TargetRegister.Result, ref loadFromEax); if (!hasLazyStaticConstructor) { + AddrMode loadFromEax = new AddrMode(encoder.TargetRegister.Result, null, 0, 0, AddrModeSize.Int32); + encoder.EmitMOV(encoder.TargetRegister.Result, ref loadFromEax); encoder.EmitRET(); } else { - // We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. + // The fast path check is not necessary. It is always expanded by RyuJIT. + AddrMode loadFromEax = new AddrMode(encoder.TargetRegister.Result, null, 0, 0, AddrModeSize.Int32); + encoder.EmitMOV(encoder.TargetRegister.Arg1, ref loadFromEax); encoder.EmitMOV(encoder.TargetRegister.Arg0, factory.TypeNonGCStaticsSymbol(target), -NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); - - AddrMode initialized = new AddrMode(encoder.TargetRegister.Arg0, null, 0, 0, AddrModeSize.Int32); - encoder.EmitCMP(ref initialized, 0); - encoder.EmitRETIfEqual(); - - encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnGCStaticBase)); } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs index 11b3bf944d83a8..53a722cdb663f0 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs @@ -41,7 +41,7 @@ namespace ILCompiler /// public abstract class MetadataManager : ICompilationRootProvider { - internal const int MetadataOffsetMask = 0xFFFFFF; + internal const int MetadataOffsetMask = 0x1FFFFFF; protected readonly MetadataManagerOptions _options; @@ -776,10 +776,10 @@ protected void ComputeMetadata( metadataBlob = ms.ToArray(); - const int MaxAllowedMetadataOffset = 0xFFFFFF; + const int MaxAllowedMetadataOffset = 0x1FFFFFF; if (metadataBlob.Length > MaxAllowedMetadataOffset) { - // Offset portion of metadata handles is limited to 16 MB. + // Offset portion of metadata handles is limited to 32 MB. throw new InvalidOperationException($"Metadata blob exceeded the addressing range (allowed: {MaxAllowedMetadataOffset}, actual: {metadataBlob.Length})"); } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/SubstitutedILProvider.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/SubstitutedILProvider.cs index fd2442c4b6b41c..4450c53ed99584 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/SubstitutedILProvider.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/SubstitutedILProvider.cs @@ -672,6 +672,7 @@ private bool TryGetMethodConstantValue(MethodDesc method, out int constant, int if (returnType is < TypeFlags.Boolean or > TypeFlags.UInt32 || method.IsIntrinsic || method.IsNoInlining + || method.IsNoOptimization || _nestedILProvider.GetMethodIL(method) is not MethodIL methodIL) { constant = 0; diff --git a/src/coreclr/tools/aot/ILCompiler.MetadataTransform/Internal/Metadata/NativeFormat/Writer/MdBinaryWriter.cs b/src/coreclr/tools/aot/ILCompiler.MetadataTransform/Internal/Metadata/NativeFormat/Writer/MdBinaryWriter.cs index ea6a7622e6b76a..fc4502c0f49fe1 100644 --- a/src/coreclr/tools/aot/ILCompiler.MetadataTransform/Internal/Metadata/NativeFormat/Writer/MdBinaryWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.MetadataTransform/Internal/Metadata/NativeFormat/Writer/MdBinaryWriter.cs @@ -77,7 +77,7 @@ public static void Write(this NativeWriter writer, double value) public static void Write(this NativeWriter writer, MetadataRecord record) { if (record != null) - writer.WriteUnsigned((uint)record.HandleType | (uint)(record.HandleOffset << 8)); + writer.WriteUnsigned((uint)record.HandleType | (uint)(record.HandleOffset << 7)); else writer.WriteUnsigned(0); } diff --git a/src/coreclr/tools/aot/ILCompiler.MetadataTransform/Internal/Metadata/NativeFormat/Writer/NativeMetadataWriter.cs b/src/coreclr/tools/aot/ILCompiler.MetadataTransform/Internal/Metadata/NativeFormat/Writer/NativeMetadataWriter.cs index b05c1c6ed3a73b..f4df3c7e207172 100644 --- a/src/coreclr/tools/aot/ILCompiler.MetadataTransform/Internal/Metadata/NativeFormat/Writer/NativeMetadataWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.MetadataTransform/Internal/Metadata/NativeFormat/Writer/NativeMetadataWriter.cs @@ -519,7 +519,7 @@ internal int HandleOffset { get { - return _offset & 0x00FFFFFF; + return _offset & 0x01FFFFFF; } } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs index 66c7767dab8a81..e1803a3f5d7931 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs @@ -82,8 +82,9 @@ public bool CanInline(MethodDesc caller, MethodDesc callee) return false; } - if (callee.IsNoInlining) + if (callee.IsNoInlining || callee.IsNoOptimization) { + // NoOptimization implies NoInlining return false; } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs index 500863a90d9347..7cc3343a56d416 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs @@ -1299,10 +1299,12 @@ private bool canTailCall(CORINFO_METHOD_STRUCT_* callerHnd, CORINFO_METHOD_STRUC return false; } - // Do not tailcall from methods that are marked as noinline (people often use no-inline + // Do not tailcall from methods that are marked as NoInlining (people often use no-inline // to mean "I want to always see this method in stacktrace") if (caller.IsNoInlining) { + // NOTE: we don't have to handle NoOptimization here, because JIT is not expected + // to emit fast tail calls if optimizations are disabled. return false; } diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index fab907801e723b..b4933c28b25afc 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -833,8 +833,11 @@ private bool canTailCall(CORINFO_METHOD_STRUCT_* callerHnd, CORINFO_METHOD_STRUC if (caller.IsNoInlining) { - // Do not tailcall from methods that are marked as noinline (people often use no-inline + // Do not tailcall from methods that are marked as NoInlining (people often use no-inline // to mean "I want to always see this method in stacktrace") + // + // NOTE: we don't have to handle NoOptimization here, because JIT is not expected + // to emit fast tail calls if optimizations are disabled. result = false; } } diff --git a/src/coreclr/vm/CMakeLists.txt b/src/coreclr/vm/CMakeLists.txt index 9d73e3783e1aba..c6edfe5a6ff526 100644 --- a/src/coreclr/vm/CMakeLists.txt +++ b/src/coreclr/vm/CMakeLists.txt @@ -855,12 +855,6 @@ elseif(CLR_CMAKE_TARGET_ARCH_RISCV64) ) endif() -if(CLR_CMAKE_HOST_UNIX) - list(APPEND VM_SOURCES_WKS_ARCH - ${ARCH_SOURCES_DIR}/unixstubs.cpp - ) -endif(CLR_CMAKE_HOST_UNIX) - set(VM_SOURCES_DAC_ARCH exceptionhandling.cpp ) diff --git a/src/coreclr/vm/amd64/AsmHelpers.asm b/src/coreclr/vm/amd64/AsmHelpers.asm index 18435be1b13727..95714fd0757321 100644 --- a/src/coreclr/vm/amd64/AsmHelpers.asm +++ b/src/coreclr/vm/amd64/AsmHelpers.asm @@ -12,6 +12,8 @@ extern ProfileTailcall:proc extern OnHijackWorker:proc extern JIT_RareDisableHelperWorker:proc +extern g_pPollGC:QWORD +extern g_TrapReturningThreads:DWORD ; EXTERN_C int __fastcall HelperMethodFrameRestoreState( ; INDEBUG_COMMA(HelperMethodFrame *pFrame) @@ -447,5 +449,13 @@ NESTED_END OnCallCountThresholdReachedStub, _TEXT endif ; FEATURE_TIERED_COMPILATION - end +LEAF_ENTRY JIT_PollGC, _TEXT + cmp [g_TrapReturningThreads], 0 + jnz JIT_PollGCRarePath + ret +JIT_PollGCRarePath: + mov rax, g_pPollGC + TAILJMP_RAX +LEAF_END JIT_PollGC, _TEXT + end \ No newline at end of file diff --git a/src/coreclr/vm/amd64/asmhelpers.S b/src/coreclr/vm/amd64/asmhelpers.S index 8d83938246a2c9..6bce2d2f2d3436 100644 --- a/src/coreclr/vm/amd64/asmhelpers.S +++ b/src/coreclr/vm/amd64/asmhelpers.S @@ -44,6 +44,14 @@ # # *********************************************************** +# EXTERN_C void JIT_ProfilerEnterLeaveTailcallStub(UINT_PTR ProfilerHandle); +# +# +# +LEAF_ENTRY JIT_ProfilerEnterLeaveTailcallStub, _TEXT + ret +LEAF_END JIT_ProfilerEnterLeaveTailcallStub, _TEXT + # EXTERN_C void ProfileEnterNaked(FunctionIDOrClientID functionIDOrClientID, size_t profiledRsp); # # @@ -311,3 +319,14 @@ LEAF_ENTRY GetTlsIndexObjectDescOffset, _TEXT int 3 LEAF_END GetTlsIndexObjectDescOffset, _TEXT #endif + +LEAF_ENTRY JIT_PollGC, _TEXT + PREPARE_EXTERNAL_VAR g_TrapReturningThreads, rax + cmp dword ptr [rax], 0 + jnz LOCAL_LABEL(JIT_PollGCRarePath) + ret +LOCAL_LABEL(JIT_PollGCRarePath): + PREPARE_EXTERNAL_VAR g_pPollGC, rax + mov rax, [rax] + jmp rax +LEAF_END JIT_PollGC, _TEXT diff --git a/src/coreclr/vm/amd64/excepamd64.cpp b/src/coreclr/vm/amd64/excepamd64.cpp index 282a84c7d788db..c679a67b996fc2 100644 --- a/src/coreclr/vm/amd64/excepamd64.cpp +++ b/src/coreclr/vm/amd64/excepamd64.cpp @@ -48,12 +48,14 @@ inline PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrameWorker(UINT_PTR establi return *ppContext; } +#ifdef TARGET_WINDOWS PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(DISPATCHER_CONTEXT * pDispatcherContext) { LIMITED_METHOD_DAC_CONTRACT; return GetCONTEXTFromRedirectedStubStackFrameWorker(pDispatcherContext->EstablisherFrame); } +#endif // TARGET_WINDOWS PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(CONTEXT * pContext) { @@ -63,17 +65,14 @@ PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(CONTEXT * pContext) } #if !defined(DACCESS_COMPILE) - +#ifdef TARGET_WINDOWS FaultingExceptionFrame *GetFrameFromRedirectedStubStackFrame (DISPATCHER_CONTEXT *pDispatcherContext) { LIMITED_METHOD_CONTRACT; return (FaultingExceptionFrame*)(pDispatcherContext->EstablisherFrame + THROWSTUB_ESTABLISHER_OFFSET_FaultingExceptionFrame); } - -#endif // !DACCESS_COMPILE - -#if !defined(DACCESS_COMPILE) +#endif // TARGET_WINDOWS #define AMD64_SIZE64_PREFIX 0x48 #define AMD64_ADD_IMM8_OP 0x83 diff --git a/src/coreclr/vm/amd64/excepcpu.h b/src/coreclr/vm/amd64/excepcpu.h index 07a7d041dc9ce9..3403f99a5e8d91 100644 --- a/src/coreclr/vm/amd64/excepcpu.h +++ b/src/coreclr/vm/amd64/excepcpu.h @@ -40,14 +40,18 @@ EXTERN_C void RedirectForThrowControl(); // Retrieves the redirected CONTEXT* from the stack frame of one of the // RedirectedHandledJITCaseForXXX_Stub's. // +#ifdef TARGET_WINDOWS PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(DISPATCHER_CONTEXT * pDispatcherContext); +#endif // TARGET_WINDOWS PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(CONTEXT * pContext); +#ifdef TARGET_WINDOWS // // Retrieves the FaultingExceptionFrame* from the stack frame of // RedirectForThrowControl. // FaultingExceptionFrame *GetFrameFromRedirectedStubStackFrame (DISPATCHER_CONTEXT *pDispatcherContext); +#endif // TARGET_WINDOWS // // Functions that wrap RtlVirtualUnwind to make sure that in the AMD64 case all the diff --git a/src/coreclr/vm/amd64/unixstubs.cpp b/src/coreclr/vm/amd64/unixstubs.cpp deleted file mode 100644 index 0edb1aef92cc3e..00000000000000 --- a/src/coreclr/vm/amd64/unixstubs.cpp +++ /dev/null @@ -1,11 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#include "common.h" - -extern "C" -{ - void STDMETHODCALLTYPE JIT_ProfilerEnterLeaveTailcallStub(UINT_PTR ProfilerHandle) - { - } -}; diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index a3fb8bc3e9a4e0..7762d755052033 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -1006,6 +1006,8 @@ extern "C" PCODE g_pGetGCStaticBase; PCODE g_pGetGCStaticBase; extern "C" PCODE g_pGetNonGCStaticBase; PCODE g_pGetNonGCStaticBase; +extern "C" PCODE g_pPollGC; +PCODE g_pPollGC; void SystemDomain::LoadBaseSystemClasses() { @@ -1144,6 +1146,7 @@ void SystemDomain::LoadBaseSystemClasses() g_pGetGCStaticBase = CoreLibBinder::GetMethod(METHOD__STATICSHELPERS__GET_GC_STATIC)->GetMultiCallableAddrOfCode(); g_pGetNonGCStaticBase = CoreLibBinder::GetMethod(METHOD__STATICSHELPERS__GET_NONGC_STATIC)->GetMultiCallableAddrOfCode(); + g_pPollGC = CoreLibBinder::GetMethod(METHOD__THREAD__POLLGC)->GetMultiCallableAddrOfCode(); #ifdef PROFILING_SUPPORTED // Note that g_profControlBlock.fBaseSystemClassesLoaded must be set to TRUE only after @@ -1287,6 +1290,8 @@ bool SystemDomain::IsReflectionInvocationMethod(MethodDesc* pMeth) CLASS__DELEGATE, CLASS__MULTICAST_DELEGATE, CLASS__METHODBASEINVOKER, + CLASS__INITHELPERS, + CLASS__STATICSHELPERS, }; static bool fInited = false; diff --git a/src/coreclr/vm/arm/asmhelpers.S b/src/coreclr/vm/arm/asmhelpers.S index b970aaf28f07c8..5017a582f3ab8c 100644 --- a/src/coreclr/vm/arm/asmhelpers.S +++ b/src/coreclr/vm/arm/asmhelpers.S @@ -914,3 +914,26 @@ ProbeLoop: NESTED_END OnCallCountThresholdReachedStub, _TEXT #endif // FEATURE_TIERED_COMPILATION + + LEAF_ENTRY JIT_PollGC, _TEXT +#if defined(__clang__) + ldr r2, =g_TrapReturningThreads-(1f+4) +1: + add r2, pc +#else + ldr r2, =g_TrapReturningThreads +#endif + ldr r2, [r2] + cbnz r2, LOCAL_LABEL(JIT_PollGCRarePath) + bx lr +LOCAL_LABEL(JIT_PollGCRarePath): +#if defined(__clang__) + ldr r2, =g_pPollGC-(1f+4) +1: + add r2, pc +#else + ldr r2, =g_pPollGC +#endif + ldr r2, [r2] + EPILOG_BRANCH_REG r2 + LEAF_END JIT_PollGC, _TEXT diff --git a/src/coreclr/vm/arm/exceparm.cpp b/src/coreclr/vm/arm/exceparm.cpp index 517c3c774cfb99..f9ce191fa3e36f 100644 --- a/src/coreclr/vm/arm/exceparm.cpp +++ b/src/coreclr/vm/arm/exceparm.cpp @@ -7,15 +7,6 @@ #include "asmconstants.h" #include "virtualcallstub.h" -PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_DISPATCHER_CONTEXT * pDispatcherContext) -{ - LIMITED_METHOD_DAC_CONTRACT; - - UINT_PTR stackSlot = pDispatcherContext->EstablisherFrame + REDIRECTSTUB_SP_OFFSET_CONTEXT; - PTR_PTR_CONTEXT ppContext = dac_cast((TADDR)stackSlot); - return *ppContext; -} - PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_CONTEXT * pContext) { LIMITED_METHOD_DAC_CONTRACT; @@ -27,32 +18,6 @@ PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_CONTEXT * pContext) #if !defined(DACCESS_COMPILE) -// The next two functions help retrieve data kept relative to FaultingExceptionFrame that is setup -// for handling async exceptions (e.g. AV, NullRef, ThreadAbort, etc). -// -// FEF (and related data) is available relative to R4 - the thing to be kept in mind is that the -// DispatcherContext->ContextRecord: -// -// 1) represents the caller context in the first pass. -// 2) represents the current context in the second pass. -// -// Since R4 is a non-volatile register, this works for us since we setup the value of R4 -// in the redirection helpers (e.g. RedirectForThreadAbort) but do not -// change it in their respective callee functions (e.g. RedirectForThreadAbort2) -// that have the personality routines associated with them (which perform the collided unwind and also -// invoke the two functions below). -// -// Thus, when our personality routine gets called in either passes, DC->ContextRecord->R4 will -// have the same value. - -// Returns the pointer to the FEF -FaultingExceptionFrame *GetFrameFromRedirectedStubStackFrame (T_DISPATCHER_CONTEXT *pDispatcherContext) -{ - LIMITED_METHOD_CONTRACT; - - return (FaultingExceptionFrame*)((TADDR)pDispatcherContext->ContextRecord->R4); -} - // Returns TRUE if caller should resume execution. BOOL AdjustContextForVirtualStub( diff --git a/src/coreclr/vm/arm/excepcpu.h b/src/coreclr/vm/arm/excepcpu.h index f0c002e70930ce..7637cec21e76fd 100644 --- a/src/coreclr/vm/arm/excepcpu.h +++ b/src/coreclr/vm/arm/excepcpu.h @@ -26,15 +26,8 @@ class FaultingExceptionFrame; // Retrieves the redirected CONTEXT* from the stack frame of one of the // RedirectedHandledJITCaseForXXX_Stub's. // -PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_DISPATCHER_CONTEXT * pDispatcherContext); PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_CONTEXT * pContext); -// -// Retrieves the FaultingExceptionFrame* from the stack frame of -// RedirectForThrowControl. -// -FaultingExceptionFrame *GetFrameFromRedirectedStubStackFrame (T_DISPATCHER_CONTEXT *pDispatcherContext); - inline PCODE GetAdjustedCallAddress(PCODE returnAddress) { diff --git a/src/coreclr/vm/arm/unixstubs.cpp b/src/coreclr/vm/arm/unixstubs.cpp deleted file mode 100644 index 878d5b003686b6..00000000000000 --- a/src/coreclr/vm/arm/unixstubs.cpp +++ /dev/null @@ -1,4 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#include "common.h" diff --git a/src/coreclr/vm/arm64/asmhelpers.S b/src/coreclr/vm/arm64/asmhelpers.S index 65c1eaec4121ad..d40d210dfb03ad 100644 --- a/src/coreclr/vm/arm64/asmhelpers.S +++ b/src/coreclr/vm/arm64/asmhelpers.S @@ -806,3 +806,14 @@ LEAF_ENTRY GetTLSResolverAddress, _TEXT LEAF_END GetTLSResolverAddress, _TEXT // ------------------------------------------------------------------ #endif // !TARGET_OSX + +LEAF_ENTRY JIT_PollGC, _TEXT + PREPARE_EXTERNAL_VAR g_TrapReturningThreads, x9 + ldr w9, [x9] + cbnz w9, LOCAL_LABEL(JIT_PollGCRarePath) + ret +LOCAL_LABEL(JIT_PollGCRarePath): + PREPARE_EXTERNAL_VAR g_pPollGC, x9 + ldr x9, [x9] + br x9 +LEAF_END JIT_PollGC, _TEXT diff --git a/src/coreclr/vm/arm64/asmhelpers.asm b/src/coreclr/vm/arm64/asmhelpers.asm index eea1e98df75274..e240919a7395f0 100644 --- a/src/coreclr/vm/arm64/asmhelpers.asm +++ b/src/coreclr/vm/arm64/asmhelpers.asm @@ -39,6 +39,9 @@ IMPORT g_pGetGCStaticBase IMPORT g_pGetNonGCStaticBase + IMPORT g_pPollGC + IMPORT g_TrapReturningThreads + #ifdef WRITE_BARRIER_CHECK SETALIAS g_GCShadow, ?g_GCShadow@@3PEAEEA SETALIAS g_GCShadowEnd, ?g_GCShadowEnd@@3PEAEEA @@ -1179,6 +1182,17 @@ __HelperNakedFuncName SETS "$helper":CC:"Naked" #endif ; FEATURE_SPECIAL_USER_MODE_APC + LEAF_ENTRY JIT_PollGC + ldr x9, =g_TrapReturningThreads + ldr w9, [x9] + cbnz w9, JIT_PollGCRarePath + ret +JIT_PollGCRarePath + ldr x9, =g_pPollGC + ldr x9, [x9] + br x9 + LEAF_END + ; Must be at very end of file END diff --git a/src/coreclr/vm/arm64/excepcpu.h b/src/coreclr/vm/arm64/excepcpu.h index eb575235af8feb..acbd29b102e7b5 100644 --- a/src/coreclr/vm/arm64/excepcpu.h +++ b/src/coreclr/vm/arm64/excepcpu.h @@ -28,14 +28,18 @@ class FaultingExceptionFrame; // Retrieves the redirected CONTEXT* from the stack frame of one of the // RedirectedHandledJITCaseForXXX_Stub's. // +#ifdef TARGET_WINDOWS PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_DISPATCHER_CONTEXT * pDispatcherContext); +#endif // TARGET_WINDOWS PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_CONTEXT * pContext); +#ifdef TARGET_WINDOWS // // Retrieves the FaultingExceptionFrame* from the stack frame of -// RedirectForThrowControl. +// RedirectForThreadAbort. // FaultingExceptionFrame *GetFrameFromRedirectedStubStackFrame (T_DISPATCHER_CONTEXT *pDispatcherContext); +#endif // TARGET_WINDOWS inline PCODE GetAdjustedCallAddress(PCODE returnAddress) diff --git a/src/coreclr/vm/arm64/stubs.cpp b/src/coreclr/vm/arm64/stubs.cpp index 825d2e0e4fd811..6c7b02bab13e9e 100644 --- a/src/coreclr/vm/arm64/stubs.cpp +++ b/src/coreclr/vm/arm64/stubs.cpp @@ -859,11 +859,6 @@ void emitCOMStubCall (ComCallMethodDesc *pCOMMethodRX, ComCallMethodDesc *pCOMMe } #endif // FEATURE_COMINTEROP -void JIT_TailCall() -{ - _ASSERTE(!"ARM64:NYI"); -} - #if !defined(DACCESS_COMPILE) EXTERN_C void JIT_UpdateWriteBarrierState(bool skipEphemeralCheck, size_t writeableOffset); @@ -917,6 +912,7 @@ void InitJITHelpers1() void UpdateWriteBarrierState(bool) {} #endif // !defined(DACCESS_COMPILE) +#ifdef TARGET_WINDOWS PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_DISPATCHER_CONTEXT * pDispatcherContext) { LIMITED_METHOD_DAC_CONTRACT; @@ -925,6 +921,7 @@ PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_DISPATCHER_CONTEXT * pDispa PTR_PTR_CONTEXT ppContext = dac_cast((TADDR)stackSlot); return *ppContext; } +#endif // TARGET_WINDOWS PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_CONTEXT * pContext) { @@ -936,13 +933,14 @@ PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_CONTEXT * pContext) } #if !defined(DACCESS_COMPILE) +#ifdef TARGET_WINDOWS FaultingExceptionFrame *GetFrameFromRedirectedStubStackFrame (DISPATCHER_CONTEXT *pDispatcherContext) { LIMITED_METHOD_CONTRACT; return (FaultingExceptionFrame*)((TADDR)pDispatcherContext->ContextRecord->X19); } - +#endif // TARGET_WINDOWS BOOL AdjustContextForVirtualStub( diff --git a/src/coreclr/vm/arm64/unixstubs.cpp b/src/coreclr/vm/arm64/unixstubs.cpp deleted file mode 100644 index 878d5b003686b6..00000000000000 --- a/src/coreclr/vm/arm64/unixstubs.cpp +++ /dev/null @@ -1,4 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#include "common.h" diff --git a/src/coreclr/vm/assembly.cpp b/src/coreclr/vm/assembly.cpp index e6be6728778d52..e124702167889b 100644 --- a/src/coreclr/vm/assembly.cpp +++ b/src/coreclr/vm/assembly.cpp @@ -2418,7 +2418,7 @@ HRESULT Assembly::GetDebuggingCustomAttributes(DWORD *pdwFlags) ULONG size; BYTE *blob; IMDInternalImport* mdImport = GetPEAssembly()->GetMDImport(); - mdAssembly asTK = TokenFromRid(mdtAssembly, 1); + mdAssembly asTK = TokenFromRid(1, mdtAssembly); HRESULT hr = mdImport->GetCustomAttributeByName(asTK, DEBUGGABLE_ATTRIBUTE_TYPE, diff --git a/src/coreclr/vm/clsload.cpp b/src/coreclr/vm/clsload.cpp index 2acc0ffa4dc2c8..7862eef313478f 100644 --- a/src/coreclr/vm/clsload.cpp +++ b/src/coreclr/vm/clsload.cpp @@ -3461,6 +3461,12 @@ VOID ClassLoader::AddAvailableClassHaveLock( if (SUCCEEDED(pMDImport->GetNestedClassProps(classdef, &enclosing))) { // nested type + if (enclosing == COR_GLOBAL_PARENT_TOKEN) + { + // Types nested in the class can't be found by lookup. + return; + } + COUNT_T classEntryIndex = RidFromToken(enclosing) - 1; _ASSERTE(RidFromToken(enclosing) < RidFromToken(classdef)); if (classEntries->GetCount() > classEntryIndex) diff --git a/src/coreclr/vm/comsynchronizable.cpp b/src/coreclr/vm/comsynchronizable.cpp index e71fe3908786bf..2e4170a81ef838 100644 --- a/src/coreclr/vm/comsynchronizable.cpp +++ b/src/coreclr/vm/comsynchronizable.cpp @@ -848,6 +848,12 @@ extern "C" void QCALLTYPE ThreadNative_DisableComObjectEagerCleanup(QCall::Threa } #endif //FEATURE_COMINTEROP +extern "C" void QCALLTYPE ThreadNative_PollGC() +{ + // This is an intentional no-op. The call is made to ensure that the thread goes through a GC transition + // and is thus marked as a GC safe point, and that the p/invoke rare path will kick in +} + extern "C" BOOL QCALLTYPE ThreadNative_YieldThread() { QCALL_CONTRACT; diff --git a/src/coreclr/vm/comsynchronizable.h b/src/coreclr/vm/comsynchronizable.h index c06af82d0f2967..9b17981e16e7a3 100644 --- a/src/coreclr/vm/comsynchronizable.h +++ b/src/coreclr/vm/comsynchronizable.h @@ -50,6 +50,7 @@ extern "C" BOOL QCALLTYPE ThreadNative_GetIsBackground(QCall::ThreadHandle threa extern "C" void QCALLTYPE ThreadNative_SetIsBackground(QCall::ThreadHandle thread, BOOL value); extern "C" void QCALLTYPE ThreadNative_InformThreadNameChange(QCall::ThreadHandle thread, LPCWSTR name, INT32 len); extern "C" BOOL QCALLTYPE ThreadNative_YieldThread(); +extern "C" void QCALLTYPE ThreadNative_PollGC(); extern "C" UINT64 QCALLTYPE ThreadNative_GetCurrentOSThreadId(); extern "C" void QCALLTYPE ThreadNative_Initialize(QCall::ObjectHandleOnStack t); extern "C" INT32 QCALLTYPE ThreadNative_GetThreadState(QCall::ThreadHandle thread); diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index e8eaf0ca12c224..e483a08eb1d670 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -867,6 +867,8 @@ DEFINE_CLASS(DIRECTONTHREADLOCALDATA, Threading, Thread+DirectOnThreadLocalData) DEFINE_CLASS(THREAD, Threading, Thread) DEFINE_METHOD(THREAD, START_CALLBACK, StartCallback, IM_RetVoid) +DEFINE_METHOD(THREAD, POLLGC, PollGC, NoSig) + #ifdef FEATURE_OBJCMARSHAL DEFINE_CLASS(AUTORELEASEPOOL, Threading, AutoreleasePool) DEFINE_METHOD(AUTORELEASEPOOL, CREATEAUTORELEASEPOOL, CreateAutoreleasePool, SM_RetVoid) diff --git a/src/coreclr/vm/exceptionhandling.cpp b/src/coreclr/vm/exceptionhandling.cpp index 18abf22d51a48c..eedc2b5c39c195 100644 --- a/src/coreclr/vm/exceptionhandling.cpp +++ b/src/coreclr/vm/exceptionhandling.cpp @@ -5867,7 +5867,7 @@ void TrackerAllocator::FreeTrackerMemory(ExceptionTracker* pTracker) InterlockedExchangeT(&(pTracker->m_pThread), NULL); } -#ifndef TARGET_UNIX +#ifdef TARGET_WINDOWS // This is Windows specific implementation as it is based upon the notion of collided unwind that is specific // to Windows 64bit. // @@ -5890,8 +5890,8 @@ void FixupDispatcherContext(DISPATCHER_CONTEXT* pDispatcherContext, CONTEXT* pCo } pDispatcherContext->ControlPc = (UINT_PTR) GetIP(pDispatcherContext->ContextRecord); - -#if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) + +#if defined(TARGET_ARM64) // Since this routine is used to fixup contexts for async exceptions, // clear the CONTEXT_UNWOUND_TO_CALL flag since, semantically, frames // where such exceptions have happened do not have callsites. On a similar @@ -5911,21 +5911,10 @@ void FixupDispatcherContext(DISPATCHER_CONTEXT* pDispatcherContext, CONTEXT* pCo // be fixing it at their end, in their implementation of collided unwind. pDispatcherContext->ContextRecord->ContextFlags &= ~CONTEXT_DEBUG_REGISTERS; -#ifdef TARGET_ARM - // But keep the architecture flag set (its part of CONTEXT_DEBUG_REGISTERS) - pDispatcherContext->ContextRecord->ContextFlags |= CONTEXT_ARM; -#elif defined(TARGET_LOONGARCH64) - // But keep the architecture flag set (its part of CONTEXT_DEBUG_REGISTERS) - pDispatcherContext->ContextRecord->ContextFlags |= CONTEXT_LOONGARCH64; -#elif defined(TARGET_RISCV64) - // But keep the architecture flag set (its part of CONTEXT_DEBUG_REGISTERS) - pDispatcherContext->ContextRecord->ContextFlags |= CONTEXT_RISCV64; -#else // TARGET_ARM64 // But keep the architecture flag set (its part of CONTEXT_DEBUG_REGISTERS) pDispatcherContext->ContextRecord->ContextFlags |= CONTEXT_ARM64; -#endif // TARGET_ARM -#endif // TARGET_ARM || TARGET_ARM64 || TARGET_LOONGARCH64 || TARGET_RISCV64 +#endif // TARGET_ARM64 INDEBUG(pDispatcherContext->FunctionEntry = (PT_RUNTIME_FUNCTION)INVALID_POINTER_CD); INDEBUG(pDispatcherContext->ImageBase = INVALID_POINTER_CD); @@ -6101,7 +6090,7 @@ HijackHandler(IN PEXCEPTION_RECORD pExceptionRecord, } -#endif // !TARGET_UNIX +#endif // !TARGET_WINDOWS #ifdef _DEBUG // IsSafeToUnwindFrameChain: diff --git a/src/coreclr/vm/frames.h b/src/coreclr/vm/frames.h index 46b435f94b8d94..f4a528d6f93962 100644 --- a/src/coreclr/vm/frames.h +++ b/src/coreclr/vm/frames.h @@ -720,7 +720,6 @@ class Frame : public FrameBase friend class TailCallFrame; friend class AppDomain; friend VOID RealCOMPlusThrow(OBJECTREF); - #ifdef _DEBUG friend LONG WINAPI CLRVectoredExceptionHandlerShim(PEXCEPTION_POINTERS pExceptionInfo); #endif diff --git a/src/coreclr/vm/i386/PInvokeStubs.asm b/src/coreclr/vm/i386/PInvokeStubs.asm index 6f9ec4526a7ead..a0bc18d616bce1 100644 --- a/src/coreclr/vm/i386/PInvokeStubs.asm +++ b/src/coreclr/vm/i386/PInvokeStubs.asm @@ -24,7 +24,7 @@ extern _s_gsCookie:DWORD extern ??_7InlinedCallFrame@@6B@:DWORD extern _g_TrapReturningThreads:DWORD -extern @JIT_PInvokeEndRarePath@0:proc +extern _JIT_PInvokeEndRarePath@0:proc .686P .XMM @@ -103,7 +103,7 @@ _JIT_PInvokeEnd@4 PROC public ret RarePath: - jmp @JIT_PInvokeEndRarePath@0 + jmp _JIT_PInvokeEndRarePath@0 _JIT_PInvokeEnd@4 ENDP diff --git a/src/coreclr/vm/i386/excepcpu.h b/src/coreclr/vm/i386/excepcpu.h index 09f0fa2fc8b725..779b6d61841a65 100644 --- a/src/coreclr/vm/i386/excepcpu.h +++ b/src/coreclr/vm/i386/excepcpu.h @@ -89,9 +89,6 @@ EXTERN_C LPVOID STDCALL COMPlusEndCatch(LPVOID ebp, DWORD ebx, DWORD edi, DWORD // RedirectedHandledJITCaseForXXX_Stub's. // PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(CONTEXT * pContext); -#ifdef FEATURE_EH_FUNCLETS -PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_DISPATCHER_CONTEXT * pDispatcherContext); -#endif // FEATURE_EH_FUNCLETS // Determine the address of the instruction that made the current call. inline diff --git a/src/coreclr/vm/i386/jithelp.S b/src/coreclr/vm/i386/jithelp.S index d0275252027814..71df3fa4610841 100644 --- a/src/coreclr/vm/i386/jithelp.S +++ b/src/coreclr/vm/i386/jithelp.S @@ -692,3 +692,13 @@ LEAF_END JIT_PatchedWriteBarrierGroup_End, _TEXT LEAF_ENTRY JIT_PatchedCodeLast, _TEXT ret LEAF_END JIT_PatchedCodeLast, _TEXT + +LEAF_ENTRY JIT_PollGC, _TEXT + PREPARE_EXTERNAL_VAR g_TrapReturningThreads, eax + cmp DWORD PTR [eax], 0 + jnz LOCAL_LABEL(JIT_PollGCRarePath) + ret +LOCAL_LABEL(JIT_PollGCRarePath): + PREPARE_EXTERNAL_VAR g_pPollGC, eax + jmp [eax] +LEAF_END JIT_PollGC, _TEXT diff --git a/src/coreclr/vm/i386/jithelp.asm b/src/coreclr/vm/i386/jithelp.asm index 536f55e4f5809a..54fce3385044c9 100644 --- a/src/coreclr/vm/i386/jithelp.asm +++ b/src/coreclr/vm/i386/jithelp.asm @@ -44,6 +44,9 @@ JIT_TailCallVSDLeave TEXTEQU <_JIT_TailCallVSDLeave@0> JIT_TailCallHelper TEXTEQU <_JIT_TailCallHelper@4> JIT_TailCallReturnFromVSD TEXTEQU <_JIT_TailCallReturnFromVSD@0> +g_pPollGC TEXTEQU <_g_pPollGC> +g_TrapReturningThreads TEXTEQU <_g_TrapReturningThreads> + EXTERN g_ephemeral_low:DWORD EXTERN g_ephemeral_high:DWORD EXTERN g_lowest_address:DWORD @@ -59,6 +62,10 @@ EXTERN _g_TailCallFrameVptr:DWORD EXTERN @JIT_FailFast@0:PROC EXTERN _s_gsCookie:DWORD +EXTERN g_pPollGC:DWORD +EXTERN g_TrapReturningThreads:DWORD + + ifdef WRITE_BARRIER_CHECK ; Those global variables are always defined, but should be 0 for Server GC g_GCShadow TEXTEQU @@ -1149,4 +1156,13 @@ _JIT_StackProbe_End@0 PROC ret _JIT_StackProbe_End@0 ENDP +@JIT_PollGC@0 PROC public + cmp [g_TrapReturningThreads], 0 + jnz JIT_PollGCRarePath + ret +JIT_PollGCRarePath: + mov eax, g_pPollGC + jmp eax +@JIT_PollGC@0 ENDP + end diff --git a/src/coreclr/vm/i386/unixstubs.cpp b/src/coreclr/vm/i386/unixstubs.cpp deleted file mode 100644 index eb6844e1b03825..00000000000000 --- a/src/coreclr/vm/i386/unixstubs.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#include "common.h" - -EXTERN_C VOID JIT_TailCall() -{ - PORTABILITY_ASSERT("JIT_TailCall"); -} - -EXTERN_C VOID JIT_TailCallReturnFromVSD() -{ - PORTABILITY_ASSERT("JIT_TailCallReturnFromVSD"); -} - -EXTERN_C VOID JIT_TailCallVSDLeave() -{ - PORTABILITY_ASSERT("JIT_TailCallVSDLeave"); -} - -EXTERN_C VOID JIT_TailCallLeave() -{ - PORTABILITY_ASSERT("JIT_TailCallLeave"); -} - -PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_DISPATCHER_CONTEXT * pDispatcherContext) -{ - PORTABILITY_ASSERT("GetCONTEXTFromRedirectedStubStackFrame"); - return NULL; -} diff --git a/src/coreclr/vm/i386/virtualcallstubcpu.hpp b/src/coreclr/vm/i386/virtualcallstubcpu.hpp index 34a9c4d86c0ed6..6da58594858d04 100644 --- a/src/coreclr/vm/i386/virtualcallstubcpu.hpp +++ b/src/coreclr/vm/i386/virtualcallstubcpu.hpp @@ -690,8 +690,10 @@ StubCallSite::StubCallSite(TADDR siteAddrForRegisterIndirect, PCODE returnAddr) } } +#ifndef UNIX_X86_ABI // the special return address for VSD tailcalls extern "C" void STDCALL JIT_TailCallReturnFromVSD(); +#endif // UNIX_X86_ABI PCODE StubCallSite::GetCallerAddress() { diff --git a/src/coreclr/vm/jithelpers.cpp b/src/coreclr/vm/jithelpers.cpp index e499579b040afa..eeac550b3c0979 100644 --- a/src/coreclr/vm/jithelpers.cpp +++ b/src/coreclr/vm/jithelpers.cpp @@ -2134,101 +2134,60 @@ HRESULT EEToProfInterfaceImpl::SetEnterLeaveFunctionHooksForJit(FunctionEnter3 * // //======================================================================== -/*************************************************************/ -// Slow helper to tailcall from the fast one -NOINLINE HCIMPL0(void, JIT_PollGC_Framed) -{ - BEGIN_PRESERVE_LAST_ERROR; - - FCALL_CONTRACT; - FC_GC_POLL_NOT_NEEDED(); - - HELPER_METHOD_FRAME_BEGIN_NOPOLL(); // Set up a frame -#ifdef _DEBUG - BOOL GCOnTransition = FALSE; - if (g_pConfig->FastGCStressLevel()) { - GCOnTransition = GC_ON_TRANSITIONS (FALSE); - } -#endif // _DEBUG - CommonTripThread(); // Indicate we are at a GC safe point -#ifdef _DEBUG - if (g_pConfig->FastGCStressLevel()) { - GC_ON_TRANSITIONS (GCOnTransition); - } -#endif // _DEBUG - HELPER_METHOD_FRAME_END(); - END_PRESERVE_LAST_ERROR; -} -HCIMPLEND - -HCIMPL0(VOID, JIT_PollGC) -{ - FCALL_CONTRACT; - - // As long as we can have GCPOLL_CALL polls, it would not hurt to check the trap flag. - if (!g_TrapReturningThreads) - return; - - // Does someone want this thread stopped? - if (!GetThread()->CatchAtSafePoint()) - return; - - // Tailcall to the slow helper - ENDFORBIDGC(); - HCCALL0(JIT_PollGC_Framed); -} -HCIMPLEND - - /*************************************************************/ // This helper is similar to JIT_RareDisableHelper, but has more operations // tailored to the post-pinvoke operations. -extern "C" FCDECL0(VOID, JIT_PInvokeEndRarePath); +extern "C" VOID JIT_PInvokeEndRarePath(); -HCIMPL0(void, JIT_PInvokeEndRarePath) +void JIT_PInvokeEndRarePath() { BEGIN_PRESERVE_LAST_ERROR; - FCALL_CONTRACT; - Thread *thread = GetThread(); - // We need to disable the implicit FORBID GC region that exists inside an FCALL - // in order to call RareDisablePreemptiveGC(). - FC_CAN_TRIGGER_GC(); + // We execute RareDisablePreemptiveGC manually before checking any abort conditions + // as that operation may run the allocator, etc, and we need to have handled any suspensions requested + // by the GC before we reach that point. thread->RareDisablePreemptiveGC(); - FC_CAN_TRIGGER_GC_END(); - FC_GC_POLL_NOT_NEEDED(); - - HELPER_METHOD_FRAME_BEGIN_NOPOLL(); // Set up a frame - thread->HandleThreadAbort(); - HELPER_METHOD_FRAME_END(); + if (thread->IsAbortRequested()) + { + // This function is called after a pinvoke finishes, in the rare case that either a GC + // or ThreadAbort is requested. This means that the pinvoke frame is still on the stack and + // enabled, but the thread has been marked as returning to cooperative mode. Thus we can + // use that frame to provide GC suspension safety, but we need to manually call EnablePreemptiveGC + // and DisablePreemptiveGC to put the function in a state where the BEGIN_QCALL/END_QCALL macros + // will work correctly. + thread->EnablePreemptiveGC(); + BEGIN_QCALL; + thread->HandleThreadAbort(); + END_QCALL; + thread->DisablePreemptiveGC(); + } thread->m_pFrame->Pop(thread); END_PRESERVE_LAST_ERROR; } -HCIMPLEND /*************************************************************/ // For an inlined N/Direct call (and possibly for other places that need this service) // we have noticed that the returning thread should trap for one reason or another. // ECall sets up the frame. -extern "C" FCDECL0(VOID, JIT_RareDisableHelper); +extern "C" VOID JIT_RareDisableHelper(); #if defined(TARGET_ARM) || defined(TARGET_AMD64) // The JIT expects this helper to preserve the return value on AMD64 and ARM. We should eventually // switch other platforms to the same convention since it produces smaller code. -extern "C" FCDECL0(VOID, JIT_RareDisableHelperWorker); +extern "C" VOID JIT_RareDisableHelperWorker(); -HCIMPL0(void, JIT_RareDisableHelperWorker) +void JIT_RareDisableHelperWorker() #else -HCIMPL0(void, JIT_RareDisableHelper) +void JIT_RareDisableHelper() #endif { - // We do this here (before we set up a frame), because the following scenario + // We do this here (before we enter the BEGIN_QCALL macro), because the following scenario // We are in the process of doing an inlined pinvoke. Since we are in preemtive // mode, the thread is allowed to continue. The thread continues and gets a context // switch just after it has cleared the preemptive mode bit but before it gets @@ -2248,25 +2207,29 @@ HCIMPL0(void, JIT_RareDisableHelper) BEGIN_PRESERVE_LAST_ERROR; - FCALL_CONTRACT; - Thread *thread = GetThread(); - - // We need to disable the implicit FORBID GC region that exists inside an FCALL - // in order to call RareDisablePreemptiveGC(). - FC_CAN_TRIGGER_GC(); + // We execute RareDisablePreemptiveGC manually before checking any abort conditions + // as that operation may run the allocator, etc, and we need to be have have handled any suspensions requested + // by the GC before we reach that point. thread->RareDisablePreemptiveGC(); - FC_CAN_TRIGGER_GC_END(); - FC_GC_POLL_NOT_NEEDED(); - - HELPER_METHOD_FRAME_BEGIN_NOPOLL(); // Set up a frame - thread->HandleThreadAbort(); - HELPER_METHOD_FRAME_END(); + if (thread->IsAbortRequested()) + { + // This function is called after a pinvoke finishes, in the rare case that either a GC + // or ThreadAbort is requested. This means that the pinvoke frame is still on the stack and + // enabled, but the thread has been marked as returning to cooperative mode. Thus we can + // use that frame to provide GC suspension safety, but we need to manually call EnablePreemptiveGC + // and DisablePreemptiveGC to put the function in a state where the BEGIN_QCALL/END_QCALL macros + // will work correctly. + thread->EnablePreemptiveGC(); + BEGIN_QCALL; + thread->HandleThreadAbort(); + END_QCALL; + thread->DisablePreemptiveGC(); + } END_PRESERVE_LAST_ERROR; } -HCIMPLEND FCIMPL0(INT32, JIT_GetCurrentManagedThreadId) { diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 0a5e03371994dc..3354a7ec0f2ab4 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -8200,7 +8200,7 @@ bool CEEInfo::canTailCall (CORINFO_METHOD_HANDLE hCaller, if (!pCaller->IsNoMetadata()) { - // Do not tailcall from methods that are marked as noinline (people often use no-inline + // Do not tailcall from methods that are marked as NoInlining (people often use no-inline // to mean "I want to always see this method in stacktrace") DWORD dwImplFlags = 0; IfFailThrow(pCaller->GetMDImport()->GetMethodImplProps(callerToken, NULL, &dwImplFlags)); @@ -8208,9 +8208,12 @@ bool CEEInfo::canTailCall (CORINFO_METHOD_HANDLE hCaller, if (IsMiNoInlining(dwImplFlags)) { result = false; - szFailReason = "Caller is marked as no inline"; + szFailReason = "Caller is marked as NoInlining"; goto exit; } + + // NOTE: we don't have to handle NoOptimization here, because JIT is not expected + // to emit fast tail calls if optimizations are disabled. } // Methods with StackCrawlMark depend on finding their caller on the stack. @@ -12613,8 +12616,8 @@ CorJitResult invokeCompileMethod(EEJitManager *jitMgr, flags.Set(CORJIT_FLAGS::CORJIT_FLAG_MIN_OPT); } - // Always emit frames for methods marked no-inline (see #define ETW_EBP_FRAMED in the JIT) - if (IsMiNoInlining(dwImplFlags)) + // Always emit frames for methods marked NoInlining or NoOptimization (see #define ETW_EBP_FRAMED in the JIT) + if (IsMiNoInlining(dwImplFlags) || IsMiNoOptimization(dwImplFlags)) { flags.Set(CORJIT_FLAGS::CORJIT_FLAG_FRAMED); } diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h index 2dd59db18807cb..1d20db72f5f244 100644 --- a/src/coreclr/vm/jitinterface.h +++ b/src/coreclr/vm/jitinterface.h @@ -109,6 +109,8 @@ BOOL LoadDynamicInfoEntry(Module *currentModule, // The portable helper is used if the platform does not provide optimized implementation. // +EXTERN_C FCDECL0(void, JIT_PollGC); + #ifndef JIT_MonEnter #define JIT_MonEnter JIT_MonEnter_Portable #endif @@ -352,24 +354,19 @@ extern "C" { #ifndef FEATURE_EH_FUNCLETS void STDCALL JIT_EndCatch(); // JIThelp.asm/JIThelp.s -#endif // TARGET_X86 +#endif // FEATURE_EH_FUNCLETS void STDCALL JIT_ByRefWriteBarrier(); // JIThelp.asm/JIThelp.s -#if defined(TARGET_AMD64) || defined(TARGET_ARM) - - FCDECL2VA(void, JIT_TailCall, PCODE copyArgs, PCODE target); - -#else // TARGET_AMD64 || TARGET_ARM - +#if defined(TARGET_X86) && !defined(UNIX_X86_ABI) void STDCALL JIT_TailCall(); // JIThelp.asm - -#endif // TARGET_AMD64 || TARGET_ARM +#endif // defined(TARGET_X86) && !defined(UNIX_X86_ABI) void STDMETHODCALLTYPE JIT_ProfilerEnterLeaveTailcallStub(UINT_PTR ProfilerHandle); #if !defined(TARGET_ARM64) && !defined(TARGET_LOONGARCH64) && !defined(TARGET_RISCV64) + // TODO: implement stack probing for other architectures https://github.com/dotnet/runtime/issues/13519 void STDCALL JIT_StackProbe(); -#endif // TARGET_ARM64 +#endif // !defined(TARGET_ARM64) && !defined(TARGET_LOONGARCH64) && !defined(TARGET_RISCV64) }; /*********************************************************************/ @@ -1032,7 +1029,6 @@ OBJECTHANDLE ConstructStringLiteral(CORINFO_MODULE_HANDLE scopeHnd, mdToken meta FCDECL2(Object*, JIT_Box_MP_FastPortable, CORINFO_CLASS_HANDLE type, void* data); FCDECL2(Object*, JIT_Box, CORINFO_CLASS_HANDLE type, void* data); -FCDECL0(VOID, JIT_PollGC); BOOL ObjIsInstanceOf(Object *pObject, TypeHandle toTypeHnd, BOOL throwCastException = FALSE); diff --git a/src/coreclr/vm/loongarch64/asmhelpers.S b/src/coreclr/vm/loongarch64/asmhelpers.S index 9a40cf8660a130..6be20320f9850c 100644 --- a/src/coreclr/vm/loongarch64/asmhelpers.S +++ b/src/coreclr/vm/loongarch64/asmhelpers.S @@ -1121,3 +1121,14 @@ LEAF_ENTRY GetTLSResolverAddress, _TEXT EPILOG_RETURN LEAF_END GetTLSResolverAddress, _TEXT // ------------------------------------------------------------------ + +LEAF_ENTRY JIT_PollGC, _TEXT + PREPARE_EXTERNAL_VAR g_TrapReturningThreads, $t0 + ld.w $t0, $t0, 0 + bne $t0, $zero, LOCAL_LABEL(JIT_PollGCRarePath) + jirl $r0, $ra, 0 +LOCAL_LABEL(JIT_PollGCRarePath): + PREPARE_EXTERNAL_VAR g_pPollGC, $t0 + ld.d $t0, $t0, 0 + EPILOG_BRANCH_REG $t0 +LEAF_END JIT_PollGC, _TEXT diff --git a/src/coreclr/vm/loongarch64/excepcpu.h b/src/coreclr/vm/loongarch64/excepcpu.h index 4146f7c6bd9417..8d2e1fdbbd2c07 100644 --- a/src/coreclr/vm/loongarch64/excepcpu.h +++ b/src/coreclr/vm/loongarch64/excepcpu.h @@ -24,15 +24,8 @@ class FaultingExceptionFrame; // Retrieves the redirected CONTEXT* from the stack frame of one of the // RedirectedHandledJITCaseForXXX_Stub's. // -PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_DISPATCHER_CONTEXT * pDispatcherContext); PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_CONTEXT * pContext); -// -// Retrieves the FaultingExceptionFrame* from the stack frame of -// RedirectForThrowControl. -// -FaultingExceptionFrame *GetFrameFromRedirectedStubStackFrame (T_DISPATCHER_CONTEXT *pDispatcherContext); - inline PCODE GetAdjustedCallAddress(PCODE returnAddress) { diff --git a/src/coreclr/vm/loongarch64/stubs.cpp b/src/coreclr/vm/loongarch64/stubs.cpp index c8e612ea2a9159..391c6fdf4cdd9e 100644 --- a/src/coreclr/vm/loongarch64/stubs.cpp +++ b/src/coreclr/vm/loongarch64/stubs.cpp @@ -892,11 +892,6 @@ void emitCOMStubCall (ComCallMethodDesc *pCOMMethodRX, ComCallMethodDesc *pCOMMe #endif // FEATURE_COMINTEROP -void JIT_TailCall() -{ - _ASSERTE(!"LOONGARCH64:NYI"); -} - #if !defined(DACCESS_COMPILE) EXTERN_C void JIT_UpdateWriteBarrierState(bool skipEphemeralCheck, size_t writeableOffset); @@ -949,15 +944,6 @@ void InitJITHelpers1() void UpdateWriteBarrierState(bool) {} #endif // !defined(DACCESS_COMPILE) -PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_DISPATCHER_CONTEXT * pDispatcherContext) -{ - LIMITED_METHOD_DAC_CONTRACT; - - DWORD64 stackSlot = pDispatcherContext->EstablisherFrame + REDIRECTSTUB_SP_OFFSET_CONTEXT; - PTR_PTR_CONTEXT ppContext = dac_cast((TADDR)stackSlot); - return *ppContext; -} - PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_CONTEXT * pContext) { LIMITED_METHOD_DAC_CONTRACT; @@ -968,13 +954,6 @@ PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_CONTEXT * pContext) } #if !defined(DACCESS_COMPILE) -FaultingExceptionFrame *GetFrameFromRedirectedStubStackFrame (DISPATCHER_CONTEXT *pDispatcherContext) -{ - LIMITED_METHOD_CONTRACT; - - return (FaultingExceptionFrame*)((TADDR)pDispatcherContext->ContextRecord->S0); -} - BOOL AdjustContextForVirtualStub( diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp index 69d5aa64d34ec1..60110263e4a274 100644 --- a/src/coreclr/vm/methodtablebuilder.cpp +++ b/src/coreclr/vm/methodtablebuilder.cpp @@ -5219,9 +5219,8 @@ MethodTableBuilder::InitNewMethodDesc( } } - // Turn off inlining for any calls - // that are marked in the metadata as not being inlineable. - if(IsMiNoInlining(pMethod->GetImplAttrs())) + // Turn off inlining for any calls that are marked in the metadata as NoInlining or NoOptimization. + if (IsMiNoInlining(pMethod->GetImplAttrs()) || IsMiNoOptimization(pMethod->GetImplAttrs())) { pNewMD->SetNotInline(true); } diff --git a/src/coreclr/vm/ppc64le/unixstubs.cpp b/src/coreclr/vm/ppc64le/unixstubs.cpp deleted file mode 100644 index d51902a949f26c..00000000000000 --- a/src/coreclr/vm/ppc64le/unixstubs.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#include "common.h" - -extern "C" -{ - void RedirectForThrowControl() - { - PORTABILITY_ASSERT("Implement for PAL"); - } -}; diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index 2836faa8b8fce8..085468f030e9b1 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -294,6 +294,7 @@ static const Entry s_QCall[] = DllImportEntry(ThreadNative_SpinWait) DllImportEntry(ThreadNative_Interrupt) DllImportEntry(ThreadNative_Sleep) + DllImportEntry(ThreadNative_PollGC) #ifdef FEATURE_COMINTEROP DllImportEntry(ThreadNative_DisableComObjectEagerCleanup) #endif // FEATURE_COMINTEROP diff --git a/src/coreclr/vm/riscv64/asmhelpers.S b/src/coreclr/vm/riscv64/asmhelpers.S index 8a14864b51f6d9..12b2918ae31e63 100644 --- a/src/coreclr/vm/riscv64/asmhelpers.S +++ b/src/coreclr/vm/riscv64/asmhelpers.S @@ -82,8 +82,8 @@ WRITE_BARRIER_ENTRY JIT_UpdateWriteBarrierState beq t0, zero, LOCAL_LABEL(EphemeralCheckEnabled) - ori a5, zero, 0 - addi a6, zero, -1 + li a5, 0 + li a6, -1 LOCAL_LABEL(EphemeralCheckEnabled): lla a7, g_lowest_address @@ -253,7 +253,7 @@ LOCAL_LABEL(ShadowUpdateDisabled): lb t0, 0(t6) bne t0, zero, LOCAL_LABEL(CheckCardTable) - ori t0, zero, 0xFF + li t0, 0xFF sb t0, 0(t6) LOCAL_LABEL(CheckCardTable): @@ -277,7 +277,7 @@ LOCAL_LABEL(SkipEphemeralCheck): srli t0, t3, 11 add t4, t6, t0 lbu t1, 0(t4) - ori t0, zero, 0xFF + li t0, 0xFF beq t1, t0, LOCAL_LABEL(Exit) sb t0, 0(t4) @@ -290,7 +290,7 @@ LOCAL_LABEL(SkipEphemeralCheck): add t4, t6, t0 lbu t6, 0(t4) - ori t0, zero, 0xFF + li t0, 0xFF beq t6, t0, LOCAL_LABEL(Exit) sb t0, 0(t4) @@ -968,3 +968,14 @@ LEAF_ENTRY GetThreadStaticsVariableOffset, _TEXT la.tls.ie a0, t_ThreadStatics EPILOG_RETURN LEAF_END GetThreadStaticsVariableOffset, _TEXT + +LEAF_ENTRY JIT_PollGC, _TEXT + PREPARE_EXTERNAL_VAR g_TrapReturningThreads, t0 + lw t0, 0(t0) + bnez t0, LOCAL_LABEL(JIT_PollGCRarePath) + ret +LOCAL_LABEL(JIT_PollGCRarePath): + PREPARE_EXTERNAL_VAR g_pPollGC, t0 + ld t0, 0(t0) + jr t0 +LEAF_END JIT_PollGC, _TEXT \ No newline at end of file diff --git a/src/coreclr/vm/riscv64/excepcpu.h b/src/coreclr/vm/riscv64/excepcpu.h index eb575235af8feb..416828487517d8 100644 --- a/src/coreclr/vm/riscv64/excepcpu.h +++ b/src/coreclr/vm/riscv64/excepcpu.h @@ -28,15 +28,8 @@ class FaultingExceptionFrame; // Retrieves the redirected CONTEXT* from the stack frame of one of the // RedirectedHandledJITCaseForXXX_Stub's. // -PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_DISPATCHER_CONTEXT * pDispatcherContext); PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_CONTEXT * pContext); -// -// Retrieves the FaultingExceptionFrame* from the stack frame of -// RedirectForThrowControl. -// -FaultingExceptionFrame *GetFrameFromRedirectedStubStackFrame (T_DISPATCHER_CONTEXT *pDispatcherContext); - inline PCODE GetAdjustedCallAddress(PCODE returnAddress) { diff --git a/src/coreclr/vm/riscv64/pinvokestubs.S b/src/coreclr/vm/riscv64/pinvokestubs.S index 9f8cecb3bff43b..d96a581b8d8570 100644 --- a/src/coreclr/vm/riscv64/pinvokestubs.S +++ b/src/coreclr/vm/riscv64/pinvokestubs.S @@ -137,7 +137,7 @@ // a1 = pThread // pThread->m_fPreemptiveGCDisabled = 1 - ori t4, x0, 1 + li t4, 1 sw t4, (Thread_m_fPreemptiveGCDisabled)(a1) // Check return trap diff --git a/src/coreclr/vm/riscv64/stubs.cpp b/src/coreclr/vm/riscv64/stubs.cpp index 3d48d68a4163f5..0d3d0e2f80d7cd 100644 --- a/src/coreclr/vm/riscv64/stubs.cpp +++ b/src/coreclr/vm/riscv64/stubs.cpp @@ -790,11 +790,6 @@ void emitCOMStubCall (ComCallMethodDesc *pCOMMethodRX, ComCallMethodDesc *pCOMMe } #endif // FEATURE_COMINTEROP -void JIT_TailCall() -{ - _ASSERTE(!"RISCV64:NYI"); -} - #if !defined(DACCESS_COMPILE) EXTERN_C void JIT_UpdateWriteBarrierState(bool skipEphemeralCheck, size_t writeableOffset); @@ -847,15 +842,6 @@ void InitJITHelpers1() void UpdateWriteBarrierState(bool) {} #endif // !defined(DACCESS_COMPILE) -PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_DISPATCHER_CONTEXT * pDispatcherContext) -{ - LIMITED_METHOD_DAC_CONTRACT; - - DWORD64 stackSlot = pDispatcherContext->EstablisherFrame + REDIRECTSTUB_SP_OFFSET_CONTEXT; - PTR_PTR_CONTEXT ppContext = dac_cast((TADDR)stackSlot); - return *ppContext; -} - PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_CONTEXT * pContext) { LIMITED_METHOD_DAC_CONTRACT; @@ -866,14 +852,6 @@ PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_CONTEXT * pContext) } #if !defined(DACCESS_COMPILE) -FaultingExceptionFrame *GetFrameFromRedirectedStubStackFrame (DISPATCHER_CONTEXT *pDispatcherContext) -{ - _ASSERTE(!"RISCV64: not implementation on riscv64!!!"); - LIMITED_METHOD_CONTRACT; - - return (FaultingExceptionFrame*)NULL; -} - BOOL AdjustContextForVirtualStub( diff --git a/src/coreclr/vm/riscv64/unixstubs.cpp b/src/coreclr/vm/riscv64/unixstubs.cpp deleted file mode 100644 index 878d5b003686b6..00000000000000 --- a/src/coreclr/vm/riscv64/unixstubs.cpp +++ /dev/null @@ -1,4 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#include "common.h" diff --git a/src/coreclr/vm/s390x/unixstubs.cpp b/src/coreclr/vm/s390x/unixstubs.cpp deleted file mode 100644 index d51902a949f26c..00000000000000 --- a/src/coreclr/vm/s390x/unixstubs.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#include "common.h" - -extern "C" -{ - void RedirectForThrowControl() - { - PORTABILITY_ASSERT("Implement for PAL"); - } -}; diff --git a/src/installer/pkg/projects/Microsoft.NETCore.DotNetAppHost/Microsoft.NETCore.DotNetAppHost.pkgproj b/src/installer/pkg/projects/Microsoft.NETCore.DotNetAppHost/Microsoft.NETCore.DotNetAppHost.pkgproj index 6f50203e9056c1..fcae5c30d7a086 100644 --- a/src/installer/pkg/projects/Microsoft.NETCore.DotNetAppHost/Microsoft.NETCore.DotNetAppHost.pkgproj +++ b/src/installer/pkg/projects/Microsoft.NETCore.DotNetAppHost/Microsoft.NETCore.DotNetAppHost.pkgproj @@ -11,7 +11,7 @@ - + diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Host.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Host.sfxproj index fc7b8b90fe9070..078991b13e8292 100644 --- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Host.sfxproj +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Host.sfxproj @@ -2,7 +2,7 @@ - true + true AppHostPack true dotnet-apphost-pack @@ -31,7 +31,7 @@ - + diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.CoreCLR.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.CoreCLR.sfxproj new file mode 100644 index 00000000000000..18ad16cfff4501 --- /dev/null +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.CoreCLR.sfxproj @@ -0,0 +1,84 @@ + + + CoreCLR + false + coreclr-pack + + + + + + RuntimePack + dotnet-runtime + dotnet-runtime-internal + false + NetCore.SharedFramework + true + true + + + + + + + + true + + false + + false + true + true + $(PublishReadyToRun) + + + + + + true + + + + + + $([MSBuild]::NormalizePath('$(Crossgen2InBuildDir)', 'crossgen2$(ExeSuffix)')) + + + + + + + + + + + + tools + + + + + + + + + + + tools/$(CoreCLRCrossTargetComponentDirName)_$(TargetArchitecture) + + + tools/$(CoreCLRCrossTargetComponentDirName)_$(TargetArchitecture) + + + + + + diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.Mono.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.Mono.sfxproj new file mode 100644 index 00000000000000..f074aa4c2e5e06 --- /dev/null +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.Mono.sfxproj @@ -0,0 +1,73 @@ + + + Mono + false + mono-pack + + + + + + + RuntimePack + true + true + + + + true + + + + false + true + true + true + + + + Mono + false + + + Mono.LLVM + false + + + Mono.LLVM.AOT + false + + + Mono.multithread + + + $(SharedFrameworkName).Runtime.$(RuntimeSpecificFrameworkSuffix).$(RuntimeIdentifier) + + + + + + + + runtimes/$(RuntimeIdentifier)/native/Mono.release.framework/%(RecursiveDir) + + + + runtimes/$(RuntimeIdentifier)/native/Mono.debug.framework/%(RecursiveDir) + + + + runtimes/$(RuntimeIdentifier)/native/include/%(RecursiveDir) + + + + runtimes/$(RuntimeIdentifier)/build/%(RecursiveDir) + + + + + diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.NativeAOT.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.NativeAOT.sfxproj new file mode 100644 index 00000000000000..336574ffe10fc7 --- /dev/null +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.NativeAOT.sfxproj @@ -0,0 +1,39 @@ + + + CoreCLR + true + naot-pack + + + + + + + RuntimePack + true + true + true + false + $(SharedFrameworkName).Runtime.NativeAOT.$(RuntimeIdentifier) + true + + + + + + + + + + + + + true + + + true + + + + diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.props b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.props index ea2a155cb59066..f64d11dfae3551 100644 --- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.props +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.props @@ -5,61 +5,26 @@ AddRuntimeFilesToPackage; AddFrameworkFilesToPackage - true - false - - false - - false true true The .NET Shared Framework - $(PublishReadyToRun) - - NativeAOT - - - Mono - false - - - Mono.LLVM - false - - - Mono.LLVM.AOT - false - - - Mono.multithread - - - $(SharedFrameworkName).Runtime.$(RuntimeSpecificFrameworkSuffix).$(RuntimeIdentifier) - - - - + + + - - - - - - - <_HostFiles Include="$(DotNetHostBinDir)/$(LibPrefix)hostpolicy$(LibSuffix)" /> <_HostFiles Include="$(DotNetHostBinDir)/$(LibPrefix)hostfxr$(LibSuffix)" PackOnly="true" /> @@ -74,80 +39,29 @@ runtimes/$(RuntimeIdentifier)/native - - - - tools - - - - runtimes/$(RuntimeIdentifier)/native/Mono.release.framework/%(RecursiveDir) - - - - runtimes/$(RuntimeIdentifier)/native/Mono.debug.framework/%(RecursiveDir) - - - - runtimes/$(RuntimeIdentifier)/native/include/%(RecursiveDir) - - - - runtimes/$(RuntimeIdentifier)/build/%(RecursiveDir) - - - - runtimes/$(CoreCLRCrossTargetComponentDirName)_$(TargetArchitecture)/native - - - tools/$(CoreCLRCrossTargetComponentDirName)_$(TargetArchitecture) - - - tools/$(CoreCLRCrossTargetComponentDirName)_$(TargetArchitecture) - - - tools/$(CoreCLRCrossTargetComponentDirName)_$(TargetArchitecture) - - - tools - - - - + + Condition="'%(LibrariesRuntimeFiles.Extension)' != '$(StaticLibSuffix)' or '$(IncludeStaticLibrariesInPack)' == 'true'"> runtimes/$(RuntimeIdentifier)/native/%(LibrariesRuntimeFiles.NativeSubDirectory)%(RecursiveDir) - - - <_diaSymArch>$(_hostArch) - <_diaSymReaderPath>$(PkgMicrosoft_DiaSymReader_Native)/runtimes/win/native/Microsoft.DiaSymReader.Native.$(_diaSymArch).dll - + <_diaSymTargetArch>$(TargetArchitecture) <_diaSymTargetArch Condition="'$(TargetArchitecture)' == 'x64'">amd64 <_diaSymReaderTargetArchPath>$(PkgMicrosoft_DiaSymReader_Native)/runtimes/win/native/Microsoft.DiaSymReader.Native.$(_diaSymTargetArch).dll - + - - runtimes/$(CoreCLRCrossTargetComponentDirName)_$(TargetArchitecture)/native - @@ -169,37 +83,10 @@ - + - - - true - - - - - - - tools - - - - - - - - - - - true - - - - + diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.sfxproj deleted file mode 100644 index e963032de1005e..00000000000000 --- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.sfxproj +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - RuntimePack - dotnet-runtime-internal - dotnet-runtime - dotnet-runtime-internal - true - false - dotnet-runtime-symbols - NetCore.SharedFramework - true - true - - - - true - - true - - - - - - - - - - diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.MonoCrossAOT.Sdk.props.in b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.Sdk.props.in similarity index 100% rename from src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.MonoCrossAOT.Sdk.props.in rename to src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.Sdk.props.in diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.MonoCrossAOT.UnixFilePermissions.xml.in b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.UnixFilePermissions.xml.in similarity index 100% rename from src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.MonoCrossAOT.UnixFilePermissions.xml.in rename to src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.UnixFilePermissions.xml.in diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.android-arm.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.android-arm.sfxproj new file mode 100644 index 00000000000000..33bf3321c0eb9c --- /dev/null +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.android-arm.sfxproj @@ -0,0 +1,8 @@ + + + + android-arm + + + + diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.android-arm64.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.android-arm64.sfxproj new file mode 100644 index 00000000000000..ee259d7812b9fc --- /dev/null +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.android-arm64.sfxproj @@ -0,0 +1,8 @@ + + + + android-arm64 + + + + diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.android-x64.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.android-x64.sfxproj new file mode 100644 index 00000000000000..6574e57fd4db27 --- /dev/null +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.android-x64.sfxproj @@ -0,0 +1,8 @@ + + + + android-x64 + + + + diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.android-x86.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.android-x86.sfxproj new file mode 100644 index 00000000000000..b4279f57110d84 --- /dev/null +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.android-x86.sfxproj @@ -0,0 +1,8 @@ + + + + android-x86 + + + + diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.browser-wasm.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.browser-wasm.sfxproj new file mode 100644 index 00000000000000..19b7059c546e37 --- /dev/null +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.browser-wasm.sfxproj @@ -0,0 +1,8 @@ + + + + browser-wasm + + + + diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.ios-arm64.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.ios-arm64.sfxproj new file mode 100644 index 00000000000000..0395c9e026647d --- /dev/null +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.ios-arm64.sfxproj @@ -0,0 +1,8 @@ + + + + ios-arm64 + + + + diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.iossimulator-arm64.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.iossimulator-arm64.sfxproj new file mode 100644 index 00000000000000..245c0aceebfc86 --- /dev/null +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.iossimulator-arm64.sfxproj @@ -0,0 +1,8 @@ + + + + iossimulator-arm64 + + + + diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.iossimulator-x64.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.iossimulator-x64.sfxproj new file mode 100644 index 00000000000000..e4aa8896ac855e --- /dev/null +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.iossimulator-x64.sfxproj @@ -0,0 +1,8 @@ + + + + iossimulator-x64 + + + + diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.maccatalyst-arm64.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.maccatalyst-arm64.sfxproj new file mode 100644 index 00000000000000..7625df228fc760 --- /dev/null +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.maccatalyst-arm64.sfxproj @@ -0,0 +1,8 @@ + + + + maccatalyst-arm64 + + + + diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.maccatalyst-x64.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.maccatalyst-x64.sfxproj new file mode 100644 index 00000000000000..7382e99e054f91 --- /dev/null +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.maccatalyst-x64.sfxproj @@ -0,0 +1,8 @@ + + + + maccatalyst-x64 + + + + diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.MonoCrossAOT.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.props similarity index 85% rename from src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.MonoCrossAOT.sfxproj rename to src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.props index 74b9b1462dccc4..4394697562706b 100644 --- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.MonoCrossAOT.sfxproj +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.props @@ -1,19 +1,15 @@ - - - + true - RuntimePack + ToolPack Microsoft.NETCore.App.MonoCrossAOT Microsoft.NETCore.App.Runtime.AOT.$(RuntimeIdentifier).Cross.$(TargetCrossRid) - monocrossaot linux-x64;linux-arm64;linux-musl-x64;linux-musl-arm64;osx-x64;osx-arm64;win-x64;win-arm64 false - false - tools/ true - mono-aot-cross - $(AotCompilerFileName).exe + mono-aot-cross$(ExeSuffix) + true + ../PACKAGE.md @@ -58,5 +54,4 @@ - diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.tvos-arm64.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.tvos-arm64.sfxproj new file mode 100644 index 00000000000000..dcee36b4c8cecd --- /dev/null +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.tvos-arm64.sfxproj @@ -0,0 +1,8 @@ + + + + tvos-arm64 + + + + diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.tvossimulator-arm64.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.tvossimulator-arm64.sfxproj new file mode 100644 index 00000000000000..277b5aa1fdf4f7 --- /dev/null +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.tvossimulator-arm64.sfxproj @@ -0,0 +1,8 @@ + + + + tvossimulator-arm64 + + + + diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.tvossimulator-x64.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.tvossimulator-x64.sfxproj new file mode 100644 index 00000000000000..223592b08d753d --- /dev/null +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.tvossimulator-x64.sfxproj @@ -0,0 +1,8 @@ + + + + tvossimulator-x64 + + + + diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.wasi-wasm.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.wasi-wasm.sfxproj new file mode 100644 index 00000000000000..36b9e2dcd7c6fb --- /dev/null +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/MonoCrossAOT/Microsoft.NETCore.App.MonoCrossAOT.wasi-wasm.sfxproj @@ -0,0 +1,8 @@ + + + + wasi-wasm + + + + diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/ReadyToRun.targets b/src/installer/pkg/sfx/Microsoft.NETCore.App/ReadyToRun.targets deleted file mode 100644 index 1e27f828c5bf58..00000000000000 --- a/src/installer/pkg/sfx/Microsoft.NETCore.App/ReadyToRun.targets +++ /dev/null @@ -1,15 +0,0 @@ - - - - 1 - $([MSBuild]::NormalizePath('$(Crossgen2InBuildDir)', 'crossgen2$(ExeSuffix)')) - - - - - - - diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/monocrossaot.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/monocrossaot.proj similarity index 52% rename from src/installer/pkg/sfx/Microsoft.NETCore.App/monocrossaot.sfxproj rename to src/installer/pkg/sfx/Microsoft.NETCore.App/monocrossaot.proj index 08da76561f220b..1f904f0d515fbe 100644 --- a/src/installer/pkg/sfx/Microsoft.NETCore.App/monocrossaot.sfxproj +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/monocrossaot.proj @@ -8,23 +8,17 @@ $(MonoAotTargets);iossimulator-x64;iossimulator-arm64;ios-arm64 $(MonoAotTargets);maccatalyst-x64;maccatalyst-arm64 $(MonoAotTargets);wasi-wasm + true - - + + + + + + + - - - - - - - diff --git a/src/installer/pkg/sfx/bundle/Microsoft.NETCore.App.Bundle.bundleproj b/src/installer/pkg/sfx/bundle/Microsoft.NETCore.App.Bundle.bundleproj index 178a37fed055bb..d2701902038ee9 100644 --- a/src/installer/pkg/sfx/bundle/Microsoft.NETCore.App.Bundle.bundleproj +++ b/src/installer/pkg/sfx/bundle/Microsoft.NETCore.App.Bundle.bundleproj @@ -5,7 +5,7 @@ Name, used to generate the bundle upgrade code. Must stay the same to allow bundles in a given product band to upgrade in place. --> - true + true false .NET Core Shared Framework Bundle Installer $(MSBuildProjectDirectory) @@ -24,7 +24,8 @@ - + + diff --git a/src/installer/pkg/sfx/installers.proj b/src/installer/pkg/sfx/installers.proj index 257ff4cc7593bd..41fe958ed6bb40 100644 --- a/src/installer/pkg/sfx/installers.proj +++ b/src/installer/pkg/sfx/installers.proj @@ -1,6 +1,8 @@ - + + + diff --git a/src/installer/tests/TestUtils/NetCoreAppBuilder.cs b/src/installer/tests/TestUtils/NetCoreAppBuilder.cs index d2099b3ebfc4b3..636b8260af6af0 100644 --- a/src/installer/tests/TestUtils/NetCoreAppBuilder.cs +++ b/src/installer/tests/TestUtils/NetCoreAppBuilder.cs @@ -356,8 +356,10 @@ public NetCoreAppBuilder WithStandardRuntimeFallbacks() .WithRuntimeFallbacks("win-x86", "win", "any") .WithRuntimeFallbacks("win", "any") .WithRuntimeFallbacks("linux-arm64", "linux", "any") + .WithRuntimeFallbacks("linux-riscv64", "linux", "any") .WithRuntimeFallbacks("linux-x64", "linux", "any") .WithRuntimeFallbacks("linux-musl-arm64", "linux-musl", "linux", "any") + .WithRuntimeFallbacks("linux-musl-riscv64", "linux-musl", "linux", "any") .WithRuntimeFallbacks("linux-musl-x64", "linux-musl", "linux", "any") .WithRuntimeFallbacks("linux", "any") .WithRuntimeFallbacks("osx.10.12-x64", "osx-x64", "osx", "any") diff --git a/src/installer/tests/pretest.proj b/src/installer/tests/hostpretest.proj similarity index 60% rename from src/installer/tests/pretest.proj rename to src/installer/tests/hostpretest.proj index b97a2e77c2e131..98b493566a73c4 100644 --- a/src/installer/tests/pretest.proj +++ b/src/installer/tests/hostpretest.proj @@ -8,13 +8,18 @@ + + + + + - + Properties="MSBuildRestoreSessionId=$([System.Guid]::NewGuid())" /> diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.InitializeTerminalAndSignalHandling.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.InitializeTerminalAndSignalHandling.cs index 9824f62e29fef2..fccf35c24ec8cd 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.InitializeTerminalAndSignalHandling.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.InitializeTerminalAndSignalHandling.cs @@ -14,5 +14,8 @@ internal static partial class Sys [LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_SetKeypadXmit", StringMarshalling = StringMarshalling.Utf8)] internal static partial void SetKeypadXmit(SafeFileHandle terminalHandle, string terminfoString); + + [LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_UninitializeTerminal")] + internal static partial void UninitializeTerminal(); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs index f8fa8b7d736c0f..1fe9ee1ffb9200 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs @@ -408,7 +408,7 @@ internal static SafeSslHandle AllocateSslHandle(SslAuthenticationOptions sslAuth if (sslAuthenticationOptions.IsClient) { - if (!string.IsNullOrEmpty(sslAuthenticationOptions.TargetHost) && !TargetHostNameHelper.IsValidAddress(sslAuthenticationOptions.TargetHost)) + if (!string.IsNullOrEmpty(sslAuthenticationOptions.TargetHost) && !IPAddress.IsValid(sslAuthenticationOptions.TargetHost)) { // Similar to windows behavior, set SNI on openssl by default for client context, ignore errors. if (!Ssl.SslSetTlsExtHostName(sslHandle, sslAuthenticationOptions.TargetHost)) diff --git a/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/StreamExtensions.netstandard.cs b/src/libraries/Common/src/System/IO/StreamExtensions.netstandard.cs similarity index 97% rename from src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/StreamExtensions.netstandard.cs rename to src/libraries/Common/src/System/IO/StreamExtensions.netstandard.cs index d19a30d1d15750..368d80094fabd4 100644 --- a/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/StreamExtensions.netstandard.cs +++ b/src/libraries/Common/src/System/IO/StreamExtensions.netstandard.cs @@ -1,15 +1,12 @@ // 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.Buffers; -using System.Collections.Generic; using System.Runtime.InteropServices; -using System.Text; using System.Threading; using System.Threading.Tasks; -namespace System.IO.Pipelines +namespace System.IO { // Helpers to write Memory to Stream on netstandard 2.0 internal static class StreamExtensions diff --git a/src/libraries/Common/src/System/Net/ArrayBuffer.cs b/src/libraries/Common/src/System/Net/ArrayBuffer.cs index 7499861512f4b3..e07ff3ea333ceb 100644 --- a/src/libraries/Common/src/System/Net/ArrayBuffer.cs +++ b/src/libraries/Common/src/System/Net/ArrayBuffer.cs @@ -21,6 +21,12 @@ namespace System.Net [StructLayout(LayoutKind.Auto)] internal struct ArrayBuffer : IDisposable { +#if NET + private static int ArrayMaxLength => Array.MaxLength; +#else + private const int ArrayMaxLength = 0X7FFFFFC7; +#endif + private readonly bool _usePool; private byte[] _bytes; private int _activeStart; @@ -144,13 +150,15 @@ private void EnsureAvailableSpaceCore(int byteCount) return; } - // Double the size of the buffer until we have enough space. int desiredSize = ActiveLength + byteCount; - int newSize = _bytes.Length; - do + + if ((uint)desiredSize > ArrayMaxLength) { - newSize *= 2; - } while (newSize < desiredSize); + throw new OutOfMemoryException(); + } + + // Double the existing buffer size (capped at Array.MaxLength). + int newSize = Math.Max(desiredSize, (int)Math.Min(ArrayMaxLength, 2 * (uint)_bytes.Length)); byte[] newBytes = _usePool ? ArrayPool.Shared.Rent(newSize) : diff --git a/src/libraries/Common/src/System/Net/IPv6AddressHelper.Common.cs b/src/libraries/Common/src/System/Net/IPv6AddressHelper.Common.cs index 6645daa83e4b20..d27cd18b8d56c3 100644 --- a/src/libraries/Common/src/System/Net/IPv6AddressHelper.Common.cs +++ b/src/libraries/Common/src/System/Net/IPv6AddressHelper.Common.cs @@ -95,7 +95,7 @@ internal static bool ShouldHaveIpv4Embedded(ReadOnlySpan numbers) // Remarks: MUST NOT be used unless all input indexes are verified and trusted. // start must be next to '[' position, or error is reported - internal static unsafe bool IsValidStrict(TChar* name, int start, ref int end) + internal static unsafe bool IsValidStrict(TChar* name, int start, int end) where TChar : unmanaged, IBinaryInteger { Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte)); diff --git a/src/libraries/Common/src/System/Net/Security/TargetHostNameHelper.cs b/src/libraries/Common/src/System/Net/Security/TargetHostNameHelper.cs index bc973c247aa91c..b60db14144d51a 100644 --- a/src/libraries/Common/src/System/Net/Security/TargetHostNameHelper.cs +++ b/src/libraries/Common/src/System/Net/Security/TargetHostNameHelper.cs @@ -1,9 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. + using System.Buffers; -using System.Collections.Generic; using System.Globalization; -using System.Runtime.InteropServices; namespace System.Net.Security { @@ -37,45 +36,5 @@ internal static string NormalizeHostName(string? targetHost) return targetHost; } - - // Simplified version of IPAddressParser.Parse to avoid allocations and dependencies. - // It purposely ignores scopeId as we don't really use so we do not need to map it to actual interface id. - internal static unsafe bool IsValidAddress(string? hostname) - { - if (string.IsNullOrEmpty(hostname)) - { - return false; - } - - ReadOnlySpan ipSpan = hostname.AsSpan(); - - int end = ipSpan.Length; - - if (ipSpan.Contains(':')) - { - // The address is parsed as IPv6 if and only if it contains a colon. This is valid because - // we don't support/parse a port specification at the end of an IPv4 address. - fixed (char* ipStringPtr = &MemoryMarshal.GetReference(ipSpan)) - { - return IPv6AddressHelper.IsValidStrict(ipStringPtr, 0, ref end); - } - } - else if (char.IsDigit(ipSpan[0])) - { - long tmpAddr; - - fixed (char* ipStringPtr = &MemoryMarshal.GetReference(ipSpan)) - { - tmpAddr = IPv4AddressHelper.ParseNonCanonical(ipStringPtr, 0, ref end, notImplicitFile: true); - } - - if (tmpAddr != IPv4AddressHelper.Invalid && end == ipSpan.Length) - { - return true; - } - } - - return false; - } } } diff --git a/src/libraries/Common/src/System/Text/Json/PooledByteBufferWriter.cs b/src/libraries/Common/src/System/Text/Json/PooledByteBufferWriter.cs index 824e3ff409315d..d65665ec902b4b 100644 --- a/src/libraries/Common/src/System/Text/Json/PooledByteBufferWriter.cs +++ b/src/libraries/Common/src/System/Text/Json/PooledByteBufferWriter.cs @@ -1,12 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Buffers; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.IO; using System.IO.Pipelines; -using System.Runtime.CompilerServices; +using System.Net; using System.Threading; using System.Threading.Tasks; @@ -14,33 +12,14 @@ namespace System.Text.Json { internal sealed class PooledByteBufferWriter : PipeWriter, IDisposable { - // This class allows two possible configurations: if rentedBuffer is not null then - // it can be used as an IBufferWriter and holds a buffer that should eventually be - // returned to the shared pool. If rentedBuffer is null, then the instance is in a - // cleared/disposed state and it must re-rent a buffer before it can be used again. - private byte[]? _rentedBuffer; - private int _index; - private readonly Stream? _stream; - private const int MinimumBufferSize = 256; - // Value copied from Array.MaxLength in System.Private.CoreLib/src/libraries/System.Private.CoreLib/src/System/Array.cs. - public const int MaximumBufferSize = 0X7FFFFFC7; - - private PooledByteBufferWriter() - { -#if NET - // Ensure we are in sync with the Array.MaxLength implementation. - Debug.Assert(MaximumBufferSize == Array.MaxLength); -#endif - } + private ArrayBuffer _buffer; + private readonly Stream? _stream; - public PooledByteBufferWriter(int initialCapacity) : this() + public PooledByteBufferWriter(int initialCapacity) { - Debug.Assert(initialCapacity > 0); - - _rentedBuffer = ArrayPool.Shared.Rent(initialCapacity); - _index = 0; + _buffer = new ArrayBuffer(initialCapacity, usePool: true); } public PooledByteBufferWriter(int initialCapacity, Stream stream) : this(initialCapacity) @@ -48,202 +27,67 @@ public PooledByteBufferWriter(int initialCapacity, Stream stream) : this(initial _stream = stream; } - public ReadOnlyMemory WrittenMemory - { - get - { - Debug.Assert(_rentedBuffer != null); - Debug.Assert(_index <= _rentedBuffer.Length); - return _rentedBuffer.AsMemory(0, _index); - } - } + public ReadOnlySpan WrittenSpan => _buffer.ActiveSpan; - public int WrittenCount - { - get - { - Debug.Assert(_rentedBuffer != null); - return _index; - } - } + public ReadOnlyMemory WrittenMemory => _buffer.ActiveMemory; - public int Capacity - { - get - { - Debug.Assert(_rentedBuffer != null); - return _rentedBuffer.Length; - } - } + public int Capacity => _buffer.Capacity; - public int FreeCapacity - { - get - { - Debug.Assert(_rentedBuffer != null); - return _rentedBuffer.Length - _index; - } - } - - public void Clear() - { - ClearHelper(); - } + public void Clear() => _buffer.Discard(_buffer.ActiveLength); - public void ClearAndReturnBuffers() - { - Debug.Assert(_rentedBuffer != null); + public void ClearAndReturnBuffers() => _buffer.ClearAndReturnBuffer(); - ClearHelper(); - byte[] toReturn = _rentedBuffer; - _rentedBuffer = null; - ArrayPool.Shared.Return(toReturn); - } - - private void ClearHelper() - { - Debug.Assert(_rentedBuffer != null); - Debug.Assert(_index <= _rentedBuffer.Length); - - _rentedBuffer.AsSpan(0, _index).Clear(); - _index = 0; - } - - // Returns the rented buffer back to the pool - public void Dispose() - { - if (_rentedBuffer == null) - { - return; - } - - ClearHelper(); - byte[] toReturn = _rentedBuffer; - _rentedBuffer = null; - ArrayPool.Shared.Return(toReturn); - } + public void Dispose() => _buffer.Dispose(); public void InitializeEmptyInstance(int initialCapacity) { Debug.Assert(initialCapacity > 0); - Debug.Assert(_rentedBuffer is null); + Debug.Assert(_buffer.ActiveLength == 0); - _rentedBuffer = ArrayPool.Shared.Rent(initialCapacity); - _index = 0; + _buffer.EnsureAvailableSpace(initialCapacity); } - public static PooledByteBufferWriter CreateEmptyInstanceForCaching() => new PooledByteBufferWriter(); + public static PooledByteBufferWriter CreateEmptyInstanceForCaching() => new PooledByteBufferWriter(initialCapacity: 0); - public override void Advance(int count) - { - Debug.Assert(_rentedBuffer != null); - Debug.Assert(count >= 0); - Debug.Assert(_index <= _rentedBuffer.Length - count); - _index += count; - } + public override void Advance(int count) => _buffer.Commit(count); public override Memory GetMemory(int sizeHint = MinimumBufferSize) { - CheckAndResizeBuffer(sizeHint); - return _rentedBuffer.AsMemory(_index); + Debug.Assert(sizeHint > 0); + + _buffer.EnsureAvailableSpace(sizeHint); + return _buffer.AvailableMemory; } public override Span GetSpan(int sizeHint = MinimumBufferSize) { - CheckAndResizeBuffer(sizeHint); - return _rentedBuffer.AsSpan(_index); + Debug.Assert(sizeHint > 0); + + _buffer.EnsureAvailableSpace(sizeHint); + return _buffer.AvailableSpan; } #if NET - internal void WriteToStream(Stream destination) - { - destination.Write(WrittenMemory.Span); - } + internal void WriteToStream(Stream destination) => destination.Write(_buffer.ActiveSpan); #else - internal void WriteToStream(Stream destination) - { - Debug.Assert(_rentedBuffer != null); - destination.Write(_rentedBuffer, 0, _index); - } + internal void WriteToStream(Stream destination) => destination.Write(_buffer.ActiveMemory); #endif - private void CheckAndResizeBuffer(int sizeHint) - { - Debug.Assert(_rentedBuffer != null); - Debug.Assert(sizeHint > 0); - - int currentLength = _rentedBuffer.Length; - int availableSpace = currentLength - _index; - - // If we've reached ~1GB written, grow to the maximum buffer - // length to avoid incessant minimal growths causing perf issues. - if (_index >= MaximumBufferSize / 2) - { - sizeHint = Math.Max(sizeHint, MaximumBufferSize - currentLength); - } - - if (sizeHint > availableSpace) - { - int growBy = Math.Max(sizeHint, currentLength); - - int newSize = currentLength + growBy; - - if ((uint)newSize > MaximumBufferSize) - { - newSize = currentLength + sizeHint; - if ((uint)newSize > MaximumBufferSize) - { - ThrowHelper.ThrowOutOfMemoryException_BufferMaximumSizeExceeded((uint)newSize); - } - } - - byte[] oldBuffer = _rentedBuffer; - - _rentedBuffer = ArrayPool.Shared.Rent(newSize); - - Debug.Assert(oldBuffer.Length >= _index); - Debug.Assert(_rentedBuffer.Length >= _index); - - Span oldBufferAsSpan = oldBuffer.AsSpan(0, _index); - oldBufferAsSpan.CopyTo(_rentedBuffer); - oldBufferAsSpan.Clear(); - ArrayPool.Shared.Return(oldBuffer); - } - - Debug.Assert(_rentedBuffer.Length - _index > 0); - Debug.Assert(_rentedBuffer.Length - _index >= sizeHint); - } - public override async ValueTask FlushAsync(CancellationToken cancellationToken = default) { Debug.Assert(_stream is not null); -#if NET await _stream.WriteAsync(WrittenMemory, cancellationToken).ConfigureAwait(false); -#else - Debug.Assert(_rentedBuffer != null); - await _stream.WriteAsync(_rentedBuffer, 0, _index, cancellationToken).ConfigureAwait(false); -#endif Clear(); return new FlushResult(isCanceled: false, isCompleted: false); } public override bool CanGetUnflushedBytes => true; - public override long UnflushedBytes => _index; + public override long UnflushedBytes => _buffer.ActiveLength; // This type is used internally in JsonSerializer to help buffer and flush bytes to the underlying Stream. // It's only pretending to be a PipeWriter and doesn't need Complete or CancelPendingFlush for the internal usage. public override void CancelPendingFlush() => throw new NotImplementedException(); public override void Complete(Exception? exception = null) => throw new NotImplementedException(); } - - internal static partial class ThrowHelper - { - [DoesNotReturn] - [MethodImpl(MethodImplOptions.NoInlining)] - public static void ThrowOutOfMemoryException_BufferMaximumSizeExceeded(uint capacity) - { - throw new OutOfMemoryException(SR.Format(SR.BufferMaximumSizeExceeded, capacity)); - } - } } diff --git a/src/libraries/Common/tests/Common.Tests.csproj b/src/libraries/Common/tests/Common.Tests.csproj index baf24f1232c42e..453f93145e7178 100644 --- a/src/libraries/Common/tests/Common.Tests.csproj +++ b/src/libraries/Common/tests/Common.Tests.csproj @@ -83,6 +83,7 @@ + diff --git a/src/libraries/Common/tests/System/GenericMathTestMemberData.cs b/src/libraries/Common/tests/System/GenericMathTestMemberData.cs index 0e19ac826dfdda..0e314aa9e9a27f 100644 --- a/src/libraries/Common/tests/System/GenericMathTestMemberData.cs +++ b/src/libraries/Common/tests/System/GenericMathTestMemberData.cs @@ -676,23 +676,201 @@ public static IEnumerable HypotSingle } } + public static IEnumerable IsTestByte + { + get + { + yield return new object[] { byte.MinValue }; + yield return new object[] { 1.0 }; + yield return new object[] { 2.0 }; + yield return new object[] { 3.0 }; + yield return new object[] { sbyte.MaxValue }; + yield return new object[] { byte.MaxValue }; + } + } + + public static IEnumerable IsTestDouble + { + get + { + yield return new object[] { double.NegativeInfinity }; + yield return new object[] { double.MinValue }; + yield return new object[] { -1.0 }; + yield return new object[] { -MinNormalDouble }; + yield return new object[] { -MaxSubnormalDouble }; + yield return new object[] { -double.Epsilon }; + yield return new object[] { -0.0 }; + yield return new object[] { double.NaN }; + yield return new object[] { 0.0 }; + yield return new object[] { double.Epsilon }; + yield return new object[] { MaxSubnormalDouble }; + yield return new object[] { MinNormalDouble }; + yield return new object[] { 1.0 }; + yield return new object[] { double.MaxValue }; + yield return new object[] { double.PositiveInfinity }; + } + } + + public static IEnumerable IsTestInt16 + { + get + { + yield return new object[] { short.MinValue }; + yield return new object[] { sbyte.MinValue }; + yield return new object[] { -3.0 }; + yield return new object[] { -2.0 }; + yield return new object[] { -1.0 }; + yield return new object[] { 0.0 }; + yield return new object[] { 1.0 }; + yield return new object[] { 2.0 }; + yield return new object[] { 3.0 }; + yield return new object[] { sbyte.MaxValue }; + yield return new object[] { byte.MaxValue }; + yield return new object[] { short.MaxValue }; + } + } + + public static IEnumerable IsTestInt32 + { + get + { + yield return new object[] { int.MinValue }; + yield return new object[] { short.MinValue }; + yield return new object[] { sbyte.MinValue }; + yield return new object[] { -3.0 }; + yield return new object[] { -2.0 }; + yield return new object[] { -1.0 }; + yield return new object[] { 0.0 }; + yield return new object[] { 1.0 }; + yield return new object[] { 2.0 }; + yield return new object[] { 3.0 }; + yield return new object[] { sbyte.MaxValue }; + yield return new object[] { byte.MaxValue }; + yield return new object[] { short.MaxValue }; + yield return new object[] { int.MaxValue }; + } + } + + public static IEnumerable IsTestInt64 + { + get + { + yield return new object[] { long.MinValue }; + yield return new object[] { int.MinValue }; + yield return new object[] { short.MinValue }; + yield return new object[] { sbyte.MinValue }; + yield return new object[] { -3.0 }; + yield return new object[] { -2.0 }; + yield return new object[] { -1.0 }; + yield return new object[] { 0.0 }; + yield return new object[] { 1.0 }; + yield return new object[] { 2.0 }; + yield return new object[] { 3.0 }; + yield return new object[] { sbyte.MaxValue }; + yield return new object[] { byte.MaxValue }; + yield return new object[] { short.MaxValue }; + yield return new object[] { int.MaxValue }; + yield return new object[] { long.MaxValue }; + } + } + + public static IEnumerable IsTestSByte + { + get + { + yield return new object[] { sbyte.MinValue }; + yield return new object[] { -3.0 }; + yield return new object[] { -2.0 }; + yield return new object[] { -1.0 }; + yield return new object[] { 0.0 }; + yield return new object[] { 1.0 }; + yield return new object[] { 2.0 }; + yield return new object[] { 3.0 }; + yield return new object[] { sbyte.MaxValue }; + } + } + + public static IEnumerable IsTestSingle + { + get + { + yield return new object[] { float.NegativeInfinity }; + yield return new object[] { float.MinValue }; + yield return new object[] { -1.0f }; + yield return new object[] { -MinNormalSingle }; + yield return new object[] { -MaxSubnormalSingle }; + yield return new object[] { -float.Epsilon }; + yield return new object[] { -0.0f }; + yield return new object[] { float.NaN }; + yield return new object[] { 0.0f }; + yield return new object[] { float.Epsilon }; + yield return new object[] { MaxSubnormalSingle }; + yield return new object[] { MinNormalSingle }; + yield return new object[] { 1.0f }; + yield return new object[] { float.MaxValue }; + yield return new object[] { float.PositiveInfinity }; + } + } + + public static IEnumerable IsTestUInt16 + { + get + { + yield return new object[] { ushort.MinValue }; + yield return new object[] { 1.0 }; + yield return new object[] { 2.0 }; + yield return new object[] { 3.0 }; + yield return new object[] { sbyte.MaxValue }; + yield return new object[] { byte.MaxValue }; + yield return new object[] { short.MaxValue }; + yield return new object[] { ushort.MaxValue }; + } + } + + public static IEnumerable IsTestUInt32 + { + get + { + yield return new object[] { uint.MinValue }; + yield return new object[] { sbyte.MaxValue }; + yield return new object[] { byte.MaxValue }; + yield return new object[] { short.MaxValue }; + yield return new object[] { int.MaxValue }; + yield return new object[] { uint.MaxValue }; + } + } + + public static IEnumerable IsTestUInt64 + { + get + { + yield return new object[] { ulong.MinValue }; + yield return new object[] { sbyte.MaxValue }; + yield return new object[] { byte.MaxValue }; + yield return new object[] { short.MaxValue }; + yield return new object[] { int.MaxValue }; + yield return new object[] { long.MaxValue }; + yield return new object[] { ulong.MaxValue }; + } + } + public static IEnumerable IsNaNDouble { get { - yield return new object[] { double.NegativeInfinity, false }; - yield return new object[] { double.MinValue, false }; - yield return new object[] { -MinNormalDouble, false }; - yield return new object[] { -MaxSubnormalDouble, false }; - yield return new object[] { -double.Epsilon, false }; - yield return new object[] { -0.0, false }; - yield return new object[] { double.NaN, true }; - yield return new object[] { 0.0, false }; - yield return new object[] { double.Epsilon, false }; - yield return new object[] { MaxSubnormalDouble, false }; - yield return new object[] { MinNormalDouble, false }; - yield return new object[] { double.MaxValue, false }; - yield return new object[] { double.PositiveInfinity, false }; + yield return new object[] { double.NegativeInfinity, false }; + yield return new object[] { double.MinValue, false }; + yield return new object[] { -MinNormalDouble, false }; + yield return new object[] { -MaxSubnormalDouble, false }; + yield return new object[] { -double.Epsilon, false }; + yield return new object[] { -0.0, false }; + yield return new object[] { double.NaN, true }; + yield return new object[] { 0.0, false }; + yield return new object[] { double.Epsilon, false }; + yield return new object[] { MaxSubnormalDouble, false }; + yield return new object[] { MinNormalDouble, false }; + yield return new object[] { double.MaxValue, false }; + yield return new object[] { double.PositiveInfinity, false }; } } @@ -700,19 +878,19 @@ public static IEnumerable IsNaNSingle { get { - yield return new object[] { float.NegativeInfinity, false }; - yield return new object[] { float.MinValue, false }; - yield return new object[] { -MinNormalSingle, false }; - yield return new object[] { -MaxSubnormalSingle, false }; - yield return new object[] { -float.Epsilon, false }; - yield return new object[] { -0.0f, false }; - yield return new object[] { float.NaN, true }; - yield return new object[] { 0.0f, false }; - yield return new object[] { float.Epsilon, false }; - yield return new object[] { MaxSubnormalSingle, false }; - yield return new object[] { MinNormalSingle, false }; - yield return new object[] { float.MaxValue, false }; - yield return new object[] { float.PositiveInfinity, false }; + yield return new object[] { float.NegativeInfinity, false }; + yield return new object[] { float.MinValue, false }; + yield return new object[] { -MinNormalSingle, false }; + yield return new object[] { -MaxSubnormalSingle, false }; + yield return new object[] { -float.Epsilon, false }; + yield return new object[] { -0.0f, false }; + yield return new object[] { float.NaN, true }; + yield return new object[] { 0.0f, false }; + yield return new object[] { float.Epsilon, false }; + yield return new object[] { MaxSubnormalSingle, false }; + yield return new object[] { MinNormalSingle, false }; + yield return new object[] { float.MaxValue, false }; + yield return new object[] { float.PositiveInfinity, false }; } } @@ -720,17 +898,17 @@ public static IEnumerable IsNegativeDouble { get { - yield return new object[] { double.NegativeInfinity, true }; - yield return new object[] { double.MinValue, true }; - yield return new object[] { -MinNormalDouble, true }; - yield return new object[] { -MaxSubnormalDouble, true }; - yield return new object[] { -0.0, true }; - yield return new object[] { double.NaN, true }; - yield return new object[] { 0.0, false }; - yield return new object[] { MaxSubnormalDouble, false }; - yield return new object[] { MinNormalDouble, false }; - yield return new object[] { double.MaxValue, false }; - yield return new object[] { double.PositiveInfinity, false }; + yield return new object[] { double.NegativeInfinity, true }; + yield return new object[] { double.MinValue, true }; + yield return new object[] { -MinNormalDouble, true }; + yield return new object[] { -MaxSubnormalDouble, true }; + yield return new object[] { -0.0, true }; + yield return new object[] { double.NaN, true }; + yield return new object[] { 0.0, false }; + yield return new object[] { MaxSubnormalDouble, false }; + yield return new object[] { MinNormalDouble, false }; + yield return new object[] { double.MaxValue, false }; + yield return new object[] { double.PositiveInfinity, false }; } } @@ -738,17 +916,17 @@ public static IEnumerable IsNegativeSingle { get { - yield return new object[] { float.NegativeInfinity, true }; - yield return new object[] { float.MinValue, true }; - yield return new object[] { -MinNormalSingle, true }; - yield return new object[] { -MaxSubnormalSingle, true }; - yield return new object[] { -0.0f, true }; - yield return new object[] { float.NaN, true }; - yield return new object[] { 0.0f, false }; - yield return new object[] { MaxSubnormalSingle, false }; - yield return new object[] { MinNormalSingle, false }; - yield return new object[] { float.MaxValue, false }; - yield return new object[] { float.PositiveInfinity, false }; + yield return new object[] { float.NegativeInfinity, true }; + yield return new object[] { float.MinValue, true }; + yield return new object[] { -MinNormalSingle, true }; + yield return new object[] { -MaxSubnormalSingle, true }; + yield return new object[] { -0.0f, true }; + yield return new object[] { float.NaN, true }; + yield return new object[] { 0.0f, false }; + yield return new object[] { MaxSubnormalSingle, false }; + yield return new object[] { MinNormalSingle, false }; + yield return new object[] { float.MaxValue, false }; + yield return new object[] { float.PositiveInfinity, false }; } } @@ -756,17 +934,17 @@ public static IEnumerable IsPositiveDouble { get { - yield return new object[] { double.NegativeInfinity, false }; - yield return new object[] { double.MinValue, false }; - yield return new object[] { -MinNormalDouble, false }; - yield return new object[] { -MaxSubnormalDouble, false }; - yield return new object[] { -0.0, false }; - yield return new object[] { double.NaN, false }; - yield return new object[] { 0.0, true }; - yield return new object[] { MaxSubnormalDouble, true }; - yield return new object[] { MinNormalDouble, true }; - yield return new object[] { double.MaxValue, true }; - yield return new object[] { double.PositiveInfinity, true }; + yield return new object[] { double.NegativeInfinity, false }; + yield return new object[] { double.MinValue, false }; + yield return new object[] { -MinNormalDouble, false }; + yield return new object[] { -MaxSubnormalDouble, false }; + yield return new object[] { -0.0, false }; + yield return new object[] { double.NaN, false }; + yield return new object[] { 0.0, true }; + yield return new object[] { MaxSubnormalDouble, true }; + yield return new object[] { MinNormalDouble, true }; + yield return new object[] { double.MaxValue, true }; + yield return new object[] { double.PositiveInfinity, true }; } } @@ -774,17 +952,17 @@ public static IEnumerable IsPositiveSingle { get { - yield return new object[] { float.NegativeInfinity, false }; - yield return new object[] { float.MinValue, false }; - yield return new object[] { -MinNormalSingle, false }; - yield return new object[] { -MaxSubnormalSingle, false }; - yield return new object[] { -0.0f, false }; - yield return new object[] { float.NaN, false }; - yield return new object[] { 0.0f, true }; - yield return new object[] { MaxSubnormalSingle, true }; - yield return new object[] { MinNormalSingle, true }; - yield return new object[] { float.MaxValue, true }; - yield return new object[] { float.PositiveInfinity, true }; + yield return new object[] { float.NegativeInfinity, false }; + yield return new object[] { float.MinValue, false }; + yield return new object[] { -MinNormalSingle, false }; + yield return new object[] { -MaxSubnormalSingle, false }; + yield return new object[] { -0.0f, false }; + yield return new object[] { float.NaN, false }; + yield return new object[] { 0.0f, true }; + yield return new object[] { MaxSubnormalSingle, true }; + yield return new object[] { MinNormalSingle, true }; + yield return new object[] { float.MaxValue, true }; + yield return new object[] { float.PositiveInfinity, true }; } } @@ -792,19 +970,19 @@ public static IEnumerable IsPositiveInfinityDouble { get { - yield return new object[] { double.NegativeInfinity, false }; - yield return new object[] { double.MinValue, false }; - yield return new object[] { -MinNormalDouble, false }; - yield return new object[] { -MaxSubnormalDouble, false }; - yield return new object[] { -double.Epsilon, false }; - yield return new object[] { -0.0, false }; - yield return new object[] { double.NaN, false }; - yield return new object[] { 0.0, false }; - yield return new object[] { double.Epsilon, false }; - yield return new object[] { MaxSubnormalDouble, false }; - yield return new object[] { MinNormalDouble, false }; - yield return new object[] { double.MaxValue, false }; - yield return new object[] { double.PositiveInfinity, true }; + yield return new object[] { double.NegativeInfinity, false }; + yield return new object[] { double.MinValue, false }; + yield return new object[] { -MinNormalDouble, false }; + yield return new object[] { -MaxSubnormalDouble, false }; + yield return new object[] { -double.Epsilon, false }; + yield return new object[] { -0.0, false }; + yield return new object[] { double.NaN, false }; + yield return new object[] { 0.0, false }; + yield return new object[] { double.Epsilon, false }; + yield return new object[] { MaxSubnormalDouble, false }; + yield return new object[] { MinNormalDouble, false }; + yield return new object[] { double.MaxValue, false }; + yield return new object[] { double.PositiveInfinity, true }; } } @@ -812,19 +990,19 @@ public static IEnumerable IsPositiveInfinitySingle { get { - yield return new object[] { float.NegativeInfinity, false }; - yield return new object[] { float.MinValue, false }; - yield return new object[] { -MinNormalSingle, false }; - yield return new object[] { -MaxSubnormalSingle, false }; - yield return new object[] { -float.Epsilon, false }; - yield return new object[] { -0.0f, false }; - yield return new object[] { float.NaN, false }; - yield return new object[] { 0.0f, false }; - yield return new object[] { float.Epsilon, false }; - yield return new object[] { MaxSubnormalSingle, false }; - yield return new object[] { MinNormalSingle, false }; - yield return new object[] { float.MaxValue, false }; - yield return new object[] { float.PositiveInfinity, true }; + yield return new object[] { float.NegativeInfinity, false }; + yield return new object[] { float.MinValue, false }; + yield return new object[] { -MinNormalSingle, false }; + yield return new object[] { -MaxSubnormalSingle, false }; + yield return new object[] { -float.Epsilon, false }; + yield return new object[] { -0.0f, false }; + yield return new object[] { float.NaN, false }; + yield return new object[] { 0.0f, false }; + yield return new object[] { float.Epsilon, false }; + yield return new object[] { MaxSubnormalSingle, false }; + yield return new object[] { MinNormalSingle, false }; + yield return new object[] { float.MaxValue, false }; + yield return new object[] { float.PositiveInfinity, true }; } } @@ -832,19 +1010,19 @@ public static IEnumerable IsZeroDouble { get { - yield return new object[] { double.NegativeInfinity, false }; - yield return new object[] { double.MinValue, false }; - yield return new object[] { -MinNormalDouble, false }; - yield return new object[] { -MaxSubnormalDouble, false }; - yield return new object[] { -double.Epsilon, false }; - yield return new object[] { -0.0, true }; - yield return new object[] { double.NaN, false }; - yield return new object[] { 0.0, true }; - yield return new object[] { double.Epsilon, false }; - yield return new object[] { MaxSubnormalDouble, false }; - yield return new object[] { MinNormalDouble, false }; - yield return new object[] { double.MaxValue, false }; - yield return new object[] { double.PositiveInfinity, false }; + yield return new object[] { double.NegativeInfinity, false }; + yield return new object[] { double.MinValue, false }; + yield return new object[] { -MinNormalDouble, false }; + yield return new object[] { -MaxSubnormalDouble, false }; + yield return new object[] { -double.Epsilon, false }; + yield return new object[] { -0.0, true }; + yield return new object[] { double.NaN, false }; + yield return new object[] { 0.0, true }; + yield return new object[] { double.Epsilon, false }; + yield return new object[] { MaxSubnormalDouble, false }; + yield return new object[] { MinNormalDouble, false }; + yield return new object[] { double.MaxValue, false }; + yield return new object[] { double.PositiveInfinity, false }; } } @@ -852,19 +1030,19 @@ public static IEnumerable IsZeroSingle { get { - yield return new object[] { float.NegativeInfinity, false }; - yield return new object[] { float.MinValue, false }; - yield return new object[] { -MinNormalSingle, false }; - yield return new object[] { -MaxSubnormalSingle, false }; - yield return new object[] { -float.Epsilon, false }; - yield return new object[] { -0.0f, true }; - yield return new object[] { float.NaN, false }; - yield return new object[] { 0.0f, true }; - yield return new object[] { float.Epsilon, false }; - yield return new object[] { MaxSubnormalSingle, false }; - yield return new object[] { MinNormalSingle, false }; - yield return new object[] { float.MaxValue, false }; - yield return new object[] { float.PositiveInfinity, false }; + yield return new object[] { float.NegativeInfinity, false }; + yield return new object[] { float.MinValue, false }; + yield return new object[] { -MinNormalSingle, false }; + yield return new object[] { -MaxSubnormalSingle, false }; + yield return new object[] { -float.Epsilon, false }; + yield return new object[] { -0.0f, true }; + yield return new object[] { float.NaN, false }; + yield return new object[] { 0.0f, true }; + yield return new object[] { float.Epsilon, false }; + yield return new object[] { MaxSubnormalSingle, false }; + yield return new object[] { MinNormalSingle, false }; + yield return new object[] { float.MaxValue, false }; + yield return new object[] { float.PositiveInfinity, false }; } } diff --git a/src/libraries/Common/tests/System/IO/StreamSpanExtensions.netstandard.cs b/src/libraries/Common/tests/System/IO/StreamSpanExtensions.netstandard.cs deleted file mode 100644 index e20f0947feec32..00000000000000 --- a/src/libraries/Common/tests/System/IO/StreamSpanExtensions.netstandard.cs +++ /dev/null @@ -1,38 +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.IO; -using System.Threading; -using System.Threading.Tasks; - -/// Extensions to enable the tests to use the span-based Read/Write methods that only exist in netcoreapp. -internal static class StreamSpanExtensions -{ - // These implementations are inefficient and are just for testing purposes. - - public static int Read(this Stream stream, Span destination) - { - byte[] array = new byte[destination.Length]; - int bytesRead = stream.Read(array, 0, array.Length); - new Span(array, 0, bytesRead).CopyTo(destination); - return bytesRead; - } - - public static void Write(this Stream stream, ReadOnlySpan source) => - stream.Write(source.ToArray(), 0, source.Length); - - public static ValueTask ReadAsync(this Stream stream, Memory destination, CancellationToken cancellationToken = default(CancellationToken)) - { - byte[] array = new byte[destination.Length]; - return new ValueTask(stream.ReadAsync(array, 0, array.Length, cancellationToken).ContinueWith(t => - { - int bytesRead = t.GetAwaiter().GetResult(); - new Span(array, 0, bytesRead).CopyTo(destination.Span); - return bytesRead; - })); - } - - public static Task WriteAsync(this Stream stream, ReadOnlyMemory source, CancellationToken cancellationToken = default(CancellationToken)) => - stream.WriteAsync(source.ToArray(), 0, source.Length, cancellationToken); -} diff --git a/src/libraries/Common/tests/System/Net/Http/DefaultCredentialsTest.cs b/src/libraries/Common/tests/System/Net/Http/DefaultCredentialsTest.cs index e51991b0cb21e1..169062d4c486b6 100644 --- a/src/libraries/Common/tests/System/Net/Http/DefaultCredentialsTest.cs +++ b/src/libraries/Common/tests/System/Net/Http/DefaultCredentialsTest.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.IO; using System.Security.Principal; using System.Threading.Tasks; diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.RemoteServer.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.RemoteServer.cs index f01e2a59c29c7a..ac8abebe5d4bb2 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.RemoteServer.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.RemoteServer.cs @@ -70,7 +70,7 @@ public async Task UseDefaultCredentials_SetToFalseAndServerNeedsAuth_StatusCodeU handler.UseDefaultCredentials = false; using (HttpClient client = CreateHttpClient(handler)) { - Uri uri = Configuration.Http.RemoteHttp11Server.NegotiateAuthUriForDefaultCreds; + Uri uri = Configuration.Http.RemoteSecureHttp11Server.NegotiateAuthUriForDefaultCreds; _output.WriteLine("Uri: {0}", uri); using (HttpResponseMessage response = await client.GetAsync(uri)) { @@ -602,9 +602,9 @@ public async Task PostAsync_CallMethod_EmptyContent(Configuration.Http.RemoteSer public static IEnumerable ExpectContinueVersion() { return - from expect in new bool?[] {true, false, null} - from version in new Version[] {new Version(1, 0), new Version(1, 1), new Version(2, 0)} - select new object[] {expect, version}; + from expect in new bool?[] { true, false, null } + from version in new Version[] { new Version(1, 0), new Version(1, 1), new Version(2, 0) } + select new object[] { expect, version }; } [OuterLoop("Uses external servers", typeof(PlatformDetection), nameof(PlatformDetection.LocalEchoServerIsNotAvailable))] @@ -776,7 +776,8 @@ public async Task SendAsync_SendRequestUsingMethodToEchoServerWithNoContent_Meth { var request = new HttpRequestMessage( new HttpMethod(method), - serverUri) { Version = UseVersion }; + serverUri) + { Version = UseVersion }; using (HttpResponseMessage response = await client.SendAsync(TestAsync, request)) { @@ -802,7 +803,8 @@ public async Task SendAsync_SendRequestUsingMethodToEchoServerWithContent_Succes { var request = new HttpRequestMessage( new HttpMethod(method), - serverUri) { Version = UseVersion }; + serverUri) + { Version = UseVersion }; request.Content = new StringContent(ExpectedContent); using (HttpResponseMessage response = await client.SendAsync(TestAsync, request)) { @@ -981,6 +983,7 @@ public async Task GetAsync_AllowAutoRedirectTrue_RedirectFromHttpToHttp_StatusCo [OuterLoop("Uses external servers")] [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/55083", TestPlatforms.Browser)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/110578")] public async Task GetAsync_AllowAutoRedirectTrue_RedirectFromHttpToHttps_StatusCodeOK() { HttpClientHandler handler = CreateHttpClientHandler(); @@ -1065,9 +1068,9 @@ public async Task GetAsync_MaxAutomaticRedirectionsNServerHops_ThrowsIfTooMany(i handler.MaxAutomaticRedirections = maxHops; using (HttpClient client = CreateHttpClient(handler)) { - Task t = client.GetAsync(Configuration.Http.RemoteHttp11Server.RedirectUriForDestinationUri( + Task t = client.GetAsync(Configuration.Http.RemoteSecureHttp11Server.RedirectUriForDestinationUri( statusCode: 302, - destinationUri: Configuration.Http.RemoteHttp11Server.EchoUri, + destinationUri: Configuration.Http.RemoteSecureHttp11Server.EchoUri, hops: hops)); if (hops <= maxHops) @@ -1075,7 +1078,7 @@ public async Task GetAsync_MaxAutomaticRedirectionsNServerHops_ThrowsIfTooMany(i using (HttpResponseMessage response = await t) { Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Equal(Configuration.Http.RemoteEchoServer, response.RequestMessage.RequestUri); + Assert.Equal(Configuration.Http.SecureRemoteEchoServer, response.RequestMessage.RequestUri); } } else diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ServerCertificates.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ServerCertificates.cs index 4dc2eb3fcfdeaf..95ba0752a5daa4 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ServerCertificates.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ServerCertificates.cs @@ -97,6 +97,7 @@ public async Task NoCallback_ValidCertificate_SuccessAndExpectedPropertyBehavior [OuterLoop("Uses external servers")] [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/110578")] public async Task UseCallback_NotSecureConnection_CallbackNotCalled() { HttpClientHandler handler = CreateHttpClientHandler(); diff --git a/src/libraries/Common/tests/System/Net/StreamArrayExtensions.cs b/src/libraries/Common/tests/System/Net/StreamArrayExtensions.cs deleted file mode 100644 index 1a8d1bcf61f2b4..00000000000000 --- a/src/libraries/Common/tests/System/Net/StreamArrayExtensions.cs +++ /dev/null @@ -1,35 +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.IO; -using System.Runtime.InteropServices; -using System.Threading; -using System.Threading.Tasks; -using Xunit; - -namespace System.Net -{ - public static class StreamArrayExtensions - { - public static ValueTask WriteAsync(this Stream stream, ReadOnlyMemory memory) - { - bool isArray = MemoryMarshal.TryGetArray(memory, out ArraySegment segment); - Assert.True(isArray); - - return new ValueTask(stream.WriteAsync(segment.Array, segment.Offset, segment.Count)); - } - - public static ValueTask WriteAsync(this StreamWriter writer, string text) - { - return new ValueTask(writer.WriteAsync(text.ToCharArray(), 0, text.Length)); - } - - public static ValueTask ReadAsync(this Stream stream, ReadOnlyMemory buffer, CancellationToken cancellationToken) - { - bool isArray = MemoryMarshal.TryGetArray(buffer, out ArraySegment segment); - Assert.True(isArray); - - return new ValueTask(stream.ReadAsync(segment.Array, segment.Offset, segment.Count, cancellationToken)); - } - } -} diff --git a/src/libraries/Common/tests/Tests/System/Net/ArrayBufferTests.cs b/src/libraries/Common/tests/Tests/System/Net/ArrayBufferTests.cs new file mode 100644 index 00000000000000..2294a166581a8e --- /dev/null +++ b/src/libraries/Common/tests/Tests/System/Net/ArrayBufferTests.cs @@ -0,0 +1,227 @@ +// 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.Net; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Xunit; + +namespace Tests.System.Net +{ + public sealed class ArrayBufferTests + { + private static void AssertInvariants(ArrayBuffer buffer) + { + byte[]? bytes = buffer.DangerousGetUnderlyingBuffer(); + + if (bytes is null) + { + Assert.Equal(0, buffer.ActiveStartOffset); + Assert.Equal(0, buffer.ActiveLength); + Assert.Throws(() => buffer.Capacity); + } + else + { + Assert.Equal(bytes.Length, buffer.Capacity); + + Assert.True(buffer.ActiveLength >= 0); + Assert.True(buffer.AvailableLength >= 0); + Assert.True(buffer.AvailableLength <= bytes.Length); + + int availableOffset = bytes.Length - buffer.AvailableLength; + int activeOffset = buffer.ActiveStartOffset; + + Assert.True(availableOffset >= 0); + Assert.True(activeOffset >= 0); + Assert.True(availableOffset >= activeOffset); + Assert.Equal(availableOffset - activeOffset, buffer.ActiveLength); + + Assert.Equal(bytes.Length - availableOffset, buffer.AvailableLength); + Assert.Equal(buffer.AvailableLength, buffer.AvailableSpan.Length); + Assert.Equal(buffer.AvailableLength, buffer.AvailableMemory.Length); + + Assert.Equal(buffer.ActiveLength, buffer.ActiveSpan.Length); + Assert.Equal(buffer.ActiveLength, buffer.ActiveMemory.Length); + + ref byte expectedAvailableRef = ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(bytes), availableOffset); + Assert.True(Unsafe.AreSame(ref expectedAvailableRef, ref MemoryMarshal.GetReference(buffer.AvailableSpan))); + Assert.True(Unsafe.AreSame(ref expectedAvailableRef, ref MemoryMarshal.GetReference(buffer.AvailableMemory.Span))); + + ref byte expectedActiveRef = ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(bytes), activeOffset); + Assert.True(Unsafe.AreSame(ref expectedActiveRef, ref MemoryMarshal.GetReference(buffer.ActiveSpan))); + Assert.True(Unsafe.AreSame(ref expectedActiveRef, ref MemoryMarshal.GetReference(buffer.ActiveMemory.Span))); + } + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void BasicTest(bool usePool) + { + AssertInvariants(default); + + var buffer = new ArrayBuffer(32, usePool); + AssertInvariants(buffer); + + Assert.Equal(32, buffer.Capacity); + buffer.AvailableSpan[0] = 42; + buffer.Commit(1); + Assert.Equal(new byte[] { 42 }, buffer.ActiveSpan); + AssertInvariants(buffer); + + buffer.EnsureAvailableSpace(32); + Assert.Equal(64, buffer.Capacity); + Assert.Equal(new byte[] { 42 }, buffer.ActiveSpan); + AssertInvariants(buffer); + + buffer.AvailableSpan.Fill(43); + buffer.AvailableSpan[^2] = 44; + buffer.Commit(buffer.AvailableLength - 1); + AssertInvariants(buffer); + + buffer.Discard(1); + Assert.Equal(62, buffer.ActiveLength); + Assert.Equal(1, buffer.ActiveStartOffset); + Assert.Equal(44, buffer.ActiveSpan[^1]); + Assert.Equal(61, buffer.ActiveSpan.IndexOfAnyExcept((byte)43)); + AssertInvariants(buffer); + + // We shift the contents instead of resizing the buffer + Assert.Equal(1, buffer.AvailableLength); + buffer.EnsureAvailableSpace(2); + Assert.Equal(2, buffer.AvailableLength); + Assert.Equal(64, buffer.Capacity); + Assert.Equal(62, buffer.ActiveLength); + Assert.Equal(0, buffer.ActiveStartOffset); + AssertInvariants(buffer); + + buffer.Discard(1); + Assert.Equal(1, buffer.ActiveStartOffset); + AssertInvariants(buffer); + + buffer.EnsureAvailableSpace(4); + Assert.Equal(128, buffer.Capacity); + Assert.Equal(67, buffer.AvailableLength); + Assert.Equal(0, buffer.ActiveStartOffset); + AssertInvariants(buffer); + + buffer.EnsureAvailableSpace(500); + Assert.Equal(usePool ? 1024 : 500 + buffer.ActiveLength, buffer.Capacity); + AssertInvariants(buffer); + + Assert.Equal(61, buffer.ActiveLength); + Assert.Equal(44, buffer.ActiveSpan[^1]); + Assert.Equal(60, buffer.ActiveSpan.IndexOfAnyExcept((byte)43)); + + buffer.Commit(buffer.AvailableLength); + buffer.EnsureAvailableSpace(0); + Assert.Equal(0, buffer.AvailableLength); + AssertInvariants(buffer); + + if (usePool) + { + buffer.ClearAndReturnBuffer(); + AssertInvariants(buffer); + + buffer.EnsureAvailableSpace(42); + Assert.Equal(64, buffer.Capacity); + AssertInvariants(buffer); + } + + buffer.Dispose(); + AssertInvariants(buffer); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void AddByteByByteAndConsumeByteByByte_Success(bool usePool) + { + const int Size = 64 * 1024 + 1; + + using ArrayBuffer buffer = new(42, usePool); + + for (int i = 0; i < Size; i++) + { + buffer.EnsureAvailableSpace(1); + buffer.AvailableSpan[0] = (byte)i; + buffer.Commit(1); + AssertInvariants(buffer); + } + + for (int i = 0; i < Size; i++) + { + Assert.Equal((byte)i, buffer.ActiveSpan[0]); + buffer.Discard(1); + AssertInvariants(buffer); + } + + Assert.Equal(0, buffer.ActiveLength); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void AddSeveralBytesRepeatedlyAndConsumeSeveralBytesRepeatedly_Success(bool usePool) + { + const int ByteCount = 7; + const int RepeatCount = 8 * 1024; + + using ArrayBuffer buffer = new(42, usePool); + + for (int i = 0; i < RepeatCount; i++) + { + buffer.EnsureAvailableSpace(ByteCount); + for (int j = 0; j < ByteCount; j++) + { + buffer.AvailableSpan[j] = (byte)(j + 1); + } + buffer.Commit(ByteCount); + AssertInvariants(buffer); + } + + for (int i = 0; i < RepeatCount; i++) + { + for (int j = 0; j < ByteCount; j++) + { + Assert.Equal(j + 1, buffer.ActiveSpan[j]); + } + buffer.Discard(ByteCount); + AssertInvariants(buffer); + } + + Assert.Equal(0, buffer.ActiveLength); + } + + [OuterLoop] + [ConditionalTheory(typeof(Environment), nameof(Environment.Is64BitProcess))] + [InlineData(true)] + [InlineData(false)] + public void CanResizeToMaxArraySize(bool usePool) + { + using var buffer = new ArrayBuffer(42, usePool); + + while (buffer.Capacity < Array.MaxLength) + { + buffer.EnsureAvailableSpace(1); + buffer.Commit(buffer.AvailableLength); + AssertInvariants(buffer); + } + + Assert.Equal(Array.MaxLength, buffer.Capacity); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void ExceedMaximumBufferSize_Throws(bool usePool) + { + using var buffer = new ArrayBuffer(42, usePool); + Assert.Throws(() => buffer.EnsureAvailableSpace(int.MaxValue)); + + buffer.Commit(1); + Assert.Throws(() => buffer.EnsureAvailableSpace(Array.MaxLength)); + } + } +} diff --git a/src/libraries/Fuzzing/DotnetFuzzing/Assert.cs b/src/libraries/Fuzzing/DotnetFuzzing/Assert.cs index 2814de3f08bf49..9f260440cc4764 100644 --- a/src/libraries/Fuzzing/DotnetFuzzing/Assert.cs +++ b/src/libraries/Fuzzing/DotnetFuzzing/Assert.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace DotnetFuzzing; internal static class Assert @@ -18,6 +20,12 @@ static void Throw(T expected, T actual) => throw new Exception($"Expected={expected} Actual={actual}"); } + public static void True([DoesNotReturnIf(false)] bool actual) => + Equal(true, actual); + + public static void False([DoesNotReturnIf(true)] bool actual) => + Equal(false, actual); + public static void NotNull(T value) { if (value == null) @@ -26,7 +34,7 @@ public static void NotNull(T value) } static void ThrowNull() => - throw new Exception("Value is null"); + throw new Exception("Value is null"); } public static void SequenceEqual(ReadOnlySpan expected, ReadOnlySpan actual) diff --git a/src/libraries/Fuzzing/DotnetFuzzing/DotnetFuzzing.csproj b/src/libraries/Fuzzing/DotnetFuzzing/DotnetFuzzing.csproj index a392983c364e9f..195dc8d04ff993 100644 --- a/src/libraries/Fuzzing/DotnetFuzzing/DotnetFuzzing.csproj +++ b/src/libraries/Fuzzing/DotnetFuzzing/DotnetFuzzing.csproj @@ -22,6 +22,7 @@ + diff --git a/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/IPAddressFuzzer.cs b/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/IPAddressFuzzer.cs new file mode 100644 index 00000000000000..fd7df5fb9c29e3 --- /dev/null +++ b/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/IPAddressFuzzer.cs @@ -0,0 +1,107 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Buffers; +using System.Net; +using System.Net.Sockets; +using System.Runtime.InteropServices; +using System.Text; +using System.Text.Unicode; + +namespace DotnetFuzzing.Fuzzers +{ + internal sealed class IPAddressFuzzer : IFuzzer + { + public string[] TargetAssemblies => ["System.Net.Primitives", "System.Private.Uri"]; + public string[] TargetCoreLibPrefixes => []; + + public void FuzzTarget(ReadOnlySpan bytes) + { + using var poisonedBytes = PooledBoundedMemory.Rent(bytes, PoisonPagePlacement.After); + using var poisonedChars = PooledBoundedMemory.Rent(MemoryMarshal.Cast(bytes), PoisonPagePlacement.After); + + if (IPAddress.IsValidUtf8(poisonedBytes.Span)) + { + TestValidInput(bytes: poisonedBytes.Span); + } + else + { + Assert.False(IPAddress.TryParse(poisonedBytes.Span, out _)); + } + + if (IPAddress.IsValid(poisonedChars.Span)) + { + TestValidInput(chars: poisonedChars.Span.ToString()); + } + else + { + Assert.False(IPAddress.TryParse(poisonedChars.Span, out _)); + } + + static void TestValidInput(ReadOnlySpan bytes = default, string? chars = null) + { + if (chars is null) + { + // bytes past the '%' may not be valid UTF-8: https://github.com/dotnet/runtime/issues/111288 + int percentIndex = bytes.IndexOf((byte)'%'); + Assert.True(Utf8.IsValid(bytes.Slice(0, percentIndex < 0 ? bytes.Length : percentIndex))); + + chars = Encoding.UTF8.GetString(bytes); + } + else + { + bytes = Encoding.UTF8.GetBytes(chars); + } + + Assert.True(IPAddress.IsValid(chars)); + Assert.True(IPAddress.TryParse(chars, out IPAddress? ipFromChars)); + Assert.True(IPAddress.TryParse(bytes, out IPAddress? ipFromBytes)); + + Assert.True(ipFromChars.Equals(ipFromBytes)); + Assert.True(ipFromBytes.Equals(ipFromChars)); + + Assert.True(IPAddress.IsValid(ipFromChars.ToString())); + + TestUri(chars); + } + + static void TestUri(string chars) + { + bool isIpv6 = chars.Contains(':'); + UriHostNameType hostNameType = isIpv6 ? UriHostNameType.IPv6 : UriHostNameType.IPv4; + + if (isIpv6) + { + // Remove the ScopeId + int percentIndex = chars.IndexOf('%'); + if (percentIndex >= 0) + { + chars = chars.Substring(0, percentIndex); + if (chars.StartsWith('[')) + { + chars = $"{chars}]"; + } + } + + if (!chars.StartsWith('[')) + { + chars = $"[{chars}]"; + } + + // Remove the port + int bracketIndex = chars.IndexOf(']'); + if (bracketIndex >= 0 && + bracketIndex + 1 < chars.Length && + chars[bracketIndex + 1] == ':') + { + chars = chars.Substring(0, bracketIndex + 1); + } + } + + Assert.True(Uri.TryCreate($"http://{chars}/", UriKind.Absolute, out Uri? uri)); + Assert.Equal(hostNameType, uri.HostNameType); + Assert.Equal(hostNameType, Uri.CheckHostName(chars)); + } + } + } +} diff --git a/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/Utf8JsonWriterFuzzer.cs b/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/Utf8JsonWriterFuzzer.cs index 767821bcf875b1..5600ce7c357a00 100644 --- a/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/Utf8JsonWriterFuzzer.cs +++ b/src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/Utf8JsonWriterFuzzer.cs @@ -3,6 +3,7 @@ using System; using System.Buffers; +using System.Buffers.Text; using System.Collections; using System.Collections.Generic; using System.Diagnostics; @@ -33,8 +34,11 @@ internal sealed class Utf8JsonWriterFuzzer : IFuzzer private const byte NewLineFlag = 1 << 3; private const byte SkipValidationFlag = 1 << 4; - // Options for choosing between UTF-8 and UTF-16 encoding - private const byte EncodingFlag = 1 << 5; + // Options for choosing between base64, UTF-8 and UTF-16 encoding + private const byte EncodingMask = 0b11 << 5; + private const byte Utf8EncodingFlag = 0b00 << 5; + private const byte Utf16EncodingFlag = 0b01 << 5; + private const byte Base64EncodingFlag = 0b10 << 5; public void FuzzTarget(ReadOnlySpan bytes) { @@ -53,8 +57,13 @@ public void FuzzTarget(ReadOnlySpan bytes) ReadOnlySpan chars = MemoryMarshal.Cast(bytes); // Validate that the indices are within bounds of the input - bool utf8 = (optionsByte & EncodingFlag) == 0; - if (!(0 <= slice1 && slice1 <= slice2 && slice2 <= (utf8 ? bytes.Length : chars.Length))) + int encoding = optionsByte & EncodingMask; + if (encoding is not Utf8EncodingFlag and not Utf16EncodingFlag and not Base64EncodingFlag) + { + return; + } + + if (!(0 <= slice1 && slice1 <= slice2 && slice2 <= (encoding is Utf16EncodingFlag ? chars.Length : bytes.Length))) { return; } @@ -63,7 +72,7 @@ public void FuzzTarget(ReadOnlySpan bytes) bool indented = (optionsByte & IndentFlag) == 0; JsonWriterOptions options = new() { - Encoder = (optionsByte & EncodingFlag) == 0 ? JavaScriptEncoder.Default : JavaScriptEncoder.UnsafeRelaxedJsonEscaping, + Encoder = (optionsByte & EncoderFlag) == 0 ? JavaScriptEncoder.Default : JavaScriptEncoder.UnsafeRelaxedJsonEscaping, Indented = indented, MaxDepth = (optionsByte & MaxDepthFlag) == 0 ? 1 : 0, NewLine = (optionsByte & NewLineFlag) == 0 ? "\n" : "\r\n", @@ -74,9 +83,9 @@ public void FuzzTarget(ReadOnlySpan bytes) int maxExpandedSizeBytes = 6 * bytes.Length + 2; byte[] expectedBuffer = ArrayPool.Shared.Rent(maxExpandedSizeBytes); Span expected = - expectedBuffer.AsSpan(0, utf8 - ? EncodeToUtf8(bytes, expectedBuffer, options.Encoder) - : EncodeToUtf8(chars, expectedBuffer, options.Encoder)); + expectedBuffer.AsSpan(0, encoding == Utf16EncodingFlag + ? EncodeToUtf8(chars, expectedBuffer, options.Encoder) + : EncodeToUtf8(bytes, expectedBuffer, options.Encoder, encoding == Base64EncodingFlag)); // Compute the actual result by using Utf8JsonWriter. Each iteration is a different slice of the input, but the result should be the same. byte[] actualBuffer = new byte[expected.Length]; @@ -89,14 +98,14 @@ public void FuzzTarget(ReadOnlySpan bytes) { using MemoryStream stream = new(actualBuffer); using Utf8JsonWriter writer = new(stream, options); - - if (utf8) + + if (encoding == Utf16EncodingFlag) { - WriteStringValueSegments(writer, bytes, ranges); + WriteStringValueSegments(writer, chars, ranges); } else { - WriteStringValueSegments(writer, chars, ranges); + WriteStringValueSegments(writer, bytes, ranges, encoding == Base64EncodingFlag); } writer.Flush(); @@ -110,7 +119,7 @@ public void FuzzTarget(ReadOnlySpan bytes) } // Additional test for mixing UTF-8 and UTF-16 encoding. The alignment math is easier in UTF-16 mode so just run it for that. - if (!utf8) + if (encoding == Utf16EncodingFlag) { Array.Clear(expectedBuffer); @@ -124,9 +133,16 @@ public void FuzzTarget(ReadOnlySpan bytes) using MemoryStream stream = new(actualBuffer); using Utf8JsonWriter writer = new(stream, options); + // UTF-16 + UTF-8 writer.WriteStringValueSegment(firstSegment, false); - Assert.Throws>(state => writer.WriteStringValueSegment(state, true), secondSegment); + + stream.Position = 0; + writer.Reset(); + + // UTF-16 + Base64 + writer.WriteStringValueSegment(firstSegment, false); + Assert.Throws>(state => writer.WriteBase64StringSegment(state, true), secondSegment); } Array.Clear(expectedBuffer); @@ -135,25 +151,67 @@ public void FuzzTarget(ReadOnlySpan bytes) ReadOnlySpan firstSegment = bytes[0..(2 * slice1)]; ReadOnlySpan secondSegment = chars[slice1..]; - expected = expectedBuffer.AsSpan(0, EncodeToUtf8(firstSegment, secondSegment, expectedBuffer, options.Encoder)); + expected = expectedBuffer.AsSpan(0, EncodeToUtf8(firstSegment, expectedBuffer, options.Encoder, base64Encode: false)); actualBuffer = new byte[expected.Length]; using MemoryStream stream = new(actualBuffer); using Utf8JsonWriter writer = new(stream, options); + // UTF-8 + UTF-16 writer.WriteStringValueSegment(firstSegment, false); Assert.Throws>(state => writer.WriteStringValueSegment(state, true), secondSegment); + + stream.Position = 0; + writer.Reset(); + + // UTF-8 + Base64 + writer.WriteStringValueSegment(firstSegment, false); + Assert.Throws>(state => writer.WriteBase64StringSegment(state, true), MemoryMarshal.AsBytes(secondSegment)); + } + + Array.Clear(expectedBuffer); + + { + ReadOnlySpan firstSegment = bytes[0..(2 * slice1)]; + ReadOnlySpan secondSegment = chars[slice1..]; + + expected = expectedBuffer.AsSpan(0, EncodeToUtf8(firstSegment, expectedBuffer, options.Encoder, base64Encode: true)); + + actualBuffer = new byte[expected.Length]; + using MemoryStream stream = new(actualBuffer); + using Utf8JsonWriter writer = new(stream, options); + + // Base64 + UTF-16 + writer.WriteBase64StringSegment(firstSegment, false); + Assert.Throws>(state => writer.WriteStringValueSegment(state, true), secondSegment); + + stream.Position = 0; + writer.Reset(); + + // Base64 + UTF-8 + writer.WriteBase64StringSegment(firstSegment, false); + Assert.Throws>(state => writer.WriteStringValueSegment(state, true), MemoryMarshal.AsBytes(secondSegment)); } } ArrayPool.Shared.Return(expectedBuffer); } - private static void WriteStringValueSegments(Utf8JsonWriter writer, ReadOnlySpan bytes, ReadOnlySpan ranges) + private static void WriteStringValueSegments(Utf8JsonWriter writer, ReadOnlySpan bytes, ReadOnlySpan ranges, bool base64Encode) { - for (int i = 0; i < ranges.Length; i++) + if (base64Encode) + { + for (int i = 0; i < ranges.Length; i++) + { + writer.WriteBase64StringSegment(bytes[ranges[i]], i == ranges.Length - 1); + } + } + else { - writer.WriteStringValueSegment(bytes[ranges[i]], i == ranges.Length - 1); + for (int i = 0; i < ranges.Length; i++) + { + writer.WriteStringValueSegment(bytes[ranges[i]], i == ranges.Length - 1); + } } } @@ -165,10 +223,20 @@ private static void WriteStringValueSegments(Utf8JsonWriter writer, ReadOnlySpan } } - private static int EncodeToUtf8(ReadOnlySpan bytes, Span destBuffer, JavaScriptEncoder encoder) + private static int EncodeToUtf8(ReadOnlySpan bytes, Span destBuffer, JavaScriptEncoder encoder, bool base64Encode) { destBuffer[0] = (byte)'"'; - encoder.EncodeUtf8(bytes, destBuffer[1..], out _, out int written, isFinalBlock: true); + + int written; + if (base64Encode) + { + Base64.EncodeToUtf8(bytes, destBuffer[1..], out _, out written, isFinalBlock: true); + } + else + { + encoder.EncodeUtf8(bytes, destBuffer[1..], out _, out written, isFinalBlock: true); + } + destBuffer[++written] = (byte)'"'; return written + 1; } @@ -181,27 +249,6 @@ private static int EncodeToUtf8(ReadOnlySpan chars, Span destBuffer, return written + 1; } - private static int EncodeToUtf8(ReadOnlySpan bytes, ReadOnlySpan chars, Span destBuffer, JavaScriptEncoder encoder) - { - int written = 1; - destBuffer[0] = (byte)'"'; - encoder.EncodeUtf8(bytes, destBuffer[1..], out _, out int writtenTemp, isFinalBlock: true); - written += writtenTemp; - destBuffer[written += EncodeTranscode(chars, destBuffer[written..], encoder, isFinalBlock: true)] = (byte)'"'; - return written + 1; - } - - private static int EncodeToUtf8(ReadOnlySpan chars, ReadOnlySpan bytes, Span destBuffer, JavaScriptEncoder encoder) - { - int written = 1; - destBuffer[0] = (byte)'"'; - written += EncodeTranscode(chars, destBuffer[1..], encoder, isFinalBlock: true); - encoder.EncodeUtf8(bytes, destBuffer[written..], out _, out int writtenTemp, isFinalBlock: true); - written += writtenTemp; - destBuffer[written] = (byte)'"'; - return written + 1; - } - private static int EncodeTranscode(ReadOnlySpan chars, Span destBuffer, JavaScriptEncoder encoder, bool isFinalBlock = true) { var utf16buffer = ArrayPool.Shared.Rent(6 * chars.Length); diff --git a/src/libraries/Fuzzing/DotnetFuzzing/Program.cs b/src/libraries/Fuzzing/DotnetFuzzing/Program.cs index a2e0f4d6e60a4f..243fd25f954766 100644 --- a/src/libraries/Fuzzing/DotnetFuzzing/Program.cs +++ b/src/libraries/Fuzzing/DotnetFuzzing/Program.cs @@ -110,15 +110,33 @@ await DownloadArtifactAsync( "https://github.com/Metalnem/libfuzzer-dotnet/releases/download/v2023.06.26.1359/libfuzzer-dotnet-windows.exe", "cbc1f510caaec01b17b5e89fc780f426710acee7429151634bbf4d0c57583458").ConfigureAwait(false); - foreach (IFuzzer fuzzer in fuzzers) + Console.WriteLine("Preparing fuzzers ..."); + + List exceptions = new(); + + Parallel.ForEach(fuzzers, fuzzer => { - Console.WriteLine(); - Console.WriteLine($"Preparing {fuzzer.Name} ..."); + try + { + PrepareFuzzer(fuzzer); + } + catch (Exception ex) + { + exceptions.Add($"Failed to prepare {fuzzer.Name}: {ex.Message}"); + } + }); + if (exceptions.Count != 0) + { + Console.WriteLine(string.Join('\n', exceptions)); + throw new Exception($"Failed to prepare {exceptions.Count} fuzzers."); + } + + void PrepareFuzzer(IFuzzer fuzzer) + { string fuzzerDirectory = Path.Combine(outputDirectory, fuzzer.Name); Directory.CreateDirectory(fuzzerDirectory); - Console.WriteLine($"Copying artifacts to {fuzzerDirectory}"); // NOTE: The expected fuzzer directory structure is currently flat. // If we ever need to support subdirectories, OneFuzzConfig.json must also be updated to use PreservePathsJobDependencies. foreach (string file in Directory.GetFiles(publishDirectory)) @@ -138,10 +156,7 @@ await DownloadArtifactAsync( InstrumentAssemblies(fuzzer, fuzzerDirectory); - Console.WriteLine("Generating OneFuzzConfig.json"); File.WriteAllText(Path.Combine(fuzzerDirectory, "OneFuzzConfig.json"), GenerateOneFuzzConfigJson(fuzzer)); - - Console.WriteLine("Generating local-run.bat"); File.WriteAllText(Path.Combine(fuzzerDirectory, "local-run.bat"), GenerateLocalRunHelperScript(fuzzer)); } @@ -195,8 +210,6 @@ private static void InstrumentAssemblies(IFuzzer fuzzer, string fuzzerDirectory) { foreach (var (assembly, prefixes) in GetInstrumentationTargets(fuzzer)) { - Console.WriteLine($"Instrumenting {assembly} {(prefixes is null ? "" : $"({prefixes})")}"); - string path = Path.Combine(fuzzerDirectory, assembly); if (!File.Exists(path)) { diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/tests/Microsoft.Extensions.DependencyModel.Tests.csproj b/src/libraries/Microsoft.Extensions.DependencyModel/tests/Microsoft.Extensions.DependencyModel.Tests.csproj index 7717367bbbbe14..70fd9e556fb285 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/tests/Microsoft.Extensions.DependencyModel.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.DependencyModel/tests/Microsoft.Extensions.DependencyModel.Tests.csproj @@ -18,4 +18,7 @@ + + + diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/JsonConsoleFormatter.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/JsonConsoleFormatter.cs index 1be9425aa310b8..6dd794b05a02eb 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/JsonConsoleFormatter.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/JsonConsoleFormatter.cs @@ -96,7 +96,7 @@ private void WriteInternal(IExternalScopeProvider? scopeProvider, TextWriter tex writer.Flush(); } - var messageBytes = output.WrittenMemory.Span; + var messageBytes = output.WrittenSpan; var logMessageBuffer = ArrayPool.Shared.Rent(Encoding.UTF8.GetMaxCharCount(messageBytes.Length)); try { diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/Microsoft.Extensions.Logging.Console.csproj b/src/libraries/Microsoft.Extensions.Logging.Console/src/Microsoft.Extensions.Logging.Console.csproj index bb9145aaab774d..217bfaed0470f8 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/Microsoft.Extensions.Logging.Console.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/Microsoft.Extensions.Logging.Console.csproj @@ -17,6 +17,7 @@ + @@ -29,6 +30,7 @@ + diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/Resources/Strings.resx b/src/libraries/Microsoft.Extensions.Logging.Console/src/Resources/Strings.resx index 8d925d89baf50f..1513cb7b8224bc 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/Resources/Strings.resx +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/Resources/Strings.resx @@ -117,9 +117,6 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Cannot allocate a buffer of size {0}. - {0} is not a supported queue mode value. diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Container.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Container.cs index 3c32c1ee6a3f67..c0058edd936430 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Container.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Container.cs @@ -223,16 +223,19 @@ protected virtual void ValidateName(IComponent component, string? name) if (name != null) { - for (int i = 0; i < Math.Min(_siteCount, _sites!.Length); i++) + lock (_syncObj) { - ISite? s = _sites[i]; - - if (s?.Name != null && string.Equals(s.Name, name, StringComparison.OrdinalIgnoreCase) && s.Component != component) + for (int i = 0; i < Math.Min(_siteCount, _sites!.Length); i++) { - InheritanceAttribute inheritanceAttribute = (InheritanceAttribute)TypeDescriptor.GetAttributes(s.Component)[typeof(InheritanceAttribute)]!; - if (inheritanceAttribute.InheritanceLevel != InheritanceLevel.InheritedReadOnly) + ISite? s = _sites[i]; + + if (s?.Name != null && string.Equals(s.Name, name, StringComparison.OrdinalIgnoreCase) && s.Component != component) { - throw new ArgumentException(SR.Format(SR.DuplicateComponentName, name)); + InheritanceAttribute inheritanceAttribute = (InheritanceAttribute)TypeDescriptor.GetAttributes(s.Component)[typeof(InheritanceAttribute)]!; + if (inheritanceAttribute.InheritanceLevel != InheritanceLevel.InheritedReadOnly) + { + throw new ArgumentException(SR.Format(SR.DuplicateComponentName, name)); + } } } } diff --git a/src/libraries/System.Console/src/System/ConsolePal.Unix.cs b/src/libraries/System.Console/src/System/ConsolePal.Unix.cs index e7acb0e850400c..98aca9d7ef698b 100644 --- a/src/libraries/System.Console/src/System/ConsolePal.Unix.cs +++ b/src/libraries/System.Console/src/System/ConsolePal.Unix.cs @@ -885,6 +885,9 @@ private static unsafe void EnsureInitializedCore() { throw new Win32Exception(); } + // InitializeTerminalAndSignalHandling will reset the terminal on a normal exit. + // This also resets it for termination due to an unhandled exception. + AppDomain.CurrentDomain.UnhandledException += (_, _) => { Interop.Sys.UninitializeTerminal(); }; s_terminalHandle = !Console.IsOutputRedirected ? Interop.Sys.FileDescriptors.STDOUT_FILENO : !Console.IsInputRedirected ? Interop.Sys.FileDescriptors.STDIN_FILENO : diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs index b408cead906853..e7d36273408355 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs @@ -1233,7 +1233,9 @@ internal static Activity Create(ActivitySource source, string name, ActivityKind activity._parentSpanId = parentContext.SpanId.ToString(); } - activity.ActivityTraceFlags = parentContext.TraceFlags; + // Note: Don't inherit Recorded from parent as it is set below + // based on sampling decision + activity.ActivityTraceFlags = parentContext.TraceFlags & ~ActivityTraceFlags.Recorded; activity._parentTraceFlags = (byte)parentContext.TraceFlags; activity.HasRemoteParent = parentContext.IsRemote; } diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivitySourceTests.cs b/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivitySourceTests.cs index 86227dc2e74275..5870822e5b03ad 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivitySourceTests.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivitySourceTests.cs @@ -256,7 +256,7 @@ public void TestListeningToConstructedActivityEvents() } [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] - public void EnsureRecordingTest() + public void AllDataAndRecordedSamplingTest() { RemoteExecutor.Invoke(() => { Activity.ForceDefaultIdFormat = true; @@ -278,14 +278,76 @@ public void EnsureRecordingTest() ActivitySource.AddActivityListener(listener); - Activity a = aSource.StartActivity("RecordedActivity"); + // Note: Remote parent is set as NOT recorded + var parentContext = new ActivityContext(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, isRemote: true); + + Activity a = aSource.StartActivity("RecordedActivity", ActivityKind.Internal, parentContext); Assert.NotNull(a); + Assert.True(a.IsAllDataRequested); Assert.True(a.Recorded); Assert.True((a.Context.TraceFlags & ActivityTraceFlags.Recorded) != 0); }).Dispose(); } + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public void AllDataSamplingTest() + { + RemoteExecutor.Invoke(() => { + Activity.ForceDefaultIdFormat = true; + Activity.DefaultIdFormat = ActivityIdFormat.W3C; + + ActivitySource aSource = new ActivitySource("EnsureRecordingTest"); + + ActivityListener listener = new ActivityListener + { + ShouldListenTo = (activitySource) => true, + Sample = (ref ActivityCreationOptions activityOptions) => ActivitySamplingResult.AllData + }; + + ActivitySource.AddActivityListener(listener); + + // Note: Remote parent is set as recorded + var parentContext = new ActivityContext(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.Recorded, isRemote: true); + + Activity a = aSource.StartActivity("RecordedActivity", ActivityKind.Internal, parentContext); + Assert.NotNull(a); + + Assert.True(a.IsAllDataRequested); + Assert.False(a.Recorded); + Assert.False((a.Context.TraceFlags & ActivityTraceFlags.Recorded) != 0); + }).Dispose(); + } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public void PropagationDataSamplingTest() + { + RemoteExecutor.Invoke(() => { + Activity.ForceDefaultIdFormat = true; + Activity.DefaultIdFormat = ActivityIdFormat.W3C; + + ActivitySource aSource = new ActivitySource("EnsureRecordingTest"); + + ActivityListener listener = new ActivityListener + { + ShouldListenTo = (activitySource) => true, + Sample = (ref ActivityCreationOptions activityOptions) => ActivitySamplingResult.PropagationData + }; + + ActivitySource.AddActivityListener(listener); + + // Note: Remote parent is set as recorded + var parentContext = new ActivityContext(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.Recorded, isRemote: true); + + Activity a = aSource.StartActivity("RecordedActivity", ActivityKind.Internal, parentContext); + Assert.NotNull(a); + + Assert.False(a.IsAllDataRequested); + Assert.False(a.Recorded); + Assert.False((a.Context.TraceFlags & ActivityTraceFlags.Recorded) != 0); + }).Dispose(); + } + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] public void TestExpectedListenersReturnValues() { @@ -424,7 +486,10 @@ public void TestActivityCreationProperties() Assert.Equal(ctx.TraceId, activity.TraceId); Assert.Equal(ctx.SpanId, activity.ParentSpanId); - Assert.Equal(ctx.TraceFlags, activity.ActivityTraceFlags); + Assert.NotEqual(ctx.TraceFlags, activity.ActivityTraceFlags); + Assert.True(ctx.TraceFlags.HasFlag(ActivityTraceFlags.Recorded)); + Assert.False(activity.ActivityTraceFlags.HasFlag(ActivityTraceFlags.Recorded)); + Assert.False(activity.Recorded); Assert.Equal(ctx.TraceState, activity.TraceStateString); Assert.Equal(ActivityIdFormat.W3C, activity.IdFormat); diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/HuffmanTree.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/HuffmanTree.cs index f2262caad22986..a4f1f621df37ee 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/HuffmanTree.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/HuffmanTree.cs @@ -247,6 +247,12 @@ private void CreateTable() } index = -value; // go to next node + if (index >= array.Length) + { + // prevent an IndexOutOfRangeException from array[index] + throw new InvalidDataException(SR.InvalidHuffmanData); + } + codeBitMask <<= 1; overflowBits--; } while (overflowBits != 0); diff --git a/src/libraries/System.IO.Compression/tests/ZipArchive/zip_InvalidParametersAndStrangeFiles.cs b/src/libraries/System.IO.Compression/tests/ZipArchive/zip_InvalidParametersAndStrangeFiles.cs index 87695ad071edff..1bb8b2a113b05a 100644 --- a/src/libraries/System.IO.Compression/tests/ZipArchive/zip_InvalidParametersAndStrangeFiles.cs +++ b/src/libraries/System.IO.Compression/tests/ZipArchive/zip_InvalidParametersAndStrangeFiles.cs @@ -871,6 +871,24 @@ public void ReadArchive_WithDiskStartNumberGreaterThanIntMax() Assert.Null(exception); } + /// + /// This test checks that an InvalidDataException will be thrown when consuming a zip with bad Huffman data. + /// + [Fact] + public static async Task ZipArchive_InvalidHuffmanData() + { + string filename = bad("HuffmanTreeException.zip"); + using (ZipArchive archive = new ZipArchive(await StreamHelpers.CreateTempCopyStream(filename), ZipArchiveMode.Read)) + { + ZipArchiveEntry e = archive.Entries[0]; + using (MemoryStream ms = new MemoryStream()) + using (Stream s = e.Open()) + { + Assert.Throws(() => s.CopyTo(ms)); //"Should throw on creating Huffman tree" + } + } + } + private static readonly byte[] s_slightlyIncorrectZip64 = { // ===== Local file header signature 0x04034b50 diff --git a/src/libraries/System.IO.Pipelines/src/System.IO.Pipelines.csproj b/src/libraries/System.IO.Pipelines/src/System.IO.Pipelines.csproj index a4517443d1832b..7c1901590e388c 100644 --- a/src/libraries/System.IO.Pipelines/src/System.IO.Pipelines.csproj +++ b/src/libraries/System.IO.Pipelines/src/System.IO.Pipelines.csproj @@ -52,10 +52,10 @@ System.IO.Pipelines.PipeReader - + diff --git a/src/libraries/System.IO.Ports/pkg/runtime.native.System.IO.Ports.proj b/src/libraries/System.IO.Ports/pkg/runtime.native.System.IO.Ports.proj index 4be58c3771667f..00e32f9ad27dcd 100644 --- a/src/libraries/System.IO.Ports/pkg/runtime.native.System.IO.Ports.proj +++ b/src/libraries/System.IO.Ports/pkg/runtime.native.System.IO.Ports.proj @@ -13,7 +13,7 @@ + They are filtered in the traversal build in oob-src.csproj based on the OutputRID. --> diff --git a/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/ServerCertificateTest.cs b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/ServerCertificateTest.cs index df73619bf8dad8..4f7d573df68b09 100644 --- a/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/ServerCertificateTest.cs +++ b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/ServerCertificateTest.cs @@ -32,6 +32,7 @@ public async Task NoCallback_ValidCertificate_CallbackNotCalled() [OuterLoop] [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/110578")] public async Task UseCallback_NotSecureConnection_CallbackNotCalled() { var handler = new WinHttpHandler(); diff --git a/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/System.Net.Http.WinHttpHandler.Functional.Tests.csproj b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/System.Net.Http.WinHttpHandler.Functional.Tests.csproj index f25614ada92b3f..c5c7099713aa5f 100644 --- a/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/System.Net.Http.WinHttpHandler.Functional.Tests.csproj +++ b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/System.Net.Http.WinHttpHandler.Functional.Tests.csproj @@ -40,8 +40,6 @@ Link="Common\System\Net\VerboseTestLogging.cs" /> - + + + diff --git a/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/WinHttpHandlerTest.cs b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/WinHttpHandlerTest.cs index 0abe14c11887bf..cc2b97bdde6da7 100644 --- a/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/WinHttpHandlerTest.cs +++ b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/WinHttpHandlerTest.cs @@ -55,7 +55,7 @@ public async Task GetAsync_RedirectResponseHasCookie_CookieSentToFinalUri( string cookieName, string cookieValue) { - Uri uri = System.Net.Test.Common.Configuration.Http.RemoteHttp11Server.RedirectUriForDestinationUri(302, System.Net.Test.Common.Configuration.Http.RemoteEchoServer, 1); + Uri uri = System.Net.Test.Common.Configuration.Http.RemoteSecureHttp11Server.RedirectUriForDestinationUri(302, System.Net.Test.Common.Configuration.Http.SecureRemoteEchoServer, 1); var handler = new WinHttpHandler(); handler.WindowsProxyUsePolicy = WindowsProxyUsePolicy.UseWinInetProxy; handler.CookieUsePolicy = cookieUsePolicy; diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/MetricsTest.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/MetricsTest.cs index 9d4afdd97788ab..1715dbf8c676df 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/MetricsTest.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/MetricsTest.cs @@ -381,7 +381,7 @@ public async Task ExternalServer_DurationMetrics_Recorded() using InstrumentRecorder openConnectionsRecorder = SetupInstrumentRecorder(InstrumentNames.OpenConnections); Uri uri = UseVersion == HttpVersion.Version11 - ? Test.Common.Configuration.Http.RemoteHttp11Server.EchoUri + ? Test.Common.Configuration.Http.RemoteSecureHttp11Server.EchoUri : Test.Common.Configuration.Http.RemoteHttp2Server.EchoUri; IPAddress[] addresses = await Dns.GetHostAddressesAsync(uri.Host); addresses = addresses.Union(addresses.Select(a => a.MapToIPv6())).ToArray(); @@ -1259,7 +1259,7 @@ public Task RequestDuration_Redirect_RecordedForEachHttpSpan() }); }, options: new GenericLoopbackOptions() { UseSsl = true }); - }, options: new GenericLoopbackOptions() { UseSsl = false}); + }, options: new GenericLoopbackOptions() { UseSsl = false }); } [Fact] diff --git a/src/libraries/System.Net.HttpListener/src/System/Net/ServiceNameStore.cs b/src/libraries/System.Net.HttpListener/src/System/Net/ServiceNameStore.cs index deaf7e1851a591..ed0d541195b7f1 100644 --- a/src/libraries/System.Net.HttpListener/src/System/Net/ServiceNameStore.cs +++ b/src/libraries/System.Net.HttpListener/src/System/Net/ServiceNameStore.cs @@ -272,7 +272,7 @@ public static string[] BuildServiceNames(string uriPrefix) if (hostname == "*" || hostname == "+" || - IPAddress.TryParse(hostname, out _)) + IPAddress.IsValid(hostname)) { // for a wildcard, register the machine name. If the caller doesn't have DNS permission // or the query fails for some reason, don't add an SPN. diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/StringParsingHelpers.Addresses.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/StringParsingHelpers.Addresses.cs index 426328818210a1..0543e2aabfc414 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/StringParsingHelpers.Addresses.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/StringParsingHelpers.Addresses.cs @@ -131,14 +131,30 @@ internal static List ParseWinsServerAddressesFromSmbConfFile(string s string fileContents = ReadAllText(smbConfFilePath); string label = "wins server = "; int labelIndex = fileContents.IndexOf(label); + + if (labelIndex == -1) + { + return collection; + } + int labelLineStart = fileContents.LastIndexOf(Environment.NewLine, labelIndex, StringComparison.Ordinal); - if (labelLineStart < labelIndex) + + while (labelIndex != -1) { - int commentIndex = fileContents.IndexOf(';', labelLineStart, labelIndex - labelLineStart); - if (commentIndex != -1) + int commentIndex = fileContents.IndexOfAny(CommentSymbols, labelLineStart, labelIndex - labelLineStart); + if (commentIndex == -1) + { + break; + } + + labelIndex = fileContents.IndexOf(label, labelIndex + 16); + + if (labelIndex == -1) { return collection; } + + labelLineStart = fileContents.LastIndexOf(Environment.NewLine, labelIndex, StringComparison.Ordinal); } int endOfLine = fileContents.IndexOf(Environment.NewLine, labelIndex, StringComparison.Ordinal); ReadOnlySpan addressSpan = fileContents.AsSpan(labelIndex + label.Length, endOfLine - (labelIndex + label.Length)); @@ -154,5 +170,6 @@ internal static List ParseWinsServerAddressesFromSmbConfFile(string s return collection; } + private static readonly char[] CommentSymbols = [';', '#']; } } diff --git a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/AddressParsingTests.cs b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/AddressParsingTests.cs index 637cb202fe4362..378529b700fd75 100644 --- a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/AddressParsingTests.cs +++ b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/AddressParsingTests.cs @@ -97,15 +97,27 @@ public void DhcpServerAddressParsing() Assert.Equal(IPAddress.Parse("10.105.128.4"), dhcpServerAddresses[0]); } - [Fact] - public void WinsServerAddressParsing() + [Theory] + [InlineData("NetworkFiles/smb.conf")] + [InlineData("NetworkFiles/smb_with_commented_wins.conf")] + public void WinsServerAddressParsing(string source) { string fileName = GetTestFilePath(); - FileUtil.NormalizeLineEndings("NetworkFiles/smb.conf", fileName); + FileUtil.NormalizeLineEndings(source, fileName); List winsServerAddresses = StringParsingHelpers.ParseWinsServerAddressesFromSmbConfFile(fileName); Assert.Equal(1, winsServerAddresses.Count); Assert.Equal(IPAddress.Parse("255.1.255.1"), winsServerAddresses[0]); } + + [Fact] + public void WinsServerAddressParsingWhenFileHasNotAny() + { + string fileName = GetTestFilePath(); + FileUtil.NormalizeLineEndings("NetworkFiles/smb_without_wins.conf", fileName); + + List winsServerAddresses = StringParsingHelpers.ParseWinsServerAddressesFromSmbConfFile(fileName); + Assert.Empty(winsServerAddresses); + } } } diff --git a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkFiles/THIRD-PARTY-NOTICES b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkFiles/THIRD-PARTY-NOTICES new file mode 100644 index 00000000000000..72123e758ebea2 --- /dev/null +++ b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkFiles/THIRD-PARTY-NOTICES @@ -0,0 +1,19 @@ +.NET uses third-party libraries or other resources that may be +distributed under licenses different than the .NET software. + +In the event that we accidentally failed to list a required notice, please +bring it to our attention. Post an issue or email us: + + dotnet@microsoft.com + +The attached notices are provided for information only. + +License notice for the Samba team +----------------------------- + +GPL-v3 and LGPL-v3: Copyright (C) [Samba team](https://www.samba.org/samba/team/). + +We use smb config template files in our tests (as provided in https://github.com/samba-team/samba/blob/master/examples/smb.conf.default): +* https://github.com/dotnet/runtime/blob/main/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkFiles/smb.conf +* https://github.com/dotnet/runtime/blob/main/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkFiles/smb_with_commented_wins.conf +* https://github.com/dotnet/runtime/blob/main/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkFiles/smb_without_wins.conf diff --git a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkFiles/smb_with_commented_wins.conf b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkFiles/smb_with_commented_wins.conf new file mode 100644 index 00000000000000..c3a504afd88a39 --- /dev/null +++ b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkFiles/smb_with_commented_wins.conf @@ -0,0 +1,269 @@ +# +# Sample configuration file for the Samba suite for Debian GNU/Linux. +# +# +# This is the main Samba configuration file. You should read the +# smb.conf(5) manual page in order to understand the options listed +# here. Samba has a huge number of configurable options most of which +# are not shown in this example +# +# Some options that are often worth tuning have been included as +# commented-out examples in this file. +# - When such options are commented with ";", the proposed setting +# differs from the default Samba behaviour +# - When commented with "#", the proposed setting is the default +# behaviour of Samba but the option is considered important +# enough to be mentioned here +# +# NOTE: Whenever you modify this file you should run the command +# "testparm" to check that you have not made any basic syntactic +# errors. + +#======================= Global Settings ======================= + +[global] + +## Browsing/Identification ### + +# Change this to the workgroup/NT-domain name your Samba server will part of + workgroup = WORKGROUP + +# server string is the equivalent of the NT Description field + server string = %h server (Samba, Ubuntu) + +# Windows Internet Name Serving Support Section: +# WINS Support - Tells the NMBD component of Samba to enable its WINS Server +# wins support = no + +# WINS Server - Tells the NMBD components of Samba to be a WINS Client +# Note: Samba can be either a WINS Server, or a WINS Client, but NOT both + +# we comment the next two lines to check that we will consider only the uncommented server +;wins server = 255.1.255.2 +#wins server = 255.1.255.3 + +wins server = 255.1.255.1 + +# we comment the next two lines to check that we will not consider them +;wins server = 255.1.255.4 +#wins server = 255.1.255.5 + +# This will prevent nmbd to search for NetBIOS names through DNS. + dns proxy = no + +#### Networking #### + +# The specific set of interfaces / networks to bind to +# This can be either the interface name or an IP address/netmask; +# interface names are normally preferred +; interfaces = 127.0.0.0/8 eth0 + +# Only bind to the named interfaces and/or networks; you must use the +# 'interfaces' option above to use this. +# It is recommended that you enable this feature if your Samba machine is +# not protected by a firewall or is a firewall itself. However, this +# option cannot handle dynamic or non-broadcast interfaces correctly. +; bind interfaces only = yes + + + +#### Debugging/Accounting #### + +# This tells Samba to use a separate log file for each machine +# that connects + log file = /var/log/samba/log.%m + +# Cap the size of the individual log files (in KiB). + max log size = 1000 + +# If you want Samba to only log through syslog then set the following +# parameter to 'yes'. +# syslog only = no + +# We want Samba to log a minimum amount of information to syslog. Everything +# should go to /var/log/samba/log.{smbd,nmbd} instead. If you want to log +# through syslog you should set the following parameter to something higher. + syslog = 0 + +# Do something sensible when Samba crashes: mail the admin a backtrace + panic action = /usr/share/samba/panic-action %d + + +####### Authentication ####### + +# Server role. Defines in which mode Samba will operate. Possible +# values are "standalone server", "member server", "classic primary +# domain controller", "classic backup domain controller", "active +# directory domain controller". +# +# Most people will want "standalone sever" or "member server". +# Running as "active directory domain controller" will require first +# running "samba-tool domain provision" to wipe databases and create a +# new domain. + server role = standalone server + +# If you are using encrypted passwords, Samba will need to know what +# password database type you are using. + passdb backend = tdbsam + + obey pam restrictions = yes + +# This boolean parameter controls whether Samba attempts to sync the Unix +# password with the SMB password when the encrypted SMB password in the +# passdb is changed. + unix password sync = yes + +# For Unix password sync to work on a Debian GNU/Linux system, the following +# parameters must be set (thanks to Ian Kahan < for +# sending the correct chat script for the passwd program in Debian Sarge). + passwd program = /usr/bin/passwd %u + passwd chat = *Enter\snew\s*\spassword:* %n\n *Retype\snew\s*\spassword:* %n\n *password\supdated\ssuccessfully* . + +# This boolean controls whether PAM will be used for password changes +# when requested by an SMB client instead of the program listed in +# 'passwd program'. The default is 'no'. + pam password change = yes + +# This option controls how unsuccessful authentication attempts are mapped +# to anonymous connections + map to guest = bad user + +########## Domains ########### + +# +# The following settings only takes effect if 'server role = primary +# classic domain controller', 'server role = backup domain controller' +# or 'domain logons' is set +# + +# It specifies the location of the user's +# profile directory from the client point of view) The following +# required a [profiles] share to be setup on the samba server (see +# below) +; logon path = \\%N\profiles\%U +# Another common choice is storing the profile in the user's home directory +# (this is Samba's default) +# logon path = \\%N\%U\profile + +# The following setting only takes effect if 'domain logons' is set +# It specifies the location of a user's home directory (from the client +# point of view) +; logon drive = H: +# logon home = \\%N\%U + +# The following setting only takes effect if 'domain logons' is set +# It specifies the script to run during logon. The script must be stored +# in the [netlogon] share +# NOTE: Must be store in 'DOS' file format convention +; logon script = logon.cmd + +# This allows Unix users to be created on the domain controller via the SAMR +# RPC pipe. The example command creates a user account with a disabled Unix +# password; please adapt to your needs +; add user script = /usr/sbin/adduser --quiet --disabled-password --gecos "" %u + +# This allows machine accounts to be created on the domain controller via the +# SAMR RPC pipe. +# The following assumes a "machines" group exists on the system +; add machine script = /usr/sbin/useradd -g machines -c "%u machine account" -d /var/lib/samba -s /bin/false %u + +# This allows Unix groups to be created on the domain controller via the SAMR +# RPC pipe. +; add group script = /usr/sbin/addgroup --force-badname %g + +############ Misc ############ + +# Using the following line enables you to customize your configuration +# on a per machine basis. The %m gets replaced with the netbios name +# of the machine that is connecting +; include = /home/samba/etc/smb.conf.%m + +# Some defaults for winbind (make sure you're not using the ranges +# for something else.) +; idmap uid = 10000-20000 +; idmap gid = 10000-20000 +; template shell = /bin/bash + +# Setup usershare options to enable non-root users to share folders +# with the net usershare command. + +# Maximum number of usershare. 0 (default) means that usershare is disabled. +; usershare max shares = 100 + +# Allow users who've been granted usershare privileges to create +# public shares, not just authenticated ones + usershare allow guests = yes + +#======================= Share Definitions ======================= + +# Un-comment the following (and tweak the other settings below to suit) +# to enable the default home directory shares. This will share each +# user's home directory as \\server\username +;[homes] +; comment = Home Directories +; browseable = no + +# By default, the home directories are exported read-only. Change the +# next parameter to 'no' if you want to be able to write to them. +; read only = yes + +# File creation mask is set to 0700 for security reasons. If you want to +# create files with group=rw permissions, set next parameter to 0775. +; create mask = 0700 + +# Directory creation mask is set to 0700 for security reasons. If you want to +# create dirs. with group=rw permissions, set next parameter to 0775. +; directory mask = 0700 + +# By default, \\server\username shares can be connected to by anyone +# with access to the samba server. +# Un-comment the following parameter to make sure that only "username" +# can connect to \\server\username +# This might need tweaking when using external authentication schemes +; valid users = %S + +# Un-comment the following and create the netlogon directory for Domain Logons +# (you need to configure Samba to act as a domain controller too.) +;[netlogon] +; comment = Network Logon Service +; path = /home/samba/netlogon +; guest ok = yes +; read only = yes + +# Un-comment the following and create the profiles directory to store +# users profiles (see the "logon path" option above) +# (you need to configure Samba to act as a domain controller too.) +# The path below should be writable by all users so that their +# profile directory may be created the first time they log on +;[profiles] +; comment = Users profiles +; path = /home/samba/profiles +; guest ok = no +; browseable = no +; create mask = 0600 +; directory mask = 0700 + +[printers] + comment = All Printers + browseable = no + path = /var/spool/samba + printable = yes + guest ok = no + read only = yes + create mask = 0700 + +# Windows clients look for this share name as a source of downloadable +# printer drivers +[print$] + comment = Printer Drivers + path = /var/lib/samba/printers + browseable = yes + read only = yes + guest ok = no +# Uncomment to allow remote administration of Windows print drivers. +# You may need to replace 'lpadmin' with the name of the group your +# admin users are members of. +# Please note that you also need to set appropriate Unix permissions +# to the drivers directory for these users to have write rights in it +; write list = root, @lpadmin + diff --git a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkFiles/smb_without_wins.conf b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkFiles/smb_without_wins.conf new file mode 100644 index 00000000000000..ba3e9754e111ee --- /dev/null +++ b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkFiles/smb_without_wins.conf @@ -0,0 +1,252 @@ +# +# Sample configuration file for the Samba suite for Debian GNU/Linux. +# +# +# This is the main Samba configuration file. You should read the +# smb.conf(5) manual page in order to understand the options listed +# here. Samba has a huge number of configurable options most of which +# are not shown in this example +# +# Some options that are often worth tuning have been included as +# commented-out examples in this file. +# - When such options are commented with ";", the proposed setting +# differs from the default Samba behaviour +# - When commented with "#", the proposed setting is the default +# behaviour of Samba but the option is considered important +# enough to be mentioned here +# +# NOTE: Whenever you modify this file you should run the command +# "testparm" to check that you have not made any basic syntactic +# errors. + +#======================= Global Settings ======================= + +[global] + +## Browsing/Identification ### + +# Change this to the workgroup/NT-domain name your Samba server will part of + workgroup = WORKGROUP + +# server string is the equivalent of the NT Description field + server string = %h server (Samba, Ubuntu) + +# This will prevent nmbd to search for NetBIOS names through DNS. + dns proxy = no + +#### Networking #### + +# The specific set of interfaces / networks to bind to +# This can be either the interface name or an IP address/netmask; +# interface names are normally preferred +; interfaces = 127.0.0.0/8 eth0 + +# Only bind to the named interfaces and/or networks; you must use the +# 'interfaces' option above to use this. +# It is recommended that you enable this feature if your Samba machine is +# not protected by a firewall or is a firewall itself. However, this +# option cannot handle dynamic or non-broadcast interfaces correctly. +; bind interfaces only = yes + + + +#### Debugging/Accounting #### + +# This tells Samba to use a separate log file for each machine +# that connects + log file = /var/log/samba/log.%m + +# Cap the size of the individual log files (in KiB). + max log size = 1000 + +# If you want Samba to only log through syslog then set the following +# parameter to 'yes'. +# syslog only = no + +# We want Samba to log a minimum amount of information to syslog. Everything +# should go to /var/log/samba/log.{smbd,nmbd} instead. If you want to log +# through syslog you should set the following parameter to something higher. + syslog = 0 + +# Do something sensible when Samba crashes: mail the admin a backtrace + panic action = /usr/share/samba/panic-action %d + + +####### Authentication ####### + +# Server role. Defines in which mode Samba will operate. Possible +# values are "standalone server", "member server", "classic primary +# domain controller", "classic backup domain controller", "active +# directory domain controller". +# +# Most people will want "standalone sever" or "member server". +# Running as "active directory domain controller" will require first +# running "samba-tool domain provision" to wipe databases and create a +# new domain. + server role = standalone server + +# If you are using encrypted passwords, Samba will need to know what +# password database type you are using. + passdb backend = tdbsam + + obey pam restrictions = yes + +# This boolean parameter controls whether Samba attempts to sync the Unix +# password with the SMB password when the encrypted SMB password in the +# passdb is changed. + unix password sync = yes + +# For Unix password sync to work on a Debian GNU/Linux system, the following +# parameters must be set (thanks to Ian Kahan < for +# sending the correct chat script for the passwd program in Debian Sarge). + passwd program = /usr/bin/passwd %u + passwd chat = *Enter\snew\s*\spassword:* %n\n *Retype\snew\s*\spassword:* %n\n *password\supdated\ssuccessfully* . + +# This boolean controls whether PAM will be used for password changes +# when requested by an SMB client instead of the program listed in +# 'passwd program'. The default is 'no'. + pam password change = yes + +# This option controls how unsuccessful authentication attempts are mapped +# to anonymous connections + map to guest = bad user + +########## Domains ########### + +# +# The following settings only takes effect if 'server role = primary +# classic domain controller', 'server role = backup domain controller' +# or 'domain logons' is set +# + +# It specifies the location of the user's +# profile directory from the client point of view) The following +# required a [profiles] share to be setup on the samba server (see +# below) +; logon path = \\%N\profiles\%U +# Another common choice is storing the profile in the user's home directory +# (this is Samba's default) +# logon path = \\%N\%U\profile + +# The following setting only takes effect if 'domain logons' is set +# It specifies the location of a user's home directory (from the client +# point of view) +; logon drive = H: +# logon home = \\%N\%U + +# The following setting only takes effect if 'domain logons' is set +# It specifies the script to run during logon. The script must be stored +# in the [netlogon] share +# NOTE: Must be store in 'DOS' file format convention +; logon script = logon.cmd + +# This allows Unix users to be created on the domain controller via the SAMR +# RPC pipe. The example command creates a user account with a disabled Unix +# password; please adapt to your needs +; add user script = /usr/sbin/adduser --quiet --disabled-password --gecos "" %u + +# This allows machine accounts to be created on the domain controller via the +# SAMR RPC pipe. +# The following assumes a "machines" group exists on the system +; add machine script = /usr/sbin/useradd -g machines -c "%u machine account" -d /var/lib/samba -s /bin/false %u + +# This allows Unix groups to be created on the domain controller via the SAMR +# RPC pipe. +; add group script = /usr/sbin/addgroup --force-badname %g + +############ Misc ############ + +# Using the following line enables you to customize your configuration +# on a per machine basis. The %m gets replaced with the netbios name +# of the machine that is connecting +; include = /home/samba/etc/smb.conf.%m + +# Some defaults for winbind (make sure you're not using the ranges +# for something else.) +; idmap uid = 10000-20000 +; idmap gid = 10000-20000 +; template shell = /bin/bash + +# Setup usershare options to enable non-root users to share folders +# with the net usershare command. + +# Maximum number of usershare. 0 (default) means that usershare is disabled. +; usershare max shares = 100 + +# Allow users who've been granted usershare privileges to create +# public shares, not just authenticated ones + usershare allow guests = yes + +#======================= Share Definitions ======================= + +# Un-comment the following (and tweak the other settings below to suit) +# to enable the default home directory shares. This will share each +# user's home directory as \\server\username +;[homes] +; comment = Home Directories +; browseable = no + +# By default, the home directories are exported read-only. Change the +# next parameter to 'no' if you want to be able to write to them. +; read only = yes + +# File creation mask is set to 0700 for security reasons. If you want to +# create files with group=rw permissions, set next parameter to 0775. +; create mask = 0700 + +# Directory creation mask is set to 0700 for security reasons. If you want to +# create dirs. with group=rw permissions, set next parameter to 0775. +; directory mask = 0700 + +# By default, \\server\username shares can be connected to by anyone +# with access to the samba server. +# Un-comment the following parameter to make sure that only "username" +# can connect to \\server\username +# This might need tweaking when using external authentication schemes +; valid users = %S + +# Un-comment the following and create the netlogon directory for Domain Logons +# (you need to configure Samba to act as a domain controller too.) +;[netlogon] +; comment = Network Logon Service +; path = /home/samba/netlogon +; guest ok = yes +; read only = yes + +# Un-comment the following and create the profiles directory to store +# users profiles (see the "logon path" option above) +# (you need to configure Samba to act as a domain controller too.) +# The path below should be writable by all users so that their +# profile directory may be created the first time they log on +;[profiles] +; comment = Users profiles +; path = /home/samba/profiles +; guest ok = no +; browseable = no +; create mask = 0600 +; directory mask = 0700 + +[printers] + comment = All Printers + browseable = no + path = /var/spool/samba + printable = yes + guest ok = no + read only = yes + create mask = 0700 + +# Windows clients look for this share name as a source of downloadable +# printer drivers +[print$] + comment = Printer Drivers + path = /var/lib/samba/printers + browseable = yes + read only = yes + guest ok = no +# Uncomment to allow remote administration of Windows print drivers. +# You may need to replace 'lpadmin' with the name of the group your +# admin users are members of. +# Please note that you also need to set appropriate Unix permissions +# to the drivers directory for these users to have write rights in it +; write list = root, @lpadmin + diff --git a/src/libraries/System.Net.Primitives/ref/System.Net.Primitives.cs b/src/libraries/System.Net.Primitives/ref/System.Net.Primitives.cs index 05dee66ca23777..6122e499bd50ae 100644 --- a/src/libraries/System.Net.Primitives/ref/System.Net.Primitives.cs +++ b/src/libraries/System.Net.Primitives/ref/System.Net.Primitives.cs @@ -256,6 +256,8 @@ public IPAddress(System.ReadOnlySpan address, long scopeid) { } public static int HostToNetworkOrder(int host) { throw null; } public static long HostToNetworkOrder(long host) { throw null; } public static bool IsLoopback(System.Net.IPAddress address) { throw null; } + public static bool IsValidUtf8(System.ReadOnlySpan utf8Text) { throw null; } + public static bool IsValid(System.ReadOnlySpan ipSpan) { throw null; } public System.Net.IPAddress MapToIPv4() { throw null; } public System.Net.IPAddress MapToIPv6() { throw null; } public static short NetworkToHostOrder(short network) { throw null; } diff --git a/src/libraries/System.Net.Primitives/src/System/Net/IPAddress.cs b/src/libraries/System.Net.Primitives/src/System/Net/IPAddress.cs index cd7e281e541c52..541e96219c1c03 100644 --- a/src/libraries/System.Net.Primitives/src/System/Net/IPAddress.cs +++ b/src/libraries/System.Net.Primitives/src/System/Net/IPAddress.cs @@ -226,6 +226,14 @@ internal IPAddress(int newAddress) PrivateAddress = (uint)newAddress; } + /// Determines whether the provided span contains a valid . + /// The text to parse. + public static bool IsValid(ReadOnlySpan ipSpan) => IPAddressParser.IsValid(ipSpan); + + /// Determines whether the provided span contains a valid . + /// The text to parse. + public static bool IsValidUtf8(ReadOnlySpan utf8Text) => IPAddressParser.IsValid(utf8Text); + /// /// /// Converts an IP address string to an instance. diff --git a/src/libraries/System.Net.Primitives/src/System/Net/IPAddressParser.cs b/src/libraries/System.Net.Primitives/src/System/Net/IPAddressParser.cs index 7ef1cd216e99cb..2352c4f88397d2 100644 --- a/src/libraries/System.Net.Primitives/src/System/Net/IPAddressParser.cs +++ b/src/libraries/System.Net.Primitives/src/System/Net/IPAddressParser.cs @@ -16,6 +16,24 @@ internal static class IPAddressParser internal const int MaxIPv4StringLength = 15; // 4 numbers separated by 3 periods, with up to 3 digits per number internal const int MaxIPv6StringLength = 65; + public static unsafe bool IsValid(ReadOnlySpan ipSpan) + where TChar : unmanaged, IBinaryInteger + { + fixed (TChar* ipStringPtr = &MemoryMarshal.GetReference(ipSpan)) + { + if (ipSpan.Contains(TChar.CreateTruncating(':'))) + { + return IPv6AddressHelper.IsValidStrict(ipStringPtr, 0, ipSpan.Length); + } + else + { + int end = ipSpan.Length; + long address = IPv4AddressHelper.ParseNonCanonical(ipStringPtr, 0, ref end, notImplicitFile: true); + return address != IPv4AddressHelper.Invalid && end == ipSpan.Length; + } + } + } + internal static IPAddress? Parse(ReadOnlySpan ipSpan, bool tryParse) where TChar : unmanaged, IBinaryInteger { @@ -75,60 +93,57 @@ private static unsafe bool TryParseIPv6(ReadOnlySpan ipSpan, Span< Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte)); Debug.Assert(numbersLength >= IPAddressParserStatics.IPv6AddressShorts); - int end = ipSpan.Length; - bool isValid = false; fixed (TChar* ipStringPtr = &MemoryMarshal.GetReference(ipSpan)) { - isValid = IPv6AddressHelper.IsValidStrict(ipStringPtr, 0, ref end); + if (!IPv6AddressHelper.IsValidStrict(ipStringPtr, 0, ipSpan.Length)) + { + scope = 0; + return false; + } } - scope = 0; - if (isValid || (end != ipSpan.Length)) + IPv6AddressHelper.Parse(ipSpan, numbers, out ReadOnlySpan scopeIdSpan); + + if (scopeIdSpan.Length > 1) { - IPv6AddressHelper.Parse(ipSpan, numbers, out ReadOnlySpan scopeIdSpan); + bool parsedNumericScope; + scopeIdSpan = scopeIdSpan.Slice(1); - if (scopeIdSpan.Length > 1) + // scopeId is a numeric value + if (typeof(TChar) == typeof(byte)) { - bool parsedNumericScope = false; - scopeIdSpan = scopeIdSpan.Slice(1); + ReadOnlySpan castScopeIdSpan = MemoryMarshal.Cast(scopeIdSpan); - // scopeId is a numeric value - if (typeof(TChar) == typeof(byte)) - { - ReadOnlySpan castScopeIdSpan = MemoryMarshal.Cast(scopeIdSpan); + parsedNumericScope = uint.TryParse(castScopeIdSpan, NumberStyles.None, CultureInfo.InvariantCulture, out scope); + } + else + { + ReadOnlySpan castScopeIdSpan = MemoryMarshal.Cast(scopeIdSpan); - parsedNumericScope = uint.TryParse(castScopeIdSpan, NumberStyles.None, CultureInfo.InvariantCulture, out scope); - } - else if (typeof(TChar) == typeof(char)) - { - ReadOnlySpan castScopeIdSpan = MemoryMarshal.Cast(scopeIdSpan); + parsedNumericScope = uint.TryParse(castScopeIdSpan, NumberStyles.None, CultureInfo.InvariantCulture, out scope); + } - parsedNumericScope = uint.TryParse(castScopeIdSpan, NumberStyles.None, CultureInfo.InvariantCulture, out scope); - } + if (parsedNumericScope) + { + return true; + } + else + { + uint interfaceIndex = InterfaceInfoPal.InterfaceNameToIndex(scopeIdSpan); - if (parsedNumericScope) + if (interfaceIndex > 0) { - return true; + scope = interfaceIndex; + return true; // scopeId is a known interface name } - else - { - uint interfaceIndex = InterfaceInfoPal.InterfaceNameToIndex(scopeIdSpan); - - if (interfaceIndex > 0) - { - scope = interfaceIndex; - return true; // scopeId is a known interface name - } - } - - // scopeId is an unknown interface name } - // scopeId is not presented - return true; + // scopeId is an unknown interface name } - return false; + // scopeId is not presented + scope = 0; + return true; } internal static int FormatIPv4Address(uint address, Span addressString) diff --git a/src/libraries/System.Net.Primitives/tests/FunctionalTests/IPAddressParsing.cs b/src/libraries/System.Net.Primitives/tests/FunctionalTests/IPAddressParsing.cs index 9331bf6b3b98c0..3e326de9236c9a 100644 --- a/src/libraries/System.Net.Primitives/tests/FunctionalTests/IPAddressParsing.cs +++ b/src/libraries/System.Net.Primitives/tests/FunctionalTests/IPAddressParsing.cs @@ -219,6 +219,8 @@ public abstract class IPAddressParsingFormatting [MemberData(nameof(ValidIpv4Addresses))] public void ParseIPv4_ValidAddress_Success(string address, string expected) { + TestIsValid(address, true); + IPAddress ip = Parse(address); // Validate the ToString of the parsed address matches the expected value @@ -443,6 +445,8 @@ public void ParseIPv4_InvalidAddress_ThrowsFormatExceptionWithInnerException(str [MemberData(nameof(ValidIpv6Addresses))] public void ParseIPv6_ValidAddress_RoundtripMatchesExpected(string address, string expected) { + TestIsValid(address, true); + IPAddress ip = Parse(address); // Validate the ToString of the parsed address matches the expected value @@ -467,6 +471,8 @@ public void ParseIPv6_ValidAddress_RoundtripMatchesExpected(string address, stri [MemberData(nameof(ValidIpv6Addresses))] public void TryParseIPv6_ValidAddress_RoundtripMatchesExpected(string address, string expected) { + TestIsValid(address, true); + Assert.True(TryParse(address, out IPAddress ip)); // Validate the ToString of the parsed address matches the expected value @@ -502,6 +508,7 @@ public void TryParseIPv6_ValidAddress_RoundtripMatchesExpected(string address, s [MemberData(nameof(ScopeIds))] public void ParseIPv6_ExtractsScopeId(string address, int expectedScopeId) { + TestIsValid(address, true); IPAddress ip = Parse(address); Assert.Equal(expectedScopeId, ip.ScopeId); } @@ -613,6 +620,8 @@ public void ParseIPv6_InvalidAddress_ThrowsFormatExceptionWithNoInnerExceptionIn private void ParseInvalidAddress(string invalidAddress, bool hasInnerSocketException) { + TestIsValid(invalidAddress, false); + FormatException fe = Assert.Throws(() => Parse(invalidAddress)); if (hasInnerSocketException) { @@ -628,5 +637,11 @@ private void ParseInvalidAddress(string invalidAddress, bool hasInnerSocketExcep Assert.False(TryParse(invalidAddress, out result)); Assert.Null(result); } + + private static void TestIsValid(string address, bool expectedValid) + { + Assert.Equal(expectedValid, IPAddress.IsValid(address)); + Assert.Equal(expectedValid, IPAddress.IsValidUtf8(Encoding.UTF8.GetBytes(address))); + } } } diff --git a/src/libraries/System.Net.Primitives/tests/UnitTests/Fakes/IPv6AddressHelper.cs b/src/libraries/System.Net.Primitives/tests/UnitTests/Fakes/IPv6AddressHelper.cs index 32dc4cc2631925..07be627eedcba9 100644 --- a/src/libraries/System.Net.Primitives/tests/UnitTests/Fakes/IPv6AddressHelper.cs +++ b/src/libraries/System.Net.Primitives/tests/UnitTests/Fakes/IPv6AddressHelper.cs @@ -11,7 +11,7 @@ internal static class IPv6AddressHelper internal static unsafe (int longestSequenceStart, int longestSequenceLength) FindCompressionRange( ReadOnlySpan numbers) => (-1, -1); internal static unsafe bool ShouldHaveIpv4Embedded(ReadOnlySpan numbers) => false; - internal static unsafe bool IsValidStrict(TChar* name, int start, ref int end) + internal static unsafe bool IsValidStrict(TChar* name, int start, int end) where TChar : unmanaged, IBinaryInteger => false; internal static unsafe bool Parse(ReadOnlySpan address, Span numbers, out ReadOnlySpan scopeId) where TChar : unmanaged, IBinaryInteger diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs index 840e1bdac7b0c1..95457e48584077 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs @@ -423,7 +423,7 @@ private async ValueTask FinishConnectAsync(QuicClientConnectionOptions options, // RFC 6066 forbids IP literals. // IDN mapping is handled by MsQuic. - string sni = (TargetHostNameHelper.IsValidAddress(options.ClientAuthenticationOptions.TargetHost) ? null : options.ClientAuthenticationOptions.TargetHost) ?? host ?? string.Empty; + string sni = (IPAddress.IsValid(options.ClientAuthenticationOptions.TargetHost) ? null : options.ClientAuthenticationOptions.TargetHost) ?? host ?? string.Empty; IntPtr targetHostPtr = Marshal.StringToCoTaskMemUTF8(sni); try @@ -458,7 +458,7 @@ internal ValueTask FinishHandshakeAsync(QuicServerConnectionOptions options, str _streamCapacityCallback = options.StreamCapacityCallback; // RFC 6066 forbids IP literals, avoid setting IP address here for consistency with SslStream - if (TargetHostNameHelper.IsValidAddress(targetHost)) + if (IPAddress.IsValid(targetHost)) { targetHost = string.Empty; } diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/Pal.Android/SafeDeleteSslContext.cs b/src/libraries/System.Net.Security/src/System/Net/Security/Pal.Android/SafeDeleteSslContext.cs index 0f141c0812f942..e958a482898f9e 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/Pal.Android/SafeDeleteSslContext.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/Pal.Android/SafeDeleteSslContext.cs @@ -255,7 +255,7 @@ private unsafe void InitializeSslContext( Interop.AndroidCrypto.SSLStreamRequestClientAuthentication(handle); } - if (!isServer && !string.IsNullOrEmpty(authOptions.TargetHost) && !TargetHostNameHelper.IsValidAddress(authOptions.TargetHost)) + if (!isServer && !string.IsNullOrEmpty(authOptions.TargetHost) && !IPAddress.IsValid(authOptions.TargetHost)) { Interop.AndroidCrypto.SSLStreamSetTargetHost(handle, authOptions.TargetHost); } diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/Pal.OSX/SafeDeleteSslContext.cs b/src/libraries/System.Net.Security/src/System/Net/Security/Pal.OSX/SafeDeleteSslContext.cs index 7ff7b26e7a5e62..f1945c428363cd 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/Pal.OSX/SafeDeleteSslContext.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/Pal.OSX/SafeDeleteSslContext.cs @@ -95,7 +95,7 @@ public SafeDeleteSslContext(SslAuthenticationOptions sslAuthenticationOptions) throw; } - if (!string.IsNullOrEmpty(sslAuthenticationOptions.TargetHost) && !sslAuthenticationOptions.IsServer && !TargetHostNameHelper.IsValidAddress(sslAuthenticationOptions.TargetHost)) + if (!string.IsNullOrEmpty(sslAuthenticationOptions.TargetHost) && !sslAuthenticationOptions.IsServer && !IPAddress.IsValid(sslAuthenticationOptions.TargetHost)) { Interop.AppleCrypto.SslSetTargetName(_sslContext, sslAuthenticationOptions.TargetHost); } diff --git a/src/libraries/System.Net.ServerSentEvents/src/System.Net.ServerSentEvents.csproj b/src/libraries/System.Net.ServerSentEvents/src/System.Net.ServerSentEvents.csproj index 7ca797752fa435..4f94192389cfe3 100644 --- a/src/libraries/System.Net.ServerSentEvents/src/System.Net.ServerSentEvents.csproj +++ b/src/libraries/System.Net.ServerSentEvents/src/System.Net.ServerSentEvents.csproj @@ -24,6 +24,7 @@ System.Net.ServerSentEvents.SseParser + diff --git a/src/libraries/System.Net.ServerSentEvents/src/System/Net/ServerSentEvents/Helpers.cs b/src/libraries/System.Net.ServerSentEvents/src/System/Net/ServerSentEvents/Helpers.cs index 4639c84cd3ded9..2b78bb445f28d7 100644 --- a/src/libraries/System.Net.ServerSentEvents/src/System/Net/ServerSentEvents/Helpers.cs +++ b/src/libraries/System.Net.ServerSentEvents/src/System/Net/ServerSentEvents/Helpers.cs @@ -4,11 +4,7 @@ using System.Buffers; using System.Diagnostics; using System.Globalization; -using System.IO; -using System.Runtime.InteropServices; using System.Text; -using System.Threading; -using System.Threading.Tasks; namespace System.Net.ServerSentEvents { @@ -67,34 +63,5 @@ public static unsafe void WriteUtf8String(this IBufferWriter writer, ReadO public static bool ContainsLineBreaks(this ReadOnlySpan text) => text.IndexOfAny('\r', '\n') >= 0; - -#if !NET - - public static ValueTask WriteAsync(this Stream stream, ReadOnlyMemory buffer, CancellationToken cancellationToken = default) - { - if (MemoryMarshal.TryGetArray(buffer, out ArraySegment segment)) - { - return new ValueTask(stream.WriteAsync(segment.Array, segment.Offset, segment.Count, cancellationToken)); - } - else - { - return WriteAsyncUsingPooledBuffer(stream, buffer, cancellationToken); - - static async ValueTask WriteAsyncUsingPooledBuffer(Stream stream, ReadOnlyMemory buffer, CancellationToken cancellationToken) - { - byte[] sharedBuffer = ArrayPool.Shared.Rent(buffer.Length); - buffer.Span.CopyTo(sharedBuffer); - try - { - await stream.WriteAsync(sharedBuffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false); - } - finally - { - ArrayPool.Shared.Return(sharedBuffer); - } - } - } - } -#endif } } diff --git a/src/libraries/System.Net.ServerSentEvents/src/System/Net/ServerSentEvents/SseParser_1.cs b/src/libraries/System.Net.ServerSentEvents/src/System/Net/ServerSentEvents/SseParser_1.cs index bff2149a6b9f24..dbf4bd1579c03b 100644 --- a/src/libraries/System.Net.ServerSentEvents/src/System/Net/ServerSentEvents/SseParser_1.cs +++ b/src/libraries/System.Net.ServerSentEvents/src/System/Net/ServerSentEvents/SseParser_1.cs @@ -500,13 +500,7 @@ private async ValueTask FillLineBufferAsync(CancellationToken cancellationT ShiftOrGrowLineBufferIfNecessary(); int offset = _lineOffset + _lineLength; - int bytesRead = await -#if NET - _stream.ReadAsync(_lineBuffer.AsMemory(offset), cancellationToken) -#else - new ValueTask(_stream.ReadAsync(_lineBuffer, offset, _lineBuffer.Length - offset, cancellationToken)) -#endif - .ConfigureAwait(false); + int bytesRead = await _stream.ReadAsync(_lineBuffer.AsMemory(offset), cancellationToken).ConfigureAwait(false); if (bytesRead > 0) { diff --git a/src/libraries/System.Net.Sockets/src/Resources/Strings.resx b/src/libraries/System.Net.Sockets/src/Resources/Strings.resx index 7a0feca077c032..36faf4552f604c 100644 --- a/src/libraries/System.Net.Sockets/src/Resources/Strings.resx +++ b/src/libraries/System.Net.Sockets/src/Resources/Strings.resx @@ -312,9 +312,6 @@ System.Net.Sockets is not supported on this platform. - - Handle is already used by another Socket. - Provided SocketAddress is too small for given AddressFamily. diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs index 8463c5142b573c..4cc7a28fca8143 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs @@ -1262,6 +1262,8 @@ public void Trace(SocketAsyncContext context, string message, [CallerMemberName] private SocketAsyncEngine? _asyncEngine; private bool IsRegistered => _asyncEngine != null; private bool _isHandleNonBlocking = OperatingSystem.IsWasi(); // WASI sockets are always non-blocking, because we don't have another thread which could be blocked + /// An index into 's table of all contexts that are currently . + internal int GlobalContextIndex = -1; private readonly object _registerLock = new object(); @@ -1330,7 +1332,10 @@ public bool StopAndAbort() // We don't need to synchronize with Register. // This method is called when the handle gets released. // The Register method will throw ODE when it tries to use the handle at this point. - _asyncEngine?.UnregisterSocket(_socket.DangerousGetHandle(), this); + if (IsRegistered) + { + SocketAsyncEngine.UnregisterSocket(this); + } return aborted; } diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEngine.Unix.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEngine.Unix.cs index 7405e579042232..b67af69163bc5e 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEngine.Unix.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEngine.Unix.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Concurrent; +using System.Collections.Generic; using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -74,14 +75,17 @@ private static SocketAsyncEngine[] CreateEngines() return engines; } + /// + /// Each is assigned an index into this table while registered with a . + /// The index is used as the to quickly map events to s. + /// It is also stored in so that we can efficiently remove it when unregistering the socket. + /// + private static SocketAsyncContext?[] s_registeredContexts = []; + private static readonly Queue s_registeredContextsFreeList = []; + private readonly IntPtr _port; private readonly Interop.Sys.SocketEvent* _buffer; - // - // Maps handle values to SocketAsyncContext instances. - // - private readonly ConcurrentDictionary _handleToContextMap = new ConcurrentDictionary(); - // // Queue of events generated by EventLoop() that would be processed by the thread pool // @@ -119,28 +123,54 @@ public static bool TryRegisterSocket(IntPtr socketHandle, SocketAsyncContext con private bool TryRegisterCore(IntPtr socketHandle, SocketAsyncContext context, out Interop.Error error) { - bool added = _handleToContextMap.TryAdd(socketHandle, new SocketAsyncContextWrapper(context)); - if (!added) + Debug.Assert(context.GlobalContextIndex == -1); + + lock (s_registeredContextsFreeList) { - // Using public SafeSocketHandle(IntPtr) a user can add the same handle - // from a different Socket instance. - throw new InvalidOperationException(SR.net_sockets_handle_already_used); + if (!s_registeredContextsFreeList.TryDequeue(out int index)) + { + int previousLength = s_registeredContexts.Length; + int newLength = Math.Max(4, 2 * previousLength); + + Array.Resize(ref s_registeredContexts, newLength); + + for (int i = previousLength + 1; i < newLength; i++) + { + s_registeredContextsFreeList.Enqueue(i); + } + + index = previousLength; + } + + Debug.Assert(s_registeredContexts[index] is null); + + s_registeredContexts[index] = context; + context.GlobalContextIndex = index; } error = Interop.Sys.TryChangeSocketEventRegistration(_port, socketHandle, Interop.Sys.SocketEvents.None, - Interop.Sys.SocketEvents.Read | Interop.Sys.SocketEvents.Write, socketHandle); + Interop.Sys.SocketEvents.Read | Interop.Sys.SocketEvents.Write, context.GlobalContextIndex); if (error == Interop.Error.SUCCESS) { return true; } - _handleToContextMap.TryRemove(socketHandle, out _); + UnregisterSocket(context); return false; } - public void UnregisterSocket(IntPtr socketHandle, SocketAsyncContext __) + public static void UnregisterSocket(SocketAsyncContext context) { - _handleToContextMap.TryRemove(socketHandle, out _); + Debug.Assert(context.GlobalContextIndex >= 0); + Debug.Assert(ReferenceEquals(s_registeredContexts[context.GlobalContextIndex], context)); + + lock (s_registeredContextsFreeList) + { + s_registeredContexts[context.GlobalContextIndex] = null; + s_registeredContextsFreeList.Enqueue(context.GlobalContextIndex); + } + + context.GlobalContextIndex = -1; } private SocketAsyncEngine() @@ -324,13 +354,11 @@ private readonly struct SocketEventHandler { public Interop.Sys.SocketEvent* Buffer { get; } - private readonly ConcurrentDictionary _handleToContextMap; private readonly ConcurrentQueue _eventQueue; public SocketEventHandler(SocketAsyncEngine engine) { Buffer = engine._buffer; - _handleToContextMap = engine._handleToContextMap; _eventQueue = engine._eventQueue; } @@ -340,10 +368,15 @@ public bool HandleSocketEvents(int numEvents) bool enqueuedEvent = false; foreach (var socketEvent in new ReadOnlySpan(Buffer, numEvents)) { - if (_handleToContextMap.TryGetValue(socketEvent.Data, out SocketAsyncContextWrapper contextWrapper)) - { - SocketAsyncContext context = contextWrapper.Context; + Debug.Assert((uint)socketEvent.Data < (uint)s_registeredContexts.Length); + // The context may be null if the socket was unregistered right before the event was processed. + // The slot in s_registeredContexts may have been reused by a different context, in which case the + // incorrect socket will notice that no information is available yet and harmlessly retry, waiting for new events. + SocketAsyncContext? context = s_registeredContexts[(uint)socketEvent.Data]; + + if (context is not null) + { if (context.PreferInlineCompletions) { context.HandleEventsInline(socketEvent.Events); @@ -365,18 +398,6 @@ public bool HandleSocketEvents(int numEvents) } } - // struct wrapper is used in order to improve the performance of the epoll thread hot path by up to 3% of some TechEmpower benchmarks - // the goal is to have a dedicated generic instantiation and using: - // System.Collections.Concurrent.ConcurrentDictionary`2[System.IntPtr,System.Net.Sockets.SocketAsyncContextWrapper]::TryGetValueInternal(!0,int32,!1&) - // instead of: - // System.Collections.Concurrent.ConcurrentDictionary`2[System.IntPtr,System.__Canon]::TryGetValueInternal(!0,int32,!1&) - private readonly struct SocketAsyncContextWrapper - { - public SocketAsyncContextWrapper(SocketAsyncContext context) => Context = context; - - internal SocketAsyncContext Context { get; } - } - private readonly struct SocketIOEvent { public SocketAsyncContext Context { get; } diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEngine.Wasi.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEngine.Wasi.cs index 3b69902260d812..0a39feb2699364 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEngine.Wasi.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEngine.Wasi.cs @@ -35,9 +35,7 @@ public static bool TryRegisterSocket(IntPtr socketHandle, SocketAsyncContext con return true; } -#pragma warning disable CA1822 - public void UnregisterSocket(IntPtr _, SocketAsyncContext context) -#pragma warning restore CA1822 + public static void UnregisterSocket(SocketAsyncContext context) { context.unregisterPollHook.Cancel(); } diff --git a/src/libraries/System.Net.WebProxy/src/System/Net/WebProxy.Wasm.cs b/src/libraries/System.Net.WebProxy/src/System/Net/WebProxy.Wasm.cs index a2756eb6487396..26f47648d5c8f5 100644 --- a/src/libraries/System.Net.WebProxy/src/System/Net/WebProxy.Wasm.cs +++ b/src/libraries/System.Net.WebProxy/src/System/Net/WebProxy.Wasm.cs @@ -16,7 +16,7 @@ private static bool IsLocal(Uri host) string hostString = host.Host; return - !IPAddress.TryParse(hostString, out _) && + !IPAddress.IsValid(hostString) && !hostString.Contains('.'); } } diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorExtensions.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorExtensions.cs index 1274b20b8cf9eb..5ba164337bfc91 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorExtensions.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorExtensions.cs @@ -3501,7 +3501,7 @@ public static ref readonly TensorSpan StackAlongDimension(scoped ReadOnlyS { outputs[i] = Tensor.Unsqueeze(tensors[i], dimension); } - return ref Tensor.ConcatenateOnDimension(dimension, tensors, destination); + return ref Tensor.ConcatenateOnDimension(dimension, outputs, destination); } #endregion diff --git a/src/libraries/System.Numerics.Tensors/tests/TensorTests.cs b/src/libraries/System.Numerics.Tensors/tests/TensorTests.cs index 16cf20c3fc82b8..165779fe329a61 100644 --- a/src/libraries/System.Numerics.Tensors/tests/TensorTests.cs +++ b/src/libraries/System.Numerics.Tensors/tests/TensorTests.cs @@ -988,6 +988,7 @@ public static void TensorSetSliceTests() Assert.Equal(13, t0[1, 3]); Assert.Equal(14, t0[1, 4]); } + [Fact] public static void TensorStackTests() { @@ -1075,7 +1076,7 @@ public static void TensorStackTests() Assert.Equal(9, resultTensor[1, 4, 0]); Assert.Equal(9, resultTensor[1, 4, 1]); - // stacking 2x2 tensors along dimention 1 + // stacking 2x2 tensors along dimension 1 Tensor v1 = Tensor.Create([1, 2, 3, 4], [2, 2]); Tensor v2 = Tensor.Create([10, 20, 30, 40], [2, 2]); @@ -1095,6 +1096,26 @@ public static void TensorStackTests() Assert.Equal(4, resultTensor[1, 0, 1]); Assert.Equal(30, resultTensor[1, 1, 0]); Assert.Equal(40, resultTensor[1, 1, 1]); + + resultTensor = Tensor.StackAlongDimension(0, [v1, v2]); + + Tensor resultTensor2 = Tensor.Create([2, 2, 2]); + Tensor.StackAlongDimension([v1, v2], resultTensor2, 1); + + Assert.Equal(3, resultTensor2.Rank); + Assert.Equal(2, resultTensor2.Lengths[0]); + Assert.Equal(2, resultTensor2.Lengths[1]); + Assert.Equal(2, resultTensor2.Lengths[2]); + + Assert.Equal(1, resultTensor2[0, 0, 0]); + Assert.Equal(2, resultTensor2[0, 0, 1]); + Assert.Equal(10, resultTensor2[0, 1, 0]); + Assert.Equal(20, resultTensor2[0, 1, 1]); + + Assert.Equal(3, resultTensor2[1, 0, 0]); + Assert.Equal(4, resultTensor2[1, 0, 1]); + Assert.Equal(30, resultTensor2[1, 1, 0]); + Assert.Equal(40, resultTensor2[1, 1, 1]); } [Fact] diff --git a/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs b/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs index fd00fe8c727068..e485b71f87639e 100644 --- a/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs +++ b/src/libraries/System.Numerics.Vectors/ref/System.Numerics.Vectors.cs @@ -205,7 +205,11 @@ public static partial class Vector public static bool IsHardwareAccelerated { get { throw null; } } public static System.Numerics.Vector Abs(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector Add(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static bool All(System.Numerics.Vector vector, T value) { throw null; } + public static bool AllWhereAllBitsSet(System.Numerics.Vector vector) { throw null; } public static System.Numerics.Vector AndNot(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } + public static bool Any(System.Numerics.Vector vector, T value) { throw null; } + public static bool AnyWhereAllBitsSet(System.Numerics.Vector vector) { throw null; } public static System.Numerics.Vector As(this System.Numerics.Vector vector) { throw null; } public static System.Numerics.Plane AsPlane(this System.Numerics.Vector4 value) { throw null; } public static System.Numerics.Quaternion AsQuaternion(this System.Numerics.Vector4 value) { throw null; } @@ -264,6 +268,8 @@ public static partial class Vector public static System.Numerics.Vector CopySign(System.Numerics.Vector value, System.Numerics.Vector sign) { throw null; } public static System.Numerics.Vector Cos(System.Numerics.Vector vector) { throw null; } public static System.Numerics.Vector Cos(System.Numerics.Vector vector) { throw null; } + public static int Count(System.Numerics.Vector vector, T value) { throw null; } + public static int CountWhereAllBitsSet(System.Numerics.Vector vector) { throw null; } public static System.Numerics.Vector Create(T value) { throw null; } public static System.Numerics.Vector Create(System.ReadOnlySpan values) { throw null; } public static System.Numerics.Vector CreateSequence(T start, T step) { throw null; } @@ -281,11 +287,20 @@ public static partial class Vector public static System.Numerics.Vector Equals(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector Exp(System.Numerics.Vector vector) { throw null; } public static System.Numerics.Vector Exp(System.Numerics.Vector vector) { throw null; } + [CLSCompliant(false)] + public static uint ExtractMostSignificantBits(this System.Numerics.Vector2 vector) { throw null; } + [CLSCompliant(false)] + public static uint ExtractMostSignificantBits(this System.Numerics.Vector3 vector) { throw null; } + [CLSCompliant(false)] + public static uint ExtractMostSignificantBits(this System.Numerics.Vector4 vector) { throw null; } public static System.Numerics.Vector Floor(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector Floor(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector FusedMultiplyAdd(System.Numerics.Vector left, System.Numerics.Vector right, System.Numerics.Vector addend) { throw null; } public static System.Numerics.Vector FusedMultiplyAdd(System.Numerics.Vector left, System.Numerics.Vector right, System.Numerics.Vector addend) { throw null; } public static T GetElement(this System.Numerics.Vector vector, int index) { throw null; } + public static float GetElement(this System.Numerics.Vector2 vector, int index) { throw null; } + public static float GetElement(this System.Numerics.Vector3 vector, int index) { throw null; } + public static float GetElement(this System.Numerics.Vector4 vector, int index) { throw null; } public static System.Numerics.Vector GreaterThan(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector GreaterThan(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector GreaterThan(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } @@ -302,11 +317,23 @@ public static partial class Vector public static System.Numerics.Vector GreaterThan(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static System.Numerics.Vector Hypot(System.Numerics.Vector x, System.Numerics.Vector y) { throw null; } public static System.Numerics.Vector Hypot(System.Numerics.Vector x, System.Numerics.Vector y) { throw null; } + public static int IndexOf(System.Numerics.Vector vector, T value) { throw null; } + public static int IndexOfWhereAllBitsSet(System.Numerics.Vector vector) { throw null; } + public static System.Numerics.Vector IsEvenInteger(System.Numerics.Vector vector) { throw null; } + public static System.Numerics.Vector IsFinite(System.Numerics.Vector vector) { throw null; } + public static System.Numerics.Vector IsInfinity(System.Numerics.Vector vector) { throw null; } + public static System.Numerics.Vector IsInteger(System.Numerics.Vector vector) { throw null; } public static System.Numerics.Vector IsNaN(System.Numerics.Vector vector) { throw null; } public static System.Numerics.Vector IsNegative(System.Numerics.Vector vector) { throw null; } + public static System.Numerics.Vector IsNegativeInfinity(System.Numerics.Vector vector) { throw null; } + public static System.Numerics.Vector IsNormal(System.Numerics.Vector vector) { throw null; } + public static System.Numerics.Vector IsOddInteger(System.Numerics.Vector vector) { throw null; } public static System.Numerics.Vector IsPositive(System.Numerics.Vector vector) { throw null; } public static System.Numerics.Vector IsPositiveInfinity(System.Numerics.Vector vector) { throw null; } + public static System.Numerics.Vector IsSubnormal(System.Numerics.Vector vector) { throw null; } public static System.Numerics.Vector IsZero(System.Numerics.Vector vector) { throw null; } + public static int LastIndexOf(System.Numerics.Vector vector, T value) { throw null; } + public static int LastIndexOfWhereAllBitsSet(System.Numerics.Vector vector) { throw null; } public static System.Numerics.Vector Lerp(System.Numerics.Vector x, System.Numerics.Vector y, System.Numerics.Vector amount) { throw null; } public static System.Numerics.Vector Lerp(System.Numerics.Vector x, System.Numerics.Vector y, System.Numerics.Vector amount) { throw null; } public static System.Numerics.Vector LessThan(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } @@ -363,6 +390,8 @@ public static partial class Vector [System.CLSCompliantAttribute(false)] public static System.Numerics.Vector Narrow(System.Numerics.Vector low, System.Numerics.Vector high) { throw null; } public static System.Numerics.Vector Negate(System.Numerics.Vector value) { throw null; } + public static bool None(System.Numerics.Vector vector, T value) { throw null; } + public static bool NoneWhereAllBitsSet(System.Numerics.Vector vector) { throw null; } public static System.Numerics.Vector OnesComplement(System.Numerics.Vector value) { throw null; } public static System.Numerics.Vector RadiansToDegrees(System.Numerics.Vector radians) { throw null; } public static System.Numerics.Vector RadiansToDegrees(System.Numerics.Vector radians) { throw null; } @@ -414,15 +443,45 @@ public static partial class Vector [System.CLSCompliantAttribute(false)] public static unsafe void Store(this System.Numerics.Vector source, T* destination) { throw null; } [System.CLSCompliantAttribute(false)] + public static unsafe void Store(this System.Numerics.Vector2 source, float* destination) { throw null; } + [System.CLSCompliantAttribute(false)] + public static unsafe void Store(this System.Numerics.Vector3 source, float* destination) { throw null; } + [System.CLSCompliantAttribute(false)] + public static unsafe void Store(this System.Numerics.Vector4 source, float* destination) { throw null; } + [System.CLSCompliantAttribute(false)] public static unsafe void StoreAligned(this System.Numerics.Vector source, T* destination) { throw null; } [System.CLSCompliantAttribute(false)] + public static unsafe void StoreAligned(this System.Numerics.Vector2 source, float* destination) { throw null; } + [System.CLSCompliantAttribute(false)] + public static unsafe void StoreAligned(this System.Numerics.Vector3 source, float* destination) { throw null; } + [System.CLSCompliantAttribute(false)] + public static unsafe void StoreAligned(this System.Numerics.Vector4 source, float* destination) { throw null; } + [System.CLSCompliantAttribute(false)] public static unsafe void StoreAlignedNonTemporal(this System.Numerics.Vector source, T* destination) { throw null; } + [System.CLSCompliantAttribute(false)] + public static unsafe void StoreAlignedNonTemporal(this System.Numerics.Vector2 source, float* destination) { throw null; } + [System.CLSCompliantAttribute(false)] + public static unsafe void StoreAlignedNonTemporal(this System.Numerics.Vector3 source, float* destination) { throw null; } + [System.CLSCompliantAttribute(false)] + public static unsafe void StoreAlignedNonTemporal(this System.Numerics.Vector4 source, float* destination) { throw null; } public static void StoreUnsafe(this System.Numerics.Vector source, ref T destination) { throw null; } + public static void StoreUnsafe(this System.Numerics.Vector2 source, ref float destination) { throw null; } + public static void StoreUnsafe(this System.Numerics.Vector3 source, ref float destination) { throw null; } + public static void StoreUnsafe(this System.Numerics.Vector4 source, ref float destination) { throw null; } [System.CLSCompliantAttribute(false)] public static void StoreUnsafe(this System.Numerics.Vector source, ref T destination, nuint elementOffset) { throw null; } + [System.CLSCompliantAttribute(false)] + public static void StoreUnsafe(this System.Numerics.Vector2 source, ref float destination, nuint elementOffset) { throw null; } + [System.CLSCompliantAttribute(false)] + public static void StoreUnsafe(this System.Numerics.Vector3 source, ref float destination, nuint elementOffset) { throw null; } + [System.CLSCompliantAttribute(false)] + public static void StoreUnsafe(this System.Numerics.Vector4 source, ref float destination, nuint elementOffset) { throw null; } public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } public static T Sum(System.Numerics.Vector value) { throw null; } public static T ToScalar(this System.Numerics.Vector vector) { throw null; } + public static float ToScalar(this System.Numerics.Vector2 vector) { throw null; } + public static float ToScalar(this System.Numerics.Vector3 vector) { throw null; } + public static float ToScalar(this System.Numerics.Vector4 vector) { throw null; } public static System.Numerics.Vector Truncate(System.Numerics.Vector vector) { throw null; } public static System.Numerics.Vector Truncate(System.Numerics.Vector vector) { throw null; } [System.CLSCompliantAttribute(false)] @@ -459,6 +518,9 @@ public static partial class Vector [System.CLSCompliantAttribute(false)] public static System.Numerics.Vector WidenUpper(System.Numerics.Vector source) { throw null; } public static System.Numerics.Vector WithElement(this System.Numerics.Vector vector, int index, T value) { throw null; } + public static System.Numerics.Vector2 WithElement(this System.Numerics.Vector2 vector, int index, float value) { throw null; } + public static System.Numerics.Vector3 WithElement(this System.Numerics.Vector3 vector, int index, float value) { throw null; } + public static System.Numerics.Vector4 WithElement(this System.Numerics.Vector4 vector, int index, float value) { throw null; } public static System.Numerics.Vector Xor(System.Numerics.Vector left, System.Numerics.Vector right) { throw null; } } public partial struct Vector2 : System.IEquatable, System.IFormattable @@ -468,6 +530,7 @@ public partial struct Vector2 : System.IEquatable, Syst public Vector2(float value) { throw null; } public Vector2(float x, float y) { throw null; } public Vector2(System.ReadOnlySpan values) { throw null; } + public static System.Numerics.Vector2 AllBitsSet { get { throw null; } } public static System.Numerics.Vector2 E { get { throw null; } } public static System.Numerics.Vector2 Epsilon { get { throw null; } } public static System.Numerics.Vector2 NaN { get { throw null; } } @@ -483,9 +546,19 @@ public partial struct Vector2 : System.IEquatable, Syst public static System.Numerics.Vector2 Zero { get { throw null; } } public static System.Numerics.Vector2 Abs(System.Numerics.Vector2 value) { throw null; } public static System.Numerics.Vector2 Add(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } + public static bool All(System.Numerics.Vector2 vector, float value) { throw null; } + public static bool AllWhereAllBitsSet(System.Numerics.Vector2 vector) { throw null; } + public static System.Numerics.Vector2 AndNot(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } + public static bool Any(System.Numerics.Vector2 vector, float value) { throw null; } + public static bool AnyWhereAllBitsSet(System.Numerics.Vector2 vector) { throw null; } + public static System.Numerics.Vector2 BitwiseAnd(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } + public static System.Numerics.Vector2 BitwiseOr(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } public static System.Numerics.Vector2 Clamp(System.Numerics.Vector2 value1, System.Numerics.Vector2 min, System.Numerics.Vector2 max) { throw null; } public static System.Numerics.Vector2 ClampNative(System.Numerics.Vector2 value1, System.Numerics.Vector2 min, System.Numerics.Vector2 max) { throw null; } + public static System.Numerics.Vector2 ConditionalSelect(System.Numerics.Vector2 condition, System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } public static System.Numerics.Vector2 CopySign(System.Numerics.Vector2 value, System.Numerics.Vector2 sign) { throw null; } + public static int Count(System.Numerics.Vector2 vector, float value) { throw null; } + public static int CountWhereAllBitsSet(System.Numerics.Vector2 vector) { throw null; } public static System.Numerics.Vector2 Create(float value) { throw null; } public static System.Numerics.Vector2 Create(float x, float y) { throw null; } public static System.Numerics.Vector2 Create(System.ReadOnlySpan values) { throw null; } @@ -502,14 +575,55 @@ public readonly void CopyTo(System.Span destination) { } public static float Dot(System.Numerics.Vector2 value1, System.Numerics.Vector2 value2) { throw null; } public readonly bool Equals(System.Numerics.Vector2 other) { throw null; } public override readonly bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } + public static Vector2 Equals(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } + public static bool EqualsAll(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } + public static bool EqualsAny(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } public static System.Numerics.Vector2 Exp(System.Numerics.Vector2 vector) { throw null; } public static System.Numerics.Vector2 FusedMultiplyAdd(System.Numerics.Vector2 left, System.Numerics.Vector2 right, System.Numerics.Vector2 addend) { throw null; } public override readonly int GetHashCode() { throw null; } + public static Vector2 GreaterThan(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } + public static bool GreaterThanAll(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } + public static bool GreaterThanAny(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } + public static Vector2 GreaterThanOrEqual(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } + public static bool GreaterThanOrEqualAll(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } + public static bool GreaterThanOrEqualAny(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } public static System.Numerics.Vector2 Hypot(System.Numerics.Vector2 x, System.Numerics.Vector2 y) { throw null; } + public static int IndexOf(System.Numerics.Vector2 vector, float value) { throw null; } + public static int IndexOfWhereAllBitsSet(System.Numerics.Vector2 vector) { throw null; } + public static System.Numerics.Vector2 IsEvenInteger(System.Numerics.Vector2 vector) { throw null; } + public static System.Numerics.Vector2 IsFinite(System.Numerics.Vector2 vector) { throw null; } + public static System.Numerics.Vector2 IsInfinity(System.Numerics.Vector2 vector) { throw null; } + public static System.Numerics.Vector2 IsInteger(System.Numerics.Vector2 vector) { throw null; } + public static System.Numerics.Vector2 IsNaN(System.Numerics.Vector2 vector) { throw null; } + public static System.Numerics.Vector2 IsNegative(System.Numerics.Vector2 vector) { throw null; } + public static System.Numerics.Vector2 IsNegativeInfinity(System.Numerics.Vector2 vector) { throw null; } + public static System.Numerics.Vector2 IsNormal(System.Numerics.Vector2 vector) { throw null; } + public static System.Numerics.Vector2 IsOddInteger(System.Numerics.Vector2 vector) { throw null; } + public static System.Numerics.Vector2 IsPositive(System.Numerics.Vector2 vector) { throw null; } + public static System.Numerics.Vector2 IsPositiveInfinity(System.Numerics.Vector2 vector) { throw null; } + public static System.Numerics.Vector2 IsSubnormal(System.Numerics.Vector2 vector) { throw null; } + public static System.Numerics.Vector2 IsZero(System.Numerics.Vector2 vector) { throw null; } + public static int LastIndexOf(System.Numerics.Vector2 vector, float value) { throw null; } + public static int LastIndexOfWhereAllBitsSet(System.Numerics.Vector2 vector) { throw null; } public readonly float Length() { throw null; } public readonly float LengthSquared() { throw null; } public static System.Numerics.Vector2 Lerp(System.Numerics.Vector2 value1, System.Numerics.Vector2 value2, float amount) { throw null; } public static System.Numerics.Vector2 Lerp(System.Numerics.Vector2 value1, System.Numerics.Vector2 value2, System.Numerics.Vector2 amount) { throw null; } + public static Vector2 LessThan(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } + public static bool LessThanAll(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } + public static bool LessThanAny(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } + public static Vector2 LessThanOrEqual(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } + public static bool LessThanOrEqualAll(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } + public static bool LessThanOrEqualAny(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } + [CLSCompliant(false)] + public static unsafe System.Numerics.Vector2 Load(float* source) { throw null; } + [CLSCompliant(false)] + public static unsafe System.Numerics.Vector2 LoadAligned(float* source) { throw null; } + [CLSCompliant(false)] + public static unsafe System.Numerics.Vector2 LoadAlignedNonTemporal(float* source) { throw null; } + public static System.Numerics.Vector2 LoadUnsafe(ref readonly float source) { throw null; } + [CLSCompliant(false)] + public static System.Numerics.Vector2 LoadUnsafe(ref readonly float source, nuint elementOffset) { throw null; } public static System.Numerics.Vector2 Log(System.Numerics.Vector2 vector) { throw null; } public static System.Numerics.Vector2 Log2(System.Numerics.Vector2 vector) { throw null; } public static System.Numerics.Vector2 Max(System.Numerics.Vector2 value1, System.Numerics.Vector2 value2) { throw null; } @@ -527,24 +641,37 @@ public readonly void CopyTo(System.Span destination) { } public static System.Numerics.Vector2 Multiply(float left, System.Numerics.Vector2 right) { throw null; } public static System.Numerics.Vector2 MultiplyAddEstimate(System.Numerics.Vector2 left, System.Numerics.Vector2 right, System.Numerics.Vector2 addend) { throw null; } public static System.Numerics.Vector2 Negate(System.Numerics.Vector2 value) { throw null; } + public static bool None(System.Numerics.Vector2 vector, float value) { throw null; } + public static bool NoneWhereAllBitsSet(System.Numerics.Vector2 vector) { throw null; } public static System.Numerics.Vector2 Normalize(System.Numerics.Vector2 value) { throw null; } + public static System.Numerics.Vector2 OnesComplement(System.Numerics.Vector2 value) { throw null; } public static System.Numerics.Vector2 operator +(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } + public static System.Numerics.Vector2 operator &(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } + public static System.Numerics.Vector2 operator |(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } public static System.Numerics.Vector2 operator /(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } public static System.Numerics.Vector2 operator /(System.Numerics.Vector2 value1, float value2) { throw null; } + public static System.Numerics.Vector2 operator ^(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } public static bool operator ==(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } + public static System.Numerics.Vector2 operator <<(System.Numerics.Vector2 value, int shiftAmount) { throw null; } public static bool operator !=(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } public static System.Numerics.Vector2 operator *(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } public static System.Numerics.Vector2 operator *(System.Numerics.Vector2 left, float right) { throw null; } public static System.Numerics.Vector2 operator *(float left, System.Numerics.Vector2 right) { throw null; } + public static System.Numerics.Vector2 operator ~(System.Numerics.Vector2 value) { throw null; } + public static System.Numerics.Vector2 operator >>(System.Numerics.Vector2 value, int shiftAmount) { throw null; } public static System.Numerics.Vector2 operator -(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } public static System.Numerics.Vector2 operator -(System.Numerics.Vector2 value) { throw null; } + public static System.Numerics.Vector2 operator +(System.Numerics.Vector2 value) { throw null; } + public static System.Numerics.Vector2 operator >>>(System.Numerics.Vector2 value, int shiftAmount) { throw null; } public static System.Numerics.Vector2 RadiansToDegrees(System.Numerics.Vector2 radians) { throw null; } public static System.Numerics.Vector2 Round(System.Numerics.Vector2 vector) { throw null; } public static System.Numerics.Vector2 Round(System.Numerics.Vector2 vector, System.MidpointRounding mode) { throw null; } public static System.Numerics.Vector2 Reflect(System.Numerics.Vector2 vector, System.Numerics.Vector2 normal) { throw null; } + public static System.Numerics.Vector2 Shuffle(System.Numerics.Vector2 vector, byte xIndex, byte yIndex) { throw null; } public static System.Numerics.Vector2 Sin(System.Numerics.Vector2 vector) { throw null; } public static (System.Numerics.Vector2 Sin, System.Numerics.Vector2 Cos) SinCos(System.Numerics.Vector2 vector) { throw null; } public static System.Numerics.Vector2 SquareRoot(System.Numerics.Vector2 value) { throw null; } + public static float Sum(System.Numerics.Vector2 value) { throw null; } public static System.Numerics.Vector2 Subtract(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } public override readonly string ToString() { throw null; } public readonly string ToString([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("NumericFormat")] string? format) { throw null; } @@ -555,6 +682,7 @@ public readonly void CopyTo(System.Span destination) { } public static System.Numerics.Vector2 TransformNormal(System.Numerics.Vector2 normal, System.Numerics.Matrix3x2 matrix) { throw null; } public static System.Numerics.Vector2 TransformNormal(System.Numerics.Vector2 normal, System.Numerics.Matrix4x4 matrix) { throw null; } public static System.Numerics.Vector2 Truncate(System.Numerics.Vector2 vector) { throw null; } + public static System.Numerics.Vector2 Xor(System.Numerics.Vector2 left, System.Numerics.Vector2 right) { throw null; } } public partial struct Vector3 : System.IEquatable, System.IFormattable { @@ -565,6 +693,7 @@ public partial struct Vector3 : System.IEquatable, Syst public Vector3(float value) { throw null; } public Vector3(float x, float y, float z) { throw null; } public Vector3(System.ReadOnlySpan values) { throw null; } + public static System.Numerics.Vector3 AllBitsSet { get { throw null; } } public static System.Numerics.Vector3 E { get { throw null; } } public static System.Numerics.Vector3 Epsilon { get { throw null; } } public static System.Numerics.Vector3 NaN { get { throw null; } } @@ -581,9 +710,19 @@ public partial struct Vector3 : System.IEquatable, Syst public static System.Numerics.Vector3 Zero { get { throw null; } } public static System.Numerics.Vector3 Abs(System.Numerics.Vector3 value) { throw null; } public static System.Numerics.Vector3 Add(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } + public static bool All(System.Numerics.Vector3 vector, float value) { throw null; } + public static bool AllWhereAllBitsSet(System.Numerics.Vector3 vector) { throw null; } + public static System.Numerics.Vector3 AndNot(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } + public static bool Any(System.Numerics.Vector3 vector, float value) { throw null; } + public static bool AnyWhereAllBitsSet(System.Numerics.Vector3 vector) { throw null; } + public static System.Numerics.Vector3 BitwiseAnd(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } + public static System.Numerics.Vector3 BitwiseOr(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } public static System.Numerics.Vector3 Clamp(System.Numerics.Vector3 value1, System.Numerics.Vector3 min, System.Numerics.Vector3 max) { throw null; } public static System.Numerics.Vector3 ClampNative(System.Numerics.Vector3 value1, System.Numerics.Vector3 min, System.Numerics.Vector3 max) { throw null; } + public static System.Numerics.Vector3 ConditionalSelect(System.Numerics.Vector3 condition, System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } public static System.Numerics.Vector3 CopySign(System.Numerics.Vector3 value, System.Numerics.Vector3 sign) { throw null; } + public static int Count(System.Numerics.Vector3 vector, float value) { throw null; } + public static int CountWhereAllBitsSet(System.Numerics.Vector3 vector) { throw null; } public static System.Numerics.Vector3 Create(float value) { throw null; } public static System.Numerics.Vector3 Create(System.Numerics.Vector2 vector, float z) { throw null; } public static System.Numerics.Vector3 Create(float x, float y, float z) { throw null; } @@ -602,14 +741,55 @@ public readonly void CopyTo(System.Span destination) { } public static float Dot(System.Numerics.Vector3 vector1, System.Numerics.Vector3 vector2) { throw null; } public readonly bool Equals(System.Numerics.Vector3 other) { throw null; } public override readonly bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } + public static Vector3 Equals(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } + public static bool EqualsAll(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } + public static bool EqualsAny(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } public static System.Numerics.Vector3 Exp(System.Numerics.Vector3 vector) { throw null; } public static System.Numerics.Vector3 FusedMultiplyAdd(System.Numerics.Vector3 left, System.Numerics.Vector3 right, System.Numerics.Vector3 addend) { throw null; } public override readonly int GetHashCode() { throw null; } + public static Vector3 GreaterThan(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } + public static bool GreaterThanAll(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } + public static bool GreaterThanAny(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } + public static Vector3 GreaterThanOrEqual(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } + public static bool GreaterThanOrEqualAll(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } + public static bool GreaterThanOrEqualAny(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } + public static System.Numerics.Vector3 Hypot(System.Numerics.Vector3 x, System.Numerics.Vector3 y) { throw null; } + public static int IndexOf(System.Numerics.Vector3 vector, float value) { throw null; } + public static int IndexOfWhereAllBitsSet(System.Numerics.Vector3 vector) { throw null; } + public static System.Numerics.Vector3 IsEvenInteger(System.Numerics.Vector3 vector) { throw null; } + public static System.Numerics.Vector3 IsFinite(System.Numerics.Vector3 vector) { throw null; } + public static System.Numerics.Vector3 IsInfinity(System.Numerics.Vector3 vector) { throw null; } + public static System.Numerics.Vector3 IsInteger(System.Numerics.Vector3 vector) { throw null; } + public static System.Numerics.Vector3 IsNaN(System.Numerics.Vector3 vector) { throw null; } + public static System.Numerics.Vector3 IsNegative(System.Numerics.Vector3 vector) { throw null; } + public static System.Numerics.Vector3 IsNegativeInfinity(System.Numerics.Vector3 vector) { throw null; } + public static System.Numerics.Vector3 IsNormal(System.Numerics.Vector3 vector) { throw null; } + public static System.Numerics.Vector3 IsOddInteger(System.Numerics.Vector3 vector) { throw null; } + public static System.Numerics.Vector3 IsPositive(System.Numerics.Vector3 vector) { throw null; } + public static System.Numerics.Vector3 IsPositiveInfinity(System.Numerics.Vector3 vector) { throw null; } + public static System.Numerics.Vector3 IsSubnormal(System.Numerics.Vector3 vector) { throw null; } + public static System.Numerics.Vector3 IsZero(System.Numerics.Vector3 vector) { throw null; } + public static int LastIndexOf(System.Numerics.Vector3 vector, float value) { throw null; } + public static int LastIndexOfWhereAllBitsSet(System.Numerics.Vector3 vector) { throw null; } public readonly float Length() { throw null; } public readonly float LengthSquared() { throw null; } - public static System.Numerics.Vector3 Hypot(System.Numerics.Vector3 x, System.Numerics.Vector3 y) { throw null; } public static System.Numerics.Vector3 Lerp(System.Numerics.Vector3 value1, System.Numerics.Vector3 value2, float amount) { throw null; } public static System.Numerics.Vector3 Lerp(System.Numerics.Vector3 value1, System.Numerics.Vector3 value2, System.Numerics.Vector3 amount) { throw null; } + public static Vector3 LessThan(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } + public static bool LessThanAll(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } + public static bool LessThanAny(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } + public static Vector3 LessThanOrEqual(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } + public static bool LessThanOrEqualAll(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } + public static bool LessThanOrEqualAny(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } + [CLSCompliant(false)] + public static unsafe System.Numerics.Vector3 Load(float* source) { throw null; } + [CLSCompliant(false)] + public static unsafe System.Numerics.Vector3 LoadAligned(float* source) { throw null; } + [CLSCompliant(false)] + public static unsafe System.Numerics.Vector3 LoadAlignedNonTemporal(float* source) { throw null; } + public static System.Numerics.Vector3 LoadUnsafe(ref readonly float source) { throw null; } + [CLSCompliant(false)] + public static System.Numerics.Vector3 LoadUnsafe(ref readonly float source, nuint elementOffset) { throw null; } public static System.Numerics.Vector3 Log(System.Numerics.Vector3 vector) { throw null; } public static System.Numerics.Vector3 Log2(System.Numerics.Vector3 vector) { throw null; } public static System.Numerics.Vector3 Max(System.Numerics.Vector3 value1, System.Numerics.Vector3 value2) { throw null; } @@ -627,25 +807,38 @@ public readonly void CopyTo(System.Span destination) { } public static System.Numerics.Vector3 Multiply(float left, System.Numerics.Vector3 right) { throw null; } public static System.Numerics.Vector3 MultiplyAddEstimate(System.Numerics.Vector3 left, System.Numerics.Vector3 right, System.Numerics.Vector3 addend) { throw null; } public static System.Numerics.Vector3 Negate(System.Numerics.Vector3 value) { throw null; } + public static bool None(System.Numerics.Vector3 vector, float value) { throw null; } + public static bool NoneWhereAllBitsSet(System.Numerics.Vector3 vector) { throw null; } public static System.Numerics.Vector3 Normalize(System.Numerics.Vector3 value) { throw null; } + public static System.Numerics.Vector3 OnesComplement(System.Numerics.Vector3 value) { throw null; } public static System.Numerics.Vector3 operator +(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } + public static System.Numerics.Vector3 operator &(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } + public static System.Numerics.Vector3 operator |(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } public static System.Numerics.Vector3 operator /(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } public static System.Numerics.Vector3 operator /(System.Numerics.Vector3 value1, float value2) { throw null; } + public static System.Numerics.Vector3 operator ^(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } public static bool operator ==(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } + public static System.Numerics.Vector3 operator <<(System.Numerics.Vector3 value, int shiftAmount) { throw null; } public static bool operator !=(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } public static System.Numerics.Vector3 operator *(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } public static System.Numerics.Vector3 operator *(System.Numerics.Vector3 left, float right) { throw null; } public static System.Numerics.Vector3 operator *(float left, System.Numerics.Vector3 right) { throw null; } + public static System.Numerics.Vector3 operator ~(System.Numerics.Vector3 value) { throw null; } + public static System.Numerics.Vector3 operator >>(System.Numerics.Vector3 value, int shiftAmount) { throw null; } public static System.Numerics.Vector3 operator -(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } public static System.Numerics.Vector3 operator -(System.Numerics.Vector3 value) { throw null; } + public static System.Numerics.Vector3 operator +(System.Numerics.Vector3 value) { throw null; } + public static System.Numerics.Vector3 operator >>>(System.Numerics.Vector3 value, int shiftAmount) { throw null; } public static System.Numerics.Vector3 RadiansToDegrees(System.Numerics.Vector3 radians) { throw null; } public static System.Numerics.Vector3 Reflect(System.Numerics.Vector3 vector, System.Numerics.Vector3 normal) { throw null; } public static System.Numerics.Vector3 Round(System.Numerics.Vector3 vector) { throw null; } public static System.Numerics.Vector3 Round(System.Numerics.Vector3 vector, System.MidpointRounding mode) { throw null; } + public static System.Numerics.Vector3 Shuffle(System.Numerics.Vector3 vector, byte xIndex, byte yIndex, byte zIndex) { throw null; } public static System.Numerics.Vector3 Sin(System.Numerics.Vector3 vector) { throw null; } public static (System.Numerics.Vector3 Sin, System.Numerics.Vector3 Cos) SinCos(System.Numerics.Vector3 vector) { throw null; } public static System.Numerics.Vector3 SquareRoot(System.Numerics.Vector3 value) { throw null; } public static System.Numerics.Vector3 Subtract(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } + public static float Sum(System.Numerics.Vector3 value) { throw null; } public override readonly string ToString() { throw null; } public readonly string ToString([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("NumericFormat")] string? format) { throw null; } public readonly string ToString([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("NumericFormat")] string? format, System.IFormatProvider? formatProvider) { throw null; } @@ -653,6 +846,7 @@ public readonly void CopyTo(System.Span destination) { } public static System.Numerics.Vector3 Transform(System.Numerics.Vector3 value, System.Numerics.Quaternion rotation) { throw null; } public static System.Numerics.Vector3 TransformNormal(System.Numerics.Vector3 normal, System.Numerics.Matrix4x4 matrix) { throw null; } public static System.Numerics.Vector3 Truncate(System.Numerics.Vector3 vector) { throw null; } + public static System.Numerics.Vector3 Xor(System.Numerics.Vector3 left, System.Numerics.Vector3 right) { throw null; } } public partial struct Vector4 : System.IEquatable, System.IFormattable { @@ -665,6 +859,7 @@ public partial struct Vector4 : System.IEquatable, Syst public Vector4(float value) { throw null; } public Vector4(float x, float y, float z, float w) { throw null; } public Vector4(System.ReadOnlySpan values) { throw null; } + public static System.Numerics.Vector4 AllBitsSet { get { throw null; } } public static System.Numerics.Vector4 E { get { throw null; } } public static System.Numerics.Vector4 Epsilon { get { throw null; } } public static System.Numerics.Vector4 NaN { get { throw null; } } @@ -682,9 +877,19 @@ public partial struct Vector4 : System.IEquatable, Syst public static System.Numerics.Vector4 Zero { get { throw null; } } public static System.Numerics.Vector4 Abs(System.Numerics.Vector4 value) { throw null; } public static System.Numerics.Vector4 Add(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } + public static bool All(System.Numerics.Vector4 vector, float value) { throw null; } + public static bool AllWhereAllBitsSet(System.Numerics.Vector4 vector) { throw null; } + public static System.Numerics.Vector4 AndNot(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } + public static bool Any(System.Numerics.Vector4 vector, float value) { throw null; } + public static bool AnyWhereAllBitsSet(System.Numerics.Vector4 vector) { throw null; } + public static System.Numerics.Vector4 BitwiseAnd(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } + public static System.Numerics.Vector4 BitwiseOr(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } public static System.Numerics.Vector4 Clamp(System.Numerics.Vector4 value1, System.Numerics.Vector4 min, System.Numerics.Vector4 max) { throw null; } public static System.Numerics.Vector4 ClampNative(System.Numerics.Vector4 value1, System.Numerics.Vector4 min, System.Numerics.Vector4 max) { throw null; } + public static System.Numerics.Vector4 ConditionalSelect(System.Numerics.Vector4 condition, System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } public static System.Numerics.Vector4 CopySign(System.Numerics.Vector4 value, System.Numerics.Vector4 sign) { throw null; } + public static int Count(System.Numerics.Vector4 vector, float value) { throw null; } + public static int CountWhereAllBitsSet(System.Numerics.Vector4 vector) { throw null; } public static System.Numerics.Vector4 Create(float value) { throw null; } public static System.Numerics.Vector4 Create(System.Numerics.Vector2 vector, float z, float w) { throw null; } public static System.Numerics.Vector4 Create(System.Numerics.Vector3 vector, float w) { throw null; } @@ -703,16 +908,57 @@ public readonly void CopyTo(System.Span destination) { } public static float Dot(System.Numerics.Vector4 vector1, System.Numerics.Vector4 vector2) { throw null; } public readonly bool Equals(System.Numerics.Vector4 other) { throw null; } public override readonly bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } + public static Vector4 Equals(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } + public static bool EqualsAll(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } + public static bool EqualsAny(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } public static System.Numerics.Vector4 Exp(System.Numerics.Vector4 vector) { throw null; } public static System.Numerics.Vector4 FusedMultiplyAdd(System.Numerics.Vector4 left, System.Numerics.Vector4 right, System.Numerics.Vector4 addend) { throw null; } public override readonly int GetHashCode() { throw null; } + public static Vector4 GreaterThan(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } + public static bool GreaterThanAll(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } + public static bool GreaterThanAny(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } + public static Vector4 GreaterThanOrEqual(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } + public static bool GreaterThanOrEqualAll(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } + public static bool GreaterThanOrEqualAny(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } + public static System.Numerics.Vector4 Hypot(System.Numerics.Vector4 x, System.Numerics.Vector4 y) { throw null; } + public static int IndexOf(System.Numerics.Vector4 vector, float value) { throw null; } + public static int IndexOfWhereAllBitsSet(System.Numerics.Vector4 vector) { throw null; } + public static System.Numerics.Vector4 IsEvenInteger(System.Numerics.Vector4 vector) { throw null; } + public static System.Numerics.Vector4 IsFinite(System.Numerics.Vector4 vector) { throw null; } + public static System.Numerics.Vector4 IsInfinity(System.Numerics.Vector4 vector) { throw null; } + public static System.Numerics.Vector4 IsInteger(System.Numerics.Vector4 vector) { throw null; } + public static System.Numerics.Vector4 IsNaN(System.Numerics.Vector4 vector) { throw null; } + public static System.Numerics.Vector4 IsNegative(System.Numerics.Vector4 vector) { throw null; } + public static System.Numerics.Vector4 IsNegativeInfinity(System.Numerics.Vector4 vector) { throw null; } + public static System.Numerics.Vector4 IsNormal(System.Numerics.Vector4 vector) { throw null; } + public static System.Numerics.Vector4 IsOddInteger(System.Numerics.Vector4 vector) { throw null; } + public static System.Numerics.Vector4 IsPositive(System.Numerics.Vector4 vector) { throw null; } + public static System.Numerics.Vector4 IsPositiveInfinity(System.Numerics.Vector4 vector) { throw null; } + public static System.Numerics.Vector4 IsSubnormal(System.Numerics.Vector4 vector) { throw null; } + public static System.Numerics.Vector4 IsZero(System.Numerics.Vector4 vector) { throw null; } + public static int LastIndexOf(System.Numerics.Vector4 vector, float value) { throw null; } + public static int LastIndexOfWhereAllBitsSet(System.Numerics.Vector4 vector) { throw null; } public readonly float Length() { throw null; } public readonly float LengthSquared() { throw null; } - public static System.Numerics.Vector4 Hypot(System.Numerics.Vector4 x, System.Numerics.Vector4 y) { throw null; } public static System.Numerics.Vector4 Lerp(System.Numerics.Vector4 value1, System.Numerics.Vector4 value2, float amount) { throw null; } public static System.Numerics.Vector4 Lerp(System.Numerics.Vector4 value1, System.Numerics.Vector4 value2, System.Numerics.Vector4 amount) { throw null; } + public static Vector4 LessThan(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } + public static bool LessThanAll(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } + public static bool LessThanAny(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } + public static Vector4 LessThanOrEqual(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } + public static bool LessThanOrEqualAll(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } + public static bool LessThanOrEqualAny(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } public static System.Numerics.Vector4 Log(System.Numerics.Vector4 vector) { throw null; } public static System.Numerics.Vector4 Log2(System.Numerics.Vector4 vector) { throw null; } + [CLSCompliant(false)] + public static unsafe System.Numerics.Vector4 Load(float* source) { throw null; } + [CLSCompliant(false)] + public static unsafe System.Numerics.Vector4 LoadAligned(float* source) { throw null; } + [CLSCompliant(false)] + public static unsafe System.Numerics.Vector4 LoadAlignedNonTemporal(float* source) { throw null; } + public static System.Numerics.Vector4 LoadUnsafe(ref readonly float source) { throw null; } + [CLSCompliant(false)] + public static System.Numerics.Vector4 LoadUnsafe(ref readonly float source, nuint elementOffset) { throw null; } public static System.Numerics.Vector4 Max(System.Numerics.Vector4 value1, System.Numerics.Vector4 value2) { throw null; } public static System.Numerics.Vector4 MaxMagnitude(System.Numerics.Vector4 value1, System.Numerics.Vector4 value2) { throw null; } public static System.Numerics.Vector4 MaxMagnitudeNumber(System.Numerics.Vector4 value1, System.Numerics.Vector4 value2) { throw null; } @@ -728,24 +974,37 @@ public readonly void CopyTo(System.Span destination) { } public static System.Numerics.Vector4 Multiply(float left, System.Numerics.Vector4 right) { throw null; } public static System.Numerics.Vector4 MultiplyAddEstimate(System.Numerics.Vector4 left, System.Numerics.Vector4 right, System.Numerics.Vector4 addend) { throw null; } public static System.Numerics.Vector4 Negate(System.Numerics.Vector4 value) { throw null; } + public static bool None(System.Numerics.Vector4 vector, float value) { throw null; } + public static bool NoneWhereAllBitsSet(System.Numerics.Vector4 vector) { throw null; } public static System.Numerics.Vector4 Normalize(System.Numerics.Vector4 vector) { throw null; } + public static System.Numerics.Vector4 OnesComplement(System.Numerics.Vector4 value) { throw null; } public static System.Numerics.Vector4 operator +(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } + public static System.Numerics.Vector4 operator &(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } + public static System.Numerics.Vector4 operator |(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } public static System.Numerics.Vector4 operator /(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } public static System.Numerics.Vector4 operator /(System.Numerics.Vector4 value1, float value2) { throw null; } + public static System.Numerics.Vector4 operator ^(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } public static bool operator ==(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } + public static System.Numerics.Vector4 operator <<(System.Numerics.Vector4 value, int shiftAmount) { throw null; } public static bool operator !=(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } public static System.Numerics.Vector4 operator *(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } public static System.Numerics.Vector4 operator *(System.Numerics.Vector4 left, float right) { throw null; } public static System.Numerics.Vector4 operator *(float left, System.Numerics.Vector4 right) { throw null; } + public static System.Numerics.Vector4 operator ~(System.Numerics.Vector4 value) { throw null; } + public static System.Numerics.Vector4 operator >>(System.Numerics.Vector4 value, int shiftAmount) { throw null; } public static System.Numerics.Vector4 operator -(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } public static System.Numerics.Vector4 operator -(System.Numerics.Vector4 value) { throw null; } + public static System.Numerics.Vector4 operator +(System.Numerics.Vector4 value) { throw null; } + public static System.Numerics.Vector4 operator >>>(System.Numerics.Vector4 value, int shiftAmount) { throw null; } public static System.Numerics.Vector4 RadiansToDegrees(System.Numerics.Vector4 radians) { throw null; } public static System.Numerics.Vector4 Round(System.Numerics.Vector4 vector) { throw null; } public static System.Numerics.Vector4 Round(System.Numerics.Vector4 vector, System.MidpointRounding mode) { throw null; } + public static System.Numerics.Vector4 Shuffle(System.Numerics.Vector4 vector, byte xIndex, byte yIndex, byte zIndex, byte wIndex) { throw null; } public static System.Numerics.Vector4 Sin(System.Numerics.Vector4 vector) { throw null; } public static (System.Numerics.Vector4 Sin, System.Numerics.Vector4 Cos) SinCos(System.Numerics.Vector4 vector) { throw null; } public static System.Numerics.Vector4 SquareRoot(System.Numerics.Vector4 value) { throw null; } public static System.Numerics.Vector4 Subtract(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } + public static float Sum(System.Numerics.Vector4 value) { throw null; } public override readonly string ToString() { throw null; } public readonly string ToString([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("NumericFormat")] string? format) { throw null; } public readonly string ToString([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("NumericFormat")] string? format, System.IFormatProvider? formatProvider) { throw null; } @@ -756,6 +1015,7 @@ public readonly void CopyTo(System.Span destination) { } public static System.Numerics.Vector4 Transform(System.Numerics.Vector4 vector, System.Numerics.Matrix4x4 matrix) { throw null; } public static System.Numerics.Vector4 Transform(System.Numerics.Vector4 value, System.Numerics.Quaternion rotation) { throw null; } public static System.Numerics.Vector4 Truncate(System.Numerics.Vector4 vector) { throw null; } + public static System.Numerics.Vector4 Xor(System.Numerics.Vector4 left, System.Numerics.Vector4 right) { throw null; } } public readonly partial struct Vector : System.IEquatable>, System.IFormattable { diff --git a/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs b/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs index 2a0ac9701de02e..0ebac20f1b9194 100644 --- a/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs +++ b/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs @@ -4691,76 +4691,604 @@ public void HypotSingleTest(float x, float y, float expectedResult, float varian AssertEqual(Vector.Create(expectedResult), Vector.Hypot(Vector.Create(+y), Vector.Create(+x)), Vector.Create(variance)); } + private void IsEvenInteger(T value) + where T : INumber + { + Assert.Equal(T.IsEvenInteger(value) ? Vector.AllBitsSet : Vector.Zero, Vector.IsEvenInteger(Vector.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerByteTest(byte value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerDoubleTest(double value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerInt16Test(short value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerInt32Test(int value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerInt64Test(long value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerSByteTest(sbyte value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerSingleTest(float value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerUInt16Test(ushort value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerUInt32Test(uint value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerUInt64Test(ulong value) => IsEvenInteger(value); + + private void IsFinite(T value) + where T : INumber + { + Assert.Equal(T.IsFinite(value) ? Vector.AllBitsSet : Vector.Zero, Vector.IsFinite(Vector.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteByteTest(byte value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteDoubleTest(double value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteInt16Test(short value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteInt32Test(int value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteInt64Test(long value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteSByteTest(sbyte value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteSingleTest(float value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteUInt16Test(ushort value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteUInt32Test(uint value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteUInt64Test(ulong value) => IsFinite(value); + + private void IsInfinity(T value) + where T : INumber + { + Assert.Equal(T.IsInfinity(value) ? Vector.AllBitsSet : Vector.Zero, Vector.IsInfinity(Vector.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityByteTest(byte value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityDoubleTest(double value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityInt16Test(short value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityInt32Test(int value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityInt64Test(long value) => IsInfinity(value); + [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsNaNDouble), MemberType = typeof(GenericMathTestMemberData))] - public void IsNaNDoubleTest(double value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinitySByteTest(sbyte value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinitySingleTest(float value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityUInt16Test(ushort value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityUInt32Test(uint value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityUInt64Test(ulong value) => IsInfinity(value); + + private void IsInteger(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector.AllBitsSet : Vector.Zero, Vector.IsNaN(Vector.Create(value))); + Assert.Equal(T.IsInteger(value) ? Vector.AllBitsSet : Vector.Zero, Vector.IsInteger(Vector.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsNaNSingle), MemberType = typeof(GenericMathTestMemberData))] - public void IsNaNSingleTest(float value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerByteTest(byte value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerDoubleTest(double value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerInt16Test(short value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerInt32Test(int value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerInt64Test(long value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerSByteTest(sbyte value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerSingleTest(float value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerUInt16Test(ushort value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerUInt32Test(uint value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerUInt64Test(ulong value) => IsInteger(value); + + private void IsNaN(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector.AllBitsSet : Vector.Zero, Vector.IsNaN(Vector.Create(value))); + Assert.Equal(T.IsNaN(value) ? Vector.AllBitsSet : Vector.Zero, Vector.IsNaN(Vector.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsNegativeDouble), MemberType = typeof(GenericMathTestMemberData))] - public void IsNegativeDoubleTest(double value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNByteTest(byte value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNDoubleTest(double value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNInt16Test(short value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNInt32Test(int value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNInt64Test(long value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNSByteTest(sbyte value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNSingleTest(float value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNUInt16Test(ushort value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNUInt32Test(uint value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNUInt64Test(ulong value) => IsNaN(value); + + private void IsNegative(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector.AllBitsSet : Vector.Zero, Vector.IsNegative(Vector.Create(value))); + Assert.Equal(T.IsNegative(value) ? Vector.AllBitsSet : Vector.Zero, Vector.IsNegative(Vector.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsNegativeSingle), MemberType = typeof(GenericMathTestMemberData))] - public void IsNegativeSingleTest(float value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeByteTest(byte value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeDoubleTest(double value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInt16Test(short value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInt32Test(int value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInt64Test(long value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeSByteTest(sbyte value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeSingleTest(float value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeUInt16Test(ushort value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeUInt32Test(uint value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeUInt64Test(ulong value) => IsNegative(value); + + private void IsNegativeInfinity(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector.AllBitsSet : Vector.Zero, Vector.IsNegative(Vector.Create(value))); + Assert.Equal(T.IsNegativeInfinity(value) ? Vector.AllBitsSet : Vector.Zero, Vector.IsNegativeInfinity(Vector.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsPositiveDouble), MemberType = typeof(GenericMathTestMemberData))] - public void IsPositiveDoubleTest(double value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityByteTest(byte value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityDoubleTest(double value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityInt16Test(short value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityInt32Test(int value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityInt64Test(long value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinitySByteTest(sbyte value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinitySingleTest(float value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityUInt16Test(ushort value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityUInt32Test(uint value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityUInt64Test(ulong value) => IsNegativeInfinity(value); + + private void IsNormal(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector.AllBitsSet : Vector.Zero, Vector.IsPositive(Vector.Create(value))); + Assert.Equal(T.IsNormal(value) ? Vector.AllBitsSet : Vector.Zero, Vector.IsNormal(Vector.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsPositiveSingle), MemberType = typeof(GenericMathTestMemberData))] - public void IsPositiveSingleTest(float value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalByteTest(byte value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalDoubleTest(double value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalInt16Test(short value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalInt32Test(int value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalInt64Test(long value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalSByteTest(sbyte value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalSingleTest(float value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalUInt16Test(ushort value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalUInt32Test(uint value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalUInt64Test(ulong value) => IsNormal(value); + + private void IsOddInteger(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector.AllBitsSet : Vector.Zero, Vector.IsPositive(Vector.Create(value))); + Assert.Equal(T.IsOddInteger(value) ? Vector.AllBitsSet : Vector.Zero, Vector.IsOddInteger(Vector.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsPositiveInfinityDouble), MemberType = typeof(GenericMathTestMemberData))] - public void IsPositiveInfinityDoubleTest(double value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerByteTest(byte value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerDoubleTest(double value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerInt16Test(short value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerInt32Test(int value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerInt64Test(long value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerSByteTest(sbyte value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerSingleTest(float value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerUInt16Test(ushort value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerUInt32Test(uint value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerUInt64Test(ulong value) => IsOddInteger(value); + + private void IsPositive(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector.AllBitsSet : Vector.Zero, Vector.IsPositiveInfinity(Vector.Create(value))); + Assert.Equal(T.IsPositive(value) ? Vector.AllBitsSet : Vector.Zero, Vector.IsPositive(Vector.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsPositiveInfinitySingle), MemberType = typeof(GenericMathTestMemberData))] - public void IsPositiveInfinitySingleTest(float value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveByteTest(byte value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveDoubleTest(double value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInt16Test(short value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInt32Test(int value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInt64Test(long value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveSByteTest(sbyte value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveSingleTest(float value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveUInt16Test(ushort value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveUInt32Test(uint value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveUInt64Test(ulong value) => IsPositive(value); + + private void IsPositiveInfinity(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector.AllBitsSet : Vector.Zero, Vector.IsPositiveInfinity(Vector.Create(value))); + Assert.Equal(T.IsPositiveInfinity(value) ? Vector.AllBitsSet : Vector.Zero, Vector.IsPositiveInfinity(Vector.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsZeroDouble), MemberType = typeof(GenericMathTestMemberData))] - public void IsZeroDoubleTest(double value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityByteTest(byte value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityDoubleTest(double value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityInt16Test(short value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityInt32Test(int value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityInt64Test(long value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinitySByteTest(sbyte value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinitySingleTest(float value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityUInt16Test(ushort value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityUInt32Test(uint value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityUInt64Test(ulong value) => IsPositiveInfinity(value); + + private void IsSubnormal(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector.AllBitsSet : Vector.Zero, Vector.IsZero(Vector.Create(value))); + Assert.Equal(T.IsSubnormal(value) ? Vector.AllBitsSet : Vector.Zero, Vector.IsSubnormal(Vector.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsZeroSingle), MemberType = typeof(GenericMathTestMemberData))] - public void IsZeroSingleTest(float value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalByteTest(byte value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalDoubleTest(double value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalInt16Test(short value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalInt32Test(int value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalInt64Test(long value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalSByteTest(sbyte value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalSingleTest(float value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalUInt16Test(ushort value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalUInt32Test(uint value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalUInt64Test(ulong value) => IsSubnormal(value); + + private void IsZero(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector.AllBitsSet : Vector.Zero, Vector.IsZero(Vector.Create(value))); + Assert.Equal(T.IsZero(value) ? Vector.AllBitsSet : Vector.Zero, Vector.IsZero(Vector.Create(value))); } + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroByteTest(byte value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroDoubleTest(double value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroInt16Test(short value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroInt32Test(int value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroInt64Test(long value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroSByteTest(sbyte value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroSingleTest(float value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroUInt16Test(ushort value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroUInt32Test(uint value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroUInt64Test(ulong value) => IsZero(value); + [Theory] [MemberData(nameof(GenericMathTestMemberData.LerpDouble), MemberType = typeof(GenericMathTestMemberData))] public void LerpDoubleTest(double x, double y, double amount, double expectedResult) @@ -5018,5 +5546,275 @@ public void TruncateSingleTest(float value, float expectedResult) Vector actualResult = Vector.Truncate(Vector.Create(value)); AssertEqual(Vector.Create(expectedResult), actualResult, Vector.Zero); } + + [MethodImpl(MethodImplOptions.NoInlining)] + private void AllAnyNoneTest(T value1, T value2) + where T : struct, INumber + { + var input1 = Vector.Create(value1); + var input2 = Vector.Create(value2); + + Assert.True(Vector.All(input1, value1)); + Assert.True(Vector.All(input2, value2)); + Assert.False(Vector.All(input1.WithElement(0, value2), value1)); + Assert.False(Vector.All(input2.WithElement(0, value1), value2)); + Assert.False(Vector.All(input1, value2)); + Assert.False(Vector.All(input2, value1)); + Assert.False(Vector.All(input1.WithElement(0, value2), value2)); + Assert.False(Vector.All(input2.WithElement(0, value1), value1)); + + Assert.True(Vector.Any(input1, value1)); + Assert.True(Vector.Any(input2, value2)); + Assert.True(Vector.Any(input1.WithElement(0, value2), value1)); + Assert.True(Vector.Any(input2.WithElement(0, value1), value2)); + Assert.False(Vector.Any(input1, value2)); + Assert.False(Vector.Any(input2, value1)); + Assert.True(Vector.Any(input1.WithElement(0, value2), value2)); + Assert.True(Vector.Any(input2.WithElement(0, value1), value1)); + + Assert.False(Vector.None(input1, value1)); + Assert.False(Vector.None(input2, value2)); + Assert.False(Vector.None(input1.WithElement(0, value2), value1)); + Assert.False(Vector.None(input2.WithElement(0, value1), value2)); + Assert.True(Vector.None(input1, value2)); + Assert.True(Vector.None(input2, value1)); + Assert.False(Vector.None(input1.WithElement(0, value2), value2)); + Assert.False(Vector.None(input2.WithElement(0, value1), value1)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private void AllAnyNoneTest_IFloatingPointIeee754(T value) + where T : struct, IFloatingPointIeee754 + { + var input = Vector.Create(value); + + Assert.False(Vector.All(input, value)); + Assert.False(Vector.Any(input, value)); + Assert.True(Vector.None(input, value)); + } + + [Fact] + public void AllAnyNoneByteTest() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneDoubleTest() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneDoubleTest_AllBitsSet() => AllAnyNoneTest_IFloatingPointIeee754(BitConverter.Int64BitsToDouble(-1)); + + [Fact] + public void AllAnyNoneInt16Test() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneInt32Test() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneInt64Test() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneSByteTest() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneSingleTest() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneSingleTest_AllBitsSet() => AllAnyNoneTest_IFloatingPointIeee754(BitConverter.Int32BitsToSingle(-1)); + + [Fact] + public void AllAnyNoneUInt16Test() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneUInt32Test() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneUInt64Test() => AllAnyNoneTest(3, 2); + + [MethodImpl(MethodImplOptions.NoInlining)] + private void AllAnyNoneWhereAllBitsSetTest(T allBitsSet, T value2) + where T : struct, INumber + { + var input1 = Vector.Create(allBitsSet); + var input2 = Vector.Create(value2); + + Assert.True(Vector.AllWhereAllBitsSet(input1)); + Assert.False(Vector.AllWhereAllBitsSet(input2)); + Assert.False(Vector.AllWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.False(Vector.AllWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.True(Vector.AnyWhereAllBitsSet(input1)); + Assert.False(Vector.AnyWhereAllBitsSet(input2)); + Assert.True(Vector.AnyWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.True(Vector.AnyWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.False(Vector.NoneWhereAllBitsSet(input1)); + Assert.True(Vector.NoneWhereAllBitsSet(input2)); + Assert.False(Vector.NoneWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.False(Vector.NoneWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + } + + [Fact] + public void AllAnyNoneWhereAllBitsSetByteTest() => AllAnyNoneWhereAllBitsSetTest(byte.MaxValue, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetDoubleTest() => AllAnyNoneWhereAllBitsSetTest(BitConverter.Int64BitsToDouble(-1), 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetInt16Test() => AllAnyNoneWhereAllBitsSetTest(-1, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetInt32Test() => AllAnyNoneWhereAllBitsSetTest(-1, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetInt64Test() => AllAnyNoneWhereAllBitsSetTest(-1, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetSByteTest() => AllAnyNoneWhereAllBitsSetTest(-1, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetSingleTest() => AllAnyNoneWhereAllBitsSetTest(BitConverter.Int32BitsToSingle(-1), 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetUInt16Test() => AllAnyNoneWhereAllBitsSetTest(ushort.MaxValue, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetUInt32Test() => AllAnyNoneWhereAllBitsSetTest(uint.MaxValue, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetUInt64Test() => AllAnyNoneWhereAllBitsSetTest(ulong.MaxValue, 2); + + [MethodImpl(MethodImplOptions.NoInlining)] + private void CountIndexOfLastIndexOfTest(T value1, T value2) + where T : struct, INumber + { + var input1 = Vector.Create(value1); + var input2 = Vector.Create(value2); + + Assert.Equal(Vector.Count, Vector.Count(input1, value1)); + Assert.Equal(Vector.Count, Vector.Count(input2, value2)); + Assert.Equal(Vector.Count - 1, Vector.Count(input1.WithElement(0, value2), value1)); + Assert.Equal(Vector.Count - 1, Vector.Count(input2.WithElement(0, value1), value2)); + Assert.Equal(0, Vector.Count(input1, value2)); + Assert.Equal(0, Vector.Count(input2, value1)); + Assert.Equal(1, Vector.Count(input1.WithElement(0, value2), value2)); + Assert.Equal(1, Vector.Count(input2.WithElement(0, value1), value1)); + + Assert.Equal(0, Vector.IndexOf(input1, value1)); + Assert.Equal(0, Vector.IndexOf(input2, value2)); + Assert.Equal(1, Vector.IndexOf(input1.WithElement(0, value2), value1)); + Assert.Equal(1, Vector.IndexOf(input2.WithElement(0, value1), value2)); + Assert.Equal(-1, Vector.IndexOf(input1, value2)); + Assert.Equal(-1, Vector.IndexOf(input2, value1)); + Assert.Equal(0, Vector.IndexOf(input1.WithElement(0, value2), value2)); + Assert.Equal(0, Vector.IndexOf(input2.WithElement(0, value1), value1)); + + Assert.Equal(Vector.Count - 1, Vector.LastIndexOf(input1, value1)); + Assert.Equal(Vector.Count - 1, Vector.LastIndexOf(input2, value2)); + Assert.Equal(Vector.Count - 1, Vector.LastIndexOf(input1.WithElement(0, value2), value1)); + Assert.Equal(Vector.Count - 1, Vector.LastIndexOf(input2.WithElement(0, value1), value2)); + Assert.Equal(-1, Vector.LastIndexOf(input1, value2)); + Assert.Equal(-1, Vector.LastIndexOf(input2, value1)); + Assert.Equal(0, Vector.LastIndexOf(input1.WithElement(0, value2), value2)); + Assert.Equal(0, Vector.LastIndexOf(input2.WithElement(0, value1), value1)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private void CountIndexOfLastIndexOfTest_IFloatingPointIeee754(T value) + where T : struct, IFloatingPointIeee754 + { + var input = Vector.Create(value); + + Assert.Equal(0, Vector.Count(input, value)); + Assert.Equal(-1, Vector.IndexOf(input, value)); + Assert.Equal(-1, Vector.LastIndexOf(input, value)); + } + + [Fact] + public void CountIndexOfLastIndexOfByteTest() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfDoubleTest() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfDoubleTest_AllBitsSet() => CountIndexOfLastIndexOfTest_IFloatingPointIeee754(BitConverter.Int64BitsToDouble(-1)); + + [Fact] + public void CountIndexOfLastIndexOfInt16Test() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfInt32Test() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfInt64Test() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfSByteTest() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfSingleTest() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfSingleTest_AllBitsSet() => CountIndexOfLastIndexOfTest_IFloatingPointIeee754(BitConverter.Int32BitsToSingle(-1)); + + [Fact] + public void CountIndexOfLastIndexOfUInt16Test() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfUInt32Test() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfUInt64Test() => CountIndexOfLastIndexOfTest(3, 2); + + [MethodImpl(MethodImplOptions.NoInlining)] + private void CountIndexOfLastIndexOfWhereAllBitsSetTest(T allBitsSet, T value2) + where T : struct, INumber + { + var input1 = Vector.Create(allBitsSet); + var input2 = Vector.Create(value2); + + Assert.Equal(Vector.Count, Vector.CountWhereAllBitsSet(input1)); + Assert.Equal(0, Vector.CountWhereAllBitsSet(input2)); + Assert.Equal(Vector.Count - 1, Vector.CountWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.Equal(1, Vector.CountWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.Equal(0, Vector.IndexOfWhereAllBitsSet(input1)); + Assert.Equal(-1, Vector.IndexOfWhereAllBitsSet(input2)); + Assert.Equal(1, Vector.IndexOfWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.Equal(0, Vector.IndexOfWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.Equal(Vector.Count - 1, Vector.LastIndexOfWhereAllBitsSet(input1)); + Assert.Equal(-1, Vector.LastIndexOfWhereAllBitsSet(input2)); + Assert.Equal(Vector.Count - 1, Vector.LastIndexOfWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.Equal(0, Vector.LastIndexOfWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + } + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetByteTest() => CountIndexOfLastIndexOfWhereAllBitsSetTest(byte.MaxValue, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetDoubleTest() => CountIndexOfLastIndexOfWhereAllBitsSetTest(BitConverter.Int64BitsToDouble(-1), 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetInt16Test() => CountIndexOfLastIndexOfWhereAllBitsSetTest(-1, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetInt32Test() => CountIndexOfLastIndexOfWhereAllBitsSetTest(-1, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetInt64Test() => CountIndexOfLastIndexOfWhereAllBitsSetTest(-1, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetSByteTest() => CountIndexOfLastIndexOfWhereAllBitsSetTest(-1, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetSingleTest() => CountIndexOfLastIndexOfWhereAllBitsSetTest(BitConverter.Int32BitsToSingle(-1), 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetUInt16Test() => CountIndexOfLastIndexOfWhereAllBitsSetTest(ushort.MaxValue, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetUInt32Test() => CountIndexOfLastIndexOfWhereAllBitsSetTest(uint.MaxValue, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetUInt64Test() => CountIndexOfLastIndexOfWhereAllBitsSetTest(ulong.MaxValue, 2); } } diff --git a/src/libraries/System.Numerics.Vectors/tests/Vector2Tests.cs b/src/libraries/System.Numerics.Vectors/tests/Vector2Tests.cs index f2b4a61bbd9bc7..9f6ab423bfab8f 100644 --- a/src/libraries/System.Numerics.Vectors/tests/Vector2Tests.cs +++ b/src/libraries/System.Numerics.Vectors/tests/Vector2Tests.cs @@ -2,7 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Globalization; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; using System.Tests; using Xunit; @@ -10,6 +12,8 @@ namespace System.Numerics.Tests { public sealed class Vector2Tests { + private const int ElementCount = 2; + /// Verifies that two values are equal, within the . /// The expected value /// The value to be compared against @@ -1506,5 +1510,310 @@ public void TruncateSingleTest(float value, float expectedResult) Vector2 actualResult = Vector2.Truncate(Vector2.Create(value)); AssertEqual(Vector2.Create(expectedResult), actualResult, Vector2.Zero); } + + [Fact] + public void AllAnyNoneTest() + { + Test(3, 2); + + [MethodImpl(MethodImplOptions.NoInlining)] + void Test(float value1, float value2) + { + var input1 = Vector2.Create(value1); + var input2 = Vector2.Create(value2); + + Assert.True(Vector2.All(input1, value1)); + Assert.True(Vector2.All(input2, value2)); + Assert.False(Vector2.All(input1.WithElement(0, value2), value1)); + Assert.False(Vector2.All(input2.WithElement(0, value1), value2)); + Assert.False(Vector2.All(input1, value2)); + Assert.False(Vector2.All(input2, value1)); + Assert.False(Vector2.All(input1.WithElement(0, value2), value2)); + Assert.False(Vector2.All(input2.WithElement(0, value1), value1)); + + Assert.True(Vector2.Any(input1, value1)); + Assert.True(Vector2.Any(input2, value2)); + Assert.True(Vector2.Any(input1.WithElement(0, value2), value1)); + Assert.True(Vector2.Any(input2.WithElement(0, value1), value2)); + Assert.False(Vector2.Any(input1, value2)); + Assert.False(Vector2.Any(input2, value1)); + Assert.True(Vector2.Any(input1.WithElement(0, value2), value2)); + Assert.True(Vector2.Any(input2.WithElement(0, value1), value1)); + + Assert.False(Vector2.None(input1, value1)); + Assert.False(Vector2.None(input2, value2)); + Assert.False(Vector2.None(input1.WithElement(0, value2), value1)); + Assert.False(Vector2.None(input2.WithElement(0, value1), value2)); + Assert.True(Vector2.None(input1, value2)); + Assert.True(Vector2.None(input2, value1)); + Assert.False(Vector2.None(input1.WithElement(0, value2), value2)); + Assert.False(Vector2.None(input2.WithElement(0, value1), value1)); + } + } + + [Fact] + public void AllAnyNoneTest_AllBitsSet() + { + Test(BitConverter.Int32BitsToSingle(-1)); + + [MethodImpl(MethodImplOptions.NoInlining)] + void Test(float value) + { + var input = Vector2.Create(value); + + Assert.False(Vector2.All(input, value)); + Assert.False(Vector2.Any(input, value)); + Assert.True(Vector2.None(input, value)); + } + } + + [Fact] + public void AllAnyNoneWhereAllBitsSetTest() + { + Test(BitConverter.Int32BitsToSingle(-1), 2); + + [MethodImpl(MethodImplOptions.NoInlining)] + void Test(float allBitsSet, float value2) + { + var input1 = Vector2.Create(allBitsSet); + var input2 = Vector2.Create(value2); + + Assert.True(Vector2.AllWhereAllBitsSet(input1)); + Assert.False(Vector2.AllWhereAllBitsSet(input2)); + Assert.False(Vector2.AllWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.False(Vector2.AllWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.True(Vector2.AnyWhereAllBitsSet(input1)); + Assert.False(Vector2.AnyWhereAllBitsSet(input2)); + Assert.True(Vector2.AnyWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.True(Vector2.AnyWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.False(Vector2.NoneWhereAllBitsSet(input1)); + Assert.True(Vector2.NoneWhereAllBitsSet(input2)); + Assert.False(Vector2.NoneWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.False(Vector2.NoneWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + } + } + + [Fact] + public void CountIndexOfLastIndexOfSingleTest() + { + Test(3, 2); + + [MethodImpl(MethodImplOptions.NoInlining)] + void Test(float value1, float value2) + { + var input1 = Vector2.Create(value1); + var input2 = Vector2.Create(value2); + + Assert.Equal(ElementCount, Vector2.Count(input1, value1)); + Assert.Equal(ElementCount, Vector2.Count(input2, value2)); + Assert.Equal(ElementCount - 1, Vector2.Count(input1.WithElement(0, value2), value1)); + Assert.Equal(ElementCount - 1, Vector2.Count(input2.WithElement(0, value1), value2)); + Assert.Equal(0, Vector2.Count(input1, value2)); + Assert.Equal(0, Vector2.Count(input2, value1)); + Assert.Equal(1, Vector2.Count(input1.WithElement(0, value2), value2)); + Assert.Equal(1, Vector2.Count(input2.WithElement(0, value1), value1)); + + Assert.Equal(0, Vector2.IndexOf(input1, value1)); + Assert.Equal(0, Vector2.IndexOf(input2, value2)); + Assert.Equal(1, Vector2.IndexOf(input1.WithElement(0, value2), value1)); + Assert.Equal(1, Vector2.IndexOf(input2.WithElement(0, value1), value2)); + Assert.Equal(-1, Vector2.IndexOf(input1, value2)); + Assert.Equal(-1, Vector2.IndexOf(input2, value1)); + Assert.Equal(0, Vector2.IndexOf(input1.WithElement(0, value2), value2)); + Assert.Equal(0, Vector2.IndexOf(input2.WithElement(0, value1), value1)); + + Assert.Equal(ElementCount - 1, Vector2.LastIndexOf(input1, value1)); + Assert.Equal(ElementCount - 1, Vector2.LastIndexOf(input2, value2)); + Assert.Equal(ElementCount - 1, Vector2.LastIndexOf(input1.WithElement(0, value2), value1)); + Assert.Equal(ElementCount - 1, Vector2.LastIndexOf(input2.WithElement(0, value1), value2)); + Assert.Equal(-1, Vector2.LastIndexOf(input1, value2)); + Assert.Equal(-1, Vector2.LastIndexOf(input2, value1)); + Assert.Equal(0, Vector2.LastIndexOf(input1.WithElement(0, value2), value2)); + Assert.Equal(0, Vector2.LastIndexOf(input2.WithElement(0, value1), value1)); + } + } + + [Fact] + public void CountIndexOfLastIndexOfSingleTest_AllBitsSet() + { + Test(BitConverter.Int32BitsToSingle(-1)); + + [MethodImpl(MethodImplOptions.NoInlining)] + void Test(float value) + { + var input = Vector2.Create(value); + + Assert.Equal(0, Vector2.Count(input, value)); + Assert.Equal(-1, Vector2.IndexOf(input, value)); + Assert.Equal(-1, Vector2.LastIndexOf(input, value)); + } + } + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetSingleTest() + { + Test(BitConverter.Int32BitsToSingle(-1), 2); + + [MethodImpl(MethodImplOptions.NoInlining)] + void Test(float allBitsSet, float value2) + { + var input1 = Vector2.Create(allBitsSet); + var input2 = Vector2.Create(value2); + + Assert.Equal(ElementCount, Vector2.CountWhereAllBitsSet(input1)); + Assert.Equal(0, Vector2.CountWhereAllBitsSet(input2)); + Assert.Equal(ElementCount - 1, Vector2.CountWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.Equal(1, Vector2.CountWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.Equal(0, Vector2.IndexOfWhereAllBitsSet(input1)); + Assert.Equal(-1, Vector2.IndexOfWhereAllBitsSet(input2)); + Assert.Equal(1, Vector2.IndexOfWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.Equal(0, Vector2.IndexOfWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.Equal(ElementCount - 1, Vector2.LastIndexOfWhereAllBitsSet(input1)); + Assert.Equal(-1, Vector2.LastIndexOfWhereAllBitsSet(input2)); + Assert.Equal(ElementCount - 1, Vector2.LastIndexOfWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.Equal(0, Vector2.LastIndexOfWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + } + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerTest(float value) => Assert.Equal(float.IsEvenInteger(value) ? Vector2.AllBitsSet : Vector2.Zero, Vector2.IsEvenInteger(Vector2.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteTest(float value) => Assert.Equal(float.IsFinite(value) ? Vector2.AllBitsSet : Vector2.Zero, Vector2.IsFinite(Vector2.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityTest(float value) => Assert.Equal(float.IsInfinity(value) ? Vector2.AllBitsSet : Vector2.Zero, Vector2.IsInfinity(Vector2.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerTest(float value) => Assert.Equal(float.IsInteger(value) ? Vector2.AllBitsSet : Vector2.Zero, Vector2.IsInteger(Vector2.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNTest(float value) => Assert.Equal(float.IsNaN(value) ? Vector2.AllBitsSet : Vector2.Zero, Vector2.IsNaN(Vector2.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeTest(float value) => Assert.Equal(float.IsNegative(value) ? Vector2.AllBitsSet : Vector2.Zero, Vector2.IsNegative(Vector2.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityTest(float value) => Assert.Equal(float.IsNegativeInfinity(value) ? Vector2.AllBitsSet : Vector2.Zero, Vector2.IsNegativeInfinity(Vector2.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalTest(float value) => Assert.Equal(float.IsNormal(value) ? Vector2.AllBitsSet : Vector2.Zero, Vector2.IsNormal(Vector2.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerTest(float value) => Assert.Equal(float.IsOddInteger(value) ? Vector2.AllBitsSet : Vector2.Zero, Vector2.IsOddInteger(Vector2.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveTest(float value) => Assert.Equal(float.IsPositive(value) ? Vector2.AllBitsSet : Vector2.Zero, Vector2.IsPositive(Vector2.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityTest(float value) => Assert.Equal(float.IsPositiveInfinity(value) ? Vector2.AllBitsSet : Vector2.Zero, Vector2.IsPositiveInfinity(Vector2.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalTest(float value) => Assert.Equal(float.IsSubnormal(value) ? Vector2.AllBitsSet : Vector2.Zero, Vector2.IsSubnormal(Vector2.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroSingleTest(float value) => Assert.Equal((value == 0) ? Vector2.AllBitsSet : Vector2.Zero, Vector2.IsZero(Vector2.Create(value))); + + [Fact] + public void AllBitsSetTest() + { + Assert.Equal(-1, BitConverter.SingleToInt32Bits(Vector2.AllBitsSet.X)); + Assert.Equal(-1, BitConverter.SingleToInt32Bits(Vector2.AllBitsSet.Y)); + } + + [Fact] + public void ConditionalSelectTest() + { + Test(Vector2.Create(1, 2), Vector2.AllBitsSet, Vector2.Create(1, 2), Vector2.Create(5, 6)); + Test(Vector2.Create(5, 6), Vector2.Zero, Vector2.Create(1, 2), Vector2.Create(5, 6)); + Test(Vector2.Create(1, 6), Vector128.Create(-1, 0, -1, 0).AsSingle().AsVector2(), Vector2.Create(1, 2), Vector2.Create(5, 6)); + + [MethodImpl(MethodImplOptions.NoInlining)] + void Test(Vector2 expectedResult, Vector2 condition, Vector2 left, Vector2 right) + { + Assert.Equal(expectedResult, Vector2.ConditionalSelect(condition, left, right)); + } + } + + [Theory] + [InlineData(+0.0f, +0.0f, 0b00)] + [InlineData(-0.0f, +1.0f, 0b01)] + [InlineData(-0.0f, -0.0f, 0b11)] + public void ExtractMostSignificantBitsTest(float x, float y, uint expectedResult) + { + Assert.Equal(expectedResult, Vector2.Create(x, y).ExtractMostSignificantBits()); + } + + [Theory] + [InlineData(1.0f, 2.0f)] + [InlineData(5.0f, 6.0f)] + public void GetElementTest(float x, float y) + { + Assert.Equal(x, Vector2.Create(x, y).GetElement(0)); + Assert.Equal(y, Vector2.Create(x, y).GetElement(1)); + } + + [Theory] + [InlineData(1.0f, 2.0f)] + [InlineData(5.0f, 6.0f)] + public void ShuffleTest(float x, float y) + { + Assert.Equal(Vector2.Create(y, x), Vector2.Shuffle(Vector2.Create(x, y), 1, 0)); + Assert.Equal(Vector2.Create(x, x), Vector2.Shuffle(Vector2.Create(x, y), 0, 0)); + } + + [Theory] + [InlineData(1.0f, 2.0f, 3.0f)] + [InlineData(5.0f, 6.0f, 11.0f)] + public void SumTest(float x, float y, float expectedResult) + { + Assert.Equal(expectedResult, Vector2.Sum(Vector2.Create(x, y))); + } + + [Theory] + [InlineData(1.0f, 2.0f)] + [InlineData(5.0f, 6.0f)] + public void ToScalarTest(float x, float y) + { + Assert.Equal(x, Vector2.Create(x, y).ToScalar()); + } + + [Theory] + [InlineData(1.0f, 2.0f)] + [InlineData(5.0f, 6.0f)] + public void WithElementTest(float x, float y) + { + var vector = Vector2.Create(10); + + Assert.Equal(10, vector.X); + Assert.Equal(10, vector.Y); + + vector = vector.WithElement(0, x); + + Assert.Equal(x, vector.X); + Assert.Equal(10, vector.Y); + + vector = vector.WithElement(1, y); + + Assert.Equal(x, vector.X); + Assert.Equal(y, vector.Y); + } } } diff --git a/src/libraries/System.Numerics.Vectors/tests/Vector3Tests.cs b/src/libraries/System.Numerics.Vectors/tests/Vector3Tests.cs index 210caf826fb10d..880cf4be75e7cb 100644 --- a/src/libraries/System.Numerics.Vectors/tests/Vector3Tests.cs +++ b/src/libraries/System.Numerics.Vectors/tests/Vector3Tests.cs @@ -2,7 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Globalization; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; using System.Tests; using Xunit; @@ -10,6 +12,8 @@ namespace System.Numerics.Tests { public sealed class Vector3Tests { + private const int ElementCount = 3; + /// Verifies that two values are equal, within the . /// The expected value /// The value to be compared against @@ -1556,5 +1560,321 @@ public void TruncateSingleTest(float value, float expectedResult) Vector3 actualResult = Vector3.Truncate(Vector3.Create(value)); AssertEqual(Vector3.Create(expectedResult), actualResult, Vector3.Zero); } + + [Fact] + public void AllAnyNoneTest() + { + Test(3, 2); + + [MethodImpl(MethodImplOptions.NoInlining)] + void Test(float value1, float value2) + { + var input1 = Vector3.Create(value1); + var input2 = Vector3.Create(value2); + + Assert.True(Vector3.All(input1, value1)); + Assert.True(Vector3.All(input2, value2)); + Assert.False(Vector3.All(input1.WithElement(0, value2), value1)); + Assert.False(Vector3.All(input2.WithElement(0, value1), value2)); + Assert.False(Vector3.All(input1, value2)); + Assert.False(Vector3.All(input2, value1)); + Assert.False(Vector3.All(input1.WithElement(0, value2), value2)); + Assert.False(Vector3.All(input2.WithElement(0, value1), value1)); + + Assert.True(Vector3.Any(input1, value1)); + Assert.True(Vector3.Any(input2, value2)); + Assert.True(Vector3.Any(input1.WithElement(0, value2), value1)); + Assert.True(Vector3.Any(input2.WithElement(0, value1), value2)); + Assert.False(Vector3.Any(input1, value2)); + Assert.False(Vector3.Any(input2, value1)); + Assert.True(Vector3.Any(input1.WithElement(0, value2), value2)); + Assert.True(Vector3.Any(input2.WithElement(0, value1), value1)); + + Assert.False(Vector3.None(input1, value1)); + Assert.False(Vector3.None(input2, value2)); + Assert.False(Vector3.None(input1.WithElement(0, value2), value1)); + Assert.False(Vector3.None(input2.WithElement(0, value1), value2)); + Assert.True(Vector3.None(input1, value2)); + Assert.True(Vector3.None(input2, value1)); + Assert.False(Vector3.None(input1.WithElement(0, value2), value2)); + Assert.False(Vector3.None(input2.WithElement(0, value1), value1)); + } + } + + [Fact] + public void AllAnyNoneTest_AllBitsSet() + { + Test(BitConverter.Int32BitsToSingle(-1)); + + [MethodImpl(MethodImplOptions.NoInlining)] + void Test(float value) + { + var input = Vector3.Create(value); + + Assert.False(Vector3.All(input, value)); + Assert.False(Vector3.Any(input, value)); + Assert.True(Vector3.None(input, value)); + } + } + + [Fact] + public void AllAnyNoneWhereAllBitsSetTest() + { + Test(BitConverter.Int32BitsToSingle(-1), 2); + + [MethodImpl(MethodImplOptions.NoInlining)] + void Test(float allBitsSet, float value2) + { + var input1 = Vector3.Create(allBitsSet); + var input2 = Vector3.Create(value2); + + Assert.True(Vector3.AllWhereAllBitsSet(input1)); + Assert.False(Vector3.AllWhereAllBitsSet(input2)); + Assert.False(Vector3.AllWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.False(Vector3.AllWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.True(Vector3.AnyWhereAllBitsSet(input1)); + Assert.False(Vector3.AnyWhereAllBitsSet(input2)); + Assert.True(Vector3.AnyWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.True(Vector3.AnyWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.False(Vector3.NoneWhereAllBitsSet(input1)); + Assert.True(Vector3.NoneWhereAllBitsSet(input2)); + Assert.False(Vector3.NoneWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.False(Vector3.NoneWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + } + } + + [Fact] + public void CountIndexOfLastIndexOfSingleTest() + { + Test(3, 2); + + [MethodImpl(MethodImplOptions.NoInlining)] + void Test(float value1, float value2) + { + var input1 = Vector3.Create(value1); + var input2 = Vector3.Create(value2); + + Assert.Equal(ElementCount, Vector3.Count(input1, value1)); + Assert.Equal(ElementCount, Vector3.Count(input2, value2)); + Assert.Equal(ElementCount - 1, Vector3.Count(input1.WithElement(0, value2), value1)); + Assert.Equal(ElementCount - 1, Vector3.Count(input2.WithElement(0, value1), value2)); + Assert.Equal(0, Vector3.Count(input1, value2)); + Assert.Equal(0, Vector3.Count(input2, value1)); + Assert.Equal(1, Vector3.Count(input1.WithElement(0, value2), value2)); + Assert.Equal(1, Vector3.Count(input2.WithElement(0, value1), value1)); + + Assert.Equal(0, Vector3.IndexOf(input1, value1)); + Assert.Equal(0, Vector3.IndexOf(input2, value2)); + Assert.Equal(1, Vector3.IndexOf(input1.WithElement(0, value2), value1)); + Assert.Equal(1, Vector3.IndexOf(input2.WithElement(0, value1), value2)); + Assert.Equal(-1, Vector3.IndexOf(input1, value2)); + Assert.Equal(-1, Vector3.IndexOf(input2, value1)); + Assert.Equal(0, Vector3.IndexOf(input1.WithElement(0, value2), value2)); + Assert.Equal(0, Vector3.IndexOf(input2.WithElement(0, value1), value1)); + + Assert.Equal(ElementCount - 1, Vector3.LastIndexOf(input1, value1)); + Assert.Equal(ElementCount - 1, Vector3.LastIndexOf(input2, value2)); + Assert.Equal(ElementCount - 1, Vector3.LastIndexOf(input1.WithElement(0, value2), value1)); + Assert.Equal(ElementCount - 1, Vector3.LastIndexOf(input2.WithElement(0, value1), value2)); + Assert.Equal(-1, Vector3.LastIndexOf(input1, value2)); + Assert.Equal(-1, Vector3.LastIndexOf(input2, value1)); + Assert.Equal(0, Vector3.LastIndexOf(input1.WithElement(0, value2), value2)); + Assert.Equal(0, Vector3.LastIndexOf(input2.WithElement(0, value1), value1)); + } + } + + [Fact] + public void CountIndexOfLastIndexOfSingleTest_AllBitsSet() + { + Test(BitConverter.Int32BitsToSingle(-1)); + + [MethodImpl(MethodImplOptions.NoInlining)] + void Test(float value) + { + var input = Vector3.Create(value); + + Assert.Equal(0, Vector3.Count(input, value)); + Assert.Equal(-1, Vector3.IndexOf(input, value)); + Assert.Equal(-1, Vector3.LastIndexOf(input, value)); + } + } + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetSingleTest() + { + Test(BitConverter.Int32BitsToSingle(-1), 2); + + [MethodImpl(MethodImplOptions.NoInlining)] + void Test(float allBitsSet, float value2) + { + var input1 = Vector3.Create(allBitsSet); + var input2 = Vector3.Create(value2); + + Assert.Equal(ElementCount, Vector3.CountWhereAllBitsSet(input1)); + Assert.Equal(0, Vector3.CountWhereAllBitsSet(input2)); + Assert.Equal(ElementCount - 1, Vector3.CountWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.Equal(1, Vector3.CountWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.Equal(0, Vector3.IndexOfWhereAllBitsSet(input1)); + Assert.Equal(-1, Vector3.IndexOfWhereAllBitsSet(input2)); + Assert.Equal(1, Vector3.IndexOfWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.Equal(0, Vector3.IndexOfWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.Equal(ElementCount - 1, Vector3.LastIndexOfWhereAllBitsSet(input1)); + Assert.Equal(-1, Vector3.LastIndexOfWhereAllBitsSet(input2)); + Assert.Equal(ElementCount - 1, Vector3.LastIndexOfWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.Equal(0, Vector3.LastIndexOfWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + } + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerTest(float value) => Assert.Equal(float.IsEvenInteger(value) ? Vector3.AllBitsSet : Vector3.Zero, Vector3.IsEvenInteger(Vector3.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteTest(float value) => Assert.Equal(float.IsFinite(value) ? Vector3.AllBitsSet : Vector3.Zero, Vector3.IsFinite(Vector3.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityTest(float value) => Assert.Equal(float.IsInfinity(value) ? Vector3.AllBitsSet : Vector3.Zero, Vector3.IsInfinity(Vector3.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerTest(float value) => Assert.Equal(float.IsInteger(value) ? Vector3.AllBitsSet : Vector3.Zero, Vector3.IsInteger(Vector3.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNTest(float value) => Assert.Equal(float.IsNaN(value) ? Vector3.AllBitsSet : Vector3.Zero, Vector3.IsNaN(Vector3.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeTest(float value) => Assert.Equal(float.IsNegative(value) ? Vector3.AllBitsSet : Vector3.Zero, Vector3.IsNegative(Vector3.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityTest(float value) => Assert.Equal(float.IsNegativeInfinity(value) ? Vector3.AllBitsSet : Vector3.Zero, Vector3.IsNegativeInfinity(Vector3.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalTest(float value) => Assert.Equal(float.IsNormal(value) ? Vector3.AllBitsSet : Vector3.Zero, Vector3.IsNormal(Vector3.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerTest(float value) => Assert.Equal(float.IsOddInteger(value) ? Vector3.AllBitsSet : Vector3.Zero, Vector3.IsOddInteger(Vector3.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveTest(float value) => Assert.Equal(float.IsPositive(value) ? Vector3.AllBitsSet : Vector3.Zero, Vector3.IsPositive(Vector3.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityTest(float value) => Assert.Equal(float.IsPositiveInfinity(value) ? Vector3.AllBitsSet : Vector3.Zero, Vector3.IsPositiveInfinity(Vector3.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalTest(float value) => Assert.Equal(float.IsSubnormal(value) ? Vector3.AllBitsSet : Vector3.Zero, Vector3.IsSubnormal(Vector3.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroSingleTest(float value) => Assert.Equal((value == 0) ? Vector3.AllBitsSet : Vector3.Zero, Vector3.IsZero(Vector3.Create(value))); + + [Fact] + public void AllBitsSetTest() + { + Assert.Equal(-1, BitConverter.SingleToInt32Bits(Vector3.AllBitsSet.X)); + Assert.Equal(-1, BitConverter.SingleToInt32Bits(Vector3.AllBitsSet.Y)); + Assert.Equal(-1, BitConverter.SingleToInt32Bits(Vector3.AllBitsSet.Z)); + } + + [Fact] + public void ConditionalSelectTest() + { + Test(Vector3.Create(1, 2, 3), Vector3.AllBitsSet, Vector3.Create(1, 2, 3), Vector3.Create(5, 6, 7)); + Test(Vector3.Create(5, 6, 7), Vector3.Zero, Vector3.Create(1, 2, 3), Vector3.Create(5, 6, 7)); + Test(Vector3.Create(1, 6, 3), Vector128.Create(-1, 0, -1, 0).AsSingle().AsVector3(), Vector3.Create(1, 2, 3), Vector3.Create(5, 6, 7)); + + [MethodImpl(MethodImplOptions.NoInlining)] + void Test(Vector3 expectedResult, Vector3 condition, Vector3 left, Vector3 right) + { + Assert.Equal(expectedResult, Vector3.ConditionalSelect(condition, left, right)); + } + } + + [Theory] + [InlineData(+0.0f, +0.0f, +0.0f, 0b000)] + [InlineData(-0.0f, +1.0f, -0.0f, 0b101)] + [InlineData(-0.0f, -0.0f, -0.0f, 0b111)] + public void ExtractMostSignificantBitsTest(float x, float y, float z, uint expectedResult) + { + Assert.Equal(expectedResult, Vector3.Create(x, y, z).ExtractMostSignificantBits()); + } + + [Theory] + [InlineData(1.0f, 2.0f, 3.0f)] + [InlineData(5.0f, 6.0f, 7.0f)] + public void GetElementTest(float x, float y, float z) + { + Assert.Equal(x, Vector3.Create(x, y, z).GetElement(0)); + Assert.Equal(y, Vector3.Create(x, y, z).GetElement(1)); + Assert.Equal(z, Vector3.Create(x, y, z).GetElement(2)); + } + + [Theory] + [InlineData(1.0f, 2.0f, 3.0f)] + [InlineData(5.0f, 6.0f, 7.0f)] + public void ShuffleTest(float x, float y, float z) + { + Assert.Equal(Vector3.Create(z, y, x), Vector3.Shuffle(Vector3.Create(x, y, z), 2, 1, 0)); + Assert.Equal(Vector3.Create(y, x, z), Vector3.Shuffle(Vector3.Create(x, y, z), 1, 0, 2)); + } + + [Theory] + [InlineData(1.0f, 2.0f, 3.0f, 6.0f)] + [InlineData(5.0f, 6.0f, 7.0f, 18.0f)] + public void SumTest(float x, float y, float z, float expectedResult) + { + Assert.Equal(expectedResult, Vector3.Sum(Vector3.Create(x, y, z))); + } + + [Theory] + [InlineData(1.0f, 2.0f, 3.0f)] + [InlineData(5.0f, 6.0f, 7.0f)] + public void ToScalarTest(float x, float y, float z) + { + Assert.Equal(x, Vector3.Create(x, y, z).ToScalar()); + } + + [Theory] + [InlineData(1.0f, 2.0f, 3.0f)] + [InlineData(5.0f, 6.0f, 7.0f)] + public void WithElementTest(float x, float y, float z) + { + var vector = Vector3.Create(10); + + Assert.Equal(10, vector.X); + Assert.Equal(10, vector.Y); + Assert.Equal(10, vector.Z); + + vector = vector.WithElement(0, x); + + Assert.Equal(x, vector.X); + Assert.Equal(10, vector.Y); + Assert.Equal(10, vector.Z); + + vector = vector.WithElement(1, y); + + Assert.Equal(x, vector.X); + Assert.Equal(y, vector.Y); + Assert.Equal(10, vector.Z); + + vector = vector.WithElement(2, z); + + Assert.Equal(x, vector.X); + Assert.Equal(y, vector.Y); + Assert.Equal(z, vector.Z); + } } } diff --git a/src/libraries/System.Numerics.Vectors/tests/Vector4Tests.cs b/src/libraries/System.Numerics.Vectors/tests/Vector4Tests.cs index 74ffeeba94c564..ee1f85c9ff2fe7 100644 --- a/src/libraries/System.Numerics.Vectors/tests/Vector4Tests.cs +++ b/src/libraries/System.Numerics.Vectors/tests/Vector4Tests.cs @@ -2,7 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Globalization; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; using System.Tests; using Xunit; @@ -10,6 +12,8 @@ namespace System.Numerics.Tests { public sealed class Vector4Tests { + private const int ElementCount = 4; + /// Verifies that two values are equal, within the . /// The expected value /// The value to be compared against @@ -1931,5 +1935,334 @@ public void TruncateSingleTest(float value, float expectedResult) Vector4 actualResult = Vector4.Truncate(Vector4.Create(value)); AssertEqual(Vector4.Create(expectedResult), actualResult, Vector4.Zero); } + + [Fact] + public void AllAnyNoneTest() + { + Test(3, 2); + + [MethodImpl(MethodImplOptions.NoInlining)] + void Test(float value1, float value2) + { + var input1 = Vector4.Create(value1); + var input2 = Vector4.Create(value2); + + Assert.True(Vector4.All(input1, value1)); + Assert.True(Vector4.All(input2, value2)); + Assert.False(Vector4.All(input1.WithElement(0, value2), value1)); + Assert.False(Vector4.All(input2.WithElement(0, value1), value2)); + Assert.False(Vector4.All(input1, value2)); + Assert.False(Vector4.All(input2, value1)); + Assert.False(Vector4.All(input1.WithElement(0, value2), value2)); + Assert.False(Vector4.All(input2.WithElement(0, value1), value1)); + + Assert.True(Vector4.Any(input1, value1)); + Assert.True(Vector4.Any(input2, value2)); + Assert.True(Vector4.Any(input1.WithElement(0, value2), value1)); + Assert.True(Vector4.Any(input2.WithElement(0, value1), value2)); + Assert.False(Vector4.Any(input1, value2)); + Assert.False(Vector4.Any(input2, value1)); + Assert.True(Vector4.Any(input1.WithElement(0, value2), value2)); + Assert.True(Vector4.Any(input2.WithElement(0, value1), value1)); + + Assert.False(Vector4.None(input1, value1)); + Assert.False(Vector4.None(input2, value2)); + Assert.False(Vector4.None(input1.WithElement(0, value2), value1)); + Assert.False(Vector4.None(input2.WithElement(0, value1), value2)); + Assert.True(Vector4.None(input1, value2)); + Assert.True(Vector4.None(input2, value1)); + Assert.False(Vector4.None(input1.WithElement(0, value2), value2)); + Assert.False(Vector4.None(input2.WithElement(0, value1), value1)); + } + } + + [Fact] + public void AllAnyNoneTest_AllBitsSet() + { + Test(BitConverter.Int32BitsToSingle(-1)); + + [MethodImpl(MethodImplOptions.NoInlining)] + void Test(float value) + { + var input = Vector4.Create(value); + + Assert.False(Vector4.All(input, value)); + Assert.False(Vector4.Any(input, value)); + Assert.True(Vector4.None(input, value)); + } + } + + [Fact] + public void AllAnyNoneWhereAllBitsSetTest() + { + Test(BitConverter.Int32BitsToSingle(-1), 2); + + [MethodImpl(MethodImplOptions.NoInlining)] + void Test(float allBitsSet, float value2) + { + var input1 = Vector4.Create(allBitsSet); + var input2 = Vector4.Create(value2); + + Assert.True(Vector4.AllWhereAllBitsSet(input1)); + Assert.False(Vector4.AllWhereAllBitsSet(input2)); + Assert.False(Vector4.AllWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.False(Vector4.AllWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.True(Vector4.AnyWhereAllBitsSet(input1)); + Assert.False(Vector4.AnyWhereAllBitsSet(input2)); + Assert.True(Vector4.AnyWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.True(Vector4.AnyWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.False(Vector4.NoneWhereAllBitsSet(input1)); + Assert.True(Vector4.NoneWhereAllBitsSet(input2)); + Assert.False(Vector4.NoneWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.False(Vector4.NoneWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + } + } + + [Fact] + public void CountIndexOfLastIndexOfSingleTest() + { + Test(3, 2); + + [MethodImpl(MethodImplOptions.NoInlining)] + void Test(float value1, float value2) + { + var input1 = Vector4.Create(value1); + var input2 = Vector4.Create(value2); + + Assert.Equal(ElementCount, Vector4.Count(input1, value1)); + Assert.Equal(ElementCount, Vector4.Count(input2, value2)); + Assert.Equal(ElementCount - 1, Vector4.Count(input1.WithElement(0, value2), value1)); + Assert.Equal(ElementCount - 1, Vector4.Count(input2.WithElement(0, value1), value2)); + Assert.Equal(0, Vector4.Count(input1, value2)); + Assert.Equal(0, Vector4.Count(input2, value1)); + Assert.Equal(1, Vector4.Count(input1.WithElement(0, value2), value2)); + Assert.Equal(1, Vector4.Count(input2.WithElement(0, value1), value1)); + + Assert.Equal(0, Vector4.IndexOf(input1, value1)); + Assert.Equal(0, Vector4.IndexOf(input2, value2)); + Assert.Equal(1, Vector4.IndexOf(input1.WithElement(0, value2), value1)); + Assert.Equal(1, Vector4.IndexOf(input2.WithElement(0, value1), value2)); + Assert.Equal(-1, Vector4.IndexOf(input1, value2)); + Assert.Equal(-1, Vector4.IndexOf(input2, value1)); + Assert.Equal(0, Vector4.IndexOf(input1.WithElement(0, value2), value2)); + Assert.Equal(0, Vector4.IndexOf(input2.WithElement(0, value1), value1)); + + Assert.Equal(ElementCount - 1, Vector4.LastIndexOf(input1, value1)); + Assert.Equal(ElementCount - 1, Vector4.LastIndexOf(input2, value2)); + Assert.Equal(ElementCount - 1, Vector4.LastIndexOf(input1.WithElement(0, value2), value1)); + Assert.Equal(ElementCount - 1, Vector4.LastIndexOf(input2.WithElement(0, value1), value2)); + Assert.Equal(-1, Vector4.LastIndexOf(input1, value2)); + Assert.Equal(-1, Vector4.LastIndexOf(input2, value1)); + Assert.Equal(0, Vector4.LastIndexOf(input1.WithElement(0, value2), value2)); + Assert.Equal(0, Vector4.LastIndexOf(input2.WithElement(0, value1), value1)); + } + } + + [Fact] + public void CountIndexOfLastIndexOfSingleTest_AllBitsSet() + { + Test(BitConverter.Int32BitsToSingle(-1)); + + [MethodImpl(MethodImplOptions.NoInlining)] + void Test(float value) + { + var input = Vector4.Create(value); + + Assert.Equal(0, Vector4.Count(input, value)); + Assert.Equal(-1, Vector4.IndexOf(input, value)); + Assert.Equal(-1, Vector4.LastIndexOf(input, value)); + } + } + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetSingleTest() + { + Test(BitConverter.Int32BitsToSingle(-1), 2); + + [MethodImpl(MethodImplOptions.NoInlining)] + void Test(float allBitsSet, float value2) + { + var input1 = Vector4.Create(allBitsSet); + var input2 = Vector4.Create(value2); + + Assert.Equal(ElementCount, Vector4.CountWhereAllBitsSet(input1)); + Assert.Equal(0, Vector4.CountWhereAllBitsSet(input2)); + Assert.Equal(ElementCount - 1, Vector4.CountWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.Equal(1, Vector4.CountWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.Equal(0, Vector4.IndexOfWhereAllBitsSet(input1)); + Assert.Equal(-1, Vector4.IndexOfWhereAllBitsSet(input2)); + Assert.Equal(1, Vector4.IndexOfWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.Equal(0, Vector4.IndexOfWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.Equal(ElementCount - 1, Vector4.LastIndexOfWhereAllBitsSet(input1)); + Assert.Equal(-1, Vector4.LastIndexOfWhereAllBitsSet(input2)); + Assert.Equal(ElementCount - 1, Vector4.LastIndexOfWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.Equal(0, Vector4.LastIndexOfWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + } + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerTest(float value) => Assert.Equal(float.IsEvenInteger(value) ? Vector4.AllBitsSet : Vector4.Zero, Vector4.IsEvenInteger(Vector4.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteTest(float value) => Assert.Equal(float.IsFinite(value) ? Vector4.AllBitsSet : Vector4.Zero, Vector4.IsFinite(Vector4.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityTest(float value) => Assert.Equal(float.IsInfinity(value) ? Vector4.AllBitsSet : Vector4.Zero, Vector4.IsInfinity(Vector4.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerTest(float value) => Assert.Equal(float.IsInteger(value) ? Vector4.AllBitsSet : Vector4.Zero, Vector4.IsInteger(Vector4.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNTest(float value) => Assert.Equal(float.IsNaN(value) ? Vector4.AllBitsSet : Vector4.Zero, Vector4.IsNaN(Vector4.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeTest(float value) => Assert.Equal(float.IsNegative(value) ? Vector4.AllBitsSet : Vector4.Zero, Vector4.IsNegative(Vector4.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityTest(float value) => Assert.Equal(float.IsNegativeInfinity(value) ? Vector4.AllBitsSet : Vector4.Zero, Vector4.IsNegativeInfinity(Vector4.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalTest(float value) => Assert.Equal(float.IsNormal(value) ? Vector4.AllBitsSet : Vector4.Zero, Vector4.IsNormal(Vector4.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerTest(float value) => Assert.Equal(float.IsOddInteger(value) ? Vector4.AllBitsSet : Vector4.Zero, Vector4.IsOddInteger(Vector4.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveTest(float value) => Assert.Equal(float.IsPositive(value) ? Vector4.AllBitsSet : Vector4.Zero, Vector4.IsPositive(Vector4.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityTest(float value) => Assert.Equal(float.IsPositiveInfinity(value) ? Vector4.AllBitsSet : Vector4.Zero, Vector4.IsPositiveInfinity(Vector4.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalTest(float value) => Assert.Equal(float.IsSubnormal(value) ? Vector4.AllBitsSet : Vector4.Zero, Vector4.IsSubnormal(Vector4.Create(value))); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroSingleTest(float value) => Assert.Equal((value == 0) ? Vector4.AllBitsSet : Vector4.Zero, Vector4.IsZero(Vector4.Create(value))); + + [Fact] + public void AllBitsSetTest() + { + Assert.Equal(-1, BitConverter.SingleToInt32Bits(Vector4.AllBitsSet.X)); + Assert.Equal(-1, BitConverter.SingleToInt32Bits(Vector4.AllBitsSet.Y)); + Assert.Equal(-1, BitConverter.SingleToInt32Bits(Vector4.AllBitsSet.Z)); + Assert.Equal(-1, BitConverter.SingleToInt32Bits(Vector4.AllBitsSet.W)); + } + + [Fact] + public void ConditionalSelectTest() + { + Test(Vector4.Create(1, 2, 3, 4), Vector4.AllBitsSet, Vector4.Create(1, 2, 3, 4), Vector4.Create(5, 6, 7, 8)); + Test(Vector4.Create(5, 6, 7, 8), Vector4.Zero, Vector4.Create(1, 2, 3, 4), Vector4.Create(5, 6, 7, 8)); + Test(Vector4.Create(1, 6, 3, 8), Vector128.Create(-1, 0, -1, 0).AsSingle().AsVector4(), Vector4.Create(1, 2, 3, 4), Vector4.Create(5, 6, 7, 8)); + + [MethodImpl(MethodImplOptions.NoInlining)] + void Test(Vector4 expectedResult, Vector4 condition, Vector4 left, Vector4 right) + { + Assert.Equal(expectedResult, Vector4.ConditionalSelect(condition, left, right)); + } + } + + [Theory] + [InlineData(+0.0f, +0.0f, +0.0f, +0.0f, 0b0000)] + [InlineData(-0.0f, +1.0f, -0.0f, +0.0f, 0b0101)] + [InlineData(-0.0f, -0.0f, -0.0f, -0.0f, 0b1111)] + public void ExtractMostSignificantBitsTest(float x, float y, float z, float w, uint expectedResult) + { + Assert.Equal(expectedResult, Vector4.Create(x, y, z, w).ExtractMostSignificantBits()); + } + + [Theory] + [InlineData(1.0f, 2.0f, 3.0f, 4.0f)] + [InlineData(5.0f, 6.0f, 7.0f, 8.0f)] + public void GetElementTest(float x, float y, float z, float w) + { + Assert.Equal(x, Vector4.Create(x, y, z, w).GetElement(0)); + Assert.Equal(y, Vector4.Create(x, y, z, w).GetElement(1)); + Assert.Equal(z, Vector4.Create(x, y, z, w).GetElement(2)); + Assert.Equal(w, Vector4.Create(x, y, z, w).GetElement(3)); + } + + [Theory] + [InlineData(1.0f, 2.0f, 3.0f, 4.0f)] + [InlineData(5.0f, 6.0f, 7.0f, 8.0f)] + public void ShuffleTest(float x, float y, float z, float w) + { + Assert.Equal(Vector4.Create(w, z, y, x), Vector4.Shuffle(Vector4.Create(x, y, z, w), 3, 2, 1, 0)); + Assert.Equal(Vector4.Create(y, x, w, z), Vector4.Shuffle(Vector4.Create(x, y, z, w), 1, 0, 3, 2)); + } + + [Theory] + [InlineData(1.0f, 2.0f, 3.0f, 4.0f, 10.0f)] + [InlineData(5.0f, 6.0f, 7.0f, 8.0f, 26.0f)] + public void SumTest(float x, float y, float z, float w, float expectedResult) + { + Assert.Equal(expectedResult, Vector4.Sum(Vector4.Create(x, y, z, w))); + } + + [Theory] + [InlineData(1.0f, 2.0f, 3.0f, 4.0f)] + [InlineData(5.0f, 6.0f, 7.0f, 8.0f)] + public void ToScalarTest(float x, float y, float z, float w) + { + Assert.Equal(x, Vector4.Create(x, y, z, w).ToScalar()); + } + + [Theory] + [InlineData(1.0f, 2.0f, 3.0f, 4.0f)] + [InlineData(5.0f, 6.0f, 7.0f, 8.0f)] + public void WithElementTest(float x, float y, float z, float w) + { + var vector = Vector4.Create(10); + + Assert.Equal(10, vector.X); + Assert.Equal(10, vector.Y); + Assert.Equal(10, vector.Z); + Assert.Equal(10, vector.W); + + vector = vector.WithElement(0, x); + + Assert.Equal(x, vector.X); + Assert.Equal(10, vector.Y); + Assert.Equal(10, vector.Z); + Assert.Equal(10, vector.W); + + vector = vector.WithElement(1, y); + + Assert.Equal(x, vector.X); + Assert.Equal(y, vector.Y); + Assert.Equal(10, vector.Z); + Assert.Equal(10, vector.W); + + vector = vector.WithElement(2, z); + + Assert.Equal(x, vector.X); + Assert.Equal(y, vector.Y); + Assert.Equal(z, vector.Z); + Assert.Equal(10, vector.W); + + vector = vector.WithElement(3, w); + + Assert.Equal(x, vector.X); + Assert.Equal(y, vector.Y); + Assert.Equal(z, vector.Z); + Assert.Equal(w, vector.W); + } } } diff --git a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx index 3e91b3ecb8340f..7c57b8a835b2d3 100644 --- a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx +++ b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx @@ -4271,12 +4271,6 @@ Cannot create a pointer to a byref: {0} - - The type '{0}' cannot be found. - - - The type '{0}' cannot be found in assembly '{1}'. - Method '{0}' overrides '{1}' but it is not virtual. diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index 2fdf95932689b8..61d304184b2865 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -1043,6 +1043,7 @@ + diff --git a/src/libraries/System.Private.CoreLib/src/System/DateOnly.cs b/src/libraries/System.Private.CoreLib/src/System/DateOnly.cs index 7e88362f83f228..f24aa06296c2a4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/DateOnly.cs +++ b/src/libraries/System.Private.CoreLib/src/System/DateOnly.cs @@ -21,7 +21,7 @@ public readonly struct DateOnly ISpanParsable, IUtf8SpanFormattable { - private readonly int _dayNumber; + private readonly uint _dayNumber; // Maps to Jan 1st year 1 private const int MinDayNumber = 0; @@ -29,13 +29,13 @@ public readonly struct DateOnly // Maps to December 31 year 9999. private const int MaxDayNumber = DateTime.DaysTo10000 - 1; - private static int DayNumberFromDateTime(DateTime dt) => (int)((ulong)dt.Ticks / TimeSpan.TicksPerDay); + private static uint DayNumberFromDateTime(DateTime dt) => (uint)((ulong)dt.Ticks / TimeSpan.TicksPerDay); - internal DateTime GetEquivalentDateTime() => DateTime.UnsafeCreate(_dayNumber * TimeSpan.TicksPerDay); + internal DateTime GetEquivalentDateTime() => DateTime.CreateUnchecked(_dayNumber * TimeSpan.TicksPerDay); - private DateOnly(int dayNumber) + private DateOnly(uint dayNumber) { - Debug.Assert((uint)dayNumber <= MaxDayNumber); + Debug.Assert(dayNumber <= MaxDayNumber); _dayNumber = dayNumber; } @@ -77,7 +77,7 @@ public static DateOnly FromDayNumber(int dayNumber) ThrowHelper.ThrowArgumentOutOfRange_DayNumber(dayNumber); } - return new DateOnly(dayNumber); + return new DateOnly((uint)dayNumber); } /// @@ -98,7 +98,7 @@ public static DateOnly FromDayNumber(int dayNumber) /// /// Gets the day of the week represented by this instance. /// - public DayOfWeek DayOfWeek => (DayOfWeek)(((uint)_dayNumber + 1) % 7); + public DayOfWeek DayOfWeek => (DayOfWeek)((_dayNumber + 1) % 7); /// /// Gets the day of the year represented by this instance. @@ -108,7 +108,7 @@ public static DateOnly FromDayNumber(int dayNumber) /// /// Gets the number of days since January 1, 0001 in the Proleptic Gregorian calendar represented by this instance. /// - public int DayNumber => _dayNumber; + public int DayNumber => (int)_dayNumber; /// /// Adds the specified number of days to the value of this instance. @@ -120,8 +120,8 @@ public static DateOnly FromDayNumber(int dayNumber) /// public DateOnly AddDays(int value) { - int newDayNumber = _dayNumber + value; - if ((uint)newDayNumber > MaxDayNumber) + uint newDayNumber = _dayNumber + (uint)value; + if (newDayNumber > MaxDayNumber) { ThrowOutOfRange(); } @@ -214,7 +214,7 @@ public void Deconstruct(out int year, out int month, out int day) /// /// The time of the day. /// The DateTime instance composed of the date of the current DateOnly instance and the time specified by the input time. - public DateTime ToDateTime(TimeOnly time) => new DateTime(_dayNumber * TimeSpan.TicksPerDay + time.Ticks); + public DateTime ToDateTime(TimeOnly time) => DateTime.CreateUnchecked(_dayNumber * TimeSpan.TicksPerDay + time.Ticks); /// /// Returns a DateTime instance with the specified input kind that is set to the date of this DateOnly instance and the time of specified input time. @@ -222,7 +222,7 @@ public void Deconstruct(out int year, out int month, out int day) /// The time of the day. /// One of the enumeration values that indicates whether ticks specifies a local time, Coordinated Universal Time (UTC), or neither. /// The DateTime instance composed of the date of the current DateOnly instance and the time specified by the input time. - public DateTime ToDateTime(TimeOnly time, DateTimeKind kind) => new DateTime(_dayNumber * TimeSpan.TicksPerDay + time.Ticks, kind); + public DateTime ToDateTime(TimeOnly time, DateTimeKind kind) => DateTime.SpecifyKind(ToDateTime(time), kind); /// /// Returns a DateOnly instance that is set to the date part of the specified dateTime. @@ -272,7 +272,7 @@ public int CompareTo(object? value) /// Returns the hash code for this instance. /// /// A 32-bit signed integer hash code. - public override int GetHashCode() => _dayNumber; + public override int GetHashCode() => (int)_dayNumber; private const ParseFlags ParseFlagsDateMask = ParseFlags.HaveHour | ParseFlags.HaveMinute | ParseFlags.HaveSecond | ParseFlags.HaveTime | ParseFlags.TimeZoneUsed | ParseFlags.TimeZoneUtc | ParseFlags.CaptureOffset | ParseFlags.UtcSortPattern; @@ -498,12 +498,12 @@ private static ParseFailureKind TryParseExactInternal(ReadOnlySpan s, Read { case 'o': format = OFormat; - provider = CultureInfo.InvariantCulture.DateTimeFormat; + provider = DateTimeFormat.InvariantFormatInfo; break; case 'r': format = RFormat; - provider = CultureInfo.InvariantCulture.DateTimeFormat; + provider = DateTimeFormat.InvariantFormatInfo; break; } } @@ -575,12 +575,12 @@ private static ParseFailureKind TryParseExactInternal(ReadOnlySpan s, stri { case 'o': format = OFormat; - dtfiToUse = CultureInfo.InvariantCulture.DateTimeFormat; + dtfiToUse = DateTimeFormat.InvariantFormatInfo; break; case 'r': format = RFormat; - dtfiToUse = CultureInfo.InvariantCulture.DateTimeFormat; + dtfiToUse = DateTimeFormat.InvariantFormatInfo; break; } } @@ -718,7 +718,7 @@ private static void ThrowOnError(ParseFailureKind result, ReadOnlySpan s) /// The DateOnly object will be formatted in short form. /// /// A string that contains the short date string representation of the current DateOnly object. - public override string ToString() => ToString("d"); + public override string ToString() => DateTimeFormat.Format(GetEquivalentDateTime(), "d", null); /// /// Converts the value of the current DateOnly object to its equivalent string representation using the specified format and the formatting conventions of the current culture. @@ -732,7 +732,7 @@ private static void ThrowOnError(ParseFailureKind result, ReadOnlySpan s) /// /// An object that supplies culture-specific formatting information. /// A string representation of value of the current DateOnly object as specified by provider. - public string ToString(IFormatProvider? provider) => ToString("d", provider); + public string ToString(IFormatProvider? provider) => DateTimeFormat.Format(GetEquivalentDateTime(), "d", provider); /// /// Converts the value of the current DateOnly object to its equivalent string representation using the specified culture-specific format information. @@ -753,13 +753,13 @@ public string ToString([StringSyntax(StringSyntaxAttribute.DateOnlyFormat)] stri { 'o' => string.Create(10, this, (destination, value) => { - DateTimeFormat.TryFormatDateOnlyO(value.Year, value.Month, value.Day, destination, out int charsWritten); + DateTimeFormat.TryFormatDateOnlyO(value, destination, out int charsWritten); Debug.Assert(charsWritten == destination.Length); }), 'r' => string.Create(16, this, (destination, value) => { - DateTimeFormat.TryFormatDateOnlyR(value.DayOfWeek, value.Year, value.Month, value.Day, destination, out int charsWritten); + DateTimeFormat.TryFormatDateOnlyR(value, destination, out int charsWritten); Debug.Assert(charsWritten == destination.Length); }), @@ -801,10 +801,10 @@ private bool TryFormatCore(Span destination, out int charsWritten, switch (format[0] | 0x20) { case 'o': - return DateTimeFormat.TryFormatDateOnlyO(Year, Month, Day, destination, out charsWritten); + return DateTimeFormat.TryFormatDateOnlyO(this, destination, out charsWritten); case 'r': - return DateTimeFormat.TryFormatDateOnlyR(DayOfWeek, Year, Month, Day, destination, out charsWritten); + return DateTimeFormat.TryFormatDateOnlyR(this, destination, out charsWritten); case 'm': case 'd': diff --git a/src/libraries/System.Private.CoreLib/src/System/DateTime.cs b/src/libraries/System.Private.CoreLib/src/System/DateTime.cs index 30b930841516a1..ca8b47dec25a5d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/DateTime.cs +++ b/src/libraries/System.Private.CoreLib/src/System/DateTime.cs @@ -148,10 +148,11 @@ public DateTime(long ticks) private DateTime(ulong dateData) { - this._dateData = dateData; + Debug.Assert((dateData & TicksMask) <= MaxTicks); + _dateData = dateData; } - internal static DateTime UnsafeCreate(long ticks) => new DateTime((ulong)ticks); + internal static DateTime CreateUnchecked(long ticks) => new DateTime((ulong)ticks); public DateTime(long ticks, DateTimeKind kind) { @@ -1086,7 +1087,7 @@ private static ulong DateToTicks(int year, int month, int day) ThrowHelper.ThrowArgumentOutOfRange_BadYearMonthDay(); } - ReadOnlySpan days = IsLeapYear(year) ? DaysToMonth366 : DaysToMonth365; + ReadOnlySpan days = RuntimeHelpers.IsKnownConstant(month) && month == 1 || IsLeapYear(year) ? DaysToMonth366 : DaysToMonth365; if ((uint)day > days[month] - days[month - 1]) { ThrowHelper.ThrowArgumentOutOfRange_BadYearMonthDay(); diff --git a/src/libraries/System.Private.CoreLib/src/System/DateTimeOffset.cs b/src/libraries/System.Private.CoreLib/src/System/DateTimeOffset.cs index 811eafc1ab4eed..8846329fe93afa 100644 --- a/src/libraries/System.Private.CoreLib/src/System/DateTimeOffset.cs +++ b/src/libraries/System.Private.CoreLib/src/System/DateTimeOffset.cs @@ -59,8 +59,8 @@ public readonly partial struct DateTimeOffset // Static Fields public static readonly DateTimeOffset MinValue; - public static readonly DateTimeOffset MaxValue = new DateTimeOffset(0, DateTime.UnsafeCreate(DateTime.MaxTicks)); - public static readonly DateTimeOffset UnixEpoch = new DateTimeOffset(0, DateTime.UnsafeCreate(DateTime.UnixEpochTicks)); + public static readonly DateTimeOffset MaxValue = new DateTimeOffset(0, DateTime.CreateUnchecked(DateTime.MaxTicks)); + public static readonly DateTimeOffset UnixEpoch = new DateTimeOffset(0, DateTime.CreateUnchecked(DateTime.UnixEpochTicks)); // Instance Fields private readonly DateTime _dateTime; @@ -167,7 +167,7 @@ public DateTimeOffset(int year, int month, int day, int hour, int minute, int se : this(year, month, day, hour, minute, second, offset) { if ((uint)millisecond >= TimeSpan.MillisecondsPerSecond) DateTime.ThrowMillisecondOutOfRange(); - _dateTime = DateTime.UnsafeCreate(UtcTicks + (uint)millisecond * (uint)TimeSpan.TicksPerMillisecond); + _dateTime = DateTime.CreateUnchecked(UtcTicks + (uint)millisecond * (uint)TimeSpan.TicksPerMillisecond); } // Constructs a DateTimeOffset from a given year, month, day, hour, @@ -252,7 +252,7 @@ public DateTimeOffset(int year, int month, int day, int hour, int minute, int se : this(year, month, day, hour, minute, second, millisecond, offset) { if ((uint)microsecond >= TimeSpan.MicrosecondsPerMillisecond) DateTime.ThrowMicrosecondOutOfRange(); - _dateTime = DateTime.UnsafeCreate(UtcTicks + (uint)microsecond * (uint)TimeSpan.TicksPerMicrosecond); + _dateTime = DateTime.CreateUnchecked(UtcTicks + (uint)microsecond * (uint)TimeSpan.TicksPerMicrosecond); } /// @@ -326,14 +326,14 @@ public DateTimeOffset(int year, int month, int day, int hour, int minute, int se : this(year, month, day, hour, minute, second, millisecond, calendar, offset) { if ((uint)microsecond >= TimeSpan.MicrosecondsPerMillisecond) DateTime.ThrowMicrosecondOutOfRange(); - _dateTime = DateTime.UnsafeCreate(UtcTicks + (uint)microsecond * (uint)TimeSpan.TicksPerMicrosecond); + _dateTime = DateTime.CreateUnchecked(UtcTicks + (uint)microsecond * (uint)TimeSpan.TicksPerMicrosecond); } public static DateTimeOffset UtcNow => new DateTimeOffset(0, DateTime.SpecifyKind(DateTime.UtcNow, DateTimeKind.Unspecified)); public DateTime DateTime => ClockDateTime; - public DateTime UtcDateTime => DateTime.UnsafeCreate((long)(_dateTime._dateData | DateTime.KindUtc)); + public DateTime UtcDateTime => DateTime.CreateUnchecked((long)(_dateTime._dateData | DateTime.KindUtc)); public DateTime LocalDateTime => UtcDateTime.ToLocalTime(); @@ -346,7 +346,7 @@ public DateTimeOffset(int year, int month, int day, int hour, int minute, int se // The clock or visible time represented. This is just a wrapper around the internal date because this is // the chosen storage mechanism. Going through this helper is good for readability and maintainability. // This should be used for display but not identity. - private DateTime ClockDateTime => DateTime.UnsafeCreate(UtcTicks + _offsetMinutes * TimeSpan.TicksPerMinute); + private DateTime ClockDateTime => DateTime.CreateUnchecked(UtcTicks + _offsetMinutes * TimeSpan.TicksPerMinute); // Returns the date part of this DateTimeOffset. The resulting value // corresponds to this DateTimeOffset with the time-of-day part set to @@ -587,12 +587,11 @@ public static DateTimeOffset FromUnixTimeSeconds(long seconds) { if (seconds < UnixMinSeconds || seconds > UnixMaxSeconds) { - throw new ArgumentOutOfRangeException(nameof(seconds), - SR.Format(SR.ArgumentOutOfRange_Range, UnixMinSeconds, UnixMaxSeconds)); + ThrowHelper.ThrowArgumentOutOfRange_Range(nameof(seconds), seconds, UnixMinSeconds, UnixMaxSeconds); } long ticks = seconds * TimeSpan.TicksPerSecond + DateTime.UnixEpochTicks; - return new DateTimeOffset(0, DateTime.UnsafeCreate(ticks)); + return new DateTimeOffset(0, DateTime.CreateUnchecked(ticks)); } public static DateTimeOffset FromUnixTimeMilliseconds(long milliseconds) @@ -602,12 +601,11 @@ public static DateTimeOffset FromUnixTimeMilliseconds(long milliseconds) if (milliseconds < MinMilliseconds || milliseconds > MaxMilliseconds) { - throw new ArgumentOutOfRangeException(nameof(milliseconds), - SR.Format(SR.ArgumentOutOfRange_Range, MinMilliseconds, MaxMilliseconds)); + ThrowHelper.ThrowArgumentOutOfRange_Range(nameof(milliseconds), milliseconds, MinMilliseconds, MaxMilliseconds); } long ticks = milliseconds * TimeSpan.TicksPerMillisecond + DateTime.UnixEpochTicks; - return new DateTimeOffset(0, DateTime.UnsafeCreate(ticks)); + return new DateTimeOffset(0, DateTime.CreateUnchecked(ticks)); } // ----- SECTION: private serialization instance methods ----------------* @@ -788,7 +786,7 @@ private static DateTimeOffset ToLocalTime(DateTime utcDateTime, bool throwOnOver localTicks = localTicks < DateTime.MinTicks ? DateTime.MinTicks : DateTime.MaxTicks; } - return CreateValidateOffset(DateTime.UnsafeCreate(localTicks), offset); + return CreateValidateOffset(DateTime.CreateUnchecked(localTicks), offset); } public override string ToString() => @@ -947,7 +945,7 @@ private static DateTime ValidateDate(DateTime dateTime, TimeSpan offset) static void ThrowOutOfRange() => throw new ArgumentOutOfRangeException(nameof(offset), SR.Argument_UTCOutOfRange); } // make sure the Kind is set to Unspecified - return DateTime.UnsafeCreate(utcTicks); + return DateTime.CreateUnchecked(utcTicks); } private static DateTimeStyles ValidateStyles(DateTimeStyles styles) diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs index 8bf344f4e73356..aebe43c1640289 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs @@ -418,7 +418,7 @@ private static bool IsDefinedSafe(MemberInfo memberInfo, Type attributeType, boo } } - private static Attribute[] GetCustomAttributesSafe(MemberInfo memberInfo, Type attributeType, bool inherit) + private static Attribute[]? GetCustomAttributesSafe(MemberInfo memberInfo, Type attributeType, bool inherit) { try { @@ -426,9 +426,9 @@ private static Attribute[] GetCustomAttributesSafe(MemberInfo memberInfo, Type a } catch { - // Getting the attributes has failed, return an empty array. One of the reasons + // Getting the attributes has failed, return null. One of the reasons // can be that the member has attributes defined in an assembly that is missing. - return []; + return null; } } @@ -459,7 +459,7 @@ private static bool TryResolveStateMachineMethod(ref MethodBase method, out Type foreach (MethodInfo candidateMethod in methods) { - StateMachineAttribute[]? attributes = (StateMachineAttribute[])GetCustomAttributesSafe(candidateMethod, typeof(StateMachineAttribute), inherit: false); + StateMachineAttribute[]? attributes = (StateMachineAttribute[]?)GetCustomAttributesSafe(candidateMethod, typeof(StateMachineAttribute), inherit: false); if (attributes == null) { continue; diff --git a/src/libraries/System.Private.CoreLib/src/System/Double.cs b/src/libraries/System.Private.CoreLib/src/System/Double.cs index 8d24c4024c3000..c4ed8ed65587ad 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Double.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Double.cs @@ -85,7 +85,7 @@ public readonly struct Double internal const ulong BiasedExponentMask = 0x7FF0_0000_0000_0000; internal const int BiasedExponentShift = 52; internal const int BiasedExponentLength = 11; - internal const ushort ShiftedExponentMask = (ushort)(BiasedExponentMask >> BiasedExponentShift); + internal const ushort ShiftedBiasedExponentMask = (ushort)(BiasedExponentMask >> BiasedExponentShift); internal const ulong TrailingSignificandMask = 0x000F_FFFF_FFFF_FFFF; @@ -154,7 +154,7 @@ internal ulong TrailingSignificand internal static ushort ExtractBiasedExponentFromBits(ulong bits) { - return (ushort)((bits >> BiasedExponentShift) & ShiftedExponentMask); + return (ushort)((bits >> BiasedExponentShift) & ShiftedBiasedExponentMask); } internal static ulong ExtractTrailingSignificandFromBits(ulong bits) @@ -177,8 +177,8 @@ public static bool IsFinite(double d) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsInfinity(double d) { - ulong bits = BitConverter.DoubleToUInt64Bits(d); - return (bits & ~SignMask) == PositiveInfinityBits; + ulong bits = BitConverter.DoubleToUInt64Bits(Abs(d)); + return bits == PositiveInfinityBits; } /// Determines whether the specified value is NaN. @@ -224,8 +224,8 @@ public static bool IsNegativeInfinity(double d) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsNormal(double d) { - ulong bits = BitConverter.DoubleToUInt64Bits(d); - return ((bits & ~SignMask) - SmallestNormalBits) < (PositiveInfinityBits - SmallestNormalBits); + ulong bits = BitConverter.DoubleToUInt64Bits(Abs(d)); + return (bits - SmallestNormalBits) < (PositiveInfinityBits - SmallestNormalBits); } /// Determines whether the specified value is positive infinity. @@ -242,8 +242,8 @@ public static bool IsPositiveInfinity(double d) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsSubnormal(double d) { - ulong bits = BitConverter.DoubleToUInt64Bits(d); - return ((bits & ~SignMask) - 1) < MaxTrailingSignificand; + ulong bits = BitConverter.DoubleToUInt64Bits(Abs(d)); + return (bits - 1) < MaxTrailingSignificand; } [NonVersionable] @@ -941,7 +941,24 @@ bool IFloatingPoint.TryWriteSignificandLittleEndian(Span destinati // /// - public static double Clamp(double value, double min, double max) => Math.Clamp(value, min, max); + public static double Clamp(double value, double min, double max) + { + if (min > max) + { + Math.ThrowMinMaxException(min, max); + } + return Min(Max(value, min), max); + } + + /// + public static double ClampNative(double value, double min, double max) + { + if (min > max) + { + Math.ThrowMinMaxException(min, max); + } + return MinNative(MaxNative(value, min), max); + } /// public static double CopySign(double value, double sign) => Math.CopySign(value, sign); @@ -950,6 +967,10 @@ bool IFloatingPoint.TryWriteSignificandLittleEndian(Span destinati [Intrinsic] public static double Max(double x, double y) => Math.Max(x, y); + /// + [Intrinsic] + public static double MaxNative(double x, double y) => (x > y) ? x : y; + /// [Intrinsic] public static double MaxNumber(double x, double y) @@ -977,6 +998,10 @@ public static double MaxNumber(double x, double y) [Intrinsic] public static double Min(double x, double y) => Math.Min(x, y); + /// + [Intrinsic] + public static double MinNative(double x, double y) => (x < y) ? x : y; + /// [Intrinsic] public static double MinNumber(double x, double y) @@ -1489,8 +1514,8 @@ public static double Hypot(double x, double y) ulong xBits = BitConverter.DoubleToUInt64Bits(ax); ulong yBits = BitConverter.DoubleToUInt64Bits(ay); - uint xExp = (uint)((xBits >> BiasedExponentShift) & ShiftedExponentMask); - uint yExp = (uint)((yBits >> BiasedExponentShift) & ShiftedExponentMask); + uint xExp = (uint)((xBits >> BiasedExponentShift) & ShiftedBiasedExponentMask); + uint yExp = (uint)((yBits >> BiasedExponentShift) & ShiftedBiasedExponentMask); int expDiff = (int)(xExp - yExp); double expFix = 1.0; diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs index a7ca7828e6e493..bb7952affe4b73 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs @@ -1313,7 +1313,7 @@ internal static bool IsValidCustomTimeOnlyFormat(ReadOnlySpan format, bool // 012345678901234567890123456789012 // --------------------------------- // 05:30:45.7680000 - internal static unsafe bool TryFormatTimeOnlyO(int hour, int minute, int second, long fraction, Span destination, out int charsWritten) where TChar : unmanaged, IUtfChar + internal static unsafe bool TryFormatTimeOnlyO(TimeOnly value, Span destination, out int charsWritten) where TChar : unmanaged, IUtfChar { if (destination.Length < 16) { @@ -1322,6 +1322,7 @@ internal static unsafe bool TryFormatTimeOnlyO(int hour, int minute, int } charsWritten = 16; + value.ToDateTime().GetTimePrecise(out int hour, out int minute, out int second, out int fraction); fixed (TChar* dest = &MemoryMarshal.GetReference(destination)) { @@ -1340,7 +1341,7 @@ internal static unsafe bool TryFormatTimeOnlyO(int hour, int minute, int // 012345678901234567890123456789012 // --------------------------------- // 05:30:45 - internal static unsafe bool TryFormatTimeOnlyR(int hour, int minute, int second, Span destination, out int charsWritten) where TChar : unmanaged, IUtfChar + internal static unsafe bool TryFormatTimeOnlyR(TimeOnly value, Span destination, out int charsWritten) where TChar : unmanaged, IUtfChar { if (destination.Length < 8) { @@ -1349,6 +1350,7 @@ internal static unsafe bool TryFormatTimeOnlyR(int hour, int minute, int } charsWritten = 8; + value.ToDateTime().GetTime(out int hour, out int minute, out int second); fixed (TChar* dest = &MemoryMarshal.GetReference(destination)) { @@ -1366,7 +1368,7 @@ internal static unsafe bool TryFormatTimeOnlyR(int hour, int minute, int // 012345678901234567890123456789012 // --------------------------------- // 2017-06-12 - internal static unsafe bool TryFormatDateOnlyO(int year, int month, int day, Span destination, out int charsWritten) where TChar : unmanaged, IUtfChar + internal static unsafe bool TryFormatDateOnlyO(DateOnly value, Span destination, out int charsWritten) where TChar : unmanaged, IUtfChar { if (destination.Length < 10) { @@ -1375,6 +1377,7 @@ internal static unsafe bool TryFormatDateOnlyO(int year, int month, int d } charsWritten = 10; + (int year, int month, int day) = value; fixed (TChar* dest = &MemoryMarshal.GetReference(destination)) { @@ -1392,7 +1395,7 @@ internal static unsafe bool TryFormatDateOnlyO(int year, int month, int d // 01234567890123456789012345678 // ----------------------------- // Tue, 03 Jan 2017 - internal static unsafe bool TryFormatDateOnlyR(DayOfWeek dayOfWeek, int year, int month, int day, Span destination, out int charsWritten) where TChar : unmanaged, IUtfChar + internal static unsafe bool TryFormatDateOnlyR(DateOnly value, Span destination, out int charsWritten) where TChar : unmanaged, IUtfChar { if (destination.Length < 16) { @@ -1401,9 +1404,9 @@ internal static unsafe bool TryFormatDateOnlyR(DayOfWeek dayOfWeek, int y } charsWritten = 16; + (int year, int month, int day) = value; - Debug.Assert((uint)dayOfWeek < 7); - string dayAbbrev = s_invariantAbbreviatedDayNames[(int)dayOfWeek]; + string dayAbbrev = s_invariantAbbreviatedDayNames[(int)value.DayOfWeek]; Debug.Assert(dayAbbrev.Length == 3); string monthAbbrev = s_invariantAbbreviatedMonthNames[month - 1]; @@ -1467,7 +1470,6 @@ internal static unsafe bool TryFormatO(DateTime dateTime, TimeSpan offset charsWritten = charsRequired; dateTime.GetDate(out int year, out int month, out int day); - dateTime.GetTimePrecise(out int hour, out int minute, out int second, out int tick); fixed (TChar* dest = &MemoryMarshal.GetReference(destination)) { @@ -1477,6 +1479,7 @@ internal static unsafe bool TryFormatO(DateTime dateTime, TimeSpan offset dest[7] = TChar.CastFrom('-'); Number.WriteTwoDigits((uint)day, dest + 8); dest[10] = TChar.CastFrom('T'); + dateTime.GetTimePrecise(out int hour, out int minute, out int second, out int tick); Number.WriteTwoDigits((uint)hour, dest + 11); dest[13] = TChar.CastFrom(':'); Number.WriteTwoDigits((uint)minute, dest + 14); @@ -1527,7 +1530,6 @@ internal static unsafe bool TryFormatS(DateTime dateTime, Span des charsWritten = FormatSLength; dateTime.GetDate(out int year, out int month, out int day); - dateTime.GetTime(out int hour, out int minute, out int second); fixed (TChar* dest = &MemoryMarshal.GetReference(destination)) { @@ -1537,6 +1539,7 @@ internal static unsafe bool TryFormatS(DateTime dateTime, Span des dest[7] = TChar.CastFrom('-'); Number.WriteTwoDigits((uint)day, dest + 8); dest[10] = TChar.CastFrom('T'); + dateTime.GetTime(out int hour, out int minute, out int second); Number.WriteTwoDigits((uint)hour, dest + 11); dest[13] = TChar.CastFrom(':'); Number.WriteTwoDigits((uint)minute, dest + 14); @@ -1567,7 +1570,6 @@ internal static unsafe bool TryFormatu(DateTime dateTime, TimeSpan offset } dateTime.GetDate(out int year, out int month, out int day); - dateTime.GetTime(out int hour, out int minute, out int second); fixed (TChar* dest = &MemoryMarshal.GetReference(destination)) { @@ -1577,6 +1579,7 @@ internal static unsafe bool TryFormatu(DateTime dateTime, TimeSpan offset dest[7] = TChar.CastFrom('-'); Number.WriteTwoDigits((uint)day, dest + 8); dest[10] = TChar.CastFrom(' '); + dateTime.GetTime(out int hour, out int minute, out int second); Number.WriteTwoDigits((uint)hour, dest + 11); dest[13] = TChar.CastFrom(':'); Number.WriteTwoDigits((uint)minute, dest + 14); @@ -1609,7 +1612,6 @@ internal static unsafe bool TryFormatR(DateTime dateTime, TimeSpan offset } dateTime.GetDate(out int year, out int month, out int day); - dateTime.GetTime(out int hour, out int minute, out int second); string dayAbbrev = s_invariantAbbreviatedDayNames[(int)dateTime.DayOfWeek]; Debug.Assert(dayAbbrev.Length == 3); @@ -1634,6 +1636,7 @@ internal static unsafe bool TryFormatR(DateTime dateTime, TimeSpan offset dest[11] = TChar.CastFrom(' '); Number.WriteFourDigits((uint)year, dest + 12); dest[16] = TChar.CastFrom(' '); + dateTime.GetTime(out int hour, out int minute, out int second); Number.WriteTwoDigits((uint)hour, dest + 17); dest[19] = TChar.CastFrom(':'); Number.WriteTwoDigits((uint)minute, dest + 20); @@ -1674,7 +1677,6 @@ internal static unsafe bool TryFormatInvariantG(DateTime value, TimeSpan bytesWritten = bytesRequired; value.GetDate(out int year, out int month, out int day); - value.GetTime(out int hour, out int minute, out int second); fixed (TChar* dest = &MemoryMarshal.GetReference(destination)) { @@ -1685,6 +1687,7 @@ internal static unsafe bool TryFormatInvariantG(DateTime value, TimeSpan Number.WriteFourDigits((uint)year, dest + 6); dest[10] = TChar.CastFrom(' '); + value.GetTime(out int hour, out int minute, out int second); Number.WriteTwoDigits((uint)hour, dest + 11); dest[13] = TChar.CastFrom(':'); Number.WriteTwoDigits((uint)minute, dest + 14); diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/ISOWeek.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/ISOWeek.cs index ee175f0f1bf3aa..3dfb11ba63acdd 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/ISOWeek.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/ISOWeek.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.CompilerServices; using static System.Globalization.GregorianCalendar; namespace System.Globalization @@ -24,7 +25,7 @@ public static int GetWeekOfYear(DateTime date) return GetWeeksInYear(date.Year - 1); } - if (week > GetWeeksInYear(date.Year)) + if (week > WeeksInShortYear && GetWeeksInYear(date.Year) == WeeksInShortYear) { // If a week number of 53 is obtained, one must check that // the date is not actually in week 1 of the following year. @@ -44,22 +45,22 @@ public static int GetWeekOfYear(DateTime date) public static int GetYear(DateTime date) { int week = GetWeekNumber(date); + int year = date.Year; if (week < MinWeek) { // If the week number obtained equals 0, it means that the // given date belongs to the preceding (week-based) year. - return date.Year - 1; + year--; } - - if (week > GetWeeksInYear(date.Year)) + else if (week > WeeksInShortYear && GetWeeksInYear(year) == WeeksInShortYear) { // If a week number of 53 is obtained, one must check that // the date is not actually in week 1 of the following year. - return date.Year + 1; + year++; } - return date.Year; + return year; } /// @@ -100,12 +101,17 @@ public static int GetWeeksInYear(int year) { if (year < MinYear || year > MaxYear) { - throw new ArgumentOutOfRangeException(nameof(year), SR.ArgumentOutOfRange_Year); + ThrowHelper.ThrowArgumentOutOfRange_Year(); } - static int P(int y) => (y + (y / 4) - (y / 100) + (y / 400)) % 7; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static uint P(uint y) + { + uint cent = y / 100; + return (y + (y / 4) - cent + cent / 4) % 7; + } - if (P(year) == 4 || P(year - 1) == 3) + if (P((uint)year) == 4 || P((uint)year - 1) == 3) { return WeeksInLongYear; } @@ -127,7 +133,7 @@ public static DateTime ToDateTime(int year, int week, DayOfWeek dayOfWeek) { if (year < MinYear || year > MaxYear) { - throw new ArgumentOutOfRangeException(nameof(year), SR.ArgumentOutOfRange_Year); + ThrowHelper.ThrowArgumentOutOfRange_Year(); } if (week < MinWeek || week > MaxWeek) @@ -149,7 +155,7 @@ public static DateTime ToDateTime(int year, int week, DayOfWeek dayOfWeek) int ordinal = (week * 7) + GetWeekday(dayOfWeek) - correction; - return new DateTime(year, month: 1, day: 1).AddDays(ordinal - 1); + return jan4.AddTicks((ordinal - 4) * TimeSpan.TicksPerDay); } @@ -172,7 +178,7 @@ public static DateTime ToDateTime(int year, int week, DayOfWeek dayOfWeek) // If a week number of 53 is obtained, one must check that the date is not actually in week 1 of the following year. private static int GetWeekNumber(DateTime date) { - return (date.DayOfYear - GetWeekday(date.DayOfWeek) + 10) / 7; + return (int)((uint)(date.DayOfYear - GetWeekday(date.DayOfWeek) + 10) / 7); } // Day of week in ISO is represented by an integer from 1 through 7, beginning with Monday and ending with Sunday. diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs index 68bcde60f941da..b9ed56a9fb06a4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/Ordinal.cs @@ -81,10 +81,10 @@ internal static int CompareStringIgnoreCaseNonAscii(ref char strA, int lengthA, private static bool EqualsIgnoreCase_Vector(ref char charA, ref char charB, int length) where TVector : struct, ISimdVector { - Debug.Assert(length >= TVector.Count); + Debug.Assert(length >= TVector.ElementCount); nuint lengthU = (nuint)length; - nuint lengthToExamine = lengthU - (nuint)TVector.Count; + nuint lengthToExamine = lengthU - (nuint)TVector.ElementCount; nuint i = 0; TVector vec1; TVector vec2; @@ -113,13 +113,13 @@ private static bool EqualsIgnoreCase_Vector(ref char charA, ref char ch return false; // first input isn't in [A-Za-z], and not exact match of lowered } } - i += (nuint)TVector.Count; + i += (nuint)TVector.ElementCount; } while (i <= lengthToExamine); // Handle trailing elements if (i != lengthU) { - i = lengthU - (nuint)TVector.Count; + i = lengthU - (nuint)TVector.ElementCount; vec1 = TVector.LoadUnsafe(ref Unsafe.As(ref charA), i); vec2 = TVector.LoadUnsafe(ref Unsafe.As(ref charB), i); diff --git a/src/libraries/System.Private.CoreLib/src/System/Guid.cs b/src/libraries/System.Private.CoreLib/src/System/Guid.cs index 999e82e81377e5..37c8cc2d50e8fe 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Guid.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Guid.cs @@ -900,13 +900,13 @@ public byte[] ToByteArray() var g = new byte[16]; if (BitConverter.IsLittleEndian) { - MemoryMarshal.TryWrite(g, in this); + MemoryMarshal.Write(g, in this); } else { // slower path for BigEndian Guid guid = new Guid(MemoryMarshal.AsBytes(new ReadOnlySpan(in this)), false); - MemoryMarshal.TryWrite(g, in guid); + MemoryMarshal.Write(g, in guid); } return g; } @@ -918,13 +918,13 @@ public byte[] ToByteArray(bool bigEndian) var g = new byte[16]; if (BitConverter.IsLittleEndian != bigEndian) { - MemoryMarshal.TryWrite(g, in this); + MemoryMarshal.Write(g, in this); } else { // slower path for Reverse Guid guid = new Guid(MemoryMarshal.AsBytes(new ReadOnlySpan(in this)), bigEndian); - MemoryMarshal.TryWrite(g, in guid); + MemoryMarshal.Write(g, in guid); } return g; } @@ -937,13 +937,13 @@ public bool TryWriteBytes(Span destination) if (BitConverter.IsLittleEndian) { - MemoryMarshal.TryWrite(destination, in this); + MemoryMarshal.Write(destination, in this); } else { // slower path for BigEndian Guid guid = new Guid(MemoryMarshal.AsBytes(new ReadOnlySpan(in this)), false); - MemoryMarshal.TryWrite(destination, in guid); + MemoryMarshal.Write(destination, in guid); } return true; } @@ -959,13 +959,13 @@ public bool TryWriteBytes(Span destination, bool bigEndian, out int bytesW if (BitConverter.IsLittleEndian != bigEndian) { - MemoryMarshal.TryWrite(destination, in this); + MemoryMarshal.Write(destination, in this); } else { // slower path for Reverse Guid guid = new Guid(MemoryMarshal.AsBytes(new ReadOnlySpan(in this)), bigEndian); - MemoryMarshal.TryWrite(destination, in guid); + MemoryMarshal.Write(destination, in guid); } bytesWritten = 16; return true; diff --git a/src/libraries/System.Private.CoreLib/src/System/Half.cs b/src/libraries/System.Private.CoreLib/src/System/Half.cs index dab5e73a278876..80e3f9532248a4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Half.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Half.cs @@ -1641,7 +1641,17 @@ public static int ILogB(Half x) // /// - public static Half Clamp(Half value, Half min, Half max) => (Half)Math.Clamp((float)value, (float)min, (float)max); + public static Half Clamp(Half value, Half min, Half max) => (Half)float.Clamp((float)value, (float)min, (float)max); + + /// + public static Half ClampNative(Half value, Half min, Half max) + { + if (min > max) + { + Math.ThrowMinMaxException(min, max); + } + return MinNative(MaxNative(value, min), max); + } /// public static Half CopySign(Half value, Half sign) @@ -1657,7 +1667,10 @@ public static Half CopySign(Half value, Half sign) } /// - public static Half Max(Half x, Half y) => (Half)MathF.Max((float)x, (float)y); + public static Half Max(Half x, Half y) => (Half)float.Max((float)x, (float)y); + + /// + public static Half MaxNative(Half x, Half y) => (x > y) ? x : y; /// public static Half MaxNumber(Half x, Half y) @@ -1682,7 +1695,10 @@ public static Half MaxNumber(Half x, Half y) } /// - public static Half Min(Half x, Half y) => (Half)MathF.Min((float)x, (float)y); + public static Half Min(Half x, Half y) => (Half)float.Min((float)x, (float)y); + + /// + public static Half MinNative(Half x, Half y) => (x < y) ? x : y; /// public static Half MinNumber(Half x, Half y) diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs b/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs index 38a752c6810ffe..e22a12d24f6440 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs @@ -268,11 +268,11 @@ internal static partial class Number 300; #endif /// Lazily-populated cache of strings for uint values in the range [0, ). - private static readonly string[] s_smallNumberCache = new string[SmallNumberCacheLength]; + private static readonly string?[] s_smallNumberCache = new string[SmallNumberCacheLength]; // Optimizations using "TwoDigits" inspired by: // https://engineering.fb.com/2013/03/15/developer-tools/three-optimization-tips-for-c/ - private static readonly byte[] TwoDigitsCharsAsBytes = + private static ReadOnlySpan TwoDigitsCharsAsBytes => MemoryMarshal.AsBytes("00010203040506070809" + "10111213141516171819" + "20212223242526272829" + @@ -282,9 +282,9 @@ internal static partial class Number "60616263646566676869" + "70717273747576777879" + "80818283848586878889" + - "90919293949596979899").ToArray(); - private static readonly byte[] TwoDigitsBytes = - ("00010203040506070809"u8 + + "90919293949596979899"); + private static ReadOnlySpan TwoDigitsBytes => + "00010203040506070809"u8 + "10111213141516171819"u8 + "20212223242526272829"u8 + "30313233343536373839"u8 + @@ -293,7 +293,7 @@ internal static partial class Number "60616263646566676869"u8 + "70717273747576777879"u8 + "80818283848586878889"u8 + - "90919293949596979899"u8).ToArray(); + "90919293949596979899"u8; public static unsafe string FormatDecimal(decimal value, ReadOnlySpan format, NumberFormatInfo info) { @@ -387,9 +387,8 @@ private static int GetFloatingPointMaxDigitsAndPrecision(char fmt, ref int preci int maxDigits = precision; - switch (fmt) + switch (fmt | 0x20) { - case 'C': case 'c': { // The currency format uses the precision specifier to indicate the number of @@ -404,7 +403,6 @@ private static int GetFloatingPointMaxDigitsAndPrecision(char fmt, ref int preci break; } - case 'E': case 'e': { // The exponential format uses the precision specifier to indicate the number of @@ -423,9 +421,7 @@ private static int GetFloatingPointMaxDigitsAndPrecision(char fmt, ref int preci break; } - case 'F': case 'f': - case 'N': case 'n': { // The fixed-point and number formats use the precision specifier to indicate the number @@ -440,7 +436,6 @@ private static int GetFloatingPointMaxDigitsAndPrecision(char fmt, ref int preci break; } - case 'G': case 'g': { // The general format uses the precision specifier to indicate the number of significant @@ -457,7 +452,6 @@ private static int GetFloatingPointMaxDigitsAndPrecision(char fmt, ref int preci break; } - case 'P': case 'p': { // The percent format uses the precision specifier to indicate the number of @@ -476,7 +470,6 @@ private static int GetFloatingPointMaxDigitsAndPrecision(char fmt, ref int preci break; } - case 'R': case 'r': { // The roundtrip format ignores the precision specifier and always returns the shortest @@ -1579,7 +1572,7 @@ internal static unsafe void WriteTwoDigits(uint value, TChar* ptr) where Unsafe.CopyBlockUnaligned( ref *(byte*)ptr, - ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(typeof(TChar) == typeof(char) ? TwoDigitsCharsAsBytes : TwoDigitsBytes), (uint)sizeof(TChar) * 2 * value), + ref Unsafe.Add(ref MemoryMarshal.GetReference(typeof(TChar) == typeof(char) ? TwoDigitsCharsAsBytes : TwoDigitsBytes), (uint)sizeof(TChar) * 2 * value), (uint)sizeof(TChar) * 2); } @@ -1595,7 +1588,7 @@ internal static unsafe void WriteFourDigits(uint value, TChar* ptr) where (value, uint remainder) = Math.DivRem(value, 100); - ref byte charsArray = ref MemoryMarshal.GetArrayDataReference(typeof(TChar) == typeof(char) ? TwoDigitsCharsAsBytes : TwoDigitsBytes); + ref byte charsArray = ref MemoryMarshal.GetReference(typeof(TChar) == typeof(char) ? TwoDigitsCharsAsBytes : TwoDigitsBytes); Unsafe.CopyBlockUnaligned( ref *(byte*)ptr, @@ -1677,7 +1670,7 @@ internal static unsafe void WriteDigits(uint value, TChar* ptr, int count return bufferEnd; } - internal static unsafe string UInt32ToDecStr(uint value) + internal static string UInt32ToDecStr(uint value) { // For small numbers, consult a lazily-populated cache. if (value < SmallNumberCacheLength) @@ -2540,102 +2533,6 @@ private static unsafe bool TryUInt128ToDecStr(UInt128 value, int digits, return false; } - private static ulong ExtractFractionAndBiasedExponent(double value, out int exponent) - { - ulong bits = BitConverter.DoubleToUInt64Bits(value); - ulong fraction = (bits & 0xFFFFFFFFFFFFF); - exponent = ((int)(bits >> 52) & 0x7FF); - - if (exponent != 0) - { - // For normalized value, according to https://en.wikipedia.org/wiki/Double-precision_floating-point_format - // value = 1.fraction * 2^(exp - 1023) - // = (1 + mantissa / 2^52) * 2^(exp - 1023) - // = (2^52 + mantissa) * 2^(exp - 1023 - 52) - // - // So f = (2^52 + mantissa), e = exp - 1075; - - fraction |= (1UL << 52); - exponent -= 1075; - } - else - { - // For denormalized value, according to https://en.wikipedia.org/wiki/Double-precision_floating-point_format - // value = 0.fraction * 2^(1 - 1023) - // = (mantissa / 2^52) * 2^(-1022) - // = mantissa * 2^(-1022 - 52) - // = mantissa * 2^(-1074) - // So f = mantissa, e = -1074 - exponent = -1074; - } - - return fraction; - } - - private static ushort ExtractFractionAndBiasedExponent(Half value, out int exponent) - { - ushort bits = BitConverter.HalfToUInt16Bits(value); - ushort fraction = (ushort)(bits & 0x3FF); - exponent = ((int)(bits >> 10) & 0x1F); - - if (exponent != 0) - { - // For normalized value, according to https://en.wikipedia.org/wiki/Half-precision_floating-point_format - // value = 1.fraction * 2^(exp - 15) - // = (1 + mantissa / 2^10) * 2^(exp - 15) - // = (2^10 + mantissa) * 2^(exp - 15 - 10) - // - // So f = (2^10 + mantissa), e = exp - 25; - - fraction |= (ushort)(1U << 10); - exponent -= 25; - } - else - { - // For denormalized value, according to https://en.wikipedia.org/wiki/Half-precision_floating-point_format - // value = 0.fraction * 2^(1 - 15) - // = (mantissa / 2^10) * 2^(-14) - // = mantissa * 2^(-14 - 10) - // = mantissa * 2^(-24) - // So f = mantissa, e = -24 - exponent = -24; - } - - return fraction; - } - - private static uint ExtractFractionAndBiasedExponent(float value, out int exponent) - { - uint bits = BitConverter.SingleToUInt32Bits(value); - uint fraction = (bits & 0x7FFFFF); - exponent = ((int)(bits >> 23) & 0xFF); - - if (exponent != 0) - { - // For normalized value, according to https://en.wikipedia.org/wiki/Single-precision_floating-point_format - // value = 1.fraction * 2^(exp - 127) - // = (1 + mantissa / 2^23) * 2^(exp - 127) - // = (2^23 + mantissa) * 2^(exp - 127 - 23) - // - // So f = (2^23 + mantissa), e = exp - 150; - - fraction |= (1U << 23); - exponent -= 150; - } - else - { - // For denormalized value, according to https://en.wikipedia.org/wiki/Single-precision_floating-point_format - // value = 0.fraction * 2^(1 - 127) - // = (mantissa / 2^23) * 2^(-126) - // = mantissa * 2^(-126 - 23) - // = mantissa * 2^(-149) - // So f = mantissa, e = -149 - exponent = -149; - } - - return fraction; - } - private static ulong ExtractFractionAndBiasedExponent(TNumber value, out int exponent) where TNumber : unmanaged, IBinaryFloatParseAndFormatInfo { diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/INumber.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/INumber.cs index 59aa0a761efa7e..2e0eb00e22ee14 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/INumber.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/INumber.cs @@ -37,6 +37,27 @@ static virtual TSelf Clamp(TSelf value, TSelf min, TSelf max) return result; } + /// Clamps a value to an inclusive minimum and maximum value using platform-specific behavior for NaN and NegativeZero. + /// The value to clamp. + /// The inclusive minimum to which should clamp. + /// The inclusive maximum to which should clamp. + /// The result of clamping to the inclusive range of and . + /// is greater than . + static virtual TSelf ClampNative(TSelf value, TSelf min, TSelf max) + { + if (min > max) + { + Math.ThrowMinMaxException(min, max); + } + + TSelf result = value; + + result = TSelf.MaxNative(result, min); + result = TSelf.MinNative(result, max); + + return result; + } + /// Copies the sign of a value to the sign of another value. /// The value whose magnitude is used in the result. /// The value whose sign is used in the result. @@ -79,6 +100,15 @@ static virtual TSelf Max(TSelf x, TSelf y) return TSelf.IsNegative(y) ? x : y; } + /// Compares two values to compute which is greater using platform-specific behavior for NaN and NegativeZero. + /// The value to compare with . + /// The value to compare with . + /// if it is greater than ; otherwise, . + static virtual TSelf MaxNative(TSelf x, TSelf y) + { + return (x > y) ? x : y; + } + /// Compares two values to compute which is greater and returning the other value if an input is NaN. /// The value to compare with . /// The value to compare with . @@ -131,6 +161,15 @@ static virtual TSelf Min(TSelf x, TSelf y) return TSelf.IsNegative(x) ? x : y; } + /// Compares two values to compute which is lesser using platform-specific behavior for NaN and NegativeZero. + /// The value to compare with . + /// The value to compare with . + /// if it is lesser than ; otherwise, . + static virtual TSelf MinNative(TSelf x, TSelf y) + { + return (x < y) ? x : y; + } + /// Compares two values to compute which is lesser and returning the other value if an input is NaN. /// The value to compare with . /// The value to compare with . diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs index 40e9fdc8c16510..57a71792bc5f0f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector.cs @@ -62,6 +62,30 @@ public static Vector Abs(Vector value) [Intrinsic] public static Vector Add(Vector left, Vector right) => left + right; + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool All(Vector vector, T value) => vector == Create(value); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool AllWhereAllBitsSet(Vector vector) + { + if (typeof(T) == typeof(float)) + { + return All(vector.As(), -1); + } + else if (typeof(T) == typeof(double)) + { + return All(vector.As(), -1); + } + else + { + return All(vector, Scalar.AllBitsSet); + } + } + /// Computes the bitwise-and of a given vector and the ones complement of another vector. /// The vector to bitwise-and with . /// The vector to that is ones-complemented before being bitwise-and with . @@ -70,6 +94,30 @@ public static Vector Abs(Vector value) [Intrinsic] public static Vector AndNot(Vector left, Vector right) => left & ~right; + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool Any(Vector vector, T value) => EqualsAny(vector, Create(value)); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool AnyWhereAllBitsSet(Vector vector) + { + if (typeof(T) == typeof(float)) + { + return Any(vector.As(), -1); + } + else if (typeof(T) == typeof(double)) + { + return Any(vector.As(), -1); + } + else + { + return Any(vector, Scalar.AllBitsSet); + } + } + /// Reinterprets a as a new . /// The type of the input vector. /// The type of the vector should be reinterpreted as. @@ -279,7 +327,7 @@ public static Vector Ceiling(Vector value) return result; } - /// + /// [Intrinsic] public static Vector Clamp(Vector value, Vector min, Vector max) { @@ -287,7 +335,7 @@ public static Vector Clamp(Vector value, Vector min, Vector max) return Min(Max(value, min), max); } - /// + /// [Intrinsic] public static Vector ClampNative(Vector value, Vector min, Vector max) { @@ -328,17 +376,17 @@ public static Vector ClampNative(Vector value, Vector min, Vector [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector ConvertToDouble(Vector value) { - if (Vector.Count == Vector512.Count) + if (sizeof(Vector) == sizeof(Vector512)) { return Vector512.ConvertToDouble(value.AsVector512()).AsVector(); } - else if (Vector.Count == Vector256.Count) + else if (sizeof(Vector) == sizeof(Vector256)) { return Vector256.ConvertToDouble(value.AsVector256()).AsVector(); } else { - Debug.Assert(Vector.Count == Vector128.Count); + Debug.Assert(sizeof(Vector) == sizeof(Vector128)); return Vector128.ConvertToDouble(value.AsVector128()).AsVector(); } } @@ -351,17 +399,17 @@ public static Vector ConvertToDouble(Vector value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector ConvertToDouble(Vector value) { - if (Vector.Count == Vector512.Count) + if (sizeof(Vector) == sizeof(Vector512)) { return Vector512.ConvertToDouble(value.AsVector512()).AsVector(); } - else if (Vector.Count == Vector256.Count) + else if (sizeof(Vector) == sizeof(Vector256)) { return Vector256.ConvertToDouble(value.AsVector256()).AsVector(); } else { - Debug.Assert(Vector.Count == Vector128.Count); + Debug.Assert(sizeof(Vector) == sizeof(Vector128)); return Vector128.ConvertToDouble(value.AsVector128()).AsVector(); } } @@ -459,17 +507,17 @@ public static Vector ConvertToSingle(Vector value) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector ConvertToSingle(Vector value) { - if (Vector.Count == Vector512.Count) + if (sizeof(Vector) == sizeof(Vector512)) { return Vector512.ConvertToSingle(value.AsVector512()).AsVector(); } - else if (Vector.Count == Vector256.Count) + else if (sizeof(Vector) == sizeof(Vector256)) { return Vector256.ConvertToSingle(value.AsVector256()).AsVector(); } else { - Debug.Assert(Vector.Count == Vector128.Count); + Debug.Assert(sizeof(Vector) == sizeof(Vector128)); return Vector128.ConvertToSingle(value.AsVector128()).AsVector(); } } @@ -588,7 +636,7 @@ public static Vector Cos(Vector vector) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector CopySign(Vector value, Vector sign) @@ -619,6 +667,47 @@ public static Vector CopySign(Vector value, Vector sign) } } + + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Count(Vector vector, T value) + { + if (sizeof(Vector) == sizeof(Vector512)) + { + return Vector512.Count(vector.AsVector512(), value); + } + else if (sizeof(Vector) == sizeof(Vector256)) + { + return Vector256.Count(vector.AsVector256(), value); + } + else + { + Debug.Assert(sizeof(Vector) == sizeof(Vector128)); + return Vector128.Count(vector.AsVector128(), value); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int CountWhereAllBitsSet(Vector vector) + { + if (typeof(T) == typeof(float)) + { + return Count(vector.As(), -1); + } + else if (typeof(T) == typeof(double)) + { + return Count(vector.As(), -1); + } + else + { + return Count(vector, Scalar.AllBitsSet); + } + } + /// Creates a new instance with all elements initialized to the specified value. /// The type of the elements in the vector. /// The value that all elements will be initialized to. @@ -1237,7 +1326,102 @@ public static Vector Hypot(Vector x, Vector y) } } - /// + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int IndexOf(Vector vector, T value) + { + if (sizeof(Vector) == sizeof(Vector512)) + { + return Vector512.IndexOf(vector.AsVector512(), value); + } + else if (sizeof(Vector) == sizeof(Vector256)) + { + return Vector256.IndexOf(vector.AsVector256(), value); + } + else + { + Debug.Assert(sizeof(Vector) == sizeof(Vector128)); + return Vector128.IndexOf(vector.AsVector128(), value); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int IndexOfWhereAllBitsSet(Vector vector) + { + if (typeof(T) == typeof(float)) + { + return IndexOf(vector.As(), -1); + } + else if (typeof(T) == typeof(double)) + { + return IndexOf(vector.As(), -1); + } + else + { + return IndexOf(vector, Scalar.AllBitsSet); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector IsEvenInteger(Vector vector) + { + if (typeof(T) == typeof(float)) + { + return VectorMath.IsEvenIntegerSingle, Vector>(vector.As()).As(); + } + else if (typeof(T) == typeof(double)) + { + return VectorMath.IsEvenIntegerDouble, Vector>(vector.As()).As(); + } + return IsZero(vector & Vector.One); + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector IsFinite(Vector vector) + { + if (typeof(T) == typeof(float)) + { + return ~IsZero(AndNot(Create(float.PositiveInfinityBits), vector.As())).As(); + } + else if (typeof(T) == typeof(double)) + { + return ~IsZero(AndNot(Create(double.PositiveInfinityBits), vector.As())).As(); + } + return Vector.AllBitsSet; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector IsInfinity(Vector vector) + { + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) + { + return IsPositiveInfinity(Abs(vector)); + } + return Vector.Zero; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector IsInteger(Vector vector) + { + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) + { + return IsFinite(vector) & Equals(vector, Truncate(vector)); + } + return Vector.AllBitsSet; + } + + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector IsNaN(Vector vector) @@ -1249,7 +1433,7 @@ public static Vector IsNaN(Vector vector) return Vector.Zero; } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector IsNegative(Vector vector) @@ -1276,7 +1460,55 @@ public static Vector IsNegative(Vector vector) } } - /// + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector IsNegativeInfinity(Vector vector) + { + if (typeof(T) == typeof(float)) + { + return Equals(vector, Create(float.NegativeInfinity).As()); + } + else if (typeof(T) == typeof(double)) + { + return Equals(vector, Create(double.NegativeInfinity).As()); + } + return Vector.Zero; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector IsNormal(Vector vector) + { + if (typeof(T) == typeof(float)) + { + return LessThan(Abs(vector).As() - Create(float.SmallestNormalBits), Create(float.PositiveInfinityBits - float.SmallestNormalBits)).As(); + } + else if (typeof(T) == typeof(double)) + { + return LessThan(Abs(vector).As() - Create(double.SmallestNormalBits), Create(double.PositiveInfinityBits - double.SmallestNormalBits)).As(); + } + return ~IsZero(vector); + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector IsOddInteger(Vector vector) + { + if (typeof(T) == typeof(float)) + { + return VectorMath.IsOddIntegerSingle, Vector>(vector.As()).As(); + } + else if (typeof(T) == typeof(double)) + { + return VectorMath.IsOddIntegerDouble, Vector>(vector.As()).As(); + } + return ~IsZero(vector & Vector.One); + } + + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector IsPositive(Vector vector) @@ -1303,7 +1535,7 @@ public static Vector IsPositive(Vector vector) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector IsPositiveInfinity(Vector vector) @@ -1319,11 +1551,66 @@ public static Vector IsPositiveInfinity(Vector vector) return Vector.Zero; } - /// + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector IsSubnormal(Vector vector) + { + if (typeof(T) == typeof(float)) + { + return LessThan(Abs(vector).As() - Vector.One, Create(float.MaxTrailingSignificand)).As(); + } + else if (typeof(T) == typeof(double)) + { + return LessThan(Abs(vector).As() - Vector.One, Create(double.MaxTrailingSignificand)).As(); + } + return Vector.Zero; + } + + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector IsZero(Vector vector) => Equals(vector, Vector.Zero); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int LastIndexOf(Vector vector, T value) + { + if (sizeof(Vector) == sizeof(Vector512)) + { + return Vector512.LastIndexOf(vector.AsVector512(), value); + } + else if (sizeof(Vector) == sizeof(Vector256)) + { + return Vector256.LastIndexOf(vector.AsVector256(), value); + } + else + { + Debug.Assert(sizeof(Vector) == sizeof(Vector128)); + return Vector128.LastIndexOf(vector.AsVector128(), value); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int LastIndexOfWhereAllBitsSet(Vector vector) + { + if (typeof(T) == typeof(float)) + { + return LastIndexOf(vector.As(), -1); + } + else if (typeof(T) == typeof(double)) + { + return LastIndexOf(vector.As(), -1); + } + else + { + return LastIndexOf(vector, Scalar.AllBitsSet); + } + } + internal static Vector Lerp(Vector x, Vector y, Vector amount) where T : IFloatingPointIeee754 { @@ -1705,7 +1992,7 @@ public static Vector Log2(Vector vector) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector Max(Vector left, Vector right) @@ -1728,7 +2015,7 @@ public static Vector Max(Vector left, Vector right) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector MaxMagnitude(Vector left, Vector right) @@ -1751,7 +2038,7 @@ public static Vector MaxMagnitude(Vector left, Vector right) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector MaxMagnitudeNumber(Vector left, Vector right) @@ -1774,7 +2061,7 @@ public static Vector MaxMagnitudeNumber(Vector left, Vector right) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector MaxNative(Vector left, Vector right) @@ -1797,7 +2084,7 @@ public static Vector MaxNative(Vector left, Vector right) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector MaxNumber(Vector left, Vector right) @@ -1820,7 +2107,7 @@ public static Vector MaxNumber(Vector left, Vector right) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector Min(Vector left, Vector right) @@ -1843,7 +2130,7 @@ public static Vector Min(Vector left, Vector right) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector MinMagnitude(Vector left, Vector right) @@ -1866,7 +2153,7 @@ public static Vector MinMagnitude(Vector left, Vector right) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector MinMagnitudeNumber(Vector left, Vector right) @@ -1889,7 +2176,7 @@ public static Vector MinMagnitudeNumber(Vector left, Vector right) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector MinNative(Vector left, Vector right) @@ -1912,7 +2199,7 @@ public static Vector MinNative(Vector left, Vector right) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector MinNumber(Vector left, Vector right) @@ -2192,6 +2479,30 @@ public static Vector Narrow(Vector low, Vector high) [Intrinsic] public static Vector Negate(Vector value) => -value; + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool None(Vector vector, T value) => !EqualsAny(vector, Create(value)); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool NoneWhereAllBitsSet(Vector vector) + { + if (typeof(T) == typeof(float)) + { + return None(vector.As(), -1); + } + else if (typeof(T) == typeof(double)) + { + return None(vector.As(), -1); + } + else + { + return None(vector, Scalar.AllBitsSet); + } + } + /// Computes the ones-complement of a vector. /// The vector whose ones-complement is to be computed. /// The type of the elements in the vector. @@ -2355,6 +2666,24 @@ internal static Vector Round(Vector vector) [CLSCompliant(false)] public static Vector ShiftLeft(Vector value, int shiftCount) => value << shiftCount; + [Intrinsic] + internal static Vector ShiftLeft(Vector vector, Vector shiftCount) + { + if (sizeof(Vector) == sizeof(Vector512)) + { + return Vector512.ShiftLeft(vector.AsVector512(), shiftCount.AsVector512()).AsVector(); + } + else if (sizeof(Vector) == sizeof(Vector256)) + { + return Vector256.ShiftLeft(vector.AsVector256(), shiftCount.AsVector256()).AsVector(); + } + else + { + Debug.Assert(sizeof(Vector) == sizeof(Vector128)); + return Vector128.ShiftLeft(vector.AsVector128(), shiftCount.AsVector128()).AsVector(); + } + } + /// Shifts each element of a vector left by the specified amount. /// The vector whose elements are to be shifted. /// The number of bits by which to shift each element. @@ -2363,6 +2692,24 @@ internal static Vector Round(Vector vector) [CLSCompliant(false)] public static Vector ShiftLeft(Vector value, int shiftCount) => value << shiftCount; + [Intrinsic] + internal static Vector ShiftLeft(Vector vector, Vector shiftCount) + { + if (sizeof(Vector) == sizeof(Vector512)) + { + return Vector512.ShiftLeft(vector.AsVector512(), shiftCount.AsVector512()).AsVector(); + } + else if (sizeof(Vector) == sizeof(Vector256)) + { + return Vector256.ShiftLeft(vector.AsVector256(), shiftCount.AsVector256()).AsVector(); + } + else + { + Debug.Assert(sizeof(Vector) == sizeof(Vector128)); + return Vector128.ShiftLeft(vector.AsVector128(), shiftCount.AsVector128()).AsVector(); + } + } + /// Shifts (signed) each element of a vector right by the specified amount. /// The vector whose elements are to be shifted. /// The number of bits by which to shift each element. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.Extensions.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.Extensions.cs index 21e3defd777a4e..3c38c3852bdd9c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.Extensions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.Extensions.cs @@ -12,13 +12,94 @@ public static unsafe partial class Vector /// Reinterprets a to a new with the new elements zeroed. /// The vector to reinterpret. /// reinterpreted to a new with the new elements zeroed. - [Intrinsic] public static Vector4 AsVector4(this Vector2 value) => value.AsVector128().AsVector4(); /// Reinterprets a to a new with the new elements undefined. /// The vector to reinterpret. /// reinterpreted to a new with the new elements undefined. - [Intrinsic] public static Vector4 AsVector4Unsafe(this Vector2 value) => value.AsVector128Unsafe().AsVector4(); + + /// + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint ExtractMostSignificantBits(this Vector2 vector) => vector.AsVector128().ExtractMostSignificantBits(); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float GetElement(this Vector2 vector, int index) + { + if ((uint)index >= Vector2.ElementCount) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); + } + return vector.AsVector128Unsafe().GetElement(index); + } + + /// Stores a vector at the given destination. + /// The vector that will be stored. + /// The destination at which will be stored. + [CLSCompliant(false)] + public static void Store(this Vector2 source, float* destination) => source.StoreUnsafe(ref *destination); + + /// Stores a vector at the given 8-byte aligned destination. + /// The vector that will be stored. + /// The aligned destination at which will be stored. + /// is not 8-byte aligned. + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void StoreAligned(this Vector2 source, float* destination) + { + if (((nuint)destination % (uint)(Vector2.Alignment)) != 0) + { + ThrowHelper.ThrowAccessViolationException(); + } + + *(Vector2*)destination = source; + } + + /// Stores a vector at the given 8-byte aligned destination. + /// The vector that will be stored. + /// The aligned destination at which will be stored. + /// is not 8-byte aligned. + /// This method may bypass the cache on certain platforms. + [CLSCompliant(false)] + public static void StoreAlignedNonTemporal(this Vector2 source, float* destination) => source.StoreAligned(destination); + + /// Stores a vector at the given destination. + /// The vector that will be stored. + /// The destination at which will be stored. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void StoreUnsafe(this Vector2 source, ref float destination) + { + ref byte address = ref Unsafe.As(ref destination); + Unsafe.WriteUnaligned(ref address, source); + } + + /// Stores a vector at the given destination. + /// The vector that will be stored. + /// The destination to which will be added before the vector will be stored. + /// The element offset from from which the vector will be stored. + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void StoreUnsafe(this Vector2 source, ref float destination, nuint elementOffset) + { + destination = ref Unsafe.Add(ref destination, (nint)elementOffset); + Unsafe.WriteUnaligned(ref Unsafe.As(ref destination), source); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float ToScalar(this Vector2 vector) => vector.AsVector128Unsafe().ToScalar(); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 WithElement(this Vector2 vector, int index, float value) + { + if ((uint)index >= Vector2.ElementCount) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); + } + return vector.AsVector128Unsafe().WithElement(index, value).AsVector2(); + } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs index 5619dcfede46b0..351986ea4ac578 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector2.cs @@ -17,13 +17,31 @@ namespace System.Numerics [Intrinsic] public partial struct Vector2 : IEquatable, IFormattable { + /// Specifies the alignment of the vector as used by the and APIs. + /// + /// + /// Different environments all have their own concepts of alignment/packing. + /// For example, a Vector3 in .NET is 4-byte aligned and 12-bytes in size, + /// in GLSL a vec3 is 16-byte aligned and 16-byte sized, while in HLSL a + /// float3 is functionally 8-byte aligned and 12-byte sized. These differences + /// make it impossible to define a "correct" alignment; additionally, the nuance + /// in environments like HLSL where size is not a multiple of alignment introduce complications. + /// + /// + /// For the purposes of the LoadAligned and StoreAligned APIs we + /// therefore pick a value that allows for a broad range of compatibility while + /// also allowing more optimal codegen for various target platforms. + /// + /// + internal const int Alignment = 8; + /// The X component of the vector. public float X; /// The Y component of the vector. public float Y; - internal const int Count = 2; + internal const int ElementCount = 2; /// Creates a new object whose two elements have the same value. /// The value to assign to both elements. @@ -50,6 +68,13 @@ public Vector2(ReadOnlySpan values) this = Create(values); } + /// + public static Vector2 AllBitsSet + { + [Intrinsic] + get => Vector128.AllBitsSet.AsVector2(); + } + /// public static Vector2 E { @@ -143,25 +168,12 @@ public static Vector2 Zero public float this[int index] { [Intrinsic] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - readonly get - { - if ((uint)index >= Count) - { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); - } - return this.AsVector128Unsafe().GetElement(index); - } + readonly get => this.GetElement(index); [Intrinsic] - [MethodImpl(MethodImplOptions.AggressiveInlining)] set { - if ((uint)index >= Count) - { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); - } - this = this.AsVector128Unsafe().WithElement(index, value).AsVector2(); + this = this.WithElement(index, value); } } @@ -251,6 +263,46 @@ readonly get [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 operator -(Vector2 value) => (-value.AsVector128Unsafe()).AsVector2(); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 operator &(Vector2 left, Vector2 right) => (left.AsVector128Unsafe() & right.AsVector128Unsafe()).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 operator |(Vector2 left, Vector2 right) => (left.AsVector128Unsafe() | right.AsVector128Unsafe()).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 operator ^(Vector2 left, Vector2 right) => (left.AsVector128Unsafe() ^ right.AsVector128Unsafe()).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 operator <<(Vector2 value, int shiftAmount) => (value.AsVector128Unsafe() << shiftAmount).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 operator ~(Vector2 value) => (~value.AsVector128Unsafe()).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 operator >>(Vector2 value, int shiftAmount) => (value.AsVector128Unsafe() >> shiftAmount).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 operator +(Vector2 value) => value; + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 operator >>>(Vector2 value, int shiftAmount) => (value.AsVector128Unsafe() >>> shiftAmount).AsVector2(); + /// Returns a vector whose elements are the absolute values of each of the specified vector's elements. /// A vector. /// The absolute value vector. @@ -265,17 +317,55 @@ readonly get [Intrinsic] public static Vector2 Add(Vector2 left, Vector2 right) => left + right; - /// + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool All(Vector2 vector, float value) => Vector128.All(vector, value); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool AllWhereAllBitsSet(Vector2 vector) => Vector128.AllWhereAllBitsSet(vector); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 AndNot(Vector2 left, Vector2 right) => Vector128.AndNot(left.AsVector128Unsafe(), right.AsVector128Unsafe()).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool Any(Vector2 vector, float value) => Vector128.Any(vector, value); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool AnyWhereAllBitsSet(Vector2 vector) => Vector128.AnyWhereAllBitsSet(vector); + + /// + [Intrinsic] + public static Vector2 BitwiseAnd(Vector2 left, Vector2 right) => left & right; + + /// + [Intrinsic] + public static Vector2 BitwiseOr(Vector2 left, Vector2 right) => left | right; + + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Clamp(Vector2 value1, Vector2 min, Vector2 max) => Vector128.Clamp(value1.AsVector128Unsafe(), min.AsVector128Unsafe(), max.AsVector128Unsafe()).AsVector2(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 ClampNative(Vector2 value1, Vector2 min, Vector2 max) => Vector128.ClampNative(value1.AsVector128Unsafe(), min.AsVector128Unsafe(), max.AsVector128Unsafe()).AsVector2(); - /// + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 ConditionalSelect(Vector2 condition, Vector2 left, Vector2 right) => Vector128.ConditionalSelect(condition.AsVector128Unsafe(), left.AsVector128Unsafe(), right.AsVector128Unsafe()).AsVector2(); + + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 CopySign(Vector2 value, Vector2 sign) => Vector128.CopySign(value.AsVector128Unsafe(), sign.AsVector128Unsafe()).AsVector2(); @@ -284,6 +374,16 @@ readonly get [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Cos(Vector2 vector) => Vector128.Cos(vector.AsVector128()).AsVector2(); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Count(Vector2 vector, float value) => Vector128.Count(vector, value); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int CountWhereAllBitsSet(Vector2 vector) => Vector128.CountWhereAllBitsSet(vector); + /// Creates a new object whose two elements have the same value. /// The value to assign to all two elements. /// A new whose two elements have the same value. @@ -304,7 +404,7 @@ readonly get [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Create(ReadOnlySpan values) { - if (values.Length < Count) + if (values.Length < ElementCount) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.values); } @@ -368,16 +468,146 @@ public static Vector2 Create(ReadOnlySpan values) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Exp(Vector2 vector) => Vector128.Exp(vector.AsVector128()).AsVector2(); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 Equals(Vector2 left, Vector2 right) => Vector128.Equals(left.AsVector128Unsafe(), right.AsVector128Unsafe()).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool EqualsAll(Vector2 left, Vector2 right) => Vector128.EqualsAll(left.AsVector128Unsafe(), right.AsVector128Unsafe()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool EqualsAny(Vector2 left, Vector2 right) => Vector128.EqualsAny(left.AsVector128Unsafe(), right.AsVector128Unsafe()); + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 FusedMultiplyAdd(Vector2 left, Vector2 right, Vector2 addend) => Vector128.FusedMultiplyAdd(left.AsVector128Unsafe(), right.AsVector128Unsafe(), addend.AsVector128Unsafe()).AsVector2(); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 GreaterThan(Vector2 left, Vector2 right) => Vector128.GreaterThan(left.AsVector128Unsafe(), right.AsVector128Unsafe()).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool GreaterThanAll(Vector2 left, Vector2 right) => Vector128.GreaterThanAll(left.AsVector128Unsafe(), right.AsVector128Unsafe()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool GreaterThanAny(Vector2 left, Vector2 right) => Vector128.GreaterThanAny(left.AsVector128Unsafe(), right.AsVector128Unsafe()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 GreaterThanOrEqual(Vector2 left, Vector2 right) => Vector128.GreaterThanOrEqual(left.AsVector128Unsafe(), right.AsVector128Unsafe()).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool GreaterThanOrEqualAll(Vector2 left, Vector2 right) => Vector128.GreaterThanOrEqualAll(left.AsVector128Unsafe(), right.AsVector128Unsafe()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool GreaterThanOrEqualAny(Vector2 left, Vector2 right) => Vector128.GreaterThanOrEqualAny(left.AsVector128Unsafe(), right.AsVector128Unsafe()); + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Hypot(Vector2 x, Vector2 y) => Vector128.Hypot(x.AsVector128Unsafe(), y.AsVector128Unsafe()).AsVector2(); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int IndexOf(Vector2 vector, float value) => Vector128.IndexOf(vector, value); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int IndexOfWhereAllBitsSet(Vector2 vector) => Vector128.IndexOfWhereAllBitsSet(vector); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 IsEvenInteger(Vector2 vector) => Vector128.IsEvenInteger(vector.AsVector128()).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 IsFinite(Vector2 vector) => Vector128.IsFinite(vector.AsVector128()).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 IsInfinity(Vector2 vector) => Vector128.IsInfinity(vector.AsVector128()).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 IsInteger(Vector2 vector) => Vector128.IsInteger(vector.AsVector128()).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 IsNaN(Vector2 vector) => Vector128.IsNaN(vector.AsVector128()).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 IsNegative(Vector2 vector) => Vector128.IsNegative(vector.AsVector128()).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 IsNegativeInfinity(Vector2 vector) => Vector128.IsNegativeInfinity(vector.AsVector128()).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 IsNormal(Vector2 vector) => Vector128.IsNormal(vector.AsVector128()).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 IsOddInteger(Vector2 vector) => Vector128.IsOddInteger(vector.AsVector128()).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 IsPositive(Vector2 vector) => Vector128.IsPositive(vector.AsVector128()).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 IsPositiveInfinity(Vector2 vector) => Vector128.IsPositiveInfinity(vector.AsVector128()).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 IsSubnormal(Vector2 vector) => Vector128.IsSubnormal(vector.AsVector128()).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 IsZero(Vector2 vector) => Vector128.IsZero(vector.AsVector128()).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int LastIndexOf(Vector2 vector, float value) => Vector128.LastIndexOf(vector, value); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int LastIndexOfWhereAllBitsSet(Vector2 vector) => Vector128.LastIndexOfWhereAllBitsSet(vector); + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -388,6 +618,79 @@ public static Vector2 Create(ReadOnlySpan values) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Lerp(Vector2 value1, Vector2 value2, Vector2 amount) => Vector128.Lerp(value1.AsVector128Unsafe(), value2.AsVector128Unsafe(), amount.AsVector128Unsafe()).AsVector2(); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 LessThan(Vector2 left, Vector2 right) => Vector128.LessThan(left.AsVector128Unsafe(), right.AsVector128Unsafe()).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool LessThanAll(Vector2 left, Vector2 right) => Vector128.LessThanAll(left.AsVector128Unsafe(), right.AsVector128Unsafe()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool LessThanAny(Vector2 left, Vector2 right) => Vector128.LessThanAny(left.AsVector128Unsafe(), right.AsVector128Unsafe()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 LessThanOrEqual(Vector2 left, Vector2 right) => Vector128.LessThanOrEqual(left.AsVector128Unsafe(), right.AsVector128Unsafe()).AsVector2(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool LessThanOrEqualAll(Vector2 left, Vector2 right) => Vector128.LessThanOrEqualAll(left.AsVector128Unsafe(), right.AsVector128Unsafe()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool LessThanOrEqualAny(Vector2 left, Vector2 right) => Vector128.LessThanOrEqualAny(left.AsVector128Unsafe(), right.AsVector128Unsafe()); + + /// + [Intrinsic] + [CLSCompliant(false)] + public static unsafe Vector2 Load(float* source) => LoadUnsafe(in *source); + + /// + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe Vector2 LoadAligned(float* source) + { + if (((nuint)(source) % Alignment) != 0) + { + ThrowHelper.ThrowAccessViolationException(); + } + + return *(Vector2*)source; + } + + /// + [Intrinsic] + [CLSCompliant(false)] + public static unsafe Vector2 LoadAlignedNonTemporal(float* source) => LoadAligned(source); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 LoadUnsafe(ref readonly float source) + { + ref readonly byte address = ref Unsafe.As(ref Unsafe.AsRef(in source)); + return Unsafe.ReadUnaligned(in address); + } + + /// + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 LoadUnsafe(ref readonly float source, nuint elementOffset) + { + ref readonly byte address = ref Unsafe.As(ref Unsafe.Add(ref Unsafe.AsRef(in source), (nint)elementOffset)); + return Unsafe.ReadUnaligned(in address); + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Log(Vector2 vector) => Vector128.Log(Vector4.Create(vector, 1.0f, 1.0f).AsVector128()).AsVector2(); @@ -396,52 +699,52 @@ public static Vector2 Create(ReadOnlySpan values) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Log2(Vector2 vector) => Vector128.Log2(Vector4.Create(vector, 1.0f, 1.0f).AsVector128()).AsVector2(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Max(Vector2 value1, Vector2 value2) => Vector128.Max(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector2(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 MaxMagnitude(Vector2 value1, Vector2 value2) => Vector128.MaxMagnitude(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector2(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 MaxMagnitudeNumber(Vector2 value1, Vector2 value2) => Vector128.MaxMagnitudeNumber(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector2(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 MaxNative(Vector2 value1, Vector2 value2) => Vector128.MaxNative(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector2(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 MaxNumber(Vector2 value1, Vector2 value2) => Vector128.MaxNumber(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector2(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Min(Vector2 value1, Vector2 value2) => Vector128.Min(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector2(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 MinMagnitude(Vector2 value1, Vector2 value2) => Vector128.MinMagnitude(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector2(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 MinMagnitudeNumber(Vector2 value1, Vector2 value2) => Vector128.MinMagnitudeNumber(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector2(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 MinNative(Vector2 value1, Vector2 value2) => Vector128.MinNative(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector2(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 MinNumber(Vector2 value1, Vector2 value2) => Vector128.MinNumber(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector2(); @@ -478,12 +781,26 @@ public static Vector2 Create(ReadOnlySpan values) [Intrinsic] public static Vector2 Negate(Vector2 value) => -value; + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool None(Vector2 vector, float value) => Vector128.None(vector, value); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool NoneWhereAllBitsSet(Vector2 vector) => Vector128.NoneWhereAllBitsSet(vector); + /// Returns a vector with the same direction as the specified vector, but with a length of one. /// The vector to normalize. /// The normalized vector. [Intrinsic] public static Vector2 Normalize(Vector2 value) => value / value.Length(); + /// + [Intrinsic] + public static Vector2 OnesComplement(Vector2 value) => ~value; + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -512,6 +829,19 @@ public static Vector2 Reflect(Vector2 vector, Vector2 normal) [Intrinsic] public static Vector2 Round(Vector2 vector, MidpointRounding mode) => Vector128.Round(vector.AsVector128Unsafe(), mode).AsVector2(); + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// The input vector from which values are selected. + /// The index used to select a value from to be used as the value of in the result. + /// The index used to select a value from to be used as the value of in the result + /// A new vector containing the values from selected by the given indices. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 Shuffle(Vector2 vector, byte xIndex, byte yIndex) + { + // We do `AsVector128` instead of `AsVector128Unsafe` so that indices which + // are out of range for Vector2 but in range for Vector128 still produce 0 + return Vector128.Shuffle(vector.AsVector128(), Vector128.Create(xIndex, yIndex, 2, 3)).AsVector2(); + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Sin(Vector2 vector) => Vector128.Sin(vector.AsVector128()).AsVector2(); @@ -538,6 +868,11 @@ public static (Vector2 Sin, Vector2 Cos) SinCos(Vector2 vector) [Intrinsic] public static Vector2 Subtract(Vector2 left, Vector2 right) => left - right; + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(Vector2 value) => Vector128.Sum(value.AsVector128()); + /// Transforms a vector by a specified 3x2 matrix. /// The vector to transform. /// The transformation matrix. @@ -598,6 +933,10 @@ internal static Vector2 TransformNormal(Vector2 normal, in Matrix4x4.Impl matrix [Intrinsic] public static Vector2 Truncate(Vector2 vector) => Vector128.Truncate(vector.AsVector128Unsafe()).AsVector2(); + /// + [Intrinsic] + public static Vector2 Xor(Vector2 left, Vector2 right) => left ^ right; + /// Copies the elements of the vector to a specified array. /// The destination array. /// must have at least two elements. The method copies the vector's elements starting at index 0. @@ -609,7 +948,7 @@ public readonly void CopyTo(float[] array) { // We explicitly don't check for `null` because historically this has thrown `NullReferenceException` for perf reasons - if (array.Length < Count) + if (array.Length < ElementCount) { ThrowHelper.ThrowArgumentException_DestinationTooShort(); } @@ -637,7 +976,7 @@ public readonly void CopyTo(float[] array, int index) ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_IndexMustBeLess(); } - if ((array.Length - index) < Count) + if ((array.Length - index) < ElementCount) { ThrowHelper.ThrowArgumentException_DestinationTooShort(); } @@ -651,7 +990,7 @@ public readonly void CopyTo(float[] array, int index) [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly void CopyTo(Span destination) { - if (destination.Length < Count) + if (destination.Length < ElementCount) { ThrowHelper.ThrowArgumentException_DestinationTooShort(); } @@ -665,7 +1004,7 @@ public readonly void CopyTo(Span destination) [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly bool TryCopyTo(Span destination) { - if (destination.Length < Count) + if (destination.Length < ElementCount) { return false; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.Extensions.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.Extensions.cs index ba7457ba8310a8..b818143530be72 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.Extensions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.Extensions.cs @@ -12,13 +12,94 @@ public static unsafe partial class Vector /// Converts a to a new with the new elements zeroed. /// The vector to convert. /// converted to a new with the new elements zeroed. - [Intrinsic] public static Vector4 AsVector4(this Vector3 value) => value.AsVector128().AsVector4(); /// Converts a to a new with the new elements undefined. /// The vector to convert. /// converted to a new with the new elements undefined. - [Intrinsic] public static Vector4 AsVector4Unsafe(this Vector3 value) => value.AsVector128Unsafe().AsVector4(); + + /// + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint ExtractMostSignificantBits(this Vector3 vector) => vector.AsVector128().ExtractMostSignificantBits(); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float GetElement(this Vector3 vector, int index) + { + if ((uint)index >= Vector3.ElementCount) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); + } + return vector.AsVector128Unsafe().GetElement(index); + } + + /// Stores a vector at the given destination. + /// The vector that will be stored. + /// The destination at which will be stored. + [CLSCompliant(false)] + public static void Store(this Vector3 source, float* destination) => source.StoreUnsafe(ref *destination); + + /// Stores a vector at the given 8-byte aligned destination. + /// The vector that will be stored. + /// The aligned destination at which will be stored. + /// is not 8-byte aligned. + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void StoreAligned(this Vector3 source, float* destination) + { + if (((nuint)destination % (uint)(Vector3.Alignment)) != 0) + { + ThrowHelper.ThrowAccessViolationException(); + } + + *(Vector3*)destination = source; + } + + /// Stores a vector at the given 8-byte aligned destination. + /// The vector that will be stored. + /// The aligned destination at which will be stored. + /// is not 8-byte aligned. + /// This method may bypass the cache on certain platforms. + [CLSCompliant(false)] + public static void StoreAlignedNonTemporal(this Vector3 source, float* destination) => source.StoreAligned(destination); + + /// Stores a vector at the given destination. + /// The vector that will be stored. + /// The destination at which will be stored. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void StoreUnsafe(this Vector3 source, ref float destination) + { + ref byte address = ref Unsafe.As(ref destination); + Unsafe.WriteUnaligned(ref address, source); + } + + /// Stores a vector at the given destination. + /// The vector that will be stored. + /// The destination to which will be added before the vector will be stored. + /// The element offset from from which the vector will be stored. + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void StoreUnsafe(this Vector3 source, ref float destination, nuint elementOffset) + { + destination = ref Unsafe.Add(ref destination, (nint)elementOffset); + Unsafe.WriteUnaligned(ref Unsafe.As(ref destination), source); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float ToScalar(this Vector3 vector) => vector.AsVector128Unsafe().ToScalar(); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 WithElement(this Vector3 vector, int index, float value) + { + if ((uint)index >= Vector3.ElementCount) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); + } + return vector.AsVector128Unsafe().WithElement(index, value).AsVector3(); + } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs index 4641a86687271f..6091285eed3bb4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector3.cs @@ -17,6 +17,24 @@ namespace System.Numerics [Intrinsic] public partial struct Vector3 : IEquatable, IFormattable { + /// Specifies the alignment of the vector as used by the and APIs. + /// + /// + /// Different environments all have their own concepts of alignment/packing. + /// For example, a Vector3 in .NET is 4-byte aligned and 12-bytes in size, + /// in GLSL a vec3 is 16-byte aligned and 16-byte sized, while in HLSL a + /// float3 is functionally 8-byte aligned and 12-byte sized. These differences + /// make it impossible to define a "correct" alignment; additionally, the nuance + /// in environments like HLSL where size is not a multiple of alignment introduce complications. + /// + /// + /// For the purposes of the LoadAligned and StoreAligned APIs we + /// therefore pick a value that allows for a broad range of compatibility while + /// also allowing more optimal codegen for various target platforms. + /// + /// + internal const int Alignment = 8; + /// The X component of the vector. public float X; @@ -26,7 +44,7 @@ public partial struct Vector3 : IEquatable, IFormattable /// The Z component of the vector. public float Z; - internal const int Count = 3; + internal const int ElementCount = 3; /// Creates a new object whose three elements have the same value. /// The value to assign to all three elements. @@ -63,6 +81,13 @@ public Vector3(ReadOnlySpan values) this = Create(values); } + /// + public static Vector3 AllBitsSet + { + [Intrinsic] + get => Vector128.AllBitsSet.AsVector3(); + } + /// public static Vector3 E { @@ -164,25 +189,12 @@ public static Vector3 Zero public float this[int index] { [Intrinsic] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - readonly get - { - if ((uint)index >= Count) - { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); - } - return this.AsVector128Unsafe().GetElement(index); - } + readonly get => this.GetElement(index); [Intrinsic] - [MethodImpl(MethodImplOptions.AggressiveInlining)] set { - if ((uint)index >= Count) - { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); - } - this = this.AsVector128Unsafe().WithElement(index, value).AsVector3(); + this = this.WithElement(index, value); } } @@ -272,6 +284,46 @@ readonly get [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 operator -(Vector3 value) => (-value.AsVector128Unsafe()).AsVector3(); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 operator &(Vector3 left, Vector3 right) => (left.AsVector128Unsafe() & right.AsVector128Unsafe()).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 operator |(Vector3 left, Vector3 right) => (left.AsVector128Unsafe() | right.AsVector128Unsafe()).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 operator ^(Vector3 left, Vector3 right) => (left.AsVector128Unsafe() ^ right.AsVector128Unsafe()).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 operator <<(Vector3 value, int shiftAmount) => (value.AsVector128Unsafe() << shiftAmount).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 operator ~(Vector3 value) => (~value.AsVector128Unsafe()).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 operator >>(Vector3 value, int shiftAmount) => (value.AsVector128Unsafe() >> shiftAmount).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 operator +(Vector3 value) => value; + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 operator >>>(Vector3 value, int shiftAmount) => (value.AsVector128Unsafe() >>> shiftAmount).AsVector3(); + /// Returns a vector whose elements are the absolute values of each of the specified vector's elements. /// A vector. /// The absolute value vector. @@ -286,17 +338,55 @@ readonly get [Intrinsic] public static Vector3 Add(Vector3 left, Vector3 right) => left + right; - /// + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool All(Vector3 vector, float value) => Vector128.All(vector, value); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool AllWhereAllBitsSet(Vector3 vector) => Vector128.AllWhereAllBitsSet(vector); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 AndNot(Vector3 left, Vector3 right) => Vector128.AndNot(left.AsVector128Unsafe(), right.AsVector128Unsafe()).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool Any(Vector3 vector, float value) => Vector128.Any(vector, value); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool AnyWhereAllBitsSet(Vector3 vector) => Vector128.AnyWhereAllBitsSet(vector); + + /// + [Intrinsic] + public static Vector3 BitwiseAnd(Vector3 left, Vector3 right) => left & right; + + /// + [Intrinsic] + public static Vector3 BitwiseOr(Vector3 left, Vector3 right) => left | right; + + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Clamp(Vector3 value1, Vector3 min, Vector3 max) => Vector128.Clamp(value1.AsVector128Unsafe(), min.AsVector128Unsafe(), max.AsVector128Unsafe()).AsVector3(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 ClampNative(Vector3 value1, Vector3 min, Vector3 max) => Vector128.ClampNative(value1.AsVector128Unsafe(), min.AsVector128Unsafe(), max.AsVector128Unsafe()).AsVector3(); - /// + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 ConditionalSelect(Vector3 condition, Vector3 left, Vector3 right) => Vector128.ConditionalSelect(condition.AsVector128Unsafe(), left.AsVector128Unsafe(), right.AsVector128Unsafe()).AsVector3(); + + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 CopySign(Vector3 value, Vector3 sign) => Vector128.CopySign(value.AsVector128Unsafe(), sign.AsVector128Unsafe()).AsVector3(); @@ -305,6 +395,16 @@ readonly get [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Cos(Vector3 vector) => Vector128.Cos(vector.AsVector128()).AsVector3(); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Count(Vector3 vector, float value) => Vector128.Count(vector, value); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int CountWhereAllBitsSet(Vector3 vector) => Vector128.CountWhereAllBitsSet(vector); + /// Creates a new object whose three elements have the same value. /// The value to assign to all three elements. /// A new whose three elements have the same value. @@ -339,7 +439,7 @@ public static Vector3 Create(Vector2 vector, float z) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Create(ReadOnlySpan values) { - if (values.Length < Count) + if (values.Length < ElementCount) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.values); } @@ -425,16 +525,146 @@ public static Vector3 Cross(Vector3 vector1, Vector3 vector2) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Exp(Vector3 vector) => Vector128.Exp(vector.AsVector128()).AsVector3(); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 Equals(Vector3 left, Vector3 right) => Vector128.Equals(left.AsVector128Unsafe(), right.AsVector128Unsafe()).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool EqualsAll(Vector3 left, Vector3 right) => Vector128.EqualsAll(left.AsVector128Unsafe(), right.AsVector128Unsafe()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool EqualsAny(Vector3 left, Vector3 right) => Vector128.EqualsAny(left.AsVector128Unsafe(), right.AsVector128Unsafe()); + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 FusedMultiplyAdd(Vector3 left, Vector3 right, Vector3 addend) => Vector128.FusedMultiplyAdd(left.AsVector128Unsafe(), right.AsVector128Unsafe(), addend.AsVector128Unsafe()).AsVector3(); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 GreaterThan(Vector3 left, Vector3 right) => Vector128.GreaterThan(left.AsVector128Unsafe(), right.AsVector128Unsafe()).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool GreaterThanAll(Vector3 left, Vector3 right) => Vector128.GreaterThanAll(left.AsVector128Unsafe(), right.AsVector128Unsafe()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool GreaterThanAny(Vector3 left, Vector3 right) => Vector128.GreaterThanAny(left.AsVector128Unsafe(), right.AsVector128Unsafe()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 GreaterThanOrEqual(Vector3 left, Vector3 right) => Vector128.GreaterThanOrEqual(left.AsVector128Unsafe(), right.AsVector128Unsafe()).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool GreaterThanOrEqualAll(Vector3 left, Vector3 right) => Vector128.GreaterThanOrEqualAll(left.AsVector128Unsafe(), right.AsVector128Unsafe()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool GreaterThanOrEqualAny(Vector3 left, Vector3 right) => Vector128.GreaterThanOrEqualAny(left.AsVector128Unsafe(), right.AsVector128Unsafe()); + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Hypot(Vector3 x, Vector3 y) => Vector128.Hypot(x.AsVector128Unsafe(), y.AsVector128Unsafe()).AsVector3(); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int IndexOf(Vector3 vector, float value) => Vector128.IndexOf(vector, value); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int IndexOfWhereAllBitsSet(Vector3 vector) => Vector128.IndexOfWhereAllBitsSet(vector); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 IsEvenInteger(Vector3 vector) => Vector128.IsEvenInteger(vector.AsVector128()).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 IsFinite(Vector3 vector) => Vector128.IsFinite(vector.AsVector128()).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 IsInfinity(Vector3 vector) => Vector128.IsInfinity(vector.AsVector128()).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 IsInteger(Vector3 vector) => Vector128.IsInteger(vector.AsVector128()).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 IsNaN(Vector3 vector) => Vector128.IsNaN(vector.AsVector128()).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 IsNegative(Vector3 vector) => Vector128.IsNegative(vector.AsVector128()).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 IsNegativeInfinity(Vector3 vector) => Vector128.IsNegativeInfinity(vector.AsVector128()).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 IsNormal(Vector3 vector) => Vector128.IsNormal(vector.AsVector128()).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 IsOddInteger(Vector3 vector) => Vector128.IsOddInteger(vector.AsVector128()).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 IsPositive(Vector3 vector) => Vector128.IsPositive(vector.AsVector128()).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 IsPositiveInfinity(Vector3 vector) => Vector128.IsPositiveInfinity(vector.AsVector128()).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 IsSubnormal(Vector3 vector) => Vector128.IsSubnormal(vector.AsVector128()).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 IsZero(Vector3 vector) => Vector128.IsZero(vector.AsVector128()).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int LastIndexOf(Vector3 vector, float value) => Vector128.LastIndexOf(vector, value); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int LastIndexOfWhereAllBitsSet(Vector3 vector) => Vector128.LastIndexOfWhereAllBitsSet(vector); + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -445,6 +675,79 @@ public static Vector3 Cross(Vector3 vector1, Vector3 vector2) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Lerp(Vector3 value1, Vector3 value2, Vector3 amount) => Vector128.Lerp(value1.AsVector128Unsafe(), value2.AsVector128Unsafe(), amount.AsVector128Unsafe()).AsVector3(); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 LessThan(Vector3 left, Vector3 right) => Vector128.LessThan(left.AsVector128Unsafe(), right.AsVector128Unsafe()).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool LessThanAll(Vector3 left, Vector3 right) => Vector128.LessThanAll(left.AsVector128Unsafe(), right.AsVector128Unsafe()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool LessThanAny(Vector3 left, Vector3 right) => Vector128.LessThanAny(left.AsVector128Unsafe(), right.AsVector128Unsafe()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 LessThanOrEqual(Vector3 left, Vector3 right) => Vector128.LessThanOrEqual(left.AsVector128Unsafe(), right.AsVector128Unsafe()).AsVector3(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool LessThanOrEqualAll(Vector3 left, Vector3 right) => Vector128.LessThanOrEqualAll(left.AsVector128Unsafe(), right.AsVector128Unsafe()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool LessThanOrEqualAny(Vector3 left, Vector3 right) => Vector128.LessThanOrEqualAny(left.AsVector128Unsafe(), right.AsVector128Unsafe()); + + /// + [Intrinsic] + [CLSCompliant(false)] + public static unsafe Vector3 Load(float* source) => LoadUnsafe(in *source); + + /// + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe Vector3 LoadAligned(float* source) + { + if (((nuint)(source) % Alignment) != 0) + { + ThrowHelper.ThrowAccessViolationException(); + } + + return *(Vector3*)source; + } + + /// + [Intrinsic] + [CLSCompliant(false)] + public static unsafe Vector3 LoadAlignedNonTemporal(float* source) => LoadAligned(source); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 LoadUnsafe(ref readonly float source) + { + ref readonly byte address = ref Unsafe.As(ref Unsafe.AsRef(in source)); + return Unsafe.ReadUnaligned(in address); + } + + /// + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 LoadUnsafe(ref readonly float source, nuint elementOffset) + { + ref readonly byte address = ref Unsafe.As(ref Unsafe.Add(ref Unsafe.AsRef(in source), (nint)elementOffset)); + return Unsafe.ReadUnaligned(in address); + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Log(Vector3 vector) => Vector128.Log(Vector4.Create(vector, 1.0f).AsVector128()).AsVector3(); @@ -453,52 +756,52 @@ public static Vector3 Cross(Vector3 vector1, Vector3 vector2) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Log2(Vector3 vector) => Vector128.Log2(Vector4.Create(vector, 1.0f).AsVector128()).AsVector3(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Max(Vector3 value1, Vector3 value2) => Vector128.Max(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector3(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 MaxMagnitude(Vector3 value1, Vector3 value2) => Vector128.MaxMagnitude(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector3(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 MaxMagnitudeNumber(Vector3 value1, Vector3 value2) => Vector128.MaxMagnitudeNumber(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector3(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 MaxNative(Vector3 value1, Vector3 value2) => Vector128.MaxNative(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector3(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 MaxNumber(Vector3 value1, Vector3 value2) => Vector128.MaxNumber(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector3(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Min(Vector3 value1, Vector3 value2) => Vector128.Min(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector3(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 MinMagnitude(Vector3 value1, Vector3 value2) => Vector128.MinMagnitude(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector3(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 MinMagnitudeNumber(Vector3 value1, Vector3 value2) => Vector128.MinMagnitudeNumber(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector3(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 MinNative(Vector3 value1, Vector3 value2) => Vector128.MinNative(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector3(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 MinNumber(Vector3 value1, Vector3 value2) => Vector128.MinNumber(value1.AsVector128Unsafe(), value2.AsVector128Unsafe()).AsVector3(); @@ -535,12 +838,26 @@ public static Vector3 Cross(Vector3 vector1, Vector3 vector2) [Intrinsic] public static Vector3 Negate(Vector3 value) => -value; + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool None(Vector3 vector, float value) => Vector128.None(vector, value); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool NoneWhereAllBitsSet(Vector3 vector) => Vector128.NoneWhereAllBitsSet(vector); + /// Returns a vector with the same direction as the specified vector, but with a length of one. /// The vector to normalize. /// The normalized vector. [Intrinsic] public static Vector3 Normalize(Vector3 value) => value / value.Length(); + /// + [Intrinsic] + public static Vector3 OnesComplement(Vector3 value) => ~value; + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -569,6 +886,20 @@ public static Vector3 Reflect(Vector3 vector, Vector3 normal) [Intrinsic] public static Vector3 Round(Vector3 vector, MidpointRounding mode) => Vector128.Round(vector.AsVector128Unsafe(), mode).AsVector3(); + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// The input vector from which values are selected. + /// The index used to select a value from to be used as the value of in the result. + /// The index used to select a value from to be used as the value of in the result + /// The index used to select a value from to be used as the value of in the result + /// A new vector containing the values from selected by the given indices. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 Shuffle(Vector3 vector, byte xIndex, byte yIndex, byte zIndex) + { + // We do `AsVector128` instead of `AsVector128Unsafe` so that indices which + // are out of range for Vector3 but in range for Vector128 still produce 0 + return Vector128.Shuffle(vector.AsVector128(), Vector128.Create(xIndex, yIndex, zIndex, 3)).AsVector3(); + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector3 Sin(Vector3 vector) => Vector128.Sin(vector.AsVector128()).AsVector3(); @@ -595,6 +926,11 @@ public static (Vector3 Sin, Vector3 Cos) SinCos(Vector3 vector) [Intrinsic] public static Vector3 Subtract(Vector3 left, Vector3 right) => left - right; + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(Vector3 value) => Vector128.Sum(value.AsVector128()); + /// Transforms a vector by a specified 4x4 matrix. /// The vector to transform. /// The transformation matrix. @@ -631,6 +967,10 @@ internal static Vector3 TransformNormal(Vector3 normal, in Matrix4x4.Impl matrix [Intrinsic] public static Vector3 Truncate(Vector3 vector) => Vector128.Truncate(vector.AsVector128Unsafe()).AsVector3(); + /// + [Intrinsic] + public static Vector3 Xor(Vector3 left, Vector3 right) => left ^ right; + /// Copies the elements of the vector to a specified array. /// The destination array. /// must have at least three elements. The method copies the vector's elements starting at index 0. @@ -642,7 +982,7 @@ public readonly void CopyTo(float[] array) { // We explicitly don't check for `null` because historically this has thrown `NullReferenceException` for perf reasons - if (array.Length < Count) + if (array.Length < ElementCount) { ThrowHelper.ThrowArgumentException_DestinationTooShort(); } @@ -670,7 +1010,7 @@ public readonly void CopyTo(float[] array, int index) ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_IndexMustBeLess(); } - if ((array.Length - index) < Count) + if ((array.Length - index) < ElementCount) { ThrowHelper.ThrowArgumentException_DestinationTooShort(); } @@ -684,7 +1024,7 @@ public readonly void CopyTo(float[] array, int index) [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly void CopyTo(Span destination) { - if (destination.Length < Count) + if (destination.Length < ElementCount) { ThrowHelper.ThrowArgumentException_DestinationTooShort(); } @@ -698,7 +1038,7 @@ public readonly void CopyTo(Span destination) [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly bool TryCopyTo(Span destination) { - if (destination.Length < Count) + if (destination.Length < ElementCount) { return false; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.Extensions.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.Extensions.cs index 8e243636d96e40..6aa93a2d4a47a8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.Extensions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.Extensions.cs @@ -12,7 +12,6 @@ public static unsafe partial class Vector /// Reinterprets a as a new . /// The vector to reinterpret. /// reinterpreted as a new . - [Intrinsic] public static Plane AsPlane(this Vector4 value) { #if MONO @@ -25,7 +24,6 @@ public static Plane AsPlane(this Vector4 value) /// Reinterprets a as a new . /// The vector to reinterpret. /// reinterpreted as a new . - [Intrinsic] public static Quaternion AsQuaternion(this Vector4 value) { #if MONO @@ -38,13 +36,64 @@ public static Quaternion AsQuaternion(this Vector4 value) /// Reinterprets a as a new . /// The vector to reinterpret. /// reinterpreted as a new . - [Intrinsic] public static Vector2 AsVector2(this Vector4 value) => value.AsVector128().AsVector2(); /// Reinterprets a as a new . /// The vector to reinterpret. /// reinterpreted as a new . - [Intrinsic] public static Vector3 AsVector3(this Vector4 value) => value.AsVector128().AsVector3(); + + /// + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint ExtractMostSignificantBits(this Vector4 vector) => vector.AsVector128().ExtractMostSignificantBits(); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float GetElement(this Vector4 vector, int index) => vector.AsVector128().GetElement(index); + + /// Stores a vector at the given destination. + /// The vector that will be stored. + /// The destination at which will be stored. + [CLSCompliant(false)] + public static void Store(this Vector4 source, float* destination) => source.AsVector128().Store(destination); + + /// Stores a vector at the given 16-byte aligned destination. + /// The vector that will be stored. + /// The aligned destination at which will be stored. + /// is not 16-byte aligned. + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void StoreAligned(this Vector4 source, float* destination) => source.AsVector128().StoreAligned(destination); + + /// Stores a vector at the given 16-byte aligned destination. + /// The vector that will be stored. + /// The aligned destination at which will be stored. + /// is not 16-byte aligned. + /// This method may bypass the cache on certain platforms. + [CLSCompliant(false)] + public static void StoreAlignedNonTemporal(this Vector4 source, float* destination) => source.AsVector128().StoreAlignedNonTemporal(destination); + + /// Stores a vector at the given destination. + /// The vector that will be stored. + /// The destination at which will be stored. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void StoreUnsafe(this Vector4 source, ref float destination) => source.AsVector128().StoreUnsafe(ref destination); + + /// Stores a vector at the given destination. + /// The vector that will be stored. + /// The destination to which will be added before the vector will be stored. + /// The element offset from from which the vector will be stored. + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void StoreUnsafe(this Vector4 source, ref float destination, nuint elementOffset) => source.AsVector128().StoreUnsafe(ref destination, elementOffset); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float ToScalar(this Vector4 vector) => vector.AsVector128().ToScalar(); + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 WithElement(this Vector4 vector, int index, float value) => vector.AsVector128().WithElement(index, value).AsVector4(); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs index 305992ed815a28..e0696871900333 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector4.cs @@ -16,6 +16,24 @@ namespace System.Numerics [Intrinsic] public partial struct Vector4 : IEquatable, IFormattable { + /// Specifies the alignment of the vector as used by the and APIs. + /// + /// + /// Different environments all have their own concepts of alignment/packing. + /// For example, a Vector3 in .NET is 4-byte aligned and 12-bytes in size, + /// in GLSL a vec3 is 16-byte aligned and 16-byte sized, while in HLSL a + /// float3 is functionally 8-byte aligned and 12-byte sized. These differences + /// make it impossible to define a "correct" alignment; additionally, the nuance + /// in environments like HLSL where size is not a multiple of alignment introduce complications. + /// + /// + /// For the purposes of the LoadAligned and StoreAligned APIs we + /// therefore pick a value that allows for a broad range of compatibility while + /// also allowing more optimal codegen for various target platforms. + /// + /// + internal const int Alignment = 16; + /// The X component of the vector. public float X; @@ -28,7 +46,7 @@ public partial struct Vector4 : IEquatable, IFormattable /// The W component of the vector. public float W; - internal const int Count = 4; + internal const int ElementCount = 4; /// Creates a new object whose four elements have the same value. /// The value to assign to all four elements. @@ -76,6 +94,14 @@ public Vector4(ReadOnlySpan values) this = Create(values); } + /// Gets a vector where all bits are set to 1. + /// A vector where all bits are set to 1. + public static Vector4 AllBitsSet + { + [Intrinsic] + get => Vector128.AllBitsSet.AsVector4(); + } + /// Gets a vector whose elements are equal to . /// A vector whose elements are equal to (that is, it returns the vector Create(float.E)). public static Vector4 E @@ -195,13 +221,12 @@ public static Vector4 Zero public float this[int index] { [Intrinsic] - readonly get => this.AsVector128().GetElement(index); + readonly get => this.GetElement(index); [Intrinsic] - [MethodImpl(MethodImplOptions.AggressiveInlining)] set { - this = this.AsVector128().WithElement(index, value).AsVector4(); + this = this.WithElement(index, value); } } @@ -291,6 +316,46 @@ public float this[int index] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator -(Vector4 value) => (-value.AsVector128()).AsVector4(); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 operator &(Vector4 left, Vector4 right) => (left.AsVector128() & right.AsVector128()).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 operator |(Vector4 left, Vector4 right) => (left.AsVector128() | right.AsVector128()).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 operator ^(Vector4 left, Vector4 right) => (left.AsVector128() ^ right.AsVector128()).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 operator <<(Vector4 value, int shiftAmount) => (value.AsVector128() << shiftAmount).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 operator ~(Vector4 value) => (~value.AsVector128()).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 operator >>(Vector4 value, int shiftAmount) => (value.AsVector128() >> shiftAmount).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 operator +(Vector4 value) => value; + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 operator >>>(Vector4 value, int shiftAmount) => (value.AsVector128() >>> shiftAmount).AsVector4(); + /// Returns a vector whose elements are the absolute values of each of the specified vector's elements. /// A vector. /// The absolute value vector. @@ -305,17 +370,55 @@ public float this[int index] [Intrinsic] public static Vector4 Add(Vector4 left, Vector4 right) => left + right; - /// + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool All(Vector4 vector, float value) => Vector128.All(vector.AsVector128(), value); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool AllWhereAllBitsSet(Vector4 vector) => Vector128.AllWhereAllBitsSet(vector.AsVector128()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 AndNot(Vector4 left, Vector4 right) => Vector128.AndNot(left.AsVector128(), right.AsVector128()).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool Any(Vector4 vector, float value) => Vector128.Any(vector.AsVector128(), value); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool AnyWhereAllBitsSet(Vector4 vector) => Vector128.AnyWhereAllBitsSet(vector.AsVector128()); + + /// + [Intrinsic] + public static Vector4 BitwiseAnd(Vector4 left, Vector4 right) => left & right; + + /// + [Intrinsic] + public static Vector4 BitwiseOr(Vector4 left, Vector4 right) => left | right; + + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Clamp(Vector4 value1, Vector4 min, Vector4 max) => Vector128.Clamp(value1.AsVector128(), min.AsVector128(), max.AsVector128()).AsVector4(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 ClampNative(Vector4 value1, Vector4 min, Vector4 max) => Vector128.ClampNative(value1.AsVector128(), min.AsVector128(), max.AsVector128()).AsVector4(); - /// + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 ConditionalSelect(Vector4 condition, Vector4 left, Vector4 right) => Vector128.ConditionalSelect(condition.AsVector128(), left.AsVector128(), right.AsVector128()).AsVector4(); + + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 CopySign(Vector4 value, Vector4 sign) => Vector128.CopySign(value.AsVector128(), sign.AsVector128()).AsVector4(); @@ -324,6 +427,16 @@ public float this[int index] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Cos(Vector4 vector) => Vector128.Cos(vector.AsVector128()).AsVector4(); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Count(Vector4 vector, float value) => Vector128.Count(vector.AsVector128(), value); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int CountWhereAllBitsSet(Vector4 vector) => Vector128.CountWhereAllBitsSet(vector.AsVector128()); + /// Creates a new object whose four elements have the same value. /// The value to assign to all four elements. /// A new whose four elements have the same value. @@ -430,16 +543,146 @@ public static Vector4 Create(Vector3 vector, float w) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Exp(Vector4 vector) => Vector128.Exp(vector.AsVector128()).AsVector4(); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Equals(Vector4 left, Vector4 right) => Vector128.Equals(left.AsVector128(), right.AsVector128()).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool EqualsAll(Vector4 left, Vector4 right) => Vector128.EqualsAll(left.AsVector128(), right.AsVector128()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool EqualsAny(Vector4 left, Vector4 right) => Vector128.EqualsAny(left.AsVector128(), right.AsVector128()); + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 FusedMultiplyAdd(Vector4 left, Vector4 right, Vector4 addend) => Vector128.FusedMultiplyAdd(left.AsVector128(), right.AsVector128(), addend.AsVector128()).AsVector4(); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 GreaterThan(Vector4 left, Vector4 right) => Vector128.GreaterThan(left.AsVector128(), right.AsVector128()).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool GreaterThanAll(Vector4 left, Vector4 right) => Vector128.GreaterThanAll(left.AsVector128(), right.AsVector128()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool GreaterThanAny(Vector4 left, Vector4 right) => Vector128.GreaterThanAny(left.AsVector128(), right.AsVector128()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 GreaterThanOrEqual(Vector4 left, Vector4 right) => Vector128.GreaterThanOrEqual(left.AsVector128(), right.AsVector128()).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool GreaterThanOrEqualAll(Vector4 left, Vector4 right) => Vector128.GreaterThanOrEqualAll(left.AsVector128(), right.AsVector128()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool GreaterThanOrEqualAny(Vector4 left, Vector4 right) => Vector128.GreaterThanOrEqualAny(left.AsVector128(), right.AsVector128()); + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Hypot(Vector4 x, Vector4 y) => Vector128.Hypot(x.AsVector128(), y.AsVector128()).AsVector4(); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int IndexOf(Vector4 vector, float value) => Vector128.IndexOf(vector.AsVector128(), value); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int IndexOfWhereAllBitsSet(Vector4 vector) => Vector128.IndexOfWhereAllBitsSet(vector.AsVector128()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 IsEvenInteger(Vector4 vector) => Vector128.IsEvenInteger(vector.AsVector128()).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 IsFinite(Vector4 vector) => Vector128.IsFinite(vector.AsVector128()).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 IsInfinity(Vector4 vector) => Vector128.IsInfinity(vector.AsVector128()).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 IsInteger(Vector4 vector) => Vector128.IsInteger(vector.AsVector128()).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 IsNaN(Vector4 vector) => Vector128.IsNaN(vector.AsVector128()).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 IsNegative(Vector4 vector) => Vector128.IsNegative(vector.AsVector128()).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 IsNegativeInfinity(Vector4 vector) => Vector128.IsNegativeInfinity(vector.AsVector128()).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 IsNormal(Vector4 vector) => Vector128.IsNormal(vector.AsVector128()).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 IsOddInteger(Vector4 vector) => Vector128.IsOddInteger(vector.AsVector128()).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 IsPositive(Vector4 vector) => Vector128.IsPositive(vector.AsVector128()).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 IsPositiveInfinity(Vector4 vector) => Vector128.IsPositiveInfinity(vector.AsVector128()).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 IsSubnormal(Vector4 vector) => Vector128.IsSubnormal(vector.AsVector128()).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 IsZero(Vector4 vector) => Vector128.IsZero(vector.AsVector128()).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int LastIndexOf(Vector4 vector, float value) => Vector128.LastIndexOf(vector.AsVector128(), value); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int LastIndexOfWhereAllBitsSet(Vector4 vector) => Vector128.LastIndexOfWhereAllBitsSet(vector.AsVector128()); + /// /// Vector128.Lerp(value1.AsVector128(), value2.AsVector128(), amount.AsVector128()).AsVector4(); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 LessThan(Vector4 left, Vector4 right) => Vector128.LessThan(left.AsVector128(), right.AsVector128()).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool LessThanAll(Vector4 left, Vector4 right) => Vector128.LessThanAll(left.AsVector128(), right.AsVector128()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool LessThanAny(Vector4 left, Vector4 right) => Vector128.LessThanAny(left.AsVector128(), right.AsVector128()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 LessThanOrEqual(Vector4 left, Vector4 right) => Vector128.LessThanOrEqual(left.AsVector128(), right.AsVector128()).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool LessThanOrEqualAll(Vector4 left, Vector4 right) => Vector128.LessThanOrEqualAll(left.AsVector128(), right.AsVector128()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool LessThanOrEqualAny(Vector4 left, Vector4 right) => Vector128.LessThanOrEqualAny(left.AsVector128(), right.AsVector128()); + + /// + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe Vector4 Load(float* source) => Vector128.Load(source).AsVector4(); + + /// + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe Vector4 LoadAligned(float* source) => Vector128.LoadAligned(source).AsVector4(); + + /// + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe Vector4 LoadAlignedNonTemporal(float* source) => Vector128.LoadAlignedNonTemporal(source).AsVector4(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 LoadUnsafe(ref readonly float source) => Vector128.LoadUnsafe(in source).AsVector4(); + + /// + [Intrinsic] + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 LoadUnsafe(ref readonly float source, nuint elementOffset) => Vector128.LoadUnsafe(in source, elementOffset).AsVector4(); + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Log(Vector4 vector) => Vector128.Log(vector.AsVector128()).AsVector4(); @@ -461,52 +763,52 @@ public static Vector4 Create(Vector3 vector, float w) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Log2(Vector4 vector) => Vector128.Log2(vector.AsVector128()).AsVector4(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Max(Vector4 value1, Vector4 value2) => Vector128.Max(value1.AsVector128(), value2.AsVector128()).AsVector4(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 MaxMagnitude(Vector4 value1, Vector4 value2) => Vector128.MaxMagnitude(value1.AsVector128(), value2.AsVector128()).AsVector4(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 MaxMagnitudeNumber(Vector4 value1, Vector4 value2) => Vector128.MaxMagnitudeNumber(value1.AsVector128(), value2.AsVector128()).AsVector4(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 MaxNative(Vector4 value1, Vector4 value2) => Vector128.MaxNative(value1.AsVector128(), value2.AsVector128()).AsVector4(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 MaxNumber(Vector4 value1, Vector4 value2) => Vector128.MaxNumber(value1.AsVector128(), value2.AsVector128()).AsVector4(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Min(Vector4 value1, Vector4 value2) => Vector128.Min(value1.AsVector128(), value2.AsVector128()).AsVector4(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 MinMagnitude(Vector4 value1, Vector4 value2) => Vector128.MinMagnitude(value1.AsVector128(), value2.AsVector128()).AsVector4(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 MinMagnitudeNumber(Vector4 value1, Vector4 value2) => Vector128.MinMagnitudeNumber(value1.AsVector128(), value2.AsVector128()).AsVector4(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 MinNative(Vector4 value1, Vector4 value2) => Vector128.MinNative(value1.AsVector128(), value2.AsVector128()).AsVector4(); - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 MinNumber(Vector4 value1, Vector4 value2) => Vector128.MinNumber(value1.AsVector128(), value2.AsVector128()).AsVector4(); @@ -543,12 +845,26 @@ public static Vector4 Create(Vector3 vector, float w) [Intrinsic] public static Vector4 Negate(Vector4 value) => -value; + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool None(Vector4 vector, float value) => Vector128.None(vector.AsVector128(), value); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool NoneWhereAllBitsSet(Vector4 vector) => Vector128.NoneWhereAllBitsSet(vector.AsVector128()); + /// Returns a vector with the same direction as the specified vector, but with a length of one. /// The vector to normalize. /// The normalized vector. [Intrinsic] public static Vector4 Normalize(Vector4 vector) => vector / vector.Length(); + /// + [Intrinsic] + public static Vector4 OnesComplement(Vector4 value) => ~value; + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -562,6 +878,19 @@ public static Vector4 Create(Vector3 vector, float w) [Intrinsic] public static Vector4 Round(Vector4 vector, MidpointRounding mode) => Vector128.Round(vector.AsVector128(), mode).AsVector4(); + /// Creates a new vector by selecting values from an input vector using a set of indices. + /// The input vector from which values are selected. + /// The index used to select a value from to be used as the value of in the result. + /// The index used to select a value from to be used as the value of in the result + /// The index used to select a value from to be used as the value of in the result + /// The index used to select a value from to be used as the value of in the result + /// A new vector containing the values from selected by the given indices. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Shuffle(Vector4 vector, byte xIndex, byte yIndex, byte zIndex, byte wIndex) + { + return Vector128.Shuffle(vector.AsVector128(), Vector128.Create(xIndex, yIndex, zIndex, wIndex)).AsVector4(); + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 Sin(Vector4 vector) => Vector128.Sin(vector.AsVector128()).AsVector4(); @@ -588,6 +917,11 @@ public static (Vector4 Sin, Vector4 Cos) SinCos(Vector4 vector) [Intrinsic] public static Vector4 Subtract(Vector4 left, Vector4 right) => left - right; + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(Vector4 value) => Vector128.Sum(value.AsVector128()); + /// Transforms a two-dimensional vector by a specified 4x4 matrix. /// The vector to transform. /// The transformation matrix. @@ -675,6 +1009,10 @@ public static Vector4 Transform(Vector4 value, Quaternion rotation) [Intrinsic] public static Vector4 Truncate(Vector4 vector) => Vector128.Truncate(vector.AsVector128()).AsVector4(); + /// + [Intrinsic] + public static Vector4 Xor(Vector4 left, Vector4 right) => left ^ right; + /// Copies the elements of the vector to a specified array. /// The destination array. /// must have at least four elements. The method copies the vector's elements starting at index 0. diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector_1.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector_1.cs index 30a3cb9fa37287..3cea422e72c638 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector_1.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Vector_1.cs @@ -820,6 +820,9 @@ public bool TryCopyTo(Span destination) /// static int ISimdVector, T>.Alignment => Vector.Alignment; + /// + static int ISimdVector, T>.ElementCount => Vector.Count; + /// static bool ISimdVector, T>.IsHardwareAccelerated { @@ -835,10 +838,26 @@ static bool ISimdVector, T>.IsHardwareAccelerated [Intrinsic] static Vector ISimdVector, T>.Add(Vector left, Vector right) => left + right; + /// + [Intrinsic] + static bool ISimdVector, T>.All(Vector vector, T value) => Vector.All(vector, value); + + /// + [Intrinsic] + static bool ISimdVector, T>.AllWhereAllBitsSet(Vector vector) => Vector.AllWhereAllBitsSet(vector); + /// [Intrinsic] static Vector ISimdVector, T>.AndNot(Vector left, Vector right) => Vector.AndNot(left, right); + /// + [Intrinsic] + static bool ISimdVector, T>.Any(Vector vector, T value) => Vector.Any(vector, value); + + /// + [Intrinsic] + static bool ISimdVector, T>.AnyWhereAllBitsSet(Vector vector) => Vector.AnyWhereAllBitsSet(vector); + /// [Intrinsic] static Vector ISimdVector, T>.BitwiseAnd(Vector left, Vector right) => left & right; @@ -876,6 +895,14 @@ static bool ISimdVector, T>.IsHardwareAccelerated /// static void ISimdVector, T>.CopyTo(Vector vector, Span destination) => vector.CopyTo(destination); + /// + [Intrinsic] + static int ISimdVector, T>.Count(Vector vector, T value) => Vector.Count(vector, value); + + /// + [Intrinsic] + static int ISimdVector, T>.CountWhereAllBitsSet(Vector vector) => Vector.CountWhereAllBitsSet(vector); + /// [Intrinsic] static Vector ISimdVector, T>.Create(T value) => Vector.Create(value); @@ -953,6 +980,73 @@ static bool ISimdVector, T>.IsHardwareAccelerated [Intrinsic] static bool ISimdVector, T>.GreaterThanOrEqualAny(Vector left, Vector right) => Vector.GreaterThanOrEqualAny(left, right); + /// + [Intrinsic] + static int ISimdVector, T>.IndexOf(Vector vector, T value) => Vector.IndexOf(vector, value); + + /// + [Intrinsic] + static int ISimdVector, T>.IndexOfWhereAllBitsSet(Vector vector) => Vector.IndexOfWhereAllBitsSet(vector); + + /// + [Intrinsic] + static Vector ISimdVector, T>.IsEvenInteger(Vector vector) => Vector.IsEvenInteger(vector); + + /// + [Intrinsic] + static Vector ISimdVector, T>.IsFinite(Vector vector) => Vector.IsFinite(vector); + + /// + [Intrinsic] + static Vector ISimdVector, T>.IsInfinity(Vector vector) => Vector.IsInfinity(vector); + + /// + [Intrinsic] + static Vector ISimdVector, T>.IsInteger(Vector vector) => Vector.IsInteger(vector); + + /// + [Intrinsic] + static Vector ISimdVector, T>.IsNaN(Vector vector) => Vector.IsNaN(vector); + + /// + [Intrinsic] + static Vector ISimdVector, T>.IsNegative(Vector vector) => Vector.IsNegative(vector); + + /// + [Intrinsic] + static Vector ISimdVector, T>.IsNegativeInfinity(Vector vector) => Vector.IsNegativeInfinity(vector); + + /// + [Intrinsic] + static Vector ISimdVector, T>.IsNormal(Vector vector) => Vector.IsNormal(vector); + + /// + [Intrinsic] + static Vector ISimdVector, T>.IsOddInteger(Vector vector) => Vector.IsOddInteger(vector); + + /// + [Intrinsic] + static Vector ISimdVector, T>.IsPositive(Vector vector) => Vector.IsPositive(vector); + + /// + [Intrinsic] + static Vector ISimdVector, T>.IsPositiveInfinity(Vector vector) => Vector.IsPositiveInfinity(vector); + + /// + [Intrinsic] + static Vector ISimdVector, T>.IsSubnormal(Vector vector) => Vector.IsSubnormal(vector); + + /// + static Vector ISimdVector, T>.IsZero(Vector vector) => Vector.IsZero(vector); + + /// + [Intrinsic] + static int ISimdVector, T>.LastIndexOf(Vector vector, T value) => Vector.LastIndexOf(vector, value); + + /// + [Intrinsic] + static int ISimdVector, T>.LastIndexOfWhereAllBitsSet(Vector vector) => Vector.LastIndexOfWhereAllBitsSet(vector); + /// [Intrinsic] static Vector ISimdVector, T>.LessThan(Vector left, Vector right) => Vector.LessThan(left, right); @@ -1053,6 +1147,14 @@ static bool ISimdVector, T>.IsHardwareAccelerated [Intrinsic] static Vector ISimdVector, T>.Negate(Vector vector) => -vector; + /// + [Intrinsic] + static bool ISimdVector, T>.None(Vector vector, T value) => Vector.None(vector, value); + + /// + [Intrinsic] + static bool ISimdVector, T>.NoneWhereAllBitsSet(Vector vector) => Vector.NoneWhereAllBitsSet(vector); + /// [Intrinsic] static Vector ISimdVector, T>.OnesComplement(Vector vector) => ~vector; @@ -1123,48 +1225,5 @@ static bool ISimdVector, T>.IsHardwareAccelerated /// [Intrinsic] static Vector ISimdVector, T>.Xor(Vector left, Vector right) => left ^ right; - - // - // New Surface Area - // - - static bool ISimdVector, T>.AnyWhereAllBitsSet(Vector vector) => Vector.EqualsAny(vector, AllBitsSet); - - static bool ISimdVector, T>.Any(Vector vector, T value) => Vector.EqualsAny(vector, Vector.Create(value)); - - static int ISimdVector, T>.IndexOfLastMatch(Vector vector) - { - if (sizeof(Vector) == 64) - { - ulong mask = vector.AsVector512().ExtractMostSignificantBits(); - return 63 - BitOperations.LeadingZeroCount(mask); // 63 = 64 (bits in Int64) - 1 (indexing from zero) - } - else if (sizeof(Vector) == 32) - { - uint mask = vector.AsVector256().ExtractMostSignificantBits(); - return 31 - BitOperations.LeadingZeroCount(mask); // 31 = 32 (bits in Int32) - 1 (indexing from zero) - } - else - { - Debug.Assert(sizeof(Vector) == 16); - uint mask = vector.AsVector128().ExtractMostSignificantBits(); - return 31 - BitOperations.LeadingZeroCount(mask); // 31 = 32 (bits in Int32) - 1 (indexing from zero) - } - } - - [Intrinsic] - static Vector ISimdVector, T>.IsNaN(Vector vector) => Vector.IsNaN(vector); - - [Intrinsic] - static Vector ISimdVector, T>.IsNegative(Vector vector) => Vector.IsNegative(vector); - - [Intrinsic] - static Vector ISimdVector, T>.IsPositive(Vector vector) => Vector.IsPositive(vector); - - [Intrinsic] - static Vector ISimdVector, T>.IsPositiveInfinity(Vector vector) => Vector.IsPositiveInfinity(vector); - - [Intrinsic] - static Vector ISimdVector, T>.IsZero(Vector vector) => Vector.IsZero(vector); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NFloat.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NFloat.cs index f0e1f6d28aeacc..5939bc9e159450 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NFloat.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NFloat.cs @@ -1247,18 +1247,27 @@ bool IFloatingPoint.TryWriteSignificandLittleEndian(Span destinati /// public static NFloat Clamp(NFloat value, NFloat min, NFloat max) => new NFloat(NativeType.Clamp(value._value, min._value, max._value)); + /// + public static NFloat ClampNative(NFloat value, NFloat min, NFloat max) => new NFloat(NativeType.ClampNative(value._value, min._value, max._value)); + /// public static NFloat CopySign(NFloat value, NFloat sign) => new NFloat(NativeType.CopySign(value._value, sign._value)); /// public static NFloat Max(NFloat x, NFloat y) => new NFloat(NativeType.Max(x._value, y._value)); + /// + public static NFloat MaxNative(NFloat x, NFloat y) => new NFloat(NativeType.MaxNative(x._value, y._value)); + /// public static NFloat MaxNumber(NFloat x, NFloat y) => new NFloat(NativeType.MaxNumber(x._value, y._value)); /// public static NFloat Min(NFloat x, NFloat y) => new NFloat(NativeType.Min(x._value, y._value)); + /// + public static NFloat MinNative(NFloat x, NFloat y) => new NFloat(NativeType.MinNative(x._value, y._value)); + /// public static NFloat MinNumber(NFloat x, NFloat y) => new NFloat(NativeType.MinNumber(x._value, y._value)); diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/ISimdVector_2.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/ISimdVector_2.cs index ec4f3640f1475c..bec27899e9f6b5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/ISimdVector_2.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/ISimdVector_2.cs @@ -42,7 +42,7 @@ internal unsafe interface ISimdVector /// Gets the number of that are in the vector. /// The type of the elements in the vector () is not supported. - static abstract int Count { get; } + static abstract int ElementCount { get; } /// Gets a value that indicates whether the vector operations are subject to hardware acceleration through JIT intrinsic support. /// if the vector operations are subject to hardware acceleration; otherwise, . @@ -93,12 +93,38 @@ internal unsafe interface ISimdVector /// The type of and () is not supported. static virtual TSelf Add(TSelf left, TSelf right) => left + right; + /// Determines if all elements of a vector are equal to a given value. + /// The vector whose elements are being checked. + /// The value to check for in + /// true if all elements of are equal to ; otherwise, false. + /// The type of and () is not supported. + static abstract bool All(TSelf vector, T value); + + /// Determines if all elements of a vector have all their bits set. + /// The vector whose elements are being checked. + /// true if all elements of have all their bits set; otherwise, false. + /// The type of () is not supported. + static abstract bool AllWhereAllBitsSet(TSelf vector); + /// Computes the bitwise-and of a given vector and the ones complement of another vector. /// The vector to bitwise-and with . /// The vector to that is ones-complemented before being bitwise-and with . /// The bitwise-and of and the ones-complement of . static virtual TSelf AndNot(TSelf left, TSelf right) => left & ~right; + /// Determines if any elements of a vector are equal to a given value. + /// The vector whose elements are being checked. + /// The value to check for in + /// true if any elements of are equal to ; otherwise, false. + /// The type of and () is not supported. + static abstract bool Any(TSelf vector, T value); + + /// Determines if any elements of a vector have all their bits set. + /// The vector whose elements are being checked. + /// true if any elements of have all their bits set; otherwise, false. + /// The type of () is not supported. + static abstract bool AnyWhereAllBitsSet(TSelf vector); + /// Computes the bitwise-and of two vectors. /// The vector to bitwise-and with . /// The vector to bitwise-and with . @@ -173,13 +199,26 @@ internal unsafe interface ISimdVector /// The type of the elements in the vector () is not supported. static virtual void CopyTo(TSelf vector, Span destination) { - if (destination.Length < TSelf.Count) + if (destination.Length < TSelf.ElementCount) { ThrowHelper.ThrowArgumentException_DestinationTooShort(); } TSelf.StoreUnsafe(vector, ref MemoryMarshal.GetReference(destination)); } + /// Determines the number of elements in a vector that are equal to a given value. + /// The vector whose elements are being checked. + /// The value to check for in + /// The number of elements in that are equal to . + /// The type of and () is not supported. + static abstract int Count(TSelf vector, T value); + + /// Determines the number of elements in a vector that have all their bits set. + /// The vector whose elements are being checked. + /// The number of elements in that have all their bits set. + /// The type of () is not supported. + static abstract int CountWhereAllBitsSet(TSelf vector); + /// Creates a new vector with all elements initialized to the specified value. /// The value that all elements will be initialized to. /// A new vector with all elements initialized to . @@ -210,7 +249,7 @@ static virtual void CopyTo(TSelf vector, Span destination) /// The type of the elements in the vector () is not supported. static virtual TSelf Create(ReadOnlySpan values) { - if (values.Length < TSelf.Count) + if (values.Length < TSelf.ElementCount) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.values); } @@ -332,6 +371,46 @@ static virtual TSelf CreateScalarUnsafe(T value) /// The type of the elements in the vector () is not supported. static abstract bool GreaterThanOrEqualAny(TSelf left, TSelf right); + /// Determines the index of the first element in a vector that is equal to a given value. + /// The vector whose elements are being checked. + /// The value to check for in + /// The index into representing the first element that was equal to ; otherwise, -1 if no such element exists. + /// The type of and () is not supported. + static abstract int IndexOf(TSelf vector, T value); + + /// Determines the index of the first element in a vector that has all bits set. + /// The vector whose elements are being checked. + /// The index into representing the first element that had all bits set; otherwise, -1 if no such element exists. + /// The type of () is not supported. + static abstract int IndexOfWhereAllBitsSet(TSelf vector); + + /// Determines which elements in a vector are even integral values. + /// The vector to be checked. + /// A vector whose elements are all-bits-set or zero, depending on if the corresponding elements in were even integral values. + /// + /// This correctly handles floating-point values and so 2.0 will return all-bits-set while 2.2 will return zero. + /// This functioning returning zero for a corresponding element does not imply that will return all-bits-set for that element. A number with a fractional portion, 3.3, is not even nor odd. + /// + static abstract TSelf IsEvenInteger(TSelf vector); + + /// Determines which elements in a vector are finite. + /// The vector to be checked. + /// A vector whose elements are all-bits-set or zero, depending on if the corresponding elements in were finite. + /// This function returning zero for a corresponding element does not imply that will return all-bits-set for that element. NaN is not finite nor infinite. + static abstract TSelf IsFinite(TSelf vector); + + /// Determines which elements in a vector are infinity. + /// The vector to be checked. + /// A vector whose elements are all-bits-set or zero, depending on if the corresponding elements in were infinity. + /// This function returning zero for a corresponding element does not imply that will return all-bits-set for that element. NaN is not finite nor infinite. + static abstract TSelf IsInfinity(TSelf vector); + + /// Determines which elements in a vector are integral values. + /// The vector to be checked. + /// A vector whose elements are all-bits-set or zero, depending on if the corresponding elements in were integral values. + /// This correctly handles floating-point values and so 2.0 and 3.0 will return all-bits-set for a corresponding element while 2.2 and 3.3 will return zero. + static abstract TSelf IsInteger(TSelf vector); + /// Determines which elements in a vector are NaN. /// The vector to be checked. /// A vector whose elements are all-bits-set or zero, depending on if the corresponding elements in were NaN. @@ -340,11 +419,32 @@ static virtual TSelf CreateScalarUnsafe(T value) /// Determines which elements in a vector represents negative real numbers. /// The vector to be checked. /// A vector whose elements are all-bits-set or zero, depending on if the corresponding elements in were negative. + /// If this type has signed zero, then -0 is also considered negative. static abstract TSelf IsNegative(TSelf vector); + /// Determines which elements in a vector are negative infinity. + /// The vector to be checked. + /// A vector whose elements are all-bits-set or zero, depending on if the corresponding elements in were negative infinity. + static abstract TSelf IsNegativeInfinity(TSelf vector); + + /// Determines which elements in a vector are normal. + /// The vector to be checked. + /// A vector whose elements are all-bits-set or zero, depending on if the corresponding elements in were normal. + static abstract TSelf IsNormal(TSelf vector); + + /// Determines which elements in a vector are odd integral values. + /// The vector to be checked. + /// A vector whose elements are all-bits-set or zero, depending on if the corresponding elements in were odd integral values. + /// + /// This correctly handles floating-point values and so 3.0 will return all-bits-set for a corresponding element while 3.3 will return zero. + /// This functioning returning zero for a corresponding element does not imply that will return all-bits-set for that element. A number with a fractional portion, 3.3, is neither even nor odd. + /// + static abstract TSelf IsOddInteger(TSelf vector); + /// Determines which elements in a vector represents positive real numbers. /// The vector to be checked. /// A vector whose elements are all-bits-set or zero, depending on if the corresponding elements in were positive. + /// If this type has signed zero, then -0 is not considered positive, but +0 is. static abstract TSelf IsPositive(TSelf vector); /// Determines which elements in a vector are positive infinity. @@ -352,11 +452,29 @@ static virtual TSelf CreateScalarUnsafe(T value) /// A vector whose elements are all-bits-set or zero, depending on if the corresponding elements in were positive infinity. static abstract TSelf IsPositiveInfinity(TSelf vector); + /// Determines which elements in a vector are subnormal. + /// The vector to be checked. + /// A vector whose elements are all-bits-set or zero, depending on if the corresponding elements in were subnormal. + static abstract TSelf IsSubnormal(TSelf vector); + /// Determines which elements in a vector are zero. /// The vector to be checked. /// A vector whose elements are all-bits-set or zero, depending on if the corresponding elements in were zero. static abstract TSelf IsZero(TSelf vector); + /// Determines the index of the last element in a vector that is equal to a given value. + /// The vector whose elements are being checked. + /// The value to check for in + /// The index into representing the last element that was equal to ; otherwise, -1 if no such element exists. + /// The type of and () is not supported. + static abstract int LastIndexOf(TSelf vector, T value); + + /// Determines the index of the last element in a vector that has all bits set. + /// The vector whose elements are being checked. + /// The index into representing the last element that had all bits set; otherwise, -1 if no such element exists. + /// The type of () is not supported. + static abstract int LastIndexOfWhereAllBitsSet(TSelf vector); + /// Compares two vectors to determine which is less on a per-element basis. /// The vector to compare with . /// The vector to compare with . @@ -547,6 +665,19 @@ static virtual TSelf LoadAligned(T* source) /// The type of () is not supported. static virtual TSelf Negate(TSelf vector) => -vector; + /// Determines if no elements of a vector are equal to a given value. + /// The vector whose elements are being checked. + /// The value to check for in + /// true if no elements of are equal to ; otherwise, false. + /// The type of and () is not supported. + static abstract bool None(TSelf vector, T value); + + /// Determines if no elements of a vector have all their bits set. + /// The vector whose elements are being checked. + /// true if no elements of have all their bits set; otherwise, false. + /// The type of () is not supported. + static abstract bool NoneWhereAllBitsSet(TSelf vector); + /// Computes the ones-complement of a vector. /// The vector whose ones-complement is to be computed. /// A vector whose elements are the ones-complement of the corresponding elements in . @@ -652,7 +783,7 @@ static virtual void StoreAligned(TSelf source, T* destination) /// The type of the elements in the vector () is not supported. static virtual bool TryCopyTo(TSelf vector, Span destination) { - if (destination.Length < TSelf.Count) + if (destination.Length < TSelf.ElementCount) { return false; } @@ -676,24 +807,5 @@ static virtual bool TryCopyTo(TSelf vector, Span destination) /// The exclusive-or of and . /// The type of and () is not supported. static virtual TSelf Xor(TSelf left, TSelf right) => left ^ right; - - // - // New Surface Area - // - - /// Checks if any of the vector lanes are equivalent to value. - /// The Vector. - /// The Value to check. - /// true if has any lanes equivalent to otherwise, false if none of the lanes are equivalent to />. - /// The type of the elements in the vector () is not supported. - static abstract bool Any(TSelf vector, T value); - - /// Checks if any of the vector lanes have All Bits set. - /// The Vector to check. - /// true if has any lanes with All Bits set otherwise, false if none of the lanes have All Bits set />. - /// The type of the elements in the vector () is not supported. - static abstract bool AnyWhereAllBitsSet(TSelf vector); - - static abstract int IndexOfLastMatch(TSelf vector); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.Numerics.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.Numerics.cs new file mode 100644 index 00000000000000..699c8c5f6734c2 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.Numerics.cs @@ -0,0 +1,321 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Numerics; +using System.Runtime.CompilerServices; + +namespace System.Runtime.Intrinsics +{ + public static partial class Vector128 + { + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool All(Vector2 vector, float value) => vector.AsVector128() == Vector2.Create(value).AsVector128(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool All(Vector3 vector, float value) => vector.AsVector128() == Vector3.Create(value).AsVector128(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool AllWhereAllBitsSet(Vector2 vector) => vector.AsVector128().AsInt32() == Vector2.AllBitsSet.AsVector128().AsInt32(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool AllWhereAllBitsSet(Vector3 vector) => vector.AsVector128().AsInt32() == Vector3.AllBitsSet.AsVector128().AsInt32(); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool Any(Vector2 vector, float value) => EqualsAny(vector.AsVector128(), Create(value, value, -1, -1)); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool Any(Vector3 vector, float value) => EqualsAny(vector.AsVector128(), Create(value, value, value, -1)); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool AnyWhereAllBitsSet(Vector2 vector) => EqualsAny(vector.AsVector128().AsInt32(), Vector128.AllBitsSet); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool AnyWhereAllBitsSet(Vector3 vector) => EqualsAny(vector.AsVector128().AsInt32(), Vector128.AllBitsSet); + + /// Reinterprets a as a new . + /// The vector to reinterpret. + /// reinterpreted as a new . + [Intrinsic] + internal static Plane AsPlane(this Vector128 value) + { +#if MONO + return Unsafe.As, Plane>(ref value); +#else + return Unsafe.BitCast, Plane>(value); +#endif + } + + /// Reinterprets a as a new . + /// The vector to reinterpret. + /// reinterpreted as a new . + [Intrinsic] + internal static Quaternion AsQuaternion(this Vector128 value) + { +#if MONO + return Unsafe.As, Quaternion>(ref value); +#else + return Unsafe.BitCast, Quaternion>(value); +#endif + } + + /// Reinterprets a as a new . + /// The plane to reinterpret. + /// reinterpreted as a new . + [Intrinsic] + internal static Vector128 AsVector128(this Plane value) + { +#if MONO + return Unsafe.As>(ref value); +#else + return Unsafe.BitCast>(value); +#endif + } + + /// Reinterprets a as a new . + /// The quaternion to reinterpret. + /// reinterpreted as a new . + [Intrinsic] + internal static Vector128 AsVector128(this Quaternion value) + { +#if MONO + return Unsafe.As>(ref value); +#else + return Unsafe.BitCast>(value); +#endif + } + + /// Reinterprets a as a new with the new elements zeroed. + /// The vector to reinterpret. + /// reinterpreted as a new with the new elements zeroed. + [Intrinsic] + public static Vector128 AsVector128(this Vector2 value) => Vector4.Create(value, 0, 0).AsVector128(); + + /// Reinterprets a as a new with the new elements zeroed. + /// The vector to reinterpret. + /// reinterpreted as a new with the new elements zeroed. + [Intrinsic] + public static Vector128 AsVector128(this Vector3 value) => Vector4.Create(value, 0).AsVector128(); + + /// Reinterprets a as a new . + /// The vector to reinterpret. + /// reinterpreted as a new . + [Intrinsic] + public static Vector128 AsVector128(this Vector4 value) + { +#if MONO + return Unsafe.As>(ref value); +#else + return Unsafe.BitCast>(value); +#endif + } + + /// Reinterprets a as a new . + /// The type of the elements in the vector. + /// The vector to reinterpret. + /// reinterpreted as a new . + /// The type of () is not supported. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 AsVector128(this Vector value) + { + Debug.Assert(Vector.Count >= Vector128.Count); + ThrowHelper.ThrowForUnsupportedIntrinsicsVector128BaseType(); + + ref byte address = ref Unsafe.As, byte>(ref value); + return Unsafe.ReadUnaligned>(ref address); + } + + /// Reinterprets a as a new , leaving the new elements undefined. + /// The vector to reinterpret. + /// reinterpreted as a new . + [Intrinsic] + public static Vector128 AsVector128Unsafe(this Vector2 value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + Unsafe.SkipInit(out Vector128 result); + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + + /// Reinterprets a as a new , leaving the new elements undefined. + /// The vector to reinterpret. + /// reinterpreted as a new . + [Intrinsic] + public static Vector128 AsVector128Unsafe(this Vector3 value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + Unsafe.SkipInit(out Vector128 result); + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + + /// Reinterprets a as a new . + /// The vector to reinterpret. + /// reinterpreted as a new . + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 AsVector2(this Vector128 value) + { + ref byte address = ref Unsafe.As, byte>(ref value); + return Unsafe.ReadUnaligned(ref address); + } + + /// Reinterprets a as a new . + /// The vector to reinterpret. + /// reinterpreted as a new . + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector3 AsVector3(this Vector128 value) + { + ref byte address = ref Unsafe.As, byte>(ref value); + return Unsafe.ReadUnaligned(ref address); + } + + /// Reinterprets a as a new . + /// The vector to reinterpret. + /// reinterpreted as a new . + [Intrinsic] + public static Vector4 AsVector4(this Vector128 value) + { +#if MONO + return Unsafe.As, Vector4>(ref value); +#else + return Unsafe.BitCast, Vector4>(value); +#endif + } + + /// Reinterprets a as a new . + /// The type of the elements in the vector. + /// The vector to reinterpret. + /// reinterpreted as a new . + /// The type of () is not supported. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector AsVector(this Vector128 value) + { + Debug.Assert(Vector.Count >= Vector128.Count); + ThrowHelper.ThrowForUnsupportedIntrinsicsVector128BaseType(); + + Vector result = default; + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int Count(Vector2 vector, float value) => BitOperations.PopCount(Equals(vector.AsVector128(), Create(value, value, -1, -1)).ExtractMostSignificantBits()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int Count(Vector3 vector, float value) => BitOperations.PopCount(Equals(vector.AsVector128(), Create(value, value, value, -1)).ExtractMostSignificantBits()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int CountWhereAllBitsSet(Vector2 vector) => BitOperations.PopCount(Equals(vector.AsVector128().AsInt32(), Vector128.AllBitsSet).ExtractMostSignificantBits()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int CountWhereAllBitsSet(Vector3 vector) => BitOperations.PopCount(Equals(vector.AsVector128().AsInt32(), Vector128.AllBitsSet).ExtractMostSignificantBits()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int IndexOf(Vector2 vector, float value) + { + int result = BitOperations.TrailingZeroCount(Equals(vector.AsVector128(), Create(value, value, -1, -1)).ExtractMostSignificantBits()); + return (result != 32) ? result : -1; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int IndexOf(Vector3 vector, float value) + { + int result = BitOperations.TrailingZeroCount(Equals(vector.AsVector128(), Create(value, value, value, -1)).ExtractMostSignificantBits()); + return (result != 32) ? result : -1; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int IndexOfWhereAllBitsSet(Vector2 vector) + { + int result = BitOperations.TrailingZeroCount(Equals(vector.AsVector128().AsInt32(), Vector128.AllBitsSet).ExtractMostSignificantBits()); + return (result != 32) ? result : -1; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int IndexOfWhereAllBitsSet(Vector3 vector) + { + int result = BitOperations.TrailingZeroCount(Equals(vector.AsVector128().AsInt32(), Vector128.AllBitsSet).ExtractMostSignificantBits()); + return (result != 32) ? result : -1; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int LastIndexOf(Vector2 vector, float value) => 31 - BitOperations.LeadingZeroCount(Equals(vector.AsVector128(), Create(value, value, -1, -1)).ExtractMostSignificantBits()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int LastIndexOf(Vector3 vector, float value) => 31 - BitOperations.LeadingZeroCount(Equals(vector.AsVector128(), Create(value, value, value, -1)).ExtractMostSignificantBits()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int LastIndexOfWhereAllBitsSet(Vector2 vector) => 31 - BitOperations.LeadingZeroCount(Equals(vector.AsVector128().AsInt32(), Vector128.AllBitsSet).ExtractMostSignificantBits()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int LastIndexOfWhereAllBitsSet(Vector3 vector) => 31 - BitOperations.LeadingZeroCount(Equals(vector.AsVector128().AsInt32(), Vector128.AllBitsSet).ExtractMostSignificantBits()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool None(Vector2 vector, float value) => !EqualsAny(vector.AsVector128(), Create(value, value, -1, -1)); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool None(Vector3 vector, float value) => !EqualsAny(vector.AsVector128(), Create(value, value, value, -1)); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool NoneWhereAllBitsSet(Vector2 vector) => !EqualsAny(vector.AsVector128().AsInt32(), Vector128.AllBitsSet); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool NoneWhereAllBitsSet(Vector3 vector) => !EqualsAny(vector.AsVector128().AsInt32(), Vector128.AllBitsSet); + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs index 8fb3436cf3cf8e..6831123b931848 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128.cs @@ -30,7 +30,7 @@ namespace System.Runtime.Intrinsics // the internal inlining limits of the JIT. /// Provides a collection of static methods for creating, manipulating, and otherwise operating on 128-bit vectors. - public static class Vector128 + public static partial class Vector128 { internal const int Size = 16; @@ -84,6 +84,30 @@ public static Vector128 Abs(Vector128 vector) [Intrinsic] public static Vector128 Add(Vector128 left, Vector128 right) => left + right; + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool All(Vector128 vector, T value) => vector == Create(value); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool AllWhereAllBitsSet(Vector128 vector) + { + if (typeof(T) == typeof(float)) + { + return All(vector.AsInt32(), -1); + } + else if (typeof(T) == typeof(double)) + { + return All(vector.AsInt64(), -1); + } + else + { + return All(vector, Scalar.AllBitsSet); + } + } + /// Computes the bitwise-and of a given vector and the ones complement of another vector. /// The type of the elements in the vector. /// The vector to bitwise-and with . @@ -93,6 +117,30 @@ public static Vector128 Abs(Vector128 vector) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 AndNot(Vector128 left, Vector128 right) => left & ~right; + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool Any(Vector128 vector, T value) => EqualsAny(vector, Create(value)); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool AnyWhereAllBitsSet(Vector128 vector) + { + if (typeof(T) == typeof(float)) + { + return Any(vector.AsInt32(), -1); + } + else if (typeof(T) == typeof(double)) + { + return Any(vector.AsInt64(), -1); + } + else + { + return Any(vector, Scalar.AllBitsSet); + } + } + /// Reinterprets a as a new . /// The type of the elements in the input vector. /// The type of the elements in the output vector. @@ -170,32 +218,6 @@ public static Vector128 As(this Vector128 vector) [CLSCompliant(false)] public static Vector128 AsNUInt(this Vector128 vector) => vector.As(); - /// Reinterprets a as a new . - /// The vector to reinterpret. - /// reinterpreted as a new . - [Intrinsic] - internal static Plane AsPlane(this Vector128 value) - { -#if MONO - return Unsafe.As, Plane>(ref value); -#else - return Unsafe.BitCast, Plane>(value); -#endif - } - - /// Reinterprets a as a new . - /// The vector to reinterpret. - /// reinterpreted as a new . - [Intrinsic] - internal static Quaternion AsQuaternion(this Vector128 value) - { -#if MONO - return Unsafe.As, Quaternion>(ref value); -#else - return Unsafe.BitCast, Quaternion>(value); -#endif - } - /// Reinterprets a as a new . /// The type of the elements in the vector. /// The vector to reinterpret. @@ -240,153 +262,6 @@ internal static Quaternion AsQuaternion(this Vector128 value) [CLSCompliant(false)] public static Vector128 AsUInt64(this Vector128 vector) => vector.As(); - /// Reinterprets a as a new . - /// The plane to reinterpret. - /// reinterpreted as a new . - [Intrinsic] - internal static Vector128 AsVector128(this Plane value) - { -#if MONO - return Unsafe.As>(ref value); -#else - return Unsafe.BitCast>(value); -#endif - } - - /// Reinterprets a as a new . - /// The quaternion to reinterpret. - /// reinterpreted as a new . - [Intrinsic] - internal static Vector128 AsVector128(this Quaternion value) - { -#if MONO - return Unsafe.As>(ref value); -#else - return Unsafe.BitCast>(value); -#endif - } - - /// Reinterprets a as a new with the new elements zeroed. - /// The vector to reinterpret. - /// reinterpreted as a new with the new elements zeroed. - [Intrinsic] - public static Vector128 AsVector128(this Vector2 value) => Vector4.Create(value, 0, 0).AsVector128(); - - /// Reinterprets a as a new with the new elements zeroed. - /// The vector to reinterpret. - /// reinterpreted as a new with the new elements zeroed. - [Intrinsic] - public static Vector128 AsVector128(this Vector3 value) => Vector4.Create(value, 0).AsVector128(); - - /// Reinterprets a as a new . - /// The vector to reinterpret. - /// reinterpreted as a new . - [Intrinsic] - public static Vector128 AsVector128(this Vector4 value) - { -#if MONO - return Unsafe.As>(ref value); -#else - return Unsafe.BitCast>(value); -#endif - } - - /// Reinterprets a as a new . - /// The type of the elements in the vector. - /// The vector to reinterpret. - /// reinterpreted as a new . - /// The type of () is not supported. - [Intrinsic] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector128 AsVector128(this Vector value) - { - Debug.Assert(Vector.Count >= Vector128.Count); - ThrowHelper.ThrowForUnsupportedIntrinsicsVector128BaseType(); - - ref byte address = ref Unsafe.As, byte>(ref value); - return Unsafe.ReadUnaligned>(ref address); - } - - /// Reinterprets a as a new , leaving the new elements undefined. - /// The vector to reinterpret. - /// reinterpreted as a new . - [Intrinsic] - public static Vector128 AsVector128Unsafe(this Vector2 value) - { - // This relies on us stripping the "init" flag from the ".locals" - // declaration to let the upper bits be uninitialized. - - Unsafe.SkipInit(out Vector128 result); - Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); - return result; - } - - /// Reinterprets a as a new , leaving the new elements undefined. - /// The vector to reinterpret. - /// reinterpreted as a new . - [Intrinsic] - public static Vector128 AsVector128Unsafe(this Vector3 value) - { - // This relies on us stripping the "init" flag from the ".locals" - // declaration to let the upper bits be uninitialized. - - Unsafe.SkipInit(out Vector128 result); - Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); - return result; - } - - /// Reinterprets a as a new . - /// The vector to reinterpret. - /// reinterpreted as a new . - [Intrinsic] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector2 AsVector2(this Vector128 value) - { - ref byte address = ref Unsafe.As, byte>(ref value); - return Unsafe.ReadUnaligned(ref address); - } - - /// Reinterprets a as a new . - /// The vector to reinterpret. - /// reinterpreted as a new . - [Intrinsic] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector3 AsVector3(this Vector128 value) - { - ref byte address = ref Unsafe.As, byte>(ref value); - return Unsafe.ReadUnaligned(ref address); - } - - /// Reinterprets a as a new . - /// The vector to reinterpret. - /// reinterpreted as a new . - [Intrinsic] - public static Vector4 AsVector4(this Vector128 value) - { -#if MONO - return Unsafe.As, Vector4>(ref value); -#else - return Unsafe.BitCast, Vector4>(value); -#endif - } - - /// Reinterprets a as a new . - /// The type of the elements in the vector. - /// The vector to reinterpret. - /// reinterpreted as a new . - /// The type of () is not supported. - [Intrinsic] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector AsVector(this Vector128 value) - { - Debug.Assert(Vector.Count >= Vector128.Count); - ThrowHelper.ThrowForUnsupportedIntrinsicsVector128BaseType(); - - Vector result = default; - Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); - return result; - } - /// Computes the bitwise-and of two vectors. /// The type of the elements in the vector. /// The vector to bitwise-and with . @@ -448,7 +323,7 @@ internal static Vector128 Ceiling(Vector128 vector) [Intrinsic] public static Vector128 Ceiling(Vector128 vector) => Ceiling(vector); - /// + /// [Intrinsic] public static Vector128 Clamp(Vector128 value, Vector128 min, Vector128 max) { @@ -456,7 +331,7 @@ public static Vector128 Clamp(Vector128 value, Vector128 min, Vector return Min(Max(value, min), max); } - /// + /// [Intrinsic] public static Vector128 ClampNative(Vector128 value, Vector128 min, Vector128 max) { @@ -734,7 +609,7 @@ public static unsafe Vector128 ConvertToUInt64Native(Vector128 ve ); } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 CopySign(Vector128 value, Vector128 sign) @@ -865,6 +740,30 @@ public static Vector128 Cos(Vector128 vector) } } + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Count(Vector128 vector, T value) => BitOperations.PopCount(Equals(vector, Create(value)).ExtractMostSignificantBits()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int CountWhereAllBitsSet(Vector128 vector) + { + if (typeof(T) == typeof(float)) + { + return Count(vector.AsInt32(), -1); + } + else if (typeof(T) == typeof(double)) + { + return Count(vector.AsInt64(), -1); + } + else + { + return Count(vector, Scalar.AllBitsSet); + } + } + /// Creates a new instance with all elements initialized to the specified value. /// The type of the elements in the vector. /// The value that all elements will be initialized to. @@ -1921,7 +1820,91 @@ public static Vector128 Hypot(Vector128 x, Vector128 y) } } - /// + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int IndexOf(Vector128 vector, T value) + { + int result = BitOperations.TrailingZeroCount(Equals(vector, Create(value)).ExtractMostSignificantBits()); + return (result != 32) ? result : -1; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int IndexOfWhereAllBitsSet(Vector128 vector) + { + if (typeof(T) == typeof(float)) + { + return IndexOf(vector.AsInt32(), -1); + } + else if (typeof(T) == typeof(double)) + { + return IndexOf(vector.AsInt64(), -1); + } + else + { + return IndexOf(vector, Scalar.AllBitsSet); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 IsEvenInteger(Vector128 vector) + { + if (typeof(T) == typeof(float)) + { + return VectorMath.IsEvenIntegerSingle, Vector128>(vector.AsSingle()).As(); + } + else if (typeof(T) == typeof(double)) + { + return VectorMath.IsEvenIntegerDouble, Vector128>(vector.AsDouble()).As(); + } + return IsZero(vector & Vector128.One); + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 IsFinite(Vector128 vector) + { + if (typeof(T) == typeof(float)) + { + return ~IsZero(AndNot(Create(float.PositiveInfinityBits), vector.AsUInt32())).As(); + } + else if (typeof(T) == typeof(double)) + { + return ~IsZero(AndNot(Create(double.PositiveInfinityBits), vector.AsUInt64())).As(); + } + return Vector128.AllBitsSet; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 IsInfinity(Vector128 vector) + { + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) + { + return IsPositiveInfinity(Abs(vector)); + } + return Vector128.Zero; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 IsInteger(Vector128 vector) + { + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) + { + return IsFinite(vector) & Equals(vector, Truncate(vector)); + } + return Vector128.AllBitsSet; + } + + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 IsNaN(Vector128 vector) @@ -1933,7 +1916,7 @@ public static Vector128 IsNaN(Vector128 vector) return Vector128.Zero; } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 IsNegative(Vector128 vector) @@ -1960,7 +1943,55 @@ public static Vector128 IsNegative(Vector128 vector) } } - /// + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 IsNegativeInfinity(Vector128 vector) + { + if (typeof(T) == typeof(float)) + { + return Equals(vector, Create(float.NegativeInfinity).As()); + } + else if (typeof(T) == typeof(double)) + { + return Equals(vector, Create(double.NegativeInfinity).As()); + } + return Vector128.Zero; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 IsNormal(Vector128 vector) + { + if (typeof(T) == typeof(float)) + { + return LessThan(Abs(vector).AsUInt32() - Create(float.SmallestNormalBits), Create(float.PositiveInfinityBits - float.SmallestNormalBits)).As(); + } + else if (typeof(T) == typeof(double)) + { + return LessThan(Abs(vector).AsUInt64() - Create(double.SmallestNormalBits), Create(double.PositiveInfinityBits - double.SmallestNormalBits)).As(); + } + return ~IsZero(vector); + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 IsOddInteger(Vector128 vector) + { + if (typeof(T) == typeof(float)) + { + return VectorMath.IsOddIntegerSingle, Vector128>(vector.AsSingle()).As(); + } + else if (typeof(T) == typeof(double)) + { + return VectorMath.IsOddIntegerDouble, Vector128>(vector.AsDouble()).As(); + } + return ~IsZero(vector & Vector128.One); + } + + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 IsPositive(Vector128 vector) @@ -1987,7 +2018,7 @@ public static Vector128 IsPositive(Vector128 vector) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 IsPositiveInfinity(Vector128 vector) @@ -2003,11 +2034,51 @@ public static Vector128 IsPositiveInfinity(Vector128 vector) return Vector128.Zero; } - /// + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector128 IsSubnormal(Vector128 vector) + { + if (typeof(T) == typeof(float)) + { + return LessThan(Abs(vector).AsUInt32() - Vector128.One, Create(float.MaxTrailingSignificand)).As(); + } + else if (typeof(T) == typeof(double)) + { + return LessThan(Abs(vector).AsUInt64() - Vector128.One, Create(double.MaxTrailingSignificand)).As(); + } + return Vector128.Zero; + } + + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 IsZero(Vector128 vector) => Equals(vector, Vector128.Zero); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int LastIndexOf(Vector128 vector, T value) => 31 - BitOperations.LeadingZeroCount(Equals(vector, Create(value)).ExtractMostSignificantBits()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int LastIndexOfWhereAllBitsSet(Vector128 vector) + { + if (typeof(T) == typeof(float)) + { + return LastIndexOf(vector.AsInt32(), -1); + } + else if (typeof(T) == typeof(double)) + { + return LastIndexOf(vector.AsInt64(), -1); + } + else + { + return LastIndexOf(vector, Scalar.AllBitsSet); + } + } + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -2280,7 +2351,7 @@ public static Vector128 Log2(Vector128 vector) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 Max(Vector128 left, Vector128 right) @@ -2298,7 +2369,7 @@ public static Vector128 Max(Vector128 left, Vector128 right) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 MaxMagnitude(Vector128 left, Vector128 right) @@ -2316,7 +2387,7 @@ public static Vector128 MaxMagnitude(Vector128 left, Vector128 right } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 MaxMagnitudeNumber(Vector128 left, Vector128 right) @@ -2334,7 +2405,7 @@ public static Vector128 MaxMagnitudeNumber(Vector128 left, Vector128 } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 MaxNative(Vector128 left, Vector128 right) @@ -2352,7 +2423,7 @@ public static Vector128 MaxNative(Vector128 left, Vector128 right) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 MaxNumber(Vector128 left, Vector128 right) @@ -2370,7 +2441,7 @@ public static Vector128 MaxNumber(Vector128 left, Vector128 right) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 Min(Vector128 left, Vector128 right) @@ -2388,7 +2459,7 @@ public static Vector128 Min(Vector128 left, Vector128 right) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 MinMagnitude(Vector128 left, Vector128 right) @@ -2406,7 +2477,7 @@ public static Vector128 MinMagnitude(Vector128 left, Vector128 right } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 MinMagnitudeNumber(Vector128 left, Vector128 right) @@ -2424,7 +2495,7 @@ public static Vector128 MinMagnitudeNumber(Vector128 left, Vector128 } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 MinNative(Vector128 left, Vector128 right) @@ -2442,7 +2513,7 @@ public static Vector128 MinNative(Vector128 left, Vector128 right) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector128 MinNumber(Vector128 left, Vector128 right) @@ -2629,6 +2700,30 @@ public static unsafe Vector128 Narrow(Vector128 lower, Vector128
    Negate(Vector128 vector) => -vector; + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool None(Vector128 vector, T value) => !EqualsAny(vector, Create(value)); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool NoneWhereAllBitsSet(Vector128 vector) + { + if (typeof(T) == typeof(float)) + { + return None(vector.AsInt32(), -1); + } + else if (typeof(T) == typeof(double)) + { + return None(vector.AsInt64(), -1); + } + else + { + return None(vector, Scalar.AllBitsSet); + } + } + /// Computes the ones-complement of a vector. /// The type of the elements in the vector. /// The vector whose ones-complement is to be computed. @@ -2789,6 +2884,15 @@ internal static Vector128 Round(Vector128 vector) [CLSCompliant(false)] public static Vector128 ShiftLeft(Vector128 vector, int shiftCount) => vector << shiftCount; + [Intrinsic] + internal static Vector128 ShiftLeft(Vector128 vector, Vector128 shiftCount) + { + return Create( + Vector64.ShiftLeft(vector._lower, shiftCount._lower), + Vector64.ShiftLeft(vector._lower, shiftCount._upper) + ); + } + /// Shifts each element of a vector left by the specified amount. /// The vector whose elements are to be shifted. /// The number of bits by which to shift each element. @@ -2797,6 +2901,15 @@ internal static Vector128 Round(Vector128 vector) [CLSCompliant(false)] public static Vector128 ShiftLeft(Vector128 vector, int shiftCount) => vector << shiftCount; + [Intrinsic] + internal static Vector128 ShiftLeft(Vector128 vector, Vector128 shiftCount) + { + return Create( + Vector64.ShiftLeft(vector._lower, shiftCount._lower), + Vector64.ShiftLeft(vector._lower, shiftCount._upper) + ); + } + /// Shifts (signed) each element of a vector right by the specified amount. /// The vector whose elements are to be shifted. /// The number of bits by which to shift each element. @@ -3495,7 +3608,7 @@ internal static Vector128 Truncate(Vector128 vector) [Intrinsic] public static Vector128 Truncate(Vector128 vector) => Truncate(vector); - /// Tries to copy a to a given span. + /// Tries to copy a to a given span. /// The type of the input vector. /// The vector to copy. /// The span to which is copied. diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128_1.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128_1.cs index 46c2ae3cb1c93d..bfcf28021c5845 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128_1.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128_1.cs @@ -471,6 +471,9 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri /// static int ISimdVector, T>.Alignment => Vector128.Alignment; + /// + static int ISimdVector, T>.ElementCount => Vector128.Count; + /// static bool ISimdVector, T>.IsHardwareAccelerated { @@ -486,10 +489,26 @@ static bool ISimdVector, T>.IsHardwareAccelerated [Intrinsic] static Vector128 ISimdVector, T>.Add(Vector128 left, Vector128 right) => left + right; + /// + [Intrinsic] + static bool ISimdVector, T>.All(Vector128 vector, T value) => Vector128.All(vector, value); + + /// + [Intrinsic] + static bool ISimdVector, T>.AllWhereAllBitsSet(Vector128 vector) => Vector128.AllWhereAllBitsSet(vector); + /// [Intrinsic] static Vector128 ISimdVector, T>.AndNot(Vector128 left, Vector128 right) => Vector128.AndNot(left, right); + /// + [Intrinsic] + static bool ISimdVector, T>.Any(Vector128 vector, T value) => Vector128.Any(vector, value); + + /// + [Intrinsic] + static bool ISimdVector, T>.AnyWhereAllBitsSet(Vector128 vector) => Vector128.AnyWhereAllBitsSet(vector); + /// [Intrinsic] static Vector128 ISimdVector, T>.BitwiseAnd(Vector128 left, Vector128 right) => left & right; @@ -527,6 +546,14 @@ static bool ISimdVector, T>.IsHardwareAccelerated /// static void ISimdVector, T>.CopyTo(Vector128 vector, Span destination) => vector.CopyTo(destination); + /// + [Intrinsic] + static int ISimdVector, T>.Count(Vector128 vector, T value) => Vector128.Count(vector, value); + + /// + [Intrinsic] + static int ISimdVector, T>.CountWhereAllBitsSet(Vector128 vector) => Vector128.CountWhereAllBitsSet(vector); + /// [Intrinsic] static Vector128 ISimdVector, T>.Create(T value) => Vector128.Create(value); @@ -604,6 +631,74 @@ static bool ISimdVector, T>.IsHardwareAccelerated [Intrinsic] static bool ISimdVector, T>.GreaterThanOrEqualAny(Vector128 left, Vector128 right) => Vector128.GreaterThanOrEqualAny(left, right); + /// + [Intrinsic] + static int ISimdVector, T>.IndexOf(Vector128 vector, T value) => Vector128.IndexOf(vector, value); + + /// + [Intrinsic] + static int ISimdVector, T>.IndexOfWhereAllBitsSet(Vector128 vector) => Vector128.IndexOfWhereAllBitsSet(vector); + + /// + [Intrinsic] + static Vector128 ISimdVector, T>.IsEvenInteger(Vector128 vector) => Vector128.IsEvenInteger(vector); + + /// + [Intrinsic] + static Vector128 ISimdVector, T>.IsFinite(Vector128 vector) => Vector128.IsFinite(vector); + + /// + [Intrinsic] + static Vector128 ISimdVector, T>.IsInfinity(Vector128 vector) => Vector128.IsInfinity(vector); + + /// + [Intrinsic] + static Vector128 ISimdVector, T>.IsInteger(Vector128 vector) => Vector128.IsInteger(vector); + + /// + [Intrinsic] + static Vector128 ISimdVector, T>.IsNaN(Vector128 vector) => Vector128.IsNaN(vector); + + /// + [Intrinsic] + static Vector128 ISimdVector, T>.IsNegative(Vector128 vector) => Vector128.IsNegative(vector); + + /// + [Intrinsic] + static Vector128 ISimdVector, T>.IsNegativeInfinity(Vector128 vector) => Vector128.IsNegativeInfinity(vector); + + /// + [Intrinsic] + static Vector128 ISimdVector, T>.IsNormal(Vector128 vector) => Vector128.IsNormal(vector); + + /// + [Intrinsic] + static Vector128 ISimdVector, T>.IsOddInteger(Vector128 vector) => Vector128.IsOddInteger(vector); + + /// + [Intrinsic] + static Vector128 ISimdVector, T>.IsPositive(Vector128 vector) => Vector128.IsPositive(vector); + + /// + [Intrinsic] + static Vector128 ISimdVector, T>.IsPositiveInfinity(Vector128 vector) => Vector128.IsPositiveInfinity(vector); + + /// + [Intrinsic] + static Vector128 ISimdVector, T>.IsSubnormal(Vector128 vector) => Vector128.IsSubnormal(vector); + + /// + [Intrinsic] + static Vector128 ISimdVector, T>.IsZero(Vector128 vector) => Vector128.IsZero(vector); + + /// + [Intrinsic] + static int ISimdVector, T>.LastIndexOf(Vector128 vector, T value) => Vector128.LastIndexOf(vector, value); + + /// + [Intrinsic] + static int ISimdVector, T>.LastIndexOfWhereAllBitsSet(Vector128 vector) => Vector128.LastIndexOfWhereAllBitsSet(vector); + /// [Intrinsic] static Vector128 ISimdVector, T>.LessThan(Vector128 left, Vector128 right) => Vector128.LessThan(left, right); @@ -704,6 +799,14 @@ static bool ISimdVector, T>.IsHardwareAccelerated [Intrinsic] static Vector128 ISimdVector, T>.Negate(Vector128 vector) => -vector; + /// + [Intrinsic] + static bool ISimdVector, T>.None(Vector128 vector, T value) => Vector128.None(vector, value); + + /// + [Intrinsic] + static bool ISimdVector, T>.NoneWhereAllBitsSet(Vector128 vector) => Vector128.NoneWhereAllBitsSet(vector); + /// [Intrinsic] static Vector128 ISimdVector, T>.OnesComplement(Vector128 vector) => ~vector; @@ -774,34 +877,5 @@ static bool ISimdVector, T>.IsHardwareAccelerated /// [Intrinsic] static Vector128 ISimdVector, T>.Xor(Vector128 left, Vector128 right) => left ^ right; - - // - // New Surface Area - // - - static bool ISimdVector, T>.AnyWhereAllBitsSet(Vector128 vector) => Vector128.EqualsAny(vector, AllBitsSet); - - static bool ISimdVector, T>.Any(Vector128 vector, T value) => Vector128.EqualsAny(vector, Vector128.Create(value)); - - static int ISimdVector, T>.IndexOfLastMatch(Vector128 vector) - { - uint mask = vector.ExtractMostSignificantBits(); - return 31 - BitOperations.LeadingZeroCount(mask); // 31 = 32 (bits in Int32) - 1 (indexing from zero) - } - - [Intrinsic] - static Vector128 ISimdVector, T>.IsNaN(Vector128 vector) => Vector128.IsNaN(vector); - - [Intrinsic] - static Vector128 ISimdVector, T>.IsNegative(Vector128 vector) => Vector128.IsNegative(vector); - - [Intrinsic] - static Vector128 ISimdVector, T>.IsPositive(Vector128 vector) => Vector128.IsPositive(vector); - - [Intrinsic] - static Vector128 ISimdVector, T>.IsPositiveInfinity(Vector128 vector) => Vector128.IsPositiveInfinity(vector); - - [Intrinsic] - static Vector128 ISimdVector, T>.IsZero(Vector128 vector) => Vector128.IsZero(vector); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs index ebd1bb725bebdd..3393ca1b58c5f9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256.cs @@ -88,6 +88,30 @@ public static Vector256 Abs(Vector256 vector) [Intrinsic] public static Vector256 Add(Vector256 left, Vector256 right) => left + right; + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool All(Vector256 vector, T value) => vector == Create(value); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool AllWhereAllBitsSet(Vector256 vector) + { + if (typeof(T) == typeof(float)) + { + return All(vector.AsInt32(), -1); + } + else if (typeof(T) == typeof(double)) + { + return All(vector.AsInt64(), -1); + } + else + { + return All(vector, Scalar.AllBitsSet); + } + } + /// Computes the bitwise-and of a given vector and the ones complement of another vector. /// The type of the elements in the vector. /// The vector to bitwise-and with . @@ -98,6 +122,30 @@ public static Vector256 Abs(Vector256 vector) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 AndNot(Vector256 left, Vector256 right) => left & ~right; + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool Any(Vector256 vector, T value) => EqualsAny(vector, Create(value)); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool AnyWhereAllBitsSet(Vector256 vector) + { + if (typeof(T) == typeof(float)) + { + return Any(vector.AsInt32(), -1); + } + else if (typeof(T) == typeof(double)) + { + return Any(vector.AsInt64(), -1); + } + else + { + return Any(vector, Scalar.AllBitsSet); + } + } + /// Reinterprets a as a new . /// The type of the elements in the input vector. /// The type of the elements in the output vector. @@ -328,7 +376,7 @@ internal static Vector256 Ceiling(Vector256 vector) [Intrinsic] public static Vector256 Ceiling(Vector256 vector) => Ceiling(vector); - /// + /// [Intrinsic] public static Vector256 Clamp(Vector256 value, Vector256 min, Vector256 max) { @@ -336,7 +384,7 @@ public static Vector256 Clamp(Vector256 value, Vector256 min, Vector return Min(Max(value, min), max); } - /// + /// [Intrinsic] public static Vector256 ClampNative(Vector256 value, Vector256 min, Vector256 max) { @@ -588,7 +636,7 @@ public static Vector256 ConvertToUInt64Native(Vector256 vector) ); } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 CopySign(Vector256 value, Vector256 sign) @@ -719,6 +767,30 @@ public static Vector256 Cos(Vector256 vector) } } + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Count(Vector256 vector, T value) => BitOperations.PopCount(Equals(vector, Create(value)).ExtractMostSignificantBits()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int CountWhereAllBitsSet(Vector256 vector) + { + if (typeof(T) == typeof(float)) + { + return Count(vector.AsInt32(), -1); + } + else if (typeof(T) == typeof(double)) + { + return Count(vector.AsInt64(), -1); + } + else + { + return Count(vector, Scalar.AllBitsSet); + } + } + /// Creates a new instance with all elements initialized to the specified value. /// The type of the elements in the vector. /// The value that all elements will be initialized to. @@ -1852,7 +1924,91 @@ public static Vector256 Hypot(Vector256 x, Vector256 y) } } - /// + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int IndexOf(Vector256 vector, T value) + { + int result = BitOperations.TrailingZeroCount(Equals(vector, Create(value)).ExtractMostSignificantBits()); + return (result != 32) ? result : -1; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int IndexOfWhereAllBitsSet(Vector256 vector) + { + if (typeof(T) == typeof(float)) + { + return IndexOf(vector.AsInt32(), -1); + } + else if (typeof(T) == typeof(double)) + { + return IndexOf(vector.AsInt64(), -1); + } + else + { + return IndexOf(vector, Scalar.AllBitsSet); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 IsEvenInteger(Vector256 vector) + { + if (typeof(T) == typeof(float)) + { + return VectorMath.IsEvenIntegerSingle, Vector256>(vector.AsSingle()).As(); + } + else if (typeof(T) == typeof(double)) + { + return VectorMath.IsEvenIntegerDouble, Vector256>(vector.AsDouble()).As(); + } + return IsZero(vector & Vector256.One); + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 IsFinite(Vector256 vector) + { + if (typeof(T) == typeof(float)) + { + return ~IsZero(AndNot(Create(float.PositiveInfinityBits), vector.AsUInt32())).As(); + } + else if (typeof(T) == typeof(double)) + { + return ~IsZero(AndNot(Create(double.PositiveInfinityBits), vector.AsUInt64())).As(); + } + return Vector256.AllBitsSet; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 IsInfinity(Vector256 vector) + { + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) + { + return IsPositiveInfinity(Abs(vector)); + } + return Vector256.Zero; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 IsInteger(Vector256 vector) + { + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) + { + return IsFinite(vector) & Equals(vector, Truncate(vector)); + } + return Vector256.AllBitsSet; + } + + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 IsNaN(Vector256 vector) @@ -1864,7 +2020,7 @@ public static Vector256 IsNaN(Vector256 vector) return Vector256.Zero; } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 IsNegative(Vector256 vector) @@ -1891,7 +2047,55 @@ public static Vector256 IsNegative(Vector256 vector) } } - /// + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 IsNegativeInfinity(Vector256 vector) + { + if (typeof(T) == typeof(float)) + { + return Equals(vector, Create(float.NegativeInfinity).As()); + } + else if (typeof(T) == typeof(double)) + { + return Equals(vector, Create(double.NegativeInfinity).As()); + } + return Vector256.Zero; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 IsNormal(Vector256 vector) + { + if (typeof(T) == typeof(float)) + { + return LessThan(Abs(vector).AsUInt32() - Create(float.SmallestNormalBits), Create(float.PositiveInfinityBits - float.SmallestNormalBits)).As(); + } + else if (typeof(T) == typeof(double)) + { + return LessThan(Abs(vector).AsUInt64() - Create(double.SmallestNormalBits), Create(double.PositiveInfinityBits - double.SmallestNormalBits)).As(); + } + return ~IsZero(vector); + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 IsOddInteger(Vector256 vector) + { + if (typeof(T) == typeof(float)) + { + return VectorMath.IsOddIntegerSingle, Vector256>(vector.AsSingle()).As(); + } + else if (typeof(T) == typeof(double)) + { + return VectorMath.IsOddIntegerDouble, Vector256>(vector.AsDouble()).As(); + } + return ~IsZero(vector & Vector256.One); + } + + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 IsPositive(Vector256 vector) @@ -1918,7 +2122,7 @@ public static Vector256 IsPositive(Vector256 vector) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 IsPositiveInfinity(Vector256 vector) @@ -1934,11 +2138,51 @@ public static Vector256 IsPositiveInfinity(Vector256 vector) return Vector256.Zero; } - /// + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 IsSubnormal(Vector256 vector) + { + if (typeof(T) == typeof(float)) + { + return LessThan(Abs(vector).AsUInt32() - Vector256.One, Create(float.MaxTrailingSignificand)).As(); + } + else if (typeof(T) == typeof(double)) + { + return LessThan(Abs(vector).AsUInt64() - Vector256.One, Create(double.MaxTrailingSignificand)).As(); + } + return Vector256.Zero; + } + + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 IsZero(Vector256 vector) => Equals(vector, Vector256.Zero); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int LastIndexOf(Vector256 vector, T value) => 31 - BitOperations.LeadingZeroCount(Equals(vector, Create(value)).ExtractMostSignificantBits()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int LastIndexOfWhereAllBitsSet(Vector256 vector) + { + if (typeof(T) == typeof(float)) + { + return LastIndexOf(vector.AsInt32(), -1); + } + else if (typeof(T) == typeof(double)) + { + return LastIndexOf(vector.AsInt64(), -1); + } + else + { + return LastIndexOf(vector, Scalar.AllBitsSet); + } + } + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -2211,7 +2455,7 @@ public static Vector256 Log2(Vector256 vector) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 Max(Vector256 left, Vector256 right) @@ -2229,7 +2473,7 @@ public static Vector256 Max(Vector256 left, Vector256 right) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 MaxMagnitude(Vector256 left, Vector256 right) @@ -2247,7 +2491,7 @@ public static Vector256 MaxMagnitude(Vector256 left, Vector256 right } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 MaxMagnitudeNumber(Vector256 left, Vector256 right) @@ -2265,7 +2509,7 @@ public static Vector256 MaxMagnitudeNumber(Vector256 left, Vector256 } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 MaxNative(Vector256 left, Vector256 right) @@ -2283,7 +2527,7 @@ public static Vector256 MaxNative(Vector256 left, Vector256 right) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 MaxNumber(Vector256 left, Vector256 right) @@ -2301,7 +2545,7 @@ public static Vector256 MaxNumber(Vector256 left, Vector256 right) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 Min(Vector256 left, Vector256 right) @@ -2319,7 +2563,7 @@ public static Vector256 Min(Vector256 left, Vector256 right) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 MinMagnitude(Vector256 left, Vector256 right) @@ -2337,7 +2581,7 @@ public static Vector256 MinMagnitude(Vector256 left, Vector256 right } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 MinMagnitudeNumber(Vector256 left, Vector256 right) @@ -2355,7 +2599,7 @@ public static Vector256 MinMagnitudeNumber(Vector256 left, Vector256 } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 MinNative(Vector256 left, Vector256 right) @@ -2373,7 +2617,7 @@ public static Vector256 MinNative(Vector256 left, Vector256 right) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector256 MinNumber(Vector256 left, Vector256 right) @@ -2560,6 +2804,30 @@ public static Vector256 Narrow(Vector256 lower, Vector256 up [Intrinsic] public static Vector256 Negate(Vector256 vector) => -vector; + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool None(Vector256 vector, T value) => !EqualsAny(vector, Create(value)); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool NoneWhereAllBitsSet(Vector256 vector) + { + if (typeof(T) == typeof(float)) + { + return None(vector.AsInt32(), -1); + } + else if (typeof(T) == typeof(double)) + { + return None(vector.AsInt64(), -1); + } + else + { + return None(vector, Scalar.AllBitsSet); + } + } + /// Computes the ones-complement of a vector. /// The type of the elements in the vector. /// The vector whose ones-complement is to be computed. @@ -2720,6 +2988,15 @@ internal static Vector256 Round(Vector256 vector) [CLSCompliant(false)] public static Vector256 ShiftLeft(Vector256 vector, int shiftCount) => vector << shiftCount; + [Intrinsic] + internal static Vector256 ShiftLeft(Vector256 vector, Vector256 shiftCount) + { + return Create( + Vector128.ShiftLeft(vector._lower, shiftCount._lower), + Vector128.ShiftLeft(vector._lower, shiftCount._upper) + ); + } + /// Shifts each element of a vector left by the specified amount. /// The vector whose elements are to be shifted. /// The number of bits by which to shift each element. @@ -2728,6 +3005,15 @@ internal static Vector256 Round(Vector256 vector) [CLSCompliant(false)] public static Vector256 ShiftLeft(Vector256 vector, int shiftCount) => vector << shiftCount; + [Intrinsic] + internal static Vector256 ShiftLeft(Vector256 vector, Vector256 shiftCount) + { + return Create( + Vector128.ShiftLeft(vector._lower, shiftCount._lower), + Vector128.ShiftLeft(vector._lower, shiftCount._upper) + ); + } + /// Shifts (signed) each element of a vector right by the specified amount. /// The vector whose elements are to be shifted. /// The number of bits by which to shift each element. diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256_1.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256_1.cs index b4c2996484f9eb..d9fdbd88f3db9d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256_1.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256_1.cs @@ -460,6 +460,9 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri /// static int ISimdVector, T>.Alignment => Vector256.Alignment; + /// + static int ISimdVector, T>.ElementCount => Vector256.Count; + /// static bool ISimdVector, T>.IsHardwareAccelerated { @@ -475,10 +478,26 @@ static bool ISimdVector, T>.IsHardwareAccelerated [Intrinsic] static Vector256 ISimdVector, T>.Add(Vector256 left, Vector256 right) => left + right; + /// + [Intrinsic] + static bool ISimdVector, T>.All(Vector256 vector, T value) => Vector256.All(vector, value); + + /// + [Intrinsic] + static bool ISimdVector, T>.AllWhereAllBitsSet(Vector256 vector) => Vector256.AllWhereAllBitsSet(vector); + /// [Intrinsic] static Vector256 ISimdVector, T>.AndNot(Vector256 left, Vector256 right) => Vector256.AndNot(left, right); + /// + [Intrinsic] + static bool ISimdVector, T>.Any(Vector256 vector, T value) => Vector256.Any(vector, value); + + /// + [Intrinsic] + static bool ISimdVector, T>.AnyWhereAllBitsSet(Vector256 vector) => Vector256.AnyWhereAllBitsSet(vector); + /// [Intrinsic] static Vector256 ISimdVector, T>.BitwiseAnd(Vector256 left, Vector256 right) => left & right; @@ -516,6 +535,14 @@ static bool ISimdVector, T>.IsHardwareAccelerated /// static void ISimdVector, T>.CopyTo(Vector256 vector, Span destination) => vector.CopyTo(destination); + /// + [Intrinsic] + static int ISimdVector, T>.Count(Vector256 vector, T value) => Vector256.Count(vector, value); + + /// + [Intrinsic] + static int ISimdVector, T>.CountWhereAllBitsSet(Vector256 vector) => Vector256.CountWhereAllBitsSet(vector); + /// [Intrinsic] static Vector256 ISimdVector, T>.Create(T value) => Vector256.Create(value); @@ -593,6 +620,73 @@ static bool ISimdVector, T>.IsHardwareAccelerated [Intrinsic] static bool ISimdVector, T>.GreaterThanOrEqualAny(Vector256 left, Vector256 right) => Vector256.GreaterThanOrEqualAny(left, right); + /// + [Intrinsic] + static int ISimdVector, T>.IndexOf(Vector256 vector, T value) => Vector256.IndexOf(vector, value); + + /// + [Intrinsic] + static int ISimdVector, T>.IndexOfWhereAllBitsSet(Vector256 vector) => Vector256.IndexOfWhereAllBitsSet(vector); + + /// + [Intrinsic] + static Vector256 ISimdVector, T>.IsEvenInteger(Vector256 vector) => Vector256.IsEvenInteger(vector); + + /// + [Intrinsic] + static Vector256 ISimdVector, T>.IsFinite(Vector256 vector) => Vector256.IsFinite(vector); + + /// + [Intrinsic] + static Vector256 ISimdVector, T>.IsInfinity(Vector256 vector) => Vector256.IsInfinity(vector); + + /// + [Intrinsic] + static Vector256 ISimdVector, T>.IsInteger(Vector256 vector) => Vector256.IsInteger(vector); + + /// + [Intrinsic] + static Vector256 ISimdVector, T>.IsNaN(Vector256 vector) => Vector256.IsNaN(vector); + + /// + [Intrinsic] + static Vector256 ISimdVector, T>.IsNegative(Vector256 vector) => Vector256.IsNegative(vector); + + /// + [Intrinsic] + static Vector256 ISimdVector, T>.IsNegativeInfinity(Vector256 vector) => Vector256.IsNegativeInfinity(vector); + + /// + [Intrinsic] + static Vector256 ISimdVector, T>.IsNormal(Vector256 vector) => Vector256.IsNormal(vector); + + /// + [Intrinsic] + static Vector256 ISimdVector, T>.IsOddInteger(Vector256 vector) => Vector256.IsOddInteger(vector); + + /// + [Intrinsic] + static Vector256 ISimdVector, T>.IsPositive(Vector256 vector) => Vector256.IsPositive(vector); + + /// + [Intrinsic] + static Vector256 ISimdVector, T>.IsPositiveInfinity(Vector256 vector) => Vector256.IsPositiveInfinity(vector); + + /// + [Intrinsic] + static Vector256 ISimdVector, T>.IsSubnormal(Vector256 vector) => Vector256.IsSubnormal(vector); + + /// + static Vector256 ISimdVector, T>.IsZero(Vector256 vector) => Vector256.IsZero(vector); + + /// + [Intrinsic] + static int ISimdVector, T>.LastIndexOf(Vector256 vector, T value) => Vector256.LastIndexOf(vector, value); + + /// + [Intrinsic] + static int ISimdVector, T>.LastIndexOfWhereAllBitsSet(Vector256 vector) => Vector256.LastIndexOfWhereAllBitsSet(vector); + /// [Intrinsic] static Vector256 ISimdVector, T>.LessThan(Vector256 left, Vector256 right) => Vector256.LessThan(left, right); @@ -693,6 +787,14 @@ static bool ISimdVector, T>.IsHardwareAccelerated [Intrinsic] static Vector256 ISimdVector, T>.Negate(Vector256 vector) => -vector; + /// + [Intrinsic] + static bool ISimdVector, T>.None(Vector256 vector, T value) => Vector256.None(vector, value); + + /// + [Intrinsic] + static bool ISimdVector, T>.NoneWhereAllBitsSet(Vector256 vector) => Vector256.NoneWhereAllBitsSet(vector); + /// [Intrinsic] static Vector256 ISimdVector, T>.OnesComplement(Vector256 vector) => ~vector; @@ -763,34 +865,5 @@ static bool ISimdVector, T>.IsHardwareAccelerated /// [Intrinsic] static Vector256 ISimdVector, T>.Xor(Vector256 left, Vector256 right) => left ^ right; - - // - // New Surface Area - // - - static bool ISimdVector, T>.AnyWhereAllBitsSet(Vector256 vector) => Vector256.EqualsAny(vector, AllBitsSet); - - static bool ISimdVector, T>.Any(Vector256 vector, T value) => Vector256.EqualsAny(vector, Vector256.Create(value)); - - static int ISimdVector, T>.IndexOfLastMatch(Vector256 vector) - { - uint mask = vector.ExtractMostSignificantBits(); - return 31 - BitOperations.LeadingZeroCount(mask); // 31 = 32 (bits in Int32) - 1 (indexing from zero) - } - - [Intrinsic] - static Vector256 ISimdVector, T>.IsNaN(Vector256 vector) => Vector256.IsNaN(vector); - - [Intrinsic] - static Vector256 ISimdVector, T>.IsNegative(Vector256 vector) => Vector256.IsNegative(vector); - - [Intrinsic] - static Vector256 ISimdVector, T>.IsPositive(Vector256 vector) => Vector256.IsPositive(vector); - - [Intrinsic] - static Vector256 ISimdVector, T>.IsPositiveInfinity(Vector256 vector) => Vector256.IsPositiveInfinity(vector); - - [Intrinsic] - static Vector256 ISimdVector, T>.IsZero(Vector256 vector) => Vector256.IsZero(vector); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs index 2b683f06524f45..6877dae70af508 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs @@ -88,6 +88,30 @@ public static Vector512 Abs(Vector512 vector) [Intrinsic] public static Vector512 Add(Vector512 left, Vector512 right) => left + right; + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool All(Vector512 vector, T value) => vector == Create(value); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool AllWhereAllBitsSet(Vector512 vector) + { + if (typeof(T) == typeof(float)) + { + return All(vector.AsInt32(), -1); + } + else if (typeof(T) == typeof(double)) + { + return All(vector.AsInt64(), -1); + } + else + { + return All(vector, Scalar.AllBitsSet); + } + } + /// Computes the bitwise-and of a given vector and the ones complement of another vector. /// The type of the elements in the vector. /// The vector to bitwise-and with . @@ -98,6 +122,30 @@ public static Vector512 Abs(Vector512 vector) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 AndNot(Vector512 left, Vector512 right) => left & ~right; + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool Any(Vector512 vector, T value) => EqualsAny(vector, Create(value)); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool AnyWhereAllBitsSet(Vector512 vector) + { + if (typeof(T) == typeof(float)) + { + return Any(vector.AsInt32(), -1); + } + else if (typeof(T) == typeof(double)) + { + return Any(vector.AsInt64(), -1); + } + else + { + return Any(vector, Scalar.AllBitsSet); + } + } + /// Reinterprets a as a new . /// The type of the elements in the input vector. /// The type of the elements in the output vector. @@ -313,7 +361,7 @@ internal static Vector512 Ceiling(Vector512 vector) [Intrinsic] public static Vector512 Ceiling(Vector512 vector) => Ceiling(vector); - /// + /// [Intrinsic] public static Vector512 Clamp(Vector512 value, Vector512 min, Vector512 max) { @@ -321,7 +369,7 @@ public static Vector512 Clamp(Vector512 value, Vector512 min, Vector return Min(Max(value, min), max); } - /// + /// [Intrinsic] public static Vector512 ClampNative(Vector512 value, Vector512 min, Vector512 max) { @@ -502,7 +550,7 @@ public static Vector512 ConvertToUInt64Native(Vector512 vector) ); } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 CopySign(Vector512 value, Vector512 sign) @@ -623,6 +671,30 @@ public static Vector512 Cos(Vector512 vector) } } + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Count(Vector512 vector, T value) => BitOperations.PopCount(Equals(vector, Create(value)).ExtractMostSignificantBits()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int CountWhereAllBitsSet(Vector512 vector) + { + if (typeof(T) == typeof(float)) + { + return Count(vector.AsInt32(), -1); + } + else if (typeof(T) == typeof(double)) + { + return Count(vector.AsInt64(), -1); + } + else + { + return Count(vector, Scalar.AllBitsSet); + } + } + /// Creates a new instance with all elements initialized to the specified value. /// The type of the elements in the vector. /// The value that all elements will be initialized to. @@ -1879,7 +1951,91 @@ public static Vector512 Hypot(Vector512 x, Vector512 y) } } - /// + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int IndexOf(Vector512 vector, T value) + { + int result = BitOperations.TrailingZeroCount(Equals(vector, Create(value)).ExtractMostSignificantBits()); + return (result != 64) ? result : -1; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int IndexOfWhereAllBitsSet(Vector512 vector) + { + if (typeof(T) == typeof(float)) + { + return IndexOf(vector.AsInt32(), -1); + } + else if (typeof(T) == typeof(double)) + { + return IndexOf(vector.AsInt64(), -1); + } + else + { + return IndexOf(vector, Scalar.AllBitsSet); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 IsEvenInteger(Vector512 vector) + { + if (typeof(T) == typeof(float)) + { + return VectorMath.IsEvenIntegerSingle, Vector512>(vector.AsSingle()).As(); + } + else if (typeof(T) == typeof(double)) + { + return VectorMath.IsEvenIntegerDouble, Vector512>(vector.AsDouble()).As(); + } + return IsZero(vector & Vector512.One); + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 IsFinite(Vector512 vector) + { + if (typeof(T) == typeof(float)) + { + return ~IsZero(AndNot(Create(float.PositiveInfinityBits), vector.AsUInt32())).As(); + } + else if (typeof(T) == typeof(double)) + { + return ~IsZero(AndNot(Create(double.PositiveInfinityBits), vector.AsUInt64())).As(); + } + return Vector512.AllBitsSet; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 IsInfinity(Vector512 vector) + { + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) + { + return IsPositiveInfinity(Abs(vector)); + } + return Vector512.Zero; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 IsInteger(Vector512 vector) + { + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) + { + return IsFinite(vector) & Equals(vector, Truncate(vector)); + } + return Vector512.AllBitsSet; + } + + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 IsNaN(Vector512 vector) @@ -1891,7 +2047,7 @@ public static Vector512 IsNaN(Vector512 vector) return Vector512.Zero; } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 IsNegative(Vector512 vector) @@ -1918,7 +2074,55 @@ public static Vector512 IsNegative(Vector512 vector) } } - /// + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 IsNegativeInfinity(Vector512 vector) + { + if (typeof(T) == typeof(float)) + { + return Equals(vector, Create(float.NegativeInfinity).As()); + } + else if (typeof(T) == typeof(double)) + { + return Equals(vector, Create(double.NegativeInfinity).As()); + } + return Vector512.Zero; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 IsNormal(Vector512 vector) + { + if (typeof(T) == typeof(float)) + { + return LessThan(Abs(vector).AsUInt32() - Create(float.SmallestNormalBits), Create(float.PositiveInfinityBits - float.SmallestNormalBits)).As(); + } + else if (typeof(T) == typeof(double)) + { + return LessThan(Abs(vector).AsUInt64() - Create(double.SmallestNormalBits), Create(double.PositiveInfinityBits - double.SmallestNormalBits)).As(); + } + return ~IsZero(vector); + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 IsOddInteger(Vector512 vector) + { + if (typeof(T) == typeof(float)) + { + return VectorMath.IsOddIntegerSingle, Vector512>(vector.AsSingle()).As(); + } + else if (typeof(T) == typeof(double)) + { + return VectorMath.IsOddIntegerDouble, Vector512>(vector.AsDouble()).As(); + } + return ~IsZero(vector & Vector512.One); + } + + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 IsPositive(Vector512 vector) @@ -1945,7 +2149,7 @@ public static Vector512 IsPositive(Vector512 vector) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 IsPositiveInfinity(Vector512 vector) @@ -1961,11 +2165,51 @@ public static Vector512 IsPositiveInfinity(Vector512 vector) return Vector512.Zero; } - /// + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector512 IsSubnormal(Vector512 vector) + { + if (typeof(T) == typeof(float)) + { + return LessThan(Abs(vector).AsUInt32() - Vector512.One, Create(float.MaxTrailingSignificand)).As(); + } + else if (typeof(T) == typeof(double)) + { + return LessThan(Abs(vector).AsUInt64() - Vector512.One, Create(double.MaxTrailingSignificand)).As(); + } + return Vector512.Zero; + } + + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 IsZero(Vector512 vector) => Equals(vector, Vector512.Zero); + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int LastIndexOf(Vector512 vector, T value) => 63 - BitOperations.LeadingZeroCount(Equals(vector, Create(value)).ExtractMostSignificantBits()); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int LastIndexOfWhereAllBitsSet(Vector512 vector) + { + if (typeof(T) == typeof(float)) + { + return LastIndexOf(vector.AsInt32(), -1); + } + else if (typeof(T) == typeof(double)) + { + return LastIndexOf(vector.AsInt64(), -1); + } + else + { + return LastIndexOf(vector, Scalar.AllBitsSet); + } + } + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -2238,7 +2482,7 @@ public static Vector512 Log2(Vector512 vector) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 Max(Vector512 left, Vector512 right) @@ -2256,7 +2500,7 @@ public static Vector512 Max(Vector512 left, Vector512 right) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 MaxMagnitude(Vector512 left, Vector512 right) @@ -2274,7 +2518,7 @@ public static Vector512 MaxMagnitude(Vector512 left, Vector512 right } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 MaxMagnitudeNumber(Vector512 left, Vector512 right) @@ -2292,7 +2536,7 @@ public static Vector512 MaxMagnitudeNumber(Vector512 left, Vector512 } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 MaxNative(Vector512 left, Vector512 right) @@ -2310,7 +2554,7 @@ public static Vector512 MaxNative(Vector512 left, Vector512 right) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 MaxNumber(Vector512 left, Vector512 right) @@ -2328,7 +2572,7 @@ public static Vector512 MaxNumber(Vector512 left, Vector512 right) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 Min(Vector512 left, Vector512 right) @@ -2346,7 +2590,7 @@ public static Vector512 Min(Vector512 left, Vector512 right) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 MinMagnitude(Vector512 left, Vector512 right) @@ -2364,7 +2608,7 @@ public static Vector512 MinMagnitude(Vector512 left, Vector512 right } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 MinMagnitudeNumber(Vector512 left, Vector512 right) @@ -2382,7 +2626,7 @@ public static Vector512 MinMagnitudeNumber(Vector512 left, Vector512 } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 MinNative(Vector512 left, Vector512 right) @@ -2400,7 +2644,7 @@ public static Vector512 MinNative(Vector512 left, Vector512 right) } } - /// + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector512 MinNumber(Vector512 left, Vector512 right) @@ -2586,6 +2830,30 @@ public static Vector512 Narrow(Vector512 lower, Vector512 up [Intrinsic] public static Vector512 Negate(Vector512 vector) => -vector; + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool None(Vector512 vector, T value) => !EqualsAny(vector, Create(value)); + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool NoneWhereAllBitsSet(Vector512 vector) + { + if (typeof(T) == typeof(float)) + { + return None(vector.AsInt32(), -1); + } + else if (typeof(T) == typeof(double)) + { + return None(vector.AsInt64(), -1); + } + else + { + return None(vector, Scalar.AllBitsSet); + } + } + /// Computes the ones-complement of a vector. /// The type of the elements in the vector. /// The vector whose ones-complement is to be computed. @@ -2746,6 +3014,15 @@ internal static Vector512 Round(Vector512 vector) [CLSCompliant(false)] public static Vector512 ShiftLeft(Vector512 vector, int shiftCount) => vector << shiftCount; + [Intrinsic] + internal static Vector512 ShiftLeft(Vector512 vector, Vector512 shiftCount) + { + return Create( + Vector256.ShiftLeft(vector._lower, shiftCount._lower), + Vector256.ShiftLeft(vector._lower, shiftCount._upper) + ); + } + /// Shifts each element of a vector left by the specified amount. /// The vector whose elements are to be shifted. /// The number of bits by which to shift each element. @@ -2754,6 +3031,15 @@ internal static Vector512 Round(Vector512 vector) [CLSCompliant(false)] public static Vector512 ShiftLeft(Vector512 vector, int shiftCount) => vector << shiftCount; + [Intrinsic] + internal static Vector512 ShiftLeft(Vector512 vector, Vector512 shiftCount) + { + return Create( + Vector256.ShiftLeft(vector._lower, shiftCount._lower), + Vector256.ShiftLeft(vector._lower, shiftCount._upper) + ); + } + /// Shifts (signed) each element of a vector right by the specified amount. /// The vector whose elements are to be shifted. /// The number of bits by which to shift each element. diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512_1.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512_1.cs index 2105c18257a195..b1c40fcfa72c1b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512_1.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512_1.cs @@ -460,6 +460,9 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri /// static int ISimdVector, T>.Alignment => Vector512.Alignment; + /// + static int ISimdVector, T>.ElementCount => Vector512.Count; + /// static bool ISimdVector, T>.IsHardwareAccelerated { @@ -475,10 +478,26 @@ static bool ISimdVector, T>.IsHardwareAccelerated [Intrinsic] static Vector512 ISimdVector, T>.Add(Vector512 left, Vector512 right) => left + right; + /// + [Intrinsic] + static bool ISimdVector, T>.All(Vector512 vector, T value) => Vector512.All(vector, value); + + /// + [Intrinsic] + static bool ISimdVector, T>.AllWhereAllBitsSet(Vector512 vector) => Vector512.AllWhereAllBitsSet(vector); + /// [Intrinsic] static Vector512 ISimdVector, T>.AndNot(Vector512 left, Vector512 right) => Vector512.AndNot(left, right); + /// + [Intrinsic] + static bool ISimdVector, T>.Any(Vector512 vector, T value) => Vector512.Any(vector, value); + + /// + [Intrinsic] + static bool ISimdVector, T>.AnyWhereAllBitsSet(Vector512 vector) => Vector512.AnyWhereAllBitsSet(vector); + /// [Intrinsic] static Vector512 ISimdVector, T>.BitwiseAnd(Vector512 left, Vector512 right) => left & right; @@ -516,6 +535,14 @@ static bool ISimdVector, T>.IsHardwareAccelerated /// static void ISimdVector, T>.CopyTo(Vector512 vector, Span destination) => vector.CopyTo(destination); + /// + [Intrinsic] + static int ISimdVector, T>.Count(Vector512 vector, T value) => Vector512.Count(vector, value); + + /// + [Intrinsic] + static int ISimdVector, T>.CountWhereAllBitsSet(Vector512 vector) => Vector512.CountWhereAllBitsSet(vector); + /// [Intrinsic] static Vector512 ISimdVector, T>.Create(T value) => Vector512.Create(value); @@ -593,6 +620,73 @@ static bool ISimdVector, T>.IsHardwareAccelerated [Intrinsic] static bool ISimdVector, T>.GreaterThanOrEqualAny(Vector512 left, Vector512 right) => Vector512.GreaterThanOrEqualAny(left, right); + /// + [Intrinsic] + static int ISimdVector, T>.IndexOf(Vector512 vector, T value) => Vector512.IndexOf(vector, value); + + /// + [Intrinsic] + static int ISimdVector, T>.IndexOfWhereAllBitsSet(Vector512 vector) => Vector512.IndexOfWhereAllBitsSet(vector); + + /// + [Intrinsic] + static Vector512 ISimdVector, T>.IsEvenInteger(Vector512 vector) => Vector512.IsEvenInteger(vector); + + /// + [Intrinsic] + static Vector512 ISimdVector, T>.IsFinite(Vector512 vector) => Vector512.IsFinite(vector); + + /// + [Intrinsic] + static Vector512 ISimdVector, T>.IsInfinity(Vector512 vector) => Vector512.IsInfinity(vector); + + /// + [Intrinsic] + static Vector512 ISimdVector, T>.IsInteger(Vector512 vector) => Vector512.IsInteger(vector); + + /// + [Intrinsic] + static Vector512 ISimdVector, T>.IsNaN(Vector512 vector) => Vector512.IsNaN(vector); + + /// + [Intrinsic] + static Vector512 ISimdVector, T>.IsNegative(Vector512 vector) => Vector512.IsNegative(vector); + + /// + [Intrinsic] + static Vector512 ISimdVector, T>.IsNegativeInfinity(Vector512 vector) => Vector512.IsNegativeInfinity(vector); + + /// + [Intrinsic] + static Vector512 ISimdVector, T>.IsNormal(Vector512 vector) => Vector512.IsNormal(vector); + + /// + [Intrinsic] + static Vector512 ISimdVector, T>.IsOddInteger(Vector512 vector) => Vector512.IsOddInteger(vector); + + /// + [Intrinsic] + static Vector512 ISimdVector, T>.IsPositive(Vector512 vector) => Vector512.IsPositive(vector); + + /// + [Intrinsic] + static Vector512 ISimdVector, T>.IsPositiveInfinity(Vector512 vector) => Vector512.IsPositiveInfinity(vector); + + /// + [Intrinsic] + static Vector512 ISimdVector, T>.IsSubnormal(Vector512 vector) => Vector512.IsSubnormal(vector); + + /// + static Vector512 ISimdVector, T>.IsZero(Vector512 vector) => Vector512.IsZero(vector); + + /// + [Intrinsic] + static int ISimdVector, T>.LastIndexOf(Vector512 vector, T value) => Vector512.LastIndexOf(vector, value); + + /// + [Intrinsic] + static int ISimdVector, T>.LastIndexOfWhereAllBitsSet(Vector512 vector) => Vector512.LastIndexOfWhereAllBitsSet(vector); + /// [Intrinsic] static Vector512 ISimdVector, T>.LessThan(Vector512 left, Vector512 right) => Vector512.LessThan(left, right); @@ -693,6 +787,14 @@ static bool ISimdVector, T>.IsHardwareAccelerated [Intrinsic] static Vector512 ISimdVector, T>.Negate(Vector512 vector) => -vector; + /// + [Intrinsic] + static bool ISimdVector, T>.None(Vector512 vector, T value) => Vector512.None(vector, value); + + /// + [Intrinsic] + static bool ISimdVector, T>.NoneWhereAllBitsSet(Vector512 vector) => Vector512.NoneWhereAllBitsSet(vector); + /// [Intrinsic] static Vector512 ISimdVector, T>.OnesComplement(Vector512 vector) => ~vector; @@ -763,34 +865,5 @@ static bool ISimdVector, T>.IsHardwareAccelerated /// [Intrinsic] static Vector512 ISimdVector, T>.Xor(Vector512 left, Vector512 right) => left ^ right; - - // - // New Surface Area - // - - static bool ISimdVector, T>.AnyWhereAllBitsSet(Vector512 vector) => Vector512.EqualsAny(vector, AllBitsSet); - - static bool ISimdVector, T>.Any(Vector512 vector, T value) => Vector512.EqualsAny(vector, Vector512.Create(value)); - - static int ISimdVector, T>.IndexOfLastMatch(Vector512 vector) - { - ulong mask = vector.ExtractMostSignificantBits(); - return 63 - BitOperations.LeadingZeroCount(mask); // 63 = 64 (bits in Int64) - 1 (indexing from zero) - } - - [Intrinsic] - static Vector512 ISimdVector, T>.IsNaN(Vector512 vector) => Vector512.IsNaN(vector); - - [Intrinsic] - static Vector512 ISimdVector, T>.IsNegative(Vector512 vector) => Vector512.IsNegative(vector); - - [Intrinsic] - static Vector512 ISimdVector, T>.IsPositive(Vector512 vector) => Vector512.IsPositive(vector); - - [Intrinsic] - static Vector512 ISimdVector, T>.IsPositiveInfinity(Vector512 vector) => Vector512.IsPositiveInfinity(vector); - - [Intrinsic] - static Vector512 ISimdVector, T>.IsZero(Vector512 vector) => Vector512.IsZero(vector); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs index 570933c7abbba2..4ddbe5eb4831b6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64.cs @@ -67,6 +67,39 @@ public static Vector64 Abs(Vector64 vector) [Intrinsic] public static Vector64 Add(Vector64 left, Vector64 right) => left + right; + /// Determines if all elements of a vector are equal to a given value. + /// The type of the elements in the vector. + /// The vector whose elements are being checked. + /// The value to check for in + /// true if all elements of are equal to ; otherwise, false. + /// The type of and () is not supported. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool All(Vector64 vector, T value) => vector == Create(value); + + /// Determines if all elements of a vector have all their bits set. + /// The type of the elements in the vector. + /// The vector whose elements are being checked. + /// true if all elements of have all their bits set; otherwise, false. + /// The type of () is not supported. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool AllWhereAllBitsSet(Vector64 vector) + { + if (typeof(T) == typeof(float)) + { + return All(vector.AsInt32(), -1); + } + else if (typeof(T) == typeof(double)) + { + return All(vector.AsInt64(), -1); + } + else + { + return All(vector, Scalar.AllBitsSet); + } + } + /// Computes the bitwise-and of a given vector and the ones complement of another vector. /// The type of the elements in the vector. /// The vector to bitwise-and with . @@ -76,6 +109,39 @@ public static Vector64 Abs(Vector64 vector) [Intrinsic] public static Vector64 AndNot(Vector64 left, Vector64 right) => left & ~right; + /// Determines if any elements of a vector are equal to a given value. + /// The type of the elements in the vector. + /// The vector whose elements are being checked. + /// The value to check for in + /// true if any elements of are equal to ; otherwise, false. + /// The type of and () is not supported. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool Any(Vector64 vector, T value) => EqualsAny(vector, Create(value)); + + /// Determines if any elements of a vector have all their bits set. + /// The type of the elements in the vector. + /// The vector whose elements are being checked. + /// true if any elements of have all their bits set; otherwise, false. + /// The type of () is not supported. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool AnyWhereAllBitsSet(Vector64 vector) + { + if (typeof(T) == typeof(float)) + { + return Any(vector.AsInt32(), -1); + } + else if (typeof(T) == typeof(double)) + { + return Any(vector.AsInt64(), -1); + } + else + { + return Any(vector, Scalar.AllBitsSet); + } + } + /// Reinterprets a as a new . /// The type of the elements in the input vector. /// The type of the elements in the output vector. @@ -660,6 +726,39 @@ public static Vector64 Cos(Vector64 vector) } } + /// Determines the number of elements in a vector that are equal to a given value. + /// The type of the elements in the vector. + /// The vector whose elements are being checked. + /// The value to check for in + /// The number of elements in that are equal to . + /// The type of and () is not supported. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Count(Vector64 vector, T value) => BitOperations.PopCount(Equals(vector, Create(value)).ExtractMostSignificantBits()); + + /// Determines the number of elements in a vector that have all their bits set. + /// The type of the elements in the vector. + /// The vector whose elements are being checked. + /// The number of elements in that have all their bits set. + /// The type of () is not supported. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int CountWhereAllBitsSet(Vector64 vector) + { + if (typeof(T) == typeof(float)) + { + return Count(vector.AsInt32(), -1); + } + else if (typeof(T) == typeof(double)) + { + return Count(vector.AsInt64(), -1); + } + else + { + return Count(vector, Scalar.AllBitsSet); + } + } + /// Creates a new instance with all elements initialized to the specified value. /// The type of the elements in the vector. /// The value that all elements will be initialized to. @@ -1649,6 +1748,99 @@ public static Vector64 Hypot(Vector64 x, Vector64 y) } } + /// Determines the index of the first element in a vector that is equal to a given value. + /// The type of the elements in the vector. + /// The vector whose elements are being checked. + /// The value to check for in + /// The index into representing the first element that was equal to ; otherwise, -1 if no such element exists. + /// The type of and () is not supported. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int IndexOf(Vector64 vector, T value) + { + int result = BitOperations.TrailingZeroCount(Equals(vector, Create(value)).ExtractMostSignificantBits()); + return (result != 32) ? result : -1; + } + + /// Determines the index of the first element in a vector that has all bits set. + /// The type of the elements in the vector. + /// The vector whose elements are being checked. + /// The index into representing the first element that had all bits set; otherwise, -1 if no such element exists. + /// The type of () is not supported. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int IndexOfWhereAllBitsSet(Vector64 vector) + { + if (typeof(T) == typeof(float)) + { + return IndexOf(vector.AsInt32(), -1); + } + else if (typeof(T) == typeof(double)) + { + return IndexOf(vector.AsInt64(), -1); + } + else + { + return IndexOf(vector, Scalar.AllBitsSet); + } + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 IsEvenInteger(Vector64 vector) + { + if (typeof(T) == typeof(float)) + { + return VectorMath.IsEvenIntegerSingle, Vector64>(vector.AsSingle()).As(); + } + else if (typeof(T) == typeof(double)) + { + return VectorMath.IsEvenIntegerDouble, Vector64>(vector.AsDouble()).As(); + } + return IsZero(vector & Vector64.One); + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 IsFinite(Vector64 vector) + { + if (typeof(T) == typeof(float)) + { + return ~IsZero(AndNot(Create(float.PositiveInfinityBits), vector.AsUInt32())).As(); + } + else if (typeof(T) == typeof(double)) + { + return ~IsZero(AndNot(Create(double.PositiveInfinityBits), vector.AsUInt64())).As(); + } + return Vector64.AllBitsSet; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 IsInfinity(Vector64 vector) + { + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) + { + return IsPositiveInfinity(Abs(vector)); + } + return Vector64.Zero; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 IsInteger(Vector64 vector) + { + if ((typeof(T) == typeof(float)) || (typeof(T) == typeof(double))) + { + return IsFinite(vector) & Equals(vector, Truncate(vector)); + } + return Vector64.AllBitsSet; + } + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1688,6 +1880,54 @@ public static Vector64 IsNegative(Vector64 vector) } } + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 IsNegativeInfinity(Vector64 vector) + { + if (typeof(T) == typeof(float)) + { + return Equals(vector, Create(float.NegativeInfinity).As()); + } + else if (typeof(T) == typeof(double)) + { + return Equals(vector, Create(double.NegativeInfinity).As()); + } + return Vector64.Zero; + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 IsNormal(Vector64 vector) + { + if (typeof(T) == typeof(float)) + { + return LessThan(Abs(vector).AsUInt32() - Create(float.SmallestNormalBits), Create(float.PositiveInfinityBits - float.SmallestNormalBits)).As(); + } + else if (typeof(T) == typeof(double)) + { + return LessThan(Abs(vector).AsUInt64() - Create(double.SmallestNormalBits), Create(double.PositiveInfinityBits - double.SmallestNormalBits)).As(); + } + return ~IsZero(vector); + } + + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 IsOddInteger(Vector64 vector) + { + if (typeof(T) == typeof(float)) + { + return VectorMath.IsOddIntegerSingle, Vector64>(vector.AsSingle()).As(); + } + else if (typeof(T) == typeof(double)) + { + return VectorMath.IsOddIntegerDouble, Vector64>(vector.AsDouble()).As(); + } + return ~IsZero(vector & Vector64.One); + } + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1731,11 +1971,60 @@ public static Vector64 IsPositiveInfinity(Vector64 vector) return Vector64.Zero; } + /// + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector64 IsSubnormal(Vector64 vector) + { + if (typeof(T) == typeof(float)) + { + return LessThan(Abs(vector).AsUInt32() - Vector64.One, Create(float.MaxTrailingSignificand)).As(); + } + else if (typeof(T) == typeof(double)) + { + return LessThan(Abs(vector).AsUInt64() - Vector64.One, Create(double.MaxTrailingSignificand)).As(); + } + return Vector64.Zero; + } + /// [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector64 IsZero(Vector64 vector) => Equals(vector, Vector64.Zero); + /// Determines the index of the last element in a vector that is equal to a given value. + /// The type of the elements in the vector. + /// The vector whose elements are being checked. + /// The value to check for in + /// The index into representing the last element that was equal to ; otherwise, -1 if no such element exists. + /// The type of and () is not supported. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int LastIndexOf(Vector64 vector, T value) => 31 - BitOperations.LeadingZeroCount(Equals(vector, Create(value)).ExtractMostSignificantBits()); + + /// Determines the index of the last element in a vector that has all bits set. + /// The type of the elements in the vector. + /// The vector whose elements are being checked. + /// The index into representing the last element that had all bits set; otherwise, -1 if no such element exists. + /// The type of () is not supported. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int LastIndexOfWhereAllBitsSet(Vector64 vector) + { + if (typeof(T) == typeof(float)) + { + return LastIndexOf(vector.AsInt32(), -1); + } + else if (typeof(T) == typeof(double)) + { + return LastIndexOf(vector.AsInt64(), -1); + } + else + { + return LastIndexOf(vector, Scalar.AllBitsSet); + } + } + internal static Vector64 Lerp(Vector64 x, Vector64 y, Vector64 amount) where T : IFloatingPointIeee754 { @@ -2582,6 +2871,39 @@ public static unsafe Vector64 Narrow(Vector64 lower, Vector64 Negate(Vector64 vector) => -vector; + /// Determines if no elements of a vector are equal to a given value. + /// The type of the elements in the vector. + /// The vector whose elements are being checked. + /// The value to check for in + /// true if no elements of are equal to ; otherwise, false. + /// The type of and () is not supported. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool None(Vector64 vector, T value) => !EqualsAny(vector, Create(value)); + + /// Determines if no elements of a vector have all their bits set. + /// The type of the elements in the vector. + /// The vector whose elements are being checked. + /// true if no elements of have all their bits set; otherwise, false. + /// The type of () is not supported. + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool NoneWhereAllBitsSet(Vector64 vector) + { + if (typeof(T) == typeof(float)) + { + return None(vector.AsInt32(), -1); + } + else if (typeof(T) == typeof(double)) + { + return None(vector.AsInt64(), -1); + } + else + { + return None(vector, Scalar.AllBitsSet); + } + } + /// Computes the ones-complement of a vector. /// The type of the elements in the vector. /// The vector whose ones-complement is to be computed. @@ -2765,6 +3087,20 @@ internal static Vector64 Round(Vector64 vector) [CLSCompliant(false)] public static Vector64 ShiftLeft(Vector64 vector, int shiftCount) => vector << shiftCount; + [Intrinsic] + internal static Vector64 ShiftLeft(Vector64 vector, Vector64 shiftCount) + { + Unsafe.SkipInit(out Vector64 result); + + for (int index = 0; index < Vector64.Count; index++) + { + uint element = vector.GetElementUnsafe(index) << (int)shiftCount.GetElementUnsafe(index); + result.SetElementUnsafe(index, element); + } + + return result; + } + /// Shifts each element of a vector left by the specified amount. /// The vector whose elements are to be shifted. /// The number of bits by which to shift each element. @@ -2773,6 +3109,20 @@ internal static Vector64 Round(Vector64 vector) [CLSCompliant(false)] public static Vector64 ShiftLeft(Vector64 vector, int shiftCount) => vector << shiftCount; + [Intrinsic] + internal static Vector64 ShiftLeft(Vector64 vector, Vector64 shiftCount) + { + Unsafe.SkipInit(out Vector64 result); + + for (int index = 0; index < Vector64.Count; index++) + { + ulong element = vector.GetElementUnsafe(index) << (int)shiftCount.GetElementUnsafe(index); + result.SetElementUnsafe(index, element); + } + + return result; + } + /// Shifts (signed) each element of a vector right by the specified amount. /// The vector whose elements are to be shifted. /// The number of bits by which to shift each element. diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs index 9ced0d4f2950fd..e3e4d8c1f55344 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs @@ -528,37 +528,70 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri /// static int ISimdVector, T>.Alignment => Vector64.Alignment; + /// + static int ISimdVector, T>.ElementCount => Vector64.Count; + /// - static bool ISimdVector, T>.IsHardwareAccelerated => Vector64.IsHardwareAccelerated; + static bool ISimdVector, T>.IsHardwareAccelerated + { + [Intrinsic] + get => Vector64.IsHardwareAccelerated; + } /// + [Intrinsic] static Vector64 ISimdVector, T>.Abs(Vector64 vector) => Vector64.Abs(vector); /// + [Intrinsic] static Vector64 ISimdVector, T>.Add(Vector64 left, Vector64 right) => left + right; + /// + [Intrinsic] + static bool ISimdVector, T>.All(Vector64 vector, T value) => Vector64.All(vector, value); + + /// + [Intrinsic] + static bool ISimdVector, T>.AllWhereAllBitsSet(Vector64 vector) => Vector64.AllWhereAllBitsSet(vector); + /// + [Intrinsic] static Vector64 ISimdVector, T>.AndNot(Vector64 left, Vector64 right) => Vector64.AndNot(left, right); + /// + [Intrinsic] + static bool ISimdVector, T>.Any(Vector64 vector, T value) => Vector64.Any(vector, value); + + /// + [Intrinsic] + static bool ISimdVector, T>.AnyWhereAllBitsSet(Vector64 vector) => Vector64.AnyWhereAllBitsSet(vector); + /// + [Intrinsic] static Vector64 ISimdVector, T>.BitwiseAnd(Vector64 left, Vector64 right) => left & right; /// + [Intrinsic] static Vector64 ISimdVector, T>.BitwiseOr(Vector64 left, Vector64 right) => left | right; /// + [Intrinsic] static Vector64 ISimdVector, T>.Ceiling(Vector64 vector) => Vector64.Ceiling(vector); /// + [Intrinsic] static Vector64 ISimdVector, T>.Clamp(Vector64 value, Vector64 min, Vector64 max) => Vector64.Clamp(value, min, max); /// + [Intrinsic] static Vector64 ISimdVector, T>.ClampNative(Vector64 value, Vector64 min, Vector64 max) => Vector64.ClampNative(value, min, max); /// + [Intrinsic] static Vector64 ISimdVector, T>.ConditionalSelect(Vector64 condition, Vector64 left, Vector64 right) => Vector64.ConditionalSelect(condition, left, right); /// + [Intrinsic] static Vector64 ISimdVector, T>.CopySign(Vector64 value, Vector64 sign) => Vector64.CopySign(value, sign); /// @@ -570,7 +603,16 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri /// static void ISimdVector, T>.CopyTo(Vector64 vector, Span destination) => vector.CopyTo(destination); + /// + [Intrinsic] + static int ISimdVector, T>.Count(Vector64 vector, T value) => Vector64.Count(vector, value); + + /// + [Intrinsic] + static int ISimdVector, T>.CountWhereAllBitsSet(Vector64 vector) => Vector64.CountWhereAllBitsSet(vector); + /// + [Intrinsic] static Vector64 ISimdVector, T>.Create(T value) => Vector64.Create(value); /// @@ -583,204 +625,314 @@ private string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] stri static Vector64 ISimdVector, T>.Create(ReadOnlySpan values) => Vector64.Create(values); /// + [Intrinsic] static Vector64 ISimdVector, T>.CreateScalar(T value) => Vector64.CreateScalar(value); /// + [Intrinsic] static Vector64 ISimdVector, T>.CreateScalarUnsafe(T value) => Vector64.CreateScalarUnsafe(value); /// + [Intrinsic] static Vector64 ISimdVector, T>.Divide(Vector64 left, Vector64 right) => left / right; /// + [Intrinsic] static Vector64 ISimdVector, T>.Divide(Vector64 left, T right) => left / right; /// + [Intrinsic] static T ISimdVector, T>.Dot(Vector64 left, Vector64 right) => Vector64.Dot(left, right); /// + [Intrinsic] static Vector64 ISimdVector, T>.Equals(Vector64 left, Vector64 right) => Vector64.Equals(left, right); /// + [Intrinsic] static bool ISimdVector, T>.EqualsAll(Vector64 left, Vector64 right) => left == right; /// + [Intrinsic] static bool ISimdVector, T>.EqualsAny(Vector64 left, Vector64 right) => Vector64.EqualsAny(left, right); /// + [Intrinsic] static Vector64 ISimdVector, T>.Floor(Vector64 vector) => Vector64.Floor(vector); /// + [Intrinsic] static T ISimdVector, T>.GetElement(Vector64 vector, int index) => vector.GetElement(index); /// + [Intrinsic] static Vector64 ISimdVector, T>.GreaterThan(Vector64 left, Vector64 right) => Vector64.GreaterThan(left, right); /// + [Intrinsic] static bool ISimdVector, T>.GreaterThanAll(Vector64 left, Vector64 right) => Vector64.GreaterThanAll(left, right); /// + [Intrinsic] static bool ISimdVector, T>.GreaterThanAny(Vector64 left, Vector64 right) => Vector64.GreaterThanAny(left, right); /// + [Intrinsic] static Vector64 ISimdVector, T>.GreaterThanOrEqual(Vector64 left, Vector64 right) => Vector64.GreaterThanOrEqual(left, right); /// + [Intrinsic] static bool ISimdVector, T>.GreaterThanOrEqualAll(Vector64 left, Vector64 right) => Vector64.GreaterThanOrEqualAll(left, right); /// + [Intrinsic] static bool ISimdVector, T>.GreaterThanOrEqualAny(Vector64 left, Vector64 right) => Vector64.GreaterThanOrEqualAny(left, right); + /// + [Intrinsic] + static int ISimdVector, T>.IndexOf(Vector64 vector, T value) => Vector64.IndexOf(vector, value); + + /// + [Intrinsic] + static int ISimdVector, T>.IndexOfWhereAllBitsSet(Vector64 vector) => Vector64.IndexOfWhereAllBitsSet(vector); + + /// + [Intrinsic] + static Vector64 ISimdVector, T>.IsEvenInteger(Vector64 vector) => Vector64.IsEvenInteger(vector); + + /// + [Intrinsic] + static Vector64 ISimdVector, T>.IsFinite(Vector64 vector) => Vector64.IsFinite(vector); + + /// + [Intrinsic] + static Vector64 ISimdVector, T>.IsInfinity(Vector64 vector) => Vector64.IsInfinity(vector); + + /// + [Intrinsic] + static Vector64 ISimdVector, T>.IsInteger(Vector64 vector) => Vector64.IsInteger(vector); + + /// + [Intrinsic] + static Vector64 ISimdVector, T>.IsNaN(Vector64 vector) => Vector64.IsNaN(vector); + + /// + [Intrinsic] + static Vector64 ISimdVector, T>.IsNegative(Vector64 vector) => Vector64.IsNegative(vector); + + /// + [Intrinsic] + static Vector64 ISimdVector, T>.IsNegativeInfinity(Vector64 vector) => Vector64.IsNegativeInfinity(vector); + + /// + [Intrinsic] + static Vector64 ISimdVector, T>.IsNormal(Vector64 vector) => Vector64.IsNormal(vector); + + /// + [Intrinsic] + static Vector64 ISimdVector, T>.IsOddInteger(Vector64 vector) => Vector64.IsOddInteger(vector); + + /// + [Intrinsic] + static Vector64 ISimdVector, T>.IsPositive(Vector64 vector) => Vector64.IsPositive(vector); + + /// + [Intrinsic] + static Vector64 ISimdVector, T>.IsPositiveInfinity(Vector64 vector) => Vector64.IsPositiveInfinity(vector); + + /// + [Intrinsic] + static Vector64 ISimdVector, T>.IsSubnormal(Vector64 vector) => Vector64.IsSubnormal(vector); + + /// + [Intrinsic] + static Vector64 ISimdVector, T>.IsZero(Vector64 vector) => Vector64.IsZero(vector); + + /// + [Intrinsic] + static int ISimdVector, T>.LastIndexOf(Vector64 vector, T value) => Vector64.LastIndexOf(vector, value); + + /// + [Intrinsic] + static int ISimdVector, T>.LastIndexOfWhereAllBitsSet(Vector64 vector) => Vector64.LastIndexOfWhereAllBitsSet(vector); + /// + [Intrinsic] static Vector64 ISimdVector, T>.LessThan(Vector64 left, Vector64 right) => Vector64.LessThan(left, right); /// + [Intrinsic] static bool ISimdVector, T>.LessThanAll(Vector64 left, Vector64 right) => Vector64.LessThanAll(left, right); /// + [Intrinsic] static bool ISimdVector, T>.LessThanAny(Vector64 left, Vector64 right) => Vector64.LessThanAny(left, right); /// + [Intrinsic] static Vector64 ISimdVector, T>.LessThanOrEqual(Vector64 left, Vector64 right) => Vector64.LessThanOrEqual(left, right); /// + [Intrinsic] static bool ISimdVector, T>.LessThanOrEqualAll(Vector64 left, Vector64 right) => Vector64.LessThanOrEqualAll(left, right); /// + [Intrinsic] static bool ISimdVector, T>.LessThanOrEqualAny(Vector64 left, Vector64 right) => Vector64.LessThanOrEqualAny(left, right); /// + [Intrinsic] static Vector64 ISimdVector, T>.Load(T* source) => Vector64.Load(source); /// + [Intrinsic] static Vector64 ISimdVector, T>.LoadAligned(T* source) => Vector64.LoadAligned(source); /// + [Intrinsic] static Vector64 ISimdVector, T>.LoadAlignedNonTemporal(T* source) => Vector64.LoadAlignedNonTemporal(source); /// + [Intrinsic] static Vector64 ISimdVector, T>.LoadUnsafe(ref readonly T source) => Vector64.LoadUnsafe(in source); /// + [Intrinsic] static Vector64 ISimdVector, T>.LoadUnsafe(ref readonly T source, nuint elementOffset) => Vector64.LoadUnsafe(in source, elementOffset); /// + [Intrinsic] static Vector64 ISimdVector, T>.Max(Vector64 left, Vector64 right) => Vector64.Max(left, right); /// + [Intrinsic] static Vector64 ISimdVector, T>.MaxMagnitude(Vector64 left, Vector64 right) => Vector64.MaxMagnitude(left, right); /// + [Intrinsic] static Vector64 ISimdVector, T>.MaxMagnitudeNumber(Vector64 left, Vector64 right) => Vector64.MaxMagnitudeNumber(left, right); /// + [Intrinsic] static Vector64 ISimdVector, T>.MaxNative(Vector64 left, Vector64 right) => Vector64.MaxNative(left, right); /// + [Intrinsic] static Vector64 ISimdVector, T>.MaxNumber(Vector64 left, Vector64 right) => Vector64.MaxNumber(left, right); /// + [Intrinsic] static Vector64 ISimdVector, T>.Min(Vector64 left, Vector64 right) => Vector64.Min(left, right); /// + [Intrinsic] static Vector64 ISimdVector, T>.MinMagnitude(Vector64 left, Vector64 right) => Vector64.MinMagnitude(left, right); /// + [Intrinsic] static Vector64 ISimdVector, T>.MinMagnitudeNumber(Vector64 left, Vector64 right) => Vector64.MinMagnitudeNumber(left, right); /// + [Intrinsic] static Vector64 ISimdVector, T>.MinNative(Vector64 left, Vector64 right) => Vector64.MinNative(left, right); /// + [Intrinsic] static Vector64 ISimdVector, T>.MinNumber(Vector64 left, Vector64 right) => Vector64.MinNumber(left, right); /// + [Intrinsic] static Vector64 ISimdVector, T>.Multiply(Vector64 left, Vector64 right) => left * right; /// + [Intrinsic] static Vector64 ISimdVector, T>.Multiply(Vector64 left, T right) => left * right; /// + [Intrinsic] static Vector64 ISimdVector, T>.MultiplyAddEstimate(Vector64 left, Vector64 right, Vector64 addend) => Vector64.MultiplyAddEstimate(left, right, addend); /// + [Intrinsic] static Vector64 ISimdVector, T>.Negate(Vector64 vector) => -vector; + /// + [Intrinsic] + static bool ISimdVector, T>.None(Vector64 vector, T value) => Vector64.None(vector, value); + + /// + [Intrinsic] + static bool ISimdVector, T>.NoneWhereAllBitsSet(Vector64 vector) => Vector64.NoneWhereAllBitsSet(vector); + /// + [Intrinsic] static Vector64 ISimdVector, T>.OnesComplement(Vector64 vector) => ~vector; /// + [Intrinsic] static Vector64 ISimdVector, T>.Round(Vector64 vector) => Vector64.Round(vector); /// + [Intrinsic] static Vector64 ISimdVector, T>.ShiftLeft(Vector64 vector, int shiftCount) => vector << shiftCount; /// + [Intrinsic] static Vector64 ISimdVector, T>.ShiftRightArithmetic(Vector64 vector, int shiftCount) => vector >> shiftCount; /// + [Intrinsic] static Vector64 ISimdVector, T>.ShiftRightLogical(Vector64 vector, int shiftCount) => vector >>> shiftCount; /// + [Intrinsic] static Vector64 ISimdVector, T>.Sqrt(Vector64 vector) => Vector64.Sqrt(vector); /// + [Intrinsic] static void ISimdVector, T>.Store(Vector64 source, T* destination) => source.Store(destination); /// + [Intrinsic] static void ISimdVector, T>.StoreAligned(Vector64 source, T* destination) => source.StoreAligned(destination); /// + [Intrinsic] static void ISimdVector, T>.StoreAlignedNonTemporal(Vector64 source, T* destination) => source.StoreAlignedNonTemporal(destination); /// + [Intrinsic] static void ISimdVector, T>.StoreUnsafe(Vector64 vector, ref T destination) => vector.StoreUnsafe(ref destination); /// + [Intrinsic] static void ISimdVector, T>.StoreUnsafe(Vector64 vector, ref T destination, nuint elementOffset) => vector.StoreUnsafe(ref destination, elementOffset); /// + [Intrinsic] static Vector64 ISimdVector, T>.Subtract(Vector64 left, Vector64 right) => left - right; /// + [Intrinsic] static T ISimdVector, T>.Sum(Vector64 vector) => Vector64.Sum(vector); /// + [Intrinsic] static T ISimdVector, T>.ToScalar(Vector64 vector) => vector.ToScalar(); /// + [Intrinsic] static Vector64 ISimdVector, T>.Truncate(Vector64 vector) => Vector64.Truncate(vector); /// static bool ISimdVector, T>.TryCopyTo(Vector64 vector, Span destination) => vector.TryCopyTo(destination); /// + [Intrinsic] static Vector64 ISimdVector, T>.WithElement(Vector64 vector, int index, T value) => vector.WithElement(index, value); /// + [Intrinsic] static Vector64 ISimdVector, T>.Xor(Vector64 left, Vector64 right) => left ^ right; - - // - // New Surface Area - // - - static bool ISimdVector, T>.AnyWhereAllBitsSet(Vector64 vector) => Vector64.EqualsAny(vector, AllBitsSet); - - static bool ISimdVector, T>.Any(Vector64 vector, T value) => Vector64.EqualsAny(vector, Vector64.Create(value)); - - static int ISimdVector, T>.IndexOfLastMatch(Vector64 vector) - { - uint mask = vector.ExtractMostSignificantBits(); - return 31 - BitOperations.LeadingZeroCount(mask); // 31 = 32 (bits in Int32) - 1 (indexing from zero) - } - - static Vector64 ISimdVector, T>.IsNaN(Vector64 vector) => Vector64.IsNaN(vector); - - static Vector64 ISimdVector, T>.IsNegative(Vector64 vector) => Vector64.IsNegative(vector); - - static Vector64 ISimdVector, T>.IsPositive(Vector64 vector) => Vector64.IsPositive(vector); - - static Vector64 ISimdVector, T>.IsPositiveInfinity(Vector64 vector) => Vector64.IsPositiveInfinity(vector); - - static Vector64 ISimdVector, T>.IsZero(Vector64 vector) => Vector64.IsZero(vector); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/VectorMath.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/VectorMath.cs index ba2838dd336e32..f5216c5dd48b46 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/VectorMath.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/VectorMath.cs @@ -136,7 +136,7 @@ static TVectorDouble ScalarFallback(TVectorDouble x) { TVectorDouble result = TVectorDouble.Zero; - for (int i = 0; i < TVectorDouble.Count; i++) + for (int i = 0; i < TVectorDouble.ElementCount; i++) { double scalar = double.Cos(x[i]); result = result.WithElement(i, scalar); @@ -225,7 +225,7 @@ public static TVectorSingle CosSingle= 2^-13 - if (TVectorSingle.Count == TVectorDouble.Count) + if (TVectorSingle.ElementCount == TVectorDouble.ElementCount) { result = Narrow( CosSingleSmall(Widen(x)) @@ -250,7 +250,7 @@ public static TVectorSingle CosSingle (pi / 4) -or- infinite -or- nan - if (TVectorSingle.Count == TVectorDouble.Count) + if (TVectorSingle.ElementCount == TVectorDouble.ElementCount) { result = Narrow( CoreImpl(Widen(ax)) @@ -300,7 +300,7 @@ static TVectorSingle ScalarFallback(TVectorSingle x) { TVectorSingle result = TVectorSingle.Zero; - for (int i = 0; i < TVectorSingle.Count; i++) + for (int i = 0; i < TVectorSingle.ElementCount; i++) { float scalar = float.Cos(x[i]); result = result.WithElement(i, scalar); @@ -461,7 +461,7 @@ static TVectorDouble ScalarFallback(TVectorDouble x) { TVectorDouble expResult = TVectorDouble.Zero; - for (int i = 0; i < TVectorDouble.Count; i++) + for (int i = 0; i < TVectorDouble.ElementCount; i++) { double expScalar = double.Exp(x[i]); expResult = expResult.WithElement(i, expScalar); @@ -524,7 +524,7 @@ public static TVectorSingle ExpSingle( CoreImpl(Widen(x)) @@ -608,7 +608,7 @@ public static TVectorDouble HypotDouble(TVectorDou TVectorUInt64 xBits = Unsafe.BitCast(ax); TVectorUInt64 yBits = Unsafe.BitCast(ay); - TVectorUInt64 shiftedExponentMask = TVectorUInt64.Create(double.ShiftedExponentMask); + TVectorUInt64 shiftedExponentMask = TVectorUInt64.Create(double.ShiftedBiasedExponentMask); TVectorUInt64 xExp = (xBits >> double.BiasedExponentShift) & shiftedExponentMask; TVectorUInt64 yExp = (yBits >> double.BiasedExponentShift) & shiftedExponentMask; @@ -737,7 +737,7 @@ public static TVectorSingle HypotSingle(TVectorSin TVectorSingle result; - if (TVectorSingle.Count == TVectorDouble.Count) + if (TVectorSingle.ElementCount == TVectorDouble.ElementCount) { result = Narrow( CoreImpl(Widen(ax), Widen(ay)) @@ -768,6 +768,98 @@ static TVectorDouble CoreImpl(TVectorDouble x, TVectorDouble y) } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TVectorSingle IsEvenIntegerSingle(TVectorSingle vector) + where TVectorSingle : unmanaged, ISimdVector + where TVectorUInt32 : unmanaged, ISimdVector + { + TVectorUInt32 bits = Unsafe.BitCast(TVectorSingle.Abs(vector)); + + TVectorUInt32 exponent = ((bits >> float.BiasedExponentShift) & TVectorUInt32.Create(float.ShiftedBiasedExponentMask)) - TVectorUInt32.Create(float.ExponentBias); + TVectorUInt32 fractionalBits = TVectorUInt32.Create(float.BiasedExponentShift) - exponent; + TVectorUInt32 firstIntegralBit = ShiftLeftUInt32(TVectorUInt32.One, fractionalBits); + TVectorUInt32 fractionalBitMask = firstIntegralBit - TVectorUInt32.One; + + // We must be an integer in the range [1, 2^24) with the least significant integral bit clear + // or in the range [2^24, +Infinity) in which case we are known to be an even integer + TVectorUInt32 result = TVectorUInt32.GreaterThan(bits, TVectorUInt32.Create(0x3FFF_FFFF)) + & TVectorUInt32.LessThan(bits, TVectorUInt32.Create(float.PositiveInfinityBits)) + & ((TVectorUInt32.IsZero(bits & fractionalBitMask) & TVectorUInt32.IsZero(bits & firstIntegralBit)) + | TVectorUInt32.GreaterThan(bits, TVectorUInt32.Create(0x4B7F_FFFF))); + + // We are also an even integer if we are zero + result |= TVectorUInt32.IsZero(bits); + + return Unsafe.BitCast(result); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TVectorDouble IsEvenIntegerDouble(TVectorDouble vector) + where TVectorDouble : unmanaged, ISimdVector + where TVectorUInt64 : unmanaged, ISimdVector + { + TVectorUInt64 bits = Unsafe.BitCast(TVectorDouble.Abs(vector)); + + TVectorUInt64 exponent = ((bits >> double.BiasedExponentShift) & TVectorUInt64.Create(double.ShiftedBiasedExponentMask)) - TVectorUInt64.Create(double.ExponentBias); + TVectorUInt64 fractionalBits = TVectorUInt64.Create(double.BiasedExponentShift) - exponent; + TVectorUInt64 firstIntegralBit = ShiftLeftUInt64(TVectorUInt64.One, fractionalBits); + TVectorUInt64 fractionalBitMask = firstIntegralBit - TVectorUInt64.One; + + // We must be an integer in the range [1, 2^53) with the least significant integral bit clear + // or in the range [2^53, +Infinity) in which case we are known to be an even integer + TVectorUInt64 result = TVectorUInt64.GreaterThan(bits, TVectorUInt64.Create(0x3FFF_FFFF_FFFF_FFFF)) + & TVectorUInt64.LessThan(bits, TVectorUInt64.Create(double.PositiveInfinityBits)) + & ((TVectorUInt64.IsZero(bits & fractionalBitMask) & TVectorUInt64.IsZero(bits & firstIntegralBit)) + | TVectorUInt64.GreaterThan(bits, TVectorUInt64.Create(0x433F_FFFF_FFFF_FFFF))); + + // We are also an even integer if we are zero + result |= TVectorUInt64.IsZero(bits); + + return Unsafe.BitCast(result); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TVectorSingle IsOddIntegerSingle(TVectorSingle vector) + where TVectorSingle : unmanaged, ISimdVector + where TVectorUInt32 : unmanaged, ISimdVector + { + TVectorUInt32 bits = Unsafe.BitCast(TVectorSingle.Abs(vector)); + + TVectorUInt32 exponent = ((bits >> float.BiasedExponentShift) & TVectorUInt32.Create(float.ShiftedBiasedExponentMask)) - TVectorUInt32.Create(float.ExponentBias); + TVectorUInt32 fractionalBits = TVectorUInt32.Create(float.BiasedExponentShift) - exponent; + TVectorUInt32 firstIntegralBit = ShiftLeftUInt32(TVectorUInt32.One, fractionalBits); + TVectorUInt32 fractionalBitMask = firstIntegralBit - TVectorUInt32.One; + + // We must be an integer in the range [1, 2^24) with the least significant integral bit set + TVectorUInt32 result = TVectorUInt32.GreaterThan(bits, TVectorUInt32.Create(0x3F7F_FFFF)) + & TVectorUInt32.LessThan(bits, TVectorUInt32.Create(0x4B80_0000)) + & TVectorUInt32.IsZero(bits & fractionalBitMask) + & ~TVectorUInt32.IsZero(bits & firstIntegralBit); + + return Unsafe.BitCast(result); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TVectorDouble IsOddIntegerDouble(TVectorDouble vector) + where TVectorDouble : unmanaged, ISimdVector + where TVectorUInt64 : unmanaged, ISimdVector + { + TVectorUInt64 bits = Unsafe.BitCast(TVectorDouble.Abs(vector)); + + TVectorUInt64 exponent = ((bits >> double.BiasedExponentShift) & TVectorUInt64.Create(double.ShiftedBiasedExponentMask)) - TVectorUInt64.Create(double.ExponentBias); + TVectorUInt64 fractionalBits = TVectorUInt64.Create(double.BiasedExponentShift) - exponent; + TVectorUInt64 firstIntegralBit = ShiftLeftUInt64(TVectorUInt64.One, fractionalBits); + TVectorUInt64 fractionalBitMask = firstIntegralBit - TVectorUInt64.One; + + // We must be an integer in the range [1, 2^53) with the least significant integral bit set + TVectorUInt64 result = TVectorUInt64.GreaterThan(bits, TVectorUInt64.Create(0x3FEF_FFFF_FFFF_FFFF)) + & TVectorUInt64.LessThan(bits, TVectorUInt64.Create(0x4340_0000_0000_0000)) + & TVectorUInt64.IsZero(bits & fractionalBitMask) + & ~TVectorUInt64.IsZero(bits & firstIntegralBit); + + return Unsafe.BitCast(result); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static TVector Lerp(TVector x, TVector y, TVector amount) where TVector : unmanaged, ISimdVector @@ -1796,7 +1888,7 @@ public static (TVectorDouble Sin, TVectorDouble Cos) SinCosDouble= 2^-13 - if (TVectorSingle.Count == TVectorDouble.Count) + if (TVectorSingle.ElementCount == TVectorDouble.ElementCount) { TVectorDouble dx = Widen(x); @@ -1880,7 +1972,7 @@ public static (TVectorSingle Sin, TVectorSingle Cos) SinCosSingle (pi / 4) -or- infinite -or- nan - if (TVectorSingle.Count == TVectorDouble.Count) + if (TVectorSingle.ElementCount == TVectorDouble.ElementCount) { (TVectorDouble sin, TVectorDouble cos) = CoreImpl(Widen(x)); @@ -1957,7 +2049,7 @@ public static (TVectorSingle Sin, TVectorSingle Cos) SinCosSingle= 2^-13 - if (TVectorSingle.Count == TVectorDouble.Count) + if (TVectorSingle.ElementCount == TVectorDouble.ElementCount) { result = Narrow( SinSinglePoly(Widen(x)) @@ -2195,7 +2287,7 @@ public static TVectorSingle SinSingle (pi / 4) -or- infinite -or- nan - if (TVectorSingle.Count == TVectorDouble.Count) + if (TVectorSingle.ElementCount == TVectorDouble.ElementCount) { result = Narrow( CoreImpl(Widen(x)) @@ -2248,7 +2340,7 @@ static TVectorSingle ScalarFallback(TVectorSingle x) { TVectorSingle result = TVectorSingle.Zero; - for (int i = 0; i < TVectorSingle.Count; i++) + for (int i = 0; i < TVectorSingle.ElementCount; i++) { float scalar = float.Sin(x[i]); result = result.WithElement(i, scalar); @@ -2583,6 +2675,104 @@ private static TVectorSingle Narrow(TVectorDouble return result; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static TVectorUInt32 ShiftLeftUInt32(TVectorUInt32 vector, TVectorUInt32 shiftAmount) + where TVectorUInt32 : unmanaged, ISimdVector + { + Unsafe.SkipInit(out TVectorUInt32 result); + + if (typeof(TVectorUInt32) == typeof(Vector)) + { + result = (TVectorUInt32)(object)Vector.ShiftLeft( + (Vector)(object)vector, + (Vector)(object)shiftAmount + ); + } + else if (typeof(TVectorUInt32) == typeof(Vector64)) + { + result = (TVectorUInt32)(object)Vector64.ShiftLeft( + (Vector64)(object)vector, + (Vector64)(object)shiftAmount + ); + } + else if (typeof(TVectorUInt32) == typeof(Vector128)) + { + result = (TVectorUInt32)(object)Vector128.ShiftLeft( + (Vector128)(object)vector, + (Vector128)(object)shiftAmount + ); + } + else if (typeof(TVectorUInt32) == typeof(Vector256)) + { + result = (TVectorUInt32)(object)Vector256.ShiftLeft( + (Vector256)(object)vector, + (Vector256)(object)shiftAmount + ); + } + else if (typeof(TVectorUInt32) == typeof(Vector512)) + { + result = (TVectorUInt32)(object)Vector512.ShiftLeft( + (Vector512)(object)vector, + (Vector512)(object)shiftAmount + ); + } + else + { + ThrowHelper.ThrowNotSupportedException(); + } + + return result; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static TVectorUInt64 ShiftLeftUInt64(TVectorUInt64 vector, TVectorUInt64 shiftAmount) + where TVectorUInt64 : unmanaged, ISimdVector + { + Unsafe.SkipInit(out TVectorUInt64 result); + + if (typeof(TVectorUInt64) == typeof(Vector)) + { + result = (TVectorUInt64)(object)Vector.ShiftLeft( + (Vector)(object)vector, + (Vector)(object)shiftAmount + ); + } + else if (typeof(TVectorUInt64) == typeof(Vector64)) + { + result = (TVectorUInt64)(object)Vector64.ShiftLeft( + (Vector64)(object)vector, + (Vector64)(object)shiftAmount + ); + } + else if (typeof(TVectorUInt64) == typeof(Vector128)) + { + result = (TVectorUInt64)(object)Vector128.ShiftLeft( + (Vector128)(object)vector, + (Vector128)(object)shiftAmount + ); + } + else if (typeof(TVectorUInt64) == typeof(Vector256)) + { + result = (TVectorUInt64)(object)Vector256.ShiftLeft( + (Vector256)(object)vector, + (Vector256)(object)shiftAmount + ); + } + else if (typeof(TVectorUInt64) == typeof(Vector512)) + { + result = (TVectorUInt64)(object)Vector512.ShiftLeft( + (Vector512)(object)vector, + (Vector512)(object)shiftAmount + ); + } + else + { + ThrowHelper.ThrowNotSupportedException(); + } + + return result; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private static TVectorDouble SinDoubleLarge(TVectorDouble r, TVectorDouble rr) where TVectorDouble : unmanaged, ISimdVector diff --git a/src/libraries/System.Private.CoreLib/src/System/Single.cs b/src/libraries/System.Private.CoreLib/src/System/Single.cs index 28c545a65a628b..38b9b389f7d9c3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Single.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Single.cs @@ -177,8 +177,8 @@ public static bool IsFinite(float f) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsInfinity(float f) { - uint bits = BitConverter.SingleToUInt32Bits(f); - return (bits & ~SignMask) == PositiveInfinityBits; + uint bits = BitConverter.SingleToUInt32Bits(Abs(f)); + return bits == PositiveInfinityBits; } /// Determines whether the specified value is NaN. @@ -224,8 +224,8 @@ public static bool IsNegativeInfinity(float f) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsNormal(float f) { - uint bits = BitConverter.SingleToUInt32Bits(f); - return ((bits & ~SignMask) - SmallestNormalBits) < (PositiveInfinityBits - SmallestNormalBits); + uint bits = BitConverter.SingleToUInt32Bits(Abs(f)); + return (bits - SmallestNormalBits) < (PositiveInfinityBits - SmallestNormalBits); } /// Determines whether the specified value is positive infinity. @@ -242,8 +242,8 @@ public static bool IsPositiveInfinity(float f) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsSubnormal(float f) { - uint bits = BitConverter.SingleToUInt32Bits(f); - return ((bits & ~SignMask) - 1) < MaxTrailingSignificand; + uint bits = BitConverter.SingleToUInt32Bits(Abs(f)); + return (bits - 1) < MaxTrailingSignificand; } [NonVersionable] @@ -938,7 +938,24 @@ bool IFloatingPoint.TryWriteSignificandLittleEndian(Span destinatio // /// - public static float Clamp(float value, float min, float max) => Math.Clamp(value, min, max); + public static float Clamp(float value, float min, float max) + { + if (min > max) + { + Math.ThrowMinMaxException(min, max); + } + return Min(Max(value, min), max); + } + + /// + public static float ClampNative(float value, float min, float max) + { + if (min > max) + { + Math.ThrowMinMaxException(min, max); + } + return MinNative(MaxNative(value, min), max); + } /// public static float CopySign(float value, float sign) => MathF.CopySign(value, sign); @@ -947,6 +964,10 @@ bool IFloatingPoint.TryWriteSignificandLittleEndian(Span destinatio [Intrinsic] public static float Max(float x, float y) => MathF.Max(x, y); + /// + [Intrinsic] + public static float MaxNative(float x, float y) => (x > y) ? x : y; + /// [Intrinsic] public static float MaxNumber(float x, float y) @@ -974,6 +995,10 @@ public static float MaxNumber(float x, float y) [Intrinsic] public static float Min(float x, float y) => MathF.Min(x, y); + /// + [Intrinsic] + public static float MinNative(float x, float y) => (x < y) ? x : y; + /// [Intrinsic] public static float MinNumber(float x, float y) @@ -1081,7 +1106,27 @@ public static float CreateTruncating(TOther value) static bool INumberBase.IsComplexNumber(float value) => false; /// - public static bool IsEvenInteger(float value) => IsInteger(value) && (Abs(value % 2) == 0); + public static bool IsEvenInteger(float value) + { + uint bits = BitConverter.SingleToUInt32Bits(Abs(value)); + + if (bits < 0x3F80_0000) + { + return bits == 0; + } + + if (bits >= 0x4B80_0000) + { + return bits < 0x7F80_0000; + } + + uint exponent = ((bits >> 23) & 0xFF) - 127; + uint fractionalBits = 23 - exponent; + uint firstIntegerBit = 1u << (int)fractionalBits; + uint fractionalBitMask = firstIntegerBit - 1; + + return ((bits & fractionalBitMask) == 0) && ((bits & firstIntegerBit) == 0); + } /// static bool INumberBase.IsImaginaryNumber(float value) => false; diff --git a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs index 4c1cf529384d1d..35b69944f883cc 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.T.cs @@ -2527,7 +2527,7 @@ static int SimdImpl(ref TValue searchSpace, TValue value, int length) TVector current; TVector values = TVector.Create(value); - int offset = length - TVector.Count; + int offset = length - TVector.ElementCount; // Loop until either we've finished all elements -or- there's one or less than a vector's-worth remaining. while (offset > 0) @@ -2536,10 +2536,10 @@ static int SimdImpl(ref TValue searchSpace, TValue value, int length) if (TNegator.HasMatch(values, current)) { - return offset + TVector.IndexOfLastMatch(TNegator.GetMatchMask(values, current)); + return offset + TVector.LastIndexOfWhereAllBitsSet(TNegator.GetMatchMask(values, current)); } - offset -= TVector.Count; + offset -= TVector.ElementCount; } // Process the first vector in the search space. @@ -2548,7 +2548,7 @@ static int SimdImpl(ref TValue searchSpace, TValue value, int length) if (TNegator.HasMatch(values, current)) { - return TVector.IndexOfLastMatch(TNegator.GetMatchMask(values, current)); + return TVector.LastIndexOfWhereAllBitsSet(TNegator.GetMatchMask(values, current)); } return -1; diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/Ascii.Utility.cs b/src/libraries/System.Private.CoreLib/src/System/Text/Ascii.Utility.cs index 580550467fe589..2d337d0fb41697 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/Ascii.Utility.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/Ascii.Utility.cs @@ -2167,14 +2167,14 @@ private static unsafe void WidenAsciiToUtf1_Vector(b // Calculating the destination address outside the loop results in significant // perf wins vs. relying on the JIT to fold memory addressing logic into the // write instructions. See: https://github.com/dotnet/runtime/issues/33002 - nuint finalOffsetWhereCanRunLoop = elementCount - (nuint)TVectorByte.Count; + nuint finalOffsetWhereCanRunLoop = elementCount - (nuint)TVectorByte.ElementCount; TVectorByte asciiVector = TVectorByte.Load(pAsciiBuffer + currentOffset); if (!HasMatch(asciiVector)) { (TVectorUInt16 utf16LowVector, TVectorUInt16 utf16HighVector) = Widen(asciiVector); utf16LowVector.Store(pCurrentWriteAddress); - utf16HighVector.Store(pCurrentWriteAddress + TVectorUInt16.Count); - pCurrentWriteAddress += (nuint)(TVectorUInt16.Count * 2); + utf16HighVector.Store(pCurrentWriteAddress + TVectorUInt16.ElementCount); + pCurrentWriteAddress += (nuint)(TVectorUInt16.ElementCount * 2); if (((nuint)pCurrentWriteAddress % sizeof(char)) == 0) { // Bump write buffer up to the next aligned boundary @@ -2185,7 +2185,7 @@ private static unsafe void WidenAsciiToUtf1_Vector(b else { // If input isn't char aligned, we won't be able to align it to a Vector - currentOffset += (nuint)TVectorByte.Count; + currentOffset += (nuint)TVectorByte.ElementCount; } while (currentOffset <= finalOffsetWhereCanRunLoop) { @@ -2196,10 +2196,10 @@ private static unsafe void WidenAsciiToUtf1_Vector(b } (utf16LowVector, utf16HighVector) = Widen(asciiVector); utf16LowVector.Store(pCurrentWriteAddress); - utf16HighVector.Store(pCurrentWriteAddress + TVectorUInt16.Count); + utf16HighVector.Store(pCurrentWriteAddress + TVectorUInt16.ElementCount); - currentOffset += (nuint)TVectorByte.Count; - pCurrentWriteAddress += (nuint)(TVectorUInt16.Count * 2); + currentOffset += (nuint)TVectorByte.ElementCount; + pCurrentWriteAddress += (nuint)(TVectorUInt16.ElementCount * 2); } } return; diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeOnly.cs b/src/libraries/System.Private.CoreLib/src/System/TimeOnly.cs index 8e3a11bb2ebac2..72e15d2faada6a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeOnly.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeOnly.cs @@ -21,7 +21,7 @@ public readonly struct TimeOnly IUtf8SpanFormattable { // represent the number of ticks map to the time of the day. 1 ticks = 100-nanosecond in time measurements. - private readonly long _ticks; + private readonly ulong _ticks; // MinTimeTicks is the ticks for the midnight time 00:00:00.000 AM private const long MinTimeTicks = 0; @@ -84,68 +84,66 @@ public TimeOnly(long ticks) throw new ArgumentOutOfRangeException(nameof(ticks), SR.ArgumentOutOfRange_TimeOnlyBadTicks); } - _ticks = ticks; + _ticks = (ulong)ticks; } // exist to bypass the check in the public constructor. - internal TimeOnly(ulong ticks) => _ticks = (long)ticks; + internal TimeOnly(ulong ticks) => _ticks = ticks; /// /// Gets the hour component of the time represented by this instance. /// - public int Hour => new TimeSpan(_ticks).Hours; + public int Hour => (int)(_ticks / TimeSpan.TicksPerHour); /// /// Gets the minute component of the time represented by this instance. /// - public int Minute => new TimeSpan(_ticks).Minutes; + public int Minute => (int)((uint)(_ticks / TimeSpan.TicksPerMinute) % (uint)TimeSpan.MinutesPerHour); /// /// Gets the second component of the time represented by this instance. /// - public int Second => new TimeSpan(_ticks).Seconds; + public int Second => (int)((uint)(_ticks / TimeSpan.TicksPerSecond) % (uint)TimeSpan.SecondsPerMinute); /// /// Gets the millisecond component of the time represented by this instance. /// - public int Millisecond => new TimeSpan(_ticks).Milliseconds; + public int Millisecond => (int)((uint)(_ticks / TimeSpan.TicksPerMillisecond) % (uint)TimeSpan.MillisecondsPerSecond); /// /// Gets the microsecond component of the time represented by this instance. /// - public int Microsecond => new TimeSpan(_ticks).Microseconds; + public int Microsecond => (int)(_ticks / TimeSpan.TicksPerMicrosecond % (uint)TimeSpan.MicrosecondsPerMillisecond); /// /// Gets the nanosecond component of the time represented by this instance. /// - public int Nanosecond => new TimeSpan(_ticks).Nanoseconds; + public int Nanosecond => (int)(_ticks % TimeSpan.TicksPerMicrosecond * TimeSpan.NanosecondsPerTick); /// /// Gets the number of ticks that represent the time of this instance. /// - public long Ticks => _ticks; + public long Ticks => (long)_ticks; - private TimeOnly AddTicks(long ticks) => new TimeOnly((_ticks + TimeSpan.TicksPerDay + (ticks % TimeSpan.TicksPerDay)) % TimeSpan.TicksPerDay); + private TimeOnly AddTicks(long ticks) => new TimeOnly((_ticks + TimeSpan.TicksPerDay + (ulong)(ticks % TimeSpan.TicksPerDay)) % TimeSpan.TicksPerDay); private TimeOnly AddTicks(long ticks, out int wrappedDays) { - wrappedDays = (int)(ticks / TimeSpan.TicksPerDay); - long newTicks = _ticks + ticks % TimeSpan.TicksPerDay; + (long days, long newTicks) = Math.DivRem(ticks, TimeSpan.TicksPerDay); + newTicks += (long)_ticks; if (newTicks < 0) { - wrappedDays--; + days--; newTicks += TimeSpan.TicksPerDay; } - else + else if (newTicks >= TimeSpan.TicksPerDay) { - if (newTicks >= TimeSpan.TicksPerDay) - { - wrappedDays++; - newTicks -= TimeSpan.TicksPerDay; - } + days++; + newTicks -= TimeSpan.TicksPerDay; } - return new TimeOnly(newTicks); + wrappedDays = (int)days; + return new TimeOnly((ulong)newTicks); } /// @@ -209,12 +207,13 @@ private TimeOnly AddTicks(long ticks, out int wrappedDays) /// public bool IsBetween(TimeOnly start, TimeOnly end) { - long startTicks = start._ticks; - long endTicks = end._ticks; + ulong time = _ticks; + ulong startTicks = start._ticks; + ulong endTicks = end._ticks; return startTicks <= endTicks - ? (startTicks <= _ticks && endTicks > _ticks) - : (startTicks <= _ticks || endTicks > _ticks); + ? (time - startTicks < endTicks - startTicks) + : (time - endTicks >= startTicks - endTicks); } /// @@ -277,7 +276,12 @@ public bool IsBetween(TimeOnly start, TimeOnly end) /// The first TimeOnly instance. /// The second TimeOnly instance.. /// The elapsed time between t1 and t2. - public static TimeSpan operator -(TimeOnly t1, TimeOnly t2) => new TimeSpan((t1._ticks - t2._ticks + TimeSpan.TicksPerDay) % TimeSpan.TicksPerDay); + public static TimeSpan operator -(TimeOnly t1, TimeOnly t2) + { + long diff = (long)(t1._ticks - t2._ticks); + // If the result is negative, add 24h to make it positive again using the sign bit. + return new TimeSpan(diff + ((diff >> 63) & TimeSpan.TicksPerDay)); + } /// /// Deconstructs by and . @@ -310,8 +314,7 @@ public void Deconstruct(out int hour, out int minute) [EditorBrowsable(EditorBrowsableState.Never)] public void Deconstruct(out int hour, out int minute, out int second) { - (hour, minute) = this; - second = Second; + ToDateTime().GetTime(out hour, out minute, out second); } /// @@ -332,8 +335,7 @@ public void Deconstruct(out int hour, out int minute, out int second) [EditorBrowsable(EditorBrowsableState.Never)] public void Deconstruct(out int hour, out int minute, out int second, out int millisecond) { - (hour, minute, second) = this; - millisecond = Millisecond; + ToDateTime().GetTime(out hour, out minute, out second, out millisecond); } /// @@ -373,15 +375,15 @@ public void Deconstruct(out int hour, out int minute, out int second, out int mi /// /// The time DateTime object to extract the time of the day from. /// A TimeOnly object representing time of the day specified in the DateTime object. - public static TimeOnly FromDateTime(DateTime dateTime) => new TimeOnly(dateTime.TimeOfDay.Ticks); + public static TimeOnly FromDateTime(DateTime dateTime) => new TimeOnly((ulong)dateTime.TimeOfDay.Ticks); /// /// Convert the current TimeOnly instance to a TimeSpan object. /// /// A TimeSpan object spanning to the time specified in the current TimeOnly object. - public TimeSpan ToTimeSpan() => new TimeSpan(_ticks); + public TimeSpan ToTimeSpan() => new TimeSpan((long)_ticks); - internal DateTime ToDateTime() => new DateTime(_ticks); + internal DateTime ToDateTime() => DateTime.CreateUnchecked((long)_ticks); /// /// Compares the value of this instance to a specified TimeOnly value and indicates whether this instance is earlier than, the same as, or later than the specified TimeOnly value. @@ -436,7 +438,7 @@ public int CompareTo(object? value) /// A 32-bit signed integer hash code. public override int GetHashCode() { - long ticks = _ticks; + ulong ticks = _ticks; return unchecked((int)ticks) ^ (int)(ticks >> 32); } @@ -626,8 +628,7 @@ private static ParseFailureKind TryParseInternal(ReadOnlySpan s, IFormatPr return ParseFailureKind.Format_DateTimeOnlyContainsNoneDateParts; } - result = new TimeOnly(dtResult.parsedDate.TimeOfDay.Ticks); - + result = FromDateTime(dtResult.parsedDate); return ParseFailureKind.None; } @@ -668,12 +669,12 @@ private static ParseFailureKind TryParseExactInternal(ReadOnlySpan s, Read { case 'o': format = OFormat; - provider = CultureInfo.InvariantCulture.DateTimeFormat; + provider = DateTimeFormat.InvariantFormatInfo; break; case 'r': format = RFormat; - provider = CultureInfo.InvariantCulture.DateTimeFormat; + provider = DateTimeFormat.InvariantFormatInfo; break; } } @@ -693,8 +694,7 @@ private static ParseFailureKind TryParseExactInternal(ReadOnlySpan s, Read return ParseFailureKind.Format_DateTimeOnlyContainsNoneDateParts; } - result = new TimeOnly(dtResult.parsedDate.TimeOfDay.Ticks); - + result = FromDateTime(dtResult.parsedDate); return ParseFailureKind.None; } @@ -745,12 +745,12 @@ private static ParseFailureKind TryParseExactInternal(ReadOnlySpan s, stri { case 'o': format = OFormat; - dtfiToUse = CultureInfo.InvariantCulture.DateTimeFormat; + dtfiToUse = DateTimeFormat.InvariantFormatInfo; break; case 'r': format = RFormat; - dtfiToUse = CultureInfo.InvariantCulture.DateTimeFormat; + dtfiToUse = DateTimeFormat.InvariantFormatInfo; break; } } @@ -761,7 +761,7 @@ private static ParseFailureKind TryParseExactInternal(ReadOnlySpan s, stri dtResult.Init(s); if (DateTimeParse.TryParseExact(s, format, dtfiToUse, style, ref dtResult) && ((dtResult.flags & ParseFlagsTimeMask) == 0)) { - result = new TimeOnly(dtResult.parsedDate.TimeOfDay.Ticks); + result = FromDateTime(dtResult.parsedDate); return ParseFailureKind.None; } } @@ -888,7 +888,7 @@ private static void ThrowOnError(ParseFailureKind result, ReadOnlySpan s) /// The TimeOnly object will be formatted in short form. /// /// A string that contains the short time string representation of the current TimeOnly object. - public override string ToString() => ToString("t"); + public override string ToString() => DateTimeFormat.Format(ToDateTime(), "t", null); /// /// Converts the value of the current TimeOnly object to its equivalent string representation using the specified format and the formatting conventions of the current culture. @@ -903,7 +903,7 @@ private static void ThrowOnError(ParseFailureKind result, ReadOnlySpan s) /// /// An object that supplies culture-specific formatting information. /// A string representation of value of the current TimeOnly object as specified by provider. - public string ToString(IFormatProvider? provider) => ToString("t", provider); + public string ToString(IFormatProvider? provider) => DateTimeFormat.Format(ToDateTime(), "t", provider); /// /// Converts the value of the current TimeOnly object to its equivalent string representation using the specified culture-specific format information. @@ -925,13 +925,13 @@ public string ToString([StringSyntax(StringSyntaxAttribute.TimeOnlyFormat)] stri { 'o' => string.Create(16, this, (destination, value) => { - DateTimeFormat.TryFormatTimeOnlyO(value.Hour, value.Minute, value.Second, value._ticks % TimeSpan.TicksPerSecond, destination, out int charsWritten); + DateTimeFormat.TryFormatTimeOnlyO(value, destination, out int charsWritten); Debug.Assert(charsWritten == destination.Length); }), 'r' => string.Create(8, this, (destination, value) => { - DateTimeFormat.TryFormatTimeOnlyR(value.Hour, value.Minute, value.Second, destination, out int charsWritten); + DateTimeFormat.TryFormatTimeOnlyR(value, destination, out int charsWritten); Debug.Assert(charsWritten == destination.Length); }), @@ -973,10 +973,10 @@ private bool TryFormatCore(Span destination, out int written, [Str switch (format[0] | 0x20) { case 'o': - return DateTimeFormat.TryFormatTimeOnlyO(Hour, Minute, Second, _ticks % TimeSpan.TicksPerSecond, destination, out written); + return DateTimeFormat.TryFormatTimeOnlyO(this, destination, out written); case 'r': - return DateTimeFormat.TryFormatTimeOnlyR(Hour, Minute, Second, destination, out written); + return DateTimeFormat.TryFormatTimeOnlyR(this, destination, out written); case 't': return DateTimeFormat.TryFormat(ToDateTime(), destination, out written, format, provider); diff --git a/src/libraries/System.Private.CoreLib/src/System/TypeLoadException.cs b/src/libraries/System.Private.CoreLib/src/System/TypeLoadException.cs index f588f3d23f0ff4..b269f391316250 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TypeLoadException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TypeLoadException.cs @@ -29,6 +29,15 @@ public TypeLoadException(string? message, Exception? inner) HResult = HResults.COR_E_TYPELOAD; } +#if !MONO + internal TypeLoadException(string message, string typeName) + : base(message) + { + HResult = HResults.COR_E_TYPELOAD; + _className = typeName; + } +#endif + public override string Message { get diff --git a/src/libraries/System.Reflection.TypeExtensions/tests/ILLink.Descriptors.xml b/src/libraries/System.Reflection.TypeExtensions/tests/ILLink.Descriptors.xml deleted file mode 100644 index 573b67e7172d49..00000000000000 --- a/src/libraries/System.Reflection.TypeExtensions/tests/ILLink.Descriptors.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/libraries/System.Reflection.TypeExtensions/tests/System.Reflection.TypeExtensions.Tests.csproj b/src/libraries/System.Reflection.TypeExtensions/tests/System.Reflection.TypeExtensions.Tests.csproj index 4cec27f2eab318..eec6c3be0d0e89 100644 --- a/src/libraries/System.Reflection.TypeExtensions/tests/System.Reflection.TypeExtensions.Tests.csproj +++ b/src/libraries/System.Reflection.TypeExtensions/tests/System.Reflection.TypeExtensions.Tests.csproj @@ -22,6 +22,5 @@ TinyAssembly.dll PreserveNewest - diff --git a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs index bbca9ddf8ec3cf..4fa55777f5327c 100644 --- a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs +++ b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs @@ -1343,6 +1343,7 @@ public static void Free(void* ptr) { } public static System.Runtime.InteropServices.NFloat Cbrt(System.Runtime.InteropServices.NFloat x) { throw null; } public static System.Runtime.InteropServices.NFloat Ceiling(System.Runtime.InteropServices.NFloat x) { throw null; } public static System.Runtime.InteropServices.NFloat Clamp(System.Runtime.InteropServices.NFloat value, System.Runtime.InteropServices.NFloat min, System.Runtime.InteropServices.NFloat max) { throw null; } + public static System.Runtime.InteropServices.NFloat ClampNative(System.Runtime.InteropServices.NFloat value, System.Runtime.InteropServices.NFloat min, System.Runtime.InteropServices.NFloat max) { throw null; } public int CompareTo(object? obj) { throw null; } public int CompareTo(System.Runtime.InteropServices.NFloat other) { throw null; } public static TInteger ConvertToInteger(System.Runtime.InteropServices.NFloat value) where TInteger : System.Numerics.IBinaryInteger { throw null; } @@ -1394,10 +1395,12 @@ public static void Free(void* ptr) { } public static System.Runtime.InteropServices.NFloat Max(System.Runtime.InteropServices.NFloat x, System.Runtime.InteropServices.NFloat y) { throw null; } public static System.Runtime.InteropServices.NFloat MaxMagnitude(System.Runtime.InteropServices.NFloat x, System.Runtime.InteropServices.NFloat y) { throw null; } public static System.Runtime.InteropServices.NFloat MaxMagnitudeNumber(System.Runtime.InteropServices.NFloat x, System.Runtime.InteropServices.NFloat y) { throw null; } + public static System.Runtime.InteropServices.NFloat MaxNative(System.Runtime.InteropServices.NFloat x, System.Runtime.InteropServices.NFloat y) { throw null; } public static System.Runtime.InteropServices.NFloat MaxNumber(System.Runtime.InteropServices.NFloat x, System.Runtime.InteropServices.NFloat y) { throw null; } public static System.Runtime.InteropServices.NFloat Min(System.Runtime.InteropServices.NFloat x, System.Runtime.InteropServices.NFloat y) { throw null; } public static System.Runtime.InteropServices.NFloat MinMagnitude(System.Runtime.InteropServices.NFloat x, System.Runtime.InteropServices.NFloat y) { throw null; } public static System.Runtime.InteropServices.NFloat MinMagnitudeNumber(System.Runtime.InteropServices.NFloat x, System.Runtime.InteropServices.NFloat y) { throw null; } + public static System.Runtime.InteropServices.NFloat MinNative(System.Runtime.InteropServices.NFloat x, System.Runtime.InteropServices.NFloat y) { throw null; } public static System.Runtime.InteropServices.NFloat MinNumber(System.Runtime.InteropServices.NFloat x, System.Runtime.InteropServices.NFloat y) { throw null; } public static System.Runtime.InteropServices.NFloat MultiplyAddEstimate(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right, System.Runtime.InteropServices.NFloat addend) { throw null; } public static System.Runtime.InteropServices.NFloat operator +(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) { throw null; } diff --git a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs index 20aae5b67f0e70..1da0bf8ed49588 100644 --- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -13,7 +13,11 @@ public static partial class Vector128 public static bool IsHardwareAccelerated { get { throw null; } } public static System.Runtime.Intrinsics.Vector128 Abs(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 Add(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static bool All(System.Runtime.Intrinsics.Vector128 vector, T value) { throw null; } + public static bool AllWhereAllBitsSet(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 AndNot(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } + public static bool Any(System.Runtime.Intrinsics.Vector128 vector, T value) { throw null; } + public static bool AnyWhereAllBitsSet(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 AsByte(this System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 AsDouble(this System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 AsInt16(this System.Runtime.Intrinsics.Vector128 vector) { throw null; } @@ -73,6 +77,8 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector128 vector, public static void CopyTo(this System.Runtime.Intrinsics.Vector128 vector, T[] destination, int startIndex) { } public static System.Runtime.Intrinsics.Vector128 Cos(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 Cos(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static int Count(System.Runtime.Intrinsics.Vector128 vector, T value) { throw null; } + public static int CountWhereAllBitsSet(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 Create(byte value) { throw null; } public static System.Runtime.Intrinsics.Vector128 Create(byte e0, byte e1, byte e2, byte e3, byte e4, byte e5, byte e6, byte e7, byte e8, byte e9, byte e10, byte e11, byte e12, byte e13, byte e14, byte e15) { throw null; } public static System.Runtime.Intrinsics.Vector128 Create(double value) { throw null; } @@ -191,11 +197,23 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector128 vector, public static System.Runtime.Intrinsics.Vector128 GreaterThan(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } public static System.Runtime.Intrinsics.Vector128 Hypot(System.Runtime.Intrinsics.Vector128 x, System.Runtime.Intrinsics.Vector128 y) { throw null; } public static System.Runtime.Intrinsics.Vector128 Hypot(System.Runtime.Intrinsics.Vector128 x, System.Runtime.Intrinsics.Vector128 y) { throw null; } + public static int IndexOf(System.Runtime.Intrinsics.Vector128 vector, T value) { throw null; } + public static int IndexOfWhereAllBitsSet(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector128 IsEvenInteger(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector128 IsFinite(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector128 IsInfinity(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector128 IsInteger(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 IsNaN(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 IsNegative(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector128 IsNegativeInfinity(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector128 IsNormal(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector128 IsOddInteger(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 IsPositive(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 IsPositiveInfinity(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector128 IsSubnormal(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 IsZero(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static int LastIndexOf(System.Runtime.Intrinsics.Vector128 vector, T value) { throw null; } + public static int LastIndexOfWhereAllBitsSet(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 Lerp(System.Runtime.Intrinsics.Vector128 x, System.Runtime.Intrinsics.Vector128 y, System.Runtime.Intrinsics.Vector128 amount) { throw null; } public static System.Runtime.Intrinsics.Vector128 Lerp(System.Runtime.Intrinsics.Vector128 x, System.Runtime.Intrinsics.Vector128 y, System.Runtime.Intrinsics.Vector128 amount) { throw null; } public static bool LessThanAll(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) { throw null; } @@ -244,6 +262,8 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector128 vector, [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector128 Narrow(System.Runtime.Intrinsics.Vector128 lower, System.Runtime.Intrinsics.Vector128 upper) { throw null; } public static System.Runtime.Intrinsics.Vector128 Negate(System.Runtime.Intrinsics.Vector128 vector) { throw null; } + public static bool None(System.Runtime.Intrinsics.Vector128 vector, T value) { throw null; } + public static bool NoneWhereAllBitsSet(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 OnesComplement(System.Runtime.Intrinsics.Vector128 vector) { throw null; } public static System.Runtime.Intrinsics.Vector128 RadiansToDegrees(System.Runtime.Intrinsics.Vector128 radians) { throw null; } public static System.Runtime.Intrinsics.Vector128 RadiansToDegrees(System.Runtime.Intrinsics.Vector128 radians) { throw null; } @@ -399,7 +419,11 @@ public static partial class Vector256 public static bool IsHardwareAccelerated { get { throw null; } } public static System.Runtime.Intrinsics.Vector256 Abs(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 Add(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) { throw null; } + public static bool All(System.Runtime.Intrinsics.Vector256 vector, T value) { throw null; } + public static bool AllWhereAllBitsSet(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 AndNot(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) { throw null; } + public static bool Any(System.Runtime.Intrinsics.Vector256 vector, T value) { throw null; } + public static bool AnyWhereAllBitsSet(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 AsByte(this System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 AsDouble(this System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 AsInt16(this System.Runtime.Intrinsics.Vector256 vector) { throw null; } @@ -451,6 +475,8 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector256 vector, public static void CopyTo(this System.Runtime.Intrinsics.Vector256 vector, T[] destination, int startIndex) { } public static System.Runtime.Intrinsics.Vector256 Cos(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 Cos(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + public static int Count(System.Runtime.Intrinsics.Vector256 vector, T value) { throw null; } + public static int CountWhereAllBitsSet(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 Create(byte value) { throw null; } public static System.Runtime.Intrinsics.Vector256 Create(byte e0, byte e1, byte e2, byte e3, byte e4, byte e5, byte e6, byte e7, byte e8, byte e9, byte e10, byte e11, byte e12, byte e13, byte e14, byte e15, byte e16, byte e17, byte e18, byte e19, byte e20, byte e21, byte e22, byte e23, byte e24, byte e25, byte e26, byte e27, byte e28, byte e29, byte e30, byte e31) { throw null; } public static System.Runtime.Intrinsics.Vector256 Create(double value) { throw null; } @@ -570,11 +596,23 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector256 vector, public static System.Runtime.Intrinsics.Vector256 GreaterThan(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) { throw null; } public static System.Runtime.Intrinsics.Vector256 Hypot(System.Runtime.Intrinsics.Vector256 x, System.Runtime.Intrinsics.Vector256 y) { throw null; } public static System.Runtime.Intrinsics.Vector256 Hypot(System.Runtime.Intrinsics.Vector256 x, System.Runtime.Intrinsics.Vector256 y) { throw null; } + public static int IndexOf(System.Runtime.Intrinsics.Vector256 vector, T value) { throw null; } + public static int IndexOfWhereAllBitsSet(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector256 IsEvenInteger(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector256 IsFinite(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector256 IsInfinity(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector256 IsInteger(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 IsNaN(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 IsNegative(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector256 IsNegativeInfinity(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector256 IsNormal(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector256 IsOddInteger(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 IsPositive(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 IsPositiveInfinity(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector256 IsSubnormal(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 IsZero(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + public static int LastIndexOf(System.Runtime.Intrinsics.Vector256 vector, T value) { throw null; } + public static int LastIndexOfWhereAllBitsSet(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 Lerp(System.Runtime.Intrinsics.Vector256 x, System.Runtime.Intrinsics.Vector256 y, System.Runtime.Intrinsics.Vector256 amount) { throw null; } public static System.Runtime.Intrinsics.Vector256 Lerp(System.Runtime.Intrinsics.Vector256 x, System.Runtime.Intrinsics.Vector256 y, System.Runtime.Intrinsics.Vector256 amount) { throw null; } public static bool LessThanAll(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) { throw null; } @@ -623,6 +661,8 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector256 vector, [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector256 Narrow(System.Runtime.Intrinsics.Vector256 lower, System.Runtime.Intrinsics.Vector256 upper) { throw null; } public static System.Runtime.Intrinsics.Vector256 Negate(System.Runtime.Intrinsics.Vector256 vector) { throw null; } + public static bool None(System.Runtime.Intrinsics.Vector256 vector, T value) { throw null; } + public static bool NoneWhereAllBitsSet(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 OnesComplement(System.Runtime.Intrinsics.Vector256 vector) { throw null; } public static System.Runtime.Intrinsics.Vector256 RadiansToDegrees(System.Runtime.Intrinsics.Vector256 radians) { throw null; } public static System.Runtime.Intrinsics.Vector256 RadiansToDegrees(System.Runtime.Intrinsics.Vector256 radians) { throw null; } @@ -778,7 +818,11 @@ public static partial class Vector512 public static bool IsHardwareAccelerated { get { throw null; } } public static System.Runtime.Intrinsics.Vector512 Abs(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 Add(System.Runtime.Intrinsics.Vector512 left, System.Runtime.Intrinsics.Vector512 right) { throw null; } + public static bool All(System.Runtime.Intrinsics.Vector512 vector, T value) { throw null; } + public static bool AllWhereAllBitsSet(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 AndNot(System.Runtime.Intrinsics.Vector512 left, System.Runtime.Intrinsics.Vector512 right) { throw null; } + public static bool Any(System.Runtime.Intrinsics.Vector512 vector, T value) { throw null; } + public static bool AnyWhereAllBitsSet(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 AsByte(this System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 AsDouble(this System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 AsInt16(this System.Runtime.Intrinsics.Vector512 vector) { throw null; } @@ -830,6 +874,8 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector512 vector, public static void CopyTo(this System.Runtime.Intrinsics.Vector512 vector, T[] destination, int startIndex) { } public static System.Runtime.Intrinsics.Vector512 Cos(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 Cos(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + public static int Count(System.Runtime.Intrinsics.Vector512 vector, T value) { throw null; } + public static int CountWhereAllBitsSet(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 Create(byte value) { throw null; } public static System.Runtime.Intrinsics.Vector512 Create(byte e0, byte e1, byte e2, byte e3, byte e4, byte e5, byte e6, byte e7, byte e8, byte e9, byte e10, byte e11, byte e12, byte e13, byte e14, byte e15, byte e16, byte e17, byte e18, byte e19, byte e20, byte e21, byte e22, byte e23, byte e24, byte e25, byte e26, byte e27, byte e28, byte e29, byte e30, byte e31, byte e32, byte e33, byte e34, byte e35, byte e36, byte e37, byte e38, byte e39, byte e40, byte e41, byte e42, byte e43, byte e44, byte e45, byte e46, byte e47, byte e48, byte e49, byte e50, byte e51, byte e52, byte e53, byte e54, byte e55, byte e56, byte e57, byte e58, byte e59, byte e60, byte e61, byte e62, byte e63) { throw null; } public static System.Runtime.Intrinsics.Vector512 Create(double value) { throw null; } @@ -950,11 +996,23 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector512 vector, public static System.Runtime.Intrinsics.Vector512 GreaterThan(System.Runtime.Intrinsics.Vector512 left, System.Runtime.Intrinsics.Vector512 right) { throw null; } public static System.Runtime.Intrinsics.Vector512 Hypot(System.Runtime.Intrinsics.Vector512 x, System.Runtime.Intrinsics.Vector512 y) { throw null; } public static System.Runtime.Intrinsics.Vector512 Hypot(System.Runtime.Intrinsics.Vector512 x, System.Runtime.Intrinsics.Vector512 y) { throw null; } + public static int IndexOf(System.Runtime.Intrinsics.Vector512 vector, T value) { throw null; } + public static int IndexOfWhereAllBitsSet(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector512 IsEvenInteger(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector512 IsFinite(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector512 IsInfinity(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector512 IsInteger(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 IsNaN(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 IsNegative(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector512 IsNegativeInfinity(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector512 IsNormal(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector512 IsOddInteger(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 IsPositive(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 IsPositiveInfinity(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector512 IsSubnormal(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 IsZero(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + public static int LastIndexOf(System.Runtime.Intrinsics.Vector512 vector, T value) { throw null; } + public static int LastIndexOfWhereAllBitsSet(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 Lerp(System.Runtime.Intrinsics.Vector512 x, System.Runtime.Intrinsics.Vector512 y, System.Runtime.Intrinsics.Vector512 amount) { throw null; } public static System.Runtime.Intrinsics.Vector512 Lerp(System.Runtime.Intrinsics.Vector512 x, System.Runtime.Intrinsics.Vector512 y, System.Runtime.Intrinsics.Vector512 amount) { throw null; } public static bool LessThanAll(System.Runtime.Intrinsics.Vector512 left, System.Runtime.Intrinsics.Vector512 right) { throw null; } @@ -1003,6 +1061,8 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector512 vector, [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector512 Narrow(System.Runtime.Intrinsics.Vector512 lower, System.Runtime.Intrinsics.Vector512 upper) { throw null; } public static System.Runtime.Intrinsics.Vector512 Negate(System.Runtime.Intrinsics.Vector512 vector) { throw null; } + public static bool None(System.Runtime.Intrinsics.Vector512 vector, T value) { throw null; } + public static bool NoneWhereAllBitsSet(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 OnesComplement(System.Runtime.Intrinsics.Vector512 vector) { throw null; } public static System.Runtime.Intrinsics.Vector512 RadiansToDegrees(System.Runtime.Intrinsics.Vector512 radians) { throw null; } public static System.Runtime.Intrinsics.Vector512 RadiansToDegrees(System.Runtime.Intrinsics.Vector512 radians) { throw null; } @@ -1156,7 +1216,11 @@ public static partial class Vector64 public static bool IsHardwareAccelerated { get { throw null; } } public static System.Runtime.Intrinsics.Vector64 Abs(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 Add(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } + public static bool All(System.Runtime.Intrinsics.Vector64 vector, T value) { throw null; } + public static bool AllWhereAllBitsSet(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 AndNot(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } + public static bool Any(System.Runtime.Intrinsics.Vector64 vector, T value) { throw null; } + public static bool AnyWhereAllBitsSet(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 AsByte(this System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 AsDouble(this System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 AsInt16(this System.Runtime.Intrinsics.Vector64 vector) { throw null; } @@ -1206,6 +1270,8 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector64 vector, public static void CopyTo(this System.Runtime.Intrinsics.Vector64 vector, T[] destination, int startIndex) { } public static System.Runtime.Intrinsics.Vector64 Cos(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 Cos(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + public static int Count(System.Runtime.Intrinsics.Vector64 vector, T value) { throw null; } + public static int CountWhereAllBitsSet(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 Create(byte value) { throw null; } public static System.Runtime.Intrinsics.Vector64 Create(byte e0, byte e1, byte e2, byte e3, byte e4, byte e5, byte e6, byte e7) { throw null; } public static System.Runtime.Intrinsics.Vector64 Create(double value) { throw null; } @@ -1299,11 +1365,23 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector64 vector, public static System.Runtime.Intrinsics.Vector64 GreaterThan(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } public static System.Runtime.Intrinsics.Vector64 Hypot(System.Runtime.Intrinsics.Vector64 x, System.Runtime.Intrinsics.Vector64 y) { throw null; } public static System.Runtime.Intrinsics.Vector64 Hypot(System.Runtime.Intrinsics.Vector64 x, System.Runtime.Intrinsics.Vector64 y) { throw null; } + public static int IndexOf(System.Runtime.Intrinsics.Vector64 vector, T value) { throw null; } + public static int IndexOfWhereAllBitsSet(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector64 IsEvenInteger(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector64 IsFinite(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector64 IsInfinity(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector64 IsInteger(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 IsNaN(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 IsNegative(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector64 IsNegativeInfinity(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector64 IsNormal(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector64 IsOddInteger(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 IsPositive(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 IsPositiveInfinity(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + public static System.Runtime.Intrinsics.Vector64 IsSubnormal(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 IsZero(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + public static int LastIndexOf(System.Runtime.Intrinsics.Vector64 vector, T value) { throw null; } + public static int LastIndexOfWhereAllBitsSet(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 Lerp(System.Runtime.Intrinsics.Vector64 x, System.Runtime.Intrinsics.Vector64 y, System.Runtime.Intrinsics.Vector64 amount) { throw null; } public static System.Runtime.Intrinsics.Vector64 Lerp(System.Runtime.Intrinsics.Vector64 x, System.Runtime.Intrinsics.Vector64 y, System.Runtime.Intrinsics.Vector64 amount) { throw null; } public static bool LessThanAll(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) { throw null; } @@ -1352,6 +1430,8 @@ public static void CopyTo(this System.Runtime.Intrinsics.Vector64 vector, [System.CLSCompliantAttribute(false)] public static System.Runtime.Intrinsics.Vector64 Narrow(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector64 upper) { throw null; } public static System.Runtime.Intrinsics.Vector64 Negate(System.Runtime.Intrinsics.Vector64 vector) { throw null; } + public static bool None(System.Runtime.Intrinsics.Vector64 vector, T value) { throw null; } + public static bool NoneWhereAllBitsSet(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 OnesComplement(System.Runtime.Intrinsics.Vector64 vector) { throw null; } public static System.Runtime.Intrinsics.Vector64 RadiansToDegrees(System.Runtime.Intrinsics.Vector64 radians) { throw null; } public static System.Runtime.Intrinsics.Vector64 RadiansToDegrees(System.Runtime.Intrinsics.Vector64 radians) { throw null; } diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs index 09153068d91439..7163c17c8f8c17 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs +++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs @@ -4,6 +4,7 @@ using System.Diagnostics.CodeAnalysis; using System.Numerics; using System.Reflection; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Tests; using Xunit; @@ -4505,9 +4506,9 @@ public void Vector128DoubleEqualsNonCanonicalNaNTest() }; // all Vector NaNs .Equals compare the same, but == compare as different - foreach(var i in nans) + foreach (var i in nans) { - foreach(var j in nans) + foreach (var j in nans) { Assert.True(Vector128.Create(i).Equals(Vector128.Create(j))); Assert.False(Vector128.Create(i) == Vector128.Create(j)); @@ -4529,9 +4530,9 @@ public void Vector128SingleEqualsNonCanonicalNaNTest() }; // all Vector NaNs .Equals compare the same, but == compare as different - foreach(var i in nans) + foreach (var i in nans) { - foreach(var j in nans) + foreach (var j in nans) { Assert.True(Vector128.Create(i).Equals(Vector128.Create(j))); Assert.False(Vector128.Create(i) == Vector128.Create(j)); @@ -5066,76 +5067,604 @@ public void HypotSingleTest(float x, float y, float expectedResult, float varian AssertEqual(Vector128.Create(expectedResult), Vector128.Hypot(Vector128.Create(+y), Vector128.Create(+x)), Vector128.Create(variance)); } + private void IsEvenInteger(T value) + where T : INumber + { + Assert.Equal(T.IsEvenInteger(value) ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsEvenInteger(Vector128.Create(value))); + } + [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsNaNDouble), MemberType = typeof(GenericMathTestMemberData))] - public void IsNaNDoubleTest(double value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerByteTest(byte value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerDoubleTest(double value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerInt16Test(short value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerInt32Test(int value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerInt64Test(long value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerSByteTest(sbyte value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerSingleTest(float value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerUInt16Test(ushort value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerUInt32Test(uint value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerUInt64Test(ulong value) => IsEvenInteger(value); + + private void IsFinite(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsNaN(Vector128.Create(value))); + Assert.Equal(T.IsFinite(value) ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsFinite(Vector128.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsNaNSingle), MemberType = typeof(GenericMathTestMemberData))] - public void IsNaNSingleTest(float value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteByteTest(byte value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteDoubleTest(double value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteInt16Test(short value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteInt32Test(int value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteInt64Test(long value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteSByteTest(sbyte value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteSingleTest(float value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteUInt16Test(ushort value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteUInt32Test(uint value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteUInt64Test(ulong value) => IsFinite(value); + + private void IsInfinity(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsNaN(Vector128.Create(value))); + Assert.Equal(T.IsInfinity(value) ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsInfinity(Vector128.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsNegativeDouble), MemberType = typeof(GenericMathTestMemberData))] - public void IsNegativeDoubleTest(double value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityByteTest(byte value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityDoubleTest(double value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityInt16Test(short value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityInt32Test(int value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityInt64Test(long value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinitySByteTest(sbyte value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinitySingleTest(float value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityUInt16Test(ushort value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityUInt32Test(uint value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityUInt64Test(ulong value) => IsInfinity(value); + + private void IsInteger(T value) + where T : INumber + { + Assert.Equal(T.IsInteger(value) ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsInteger(Vector128.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerByteTest(byte value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerDoubleTest(double value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerInt16Test(short value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerInt32Test(int value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerInt64Test(long value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerSByteTest(sbyte value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerSingleTest(float value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerUInt16Test(ushort value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerUInt32Test(uint value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerUInt64Test(ulong value) => IsInteger(value); + + private void IsNaN(T value) + where T : INumber + { + Assert.Equal(T.IsNaN(value) ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsNaN(Vector128.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNByteTest(byte value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNDoubleTest(double value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNInt16Test(short value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNInt32Test(int value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNInt64Test(long value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNSByteTest(sbyte value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNSingleTest(float value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNUInt16Test(ushort value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNUInt32Test(uint value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNUInt64Test(ulong value) => IsNaN(value); + + private void IsNegative(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsNegative(Vector128.Create(value))); + Assert.Equal(T.IsNegative(value) ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsNegative(Vector128.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsNegativeSingle), MemberType = typeof(GenericMathTestMemberData))] - public void IsNegativeSingleTest(float value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeByteTest(byte value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeDoubleTest(double value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInt16Test(short value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInt32Test(int value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInt64Test(long value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeSByteTest(sbyte value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeSingleTest(float value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeUInt16Test(ushort value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeUInt32Test(uint value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeUInt64Test(ulong value) => IsNegative(value); + + private void IsNegativeInfinity(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsNegative(Vector128.Create(value))); + Assert.Equal(T.IsNegativeInfinity(value) ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsNegativeInfinity(Vector128.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsPositiveDouble), MemberType = typeof(GenericMathTestMemberData))] - public void IsPositiveDoubleTest(double value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityByteTest(byte value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityDoubleTest(double value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityInt16Test(short value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityInt32Test(int value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityInt64Test(long value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinitySByteTest(sbyte value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinitySingleTest(float value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityUInt16Test(ushort value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityUInt32Test(uint value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityUInt64Test(ulong value) => IsNegativeInfinity(value); + + private void IsNormal(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsPositive(Vector128.Create(value))); + Assert.Equal(T.IsNormal(value) ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsNormal(Vector128.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsPositiveSingle), MemberType = typeof(GenericMathTestMemberData))] - public void IsPositiveSingleTest(float value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalByteTest(byte value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalDoubleTest(double value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalInt16Test(short value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalInt32Test(int value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalInt64Test(long value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalSByteTest(sbyte value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalSingleTest(float value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalUInt16Test(ushort value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalUInt32Test(uint value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalUInt64Test(ulong value) => IsNormal(value); + + private void IsOddInteger(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsPositive(Vector128.Create(value))); + Assert.Equal(T.IsOddInteger(value) ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsOddInteger(Vector128.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsPositiveInfinityDouble), MemberType = typeof(GenericMathTestMemberData))] - public void IsPositiveInfinityDoubleTest(double value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerByteTest(byte value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerDoubleTest(double value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerInt16Test(short value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerInt32Test(int value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerInt64Test(long value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerSByteTest(sbyte value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerSingleTest(float value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerUInt16Test(ushort value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerUInt32Test(uint value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerUInt64Test(ulong value) => IsOddInteger(value); + + private void IsPositive(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsPositiveInfinity(Vector128.Create(value))); + Assert.Equal(T.IsPositive(value) ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsPositive(Vector128.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsPositiveInfinitySingle), MemberType = typeof(GenericMathTestMemberData))] - public void IsPositiveInfinitySingleTest(float value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveByteTest(byte value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveDoubleTest(double value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInt16Test(short value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInt32Test(int value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInt64Test(long value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveSByteTest(sbyte value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveSingleTest(float value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveUInt16Test(ushort value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveUInt32Test(uint value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveUInt64Test(ulong value) => IsPositive(value); + + private void IsPositiveInfinity(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsPositiveInfinity(Vector128.Create(value))); + Assert.Equal(T.IsPositiveInfinity(value) ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsPositiveInfinity(Vector128.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsZeroDouble), MemberType = typeof(GenericMathTestMemberData))] - public void IsZeroDoubleTest(double value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityByteTest(byte value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityDoubleTest(double value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityInt16Test(short value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityInt32Test(int value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityInt64Test(long value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinitySByteTest(sbyte value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinitySingleTest(float value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityUInt16Test(ushort value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityUInt32Test(uint value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityUInt64Test(ulong value) => IsPositiveInfinity(value); + + private void IsSubnormal(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsZero(Vector128.Create(value))); + Assert.Equal(T.IsSubnormal(value) ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsSubnormal(Vector128.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsZeroSingle), MemberType = typeof(GenericMathTestMemberData))] - public void IsZeroSingleTest(float value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalByteTest(byte value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalDoubleTest(double value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalInt16Test(short value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalInt32Test(int value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalInt64Test(long value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalSByteTest(sbyte value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalSingleTest(float value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalUInt16Test(ushort value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalUInt32Test(uint value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalUInt64Test(ulong value) => IsSubnormal(value); + + private void IsZero(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsZero(Vector128.Create(value))); + Assert.Equal(T.IsZero(value) ? Vector128.AllBitsSet : Vector128.Zero, Vector128.IsZero(Vector128.Create(value))); } + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroByteTest(byte value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroDoubleTest(double value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroInt16Test(short value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroInt32Test(int value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroInt64Test(long value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroSByteTest(sbyte value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroSingleTest(float value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroUInt16Test(ushort value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroUInt32Test(uint value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroUInt64Test(ulong value) => IsZero(value); + [Theory] [MemberData(nameof(GenericMathTestMemberData.LerpDouble), MemberType = typeof(GenericMathTestMemberData))] public void LerpDoubleTest(double x, double y, double amount, double expectedResult) @@ -5393,5 +5922,275 @@ public void TruncateSingleTest(float value, float expectedResult) Vector128 actualResult = Vector128.Truncate(Vector128.Create(value)); AssertEqual(Vector128.Create(expectedResult), actualResult, Vector128.Zero); } + + [MethodImpl(MethodImplOptions.NoInlining)] + private void AllAnyNoneTest(T value1, T value2) + where T : struct, INumber + { + var input1 = Vector128.Create(value1); + var input2 = Vector128.Create(value2); + + Assert.True(Vector128.All(input1, value1)); + Assert.True(Vector128.All(input2, value2)); + Assert.False(Vector128.All(input1.WithElement(0, value2), value1)); + Assert.False(Vector128.All(input2.WithElement(0, value1), value2)); + Assert.False(Vector128.All(input1, value2)); + Assert.False(Vector128.All(input2, value1)); + Assert.False(Vector128.All(input1.WithElement(0, value2), value2)); + Assert.False(Vector128.All(input2.WithElement(0, value1), value1)); + + Assert.True(Vector128.Any(input1, value1)); + Assert.True(Vector128.Any(input2, value2)); + Assert.True(Vector128.Any(input1.WithElement(0, value2), value1)); + Assert.True(Vector128.Any(input2.WithElement(0, value1), value2)); + Assert.False(Vector128.Any(input1, value2)); + Assert.False(Vector128.Any(input2, value1)); + Assert.True(Vector128.Any(input1.WithElement(0, value2), value2)); + Assert.True(Vector128.Any(input2.WithElement(0, value1), value1)); + + Assert.False(Vector128.None(input1, value1)); + Assert.False(Vector128.None(input2, value2)); + Assert.False(Vector128.None(input1.WithElement(0, value2), value1)); + Assert.False(Vector128.None(input2.WithElement(0, value1), value2)); + Assert.True(Vector128.None(input1, value2)); + Assert.True(Vector128.None(input2, value1)); + Assert.False(Vector128.None(input1.WithElement(0, value2), value2)); + Assert.False(Vector128.None(input2.WithElement(0, value1), value1)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private void AllAnyNoneTest_IFloatingPointIeee754(T value) + where T : struct, IFloatingPointIeee754 + { + var input = Vector128.Create(value); + + Assert.False(Vector128.All(input, value)); + Assert.False(Vector128.Any(input, value)); + Assert.True(Vector128.None(input, value)); + } + + [Fact] + public void AllAnyNoneByteTest() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneDoubleTest() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneDoubleTest_AllBitsSet() => AllAnyNoneTest_IFloatingPointIeee754(BitConverter.Int64BitsToDouble(-1)); + + [Fact] + public void AllAnyNoneInt16Test() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneInt32Test() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneInt64Test() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneSByteTest() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneSingleTest() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneSingleTest_AllBitsSet() => AllAnyNoneTest_IFloatingPointIeee754(BitConverter.Int32BitsToSingle(-1)); + + [Fact] + public void AllAnyNoneUInt16Test() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneUInt32Test() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneUInt64Test() => AllAnyNoneTest(3, 2); + + [MethodImpl(MethodImplOptions.NoInlining)] + private void AllAnyNoneWhereAllBitsSetTest(T allBitsSet, T value2) + where T : struct, INumber + { + var input1 = Vector128.Create(allBitsSet); + var input2 = Vector128.Create(value2); + + Assert.True(Vector128.AllWhereAllBitsSet(input1)); + Assert.False(Vector128.AllWhereAllBitsSet(input2)); + Assert.False(Vector128.AllWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.False(Vector128.AllWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.True(Vector128.AnyWhereAllBitsSet(input1)); + Assert.False(Vector128.AnyWhereAllBitsSet(input2)); + Assert.True(Vector128.AnyWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.True(Vector128.AnyWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.False(Vector128.NoneWhereAllBitsSet(input1)); + Assert.True(Vector128.NoneWhereAllBitsSet(input2)); + Assert.False(Vector128.NoneWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.False(Vector128.NoneWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + } + + [Fact] + public void AllAnyNoneWhereAllBitsSetByteTest() => AllAnyNoneWhereAllBitsSetTest(byte.MaxValue, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetDoubleTest() => AllAnyNoneWhereAllBitsSetTest(BitConverter.Int64BitsToDouble(-1), 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetInt16Test() => AllAnyNoneWhereAllBitsSetTest(-1, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetInt32Test() => AllAnyNoneWhereAllBitsSetTest(-1, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetInt64Test() => AllAnyNoneWhereAllBitsSetTest(-1, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetSByteTest() => AllAnyNoneWhereAllBitsSetTest(-1, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetSingleTest() => AllAnyNoneWhereAllBitsSetTest(BitConverter.Int32BitsToSingle(-1), 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetUInt16Test() => AllAnyNoneWhereAllBitsSetTest(ushort.MaxValue, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetUInt32Test() => AllAnyNoneWhereAllBitsSetTest(uint.MaxValue, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetUInt64Test() => AllAnyNoneWhereAllBitsSetTest(ulong.MaxValue, 2); + + [MethodImpl(MethodImplOptions.NoInlining)] + private void CountIndexOfLastIndexOfTest(T value1, T value2) + where T : struct, INumber + { + var input1 = Vector128.Create(value1); + var input2 = Vector128.Create(value2); + + Assert.Equal(Vector128.Count, Vector128.Count(input1, value1)); + Assert.Equal(Vector128.Count, Vector128.Count(input2, value2)); + Assert.Equal(Vector128.Count - 1, Vector128.Count(input1.WithElement(0, value2), value1)); + Assert.Equal(Vector128.Count - 1, Vector128.Count(input2.WithElement(0, value1), value2)); + Assert.Equal(0, Vector128.Count(input1, value2)); + Assert.Equal(0, Vector128.Count(input2, value1)); + Assert.Equal(1, Vector128.Count(input1.WithElement(0, value2), value2)); + Assert.Equal(1, Vector128.Count(input2.WithElement(0, value1), value1)); + + Assert.Equal(0, Vector128.IndexOf(input1, value1)); + Assert.Equal(0, Vector128.IndexOf(input2, value2)); + Assert.Equal(1, Vector128.IndexOf(input1.WithElement(0, value2), value1)); + Assert.Equal(1, Vector128.IndexOf(input2.WithElement(0, value1), value2)); + Assert.Equal(-1, Vector128.IndexOf(input1, value2)); + Assert.Equal(-1, Vector128.IndexOf(input2, value1)); + Assert.Equal(0, Vector128.IndexOf(input1.WithElement(0, value2), value2)); + Assert.Equal(0, Vector128.IndexOf(input2.WithElement(0, value1), value1)); + + Assert.Equal(Vector128.Count - 1, Vector128.LastIndexOf(input1, value1)); + Assert.Equal(Vector128.Count - 1, Vector128.LastIndexOf(input2, value2)); + Assert.Equal(Vector128.Count - 1, Vector128.LastIndexOf(input1.WithElement(0, value2), value1)); + Assert.Equal(Vector128.Count - 1, Vector128.LastIndexOf(input2.WithElement(0, value1), value2)); + Assert.Equal(-1, Vector128.LastIndexOf(input1, value2)); + Assert.Equal(-1, Vector128.LastIndexOf(input2, value1)); + Assert.Equal(0, Vector128.LastIndexOf(input1.WithElement(0, value2), value2)); + Assert.Equal(0, Vector128.LastIndexOf(input2.WithElement(0, value1), value1)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private void CountIndexOfLastIndexOfTest_IFloatingPointIeee754(T value) + where T : struct, IFloatingPointIeee754 + { + var input = Vector128.Create(value); + + Assert.Equal(0, Vector128.Count(input, value)); + Assert.Equal(-1, Vector128.IndexOf(input, value)); + Assert.Equal(-1, Vector128.LastIndexOf(input, value)); + } + + [Fact] + public void CountIndexOfLastIndexOfByteTest() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfDoubleTest() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfDoubleTest_AllBitsSet() => CountIndexOfLastIndexOfTest_IFloatingPointIeee754(BitConverter.Int64BitsToDouble(-1)); + + [Fact] + public void CountIndexOfLastIndexOfInt16Test() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfInt32Test() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfInt64Test() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfSByteTest() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfSingleTest() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfSingleTest_AllBitsSet() => CountIndexOfLastIndexOfTest_IFloatingPointIeee754(BitConverter.Int32BitsToSingle(-1)); + + [Fact] + public void CountIndexOfLastIndexOfUInt16Test() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfUInt32Test() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfUInt64Test() => CountIndexOfLastIndexOfTest(3, 2); + + [MethodImpl(MethodImplOptions.NoInlining)] + private void CountIndexOfLastIndexOfWhereAllBitsSetTest(T allBitsSet, T value2) + where T : struct, INumber + { + var input1 = Vector128.Create(allBitsSet); + var input2 = Vector128.Create(value2); + + Assert.Equal(Vector128.Count, Vector128.CountWhereAllBitsSet(input1)); + Assert.Equal(0, Vector128.CountWhereAllBitsSet(input2)); + Assert.Equal(Vector128.Count - 1, Vector128.CountWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.Equal(1, Vector128.CountWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.Equal(0, Vector128.IndexOfWhereAllBitsSet(input1)); + Assert.Equal(-1, Vector128.IndexOfWhereAllBitsSet(input2)); + Assert.Equal(1, Vector128.IndexOfWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.Equal(0, Vector128.IndexOfWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.Equal(Vector128.Count - 1, Vector128.LastIndexOfWhereAllBitsSet(input1)); + Assert.Equal(-1, Vector128.LastIndexOfWhereAllBitsSet(input2)); + Assert.Equal(Vector128.Count - 1, Vector128.LastIndexOfWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.Equal(0, Vector128.LastIndexOfWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + } + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetByteTest() => CountIndexOfLastIndexOfWhereAllBitsSetTest(byte.MaxValue, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetDoubleTest() => CountIndexOfLastIndexOfWhereAllBitsSetTest(BitConverter.Int64BitsToDouble(-1), 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetInt16Test() => CountIndexOfLastIndexOfWhereAllBitsSetTest(-1, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetInt32Test() => CountIndexOfLastIndexOfWhereAllBitsSetTest(-1, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetInt64Test() => CountIndexOfLastIndexOfWhereAllBitsSetTest(-1, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetSByteTest() => CountIndexOfLastIndexOfWhereAllBitsSetTest(-1, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetSingleTest() => CountIndexOfLastIndexOfWhereAllBitsSetTest(BitConverter.Int32BitsToSingle(-1), 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetUInt16Test() => CountIndexOfLastIndexOfWhereAllBitsSetTest(ushort.MaxValue, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetUInt32Test() => CountIndexOfLastIndexOfWhereAllBitsSetTest(uint.MaxValue, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetUInt64Test() => CountIndexOfLastIndexOfWhereAllBitsSetTest(ulong.MaxValue, 2); } } diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs index d16e5eed481809..30c92e16c12b4c 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs +++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs @@ -3,8 +3,8 @@ using System.Numerics; using System.Reflection; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using System.Runtime.Intrinsics.X86; using System.Tests; using Xunit; @@ -5529,9 +5529,9 @@ public void Vector256DoubleEqualsNonCanonicalNaNTest() }; // all Vector NaNs .Equals compare the same, but == compare as different - foreach(var i in nans) + foreach (var i in nans) { - foreach(var j in nans) + foreach (var j in nans) { Assert.True(Vector256.Create(i).Equals(Vector256.Create(j))); Assert.False(Vector256.Create(i) == Vector256.Create(j)); @@ -5553,9 +5553,9 @@ public void Vector256SingleEqualsNonCanonicalNaNTest() }; // all Vector NaNs .Equals compare the same, but == compare as different - foreach(var i in nans) + foreach (var i in nans) { - foreach(var j in nans) + foreach (var j in nans) { Assert.True(Vector256.Create(i).Equals(Vector256.Create(j))); Assert.False(Vector256.Create(i) == Vector256.Create(j)); @@ -6083,76 +6083,604 @@ public void HypotSingleTest(float x, float y, float expectedResult, float varian AssertEqual(Vector256.Create(expectedResult), Vector256.Hypot(Vector256.Create(+y), Vector256.Create(+x)), Vector256.Create(variance)); } + private void IsEvenInteger(T value) + where T : INumber + { + Assert.Equal(T.IsEvenInteger(value) ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsEvenInteger(Vector256.Create(value))); + } + [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsNaNDouble), MemberType = typeof(GenericMathTestMemberData))] - public void IsNaNDoubleTest(double value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerByteTest(byte value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerDoubleTest(double value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerInt16Test(short value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerInt32Test(int value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerInt64Test(long value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerSByteTest(sbyte value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerSingleTest(float value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerUInt16Test(ushort value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerUInt32Test(uint value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerUInt64Test(ulong value) => IsEvenInteger(value); + + private void IsFinite(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsNaN(Vector256.Create(value))); + Assert.Equal(T.IsFinite(value) ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsFinite(Vector256.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsNaNSingle), MemberType = typeof(GenericMathTestMemberData))] - public void IsNaNSingleTest(float value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteByteTest(byte value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteDoubleTest(double value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteInt16Test(short value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteInt32Test(int value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteInt64Test(long value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteSByteTest(sbyte value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteSingleTest(float value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteUInt16Test(ushort value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteUInt32Test(uint value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteUInt64Test(ulong value) => IsFinite(value); + + private void IsInfinity(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsNaN(Vector256.Create(value))); + Assert.Equal(T.IsInfinity(value) ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsInfinity(Vector256.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsNegativeDouble), MemberType = typeof(GenericMathTestMemberData))] - public void IsNegativeDoubleTest(double value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityByteTest(byte value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityDoubleTest(double value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityInt16Test(short value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityInt32Test(int value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityInt64Test(long value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinitySByteTest(sbyte value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinitySingleTest(float value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityUInt16Test(ushort value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityUInt32Test(uint value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityUInt64Test(ulong value) => IsInfinity(value); + + private void IsInteger(T value) + where T : INumber + { + Assert.Equal(T.IsInteger(value) ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsInteger(Vector256.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerByteTest(byte value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerDoubleTest(double value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerInt16Test(short value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerInt32Test(int value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerInt64Test(long value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerSByteTest(sbyte value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerSingleTest(float value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerUInt16Test(ushort value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerUInt32Test(uint value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerUInt64Test(ulong value) => IsInteger(value); + + private void IsNaN(T value) + where T : INumber + { + Assert.Equal(T.IsNaN(value) ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsNaN(Vector256.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNByteTest(byte value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNDoubleTest(double value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNInt16Test(short value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNInt32Test(int value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNInt64Test(long value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNSByteTest(sbyte value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNSingleTest(float value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNUInt16Test(ushort value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNUInt32Test(uint value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNUInt64Test(ulong value) => IsNaN(value); + + private void IsNegative(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsNegative(Vector256.Create(value))); + Assert.Equal(T.IsNegative(value) ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsNegative(Vector256.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsNegativeSingle), MemberType = typeof(GenericMathTestMemberData))] - public void IsNegativeSingleTest(float value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeByteTest(byte value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeDoubleTest(double value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInt16Test(short value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInt32Test(int value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInt64Test(long value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeSByteTest(sbyte value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeSingleTest(float value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeUInt16Test(ushort value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeUInt32Test(uint value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeUInt64Test(ulong value) => IsNegative(value); + + private void IsNegativeInfinity(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsNegative(Vector256.Create(value))); + Assert.Equal(T.IsNegativeInfinity(value) ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsNegativeInfinity(Vector256.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsPositiveDouble), MemberType = typeof(GenericMathTestMemberData))] - public void IsPositiveDoubleTest(double value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityByteTest(byte value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityDoubleTest(double value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityInt16Test(short value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityInt32Test(int value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityInt64Test(long value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinitySByteTest(sbyte value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinitySingleTest(float value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityUInt16Test(ushort value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityUInt32Test(uint value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityUInt64Test(ulong value) => IsNegativeInfinity(value); + + private void IsNormal(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsPositive(Vector256.Create(value))); + Assert.Equal(T.IsNormal(value) ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsNormal(Vector256.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsPositiveSingle), MemberType = typeof(GenericMathTestMemberData))] - public void IsPositiveSingleTest(float value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalByteTest(byte value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalDoubleTest(double value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalInt16Test(short value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalInt32Test(int value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalInt64Test(long value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalSByteTest(sbyte value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalSingleTest(float value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalUInt16Test(ushort value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalUInt32Test(uint value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalUInt64Test(ulong value) => IsNormal(value); + + private void IsOddInteger(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsPositive(Vector256.Create(value))); + Assert.Equal(T.IsOddInteger(value) ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsOddInteger(Vector256.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsPositiveInfinityDouble), MemberType = typeof(GenericMathTestMemberData))] - public void IsPositiveInfinityDoubleTest(double value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerByteTest(byte value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerDoubleTest(double value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerInt16Test(short value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerInt32Test(int value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerInt64Test(long value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerSByteTest(sbyte value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerSingleTest(float value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerUInt16Test(ushort value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerUInt32Test(uint value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerUInt64Test(ulong value) => IsOddInteger(value); + + private void IsPositive(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsPositiveInfinity(Vector256.Create(value))); + Assert.Equal(T.IsPositive(value) ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsPositive(Vector256.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsPositiveInfinitySingle), MemberType = typeof(GenericMathTestMemberData))] - public void IsPositiveInfinitySingleTest(float value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveByteTest(byte value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveDoubleTest(double value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInt16Test(short value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInt32Test(int value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInt64Test(long value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveSByteTest(sbyte value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveSingleTest(float value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveUInt16Test(ushort value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveUInt32Test(uint value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveUInt64Test(ulong value) => IsPositive(value); + + private void IsPositiveInfinity(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsPositiveInfinity(Vector256.Create(value))); + Assert.Equal(T.IsPositiveInfinity(value) ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsPositiveInfinity(Vector256.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsZeroDouble), MemberType = typeof(GenericMathTestMemberData))] - public void IsZeroDoubleTest(double value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityByteTest(byte value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityDoubleTest(double value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityInt16Test(short value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityInt32Test(int value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityInt64Test(long value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinitySByteTest(sbyte value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinitySingleTest(float value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityUInt16Test(ushort value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityUInt32Test(uint value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityUInt64Test(ulong value) => IsPositiveInfinity(value); + + private void IsSubnormal(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsZero(Vector256.Create(value))); + Assert.Equal(T.IsSubnormal(value) ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsSubnormal(Vector256.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsZeroSingle), MemberType = typeof(GenericMathTestMemberData))] - public void IsZeroSingleTest(float value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalByteTest(byte value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalDoubleTest(double value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalInt16Test(short value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalInt32Test(int value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalInt64Test(long value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalSByteTest(sbyte value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalSingleTest(float value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalUInt16Test(ushort value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalUInt32Test(uint value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalUInt64Test(ulong value) => IsSubnormal(value); + + private void IsZero(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsZero(Vector256.Create(value))); + Assert.Equal(T.IsZero(value) ? Vector256.AllBitsSet : Vector256.Zero, Vector256.IsZero(Vector256.Create(value))); } + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroByteTest(byte value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroDoubleTest(double value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroInt16Test(short value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroInt32Test(int value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroInt64Test(long value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroSByteTest(sbyte value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroSingleTest(float value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroUInt16Test(ushort value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroUInt32Test(uint value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroUInt64Test(ulong value) => IsZero(value); + [Theory] [MemberData(nameof(GenericMathTestMemberData.LerpDouble), MemberType = typeof(GenericMathTestMemberData))] public void LerpDoubleTest(double x, double y, double amount, double expectedResult) @@ -6410,5 +6938,275 @@ public void TruncateSingleTest(float value, float expectedResult) Vector256 actualResult = Vector256.Truncate(Vector256.Create(value)); AssertEqual(Vector256.Create(expectedResult), actualResult, Vector256.Zero); } + + [MethodImpl(MethodImplOptions.NoInlining)] + private void AllAnyNoneTest(T value1, T value2) + where T : struct, INumber + { + var input1 = Vector256.Create(value1); + var input2 = Vector256.Create(value2); + + Assert.True(Vector256.All(input1, value1)); + Assert.True(Vector256.All(input2, value2)); + Assert.False(Vector256.All(input1.WithElement(0, value2), value1)); + Assert.False(Vector256.All(input2.WithElement(0, value1), value2)); + Assert.False(Vector256.All(input1, value2)); + Assert.False(Vector256.All(input2, value1)); + Assert.False(Vector256.All(input1.WithElement(0, value2), value2)); + Assert.False(Vector256.All(input2.WithElement(0, value1), value1)); + + Assert.True(Vector256.Any(input1, value1)); + Assert.True(Vector256.Any(input2, value2)); + Assert.True(Vector256.Any(input1.WithElement(0, value2), value1)); + Assert.True(Vector256.Any(input2.WithElement(0, value1), value2)); + Assert.False(Vector256.Any(input1, value2)); + Assert.False(Vector256.Any(input2, value1)); + Assert.True(Vector256.Any(input1.WithElement(0, value2), value2)); + Assert.True(Vector256.Any(input2.WithElement(0, value1), value1)); + + Assert.False(Vector256.None(input1, value1)); + Assert.False(Vector256.None(input2, value2)); + Assert.False(Vector256.None(input1.WithElement(0, value2), value1)); + Assert.False(Vector256.None(input2.WithElement(0, value1), value2)); + Assert.True(Vector256.None(input1, value2)); + Assert.True(Vector256.None(input2, value1)); + Assert.False(Vector256.None(input1.WithElement(0, value2), value2)); + Assert.False(Vector256.None(input2.WithElement(0, value1), value1)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private void AllAnyNoneTest_IFloatingPointIeee754(T value) + where T : struct, IFloatingPointIeee754 + { + var input = Vector256.Create(value); + + Assert.False(Vector256.All(input, value)); + Assert.False(Vector256.Any(input, value)); + Assert.True(Vector256.None(input, value)); + } + + [Fact] + public void AllAnyNoneByteTest() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneDoubleTest() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneDoubleTest_AllBitsSet() => AllAnyNoneTest_IFloatingPointIeee754(BitConverter.Int64BitsToDouble(-1)); + + [Fact] + public void AllAnyNoneInt16Test() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneInt32Test() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneInt64Test() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneSByteTest() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneSingleTest() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneSingleTest_AllBitsSet() => AllAnyNoneTest_IFloatingPointIeee754(BitConverter.Int32BitsToSingle(-1)); + + [Fact] + public void AllAnyNoneUInt16Test() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneUInt32Test() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneUInt64Test() => AllAnyNoneTest(3, 2); + + [MethodImpl(MethodImplOptions.NoInlining)] + private void AllAnyNoneWhereAllBitsSetTest(T allBitsSet, T value2) + where T : struct, INumber + { + var input1 = Vector256.Create(allBitsSet); + var input2 = Vector256.Create(value2); + + Assert.True(Vector256.AllWhereAllBitsSet(input1)); + Assert.False(Vector256.AllWhereAllBitsSet(input2)); + Assert.False(Vector256.AllWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.False(Vector256.AllWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.True(Vector256.AnyWhereAllBitsSet(input1)); + Assert.False(Vector256.AnyWhereAllBitsSet(input2)); + Assert.True(Vector256.AnyWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.True(Vector256.AnyWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.False(Vector256.NoneWhereAllBitsSet(input1)); + Assert.True(Vector256.NoneWhereAllBitsSet(input2)); + Assert.False(Vector256.NoneWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.False(Vector256.NoneWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + } + + [Fact] + public void AllAnyNoneWhereAllBitsSetByteTest() => AllAnyNoneWhereAllBitsSetTest(byte.MaxValue, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetDoubleTest() => AllAnyNoneWhereAllBitsSetTest(BitConverter.Int64BitsToDouble(-1), 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetInt16Test() => AllAnyNoneWhereAllBitsSetTest(-1, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetInt32Test() => AllAnyNoneWhereAllBitsSetTest(-1, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetInt64Test() => AllAnyNoneWhereAllBitsSetTest(-1, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetSByteTest() => AllAnyNoneWhereAllBitsSetTest(-1, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetSingleTest() => AllAnyNoneWhereAllBitsSetTest(BitConverter.Int32BitsToSingle(-1), 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetUInt16Test() => AllAnyNoneWhereAllBitsSetTest(ushort.MaxValue, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetUInt32Test() => AllAnyNoneWhereAllBitsSetTest(uint.MaxValue, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetUInt64Test() => AllAnyNoneWhereAllBitsSetTest(ulong.MaxValue, 2); + + [MethodImpl(MethodImplOptions.NoInlining)] + private void CountIndexOfLastIndexOfTest(T value1, T value2) + where T : struct, INumber + { + var input1 = Vector256.Create(value1); + var input2 = Vector256.Create(value2); + + Assert.Equal(Vector256.Count, Vector256.Count(input1, value1)); + Assert.Equal(Vector256.Count, Vector256.Count(input2, value2)); + Assert.Equal(Vector256.Count - 1, Vector256.Count(input1.WithElement(0, value2), value1)); + Assert.Equal(Vector256.Count - 1, Vector256.Count(input2.WithElement(0, value1), value2)); + Assert.Equal(0, Vector256.Count(input1, value2)); + Assert.Equal(0, Vector256.Count(input2, value1)); + Assert.Equal(1, Vector256.Count(input1.WithElement(0, value2), value2)); + Assert.Equal(1, Vector256.Count(input2.WithElement(0, value1), value1)); + + Assert.Equal(0, Vector256.IndexOf(input1, value1)); + Assert.Equal(0, Vector256.IndexOf(input2, value2)); + Assert.Equal(1, Vector256.IndexOf(input1.WithElement(0, value2), value1)); + Assert.Equal(1, Vector256.IndexOf(input2.WithElement(0, value1), value2)); + Assert.Equal(-1, Vector256.IndexOf(input1, value2)); + Assert.Equal(-1, Vector256.IndexOf(input2, value1)); + Assert.Equal(0, Vector256.IndexOf(input1.WithElement(0, value2), value2)); + Assert.Equal(0, Vector256.IndexOf(input2.WithElement(0, value1), value1)); + + Assert.Equal(Vector256.Count - 1, Vector256.LastIndexOf(input1, value1)); + Assert.Equal(Vector256.Count - 1, Vector256.LastIndexOf(input2, value2)); + Assert.Equal(Vector256.Count - 1, Vector256.LastIndexOf(input1.WithElement(0, value2), value1)); + Assert.Equal(Vector256.Count - 1, Vector256.LastIndexOf(input2.WithElement(0, value1), value2)); + Assert.Equal(-1, Vector256.LastIndexOf(input1, value2)); + Assert.Equal(-1, Vector256.LastIndexOf(input2, value1)); + Assert.Equal(0, Vector256.LastIndexOf(input1.WithElement(0, value2), value2)); + Assert.Equal(0, Vector256.LastIndexOf(input2.WithElement(0, value1), value1)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private void CountIndexOfLastIndexOfTest_IFloatingPointIeee754(T value) + where T : struct, IFloatingPointIeee754 + { + var input = Vector256.Create(value); + + Assert.Equal(0, Vector256.Count(input, value)); + Assert.Equal(-1, Vector256.IndexOf(input, value)); + Assert.Equal(-1, Vector256.LastIndexOf(input, value)); + } + + [Fact] + public void CountIndexOfLastIndexOfByteTest() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfDoubleTest() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfDoubleTest_AllBitsSet() => CountIndexOfLastIndexOfTest_IFloatingPointIeee754(BitConverter.Int64BitsToDouble(-1)); + + [Fact] + public void CountIndexOfLastIndexOfInt16Test() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfInt32Test() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfInt64Test() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfSByteTest() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfSingleTest() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfSingleTest_AllBitsSet() => CountIndexOfLastIndexOfTest_IFloatingPointIeee754(BitConverter.Int32BitsToSingle(-1)); + + [Fact] + public void CountIndexOfLastIndexOfUInt16Test() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfUInt32Test() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfUInt64Test() => CountIndexOfLastIndexOfTest(3, 2); + + [MethodImpl(MethodImplOptions.NoInlining)] + private void CountIndexOfLastIndexOfWhereAllBitsSetTest(T allBitsSet, T value2) + where T : struct, INumber + { + var input1 = Vector256.Create(allBitsSet); + var input2 = Vector256.Create(value2); + + Assert.Equal(Vector256.Count, Vector256.CountWhereAllBitsSet(input1)); + Assert.Equal(0, Vector256.CountWhereAllBitsSet(input2)); + Assert.Equal(Vector256.Count - 1, Vector256.CountWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.Equal(1, Vector256.CountWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.Equal(0, Vector256.IndexOfWhereAllBitsSet(input1)); + Assert.Equal(-1, Vector256.IndexOfWhereAllBitsSet(input2)); + Assert.Equal(1, Vector256.IndexOfWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.Equal(0, Vector256.IndexOfWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.Equal(Vector256.Count - 1, Vector256.LastIndexOfWhereAllBitsSet(input1)); + Assert.Equal(-1, Vector256.LastIndexOfWhereAllBitsSet(input2)); + Assert.Equal(Vector256.Count - 1, Vector256.LastIndexOfWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.Equal(0, Vector256.LastIndexOfWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + } + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetByteTest() => CountIndexOfLastIndexOfWhereAllBitsSetTest(byte.MaxValue, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetDoubleTest() => CountIndexOfLastIndexOfWhereAllBitsSetTest(BitConverter.Int64BitsToDouble(-1), 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetInt16Test() => CountIndexOfLastIndexOfWhereAllBitsSetTest(-1, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetInt32Test() => CountIndexOfLastIndexOfWhereAllBitsSetTest(-1, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetInt64Test() => CountIndexOfLastIndexOfWhereAllBitsSetTest(-1, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetSByteTest() => CountIndexOfLastIndexOfWhereAllBitsSetTest(-1, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetSingleTest() => CountIndexOfLastIndexOfWhereAllBitsSetTest(BitConverter.Int32BitsToSingle(-1), 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetUInt16Test() => CountIndexOfLastIndexOfWhereAllBitsSetTest(ushort.MaxValue, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetUInt32Test() => CountIndexOfLastIndexOfWhereAllBitsSetTest(uint.MaxValue, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetUInt64Test() => CountIndexOfLastIndexOfWhereAllBitsSetTest(ulong.MaxValue, 2); } } diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs index f996d82369615f..6016fc822a1cab 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs +++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs @@ -3,8 +3,8 @@ using System.Numerics; using System.Reflection; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using System.Runtime.Intrinsics.X86; using System.Tests; using Xunit; @@ -5007,9 +5007,9 @@ public void Vector512DoubleEqualsNonCanonicalNaNTest() }; // all Vector NaNs .Equals compare the same, but == compare as different - foreach(var i in nans) + foreach (var i in nans) { - foreach(var j in nans) + foreach (var j in nans) { Assert.True(Vector512.Create(i).Equals(Vector512.Create(j))); Assert.False(Vector512.Create(i) == Vector512.Create(j)); @@ -5031,9 +5031,9 @@ public void Vector512SingleEqualsNonCanonicalNaNTest() }; // all Vector NaNs .Equals compare the same, but == compare as different - foreach(var i in nans) + foreach (var i in nans) { - foreach(var j in nans) + foreach (var j in nans) { Assert.True(Vector512.Create(i).Equals(Vector512.Create(j))); Assert.False(Vector512.Create(i) == Vector512.Create(j)); @@ -5516,76 +5516,604 @@ public void HypotSingleTest(float x, float y, float expectedResult, float varian AssertEqual(Vector512.Create(expectedResult), Vector512.Hypot(Vector512.Create(+y), Vector512.Create(+x)), Vector512.Create(variance)); } + private void IsEvenInteger(T value) + where T : INumber + { + Assert.Equal(T.IsEvenInteger(value) ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsEvenInteger(Vector512.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerByteTest(byte value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerDoubleTest(double value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerInt16Test(short value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerInt32Test(int value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerInt64Test(long value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerSByteTest(sbyte value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerSingleTest(float value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerUInt16Test(ushort value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerUInt32Test(uint value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerUInt64Test(ulong value) => IsEvenInteger(value); + + private void IsFinite(T value) + where T : INumber + { + Assert.Equal(T.IsFinite(value) ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsFinite(Vector512.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteByteTest(byte value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteDoubleTest(double value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteInt16Test(short value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteInt32Test(int value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteInt64Test(long value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteSByteTest(sbyte value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteSingleTest(float value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteUInt16Test(ushort value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteUInt32Test(uint value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteUInt64Test(ulong value) => IsFinite(value); + + private void IsInfinity(T value) + where T : INumber + { + Assert.Equal(T.IsInfinity(value) ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsInfinity(Vector512.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityByteTest(byte value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityDoubleTest(double value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityInt16Test(short value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityInt32Test(int value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityInt64Test(long value) => IsInfinity(value); + [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsNaNDouble), MemberType = typeof(GenericMathTestMemberData))] - public void IsNaNDoubleTest(double value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinitySByteTest(sbyte value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinitySingleTest(float value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityUInt16Test(ushort value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityUInt32Test(uint value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityUInt64Test(ulong value) => IsInfinity(value); + + private void IsInteger(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsNaN(Vector512.Create(value))); + Assert.Equal(T.IsInteger(value) ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsInteger(Vector512.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsNaNSingle), MemberType = typeof(GenericMathTestMemberData))] - public void IsNaNSingleTest(float value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerByteTest(byte value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerDoubleTest(double value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerInt16Test(short value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerInt32Test(int value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerInt64Test(long value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerSByteTest(sbyte value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerSingleTest(float value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerUInt16Test(ushort value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerUInt32Test(uint value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerUInt64Test(ulong value) => IsInteger(value); + + private void IsNaN(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsNaN(Vector512.Create(value))); + Assert.Equal(T.IsNaN(value) ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsNaN(Vector512.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsNegativeDouble), MemberType = typeof(GenericMathTestMemberData))] - public void IsNegativeDoubleTest(double value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNByteTest(byte value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNDoubleTest(double value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNInt16Test(short value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNInt32Test(int value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNInt64Test(long value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNSByteTest(sbyte value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNSingleTest(float value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNUInt16Test(ushort value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNUInt32Test(uint value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNUInt64Test(ulong value) => IsNaN(value); + + private void IsNegative(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsNegative(Vector512.Create(value))); + Assert.Equal(T.IsNegative(value) ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsNegative(Vector512.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsNegativeSingle), MemberType = typeof(GenericMathTestMemberData))] - public void IsNegativeSingleTest(float value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeByteTest(byte value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeDoubleTest(double value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInt16Test(short value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInt32Test(int value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInt64Test(long value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeSByteTest(sbyte value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeSingleTest(float value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeUInt16Test(ushort value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeUInt32Test(uint value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeUInt64Test(ulong value) => IsNegative(value); + + private void IsNegativeInfinity(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsNegative(Vector512.Create(value))); + Assert.Equal(T.IsNegativeInfinity(value) ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsNegativeInfinity(Vector512.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsPositiveDouble), MemberType = typeof(GenericMathTestMemberData))] - public void IsPositiveDoubleTest(double value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityByteTest(byte value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityDoubleTest(double value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityInt16Test(short value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityInt32Test(int value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityInt64Test(long value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinitySByteTest(sbyte value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinitySingleTest(float value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityUInt16Test(ushort value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityUInt32Test(uint value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityUInt64Test(ulong value) => IsNegativeInfinity(value); + + private void IsNormal(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsPositive(Vector512.Create(value))); + Assert.Equal(T.IsNormal(value) ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsNormal(Vector512.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsPositiveSingle), MemberType = typeof(GenericMathTestMemberData))] - public void IsPositiveSingleTest(float value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalByteTest(byte value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalDoubleTest(double value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalInt16Test(short value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalInt32Test(int value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalInt64Test(long value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalSByteTest(sbyte value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalSingleTest(float value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalUInt16Test(ushort value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalUInt32Test(uint value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalUInt64Test(ulong value) => IsNormal(value); + + private void IsOddInteger(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsPositive(Vector512.Create(value))); + Assert.Equal(T.IsOddInteger(value) ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsOddInteger(Vector512.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsPositiveInfinityDouble), MemberType = typeof(GenericMathTestMemberData))] - public void IsPositiveInfinityDoubleTest(double value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerByteTest(byte value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerDoubleTest(double value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerInt16Test(short value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerInt32Test(int value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerInt64Test(long value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerSByteTest(sbyte value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerSingleTest(float value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerUInt16Test(ushort value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerUInt32Test(uint value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerUInt64Test(ulong value) => IsOddInteger(value); + + private void IsPositive(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsPositiveInfinity(Vector512.Create(value))); + Assert.Equal(T.IsPositive(value) ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsPositive(Vector512.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsPositiveInfinitySingle), MemberType = typeof(GenericMathTestMemberData))] - public void IsPositiveInfinitySingleTest(float value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveByteTest(byte value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveDoubleTest(double value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInt16Test(short value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInt32Test(int value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInt64Test(long value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveSByteTest(sbyte value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveSingleTest(float value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveUInt16Test(ushort value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveUInt32Test(uint value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveUInt64Test(ulong value) => IsPositive(value); + + private void IsPositiveInfinity(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsPositiveInfinity(Vector512.Create(value))); + Assert.Equal(T.IsPositiveInfinity(value) ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsPositiveInfinity(Vector512.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsZeroDouble), MemberType = typeof(GenericMathTestMemberData))] - public void IsZeroDoubleTest(double value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityByteTest(byte value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityDoubleTest(double value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityInt16Test(short value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityInt32Test(int value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityInt64Test(long value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinitySByteTest(sbyte value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinitySingleTest(float value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityUInt16Test(ushort value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityUInt32Test(uint value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityUInt64Test(ulong value) => IsPositiveInfinity(value); + + private void IsSubnormal(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsZero(Vector512.Create(value))); + Assert.Equal(T.IsSubnormal(value) ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsSubnormal(Vector512.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsZeroSingle), MemberType = typeof(GenericMathTestMemberData))] - public void IsZeroSingleTest(float value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalByteTest(byte value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalDoubleTest(double value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalInt16Test(short value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalInt32Test(int value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalInt64Test(long value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalSByteTest(sbyte value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalSingleTest(float value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalUInt16Test(ushort value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalUInt32Test(uint value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalUInt64Test(ulong value) => IsSubnormal(value); + + private void IsZero(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsZero(Vector512.Create(value))); + Assert.Equal(T.IsZero(value) ? Vector512.AllBitsSet : Vector512.Zero, Vector512.IsZero(Vector512.Create(value))); } + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroByteTest(byte value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroDoubleTest(double value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroInt16Test(short value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroInt32Test(int value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroInt64Test(long value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroSByteTest(sbyte value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroSingleTest(float value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroUInt16Test(ushort value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroUInt32Test(uint value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroUInt64Test(ulong value) => IsZero(value); + [Theory] [MemberData(nameof(GenericMathTestMemberData.LerpDouble), MemberType = typeof(GenericMathTestMemberData))] public void LerpDoubleTest(double x, double y, double amount, double expectedResult) @@ -5843,5 +6371,275 @@ public void TruncateSingleTest(float value, float expectedResult) Vector512 actualResult = Vector512.Truncate(Vector512.Create(value)); AssertEqual(Vector512.Create(expectedResult), actualResult, Vector512.Zero); } + + [MethodImpl(MethodImplOptions.NoInlining)] + private void AllAnyNoneTest(T value1, T value2) + where T : struct, INumber + { + var input1 = Vector512.Create(value1); + var input2 = Vector512.Create(value2); + + Assert.True(Vector512.All(input1, value1)); + Assert.True(Vector512.All(input2, value2)); + Assert.False(Vector512.All(input1.WithElement(0, value2), value1)); + Assert.False(Vector512.All(input2.WithElement(0, value1), value2)); + Assert.False(Vector512.All(input1, value2)); + Assert.False(Vector512.All(input2, value1)); + Assert.False(Vector512.All(input1.WithElement(0, value2), value2)); + Assert.False(Vector512.All(input2.WithElement(0, value1), value1)); + + Assert.True(Vector512.Any(input1, value1)); + Assert.True(Vector512.Any(input2, value2)); + Assert.True(Vector512.Any(input1.WithElement(0, value2), value1)); + Assert.True(Vector512.Any(input2.WithElement(0, value1), value2)); + Assert.False(Vector512.Any(input1, value2)); + Assert.False(Vector512.Any(input2, value1)); + Assert.True(Vector512.Any(input1.WithElement(0, value2), value2)); + Assert.True(Vector512.Any(input2.WithElement(0, value1), value1)); + + Assert.False(Vector512.None(input1, value1)); + Assert.False(Vector512.None(input2, value2)); + Assert.False(Vector512.None(input1.WithElement(0, value2), value1)); + Assert.False(Vector512.None(input2.WithElement(0, value1), value2)); + Assert.True(Vector512.None(input1, value2)); + Assert.True(Vector512.None(input2, value1)); + Assert.False(Vector512.None(input1.WithElement(0, value2), value2)); + Assert.False(Vector512.None(input2.WithElement(0, value1), value1)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private void AllAnyNoneTest_IFloatingPointIeee754(T value) + where T : struct, IFloatingPointIeee754 + { + var input = Vector512.Create(value); + + Assert.False(Vector512.All(input, value)); + Assert.False(Vector512.Any(input, value)); + Assert.True(Vector512.None(input, value)); + } + + [Fact] + public void AllAnyNoneByteTest() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneDoubleTest() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneDoubleTest_AllBitsSet() => AllAnyNoneTest_IFloatingPointIeee754(BitConverter.Int64BitsToDouble(-1)); + + [Fact] + public void AllAnyNoneInt16Test() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneInt32Test() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneInt64Test() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneSByteTest() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneSingleTest() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneSingleTest_AllBitsSet() => AllAnyNoneTest_IFloatingPointIeee754(BitConverter.Int32BitsToSingle(-1)); + + [Fact] + public void AllAnyNoneUInt16Test() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneUInt32Test() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneUInt64Test() => AllAnyNoneTest(3, 2); + + [MethodImpl(MethodImplOptions.NoInlining)] + private void AllAnyNoneWhereAllBitsSetTest(T allBitsSet, T value2) + where T : struct, INumber + { + var input1 = Vector512.Create(allBitsSet); + var input2 = Vector512.Create(value2); + + Assert.True(Vector512.AllWhereAllBitsSet(input1)); + Assert.False(Vector512.AllWhereAllBitsSet(input2)); + Assert.False(Vector512.AllWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.False(Vector512.AllWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.True(Vector512.AnyWhereAllBitsSet(input1)); + Assert.False(Vector512.AnyWhereAllBitsSet(input2)); + Assert.True(Vector512.AnyWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.True(Vector512.AnyWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.False(Vector512.NoneWhereAllBitsSet(input1)); + Assert.True(Vector512.NoneWhereAllBitsSet(input2)); + Assert.False(Vector512.NoneWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.False(Vector512.NoneWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + } + + [Fact] + public void AllAnyNoneWhereAllBitsSetByteTest() => AllAnyNoneWhereAllBitsSetTest(byte.MaxValue, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetDoubleTest() => AllAnyNoneWhereAllBitsSetTest(BitConverter.Int64BitsToDouble(-1), 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetInt16Test() => AllAnyNoneWhereAllBitsSetTest(-1, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetInt32Test() => AllAnyNoneWhereAllBitsSetTest(-1, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetInt64Test() => AllAnyNoneWhereAllBitsSetTest(-1, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetSByteTest() => AllAnyNoneWhereAllBitsSetTest(-1, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetSingleTest() => AllAnyNoneWhereAllBitsSetTest(BitConverter.Int32BitsToSingle(-1), 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetUInt16Test() => AllAnyNoneWhereAllBitsSetTest(ushort.MaxValue, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetUInt32Test() => AllAnyNoneWhereAllBitsSetTest(uint.MaxValue, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetUInt64Test() => AllAnyNoneWhereAllBitsSetTest(ulong.MaxValue, 2); + + [MethodImpl(MethodImplOptions.NoInlining)] + private void CountIndexOfLastIndexOfTest(T value1, T value2) + where T : struct, INumber + { + var input1 = Vector512.Create(value1); + var input2 = Vector512.Create(value2); + + Assert.Equal(Vector512.Count, Vector512.Count(input1, value1)); + Assert.Equal(Vector512.Count, Vector512.Count(input2, value2)); + Assert.Equal(Vector512.Count - 1, Vector512.Count(input1.WithElement(0, value2), value1)); + Assert.Equal(Vector512.Count - 1, Vector512.Count(input2.WithElement(0, value1), value2)); + Assert.Equal(0, Vector512.Count(input1, value2)); + Assert.Equal(0, Vector512.Count(input2, value1)); + Assert.Equal(1, Vector512.Count(input1.WithElement(0, value2), value2)); + Assert.Equal(1, Vector512.Count(input2.WithElement(0, value1), value1)); + + Assert.Equal(0, Vector512.IndexOf(input1, value1)); + Assert.Equal(0, Vector512.IndexOf(input2, value2)); + Assert.Equal(1, Vector512.IndexOf(input1.WithElement(0, value2), value1)); + Assert.Equal(1, Vector512.IndexOf(input2.WithElement(0, value1), value2)); + Assert.Equal(-1, Vector512.IndexOf(input1, value2)); + Assert.Equal(-1, Vector512.IndexOf(input2, value1)); + Assert.Equal(0, Vector512.IndexOf(input1.WithElement(0, value2), value2)); + Assert.Equal(0, Vector512.IndexOf(input2.WithElement(0, value1), value1)); + + Assert.Equal(Vector512.Count - 1, Vector512.LastIndexOf(input1, value1)); + Assert.Equal(Vector512.Count - 1, Vector512.LastIndexOf(input2, value2)); + Assert.Equal(Vector512.Count - 1, Vector512.LastIndexOf(input1.WithElement(0, value2), value1)); + Assert.Equal(Vector512.Count - 1, Vector512.LastIndexOf(input2.WithElement(0, value1), value2)); + Assert.Equal(-1, Vector512.LastIndexOf(input1, value2)); + Assert.Equal(-1, Vector512.LastIndexOf(input2, value1)); + Assert.Equal(0, Vector512.LastIndexOf(input1.WithElement(0, value2), value2)); + Assert.Equal(0, Vector512.LastIndexOf(input2.WithElement(0, value1), value1)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private void CountIndexOfLastIndexOfTest_IFloatingPointIeee754(T value) + where T : struct, IFloatingPointIeee754 + { + var input = Vector512.Create(value); + + Assert.Equal(0, Vector512.Count(input, value)); + Assert.Equal(-1, Vector512.IndexOf(input, value)); + Assert.Equal(-1, Vector512.LastIndexOf(input, value)); + } + + [Fact] + public void CountIndexOfLastIndexOfByteTest() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfDoubleTest() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfDoubleTest_AllBitsSet() => CountIndexOfLastIndexOfTest_IFloatingPointIeee754(BitConverter.Int64BitsToDouble(-1)); + + [Fact] + public void CountIndexOfLastIndexOfInt16Test() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfInt32Test() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfInt64Test() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfSByteTest() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfSingleTest() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfSingleTest_AllBitsSet() => CountIndexOfLastIndexOfTest_IFloatingPointIeee754(BitConverter.Int32BitsToSingle(-1)); + + [Fact] + public void CountIndexOfLastIndexOfUInt16Test() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfUInt32Test() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfUInt64Test() => CountIndexOfLastIndexOfTest(3, 2); + + [MethodImpl(MethodImplOptions.NoInlining)] + private void CountIndexOfLastIndexOfWhereAllBitsSetTest(T allBitsSet, T value2) + where T : struct, INumber + { + var input1 = Vector512.Create(allBitsSet); + var input2 = Vector512.Create(value2); + + Assert.Equal(Vector512.Count, Vector512.CountWhereAllBitsSet(input1)); + Assert.Equal(0, Vector512.CountWhereAllBitsSet(input2)); + Assert.Equal(Vector512.Count - 1, Vector512.CountWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.Equal(1, Vector512.CountWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.Equal(0, Vector512.IndexOfWhereAllBitsSet(input1)); + Assert.Equal(-1, Vector512.IndexOfWhereAllBitsSet(input2)); + Assert.Equal(1, Vector512.IndexOfWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.Equal(0, Vector512.IndexOfWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.Equal(Vector512.Count - 1, Vector512.LastIndexOfWhereAllBitsSet(input1)); + Assert.Equal(-1, Vector512.LastIndexOfWhereAllBitsSet(input2)); + Assert.Equal(Vector512.Count - 1, Vector512.LastIndexOfWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.Equal(0, Vector512.LastIndexOfWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + } + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetByteTest() => CountIndexOfLastIndexOfWhereAllBitsSetTest(byte.MaxValue, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetDoubleTest() => CountIndexOfLastIndexOfWhereAllBitsSetTest(BitConverter.Int64BitsToDouble(-1), 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetInt16Test() => CountIndexOfLastIndexOfWhereAllBitsSetTest(-1, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetInt32Test() => CountIndexOfLastIndexOfWhereAllBitsSetTest(-1, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetInt64Test() => CountIndexOfLastIndexOfWhereAllBitsSetTest(-1, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetSByteTest() => CountIndexOfLastIndexOfWhereAllBitsSetTest(-1, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetSingleTest() => CountIndexOfLastIndexOfWhereAllBitsSetTest(BitConverter.Int32BitsToSingle(-1), 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetUInt16Test() => CountIndexOfLastIndexOfWhereAllBitsSetTest(ushort.MaxValue, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetUInt32Test() => CountIndexOfLastIndexOfWhereAllBitsSetTest(uint.MaxValue, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetUInt64Test() => CountIndexOfLastIndexOfWhereAllBitsSetTest(ulong.MaxValue, 2); } } diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs index c049c08515a083..9cdbc25be4a723 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs +++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs @@ -3,6 +3,7 @@ using System.Numerics; using System.Reflection; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Tests; using Xunit; @@ -3930,9 +3931,9 @@ public void Vector64DoubleEqualsNonCanonicalNaNTest() }; // all Vector NaNs .Equals compare the same, but == compare as different - foreach(var i in nans) + foreach (var i in nans) { - foreach(var j in nans) + foreach (var j in nans) { Assert.True(Vector64.Create(i).Equals(Vector64.Create(j))); Assert.False(Vector64.Create(i) == Vector64.Create(j)); @@ -3954,9 +3955,9 @@ public void Vector64SingleEqualsNonCanonicalNaNTest() }; // all Vector NaNs .Equals compare the same, but == compare as different - foreach(var i in nans) + foreach (var i in nans) { - foreach(var j in nans) + foreach (var j in nans) { Assert.True(Vector64.Create(i).Equals(Vector64.Create(j))); Assert.False(Vector64.Create(i) == Vector64.Create(j)); @@ -4474,76 +4475,604 @@ public void HypotSingleTest(float x, float y, float expectedResult, float varian AssertEqual(Vector64.Create(expectedResult), Vector64.Hypot(Vector64.Create(+y), Vector64.Create(+x)), Vector64.Create(variance)); } + private void IsEvenInteger(T value) + where T : INumber + { + Assert.Equal(T.IsEvenInteger(value) ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsEvenInteger(Vector64.Create(value))); + } + [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsNaNDouble), MemberType = typeof(GenericMathTestMemberData))] - public void IsNaNDoubleTest(double value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerByteTest(byte value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerDoubleTest(double value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerInt16Test(short value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerInt32Test(int value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerInt64Test(long value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerSByteTest(sbyte value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerSingleTest(float value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerUInt16Test(ushort value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerUInt32Test(uint value) => IsEvenInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsEvenIntegerUInt64Test(ulong value) => IsEvenInteger(value); + + private void IsFinite(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsNaN(Vector64.Create(value))); + Assert.Equal(T.IsFinite(value) ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsFinite(Vector64.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsNaNSingle), MemberType = typeof(GenericMathTestMemberData))] - public void IsNaNSingleTest(float value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteByteTest(byte value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteDoubleTest(double value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteInt16Test(short value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteInt32Test(int value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteInt64Test(long value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteSByteTest(sbyte value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteSingleTest(float value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteUInt16Test(ushort value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteUInt32Test(uint value) => IsFinite(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsFiniteUInt64Test(ulong value) => IsFinite(value); + + private void IsInfinity(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsNaN(Vector64.Create(value))); + Assert.Equal(T.IsInfinity(value) ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsInfinity(Vector64.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsNegativeDouble), MemberType = typeof(GenericMathTestMemberData))] - public void IsNegativeDoubleTest(double value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityByteTest(byte value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityDoubleTest(double value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityInt16Test(short value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityInt32Test(int value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityInt64Test(long value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinitySByteTest(sbyte value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinitySingleTest(float value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityUInt16Test(ushort value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityUInt32Test(uint value) => IsInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsInfinityUInt64Test(ulong value) => IsInfinity(value); + + private void IsInteger(T value) + where T : INumber + { + Assert.Equal(T.IsInteger(value) ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsInteger(Vector64.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerByteTest(byte value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerDoubleTest(double value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerInt16Test(short value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerInt32Test(int value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerInt64Test(long value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerSByteTest(sbyte value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerSingleTest(float value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerUInt16Test(ushort value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerUInt32Test(uint value) => IsInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsIntegerUInt64Test(ulong value) => IsInteger(value); + + private void IsNaN(T value) + where T : INumber + { + Assert.Equal(T.IsNaN(value) ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsNaN(Vector64.Create(value))); + } + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNByteTest(byte value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNDoubleTest(double value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNInt16Test(short value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNInt32Test(int value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNInt64Test(long value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNSByteTest(sbyte value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNSingleTest(float value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNUInt16Test(ushort value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNUInt32Test(uint value) => IsNaN(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNaNUInt64Test(ulong value) => IsNaN(value); + + private void IsNegative(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsNegative(Vector64.Create(value))); + Assert.Equal(T.IsNegative(value) ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsNegative(Vector64.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsNegativeSingle), MemberType = typeof(GenericMathTestMemberData))] - public void IsNegativeSingleTest(float value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeByteTest(byte value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeDoubleTest(double value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInt16Test(short value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInt32Test(int value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInt64Test(long value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeSByteTest(sbyte value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeSingleTest(float value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeUInt16Test(ushort value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeUInt32Test(uint value) => IsNegative(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeUInt64Test(ulong value) => IsNegative(value); + + private void IsNegativeInfinity(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsNegative(Vector64.Create(value))); + Assert.Equal(T.IsNegativeInfinity(value) ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsNegativeInfinity(Vector64.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsPositiveDouble), MemberType = typeof(GenericMathTestMemberData))] - public void IsPositiveDoubleTest(double value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityByteTest(byte value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityDoubleTest(double value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityInt16Test(short value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityInt32Test(int value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityInt64Test(long value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinitySByteTest(sbyte value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinitySingleTest(float value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityUInt16Test(ushort value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityUInt32Test(uint value) => IsNegativeInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNegativeInfinityUInt64Test(ulong value) => IsNegativeInfinity(value); + + private void IsNormal(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsPositive(Vector64.Create(value))); + Assert.Equal(T.IsNormal(value) ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsNormal(Vector64.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsPositiveSingle), MemberType = typeof(GenericMathTestMemberData))] - public void IsPositiveSingleTest(float value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalByteTest(byte value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalDoubleTest(double value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalInt16Test(short value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalInt32Test(int value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalInt64Test(long value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalSByteTest(sbyte value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalSingleTest(float value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalUInt16Test(ushort value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalUInt32Test(uint value) => IsNormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsNormalUInt64Test(ulong value) => IsNormal(value); + + private void IsOddInteger(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsPositive(Vector64.Create(value))); + Assert.Equal(T.IsOddInteger(value) ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsOddInteger(Vector64.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsPositiveInfinityDouble), MemberType = typeof(GenericMathTestMemberData))] - public void IsPositiveInfinityDoubleTest(double value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerByteTest(byte value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerDoubleTest(double value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerInt16Test(short value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerInt32Test(int value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerInt64Test(long value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerSByteTest(sbyte value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerSingleTest(float value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerUInt16Test(ushort value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerUInt32Test(uint value) => IsOddInteger(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsOddIntegerUInt64Test(ulong value) => IsOddInteger(value); + + private void IsPositive(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsPositiveInfinity(Vector64.Create(value))); + Assert.Equal(T.IsPositive(value) ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsPositive(Vector64.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsPositiveInfinitySingle), MemberType = typeof(GenericMathTestMemberData))] - public void IsPositiveInfinitySingleTest(float value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveByteTest(byte value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveDoubleTest(double value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInt16Test(short value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInt32Test(int value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInt64Test(long value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveSByteTest(sbyte value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveSingleTest(float value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveUInt16Test(ushort value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveUInt32Test(uint value) => IsPositive(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveUInt64Test(ulong value) => IsPositive(value); + + private void IsPositiveInfinity(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsPositiveInfinity(Vector64.Create(value))); + Assert.Equal(T.IsPositiveInfinity(value) ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsPositiveInfinity(Vector64.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsZeroDouble), MemberType = typeof(GenericMathTestMemberData))] - public void IsZeroDoubleTest(double value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityByteTest(byte value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityDoubleTest(double value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityInt16Test(short value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityInt32Test(int value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityInt64Test(long value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinitySByteTest(sbyte value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinitySingleTest(float value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityUInt16Test(ushort value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityUInt32Test(uint value) => IsPositiveInfinity(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsPositiveInfinityUInt64Test(ulong value) => IsPositiveInfinity(value); + + private void IsSubnormal(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsZero(Vector64.Create(value))); + Assert.Equal(T.IsSubnormal(value) ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsSubnormal(Vector64.Create(value))); } [Theory] - [MemberData(nameof(GenericMathTestMemberData.IsZeroSingle), MemberType = typeof(GenericMathTestMemberData))] - public void IsZeroSingleTest(float value, bool expectedResult) + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalByteTest(byte value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalDoubleTest(double value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalInt16Test(short value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalInt32Test(int value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalInt64Test(long value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalSByteTest(sbyte value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalSingleTest(float value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalUInt16Test(ushort value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalUInt32Test(uint value) => IsSubnormal(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsSubnormalUInt64Test(ulong value) => IsSubnormal(value); + + private void IsZero(T value) + where T : INumber { - Assert.Equal(expectedResult ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsZero(Vector64.Create(value))); + Assert.Equal(T.IsZero(value) ? Vector64.AllBitsSet : Vector64.Zero, Vector64.IsZero(Vector64.Create(value))); } + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroByteTest(byte value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestDouble), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroDoubleTest(double value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroInt16Test(short value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroInt32Test(int value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroInt64Test(long value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSByte), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroSByteTest(sbyte value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestSingle), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroSingleTest(float value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt16), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroUInt16Test(ushort value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt32), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroUInt32Test(uint value) => IsZero(value); + + [Theory] + [MemberData(nameof(GenericMathTestMemberData.IsTestUInt64), MemberType = typeof(GenericMathTestMemberData))] + public void IsZeroUInt64Test(ulong value) => IsZero(value); + [Theory] [MemberData(nameof(GenericMathTestMemberData.LerpDouble), MemberType = typeof(GenericMathTestMemberData))] public void LerpDoubleTest(double x, double y, double amount, double expectedResult) @@ -4801,5 +5330,275 @@ public void TruncateSingleTest(float value, float expectedResult) Vector64 actualResult = Vector64.Truncate(Vector64.Create(value)); AssertEqual(Vector64.Create(expectedResult), actualResult, Vector64.Zero); } + + [MethodImpl(MethodImplOptions.NoInlining)] + private void AllAnyNoneTest(T value1, T value2) + where T : struct, INumber + { + var input1 = Vector64.Create(value1); + var input2 = Vector64.Create(value2); + + Assert.True(Vector64.All(input1, value1)); + Assert.True(Vector64.All(input2, value2)); + Assert.False(Vector64.All(input1.WithElement(0, value2), value1)); + Assert.False(Vector64.All(input2.WithElement(0, value1), value2)); + Assert.False(Vector64.All(input1, value2)); + Assert.False(Vector64.All(input2, value1)); + Assert.Equal(Vector64.Count == 1, Vector64.All(input1.WithElement(0, value2), value2)); + Assert.Equal(Vector64.Count == 1, Vector64.All(input2.WithElement(0, value1), value1)); + + Assert.True(Vector64.Any(input1, value1)); + Assert.True(Vector64.Any(input2, value2)); + Assert.Equal(Vector64.Count != 1, Vector64.Any(input1.WithElement(0, value2), value1)); + Assert.Equal(Vector64.Count != 1, Vector64.Any(input2.WithElement(0, value1), value2)); + Assert.False(Vector64.Any(input1, value2)); + Assert.False(Vector64.Any(input2, value1)); + Assert.True(Vector64.Any(input1.WithElement(0, value2), value2)); + Assert.True(Vector64.Any(input2.WithElement(0, value1), value1)); + + Assert.False(Vector64.None(input1, value1)); + Assert.False(Vector64.None(input2, value2)); + Assert.Equal(Vector64.Count == 1, Vector64.None(input1.WithElement(0, value2), value1)); + Assert.Equal(Vector64.Count == 1, Vector64.None(input2.WithElement(0, value1), value2)); + Assert.True(Vector64.None(input1, value2)); + Assert.True(Vector64.None(input2, value1)); + Assert.False(Vector64.None(input1.WithElement(0, value2), value2)); + Assert.False(Vector64.None(input2.WithElement(0, value1), value1)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private void AllAnyNoneTest_IFloatingPointIeee754(T value) + where T : struct, IFloatingPointIeee754 + { + var input = Vector64.Create(value); + + Assert.False(Vector64.All(input, value)); + Assert.False(Vector64.Any(input, value)); + Assert.True(Vector64.None(input, value)); + } + + [Fact] + public void AllAnyNoneByteTest() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneDoubleTest() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneDoubleTest_AllBitsSet() => AllAnyNoneTest_IFloatingPointIeee754(BitConverter.Int64BitsToDouble(-1)); + + [Fact] + public void AllAnyNoneInt16Test() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneInt32Test() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneInt64Test() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneSByteTest() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneSingleTest() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneSingleTest_AllBitsSet() => AllAnyNoneTest_IFloatingPointIeee754(BitConverter.Int32BitsToSingle(-1)); + + [Fact] + public void AllAnyNoneUInt16Test() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneUInt32Test() => AllAnyNoneTest(3, 2); + + [Fact] + public void AllAnyNoneUInt64Test() => AllAnyNoneTest(3, 2); + + [MethodImpl(MethodImplOptions.NoInlining)] + private void AllAnyNoneWhereAllBitsSetTest(T allBitsSet, T value2) + where T : struct, INumber + { + var input1 = Vector64.Create(allBitsSet); + var input2 = Vector64.Create(value2); + + Assert.True(Vector64.AllWhereAllBitsSet(input1)); + Assert.False(Vector64.AllWhereAllBitsSet(input2)); + Assert.False(Vector64.AllWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.Equal(Vector64.Count == 1, Vector64.AllWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.True(Vector64.AnyWhereAllBitsSet(input1)); + Assert.False(Vector64.AnyWhereAllBitsSet(input2)); + Assert.Equal(Vector64.Count != 1, Vector64.AnyWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.True(Vector64.AnyWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.False(Vector64.NoneWhereAllBitsSet(input1)); + Assert.True(Vector64.NoneWhereAllBitsSet(input2)); + Assert.Equal(Vector64.Count == 1, Vector64.NoneWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.False(Vector64.NoneWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + } + + [Fact] + public void AllAnyNoneWhereAllBitsSetByteTest() => AllAnyNoneWhereAllBitsSetTest(byte.MaxValue, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetDoubleTest() => AllAnyNoneWhereAllBitsSetTest(BitConverter.Int64BitsToDouble(-1), 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetInt16Test() => AllAnyNoneWhereAllBitsSetTest(-1, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetInt32Test() => AllAnyNoneWhereAllBitsSetTest(-1, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetInt64Test() => AllAnyNoneWhereAllBitsSetTest(-1, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetSByteTest() => AllAnyNoneWhereAllBitsSetTest(-1, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetSingleTest() => AllAnyNoneWhereAllBitsSetTest(BitConverter.Int32BitsToSingle(-1), 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetUInt16Test() => AllAnyNoneWhereAllBitsSetTest(ushort.MaxValue, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetUInt32Test() => AllAnyNoneWhereAllBitsSetTest(uint.MaxValue, 2); + + [Fact] + public void AllAnyNoneWhereAllBitsSetUInt64Test() => AllAnyNoneWhereAllBitsSetTest(ulong.MaxValue, 2); + + [MethodImpl(MethodImplOptions.NoInlining)] + private void CountIndexOfLastIndexOfTest(T value1, T value2) + where T : struct, INumber + { + var input1 = Vector64.Create(value1); + var input2 = Vector64.Create(value2); + + Assert.Equal(Vector64.Count, Vector64.Count(input1, value1)); + Assert.Equal(Vector64.Count, Vector64.Count(input2, value2)); + Assert.Equal(Vector64.Count - 1, Vector64.Count(input1.WithElement(0, value2), value1)); + Assert.Equal(Vector64.Count - 1, Vector64.Count(input2.WithElement(0, value1), value2)); + Assert.Equal(0, Vector64.Count(input1, value2)); + Assert.Equal(0, Vector64.Count(input2, value1)); + Assert.Equal(1, Vector64.Count(input1.WithElement(0, value2), value2)); + Assert.Equal(1, Vector64.Count(input2.WithElement(0, value1), value1)); + + Assert.Equal(0, Vector64.IndexOf(input1, value1)); + Assert.Equal(0, Vector64.IndexOf(input2, value2)); + Assert.Equal((Vector64.Count != 1) ? 1 : -1, Vector64.IndexOf(input1.WithElement(0, value2), value1)); + Assert.Equal((Vector64.Count != 1) ? 1 : -1, Vector64.IndexOf(input2.WithElement(0, value1), value2)); + Assert.Equal(-1, Vector64.IndexOf(input1, value2)); + Assert.Equal(-1, Vector64.IndexOf(input2, value1)); + Assert.Equal(0, Vector64.IndexOf(input1.WithElement(0, value2), value2)); + Assert.Equal(0, Vector64.IndexOf(input2.WithElement(0, value1), value1)); + + Assert.Equal(Vector64.Count - 1, Vector64.LastIndexOf(input1, value1)); + Assert.Equal(Vector64.Count - 1, Vector64.LastIndexOf(input2, value2)); + Assert.Equal((Vector64.Count != 1) ? Vector64.Count - 1 : -1, Vector64.LastIndexOf(input1.WithElement(0, value2), value1)); + Assert.Equal((Vector64.Count != 1) ? Vector64.Count - 1 : -1, Vector64.LastIndexOf(input2.WithElement(0, value1), value2)); + Assert.Equal(-1, Vector64.LastIndexOf(input1, value2)); + Assert.Equal(-1, Vector64.LastIndexOf(input2, value1)); + Assert.Equal(0, Vector64.LastIndexOf(input1.WithElement(0, value2), value2)); + Assert.Equal(0, Vector64.LastIndexOf(input2.WithElement(0, value1), value1)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private void CountIndexOfLastIndexOfTest_IFloatingPointIeee754(T value) + where T : struct, IFloatingPointIeee754 + { + var input = Vector64.Create(value); + + Assert.Equal(0, Vector64.Count(input, value)); + Assert.Equal(-1, Vector64.IndexOf(input, value)); + Assert.Equal(-1, Vector64.LastIndexOf(input, value)); + } + + [Fact] + public void CountIndexOfLastIndexOfByteTest() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfDoubleTest() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfDoubleTest_AllBitsSet() => CountIndexOfLastIndexOfTest_IFloatingPointIeee754(BitConverter.Int64BitsToDouble(-1)); + + [Fact] + public void CountIndexOfLastIndexOfInt16Test() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfInt32Test() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfInt64Test() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfSByteTest() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfSingleTest() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfSingleTest_AllBitsSet() => CountIndexOfLastIndexOfTest_IFloatingPointIeee754(BitConverter.Int32BitsToSingle(-1)); + + [Fact] + public void CountIndexOfLastIndexOfUInt16Test() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfUInt32Test() => CountIndexOfLastIndexOfTest(3, 2); + + [Fact] + public void CountIndexOfLastIndexOfUInt64Test() => CountIndexOfLastIndexOfTest(3, 2); + + [MethodImpl(MethodImplOptions.NoInlining)] + private void CountIndexOfLastIndexOfWhereAllBitsSetTest(T allBitsSet, T value2) + where T : struct, INumber + { + var input1 = Vector64.Create(allBitsSet); + var input2 = Vector64.Create(value2); + + Assert.Equal(Vector64.Count, Vector64.CountWhereAllBitsSet(input1)); + Assert.Equal(0, Vector64.CountWhereAllBitsSet(input2)); + Assert.Equal(Vector64.Count - 1, Vector64.CountWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.Equal(1, Vector64.CountWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.Equal(0, Vector64.IndexOfWhereAllBitsSet(input1)); + Assert.Equal(-1, Vector64.IndexOfWhereAllBitsSet(input2)); + Assert.Equal((Vector64.Count != 1) ? 1 : -1, Vector64.IndexOfWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.Equal(0, Vector64.IndexOfWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + + Assert.Equal(Vector64.Count - 1, Vector64.LastIndexOfWhereAllBitsSet(input1)); + Assert.Equal(-1, Vector64.LastIndexOfWhereAllBitsSet(input2)); + Assert.Equal((Vector64.Count != 1) ? Vector64.Count - 1 : -1, Vector64.LastIndexOfWhereAllBitsSet(input1.WithElement(0, value2))); + Assert.Equal(0, Vector64.LastIndexOfWhereAllBitsSet(input2.WithElement(0, allBitsSet))); + } + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetByteTest() => CountIndexOfLastIndexOfWhereAllBitsSetTest(byte.MaxValue, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetDoubleTest() => CountIndexOfLastIndexOfWhereAllBitsSetTest(BitConverter.Int64BitsToDouble(-1), 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetInt16Test() => CountIndexOfLastIndexOfWhereAllBitsSetTest(-1, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetInt32Test() => CountIndexOfLastIndexOfWhereAllBitsSetTest(-1, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetInt64Test() => CountIndexOfLastIndexOfWhereAllBitsSetTest(-1, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetSByteTest() => CountIndexOfLastIndexOfWhereAllBitsSetTest(-1, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetSingleTest() => CountIndexOfLastIndexOfWhereAllBitsSetTest(BitConverter.Int32BitsToSingle(-1), 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetUInt16Test() => CountIndexOfLastIndexOfWhereAllBitsSetTest(ushort.MaxValue, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetUInt32Test() => CountIndexOfLastIndexOfWhereAllBitsSetTest(uint.MaxValue, 2); + + [Fact] + public void CountIndexOfLastIndexOfWhereAllBitsSetUInt64Test() => CountIndexOfLastIndexOfWhereAllBitsSetTest(ulong.MaxValue, 2); } } diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index af640b0339a443..a71de86ad971a0 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -2414,6 +2414,7 @@ public DivideByZeroException(string? message, System.Exception? innerException) public static double Cbrt(double x) { throw null; } public static double Ceiling(double x) { throw null; } public static double Clamp(double value, double min, double max) { throw null; } + public static double ClampNative(double value, double min, double max) { throw null; } public int CompareTo(double value) { throw null; } public int CompareTo(object? value) { throw null; } public static TInteger ConvertToIntegerNative(double value) where TInteger : System.Numerics.IBinaryInteger { throw null; } @@ -2466,10 +2467,12 @@ public DivideByZeroException(string? message, System.Exception? innerException) public static double Max(double x, double y) { throw null; } public static double MaxMagnitude(double x, double y) { throw null; } public static double MaxMagnitudeNumber(double x, double y) { throw null; } + public static double MaxNative(double x, double y) { throw null; } public static double MaxNumber(double x, double y) { throw null; } public static double Min(double x, double y) { throw null; } public static double MinMagnitude(double x, double y) { throw null; } public static double MinMagnitudeNumber(double x, double y) { throw null; } + public static double MinNative(double x, double y) { throw null; } public static double MinNumber(double x, double y) { throw null; } public static double MultiplyAddEstimate(double left, double right, double addend) { throw null; } public static bool operator ==(double left, double right) { throw null; } @@ -3226,6 +3229,7 @@ public enum GCNotificationStatus public static System.Half Cbrt(System.Half x) { throw null; } public static System.Half Ceiling(System.Half x) { throw null; } public static System.Half Clamp(System.Half value, System.Half min, System.Half max) { throw null; } + public static System.Half ClampNative(System.Half value, System.Half min, System.Half max) { throw null; } public int CompareTo(System.Half other) { throw null; } public int CompareTo(object? obj) { throw null; } public static TInteger ConvertToIntegerNative(System.Half value) where TInteger : System.Numerics.IBinaryInteger { throw null; } @@ -3277,10 +3281,12 @@ public enum GCNotificationStatus public static System.Half Max(System.Half x, System.Half y) { throw null; } public static System.Half MaxMagnitude(System.Half x, System.Half y) { throw null; } public static System.Half MaxMagnitudeNumber(System.Half x, System.Half y) { throw null; } + public static System.Half MaxNative(System.Half x, System.Half y) { throw null; } public static System.Half MaxNumber(System.Half x, System.Half y) { throw null; } public static System.Half Min(System.Half x, System.Half y) { throw null; } public static System.Half MinMagnitude(System.Half x, System.Half y) { throw null; } public static System.Half MinMagnitudeNumber(System.Half x, System.Half y) { throw null; } + public static System.Half MinNative(System.Half x, System.Half y) { throw null; } public static System.Half MinNumber(System.Half x, System.Half y) { throw null; } public static System.Half MultiplyAddEstimate(System.Half left, System.Half right, System.Half addend) { throw null; } public static System.Half operator +(System.Half left, System.Half right) { throw null; } @@ -5359,6 +5365,7 @@ public SerializableAttribute() { } public static float Cbrt(float x) { throw null; } public static float Ceiling(float x) { throw null; } public static float Clamp(float value, float min, float max) { throw null; } + public static float ClampNative(float value, float min, float max) { throw null; } public int CompareTo(object? value) { throw null; } public int CompareTo(float value) { throw null; } public static TInteger ConvertToIntegerNative(float value) where TInteger : System.Numerics.IBinaryInteger { throw null; } @@ -5411,10 +5418,12 @@ public SerializableAttribute() { } public static float Max(float x, float y) { throw null; } public static float MaxMagnitude(float x, float y) { throw null; } public static float MaxMagnitudeNumber(float x, float y) { throw null; } + public static float MaxNative(float x, float y) { throw null; } public static float MaxNumber(float x, float y) { throw null; } public static float Min(float x, float y) { throw null; } public static float MinMagnitude(float x, float y) { throw null; } public static float MinMagnitudeNumber(float x, float y) { throw null; } + public static float MinNative(float x, float y) { throw null; } public static float MinNumber(float x, float y) { throw null; } public static float MultiplyAddEstimate(float left, float right, float addend) { throw null; } public static bool operator ==(float left, float right) { throw null; } @@ -11459,10 +11468,13 @@ protected static abstract bool TryConvertToTruncating(TSelf value, [Syst public partial interface INumber : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumberBase, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.INumber? { static virtual TSelf Clamp(TSelf value, TSelf min, TSelf max) { throw null; } + static virtual TSelf ClampNative(TSelf value, TSelf min, TSelf max) { throw null; } static virtual TSelf CopySign(TSelf value, TSelf sign) { throw null; } static virtual TSelf Max(TSelf x, TSelf y) { throw null; } + static virtual TSelf MaxNative(TSelf x, TSelf y) { throw null; } static virtual TSelf MaxNumber(TSelf x, TSelf y) { throw null; } static virtual TSelf Min(TSelf x, TSelf y) { throw null; } + static virtual TSelf MinNative(TSelf x, TSelf y) { throw null; } static virtual TSelf MinNumber(TSelf x, TSelf y) { throw null; } static virtual int Sign(TSelf value) { throw null; } } diff --git a/src/libraries/System.Runtime/tests/System.Reflection.Tests/AssemblyTests.cs b/src/libraries/System.Runtime/tests/System.Reflection.Tests/AssemblyTests.cs index 65752a40ab8167..57a5e1277fcfe9 100644 --- a/src/libraries/System.Runtime/tests/System.Reflection.Tests/AssemblyTests.cs +++ b/src/libraries/System.Runtime/tests/System.Reflection.Tests/AssemblyTests.cs @@ -732,6 +732,29 @@ public void GetCallingAssembly(Assembly assembly1, Assembly assembly2, bool expe Assert.Equal(expected, assembly1.Equals(assembly2)); } + [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/51673", typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser), nameof(PlatformDetection.IsMonoAOT))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/69919", typeof(PlatformDetection), nameof(PlatformDetection.IsNativeAot))] + public void GetCallingAssemblyInCctor() + { + TestGetCallingAssemblyInCctor.Run(); + } + + private class TestGetCallingAssemblyInCctor + { + private static Assembly _callingAssembly; + + static TestGetCallingAssemblyInCctor() + { + _callingAssembly = Assembly.GetCallingAssembly(); + } + + public static void Run() + { + Assert.Equal(typeof(AssemblyTests).Assembly, _callingAssembly); + } + } + [Fact] public void GetExecutingAssembly() { diff --git a/src/libraries/System.Runtime/tests/System.Reflection.Tests/GetTypeTests.cs b/src/libraries/System.Runtime/tests/System.Reflection.Tests/GetTypeTests.cs index b034a56c0972f9..801f2c8c7594de 100644 --- a/src/libraries/System.Runtime/tests/System.Reflection.Tests/GetTypeTests.cs +++ b/src/libraries/System.Runtime/tests/System.Reflection.Tests/GetTypeTests.cs @@ -87,6 +87,21 @@ public static IEnumerable GetType_TestData() yield return new object[] { type.FullName.ToLower(), type }; } + private void VerifyTypeLoadException(string typeName, TypeLoadException exception) + { + string actualTypeName = exception.TypeName; + + string expectedTypeName = typeName.Contains(',') ? typeName[..typeName.IndexOf(',')] : typeName; + + // It is ok for the actual type name to miss the nested type name + if (expectedTypeName.Contains('+') && !actualTypeName.Contains('+')) + { + expectedTypeName = expectedTypeName[..typeName.IndexOf('+')]; + } + + Assert.Equal(expectedTypeName, actualTypeName); + } + [Theory] [MemberData(nameof(GetType_TestData))] public void GetTypeTest(string typeName, Type expectedResult) @@ -112,10 +127,10 @@ public void GetTypeTest(string typeName, Type expectedResult) Assert.Null(Type.GetType(aqn, throwOnError: false, ignoreCase: false)); Assert.Null(Type.GetType(aqn, throwOnError: false, ignoreCase: true)); - Assert.Throws(() => Type.GetType(typeName, throwOnError: true, ignoreCase: false)); - Assert.Throws(() => Type.GetType(typeName, throwOnError: true, ignoreCase: true)); - Assert.Throws(() => Type.GetType(aqn, throwOnError: true, ignoreCase: false)); - Assert.Throws(() => Type.GetType(aqn, throwOnError: true, ignoreCase: true)); + VerifyTypeLoadException(typeName, Assert.Throws(() => Type.GetType(typeName, throwOnError: true, ignoreCase: false))); + VerifyTypeLoadException(typeName, Assert.Throws(() => Type.GetType(typeName, throwOnError: true, ignoreCase: true))); + VerifyTypeLoadException(typeName, Assert.Throws(() => Type.GetType(aqn, throwOnError: true, ignoreCase: false))); + VerifyTypeLoadException(typeName, Assert.Throws(() => Type.GetType(aqn, throwOnError: true, ignoreCase: true))); // Assembly.GetType Assert.Null(a.GetType(typeName)); @@ -126,8 +141,8 @@ public void GetTypeTest(string typeName, Type expectedResult) Assert.Null(a.GetType(aqn, throwOnError: false, ignoreCase: false)); Assert.Null(a.GetType(aqn, throwOnError: false, ignoreCase: true)); - Assert.Throws(() => a.GetType(typeName, throwOnError: true, ignoreCase: false)); - Assert.Throws(() => a.GetType(typeName, throwOnError: true, ignoreCase: true)); + VerifyTypeLoadException(typeName, Assert.Throws(() => a.GetType(typeName, throwOnError: true, ignoreCase: false))); + VerifyTypeLoadException(typeName, Assert.Throws(() => a.GetType(typeName, throwOnError: true, ignoreCase: true))); AssertExtensions.Throws(null, () => a.GetType(aqn, throwOnError: true, ignoreCase: false)); AssertExtensions.Throws(null, () => a.GetType(aqn, throwOnError: true, ignoreCase: true)); @@ -137,8 +152,8 @@ public void GetTypeTest(string typeName, Type expectedResult) Assert.Null(m.GetType(aqn, throwOnError: false, ignoreCase: false)); Assert.Null(m.GetType(aqn, throwOnError: false, ignoreCase: true)); - Assert.Throws(() => m.GetType(typeName, throwOnError: true, ignoreCase: false)); - Assert.Throws(() => m.GetType(typeName, throwOnError: true, ignoreCase: true)); + VerifyTypeLoadException(typeName, Assert.Throws(() => m.GetType(typeName, throwOnError: true, ignoreCase: false))); + VerifyTypeLoadException(typeName, Assert.Throws(() => m.GetType(typeName, throwOnError: true, ignoreCase: true))); AssertExtensions.Throws(null, () => m.GetType(aqn, throwOnError: true, ignoreCase: false)); AssertExtensions.Throws(null, () => m.GetType(aqn, throwOnError: true, ignoreCase: true)); } diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/ILLink.Descriptors.iOS.xml b/src/libraries/System.Runtime/tests/System.Runtime.Tests/ILLink.Descriptors.iOS.xml index b327a37c7a60be..9f5adb4befda83 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/ILLink.Descriptors.iOS.xml +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/ILLink.Descriptors.iOS.xml @@ -9,11 +9,8 @@ - - - diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RandomNumberGenerator.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RandomNumberGenerator.cs index 14d8635fd70fbf..d535cedc26ec61 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RandomNumberGenerator.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RandomNumberGenerator.cs @@ -313,7 +313,9 @@ private static void GetHexStringCore(Span destination, bool lowercase) // Don't overfill the buffer if the destination is smaller than the buffer size. We need to round up when // when dividing by two to account for an odd-length destination. - int needed = (destination.Length + 1) / 2; + // Adding one to a span of length int.MaxValue may overflow. This is handled by the unsigned shift to the right + // which will correct the overflow. + int needed = (destination.Length + 1) >>> 1; Span remainingRandom = randomBuffer.Slice(0, Math.Min(RandomBufferSize, needed)); RandomNumberGenerator.Fill(remainingRandom); diff --git a/src/libraries/System.Text.Encoding.CodePages/src/System/Text/EncodingCharBuffer.cs b/src/libraries/System.Text.Encoding.CodePages/src/System/Text/EncodingCharBuffer.cs index 1ba281dc68afbd..71c411b0c79cae 100644 --- a/src/libraries/System.Text.Encoding.CodePages/src/System/Text/EncodingCharBuffer.cs +++ b/src/libraries/System.Text.Encoding.CodePages/src/System/Text/EncodingCharBuffer.cs @@ -68,9 +68,14 @@ internal unsafe bool AddChar(char ch) return AddChar(ch, 1); } - internal unsafe bool AddChar(char ch1, char ch2, int numBytes) { + if (_chars is null) + { + _charCountResult += 2; + return true; + } + // Need room for 2 chars if (_charEnd - _chars < 2) { diff --git a/src/libraries/System.Text.Encoding.CodePages/tests/EncodingCodePages.cs b/src/libraries/System.Text.Encoding.CodePages/tests/EncodingCodePages.cs index f075b37d522dde..e6e25c19dd1455 100644 --- a/src/libraries/System.Text.Encoding.CodePages/tests/EncodingCodePages.cs +++ b/src/libraries/System.Text.Encoding.CodePages/tests/EncodingCodePages.cs @@ -519,6 +519,7 @@ public static void TestDefaultEncodings() Assert.Contains(mappedEncoding, CrossplatformDefaultEncodings().Union(CodePageInfo().Select(i => Map((int)i[0], (string)i[1])))); TestRegister1252(); + TestMultiBytesEncodingsSupportSurrogate(); } private static void ValidateDefaultEncodings() @@ -639,6 +640,23 @@ public static void TestEncodingDisplayNames(int codePage, string webName, string Assert.All(name, c => Assert.True(c >= ' ' && c < '~' + 1, "Name: " + name + " contains character: " + c)); } + private static void TestMultiBytesEncodingsSupportSurrogate() + { + Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); + + Encoding encoding = Encoding.GetEncoding("GB18030"); + Assert.NotNull(encoding); + + string surrogatePair = "\uD840\uDE13"; // Surrogate Pair codepoint '𠈓' \U00020213 + byte[] expectedBytes = new byte[] { 0x95, 0x32, 0xB7, 0x37 }; + + Assert.Equal(expectedBytes, encoding.GetBytes(surrogatePair)); + Assert.Equal(expectedBytes.Length, encoding.GetByteCount(surrogatePair)); + + Assert.Equal(surrogatePair, encoding.GetString(expectedBytes)); + Assert.Equal(surrogatePair.Length, encoding.GetCharCount(expectedBytes)); + } + // This test is run as part of the default mappings test, since it modifies global state which that test // depends on. private static void TestRegister1252() diff --git a/src/libraries/System.Text.Json/ref/System.Text.Json.cs b/src/libraries/System.Text.Json/ref/System.Text.Json.cs index 469ea5e4f07c89..0b1d60e5c8b4c1 100644 --- a/src/libraries/System.Text.Json/ref/System.Text.Json.cs +++ b/src/libraries/System.Text.Json/ref/System.Text.Json.cs @@ -681,6 +681,7 @@ public void WriteStringValue(string? value) { } public void WriteStringValue(System.Text.Json.JsonEncodedText value) { } public void WriteStringValueSegment(System.ReadOnlySpan value, bool isFinalSegment) { } public void WriteStringValueSegment(System.ReadOnlySpan value, bool isFinalSegment) { } + public void WriteBase64StringSegment(ReadOnlySpan value, bool isFinalSegment) { } } } namespace System.Text.Json.Nodes diff --git a/src/libraries/System.Text.Json/src/System.Text.Json.csproj b/src/libraries/System.Text.Json/src/System.Text.Json.csproj index b7130feea79ea8..0acc35d1987792 100644 --- a/src/libraries/System.Text.Json/src/System.Text.Json.csproj +++ b/src/libraries/System.Text.Json/src/System.Text.Json.csproj @@ -1,4 +1,4 @@ - + $(NetCoreAppCurrent);$(NetCoreAppPrevious);$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum) @@ -21,6 +21,7 @@ The System.Text.Json library is built-in as part of the shared framework in .NET + @@ -382,6 +383,7 @@ The System.Text.Json library is built-in as part of the shared framework in .NET + diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.Parse.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.Parse.cs index 6bd5a2814b6460..d0383eb756eecb 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.Parse.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.Parse.cs @@ -870,15 +870,7 @@ private static async // No need for checking for growth, the minimal rent sizes both guarantee it'll fit. Debug.Assert(rented.Length >= JsonConstants.Utf8Bom.Length); - lastRead = await stream.ReadAsync( -#if NET - rented.AsMemory(written, utf8BomLength - written), -#else - rented, - written, - utf8BomLength - written, -#endif - cancellationToken).ConfigureAwait(false); + lastRead = await stream.ReadAsync(rented.AsMemory(written, utf8BomLength - written), cancellationToken).ConfigureAwait(false); written += lastRead; } while (lastRead > 0 && written < utf8BomLength); @@ -901,15 +893,7 @@ private static async ArrayPool.Shared.Return(toReturn, clearArray: true); } - lastRead = await stream.ReadAsync( -#if NET - rented.AsMemory(written), -#else - rented, - written, - rented.Length - written, -#endif - cancellationToken).ConfigureAwait(false); + lastRead = await stream.ReadAsync(rented.AsMemory(written), cancellationToken).ConfigureAwait(false); written += lastRead; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.To.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.To.cs index 34b12052d31d18..fd86c0b19a31bc 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.To.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.To.cs @@ -27,7 +27,7 @@ public string ToJsonString(JsonSerializerOptions? options = null) { WriteTo(writer, options); writer.Flush(); - return JsonHelpers.Utf8GetString(output.WrittenMemory.Span); + return JsonHelpers.Utf8GetString(output.WrittenSpan); } finally { @@ -60,7 +60,7 @@ public override string ToString() { WriteTo(writer); writer.Flush(); - return JsonHelpers.Utf8GetString(output.WrittenMemory.Span); + return JsonHelpers.Utf8GetString(output.WrittenSpan); } finally { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonValue.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonValue.cs index d93546cdf92e42..b3d72f57e28435 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonValue.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonValue.cs @@ -143,7 +143,7 @@ static JsonElement ToJsonElement(JsonNode node, out JsonDocument? backingDocumen { node.WriteTo(writer); writer.Flush(); - Utf8JsonReader reader = new(output.WrittenMemory.Span); + Utf8JsonReader reader = new(output.WrittenSpan); backingDocument = JsonDocument.ParseValue(ref reader); return backingDocument.RootElement; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonValueOfTCustomized.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonValueOfTCustomized.cs index 589a8ec8e5556f..ceaa849f957ccc 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonValueOfTCustomized.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonValueOfTCustomized.cs @@ -54,7 +54,7 @@ private JsonValueKind ComputeValueKind() { WriteTo(writer); writer.Flush(); - Utf8JsonReader reader = new(output.WrittenMemory.Span); + Utf8JsonReader reader = new(output.WrittenSpan); bool success = reader.Read(); Debug.Assert(success); return JsonReaderHelper.ToValueKind(reader.TokenType); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Node.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Node.cs index b22be1ceec6762..c1e3892060a072 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Node.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Node.cs @@ -169,7 +169,7 @@ public static partial class JsonSerializer } } - return ReadFromSpan(output.WrittenMemory.Span, jsonTypeInfo); + return ReadFromSpan(output.WrittenSpan, jsonTypeInfo); } private static object? ReadFromNodeAsObject(JsonNode? node, JsonTypeInfo jsonTypeInfo) @@ -190,7 +190,7 @@ public static partial class JsonSerializer } } - return ReadFromSpanAsObject(output.WrittenMemory.Span, jsonTypeInfo); + return ReadFromSpanAsObject(output.WrittenSpan, jsonTypeInfo); } } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.ByteArray.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.ByteArray.cs index bc13797f4231f0..b2287d6ea8cc45 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.ByteArray.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.ByteArray.cs @@ -144,7 +144,7 @@ private static byte[] WriteBytes(in TValue value, JsonTypeInfo j try { jsonTypeInfo.Serialize(writer, value); - return output.WrittenMemory.ToArray(); + return output.WrittenSpan.ToArray(); } finally { @@ -161,7 +161,7 @@ private static byte[] WriteBytesAsObject(object? value, JsonTypeInfo jsonTypeInf try { jsonTypeInfo.SerializeAsObject(writer, value); - return output.WrittenMemory.ToArray(); + return output.WrittenSpan.ToArray(); } finally { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Element.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Element.cs index 90302e81cbc2e4..4057cd667beddc 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Element.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Element.cs @@ -139,7 +139,7 @@ private static JsonElement WriteElement(in TValue value, JsonTypeInfo(in TValue value, JsonTypeInfo try { jsonTypeInfo.Serialize(writer, value); - return JsonReaderHelper.TranscodeHelper(output.WrittenMemory.Span); + return JsonReaderHelper.TranscodeHelper(output.WrittenSpan); } finally { @@ -178,7 +178,7 @@ private static string WriteStringAsObject(object? value, JsonTypeInfo jsonTypeIn try { jsonTypeInfo.SerializeAsObject(writer, value); - return JsonReaderHelper.TranscodeHelper(output.WrittenMemory.Span); + return JsonReaderHelper.TranscodeHelper(output.WrittenSpan); } finally { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadBufferState.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadBufferState.cs index c218fd5b7bca27..449fe5270d3989 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadBufferState.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadBufferState.cs @@ -70,13 +70,7 @@ public readonly async ValueTask ReadFromStreamAsync( int minBufferCount = fillBuffer || _unsuccessfulReadCount > UnsuccessfulReadCountThreshold ? bufferState._buffer.Length : 0; do { - int bytesRead = await utf8Json.ReadAsync( -#if NET - bufferState._buffer.AsMemory(bufferState._count), -#else - bufferState._buffer, bufferState._count, bufferState._buffer.Length - bufferState._count, -#endif - cancellationToken).ConfigureAwait(false); + int bytesRead = await utf8Json.ReadAsync(bufferState._buffer.AsMemory(bufferState._count), cancellationToken).ConfigureAwait(false); if (bytesRead == 0) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Helpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Helpers.cs index a8440144d4cf88..00f927aae9c791 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Helpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Helpers.cs @@ -12,9 +12,9 @@ namespace System.Text.Json { public sealed partial class Utf8JsonWriter { - private bool HasPartialCodePoint => PartialCodePointLength != 0; + private bool HasPartialStringData => PartialStringDataLength != 0; - private void ClearPartialCodePoint() => PartialCodePointLength = 0; + private void ClearPartialStringData() => PartialStringDataLength = 0; private void ValidateEncodingDidNotChange(SegmentEncoding currentSegmentEncoding) { @@ -32,7 +32,7 @@ private void ValidateNotWithinUnfinalizedString() } Debug.Assert(PreviousSegmentEncoding == SegmentEncoding.None); - Debug.Assert(!HasPartialCodePoint); + Debug.Assert(!HasPartialStringData); } private void ValidateWritingValue() diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.StringSegment.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.StringSegment.cs index 08b517cce9648d..97efe65aba655c 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.StringSegment.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.StringSegment.cs @@ -3,10 +3,7 @@ using System.Buffers; using System.Buffers.Text; -using System.ComponentModel; using System.Diagnostics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; namespace System.Text.Json { @@ -34,7 +31,7 @@ public void WriteStringValueSegment(ReadOnlySpan value, bool isFinalSegmen if (_tokenType != Utf8JsonWriter.StringSegmentSentinel) { Debug.Assert(PreviousSegmentEncoding == SegmentEncoding.None); - Debug.Assert(!HasPartialCodePoint); + Debug.Assert(!HasPartialStringData); if (!_options.SkipValidation) { @@ -53,7 +50,7 @@ public void WriteStringValueSegment(ReadOnlySpan value, bool isFinalSegmen // The steps to write a string segment are to complete the previous partial code point // and escape either of which might not be required so there is a fast path for each of these steps. - if (HasPartialCodePoint) + if (HasPartialStringData) { WriteStringSegmentWithLeftover(value, isFinalSegment); } @@ -74,35 +71,35 @@ public void WriteStringValueSegment(ReadOnlySpan value, bool isFinalSegmen private void WriteStringSegmentWithLeftover(scoped ReadOnlySpan value, bool isFinalSegment) { - Debug.Assert(HasPartialCodePoint); + Debug.Assert(HasPartialStringData); Debug.Assert(PreviousSegmentEncoding == SegmentEncoding.Utf16); - scoped ReadOnlySpan partialCodePointBuffer = PartialUtf16CodePoint; + scoped ReadOnlySpan partialStringDataBuffer = PartialUtf16StringData; Span combinedBuffer = stackalloc char[2]; - combinedBuffer = combinedBuffer.Slice(0, ConcatInto(partialCodePointBuffer, value, combinedBuffer)); + combinedBuffer = combinedBuffer.Slice(0, ConcatInto(partialStringDataBuffer, value, combinedBuffer)); switch (Rune.DecodeFromUtf16(combinedBuffer, out _, out int charsConsumed)) { case OperationStatus.NeedMoreData: - Debug.Assert(value.Length + partialCodePointBuffer.Length < 2); - Debug.Assert(charsConsumed == value.Length + partialCodePointBuffer.Length); + Debug.Assert(value.Length + partialStringDataBuffer.Length < 2); + Debug.Assert(charsConsumed == value.Length + partialStringDataBuffer.Length); // Let the encoder deal with the error if this is a final buffer. value = combinedBuffer.Slice(0, charsConsumed); - partialCodePointBuffer = ReadOnlySpan.Empty; + partialStringDataBuffer = []; break; case OperationStatus.Done: - Debug.Assert(charsConsumed > partialCodePointBuffer.Length); + Debug.Assert(charsConsumed > partialStringDataBuffer.Length); Debug.Assert(charsConsumed <= 2); // Divide up the code point chars into its own buffer and the remainder of the input buffer. - value = value.Slice(charsConsumed - partialCodePointBuffer.Length); - partialCodePointBuffer = combinedBuffer.Slice(0, charsConsumed); + value = value.Slice(charsConsumed - partialStringDataBuffer.Length); + partialStringDataBuffer = combinedBuffer.Slice(0, charsConsumed); break; case OperationStatus.InvalidData: - Debug.Assert(charsConsumed >= partialCodePointBuffer.Length); + Debug.Assert(charsConsumed >= partialStringDataBuffer.Length); Debug.Assert(charsConsumed <= 2); - value = value.Slice(charsConsumed - partialCodePointBuffer.Length); - partialCodePointBuffer = combinedBuffer.Slice(0, charsConsumed); + value = value.Slice(charsConsumed - partialStringDataBuffer.Length); + partialStringDataBuffer = combinedBuffer.Slice(0, charsConsumed); break; case OperationStatus.DestinationTooSmall: default: @@ -111,7 +108,7 @@ private void WriteStringSegmentWithLeftover(scoped ReadOnlySpan value, boo } // The "isFinalSegment" argument indicates whether input that NeedsMoreData should be consumed as an error or not. - // Because we have validated above that partialCodePointBuffer will be the next consumed chars during Rune decoding + // Because we have validated above that partialStringDataBuffer will be the next consumed chars during Rune decoding // (even if this is because it is invalid), we should pass isFinalSegment = true to indicate to the decoder to // parse the code units without extra data. // @@ -119,9 +116,9 @@ private void WriteStringSegmentWithLeftover(scoped ReadOnlySpan value, boo // to determine that only the first unit should be consumed (as invalid). So this method will get only ['\uD800']. // Because we know more data will not be able to complete this code point, we need to pass isFinalSegment = true // to ensure that the encoder consumes this data eagerly instead of leaving it and returning NeedsMoreData. - WriteStringSegmentEscape(partialCodePointBuffer, true); + WriteStringSegmentEscape(partialStringDataBuffer, true); - ClearPartialCodePoint(); + ClearPartialStringData(); WriteStringSegmentEscape(value, isFinalSegment); } @@ -163,7 +160,7 @@ private void WriteStringSegmentEscapeValue(ReadOnlySpan value, int firstEs { Debug.Assert(!isFinalSegment); Debug.Assert(value.Length - consumed < 2); - PartialUtf16CodePoint = value.Slice(consumed); + PartialUtf16StringData = value.Slice(consumed); } if (valueArray != null) @@ -210,7 +207,7 @@ public void WriteStringValueSegment(ReadOnlySpan value, bool isFinalSegmen if (_tokenType != Utf8JsonWriter.StringSegmentSentinel) { Debug.Assert(PreviousSegmentEncoding == SegmentEncoding.None); - Debug.Assert(!HasPartialCodePoint); + Debug.Assert(!HasPartialStringData); if (!_options.SkipValidation) { @@ -229,7 +226,7 @@ public void WriteStringValueSegment(ReadOnlySpan value, bool isFinalSegmen // The steps to write a string segment are to complete the previous partial code point // and escape either of which might not be required so there is a fast path for each of these steps. - if (HasPartialCodePoint) + if (HasPartialStringData) { WriteStringSegmentWithLeftover(value, isFinalSegment); } @@ -250,35 +247,35 @@ public void WriteStringValueSegment(ReadOnlySpan value, bool isFinalSegmen private void WriteStringSegmentWithLeftover(scoped ReadOnlySpan utf8Value, bool isFinalSegment) { - Debug.Assert(HasPartialCodePoint); + Debug.Assert(HasPartialStringData); Debug.Assert(PreviousSegmentEncoding == SegmentEncoding.Utf8); - scoped ReadOnlySpan partialCodePointBuffer = PartialUtf8CodePoint; + scoped ReadOnlySpan partialStringDataBuffer = PartialUtf8StringData; Span combinedBuffer = stackalloc byte[4]; - combinedBuffer = combinedBuffer.Slice(0, ConcatInto(partialCodePointBuffer, utf8Value, combinedBuffer)); + combinedBuffer = combinedBuffer.Slice(0, ConcatInto(partialStringDataBuffer, utf8Value, combinedBuffer)); switch (Rune.DecodeFromUtf8(combinedBuffer, out _, out int bytesConsumed)) { case OperationStatus.NeedMoreData: - Debug.Assert(utf8Value.Length + partialCodePointBuffer.Length < 4); - Debug.Assert(bytesConsumed == utf8Value.Length + partialCodePointBuffer.Length); + Debug.Assert(utf8Value.Length + partialStringDataBuffer.Length < 4); + Debug.Assert(bytesConsumed == utf8Value.Length + partialStringDataBuffer.Length); // Let the encoder deal with the error if this is a final buffer. utf8Value = combinedBuffer.Slice(0, bytesConsumed); - partialCodePointBuffer = ReadOnlySpan.Empty; + partialStringDataBuffer = []; break; case OperationStatus.Done: - Debug.Assert(bytesConsumed > partialCodePointBuffer.Length); + Debug.Assert(bytesConsumed > partialStringDataBuffer.Length); Debug.Assert(bytesConsumed <= 4); // Divide up the code point bytes into its own buffer and the remainder of the input buffer. - utf8Value = utf8Value.Slice(bytesConsumed - partialCodePointBuffer.Length); - partialCodePointBuffer = combinedBuffer.Slice(0, bytesConsumed); + utf8Value = utf8Value.Slice(bytesConsumed - partialStringDataBuffer.Length); + partialStringDataBuffer = combinedBuffer.Slice(0, bytesConsumed); break; case OperationStatus.InvalidData: - Debug.Assert(bytesConsumed >= partialCodePointBuffer.Length); + Debug.Assert(bytesConsumed >= partialStringDataBuffer.Length); Debug.Assert(bytesConsumed <= 4); - utf8Value = utf8Value.Slice(bytesConsumed - partialCodePointBuffer.Length); - partialCodePointBuffer = combinedBuffer.Slice(0, bytesConsumed); + utf8Value = utf8Value.Slice(bytesConsumed - partialStringDataBuffer.Length); + partialStringDataBuffer = combinedBuffer.Slice(0, bytesConsumed); break; case OperationStatus.DestinationTooSmall: default: @@ -287,7 +284,7 @@ private void WriteStringSegmentWithLeftover(scoped ReadOnlySpan utf8Value, } // The "isFinalSegment" argument indicates whether input that NeedsMoreData should be consumed as an error or not. - // Because we have validated above that partialCodePointBuffer will be the next consumed bytes during Rune decoding + // Because we have validated above that partialStringDataBuffer will be the next consumed bytes during Rune decoding // (even if this is because it is invalid), we should pass isFinalSegment = true to indicate to the decoder to // parse the code units without extra data. // @@ -296,9 +293,9 @@ private void WriteStringSegmentWithLeftover(scoped ReadOnlySpan utf8Value, // So this method will get only <3-size prefix code unit>. Because we know more data will not be able // to complete this code point, we need to pass isFinalSegment = true to ensure that the encoder consumes this data eagerly // instead of leaving it and returning NeedsMoreData. - WriteStringSegmentEscape(partialCodePointBuffer, true); + WriteStringSegmentEscape(partialStringDataBuffer, true); - ClearPartialCodePoint(); + ClearPartialStringData(); WriteStringSegmentEscape(utf8Value, isFinalSegment); } @@ -337,7 +334,7 @@ private void WriteStringSegmentEscapeValue(ReadOnlySpan utf8Value, int fir { Debug.Assert(!isFinalSegment); Debug.Assert(utf8Value.Length - consumed < 4); - PartialUtf8CodePoint = utf8Value.Slice(consumed); + PartialUtf8StringData = utf8Value.Slice(consumed); } if (valueArray != null) @@ -363,6 +360,128 @@ private void WriteStringSegmentData(ReadOnlySpan escapedValue) BytesPending += escapedValue.Length; } + /// + /// Writes the input bytes as a partial JSON string. + /// + /// The bytes to be written as a JSON string element of a JSON array. + /// Indicates that this is the final segment of the string. + /// + /// Thrown when the specified value is too large. + /// + /// + /// Thrown if this would result in invalid JSON being written (while validation is enabled) or + /// if the previously written segment (if any) was not written with this same overload. + /// + public void WriteBase64StringSegment(ReadOnlySpan value, bool isFinalSegment) + { + if (value.Length > Base64.GetMaxDecodedFromUtf8Length(int.MaxValue)) + { + ThrowHelper.ThrowArgumentException_ValueTooLarge(value.Length); + } + + if (_tokenType != Utf8JsonWriter.StringSegmentSentinel) + { + Debug.Assert(PreviousSegmentEncoding == SegmentEncoding.None); + Debug.Assert(!HasPartialStringData); + + if (!_options.SkipValidation) + { + ValidateWritingValue(); + } + + WriteStringSegmentPrologue(); + + PreviousSegmentEncoding = SegmentEncoding.Base64; + _tokenType = Utf8JsonWriter.StringSegmentSentinel; + } + else + { + ValidateEncodingDidNotChange(SegmentEncoding.Base64); + } + + // The steps to write a string segment are to complete the previous partial string data + // and escape either of which might not be required so there is a fast path for each of these steps. + if (HasPartialStringData) + { + WriteBase64StringSegmentWithLeftover(value, isFinalSegment); + } + else + { + WriteBase64StringSegmentData(value, isFinalSegment); + } + + if (isFinalSegment) + { + WriteStringSegmentEpilogue(); + + SetFlagToAddListSeparatorBeforeNextItem(); + PreviousSegmentEncoding = SegmentEncoding.None; + _tokenType = JsonTokenType.String; + } + } + + private void WriteBase64StringSegmentWithLeftover(scoped ReadOnlySpan bytes, bool isFinalSegment) + { + Debug.Assert(HasPartialStringData); + Debug.Assert(PreviousSegmentEncoding == SegmentEncoding.Base64); + + scoped ReadOnlySpan partialStringDataBuffer = PartialBase64StringData; + + Span combinedBuffer = stackalloc byte[3]; + combinedBuffer = combinedBuffer.Slice(0, ConcatInto(partialStringDataBuffer, bytes, combinedBuffer)); + if (combinedBuffer.Length is 3) + { + // Divide up the partial bytes into its own buffer and the remainder of the input buffer. + bytes = bytes.Slice(3 - partialStringDataBuffer.Length); + partialStringDataBuffer = combinedBuffer.Slice(0, 3); + } + else + { + Debug.Assert(combinedBuffer.Length is 1 or 2); + // Need more data. If this is a final segment, then the encoder will append '=' as needed. + Debug.Assert(bytes.Length + partialStringDataBuffer.Length < 3); + bytes = combinedBuffer; + partialStringDataBuffer = []; + } + + // It doesn't matter if we pass true or false for isFinalSegment since we are guaranteed to not have partial data + // here (it is either empty or completed using the combined buffer above). + WriteBase64StringSegmentData(partialStringDataBuffer, false); + + ClearPartialStringData(); + + WriteBase64StringSegmentData(bytes, isFinalSegment); + } + + private void WriteBase64StringSegmentData(ReadOnlySpan bytes, bool isFinalSegment) + { + int leftoverSize; + if (!isFinalSegment && (leftoverSize = bytes.Length % 3) != 0) + { + // If this is not the final segment, we need to wait for more data to come in. + PartialBase64StringData = bytes.Slice(bytes.Length - leftoverSize); + bytes = bytes.Slice(0, bytes.Length - leftoverSize); + } + + if (bytes.Length == 0) + { + return; + } + + int requiredBytes = Base64.GetMaxEncodedToUtf8Length(bytes.Length); + + if (_memory.Length - BytesPending < requiredBytes) + { + Grow(requiredBytes); + } + + Span output = _memory.Span; + + // For non-final segments, the input is sliced to be a multiple of 3 bytes above which guarantees + // that the base64 encoding will never end with padding since 3x input bytes turn into exactly 4x base64 bytes. + Base64EncodeAndWrite(bytes, output); + } + private void WriteStringSegmentPrologue() { if (_options.Indented) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.cs index da9dc4b6bac503..fa5bc735d8c843 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.cs @@ -8,7 +8,6 @@ using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; -using System.ComponentModel; namespace System.Text.Json { @@ -38,12 +37,13 @@ public sealed partial class Utf8JsonWriter : IDisposable, IAsyncDisposable // A special value for JsonTokenType that lets the writer keep track of string segments. private const JsonTokenType StringSegmentSentinel = (JsonTokenType)255; - // Masks and flags for the length and encoding of the partial code point - private const byte PartialCodePointLengthMask = 0b000_000_11; - private const byte PartialCodePointEncodingMask = 0b000_111_00; + // Masks and flags for the length and encoding of the partial string data. + private const byte PartialStringDataLengthMask = 0b000_000_11; + private const byte PartialStringDataEncodingMask = 0b000_111_00; - private const byte PartialCodePointUtf8EncodingFlag = 0b000_001_00; - private const byte PartialCodePointUtf16EncodingFlag = 0b000_010_00; + private const byte PartialStringDataUtf8EncodingFlag = 0b000_001_00; + private const byte PartialStringDataUtf16EncodingFlag = 0b000_010_00; + private const byte PartialStringDataBase64EncodingFlag = 0b000_100_00; private IBufferWriter? _output; private Stream? _stream; @@ -57,15 +57,15 @@ public sealed partial class Utf8JsonWriter : IDisposable, IAsyncDisposable private BitStack _bitStack; /// - /// This 3-byte array stores the partial code point leftover when writing a string value + /// This 3-byte array stores the partial string data leftover when writing a string value /// segment that is split across multiple segment write calls. /// #if !NET - private byte[]? _partialCodePoint; - private Span PartialCodePointRaw => _partialCodePoint ??= new byte[3]; + private byte[]? _partialStringData; + private Span PartialStringDataRaw => _partialStringData ??= new byte[3]; #else - private Inline3ByteArray _partialCodePoint; - private Span PartialCodePointRaw => _partialCodePoint; + private Inline3ByteArray _partialStringData; + private Span PartialStringDataRaw => _partialStringData; [InlineArray(3)] private struct Inline3ByteArray @@ -75,11 +75,11 @@ private struct Inline3ByteArray #endif /// - /// Stores the length and encoding of the partial code point. Outside of segment writes, this value is 0. + /// Stores the length and encoding of the partial string data. Outside of segment writes, this value is 0. /// Across segment writes, this value is always non-zero even if the length is 0, to indicate the encoding of the segment. /// This allows detection of encoding changes across segment writes. /// - private byte _partialCodePointFlags; + private byte _partialStringDataFlags; // The highest order bit of _currentDepth is used to discern whether we are writing the first item in a list or not. // if (_currentDepth >> 31) == 1, add a list separator before writing the item @@ -128,68 +128,96 @@ private struct Inline3ByteArray public int CurrentDepth => _currentDepth & JsonConstants.RemoveFlagsBitMask; /// - /// Length of the partial code point. + /// Length of the partial string data. /// - private byte PartialCodePointLength + private byte PartialStringDataLength { - get => (byte)(_partialCodePointFlags & PartialCodePointLengthMask); - set => _partialCodePointFlags = (byte)((_partialCodePointFlags & ~PartialCodePointLengthMask) | (byte)value); + get => (byte)(_partialStringDataFlags & PartialStringDataLengthMask); + set => _partialStringDataFlags = (byte)((_partialStringDataFlags & ~PartialStringDataLengthMask) | value); } /// /// The partial UTF-8 code point. /// - private ReadOnlySpan PartialUtf8CodePoint + private ReadOnlySpan PartialUtf8StringData { get { Debug.Assert(PreviousSegmentEncoding == SegmentEncoding.Utf8); - ReadOnlySpan partialCodePointBytes = PartialCodePointRaw; - Debug.Assert(partialCodePointBytes.Length == 3); + ReadOnlySpan partialStringDataBytes = PartialStringDataRaw; + Debug.Assert(partialStringDataBytes.Length == 3); - byte length = PartialCodePointLength; + byte length = PartialStringDataLength; Debug.Assert(length < 4); - return partialCodePointBytes.Slice(0, length); + return partialStringDataBytes.Slice(0, length); } set { Debug.Assert(value.Length <= 3); - Span partialCodePointBytes = PartialCodePointRaw; + Span partialStringDataBytes = PartialStringDataRaw; - value.CopyTo(partialCodePointBytes); - PartialCodePointLength = (byte)value.Length; + value.CopyTo(partialStringDataBytes); + PartialStringDataLength = (byte)value.Length; } } /// /// The partial UTF-16 code point. /// - private ReadOnlySpan PartialUtf16CodePoint + private ReadOnlySpan PartialUtf16StringData { get { Debug.Assert(PreviousSegmentEncoding == SegmentEncoding.Utf16); - ReadOnlySpan partialCodePointBytes = PartialCodePointRaw; - Debug.Assert(partialCodePointBytes.Length == 3); + ReadOnlySpan partialStringDataBytes = PartialStringDataRaw; + Debug.Assert(partialStringDataBytes.Length == 3); - byte length = PartialCodePointLength; + byte length = PartialStringDataLength; Debug.Assert(length is 2 or 0); - return MemoryMarshal.Cast(partialCodePointBytes.Slice(0, length)); + return MemoryMarshal.Cast(partialStringDataBytes.Slice(0, length)); } set { Debug.Assert(value.Length <= 1); - Span partialCodePointBytes = PartialCodePointRaw; + Span partialStringDataBytes = PartialStringDataRaw; - value.CopyTo(MemoryMarshal.Cast(partialCodePointBytes)); - PartialCodePointLength = (byte)(2 * value.Length); + value.CopyTo(MemoryMarshal.Cast(partialStringDataBytes)); + PartialStringDataLength = (byte)(2 * value.Length); + } + } + + /// + /// The partial base64 data. + /// + private ReadOnlySpan PartialBase64StringData + { + get + { + Debug.Assert(PreviousSegmentEncoding == SegmentEncoding.Base64); + + ReadOnlySpan partialStringDataBytes = PartialStringDataRaw; + Debug.Assert(partialStringDataBytes.Length == 3); + + byte length = PartialStringDataLength; + Debug.Assert(length < 3); + + return partialStringDataBytes.Slice(0, length); + } + set + { + Debug.Assert(value.Length < 3); + + Span partialStringDataBytes = PartialStringDataRaw; + + value.CopyTo(partialStringDataBytes); + PartialStringDataLength = (byte)value.Length; } } @@ -198,18 +226,19 @@ private ReadOnlySpan PartialUtf16CodePoint /// private SegmentEncoding PreviousSegmentEncoding { - get => (SegmentEncoding)(_partialCodePointFlags & PartialCodePointEncodingMask); - set => _partialCodePointFlags = (byte)((_partialCodePointFlags & ~PartialCodePointEncodingMask) | (byte)value); + get => (SegmentEncoding)(_partialStringDataFlags & PartialStringDataEncodingMask); + set => _partialStringDataFlags = (byte)((_partialStringDataFlags & ~PartialStringDataEncodingMask) | (byte)value); } /// - /// Convenience enumeration to track the encoding of the partial code point. This must be kept in sync with the PartialCodePoint*Encoding flags. + /// Convenience enumeration to track the encoding of the partial string data. This must be kept in sync with the PartialStringData*Encoding flags. /// internal enum SegmentEncoding : byte { None = 0, - Utf8 = PartialCodePointUtf8EncodingFlag, - Utf16 = PartialCodePointUtf16EncodingFlag, + Utf8 = PartialStringDataUtf8EncodingFlag, + Utf16 = PartialStringDataUtf16EncodingFlag, + Base64 = PartialStringDataBase64EncodingFlag, } private Utf8JsonWriter() @@ -390,8 +419,8 @@ private void ResetHelper() _bitStack = default; - _partialCodePoint = default; - _partialCodePointFlags = default; + _partialStringData = default; + _partialStringDataFlags = default; } private void CheckNotDisposed() @@ -433,12 +462,7 @@ public void Flush() #if NET _stream.Write(_arrayBufferWriter.WrittenSpan); #else - Debug.Assert(_arrayBufferWriter.WrittenMemory.Length == _arrayBufferWriter.WrittenCount); - bool result = MemoryMarshal.TryGetArray(_arrayBufferWriter.WrittenMemory, out ArraySegment underlyingBuffer); - Debug.Assert(result); - Debug.Assert(underlyingBuffer.Offset == 0); - Debug.Assert(_arrayBufferWriter.WrittenCount == underlyingBuffer.Count); - _stream.Write(underlyingBuffer.Array, underlyingBuffer.Offset, underlyingBuffer.Count); + _stream.Write(_arrayBufferWriter.WrittenMemory); #endif BytesCommitted += _arrayBufferWriter.WrittenCount; @@ -544,16 +568,7 @@ public async Task FlushAsync(CancellationToken cancellationToken = default) _arrayBufferWriter.Advance(BytesPending); BytesPending = 0; -#if NET await _stream.WriteAsync(_arrayBufferWriter.WrittenMemory, cancellationToken).ConfigureAwait(false); -#else - Debug.Assert(_arrayBufferWriter.WrittenMemory.Length == _arrayBufferWriter.WrittenCount); - bool result = MemoryMarshal.TryGetArray(_arrayBufferWriter.WrittenMemory, out ArraySegment underlyingBuffer); - Debug.Assert(result); - Debug.Assert(underlyingBuffer.Offset == 0); - Debug.Assert(_arrayBufferWriter.WrittenCount == underlyingBuffer.Count); - await _stream.WriteAsync(underlyingBuffer.Array, underlyingBuffer.Offset, underlyingBuffer.Count, cancellationToken).ConfigureAwait(false); -#endif BytesCommitted += _arrayBufferWriter.WrittenCount; _arrayBufferWriter.Clear(); diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Utf8JsonWriterTests.Values.StringSegment.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Utf8JsonWriterTests.Values.StringSegment.cs index 9d95eeb0f9a26a..4a274ff926c5c6 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Utf8JsonWriterTests.Values.StringSegment.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Utf8JsonWriterTests.Values.StringSegment.cs @@ -4,10 +4,13 @@ using System.Buffers; +using System.Buffers.Text; using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text.Encodings.Web; +using System.Text.Unicode; using Xunit; namespace System.Text.Json.Tests @@ -62,7 +65,7 @@ public static void WriteStringValueSegment_Utf16_SplitCodePointsReplacement(char options.Encoder.Encode(inputArr, expectedChars, out int charsConsumed, out int charsWritten); Assert.Equal(inputArr.Length, charsConsumed); - SplitCodePointsHelper(inputArr, $@"""{new string(expectedChars, 0, charsWritten)}""", options); + SplitStringDataHelper(inputArr, options, $@"""{new string(expectedChars, 0, charsWritten)}""", StringValueEncodingType.Utf16); } public static IEnumerable InvalidUtf8Data() @@ -120,31 +123,34 @@ public static void WriteStringValueSegment_Utf8_SplitCodePointsReplacement(byte[ string expectedString = $@"""{Encoding.UTF8.GetString(expectedBytes, 0, bytesWritten)}"""; - SplitCodePointsHelper(inputArr, expectedString, options); + SplitStringDataHelper(inputArr, options, expectedString, StringValueEncodingType.Utf8); } - private static void SplitCodePointsHelper( + private static void SplitStringDataHelper( T[] inputArr, + JsonWriterOptions options, string expected, - JsonWriterOptions options) + StringValueEncodingType encoding) where T : struct { - SplitCodePointsHelper(inputArr, options, output => JsonTestHelper.AssertContents(expected, output)); + SplitStringDataHelper(inputArr, options, output => JsonTestHelper.AssertContents(expected, output), encoding); } - private static void SplitCodePointsHelper( + private static void SplitStringDataHelper( T[] inputArr, JsonWriterOptions options, - Action> assert) + Action> assert, + StringValueEncodingType encoding) where T : struct { - SplitCodePointsHelper(inputArr.AsSpan(), options, assert); + SplitStringDataHelper(inputArr.AsSpan(), options, assert, encoding); } - private static void SplitCodePointsHelper( + private static void SplitStringDataHelper( ReadOnlySpan inputArr, JsonWriterOptions options, - Action> assert) + Action> assert, + StringValueEncodingType encoding) where T : struct { ReadOnlySpan input = inputArr; @@ -155,7 +161,7 @@ private static void SplitCodePointsHelper( using (var writer = new Utf8JsonWriter(output, options)) { - WriteStringValueHelper(writer, input); + WriteStringValueHelper(writer, input, encoding); writer.Flush(); } @@ -168,7 +174,7 @@ private static void SplitCodePointsHelper( using (var writer = new Utf8JsonWriter(output, options)) { - WriteStringValueSegmentsHelper(writer, input.Slice(0, splitIndex), input.Slice(splitIndex)); + WriteStringValueSegmentsHelper(writer, input.Slice(0, splitIndex), input.Slice(splitIndex), encoding); writer.Flush(); } @@ -183,7 +189,7 @@ private static void SplitCodePointsHelper( using (var writer = new Utf8JsonWriter(output, options)) { - WriteStringValueSegmentsHelper(writer, input.Slice(0, splitIndex), input.Slice(splitIndex, splitIndex2 - splitIndex), input.Slice(splitIndex2)); + WriteStringValueSegmentsHelper(writer, input.Slice(0, splitIndex), input.Slice(splitIndex, splitIndex2 - splitIndex), input.Slice(splitIndex2), encoding); writer.Flush(); } @@ -201,9 +207,25 @@ public static void WriteStringValueSegment_Utf16_Basic(JsonWriterOptions options " Wor".AsSpan(), "ld!".AsSpan(), options.Encoder.Encode("Hello"), - options.Encoder.Encode(" Wor"), - options.Encoder.Encode("ld!"), - options); + options.Encoder.Encode("Hello Wor"), + options.Encoder.Encode("Hello World!"), + options, + StringValueEncodingType.Utf16); + } + + [Theory] + [MemberData(nameof(BasicStringJsonOptions_TestData))] + public static void WriteStringValueSegment_Utf16_BasicSplit(JsonWriterOptions options) + { + WriteStringValueSegment_BasicHelper( + "\uD800 <- Invalid Partial -> \uD800".AsSpan(), + "\uDC00 <- Partial".AsSpan(), + " Invalid -> \uD800".AsSpan(), + options.Encoder.Encode("\uD800 <- Invalid Partial -> \uD800"), + options.Encoder.Encode("\uD800 <- Invalid Partial -> \uD800\uDC00 <- Partial"), + options.Encoder.Encode("\uD800 <- Invalid Partial -> \uD800\uDC00 <- Partial Invalid -> \uD800"), + options, + StringValueEncodingType.Utf16); } [Theory] @@ -215,9 +237,57 @@ public static void WriteStringValueSegment_Utf8_Basic(JsonWriterOptions options) " Wor"u8, "ld!"u8, options.Encoder.Encode("Hello"), - options.Encoder.Encode(" Wor"), - options.Encoder.Encode("ld!"), - options); + options.Encoder.Encode("Hello Wor"), + options.Encoder.Encode("Hello World!"), + options, + StringValueEncodingType.Utf8); + } + + [Theory] + [MemberData(nameof(BasicStringJsonOptions_TestData))] + public static void WriteStringValueSegment_Utf8_BasicSplit(JsonWriterOptions options) + { + byte[] segment1 = [0b10_000000, .. " <- Invalid Partial -> "u8, 0b110_11111]; + byte[] segment2 = [0b10_111111, .. " <- Partial"u8]; + byte[] segment3 = [.. " Invalid -> "u8, 0b110_11111]; + WriteStringValueSegment_BasicHelper( + segment1, + segment2, + segment3, + // Since we're using string (base-16) encode for convenience, we just use an invalid utf-16 character + options.Encoder.Encode("\udc00 <- Invalid Partial -> \udc00"), + options.Encoder.Encode("\udc00 <- Invalid Partial -> \u07ff <- Partial"), + options.Encoder.Encode("\udc00 <- Invalid Partial -> \u07ff <- Partial Invalid -> \udc00"), + options, + StringValueEncodingType.Utf8); + } + + [Fact] + public static void WriteStringValueSegment_Base64_Basic() + { + { + WriteStringValueSegment_BasicHelper( + "Hello"u8, + " Worl"u8, + "d!"u8, + "SGVsbG8=", + "SGVsbG8gV29ybA==", + "SGVsbG8gV29ybGQh", + new JsonWriterOptions { Indented = false }, + StringValueEncodingType.Base64); + } + + { + WriteStringValueSegment_BasicHelper( + "Hello"u8, + " Worl"u8, + "d!"u8, + "SGVsbG8=", + "SGVsbG8gV29ybA==", + "SGVsbG8gV29ybGQh", + new JsonWriterOptions { Indented = true }, + StringValueEncodingType.Base64); + } } private static void WriteStringValueSegment_BasicHelper( @@ -227,27 +297,29 @@ private static void WriteStringValueSegment_BasicHelper( string expected1, string expected2, string expected3, - JsonWriterOptions options) + JsonWriterOptions options, + StringValueEncodingType encoding) where T : struct { + JavaScriptEncoder encoder = options.Encoder ?? JavaScriptEncoder.Default; string indent = options.Indented ? new string(options.IndentCharacter, options.IndentSize) : ""; string n = options.Indented ? options.NewLine : ""; string ni = n + indent; string nii = ni + indent; string s = options.Indented ? " " : ""; string e1 = '"' + expected1 + '"'; - string e2 = '"' + expected1 + expected2 + '"'; - string e3 = '"' + expected1 + expected2 + expected3 + '"'; - string foo = '"' + options.Encoder.Encode("foo") + '"'; - string bar = '"' + options.Encoder.Encode("bar") + '"'; - string baz = '"' + options.Encoder.Encode("baz") + '"'; - string inner = '"' + options.Encoder.Encode("inner") + '"'; + string e2 = '"' + expected2 + '"'; + string e3 = '"' + expected3 + '"'; + string foo = '"' + encoder.Encode("foo") + '"'; + string bar = '"' + encoder.Encode("bar") + '"'; + string baz = '"' + encoder.Encode("baz") + '"'; + string inner = '"' + encoder.Encode("inner") + '"'; // JSON string { var output = new ArrayBufferWriter(); using var jsonUtf8 = new Utf8JsonWriter(output, options); - WriteStringValueSegmentsHelper(jsonUtf8, segment1); + WriteStringValueSegmentsHelper(jsonUtf8, segment1, encoding); jsonUtf8.Flush(); JsonTestHelper.AssertContents(e1, output); @@ -256,7 +328,7 @@ private static void WriteStringValueSegment_BasicHelper( { var output = new ArrayBufferWriter(); using var jsonUtf8 = new Utf8JsonWriter(output, options); - WriteStringValueSegmentsHelper(jsonUtf8, segment1, segment2); + WriteStringValueSegmentsHelper(jsonUtf8, segment1, segment2, encoding); jsonUtf8.Flush(); JsonTestHelper.AssertContents(e2, output); @@ -265,7 +337,7 @@ private static void WriteStringValueSegment_BasicHelper( { var output = new ArrayBufferWriter(); using var jsonUtf8 = new Utf8JsonWriter(output, options); - WriteStringValueSegmentsHelper(jsonUtf8, segment1, segment2, segment3); + WriteStringValueSegmentsHelper(jsonUtf8, segment1, segment2, segment3, encoding); jsonUtf8.Flush(); JsonTestHelper.AssertContents(e3, output); @@ -276,7 +348,7 @@ private static void WriteStringValueSegment_BasicHelper( var output = new ArrayBufferWriter(); using var jsonUtf8 = new Utf8JsonWriter(output, options); jsonUtf8.WriteStartArray(); - WriteStringValueSegmentsHelper(jsonUtf8, segment1); + WriteStringValueSegmentsHelper(jsonUtf8, segment1, encoding); jsonUtf8.WriteEndArray(); jsonUtf8.Flush(); @@ -289,7 +361,7 @@ private static void WriteStringValueSegment_BasicHelper( var output = new ArrayBufferWriter(); using var jsonUtf8 = new Utf8JsonWriter(output, options); jsonUtf8.WriteStartArray(); - WriteStringValueSegmentsHelper(jsonUtf8, segment1, segment2); + WriteStringValueSegmentsHelper(jsonUtf8, segment1, segment2, encoding); jsonUtf8.WriteEndArray(); jsonUtf8.Flush(); @@ -302,7 +374,7 @@ private static void WriteStringValueSegment_BasicHelper( var output = new ArrayBufferWriter(); using var jsonUtf8 = new Utf8JsonWriter(output, options); jsonUtf8.WriteStartArray(); - WriteStringValueSegmentsHelper(jsonUtf8, segment1, segment2, segment3); + WriteStringValueSegmentsHelper(jsonUtf8, segment1, segment2, segment3, encoding); jsonUtf8.WriteEndArray(); jsonUtf8.Flush(); @@ -317,7 +389,7 @@ private static void WriteStringValueSegment_BasicHelper( using var jsonUtf8 = new Utf8JsonWriter(output, options); jsonUtf8.WriteStartArray(); jsonUtf8.WriteBooleanValue(true); - WriteStringValueSegmentsHelper(jsonUtf8, segment1); + WriteStringValueSegmentsHelper(jsonUtf8, segment1, encoding); jsonUtf8.WriteBooleanValue(false); jsonUtf8.WriteEndArray(); jsonUtf8.Flush(); @@ -332,7 +404,7 @@ private static void WriteStringValueSegment_BasicHelper( using var jsonUtf8 = new Utf8JsonWriter(output, options); jsonUtf8.WriteStartArray(); jsonUtf8.WriteBooleanValue(true); - WriteStringValueSegmentsHelper(jsonUtf8, segment1, segment2); + WriteStringValueSegmentsHelper(jsonUtf8, segment1, segment2, encoding); jsonUtf8.WriteBooleanValue(false); jsonUtf8.WriteEndArray(); jsonUtf8.Flush(); @@ -347,7 +419,7 @@ private static void WriteStringValueSegment_BasicHelper( using var jsonUtf8 = new Utf8JsonWriter(output, options); jsonUtf8.WriteStartArray(); jsonUtf8.WriteBooleanValue(true); - WriteStringValueSegmentsHelper(jsonUtf8, segment1, segment2, segment3); + WriteStringValueSegmentsHelper(jsonUtf8, segment1, segment2, segment3, encoding); jsonUtf8.WriteBooleanValue(false); jsonUtf8.WriteEndArray(); jsonUtf8.Flush(); @@ -364,7 +436,7 @@ private static void WriteStringValueSegment_BasicHelper( jsonUtf8.WriteStartArray(); jsonUtf8.WriteStartArray(); jsonUtf8.WriteBooleanValue(true); - WriteStringValueSegmentsHelper(jsonUtf8, segment1); + WriteStringValueSegmentsHelper(jsonUtf8, segment1, encoding); jsonUtf8.WriteBooleanValue(false); jsonUtf8.WriteEndArray(); jsonUtf8.WriteEndArray(); @@ -381,7 +453,7 @@ private static void WriteStringValueSegment_BasicHelper( jsonUtf8.WriteStartArray(); jsonUtf8.WriteStartArray(); jsonUtf8.WriteBooleanValue(true); - WriteStringValueSegmentsHelper(jsonUtf8, segment1, segment2); + WriteStringValueSegmentsHelper(jsonUtf8, segment1, segment2, encoding); jsonUtf8.WriteBooleanValue(false); jsonUtf8.WriteEndArray(); jsonUtf8.WriteEndArray(); @@ -398,7 +470,7 @@ private static void WriteStringValueSegment_BasicHelper( jsonUtf8.WriteStartArray(); jsonUtf8.WriteStartArray(); jsonUtf8.WriteBooleanValue(true); - WriteStringValueSegmentsHelper(jsonUtf8, segment1, segment2, segment3); + WriteStringValueSegmentsHelper(jsonUtf8, segment1, segment2, segment3, encoding); jsonUtf8.WriteBooleanValue(false); jsonUtf8.WriteEndArray(); jsonUtf8.WriteEndArray(); @@ -415,7 +487,7 @@ private static void WriteStringValueSegment_BasicHelper( using var jsonUtf8 = new Utf8JsonWriter(output, options); jsonUtf8.WriteStartObject(); jsonUtf8.WritePropertyName("foo"); - WriteStringValueSegmentsHelper(jsonUtf8, segment1); + WriteStringValueSegmentsHelper(jsonUtf8, segment1, encoding); jsonUtf8.WriteEndObject(); jsonUtf8.Flush(); @@ -429,7 +501,7 @@ private static void WriteStringValueSegment_BasicHelper( using var jsonUtf8 = new Utf8JsonWriter(output, options); jsonUtf8.WriteStartObject(); jsonUtf8.WritePropertyName("foo"); - WriteStringValueSegmentsHelper(jsonUtf8, segment1, segment2); + WriteStringValueSegmentsHelper(jsonUtf8, segment1, segment2, encoding); jsonUtf8.WriteEndObject(); jsonUtf8.Flush(); @@ -443,7 +515,7 @@ private static void WriteStringValueSegment_BasicHelper( using var jsonUtf8 = new Utf8JsonWriter(output, options); jsonUtf8.WriteStartObject(); jsonUtf8.WritePropertyName("foo"); - WriteStringValueSegmentsHelper(jsonUtf8, segment1, segment2, segment3); + WriteStringValueSegmentsHelper(jsonUtf8, segment1, segment2, segment3, encoding); jsonUtf8.WriteEndObject(); jsonUtf8.Flush(); @@ -459,7 +531,7 @@ private static void WriteStringValueSegment_BasicHelper( jsonUtf8.WriteStartObject(); jsonUtf8.WriteBoolean("bar", true); jsonUtf8.WritePropertyName("foo"); - WriteStringValueSegmentsHelper(jsonUtf8, segment1); + WriteStringValueSegmentsHelper(jsonUtf8, segment1, encoding); jsonUtf8.WriteBoolean("baz", false); jsonUtf8.WriteEndObject(); jsonUtf8.Flush(); @@ -475,7 +547,7 @@ private static void WriteStringValueSegment_BasicHelper( jsonUtf8.WriteStartObject(); jsonUtf8.WriteBoolean("bar", true); jsonUtf8.WritePropertyName("foo"); - WriteStringValueSegmentsHelper(jsonUtf8, segment1, segment2); + WriteStringValueSegmentsHelper(jsonUtf8, segment1, segment2, encoding); jsonUtf8.WriteBoolean("baz", false); jsonUtf8.WriteEndObject(); jsonUtf8.Flush(); @@ -491,7 +563,7 @@ private static void WriteStringValueSegment_BasicHelper( jsonUtf8.WriteStartObject(); jsonUtf8.WriteBoolean("bar", true); jsonUtf8.WritePropertyName("foo"); - WriteStringValueSegmentsHelper(jsonUtf8, segment1, segment2, segment3); + WriteStringValueSegmentsHelper(jsonUtf8, segment1, segment2, segment3, encoding); jsonUtf8.WriteBoolean("baz", false); jsonUtf8.WriteEndObject(); jsonUtf8.Flush(); @@ -509,7 +581,7 @@ private static void WriteStringValueSegment_BasicHelper( jsonUtf8.WriteStartObject("inner"); jsonUtf8.WriteBoolean("bar", true); jsonUtf8.WritePropertyName("foo"); - WriteStringValueSegmentsHelper(jsonUtf8, segment1); + WriteStringValueSegmentsHelper(jsonUtf8, segment1, encoding); jsonUtf8.WriteBoolean("baz", false); jsonUtf8.WriteEndObject(); jsonUtf8.WriteEndObject(); @@ -527,7 +599,7 @@ private static void WriteStringValueSegment_BasicHelper( jsonUtf8.WriteStartObject("inner"); jsonUtf8.WriteBoolean("bar", true); jsonUtf8.WritePropertyName("foo"); - WriteStringValueSegmentsHelper(jsonUtf8, segment1, segment2); + WriteStringValueSegmentsHelper(jsonUtf8, segment1, segment2, encoding); jsonUtf8.WriteBoolean("baz", false); jsonUtf8.WriteEndObject(); jsonUtf8.WriteEndObject(); @@ -545,7 +617,7 @@ private static void WriteStringValueSegment_BasicHelper( jsonUtf8.WriteStartObject("inner"); jsonUtf8.WriteBoolean("bar", true); jsonUtf8.WritePropertyName("foo"); - WriteStringValueSegmentsHelper(jsonUtf8, segment1, segment2, segment3); + WriteStringValueSegmentsHelper(jsonUtf8, segment1, segment2, segment3, encoding); jsonUtf8.WriteBoolean("baz", false); jsonUtf8.WriteEndObject(); jsonUtf8.WriteEndObject(); @@ -639,6 +711,17 @@ public static void WriteStringValueSegment_Utf8_Split8CodePointsBasic() JsonTestHelper.AssertContents($"{{\"full\":\"{result}\",\"segmented\":\"{result}\"}}", output); } + [Theory] + [InlineData("", "")] + [InlineData("0 padding", "MCBwYWRkaW5n")] + [InlineData("_1 padding", "XzEgcGFkZGluZw==")] + [InlineData("__2 padding", "X18yIHBhZGRpbmc=")] + public static void WriteStringValueSegment_Base64_SplitDataBasic(string input, string expected) + { + byte[] bytes = input.Select(c => (byte)c).ToArray(); + SplitStringDataHelper(bytes, new JsonWriterOptions { Indented = true }, "\"" + expected + "\"", StringValueEncodingType.Base64); + } + [Fact] public static void WriteStringValueSegment_Utf8_ClearedPartial() { @@ -699,9 +782,9 @@ public static void WriteStringValueSegment_Utf16_ClearedPartial() jsonUtf8.WriteStartArray(); - WriteStringValueSegmentsHelper(jsonUtf8, ['\uD800'], ['\uDC00']); - WriteStringValueSegmentsHelper(jsonUtf8, ['\uDC00']); - WriteStringValueSegmentsHelper(jsonUtf8, ['\uD800'], ['\uDC00'], ['\uDC00']); + WriteStringValueSegmentsHelper(jsonUtf8, ['\uD800'], ['\uDC00'], StringValueEncodingType.Utf16); + WriteStringValueSegmentsHelper(jsonUtf8, ['\uDC00'], StringValueEncodingType.Utf16); + WriteStringValueSegmentsHelper(jsonUtf8, ['\uD800'], ['\uDC00'], ['\uDC00'], StringValueEncodingType.Utf16); jsonUtf8.WriteEndArray(); @@ -712,22 +795,108 @@ public static void WriteStringValueSegment_Utf16_ClearedPartial() } } + [Fact] + public static void WriteStringValueSegment_Base64_ClearedPartial() + { + var output = new ArrayBufferWriter(); + + { + var expected = new StringBuilder(); + using var jsonUtf8 = new Utf8JsonWriter(output); + + jsonUtf8.WriteStartArray(); + expected.Append('['); + + // Helpers to build up the expected string + var buffer = new List(); + ReadOnlySpan AddPartial(ReadOnlySpan arr) + { + foreach (byte b in arr) buffer.Add(b); + + return arr; + } + + ReadOnlySpan AddFinal(ReadOnlySpan arr) + { + foreach (byte b in arr) buffer.Add(b); + + expected.Append('"'); + expected.Append(Convert.ToBase64String(buffer.ToArray())); + expected.Append('"'); + expected.Append(','); + buffer.Clear(); + + return arr; + } + + // 1 segment + WriteStringValueSegmentsHelper(jsonUtf8, AddFinal([]), StringValueEncodingType.Base64); + WriteStringValueSegmentsHelper(jsonUtf8, AddFinal([0]), StringValueEncodingType.Base64); + WriteStringValueSegmentsHelper(jsonUtf8, AddFinal([0, 1]), StringValueEncodingType.Base64); + WriteStringValueSegmentsHelper(jsonUtf8, AddFinal([0, 1, 2]), StringValueEncodingType.Base64); + + // 2 segments + for (int i = 0; i <= 3; i++) + { + for (int j = 0; j <= 3; j++) + { + WriteStringValueSegmentsHelper( + jsonUtf8, + AddPartial([..Enumerable.Range(0, i).Select(x => (byte)x)]), + AddFinal([..Enumerable.Range(i, j).Select(x => (byte)x)]), + StringValueEncodingType.Base64); + } + } + + // 3 segments + for (int i = 0; i <= 3; i++) + { + for (int j = 0; j <= 3; j++) + { + for (int k = 0; k <= 3; k++) + { + WriteStringValueSegmentsHelper( + jsonUtf8, + AddPartial([..Enumerable.Range(0, i).Select(x => (byte)x)]), + AddPartial([..Enumerable.Range(i, j).Select(x => (byte)x)]), + AddFinal([.. Enumerable.Range(i + j, k).Select(x => (byte)x)]), + StringValueEncodingType.Base64); + } + } + } + + // Remove trailing comma + expected.Remove(expected.Length - 1, 1); + + jsonUtf8.WriteEndArray(); + expected.Append(']'); + + jsonUtf8.Flush(); + + // First code point is written and the second is replaced. + JsonTestHelper.AssertContents(expected.ToString(), output); + } + } + [Fact] public static void WriteStringValueSegment_Flush() { var noEscape = JavaScriptEncoder.UnsafeRelaxedJsonEscaping; - TestFlushImpl('\uD800', '\uDC00', new(), @"""\uD800\uDC00"""); - TestFlushImpl(0b110_11111, 0b10_111111, new(), @"""\u07FF"""); - TestFlushImpl(0b110_11111, 0b10_111111, new() { Encoder = noEscape }, "\"\u07FF\""); - - void TestFlushImpl(T unit1, T unit2, JsonWriterOptions options, string expected) + TestFlushImpl(['\uD800'], ['\uDC00'], new(), @"""\uD800\uDC00""", StringValueEncodingType.Utf16); + TestFlushImpl([0b110_11111], [0b10_111111], new(), @"""\u07FF""", StringValueEncodingType.Utf8); + TestFlushImpl([0b110_11111], [0b10_111111], new() { Encoder = noEscape }, "\"\u07FF\"", StringValueEncodingType.Utf8); + TestFlushImpl([], [0, 0, 0], new(), "\"AAAA\"", StringValueEncodingType.Base64); + TestFlushImpl([0], [0, 0], new(), "\"AAAA\"", StringValueEncodingType.Base64); + TestFlushImpl([0, 0], [0], new(), "\"AAAA\"", StringValueEncodingType.Base64); + + void TestFlushImpl(ReadOnlySpan unit1, ReadOnlySpan unit2, JsonWriterOptions options, string expected, StringValueEncodingType encoding) where T : struct { byte[] expectedBytes = Encoding.UTF8.GetBytes(expected); var output = new ArrayBufferWriter(); using Utf8JsonWriter jsonUtf8 = new(output, options); - WriteStringValueSegmentHelper(jsonUtf8, [unit1], false); + WriteStringValueSegmentHelper(jsonUtf8, unit1, false, encoding); Assert.Equal(0, output.WrittenCount); Assert.Equal(0, jsonUtf8.BytesCommitted); @@ -738,7 +907,7 @@ void TestFlushImpl(T unit1, T unit2, JsonWriterOptions options, string expect Assert.Equal(1, jsonUtf8.BytesCommitted); Assert.Equal(0, jsonUtf8.BytesPending); - WriteStringValueSegmentHelper(jsonUtf8, [unit2], true); + WriteStringValueSegmentHelper(jsonUtf8, unit2, true, encoding); Assert.Equal(1, output.WrittenCount); Assert.Equal(1, jsonUtf8.BytesCommitted); @@ -813,6 +982,36 @@ public static void WriteStringValueSegment_Utf8_Reset() JsonTestHelper.AssertContents('"' + expected, output); } + [Fact] + public static void WriteStringValueSegment_Base64_Reset() + { + var output = new ArrayBufferWriter(); + using var jsonUtf8 = new Utf8JsonWriter(output); + + jsonUtf8.WriteBase64StringSegment([0], false); + jsonUtf8.Flush(); + + Assert.Equal(0, jsonUtf8.BytesPending); + Assert.Equal(1, jsonUtf8.BytesCommitted); + + jsonUtf8.Reset(); + + Assert.Equal(0, jsonUtf8.BytesPending); + Assert.Equal(0, jsonUtf8.BytesCommitted); + + jsonUtf8.WriteBase64StringSegment([0, 0, 0], true); + + string expected = @"""AAAA"""; + Assert.Equal(expected.Length, jsonUtf8.BytesPending); + Assert.Equal(0, jsonUtf8.BytesCommitted); + + jsonUtf8.Flush(); + + Assert.Equal(0, jsonUtf8.BytesPending); + Assert.Equal(expected.Length, jsonUtf8.BytesCommitted); + JsonTestHelper.AssertContents('"' + expected, output); + } + [Fact] public static void WriteStringValueSegment_MixEncoding() { @@ -826,6 +1025,26 @@ public static void WriteStringValueSegment_MixEncoding() Assert.Throws(() => jsonUtf8.WriteStringValueSegment([0b10_111111], true)); } + { + var output = new ArrayBufferWriter(); + using var jsonUtf8 = new Utf8JsonWriter(output); + + // High surrogate + jsonUtf8.WriteStringValueSegment("\uD8D8".AsSpan(), false); + + Assert.Throws(() => jsonUtf8.WriteBase64StringSegment([0], true)); + } + + { + var output = new ArrayBufferWriter(); + using var jsonUtf8 = new Utf8JsonWriter(output); + + // Start of a 3-byte sequence + jsonUtf8.WriteStringValueSegment([0b1110_1111], false); + + Assert.Throws(() => jsonUtf8.WriteStringValueSegment("\u8080".AsSpan(), true)); + } + { var output = new ArrayBufferWriter(); using var jsonUtf8 = new Utf8JsonWriter(output); @@ -833,6 +1052,26 @@ public static void WriteStringValueSegment_MixEncoding() // Start of a 3-byte sequence jsonUtf8.WriteStringValueSegment([0b1110_1111], false); + Assert.Throws(() => jsonUtf8.WriteBase64StringSegment([0], true)); + } + + { + var output = new ArrayBufferWriter(); + using var jsonUtf8 = new Utf8JsonWriter(output); + + // Partial Base64 + jsonUtf8.WriteBase64StringSegment([0], false); + + Assert.Throws(() => jsonUtf8.WriteStringValueSegment([0b10_111111], true)); + } + + { + var output = new ArrayBufferWriter(); + using var jsonUtf8 = new Utf8JsonWriter(output); + + // Partial Base64 + jsonUtf8.WriteBase64StringSegment([0], false); + Assert.Throws(() => jsonUtf8.WriteStringValueSegment("\u8080".AsSpan(), true)); } @@ -852,6 +1091,38 @@ public static void WriteStringValueSegment_MixEncoding() Assert.Throws(() => jsonUtf8.WriteStringValueSegment(ReadOnlySpan.Empty, false)); } + { + var output = new ArrayBufferWriter(); + using var jsonUtf8 = new Utf8JsonWriter(output); + jsonUtf8.WriteStringValueSegment([0b110_11111], false); + jsonUtf8.Flush(); + JsonTestHelper.AssertContents("\"", output); + + // Writing empty base64 sequence will still keep the partial code point + jsonUtf8.WriteStringValueSegment(ReadOnlySpan.Empty, false); + jsonUtf8.Flush(); + JsonTestHelper.AssertContents("\"", output); + + // Writing empty UTF-8 sequence will throw + Assert.Throws(() => jsonUtf8.WriteBase64StringSegment(ReadOnlySpan.Empty, false)); + } + + { + var output = new ArrayBufferWriter(); + using var jsonUtf8 = new Utf8JsonWriter(output); + jsonUtf8.WriteStringValueSegment(['\uD800'], false); + jsonUtf8.Flush(); + JsonTestHelper.AssertContents("\"", output); + + // Writing empty UTF-16 sequence will still keep the partial code point + jsonUtf8.WriteStringValueSegment(ReadOnlySpan.Empty, false); + jsonUtf8.Flush(); + JsonTestHelper.AssertContents("\"", output); + + // Writing empty UTF-8 sequence will throw + Assert.Throws(() => jsonUtf8.WriteStringValueSegment(ReadOnlySpan.Empty, false)); + } + { var output = new ArrayBufferWriter(); using var jsonUtf8 = new Utf8JsonWriter(output); @@ -864,9 +1135,41 @@ public static void WriteStringValueSegment_MixEncoding() jsonUtf8.Flush(); JsonTestHelper.AssertContents("\"", output); - // Writing empty UTF-8 sequence will dump the partial UTF-16 code point + // Writing empty base64 sequence will throw + Assert.Throws(() => jsonUtf8.WriteBase64StringSegment(ReadOnlySpan.Empty, false)); + } + + { + var output = new ArrayBufferWriter(); + using var jsonUtf8 = new Utf8JsonWriter(output); + jsonUtf8.WriteBase64StringSegment([0], false); + jsonUtf8.Flush(); + JsonTestHelper.AssertContents("\"", output); + + // Writing empty base64 sequence will still keep the partial code point + jsonUtf8.WriteBase64StringSegment(ReadOnlySpan.Empty, false); + jsonUtf8.Flush(); + JsonTestHelper.AssertContents("\"", output); + + // Writing empty UTF-8 sequence will throw Assert.Throws(() => jsonUtf8.WriteStringValueSegment(ReadOnlySpan.Empty, false)); } + + { + var output = new ArrayBufferWriter(); + using var jsonUtf8 = new Utf8JsonWriter(output); + jsonUtf8.WriteBase64StringSegment([0], false); + jsonUtf8.Flush(); + JsonTestHelper.AssertContents("\"", output); + + // Writing empty base64 sequence will still keep the partial code point + jsonUtf8.WriteBase64StringSegment(ReadOnlySpan.Empty, false); + jsonUtf8.Flush(); + JsonTestHelper.AssertContents("\"", output); + + // Writing empty UTF-16 sequence will throw + Assert.Throws(() => jsonUtf8.WriteStringValueSegment(ReadOnlySpan.Empty, false)); + } } [Fact] @@ -941,146 +1244,191 @@ public static void WriteStringValueSegment_Empty() jsonUtf8.Flush(); JsonTestHelper.AssertContents("\"\"", output); } - } - // Switch this to use an enum discriminator input when base64 is supported - private static void WriteStringValueHelper(Utf8JsonWriter writer, ReadOnlySpan value) - where T : struct - { - if (typeof(T) == typeof(char)) - { - writer.WriteStringValue(MemoryMarshal.Cast(value)); - } - else if (typeof(T) == typeof(byte)) { - writer.WriteStringValue(MemoryMarshal.Cast(value)); + var output = new ArrayBufferWriter(); + using var jsonUtf8 = new Utf8JsonWriter(output); + jsonUtf8.WriteBase64StringSegment([], true); + jsonUtf8.Flush(); + JsonTestHelper.AssertContents("\"\"", output); } - else + { - if (typeof(T) == typeof(int)) - { - Assert.Fail($"Did you pass in int or int[] instead of byte or byte[]? Type {typeof(T)} is not supported by {nameof(WriteStringValueHelper)}."); - } - else - { - Assert.Fail($"Type {typeof(T)} is not supported by {nameof(WriteStringValueHelper)}."); - } + var output = new ArrayBufferWriter(); + using var jsonUtf8 = new Utf8JsonWriter(output); + jsonUtf8.WriteBase64StringSegment([], false); + jsonUtf8.Flush(); + JsonTestHelper.AssertContents("\"", output); } - } - // Switch this to use an enum discriminator input when base64 is supported - private static void WriteStringValueSegmentHelper(Utf8JsonWriter writer, ReadOnlySpan value, bool isFinal) - where T : struct - { - if (typeof(T) == typeof(char)) { - writer.WriteStringValueSegment(MemoryMarshal.Cast(value), isFinal); + var output = new ArrayBufferWriter(); + using var jsonUtf8 = new Utf8JsonWriter(output); + jsonUtf8.WriteBase64StringSegment([], false); + jsonUtf8.WriteBase64StringSegment([], true); + jsonUtf8.Flush(); + JsonTestHelper.AssertContents("\"\"", output); } - else if (typeof(T) == typeof(byte)) + { - writer.WriteStringValueSegment(MemoryMarshal.Cast(value), isFinal); + var output = new ArrayBufferWriter(); + using var jsonUtf8 = new Utf8JsonWriter(output); + jsonUtf8.WriteBase64StringSegment([], false); + jsonUtf8.WriteBase64StringSegment([], false); + jsonUtf8.WriteBase64StringSegment([], true); + jsonUtf8.Flush(); + JsonTestHelper.AssertContents("\"\"", output); } - else + } + + enum StringValueEncodingType + { + Utf8, + Utf16, + Base64, + } + + private static void EnsureByteOrChar([CallerMemberName]string caller = "") + { + if (typeof(T) != typeof(byte) && typeof(T) != typeof(char)) { if (typeof(T) == typeof(int)) { - Assert.Fail($"Did you pass in int or int[] instead of byte or byte[]? Type {typeof(T)} is not supported by {nameof(WriteStringValueSegmentsHelper)}."); - } - else - { - Assert.Fail($"Type {typeof(T)} is not supported by {nameof(WriteStringValueSegmentsHelper)}."); + Assert.Fail($"Did you pass in int or int[] instead of byte or byte[]? Type {typeof(T)} is not supported by {caller}."); } + + Assert.Fail($"Type {typeof(T)} is not supported by {caller}."); } } - // Switch this to use an enum discriminator input when base64 is supported - private static void WriteStringValueSegmentsHelper(Utf8JsonWriter writer, ReadOnlySpan value) + private static void WriteStringValueHelper(Utf8JsonWriter writer, ReadOnlySpan value, StringValueEncodingType encoding) where T : struct { - if (typeof(T) == typeof(char)) + EnsureByteOrChar(); + + switch (encoding) { - writer.WriteStringValueSegment(MemoryMarshal.Cast(value), true); + case StringValueEncodingType.Utf16: + writer.WriteStringValue(MemoryMarshal.Cast(value)); + break; + case StringValueEncodingType.Utf8: + writer.WriteStringValue(MemoryMarshal.Cast(value)); + break; + case StringValueEncodingType.Base64: + writer.WriteBase64StringValue(MemoryMarshal.Cast(value)); + break; + default: + Assert.Fail($"Encoding {encoding} not valid."); + break; } - else if (typeof(T) == typeof(byte)) + } + + private static void WriteStringValueSegmentHelper(Utf8JsonWriter writer, ReadOnlySpan value, bool isFinal, StringValueEncodingType encoding) + where T : struct + { + EnsureByteOrChar(); + + switch (encoding) { - writer.WriteStringValueSegment(MemoryMarshal.Cast(value), true); + case StringValueEncodingType.Utf16: + writer.WriteStringValueSegment(MemoryMarshal.Cast(value), isFinal); + break; + case StringValueEncodingType.Utf8: + writer.WriteStringValueSegment(MemoryMarshal.Cast(value), isFinal); + break; + case StringValueEncodingType.Base64: + writer.WriteBase64StringSegment(MemoryMarshal.Cast(value), isFinal); + break; + default: + Assert.Fail($"Encoding {encoding} not valid."); + break; } - else + } + + private static void WriteStringValueSegmentsHelper(Utf8JsonWriter writer, ReadOnlySpan value, StringValueEncodingType encoding) + where T : struct + { + EnsureByteOrChar(); + + switch (encoding) { - if (typeof(T) == typeof(int)) - { - Assert.Fail($"Did you pass in int or int[] instead of byte or byte[]? Type {typeof(T)} is not supported by {nameof(WriteStringValueSegmentsHelper)}."); - } - else - { - Assert.Fail($"Type {typeof(T)} is not supported by {nameof(WriteStringValueSegmentsHelper)}."); - } + case StringValueEncodingType.Utf16: + writer.WriteStringValueSegment(MemoryMarshal.Cast(value), true); + break; + case StringValueEncodingType.Utf8: + writer.WriteStringValueSegment(MemoryMarshal.Cast(value), true); + break; + case StringValueEncodingType.Base64: + writer.WriteBase64StringSegment(MemoryMarshal.Cast(value), true); + break; + default: + Assert.Fail($"Encoding {encoding} not valid."); + break; } } // Switch this to use an enum discriminator input when base64 is supported - private static void WriteStringValueSegmentsHelper(Utf8JsonWriter writer, ReadOnlySpan value1, ReadOnlySpan value2) + private static void WriteStringValueSegmentsHelper(Utf8JsonWriter writer, ReadOnlySpan value1, ReadOnlySpan value2, StringValueEncodingType encoding) where T : struct { - if (typeof(T) == typeof(char)) - { - writer.WriteStringValueSegment(MemoryMarshal.Cast(value1), false); - writer.WriteStringValueSegment(MemoryMarshal.Cast(value2), true); - } - else if (typeof(T) == typeof(byte)) - { - writer.WriteStringValueSegment(MemoryMarshal.Cast(value1), false); - writer.WriteStringValueSegment(MemoryMarshal.Cast(value2), true); - } - else + EnsureByteOrChar(); + + switch (encoding) { - if (typeof(T) == typeof(int)) - { - Assert.Fail($"Did you pass in int or int[] instead of byte or byte[]? Type {typeof(T)} is not supported by {nameof(WriteStringValueSegmentsHelper)}."); - } - else - { - Assert.Fail($"Type {typeof(T)} is not supported by {nameof(WriteStringValueSegmentsHelper)}."); - } + case StringValueEncodingType.Utf16: + writer.WriteStringValueSegment(MemoryMarshal.Cast(value1), false); + writer.WriteStringValueSegment(MemoryMarshal.Cast(value2), true); + break; + case StringValueEncodingType.Utf8: + writer.WriteStringValueSegment(MemoryMarshal.Cast(value1), false); + writer.WriteStringValueSegment(MemoryMarshal.Cast(value2), true); + break; + case StringValueEncodingType.Base64: + writer.WriteBase64StringSegment(MemoryMarshal.Cast(value1), false); + writer.WriteBase64StringSegment(MemoryMarshal.Cast(value2), true); + break; + default: + Assert.Fail($"Encoding {encoding} not valid."); + break; } } // Switch this to use an enum discriminator input when base64 is supported - private static void WriteStringValueSegmentsHelper(Utf8JsonWriter writer, ReadOnlySpan value1, ReadOnlySpan value2, ReadOnlySpan value3) + private static void WriteStringValueSegmentsHelper(Utf8JsonWriter writer, ReadOnlySpan value1, ReadOnlySpan value2, ReadOnlySpan value3, StringValueEncodingType encoding) where T : struct { - if (typeof(T) == typeof(char)) - { - writer.WriteStringValueSegment(MemoryMarshal.Cast(value1), false); - writer.WriteStringValueSegment(MemoryMarshal.Cast(value2), false); - writer.WriteStringValueSegment(MemoryMarshal.Cast(value3), true); - } - else if (typeof(T) == typeof(byte)) - { - writer.WriteStringValueSegment(MemoryMarshal.Cast(value1), false); - writer.WriteStringValueSegment(MemoryMarshal.Cast(value2), false); - writer.WriteStringValueSegment(MemoryMarshal.Cast(value3), true); - } - else + EnsureByteOrChar(); + + switch (encoding) { - if (typeof(T) == typeof(int)) - { - Assert.Fail($"Did you pass in int or int[] instead of byte or byte[]? Type {typeof(T)} is not supported by {nameof(WriteStringValueSegmentsHelper)}."); - } - else - { - Assert.Fail($"Type {typeof(T)} is not supported by {nameof(WriteStringValueSegmentsHelper)}."); - } + case StringValueEncodingType.Utf16: + writer.WriteStringValueSegment(MemoryMarshal.Cast(value1), false); + writer.WriteStringValueSegment(MemoryMarshal.Cast(value2), false); + writer.WriteStringValueSegment(MemoryMarshal.Cast(value3), true); + break; + case StringValueEncodingType.Utf8: + writer.WriteStringValueSegment(MemoryMarshal.Cast(value1), false); + writer.WriteStringValueSegment(MemoryMarshal.Cast(value2), false); + writer.WriteStringValueSegment(MemoryMarshal.Cast(value3), true); + break; + case StringValueEncodingType.Base64: + writer.WriteBase64StringSegment(MemoryMarshal.Cast(value1), false); + writer.WriteBase64StringSegment(MemoryMarshal.Cast(value2), false); + writer.WriteBase64StringSegment(MemoryMarshal.Cast(value3), true); + break; + default: + Assert.Fail($"Encoding {encoding} not valid."); + break; } } - private static void WriteStringValueSegmentsHelper(Utf8JsonWriter writer, string value) - => WriteStringValueSegmentsHelper(writer, value.AsSpan()); + private static void WriteStringValueSegmentsHelper(Utf8JsonWriter writer, string value, StringValueEncodingType encoding) + => WriteStringValueSegmentsHelper(writer, value.AsSpan(), encoding); - private static void WriteStringValueSegmentsHelper(Utf8JsonWriter writer, string value1, string value2) - => WriteStringValueSegmentsHelper(writer, value1.AsSpan(), value2.AsSpan()); + private static void WriteStringValueSegmentsHelper(Utf8JsonWriter writer, string value1, string value2, StringValueEncodingType encoding) + => WriteStringValueSegmentsHelper(writer, value1.AsSpan(), value2.AsSpan(), encoding); - private static void WriteStringValueSegmentsHelper(Utf8JsonWriter writer, string value1, string value2, string value3) - => WriteStringValueSegmentsHelper(writer, value1.AsSpan(), value2.AsSpan(), value3.AsSpan()); + private static void WriteStringValueSegmentsHelper(Utf8JsonWriter writer, string value1, string value2, string value3, StringValueEncodingType encoding) + => WriteStringValueSegmentsHelper(writer, value1.AsSpan(), value2.AsSpan(), value3.AsSpan(), encoding); } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Utf8JsonWriterTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Utf8JsonWriterTests.cs index 382349214beb1b..b9564958092f9a 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Utf8JsonWriterTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Utf8JsonWriterTests.cs @@ -272,17 +272,17 @@ public void EscapingTestWhileWriting(char replacementChar, JavaScriptEncoder enc if (dataLength < 10) { - SplitCodePointsHelper(changed, writerOptions, output => + SplitStringDataHelper(newStr.AsSpan(), writerOptions, output => { escapedIndex = output.WrittenSpan.IndexOf((byte)'\\'); Assert.Equal(requiresEscaping ? (i + 1) : -1, escapedIndex); // Account for the start quote - }); + }, StringValueEncodingType.Utf16); - SplitCodePointsHelper(changed, writerOptions, output => + SplitStringDataHelper(sourceUtf8, writerOptions, output => { escapedIndex = output.WrittenSpan.IndexOf((byte)'\\'); Assert.Equal(requiresEscaping ? (i + 1) : -1, escapedIndex); // Account for the start quote - }); + }, StringValueEncodingType.Utf8); } } @@ -303,17 +303,17 @@ public void EscapingTestWhileWriting(char replacementChar, JavaScriptEncoder enc if (dataLength < 10) { - SplitCodePointsHelper(changed, writerOptions, output => + SplitStringDataHelper(changed, writerOptions, output => { escapedIndex = output.WrittenSpan.IndexOf((byte)'\\'); Assert.Equal(requiresEscaping ? 1 : -1, escapedIndex); // Account for the start quote - }); + }, StringValueEncodingType.Utf16); - SplitCodePointsHelper(sourceUtf8, writerOptions, output => + SplitStringDataHelper(sourceUtf8, writerOptions, output => { escapedIndex = output.WrittenSpan.IndexOf((byte)'\\'); Assert.Equal(requiresEscaping ? 1 : -1, escapedIndex); // Account for the start quote - }); + }, StringValueEncodingType.Utf8); } } } @@ -427,15 +427,15 @@ public unsafe void WriteString_NonAscii(char replacementChar, JavaScriptEncoder if (dataLength < 10) { - SplitCodePointsHelper(str, writerOptions, output => + SplitStringDataHelper(str, writerOptions, output => { Assert.Equal(-1, output.WrittenSpan.IndexOf((byte)'\\')); - }); + }, StringValueEncodingType.Utf16); - SplitCodePointsHelper(sourceUtf8, writerOptions, output => + SplitStringDataHelper(sourceUtf8, writerOptions, output => { Assert.Equal(-1, output.WrittenSpan.IndexOf((byte)'\\')); - }); + }, StringValueEncodingType.Utf8); } for (int i = 0; i < dataLength; i++) @@ -455,19 +455,19 @@ public unsafe void WriteString_NonAscii(char replacementChar, JavaScriptEncoder if (dataLength < 10) { - SplitCodePointsHelper(source.ToCharArray(), writerOptions, output => + SplitStringDataHelper(source.AsSpan(), writerOptions, output => { escapedIndex = output.WrittenSpan.IndexOf((byte)'\\'); // Each CJK character expands to 3 utf-8 bytes. Assert.Equal(requiresEscaping ? ((i * 3) + 1) : -1, escapedIndex); // Account for the start quote - }); + }, StringValueEncodingType.Utf16); - SplitCodePointsHelper(sourceUtf8, writerOptions, output => + SplitStringDataHelper(sourceUtf8, writerOptions, output => { escapedIndex = output.WrittenSpan.IndexOf((byte)'\\'); // Each CJK character expands to 3 utf-8 bytes. Assert.Equal(requiresEscaping ? ((i * 3) + 1) : -1, escapedIndex); // Account for the start quote - }); + }, StringValueEncodingType.Utf8); } } } @@ -538,15 +538,15 @@ public void EscapingTestWhileWritingSurrogate(JavaScriptEncoder encoder) if (dataLength < 10) { - SplitCodePointsHelper(str, writerOptions, output => + SplitStringDataHelper(str, writerOptions, output => { Assert.Equal(-1, output.WrittenSpan.IndexOf((byte)'\\')); - }); + }, StringValueEncodingType.Utf16); - SplitCodePointsHelper(sourceUtf8, writerOptions, output => + SplitStringDataHelper(sourceUtf8, writerOptions, output => { Assert.Equal(-1, output.WrittenSpan.IndexOf((byte)'\\')); - }); + }, StringValueEncodingType.Utf8); } for (int i = 0; i < dataLength - 1; i++) @@ -567,17 +567,17 @@ public void EscapingTestWhileWritingSurrogate(JavaScriptEncoder encoder) if (dataLength < 10) { - SplitCodePointsHelper(changed, writerOptions, output => + SplitStringDataHelper(changed, writerOptions, output => { escapedIndex = output.WrittenSpan.IndexOf((byte)'\\'); Assert.Equal(i + 1, escapedIndex); // Account for the start quote - }); + }, StringValueEncodingType.Utf16); - SplitCodePointsHelper(sourceUtf8, writerOptions, output => + SplitStringDataHelper(sourceUtf8, writerOptions, output => { escapedIndex = output.WrittenSpan.IndexOf((byte)'\\'); Assert.Equal(i + 1, escapedIndex); // Account for the start quote - }); + }, StringValueEncodingType.Utf8); } } @@ -603,17 +603,17 @@ public void EscapingTestWhileWritingSurrogate(JavaScriptEncoder encoder) if (dataLength < 10) { - SplitCodePointsHelper(changed, writerOptions, output => + SplitStringDataHelper(changed, writerOptions, output => { escapedIndex = output.WrittenSpan.IndexOf((byte)'\\'); Assert.Equal(1, escapedIndex); // Account for the start quote - }); + }, StringValueEncodingType.Utf16); - SplitCodePointsHelper(sourceUtf8, writerOptions, output => + SplitStringDataHelper(sourceUtf8, writerOptions, output => { escapedIndex = output.WrittenSpan.IndexOf((byte)'\\'); Assert.Equal(1, escapedIndex); // Account for the start quote - }); + }, StringValueEncodingType.Utf8); } } } @@ -667,15 +667,15 @@ public unsafe void WriteStringInvalidCharacter(char replacementChar, JavaScriptE if (dataLength < 10) { - SplitCodePointsHelper(changed, writerOptions, output => + SplitStringDataHelper(changed, writerOptions, output => { Assert.True(BeginsWithReplacementCharacter(output.WrittenSpan.Slice(i + 1))); // +1 to account for starting quote - }); + }, StringValueEncodingType.Utf16); - SplitCodePointsHelper(sourceUtf8, writerOptions, output => + SplitStringDataHelper(sourceUtf8, writerOptions, output => { Assert.True(BeginsWithReplacementCharacter(output.WrittenSpan.Slice(i + 1))); // +1 to account for starting quote - }); + }, StringValueEncodingType.Utf8); } } } @@ -1886,6 +1886,18 @@ public void InvalidJsonDueToWritingMultipleValues(JsonWriterOptions options, Jso ValidateAction(jsonUtf8, () => jsonUtf8.WriteStringValueSegment("foo"u8, false), options.SkipValidation); } + using (var jsonUtf8 = new Utf8JsonWriter(output, options)) + { + WritePreamble(jsonUtf8, kind); + ValidateAction(jsonUtf8, () => jsonUtf8.WriteBase64StringSegment("foo"u8, true), options.SkipValidation); + } + + using (var jsonUtf8 = new Utf8JsonWriter(output, options)) + { + WritePreamble(jsonUtf8, kind); + ValidateAction(jsonUtf8, () => jsonUtf8.WriteBase64StringSegment("foo"u8, false), options.SkipValidation); + } + using (var jsonUtf8 = new Utf8JsonWriter(output, options)) { WritePreamble(jsonUtf8, kind); @@ -2020,6 +2032,18 @@ public void InvalidJsonDueToWritingMultipleValuesWithComments(JsonWriterOptions ValidateAction(jsonUtf8, () => jsonUtf8.WriteStringValueSegment("foo"u8, false), options.SkipValidation); } + using (var jsonUtf8 = new Utf8JsonWriter(output, options)) + { + WritePreamble(jsonUtf8, kind, addComments: true); + ValidateAction(jsonUtf8, () => jsonUtf8.WriteBase64StringSegment("foo"u8, true), options.SkipValidation); + } + + using (var jsonUtf8 = new Utf8JsonWriter(output, options)) + { + WritePreamble(jsonUtf8, kind, addComments: true); + ValidateAction(jsonUtf8, () => jsonUtf8.WriteBase64StringSegment("foo"u8, false), options.SkipValidation); + } + using (var jsonUtf8 = new Utf8JsonWriter(output, options)) { WritePreamble(jsonUtf8, kind, addComments: true); @@ -2258,6 +2282,10 @@ public void InvalidJsonMismatch(JsonWriterOptions options) jsonUtf8.WriteStringValueSegment([65, 66], true); jsonUtf8.WriteStringValueSegment([65, 66], false); jsonUtf8.WriteStringValueSegment([65, 66], true); + + jsonUtf8.WriteBase64StringSegment([65, 66], true); + jsonUtf8.WriteBase64StringSegment([65, 66], false); + jsonUtf8.WriteBase64StringSegment([65, 66], true); } else { @@ -2265,6 +2293,8 @@ public void InvalidJsonMismatch(JsonWriterOptions options) Assert.Throws(() => jsonUtf8.WriteStringValueSegment(['a', 'b'], false)); Assert.Throws(() => jsonUtf8.WriteStringValueSegment([65, 66], true)); Assert.Throws(() => jsonUtf8.WriteStringValueSegment([65, 66], false)); + Assert.Throws(() => jsonUtf8.WriteBase64StringSegment([65, 66], true)); + Assert.Throws(() => jsonUtf8.WriteBase64StringSegment([65, 66], false)); } } @@ -2830,6 +2860,19 @@ public void InvalidJsonPrimitive(JsonWriterOptions options) Assert.Throws(() => jsonUtf8.WritePropertyName("test name")); } } + + using (var jsonUtf8 = new Utf8JsonWriter(output, options)) + { + jsonUtf8.WriteBase64StringSegment("a"u8, true); + if (options.SkipValidation) + { + jsonUtf8.WritePropertyName("test name"); + } + else + { + Assert.Throws(() => jsonUtf8.WritePropertyName("test name")); + } + } } // Name is present in the test data to make it easier to identify the test case @@ -2867,6 +2910,19 @@ public void InvalidJsonStringValueSegment(string _, Action write } } + using (var jsonUtf8 = new Utf8JsonWriter(output, options)) + { + jsonUtf8.WriteBase64StringSegment("foo"u8, isFinalSegment: false); + if (options.SkipValidation) + { + write(jsonUtf8); + } + else + { + Assert.Throws(() => write(jsonUtf8)); + } + } + using (var jsonUtf8 = new Utf8JsonWriter(output, options)) { jsonUtf8.WriteStringValueSegment("foo".ToCharArray(), isFinalSegment: false); @@ -3236,7 +3292,7 @@ public void WritingTooLargeBase64Bytes(JsonWriterOptions options) byte[] value = new byte[200_000_000]; value.AsSpan().Fill((byte)'a'); - var output = new ArrayBufferWriter(value.Length); + var output = new ArrayBufferWriter(value.Length); using (var jsonUtf8 = new Utf8JsonWriter(output, options)) { diff --git a/src/libraries/oob-src.proj b/src/libraries/oob-src.proj index 48bc4897a26790..4040662811bfc8 100644 --- a/src/libraries/oob-src.proj +++ b/src/libraries/oob-src.proj @@ -15,15 +15,15 @@ @(NetCoreAppLibrary->'%(Identity)\src\%(Identity).csproj'); Microsoft.VisualBasic.Core\src\Microsoft.VisualBasic.Core.vbproj" /> - + diff --git a/src/libraries/pretest.proj b/src/libraries/pretest.proj index b70c66a6c175f9..07f7e90f9beb08 100644 --- a/src/libraries/pretest.proj +++ b/src/libraries/pretest.proj @@ -23,13 +23,13 @@ - - + diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index fae36df0a3f5b1..76f22763eac181 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -339,6 +339,10 @@ + + + + diff --git a/src/mono/browser/browser.proj b/src/mono/browser/browser.proj index 40e600230619fe..5ab8d0407a7751 100644 --- a/src/mono/browser/browser.proj +++ b/src/mono/browser/browser.proj @@ -554,7 +554,7 @@ - diff --git a/src/mono/mono/cil/opcode.def b/src/mono/mono/cil/opcode.def index 47bccb295e99b2..049c0500b66bd1 100644 --- a/src/mono/mono/cil/opcode.def +++ b/src/mono/mono/cil/opcode.def @@ -328,6 +328,8 @@ OPDEF(CEE_MONO_GET_SP, "mono_get_sp", Pop0, PushI, InlineNone, 0, 2, 0xF0, 0x20, OPDEF(CEE_MONO_METHODCONST, "mono_methodconst", Pop0, PushI, InlineI, 0, 2, 0xF0, 0x21, NEXT) OPDEF(CEE_MONO_PINVOKE_ADDR_CACHE, "mono_pinvoke_addr_cache", Pop0, PushI, InlineI, 0, 2, 0xF0, 0x22, NEXT) OPDEF(CEE_MONO_REMAP_OVF_EXC, "mono_remap_ovf_exc", Pop0, Push0, InlineI, 0, 2, 0xF0, 0x23, NEXT) +OPDEF(CEE_MONO_LDVIRTFTN_DELEGATE, "mono_ldvirtftn_delegate", PopI+PopI, PushI, InlineNone, 0, 2, 0xF0, 0x24, NEXT) + #ifndef OPALIAS #define _MONO_CIL_OPALIAS_DEFINED_ #define OPALIAS(a,s,r) diff --git a/src/mono/mono/metadata/icall.c b/src/mono/mono/metadata/icall.c index e73780a6678fff..139a2d02dd2012 100644 --- a/src/mono/mono/metadata/icall.c +++ b/src/mono/mono/metadata/icall.c @@ -1705,7 +1705,7 @@ ves_icall_System_RuntimeTypeHandle_internal_from_name (char *name, if (!(*res)) { if (throwOnError) { - char *tname = info.name_space ? g_strdup_printf ("%s.%s", info.name_space, info.name) : g_strdup (info.name); + char *tname = (info.name_space && *info.name_space) ? g_strdup_printf ("%s.%s", info.name_space, info.name) : g_strdup (info.name); char *aname; if (info.assembly.name) aname = mono_stringify_assembly_name (&info.assembly); diff --git a/src/mono/mono/metadata/marshal-lightweight.c b/src/mono/mono/metadata/marshal-lightweight.c index d79919ec3623d5..2095334a818afe 100644 --- a/src/mono/mono/metadata/marshal-lightweight.c +++ b/src/mono/mono/metadata/marshal-lightweight.c @@ -2052,7 +2052,8 @@ emit_delegate_invoke_internal_ilgen (MonoMethodBuilder *mb, MonoMethodSignature } mono_mb_emit_ldarg_addr (mb, 1); mono_mb_emit_ldarg (mb, 0); - mono_mb_emit_icall (mb, mono_get_addr_compiled_method); + mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); + mono_mb_emit_byte (mb, CEE_MONO_LDVIRTFTN_DELEGATE); mono_mb_emit_op (mb, CEE_CALLI, target_method_sig); } else { mono_mb_emit_byte (mb, CEE_LDNULL); diff --git a/src/mono/mono/metadata/sgen-bridge-internals.h b/src/mono/mono/metadata/sgen-bridge-internals.h index a53c5f7f66fb53..fb0bbe875d690e 100644 --- a/src/mono/mono/metadata/sgen-bridge-internals.h +++ b/src/mono/mono/metadata/sgen-bridge-internals.h @@ -52,7 +52,6 @@ typedef struct { void (*processing_stw_step) (void); void (*processing_build_callback_data) (int generation); void (*processing_after_callback) (int generation); - MonoGCBridgeObjectKind (*class_kind) (MonoClass *klass); void (*register_finalized_object) (GCObject *object); void (*describe_pointer) (GCObject *object); diff --git a/src/mono/mono/metadata/sgen-bridge.c b/src/mono/mono/metadata/sgen-bridge.c index 579fc0d376cd6a..c942403efb523a 100644 --- a/src/mono/mono/metadata/sgen-bridge.c +++ b/src/mono/mono/metadata/sgen-bridge.c @@ -486,10 +486,36 @@ sgen_bridge_processing_finish (int generation) mono_bridge_processing_in_progress = FALSE; } +// Is this class bridged or not, and should its dependencies be scanned or not? +// The result of this callback will be cached for use by is_opaque_object later. MonoGCBridgeObjectKind sgen_bridge_class_kind (MonoClass *klass) { - return bridge_processor.class_kind (klass); + MonoGCBridgeObjectKind res = mono_bridge_callbacks.bridge_class_kind (klass); + + /* If it's a bridge, nothing we can do about it. */ + if (res == GC_BRIDGE_TRANSPARENT_BRIDGE_CLASS || res == GC_BRIDGE_OPAQUE_BRIDGE_CLASS) + return res; + + /* Non bridge classes with no pointers will never point to a bridge, so we can savely ignore them. */ + if (!m_class_has_references (klass)) { + SGEN_LOG (6, "class %s is opaque\n", m_class_get_name (klass)); + return GC_BRIDGE_OPAQUE_CLASS; + } + + /* Some arrays can be ignored */ + if (m_class_get_rank (klass) == 1) { + MonoClass *elem_class = m_class_get_element_class (klass); + + /* FIXME the bridge check can be quite expensive, cache it at the class level. */ + /* An array of a sealed type that is not a bridge will never get to a bridge */ + if ((mono_class_get_flags (elem_class) & TYPE_ATTRIBUTE_SEALED) && !m_class_has_references (elem_class) && !mono_bridge_callbacks.bridge_class_kind (elem_class)) { + SGEN_LOG (6, "class %s is opaque\n", m_class_get_name (klass)); + return GC_BRIDGE_OPAQUE_CLASS; + } + } + + return GC_BRIDGE_TRANSPARENT_CLASS; } void diff --git a/src/mono/mono/metadata/sgen-new-bridge.c b/src/mono/mono/metadata/sgen-new-bridge.c index cddaee8bff7594..ac6632b8cf470d 100644 --- a/src/mono/mono/metadata/sgen-new-bridge.c +++ b/src/mono/mono/metadata/sgen-new-bridge.c @@ -176,36 +176,6 @@ set_config (const SgenBridgeProcessorConfig *config) } } -static MonoGCBridgeObjectKind -class_kind (MonoClass *klass) -{ - MonoGCBridgeObjectKind res = mono_bridge_callbacks.bridge_class_kind (klass); - - /* If it's a bridge, nothing we can do about it. */ - if (res == GC_BRIDGE_TRANSPARENT_BRIDGE_CLASS || res == GC_BRIDGE_OPAQUE_BRIDGE_CLASS) - return res; - - /* Non bridge classes with no pointers will never point to a bridge, so we can savely ignore them. */ - if (!m_class_has_references (klass)) { - SGEN_LOG (6, "class %s is opaque\n", m_class_get_name (klass)); - return GC_BRIDGE_OPAQUE_CLASS; - } - - /* Some arrays can be ignored */ - if (m_class_get_rank (klass) == 1) { - MonoClass *elem_class = m_class_get_element_class (klass); - - /* FIXME the bridge check can be quite expensive, cache it at the class level. */ - /* An array of a sealed type that is not a bridge will never get to a bridge */ - if ((mono_class_get_flags (elem_class) & TYPE_ATTRIBUTE_SEALED) && !m_class_has_references (elem_class) && !mono_bridge_callbacks.bridge_class_kind (elem_class)) { - SGEN_LOG (6, "class %s is opaque\n", m_class_get_name (klass)); - return GC_BRIDGE_OPAQUE_CLASS; - } - } - - return GC_BRIDGE_TRANSPARENT_CLASS; -} - static HashEntry* get_hash_entry (MonoObject *obj, gboolean *existing) { @@ -1081,7 +1051,6 @@ sgen_new_bridge_init (SgenBridgeProcessor *collector) collector->processing_stw_step = processing_stw_step; collector->processing_build_callback_data = processing_build_callback_data; collector->processing_after_callback = processing_after_callback; - collector->class_kind = class_kind; collector->register_finalized_object = register_finalized_object; collector->describe_pointer = describe_pointer; collector->set_config = set_config; diff --git a/src/mono/mono/metadata/sgen-tarjan-bridge.c b/src/mono/mono/metadata/sgen-tarjan-bridge.c index b0c9cf1f83baef..3a869d3e4423d9 100644 --- a/src/mono/mono/metadata/sgen-tarjan-bridge.c +++ b/src/mono/mono/metadata/sgen-tarjan-bridge.c @@ -40,38 +40,6 @@ * which colors. The color graph then becomes the reduced SCC graph. */ -// Is this class bridged or not, and should its dependencies be scanned or not? -// The result of this callback will be cached for use by is_opaque_object later. -static MonoGCBridgeObjectKind -class_kind (MonoClass *klass) -{ - MonoGCBridgeObjectKind res = mono_bridge_callbacks.bridge_class_kind (klass); - - /* If it's a bridge, nothing we can do about it. */ - if (res == GC_BRIDGE_TRANSPARENT_BRIDGE_CLASS || res == GC_BRIDGE_OPAQUE_BRIDGE_CLASS) - return res; - - /* Non bridge classes with no pointers will never point to a bridge, so we can savely ignore them. */ - if (!m_class_has_references (klass)) { - SGEN_LOG (6, "class %s is opaque\n", m_class_get_name (klass)); - return GC_BRIDGE_OPAQUE_CLASS; - } - - /* Some arrays can be ignored */ - if (m_class_get_rank (klass) == 1) { - MonoClass *elem_class = m_class_get_element_class (klass); - - /* FIXME the bridge check can be quite expensive, cache it at the class level. */ - /* An array of a sealed type that is not a bridge will never get to a bridge */ - if ((mono_class_get_flags (elem_class) & TYPE_ATTRIBUTE_SEALED) && !m_class_has_references (elem_class) && !mono_bridge_callbacks.bridge_class_kind (elem_class)) { - SGEN_LOG (6, "class %s is opaque\n", m_class_get_name (klass)); - return GC_BRIDGE_OPAQUE_CLASS; - } - } - - return GC_BRIDGE_TRANSPARENT_CLASS; -} - //enable usage logging // #define DUMP_GRAPH 1 @@ -1260,7 +1228,6 @@ sgen_tarjan_bridge_init (SgenBridgeProcessor *collector) collector->processing_stw_step = processing_stw_step; collector->processing_build_callback_data = processing_build_callback_data; collector->processing_after_callback = processing_after_callback; - collector->class_kind = class_kind; collector->register_finalized_object = register_finalized_object; collector->describe_pointer = describe_pointer; collector->set_config = set_config; diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index df0abac566ed6e..a83fd3ac4e3380 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -3863,6 +3863,34 @@ max_d (double lhs, double rhs) return fmax (lhs, rhs); } +// Equivalent of mono_get_addr_compiled_method +static gpointer +interp_ldvirtftn_delegate (gpointer arg, MonoDelegate *del) +{ + MonoMethod *virtual_method = del->method; + ERROR_DECL(error); + + MonoClass *klass = del->object.vtable->klass; + MonoMethod *invoke = mono_get_delegate_invoke_internal (klass); + MonoMethodSignature *invoke_sig = mono_method_signature_internal (invoke); + + MonoClass *arg_class = NULL; + if (m_type_is_byref (invoke_sig->params [0])) { + arg_class = mono_class_from_mono_type_internal (invoke_sig->params [0]); + } else { + MonoObject *object = (MonoObject*)arg; + arg_class = object->vtable->klass; + } + + MonoMethod *res = mono_class_get_virtual_method (arg_class, virtual_method, error); + mono_error_assert_ok (error); + + gboolean need_unbox = m_class_is_valuetype (res->klass) && !m_class_is_valuetype (virtual_method->klass); + + InterpMethod *imethod = mono_interp_get_imethod (res); + return imethod_to_ftnptr (imethod, need_unbox); +} + /* * If CLAUSE_ARGS is non-null, start executing from it. * The ERROR argument is used to avoid declaring an error object for every interp frame, its not used @@ -7794,6 +7822,15 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; ip += 3; MINT_IN_BREAK; } + MINT_IN_CASE(MINT_LDVIRTFTN_DELEGATE) { + gpointer arg = LOCAL_VAR (ip [2], gpointer); + MonoDelegate *del = LOCAL_VAR (ip [3], MonoDelegate*); + NULL_CHECK (arg); + + LOCAL_VAR (ip [1], gpointer) = interp_ldvirtftn_delegate (arg, del); + ip += 4; + MINT_IN_BREAK; + } #define MATH_UNOP(mathfunc) \ LOCAL_VAR (ip [1], double) = mathfunc (LOCAL_VAR (ip [2], double)); \ diff --git a/src/mono/mono/mini/interp/mintops.def b/src/mono/mono/mini/interp/mintops.def index 5e2c41d60c47f1..43424be305ede3 100644 --- a/src/mono/mono/mini/interp/mintops.def +++ b/src/mono/mono/mini/interp/mintops.def @@ -732,6 +732,7 @@ OPDEF(MINT_SDB_INTR_LOC, "sdb_intr_loc", 1, 0, 0, MintOpNoArgs) OPDEF(MINT_SDB_SEQ_POINT, "sdb_seq_point", 1, 0, 0, MintOpNoArgs) OPDEF(MINT_SDB_BREAKPOINT, "sdb_breakpoint", 1, 0, 0, MintOpNoArgs) OPDEF(MINT_LD_DELEGATE_METHOD_PTR, "ld_delegate_method_ptr", 3, 1, 1, MintOpNoArgs) +OPDEF(MINT_LDVIRTFTN_DELEGATE, "ldvirtftn_delegate", 4, 1, 2, MintOpNoArgs) // Math intrinsics // double diff --git a/src/mono/mono/mini/interp/transform-simd.c b/src/mono/mono/mini/interp/transform-simd.c index c1d6b81019d02f..a9c0a697e4ee9d 100644 --- a/src/mono/mono/mini/interp/transform-simd.c +++ b/src/mono/mono/mini/interp/transform-simd.c @@ -567,12 +567,13 @@ emit_sri_vector128 (TransformData *td, MonoMethod *cmethod, MonoMethodSignature if (atype == MONO_TYPE_U1) simd_intrins = INTERP_SIMD_INTRINSIC_V128_U1_NARROW; break; case SN_ShiftLeft: - g_assert (scalar_arg == 1); - simd_opcode = MINT_SIMD_INTRINS_P_PP; - if (arg_size == 1) simd_intrins = INTERP_SIMD_INTRINSIC_V128_I1_LEFT_SHIFT; - else if (arg_size == 2) simd_intrins = INTERP_SIMD_INTRINSIC_V128_I2_LEFT_SHIFT; - else if (arg_size == 4) simd_intrins = INTERP_SIMD_INTRINSIC_V128_I4_LEFT_SHIFT; - else if (arg_size == 8) simd_intrins = INTERP_SIMD_INTRINSIC_V128_I8_LEFT_SHIFT; + if (scalar_arg == 1) { + simd_opcode = MINT_SIMD_INTRINS_P_PP; + if (arg_size == 1) simd_intrins = INTERP_SIMD_INTRINSIC_V128_I1_LEFT_SHIFT; + else if (arg_size == 2) simd_intrins = INTERP_SIMD_INTRINSIC_V128_I2_LEFT_SHIFT; + else if (arg_size == 4) simd_intrins = INTERP_SIMD_INTRINSIC_V128_I4_LEFT_SHIFT; + else if (arg_size == 8) simd_intrins = INTERP_SIMD_INTRINSIC_V128_I8_LEFT_SHIFT; + } break; case SN_ShiftRightLogical: g_assert (scalar_arg == 1); diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index cf17b88970345d..53ca6d2a10804a 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -8056,6 +8056,16 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, push_simple_type (td, STACK_TYPE_I); interp_ins_set_dreg (td->last_ins, td->sp [-1].var); break; + case CEE_MONO_LDVIRTFTN_DELEGATE: + CHECK_STACK (td, 2); + td->sp -= 2; + td->ip += 1; + interp_add_ins (td, MINT_LDVIRTFTN_DELEGATE); + interp_ins_set_sregs2 (td->last_ins, td->sp [0].var, td->sp [1].var); + push_simple_type (td, STACK_TYPE_I); + interp_ins_set_dreg (td->last_ins, td->sp [-1].var); + break; + case CEE_MONO_CALLI_EXTRA_ARG: { int saved_local = td->sp [-1].var; /* Same as CEE_CALLI, except that we drop the extra arg required for llvm specific behaviour */ diff --git a/src/mono/mono/mini/method-to-ir.c b/src/mono/mono/mini/method-to-ir.c index 879d98dfc673e8..5fc3320278f3de 100644 --- a/src/mono/mono/mini/method-to-ir.c +++ b/src/mono/mono/mini/method-to-ir.c @@ -11594,6 +11594,14 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b *sp++ = ins; break; } + case MONO_CEE_MONO_LDVIRTFTN_DELEGATE: { + CHECK_STACK (2); + sp -= 2; + + ins = mono_emit_jit_icall (cfg, mono_get_addr_compiled_method, sp); + *sp++ = ins; + break; + } case MONO_CEE_MONO_CALLI_EXTRA_ARG: { MonoInst *addr; MonoInst *arg; diff --git a/src/mono/mono/mini/simd-intrinsics.c b/src/mono/mono/mini/simd-intrinsics.c index 7a706fa49d0929..04123b3fe531c8 100644 --- a/src/mono/mono/mini/simd-intrinsics.c +++ b/src/mono/mono/mini/simd-intrinsics.c @@ -1638,10 +1638,18 @@ static guint16 sri_vector_methods [] = { SN_GreaterThanOrEqual, SN_GreaterThanOrEqualAll, SN_GreaterThanOrEqualAny, + SN_IsEvenInteger, + SN_IsFinite, + SN_IsInfinity, + SN_IsInteger, SN_IsNaN, SN_IsNegative, + SN_IsNegativeInfinity, + SN_IsNormal, + SN_IsOddInteger, SN_IsPositive, SN_IsPositiveInfinity, + SN_IsSubnormal, SN_IsZero, SN_LessThan, SN_LessThanAll, @@ -2395,13 +2403,28 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi case SN_ExtractMostSignificantBits: { if (!is_element_type_primitive (fsig->params [0])) return NULL; + + MonoClass *arg_class = mono_class_from_mono_type_internal (fsig->params [0]); + + if (fsig->params [0]->type != MONO_TYPE_GENERICINST) { + // This exists to handle the static extension methods for Vector2/3/4, Quaternion, and Plane + // which live on System.Numerics.Vector + + arg0_type = MONO_TYPE_R4; + } + + int size = mono_class_value_size (arg_class, NULL); + + if (size != 16) { + // FIXME: Add support for Vector2/3 + return NULL; + } #ifdef TARGET_WASM if (type_enum_is_float (arg0_type)) return NULL; return emit_simd_ins_for_sig (cfg, klass, OP_WASM_SIMD_BITMASK, -1, -1, fsig, args); #elif defined(TARGET_ARM64) - MonoClass* arg_class; if (type_enum_is_float (arg0_type)) { MonoClass* cast_class; if (arg0_type == MONO_TYPE_R4) { @@ -2411,15 +2434,23 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi arg0_type = MONO_TYPE_I8; cast_class = mono_defaults.int64_class; } - arg_class = create_class_instance ("System.Runtime.Intrinsics", m_class_get_name (klass), m_class_get_byval_arg (cast_class)); + + const char *klass_name = m_class_get_name (klass); + + if (!strcmp (klass_name, "Vector4")) { + klass_name = "Vector128`1"; + } + arg_class = create_class_instance ("System.Runtime.Intrinsics", klass_name, m_class_get_byval_arg (cast_class)); } else { arg_class = mono_class_from_mono_type_internal (fsig->params [0]); } - // FIXME: Add support for Vector64 on arm64 https://github.com/dotnet/runtime/issues/90402 - int size = mono_class_value_size (arg_class, NULL); - if (size != 16) + size = mono_class_value_size (arg_class, NULL); + + if (size != 16) { + // FIXME: Add support for Vector64 on arm64 https://github.com/dotnet/runtime/issues/90402 return NULL; + } MonoInst* msb_mask_vec = emit_msb_vector_mask (cfg, arg_class, arg0_type); MonoInst* and_res_vec = emit_simd_ins_for_binary_op (cfg, arg_class, fsig, args, arg0_type, SN_BitwiseAnd); @@ -2459,7 +2490,7 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi return NULL; type = type_enum_is_unsigned (arg0_type) ? MONO_TYPE_U1 : MONO_TYPE_I1; - MonoClass* arg_class = mono_class_from_mono_type_internal (fsig->params [0]); + arg_class = mono_class_from_mono_type_internal (fsig->params [0]); guint64 shuffle_mask[2]; shuffle_mask[0] = 0x0F0D0B0907050301; // Place odd bytes in the lower half of vector @@ -2504,18 +2535,25 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi return NULL; MonoClass *arg_class = mono_class_from_mono_type_internal (fsig->params [0]); + int esize; if (fsig->params [0]->type == MONO_TYPE_GENERICINST) { MonoType *etype = mono_class_get_context (arg_class)->class_inst->type_argv [0]; - int size = mono_class_value_size (arg_class, NULL); - int esize = mono_class_value_size (mono_class_from_mono_type_internal (etype), NULL); - elems = size / esize; + esize = mono_class_value_size (mono_class_from_mono_type_internal (etype), NULL); } else { // This exists to handle the static extension methods for Vector2/3/4, Quaternion, and Plane // which live on System.Numerics.Vector arg0_type = MONO_TYPE_R4; - elems = 4; + esize = 4; + } + + int size = mono_class_value_size (arg_class, NULL); + elems = size / esize; + + if (size != 16) { + // FIXME: Add support for Vector2/3 + return NULL; } if (args [1]->opcode == OP_ICONST) { @@ -2642,6 +2680,61 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi return ret; } } + case SN_IsEvenInteger: + case SN_IsOddInteger: { + if (!is_element_type_primitive (fsig->params [0])) + return NULL; + if (type_enum_is_float(arg0_type)) + return NULL; + + // TODO: This requires a centralized way for get_One() + // + // IsEvenInteger: + // x = And(x, get_One()) + // return IntEqCmp(x, zero) + // + // IsOddInteger + // x = And(x, get_One()) + // return IntNeCmp(x, zero) + + return NULL; + } + case SN_IsFinite: { + if (!is_element_type_primitive (fsig->params [0])) + return NULL; + if (!type_enum_is_float(arg0_type)) + return emit_xones (cfg, klass); + + // TODO: This requires a centralized way for AndNot(x, y) + // + // x = AndNot(PositiveInfinityBits, x) + // return IntNeCmp(x, zero) + + return NULL; + } + case SN_IsInfinity: { + // TODO: This requires a centralized way for Abs(x) and IsPositiveInfinity(x) + // + // x = Abs(x) + // return IsPositiveInfinity(x) + + return NULL; + } + case SN_IsInteger: { + if (!is_element_type_primitive (fsig->params [0])) + return NULL; + if (!type_enum_is_float(arg0_type)) + return emit_xones (cfg, klass); + + // TODO: This requires a centralized way for IsFinite(x) and Trunc(c) + // + // tmp1 = IsFinite(x) + // tmp2 = Trunc(x) + // tmp2 = FltEqCmp(x, tmp2) + // return And(tmp1, tmp2) + + return NULL; + } case SN_IsNaN: { if (!is_element_type_primitive (fsig->params [0])) return NULL; @@ -2695,30 +2788,79 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi } return ins; } + case SN_IsNegativeInfinity: case SN_IsPositiveInfinity: { if (!is_element_type_primitive (fsig->params [0])) return NULL; if (arg0_type == MONO_TYPE_R4) { guint32 value[4]; - value [0] = 0x7F800000; - value [1] = 0x7F800000; - value [2] = 0x7F800000; - value [3] = 0x7F800000; + if (id == SN_IsNegativeInfinity) + { + value [0] = 0xFF800000; + value [1] = 0xFF800000; + value [2] = 0xFF800000; + value [3] = 0xFF800000; + } + else + { + value [0] = 0x7F800000; + value [1] = 0x7F800000; + value [2] = 0x7F800000; + value [3] = 0x7F800000; + } MonoInst *arg1 = emit_xconst_v128 (cfg, klass, (guint8*)value); return emit_xcompare (cfg, klass, arg0_type, args [0], arg1); } else if (arg0_type == MONO_TYPE_R8) { guint64 value[2]; - value [0] = 0x7FF0000000000000; - value [1] = 0x7FF0000000000000; + if (id == SN_IsNegativeInfinity) + { + value [0] = 0xFFF0000000000000; + value [1] = 0xFFF0000000000000; + } + else + { + value [0] = 0x7FF0000000000000; + value [1] = 0x7FF0000000000000; + } MonoInst *arg1 = emit_xconst_v128 (cfg, klass, (guint8*)value); return emit_xcompare (cfg, klass, arg0_type, args [0], arg1); } return emit_xzero (cfg, klass); } + case SN_IsNormal: { + if (!is_element_type_primitive (fsig->params [0])) + return NULL; + if (!type_enum_is_float(arg0_type)) + return emit_not_xequal (cfg, klass, arg0_type, args [0], emit_xzero (cfg, klass)); + + // TODO: This requires a centralized way for Abs(x) + // and retyping from float to the same sized unsigned integer + // + // x = FltAbs(x) + // x = UIntSub(x, SmallestNormalBits) + // return UIntLtCmp(x, PositiveInfinityBits - SmallestNormalBits) + + return NULL; + } + case SN_IsSubnormal: { + if (!is_element_type_primitive (fsig->params [0])) + return NULL; + if (!type_enum_is_float(arg0_type)) + return emit_xzero (cfg, klass); + + // TODO: This requires a centralized way for Abs(x) + // and retyping from float to the same sized unsigned integer + // + // x = FltAbs(x) + // x = UIntSub(x, 1) + // return UIntLtCmp(x, MaxTrailingSignificand) + + return NULL; + } case SN_IsZero: { if (!is_element_type_primitive (fsig->params [0])) return NULL; @@ -3026,6 +3168,23 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi case SN_ToScalar: { if (!is_element_type_primitive (fsig->params [0])) return NULL; + + MonoClass *arg_class = mono_class_from_mono_type_internal (fsig->params [0]); + + if (fsig->params [0]->type != MONO_TYPE_GENERICINST) { + // This exists to handle the static extension methods for Vector2/3/4, Quaternion, and Plane + // which live on System.Numerics.Vector + + arg0_type = MONO_TYPE_R4; + } + + int size = mono_class_value_size (arg_class, NULL); + + if (size != 16) { + // FIXME: Add support for Vector2/3 + return NULL; + } + int extract_op = type_to_extract_op (arg0_type); return emit_simd_ins_for_sig (cfg, klass, extract_op, 0, arg0_type, fsig, args); } @@ -3043,18 +3202,25 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi return NULL; MonoClass *arg_class = mono_class_from_mono_type_internal (fsig->params [0]); + int esize; if (fsig->params [0]->type == MONO_TYPE_GENERICINST) { MonoType *etype = mono_class_get_context (arg_class)->class_inst->type_argv [0]; - int size = mono_class_value_size (arg_class, NULL); - int esize = mono_class_value_size (mono_class_from_mono_type_internal (etype), NULL); - elems = size / esize; + esize = mono_class_value_size (mono_class_from_mono_type_internal (etype), NULL); } else { // This exists to handle the static extension methods for Vector2/3/4, Quaternion, and Plane // which live on System.Numerics.Vector arg0_type = MONO_TYPE_R4; - elems = 4; + esize = 4; + } + + int size = mono_class_value_size (arg_class, NULL); + elems = size / esize; + + if (size != 16) { + // FIXME: Add support for Vector2/3 + return NULL; } if (args [1]->opcode == OP_ICONST) { @@ -6525,6 +6691,7 @@ emit_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi MonoInst* mono_emit_simd_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) { + // TODO: We shouldn't be processing any methods which aren't marked [Intrinsic] return emit_intrinsics (cfg, cmethod, fsig, args, emit_simd_intrinsics); } diff --git a/src/mono/mono/mini/simd-methods.h b/src/mono/mono/mini/simd-methods.h index fd7f56e4c72009..b696931ce51e92 100644 --- a/src/mono/mono/mini/simd-methods.h +++ b/src/mono/mono/mini/simd-methods.h @@ -12,10 +12,18 @@ METHOD(GreaterThanAny) METHOD(GreaterThanOrEqual) METHOD(GreaterThanOrEqualAll) METHOD(GreaterThanOrEqualAny) +METHOD(IsEvenInteger) +METHOD(IsFinite) +METHOD(IsInfinity) +METHOD(IsInteger) METHOD(IsNaN) METHOD(IsNegative) +METHOD(IsNegativeInfinity) +METHOD(IsNormal) +METHOD(IsOddInteger) METHOD(IsPositive) METHOD(IsPositiveInfinity) +METHOD(IsSubnormal) METHOD(IsZero) METHOD(LessThan) METHOD(LessThanAll) diff --git a/src/mono/msbuild/apple/data/ProxyProjectForAOTOnHelix.proj b/src/mono/msbuild/apple/data/ProxyProjectForAOTOnHelix.proj index 2847f567f469a1..2035333122a2f0 100644 --- a/src/mono/msbuild/apple/data/ProxyProjectForAOTOnHelix.proj +++ b/src/mono/msbuild/apple/data/ProxyProjectForAOTOnHelix.proj @@ -7,7 +7,6 @@ $([MSBuild]::NormalizeDirectory($(TestRootDir), '..', 'extraFiles')) $([MSBuild]::NormalizeDirectory($(TestRootDir), '..', 'obj')) - ConfigureTrimming;_AdjustTrimmedAssembliesToBundle;$(AppleBuildDependsOn) _PublishRuntimePack;_PrepareForAppleBuildAppOnHelix;$(AppleBuildDependsOn);_AfterAppleBuildOnHelix true @@ -71,7 +70,7 @@ - + <_ExtraFiles Include="$(ExtraFilesPath)**\*" /> @@ -95,14 +94,6 @@ - - - - - - - - - - - - - - - - diff --git a/src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Sdk/Sdk/Sdk.props b/src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Sdk/Sdk/Sdk.props index dae0b088f16071..53dfe5e48eac09 100644 --- a/src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Sdk/Sdk/Sdk.props +++ b/src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Sdk/Sdk/Sdk.props @@ -3,7 +3,7 @@ wasm browser true - Exe + Exe true diff --git a/src/mono/wasi/Wasi.Build.Tests/WasiLibraryModeTests.cs b/src/mono/wasi/Wasi.Build.Tests/WasiLibraryModeTests.cs index 2c191e745dac2f..da350ccadf6f77 100644 --- a/src/mono/wasi/Wasi.Build.Tests/WasiLibraryModeTests.cs +++ b/src/mono/wasi/Wasi.Build.Tests/WasiLibraryModeTests.cs @@ -19,29 +19,17 @@ public WasiLibraryModeTests(ITestOutputHelper output, SharedBuildPerTestClassFix { } - [Fact] - public void ConsoleBuildLibraryMode() + [Theory] + [InlineData("Microsoft.NET.Sdk", false)] + [InlineData("Microsoft.NET.Sdk.WebAssembly", true)] + public void LibraryModeBuild(string sdk, bool hasWasmAppBundle) { string config = "Release"; string id = $"{config}_{GetRandomId()}"; string projectFile = CreateWasmTemplateProject(id, "wasiconsole"); - string code = - """ - using System; - using System.Runtime.InteropServices; - public unsafe class Test - { - [UnmanagedCallersOnly(EntryPoint = "MyCallback")] - public static int MyCallback() - { - Console.WriteLine("WASM Library MyCallback is called"); - return 100; - } - } - """; - string csprojCode = - """ - + string csprojCode = + $""" + net9.0 wasi-wasm @@ -51,6 +39,7 @@ public static int MyCallback() """; + string code = File.ReadAllText(Path.Combine(BuildEnvironment.TestAssetsPath, "LibraryMode.cs")); File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), code); File.WriteAllText(Path.Combine(_projectDir!, $"{id}.csproj"), csprojCode); string projectName = Path.GetFileNameWithoutExtension(projectFile); @@ -62,9 +51,8 @@ public static int MyCallback() DotnetWasmFromRuntimePack: false, CreateProject: false, Publish: false, + AssertAppBundle: hasWasmAppBundle, TargetFramework: BuildTestBase.DefaultTargetFramework )); - - Assert.Contains("Build succeeded.", output); } } diff --git a/src/mono/wasi/testassets/LibraryMode.cs b/src/mono/wasi/testassets/LibraryMode.cs new file mode 100644 index 00000000000000..22d22660c515b7 --- /dev/null +++ b/src/mono/wasi/testassets/LibraryMode.cs @@ -0,0 +1,11 @@ +using System; +using System.Runtime.InteropServices; +public unsafe class Test +{ + [UnmanagedCallersOnly(EntryPoint = "MyCallback")] + public static int MyCallback() + { + Console.WriteLine("TestOutput -> WASM Library MyCallback is called"); + return 100; + } +} diff --git a/src/mono/wasm/Wasm.Build.Tests/BrowserStructures/TestAsset.cs b/src/mono/wasm/Wasm.Build.Tests/BrowserStructures/TestAsset.cs index 4062b307cbc628..a3febcea7381db 100644 --- a/src/mono/wasm/Wasm.Build.Tests/BrowserStructures/TestAsset.cs +++ b/src/mono/wasm/Wasm.Build.Tests/BrowserStructures/TestAsset.cs @@ -4,4 +4,5 @@ public class TestAsset public string RunnableProjectSubPath { get; init; } public static readonly TestAsset WasmBasicTestApp = new() { Name = "WasmBasicTestApp", RunnableProjectSubPath = "App" }; public static readonly TestAsset BlazorBasicTestApp = new() { Name = "BlazorBasicTestApp", RunnableProjectSubPath = "App" }; + public static readonly TestAsset LibraryModeTestApp = new() { Name = "LibraryMode" }; } \ No newline at end of file diff --git a/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTests.cs b/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTests.cs index 873fda2f3e47fb..eb56d5393aed52 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTests.cs @@ -284,5 +284,27 @@ void AssertFile(string suffix) Assert.True(copyOutputSymbolsToPublishDirectory == (fileName != null && File.Exists(fileName)), $"The {fileName} file {(copyOutputSymbolsToPublishDirectory ? "should" : "shouldn't")} exist in publish folder"); } } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public async void LibraryModeBuild(bool useWasmSdk) + { + var config = Configuration.Release; + ProjectInfo info = CopyTestAsset(config, aot: false, TestAsset.LibraryModeTestApp, "libraryMode"); + if (!useWasmSdk) + { + UpdateFile($"{info.ProjectName}.csproj", new Dictionary() { + { "Microsoft.NET.Sdk.WebAssembly", "Microsoft.NET.Sdk" } + }); + } + BuildProject(info, config, new BuildOptions(AssertAppBundle: useWasmSdk)); + if (useWasmSdk) + { + var result = await RunForBuildWithDotnetRun(new BrowserRunOptions(config, ExpectedExitCode: 100)); + Assert.Contains("WASM Library MyExport is called", result.TestOutput); + } + + } } } diff --git a/src/mono/wasm/host/DevServer/DevServerStartup.cs b/src/mono/wasm/host/DevServer/DevServerStartup.cs index 87dfc0eb70f474..5df2eabcaa8606 100644 --- a/src/mono/wasm/host/DevServer/DevServerStartup.cs +++ b/src/mono/wasm/host/DevServer/DevServerStartup.cs @@ -12,6 +12,7 @@ using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using Microsoft.Net.Http.Headers; using Microsoft.WebAssembly.AppHost; namespace Microsoft.WebAssembly.AppHost.DevServer; @@ -67,7 +68,6 @@ public static void Configure(IApplicationBuilder app, IOptions ServeUnknownFileTypes = true, }); - app.UseRouting(); app.UseWebSockets(); if (options.OnConsoleConnected is not null) @@ -100,6 +100,14 @@ public static void Configure(IApplicationBuilder app, IOptions { OnPrepareResponse = fileContext => { + // Avoid caching index.html during development. + // When hot reload is enabled, a middleware injects a hot reload script into the response HTML. + // We don't want the browser to bypass this injection by using a cached response that doesn't + // contain the injected script. In the future, if script injection is removed in favor of a + // different mechanism, we can delete this comment and the line below it. + // See also: https://github.com/dotnet/aspnetcore/issues/45213 + fileContext.Context.Response.Headers[HeaderNames.CacheControl] = "no-store"; + if (options.WebServerUseCrossOriginPolicy) { // Browser multi-threaded runtime requires cross-origin policy headers to enable SharedArrayBuffer. diff --git a/src/mono/wasm/testassets/LibraryMode/LibraryMode.cs b/src/mono/wasm/testassets/LibraryMode/LibraryMode.cs new file mode 100644 index 00000000000000..8b008105802165 --- /dev/null +++ b/src/mono/wasm/testassets/LibraryMode/LibraryMode.cs @@ -0,0 +1,17 @@ +// 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; + +namespace LibraryMode; + +public partial class Test +{ + [JSExport] + public static int MyExport() + { + Console.WriteLine("TestOutput -> WASM Library MyExport is called"); + return 100; + } +} diff --git a/src/mono/wasm/testassets/LibraryMode/LibraryMode.csproj b/src/mono/wasm/testassets/LibraryMode/LibraryMode.csproj new file mode 100644 index 00000000000000..6f0edcd2c21e99 --- /dev/null +++ b/src/mono/wasm/testassets/LibraryMode/LibraryMode.csproj @@ -0,0 +1,9 @@ + + + browser-wasm + net10.0 + true + Library + + + diff --git a/src/coreclr/vm/loongarch64/unixstubs.cpp b/src/mono/wasm/testassets/LibraryMode/Properties/AssemblyInfo.cs similarity index 66% rename from src/coreclr/vm/loongarch64/unixstubs.cpp rename to src/mono/wasm/testassets/LibraryMode/Properties/AssemblyInfo.cs index 878d5b003686b6..9ad9b578f20649 100644 --- a/src/coreclr/vm/loongarch64/unixstubs.cpp +++ b/src/mono/wasm/testassets/LibraryMode/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#include "common.h" +[assembly:System.Runtime.Versioning.SupportedOSPlatform("browser")] diff --git a/src/mono/wasm/testassets/LibraryMode/wwwroot/index.html b/src/mono/wasm/testassets/LibraryMode/wwwroot/index.html new file mode 100644 index 00000000000000..c18dfd76732e2c --- /dev/null +++ b/src/mono/wasm/testassets/LibraryMode/wwwroot/index.html @@ -0,0 +1,16 @@ + + + + + + + tmp + + + + + + + + + diff --git a/src/mono/wasm/testassets/LibraryMode/wwwroot/main.js b/src/mono/wasm/testassets/LibraryMode/wwwroot/main.js new file mode 100644 index 00000000000000..91ea838e89c235 --- /dev/null +++ b/src/mono/wasm/testassets/LibraryMode/wwwroot/main.js @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +import { dotnet } from './_framework/dotnet.js' + +const { getAssemblyExports, getConfig } = await dotnet.create(); + +const config = getConfig(); +const exports = await getAssemblyExports(config.mainAssemblyName); +var code = exports.LibraryMode.Test.MyExport(); +console.log(`WASM EXIT ${code}`); \ No newline at end of file diff --git a/src/mono/wasm/workloads.proj b/src/mono/wasm/workloads.proj index 4c8e6943618983..ba206c5a0e1385 100644 --- a/src/mono/wasm/workloads.proj +++ b/src/mono/wasm/workloads.proj @@ -11,10 +11,9 @@ <_PropsForAOTCrossBuild Include="@(_DefaultPropsForNuGetBuild)" /> <_PropsForAOTCrossBuild Include="TestingWorkloads=true" /> <_PropsForAOTCrossBuild Include="RuntimeIdentifier=$(NETCoreSdkRuntimeIdentifier)" /> - <_PropsForAOTCrossBuild Include="TargetCrossRid=browser-wasm" /> <_PropsForAOTCrossBuild Include="DisableSourceLink=true" /> - diff --git a/src/native/corehost/CMakeLists.txt b/src/native/corehost/CMakeLists.txt index c03885d5b349ed..5ce72395e49f7f 100644 --- a/src/native/corehost/CMakeLists.txt +++ b/src/native/corehost/CMakeLists.txt @@ -103,9 +103,7 @@ if (NOT "${ASAN_RUNTIME}" STREQUAL "") install(FILES ${ASAN_RUNTIME} DESTINATION corehost_test) endif() -if (NOT RUNTIME_FLAVOR STREQUAL Mono) - if(CLR_CMAKE_TARGET_WIN32) - add_subdirectory(comhost) - add_subdirectory(ijwhost) - endif() +if(CLR_CMAKE_HOST_WIN32) + add_subdirectory(comhost) + add_subdirectory(ijwhost) endif() diff --git a/src/native/corehost/build.cmd b/src/native/corehost/build.cmd index e5f535467ad38b..666226ee29a965 100644 --- a/src/native/corehost/build.cmd +++ b/src/native/corehost/build.cmd @@ -104,7 +104,6 @@ for /f "delims=-" %%i in ("%__OutputRid%") do set __HostFallbackOS=%%i if "%__HostFallbackOS%" == "win" (set __HostFallbackOS=win10) set __ExtraCmakeParams=%__ExtraCmakeParams% "-DCLI_CMAKE_PKG_RID=%cm_BaseRid%" "-DCLI_CMAKE_FALLBACK_OS=%__HostFallbackOS%" "-DCLI_CMAKE_COMMIT_HASH=%__CommitSha%" -set __ExtraCmakeParams=%__ExtraCmakeParams% "-DRUNTIME_FLAVOR=%__RuntimeFlavor% " set __ExtraCmakeParams=%__ExtraCmakeParams% "-DCLI_CMAKE_RESOURCE_DIR=%__ResourcesDir%" "-DCMAKE_BUILD_TYPE=%CMAKE_BUILD_TYPE%" :: Regenerate the native build files diff --git a/src/native/corehost/build.sh b/src/native/corehost/build.sh index 6d112876e9de23..0f90013591b4ce 100755 --- a/src/native/corehost/build.sh +++ b/src/native/corehost/build.sh @@ -60,7 +60,6 @@ __IntermediatesDir="$__RootBinDir/obj/$__OutputRid.$__BuildType" export __BinDir __IntermediatesDir __RuntimeFlavor __CMakeArgs="-DCLI_CMAKE_PKG_RID=\"$__OutputRid\" -DCLI_CMAKE_FALLBACK_OS=\"$__HostFallbackOS\" -DCLI_CMAKE_COMMIT_HASH=\"$__commit_hash\" $__CMakeArgs" -__CMakeArgs="-DRUNTIME_FLAVOR=\"$__RuntimeFlavor\" $__CMakeArgs" __CMakeArgs="-DFEATURE_DISTRO_AGNOSTIC_SSL=$__PortableBuild $__CMakeArgs" # Specify path to be set for CMAKE_INSTALL_PREFIX. diff --git a/src/native/corehost/hostmisc/pal.windows.cpp b/src/native/corehost/hostmisc/pal.windows.cpp index 06070b0b1d5da2..40999ab002fe27 100644 --- a/src/native/corehost/hostmisc/pal.windows.cpp +++ b/src/native/corehost/hostmisc/pal.windows.cpp @@ -898,8 +898,12 @@ bool pal::realpath(pal::string_t* path, bool skip_error_logging) } } - // Remove the \\?\ prefix, unless it is necessary or was already there - if (LongFile::IsExtended(str) && !LongFile::IsExtended(*path) && + // Remove the UNC extended prefix (\\?\UNC\) or extended prefix (\\?\) unless it is necessary or was already there + if (LongFile::IsUNCExtended(str) && !LongFile::IsUNCExtended(*path) && str.length() < MAX_PATH) + { + str.replace(0, LongFile::UNCExtendedPathPrefix.size(), LongFile::UNCPathPrefix); + } + else if (LongFile::IsExtended(str) && !LongFile::IsExtended(*path) && !LongFile::ShouldNormalize(str.substr(LongFile::ExtendedPrefix.size()))) { str.erase(0, LongFile::ExtendedPrefix.size()); diff --git a/src/native/corehost/test/CMakeLists.txt b/src/native/corehost/test/CMakeLists.txt index 4310a0e8449b36..ff270ede2697c2 100644 --- a/src/native/corehost/test/CMakeLists.txt +++ b/src/native/corehost/test/CMakeLists.txt @@ -3,10 +3,8 @@ add_subdirectory(mockcoreclr) add_subdirectory(mockhostfxr) add_subdirectory(mockhostpolicy) add_subdirectory(nativehost) -if (NOT RUNTIME_FLAVOR STREQUAL Mono) - if (CLR_CMAKE_TARGET_WIN32) - add_subdirectory(comsxs) - add_subdirectory(ijw) - add_subdirectory(typelibs) - endif() +if (CLR_CMAKE_HOST_WIN32) + add_subdirectory(comsxs) + add_subdirectory(ijw) + add_subdirectory(typelibs) endif() diff --git a/src/native/external/zlib-ng-version.txt b/src/native/external/zlib-ng-version.txt index 3384f5f8617e73..a892ef3e5239e9 100644 --- a/src/native/external/zlib-ng-version.txt +++ b/src/native/external/zlib-ng-version.txt @@ -12,3 +12,4 @@ We have removed the following folders from our local copy as these files are not Also, if the next version does not yet contain the fixes included in 12bc7edc73308f017ec40c6b2db694a6e3490ac2, cherry-pick it as a patch. Apply https://github.com/zlib-ng/zlib-ng/pull/1812 +Apply https://github.com/zlib-ng/zlib-ng/pull/1853 diff --git a/src/native/external/zlib-ng/arch/riscv/riscv_features.c b/src/native/external/zlib-ng/arch/riscv/riscv_features.c index 1e3f45e0a73a55..b1f166d749b568 100644 --- a/src/native/external/zlib-ng/arch/riscv/riscv_features.c +++ b/src/native/external/zlib-ng/arch/riscv/riscv_features.c @@ -22,7 +22,7 @@ int Z_INTERNAL is_kernel_version_greater_or_equal_to_6_5() { return 0; } - if (major > 6 || major == 6 && minor >= 5) + if (major > 6 || (major == 6 && minor >= 5)) return 1; return 0; } diff --git a/src/native/libs/System.Globalization.Native/CMakeLists.txt b/src/native/libs/System.Globalization.Native/CMakeLists.txt index 45dab320037cda..035f85a257b97c 100644 --- a/src/native/libs/System.Globalization.Native/CMakeLists.txt +++ b/src/native/libs/System.Globalization.Native/CMakeLists.txt @@ -140,7 +140,6 @@ include_directories("../Common") if (GEN_SHARED_LIB) if (CLR_CMAKE_TARGET_APPLE) - include(CMakeFindFrameworks) find_library(FOUNDATION Foundation REQUIRED) endif() diff --git a/src/native/libs/System.Native/entrypoints.c b/src/native/libs/System.Native/entrypoints.c index fcde21046a7c4b..a133f59b179e2d 100644 --- a/src/native/libs/System.Native/entrypoints.c +++ b/src/native/libs/System.Native/entrypoints.c @@ -37,6 +37,7 @@ static const Entry s_sysNative[] = DllImportEntry(SystemNative_GetWindowSize) DllImportEntry(SystemNative_IsATty) DllImportEntry(SystemNative_InitializeTerminalAndSignalHandling) + DllImportEntry(SystemNative_UninitializeTerminal) DllImportEntry(SystemNative_SetKeypadXmit) DllImportEntry(SystemNative_GetControlCharacters) DllImportEntry(SystemNative_StdinReady) diff --git a/src/native/libs/System.Native/extra_libs.cmake b/src/native/libs/System.Native/extra_libs.cmake index 59568825464fdb..68c2c128105b50 100644 --- a/src/native/libs/System.Native/extra_libs.cmake +++ b/src/native/libs/System.Native/extra_libs.cmake @@ -13,7 +13,6 @@ macro(append_extra_system_libs NativeLibsExtra) endif () if (CLR_CMAKE_TARGET_APPLE) - include(CMakeFindFrameworks) find_library(FOUNDATION Foundation REQUIRED) list(APPEND ${NativeLibsExtra} ${FOUNDATION}) endif () diff --git a/src/native/libs/System.Native/pal_console.c b/src/native/libs/System.Native/pal_console.c index fed98724be3935..b51e16c0bbc271 100644 --- a/src/native/libs/System.Native/pal_console.c +++ b/src/native/libs/System.Native/pal_console.c @@ -194,8 +194,8 @@ static bool ConfigureTerminal(bool signalForBreak, bool forChild, uint8_t minCha void UninitializeTerminal(void) { - // This method is called on SIGQUIT/SIGINT from the signal dispatching thread - // and on atexit. + // This method is called on SIGQUIT/SIGINT from the signal dispatching thread, + // on atexit, and for AppDomain.UnhandledException. if (pthread_mutex_lock(&g_lock) == 0) { @@ -473,3 +473,8 @@ int32_t SystemNative_InitializeTerminalAndSignalHandling(void) return initialized; } + +void SystemNative_UninitializeTerminal(void) +{ + UninitializeTerminal(); +} diff --git a/src/native/libs/System.Native/pal_console.h b/src/native/libs/System.Native/pal_console.h index 5bf8e63b80bc19..ba4feb2a290a56 100644 --- a/src/native/libs/System.Native/pal_console.h +++ b/src/native/libs/System.Native/pal_console.h @@ -123,6 +123,11 @@ PALEXPORT int32_t SystemNative_GetSignalForBreak(void); */ PALEXPORT int32_t SystemNative_SetSignalForBreak(int32_t signalForBreak); +/** + * Resets the terminal to the state it was in before calling InitializeTerminalAndSignalHandling. + */ +PALEXPORT void SystemNative_UninitializeTerminal(void); + typedef enum { Interrupt = 0, diff --git a/src/native/libs/System.Native/pal_console_wasi.c b/src/native/libs/System.Native/pal_console_wasi.c index f5930c41ec63f5..be7aaf888294f7 100644 --- a/src/native/libs/System.Native/pal_console_wasi.c +++ b/src/native/libs/System.Native/pal_console_wasi.c @@ -117,3 +117,6 @@ int32_t SystemNative_InitializeTerminalAndSignalHandling(void) { return true; } + +void SystemNative_UninitializeTerminal(void) +{ } diff --git a/src/tests/Directory.Build.targets b/src/tests/Directory.Build.targets index 8e7b97442b55bc..2aa41bd5137c0a 100644 --- a/src/tests/Directory.Build.targets +++ b/src/tests/Directory.Build.targets @@ -121,6 +121,7 @@ <_WillCLRTestProjectBuild Condition="'$(CLRTestBuildAllTargets)' != 'allTargets' And '$(CLRTestTargetUnsupported)' == 'true'">false <_WillCLRTestProjectBuild Condition="'$(DisableProjectBuild)' == 'true'">false <_WillCLRTestProjectBuild Condition="'$(NativeAotIncompatible)' == 'true' and '$(TestBuildMode)' == 'nativeaot'">false + <_WillCLRTestProjectBuild Condition="'$(IsGCSimulatorTest)' == 'true' and '$(TestBuildMode)' == 'nativeaot'">false <_WillCLRTestProjectBuild Condition="'$(RuntimeFlavor)' == 'mono' And '$(AlwaysUseCrossgen2)' == 'true'">false <_WillCLRTestProjectBuild Condition="'$(EnableNativeSanitizers)' != '' And '$(AlwaysUseCrossgen2)' == 'true'">false <_WillCLRTestProjectBuild Condition="'$(TestBuildMode)' == 'nativeaot' And '$(AlwaysUseCrossgen2)' == 'true'">false diff --git a/src/tests/FunctionalTests/tvOS/Device/AOT/tvOS.Device.Aot.Test.csproj b/src/tests/FunctionalTests/tvOS/Device/AOT/tvOS.Device.Aot.Test.csproj index 0e2f71fe06b3d0..92271eb0c889ce 100644 --- a/src/tests/FunctionalTests/tvOS/Device/AOT/tvOS.Device.Aot.Test.csproj +++ b/src/tests/FunctionalTests/tvOS/Device/AOT/tvOS.Device.Aot.Test.csproj @@ -19,11 +19,6 @@ false - - - - - diff --git a/src/tests/Interop/ObjectiveC/AutoReleaseTest/CMakeLists.txt b/src/tests/Interop/ObjectiveC/AutoReleaseTest/CMakeLists.txt index 2e5e11993ef623..39417b1124c9d6 100644 --- a/src/tests/Interop/ObjectiveC/AutoReleaseTest/CMakeLists.txt +++ b/src/tests/Interop/ObjectiveC/AutoReleaseTest/CMakeLists.txt @@ -15,7 +15,6 @@ set(SOURCES set_source_files_properties(autorelease.m PROPERTIES COMPILE_FLAGS -fno-objc-arc) -include(CMakeFindFrameworks) find_library(FOUNDATION Foundation REQUIRED) add_library(ObjectiveC SHARED ${SOURCES}) diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_nd0A_d.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_nd0A_d.csproj index 144281b7875e25..89a5c99afe660a 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_nd0A_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_nd0A_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_nd0A_r.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_nd0A_r.csproj index 59283283f66451..3da78e93de13ea 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_nd0A_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_nd0A_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_nd1A_d.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_nd1A_d.csproj index da191efaf5b279..730240057fd6c3 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_nd1A_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_nd1A_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_nd1A_r.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_nd1A_r.csproj index a4380d994b4cf0..8663c57654a963 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_nd1A_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_nd1A_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_nd2A_d.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_nd2A_d.csproj index f6446a53f58d6e..63f9af7888e84b 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_nd2A_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_nd2A_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_nd2A_r.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_nd2A_r.csproj index 1623da04f2371e..df97eebda945bb 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_nd2A_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_nd2A_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_nf0A_d.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_nf0A_d.csproj index 8651e5abb23628..104278a7e73f75 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_nf0A_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_nf0A_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_nf0A_r.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_nf0A_r.csproj index 05fe26037aedcd..60d259fd197087 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_nf0A_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_nf0A_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_nf1A_d.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_nf1A_d.csproj index 76653333475b6b..2c7063fd7c7899 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_nf1A_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_nf1A_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_nf1A_r.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_nf1A_r.csproj index a644f3db52b303..1d78a0b93d01a3 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_nf1A_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_nf1A_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_nf2A_d.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_nf2A_d.csproj index bdc39b8eed92d1..2941d07fceca67 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_nf2A_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_nf2A_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_nf2A_r.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_nf2A_r.csproj index 1760d3f7cda870..ec6438458df73e 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_nf2A_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_nf2A_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_sd0A_d.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_sd0A_d.csproj index 36e3ae5e205fe5..5c0284395f4d20 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_sd0A_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_sd0A_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_sd0A_r.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_sd0A_r.csproj index 7b409dab0296dd..736e88b1a81723 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_sd0A_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_sd0A_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_sd1A_d.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_sd1A_d.csproj index 76b4ce34b28208..445cc1d2a69c75 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_sd1A_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_sd1A_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_sd1A_r.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_sd1A_r.csproj index 3d7e473c2e9a70..ceab2b9986b803 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_sd1A_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_sd1A_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_sd2A_d.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_sd2A_d.csproj index c6033cb9704649..ee2705c025df06 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_sd2A_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_sd2A_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_sd2A_r.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_sd2A_r.csproj index 84e865a88838db..a0b2e2256df777 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_sd2A_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_sd2A_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_sf0A_d.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_sf0A_d.csproj index 74b537d8b26394..5b055f3f57448b 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_sf0A_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_sf0A_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_sf0A_r.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_sf0A_r.csproj index 881ce73bf9436c..e1cb4737fe6517 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_sf0A_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_sf0A_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_sf1A_d.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_sf1A_d.csproj index 3d8cf022440939..72f60f05c894f2 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_sf1A_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_sf1A_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_sf1A_r.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_sf1A_r.csproj index 66095581005acb..b858564cd55258 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_sf1A_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_sf1A_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_sf2A_d.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_sf2A_d.csproj index 5d58fc8c40c787..5b76bad8bf5f99 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_sf2A_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_sf2A_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testA/hfa_sf2A_r.csproj b/src/tests/JIT/jit64/hfa/main/testA/hfa_sf2A_r.csproj index 1936c66fad2364..63857f5e7f1766 100644 --- a/src/tests/JIT/jit64/hfa/main/testA/hfa_sf2A_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testA/hfa_sf2A_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testB/hfa_nd0B_d.csproj b/src/tests/JIT/jit64/hfa/main/testB/hfa_nd0B_d.csproj index b7014d2d55a77c..20a4cd50100183 100644 --- a/src/tests/JIT/jit64/hfa/main/testB/hfa_nd0B_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testB/hfa_nd0B_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testB/hfa_nd0B_r.csproj b/src/tests/JIT/jit64/hfa/main/testB/hfa_nd0B_r.csproj index c33df19bebb88e..80ac74884c56fe 100644 --- a/src/tests/JIT/jit64/hfa/main/testB/hfa_nd0B_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testB/hfa_nd0B_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testB/hfa_nd2B_d.csproj b/src/tests/JIT/jit64/hfa/main/testB/hfa_nd2B_d.csproj index 58a0024122da47..8f55ed4610016f 100644 --- a/src/tests/JIT/jit64/hfa/main/testB/hfa_nd2B_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testB/hfa_nd2B_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testB/hfa_nd2B_r.csproj b/src/tests/JIT/jit64/hfa/main/testB/hfa_nd2B_r.csproj index 63c94600c7c9a8..64a6dd0efb1121 100644 --- a/src/tests/JIT/jit64/hfa/main/testB/hfa_nd2B_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testB/hfa_nd2B_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testB/hfa_nf0B_d.csproj b/src/tests/JIT/jit64/hfa/main/testB/hfa_nf0B_d.csproj index 87dea2be99c91e..6061c152897d98 100644 --- a/src/tests/JIT/jit64/hfa/main/testB/hfa_nf0B_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testB/hfa_nf0B_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testB/hfa_nf0B_r.csproj b/src/tests/JIT/jit64/hfa/main/testB/hfa_nf0B_r.csproj index ff6b1d32798897..b49c304b97b121 100644 --- a/src/tests/JIT/jit64/hfa/main/testB/hfa_nf0B_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testB/hfa_nf0B_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testB/hfa_nf2B_d.csproj b/src/tests/JIT/jit64/hfa/main/testB/hfa_nf2B_d.csproj index c6bc2ee5807729..ae0702dcd14db3 100644 --- a/src/tests/JIT/jit64/hfa/main/testB/hfa_nf2B_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testB/hfa_nf2B_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testB/hfa_nf2B_r.csproj b/src/tests/JIT/jit64/hfa/main/testB/hfa_nf2B_r.csproj index cda150a02ad59d..d226b59e68987a 100644 --- a/src/tests/JIT/jit64/hfa/main/testB/hfa_nf2B_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testB/hfa_nf2B_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testB/hfa_sd0B_d.csproj b/src/tests/JIT/jit64/hfa/main/testB/hfa_sd0B_d.csproj index 2944fb62db9b65..6110a94701e0a5 100644 --- a/src/tests/JIT/jit64/hfa/main/testB/hfa_sd0B_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testB/hfa_sd0B_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testB/hfa_sd0B_r.csproj b/src/tests/JIT/jit64/hfa/main/testB/hfa_sd0B_r.csproj index 844ee631e04852..d0589f7d3250b0 100644 --- a/src/tests/JIT/jit64/hfa/main/testB/hfa_sd0B_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testB/hfa_sd0B_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testB/hfa_sd2B_d.csproj b/src/tests/JIT/jit64/hfa/main/testB/hfa_sd2B_d.csproj index 5880bc518be6bc..e9ed41e43f6a3b 100644 --- a/src/tests/JIT/jit64/hfa/main/testB/hfa_sd2B_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testB/hfa_sd2B_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testB/hfa_sd2B_r.csproj b/src/tests/JIT/jit64/hfa/main/testB/hfa_sd2B_r.csproj index fe56d1f47265e7..200e26b86d8eab 100644 --- a/src/tests/JIT/jit64/hfa/main/testB/hfa_sd2B_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testB/hfa_sd2B_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testB/hfa_sf0B_d.csproj b/src/tests/JIT/jit64/hfa/main/testB/hfa_sf0B_d.csproj index ab8d8362eed0fb..f116867606285e 100644 --- a/src/tests/JIT/jit64/hfa/main/testB/hfa_sf0B_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testB/hfa_sf0B_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testB/hfa_sf0B_r.csproj b/src/tests/JIT/jit64/hfa/main/testB/hfa_sf0B_r.csproj index a62d66b7f4c7be..e428f2f0b0e907 100644 --- a/src/tests/JIT/jit64/hfa/main/testB/hfa_sf0B_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testB/hfa_sf0B_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testB/hfa_sf2B_d.csproj b/src/tests/JIT/jit64/hfa/main/testB/hfa_sf2B_d.csproj index 08537b15adf6d9..45a28baeeb9540 100644 --- a/src/tests/JIT/jit64/hfa/main/testB/hfa_sf2B_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testB/hfa_sf2B_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testB/hfa_sf2B_r.csproj b/src/tests/JIT/jit64/hfa/main/testB/hfa_sf2B_r.csproj index cb9eb764050424..c175069e6012a2 100644 --- a/src/tests/JIT/jit64/hfa/main/testB/hfa_sf2B_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testB/hfa_sf2B_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_nd0C_d.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_nd0C_d.csproj index 5b35cddcbd1b7f..adf1127046a057 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_nd0C_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_nd0C_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_nd0C_r.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_nd0C_r.csproj index b746c42d03f058..45c5266b2aac9a 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_nd0C_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_nd0C_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_nd1C_d.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_nd1C_d.csproj index 88b0e0aceafe06..e2357af3fa069a 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_nd1C_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_nd1C_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_nd1C_r.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_nd1C_r.csproj index 3d2d53728b4f8e..62b62f47ede38a 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_nd1C_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_nd1C_r.csproj @@ -1,8 +1,4 @@ - - - true - PdbOnly diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_nd2C_d.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_nd2C_d.csproj index f229cf11b9e52f..1ec0ca2927349e 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_nd2C_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_nd2C_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_nd2C_r.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_nd2C_r.csproj index f4688126ad5a2a..d0d529557f3760 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_nd2C_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_nd2C_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_nf0C_d.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_nf0C_d.csproj index ab9e02a15a32f7..6bae35581d6f5e 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_nf0C_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_nf0C_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_nf0C_r.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_nf0C_r.csproj index 78db6548a48a30..13ca1c867f4094 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_nf0C_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_nf0C_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_nf1C_d.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_nf1C_d.csproj index 27dceaddd9cf6c..c44482ae2b139d 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_nf1C_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_nf1C_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_nf1C_r.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_nf1C_r.csproj index bc3b1a6dc0e1ec..eaae7a345b8bb8 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_nf1C_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_nf1C_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_nf2C_d.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_nf2C_d.csproj index 0a4b1bb9ef81db..bd0ee9c1d9f2bb 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_nf2C_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_nf2C_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_nf2C_r.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_nf2C_r.csproj index f3ef987c7d7cf0..6fb6651fa7c48d 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_nf2C_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_nf2C_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_sd0C_d.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_sd0C_d.csproj index 12f349c76d0c31..ad545125d1e685 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_sd0C_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_sd0C_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_sd0C_r.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_sd0C_r.csproj index b2436fd19f2dce..47bcb05d141e9f 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_sd0C_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_sd0C_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_sd1C_d.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_sd1C_d.csproj index aad65d7d0a4631..92bb78b15f4ae8 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_sd1C_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_sd1C_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_sd1C_r.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_sd1C_r.csproj index d4fa63063e8a8c..bf2a292018b846 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_sd1C_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_sd1C_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_sd2C_d.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_sd2C_d.csproj index f59fe94898832c..9aa15371f98f0f 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_sd2C_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_sd2C_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_sd2C_r.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_sd2C_r.csproj index e3e328cd7371c2..3c68c19af3542a 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_sd2C_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_sd2C_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_sf0C_d.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_sf0C_d.csproj index e16007034ccdd1..4d94494a341530 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_sf0C_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_sf0C_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_sf0C_r.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_sf0C_r.csproj index 9defb84da15992..713e9714d780ac 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_sf0C_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_sf0C_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_sf1C_d.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_sf1C_d.csproj index d68bd16fc2ef21..dfd573ffcc0253 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_sf1C_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_sf1C_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_sf1C_r.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_sf1C_r.csproj index 6726921a74ac4c..158699160c4e73 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_sf1C_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_sf1C_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_sf2C_d.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_sf2C_d.csproj index 45b47e04deb0b0..95897f0b30feae 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_sf2C_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_sf2C_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testC/hfa_sf2C_r.csproj b/src/tests/JIT/jit64/hfa/main/testC/hfa_sf2C_r.csproj index 41a82f7852d95d..6f7b5f08dbd027 100644 --- a/src/tests/JIT/jit64/hfa/main/testC/hfa_sf2C_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testC/hfa_sf2C_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_nd0E_d.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_nd0E_d.csproj index 6649b58ad6573a..12bfcada947ae1 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_nd0E_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_nd0E_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_nd0E_r.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_nd0E_r.csproj index 773e14e2351ce0..159dcf3027c948 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_nd0E_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_nd0E_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_nd1E_d.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_nd1E_d.csproj index 4a64c5b956fa6f..f1e42c039ae2b5 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_nd1E_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_nd1E_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_nd1E_r.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_nd1E_r.csproj index cab53553d64945..a2fd7adbeb3f00 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_nd1E_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_nd1E_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_nd2E_d.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_nd2E_d.csproj index f225a846db1e60..1d0cafe06b2a61 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_nd2E_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_nd2E_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_nd2E_r.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_nd2E_r.csproj index 609b3debadd64a..8bdbbf8a42ef99 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_nd2E_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_nd2E_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_nf0E_d.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_nf0E_d.csproj index 75b3829d2f55dc..6c4570c97cbdba 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_nf0E_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_nf0E_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_nf0E_r.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_nf0E_r.csproj index 1797059ceb61eb..b1dcad03e503cc 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_nf0E_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_nf0E_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_nf1E_d.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_nf1E_d.csproj index dfa7a0cd63d79b..60015cabf40c92 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_nf1E_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_nf1E_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_nf1E_r.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_nf1E_r.csproj index 4900b6f0831c26..107adda4103957 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_nf1E_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_nf1E_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_nf2E_d.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_nf2E_d.csproj index a0727f248a6577..e8ffaea1631f71 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_nf2E_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_nf2E_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_nf2E_r.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_nf2E_r.csproj index b7feb453e131fa..b984a0d23f1d33 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_nf2E_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_nf2E_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_sd0E_d.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_sd0E_d.csproj index b37107a2230d36..1624ab3ec88cb7 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_sd0E_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_sd0E_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_sd0E_r.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_sd0E_r.csproj index b381d0fdc0d498..be12361d9a843e 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_sd0E_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_sd0E_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_sd1E_d.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_sd1E_d.csproj index 2f49d970aece00..6b8eac873aa1fc 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_sd1E_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_sd1E_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_sd1E_r.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_sd1E_r.csproj index c1e5ea7a400d5c..2a8a9e14ec7aaa 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_sd1E_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_sd1E_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_sd2E_d.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_sd2E_d.csproj index cebf000e1f8ded..0c0aefa4bd3411 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_sd2E_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_sd2E_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_sd2E_r.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_sd2E_r.csproj index 0e538325406872..840d864dd5479b 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_sd2E_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_sd2E_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_sf0E_d.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_sf0E_d.csproj index 4579f26a8b3b31..185e9d55e1d3f0 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_sf0E_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_sf0E_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_sf0E_r.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_sf0E_r.csproj index 0a71ab99798569..0a85698cdd4bf6 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_sf0E_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_sf0E_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_sf1E_d.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_sf1E_d.csproj index 6365117624af3d..e30ca9dd2da387 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_sf1E_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_sf1E_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_sf1E_r.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_sf1E_r.csproj index 68d35b2dcc7a95..8d6de798d323ea 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_sf1E_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_sf1E_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_sf2E_d.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_sf2E_d.csproj index 4709e657f0beca..78d2bdf84593a9 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_sf2E_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_sf2E_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testE/hfa_sf2E_r.csproj b/src/tests/JIT/jit64/hfa/main/testE/hfa_sf2E_r.csproj index 8830166d0fbf7f..6aea30e966e695 100644 --- a/src/tests/JIT/jit64/hfa/main/testE/hfa_sf2E_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testE/hfa_sf2E_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_nd0G_d.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_nd0G_d.csproj index dd28b44c9bda91..35022dd89969c9 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_nd0G_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_nd0G_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_nd0G_r.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_nd0G_r.csproj index 2274ac7a563ab8..df8aecb4a9d5f6 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_nd0G_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_nd0G_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_nd1G_d.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_nd1G_d.csproj index 456d75ba94aa40..2c68a1d2836718 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_nd1G_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_nd1G_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_nd1G_r.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_nd1G_r.csproj index 7ce16104572e44..9b932ecd8af776 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_nd1G_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_nd1G_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_nd2G_d.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_nd2G_d.csproj index d2accffa7d1200..253af8f5315152 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_nd2G_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_nd2G_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_nd2G_r.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_nd2G_r.csproj index c0713710cb07a4..7f2197bf5af7c2 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_nd2G_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_nd2G_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_nf0G_d.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_nf0G_d.csproj index c6d315db21e7aa..ea85cae91783e3 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_nf0G_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_nf0G_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_nf0G_r.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_nf0G_r.csproj index 99de5e20f0a2db..514495faca4981 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_nf0G_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_nf0G_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_nf1G_d.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_nf1G_d.csproj index f0c983f5eaa678..bd869a63bb89b6 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_nf1G_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_nf1G_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_nf1G_r.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_nf1G_r.csproj index 36e9a1895c1722..21ca4bbb416bf9 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_nf1G_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_nf1G_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_nf2G_d.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_nf2G_d.csproj index 34236426629244..6474310172b50f 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_nf2G_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_nf2G_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_nf2G_r.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_nf2G_r.csproj index ceb7184cdb34fa..19715f7a8c1586 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_nf2G_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_nf2G_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_sd0G_d.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_sd0G_d.csproj index b74bf000226902..e1de2ee49e6ba3 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_sd0G_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_sd0G_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_sd0G_r.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_sd0G_r.csproj index 1ea7b2e00b07bd..b93c2891b0ab49 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_sd0G_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_sd0G_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_sd1G_d.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_sd1G_d.csproj index 43779d651d5d57..fb3360664f3734 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_sd1G_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_sd1G_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_sd1G_r.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_sd1G_r.csproj index 5962d7bfc79bde..2f2d72f1de8d65 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_sd1G_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_sd1G_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_sd2G_d.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_sd2G_d.csproj index 4704fed6e0b94e..eee97f05f36201 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_sd2G_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_sd2G_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_sd2G_r.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_sd2G_r.csproj index ae2c725f0a7c1a..f809fcd1b12125 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_sd2G_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_sd2G_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_sf0G_d.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_sf0G_d.csproj index 99a0a2fb66bbe2..7991f29c89bcb5 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_sf0G_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_sf0G_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_sf0G_r.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_sf0G_r.csproj index fc95305670f0a6..1fec4a76e5085e 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_sf0G_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_sf0G_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_sf1G_d.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_sf1G_d.csproj index 7b24ad20afbfa3..7079f8a4e36462 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_sf1G_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_sf1G_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_sf1G_r.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_sf1G_r.csproj index c103cb44789496..50bd82d40359c3 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_sf1G_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_sf1G_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_sf2G_d.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_sf2G_d.csproj index dc0cc3db6e74f5..a4286a5b786610 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_sf2G_d.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_sf2G_d.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/JIT/jit64/hfa/main/testG/hfa_sf2G_r.csproj b/src/tests/JIT/jit64/hfa/main/testG/hfa_sf2G_r.csproj index a39899f4dee017..f0435905a7e979 100644 --- a/src/tests/JIT/jit64/hfa/main/testG/hfa_sf2G_r.csproj +++ b/src/tests/JIT/jit64/hfa/main/testG/hfa_sf2G_r.csproj @@ -1,7 +1,5 @@ - - true 1 diff --git a/src/tests/Loader/StartupHooks/StartupHookTests.cs b/src/tests/Loader/StartupHooks/StartupHookTests.cs index e0801f335222f3..937538fcaa4836 100644 --- a/src/tests/Loader/StartupHooks/StartupHookTests.cs +++ b/src/tests/Loader/StartupHooks/StartupHookTests.cs @@ -208,7 +208,14 @@ public static void MissingStartupHookType() string hook = asm.Location; AppContext.SetData(StartupHookKey, hook); var ex = Assert.Throws(() => ProcessStartupHooks(string.Empty)); - Assert.StartsWith($"Could not load type 'StartupHook' from assembly '{asm.GetName().Name}", ex.Message); + if (ex.Message.StartsWith("Could not load type")) // Mono-specific behavior, avoid dependency on TestLibrary.Utilities.IsMonoRuntime + { + Assert.StartsWith($"Could not load type 'StartupHook' from assembly '{asm.GetName().Name}", ex.Message); + } + else + { + Assert.StartsWith($"Could not resolve type 'StartupHook' in assembly '{asm.GetName().Name}", ex.Message); + } } [Fact] diff --git a/src/tests/Loader/regressions/polyrec/Polyrec.csproj b/src/tests/Loader/regressions/polyrec/Polyrec.csproj index f3f7177188e83e..cfbe965e94851a 100644 --- a/src/tests/Loader/regressions/polyrec/Polyrec.csproj +++ b/src/tests/Loader/regressions/polyrec/Polyrec.csproj @@ -3,6 +3,8 @@ 1 true + + true diff --git a/src/tests/Regressions/coreclr/GitHub_110987/test110987.cs b/src/tests/Regressions/coreclr/GitHub_110987/test110987.cs index afedce3e944c61..c56f2fbdbf6955 100644 --- a/src/tests/Regressions/coreclr/GitHub_110987/test110987.cs +++ b/src/tests/Regressions/coreclr/GitHub_110987/test110987.cs @@ -6,6 +6,7 @@ using System.Reflection.Emit; using System.Runtime.Loader; using Xunit; +using TestLibrary; class TestAssemblyLoadContext : AssemblyLoadContext { @@ -16,7 +17,7 @@ public TestAssemblyLoadContext() : base(isCollectible: true) public class Test110987 { - [Fact] + [ConditionalFact(typeof(Utilities), nameof(Utilities.IsReflectionEmitSupported))] public static void TestDynamicMethodALC() { // Create a simple type