diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index a5b2ac29d318e5..308fee9e58f1fd 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -54,157 +54,157 @@ - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://github.com/dotnet/runtime-assets - 555080fde81d34b38dfab27115c52f0a620803a2 + bed0f7baa99a0dd670f096eba4adf0bec30f2f5d - + https://github.com/dotnet/runtime-assets - 555080fde81d34b38dfab27115c52f0a620803a2 + bed0f7baa99a0dd670f096eba4adf0bec30f2f5d - + https://github.com/dotnet/runtime-assets - 555080fde81d34b38dfab27115c52f0a620803a2 + bed0f7baa99a0dd670f096eba4adf0bec30f2f5d - + https://github.com/dotnet/runtime-assets - 555080fde81d34b38dfab27115c52f0a620803a2 + bed0f7baa99a0dd670f096eba4adf0bec30f2f5d - + https://github.com/dotnet/runtime-assets - 555080fde81d34b38dfab27115c52f0a620803a2 + bed0f7baa99a0dd670f096eba4adf0bec30f2f5d - + https://github.com/dotnet/runtime-assets - 555080fde81d34b38dfab27115c52f0a620803a2 + bed0f7baa99a0dd670f096eba4adf0bec30f2f5d - + https://github.com/dotnet/runtime-assets - 555080fde81d34b38dfab27115c52f0a620803a2 + bed0f7baa99a0dd670f096eba4adf0bec30f2f5d - + https://github.com/dotnet/runtime-assets - 555080fde81d34b38dfab27115c52f0a620803a2 + bed0f7baa99a0dd670f096eba4adf0bec30f2f5d - + https://github.com/dotnet/runtime-assets - 555080fde81d34b38dfab27115c52f0a620803a2 + bed0f7baa99a0dd670f096eba4adf0bec30f2f5d - + https://github.com/dotnet/runtime-assets - 555080fde81d34b38dfab27115c52f0a620803a2 + bed0f7baa99a0dd670f096eba4adf0bec30f2f5d - + https://github.com/dotnet/runtime-assets - 555080fde81d34b38dfab27115c52f0a620803a2 + bed0f7baa99a0dd670f096eba4adf0bec30f2f5d - + https://github.com/dotnet/runtime-assets - 555080fde81d34b38dfab27115c52f0a620803a2 + bed0f7baa99a0dd670f096eba4adf0bec30f2f5d - + https://github.com/dotnet/llvm-project - f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 + 75d7db9e507e979d2109bea18a19e44f1f655dd8 - + https://github.com/dotnet/llvm-project - f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 + 75d7db9e507e979d2109bea18a19e44f1f655dd8 - + https://github.com/dotnet/llvm-project - f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 + 75d7db9e507e979d2109bea18a19e44f1f655dd8 - + https://github.com/dotnet/llvm-project - f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 + 75d7db9e507e979d2109bea18a19e44f1f655dd8 - + https://github.com/dotnet/llvm-project - f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 + 75d7db9e507e979d2109bea18a19e44f1f655dd8 - + https://github.com/dotnet/llvm-project - f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 + 75d7db9e507e979d2109bea18a19e44f1f655dd8 - + https://github.com/dotnet/llvm-project - f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 + 75d7db9e507e979d2109bea18a19e44f1f655dd8 - + https://github.com/dotnet/llvm-project - f049b5ff5955a8281c70d27ad45cbd87e9df1ab6 + 75d7db9e507e979d2109bea18a19e44f1f655dd8 https://github.com/dotnet/runtime @@ -250,41 +250,49 @@ https://github.com/dotnet/xharness 5ebf69650b9f7b4ecab485be840b3022420f7812 - + https://github.com/dotnet/arcade - 6a638cd0c13962ab2a1943cb1c878be5a41dd82e + 0c027eede69ba22bafca9a1955f1e00848655ece - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - e01e5b0aed54a5a8d9df74e717d1b13f0fb0e056 + 5e0b0da43f660de5798186f4fd3bc900fc90576c - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - e01e5b0aed54a5a8d9df74e717d1b13f0fb0e056 + 5e0b0da43f660de5798186f4fd3bc900fc90576c - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - e01e5b0aed54a5a8d9df74e717d1b13f0fb0e056 + 5e0b0da43f660de5798186f4fd3bc900fc90576c - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - e01e5b0aed54a5a8d9df74e717d1b13f0fb0e056 + 5e0b0da43f660de5798186f4fd3bc900fc90576c https://github.com/dotnet/hotreload-utils beb43eebb0bb4bd299d562cedd54714528962add - + https://github.com/dotnet/runtime-assets - 555080fde81d34b38dfab27115c52f0a620803a2 + bed0f7baa99a0dd670f096eba4adf0bec30f2f5d - + https://github.com/dotnet/roslyn-analyzers - 793113a41d7f21b03470521bf48438f2abd9b12f + d80e535c08bf3eace650005ac2e7e061ed8692cd https://github.com/dotnet/sdk 3f2524bd65a6ab77b9160bcc23824dbc03990f3d + + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization + 5e0b0da43f660de5798186f4fd3bc900fc90576c + + + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization + 5e0b0da43f660de5798186f4fd3bc900fc90576c + diff --git a/eng/Versions.props b/eng/Versions.props index d65a78f7e95482..56a0914b1df516 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -44,7 +44,7 @@ 4.3.0-2.final 4.3.0-2.final 4.3.0-2.final - 7.0.0-preview1.22403.2 + 7.0.0-preview1.22419.4 4.3.0-2.final 7.0.100-rc.1.22402.1 - 7.0.0-beta.22411.2 - 7.0.0-beta.22411.2 - 7.0.0-beta.22411.2 - 7.0.0-beta.22411.2 - 7.0.0-beta.22411.2 - 7.0.0-beta.22411.2 - 2.5.1-beta.22411.2 - 7.0.0-beta.22411.2 - 7.0.0-beta.22411.2 - 7.0.0-beta.22411.2 - 7.0.0-beta.22411.2 - 7.0.0-beta.22411.2 - 7.0.0-beta.22411.2 - 7.0.0-beta.22411.2 - 7.0.0-beta.22411.2 - 7.0.0-beta.22411.2 + 7.0.0-beta.22418.4 + 7.0.0-beta.22418.4 + 7.0.0-beta.22418.4 + 7.0.0-beta.22418.4 + 7.0.0-beta.22418.4 + 7.0.0-beta.22418.4 + 2.5.1-beta.22418.4 + 7.0.0-beta.22418.4 + 7.0.0-beta.22418.4 + 7.0.0-beta.22418.4 + 7.0.0-beta.22418.4 + 7.0.0-beta.22418.4 + 7.0.0-beta.22418.4 + 7.0.0-beta.22418.4 + 7.0.0-beta.22418.4 + 7.0.0-beta.22418.4 6.0.0-preview.1.102 @@ -99,9 +99,9 @@ 4.5.0 5.0.0 5.0.0 - 4.5.4 + 4.5.5 4.5.0 - 6.0.0 + 6.0.1 4.7.1 4.7.0 4.7.0 @@ -119,24 +119,26 @@ 4.5.0 7.0.0-rc.1.22414.6 - 7.0.0-beta.22415.3 - 7.0.0-beta.22415.3 - 7.0.0-beta.22415.3 - 7.0.0-beta.22415.3 - 7.0.0-beta.22415.3 - 7.0.0-beta.22415.3 - 7.0.0-beta.22415.3 - 7.0.0-beta.22415.3 - 7.0.0-beta.22415.3 - 7.0.0-beta.22415.3 - 7.0.0-beta.22415.3 - 7.0.0-beta.22415.3 - 7.0.0-beta.22415.3 + 7.0.0-beta.22419.1 + 7.0.0-beta.22419.1 + 7.0.0-beta.22419.1 + 7.0.0-beta.22419.1 + 7.0.0-beta.22419.1 + 7.0.0-beta.22419.1 + 7.0.0-beta.22419.1 + 7.0.0-beta.22419.1 + 7.0.0-beta.22419.1 + 7.0.0-beta.22419.1 + 7.0.0-beta.22419.1 + 7.0.0-beta.22419.1 + 7.0.0-beta.22419.1 - 1.0.0-prerelease.22375.7 - 1.0.0-prerelease.22375.7 - 1.0.0-prerelease.22375.7 - 1.0.0-prerelease.22375.7 + 1.0.0-prerelease.22415.6 + 1.0.0-prerelease.22415.6 + 1.0.0-prerelease.22415.6 + 1.0.0-prerelease.22415.6 + 1.0.0-prerelease.22415.6 + 1.0.0-prerelease.22415.6 16.9.0-beta1.21055.5 2.0.0-beta4.22355.1 @@ -179,14 +181,14 @@ 2.1 7.0.0-alpha.1.22406.1 - 11.1.0-alpha.1.22415.2 - 11.1.0-alpha.1.22415.2 - 11.1.0-alpha.1.22415.2 - 11.1.0-alpha.1.22415.2 - 11.1.0-alpha.1.22415.2 - 11.1.0-alpha.1.22415.2 - 11.1.0-alpha.1.22415.2 - 11.1.0-alpha.1.22415.2 + 11.1.0-alpha.1.22419.2 + 11.1.0-alpha.1.22419.2 + 11.1.0-alpha.1.22419.2 + 11.1.0-alpha.1.22419.2 + 11.1.0-alpha.1.22419.2 + 11.1.0-alpha.1.22419.2 + 11.1.0-alpha.1.22419.2 + 11.1.0-alpha.1.22419.2 7.0.0-rc.1.22411.1 $(MicrosoftNETWorkloadEmscriptenManifest70100Version) diff --git a/eng/common/cross/build-rootfs.sh b/eng/common/cross/build-rootfs.sh index d3b0ac3ba7b600..032f5f193732a1 100755 --- a/eng/common/cross/build-rootfs.sh +++ b/eng/common/cross/build-rootfs.sh @@ -76,10 +76,10 @@ __FreeBSDPackages+=" openssl" __FreeBSDPackages+=" krb5" __FreeBSDPackages+=" terminfo-db" -__IllumosPackages="icu-64.2nb2" -__IllumosPackages+=" mit-krb5-1.16.2nb4" -__IllumosPackages+=" openssl-1.1.1e" -__IllumosPackages+=" zlib-1.2.11" +__IllumosPackages="icu" +__IllumosPackages+=" mit-krb5" +__IllumosPackages+=" openssl" +__IllumosPackages+=" zlib" __HaikuPackages="gmp" __HaikuPackages+=" gmp_devel" @@ -390,14 +390,18 @@ elif [[ "$__CodeName" == "illumos" ]]; then if [[ "$__UseMirror" == 1 ]]; then BaseUrl=http://pkgsrc.smartos.skylime.net fi - BaseUrl="$BaseUrl/packages/SmartOS/2020Q1/${__illumosArch}/All" + BaseUrl="$BaseUrl/packages/SmartOS/trunk/${__illumosArch}/All" + echo "Downloading manifest" + wget "$BaseUrl" echo "Downloading dependencies." read -ra array <<<"$__IllumosPackages" for package in "${array[@]}"; do - echo "Installing $package..." + echo "Installing '$package'" + package="$(grep ">$package-[0-9]" All | sed -En 's/.*href="(.*)\.tgz".*/\1/p')" + echo "Resolved name '$package'" wget "$BaseUrl"/"$package".tgz ar -x "$package".tgz - tar --skip-old-files -xzf "$package".tmp.tgz -C "$__RootfsDir" 2>/dev/null + tar --skip-old-files -xzf "$package".tmp.tg* -C "$__RootfsDir" 2>/dev/null done echo "Cleaning up temporary files." popd diff --git a/eng/common/generate-locproject.ps1 b/eng/common/generate-locproject.ps1 index afdd1750290923..846e7950ce945b 100644 --- a/eng/common/generate-locproject.ps1 +++ b/eng/common/generate-locproject.ps1 @@ -33,6 +33,8 @@ $jsonTemplateFiles | ForEach-Object { $jsonWinformsTemplateFiles = Get-ChildItem -Recurse -Path "$SourcesDirectory" | Where-Object { $_.FullName -Match "en\\strings\.json" } # current winforms pattern +$wxlFiles = Get-ChildItem -Recurse -Path "$SourcesDirectory" | Where-Object { $_.FullName -Match "\\.+\.wxl" -And -Not( $_.Directory.Name -Match "\d{4}" ) } # localized files live in four digit lang ID directories; this excludes them + $xlfFiles = @() $allXlfFiles = Get-ChildItem -Recurse -Path "$SourcesDirectory\*\*.xlf" @@ -77,8 +79,7 @@ $locJson = @{ CopyOption = "LangIDOnPath" OutputPath = "$($_.Directory.Parent.FullName | Resolve-Path -Relative)\" } - } - else { + } else { return @{ SourceFile = $sourceFile CopyOption = "LangIDOnName" @@ -88,6 +89,32 @@ $locJson = @{ } } ) + }, + @{ + CloneLanguageSet = "WiX_CloneLanguages" + LssFiles = @( "wxl_loc.lss" ) + LocItems = @( + $wxlFiles | ForEach-Object { + $outputPath = "$($_.Directory.FullName | Resolve-Path -Relative)\" + $continue = $true + foreach ($exclusion in $exclusions.Exclusions) { + if ($outputPath.Contains($exclusion)) + { + $continue = $false + } + } + $sourceFile = ($_.FullName | Resolve-Path -Relative) + if ($continue) + { + return @{ + SourceFile = $sourceFile + CopyOption = "LangIDOnPath" + OutputPath = $outputPath + Languages = "cs-CZ;de-DE;es-ES;fr-FR;it-IT;ja-JP;ko-KR;pl-PL;pt-BR;ru-RU;tr-TR;zh-CN;zh-TW" + } + } + } + ) } ) } diff --git a/eng/common/sdk-task.ps1 b/eng/common/sdk-task.ps1 index 119a6c660d1a4d..c35087a06019ef 100644 --- a/eng/common/sdk-task.ps1 +++ b/eng/common/sdk-task.ps1 @@ -64,7 +64,7 @@ try { $GlobalJson.tools | Add-Member -Name "vs" -Value (ConvertFrom-Json "{ `"version`": `"16.5`" }") -MemberType NoteProperty } if( -not ($GlobalJson.tools.PSObject.Properties.Name -match "xcopy-msbuild" )) { - $GlobalJson.tools | Add-Member -Name "xcopy-msbuild" -Value "17.1.0" -MemberType NoteProperty + $GlobalJson.tools | Add-Member -Name "xcopy-msbuild" -Value "17.2.1" -MemberType NoteProperty } if ($GlobalJson.tools."xcopy-msbuild".Trim() -ine "none") { $xcopyMSBuildToolsFolder = InitializeXCopyMSBuild $GlobalJson.tools."xcopy-msbuild" -install $true diff --git a/eng/common/sdl/sdl.ps1 b/eng/common/sdl/sdl.ps1 new file mode 100644 index 00000000000000..ac196e164a4016 --- /dev/null +++ b/eng/common/sdl/sdl.ps1 @@ -0,0 +1,37 @@ + +function Install-Gdn { + param( + [string]$Path, + + # If omitted, install the latest version of Guardian, otherwise install that specific version. + [string]$Version + ) + + $ErrorActionPreference = 'Stop' + Set-StrictMode -Version 2.0 + $disableConfigureToolsetImport = $true + $global:LASTEXITCODE = 0 + + # `tools.ps1` checks $ci to perform some actions. Since the SDL + # scripts don't necessarily execute in the same agent that run the + # build.ps1/sh script this variable isn't automatically set. + $ci = $true + . $PSScriptRoot\..\tools.ps1 + + $argumentList = @("install", "Microsoft.Guardian.Cli", "-Source https://securitytools.pkgs.visualstudio.com/_packaging/Guardian/nuget/v3/index.json", "-OutputDirectory $Path", "-NonInteractive", "-NoCache") + + if ($Version) { + $argumentList += "-Version $Version" + } + + Start-Process nuget -Verbose -ArgumentList $argumentList -NoNewWindow -Wait + + $gdnCliPath = Get-ChildItem -Filter guardian.cmd -Recurse -Path $Path + + if (!$gdnCliPath) + { + Write-PipelineTelemetryError -Category 'Sdl' -Message 'Failure installing Guardian' + } + + return $gdnCliPath.FullName +} \ No newline at end of file diff --git a/eng/common/templates/steps/execute-sdl.yml b/eng/common/templates/steps/execute-sdl.yml index 73245593cef53d..86cf578c431443 100644 --- a/eng/common/templates/steps/execute-sdl.yml +++ b/eng/common/templates/steps/execute-sdl.yml @@ -8,29 +8,26 @@ parameters: condition: '' steps: -- ${{ if ne(parameters.overrideGuardianVersion, '') }}: - - powershell: | - $content = Get-Content $(GuardianPackagesConfigFile) - - Write-Host "packages.config content was:`n$content" - - $content = $content.Replace('$(DefaultGuardianVersion)', '$(GuardianVersion)') - $content | Set-Content $(GuardianPackagesConfigFile) - - Write-Host "packages.config content updated to:`n$content" - displayName: Use overridden Guardian version ${{ parameters.overrideGuardianVersion }} +- task: NuGetAuthenticate@1 + inputs: + nuGetServiceConnections: GuardianConnect - task: NuGetToolInstaller@1 displayName: 'Install NuGet.exe' -- task: NuGetCommand@2 - displayName: 'Install Guardian' - inputs: - restoreSolution: $(Build.SourcesDirectory)\eng\common\sdl\packages.config - feedsToUse: config - nugetConfigPath: $(Build.SourcesDirectory)\eng\common\sdl\NuGet.config - externalFeedCredentials: GuardianConnect - restoreDirectory: $(Build.SourcesDirectory)\.packages +- ${{ if ne(parameters.overrideGuardianVersion, '') }}: + - pwsh: | + . $(Build.SourcesDirectory)\eng\common\sdl\sdl.ps1 + $guardianCliLocation = Install-Gdn -Path $(Build.SourcesDirectory)\.artifacts -Version ${{ parameters.overrideGuardianVersion }} + Write-Host "##vso[task.setvariable variable=GuardianCliLocation]$guardianCliLocation" + displayName: Install Guardian (Overridden) + +- ${{ if eq(parameters.overrideGuardianVersion, '') }}: + - pwsh: | + . $(Build.SourcesDirectory)\eng\common\sdl\sdl.ps1 + $guardianCliLocation = Install-Gdn -Path $(Build.SourcesDirectory)\.artifacts + Write-Host "##vso[task.setvariable variable=GuardianCliLocation]$guardianCliLocation" + displayName: Install Guardian - ${{ if ne(parameters.overrideParameters, '') }}: - powershell: ${{ parameters.executeAllSdlToolsScript }} ${{ parameters.overrideParameters }} @@ -40,7 +37,7 @@ steps: - ${{ if eq(parameters.overrideParameters, '') }}: - powershell: ${{ parameters.executeAllSdlToolsScript }} - -GuardianPackageName Microsoft.Guardian.Cli.$(GuardianVersion) + -GuardianCliLocation $(GuardianCliLocation) -NugetPackageDirectory $(Build.SourcesDirectory)\.packages -AzureDevOpsAccessToken $(dn-bot-dotnet-build-rw-code-rw) ${{ parameters.additionalParameters }} diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1 index f83a748c37e9cf..aba6308ad313c5 100644 --- a/eng/common/tools.ps1 +++ b/eng/common/tools.ps1 @@ -365,8 +365,8 @@ function InitializeVisualStudioMSBuild([bool]$install, [object]$vsRequirements = # If the version of msbuild is going to be xcopied, # use this version. Version matches a package here: - # https://dev.azure.com/dnceng/public/_packaging?_a=package&feed=dotnet-eng&package=RoslynTools.MSBuild&protocolType=NuGet&version=17.1.0&view=overview - $defaultXCopyMSBuildVersion = '17.1.0' + # https://dev.azure.com/dnceng/public/_packaging?_a=package&feed=dotnet-eng&package=RoslynTools.MSBuild&protocolType=NuGet&version=17.2.1&view=overview + $defaultXCopyMSBuildVersion = '17.2.1' if (!$vsRequirements) { if (Get-Member -InputObject $GlobalJson.tools -Name 'vs') { diff --git a/eng/native/configureplatform.cmake b/eng/native/configureplatform.cmake index c7a38c3eee8294..9f8ac48694b3c8 100644 --- a/eng/native/configureplatform.cmake +++ b/eng/native/configureplatform.cmake @@ -2,7 +2,7 @@ include(${CMAKE_CURRENT_LIST_DIR}/functions.cmake) # If set, indicates that this is not an officially supported release. # Release branches should set this to false. -set(PRERELEASE 1) +set(PRERELEASE 0) #---------------------------------------- # Detect and set platform variable names diff --git a/eng/nativepgo.targets b/eng/nativepgo.targets index e6d58a33994fff..5dc312774e3078 100644 --- a/eng/nativepgo.targets +++ b/eng/nativepgo.targets @@ -1,7 +1,7 @@ - true - true + true + true false false @@ -16,14 +16,20 @@ + + - + diff --git a/eng/pipelines/coreclr/templates/run-performance-job.yml b/eng/pipelines/coreclr/templates/run-performance-job.yml index d4e25aff3f4985..218c8262ad52de 100644 --- a/eng/pipelines/coreclr/templates/run-performance-job.yml +++ b/eng/pipelines/coreclr/templates/run-performance-job.yml @@ -64,29 +64,35 @@ jobs: - HelixPerfUploadTokenValue: '$(PerfCommandUploadTokenLinux)' - ${{ if and(notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.osGroup, 'windows')) }}: - HelixPerfUploadTokenValue: '$(PerfCommandUploadToken)' + - ${{ if eq(parameters.runtimeType, 'wasm') }}: + - HelixPreCommandsWasmOnLinux: >- + sudo apt-get -y remove nodejs && + curl -fsSL https://deb.nodesource.com/setup_14.x | sudo -E bash - && + sudo apt-get -y install nodejs && + npm install --prefix $HELIX_WORKITEM_PAYLOAD jsvu -g && + $HELIX_WORKITEM_PAYLOAD/bin/jsvu --os=linux64 --engines=v8,javascriptcore + - ${{ if ne(parameters.runtimeType, 'wasm') }}: + - HelixPreCommandsWasmOnLinux: echo - HelixPreCommandStemWindows: 'set ORIGPYPATH=%PYTHONPATH%;py -m pip install -U pip;py -3 -m venv %HELIX_WORKITEM_PAYLOAD%\.venv;call %HELIX_WORKITEM_PAYLOAD%\.venv\Scripts\activate.bat;set PYTHONPATH=;py -3 -m pip install -U pip;py -3 -m pip install azure.storage.blob==12.0.0;py -3 -m pip install azure.storage.queue==12.0.0;set "PERFLAB_UPLOAD_TOKEN=$(HelixPerfUploadTokenValue)"' - HelixPreCommandStemLinux: >- export ORIGPYPATH=$PYTHONPATH export CRYPTOGRAPHY_ALLOW_OPENSSL_102=true; echo "** Installing prerequistes **"; - python3 -m pip install -U pip && + python3 -m pip install --user -U pip && sudo apt-get -y install python3-venv && python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv && ls -l $HELIX_WORKITEM_PAYLOAD/.venv/bin/activate && export PYTHONPATH= && - python3 -m pip install -U pip && - pip3 install azure.storage.blob==12.0.0 && - pip3 install azure.storage.queue==12.0.0 && + python3 -m pip install --user -U pip && + pip3 install --user azure.storage.blob==12.0.0 && + pip3 install --user azure.storage.queue==12.0.0 && sudo apt-get update && sudo apt -y install curl dirmngr apt-transport-https lsb-release ca-certificates && - curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - && - sudo apt-get -y install nodejs && - npm install --prefix $HELIX_WORKITEM_PAYLOAD jsvu -g && - $HELIX_WORKITEM_PAYLOAD/bin/jsvu --os=linux64 --engines=v8,javascriptcore && - export PERFLAB_UPLOAD_TOKEN="$(HelixPerfUploadTokenValue)" && - export PERF_PREREQS_INSTALLED=1; - test "x$PERF_PREREQS_INSTALLED" = "x1" || echo "** Error: Failed to install prerequites **" - - HelixPreCommandStemMusl: 'export ORIGPYPATH=$PYTHONPATH;sudo apk add icu-libs krb5-libs libgcc libintl libssl1.1 libstdc++ zlib cargo;sudo apk add libgdiplus --repository http://dl-cdn.alpinelinux.org/alpine/edge/testing; python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv;source $HELIX_WORKITEM_PAYLOAD/.venv/bin/activate;export PYTHONPATH=;python3 -m pip install -U pip;pip3 install azure.storage.blob==12.7.1;pip3 install azure.storage.queue==12.1.5;export PERFLAB_UPLOAD_TOKEN="$(HelixPerfUploadTokenValue)"' + $(HelixPreCommandsWasmOnLinux) && + export PERFLAB_UPLOAD_TOKEN="$(HelixPerfUploadTokenValue)" + || export PERF_PREREQS_INSTALL_FAILED=1; + test "x$PERF_PREREQS_INSTALL_FAILED" = "x1" && echo "** Error: Failed to install prerequites **" + - HelixPreCommandStemMusl: 'export ORIGPYPATH=$PYTHONPATH;sudo apk add icu-libs krb5-libs libgcc libintl libssl1.1 libstdc++ zlib cargo;sudo apk add libgdiplus --repository http://dl-cdn.alpinelinux.org/alpine/edge/testing; python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv;source $HELIX_WORKITEM_PAYLOAD/.venv/bin/activate;export PYTHONPATH=;python3 -m pip install --user -U pip;pip3 install --user azure.storage.blob==12.7.1;pip3 install --user azure.storage.queue==12.1.5;export PERFLAB_UPLOAD_TOKEN="$(HelixPerfUploadTokenValue)"' - ExtraMSBuildLogsWindows: 'set MSBUILDDEBUGCOMM=1;set "MSBUILDDEBUGPATH=%HELIX_WORKITEM_UPLOAD_ROOT%"' - ExtraMSBuildLogsLinux: 'export MSBUILDDEBUGCOMM=1;export "MSBUILDDEBUGPATH=$HELIX_WORKITEM_UPLOAD_ROOT"' - HelixPreCommand: '' diff --git a/eng/pipelines/mono/templates/workloads-build.yml b/eng/pipelines/mono/templates/workloads-build.yml index 28fb20114c89a3..19a56febb53ab4 100644 --- a/eng/pipelines/mono/templates/workloads-build.yml +++ b/eng/pipelines/mono/templates/workloads-build.yml @@ -56,6 +56,8 @@ jobs: IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.AOT.win-x64.Cross.browser-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.perftrace.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 diff --git a/eng/restore/optimizationData.targets b/eng/restore/optimizationData.targets index 2072c6a28d2f06..9d8717803f1946 100644 --- a/eng/restore/optimizationData.targets +++ b/eng/restore/optimizationData.targets @@ -3,7 +3,9 @@ + + diff --git a/eng/testing/performance/microbenchmarks.proj b/eng/testing/performance/microbenchmarks.proj index 1331e1e7a811c0..3793751775f92d 100644 --- a/eng/testing/performance/microbenchmarks.proj +++ b/eng/testing/performance/microbenchmarks.proj @@ -132,10 +132,10 @@ $(WorkItemDirectory) $(WorkItemCommand) --bdn-artifacts $(BaselineArtifactsDirectory) --bdn-arguments="--anyCategories $(BDNCategories) $(ExtraBenchmarkDotNetArguments) $(BaselineCoreRunArgument) --partition-count $(PartitionCount) --partition-index %(HelixWorkItem.Index)" - if [ "x$PERF_PREREQS_INSTALLED" = "x1" ]; then - $(WorkItemCommand) --bdn-artifacts $(ArtifactsDirectory) --bdn-arguments="--anyCategories $(BDNCategories) $(ExtraBenchmarkDotNetArguments) $(CoreRunArgument) --partition-count $(PartitionCount) --partition-index %(HelixWorkItem.Index)"; + if [ "x$PERF_PREREQS_INSTALL_FAILED" = "x1" ]; then + echo "\n\n** Error: Failed to install prerequisites **\n\n"; (exit 1); else - echo "\n\n** Error: Failed to install prerequisites **\n\n"; export _commandExitCode=1; + $(WorkItemCommand) --bdn-artifacts $(ArtifactsDirectory) --bdn-arguments="--anyCategories $(BDNCategories) $(ExtraBenchmarkDotNetArguments) $(CoreRunArgument) --partition-count $(PartitionCount) --partition-index %(HelixWorkItem.Index)"; fi $(WorkItemCommand) --bdn-artifacts $(ArtifactsDirectory) --bdn-arguments="--anyCategories $(BDNCategories) $(ExtraBenchmarkDotNetArguments) $(CoreRunArgument) --partition-count $(PartitionCount) --partition-index %(HelixWorkItem.Index)" $(DotnetExe) run -f $(PERFLAB_Framework) -p $(ResultsComparer) --base $(BaselineArtifactsDirectory) --diff $(ArtifactsDirectory) --threshold 2$(Percent) --xml $(XMLResults);$(FinalCommand) @@ -148,10 +148,10 @@ $(WorkItemDirectory) $(WorkItemCommand) --bdn-artifacts $(BaselineArtifactsDirectory) --bdn-arguments="--anyCategories $(BDNCategories) $(ExtraBenchmarkDotNetArguments) $(BaselineCoreRunArgument)" - if [ "x$PERF_PREREQS_INSTALLED" = "x1" ]; then - $(WorkItemCommand) --bdn-artifacts $(ArtifactsDirectory) --bdn-arguments="--anyCategories $(BDNCategories) $(ExtraBenchmarkDotNetArguments) $(CoreRunArgument)"; + if [ "x$PERF_PREREQS_INSTALL_FAILED" = "x1" ]; then + echo "\n\n** Error: Failed to install prerequisites **\n\n"; (exit 1); else - echo "\n\n** Error: Failed to install prerequisites **\n\n"; export _commandExitCode=1; + $(WorkItemCommand) --bdn-artifacts $(ArtifactsDirectory) --bdn-arguments="--anyCategories $(BDNCategories) $(ExtraBenchmarkDotNetArguments) $(CoreRunArgument)"; fi $(WorkItemCommand) --bdn-artifacts $(ArtifactsDirectory) --bdn-arguments="--anyCategories $(BDNCategories) $(ExtraBenchmarkDotNetArguments) $(CoreRunArgument)" $(DotnetExe) run -f $(PERFLAB_Framework) -p $(ResultsComparer) --base $(BaselineArtifactsDirectory) --diff $(ArtifactsDirectory) --threshold 2$(Percent) --xml $(XMLResults) diff --git a/eng/testing/tests.singlefile.targets b/eng/testing/tests.singlefile.targets index 86a8b98d545f84..d307e837e6235a 100644 --- a/eng/testing/tests.singlefile.targets +++ b/eng/testing/tests.singlefile.targets @@ -26,48 +26,13 @@ $(CoreCLRILCompilerDir)netstandard/ILCompiler.Build.Tasks.dll $(CoreCLRAotSdkDir) $(NetCoreAppCurrentTestHostSharedFrameworkPath) - $(NoWarn);IL3050;IL3051;IL3052;IL3054;IL3055;IL1005;IL3002 + $(NoWarn);IL1005;IL3002 partial - false true + true true - - - - $(NoWarn);IL2026;IL2116 - - $(NoWarn);IL2041;IL2042;IL2043;IL2056 - - $(NoWarn);IL2045 - - $(NoWarn);IL2046 - - $(NoWarn);IL2050 - - $(NoWarn);IL2032;IL2055;IL2057;IL2058;IL2059;IL2060;IL2061;IL2096 - - $(NoWarn);IL2062;IL2063;IL2064;IL2065;IL2066 - - $(NoWarn);IL2067;IL2068;IL2069;IL2070;IL2071;IL2072;IL2073;IL2074;IL2075;IL2076;IL2077;IL2078;IL2079;IL2080;IL2081;IL2082;IL2083;IL2084;IL2085;IL2086;IL2087;IL2088;IL2089;IL2090;IL2091 - - $(NoWarn);IL2092;IL2093;IL2094;IL2095 - - $(NoWarn);IL2097;IL2098;IL2099;IL2106 - - $(NoWarn);IL2103 - - $(NoWarn);IL2107;IL2117 - - $(NoWarn);IL2109 - - $(NoWarn);IL2110;IL2111;IL2114;IL2115 - - $(NoWarn);IL2112;IL2113 - - $(NoWarn);IL2118;IL2119;IL2120 - diff --git a/global.json b/global.json index 9f0baa92e79cf3..555895afe031e4 100644 --- a/global.json +++ b/global.json @@ -8,9 +8,9 @@ "dotnet": "7.0.100-preview.7.22377.5" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.22411.2", - "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.22411.2", - "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.22411.2", + "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.22418.4", + "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.22418.4", + "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.22418.4", "Microsoft.Build.NoTargets": "3.5.0", "Microsoft.Build.Traversal": "3.1.6", "Microsoft.NET.Sdk.IL": "7.0.0-rc.1.22414.6" diff --git a/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs b/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs index 595f5482fca5b9..bc731b674d2e97 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs @@ -176,7 +176,7 @@ internal static unsafe void ConvertFixedToNative(int flags, string strManaged, I internal static unsafe string ConvertFixedToManaged(IntPtr cstr, int length) { - int end = SpanHelpers.IndexOf(ref *(byte*)cstr, 0, length); + int end = new ReadOnlySpan((byte*)cstr, length).IndexOf((byte)0); if (end >= 0) { length = end; @@ -450,7 +450,7 @@ internal static unsafe void ConvertToNative(string? strManaged, IntPtr nativeHom internal static unsafe string ConvertToManaged(IntPtr nativeHome, int length) { - int end = SpanHelpers.IndexOf(ref *(char*)nativeHome, '\0', length); + int end = new ReadOnlySpan((char*)nativeHome, length).IndexOf('\0'); if (end >= 0) { length = end; diff --git a/src/coreclr/dlls/mscorrc/mscorrc.rc b/src/coreclr/dlls/mscorrc/mscorrc.rc index 892c1f1c27bfcb..e91bb09807bbdb 100644 --- a/src/coreclr/dlls/mscorrc/mscorrc.rc +++ b/src/coreclr/dlls/mscorrc/mscorrc.rc @@ -271,6 +271,7 @@ BEGIN IDS_EE_BADMARSHAL_ABSTRACTRETCRITICALHANDLE "Returned CriticalHandles cannot be abstract." IDS_EE_BADMARSHAL_CUSTOMMARSHALER "Custom marshalers are only allowed on classes, strings, arrays, and boxed value types." IDS_EE_BADMARSHAL_GENERICS_RESTRICTION "Non-blittable generic types cannot be marshaled." + IDS_EE_BADMARSHAL_INT128_RESTRICTION "System.Int128 and System.UInt128 cannot be passed by value to unmanaged." IDS_EE_BADMARSHAL_AUTOLAYOUT "Structures marked with [StructLayout(LayoutKind.Auto)] cannot be marshaled." IDS_EE_BADMARSHAL_STRING_OUT "Cannot marshal a string by-value with the [Out] attribute." IDS_EE_BADMARSHAL_MARSHAL_DISABLED "Cannot marshal managed types when the runtime marshalling system is disabled." diff --git a/src/coreclr/dlls/mscorrc/resource.h b/src/coreclr/dlls/mscorrc/resource.h index d2177bd56db2fd..3245329339c91f 100644 --- a/src/coreclr/dlls/mscorrc/resource.h +++ b/src/coreclr/dlls/mscorrc/resource.h @@ -283,6 +283,7 @@ #define IDS_EE_BADMARSHAL_ABSTRACTOUTCRITICALHANDLE 0x1a63 #define IDS_EE_BADMARSHAL_RETURNCHCOMTONATIVE 0x1a64 #define IDS_EE_BADMARSHAL_CRITICALHANDLE 0x1a65 +#define IDS_EE_BADMARSHAL_INT128_RESTRICTION 0x1a66 #define IDS_EE_BADMARSHAL_ABSTRACTRETCRITICALHANDLE 0x1a6a #define IDS_EE_CH_IN_VARIANT_NOT_SUPPORTED 0x1a6b diff --git a/src/coreclr/inc/readytorun.h b/src/coreclr/inc/readytorun.h index 0934f2ea627481..20a1462125534c 100644 --- a/src/coreclr/inc/readytorun.h +++ b/src/coreclr/inc/readytorun.h @@ -15,10 +15,10 @@ #define READYTORUN_SIGNATURE 0x00525452 // 'RTR' // Keep these in sync with src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs -#define READYTORUN_MAJOR_VERSION 0x0007 -#define READYTORUN_MINOR_VERSION 0x0001 +#define READYTORUN_MAJOR_VERSION 0x0008 +#define READYTORUN_MINOR_VERSION 0x0000 -#define MINIMUM_READYTORUN_MAJOR_VERSION 0x006 +#define MINIMUM_READYTORUN_MAJOR_VERSION 0x008 // R2R Version 2.1 adds the InliningInfo section // R2R Version 2.2 adds the ProfileDataInfo section @@ -26,6 +26,7 @@ // R2R 3.0 is not backward compatible with 2.x. // R2R Version 6.0 changes managed layout for sequential types with any unmanaged non-blittable fields. // R2R 6.0 is not backward compatible with 5.x or earlier. +// R2R Version 8.0 Changes the alignment of the Int128 type struct READYTORUN_CORE_HEADER { diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.DotNet.ILCompiler.props b/src/coreclr/nativeaot/BuildIntegration/Microsoft.DotNet.ILCompiler.props index da6b72b12d7ce1..e0cc69015b8e16 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.DotNet.ILCompiler.props +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.DotNet.ILCompiler.props @@ -11,8 +11,8 @@ Copyright (c) .NET Foundation. All rights reserved. --> - - true + + true $(MSBuildThisFileDirectory)Microsoft.DotNet.ILCompiler.SingleEntry.targets diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets index 690ef724af07e1..417d4567a95189 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets @@ -49,6 +49,10 @@ The .NET Foundation licenses this file to you under the MIT license. false + + false + + .obj .o @@ -241,6 +245,8 @@ The .NET Foundation licenses this file to you under the MIT license. + + diff --git a/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h b/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h index 176aef2ad1033b..6f77813cd06143 100644 --- a/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h +++ b/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h @@ -10,8 +10,8 @@ struct ReadyToRunHeaderConstants { static const uint32_t Signature = 0x00525452; // 'RTR' - static const uint32_t CurrentMajorVersion = 7; - static const uint32_t CurrentMinorVersion = 1; + static const uint32_t CurrentMajorVersion = 8; + static const uint32_t CurrentMinorVersion = 0; }; struct ReadyToRunHeader diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs index 4e8bfcd492dde1..8e383b44d85033 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs @@ -55,8 +55,8 @@ internal static unsafe void StringToByValAnsiString(string str, byte* pNative, i public static unsafe string ByValAnsiStringToString(byte* buffer, int length) { - int end = SpanHelpers.IndexOf(ref *(byte*)buffer, 0, length); - if (end != -1) + int end = new ReadOnlySpan(buffer, length).IndexOf((byte)0); + if (end >= 0) { length = end; } @@ -77,8 +77,8 @@ internal static unsafe void StringToUnicodeFixedArray(string str, ushort* buffer internal static unsafe string UnicodeToStringFixedArray(ushort* buffer, int length) { - int end = SpanHelpers.IndexOf(ref *(char*)buffer, '\0', length); - if (end != -1) + int end = new ReadOnlySpan(buffer, length).IndexOf('\0'); + if (end >= 0) { length = end; } diff --git a/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/Internal/StackTraceMetadata/MethodNameFormatter.cs b/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/Internal/StackTraceMetadata/MethodNameFormatter.cs index ebfbab7a8e2c02..41226385ea86ac 100644 --- a/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/Internal/StackTraceMetadata/MethodNameFormatter.cs +++ b/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/Internal/StackTraceMetadata/MethodNameFormatter.cs @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections.Generic; using System.Diagnostics; using System.Text; @@ -49,7 +47,6 @@ public static string FormatMethodName(MetadataReader metadataReader, TypeDefinit MethodNameFormatter formatter = new MethodNameFormatter(metadataReader, SigTypeContext.FromMethod(metadataReader, enclosingTypeHandle, methodHandle)); Method method = metadataReader.GetMethod(methodHandle); - MethodSignature methodSignature = metadataReader.GetMethodSignature(method.Signature); formatter.EmitTypeName(enclosingTypeHandle, namespaceQualified: true); formatter._outputBuilder.Append('.'); formatter.EmitString(method.Name); @@ -64,7 +61,7 @@ public static string FormatMethodName(MetadataReader metadataReader, TypeDefinit } else { - formatter._outputBuilder.Append(", "); + formatter._outputBuilder.Append(','); } formatter.EmitTypeName(handle, namespaceQualified: false); } @@ -73,7 +70,7 @@ public static string FormatMethodName(MetadataReader metadataReader, TypeDefinit formatter._outputBuilder.Append(']'); } - formatter.EmitMethodParameters(methodSignature); + formatter.EmitMethodParameters(methodHandle); return formatter._outputBuilder.ToString(); } @@ -124,28 +121,30 @@ private void EmitMethodReferenceName(MemberReferenceHandle memberRefHandle) private void EmitMethodInstantiationName(MethodInstantiationHandle methodInstHandle) { MethodInstantiation methodInst = _metadataReader.GetMethodInstantiation(methodInstHandle); - MethodSignature methodSignature; + if (methodInst.Method.HandleType == HandleType.MemberReference) { MemberReferenceHandle methodRefHandle = methodInst.Method.ToMemberReferenceHandle(_metadataReader); MemberReference methodRef = methodRefHandle.GetMemberReference(_metadataReader); - EmitContainingTypeAndMethodName(methodRef, out methodSignature); + EmitContainingTypeAndMethodName(methodRef, out MethodSignature methodSignature); + EmitGenericArguments(methodInst.GenericTypeArguments); + EmitMethodParameters(methodSignature); } else { QualifiedMethodHandle qualifiedMethodHandle = methodInst.Method.ToQualifiedMethodHandle(_metadataReader); QualifiedMethod qualifiedMethod = _metadataReader.GetQualifiedMethod(qualifiedMethodHandle); - EmitContainingTypeAndMethodName(qualifiedMethod, out methodSignature); + EmitContainingTypeAndMethodName(qualifiedMethod); + EmitGenericArguments(methodInst.GenericTypeArguments); + EmitMethodParameters(qualifiedMethod.Method); } - EmitGenericArguments(methodInst.GenericTypeArguments); - EmitMethodParameters(methodSignature); } private void EmitMethodDefinitionName(QualifiedMethodHandle qualifiedMethodHandle) { QualifiedMethod qualifiedMethod = _metadataReader.GetQualifiedMethod(qualifiedMethodHandle); - EmitContainingTypeAndMethodName(qualifiedMethod, out MethodSignature methodSignature); - EmitMethodParameters(methodSignature); + EmitContainingTypeAndMethodName(qualifiedMethod); + EmitMethodParameters(qualifiedMethod.Method); } /// @@ -161,10 +160,9 @@ private void EmitContainingTypeAndMethodName(MemberReference methodRef, out Meth EmitString(methodRef.Name); } - private void EmitContainingTypeAndMethodName(QualifiedMethod qualifiedMethod, out MethodSignature methodSignature) + private void EmitContainingTypeAndMethodName(QualifiedMethod qualifiedMethod) { Method method = _metadataReader.GetMethod(qualifiedMethod.Method); - methodSignature = _metadataReader.GetMethodSignature(method.Signature); EmitTypeName(qualifiedMethod.EnclosingType, namespaceQualified: true); _outputBuilder.Append('.'); EmitString(method.Name); @@ -181,6 +179,57 @@ private void EmitMethodParameters(MethodSignature methodSignature) _outputBuilder.Append(')'); } + /// + /// Emit parenthesized method argument type list with parameter names. + /// + /// Method handle to use for parameter formatting + private void EmitMethodParameters(MethodHandle methodHandle) + { + bool TryGetNextParameter(ref ParameterHandleCollection.Enumerator enumerator, out Parameter parameter) + { + bool hasNext = enumerator.MoveNext(); + parameter = hasNext ? enumerator.Current.GetParameter(_metadataReader) : default; + return hasNext; + } + + Method method = methodHandle.GetMethod(_metadataReader); + HandleCollection typeVector = method.Signature.GetMethodSignature(_metadataReader).Parameters; + ParameterHandleCollection.Enumerator parameters = method.Parameters.GetEnumerator(); + + bool hasParameter = TryGetNextParameter(ref parameters, out Parameter parameter); + if (hasParameter && parameter.Sequence == 0) + { + hasParameter = TryGetNextParameter(ref parameters, out parameter); + } + + _outputBuilder.Append('('); + + uint typeIndex = 0; + foreach (Handle type in typeVector) + { + if (typeIndex != 0) + { + _outputBuilder.Append(", "); + } + + EmitTypeName(type, namespaceQualified: false); + + if (++typeIndex == parameter.Sequence && hasParameter) + { + string name = parameter.Name.GetConstantStringValue(_metadataReader).Value; + hasParameter = TryGetNextParameter(ref parameters, out parameter); + + if (!string.IsNullOrEmpty(name)) + { + _outputBuilder.Append(' '); + _outputBuilder.Append(name); + } + } + } + + _outputBuilder.Append(')'); + } + /// /// Emit comma-separated list of type names into the output string builder. /// diff --git a/src/coreclr/tools/Common/Compiler/Int128FieldLayoutAlgorithm.cs b/src/coreclr/tools/Common/Compiler/Int128FieldLayoutAlgorithm.cs index 60be29fdce95c9..18f794a6f354e8 100644 --- a/src/coreclr/tools/Common/Compiler/Int128FieldLayoutAlgorithm.cs +++ b/src/coreclr/tools/Common/Compiler/Int128FieldLayoutAlgorithm.cs @@ -28,8 +28,11 @@ public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType defTyp ComputedInstanceFieldLayout layoutFromMetadata = _fallbackAlgorithm.ComputeInstanceLayout(defType, layoutKind); - if (defType.Context.Target.IsWindows || (defType.Context.Target.PointerSize == 4)) + // 32bit platforms use standard metadata layout engine + if (defType.Context.Target.Architecture == TargetArchitecture.ARM) { + layoutFromMetadata.LayoutAbiStable = false; // Int128 parameter passing ABI is unstable at this time + layoutFromMetadata.IsInt128OrHasInt128Fields = true; return layoutFromMetadata; } @@ -42,7 +45,8 @@ public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType defTyp FieldAlignment = new LayoutInt(16), FieldSize = layoutFromMetadata.FieldSize, Offsets = layoutFromMetadata.Offsets, - LayoutAbiStable = true + LayoutAbiStable = false, // Int128 parameter passing ABI is unstable at this time + IsInt128OrHasInt128Fields = true }; } @@ -72,7 +76,7 @@ public override ValueTypeShapeCharacteristics ComputeValueTypeShapeCharacteristi public static bool IsIntegerType(DefType type) { return type.IsIntrinsic - && type.Namespace == "System." + && type.Namespace == "System" && ((type.Name == "Int128") || (type.Name == "UInt128")); } } diff --git a/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs b/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs index c5fdfda3d0f58f..cc286f81b03619 100644 --- a/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs +++ b/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs @@ -14,8 +14,8 @@ internal struct ReadyToRunHeaderConstants { public const uint Signature = 0x00525452; // 'RTR' - public const ushort CurrentMajorVersion = 7; - public const ushort CurrentMinorVersion = 1; + public const ushort CurrentMajorVersion = 8; + public const ushort CurrentMinorVersion = 0; } #pragma warning disable 0169 diff --git a/src/coreclr/tools/Common/TypeSystem/Common/DefType.FieldLayout.cs b/src/coreclr/tools/Common/TypeSystem/Common/DefType.FieldLayout.cs index 2190f9ac1a2785..4c3555c198af66 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/DefType.FieldLayout.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/DefType.FieldLayout.cs @@ -68,6 +68,11 @@ private static class FieldLayoutFlags /// True if the type transitively has any types with LayoutKind.Auto in its layout. /// public const int IsAutoLayoutOrHasAutoLayoutFields = 0x400; + + /// + /// True if the type transitively has an Int128 in it or is an Int128 + /// + public const int IsInt128OrHasInt128Fields = 0x800; } private class StaticBlockInfo @@ -135,6 +140,20 @@ public virtual bool IsAutoLayoutOrHasAutoLayoutFields } } + /// + /// Is a type Int128 or transitively have any fields of a type Int128. + /// + public virtual bool IsInt128OrHasInt128Fields + { + get + { + if (!_fieldLayoutFlags.HasFlags(FieldLayoutFlags.ComputedInstanceTypeLayout)) + { + ComputeInstanceLayout(InstanceLayoutKind.TypeAndFields); + } + return _fieldLayoutFlags.HasFlags(FieldLayoutFlags.IsInt128OrHasInt128Fields); + } + } /// /// The number of bytes required to hold a field of this type @@ -430,6 +449,10 @@ public void ComputeInstanceLayout(InstanceLayoutKind layoutKind) { _fieldLayoutFlags.AddFlags(FieldLayoutFlags.IsAutoLayoutOrHasAutoLayoutFields); } + if (computedLayout.IsInt128OrHasInt128Fields) + { + _fieldLayoutFlags.AddFlags(FieldLayoutFlags.IsInt128OrHasInt128Fields); + } if (computedLayout.Offsets != null) { diff --git a/src/coreclr/tools/Common/TypeSystem/Common/FieldLayoutAlgorithm.cs b/src/coreclr/tools/Common/TypeSystem/Common/FieldLayoutAlgorithm.cs index a19ec4b3603bf4..53388c915b85d8 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/FieldLayoutAlgorithm.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/FieldLayoutAlgorithm.cs @@ -83,6 +83,7 @@ public struct ComputedInstanceFieldLayout public LayoutInt ByteCountAlignment; public bool LayoutAbiStable; // Is the layout stable such that it can safely be used in function calling conventions public bool IsAutoLayoutOrHasAutoLayoutFields; + public bool IsInt128OrHasInt128Fields; /// /// If Offsets is non-null, then all field based layout is complete. diff --git a/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs b/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs index 8da028a5190fb5..9d291d8c372d69 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs @@ -110,6 +110,7 @@ out instanceByteSizeAndAlignment FieldSize = sizeAndAlignment.Size, LayoutAbiStable = true, IsAutoLayoutOrHasAutoLayoutFields = false, + IsInt128OrHasInt128Fields = false, }; if (numInstanceFields > 0) @@ -211,7 +212,7 @@ public override ComputedStaticFieldLayout ComputeStaticFieldLayout(DefType defTy } ref StaticsBlock block = ref GetStaticsBlockForField(ref result, field); - SizeAndAlignment sizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout: false, context.Target.DefaultPackingSize, out bool _, out bool _); + SizeAndAlignment sizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout: false, context.Target.DefaultPackingSize, out bool _, out bool _, out bool _); block.Size = LayoutInt.AlignUp(block.Size, sizeAndAlignment.Alignment, context.Target); result.Offsets[index] = new FieldAndOffset(field, block.Size); @@ -303,15 +304,18 @@ protected ComputedInstanceFieldLayout ComputeExplicitFieldLayout(MetadataType ty int fieldOrdinal = 0; bool layoutAbiStable = true; bool hasAutoLayoutField = false; + bool hasInt128Field = type.BaseType == null ? false : type.BaseType.IsInt128OrHasInt128Fields; foreach (var fieldAndOffset in layoutMetadata.Offsets) { TypeDesc fieldType = fieldAndOffset.Field.FieldType; - var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType.UnderlyingType, hasLayout: true, packingSize, out bool fieldLayoutAbiStable, out bool fieldHasAutoLayout); + var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType.UnderlyingType, hasLayout: true, packingSize, out bool fieldLayoutAbiStable, out bool fieldHasAutoLayout, out bool fieldHasInt128Field); if (!fieldLayoutAbiStable) layoutAbiStable = false; if (fieldHasAutoLayout) hasAutoLayoutField = true; + if (fieldHasInt128Field) + hasInt128Field = true; largestAlignmentRequired = LayoutInt.Max(fieldSizeAndAlignment.Alignment, largestAlignmentRequired); @@ -357,6 +361,7 @@ protected ComputedInstanceFieldLayout ComputeExplicitFieldLayout(MetadataType ty ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout { IsAutoLayoutOrHasAutoLayoutFields = hasAutoLayoutField, + IsInt128OrHasInt128Fields = hasInt128Field, }; computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment; computedLayout.FieldSize = instanceSizeAndAlignment.Size; @@ -392,17 +397,20 @@ protected ComputedInstanceFieldLayout ComputeSequentialFieldLayout(MetadataType int packingSize = ComputePackingSize(type, layoutMetadata); bool layoutAbiStable = true; bool hasAutoLayoutField = false; + bool hasInt128Field = type.BaseType == null ? false : type.BaseType.IsInt128OrHasInt128Fields; foreach (var field in type.GetFields()) { if (field.IsStatic) continue; - var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType.UnderlyingType, hasLayout: true, packingSize, out bool fieldLayoutAbiStable, out bool fieldHasAutoLayout); + var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType.UnderlyingType, hasLayout: true, packingSize, out bool fieldLayoutAbiStable, out bool fieldHasAutoLayout, out bool fieldHasInt128Field); if (!fieldLayoutAbiStable) layoutAbiStable = false; if (fieldHasAutoLayout) hasAutoLayoutField = true; + if (fieldHasInt128Field) + hasInt128Field = true; largestAlignmentRequirement = LayoutInt.Max(fieldSizeAndAlignment.Alignment, largestAlignmentRequirement); @@ -424,6 +432,7 @@ protected ComputedInstanceFieldLayout ComputeSequentialFieldLayout(MetadataType ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout { IsAutoLayoutOrHasAutoLayoutFields = hasAutoLayoutField, + IsInt128OrHasInt128Fields = hasInt128Field, }; computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment; computedLayout.FieldSize = instanceSizeAndAlignment.Size; @@ -459,6 +468,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, int instanceValueClassFieldCount = 0; int instanceGCPointerFieldsCount = 0; int[] instanceNonGCPointerFieldsCount = new int[maxLog2Size + 1]; + bool hasInt128Field = false; foreach (var field in type.GetFields()) { @@ -469,7 +479,10 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, if (IsByValueClass(fieldType)) { + // Valuetypes which are not primitives or enums instanceValueClassFieldCount++; + if (((DefType)fieldType).IsInt128OrHasInt128Fields) + hasInt128Field = true; } else if (fieldType.IsGCPointer) { @@ -479,7 +492,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, { Debug.Assert(fieldType.IsPrimitive || fieldType.IsPointer || fieldType.IsFunctionPointer || fieldType.IsEnum || fieldType.IsByRef); - var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout, packingSize, out bool _, out bool _); + var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout, packingSize, out bool _, out bool _, out bool _); instanceNonGCPointerFieldsCount[CalculateLog2(fieldSizeAndAlignment.Size.AsInt)]++; } } @@ -516,29 +529,51 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, TypeDesc fieldType = field.FieldType; - var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout, packingSize, out bool fieldLayoutAbiStable, out bool _); + var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout, packingSize, out bool fieldLayoutAbiStable, out bool _, out bool _); if (!fieldLayoutAbiStable) layoutAbiStable = false; - largestAlignmentRequired = LayoutInt.Max(fieldSizeAndAlignment.Alignment, largestAlignmentRequired); - if (IsByValueClass(fieldType)) { + // This block handles valuetypes which are not primitives or enums, it only has a meaningful effect, if the + // type has an alignment greater than pointer size. + largestAlignmentRequired = LayoutInt.Max(fieldSizeAndAlignment.Alignment, largestAlignmentRequired); instanceValueClassFieldsArr[instanceValueClassFieldCount++] = field; } - else if (fieldType.IsGCPointer) - { - instanceGCPointerFieldsArr[instanceGCPointerFieldsCount++] = field; - } else { - int log2size = CalculateLog2(fieldSizeAndAlignment.Size.AsInt); - instanceNonGCPointerFieldsArr[log2size][instanceNonGCPointerFieldsCount[log2size]++] = field; + // non-value-type (and primitive type) fields will add an alignment requirement of pointer size + // This alignment requirement will not be significant in the final alignment calculation unlesss the + // type is greater than the size of a single pointer. + // + // This does not account for types that are marked IsAlign8Candidate due to 8-byte fields + // but that is explicitly handled when we calculate the final alignment for the type. + + // This behavior is extremely strange for primitive types, as it makes a struct with a single byte in it + // have 8 byte alignment, but that is the current implementation. + + largestAlignmentRequired = LayoutInt.Max(new LayoutInt(context.Target.PointerSize), largestAlignmentRequired); + + if (fieldType.IsGCPointer) + { + instanceGCPointerFieldsArr[instanceGCPointerFieldsCount++] = field; + } + else + { + Debug.Assert(fieldType.IsPrimitive || fieldType.IsPointer || fieldType.IsFunctionPointer || fieldType.IsEnum || fieldType.IsByRef); + int log2size = CalculateLog2(fieldSizeAndAlignment.Size.AsInt); + instanceNonGCPointerFieldsArr[log2size][instanceNonGCPointerFieldsCount[log2size]++] = field; + + if (fieldType.IsPrimitive || fieldType.IsEnum) + { + // Handle alignment of long/ulong/double on ARM32 + largestAlignmentRequired = LayoutInt.Max(context.Target.GetObjectAlignment(fieldSizeAndAlignment.Size), largestAlignmentRequired); + } + } } } - largestAlignmentRequired = context.Target.GetObjectAlignment(largestAlignmentRequired); - bool requiresAlign8 = !largestAlignmentRequired.IsIndeterminate && largestAlignmentRequired.AsInt > 4; + bool requiresAlign8 = !largestAlignmentRequired.IsIndeterminate && context.Target.PointerSize == 4 && context.Target.GetObjectAlignment(largestAlignmentRequired).AsInt > 4 && context.Target.PointerSize == 4; // For types inheriting from another type, field offsets continue on from where they left off // Base alignment is not always required, it's only applied when there's a version bubble boundary @@ -655,7 +690,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, for (int i = 0; i < instanceValueClassFieldsArr.Length; i++) { // Align the cumulative field offset to the indeterminate value - var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(instanceValueClassFieldsArr[i].FieldType, hasLayout, packingSize, out bool fieldLayoutAbiStable, out bool _); + var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(instanceValueClassFieldsArr[i].FieldType, hasLayout, packingSize, out bool fieldLayoutAbiStable, out bool _, out bool _); if (!fieldLayoutAbiStable) layoutAbiStable = false; @@ -706,6 +741,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout { IsAutoLayoutOrHasAutoLayoutFields = true, + IsInt128OrHasInt128Fields = hasInt128Field, }; computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment; computedLayout.FieldSize = instanceSizeAndAlignment.Size; @@ -719,7 +755,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, private static void PlaceInstanceField(FieldDesc field, bool hasLayout, int packingSize, FieldAndOffset[] offsets, ref LayoutInt instanceFieldPos, ref int fieldOrdinal, LayoutInt offsetBias) { - var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType, hasLayout, packingSize, out bool _, out bool _); + var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType, hasLayout, packingSize, out bool _, out bool _, out bool _); instanceFieldPos = AlignUpInstanceFieldOffset(field.OwningType, instanceFieldPos, fieldSizeAndAlignment.Alignment, field.Context.Target); offsets[fieldOrdinal] = new FieldAndOffset(field, instanceFieldPos + offsetBias); @@ -779,11 +815,12 @@ public LayoutInt CalculateFieldBaseOffset(MetadataType type, bool requiresAlign8 return cumulativeInstanceFieldPos; } - private static SizeAndAlignment ComputeFieldSizeAndAlignment(TypeDesc fieldType, bool hasLayout, int packingSize, out bool layoutAbiStable, out bool fieldTypeHasAutoLayout) + private static SizeAndAlignment ComputeFieldSizeAndAlignment(TypeDesc fieldType, bool hasLayout, int packingSize, out bool layoutAbiStable, out bool fieldTypeHasAutoLayout, out bool fieldTypeHasInt128Field) { SizeAndAlignment result; layoutAbiStable = true; fieldTypeHasAutoLayout = true; + fieldTypeHasInt128Field = false; if (fieldType.IsDefType) { @@ -794,6 +831,7 @@ private static SizeAndAlignment ComputeFieldSizeAndAlignment(TypeDesc fieldType, result.Alignment = defType.InstanceFieldAlignment; layoutAbiStable = defType.LayoutAbiStable; fieldTypeHasAutoLayout = defType.IsAutoLayoutOrHasAutoLayoutFields; + fieldTypeHasInt128Field = defType.IsInt128OrHasInt128Fields; } else { diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs index 658302d0faaf42..b70749272b0d38 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs @@ -434,6 +434,12 @@ internal static MarshallerKind GetMarshallerKind( return MarshallerKind.Invalid; } + if (!isField && InteropTypes.IsInt128Type(context, type)) + { + // Int128 types cannot be passed by value + return MarshallerKind.Invalid; + } + if (isBlittable) { if (nativeType != NativeTypeKind.Default && nativeType != NativeTypeKind.Struct) @@ -887,7 +893,7 @@ internal static MarshallerKind GetDisabledMarshallerKind( else if (underlyingType.IsValueType) { var defType = (DefType)underlyingType; - if (!defType.ContainsGCPointers && !defType.IsAutoLayoutOrHasAutoLayoutFields) + if (!defType.ContainsGCPointers && !defType.IsAutoLayoutOrHasAutoLayoutFields && !defType.IsInt128OrHasInt128Fields) { return MarshallerKind.BlittableValue; } diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/InteropTypes.cs b/src/coreclr/tools/Common/TypeSystem/Interop/InteropTypes.cs index f69879a10ee15f..e6a684ba82e10f 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/InteropTypes.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/InteropTypes.cs @@ -137,6 +137,11 @@ public static bool IsSystemRuntimeIntrinsicsVector64T(TypeSystemContext context, return IsCoreNamedType(context, type, "System.Runtime.Intrinsics", "Vector64`1"); } + public static bool IsInt128Type(TypeSystemContext context, TypeDesc type) + { + return IsCoreNamedType(context, type, "System", "Int128") || IsCoreNamedType(context, type, "System", "UInt128"); + } + public static bool IsSystemRuntimeIntrinsicsVector128T(TypeSystemContext context, TypeDesc type) { return IsCoreNamedType(context, type, "System.Runtime.Intrinsics", "Vector128`1"); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/CompilerGeneratedNames.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/CompilerGeneratedNames.cs index c41d5fa11d7a31..90584110173b88 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/CompilerGeneratedNames.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/CompilerGeneratedNames.cs @@ -36,6 +36,19 @@ internal static bool IsStateMachineType(string typeName) return typeName.Length > i + 1 && typeName[i + 1] == 'd'; } + internal static bool IsStateMachineCurrentField(string fieldName) + { + if (!IsGeneratedMemberName(fieldName)) + return false; + + int i = fieldName.LastIndexOf('>'); + if (i == -1) + return false; + + // Current field is <>2__current + return fieldName.Length > i + 1 && fieldName[i + 1] == '2'; + } + internal static bool IsGeneratedType(string name) => IsStateMachineType(name) || IsLambdaDisplayClass(name); internal static bool IsLambdaOrLocalFunction(string methodName) => IsLambdaMethod(methodName) || IsLocalFunction(methodName); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/CompilerGeneratedState.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/CompilerGeneratedState.cs index 6b6c6e36cd6674..c62233bd957a9c 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/CompilerGeneratedState.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/CompilerGeneratedState.cs @@ -500,10 +500,17 @@ static IEnumerable GetCompilerGeneratedNestedTypes(MetadataType ty public static bool IsHoistedLocal(FieldDesc field) { - // Treat all fields on compiler-generated types as hoisted locals. - // This avoids depending on the name mangling scheme for hoisted locals. - var declaringTypeName = field.OwningType.Name; - return CompilerGeneratedNames.IsLambdaDisplayClass(declaringTypeName) || CompilerGeneratedNames.IsStateMachineType(declaringTypeName); + if (CompilerGeneratedNames.IsLambdaDisplayClass(field.OwningType.Name)) + return true; + + if (CompilerGeneratedNames.IsStateMachineType(field.OwningType.Name)) + { + // Don't track the "current" field which is used for state machine return values, + // because this can be expensive to track. + return !CompilerGeneratedNames.IsStateMachineCurrentField(field.Name); + } + + return false; } // "Nested function" refers to lambdas and local functions. diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/CompilerGeneratedNames.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/CompilerGeneratedNames.cs index 46e6c9764782a5..afdb716f5af6ae 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/CompilerGeneratedNames.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/CompilerGeneratedNames.cs @@ -34,6 +34,19 @@ internal static bool IsStateMachineType (string typeName) return typeName.Length > i + 1 && typeName[i + 1] == 'd'; } + internal static bool IsStateMachineCurrentField (string fieldName) + { + if (!IsGeneratedMemberName (fieldName)) + return false; + + int i = fieldName.LastIndexOf ('>'); + if (i == -1) + return false; + + // Current field is <>2__current + return fieldName.Length > i + 1 && fieldName[i + 1] == '2'; + } + internal static bool IsGeneratedType (string name) => IsStateMachineType (name) || IsLambdaDisplayClass (name); internal static bool IsLambdaOrLocalFunction (string methodName) => IsLambdaMethod (methodName) || IsLocalFunction (methodName); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/CompilerGeneratedState.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/CompilerGeneratedState.cs index 3213f49fdc4931..3033cef70153c0 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/CompilerGeneratedState.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/CompilerGeneratedState.cs @@ -55,10 +55,16 @@ static IEnumerable GetCompilerGeneratedNestedTypes (TypeDefiniti public static bool IsHoistedLocal (FieldDefinition field) { - // Treat all fields on compiler-generated types as hoisted locals. - // This avoids depending on the name mangling scheme for hoisted locals. - var declaringTypeName = field.DeclaringType.Name; - return CompilerGeneratedNames.IsLambdaDisplayClass (declaringTypeName) || CompilerGeneratedNames.IsStateMachineType (declaringTypeName); + if (CompilerGeneratedNames.IsLambdaDisplayClass (field.DeclaringType.Name)) + return true; + + if (CompilerGeneratedNames.IsStateMachineType (field.DeclaringType.Name)) { + // Don't track the "current" field which is used for state machine return values, + // because this can be expensive to track. + return !CompilerGeneratedNames.IsStateMachineCurrentField (field.Name); + } + + return false; } // "Nested function" refers to lambdas and local functions. diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logger.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logger.cs index 0482731b0432b3..fac33d4b58cbcf 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logger.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logger.cs @@ -26,6 +26,7 @@ public class Logger private readonly CompilerGeneratedState _compilerGeneratedState; private readonly HashSet _suppressedWarnings; + private readonly HashSet _suppressedCategories; private readonly bool _isSingleWarn; private readonly HashSet _singleWarnEnabledAssemblies; @@ -44,7 +45,8 @@ public Logger( IEnumerable suppressedWarnings, bool singleWarn, IEnumerable singleWarnEnabledModules, - IEnumerable singleWarnDisabledModules) + IEnumerable singleWarnDisabledModules, + IEnumerable suppressedCategories) { _logWriter = writer; _compilerGeneratedState = ilProvider == null ? null : new CompilerGeneratedState(ilProvider, this); @@ -53,15 +55,16 @@ public Logger( _isSingleWarn = singleWarn; _singleWarnEnabledAssemblies = new HashSet(singleWarnEnabledModules, StringComparer.OrdinalIgnoreCase); _singleWarnDisabledAssemblies = new HashSet(singleWarnDisabledModules, StringComparer.OrdinalIgnoreCase); + _suppressedCategories = new HashSet(suppressedCategories, StringComparer.Ordinal); } - public Logger(TextWriter writer, ILProvider ilProvider, bool isVerbose, IEnumerable suppressedWarnings, bool singleWarn, IEnumerable singleWarnEnabledModules, IEnumerable singleWarnDisabledModules) - : this(new TextLogWriter(writer), ilProvider, isVerbose, suppressedWarnings, singleWarn, singleWarnEnabledModules, singleWarnDisabledModules) + public Logger(TextWriter writer, ILProvider ilProvider, bool isVerbose, IEnumerable suppressedWarnings, bool singleWarn, IEnumerable singleWarnEnabledModules, IEnumerable singleWarnDisabledModules, IEnumerable suppressedCategories) + : this(new TextLogWriter(writer), ilProvider, isVerbose, suppressedWarnings, singleWarn, singleWarnEnabledModules, singleWarnDisabledModules, suppressedCategories) { } public Logger(ILogWriter writer, ILProvider ilProvider, bool isVerbose) - : this(writer, ilProvider, isVerbose, Array.Empty(), singleWarn: false, Array.Empty(), Array.Empty()) + : this(writer, ilProvider, isVerbose, Array.Empty(), singleWarn: false, Array.Empty(), Array.Empty(), Array.Empty()) { } @@ -141,6 +144,8 @@ public void LogError(string text, int code, TypeSystemEntity origin, string subc public void LogError(TypeSystemEntity origin, DiagnosticId id, params string[] args) => LogError(new MessageOrigin(origin), id, args); + internal bool IsWarningSubcategorySuppressed(string category) => _suppressedCategories.Contains(category); + internal bool IsWarningSuppressed(int code, MessageOrigin origin) { // This is causing too much noise diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logging/MessageContainer.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logging/MessageContainer.cs index 25d849a46dee05..8f6e4f33efd2fd 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logging/MessageContainer.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logging/MessageContainer.cs @@ -125,6 +125,9 @@ internal static MessageContainer CreateErrorMessage(MessageOrigin? origin, Diagn if (context.IsWarningSuppressed(code, origin)) return null; + if (context.IsWarningSubcategorySuppressed(subcategory)) + return null; + if (TryLogSingleWarning(context, code, origin, subcategory)) return null; @@ -139,6 +142,9 @@ internal static MessageContainer CreateErrorMessage(MessageOrigin? origin, Diagn if (context.IsWarningSuppressed((int)id, origin)) return null; + if (context.IsWarningSubcategorySuppressed(subcategory)) + return null; + if (TryLogSingleWarning(context, (int)id, origin, subcategory)) return null; diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ArchitectureSpecificFieldLayoutTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ArchitectureSpecificFieldLayoutTests.cs index 067486f858c168..f9fe3b7687439d 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ArchitectureSpecificFieldLayoutTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ArchitectureSpecificFieldLayoutTests.cs @@ -19,9 +19,16 @@ public class ArchitectureSpecificFieldLayoutTests ModuleDesc _testModuleX86; TestTypeSystemContext _contextX64; ModuleDesc _testModuleX64; + TestTypeSystemContext _contextX64Windows; + ModuleDesc _testModuleX64Windows; + TestTypeSystemContext _contextX64Linux; + ModuleDesc _testModuleX64Linux; TestTypeSystemContext _contextARM; ModuleDesc _testModuleARM; + TestTypeSystemContext _contextARM64; + ModuleDesc _testModuleARM64; + public ArchitectureSpecificFieldLayoutTests() { _contextX64 = new TestTypeSystemContext(TargetArchitecture.X64); @@ -30,6 +37,18 @@ public ArchitectureSpecificFieldLayoutTests() _testModuleX64 = systemModuleX64; + _contextX64Linux = new TestTypeSystemContext(TargetArchitecture.X64, TargetOS.Linux); + var systemModuleX64Linux = _contextX64Linux.CreateModuleForSimpleName("CoreTestAssembly"); + _contextX64Linux.SetSystemModule(systemModuleX64Linux); + + _testModuleX64Linux = systemModuleX64Linux; + + _contextX64Windows = new TestTypeSystemContext(TargetArchitecture.X64, TargetOS.Windows); + var systemModuleX64Windows = _contextX64Windows.CreateModuleForSimpleName("CoreTestAssembly"); + _contextX64Windows.SetSystemModule(systemModuleX64Windows); + + _testModuleX64Windows = systemModuleX64Windows; + _contextARM = new TestTypeSystemContext(TargetArchitecture.ARM); var systemModuleARM = _contextARM.CreateModuleForSimpleName("CoreTestAssembly"); _contextARM.SetSystemModule(systemModuleARM); @@ -41,6 +60,12 @@ public ArchitectureSpecificFieldLayoutTests() _contextX86.SetSystemModule(systemModuleX86); _testModuleX86 = systemModuleX86; + + _contextARM64 = new TestTypeSystemContext(TargetArchitecture.ARM64); + var systemModuleARM64 = _contextARM64.CreateModuleForSimpleName("CoreTestAssembly"); + _contextARM64.SetSystemModule(systemModuleARM64); + + _testModuleARM64 = systemModuleARM64; } [Fact] @@ -414,5 +439,116 @@ public void TestAlignmentBehavior_ShortByteEnumStructAuto() Assert.Equal(0x4, tX86FieldStruct.GetField("_struct").Offset.AsInt); Assert.Equal(0x4, tARMFieldStruct.GetField("_struct").Offset.AsInt); } + + [Fact] + public void TestAlignmentBehavior_StructStructByte_StructByteAuto() + { + string _namespace = "Sequential"; + string _type = "StructStructByte_StructByteAuto"; + + MetadataType tX64 = _testModuleX64.GetType(_namespace, _type); + MetadataType tX86 = _testModuleX86.GetType(_namespace, _type); + MetadataType tARM = _testModuleARM.GetType(_namespace, _type); + + Assert.Equal(0x1, tX64.InstanceFieldAlignment.AsInt); + Assert.Equal(0x1, tARM.InstanceFieldAlignment.AsInt); + Assert.Equal(0x1, tX86.InstanceFieldAlignment.AsInt); + + Assert.Equal(0x2, tX64.InstanceFieldSize.AsInt); + Assert.Equal(0x2, tARM.InstanceFieldSize.AsInt); + Assert.Equal(0x2, tX86.InstanceFieldSize.AsInt); + + Assert.Equal(0x0, tX64.GetField("fld1").Offset.AsInt); + Assert.Equal(0x0, tARM.GetField("fld1").Offset.AsInt); + Assert.Equal(0x0, tX86.GetField("fld1").Offset.AsInt); + + Assert.Equal(0x1, tX64.GetField("fld2").Offset.AsInt); + Assert.Equal(0x1, tARM.GetField("fld2").Offset.AsInt); + Assert.Equal(0x1, tX86.GetField("fld2").Offset.AsInt); + } + + [Theory] + [InlineData("StructStructByte_StructByteAuto", new int[]{1,1,1}, new int[]{2,2,2})] + [InlineData("StructStructByte_Struct2BytesAuto", new int[]{2,2,2}, new int[]{4,4,4})] + [InlineData("StructStructByte_Struct3BytesAuto", new int[]{4,4,4}, new int[]{8,8,8})] + [InlineData("StructStructByte_Struct4BytesAuto", new int[]{4,4,4}, new int[]{8,8,8})] + [InlineData("StructStructByte_Struct5BytesAuto", new int[]{8,4,4}, new int[]{16,12,12})] + [InlineData("StructStructByte_Struct8BytesAuto", new int[]{8,4,4}, new int[]{16,12,12})] + [InlineData("StructStructByte_Struct9BytesAuto", new int[]{8,4,4}, new int[]{24,16,16})] + public void TestAlignmentBehavior_AutoAlignmentRules(string wrapperType, int[] alignment, int[] size) + { + string _namespace = "Sequential"; + string _type = wrapperType; + + MetadataType tX64 = _testModuleX64.GetType(_namespace, _type); + MetadataType tX86 = _testModuleX86.GetType(_namespace, _type); + MetadataType tARM = _testModuleARM.GetType(_namespace, _type); + + Assert.Equal(alignment[0], tX64.InstanceFieldAlignment.AsInt); + Assert.Equal(alignment[1], tARM.InstanceFieldAlignment.AsInt); + Assert.Equal(alignment[2], tX86.InstanceFieldAlignment.AsInt); + + Assert.Equal(size[0], tX64.InstanceFieldSize.AsInt); + Assert.Equal(size[1], tARM.InstanceFieldSize.AsInt); + Assert.Equal(size[2], tX86.InstanceFieldSize.AsInt); + + Assert.Equal(0x0, tX64.GetField("fld1").Offset.AsInt); + Assert.Equal(0x0, tARM.GetField("fld1").Offset.AsInt); + Assert.Equal(0x0, tX86.GetField("fld1").Offset.AsInt); + + Assert.Equal(alignment[0], tX64.GetField("fld2").Offset.AsInt); + Assert.Equal(alignment[1], tARM.GetField("fld2").Offset.AsInt); + Assert.Equal(alignment[2], tX86.GetField("fld2").Offset.AsInt); + } + + [Theory] + [InlineData("StructStructByte_Int128StructAuto", "ARM64", 16, 32)] + [InlineData("StructStructByte_Int128StructAuto", "ARM", 8, 24)] + [InlineData("StructStructByte_Int128StructAuto", "X86", 16, 32)] + [InlineData("StructStructByte_Int128StructAuto", "X64Linux", 16, 32)] + [InlineData("StructStructByte_Int128StructAuto", "X64Windows", 16, 32)] + [InlineData("StructStructByte_UInt128StructAuto", "ARM64", 16, 32)] + [InlineData("StructStructByte_UInt128StructAuto", "ARM", 8, 24)] + [InlineData("StructStructByte_UInt128StructAuto", "X86", 16, 32)] + [InlineData("StructStructByte_UInt128StructAuto", "X64Linux", 16, 32)] + [InlineData("StructStructByte_UInt128StructAuto", "X64Windows", 16, 32)] + // Variation of TestAlignmentBehavior_AutoAlignmentRules above that is able to deal with os specific behavior + public void TestAlignmentBehavior_AutoAlignmentRulesWithOSDependence(string wrapperType, string osArch, int alignment, int size) + { + ModuleDesc testModule; + switch (osArch) + { + case "ARM64": + testModule = _testModuleARM64; + break; + case "ARM": + testModule = _testModuleARM; + break; + case "X64": + testModule = _testModuleX64; + break; + case "X64Linux": + testModule = _testModuleX64Linux; + break; + case "X64Windows": + testModule = _testModuleX64Windows; + break; + case "X86": + testModule = _testModuleX86; + break; + default: + throw new Exception(); + } + + string _namespace = "Sequential"; + string _type = wrapperType; + + MetadataType type = testModule.GetType(_namespace, _type); + + Assert.Equal(alignment, type.InstanceFieldAlignment.AsInt); + Assert.Equal(size, type.InstanceFieldSize.AsInt); + Assert.Equal(0x0, type.GetField("fld1").Offset.AsInt); + Assert.Equal(alignment, type.GetField("fld2").Offset.AsInt); + } } } diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/InstanceFieldLayout.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/InstanceFieldLayout.cs index b49dd4ff729309..92446b5770ef94 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/InstanceFieldLayout.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/InstanceFieldLayout.cs @@ -3,56 +3,57 @@ using System; using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; #pragma warning disable 169 namespace ContainsGCPointers { - struct NoPointers + public struct NoPointers { - int int1; - byte byte1; - char char1; + public int int1; + public byte byte1; + public char char1; } - struct StillNoPointers + public struct StillNoPointers { - NoPointers noPointers1; - bool bool1; + public NoPointers noPointers1; + public bool bool1; } - class ClassNoPointers + public class ClassNoPointers { - char char1; + public char char1; } - struct HasPointers + public struct HasPointers { - string string1; + public string string1; } - struct FieldHasPointers + public struct FieldHasPointers { - HasPointers hasPointers1; + public HasPointers hasPointers1; } - class ClassHasPointers + public class ClassHasPointers { - ClassHasPointers classHasPointers1; + public ClassHasPointers classHasPointers1; } - class BaseClassHasPointers : ClassHasPointers + public class BaseClassHasPointers : ClassHasPointers { } public class ClassHasIntArray { - int[] intArrayField; + public int[] intArrayField; } public class ClassHasArrayOfClassType { - ClassNoPointers[] classTypeArray; + public ClassNoPointers[] classTypeArray; } } @@ -61,29 +62,29 @@ namespace Explicit [StructLayout(LayoutKind.Explicit)] class Class1 { - static int Stat; + public static int Stat; [FieldOffset(4)] - bool Bar; + public bool Bar; [FieldOffset(10)] - char Baz; + public char Baz; } [StructLayout(LayoutKind.Explicit)] class Class2 : Class1 { [FieldOffset(0)] - int Lol; + public int Lol; [FieldOffset(20)] - byte Omg; + public byte Omg; } [StructLayout(LayoutKind.Explicit, Size = 40)] class ExplicitSize { [FieldOffset(0)] - int Lol; + public int Lol; [FieldOffset(20)] - byte Omg; + public byte Omg; } [StructLayout(LayoutKind.Explicit)] @@ -123,194 +124,344 @@ ref struct ByRefStruct namespace Sequential { [StructLayout(LayoutKind.Sequential)] - class Class1 + public class Class1 { - int MyInt; - bool MyBool; - char MyChar; - string MyString; - byte[] MyByteArray; - Class1 MyClass1SelfRef; + public int MyInt; + public bool MyBool; + public char MyChar; + public string MyString; + public byte[] MyByteArray; + public Class1 MyClass1SelfRef; } [StructLayout(LayoutKind.Sequential)] - class Class2 : Class1 + public class Class2 : Class1 { - int MyInt2; + public int MyInt2; } // [StructLayout(LayoutKind.Sequential)] is applied by default by the C# compiler - struct Struct0 + public struct Struct0 { - bool b1; - bool b2; - bool b3; - int i1; - string s1; + public bool b1; + public bool b2; + public bool b3; + public int i1; + public string s1; } // [StructLayout(LayoutKind.Sequential)] is applied by default by the C# compiler - struct Struct1 + public struct Struct1 { - Struct0 MyStruct0; - bool MyBool; + public Struct0 MyStruct0; + public bool MyBool; } [StructLayout(LayoutKind.Sequential)] public class ClassDoubleBool { - double double1; - bool bool1; + public double double1; + public bool bool1; } [StructLayout(LayoutKind.Sequential)] public class ClassBoolDoubleBool { - bool bool1; - double double1; - bool bool2; + public bool bool1; + public double double1; + public bool bool2; + } + + public struct StructByte + { + public byte fld1; + } + + public struct StructStructByte_StructByteAuto + { + public StructByte fld1; + public Auto.StructByte fld2; + } + public struct StructStructByte_Struct2BytesAuto + { + public StructByte fld1; + public Auto.Struct2Bytes fld2; + } + public struct StructStructByte_Struct3BytesAuto + { + public StructByte fld1; + public Auto.Struct3Bytes fld2; + } + public struct StructStructByte_Struct4BytesAuto + { + public StructByte fld1; + public Auto.Struct4Bytes fld2; + } + public struct StructStructByte_Struct5BytesAuto + { + public StructByte fld1; + public Auto.Struct5Bytes fld2; + } + public struct StructStructByte_Struct8BytesAuto + { + public StructByte fld1; + public Auto.Struct8Bytes fld2; + } + public struct StructStructByte_Struct9BytesAuto + { + public StructByte fld1; + public Auto.Struct9Bytes fld2; + } + + public struct StructStructByte_Int128StructAuto + { + public StructByte fld1; + public Auto.Int128Struct fld2; + } + + public struct StructStructByte_UInt128StructAuto + { + public StructByte fld1; + public Auto.UInt128Struct fld2; } } namespace Auto { [StructLayout(LayoutKind.Auto)] - struct StructWithBool + public struct StructWithBool { - bool MyStructBool; + public bool MyStructBool; } [StructLayout(LayoutKind.Auto)] - struct StructWithIntChar + public struct StructWithIntChar { - char MyStructChar; - int MyStructInt; + public char MyStructChar; + public int MyStructInt; } [StructLayout(LayoutKind.Auto)] - struct StructWithChar + public struct StructWithChar { - char MyStructChar; + public char MyStructChar; } - class ClassContainingStructs + public class ClassContainingStructs { - static int MyStaticInt; + public static int MyStaticInt; - StructWithBool MyStructWithBool; - bool MyBool1; - char MyChar1; - int MyInt; - double MyDouble; - long MyLong; - byte[] MyByteArray; - string MyString1; - bool MyBool2; - StructWithIntChar MyStructWithIntChar; - StructWithChar MyStructWithChar; + public StructWithBool MyStructWithBool; + public bool MyBool1; + public char MyChar1; + public int MyInt; + public double MyDouble; + public long MyLong; + public byte[] MyByteArray; + public string MyString1; + public bool MyBool2; + public StructWithIntChar MyStructWithIntChar; + public StructWithChar MyStructWithChar; } - class BaseClass7BytesRemaining + public class BaseClass7BytesRemaining { - bool MyBool1; - double MyDouble1; - long MyLong1; - byte[] MyByteArray1; - string MyString1; + public bool MyBool1; + public double MyDouble1; + public long MyLong1; + public byte[] MyByteArray1; + public string MyString1; } - class BaseClass4BytesRemaining + public class BaseClass4BytesRemaining { - long MyLong1; - uint MyUint1; + public long MyLong1; + public uint MyUint1; } - class BaseClass3BytesRemaining + public class BaseClass3BytesRemaining { - int MyInt1; - string MyString1; - bool MyBool1; + public int MyInt1; + public string MyString1; + public bool MyBool1; } - class OptimizePartial : BaseClass7BytesRemaining + public class OptimizePartial : BaseClass7BytesRemaining { - bool OptBool; - char OptChar; - long NoOptLong; - string NoOptString; + public bool OptBool; + public char OptChar; + public long NoOptLong; + public string NoOptString; } - class Optimize7Bools : BaseClass7BytesRemaining + public class Optimize7Bools : BaseClass7BytesRemaining { - bool OptBool1; - bool OptBool2; - bool OptBool3; - bool OptBool4; - bool OptBool5; - bool OptBool6; - bool OptBool7; - bool NoOptBool8; - string NoOptString; + public bool OptBool1; + public bool OptBool2; + public bool OptBool3; + public bool OptBool4; + public bool OptBool5; + public bool OptBool6; + public bool OptBool7; + public bool NoOptBool8; + public string NoOptString; } - class OptimizeAlignedFields : BaseClass7BytesRemaining + public class OptimizeAlignedFields : BaseClass7BytesRemaining { - bool OptBool1; - bool OptBool2; - bool OptBool3; - bool NoOptBool4; - char OptChar1; - char OptChar2; - string NoOptString; + public bool OptBool1; + public bool OptBool2; + public bool OptBool3; + public bool NoOptBool4; + public char OptChar1; + public char OptChar2; + public string NoOptString; } - class OptimizeLargestField : BaseClass4BytesRemaining + public class OptimizeLargestField : BaseClass4BytesRemaining { - bool NoOptBool; - char NoOptChar; - int OptInt; - string NoOptString; + public bool NoOptBool; + public char NoOptChar; + public int OptInt; + public string NoOptString; } - class NoOptimizeMisaligned : BaseClass3BytesRemaining + public class NoOptimizeMisaligned : BaseClass3BytesRemaining { - char NoOptChar; - int NoOptInt; - string NoOptString; + public char NoOptChar; + public int NoOptInt; + public string NoOptString; } - class NoOptimizeCharAtSize2Alignment : BaseClass3BytesRemaining + public class NoOptimizeCharAtSize2Alignment : BaseClass3BytesRemaining { - char NoOptChar; + public char NoOptChar; } [StructLayout(LayoutKind.Auto, Pack = 1)] - struct MinPacking + public struct MinPacking { public byte _byte; public T _value; } + + [StructLayout(LayoutKind.Auto)] + public struct int8x16x2 + { + public Vector128 _0; + public Vector128 _1; + } + + public struct Wrapper_int8x16x2 + { + public int8x16x2 fld; + } + + public struct Wrapper_int8x16x2_2 + { + public bool fld1; + public int8x16x2 fld2; + } + + [StructLayout(LayoutKind.Auto)] + public struct StructByte + { + public byte fld1; + } + + [StructLayout(LayoutKind.Auto)] + public struct Struct2Bytes + { + public byte fld1; + public byte fld2; + } + + [StructLayout(LayoutKind.Auto)] + public struct Struct3Bytes + { + public byte fld1; + public byte fld2; + public byte fld3; + } + + [StructLayout(LayoutKind.Auto)] + public struct Struct4Bytes + { + public byte fld1; + public byte fld2; + public byte fld3; + public byte fld4; + } + + [StructLayout(LayoutKind.Auto)] + public struct Struct5Bytes + { + public byte fld1; + public byte fld2; + public byte fld3; + public byte fld4; + public byte fld5; + } + + [StructLayout(LayoutKind.Auto)] + public struct Struct8Bytes + { + public byte fld1; + public byte fld2; + public byte fld3; + public byte fld4; + public byte fld5; + public byte fld6; + public byte fld7; + public byte fld8; + } + + [StructLayout(LayoutKind.Auto)] + public struct Struct9Bytes + { + public byte fld1; + public byte fld2; + public byte fld3; + public byte fld4; + public byte fld5; + public byte fld6; + public byte fld7; + public byte fld8; + public byte fld9; + } + + [StructLayout(LayoutKind.Auto)] + public struct UInt128Struct + { + UInt128 fld1; + } + + [StructLayout(LayoutKind.Auto)] + public struct Int128Struct + { + Int128 fld1; + } } namespace IsByRefLike { public ref struct ByRefLikeStruct { - ref object ByRef; + public ref object ByRef; } public struct NotByRefLike { - int X; + public int X; } } namespace EnumAlignment { - public enum ByteEnum : byte {} - public enum ShortEnum : short {} - public enum IntEnum : int {} - public enum LongEnum : long {} + public enum ByteEnum : byte { Val } + public enum ShortEnum : short { Val } + public enum IntEnum : int { Val } + public enum LongEnum : long { Val } public struct LongIntEnumStruct { diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/Platform.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/Platform.cs index 2850c56a10f3c9..6935dd75d92c93 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/Platform.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/Platform.cs @@ -1,5 +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 System.Runtime.InteropServices; #pragma warning disable 649 #pragma warning disable 169 @@ -71,6 +73,24 @@ public ref struct TypedReference private readonly ref byte _value; private readonly RuntimeTypeHandle _typeHandle; } + + [Intrinsic] + [StructLayout(LayoutKind.Sequential)] + public readonly struct Int128 + { + + private readonly ulong _lower; + private readonly ulong _upper; + } + + [Intrinsic] + [StructLayout(LayoutKind.Sequential)] + public readonly struct UInt128 + { + + private readonly ulong _lower; + private readonly ulong _upper; + } } namespace System.Collections @@ -136,4 +156,22 @@ public static class RuntimeFeature public const string ByRefFields = nameof(ByRefFields); public const string VirtualStaticsInInterfaces = nameof(VirtualStaticsInInterfaces); } + + internal sealed class IntrinsicAttribute : Attribute + { + } +} + +namespace System.Runtime.Intrinsics +{ + [Intrinsic] + [StructLayout(LayoutKind.Sequential, Size = 16)] + public readonly struct Vector128 + where T : struct + { + // These fields exist to ensure the alignment is 8, rather than 1. + // This also allows the debug view to work https://github.com/dotnet/runtime/issues/9495) + private readonly ulong _00; + private readonly ulong _01; + } } diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ILCompiler.TypeSystem.Tests.csproj b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ILCompiler.TypeSystem.Tests.csproj index a9e0faf8ac8177..1f6b33ff18ba39 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ILCompiler.TypeSystem.Tests.csproj +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ILCompiler.TypeSystem.Tests.csproj @@ -46,6 +46,8 @@ + + diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/InstanceFieldLayoutTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/InstanceFieldLayoutTests.cs index 0a60a72a4a640b..4b02f805f3535b 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/InstanceFieldLayoutTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/InstanceFieldLayoutTests.cs @@ -850,5 +850,25 @@ public void TestInvalidByRefLikeTypes() Assert.Throws(() => type.ComputeInstanceLayout(InstanceLayoutKind.TypeAndFields)); } } + + [Fact] + public void TestWrapperAroundVectorTypes() + { + { + MetadataType type = (MetadataType)_testModule.GetType("System.Runtime.Intrinsics", "Vector128`1"); + MetadataType instantiatedType = type.MakeInstantiatedType(_context.GetWellKnownType(WellKnownType.Byte)); + Assert.Equal(16, instantiatedType.InstanceFieldAlignment.AsInt); + } + + { + DefType type = _testModule.GetType("Auto", "int8x16x2"); + Assert.Equal(16, type.InstanceFieldAlignment.AsInt); + } + + { + DefType type = _testModule.GetType("Auto", "Wrapper_int8x16x2"); + Assert.Equal(16, type.InstanceFieldAlignment.AsInt); + } + } } } diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/TestTypeSystemContext.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/TestTypeSystemContext.cs index 0fbd0b6a35329e..3f963c24104eb1 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/TestTypeSystemContext.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/TestTypeSystemContext.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Diagnostics; +using ILCompiler; using Internal.TypeSystem; using System.Reflection; using System.Reflection.PortableExecutable; @@ -22,6 +23,9 @@ class TestTypeSystemContext : MetadataTypeSystemContext { Dictionary _modules = new Dictionary(StringComparer.OrdinalIgnoreCase); + private VectorFieldLayoutAlgorithm _vectorFieldLayoutAlgorithm; + private Int128FieldLayoutAlgorithm _int128FieldLayoutAlgorithm; + MetadataFieldLayoutAlgorithm _metadataFieldLayout = new TestMetadataFieldLayoutAlgorithm(); MetadataRuntimeInterfacesAlgorithm _metadataRuntimeInterfacesAlgorithm = new MetadataRuntimeInterfacesAlgorithm(); ArrayOfTRuntimeInterfacesAlgorithm _arrayOfTRuntimeInterfacesAlgorithm; @@ -29,9 +33,11 @@ class TestTypeSystemContext : MetadataTypeSystemContext public CanonicalizationMode CanonMode { get; set; } = CanonicalizationMode.RuntimeDetermined; - public TestTypeSystemContext(TargetArchitecture arch) - : base(new TargetDetails(arch, TargetOS.Unknown, TargetAbi.Unknown)) + public TestTypeSystemContext(TargetArchitecture arch, TargetOS targetOS = TargetOS.Unknown) + : base(new TargetDetails(arch, targetOS, TargetAbi.Unknown)) { + _vectorFieldLayoutAlgorithm = new VectorFieldLayoutAlgorithm(_metadataFieldLayout, true); + _int128FieldLayoutAlgorithm = new Int128FieldLayoutAlgorithm(_metadataFieldLayout); } public ModuleDesc GetModuleForSimpleName(string simpleName) @@ -67,6 +73,14 @@ public override FieldLayoutAlgorithm GetLayoutAlgorithmForType(DefType type) { if (type == UniversalCanonType) return UniversalCanonLayoutAlgorithm.Instance; + else if (VectorFieldLayoutAlgorithm.IsVectorType(type)) + { + return _vectorFieldLayoutAlgorithm; + } + else if (Int128FieldLayoutAlgorithm.IsIntegerType(type)) + { + return _int128FieldLayoutAlgorithm; + } return _metadataFieldLayout; } diff --git a/src/coreclr/tools/aot/ILCompiler/Program.cs b/src/coreclr/tools/aot/ILCompiler/Program.cs index f33053fc898f17..f3c064835d8bff 100644 --- a/src/coreclr/tools/aot/ILCompiler/Program.cs +++ b/src/coreclr/tools/aot/ILCompiler/Program.cs @@ -15,9 +15,11 @@ using Internal.CommandLine; +using ILCompiler.Dataflow; +using ILLink.Shared; + using Debug = System.Diagnostics.Debug; using InstructionSet = Internal.JitInterface.InstructionSet; -using ILCompiler.Dataflow; namespace ILCompiler { @@ -103,6 +105,8 @@ internal class Program private IReadOnlyList _singleWarnEnabledAssemblies = Array.Empty(); private IReadOnlyList _singleWarnDisabledAssemblies = Array.Empty(); private bool _singleWarn; + private bool _noTrimWarn; + private bool _noAotWarn; private string _makeReproPath; @@ -228,6 +232,8 @@ private ArgumentSyntax ParseCommandLine(string[] args) syntax.DefineOption("nopreinitstatics", ref _noPreinitStatics, "Do not interpret static constructors at compile time"); syntax.DefineOptionList("nowarn", ref _suppressedWarnings, "Disable specific warning messages"); syntax.DefineOption("singlewarn", ref _singleWarn, "Generate single AOT/trimming warning per assembly"); + syntax.DefineOption("notrimwarn", ref _noTrimWarn, "Disable warnings related to trimming"); + syntax.DefineOption("noaotwarn", ref _noAotWarn, "Disable warnings related to AOT"); syntax.DefineOptionList("singlewarnassembly", ref _singleWarnEnabledAssemblies, "Generate single AOT/trimming warning for given assembly"); syntax.DefineOptionList("nosinglewarnassembly", ref _singleWarnDisabledAssemblies, "Expand AOT/trimming warnings for given assembly"); syntax.DefineOptionList("directpinvoke", ref _directPInvokes, "PInvoke to call directly"); @@ -768,7 +774,13 @@ static string ILLinkify(string rootedAssembly) } ilProvider = new FeatureSwitchManager(ilProvider, featureSwitches); - var logger = new Logger(Console.Out, ilProvider, _isVerbose, ProcessWarningCodes(_suppressedWarnings), _singleWarn, _singleWarnEnabledAssemblies, _singleWarnDisabledAssemblies); + var suppressedWarningCategories = new List(); + if (_noTrimWarn) + suppressedWarningCategories.Add(MessageSubCategory.TrimAnalysis); + if (_noAotWarn) + suppressedWarningCategories.Add(MessageSubCategory.AotAnalysis); + + var logger = new Logger(Console.Out, ilProvider, _isVerbose, ProcessWarningCodes(_suppressedWarnings), _singleWarn, _singleWarnEnabledAssemblies, _singleWarnDisabledAssemblies, suppressedWarningCategories); CompilerGeneratedState compilerGeneratedState = new CompilerGeneratedState(ilProvider, logger); var stackTracePolicy = _emitStackTraceData ? diff --git a/src/coreclr/tools/aot/crossgen2/crossgen2.csproj b/src/coreclr/tools/aot/crossgen2/crossgen2.csproj index 8696352abc03e8..0d50278228a310 100644 --- a/src/coreclr/tools/aot/crossgen2/crossgen2.csproj +++ b/src/coreclr/tools/aot/crossgen2/crossgen2.csproj @@ -7,6 +7,10 @@ false + + + false + true linux-x64;linux-musl-x64;linux-arm;linux-musl-arm;linux-arm64;linux-musl-arm64;freebsd-x64;osx-x64;osx-arm64;win-x64;win-x86;win-arm64;win-arm diff --git a/src/coreclr/vm/class.h b/src/coreclr/vm/class.h index 1fc909efe9c623..22ef2b9919cc19 100644 --- a/src/coreclr/vm/class.h +++ b/src/coreclr/vm/class.h @@ -376,7 +376,9 @@ class EEClassLayoutInfo // The size of the struct is explicitly specified in the meta-data. e_HAS_EXPLICIT_SIZE = 0x08, // The type recursively has a field that is LayoutKind.Auto and not an enum. - e_HAS_AUTO_LAYOUT_FIELD_IN_LAYOUT = 0x10 + e_HAS_AUTO_LAYOUT_FIELD_IN_LAYOUT = 0x10, + // Type type recursively has a field which is an Int128 + e_IS_OR_HAS_INT128_FIELD = 0x20, }; BYTE m_bFlags; @@ -426,6 +428,12 @@ class EEClassLayoutInfo return (m_bFlags & e_HAS_AUTO_LAYOUT_FIELD_IN_LAYOUT) == e_HAS_AUTO_LAYOUT_FIELD_IN_LAYOUT; } + BOOL IsInt128OrHasInt128Fields() const + { + LIMITED_METHOD_CONTRACT; + return (m_bFlags & e_IS_OR_HAS_INT128_FIELD) == e_IS_OR_HAS_INT128_FIELD; + } + BYTE GetPackingSize() const { LIMITED_METHOD_CONTRACT; @@ -467,6 +475,13 @@ class EEClassLayoutInfo m_bFlags = hasAutoLayoutField ? (m_bFlags | e_HAS_AUTO_LAYOUT_FIELD_IN_LAYOUT) : (m_bFlags & ~e_HAS_AUTO_LAYOUT_FIELD_IN_LAYOUT); } + + void SetIsInt128OrHasInt128Fields(BOOL hasInt128Field) + { + LIMITED_METHOD_CONTRACT; + m_bFlags = hasInt128Field ? (m_bFlags | e_IS_OR_HAS_INT128_FIELD) + : (m_bFlags & ~e_IS_OR_HAS_INT128_FIELD); + } }; // @@ -1410,6 +1425,9 @@ class EEClass // DO NOT CREATE A NEW EEClass USING NEW! BOOL HasExplicitSize(); BOOL IsAutoLayoutOrHasAutoLayoutField(); + + // Only accurate on non-auto layout types + BOOL IsInt128OrHasInt128Fields(); static void GetBestFitMapping(MethodTable * pMT, BOOL *pfBestFitMapping, BOOL *pfThrowOnUnmappableChar); @@ -2105,6 +2123,15 @@ inline BOOL EEClass::IsAutoLayoutOrHasAutoLayoutField() return !HasLayout() || GetLayoutInfo()->HasAutoLayoutField(); } +inline BOOL EEClass::IsInt128OrHasInt128Fields() +{ + // The name of this type is a slight misnomer as it doesn't detect Int128 fields on + // auto layout types, but since we only need this for interop scenarios, it works out. + LIMITED_METHOD_CONTRACT; + // If this type is not auto + return HasLayout() && GetLayoutInfo()->IsInt128OrHasInt128Fields(); +} + //========================================================================== // These routines manage the prestub (a bootstrapping stub that all // FunctionDesc's are initialized with.) diff --git a/src/coreclr/vm/classlayoutinfo.cpp b/src/coreclr/vm/classlayoutinfo.cpp index 34b04dcd6f7ab3..a37d7a06521216 100644 --- a/src/coreclr/vm/classlayoutinfo.cpp +++ b/src/coreclr/vm/classlayoutinfo.cpp @@ -328,6 +328,16 @@ namespace return FALSE; } + BOOL TypeHasInt128Field(CorElementType corElemType, TypeHandle pNestedType) + { + if (corElemType == ELEMENT_TYPE_VALUETYPE) + { + _ASSERTE(!pNestedType.IsNull()); + return pNestedType.GetMethodTable()->IsInt128OrHasInt128Fields(); + } + return FALSE; + } + #ifdef UNIX_AMD64_ABI void SystemVAmd64CheckForPassNativeStructInRegister(MethodTable* pMT, EEClassNativeLayoutInfo* pNativeLayoutInfo) { @@ -454,6 +464,7 @@ namespace const SigTypeContext* pTypeContext, BOOL* fDisqualifyFromManagedSequential, BOOL* fHasAutoLayoutField, + BOOL* fHasInt128Field, LayoutRawFieldInfo* pFieldInfoArrayOut, BOOL* pIsBlittableOut, ULONG* cInstanceFields @@ -532,6 +543,7 @@ namespace pFieldInfoArrayOut->m_placement = GetFieldPlacementInfo(corElemType, typeHandleMaybe); *fDisqualifyFromManagedSequential |= TypeHasGCPointers(corElemType, typeHandleMaybe); *fHasAutoLayoutField |= TypeHasAutoLayoutField(corElemType, typeHandleMaybe); + *fHasInt128Field |= TypeHasInt128Field(corElemType, typeHandleMaybe); if (!IsFieldBlittable(pModule, fd, fsig.GetArgProps(), pTypeContext, nativeTypeFlags)) *pIsBlittableOut = FALSE; @@ -625,6 +637,7 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing( // function exits. BOOL fDisqualifyFromManagedSequential; BOOL hasAutoLayoutField = FALSE; + BOOL hasInt128Field = FALSE; // Check if this type might be ManagedSequential. Only valuetypes marked Sequential can be // ManagedSequential. Other issues checked below might also disqualify the type. @@ -639,9 +652,12 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing( fDisqualifyFromManagedSequential = TRUE; } - if (pParentMT && !pParentMT->IsValueTypeClass() && pParentMT->IsAutoLayoutOrHasAutoLayoutField()) + if (pParentMT && !pParentMT->IsValueTypeClass()) { - hasAutoLayoutField = TRUE; + if (pParentMT->IsAutoLayoutOrHasAutoLayoutField()) + hasAutoLayoutField = TRUE; + if (pParentMT->IsInt128OrHasInt128Fields()) + hasInt128Field = TRUE; } @@ -692,6 +708,7 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing( pTypeContext, &fDisqualifyFromManagedSequential, &hasAutoLayoutField, + &hasInt128Field, pInfoArrayOut, &isBlittable, &cInstanceFields @@ -706,6 +723,8 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing( pEEClassLayoutInfoOut->SetHasAutoLayoutField(hasAutoLayoutField); + pEEClassLayoutInfoOut->SetIsInt128OrHasInt128Fields(hasInt128Field); + S_UINT32 cbSortArraySize = S_UINT32(cTotalFields) * S_UINT32(sizeof(LayoutRawFieldInfo*)); if (cbSortArraySize.IsOverflow()) { diff --git a/src/coreclr/vm/dllimport.cpp b/src/coreclr/vm/dllimport.cpp index 239480035443d7..de49ed7b1781b4 100644 --- a/src/coreclr/vm/dllimport.cpp +++ b/src/coreclr/vm/dllimport.cpp @@ -3326,6 +3326,12 @@ BOOL NDirect::MarshalingRequired( { TypeHandle hndArgType = arg.GetTypeHandleThrowing(pModule, &emptyTypeContext); + if (hndArgType.GetMethodTable()->IsInt128OrHasInt128Fields()) + { + // Int128 cannot be marshalled by value at this time + return TRUE; + } + // When the runtime runtime marshalling system is disabled, we don't support // any types that contain gc pointers, but all "unmanaged" types are treated as blittable // as long as they aren't auto-layout and don't have any auto-layout fields. diff --git a/src/coreclr/vm/methodtable.h b/src/coreclr/vm/methodtable.h index 515cc554b4f6d8..07792d5fbf36d9 100644 --- a/src/coreclr/vm/methodtable.h +++ b/src/coreclr/vm/methodtable.h @@ -1487,6 +1487,9 @@ class MethodTable inline BOOL IsAutoLayoutOrHasAutoLayoutField(); + // Only accurate on types which are not auto layout + inline BOOL IsInt128OrHasInt128Fields(); + UINT32 GetNativeSize(); DWORD GetBaseSize() diff --git a/src/coreclr/vm/methodtable.inl b/src/coreclr/vm/methodtable.inl index adcdbd33469858..8f8f8178e26023 100644 --- a/src/coreclr/vm/methodtable.inl +++ b/src/coreclr/vm/methodtable.inl @@ -948,6 +948,13 @@ inline BOOL MethodTable::IsAutoLayoutOrHasAutoLayoutField() return GetClass()->IsAutoLayoutOrHasAutoLayoutField(); } +//========================================================================================== +inline BOOL MethodTable::IsInt128OrHasInt128Fields() +{ + LIMITED_METHOD_CONTRACT; + return HasLayout() && GetClass()->IsInt128OrHasInt128Fields(); +} + //========================================================================================== inline DWORD MethodTable::GetPerInstInfoSize() { diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp index ecd1e9d22916cb..b0c0c1ce749d37 100644 --- a/src/coreclr/vm/methodtablebuilder.cpp +++ b/src/coreclr/vm/methodtablebuilder.cpp @@ -9907,21 +9907,6 @@ void MethodTableBuilder::CheckForSystemTypes() return; } -#if defined(UNIX_AMD64_ABI) || defined(TARGET_ARM64) - else if (strcmp(nameSpace, g_SystemNS) == 0) - { - EEClassLayoutInfo* pLayout = pClass->GetLayoutInfo(); - - // These types correspond to fundamental data types in the underlying ABIs: - // * Int128: __int128 - // * UInt128: unsigned __int128 - - if ((strcmp(name, g_Int128Name) == 0) || (strcmp(name, g_UInt128Name) == 0)) - { - pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16; // sizeof(__int128) - } - } -#endif // UNIX_AMD64_ABI || TARGET_ARM64 } if (g_pNullableClass != NULL) @@ -10005,6 +9990,30 @@ void MethodTableBuilder::CheckForSystemTypes() { pMT->SetInternalCorElementType (ELEMENT_TYPE_I); } + else if ((strcmp(name, g_Int128Name) == 0) || (strcmp(name, g_UInt128Name) == 0)) + { + EEClassLayoutInfo* pLayout = pClass->GetLayoutInfo(); + pLayout->SetIsInt128OrHasInt128Fields(TRUE); +#ifdef TARGET_ARM + // No such type exists for the Procedure Call Standard for ARM. We will default + // to the same alignment as __m128, which is supported by the ABI. + + pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 8; +#elif defined(TARGET_64BIT) || defined(TARGET_X86) + + // These types correspond to fundamental data types in the underlying ABIs: + // * Int128: __int128 + // * UInt128: unsigned __int128 + // + // This behavior matches the ABI standard on various Unix platforms + // On Windows, no standard for Int128 has been established yet, + // although applying 16 byte alignment is consistent with treatment of 128 bit SSE types + // even on X86 + pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16; // sizeof(__int128) +#else +#error Unknown architecture +#endif // TARGET_64BIT + } } else { diff --git a/src/coreclr/vm/mlinfo.cpp b/src/coreclr/vm/mlinfo.cpp index 2665a46d12f0ab..2ca3596ac9236f 100644 --- a/src/coreclr/vm/mlinfo.cpp +++ b/src/coreclr/vm/mlinfo.cpp @@ -1131,6 +1131,11 @@ namespace *errorResIDOut = IDS_EE_BADMARSHAL_AUTOLAYOUT; return MarshalInfo::MARSHAL_TYPE_UNKNOWN; } + if (pMT->IsInt128OrHasInt128Fields()) + { + *errorResIDOut = IDS_EE_BADMARSHAL_INT128_RESTRICTION; + return MarshalInfo::MARSHAL_TYPE_UNKNOWN; + } *pMTOut = pMT; return MarshalInfo::MARSHAL_TYPE_BLITTABLEVALUECLASS; } @@ -2283,6 +2288,18 @@ MarshalInfo::MarshalInfo(Module* pModule, IfFailGoto(E_FAIL, lFail); } + // * Int128: Represents the 128 bit integer ABI primitive type which requires currently unimplemented handling + // * UInt128: Represents the 128 bit integer ABI primitive type which requires currently unimplemented handling + // The field layout is correct, so field scenarios work, but these should not be passed by value as parameters + if (!IsFieldScenario() && !m_byref) + { + if (m_pMT->IsInt128OrHasInt128Fields()) + { + m_resID = IDS_EE_BADMARSHAL_INT128_RESTRICTION; + IfFailGoto(E_FAIL, lFail); + } + } + if (!m_pMT->HasLayout()) { m_resID = IDS_EE_BADMARSHAL_AUTOLAYOUT; diff --git a/src/installer/prepare-artifacts.proj b/src/installer/prepare-artifacts.proj index 595c8e49d575c1..3eed860616f28a 100644 --- a/src/installer/prepare-artifacts.proj +++ b/src/installer/prepare-artifacts.proj @@ -133,7 +133,7 @@ - $(InstallersRelativePath)workloads/$(SdkBandVersion)/%(Filename)%(Extension) + $(InstallersRelativePath)workloads/%(Filename)%(Extension) true @@ -222,11 +222,13 @@ Include="$(DownloadDirectory)**\VS.Redist.Common.*.nupkg" Exclude="@(DownloadedSymbolNupkgFile)" /> - + + $(DownloadDirectory)*\workloads-vs\**\*.zip"/> @@ -44,7 +46,6 @@ debugger-main.js -1 - true @@ -52,6 +53,8 @@ + + @@ -63,6 +66,7 @@ + GetStructWithShortAndBoolCallback(); diff --git a/src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingDisabled/PInvokes.cs b/src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingDisabled/PInvokes.cs index 4fa7315d43063d..21b0716948d20b 100644 --- a/src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingDisabled/PInvokes.cs +++ b/src/tests/Interop/DisabledRuntimeMarshalling/PInvokeAssemblyMarshallingDisabled/PInvokes.cs @@ -148,4 +148,11 @@ public static void CanUseEnumsWithDisabledMarshalling() { Assert.Equal((byte)ByteEnum.Value, DisabledRuntimeMarshallingNative.GetEnumUnderlyingValue(ByteEnum.Value)); } + + [Fact] + [SkipOnMono("Blocking this on CoreCLR should be good enough.")] + public static void Int128_NotSupported() + { + Assert.Throws(() => DisabledRuntimeMarshallingNative.CallWithInt128(default(Int128))); + } } diff --git a/src/tests/Interop/PInvoke/Int128/Int128Native.cpp b/src/tests/Interop/PInvoke/Int128/Int128Native.cpp index 28f70bca06fabd..9cd68311421632 100644 --- a/src/tests/Interop/PInvoke/Int128/Int128Native.cpp +++ b/src/tests/Interop/PInvoke/Int128/Int128Native.cpp @@ -11,14 +11,29 @@ #elif defined(__SIZEOF_INT128__) typedef __int128 Int128; #else - typedef struct { +struct +#if defined(_M_ARM64) || defined(_M_AMD64) || defined(_M_IX86) +alignas(16) +#endif +Int128 { uint64_t lower; uint64_t upper; - } Int128; + }; #endif static Int128 Int128Value = { }; +struct StructWithInt128 +{ + int8_t messUpPadding; + Int128 value; +}; + +struct StructJustInt128 +{ + Int128 value; +}; + extern "C" DLL_EXPORT Int128 STDMETHODCALLTYPE GetInt128(uint64_t upper, uint64_t lower) { Int128 result; @@ -41,6 +56,24 @@ extern "C" DLL_EXPORT void STDMETHODCALLTYPE GetInt128Out(uint64_t upper, uint64 *pValue = value; } +extern "C" DLL_EXPORT uint64_t STDMETHODCALLTYPE GetInt128Lower(Int128 value) +{ +#if (INT128_WIDTH == 128) || defined(__SIZEOF_INT128__) + return (uint64_t)value; +#else + return value.lower; +#endif +} + +extern "C" DLL_EXPORT uint64_t STDMETHODCALLTYPE GetInt128Lower_S(StructJustInt128 value) +{ +#if (INT128_WIDTH == 128) || defined(__SIZEOF_INT128__) + return (uint64_t)value.value; +#else + return value.value.lower; +#endif +} + extern "C" DLL_EXPORT const Int128* STDMETHODCALLTYPE GetInt128Ptr(uint64_t upper, uint64_t lower) { GetInt128Out(upper, lower, &Int128Value); @@ -62,6 +95,210 @@ extern "C" DLL_EXPORT Int128 STDMETHODCALLTYPE AddInt128(Int128 lhs, Int128 rhs) return result; } +// Test that struct alignment behavior matches with the standard OS compiler +extern "C" DLL_EXPORT void STDMETHODCALLTYPE AddStructWithInt128_ByRef(StructWithInt128 *pLhs, StructWithInt128 *pRhs) +{ + StructWithInt128 result = {}; + StructWithInt128 lhs = *pLhs; + StructWithInt128 rhs = *pRhs; + + result.messUpPadding = lhs.messUpPadding; + +#if (INT128_WIDTH == 128) || defined(__SIZEOF_INT128__) + result.value = lhs.value + rhs.value; +#else + result.value.lower = lhs.value.lower + rhs.value.lower; + uint64_t carry = (result.value.lower < lhs.value.lower) ? 1 : 0; + result.value.upper = lhs.value.upper + rhs.value.upper + carry; +#endif + + *pLhs = result; +} + +extern "C" DLL_EXPORT StructWithInt128 STDMETHODCALLTYPE AddStructWithInt128(StructWithInt128 lhs, StructWithInt128 rhs) +{ + StructWithInt128 result = {}; + result.messUpPadding = lhs.messUpPadding; + +#if (INT128_WIDTH == 128) || defined(__SIZEOF_INT128__) + result.value = lhs.value + rhs.value; +#else + result.value.lower = lhs.value.lower + rhs.value.lower; + uint64_t carry = (result.value.lower < lhs.value.lower) ? 1 : 0; + result.value.upper = lhs.value.upper + rhs.value.upper + carry; +#endif + + return result; +} + +extern "C" DLL_EXPORT StructWithInt128 STDMETHODCALLTYPE AddStructWithInt128_1(int64_t dummy1, StructWithInt128 lhs, StructWithInt128 rhs) +{ + StructWithInt128 result = {}; + result.messUpPadding = lhs.messUpPadding; + +#if (INT128_WIDTH == 128) || defined(__SIZEOF_INT128__) + result.value = lhs.value + rhs.value; +#else + result.value.lower = lhs.value.lower + rhs.value.lower; + uint64_t carry = (result.value.lower < lhs.value.lower) ? 1 : 0; + result.value.upper = lhs.value.upper + rhs.value.upper + carry; +#endif + + return result; +} + +extern "C" DLL_EXPORT StructWithInt128 STDMETHODCALLTYPE AddStructWithInt128_9(int64_t dummy1, int64_t dummy2, int64_t dummy3, int64_t dummy4, int64_t dummy5, int64_t dummy6, int64_t dummy7, int64_t dummy8, int64_t dummy9, StructWithInt128 lhs, StructWithInt128 rhs) +{ + StructWithInt128 result = {}; + result.messUpPadding = lhs.messUpPadding; + +#if (INT128_WIDTH == 128) || defined(__SIZEOF_INT128__) + result.value = lhs.value + rhs.value; +#else + result.value.lower = lhs.value.lower + rhs.value.lower; + uint64_t carry = (result.value.lower < lhs.value.lower) ? 1 : 0; + result.value.upper = lhs.value.upper + rhs.value.upper + carry; +#endif + + return result; +} + +extern "C" DLL_EXPORT Int128 STDMETHODCALLTYPE AddInt128_1(int64_t dummy1, Int128 lhs, Int128 rhs) +{ + Int128 result; + +#if (INT128_WIDTH == 128) || defined(__SIZEOF_INT128__) + result = lhs + rhs; +#else + result.lower = lhs.lower + rhs.lower; + uint64_t carry = (result.lower < lhs.lower) ? 1 : 0; + result.upper = lhs.upper + rhs.upper + carry; +#endif + + return result; +} + +extern "C" DLL_EXPORT Int128 STDMETHODCALLTYPE AddInt128_2(int64_t dummy1, int64_t dummy2, Int128 lhs, Int128 rhs) +{ + Int128 result; + +#if (INT128_WIDTH == 128) || defined(__SIZEOF_INT128__) + result = lhs + rhs; +#else + result.lower = lhs.lower + rhs.lower; + uint64_t carry = (result.lower < lhs.lower) ? 1 : 0; + result.upper = lhs.upper + rhs.upper + carry; +#endif + + return result; +} + +extern "C" DLL_EXPORT Int128 STDMETHODCALLTYPE AddInt128_3(int64_t dummy1, int64_t dummy2, int64_t dummy3, Int128 lhs, Int128 rhs) +{ + Int128 result; + +#if (INT128_WIDTH == 128) || defined(__SIZEOF_INT128__) + result = lhs + rhs; +#else + result.lower = lhs.lower + rhs.lower; + uint64_t carry = (result.lower < lhs.lower) ? 1 : 0; + result.upper = lhs.upper + rhs.upper + carry; +#endif + + return result; +} + +extern "C" DLL_EXPORT Int128 STDMETHODCALLTYPE AddInt128_4(int64_t dummy1, int64_t dummy2, int64_t dummy3, int64_t dummy4, Int128 lhs, Int128 rhs) +{ + Int128 result; + +#if (INT128_WIDTH == 128) || defined(__SIZEOF_INT128__) + result = lhs + rhs; +#else + result.lower = lhs.lower + rhs.lower; + uint64_t carry = (result.lower < lhs.lower) ? 1 : 0; + result.upper = lhs.upper + rhs.upper + carry; +#endif + + return result; +} + +extern "C" DLL_EXPORT Int128 STDMETHODCALLTYPE AddInt128_5(int64_t dummy1, int64_t dummy2, int64_t dummy3, int64_t dummy4, int64_t dummy5, Int128 lhs, Int128 rhs) +{ + Int128 result; + +#if (INT128_WIDTH == 128) || defined(__SIZEOF_INT128__) + result = lhs + rhs; +#else + result.lower = lhs.lower + rhs.lower; + uint64_t carry = (result.lower < lhs.lower) ? 1 : 0; + result.upper = lhs.upper + rhs.upper + carry; +#endif + + return result; +} + +extern "C" DLL_EXPORT Int128 STDMETHODCALLTYPE AddInt128_6(int64_t dummy1, int64_t dummy2, int64_t dummy3, int64_t dummy4, int64_t dummy5, int64_t dummy6, Int128 lhs, Int128 rhs) +{ + Int128 result; + +#if (INT128_WIDTH == 128) || defined(__SIZEOF_INT128__) + result = lhs + rhs; +#else + result.lower = lhs.lower + rhs.lower; + uint64_t carry = (result.lower < lhs.lower) ? 1 : 0; + result.upper = lhs.upper + rhs.upper + carry; +#endif + + return result; +} + +extern "C" DLL_EXPORT Int128 STDMETHODCALLTYPE AddInt128_7(int64_t dummy1, int64_t dummy2, int64_t dummy3, int64_t dummy4, int64_t dummy5, int64_t dummy6, int64_t dummy7, Int128 lhs, Int128 rhs) +{ + Int128 result; + +#if (INT128_WIDTH == 128) || defined(__SIZEOF_INT128__) + result = lhs + rhs; +#else + result.lower = lhs.lower + rhs.lower; + uint64_t carry = (result.lower < lhs.lower) ? 1 : 0; + result.upper = lhs.upper + rhs.upper + carry; +#endif + + return result; +} + +extern "C" DLL_EXPORT Int128 STDMETHODCALLTYPE AddInt128_8(int64_t dummy1, int64_t dummy2, int64_t dummy3, int64_t dummy4, int64_t dummy5, int64_t dummy6, int64_t dummy7, int64_t dummy8, Int128 lhs, Int128 rhs) +{ + Int128 result; + +#if (INT128_WIDTH == 128) || defined(__SIZEOF_INT128__) + result = lhs + rhs; +#else + result.lower = lhs.lower + rhs.lower; + uint64_t carry = (result.lower < lhs.lower) ? 1 : 0; + result.upper = lhs.upper + rhs.upper + carry; +#endif + + return result; +} + +extern "C" DLL_EXPORT Int128 STDMETHODCALLTYPE AddInt128_9(int64_t dummy1, int64_t dummy2, int64_t dummy3, int64_t dummy4, int64_t dummy5, int64_t dummy6, int64_t dummy7, int64_t dummy8, int64_t dummy9, Int128 lhs, Int128 rhs) +{ + Int128 result; + +#if (INT128_WIDTH == 128) || defined(__SIZEOF_INT128__) + result = lhs + rhs; +#else + result.lower = lhs.lower + rhs.lower; + uint64_t carry = (result.lower < lhs.lower) ? 1 : 0; + result.upper = lhs.upper + rhs.upper + carry; +#endif + + return result; +} + + extern "C" DLL_EXPORT Int128 STDMETHODCALLTYPE AddInt128s(const Int128* pValues, uint32_t count) { Int128 result = {}; diff --git a/src/tests/Interop/PInvoke/Int128/Int128Test.cs b/src/tests/Interop/PInvoke/Int128/Int128Test.cs index 5a9ddd5bb2135d..c6a8c378d6f25e 100644 --- a/src/tests/Interop/PInvoke/Int128/Int128Test.cs +++ b/src/tests/Interop/PInvoke/Int128/Int128Test.cs @@ -5,6 +5,20 @@ using System.Runtime.InteropServices; using Xunit; + +struct StructJustInt128 +{ + public StructJustInt128(Int128 val) { value = val; } + public Int128 value; +} + +struct StructWithInt128 +{ + public StructWithInt128(Int128 val) { value = val; messUpPadding = 0x10; } + public byte messUpPadding; + public Int128 value; +} + unsafe partial class Int128Native { [DllImport(nameof(Int128Native))] @@ -16,6 +30,15 @@ unsafe partial class Int128Native [DllImport(nameof(Int128Native))] public static extern void GetInt128Out(ulong upper, ulong lower, out Int128 value); + [DllImport(nameof(Int128Native))] + public static extern void GetInt128Out(ulong upper, ulong lower, out StructJustInt128 value); + + [DllImport(nameof(Int128Native))] + public static extern ulong GetInt128Lower_S(StructJustInt128 value); + + [DllImport(nameof(Int128Native))] + public static extern ulong GetInt128Lower(Int128 value); + [DllImport(nameof(Int128Native))] public static extern Int128* GetInt128Ptr(ulong upper, ulong lower); @@ -25,6 +48,47 @@ unsafe partial class Int128Native [DllImport(nameof(Int128Native))] public static extern Int128 AddInt128(Int128 lhs, Int128 rhs); + + [DllImport(nameof(Int128Native))] + public static extern void AddStructWithInt128_ByRef(ref StructWithInt128 lhs, ref StructWithInt128 rhs); + + [DllImport(nameof(Int128Native))] + public static extern StructWithInt128 AddStructWithInt128(StructWithInt128 lhs, StructWithInt128 rhs); + + [DllImport(nameof(Int128Native))] + public static extern StructWithInt128 AddStructWithInt128_1(long dummy1, StructWithInt128 lhs, StructWithInt128 rhs); + + [DllImport(nameof(Int128Native))] + public static extern StructWithInt128 AddStructWithInt128_9(long dummy1, long dummy2, long dummy3, long dummy4, long dummy5, long dummy6, long dummy7, long dummy8, long dummy9, StructWithInt128 lhs, StructWithInt128 rhs); + + // Test alignment and proper register usage for Int128 with various amounts of other registers in use. These tests are designed to stress the calling convention of Arm64 and Unix X64. + [DllImport(nameof(Int128Native))] + public static extern Int128 AddInt128_1(long dummy1, Int128 lhs, Int128 rhs); + + [DllImport(nameof(Int128Native))] + public static extern Int128 AddInt128_2(long dummy1, long dummy2, Int128 lhs, Int128 rhs); + + [DllImport(nameof(Int128Native))] + public static extern Int128 AddInt128_3(long dummy1, long dummy2, long dummy3, Int128 lhs, Int128 rhs); + + [DllImport(nameof(Int128Native))] + public static extern Int128 AddInt128_4(long dummy1, long dummy2, long dummy3, long dummy4, Int128 lhs, Int128 rhs); + + [DllImport(nameof(Int128Native))] + public static extern Int128 AddInt128_5(long dummy1, long dummy2, long dummy3, long dummy4, long dummy5, Int128 lhs, Int128 rhs); + + [DllImport(nameof(Int128Native))] + public static extern Int128 AddInt128_6(long dummy1, long dummy2, long dummy3, long dummy4, long dummy5, long dummy6, Int128 lhs, Int128 rhs); + + [DllImport(nameof(Int128Native))] + public static extern Int128 AddInt128_7(long dummy1, long dummy2, long dummy3, long dummy4, long dummy5, long dummy6, long dummy7, Int128 lhs, Int128 rhs); + + [DllImport(nameof(Int128Native))] + public static extern Int128 AddInt128_8(long dummy1, long dummy2, long dummy3, long dummy4, long dummy5, long dummy6, long dummy7, long dummy8, Int128 lhs, Int128 rhs); + + [DllImport(nameof(Int128Native))] + public static extern Int128 AddInt128_9(long dummy1, long dummy2, long dummy3, long dummy4, long dummy5, long dummy6, long dummy7, long dummy8, long dummy9, Int128 lhs, Int128 rhs); + [DllImport(nameof(Int128Native))] public static extern Int128 AddInt128s(Int128* pValues, int count); @@ -37,10 +101,14 @@ unsafe partial class Int128Native unsafe partial class Int128Native { - private static void TestInt128() + public static void TestInt128FieldLayout() { - Int128 value1 = Int128Native.GetInt128(1, 2); - Assert.Equal(new Int128(1, 2), value1); + // This test checks that the alignment rules of Int128 structs match the native compiler + StructWithInt128 lhs = new StructWithInt128(new Int128(11, 12)); + StructWithInt128 rhs = new StructWithInt128(new Int128(13, 14)); + + Int128Native.AddStructWithInt128_ByRef(ref lhs, ref rhs); + Assert.Equal(new StructWithInt128(new Int128(24, 26)), lhs); Int128 value2; Int128Native.GetInt128Out(3, 4, &value2); @@ -49,6 +117,28 @@ private static void TestInt128() Int128Native.GetInt128Out(5, 6, out Int128 value3); Assert.Equal(new Int128(5, 6), value3); + StructJustInt128 value4; + Int128Native.GetInt128Out(7, 8, out value4); + Assert.Equal(new StructJustInt128(new Int128(7, 8)), value4); + + // Until we implement the correct abi for Int128, validate that we don't marshal to native + + // Checking return value + Assert.Throws(() => GetInt128(0, 1)); + + // Checking input value as Int128 itself + Assert.Throws(() => GetInt128Lower(default(Int128))); + + // Checking input value as structure wrapping Int128 + Assert.Throws(() => GetInt128Lower_S(default(StructJustInt128))); + } + + private static void TestInt128() + { + Int128 value1 = Int128Native.GetInt128(1, 2); + Assert.Equal(new Int128(1, 2), value1); + + Int128* value4 = Int128Native.GetInt128Ptr(7, 8); Assert.Equal(new Int128(7, 8), *value4); @@ -77,5 +167,45 @@ private static void TestInt128() Int128 value9 = Int128Native.AddInt128s(in values[0], values.Length); Assert.Equal(new Int128(95, 100), value9); + + // Test ABI alignment issues on Arm64 and Unix X64, both enregistered and while spilled to the stack + Int128 value10 = Int128Native.AddInt128_1(1, new Int128(25, 26), new Int128(27, 28)); + Assert.Equal(new Int128(52, 54), value10); + + Int128 value11 = Int128Native.AddInt128_2(1, 2, new Int128(25, 26), new Int128(27, 28)); + Assert.Equal(new Int128(52, 54), value11); + + Int128 value12 = Int128Native.AddInt128_3(1, 2, 3, new Int128(25, 26), new Int128(27, 28)); + Assert.Equal(new Int128(52, 54), value12); + + Int128 value13 = Int128Native.AddInt128_4(1, 2, 3, 4, new Int128(25, 26), new Int128(27, 28)); + Assert.Equal(new Int128(52, 54), value13); + + Int128 value14 = Int128Native.AddInt128_5(1, 2, 3, 4, 5, new Int128(25, 26), new Int128(27, 28)); + Assert.Equal(new Int128(52, 54), value14); + + Int128 value15 = Int128Native.AddInt128_6(1, 2, 3, 4, 5, 6, new Int128(25, 26), new Int128(27, 28)); + Assert.Equal(new Int128(52, 54), value15); + + Int128 value16 = Int128Native.AddInt128_7(1, 2, 3, 4, 5, 6, 7, new Int128(25, 26), new Int128(27, 28)); + Assert.Equal(new Int128(52, 54), value16); + + Int128 value17 = Int128Native.AddInt128_8(1, 2, 3, 4, 5, 6, 7, 8, new Int128(25, 26), new Int128(27, 28)); + Assert.Equal(new Int128(52, 54), value17); + + Int128 value18 = Int128Native.AddInt128_9(1, 2, 3, 4, 5, 6, 7, 8, 9, new Int128(25, 26), new Int128(27, 28)); + Assert.Equal(new Int128(52, 54), value18); + + // Test alignment within a structure + StructWithInt128 value19 = Int128Native.AddStructWithInt128(new StructWithInt128(new Int128(29, 30)), new StructWithInt128(new Int128(31, 32))); + Assert.Equal(new StructWithInt128(new Int128(60, 62)), value19); + + // Test abi register alignment within a structure + StructWithInt128 value20 = Int128Native.AddStructWithInt128_1(1, new StructWithInt128(new Int128(29, 30)), new StructWithInt128(new Int128(31, 32))); + Assert.Equal(new StructWithInt128(new Int128(60, 62)), value20); + + // Test abi alignment when spilled to the stack + StructWithInt128 value21 = Int128Native.AddStructWithInt128_9(1, 2, 3, 4, 5, 6, 7, 8, 9, new StructWithInt128(new Int128(29, 30)), new StructWithInt128(new Int128(31, 32))); + Assert.Equal(new StructWithInt128(new Int128(60, 62)), value21); } } diff --git a/src/tests/Interop/PInvoke/Int128/Int128Test.csproj b/src/tests/Interop/PInvoke/Int128/Int128Test.csproj index 42fc09c10b7185..e13c49fe94c3f7 100644 --- a/src/tests/Interop/PInvoke/Int128/Int128Test.csproj +++ b/src/tests/Interop/PInvoke/Int128/Int128Test.csproj @@ -6,7 +6,9 @@ exe - + + + diff --git a/src/tests/Interop/PInvoke/Int128/Int128TestFieldLayout.csproj b/src/tests/Interop/PInvoke/Int128/Int128TestFieldLayout.csproj new file mode 100644 index 00000000000000..449dc00c211eff --- /dev/null +++ b/src/tests/Interop/PInvoke/Int128/Int128TestFieldLayout.csproj @@ -0,0 +1,15 @@ + + + + true + embedded + exe + + + + + + + + + diff --git a/src/tests/Interop/PInvoke/Int128/ProgramFieldLayout.cs b/src/tests/Interop/PInvoke/Int128/ProgramFieldLayout.cs new file mode 100644 index 00000000000000..5a31288c5d3266 --- /dev/null +++ b/src/tests/Interop/PInvoke/Int128/ProgramFieldLayout.cs @@ -0,0 +1,23 @@ +// 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; + +unsafe partial class Int128NativeFieldLayout +{ + public static int Main(string[] args) + { + try + { + Console.WriteLine("Testing Int128"); + Int128Native.TestInt128FieldLayout(); + } + catch (System.Exception ex) + { + Console.WriteLine(ex); + return 0; + } + return 100; + } +} diff --git a/src/tests/JIT/Stress/ABI/ABIs.cs b/src/tests/JIT/Stress/ABI/ABIs.cs index a9c85f864aa88b..3ad1eed8d7c743 100644 --- a/src/tests/JIT/Stress/ABI/ABIs.cs +++ b/src/tests/JIT/Stress/ABI/ABIs.cs @@ -47,14 +47,14 @@ internal class Win86Abi : IAbi new[] { typeof(byte), typeof(short), typeof(int), typeof(long), - typeof(float), typeof(double), + typeof(float), typeof(double), typeof(Int128), typeof(Vector), typeof(Vector128), typeof(Vector256), typeof(S1P), typeof(S2P), typeof(S2U), typeof(S3U), typeof(S4P), typeof(S4U), typeof(S5U), typeof(S6U), typeof(S7U), typeof(S8P), typeof(S8U), typeof(S9U), typeof(S10U), typeof(S11U), typeof(S12U), typeof(S13U), typeof(S14U), typeof(S15U), typeof(S16U), typeof(S17U), - typeof(S31U), typeof(S32U), + typeof(S31U), typeof(S32U), typeof(I128_1), typeof(I128_2) }; public CallingConvention[] PInvokeConventions { get; } = { CallingConvention.Cdecl, CallingConvention.StdCall, }; @@ -107,12 +107,13 @@ internal class SysVAbi : IAbi typeof(byte), typeof(short), typeof(int), typeof(long), typeof(float), typeof(double), typeof(Vector), typeof(Vector128), typeof(Vector256), + typeof(Int128), typeof(S1P), typeof(S2P), typeof(S2U), typeof(S3U), typeof(S4P), typeof(S4U), typeof(S5U), typeof(S6U), typeof(S7U), typeof(S8P), typeof(S8U), typeof(S9U), typeof(S10U), typeof(S11U), typeof(S12U), typeof(S13U), typeof(S14U), typeof(S15U), typeof(S16U), typeof(S17U), - typeof(S31U), typeof(S32U), + typeof(S31U), typeof(S32U), typeof(I128_1), typeof(I128_2) }; public CallingConvention[] PInvokeConventions { get; } = { CallingConvention.Cdecl }; @@ -135,14 +136,14 @@ internal class Arm64Abi : IAbi new[] { typeof(byte), typeof(short), typeof(int), typeof(long), - typeof(float), typeof(double), + typeof(float), typeof(double), typeof(Int128), typeof(Vector), typeof(Vector128), typeof(Vector256), typeof(S1P), typeof(S2P), typeof(S2U), typeof(S3U), typeof(S4P), typeof(S4U), typeof(S5U), typeof(S6U), typeof(S7U), typeof(S8P), typeof(S8U), typeof(S9U), typeof(S10U), typeof(S11U), typeof(S12U), typeof(S13U), typeof(S14U), typeof(S15U), typeof(S16U), - typeof(Hfa1), typeof(Hfa2), + typeof(Hfa1), typeof(Hfa2), typeof(I128_1) }; public CallingConvention[] PInvokeConventions { get; } = { CallingConvention.Cdecl }; diff --git a/src/tests/JIT/Stress/ABI/Gen.cs b/src/tests/JIT/Stress/ABI/Gen.cs index a7d0d0efbe5435..ddb7c1215c87ef 100644 --- a/src/tests/JIT/Stress/ABI/Gen.cs +++ b/src/tests/JIT/Stress/ABI/Gen.cs @@ -48,6 +48,9 @@ internal static object GenConstant(Type type, FieldInfo[] fields, Random rand) if (type == typeof(double)) return (double)rand.Next(); + if (type == typeof(Int128)) + return new Int128((ulong)(long)GenConstant(typeof(long), null, rand), (ulong)(long)GenConstant(typeof(long), null, rand)); + if (type == typeof(Vector)) return GenConstantVector, int>(rand); @@ -173,6 +176,8 @@ internal static void EmitLoadPrimitive(ILGenerator il, object val) il.Emit(OpCodes.Ldc_R4, (float)val); else if (ty == typeof(double)) il.Emit(OpCodes.Ldc_R8, (double)val); + else if (ty == typeof(Int128)) + EmitLoadBlittable(il, (Int128)val); else if (ty == typeof(Vector)) EmitLoadBlittable(il, (Vector)val); else if (ty == typeof(Vector128)) diff --git a/src/tests/JIT/Stress/ABI/Program.cs b/src/tests/JIT/Stress/ABI/Program.cs index 8eab812a5748c3..1c1c00c648309b 100644 --- a/src/tests/JIT/Stress/ABI/Program.cs +++ b/src/tests/JIT/Stress/ABI/Program.cs @@ -344,6 +344,7 @@ public static void EmitDumpValues(string listName, ILGenerator g, IEnumerable), typeof(Vector128), typeof(Vector256), + typeof(Int128), typeof(S1P), typeof(S2P), typeof(S2U), typeof(S3U), typeof(S4P), typeof(S4U), typeof(S5U), typeof(S6U), typeof(S7U), typeof(S8P), typeof(S8U), typeof(S9U), @@ -351,6 +352,7 @@ public static void EmitDumpValues(string listName, ILGenerator g, IEnumerable new TypeEx(t)).ToArray(); private static readonly IAbi s_abi = SelectAbi(); diff --git a/src/tests/JIT/Stress/ABI/Types.cs b/src/tests/JIT/Stress/ABI/Types.cs index a24c47154de6d2..140ae76762b257 100644 --- a/src/tests/JIT/Stress/ABI/Types.cs +++ b/src/tests/JIT/Stress/ABI/Types.cs @@ -61,6 +61,8 @@ public struct S31U { public byte F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F1 public struct S32U { public byte F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, F31; public S32U(byte f0, byte f1, byte f2, byte f3, byte f4, byte f5, byte f6, byte f7, byte f8, byte f9, byte f10, byte f11, byte f12, byte f13, byte f14, byte f15, byte f16, byte f17, byte f18, byte f19, byte f20, byte f21, byte f22, byte f23, byte f24, byte f25, byte f26, byte f27, byte f28, byte f29, byte f30, byte f31) => (F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, F31) = (f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28, f29, f30, f31); } public struct Hfa1 { public float F0, F1; public Hfa1(float f0, float f1) => (F0, F1) = (f0, f1); } public struct Hfa2 { public double F0, F1, F2, F3; public Hfa2(double f0, double f1, double f2, double f3) => (F0, F1, F2, F3) = (f0, f1, f2, f3); } + public struct I128_1 { public Int128 F0; public I128_1(Int128 f0) => F0 = f0; } + public struct I128_2 { public byte F0; public Int128 F1; public I128_2(byte f0, Int128 f1) => (F0, F1) = (f0, f1); } internal static class TypeExtensions { @@ -78,7 +80,8 @@ public static bool IsOurStructType(this Type t) t == typeof(S14U) || t == typeof(S15U) || t == typeof(S16U) || t == typeof(S17U) || t == typeof(S31U) || t == typeof(S32U) || - t == typeof(Hfa1) || t == typeof(Hfa2); + t == typeof(Hfa1) || t == typeof(Hfa2) || + t == typeof(I128_1) || t == typeof(I128_2); } } } diff --git a/src/tests/issues.targets b/src/tests/issues.targets index 7caad0c5838b2f..aa379a245e5742 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -8,6 +8,9 @@ https://github.com/dotnet/runtime/issues/13703 + + https://github.com/dotnet/runtime/issues/74209 + @@ -916,12 +919,6 @@ https://github.com/dotnet/runtime/issues/62881 - - https://github.com/dotnet/runtime/issues/63856 - - - https://github.com/dotnet/runtime/issues/63856 - @@ -1427,6 +1424,9 @@ + + https://github.com/dotnet/runtime/issues/74223 + https://github.com/dotnet/runtime/issues/71656 diff --git a/src/tests/readytorun/fieldlayout/fieldlayout.csproj b/src/tests/readytorun/fieldlayout/fieldlayout.csproj new file mode 100644 index 00000000000000..a9902bca098f35 --- /dev/null +++ b/src/tests/readytorun/fieldlayout/fieldlayout.csproj @@ -0,0 +1,16 @@ + + + + exe + BuildAndRun + true + true + true + + + + + + + + diff --git a/src/tests/readytorun/fieldlayout/fieldlayouttests.cs b/src/tests/readytorun/fieldlayout/fieldlayouttests.cs new file mode 100644 index 00000000000000..9b421859653648 --- /dev/null +++ b/src/tests/readytorun/fieldlayout/fieldlayouttests.cs @@ -0,0 +1,300 @@ +using System; +using System.Runtime.Intrinsics; + +class Test +{ + // This test uses the same set of types as the type system unittests use, and attempts to validate that the R2R usage of said types works well. + // This is done by touching the various types, and then relying on the verification logic in R2R images to detect failures. + static int Main() + { + ContainsGCPointersFieldsTest.Test(); +// ExplicitTest.Test(); // Explicit layout is known to not quite match the runtime, and if enabled this set of tests will fail. + SequentialTest.Test(); + AutoTest.Test(); + EnumAlignmentTest.Test(); + AutoTestWithVector.Test(); + return 100; + } +} + +class EnumAlignmentTest +{ + static EnumAlignment.LongIntEnumStruct _fld1; + static EnumAlignment.LongIntEnumStructFieldStruct _fld2; + static EnumAlignment.IntShortEnumStruct _fld3; + static EnumAlignment.IntShortEnumStructFieldStruct _fld4; + static EnumAlignment.ShortByteEnumStruct _fld5; + static EnumAlignment.ShortByteEnumStructFieldStruct _fld6; + static EnumAlignment.LongIntEnumStructAuto _fld7; + static EnumAlignment.LongIntEnumStructAutoFieldStruct _fld8; + static EnumAlignment.IntShortEnumStructAuto _fld9; + static EnumAlignment.IntShortEnumStructAutoFieldStruct _fld10; + static EnumAlignment.ShortByteEnumStructAuto _fld11; + static EnumAlignment.ShortByteEnumStructAutoFieldStruct _fld12; + + public static void Test() + { + _fld1._1 = EnumAlignment.LongEnum.Val; + _fld1._2 = EnumAlignment.IntEnum.Val; + _fld1._3 = EnumAlignment.LongEnum.Val; + _fld1._4 = EnumAlignment.IntEnum.Val; + + _fld2._0 = 0; + _fld2._struct = _fld1; + + _fld3._1 = EnumAlignment.IntEnum.Val; + _fld3._2 = EnumAlignment.ShortEnum.Val; + _fld3._3 = EnumAlignment.IntEnum.Val; + _fld3._4 = EnumAlignment.ShortEnum.Val; + + _fld4._0 = 1; + _fld4._struct = _fld3; + + _fld5._1 = EnumAlignment.ShortEnum.Val; + _fld5._2 = EnumAlignment.ByteEnum.Val; + _fld5._3 = EnumAlignment.ShortEnum.Val; + _fld5._4 = EnumAlignment.ByteEnum.Val; + + _fld6._0 = 2; + _fld6._struct = _fld5; + + _fld7._1 = EnumAlignment.LongEnum.Val; + _fld7._2 = EnumAlignment.IntEnum.Val; + _fld7._3 = EnumAlignment.LongEnum.Val; + _fld7._4 = EnumAlignment.IntEnum.Val; + + _fld8._0 = 3; + _fld8._struct = _fld7; + + _fld9._1 = EnumAlignment.IntEnum.Val; + _fld9._2 = EnumAlignment.ShortEnum.Val; + _fld9._3 = EnumAlignment.IntEnum.Val; + _fld9._4 = EnumAlignment.ShortEnum.Val; + + _fld10._0 = 4; + _fld10._struct = _fld9; + + _fld11._1 = EnumAlignment.ShortEnum.Val; + _fld11._2 = EnumAlignment.ByteEnum.Val; + _fld11._3 = EnumAlignment.ShortEnum.Val; + _fld11._4 = EnumAlignment.ByteEnum.Val; + + _fld12._0 = 5; + _fld12._struct = _fld11; + } +} + +class AutoTest +{ + static Auto.StructWithBool _fld1; + static Auto.StructWithIntChar _fld2; + static Auto.StructWithChar _fld3; + static Auto.ClassContainingStructs _fld4 = new Auto.ClassContainingStructs(); + static Auto.BaseClass7BytesRemaining _fld5 = new Auto.BaseClass7BytesRemaining(); + static Auto.BaseClass4BytesRemaining _fld6 = new Auto.BaseClass4BytesRemaining(); + static Auto.BaseClass3BytesRemaining _fld7 = new Auto.BaseClass3BytesRemaining(); + static Auto.OptimizePartial _fld8 = new Auto.OptimizePartial(); + static Auto.Optimize7Bools _fld9 = new Auto.Optimize7Bools(); + static Auto.OptimizeAlignedFields _fld10 = new Auto.OptimizeAlignedFields(); + static Auto.OptimizeLargestField _fld11 = new Auto.OptimizeLargestField(); + static Auto.NoOptimizeMisaligned _fld12 = new Auto.NoOptimizeMisaligned(); + static Auto.NoOptimizeCharAtSize2Alignment _fld13 = new Auto.NoOptimizeCharAtSize2Alignment(); + static Auto.MinPacking _fld14 = new Auto.MinPacking(); + + public static void Test() + { + _fld1.MyStructBool = true; + + _fld2.MyStructInt = 1; + _fld2.MyStructChar = 'A'; + + _fld3.MyStructChar = 'B'; + + _fld4.MyStructWithChar = _fld3; + _fld4.MyStructWithIntChar = _fld2; + _fld4.MyStructWithBool = _fld1; + _fld4.MyString1 = "Str"; + _fld4.MyBool1 = false; + _fld4.MyBool2 = true; + + _fld5.MyBool1 = false; + _fld5.MyLong1 = 2; + _fld5.MyString1 = "Str2"; + _fld5.MyDouble1 = 1.0; + _fld5.MyByteArray1 = new byte[3]; + + _fld6.MyLong1 = 3; + _fld6.MyUint1 = 4; + + _fld7.MyBool1 = true; + _fld7.MyInt1 = 5; + _fld7.MyString1 = "str3"; + + _fld8.OptBool = false; + _fld8.OptChar = 'B'; + _fld8.NoOptLong = 6; + _fld8.NoOptString = "STR4"; + + _fld9.OptBool1 = true; + _fld9.OptBool2 = false; + _fld9.OptBool3 = true; + _fld9.OptBool4 = true; + _fld9.OptBool5 = false; + _fld9.OptBool6 = true; + _fld9.OptBool7 = false; + _fld9.NoOptBool8 = true; + _fld9.NoOptString = "STR5"; + + _fld10.OptBool1 = false; + _fld10.OptBool2 = true; + _fld10.OptBool3 = false; + _fld10.NoOptBool4 = true; + _fld10.OptChar1 = 'C'; + _fld10.OptChar2 = 'D'; + _fld10.NoOptString = "STR6"; + + _fld13.NoOptChar = 'E'; + + _fld14._value = 7; + _fld14._byte = 8; + } +} + +class AutoTestWithVector +{ + static Auto.int8x16x2 _fld1 = new Auto.int8x16x2(); + static Auto.Wrapper_int8x16x2 _fld2 = new Auto.Wrapper_int8x16x2(); + static Auto.Wrapper_int8x16x2_2 _fld3 = new Auto.Wrapper_int8x16x2_2(); + + public static void Test() + { + _fld1._0 = new Vector128(); + _fld1._1 = new Vector128(); + + _fld2.fld = _fld1; + + _fld3.fld1 = true; + _fld3.fld2 = _fld1; + } +} + +class SequentialTest +{ + static Sequential.Class1 _fld1 = new Sequential.Class1(); + static Sequential.Class2 _fld2 = new Sequential.Class2(); + static Sequential.Struct0 _fld3; + static Sequential.Struct1 _fld4; + static Sequential.ClassDoubleBool _fld5 = new Sequential.ClassDoubleBool(); + static Sequential.ClassBoolDoubleBool _fld6 = new Sequential.ClassBoolDoubleBool(); + static Sequential.StructStructByte_StructByteAuto _fld7; + static Sequential.StructStructByte_Struct2BytesAuto _fld8; + static Sequential.StructStructByte_Struct3BytesAuto _fld9; + static Sequential.StructStructByte_Struct4BytesAuto _fld10; + static Sequential.StructStructByte_Struct5BytesAuto _fld11; + static Sequential.StructStructByte_Struct8BytesAuto _fld12; + static Sequential.StructStructByte_Struct9BytesAuto _fld13; + static Sequential.StructStructByte_Int128StructAuto _fld14; + static Sequential.StructStructByte_UInt128StructAuto _fld15; + + public static void Test() + { + _fld1.MyClass1SelfRef = _fld1; + _fld1.MyChar = 'A'; + _fld1.MyInt = 1; + _fld1.MyString = "STR"; + _fld1.MyBool = true; + + _fld2.MyClass1SelfRef = _fld1; + _fld2.MyChar = 'B'; + _fld2.MyInt = 2; + _fld2.MyString = "STR2"; + _fld2.MyBool = false; + _fld2.MyInt2 = 3; + + _fld3.b1 = true; + _fld3.b2 = false; + _fld3.b3 = true; + _fld3.i1 = 4; + _fld3.s1 = "str"; + + _fld4.MyStruct0 = _fld3; + _fld4.MyBool = false; + + _fld5.bool1 = true; + _fld5.double1 = 1.0; + + _fld6.bool1 = false; + _fld6.bool2 = true; + _fld6.double1 = 2.0; + + _fld7.fld2 = default(Auto.StructByte); + _fld8.fld2 = default(Auto.Struct2Bytes); + _fld9.fld2 = default(Auto.Struct3Bytes); + _fld10.fld2 = default(Auto.Struct4Bytes); + _fld11.fld2 = default(Auto.Struct5Bytes); + _fld12.fld2 = default(Auto.Struct8Bytes); + _fld13.fld2 = default(Auto.Struct9Bytes); + _fld14.fld2 = default(Auto.Int128Struct); + _fld15.fld2 = default(Auto.UInt128Struct); + } +} + +class ExplicitTest +{ + static Explicit.Class1 _fld1 = new Explicit.Class1(); + static Explicit.Class2 _fld2 = new Explicit.Class2(); + static Explicit.ExplicitSize _fld3 = new Explicit.ExplicitSize(); + static Explicit.ExplicitEmptyClass _fld4 = new Explicit.ExplicitEmptyClass(); + static Explicit.ExplicitEmptyClassSize0 _fld5 = new Explicit.ExplicitEmptyClassSize0(); + static Explicit.ExplicitEmptyStruct _fld6 = new Explicit.ExplicitEmptyStruct(); + + public static void Test() + { + _fld1.Bar = true; + _fld1.Baz = 'A'; + + _fld2.Baz = 'B'; + _fld2.Bar = false; + _fld2.Lol = 1; + _fld2.Omg = 2; + + _fld3.Omg = 3; + _fld3.Lol = 4; + } +} +class ContainsGCPointersFieldsTest +{ + static ContainsGCPointers.NoPointers _fld1; + static ContainsGCPointers.StillNoPointers _fld2; + static ContainsGCPointers.ClassNoPointers _fld3 = new ContainsGCPointers.ClassNoPointers(); + static ContainsGCPointers.HasPointers _fld4; + static ContainsGCPointers.FieldHasPointers _fld5; + static ContainsGCPointers.ClassHasPointers _fld6 = new ContainsGCPointers.ClassHasPointers(); + static ContainsGCPointers.BaseClassHasPointers _fld7 = new ContainsGCPointers.BaseClassHasPointers(); + static ContainsGCPointers.ClassHasIntArray _fld8 = new ContainsGCPointers.ClassHasIntArray(); + static ContainsGCPointers.ClassHasArrayOfClassType _fld9 = new ContainsGCPointers.ClassHasArrayOfClassType(); + + public static void Test() + { + _fld1.int1 = 1; + _fld1.byte1 = 2; + _fld1.char1 = '0'; + _fld2.bool1 = true; + + _fld2.noPointers1 = _fld1; + + _fld3.char1 = '2'; + + _fld4.string1 = "STR"; + + _fld5.hasPointers1.string1 = "STR2"; + + _fld6.classHasPointers1 = new ContainsGCPointers.ClassHasPointers(); + + _fld7.classHasPointers1 = new ContainsGCPointers.ClassHasPointers(); + + _fld8.intArrayField = new int[1]; + + _fld9.classTypeArray = new ContainsGCPointers.ClassNoPointers[1]; + } +} diff --git a/src/workloads/workloads.csproj b/src/workloads/workloads.csproj index e2e96fd572c17e..1acaa7ea2356a0 100644 --- a/src/workloads/workloads.csproj +++ b/src/workloads/workloads.csproj @@ -7,6 +7,7 @@ false $(ArtifactsObjDir)workloads/ + $(WorkloadIntermediateOutputPath)VS/ $(ArtifactsBinDir)workloads/ $(workloadArtifactsPath)/ $(ArtifactsShippingPackagesDir) @@ -28,14 +29,20 @@ - + - + + + + + + - - - - - - - - - - - @@ -86,6 +78,10 @@ + + + Mono + Microsoft @@ -95,50 +91,38 @@ - + - - - - - + - + - - + - - - + + + + - - - + + + - + + - @@ -169,15 +153,7 @@ - - - - - - - - - +