.1.nupkg`
+## Important Notes
+
Test binaries are not yet available for mono.
The build places logs in `artifacts\log` and these are useful when the build fails.
The build places all of its output in the `artifacts\obj\mono` directory, so if you remove that directory you can force a
full rebuild.
-
-The build has a number of options that you can learn about using `build -?`.
\ No newline at end of file
diff --git a/docs/workflow/debugging/crash-dumps.md b/docs/workflow/debugging/crash-dumps.md
deleted file mode 100644
index 990cb6b924d37a..00000000000000
--- a/docs/workflow/debugging/crash-dumps.md
+++ /dev/null
@@ -1,16 +0,0 @@
-Crash dumps can be useful for analyzing and debugging intermittent or hard-to-reproduce bugs. In all of our CI test runs and official build test runs, we use a utility called "Dumpling" to collect and archive crash dumps that are created during test execution. These crash dumps are archived on the [Dumpling web portal](https://dumpling.azurewebsites.net/), which has download links, as well as auxiliary triage information gathered during crash dump collection.
-
-When a crash is encountered in a test run (and crash dump collection is enabled), the following information will be printed to the log:
-
-```
- Process is terminating due to StackOverflowException.
- processing dump file C:\Users\DOTNET~1\AppData\Local\Temp\CoreRunCrashDumps\dotnet.exe.13228.dmp
- creating dumpling dump 37ad6dce8b9d7f29def35b1ae1c9a3d4e3fc03bf
- uploading artifact 37ad6dce8b9d7f29def35b1ae1c9a3d4e3fc03bf dotnet.exe.13228.dmp
-```
-
-The crash dump can then be located via this unique identifier from the Dumpling portal. In the example above, the identifier is "37ad6dce8b9d7f29def35b1ae1c9a3d4e3fc03bf".
-
-Note that, while Dumpling archives the crash dumps for a long time, the Jenkins CI logs (containing the test info and the crash dump identifier) are not persisted for more than a few days.
-
-Debugging crash dumps is a fairly involved process. Windows crash dumps are well-supported using existing and documented tools like Visual Studio, WinDBG, and SOS. The instructions for Unix platforms are complicated, and are documented [here](../debugging/coreclr/debugging.md#debugging-core-dumps-with-lldb).
diff --git a/docs/workflow/debugging/libraries/unix-instructions.md b/docs/workflow/debugging/libraries/unix-instructions.md
index d33a8c023a4e63..8fdf86334dfab2 100644
--- a/docs/workflow/debugging/libraries/unix-instructions.md
+++ b/docs/workflow/debugging/libraries/unix-instructions.md
@@ -23,23 +23,10 @@ error: no such file
It is also possible to debug .NET Core crash dumps using lldb and SOS. In order to do this, you need all of the following:
-- You will find the dump url to download the crash dump file in the test logs, something similar to:
-
-2017-10-10 21:17:48,020: INFO: proc(54): run_and_log_output: Output: dumplingid: eefcb1cc36977ccf86f457ee28a33a7b4cc24e13
-2017-10-10 21:17:48,020: INFO: proc(54): run_and_log_output: Output: https://dumpling.azurewebsites.net/api/dumplings/archived/eefcb1cc36977ccf86f457ee28a33a7b4cc24e13
-
-- The crash dump file. We have a service called "Dumpling" which collects, uploads, and archives crash dump files during all of our CI jobs and official builds.
-- On Linux, there is an utility called `createdump` (see [doc](../../../design/coreclr/botr/xplat-minidump-generation.md "doc")) that can be setup to generate core dumps when a managed app throws an unhandled exception or faults.
-- Matching coreclr/corefx runtime bits from the crash. To get these, you should either:
- - Download the matching Jenkins archive onto your repro machine.
- - Check out the coreclr and corefx repositories at the appropriate commit and re-build the necessary portions.
-- lldb version 3.9. The SOS plugin (i.e. libsosplugin.so) provided is now built for lldb 3.9. In order to install lldb 3.9 just run the following commands:
-```
-~$ echo "deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.9 main" | sudo tee /etc/apt/sources.list.d/llvm.list
-~$ wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key | sudo apt-key add -
-~$ sudo apt-get update
-~$ sudo apt-get install lldb-3.9
-```
+- The crash dump file.
+- On Linux, there is an utility called `createdump` (see [doc](../../../design/coreclr/botr/xplat-minidump-generation.md "doc")) that can be setup to generate core dumps when a managed app throws an unhandled exception or faults.'
+
+There are instructions for installing lldb and SOS [here](https://github.com/dotnet/diagnostics/blob/master/documentation/sos.md).
Once you have everything listed above, you are ready to start debugging. You need to specify an extra parameter to lldb in order for it to correctly resolve the symbols for libcoreclr.so. Use a command like this:
diff --git a/docs/workflow/testing/coreclr/windows-test-instructions.md b/docs/workflow/testing/coreclr/windows-test-instructions.md
index ee5f94796f6d29..c1a423acdccd1d 100644
--- a/docs/workflow/testing/coreclr/windows-test-instructions.md
+++ b/docs/workflow/testing/coreclr/windows-test-instructions.md
@@ -51,7 +51,7 @@ Note: `build-test.cmd` or `build.cmd skipnative` needs to be run at least once
### Running Tests
-`src\coreclr\runtest.cmd /?` - will list supported parameters.
+`src\coreclr\tests\runtest.cmd /?` - will list supported parameters.
For example to run all of the tests using your checked build:
diff --git a/docs/workflow/testing/libraries/filtering-tests.md b/docs/workflow/testing/libraries/filtering-tests.md
index f7348a0281df5d..3b7d911d97fe3b 100644
--- a/docs/workflow/testing/libraries/filtering-tests.md
+++ b/docs/workflow/testing/libraries/filtering-tests.md
@@ -44,22 +44,22 @@ This attribute returns the 'failing' category, which is disabled by default.
**Disable for all platforms and all target frameworks:**
```cs
-[ActiveIssue(int issue)]
[ActiveIssue(string issue)]
```
**Disable for specific platform:**
```cs
-[ActiveIssue(int issue, TestPlatforms platforms)]
[ActiveIssue(string issue, TestPlatforms platforms)]
```
+**Disable for specific runtime:**
+```cs
+[ActiveIssue(string issue, TestRuntimes runtimes)]
+```
**Disable for specific target frameworks:**
```cs
-[ActiveIssue(int issue, TargetFrameworkMonikers frameworks)]
[ActiveIssue(string issue, TargetFrameworkMonikers frameworks)]
```
**Disable for specific test platforms and target frameworks:**
```cs
-[ActiveIssue(int issue, TestPlatforms platforms, TargetFrameworkMonikers frameworks)]
[ActiveIssue(string issue, TestPlatforms platforms, TargetFrameworkMonikers frameworks)]
```
Use this attribute over test methods to skip failing tests only on the specific platforms and the specific target frameworks.
@@ -142,7 +142,7 @@ public class TestClass
}
```
-**Note that all of the attributes above must include an issue number/link and/or have a comment next to them briefly justifying the reason. ActiveIssueAttribute and SkipOnTargetFrameworkAttribute should use their constructor parameters to do this**
+**Note that all of the attributes above must include an issue link and/or have a comment next to them briefly justifying the reason. ActiveIssueAttribute and SkipOnTargetFrameworkAttribute should use their constructor parameters to do this**
_**A few common examples with the above attributes:**_
diff --git a/docs/workflow/testing/mono/testing.md b/docs/workflow/testing/mono/testing.md
index f634d217d31875..894f44cc484b6e 100644
--- a/docs/workflow/testing/mono/testing.md
+++ b/docs/workflow/testing/mono/testing.md
@@ -1,7 +1,18 @@
# Running Tests using Mono Runtime
## Running Runtime Tests
-The runtime tests will be available at a later date.
+We currently only support running tests against coreclr. There are additional mono runtime tests in mono/mono, but they
+have not been moved over yet. Simply run the following command:
+
+```
+dotnet msbuild /t:RunCoreClrTests $(REPO_ROOT)/src/mono/mono.proj
+```
+
+If you want to run individual tests, execute this command:
+
+```
+dotnet msbuild /t:RunCoreClrTest /p:CoreClrTest="" $(REPO_ROOT)/src/mono/mono.proj
+```
## Running Library Tests
Running library tests against Mono is straightforward regardless of configuration. Simply run the following commands:
@@ -23,3 +34,21 @@ build.cmd /p:RuntimeFlavor=mono
```
dotnet msbuild /t:BuildAndTest /p:RuntimeFlavor=mono
```
+
+# Patching Local dotnet (.dotnet-mono)
+Another way to test mono out is by 'patching' a local dotnet with our runtime bits. This is a good way to write simple
+test programs and get a glimpse of how mono will work with the dotnet tooling.
+
+To generate a local .dotnet-mono, execute this command:
+
+```
+dotnet msbuild /t:PatchLocalMonoDotnet $(REPO_ROOT)/src/mono/mono.proj
+```
+
+You can then, for example, run our HelloWorld sample via:
+
+```
+dotnet build -c Release $(REPO_ROOT)/src/mono/netcore/sample/HelloWorld
+MONO_ENV_OPTIONS="" COMPlus_DebugWriteToStdErr=1 \
+$(REPO_ROOT)/.dotnet-mono/dotnet $(REPO_ROOT)/src/mono/netcore/sample/HelloWorld/bin/HelloWorld.dll
+```
\ No newline at end of file
diff --git a/eng/Analyzers.props b/eng/Analyzers.props
index e2163a76e3a96f..534d38a5546ca3 100644
--- a/eng/Analyzers.props
+++ b/eng/Analyzers.props
@@ -4,7 +4,7 @@
-
-
+
+
diff --git a/eng/CodeAnalysis.ruleset b/eng/CodeAnalysis.ruleset
index 646deabaf86736..e4525c4a7d0c94 100644
--- a/eng/CodeAnalysis.ruleset
+++ b/eng/CodeAnalysis.ruleset
@@ -50,7 +50,6 @@
-
diff --git a/eng/LicenseHeader.txt b/eng/LicenseHeader.txt
index 5c2f593e663071..94ec97db2fac35 100644
--- a/eng/LicenseHeader.txt
+++ b/eng/LicenseHeader.txt
@@ -2,6 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// ------------------------------------------------------------------------------
-// Changes to this file must follow the http://aka.ms/api-review process.
+// Changes to this file must follow the https://aka.ms/api-review process.
// ------------------------------------------------------------------------------
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index 68cefeed6be998..66c2e3d1ba1ee9 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -1,106 +1,66 @@
-
- https://github.com/dotnet/runtime
- 665983a01f9c604bc3f704f469acb8a08c619d8a
-
-
- https://github.com/dotnet/runtime
- 665983a01f9c604bc3f704f469acb8a08c619d8a
-
-
- https://github.com/dotnet/runtime
- 665983a01f9c604bc3f704f469acb8a08c619d8a
-
-
- https://github.com/dotnet/corefx
- cf64918877d98577363bb40d5eafac52beb80a79
-
-
- https://github.com/dotnet/coreclr
- 2c4fb3250989f014550882f5d165cdc36ebdbd08
-
-
- https://github.com/dotnet/coreclr
- 2c4fb3250989f014550882f5d165cdc36ebdbd08
-
-
- https://github.com/dotnet/corefx
- 5cee7c97d602f294e27c582d4dab81ec388f1d7b
-
-
- https://github.com/dotnet/corefx
- 5cee7c97d602f294e27c582d4dab81ec388f1d7b
-
https://github.com/dotnet/standard
cfe95a23647c7de1fe1a349343115bd7720d6949
-
- https://github.com/mono/linker
- cbdda5a2a6fbf01f74581aa956ef2e7b03b96977
-
-
+
https://github.com/dotnet/arcade
- b65df96ccb820fd5f7ea226aeba310485f395130
+ bd2a2b09716ddb54cb1e40f087beaaeeef859118
-
+
https://github.com/dotnet/arcade
- b65df96ccb820fd5f7ea226aeba310485f395130
+ bd2a2b09716ddb54cb1e40f087beaaeeef859118
-
+
https://github.com/dotnet/arcade
- b65df96ccb820fd5f7ea226aeba310485f395130
+ bd2a2b09716ddb54cb1e40f087beaaeeef859118
-
+
https://github.com/dotnet/arcade
- b65df96ccb820fd5f7ea226aeba310485f395130
+ bd2a2b09716ddb54cb1e40f087beaaeeef859118
-
+
https://github.com/dotnet/arcade
- b65df96ccb820fd5f7ea226aeba310485f395130
+ bd2a2b09716ddb54cb1e40f087beaaeeef859118
-
+
https://github.com/dotnet/arcade
- b65df96ccb820fd5f7ea226aeba310485f395130
+ bd2a2b09716ddb54cb1e40f087beaaeeef859118
-
+
https://github.com/dotnet/arcade
- b65df96ccb820fd5f7ea226aeba310485f395130
+ bd2a2b09716ddb54cb1e40f087beaaeeef859118
-
+
https://github.com/dotnet/arcade
- b65df96ccb820fd5f7ea226aeba310485f395130
+ bd2a2b09716ddb54cb1e40f087beaaeeef859118
-
+
https://github.com/dotnet/arcade
- b65df96ccb820fd5f7ea226aeba310485f395130
+ bd2a2b09716ddb54cb1e40f087beaaeeef859118
-
+
https://github.com/dotnet/arcade
- b65df96ccb820fd5f7ea226aeba310485f395130
+ bd2a2b09716ddb54cb1e40f087beaaeeef859118
-
+
https://github.com/dotnet/arcade
- b65df96ccb820fd5f7ea226aeba310485f395130
+ bd2a2b09716ddb54cb1e40f087beaaeeef859118
-
+
https://github.com/dotnet/arcade
- b65df96ccb820fd5f7ea226aeba310485f395130
+ bd2a2b09716ddb54cb1e40f087beaaeeef859118
-
+
https://github.com/dotnet/arcade
- b65df96ccb820fd5f7ea226aeba310485f395130
+ bd2a2b09716ddb54cb1e40f087beaaeeef859118
-
+
https://github.com/dotnet/arcade
- b65df96ccb820fd5f7ea226aeba310485f395130
-
-
- https://github.com/dotnet/arcade
- b65df96ccb820fd5f7ea226aeba310485f395130
+ bd2a2b09716ddb54cb1e40f087beaaeeef859118
https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
@@ -158,5 +118,65 @@
https://github.com/dotnet/runtime-assets
572e952eae1d4fc6e83300031c5f7c401014ff34
+
+ https://github.com/dotnet/llvm-project
+ adeaa08e7bbc9aba5d67cb16c2b348be12deb000
+
+
+ https://github.com/dotnet/llvm-project
+ adeaa08e7bbc9aba5d67cb16c2b348be12deb000
+
+
+ https://github.com/dotnet/llvm-project
+ adeaa08e7bbc9aba5d67cb16c2b348be12deb000
+
+
+ https://github.com/dotnet/llvm-project
+ adeaa08e7bbc9aba5d67cb16c2b348be12deb000
+
+
+ https://github.com/dotnet/llvm-project
+ adeaa08e7bbc9aba5d67cb16c2b348be12deb000
+
+
+ https://github.com/dotnet/llvm-project
+ adeaa08e7bbc9aba5d67cb16c2b348be12deb000
+
+
+ https://github.com/dotnet/runtime
+ 665983a01f9c604bc3f704f469acb8a08c619d8a
+
+
+ https://github.com/dotnet/runtime
+ 665983a01f9c604bc3f704f469acb8a08c619d8a
+
+
+ https://github.com/dotnet/runtime
+ 665983a01f9c604bc3f704f469acb8a08c619d8a
+
+
+ https://github.com/dotnet/corefx
+ cf64918877d98577363bb40d5eafac52beb80a79
+
+
+ https://github.com/dotnet/coreclr
+ 2c4fb3250989f014550882f5d165cdc36ebdbd08
+
+
+ https://github.com/dotnet/runtime
+ e793fcc19797f407a1b7e98d5f81b04e25a551c3
+
+
+ https://github.com/dotnet/corefx
+ 5cee7c97d602f294e27c582d4dab81ec388f1d7b
+
+
+ https://github.com/dotnet/corefx
+ 5cee7c97d602f294e27c582d4dab81ec388f1d7b
+
+
+ https://github.com/mono/linker
+ 72551f41d5925198262c1f3c2d06dfecd2596a4e
+
diff --git a/eng/Versions.props b/eng/Versions.props
index 854eb2523d8415..4a749666efcc6e 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -6,8 +6,8 @@
5
0
0
- alpha
- 1
+ preview
+ 2
$(MajorVersion).$(MinorVersion).0.0
@@ -16,6 +16,8 @@
release
true
+
+ 3.5.0-beta2-20074-05
true
false
@@ -57,16 +59,16 @@
- 5.0.0-beta.20105.2
- 5.0.0-beta.20105.2
- 5.0.0-beta.20105.2
- 5.0.0-beta.20105.2
- 5.0.0-beta.20105.2
- 5.0.0-beta.20105.2
- 2.5.1-beta.20105.2
- 5.0.0-beta.20105.2
- 5.0.0-beta.20105.2
- 5.0.0-beta.20105.2
+ 5.0.0-beta.20117.3
+ 5.0.0-beta.20117.3
+ 5.0.0-beta.20117.3
+ 5.0.0-beta.20117.3
+ 5.0.0-beta.20117.3
+ 5.0.0-beta.20117.3
+ 2.5.1-beta.20117.3
+ 5.0.0-beta.20117.3
+ 5.0.0-beta.20117.3
+ 5.0.0-beta.20117.3
5.0.0-alpha.1.20080.9
5.0.0-alpha.1.20080.9
@@ -120,9 +122,16 @@
2.1.26
4.12.0
- 3.0.0-preview9-190909-1
+ 3.1.0-preview-20200129.1
- 0.1.6-prerelease.19567.1
+ 0.1.6-prerelease.20117.1
+
+ 6.0.1-alpha.1.20078.4
+ 6.0.1-alpha.1.20078.4
+ 6.0.1-alpha.1.20078.4
+ 6.0.1-alpha.1.20078.4
+ 6.0.1-alpha.1.20078.4
+ 6.0.1-alpha.1.20078.4
diff --git a/eng/build.ps1 b/eng/build.ps1
index 81c417a34e72d7..cf9297f833999a 100644
--- a/eng/build.ps1
+++ b/eng/build.ps1
@@ -14,21 +14,24 @@ Param(
[string]$arch,
[string]$subsetCategory,
[string]$subset,
- [string]$runtimeConfiguration,
- [string]$librariesConfiguration,
+ [ValidateSet("Debug","Release","Checked")][string]$runtimeConfiguration,
+ [ValidateSet("Debug","Release")][string]$librariesConfiguration,
[Parameter(ValueFromRemainingArguments=$true)][String[]]$properties
)
function Get-Help() {
Write-Host "Common settings:"
- Write-Host " -subset Build a subset, print available subsets with -subset help"
- Write-Host " -subsetCategory Build a subsetCategory, print available subsetCategories with -subset help"
- Write-Host " -os Build operating system: Windows_NT or Unix"
- Write-Host " -arch Build platform: x86, x64, arm or arm64"
- Write-Host " -configuration Build configuration: Debug or Release (short: -c)"
- Write-Host " -verbosity MSBuild verbosity: q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic] (short: -v)"
- Write-Host " -binaryLog Output binary log (short: -bl)"
- Write-Host " -help Print help and exit (short: -h)"
+ Write-Host " -subset Build a subset, print available subsets with -subset help"
+ Write-Host " -subsetCategory Build a subsetCategory, print available subsetCategories with -subset help"
+ Write-Host " -vs Open the solution with VS for Test Explorer support. Path or solution name (ie -vs Microsoft.CSharp)"
+ Write-Host " -os Build operating system: Windows_NT or Unix"
+ Write-Host " -arch Build platform: x86, x64, arm or arm64"
+ Write-Host " -configuration Build configuration: Debug, Release or [CoreCLR]Checked (short: -c)"
+ Write-Host " -runtimeConfiguration Runtime build configuration: Debug, Release or [CoreCLR]Checked"
+ Write-Host " -librariesConfiguration Libraries build configuration: Debug or Release"
+ Write-Host " -verbosity MSBuild verbosity: q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic] (short: -v)"
+ Write-Host " -binaryLog Output binary log (short: -bl)"
+ Write-Host " -help Print help and exit (short: -h)"
Write-Host ""
Write-Host "Actions (defaults to -restore -build):"
@@ -44,7 +47,6 @@ function Get-Help() {
Write-Host ""
Write-Host "Libraries settings:"
- Write-Host " -vs Open the solution with VS for Test Explorer support. Path or solution name (ie -vs Microsoft.CSharp)"
Write-Host " -framework Build framework: netcoreapp5.0 or net472 (short: -f)"
Write-Host " -coverage Collect code coverage when testing"
Write-Host " -testscope Scope tests, allowed values: innerloop, outerloop, all"
diff --git a/eng/build.sh b/eng/build.sh
index 4da7816215aba3..22577c6332ba75 100755
--- a/eng/build.sh
+++ b/eng/build.sh
@@ -21,8 +21,10 @@ usage()
echo " --subsetCategory Build a subsetCategory, print available subsetCategories with -subset help"
echo " --os Build operating system: Windows_NT or Unix"
echo " --arch Build platform: x86, x64, arm or arm64"
- echo " --configuration Build configuration: Debug or Release (short: -c)"
- echo " --verbosity MSBuild verbosity: q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic] (short: -v)"
+ echo " --configuration Build configuration: Debug, Release or [CoreCLR]Checked (short: -c)"
+ echo " --runtimeConfiguration Runtime build configuration: Debug, Release or [CoreCLR]Checked"
+ echo " --librariesConfiguration Libraries build configuration: Debug or Release"
+ echo " --verbosity MSBuild verbosity: q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic] (short: -v)"
echo " --binaryLog Output binary log (short: -bl)"
echo " --cross Optional argument to signify cross compilation"
echo " --help Print help and exit (short: -h)"
@@ -41,7 +43,7 @@ usage()
echo ""
echo "Libraries settings:"
- echo " --framework Build framework: netcoreapp or net472 (short: -f)"
+ echo " --framework Build framework: netcoreapp5.0 or net472 (short: -f)"
echo " --coverage Collect code coverage when testing"
echo " --testscope Test scope, allowed values: innerloop, outerloop, all"
echo " --allconfigurations Build packages for all build configurations"
diff --git a/eng/common/cross/toolchain.cmake b/eng/common/cross/toolchain.cmake
index 0eea7d1df3e413..556da2e1355f7f 100644
--- a/eng/common/cross/toolchain.cmake
+++ b/eng/common/cross/toolchain.cmake
@@ -71,7 +71,17 @@ endif()
if(TARGET_ARCH_NAME MATCHES "^(arm|armel)$")
add_compile_options(-mthumb)
- add_compile_options(-mfpu=vfpv3)
+ if (NOT DEFINED CLR_ARM_FPU_TYPE)
+ set (CLR_ARM_FPU_TYPE vfpv3)
+ endif (NOT DEFINED CLR_ARM_FPU_TYPE)
+
+ add_compile_options (-mfpu=${CLR_ARM_FPU_TYPE})
+ if (NOT DEFINED CLR_ARM_FPU_CAPABILITY)
+ set (CLR_ARM_FPU_CAPABILITY 0x7)
+ endif (NOT DEFINED CLR_ARM_FPU_CAPABILITY)
+
+ add_definitions (-DCLR_ARM_FPU_CAPABILITY=${CLR_ARM_FPU_CAPABILITY})
+
if(TARGET_ARCH_NAME STREQUAL "armel")
add_compile_options(-mfloat-abi=softfp)
if(DEFINED TIZEN_TOOLCHAIN)
diff --git a/eng/common/performance/performance-setup.ps1 b/eng/common/performance/performance-setup.ps1
index a6916d25f00b08..e3376699294509 100644
--- a/eng/common/performance/performance-setup.ps1
+++ b/eng/common/performance/performance-setup.ps1
@@ -2,7 +2,7 @@ Param(
[string] $SourceDirectory=$env:BUILD_SOURCESDIRECTORY,
[string] $CoreRootDirectory,
[string] $BaselineCoreRootDirectory,
- [string] $Architecture=$env:archType,
+ [string] $Architecture="x64",
[string] $Framework="netcoreapp5.0",
[string] $CompilationMode="Tiered",
[string] $Repository=$env:BUILD_REPOSITORY_NAME,
@@ -50,7 +50,7 @@ if ($Internal) {
}
# FIX ME: This is a workaround until we get this from the actual pipeline
-$CommonSetupArguments="--channel master --queue $Queue --build-number $BuildNumber --build-configs $Configurations"
+$CommonSetupArguments="--channel master --queue $Queue --build-number $BuildNumber --build-configs $Configurations --architecture $Architecture"
$SetupArguments = "--repository https://github.com/$Repository --branch $Branch --get-perf-hash --commit-sha $CommitSha $CommonSetupArguments"
if ($RunFromPerformanceRepo) {
diff --git a/eng/common/performance/performance-setup.sh b/eng/common/performance/performance-setup.sh
index ba8bfc13dd768f..94a04e0fe5519e 100755
--- a/eng/common/performance/performance-setup.sh
+++ b/eng/common/performance/performance-setup.sh
@@ -3,7 +3,7 @@
source_directory=$BUILD_SOURCESDIRECTORY
core_root_directory=
baseline_core_root_directory=
-architecture=$archType
+architecture=x64
framework=netcoreapp5.0
compilation_mode=tiered
repository=$BUILD_REPOSITORY_NAME
@@ -164,7 +164,7 @@ if [[ "$internal" == true ]]; then
fi
fi
-common_setup_arguments="--channel master --queue $queue --build-number $build_number --build-configs $configurations"
+common_setup_arguments="--channel master --queue $queue --build-number $build_number --build-configs $configurations --architecture $architecture"
setup_arguments="--repository https://github.com/$repository --branch $branch --get-perf-hash --commit-sha $commit_sha $common_setup_arguments"
if [[ "$run_from_perf_repo" = true ]]; then
diff --git a/eng/common/post-build/darc-gather-drop.ps1 b/eng/common/post-build/darc-gather-drop.ps1
deleted file mode 100644
index 81ff2a437769be..00000000000000
--- a/eng/common/post-build/darc-gather-drop.ps1
+++ /dev/null
@@ -1,44 +0,0 @@
-param(
- [Parameter(Mandatory=$true)][int] $BarBuildId, # ID of the build which assets should be downloaded
- [Parameter(Mandatory=$true)][string] $DropLocation, # Where the assets should be downloaded to
- [Parameter(Mandatory=$true)][string] $MaestroApiAccessToken, # Token used to access Maestro API
- [Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = 'https://maestro-prod.westus2.cloudapp.azure.com', # Maestro API URL
- [Parameter(Mandatory=$false)][string] $MaestroApiVersion = '2019-01-16' # Version of Maestro API to use
-)
-
-try {
- . $PSScriptRoot\post-build-utils.ps1
-
- Write-Host 'Installing DARC ...'
-
- . $PSScriptRoot\..\darc-init.ps1
- $exitCode = $LASTEXITCODE
-
- if ($exitCode -ne 0) {
- Write-PipelineTelemetryError -Category "Darc" -Message "Something failed while running 'darc-init.ps1'. Check for errors above. Exiting now..."
- ExitWithExitCode $exitCode
- }
-
- # For now, only use a dry run.
- # Ideally we would change darc to enable a quick request that
- # would check whether the file exists that you can download it,
- # and that it won't conflict with other files.
- # https://github.com/dotnet/arcade/issues/3674
- # Right now we can't remove continue-on-error because we ocassionally will have
- # dependencies that have no associated builds (e.g. an old dependency).
- # We need to add an option to baseline specific dependencies away, or add them manually
- # to the BAR.
- darc gather-drop --non-shipping `
- --dry-run `
- --continue-on-error `
- --id $BarBuildId `
- --output-dir $DropLocation `
- --bar-uri $MaestroApiEndpoint `
- --password $MaestroApiAccessToken `
- --latest-location
-}
-catch {
- Write-Host $_.ScriptStackTrace
- Write-PipelineTelemetryError -Category "Darc" -Message $_
- ExitWithExitCode 1
-}
diff --git a/eng/common/post-build/nuget-validation.ps1 b/eng/common/post-build/nuget-validation.ps1
index 3d6129d72b0710..dab3534ab53893 100644
--- a/eng/common/post-build/nuget-validation.ps1
+++ b/eng/common/post-build/nuget-validation.ps1
@@ -9,7 +9,7 @@ param(
try {
. $PSScriptRoot\post-build-utils.ps1
- $url = 'https://raw.githubusercontent.com/NuGet/NuGetGallery/jver-verify/src/VerifyMicrosoftPackage/verify.ps1'
+ $url = 'https://raw.githubusercontent.com/NuGet/NuGetGallery/3e25ad135146676bcab0050a516939d9958bfa5d/src/VerifyMicrosoftPackage/verify.ps1'
New-Item -ItemType 'directory' -Path ${ToolDestinationPath} -Force
diff --git a/eng/common/templates/post-build/channels/generic-internal-channel.yml b/eng/common/templates/post-build/channels/generic-internal-channel.yml
index 29d8d46ee21842..380122901d0da8 100644
--- a/eng/common/templates/post-build/channels/generic-internal-channel.yml
+++ b/eng/common/templates/post-build/channels/generic-internal-channel.yml
@@ -46,7 +46,7 @@ stages:
buildId: $(AzDOBuildId)
downloadType: 'specific'
itemPattern: |
- PDBArtifacts/**
+ PdbArtifacts/**
BlobArtifacts/**
downloadPath: '$(Build.ArtifactStagingDirectory)'
diff --git a/eng/common/templates/post-build/channels/generic-public-channel.yml b/eng/common/templates/post-build/channels/generic-public-channel.yml
index 883e033c80236b..ae8c6349d49b9f 100644
--- a/eng/common/templates/post-build/channels/generic-public-channel.yml
+++ b/eng/common/templates/post-build/channels/generic-public-channel.yml
@@ -46,7 +46,7 @@ stages:
buildId: $(AzDOBuildId)
downloadType: 'specific'
itemPattern: |
- PDBArtifacts/**
+ PdbArtifacts/**
BlobArtifacts/**
downloadPath: '$(Build.ArtifactStagingDirectory)'
diff --git a/eng/common/templates/post-build/darc-gather-drop.yml b/eng/common/templates/post-build/darc-gather-drop.yml
deleted file mode 100644
index 3268ccaa551397..00000000000000
--- a/eng/common/templates/post-build/darc-gather-drop.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-parameters:
- ChannelId: 0
-
-jobs:
-- job: gatherDrop
- displayName: Gather Drop
- dependsOn: setupMaestroVars
- condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', ${{ parameters.ChannelId }}))
- variables:
- - name: BARBuildId
- value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ]
- pool:
- vmImage: 'windows-2019'
- steps:
- - task: PowerShell@2
- displayName: Darc gather-drop
- inputs:
- filePath: $(Build.SourcesDirectory)/eng/common/post-build/darc-gather-drop.ps1
- arguments: -BarBuildId $(BARBuildId)
- -DropLocation $(Agent.BuildDirectory)/Temp/Drop/
- -MaestroApiAccessToken $(MaestroApiAccessToken)
- -MaestroApiEndPoint $(MaestroApiEndPoint)
- -MaestroApiVersion $(MaestroApiVersion)
diff --git a/eng/common/templates/post-build/post-build.yml b/eng/common/templates/post-build/post-build.yml
index 70cb65f50b48b2..eff0d9ac7983d1 100644
--- a/eng/common/templates/post-build/post-build.yml
+++ b/eng/common/templates/post-build/post-build.yml
@@ -170,6 +170,32 @@ stages:
shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json'
symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-symbols/nuget/v3/index.json'
+- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
+ parameters:
+ artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
+ dependsOn: ${{ parameters.publishDependsOn }}
+ publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
+ symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
+ stageName: 'Net5_Preview1_Publish'
+ channelName: '.NET 5 Preview 1'
+ channelId: 737
+ transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-transport/nuget/v3/index.json'
+ shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json'
+ symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-symbols/nuget/v3/index.json'
+
+- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
+ parameters:
+ artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
+ dependsOn: ${{ parameters.publishDependsOn }}
+ publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
+ symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
+ stageName: 'Net5_Preview2_Publish'
+ channelName: '.NET 5 Preview 2'
+ channelId: 738
+ transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-transport/nuget/v3/index.json'
+ shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json'
+ symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-symbols/nuget/v3/index.json'
+
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
parameters:
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1
index d3a432878e2167..a45302b377f2bc 100644
--- a/eng/common/tools.ps1
+++ b/eng/common/tools.ps1
@@ -155,12 +155,12 @@ function InitializeDotNetCli([bool]$install, [bool]$createSdkLocationFile) {
# The following code block is protecting against concurrent access so that this function can
# be called in parallel.
if ($createSdkLocationFile) {
- do {
+ do {
$sdkCacheFileTemp = Join-Path $ToolsetDir $([System.IO.Path]::GetRandomFileName())
- }
+ }
until (!(Test-Path $sdkCacheFileTemp))
Set-Content -Path $sdkCacheFileTemp -Value $dotnetRoot
-
+
try {
Rename-Item -Force -Path $sdkCacheFileTemp 'sdk.txt'
} catch {
@@ -188,7 +188,33 @@ function GetDotNetInstallScript([string] $dotnetRoot) {
if (!(Test-Path $installScript)) {
Create-Directory $dotnetRoot
$ProgressPreference = 'SilentlyContinue' # Don't display the console progress UI - it's a huge perf hit
- Invoke-WebRequest "https://dot.net/$dotnetInstallScriptVersion/dotnet-install.ps1" -OutFile $installScript
+
+ $maxRetries = 5
+ $retries = 1
+
+ $uri = "https://dot.net/$dotnetInstallScriptVersion/dotnet-install.ps1"
+
+ while($true) {
+ try {
+ Write-Host "GET $uri"
+ Invoke-WebRequest $uri -OutFile $installScript
+ break
+ }
+ catch {
+ Write-Host "Failed to download '$uri'"
+ Write-Error $_.Exception.Message -ErrorAction Continue
+ }
+
+ if (++$retries -le $maxRetries) {
+ $delayInSeconds = [math]::Pow(2, $retries) - 1 # Exponential backoff
+ Write-Host "Retrying. Waiting for $delayInSeconds seconds before next attempt ($retries of $maxRetries)."
+ Start-Sleep -Seconds $delayInSeconds
+ }
+ else {
+ throw "Unable to download file in $maxRetries attempts."
+ }
+
+ }
}
return $installScript
@@ -198,12 +224,12 @@ function InstallDotNetSdk([string] $dotnetRoot, [string] $version, [string] $arc
InstallDotNet $dotnetRoot $version $architecture
}
-function InstallDotNet([string] $dotnetRoot,
- [string] $version,
- [string] $architecture = '',
- [string] $runtime = '',
- [bool] $skipNonVersionedFiles = $false,
- [string] $runtimeSourceFeed = '',
+function InstallDotNet([string] $dotnetRoot,
+ [string] $version,
+ [string] $architecture = '',
+ [string] $runtime = '',
+ [bool] $skipNonVersionedFiles = $false,
+ [string] $runtimeSourceFeed = '',
[string] $runtimeSourceFeedKey = '') {
$installScript = GetDotNetInstallScript $dotnetRoot
@@ -298,7 +324,7 @@ function InitializeVisualStudioMSBuild([bool]$install, [object]$vsRequirements =
$vsMajorVersion = $vsMinVersion.Major
$xcopyMSBuildVersion = "$vsMajorVersion.$($vsMinVersion.Minor).0-alpha"
}
-
+
$vsInstallDir = $null
if ($xcopyMSBuildVersion.Trim() -ine "none") {
$vsInstallDir = InitializeXCopyMSBuild $xcopyMSBuildVersion $install
@@ -373,7 +399,12 @@ function LocateVisualStudio([object]$vsRequirements = $null){
if (!(Test-Path $vsWhereExe)) {
Create-Directory $vsWhereDir
Write-Host 'Downloading vswhere'
- Invoke-WebRequest "https://github.com/Microsoft/vswhere/releases/download/$vswhereVersion/vswhere.exe" -OutFile $vswhereExe
+ try {
+ Invoke-WebRequest "https://netcorenativeassets.blob.core.windows.net/resource-packages/external/windows/vswhere/$vswhereVersion/vswhere.exe" -OutFile $vswhereExe
+ }
+ catch {
+ Write-PipelineTelemetryError -Category 'InitializeToolset' -Message $_
+ }
}
if (!$vsRequirements) { $vsRequirements = $GlobalJson.tools.vs }
diff --git a/eng/common/tools.sh b/eng/common/tools.sh
index e071af4ee494e9..664ac1055bd0c0 100755
--- a/eng/common/tools.sh
+++ b/eng/common/tools.sh
@@ -41,7 +41,7 @@ fi
# Configures warning treatment in msbuild.
warn_as_error=${warn_as_error:-true}
-# True to attempt using .NET Core already that meets requirements specified in global.json
+# True to attempt using .NET Core already that meets requirements specified in global.json
# installed on the machine instead of downloading one.
use_installed_dotnet_cli=${use_installed_dotnet_cli:-true}
@@ -172,7 +172,7 @@ function InstallDotNetSdk {
function InstallDotNet {
local root=$1
local version=$2
-
+
GetDotNetInstallScript "$root"
local install_script=$_GetDotNetInstallScript
@@ -218,6 +218,28 @@ function InstallDotNet {
}
}
+function with_retries {
+ local maxRetries=5
+ local retries=1
+ echo "Trying to run '$@' for maximum of $maxRetries attempts."
+ while [[ $((retries++)) -le $maxRetries ]]; do
+ "$@"
+
+ if [[ $? == 0 ]]; then
+ echo "Ran '$@' successfully."
+ return 0
+ fi
+
+ timeout=$((2**$retries-1))
+ echo "Failed to execute '$@'. Waiting $timeout seconds before next attempt ($retries out of $maxRetries)." 1>&2
+ sleep $timeout
+ done
+
+ echo "Failed to execute '$@' for $maxRetries times." 1>&2
+
+ return 1
+}
+
function GetDotNetInstallScript {
local root=$1
local install_script="$root/dotnet-install.sh"
@@ -230,13 +252,13 @@ function GetDotNetInstallScript {
# Use curl if available, otherwise use wget
if command -v curl > /dev/null; then
- curl "$install_script_url" -sSL --retry 10 --create-dirs -o "$install_script" || {
+ with_retries curl "$install_script_url" -sSL --retry 10 --create-dirs -o "$install_script" || {
local exit_code=$?
Write-PipelineTelemetryError -category 'InitializeToolset' "Failed to acquire dotnet install script (exit code '$exit_code')."
ExitWithExitCode $exit_code
}
- else
- wget -q -O "$install_script" "$install_script_url" || {
+ else
+ with_retries wget -v -O "$install_script" "$install_script_url" || {
local exit_code=$?
Write-PipelineTelemetryError -category 'InitializeToolset' "Failed to acquire dotnet install script (exit code '$exit_code')."
ExitWithExitCode $exit_code
@@ -251,11 +273,11 @@ function InitializeBuildTool {
if [[ -n "${_InitializeBuildTool:-}" ]]; then
return
fi
-
+
InitializeDotNetCli $restore
# return values
- _InitializeBuildTool="$_InitializeDotNetCli/dotnet"
+ _InitializeBuildTool="$_InitializeDotNetCli/dotnet"
_InitializeBuildToolCommand="msbuild"
_InitializeBuildToolFramework="netcoreapp2.1"
}
@@ -319,7 +341,7 @@ function InitializeToolset {
if [[ "$binary_log" == true ]]; then
bl="/bl:$log_dir/ToolsetRestore.binlog"
fi
-
+
echo '' > "$proj"
MSBuild-Core "$proj" $bl /t:__WriteToolsetLocation /clp:ErrorsOnly\;NoSummary /p:__ToolsetLocationOutputFile="$toolset_location_file"
diff --git a/eng/illink.targets b/eng/illink.targets
index 59960f31aa19a7..ae2de5625865b8 100644
--- a/eng/illink.targets
+++ b/eng/illink.targets
@@ -10,7 +10,7 @@
$([MSBuild]::NormalizeDirectory('$(PkgILLink_Tasks)', 'tools'))
- $(ILLinkTasksDir)netcoreapp2.0/ILLink.Tasks.dll
+ $(ILLinkTasksDir)netcoreapp3.0/ILLink.Tasks.dll
$(ILLinkTasksDir)$(NetFrameworkCurrent)/ILLink.Tasks.dll
$(IntermediateOutputPath)$(TargetName)$(TargetExt)
$(IntermediateOutputPath)$(TargetName).pdb
@@ -83,6 +83,8 @@
$(ILLinkArgs) --skip-unresolved true
$(ILLinkArgs) --disable-opt unusedinterfaces
+
+ $(ILLinkArgs) --disable-opt ipconstprop
$(ILLinkArgs) --keep-dep-attributes true
diff --git a/eng/native/build-commons.sh b/eng/native/build-commons.sh
index ed3362c0a31c8c..8707e3b6d70420 100755
--- a/eng/native/build-commons.sh
+++ b/eng/native/build-commons.sh
@@ -27,7 +27,7 @@ isMSBuildOnNETCoreSupported()
return
fi
- if [[ ( "$__HostOS" == "Linux" ) && ( "$__HostArch" == "x64" || "$__HostArch" == "arm" || "$__HostArch" == "arm64" ) ]]; then
+ if [[ ( "$__HostOS" == "Linux" ) && ( "$__HostArch" == "x64" || "$__HostArch" == "arm" || "$__HostArch" == "armel" || "$__HostArch" == "arm64" ) ]]; then
__IsMSBuildOnNETCoreSupported=1
elif [[ ( "$__HostOS" == "OSX" || "$__HostOS" == "FreeBSD" ) && "$__HostArch" == "x64" ]]; then
__IsMSBuildOnNETCoreSupported=1
@@ -213,8 +213,13 @@ case "$CPUName" in
;;
armv7l)
- __BuildArch=arm
- __HostArch=arm
+ if (NAME=""; . /etc/os-release; test "$NAME" = "Tizen"); then
+ __BuildArch=armel
+ __HostArch=armel
+ else
+ __BuildArch=arm
+ __HostArch=arm
+ fi
;;
i686)
diff --git a/eng/native/configureplatform.cmake b/eng/native/configureplatform.cmake
index c1b627f5f9dd74..29f4f85436ba88 100644
--- a/eng/native/configureplatform.cmake
+++ b/eng/native/configureplatform.cmake
@@ -137,7 +137,7 @@ if(CLR_CMAKE_HOST_UNIX_ARM)
set(CLR_CMAKE_HOST_ARCH_ARM 1)
set(CLR_CMAKE_HOST_ARCH "arm")
- if(CLR_CMAKE_HOST_HOST_ARMV7L)
+ if(CLR_CMAKE_HOST_UNIX_ARMV7L)
set(CLR_CMAKE_HOST_ARCH_ARMV7L 1)
endif()
elseif(CLR_CMAKE_HOST_UNIX_ARM64)
@@ -169,6 +169,12 @@ endif()
# if target arch is not specified then host & target are same
if(NOT DEFINED CLR_CMAKE_TARGET_ARCH OR CLR_CMAKE_TARGET_ARCH STREQUAL "" )
set(CLR_CMAKE_TARGET_ARCH ${CLR_CMAKE_HOST_ARCH})
+
+ # This is required for "arm" targets (CMAKE_SYSTEM_PROCESSOR "armv7l"),
+ # for which this flag otherwise won't be set up below
+ if (CLR_CMAKE_HOST_ARCH_ARMV7L)
+ set(CLR_CMAKE_TARGET_ARCH_ARMV7L 1)
+ endif()
endif()
# Set target architecture variables
@@ -182,6 +188,7 @@ if (CLR_CMAKE_TARGET_ARCH STREQUAL x64)
set(CLR_CMAKE_TARGET_ARCH_ARM 1)
elseif(CLR_CMAKE_TARGET_ARCH STREQUAL armel)
set(CLR_CMAKE_TARGET_ARCH_ARM 1)
+ set(CLR_CMAKE_TARGET_ARCH_ARMV7L 1)
set(ARM_SOFTFP 1)
else()
clr_unknown_arch()
diff --git a/eng/native/gen-buildsys.sh b/eng/native/gen-buildsys.sh
index ae2e0eb2d0bd5c..4e39d16e8243b4 100755
--- a/eng/native/gen-buildsys.sh
+++ b/eng/native/gen-buildsys.sh
@@ -25,98 +25,15 @@ fi
tryrun_dir="$2"
build_arch="$4"
compiler="$5"
-cxxCompiler="$compiler++"
majorVersion="$6"
minorVersion="$7"
-if [[ "$compiler" == "gcc" ]]; then cxxCompiler="g++"; fi
-
-check_version_exists() {
- desired_version=-1
-
- # Set up the environment to be used for building with the desired compiler.
- if command -v "$compiler-$1.$2" > /dev/null; then
- desired_version="-$1.$2"
- elif command -v "$compier$1$2" > /dev/null; then
- desired_version="$1$2"
- elif command -v "$compiler-$1$2" > /dev/null; then
- desired_version="-$1$2"
- fi
-
- echo "$desired_version"
-}
-
-if [[ -z "$CLR_CC" ]]; then
-
- # Set default versions
- if [[ -z "$majorVersion" ]]; then
- # note: gcc (all versions) and clang versions higher than 6 do not have minor version in file name, if it is zero.
- if [[ "$compiler" == "clang" ]]; then versions=( 9 8 7 6.0 5.0 4.0 3.9 3.8 3.7 3.6 3.5 )
- elif [[ "$compiler" == "gcc" ]]; then versions=( 9 8 7 6 5 4.9 ); fi
-
- for version in "${versions[@]}"; do
- parts=(${version//./ })
- desired_version="$(check_version_exists "${parts[0]}" "${parts[1]}")"
- if [[ "$desired_version" != "-1" ]]; then majorVersion="${parts[0]}"; break; fi
- done
-
- if [[ -z "$majorVersion" ]]; then
- if command -v "$compiler" > /dev/null; then
- if [[ "$(uname)" != "Darwin" ]]; then
- echo "WARN: Specific version of $compiler not found, falling back to use the one in PATH."
- fi
- CC="$(command -v "$compiler")"
- CXX="$(command -v "$cxxCompiler")"
- else
- echo "ERROR: No usable version of $compiler found."
- exit 1
- fi
- else
- if [[ "$compiler" == "clang" && "$majorVersion" -lt 5 ]]; then
- if [[ "$build_arch" == "arm" || "$build_arch" == "armel" ]]; then
- if command -v "$compiler" > /dev/null; then
- echo "WARN: Found clang version $majorVersion which is not supported on arm/armel architectures, falling back to use clang from PATH."
- CC="$(command -v "$compiler")"
- CXX="$(command -v "$cxxCompiler")"
- else
- echo "ERROR: Found clang version $majorVersion which is not supported on arm/armel architectures, and there is no clang in PATH."
- exit 1
- fi
- fi
- fi
- fi
- else
- desired_version="$(check_version_exists "$majorVersion" "$minorVersion")"
- if [[ "$desired_version" == "-1" ]]; then
- echo "ERROR: Could not find specific version of $compiler: $majorVersion $minorVersion."
- exit 1
- fi
- fi
-
- if [[ -z "$CC" ]]; then
- CC="$(command -v "$compiler$desired_version")"
- CXX="$(command -v "$cxxCompiler$desired_version")"
- if [[ -z "$CXX" ]]; then CXX="$(command -v "$cxxCompiler")"; fi
- fi
-else
- if [[ ! -f "$CLR_CC" ]]; then
- echo "ERROR: CLR_CC is set but path '$CLR_CC' does not exist"
- exit 1
- fi
- CC="$CLR_CC"
- CXX="$CLR_CXX"
-fi
-
-if [[ -z "$CC" ]]; then
- echo "ERROR: Unable to find $compiler."
- exit 1
-fi
+source "$scriptroot/init-compiler.sh" "$build_arch" "$compiler" "$majorVersion" "$minorVersion"
CCC_CC="$CC"
CCC_CXX="$CXX"
-SCAN_BUILD_COMMAND="$(command -v "scan-build$desired_version")"
-export CC CCC_CC CXX CCC_CXX SCAN_BUILD_COMMAND
+export CCC_CC CCC_CXX
buildtype=DEBUG
code_coverage=OFF
diff --git a/eng/native/init-compiler.sh b/eng/native/init-compiler.sh
new file mode 100755
index 00000000000000..ff0f69c6a00457
--- /dev/null
+++ b/eng/native/init-compiler.sh
@@ -0,0 +1,111 @@
+#!/usr/bin/env bash
+#
+# This file detects the C/C++ compiler and exports it to the CC/CXX environment variables
+#
+
+if [[ "$#" -lt 2 ]]; then
+ echo "Usage..."
+ echo "detect-compiler.sh "
+ echo "Specify the target architecture."
+ echo "Specify the name of compiler (clang or gcc)."
+ echo "Specify the major version of compiler."
+ echo "Specify the minor version of compiler."
+ exit 1
+fi
+
+build_arch="$1"
+compiler="$2"
+cxxCompiler="$compiler++"
+majorVersion="$3"
+minorVersion="$4"
+
+# clear the existing CC and CXX from environment
+CC=
+CXX=
+
+if [[ "$compiler" == "gcc" ]]; then cxxCompiler="g++"; fi
+
+check_version_exists() {
+ desired_version=-1
+
+ # Set up the environment to be used for building with the desired compiler.
+ if command -v "$compiler-$1.$2" > /dev/null; then
+ desired_version="-$1.$2"
+ elif command -v "$compiler$1$2" > /dev/null; then
+ desired_version="$1$2"
+ elif command -v "$compiler-$1$2" > /dev/null; then
+ desired_version="-$1$2"
+ fi
+
+ echo "$desired_version"
+}
+
+if [[ -z "$CLR_CC" ]]; then
+
+ # Set default versions
+ if [[ -z "$majorVersion" ]]; then
+ # note: gcc (all versions) and clang versions higher than 6 do not have minor version in file name, if it is zero.
+ if [[ "$compiler" == "clang" ]]; then versions=( 9 8 7 6.0 5.0 4.0 3.9 3.8 3.7 3.6 3.5 )
+ elif [[ "$compiler" == "gcc" ]]; then versions=( 9 8 7 6 5 4.9 ); fi
+
+ for version in "${versions[@]}"; do
+ parts=(${version//./ })
+ desired_version="$(check_version_exists "${parts[0]}" "${parts[1]}")"
+ if [[ "$desired_version" != "-1" ]]; then majorVersion="${parts[0]}"; break; fi
+ done
+
+ if [[ -z "$majorVersion" ]]; then
+ if command -v "$compiler" > /dev/null; then
+ if [[ "$(uname)" != "Darwin" ]]; then
+ echo "WARN: Specific version of $compiler not found, falling back to use the one in PATH."
+ fi
+ CC="$(command -v "$compiler")"
+ CXX="$(command -v "$cxxCompiler")"
+ else
+ echo "ERROR: No usable version of $compiler found."
+ exit 1
+ fi
+ else
+ if [[ "$compiler" == "clang" && "$majorVersion" -lt 5 ]]; then
+ if [[ "$build_arch" == "arm" || "$build_arch" == "armel" ]]; then
+ if command -v "$compiler" > /dev/null; then
+ echo "WARN: Found clang version $majorVersion which is not supported on arm/armel architectures, falling back to use clang from PATH."
+ CC="$(command -v "$compiler")"
+ CXX="$(command -v "$cxxCompiler")"
+ else
+ echo "ERROR: Found clang version $majorVersion which is not supported on arm/armel architectures, and there is no clang in PATH."
+ exit 1
+ fi
+ fi
+ fi
+ fi
+ else
+ desired_version="$(check_version_exists "$majorVersion" "$minorVersion")"
+ if [[ "$desired_version" == "-1" ]]; then
+ echo "ERROR: Could not find specific version of $compiler: $majorVersion $minorVersion."
+ exit 1
+ fi
+ fi
+
+ if [[ -z "$CC" ]]; then
+ CC="$(command -v "$compiler$desired_version")"
+ CXX="$(command -v "$cxxCompiler$desired_version")"
+ if [[ -z "$CXX" ]]; then CXX="$(command -v "$cxxCompiler")"; fi
+ fi
+else
+ if [[ ! -f "$CLR_CC" ]]; then
+ echo "ERROR: CLR_CC is set but path '$CLR_CC' does not exist"
+ exit 1
+ fi
+ CC="$CLR_CC"
+ CXX="$CLR_CXX"
+fi
+
+if [[ -z "$CC" ]]; then
+ echo "ERROR: Unable to find $compiler."
+ exit 1
+fi
+
+SCAN_BUILD_COMMAND="$(command -v "scan-build$desired_version")"
+
+export CC CXX SCAN_BUILD_COMMAND
diff --git a/eng/outerBuild.targets b/eng/outerBuild.targets
new file mode 100644
index 00000000000000..dd546d6bd6f6bc
--- /dev/null
+++ b/eng/outerBuild.targets
@@ -0,0 +1,8 @@
+
+
+
+
+
+
diff --git a/eng/packaging.props b/eng/packaging.props
index a7eb2fa7b041a5..23725665e24102 100644
--- a/eng/packaging.props
+++ b/eng/packaging.props
@@ -12,7 +12,7 @@
x64
- $(NuGetPackageRoot)$(MicrosoftPrivateIntellisensePackage)/$(MicrosoftPrivateIntellisenseVersion)/xmldocs/netcoreapp
+ $(NuGetPackageRoot)$(MicrosoftPrivateIntellisensePackage)/$(MicrosoftPrivateIntellisenseVersion)/IntellisenseFiles/netcoreapp
diff --git a/eng/pipelines/common/global-build-job.yml b/eng/pipelines/common/global-build-job.yml
index 89f8f929f033f6..b6c357f4563b08 100644
--- a/eng/pipelines/common/global-build-job.yml
+++ b/eng/pipelines/common/global-build-job.yml
@@ -19,10 +19,18 @@ jobs:
pool: ${{ parameters.pool }}
container: ${{ parameters.container }}
timeoutInMinutes: ${{ parameters.timeoutInMinutes }}
- variables: ${{ parameters.variables }}
workspace:
clean: all
+ variables:
+ - ${{ each variable in parameters.variables }}:
+ - ${{insert}}: ${{ variable }}
+ - name: noWarnAsErrorArg
+ value: ''
+ - ${{ if eq(parameters.osGroup, 'Windows_NT') }}:
+ - name: noWarnAsErrorArg
+ value: -warnAsError:0
+
steps:
- ${{ if eq(parameters.osGroup, 'OSX') }}:
- script: |
@@ -37,7 +45,7 @@ jobs:
- template: /eng/pipelines/common/clone-checkout-bundle-step.yml
# Build
- - script: $(Build.SourcesDirectory)$(dir)build$(scriptExt) -ci -arch ${{ parameters.archType }} ${{ parameters.buildArgs }}
+ - script: $(Build.SourcesDirectory)$(dir)build$(scriptExt) -ci -arch ${{ parameters.archType }} $(noWarnAsErrorArg) ${{ parameters.buildArgs }}
displayName: Build product
- task: PublishBuildArtifacts@1
diff --git a/eng/pipelines/coreclr/perf.yml b/eng/pipelines/coreclr/perf.yml
index aceeb78ed1cbf7..ffa22b8afc7515 100644
--- a/eng/pipelines/coreclr/perf.yml
+++ b/eng/pipelines/coreclr/perf.yml
@@ -22,7 +22,27 @@ trigger:
- eng/pipelines/libraries/*
-pr: none
+pr:
+ branches:
+ include:
+ - master
+ paths:
+ include:
+ - '*'
+ - src/libraries/System.Private.CoreLib/*
+ exclude:
+ - docs/*
+ - CODE-OF-CONDUCT.md
+ - CONTRIBUTING.md
+ - LICENSE.TXT
+ - PATENTS.TXT
+ - README.md
+ - SECURITY.md
+ - THIRD-PARTY-NOTICES.TXT
+ - src/installer/*
+ - src/libraries/*
+ - eng/pipelines/installer/*
+ - eng/pipelines/libraries/*
jobs:
#
diff --git a/eng/pipelines/coreclr/templates/build-job.yml b/eng/pipelines/coreclr/templates/build-job.yml
index 2bef6d6c695a5f..34af82b3900e34 100644
--- a/eng/pipelines/coreclr/templates/build-job.yml
+++ b/eng/pipelines/coreclr/templates/build-job.yml
@@ -136,12 +136,11 @@ jobs:
- powershell: eng\common\build.ps1 -ci -sign -restore -configuration:$(buildConfig) -warnaserror:0 /p:ArcadeBuild=true /p:OfficialBuild=true /p:BuildOS=$(osGroup) /p:BuildArch=$(archType) /p:BuildType=$(_BuildConfig) /p:DotNetSignType=$env:_SignType -projects $(Build.SourcesDirectory)\eng\empty.csproj
displayName: Sign Binaries
- - task: PublishBuildArtifacts@1
+ - task: PublishPipelineArtifact@1
displayName: Publish Signing Logs
inputs:
- PathtoPublish: '$(Build.SourcesDirectory)/artifacts/log/'
- PublishLocation: Container
- ArtifactName: ${{ format('SignLogs_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }}
+ targetPath: '$(Build.SourcesDirectory)/artifacts/log/'
+ artifactName: ${{ format('SignLogs_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }}
continueOnError: true
condition: always()
@@ -205,10 +204,10 @@ jobs:
NUGET_PACKAGES: $(Build.SourcesDirectory)\.packages
# Publish Logs
- - task: PublishBuildArtifacts@1
+ - task: PublishPipelineArtifact@1
displayName: Publish Logs
inputs:
- pathtoPublish: $(Build.SourcesDirectory)/artifacts/log
+ targetPath: $(Build.SourcesDirectory)/artifacts/log
artifactName: 'BuildLogs_CoreCLR_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)'
continueOnError: true
condition: always()
diff --git a/eng/pipelines/coreclr/templates/build-test-job.yml b/eng/pipelines/coreclr/templates/build-test-job.yml
index 81f9f3113ea79a..59f06f78211a2b 100644
--- a/eng/pipelines/coreclr/templates/build-test-job.yml
+++ b/eng/pipelines/coreclr/templates/build-test-job.yml
@@ -139,10 +139,10 @@ jobs:
# Publish Logs
- - task: PublishBuildArtifacts@1
+ - task: PublishPipelineArtifact@1
displayName: Publish Logs
inputs:
- pathtoPublish: $(Build.SourcesDirectory)/artifacts/log
+ targetPath: $(Build.SourcesDirectory)/artifacts/log
artifactName: 'TestBuildLogs_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)_${{ parameters.testGroup }}'
continueOnError: true
condition: always()
diff --git a/eng/pipelines/coreclr/templates/crossgen-comparison-job.yml b/eng/pipelines/coreclr/templates/crossgen-comparison-job.yml
index db45c6b70d11ed..5ba62d0032f499 100644
--- a/eng/pipelines/coreclr/templates/crossgen-comparison-job.yml
+++ b/eng/pipelines/coreclr/templates/crossgen-comparison-job.yml
@@ -176,7 +176,7 @@ jobs:
--diff_dir %HELIX_WORKITEM_PAYLOAD%\log\$(targetFlavor)
# Publish log
- - task: PublishBuildArtifacts@1
+ - task: PublishPipelineArtifact@1
displayName: Publish log
inputs:
pathtoPublish: $(artifactsDirectory)/log
diff --git a/eng/pipelines/coreclr/templates/helix-queues-setup.yml b/eng/pipelines/coreclr/templates/helix-queues-setup.yml
index c48c793b5c5e9a..12fb8ad042b3c5 100644
--- a/eng/pipelines/coreclr/templates/helix-queues-setup.yml
+++ b/eng/pipelines/coreclr/templates/helix-queues-setup.yml
@@ -116,18 +116,16 @@ jobs:
# Windows_NT arm
- ${{ if eq(parameters.platform, 'Windows_NT_arm') }}:
- # Currently down as there's no suitable ARM32 pool at the moment, tracked under
- # https://github.com/dotnet/runtime/issues/1097
- # https://github.com/dotnet/runtime/issues/1663
- # https://github.com/dotnet/core-eng/issues/8490
- # - ${{ if and(eq(variables['System.TeamProject'], 'public'), in(parameters.jobParameters.helixQueueGroup, 'pr', 'ci', 'libraries')) }}:
- # - Windows.10.Arm64.Open
+ # Currently blocked by https://github.com/dotnet/runtime/issues/32320
+ # - ${{ if and(eq(variables['System.TeamProject'], 'public'), in(parameters.jobParameters.helixQueueGroup, 'pr', 'ci', 'libraries')) }}:
+ # - Windows.10.Arm64v8.Open
- ${{ if eq(variables['System.TeamProject'], 'internal') }}:
- Windows.10.Arm64
# Windows_NT arm64
- ${{ if eq(parameters.platform, 'Windows_NT_arm64') }}:
- # TODO: Consider adding Windows.10.Arm64.Open here if capacity is enough for handling both Windows_NT/arm and Windows_NT/arm64 testing
+ - ${{ if and(eq(variables['System.TeamProject'], 'public'), in(parameters.jobParameters.helixQueueGroup, 'pr', 'ci', 'libraries')) }}:
+ - Windows.10.Arm64.Open
- ${{ if eq(variables['System.TeamProject'], 'internal') }}:
- Windows.10.Arm64
diff --git a/eng/pipelines/coreclr/templates/run-test-job.yml b/eng/pipelines/coreclr/templates/run-test-job.yml
index de04bc69914178..f6b54414d11ef9 100644
--- a/eng/pipelines/coreclr/templates/run-test-job.yml
+++ b/eng/pipelines/coreclr/templates/run-test-job.yml
@@ -380,10 +380,10 @@ jobs:
- jitelthookenabled_tiered
# Publish Logs
- - task: PublishBuildArtifacts@1
+ - task: PublishPipelineArtifact@1
displayName: Publish Logs
inputs:
- pathtoPublish: $(Build.SourcesDirectory)/artifacts/log
+ targetPath: $(Build.SourcesDirectory)/artifacts/log
artifactName: '$(LogNamePrefix)_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)_${{ parameters.testGroup }}'
continueOnError: true
condition: always()
diff --git a/eng/pipelines/installer/jobs/base-job.yml b/eng/pipelines/installer/jobs/base-job.yml
index 952a51eaac46f9..60e766303adc72 100644
--- a/eng/pipelines/installer/jobs/base-job.yml
+++ b/eng/pipelines/installer/jobs/base-job.yml
@@ -68,12 +68,8 @@ jobs:
eq(parameters.isOfficialBuild, true),
ne(parameters.crossrootfsDir, '')) }}
- # TODO: (Consolidation) Enable test signing during PR validation. https://github.com/dotnet/runtime/issues/1026
- #
- # CoreCLR only produces the UCRT redist file in Release config. When the redist file isn't
- # present, signing fails. For now, only sign in official builds which only run Release mode.
- name: SignType
- value: ''
+ value: test
# Set up non-PR build from internal project
- ${{ if eq(parameters.isOfficialBuild, true) }}:
diff --git a/eng/pipelines/installer/jobs/steps/upload-job-artifacts.yml b/eng/pipelines/installer/jobs/steps/upload-job-artifacts.yml
index a9c1bdcb0dd9ef..05232836e569c5 100644
--- a/eng/pipelines/installer/jobs/steps/upload-job-artifacts.yml
+++ b/eng/pipelines/installer/jobs/steps/upload-job-artifacts.yml
@@ -33,10 +33,10 @@ steps:
continueOnError: true
condition: succeededOrFailed()
-- task: PublishBuildArtifacts@1
+- task: PublishPipelineArtifact@1
displayName: Publish BuildLogs
inputs:
- PathtoPublish: '$(Build.StagingDirectory)/BuildLogs'
- ArtifactName: Installer-Logs-${{ parameters.name }}-$(_BuildConfig)
+ targetPath: '$(Build.StagingDirectory)/BuildLogs'
+ artifactName: Installer-Logs-${{ parameters.name }}-$(_BuildConfig)
continueOnError: true
condition: succeededOrFailed()
diff --git a/eng/pipelines/libraries/base-job.yml b/eng/pipelines/libraries/base-job.yml
index 85ea99f75c30f5..0a7389aa23813a 100644
--- a/eng/pipelines/libraries/base-job.yml
+++ b/eng/pipelines/libraries/base-job.yml
@@ -102,6 +102,8 @@ jobs:
# Windows variables
- ${{ if eq(parameters.osGroup, 'Windows_NT') }}:
- _runtimeOSArg: /p:RuntimeOS=win10
+ # Remove when: https://github.com/dotnet/runtime/issues/31888 is fixed.
+ - _warnAsErrorArg: -warnAsError:0
# Non-Windows variables
- ${{ if ne(parameters.osGroup, 'Windows_NT') }}:
diff --git a/eng/pipelines/libraries/build-job.yml b/eng/pipelines/libraries/build-job.yml
index 346be74f29ff92..4f95464e683df5 100644
--- a/eng/pipelines/libraries/build-job.yml
+++ b/eng/pipelines/libraries/build-job.yml
@@ -153,7 +153,8 @@ jobs:
inputs:
sourceFolder: $(Build.SourcesDirectory)/artifacts/packages
targetFolder: $(Build.ArtifactStagingDirectory)/artifacts/packages
-
+ condition: and(succeeded(), eq(variables['_librariesBuildProducedPackages'], true))
+
- task: CopyFiles@2
displayName: Prepare tmp assets to publish
inputs:
diff --git a/eng/pipelines/libraries/helix-queues-setup.yml b/eng/pipelines/libraries/helix-queues-setup.yml
index f15d9c2cf9d6f4..24bee99a968d0b 100644
--- a/eng/pipelines/libraries/helix-queues-setup.yml
+++ b/eng/pipelines/libraries/helix-queues-setup.yml
@@ -29,6 +29,8 @@ jobs:
- ${{ if eq(parameters.platform, 'Linux_arm64') }}:
- ${{ if eq(parameters.jobParameters.isFullMatrix, true) }}:
- (Ubuntu.1804.ArmArch.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-16.04-helix-arm64v8-bfcd90a-20200127194925
+ - ${{ if eq(parameters.jobParameters.isFullMatrix, false) }}:
+ - (Ubuntu.1804.ArmArch.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-16.04-helix-arm64v8-bfcd90a-20200127194925
# Linux musl x64
- ${{ if eq(parameters.platform, 'Linux_musl_x64') }}:
@@ -108,14 +110,16 @@ jobs:
# netcoreapp
- ${{ if notIn(parameters.jobParameters.framework, 'allConfigurations', 'net472') }}:
- ${{ if eq(parameters.jobParameters.isFullMatrix, true) }}:
- - Windows.7.Amd64.Open
- - Windows.81.Amd64.Open
+ # TODO: Reopen when https://github.com/dotnet/runtime/issues/32231 is fixed
+ #- Windows.7.Amd64.Open
+ #- Windows.81.Amd64.Open
- Windows.10.Amd64.ServerRS5.Open
- Windows.10.Amd64.Server19H1.Open
- ${{ if eq(parameters.jobParameters.isFullMatrix, false) }}:
- ${{ if eq(parameters.jobParameters.buildConfig, 'Release') }}:
- - Windows.7.Amd64.Open
- - Windows.81.Amd64.Open
+ # TODO: Reopen when https://github.com/dotnet/runtime/issues/32231 is fixed
+ #- Windows.7.Amd64.Open
+ #- Windows.81.Amd64.Open
- Windows.10.Amd64.Server19H1.ES.Open
- ${{ if eq(parameters.jobParameters.buildConfig, 'Debug') }}:
- Windows.10.Amd64.Server19H1.Open
diff --git a/eng/pipelines/libraries/run-test-job.yml b/eng/pipelines/libraries/run-test-job.yml
index e06b2b03d52e5b..2c6d1be9a66652 100644
--- a/eng/pipelines/libraries/run-test-job.yml
+++ b/eng/pipelines/libraries/run-test-job.yml
@@ -78,6 +78,7 @@ jobs:
/p:RuntimeFlavor=${{ parameters.runtimeFlavor }}
/p:ArchGroup=${{ parameters.archType }}
/p:Configuration=${{ parameters.buildConfig }}
+ /bl:$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)/overrideCoreclrFromLiveDrop.binlog
displayName: Override $(runtimeFlavorName) from live drop
- template: /eng/pipelines/libraries/helix.yml
diff --git a/eng/pipelines/mono/templates/build-job.yml b/eng/pipelines/mono/templates/build-job.yml
index 2b4f9c519d5518..a29c07e4c1170f 100644
--- a/eng/pipelines/mono/templates/build-job.yml
+++ b/eng/pipelines/mono/templates/build-job.yml
@@ -9,6 +9,8 @@ parameters:
variables: {}
pool: ''
condition: true
+ llvm: false
+ crossrootfsDir: ''
### Product build
jobs:
@@ -21,11 +23,20 @@ jobs:
helixType: 'build/product/'
enableMicrobuild: true
pool: ${{ parameters.pool }}
+ llvm: ${{ parameters.llvm }}
+ crossrootfsDir: ${{ parameters.crossroofsDir }}
condition: ${{ parameters.condition }}
# Compute job name from template parameters
- name: ${{ format('mono_product_build_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }}
- displayName: ${{ format('Mono Product Build {0}{1} {2} {3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }}
+ ${{ if ne(parameters.llvm, true) }}:
+ name: ${{ format('mono_product_build_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }}
+ displayName: ${{ format('Mono Product Build {0}{1} {2} {3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }}
+
+ # if LLVM enabled, set a variable we can consume
+ ${{ if eq(parameters.llvm, true) }}:
+ name: ${{ format('mono_llvm_product_build_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }}
+ displayName: ${{ format('Mono LLVM Product Build {0}{1} {2} {3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }}
+
# Run all steps in the container.
# Note that the containers are defined in platform-matrix.yml
@@ -58,10 +69,10 @@ jobs:
# Build
- ${{ if ne(parameters.osGroup, 'Windows_NT') }}:
- - script: ./mono$(scriptExt) -configuration $(buildConfig) -arch $(archType) -ci
+ - script: ./mono$(scriptExt) -configuration $(buildConfig) -arch $(archType) -ci /p:MonoEnableLLVM=${{ parameters.llvm }}
displayName: Build product
- ${{ if eq(parameters.osGroup, 'Windows_NT') }}:
- - script: mono$(scriptExt) -configuration $(buildConfig) -arch $(archType) -ci
+ - script: mono$(scriptExt) -configuration $(buildConfig) -arch $(archType) -ci /p:MonoEnableLLVM=${{ parameters.llvm }}
displayName: Build product
# Publish product output directory for consumption by tests.
@@ -76,10 +87,13 @@ jobs:
displayName: 'product build'
# Publish Logs
- - task: PublishBuildArtifacts@1
+ - task: PublishPipelineArtifact@1
displayName: Publish Logs
inputs:
- pathtoPublish: $(Build.SourcesDirectory)/artifacts/log
- artifactName: 'BuildLogs_Mono_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)'
+ targetPath: $(Build.SourcesDirectory)/artifacts/log
+ ${{ if ne(parameters.llvm, true) }}:
+ artifactName: 'BuildLogs_Mono_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)'
+ ${{ if eq(parameters.llvm, true) }}:
+ artifactName: 'BuildLogs_Mono_LLVM_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)'
continueOnError: true
condition: always()
diff --git a/eng/pipelines/mono/templates/xplat-pipeline-job.yml b/eng/pipelines/mono/templates/xplat-pipeline-job.yml
index 954cbdb20889d0..a0d65845203929 100644
--- a/eng/pipelines/mono/templates/xplat-pipeline-job.yml
+++ b/eng/pipelines/mono/templates/xplat-pipeline-job.yml
@@ -9,6 +9,7 @@ parameters:
liveLibrariesBuildConfig: ''
strategy: ''
pool: ''
+ llvm: false
# arcade-specific parameters
condition: true
@@ -33,6 +34,7 @@ jobs:
container: ${{ parameters.container }}
strategy: ${{ parameters.strategy }}
pool: ${{ parameters.pool }}
+ llvm: ${{ parameters.llvm }}
# arcade-specific parameters
condition: and(succeeded(), ${{ parameters.condition }})
@@ -45,7 +47,10 @@ jobs:
variables:
- name: buildProductArtifactName
- value: 'MonoProduct_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)'
+ ${{ if ne(parameters.llvm, true) }}:
+ value: 'MonoProduct_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)'
+ ${{ if eq(parameters.llvm, true) }}:
+ value: 'MonoProduct_LLVM_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)'
- name: buildProductRootFolderPath
value: '$(Build.SourcesDirectory)/artifacts/bin/mono/$(osGroup).$(archType).$(buildConfigUpper)'
diff --git a/eng/pipelines/official/jobs/prepare-signed-artifacts.yml b/eng/pipelines/official/jobs/prepare-signed-artifacts.yml
index 8df2deebf9560e..77f33ab315a541 100644
--- a/eng/pipelines/official/jobs/prepare-signed-artifacts.yml
+++ b/eng/pipelines/official/jobs/prepare-signed-artifacts.yml
@@ -2,6 +2,7 @@ parameters:
dependsOn: []
PublishRidAgnosticPackagesFromPlatform: ''
isOfficialBuild: false
+ logArtifactName: 'Logs-PrepareSignedArtifacts'
jobs:
- job: PrepareSignedArtifacts
@@ -62,9 +63,9 @@ jobs:
continueOnError: true
condition: succeededOrFailed()
- - task: PublishBuildArtifacts@1
- displayName: Publish Artifact BuildLogs
+ - task: PublishPipelineArtifact@1
+ displayName: Publish BuildLogs
inputs:
- PathtoPublish: '$(Build.StagingDirectory)\BuildLogs'
- ArtifactName: Logs-PrepareSignedArtifacts
+ targetPath: '$(Build.StagingDirectory)\BuildLogs'
+ artifactName: ${{ parameters.logArtifactName }}
condition: succeededOrFailed()
diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml
index 117601b565a8fa..66b42f95206e74 100644
--- a/eng/pipelines/runtime.yml
+++ b/eng/pipelines/runtime.yml
@@ -210,8 +210,8 @@ jobs:
platforms:
- OSX_x64
- Linux_x64
- # - Linux_arm
- # - Linux_arm64
+ - Linux_arm
+ - Linux_arm64
- Linux_musl_x64
# - Linux_musl_arm64
- Windows_NT_x64
@@ -237,8 +237,8 @@ jobs:
platforms:
- OSX_x64
- Linux_x64
- # - Linux_arm
- # - Linux_arm64
+ - Linux_arm
+ - Linux_arm64
- Linux_musl_x64
# - Linux_musl_arm64
- Windows_NT_x64
@@ -252,6 +252,62 @@ jobs:
eq(dependencies.checkout.outputs['SetPathVars_mono.containsChange'], true),
eq(variables['isFullMatrix'], true))
+#
+# Build Mono LLVM debug
+# Only when libraries or mono changed
+#
+- template: /eng/pipelines/common/platform-matrix.yml
+ parameters:
+ jobTemplate: /eng/pipelines/mono/templates/build-job.yml
+ runtimeFlavor: mono
+ buildConfig: debug
+ platforms:
+ - OSX_x64
+ - Linux_x64
+ # - Linux_arm
+ # - Linux_arm64
+ # - Linux_musl_x64
+ # - Linux_musl_arm64
+ # - Windows_NT_x64
+ # - Windows_NT_x86
+ # - Windows_NT_arm
+ # - Windows_NT_arm64
+ jobParameters:
+ llvm: true
+ condition: >-
+ or(
+ eq(dependencies.checkout.outputs['SetPathVars_libraries.containsChange'], true),
+ eq(dependencies.checkout.outputs['SetPathVars_mono.containsChange'], true),
+ eq(variables['isFullMatrix'], true))
+
+#
+# Build Mono LLVM release
+# Only when libraries or mono changed
+#
+- template: /eng/pipelines/common/platform-matrix.yml
+ parameters:
+ jobTemplate: /eng/pipelines/mono/templates/build-job.yml
+ runtimeFlavor: mono
+ buildConfig: release
+ platforms:
+ - OSX_x64
+ - Linux_x64
+ # - Linux_arm
+ # - Linux_arm64
+ # - Linux_musl_x64
+ # - Linux_musl_arm64
+ # - Windows_NT_x64
+ # - Windows_NT_x86
+ # - Windows_NT_arm
+ # - Windows_NT_arm64
+ jobParameters:
+ llvm: true
+ condition: >-
+ or(
+ eq(dependencies.checkout.outputs['SetPathVars_libraries.containsChange'], true),
+ eq(dependencies.checkout.outputs['SetPathVars_mono.containsChange'], true),
+ eq(variables['isFullMatrix'], true))
+
#
# Build libraries using live CoreLib
# These set of libraries are built always no matter what changed
@@ -464,6 +520,7 @@ jobs:
- Linux_arm
- Windows_NT_x86
- Windows_NT_arm
+ - Windows_NT_arm64
helixQueueGroup: pr
helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml
jobParameters:
@@ -505,6 +562,7 @@ jobs:
platforms:
# - Windows_NT_x64
- OSX_x64
+ - Linux_arm64
- Linux_x64
helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml
jobParameters:
@@ -639,4 +697,4 @@ jobs:
or(
eq(dependencies.checkout.outputs['SetPathVars_coreclr.containsChange'], true),
eq(dependencies.checkout.outputs['SetPathVars_libraries.containsChange'], true),
- eq(variables['isFullMatrix'], true))
\ No newline at end of file
+ eq(variables['isFullMatrix'], true))
diff --git a/eng/restore/docs.targets b/eng/restore/docs.targets
index 61c81ea99a62ba..b5d9ce90bb55f1 100644
--- a/eng/restore/docs.targets
+++ b/eng/restore/docs.targets
@@ -9,7 +9,7 @@
AfterTargets="Restore">
-
+
$([System.String]::new('%(RecursiveDir)').TrimEnd('\/'))
diff --git a/eng/testing/outerBuild.targets b/eng/testing/outerBuild.targets
index ece58160db3738..4623b0e54d2504 100644
--- a/eng/testing/outerBuild.targets
+++ b/eng/testing/outerBuild.targets
@@ -1,17 +1,6 @@
-
-
-
-
-
-
-
-
-
-
+
diff --git a/eng/testing/tests.targets b/eng/testing/tests.targets
index 8a660f917e28c8..b6a119c599fc07 100644
--- a/eng/testing/tests.targets
+++ b/eng/testing/tests.targets
@@ -80,7 +80,6 @@
<_rspFile Include="$(TestRspFile)" Condition="'$(TestRspFile)' != ''" />
- <_rspFile Include="$(MonoProjectRoot)netcore\CoreFX.issues.rsp" />
<_rspFile Include="$(MonoProjectRoot)netcore\CoreFX.issues_mac.rsp" Condition="'$(TargetOS)' == 'OSX'" />
<_rspFile Include="$(MonoProjectRoot)netcore\CoreFX.issues_linux.rsp" Condition="'$(TargetOS)' == 'Linux'" />
<_rspFile Include="$(MonoProjectRoot)netcore\CoreFX.issues_windows.rsp" Condition="'$(TargetOS)' == 'Windows_NT'" />
diff --git a/global.json b/global.json
index 02938d48ca9d09..e747f7a8dd88ac 100644
--- a/global.json
+++ b/global.json
@@ -5,17 +5,17 @@
"rollForward": "major"
},
"tools": {
- "dotnet": "5.0.100-alpha.1.20073.4"
+ "dotnet": "5.0.100-preview.1.20112.7"
},
"native-tools": {
"cmake": "3.14.2",
"python": "2.7.15"
},
"msbuild-sdks": {
- "Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk": "5.0.0-beta.20105.2",
- "Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.20105.2",
- "Microsoft.DotNet.Build.Tasks.SharedFramework.Sdk": "5.0.0-beta.20105.2",
- "Microsoft.DotNet.Helix.Sdk": "5.0.0-beta.20105.2",
+ "Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk": "5.0.0-beta.20117.3",
+ "Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.20117.3",
+ "Microsoft.DotNet.Build.Tasks.SharedFramework.Sdk": "5.0.0-beta.20117.3",
+ "Microsoft.DotNet.Helix.Sdk": "5.0.0-beta.20117.3",
"FIX-85B6-MERGE-9C38-CONFLICT": "1.0.0",
"Microsoft.NET.Sdk.IL": "5.0.0-alpha.1.20076.2",
"Microsoft.Build.NoTargets": "1.0.53",
diff --git a/src/coreclr/CMakeLists.txt b/src/coreclr/CMakeLists.txt
index 5a33d25d6fa4a5..d51dc5ed3cb716 100644
--- a/src/coreclr/CMakeLists.txt
+++ b/src/coreclr/CMakeLists.txt
@@ -131,7 +131,12 @@ endif(CLR_CROSS_COMPONENTS_BUILD)
#-------------------
include(pgosupport.cmake)
-add_subdirectory(src/libraries-native)
+#-------------------------------
+# Include libraries native shims
+#-------------------------------
+if(NOT CLR_CROSS_COMPONENTS_BUILD)
+ add_subdirectory(src/libraries-native)
+endif(NOT CLR_CROSS_COMPONENTS_BUILD)
#-----------------------------------------
# Add Projects
diff --git a/src/coreclr/all.locproj b/src/coreclr/all.locproj
index 5cccc3d7ff1291..aac54a9b41a9e3 100644
--- a/src/coreclr/all.locproj
+++ b/src/coreclr/all.locproj
@@ -1,4 +1,4 @@
-
+
+
+
diff --git a/src/coreclr/src/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/src/System.Private.CoreLib/System.Private.CoreLib.csproj
index 096771f8904061..3ee759bf34414c 100644
--- a/src/coreclr/src/System.Private.CoreLib/System.Private.CoreLib.csproj
+++ b/src/coreclr/src/System.Private.CoreLib/System.Private.CoreLib.csproj
@@ -52,7 +52,7 @@
enable
- CORECLR;NETCOREAPP
+ CORECLR;NETCOREAPP;SYSTEM_PRIVATE_CORELIB
true
+
+
diff --git a/src/coreclr/src/System.Private.CoreLib/System.Private.CoreLib.sln b/src/coreclr/src/System.Private.CoreLib/System.Private.CoreLib.sln
index d1d038ce9085de..86372c56c8a4d6 100644
--- a/src/coreclr/src/System.Private.CoreLib/System.Private.CoreLib.sln
+++ b/src/coreclr/src/System.Private.CoreLib/System.Private.CoreLib.sln
@@ -1,4 +1,3 @@
-
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.28902.138
@@ -9,6 +8,7 @@ Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "System.Private.CoreLib.Shar
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
+ ..\..\..\libraries\System.Private.CoreLib\src\System.Private.CoreLib.Shared.projitems*{3da06c3a-2e7b-4cb7-80ed-9b12916013f9}*SharedItemsImports = 5
..\..\..\libraries\System.Private.CoreLib\src\System.Private.CoreLib.Shared.projitems*{845c8b26-350b-4e63-bd11-2c8150444e28}*SharedItemsImports = 13
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
diff --git a/src/coreclr/src/System.Private.CoreLib/Tools/GenUnicodeProp/GenUnicodeProp.csproj b/src/coreclr/src/System.Private.CoreLib/Tools/GenUnicodeProp/GenUnicodeProp.csproj
index 68c616ea14ab7b..679e3fac9abc31 100644
--- a/src/coreclr/src/System.Private.CoreLib/Tools/GenUnicodeProp/GenUnicodeProp.csproj
+++ b/src/coreclr/src/System.Private.CoreLib/Tools/GenUnicodeProp/GenUnicodeProp.csproj
@@ -1,4 +1,4 @@
-
+
Exe
diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeEventDispatcher.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeEventDispatcher.cs
index e403949e8979c6..2307f642cd827b 100644
--- a/src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeEventDispatcher.cs
+++ b/src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipeEventDispatcher.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.cs
index abd68baae2bbd4..2634fb4a507f99 100644
--- a/src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.cs
+++ b/src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/StackFrameHelper.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/StackFrameHelper.cs
index 3c83ff6bc6bc3c..20a0c57492d8aa 100644
--- a/src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/StackFrameHelper.cs
+++ b/src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/StackFrameHelper.cs
@@ -4,6 +4,7 @@
using System.Threading;
using System.Reflection;
+using System.Runtime.CompilerServices;
namespace System.Diagnostics
{
@@ -82,6 +83,13 @@ public StackFrameHelper(Thread? target)
// rgiLineNumber and rgiColumnNumber fields using the portable PDB reader if not already
// done by GetStackFramesInternal (on Windows for old PDB format).
//
+
+ // This is necessary because linker can't add new assemblies to the closure when recognizing Type.GetType
+ // so the code below is actually recognized by linker, but fails to resolve the type since the System.Diagnostics.StackTrace
+ // is not always part of the closure linker works on.
+ // PreserveDependencyAttribute on the other hand can pull in additional assemblies.
+ [PreserveDependency("GetSourceLineInfo", "System.Diagnostics.StackTraceSymbols", "System.Diagnostics.StackTrace")]
+ [PreserveDependency(".ctor()", "System.Diagnostics.StackTraceSymbols", "System.Diagnostics.StackTrace")]
internal void InitializeSourceInfo(int iSkip, bool fNeedFileInfo, Exception? exception)
{
StackTrace.GetStackFramesInternal(this, iSkip, fNeedFileInfo, exception);
diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Environment.CoreCLR.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Environment.CoreCLR.cs
index 59b2bd9d79040b..f141b1e9cfeb73 100644
--- a/src/coreclr/src/System.Private.CoreLib/src/System/Environment.CoreCLR.cs
+++ b/src/coreclr/src/System.Private.CoreLib/src/System/Environment.CoreCLR.cs
@@ -16,6 +16,7 @@ public static partial class Environment
// Terminates this process with the given exit code.
[DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)]
+ [DoesNotReturn]
private static extern void _Exit(int exitCode);
[DoesNotReturn]
diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/EmptyCAHolder.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/EmptyCAHolder.cs
index 11140568060738..102e2f7f554ea0 100644
--- a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/EmptyCAHolder.cs
+++ b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/EmptyCAHolder.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs
index c9cbeefce15f0f..6763aea8e21f69 100644
--- a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs
+++ b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs
@@ -600,7 +600,7 @@ internal Type[] GetTypesNoLock()
while (startIndex <= className.Length)
{
// Are there any possible special characters left?
- int i = className.IndexOfAny(new char[] { '[', '*', '&' }, startIndex);
+ int i = className.AsSpan(startIndex).IndexOfAny('[', '*', '&');
if (i == -1)
{
// No, type name is simple.
@@ -608,6 +608,7 @@ internal Type[] GetTypesNoLock()
parameters = null;
break;
}
+ i += startIndex;
// Found a potential special character, but it might be escaped.
int slashes = 0;
diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs
index 35df17555f5669..b0905c93f506cd 100644
--- a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs
+++ b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs
@@ -165,6 +165,9 @@ private static CastResult TryGet(nuint source, nuint target)
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern object ChkCastAny_NoCacheLookup(void* toTypeHnd, object obj);
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ private static extern ref byte Unbox_Helper(void* toTypeHnd, object obj);
+
// IsInstanceOf test used for unusual cases (naked type parameters, variant generic types)
// Unlike the IsInstanceOfInterface and IsInstanceOfClass functions,
// this test must deal with all kinds of type tests
@@ -476,5 +479,17 @@ private static CastResult TryGet(nuint source, nuint target)
slowPath:
return ChkCastHelper(toTypeHnd, obj);
}
+
+ [DebuggerHidden]
+ [StackTraceHidden]
+ [DebuggerStepThrough]
+ private static ref byte Unbox(void* toTypeHnd, object obj)
+ {
+ // this will throw NullReferenceException if obj is null, attributed to the user code, as expected.
+ if (RuntimeHelpers.GetMethodTable(obj) == toTypeHnd)
+ return ref obj.GetRawData();
+
+ return ref Unbox_Helper(toTypeHnd, obj);
+ }
}
}
diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumVariantViewOfEnumerator.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumVariantViewOfEnumerator.cs
index 84ef390bb1fe5f..0b8d002bb73111 100644
--- a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumVariantViewOfEnumerator.cs
+++ b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumVariantViewOfEnumerator.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumerableToDispatchMarshaler.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumerableToDispatchMarshaler.cs
index 9aab6ba4245d81..0a758211b770db 100644
--- a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumerableToDispatchMarshaler.cs
+++ b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumerableToDispatchMarshaler.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumerableViewOfDispatch.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumerableViewOfDispatch.cs
index 4162699f1ab314..d67948660a3a9f 100644
--- a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumerableViewOfDispatch.cs
+++ b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumerableViewOfDispatch.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumeratorToEnumVariantMarshaler.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumeratorToEnumVariantMarshaler.cs
index 4e3e456786bcab..fc0bf507d764fc 100644
--- a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumeratorToEnumVariantMarshaler.cs
+++ b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumeratorToEnumVariantMarshaler.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumeratorViewOfEnumVariant.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumeratorViewOfEnumVariant.cs
index ecb583f2b9c5dd..223330afc2fe94 100644
--- a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumeratorViewOfEnumVariant.cs
+++ b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumeratorViewOfEnumVariant.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/IDispatch.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/IDispatch.cs
index f002cb661e6b43..fe57a781cb99ae 100644
--- a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/IDispatch.cs
+++ b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/IDispatch.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs
index a0a0fdfd78bf65..b22f6bc458481b 100644
--- a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs
+++ b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs
@@ -154,8 +154,7 @@ internal Type LoadTypeForWinRTTypeNameInContext(string typeName)
if (ptrAssemblyLoadContext == IntPtr.Zero)
{
// If the load context is returned null, then the assembly was bound using the TPA binder
- // and we shall return reference to the active "Default" binder - which could be the TPA binder
- // or an overridden CLRPrivBinderAssemblyLoadContext instance.
+ // and we shall return reference to the "Default" binder.
loadContextForAssembly = AssemblyLoadContext.Default;
}
else
diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Threading/Interlocked.CoreCLR.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Threading/Interlocked.CoreCLR.cs
new file mode 100644
index 00000000000000..33437141e76121
--- /dev/null
+++ b/src/coreclr/src/System.Private.CoreLib/src/System/Threading/Interlocked.CoreCLR.cs
@@ -0,0 +1,242 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Internal.Runtime.CompilerServices;
+
+namespace System.Threading
+{
+ public static partial class Interlocked
+ {
+ #region Increment
+ /// Increments a specified variable and stores the result, as an atomic operation.
+ /// The variable whose value is to be incremented.
+ /// The incremented value.
+ /// The address of location is a null pointer.
+ public static int Increment(ref int location) =>
+ Add(ref location, 1);
+
+ /// Increments a specified variable and stores the result, as an atomic operation.
+ /// The variable whose value is to be incremented.
+ /// The incremented value.
+ /// The address of location is a null pointer.
+ public static long Increment(ref long location) =>
+ Add(ref location, 1);
+ #endregion
+
+ #region Decrement
+ /// Decrements a specified variable and stores the result, as an atomic operation.
+ /// The variable whose value is to be decremented.
+ /// The decremented value.
+ /// The address of location is a null pointer.
+ public static int Decrement(ref int location) =>
+ Add(ref location, -1);
+
+ /// Decrements a specified variable and stores the result, as an atomic operation.
+ /// The variable whose value is to be decremented.
+ /// The decremented value.
+ /// The address of location is a null pointer.
+ public static long Decrement(ref long location) =>
+ Add(ref location, -1);
+ #endregion
+
+ #region Exchange
+ /// Sets a 32-bit signed integer to a specified value and returns the original value, as an atomic operation.
+ /// The variable to set to the specified value.
+ /// The value to which the parameter is set.
+ /// The original value of .
+ /// The address of location1 is a null pointer.
+ [Intrinsic]
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ public static extern int Exchange(ref int location1, int value);
+
+ /// Sets a 64-bit signed integer to a specified value and returns the original value, as an atomic operation.
+ /// The variable to set to the specified value.
+ /// The value to which the parameter is set.
+ /// The original value of .
+ /// The address of location1 is a null pointer.
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ public static extern long Exchange(ref long location1, long value);
+
+ /// Sets a single-precision floating point number to a specified value and returns the original value, as an atomic operation.
+ /// The variable to set to the specified value.
+ /// The value to which the parameter is set.
+ /// The original value of .
+ /// The address of location1 is a null pointer.
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ public static extern float Exchange(ref float location1, float value);
+
+ /// Sets a double-precision floating point number to a specified value and returns the original value, as an atomic operation.
+ /// The variable to set to the specified value.
+ /// The value to which the parameter is set.
+ /// The original value of .
+ /// The address of location1 is a null pointer.
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ public static extern double Exchange(ref double location1, double value);
+
+ /// Sets an object to the specified value and returns a reference to the original object, as an atomic operation.
+ /// The variable to set to the specified value.
+ /// The value to which the parameter is set.
+ /// The original value of .
+ /// The address of location1 is a null pointer.
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ [return: NotNullIfNotNull("location1")]
+ public static extern object? Exchange([NotNullIfNotNull("value")] ref object? location1, object? value);
+
+ /// Sets a platform-specific handle or pointer to a specified value and returns the original value, as an atomic operation.
+ /// The variable to set to the specified value.
+ /// The value to which the parameter is set.
+ /// The original value of .
+ /// The address of location1 is a null pointer.
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ public static extern IntPtr Exchange(ref IntPtr location1, IntPtr value);
+
+ // The below whole method reduces to a single call to Exchange(ref object, object) but
+ // the JIT thinks that it will generate more native code than it actually does.
+
+ /// Sets a variable of the specified type to a specified value and returns the original value, as an atomic operation.
+ /// The variable to set to the specified value.
+ /// The value to which the parameter is set.
+ /// The original value of .
+ /// The address of location1 is a null pointer.
+ /// The type to be used for and . This type must be a reference type.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [return: NotNullIfNotNull("location1")]
+ public static T Exchange([NotNullIfNotNull("value")] ref T location1, T value) where T : class? =>
+ Unsafe.As(Exchange(ref Unsafe.As(ref location1), value));
+ #endregion
+
+ #region CompareExchange
+ /// Compares two 32-bit signed integers for equality and, if they are equal, replaces the first value.
+ /// The destination, whose value is compared with and possibly replaced.
+ /// The value that replaces the destination value if the comparison results in equality.
+ /// The value that is compared to the value at .
+ /// The original value in .
+ /// The address of is a null pointer.
+ [Intrinsic]
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ public static extern int CompareExchange(ref int location1, int value, int comparand);
+
+ /// Compares two 64-bit signed integers for equality and, if they are equal, replaces the first value.
+ /// The destination, whose value is compared with and possibly replaced.
+ /// The value that replaces the destination value if the comparison results in equality.
+ /// The value that is compared to the value at .
+ /// The original value in .
+ /// The address of is a null pointer.
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ public static extern long CompareExchange(ref long location1, long value, long comparand);
+
+ /// Compares two single-precision floating point numbers for equality and, if they are equal, replaces the first value.
+ /// The destination, whose value is compared with and possibly replaced.
+ /// The value that replaces the destination value if the comparison results in equality.
+ /// The value that is compared to the value at .
+ /// The original value in .
+ /// The address of is a null pointer.
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ public static extern float CompareExchange(ref float location1, float value, float comparand);
+
+ /// Compares two double-precision floating point numbers for equality and, if they are equal, replaces the first value.
+ /// The destination, whose value is compared with and possibly replaced.
+ /// The value that replaces the destination value if the comparison results in equality.
+ /// The value that is compared to the value at .
+ /// The original value in .
+ /// The address of is a null pointer.
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ public static extern double CompareExchange(ref double location1, double value, double comparand);
+
+ /// Compares two objects for reference equality and, if they are equal, replaces the first object.
+ /// The destination object that is compared by reference with and possibly replaced.
+ /// The object that replaces the destination object if the reference comparison results in equality.
+ /// The object that is compared by reference to the object at .
+ /// The original value in .
+ /// The address of is a null pointer.
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ [return: NotNullIfNotNull("location1")]
+ public static extern object? CompareExchange(ref object? location1, object? value, object? comparand);
+
+ /// Compares two platform-specific handles or pointers for equality and, if they are equal, replaces the first one.
+ /// The destination , whose value is compared with the value of and possibly replaced by .
+ /// The that replaces the destination value if the comparison results in equality.
+ /// The that is compared to the value at .
+ /// The original value in .
+ /// The address of is a null pointer.
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ public static extern IntPtr CompareExchange(ref IntPtr location1, IntPtr value, IntPtr comparand);
+
+ // Note that getILIntrinsicImplementationForInterlocked() in vm\jitinterface.cpp replaces
+ // the body of the following method with the the following IL:
+ // ldarg.0
+ // ldarg.1
+ // ldarg.2
+ // call System.Threading.Interlocked::CompareExchange(ref Object, Object, Object)
+ // ret
+ // The workaround is no longer strictly necessary now that we have Unsafe.As but it does
+ // have the advantage of being less sensitive to JIT's inliner decisions.
+
+ /// Compares two instances of the specified reference type for reference equality and, if they are equal, replaces the first one.
+ /// The destination, whose value is compared by reference with and possibly replaced.
+ /// The value that replaces the destination value if the comparison by reference results in equality.
+ /// The object that is compared by reference to the value at .
+ /// The original value in .
+ /// The address of is a null pointer.
+ /// The type to be used for , , and . This type must be a reference type.
+ [return: NotNullIfNotNull("location1")]
+ [Intrinsic]
+ public static T CompareExchange(ref T location1, T value, T comparand) where T : class? =>
+ Unsafe.As(CompareExchange(ref Unsafe.As(ref location1), value, comparand));
+ #endregion
+
+ #region Add
+ /// Adds two 32-bit signed integers and replaces the first integer with the sum, as an atomic operation.
+ /// A variable containing the first value to be added. The sum of the two values is stored in .
+ /// The value to be added to the integer at .
+ /// The new value stored at .
+ /// The address of is a null pointer.
+ public static int Add(ref int location1, int value) =>
+ ExchangeAdd(ref location1, value) + value;
+
+ /// Adds two 64-bit signed integers and replaces the first integer with the sum, as an atomic operation.
+ /// A variable containing the first value to be added. The sum of the two values is stored in .
+ /// The value to be added to the integer at .
+ /// The new value stored at .
+ /// The address of is a null pointer.
+ public static long Add(ref long location1, long value) =>
+ ExchangeAdd(ref location1, value) + value;
+
+ [Intrinsic]
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ private static extern int ExchangeAdd(ref int location1, int value);
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ private static extern long ExchangeAdd(ref long location1, long value);
+ #endregion
+
+ #region Read
+ /// Returns a 64-bit signed value, loaded as an atomic operation.
+ /// The 64-bit value to be loaded.
+ /// The loaded value.
+ public static long Read(ref long location) =>
+ CompareExchange(ref location, 0, 0);
+ #endregion
+
+ #region MemoryBarrier
+ ///
+ /// Synchronizes memory access as follows:
+ /// The processor that executes the current thread cannot reorder instructions in such a way that memory accesses before
+ /// the call to execute after memory accesses that follow the call to .
+ ///
+ [Intrinsic]
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ public static extern void MemoryBarrier();
+
+ [DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)]
+ private static extern void _MemoryBarrierProcessWide();
+
+ /// Provides a process-wide memory barrier that ensures that reads and writes from any CPU cannot move across the barrier.
+ public static void MemoryBarrierProcessWide() => _MemoryBarrierProcessWide();
+ #endregion
+ }
+}
diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Threading/Interlocked.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Threading/Interlocked.cs
deleted file mode 100644
index 40c261b6f757d1..00000000000000
--- a/src/coreclr/src/System.Private.CoreLib/src/System/Threading/Interlocked.cs
+++ /dev/null
@@ -1,159 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Runtime.CompilerServices;
-using Internal.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Diagnostics.CodeAnalysis;
-
-namespace System.Threading
-{
- ///
- /// After much discussion, we decided the Interlocked class doesn't need
- /// any HPA's for synchronization or external threading. They hurt C#'s
- /// codegen for the yield keyword, and arguably they didn't protect much.
- /// Instead, they penalized people (and compilers) for writing threadsafe
- /// code.
- ///
- public static class Interlocked
- {
- ///
- /// Implemented: int, long
- ///
- public static int Increment(ref int location)
- {
- return Add(ref location, 1);
- }
-
- public static long Increment(ref long location)
- {
- return Add(ref location, 1);
- }
-
- ///
- /// Implemented: int, long
- ///
- public static int Decrement(ref int location)
- {
- return Add(ref location, -1);
- }
-
- public static long Decrement(ref long location)
- {
- return Add(ref location, -1);
- }
-
- ///
- /// Implemented: int, long, float, double, Object, IntPtr
- ///
- [Intrinsic]
- [MethodImpl(MethodImplOptions.InternalCall)]
- public static extern int Exchange(ref int location1, int value);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- public static extern long Exchange(ref long location1, long value);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- public static extern float Exchange(ref float location1, float value);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- public static extern double Exchange(ref double location1, double value);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- [return: NotNullIfNotNull("location1")]
- public static extern object? Exchange([NotNullIfNotNull("value")] ref object? location1, object? value);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- public static extern IntPtr Exchange(ref IntPtr location1, IntPtr value);
-
- // This whole method reduces to a single call to Exchange(ref object, object) but
- // the JIT thinks that it will generate more native code than it actually does.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- [return: NotNullIfNotNull("location1")]
- public static T Exchange([NotNullIfNotNull("value")] ref T location1, T value) where T : class?
- {
- return Unsafe.As(Exchange(ref Unsafe.As(ref location1), value));
- }
-
- ///
- /// Implemented: int, long, float, double, Object, IntPtr
- ///
- [Intrinsic]
- [MethodImpl(MethodImplOptions.InternalCall)]
- public static extern int CompareExchange(ref int location1, int value, int comparand);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- public static extern long CompareExchange(ref long location1, long value, long comparand);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- public static extern float CompareExchange(ref float location1, float value, float comparand);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- public static extern double CompareExchange(ref double location1, double value, double comparand);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- [return: NotNullIfNotNull("location1")]
- public static extern object? CompareExchange(ref object? location1, object? value, object? comparand);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- public static extern IntPtr CompareExchange(ref IntPtr location1, IntPtr value, IntPtr comparand);
-
- // Note that getILIntrinsicImplementationForInterlocked() in vm\jitinterface.cpp replaces
- // the body of this method with the the following IL:
- // ldarg.0
- // ldarg.1
- // ldarg.2
- // call System.Threading.Interlocked::CompareExchange(ref Object, Object, Object)
- // ret
- // The workaround is no longer strictly necessary now that we have Unsafe.As but it does
- // have the advantage of being less sensitive to JIT's inliner decisions.
- [return: NotNullIfNotNull("location1")]
- [Intrinsic]
- public static T CompareExchange(ref T location1, T value, T comparand) where T : class?
- {
- return Unsafe.As(CompareExchange(ref Unsafe.As(ref location1), value, comparand));
- }
-
- // BCL-internal overload that returns success via a ref bool param, useful for reliable spin locks.
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern int CompareExchange(ref int location1, int value, int comparand, ref bool succeeded);
-
- ///
- /// Implemented: int, long
- ///
- [Intrinsic]
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern int ExchangeAdd(ref int location1, int value);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern long ExchangeAdd(ref long location1, long value);
-
- public static int Add(ref int location1, int value)
- {
- return ExchangeAdd(ref location1, value) + value;
- }
-
- public static long Add(ref long location1, long value)
- {
- return ExchangeAdd(ref location1, value) + value;
- }
-
- public static long Read(ref long location)
- {
- return Interlocked.CompareExchange(ref location, 0, 0);
- }
-
- [Intrinsic]
- [MethodImpl(MethodImplOptions.InternalCall)]
- public static extern void MemoryBarrier();
-
- [DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)]
- private static extern void _MemoryBarrierProcessWide();
-
- public static void MemoryBarrierProcessWide()
- {
- _MemoryBarrierProcessWide();
- }
- }
-}
diff --git a/src/coreclr/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h b/src/coreclr/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h
index ff28c9bfd5a852..482bc998e63ea7 100644
--- a/src/coreclr/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h
+++ b/src/coreclr/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h
@@ -255,6 +255,11 @@ BOOL isValidStringRef(CORINFO_MODULE_HANDLE module, /* IN */
unsigned metaTOK /* IN */
);
+LPCWSTR getStringLiteral(CORINFO_MODULE_HANDLE module, /* IN */
+ unsigned metaTOK, /* IN */
+ int* length /* OUT */
+ );
+
BOOL shouldEnforceCallvirtRestriction(CORINFO_MODULE_HANDLE scope);
/**********************************************************************************/
diff --git a/src/coreclr/src/ToolBox/superpmi/superpmi-shared/lwmlist.h b/src/coreclr/src/ToolBox/superpmi/superpmi-shared/lwmlist.h
index 45449d1161d46a..59ebf7f35e7bad 100644
--- a/src/coreclr/src/ToolBox/superpmi/superpmi-shared/lwmlist.h
+++ b/src/coreclr/src/ToolBox/superpmi/superpmi-shared/lwmlist.h
@@ -147,6 +147,7 @@ LWM(IsInstantiationOfVerifiedGeneric, DWORDLONG, DWORD)
LWM(IsSDArray, DWORDLONG, DWORD)
LWM(IsStructRequiringStackAllocRetBuf, DWORDLONG, DWORD)
LWM(IsValidStringRef, DLD, DWORD)
+LWM(GetStringLiteral, DLD, DD)
LWM(IsValidToken, DLD, DWORD)
LWM(IsValueClass, DWORDLONG, DWORD)
LWM(IsWriteBarrierHelperRequired, DWORDLONG, DWORD)
diff --git a/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp
index 0523e77d9c81c5..2a5da1050b1d01 100644
--- a/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp
+++ b/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp
@@ -4606,6 +4606,65 @@ BOOL MethodContext::repIsValidStringRef(CORINFO_MODULE_HANDLE module, unsigned m
return value;
}
+
+void MethodContext::recGetStringLiteral(CORINFO_MODULE_HANDLE module, unsigned metaTOK, int length, LPCWSTR result)
+{
+ if (GetStringLiteral == nullptr)
+ GetStringLiteral = new LightWeightMap();
+
+ DLD key;
+ ZeroMemory(&key, sizeof(DLD)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
+ // out padding too
+
+ key.A = (DWORDLONG)module;
+ key.B = (DWORD)metaTOK;
+
+ DWORD strBuf = (DWORD)-1;
+ if (result != nullptr)
+ strBuf = (DWORD)GetStringLiteral->AddBuffer((unsigned char*)result, (unsigned int)((wcslen(result) * 2) + 2));
+
+ DD value;
+ value.A = (DWORD)length;
+ value.B = (DWORD)strBuf;
+
+ GetStringLiteral->Add(key, value);
+}
+
+void MethodContext::dmpGetStringLiteral(DLD key, DD value)
+{
+ printf("GetStringLiteral key mod-%016llX tok-%08X, result-%s, len-%u", key.A, key.B,
+ GetStringLiteral->GetBuffer(value.B), value.A);
+}
+
+LPCWSTR MethodContext::repGetStringLiteral(CORINFO_MODULE_HANDLE module, unsigned metaTOK, int* length)
+{
+ if (GetStringLiteral == nullptr)
+ {
+ *length = -1;
+ return nullptr;
+ }
+
+ DLD key;
+ ZeroMemory(&key, sizeof(DLD)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
+ // out padding too
+
+ key.A = (DWORDLONG)module;
+ key.B = (DWORD)metaTOK;
+
+ int itemIndex = GetStringLiteral->GetIndex(key);
+ if (itemIndex < 0)
+ {
+ *length = -1;
+ return nullptr;
+ }
+ else
+ {
+ DD result = GetStringLiteral->Get(key);
+ *length = (int)result.A;
+ return (LPCWSTR)GetStringLiteral->GetBuffer(itemIndex);
+ }
+}
+
void MethodContext::recGetHelperName(CorInfoHelpFunc funcNum, const char* result)
{
if (GetHelperName == nullptr)
diff --git a/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.h
index fb596c263ef0fc..3c1c4792d96a4c 100644
--- a/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.h
+++ b/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.h
@@ -1086,6 +1086,10 @@ class MethodContext
void dmpIsValidStringRef(DLD key, DWORD value);
BOOL repIsValidStringRef(CORINFO_MODULE_HANDLE module, unsigned metaTOK);
+ void recGetStringLiteral(CORINFO_MODULE_HANDLE module, unsigned metaTOK, int length, LPCWSTR result);
+ void dmpGetStringLiteral(DLD key, DD value);
+ LPCWSTR repGetStringLiteral(CORINFO_MODULE_HANDLE module, unsigned metaTOK, int* length);
+
void recGetHelperName(CorInfoHelpFunc funcNum, const char* result);
void dmpGetHelperName(DWORD key, DWORD value);
const char* repGetHelperName(CorInfoHelpFunc funcNum);
@@ -1352,7 +1356,7 @@ class MethodContext
};
// ********************* Please keep this up-to-date to ease adding more ***************
-// Highest packet number: 174
+// Highest packet number: 175
// *************************************************************************************
enum mcPackets
{
@@ -1493,6 +1497,7 @@ enum mcPackets
Packet_IsSDArray = 101,
Packet_IsStructRequiringStackAllocRetBuf = 102,
Packet_IsValidStringRef = 103,
+ Packet_GetStringLiteral = 175, // Added 1/7/2020
Retired6 = 104,
Packet_IsValidToken = 144, // Added 7/19/2013 - adjusted members to proper types
Packet_IsValueClass = 105,
diff --git a/src/coreclr/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/coreclr/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp
index 0384e2c3218d29..9f42b42925344a 100644
--- a/src/coreclr/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp
+++ b/src/coreclr/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp
@@ -517,6 +517,17 @@ BOOL interceptor_ICJI::isValidStringRef(CORINFO_MODULE_HANDLE module, /* IN */
return temp;
}
+LPCWSTR interceptor_ICJI::getStringLiteral(CORINFO_MODULE_HANDLE module, /* IN */
+ unsigned metaTOK, /* IN */
+ int* length /* OUT */
+ )
+{
+ mc->cr->AddCall("getStringLiteral");
+ LPCWSTR temp = original_ICorJitInfo->getStringLiteral(module, metaTOK, length);
+ mc->recGetStringLiteral(module, metaTOK, *length, temp);
+ return temp;
+}
+
BOOL interceptor_ICJI::shouldEnforceCallvirtRestriction(CORINFO_MODULE_HANDLE scope)
{
mc->cr->AddCall("shouldEnforceCallvirtRestriction");
diff --git a/src/coreclr/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp b/src/coreclr/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp
index 810aed301dcced..aa7d8a383cc3a9 100644
--- a/src/coreclr/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp
+++ b/src/coreclr/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp
@@ -378,6 +378,15 @@ BOOL interceptor_ICJI::isValidStringRef(CORINFO_MODULE_HANDLE module, /* IN */
return original_ICorJitInfo->isValidStringRef(module, metaTOK);
}
+LPCWSTR interceptor_ICJI::getStringLiteral(CORINFO_MODULE_HANDLE module, /* IN */
+ unsigned metaTOK, /* IN */
+ int* length /* OUT */
+ )
+{
+ mcs->AddCall("getStringLiteral");
+ return original_ICorJitInfo->getStringLiteral(module, metaTOK, length);
+}
+
BOOL interceptor_ICJI::shouldEnforceCallvirtRestriction(CORINFO_MODULE_HANDLE scope)
{
mcs->AddCall("shouldEnforceCallvirtRestriction");
diff --git a/src/coreclr/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp b/src/coreclr/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp
index b562704433a69e..4a9a71464c8365 100644
--- a/src/coreclr/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp
+++ b/src/coreclr/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp
@@ -340,6 +340,14 @@ BOOL interceptor_ICJI::isValidStringRef(CORINFO_MODULE_HANDLE module, /* IN */
return original_ICorJitInfo->isValidStringRef(module, metaTOK);
}
+LPCWSTR interceptor_ICJI::getStringLiteral(CORINFO_MODULE_HANDLE module, /* IN */
+ unsigned metaTOK, /* IN */
+ int* length /* OUT */
+ )
+{
+ return original_ICorJitInfo->getStringLiteral(module, metaTOK, length);
+}
+
BOOL interceptor_ICJI::shouldEnforceCallvirtRestriction(CORINFO_MODULE_HANDLE scope)
{
return original_ICorJitInfo->shouldEnforceCallvirtRestriction(scope);
diff --git a/src/coreclr/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp
index 630ca18c69b63e..f3bf12be739a7d 100644
--- a/src/coreclr/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp
+++ b/src/coreclr/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp
@@ -408,6 +408,15 @@ BOOL MyICJI::isValidStringRef(CORINFO_MODULE_HANDLE module, /* IN */
return jitInstance->mc->repIsValidStringRef(module, metaTOK);
}
+LPCWSTR MyICJI::getStringLiteral(CORINFO_MODULE_HANDLE module, /* IN */
+ unsigned metaTOK, /* IN */
+ int* length /* OUT */
+ )
+{
+ jitInstance->mc->cr->AddCall("getStringLiteral");
+ return jitInstance->mc->repGetStringLiteral(module, metaTOK, length);
+}
+
BOOL MyICJI::shouldEnforceCallvirtRestriction(CORINFO_MODULE_HANDLE scope)
{
jitInstance->mc->cr->AddCall("shouldEnforceCallvirtRestriction");
diff --git a/src/coreclr/src/binder/clrprivbinderassemblyloadcontext.cpp b/src/coreclr/src/binder/clrprivbinderassemblyloadcontext.cpp
index 657e6c304d1e2d..0881af5c599832 100644
--- a/src/coreclr/src/binder/clrprivbinderassemblyloadcontext.cpp
+++ b/src/coreclr/src/binder/clrprivbinderassemblyloadcontext.cpp
@@ -165,13 +165,6 @@ Exit:;
return hr;
}
-HRESULT CLRPrivBinderAssemblyLoadContext::GetBinderID(
- UINT_PTR *pBinderId)
-{
- *pBinderId = reinterpret_cast(this);
- return S_OK;
-}
-
HRESULT CLRPrivBinderAssemblyLoadContext::GetLoaderAllocator(LPVOID* pLoaderAllocator)
{
_ASSERTE(pLoaderAllocator != NULL);
diff --git a/src/coreclr/src/binder/clrprivbindercoreclr.cpp b/src/coreclr/src/binder/clrprivbindercoreclr.cpp
index f99fe465078c92..62d5f867beea5c 100644
--- a/src/coreclr/src/binder/clrprivbindercoreclr.cpp
+++ b/src/coreclr/src/binder/clrprivbindercoreclr.cpp
@@ -198,13 +198,6 @@ Exit:;
}
#endif // !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
-HRESULT CLRPrivBinderCoreCLR::GetBinderID(
- UINT_PTR *pBinderId)
-{
- *pBinderId = reinterpret_cast(this);
- return S_OK;
-}
-
HRESULT CLRPrivBinderCoreCLR::SetupBindingPaths(SString &sTrustedPlatformAssemblies,
SString &sPlatformResourceRoots,
SString &sAppPaths,
diff --git a/src/coreclr/src/binder/inc/clrprivbinderassemblyloadcontext.h b/src/coreclr/src/binder/inc/clrprivbinderassemblyloadcontext.h
index 6d012d9b1c684f..09695b09fc0108 100644
--- a/src/coreclr/src/binder/inc/clrprivbinderassemblyloadcontext.h
+++ b/src/coreclr/src/binder/inc/clrprivbinderassemblyloadcontext.h
@@ -23,8 +23,7 @@ class Object;
class Assembly;
class LoaderAllocator;
-class CLRPrivBinderAssemblyLoadContext :
- public IUnknownCommon
+class CLRPrivBinderAssemblyLoadContext : public AssemblyLoadContext
{
public:
@@ -35,9 +34,6 @@ class CLRPrivBinderAssemblyLoadContext :
/* [in] */ IAssemblyName *pIAssemblyName,
/* [retval][out] */ ICLRPrivAssembly **ppAssembly);
- STDMETHOD(GetBinderID)(
- /* [retval][out] */ UINT_PTR *pBinderId);
-
STDMETHOD(GetLoaderAllocator)(
/* [retval][out] */ LPVOID *pLoaderAllocator);
diff --git a/src/coreclr/src/binder/inc/clrprivbindercoreclr.h b/src/coreclr/src/binder/inc/clrprivbindercoreclr.h
index f5fd7d4653ea71..3779e5bd63a213 100644
--- a/src/coreclr/src/binder/inc/clrprivbindercoreclr.h
+++ b/src/coreclr/src/binder/inc/clrprivbindercoreclr.h
@@ -8,13 +8,14 @@
#include "coreclrbindercommon.h"
#include "applicationcontext.hpp"
+#include "assemblyloadcontext.h"
namespace BINDER_SPACE
{
class AssemblyIdentityUTF8;
};
-class CLRPrivBinderCoreCLR : public IUnknownCommon
+class CLRPrivBinderCoreCLR : public AssemblyLoadContext
{
public:
@@ -25,9 +26,6 @@ class CLRPrivBinderCoreCLR : public IUnknownCommon
-
diff --git a/src/coreclr/src/debug/CMakeLists.txt b/src/coreclr/src/debug/CMakeLists.txt
index bcfc257b9dbeca..fcba648128b102 100644
--- a/src/coreclr/src/debug/CMakeLists.txt
+++ b/src/coreclr/src/debug/CMakeLists.txt
@@ -1,6 +1,5 @@
add_subdirectory(daccess)
-add_subdirectory(dbgutil)
add_subdirectory(ildbsymlib)
add_subdirectory(ee)
add_subdirectory(di)
-add_subdirectory(shim)
\ No newline at end of file
+add_subdirectory(shim)
diff --git a/src/coreclr/src/debug/createdump/CMakeLists.txt b/src/coreclr/src/debug/createdump/CMakeLists.txt
index 16f79702aab7ee..e110566cb5088e 100644
--- a/src/coreclr/src/debug/createdump/CMakeLists.txt
+++ b/src/coreclr/src/debug/createdump/CMakeLists.txt
@@ -2,6 +2,8 @@ project(createdump)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
+include(configure.cmake)
+
# Set the RPATH of createdump so that it can find dependencies without needing to set LD_LIBRARY_PATH
# For more information: http://www.cmake.org/Wiki/CMake_RPATH_handling.
if (CORECLR_SET_RPATH)
@@ -42,6 +44,7 @@ add_dependencies(createdump pal_redefines_file)
target_link_libraries(createdump
createdump_lib
corguids
+ dbgutil
# share the PAL in the dac module
mscordaccore
)
diff --git a/src/coreclr/src/debug/createdump/config.h.in b/src/coreclr/src/debug/createdump/config.h.in
new file mode 100644
index 00000000000000..368627bbe50fd7
--- /dev/null
+++ b/src/coreclr/src/debug/createdump/config.h.in
@@ -0,0 +1,7 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#pragma once
+
+#cmakedefine HAVE_PROCESS_VM_READV
diff --git a/src/coreclr/src/debug/createdump/configure.cmake b/src/coreclr/src/debug/createdump/configure.cmake
new file mode 100644
index 00000000000000..9587b3f75f392a
--- /dev/null
+++ b/src/coreclr/src/debug/createdump/configure.cmake
@@ -0,0 +1,3 @@
+check_function_exists(process_vm_readv HAVE_PROCESS_VM_READV)
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
diff --git a/src/coreclr/src/debug/createdump/crashinfo.cpp b/src/coreclr/src/debug/createdump/crashinfo.cpp
index ec2ad71e053a0e..cfc6b5503a7e9d 100644
--- a/src/coreclr/src/debug/createdump/crashinfo.cpp
+++ b/src/coreclr/src/debug/createdump/crashinfo.cpp
@@ -371,15 +371,6 @@ CrashInfo::EnumerateModuleMappings()
if (moduleName != nullptr && *moduleName == '/')
{
- if (m_coreclrPath.empty())
- {
- std::string coreclrPath;
- coreclrPath.append(moduleName);
- size_t last = coreclrPath.rfind(MAKEDLLNAME_A("coreclr"));
- if (last != std::string::npos) {
- m_coreclrPath = coreclrPath.substr(0, last);
- }
- }
m_moduleMappings.insert(memoryRegion);
}
else
@@ -425,183 +416,64 @@ CrashInfo::GetDSOInfo()
assert(m_auxvValues[AT_PHENT] == sizeof(Phdr));
assert(phnum != PN_XNUM);
- if (phnum <= 0 || phdrAddr == nullptr) {
+ if (!PopulateELFInfo(phdrAddr, phnum)) {
return false;
}
- uint64_t baseAddress = (uint64_t)phdrAddr - sizeof(Ehdr);
- ElfW(Dyn)* dynamicAddr = nullptr;
-
- TRACE("DSO: base %" PRIA PRIx64 " phdr %p phnum %d\n", baseAddress, phdrAddr, phnum);
-
- // Enumerate program headers searching for the PT_DYNAMIC header, etc.
- if (!EnumerateProgramHeaders(phdrAddr, phnum, baseAddress, &dynamicAddr))
- {
- return false;
- }
- if (dynamicAddr == nullptr) {
- return false;
- }
-
- // Search for dynamic debug (DT_DEBUG) entry
- struct r_debug* rdebugAddr = nullptr;
- for (;;) {
- ElfW(Dyn) dyn;
- if (!ReadMemory(dynamicAddr, &dyn, sizeof(dyn))) {
- fprintf(stderr, "ReadMemory(%p, %" PRIx ") dyn FAILED\n", dynamicAddr, sizeof(dyn));
- return false;
- }
- TRACE("DSO: dyn %p tag %" PRId " (%" PRIx ") d_ptr %" PRIxA "\n", dynamicAddr, dyn.d_tag, dyn.d_tag, dyn.d_un.d_ptr);
- if (dyn.d_tag == DT_DEBUG) {
- rdebugAddr = reinterpret_cast(dyn.d_un.d_ptr);
- }
- else if (dyn.d_tag == DT_NULL) {
- break;
- }
- dynamicAddr++;
- }
-
- // Add the DSO r_debug entry
- TRACE("DSO: rdebugAddr %p\n", rdebugAddr);
- struct r_debug debugEntry;
- if (!ReadMemory(rdebugAddr, &debugEntry, sizeof(debugEntry))) {
- fprintf(stderr, "ReadMemory(%p, %" PRIx ") r_debug FAILED\n", rdebugAddr, sizeof(debugEntry));
+ if (!EnumerateLinkMapEntries()) {
return false;
}
-
- // Add the DSO link_map entries
- ArrayHolder moduleName = new char[PATH_MAX];
- for (struct link_map* linkMapAddr = debugEntry.r_map; linkMapAddr != nullptr;) {
- struct link_map map;
- if (!ReadMemory(linkMapAddr, &map, sizeof(map))) {
- fprintf(stderr, "ReadMemory(%p, %" PRIx ") link_map FAILED\n", linkMapAddr, sizeof(map));
- return false;
- }
- // Read the module's name and make sure the memory is added to the core dump
- int i = 0;
- if (map.l_name != nullptr) {
- for (; i < PATH_MAX; i++)
- {
- if (!ReadMemory(map.l_name + i, &moduleName[i], 1)) {
- TRACE("DSO: ReadMemory link_map name %p + %d FAILED\n", map.l_name, i);
- break;
- }
- if (moduleName[i] == '\0') {
- break;
- }
- }
- }
- moduleName[i] = '\0';
- TRACE("\nDSO: link_map entry %p l_ld %p l_addr (Ehdr) %" PRIx " %s\n", linkMapAddr, map.l_ld, map.l_addr, (char*)moduleName);
-
- // Read the ELF header and info adding it to the core dump
- if (!GetELFInfo(map.l_addr)) {
- return false;
- }
- linkMapAddr = map.l_next;
- }
-
return true;
}
//
// Add all the necessary ELF headers to the core dump
//
-bool
-CrashInfo::GetELFInfo(uint64_t baseAddress)
+void
+CrashInfo::VisitModule(uint64_t baseAddress, std::string& moduleName)
{
if (baseAddress == 0 || baseAddress == m_auxvValues[AT_SYSINFO_EHDR] || baseAddress == m_auxvValues[AT_BASE]) {
- return true;
- }
- Ehdr ehdr;
- if (!ReadMemory((void*)baseAddress, &ehdr, sizeof(ehdr))) {
- TRACE("ReadMemory(%p, %" PRIx ") ehdr FAILED\n", (void*)baseAddress, sizeof(ehdr));
- return true;
+ return;
}
- int phnum = ehdr.e_phnum;
- assert(phnum != PN_XNUM);
- assert(ehdr.e_phentsize == sizeof(Phdr));
-#ifdef HOST_64BIT
- assert(ehdr.e_ident[EI_CLASS] == ELFCLASS64);
-#else
- assert(ehdr.e_ident[EI_CLASS] == ELFCLASS32);
-#endif
- assert(ehdr.e_ident[EI_DATA] == ELFDATA2LSB);
-
- TRACE("ELF: type %d mach 0x%x ver %d flags 0x%x phnum %d phoff %" PRIxA " phentsize 0x%02x shnum %d shoff %" PRIxA " shentsize 0x%02x shstrndx %d\n",
- ehdr.e_type, ehdr.e_machine, ehdr.e_version, ehdr.e_flags, phnum, ehdr.e_phoff, ehdr.e_phentsize, ehdr.e_shnum, ehdr.e_shoff, ehdr.e_shentsize, ehdr.e_shstrndx);
-
- if (ehdr.e_phoff != 0 && phnum > 0)
+ if (m_coreclrPath.empty())
{
- Phdr* phdrAddr = reinterpret_cast(baseAddress + ehdr.e_phoff);
+ size_t last = moduleName.rfind(MAKEDLLNAME_A("coreclr"));
+ if (last != std::string::npos) {
+ m_coreclrPath = moduleName.substr(0, last);
- if (!EnumerateProgramHeaders(phdrAddr, phnum, baseAddress, nullptr))
- {
- return false;
+ // Now populate the elfreader with the runtime module info and
+ // lookup the DAC table symbol to ensure that all the memory
+ // necessary is in the core dump.
+ if (PopulateELFInfo(baseAddress)) {
+ uint64_t symbolOffset;
+ TryLookupSymbol("g_dacTable", &symbolOffset);
+ }
}
}
-
- return true;
+ EnumerateProgramHeaders(baseAddress, nullptr);
}
//
-// Enumerate the program headers adding the build id note, unwind frame
+// Called for each program header adding the build id note, unwind frame
// region and module addresses to the crash info.
//
-bool
-CrashInfo::EnumerateProgramHeaders(Phdr* phdrAddr, int phnum, uint64_t baseAddress, ElfW(Dyn)** pdynamicAddr)
+void
+CrashInfo::VisitProgramHeader(uint64_t loadbias, uint64_t baseAddress, Phdr* phdr)
{
- uint64_t loadbias = baseAddress;
-
- for (int i = 0; i < phnum; i++)
- {
- Phdr ph;
- if (!ReadMemory(phdrAddr + i, &ph, sizeof(ph))) {
- fprintf(stderr, "ReadMemory(%p, %" PRIx ") phdr FAILED\n", phdrAddr + i, sizeof(ph));
- return false;
- }
- if (ph.p_type == PT_LOAD && ph.p_offset == 0)
- {
- loadbias -= ph.p_vaddr;
- TRACE("PHDR: loadbias %" PRIA PRIx64 "\n", loadbias);
- break;
- }
- }
-
- for (int i = 0; i < phnum; i++)
+ switch (phdr->p_type)
{
- Phdr ph;
- if (!ReadMemory(phdrAddr + i, &ph, sizeof(ph))) {
- fprintf(stderr, "ReadMemory(%p, %" PRIx ") phdr FAILED\n", phdrAddr + i, sizeof(ph));
- return false;
+ case PT_DYNAMIC:
+ case PT_NOTE:
+ case PT_GNU_EH_FRAME:
+ if (phdr->p_vaddr != 0 && phdr->p_memsz != 0) {
+ InsertMemoryRegion(loadbias + phdr->p_vaddr, phdr->p_memsz);
}
- TRACE("PHDR: %p type %d (%x) vaddr %" PRIxA " memsz %" PRIxA " paddr %" PRIxA " filesz %" PRIxA " offset %" PRIxA " align %" PRIxA "\n",
- phdrAddr + i, ph.p_type, ph.p_type, ph.p_vaddr, ph.p_memsz, ph.p_paddr, ph.p_filesz, ph.p_offset, ph.p_align);
-
- switch (ph.p_type)
- {
- case PT_DYNAMIC:
- if (pdynamicAddr != nullptr)
- {
- *pdynamicAddr = reinterpret_cast(loadbias + ph.p_vaddr);
- break;
- }
- // fall into InsertMemoryRegion
+ break;
- case PT_NOTE:
- case PT_GNU_EH_FRAME:
- if (ph.p_vaddr != 0 && ph.p_memsz != 0) {
- InsertMemoryRegion(loadbias + ph.p_vaddr, ph.p_memsz);
- }
- break;
-
- case PT_LOAD:
- MemoryRegion region(0, loadbias + ph.p_vaddr, loadbias + ph.p_vaddr + ph.p_memsz, baseAddress);
- m_moduleAddresses.insert(region);
- break;
- }
+ case PT_LOAD:
+ MemoryRegion region(0, loadbias + phdr->p_vaddr, loadbias + phdr->p_vaddr + phdr->p_memsz, baseAddress);
+ m_moduleAddresses.insert(region);
+ break;
}
-
- return true;
}
//
@@ -1092,3 +964,14 @@ CrashInfo::GetStatus(pid_t pid, pid_t* ppid, pid_t* tgid, char** name)
fclose(statusFile);
return true;
}
+
+void
+CrashInfo::Trace(const char* format, ...)
+{
+ if (g_diagnostics) {
+ va_list ap;
+ va_start(ap, format);
+ vprintf(format, ap);
+ va_end(ap);
+ }
+}
diff --git a/src/coreclr/src/debug/createdump/crashinfo.h b/src/coreclr/src/debug/createdump/crashinfo.h
index 9fbc2119be625b..341e3af33e297a 100644
--- a/src/coreclr/src/debug/createdump/crashinfo.h
+++ b/src/coreclr/src/debug/createdump/crashinfo.h
@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+#include "../dbgutil/elfreader.h"
+
// typedef for our parsing of the auxv variables in /proc/pid/auxv.
#if defined(__i386) || defined(__ARM_EABI__)
typedef Elf32_auxv_t elf_aux_entry;
@@ -24,7 +26,7 @@ typedef __typeof__(((elf_aux_entry*) 0)->a_un.a_val) elf_aux_val_t;
// All interesting auvx entry types are AT_SYSINFO_EHDR and below
#define AT_MAX (AT_SYSINFO_EHDR + 1)
-class CrashInfo : public ICLRDataEnumMemoryRegionsCallback
+class CrashInfo : public ElfReader, public ICLRDataEnumMemoryRegionsCallback
{
private:
LONG m_ref; // reference count
@@ -78,10 +80,10 @@ class CrashInfo : public ICLRDataEnumMemoryRegionsCallback
private:
bool GetAuxvEntries();
- bool EnumerateModuleMappings();
bool GetDSOInfo();
- bool GetELFInfo(uint64_t baseAddress);
- bool EnumerateProgramHeaders(ElfW(Phdr)* phdrAddr, int phnum, uint64_t baseAddress, ElfW(Dyn)** pdynamicAddr);
+ void VisitModule(uint64_t baseAddress, std::string& moduleName);
+ void VisitProgramHeader(uint64_t loadbias, uint64_t baseAddress, ElfW(Phdr)* phdr);
+ bool EnumerateModuleMappings();
bool EnumerateMemoryRegionsWithDAC(MINIDUMP_TYPE minidumpType);
bool EnumerateManagedModules(IXCLRDataProcess* pClrDataProcess);
bool UnwindAllThreads(IXCLRDataProcess* pClrDataProcess);
@@ -91,4 +93,5 @@ class CrashInfo : public ICLRDataEnumMemoryRegionsCallback
uint32_t GetMemoryRegionFlags(uint64_t start);
bool ValidRegion(const MemoryRegion& region);
void CombineMemoryRegions();
+ void Trace(const char* format, ...);
};
diff --git a/src/coreclr/src/debug/createdump/createdump.h b/src/coreclr/src/debug/createdump/createdump.h
index 9771e24a934390..7627fb6e8611b2 100644
--- a/src/coreclr/src/debug/createdump/createdump.h
+++ b/src/coreclr/src/debug/createdump/createdump.h
@@ -16,6 +16,8 @@ extern bool g_diagnostics;
printf(args); \
}
+#include "config.h"
+
#include
#include
#include
diff --git a/src/coreclr/src/debug/daccess/CMakeLists.txt b/src/coreclr/src/debug/daccess/CMakeLists.txt
index dcd6fa1fdd873b..bbee976ecb2469 100644
--- a/src/coreclr/src/debug/daccess/CMakeLists.txt
+++ b/src/coreclr/src/debug/daccess/CMakeLists.txt
@@ -41,7 +41,9 @@ target_precompile_header(TARGET daccess HEADER stdafx.h)
add_dependencies(daccess eventing_headers)
-if(CLR_CMAKE_HOST_UNIX)
+if(CLR_CMAKE_HOST_DARWIN OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD)
+ add_definitions(-DUSE_DAC_TABLE_RVA)
+
add_custom_command(
OUTPUT ${GENERATED_INCLUDE_DIR}/dactablerva.h
DEPENDS coreclr
@@ -61,4 +63,4 @@ if(CLR_CMAKE_HOST_UNIX)
)
add_dependencies(daccess dactablerva_header)
-endif(CLR_CMAKE_HOST_UNIX)
+endif(CLR_CMAKE_HOST_DARWIN OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD)
diff --git a/src/coreclr/src/debug/daccess/daccess.cpp b/src/coreclr/src/debug/daccess/daccess.cpp
index 72a9c5130a60c0..fea12eb75fcacc 100644
--- a/src/coreclr/src/debug/daccess/daccess.cpp
+++ b/src/coreclr/src/debug/daccess/daccess.cpp
@@ -24,8 +24,13 @@
#include "dwreport.h"
#include "primitives.h"
#include "dbgutil.h"
+
#ifdef TARGET_UNIX
+#ifdef USE_DAC_TABLE_RVA
#include
+#else
+extern bool TryGetSymbol(ICorDebugDataTarget* dataTarget, uint64_t baseAddress, const char* symbolName, uint64_t* symbolAddress);
+#endif
#endif
#include "dwbucketmanager.hpp"
@@ -7245,16 +7250,39 @@ bool ClrDataAccess::MdCacheGetEEName(TADDR taEEStruct, SString & eeName)
#define _WIDE2(x) W(x)
HRESULT
-ClrDataAccess::GetDacGlobals()
+GetDacTableAddress(ICorDebugDataTarget* dataTarget, ULONG64 baseAddress, PULONG64 dacTableAddress)
{
#ifdef TARGET_UNIX
+#ifdef USE_DAC_TABLE_RVA
#ifdef DAC_TABLE_SIZE
if (DAC_TABLE_SIZE != sizeof(g_dacGlobals))
{
return E_INVALIDARG;
}
#endif
- ULONG64 dacTableAddress = m_globalBase + DAC_TABLE_RVA;
+ // On MacOS, FreeBSD or NetBSD use the RVA include file
+ *dacTableAddress = baseAddress + DAC_TABLE_RVA;
+#else
+ // On Linux try to get the dac table address via the export symbol
+ if (!TryGetSymbol(dataTarget, baseAddress, "g_dacTable", dacTableAddress))
+ {
+ return CORDBG_E_MISSING_DEBUGGER_EXPORTS;
+ }
+#endif
+#endif
+ return S_OK;
+}
+
+HRESULT
+ClrDataAccess::GetDacGlobals()
+{
+#ifdef TARGET_UNIX
+ ULONG64 dacTableAddress;
+ HRESULT hr = GetDacTableAddress(m_pTarget, m_globalBase, &dacTableAddress);
+ if (FAILED(hr))
+ {
+ return hr;
+ }
if (FAILED(ReadFromDataTarget(m_pTarget, dacTableAddress, (BYTE*)&g_dacGlobals, sizeof(g_dacGlobals))))
{
return CORDBG_E_MISSING_DEBUGGER_EXPORTS;
diff --git a/src/coreclr/src/debug/daccess/enummem.cpp b/src/coreclr/src/debug/daccess/enummem.cpp
index 1a5cff87ab0ce9..ec7fd1b0b72bd9 100644
--- a/src/coreclr/src/debug/daccess/enummem.cpp
+++ b/src/coreclr/src/debug/daccess/enummem.cpp
@@ -21,14 +21,12 @@
#include "binder.h"
#include "win32threadpool.h"
-#ifdef TARGET_UNIX
-#include
-#endif
-
#ifdef FEATURE_APPX
#include "appxutil.h"
#endif // FEATURE_APPX
+extern HRESULT GetDacTableAddress(ICorDebugDataTarget* dataTarget, ULONG64 baseAddress, PULONG64 dacTableAddress);
+
#if defined(DAC_MEASURE_PERF)
unsigned __int64 g_nTotalTime;
@@ -196,8 +194,13 @@ HRESULT ClrDataAccess::EnumMemCLRStatic(IN CLRDataEnumMemoryFlags flags)
ReportMem(m_globalBase + g_dacGlobals.id, sizeof(size_type));
#ifdef TARGET_UNIX
+ ULONG64 dacTableAddress;
+ HRESULT hr = GetDacTableAddress(m_pTarget, m_globalBase, &dacTableAddress);
+ if (FAILED(hr)) {
+ return hr;
+ }
// Add the dac table memory in coreclr
- CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED ( ReportMem(m_globalBase + DAC_TABLE_RVA, sizeof(g_dacGlobals)); )
+ CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED ( ReportMem(dacTableAddress, sizeof(g_dacGlobals)); )
#endif
// Cannot use CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED
diff --git a/src/coreclr/src/debug/daccess/nidump.cpp b/src/coreclr/src/debug/daccess/nidump.cpp
index 1f0c91e5faa82d..0b236337275709 100644
--- a/src/coreclr/src/debug/daccess/nidump.cpp
+++ b/src/coreclr/src/debug/daccess/nidump.cpp
@@ -8828,7 +8828,7 @@ void NativeImageDumper::DumpDictionaryEntry( const char * elementName,
}
#ifdef FEATURE_READYTORUN
-IMAGE_DATA_DIRECTORY * NativeImageDumper::FindReadyToRunSection(DWORD type)
+IMAGE_DATA_DIRECTORY * NativeImageDumper::FindReadyToRunSection(ReadyToRunSectionType type)
{
PTR_READYTORUN_SECTION pSections = dac_cast(dac_cast(m_pReadyToRunHeader) + sizeof(READYTORUN_HEADER));
for (DWORD i = 0; i < m_pReadyToRunHeader->NumberOfSections; i++)
@@ -8852,7 +8852,7 @@ void NativeImageDumper::DumpReadyToRun()
m_nativeReader = NativeFormat::NativeReader(dac_cast(m_decoder.GetBase()), m_decoder.GetVirtualSize());
- IMAGE_DATA_DIRECTORY * pRuntimeFunctionsDir = FindReadyToRunSection(READYTORUN_SECTION_RUNTIME_FUNCTIONS);
+ IMAGE_DATA_DIRECTORY * pRuntimeFunctionsDir = FindReadyToRunSection(ReadyToRunSectionType::RuntimeFunctions);
if (pRuntimeFunctionsDir != NULL)
{
m_pRuntimeFunctions = dac_cast(m_decoder.GetDirectoryData(pRuntimeFunctionsDir));
@@ -8863,7 +8863,7 @@ void NativeImageDumper::DumpReadyToRun()
m_nRuntimeFunctions = 0;
}
- IMAGE_DATA_DIRECTORY * pEntryPointsDir = FindReadyToRunSection(READYTORUN_SECTION_METHODDEF_ENTRYPOINTS);
+ IMAGE_DATA_DIRECTORY * pEntryPointsDir = FindReadyToRunSection(ReadyToRunSectionType::MethodDefEntryPoints);
if (pEntryPointsDir != NULL)
m_methodDefEntryPoints = NativeFormat::NativeArray((TADDR)&m_nativeReader, pEntryPointsDir->VirtualAddress);
diff --git a/src/coreclr/src/debug/daccess/nidump.h b/src/coreclr/src/debug/daccess/nidump.h
index a32a4d96bbbbc8..ab07e53ee71d0a 100644
--- a/src/coreclr/src/debug/daccess/nidump.h
+++ b/src/coreclr/src/debug/daccess/nidump.h
@@ -244,7 +244,7 @@ class NativeImageDumper
NativeFormat::NativeReader m_nativeReader;
NativeFormat::NativeArray m_methodDefEntryPoints;
- IMAGE_DATA_DIRECTORY * FindReadyToRunSection(DWORD type);
+ IMAGE_DATA_DIRECTORY * FindReadyToRunSection(ReadyToRunSectionType type);
public:
void DumpReadyToRun();
diff --git a/src/coreclr/src/debug/dbgutil/CMakeLists.txt b/src/coreclr/src/debug/dbgutil/CMakeLists.txt
index c432a32cefa3b1..2276831cbcbd51 100644
--- a/src/coreclr/src/debug/dbgutil/CMakeLists.txt
+++ b/src/coreclr/src/debug/dbgutil/CMakeLists.txt
@@ -5,8 +5,18 @@ endif(CLR_CMAKE_HOST_WIN32)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
+include_directories(${CLR_DIR}/src/inc/llvm)
+
+add_definitions(-DPAL_STDCPP_COMPAT)
+
set(DBGUTIL_SOURCES
dbgutil.cpp
)
+if(CLR_CMAKE_TARGET_LINUX)
+ list(APPEND DBGUTIL_SOURCES
+ elfreader.cpp
+ )
+endif(CLR_CMAKE_TARGET_LINUX)
+
add_library_clr(dbgutil STATIC ${DBGUTIL_SOURCES})
diff --git a/src/coreclr/src/debug/dbgutil/dbgutil.cpp b/src/coreclr/src/debug/dbgutil/dbgutil.cpp
index 62135af777d92f..0f30fdf55ff94b 100644
--- a/src/coreclr/src/debug/dbgutil/dbgutil.cpp
+++ b/src/coreclr/src/debug/dbgutil/dbgutil.cpp
@@ -17,6 +17,8 @@
#include
#include
+#ifdef HOST_WINDOWS
+
// Returns the RVA of the resource section for the module specified by the given data target and module base.
// Returns failure if the module doesn't have a resource section.
//
@@ -391,6 +393,8 @@ HRESULT GetNextLevelResourceEntryRVAByName(ICorDebugDataTarget* pDataTarget,
return hr;
}
+#endif // HOST_WINDOWS
+
// A small wrapper that reads from the data target and throws on error
HRESULT ReadFromDataTarget(ICorDebugDataTarget* pDataTarget,
ULONG64 addr,
diff --git a/src/coreclr/src/debug/dbgutil/elfreader.cpp b/src/coreclr/src/debug/dbgutil/elfreader.cpp
new file mode 100644
index 00000000000000..d345495f2e3572
--- /dev/null
+++ b/src/coreclr/src/debug/dbgutil/elfreader.cpp
@@ -0,0 +1,516 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#include "elfreader.h"
+#include
+
+#define Elf_Ehdr ElfW(Ehdr)
+#define Elf_Phdr ElfW(Phdr)
+#define Elf_Shdr ElfW(Shdr)
+#define Elf_Nhdr ElfW(Nhdr)
+#define Elf_Dyn ElfW(Dyn)
+#define Elf_Sym ElfW(Sym)
+
+#ifdef HOST_UNIX
+#define TRACE(args...) Trace(args)
+#else
+#define TRACE(args, ...)
+#endif
+
+#ifndef HOST_WINDOWS
+static const char ElfMagic[] = { 0x7f, 'E', 'L', 'F', '\0' };
+#endif
+
+class ElfReaderExport: public ElfReader
+{
+private:
+ ICorDebugDataTarget* m_dataTarget;
+
+public:
+ ElfReaderExport(ICorDebugDataTarget* dataTarget) :
+ m_dataTarget(dataTarget)
+ {
+ dataTarget->AddRef();
+ }
+
+ virtual ~ElfReaderExport()
+ {
+ m_dataTarget->Release();
+ }
+
+private:
+ virtual bool ReadMemory(void* address, void* buffer, size_t size)
+ {
+ uint32_t read = 0;
+ return SUCCEEDED(m_dataTarget->ReadVirtual(reinterpret_cast(address), reinterpret_cast(buffer), (uint32_t)size, &read));
+ }
+};
+
+//
+// Main entry point to get an export symbol
+//
+bool
+TryGetSymbol(ICorDebugDataTarget* dataTarget, uint64_t baseAddress, const char* symbolName, uint64_t* symbolAddress)
+{
+ ElfReaderExport elfreader(dataTarget);
+ if (elfreader.PopulateELFInfo(baseAddress))
+ {
+ uint64_t symbolOffset;
+ if (elfreader.TryLookupSymbol(symbolName, &symbolOffset))
+ {
+ *symbolAddress = baseAddress + symbolOffset;
+ return true;
+ }
+ }
+ *symbolAddress = 0;
+ return false;
+}
+
+//
+// ELF reader constructor/destructor
+//
+
+ElfReader::ElfReader() :
+ m_rdebugAddr(nullptr),
+ m_gnuHashTableAddr(nullptr),
+ m_stringTableAddr(nullptr),
+ m_stringTableSize(0),
+ m_symbolTableAddr(nullptr),
+ m_buckets(nullptr),
+ m_chainsAddress(nullptr)
+{
+ memset(&m_hashTable, 0, sizeof(m_hashTable));
+}
+
+ElfReader::~ElfReader()
+{
+ if (m_buckets != nullptr) {
+ delete m_buckets;
+ }
+}
+
+//
+// Initialize the ELF reader from a module the base address
+//
+bool
+ElfReader::PopulateELFInfo(uint64_t baseAddress)
+{
+ TRACE("PopulateELFInfo: base %" PRIA PRIx64 "\n", baseAddress);
+ Elf_Dyn* dynamicAddr = nullptr;
+
+ // Enumerate program headers searching for the PT_DYNAMIC header, etc.
+ if (!EnumerateProgramHeaders(baseAddress, &dynamicAddr)) {
+ return false;
+ }
+ return EnumerateDynamicEntries(dynamicAddr);
+}
+
+//
+// Initialize the ELF reader from the root program header
+//
+bool
+ElfReader::PopulateELFInfo(Elf_Phdr* phdrAddr, int phnum)
+{
+ TRACE("PopulateELFInfo: phdr %p phnum %d\n", phdrAddr, phnum);
+
+ if (phdrAddr == nullptr || phnum <= 0) {
+ return false;
+ }
+ uint64_t baseAddress = (uint64_t)phdrAddr - sizeof(Elf_Ehdr);
+ Elf_Dyn* dynamicAddr = nullptr;
+
+ // Enumerate program headers searching for the PT_DYNAMIC header, etc.
+ if (!EnumerateProgramHeaders(phdrAddr, phnum, baseAddress, &dynamicAddr)) {
+ return false;
+ }
+ return EnumerateDynamicEntries(dynamicAddr);
+}
+
+bool
+ElfReader::EnumerateDynamicEntries(Elf_Dyn* dynamicAddr)
+{
+ if (dynamicAddr == nullptr) {
+ return false;
+ }
+
+ // Search for dynamic entries
+ for (;;) {
+ Elf_Dyn dyn;
+ if (!ReadMemory(dynamicAddr, &dyn, sizeof(dyn))) {
+ TRACE("ERROR: ReadMemory(%p, %" PRIx ") dyn FAILED\n", dynamicAddr, sizeof(dyn));
+ return false;
+ }
+ TRACE("DSO: dyn %p tag %" PRId " (%" PRIx ") d_ptr %" PRIxA "\n", dynamicAddr, dyn.d_tag, dyn.d_tag, dyn.d_un.d_ptr);
+ if (dyn.d_tag == DT_NULL) {
+ break;
+ }
+ else if (dyn.d_tag == DT_DEBUG) {
+ m_rdebugAddr = (void*)dyn.d_un.d_ptr;
+ }
+ else if (dyn.d_tag == DT_GNU_HASH) {
+ m_gnuHashTableAddr = (void*)dyn.d_un.d_ptr;
+ }
+ else if (dyn.d_tag == DT_STRTAB) {
+ m_stringTableAddr = (void*)dyn.d_un.d_ptr;
+ }
+ else if (dyn.d_tag == DT_STRSZ) {
+ m_stringTableSize = (int)dyn.d_un.d_ptr;
+ }
+ else if (dyn.d_tag == DT_SYMTAB) {
+ m_symbolTableAddr = (void*)dyn.d_un.d_ptr;
+ }
+ dynamicAddr++;
+ }
+
+ if (m_gnuHashTableAddr == nullptr || m_stringTableAddr == nullptr || m_symbolTableAddr == nullptr) {
+ TRACE("ERROR: hash, string or symbol table address not found\n");
+ return false;
+ }
+
+ // Initialize the hash table
+ if (!InitializeGnuHashTable()) {
+ return false;
+ }
+
+ return true;
+}
+
+//
+// Symbol table support
+//
+
+bool
+ElfReader::TryLookupSymbol(std::string symbolName, uint64_t* symbolOffset)
+{
+ std::vector symbolIndexes;
+ if (GetPossibleSymbolIndex(symbolName, symbolIndexes)) {
+ Elf_Sym symbol;
+ for (int32_t possibleLocation : symbolIndexes)
+ {
+ if (GetSymbol(possibleLocation, &symbol))
+ {
+ std::string possibleName;
+ if (GetStringAtIndex(symbol.st_name, possibleName))
+ {
+ if (symbolName.compare(possibleName) == 0)
+ {
+ *symbolOffset = symbol.st_value;
+ TRACE("TryLookupSymbol found '%s' at offset %" PRIxA "\n", symbolName.c_str(), *symbolOffset);
+ return true;
+ }
+ }
+ }
+ }
+ }
+ TRACE("TryLookupSymbol '%s' not found\n", symbolName.c_str());
+ *symbolOffset = 0;
+ return false;
+}
+
+bool
+ElfReader::GetSymbol(int32_t index, Elf_Sym* symbol)
+{
+ int symSize = sizeof(Elf_Sym);
+ if (!ReadMemory((char*)m_symbolTableAddr + (index * symSize), symbol, symSize)) {
+ return false;
+ }
+ return true;
+}
+
+//
+// Hash (GNU) hash table support
+//
+
+bool
+ElfReader::InitializeGnuHashTable()
+{
+ if (!ReadMemory(m_gnuHashTableAddr, &m_hashTable, sizeof(m_hashTable))) {
+ TRACE("ERROR: InitializeGnuHashTable hashtable ReadMemory(%p) FAILED\n", m_gnuHashTableAddr);
+ return false;
+ }
+ if (m_hashTable.BucketCount <= 0 || m_hashTable.SymbolOffset == 0) {
+ TRACE("ERROR: InitializeGnuHashTable invalid BucketCount or SymbolOffset\n");
+ return false;
+ }
+ m_buckets = new (std::nothrow) int32_t[m_hashTable.BucketCount];
+ if (m_buckets == nullptr) {
+ return false;
+ }
+ void* bucketsAddress = (char*)m_gnuHashTableAddr + sizeof(GnuHashTable) + (m_hashTable.BloomSize * sizeof(size_t));
+ if (!ReadMemory(bucketsAddress, m_buckets, m_hashTable.BucketCount * sizeof(int32_t))) {
+ TRACE("ERROR: InitializeGnuHashTable buckets ReadMemory(%p) FAILED\n", bucketsAddress);
+ return false;
+ }
+ m_chainsAddress = (char*)bucketsAddress + (m_hashTable.BucketCount * sizeof(int32_t));
+ return true;
+}
+
+bool
+ElfReader::GetPossibleSymbolIndex(const std::string& symbolName, std::vector& symbolIndexes)
+{
+ uint32_t hash = Hash(symbolName);
+ int i = m_buckets[hash % m_hashTable.BucketCount] - m_hashTable.SymbolOffset;
+ TRACE("GetPossibleSymbolIndex hash %08x index: %d BucketCount %d SymbolOffset %08x\n", hash, i, m_hashTable.BucketCount, m_hashTable.SymbolOffset);
+ for (;; i++)
+ {
+ int32_t chainVal;
+ if (!GetChain(i, &chainVal)) {
+ TRACE("ERROR: GetPossibleSymbolIndex GetChain FAILED\n");
+ return false;
+ }
+ if ((chainVal & 0xfffffffe) == (hash & 0xfffffffe))
+ {
+ symbolIndexes.push_back(i + m_hashTable.SymbolOffset);
+ }
+ if ((chainVal & 0x1) == 0x1)
+ {
+ break;
+ }
+ }
+ return true;
+}
+
+uint32_t
+ElfReader::Hash(const std::string& symbolName)
+{
+ uint32_t h = 5381;
+ for (int i = 0; i < symbolName.length(); i++)
+ {
+ h = (h << 5) + h + symbolName[i];
+ }
+ return h;
+}
+
+bool
+ElfReader::GetChain(int index, int32_t* chain)
+{
+ return ReadMemory((char*)m_chainsAddress + (index * sizeof(int32_t)), chain, sizeof(int32_t));
+}
+
+//
+// String table support
+//
+
+bool
+ElfReader::GetStringAtIndex(int index, std::string& result)
+{
+ while(true)
+ {
+ if (index > m_stringTableSize) {
+ TRACE("ERROR: GetStringAtIndex index %d > string table size\n", index);
+ return false;
+ }
+ char ch;
+ void* address = (char*)m_stringTableAddr + index;
+ if (!ReadMemory(address, &ch, sizeof(ch))) {
+ TRACE("ERROR: GetStringAtIndex ReadMemory(%p) FAILED\n", address);
+ return false;
+ }
+ if (ch == '\0') {
+ break;
+ }
+ result.append(1, ch);
+ index++;
+ }
+ return true;
+}
+
+#ifdef HOST_UNIX
+
+//
+// Enumerate through the dynamic debug link map entries
+//
+bool
+ElfReader::EnumerateLinkMapEntries()
+{
+ struct r_debug* rdebugAddr = reinterpret_cast(m_rdebugAddr);
+ TRACE("DSO: rdebugAddr %p\n", rdebugAddr);
+
+ struct r_debug debugEntry;
+ if (!ReadMemory(rdebugAddr, &debugEntry, sizeof(debugEntry))) {
+ TRACE("ERROR: ReadMemory(%p, %" PRIx ") r_debug FAILED\n", rdebugAddr, sizeof(debugEntry));
+ return false;
+ }
+
+ // Add the DSO link_map entries
+ for (struct link_map* linkMapAddr = debugEntry.r_map; linkMapAddr != nullptr;) {
+ struct link_map map;
+ if (!ReadMemory(linkMapAddr, &map, sizeof(map))) {
+ TRACE("ERROR: ReadMemory(%p, %" PRIx ") link_map FAILED\n", linkMapAddr, sizeof(map));
+ return false;
+ }
+ // Read the module's name and make sure the memory is added to the core dump
+ std::string moduleName;
+ int i = 0;
+ if (map.l_name != nullptr) {
+ for (; i < PATH_MAX; i++)
+ {
+ char ch;
+ if (!ReadMemory(map.l_name + i, &ch, sizeof(ch))) {
+ TRACE("DSO: ReadMemory link_map name %p + %d FAILED\n", map.l_name, i);
+ break;
+ }
+ if (ch == '\0') {
+ break;
+ }
+ moduleName.append(1, ch);
+ }
+ }
+ TRACE("\nDSO: link_map entry %p l_ld %p l_addr (Ehdr) %" PRIx " %s\n", linkMapAddr, map.l_ld, map.l_addr, moduleName.c_str());
+
+ // Call the derived class for each module
+ VisitModule(map.l_addr, moduleName);
+
+ linkMapAddr = map.l_next;
+ }
+
+ return true;
+}
+
+#endif // HOST_UNIX
+
+bool
+ElfReader::EnumerateProgramHeaders(uint64_t baseAddress, Elf_Dyn** pdynamicAddr)
+{
+ Elf_Ehdr ehdr;
+ if (!ReadMemory((void*)baseAddress, &ehdr, sizeof(ehdr))) {
+ TRACE("ERROR: EnumerateProgramHeaders ReadMemory(%p, %" PRIx ") ehdr FAILED\n", (void*)baseAddress, sizeof(ehdr));
+ return false;
+ }
+ if (memcmp(ehdr.e_ident, ElfMagic, strlen(ElfMagic)) != 0) {
+ TRACE("ERROR: EnumerateProgramHeaders Invalid elf header signature\n");
+ return false;
+ }
+ int phnum = ehdr.e_phnum;
+ if (ehdr.e_phoff == 0 || phnum <= 0) {
+ return false;
+ }
+ TRACE("ELF: type %d mach 0x%x ver %d flags 0x%x phnum %d phoff %" PRIxA " phentsize 0x%02x shnum %d shoff %" PRIxA " shentsize 0x%02x shstrndx %d\n",
+ ehdr.e_type, ehdr.e_machine, ehdr.e_version, ehdr.e_flags, phnum, ehdr.e_phoff, ehdr.e_phentsize, ehdr.e_shnum, ehdr.e_shoff, ehdr.e_shentsize, ehdr.e_shstrndx);
+#ifdef PN_XNUM
+ _ASSERTE(phnum != PN_XNUM);
+#endif
+ _ASSERTE(ehdr.e_phentsize == sizeof(Elf_Phdr));
+#ifdef TARGET_64BIT
+ _ASSERTE(ehdr.e_ident[EI_CLASS] == ELFCLASS64);
+#else
+ _ASSERTE(ehdr.e_ident[EI_CLASS] == ELFCLASS32);
+#endif
+ _ASSERTE(ehdr.e_ident[EI_DATA] == ELFDATA2LSB);
+
+ Elf_Phdr* phdrAddr = reinterpret_cast(baseAddress + ehdr.e_phoff);
+ return EnumerateProgramHeaders(phdrAddr, phnum, baseAddress, pdynamicAddr);
+}
+
+//
+// Enumerate and find the dynamic program header entry
+//
+bool
+ElfReader::EnumerateProgramHeaders(Elf_Phdr* phdrAddr, int phnum, uint64_t baseAddress, Elf_Dyn** pdynamicAddr)
+{
+ uint64_t loadbias = baseAddress;
+
+ for (int i = 0; i < phnum; i++)
+ {
+ Elf_Phdr ph;
+ if (!ReadMemory(phdrAddr + i, &ph, sizeof(ph))) {
+ TRACE("ERROR: ReadMemory(%p, %" PRIx ") phdr FAILED\n", phdrAddr + i, sizeof(ph));
+ return false;
+ }
+ if (ph.p_type == PT_LOAD && ph.p_offset == 0) {
+ loadbias -= ph.p_vaddr;
+ TRACE("PHDR: loadbias %" PRIA PRIx64 "\n", loadbias);
+ break;
+ }
+ }
+
+ for (int i = 0; i < phnum; i++)
+ {
+ Elf_Phdr ph;
+ if (!ReadMemory(phdrAddr + i, &ph, sizeof(ph))) {
+ TRACE("ERROR: ReadMemory(%p, %" PRIx ") phdr FAILED\n", phdrAddr + i, sizeof(ph));
+ return false;
+ }
+ TRACE("PHDR: %p type %d (%x) vaddr %" PRIxA " memsz %" PRIxA " paddr %" PRIxA " filesz %" PRIxA " offset %" PRIxA " align %" PRIxA "\n",
+ phdrAddr + i, ph.p_type, ph.p_type, ph.p_vaddr, ph.p_memsz, ph.p_paddr, ph.p_filesz, ph.p_offset, ph.p_align);
+
+ switch (ph.p_type)
+ {
+ case PT_DYNAMIC:
+ if (pdynamicAddr != nullptr) {
+ *pdynamicAddr = reinterpret_cast(loadbias + ph.p_vaddr);
+ }
+ break;
+ }
+
+ // Give any derived classes a chance at the program header
+ VisitProgramHeader(loadbias, baseAddress, &ph);
+ }
+
+ return true;
+}
+
+#ifdef HOST_WINDOWS
+
+/* ELF 32bit header */
+Elf32_Ehdr::Elf32_Ehdr()
+{
+ e_ident[EI_MAG0] = ElfMagic[0];
+ e_ident[EI_MAG1] = ElfMagic[1];
+ e_ident[EI_MAG2] = ElfMagic[2];
+ e_ident[EI_MAG3] = ElfMagic[3];
+ e_ident[EI_CLASS] = ELFCLASS32;
+ e_ident[EI_DATA] = ELFDATA2LSB;
+ e_ident[EI_VERSION] = EV_CURRENT;
+ e_ident[EI_OSABI] = ELFOSABI_NONE;
+ e_ident[EI_ABIVERSION] = 0;
+ for (int i = EI_PAD; i < EI_NIDENT; ++i) {
+ e_ident[i] = 0;
+ }
+ e_type = ET_REL;
+#if defined(TARGET_X86)
+ e_machine = EM_386;
+#elif defined(TARGET_ARM)
+ e_machine = EM_ARM;
+#endif
+ e_flags = 0;
+ e_version = 1;
+ e_entry = 0;
+ e_phoff = 0;
+ e_ehsize = sizeof(Elf32_Ehdr);
+ e_phentsize = 0;
+ e_phnum = 0;
+}
+
+/* ELF 64bit header */
+Elf64_Ehdr::Elf64_Ehdr()
+{
+ e_ident[EI_MAG0] = ElfMagic[0];
+ e_ident[EI_MAG1] = ElfMagic[1];
+ e_ident[EI_MAG2] = ElfMagic[2];
+ e_ident[EI_MAG3] = ElfMagic[3];
+ e_ident[EI_CLASS] = ELFCLASS64;
+ e_ident[EI_DATA] = ELFDATA2LSB;
+ e_ident[EI_VERSION] = EV_CURRENT;
+ e_ident[EI_OSABI] = ELFOSABI_NONE;
+ e_ident[EI_ABIVERSION] = 0;
+ for (int i = EI_PAD; i < EI_NIDENT; ++i) {
+ e_ident[i] = 0;
+ }
+ e_type = ET_REL;
+#if defined(TARGET_AMD64)
+ e_machine = EM_X86_64;
+#elif defined(TARGET_ARM64)
+ e_machine = EM_AARCH64;
+#endif
+ e_flags = 0;
+ e_version = 1;
+ e_entry = 0;
+ e_phoff = 0;
+ e_ehsize = sizeof(Elf64_Ehdr);
+ e_phentsize = 0;
+ e_phnum = 0;
+}
+
+#endif // HOST_WINDOWS
diff --git a/src/coreclr/src/debug/dbgutil/elfreader.h b/src/coreclr/src/debug/dbgutil/elfreader.h
new file mode 100644
index 00000000000000..77129bbcf1a38d
--- /dev/null
+++ b/src/coreclr/src/debug/dbgutil/elfreader.h
@@ -0,0 +1,86 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#include
+#include
+#include
+#include
+#define __STDC_FORMAT_MACROS
+#include
+#include
+#ifdef HOST_UNIX
+#include
+#endif // HOST_UNIX
+#include
+#include
+
+#if TARGET_64BIT
+#define PRIx PRIx64
+#define PRIu PRIu64
+#define PRId PRId64
+#define PRIA "016"
+#define PRIxA PRIA PRIx
+#define TARGET_WORDSIZE 64
+#else
+#define PRIx PRIx32
+#define PRIu PRIu32
+#define PRId PRId32
+#define PRIA "08"
+#define PRIxA PRIA PRIx
+#define TARGET_WORDSIZE 32
+#endif
+
+#ifndef ElfW
+/* We use this macro to refer to ELF types independent of the native wordsize.
+ `ElfW(TYPE)' is used in place of `Elf32_TYPE' or `Elf64_TYPE'. */
+#define ElfW(type) _ElfW (Elf, TARGET_WORDSIZE, type)
+#define _ElfW(e,w,t) _ElfW_1 (e, w, _##t)
+#define _ElfW_1(e,w,t) e##w##t
+#endif
+
+typedef struct {
+ int32_t BucketCount;
+ int32_t SymbolOffset;
+ int32_t BloomSize;
+ int32_t BloomShift;
+} GnuHashTable;
+
+class ElfReader
+{
+private:
+ void* m_rdebugAddr; // DT_DEBUG
+ void* m_gnuHashTableAddr; // DT_GNU_HASH
+ void* m_stringTableAddr; // DT_STRTAB
+ int m_stringTableSize; // DT_STRSIZ
+ void* m_symbolTableAddr; // DT_SYMTAB
+
+ GnuHashTable m_hashTable; // gnu hash table info
+ int32_t* m_buckets; // gnu hash table buckets
+ void* m_chainsAddress;
+
+public:
+ ElfReader();
+ virtual ~ElfReader();
+ bool PopulateELFInfo(uint64_t baseAddress);
+ bool PopulateELFInfo(ElfW(Phdr)* phdrAddr, int phnum);
+ bool TryLookupSymbol(std::string symbolName, uint64_t* symbolOffset);
+#ifdef HOST_UNIX
+ bool EnumerateLinkMapEntries();
+#endif
+ bool EnumerateProgramHeaders(uint64_t baseAddress, ElfW(Dyn)** pdynamicAddr);
+ bool EnumerateProgramHeaders(ElfW(Phdr)* phdrAddr, int phnum, uint64_t baseAddress, ElfW(Dyn)** pdynamicAddr);
+
+private:
+ bool GetSymbol(int32_t index, ElfW(Sym)* symbol);
+ bool InitializeGnuHashTable();
+ bool GetPossibleSymbolIndex(const std::string& symbolName, std::vector& symbolIndexes);
+ uint32_t Hash(const std::string& symbolName);
+ bool GetChain(int index, int32_t* chain);
+ bool GetStringAtIndex(int index, std::string& result);
+ bool EnumerateDynamicEntries(ElfW(Dyn)* dynamicAddr);
+ virtual void VisitModule(uint64_t baseAddress, std::string& moduleName) { };
+ virtual void VisitProgramHeader(uint64_t loadbias, uint64_t baseAddress, ElfW(Phdr)* phdr) { };
+ virtual bool ReadMemory(void* address, void* buffer, size_t size) = 0;
+ virtual void Trace(const char* format, ...) { };
+};
diff --git a/src/coreclr/src/debug/ee/amd64/gen_amd64InstrDecode/Amd64InstructionTableGenerator.cs b/src/coreclr/src/debug/ee/amd64/gen_amd64InstrDecode/Amd64InstructionTableGenerator.cs
index 9e2ce2da1190c8..d90a1278c80dcb 100644
--- a/src/coreclr/src/debug/ee/amd64/gen_amd64InstrDecode/Amd64InstructionTableGenerator.cs
+++ b/src/coreclr/src/debug/ee/amd64/gen_amd64InstrDecode/Amd64InstructionTableGenerator.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
diff --git a/src/coreclr/src/debug/ee/controller.cpp b/src/coreclr/src/debug/ee/controller.cpp
index 03b27612e5a5e6..137fcf774067db 100644
--- a/src/coreclr/src/debug/ee/controller.cpp
+++ b/src/coreclr/src/debug/ee/controller.cpp
@@ -8961,7 +8961,7 @@ bool DebuggerContinuableExceptionBreakpoint::SendEvent(Thread *thread, bool fIpC
CONTEXT contextToAdjust;
BOOL adjustedContext = FALSE;
memcpy(&contextToAdjust, pContext, sizeof(CONTEXT));
- adjustedContext = g_pEEInterface->AdjustContextForWriteBarrierForDebugger(&contextToAdjust);
+ adjustedContext = g_pEEInterface->AdjustContextForJITHelpersForDebugger(&contextToAdjust);
if (adjustedContext)
{
LOG((LF_CORDB, LL_INFO10000, "D::DDBP: HIT DATA BREAKPOINT INSIDE WRITE BARRIER...\n"));
diff --git a/src/coreclr/src/debug/ee/dactable.cpp b/src/coreclr/src/debug/ee/dactable.cpp
index 2f601249064899..967ac69bc28c4d 100644
--- a/src/coreclr/src/debug/ee/dactable.cpp
+++ b/src/coreclr/src/debug/ee/dactable.cpp
@@ -40,6 +40,7 @@ extern DWORD gAppDomainTLSIndex;
extern BOOL g_fAppX;
#endif // FEATURE_APPX
+DLLEXPORT
DacGlobals g_dacTable;
// DAC global pointer table initialization
diff --git a/src/coreclr/src/debug/inc/twowaypipe.h b/src/coreclr/src/debug/inc/twowaypipe.h
index 18942b4a4ba8d6..5a3d78ea97f74c 100644
--- a/src/coreclr/src/debug/inc/twowaypipe.h
+++ b/src/coreclr/src/debug/inc/twowaypipe.h
@@ -8,7 +8,7 @@
#include "processdescriptor.h"
-#ifdef TARGET_UNIX
+#ifdef HOST_UNIX
#define INVALID_PIPE -1
#else
#define INVALID_PIPE INVALID_HANDLE_VALUE
@@ -83,7 +83,7 @@ class TwoWayPipe
State m_state;
-#ifdef TARGET_UNIX
+#ifdef HOST_UNIX
int m_inboundPipe, m_outboundPipe; // two one sided pipes used for communication
char m_inPipeName[MAX_DEBUGGER_TRANSPORT_PIPE_NAME_LENGTH]; // filename of the inbound pipe
@@ -99,7 +99,7 @@ class TwoWayPipe
HANDLE CreateOneWayPipe(DWORD id, bool inbound);
HANDLE m_inboundPipe, m_outboundPipe; //two one sided pipes used for communication
-#endif //TARGET_UNIX
+#endif //HOST_UNIX
};
#endif //TwoWayPipe_H
diff --git a/src/coreclr/src/dlls/mscordac/CMakeLists.txt b/src/coreclr/src/dlls/mscordac/CMakeLists.txt
index ba45564b05296f..e5bc381a0679ef 100644
--- a/src/coreclr/src/dlls/mscordac/CMakeLists.txt
+++ b/src/coreclr/src/dlls/mscordac/CMakeLists.txt
@@ -5,7 +5,7 @@ set(CLR_DAC_SOURCES
add_definitions(-DFX_VER_INTERNALNAME_STR=mscordaccore.dll)
-if(CLR_CMAKE_TARGET_WIN32)
+if(CLR_CMAKE_HOST_WIN32)
list(APPEND CLR_DAC_SOURCES
Native.rc
)
@@ -24,7 +24,7 @@ if(CLR_CMAKE_TARGET_WIN32)
# No library groups for Win32
set(START_LIBRARY_GROUP)
set(END_LIBRARY_GROUP)
-else(CLR_CMAKE_TARGET_WIN32)
+else(CLR_CMAKE_HOST_WIN32)
set(DEF_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/mscordac_unixexports.src)
set(EXPORTS_FILE ${CMAKE_CURRENT_BINARY_DIR}/mscordac.exports)
@@ -71,7 +71,7 @@ else(CLR_CMAKE_TARGET_WIN32)
# Add lib redefines file to DAC
list(APPEND CLR_DAC_SOURCES libredefines.S)
endif(CLR_CMAKE_HOST_LINUX)
-endif(CLR_CMAKE_TARGET_WIN32)
+endif(CLR_CMAKE_HOST_WIN32)
if(CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD)
# This option is necessary to ensure that the overloaded delete operator defined inside
@@ -136,6 +136,12 @@ set(COREDAC_LIBRARIES
)
if(CLR_CMAKE_TARGET_WIN32)
+ list(APPEND COREDAC_LIBRARIES
+ mdwinmd_dac
+ )
+endif(CLR_CMAKE_TARGET_WIN32)
+
+if(CLR_CMAKE_HOST_WIN32)
# mscordac.def should be generated before mscordaccore.dll is built
add_dependencies(mscordaccore mscordaccore_def)
@@ -160,7 +166,6 @@ if(CLR_CMAKE_TARGET_WIN32)
set(COREDAC_LIBRARIES
${CMAKE_CURRENT_BINARY_DIR}/mscordaccore.exp # export file
${COREDAC_LIBRARIES}
- mdwinmd_dac
kernel32.lib
advapi32.lib
ole32.lib
@@ -170,7 +175,7 @@ if(CLR_CMAKE_TARGET_WIN32)
${STATIC_MT_CRT_LIB}
${STATIC_MT_VCRT_LIB}
)
-else(CLR_CMAKE_TARGET_WIN32)
+else(CLR_CMAKE_HOST_WIN32)
list(APPEND COREDAC_LIBRARIES
mscorrc_debug
${START_WHOLE_ARCHIVE} # force all PAL objects to be included so all exports are available
@@ -178,7 +183,7 @@ else(CLR_CMAKE_TARGET_WIN32)
palrt
${END_WHOLE_ARCHIVE}
)
-endif(CLR_CMAKE_TARGET_WIN32)
+endif(CLR_CMAKE_HOST_WIN32)
target_link_libraries(mscordaccore PRIVATE ${COREDAC_LIBRARIES})
@@ -186,7 +191,7 @@ target_link_libraries(mscordaccore PRIVATE ${COREDAC_LIBRARIES})
install_clr(TARGETS mscordaccore)
install_clr(TARGETS mscordaccore DESTINATION sharedFramework SKIP_STRIP)
-if(CLR_CMAKE_TARGET_WIN32)
+if(CLR_CMAKE_HOST_WIN32)
set(LONG_NAME_HOST_ARCH ${CLR_CMAKE_HOST_ARCH})
set(LONG_NAME_TARGET_ARCH ${CLR_CMAKE_TARGET_ARCH})
if (LONG_NAME_HOST_ARCH STREQUAL x64)
diff --git a/src/coreclr/src/dlls/mscoree/coreclr/CMakeLists.txt b/src/coreclr/src/dlls/mscoree/coreclr/CMakeLists.txt
index 0745ad4ad22f73..1f5f62509a1409 100644
--- a/src/coreclr/src/dlls/mscoree/coreclr/CMakeLists.txt
+++ b/src/coreclr/src/dlls/mscoree/coreclr/CMakeLists.txt
@@ -90,6 +90,7 @@ set(CORECLR_LIBRARIES
debug-pal
${LIB_UNWINDER}
cee_wks
+ v3binder
${END_LIBRARY_GROUP} # End group of libraries that have circular references
mdcompiler_wks
mdruntime_wks
@@ -103,7 +104,7 @@ set(CORECLR_LIBRARIES
gcinfo # Condition="'$(TargetCpu)'=='amd64' or '$(TargetCpu)' == 'arm' or '$(TargetCpu)' == 'arm64'"
ildbsymlib
utilcode
- v3binder
+ libraries-native
)
if(CLR_CMAKE_TARGET_WIN32)
diff --git a/src/coreclr/src/dlls/mscoree/mscorwks_unixexports.src b/src/coreclr/src/dlls/mscoree/mscorwks_unixexports.src
index 1085876f981dc1..2f742f327198fb 100644
--- a/src/coreclr/src/dlls/mscoree/mscorwks_unixexports.src
+++ b/src/coreclr/src/dlls/mscoree/mscorwks_unixexports.src
@@ -8,3 +8,6 @@ coreclr_shutdown_2
; Functions exported by the coreclr
DllMain
GetCLRRuntimeHost
+; DAC table export
+g_dacTable
+
diff --git a/src/coreclr/src/dlls/mscorrc/full/CMakeLists.txt b/src/coreclr/src/dlls/mscorrc/full/CMakeLists.txt
index 5414e790146b5e..ffdb8a3b146419 100644
--- a/src/coreclr/src/dlls/mscorrc/full/CMakeLists.txt
+++ b/src/coreclr/src/dlls/mscorrc/full/CMakeLists.txt
@@ -1,6 +1,6 @@
add_definitions(-DFX_VER_INTERNALNAME_STR=mscorrc.debug.dll)
-if(CLR_CMAKE_TARGET_WIN32)
+if(CLR_CMAKE_HOST_WIN32)
add_library_clr(mscorrc.debug SHARED
../include.rc
@@ -16,5 +16,5 @@ else()
${TARGET_CPP_FILE}
)
-endif(CLR_CMAKE_TARGET_WIN32)
+endif(CLR_CMAKE_HOST_WIN32)
diff --git a/src/coreclr/src/dlls/mscorrc/mscorrc.rc b/src/coreclr/src/dlls/mscorrc/mscorrc.rc
index 6cb75fb81d7df6..fb8905d8e9d3e0 100644
--- a/src/coreclr/src/dlls/mscorrc/mscorrc.rc
+++ b/src/coreclr/src/dlls/mscorrc/mscorrc.rc
@@ -795,7 +795,6 @@ BEGIN
IDS_HOST_ASSEMBLY_RESOLVER_ASSEMBLY_ALREADY_LOADED_IN_CONTEXT "Assembly with same name is already loaded"
IDS_HOST_ASSEMBLY_RESOLVER_DYNAMICALLY_EMITTED_ASSEMBLIES_UNSUPPORTED "Dynamically emitted assemblies are unsupported during host-based resolution."
IDS_HOST_ASSEMBLY_RESOLVER_INCOMPATIBLE_BINDING_CONTEXT "Assembly is already bound to an incompatible binding context."
- IDS_HOST_ASSEMBLY_RESOLVER_INCOMPATIBLE_TPA_BINDING_CONTEXT "Default binding context is already attached to managed load context."
END
STRINGTABLE DISCARDABLE
diff --git a/src/coreclr/src/dlls/mscorrc/resource.h b/src/coreclr/src/dlls/mscorrc/resource.h
index 519e17273b2bd3..05f7346773d4d8 100644
--- a/src/coreclr/src/dlls/mscorrc/resource.h
+++ b/src/coreclr/src/dlls/mscorrc/resource.h
@@ -618,7 +618,6 @@
#define IDS_HOST_ASSEMBLY_RESOLVER_ASSEMBLY_ALREADY_LOADED_IN_CONTEXT 0x2636
#define IDS_HOST_ASSEMBLY_RESOLVER_DYNAMICALLY_EMITTED_ASSEMBLIES_UNSUPPORTED 0x2637
#define IDS_HOST_ASSEMBLY_RESOLVER_INCOMPATIBLE_BINDING_CONTEXT 0x2638
-#define IDS_HOST_ASSEMBLY_RESOLVER_INCOMPATIBLE_TPA_BINDING_CONTEXT 0x2639
#define IDS_NATIVE_IMAGE_CANNOT_BE_LOADED_MULTIPLE_TIMES 0x263a
diff --git a/src/coreclr/src/gc/env/gcenv.unix.inl b/src/coreclr/src/gc/env/gcenv.unix.inl
index 42b8a434a05813..cc71651c57fc0b 100644
--- a/src/coreclr/src/gc/env/gcenv.unix.inl
+++ b/src/coreclr/src/gc/env/gcenv.unix.inl
@@ -11,9 +11,11 @@ extern uint32_t g_pageSizeUnixInl;
#define OS_PAGE_SIZE GCToOSInterface::GetPageSize()
+#ifndef DACCESS_COMPILE
__forceinline size_t GCToOSInterface::GetPageSize()
{
return g_pageSizeUnixInl;
}
+#endif // DACCESS_COMPILE
#endif // __GCENV_UNIX_INL__
diff --git a/src/coreclr/src/gc/gc.cpp b/src/coreclr/src/gc/gc.cpp
index 63598a3fa34b2e..44020b3b74a155 100644
--- a/src/coreclr/src/gc/gc.cpp
+++ b/src/coreclr/src/gc/gc.cpp
@@ -1022,50 +1022,44 @@ class t_join
if (Interlocked::CompareExchange(&join_struct.r_join_lock, 0, join_struct.n_threads) == 0)
{
- if (!join_struct.wait_done)
- {
- dprintf (JOIN_LOG, ("r_join() Waiting..."));
+ fire_event (gch->heap_number, time_start, type_join, join_id);
- fire_event (gch->heap_number, time_start, type_join, join_id);
+ dprintf (JOIN_LOG, ("r_join() Waiting..."));
- //busy wait around the color
- if (!join_struct.wait_done)
- {
+ //busy wait around the color
respin:
- int spin_count = 256 * yp_spin_count_unit;
- for (int j = 0; j < spin_count; j++)
- {
- if (join_struct.wait_done)
- {
- break;
- }
- YieldProcessor(); // indicate to the processor that we are spinning
- }
-
- // we've spun, and if color still hasn't changed, fall into hard wait
- if (!join_struct.wait_done)
- {
- dprintf (JOIN_LOG, ("Join() hard wait on reset event %d", first_thread_arrived));
- uint32_t dwJoinWait = join_struct.joined_event[first_thread_arrived].Wait(INFINITE, FALSE);
- if (dwJoinWait != WAIT_OBJECT_0)
- {
- STRESS_LOG1 (LF_GC, LL_FATALERROR, "joined event wait failed with code: %Ix", dwJoinWait);
- FATAL_GC_ERROR ();
- }
- }
-
- // avoid race due to the thread about to reset the event (occasionally) being preempted before ResetEvent()
- if (!join_struct.wait_done)
- {
- goto respin;
- }
+ int spin_count = 256 * yp_spin_count_unit;
+ for (int j = 0; j < spin_count; j++)
+ {
+ if (join_struct.wait_done)
+ {
+ break;
+ }
+ YieldProcessor(); // indicate to the processor that we are spinning
+ }
- dprintf (JOIN_LOG, ("r_join() done"));
+ // we've spun, and if color still hasn't changed, fall into hard wait
+ if (!join_struct.wait_done)
+ {
+ dprintf (JOIN_LOG, ("Join() hard wait on reset event %d", first_thread_arrived));
+ uint32_t dwJoinWait = join_struct.joined_event[first_thread_arrived].Wait(INFINITE, FALSE);
+ if (dwJoinWait != WAIT_OBJECT_0)
+ {
+ STRESS_LOG1 (LF_GC, LL_FATALERROR, "joined event wait failed with code: %Ix", dwJoinWait);
+ FATAL_GC_ERROR ();
}
+ }
- fire_event (gch->heap_number, time_end, type_join, join_id);
+ // avoid race due to the thread about to reset the event (occasionally) being preempted before ResetEvent()
+ if (!join_struct.wait_done)
+ {
+ goto respin;
}
+ dprintf (JOIN_LOG, ("r_join() done"));
+
+ fire_event (gch->heap_number, time_end, type_join, join_id);
+
return FALSE;
}
else
@@ -2415,7 +2409,10 @@ static static_data static_data_table[latency_level_last - latency_level_first +
// gen2
{256*1024, SSIZE_T_MAX, 200000, 0.25f, 1.2f, 1.8f, 100000, 100},
// loh
- {3*1024*1024, SSIZE_T_MAX, 0, 0.0f, 1.25f, 4.5f, 0, 0}
+ {3*1024*1024, SSIZE_T_MAX, 0, 0.0f, 1.25f, 4.5f, 0, 0},
+ // poh
+ // TODO: tuning https://github.com/dotnet/runtime/issues/13739
+ {3*1024*1024, SSIZE_T_MAX, 0, 0.0f, 1.25f, 4.5f, 0, 0},
},
// latency_level_balanced
@@ -2433,6 +2430,9 @@ static static_data static_data_table[latency_level_last - latency_level_first +
// gen2
{256*1024, SSIZE_T_MAX, 200000, 0.25f, 1.2f, 1.8f, 100000, 100},
// loh
+ {3*1024*1024, SSIZE_T_MAX, 0, 0.0f, 1.25f, 4.5f, 0, 0},
+ // poh
+ // TODO: tuning https://github.com/dotnet/runtime/issues/13739
{3*1024*1024, SSIZE_T_MAX, 0, 0.0f, 1.25f, 4.5f, 0, 0}
},
};
@@ -2764,6 +2764,8 @@ size_t gc_heap::bgc_overflow_count = 0;
size_t gc_heap::bgc_begin_loh_size = 0;
size_t gc_heap::end_loh_size = 0;
+size_t gc_heap::bgc_begin_poh_size = 0;
+size_t gc_heap::end_poh_size = 0;
#ifdef BGC_SERVO_TUNING
uint64_t gc_heap::loh_a_no_bgc = 0;
@@ -2779,6 +2781,8 @@ uint32_t gc_heap::bgc_alloc_spin_uoh = 0;
size_t gc_heap::bgc_loh_size_increased = 0;
+size_t gc_heap::bgc_poh_size_increased = 0;
+
size_t gc_heap::background_soh_alloc_count = 0;
size_t gc_heap::background_uoh_alloc_count = 0;
@@ -2963,6 +2967,7 @@ BOOL gc_heap::heap_analyze_enabled = FALSE;
alloc_list gc_heap::loh_alloc_list [NUM_LOH_ALIST-1];
alloc_list gc_heap::gen2_alloc_list[NUM_GEN2_ALIST-1];
+alloc_list gc_heap::poh_alloc_list [NUM_POH_ALIST-1];
dynamic_data gc_heap::dynamic_data_table [total_generation_count];
gc_history_per_heap gc_heap::gc_data_per_heap;
@@ -3008,6 +3013,7 @@ CFinalize* gc_heap::finalize_queue = 0;
VOLATILE(uint32_t) gc_heap::card_mark_chunk_index_soh;
VOLATILE(bool) gc_heap::card_mark_done_soh;
VOLATILE(uint32_t) gc_heap::card_mark_chunk_index_loh;
+VOLATILE(uint32_t) gc_heap::card_mark_chunk_index_poh;
VOLATILE(bool) gc_heap::card_mark_done_uoh;
#endif // FEATURE_CARD_MARKING_STEALING
@@ -4338,13 +4344,16 @@ typedef struct
imemory_data *initial_memory;
imemory_data *initial_normal_heap; // points into initial_memory_array
imemory_data *initial_large_heap; // points into initial_memory_array
+ imemory_data *initial_pinned_heap; // points into initial_memory_array
size_t block_size_normal;
size_t block_size_large;
+ size_t block_size_pinned;
int block_count; // # of blocks in each
int current_block_normal;
int current_block_large;
+ int current_block_pinned;
enum
{
@@ -4361,6 +4370,7 @@ typedef struct
{
case 0: return block_size_normal;
case 1: return block_size_large;
+ case 2: return block_size_pinned;
default: __UNREACHABLE();
}
};
@@ -4373,6 +4383,7 @@ typedef struct
case soh_gen1:
case soh_gen2: return initial_normal_heap[h_number].memory_base;
case loh_generation: return initial_large_heap[h_number].memory_base;
+ case poh_generation: return initial_pinned_heap[h_number].memory_base;
default: __UNREACHABLE();
}
};
@@ -4385,6 +4396,7 @@ typedef struct
case soh_gen1:
case soh_gen2: return block_size_normal;
case loh_generation: return block_size_large;
+ case poh_generation: return block_size_pinned;
default: __UNREACHABLE();
}
};
@@ -4393,15 +4405,15 @@ typedef struct
initial_memory_details memory_details;
-BOOL reserve_initial_memory (size_t normal_size, size_t large_size, int num_heaps, bool use_large_pages_p)
+BOOL reserve_initial_memory (size_t normal_size, size_t large_size, size_t pinned_size, int num_heaps, bool use_large_pages_p)
{
BOOL reserve_success = FALSE;
// should only be called once
assert (memory_details.initial_memory == 0);
- // soh + loh segments * num_heaps
- memory_details.initial_memory = new (nothrow) imemory_data[num_heaps * (total_generation_count - ephemeral_generation_count)];
+ // soh + loh + poh segments * num_heaps
+ memory_details.initial_memory = new (nothrow) imemory_data[num_heaps * (total_generation_count - ephemeral_generation_count)];
if (memory_details.initial_memory == 0)
{
dprintf (2, ("failed to reserve %Id bytes for imemory_data", num_heaps * (total_generation_count - ephemeral_generation_count) * sizeof (imemory_data)));
@@ -4410,13 +4422,16 @@ BOOL reserve_initial_memory (size_t normal_size, size_t large_size, int num_heap
memory_details.initial_normal_heap = memory_details.initial_memory;
memory_details.initial_large_heap = memory_details.initial_normal_heap + num_heaps;
+ memory_details.initial_pinned_heap = memory_details.initial_large_heap + num_heaps;
memory_details.block_size_normal = normal_size;
memory_details.block_size_large = large_size;
+ memory_details.block_size_pinned = pinned_size;
memory_details.block_count = num_heaps;
memory_details.current_block_normal = 0;
memory_details.current_block_large = 0;
+ memory_details.current_block_pinned = 0;
g_gc_lowest_address = MAX_PTR;
g_gc_highest_address = 0;
@@ -4428,13 +4443,13 @@ BOOL reserve_initial_memory (size_t normal_size, size_t large_size, int num_heap
return FALSE;
}
- if (((size_t)MAX_PTR / memory_details.block_count) < (normal_size + large_size))
+ if (((size_t)MAX_PTR / memory_details.block_count) < (normal_size + large_size + pinned_size))
{
dprintf (2, ("(0x%Ix + 0x%Ix)*0x%Ix overflow", normal_size, large_size, memory_details.block_count));
return FALSE;
}
- size_t requestedMemory = memory_details.block_count * (normal_size + large_size);
+ size_t requestedMemory = memory_details.block_count * (normal_size + large_size + pinned_size);
uint8_t* allatonce_block = (uint8_t*)virtual_alloc (requestedMemory, use_large_pages_p);
if (allatonce_block)
@@ -4449,27 +4464,32 @@ BOOL reserve_initial_memory (size_t normal_size, size_t large_size, int num_heap
(i * normal_size);
memory_details.initial_large_heap[i].memory_base = allatonce_block +
(memory_details.block_count * normal_size) + (i * large_size);
+ memory_details.initial_pinned_heap[i].memory_base = allatonce_block +
+ (memory_details.block_count * (normal_size + large_size)) + (i * pinned_size);
reserve_success = TRUE;
}
}
else
{
- // try to allocate 2 blocks
+ // try to allocate 3 blocks
uint8_t* b1 = (uint8_t*)virtual_alloc (memory_details.block_count * normal_size, use_large_pages_p);
uint8_t* b2 = (uint8_t*)virtual_alloc (memory_details.block_count * large_size, use_large_pages_p);
+ uint8_t* b3 = (uint8_t*)virtual_alloc (memory_details.block_count * pinned_size, use_large_pages_p);
- if (b1 && b2)
+ if (b1 && b2 && b3)
{
memory_details.allocation_pattern = initial_memory_details::EACH_GENERATION;
- g_gc_lowest_address = min (b1, b2);
+ g_gc_lowest_address = min (b1, min(b2, b3));
g_gc_highest_address = max (b1 + memory_details.block_count * normal_size,
- b2 + memory_details.block_count * large_size);
+ max (b2 + memory_details.block_count * large_size,
+ b3 + memory_details.block_count * pinned_size));
for (int i = 0; i < memory_details.block_count; i++)
{
memory_details.initial_normal_heap[i].memory_base = b1 + (i * normal_size);
memory_details.initial_large_heap[i].memory_base = b2 + (i * large_size);
+ memory_details.initial_pinned_heap[i].memory_base = b3 + (i * pinned_size);
}
reserve_success = TRUE;
@@ -4482,6 +4502,8 @@ BOOL reserve_initial_memory (size_t normal_size, size_t large_size, int num_heap
virtual_free (b1, memory_details.block_count * normal_size);
if (b2)
virtual_free (b2, memory_details.block_count * large_size);
+ if (b3)
+ virtual_free (b3, memory_details.block_count * pinned_size);
}
if ((b2 == NULL) && (memory_details.block_count > 1))
@@ -4539,12 +4561,15 @@ void destroy_initial_memory()
virtual_free (memory_details.initial_large_heap[0].memory_base,
memory_details.block_count*memory_details.block_size_large);
+
+ virtual_free (memory_details.initial_pinned_heap[0].memory_base,
+ memory_details.block_count*memory_details.block_size_pinned);
}
else
{
assert (memory_details.allocation_pattern == initial_memory_details::EACH_BLOCK);
imemory_data *current_block = memory_details.initial_memory;
- for(int i = 0; i < (memory_details.block_count*2); i++, current_block++)
+ for (int i = 0; i < (memory_details.block_count*(total_generation_count - ephemeral_generation_count)); i++, current_block++)
{
size_t block_size = memory_details.block_size (i);
if (current_block->memory_base != NULL)
@@ -4558,6 +4583,7 @@ void destroy_initial_memory()
memory_details.initial_memory = NULL;
memory_details.initial_normal_heap = NULL;
memory_details.initial_large_heap = NULL;
+ memory_details.initial_pinned_heap = NULL;
}
}
@@ -5018,7 +5044,9 @@ heap_segment* gc_heap::get_segment_for_uoh (int gen_number, size_t size
#ifdef MULTIPLE_HEAPS
heap_segment_heap (res) = hp;
#endif //MULTIPLE_HEAPS
- res->flags |= heap_segment_flags_loh;
+ res->flags |= gen_number == poh_generation ?
+ heap_segment_flags_poh :
+ heap_segment_flags_loh;
FIRE_EVENT(GCCreateSegment_V1, heap_segment_mem(res), (size_t)(heap_segment_reserved (res) - heap_segment_mem(res)), gc_etw_segment_large_object_heap);
@@ -6426,7 +6454,7 @@ void gc_heap::fix_uoh_allocation_area (BOOL for_gc_p)
{
UNREFERENCED_PARAMETER(for_gc_p);
- for(int i = uoh_start_generation; i < total_generation_count; i++)
+ for (int i = uoh_start_generation; i < total_generation_count; i++)
{
#ifdef _DEBUG
alloc_context* acontext =
@@ -8207,7 +8235,7 @@ void gc_heap::copy_brick_card_range (uint8_t* la, uint32_t* old_card_table,
// We don't need to go through all the card tables here because
// we only need to copy from the GC version of the mark array - when we
- // mark (even in allocate_large_object) we always use that mark array.
+ // mark (even in allocate_uoh_object) we always use that mark array.
if ((card_table_highest_address (old_ct) >= start) &&
(card_table_lowest_address (old_ct) <= end))
{
@@ -10380,7 +10408,8 @@ size_t gc_heap::get_segment_size_hard_limit (uint32_t* num_heaps, bool should_ad
}
HRESULT gc_heap::initialize_gc (size_t soh_segment_size,
- size_t loh_segment_size
+ size_t loh_segment_size,
+ size_t poh_segment_size
#ifdef MULTIPLE_HEAPS
,int number_of_heaps
#endif //MULTIPLE_HEAPS
@@ -10500,7 +10529,7 @@ HRESULT gc_heap::initialize_gc (size_t soh_segment_size,
#endif //BACKGROUND_GC
reserved_memory = 0;
- size_t initial_heap_size = soh_segment_size + loh_segment_size;
+ size_t initial_heap_size = soh_segment_size + loh_segment_size + poh_segment_size;
#ifdef MULTIPLE_HEAPS
reserved_memory_limit = initial_heap_size * number_of_heaps;
#else //MULTIPLE_HEAPS
@@ -10513,7 +10542,7 @@ HRESULT gc_heap::initialize_gc (size_t soh_segment_size,
check_commit_cs.Initialize();
}
- if (!reserve_initial_memory (soh_segment_size, loh_segment_size, number_of_heaps, use_large_pages_p))
+ if (!reserve_initial_memory (soh_segment_size, loh_segment_size, poh_segment_size, number_of_heaps, use_large_pages_p))
return E_OUTOFMEMORY;
#ifdef CARD_BUNDLE
@@ -11179,7 +11208,7 @@ gc_heap::init_gc_heap (int h_number)
#endif //!SEG_MAPPING_TABLE
- // Create segments for the large generation
+ // Create segments for the large and pinned generations
heap_segment* lseg = make_initial_segment(loh_generation, h_number);
if (!lseg)
return 0;
@@ -11190,19 +11219,36 @@ gc_heap::init_gc_heap (int h_number)
(size_t)(heap_segment_reserved (lseg) - heap_segment_mem(lseg)),
gc_etw_segment_large_object_heap);
+ heap_segment* pseg = make_initial_segment(poh_generation, h_number);
+ if (!pseg)
+ return 0;
+
+ pseg->flags |= heap_segment_flags_poh;
+
+ FIRE_EVENT(GCCreateSegment_V1, heap_segment_mem(pseg),
+ (size_t)(heap_segment_reserved (pseg) - heap_segment_mem(pseg)),
+ gc_etw_segment_pinned_object_heap);
+
#ifdef SEG_MAPPING_TABLE
seg_mapping_table_add_segment (lseg, __this);
+ seg_mapping_table_add_segment (pseg, __this);
#else //SEG_MAPPING_TABLE
seg_table->insert ((uint8_t*)lseg, sdelta);
+ seg_table->insert ((uint8_t*)pseg, sdelta);
#endif //SEG_MAPPING_TABLE
make_generation (loh_generation, lseg, heap_segment_mem (lseg), 0);
+ make_generation (poh_generation, pseg, heap_segment_mem (pseg), 0);
heap_segment_allocated (lseg) = heap_segment_mem (lseg) + Align (min_obj_size, get_alignment_constant (FALSE));
heap_segment_used (lseg) = heap_segment_allocated (lseg) - plug_skew;
+ heap_segment_allocated (pseg) = heap_segment_mem (pseg) + Align (min_obj_size, get_alignment_constant (FALSE));
+ heap_segment_used (pseg) = heap_segment_allocated (pseg) - plug_skew;
+
generation_of (max_generation)->free_list_allocator = allocator(NUM_GEN2_ALIST, BASE_GEN2_ALIST, gen2_alloc_list);
generation_of (loh_generation)->free_list_allocator = allocator(NUM_LOH_ALIST, BASE_LOH_ALIST, loh_alloc_list);
+ generation_of (poh_generation)->free_list_allocator = allocator(NUM_POH_ALIST, BASE_POH_ALIST, poh_alloc_list);
for (int gen_num = 0; gen_num < total_generation_count; gen_num++)
{
@@ -11212,10 +11258,12 @@ gc_heap::init_gc_heap (int h_number)
#ifdef MULTIPLE_HEAPS
heap_segment_heap (lseg) = this;
+ heap_segment_heap (pseg) = this;
//initialize the alloc context heap
generation_alloc_context (generation_of (soh_gen0))->set_alloc_heap(vm_heap);
generation_alloc_context (generation_of (loh_generation))->set_alloc_heap(vm_heap);
+ generation_alloc_context (generation_of (poh_generation))->set_alloc_heap(vm_heap);
#endif //MULTIPLE_HEAPS
@@ -11385,6 +11433,7 @@ gc_heap::init_gc_heap (int h_number)
background_uoh_alloc_count = 0;
bgc_overflow_count = 0;
end_loh_size = dd_min_size (dynamic_data_of (loh_generation));
+ end_poh_size = dd_min_size (dynamic_data_of (poh_generation));
#endif //BACKGROUND_GC
#ifdef GC_CONFIG_DRIVEN
@@ -13444,6 +13493,15 @@ int gc_heap::bgc_loh_allocate_spin()
return bgc_allocate_spin(min_gc_size, bgc_begin_size, bgc_size_increased, end_size);
}
+int gc_heap::bgc_poh_allocate_spin()
+{
+ size_t min_gc_size = dd_min_size (dynamic_data_of (poh_generation));
+ size_t bgc_begin_size = bgc_begin_poh_size;
+ size_t bgc_size_increased = bgc_poh_size_increased;
+ size_t end_size = end_poh_size;
+
+ return bgc_allocate_spin(min_gc_size, bgc_begin_size, bgc_size_increased, end_size);
+}
#endif //BACKGROUND_GC
size_t gc_heap::get_uoh_seg_size (size_t size)
@@ -13699,7 +13757,9 @@ allocation_state gc_heap::allocate_uoh (int gen_number,
}
#endif //BGC_SERVO_TUNING
- int spin_for_allocation = bgc_loh_allocate_spin();
+ int spin_for_allocation = (gen_number == loh_generation) ?
+ bgc_loh_allocate_spin() :
+ bgc_poh_allocate_spin();
if (spin_for_allocation >= 0)
{
@@ -15560,7 +15620,7 @@ int gc_heap::joined_generation_to_condemn (BOOL should_evaluate_elevation,
else
{
dprintf (GTC_LOG, ("reducing gen in PM: %d->%d->%d", initial_gen, n, (max_generation - 1)));
- gc_data_global.gen_to_condemn_reasons.set_condition(gen_joined_last_gen2_fragmented);
+ gc_data_global.gen_to_condemn_reasons.set_condition(gen_joined_gen1_in_pm);
n = max_generation - 1;
}
}
@@ -15601,8 +15661,11 @@ int gc_heap::joined_generation_to_condemn (BOOL should_evaluate_elevation,
// If there's not much fragmentation but it looks like it'll be productive to
// collect LOH, do that.
size_t est_loh_reclaim = get_total_gen_estimated_reclaim (loh_generation);
- gc_data_global.gen_to_condemn_reasons.set_condition(gen_joined_limit_loh_reclaim);
- full_compact_gc_p = ((est_loh_reclaim * 8) >= heap_hard_limit);
+ if ((est_loh_reclaim * 8) >= heap_hard_limit)
+ {
+ gc_data_global.gen_to_condemn_reasons.set_condition(gen_joined_limit_loh_reclaim);
+ full_compact_gc_p = true;
+ }
dprintf (GTC_LOG, ("loh est reclaim: %Id, 1/8 of limit %Id", est_loh_reclaim, (heap_hard_limit / 8)));
}
}
@@ -16411,7 +16474,8 @@ int gc_heap::generation_to_condemn (int n_initial,
for (int i = 0; i < n_heaps; i++)
{
if (((g_heaps[i]->current_generation_size (max_generation)) > bgc_min_per_heap) ||
- ((g_heaps[i]->current_generation_size (loh_generation)) > bgc_min_per_heap))
+ ((g_heaps[i]->current_generation_size (loh_generation)) > bgc_min_per_heap) ||
+ ((g_heaps[i]->current_generation_size (poh_generation)) > bgc_min_per_heap))
{
bgc_heap_too_small = FALSE;
break;
@@ -16419,7 +16483,8 @@ int gc_heap::generation_to_condemn (int n_initial,
}
#else //MULTIPLE_HEAPS
if ((current_generation_size (max_generation) > bgc_min_per_heap) ||
- (current_generation_size (loh_generation) > bgc_min_per_heap))
+ (current_generation_size (loh_generation) > bgc_min_per_heap) ||
+ (current_generation_size (poh_generation) > bgc_min_per_heap))
{
bgc_heap_too_small = FALSE;
}
@@ -17650,6 +17715,7 @@ void gc_heap::update_collection_counts ()
if (i == max_generation)
{
dd_collection_count (dynamic_data_of (loh_generation))++;
+ dd_collection_count(dynamic_data_of(poh_generation))++;
}
dd_gc_clock (dd) = dd_gc_clock (dd0);
@@ -21149,9 +21215,12 @@ void gc_heap::mark_phase (int condemned_gen_number, BOOL mark_only_p)
#endif // MULTIPLE_HEAPS && FEATURE_CARD_MARKING_STEALING
{
dprintf (3, ("Marking cross generation pointers for uoh objects on heap %d", heap_number));
- for(int i = uoh_start_generation; i < total_generation_count; i++)
+ for (int i = uoh_start_generation; i < total_generation_count; i++)
{
- mark_through_cards_for_uoh_objects(mark_object_fn, i, FALSE THIS_ARG);
+#ifndef ALLOW_REFERENCES_IN_POH
+ if (i != poh_generation)
+#endif //ALLOW_REFERENCES_IN_POH
+ mark_through_cards_for_uoh_objects(mark_object_fn, i, FALSE THIS_ARG);
}
#if defined(MULTIPLE_HEAPS) && defined(FEATURE_CARD_MARKING_STEALING)
@@ -21175,9 +21244,12 @@ void gc_heap::mark_phase (int condemned_gen_number, BOOL mark_only_p)
if (!hp->card_mark_done_uoh)
{
dprintf(3, ("Marking cross generation pointers for large objects on heap %d", hp->heap_number));
- for(int i = uoh_start_generation; i < total_generation_count; i++)
+ for (int i = uoh_start_generation; i < total_generation_count; i++)
{
- hp->mark_through_cards_for_uoh_objects(mark_object_fn, i, FALSE THIS_ARG);
+#ifndef ALLOW_REFERENCES_IN_POH
+ if (i != poh_generation)
+#endif //ALLOW_REFERENCES_IN_POH
+ hp->mark_through_cards_for_uoh_objects(mark_object_fn, i, FALSE THIS_ARG);
}
hp->card_mark_done_uoh = true;
@@ -23924,6 +23996,8 @@ void gc_heap::plan_phase (int condemned_gen_number)
GCToEEInterface::DiagWalkLOHSurvivors(__this);
sweep_uoh_objects (loh_generation);
}
+
+ sweep_uoh_objects (poh_generation);
}
else
{
@@ -25897,8 +25971,14 @@ void gc_heap::relocate_phase (int condemned_gen_number,
if (!card_mark_done_uoh)
#endif // MULTIPLE_HEAPS && FEATURE_CARD_MARKING_STEALING
{
- dprintf (3, ("Relocating cross generation pointers for large objects on heap %d", heap_number));
- mark_through_cards_for_uoh_objects(&gc_heap::relocate_address, loh_generation, TRUE THIS_ARG);
+ dprintf (3, ("Relocating cross generation pointers for uoh objects on heap %d", heap_number));
+ for (int i = uoh_start_generation; i < total_generation_count; i++)
+ {
+#ifndef ALLOW_REFERENCES_IN_POH
+ if (i != poh_generation)
+#endif //ALLOW_REFERENCES_IN_POH
+ mark_through_cards_for_uoh_objects(&gc_heap::relocate_address, i, TRUE THIS_ARG);
+ }
#if defined(MULTIPLE_HEAPS) && defined(FEATURE_CARD_MARKING_STEALING)
card_mark_done_uoh = true;
@@ -25918,6 +25998,10 @@ void gc_heap::relocate_phase (int condemned_gen_number,
{
relocate_in_uoh_objects (loh_generation);
}
+
+#ifdef ALLOW_REFERENCES_IN_POH
+ relocate_in_uoh_objects (poh_generation);
+#endif
}
#ifndef FEATURE_CARD_MARKING_STEALING
// moved this code *before* we scan the older generations via mark_through_cards_xxx
@@ -25961,8 +26045,14 @@ void gc_heap::relocate_phase (int condemned_gen_number,
if (!hp->card_mark_done_uoh)
{
- dprintf(3, ("Relocating cross generation pointers for large objects on heap %d", hp->heap_number));
- hp->mark_through_cards_for_uoh_objects(&gc_heap::relocate_address, loh_generation, TRUE THIS_ARG);
+ dprintf(3, ("Relocating cross generation pointers for uoh objects on heap %d", hp->heap_number));
+ for (int i = uoh_start_generation; i < total_generation_count; i++)
+ {
+#ifndef ALLOW_REFERENCES_IN_POH
+ if (i != poh_generation)
+#endif //ALLOW_REFERENCES_IN_POH
+ hp->mark_through_cards_for_uoh_objects(&gc_heap::relocate_address, i, TRUE THIS_ARG);
+ }
hp->card_mark_done_uoh = true;
}
}
@@ -27169,10 +27259,13 @@ void gc_heap::background_mark_phase ()
size_t total_soh_size = generation_sizes (generation_of (max_generation));
size_t total_loh_size = generation_size (loh_generation);
+ size_t total_poh_size = generation_size (poh_generation);
bgc_begin_loh_size = total_loh_size;
+ bgc_begin_poh_size = total_poh_size;
bgc_loh_size_increased = 0;
+ bgc_poh_size_increased = 0;
- dprintf (GTC_LOG, ("BM: h%d: loh: %Id, soh: %Id", heap_number, total_loh_size, total_soh_size));
+ dprintf (GTC_LOG, ("BM: h%d: loh: %Id, soh: %Id, poh: %Id", heap_number, total_loh_size, total_soh_size, total_poh_size));
{
//concurrent_print_time_delta ("copying stack roots");
@@ -27449,8 +27542,9 @@ void gc_heap::background_mark_phase ()
total_soh_size = generation_sizes (generation_of (max_generation));
total_loh_size = generation_size (loh_generation);
+ total_poh_size = generation_size (poh_generation);
- dprintf (GTC_LOG, ("FM: h%d: loh: %Id, soh: %Id", heap_number, total_loh_size, total_soh_size));
+ dprintf (GTC_LOG, ("FM: h%d: loh: %Id, soh: %Id, poh: %Id", heap_number, total_loh_size, total_soh_size, total_poh_size));
dprintf (2, ("nonconcurrent marking stack roots"));
GCScan::GcScanRoots(background_promote,
@@ -27594,8 +27688,9 @@ void gc_heap::background_mark_phase ()
gen0_bricks_cleared = FALSE;
- dprintf (2, ("end of bgc mark: loh: %d, soh: %d",
+ dprintf (2, ("end of bgc mark: loh: %d, poh: %d, soh: %d",
generation_size (loh_generation),
+ generation_size (poh_generation),
generation_sizes (generation_of (max_generation))));
for (int gen_idx = max_generation; gen_idx < total_generation_count; gen_idx++)
@@ -27906,7 +28001,7 @@ void gc_heap::revisit_written_pages (BOOL concurrent_p, BOOL reset_only_p)
bool reset_watch_state = !!concurrent_p;
bool is_runtime_suspended = !concurrent_p;
BOOL small_object_segments = TRUE;
- for(int i = max_generation; i < total_generation_count; i++)
+ for (int i = max_generation; i < total_generation_count; i++)
{
heap_segment* seg = heap_segment_rw (generation_start_segment (generation_of (i)));
PREFIX_ASSUME(seg != NULL);
@@ -32801,6 +32896,10 @@ void gc_heap::compute_new_dynamic_data (int gen_number)
#ifdef BACKGROUND_GC
if (i == loh_generation)
end_loh_size = total_gen_size;
+
+ if (i == poh_generation)
+ end_poh_size = total_gen_size;
+
#endif //BACKGROUND_GC
//update counter
dd_promoted_size (dd) = out;
@@ -33373,7 +33472,7 @@ BOOL gc_heap::ephemeral_gen_fit_p (gc_tuning_point tp)
}
}
-CObjectHeader* gc_heap::allocate_large_object (size_t jsize, uint32_t flags, int64_t& alloc_bytes)
+CObjectHeader* gc_heap::allocate_uoh_object (size_t jsize, uint32_t flags, int gen_number, int64_t& alloc_bytes)
{
//create a new alloc context because gen3context is shared.
alloc_context acontext;
@@ -33396,17 +33495,19 @@ CObjectHeader* gc_heap::allocate_large_object (size_t jsize, uint32_t flags, int
size_t size = AlignQword (jsize);
int align_const = get_alignment_constant (FALSE);
-#ifdef FEATURE_LOH_COMPACTION
- size_t pad = Align (loh_padding_obj_size, align_const);
-#else
size_t pad = 0;
+#ifdef FEATURE_LOH_COMPACTION
+ if (gen_number == loh_generation)
+ {
+ pad = Align (loh_padding_obj_size, align_const);
+ }
#endif //FEATURE_LOH_COMPACTION
assert (size >= Align (min_obj_size, align_const));
#ifdef _MSC_VER
#pragma inline_depth(0)
#endif //_MSC_VER
- if (! allocate_more_space (&acontext, (size + pad), flags, loh_generation))
+ if (! allocate_more_space (&acontext, (size + pad), flags, gen_number))
{
return 0;
}
@@ -33450,8 +33551,6 @@ CObjectHeader* gc_heap::allocate_large_object (size_t jsize, uint32_t flags, int
mark_array_clear_marked (result);
}
#ifdef BACKGROUND_GC
- //the object has to cover one full mark uint32_t
- assert (size >= mark_word_size);
if (current_c_gc_state != c_gc_state_free)
{
dprintf (3, ("Concurrent allocation of a large object %Ix",
@@ -34298,8 +34397,9 @@ void gc_heap::background_sweep()
size_t total_soh_size = generation_sizes (generation_of (max_generation));
size_t total_loh_size = generation_size (loh_generation);
+ size_t total_poh_size = generation_size (poh_generation);
- dprintf (GTC_LOG, ("loh: %Id, soh: %Id", heap_number, total_loh_size, total_soh_size));
+ dprintf (GTC_LOG, ("h%d: S: poh: %Id, loh: %Id, soh: %Id", heap_number, total_poh_size, total_loh_size, total_soh_size));
dprintf (GTC_LOG, ("end of bgc sweep: gen2 FL: %Id, FO: %Id",
generation_free_list_space (generation_of (max_generation)),
@@ -34310,6 +34410,11 @@ void gc_heap::background_sweep()
generation_free_list_space (generation_of (loh_generation)),
generation_free_obj_space (generation_of (loh_generation))));
+ dprintf (GTC_LOG, ("h%d: end of bgc sweep: poh FL: %Id, FO: %Id",
+ heap_number,
+ generation_free_list_space (generation_of (poh_generation)),
+ generation_free_obj_space (generation_of (poh_generation))));
+
FIRE_EVENT(BGC2ndConEnd);
concurrent_print_time_delta ("background sweep");
@@ -34559,7 +34664,9 @@ void gc_heap::mark_through_cards_for_uoh_objects (card_fn fn,
size_t total_cards_cleared = 0;
#ifdef FEATURE_CARD_MARKING_STEALING
- VOLATILE(uint32_t)* chunk_index = (VOLATILE(uint32_t)*) & card_mark_chunk_index_loh;
+ VOLATILE(uint32_t)* chunk_index = (VOLATILE(uint32_t)*) &(gen_num == loh_generation ?
+ card_mark_chunk_index_loh :
+ card_mark_chunk_index_poh);
card_marking_enumerator card_mark_enumerator(seg, low, chunk_index);
card_word_end = 0;
@@ -35454,7 +35561,7 @@ void gc_heap::verify_partial ()
BOOL bad_ref_p = FALSE;
BOOL free_ref_p = FALSE;
- for(int i = max_generation; i < total_generation_count; i++)
+ for (int i = max_generation; i < total_generation_count; i++)
{
generation* gen = generation_of (i);
int align_const = get_alignment_constant (i == max_generation);
@@ -36353,9 +36460,11 @@ HRESULT GCHeap::Initialize()
#ifdef MULTIPLE_HEAPS
gc_heap::n_heaps = nhp;
- hr = gc_heap::initialize_gc (seg_size, large_seg_size /*loh_segment_size*/, nhp);
+ // TODO: tuning https://github.com/dotnet/runtime/issues/13739
+ hr = gc_heap::initialize_gc (seg_size, large_seg_size /*loh_segment_size*/, large_seg_size /*poh_segment_size*/, nhp);
#else
- hr = gc_heap::initialize_gc (seg_size, large_seg_size /*loh_segment_size*/);
+ // TODO: tuning https://github.com/dotnet/runtime/issues/13739
+ hr = gc_heap::initialize_gc (seg_size, large_seg_size /*loh_segment_size*/, large_seg_size /*poh_segment_size*/);
#endif //MULTIPLE_HEAPS
if (hr != S_OK)
@@ -36414,7 +36523,7 @@ HRESULT GCHeap::Initialize()
#ifndef FEATURE_REDHAWK // Redhawk forces relocation a different way
#if defined (STRESS_HEAP) && !defined (MULTIPLE_HEAPS)
if (GCStress::IsEnabled()) {
- for(int i = 0; i < GCHeap::NUM_HEAP_STRESS_OBJS; i++)
+ for (int i = 0; i < GCHeap::NUM_HEAP_STRESS_OBJS; i++)
{
m_StressObjs[i] = CreateGlobalHandle(0);
}
@@ -37160,7 +37269,7 @@ GCHeap::AllocAlign8Common(void* _hp, alloc_context* acontext, size_t size, uint3
alloc_context* acontext = generation_alloc_context (hp->generation_of (loh_generation));
- newAlloc = (Object*) hp->allocate_large_object (size, flags, acontext->alloc_bytes_uoh);
+ newAlloc = (Object*) hp->allocate_uoh_object (size, flags, loh_generation, acontext->alloc_bytes_uoh);
ASSERT(((size_t)newAlloc & 7) == 0);
}
@@ -37205,7 +37314,7 @@ GCHeap::AllocLHeap( size_t size, uint32_t flags REQD_ALIGN_DCL)
#endif //MULTIPLE_HEAPS
alloc_context* acontext = generation_alloc_context (hp->generation_of (loh_generation));
- newAlloc = (Object*) hp->allocate_large_object (size + ComputeMaxStructAlignPadLarge(requiredAlignment), flags, acontext->alloc_bytes_uoh);
+ newAlloc = (Object*) hp->allocate_uoh_object (size + ComputeMaxStructAlignPadLarge(requiredAlignment), flags, loh_generation, acontext->alloc_bytes_uoh);
#ifdef FEATURE_STRUCTALIGN
newAlloc = (Object*) hp->pad_for_alignment_large ((uint8_t*) newAlloc, requiredAlignment, size);
@@ -37261,7 +37370,7 @@ GCHeap::Alloc(gc_alloc_context* context, size_t size, uint32_t flags REQD_ALIGN_
}
else
{
- newAlloc = (Object*) hp->allocate_large_object (size + ComputeMaxStructAlignPadLarge(requiredAlignment), flags, acontext->alloc_bytes_uoh);
+ newAlloc = (Object*) hp->allocate_uoh_object (size + ComputeMaxStructAlignPadLarge(requiredAlignment), flags, loh_generation, acontext->alloc_bytes_uoh);
#ifdef FEATURE_STRUCTALIGN
newAlloc = (Object*) hp->pad_for_alignment_large ((uint8_t*) newAlloc, requiredAlignment, size);
#endif // FEATURE_STRUCTALIGN
diff --git a/src/coreclr/src/gc/gc.h b/src/coreclr/src/gc/gc.h
index 2ac171028da1aa..51bb27007e4f4e 100644
--- a/src/coreclr/src/gc/gc.h
+++ b/src/coreclr/src/gc/gc.h
@@ -89,7 +89,8 @@ enum gc_etw_segment_type
{
gc_etw_segment_small_object_heap = 0,
gc_etw_segment_large_object_heap = 1,
- gc_etw_segment_read_only_heap = 2
+ gc_etw_segment_read_only_heap = 2,
+ gc_etw_segment_pinned_object_heap = 3
};
// Types of allocations, emitted by the GCAllocationTick ETW event.
@@ -119,13 +120,16 @@ enum gc_generation_num
// large object heap, technically not a generation, but it is convenient to represent it as such
loh_generation = 3,
+ // pinned heap, a separate generation for the same reasons as loh
+ poh_generation = 4,
+
uoh_start_generation = loh_generation,
// number of ephemeral generations
ephemeral_generation_count = max_generation,
// number of all generations
- total_generation_count = loh_generation + 1
+ total_generation_count = poh_generation + 1
};
#ifdef GC_CONFIG_DRIVEN
diff --git a/src/coreclr/src/gc/gcpriv.h b/src/coreclr/src/gc/gcpriv.h
index 952eb83c695a83..4801a19f1d487f 100644
--- a/src/coreclr/src/gc/gcpriv.h
+++ b/src/coreclr/src/gc/gcpriv.h
@@ -106,6 +106,8 @@ inline void FATAL_GC_ERROR()
#define CARD_BUNDLE //enable card bundle feature.(requires WRITE_WATCH)
+#define ALLOW_REFERENCES_IN_POH //Allow POH objects to contain references.
+
// If this is defined we use a map for segments in order to find the heap for
// a segment fast. But it does use more memory as we have to cover the whole
// heap range and for each entry we allocate a struct of 5 ptr-size words
@@ -1227,7 +1229,8 @@ class gc_heap
static
HRESULT initialize_gc (size_t soh_segment_size,
- size_t loh_segment_size
+ size_t loh_segment_size,
+ size_t poh_segment_size
#ifdef MULTIPLE_HEAPS
, int number_of_heaps
#endif //MULTIPLE_HEAPS
@@ -1269,13 +1272,13 @@ class gc_heap
void gc_thread_stub (void* arg);
#endif //MULTIPLE_HEAPS
- // For LOH allocations we only update the alloc_bytes_uoh in allocation
+ // For UOH allocations we only update the alloc_bytes_uoh in allocation
// context - we don't actually use the ptr/limit from it so I am
// making this explicit by not passing in the alloc_context.
- // Note: This is an instance method, but the heap instance is only used for
+ // Note: This are instance methods, but the heap instance is only used for
// lowest_address and highest_address, which are currently the same accross all heaps.
PER_HEAP
- CObjectHeader* allocate_large_object (size_t size, uint32_t flags, int64_t& alloc_bytes);
+ CObjectHeader* allocate_uoh_object (size_t size, uint32_t flags, int gen_num, int64_t& alloc_bytes);
#ifdef FEATURE_STRUCTALIGN
PER_HEAP
@@ -1541,6 +1544,9 @@ class gc_heap
PER_HEAP
BOOL bgc_loh_allocate_spin();
+
+ PER_HEAP
+ BOOL bgc_poh_allocate_spin();
#endif //BACKGROUND_GC
#define max_saved_spinlock_info 48
@@ -3724,7 +3730,11 @@ class gc_heap
PER_HEAP
size_t bgc_begin_loh_size;
PER_HEAP
+ size_t bgc_begin_poh_size;
+ PER_HEAP
size_t end_loh_size;
+ PER_HEAP
+ size_t end_poh_size;
#ifdef BGC_SERVO_TUNING
PER_HEAP
@@ -3758,6 +3768,8 @@ class gc_heap
// in free list doesn't increase the heap size.
PER_HEAP
size_t bgc_loh_size_increased;
+ PER_HEAP
+ size_t bgc_poh_size_increased;
PER_HEAP
size_t background_soh_alloc_count;
@@ -3895,6 +3907,7 @@ class gc_heap
#define youngest_generation (generation_of (0))
#define large_object_generation (generation_of (loh_generation))
+#define pinned_object_generation (generation_of (poh_generation))
// The more_space_lock and gc_lock is used for 3 purposes:
//
@@ -3982,6 +3995,16 @@ class gc_heap
PER_HEAP
alloc_list gen2_alloc_list[NUM_GEN2_ALIST-1];
+// TODO: tuning https://github.com/dotnet/runtime/issues/13739
+#define NUM_POH_ALIST (12)
+#ifdef BIT64
+#define BASE_POH_ALIST (1*256)
+#else
+#define BASE_POH_ALIST (1*128)
+#endif // BIT64
+ PER_HEAP
+ alloc_list poh_alloc_list[NUM_POH_ALIST-1];
+
//------------------------------------------
PER_HEAP
@@ -4271,6 +4294,9 @@ class gc_heap
PER_HEAP
VOLATILE(uint32_t) card_mark_chunk_index_loh;
+ PER_HEAP
+ VOLATILE(uint32_t) card_mark_chunk_index_poh;
+
PER_HEAP
VOLATILE(bool) card_mark_done_uoh;
@@ -4282,6 +4308,7 @@ class gc_heap
card_mark_done_soh = false;
card_mark_chunk_index_loh = ~0;
+ card_mark_chunk_index_poh = ~0;
card_mark_done_uoh = false;
}
@@ -4772,6 +4799,7 @@ struct loh_padding_obj
#define heap_segment_flags_ma_pcommitted 128
#define heap_segment_flags_uoh_delete 256
+#define heap_segment_flags_poh 512
#endif //BACKGROUND_GC
//need to be careful to keep enough pad items to fit a relocation node
@@ -4860,7 +4888,7 @@ BOOL heap_segment_unmappable_p (heap_segment* inst)
inline
BOOL heap_segment_uoh_p (heap_segment * inst)
{
- return !!(inst->flags & heap_segment_flags_loh);
+ return !!(inst->flags & (heap_segment_flags_loh | heap_segment_flags_poh));
}
#ifdef BACKGROUND_GC
diff --git a/src/coreclr/src/gc/gcrecord.h b/src/coreclr/src/gc/gcrecord.h
index 8b50708e59192d..7e623052f12c9e 100644
--- a/src/coreclr/src/gc/gcrecord.h
+++ b/src/coreclr/src/gc/gcrecord.h
@@ -61,19 +61,19 @@ enum gc_condemn_reason_condition
gen_induced_noforce_p = 14,
gen_before_bgc = 15,
gen_almost_max_alloc = 16,
- gen_joined_avoid_unproductive = 17, /* This happens when the GC detects previous attempts to do a full compacting GC is not making progress and therefore reduce its generation */
- gen_joined_pm_induced_fullgc_p = 18, /* This happens when a full gc is induced under provisional mode */
- gen_joined_pm_alloc_loh = 19, /* This happens when a large object heap allocation is requested under provisional mode */
- gen_joined_last_gen2_fragmented = 20, /* This happens when we had a high memory and high fragmentation detected after the last full blocking GC, indicating we have lot of pinned objects in gen 2, so reducing its generation */
- gen_joined_limit_before_oom = 21, /* This happens when the last gc was oom */
- gen_joined_limit_loh_frag = 22, /* This happens when we had a heap limit and the fragmentation is reaching 1/8 of it */
- gen_joined_limit_loh_reclaim = 23, /* This happens when we had a heap limit and we could reclaim 1/8 of it */
- gen_joined_servo_initial = 24, /* This happen when the servo tuning is trying to get some initial data */
- gen_joined_servo_ngc = 25, /* This happen when the servo tuning decides a background gc is appropriate */
- gen_joined_servo_bgc = 26, /* This happen when the servo tuning decides a background gc is appropriate */
- gen_joined_servo_postpone = 27, /* This happen when the servo tuning decides a gen2 gc should be postponed */
- gen_joined_stress_mix = 28, /* This happen in GCStress mix mode, every 10th GC is gen2 */
- gen_joined_stress = 29, /* This happen in GCStress, every GC is gen2 */
+ gen_joined_avoid_unproductive = 17,
+ gen_joined_pm_induced_fullgc_p = 18,
+ gen_joined_pm_alloc_loh = 19,
+ gen_joined_gen1_in_pm = 20,
+ gen_joined_limit_before_oom = 21,
+ gen_joined_limit_loh_frag = 22,
+ gen_joined_limit_loh_reclaim = 23,
+ gen_joined_servo_initial = 24,
+ gen_joined_servo_ngc = 25,
+ gen_joined_servo_bgc = 26,
+ gen_joined_servo_postpone = 27,
+ gen_joined_stress_mix = 28,
+ gen_joined_stress = 29,
gcrc_max = 30
};
diff --git a/src/coreclr/src/gc/sample/GCSample.vcxproj b/src/coreclr/src/gc/sample/GCSample.vcxproj
index 74c48d85e18510..6e33738d18d0dd 100644
--- a/src/coreclr/src/gc/sample/GCSample.vcxproj
+++ b/src/coreclr/src/gc/sample/GCSample.vcxproj
@@ -1,4 +1,4 @@
-
+
diff --git a/src/coreclr/src/gc/sample/GCSample.vcxproj.filters b/src/coreclr/src/gc/sample/GCSample.vcxproj.filters
index b5647b3fcb4df2..9fac162f4ac83e 100644
--- a/src/coreclr/src/gc/sample/GCSample.vcxproj.filters
+++ b/src/coreclr/src/gc/sample/GCSample.vcxproj.filters
@@ -1,4 +1,4 @@
-
+
diff --git a/src/coreclr/src/gc/unix/gcenv.unix.cpp b/src/coreclr/src/gc/unix/gcenv.unix.cpp
index 9f6e2c31d485ad..f32308c90106c8 100644
--- a/src/coreclr/src/gc/unix/gcenv.unix.cpp
+++ b/src/coreclr/src/gc/unix/gcenv.unix.cpp
@@ -478,6 +478,7 @@ uint32_t GCToOSInterface::GetCurrentProcessorNumber()
assert(processorNumber != -1);
return processorNumber;
#else
+ assert(false); // This method is expected to be called only if CanGetCurrentProcessorNumber is true
return 0;
#endif
}
diff --git a/src/coreclr/src/hosts/CMakeLists.txt b/src/coreclr/src/hosts/CMakeLists.txt
index fed5a0f81c0a58..c3a6875feb6e86 100644
--- a/src/coreclr/src/hosts/CMakeLists.txt
+++ b/src/coreclr/src/hosts/CMakeLists.txt
@@ -1,14 +1,14 @@
include_directories(inc)
-if(CLR_CMAKE_TARGET_WIN32)
+if(CLR_CMAKE_HOST_WIN32)
add_subdirectory(corerun)
add_subdirectory(coreconsole)
add_subdirectory(coreshim)
-else(CLR_CMAKE_TARGET_WIN32)
+else(CLR_CMAKE_HOST_WIN32)
add_subdirectory(unixcoreruncommon)
add_subdirectory(unixcorerun)
add_subdirectory(unixcoreconsole)
if(CLR_CMAKE_HOST_DARWIN)
add_subdirectory(osxbundlerun)
endif(CLR_CMAKE_HOST_DARWIN)
-endif(CLR_CMAKE_TARGET_WIN32)
+endif(CLR_CMAKE_HOST_WIN32)
diff --git a/src/coreclr/src/hosts/corerun/corerun.cpp b/src/coreclr/src/hosts/corerun/corerun.cpp
index 6f175b567935a1..da62b217adee72 100644
--- a/src/coreclr/src/hosts/corerun/corerun.cpp
+++ b/src/coreclr/src/hosts/corerun/corerun.cpp
@@ -582,18 +582,6 @@ bool TryRun(const int argc, const wchar_t* argv[], Logger &log, const bool verbo
return false;
}
- StackSString tpaList;
- if (!managedAssemblyFullName.IsEmpty())
- {
- // Target assembly should be added to the tpa list. Otherwise corerun.exe
- // may find wrong assembly to execute.
- // Details can be found at https://github.com/dotnet/coreclr/issues/5631
- tpaList = managedAssemblyFullName;
- tpaList.Append(W(';'));
- }
-
- tpaList.Append(hostEnvironment.GetTpaList());
-
//-------------------------------------------------------------
// Create an AppDomain
@@ -623,7 +611,7 @@ bool TryRun(const int argc, const wchar_t* argv[], Logger &log, const bool verbo
};
const wchar_t *property_values[] = {
// TRUSTED_PLATFORM_ASSEMBLIES
- tpaList,
+ hostEnvironment.GetTpaList(),
// APP_PATHS
appPath,
// APP_NI_PATHS
diff --git a/src/coreclr/src/hosts/coreshim/CoreShim.cpp b/src/coreclr/src/hosts/coreshim/CoreShim.cpp
index 238e40fb87d2dd..44ff77e4cab638 100644
--- a/src/coreclr/src/hosts/coreshim/CoreShim.cpp
+++ b/src/coreclr/src/hosts/coreshim/CoreShim.cpp
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/hosts/unixcoreruncommon/coreruncommon.cpp b/src/coreclr/src/hosts/unixcoreruncommon/coreruncommon.cpp
index dd50a5dc4ac4dd..a2c00b1c3b4ab4 100644
--- a/src/coreclr/src/hosts/unixcoreruncommon/coreruncommon.cpp
+++ b/src/coreclr/src/hosts/unixcoreruncommon/coreruncommon.cpp
@@ -350,15 +350,6 @@ int ExecuteManagedAssembly(
GetDirectory(managedAssemblyAbsolutePath, appPath);
std::string tpaList;
- if (strlen(managedAssemblyAbsolutePath) > 0)
- {
- // Target assembly should be added to the tpa list. Otherwise corerun.exe
- // may find wrong assembly to execute.
- // Details can be found at https://github.com/dotnet/coreclr/issues/5631
- tpaList = managedAssemblyAbsolutePath;
- tpaList.append(":");
- }
-
// Construct native search directory paths
std::string nativeDllSearchDirs(appPath);
char *coreLibraries = getenv("CORE_LIBRARIES");
@@ -371,7 +362,6 @@ int ExecuteManagedAssembly(
AddFilesFromDirectoryToTpaList(coreLibraries, tpaList);
}
}
-
nativeDllSearchDirs.append(":");
nativeDllSearchDirs.append(clrFilesAbsolutePath);
diff --git a/src/coreclr/src/inc/clrconfigvalues.h b/src/coreclr/src/inc/clrconfigvalues.h
index 2e2474fa766322..1527ffe87008ad 100644
--- a/src/coreclr/src/inc/clrconfigvalues.h
+++ b/src/coreclr/src/inc/clrconfigvalues.h
@@ -717,7 +717,7 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeProcNumbers, W("EventPipeProcNumbers"
//
// Diagnostics Server
//
-RETAIL_CONFIG_STRING_INFO(EXTERNAL_DiagnosticsServerTransportPath, W("DiagnosticsServerTransportPath"), "The full path including filename for the OS transport (NamedPipe on Windows; Unix Domain Socket on Linux) to be used by the Diagnostics Server");
+RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_DOTNET_DiagnosticsServerAddress, W("DOTNET_DiagnosticsServerAddress"), "The full path including filename for the OS transport (NamedPipe on Windows; Unix Domain Socket on Linux) to be used by the Diagnostics Server", CLRConfig::DontPrependCOMPlus_);
//
// LTTng
diff --git a/src/coreclr/src/inc/clrnt.h b/src/coreclr/src/inc/clrnt.h
index de596918ca6ff6..078299ee9938f6 100644
--- a/src/coreclr/src/inc/clrnt.h
+++ b/src/coreclr/src/inc/clrnt.h
@@ -945,7 +945,7 @@ RtlUnwindEx (
__in_opt PEXCEPTION_RECORD ExceptionRecord,
__in PVOID ReturnValue,
__in PT_CONTEXT ContextRecord,
- __in_opt PUNWIND_HISTORY_TABLE HistoryTable
+ __in_opt PVOID HistoryTable
);
EXTERN_C
@@ -956,7 +956,7 @@ RtlVirtualUnwind (
__in DWORD HandlerType,
__in DWORD ImageBase,
__in DWORD ControlPc,
- __in PRUNTIME_FUNCTION FunctionEntry,
+ __in PT_RUNTIME_FUNCTION FunctionEntry,
__inout PT_CONTEXT ContextRecord,
__out PVOID *HandlerData,
__out PDWORD EstablisherFrame,
diff --git a/src/coreclr/src/inc/corinfo.h b/src/coreclr/src/inc/corinfo.h
index bf5d8b8ed1e622..ca7cdabf45d4fd 100644
--- a/src/coreclr/src/inc/corinfo.h
+++ b/src/coreclr/src/inc/corinfo.h
@@ -217,11 +217,11 @@ TODO: Talk about initializing strutures before use
#endif
#endif
-SELECTANY const GUID JITEEVersionIdentifier = { /* abcf830c-56d1-4b33-a8ec-5063bb5495f1 */
- 0xabcf830c,
- 0x56d1,
- 0x4b33,
- {0xa8, 0xec, 0x50, 0x63, 0xbb, 0x54, 0x95, 0xf1}
+SELECTANY const GUID JITEEVersionIdentifier = { /* 96fc0c0a-9f77-450d-9663-ee33ae0fcae8 */
+ 0x96fc0c0a,
+ 0x9f77,
+ 0x450d,
+ {0x96, 0x63, 0xee, 0x33, 0xae, 0x0f, 0xca, 0xe8}
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -2293,6 +2293,14 @@ class ICorStaticInfo
unsigned metaTOK /* IN */
) = 0;
+ // Returns string length and content (can be null for dynamic context)
+ // for given metaTOK and module, length `-1` means input is incorrect
+ virtual LPCWSTR getStringLiteral (
+ CORINFO_MODULE_HANDLE module, /* IN */
+ unsigned metaTOK, /* IN */
+ int* length /* OUT */
+ ) = 0;
+
virtual BOOL shouldEnforceCallvirtRestriction(
CORINFO_MODULE_HANDLE scope
) = 0;
diff --git a/src/coreclr/src/inc/corjit.h b/src/coreclr/src/inc/corjit.h
index 2e0a42c95d41a3..190d911f4d54fb 100644
--- a/src/coreclr/src/inc/corjit.h
+++ b/src/coreclr/src/inc/corjit.h
@@ -179,6 +179,8 @@ enum CorJitAllocMemFlag
CORJIT_ALLOCMEM_DEFAULT_CODE_ALIGN = 0x00000000, // The code will be use the normal alignment
CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN = 0x00000001, // The code will be 16-byte aligned
CORJIT_ALLOCMEM_FLG_RODATA_16BYTE_ALIGN = 0x00000002, // The read-only data will be 16-byte aligned
+ CORJIT_ALLOCMEM_FLG_32BYTE_ALIGN = 0x00000004, // The code will be 32-byte aligned
+ CORJIT_ALLOCMEM_FLG_RODATA_32BYTE_ALIGN = 0x00000008, // The read-only data will be 32-byte aligned
};
inline CorJitAllocMemFlag operator |(CorJitAllocMemFlag a, CorJitAllocMemFlag b)
diff --git a/src/coreclr/src/inc/crosscomp.h b/src/coreclr/src/inc/crosscomp.h
index 9d3a29e6cb3a4e..f05c3d32ca670b 100644
--- a/src/coreclr/src/inc/crosscomp.h
+++ b/src/coreclr/src/inc/crosscomp.h
@@ -18,7 +18,7 @@
#define MAKE_TARGET_DLLNAME_W(name) name W(".dll")
#define MAKE_TARGET_DLLNAME_A(name) name ".dll"
#else // TARGET_WINDOWS
-#ifdef TARGET_OSX
+#ifdef TARGET_DARWIN
#define MAKE_TARGET_DLLNAME_W(name) W("lib") name W(".dylib")
#define MAKE_TARGET_DLLNAME_A(name) "lib" name ".dylib"
#else
@@ -113,37 +113,15 @@ typedef struct DECLSPEC_ALIGN(8) _T_CONTEXT {
// each frame function.
//
-#ifndef TARGET_UNIX
-#ifdef HOST_X86
-typedef struct _RUNTIME_FUNCTION {
+#if defined(HOST_WINDOWS)
+typedef struct _T_RUNTIME_FUNCTION {
DWORD BeginAddress;
DWORD UnwindData;
-} RUNTIME_FUNCTION, *PRUNTIME_FUNCTION;
-
-//
-// Define unwind history table structure.
-//
-
-#define UNWIND_HISTORY_TABLE_SIZE 12
-
-typedef struct _UNWIND_HISTORY_TABLE_ENTRY {
- DWORD ImageBase;
- PRUNTIME_FUNCTION FunctionEntry;
-} UNWIND_HISTORY_TABLE_ENTRY, *PUNWIND_HISTORY_TABLE_ENTRY;
-
-typedef struct _UNWIND_HISTORY_TABLE {
- DWORD Count;
- BYTE LocalHint;
- BYTE GlobalHint;
- BYTE Search;
- BYTE Once;
- DWORD LowAddress;
- DWORD HighAddress;
- UNWIND_HISTORY_TABLE_ENTRY Entry[UNWIND_HISTORY_TABLE_SIZE];
-} UNWIND_HISTORY_TABLE, *PUNWIND_HISTORY_TABLE;
-#endif // HOST_X86
-#endif // !TARGET_UNIX
-
+} T_RUNTIME_FUNCTION, *PT_RUNTIME_FUNCTION;
+#else // HOST_WINDOWS
+#define T_RUNTIME_FUNCTION RUNTIME_FUNCTION
+#define PT_RUNTIME_FUNCTION PRUNTIME_FUNCTION
+#endif // HOST_WINDOWS
//
// Nonvolatile context pointer record.
@@ -177,7 +155,7 @@ typedef struct _T_KNONVOLATILE_CONTEXT_POINTERS {
//
typedef
-PRUNTIME_FUNCTION
+PT_RUNTIME_FUNCTION
(*PGET_RUNTIME_FUNCTION_CALLBACK) (
IN DWORD64 ControlPc,
IN PVOID Context
@@ -186,27 +164,18 @@ PRUNTIME_FUNCTION
typedef struct _T_DISPATCHER_CONTEXT {
ULONG ControlPc;
ULONG ImageBase;
- PRUNTIME_FUNCTION FunctionEntry;
+ PT_RUNTIME_FUNCTION FunctionEntry;
ULONG EstablisherFrame;
ULONG TargetPc;
PT_CONTEXT ContextRecord;
PEXCEPTION_ROUTINE LanguageHandler;
PVOID HandlerData;
- PUNWIND_HISTORY_TABLE HistoryTable;
+ PVOID HistoryTable;
ULONG ScopeIndex;
BOOLEAN ControlPcIsUnwound;
PUCHAR NonVolatileRegisters;
} T_DISPATCHER_CONTEXT, *PT_DISPATCHER_CONTEXT;
-#if defined(TARGET_UNIX) || defined(HOST_X86)
-#define T_RUNTIME_FUNCTION RUNTIME_FUNCTION
-#define PT_RUNTIME_FUNCTION PRUNTIME_FUNCTION
-#else
-typedef struct _T_RUNTIME_FUNCTION {
- DWORD BeginAddress;
- DWORD UnwindData;
-} T_RUNTIME_FUNCTION, *PT_RUNTIME_FUNCTION;
-#endif
#elif defined(HOST_AMD64) && defined(TARGET_ARM64) // Host amd64 managing ARM64 related code
@@ -339,7 +308,7 @@ typedef struct _T_DISPATCHER_CONTEXT {
PCONTEXT ContextRecord;
PEXCEPTION_ROUTINE LanguageHandler;
PVOID HandlerData;
- PUNWIND_HISTORY_TABLE HistoryTable;
+ PVOID HistoryTable;
DWORD ScopeIndex;
BOOLEAN ControlPcIsUnwound;
PBYTE NonVolatileRegisters;
@@ -393,6 +362,62 @@ typedef struct _T_KNONVOLATILE_CONTEXT_POINTERS {
#endif
+#if defined(DAC_COMPILE) && defined(TARGET_UNIX)
+// This is a TARGET oriented copy of CRITICAL_SECTION and PAL_CS_NATIVE_DATA_SIZE
+// It is configured based on TARGET configuration rather than HOST configuration
+// There is validation code in src/coreclr/src/vm/crst.cpp to keep these from
+// getting out of sync
+
+#define T_CRITICAL_SECTION_VALIDATION_MESSAGE "T_CRITICAL_SECTION validation failed. It is not in sync with CRITICAL_SECTION"
+
+#if defined(TARGET_DARWIN) && defined(TARGET_X86)
+#define DAC_CS_NATIVE_DATA_SIZE 76
+#elif defined(TARGET_DARWIN) && defined(TARGET_AMD64)
+#define DAC_CS_NATIVE_DATA_SIZE 120
+#elif defined(TARGET_FREEBSD) && defined(TARGET_X86)
+#define DAC_CS_NATIVE_DATA_SIZE 12
+#elif defined(TARGET_FREEBSD) && defined(TARGET_AMD64)
+#define DAC_CS_NATIVE_DATA_SIZE 24
+#elif defined(TARGET_LINUX) && defined(TARGET_ARM)
+#define DAC_CS_NATIVE_DATA_SIZE 80
+#elif defined(TARGET_LINUX) && defined(TARGET_ARM64)
+#define DAC_CS_NATIVE_DATA_SIZE 116
+#elif defined(TARGET_LINUX) && defined(TARGET_X86)
+#define DAC_CS_NATIVE_DATA_SIZE 76
+#elif defined(TARGET_LINUX) && defined(TARGET_AMD64)
+#define DAC_CS_NATIVE_DATA_SIZE 96
+#elif defined(TARGET_NETBSD) && defined(TARGET_AMD64)
+#define DAC_CS_NATIVE_DATA_SIZE 96
+#elif defined(TARGET_NETBSD) && defined(TARGET_ARM)
+#define DAC_CS_NATIVE_DATA_SIZE 56
+#elif defined(TARGET_NETBSD) && defined(TARGET_X86)
+#define DAC_CS_NATIVE_DATA_SIZE 56
+#else
+#warning
+#error DAC_CS_NATIVE_DATA_SIZE is not defined for this architecture
+#endif
+
+struct T_CRITICAL_SECTION {
+ PVOID DebugInfo;
+ LONG LockCount;
+ LONG RecursionCount;
+ HANDLE OwningThread;
+ ULONG_PTR SpinCount;
+
+#ifdef PAL_TRACK_CRITICAL_SECTIONS_DATA
+ BOOL bInternal;
+#endif // PAL_TRACK_CRITICAL_SECTIONS_DATA
+ volatile DWORD dwInitState;
+
+ union CSNativeDataStorage
+ {
+ BYTE rgNativeDataStorage[DAC_CS_NATIVE_DATA_SIZE];
+ PVOID pvAlign; // make sure the storage is machine-pointer-size aligned
+ } csnds;
+};
+#else
+#define T_CRITICAL_SECTION CRITICAL_SECTION
+#endif
#ifdef CROSSGEN_COMPILE
void CrossGenNotSupported(const char * message);
diff --git a/src/coreclr/src/inc/debugmacros.h b/src/coreclr/src/inc/debugmacros.h
index 14cba426f148a5..4fb4fb86711e70 100644
--- a/src/coreclr/src/inc/debugmacros.h
+++ b/src/coreclr/src/inc/debugmacros.h
@@ -201,7 +201,7 @@ do { hr = (EXPR); if(hr != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(hr); goto LA
#define _ASSERT _ASSERTE
-#if defined(_DEBUG) && !defined(TARGET_UNIX)
+#if defined(_DEBUG) && defined(HOST_WINDOWS)
// This function returns the EXE time stamp (effectively a random number)
// Under retail it always returns 0. This is meant to be used in the
diff --git a/src/coreclr/src/inc/ex.h b/src/coreclr/src/inc/ex.h
index 548fa2200dcc38..21ce9d3d4b0ec7 100644
--- a/src/coreclr/src/inc/ex.h
+++ b/src/coreclr/src/inc/ex.h
@@ -6,15 +6,15 @@
#if !defined(_EX_H_)
#define _EX_H_
-#ifdef TARGET_UNIX
+#ifdef HOST_UNIX
#define EX_TRY_HOLDER \
HardwareExceptionHolder \
NativeExceptionHolderCatchAll __exceptionHolder; \
__exceptionHolder.Push(); \
-#else // TARGET_UNIX
+#else // HOST_UNIX
#define EX_TRY_HOLDER
-#endif // TARGET_UNIX
+#endif // HOST_UNIX
#include "sstring.h"
#include "crtwrap.h"
@@ -112,7 +112,7 @@ void GenerateTopLevelHRExceptionMessage(HRESULT hresult, SString &result);
// We save current ExceptionPointers using VectoredExceptionHandler. The save data is only valid
// duing exception handling. GetCurrentExceptionPointers returns the saved data.
// ---------------------------------------------------------------------------
-void GetCurrentExceptionPointers(PEXCEPTION_POINTERS pExceptionInfo);
+void GetCurrentExceptionPointers(PEXCEPTION_POINTERS pExceptionInfo DEBUG_ARG(bool checkExceptionRecordLocation));
// ---------------------------------------------------------------------------
// We save current ExceptionPointers using VectoredExceptionHandler. The save data is only valid
diff --git a/src/coreclr/src/inc/holder.h b/src/coreclr/src/inc/holder.h
index 4ac41827172333..1d34f2b091f3e8 100644
--- a/src/coreclr/src/inc/holder.h
+++ b/src/coreclr/src/inc/holder.h
@@ -1175,10 +1175,10 @@ FORCEINLINE void CounterDecrease(RAW_KEYWORD(volatile) LONG* p) {InterlockedDecr
typedef Wrapper> CounterHolder;
-#ifndef TARGET_UNIX
+#ifdef HOST_WINDOWS
FORCEINLINE void RegKeyRelease(HKEY k) {RegCloseKey(k);};
typedef Wrapper RegKeyHolder;
-#endif // !TARGET_UNIX
+#endif // HOST_WINDOWS
class ErrorModeHolder
{
@@ -1189,7 +1189,7 @@ class ErrorModeHolder
UINT OldMode() {return m_oldMode;};
};
-#ifndef TARGET_UNIX
+#ifdef HOST_WINDOWS
//-----------------------------------------------------------------------------
// HKEYHolder : HKEY holder, Calls RegCloseKey on scope exit.
//
@@ -1244,7 +1244,7 @@ class HKEYHolder
private:
HKEY m_value;
};
-#endif // !TARGET_UNIX
+#endif // HOST_WINDOWS
//----------------------------------------------------------------------------
//
diff --git a/src/coreclr/src/inc/jithelpers.h b/src/coreclr/src/inc/jithelpers.h
index 73b5d2b54cf070..feeb880ac8a048 100644
--- a/src/coreclr/src/inc/jithelpers.h
+++ b/src/coreclr/src/inc/jithelpers.h
@@ -104,7 +104,7 @@
DYNAMICJITHELPER(CORINFO_HELP_BOX, JIT_Box, CORINFO_HELP_SIG_REG_ONLY)
JITHELPER(CORINFO_HELP_BOX_NULLABLE, JIT_Box, CORINFO_HELP_SIG_REG_ONLY)
- JITHELPER(CORINFO_HELP_UNBOX, JIT_Unbox, CORINFO_HELP_SIG_REG_ONLY)
+ DYNAMICJITHELPER(CORINFO_HELP_UNBOX, NULL, CORINFO_HELP_SIG_REG_ONLY)
JITHELPER(CORINFO_HELP_UNBOX_NULLABLE, JIT_Unbox_Nullable, CORINFO_HELP_SIG_4_STACK)
JITHELPER(CORINFO_HELP_GETREFANY, JIT_GetRefAny, CORINFO_HELP_SIG_8_STACK)
diff --git a/src/coreclr/src/inc/palclr.h b/src/coreclr/src/inc/palclr.h
index 1fcd9513d2b9f4..5978ea167642a9 100644
--- a/src/coreclr/src/inc/palclr.h
+++ b/src/coreclr/src/inc/palclr.h
@@ -10,7 +10,7 @@
// ===========================================================================
-#if !defined(HOST_UNIX)
+#if defined(HOST_WINDOWS)
#ifndef __PALCLR_H__
#define __PALCLR_H__
@@ -19,11 +19,7 @@
// Unix L"" is UTF32, and on windows it's UTF16. Because of built-in assumptions on the size
// of string literals, it's important to match behaviour between Unix and Windows. Unix will be defined
// as u"" (char16_t)
-#ifdef HOST_UNIX
-#define W(str) u##str
-#else // HOST_UNIX
#define W(str) L##str
-#endif // HOST_UNIX
#include
@@ -515,7 +511,7 @@
#endif
-#if defined(_DEBUG_IMPL) && !defined(JIT_BUILD) && !defined(JIT64_BUILD) && !defined(CROSS_COMPILE) && !defined(DISABLE_CONTRACTS)
+#if defined(_DEBUG_IMPL) && !defined(JIT_BUILD) && !defined(CROSS_COMPILE) && !defined(DISABLE_CONTRACTS)
#define PAL_TRY_HANDLER_DBG_BEGIN \
BOOL ___oldOkayToThrowValue = FALSE; \
ClrDebugState *___pState = ::GetClrDebugState(); \
@@ -560,7 +556,7 @@
#define PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(_reason) ANNOTATION_TRY_BEGIN;
#define PAL_TRY_HANDLER_DBG_END ANNOTATION_TRY_END;
#define PAL_ENDTRY_NAKED_DBG
-#endif // defined(ENABLE_CONTRACTS_IMPL) && !defined(JIT64_BUILD)
+#endif // defined(ENABLE_CONTRACTS_IMPL)
#if !BIGENDIAN
@@ -631,4 +627,4 @@
#include "palclr_win.h"
-#endif // !defined(HOST_UNIX)
+#endif // defined(HOST_WINDOWS)
diff --git a/src/coreclr/src/inc/palclr_win.h b/src/coreclr/src/inc/palclr_win.h
index 2d88e6fcc378f5..4db25f6eab42c5 100644
--- a/src/coreclr/src/inc/palclr_win.h
+++ b/src/coreclr/src/inc/palclr_win.h
@@ -85,7 +85,7 @@
-#if defined(_DEBUG_IMPL) && !defined(JIT_BUILD) && !defined(JIT64_BUILD) && !defined(HOST_ARM) // @ARMTODO
+#if defined(_DEBUG_IMPL) && !defined(JIT_BUILD) && !defined(HOST_ARM) // @ARMTODO
#define WIN_PAL_TRY_HANDLER_DBG_BEGIN \
BOOL ___oldOkayToThrowValue = FALSE; \
ClrDebugState *___pState = GetClrDebugState(); \
@@ -133,12 +133,12 @@
#define WIN_PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(_reason) ANNOTATION_TRY_BEGIN;
#define WIN_PAL_TRY_HANDLER_DBG_END ANNOTATION_TRY_END;
#define WIN_PAL_ENDTRY_NAKED_DBG
-#endif // defined(ENABLE_CONTRACTS_IMPL) && !defined(JIT64_BUILD)
+#endif // defined(ENABLE_CONTRACTS_IMPL)
-#if !defined (TARGET_UNIX)
+#if defined(HOST_WINDOWS)
// Native system libray handle.
// In Windows, NATIVE_LIBRARY_HANDLE is the same as HMODULE.
typedef HMODULE NATIVE_LIBRARY_HANDLE;
-#endif // !TARGET_UNIX
+#endif // HOST_WINDOWS
#endif // __PALCLR_WIN_H__
diff --git a/src/coreclr/src/inc/readytorun.h b/src/coreclr/src/inc/readytorun.h
index cd06ba68565994..7df03784ced816 100644
--- a/src/coreclr/src/inc/readytorun.h
+++ b/src/coreclr/src/inc/readytorun.h
@@ -18,8 +18,8 @@
#define READYTORUN_MAJOR_VERSION 0x0004
#define READYTORUN_MINOR_VERSION 0x0001
#define MINIMUM_READYTORUN_MAJOR_VERSION 0x003
-// R2R Version 2.1 adds the READYTORUN_SECTION_INLINING_INFO section
-// R2R Version 2.2 adds the READYTORUN_SECTION_PROFILEDATA_INFO section
+// R2R Version 2.1 adds the InliningInfo section
+// R2R Version 2.2 adds the ProfileDataInfo section
// R2R Version 3.0 changes calling conventions to correctly handle explicit structures to spec.
// R2R 3.0 is not backward compatible with 2.x.
@@ -37,12 +37,6 @@ struct READYTORUN_HEADER
// READYTORUN_SECTION Sections[];
};
-struct READYTORUN_SECTION
-{
- DWORD Type; // READYTORUN_SECTION_XXX
- IMAGE_DATA_DIRECTORY Section;
-};
-
enum ReadyToRunFlag
{
READYTORUN_FLAG_PLATFORM_NEUTRAL_SOURCE = 0x00000001, // Set if the original IL assembly was platform-neutral
@@ -51,29 +45,35 @@ enum ReadyToRunFlag
READYTORUN_FLAG_NONSHARED_PINVOKE_STUBS = 0x00000008 // PInvoke stubs compiled into image are non-shareable (no secret parameter)
};
-enum ReadyToRunSectionType
+enum class ReadyToRunSectionType : uint32_t
{
- READYTORUN_SECTION_COMPILER_IDENTIFIER = 100,
- READYTORUN_SECTION_IMPORT_SECTIONS = 101,
- READYTORUN_SECTION_RUNTIME_FUNCTIONS = 102,
- READYTORUN_SECTION_METHODDEF_ENTRYPOINTS = 103,
- READYTORUN_SECTION_EXCEPTION_INFO = 104,
- READYTORUN_SECTION_DEBUG_INFO = 105,
- READYTORUN_SECTION_DELAYLOAD_METHODCALL_THUNKS = 106,
- // 107 used by an older format of READYTORUN_SECTION_AVAILABLE_TYPES
- READYTORUN_SECTION_AVAILABLE_TYPES = 108,
- READYTORUN_SECTION_INSTANCE_METHOD_ENTRYPOINTS = 109,
- READYTORUN_SECTION_INLINING_INFO = 110, // Added in V2.1, deprecated in 4.1
- READYTORUN_SECTION_PROFILEDATA_INFO = 111, // Added in V2.2
- READYTORUN_SECTION_MANIFEST_METADATA = 112, // Added in V2.3
- READYTORUN_SECTION_ATTRIBUTEPRESENCE = 113, // Added in V3.1
- READYTORUN_SECTION_INLINING_INFO2 = 114, // Added in V4.1
-
- // If you add a new section consider whether it is a breaking or non-breaking change.
- // Usually it is non-breaking, but if it is preferable to have older runtimes fail
- // to load the image vs. ignoring the new section it could be marked breaking.
- // Increment the READYTORUN_MINOR_VERSION (non-breaking) or READYTORUN_MAJOR_VERSION
- // (breaking) as appropriate.
+ CompilerIdentifier = 100,
+ ImportSections = 101,
+ RuntimeFunctions = 102,
+ MethodDefEntryPoints = 103,
+ ExceptionInfo = 104,
+ DebugInfo = 105,
+ DelayLoadMethodCallThunks = 106,
+ // 107 used by an older format of AvailableTypes
+ AvailableTypes = 108,
+ InstanceMethodEntryPoints = 109,
+ InliningInfo = 110, // Added in V2.1, deprecated in 4.1
+ ProfileDataInfo = 111, // Added in V2.2
+ ManifestMetadata = 112, // Added in V2.3
+ AttributePresence = 113, // Added in V3.1
+ InliningInfo2 = 114, // Added in V4.1
+
+ // If you add a new section consider whether it is a breaking or non-breaking change.
+ // Usually it is non-breaking, but if it is preferable to have older runtimes fail
+ // to load the image vs. ignoring the new section it could be marked breaking.
+ // Increment the READYTORUN_MINOR_VERSION (non-breaking) or READYTORUN_MAJOR_VERSION
+ // (breaking) as appropriate.
+};
+
+struct READYTORUN_SECTION
+{
+ ReadyToRunSectionType Type; // READYTORUN_SECTION_XXX
+ IMAGE_DATA_DIRECTORY Section;
};
//
diff --git a/src/coreclr/src/inc/utilcode.h b/src/coreclr/src/inc/utilcode.h
index 4fb33d1d7746c0..73971b5b97ad1d 100644
--- a/src/coreclr/src/inc/utilcode.h
+++ b/src/coreclr/src/inc/utilcode.h
@@ -704,9 +704,9 @@ class CCompRC
m_nHashSize = 0;
m_csMap = NULL;
m_pResourceFile = NULL;
-#ifdef TARGET_UNIX
+#ifdef HOST_UNIX
m_pResourceDomain = NULL;
-#endif // TARGET_UNIX
+#endif // HOST_UNIX
}// CCompRC
@@ -794,12 +794,12 @@ class CCompRC
CRITSEC_COOKIE m_csMap;
LPCWSTR m_pResourceFile;
-#ifdef TARGET_UNIX
+#ifdef HOST_UNIX
// Resource domain is an ANSI string identifying a native resources file
static LPCSTR m_pDefaultResourceDomain;
static LPCSTR m_pFallbackResourceDomain;
LPCSTR m_pResourceDomain;
-#endif // TARGET_UNIX
+#endif // HOST_UNIX
// Main accessors for hash
HRESOURCEDLL LookupNode(LocaleID langId, BOOL &fMissing);
@@ -1280,16 +1280,16 @@ class NumaNodeInfo
static LPVOID VirtualAllocExNuma(HANDLE hProc, LPVOID lpAddr, SIZE_T size,
DWORD allocType, DWORD prot, DWORD node);
-#ifndef TARGET_UNIX
+#ifdef HOST_WINDOWS
static BOOL GetNumaProcessorNodeEx(PPROCESSOR_NUMBER proc_no, PUSHORT node_no);
static bool GetNumaInfo(PUSHORT total_nodes, DWORD* max_procs_per_node);
-#else // !TARGET_UNIX
+#else // HOST_WINDOWS
static BOOL GetNumaProcessorNodeEx(USHORT proc_no, PUSHORT node_no);
-#endif // !TARGET_UNIX
+#endif // HOST_WINDOWS
#endif
};
-#ifndef TARGET_UNIX
+#ifdef HOST_WINDOWS
struct CPU_Group_Info
{
@@ -1353,7 +1353,7 @@ class CPUGroupInfo
DWORD_PTR GetCurrentProcessCpuMask();
-#endif // !TARGET_UNIX
+#endif // HOST_WINDOWS
//******************************************************************************
// Returns the number of processors that a process has been configured to run on
@@ -4321,7 +4321,7 @@ class ClrTeb
return PAL_GetStackLimit();
}
-#else // !HOST_UNIX
+#else // HOST_UNIX
// returns pointer that uniquely identifies the fiber
static void* GetFiberPtrId()
@@ -4370,7 +4370,7 @@ class ClrTeb
{
return (void*) 1;
}
-#endif // !HOST_UNIX
+#endif // HOST_UNIX
};
#if !defined(DACCESS_COMPILE)
@@ -4809,7 +4809,7 @@ namespace util
* Overloaded operators for the executable heap
* ------------------------------------------------------------------------ */
-#ifndef TARGET_UNIX
+#ifdef HOST_WINDOWS
struct CExecutable { int x; };
extern const CExecutable executable;
@@ -4833,7 +4833,7 @@ template void DeleteExecutable(T *p)
}
}
-#endif // TARGET_UNIX
+#endif // HOST_WINDOWS
INDEBUG(BOOL DbgIsExecutable(LPVOID lpMem, SIZE_T length);)
diff --git a/src/coreclr/src/jit/ICorJitInfo_API_names.h b/src/coreclr/src/jit/ICorJitInfo_API_names.h
index 2e578342cc1e12..a17127ed6d29a8 100644
--- a/src/coreclr/src/jit/ICorJitInfo_API_names.h
+++ b/src/coreclr/src/jit/ICorJitInfo_API_names.h
@@ -38,6 +38,7 @@ DEF_CLR_API(getTokenTypeAsHandle)
DEF_CLR_API(canSkipVerification)
DEF_CLR_API(isValidToken)
DEF_CLR_API(isValidStringRef)
+DEF_CLR_API(getStringLiteral)
DEF_CLR_API(shouldEnforceCallvirtRestriction)
DEF_CLR_API(asCorInfoType)
DEF_CLR_API(getClassName)
diff --git a/src/coreclr/src/jit/ICorJitInfo_API_wrapper.hpp b/src/coreclr/src/jit/ICorJitInfo_API_wrapper.hpp
index 83ca2a2c7488f3..824f86b8dd9955 100644
--- a/src/coreclr/src/jit/ICorJitInfo_API_wrapper.hpp
+++ b/src/coreclr/src/jit/ICorJitInfo_API_wrapper.hpp
@@ -367,6 +367,17 @@ BOOL WrapICorJitInfo::isValidStringRef(
return temp;
}
+LPCWSTR WrapICorJitInfo::getStringLiteral(
+ CORINFO_MODULE_HANDLE module, /* IN */
+ unsigned metaTOK, /* IN */
+ int* length /* OUT */)
+{
+ API_ENTER(getStringLiteral);
+ LPCWSTR temp = wrapHnd->getStringLiteral(module, metaTOK, length);
+ API_LEAVE(getStringLiteral);
+ return temp;
+}
+
BOOL WrapICorJitInfo::shouldEnforceCallvirtRestriction(
CORINFO_MODULE_HANDLE scope)
{
diff --git a/src/coreclr/src/jit/codegen.h b/src/coreclr/src/jit/codegen.h
index ad74a0b79adea4..04fd7208f1f00d 100644
--- a/src/coreclr/src/jit/codegen.h
+++ b/src/coreclr/src/jit/codegen.h
@@ -833,6 +833,12 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
void genLongToIntCast(GenTree* treeNode);
#endif
+ // Generate code for a GT_BITCAST that is not contained.
+ void genCodeForBitCast(GenTreeOp* treeNode);
+
+ // Generate the instruction to move a value between register files
+ void genBitCast(var_types targetType, regNumber targetReg, var_types srcType, regNumber srcReg);
+
struct GenIntCastDesc
{
enum CheckKind
@@ -1364,6 +1370,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
instruction ins_Move_Extend(var_types srcType, bool srcInReg);
instruction ins_Copy(var_types dstType);
+ instruction ins_Copy(regNumber srcReg, var_types dstType);
instruction ins_CopyIntToFloat(var_types srcType, var_types dstTyp);
instruction ins_CopyFloatToInt(var_types srcType, var_types dstTyp);
static instruction ins_FloatStore(var_types type = TYP_DOUBLE);
diff --git a/src/coreclr/src/jit/codegenarm64.cpp b/src/coreclr/src/jit/codegenarm64.cpp
index 39b81bc1dc723d..9c7a4447d241b8 100644
--- a/src/coreclr/src/jit/codegenarm64.cpp
+++ b/src/coreclr/src/jit/codegenarm64.cpp
@@ -4518,11 +4518,11 @@ void CodeGen::genSIMDIntrinsicDotProduct(GenTreeSIMD* simdNode)
{
GetEmitter()->emitIns_R_R_R(INS_faddp, attr, tmpReg, tmpReg, tmpReg, INS_OPTS_4S);
}
- GetEmitter()->emitIns_R_R(INS_faddp, EA_4BYTE, targetReg, tmpReg);
+ GetEmitter()->emitIns_R_R(INS_faddp, EA_4BYTE, targetReg, tmpReg, INS_OPTS_2S);
}
else
{
- GetEmitter()->emitIns_R_R(INS_faddp, EA_8BYTE, targetReg, tmpReg);
+ GetEmitter()->emitIns_R_R(INS_faddp, EA_8BYTE, targetReg, tmpReg, INS_OPTS_2D);
}
}
else
@@ -6892,6 +6892,34 @@ void CodeGen::genArm64EmitterUnitTests()
theEmitter->emitIns_R_R(INS_fabs, EA_16BYTE, REG_V6, REG_V7, INS_OPTS_4S);
theEmitter->emitIns_R_R(INS_fabs, EA_16BYTE, REG_V8, REG_V9, INS_OPTS_2D);
+ // fmaxp scalar
+ theEmitter->emitIns_R_R(INS_fmaxp, EA_4BYTE, REG_V0, REG_V1, INS_OPTS_2S);
+ theEmitter->emitIns_R_R(INS_fmaxp, EA_8BYTE, REG_V2, REG_V3, INS_OPTS_2D);
+
+ // fmaxnmp scalar
+ theEmitter->emitIns_R_R(INS_fmaxnmp, EA_4BYTE, REG_V0, REG_V1, INS_OPTS_2S);
+ theEmitter->emitIns_R_R(INS_fmaxnmp, EA_8BYTE, REG_V2, REG_V3, INS_OPTS_2D);
+
+ // fmaxnmv vector
+ theEmitter->emitIns_R_R(INS_fmaxnmv, EA_4BYTE, REG_V0, REG_V1, INS_OPTS_4S);
+
+ // fmaxv vector
+ theEmitter->emitIns_R_R(INS_fmaxv, EA_4BYTE, REG_V0, REG_V1, INS_OPTS_4S);
+
+ // fminp vector
+ theEmitter->emitIns_R_R(INS_fminp, EA_4BYTE, REG_V0, REG_V1, INS_OPTS_2S);
+ theEmitter->emitIns_R_R(INS_fminp, EA_8BYTE, REG_V2, REG_V3, INS_OPTS_2D);
+
+ // fminnmp scalar
+ theEmitter->emitIns_R_R(INS_fminnmp, EA_4BYTE, REG_V0, REG_V1, INS_OPTS_2S);
+ theEmitter->emitIns_R_R(INS_fminnmp, EA_8BYTE, REG_V2, REG_V3, INS_OPTS_2D);
+
+ // fminnmv vector
+ theEmitter->emitIns_R_R(INS_fminnmv, EA_4BYTE, REG_V0, REG_V1, INS_OPTS_4S);
+
+ // fminv vector
+ theEmitter->emitIns_R_R(INS_fminv, EA_4BYTE, REG_V0, REG_V1, INS_OPTS_4S);
+
// fneg scalar
theEmitter->emitIns_R_R(INS_fneg, EA_4BYTE, REG_V0, REG_V1);
theEmitter->emitIns_R_R(INS_fneg, EA_8BYTE, REG_V2, REG_V3);
@@ -7006,21 +7034,19 @@ void CodeGen::genArm64EmitterUnitTests()
theEmitter->emitIns_R_R(INS_saddlv, EA_8BYTE, REG_V12, REG_V13, INS_OPTS_2S);
theEmitter->emitIns_R_R(INS_saddlv, EA_16BYTE, REG_V14, REG_V15, INS_OPTS_4S);
- // smaxlv vector
- theEmitter->emitIns_R_R(INS_smaxlv, EA_8BYTE, REG_V4, REG_V5, INS_OPTS_8B);
- theEmitter->emitIns_R_R(INS_smaxlv, EA_16BYTE, REG_V6, REG_V7, INS_OPTS_16B);
- theEmitter->emitIns_R_R(INS_smaxlv, EA_8BYTE, REG_V8, REG_V9, INS_OPTS_4H);
- theEmitter->emitIns_R_R(INS_smaxlv, EA_16BYTE, REG_V10, REG_V11, INS_OPTS_8H);
- theEmitter->emitIns_R_R(INS_smaxlv, EA_8BYTE, REG_V12, REG_V13, INS_OPTS_2S);
- theEmitter->emitIns_R_R(INS_smaxlv, EA_16BYTE, REG_V14, REG_V15, INS_OPTS_4S);
-
- // sminlv vector
- theEmitter->emitIns_R_R(INS_sminlv, EA_8BYTE, REG_V4, REG_V5, INS_OPTS_8B);
- theEmitter->emitIns_R_R(INS_sminlv, EA_16BYTE, REG_V6, REG_V7, INS_OPTS_16B);
- theEmitter->emitIns_R_R(INS_sminlv, EA_8BYTE, REG_V8, REG_V9, INS_OPTS_4H);
- theEmitter->emitIns_R_R(INS_sminlv, EA_16BYTE, REG_V10, REG_V11, INS_OPTS_8H);
- theEmitter->emitIns_R_R(INS_sminlv, EA_8BYTE, REG_V12, REG_V13, INS_OPTS_2S);
- theEmitter->emitIns_R_R(INS_sminlv, EA_16BYTE, REG_V14, REG_V15, INS_OPTS_4S);
+ // smaxv vector
+ theEmitter->emitIns_R_R(INS_smaxv, EA_8BYTE, REG_V4, REG_V5, INS_OPTS_8B);
+ theEmitter->emitIns_R_R(INS_smaxv, EA_16BYTE, REG_V6, REG_V7, INS_OPTS_16B);
+ theEmitter->emitIns_R_R(INS_smaxv, EA_8BYTE, REG_V8, REG_V9, INS_OPTS_4H);
+ theEmitter->emitIns_R_R(INS_smaxv, EA_16BYTE, REG_V10, REG_V11, INS_OPTS_8H);
+ theEmitter->emitIns_R_R(INS_smaxv, EA_16BYTE, REG_V12, REG_V13, INS_OPTS_4S);
+
+ // sminv vector
+ theEmitter->emitIns_R_R(INS_sminv, EA_8BYTE, REG_V4, REG_V5, INS_OPTS_8B);
+ theEmitter->emitIns_R_R(INS_sminv, EA_16BYTE, REG_V6, REG_V7, INS_OPTS_16B);
+ theEmitter->emitIns_R_R(INS_sminv, EA_8BYTE, REG_V8, REG_V9, INS_OPTS_4H);
+ theEmitter->emitIns_R_R(INS_sminv, EA_16BYTE, REG_V10, REG_V11, INS_OPTS_8H);
+ theEmitter->emitIns_R_R(INS_sminv, EA_16BYTE, REG_V12, REG_V13, INS_OPTS_4S);
// uaddlv vector
theEmitter->emitIns_R_R(INS_uaddlv, EA_8BYTE, REG_V4, REG_V5, INS_OPTS_8B);
@@ -7030,79 +7056,23 @@ void CodeGen::genArm64EmitterUnitTests()
theEmitter->emitIns_R_R(INS_uaddlv, EA_8BYTE, REG_V12, REG_V13, INS_OPTS_2S);
theEmitter->emitIns_R_R(INS_uaddlv, EA_16BYTE, REG_V14, REG_V15, INS_OPTS_4S);
- // umaxlv vector
- theEmitter->emitIns_R_R(INS_umaxlv, EA_8BYTE, REG_V4, REG_V5, INS_OPTS_8B);
- theEmitter->emitIns_R_R(INS_umaxlv, EA_16BYTE, REG_V6, REG_V7, INS_OPTS_16B);
- theEmitter->emitIns_R_R(INS_umaxlv, EA_8BYTE, REG_V8, REG_V9, INS_OPTS_4H);
- theEmitter->emitIns_R_R(INS_umaxlv, EA_16BYTE, REG_V10, REG_V11, INS_OPTS_8H);
- theEmitter->emitIns_R_R(INS_umaxlv, EA_8BYTE, REG_V12, REG_V13, INS_OPTS_2S);
- theEmitter->emitIns_R_R(INS_umaxlv, EA_16BYTE, REG_V14, REG_V15, INS_OPTS_4S);
-
- // uminlv vector
- theEmitter->emitIns_R_R(INS_uminlv, EA_8BYTE, REG_V4, REG_V5, INS_OPTS_8B);
- theEmitter->emitIns_R_R(INS_uminlv, EA_16BYTE, REG_V6, REG_V7, INS_OPTS_16B);
- theEmitter->emitIns_R_R(INS_uminlv, EA_8BYTE, REG_V8, REG_V9, INS_OPTS_4H);
- theEmitter->emitIns_R_R(INS_uminlv, EA_16BYTE, REG_V10, REG_V11, INS_OPTS_8H);
- theEmitter->emitIns_R_R(INS_uminlv, EA_8BYTE, REG_V12, REG_V13, INS_OPTS_2S);
- theEmitter->emitIns_R_R(INS_uminlv, EA_16BYTE, REG_V14, REG_V15, INS_OPTS_4S);
+ // umaxv vector
+ theEmitter->emitIns_R_R(INS_umaxv, EA_8BYTE, REG_V4, REG_V5, INS_OPTS_8B);
+ theEmitter->emitIns_R_R(INS_umaxv, EA_16BYTE, REG_V6, REG_V7, INS_OPTS_16B);
+ theEmitter->emitIns_R_R(INS_umaxv, EA_8BYTE, REG_V8, REG_V9, INS_OPTS_4H);
+ theEmitter->emitIns_R_R(INS_umaxv, EA_16BYTE, REG_V10, REG_V11, INS_OPTS_8H);
+ theEmitter->emitIns_R_R(INS_umaxv, EA_16BYTE, REG_V12, REG_V13, INS_OPTS_4S);
- // uzp1 vector
- theEmitter->emitIns_R_R(INS_uzp1, EA_8BYTE, REG_V4, REG_V5, INS_OPTS_8B);
- theEmitter->emitIns_R_R(INS_uzp1, EA_16BYTE, REG_V6, REG_V7, INS_OPTS_16B);
- theEmitter->emitIns_R_R(INS_uzp1, EA_8BYTE, REG_V8, REG_V9, INS_OPTS_4H);
- theEmitter->emitIns_R_R(INS_uzp1, EA_16BYTE, REG_V10, REG_V11, INS_OPTS_8H);
- theEmitter->emitIns_R_R(INS_uzp1, EA_8BYTE, REG_V12, REG_V13, INS_OPTS_2S);
- theEmitter->emitIns_R_R(INS_uzp1, EA_16BYTE, REG_V14, REG_V15, INS_OPTS_4S);
- theEmitter->emitIns_R_R(INS_uzp1, EA_16BYTE, REG_V14, REG_V15, INS_OPTS_2D);
-
- // uzp2 vector
- theEmitter->emitIns_R_R(INS_uzp2, EA_8BYTE, REG_V4, REG_V5, INS_OPTS_8B);
- theEmitter->emitIns_R_R(INS_uzp2, EA_16BYTE, REG_V6, REG_V7, INS_OPTS_16B);
- theEmitter->emitIns_R_R(INS_uzp2, EA_8BYTE, REG_V8, REG_V9, INS_OPTS_4H);
- theEmitter->emitIns_R_R(INS_uzp2, EA_16BYTE, REG_V10, REG_V11, INS_OPTS_8H);
- theEmitter->emitIns_R_R(INS_uzp2, EA_8BYTE, REG_V12, REG_V13, INS_OPTS_2S);
- theEmitter->emitIns_R_R(INS_uzp2, EA_16BYTE, REG_V14, REG_V15, INS_OPTS_4S);
- theEmitter->emitIns_R_R(INS_uzp2, EA_16BYTE, REG_V14, REG_V15, INS_OPTS_2D);
-
- // zip1 vector
- theEmitter->emitIns_R_R(INS_zip1, EA_8BYTE, REG_V4, REG_V5, INS_OPTS_8B);
- theEmitter->emitIns_R_R(INS_zip1, EA_16BYTE, REG_V6, REG_V7, INS_OPTS_16B);
- theEmitter->emitIns_R_R(INS_zip1, EA_8BYTE, REG_V8, REG_V9, INS_OPTS_4H);
- theEmitter->emitIns_R_R(INS_zip1, EA_16BYTE, REG_V10, REG_V11, INS_OPTS_8H);
- theEmitter->emitIns_R_R(INS_zip1, EA_8BYTE, REG_V12, REG_V13, INS_OPTS_2S);
- theEmitter->emitIns_R_R(INS_zip1, EA_16BYTE, REG_V14, REG_V15, INS_OPTS_4S);
- theEmitter->emitIns_R_R(INS_zip1, EA_16BYTE, REG_V14, REG_V15, INS_OPTS_2D);
-
- // zip2 vector
- theEmitter->emitIns_R_R(INS_zip2, EA_8BYTE, REG_V4, REG_V5, INS_OPTS_8B);
- theEmitter->emitIns_R_R(INS_zip2, EA_16BYTE, REG_V6, REG_V7, INS_OPTS_16B);
- theEmitter->emitIns_R_R(INS_zip2, EA_8BYTE, REG_V8, REG_V9, INS_OPTS_4H);
- theEmitter->emitIns_R_R(INS_zip2, EA_16BYTE, REG_V10, REG_V11, INS_OPTS_8H);
- theEmitter->emitIns_R_R(INS_zip2, EA_8BYTE, REG_V12, REG_V13, INS_OPTS_2S);
- theEmitter->emitIns_R_R(INS_zip2, EA_16BYTE, REG_V14, REG_V15, INS_OPTS_4S);
- theEmitter->emitIns_R_R(INS_zip2, EA_16BYTE, REG_V14, REG_V15, INS_OPTS_2D);
-
- // trn1 vector
- theEmitter->emitIns_R_R(INS_trn1, EA_8BYTE, REG_V4, REG_V5, INS_OPTS_8B);
- theEmitter->emitIns_R_R(INS_trn1, EA_16BYTE, REG_V6, REG_V7, INS_OPTS_16B);
- theEmitter->emitIns_R_R(INS_trn1, EA_8BYTE, REG_V8, REG_V9, INS_OPTS_4H);
- theEmitter->emitIns_R_R(INS_trn1, EA_16BYTE, REG_V10, REG_V11, INS_OPTS_8H);
- theEmitter->emitIns_R_R(INS_trn1, EA_8BYTE, REG_V12, REG_V13, INS_OPTS_2S);
- theEmitter->emitIns_R_R(INS_trn1, EA_16BYTE, REG_V14, REG_V15, INS_OPTS_4S);
- theEmitter->emitIns_R_R(INS_trn1, EA_16BYTE, REG_V14, REG_V15, INS_OPTS_2D);
-
- // trn2 vector
- theEmitter->emitIns_R_R(INS_trn2, EA_8BYTE, REG_V4, REG_V5, INS_OPTS_8B);
- theEmitter->emitIns_R_R(INS_trn2, EA_16BYTE, REG_V6, REG_V7, INS_OPTS_16B);
- theEmitter->emitIns_R_R(INS_trn2, EA_8BYTE, REG_V8, REG_V9, INS_OPTS_4H);
- theEmitter->emitIns_R_R(INS_trn2, EA_16BYTE, REG_V10, REG_V11, INS_OPTS_8H);
- theEmitter->emitIns_R_R(INS_trn2, EA_8BYTE, REG_V12, REG_V13, INS_OPTS_2S);
- theEmitter->emitIns_R_R(INS_trn2, EA_16BYTE, REG_V14, REG_V15, INS_OPTS_4S);
- theEmitter->emitIns_R_R(INS_trn2, EA_16BYTE, REG_V14, REG_V15, INS_OPTS_2D);
+ // uminv vector
+ theEmitter->emitIns_R_R(INS_uminv, EA_8BYTE, REG_V4, REG_V5, INS_OPTS_8B);
+ theEmitter->emitIns_R_R(INS_uminv, EA_16BYTE, REG_V6, REG_V7, INS_OPTS_16B);
+ theEmitter->emitIns_R_R(INS_uminv, EA_8BYTE, REG_V8, REG_V9, INS_OPTS_4H);
+ theEmitter->emitIns_R_R(INS_uminv, EA_16BYTE, REG_V10, REG_V11, INS_OPTS_8H);
+ theEmitter->emitIns_R_R(INS_uminv, EA_16BYTE, REG_V12, REG_V13, INS_OPTS_4S);
// faddp scalar
- theEmitter->emitIns_R_R(INS_faddp, EA_4BYTE, REG_V0, REG_V1);
- theEmitter->emitIns_R_R(INS_faddp, EA_8BYTE, REG_V2, REG_V3);
+ theEmitter->emitIns_R_R(INS_faddp, EA_4BYTE, REG_V0, REG_V1, INS_OPTS_2S);
+ theEmitter->emitIns_R_R(INS_faddp, EA_8BYTE, REG_V2, REG_V3, INS_OPTS_2D);
// INS_fcvtl
theEmitter->emitIns_R_R(INS_fcvtl, EA_4BYTE, REG_V0, REG_V1);
@@ -7194,36 +7164,75 @@ void CodeGen::genArm64EmitterUnitTests()
genDefineTempLabel(genCreateTempLabel());
+ // fadd
theEmitter->emitIns_R_R_R(INS_fadd, EA_4BYTE, REG_V0, REG_V1, REG_V2); // scalar 4BYTE
theEmitter->emitIns_R_R_R(INS_fadd, EA_8BYTE, REG_V3, REG_V4, REG_V5); // scalar 8BYTE
theEmitter->emitIns_R_R_R(INS_fadd, EA_8BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_2S);
theEmitter->emitIns_R_R_R(INS_fadd, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_4S);
theEmitter->emitIns_R_R_R(INS_fadd, EA_16BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2D);
+ // fsub
theEmitter->emitIns_R_R_R(INS_fsub, EA_4BYTE, REG_V0, REG_V1, REG_V2); // scalar 4BYTE
theEmitter->emitIns_R_R_R(INS_fsub, EA_8BYTE, REG_V3, REG_V4, REG_V5); // scalar 8BYTE
theEmitter->emitIns_R_R_R(INS_fsub, EA_8BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_2S);
theEmitter->emitIns_R_R_R(INS_fsub, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_4S);
theEmitter->emitIns_R_R_R(INS_fsub, EA_16BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2D);
+ // fdiv
theEmitter->emitIns_R_R_R(INS_fdiv, EA_4BYTE, REG_V0, REG_V1, REG_V2); // scalar 4BYTE
theEmitter->emitIns_R_R_R(INS_fdiv, EA_8BYTE, REG_V3, REG_V4, REG_V5); // scalar 8BYTE
theEmitter->emitIns_R_R_R(INS_fdiv, EA_8BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_2S);
theEmitter->emitIns_R_R_R(INS_fdiv, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_4S);
theEmitter->emitIns_R_R_R(INS_fdiv, EA_16BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2D);
+ // fmax
theEmitter->emitIns_R_R_R(INS_fmax, EA_4BYTE, REG_V0, REG_V1, REG_V2); // scalar 4BYTE
theEmitter->emitIns_R_R_R(INS_fmax, EA_8BYTE, REG_V3, REG_V4, REG_V5); // scalar 8BYTE
theEmitter->emitIns_R_R_R(INS_fmax, EA_8BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_2S);
theEmitter->emitIns_R_R_R(INS_fmax, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_4S);
theEmitter->emitIns_R_R_R(INS_fmax, EA_16BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2D);
+ // fmaxp
+ theEmitter->emitIns_R_R_R(INS_fmaxp, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_2S);
+ theEmitter->emitIns_R_R_R(INS_fmaxp, EA_16BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_4S);
+ theEmitter->emitIns_R_R_R(INS_fmaxp, EA_16BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_2D);
+
+ // fmaxnm
+ theEmitter->emitIns_R_R_R(INS_fmaxnm, EA_4BYTE, REG_V0, REG_V1, REG_V2); // scalar 4BYTE
+ theEmitter->emitIns_R_R_R(INS_fmaxnm, EA_8BYTE, REG_V3, REG_V4, REG_V5); // scalar 8BYTE
+ theEmitter->emitIns_R_R_R(INS_fmaxnm, EA_8BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_2S);
+ theEmitter->emitIns_R_R_R(INS_fmaxnm, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_4S);
+ theEmitter->emitIns_R_R_R(INS_fmaxnm, EA_16BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2D);
+
+ // fmaxnmp vector
+ theEmitter->emitIns_R_R_R(INS_fmaxnmp, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_2S);
+ theEmitter->emitIns_R_R_R(INS_fmaxnmp, EA_16BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_4S);
+ theEmitter->emitIns_R_R_R(INS_fmaxnmp, EA_16BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_2D);
+
+ // fmin
theEmitter->emitIns_R_R_R(INS_fmin, EA_4BYTE, REG_V0, REG_V1, REG_V2); // scalar 4BYTE
theEmitter->emitIns_R_R_R(INS_fmin, EA_8BYTE, REG_V3, REG_V4, REG_V5); // scalar 8BYTE
theEmitter->emitIns_R_R_R(INS_fmin, EA_8BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_2S);
theEmitter->emitIns_R_R_R(INS_fmin, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_4S);
theEmitter->emitIns_R_R_R(INS_fmin, EA_16BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2D);
+ // fminp
+ theEmitter->emitIns_R_R_R(INS_fminp, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_2S);
+ theEmitter->emitIns_R_R_R(INS_fminp, EA_16BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_4S);
+ theEmitter->emitIns_R_R_R(INS_fminp, EA_16BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_2D);
+
+ // fminnm
+ theEmitter->emitIns_R_R_R(INS_fminnm, EA_4BYTE, REG_V0, REG_V1, REG_V2); // scalar 4BYTE
+ theEmitter->emitIns_R_R_R(INS_fminnm, EA_8BYTE, REG_V3, REG_V4, REG_V5); // scalar 8BYTE
+ theEmitter->emitIns_R_R_R(INS_fminnm, EA_8BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_2S);
+ theEmitter->emitIns_R_R_R(INS_fminnm, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_4S);
+ theEmitter->emitIns_R_R_R(INS_fminnm, EA_16BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2D);
+
+ // fminnmp vector
+ theEmitter->emitIns_R_R_R(INS_fminnmp, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_2S);
+ theEmitter->emitIns_R_R_R(INS_fminnmp, EA_16BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_4S);
+ theEmitter->emitIns_R_R_R(INS_fminnmp, EA_16BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_2D);
+
// fabd
theEmitter->emitIns_R_R_R(INS_fabd, EA_4BYTE, REG_V0, REG_V1, REG_V2); // scalar 4BYTE
theEmitter->emitIns_R_R_R(INS_fabd, EA_8BYTE, REG_V3, REG_V4, REG_V5); // scalar 8BYTE
@@ -7555,6 +7564,7 @@ void CodeGen::genArm64EmitterUnitTests()
genDefineTempLabel(genCreateTempLabel());
+ // add
theEmitter->emitIns_R_R_R(INS_add, EA_8BYTE, REG_V0, REG_V1, REG_V2); // scalar 8BYTE
theEmitter->emitIns_R_R_R(INS_add, EA_8BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_8B);
theEmitter->emitIns_R_R_R(INS_add, EA_8BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_4H);
@@ -7564,6 +7574,17 @@ void CodeGen::genArm64EmitterUnitTests()
theEmitter->emitIns_R_R_R(INS_add, EA_16BYTE, REG_V18, REG_V19, REG_V20, INS_OPTS_4S);
theEmitter->emitIns_R_R_R(INS_add, EA_16BYTE, REG_V21, REG_V22, REG_V23, INS_OPTS_2D);
+ // addp
+ theEmitter->emitIns_R_R(INS_addp, EA_8BYTE, REG_V0, REG_V1, INS_OPTS_2D); // scalar 8BYTE
+ theEmitter->emitIns_R_R_R(INS_addp, EA_8BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_8B);
+ theEmitter->emitIns_R_R_R(INS_addp, EA_8BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_4H);
+ theEmitter->emitIns_R_R_R(INS_addp, EA_8BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_2S);
+ theEmitter->emitIns_R_R_R(INS_addp, EA_16BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_16B);
+ theEmitter->emitIns_R_R_R(INS_addp, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_8H);
+ theEmitter->emitIns_R_R_R(INS_addp, EA_16BYTE, REG_V18, REG_V19, REG_V20, INS_OPTS_4S);
+ theEmitter->emitIns_R_R_R(INS_addp, EA_16BYTE, REG_V21, REG_V22, REG_V23, INS_OPTS_2D);
+
+ // sub
theEmitter->emitIns_R_R_R(INS_sub, EA_8BYTE, REG_V1, REG_V2, REG_V3); // scalar 8BYTE
theEmitter->emitIns_R_R_R(INS_sub, EA_8BYTE, REG_V4, REG_V5, REG_V6, INS_OPTS_8B);
theEmitter->emitIns_R_R_R(INS_sub, EA_8BYTE, REG_V7, REG_V8, REG_V9, INS_OPTS_4H);
@@ -7617,6 +7638,14 @@ void CodeGen::genArm64EmitterUnitTests()
theEmitter->emitIns_R_R_R(INS_smax, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2S);
theEmitter->emitIns_R_R_R(INS_smax, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_4S);
+ // smaxp vector
+ theEmitter->emitIns_R_R_R(INS_smaxp, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_8B);
+ theEmitter->emitIns_R_R_R(INS_smaxp, EA_16BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_16B);
+ theEmitter->emitIns_R_R_R(INS_smaxp, EA_8BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_4H);
+ theEmitter->emitIns_R_R_R(INS_smaxp, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_8H);
+ theEmitter->emitIns_R_R_R(INS_smaxp, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2S);
+ theEmitter->emitIns_R_R_R(INS_smaxp, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_4S);
+
// smin vector
theEmitter->emitIns_R_R_R(INS_smin, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_8B);
theEmitter->emitIns_R_R_R(INS_smin, EA_16BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_16B);
@@ -7625,6 +7654,14 @@ void CodeGen::genArm64EmitterUnitTests()
theEmitter->emitIns_R_R_R(INS_smin, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2S);
theEmitter->emitIns_R_R_R(INS_smin, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_4S);
+ // sminp vector
+ theEmitter->emitIns_R_R_R(INS_sminp, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_8B);
+ theEmitter->emitIns_R_R_R(INS_sminp, EA_16BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_16B);
+ theEmitter->emitIns_R_R_R(INS_sminp, EA_8BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_4H);
+ theEmitter->emitIns_R_R_R(INS_sminp, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_8H);
+ theEmitter->emitIns_R_R_R(INS_sminp, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2S);
+ theEmitter->emitIns_R_R_R(INS_sminp, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_4S);
+
// umax vector
theEmitter->emitIns_R_R_R(INS_umax, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_8B);
theEmitter->emitIns_R_R_R(INS_umax, EA_16BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_16B);
@@ -7633,6 +7670,14 @@ void CodeGen::genArm64EmitterUnitTests()
theEmitter->emitIns_R_R_R(INS_umax, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2S);
theEmitter->emitIns_R_R_R(INS_umax, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_4S);
+ // umaxp vector
+ theEmitter->emitIns_R_R_R(INS_umaxp, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_8B);
+ theEmitter->emitIns_R_R_R(INS_umaxp, EA_16BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_16B);
+ theEmitter->emitIns_R_R_R(INS_umaxp, EA_8BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_4H);
+ theEmitter->emitIns_R_R_R(INS_umaxp, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_8H);
+ theEmitter->emitIns_R_R_R(INS_umaxp, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2S);
+ theEmitter->emitIns_R_R_R(INS_umaxp, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_4S);
+
// umin vector
theEmitter->emitIns_R_R_R(INS_umin, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_8B);
theEmitter->emitIns_R_R_R(INS_umin, EA_16BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_16B);
@@ -7641,6 +7686,14 @@ void CodeGen::genArm64EmitterUnitTests()
theEmitter->emitIns_R_R_R(INS_umin, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2S);
theEmitter->emitIns_R_R_R(INS_umin, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_4S);
+ // uminp vector
+ theEmitter->emitIns_R_R_R(INS_uminp, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_8B);
+ theEmitter->emitIns_R_R_R(INS_uminp, EA_16BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_16B);
+ theEmitter->emitIns_R_R_R(INS_uminp, EA_8BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_4H);
+ theEmitter->emitIns_R_R_R(INS_uminp, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_8H);
+ theEmitter->emitIns_R_R_R(INS_uminp, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2S);
+ theEmitter->emitIns_R_R_R(INS_uminp, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_4S);
+
// cmeq vector
theEmitter->emitIns_R_R_R(INS_cmeq, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_8B);
theEmitter->emitIns_R_R_R(INS_cmeq, EA_16BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_16B);
@@ -7648,8 +7701,7 @@ void CodeGen::genArm64EmitterUnitTests()
theEmitter->emitIns_R_R_R(INS_cmeq, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_8H);
theEmitter->emitIns_R_R_R(INS_cmeq, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2S);
theEmitter->emitIns_R_R_R(INS_cmeq, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_4S);
- theEmitter->emitIns_R_R_R(INS_cmeq, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_1D);
- theEmitter->emitIns_R_R_R(INS_cmeq, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_2D);
+ theEmitter->emitIns_R_R_R(INS_cmeq, EA_16BYTE, REG_V18, REG_V19, REG_V20, INS_OPTS_2D);
// cmge vector
theEmitter->emitIns_R_R_R(INS_cmge, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_8B);
@@ -7658,8 +7710,7 @@ void CodeGen::genArm64EmitterUnitTests()
theEmitter->emitIns_R_R_R(INS_cmge, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_8H);
theEmitter->emitIns_R_R_R(INS_cmge, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2S);
theEmitter->emitIns_R_R_R(INS_cmge, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_4S);
- theEmitter->emitIns_R_R_R(INS_cmge, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_1D);
- theEmitter->emitIns_R_R_R(INS_cmge, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_2D);
+ theEmitter->emitIns_R_R_R(INS_cmge, EA_16BYTE, REG_V18, REG_V19, REG_V20, INS_OPTS_2D);
// cmgt vector
theEmitter->emitIns_R_R_R(INS_cmgt, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_8B);
@@ -7668,8 +7719,7 @@ void CodeGen::genArm64EmitterUnitTests()
theEmitter->emitIns_R_R_R(INS_cmgt, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_8H);
theEmitter->emitIns_R_R_R(INS_cmgt, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2S);
theEmitter->emitIns_R_R_R(INS_cmgt, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_4S);
- theEmitter->emitIns_R_R_R(INS_cmgt, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_1D);
- theEmitter->emitIns_R_R_R(INS_cmgt, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_2D);
+ theEmitter->emitIns_R_R_R(INS_cmgt, EA_16BYTE, REG_V18, REG_V19, REG_V20, INS_OPTS_2D);
// cmhi vector
theEmitter->emitIns_R_R_R(INS_cmhi, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_8B);
@@ -7678,8 +7728,7 @@ void CodeGen::genArm64EmitterUnitTests()
theEmitter->emitIns_R_R_R(INS_cmhi, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_8H);
theEmitter->emitIns_R_R_R(INS_cmhi, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2S);
theEmitter->emitIns_R_R_R(INS_cmhi, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_4S);
- theEmitter->emitIns_R_R_R(INS_cmhi, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_1D);
- theEmitter->emitIns_R_R_R(INS_cmhi, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_2D);
+ theEmitter->emitIns_R_R_R(INS_cmhi, EA_16BYTE, REG_V18, REG_V19, REG_V20, INS_OPTS_2D);
// cmhs vector
theEmitter->emitIns_R_R_R(INS_cmhs, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_8B);
@@ -7688,18 +7737,16 @@ void CodeGen::genArm64EmitterUnitTests()
theEmitter->emitIns_R_R_R(INS_cmhs, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_8H);
theEmitter->emitIns_R_R_R(INS_cmhs, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2S);
theEmitter->emitIns_R_R_R(INS_cmhs, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_4S);
- theEmitter->emitIns_R_R_R(INS_cmhs, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_1D);
- theEmitter->emitIns_R_R_R(INS_cmhs, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_2D);
-
- // ctst vector
- theEmitter->emitIns_R_R_R(INS_ctst, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_8B);
- theEmitter->emitIns_R_R_R(INS_ctst, EA_16BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_16B);
- theEmitter->emitIns_R_R_R(INS_ctst, EA_8BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_4H);
- theEmitter->emitIns_R_R_R(INS_ctst, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_8H);
- theEmitter->emitIns_R_R_R(INS_ctst, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2S);
- theEmitter->emitIns_R_R_R(INS_ctst, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_4S);
- theEmitter->emitIns_R_R_R(INS_ctst, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_1D);
- theEmitter->emitIns_R_R_R(INS_ctst, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_2D);
+ theEmitter->emitIns_R_R_R(INS_cmhs, EA_16BYTE, REG_V18, REG_V19, REG_V20, INS_OPTS_2D);
+
+ // cmtst vector
+ theEmitter->emitIns_R_R_R(INS_cmtst, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_8B);
+ theEmitter->emitIns_R_R_R(INS_cmtst, EA_16BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_16B);
+ theEmitter->emitIns_R_R_R(INS_cmtst, EA_8BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_4H);
+ theEmitter->emitIns_R_R_R(INS_cmtst, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_8H);
+ theEmitter->emitIns_R_R_R(INS_cmtst, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2S);
+ theEmitter->emitIns_R_R_R(INS_cmtst, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_4S);
+ theEmitter->emitIns_R_R_R(INS_cmtst, EA_16BYTE, REG_V18, REG_V19, REG_V20, INS_OPTS_2D);
// faddp vector
theEmitter->emitIns_R_R_R(INS_faddp, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2S);
@@ -7722,6 +7769,62 @@ void CodeGen::genArm64EmitterUnitTests()
theEmitter->emitIns_R_R_R(INS_fcmgt, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_2D);
#endif // ALL_ARM64_EMITTER_UNIT_TESTS
+#ifdef ALL_ARM64_EMITTER_UNIT_TESTS
+ // trn1 vector
+ theEmitter->emitIns_R_R_R(INS_trn1, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_8B);
+ theEmitter->emitIns_R_R_R(INS_trn1, EA_16BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_16B);
+ theEmitter->emitIns_R_R_R(INS_trn1, EA_8BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_4H);
+ theEmitter->emitIns_R_R_R(INS_trn1, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_8H);
+ theEmitter->emitIns_R_R_R(INS_trn1, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2S);
+ theEmitter->emitIns_R_R_R(INS_trn1, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_4S);
+ theEmitter->emitIns_R_R_R(INS_trn1, EA_16BYTE, REG_V18, REG_V19, REG_V20, INS_OPTS_2D);
+
+ // trn2 vector
+ theEmitter->emitIns_R_R_R(INS_trn2, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_8B);
+ theEmitter->emitIns_R_R_R(INS_trn2, EA_16BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_16B);
+ theEmitter->emitIns_R_R_R(INS_trn2, EA_8BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_4H);
+ theEmitter->emitIns_R_R_R(INS_trn2, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_8H);
+ theEmitter->emitIns_R_R_R(INS_trn2, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2S);
+ theEmitter->emitIns_R_R_R(INS_trn2, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_4S);
+ theEmitter->emitIns_R_R_R(INS_trn2, EA_16BYTE, REG_V18, REG_V19, REG_V20, INS_OPTS_2D);
+
+ // uzp1 vector
+ theEmitter->emitIns_R_R_R(INS_uzp1, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_8B);
+ theEmitter->emitIns_R_R_R(INS_uzp1, EA_16BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_16B);
+ theEmitter->emitIns_R_R_R(INS_uzp1, EA_8BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_4H);
+ theEmitter->emitIns_R_R_R(INS_uzp1, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_8H);
+ theEmitter->emitIns_R_R_R(INS_uzp1, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2S);
+ theEmitter->emitIns_R_R_R(INS_uzp1, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_4S);
+ theEmitter->emitIns_R_R_R(INS_uzp1, EA_16BYTE, REG_V18, REG_V19, REG_V20, INS_OPTS_2D);
+
+ // uzp2 vector
+ theEmitter->emitIns_R_R_R(INS_uzp2, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_8B);
+ theEmitter->emitIns_R_R_R(INS_uzp2, EA_16BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_16B);
+ theEmitter->emitIns_R_R_R(INS_uzp2, EA_8BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_4H);
+ theEmitter->emitIns_R_R_R(INS_uzp2, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_8H);
+ theEmitter->emitIns_R_R_R(INS_uzp2, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2S);
+ theEmitter->emitIns_R_R_R(INS_uzp2, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_4S);
+ theEmitter->emitIns_R_R_R(INS_uzp2, EA_16BYTE, REG_V18, REG_V19, REG_V20, INS_OPTS_2D);
+
+ // zip1 vector
+ theEmitter->emitIns_R_R_R(INS_zip1, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_8B);
+ theEmitter->emitIns_R_R_R(INS_zip1, EA_16BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_16B);
+ theEmitter->emitIns_R_R_R(INS_zip1, EA_8BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_4H);
+ theEmitter->emitIns_R_R_R(INS_zip1, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_8H);
+ theEmitter->emitIns_R_R_R(INS_zip1, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2S);
+ theEmitter->emitIns_R_R_R(INS_zip1, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_4S);
+ theEmitter->emitIns_R_R_R(INS_zip1, EA_16BYTE, REG_V18, REG_V19, REG_V20, INS_OPTS_2D);
+
+ // zip2 vector
+ theEmitter->emitIns_R_R_R(INS_zip2, EA_8BYTE, REG_V0, REG_V1, REG_V2, INS_OPTS_8B);
+ theEmitter->emitIns_R_R_R(INS_zip2, EA_16BYTE, REG_V3, REG_V4, REG_V5, INS_OPTS_16B);
+ theEmitter->emitIns_R_R_R(INS_zip2, EA_8BYTE, REG_V6, REG_V7, REG_V8, INS_OPTS_4H);
+ theEmitter->emitIns_R_R_R(INS_zip2, EA_16BYTE, REG_V9, REG_V10, REG_V11, INS_OPTS_8H);
+ theEmitter->emitIns_R_R_R(INS_zip2, EA_8BYTE, REG_V12, REG_V13, REG_V14, INS_OPTS_2S);
+ theEmitter->emitIns_R_R_R(INS_zip2, EA_16BYTE, REG_V15, REG_V16, REG_V17, INS_OPTS_4S);
+ theEmitter->emitIns_R_R_R(INS_zip2, EA_16BYTE, REG_V18, REG_V19, REG_V20, INS_OPTS_2D);
+#endif // ALL_ARM64_EMITTER_UNIT_TESTS
+
#ifdef ALL_ARM64_EMITTER_UNIT_TESTS
//
// R_R_R vector multiply
diff --git a/src/coreclr/src/jit/codegenarmarch.cpp b/src/coreclr/src/jit/codegenarmarch.cpp
index ab0e11f1a03df2..47678ff275adc4 100644
--- a/src/coreclr/src/jit/codegenarmarch.cpp
+++ b/src/coreclr/src/jit/codegenarmarch.cpp
@@ -239,43 +239,8 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode)
break;
case GT_BITCAST:
- {
- GenTree* op1 = treeNode->AsOp()->gtOp1;
- if (varTypeIsFloating(treeNode) != varTypeIsFloating(op1))
- {
-#ifdef TARGET_ARM64
- inst_RV_RV(INS_fmov, targetReg, genConsumeReg(op1), targetType);
-#else // !TARGET_ARM64
- if (varTypeIsFloating(treeNode))
- {
- // GT_BITCAST on ARM is only used to cast floating-point arguments to integer
- // registers. Nobody generates GT_BITCAST from int to float currently.
- NYI_ARM("GT_BITCAST from 'int' to 'float'");
- }
- else
- {
- assert(varTypeIsFloating(op1));
-
- if (op1->TypeGet() == TYP_FLOAT)
- {
- inst_RV_RV(INS_vmov_f2i, targetReg, genConsumeReg(op1), targetType);
- }
- else
- {
- assert(op1->TypeGet() == TYP_DOUBLE);
- regNumber otherReg = treeNode->AsMultiRegOp()->gtOtherReg;
- assert(otherReg != REG_NA);
- inst_RV_RV_RV(INS_vmov_d2i, targetReg, otherReg, genConsumeReg(op1), EA_8BYTE);
- }
- }
-#endif // !TARGET_ARM64
- }
- else
- {
- inst_RV_RV(ins_Copy(targetType), targetReg, genConsumeReg(op1), targetType);
- }
- }
- break;
+ genCodeForBitCast(treeNode->AsOp());
+ break;
case GT_LCL_FLD_ADDR:
case GT_LCL_VAR_ADDR:
@@ -763,7 +728,7 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode)
#else // !TARGET_ARM64
// There is no zero register on ARM32
unreached();
-#endif // !_TARGET_ARM64
+#endif // !TARGET_ARM64
}
else
{
@@ -1105,6 +1070,59 @@ void CodeGen::genPutArgReg(GenTreeOp* tree)
genProduceReg(tree);
}
+//----------------------------------------------------------------------
+// genCodeForBitCast - Generate code for a GT_BITCAST that is not contained
+//
+// Arguments
+// treeNode - the GT_BITCAST for which we're generating code
+//
+void CodeGen::genCodeForBitCast(GenTreeOp* treeNode)
+{
+ regNumber targetReg = treeNode->GetRegNum();
+ var_types targetType = treeNode->TypeGet();
+ GenTree* op1 = treeNode->gtGetOp1();
+ genConsumeRegs(op1);
+ if (op1->isContained())
+ {
+ assert(op1->IsLocal() || op1->isIndir());
+ op1->gtType = treeNode->TypeGet();
+ op1->SetRegNum(targetReg);
+ op1->ClearContained();
+ JITDUMP("Changing type of BITCAST source to load directly.");
+ genCodeForTreeNode(op1);
+ }
+ else if (varTypeIsFloating(treeNode) != varTypeIsFloating(op1))
+ {
+ regNumber srcReg = op1->GetRegNum();
+ assert(genTypeSize(op1->TypeGet()) == genTypeSize(targetType));
+#ifdef TARGET_ARM
+ if (genTypeSize(targetType) == 8)
+ {
+ // Converting between long and double on ARM is a special case.
+ if (targetType == TYP_LONG)
+ {
+ regNumber otherReg = treeNode->AsMultiRegOp()->gtOtherReg;
+ assert(otherReg != REG_NA);
+ inst_RV_RV_RV(INS_vmov_d2i, targetReg, otherReg, srcReg, EA_8BYTE);
+ }
+ else
+ {
+ NYI_ARM("Converting from long to double");
+ }
+ }
+ else
+#endif // TARGET_ARM
+ {
+ instruction ins = ins_Copy(srcReg, targetType);
+ inst_RV_RV(ins, targetReg, srcReg, targetType);
+ }
+ }
+ else
+ {
+ inst_RV_RV(ins_Copy(targetType), targetReg, genConsumeReg(op1), targetType);
+ }
+}
+
#if FEATURE_ARG_SPLIT
//---------------------------------------------------------------------
// genPutArgSplit - generate code for a GT_PUTARG_SPLIT node
@@ -1344,7 +1362,7 @@ void CodeGen::genMultiRegCallStoreToLocal(GenTree* treeNode)
#elif defined(TARGET_ARM64)
// Structs of size >=9 and <=16 are returned in two return registers on ARM64 and HFAs.
assert(varTypeIsStruct(treeNode));
-#endif // _TARGET_*
+#endif // TARGET*
// Assumption: current implementation requires that a multi-reg
// var in 'var = call' is flagged as lvIsMultiRegRet to prevent it from
@@ -2496,7 +2514,7 @@ void CodeGen::genCallInstruction(GenTreeCall* call)
GetEmitter()->emitIns_R_R_I(INS_ldr, EA_4BYTE, tmpReg, regThis, 0);
#elif defined(TARGET_ARM64)
GetEmitter()->emitIns_R_R_I(INS_ldr, EA_4BYTE, REG_ZR, regThis, 0);
-#endif // _TARGET_*
+#endif // TARGET*
}
// Either gtControlExpr != null or gtCallAddr != null or it is a direct non-virtual call to a user or helper
@@ -3334,7 +3352,7 @@ void CodeGen::genFloatToFloatCast(GenTree* treeNode)
GetEmitter()->emitIns_R_R(INS_mov, emitActualTypeSize(treeNode), treeNode->GetRegNum(), op1->GetRegNum());
}
-#endif // _TARGET_*
+#endif // TARGET*
genProduceReg(treeNode);
}
diff --git a/src/coreclr/src/jit/codegencommon.cpp b/src/coreclr/src/jit/codegencommon.cpp
index 92f8fed1e1596d..f15259334eb722 100644
--- a/src/coreclr/src/jit/codegencommon.cpp
+++ b/src/coreclr/src/jit/codegencommon.cpp
@@ -243,8 +243,8 @@ int CodeGenInterface::genCallerSPtoFPdelta() const
// pushed ebp
callerSPtoFPdelta -= 2 * REGSIZE_BYTES;
#else
-#error "Unknown _TARGET_"
-#endif // _TARGET_*
+#error "Unknown TARGET"
+#endif // TARGET*
assert(callerSPtoFPdelta <= 0);
return callerSPtoFPdelta;
@@ -273,8 +273,8 @@ int CodeGenInterface::genCallerSPtoInitialSPdelta() const
callerSPtoSPdelta -= REGSIZE_BYTES;
}
#else
-#error "Unknown _TARGET_"
-#endif // _TARGET_*
+#error "Unknown TARGET"
+#endif // TARGET*
assert(callerSPtoSPdelta <= 0);
return callerSPtoSPdelta;
@@ -1509,7 +1509,7 @@ bool CodeGen::genCreateAddrMode(GenTree* addr,
break;
#endif // SCALED_ADDR_MODES
-#endif // !_TARGET_ARMARCH
+#endif // !TARGET_ARMARCH
case GT_NOP:
@@ -1587,7 +1587,7 @@ bool CodeGen::genCreateAddrMode(GenTree* addr,
break;
#endif // SCALED_ADDR_MODES
-#endif // !_TARGET_ARMARCH
+#endif // !TARGET_ARMARCH
case GT_NOP:
@@ -4363,8 +4363,18 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere
size = EA_8BYTE;
}
#endif
-
- GetEmitter()->emitIns_R_R(ins_Copy(destMemType), size, destRegNum, regNum);
+ instruction copyIns = ins_Copy(regNum, destMemType);
+#if defined(TARGET_XARCH)
+ // For INS_mov_xmm2i, the source xmm reg comes first.
+ if (copyIns == INS_mov_xmm2i)
+ {
+ GetEmitter()->emitIns_R_R(copyIns, size, regNum, destRegNum);
+ }
+ else
+#endif // TARGET_XARCH
+ {
+ GetEmitter()->emitIns_R_R(copyIns, size, destRegNum, regNum);
+ }
#ifdef USING_SCOPE_INFO
psiMoveToReg(varNum);
#endif // USING_SCOPE_INFO
@@ -4656,6 +4666,9 @@ void CodeGen::genCheckUseBlockInit()
continue;
}
+// TODO-Review: The code below is currently unreachable. We are guaranteed to execute one of the
+// 'continue' statements above.
+#if 0
/* If we don't know lifetimes of variables, must be conservative */
if (!compiler->backendRequiresLocalVarLifetimes())
{
@@ -4690,6 +4703,7 @@ void CodeGen::genCheckUseBlockInit()
{
largeGcStructs++;
}
+#endif
}
/* Don't forget about spill temps that hold pointers */
@@ -4718,6 +4732,11 @@ void CodeGen::genCheckUseBlockInit()
// Secondary factor is the presence of large structs that
// potentially only need some fields set to zero. We likely don't
// model this very well, but have left the logic as is for now.
+
+ // Compiler::fgVarNeedsExplicitZeroInit relies on this logic to
+ // find structs that are guaranteed to be block initialized.
+ // If this logic changes, Compiler::fgVarNeedsExplicitZeroInit needs
+ // to be modified.
CLANG_FORMAT_COMMENT_ANCHOR;
#ifdef TARGET_64BIT
@@ -5383,7 +5402,7 @@ void CodeGen::genPushCalleeSavedRegisters()
#else
assert(!"Unknown TARGET");
-#endif // _TARGET_*
+#endif // TARGET*
}
#if defined(TARGET_ARM)
@@ -5622,7 +5641,7 @@ void CodeGen::genZeroInitFltRegs(const regMaskTP& initFltRegs, const regMaskTP&
#elif defined(TARGET_ARM64)
// We will just zero out the entire vector register. This sets it to a double/float zero value
GetEmitter()->emitIns_R_I(INS_movi, EA_16BYTE, reg, 0x00, INS_OPTS_16B);
-#else // _TARGET_*
+#else // TARGET*
#error Unsupported or unset target architecture
#endif
fltInitReg = reg;
@@ -5657,7 +5676,7 @@ void CodeGen::genZeroInitFltRegs(const regMaskTP& initFltRegs, const regMaskTP&
#elif defined(TARGET_ARM64)
// We will just zero out the entire vector register. This sets it to a double/float zero value
GetEmitter()->emitIns_R_I(INS_movi, EA_16BYTE, reg, 0x00, INS_OPTS_16B);
-#else // _TARGET_*
+#else // TARGET*
#error Unsupported or unset target architecture
#endif
dblInitReg = reg;
@@ -6071,7 +6090,7 @@ void CodeGen::genPopCalleeSavedRegisters(bool jmpEpilog)
noway_assert(compiler->compCalleeRegsPushed == popCount);
}
-#endif // _TARGET_*
+#endif // TARGET*
// We need a register with value zero. Zero the initReg, if necessary, and set *pInitRegZeroed if so.
// Return the register to use. On ARM64, we never touch the initReg, and always just return REG_ZR.
@@ -6353,9 +6372,9 @@ void CodeGen::genZeroInitFrame(int untrLclHi, int untrLclLo, regNumber initReg,
}
#endif // !UNIX_AMD64_ABI
-#else // _TARGET_*
+#else // TARGET*
#error Unsupported or unset target architecture
-#endif // _TARGET_*
+#endif // TARGET*
}
else if (genInitStkLclCnt > 0)
{
@@ -8249,7 +8268,7 @@ void CodeGen::genFnEpilog(BasicBlock* block)
regSet.verifyRegUsed(REG_ECX);
}
else
-#endif // _TARGET_X86
+#endif // TARGET_X86
{
/* Add 'compiler->compLclFrameSize' to ESP */
/* Generate "add esp, " */
@@ -8319,7 +8338,7 @@ void CodeGen::genFnEpilog(BasicBlock* block)
inst_RV(INS_pop, REG_ECX, TYP_I_IMPL);
regSet.verifyRegUsed(REG_ECX);
}
-#endif // _TARGET_X86
+#endif // TARGET_X86
else
{
// We need to make ESP point to the callee-saved registers
@@ -8547,9 +8566,9 @@ void CodeGen::genFnEpilog(BasicBlock* block)
}
}
-#else // _TARGET_*
+#else // TARGET*
#error Unsupported or unset target architecture
-#endif // _TARGET_*
+#endif // TARGET*
#if defined(FEATURE_EH_FUNCLETS)
@@ -9239,7 +9258,7 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo()
}
}
-#else // _TARGET_*
+#else // TARGET*
/*****************************************************************************
*
@@ -9274,7 +9293,7 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo()
}
}
-#endif // _TARGET_*
+#endif // TARGET*
/*-----------------------------------------------------------------------------
*
@@ -9423,11 +9442,11 @@ void CodeGen::genSetPSPSym(regNumber initReg, bool* pInitRegZeroed)
GetEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_SPBASE, compiler->lvaPSPSym, 0);
-#else // _TARGET_*
+#else // TARGET*
NYI("Set function PSP sym");
-#endif // _TARGET_*
+#endif // TARGET*
}
#endif // FEATURE_EH_FUNCLETS
@@ -9866,7 +9885,7 @@ unsigned CodeGen::getFirstArgWithStackSlot()
return baseVarNum;
#elif defined(TARGET_AMD64)
return 0;
-#else // _TARGET_X86
+#else // TARGET_X86
// Not implemented for x86.
NYI_X86("getFirstArgWithStackSlot not yet implemented for x86.");
return BAD_VAR_NUM;
diff --git a/src/coreclr/src/jit/codegenlinear.cpp b/src/coreclr/src/jit/codegenlinear.cpp
index 45b2e9afefa237..c6f7b6f8c483cd 100644
--- a/src/coreclr/src/jit/codegenlinear.cpp
+++ b/src/coreclr/src/jit/codegenlinear.cpp
@@ -1413,6 +1413,10 @@ void CodeGen::genConsumeRegs(GenTree* tree)
}
#endif // FEATURE_HW_INTRINSICS
#endif // TARGET_XARCH
+ else if (tree->OperIs(GT_BITCAST))
+ {
+ genConsumeReg(tree->gtGetOp1());
+ }
else
{
#ifdef FEATURE_SIMD
diff --git a/src/coreclr/src/jit/codegenxarch.cpp b/src/coreclr/src/jit/codegenxarch.cpp
index 977a9e274fc23c..0eadce2c17f97b 100644
--- a/src/coreclr/src/jit/codegenxarch.cpp
+++ b/src/coreclr/src/jit/codegenxarch.cpp
@@ -1736,39 +1736,8 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode)
break;
case GT_BITCAST:
- {
- GenTree* const op1 = treeNode->AsOp()->gtOp1;
- genConsumeReg(op1);
-
- const bool srcFltReg = varTypeIsFloating(op1) || varTypeIsSIMD(op1);
- const bool dstFltReg = varTypeIsFloating(treeNode) || varTypeIsSIMD(treeNode);
- if (srcFltReg != dstFltReg)
- {
- instruction ins;
- regNumber fltReg;
- regNumber intReg;
- if (dstFltReg)
- {
- ins = ins_CopyIntToFloat(op1->TypeGet(), treeNode->TypeGet());
- fltReg = treeNode->GetRegNum();
- intReg = op1->GetRegNum();
- }
- else
- {
- ins = ins_CopyFloatToInt(op1->TypeGet(), treeNode->TypeGet());
- intReg = treeNode->GetRegNum();
- fltReg = op1->GetRegNum();
- }
- inst_RV_RV(ins, fltReg, intReg, treeNode->TypeGet());
- }
- else if (treeNode->GetRegNum() != op1->GetRegNum())
- {
- inst_RV_RV(ins_Copy(treeNode->TypeGet()), treeNode->GetRegNum(), op1->GetRegNum(), treeNode->TypeGet());
- }
-
- genProduceReg(treeNode);
+ genCodeForBitCast(treeNode->AsOp());
break;
- }
case GT_LCL_FLD_ADDR:
case GT_LCL_VAR_ADDR:
@@ -4588,7 +4557,8 @@ void CodeGen::genCodeForLclVar(GenTreeLclVar* tree)
// lcl_vars are not defs
assert((tree->gtFlags & GTF_VAR_DEF) == 0);
- bool isRegCandidate = compiler->lvaTable[tree->GetLclNum()].lvIsRegCandidate();
+ LclVarDsc* varDsc = compiler->lvaGetDesc(tree);
+ bool isRegCandidate = varDsc->lvIsRegCandidate();
// If this is a register candidate that has been spilled, genConsumeReg() will
// reload it at the point of use. Otherwise, if it's not in a register, we load it here.
@@ -4621,8 +4591,9 @@ void CodeGen::genCodeForStoreLclFld(GenTreeLclFld* tree)
assert(tree->OperIs(GT_STORE_LCL_FLD));
var_types targetType = tree->TypeGet();
+ GenTree* op1 = tree->gtGetOp1();
+
noway_assert(targetType != TYP_STRUCT);
- assert(!varTypeIsFloating(targetType) || (targetType == tree->gtOp1->TypeGet()));
#ifdef FEATURE_SIMD
// storing of TYP_SIMD12 (i.e. Vector3) field
@@ -4633,7 +4604,9 @@ void CodeGen::genCodeForStoreLclFld(GenTreeLclFld* tree)
}
#endif // FEATURE_SIMD
- GenTree* op1 = tree->gtGetOp1();
+ assert(varTypeUsesFloatReg(targetType) == varTypeUsesFloatReg(op1));
+ assert(genTypeSize(genActualType(targetType)) == genTypeSize(genActualType(op1->TypeGet())));
+
genConsumeRegs(op1);
GetEmitter()->emitInsBinary(ins_Store(targetType), emitTypeSize(tree), tree, op1);
@@ -4704,7 +4677,24 @@ void CodeGen::genCodeForStoreLclVar(GenTreeLclVar* tree)
genConsumeRegs(op1);
- if (targetReg == REG_NA)
+ if (op1->OperIs(GT_BITCAST) && op1->isContained())
+ {
+ GenTree* bitCastSrc = op1->gtGetOp1();
+ var_types srcType = bitCastSrc->TypeGet();
+ noway_assert(!bitCastSrc->isContained());
+ if (targetReg == REG_NA)
+ {
+ emit->emitIns_S_R(ins_Store(srcType, compiler->isSIMDTypeLocalAligned(lclNum)),
+ emitTypeSize(targetType), bitCastSrc->GetRegNum(), lclNum, 0);
+ genUpdateLife(tree);
+ varDsc->SetRegNum(REG_STK);
+ }
+ else
+ {
+ genBitCast(targetType, targetReg, srcType, bitCastSrc->GetRegNum());
+ }
+ }
+ else if (targetReg == REG_NA)
{
// stack store
emit->emitInsStoreLcl(ins_Store(targetType, compiler->isSIMDTypeLocalAligned(lclNum)),
@@ -5028,7 +5018,7 @@ void CodeGen::genCodeForStoreInd(GenTreeStoreInd* tree)
GenTree* addr = tree->Addr();
var_types targetType = tree->TypeGet();
- assert(!varTypeIsFloating(targetType) || (targetType == data->TypeGet()));
+ assert(!varTypeIsFloating(targetType) || (genTypeSize(targetType) == genTypeSize(data->TypeGet())));
GCInfo::WriteBarrierForm writeBarrierForm = gcInfo.gcIsWriteBarrierCandidate(tree, data);
if (writeBarrierForm != GCInfo::WBF_NoBarrier)
@@ -7435,6 +7425,84 @@ void CodeGen::genIntrinsic(GenTree* treeNode)
genProduceReg(treeNode);
}
+//----------------------------------------------------------------------
+// genBitCast - Generate the instruction to move a value between register files
+//
+// Arguments
+// targetType - the destination type
+// targetReg - the destination register
+// srcType - the source type
+// srcReg - the source register
+//
+void CodeGen::genBitCast(var_types targetType, regNumber targetReg, var_types srcType, regNumber srcReg)
+{
+ const bool srcFltReg = varTypeIsFloating(srcType) || varTypeIsSIMD(srcType);
+ assert(srcFltReg == genIsValidFloatReg(srcReg));
+ const bool dstFltReg = varTypeIsFloating(targetType) || varTypeIsSIMD(targetType);
+ assert(dstFltReg == genIsValidFloatReg(targetReg));
+ if (srcFltReg != dstFltReg)
+ {
+ instruction ins;
+ regNumber fltReg;
+ regNumber intReg;
+ if (dstFltReg)
+ {
+ ins = ins_CopyIntToFloat(srcType, targetType);
+ fltReg = targetReg;
+ intReg = srcReg;
+ }
+ else
+ {
+ ins = ins_CopyFloatToInt(srcType, targetType);
+ intReg = targetReg;
+ fltReg = srcReg;
+ }
+ inst_RV_RV(ins, fltReg, intReg, targetType);
+ }
+ else if (targetReg != srcReg)
+ {
+ inst_RV_RV(ins_Copy(targetType), targetReg, srcReg, targetType);
+ }
+}
+
+//----------------------------------------------------------------------
+// genCodeForBitCast - Generate code for a GT_BITCAST that is not contained
+//
+// Arguments
+// treeNode - the GT_BITCAST for which we're generating code
+//
+void CodeGen::genCodeForBitCast(GenTreeOp* treeNode)
+{
+ regNumber targetReg = treeNode->GetRegNum();
+ var_types targetType = treeNode->TypeGet();
+ GenTree* op1 = treeNode->gtGetOp1();
+ genConsumeRegs(op1);
+
+ if (op1->isContained())
+ {
+ assert(op1->IsLocal() || op1->isIndir());
+ if (genIsRegCandidateLocal(op1))
+ {
+ unsigned lclNum = op1->AsLclVar()->GetLclNum();
+ GetEmitter()->emitIns_R_S(ins_Load(treeNode->TypeGet(), compiler->isSIMDTypeLocalAligned(lclNum)),
+ emitTypeSize(treeNode), targetReg, lclNum, 0);
+ }
+ else
+ {
+ op1->gtType = treeNode->TypeGet();
+ op1->SetRegNum(targetReg);
+ op1->ClearContained();
+ JITDUMP("Changing type of BITCAST source to load directly.");
+ genCodeForTreeNode(op1);
+ }
+ }
+ else
+ {
+ genBitCast(targetType, targetReg, op1->TypeGet(), op1->GetRegNum());
+ }
+ genProduceReg(treeNode);
+}
+
//-------------------------------------------------------------------------- //
// getBaseVarForPutArgStk - returns the baseVarNum for passing a stack arg.
//
@@ -7585,7 +7653,7 @@ void CodeGen::genRemoveAlignmentAfterCall(GenTreeCall* call, unsigned bias)
#endif // !UNIX_X86_ABI_
#else // TARGET_X86
assert(bias == 0);
-#endif // !_TARGET_X86
+#endif // !TARGET_X86
}
#ifdef TARGET_X86
diff --git a/src/coreclr/src/jit/compiler.cpp b/src/coreclr/src/jit/compiler.cpp
index f4bc154c59aa3e..c066d2b1be9f11 100644
--- a/src/coreclr/src/jit/compiler.cpp
+++ b/src/coreclr/src/jit/compiler.cpp
@@ -822,11 +822,11 @@ var_types Compiler::getArgTypeForStruct(CORINFO_CLASS_HANDLE clsHnd,
howToPassStruct = SPK_ByValue;
useType = TYP_STRUCT;
-#else // _TARGET_XXX_
+#else // TARGET_XXX
noway_assert(!"Unhandled TARGET in getArgTypeForStruct (with FEATURE_MULTIREG_ARGS=1)");
-#endif // _TARGET_XXX_
+#endif // TARGET_XXX
}
}
else // (structSize > MAX_PASS_MULTIREG_BYTES)
@@ -849,11 +849,11 @@ var_types Compiler::getArgTypeForStruct(CORINFO_CLASS_HANDLE clsHnd,
howToPassStruct = SPK_ByReference;
useType = TYP_UNKNOWN;
-#else // _TARGET_XXX_
+#else // TARGET_XXX
noway_assert(!"Unhandled TARGET in getArgTypeForStruct");
-#endif // _TARGET_XXX_
+#endif // TARGET_XXX
}
}
@@ -1080,11 +1080,11 @@ var_types Compiler::getReturnTypeForStruct(CORINFO_CLASS_HANDLE clsHnd,
howToReturnStruct = SPK_ByReference;
useType = TYP_UNKNOWN;
-#else // _TARGET_XXX_
+#else // TARGET_XXX
noway_assert(!"Unhandled TARGET in getReturnTypeForStruct (with FEATURE_MULTIREG_ARGS=1)");
-#endif // _TARGET_XXX_
+#endif // TARGET_XXX
}
}
else // (structSize > MAX_RET_MULTIREG_BYTES) || (FEATURE_MULTIREG_RET == 0)
@@ -9102,6 +9102,21 @@ void cTreeFlags(Compiler* comp, GenTree* tree)
{
chars += printf("[CALL_M_PINVOKE]");
}
+
+ if (call->IsFatPointerCandidate())
+ {
+ chars += printf("[CALL_FAT_POINTER_CANDIDATE]");
+ }
+
+ if (call->IsGuarded())
+ {
+ chars += printf("[CALL_GUARDED]");
+ }
+
+ if (call->IsExpRuntimeLookup())
+ {
+ chars += printf("[CALL_EXP_RUNTIME_LOOKUP]");
+ }
}
break;
default:
diff --git a/src/coreclr/src/jit/compiler.h b/src/coreclr/src/jit/compiler.h
index 33a1859f91c948..d8aff229e8156d 100644
--- a/src/coreclr/src/jit/compiler.h
+++ b/src/coreclr/src/jit/compiler.h
@@ -1616,7 +1616,7 @@ struct fgArgTabEntry
bool isPassedInFloatRegisters()
{
-#ifdef _TARGET_X86
+#ifdef TARGET_X86
return false;
#else
return isValidFloatArgReg(GetRegNum());
@@ -2447,7 +2447,7 @@ class Compiler
// For binary opers.
GenTree* gtNewOperNode(genTreeOps oper, var_types type, GenTree* op1, GenTree* op2);
- GenTree* gtNewQmarkNode(var_types type, GenTree* cond, GenTree* colon);
+ GenTreeQmark* gtNewQmarkNode(var_types type, GenTree* cond, GenTree* colon);
GenTree* gtNewLargeOperNode(genTreeOps oper,
var_types type = TYP_I_IMPL,
@@ -4542,8 +4542,8 @@ class Compiler
unsigned fgSsaPassesCompleted; // Number of times fgSsaBuild has been run.
- // Returns "true" if a struct temp of the given type requires needs zero init in this block
- inline bool fgStructTempNeedsExplicitZeroInit(LclVarDsc* varDsc, BasicBlock* block);
+ // Returns "true" if the variable needs explicit zero initialization.
+ inline bool fgVarNeedsExplicitZeroInit(LclVarDsc* varDsc, bool bbInALoop, bool bbIsReturn);
// The value numbers for this compilation.
ValueNumStore* vnStore;
@@ -6326,14 +6326,15 @@ class Compiler
}
};
-#define OMF_HAS_NEWARRAY 0x00000001 // Method contains 'new' of an array
-#define OMF_HAS_NEWOBJ 0x00000002 // Method contains 'new' of an object type.
-#define OMF_HAS_ARRAYREF 0x00000004 // Method contains array element loads or stores.
-#define OMF_HAS_VTABLEREF 0x00000008 // Method contains method table reference.
-#define OMF_HAS_NULLCHECK 0x00000010 // Method contains null check.
-#define OMF_HAS_FATPOINTER 0x00000020 // Method contains call, that needs fat pointer transformation.
-#define OMF_HAS_OBJSTACKALLOC 0x00000040 // Method contains an object allocated on the stack.
-#define OMF_HAS_GUARDEDDEVIRT 0x00000080 // Method contains guarded devirtualization candidate
+#define OMF_HAS_NEWARRAY 0x00000001 // Method contains 'new' of an array
+#define OMF_HAS_NEWOBJ 0x00000002 // Method contains 'new' of an object type.
+#define OMF_HAS_ARRAYREF 0x00000004 // Method contains array element loads or stores.
+#define OMF_HAS_VTABLEREF 0x00000008 // Method contains method table reference.
+#define OMF_HAS_NULLCHECK 0x00000010 // Method contains null check.
+#define OMF_HAS_FATPOINTER 0x00000020 // Method contains call, that needs fat pointer transformation.
+#define OMF_HAS_OBJSTACKALLOC 0x00000040 // Method contains an object allocated on the stack.
+#define OMF_HAS_GUARDEDDEVIRT 0x00000080 // Method contains guarded devirtualization candidate
+#define OMF_HAS_EXPRUNTIMELOOKUP 0x00000100 // Method contains a runtime lookup to an expandable dictionary.
bool doesMethodHaveFatPointer()
{
@@ -6373,6 +6374,23 @@ class Compiler
unsigned methodAttr,
unsigned classAttr);
+ bool doesMethodHaveExpRuntimeLookup()
+ {
+ return (optMethodFlags & OMF_HAS_EXPRUNTIMELOOKUP) != 0;
+ }
+
+ void setMethodHasExpRuntimeLookup()
+ {
+ optMethodFlags |= OMF_HAS_EXPRUNTIMELOOKUP;
+ }
+
+ void clearMethodHasExpRuntimeLookup()
+ {
+ optMethodFlags &= ~OMF_HAS_EXPRUNTIMELOOKUP;
+ }
+
+ void addExpRuntimeLookupCandidate(GenTreeCall* call);
+
unsigned optMethodFlags;
bool doesMethodHaveNoReturnCalls()
diff --git a/src/coreclr/src/jit/compiler.hpp b/src/coreclr/src/jit/compiler.hpp
index d0de0f1f1e1be5..889d5017b0d769 100644
--- a/src/coreclr/src/jit/compiler.hpp
+++ b/src/coreclr/src/jit/compiler.hpp
@@ -4106,26 +4106,59 @@ inline void Compiler::CLR_API_Leave(API_ICorJitInfo_Names ename)
#endif // MEASURE_CLRAPI_CALLS
//------------------------------------------------------------------------------
-// fgStructTempNeedsExplicitZeroInit : Check whether temp struct needs
-// explicit zero initialization in this basic block.
+// fgVarNeedsExplicitZeroInit : Check whether the variable needs an explicit zero initialization.
//
// Arguments:
-// varDsc - struct local var description
-// block - basic block to check
+// varDsc - local var description
+// bbInALoop - true if the basic block may be in a loop
+// bbIsReturn - true if the basic block always returns
//
// Returns:
-// true if the struct temp needs explicit zero-initialization in this basic block;
+// true if the var needs explicit zero-initialization in this basic block;
// false otherwise
//
// Notes:
-// If compInitMem is true, structs with GC pointer fields and long-lifetime structs
-// are fully zero-initialized in the prologue. Therefore, we don't need to insert
-// zero-initialization in this block if it is not in a loop.
+// If the variable is not being initialized in a loop, we can avoid explicit zero initialization if
+// - the variable is a gc pointer, or
+// - the variable is a struct with gc pointer fields and either all fields are gc pointer fields
+// or the struct is big enough to guarantee block initialization, or
+// - compInitMem is set and the variable has a long lifetime or has gc fields.
+// In these cases we will insert zero-initialization in the prolog if necessary.
-bool Compiler::fgStructTempNeedsExplicitZeroInit(LclVarDsc* varDsc, BasicBlock* block)
+bool Compiler::fgVarNeedsExplicitZeroInit(LclVarDsc* varDsc, bool bbInALoop, bool bbIsReturn)
{
- return !info.compInitMem || ((block->bbFlags & BBF_BACKWARD_JUMP) != 0) ||
- (!varDsc->HasGCPtr() && varDsc->lvIsTemp);
+ if (bbInALoop && !bbIsReturn)
+ {
+ return true;
+ }
+
+ if (varTypeIsGC(varDsc->lvType))
+ {
+ return false;
+ }
+
+ if ((varDsc->lvType == TYP_STRUCT) && varDsc->HasGCPtr())
+ {
+ ClassLayout* layout = varDsc->GetLayout();
+ if (layout->GetSlotCount() == layout->GetGCPtrCount())
+ {
+ return false;
+ }
+
+// Below conditions guarantee block initialization, which will initialize
+// all struct fields. If the logic for block initialization in CodeGen::genCheckUseBlockInit()
+// changes, these conditions need to be updated.
+#ifdef TARGET_64BIT
+ if (roundUp(varDsc->lvSize(), TARGET_POINTER_SIZE) / sizeof(int) > 8)
+#else
+ if (roundUp(varDsc->lvSize(), TARGET_POINTER_SIZE) / sizeof(int) > 4)
+#endif
+ {
+ return false;
+ }
+ }
+
+ return !info.compInitMem || (varDsc->lvIsTemp && !varDsc->HasGCPtr());
}
/*****************************************************************************/
diff --git a/src/coreclr/src/jit/disasm.cpp b/src/coreclr/src/jit/disasm.cpp
index 9190820ff0168c..5896454685f685 100644
--- a/src/coreclr/src/jit/disasm.cpp
+++ b/src/coreclr/src/jit/disasm.cpp
@@ -319,9 +319,9 @@ size_t DisAssembler::disCchAddrMember(
break;
}
-#else // _TARGET_*
+#else // TARGET*
#error Unsupported or unset target architecture
-#endif // _TARGET_*
+#endif // TARGET*
if (retval == 0)
{
@@ -568,9 +568,9 @@ size_t DisAssembler::disCchFixupMember(
break;
}
-#else // _TARGET_*
+#else // TARGET*
#error Unsupported or unset target architecture
-#endif // _TARGET_*
+#endif // TARGET*
/* no displacement */
@@ -781,9 +781,9 @@ size_t DisAssembler::disCchRegRelMember(
break;
}
-#else // _TARGET_*
+#else // TARGET*
#error Unsupported or unset target architecture
-#endif // _TARGET_*
+#endif // TARGET*
/* save displacement */
@@ -1083,9 +1083,9 @@ size_t DisAssembler::CbDisassemble(DIS* pdis,
break;
} // end switch
-#else // _TARGET_*
+#else // TARGET*
#error Unsupported or unset target architecture
-#endif // _TARGET_*
+#endif // TARGET*
return cb;
} // end if
@@ -1252,7 +1252,7 @@ void DisAssembler::DisasmBuffer(FILE* pfile, bool printit)
pdis = DIS::PdisNew(DIS::distX8664);
#elif defined(TARGET_ARM64)
pdis = DIS::PdisNew(DIS::distArm64);
-#else // _TARGET_*
+#else // TARGET*
#error Unsupported or unset target architecture
#endif
diff --git a/src/coreclr/src/jit/disasm.h b/src/coreclr/src/jit/disasm.h
index c4d09a38376f74..f7cea20b5c4151 100644
--- a/src/coreclr/src/jit/disasm.h
+++ b/src/coreclr/src/jit/disasm.h
@@ -45,7 +45,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#include "disx86.h"
#elif defined(TARGET_ARM64)
#include "disarm64.h"
-#else // _TARGET_*
+#else // TARGET*
#error Unsupported or unset target architecture
#endif
diff --git a/src/coreclr/src/jit/ee_il_dll.cpp b/src/coreclr/src/jit/ee_il_dll.cpp
index d5d3bbdefd46bf..cbf8d59135338d 100644
--- a/src/coreclr/src/jit/ee_il_dll.cpp
+++ b/src/coreclr/src/jit/ee_il_dll.cpp
@@ -517,7 +517,7 @@ unsigned Compiler::eeGetArgSize(CORINFO_ARG_LIST_HANDLE list, CORINFO_SIG_INFO*
// otherwise will we pass this struct by value in multiple registers
#else
NYI("unknown target");
-#endif // defined(_TARGET_XXX_)
+#endif // defined(TARGET_XXX)
#endif // FEATURE_MULTIREG_ARGS
// we pass this struct by value in multiple registers
diff --git a/src/coreclr/src/jit/eeinterface.cpp b/src/coreclr/src/jit/eeinterface.cpp
index d2efd790a0e595..d0a08959f43db8 100644
--- a/src/coreclr/src/jit/eeinterface.cpp
+++ b/src/coreclr/src/jit/eeinterface.cpp
@@ -102,23 +102,24 @@ const char* Compiler::eeGetMethodFullName(CORINFO_METHOD_HANDLE hnd)
/* add length of methodName and opening bracket */
length += strlen(methodName) + 1;
- /* figure out the signature */
+ PAL_TRY(FilterSuperPMIExceptionsParam_eeinterface*, pParam, ¶m)
+ {
- param.pThis->eeGetMethodSig(param.hnd, ¶m.sig);
+ /* figure out the signature */
- // allocate space to hold the class names for each of the parameters
+ pParam->pThis->eeGetMethodSig(pParam->hnd, &pParam->sig);
- if (param.sig.numArgs > 0)
- {
- param.pArgNames = getAllocator(CMK_DebugOnly).allocate(param.sig.numArgs);
- }
- else
- {
- param.pArgNames = nullptr;
- }
+ // allocate space to hold the class names for each of the parameters
+
+ if (pParam->sig.numArgs > 0)
+ {
+ pParam->pArgNames = pParam->pThis->getAllocator(CMK_DebugOnly).allocate(pParam->sig.numArgs);
+ }
+ else
+ {
+ pParam->pArgNames = nullptr;
+ }
- PAL_TRY(FilterSuperPMIExceptionsParam_eeinterface*, pParam, ¶m)
- {
unsigned i;
pParam->argLst = pParam->sig.args;
diff --git a/src/coreclr/src/jit/emit.cpp b/src/coreclr/src/jit/emit.cpp
index d621d5a060481a..9288f6c2c7392d 100644
--- a/src/coreclr/src/jit/emit.cpp
+++ b/src/coreclr/src/jit/emit.cpp
@@ -4615,6 +4615,16 @@ unsigned emitter::emitEndCodeGen(Compiler* comp,
}
#endif
+#ifdef TARGET_XARCH
+ // For x64/x86, align Tier1 methods to 32 byte boundaries if
+ // they are larger than 16 bytes and contain a loop.
+ //
+ if (emitComp->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_TIER1) && (emitTotalHotCodeSize > 16) && emitComp->fgHasLoops)
+ {
+ allocMemFlag = CORJIT_ALLOCMEM_FLG_32BYTE_ALIGN;
+ }
+#endif
+
if (emitConsDsc.align16)
{
allocMemFlag = static_cast(allocMemFlag | CORJIT_ALLOCMEM_FLG_RODATA_16BYTE_ALIGN);
diff --git a/src/coreclr/src/jit/emit.h b/src/coreclr/src/jit/emit.h
index cec64ecb811881..37a1795aa13e24 100644
--- a/src/coreclr/src/jit/emit.h
+++ b/src/coreclr/src/jit/emit.h
@@ -1309,7 +1309,7 @@ class emitter
#define PERFSCORE_LATENCY_WR_GENERAL PERFSCORE_LATENCY_1C
#define PERFSCORE_LATENCY_RD_WR_GENERAL PERFSCORE_LATENCY_4C
-#endif // _TARGET_XXX
+#endif // TARGET_XXX
// Make this an enum:
//
diff --git a/src/coreclr/src/jit/emitarm64.cpp b/src/coreclr/src/jit/emitarm64.cpp
index 4771a95e9202a8..c196d95ebf4da4 100644
--- a/src/coreclr/src/jit/emitarm64.cpp
+++ b/src/coreclr/src/jit/emitarm64.cpp
@@ -730,6 +730,35 @@ void emitter::emitInsSanityCheck(instrDesc* id)
assert(isVectorRegister(id->idReg2()));
break;
+ case IF_DV_2Q: // DV_2Q .........X...... ......nnnnnddddd Sd Vn (faddp, fmaxnmp, fmaxp, fminnmp,
+ // fminp - scalar)
+ if (id->idOpSize() == EA_8BYTE)
+ {
+ assert(id->idInsOpt() == INS_OPTS_2D);
+ }
+ else
+ {
+ assert(id->idOpSize() == EA_4BYTE);
+ assert(id->idInsOpt() == INS_OPTS_2S);
+ }
+ assert(isVectorRegister(id->idReg1()));
+ assert(isVectorRegister(id->idReg2()));
+ break;
+
+ case IF_DV_2R: // DV_2R .Q.......X...... ......nnnnnddddd Sd Vn (fmaxnmv, fmaxv, fminnmv, fminv)
+ assert(id->idOpSize() == EA_4BYTE);
+ assert(id->idInsOpt() == INS_OPTS_4S);
+ assert(isVectorRegister(id->idReg1()));
+ assert(isVectorRegister(id->idReg2()));
+ break;
+
+ case IF_DV_2S: // DV_2S ........XX...... ......nnnnnddddd Sd Vn (addp - scalar)
+ assert(id->idOpSize() == EA_8BYTE);
+ assert(id->idInsOpt() == INS_OPTS_2D);
+ assert(isVectorRegister(id->idReg1()));
+ assert(isVectorRegister(id->idReg2()));
+ break;
+
case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
assert(isValidVectorDatasize(id->idOpSize()));
assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
@@ -895,6 +924,11 @@ bool emitter::emitInsMayWriteToGCReg(instrDesc* id)
case IF_DV_2P: // DV_2P ................ ......nnnnnddddd Vd Vn (aes*, sha1su1) - Vd both source and
// destination
+ case IF_DV_2Q: // DV_2Q .........X...... ......nnnnnddddd Sd Vn (faddp, fmaxnmp, fmaxp, fminnmp,
+ // fminp - scalar)
+ case IF_DV_2R: // DV_2R .Q.......X...... ......nnnnnddddd Sd Vn (fmaxnmv, fmaxv, fminnmv, fminv)
+ case IF_DV_2S: // DV_2S ........XX...... ......nnnnnddddd Sd Vn (addp - scalar)
+
case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector)
case IF_DV_3B: // DV_3B .Q.......X.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
@@ -1527,7 +1561,8 @@ emitter::code_t emitter::emitInsCode(instruction ins, insFormat fmt)
const static insFormat formatEncode2M[2] = {IF_DV_3A, IF_DV_3AI};
const static insFormat formatEncode2N[2] = {IF_DV_2N, IF_DV_2O};
const static insFormat formatEncode2O[2] = {IF_DV_3E, IF_DV_3A};
- const static insFormat formatEncode2P[2] = {IF_DV_2G, IF_DV_3B};
+ const static insFormat formatEncode2P[2] = {IF_DV_2Q, IF_DV_3B};
+ const static insFormat formatEncode2Q[2] = {IF_DV_2S, IF_DV_3A};
code_t code = BAD_CODE;
insFormat insFmt = emitInsFormat(ins);
@@ -1976,6 +2011,17 @@ emitter::code_t emitter::emitInsCode(instruction ins, insFormat fmt)
}
break;
+ case IF_EN2Q:
+ for (index = 0; index < 2; index++)
+ {
+ if (fmt == formatEncode2Q[index])
+ {
+ encoding_found = true;
+ break;
+ }
+ }
+ break;
+
case IF_BI_0A:
case IF_BI_0B:
case IF_BI_0C:
@@ -2038,6 +2084,7 @@ emitter::code_t emitter::emitInsCode(instruction ins, insFormat fmt)
case IF_DV_2N:
case IF_DV_2O:
case IF_DV_2P:
+ case IF_DV_2R:
case IF_DV_3A:
case IF_DV_3AI:
case IF_DV_3B:
@@ -4293,12 +4340,34 @@ void emitter::emitIns_R_R(
break;
case INS_faddp:
+ case INS_fmaxnmp:
+ case INS_fmaxp:
+ case INS_fminnmp:
+ case INS_fminp:
// Scalar operation
- assert(insOptsNone(opt));
- assert(isValidVectorElemsizeFloat(size));
+ assert(((size == EA_4BYTE) && (opt == INS_OPTS_2S)) || ((size == EA_8BYTE) && (opt == INS_OPTS_2D)));
assert(isVectorRegister(reg1));
assert(isVectorRegister(reg2));
- fmt = IF_DV_2G;
+ fmt = IF_DV_2Q;
+ break;
+
+ case INS_fmaxnmv:
+ case INS_fmaxv:
+ case INS_fminnmv:
+ case INS_fminv:
+ assert(size == EA_4BYTE);
+ assert(opt == INS_OPTS_4S);
+ assert(isVectorRegister(reg1));
+ assert(isVectorRegister(reg2));
+ fmt = IF_DV_2R;
+ break;
+
+ case INS_addp:
+ assert(size == EA_8BYTE);
+ assert(opt == INS_OPTS_2D);
+ assert(isVectorRegister(reg1));
+ assert(isVectorRegister(reg2));
+ fmt = IF_DV_2S;
break;
case INS_fcvt:
@@ -5304,14 +5373,19 @@ void emitter::emitIns_R_R_R(
case INS_saba:
case INS_sabd:
case INS_smax:
+ case INS_smaxp:
case INS_smin:
+ case INS_sminp:
case INS_uaba:
case INS_uabd:
case INS_umax:
+ case INS_umaxp:
case INS_umin:
+ case INS_uminp:
assert(elemsize != EA_8BYTE); // can't use 2D or 1D
__fallthrough;
+ case INS_addp:
case INS_uzp1:
case INS_uzp2:
case INS_zip1:
@@ -5393,7 +5467,9 @@ void emitter::emitIns_R_R_R(
case INS_fsub:
case INS_fdiv:
case INS_fmax:
+ case INS_fmaxnm:
case INS_fmin:
+ case INS_fminnm:
case INS_fabd:
case INS_fmul:
case INS_fmulx:
@@ -5432,6 +5508,11 @@ void emitter::emitIns_R_R_R(
break;
case INS_faddp:
+ case INS_fmaxnmp:
+ case INS_fmaxp:
+ case INS_fminnmp:
+ case INS_fminp:
+
case INS_fmla:
case INS_fmls:
assert(isVectorRegister(reg1));
@@ -10074,7 +10155,9 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
dst += emitOutput_Instr(dst, code);
break;
- case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov,fcvtXX - register)
+ case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov, fcvtXX - register)
+ case IF_DV_2Q: // DV_2Q .........X...... ......nnnnnddddd Vd Vn (faddp, fmaxnmp, fmaxp, fminnmp,
+ // fminp - scalar)
elemsize = id->idOpSize();
code = emitInsCode(ins, fmt);
code |= insEncodeFloatElemsize(elemsize); // X
@@ -10119,6 +10202,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
break;
case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
+ case IF_DV_2S: // DV_2S ........XX...... ......nnnnnddddd Sd Vn (addp - scalar)
elemsize = id->idOpSize();
code = emitInsCode(ins, fmt);
code |= insEncodeElemsize(elemsize); // XX
@@ -10165,6 +10249,17 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
dst += emitOutput_Instr(dst, code);
break;
+ case IF_DV_2R: // DV_2R .Q.......X...... ......nnnnnddddd Sd Vn (fmaxnmv, fmaxv, fminnmv, fminv)
+ code = emitInsCode(ins, fmt);
+ datasize = optGetDatasize(id->idInsOpt());
+ elemsize = optGetElemsize(id->idInsOpt());
+ code |= insEncodeVectorsize(datasize); // Q
+ code |= insEncodeFloatElemsize(elemsize); // X
+ code |= insEncodeReg_Vd(id->idReg1()); // ddddd
+ code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
+ dst += emitOutput_Instr(dst, code);
+ break;
+
case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
code = emitInsCode(ins, fmt);
elemsize = optGetElemsize(id->idInsOpt());
@@ -11713,6 +11808,15 @@ void emitter::emitDispIns(
emitDispReg(id->idReg2(), srcsize, false);
break;
+ case IF_DV_2Q: // DV_2Q .........X...... ......nnnnnddddd Sd Vn (faddp, fmaxnmp, fmaxp, fminnmp,
+ // fminp - scalar)
+ case IF_DV_2R: // DV_2R .Q.......X...... ......nnnnnddddd Sd Vn (fmaxnmv, fmaxv, fminnmv, fminv)
+ case IF_DV_2S: // DV_2S ........XX...... ......nnnnnddddd Sd Vn (addp - scalar)
+ elemsize = id->idOpSize();
+ emitDispReg(id->idReg1(), elemsize, true);
+ emitDispVectorReg(id->idReg2(), id->idInsOpt(), false);
+ break;
+
case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
case IF_DV_3B: // DV_3B .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
@@ -12699,7 +12803,7 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins
}
break;
- case IF_DV_2G: // fmov, fabs, fneg, fsqrt, faddp, fcmXX, fcvtXX, frintX, scvtf, ucvtf (scalar)
+ case IF_DV_2G: // fmov, fabs, fneg, fsqrt, fcmXX, fcvtXX, frintX, scvtf, ucvtf (scalar)
switch (ins)
{
case INS_fmov:
@@ -12710,7 +12814,6 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins
case INS_fabs:
case INS_fneg:
- case INS_faddp:
case INS_fcvtas:
case INS_fcvtau:
@@ -12764,21 +12867,49 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins
}
break;
- case IF_DV_3B: // fadd, fsub, fdiv, fmul, fmulx, fmla, fmls, fmin, fmax, fabd, faddp, fcmXX (vector)
+ case IF_DV_2Q: // faddp, fmaxnmp, fmaxp, fminnmp, fminp (scalar)
+ case IF_DV_2R: // fmaxnmv, fmaxv, fminnmv, fminv
+ case IF_DV_2S: // addp (scalar)
+ result.insThroughput = PERFSCORE_THROUGHPUT_2X;
+ result.insLatency = PERFSCORE_LATENCY_4C;
+ break;
+
+ case IF_DV_3B: // fadd, fsub, fdiv, fmul, fmulx, fmla, fmls, fmin, fminnm, fmax, fmaxnm, fabd, fcmXX
+ // faddp, fmaxnmp, fmaxp, fminnmp, fminp, addp (vector)
switch (ins)
{
case INS_fmin:
+ case INS_fminnm:
case INS_fmax:
+ case INS_fmaxnm:
case INS_fabd:
case INS_fadd:
case INS_fsub:
- case INS_faddp:
case INS_fmul:
case INS_fmulx:
result.insThroughput = PERFSCORE_THROUGHPUT_2X;
result.insLatency = PERFSCORE_LATENCY_4C;
break;
+ case INS_faddp:
+ case INS_fmaxnmp:
+ case INS_fmaxp:
+ case INS_fminnmp:
+ case INS_fminp:
+ case INS_addp:
+ if (id->idOpSize() == EA_16BYTE)
+ {
+ // Q-form
+ result.insThroughput = PERFSCORE_THROUGHPUT_1C;
+ result.insLatency = PERFSCORE_LATENCY_4C;
+ }
+ else
+ {
+ result.insThroughput = PERFSCORE_THROUGHPUT_2X;
+ result.insLatency = PERFSCORE_LATENCY_4C;
+ }
+ break;
+
case INS_facge:
case INS_facgt:
case INS_fcmeq:
@@ -12833,13 +12964,15 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins
result.insLatency = PERFSCORE_LATENCY_4C;
break;
- case IF_DV_3D: // fadd, fsub, fdiv, fmul, fmulx, fmla, fmls, fmin, fmax, fabd, faddp, fcmXX (scalar)
+ case IF_DV_3D: // fadd, fsub, fdiv, fmul, fmulx, fmla, fmls, fmin, fminnm, fmax, fmaxnm, fabd, fcmXX (scalar)
switch (ins)
{
case INS_fadd:
case INS_fsub:
case INS_fmin:
+ case INS_fminnm:
case INS_fmax:
+ case INS_fmaxnm:
case INS_fmul:
case INS_fmulx:
case INS_fnmul:
@@ -12948,7 +13081,7 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins
case IF_DV_3A: // (vector)
// add, sub, mul, mla, mls, cmeq, cmge, cmgt, cmhi, cmhs, ctst,
- // pmul, saba, uaba, sabd, uabd, umin, umax, smin, smax,
+ // pmul, saba, uaba, sabd, uabd, umin, uminp, umax, umaxp, smin, sminp, smax, smaxp
switch (ins)
{
case INS_add:
@@ -12958,10 +13091,14 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins
case INS_cmgt:
case INS_cmhi:
case INS_cmhs:
- case INS_umin:
- case INS_umax:
- case INS_smin:
case INS_smax:
+ case INS_smaxp:
+ case INS_smin:
+ case INS_sminp:
+ case INS_umax:
+ case INS_umaxp:
+ case INS_umin:
+ case INS_uminp:
case INS_uzp1:
case INS_uzp2:
case INS_zip1:
diff --git a/src/coreclr/src/jit/emitfmtsarm64.h b/src/coreclr/src/jit/emitfmtsarm64.h
index 78d8da7d30082e..42e4c5287b47b6 100644
--- a/src/coreclr/src/jit/emitfmtsarm64.h
+++ b/src/coreclr/src/jit/emitfmtsarm64.h
@@ -86,6 +86,7 @@ IF_DEF(EN2M, IS_NONE, NONE) // Instruction has 2 possible encoding types, type M
IF_DEF(EN2N, IS_NONE, NONE) // Instruction has 2 possible encoding types, type N
IF_DEF(EN2O, IS_NONE, NONE) // Instruction has 2 possible encoding types, type O
IF_DEF(EN2P, IS_NONE, NONE) // Instruction has 2 possible encoding types, type P
+IF_DEF(EN2Q, IS_NONE, NONE) // Instruction has 2 possible encoding types, type Q
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
@@ -181,8 +182,7 @@ IF_DEF(DV_1C, IS_NONE, NONE) // DV_1C .........X...... ......nnnnn..... V
IF_DEF(DV_2A, IS_NONE, NONE) // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvtXX - vector)
IF_DEF(DV_2B, IS_NONE, NONE) // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
-IF_DEF(DV_2C, IS_NONE, NONE) // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from
- // general)
+IF_DEF(DV_2C, IS_NONE, NONE) // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
IF_DEF(DV_2D, IS_NONE, NONE) // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
IF_DEF(DV_2E, IS_NONE, NONE) // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
IF_DEF(DV_2F, IS_NONE, NONE) // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
@@ -195,7 +195,10 @@ IF_DEF(DV_2L, IS_NONE, NONE) // DV_2L ........XX...... ......nnnnnddddd V
IF_DEF(DV_2M, IS_NONE, NONE) // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
IF_DEF(DV_2N, IS_NONE, NONE) // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
IF_DEF(DV_2O, IS_NONE, NONE) // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
-IF_DEF(DV_2P, IS_NONE, NONE) // DV_2P .,.............. ......nnnnnddddd Vd Vn (Vd used as both source and destination)
+IF_DEF(DV_2P, IS_NONE, NONE) // DV_2P ................ ......nnnnnddddd Vd Vn (Vd used as both source and destination)
+IF_DEF(DV_2Q, IS_NONE, NONE) // DV_2Q .........X...... ......nnnnnddddd Sd Vn (faddp, fmaxnmp, fmaxp, fminnmp, fminp - scalar)
+IF_DEF(DV_2R, IS_NONE, NONE) // DV_2R .Q.......X...... ......nnnnnddddd Sd Vn (fmaxnmv, fmaxv, fminnmv, fminv)
+IF_DEF(DV_2S, IS_NONE, NONE) // DV_2S ........XX...... ......nnnnnddddd Sd Vn (addp - scalar)
IF_DEF(DV_3A, IS_NONE, NONE) // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
IF_DEF(DV_3AI, IS_NONE, NONE) // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
diff --git a/src/coreclr/src/jit/emitinl.h b/src/coreclr/src/jit/emitinl.h
index 6647c61bbdcf37..82ea2e4f4f8f1d 100644
--- a/src/coreclr/src/jit/emitinl.h
+++ b/src/coreclr/src/jit/emitinl.h
@@ -13,7 +13,7 @@ inline bool emitter::instrIs3opImul(instruction ins)
{
#ifdef TARGET_X86
return ((ins >= INS_imul_AX) && (ins <= INS_imul_DI));
-#else // _TARGET_AMD64
+#else // TARGET_AMD64
return ((ins >= INS_imul_AX) && (ins <= INS_imul_15));
#endif
}
@@ -23,7 +23,7 @@ inline bool emitter::instrIsExtendedReg3opImul(instruction ins)
{
#ifdef TARGET_X86
return false;
-#else // _TARGET_AMD64
+#else // TARGET_AMD64
return ((ins >= INS_imul_08) && (ins <= INS_imul_15));
#endif
}
diff --git a/src/coreclr/src/jit/emitxarch.cpp b/src/coreclr/src/jit/emitxarch.cpp
index ca5b1623275388..22b800ecee4fae 100644
--- a/src/coreclr/src/jit/emitxarch.cpp
+++ b/src/coreclr/src/jit/emitxarch.cpp
@@ -456,7 +456,7 @@ bool TakesRexWPrefix(instruction ins, emitAttr attr)
{
return false;
}
-#else //!_TARGET_AMD64 = TARGET_X86
+#else //! TARGET_AMD64 = TARGET_X86
return false;
#endif //! TARGET_AMD64
}
@@ -7952,7 +7952,7 @@ void emitter::emitDispInsHex(instrDesc* id, BYTE* code, size_t sz)
#ifdef TARGET_AMD64
// how many bytes per instruction we format for
const size_t digits = 10;
-#else // _TARGET_X86
+#else // TARGET_X86
const size_t digits = 6;
#endif
printf(" ");
@@ -14283,7 +14283,7 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins
result.insLatency = PERFSCORE_LATENCY_1C;
}
break;
-#endif // _TARGET_X86
+#endif // TARGET_X86
#ifdef TARGET_AMD64
case INS_movsq:
diff --git a/src/coreclr/src/jit/flowgraph.cpp b/src/coreclr/src/jit/flowgraph.cpp
index 9528f47361532a..6cbab31aceef16 100644
--- a/src/coreclr/src/jit/flowgraph.cpp
+++ b/src/coreclr/src/jit/flowgraph.cpp
@@ -22617,8 +22617,10 @@ Compiler::fgWalkResult Compiler::fgLateDevirtualization(GenTree** pTree, fgWalkD
JITDUMP(" ... found foldable jtrue at [%06u] in BB%02u\n", dspTreeID(tree), block->bbNum);
noway_assert((block->bbNext->countOfInEdges() > 0) && (block->bbJumpDest->countOfInEdges() > 0));
- // Had hoped to assert here that we are not losing any
- // side effects, but can't find a way to express it properly.
+ // We have a constant operand, and should have the all clear to optimize.
+ // Update side effects on the tree, assert there aren't any, and bash to nop.
+ comp->gtUpdateNodeSideEffects(tree);
+ assert((tree->gtFlags & GTF_SIDE_EFFECT) == 0);
tree->gtBashToNOP();
BasicBlock* bTaken = nullptr;
@@ -23579,10 +23581,15 @@ Statement* Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo)
CORINFO_METHOD_INFO* InlineeMethodInfo = InlineeCompiler->info.compMethodInfo;
- unsigned lclCnt = InlineeMethodInfo->locals.numArgs;
+ unsigned lclCnt = InlineeMethodInfo->locals.numArgs;
+ bool bbInALoop = (block->bbFlags & BBF_BACKWARD_JUMP) != 0;
+ bool bbIsReturn = block->bbJumpKind == BBJ_RETURN;
- // Does callee contain any zero-init local?
- if ((lclCnt != 0) && (InlineeMethodInfo->options & CORINFO_OPT_INIT_LOCALS) != 0)
+ // If the callee contains zero-init locals, we need to explicitly initialize them if we are
+ // in a loop or if the caller doesn't have compInitMem set. Otherwise we can rely on the
+ // normal logic in the caller to insert zero-init in the prolog if necessary.
+ if ((lclCnt != 0) && ((InlineeMethodInfo->options & CORINFO_OPT_INIT_LOCALS) != 0) &&
+ ((bbInALoop && !bbIsReturn) || !info.compInitMem))
{
#ifdef DEBUG
@@ -23596,9 +23603,20 @@ Statement* Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo)
{
unsigned tmpNum = inlineInfo->lclTmpNum[lclNum];
- // Is the local used at all?
+ // If the local is used check whether we need to insert explicit zero initialization.
if (tmpNum != BAD_VAR_NUM)
{
+ if (!fgVarNeedsExplicitZeroInit(lvaGetDesc(tmpNum), bbInALoop, bbIsReturn))
+ {
+#ifdef DEBUG
+ if (verbose)
+ {
+ printf("\nSkipping zero initialization of V%02u\n", tmpNum);
+ }
+#endif // DEBUG
+ continue;
+ }
+
var_types lclTyp = (var_types)lvaTable[tmpNum].lvType;
noway_assert(lclTyp == lclVarInfo[lclNum + inlineInfo->argCnt].lclTypeInfo);
@@ -23613,18 +23631,14 @@ Statement* Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo)
{
CORINFO_CLASS_HANDLE structType =
lclVarInfo[lclNum + inlineInfo->argCnt].lclVerTypeInfo.GetClassHandle();
-
- if (fgStructTempNeedsExplicitZeroInit(lvaTable + tmpNum, block))
- {
- tree = gtNewBlkOpNode(gtNewLclvNode(tmpNum, lclTyp), // Dest
- gtNewIconNode(0), // Value
- false, // isVolatile
- false); // not copyBlock
-
- newStmt = gtNewStmt(tree, callILOffset);
- fgInsertStmtAfter(block, afterStmt, newStmt);
- afterStmt = newStmt;
- }
+ tree = gtNewBlkOpNode(gtNewLclvNode(tmpNum, lclTyp), // Dest
+ gtNewIconNode(0), // Value
+ false, // isVolatile
+ false); // not copyBlock
+
+ newStmt = gtNewStmt(tree, callILOffset);
+ fgInsertStmtAfter(block, afterStmt, newStmt);
+ afterStmt = newStmt;
}
#ifdef DEBUG
diff --git a/src/coreclr/src/jit/gentree.cpp b/src/coreclr/src/jit/gentree.cpp
index 5e0eb6aef1dcc4..a9aac9d6d4c22e 100644
--- a/src/coreclr/src/jit/gentree.cpp
+++ b/src/coreclr/src/jit/gentree.cpp
@@ -3035,7 +3035,7 @@ bool Compiler::gtMarkAddrMode(GenTree* addr, int* pCostEx, int* pCostSz, var_typ
}
}
#else
-#error "Unknown _TARGET_"
+#error "Unknown TARGET"
#endif
assert(addr->gtOper == GT_ADD);
@@ -3333,7 +3333,7 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree)
case GT_CNS_LNG:
case GT_CNS_STR:
case GT_CNS_INT:
-#error "Unknown _TARGET_"
+#error "Unknown TARGET"
#endif
COMMON_CNS:
@@ -3532,7 +3532,7 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree)
costSz = 6;
}
#else
-#error "Unknown _TARGET_"
+#error "Unknown TARGET"
#endif
/* Overflow casts are a lot more expensive */
@@ -5670,11 +5670,11 @@ GenTree* Compiler::gtNewOperNode(genTreeOps oper, var_types type, GenTree* op1,
return node;
}
-GenTree* Compiler::gtNewQmarkNode(var_types type, GenTree* cond, GenTree* colon)
+GenTreeQmark* Compiler::gtNewQmarkNode(var_types type, GenTree* cond, GenTree* colon)
{
compQmarkUsed = true;
cond->gtFlags |= GTF_RELOP_QMARK;
- GenTree* result = new (this, GT_QMARK) GenTreeQmark(type, cond, colon, this);
+ GenTreeQmark* result = new (this, GT_QMARK) GenTreeQmark(type, cond, colon, this);
#ifdef DEBUG
if (compQmarkRationalized)
{
@@ -14849,7 +14849,7 @@ GenTree* Compiler::gtNewTempAssign(
}
#ifdef DEBUG
- /* Make sure the actual types match */
+ // Make sure the actual types match.
if (genActualType(valTyp) != genActualType(dstTyp))
{
// Plus some other exceptions that are apparently legal:
@@ -14869,6 +14869,12 @@ GenTree* Compiler::gtNewTempAssign(
{
ok = true;
}
+ else if (!varTypeIsGC(dstTyp) && (genTypeSize(valTyp) == genTypeSize(dstTyp)))
+ {
+ // We can have assignments that require a change of register file, e.g. for arguments
+ // and call returns. Lowering and Codegen will handle these.
+ ok = true;
+ }
if (!ok)
{
@@ -14898,7 +14904,7 @@ GenTree* Compiler::gtNewTempAssign(
// internal trees use SIMD types that are not used by the input IL. In this case, we allow
// a null type handle and derive the necessary information about the type from its varType.
CORINFO_CLASS_HANDLE structHnd = gtGetStructHandleIfPresent(val);
- if (varTypeIsStruct(valTyp) && ((structHnd != NO_CLASS_HANDLE) || (varTypeIsSIMD(valTyp))))
+ if (varTypeIsStruct(varDsc) && ((structHnd != NO_CLASS_HANDLE) || (varTypeIsSIMD(valTyp))))
{
// The struct value may be be a child of a GT_COMMA.
GenTree* valx = val->gtEffectiveVal(/*commaOnly*/ true);
@@ -14917,6 +14923,11 @@ GenTree* Compiler::gtNewTempAssign(
}
else
{
+ // We may have a scalar type variable assigned a struct value, e.g. a 'genReturnLocal'
+ // when the ABI calls for returning a struct as a primitive type.
+ // TODO-1stClassStructs: When we stop "lying" about the types for ABI purposes, the
+ // 'genReturnLocal' should be the original struct type.
+ assert(!varTypeIsStruct(valTyp) || typGetObjLayout(structHnd)->GetSize() == genTypeSize(varDsc));
asg = gtNewAssignNode(dest, val);
}
@@ -16759,7 +16770,7 @@ GenTree* Compiler::gtGetSIMDZero(var_types simdType, var_types baseType, CORINFO
}
break;
-#if defined(_TARGET_XARCH4_) && defined(FEATURE_HW_INTRINSICS)
+#if defined(TARGET_XARCH) && defined(FEATURE_HW_INTRINSICS)
case TYP_SIMD32:
switch (baseType)
{
@@ -16858,6 +16869,9 @@ CORINFO_CLASS_HANDLE Compiler::gtGetStructHandleIfPresent(GenTree* tree)
case GT_OBJ:
structHnd = tree->AsObj()->GetLayout()->GetClassHandle();
break;
+ case GT_BLK:
+ structHnd = tree->AsBlk()->GetLayout()->GetClassHandle();
+ break;
case GT_CALL:
structHnd = tree->AsCall()->gtRetClsHnd;
break;
@@ -16933,6 +16947,10 @@ CORINFO_CLASS_HANDLE Compiler::gtGetStructHandleIfPresent(GenTree* tree)
}
}
}
+ else if (addr->OperGet() == GT_LCL_VAR)
+ {
+ structHnd = gtGetStructHandleIfPresent(addr);
+ }
}
}
break;
@@ -18490,7 +18508,7 @@ void ReturnTypeDesc::InitializeStructReturnType(Compiler* comp, CORINFO_CLASS_HA
m_regType[i] = comp->getJitGCType(gcPtrs[i]);
}
-#else // _TARGET_XXX_
+#else // TARGET_XXX
// This target needs support here!
//
diff --git a/src/coreclr/src/jit/gentree.h b/src/coreclr/src/jit/gentree.h
index 8d5578190eea05..755b5ee4c5d0f1 100644
--- a/src/coreclr/src/jit/gentree.h
+++ b/src/coreclr/src/jit/gentree.h
@@ -3919,6 +3919,7 @@ struct GenTreeCall final : public GenTree
#define GTF_CALL_M_GUARDED 0x00200000 // GT_CALL -- this call was transformed by guarded devirtualization
#define GTF_CALL_M_ALLOC_SIDE_EFFECTS 0x00400000 // GT_CALL -- this is a call to an allocator with side effects
#define GTF_CALL_M_SUPPRESS_GC_TRANSITION 0x00800000 // GT_CALL -- suppress the GC transition (i.e. during a pinvoke) but a separate GC safe point is required.
+#define GTF_CALL_M_EXP_RUNTIME_LOOKUP 0x01000000 // GT_CALL -- this call needs to be tranformed into CFG for the dynamic dictionary expansion feature.
// clang-format on
@@ -4168,6 +4169,21 @@ struct GenTreeCall final : public GenTree
gtCallMoreFlags |= GTF_CALL_M_GUARDED;
}
+ void SetExpRuntimeLookup()
+ {
+ gtFlags |= GTF_CALL_M_EXP_RUNTIME_LOOKUP;
+ }
+
+ void ClearExpRuntimeLookup()
+ {
+ gtFlags &= ~GTF_CALL_M_EXP_RUNTIME_LOOKUP;
+ }
+
+ bool IsExpRuntimeLookup() const
+ {
+ return (gtFlags & GTF_CALL_M_EXP_RUNTIME_LOOKUP) != 0;
+ }
+
unsigned gtCallMoreFlags; // in addition to gtFlags
unsigned char gtCallType : 3; // value from the gtCallTypes enumeration
diff --git a/src/coreclr/src/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/src/jit/hwintrinsiccodegenarm64.cpp
index f3e6e8e5bb3010..6908d975ce075a 100644
--- a/src/coreclr/src/jit/hwintrinsiccodegenarm64.cpp
+++ b/src/coreclr/src/jit/hwintrinsiccodegenarm64.cpp
@@ -293,6 +293,14 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
GetEmitter()->emitIns_R_R_R(ins, emitSize, targetReg, op2Reg, op1Reg, opt);
break;
+ case NI_AdvSimd_FusedMultiplyAddScalar:
+ case NI_AdvSimd_FusedMultiplyAddNegatedScalar:
+ case NI_AdvSimd_FusedMultiplySubtractNegatedScalar:
+ case NI_AdvSimd_FusedMultiplySubtractScalar:
+ assert(opt == INS_OPTS_NONE);
+ GetEmitter()->emitIns_R_R_R_R(ins, emitSize, targetReg, op2Reg, op3Reg, op1Reg);
+ break;
+
default:
unreached();
}
diff --git a/src/coreclr/src/jit/hwintrinsiclistarm64.h b/src/coreclr/src/jit/hwintrinsiclistarm64.h
index d619ccbd4cb6e7..b44740d6cf1759 100644
--- a/src/coreclr/src/jit/hwintrinsiclistarm64.h
+++ b/src/coreclr/src/jit/hwintrinsiclistarm64.h
@@ -67,6 +67,12 @@ HARDWARE_INTRINSIC(AdvSimd, CompareLessThan, -
HARDWARE_INTRINSIC(AdvSimd, CompareLessThanOrEqual, -1, -1, 2, {INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_invalid, INS_invalid, INS_fcmge, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize|HW_Flag_SpecialCodeGen)
HARDWARE_INTRINSIC(AdvSimd, CompareTest, -1, -1, 2, {INS_cmtst, INS_cmtst, INS_cmtst, INS_cmtst, INS_cmtst, INS_cmtst, INS_invalid, INS_invalid, INS_cmtst, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_Commutative|HW_Flag_UnfixedSIMDSize)
HARDWARE_INTRINSIC(AdvSimd, DivideScalar, -1, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fdiv, INS_fdiv}, HW_Category_SIMDScalar, HW_Flag_NoContainment)
+HARDWARE_INTRINSIC(AdvSimd, FusedMultiplyAdd, -1, -1, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmla, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize)
+HARDWARE_INTRINSIC(AdvSimd, FusedMultiplyAddScalar, -1, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmadd, INS_fmadd}, HW_Category_SIMDScalar, HW_Flag_NoContainment|HW_Flag_SpecialCodeGen)
+HARDWARE_INTRINSIC(AdvSimd, FusedMultiplyAddNegatedScalar, -1, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fnmadd, INS_fnmadd}, HW_Category_SIMDScalar, HW_Flag_NoContainment|HW_Flag_SpecialCodeGen)
+HARDWARE_INTRINSIC(AdvSimd, FusedMultiplySubtract, -1, -1, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmls, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize)
+HARDWARE_INTRINSIC(AdvSimd, FusedMultiplySubtractScalar, -1, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmsub, INS_fmsub}, HW_Category_SIMDScalar, HW_Flag_NoContainment|HW_Flag_SpecialCodeGen)
+HARDWARE_INTRINSIC(AdvSimd, FusedMultiplySubtractNegatedScalar, -1, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fnmsub, INS_fnmsub}, HW_Category_SIMDScalar, HW_Flag_NoContainment|HW_Flag_SpecialCodeGen)
HARDWARE_INTRINSIC(AdvSimd, LeadingSignCount, -1, -1, 1, {INS_cls, INS_invalid, INS_cls, INS_invalid, INS_cls, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize)
HARDWARE_INTRINSIC(AdvSimd, LeadingZeroCount, -1, -1, 1, {INS_clz, INS_clz, INS_clz, INS_clz, INS_clz, INS_clz, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize)
HARDWARE_INTRINSIC(AdvSimd, LoadVector64, -1, 8, 1, {INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics)
@@ -75,6 +81,8 @@ HARDWARE_INTRINSIC(AdvSimd, Max, -
HARDWARE_INTRINSIC(AdvSimd, Min, -1, -1, 2, {INS_smin, INS_umin, INS_smin, INS_umin, INS_smin, INS_umin, INS_invalid, INS_invalid, INS_fmin, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize|HW_Flag_Commutative)
HARDWARE_INTRINSIC(AdvSimd, Multiply, -1, -1, 2, {INS_mul, INS_mul, INS_mul, INS_mul, INS_mul, INS_mul, INS_invalid, INS_invalid, INS_fmul, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize|HW_Flag_Commutative)
HARDWARE_INTRINSIC(AdvSimd, MultiplyScalar, -1, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmul, INS_fmul}, HW_Category_SIMDScalar, HW_Flag_NoContainment|HW_Flag_Commutative)
+HARDWARE_INTRINSIC(AdvSimd, MultiplyAdd, -1, -1, 3, {INS_mla, INS_mla, INS_mla, INS_mla, INS_mla, INS_mla, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize)
+HARDWARE_INTRINSIC(AdvSimd, MultiplySubtract, -1, -1, 3, {INS_mls, INS_mls, INS_mls, INS_mls, INS_mls, INS_mls, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize)
HARDWARE_INTRINSIC(AdvSimd, Negate, -1, -1, 1, {INS_neg, INS_invalid, INS_neg, INS_invalid, INS_neg, INS_invalid, INS_invalid, INS_invalid, INS_fneg, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize)
HARDWARE_INTRINSIC(AdvSimd, NegateScalar, -1, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fneg, INS_fneg}, HW_Category_SIMDScalar, HW_Flag_NoContainment)
HARDWARE_INTRINSIC(AdvSimd, Not, -1, -1, 1, {INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize)
@@ -118,6 +126,8 @@ HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareLessThanOrEqualScalar, -
HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareTest, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmtst, INS_cmtst, INS_invalid, INS_cmtst}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_Commutative)
HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareTestScalar, -1, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmtst, INS_cmtst, INS_invalid, INS_cmtst}, HW_Category_SIMDScalar, HW_Flag_NoContainment|HW_Flag_Commutative)
HARDWARE_INTRINSIC(AdvSimd_Arm64, Divide, -1, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fdiv, INS_fdiv}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_UnfixedSIMDSize)
+HARDWARE_INTRINSIC(AdvSimd_Arm64, FusedMultiplyAdd, -1, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmla}, HW_Category_SimpleSIMD, HW_Flag_NoContainment)
+HARDWARE_INTRINSIC(AdvSimd_Arm64, FusedMultiplySubtract, -1, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmls}, HW_Category_SimpleSIMD, HW_Flag_NoContainment)
HARDWARE_INTRINSIC(AdvSimd_Arm64, Max, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmax}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_Commutative)
HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxScalar, -1, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmax, INS_fmax}, HW_Category_SIMDScalar, HW_Flag_NoContainment|HW_Flag_Commutative)
HARDWARE_INTRINSIC(AdvSimd_Arm64, Min, -1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmin}, HW_Category_SimpleSIMD, HW_Flag_NoContainment|HW_Flag_Commutative)
diff --git a/src/coreclr/src/jit/importer.cpp b/src/coreclr/src/jit/importer.cpp
index 8875a291abaf1d..c38d0cd85318d1 100644
--- a/src/coreclr/src/jit/importer.cpp
+++ b/src/coreclr/src/jit/importer.cpp
@@ -1214,7 +1214,9 @@ GenTree* Compiler::impAssignStructPtr(GenTree* destAddr,
// If it is a multi-reg struct return, don't change the oper to GT_LCL_FLD.
// That is, the IR will be of the form lclVar = call for multi-reg return
//
- GenTreeLclVar* lcl = destAddr->AsOp()->gtOp1->AsLclVar();
+ GenTreeLclVar* lcl = destAddr->AsOp()->gtOp1->AsLclVar();
+ unsigned lclNum = lcl->GetLclNum();
+ LclVarDsc* varDsc = lvaGetDesc(lclNum);
if (src->AsCall()->HasMultiRegRetVal())
{
// Mark the struct LclVar as used in a MultiReg return context
@@ -1222,13 +1224,13 @@ GenTree* Compiler::impAssignStructPtr(GenTree* destAddr,
// TODO-1stClassStructs: Eliminate this pessimization when we can more generally
// handle multireg returns.
lcl->gtFlags |= GTF_DONT_CSE;
- lvaTable[lcl->AsLclVarCommon()->GetLclNum()].lvIsMultiRegRet = true;
+ varDsc->lvIsMultiRegRet = true;
}
else if (lcl->gtType != src->gtType)
{
// We change this to a GT_LCL_FLD (from a GT_ADDR of a GT_LCL_VAR)
lcl->ChangeOper(GT_LCL_FLD);
- fgLclFldAssign(lcl->AsLclVarCommon()->GetLclNum());
+ fgLclFldAssign(lclNum);
lcl->gtType = src->gtType;
asgType = src->gtType;
}
@@ -1238,7 +1240,7 @@ GenTree* Compiler::impAssignStructPtr(GenTree* destAddr,
#if defined(TARGET_ARM)
// TODO-Cleanup: This should have been taken care of in the above HasMultiRegRetVal() case,
// but that method has not been updadted to include ARM.
- impMarkLclDstNotPromotable(lcl->AsLclVarCommon()->GetLclNum(), src, structHnd);
+ impMarkLclDstNotPromotable(lclNum, src, structHnd);
lcl->gtFlags |= GTF_DONT_CSE;
#elif defined(UNIX_AMD64_ABI)
// Not allowed for FEATURE_CORCLR which is the only SKU available for System V OSs.
@@ -1250,7 +1252,7 @@ GenTree* Compiler::impAssignStructPtr(GenTree* destAddr,
// TODO-Cleanup: Why is this needed here? This seems that it will set this even for
// non-multireg returns.
lcl->gtFlags |= GTF_DONT_CSE;
- lvaTable[lcl->AsLclVarCommon()->GetLclNum()].lvIsMultiRegRet = true;
+ varDsc->lvIsMultiRegRet = true;
#endif
}
else // we don't have a GT_ADDR of a GT_LCL_VAR
@@ -2059,7 +2061,8 @@ GenTree* Compiler::impRuntimeLookupToTree(CORINFO_RESOLVED_TOKEN* pResolvedToken
nullptr DEBUGARG("impRuntimeLookup slot"));
}
- GenTree* indOffTree = nullptr;
+ GenTree* indOffTree = nullptr;
+ GenTree* lastIndOfTree = nullptr;
// Applied repeated indirections
for (WORD i = 0; i < pRuntimeLookup->indirections; i++)
@@ -2084,6 +2087,15 @@ GenTree* Compiler::impRuntimeLookupToTree(CORINFO_RESOLVED_TOKEN* pResolvedToken
if (pRuntimeLookup->offsets[i] != 0)
{
+// The last indirection could be subject to a size check (dynamic dictionary expansion feature)
+#if 0 // Uncomment that block when you add sizeOffset field to pRuntimeLookup.
+ if (i == pRuntimeLookup->indirections - 1 && pRuntimeLookup->sizeOffset != 0xFFFF)
+ {
+ lastIndOfTree = impCloneExpr(slotPtrTree, &slotPtrTree, NO_CLASS_HANDLE, (unsigned)CHECK_SPILL_ALL,
+ nullptr DEBUGARG("impRuntimeLookup indirectOffset"));
+ }
+#endif // 0
+
slotPtrTree =
gtNewOperNode(GT_ADD, TYP_I_IMPL, slotPtrTree, gtNewIconNode(pRuntimeLookup->offsets[i], TYP_I_IMPL));
}
@@ -2138,38 +2150,56 @@ GenTree* Compiler::impRuntimeLookupToTree(CORINFO_RESOLVED_TOKEN* pResolvedToken
impSpillSideEffects(true, CHECK_SPILL_ALL DEBUGARG("bubbling QMark1"));
// Extract the handle
- GenTree* handle = gtNewOperNode(GT_IND, TYP_I_IMPL, slotPtrTree);
- handle->gtFlags |= GTF_IND_NONFAULTING;
-
- GenTree* handleCopy = impCloneExpr(handle, &handle, NO_CLASS_HANDLE, (unsigned)CHECK_SPILL_ALL,
- nullptr DEBUGARG("impRuntimeLookup typehandle"));
+ GenTree* handleForNullCheck = gtNewOperNode(GT_IND, TYP_I_IMPL, slotPtrTree);
+ handleForNullCheck->gtFlags |= GTF_IND_NONFAULTING;
// Call to helper
GenTree* argNode = gtNewIconEmbHndNode(pRuntimeLookup->signature, nullptr, GTF_ICON_TOKEN_HDL, compileTimeHandle);
GenTreeCall::Use* helperArgs = gtNewCallArgs(ctxTree, argNode);
- GenTree* helperCall = gtNewHelperCallNode(pRuntimeLookup->helper, TYP_I_IMPL, helperArgs);
+ GenTreeCall* helperCall = gtNewHelperCallNode(pRuntimeLookup->helper, TYP_I_IMPL, helperArgs);
// Check for null and possibly call helper
- GenTree* relop = gtNewOperNode(GT_NE, TYP_INT, handle, gtNewIconNode(0, TYP_I_IMPL));
+ GenTree* nullCheck = gtNewOperNode(GT_NE, TYP_INT, handleForNullCheck, gtNewIconNode(0, TYP_I_IMPL));
+ GenTree* handleForResult = gtCloneExpr(handleForNullCheck);
- GenTree* colon = new (this, GT_COLON) GenTreeColon(TYP_I_IMPL,
- gtNewNothingNode(), // do nothing if nonnull
- helperCall);
+ GenTree* result = nullptr;
- GenTree* qmark = gtNewQmarkNode(TYP_I_IMPL, relop, colon);
-
- unsigned tmp;
- if (handleCopy->IsLocal())
+#if 0 // Uncomment that block when you add sizeOffset field to pRuntimeLookup.
+ if (pRuntimeLookup->sizeOffset != 0xFFFF) // dynamic dictionary expansion feature
{
- tmp = handleCopy->AsLclVarCommon()->GetLclNum();
+ assert((lastIndOfTree != nullptr) && (pRuntimeLookup->indirections > 0));
+
+ // sizeValue = dictionary[pRuntimeLookup->sizeOffset]
+ GenTreeIntCon* sizeOffset = gtNewIconNode(pRuntimeLookup->sizeOffset, TYP_I_IMPL);
+ GenTree* sizeValueOffset = gtNewOperNode(GT_ADD, TYP_I_IMPL, lastIndOfTree, sizeOffset);
+ GenTree* sizeValue = gtNewOperNode(GT_IND, TYP_I_IMPL, sizeValueOffset);
+
+ // sizeCheck fails if sizeValue < pRuntimeLookup->offsets[i]
+ GenTree* offsetValue = gtNewIconNode(pRuntimeLookup->offsets[pRuntimeLookup->indirections - 1], TYP_I_IMPL);
+ GenTree* sizeCheck = gtNewOperNode(GT_LE, TYP_INT, sizeValue, offsetValue);
+
+ // revert null check condition.
+ nullCheck->ChangeOperUnchecked(GT_EQ);
+
+ // ((sizeCheck fails || nullCheck fails))) ? (helperCall : handle).
+ // Add checks and the handle as call arguments, indirect call transformer will handle this.
+ helperCall->gtCallArgs = gtPrependNewCallArg(handleForResult, helperCall->gtCallArgs);
+ helperCall->gtCallArgs = gtPrependNewCallArg(sizeCheck, helperCall->gtCallArgs);
+ helperCall->gtCallArgs = gtPrependNewCallArg(nullCheck, helperCall->gtCallArgs);
+ result = helperCall;
+ addExpRuntimeLookupCandidate(helperCall);
}
else
+#endif // 0
{
- tmp = lvaGrabTemp(true DEBUGARG("spilling QMark1"));
+ GenTreeColon* colonNullCheck = new (this, GT_COLON) GenTreeColon(TYP_I_IMPL, handleForResult, helperCall);
+ result = gtNewQmarkNode(TYP_I_IMPL, nullCheck, colonNullCheck);
}
- impAssignTempGen(tmp, qmark, (unsigned)CHECK_SPILL_NONE);
+ unsigned tmp = lvaGrabTemp(true DEBUGARG("spilling Runtime Lookup tree"));
+
+ impAssignTempGen(tmp, result, (unsigned)CHECK_SPILL_NONE);
return gtNewLclvNode(tmp, TYP_I_IMPL);
}
@@ -2558,7 +2588,7 @@ BasicBlock* Compiler::impPushCatchArgOnStack(BasicBlock* hndBlk, CORINFO_CLASS_H
#if defined(JIT32_GCENCODER)
const bool forceInsertNewBlock = isSingleBlockFilter || compStressCompile(STRESS_CATCH_ARG, 5);
#else
- const bool forceInsertNewBlock = compStressCompile(STRESS_CATCH_ARG, 5);
+ const bool forceInsertNewBlock = compStressCompile(STRESS_CATCH_ARG, 5);
#endif // defined(JIT32_GCENCODER)
/* Spill GT_CATCH_ARG to a temp if there are jumps to the beginning of the handler */
@@ -3632,6 +3662,27 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
op1 = impPopStack().val;
if (opts.OptimizationEnabled())
{
+ if (op1->OperIs(GT_CNS_STR))
+ {
+ // Optimize `ldstr + String::get_Length()` to CNS_INT
+ // e.g. "Hello".Length => 5
+ int length = -1;
+ LPCWSTR str = info.compCompHnd->getStringLiteral(op1->AsStrCon()->gtScpHnd,
+ op1->AsStrCon()->gtSconCPX, &length);
+ if (length >= 0)
+ {
+ retNode = gtNewIconNode(length);
+ if (str != nullptr) // can be NULL for dynamic context
+ {
+ JITDUMP("Optimizing '\"%ws\".Length' to just '%d'\n", str, length);
+ }
+ else
+ {
+ JITDUMP("Optimizing 'CNS_STR.Length' to just '%d'\n", length);
+ }
+ break;
+ }
+ }
GenTreeArrLen* arrLen = gtNewArrLen(TYP_INT, op1, OFFSETOF__CORINFO_String__stringLen, compCurBB);
op1 = arrLen;
}
@@ -5728,7 +5779,7 @@ void Compiler::verVerifyCond(const typeInfo& tiOp1, const typeInfo& tiOp2, unsig
{
#ifdef TARGET_64BIT
Verify(tiCompatibleWith(tiOp1, tiOp2, true), "Cond type mismatch");
-#else // _TARGET_64BIT
+#else // TARGET_64BIT
// [10/17/2013] Consider changing this: to put on my verification lawyer hat,
// this is non-conforming to the ECMA Spec: types don't have to be equivalent,
// but compatible, since we can coalesce native int with int32 (see section III.1.5).
@@ -13819,7 +13870,13 @@ void Compiler::impImportBlockCode(BasicBlock* block)
// and potentially exploitable.
lvaSetStruct(lclNum, resolvedToken.hClass, true /* unsafe value cls check */);
}
- if (compIsForInlining() || fgStructTempNeedsExplicitZeroInit(lvaTable + lclNum, block))
+
+ bool bbInALoop =
+ (compIsForInlining() && ((impInlineInfo->iciBlock->bbFlags & BBF_BACKWARD_JUMP) != 0)) ||
+ ((block->bbFlags & BBF_BACKWARD_JUMP) != 0);
+ bool bbIsReturn = (block->bbJumpKind == BBJ_RETURN) &&
+ (!compIsForInlining() || (impInlineInfo->iciBlock->bbJumpKind == BBJ_RETURN));
+ if (fgVarNeedsExplicitZeroInit(lvaGetDesc(lclNum), bbInALoop, bbIsReturn))
{
// Append a tree to zero-out the temp
newObjThisPtr = gtNewLclvNode(lclNum, lvaTable[lclNum].TypeGet());
@@ -14120,10 +14177,6 @@ void Compiler::impImportBlockCode(BasicBlock* block)
lclTyp = JITtype2varType(ciType);
-#ifdef _TARGET_AMD64
- noway_assert(varTypeIsIntegralOrI(lclTyp) || varTypeIsFloating(lclTyp) || lclTyp == TYP_STRUCT);
-#endif // _TARGET_AMD64
-
if (compIsForInlining())
{
switch (fieldInfo.fieldAccessor)
@@ -20847,6 +20900,12 @@ void Compiler::addGuardedDevirtualizationCandidate(GenTreeCall* call,
call->gtGuardedDevirtualizationCandidateInfo = pInfo;
}
+void Compiler::addExpRuntimeLookupCandidate(GenTreeCall* call)
+{
+ setMethodHasExpRuntimeLookup();
+ call->SetExpRuntimeLookup();
+}
+
//------------------------------------------------------------------------
// impIsClassExact: check if a class handle can only describe values
// of exactly one class.
diff --git a/src/coreclr/src/jit/indirectcalltransformer.cpp b/src/coreclr/src/jit/indirectcalltransformer.cpp
index 20f2abf0559ac3..caec347798031c 100644
--- a/src/coreclr/src/jit/indirectcalltransformer.cpp
+++ b/src/coreclr/src/jit/indirectcalltransformer.cpp
@@ -8,8 +8,8 @@
#endif
// The IndirectCallTransformer transforms indirect calls that involve fat function
-// pointers or guarded devirtualization candidates. These transformations introduce
-// control flow and so can't easily be done in the importer.
+// pointers, guarded devirtualization candidates, or runtime lookup with dynamic dictionary expansion.
+// These transformations introduce control flow and so can't easily be done in the importer.
//
// A fat function pointer is a pointer with the second least significant bit
// (aka FAT_POINTER_MASK) set. If the bit is set, the pointer (after clearing the bit)
@@ -103,19 +103,25 @@ class IndirectCallTransformer
for (Statement* stmt : block->Statements())
{
- if (ContainsFatCalli(stmt))
+ if (compiler->doesMethodHaveFatPointer() && ContainsFatCalli(stmt))
{
FatPointerCallTransformer transformer(compiler, block, stmt);
transformer.Run();
count++;
}
-
- if (ContainsGuardedDevirtualizationCandidate(stmt))
+ else if (compiler->doesMethodHaveGuardedDevirtualization() &&
+ ContainsGuardedDevirtualizationCandidate(stmt))
{
GuardedDevirtualizationTransformer transformer(compiler, block, stmt);
transformer.Run();
count++;
}
+ else if (compiler->doesMethodHaveExpRuntimeLookup() && ContainsExpRuntimeLookup(stmt))
+ {
+ ExpRuntimeLookupTransformer transformer(compiler, block, stmt);
+ transformer.Run();
+ count++;
+ }
}
return count;
@@ -154,6 +160,28 @@ class IndirectCallTransformer
return candidate->IsCall() && candidate->AsCall()->IsGuardedDevirtualizationCandidate();
}
+ //------------------------------------------------------------------------
+ // ContainsExpRuntimeLookup: check if this statement contains a dictionary
+ // with dynamic dictionary expansion that we want to transform in CFG.
+ //
+ // Return Value:
+ // true if contains, false otherwise.
+ //
+ bool ContainsExpRuntimeLookup(Statement* stmt)
+ {
+ GenTree* candidate = stmt->GetRootNode();
+ if (candidate->OperIs(GT_ASG))
+ {
+ candidate = candidate->gtGetOp2();
+ }
+ if (candidate->OperIs(GT_CALL))
+ {
+ GenTreeCall* call = candidate->AsCall();
+ return call->IsExpRuntimeLookup();
+ }
+ return false;
+ }
+
class Transformer
{
public:
@@ -243,7 +271,7 @@ class IndirectCallTransformer
//------------------------------------------------------------------------
// SetWeights: set weights for new blocks.
//
- void SetWeights()
+ virtual void SetWeights()
{
remainderBlock->inheritWeight(currBlock);
checkBlock->inheritWeight(currBlock);
@@ -254,7 +282,7 @@ class IndirectCallTransformer
//------------------------------------------------------------------------
// ChainFlow: link new blocks into correct cfg.
//
- void ChainFlow()
+ virtual void ChainFlow()
{
assert(!compiler->fgComputePredsDone);
checkBlock->bbJumpDest = elseBlock;
@@ -767,6 +795,178 @@ class IndirectCallTransformer
unsigned returnTemp;
};
+ // Runtime lookup with dynamic dictionary expansion transformer,
+ // it expects helper runtime lookup call with additional arguments that are:
+ // result handle, nullCheck tree, sizeCheck tree.
+ // before:
+ // current block
+ // {
+ // previous statements
+ // transforming statement
+ // {
+ // ASG lclVar, call with GTF_CALL_M_EXP_RUNTIME_LOOKUP flag set and additional arguments.
+ // }
+ // subsequent statements
+ // }
+ //
+ // after:
+ // current block
+ // {
+ // previous statements
+ // } BBJ_NONE check block
+ // check block
+ // {
+ // jump to else if the handle fails size check
+ // } BBJ_COND check block2, else block
+ // check block2
+ // {
+ // jump to else if the handle fails null check
+ // } BBJ_COND then block, else block
+ // then block
+ // {
+ // return handle
+ // } BBJ_ALWAYS remainder block
+ // else block
+ // {
+ // do a helper call
+ // } BBJ_NONE remainder block
+ // remainder block
+ // {
+ // subsequent statements
+ // }
+ //
+ class ExpRuntimeLookupTransformer final : public Transformer
+ {
+ public:
+ ExpRuntimeLookupTransformer(Compiler* compiler, BasicBlock* block, Statement* stmt)
+ : Transformer(compiler, block, stmt)
+ {
+ GenTreeOp* asg = stmt->GetRootNode()->AsOp();
+ resultLclNum = asg->gtOp1->AsLclVar()->GetLclNum();
+ origCall = GetCall(stmt);
+ checkBlock2 = nullptr;
+ }
+
+ protected:
+ virtual const char* Name() override
+ {
+ return "ExpRuntimeLookup";
+ }
+
+ //------------------------------------------------------------------------
+ // GetCall: find a call in a statement.
+ //
+ // Arguments:
+ // callStmt - the statement with the call inside.
+ //
+ // Return Value:
+ // call tree node pointer.
+ virtual GenTreeCall* GetCall(Statement* callStmt) override
+ {
+ GenTree* tree = callStmt->GetRootNode();
+ assert(tree->OperIs(GT_ASG));
+ GenTreeOp* asg = tree->AsOp();
+ GenTreeCall* call = tree->gtGetOp2()->AsCall();
+ return call;
+ }
+
+ //------------------------------------------------------------------------
+ // ClearFlag: clear runtime exp lookup flag from the original call.
+ //
+ virtual void ClearFlag() override
+ {
+ origCall->ClearExpRuntimeLookup();
+ }
+
+ // FixupRetExpr: no action needed.
+ virtual void FixupRetExpr() override
+ {
+ }
+
+ //------------------------------------------------------------------------
+ // CreateCheck: create check blocks, that checks dictionary size and does null test.
+ //
+ virtual void CreateCheck() override
+ {
+ GenTreeCall::UseIterator argsIter = origCall->Args().begin();
+ GenTree* nullCheck = argsIter.GetUse()->GetNode();
+ ++argsIter;
+ GenTree* sizeCheck = argsIter.GetUse()->GetNode();
+ ++argsIter;
+ origCall->gtCallArgs = argsIter.GetUse();
+ // The first argument is the handle now.
+ checkBlock = CreateAndInsertBasicBlock(BBJ_COND, currBlock);
+
+ assert(sizeCheck->OperIs(GT_LE));
+ GenTree* sizeJmpTree = compiler->gtNewOperNode(GT_JTRUE, TYP_VOID, sizeCheck);
+ Statement* sizeJmpStmt = compiler->fgNewStmtFromTree(sizeJmpTree, stmt->GetILOffsetX());
+ compiler->fgInsertStmtAtEnd(checkBlock, sizeJmpStmt);
+
+ checkBlock2 = CreateAndInsertBasicBlock(BBJ_COND, checkBlock);
+ assert(nullCheck->OperIs(GT_EQ));
+ GenTree* nullJmpTree = compiler->gtNewOperNode(GT_JTRUE, TYP_VOID, nullCheck);
+ Statement* nullJmpStmt = compiler->fgNewStmtFromTree(nullJmpTree, stmt->GetILOffsetX());
+ compiler->fgInsertStmtAtEnd(checkBlock2, nullJmpStmt);
+ }
+
+ //------------------------------------------------------------------------
+ // CreateThen: create then block, that is executed if the checks succeed.
+ // This simply returns the handle.
+ //
+ virtual void CreateThen() override
+ {
+ thenBlock = CreateAndInsertBasicBlock(BBJ_ALWAYS, checkBlock2);
+
+ GenTreeCall::UseIterator argsIter = origCall->Args().begin();
+ GenTree* resultHandle = argsIter.GetUse()->GetNode();
+ ++argsIter;
+ // The first argument is the real first argument for the call now.
+ origCall->gtCallArgs = argsIter.GetUse();
+
+ GenTree* asg = compiler->gtNewTempAssign(resultLclNum, resultHandle);
+ Statement* asgStmt = compiler->gtNewStmt(asg, stmt->GetILOffsetX());
+ compiler->fgInsertStmtAtEnd(thenBlock, asgStmt);
+ }
+
+ //------------------------------------------------------------------------
+ // CreateElse: create else block, that is executed if the checks fail.
+ //
+ virtual void CreateElse() override
+ {
+ elseBlock = CreateAndInsertBasicBlock(BBJ_NONE, thenBlock);
+ GenTree* asg = compiler->gtNewTempAssign(resultLclNum, origCall);
+ Statement* asgStmt = compiler->gtNewStmt(asg, stmt->GetILOffsetX());
+ compiler->fgInsertStmtAtEnd(elseBlock, asgStmt);
+ }
+
+ //------------------------------------------------------------------------
+ // SetWeights: set weights for new blocks.
+ //
+ virtual void SetWeights() override
+ {
+ remainderBlock->inheritWeight(currBlock);
+ checkBlock->inheritWeight(currBlock);
+ checkBlock2->inheritWeightPercentage(checkBlock, HIGH_PROBABILITY);
+ thenBlock->inheritWeightPercentage(currBlock, HIGH_PROBABILITY);
+ elseBlock->inheritWeightPercentage(currBlock, 100 - HIGH_PROBABILITY);
+ }
+
+ //------------------------------------------------------------------------
+ // ChainFlow: link new blocks into correct cfg.
+ //
+ virtual void ChainFlow() override
+ {
+ assert(!compiler->fgComputePredsDone);
+ checkBlock->bbJumpDest = elseBlock;
+ checkBlock2->bbJumpDest = elseBlock;
+ thenBlock->bbJumpDest = remainderBlock;
+ }
+
+ private:
+ BasicBlock* checkBlock2;
+ unsigned resultLclNum;
+ };
+
Compiler* compiler;
};
@@ -782,8 +982,10 @@ Compiler::fgWalkResult Compiler::fgDebugCheckForTransformableIndirectCalls(GenTr
GenTree* tree = *pTree;
if (tree->IsCall())
{
- assert(!tree->AsCall()->IsFatPointerCandidate());
- assert(!tree->AsCall()->IsGuardedDevirtualizationCandidate());
+ GenTreeCall* call = tree->AsCall();
+ assert(!call->IsFatPointerCandidate());
+ assert(!call->IsGuardedDevirtualizationCandidate());
+ assert(!call->IsExpRuntimeLookup());
}
return WALK_CONTINUE;
}
@@ -796,6 +998,7 @@ void Compiler::CheckNoTransformableIndirectCallsRemain()
{
assert(!doesMethodHaveFatPointer());
assert(!doesMethodHaveGuardedDevirtualization());
+ assert(!doesMethodHaveExpRuntimeLookup());
for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
{
@@ -817,7 +1020,7 @@ void Compiler::fgTransformIndirectCalls()
{
JITDUMP("\n*************** in fgTransformIndirectCalls(%s)\n", compIsForInlining() ? "inlinee" : "root");
- if (doesMethodHaveFatPointer() || doesMethodHaveGuardedDevirtualization())
+ if (doesMethodHaveFatPointer() || doesMethodHaveGuardedDevirtualization() || doesMethodHaveExpRuntimeLookup())
{
IndirectCallTransformer indirectCallTransformer(this);
int count = indirectCallTransformer.Run();
@@ -834,6 +1037,7 @@ void Compiler::fgTransformIndirectCalls()
clearMethodHasFatPointer();
clearMethodHasGuardedDevirtualization();
+ clearMethodHasExpRuntimeLookup();
}
else
{
diff --git a/src/coreclr/src/jit/instr.cpp b/src/coreclr/src/jit/instr.cpp
index 0b31b8a18586b6..7a0a6c63f37fd0 100644
--- a/src/coreclr/src/jit/instr.cpp
+++ b/src/coreclr/src/jit/instr.cpp
@@ -67,7 +67,7 @@ const char* CodeGen::genInsName(instruction ins)
#include "instrs.h"
#else
-#error "Unknown _TARGET_"
+#error "Unknown TARGET"
#endif
};
// clang-format on
@@ -905,7 +905,7 @@ void CodeGen::inst_RV_SH(
#else
NYI("inst_RV_SH - unknown target");
-#endif // _TARGET_*
+#endif // TARGET*
}
/*****************************************************************************
@@ -1817,6 +1817,7 @@ instruction CodeGenInterface::ins_Load(var_types srcType, bool aligned /*=false*
*/
instruction CodeGen::ins_Copy(var_types dstType)
{
+ assert(emitTypeActSz[dstType] != 0);
#if defined(TARGET_XARCH)
if (varTypeIsSIMD(dstType))
{
@@ -1850,12 +1851,62 @@ instruction CodeGen::ins_Copy(var_types dstType)
{
return INS_mov;
}
-#elif defined(TARGET_X86)
+#else // TARGET_*
+#error "Unknown TARGET_"
+#endif
+}
+
+//------------------------------------------------------------------------
+// ins_Copy: Get the machine dependent instruction for performing a reg-reg copy
+// from srcReg to a register of dstType.
+//
+// Arguments:
+// srcReg - source register
+// dstType - destination type
+//
+// Notes:
+// This assumes the size of the value in 'srcReg' is the same as the size of
+// 'dstType'.
+//
+instruction CodeGen::ins_Copy(regNumber srcReg, var_types dstType)
+{
+ bool dstIsFloatReg = isFloatRegType(dstType);
+ bool srcIsFloatReg = genIsValidFloatReg(srcReg);
+ if (srcIsFloatReg == dstIsFloatReg)
+ {
+ return ins_Copy(dstType);
+ }
+#if defined(TARGET_XARCH)
+ if (dstIsFloatReg)
+ {
+ return INS_mov_i2xmm;
+ }
+ else
+ {
+ return INS_mov_xmm2i;
+ }
+#elif defined(TARGET_ARM64)
+ if (dstIsFloatReg)
+ {
+ return INS_fmov;
+ }
+ else
+ {
+ return INS_mov;
+ }
+#elif defined(TARGET_ARM)
+ // No SIMD support yet
assert(!varTypeIsSIMD(dstType));
- assert(!varTypeIsFloating(dstType));
- return INS_mov;
-#else // _TARGET_*
-#error "Unknown _TARGET_"
+ if (dstIsFloatReg)
+ {
+ return (dstType == TYP_DOUBLE) ? INS_vmov_i2d : INS_vmov_i2f;
+ }
+ else
+ {
+ return (dstType == TYP_LONG) ? INS_vmov_d2i : INS_vmov_f2i;
+ }
+#else // TARGET*
+#error "Unknown TARGET"
#endif
}
@@ -2255,7 +2306,24 @@ instruction CodeGen::ins_FloatConv(var_types to, var_types from)
}
}
-#endif // #elif defined(TARGET_ARM)
+#elif defined(TARGET_ARM64)
+instruction CodeGen::ins_CopyIntToFloat(var_types srcType, var_types dstType)
+{
+ assert((dstType == TYP_FLOAT) || (dstType == TYP_DOUBLE));
+ assert((srcType == TYP_INT) || (srcType == TYP_UINT) || (srcType == TYP_LONG) || (srcType == TYP_ULONG));
+
+ return INS_mov;
+}
+
+instruction CodeGen::ins_CopyFloatToInt(var_types srcType, var_types dstType)
+{
+ assert((srcType == TYP_FLOAT) || (srcType == TYP_DOUBLE));
+ assert((dstType == TYP_INT) || (dstType == TYP_UINT) || (dstType == TYP_LONG) || (dstType == TYP_ULONG));
+
+ return INS_mov;
+}
+
+#endif // TARGET_ARM64
/*****************************************************************************
*
@@ -2316,7 +2384,7 @@ void CodeGen::instGen_MemoryBarrier()
#elif defined(TARGET_ARM64)
GetEmitter()->emitIns_BARR(INS_dmb, barrierType);
#else
-#error "Unknown _TARGET_"
+#error "Unknown TARGET"
#endif
}
@@ -2331,7 +2399,7 @@ void CodeGen::instGen_Set_Reg_To_Zero(emitAttr size, regNumber reg, insFlags fla
#elif defined(TARGET_ARMARCH)
GetEmitter()->emitIns_R_I(INS_mov, size, reg, 0 ARM_ARG(flags));
#else
-#error "Unknown _TARGET_"
+#error "Unknown TARGET"
#endif
regSet.verifyRegUsed(reg);
}
@@ -2348,7 +2416,7 @@ void CodeGen::instGen_Compare_Reg_To_Zero(emitAttr size, regNumber reg)
#elif defined(TARGET_ARMARCH)
GetEmitter()->emitIns_R_I(INS_cmp, size, reg, 0);
#else
-#error "Unknown _TARGET_"
+#error "Unknown TARGET"
#endif
}
@@ -2362,7 +2430,7 @@ void CodeGen::instGen_Compare_Reg_To_Reg(emitAttr size, regNumber reg1, regNumbe
#if defined(TARGET_XARCH) || defined(TARGET_ARMARCH)
GetEmitter()->emitIns_R_R(INS_cmp, size, reg1, reg2);
#else
-#error "Unknown _TARGET_"
+#error "Unknown TARGET"
#endif
}
@@ -2409,7 +2477,7 @@ void CodeGen::instGen_Compare_Reg_To_Imm(emitAttr size, regNumber reg, target_ss
assert(!"Invalid immediate for instGen_Compare_Reg_To_Imm");
}
#else
-#error "Unknown _TARGET_"
+#error "Unknown TARGET"
#endif
}
}
diff --git a/src/coreclr/src/jit/instrsarm64.h b/src/coreclr/src/jit/instrsarm64.h
index 6c8b196cba2b7f..5647c801e9b770 100644
--- a/src/coreclr/src/jit/instrsarm64.h
+++ b/src/coreclr/src/jit/instrsarm64.h
@@ -462,10 +462,18 @@ INST2(fmax, "fmax", 0, 0, IF_EN2G, 0x0E20F400, 0x1E204800)
// fmax Vd,Vn,Vm DV_3B 0Q0011100X1mmmmm 111101nnnnnddddd 0E20 F400 Vd,Vn,Vm (vector)
// fmax Vd,Vn,Vm DV_3D 000111100X1mmmmm 010010nnnnnddddd 1E20 4800 Vd,Vn,Vm (scalar)
+INST2(fmaxnm, "fmaxnm", 0, 0, IF_EN2G, 0x0E20C400, 0x1E206800)
+ // fmaxnm Vd,Vn,Vm DV_3B 0Q0011100X1mmmmm 110001nnnnnddddd 0E20 C400 Vd,Vn,Vm (vector)
+ // fmaxnm Vd,Vn,Vm DV_3D 000111100X1mmmmm 011010nnnnnddddd 1E20 6800 Vd,Vn,Vm (scalar)
+
INST2(fmin, "fmin", 0, 0, IF_EN2G, 0x0EA0F400, 0x1E205800)
// fmin Vd,Vn,Vm DV_3B 0Q0011101X1mmmmm 111101nnnnnddddd 0EA0 F400 Vd,Vn,Vm (vector)
// fmin Vd,Vn,Vm DV_3D 000111100X1mmmmm 010110nnnnnddddd 1E20 5800 Vd,Vn,Vm (scalar)
+INST2(fminnm, "fminnm", 0, 0, IF_EN2G, 0x0EA0C400, 0x1E207800)
+ // fminnm Vd,Vn,Vm DV_3B 0Q0011101X1mmmmm 110001nnnnnddddd 0EA0 C400 Vd,Vn,Vm (vector)
+ // fminnm Vd,Vn,Vm DV_3D 000111100X1mmmmm 011110nnnnnddddd 1E20 7800 Vd,Vn,Vm (scalar)
+
INST2(fabd, "fabd", 0, 0, IF_EN2G, 0x2EA0D400, 0x7EA0D400)
// fabd Vd,Vn,Vm DV_3B 0Q1011101X1mmmmm 110101nnnnnddddd 2EA0 D400 Vd,Vn,Vm (vector)
// fabd Vd,Vn,Vm DV_3D 011111101X1mmmmm 110101nnnnnddddd 7EA0 D400 Vd,Vn,Vm (scalar)
@@ -639,9 +647,29 @@ INST2(cmtst, "cmtst", 0, 0, IF_EN2O, 0x5EE08C00, 0x0E208C00)
// enum name FP LD/ST DV_2G DV_3B
INST2(faddp, "faddp", 0, 0, IF_EN2P, 0x7E30D800, 0x2E20D400)
- // faddp Vd,Vn DV_2G 011111100X110000 110110nnnnnddddd 7E30 D800 Vd,Vn (scalar)
+ // faddp Vd,Vn DV_2Q 011111100X110000 110110nnnnnddddd 7E30 D800 Vd,Vn (scalar)
// faddp Vd,Vn,Vm DV_3B 0Q1011100X1mmmmm 110101nnnnnddddd 2E20 D400 Vd,Vn,Vm (vector)
+INST2(fmaxnmp, "fmaxnmp",0, 0, IF_EN2P, 0x7E30C800, 0x2E20C400)
+ // fmaxnmp Vd,Vn DV_2Q 011111100X110000 110010nnnnnddddd 7E30 C800 Vd,Vn (scalar)
+ // fmaxnmp Vd,Vn,Vm DV_3B 0Q1011100X1mmmmm 110001nnnnnddddd 2E20 C400 Vd,Vn,Vm (vector)
+
+INST2(fmaxp, "fmaxp", 0, 0, IF_EN2P, 0x7E30F800, 0x2E20F400)
+ // fmaxp Vd,Vn DV_2Q 011111100X110000 111110nnnnnddddd 7E30 F800 Vd,Vn (scalar)
+ // fmaxp Vd,Vn,Vm DV_3B 0Q1011100X1mmmmm 111101nnnnnddddd 2E20 F400 Vd,Vn,Vm (vector)
+
+INST2(fminnmp, "fminnmp",0, 0, IF_EN2P, 0x7EB0C800, 0x2EA0C400)
+ // fminnmp Vd,Vn DV_2Q 011111101X110000 110010nnnnnddddd 7EB0 C800 Vd,Vn (scalar)
+ // fminnmp Vd,Vn,Vm DV_3B 0Q1011101X1mmmmm 110001nnnnnddddd 2EA0 C400 Vd,Vn,Vm (vector)
+
+INST2(fminp, "fminp", 0, 0, IF_EN2P, 0x7EB0F800, 0x2EA0F400)
+ // fminp Vd,Vn DV_2Q 011111101X110000 111110nnnnnddddd 7EB0 F800 Vd,Vn (scalar)
+ // fminp Vd,Vn,Vm DV_3B 0Q1011101X1mmmmm 111101nnnnnddddd 2EA0 F400 Vd,Vn,Vm (vector)
+
+INST2(addp, "addp", 0, 0, IF_EN2Q, 0x5E31B800, 0x0E20BC00)
+ // addp Vd,Vn DV_2S 01011110XX110001 101110nnnnnddddd 5E31 B800 Vd,Vn (scalar)
+ // addp Vd,Vn,Vm DV_3A 0Q001110XX1mmmmm 101111nnnnnddddd 0E20 BC00 Vd,Vn,Vm (vector)
+
INST1(ldar, "ldar", 0,LD, IF_LS_2A, 0x88DFFC00)
// ldar Rt,[Xn] LS_2A 1X00100011011111 111111nnnnnttttt 88DF FC00
@@ -1221,6 +1249,18 @@ INST1(umaxv, "umaxv", 0, 0, IF_DV_2M, 0x2E30A800)
INST1(uminv, "uminv", 0, 0, IF_DV_2M, 0x2E31A800)
// uminv Vd,Vn DV_2M 0Q101110XX110001 101010nnnnnddddd 2E31 A800 Vd,Vn (vector)
+INST1(fmaxnmv, "fmaxnmv",0, 0, IF_DV_2R, 0x2E30C800)
+ // fmaxnmv Vd,Vn DV_2R 0Q1011100X110000 110010nnnnnddddd 2E30 C800 Vd,Vn (vector)
+
+INST1(fmaxv, "fmaxv", 0, 0, IF_DV_2R, 0x2E30F800)
+ // fmaxv Vd,Vn DV_2R 0Q1011100X110000 111110nnnnnddddd 2E30 F800 Vd,Vn (vector)
+
+INST1(fminnmv, "fminnmv",0, 0, IF_DV_2R, 0x2EB0C800)
+ // fminnmv Vd,Vn DV_2R 0Q1011101X110000 110010nnnnnddddd 2EB0 C800 Vd,Vn (vector)
+
+INST1(fminv, "fminv", 0, 0, IF_DV_2R, 0x2EB0F800)
+ // fminv Vd,Vn DV_2R 0Q1011101X110000 111110nnnnnddddd 2EB0 F800 Vd,Vn (vector)
+
INST1(uzp1, "uzp1", 0, 0, IF_DV_3A, 0x0E001800)
// uzp1 Vd,Vn,Vm DV_3A 0Q001110XX0mmmmm 000110nnnnnddddd 0E00 1800 Vd,Vn,Vm (vector)
@@ -1275,9 +1315,15 @@ INST1(sabd, "sabd", 0, 0, IF_DV_3A, 0x0E207400)
INST1(smax, "smax", 0, 0, IF_DV_3A, 0x0E206400)
// smax Vd,Vn,Vm DV_3A 0Q001110XX1mmmmm 011001nnnnnddddd 0E20 6400 Vd,Vn,Vm (vector)
+INST1(smaxp, "smaxp", 0, 0, IF_DV_3A, 0x0E20A400)
+ // smaxp Vd,Vn,Vm DV_3A 0Q001110XX1mmmmm 101001nnnnnddddd 0E20 A400 Vd,Vn,Vm (vector)
+
INST1(smin, "smin", 0, 0, IF_DV_3A, 0x0E206C00)
// smax Vd,Vn,Vm DV_3A 0Q001110XX1mmmmm 011011nnnnnddddd 0E20 6C00 Vd,Vn,Vm (vector)
+INST1(sminp, "sminp", 0, 0, IF_DV_3A, 0x0E20AC00)
+ // smax Vd,Vn,Vm DV_3A 0Q001110XX1mmmmm 101011nnnnnddddd 0E20 AC00 Vd,Vn,Vm (vector)
+
INST1(uaba, "uaba", 0, 0, IF_DV_3A, 0x2E207C00)
// uaba Vd,Vn,Vm DV_3A 0Q101110XX1mmmmm 011111nnnnnddddd 2E20 7C00 Vd,Vn,Vm (vector)
@@ -1287,9 +1333,15 @@ INST1(uabd, "uabd", 0, 0, IF_DV_3A, 0x2E207400)
INST1(umax, "umax", 0, 0, IF_DV_3A, 0x2E206400)
// umax Vd,Vn,Vm DV_3A 0Q101110XX1mmmmm 011001nnnnnddddd 2E20 6400 Vd,Vn,Vm (vector)
+INST1(umaxp, "umaxp", 0, 0, IF_DV_3A, 0x2E20A400)
+ // umaxp Vd,Vn,Vm DV_3A 0Q101110XX1mmmmm 101001nnnnnddddd 2E20 A400 Vd,Vn,Vm (vector)
+
INST1(umin, "umin", 0, 0, IF_DV_3A, 0x2E206C00)
// umin Vd,Vn,Vm DV_3A 0Q101110XX1mmmmm 011011nnnnnddddd 2E20 6C00 Vd,Vn,Vm (vector)
+INST1(uminp, "uminp", 0, 0, IF_DV_3A, 0x2E20AC00)
+ // umin Vd,Vn,Vm DV_3A 0Q101110XX1mmmmm 101011nnnnnddddd 2E20 AC00 Vd,Vn,Vm (vector)
+
INST1(fcvtl, "fcvtl", 0, 0, IF_DV_2G, 0x0E217800)
// fcvtl Vd,Vn DV_2G 000011100X100001 011110nnnnnddddd 0E21 7800 Vd,Vn (scalar)
diff --git a/src/coreclr/src/jit/instrsxarch.h b/src/coreclr/src/jit/instrsxarch.h
index 0bd795d8b34870..986ce9ab450c13 100644
--- a/src/coreclr/src/jit/instrsxarch.h
+++ b/src/coreclr/src/jit/instrsxarch.h
@@ -694,7 +694,7 @@ INST1(shrd, "shrd", IUM_RW, 0x0F00AC,
#ifdef TARGET_X86
INST1(fld, "fld", IUM_WR, 0x0000D9, INS_FLAGS_x87Instr)
INST1(fstp, "fstp", IUM_WR, 0x0018D9, INS_FLAGS_x87Instr)
-#endif // _TARGET_X86
+#endif // TARGET_X86
INST1(seto, "seto", IUM_WR, 0x0F0090, INS_FLAGS_ReadsFlags)
INST1(setno, "setno", IUM_WR, 0x0F0091, INS_FLAGS_ReadsFlags)
diff --git a/src/coreclr/src/jit/lclvars.cpp b/src/coreclr/src/jit/lclvars.cpp
index a4110734d17ab1..4a5b2f1132efbe 100644
--- a/src/coreclr/src/jit/lclvars.cpp
+++ b/src/coreclr/src/jit/lclvars.cpp
@@ -557,7 +557,7 @@ void Compiler::lvaInitUserArgs(InitVarDscInfo* varDscInfo)
#elif defined(TARGET_AMD64) && !defined(UNIX_AMD64_ABI)
// On System V type environment the float registers are not indexed together with the int ones.
varDscInfo->floatRegArgNum = varDscInfo->intRegArgNum;
-#endif // _TARGET_*
+#endif // TARGET*
CORINFO_ARG_LIST_HANDLE argLst = info.compMethodInfo->args.args;
@@ -1000,7 +1000,7 @@ void Compiler::lvaInitUserArgs(InitVarDscInfo* varDscInfo)
//
varDscInfo->setAllRegArgUsed(argType);
-#endif // _TARGET_XXX_
+#endif // TARGET_XXX
#if FEATURE_FASTTAILCALL
varDsc->lvStkOffs = varDscInfo->stackArgSize;
@@ -5370,9 +5370,9 @@ int Compiler::lvaAssignVirtualFrameOffsetToArg(unsigned lclNum,
varDsc->lvStkOffs = argOffs;
argOffs += argSize;
}
-#else // _TARGET_*
+#else // TARGET*
#error Unsupported or unset target architecture
-#endif // _TARGET_*
+#endif // TARGET*
}
else
{
diff --git a/src/coreclr/src/jit/lower.cpp b/src/coreclr/src/jit/lower.cpp
index b6def42a547870..ab2820d72c2848 100644
--- a/src/coreclr/src/jit/lower.cpp
+++ b/src/coreclr/src/jit/lower.cpp
@@ -98,8 +98,14 @@ bool Lowering::IsSafeToContainMem(GenTree* parentNode, GenTree* childNode)
}
//------------------------------------------------------------------------
-
-// This is the main entry point for Lowering.
+// LowerNode: this is the main entry point for Lowering.
+//
+// Arguments:
+// node - the node we are lowering.
+//
+// Returns:
+// next node in the transformed node sequence that needs to be lowered.
+//
GenTree* Lowering::LowerNode(GenTree* node)
{
assert(node != nullptr);
@@ -128,8 +134,14 @@ GenTree* Lowering::LowerNode(GenTree* node)
break;
case GT_ADD:
- LowerAdd(node->AsOp());
- break;
+ {
+ GenTree* next = LowerAdd(node->AsOp());
+ if (next != nullptr)
+ {
+ return next;
+ }
+ }
+ break;
#if !defined(TARGET_64BIT)
case GT_ADD_LO:
@@ -190,7 +202,7 @@ GenTree* Lowering::LowerNode(GenTree* node)
break;
case GT_RETURN:
- LowerRet(node);
+ LowerRet(node->AsUnOp());
break;
case GT_RETURNTRAP:
@@ -286,16 +298,25 @@ GenTree* Lowering::LowerNode(GenTree* node)
case GT_STORE_LCL_FLD:
{
-#if defined(TARGET_AMD64) && defined(FEATURE_SIMD)
GenTreeLclVarCommon* const store = node->AsLclVarCommon();
- if ((store->TypeGet() == TYP_SIMD8) != (store->gtOp1->TypeGet() == TYP_SIMD8))
+ GenTree* op1 = store->gtGetOp1();
+ if ((varTypeUsesFloatReg(store) != varTypeUsesFloatReg(op1)) && !store->IsPhiDefn() &&
+ (op1->TypeGet() != TYP_STRUCT))
{
- GenTreeUnOp* bitcast =
- new (comp, GT_BITCAST) GenTreeOp(GT_BITCAST, store->TypeGet(), store->gtOp1, nullptr);
- store->gtOp1 = bitcast;
- BlockRange().InsertBefore(store, bitcast);
+ if (m_lsra->isRegCandidate(comp->lvaGetDesc(store->GetLclNum())))
+ {
+ GenTreeUnOp* bitcast =
+ new (comp, GT_BITCAST) GenTreeOp(GT_BITCAST, store->TypeGet(), store->gtOp1, nullptr);
+ store->gtOp1 = bitcast;
+ BlockRange().InsertBefore(store, bitcast);
+ ContainCheckBitCast(bitcast);
+ }
+ else
+ {
+ // This is an actual store, we'll just retype it.
+ store->gtType = op1->TypeGet();
+ }
}
-#endif // TARGET_AMD64
// TODO-1stClassStructs: Once we remove the requirement that all struct stores
// are block stores (GT_STORE_BLK or GT_STORE_OBJ), here is where we would put the local
// store under a block store if codegen will require it.
@@ -2306,7 +2327,7 @@ GenTree* Lowering::LowerTailCallViaHelper(GenTreeCall* call, GenTree* callTarget
#else
NYI("LowerTailCallViaHelper");
-#endif // _TARGET_*
+#endif // TARGET*
// Transform this call node into a call to Jit tail call helper.
call->gtCallType = CT_HELPER;
@@ -3075,7 +3096,7 @@ void Lowering::LowerJmpMethod(GenTree* jmp)
}
// Lower GT_RETURN node to insert PInvoke method epilog if required.
-void Lowering::LowerRet(GenTree* ret)
+void Lowering::LowerRet(GenTreeUnOp* ret)
{
assert(ret->OperGet() == GT_RETURN);
@@ -3083,22 +3104,22 @@ void Lowering::LowerRet(GenTree* ret)
DISPNODE(ret);
JITDUMP("============");
-#if defined(TARGET_AMD64) && defined(FEATURE_SIMD)
- GenTreeUnOp* const unOp = ret->AsUnOp();
- if ((unOp->TypeGet() == TYP_LONG) && (unOp->gtOp1->TypeGet() == TYP_SIMD8))
+ GenTree* op1 = ret->gtGetOp1();
+ if ((ret->TypeGet() != TYP_VOID) && (ret->TypeGet() != TYP_STRUCT) &&
+ (varTypeUsesFloatReg(ret) != varTypeUsesFloatReg(ret->gtGetOp1())))
{
- GenTreeUnOp* bitcast = new (comp, GT_BITCAST) GenTreeOp(GT_BITCAST, TYP_LONG, unOp->gtOp1, nullptr);
- unOp->gtOp1 = bitcast;
- BlockRange().InsertBefore(unOp, bitcast);
+ GenTreeUnOp* bitcast = new (comp, GT_BITCAST) GenTreeOp(GT_BITCAST, ret->TypeGet(), ret->gtGetOp1(), nullptr);
+ ret->gtOp1 = bitcast;
+ BlockRange().InsertBefore(ret, bitcast);
+ ContainCheckBitCast(bitcast);
}
-#endif // TARGET_AMD64
// Method doing PInvokes has exactly one return block unless it has tail calls.
if (comp->compMethodRequiresPInvokeFrame() && (comp->compCurBB == comp->genReturnBB))
{
InsertPInvokeMethodEpilog(comp->compCurBB DEBUGARG(ret));
}
- ContainCheckRet(ret->AsOp());
+ ContainCheckRet(ret);
}
GenTree* Lowering::LowerDirectCall(GenTreeCall* call)
@@ -4489,12 +4510,43 @@ bool Lowering::TryCreateAddrMode(GenTree* addr, bool isContainable)
// Arguments:
// node - the node we care about
//
-void Lowering::LowerAdd(GenTreeOp* node)
+// Returns:
+// nullptr if no transformation was done, or the next node in the transformed node sequence that
+// needs to be lowered.
+//
+GenTree* Lowering::LowerAdd(GenTreeOp* node)
{
-#ifndef TARGET_ARMARCH
if (varTypeIsIntegralOrI(node->TypeGet()))
{
+ GenTree* op1 = node->gtGetOp1();
+ GenTree* op2 = node->gtGetOp2();
LIR::Use use;
+
+ // It is not the best place to do such simple arithmetic optimizations,
+ // but it allows us to avoid `LEA(addr, 0)` nodes and doing that in morph
+ // requires more changes. Delete that part if we get an expression optimizer.
+ if (op2->IsIntegralConst(0))
+ {
+ JITDUMP("Lower: optimize val + 0: ");
+ DISPNODE(node);
+ JITDUMP("Replaced with: ");
+ DISPNODE(op1);
+ if (BlockRange().TryGetUse(node, &use))
+ {
+ use.ReplaceWith(comp, op1);
+ }
+ else
+ {
+ op1->SetUnusedValue();
+ }
+ GenTree* next = node->gtNext;
+ BlockRange().Remove(op2);
+ BlockRange().Remove(node);
+ JITDUMP("Remove [06%u], [06%u]\n", op2->gtTreeID, node->gtTreeID);
+ return next;
+ }
+
+#ifndef TARGET_ARMARCH
if (BlockRange().TryGetUse(node, &use))
{
// If this is a child of an indir, let the parent handle it.
@@ -4505,13 +4557,14 @@ void Lowering::LowerAdd(GenTreeOp* node)
TryCreateAddrMode(node, false);
}
}
- }
#endif // !TARGET_ARMARCH
+ }
if (node->OperIs(GT_ADD))
{
ContainCheckBinary(node);
}
+ return nullptr;
}
//------------------------------------------------------------------------
@@ -5755,7 +5808,7 @@ void Lowering::ContainCheckLclHeap(GenTreeOp* node)
// Arguments:
// node - pointer to the node
//
-void Lowering::ContainCheckRet(GenTreeOp* ret)
+void Lowering::ContainCheckRet(GenTreeUnOp* ret)
{
assert(ret->OperIs(GT_RETURN));
@@ -5802,3 +5855,38 @@ void Lowering::ContainCheckJTrue(GenTreeOp* node)
cmp->gtType = TYP_VOID;
cmp->gtFlags |= GTF_SET_FLAGS;
}
+
+//------------------------------------------------------------------------
+// ContainCheckBitCast: determine whether the source of a BITCAST should be contained.
+//
+// Arguments:
+// node - pointer to the node
+//
+void Lowering::ContainCheckBitCast(GenTree* node)
+{
+ GenTree* const op1 = node->AsOp()->gtOp1;
+ if (op1->isMemoryOp())
+ {
+ op1->SetContained();
+ }
+ else if (op1->OperIs(GT_LCL_VAR))
+ {
+ if (!m_lsra->willEnregisterLocalVars())
+ {
+ op1->SetContained();
+ }
+ LclVarDsc* varDsc = &comp->lvaTable[op1->AsLclVar()->GetLclNum()];
+ if (!m_lsra->isRegCandidate(varDsc))
+ {
+ op1->SetContained();
+ }
+ else
+ {
+ op1->SetRegOptional();
+ }
+ }
+ else if (op1->IsLocal())
+ {
+ op1->SetContained();
+ }
+}
diff --git a/src/coreclr/src/jit/lower.h b/src/coreclr/src/jit/lower.h
index 3fef773bd58da3..f3db1dfd747340 100644
--- a/src/coreclr/src/jit/lower.h
+++ b/src/coreclr/src/jit/lower.h
@@ -83,9 +83,10 @@ class Lowering final : public Phase
void ContainCheckReturnTrap(GenTreeOp* node);
void ContainCheckArrOffset(GenTreeArrOffs* node);
void ContainCheckLclHeap(GenTreeOp* node);
- void ContainCheckRet(GenTreeOp* node);
+ void ContainCheckRet(GenTreeUnOp* ret);
void ContainCheckJTrue(GenTreeOp* node);
+ void ContainCheckBitCast(GenTree* node);
void ContainCheckCallOperands(GenTreeCall* call);
void ContainCheckIndir(GenTreeIndir* indirNode);
void ContainCheckStoreIndir(GenTreeIndir* indirNode);
@@ -132,7 +133,7 @@ class Lowering final : public Phase
GenTree* LowerJTrue(GenTreeOp* jtrue);
GenTreeCC* LowerNodeCC(GenTree* node, GenCondition condition);
void LowerJmpMethod(GenTree* jmp);
- void LowerRet(GenTree* ret);
+ void LowerRet(GenTreeUnOp* ret);
GenTree* LowerDelegateInvoke(GenTreeCall* call);
GenTree* LowerIndirectNonvirtCall(GenTreeCall* call);
GenTree* LowerDirectCall(GenTreeCall* call);
@@ -277,7 +278,7 @@ class Lowering final : public Phase
// Per tree node member functions
void LowerStoreIndir(GenTreeIndir* node);
- void LowerAdd(GenTreeOp* node);
+ GenTree* LowerAdd(GenTreeOp* node);
bool LowerUnsignedDivOrMod(GenTreeOp* divMod);
GenTree* LowerConstIntDivOrMod(GenTree* node);
GenTree* LowerSignedDivOrMod(GenTree* node);
diff --git a/src/coreclr/src/jit/lowerarmarch.cpp b/src/coreclr/src/jit/lowerarmarch.cpp
index 7963a3ba716067..0254af429e37be 100644
--- a/src/coreclr/src/jit/lowerarmarch.cpp
+++ b/src/coreclr/src/jit/lowerarmarch.cpp
@@ -151,14 +151,14 @@ bool Lowering::IsContainableImmed(GenTree* parentNode, GenTree* childNode)
//
void Lowering::LowerStoreLoc(GenTreeLclVarCommon* storeLoc)
{
- // Try to widen the ops if they are going into a local var.
GenTree* op1 = storeLoc->gtGetOp1();
if ((storeLoc->gtOper == GT_STORE_LCL_VAR) && (op1->gtOper == GT_CNS_INT))
{
+ // Try to widen the ops if they are going into a local var.
GenTreeIntCon* con = op1->AsIntCon();
ssize_t ival = con->gtIconVal;
unsigned varNum = storeLoc->GetLclNum();
- LclVarDsc* varDsc = comp->lvaTable + varNum;
+ LclVarDsc* varDsc = comp->lvaGetDesc(varNum);
if (varDsc->lvIsSIMDType())
{
@@ -708,6 +708,18 @@ void Lowering::ContainCheckStoreLoc(GenTreeLclVarCommon* storeLoc)
assert(storeLoc->OperIsLocalStore());
GenTree* op1 = storeLoc->gtGetOp1();
+ if (op1->OperIs(GT_BITCAST))
+ {
+ // If we know that the source of the bitcast will be in a register, then we can make
+ // the bitcast itself contained. This will allow us to store directly from the other
+ // type if this node doesn't get a register.
+ GenTree* bitCastSrc = op1->gtGetOp1();
+ if (!bitCastSrc->isContained() && !bitCastSrc->IsRegOptional())
+ {
+ op1->SetContained();
+ return;
+ }
+ }
#ifdef FEATURE_SIMD
if (varTypeIsSIMD(storeLoc))
{
diff --git a/src/coreclr/src/jit/lowerxarch.cpp b/src/coreclr/src/jit/lowerxarch.cpp
index 86f7e71885a983..272b8b3946ba87 100644
--- a/src/coreclr/src/jit/lowerxarch.cpp
+++ b/src/coreclr/src/jit/lowerxarch.cpp
@@ -1925,6 +1925,18 @@ void Lowering::ContainCheckStoreLoc(GenTreeLclVarCommon* storeLoc)
assert(storeLoc->OperIsLocalStore());
GenTree* op1 = storeLoc->gtGetOp1();
+ if (op1->OperIs(GT_BITCAST))
+ {
+ // If we know that the source of the bitcast will be in a register, then we can make
+ // the bitcast itself contained. This will allow us to store directly from the other
+ // type if this node doesn't get a register.
+ GenTree* bitCastSrc = op1->gtGetOp1();
+ if (!bitCastSrc->isContained() && !bitCastSrc->IsRegOptional())
+ {
+ op1->SetContained();
+ return;
+ }
+ }
#ifdef FEATURE_SIMD
if (varTypeIsSIMD(storeLoc))
{
diff --git a/src/coreclr/src/jit/lsra.cpp b/src/coreclr/src/jit/lsra.cpp
index 0949203cadb285..c2b03ace694c4b 100644
--- a/src/coreclr/src/jit/lsra.cpp
+++ b/src/coreclr/src/jit/lsra.cpp
@@ -1428,7 +1428,7 @@ bool LinearScan::isRegCandidate(LclVarDsc* varDsc)
// Lowering will have split any candidate lclVars into lo/hi vars.
return false;
}
-#endif // !defined(_TARGET_64BIT)
+#endif // !defined(TARGET_64BIT)
// If we have JMP, reg args must be put on the stack
@@ -1507,15 +1507,11 @@ bool LinearScan::isRegCandidate(LclVarDsc* varDsc)
break;
#ifdef FEATURE_SIMD
+ case TYP_SIMD8:
case TYP_SIMD12:
case TYP_SIMD16:
case TYP_SIMD32:
return !varDsc->lvPromoted;
-
- // TODO-1stClassStructs: Move TYP_SIMD8 up with the other SIMD types, after handling the param issue
- // (passing & returning as TYP_LONG).
- case TYP_SIMD8:
- return false;
#endif // FEATURE_SIMD
case TYP_STRUCT:
@@ -5453,6 +5449,15 @@ void LinearScan::allocateRegisters()
// TODO-CQ: Consider doing this only for stack parameters, since otherwise we may be needlessly
// inserting a store.
allocate = false;
+ }
+ else if ((currentInterval->physReg == REG_STK) && nextRefPosition->treeNode->OperIs(GT_BITCAST))
+ {
+ // In the case of ABI mismatches, avoid allocating a register only to have to immediately move
+ // it to a different register file.
+ allocate = false;
+ }
+ if (!allocate)
+ {
INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_NO_ENTRY_REG_ALLOCATED, currentInterval));
didDump = true;
setIntervalAsSpilled(currentInterval);
diff --git a/src/coreclr/src/jit/lsraarm.cpp b/src/coreclr/src/jit/lsraarm.cpp
index 0e633c1a5ad76a..8891653f749ca7 100644
--- a/src/coreclr/src/jit/lsraarm.cpp
+++ b/src/coreclr/src/jit/lsraarm.cpp
@@ -749,7 +749,6 @@ int LinearScan::BuildNode(GenTree* tree)
case GT_BITCAST:
{
- srcCount = 1;
assert(dstCount == 1);
regNumber argReg = tree->GetRegNum();
regMaskTP argMask = genRegMask(argReg);
@@ -763,8 +762,15 @@ int LinearScan::BuildNode(GenTree* tree)
argMask |= genRegMask(REG_NEXT(argReg));
dstCount = 2;
}
-
- BuildUse(tree->gtGetOp1());
+ if (!tree->gtGetOp1()->isContained())
+ {
+ BuildUse(tree->gtGetOp1());
+ srcCount = 1;
+ }
+ else
+ {
+ srcCount = 0;
+ }
BuildDefs(tree, dstCount, argMask);
}
break;
diff --git a/src/coreclr/src/jit/lsraarm64.cpp b/src/coreclr/src/jit/lsraarm64.cpp
index 961716a591f82e..0bcb661a8e4a02 100644
--- a/src/coreclr/src/jit/lsraarm64.cpp
+++ b/src/coreclr/src/jit/lsraarm64.cpp
@@ -1079,7 +1079,6 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree)
{
case NI_Aes_Decrypt:
case NI_Aes_Encrypt:
- {
assert((numArgs == 2) && (op1 != nullptr) && (op2 != nullptr));
buildUses = false;
@@ -1087,14 +1086,11 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree)
tgtPrefUse = BuildUse(op1);
srcCount += 1;
srcCount += BuildDelayFreeUses(op2);
-
break;
- }
case NI_Sha1_HashUpdateChoose:
case NI_Sha1_HashUpdateMajority:
case NI_Sha1_HashUpdateParity:
- {
assert((numArgs == 3) && (op2 != nullptr) && (op3 != nullptr));
if (!op2->isContained())
@@ -1112,19 +1108,15 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree)
buildInternalFloatRegisterDefForNode(intrinsicTree);
break;
- }
case NI_Sha1_FixedRotate:
- {
buildInternalFloatRegisterDefForNode(intrinsicTree);
break;
- }
case NI_Sha1_ScheduleUpdate0:
case NI_Sha256_HashUpdate1:
case NI_Sha256_HashUpdate2:
case NI_Sha256_ScheduleUpdate1:
- {
assert((numArgs == 3) && (op2 != nullptr) && (op3 != nullptr));
if (!op2->isContained())
@@ -1138,13 +1130,26 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree)
srcCount += BuildDelayFreeUses(op3);
}
break;
- }
+
+ case NI_AdvSimd_FusedMultiplyAdd:
+ case NI_AdvSimd_FusedMultiplySubtract:
+ case NI_AdvSimd_Arm64_FusedMultiplyAdd:
+ case NI_AdvSimd_Arm64_FusedMultiplySubtract:
+ case NI_AdvSimd_MultiplyAdd:
+ case NI_AdvSimd_MultiplySubtract:
+ assert((numArgs == 3) && (op2 != nullptr) && (op3 != nullptr));
+
+ buildUses = false;
+
+ tgtPrefUse = BuildUse(op1);
+ srcCount += 1;
+ srcCount += BuildDelayFreeUses(op2);
+ srcCount += BuildDelayFreeUses(op3);
+ break;
default:
- {
assert((intrinsicId > NI_HW_INTRINSIC_START) && (intrinsicId < NI_HW_INTRINSIC_END));
break;
- }
}
if (buildUses)
diff --git a/src/coreclr/src/jit/lsraarmarch.cpp b/src/coreclr/src/jit/lsraarmarch.cpp
index 3ddab72698dedb..fab94aaf112520 100644
--- a/src/coreclr/src/jit/lsraarmarch.cpp
+++ b/src/coreclr/src/jit/lsraarmarch.cpp
@@ -38,13 +38,9 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
//
int LinearScan::BuildIndir(GenTreeIndir* indirTree)
{
- int srcCount = 0;
- // If this is the rhs of a block copy (i.e. non-enregisterable struct),
- // it has no register requirements.
- if (indirTree->TypeGet() == TYP_STRUCT)
- {
- return srcCount;
- }
+ // struct typed indirs are expected only on rhs of a block copy,
+ // but in this case they must be contained.
+ assert(indirTree->TypeGet() != TYP_STRUCT);
GenTree* addr = indirTree->Addr();
GenTree* index = nullptr;
@@ -109,7 +105,7 @@ int LinearScan::BuildIndir(GenTreeIndir* indirTree)
}
#endif // FEATURE_SIMD
- srcCount = BuildIndirUses(indirTree);
+ int srcCount = BuildIndirUses(indirTree);
buildInternalRegisterUses();
if (indirTree->gtOper != GT_STOREIND)
@@ -502,7 +498,7 @@ int LinearScan::BuildPutArgSplit(GenTreePutArgSplit* argNode)
currentRegCount = node->AsMultiRegOp()->GetRegCount();
}
else
-#endif // _TARGET_ARM
+#endif // TARGET_ARM
{
assert(!node->IsMultiRegNode());
currentRegCount = 1;
diff --git a/src/coreclr/src/jit/lsrabuild.cpp b/src/coreclr/src/jit/lsrabuild.cpp
index 16ca5e288adf3a..fb4b8ff61be89b 100644
--- a/src/coreclr/src/jit/lsrabuild.cpp
+++ b/src/coreclr/src/jit/lsrabuild.cpp
@@ -2473,14 +2473,18 @@ void setTgtPref(Interval* interval, RefPosition* tgtPrefUse)
RefPosition* LinearScan::BuildDef(GenTree* tree, regMaskTP dstCandidates, int multiRegIdx)
{
assert(!tree->isContained());
- RegisterType type = getDefType(tree);
if (dstCandidates != RBM_NONE)
{
assert((tree->GetRegNum() == REG_NA) || (dstCandidates == genRegMask(tree->GetRegByIndex(multiRegIdx))));
}
- if (tree->IsMultiRegNode())
+ RegisterType type = getDefType(tree);
+ if (!tree->IsMultiRegNode())
+ {
+ type = getDefType(tree);
+ }
+ else
{
type = tree->GetRegTypeByIndex(multiRegIdx);
}
@@ -2931,7 +2935,6 @@ int LinearScan::BuildStoreLoc(GenTreeLclVarCommon* storeLoc)
// srcCount = number of registers in which the value is returned by call
GenTreeCall* call = op1->AsCall();
ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc();
- unsigned regCount = retTypeDesc->GetReturnRegCount();
srcCount = retTypeDesc->GetReturnRegCount();
for (int i = 0; i < srcCount; ++i)
@@ -2939,6 +2942,16 @@ int LinearScan::BuildStoreLoc(GenTreeLclVarCommon* storeLoc)
BuildUse(op1, RBM_NONE, i);
}
}
+ else if (op1->isContained() && op1->OperIs(GT_BITCAST))
+ {
+ GenTree* bitCastSrc = op1->gtGetOp1();
+ RegisterType registerType = bitCastSrc->TypeGet();
+ singleUseRef = BuildUse(bitCastSrc, allRegs(registerType));
+
+ Interval* srcInterval = singleUseRef->getInterval();
+ assert(srcInterval->registerType == registerType);
+ srcCount = 1;
+ }
#ifndef TARGET_64BIT
else if (varTypeIsLong(op1))
{
@@ -3012,26 +3025,6 @@ int LinearScan::BuildStoreLoc(GenTreeLclVarCommon* storeLoc)
}
newRefPosition(varDefInterval, currentLoc + 1, RefTypeDef, storeLoc, allRegs(storeLoc->TypeGet()));
}
- else
- {
- if (storeLoc->gtOp1->OperIs(GT_BITCAST))
- {
- storeLoc->gtType = storeLoc->gtOp1->gtType = storeLoc->gtOp1->AsUnOp()->gtOp1->TypeGet();
- RegisterType registerType = regType(storeLoc->TypeGet());
- noway_assert(singleUseRef != nullptr);
-
- Interval* srcInterval = singleUseRef->getInterval();
- srcInterval->registerType = registerType;
-
- RefPosition* srcDefPosition = srcInterval->firstRefPosition;
- assert(srcDefPosition != nullptr);
- assert(srcDefPosition->refType == RefTypeDef);
- assert(srcDefPosition->treeNode == storeLoc->gtOp1);
-
- srcDefPosition->registerAssignment = allRegs(registerType);
- singleUseRef->registerAssignment = allRegs(registerType);
- }
- }
return srcCount;
}
diff --git a/src/coreclr/src/jit/lsraxarch.cpp b/src/coreclr/src/jit/lsraxarch.cpp
index 400ab3da282134..e23d1c80da6ded 100644
--- a/src/coreclr/src/jit/lsraxarch.cpp
+++ b/src/coreclr/src/jit/lsraxarch.cpp
@@ -372,13 +372,18 @@ int LinearScan::BuildNode(GenTree* tree)
break;
case GT_BITCAST:
- {
assert(dstCount == 1);
- tgtPrefUse = BuildUse(tree->gtGetOp1());
+ if (!tree->gtGetOp1()->isContained())
+ {
+ BuildUse(tree->gtGetOp1());
+ srcCount = 1;
+ }
+ else
+ {
+ srcCount = 0;
+ }
BuildDef(tree);
- srcCount = 1;
- }
- break;
+ break;
case GT_NEG:
// TODO-XArch-CQ:
@@ -2746,12 +2751,9 @@ int LinearScan::BuildCast(GenTreeCast* cast)
//
int LinearScan::BuildIndir(GenTreeIndir* indirTree)
{
- // If this is the rhs of a block copy (i.e. non-enregisterable struct),
- // it has no register requirements.
- if (indirTree->TypeGet() == TYP_STRUCT)
- {
- return 0;
- }
+ // struct typed indirs are expected only on rhs of a block copy,
+ // but in this case they must be contained.
+ assert(indirTree->TypeGet() != TYP_STRUCT);
#ifdef FEATURE_SIMD
RefPosition* internalFloatDef = nullptr;
diff --git a/src/coreclr/src/jit/morph.cpp b/src/coreclr/src/jit/morph.cpp
index aed99029b49179..7594aa2273aed3 100644
--- a/src/coreclr/src/jit/morph.cpp
+++ b/src/coreclr/src/jit/morph.cpp
@@ -2975,7 +2975,7 @@ void Compiler::fgInitArgInfo(GenTreeCall* call)
#else
#error Unsupported or unset target architecture
-#endif // _TARGET_*
+#endif // TARGET*
bool isBackFilled = false;
unsigned nextFltArgRegNum = fltArgRegNum; // This is the next floating-point argument register number to use
@@ -3079,7 +3079,7 @@ void Compiler::fgInitArgInfo(GenTreeCall* call)
}
#else
#error Unsupported or unset target architecture
-#endif // _TARGET_XXX_
+#endif // TARGET_XXX
if (isStructArg)
{
// We have an argument with a struct type, but it may be be a child of a GT_COMMA
@@ -3857,7 +3857,7 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call)
copyBlkClass = objClass;
}
}
- else if (genActualType(varDsc->TypeGet()) != structBaseType)
+ else if (genTypeSize(varDsc->TypeGet()) != genTypeSize(structBaseType))
{
// Not a promoted struct, so just swizzle the type by using GT_LCL_FLD
argObj->ChangeOper(GT_LCL_FLD);
@@ -4177,7 +4177,7 @@ void Compiler::fgMorphMultiregStructArgs(GenTreeCall* call)
foundStructArg = true;
if (varTypeIsStruct(argx) && !argx->OperIs(GT_FIELD_LIST))
{
- if (fgEntryPtr->IsHfaArg())
+ if (fgEntryPtr->IsHfaRegArg())
{
var_types hfaType = fgEntryPtr->GetHfaType();
unsigned structSize;
@@ -8888,7 +8888,8 @@ GenTree* Compiler::fgMorphOneAsgBlockOp(GenTree* tree)
if (dest == destLclVarTree)
{
- dest = gtNewIndir(asgType, gtNewOperNode(GT_ADDR, TYP_BYREF, dest));
+ GenTree* addr = gtNewOperNode(GT_ADDR, TYP_BYREF, dest);
+ dest = gtNewIndir(asgType, addr);
}
}
}
@@ -9713,12 +9714,12 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree)
bool isLateArg = (tree->gtFlags & GTF_LATE_ARG) != 0;
GenTree* asg = tree;
- GenTree* rhs = asg->gtGetOp2();
+ GenTree* src = asg->gtGetOp2();
GenTree* dest = asg->gtGetOp1();
#if FEATURE_MULTIREG_RET
// If this is a multi-reg return, we will not do any morphing of this node.
- if (rhs->IsMultiRegCall())
+ if (src->IsMultiRegCall())
{
assert(dest->OperGet() == GT_LCL_VAR);
JITDUMP(" not morphing a multireg call return\n");
@@ -9738,9 +9739,9 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree)
}
}
asg->gtType = dest->TypeGet();
- rhs = fgMorphBlkNode(rhs, false);
+ src = fgMorphBlkNode(src, false);
- asg->AsOp()->gtOp2 = rhs;
+ asg->AsOp()->gtOp2 = src;
GenTree* oldTree = tree;
GenTree* oneAsgTree = fgMorphOneAsgBlockOp(tree);
@@ -9876,24 +9877,24 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree)
LclVarDsc* srcLclVar = nullptr;
bool srcDoFldAsg = false;
- if (rhs->IsLocal())
+ if (src->IsLocal())
{
- srcLclVarTree = rhs->AsLclVarCommon();
+ srcLclVarTree = src->AsLclVarCommon();
srcLclNum = srcLclVarTree->GetLclNum();
- if (rhs->OperGet() == GT_LCL_FLD)
+ if (src->OperGet() == GT_LCL_FLD)
{
- srcFldSeq = rhs->AsLclFld()->GetFieldSeq();
+ srcFldSeq = src->AsLclFld()->GetFieldSeq();
}
}
- else if (rhs->OperIsIndir())
+ else if (src->OperIsIndir())
{
- if (rhs->AsOp()->gtOp1->IsLocalAddrExpr(this, &srcLclVarTree, &srcFldSeq))
+ if (src->AsOp()->gtOp1->IsLocalAddrExpr(this, &srcLclVarTree, &srcFldSeq))
{
srcLclNum = srcLclVarTree->GetLclNum();
}
else
{
- srcAddr = rhs->AsOp()->gtOp1;
+ srcAddr = src->AsOp()->gtOp1;
}
}
@@ -9960,9 +9961,9 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree)
}
#if defined(TARGET_ARM)
- if ((rhs->OperIsIndir()) && (rhs->gtFlags & GTF_IND_UNALIGNED))
+ if ((src->OperIsIndir()) && (src->gtFlags & GTF_IND_UNALIGNED))
{
- JITDUMP(" rhs is unaligned");
+ JITDUMP(" src is unaligned");
requiresCopyBlock = true;
}
@@ -9974,7 +9975,7 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree)
#endif // TARGET_ARM
// Can't use field by field assignment if the src is a call.
- if (rhs->OperGet() == GT_CALL)
+ if (src->OperGet() == GT_CALL)
{
JITDUMP(" src is a call");
// C++ style CopyBlock with holes
@@ -10115,9 +10116,9 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree)
asg->AsOp()->gtOp1 = dest;
asg->gtFlags |= (dest->gtFlags & GTF_ALL_EFFECT);
- // Eliminate the "OBJ or BLK" node on the rhs.
- rhs = fgMorphBlockOperand(rhs, asgType, blockWidth, false /*!isBlkReqd*/);
- asg->AsOp()->gtOp2 = rhs;
+ // Eliminate the "OBJ or BLK" node on the src.
+ src = fgMorphBlockOperand(src, asgType, blockWidth, false /*!isBlkReqd*/);
+ asg->AsOp()->gtOp2 = src;
goto _Done;
}
@@ -10127,7 +10128,6 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree)
//
tree = nullptr;
- GenTree* src;
GenTree* addrSpill = nullptr;
unsigned addrSpillTemp = BAD_VAR_NUM;
bool addrSpillIsStackDest = false; // true if 'addrSpill' represents the address in our local stack frame
@@ -10148,10 +10148,10 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree)
else if (destDoFldAsg)
{
fieldCnt = destLclVar->lvFieldCnt;
- rhs = fgMorphBlockOperand(rhs, asgType, blockWidth, false /*isBlkReqd*/);
+ src = fgMorphBlockOperand(src, asgType, blockWidth, false /*isBlkReqd*/);
if (srcAddr == nullptr)
{
- srcAddr = fgMorphGetStructAddr(&rhs, destLclVar->lvVerTypeInfo.GetClassHandle(), true /* rValue */);
+ srcAddr = fgMorphGetStructAddr(&src, destLclVar->lvVerTypeInfo.GetClassHandle(), true /* rValue */);
}
}
else
@@ -10281,31 +10281,29 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree)
// So, beyond this point we cannot rely on the old values of 'srcLclVar' and 'destLclVar'.
for (unsigned i = 0; i < fieldCnt; ++i)
{
- FieldSeqNode* curFieldSeq = nullptr;
+ GenTree* dstFld;
if (destDoFldAsg)
{
noway_assert(destLclNum != BAD_VAR_NUM);
- unsigned fieldLclNum = lvaTable[destLclNum].lvFieldLclStart + i;
- dest = gtNewLclvNode(fieldLclNum, lvaTable[fieldLclNum].TypeGet());
+ unsigned dstFieldLclNum = lvaTable[destLclNum].lvFieldLclStart + i;
+ dstFld = gtNewLclvNode(dstFieldLclNum, lvaTable[dstFieldLclNum].TypeGet());
// If it had been labeled a "USEASG", assignments to the the individual promoted fields are not.
if (destAddr != nullptr)
{
noway_assert(destAddr->AsOp()->gtOp1->gtOper == GT_LCL_VAR);
- dest->gtFlags |= destAddr->AsOp()->gtOp1->gtFlags & ~(GTF_NODE_MASK | GTF_VAR_USEASG);
+ dstFld->gtFlags |= destAddr->AsOp()->gtOp1->gtFlags & ~(GTF_NODE_MASK | GTF_VAR_USEASG);
}
else
{
noway_assert(lclVarTree != nullptr);
- dest->gtFlags |= lclVarTree->gtFlags & ~(GTF_NODE_MASK | GTF_VAR_USEASG);
+ dstFld->gtFlags |= lclVarTree->gtFlags & ~(GTF_NODE_MASK | GTF_VAR_USEASG);
}
// Don't CSE the lhs of an assignment.
- dest->gtFlags |= GTF_DONT_CSE;
+ dstFld->gtFlags |= GTF_DONT_CSE;
}
else
{
noway_assert(srcDoFldAsg);
- noway_assert(srcLclNum != BAD_VAR_NUM);
- unsigned fieldLclNum = lvaTable[srcLclNum].lvFieldLclStart + i;
if (destSingleLclVarAsg)
{
@@ -10313,25 +10311,25 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree)
noway_assert(destLclVar != nullptr);
noway_assert(addrSpill == nullptr);
- dest = gtNewLclvNode(destLclNum, destLclVar->TypeGet());
+ dstFld = gtNewLclvNode(destLclNum, destLclVar->TypeGet());
}
else
{
if (addrSpill)
{
assert(addrSpillTemp != BAD_VAR_NUM);
- dest = gtNewLclvNode(addrSpillTemp, TYP_BYREF);
+ dstFld = gtNewLclvNode(addrSpillTemp, TYP_BYREF);
}
else
{
- dest = gtCloneExpr(destAddr);
- noway_assert(dest != nullptr);
+ dstFld = gtCloneExpr(destAddr);
+ noway_assert(dstFld != nullptr);
// Is the address of a local?
GenTreeLclVarCommon* lclVarTree = nullptr;
bool isEntire = false;
bool* pIsEntire = (blockWidthIsConst ? &isEntire : nullptr);
- if (dest->DefinesLocalAddr(this, blockWidth, &lclVarTree, pIsEntire))
+ if (dstFld->DefinesLocalAddr(this, blockWidth, &lclVarTree, pIsEntire))
{
lclVarTree->gtFlags |= GTF_VAR_DEF;
if (!isEntire)
@@ -10341,38 +10339,51 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree)
}
}
- GenTree* fieldOffsetNode = gtNewIconNode(lvaTable[fieldLclNum].lvFldOffset, TYP_I_IMPL);
+ LclVarDsc* srcVarDsc = lvaGetDesc(srcLclNum);
+ unsigned srcFieldLclNum = srcVarDsc->lvFieldLclStart + i;
+ LclVarDsc* srcFieldVarDsc = lvaGetDesc(srcFieldLclNum);
+
// Have to set the field sequence -- which means we need the field handle.
- CORINFO_CLASS_HANDLE classHnd = lvaTable[srcLclNum].lvVerTypeInfo.GetClassHandle();
+ CORINFO_CLASS_HANDLE classHnd = srcVarDsc->lvVerTypeInfo.GetClassHandle();
CORINFO_FIELD_HANDLE fieldHnd =
- info.compCompHnd->getFieldInClass(classHnd, lvaTable[fieldLclNum].lvFldOrdinal);
- curFieldSeq = GetFieldSeqStore()->CreateSingleton(fieldHnd);
- fieldOffsetNode->AsIntCon()->gtFieldSeq = curFieldSeq;
+ info.compCompHnd->getFieldInClass(classHnd, srcFieldVarDsc->lvFldOrdinal);
+ FieldSeqNode* curFieldSeq = GetFieldSeqStore()->CreateSingleton(fieldHnd);
- dest = gtNewOperNode(GT_ADD, TYP_BYREF, dest, fieldOffsetNode);
+ unsigned srcFieldOffset = lvaGetDesc(srcFieldLclNum)->lvFldOffset;
- dest = gtNewIndir(lvaTable[fieldLclNum].TypeGet(), dest);
+ if (srcFieldOffset == 0)
+ {
+ fgAddFieldSeqForZeroOffset(dstFld, curFieldSeq);
+ }
+ else
+ {
+ GenTree* fieldOffsetNode = gtNewIconNode(srcFieldVarDsc->lvFldOffset, curFieldSeq);
+ dstFld = gtNewOperNode(GT_ADD, TYP_BYREF, dstFld, fieldOffsetNode);
+ }
+
+ dstFld = gtNewIndir(srcFieldVarDsc->TypeGet(), dstFld);
// !!! The destination could be on stack. !!!
// This flag will let us choose the correct write barrier.
- dest->gtFlags |= GTF_IND_TGTANYWHERE;
+ dstFld->gtFlags |= GTF_IND_TGTANYWHERE;
}
}
+ GenTree* srcFld;
if (srcDoFldAsg)
{
noway_assert(srcLclNum != BAD_VAR_NUM);
- unsigned fieldLclNum = lvaTable[srcLclNum].lvFieldLclStart + i;
- src = gtNewLclvNode(fieldLclNum, lvaTable[fieldLclNum].TypeGet());
+ unsigned srcFieldLclNum = lvaTable[srcLclNum].lvFieldLclStart + i;
+ srcFld = gtNewLclvNode(srcFieldLclNum, lvaTable[srcFieldLclNum].TypeGet());
noway_assert(srcLclVarTree != nullptr);
- src->gtFlags |= srcLclVarTree->gtFlags & ~GTF_NODE_MASK;
+ srcFld->gtFlags |= srcLclVarTree->gtFlags & ~GTF_NODE_MASK;
}
else
{
noway_assert(destDoFldAsg);
noway_assert(destLclNum != BAD_VAR_NUM);
- unsigned fieldLclNum = lvaTable[destLclNum].lvFieldLclStart + i;
+ unsigned dstFieldLclNum = lvaTable[destLclNum].lvFieldLclStart + i;
if (srcSingleLclVarAsg)
{
@@ -10380,29 +10391,29 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree)
noway_assert(srcLclNum != BAD_VAR_NUM);
noway_assert(addrSpill == nullptr);
- src = gtNewLclvNode(srcLclNum, lvaGetDesc(srcLclNum)->TypeGet());
+ srcFld = gtNewLclvNode(srcLclNum, lvaGetDesc(srcLclNum)->TypeGet());
}
else
{
if (addrSpill)
{
assert(addrSpillTemp != BAD_VAR_NUM);
- src = gtNewLclvNode(addrSpillTemp, TYP_BYREF);
+ srcFld = gtNewLclvNode(addrSpillTemp, TYP_BYREF);
}
else
{
- src = gtCloneExpr(srcAddr);
- noway_assert(src != nullptr);
+ srcFld = gtCloneExpr(srcAddr);
+ noway_assert(srcFld != nullptr);
}
CORINFO_CLASS_HANDLE classHnd = lvaTable[destLclNum].lvVerTypeInfo.GetClassHandle();
CORINFO_FIELD_HANDLE fieldHnd =
- info.compCompHnd->getFieldInClass(classHnd, lvaTable[fieldLclNum].lvFldOrdinal);
- curFieldSeq = GetFieldSeqStore()->CreateSingleton(fieldHnd);
- var_types destType = lvaGetDesc(fieldLclNum)->lvType;
+ info.compCompHnd->getFieldInClass(classHnd, lvaTable[dstFieldLclNum].lvFldOrdinal);
+ FieldSeqNode* curFieldSeq = GetFieldSeqStore()->CreateSingleton(fieldHnd);
+ var_types destType = lvaGetDesc(dstFieldLclNum)->lvType;
bool done = false;
- if (lvaGetDesc(fieldLclNum)->lvFldOffset == 0)
+ if (lvaGetDesc(dstFieldLclNum)->lvFldOffset == 0)
{
// If this is a full-width use of the src via a different type, we need to create a GT_LCL_FLD.
// (Note that if it was the same type, 'srcSingleLclVarAsg' would be true.)
@@ -10420,28 +10431,31 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree)
srcLclVarTree->ChangeOper(GT_LCL_FLD);
srcLclVarTree->gtType = destType;
srcLclVarTree->AsLclFld()->SetFieldSeq(curFieldSeq);
- src = srcLclVarTree;
- done = true;
+ srcFld = srcLclVarTree;
+ done = true;
}
}
}
- else // if (lvaGetDesc(fieldLclNum)->lvFldOffset != 0)
- {
- src = gtNewOperNode(GT_ADD, TYP_BYREF, src,
- new (this, GT_CNS_INT)
- GenTreeIntCon(TYP_I_IMPL, lvaGetDesc(fieldLclNum)->lvFldOffset,
- curFieldSeq));
- }
if (!done)
{
- src = gtNewIndir(destType, src);
+ unsigned fldOffset = lvaGetDesc(dstFieldLclNum)->lvFldOffset;
+ if (fldOffset == 0)
+ {
+ fgAddFieldSeqForZeroOffset(srcFld, curFieldSeq);
+ }
+ else
+ {
+ GenTreeIntCon* fldOffsetNode = gtNewIconNode(fldOffset, curFieldSeq);
+ srcFld = gtNewOperNode(GT_ADD, TYP_BYREF, srcFld, fldOffsetNode);
+ }
+ srcFld = gtNewIndir(destType, srcFld);
}
}
}
- noway_assert(dest->TypeGet() == src->TypeGet());
+ noway_assert(dstFld->TypeGet() == srcFld->TypeGet());
- asg = gtNewAssignNode(dest, src);
+ asg = gtNewAssignNode(dstFld, srcFld);
// If we spilled the address, and we didn't do individual field assignments to promoted fields,
// and it was of a local, ensure that the destination local variable has been marked as address
@@ -11185,7 +11199,7 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)
//
// Note for TARGET_ARMARCH we don't have a remainder instruction, so we don't do this optimization
//
-#else // _TARGET_XARCH
+#else // TARGET_XARCH
/* If this is an unsigned long mod with op2 which is a cast to long from a
constant int, then don't morph to a call to the helper. This can be done
faster inline using idiv.
@@ -11224,7 +11238,7 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)
return tree;
}
}
-#endif // _TARGET_XARCH
+#endif // TARGET_XARCH
ASSIGN_HELPER_FOR_MOD:
@@ -13262,13 +13276,6 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)
if (isZeroOffset)
{
- // The "op1" node might already be annotated with a zero-offset field sequence.
- FieldSeqNode* existingZeroOffsetFldSeq = nullptr;
- if (GetZeroOffsetFieldMap()->Lookup(op1, &existingZeroOffsetFldSeq))
- {
- // Append the zero field sequences
- zeroFieldSeq = GetFieldSeqStore()->Append(existingZeroOffsetFldSeq, zeroFieldSeq);
- }
// Transfer the annotation to the new GT_ADDR node.
fgAddFieldSeqForZeroOffset(op1, zeroFieldSeq);
}
@@ -16831,64 +16838,64 @@ void Compiler::fgMorphLocalField(GenTree* tree, GenTree* parent)
unsigned lclNum = tree->AsLclFld()->GetLclNum();
LclVarDsc* varDsc = &lvaTable[lclNum];
- if (varTypeIsStruct(varDsc) && (varDsc->lvPromoted))
+ if (varTypeIsStruct(varDsc))
{
- // Promoted struct
- unsigned fldOffset = tree->AsLclFld()->GetLclOffs();
- unsigned fieldLclIndex = 0;
- LclVarDsc* fldVarDsc = nullptr;
-
- if (fldOffset != BAD_VAR_NUM)
+ if (varDsc->lvPromoted)
{
- fieldLclIndex = lvaGetFieldLocal(varDsc, fldOffset);
- noway_assert(fieldLclIndex != BAD_VAR_NUM);
- fldVarDsc = &lvaTable[fieldLclIndex];
- }
+ // Promoted struct
+ unsigned fldOffset = tree->AsLclFld()->GetLclOffs();
+ unsigned fieldLclIndex = 0;
+ LclVarDsc* fldVarDsc = nullptr;
- if (fldOffset != BAD_VAR_NUM && genTypeSize(fldVarDsc->TypeGet()) == genTypeSize(tree->gtType)
-#ifdef TARGET_X86
- && varTypeIsFloating(fldVarDsc->TypeGet()) == varTypeIsFloating(tree->gtType)
-#endif
- )
- {
- // There is an existing sub-field we can use.
- tree->AsLclFld()->SetLclNum(fieldLclIndex);
+ if (fldOffset != BAD_VAR_NUM)
+ {
+ fieldLclIndex = lvaGetFieldLocal(varDsc, fldOffset);
+ noway_assert(fieldLclIndex != BAD_VAR_NUM);
+ fldVarDsc = &lvaTable[fieldLclIndex];
+ }
- // The field must be an enregisterable type; otherwise it would not be a promoted field.
- // The tree type may not match, e.g. for return types that have been morphed, but both
- // must be enregisterable types.
var_types treeType = tree->TypeGet();
var_types fieldType = fldVarDsc->TypeGet();
- assert((varTypeIsEnregisterable(treeType) || varTypeIsSIMD(treeType)) &&
- (varTypeIsEnregisterable(fieldType) || varTypeIsSIMD(fieldType)));
-
- tree->ChangeOper(GT_LCL_VAR);
- assert(tree->AsLclVarCommon()->GetLclNum() == fieldLclIndex);
- tree->gtType = fldVarDsc->TypeGet();
-#ifdef DEBUG
- if (verbose)
+ if (fldOffset != BAD_VAR_NUM && (genTypeSize(fieldType) == genTypeSize(treeType)))
{
- printf("Replacing the GT_LCL_FLD in promoted struct with local var V%02u\n", fieldLclIndex);
- }
-#endif // DEBUG
+ // There is an existing sub-field we can use.
+ tree->AsLclFld()->SetLclNum(fieldLclIndex);
- if ((parent->gtOper == GT_ASG) && (parent->AsOp()->gtOp1 == tree))
- {
- tree->gtFlags |= GTF_VAR_DEF;
- tree->gtFlags |= GTF_DONT_CSE;
+ // The field must be an enregisterable type; otherwise it would not be a promoted field.
+ // The tree type may not match, e.g. for return types that have been morphed, but both
+ // must be enregisterable types.
+ assert(varTypeIsEnregisterable(treeType) && varTypeIsEnregisterable(fieldType));
+
+ tree->ChangeOper(GT_LCL_VAR);
+ assert(tree->AsLclVarCommon()->GetLclNum() == fieldLclIndex);
+ tree->gtType = fldVarDsc->TypeGet();
+
+ if ((parent->gtOper == GT_ASG) && (parent->AsOp()->gtOp1 == tree))
+ {
+ tree->gtFlags |= GTF_VAR_DEF;
+ tree->gtFlags |= GTF_DONT_CSE;
+ }
+ JITDUMP("Replacing the GT_LCL_FLD in promoted struct with local var V%02u\n", fieldLclIndex);
}
- }
- else
- {
- // There is no existing field that has all the parts that we need
- // So we must ensure that the struct lives in memory.
- lvaSetVarDoNotEnregister(lclNum DEBUGARG(DNER_LocalField));
+ else
+ {
+ // There is no existing field that has all the parts that we need
+ // So we must ensure that the struct lives in memory.
+ lvaSetVarDoNotEnregister(lclNum DEBUGARG(DNER_LocalField));
#ifdef DEBUG
- // We can't convert this guy to a float because he really does have his
- // address taken..
- varDsc->lvKeepType = 1;
+ // We can't convert this guy to a float because he really does have his
+ // address taken..
+ varDsc->lvKeepType = 1;
#endif // DEBUG
+ }
+ }
+ else if (varTypeIsSIMD(varDsc) && (genTypeSize(tree->TypeGet()) == genTypeSize(varDsc)))
+ {
+ assert(tree->AsLclFld()->GetLclOffs() == 0);
+ tree->gtType = varDsc->TypeGet();
+ tree->ChangeOper(GT_LCL_VAR);
+ JITDUMP("Replacing GT_LCL_FLD of struct with local var V%02u\n", lclNum);
}
}
}
@@ -17576,6 +17583,16 @@ bool Compiler::fgMorphCombineSIMDFieldAssignments(BasicBlock* block, Statement*
dstNode = originalLHS;
dstNode->gtType = simdType;
dstNode->AsLclFld()->SetFieldSeq(FieldSeqStore::NotAField());
+
+ // This may have changed a partial local field into full local field
+ if (dstNode->IsPartialLclFld(this))
+ {
+ dstNode->gtFlags |= GTF_VAR_USEASG;
+ }
+ else
+ {
+ dstNode->gtFlags &= ~GTF_VAR_USEASG;
+ }
}
else
{
diff --git a/src/coreclr/src/jit/objectalloc.cpp b/src/coreclr/src/jit/objectalloc.cpp
index e5cccf2eb3cc5a..79a2685d601f9f 100644
--- a/src/coreclr/src/jit/objectalloc.cpp
+++ b/src/coreclr/src/jit/objectalloc.cpp
@@ -510,8 +510,10 @@ unsigned int ObjectAllocator::MorphAllocObjNodeIntoStackAlloc(GenTreeAllocObj* a
const int unsafeValueClsCheck = true;
comp->lvaSetStruct(lclNum, allocObj->gtAllocObjClsHnd, unsafeValueClsCheck);
- // Initialize the object memory if necessary
- if (comp->fgStructTempNeedsExplicitZeroInit(comp->lvaTable + lclNum, block))
+ // Initialize the object memory if necessary.
+ bool bbInALoop = (block->bbFlags & BBF_BACKWARD_JUMP) != 0;
+ bool bbIsReturn = block->bbJumpKind == BBJ_RETURN;
+ if (comp->fgVarNeedsExplicitZeroInit(comp->lvaGetDesc(lclNum), bbInALoop, bbIsReturn))
{
//------------------------------------------------------------------------
// STMTx (IL 0x... ???)
diff --git a/src/coreclr/src/jit/optcse.cpp b/src/coreclr/src/jit/optcse.cpp
index cb106f4467f8bb..4a9a40541304c6 100644
--- a/src/coreclr/src/jit/optcse.cpp
+++ b/src/coreclr/src/jit/optcse.cpp
@@ -1664,7 +1664,7 @@ class CSE_Heuristic
largeFrame = true;
break; // early out, we don't need to keep increasing frameSize
}
-#elif _TARGET_ARM32
+#elif defined(TARGET_ARM)
if (frameSize > 0x0400)
{
// We likely have a large stack frame.
@@ -1679,7 +1679,7 @@ class CSE_Heuristic
hugeFrame = true;
break; // early out, we don't need to keep increasing frameSize
}
-#elif TARGET_ARM64
+#elif defined(TARGET_ARM64)
if (frameSize > 0x1000)
{
// We likely have a large stack frame.
diff --git a/src/coreclr/src/jit/reglist.h b/src/coreclr/src/jit/reglist.h
index 58b02b011cac39..16239b81cd8ef2 100644
--- a/src/coreclr/src/jit/reglist.h
+++ b/src/coreclr/src/jit/reglist.h
@@ -13,6 +13,6 @@
typedef TinyArray regList;
#else
// The regList is unused for all other targets.
-#endif // _TARGET_*
+#endif // TARGET*
#endif // REGLIST_H
diff --git a/src/coreclr/src/jit/simd.cpp b/src/coreclr/src/jit/simd.cpp
index 6a25c9ef35586c..1d7b9bf7443a92 100644
--- a/src/coreclr/src/jit/simd.cpp
+++ b/src/coreclr/src/jit/simd.cpp
@@ -438,7 +438,7 @@ var_types Compiler::getBaseTypeAndSizeOfSIMDType(CORINFO_CLASS_HANDLE typeHnd, u
JITDUMP(" Known type Vector256\n");
}
else
-#endif // defined(_TARGET_XARCH)
+#endif // defined(TARGET_XARCH)
if (typeHnd == m_simdHandleCache->Vector128FloatHandle)
{
simdBaseType = TYP_FLOAT;
@@ -1763,7 +1763,7 @@ GenTree* Compiler::impSIMDAbs(CORINFO_CLASS_HANDLE typeHnd, var_types baseType,
{
retVal = gtNewSIMDNode(simdType, op1, SIMDIntrinsicAbs, baseType, size);
}
-#else // !defined(_TARGET_XARCH)_ && !defined(TARGET_ARM64)
+#else // !defined(TARGET_XARCH)_ && !defined(TARGET_ARM64)
assert(!"Abs intrinsic on non-xarch target not implemented");
#endif // !TARGET_XARCH
diff --git a/src/coreclr/src/jit/ssabuilder.cpp b/src/coreclr/src/jit/ssabuilder.cpp
index 0ca9276038147d..53cffb67c9e341 100644
--- a/src/coreclr/src/jit/ssabuilder.cpp
+++ b/src/coreclr/src/jit/ssabuilder.cpp
@@ -772,6 +772,7 @@ void SsaBuilder::RenameDef(GenTreeOp* asgNode, BasicBlock* block)
}
else
{
+ assert((lclNode->gtFlags & GTF_VAR_USEASG) == 0);
lclNode->SetSsaNum(ssaNum);
}
diff --git a/src/coreclr/src/jit/target.h b/src/coreclr/src/jit/target.h
index cab9272052a9b6..117a3e6df2ba5c 100644
--- a/src/coreclr/src/jit/target.h
+++ b/src/coreclr/src/jit/target.h
@@ -3,8 +3,8 @@
// See the LICENSE file in the project root for more information.
/*****************************************************************************/
-#ifndef _TARGET_H_
-#define _TARGET_H_
+#ifndef TARGET_H_
+#define TARGET_H_
#if defined(FEATURE_CORECLR) && defined(TARGET_UNIX)
#define FEATURE_VARARG 0
@@ -1986,5 +1986,5 @@ C_ASSERT(sizeof(target_size_t) == TARGET_POINTER_SIZE);
C_ASSERT(sizeof(target_ssize_t) == TARGET_POINTER_SIZE);
/*****************************************************************************/
-#endif // _TARGET_H_
+#endif // TARGET_H_
/*****************************************************************************/
diff --git a/src/coreclr/src/jit/unwind.cpp b/src/coreclr/src/jit/unwind.cpp
index 96c8a98fd5da43..dff2df668bc5b2 100644
--- a/src/coreclr/src/jit/unwind.cpp
+++ b/src/coreclr/src/jit/unwind.cpp
@@ -426,8 +426,8 @@ UNATIVE_OFFSET Compiler::unwindGetCurrentOffset(FuncInfoDsc* func)
// See unwindX86.cpp
-#else // _TARGET_*
+#else // TARGET*
#error Unsupported or unset target architecture
-#endif // _TARGET_*
+#endif // TARGET*
diff --git a/src/coreclr/src/jit/utils.cpp b/src/coreclr/src/jit/utils.cpp
index 7ac15135280748..d493c991e3a995 100644
--- a/src/coreclr/src/jit/utils.cpp
+++ b/src/coreclr/src/jit/utils.cpp
@@ -336,9 +336,9 @@ void dspRegMask(regMaskTP regMask, size_t minSiz)
}
#elif defined(TARGET_X86)
// No register ranges
-#else // _TARGET_*
+#else // TARGET*
#error Unsupported or unset target architecture
-#endif // _TARGET_*
+#endif // TARGET*
}
#if defined(TARGET_ARM64)
diff --git a/src/coreclr/src/jit/valuenum.cpp b/src/coreclr/src/jit/valuenum.cpp
index d8038937c1b6ff..2509bb1912ec79 100644
--- a/src/coreclr/src/jit/valuenum.cpp
+++ b/src/coreclr/src/jit/valuenum.cpp
@@ -6558,18 +6558,17 @@ void Compiler::fgValueNumberBlockAssignment(GenTree* tree)
{
if (srcAddrFuncApp.m_func == VNF_PtrToStatic)
{
- var_types indType = lclVarTree->TypeGet();
- ValueNum fieldSeqVN = srcAddrFuncApp.m_args[0];
-
+ var_types indType = lclVarTree->TypeGet();
+ ValueNum fieldSeqVN = srcAddrFuncApp.m_args[0];
+ FieldSeqNode* fldSeqForStaticVar = vnStore->FieldSeqVNToFieldSeq(fieldSeqVN);
+#ifdef DEBUG
FieldSeqNode* zeroOffsetFldSeq = nullptr;
if (GetZeroOffsetFieldMap()->Lookup(srcAddr, &zeroOffsetFldSeq))
{
- fieldSeqVN =
- vnStore->FieldSeqVNAppend(fieldSeqVN, vnStore->VNForFieldSeq(zeroOffsetFldSeq));
+ // Check that the zero offset field seq was attached for `srcAddr`.
+ assert(fldSeqForStaticVar->GetTail() == zeroOffsetFldSeq);
}
-
- FieldSeqNode* fldSeqForStaticVar = vnStore->FieldSeqVNToFieldSeq(fieldSeqVN);
-
+#endif
if (fldSeqForStaticVar != FieldSeqStore::NotAField())
{
// We model statics as indices into GcHeap (which is a subset of ByrefExposed).
diff --git a/src/coreclr/src/libraries-native/CMakeLists.txt b/src/coreclr/src/libraries-native/CMakeLists.txt
index 4835c645261e41..aaf7f9bbbb7ae1 100644
--- a/src/coreclr/src/libraries-native/CMakeLists.txt
+++ b/src/coreclr/src/libraries-native/CMakeLists.txt
@@ -1,5 +1,17 @@
set(CMAKE_INCLUDE_CURRENT_DIR ON)
+set(GLOBALIZATION_NATIVE_DIR ${CLR_REPO_ROOT_DIR}/src/libraries/Native/Unix/System.Globalization.Native)
-if(CLR_CMAKE_HOST_UNIX AND NOT CLR_CROSS_COMPONENTS_BUILD)
- add_subdirectory(${CLR_REPO_ROOT_DIR}/src/libraries/Native/Unix/System.Globalization.Native System.Globalization.Native)
+# Suppress exporting of the PAL APIs
+add_definitions(-DPALEXPORT=)
+
+if(CLR_CMAKE_HOST_UNIX)
+ include_directories("${CLR_REPO_ROOT_DIR}/src/libraries/Native/Unix/Common")
+ include_directories("${GLOBALIZATION_NATIVE_DIR}")
+
+ add_subdirectory(${GLOBALIZATION_NATIVE_DIR} System.Globalization.Native)
endif()
+
+add_library(libraries-native
+ STATIC
+ entrypoints.c
+)
diff --git a/src/coreclr/src/libraries-native/entrypoints.c b/src/coreclr/src/libraries-native/entrypoints.c
new file mode 100644
index 00000000000000..75c5b7311b1570
--- /dev/null
+++ b/src/coreclr/src/libraries-native/entrypoints.c
@@ -0,0 +1,67 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#ifdef TARGET_UNIX
+
+#include "pal_types.h"
+
+typedef uint16_t UChar;
+
+// Include System.Globalization.Native headers
+#include "pal_calendarData.h"
+#include "pal_casing.h"
+#include "pal_collation.h"
+#include "pal_locale.h"
+#include "pal_localeNumberData.h"
+#include "pal_localeStringData.h"
+#include "pal_icushim.h"
+#include "pal_idna.h"
+#include "pal_normalization.h"
+#include "pal_timeZoneInfo.h"
+#endif // TARGET_UNIX
+
+#define FCFuncStart(name) extern const void* name[]; const void* name[] = {
+#define FCFuncEnd() (void*)0x01 /* FCFuncFlag_EndOfArray */ };
+
+#define QCFuncElement(name,impl) \
+ (void*)0x8 /* FCFuncFlag_QCall */, (void*)(impl), (void*)name,
+
+#ifdef TARGET_UNIX
+FCFuncStart(gPalGlobalizationNative)
+ QCFuncElement("ChangeCase", GlobalizationNative_ChangeCase)
+ QCFuncElement("ChangeCaseInvariant", GlobalizationNative_ChangeCaseInvariant)
+ QCFuncElement("ChangeCaseTurkish", GlobalizationNative_ChangeCaseTurkish)
+ QCFuncElement("CloseSortHandle", GlobalizationNative_CloseSortHandle)
+ QCFuncElement("CompareString", GlobalizationNative_CompareString)
+ QCFuncElement("CompareStringOrdinalIgnoreCase", GlobalizationNative_CompareStringOrdinalIgnoreCase)
+ QCFuncElement("EndsWith", GlobalizationNative_EndsWith)
+ QCFuncElement("EnumCalendarInfo", GlobalizationNative_EnumCalendarInfo)
+ QCFuncElement("GetCalendarInfo", GlobalizationNative_GetCalendarInfo)
+ QCFuncElement("GetCalendars", GlobalizationNative_GetCalendars)
+ QCFuncElement("GetDefaultLocaleName", GlobalizationNative_GetDefaultLocaleName)
+ QCFuncElement("GetICUVersion", GlobalizationNative_GetICUVersion)
+ QCFuncElement("GetJapaneseEraStartDate", GlobalizationNative_GetJapaneseEraStartDate)
+ QCFuncElement("GetLatestJapaneseEra", GlobalizationNative_GetLatestJapaneseEra)
+ QCFuncElement("GetLocaleInfoGroupingSizes", GlobalizationNative_GetLocaleInfoGroupingSizes)
+ QCFuncElement("GetLocaleInfoInt", GlobalizationNative_GetLocaleInfoInt)
+ QCFuncElement("GetLocaleInfoString", GlobalizationNative_GetLocaleInfoString)
+ QCFuncElement("GetLocaleName", GlobalizationNative_GetLocaleName)
+ QCFuncElement("GetLocales", GlobalizationNative_GetLocales)
+ QCFuncElement("GetLocaleTimeFormat", GlobalizationNative_GetLocaleTimeFormat)
+ QCFuncElement("GetSortHandle", GlobalizationNative_GetSortHandle)
+ QCFuncElement("GetSortKey", GlobalizationNative_GetSortKey)
+ QCFuncElement("GetSortVersion", GlobalizationNative_GetSortVersion)
+ QCFuncElement("GetTimeZoneDisplayName", GlobalizationNative_GetTimeZoneDisplayName)
+ QCFuncElement("IndexOf", GlobalizationNative_IndexOf)
+ QCFuncElement("IndexOfOrdinalIgnoreCase", GlobalizationNative_IndexOfOrdinalIgnoreCase)
+ QCFuncElement("IsNormalized", GlobalizationNative_IsNormalized)
+ QCFuncElement("IsPredefinedLocale", GlobalizationNative_IsPredefinedLocale)
+ QCFuncElement("LastIndexOf", GlobalizationNative_LastIndexOf)
+ QCFuncElement("LoadICU", GlobalizationNative_LoadICU)
+ QCFuncElement("NormalizeString", GlobalizationNative_NormalizeString)
+ QCFuncElement("StartsWith", GlobalizationNative_StartsWith)
+ QCFuncElement("ToAscii", GlobalizationNative_ToAscii)
+ QCFuncElement("ToUnicode", GlobalizationNative_ToUnicode)
+FCFuncEnd()
+#endif // TARGET_UNIX
diff --git a/src/coreclr/src/md/ceefilegen/ceesectionstring.cpp b/src/coreclr/src/md/ceefilegen/ceesectionstring.cpp
index 073e6eeca8672a..4a0af7970d2010 100644
--- a/src/coreclr/src/md/ceefilegen/ceesectionstring.cpp
+++ b/src/coreclr/src/md/ceefilegen/ceesectionstring.cpp
@@ -66,7 +66,7 @@ CeeSectionString::~CeeSectionString()
StringTableEntry* CeeSectionString::createEntry(__in_z LPWSTR target, ULONG hashId)
{
- StringTableEntry *entry = new StringTableEntry;
+ StringTableEntry *entry = new (nothrow) StringTableEntry;
if (!entry)
return NULL;
entry->m_next = NULL;
diff --git a/src/coreclr/src/md/compiler/filtermanager.cpp b/src/coreclr/src/md/compiler/filtermanager.cpp
index 9a5033fb3f102f..3648c5c58bd72f 100644
--- a/src/coreclr/src/md/compiler/filtermanager.cpp
+++ b/src/coreclr/src/md/compiler/filtermanager.cpp
@@ -135,7 +135,7 @@ HRESULT FilterManager::MarkAssembly(mdAssembly as)
{
HRESULT hr = NOERROR;
- if (hasAssemblyBeenMarked == false)
+ if (!hasAssemblyBeenMarked)
{
hasAssemblyBeenMarked = true;
IfFailGo( MarkCustomAttributesWithParentToken(as) );
@@ -153,7 +153,7 @@ HRESULT FilterManager::MarkModule(mdModule mo)
{
HRESULT hr = NOERROR;
- if (hasModuleBeenMarked == false)
+ if (!hasModuleBeenMarked)
{
hasModuleBeenMarked = true;
IfFailGo( MarkCustomAttributesWithParentToken(mo) );
diff --git a/src/coreclr/src/pal/inc/pal.h b/src/coreclr/src/pal/inc/pal.h
index 7546046ef41b60..9cfe2e8495ab5c 100644
--- a/src/coreclr/src/pal/inc/pal.h
+++ b/src/coreclr/src/pal/inc/pal.h
@@ -2377,11 +2377,13 @@ typedef struct _CRITICAL_SECTION {
LONG LockCount;
LONG RecursionCount;
HANDLE OwningThread;
- HANDLE LockSemaphore;
ULONG_PTR SpinCount;
+#ifdef PAL_TRACK_CRITICAL_SECTIONS_DATA
BOOL bInternal;
+#endif // PAL_TRACK_CRITICAL_SECTIONS_DATA
volatile DWORD dwInitState;
+
union CSNativeDataStorage
{
BYTE rgNativeDataStorage[PAL_CS_NATIVE_DATA_SIZE];
diff --git a/src/coreclr/src/pal/inc/rt/palrt.h b/src/coreclr/src/pal/inc/rt/palrt.h
index d7245d934a5e7d..0de8be16cea27e 100644
--- a/src/coreclr/src/pal/inc/rt/palrt.h
+++ b/src/coreclr/src/pal/inc/rt/palrt.h
@@ -1173,37 +1173,6 @@ typedef OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK *POUT_OF_PROCESS_FUNCTION_TABLE_C
#define OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK_EXPORT_NAME \
"OutOfProcessFunctionTableCallback"
-// #if !defined(TARGET_OSX)
-// typedef LONG (*PEXCEPTION_ROUTINE)(
- // IN PEXCEPTION_POINTERS pExceptionPointers,
- // IN LPVOID lpvParam);
-
-// #define DISPATCHER_CONTEXT LPVOID
-
-// #else // defined(TARGET_OSX)
-
-//
-// Define unwind history table structure.
-//
-
-#define UNWIND_HISTORY_TABLE_SIZE 12
-
-typedef struct _UNWIND_HISTORY_TABLE_ENTRY {
- DWORD64 ImageBase;
- PRUNTIME_FUNCTION FunctionEntry;
-} UNWIND_HISTORY_TABLE_ENTRY, *PUNWIND_HISTORY_TABLE_ENTRY;
-
-typedef struct _UNWIND_HISTORY_TABLE {
- DWORD Count;
- BYTE LocalHint;
- BYTE GlobalHint;
- BYTE Search;
- BYTE Once;
- DWORD64 LowAddress;
- DWORD64 HighAddress;
- UNWIND_HISTORY_TABLE_ENTRY Entry[UNWIND_HISTORY_TABLE_SIZE];
-} UNWIND_HISTORY_TABLE, *PUNWIND_HISTORY_TABLE;
-
typedef
EXCEPTION_DISPOSITION
(*PEXCEPTION_ROUTINE) (
@@ -1224,7 +1193,7 @@ typedef struct _DISPATCHER_CONTEXT {
PCONTEXT ContextRecord;
PEXCEPTION_ROUTINE LanguageHandler;
PVOID HandlerData;
- PUNWIND_HISTORY_TABLE HistoryTable;
+ PVOID HistoryTable;
DWORD ScopeIndex;
BOOLEAN ControlPcIsUnwound;
PBYTE NonVolatileRegisters;
@@ -1242,7 +1211,7 @@ typedef struct _DISPATCHER_CONTEXT {
PCONTEXT ContextRecord;
PEXCEPTION_ROUTINE LanguageHandler;
PVOID HandlerData;
- PUNWIND_HISTORY_TABLE HistoryTable;
+ PVOID HistoryTable;
ULONG64 ScopeIndex;
BOOLEAN ControlPcIsUnwound;
PBYTE NonVolatileRegisters;
@@ -1260,7 +1229,7 @@ typedef struct _DISPATCHER_CONTEXT {
PCONTEXT ContextRecord;
PEXCEPTION_ROUTINE LanguageHandler;
PVOID HandlerData;
- PUNWIND_HISTORY_TABLE HistoryTable;
+ PVOID HistoryTable;
} DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT;
#elif defined(HOST_X86)
@@ -1275,7 +1244,7 @@ typedef struct _DISPATCHER_CONTEXT {
PCONTEXT ContextRecord;
PEXCEPTION_ROUTINE LanguageHandler;
PVOID HandlerData;
- PUNWIND_HISTORY_TABLE HistoryTable;
+ PVOID HistoryTable;
BOOLEAN ControlPcIsUnwound;
} DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT;
diff --git a/src/coreclr/src/pal/src/arch/amd64/signalhandlerhelper.cpp b/src/coreclr/src/pal/src/arch/amd64/signalhandlerhelper.cpp
index 28232251b13187..61eba90008d959 100644
--- a/src/coreclr/src/pal/src/arch/amd64/signalhandlerhelper.cpp
+++ b/src/coreclr/src/pal/src/arch/amd64/signalhandlerhelper.cpp
@@ -13,10 +13,11 @@ SET_DEFAULT_DEBUG_CHANNEL(EXCEPT); // some headers have code with asserts, so do
/*++
Function :
- signal_handler_worker
+ ExecuteHandlerOnCustomStack
- Handles signal on the original stack where the signal occured.
- Invoked via setcontext.
+ Execute signal handler on a custom stack, the current stack pointer is specified by the customSp
+ If the customSp is 0, then the handler is executed on the original stack where the signal was fired.
+ It installs a fake stack frame to enable stack unwinding to the signal source location.
Parameters :
POSIX signal handler parameter list ("man sigaction" for details)
@@ -24,13 +25,19 @@ Parameters :
(no return value)
--*/
-void ExecuteHandlerOnOriginalStack(int code, siginfo_t *siginfo, void *context, SignalHandlerWorkerReturnPoint* returnPoint)
+void ExecuteHandlerOnCustomStack(int code, siginfo_t *siginfo, void *context, size_t customSp, SignalHandlerWorkerReturnPoint* returnPoint)
{
ucontext_t *ucontext = (ucontext_t *)context;
size_t faultSp = (size_t)MCREG_Rsp(ucontext->uc_mcontext);
_ASSERTE(IS_ALIGNED(faultSp, 8));
+ if (customSp == 0)
+ {
+ // preserve 128 bytes long red zone and align stack pointer
+ customSp = ALIGN_DOWN(faultSp - 128, 16);
+ }
+
size_t fakeFrameReturnAddress;
if (IS_ALIGNED(faultSp, 16))
@@ -42,8 +49,7 @@ void ExecuteHandlerOnOriginalStack(int code, siginfo_t *siginfo, void *context,
fakeFrameReturnAddress = (size_t)SignalHandlerWorkerReturnOffset8 + (size_t)CallSignalHandlerWrapper8;
}
- // preserve 128 bytes long red zone and align stack pointer
- size_t* sp = (size_t*)ALIGN_DOWN(faultSp - 128, 16);
+ size_t* sp = (size_t*)customSp;
// Build fake stack frame to enable the stack unwinder to unwind from signal_handler_worker to the faulting instruction
*--sp = (size_t)MCREG_Rip(ucontext->uc_mcontext);
@@ -51,7 +57,7 @@ void ExecuteHandlerOnOriginalStack(int code, siginfo_t *siginfo, void *context,
size_t fp = (size_t)sp;
*--sp = fakeFrameReturnAddress;
- // Switch the current context to the signal_handler_worker and the original stack
+ // Switch the current context to the signal_handler_worker and the custom stack
CONTEXT context2;
RtlCaptureContext(&context2);
diff --git a/src/coreclr/src/pal/src/arch/arm/signalhandlerhelper.cpp b/src/coreclr/src/pal/src/arch/arm/signalhandlerhelper.cpp
index eac3b29b81df8b..9c6dda1f2fb7b5 100644
--- a/src/coreclr/src/pal/src/arch/arm/signalhandlerhelper.cpp
+++ b/src/coreclr/src/pal/src/arch/arm/signalhandlerhelper.cpp
@@ -13,10 +13,11 @@ SET_DEFAULT_DEBUG_CHANNEL(EXCEPT); // some headers have code with asserts, so do
/*++
Function :
- signal_handler_worker
+ ExecuteHandlerOnCustomStack
- Handles signal on the original stack where the signal occured.
- Invoked via setcontext.
+ Execute signal handler on a custom stack, the current stack pointer is specified by the customSp
+ If the customSp is 0, then the handler is executed on the original stack where the signal was fired.
+ It installs a fake stack frame to enable stack unwinding to the signal source location.
Parameters :
POSIX signal handler parameter list ("man sigaction" for details)
@@ -24,13 +25,19 @@ Parameters :
(no return value)
--*/
-void ExecuteHandlerOnOriginalStack(int code, siginfo_t *siginfo, void *context, SignalHandlerWorkerReturnPoint* returnPoint)
+void ExecuteHandlerOnCustomStack(int code, siginfo_t *siginfo, void *context, size_t customSp, SignalHandlerWorkerReturnPoint* returnPoint)
{
ucontext_t *ucontext = (ucontext_t *)context;
size_t faultSp = (size_t)MCREG_Sp(ucontext->uc_mcontext);
_ASSERTE(IS_ALIGNED(faultSp, 4));
+ if (customSp == 0)
+ {
+ // preserve 8 bytes long red zone and align stack pointer
+ customSp = ALIGN_DOWN(faultSp - 8, 8);
+ }
+
size_t fakeFrameReturnAddress;
if (IS_ALIGNED(faultSp, 8))
@@ -42,8 +49,7 @@ void ExecuteHandlerOnOriginalStack(int code, siginfo_t *siginfo, void *context,
fakeFrameReturnAddress = (size_t)SignalHandlerWorkerReturnOffset4 + (size_t)CallSignalHandlerWrapper4;
}
- // preserve 8 bytes long red zone and align stack pointer
- size_t* sp = (size_t*)ALIGN_DOWN(faultSp - 8, 8);
+ size_t* sp = (size_t*)customSp;
#ifndef __linux__
size_t cpsr = (size_t)MCREG_Cpsr(ucontext->uc_mcontext);
diff --git a/src/coreclr/src/pal/src/arch/arm64/signalhandlerhelper.cpp b/src/coreclr/src/pal/src/arch/arm64/signalhandlerhelper.cpp
index b52e8a64d19af1..524bd11b364f8d 100644
--- a/src/coreclr/src/pal/src/arch/arm64/signalhandlerhelper.cpp
+++ b/src/coreclr/src/pal/src/arch/arm64/signalhandlerhelper.cpp
@@ -13,10 +13,11 @@ SET_DEFAULT_DEBUG_CHANNEL(EXCEPT); // some headers have code with asserts, so do
/*++
Function :
- signal_handler_worker
+ ExecuteHandlerOnCustomStack
- Handles signal on the original stack where the signal occured.
- Invoked via setcontext.
+ Execute signal handler on a custom stack, the current stack pointer is specified by the customSp
+ If the customSp is 0, then the handler is executed on the original stack where the signal was fired.
+ It installs a fake stack frame to enable stack unwinding to the signal source location.
Parameters :
POSIX signal handler parameter list ("man sigaction" for details)
@@ -24,12 +25,18 @@ Parameters :
(no return value)
--*/
-void ExecuteHandlerOnOriginalStack(int code, siginfo_t *siginfo, void *context, SignalHandlerWorkerReturnPoint* returnPoint)
+void ExecuteHandlerOnCustomStack(int code, siginfo_t *siginfo, void *context, size_t customSp, SignalHandlerWorkerReturnPoint* returnPoint)
{
ucontext_t *ucontext = (ucontext_t *)context;
size_t faultSp = (size_t)MCREG_Sp(ucontext->uc_mcontext);
_ASSERTE(IS_ALIGNED(faultSp, 8));
+ if (customSp == 0)
+ {
+ // preserve 128 bytes long red zone and align stack pointer
+ customSp = ALIGN_DOWN(faultSp - 128, 16);
+ }
+
size_t fakeFrameReturnAddress;
if (IS_ALIGNED(faultSp, 16))
@@ -42,7 +49,7 @@ void ExecuteHandlerOnOriginalStack(int code, siginfo_t *siginfo, void *context,
}
// preserve 128 bytes long red zone and align stack pointer
- size_t* sp = (size_t*)ALIGN_DOWN(faultSp - 128, 16);
+ size_t* sp = (size_t*)customSp;
// Build fake stack frame to enable the stack unwinder to unwind from signal_handler_worker to the faulting instruction
// pushed LR
diff --git a/src/coreclr/src/pal/src/arch/i386/signalhandlerhelper.cpp b/src/coreclr/src/pal/src/arch/i386/signalhandlerhelper.cpp
index 8e23099193028b..16e527a1ebcb83 100644
--- a/src/coreclr/src/pal/src/arch/i386/signalhandlerhelper.cpp
+++ b/src/coreclr/src/pal/src/arch/i386/signalhandlerhelper.cpp
@@ -13,10 +13,11 @@ SET_DEFAULT_DEBUG_CHANNEL(EXCEPT); // some headers have code with asserts, so do
/*++
Function :
- signal_handler_worker
+ ExecuteHandlerOnCustomStack
- Handles signal on the original stack where the signal occured.
- Invoked via setcontext.
+ Execute signal handler on a custom stack, the current stack pointer is specified by the customSp
+ If the customSp is 0, then the handler is executed on the original stack where the signal was fired.
+ It installs a fake stack frame to enable stack unwinding to the signal source location.
Parameters :
POSIX signal handler parameter list ("man sigaction" for details)
@@ -24,13 +25,18 @@ Parameters :
(no return value)
--*/
-void ExecuteHandlerOnOriginalStack(int code, siginfo_t *siginfo, void *context, SignalHandlerWorkerReturnPoint* returnPoint)
+void ExecuteHandlerOnCustomStack(int code, siginfo_t *siginfo, void *context, size_t customSp, SignalHandlerWorkerReturnPoint* returnPoint)
{
ucontext_t *ucontext = (ucontext_t *)context;
size_t faultSp = (size_t)MCREG_Esp(ucontext->uc_mcontext);
_ASSERTE(IS_ALIGNED(faultSp, 4));
+ if (customSp == 0)
+ {
+ customSp = ALIGN_DOWN(faultSp, 16);
+ }
+
size_t fakeFrameReturnAddress;
switch (faultSp & 0xc)
@@ -49,7 +55,7 @@ void ExecuteHandlerOnOriginalStack(int code, siginfo_t *siginfo, void *context,
break;
}
- size_t* sp = (size_t*)ALIGN_DOWN(faultSp, 16);
+ size_t* sp = (size_t*)customSp;
// Build fake stack frame to enable the stack unwinder to unwind from signal_handler_worker to the faulting instruction
*--sp = (size_t)MCREG_Eip(ucontext->uc_mcontext);
diff --git a/src/coreclr/src/pal/src/configure.cmake b/src/coreclr/src/pal/src/configure.cmake
index f426d0764118ee..46d88b0915492e 100644
--- a/src/coreclr/src/pal/src/configure.cmake
+++ b/src/coreclr/src/pal/src/configure.cmake
@@ -126,7 +126,6 @@ check_function_exists(semget HAS_SYSV_SEMAPHORES)
check_function_exists(pthread_mutex_init HAS_PTHREAD_MUTEXES)
check_function_exists(ttrace HAVE_TTRACE)
check_function_exists(pipe2 HAVE_PIPE2)
-check_function_exists(process_vm_readv HAVE_PROCESS_VM_READV)
check_cxx_source_compiles("
#include
diff --git a/src/coreclr/src/pal/src/exception/seh.cpp b/src/coreclr/src/pal/src/exception/seh.cpp
index ef95f5e354a3d1..e0ebff145b893d 100644
--- a/src/coreclr/src/pal/src/exception/seh.cpp
+++ b/src/coreclr/src/pal/src/exception/seh.cpp
@@ -28,6 +28,7 @@ Module Name:
#include "pal/process.h"
#include "pal/malloc.hpp"
#include "pal/signal.hpp"
+#include "pal/virtual.h"
#if HAVE_MACH_EXCEPTIONS
#include "machexception.h"
@@ -268,14 +269,16 @@ SEHProcessException(PAL_SEHException* exception)
// Check if the failed access has hit a stack guard page. In such case, it
// was a stack probe that detected that there is not enough stack left.
void* stackLimit = CPalThread::GetStackLimit();
- void* stackGuard = (void*)((size_t)stackLimit - getpagesize());
+ void* stackOverflowBottom = (void*)((size_t)stackLimit - GetVirtualPageSize());
+ // On some versions of glibc / platforms the stackLimit is an address of the guard page, on some
+ // it is right above the guard page.
+ // So consider SIGSEGV in one page above and below stack limit to be stack overflow.
+ void* stackOverflowTop = (void*)((size_t)stackLimit + GetVirtualPageSize());
void* violationAddr = (void*)exceptionRecord->ExceptionInformation[1];
- if ((violationAddr >= stackGuard) && (violationAddr < stackLimit))
+
+ if ((violationAddr >= stackOverflowBottom) && (violationAddr < stackOverflowTop))
{
- // The exception happened in the page right below the stack limit,
- // so it is a stack overflow
- (void)write(STDERR_FILENO, StackOverflowMessage, sizeof(StackOverflowMessage) - 1);
- PROCAbort();
+ exceptionRecord->ExceptionCode = EXCEPTION_STACK_OVERFLOW;
}
}
diff --git a/src/coreclr/src/pal/src/exception/signal.cpp b/src/coreclr/src/pal/src/exception/signal.cpp
index 49fdec8db89e40..d6d8256610e5c2 100644
--- a/src/coreclr/src/pal/src/exception/signal.cpp
+++ b/src/coreclr/src/pal/src/exception/signal.cpp
@@ -113,6 +113,9 @@ struct sigaction g_previous_activation;
// Offset of the local variable containing pointer to windows style context in the common_signal_handler function.
// This offset is relative to the frame pointer.
int g_common_signal_handler_context_locvar_offset = 0;
+
+// TOP of special stack for handling stack overflow
+volatile void* g_stackOverflowHandlerStack = NULL;
#endif // !HAVE_MACH_EXCEPTIONS
/* public function definitions ************************************************/
@@ -175,6 +178,26 @@ BOOL SEHInitializeSignals(CorUnix::CPalThread *pthrCurrent, DWORD flags)
{
return FALSE;
}
+
+ // Allocate the minimal stack necessary for handling stack overflow
+ int stackOverflowStackSize = ALIGN_UP(sizeof(SignalHandlerWorkerReturnPoint), 16) + 7 * 4096;
+ // Align the size to virtual page size and add one virtual page as a stack guard
+ stackOverflowStackSize = ALIGN_UP(stackOverflowStackSize, GetVirtualPageSize()) + GetVirtualPageSize();
+ g_stackOverflowHandlerStack = mmap(NULL, stackOverflowStackSize, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_STACK | MAP_PRIVATE, -1, 0);
+ if (g_stackOverflowHandlerStack == MAP_FAILED)
+ {
+ return FALSE;
+ }
+
+ // create a guard page for the alternate stack
+ int st = mprotect((void*)g_stackOverflowHandlerStack, GetVirtualPageSize(), PROT_NONE);
+ if (st != 0)
+ {
+ munmap((void*)g_stackOverflowHandlerStack, stackOverflowStackSize);
+ return FALSE;
+ }
+
+ g_stackOverflowHandlerStack = (void*)((size_t)g_stackOverflowHandlerStack + stackOverflowStackSize);
}
/* The default action for SIGPIPE is process termination.
@@ -430,6 +453,41 @@ bool IsRunningOnAlternateStack(void *context)
return isRunningOnAlternateStack;
}
+/*++
+Function :
+ SwitchStackAndExecuteHandler
+
+ Switch to the stack specified by the sp argument
+
+Parameters :
+ POSIX signal handler parameter list ("man sigaction" for details)
+ sp - stack pointer of the stack to execute the handler on.
+ If sp == 0, execute it on the original stack where the signal has occured.
+Return :
+ The return value from the signal handler
+--*/
+static bool SwitchStackAndExecuteHandler(int code, siginfo_t *siginfo, void *context, size_t sp)
+{
+ // Establish a return point in case the common_signal_handler returns
+
+ volatile bool contextInitialization = true;
+
+ void *ptr = alloca(sizeof(SignalHandlerWorkerReturnPoint) + alignof(SignalHandlerWorkerReturnPoint) - 1);
+ SignalHandlerWorkerReturnPoint *pReturnPoint = (SignalHandlerWorkerReturnPoint *)ALIGN_UP(ptr, alignof(SignalHandlerWorkerReturnPoint));
+ RtlCaptureContext(&pReturnPoint->context);
+
+ // When the signal handler worker completes, it uses setcontext to return to this point
+
+ if (contextInitialization)
+ {
+ contextInitialization = false;
+ ExecuteHandlerOnCustomStack(code, siginfo, context, sp, pReturnPoint);
+ _ASSERTE(FALSE); // The ExecuteHandlerOnCustomStack should never return
+ }
+
+ return pReturnPoint->returnFromHandler;
+}
+
/*++
Function :
sigsegv_handler
@@ -453,8 +511,30 @@ static void sigsegv_handler(int code, siginfo_t *siginfo, void *context)
// we have a stack overflow.
if ((failureAddress - (sp - GetVirtualPageSize())) < 2 * GetVirtualPageSize())
{
- (void)write(STDERR_FILENO, StackOverflowMessage, sizeof(StackOverflowMessage) - 1);
- PROCAbort();
+ if (GetCurrentPalThread())
+ {
+ size_t handlerStackTop = __sync_val_compare_and_swap((size_t*)&g_stackOverflowHandlerStack, (size_t)g_stackOverflowHandlerStack, 0);
+ if (handlerStackTop == 0)
+ {
+ // We have only one stack for handling stack overflow preallocated. We let only the first thread that hits stack overflow to
+ // run the exception handling code on that stack (which ends up just dumping the stack trace and aborting the process).
+ // Other threads are held spinning and sleeping here until the process exits.
+ while (true)
+ {
+ sleep(1);
+ }
+ }
+
+ if (SwitchStackAndExecuteHandler(code, siginfo, context, (size_t)handlerStackTop))
+ {
+ PROCAbort();
+ }
+ }
+ else
+ {
+ (void)write(STDERR_FILENO, StackOverflowMessage, sizeof(StackOverflowMessage) - 1);
+ PROCAbort();
+ }
}
// Now that we know the SIGSEGV didn't happen due to a stack overflow, execute the common
@@ -462,24 +542,7 @@ static void sigsegv_handler(int code, siginfo_t *siginfo, void *context)
if (GetCurrentPalThread() && IsRunningOnAlternateStack(context))
{
- // Establish a return point in case the common_signal_handler returns
-
- volatile bool contextInitialization = true;
-
- void *ptr = alloca(sizeof(SignalHandlerWorkerReturnPoint) + alignof(SignalHandlerWorkerReturnPoint) - 1);
- SignalHandlerWorkerReturnPoint *pReturnPoint = (SignalHandlerWorkerReturnPoint *)ALIGN_UP(ptr, alignof(SignalHandlerWorkerReturnPoint));
- RtlCaptureContext(&pReturnPoint->context);
-
- // When the signal handler worker completes, it uses setcontext to return to this point
-
- if (contextInitialization)
- {
- contextInitialization = false;
- ExecuteHandlerOnOriginalStack(code, siginfo, context, pReturnPoint);
- _ASSERTE(FALSE); // The ExecuteHandlerOnOriginalStack should never return
- }
-
- if (pReturnPoint->returnFromHandler)
+ if (SwitchStackAndExecuteHandler(code, siginfo, context, 0 /* sp */)) // sp == 0 indicates execution on the original stack
{
return;
}
@@ -692,7 +755,10 @@ PAL_ERROR InjectActivationInternal(CorUnix::CPalThread* pThread)
{
#ifdef INJECT_ACTIVATION_SIGNAL
int status = pthread_kill(pThread->GetPThreadSelf(), INJECT_ACTIVATION_SIGNAL);
- if (status != 0)
+ // We can get EAGAIN when printing stack overflow stack trace and when other threads hit
+ // stack overflow too. Those are held in the sigsegv_handler with blocked signals until
+ // the process exits.
+ if ((status != 0) && (status != EAGAIN))
{
// Failure to send the signal is fatal. There are only two cases when sending
// the signal can fail. First, if the signal ID is invalid and second,
diff --git a/src/coreclr/src/pal/src/include/pal/signal.hpp b/src/coreclr/src/pal/src/include/pal/signal.hpp
index 51b098809447a0..7b5e1d71407b1c 100644
--- a/src/coreclr/src/pal/src/include/pal/signal.hpp
+++ b/src/coreclr/src/pal/src/include/pal/signal.hpp
@@ -78,10 +78,11 @@ extern "C" void signal_handler_worker(int code, siginfo_t *siginfo, void *contex
/*++
Function :
- ExecuteHandlerOnOriginalStack
+ ExecuteHandlerOnCustomStack
- Executes signal_handler_worker on the original stack where the signal occured.
- It installs fake stack frame to enable stack unwinding to the signal source location.
+ Execute signal handler on a custom stack, the current stack pointer is specified by the customSp
+ If the customSp is 0, then the handler is executed on the original stack where the signal was fired.
+ It installs a fake stack frame to enable stack unwinding to the signal source location.
Parameters :
POSIX signal handler parameter list ("man sigaction" for details)
@@ -89,7 +90,7 @@ Parameters :
(no return value)
--*/
-void ExecuteHandlerOnOriginalStack(int code, siginfo_t *siginfo, void *context, SignalHandlerWorkerReturnPoint* returnPoint);
+void ExecuteHandlerOnCustomStack(int code, siginfo_t *siginfo, void *context, size_t sp, SignalHandlerWorkerReturnPoint* returnPoint);
#endif // !HAVE_MACH_EXCEPTIONS
diff --git a/src/coreclr/src/pal/src/locale/utf8.cpp b/src/coreclr/src/pal/src/locale/utf8.cpp
index f34df4fe992b2e..d263248bdf310d 100644
--- a/src/coreclr/src/pal/src/locale/utf8.cpp
+++ b/src/coreclr/src/pal/src/locale/utf8.cpp
@@ -335,7 +335,7 @@ class DecoderFallbackBuffer
else
{
// Low surrogate
- if (bHighSurrogate == false)
+ if (!bHighSurrogate)
throw ArgumentException("String 'chars' contains invalid Unicode code points.");
bHighSurrogate = false;
}
@@ -391,7 +391,7 @@ class DecoderFallbackBuffer
else
{
// Low surrogate
- if (bHighSurrogate == false)
+ if (!bHighSurrogate)
throw ArgumentException("String 'chars' contains invalid Unicode code points.");
bHighSurrogate = false;
}
diff --git a/src/coreclr/src/pal/src/misc/environ.cpp b/src/coreclr/src/pal/src/misc/environ.cpp
index f2538752f6456d..9fec8a33a2b41b 100644
--- a/src/coreclr/src/pal/src/misc/environ.cpp
+++ b/src/coreclr/src/pal/src/misc/environ.cpp
@@ -893,6 +893,55 @@ BOOL EnvironPutenv(const char* entry, BOOL deleteIfEmpty)
return result;
}
+
+/*++
+Function:
+ FindEnvVarValue
+
+Get the value of environment variable with the given name.
+Caller should take care of locking and releasing palEnvironment.
+
+Parameters
+
+ name
+ [in] The name of the environment variable to get.
+
+Return Value
+
+ A pointer to the value of the environment variable if it exists,
+ or nullptr otherwise.
+
+--*/
+char* FindEnvVarValue(const char* name)
+{
+ if (*name == '\0')
+ return nullptr;
+
+ for (int i = 0; palEnvironment[i] != nullptr; ++i)
+ {
+ const char* pch = name;
+ char* p = palEnvironment[i];
+
+ do
+ {
+ if (*pch == '\0')
+ {
+ if (*p == '=')
+ return p + 1;
+
+ if (*p == '\0') // no = sign -> empty value
+ return p;
+
+ break;
+ }
+ }
+ while (*pch++ == *p++);
+ }
+
+ return nullptr;
+}
+
+
/*++
Function:
EnvironGetenv
@@ -919,33 +968,11 @@ Return Value
--*/
char* EnvironGetenv(const char* name, BOOL copyValue)
{
- char *retValue = nullptr;
-
CPalThread * pthrCurrent = InternalGetCurrentThread();
InternalEnterCriticalSection(pthrCurrent, &gcsEnvironment);
-
- size_t nameLength = strlen(name);
- for (int i = 0; palEnvironment[i] != nullptr; ++i)
- {
- if (strncmp(palEnvironment[i], name, nameLength) == 0)
- {
- char *equalsSignPosition = palEnvironment[i] + nameLength;
-
- // If this is one of the variables which has no equals sign, we
- // treat the whole thing as name, so the value is an empty string.
- if (*equalsSignPosition == '\0')
- {
- retValue = (char *)"";
- break;
- }
- else if (*equalsSignPosition == '=')
- {
- retValue = equalsSignPosition + 1;
- break;
- }
- }
- }
-
+
+ char* retValue = FindEnvVarValue(name);
+
if ((retValue != nullptr) && copyValue)
{
retValue = strdup(retValue);
@@ -955,6 +982,7 @@ char* EnvironGetenv(const char* name, BOOL copyValue)
return retValue;
}
+
/*++
Function:
EnvironGetSystemEnvironment
diff --git a/src/coreclr/src/pal/src/misc/sysinfo.cpp b/src/coreclr/src/pal/src/misc/sysinfo.cpp
index dffcc63f32962f..7e9bf4b3b6e6fc 100644
--- a/src/coreclr/src/pal/src/misc/sysinfo.cpp
+++ b/src/coreclr/src/pal/src/misc/sysinfo.cpp
@@ -37,6 +37,10 @@ Revision History:
#error Either sysctl or sysconf is required for GetSystemInfo.
#endif
+#if HAVE_SYSCTLBYNAME
+#include
+#endif
+
#if HAVE_SYSINFO
#include
#endif
diff --git a/src/coreclr/src/pal/src/sync/cs.cpp b/src/coreclr/src/pal/src/sync/cs.cpp
index 138f971b0b3522..354550063c6449 100644
--- a/src/coreclr/src/pal/src/sync/cs.cpp
+++ b/src/coreclr/src/pal/src/sync/cs.cpp
@@ -158,10 +158,11 @@ typedef struct _PAL_CRITICAL_SECTION {
Volatile LockCount;
LONG RecursionCount;
SIZE_T OwningThread;
- HANDLE LockSemaphore;
ULONG_PTR SpinCount;
// Private Unix part
+#ifdef PAL_TRACK_CRITICAL_SECTIONS_DATA
BOOL fInternal;
+#endif // PAL_TRACK_CRITICAL_SECTIONS_DATA
Volatile cisInitState;
PAL_CRITICAL_SECTION_NATIVE_DATA csndNativeData;
} PAL_CRITICAL_SECTION, *PPAL_CRITICAL_SECTION, *LPPAL_CRITICAL_SECTION;
@@ -628,8 +629,6 @@ namespace CorUnix
pPalCriticalSection->RecursionCount = 0;
pPalCriticalSection->SpinCount = dwSpinCount;
pPalCriticalSection->OwningThread = 0;
- pPalCriticalSection->LockSemaphore = NULL;
- pPalCriticalSection->fInternal = fInternal;
#ifdef _DEBUG
CPalThread * pThread =
@@ -660,6 +659,7 @@ namespace CorUnix
}
#ifdef PAL_TRACK_CRITICAL_SECTIONS_DATA
+ pPalCriticalSection->fInternal = fInternal;
InterlockedIncrement(fInternal ?
&g_lPALCSInternalInitializeCount : &g_lPALCSInitializeCount);
#endif // PAL_TRACK_CRITICAL_SECTIONS_DATA
@@ -1444,13 +1444,17 @@ namespace CorUnix
printf("\tLockCount \t= %#x\n"
"\tRecursionCount \t= %d\n"
"\tOwningThread \t= %p\n"
- "\tLockSemaphore \t= %p\n"
"\tSpinCount \t= %u\n"
"\tfInternal \t= %d\n"
"\teInitState \t= %u\n"
"\tpNativeData \t= %p ->\n",
pCS->LockCount.Load(), pCS->RecursionCount, (void *)pCS->OwningThread,
- pCS->LockSemaphore, (unsigned)pCS->SpinCount, (int)pCS->fInternal,
+ (unsigned)pCS->SpinCount,
+#ifdef PAL_TRACK_CRITICAL_SECTIONS_DATA
+ (int)pCS->fInternal,
+#else
+ (int)0,
+#endif // PAL_TRACK_CRITICAL_SECTIONS_DATA
pCS->cisInitState.Load(), &pCS->csndNativeData);
printf("\t{\n\t\t[mutex]\n\t\t[condition]\n"
diff --git a/src/coreclr/src/pal/src/thread/thread.cpp b/src/coreclr/src/pal/src/thread/thread.cpp
index c8dcc43d06f561..1473601c512523 100644
--- a/src/coreclr/src/pal/src/thread/thread.cpp
+++ b/src/coreclr/src/pal/src/thread/thread.cpp
@@ -2808,7 +2808,7 @@ PAL_InjectActivation(
palError = InjectActivationInternal(pTargetThread);
}
- if (palError == NO_ERROR)
+ if (palError != NO_ERROR)
{
pCurrentThread->SetLastError(palError);
}
diff --git a/src/coreclr/src/pal/tools/gen-dactable-rva.sh b/src/coreclr/src/pal/tools/gen-dactable-rva.sh
index dd200068e5f398..fd4fa76c6eaab4 100644
--- a/src/coreclr/src/pal/tools/gen-dactable-rva.sh
+++ b/src/coreclr/src/pal/tools/gen-dactable-rva.sh
@@ -1 +1 @@
-nm $1 | grep g_dacTable | cut -f 1 -d' ' | head -n 1 | awk '{ print "#define DAC_TABLE_RVA 0x" $1}' > $2
+${NM:-nm} $1 | grep g_dacTable | cut -f 1 -d' ' | head -n 1 | awk '{ print "#define DAC_TABLE_RVA 0x" $1}' > $2
diff --git a/src/coreclr/src/scripts/genEventPipe.py b/src/coreclr/src/scripts/genEventPipe.py
index 35586385e7f704..54a9db415706d3 100644
--- a/src/coreclr/src/scripts/genEventPipe.py
+++ b/src/coreclr/src/scripts/genEventPipe.py
@@ -1,4 +1,4 @@
-from __future__ import print_function
+from __future__ import print_function
from genEventing import *
from genLttngProvider import *
import os
diff --git a/src/coreclr/src/scripts/genEventing.py b/src/coreclr/src/scripts/genEventing.py
index 5bbbbec5c20227..e7626cc69275d9 100644
--- a/src/coreclr/src/scripts/genEventing.py
+++ b/src/coreclr/src/scripts/genEventing.py
@@ -1,4 +1,4 @@
-#
+#
## Licensed to the .NET Foundation under one or more agreements.
## The .NET Foundation licenses this file to you under the MIT license.
## See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/scripts/genLttngProvider.py b/src/coreclr/src/scripts/genLttngProvider.py
index 393ca3f4c022a7..1ed1d2a839a2fa 100644
--- a/src/coreclr/src/scripts/genLttngProvider.py
+++ b/src/coreclr/src/scripts/genLttngProvider.py
@@ -1,4 +1,4 @@
-##
+##
## Licensed to the .NET Foundation under one or more agreements.
## The .NET Foundation licenses this file to you under the MIT license.
## See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/scripts/scripts.pyproj b/src/coreclr/src/scripts/scripts.pyproj
index c0b7bef6415e5f..a36591d2834b02 100644
--- a/src/coreclr/src/scripts/scripts.pyproj
+++ b/src/coreclr/src/scripts/scripts.pyproj
@@ -1,4 +1,4 @@
-
+
Debug
diff --git a/src/coreclr/src/scripts/utilities.py b/src/coreclr/src/scripts/utilities.py
index c4767a43b7c40f..46442eed5b8aac 100644
--- a/src/coreclr/src/scripts/utilities.py
+++ b/src/coreclr/src/scripts/utilities.py
@@ -1,4 +1,4 @@
-##
+##
## Licensed to the .NET Foundation under one or more agreements.
## The .NET Foundation licenses this file to you under the MIT license.
## See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/Compiler/CodeGenerationFailedException.cs b/src/coreclr/src/tools/Common/Compiler/CodeGenerationFailedException.cs
index ab4a47be4002fb..b27be3de26e265 100644
--- a/src/coreclr/src/tools/Common/Compiler/CodeGenerationFailedException.cs
+++ b/src/coreclr/src/tools/Common/Compiler/CodeGenerationFailedException.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/Compiler/CompilationBuilder.cs b/src/coreclr/src/tools/Common/Compiler/CompilationBuilder.cs
index e115ecbd47f150..fa97ad503df2d5 100644
--- a/src/coreclr/src/tools/Common/Compiler/CompilationBuilder.cs
+++ b/src/coreclr/src/tools/Common/Compiler/CompilationBuilder.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/Compiler/CompilationModuleGroup.cs b/src/coreclr/src/tools/Common/Compiler/CompilationModuleGroup.cs
index 1feb14c46c08ff..0182fc21b47ab9 100644
--- a/src/coreclr/src/tools/Common/Compiler/CompilationModuleGroup.cs
+++ b/src/coreclr/src/tools/Common/Compiler/CompilationModuleGroup.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/Compiler/CompilerTypeSystemContext.Validation.cs b/src/coreclr/src/tools/Common/Compiler/CompilerTypeSystemContext.Validation.cs
index 6b9e863e5b0d8c..5373708e823a46 100644
--- a/src/coreclr/src/tools/Common/Compiler/CompilerTypeSystemContext.Validation.cs
+++ b/src/coreclr/src/tools/Common/Compiler/CompilerTypeSystemContext.Validation.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/Compiler/CompilerTypeSystemContext.cs b/src/coreclr/src/tools/Common/Compiler/CompilerTypeSystemContext.cs
index 7463ec7cc86152..1c103df45b7f3c 100644
--- a/src/coreclr/src/tools/Common/Compiler/CompilerTypeSystemContext.cs
+++ b/src/coreclr/src/tools/Common/Compiler/CompilerTypeSystemContext.cs
@@ -106,31 +106,22 @@ public override ModuleDesc ResolveAssembly(System.Reflection.AssemblyName name,
return GetModuleForSimpleName(name.Name, throwIfNotFound);
}
- public ModuleDesc GetModuleForSimpleName(string simpleName, bool throwIfNotFound = true)
+ public EcmaModule GetModuleForSimpleName(string simpleName, bool throwIfNotFound = true)
{
- ModuleData existing;
- if (_simpleNameHashtable.TryGetValue(simpleName, out existing))
+ if (_simpleNameHashtable.TryGetValue(simpleName, out ModuleData existing))
return existing.Module;
- string filePath;
- if (!InputFilePaths.TryGetValue(simpleName, out filePath))
- {
- if (!ReferenceFilePaths.TryGetValue(simpleName, out filePath))
- {
- // We allow the CanonTypesModule to not be an EcmaModule.
- if (((IAssemblyDesc)CanonTypesModule).GetName().Name == simpleName)
- return CanonTypesModule;
-
- // TODO: the exception is wrong for two reasons: for one, this should be assembly full name, not simple name.
- // The other reason is that on CoreCLR, the exception also captures the reason. We should be passing two
- // string IDs. This makes this rather annoying.
- if (throwIfNotFound)
- ThrowHelper.ThrowFileNotFoundException(ExceptionStringID.FileLoadErrorGeneric, simpleName);
- return null;
- }
- }
+ if (InputFilePaths.TryGetValue(simpleName, out string filePath)
+ || ReferenceFilePaths.TryGetValue(simpleName, out filePath))
+ return AddModule(filePath, simpleName, true);
+
+ // TODO: the exception is wrong for two reasons: for one, this should be assembly full name, not simple name.
+ // The other reason is that on CoreCLR, the exception also captures the reason. We should be passing two
+ // string IDs. This makes this rather annoying.
+ if (throwIfNotFound)
+ ThrowHelper.ThrowFileNotFoundException(ExceptionStringID.FileLoadErrorGeneric, simpleName);
- return AddModule(filePath, simpleName, true);
+ return null;
}
public EcmaModule GetModuleFromPath(string filePath)
diff --git a/src/coreclr/src/tools/Common/Compiler/CoreRTNameMangler.cs b/src/coreclr/src/tools/Common/Compiler/CoreRTNameMangler.cs
index b479912f34000e..ec4e90965c962e 100644
--- a/src/coreclr/src/tools/Common/Compiler/CoreRTNameMangler.cs
+++ b/src/coreclr/src/tools/Common/Compiler/CoreRTNameMangler.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/CompilerComparer.cs b/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/CompilerComparer.cs
index 250b327077e9a6..b02ab632a5ac26 100644
--- a/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/CompilerComparer.cs
+++ b/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/CompilerComparer.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/EmbeddedDataContainerNode.cs b/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/EmbeddedDataContainerNode.cs
index 0cffffac19bfc1..e219528e8ffaf1 100644
--- a/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/EmbeddedDataContainerNode.cs
+++ b/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/EmbeddedDataContainerNode.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/IMethodBodyNode.cs b/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/IMethodBodyNode.cs
index b862f59b49fdac..75d7314c9c0e48 100644
--- a/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/IMethodBodyNode.cs
+++ b/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/IMethodBodyNode.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/IMethodNode.cs b/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/IMethodNode.cs
index 393ee4adf54c10..3c148c8acc3d75 100644
--- a/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/IMethodNode.cs
+++ b/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/IMethodNode.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/INodeWithRuntimeDeterminedDependencies.cs b/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/INodeWithRuntimeDeterminedDependencies.cs
index 9969bba84a9f0a..3397f798159d9d 100644
--- a/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/INodeWithRuntimeDeterminedDependencies.cs
+++ b/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/INodeWithRuntimeDeterminedDependencies.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/ISortableNode.cs b/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/ISortableNode.cs
index ac62439b0725d4..bde728a7493a31 100644
--- a/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/ISortableNode.cs
+++ b/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/ISortableNode.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/ObjectNodeSection.cs b/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/ObjectNodeSection.cs
index 98829e5f30c15f..b89b9482403b7c 100644
--- a/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/ObjectNodeSection.cs
+++ b/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/ObjectNodeSection.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/ShadowConcreteMethodNode.cs b/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/ShadowConcreteMethodNode.cs
index 657e1100719c32..a489d68cd28846 100644
--- a/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/ShadowConcreteMethodNode.cs
+++ b/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/ShadowConcreteMethodNode.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/SortableDependencyNode.cs b/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/SortableDependencyNode.cs
index 81aa110c9d4fb9..cda380e171f15e 100644
--- a/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/SortableDependencyNode.cs
+++ b/src/coreclr/src/tools/Common/Compiler/DependencyAnalysis/SortableDependencyNode.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -59,6 +59,7 @@ protected enum ObjectNodeOrder
//
CorHeaderNode,
ReadyToRunHeaderNode,
+ ReadyToRunAssemblyHeaderNode,
ImportSectionsTableNode,
ImportSectionNode,
MethodEntrypointTableNode,
diff --git a/src/coreclr/src/tools/Common/Compiler/DependencyTrackingLevel.cs b/src/coreclr/src/tools/Common/Compiler/DependencyTrackingLevel.cs
index 9322b9d3026838..8a2eb211fda05b 100644
--- a/src/coreclr/src/tools/Common/Compiler/DependencyTrackingLevel.cs
+++ b/src/coreclr/src/tools/Common/Compiler/DependencyTrackingLevel.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/Compiler/DevirtualizationManager.cs b/src/coreclr/src/tools/Common/Compiler/DevirtualizationManager.cs
index 6191ebd11ac6d6..d07b6a84f186cc 100644
--- a/src/coreclr/src/tools/Common/Compiler/DevirtualizationManager.cs
+++ b/src/coreclr/src/tools/Common/Compiler/DevirtualizationManager.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/Compiler/HardwareIntrinsicHelpers.cs b/src/coreclr/src/tools/Common/Compiler/HardwareIntrinsicHelpers.cs
index 99b3400617c2e7..5ead0f7640d9c4 100644
--- a/src/coreclr/src/tools/Common/Compiler/HardwareIntrinsicHelpers.cs
+++ b/src/coreclr/src/tools/Common/Compiler/HardwareIntrinsicHelpers.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/Compiler/ICompilationRootProvider.cs b/src/coreclr/src/tools/Common/Compiler/ICompilationRootProvider.cs
index 8434ad8a8acbf4..76eeec6cabeb44 100644
--- a/src/coreclr/src/tools/Common/Compiler/ICompilationRootProvider.cs
+++ b/src/coreclr/src/tools/Common/Compiler/ICompilationRootProvider.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/Compiler/InternalCompilerErrorException.cs b/src/coreclr/src/tools/Common/Compiler/InternalCompilerErrorException.cs
index 06d0cf3e5dfa30..164a5f0981ecee 100644
--- a/src/coreclr/src/tools/Common/Compiler/InternalCompilerErrorException.cs
+++ b/src/coreclr/src/tools/Common/Compiler/InternalCompilerErrorException.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/Compiler/Logger.cs b/src/coreclr/src/tools/Common/Compiler/Logger.cs
index 5fa09a1c420d69..7861bde9464c50 100644
--- a/src/coreclr/src/tools/Common/Compiler/Logger.cs
+++ b/src/coreclr/src/tools/Common/Compiler/Logger.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/Compiler/SingleMethodRootProvider.cs b/src/coreclr/src/tools/Common/Compiler/SingleMethodRootProvider.cs
index c1d9f484e0be16..769747d13ed251 100644
--- a/src/coreclr/src/tools/Common/Compiler/SingleMethodRootProvider.cs
+++ b/src/coreclr/src/tools/Common/Compiler/SingleMethodRootProvider.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/Compiler/TypeExtensions.cs b/src/coreclr/src/tools/Common/Compiler/TypeExtensions.cs
index 0514b24488c5dc..03fe6874ba595b 100644
--- a/src/coreclr/src/tools/Common/Compiler/TypeExtensions.cs
+++ b/src/coreclr/src/tools/Common/Compiler/TypeExtensions.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/Internal/Runtime/CorConstants.cs b/src/coreclr/src/tools/Common/Internal/Runtime/CorConstants.cs
index 9cf2c6960e7738..ef9305c315f416 100644
--- a/src/coreclr/src/tools/Common/Internal/Runtime/CorConstants.cs
+++ b/src/coreclr/src/tools/Common/Internal/Runtime/CorConstants.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/Internal/Runtime/ModuleHeaders.cs b/src/coreclr/src/tools/Common/Internal/Runtime/ModuleHeaders.cs
index 07bc53d2ae0561..57722b4f3d7b47 100644
--- a/src/coreclr/src/tools/Common/Internal/Runtime/ModuleHeaders.cs
+++ b/src/coreclr/src/tools/Common/Internal/Runtime/ModuleHeaders.cs
@@ -64,6 +64,8 @@ public enum ReadyToRunSectionType
ManifestMetadata = 112, // Added in v2.3
AttributePresence = 113, // Added in V3.1
InliningInfo2 = 114, // Added in 4.1
+ ComponentAssemblies = 115, // Added in 4.1
+ OwnerCompositeExecutable = 116, // Added in 4.1
//
// CoreRT ReadyToRun sections
diff --git a/src/coreclr/src/tools/Common/Internal/Runtime/ReadyToRunConstants.cs b/src/coreclr/src/tools/Common/Internal/Runtime/ReadyToRunConstants.cs
index 35a9e34969cd6f..ade24391dc5a64 100644
--- a/src/coreclr/src/tools/Common/Internal/Runtime/ReadyToRunConstants.cs
+++ b/src/coreclr/src/tools/Common/Internal/Runtime/ReadyToRunConstants.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -12,7 +12,9 @@ public enum ReadyToRunFlags
READYTORUN_FLAG_PlatformNeutralSource = 0x00000001, // Set if the original IL assembly was platform-neutral
READYTORUN_FLAG_SkipTypeValidation = 0x00000002, // Set of methods with native code was determined using profile data
READYTORUN_FLAG_Partial = 0x00000004,
- READYTORUN_FLAG_NonSharedPInvokeStubs = 0x00000008 // PInvoke stubs compiled into image are non-shareable (no secret parameter)
+ READYTORUN_FLAG_NonSharedPInvokeStubs = 0x00000008, // PInvoke stubs compiled into image are non-shareable (no secret parameter)
+ READYTORUN_FLAG_EmbeddedMSIL = 0x00000010, // MSIL is embedded in the composite R2R executable
+ READYTORUN_FLAG_Component = 0x00000020, // This is the header describing a component assembly of composite R2R
}
///
diff --git a/src/coreclr/src/tools/Common/JitInterface/CorInfoBase.cs b/src/coreclr/src/tools/Common/JitInterface/CorInfoBase.cs
index 1aa42f323d6afd..5e64833b92487a 100644
--- a/src/coreclr/src/tools/Common/JitInterface/CorInfoBase.cs
+++ b/src/coreclr/src/tools/Common/JitInterface/CorInfoBase.cs
@@ -84,6 +84,8 @@ unsafe partial class CorInfoImpl
[UnmanagedFunctionPointerAttribute(default(CallingConvention))]
[return: MarshalAs(UnmanagedType.Bool)]delegate bool __isValidStringRef(IntPtr _this, IntPtr* ppException, CORINFO_MODULE_STRUCT_* module, uint metaTOK);
[UnmanagedFunctionPointerAttribute(default(CallingConvention))]
+ delegate char* __getStringLiteral(IntPtr _this, IntPtr* ppException, CORINFO_MODULE_STRUCT_* module, uint metaTOK, ref int length);
+ [UnmanagedFunctionPointerAttribute(default(CallingConvention))]
[return: MarshalAs(UnmanagedType.Bool)]delegate bool __shouldEnforceCallvirtRestriction(IntPtr _this, IntPtr* ppException, CORINFO_MODULE_STRUCT_* scope);
[UnmanagedFunctionPointerAttribute(default(CallingConvention))]
delegate CorInfoType __asCorInfoType(IntPtr _this, IntPtr* ppException, CORINFO_CLASS_STRUCT_* cls);
@@ -94,7 +96,7 @@ unsafe partial class CorInfoImpl
[UnmanagedFunctionPointerAttribute(default(CallingConvention))]
delegate CORINFO_CLASS_STRUCT_* __getTypeInstantiationArgument(IntPtr _this, IntPtr* ppException, CORINFO_CLASS_STRUCT_* cls, uint index);
[UnmanagedFunctionPointerAttribute(default(CallingConvention))]
- delegate int __appendClassName(IntPtr _this, IntPtr* ppException, short** ppBuf, ref int pnBufLen, CORINFO_CLASS_STRUCT_* cls, [MarshalAs(UnmanagedType.Bool)]bool fNamespace, [MarshalAs(UnmanagedType.Bool)]bool fFullInst, [MarshalAs(UnmanagedType.Bool)]bool fAssembly);
+ delegate int __appendClassName(IntPtr _this, IntPtr* ppException, char** ppBuf, ref int pnBufLen, CORINFO_CLASS_STRUCT_* cls, [MarshalAs(UnmanagedType.Bool)]bool fNamespace, [MarshalAs(UnmanagedType.Bool)]bool fFullInst, [MarshalAs(UnmanagedType.Bool)]bool fAssembly);
[UnmanagedFunctionPointerAttribute(default(CallingConvention))]
[return: MarshalAs(UnmanagedType.Bool)]delegate bool __isValueClass(IntPtr _this, IntPtr* ppException, CORINFO_CLASS_STRUCT_* cls);
[UnmanagedFunctionPointerAttribute(default(CallingConvention))]
@@ -228,7 +230,7 @@ unsafe partial class CorInfoImpl
[UnmanagedFunctionPointerAttribute(default(CallingConvention))]
delegate HRESULT __GetErrorHRESULT(IntPtr _this, IntPtr* ppException, _EXCEPTION_POINTERS* pExceptionPointers);
[UnmanagedFunctionPointerAttribute(default(CallingConvention))]
- delegate uint __GetErrorMessage(IntPtr _this, IntPtr* ppException, short* buffer, uint bufferLength);
+ delegate uint __GetErrorMessage(IntPtr _this, IntPtr* ppException, char* buffer, uint bufferLength);
[UnmanagedFunctionPointerAttribute(default(CallingConvention))]
delegate int __FilterException(IntPtr _this, IntPtr* ppException, _EXCEPTION_POINTERS* pExceptionPointers);
[UnmanagedFunctionPointerAttribute(default(CallingConvention))]
@@ -242,7 +244,7 @@ unsafe partial class CorInfoImpl
[UnmanagedFunctionPointerAttribute(default(CallingConvention))]
delegate void __getEEInfo(IntPtr _this, IntPtr* ppException, ref CORINFO_EE_INFO pEEInfoOut);
[UnmanagedFunctionPointerAttribute(default(CallingConvention))]
- [return: MarshalAs(UnmanagedType.LPWStr)]delegate string __getJitTimeLogFilename(IntPtr _this, IntPtr* ppException);
+ delegate char* __getJitTimeLogFilename(IntPtr _this, IntPtr* ppException);
[UnmanagedFunctionPointerAttribute(default(CallingConvention))]
delegate mdToken __getMethodDefFromMethod(IntPtr _this, IntPtr* ppException, CORINFO_METHOD_STRUCT_* hMethod);
[UnmanagedFunctionPointerAttribute(default(CallingConvention))]
@@ -860,6 +862,20 @@ static CorInfoCanSkipVerificationResult _canSkipVerification(IntPtr thisHandle,
}
}
+ static char* _getStringLiteral(IntPtr thisHandle, IntPtr* ppException, CORINFO_MODULE_STRUCT_* module, uint metaTOK, ref int length)
+ {
+ var _this = GetThis(thisHandle);
+ try
+ {
+ return _this.getStringLiteral(module, metaTOK, ref length);
+ }
+ catch (Exception ex)
+ {
+ *ppException = _this.AllocException(ex);
+ return default(char*);
+ }
+ }
+
[return: MarshalAs(UnmanagedType.Bool)]static bool _shouldEnforceCallvirtRestriction(IntPtr thisHandle, IntPtr* ppException, CORINFO_MODULE_STRUCT_* scope)
{
var _this = GetThis(thisHandle);
@@ -930,7 +946,7 @@ static CorInfoType _asCorInfoType(IntPtr thisHandle, IntPtr* ppException, CORINF
}
}
- static int _appendClassName(IntPtr thisHandle, IntPtr* ppException, short** ppBuf, ref int pnBufLen, CORINFO_CLASS_STRUCT_* cls, [MarshalAs(UnmanagedType.Bool)]bool fNamespace, [MarshalAs(UnmanagedType.Bool)]bool fFullInst, [MarshalAs(UnmanagedType.Bool)]bool fAssembly)
+ static int _appendClassName(IntPtr thisHandle, IntPtr* ppException, char** ppBuf, ref int pnBufLen, CORINFO_CLASS_STRUCT_* cls, [MarshalAs(UnmanagedType.Bool)]bool fNamespace, [MarshalAs(UnmanagedType.Bool)]bool fFullInst, [MarshalAs(UnmanagedType.Bool)]bool fAssembly)
{
var _this = GetThis(thisHandle);
try
@@ -1859,7 +1875,7 @@ static HRESULT _GetErrorHRESULT(IntPtr thisHandle, IntPtr* ppException, _EXCEPTI
}
}
- static uint _GetErrorMessage(IntPtr thisHandle, IntPtr* ppException, short* buffer, uint bufferLength)
+ static uint _GetErrorMessage(IntPtr thisHandle, IntPtr* ppException, char* buffer, uint bufferLength)
{
var _this = GetThis(thisHandle);
try
@@ -1953,7 +1969,7 @@ static void _getEEInfo(IntPtr thisHandle, IntPtr* ppException, ref CORINFO_EE_IN
}
}
- [return: MarshalAs(UnmanagedType.LPWStr)]static string _getJitTimeLogFilename(IntPtr thisHandle, IntPtr* ppException)
+ static char* _getJitTimeLogFilename(IntPtr thisHandle, IntPtr* ppException)
{
var _this = GetThis(thisHandle);
try
@@ -1963,7 +1979,7 @@ static void _getEEInfo(IntPtr thisHandle, IntPtr* ppException, ref CORINFO_EE_IN
catch (Exception ex)
{
*ppException = _this.AllocException(ex);
- return default(string);
+ return default(char*);
}
}
@@ -2833,8 +2849,8 @@ static uint _getJitFlags(IntPtr thisHandle, IntPtr* ppException, ref CORJIT_FLAG
static IntPtr GetUnmanagedCallbacks(out Object keepAlive)
{
- IntPtr * callbacks = (IntPtr *)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 179);
- Object[] delegates = new Object[179];
+ IntPtr * callbacks = (IntPtr *)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 180);
+ Object[] delegates = new Object[180];
var d0 = new __getMethodAttribs(_getMethodAttribs);
callbacks[0] = Marshal.GetFunctionPointerForDelegate(d0);
@@ -2944,435 +2960,438 @@ static IntPtr GetUnmanagedCallbacks(out Object keepAlive)
var d35 = new __isValidStringRef(_isValidStringRef);
callbacks[35] = Marshal.GetFunctionPointerForDelegate(d35);
delegates[35] = d35;
- var d36 = new __shouldEnforceCallvirtRestriction(_shouldEnforceCallvirtRestriction);
+ var d36 = new __getStringLiteral(_getStringLiteral);
callbacks[36] = Marshal.GetFunctionPointerForDelegate(d36);
delegates[36] = d36;
- var d37 = new __asCorInfoType(_asCorInfoType);
+ var d37 = new __shouldEnforceCallvirtRestriction(_shouldEnforceCallvirtRestriction);
callbacks[37] = Marshal.GetFunctionPointerForDelegate(d37);
delegates[37] = d37;
- var d38 = new __getClassName(_getClassName);
+ var d38 = new __asCorInfoType(_asCorInfoType);
callbacks[38] = Marshal.GetFunctionPointerForDelegate(d38);
delegates[38] = d38;
- var d39 = new __getClassNameFromMetadata(_getClassNameFromMetadata);
+ var d39 = new __getClassName(_getClassName);
callbacks[39] = Marshal.GetFunctionPointerForDelegate(d39);
delegates[39] = d39;
- var d40 = new __getTypeInstantiationArgument(_getTypeInstantiationArgument);
+ var d40 = new __getClassNameFromMetadata(_getClassNameFromMetadata);
callbacks[40] = Marshal.GetFunctionPointerForDelegate(d40);
delegates[40] = d40;
- var d41 = new __appendClassName(_appendClassName);
+ var d41 = new __getTypeInstantiationArgument(_getTypeInstantiationArgument);
callbacks[41] = Marshal.GetFunctionPointerForDelegate(d41);
delegates[41] = d41;
- var d42 = new __isValueClass(_isValueClass);
+ var d42 = new __appendClassName(_appendClassName);
callbacks[42] = Marshal.GetFunctionPointerForDelegate(d42);
delegates[42] = d42;
- var d43 = new __canInlineTypeCheck(_canInlineTypeCheck);
+ var d43 = new __isValueClass(_isValueClass);
callbacks[43] = Marshal.GetFunctionPointerForDelegate(d43);
delegates[43] = d43;
- var d44 = new __canInlineTypeCheckWithObjectVTable(_canInlineTypeCheckWithObjectVTable);
+ var d44 = new __canInlineTypeCheck(_canInlineTypeCheck);
callbacks[44] = Marshal.GetFunctionPointerForDelegate(d44);
delegates[44] = d44;
- var d45 = new __getClassAttribs(_getClassAttribs);
+ var d45 = new __canInlineTypeCheckWithObjectVTable(_canInlineTypeCheckWithObjectVTable);
callbacks[45] = Marshal.GetFunctionPointerForDelegate(d45);
delegates[45] = d45;
- var d46 = new __isStructRequiringStackAllocRetBuf(_isStructRequiringStackAllocRetBuf);
+ var d46 = new __getClassAttribs(_getClassAttribs);
callbacks[46] = Marshal.GetFunctionPointerForDelegate(d46);
delegates[46] = d46;
- var d47 = new __getClassModule(_getClassModule);
+ var d47 = new __isStructRequiringStackAllocRetBuf(_isStructRequiringStackAllocRetBuf);
callbacks[47] = Marshal.GetFunctionPointerForDelegate(d47);
delegates[47] = d47;
- var d48 = new __getModuleAssembly(_getModuleAssembly);
+ var d48 = new __getClassModule(_getClassModule);
callbacks[48] = Marshal.GetFunctionPointerForDelegate(d48);
delegates[48] = d48;
- var d49 = new __getAssemblyName(_getAssemblyName);
+ var d49 = new __getModuleAssembly(_getModuleAssembly);
callbacks[49] = Marshal.GetFunctionPointerForDelegate(d49);
delegates[49] = d49;
- var d50 = new __LongLifetimeMalloc(_LongLifetimeMalloc);
+ var d50 = new __getAssemblyName(_getAssemblyName);
callbacks[50] = Marshal.GetFunctionPointerForDelegate(d50);
delegates[50] = d50;
- var d51 = new __LongLifetimeFree(_LongLifetimeFree);
+ var d51 = new __LongLifetimeMalloc(_LongLifetimeMalloc);
callbacks[51] = Marshal.GetFunctionPointerForDelegate(d51);
delegates[51] = d51;
- var d52 = new __getClassModuleIdForStatics(_getClassModuleIdForStatics);
+ var d52 = new __LongLifetimeFree(_LongLifetimeFree);
callbacks[52] = Marshal.GetFunctionPointerForDelegate(d52);
delegates[52] = d52;
- var d53 = new __getClassSize(_getClassSize);
+ var d53 = new __getClassModuleIdForStatics(_getClassModuleIdForStatics);
callbacks[53] = Marshal.GetFunctionPointerForDelegate(d53);
delegates[53] = d53;
- var d54 = new __getHeapClassSize(_getHeapClassSize);
+ var d54 = new __getClassSize(_getClassSize);
callbacks[54] = Marshal.GetFunctionPointerForDelegate(d54);
delegates[54] = d54;
- var d55 = new __canAllocateOnStack(_canAllocateOnStack);
+ var d55 = new __getHeapClassSize(_getHeapClassSize);
callbacks[55] = Marshal.GetFunctionPointerForDelegate(d55);
delegates[55] = d55;
- var d56 = new __getClassAlignmentRequirement(_getClassAlignmentRequirement);
+ var d56 = new __canAllocateOnStack(_canAllocateOnStack);
callbacks[56] = Marshal.GetFunctionPointerForDelegate(d56);
delegates[56] = d56;
- var d57 = new __getClassGClayout(_getClassGClayout);
+ var d57 = new __getClassAlignmentRequirement(_getClassAlignmentRequirement);
callbacks[57] = Marshal.GetFunctionPointerForDelegate(d57);
delegates[57] = d57;
- var d58 = new __getClassNumInstanceFields(_getClassNumInstanceFields);
+ var d58 = new __getClassGClayout(_getClassGClayout);
callbacks[58] = Marshal.GetFunctionPointerForDelegate(d58);
delegates[58] = d58;
- var d59 = new __getFieldInClass(_getFieldInClass);
+ var d59 = new __getClassNumInstanceFields(_getClassNumInstanceFields);
callbacks[59] = Marshal.GetFunctionPointerForDelegate(d59);
delegates[59] = d59;
- var d60 = new __checkMethodModifier(_checkMethodModifier);
+ var d60 = new __getFieldInClass(_getFieldInClass);
callbacks[60] = Marshal.GetFunctionPointerForDelegate(d60);
delegates[60] = d60;
- var d61 = new __getNewHelper(_getNewHelper);
+ var d61 = new __checkMethodModifier(_checkMethodModifier);
callbacks[61] = Marshal.GetFunctionPointerForDelegate(d61);
delegates[61] = d61;
- var d62 = new __getNewArrHelper(_getNewArrHelper);
+ var d62 = new __getNewHelper(_getNewHelper);
callbacks[62] = Marshal.GetFunctionPointerForDelegate(d62);
delegates[62] = d62;
- var d63 = new __getCastingHelper(_getCastingHelper);
+ var d63 = new __getNewArrHelper(_getNewArrHelper);
callbacks[63] = Marshal.GetFunctionPointerForDelegate(d63);
delegates[63] = d63;
- var d64 = new __getSharedCCtorHelper(_getSharedCCtorHelper);
+ var d64 = new __getCastingHelper(_getCastingHelper);
callbacks[64] = Marshal.GetFunctionPointerForDelegate(d64);
delegates[64] = d64;
- var d65 = new __getSecurityPrologHelper(_getSecurityPrologHelper);
+ var d65 = new __getSharedCCtorHelper(_getSharedCCtorHelper);
callbacks[65] = Marshal.GetFunctionPointerForDelegate(d65);
delegates[65] = d65;
- var d66 = new __getTypeForBox(_getTypeForBox);
+ var d66 = new __getSecurityPrologHelper(_getSecurityPrologHelper);
callbacks[66] = Marshal.GetFunctionPointerForDelegate(d66);
delegates[66] = d66;
- var d67 = new __getBoxHelper(_getBoxHelper);
+ var d67 = new __getTypeForBox(_getTypeForBox);
callbacks[67] = Marshal.GetFunctionPointerForDelegate(d67);
delegates[67] = d67;
- var d68 = new __getUnBoxHelper(_getUnBoxHelper);
+ var d68 = new __getBoxHelper(_getBoxHelper);
callbacks[68] = Marshal.GetFunctionPointerForDelegate(d68);
delegates[68] = d68;
- var d69 = new __getReadyToRunHelper(_getReadyToRunHelper);
+ var d69 = new __getUnBoxHelper(_getUnBoxHelper);
callbacks[69] = Marshal.GetFunctionPointerForDelegate(d69);
delegates[69] = d69;
- var d70 = new __getReadyToRunDelegateCtorHelper(_getReadyToRunDelegateCtorHelper);
+ var d70 = new __getReadyToRunHelper(_getReadyToRunHelper);
callbacks[70] = Marshal.GetFunctionPointerForDelegate(d70);
delegates[70] = d70;
- var d71 = new __getHelperName(_getHelperName);
+ var d71 = new __getReadyToRunDelegateCtorHelper(_getReadyToRunDelegateCtorHelper);
callbacks[71] = Marshal.GetFunctionPointerForDelegate(d71);
delegates[71] = d71;
- var d72 = new __initClass(_initClass);
+ var d72 = new __getHelperName(_getHelperName);
callbacks[72] = Marshal.GetFunctionPointerForDelegate(d72);
delegates[72] = d72;
- var d73 = new __classMustBeLoadedBeforeCodeIsRun(_classMustBeLoadedBeforeCodeIsRun);
+ var d73 = new __initClass(_initClass);
callbacks[73] = Marshal.GetFunctionPointerForDelegate(d73);
delegates[73] = d73;
- var d74 = new __getBuiltinClass(_getBuiltinClass);
+ var d74 = new __classMustBeLoadedBeforeCodeIsRun(_classMustBeLoadedBeforeCodeIsRun);
callbacks[74] = Marshal.GetFunctionPointerForDelegate(d74);
delegates[74] = d74;
- var d75 = new __getTypeForPrimitiveValueClass(_getTypeForPrimitiveValueClass);
+ var d75 = new __getBuiltinClass(_getBuiltinClass);
callbacks[75] = Marshal.GetFunctionPointerForDelegate(d75);
delegates[75] = d75;
- var d76 = new __getTypeForPrimitiveNumericClass(_getTypeForPrimitiveNumericClass);
+ var d76 = new __getTypeForPrimitiveValueClass(_getTypeForPrimitiveValueClass);
callbacks[76] = Marshal.GetFunctionPointerForDelegate(d76);
delegates[76] = d76;
- var d77 = new __canCast(_canCast);
+ var d77 = new __getTypeForPrimitiveNumericClass(_getTypeForPrimitiveNumericClass);
callbacks[77] = Marshal.GetFunctionPointerForDelegate(d77);
delegates[77] = d77;
- var d78 = new __areTypesEquivalent(_areTypesEquivalent);
+ var d78 = new __canCast(_canCast);
callbacks[78] = Marshal.GetFunctionPointerForDelegate(d78);
delegates[78] = d78;
- var d79 = new __compareTypesForCast(_compareTypesForCast);
+ var d79 = new __areTypesEquivalent(_areTypesEquivalent);
callbacks[79] = Marshal.GetFunctionPointerForDelegate(d79);
delegates[79] = d79;
- var d80 = new __compareTypesForEquality(_compareTypesForEquality);
+ var d80 = new __compareTypesForCast(_compareTypesForCast);
callbacks[80] = Marshal.GetFunctionPointerForDelegate(d80);
delegates[80] = d80;
- var d81 = new __mergeClasses(_mergeClasses);
+ var d81 = new __compareTypesForEquality(_compareTypesForEquality);
callbacks[81] = Marshal.GetFunctionPointerForDelegate(d81);
delegates[81] = d81;
- var d82 = new __isMoreSpecificType(_isMoreSpecificType);
+ var d82 = new __mergeClasses(_mergeClasses);
callbacks[82] = Marshal.GetFunctionPointerForDelegate(d82);
delegates[82] = d82;
- var d83 = new __getParentType(_getParentType);
+ var d83 = new __isMoreSpecificType(_isMoreSpecificType);
callbacks[83] = Marshal.GetFunctionPointerForDelegate(d83);
delegates[83] = d83;
- var d84 = new __getChildType(_getChildType);
+ var d84 = new __getParentType(_getParentType);
callbacks[84] = Marshal.GetFunctionPointerForDelegate(d84);
delegates[84] = d84;
- var d85 = new __satisfiesClassConstraints(_satisfiesClassConstraints);
+ var d85 = new __getChildType(_getChildType);
callbacks[85] = Marshal.GetFunctionPointerForDelegate(d85);
delegates[85] = d85;
- var d86 = new __isSDArray(_isSDArray);
+ var d86 = new __satisfiesClassConstraints(_satisfiesClassConstraints);
callbacks[86] = Marshal.GetFunctionPointerForDelegate(d86);
delegates[86] = d86;
- var d87 = new __getArrayRank(_getArrayRank);
+ var d87 = new __isSDArray(_isSDArray);
callbacks[87] = Marshal.GetFunctionPointerForDelegate(d87);
delegates[87] = d87;
- var d88 = new __getArrayInitializationData(_getArrayInitializationData);
+ var d88 = new __getArrayRank(_getArrayRank);
callbacks[88] = Marshal.GetFunctionPointerForDelegate(d88);
delegates[88] = d88;
- var d89 = new __canAccessClass(_canAccessClass);
+ var d89 = new __getArrayInitializationData(_getArrayInitializationData);
callbacks[89] = Marshal.GetFunctionPointerForDelegate(d89);
delegates[89] = d89;
- var d90 = new __getFieldName(_getFieldName);
+ var d90 = new __canAccessClass(_canAccessClass);
callbacks[90] = Marshal.GetFunctionPointerForDelegate(d90);
delegates[90] = d90;
- var d91 = new __getFieldClass(_getFieldClass);
+ var d91 = new __getFieldName(_getFieldName);
callbacks[91] = Marshal.GetFunctionPointerForDelegate(d91);
delegates[91] = d91;
- var d92 = new __getFieldType(_getFieldType);
+ var d92 = new __getFieldClass(_getFieldClass);
callbacks[92] = Marshal.GetFunctionPointerForDelegate(d92);
delegates[92] = d92;
- var d93 = new __getFieldOffset(_getFieldOffset);
+ var d93 = new __getFieldType(_getFieldType);
callbacks[93] = Marshal.GetFunctionPointerForDelegate(d93);
delegates[93] = d93;
- var d94 = new __isWriteBarrierHelperRequired(_isWriteBarrierHelperRequired);
+ var d94 = new __getFieldOffset(_getFieldOffset);
callbacks[94] = Marshal.GetFunctionPointerForDelegate(d94);
delegates[94] = d94;
- var d95 = new __getFieldInfo(_getFieldInfo);
+ var d95 = new __isWriteBarrierHelperRequired(_isWriteBarrierHelperRequired);
callbacks[95] = Marshal.GetFunctionPointerForDelegate(d95);
delegates[95] = d95;
- var d96 = new __isFieldStatic(_isFieldStatic);
+ var d96 = new __getFieldInfo(_getFieldInfo);
callbacks[96] = Marshal.GetFunctionPointerForDelegate(d96);
delegates[96] = d96;
- var d97 = new __getBoundaries(_getBoundaries);
+ var d97 = new __isFieldStatic(_isFieldStatic);
callbacks[97] = Marshal.GetFunctionPointerForDelegate(d97);
delegates[97] = d97;
- var d98 = new __setBoundaries(_setBoundaries);
+ var d98 = new __getBoundaries(_getBoundaries);
callbacks[98] = Marshal.GetFunctionPointerForDelegate(d98);
delegates[98] = d98;
- var d99 = new __getVars(_getVars);
+ var d99 = new __setBoundaries(_setBoundaries);
callbacks[99] = Marshal.GetFunctionPointerForDelegate(d99);
delegates[99] = d99;
- var d100 = new __setVars(_setVars);
+ var d100 = new __getVars(_getVars);
callbacks[100] = Marshal.GetFunctionPointerForDelegate(d100);
delegates[100] = d100;
- var d101 = new __allocateArray(_allocateArray);
+ var d101 = new __setVars(_setVars);
callbacks[101] = Marshal.GetFunctionPointerForDelegate(d101);
delegates[101] = d101;
- var d102 = new __freeArray(_freeArray);
+ var d102 = new __allocateArray(_allocateArray);
callbacks[102] = Marshal.GetFunctionPointerForDelegate(d102);
delegates[102] = d102;
- var d103 = new __getArgNext(_getArgNext);
+ var d103 = new __freeArray(_freeArray);
callbacks[103] = Marshal.GetFunctionPointerForDelegate(d103);
delegates[103] = d103;
- var d104 = new __getArgType(_getArgType);
+ var d104 = new __getArgNext(_getArgNext);
callbacks[104] = Marshal.GetFunctionPointerForDelegate(d104);
delegates[104] = d104;
- var d105 = new __getArgClass(_getArgClass);
+ var d105 = new __getArgType(_getArgType);
callbacks[105] = Marshal.GetFunctionPointerForDelegate(d105);
delegates[105] = d105;
- var d106 = new __getHFAType(_getHFAType);
+ var d106 = new __getArgClass(_getArgClass);
callbacks[106] = Marshal.GetFunctionPointerForDelegate(d106);
delegates[106] = d106;
- var d107 = new __GetErrorHRESULT(_GetErrorHRESULT);
+ var d107 = new __getHFAType(_getHFAType);
callbacks[107] = Marshal.GetFunctionPointerForDelegate(d107);
delegates[107] = d107;
- var d108 = new __GetErrorMessage(_GetErrorMessage);
+ var d108 = new __GetErrorHRESULT(_GetErrorHRESULT);
callbacks[108] = Marshal.GetFunctionPointerForDelegate(d108);
delegates[108] = d108;
- var d109 = new __FilterException(_FilterException);
+ var d109 = new __GetErrorMessage(_GetErrorMessage);
callbacks[109] = Marshal.GetFunctionPointerForDelegate(d109);
delegates[109] = d109;
- var d110 = new __HandleException(_HandleException);
+ var d110 = new __FilterException(_FilterException);
callbacks[110] = Marshal.GetFunctionPointerForDelegate(d110);
delegates[110] = d110;
- var d111 = new __ThrowExceptionForJitResult(_ThrowExceptionForJitResult);
+ var d111 = new __HandleException(_HandleException);
callbacks[111] = Marshal.GetFunctionPointerForDelegate(d111);
delegates[111] = d111;
- var d112 = new __ThrowExceptionForHelper(_ThrowExceptionForHelper);
+ var d112 = new __ThrowExceptionForJitResult(_ThrowExceptionForJitResult);
callbacks[112] = Marshal.GetFunctionPointerForDelegate(d112);
delegates[112] = d112;
- var d113 = new __runWithErrorTrap(_runWithErrorTrap);
+ var d113 = new __ThrowExceptionForHelper(_ThrowExceptionForHelper);
callbacks[113] = Marshal.GetFunctionPointerForDelegate(d113);
delegates[113] = d113;
- var d114 = new __getEEInfo(_getEEInfo);
+ var d114 = new __runWithErrorTrap(_runWithErrorTrap);
callbacks[114] = Marshal.GetFunctionPointerForDelegate(d114);
delegates[114] = d114;
- var d115 = new __getJitTimeLogFilename(_getJitTimeLogFilename);
+ var d115 = new __getEEInfo(_getEEInfo);
callbacks[115] = Marshal.GetFunctionPointerForDelegate(d115);
delegates[115] = d115;
- var d116 = new __getMethodDefFromMethod(_getMethodDefFromMethod);
+ var d116 = new __getJitTimeLogFilename(_getJitTimeLogFilename);
callbacks[116] = Marshal.GetFunctionPointerForDelegate(d116);
delegates[116] = d116;
- var d117 = new __getMethodName(_getMethodName);
+ var d117 = new __getMethodDefFromMethod(_getMethodDefFromMethod);
callbacks[117] = Marshal.GetFunctionPointerForDelegate(d117);
delegates[117] = d117;
- var d118 = new __getMethodNameFromMetadata(_getMethodNameFromMetadata);
+ var d118 = new __getMethodName(_getMethodName);
callbacks[118] = Marshal.GetFunctionPointerForDelegate(d118);
delegates[118] = d118;
- var d119 = new __getMethodHash(_getMethodHash);
+ var d119 = new __getMethodNameFromMetadata(_getMethodNameFromMetadata);
callbacks[119] = Marshal.GetFunctionPointerForDelegate(d119);
delegates[119] = d119;
- var d120 = new __findNameOfToken(_findNameOfToken);
+ var d120 = new __getMethodHash(_getMethodHash);
callbacks[120] = Marshal.GetFunctionPointerForDelegate(d120);
delegates[120] = d120;
- var d121 = new __getSystemVAmd64PassStructInRegisterDescriptor(_getSystemVAmd64PassStructInRegisterDescriptor);
+ var d121 = new __findNameOfToken(_findNameOfToken);
callbacks[121] = Marshal.GetFunctionPointerForDelegate(d121);
delegates[121] = d121;
- var d122 = new __getThreadTLSIndex(_getThreadTLSIndex);
+ var d122 = new __getSystemVAmd64PassStructInRegisterDescriptor(_getSystemVAmd64PassStructInRegisterDescriptor);
callbacks[122] = Marshal.GetFunctionPointerForDelegate(d122);
delegates[122] = d122;
- var d123 = new __getInlinedCallFrameVptr(_getInlinedCallFrameVptr);
+ var d123 = new __getThreadTLSIndex(_getThreadTLSIndex);
callbacks[123] = Marshal.GetFunctionPointerForDelegate(d123);
delegates[123] = d123;
- var d124 = new __getAddrOfCaptureThreadGlobal(_getAddrOfCaptureThreadGlobal);
+ var d124 = new __getInlinedCallFrameVptr(_getInlinedCallFrameVptr);
callbacks[124] = Marshal.GetFunctionPointerForDelegate(d124);
delegates[124] = d124;
- var d125 = new __getHelperFtn(_getHelperFtn);
+ var d125 = new __getAddrOfCaptureThreadGlobal(_getAddrOfCaptureThreadGlobal);
callbacks[125] = Marshal.GetFunctionPointerForDelegate(d125);
delegates[125] = d125;
- var d126 = new __getFunctionEntryPoint(_getFunctionEntryPoint);
+ var d126 = new __getHelperFtn(_getHelperFtn);
callbacks[126] = Marshal.GetFunctionPointerForDelegate(d126);
delegates[126] = d126;
- var d127 = new __getFunctionFixedEntryPoint(_getFunctionFixedEntryPoint);
+ var d127 = new __getFunctionEntryPoint(_getFunctionEntryPoint);
callbacks[127] = Marshal.GetFunctionPointerForDelegate(d127);
delegates[127] = d127;
- var d128 = new __getMethodSync(_getMethodSync);
+ var d128 = new __getFunctionFixedEntryPoint(_getFunctionFixedEntryPoint);
callbacks[128] = Marshal.GetFunctionPointerForDelegate(d128);
delegates[128] = d128;
- var d129 = new __getLazyStringLiteralHelper(_getLazyStringLiteralHelper);
+ var d129 = new __getMethodSync(_getMethodSync);
callbacks[129] = Marshal.GetFunctionPointerForDelegate(d129);
delegates[129] = d129;
- var d130 = new __embedModuleHandle(_embedModuleHandle);
+ var d130 = new __getLazyStringLiteralHelper(_getLazyStringLiteralHelper);
callbacks[130] = Marshal.GetFunctionPointerForDelegate(d130);
delegates[130] = d130;
- var d131 = new __embedClassHandle(_embedClassHandle);
+ var d131 = new __embedModuleHandle(_embedModuleHandle);
callbacks[131] = Marshal.GetFunctionPointerForDelegate(d131);
delegates[131] = d131;
- var d132 = new __embedMethodHandle(_embedMethodHandle);
+ var d132 = new __embedClassHandle(_embedClassHandle);
callbacks[132] = Marshal.GetFunctionPointerForDelegate(d132);
delegates[132] = d132;
- var d133 = new __embedFieldHandle(_embedFieldHandle);
+ var d133 = new __embedMethodHandle(_embedMethodHandle);
callbacks[133] = Marshal.GetFunctionPointerForDelegate(d133);
delegates[133] = d133;
- var d134 = new __embedGenericHandle(_embedGenericHandle);
+ var d134 = new __embedFieldHandle(_embedFieldHandle);
callbacks[134] = Marshal.GetFunctionPointerForDelegate(d134);
delegates[134] = d134;
- var d135 = new __getLocationOfThisType(_getLocationOfThisType);
+ var d135 = new __embedGenericHandle(_embedGenericHandle);
callbacks[135] = Marshal.GetFunctionPointerForDelegate(d135);
delegates[135] = d135;
- var d136 = new __getPInvokeUnmanagedTarget(_getPInvokeUnmanagedTarget);
+ var d136 = new __getLocationOfThisType(_getLocationOfThisType);
callbacks[136] = Marshal.GetFunctionPointerForDelegate(d136);
delegates[136] = d136;
- var d137 = new __getAddressOfPInvokeFixup(_getAddressOfPInvokeFixup);
+ var d137 = new __getPInvokeUnmanagedTarget(_getPInvokeUnmanagedTarget);
callbacks[137] = Marshal.GetFunctionPointerForDelegate(d137);
delegates[137] = d137;
- var d138 = new __getAddressOfPInvokeTarget(_getAddressOfPInvokeTarget);
+ var d138 = new __getAddressOfPInvokeFixup(_getAddressOfPInvokeFixup);
callbacks[138] = Marshal.GetFunctionPointerForDelegate(d138);
delegates[138] = d138;
- var d139 = new __GetCookieForPInvokeCalliSig(_GetCookieForPInvokeCalliSig);
+ var d139 = new __getAddressOfPInvokeTarget(_getAddressOfPInvokeTarget);
callbacks[139] = Marshal.GetFunctionPointerForDelegate(d139);
delegates[139] = d139;
- var d140 = new __canGetCookieForPInvokeCalliSig(_canGetCookieForPInvokeCalliSig);
+ var d140 = new __GetCookieForPInvokeCalliSig(_GetCookieForPInvokeCalliSig);
callbacks[140] = Marshal.GetFunctionPointerForDelegate(d140);
delegates[140] = d140;
- var d141 = new __getJustMyCodeHandle(_getJustMyCodeHandle);
+ var d141 = new __canGetCookieForPInvokeCalliSig(_canGetCookieForPInvokeCalliSig);
callbacks[141] = Marshal.GetFunctionPointerForDelegate(d141);
delegates[141] = d141;
- var d142 = new __GetProfilingHandle(_GetProfilingHandle);
+ var d142 = new __getJustMyCodeHandle(_getJustMyCodeHandle);
callbacks[142] = Marshal.GetFunctionPointerForDelegate(d142);
delegates[142] = d142;
- var d143 = new __getCallInfo(_getCallInfo);
+ var d143 = new __GetProfilingHandle(_GetProfilingHandle);
callbacks[143] = Marshal.GetFunctionPointerForDelegate(d143);
delegates[143] = d143;
- var d144 = new __canAccessFamily(_canAccessFamily);
+ var d144 = new __getCallInfo(_getCallInfo);
callbacks[144] = Marshal.GetFunctionPointerForDelegate(d144);
delegates[144] = d144;
- var d145 = new __isRIDClassDomainID(_isRIDClassDomainID);
+ var d145 = new __canAccessFamily(_canAccessFamily);
callbacks[145] = Marshal.GetFunctionPointerForDelegate(d145);
delegates[145] = d145;
- var d146 = new __getClassDomainID(_getClassDomainID);
+ var d146 = new __isRIDClassDomainID(_isRIDClassDomainID);
callbacks[146] = Marshal.GetFunctionPointerForDelegate(d146);
delegates[146] = d146;
- var d147 = new __getFieldAddress(_getFieldAddress);
+ var d147 = new __getClassDomainID(_getClassDomainID);
callbacks[147] = Marshal.GetFunctionPointerForDelegate(d147);
delegates[147] = d147;
- var d148 = new __getStaticFieldCurrentClass(_getStaticFieldCurrentClass);
+ var d148 = new __getFieldAddress(_getFieldAddress);
callbacks[148] = Marshal.GetFunctionPointerForDelegate(d148);
delegates[148] = d148;
- var d149 = new __getVarArgsHandle(_getVarArgsHandle);
+ var d149 = new __getStaticFieldCurrentClass(_getStaticFieldCurrentClass);
callbacks[149] = Marshal.GetFunctionPointerForDelegate(d149);
delegates[149] = d149;
- var d150 = new __canGetVarArgsHandle(_canGetVarArgsHandle);
+ var d150 = new __getVarArgsHandle(_getVarArgsHandle);
callbacks[150] = Marshal.GetFunctionPointerForDelegate(d150);
delegates[150] = d150;
- var d151 = new __constructStringLiteral(_constructStringLiteral);
+ var d151 = new __canGetVarArgsHandle(_canGetVarArgsHandle);
callbacks[151] = Marshal.GetFunctionPointerForDelegate(d151);
delegates[151] = d151;
- var d152 = new __emptyStringLiteral(_emptyStringLiteral);
+ var d152 = new __constructStringLiteral(_constructStringLiteral);
callbacks[152] = Marshal.GetFunctionPointerForDelegate(d152);
delegates[152] = d152;
- var d153 = new __getFieldThreadLocalStoreID(_getFieldThreadLocalStoreID);
+ var d153 = new __emptyStringLiteral(_emptyStringLiteral);
callbacks[153] = Marshal.GetFunctionPointerForDelegate(d153);
delegates[153] = d153;
- var d154 = new __setOverride(_setOverride);
+ var d154 = new __getFieldThreadLocalStoreID(_getFieldThreadLocalStoreID);
callbacks[154] = Marshal.GetFunctionPointerForDelegate(d154);
delegates[154] = d154;
- var d155 = new __addActiveDependency(_addActiveDependency);
+ var d155 = new __setOverride(_setOverride);
callbacks[155] = Marshal.GetFunctionPointerForDelegate(d155);
delegates[155] = d155;
- var d156 = new __GetDelegateCtor(_GetDelegateCtor);
+ var d156 = new __addActiveDependency(_addActiveDependency);
callbacks[156] = Marshal.GetFunctionPointerForDelegate(d156);
delegates[156] = d156;
- var d157 = new __MethodCompileComplete(_MethodCompileComplete);
+ var d157 = new __GetDelegateCtor(_GetDelegateCtor);
callbacks[157] = Marshal.GetFunctionPointerForDelegate(d157);
delegates[157] = d157;
- var d158 = new __getTailCallCopyArgsThunk(_getTailCallCopyArgsThunk);
+ var d158 = new __MethodCompileComplete(_MethodCompileComplete);
callbacks[158] = Marshal.GetFunctionPointerForDelegate(d158);
delegates[158] = d158;
- var d159 = new __convertPInvokeCalliToCall(_convertPInvokeCalliToCall);
+ var d159 = new __getTailCallCopyArgsThunk(_getTailCallCopyArgsThunk);
callbacks[159] = Marshal.GetFunctionPointerForDelegate(d159);
delegates[159] = d159;
- var d160 = new __getMemoryManager(_getMemoryManager);
+ var d160 = new __convertPInvokeCalliToCall(_convertPInvokeCalliToCall);
callbacks[160] = Marshal.GetFunctionPointerForDelegate(d160);
delegates[160] = d160;
- var d161 = new __allocMem(_allocMem);
+ var d161 = new __getMemoryManager(_getMemoryManager);
callbacks[161] = Marshal.GetFunctionPointerForDelegate(d161);
delegates[161] = d161;
- var d162 = new __reserveUnwindInfo(_reserveUnwindInfo);
+ var d162 = new __allocMem(_allocMem);
callbacks[162] = Marshal.GetFunctionPointerForDelegate(d162);
delegates[162] = d162;
- var d163 = new __allocUnwindInfo(_allocUnwindInfo);
+ var d163 = new __reserveUnwindInfo(_reserveUnwindInfo);
callbacks[163] = Marshal.GetFunctionPointerForDelegate(d163);
delegates[163] = d163;
- var d164 = new __allocGCInfo(_allocGCInfo);
+ var d164 = new __allocUnwindInfo(_allocUnwindInfo);
callbacks[164] = Marshal.GetFunctionPointerForDelegate(d164);
delegates[164] = d164;
- var d165 = new __yieldExecution(_yieldExecution);
+ var d165 = new __allocGCInfo(_allocGCInfo);
callbacks[165] = Marshal.GetFunctionPointerForDelegate(d165);
delegates[165] = d165;
- var d166 = new __setEHcount(_setEHcount);
+ var d166 = new __yieldExecution(_yieldExecution);
callbacks[166] = Marshal.GetFunctionPointerForDelegate(d166);
delegates[166] = d166;
- var d167 = new __setEHinfo(_setEHinfo);
+ var d167 = new __setEHcount(_setEHcount);
callbacks[167] = Marshal.GetFunctionPointerForDelegate(d167);
delegates[167] = d167;
- var d168 = new __logMsg(_logMsg);
+ var d168 = new __setEHinfo(_setEHinfo);
callbacks[168] = Marshal.GetFunctionPointerForDelegate(d168);
delegates[168] = d168;
- var d169 = new __doAssert(_doAssert);
+ var d169 = new __logMsg(_logMsg);
callbacks[169] = Marshal.GetFunctionPointerForDelegate(d169);
delegates[169] = d169;
- var d170 = new __reportFatalError(_reportFatalError);
+ var d170 = new __doAssert(_doAssert);
callbacks[170] = Marshal.GetFunctionPointerForDelegate(d170);
delegates[170] = d170;
- var d171 = new __allocMethodBlockCounts(_allocMethodBlockCounts);
+ var d171 = new __reportFatalError(_reportFatalError);
callbacks[171] = Marshal.GetFunctionPointerForDelegate(d171);
delegates[171] = d171;
- var d172 = new __getMethodBlockCounts(_getMethodBlockCounts);
+ var d172 = new __allocMethodBlockCounts(_allocMethodBlockCounts);
callbacks[172] = Marshal.GetFunctionPointerForDelegate(d172);
delegates[172] = d172;
- var d173 = new __recordCallSite(_recordCallSite);
+ var d173 = new __getMethodBlockCounts(_getMethodBlockCounts);
callbacks[173] = Marshal.GetFunctionPointerForDelegate(d173);
delegates[173] = d173;
- var d174 = new __recordRelocation(_recordRelocation);
+ var d174 = new __recordCallSite(_recordCallSite);
callbacks[174] = Marshal.GetFunctionPointerForDelegate(d174);
delegates[174] = d174;
- var d175 = new __getRelocTypeHint(_getRelocTypeHint);
+ var d175 = new __recordRelocation(_recordRelocation);
callbacks[175] = Marshal.GetFunctionPointerForDelegate(d175);
delegates[175] = d175;
- var d176 = new __getModuleNativeEntryPointRange(_getModuleNativeEntryPointRange);
+ var d176 = new __getRelocTypeHint(_getRelocTypeHint);
callbacks[176] = Marshal.GetFunctionPointerForDelegate(d176);
delegates[176] = d176;
- var d177 = new __getExpectedTargetArchitecture(_getExpectedTargetArchitecture);
+ var d177 = new __getModuleNativeEntryPointRange(_getModuleNativeEntryPointRange);
callbacks[177] = Marshal.GetFunctionPointerForDelegate(d177);
delegates[177] = d177;
- var d178 = new __getJitFlags(_getJitFlags);
+ var d178 = new __getExpectedTargetArchitecture(_getExpectedTargetArchitecture);
callbacks[178] = Marshal.GetFunctionPointerForDelegate(d178);
delegates[178] = d178;
+ var d179 = new __getJitFlags(_getJitFlags);
+ callbacks[179] = Marshal.GetFunctionPointerForDelegate(d179);
+ delegates[179] = d179;
keepAlive = delegates;
return (IntPtr)callbacks;
diff --git a/src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.cs
index 63f817fba56314..4903aec134730a 100644
--- a/src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.cs
+++ b/src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.cs
@@ -1153,6 +1153,14 @@ private bool isValidStringRef(CORINFO_MODULE_STRUCT_* module, uint metaTOK)
private bool shouldEnforceCallvirtRestriction(CORINFO_MODULE_STRUCT_* scope)
{ throw new NotImplementedException("shouldEnforceCallvirtRestriction"); }
+ private char* getStringLiteral(CORINFO_MODULE_STRUCT_* module, uint metaTOK, ref int length)
+ {
+ MethodIL methodIL = (MethodIL)HandleToObject((IntPtr)module);
+ string s = (string)methodIL.GetObject((int)metaTOK);
+ length = (int)s.Length;
+ return (char*)GetPin(s);
+ }
+
private CorInfoType asCorInfoType(CORINFO_CLASS_STRUCT_* cls)
{
var type = HandleToObject(cls);
@@ -1189,7 +1197,7 @@ private CorInfoType asCorInfoType(CORINFO_CLASS_STRUCT_* cls)
}
- private int appendClassName(short** ppBuf, ref int pnBufLen, CORINFO_CLASS_STRUCT_* cls, bool fNamespace, bool fFullInst, bool fAssembly)
+ private int appendClassName(char** ppBuf, ref int pnBufLen, CORINFO_CLASS_STRUCT_* cls, bool fNamespace, bool fFullInst, bool fAssembly)
{
// We support enough of this to make SIMD work, but not much else.
@@ -1201,13 +1209,13 @@ private int appendClassName(short** ppBuf, ref int pnBufLen, CORINFO_CLASS_STRUC
int length = name.Length;
if (pnBufLen > 0)
{
- short* buffer = *ppBuf;
+ char* buffer = *ppBuf;
for (int i = 0; i < Math.Min(name.Length, pnBufLen); i++)
- buffer[i] = (short)name[i];
+ buffer[i] = name[i];
if (name.Length < pnBufLen)
- buffer[name.Length] = 0;
+ buffer[name.Length] = (char)0;
else
- buffer[pnBufLen - 1] = 0;
+ buffer[pnBufLen - 1] = (char)0;
pnBufLen -= length;
*ppBuf = buffer + length;
}
@@ -2061,221 +2069,6 @@ private CORINFO_FIELD_ACCESSOR getFieldIntrinsic(FieldDesc field)
return (CORINFO_FIELD_ACCESSOR)(-1);
}
- private void getFieldInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_METHOD_STRUCT_* callerHandle, CORINFO_ACCESS_FLAGS flags, CORINFO_FIELD_INFO* pResult)
- {
-#if DEBUG
- // In debug, write some bogus data to the struct to ensure we have filled everything
- // properly.
- MemoryHelper.FillMemory((byte*)pResult, 0xcc, Marshal.SizeOf());
-#endif
-
- Debug.Assert(((int)flags & ((int)CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_GET |
- (int)CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_SET |
- (int)CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_ADDRESS |
- (int)CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_INIT_ARRAY)) != 0);
-
- var field = HandleToObject(pResolvedToken.hField);
-#if READYTORUN
- MethodDesc callerMethod = HandleToObject(callerHandle);
-
- if (field.Offset.IsIndeterminate)
- throw new RequiresRuntimeJitException(field);
-#endif
-
- CORINFO_FIELD_ACCESSOR fieldAccessor;
- CORINFO_FIELD_FLAGS fieldFlags = (CORINFO_FIELD_FLAGS)0;
- uint fieldOffset = (field.IsStatic && field.HasRva ? 0xBAADF00D : (uint)field.Offset.AsInt);
-
- if (field.IsStatic)
- {
- fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_STATIC;
-
-#if READYTORUN
- if (field.FieldType.IsValueType && field.HasGCStaticBase && !field.HasRva)
- {
- // statics of struct types are stored as implicitly boxed in CoreCLR i.e.
- // we need to modify field access flags appropriately
- fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_STATIC_IN_HEAP;
- }
-#endif
-
- if (field.HasRva)
- {
- fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_UNMANAGED;
-
- // TODO: Handle the case when the RVA is in the TLS range
- fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_RVA_ADDRESS;
-
- // We are not going through a helper. The constructor has to be triggered explicitly.
-#if READYTORUN
- if (!IsClassPreInited(field.OwningType))
-#else
- if (_compilation.HasLazyStaticConstructor(field.OwningType))
-#endif
- {
- fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_INITCLASS;
- }
- }
- else if (field.OwningType.IsCanonicalSubtype(CanonicalFormKind.Any))
- {
- // The JIT wants to know how to access a static field on a generic type. We need a runtime lookup.
-#if READYTORUN
- fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_GENERICS_STATIC_HELPER;
- if (field.IsThreadStatic)
- {
- pResult->helper = (field.HasGCStaticBase ?
- CorInfoHelpFunc.CORINFO_HELP_GETGENERICS_GCTHREADSTATIC_BASE:
- CorInfoHelpFunc.CORINFO_HELP_GETGENERICS_NONGCTHREADSTATIC_BASE);
- }
- else
- {
- pResult->helper = (field.HasGCStaticBase ?
- CorInfoHelpFunc.CORINFO_HELP_GETGENERICS_GCSTATIC_BASE:
- CorInfoHelpFunc.CORINFO_HELP_GETGENERICS_NONGCSTATIC_BASE);
- }
-#else
- fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_READYTORUN_HELPER;
- pResult->helper = CorInfoHelpFunc.CORINFO_HELP_READYTORUN_GENERIC_STATIC_BASE;
-
- // Don't try to compute the runtime lookup if we're inlining. The JIT is going to abort the inlining
- // attempt anyway.
- MethodDesc contextMethod = methodFromContext(pResolvedToken.tokenContext);
- if (contextMethod == MethodBeingCompiled)
- {
- FieldDesc runtimeDeterminedField = (FieldDesc)GetRuntimeDeterminedObjectForToken(ref pResolvedToken);
-
- ReadyToRunHelperId helperId;
-
- // Find out what kind of base do we need to look up.
- if (field.IsThreadStatic)
- {
- helperId = ReadyToRunHelperId.GetThreadStaticBase;
- }
- else if (field.HasGCStaticBase)
- {
- helperId = ReadyToRunHelperId.GetGCStaticBase;
- }
- else
- {
- helperId = ReadyToRunHelperId.GetNonGCStaticBase;
- }
-
- // What generic context do we look up the base from.
- ISymbolNode helper;
- if (contextMethod.AcquiresInstMethodTableFromThis() || contextMethod.RequiresInstMethodTableArg())
- {
- helper = _compilation.NodeFactory.ReadyToRunHelperFromTypeLookup(
- helperId, runtimeDeterminedField.OwningType, contextMethod.OwningType);
- }
- else
- {
- Debug.Assert(contextMethod.RequiresInstMethodDescArg());
- helper = _compilation.NodeFactory.ReadyToRunHelperFromDictionaryLookup(
- helperId, runtimeDeterminedField.OwningType, contextMethod);
- }
-
- pResult->fieldLookup = CreateConstLookupToSymbol(helper);
- }
-#endif // READYTORUN
- }
- else
- {
- fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER;
- pResult->helper = CorInfoHelpFunc.CORINFO_HELP_READYTORUN_STATIC_BASE;
-
- ReadyToRunHelperId helperId = ReadyToRunHelperId.Invalid;
- CORINFO_FIELD_ACCESSOR intrinsicAccessor;
- if (field.IsIntrinsic &&
- (flags & CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_GET) != 0 &&
- (intrinsicAccessor = getFieldIntrinsic(field)) != (CORINFO_FIELD_ACCESSOR)(-1))
- {
- fieldAccessor = intrinsicAccessor;
- }
- else if (field.IsThreadStatic)
- {
-#if READYTORUN
- if (field.HasGCStaticBase)
- {
- helperId = ReadyToRunHelperId.GetThreadStaticBase;
- }
- else
- {
- helperId = ReadyToRunHelperId.GetThreadNonGcStaticBase;
- }
-#else
- helperId = ReadyToRunHelperId.GetThreadStaticBase;
-#endif
- }
- else
- {
- helperId = field.HasGCStaticBase ?
- ReadyToRunHelperId.GetGCStaticBase :
- ReadyToRunHelperId.GetNonGCStaticBase;
-
- //
- // Currently, we only do this optimization for regular statics, but it
- // looks like it may be permissible to do this optimization for
- // thread statics as well.
- //
- if ((flags & CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_ADDRESS) != 0 &&
- (fieldAccessor != CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_TLS))
- {
- fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_SAFESTATIC_BYREF_RETURN;
- }
- }
-
-#if READYTORUN
- if (!_compilation.NodeFactory.CompilationModuleGroup.VersionsWithType(field.OwningType) &&
- fieldAccessor == CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER)
- {
- PreventRecursiveFieldInlinesOutsideVersionBubble(field, callerMethod);
-
- // Static fields outside of the version bubble need to be accessed using the ENCODE_FIELD_ADDRESS
- // helper in accordance with ZapInfo::getFieldInfo in CoreCLR.
- pResult->fieldLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.FieldAddress(field, GetSignatureContext()));
-
- pResult->helper = CorInfoHelpFunc.CORINFO_HELP_READYTORUN_STATIC_BASE;
-
- fieldFlags &= ~CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_STATIC_IN_HEAP; // The dynamic helper takes care of the unboxing
- fieldOffset = 0;
- }
- else
-#endif
-
- if (helperId != ReadyToRunHelperId.Invalid)
- {
- pResult->fieldLookup = CreateConstLookupToSymbol(
-#if READYTORUN
- _compilation.SymbolNodeFactory.CreateReadyToRunHelper(helperId, field.OwningType, GetSignatureContext())
-#else
- _compilation.NodeFactory.ReadyToRunHelper(helperId, field.OwningType)
-#endif
- );
- }
- }
- }
- else
- {
- fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_INSTANCE;
- }
-
- if (field.IsInitOnly)
- fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_FINAL;
-
- pResult->fieldAccessor = fieldAccessor;
- pResult->fieldFlags = fieldFlags;
- pResult->fieldType = getFieldType(pResolvedToken.hField, &pResult->structType, pResolvedToken.hClass);
- pResult->accessAllowed = CorInfoIsAccessAllowedResult.CORINFO_ACCESS_ALLOWED;
- pResult->offset = fieldOffset;
-
-#if READYTORUN
- EncodeFieldBaseOffset(field, pResult, callerMethod);
-#endif
-
- // TODO: We need to implement access checks for fields and methods. See JitInterface.cpp in mrtjit
- // and STS::AccessCheck::CanAccess.
- }
-
private bool isFieldStatic(CORINFO_FIELD_STRUCT_* fldHnd)
{
return HandleToObject(fldHnd).IsStatic;
@@ -2367,7 +2160,7 @@ private CorInfoType getHFAType(CORINFO_CLASS_STRUCT_* hClass)
private HRESULT GetErrorHRESULT(_EXCEPTION_POINTERS* pExceptionPointers)
{ throw new NotImplementedException("GetErrorHRESULT"); }
- private uint GetErrorMessage(short* buffer, uint bufferLength)
+ private uint GetErrorMessage(char* buffer, uint bufferLength)
{ throw new NotImplementedException("GetErrorMessage"); }
private int FilterException(_EXCEPTION_POINTERS* pExceptionPointers)
@@ -2430,7 +2223,7 @@ private void getEEInfo(ref CORINFO_EE_INFO pEEInfoOut)
pEEInfoOut.osType = _compilation.NodeFactory.Target.IsWindows ? CORINFO_OS.CORINFO_WINNT : CORINFO_OS.CORINFO_UNIX;
}
- private string getJitTimeLogFilename()
+ private char* getJitTimeLogFilename()
{
return null;
}
diff --git a/src/coreclr/src/tools/Common/JitInterface/CorInfoTypes.cs b/src/coreclr/src/tools/Common/JitInterface/CorInfoTypes.cs
index 9f211d80a50fd4..e249197fd3480a 100644
--- a/src/coreclr/src/tools/Common/JitInterface/CorInfoTypes.cs
+++ b/src/coreclr/src/tools/Common/JitInterface/CorInfoTypes.cs
@@ -764,6 +764,8 @@ public enum CorJitAllocMemFlag
CORJIT_ALLOCMEM_DEFAULT_CODE_ALIGN = 0x00000000, // The code will be use the normal alignment
CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN = 0x00000001, // The code will be 16-byte aligned
CORJIT_ALLOCMEM_FLG_RODATA_16BYTE_ALIGN = 0x00000002, // The read-only data will be 16-byte aligned
+ CORJIT_ALLOCMEM_FLG_32BYTE_ALIGN = 0x00000004, // The code will be 32-byte aligned
+ CORJIT_ALLOCMEM_FLG_RODATA_32BYTE_ALIGN = 0x00000008, // The read-only data will be 32-byte aligned
}
public enum CorJitFuncKind
diff --git a/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/Program.cs b/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/Program.cs
index 499014b233790a..78b513211cc4a0 100644
--- a/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/Program.cs
+++ b/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/Program.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt
index fffc0de16cd8e9..a124f01f0e85b2 100644
--- a/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt
+++ b/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt
@@ -72,11 +72,11 @@ ULONG32*,ref uint,unsigned int*
LONG*,int*,long*
char*,byte*
const char**,byte**
-WCHAR**,short**,wchar_t**
+WCHAR**,char**,wchar_t**
LPCSTR,byte*,const char*
-LPWSTR,short*,wchar_t*
-LPCWSTR,short*,const wchar_t*
-wchar_t*,short*
+LPWSTR,char*,wchar_t*
+LPCWSTR,char*,const wchar_t*
+wchar_t*,char*
const wchar_t*,String
DWORD**,ref uint*,unsigned int**
@@ -158,7 +158,6 @@ struct _EXCEPTION_POINTERS*,_EXCEPTION_POINTERS*,void*
RETURNTYPES
BOOL,[return: MarshalAs(UnmanagedType.Bool)]bool,int
bool,[return: MarshalAs(UnmanagedType.I1)]bool
-LPCWSTR,[return: MarshalAs(UnmanagedType.LPWStr)]string,const wchar_t*
; NOTE in managed SIZE_T is an enum that is 64bits in size, and returning one of those causing mcg to do the wrong thing.
size_t,byte*,size_t
@@ -199,6 +198,7 @@ FUNCTIONS
CorInfoCanSkipVerificationResult canSkipVerification(CORINFO_MODULE_HANDLE module)
BOOL isValidToken(CORINFO_MODULE_HANDLE module, unsigned metaTOK)
BOOL isValidStringRef(CORINFO_MODULE_HANDLE module, unsigned metaTOK)
+ LPCWSTR getStringLiteral(CORINFO_MODULE_HANDLE module, unsigned metaTOK, int* length)
BOOL shouldEnforceCallvirtRestriction(CORINFO_MODULE_HANDLE scope)
CorInfoType asCorInfoType(CORINFO_CLASS_HANDLE cls)
const char* getClassName(CORINFO_CLASS_HANDLE cls)
diff --git a/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/gen.bat b/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/gen.bat
index 2fec5117581829..46328b52d08baf 100644
--- a/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/gen.bat
+++ b/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/gen.bat
@@ -1,2 +1,2 @@
cd /d %~dp0
-dotnet run -- ThunkInput.txt ..\CorInfoBase.cs ..\..\..\jitinterface\jitinterface.h
\ No newline at end of file
+dotnet run -- ThunkInput.txt ..\CorInfoBase.cs ..\..\..\crossgen2\jitinterface\jitinterface.h
\ No newline at end of file
diff --git a/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/gen.sh b/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/gen.sh
index 3eb458d6200b33..59672c72d4156b 100755
--- a/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/gen.sh
+++ b/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/gen.sh
@@ -1,3 +1,3 @@
#!/usr/bin/env bash
cd "$(dirname ${BASH_SOURCE[0]})"
-dotnet run -- ThunkInput.txt ../CorInfoBase.cs ../../../jitinterface/jitinterface.h
+dotnet run -- ThunkInput.txt ../CorInfoBase.cs ../../../crossgen2/jitinterface/jitinterface.h
diff --git a/src/coreclr/src/tools/Common/System/FormattingHelpers.cs b/src/coreclr/src/tools/Common/System/FormattingHelpers.cs
index de7a6370a0a3d4..62ff1152e76a2b 100644
--- a/src/coreclr/src/tools/Common/System/FormattingHelpers.cs
+++ b/src/coreclr/src/tools/Common/System/FormattingHelpers.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/TypeSystem/Canon/ArrayType.Canon.cs b/src/coreclr/src/tools/Common/TypeSystem/Canon/ArrayType.Canon.cs
index 04bd817fa7d5b9..20e92e0ae1f208 100644
--- a/src/coreclr/src/tools/Common/TypeSystem/Canon/ArrayType.Canon.cs
+++ b/src/coreclr/src/tools/Common/TypeSystem/Canon/ArrayType.Canon.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/TypeSystem/Canon/ByRefType.Canon.cs b/src/coreclr/src/tools/Common/TypeSystem/Canon/ByRefType.Canon.cs
index 921eb901487e69..a0629e6c85669d 100644
--- a/src/coreclr/src/tools/Common/TypeSystem/Canon/ByRefType.Canon.cs
+++ b/src/coreclr/src/tools/Common/TypeSystem/Canon/ByRefType.Canon.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/TypeSystem/Canon/CanonTypes.Diagnostic.cs b/src/coreclr/src/tools/Common/TypeSystem/Canon/CanonTypes.Diagnostic.cs
index 3c4098cb4d04c8..ea8ab87af27b68 100644
--- a/src/coreclr/src/tools/Common/TypeSystem/Canon/CanonTypes.Diagnostic.cs
+++ b/src/coreclr/src/tools/Common/TypeSystem/Canon/CanonTypes.Diagnostic.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/TypeSystem/Canon/CanonTypes.cs b/src/coreclr/src/tools/Common/TypeSystem/Canon/CanonTypes.cs
index d84341b154063a..943452f96b378a 100644
--- a/src/coreclr/src/tools/Common/TypeSystem/Canon/CanonTypes.cs
+++ b/src/coreclr/src/tools/Common/TypeSystem/Canon/CanonTypes.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -71,7 +71,7 @@ protected override MethodImplRecord[] ComputeVirtualMethodImplsForType()
public override bool IsExplicitLayout => false;
- public override ModuleDesc Module => _context.CanonTypesModule;
+ public override ModuleDesc Module => _context.SystemModule;
public override bool IsModuleType => false;
diff --git a/src/coreclr/src/tools/Common/TypeSystem/Canon/DefType.Canon.cs b/src/coreclr/src/tools/Common/TypeSystem/Canon/DefType.Canon.cs
index 75c03bb4601066..7e782f33717e29 100644
--- a/src/coreclr/src/tools/Common/TypeSystem/Canon/DefType.Canon.cs
+++ b/src/coreclr/src/tools/Common/TypeSystem/Canon/DefType.Canon.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/TypeSystem/Canon/InstantiatedMethod.Canon.cs b/src/coreclr/src/tools/Common/TypeSystem/Canon/InstantiatedMethod.Canon.cs
index 4e3e0204e77ed9..f77f5039ee4c2a 100644
--- a/src/coreclr/src/tools/Common/TypeSystem/Canon/InstantiatedMethod.Canon.cs
+++ b/src/coreclr/src/tools/Common/TypeSystem/Canon/InstantiatedMethod.Canon.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/TypeSystem/Canon/InstantiatedType.Canon.cs b/src/coreclr/src/tools/Common/TypeSystem/Canon/InstantiatedType.Canon.cs
index 8ed86f39c2ee5f..4049a265dc124b 100644
--- a/src/coreclr/src/tools/Common/TypeSystem/Canon/InstantiatedType.Canon.cs
+++ b/src/coreclr/src/tools/Common/TypeSystem/Canon/InstantiatedType.Canon.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/TypeSystem/Canon/MetadataType.Canon.cs b/src/coreclr/src/tools/Common/TypeSystem/Canon/MetadataType.Canon.cs
index 97d2dba198580e..a8a9d97ab5c3d0 100644
--- a/src/coreclr/src/tools/Common/TypeSystem/Canon/MetadataType.Canon.cs
+++ b/src/coreclr/src/tools/Common/TypeSystem/Canon/MetadataType.Canon.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/TypeSystem/Canon/MethodDesc.Canon.cs b/src/coreclr/src/tools/Common/TypeSystem/Canon/MethodDesc.Canon.cs
index ad9e3d6b7fcfca..3714346d73f603 100644
--- a/src/coreclr/src/tools/Common/TypeSystem/Canon/MethodDesc.Canon.cs
+++ b/src/coreclr/src/tools/Common/TypeSystem/Canon/MethodDesc.Canon.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/TypeSystem/Canon/ParameterizedType.Canon.cs b/src/coreclr/src/tools/Common/TypeSystem/Canon/ParameterizedType.Canon.cs
index 471022fc070f23..ad386bb04d1333 100644
--- a/src/coreclr/src/tools/Common/TypeSystem/Canon/ParameterizedType.Canon.cs
+++ b/src/coreclr/src/tools/Common/TypeSystem/Canon/ParameterizedType.Canon.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/TypeSystem/Canon/PointerType.Canon.cs b/src/coreclr/src/tools/Common/TypeSystem/Canon/PointerType.Canon.cs
index ae189951217b30..ce4c96d5d0064d 100644
--- a/src/coreclr/src/tools/Common/TypeSystem/Canon/PointerType.Canon.cs
+++ b/src/coreclr/src/tools/Common/TypeSystem/Canon/PointerType.Canon.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/TypeSystem/Canon/SignatureVariable.Canon.cs b/src/coreclr/src/tools/Common/TypeSystem/Canon/SignatureVariable.Canon.cs
index a7da04a857cc94..381d92db189ee6 100644
--- a/src/coreclr/src/tools/Common/TypeSystem/Canon/SignatureVariable.Canon.cs
+++ b/src/coreclr/src/tools/Common/TypeSystem/Canon/SignatureVariable.Canon.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/TypeSystem/Canon/StandardCanonicalizationAlgorithm.cs b/src/coreclr/src/tools/Common/TypeSystem/Canon/StandardCanonicalizationAlgorithm.cs
index 8cac891b311b27..04579bc1aef11e 100644
--- a/src/coreclr/src/tools/Common/TypeSystem/Canon/StandardCanonicalizationAlgorithm.cs
+++ b/src/coreclr/src/tools/Common/TypeSystem/Canon/StandardCanonicalizationAlgorithm.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/TypeSystem/Canon/TypeDesc.Canon.cs b/src/coreclr/src/tools/Common/TypeSystem/Canon/TypeDesc.Canon.cs
index c4c141c42a3092..690369ab27ae0a 100644
--- a/src/coreclr/src/tools/Common/TypeSystem/Canon/TypeDesc.Canon.cs
+++ b/src/coreclr/src/tools/Common/TypeSystem/Canon/TypeDesc.Canon.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/TypeSystem/Canon/TypeSystemContext.Canon.cs b/src/coreclr/src/tools/Common/TypeSystem/Canon/TypeSystemContext.Canon.cs
index 444f24b67a664b..268bf73b7f60f0 100644
--- a/src/coreclr/src/tools/Common/TypeSystem/Canon/TypeSystemContext.Canon.cs
+++ b/src/coreclr/src/tools/Common/TypeSystem/Canon/TypeSystemContext.Canon.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -44,11 +44,6 @@ public CanonBaseType UniversalCanonType
}
}
- protected internal virtual ModuleDesc CanonTypesModule
- {
- get { return SystemModule; }
- }
-
///
/// Returns true if and only if the '' is __Canon or __UniversalCanon
/// that matches the parameter.
diff --git a/src/coreclr/src/tools/Common/TypeSystem/Common/ExplicitLayoutValidator.cs b/src/coreclr/src/tools/Common/TypeSystem/Common/ExplicitLayoutValidator.cs
index b1c4ae54a09a00..9e7c4c6f908da7 100644
--- a/src/coreclr/src/tools/Common/TypeSystem/Common/ExplicitLayoutValidator.cs
+++ b/src/coreclr/src/tools/Common/TypeSystem/Common/ExplicitLayoutValidator.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/TypeSystem/Common/IModuleResolver.cs b/src/coreclr/src/tools/Common/TypeSystem/Common/IModuleResolver.cs
index 92c01abe9ee351..eccacb2a2d5772 100644
--- a/src/coreclr/src/tools/Common/TypeSystem/Common/IModuleResolver.cs
+++ b/src/coreclr/src/tools/Common/TypeSystem/Common/IModuleResolver.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs b/src/coreclr/src/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs
index b0be4b8430bac9..596bca577b510e 100644
--- a/src/coreclr/src/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs
+++ b/src/coreclr/src/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs
@@ -425,7 +425,7 @@ protected static ComputedInstanceFieldLayout ComputeSequentialFieldLayout(Metada
return computedLayout;
}
- protected virtual void AlignBaseOffsetIfNecessary(MetadataType type, ref LayoutInt baseOffset)
+ protected virtual void AlignBaseOffsetIfNecessary(MetadataType type, ref LayoutInt baseOffset, bool requiresAlign8)
{
}
@@ -434,8 +434,6 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type,
// For types inheriting from another type, field offsets continue on from where they left off
LayoutInt cumulativeInstanceFieldPos = ComputeBytesUsedInParentType(type);
- AlignBaseOffsetIfNecessary(type, ref cumulativeInstanceFieldPos);
-
var layoutMetadata = type.GetClassLayout();
int packingSize = ComputePackingSize(type, layoutMetadata);
@@ -459,6 +457,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type,
continue;
TypeDesc fieldType = field.FieldType;
+
if (IsByValueClass(fieldType))
{
instanceValueClassFieldCount++;
@@ -495,6 +494,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type,
// Reset the counters to be used later as the index to insert into the array
instanceGCPointerFieldsCount = 0;
instanceValueClassFieldCount = 0;
+ LayoutInt largestAlignmentRequired = LayoutInt.One;
// Iterate over all fields and do the following
// - Add instance fields to the appropriate array (while maintaining the enumerated order)
@@ -506,6 +506,9 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type,
TypeDesc fieldType = field.FieldType;
+ var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, packingSize);
+ largestAlignmentRequired = LayoutInt.Max(fieldSizeAndAlignment.Alignment, largestAlignmentRequired);
+
if (IsByValueClass(fieldType))
{
instanceValueClassFieldsArr[instanceValueClassFieldCount++] = field;
@@ -516,12 +519,14 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type,
}
else
{
- var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, packingSize);
int log2size = CalculateLog2(fieldSizeAndAlignment.Size.AsInt);
instanceNonGCPointerFieldsArr[log2size][instanceNonGCPointerFieldsCount[log2size]++] = field;
}
}
+ largestAlignmentRequired = type.Context.Target.GetObjectAlignment(largestAlignmentRequired);
+ AlignBaseOffsetIfNecessary(type, ref cumulativeInstanceFieldPos, largestAlignmentRequired.AsInt > 4);
+
// We've finished placing the fields into their appropriate arrays
// The next optimization may place non-GC Pointers, so repurpose our
// counter to keep track of the next non-GC Pointer that must be placed
diff --git a/src/coreclr/src/tools/Common/TypeSystem/Common/MetadataType.MethodImpls.cs b/src/coreclr/src/tools/Common/TypeSystem/Common/MetadataType.MethodImpls.cs
index b41133e36fa910..74ec106694eb29 100644
--- a/src/coreclr/src/tools/Common/TypeSystem/Common/MetadataType.MethodImpls.cs
+++ b/src/coreclr/src/tools/Common/TypeSystem/Common/MetadataType.MethodImpls.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/TypeSystem/Common/TargetDetails.cs b/src/coreclr/src/tools/Common/TypeSystem/Common/TargetDetails.cs
index fd81aad4755a8f..8f910dd00636ee 100644
--- a/src/coreclr/src/tools/Common/TypeSystem/Common/TargetDetails.cs
+++ b/src/coreclr/src/tools/Common/TypeSystem/Common/TargetDetails.cs
@@ -323,7 +323,7 @@ public int MaximumHfaElementCount
get
{
// There is a hard limit of 4 elements on an HFA type, see
- // http://blogs.msdn.com/b/vcblog/archive/2013/07/12/introducing-vector-calling-convention.aspx
+ // https://devblogs.microsoft.com/cppblog/introducing-vector-calling-convention/
Debug.Assert(Architecture == TargetArchitecture.ARM ||
Architecture == TargetArchitecture.ARM64 ||
Architecture == TargetArchitecture.X64 ||
diff --git a/src/coreclr/src/tools/Common/TypeSystem/Ecma/SymbolReader/UnmanagedPdbSymbolReader.cs b/src/coreclr/src/tools/Common/TypeSystem/Ecma/SymbolReader/UnmanagedPdbSymbolReader.cs
index 87c9bf41f4e6cf..5b6d1ea8b81912 100644
--- a/src/coreclr/src/tools/Common/TypeSystem/Ecma/SymbolReader/UnmanagedPdbSymbolReader.cs
+++ b/src/coreclr/src/tools/Common/TypeSystem/Ecma/SymbolReader/UnmanagedPdbSymbolReader.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/TypeSystem/Interop/InteropTypes.cs b/src/coreclr/src/tools/Common/TypeSystem/Interop/InteropTypes.cs
index 2530f1b24e1336..4231594e612da7 100644
--- a/src/coreclr/src/tools/Common/TypeSystem/Interop/InteropTypes.cs
+++ b/src/coreclr/src/tools/Common/TypeSystem/Interop/InteropTypes.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/TypeSystem/RuntimeDetermined/DefType.RuntimeDetermined.cs b/src/coreclr/src/tools/Common/TypeSystem/RuntimeDetermined/DefType.RuntimeDetermined.cs
index 02d1b252339b84..b2f669b228d8e1 100644
--- a/src/coreclr/src/tools/Common/TypeSystem/RuntimeDetermined/DefType.RuntimeDetermined.cs
+++ b/src/coreclr/src/tools/Common/TypeSystem/RuntimeDetermined/DefType.RuntimeDetermined.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/TypeSystem/RuntimeDetermined/ParameterizedType.RuntimeDetermined.cs b/src/coreclr/src/tools/Common/TypeSystem/RuntimeDetermined/ParameterizedType.RuntimeDetermined.cs
index f48325c7ebdb90..df1723270778f5 100644
--- a/src/coreclr/src/tools/Common/TypeSystem/RuntimeDetermined/ParameterizedType.RuntimeDetermined.cs
+++ b/src/coreclr/src/tools/Common/TypeSystem/RuntimeDetermined/ParameterizedType.RuntimeDetermined.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/TypeSystem/RuntimeDetermined/RuntimeDeterminedCanonicalizationAlgorithm.cs b/src/coreclr/src/tools/Common/TypeSystem/RuntimeDetermined/RuntimeDeterminedCanonicalizationAlgorithm.cs
index f1ea5fc96b0b1f..6ba17638ee0ef1 100644
--- a/src/coreclr/src/tools/Common/TypeSystem/RuntimeDetermined/RuntimeDeterminedCanonicalizationAlgorithm.cs
+++ b/src/coreclr/src/tools/Common/TypeSystem/RuntimeDetermined/RuntimeDeterminedCanonicalizationAlgorithm.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/Common/TypeSystem/RuntimeDetermined/RuntimeDeterminedFieldLayoutAlgorithm.cs b/src/coreclr/src/tools/Common/TypeSystem/RuntimeDetermined/RuntimeDeterminedFieldLayoutAlgorithm.cs
index 75039d735b2334..91c3d9e1f1149b 100644
--- a/src/coreclr/src/tools/Common/TypeSystem/RuntimeDetermined/RuntimeDeterminedFieldLayoutAlgorithm.cs
+++ b/src/coreclr/src/tools/Common/TypeSystem/RuntimeDetermined/RuntimeDeterminedFieldLayoutAlgorithm.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/GCLogParser/App.config b/src/coreclr/src/tools/GCLogParser/App.config
index ffaf5407a91075..c8f375802e873d 100644
--- a/src/coreclr/src/tools/GCLogParser/App.config
+++ b/src/coreclr/src/tools/GCLogParser/App.config
@@ -1,4 +1,4 @@
-
+
diff --git a/src/coreclr/src/tools/GCLogParser/parse-hb-log.csproj b/src/coreclr/src/tools/GCLogParser/parse-hb-log.csproj
index 940cb96f0ea3bc..f30e869f4b2d2f 100644
--- a/src/coreclr/src/tools/GCLogParser/parse-hb-log.csproj
+++ b/src/coreclr/src/tools/GCLogParser/parse-hb-log.csproj
@@ -1,4 +1,4 @@
-
+
diff --git a/src/coreclr/src/tools/GCLogParser/parse-hb-log.sln b/src/coreclr/src/tools/GCLogParser/parse-hb-log.sln
index 5ae5dcb65cd257..71aa126764ceec 100644
--- a/src/coreclr/src/tools/GCLogParser/parse-hb-log.sln
+++ b/src/coreclr/src/tools/GCLogParser/parse-hb-log.sln
@@ -1,4 +1,4 @@
-
+
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.28803.452
diff --git a/src/coreclr/src/tools/ReadyToRun.SuperIlc/Buckets.cs b/src/coreclr/src/tools/ReadyToRun.SuperIlc/Buckets.cs
index 43e602aee47ce6..04052349244d87 100644
--- a/src/coreclr/src/tools/ReadyToRun.SuperIlc/Buckets.cs
+++ b/src/coreclr/src/tools/ReadyToRun.SuperIlc/Buckets.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/ReadyToRun.SuperIlc/BuildFolder.cs b/src/coreclr/src/tools/ReadyToRun.SuperIlc/BuildFolder.cs
index d5f10808764b0e..567242b4a2db45 100644
--- a/src/coreclr/src/tools/ReadyToRun.SuperIlc/BuildFolder.cs
+++ b/src/coreclr/src/tools/ReadyToRun.SuperIlc/BuildFolder.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -46,16 +46,31 @@ public BuildFolder(
_compilations = new List();
_executions = new List();
- foreach (string file in _compilationInputFiles)
+ if (options.Composite)
{
ProcessInfo[] fileCompilations = new ProcessInfo[(int)CompilerIndex.Count];
foreach (CompilerRunner runner in compilerRunners)
{
- ProcessInfo compilationProcess = new ProcessInfo(new CompilationProcessConstructor(runner, _outputFolder, file));
+ string outputFile = runner.GetOutputFileName(_outputFolder, "composite-r2r.dll");
+ ProcessInfo compilationProcess = new ProcessInfo(new CompilationProcessConstructor(runner, outputFile, _compilationInputFiles));
fileCompilations[(int)runner.Index] = compilationProcess;
}
_compilations.Add(fileCompilations);
}
+ else
+ {
+ foreach (string file in _compilationInputFiles)
+ {
+ ProcessInfo[] fileCompilations = new ProcessInfo[(int)CompilerIndex.Count];
+ foreach (CompilerRunner runner in compilerRunners)
+ {
+ string outputFile = runner.GetOutputFileName(_outputFolder, file);
+ ProcessInfo compilationProcess = new ProcessInfo(new CompilationProcessConstructor(runner, outputFile, new string[] { file }));
+ fileCompilations[(int)runner.Index] = compilationProcess;
+ }
+ _compilations.Add(fileCompilations);
+ }
+ }
if (!options.NoExe)
{
@@ -98,7 +113,8 @@ public static BuildFolder FromDirectory(string inputDirectory, IEnumerable>[] allMethodsPerModulePerCompiler = new Dictionary>[(int)CompilerIndex.Count];
+ var allMethodsPerModulePerCompiler = new Dictionary>[(int)CompilerIndex.Count];
foreach (CompilerRunner runner in _compilerRunners)
{
@@ -108,7 +108,7 @@ private void WriteJittedMethodSummary(StreamWriter logWriter)
{
for (int exeIndex = 0; exeIndex < folder.Executions.Count; exeIndex++)
{
- Dictionary>[] appMethodsPerModulePerCompiler = new Dictionary>[(int)CompilerIndex.Count];
+ var appMethodsPerModulePerCompiler = new Dictionary>[(int)CompilerIndex.Count];
foreach (CompilerRunner runner in _compilerRunners)
{
appMethodsPerModulePerCompiler[(int)runner.Index] = new Dictionary>();
@@ -129,12 +129,11 @@ public bool Compile()
return false;
}
- Stopwatch stopwatch = new Stopwatch();
- stopwatch.Start();
+ Stopwatch stopwatch = Stopwatch.StartNew();
ResolveTestExclusions();
- List compilationsToRun = new List();
+ var compilationsToRun = new List();
foreach (BuildFolder folder in FoldersToBuild)
{
@@ -154,16 +153,16 @@ public bool Compile()
ParallelRunner.Run(compilationsToRun, _options.DegreeOfParallelism, _options.MeasurePerf);
bool success = true;
- List> failedCompilationsPerBuilder = new List>();
+ var failedCompilationsPerBuilder = new List>();
int successfulCompileCount = 0;
- List r2rDumpExecutionsToRun = new List();
+ var r2rDumpExecutionsToRun = new List();
foreach (BuildFolder folder in FoldersToBuild)
{
foreach (ProcessInfo[] compilation in folder.Compilations)
{
- string file = null;
+ HashSet failedFiles = new HashSet();
string failedBuilders = null;
foreach (CompilerRunner runner in _compilerRunners)
{
@@ -184,17 +183,9 @@ public bool Compile()
else // runner process failed
{
_compilationFailureBuckets.AddCompilation(runnerProcess);
- try
+ failedFiles.UnionWith(runnerProcess.Parameters.InputFileNames);
+ if (failedBuilders == null)
{
- File.Copy(runnerProcess.Parameters.InputFileName, runnerProcess.Parameters.OutputFileName);
- }
- catch (Exception ex)
- {
- Console.Error.WriteLine("Error copying {0} to {1}: {2}", runnerProcess.Parameters.InputFileName, runnerProcess.Parameters.OutputFileName, ex.Message);
- }
- if (file == null)
- {
- file = runnerProcess.Parameters.InputFileName;
failedBuilders = runner.CompilerName;
}
else
@@ -203,9 +194,12 @@ public bool Compile()
}
}
}
- if (file != null)
+ if (failedFiles.Count > 0)
{
- failedCompilationsPerBuilder.Add(new KeyValuePair(file, failedBuilders));
+ foreach (string file in failedFiles)
+ {
+ failedCompilationsPerBuilder.Add(new KeyValuePair(file, failedBuilders));
+ }
success = false;
}
else
@@ -235,7 +229,7 @@ public bool Compile()
causeOfFailure = "Unknown cause of failure";
}
- Console.Error.WriteLine("Error running R2R dump on {0}: {1}", r2rDumpExecution.Parameters.InputFileName, causeOfFailure);
+ Console.Error.WriteLine("Error running R2R dump on {0}: {1}", string.Join(", ", r2rDumpExecution.Parameters.InputFileNames), causeOfFailure);
success = false;
}
}
@@ -252,8 +246,7 @@ public bool CompileFramework()
return true;
}
- Stopwatch stopwatch = new Stopwatch();
- stopwatch.Start();
+ Stopwatch stopwatch = Stopwatch.StartNew();
string coreRoot = _options.CoreRootDirectory.FullName;
string[] frameworkFolderFiles = Directory.GetFiles(coreRoot);
@@ -268,37 +261,71 @@ public bool CompileFramework()
outputPath.RecreateDirectory();
}
- List compilationsToRun = new List();
- List> compilationsPerRunner = new List>();
- List excludedAssemblies = new List();
- foreach (string frameworkDll in ComputeManagedAssemblies.GetManagedAssembliesInFolder(_options.CoreRootDirectory.FullName))
- {
- string simpleName = Path.GetFileNameWithoutExtension(frameworkDll);
- FrameworkExclusion exclusion = s_frameworkExclusions.FirstOrDefault(asm => asm.SimpleName.Equals(simpleName, StringComparison.OrdinalIgnoreCase));
+ var compilationsToRun = new List();
+ var compilationsPerRunner = new List>();
+ var excludedAssemblies = new List();
- ProcessInfo[] processes = new ProcessInfo[(int)CompilerIndex.Count];
- compilationsPerRunner.Add(new KeyValuePair(frameworkDll, processes));
+ if (_options.Composite)
+ {
+ var processes = new ProcessInfo[(int)CompilerIndex.Count];
foreach (CompilerRunner runner in frameworkRunners)
{
- if (exclusion != null && (!exclusion.Crossgen2Only || runner.Index == CompilerIndex.CPAOT))
+ List inputFrameworkDlls = new List();
+ foreach (string frameworkDll in ComputeManagedAssemblies.GetManagedAssembliesInFolder(_options.CoreRootDirectory.FullName))
{
- _frameworkExclusions[exclusion.SimpleName] = exclusion.Reason;
- continue;
+ string simpleName = Path.GetFileNameWithoutExtension(frameworkDll);
+ FrameworkExclusion exclusion = s_frameworkExclusions.FirstOrDefault(asm => asm.SimpleName.Equals(simpleName, StringComparison.OrdinalIgnoreCase));
+ if (exclusion != null && (!exclusion.Crossgen2Only || runner.Index == CompilerIndex.CPAOT))
+ {
+ _frameworkExclusions[exclusion.SimpleName] = exclusion.Reason;
+ }
+ else
+ {
+ inputFrameworkDlls.Add(frameworkDll);
+ compilationsPerRunner.Add(new KeyValuePair(frameworkDll, processes));
+ }
+ }
+
+ if (inputFrameworkDlls.Count > 0)
+ {
+ string outputFileName = runner.GetOutputFileName(_options.CoreRootDirectory.FullName, "framework");
+ ProcessInfo compilationProcess = new ProcessInfo(new CompilationProcessConstructor(runner, outputFileName, inputFrameworkDlls));
+ compilationsToRun.Add(compilationProcess);
+ processes[(int)runner.Index] = compilationProcess;
+ }
+ }
+ }
+ else
+ {
+ foreach (string frameworkDll in ComputeManagedAssemblies.GetManagedAssembliesInFolder(_options.CoreRootDirectory.FullName))
+ {
+ string simpleName = Path.GetFileNameWithoutExtension(frameworkDll);
+ FrameworkExclusion exclusion = s_frameworkExclusions.FirstOrDefault(asm => asm.SimpleName.Equals(simpleName, StringComparison.OrdinalIgnoreCase));
+
+ ProcessInfo[] processes = new ProcessInfo[(int)CompilerIndex.Count];
+ compilationsPerRunner.Add(new KeyValuePair(frameworkDll, processes));
+ foreach (CompilerRunner runner in frameworkRunners)
+ {
+ if (exclusion != null && (!exclusion.Crossgen2Only || runner.Index == CompilerIndex.CPAOT))
+ {
+ _frameworkExclusions[exclusion.SimpleName] = exclusion.Reason;
+ continue;
+ }
+ var compilationProcess = new ProcessInfo(new CompilationProcessConstructor(runner, _options.CoreRootDirectory.FullName, new string[] { frameworkDll }));
+ compilationsToRun.Add(compilationProcess);
+ processes[(int)runner.Index] = compilationProcess;
}
- ProcessInfo compilationProcess = new ProcessInfo(new CompilationProcessConstructor(runner, _options.CoreRootDirectory.FullName, frameworkDll));
- compilationsToRun.Add(compilationProcess);
- processes[(int)runner.Index] = compilationProcess;
}
}
ParallelRunner.Run(compilationsToRun, _options.DegreeOfParallelism);
- HashSet[] skipCopying = new HashSet[(int)CompilerIndex.Count];
+ var skipCopying = new HashSet[(int)CompilerIndex.Count];
foreach (CompilerRunner runner in frameworkRunners)
{
skipCopying[(int)runner.Index] = new HashSet(StringComparer.OrdinalIgnoreCase);
}
- int[] failedCompilationsPerBuilder = new int[(int)CompilerIndex.Count];
+ var failedCompilationsPerBuilder = new int[(int)CompilerIndex.Count];
int successfulCompileCount = 0;
int failedCompileCount = 0;
foreach (KeyValuePair kvp in compilationsPerRunner)
@@ -313,7 +340,7 @@ public bool CompileFramework()
}
else if (compilationProcess.Succeeded)
{
- skipCopying[(int)runner.Index].Add(compilationProcess.Parameters.InputFileName);
+ skipCopying[(int)runner.Index].UnionWith(compilationProcess.Parameters.InputFileNames);
AnalyzeCompilationLog(compilationProcess, runner.Index);
}
else
@@ -432,9 +459,8 @@ private void AnalyzeMarker(string line, string marker, Dictionary
public bool Execute()
{
- Stopwatch stopwatch = new Stopwatch();
- stopwatch.Start();
- List executionsToRun = new List();
+ Stopwatch stopwatch = Stopwatch.StartNew();
+ var executionsToRun = new List();
foreach (BuildFolder folder in FoldersToBuild)
{
@@ -450,7 +476,7 @@ public bool Execute()
{
foreach (ProcessInfo[] execution in folder.Executions)
{
- string file = null;
+ HashSet failedFiles = new HashSet();
string failedBuilders = null;
foreach (CompilerRunner runner in _compilerRunners)
{
@@ -459,9 +485,9 @@ public bool Execute()
{
_executionFailureBuckets.AddExecution(runnerProcess);
- if (file == null)
+ failedFiles.UnionWith(runnerProcess.Parameters.InputFileNames);
+ if (failedBuilders == null)
{
- file = runnerProcess.Parameters.InputFileName;
failedBuilders = runner.CompilerName;
}
else
@@ -470,7 +496,7 @@ public bool Execute()
}
}
}
- if (file != null)
+ if (failedFiles.Count > 0)
{
success = false;
}
@@ -488,8 +514,7 @@ public bool Execute()
public bool Build()
{
- Stopwatch stopwatch = new Stopwatch();
- stopwatch.Start();
+ Stopwatch stopwatch = Stopwatch.StartNew();
bool success = _options.Exe || Compile();
@@ -572,7 +597,7 @@ private void WriteTopRankingProcesses(StreamWriter logWriter, string metric, IEn
foreach (ProcessInfo processInfo in selection)
{
- logWriter.WriteLine($"{processInfo.DurationMilliseconds,10} | {processInfo.Parameters.InputFileName}");
+ logWriter.WriteLine($"{processInfo.DurationMilliseconds,10} | {processInfo.Parameters.OutputFileName}");
}
}
@@ -616,14 +641,14 @@ private ExecutionOutcome GetExecutionOutcome(ProcessInfo execution)
private void WriteBuildStatistics(StreamWriter logWriter)
{
// The Count'th element corresponds to totals over all compiler runners used in the run
- int[,] compilationOutcomes = new int[(int)CompilationOutcome.Count, (int)CompilerIndex.Count + 1];
- int[,] executionOutcomes = new int[(int)ExecutionOutcome.Count, (int)CompilerIndex.Count + 1];
+ var compilationOutcomes = new int[(int)CompilationOutcome.Count, (int)CompilerIndex.Count + 1];
+ var executionOutcomes = new int[(int)ExecutionOutcome.Count, (int)CompilerIndex.Count + 1];
int totalCompilations = 0;
int totalExecutions = 0;
foreach (BuildFolder folder in FoldersToBuild)
{
- bool[] compilationFailedPerRunner = new bool[(int)CompilerIndex.Count];
+ var compilationFailedPerRunner = new bool[(int)CompilerIndex.Count];
if (!_options.Exe)
{
foreach (ProcessInfo[] compilation in folder.Compilations)
@@ -734,7 +759,7 @@ private void WriteBuildStatistics(StreamWriter logWriter)
if (foldersToBuild != 0)
{
int lineSize = 10 * _compilerRunners.Count() + 13 + 8;
- string separator = new string('-', lineSize);
+ var separator = new string('-', lineSize);
if (!_options.Exe)
{
@@ -833,7 +858,7 @@ private void WriteFrameworkExclusions(StreamWriter logWriter)
int keyLength = _frameworkExclusions.Keys.Max(key => key.Length);
const string SimpleNameTitle = "SIMPLE_NAME";
keyLength = Math.Max(keyLength, SimpleNameTitle.Length);
- StringBuilder title = new StringBuilder();
+ var title = new StringBuilder();
title.Append(SimpleNameTitle);
title.Append(' ', keyLength - SimpleNameTitle.Length);
title.Append(" | REASON");
@@ -841,7 +866,7 @@ private void WriteFrameworkExclusions(StreamWriter logWriter)
logWriter.WriteLine(new string('-', title.Length));
foreach (KeyValuePair exclusion in _frameworkExclusions.OrderBy(kvp => kvp.Key, StringComparer.OrdinalIgnoreCase))
{
- StringBuilder line = new StringBuilder();
+ var line = new StringBuilder();
line.Append(exclusion.Key);
line.Append(' ', keyLength - exclusion.Key.Length);
line.Append(" | ");
@@ -854,7 +879,7 @@ private void WritePerFolderStatistics(StreamWriter logWriter)
{
string baseFolder = _options.InputDirectory.FullName;
int baseOffset = baseFolder.Length + (baseFolder.Length > 0 && baseFolder[baseFolder.Length - 1] == Path.DirectorySeparatorChar ? 0 : 1);
- HashSet folders = new HashSet(StringComparer.OrdinalIgnoreCase);
+ var folders = new HashSet(StringComparer.OrdinalIgnoreCase);
foreach (BuildFolder folder in FoldersToBuild)
{
string relativeFolder = "";
@@ -875,7 +900,7 @@ private void WritePerFolderStatistics(StreamWriter logWriter)
return;
}
- List folderList = new List(folders);
+ var folderList = new List(folders);
folderList.Sort(StringComparer.OrdinalIgnoreCase);
logWriter.WriteLine();
logWriter.WriteLine("Folder statistics:");
@@ -980,8 +1005,8 @@ public ExeSizeInfo(string cpaotPath, long cpaotSize, string crossgenPath, long c
private void WriteExecutableSizeStatistics(StreamWriter logWriter)
{
- List sizeStats = new List();
- HashSet libraryHashes = new HashSet(StringComparer.OrdinalIgnoreCase);
+ var sizeStats = new List();
+ var libraryHashes = new HashSet(StringComparer.OrdinalIgnoreCase);
foreach (BuildFolder folder in FoldersToBuild)
{
@@ -1176,7 +1201,7 @@ private IEnumerable EnumerateExecutions()
public void WriteBuildLog(string buildLogPath)
{
- using (StreamWriter buildLogWriter = new StreamWriter(buildLogPath))
+ using (var buildLogWriter = new StreamWriter(buildLogPath))
{
WriteBuildStatistics(buildLogWriter);
}
@@ -1184,9 +1209,9 @@ public void WriteBuildLog(string buildLogPath)
public void WriteCombinedLog(string outputFile)
{
- using (StreamWriter combinedLog = new StreamWriter(outputFile))
+ using (var combinedLog = new StreamWriter(outputFile))
{
- StreamWriter[] perRunnerLog = new StreamWriter[(int)CompilerIndex.Count];
+ var perRunnerLog = new StreamWriter[(int)CompilerIndex.Count];
foreach (CompilerRunner runner in _compilerRunners)
{
string runnerLogPath = Path.ChangeExtension(outputFile, "-" + runner.CompilerName + ".log");
@@ -1195,7 +1220,7 @@ public void WriteCombinedLog(string outputFile)
foreach (BuildFolder folder in FoldersToBuild)
{
- bool[] compilationErrorPerRunner = new bool[(int)CompilerIndex.Count];
+ var compilationErrorPerRunner = new bool[(int)CompilerIndex.Count];
if (!_options.Exe)
{
foreach (ProcessInfo[] compilation in folder.Compilations)
@@ -1205,7 +1230,7 @@ public void WriteCombinedLog(string outputFile)
ProcessInfo compilationProcess = compilation[(int)runner.Index];
if (compilationProcess != null && !compilationProcess.IsEmpty)
{
- string log = $"\nCOMPILE {runner.CompilerName}:{compilationProcess.Parameters.InputFileName}";
+ string log = $"\nCOMPILE {runner.CompilerName}:{compilationProcess.Parameters.OutputFileName}";
StreamWriter runnerLog = perRunnerLog[(int)runner.Index];
runnerLog.WriteLine(log);
combinedLog.WriteLine(log);
@@ -1242,7 +1267,7 @@ public void WriteCombinedLog(string outputFile)
ProcessInfo executionProcess = execution[(int)runner.Index];
if (executionProcess != null)
{
- string header = $"\nEXECUTE {runner.CompilerName}:{executionProcess.Parameters.InputFileName}";
+ string header = $"\nEXECUTE {runner.CompilerName}:{executionProcess.Parameters.OutputFileName}";
combinedLog.WriteLine(header);
runnerLog.WriteLine(header);
try
@@ -1303,7 +1328,7 @@ public void WriteLogs()
if (_options.Framework)
{
string frameworkExclusionsFile = Path.Combine(_options.OutputDirectory.FullName, "framework-exclusions-" + suffix);
- using (StreamWriter writer = new StreamWriter(frameworkExclusionsFile))
+ using (var writer = new StreamWriter(frameworkExclusionsFile))
{
WriteFrameworkExclusions(writer);
}
@@ -1381,7 +1406,7 @@ private static void WriterMarkerLog(string fileName, Dictionary ma
return;
}
- using (StreamWriter logWriter = new StreamWriter(fileName))
+ using (var logWriter = new StreamWriter(fileName))
{
foreach (KeyValuePair kvp in markerResults.OrderBy((kvp) => kvp.Key))
{
@@ -1398,7 +1423,7 @@ private static void WriterMarkerDiff(string fileName, Dictionary c
return;
}
- using (StreamWriter logWriter = new StreamWriter(fileName))
+ using (var logWriter = new StreamWriter(fileName))
{
int cpaotCount = cpaot.Count();
logWriter.WriteLine("Objects queried by CPAOT: {0}", cpaotCount);
@@ -1464,7 +1489,7 @@ private static void WriterMarkerDiffSection(StreamWriter logWriter, string title
private void WriteFileListPerCompilationOutcome(string outputFileName, CompilationOutcome outcome)
{
- List filteredTestList = new List();
+ var filteredTestList = new List();
foreach (BuildFolder folder in _buildFolders)
{
foreach (ProcessInfo[] compilation in folder.Compilations)
@@ -1488,7 +1513,7 @@ private void WriteFileListPerCompilationOutcome(string outputFileName, Compilati
private void WriteFileListPerExecutionOutcome(string outputFileName, ExecutionOutcome outcome)
{
- List filteredTestList = new List();
+ var filteredTestList = new List();
foreach (BuildFolder folder in _buildFolders)
{
foreach (ProcessInfo[] execution in folder.Executions)
@@ -1500,7 +1525,7 @@ private void WriteFileListPerExecutionOutcome(string outputFileName, ExecutionOu
GetExecutionOutcome(executionPerRunner) == outcome &&
executionPerRunner.Parameters != null)
{
- filteredTestList.Add(executionPerRunner.Parameters.InputFileName);
+ filteredTestList.Add(executionPerRunner.Parameters.OutputFileName);
}
}
}
diff --git a/src/coreclr/src/tools/ReadyToRun.SuperIlc/BuildOptions.cs b/src/coreclr/src/tools/ReadyToRun.SuperIlc/BuildOptions.cs
index 684d18ac25b79d..08abd1dda42980 100644
--- a/src/coreclr/src/tools/ReadyToRun.SuperIlc/BuildOptions.cs
+++ b/src/coreclr/src/tools/ReadyToRun.SuperIlc/BuildOptions.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -29,6 +29,7 @@ public class BuildOptions
public bool UseFramework { get; set; }
public bool Release { get; set; }
public bool LargeBubble { get; set; }
+ public bool Composite { get; set; }
public int Crossgen2Parallelism { get; set; }
public int CompilationTimeoutMinutes { get; set; }
public int ExecutionTimeoutMinutes { get; set; }
diff --git a/src/coreclr/src/tools/ReadyToRun.SuperIlc/CommandLineOptions.cs b/src/coreclr/src/tools/ReadyToRun.SuperIlc/CommandLineOptions.cs
index 8ec905cf162aad..26b4cc3cc4fbc6 100644
--- a/src/coreclr/src/tools/ReadyToRun.SuperIlc/CommandLineOptions.cs
+++ b/src/coreclr/src/tools/ReadyToRun.SuperIlc/CommandLineOptions.cs
@@ -45,6 +45,7 @@ Command CompileFolder() =>
UseFramework(),
Release(),
LargeBubble(),
+ Composite(),
Crossgen2Parallelism(),
ReferencePath(),
IssuesPath(),
@@ -78,6 +79,7 @@ Command CompileSubtree() =>
UseFramework(),
Release(),
LargeBubble(),
+ Composite(),
Crossgen2Parallelism(),
ReferencePath(),
IssuesPath(),
@@ -101,6 +103,7 @@ Command CompileFramework() =>
Sequential(),
Release(),
LargeBubble(),
+ Composite(),
ReferencePath(),
IssuesPath(),
CompilationTimeoutMinutes(),
@@ -203,6 +206,9 @@ Option Release() =>
Option LargeBubble() =>
new Option(new[] { "--large-bubble" }, "Assume all input files as part of one version bubble", new Argument());
+ Option Composite() =>
+ new Option(new[] { "--composite" }, "Compile tests in composite R2R mode", new Argument());
+
Option Crossgen2Parallelism() =>
new Option(new[] { "--crossgen2-parallelism" }, "Max number of threads to use in Crossgen2 (default = logical processor count)", new Argument());
diff --git a/src/coreclr/src/tools/ReadyToRun.SuperIlc/Commands/CompileFrameworkCommand.cs b/src/coreclr/src/tools/ReadyToRun.SuperIlc/Commands/CompileFrameworkCommand.cs
index 96a6baaaa67a17..f52f54a6d6790c 100644
--- a/src/coreclr/src/tools/ReadyToRun.SuperIlc/Commands/CompileFrameworkCommand.cs
+++ b/src/coreclr/src/tools/ReadyToRun.SuperIlc/Commands/CompileFrameworkCommand.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/ReadyToRun.SuperIlc/Commands/CompileFromCrossgenRspCommand.cs b/src/coreclr/src/tools/ReadyToRun.SuperIlc/Commands/CompileFromCrossgenRspCommand.cs
index 1bf0cb8351440b..5c42e3e9aaff67 100644
--- a/src/coreclr/src/tools/ReadyToRun.SuperIlc/Commands/CompileFromCrossgenRspCommand.cs
+++ b/src/coreclr/src/tools/ReadyToRun.SuperIlc/Commands/CompileFromCrossgenRspCommand.cs
@@ -107,7 +107,7 @@ public static int CompileFromCrossgenRsp(BuildOptions options)
List fileCompilations = new List();
foreach (CompilerRunner runner in compilerRunners)
{
- var compilationProcess = new ProcessInfo(new CompilationProcessConstructor(runner, responseFileOuputPath, crossgenArguments.InputFile));
+ var compilationProcess = new ProcessInfo(new CompilationProcessConstructor(runner, responseFileOuputPath, new string[] { crossgenArguments.InputFile }));
fileCompilations.Add(compilationProcess);
}
@@ -121,7 +121,7 @@ public static int CompileFromCrossgenRsp(BuildOptions options)
success = false;
compilationFailures++;
- Console.WriteLine($"Failed compiling {compilationProcess.Parameters.InputFileName}");
+ Console.WriteLine($"Failed compiling {compilationProcess.Parameters.OutputFileName}");
}
}
}
diff --git a/src/coreclr/src/tools/ReadyToRun.SuperIlc/Commands/CompileSubtreeCommand.cs b/src/coreclr/src/tools/ReadyToRun.SuperIlc/Commands/CompileSubtreeCommand.cs
index 089bbf9460c5fb..40297da9b9522e 100644
--- a/src/coreclr/src/tools/ReadyToRun.SuperIlc/Commands/CompileSubtreeCommand.cs
+++ b/src/coreclr/src/tools/ReadyToRun.SuperIlc/Commands/CompileSubtreeCommand.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/ReadyToRun.SuperIlc/CompilerRunner.cs b/src/coreclr/src/tools/ReadyToRun.SuperIlc/CompilerRunner.cs
index 24320af9c90a6a..1ff43da0335de7 100644
--- a/src/coreclr/src/tools/ReadyToRun.SuperIlc/CompilerRunner.cs
+++ b/src/coreclr/src/tools/ReadyToRun.SuperIlc/CompilerRunner.cs
@@ -4,11 +4,9 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
-using Microsoft.Build.Logging;
namespace ReadyToRun.SuperIlc
{
@@ -48,15 +46,14 @@ public CompilerRunner(BuildOptions options, IEnumerable referenceFolders
protected virtual string CompilerPath => Path.Combine(_options.CoreRootDirectory.FullName, CompilerRelativePath, CompilerFileName);
- protected abstract IEnumerable BuildCommandLineArguments(string assemblyFileName, string outputFileName);
+ protected abstract IEnumerable BuildCommandLineArguments(IEnumerable assemblyFileNames, string outputFileName);
- public virtual ProcessParameters CompilationProcess(string outputRoot, string assemblyFileName)
+ public virtual ProcessParameters CompilationProcess(string outputFileName, IEnumerable inputAssemblyFileNames)
{
- CreateOutputFolder(outputRoot);
+ Directory.CreateDirectory(Path.GetDirectoryName(outputFileName));
- string outputFileName = GetOutputFileName(outputRoot, assemblyFileName);
- string responseFile = GetResponseFileName(outputRoot, assemblyFileName);
- var commandLineArgs = BuildCommandLineArguments(assemblyFileName, outputFileName);
+ string responseFile = outputFileName + ".rsp";
+ var commandLineArgs = BuildCommandLineArguments(inputAssemblyFileNames, outputFileName);
CreateResponseFile(responseFile, commandLineArgs);
ProcessParameters processParameters = new ProcessParameters();
@@ -71,9 +68,13 @@ public virtual ProcessParameters CompilationProcess(string outputRoot, string as
processParameters.TimeoutMilliseconds = ProcessParameters.DefaultIlcTimeout;
}
processParameters.LogPath = outputFileName + ".ilc.log";
- processParameters.InputFileName = assemblyFileName;
+ processParameters.InputFileNames = inputAssemblyFileNames;
processParameters.OutputFileName = outputFileName;
- processParameters.CompilationCostHeuristic = new FileInfo(assemblyFileName).Length;
+
+ foreach (string inputAssembly in inputAssemblyFileNames)
+ {
+ processParameters.CompilationCostHeuristic += new FileInfo(inputAssembly).Length;
+ }
return processParameters;
}
@@ -119,7 +120,7 @@ public ProcessParameters CompilationR2RDumpProcess(string compiledExecutable, bo
param.Arguments = builder.ToString();
param.TimeoutMilliseconds = R2RDumpTimeoutMilliseconds;
param.LogPath = compiledExecutable + (naked ? ".naked.r2r.log" : ".raw.r2r.log");
- param.InputFileName = compiledExecutable;
+ param.InputFileNames = new string[] { compiledExecutable };
param.OutputFileName = outputFileName;
try
{
@@ -186,7 +187,7 @@ public virtual ProcessParameters ScriptExecutionProcess(string outputRoot, strin
processParameters.Arguments = "-c " + scriptToRun;
}
- processParameters.InputFileName = scriptToRun;
+ processParameters.InputFileNames = new string[] { scriptToRun };
processParameters.OutputFileName = scriptToRun;
processParameters.LogPath = scriptToRun + ".log";
processParameters.EnvironmentOverrides["CORE_ROOT"] = _options.CoreRootOutputPath(Index, isFramework: false);
@@ -199,7 +200,7 @@ public virtual ProcessParameters AppExecutionProcess(string outputRoot, string a
ProcessParameters processParameters = ExecutionProcess(modules, folders, _options.NoEtw);
processParameters.ProcessPath = _options.CoreRunPath(Index, isFramework: false);
processParameters.Arguments = exeToRun;
- processParameters.InputFileName = exeToRun;
+ processParameters.InputFileNames = new string[] { exeToRun };
processParameters.OutputFileName = exeToRun;
processParameters.LogPath = exeToRun + ".log";
processParameters.ExpectedExitCode = 100;
@@ -248,19 +249,19 @@ public CompilerRunnerProcessConstructor(CompilerRunner runner)
public class CompilationProcessConstructor : CompilerRunnerProcessConstructor
{
- private readonly string _outputRoot;
- private readonly string _assemblyFileName;
+ private readonly string _outputFileName;
+ private readonly IEnumerable _inputAssemblyFileNames;
- public CompilationProcessConstructor(CompilerRunner runner, string outputRoot, string assemblyFileName)
+ public CompilationProcessConstructor(CompilerRunner runner, string outputFileName, IEnumerable inputAssemblyFileNames)
: base(runner)
{
- _outputRoot = outputRoot;
- _assemblyFileName = assemblyFileName;
+ _outputFileName = outputFileName;
+ _inputAssemblyFileNames = inputAssemblyFileNames;
}
public override ProcessParameters Construct()
{
- return _runner.CompilationProcess(_outputRoot, _assemblyFileName);
+ return _runner.CompilationProcess(_outputFileName, _inputAssemblyFileNames);
}
}
diff --git a/src/coreclr/src/tools/ReadyToRun.SuperIlc/CpaotRunner.cs b/src/coreclr/src/tools/ReadyToRun.SuperIlc/CpaotRunner.cs
index b65dd628a7f65b..f30e6217e3a81d 100644
--- a/src/coreclr/src/tools/ReadyToRun.SuperIlc/CpaotRunner.cs
+++ b/src/coreclr/src/tools/ReadyToRun.SuperIlc/CpaotRunner.cs
@@ -38,10 +38,13 @@ protected override ProcessParameters ExecutionProcess(IEnumerable module
return processParameters;
}
- protected override IEnumerable BuildCommandLineArguments(string assemblyFileName, string outputFileName)
+ protected override IEnumerable BuildCommandLineArguments(IEnumerable assemblyFileNames, string outputFileName)
{
// The file to compile
- yield return assemblyFileName;
+ foreach (string inputAssembly in assemblyFileNames)
+ {
+ yield return inputAssembly;
+ }
// Output
yield return $"-o:{outputFileName}";
@@ -59,19 +62,33 @@ protected override IEnumerable BuildCommandLineArguments(string assembly
yield return "-O";
}
- if (_options.LargeBubble)
+ if (_options.LargeBubble || _options.Composite)
{
yield return "--inputbubble";
}
+ if (_options.Composite)
+ {
+ yield return "--composite";
+ }
+
if (_options.Crossgen2Parallelism != 0)
{
yield return $"--parallelism={_options.Crossgen2Parallelism}";
}
- foreach (var reference in ComputeManagedAssemblies.GetManagedAssembliesInFolder(Path.GetDirectoryName(assemblyFileName)))
+ char referenceOption = (_options.Composite ? 'u' : 'r');
+ HashSet uniqueFolders = new HashSet();
+ foreach (string assemblyFileName in assemblyFileNames)
{
- yield return $"-r:{reference}";
+ uniqueFolders.Add(Path.GetDirectoryName(assemblyFileName));
+ }
+ foreach (string folder in uniqueFolders)
+ {
+ foreach (var reference in ComputeManagedAssemblies.GetManagedAssembliesInFolder(folder))
+ {
+ yield return $"-{referenceOption}:{reference}";
+ }
}
if (_resolvedReferences == null)
@@ -87,12 +104,13 @@ protected override IEnumerable BuildCommandLineArguments(string assembly
private List ResolveReferences()
{
+ char referenceOption = (_options.Composite ? 'u' : 'r');
List references = new List();
foreach (var referenceFolder in _referenceFolders)
{
foreach (var reference in ComputeManagedAssemblies.GetManagedAssembliesInFolder(referenceFolder))
{
- references.Add($"-r:{reference}");
+ references.Add($"-{referenceOption}:{reference}");
}
}
return references;
diff --git a/src/coreclr/src/tools/ReadyToRun.SuperIlc/CrossgenRunner.cs b/src/coreclr/src/tools/ReadyToRun.SuperIlc/CrossgenRunner.cs
index 610414637f307b..c483c472129b01 100644
--- a/src/coreclr/src/tools/ReadyToRun.SuperIlc/CrossgenRunner.cs
+++ b/src/coreclr/src/tools/ReadyToRun.SuperIlc/CrossgenRunner.cs
@@ -40,17 +40,22 @@ protected override ProcessParameters ExecutionProcess(IEnumerable module
return processParameters;
}
- protected override IEnumerable BuildCommandLineArguments(string assemblyFileName, string outputFileName)
+ protected override IEnumerable BuildCommandLineArguments(IEnumerable assemblyFileNames, string outputFileName)
{
+ if (assemblyFileNames.Count() > 1)
+ {
+ throw new NotImplementedException($@"Crossgen1 doesn't support composite build mode for compiling multiple input assemblies: {string.Join("; ", assemblyFileNames)}");
+ }
+
// The file to compile
yield return "/in";
- yield return assemblyFileName;
+ yield return assemblyFileNames.First();
// Output
yield return "/out";
yield return outputFileName;
- if (_options.LargeBubble && Path.GetFileNameWithoutExtension(assemblyFileName) != "System.Private.CoreLib")
+ if (_options.LargeBubble && Path.GetFileNameWithoutExtension(assemblyFileNames.First()) != "System.Private.CoreLib")
{
// There seems to be a bug in Crossgen on Linux we don't intend to fix -
// it crashes when trying to compile S.P.C in large version bubble mode.
@@ -59,7 +64,12 @@ protected override IEnumerable BuildCommandLineArguments(string assembly
yield return "/platform_assemblies_paths";
- IEnumerable paths = new string[] { Path.GetDirectoryName(assemblyFileName) }.Concat(_referenceFolders);
+ HashSet paths = new HashSet();
+ foreach (string assemblyFileName in assemblyFileNames)
+ {
+ paths.Add(Path.GetDirectoryName(assemblyFileName));
+ }
+ paths.UnionWith(_referenceFolders);
yield return paths.ConcatenatePaths();
}
diff --git a/src/coreclr/src/tools/ReadyToRun.SuperIlc/JitRunner.cs b/src/coreclr/src/tools/ReadyToRun.SuperIlc/JitRunner.cs
index b1b2fd87ca6fa5..863c506925d92c 100644
--- a/src/coreclr/src/tools/ReadyToRun.SuperIlc/JitRunner.cs
+++ b/src/coreclr/src/tools/ReadyToRun.SuperIlc/JitRunner.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -27,9 +27,14 @@ public JitRunner(BuildOptions options)
/// JIT runner has no compilation process as it doesn't transform the source IL code in any manner.
///
///
- public override ProcessParameters CompilationProcess(string outputRoot, string assemblyFileName)
+ public override ProcessParameters CompilationProcess(string outputFileName, IEnumerable inputAssemblyFileNames)
{
- File.Copy(assemblyFileName, GetOutputFileName(outputRoot, assemblyFileName), overwrite: true);
+ if (inputAssemblyFileNames.Count() != 1)
+ {
+ throw new Exception($@"JIT builder doesn't support composite mode for building input assemblies: {string.Join("; ", inputAssemblyFileNames)}");
+ }
+
+ File.Copy(inputAssemblyFileNames.First(), outputFileName, overwrite: true);
return null;
}
@@ -40,7 +45,7 @@ protected override ProcessParameters ExecutionProcess(IEnumerable module
return processParameters;
}
- protected override IEnumerable BuildCommandLineArguments(string assemblyFileName, string outputFileName)
+ protected override IEnumerable BuildCommandLineArguments(IEnumerable assemblyFileNames, string outputFileName)
{
// This should never get called as the overridden CompilationProcess returns null
throw new NotImplementedException();
diff --git a/src/coreclr/src/tools/ReadyToRun.SuperIlc/Linux.cs b/src/coreclr/src/tools/ReadyToRun.SuperIlc/Linux.cs
index 595e85d5f6f772..4eee0c21656cbb 100644
--- a/src/coreclr/src/tools/ReadyToRun.SuperIlc/Linux.cs
+++ b/src/coreclr/src/tools/ReadyToRun.SuperIlc/Linux.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/ReadyToRun.SuperIlc/ParallelRunner.cs b/src/coreclr/src/tools/ReadyToRun.SuperIlc/ParallelRunner.cs
index cd23ade43c2f31..95b70bd174069c 100644
--- a/src/coreclr/src/tools/ReadyToRun.SuperIlc/ParallelRunner.cs
+++ b/src/coreclr/src/tools/ReadyToRun.SuperIlc/ParallelRunner.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/ReadyToRun.SuperIlc/PerfEventSourceListener.cs b/src/coreclr/src/tools/ReadyToRun.SuperIlc/PerfEventSourceListener.cs
index b952714c662d1b..e6113599731863 100644
--- a/src/coreclr/src/tools/ReadyToRun.SuperIlc/PerfEventSourceListener.cs
+++ b/src/coreclr/src/tools/ReadyToRun.SuperIlc/PerfEventSourceListener.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/ReadyToRun.SuperIlc/ProcessRunner.cs b/src/coreclr/src/tools/ReadyToRun.SuperIlc/ProcessRunner.cs
index bfe504b104dfd8..efa1533ae55e2c 100644
--- a/src/coreclr/src/tools/ReadyToRun.SuperIlc/ProcessRunner.cs
+++ b/src/coreclr/src/tools/ReadyToRun.SuperIlc/ProcessRunner.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -32,7 +32,7 @@ public class ProcessParameters
public string LogPath;
public int TimeoutMilliseconds;
public int ExpectedExitCode;
- public string InputFileName;
+ public IEnumerable InputFileNames;
public string OutputFileName;
public long CompilationCostHeuristic;
public bool CollectJittedMethods;
diff --git a/src/coreclr/src/tools/ReadyToRun.SuperIlc/Program.cs b/src/coreclr/src/tools/ReadyToRun.SuperIlc/Program.cs
index 1bdbaa2cdf8441..6549fe49dd6d3d 100644
--- a/src/coreclr/src/tools/ReadyToRun.SuperIlc/Program.cs
+++ b/src/coreclr/src/tools/ReadyToRun.SuperIlc/Program.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/ReadyToRun.SuperIlc/ReadyToRun.SuperIlc.csproj b/src/coreclr/src/tools/ReadyToRun.SuperIlc/ReadyToRun.SuperIlc.csproj
index 3cf0cbfe0848ee..f50925530593b1 100644
--- a/src/coreclr/src/tools/ReadyToRun.SuperIlc/ReadyToRun.SuperIlc.csproj
+++ b/src/coreclr/src/tools/ReadyToRun.SuperIlc/ReadyToRun.SuperIlc.csproj
@@ -1,9 +1,10 @@
-
+
ReadyToRun.SuperIlc
true
Exe
$(NetCoreAppCurrent)
+ netcoreapp3.0
8002,NU1701
AnyCPU
$(BinDir)\ReadyToRun.SuperIlc
diff --git a/src/coreclr/src/tools/ReadyToRun.SuperIlc/TestExclusion.cs b/src/coreclr/src/tools/ReadyToRun.SuperIlc/TestExclusion.cs
index 3afcdc5ce66461..81c34704f44986 100644
--- a/src/coreclr/src/tools/ReadyToRun.SuperIlc/TestExclusion.cs
+++ b/src/coreclr/src/tools/ReadyToRun.SuperIlc/TestExclusion.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen/CMakeLists.txt b/src/coreclr/src/tools/crossgen/CMakeLists.txt
index 5e1a662f621d22..b4207f0d661a39 100644
--- a/src/coreclr/src/tools/crossgen/CMakeLists.txt
+++ b/src/coreclr/src/tools/crossgen/CMakeLists.txt
@@ -30,19 +30,28 @@ if(FEATURE_MERGE_JIT_AND_ENGINE)
set(CLRJIT_CROSSGEN clrjit_crossgen)
endif(FEATURE_MERGE_JIT_AND_ENGINE)
+if(CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD)
+ # The following linked options can be inserted into the linker libraries list to
+ # ensure proper resolving of circular references between a subset of the libraries.
+ set(START_LIBRARY_GROUP -Wl,--start-group)
+ set(END_LIBRARY_GROUP -Wl,--end-group)
+endif(CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD)
+
target_link_libraries(crossgen
+ ${START_LIBRARY_GROUP} # Start group of libraries that have circular references
cee_crossgen
+ v3binder_crossgen
mdcompiler_crossgen
mdruntime_crossgen
mdruntimerw_crossgen
mdhotdata_crossgen
+ ${END_LIBRARY_GROUP} # End group of libraries that have circular references
corguids
${CLRJIT_CROSSGEN}
gcinfo_crossgen
corzap_crossgen
mscorlib_crossgen
utilcode_crossgen
- v3binder_crossgen
)
if(CLR_CMAKE_HOST_UNIX)
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.DependencyAnalysisFramework/IDependencyNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.DependencyAnalysisFramework/IDependencyNode.cs
index d67fbd504ecc84..71f07f3fb8e0b9 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.DependencyAnalysisFramework/IDependencyNode.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.DependencyAnalysisFramework/IDependencyNode.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.DependencyAnalysisFramework/ILCompiler.DependencyAnalysisFramework.csproj b/src/coreclr/src/tools/crossgen2/ILCompiler.DependencyAnalysisFramework/ILCompiler.DependencyAnalysisFramework.csproj
index 81f4d5d5fb6331..643455201ebbb7 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.DependencyAnalysisFramework/ILCompiler.DependencyAnalysisFramework.csproj
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.DependencyAnalysisFramework/ILCompiler.DependencyAnalysisFramework.csproj
@@ -1,4 +1,4 @@
-
+
Library
ILCompiler.DependencyAnalysisFramework
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.DependencyAnalysisFramework/PerfEventSource.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.DependencyAnalysisFramework/PerfEventSource.cs
index 604855dd0ac237..bfd79e1ecbc537 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.DependencyAnalysisFramework/PerfEventSource.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.DependencyAnalysisFramework/PerfEventSource.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs
index a344bb261ccf6d..2da9f2400985cf 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -6,6 +6,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
+using System.Linq;
using System.Reflection.PortableExecutable;
using ILCompiler.DependencyAnalysis.ReadyToRun;
@@ -14,6 +15,7 @@
using ObjectData = ILCompiler.DependencyAnalysis.ObjectNode.ObjectData;
using Internal.TypeSystem;
+using Internal.TypeSystem.Ecma;
using System.Security.Cryptography;
namespace ILCompiler.DependencyAnalysis
@@ -23,11 +25,33 @@ namespace ILCompiler.DependencyAnalysis
///
internal class ReadyToRunObjectWriter
{
- // Nodefactory for which ObjectWriter is instantiated for.
+ ///
+ /// Nodefactory for which ObjectWriter is instantiated for.
+ ///
private readonly NodeFactory _nodeFactory;
+
+ ///
+ /// Output executable path.
+ ///
private readonly string _objectFilePath;
+
+ ///
+ /// Set to non-null when rewriting MSIL assemblies during composite R2R build;
+ /// we basically publish the input assemblies into the composite build output folder
+ /// using the same ReadyToRunObjectWriter as we're using for emitting the "actual"
+ /// R2R executable, just in this special mode in which we emit a minimal R2R header
+ /// with forwarding information pointing at the composite module with native code.
+ ///
+ private readonly EcmaModule _componentModule;
+
+ ///
+ /// Nodes to emit into the output executable as collected by the dependency analysis.
+ ///
private readonly IEnumerable _nodes;
- private readonly PEReader _inputPeReader;
+
+ ///
+ /// True when the executable generator should output a map file.
+ ///
private readonly bool _generateMapFile;
#if DEBUG
@@ -48,12 +72,12 @@ public NodeInfo(ISymbolNode node, int nodeIndex, int symbolIndex)
Dictionary _previouslyWrittenNodeNames = new Dictionary();
#endif
- public ReadyToRunObjectWriter(PEReader inputPeReader, string objectFilePath, IEnumerable nodes, NodeFactory factory, bool generateMapFile)
+ public ReadyToRunObjectWriter(string objectFilePath, EcmaModule componentModule, IEnumerable nodes, NodeFactory factory, bool generateMapFile)
{
_objectFilePath = objectFilePath;
+ _componentModule = componentModule;
_nodes = nodes;
_nodeFactory = factory;
- _inputPeReader = inputPeReader;
_generateMapFile = generateMapFile;
}
@@ -79,10 +103,40 @@ public void EmitPortableExecutable()
if (mapFile != null)
mapFile.WriteLine($@"R2R object emission started: {DateTime.Now}");
+ PEHeaderBuilder headerBuilder;
+ int timeDateStamp;
+ ISymbolNode r2rHeaderExportSymbol;
+
+ if (_nodeFactory.CompilationModuleGroup.IsCompositeBuildMode && _componentModule == null)
+ {
+ headerBuilder = PEHeaderProvider.Create(
+ imageCharacteristics: Characteristics.ExecutableImage | Characteristics.Dll,
+ dllCharacteristics: default(DllCharacteristics),
+ Subsystem.Unknown,
+ _nodeFactory.Target);
+ // TODO: generate a non-zero timestamp: https://github.com/dotnet/runtime/issues/32507
+ timeDateStamp = 0;
+ r2rHeaderExportSymbol = _nodeFactory.Header;
+ }
+ else
+ {
+ PEReader inputPeReader = (_componentModule != null ? _componentModule.PEReader : _nodeFactory.CompilationModuleGroup.CompilationModuleSet.First().PEReader);
+ headerBuilder = PEHeaderProvider.Copy(inputPeReader.PEHeaders, _nodeFactory.Target);
+ timeDateStamp = inputPeReader.PEHeaders.CoffHeader.TimeDateStamp;
+ r2rHeaderExportSymbol = null;
+ }
+
+ Func getRuntimeFunctionsTable = null;
+ if (_componentModule == null)
+ {
+ getRuntimeFunctionsTable = GetRuntimeFunctionsTable;
+ }
R2RPEBuilder r2rPeBuilder = new R2RPEBuilder(
_nodeFactory.Target,
- _inputPeReader,
- GetRuntimeFunctionsTable);
+ headerBuilder,
+ r2rHeaderExportSymbol,
+ Path.GetFileName(_objectFilePath),
+ getRuntimeFunctionsTable);
NativeDebugDirectoryEntryNode nativeDebugDirectoryEntryNode = null;
@@ -131,8 +185,11 @@ public void EmitPortableExecutable()
EmitObjectData(r2rPeBuilder, nodeContents, nodeIndex, name, node.Section, mapFile);
}
- r2rPeBuilder.SetCorHeader(_nodeFactory.CopiedCorHeaderNode, _nodeFactory.CopiedCorHeaderNode.Size);
- r2rPeBuilder.SetDebugDirectory(_nodeFactory.DebugDirectoryNode, _nodeFactory.DebugDirectoryNode.Size);
+ if (!_nodeFactory.CompilationModuleGroup.IsCompositeBuildMode || _componentModule != null)
+ {
+ r2rPeBuilder.SetCorHeader(_nodeFactory.CopiedCorHeaderNode, _nodeFactory.CopiedCorHeaderNode.Size);
+ r2rPeBuilder.SetDebugDirectory(_nodeFactory.DebugDirectoryNode, _nodeFactory.DebugDirectoryNode.Size);
+ }
if (_nodeFactory.Win32ResourcesNode != null)
{
@@ -142,7 +199,7 @@ public void EmitPortableExecutable()
using (var peStream = File.Create(_objectFilePath))
{
- r2rPeBuilder.Write(peStream);
+ r2rPeBuilder.Write(peStream, timeDateStamp);
// Compute MD5 hash of the output image and store that in the native DebugDirectory entry
using (var md5Hash = MD5.Create())
@@ -229,10 +286,10 @@ private void EmitObjectData(R2RPEBuilder r2rPeBuilder, ObjectData data, int node
r2rPeBuilder.AddObjectData(data, section, name, mapFile);
}
- public static void EmitObject(PEReader inputPeReader, string objectFilePath, IEnumerable nodes, NodeFactory factory, bool generateMapFile)
+ public static void EmitObject(string objectFilePath, EcmaModule componentModule, IEnumerable nodes, NodeFactory factory, bool generateMapFile)
{
Console.WriteLine($@"Emitting R2R PE file: {objectFilePath}");
- ReadyToRunObjectWriter objectWriter = new ReadyToRunObjectWriter(inputPeReader, objectFilePath, nodes, factory, generateMapFile);
+ ReadyToRunObjectWriter objectWriter = new ReadyToRunObjectWriter(objectFilePath, componentModule, nodes, factory, generateMapFile);
objectWriter.EmitPortableExecutable();
}
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/CompilationModuleGroup.ReadyToRun.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/CompilationModuleGroup.ReadyToRun.cs
index ec9e47e49a83e5..83fc679d826e5b 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/CompilationModuleGroup.ReadyToRun.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/CompilationModuleGroup.ReadyToRun.cs
@@ -1,10 +1,13 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Internal.TypeSystem;
using ILCompiler.DependencyAnalysis.ReadyToRun;
using Internal.ReadyToRunConstants;
+using Internal.TypeSystem.Ecma;
+using System.Collections.Generic;
+using System.Linq;
namespace ILCompiler
{
@@ -58,5 +61,25 @@ partial class CompilationModuleGroup
/// Gets the flags to be stored in the generated ReadyToRun module header.
///
public abstract ReadyToRunFlags GetReadyToRunFlags();
+
+ ///
+ /// When set to true, unconditionally add module overrides to all signatures. This is needed in composite
+ /// build mode so that import cells and instance entry point table are caller module-agnostic.
+ ///
+ public bool EnforceOwningType(EcmaModule module)
+ {
+ return IsCompositeBuildMode || module != CompilationModuleSet.Single();
+ }
+
+ ///
+ /// Returns true when the compiler is running in composite build mode i.e. building an arbitrary number of
+ /// input MSIL assemblies into a single output R2R binary.
+ ///
+ public abstract bool IsCompositeBuildMode { get; }
+
+ ///
+ /// List of input modules to use for the compilation.
+ ///
+ public abstract IEnumerable CompilationModuleSet { get; }
}
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ArrayOfEmbeddedPointersNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ArrayOfEmbeddedPointersNode.cs
index ed4ce4a7281a62..b70ed3378277c7 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ArrayOfEmbeddedPointersNode.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ArrayOfEmbeddedPointersNode.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/EmbeddedPointerIndirectionNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/EmbeddedPointerIndirectionNode.cs
index 5488801a39f537..0b12be37e7bf04 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/EmbeddedPointerIndirectionNode.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/EmbeddedPointerIndirectionNode.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ArgIterator.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ArgIterator.cs
index dae97d5d591781..abc90394c1ab07 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ArgIterator.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ArgIterator.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/AssemblyTableNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/AssemblyTableNode.cs
new file mode 100644
index 00000000000000..9a0bdb248e114b
--- /dev/null
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/AssemblyTableNode.cs
@@ -0,0 +1,59 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Reflection.Metadata.Ecma335;
+
+using Internal.JitInterface;
+using Internal.NativeFormat;
+using Internal.Runtime;
+using Internal.Text;
+using Internal.TypeSystem;
+using Internal.TypeSystem.Ecma;
+
+namespace ILCompiler.DependencyAnalysis.ReadyToRun
+{
+ public class AssemblyTableNode : HeaderTableNode
+ {
+ private readonly List _assemblyHeaders;
+
+ public AssemblyTableNode(TargetDetails target)
+ : base(target)
+ {
+ _assemblyHeaders = new List();
+ }
+
+ public void Add(AssemblyHeaderNode componentAssemblyHeader)
+ {
+ _assemblyHeaders.Add(componentAssemblyHeader);
+ }
+
+ public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
+ {
+ sb.Append(nameMangler.CompilationUnitPrefix);
+ sb.Append("__ReadyToRunAssemblyTable");
+ }
+
+ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
+ {
+ ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly);
+ builder.AddSymbol(this);
+ foreach (AssemblyHeaderNode assemblyHeader in _assemblyHeaders)
+ {
+ // TODO: IMAGE_DATA_DIRECTORY CorHeader - no support for embedded MSIL yet
+ builder.EmitInt(0);
+ builder.EmitInt(0);
+ // IMAGE_DATA_DIRECTORY ReadyToRunHeader
+ builder.EmitReloc(assemblyHeader, RelocType.IMAGE_REL_BASED_ADDR32NB);
+ builder.EmitReloc(assemblyHeader, RelocType.IMAGE_REL_SYMBOL_SIZE);
+ }
+ return builder.ToObjectData();
+ }
+
+ public override int ClassCode => 513314416;
+ }
+}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/AttributePresenceFilterNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/AttributePresenceFilterNode.cs
index b7dc1a09ab167b..eef7490513a059 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/AttributePresenceFilterNode.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/AttributePresenceFilterNode.cs
@@ -29,7 +29,8 @@ public AttributePresenceFilterNode(EcmaModule module)
public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append(nameMangler.CompilationUnitPrefix);
- sb.Append("__ReadyToRunAttributePresenceFilter");
+ sb.Append("__ReadyToRunAttributePresenceFilter__");
+ sb.Append(_module.Assembly.GetName().Name);
}
private struct CustomAttributeEntry
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CompilerIdentifierNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CompilerIdentifierNode.cs
index 834eb3d68eaa47..f97c5f29870738 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CompilerIdentifierNode.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CompilerIdentifierNode.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedCorHeaderNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedCorHeaderNode.cs
index 9f1d4df20d5e5f..5e7a96afa4c716 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedCorHeaderNode.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedCorHeaderNode.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedFieldRvaNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedFieldRvaNode.cs
index 25448fc1c8463b..ca3ca21435d0e3 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedFieldRvaNode.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedFieldRvaNode.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedManagedResourcesNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedManagedResourcesNode.cs
index bbb19eb5c19f23..840cb8e5927c25 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedManagedResourcesNode.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedManagedResourcesNode.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedMetadataBlobNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedMetadataBlobNode.cs
index 6f4f4207fd7aa6..4160a9e5e3f3cb 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedMetadataBlobNode.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedMetadataBlobNode.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedMethodILNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedMethodILNode.cs
index 2e1056bbbdc39d..a13d18f125ae41 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedMethodILNode.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedMethodILNode.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedStrongNameSignatureNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedStrongNameSignatureNode.cs
index 8452b859267039..ee6067260adaa0 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedStrongNameSignatureNode.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedStrongNameSignatureNode.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugDirectoryEntryNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugDirectoryEntryNode.cs
index 2dc71bde928c19..e88b2805d73694 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugDirectoryEntryNode.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugDirectoryEntryNode.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugDirectoryNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugDirectoryNode.cs
index 017428edceabe0..52e49afe79828f 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugDirectoryNode.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugDirectoryNode.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugInfoTableNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugInfoTableNode.cs
index 88318348932074..68f04436441446 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugInfoTableNode.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugInfoTableNode.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadHelperImport.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadHelperImport.cs
index 75a7bf527e8a27..df834649fdc5fd 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadHelperImport.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadHelperImport.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadHelperMethodImport.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadHelperMethodImport.cs
index 82af06eee32500..dbf106844ed7d3 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadHelperMethodImport.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadHelperMethodImport.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -22,8 +22,6 @@ public class DelayLoadHelperMethodImport : DelayLoadHelperImport, IMethodNode
private readonly bool _useInstantiatingStub;
- private readonly SignatureContext _signatureContext;
-
public DelayLoadHelperMethodImport(
NodeFactory factory,
ImportSectionNode importSectionNode,
@@ -32,13 +30,11 @@ public DelayLoadHelperMethodImport(
bool useVirtualCall,
bool useInstantiatingStub,
Signature instanceSignature,
- SignatureContext signatureContext,
string callSite = null)
: base(factory, importSectionNode, helper, instanceSignature, useVirtualCall, callSite)
{
_method = method;
_useInstantiatingStub = useInstantiatingStub;
- _signatureContext = signatureContext;
}
public override IEnumerable GetStaticDependencies(NodeFactory factory)
@@ -55,8 +51,7 @@ public override IEnumerable GetStaticDependencies(NodeFacto
new MethodWithToken(canonMethod, _method.Token, constrainedType: null),
isUnboxingStub: false,
isInstantiatingStub: false,
- isPrecodeImportRequired: false,
- signatureContext: _signatureContext);
+ isPrecodeImportRequired: false);
yield return new DependencyListEntry(canonMethodNode, "Canonical method for instantiating stub");
}
}
@@ -72,10 +67,6 @@ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer
if (result != 0)
return result;
- result = _signatureContext.CompareTo(otherNode._signatureContext, comparer);
- if (result != 0)
- return result;
-
result = _method.CompareTo(otherNode._method, comparer);
if (result != 0)
return result;
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelegateCtorSignature.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelegateCtorSignature.cs
index f81d55920f5768..4a3566fbdcab88 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelegateCtorSignature.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelegateCtorSignature.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -17,22 +17,19 @@ public class DelegateCtorSignature : Signature
private readonly ModuleToken _methodToken;
- private readonly SignatureContext _signatureContext;
-
public DelegateCtorSignature(
TypeDesc delegateType,
IMethodNode targetMethod,
- ModuleToken methodToken,
- SignatureContext signatureContext)
+ ModuleToken methodToken)
{
_delegateType = delegateType;
_targetMethod = targetMethod;
_methodToken = methodToken;
- _signatureContext = signatureContext;
// Ensure types in signature are loadable and resolvable, otherwise we'll fail later while emitting the signature
- signatureContext.Resolver.CompilerContext.EnsureLoadableType(delegateType);
- signatureContext.Resolver.CompilerContext.EnsureLoadableMethod(targetMethod.Method);
+ CompilerTypeSystemContext compilerContext = (CompilerTypeSystemContext)delegateType.Context;
+ compilerContext.EnsureLoadableType(delegateType);
+ compilerContext.EnsureLoadableMethod(targetMethod.Method);
}
public override int ClassCode => 99885741;
@@ -44,7 +41,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
if (!relocsOnly)
{
- SignatureContext innerContext = builder.EmitFixup(factory, ReadyToRunFixupKind.DelegateCtor, _methodToken.Module, _signatureContext);
+ SignatureContext innerContext = builder.EmitFixup(factory, ReadyToRunFixupKind.DelegateCtor, _methodToken.Module, factory.SignatureContext);
builder.EmitMethodSignature(
new MethodWithToken(_targetMethod.Method, _methodToken, constrainedType: null),
@@ -93,11 +90,7 @@ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer
if (result != 0)
return result;
- result = _methodToken.CompareTo(otherNode._methodToken);
- if (result != 0)
- return result;
-
- return _signatureContext.CompareTo(otherNode._signatureContext, comparer);
+ return _methodToken.CompareTo(otherNode._methodToken);
}
}
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DevirtualizationManager.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DevirtualizationManager.cs
index 793406c46bcb07..ed34d69a27ed52 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DevirtualizationManager.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DevirtualizationManager.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ExceptionInfoLookupTableNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ExceptionInfoLookupTableNode.cs
index 702b668cd14cb6..ecef116e6a0817 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ExceptionInfoLookupTableNode.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ExceptionInfoLookupTableNode.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ExternalMethodImport.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ExternalMethodImport.cs
index a1e6ff1132af8e..1e57fe0312dd0d 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ExternalMethodImport.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ExternalMethodImport.cs
@@ -1,4 +1,4 @@
-
+
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -18,8 +18,7 @@ public ExternalMethodImport(
ReadyToRunFixupKind fixupKind,
MethodWithToken method,
bool isUnboxingStub,
- bool isInstantiatingStub,
- SignatureContext signatureContext)
+ bool isInstantiatingStub)
: base(
factory,
factory.MethodImports,
@@ -28,8 +27,7 @@ public ExternalMethodImport(
fixupKind,
method,
isUnboxingStub,
- isInstantiatingStub,
- signatureContext))
+ isInstantiatingStub))
{
_method = method;
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/FieldFixupSignature.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/FieldFixupSignature.cs
index 0d09d4c54e735e..32cae03ba4016c 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/FieldFixupSignature.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/FieldFixupSignature.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -18,16 +18,13 @@ public class FieldFixupSignature : Signature
private readonly FieldDesc _fieldDesc;
- private readonly SignatureContext _signatureContext;
-
- public FieldFixupSignature(ReadyToRunFixupKind fixupKind, FieldDesc fieldDesc, SignatureContext signatureContext)
+ public FieldFixupSignature(ReadyToRunFixupKind fixupKind, FieldDesc fieldDesc)
{
_fixupKind = fixupKind;
_fieldDesc = fieldDesc;
- _signatureContext = signatureContext;
// Ensure types in signature are loadable and resolvable, otherwise we'll fail later while emitting the signature
- signatureContext.Resolver.CompilerContext.EnsureLoadableType(fieldDesc.OwningType);
+ ((CompilerTypeSystemContext)fieldDesc.Context).EnsureLoadableType(fieldDesc.OwningType);
}
public override int ClassCode => 271828182;
@@ -40,8 +37,8 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
dataBuilder.AddSymbol(this);
- EcmaModule targetModule = _signatureContext.GetTargetModule(_fieldDesc);
- SignatureContext innerContext = dataBuilder.EmitFixup(factory, _fixupKind, targetModule, _signatureContext);
+ EcmaModule targetModule = factory.SignatureContext.GetTargetModule(_fieldDesc);
+ SignatureContext innerContext = dataBuilder.EmitFixup(factory, _fixupKind, targetModule, factory.SignatureContext);
dataBuilder.EmitFieldSignature(_fieldDesc, innerContext);
}
@@ -62,11 +59,7 @@ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer
if (result != 0)
return result;
- result = comparer.Compare(_fieldDesc, otherNode._fieldDesc);
- if (result != 0)
- return result;
-
- return _signatureContext.CompareTo(otherNode._signatureContext, comparer);
+ return comparer.Compare(_fieldDesc, otherNode._fieldDesc);
}
}
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/GCRefMapBuilder.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/GCRefMapBuilder.cs
index fb434dea4b417b..5f2767c51a63b5 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/GCRefMapBuilder.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/GCRefMapBuilder.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/GCRefMapNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/GCRefMapNode.cs
index 5a4147fb56c716..1a7c9ccbb3d8ee 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/GCRefMapNode.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/GCRefMapNode.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/GenericLookupSignature.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/GenericLookupSignature.cs
index 04c12f8845b68f..a0aa10fe80c5ce 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/GenericLookupSignature.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/GenericLookupSignature.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -27,16 +27,13 @@ public class GenericLookupSignature : Signature
private readonly GenericContext _methodContext;
- private readonly SignatureContext _signatureContext;
-
public GenericLookupSignature(
CORINFO_RUNTIME_LOOKUP_KIND runtimeLookupKind,
ReadyToRunFixupKind fixupKind,
TypeDesc typeArgument,
MethodWithToken methodArgument,
FieldDesc fieldArgument,
- GenericContext methodContext,
- SignatureContext signatureContext)
+ GenericContext methodContext)
{
Debug.Assert(typeArgument != null || methodArgument != null || fieldArgument != null);
_runtimeLookupKind = runtimeLookupKind;
@@ -45,7 +42,6 @@ public GenericLookupSignature(
_methodArgument = methodArgument;
_fieldArgument = fieldArgument;
_methodContext = methodContext;
- _signatureContext = signatureContext;
}
public override int ClassCode => 258608008;
@@ -65,11 +61,11 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
}
else if (_typeArgument != null)
{
- targetModule = _signatureContext.GetTargetModule(_typeArgument);
+ targetModule = factory.SignatureContext.GetTargetModule(_typeArgument);
}
else if (_fieldArgument != null)
{
- targetModule = _signatureContext.GetTargetModule(_fieldArgument);
+ targetModule = factory.SignatureContext.GetTargetModule(_fieldArgument);
}
else
{
@@ -101,7 +97,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
ObjectDataSignatureBuilder dataBuilder = new ObjectDataSignatureBuilder();
dataBuilder.AddSymbol(this);
- SignatureContext innerContext = dataBuilder.EmitFixup(factory, fixupToEmit, targetModule, _signatureContext);
+ SignatureContext innerContext = dataBuilder.EmitFixup(factory, fixupToEmit, targetModule, factory.SignatureContext);
if (contextTypeToEmit != null)
{
dataBuilder.EmitTypeSignature(contextTypeToEmit, innerContext);
@@ -214,11 +210,7 @@ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer
return result;
}
- result = comparer.Compare(_methodContext.ContextMethod, otherNode._methodContext.ContextMethod);
- if (result != 0)
- return result;
-
- return _signatureContext.CompareTo(otherNode._signatureContext, comparer);
+ return comparer.Compare(_methodContext.ContextMethod, otherNode._methodContext.ContextMethod);
}
}
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/HeaderNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/HeaderNode.cs
index 54ba55dd927c4c..f157900c9665f9 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/HeaderNode.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/HeaderNode.cs
@@ -42,7 +42,7 @@ public override ObjectNodeSection Section
}
}
- public class HeaderNode : ObjectNode, ISymbolDefinitionNode
+ public abstract class HeaderNode : ObjectNode, ISymbolDefinitionNode
{
struct HeaderItem
{
@@ -73,16 +73,15 @@ public void Add(ReadyToRunSectionType id, ObjectNode node, ISymbolNode startSymb
_items.Add(new HeaderItem(id, node, startSymbol));
}
- public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
- {
- sb.Append(nameMangler.CompilationUnitPrefix);
- sb.Append("__ReadyToRunHeader");
- }
public int Offset => 0;
public override bool IsShareable => false;
protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);
+ protected abstract void AppendMangledHeaderName(NameMangler nameMangler, Utf8StringBuilder sb);
+
+ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) => AppendMangledHeaderName(nameMangler, sb);
+
public override bool StaticDependenciesAreComputed => true;
public override ObjectNodeSection Section
@@ -102,23 +101,18 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
builder.RequireInitialPointerAlignment();
builder.AddSymbol(this);
+ EmitHeaderPrefix(ref builder);
+
// Don't bother sorting if we're not emitting the contents
if (!relocsOnly)
_items.Sort((x, y) => Comparer.Default.Compare((int)x.Id, (int)y.Id));
- // ReadyToRunHeader.Magic
- builder.EmitInt((int)(ReadyToRunHeaderConstants.Signature));
-
- // ReadyToRunHeader.MajorVersion
- builder.EmitShort((short)(ReadyToRunHeaderConstants.CurrentMajorVersion));
- builder.EmitShort((short)(ReadyToRunHeaderConstants.CurrentMinorVersion));
-
// ReadyToRunHeader.Flags
builder.EmitInt((int)_flags);
// ReadyToRunHeader.NumberOfSections
ObjectDataBuilder.Reservation sectionCountReservation = builder.ReserveInt();
-
+
int count = 0;
foreach (var item in _items)
{
@@ -127,20 +121,75 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
continue;
builder.EmitInt((int)item.Id);
-
+
builder.EmitReloc(item.StartSymbol, RelocType.IMAGE_REL_BASED_ADDR32NB);
builder.EmitReloc(item.StartSymbol, RelocType.IMAGE_REL_SYMBOL_SIZE);
-
+
count++;
}
builder.EmitInt(sectionCountReservation, count);
-
+
return builder.ToObjectData();
}
+ protected abstract void EmitHeaderPrefix(ref ObjectDataBuilder builder);
+
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
+ }
+
+ public class GlobalHeaderNode : HeaderNode
+ {
+ public GlobalHeaderNode(TargetDetails target, ReadyToRunFlags flags)
+ : base(target, flags)
+ {
+ }
+
+ protected override void AppendMangledHeaderName(NameMangler nameMangler, Utf8StringBuilder sb)
+ {
+ sb.Append(nameMangler.CompilationUnitPrefix);
+ sb.Append("__ReadyToRunHeader");
+ }
+
+ protected override void EmitHeaderPrefix(ref ObjectDataBuilder builder)
+ {
+ // ReadyToRunHeader.Magic
+ builder.EmitInt((int)(ReadyToRunHeaderConstants.Signature));
+
+ // ReadyToRunHeader.MajorVersion
+ builder.EmitShort((short)(ReadyToRunHeaderConstants.CurrentMajorVersion));
+ builder.EmitShort((short)(ReadyToRunHeaderConstants.CurrentMinorVersion));
+ }
public override int ClassCode => (int)ObjectNodeOrder.ReadyToRunHeaderNode;
}
+
+ public class AssemblyHeaderNode : HeaderNode
+ {
+ private readonly int _index;
+
+ public AssemblyHeaderNode(TargetDetails target, ReadyToRunFlags flags, int index)
+ : base(target, flags)
+ {
+ _index = index;
+ }
+
+ protected override void EmitHeaderPrefix(ref ObjectDataBuilder builder)
+ {
+ }
+
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
+ {
+ return _index - ((AssemblyHeaderNode)other)._index;
+ }
+
+ protected override void AppendMangledHeaderName(NameMangler nameMangler, Utf8StringBuilder sb)
+ {
+ sb.Append(nameMangler.CompilationUnitPrefix);
+ sb.Append("__ReadyToRunAssemblyHeader__");
+ sb.Append(_index.ToString());
+ }
+
+ public override int ClassCode => (int)ObjectNodeOrder.ReadyToRunAssemblyHeaderNode;
+ }
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/IReadyToRunMethodCodeNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/IReadyToRunMethodCodeNode.cs
index 277d416c6ef77c..2241f09659447b 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/IReadyToRunMethodCodeNode.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/IReadyToRunMethodCodeNode.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Import.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Import.cs
index 666cd93ef77088..e276c75fa77185 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Import.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Import.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ImportSectionNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ImportSectionNode.cs
index 22e6231a00ed2a..8f929b2b30e1a4 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ImportSectionNode.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ImportSectionNode.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ImportThunk.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ImportThunk.cs
index 33779ba227c7a8..d54472dc122e9a 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ImportThunk.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ImportThunk.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/InliningInfoNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/InliningInfoNode.cs
index ce57611186494c..89eb57a871e069 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/InliningInfoNode.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/InliningInfoNode.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -20,18 +20,19 @@ namespace ILCompiler.DependencyAnalysis.ReadyToRun
///
public class InliningInfoNode : HeaderTableNode
{
- private readonly EcmaModule _globalContext;
+ private readonly EcmaModule _module;
- public InliningInfoNode(TargetDetails target, EcmaModule globalContext)
+ public InliningInfoNode(TargetDetails target, EcmaModule module)
: base(target)
{
- _globalContext = globalContext;
+ _module = module;
}
public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append(nameMangler.CompilationUnitPrefix);
- sb.Append("__ReadyToRunInliningInfoTable");
+ sb.Append("__ReadyToRunInliningInfoTable__");
+ sb.Append(_module.Assembly.GetName().Name);
}
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
@@ -48,7 +49,12 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
MethodDesc[] inlinees = methodNode.InlinedMethods;
MethodDesc inliner = methodNode.Method;
- MethodDesc inlinerDefinition = inliner.GetTypicalMethodDefinition();
+ EcmaMethod inlinerDefinition = (EcmaMethod)inliner.GetTypicalMethodDefinition();
+ if (inlinerDefinition.Module != _module)
+ {
+ // Only encode inlining info for inliners within the active module
+ continue;
+ }
foreach (MethodDesc inlinee in inlinees)
{
@@ -91,7 +97,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
var sig = new VertexSequence();
- bool isForeignInlinee = inlinee.Module != _globalContext;
+ bool isForeignInlinee = inlinee.Module != _module;
sig.Append(new UnsignedConstant((uint)(inlineeRid << 1 | (isForeignInlinee ? 1 : 0))));
if (isForeignInlinee)
{
@@ -123,7 +129,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
int ridDelta = inlinerRid - baseRid;
baseRid = inlinerRid;
Debug.Assert(ridDelta >= 0);
- bool isForeignInliner = inliner.Module != _globalContext;
+ bool isForeignInliner = inliner.Module != _module;
sig.Append(new UnsignedConstant((uint)(ridDelta << 1 | (isForeignInliner ? 1 : 0))));
if (isForeignInliner)
{
@@ -144,6 +150,12 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
definedSymbols: new ISymbolDefinitionNode[] { this });
}
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
+ {
+ InliningInfoNode otherInliningInfo = (InliningInfoNode)other;
+ return _module.Assembly.GetName().Name.CompareTo(otherInliningInfo._module.Assembly.GetName().Name);
+ }
+
public override int ClassCode => -87382891;
}
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/InstanceEntryPointTableNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/InstanceEntryPointTableNode.cs
index 148853d802d2e6..6bb6ade90cebee 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/InstanceEntryPointTableNode.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/InstanceEntryPointTableNode.cs
@@ -6,6 +6,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
+using System.Linq;
using System.Reflection.Metadata.Ecma335;
using Internal.JitInterface;
@@ -19,9 +20,12 @@ namespace ILCompiler.DependencyAnalysis.ReadyToRun
{
public class InstanceEntryPointTableNode : HeaderTableNode
{
- public InstanceEntryPointTableNode(TargetDetails target)
- : base(target)
+ private readonly NodeFactory _factory;
+
+ public InstanceEntryPointTableNode(NodeFactory factory)
+ : base(factory.Target)
{
+ _factory = factory;
}
public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
@@ -52,20 +56,17 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
int methodIndex = factory.RuntimeFunctionsTable.GetIndex(method);
- bool enforceOwningType = false;
- ModuleToken moduleToken = method.SignatureContext.GetModuleTokenForMethod(method.Method.GetTypicalMethodDefinition());
- if (moduleToken.Module != factory.InputModuleContext.GlobalContext)
- {
- enforceOwningType = true;
- }
+ // In composite R2R format, always enforce owning type to let us share generic instantiations among modules
+ EcmaMethod typicalMethod = (EcmaMethod)method.Method.GetTypicalMethodDefinition();
+ ModuleToken moduleToken = new ModuleToken(typicalMethod.Module, typicalMethod.Handle);
ArraySignatureBuilder signatureBuilder = new ArraySignatureBuilder();
signatureBuilder.EmitMethodSignature(
new MethodWithToken(method.Method, moduleToken, constrainedType: null),
enforceDefEncoding: true,
- enforceOwningType,
- method.SignatureContext,
- isUnboxingStub: false,
+ enforceOwningType: _factory.CompilationModuleGroup.EnforceOwningType(moduleToken.Module),
+ factory.SignatureContext,
+ isUnboxingStub: false,
isInstantiatingStub: false);
byte[] signature = signatureBuilder.ToArray();
BlobVertex signatureBlob;
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/LocalMethodImport.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/LocalMethodImport.cs
index aa0a8b60344493..cfc5b3075cabea 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/LocalMethodImport.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/LocalMethodImport.cs
@@ -1,4 +1,4 @@
-
+
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -21,8 +21,7 @@ public LocalMethodImport(
MethodWithToken method,
MethodWithGCInfo localMethod,
bool isUnboxingStub,
- bool isInstantiatingStub,
- SignatureContext signatureContext)
+ bool isInstantiatingStub)
: base(
factory,
factory.MethodImports,
@@ -31,8 +30,7 @@ public LocalMethodImport(
fixupKind,
method,
isUnboxingStub,
- isInstantiatingStub,
- signatureContext))
+ isInstantiatingStub))
{
_localMethod = localMethod;
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ManifestMetadataTableNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ManifestMetadataTableNode.cs
index 899b58ad23cc58..73ce2bfe03fcb4 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ManifestMetadataTableNode.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ManifestMetadataTableNode.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -10,6 +10,7 @@
using System.Reflection.Metadata.Ecma335;
using Internal.Text;
+using Internal.TypeSystem;
using Internal.TypeSystem.Ecma;
using Debug = System.Diagnostics.Debug;
@@ -41,7 +42,6 @@ public class ManifestMetadataTableNode : HeaderTableNode
///
private readonly Dictionary _moduleIdToAssemblyNameMap;
-
///
/// Registered signature emitters.
///
@@ -62,37 +62,49 @@ public class ManifestMetadataTableNode : HeaderTableNode
///
private bool _emissionCompleted;
- ///
- /// Name of the input assembly.
- ///
- private string _inputModuleName;
-
///
/// Node factory for the compilation
///
private readonly NodeFactory _nodeFactory;
- public ManifestMetadataTableNode(EcmaModule inputModule, NodeFactory nodeFactory)
- : base(inputModule.Context.Target)
+ public ManifestMetadataTableNode(NodeFactory nodeFactory)
+ : base(nodeFactory.Target)
{
_assemblyRefToModuleIdMap = new Dictionary();
_moduleIdToAssemblyNameMap = new Dictionary();
_signatureEmitters = new List();
_nodeFactory = nodeFactory;
- _inputModuleName = inputModule.Assembly.GetName().Name;
-
- _assemblyRefCount = inputModule.MetadataReader.GetTableRowCount(TableIndex.AssemblyRef);
- for (int assemblyRefIndex = 1; assemblyRefIndex <= _assemblyRefCount; assemblyRefIndex++)
+ if (!_nodeFactory.CompilationModuleGroup.IsCompositeBuildMode)
{
- AssemblyReferenceHandle assemblyRefHandle = MetadataTokens.AssemblyReferenceHandle(assemblyRefIndex);
- AssemblyReference assemblyRef = inputModule.MetadataReader.GetAssemblyReference(assemblyRefHandle);
- string assemblyName = inputModule.MetadataReader.GetString(assemblyRef.Name);
- _assemblyRefToModuleIdMap[assemblyName] = assemblyRefIndex;
+ MetadataReader mdReader = _nodeFactory.CompilationModuleGroup.CompilationModuleSet.Single().MetadataReader;
+ _assemblyRefCount = mdReader.GetTableRowCount(TableIndex.AssemblyRef);
+ for (int assemblyRefIndex = 1; assemblyRefIndex <= _assemblyRefCount; assemblyRefIndex++)
+ {
+ AssemblyReferenceHandle assemblyRefHandle = MetadataTokens.AssemblyReferenceHandle(assemblyRefIndex);
+ AssemblyReference assemblyRef = mdReader.GetAssemblyReference(assemblyRefHandle);
+ string assemblyName = mdReader.GetString(assemblyRef.Name);
+ _assemblyRefToModuleIdMap[assemblyName] = assemblyRefIndex;
+ }
}
// AssemblyRefCount + 1 corresponds to ROWID 0 in the manifest metadata
_nextModuleId = _assemblyRefCount + 2;
+
+ if (_nodeFactory.CompilationModuleGroup.IsCompositeBuildMode)
+ {
+ // Fill in entries for all input modules right away to make sure they have parallel indices
+ int nextExpectedId = 2;
+ foreach (EcmaModule inputModule in _nodeFactory.CompilationModuleGroup.CompilationModuleSet)
+ {
+ int acquiredId = ModuleToIndexInternal(inputModule);
+ if (acquiredId != nextExpectedId)
+ {
+ throw new InternalCompilerErrorException($"Manifest metadata consistency error - acquired ID {acquiredId}, expected {nextExpectedId}");
+ }
+ nextExpectedId++;
+ }
+ }
}
public void RegisterEmitter(ISignatureEmitter emitter)
@@ -109,6 +121,11 @@ public int ModuleToIndex(EcmaModule module)
throw new InvalidOperationException("Cannot get ModuleToIndex mapping until marking is complete.");
}
+ return ModuleToIndexInternal(module);
+ }
+
+ private int ModuleToIndexInternal(EcmaModule module)
+ {
AssemblyName assemblyName = module.Assembly.GetName();
int assemblyRefIndex;
if (!_assemblyRefToModuleIdMap.TryGetValue(assemblyName.Name, out assemblyRefIndex))
@@ -159,8 +176,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
MetadataBuilder metadataBuilder = new MetadataBuilder();
+ string manifestMetadataAssemblyName = "ManifestMetadata";
metadataBuilder.AddAssembly(
- metadataBuilder.GetOrAddString(_inputModuleName),
+ metadataBuilder.GetOrAddString(manifestMetadataAssemblyName),
new Version(0, 0, 0, 0),
culture: default(StringHandle),
publicKey: default(BlobHandle),
@@ -169,17 +187,17 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
metadataBuilder.AddModule(
0,
- metadataBuilder.GetOrAddString(_inputModuleName),
+ metadataBuilder.GetOrAddString(manifestMetadataAssemblyName),
default(GuidHandle), default(GuidHandle), default(GuidHandle));
// Module type
metadataBuilder.AddTypeDefinition(
- default(TypeAttributes),
- default(StringHandle),
- metadataBuilder.GetOrAddString(""),
- baseType: default(EntityHandle),
- fieldList: MetadataTokens.FieldDefinitionHandle(1),
- methodList: MetadataTokens.MethodDefinitionHandle(1));
+ default(TypeAttributes),
+ default(StringHandle),
+ metadataBuilder.GetOrAddString(""),
+ baseType: default(EntityHandle),
+ fieldList: MetadataTokens.FieldDefinitionHandle(1),
+ methodList: MetadataTokens.MethodDefinitionHandle(1));
foreach (var idAndAssemblyName in _moduleIdToAssemblyNameMap.OrderBy(x => x.Key))
{
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodEntryPointTableNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodEntryPointTableNode.cs
index 6bbfc6324f3771..0df4157babc596 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodEntryPointTableNode.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodEntryPointTableNode.cs
@@ -18,6 +18,8 @@ namespace ILCompiler.DependencyAnalysis.ReadyToRun
{
public class MethodEntryPointTableNode : HeaderTableNode
{
+ private readonly EcmaModule _module;
+
private struct EntryPoint
{
public static EntryPoint Null = new EntryPoint(-1, null);
@@ -34,15 +36,17 @@ public EntryPoint(int methodIndex, MethodWithGCInfo method)
}
}
- public MethodEntryPointTableNode(TargetDetails target)
+ public MethodEntryPointTableNode(EcmaModule module, TargetDetails target)
: base(target)
{
+ _module = module;
}
public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append(nameMangler.CompilationUnitPrefix);
- sb.Append("__ReadyToRunMethodEntryPointTable");
+ sb.Append("__ReadyToRunMethodEntryPointTable__");
+ sb.Append(_module.Assembly.GetName().Name);
}
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
@@ -56,7 +60,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
foreach (MethodWithGCInfo method in factory.EnumerateCompiledMethods())
{
- if (method.Method is EcmaMethod ecmaMethod)
+ if (method.Method is EcmaMethod ecmaMethod && ecmaMethod.Module == _module)
{
// Strip away the token type bits, keep just the low 24 bits RID
uint rid = SignatureBuilder.RidFromToken((mdToken)MetadataTokens.GetToken(ecmaMethod.Handle));
@@ -112,6 +116,13 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
alignment: 8,
definedSymbols: new ISymbolDefinitionNode[] { this });
}
+
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
+ {
+ MethodEntryPointTableNode otherMethodEntryPointTable = (MethodEntryPointTableNode)other;
+ return _module.Assembly.GetName().Name.CompareTo(otherMethodEntryPointTable._module.Assembly.GetName().Name);
+ }
+
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
public override int ClassCode => (int)ObjectNodeOrder.MethodEntrypointTableNode;
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodFixupSignature.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodFixupSignature.cs
index 9db96bd3281a66..7461e662a291cb 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodFixupSignature.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodFixupSignature.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -19,8 +19,6 @@ public class MethodFixupSignature : Signature
private readonly MethodWithToken _method;
- private readonly SignatureContext _signatureContext;
-
private readonly bool _isUnboxingStub;
private readonly bool _isInstantiatingStub;
@@ -28,20 +26,19 @@ public class MethodFixupSignature : Signature
public MethodFixupSignature(
ReadyToRunFixupKind fixupKind,
MethodWithToken method,
- SignatureContext signatureContext,
bool isUnboxingStub,
bool isInstantiatingStub)
{
_fixupKind = fixupKind;
_method = method;
- _signatureContext = signatureContext;
_isUnboxingStub = isUnboxingStub;
_isInstantiatingStub = isInstantiatingStub;
// Ensure types in signature are loadable and resolvable, otherwise we'll fail later while emitting the signature
- signatureContext.Resolver.CompilerContext.EnsureLoadableMethod(method.Method);
+ CompilerTypeSystemContext compilerContext = (CompilerTypeSystemContext)method.Method.Context;
+ compilerContext.EnsureLoadableMethod(method.Method);
if (method.ConstrainedType != null)
- signatureContext.Resolver.CompilerContext.EnsureLoadableType(method.ConstrainedType);
+ compilerContext.EnsureLoadableType(method.ConstrainedType);
}
public MethodDesc Method => _method.Method;
@@ -88,18 +85,18 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
if (method.Token.TokenType == CorTokenType.mdtMethodSpec)
{
- method = new MethodWithToken(method.Method, _signatureContext.GetModuleTokenForMethod(method.Method, throwIfNotFound: false), method.ConstrainedType);
+ method = new MethodWithToken(method.Method, factory.SignatureContext.GetModuleTokenForMethod(method.Method, throwIfNotFound: false), method.ConstrainedType);
}
else if (!optimized && (method.Token.TokenType == CorTokenType.mdtMemberRef))
{
if (method.Method.OwningType.GetTypeDefinition() is EcmaType)
{
- method = new MethodWithToken(method.Method, _signatureContext.GetModuleTokenForMethod(method.Method, throwIfNotFound: false), method.ConstrainedType);
+ method = new MethodWithToken(method.Method, factory.SignatureContext.GetModuleTokenForMethod(method.Method, throwIfNotFound: false), method.ConstrainedType);
}
}
}
- SignatureContext innerContext = dataBuilder.EmitFixup(factory, fixupKind, method.Token.Module, _signatureContext);
+ SignatureContext innerContext = dataBuilder.EmitFixup(factory, fixupKind, method.Token.Module, factory.SignatureContext);
if (optimized && method.Token.TokenType == CorTokenType.mdtMethodDef)
{
@@ -149,11 +146,7 @@ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer
if (result != 0)
return result;
- result = _method.CompareTo(otherNode._method, comparer);
- if (result != 0)
- return result;
-
- return _signatureContext.CompareTo(otherNode._signatureContext, comparer);
+ return _method.CompareTo(otherNode._method, comparer);
}
}
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodGCInfoNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodGCInfoNode.cs
index bf6b60ab7ff23f..e9c63096d16895 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodGCInfoNode.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodGCInfoNode.cs
@@ -1,10 +1,10 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
using System.Collections.Generic;
using Internal.Text;
+using Internal.TypeSystem;
namespace ILCompiler.DependencyAnalysis.ReadyToRun
{
@@ -41,7 +41,7 @@ public int[] CalculateFuncletOffsets(NodeFactory factory)
offsets[frameInfoIndex] = offset;
offset += _methodNode.FrameInfos[frameInfoIndex].BlobData.Length;
offset += (-offset & 3); // 4-alignment for the personality routine
- if (factory.Target.Architecture != Internal.TypeSystem.TargetArchitecture.X86)
+ if (factory.Target.Architecture != TargetArchitecture.X86)
{
offset += sizeof(uint); // personality routine
}
@@ -60,11 +60,14 @@ public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory f
{
return;
}
+
+ TargetArchitecture targetArch = factory.Target.Architecture;
+
for (int frameInfoIndex = 0; frameInfoIndex < _methodNode.FrameInfos.Length; frameInfoIndex++)
{
byte[] unwindInfo = _methodNode.FrameInfos[frameInfoIndex].BlobData;
- if (factory.Target.Architecture == Internal.TypeSystem.TargetArchitecture.X64)
+ if (targetArch == TargetArchitecture.X64)
{
// On Amd64, patch the first byte of the unwind info by setting the flags to EHANDLER | UHANDLER
// as that's what CoreCLR does (zapcode.cpp, ZapUnwindData::Save).
@@ -74,12 +77,17 @@ public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory f
unwindInfo[0] |= (byte)((UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER) << FlagsShift);
}
+ else if ((targetArch == TargetArchitecture.ARM) || (targetArch == TargetArchitecture.ARM64))
+ {
+ // Set the 'X' bit to indicate that there is a personality routine associated with this method
+ unwindInfo[2] |= 1 << 4;
+ }
dataBuilder.EmitBytes(unwindInfo);
// 4-align after emitting the unwind info
dataBuilder.EmitZeros(-unwindInfo.Length & 3);
- if (factory.Target.Architecture != Internal.TypeSystem.TargetArchitecture.X86)
+ if (targetArch != TargetArchitecture.X86)
{
bool isFilterFunclet = (_methodNode.FrameInfos[frameInfoIndex].Flags & FrameInfoFlags.Filter) != 0;
ISymbolNode personalityRoutine = (isFilterFunclet ? factory.FilterFuncletPersonalityRoutine : factory.PersonalityRoutine);
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodWithGCInfo.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodWithGCInfo.cs
index c1a25d32fec918..b82737e07152e2 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodWithGCInfo.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodWithGCInfo.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -17,7 +17,6 @@ public class MethodWithGCInfo : ObjectNode, IReadyToRunMethodCodeNode, IMethodBo
public readonly MethodGCInfoNode GCInfoNode;
private readonly MethodDesc _method;
- public SignatureContext SignatureContext { get; }
private ObjectData _methodCode;
private FrameInfo[] _frameInfos;
@@ -29,12 +28,11 @@ public class MethodWithGCInfo : ObjectNode, IReadyToRunMethodCodeNode, IMethodBo
private List _fixups;
private MethodDesc[] _inlinedMethods;
- public MethodWithGCInfo(MethodDesc methodDesc, SignatureContext signatureContext)
+ public MethodWithGCInfo(MethodDesc methodDesc)
{
GCInfoNode = new MethodGCInfoNode(this);
_fixups = new List();
_method = methodDesc;
- SignatureContext = signatureContext;
}
public void SetCode(ObjectData data)
@@ -294,11 +292,7 @@ public void InitializeDebugEHClauseInfos(DebugEHClauseInfo[] debugEHClauseInfos)
public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
MethodWithGCInfo otherNode = (MethodWithGCInfo)other;
- int result = comparer.Compare(_method, otherNode._method);
- if (result != 0)
- return result;
-
- return SignatureContext.CompareTo(otherNode.SignatureContext, comparer);
+ return comparer.Compare(_method, otherNode._method);
}
public void InitializeInliningInfo(MethodDesc[] inlinedMethods)
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ModuleToken.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ModuleToken.cs
index af2ea0b022c2ae..71b52cdc0efd68 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ModuleToken.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ModuleToken.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ModuleTokenResolver.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ModuleTokenResolver.cs
index af040078dcedbe..0bb2af7f3d1a2d 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ModuleTokenResolver.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ModuleTokenResolver.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/NewArrayFixupSignature.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/NewArrayFixupSignature.cs
index 752191eae875a9..7372d0235de3dd 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/NewArrayFixupSignature.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/NewArrayFixupSignature.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -12,15 +12,13 @@ namespace ILCompiler.DependencyAnalysis.ReadyToRun
public class NewArrayFixupSignature : Signature
{
private readonly ArrayType _arrayType;
- private readonly SignatureContext _signatureContext;
- public NewArrayFixupSignature(ArrayType arrayType, SignatureContext signatureContext)
+ public NewArrayFixupSignature(ArrayType arrayType)
{
_arrayType = arrayType;
- _signatureContext = signatureContext;
// Ensure types in signature are loadable and resolvable, otherwise we'll fail later while emitting the signature
- signatureContext.Resolver.CompilerContext.EnsureLoadableType(arrayType);
+ ((CompilerTypeSystemContext)arrayType.Context).EnsureLoadableType(arrayType);
}
public override int ClassCode => 815543321;
@@ -33,8 +31,8 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
dataBuilder.AddSymbol(this);
- EcmaModule targetModule = _signatureContext.GetTargetModule(_arrayType);
- SignatureContext innerContext = dataBuilder.EmitFixup(factory, ReadyToRunFixupKind.NewArray, targetModule, _signatureContext);
+ EcmaModule targetModule = factory.SignatureContext.GetTargetModule(_arrayType);
+ SignatureContext innerContext = dataBuilder.EmitFixup(factory, ReadyToRunFixupKind.NewArray, targetModule, factory.SignatureContext);
dataBuilder.EmitTypeSignature(_arrayType, innerContext);
}
@@ -51,11 +49,7 @@ public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilde
public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
NewArrayFixupSignature otherNode = (NewArrayFixupSignature)other;
- int result = comparer.Compare(_arrayType, otherNode._arrayType);
- if (result != 0)
- return result;
-
- return _signatureContext.CompareTo(otherNode._signatureContext, comparer);
+ return comparer.Compare(_arrayType, otherNode._arrayType);
}
}
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/NewObjectFixupSignature.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/NewObjectFixupSignature.cs
index 1a63f79a1ff6d9..acfeb03b34fd95 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/NewObjectFixupSignature.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/NewObjectFixupSignature.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -12,15 +12,13 @@ namespace ILCompiler.DependencyAnalysis.ReadyToRun
public class NewObjectFixupSignature : Signature
{
private readonly TypeDesc _typeDesc;
- private readonly SignatureContext _signatureContext;
- public NewObjectFixupSignature(TypeDesc typeDesc, SignatureContext signatureContext)
+ public NewObjectFixupSignature(TypeDesc typeDesc)
{
_typeDesc = typeDesc;
- _signatureContext = signatureContext;
// Ensure types in signature are loadable and resolvable, otherwise we'll fail later while emitting the signature
- signatureContext.Resolver.CompilerContext.EnsureLoadableType(typeDesc);
+ ((CompilerTypeSystemContext)typeDesc.Context).EnsureLoadableType(typeDesc);
}
public override int ClassCode => 551247760;
@@ -33,8 +31,8 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
dataBuilder.AddSymbol(this);
- EcmaModule targetModule = _signatureContext.GetTargetModule(_typeDesc);
- SignatureContext innerContext = dataBuilder.EmitFixup(factory, ReadyToRunFixupKind.NewObject, targetModule, _signatureContext);
+ EcmaModule targetModule = factory.SignatureContext.GetTargetModule(_typeDesc);
+ SignatureContext innerContext = dataBuilder.EmitFixup(factory, ReadyToRunFixupKind.NewObject, targetModule, factory.SignatureContext);
dataBuilder.EmitTypeSignature(_typeDesc, innerContext);
}
@@ -51,11 +49,7 @@ public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilde
public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
NewObjectFixupSignature otherNode = (NewObjectFixupSignature)other;
- int result = comparer.Compare(_typeDesc, otherNode._typeDesc);
- if (result != 0)
- return result;
-
- return _signatureContext.CompareTo(otherNode._signatureContext, comparer);
+ return comparer.Compare(_typeDesc, otherNode._typeDesc);
}
}
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/NibbleWriter.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/NibbleWriter.cs
index b0f7e3858cec55..edb123e9b02159 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/NibbleWriter.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/NibbleWriter.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/OwnerCompositeExecutableNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/OwnerCompositeExecutableNode.cs
new file mode 100644
index 00000000000000..bc79b4402f4919
--- /dev/null
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/OwnerCompositeExecutableNode.cs
@@ -0,0 +1,46 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Text;
+using Internal.Text;
+using Internal.TypeSystem;
+
+namespace ILCompiler.DependencyAnalysis.ReadyToRun
+{
+ ///
+ /// R2R header section holding the name of the composite R2R executable with native code
+ /// for this component module. This section gets put into R2R headers emitted when
+ /// rewriting input MSIL into standalone MSIL components of a composite R2R image.
+ /// It is used by the runtime as forwarding information to locate the composite R2R image
+ /// with the native code for a given MSIL assembly.
+ ///
+ internal class OwnerCompositeExecutableNode : HeaderTableNode
+ {
+ public override ObjectNodeSection Section => ObjectNodeSection.ReadOnlyDataSection;
+
+ public override int ClassCode => 240420333;
+
+ private readonly string _ownerExecutableName;
+
+ public OwnerCompositeExecutableNode(TargetDetails target, string ownerExecutableName)
+ : base(target)
+ {
+ _ownerExecutableName = ownerExecutableName;
+ }
+
+ public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
+ {
+ sb.Append("__ReadyToRunHeader_OwnerCompositeExecutable");
+ }
+
+ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
+ {
+ ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly);
+ builder.RequireInitialPointerAlignment();
+ builder.AddSymbol(this);
+ builder.EmitBytes(Encoding.UTF8.GetBytes(_ownerExecutableName));
+ return builder.ToObjectData();
+ }
+ }
+}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/PrecodeHelperImport.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/PrecodeHelperImport.cs
index f3b22c06a901d3..c9f685256fad91 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/PrecodeHelperImport.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/PrecodeHelperImport.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/PrecodeMethodImport.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/PrecodeMethodImport.cs
index cf6442294c9d08..7b691c4e308263 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/PrecodeMethodImport.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/PrecodeMethodImport.cs
@@ -22,16 +22,14 @@ public PrecodeMethodImport(
MethodWithToken method,
MethodWithGCInfo localMethod,
bool isUnboxingStub,
- bool isInstantiatingStub,
- SignatureContext signatureContext) :
+ bool isInstantiatingStub) :
base (
factory,
factory.MethodSignature(
fixupKind,
method,
isUnboxingStub,
- isInstantiatingStub,
- signatureContext)
+ isInstantiatingStub)
)
{
_localMethod = localMethod;
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ProfileDataNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ProfileDataNode.cs
index 6c2308d3bffd0a..16832b6cd05819 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ProfileDataNode.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ProfileDataNode.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ProfileDataSectionNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ProfileDataSectionNode.cs
index 5bddb460918ba0..44d6282410c12b 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ProfileDataSectionNode.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ProfileDataSectionNode.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ReadyToRunHelperSignature.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ReadyToRunHelperSignature.cs
index 5f037bc91503f1..8d05e925e5f20f 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ReadyToRunHelperSignature.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ReadyToRunHelperSignature.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/RuntimeFunctionsGCInfoNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/RuntimeFunctionsGCInfoNode.cs
index cb1bf6396bc02e..0d6c9dcac648bb 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/RuntimeFunctionsGCInfoNode.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/RuntimeFunctionsGCInfoNode.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Signature.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Signature.cs
index 8b50e939495d87..4e3eaa390ab7ab 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Signature.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Signature.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/SignatureBuilder.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/SignatureBuilder.cs
index 651a6902f04cba..4d76fb7cb89887 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/SignatureBuilder.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/SignatureBuilder.cs
@@ -1,4 +1,4 @@
-// The .NET Foundation licenses this file to you under the MIT license.
+// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/SignatureContext.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/SignatureContext.cs
index c52f7156687a90..901cc90a282350 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/SignatureContext.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/SignatureContext.cs
@@ -1,4 +1,4 @@
-// The .NET Foundation licenses this file to you under the MIT license.
+// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
@@ -97,17 +97,31 @@ public override bool Equals(object obj)
public override int GetHashCode()
{
- return GlobalContext.GetHashCode()
- ^ (LocalContext.GetHashCode() * 31);
+ return (GlobalContext?.GetHashCode() ?? 0) ^ ((LocalContext?.GetHashCode() ?? 0) * 31);
}
public int CompareTo(SignatureContext other, TypeSystemComparer comparer)
{
+ if (GlobalContext == null || other.GlobalContext == null)
+ {
+ return (GlobalContext != null ? 1 : other.GlobalContext != null ? -1 : 0);
+ }
+
int result = GlobalContext.CompareTo(other.GlobalContext);
if (result != 0)
return result;
+ if (LocalContext == null || other.LocalContext == null)
+ {
+ return (LocalContext != null ? 1 : other.LocalContext != null ? -1 : 0);
+ }
+
return LocalContext.CompareTo(other.LocalContext);
}
+
+ public override string ToString()
+ {
+ return (GlobalContext != null ? GlobalContext.Assembly.GetName().Name : "");
+ }
}
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/SignatureEmbeddedPointerIndirectionNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/SignatureEmbeddedPointerIndirectionNode.cs
index 3dd600cef34f62..eec93744449fb9 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/SignatureEmbeddedPointerIndirectionNode.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/SignatureEmbeddedPointerIndirectionNode.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/StringImport.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/StringImport.cs
index b410ead3f6b763..ef9f5bb378b33c 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/StringImport.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/StringImport.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -10,8 +10,8 @@ public class StringImport : Import
{
private readonly ModuleToken _token;
- public StringImport(ImportSectionNode table, ModuleToken token, SignatureContext signatureContext)
- : base(table, new StringImportSignature(token, signatureContext))
+ public StringImport(ImportSectionNode table, ModuleToken token)
+ : base(table, new StringImportSignature(token))
{
_token = token;
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/StringImportSignature.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/StringImportSignature.cs
index 1ce924d999a90d..b44e178738b73a 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/StringImportSignature.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/StringImportSignature.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -11,12 +11,9 @@ public class StringImportSignature : Signature
{
private readonly ModuleToken _token;
- private readonly SignatureContext _signatureContext;
-
- public StringImportSignature(ModuleToken token, SignatureContext signatureContext)
+ public StringImportSignature(ModuleToken token)
{
_token = token;
- _signatureContext = signatureContext;
}
public override int ClassCode => 324832559;
@@ -29,7 +26,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
dataBuilder.AddSymbol(this);
- dataBuilder.EmitFixup(factory, ReadyToRunFixupKind.StringHandle, _token.Module, _signatureContext);
+ dataBuilder.EmitFixup(factory, ReadyToRunFixupKind.StringHandle, _token.Module, factory.SignatureContext);
dataBuilder.EmitUInt(_token.TokenRid);
}
@@ -45,10 +42,6 @@ public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilde
public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
StringImportSignature otherNode = (StringImportSignature)other;
- int result = _signatureContext.CompareTo(otherNode._signatureContext, comparer);
- if (result != 0)
- return result;
-
return _token.CompareTo(otherNode._token);
}
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Target_ARM/ImportThunk.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Target_ARM/ImportThunk.cs
index 52cf31cba21d1f..15576926d06587 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Target_ARM/ImportThunk.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Target_ARM/ImportThunk.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Target_ARM64/ImportThunk.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Target_ARM64/ImportThunk.cs
index 354b0609b8a5a0..b8d18bdff1575f 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Target_ARM64/ImportThunk.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Target_ARM64/ImportThunk.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Target_X64/ImportThunk.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Target_X64/ImportThunk.cs
index 2305345aa7f8d1..554953a27f1414 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Target_X64/ImportThunk.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Target_X64/ImportThunk.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Target_X86/ImportThunk.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Target_X86/ImportThunk.cs
index 906beed7d2309a..28966aaf743a29 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Target_X86/ImportThunk.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Target_X86/ImportThunk.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/TransitionBlock.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/TransitionBlock.cs
index 7571cbd7d939c8..70f7c4a908e3b5 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/TransitionBlock.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/TransitionBlock.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -471,6 +471,9 @@ private sealed class Arm32TransitionBlock : TransitionBlock
public override int OffsetOfFloatArgumentRegisters => 8 * sizeof(double) + PointerSize;
public override int EnregisteredParamTypeMaxSize => 0;
public override int EnregisteredReturnTypeIntegerMaxSize => 4;
+
+ public override bool IsArgPassedByRef(TypeHandle th) => false;
+
public override int GetRetBuffArgOffset(bool hasThis) => OffsetOfArgumentRegisters + (hasThis ? PointerSize : 0);
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/TypeFixupSignature.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/TypeFixupSignature.cs
index e020564f8c7f58..3ae821d2dbf77d 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/TypeFixupSignature.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/TypeFixupSignature.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -17,16 +17,13 @@ public class TypeFixupSignature : Signature
private readonly TypeDesc _typeDesc;
- private readonly SignatureContext _signatureContext;
-
- public TypeFixupSignature(ReadyToRunFixupKind fixupKind, TypeDesc typeDesc, SignatureContext signatureContext)
+ public TypeFixupSignature(ReadyToRunFixupKind fixupKind, TypeDesc typeDesc)
{
_fixupKind = fixupKind;
_typeDesc = typeDesc;
- _signatureContext = signatureContext;
// Ensure types in signature are loadable and resolvable, otherwise we'll fail later while emitting the signature
- signatureContext.Resolver.CompilerContext.EnsureLoadableType(typeDesc);
+ ((CompilerTypeSystemContext)typeDesc.Context).EnsureLoadableType(typeDesc);
}
public override int ClassCode => 255607008;
@@ -39,8 +36,8 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
dataBuilder.AddSymbol(this);
- EcmaModule targetModule = _signatureContext.GetTargetModule(_typeDesc);
- SignatureContext innerContext = dataBuilder.EmitFixup(factory, _fixupKind, targetModule, _signatureContext);
+ EcmaModule targetModule = factory.SignatureContext.GetTargetModule(_typeDesc);
+ SignatureContext innerContext = dataBuilder.EmitFixup(factory, _fixupKind, targetModule, factory.SignatureContext);
dataBuilder.EmitTypeSignature(_typeDesc, innerContext);
}
@@ -61,11 +58,7 @@ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer
if (result != 0)
return result;
- result = comparer.Compare(_typeDesc, otherNode._typeDesc);
- if (result != 0)
- return result;
-
- return _signatureContext.CompareTo(otherNode._signatureContext, comparer);
+ return comparer.Compare(_typeDesc, otherNode._typeDesc);
}
protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory)
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/TypesTableNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/TypesTableNode.cs
index 26a204e83dfc46..502da243746c77 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/TypesTableNode.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/TypesTableNode.cs
@@ -18,13 +18,19 @@ namespace ILCompiler.DependencyAnalysis.ReadyToRun
{
public class TypesTableNode : HeaderTableNode
{
- public TypesTableNode(TargetDetails target)
- : base(target) {}
+ private readonly EcmaModule _module;
+
+ public TypesTableNode(TargetDetails target, EcmaModule module)
+ : base(target)
+ {
+ _module = module;
+ }
public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append(nameMangler.CompilationUnitPrefix);
- sb.Append("__ReadyToRunAvailableTypesTable");
+ sb.Append("__ReadyToRunAvailableTypesTable__");
+ sb.Append(_module.Assembly.GetName().Name);
}
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
@@ -40,8 +46,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
section.Place(typesHashtable);
ReadyToRunTableManager r2rManager = (ReadyToRunTableManager)factory.MetadataManager;
-
- foreach (TypeInfo defTypeInfo in r2rManager.GetDefinedTypes())
+ foreach (TypeInfo defTypeInfo in r2rManager.GetDefinedTypes(_module))
{
TypeDefinitionHandle defTypeHandle = defTypeInfo.Handle;
int hashCode = 0;
@@ -60,7 +65,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
typesHashtable.Append(unchecked((uint)hashCode), section.Place(new UnsignedConstant(((uint)MetadataTokens.GetRowNumber(defTypeInfo.Handle) << 1) | 0)));
}
- foreach (TypeInfo expTypeInfo in r2rManager.GetExportedTypes())
+ foreach (TypeInfo expTypeInfo in r2rManager.GetExportedTypes(_module))
{
ExportedTypeHandle expTypeHandle = expTypeInfo.Handle;
int hashCode = 0;
@@ -90,6 +95,12 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
definedSymbols: new ISymbolDefinitionNode[] { this });
}
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
+ {
+ TypesTableNode otherTypesTable = (TypesTableNode)other;
+ return _module.Assembly.GetName().Name.CompareTo(otherTypesTable._module.Assembly.GetName().Name);
+ }
+
public override int ClassCode => -944318825;
}
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Win32ResourcesNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Win32ResourcesNode.cs
index 929e762b8c73f7..ea37c34fd1c931 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Win32ResourcesNode.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Win32ResourcesNode.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -17,6 +17,7 @@ public class Win32ResourcesNode : ObjectNode, ISymbolDefinitionNode
public Win32ResourcesNode(ResourceData resourceData)
{
_resourceData = resourceData;
+ _size = -1;
}
public override ObjectNodeSection Section => ObjectNodeSection.TextSection;
@@ -35,6 +36,11 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
}
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
+ {
+ return GetDataInternal();
+ }
+
+ private ObjectData GetDataInternal()
{
ObjectDataBuilder builder = new ObjectDataBuilder();
builder.AddSymbol(this);
@@ -48,6 +54,16 @@ protected override string GetName(NodeFactory context)
return "____Win32Resources";
}
- public int Size => _size;
+ public int Size
+ {
+ get
+ {
+ if (_size < 0)
+ {
+ GetDataInternal();
+ }
+ return _size;
+ }
+ }
}
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs
index 0bce3fbbc51523..6a3e4ef56c19bb 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -6,6 +6,7 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Linq;
using ILCompiler.DependencyAnalysis.ReadyToRun;
using ILCompiler.DependencyAnalysisFramework;
@@ -68,13 +69,13 @@ public void SetMarkingComplete()
public IMethodNode MethodEntrypoint(MethodDesc method)
{
+ EcmaModule module = ((EcmaMethod)method.GetTypicalMethodDefinition()).Module;
ModuleToken moduleToken = Resolver.GetModuleTokenForMethod(method, throwIfNotFound: true);
return MethodEntrypoint(
new MethodWithToken(method, moduleToken, constrainedType: null),
isUnboxingStub: false,
isInstantiatingStub: false,
- isPrecodeImportRequired: false,
- signatureContext: InputModuleContext);
+ isPrecodeImportRequired: false);
}
private NodeCache _allMethodsOnType;
@@ -175,28 +176,33 @@ public NodeFactory(
CompilerTypeSystemContext context,
CompilationModuleGroup compilationModuleGroup,
NameMangler nameMangler,
- ModuleTokenResolver moduleTokenResolver,
- SignatureContext signatureContext,
CopiedCorHeaderNode corHeaderNode,
DebugDirectoryNode debugDirectoryNode,
ResourceData win32Resources,
- AttributePresenceFilterNode attributePresenceFilterNode,
- HeaderNode headerNode)
+ ReadyToRunFlags flags)
{
TypeSystemContext = context;
CompilationModuleGroup = compilationModuleGroup;
Target = context.Target;
NameMangler = nameMangler;
MetadataManager = new ReadyToRunTableManager(context);
- Resolver = moduleTokenResolver;
- InputModuleContext = signatureContext;
CopiedCorHeaderNode = corHeaderNode;
DebugDirectoryNode = debugDirectoryNode;
- AttributePresenceFilter = attributePresenceFilterNode;
- Header = headerNode;
+ Resolver = new ModuleTokenResolver(compilationModuleGroup, TypeSystemContext);
+ Header = new GlobalHeaderNode(Target, flags);
if (!win32Resources.IsEmpty)
Win32ResourcesNode = new Win32ResourcesNode(win32Resources);
+ if (CompilationModuleGroup.IsCompositeBuildMode)
+ {
+ // Create a null top-level signature context to force producing module overrides for all signaturess
+ SignatureContext = new SignatureContext(null, Resolver);
+ }
+ else
+ {
+ SignatureContext = new SignatureContext(CompilationModuleGroup.CompilationModuleSet.Single(), Resolver);
+ }
+
CreateNodeCaches();
}
@@ -215,8 +221,7 @@ private void CreateNodeCaches()
GetGenericStaticHelper(helperKey.HelperId),
TypeSignature(
ReadyToRunFixupKind.Invalid,
- (TypeDesc)helperKey.Target,
- InputModuleContext));
+ (TypeDesc)helperKey.Target));
});
_genericReadyToRunHelpersFromType = new NodeCache(helperKey =>
@@ -227,8 +232,7 @@ private void CreateNodeCaches()
GetGenericStaticHelper(helperKey.HelperId),
TypeSignature(
ReadyToRunFixupKind.Invalid,
- (TypeDesc)helperKey.Target,
- InputModuleContext));
+ (TypeDesc)helperKey.Target));
});
_readOnlyDataBlobs = new NodeCache(key =>
@@ -243,9 +247,9 @@ private void CreateNodeCaches()
_importMethods = new NodeCache(CreateMethodEntrypoint);
- _localMethodCache = new NodeCache(key =>
+ _localMethodCache = new NodeCache(key =>
{
- return new MethodWithGCInfo(key.Method.Method, key.SignatureContext);
+ return new MethodWithGCInfo(key);
});
_methodSignatures = new NodeCache(key =>
@@ -253,7 +257,6 @@ private void CreateNodeCaches()
return new MethodFixupSignature(
key.FixupKind,
key.TypeAndMethod.Method,
- key.TypeAndMethod.SignatureContext,
key.TypeAndMethod.IsUnboxingStub,
key.TypeAndMethod.IsInstantiatingStub
);
@@ -261,7 +264,7 @@ private void CreateNodeCaches()
_typeSignatures = new NodeCache(key =>
{
- return new TypeFixupSignature(key.FixupKind, key.TypeDesc, InputModuleContext);
+ return new TypeFixupSignature(key.FixupKind, key.TypeDesc);
});
_dynamicHelperCellCache = new NodeCache(key =>
@@ -276,10 +279,8 @@ private void CreateNodeCaches()
MethodSignature(
ReadyToRunFixupKind.VirtualEntry,
key.Method,
- signatureContext: key.SignatureContext,
isUnboxingStub: key.IsUnboxingStub,
- isInstantiatingStub: key.IsInstantiatingStub),
- key.SignatureContext);
+ isInstantiatingStub: key.IsInstantiatingStub));
});
_copiedCorHeaders = new NodeCache(module =>
@@ -326,7 +327,7 @@ private void CreateNodeCaches()
});
}
- public SignatureContext InputModuleContext;
+ public SignatureContext SignatureContext;
public ModuleTokenResolver Resolver;
@@ -336,7 +337,7 @@ private void CreateNodeCaches()
public Win32ResourcesNode Win32ResourcesNode;
- public HeaderNode Header;
+ public GlobalHeaderNode Header;
public RuntimeFunctionsTableNode RuntimeFunctionsTable;
@@ -344,14 +345,10 @@ private void CreateNodeCaches()
public ProfileDataSectionNode ProfileDataSection;
- public MethodEntryPointTableNode MethodEntryPointTable;
-
public InstanceEntryPointTableNode InstanceEntryPointTable;
public ManifestMetadataTableNode ManifestMetadataTable;
- public TypesTableNode TypesTable;
-
public ImportSectionsTableNode ImportSectionsTable;
public Import ModuleImport;
@@ -362,10 +359,6 @@ private void CreateNodeCaches()
public DebugInfoTableNode DebugInfoTable;
- public InliningInfoNode InliningInfoTable;
-
- public AttributePresenceFilterNode AttributePresenceFilter;
-
public ImportSectionNode EagerImports;
public ImportSectionNode MethodImports;
@@ -393,7 +386,6 @@ private IMethodNode CreateMethodEntrypoint(TypeAndMethod key)
bool isUnboxingStub = key.IsUnboxingStub;
bool isInstantiatingStub = key.IsInstantiatingStub;
bool isPrecodeImportRequired = key.IsPrecodeImportRequired;
- SignatureContext signatureContext = key.SignatureContext;
if (CompilationModuleGroup.ContainsMethodBody(method.Method, false))
{
if (isPrecodeImportRequired)
@@ -402,10 +394,9 @@ private IMethodNode CreateMethodEntrypoint(TypeAndMethod key)
this,
ReadyToRunFixupKind.MethodEntry,
method,
- CreateMethodEntrypointNodeHelper(method, signatureContext),
+ CreateMethodEntrypointNodeHelper(method),
isUnboxingStub,
- isInstantiatingStub,
- signatureContext);
+ isInstantiatingStub);
}
else
{
@@ -413,10 +404,9 @@ private IMethodNode CreateMethodEntrypoint(TypeAndMethod key)
this,
ReadyToRunFixupKind.MethodEntry,
method,
- CreateMethodEntrypointNodeHelper(method, signatureContext),
+ CreateMethodEntrypointNodeHelper(method),
isUnboxingStub,
- isInstantiatingStub,
- signatureContext);
+ isInstantiatingStub);
}
}
else
@@ -427,37 +417,24 @@ private IMethodNode CreateMethodEntrypoint(TypeAndMethod key)
ReadyToRunFixupKind.MethodEntry,
method,
isUnboxingStub,
- isInstantiatingStub,
- signatureContext);
+ isInstantiatingStub);
}
}
- public IMethodNode MethodEntrypoint(
- MethodWithToken method,
- bool isUnboxingStub,
- bool isInstantiatingStub,
- bool isPrecodeImportRequired,
- SignatureContext signatureContext)
+ public IMethodNode MethodEntrypoint(MethodWithToken method, bool isUnboxingStub, bool isInstantiatingStub, bool isPrecodeImportRequired)
{
- TypeAndMethod key = new TypeAndMethod(method.ConstrainedType, method, isUnboxingStub, isInstantiatingStub, isPrecodeImportRequired, signatureContext);
+ TypeAndMethod key = new TypeAndMethod(method.ConstrainedType, method, isUnboxingStub, isInstantiatingStub, isPrecodeImportRequired);
return _importMethods.GetOrAdd(key);
}
- private NodeCache _localMethodCache = new NodeCache();
+ private NodeCache _localMethodCache;
- private MethodWithGCInfo CreateMethodEntrypointNodeHelper(MethodWithToken targetMethod, SignatureContext signatureContext)
+ private MethodWithGCInfo CreateMethodEntrypointNodeHelper(MethodWithToken targetMethod)
{
Debug.Assert(CompilationModuleGroup.ContainsMethodBody(targetMethod.Method, false));
MethodDesc localMethod = targetMethod.Method.GetCanonMethodTarget(CanonicalFormKind.Specific);
-
- TypeAndMethod localMethodKey = new TypeAndMethod(localMethod.OwningType,
- new MethodWithToken(localMethod, default(ModuleToken), constrainedType: null),
- isUnboxingStub: false,
- isInstantiatingStub: false,
- isPrecodeImportRequired: false,
- signatureContext);
- return _localMethodCache.GetOrAdd(localMethodKey);
+ return _localMethodCache.GetOrAdd(localMethod);
}
public IEnumerable EnumerateCompiledMethods()
@@ -470,9 +447,9 @@ public IEnumerable EnumerateCompiledMethods()
{
methodCodeNode = localMethodImport.MethodCodeNode;
}
- if (methodCodeNode == null && methodNode is PrecodeMethodImport PrecodeMethodImport)
+ if (methodCodeNode == null && methodNode is PrecodeMethodImport precodeMethodImport)
{
- methodCodeNode = PrecodeMethodImport.MethodCodeNode;
+ methodCodeNode = precodeMethodImport.MethodCodeNode;
}
if (methodCodeNode != null && !methodCodeNode.IsEmpty)
@@ -515,10 +492,9 @@ public MethodFixupSignature MethodSignature(
ReadyToRunFixupKind fixupKind,
MethodWithToken method,
bool isUnboxingStub,
- bool isInstantiatingStub,
- SignatureContext signatureContext)
+ bool isInstantiatingStub)
{
- TypeAndMethod key = new TypeAndMethod(method.ConstrainedType, method, isUnboxingStub, isInstantiatingStub, false, signatureContext);
+ TypeAndMethod key = new TypeAndMethod(method.ConstrainedType, method, isUnboxingStub, isInstantiatingStub, false);
return _methodSignatures.GetOrAdd(new MethodFixupKey(fixupKind, key));
}
@@ -526,19 +502,16 @@ private struct TypeFixupKey : IEquatable
{
public readonly ReadyToRunFixupKind FixupKind;
public readonly TypeDesc TypeDesc;
- public readonly SignatureContext SignatureContext;
- public TypeFixupKey(ReadyToRunFixupKind fixupKind, TypeDesc typeDesc, SignatureContext signatureContext)
+
+ public TypeFixupKey(ReadyToRunFixupKind fixupKind, TypeDesc typeDesc)
{
FixupKind = fixupKind;
TypeDesc = typeDesc;
- SignatureContext = signatureContext;
}
public bool Equals(TypeFixupKey other)
{
- return FixupKind == other.FixupKind
- && TypeDesc == other.TypeDesc
- && SignatureContext.Equals(other.SignatureContext);
+ return FixupKind == other.FixupKind && TypeDesc == other.TypeDesc;
}
public override bool Equals(object obj)
@@ -548,17 +521,15 @@ public override bool Equals(object obj)
public override int GetHashCode()
{
- return FixupKind.GetHashCode()
- ^ (31 * TypeDesc.GetHashCode())
- ^ (23 * SignatureContext.GetHashCode());
+ return FixupKind.GetHashCode() ^ (31 * TypeDesc.GetHashCode());
}
}
private NodeCache _typeSignatures;
- public TypeFixupSignature TypeSignature(ReadyToRunFixupKind fixupKind, TypeDesc typeDesc, SignatureContext signatureContext)
+ public TypeFixupSignature TypeSignature(ReadyToRunFixupKind fixupKind, TypeDesc typeDesc)
{
- TypeFixupKey fixupKey = new TypeFixupKey(fixupKind, typeDesc, signatureContext);
+ TypeFixupKey fixupKey = new TypeFixupKey(fixupKind, typeDesc);
return _typeSignatures.GetOrAdd(fixupKey);
}
@@ -580,19 +551,53 @@ public void AttachToDependencyGraph(DependencyAnalyzerBase graph)
Header.Add(Internal.Runtime.ReadyToRunSectionType.ExceptionInfo, exceptionInfoLookupTableNode, exceptionInfoLookupTableNode);
graph.AddRoot(exceptionInfoLookupTableNode, "ExceptionInfoLookupTable is always generated");
- MethodEntryPointTable = new MethodEntryPointTableNode(Target);
- Header.Add(Internal.Runtime.ReadyToRunSectionType.MethodDefEntryPoints, MethodEntryPointTable, MethodEntryPointTable);
-
- ManifestMetadataTable = new ManifestMetadataTableNode(InputModuleContext.GlobalContext, this);
+ ManifestMetadataTable = new ManifestMetadataTableNode(this);
Header.Add(Internal.Runtime.ReadyToRunSectionType.ManifestMetadata, ManifestMetadataTable, ManifestMetadataTable);
-
Resolver.SetModuleIndexLookup(ManifestMetadataTable.ModuleToIndex);
- InstanceEntryPointTable = new InstanceEntryPointTableNode(Target);
- Header.Add(Internal.Runtime.ReadyToRunSectionType.InstanceMethodEntryPoints, InstanceEntryPointTable, InstanceEntryPointTable);
+ AssemblyTableNode assemblyTable = null;
+
+ if (CompilationModuleGroup.CompilationModuleSet.Skip(1).Any())
+ {
+ assemblyTable = new AssemblyTableNode(Target);
+ Header.Add(Internal.Runtime.ReadyToRunSectionType.ComponentAssemblies, assemblyTable, assemblyTable);
+ }
+
+ // Generate per assembly header tables
+ int assemblyIndex = -1;
+ foreach (EcmaModule inputModule in CompilationModuleGroup.CompilationModuleSet)
+ {
+ assemblyIndex++;
+ HeaderNode tableHeader = Header;
+ if (assemblyTable != null)
+ {
+ AssemblyHeaderNode perAssemblyHeader = new AssemblyHeaderNode(Target, ReadyToRunFlags.READYTORUN_FLAG_Component, assemblyIndex);
+ assemblyTable.Add(perAssemblyHeader);
+ tableHeader = perAssemblyHeader;
+ }
+
+ MethodEntryPointTableNode methodEntryPointTable = new MethodEntryPointTableNode(inputModule, Target);
+ tableHeader.Add(Internal.Runtime.ReadyToRunSectionType.MethodDefEntryPoints, methodEntryPointTable, methodEntryPointTable);
+
+ TypesTableNode typesTable = new TypesTableNode(Target, inputModule);
+ tableHeader.Add(Internal.Runtime.ReadyToRunSectionType.AvailableTypes, typesTable, typesTable);
+
+ InliningInfoNode inliningInfoTable = new InliningInfoNode(Target, inputModule);
+ tableHeader.Add(Internal.Runtime.ReadyToRunSectionType.InliningInfo2, inliningInfoTable, inliningInfoTable);
+
+ // Core library attributes are checked FAR more often than other dlls
+ // attributes, so produce a highly efficient table for determining if they are
+ // present. Other assemblies *MAY* benefit from this feature, but it doesn't show
+ // as useful at this time.
+ if (inputModule == TypeSystemContext.SystemModule)
+ {
+ AttributePresenceFilterNode attributePresenceTable = new AttributePresenceFilterNode(inputModule);
+ Header.Add(Internal.Runtime.ReadyToRunSectionType.AttributePresence, attributePresenceTable, attributePresenceTable);
+ }
+ }
- TypesTable = new TypesTableNode(Target);
- Header.Add(Internal.Runtime.ReadyToRunSectionType.AvailableTypes, TypesTable, TypesTable);
+ InstanceEntryPointTable = new InstanceEntryPointTableNode(this);
+ Header.Add(Internal.Runtime.ReadyToRunSectionType.InstanceMethodEntryPoints, InstanceEntryPointTable, InstanceEntryPointTable);
ImportSectionsTable = new ImportSectionsTableNode(this);
Header.Add(Internal.Runtime.ReadyToRunSectionType.ImportSections, ImportSectionsTable, ImportSectionsTable.StartSymbol);
@@ -600,18 +605,6 @@ public void AttachToDependencyGraph(DependencyAnalyzerBase graph)
DebugInfoTable = new DebugInfoTableNode(Target);
Header.Add(Internal.Runtime.ReadyToRunSectionType.DebugInfo, DebugInfoTable, DebugInfoTable);
- InliningInfoTable = new InliningInfoNode(Target, InputModuleContext.GlobalContext);
- Header.Add(Internal.Runtime.ReadyToRunSectionType.InliningInfo2, InliningInfoTable, InliningInfoTable);
-
- // Core library attributes are checked FAR more often than other dlls
- // attributes, so produce a highly efficient table for determining if they are
- // present. Other assemblies *MAY* benefit from this feature, but it doesn't show
- // as useful at this time.
- if (this.AttributePresenceFilter != null)
- {
- Header.Add(Internal.Runtime.ReadyToRunSectionType.AttributePresence, AttributePresenceFilter, AttributePresenceFilter);
- }
-
EagerImports = new ImportSectionNode(
"EagerImports",
CorCompileImportType.CORCOMPILE_IMPORT_TYPE_UNKNOWN,
@@ -695,7 +688,10 @@ public void AttachToDependencyGraph(DependencyAnalyzerBase graph)
graph.AddRoot(PrecodeImports, "Precode helper imports are always generated");
graph.AddRoot(StringImports, "String imports are always generated");
graph.AddRoot(Header, "ReadyToRunHeader is always generated");
- graph.AddRoot(CopiedCorHeaderNode, "MSIL COR header is always generated");
+ if (!CompilationModuleGroup.IsCompositeBuildMode)
+ {
+ graph.AddRoot(CopiedCorHeaderNode, "MSIL COR header is always generated for single-file R2R files");
+ }
graph.AddRoot(DebugDirectoryNode, "Debug Directory will always contain at least one entry");
if (Win32ResourcesNode != null)
@@ -738,22 +734,19 @@ struct DynamicHelperCellKey : IEquatable
public readonly MethodWithToken Method;
public readonly bool IsUnboxingStub;
public readonly bool IsInstantiatingStub;
- public readonly SignatureContext SignatureContext;
- public DynamicHelperCellKey(MethodWithToken method, bool isUnboxingStub, bool isInstantiatingStub, SignatureContext signatureContext)
+ public DynamicHelperCellKey(MethodWithToken method, bool isUnboxingStub, bool isInstantiatingStub)
{
Method = method;
IsUnboxingStub = isUnboxingStub;
IsInstantiatingStub = isInstantiatingStub;
- SignatureContext = signatureContext;
}
public bool Equals(DynamicHelperCellKey other)
{
return Method.Equals(other.Method)
&& IsUnboxingStub == other.IsUnboxingStub
- && IsInstantiatingStub == other.IsInstantiatingStub
- && SignatureContext.Equals(other.SignatureContext);
+ && IsInstantiatingStub == other.IsInstantiatingStub;
}
public override bool Equals(object obj)
@@ -765,16 +758,15 @@ public override int GetHashCode()
{
return Method.GetHashCode()
^ (IsUnboxingStub ? -0x80000000 : 0)
- ^ (IsInstantiatingStub ? -0x40000000 : 0)
- ^ (31 * SignatureContext.GetHashCode());
+ ^ (IsInstantiatingStub ? -0x40000000 : 0);
}
}
private NodeCache _dynamicHelperCellCache;
- public ISymbolNode DynamicHelperCell(MethodWithToken methodWithToken, bool isInstantiatingStub, SignatureContext signatureContext)
+ public ISymbolNode DynamicHelperCell(MethodWithToken methodWithToken, bool isInstantiatingStub)
{
- DynamicHelperCellKey key = new DynamicHelperCellKey(methodWithToken, isUnboxingStub: false, isInstantiatingStub, signatureContext);
+ DynamicHelperCellKey key = new DynamicHelperCellKey(methodWithToken, isUnboxingStub: false, isInstantiatingStub);
return _dynamicHelperCellCache.GetOrAdd(key);
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunSymbolNodeFactory.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunSymbolNodeFactory.cs
index 834e65351a8f41..735ada49e61917 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunSymbolNodeFactory.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunSymbolNodeFactory.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -47,36 +47,36 @@ public ReadyToRunSymbolNodeFactory(NodeFactory codegenNodeFactory)
private void CreateNodeCaches()
{
- _importStrings = new NodeCache(key =>
+ _importStrings = new NodeCache(key =>
{
- return new StringImport(_codegenNodeFactory.StringImports, key.ModuleToken, key.SignatureContext);
+ return new StringImport(_codegenNodeFactory.StringImports, key);
});
_r2rHelpers = new NodeCache(CreateReadyToRunHelper);
- _fieldAddressCache = new NodeCache(key =>
+ _fieldAddressCache = new NodeCache(key =>
{
return new DelayLoadHelperImport(
_codegenNodeFactory,
_codegenNodeFactory.HelperImports,
ReadyToRunHelper.DelayLoad_Helper,
- new FieldFixupSignature(ReadyToRunFixupKind.FieldAddress, key.Field, key.SignatureContext)
+ new FieldFixupSignature(ReadyToRunFixupKind.FieldAddress, key)
);
});
- _fieldOffsetCache = new NodeCache(key =>
+ _fieldOffsetCache = new NodeCache(key =>
{
return new PrecodeHelperImport(
_codegenNodeFactory,
- new FieldFixupSignature(ReadyToRunFixupKind.FieldOffset, key.Field, key.SignatureContext)
+ new FieldFixupSignature(ReadyToRunFixupKind.FieldOffset, key)
);
});
- _fieldBaseOffsetCache = new NodeCache(key =>
+ _fieldBaseOffsetCache = new NodeCache(key =>
{
return new PrecodeHelperImport(
_codegenNodeFactory,
- _codegenNodeFactory.TypeSignature(ReadyToRunFixupKind.FieldBaseOffset, key.Type, key.SignatureContext)
+ _codegenNodeFactory.TypeSignature(ReadyToRunFixupKind.FieldBaseOffset, key)
);
});
@@ -91,26 +91,23 @@ private void CreateNodeCaches()
useInstantiatingStub: false,
_codegenNodeFactory.MethodSignature(ReadyToRunFixupKind.VirtualEntry,
cellKey.Method,
- cellKey.IsUnboxingStub, isInstantiatingStub: false, cellKey.SignatureContext),
- cellKey.SignatureContext,
+ cellKey.IsUnboxingStub, isInstantiatingStub: false),
cellKey.CallSite);
});
_delegateCtors = new NodeCache(ctorKey =>
{
- SignatureContext signatureContext = ctorKey.SignatureContext;
IMethodNode targetMethodNode = _codegenNodeFactory.MethodEntrypoint(
ctorKey.Method,
isUnboxingStub: false,
isInstantiatingStub: ctorKey.Method.Method.HasInstantiation,
- isPrecodeImportRequired: false,
- signatureContext: signatureContext);
+ isPrecodeImportRequired: false);
return new DelayLoadHelperImport(
_codegenNodeFactory,
_codegenNodeFactory.HelperImports,
ReadyToRunHelper.DelayLoad_Helper_ObjObj,
- new DelegateCtorSignature(ctorKey.Type, targetMethodNode, ctorKey.Method.Token, signatureContext));
+ new DelegateCtorSignature(ctorKey.Type, targetMethodNode, ctorKey.Method.Token));
});
_genericLookupHelpers = new NodeCache(key =>
@@ -125,8 +122,7 @@ private void CreateNodeCaches()
key.TypeArgument,
key.MethodArgument,
key.FieldArgument,
- key.MethodContext,
- key.SignatureContext));
+ key.MethodContext));
});
_pInvokeTargetNodes = new NodeCache(key =>
@@ -136,65 +132,32 @@ private void CreateNodeCaches()
_codegenNodeFactory.MethodSignature(
key.IsIndirect ? ReadyToRunFixupKind.IndirectPInvokeTarget : ReadyToRunFixupKind.PInvokeTarget,
key.MethodWithToken,
- signatureContext: key.SignatureContext,
isUnboxingStub: false,
isInstantiatingStub: false));
});
}
- private struct ModuleTokenAndSignatureContext : IEquatable
- {
- public readonly ModuleToken ModuleToken;
- public readonly SignatureContext SignatureContext;
-
- public ModuleTokenAndSignatureContext(ModuleToken moduleToken, SignatureContext signatureContext)
- {
- ModuleToken = moduleToken;
- SignatureContext = signatureContext;
- }
-
- public bool Equals(ModuleTokenAndSignatureContext other)
- {
- return ModuleToken.Equals(other.ModuleToken)
- && SignatureContext.Equals(other.SignatureContext);
- }
-
- public override bool Equals(object obj)
- {
- return obj is ModuleTokenAndSignatureContext other && Equals(other);
- }
-
- public override int GetHashCode()
- {
- return ModuleToken.GetHashCode() ^ (SignatureContext.GetHashCode() * 31);
- }
- }
-
- private NodeCache _importStrings;
+ private NodeCache _importStrings;
- public ISymbolNode StringLiteral(ModuleToken moduleToken, SignatureContext signatureContext)
+ public ISymbolNode StringLiteral(ModuleToken moduleToken)
{
- return _importStrings.GetOrAdd(new ModuleTokenAndSignatureContext(moduleToken, signatureContext));
+ return _importStrings.GetOrAdd(moduleToken);
}
private struct ReadyToRunHelperKey
{
public readonly ReadyToRunHelperId Id;
public readonly object Target;
- public readonly SignatureContext SignatureContext;
- public ReadyToRunHelperKey(ReadyToRunHelperId id, object target, SignatureContext signatureContext)
+ public ReadyToRunHelperKey(ReadyToRunHelperId id, object target)
{
Id = id;
Target = target;
- SignatureContext = signatureContext;
}
public bool Equals(ReadyToRunHelperKey other)
{
- return Id == other.Id
- && Target.Equals(other.Target)
- && SignatureContext.Equals(other.SignatureContext);
+ return Id == other.Id && Target.Equals(other.Target);
}
public override bool Equals(object obj)
@@ -204,9 +167,7 @@ public override bool Equals(object obj)
public override int GetHashCode()
{
- return Id.GetHashCode()
- ^ (Target.GetHashCode() * 23)
- ^ (SignatureContext.GetHashCode() * 31);
+ return Id.GetHashCode() ^ (Target.GetHashCode() * 23);
}
}
@@ -217,137 +178,137 @@ private ISymbolNode CreateReadyToRunHelper(ReadyToRunHelperKey key)
switch (key.Id)
{
case ReadyToRunHelperId.NewHelper:
- return CreateNewHelper((TypeDesc)key.Target, key.SignatureContext);
+ return CreateNewHelper((TypeDesc)key.Target);
case ReadyToRunHelperId.NewArr1:
- return CreateNewArrayHelper((ArrayType)key.Target, key.SignatureContext);
+ return CreateNewArrayHelper((ArrayType)key.Target);
case ReadyToRunHelperId.GetGCStaticBase:
- return CreateGCStaticBaseHelper((TypeDesc)key.Target, key.SignatureContext);
+ return CreateGCStaticBaseHelper((TypeDesc)key.Target);
case ReadyToRunHelperId.GetNonGCStaticBase:
- return CreateNonGCStaticBaseHelper((TypeDesc)key.Target, key.SignatureContext);
+ return CreateNonGCStaticBaseHelper((TypeDesc)key.Target);
case ReadyToRunHelperId.GetThreadStaticBase:
- return CreateThreadGcStaticBaseHelper((TypeDesc)key.Target, key.SignatureContext);
+ return CreateThreadGcStaticBaseHelper((TypeDesc)key.Target);
case ReadyToRunHelperId.GetThreadNonGcStaticBase:
- return CreateThreadNonGcStaticBaseHelper((TypeDesc)key.Target, key.SignatureContext);
+ return CreateThreadNonGcStaticBaseHelper((TypeDesc)key.Target);
case ReadyToRunHelperId.IsInstanceOf:
- return CreateIsInstanceOfHelper((TypeDesc)key.Target, key.SignatureContext);
+ return CreateIsInstanceOfHelper((TypeDesc)key.Target);
case ReadyToRunHelperId.CastClass:
- return CreateCastClassHelper((TypeDesc)key.Target, key.SignatureContext);
+ return CreateCastClassHelper((TypeDesc)key.Target);
case ReadyToRunHelperId.TypeHandle:
- return CreateTypeHandleHelper((TypeDesc)key.Target, key.SignatureContext);
+ return CreateTypeHandleHelper((TypeDesc)key.Target);
case ReadyToRunHelperId.MethodHandle:
- return CreateMethodHandleHelper((MethodWithToken)key.Target, key.SignatureContext);
+ return CreateMethodHandleHelper((MethodWithToken)key.Target);
case ReadyToRunHelperId.FieldHandle:
- return CreateFieldHandleHelper((FieldDesc)key.Target, key.SignatureContext);
+ return CreateFieldHandleHelper((FieldDesc)key.Target);
case ReadyToRunHelperId.CctorTrigger:
- return CreateCctorTrigger((TypeDesc)key.Target, key.SignatureContext);
+ return CreateCctorTrigger((TypeDesc)key.Target);
case ReadyToRunHelperId.TypeDictionary:
- return CreateTypeDictionary((TypeDesc)key.Target, key.SignatureContext);
+ return CreateTypeDictionary((TypeDesc)key.Target);
case ReadyToRunHelperId.MethodDictionary:
- return CreateMethodDictionary((MethodWithToken)key.Target, key.SignatureContext);
+ return CreateMethodDictionary((MethodWithToken)key.Target);
default:
throw new NotImplementedException(key.Id.ToString());
}
}
- public ISymbolNode CreateReadyToRunHelper(ReadyToRunHelperId id, object target, SignatureContext signatureContext)
+ public ISymbolNode CreateReadyToRunHelper(ReadyToRunHelperId id, object target)
{
- return _r2rHelpers.GetOrAdd(new ReadyToRunHelperKey(id, target, signatureContext));
+ return _r2rHelpers.GetOrAdd(new ReadyToRunHelperKey(id, target));
}
- private ISymbolNode CreateNewHelper(TypeDesc type, SignatureContext signatureContext)
+ private ISymbolNode CreateNewHelper(TypeDesc type)
{
return new DelayLoadHelperImport(
_codegenNodeFactory,
_codegenNodeFactory.HelperImports,
ReadyToRunHelper.DelayLoad_Helper,
- new NewObjectFixupSignature(type, signatureContext));
+ new NewObjectFixupSignature(type));
}
- private ISymbolNode CreateNewArrayHelper(ArrayType type, SignatureContext signatureContext)
+ private ISymbolNode CreateNewArrayHelper(ArrayType type)
{
return new DelayLoadHelperImport(
_codegenNodeFactory,
_codegenNodeFactory.HelperImports,
ReadyToRunHelper.DelayLoad_Helper,
- new NewArrayFixupSignature(type, signatureContext));
+ new NewArrayFixupSignature(type));
}
- private ISymbolNode CreateGCStaticBaseHelper(TypeDesc type, SignatureContext signatureContext)
+ private ISymbolNode CreateGCStaticBaseHelper(TypeDesc type)
{
return new DelayLoadHelperImport(
_codegenNodeFactory,
_codegenNodeFactory.HelperImports,
ReadyToRunHelper.DelayLoad_Helper,
- _codegenNodeFactory.TypeSignature(ReadyToRunFixupKind.StaticBaseGC, type, signatureContext));
+ _codegenNodeFactory.TypeSignature(ReadyToRunFixupKind.StaticBaseGC, type));
}
- private ISymbolNode CreateNonGCStaticBaseHelper(TypeDesc type, SignatureContext signatureContext)
+ private ISymbolNode CreateNonGCStaticBaseHelper(TypeDesc type)
{
return new DelayLoadHelperImport(
_codegenNodeFactory,
_codegenNodeFactory.HelperImports,
ReadyToRunHelper.DelayLoad_Helper,
- _codegenNodeFactory.TypeSignature(ReadyToRunFixupKind.StaticBaseNonGC, type, signatureContext));
+ _codegenNodeFactory.TypeSignature(ReadyToRunFixupKind.StaticBaseNonGC, type));
}
- private ISymbolNode CreateThreadGcStaticBaseHelper(TypeDesc type, SignatureContext signatureContext)
+ private ISymbolNode CreateThreadGcStaticBaseHelper(TypeDesc type)
{
return new DelayLoadHelperImport(
_codegenNodeFactory,
_codegenNodeFactory.HelperImports,
ReadyToRunHelper.DelayLoad_Helper,
- _codegenNodeFactory.TypeSignature(ReadyToRunFixupKind.ThreadStaticBaseGC, type, signatureContext));
+ _codegenNodeFactory.TypeSignature(ReadyToRunFixupKind.ThreadStaticBaseGC, type));
}
- private ISymbolNode CreateThreadNonGcStaticBaseHelper(TypeDesc type, SignatureContext signatureContext)
+ private ISymbolNode CreateThreadNonGcStaticBaseHelper(TypeDesc type)
{
return new DelayLoadHelperImport(
_codegenNodeFactory,
_codegenNodeFactory.HelperImports,
ReadyToRunHelper.DelayLoad_Helper,
- _codegenNodeFactory.TypeSignature(ReadyToRunFixupKind.ThreadStaticBaseNonGC, type, signatureContext));
+ _codegenNodeFactory.TypeSignature(ReadyToRunFixupKind.ThreadStaticBaseNonGC, type));
}
- private ISymbolNode CreateIsInstanceOfHelper(TypeDesc type, SignatureContext signatureContext)
+ private ISymbolNode CreateIsInstanceOfHelper(TypeDesc type)
{
return new DelayLoadHelperImport(
_codegenNodeFactory,
_codegenNodeFactory.HelperImports,
ReadyToRunHelper.DelayLoad_Helper_Obj,
- _codegenNodeFactory.TypeSignature(ReadyToRunFixupKind.IsInstanceOf, type, signatureContext));
+ _codegenNodeFactory.TypeSignature(ReadyToRunFixupKind.IsInstanceOf, type));
}
- private ISymbolNode CreateCastClassHelper(TypeDesc type, SignatureContext signatureContext)
+ private ISymbolNode CreateCastClassHelper(TypeDesc type)
{
return new DelayLoadHelperImport(
_codegenNodeFactory,
_codegenNodeFactory.HelperImports,
ReadyToRunHelper.DelayLoad_Helper_Obj,
- _codegenNodeFactory.TypeSignature(ReadyToRunFixupKind.ChkCast, type, signatureContext));
+ _codegenNodeFactory.TypeSignature(ReadyToRunFixupKind.ChkCast, type));
}
- private ISymbolNode CreateTypeHandleHelper(TypeDesc type, SignatureContext signatureContext)
+ private ISymbolNode CreateTypeHandleHelper(TypeDesc type)
{
return new PrecodeHelperImport(
_codegenNodeFactory,
- _codegenNodeFactory.TypeSignature(ReadyToRunFixupKind.TypeHandle, type, signatureContext));
+ _codegenNodeFactory.TypeSignature(ReadyToRunFixupKind.TypeHandle, type));
}
- private ISymbolNode CreateMethodHandleHelper(MethodWithToken method, SignatureContext signatureContext)
+ private ISymbolNode CreateMethodHandleHelper(MethodWithToken method)
{
bool useUnboxingStub = method.Method.IsUnboxingThunk();
if (useUnboxingStub)
@@ -363,35 +324,34 @@ private ISymbolNode CreateMethodHandleHelper(MethodWithToken method, SignatureCo
ReadyToRunFixupKind.MethodHandle,
method,
isUnboxingStub: useUnboxingStub,
- isInstantiatingStub: useInstantiatingStub,
- signatureContext));
+ isInstantiatingStub: useInstantiatingStub));
}
- private ISymbolNode CreateFieldHandleHelper(FieldDesc field, SignatureContext signatureContext)
+ private ISymbolNode CreateFieldHandleHelper(FieldDesc field)
{
return new PrecodeHelperImport(
_codegenNodeFactory,
- new FieldFixupSignature(ReadyToRunFixupKind.FieldHandle, field, signatureContext));
+ new FieldFixupSignature(ReadyToRunFixupKind.FieldHandle, field));
}
- private ISymbolNode CreateCctorTrigger(TypeDesc type, SignatureContext signatureContext)
+ private ISymbolNode CreateCctorTrigger(TypeDesc type)
{
return new DelayLoadHelperImport(
_codegenNodeFactory,
_codegenNodeFactory.HelperImports,
ReadyToRunHelper.DelayLoad_Helper,
- _codegenNodeFactory.TypeSignature(ReadyToRunFixupKind.CctorTrigger, type, signatureContext));
+ _codegenNodeFactory.TypeSignature(ReadyToRunFixupKind.CctorTrigger, type));
}
- private ISymbolNode CreateTypeDictionary(TypeDesc type, SignatureContext signatureContext)
+ private ISymbolNode CreateTypeDictionary(TypeDesc type)
{
return new PrecodeHelperImport(
_codegenNodeFactory,
- _codegenNodeFactory.TypeSignature(ReadyToRunFixupKind.TypeDictionary, type, signatureContext)
+ _codegenNodeFactory.TypeSignature(ReadyToRunFixupKind.TypeDictionary, type)
);
}
- private ISymbolNode CreateMethodDictionary(MethodWithToken method, SignatureContext signatureContext)
+ private ISymbolNode CreateMethodDictionary(MethodWithToken method)
{
return new PrecodeHelperImport(
_codegenNodeFactory,
@@ -399,106 +359,48 @@ private ISymbolNode CreateMethodDictionary(MethodWithToken method, SignatureCont
ReadyToRunFixupKind.MethodDictionary,
method,
isUnboxingStub: false,
- isInstantiatingStub: true,
- signatureContext));
+ isInstantiatingStub: true));
}
- private struct FieldAndSignatureContext : IEquatable
- {
- public readonly FieldDesc Field;
- public readonly SignatureContext SignatureContext;
+ private NodeCache _fieldAddressCache;
- public FieldAndSignatureContext(FieldDesc fieldDesc, SignatureContext signatureContext)
- {
- Field = fieldDesc;
- SignatureContext = signatureContext;
- }
-
- public bool Equals(FieldAndSignatureContext other)
- {
- return Field.Equals(other.Field) &&
- SignatureContext.Equals(other.SignatureContext);
- }
-
- public override bool Equals(object obj)
- {
- return obj is FieldAndSignatureContext other && Equals(other);
- }
-
- public override int GetHashCode()
- {
- return Field.GetHashCode() ^ (SignatureContext.GetHashCode() * 31);
- }
- }
-
- private NodeCache _fieldAddressCache;
-
- public ISymbolNode FieldAddress(FieldDesc fieldDesc, SignatureContext signatureContext)
+ public ISymbolNode FieldAddress(FieldDesc fieldDesc)
{
- return _fieldAddressCache.GetOrAdd(new FieldAndSignatureContext(fieldDesc, signatureContext));
+ return _fieldAddressCache.GetOrAdd(fieldDesc);
}
- private NodeCache _fieldOffsetCache;
-
- public ISymbolNode FieldOffset(FieldDesc fieldDesc, SignatureContext signatureContext)
- {
- return _fieldOffsetCache.GetOrAdd(new FieldAndSignatureContext(fieldDesc, signatureContext));
- }
+ private NodeCache _fieldOffsetCache;
- private struct TypeAndSignatureContext : IEquatable
+ public ISymbolNode FieldOffset(FieldDesc fieldDesc)
{
- public readonly TypeDesc Type;
- public readonly SignatureContext SignatureContext;
-
- public TypeAndSignatureContext(TypeDesc typeDesc, SignatureContext signatureContext)
- {
- Type = typeDesc;
- SignatureContext = signatureContext;
- }
-
- public bool Equals(TypeAndSignatureContext other)
- {
- return Type.Equals(other.Type) &&
- SignatureContext.Equals(other.SignatureContext);
- }
-
- public override bool Equals(object obj)
- {
- return obj is FieldAndSignatureContext other && Equals(other);
- }
-
- public override int GetHashCode()
- {
- return Type.GetHashCode() ^ (SignatureContext.GetHashCode() * 31);
- }
+ return _fieldOffsetCache.GetOrAdd(fieldDesc);
}
- private NodeCache _fieldBaseOffsetCache;
+ private NodeCache _fieldBaseOffsetCache;
- public ISymbolNode FieldBaseOffset(TypeDesc typeDesc, SignatureContext signatureContext)
+ public ISymbolNode FieldBaseOffset(TypeDesc typeDesc)
{
- return _fieldBaseOffsetCache.GetOrAdd(new TypeAndSignatureContext(typeDesc, signatureContext));
+ return _fieldBaseOffsetCache.GetOrAdd(typeDesc);
}
private NodeCache _interfaceDispatchCells = new NodeCache();
- public ISymbolNode InterfaceDispatchCell(MethodWithToken method, SignatureContext signatureContext, bool isUnboxingStub, string callSite)
+ public ISymbolNode InterfaceDispatchCell(MethodWithToken method, bool isUnboxingStub, string callSite)
{
- MethodAndCallSite cellKey = new MethodAndCallSite(method, isUnboxingStub, callSite, signatureContext);
+ MethodAndCallSite cellKey = new MethodAndCallSite(method, isUnboxingStub, callSite);
return _interfaceDispatchCells.GetOrAdd(cellKey);
}
private NodeCache _delegateCtors = new NodeCache();
- public ISymbolNode DelegateCtor(TypeDesc delegateType, MethodWithToken method, SignatureContext signatureContext)
+ public ISymbolNode DelegateCtor(TypeDesc delegateType, MethodWithToken method)
{
TypeAndMethod ctorKey = new TypeAndMethod(
delegateType,
method,
isUnboxingStub: false,
isInstantiatingStub: false,
- isPrecodeImportRequired: false,
- signatureContext);
+ isPrecodeImportRequired: false);
return _delegateCtors.GetOrAdd(ctorKey);
}
@@ -507,22 +409,17 @@ struct MethodAndCallSite : IEquatable
public readonly MethodWithToken Method;
public readonly bool IsUnboxingStub;
public readonly string CallSite;
- public readonly SignatureContext SignatureContext;
- public MethodAndCallSite(MethodWithToken method, bool isUnboxingStub, string callSite, SignatureContext signatureContext)
+ public MethodAndCallSite(MethodWithToken method, bool isUnboxingStub, string callSite)
{
CallSite = callSite;
IsUnboxingStub = isUnboxingStub;
Method = method;
- SignatureContext = signatureContext;
}
public bool Equals(MethodAndCallSite other)
{
- return CallSite == other.CallSite
- && Method.Equals(other.Method)
- && IsUnboxingStub == other.IsUnboxingStub
- && SignatureContext.Equals(other.SignatureContext);
+ return CallSite == other.CallSite && Method.Equals(other.Method) && IsUnboxingStub == other.IsUnboxingStub;
}
public override bool Equals(object obj)
@@ -532,10 +429,9 @@ public override bool Equals(object obj)
public override int GetHashCode()
{
- return (CallSite != null ? CallSite.GetHashCode() : 0)
+ return (CallSite != null ? CallSite.GetHashCode() : 0)
^ unchecked(31 * Method.GetHashCode())
- ^ (IsUnboxingStub ? -0x80000000 : 0)
- ^ (23 * SignatureContext.GetHashCode());
+ ^ (IsUnboxingStub ? -0x80000000 : 0);
}
}
@@ -547,7 +443,6 @@ private struct GenericLookupKey : IEquatable
public readonly MethodWithToken MethodArgument;
public readonly FieldDesc FieldArgument;
public readonly GenericContext MethodContext;
- public readonly SignatureContext SignatureContext;
public GenericLookupKey(
CORINFO_RUNTIME_LOOKUP_KIND lookupKind,
@@ -555,8 +450,7 @@ public GenericLookupKey(
TypeDesc typeArgument,
MethodWithToken methodArgument,
FieldDesc fieldArgument,
- GenericContext methodContext,
- SignatureContext signatureContext)
+ GenericContext methodContext)
{
LookupKind = lookupKind;
FixupKind = fixupKind;
@@ -564,7 +458,6 @@ public GenericLookupKey(
MethodArgument = methodArgument;
FieldArgument = fieldArgument;
MethodContext = methodContext;
- SignatureContext = signatureContext;
}
public bool Equals(GenericLookupKey other)
@@ -599,8 +492,7 @@ public ISymbolNode GenericLookupHelper(
CORINFO_RUNTIME_LOOKUP_KIND runtimeLookupKind,
ReadyToRunHelperId helperId,
object helperArgument,
- GenericContext methodContext,
- SignatureContext signatureContext)
+ GenericContext methodContext)
{
switch (helperId)
{
@@ -609,56 +501,49 @@ public ISymbolNode GenericLookupHelper(
runtimeLookupKind,
ReadyToRunFixupKind.TypeHandle,
helperArgument,
- methodContext,
- signatureContext);
+ methodContext);
case ReadyToRunHelperId.MethodHandle:
return GenericLookupMethodHelper(
runtimeLookupKind,
ReadyToRunFixupKind.MethodHandle,
(MethodWithToken)helperArgument,
- methodContext,
- signatureContext);
+ methodContext);
case ReadyToRunHelperId.MethodEntry:
return GenericLookupMethodHelper(
runtimeLookupKind,
ReadyToRunFixupKind.MethodEntry,
(MethodWithToken)helperArgument,
- methodContext,
- signatureContext);
+ methodContext);
case ReadyToRunHelperId.MethodDictionary:
return GenericLookupMethodHelper(
runtimeLookupKind,
ReadyToRunFixupKind.MethodHandle,
(MethodWithToken)helperArgument,
- methodContext,
- signatureContext);
+ methodContext);
case ReadyToRunHelperId.TypeDictionary:
return GenericLookupTypeHelper(
runtimeLookupKind,
ReadyToRunFixupKind.TypeDictionary,
(TypeDesc)helperArgument,
- methodContext,
- signatureContext);
+ methodContext);
case ReadyToRunHelperId.VirtualDispatchCell:
return GenericLookupMethodHelper(
runtimeLookupKind,
ReadyToRunFixupKind.VirtualEntry,
(MethodWithToken)helperArgument,
- methodContext,
- signatureContext);
+ methodContext);
case ReadyToRunHelperId.FieldHandle:
return GenericLookupFieldHelper(
runtimeLookupKind,
ReadyToRunFixupKind.FieldHandle,
(FieldDesc)helperArgument,
- methodContext,
- signatureContext);
+ methodContext);
default:
throw new NotImplementedException(helperId.ToString());
@@ -669,8 +554,7 @@ private ISymbolNode GenericLookupTypeHelper(
CORINFO_RUNTIME_LOOKUP_KIND runtimeLookupKind,
ReadyToRunFixupKind fixupKind,
object helperArgument,
- GenericContext methodContext,
- SignatureContext signatureContext)
+ GenericContext methodContext)
{
TypeDesc typeArgument;
if (helperArgument is MethodWithToken methodWithToken)
@@ -686,7 +570,7 @@ private ISymbolNode GenericLookupTypeHelper(
typeArgument = (TypeDesc)helperArgument;
}
- GenericLookupKey key = new GenericLookupKey(runtimeLookupKind, fixupKind, typeArgument, methodArgument: null, fieldArgument: null, methodContext, signatureContext);
+ GenericLookupKey key = new GenericLookupKey(runtimeLookupKind, fixupKind, typeArgument, methodArgument: null, fieldArgument: null, methodContext);
return _genericLookupHelpers.GetOrAdd(key);
}
@@ -694,10 +578,9 @@ private ISymbolNode GenericLookupFieldHelper(
CORINFO_RUNTIME_LOOKUP_KIND runtimeLookupKind,
ReadyToRunFixupKind fixupKind,
FieldDesc fieldArgument,
- GenericContext methodContext,
- SignatureContext signatureContext)
+ GenericContext methodContext)
{
- GenericLookupKey key = new GenericLookupKey(runtimeLookupKind, fixupKind, typeArgument: null, methodArgument: null, fieldArgument: fieldArgument, methodContext, signatureContext);
+ GenericLookupKey key = new GenericLookupKey(runtimeLookupKind, fixupKind, typeArgument: null, methodArgument: null, fieldArgument: fieldArgument, methodContext);
return _genericLookupHelpers.GetOrAdd(key);
}
@@ -705,31 +588,26 @@ private ISymbolNode GenericLookupMethodHelper(
CORINFO_RUNTIME_LOOKUP_KIND runtimeLookupKind,
ReadyToRunFixupKind fixupKind,
MethodWithToken methodArgument,
- GenericContext methodContext,
- SignatureContext signatureContext)
+ GenericContext methodContext)
{
- GenericLookupKey key = new GenericLookupKey(runtimeLookupKind, fixupKind, typeArgument: null, methodArgument, fieldArgument: null, methodContext, signatureContext);
+ GenericLookupKey key = new GenericLookupKey(runtimeLookupKind, fixupKind, typeArgument: null, methodArgument, fieldArgument: null, methodContext);
return _genericLookupHelpers.GetOrAdd(key);
}
private struct PInvokeTargetKey : IEquatable
{
public readonly MethodWithToken MethodWithToken;
- public readonly SignatureContext SignatureContext;
public readonly bool IsIndirect;
- public PInvokeTargetKey(MethodWithToken methodWithToken, SignatureContext signatureContext, bool isIndirect)
+ public PInvokeTargetKey(MethodWithToken methodWithToken, bool isIndirect)
{
MethodWithToken = methodWithToken;
- SignatureContext = signatureContext;
IsIndirect = isIndirect;
}
public bool Equals(PInvokeTargetKey other)
{
- return IsIndirect.Equals(other.IsIndirect)
- && MethodWithToken.Equals(other.MethodWithToken)
- && SignatureContext.Equals(other.SignatureContext);
+ return IsIndirect.Equals(other.IsIndirect) && MethodWithToken.Equals(other.MethodWithToken);
}
public override bool Equals(object obj)
@@ -739,22 +617,20 @@ public override bool Equals(object obj)
public override int GetHashCode()
{
- return IsIndirect.GetHashCode()
- ^ (MethodWithToken.GetHashCode() * 23)
- ^ (SignatureContext.GetHashCode() * 31);
+ return IsIndirect.GetHashCode() ^ (MethodWithToken.GetHashCode() * 23);
}
}
private NodeCache _pInvokeTargetNodes = new NodeCache();
- public ISymbolNode GetIndirectPInvokeTargetNode(MethodWithToken methodWithToken, SignatureContext signatureContext)
+ public ISymbolNode GetIndirectPInvokeTargetNode(MethodWithToken methodWithToken)
{
- return _pInvokeTargetNodes.GetOrAdd(new PInvokeTargetKey(methodWithToken, signatureContext, isIndirect: true));
+ return _pInvokeTargetNodes.GetOrAdd(new PInvokeTargetKey(methodWithToken, isIndirect: true));
}
- public ISymbolNode GetPInvokeTargetNode(MethodWithToken methodWithToken, SignatureContext signatureContext)
+ public ISymbolNode GetPInvokeTargetNode(MethodWithToken methodWithToken)
{
- return _pInvokeTargetNodes.GetOrAdd(new PInvokeTargetKey(methodWithToken, signatureContext, isIndirect: false));
+ return _pInvokeTargetNodes.GetOrAdd(new PInvokeTargetKey(methodWithToken, isIndirect: false));
}
}
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/TypeAndMethod.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/TypeAndMethod.cs
index b03c7d547773d1..871e5a0ea78bf2 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/TypeAndMethod.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/TypeAndMethod.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -18,16 +18,14 @@ internal struct TypeAndMethod : IEquatable
public readonly bool IsUnboxingStub;
public readonly bool IsInstantiatingStub;
public readonly bool IsPrecodeImportRequired;
- public readonly SignatureContext SignatureContext;
- public TypeAndMethod(TypeDesc type, MethodWithToken method, bool isUnboxingStub, bool isInstantiatingStub, bool isPrecodeImportRequired, SignatureContext signatureContext)
+ public TypeAndMethod(TypeDesc type, MethodWithToken method, bool isUnboxingStub, bool isInstantiatingStub, bool isPrecodeImportRequired)
{
Type = type;
Method = method;
IsUnboxingStub = isUnboxingStub;
IsInstantiatingStub = isInstantiatingStub;
IsPrecodeImportRequired = isPrecodeImportRequired;
- SignatureContext = signatureContext;
}
public bool Equals(TypeAndMethod other)
@@ -36,8 +34,7 @@ public bool Equals(TypeAndMethod other)
Method.Equals(other.Method) &&
IsUnboxingStub == other.IsUnboxingStub &&
IsInstantiatingStub == other.IsInstantiatingStub &&
- IsPrecodeImportRequired == other.IsPrecodeImportRequired &&
- SignatureContext.Equals(other.SignatureContext);
+ IsPrecodeImportRequired == other.IsPrecodeImportRequired;
}
public override bool Equals(object obj)
@@ -47,12 +44,11 @@ public override bool Equals(object obj)
public override int GetHashCode()
{
- return (Type?.GetHashCode() ?? 0) ^
- unchecked(Method.GetHashCode() * 31) ^
- (IsUnboxingStub ? -0x80000000 : 0) ^
+ return (Type?.GetHashCode() ?? 0) ^
+ unchecked(Method.GetHashCode() * 31) ^
+ (IsUnboxingStub ? -0x80000000 : 0) ^
(IsInstantiatingStub ? 0x40000000 : 0) ^
- (IsPrecodeImportRequired ? 0x20000000 : 0) ^
- (SignatureContext.GetHashCode() * 23);
+ (IsPrecodeImportRequired ? 0x20000000 : 0);
}
}
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/IRootingServiceProvider.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/IRootingServiceProvider.cs
index deb14d0684e485..e6bfd1ff9d6a87 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/IRootingServiceProvider.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/IRootingServiceProvider.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/MethodExtensions.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/MethodExtensions.cs
index 340a40b82ad598..e2d4aa7cbfa2b2 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/MethodExtensions.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/MethodExtensions.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/PerfEventSource.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/PerfEventSource.cs
index fa9ca6c8e0373a..7f981a72cda568 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/PerfEventSource.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/PerfEventSource.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ProfileData.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ProfileData.cs
index f0e8cb591fc156..3c41e6b5053d19 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ProfileData.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ProfileData.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs
index 663c536d063c12..03be7bab7e8ea0 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -18,6 +18,8 @@
using ILCompiler.DependencyAnalysis;
using ILCompiler.DependencyAnalysis.ReadyToRun;
using ILCompiler.DependencyAnalysisFramework;
+using Internal.TypeSystem.Ecma;
+using System.Linq;
namespace ILCompiler
{
@@ -187,9 +189,9 @@ public sealed class ReadyToRunCodegenCompilation : Compilation
private readonly ConditionalWeakTable _corInfoImpls;
///
- /// Name of the compilation input MSIL file.
+ /// Input MSIL file names.
///
- private readonly string _inputFilePath;
+ private readonly IEnumerable _inputFiles;
private bool _resilient;
@@ -206,40 +208,86 @@ internal ReadyToRunCodegenCompilation(
ILProvider ilProvider,
Logger logger,
DevirtualizationManager devirtualizationManager,
- string inputFilePath,
- IEnumerable modulesBeingInstrumented,
+ IEnumerable inputFiles,
bool resilient,
bool generateMapFile,
int parallelism)
- : base(dependencyGraph, nodeFactory, roots, ilProvider, devirtualizationManager, modulesBeingInstrumented, logger)
+ : base(
+ dependencyGraph,
+ nodeFactory,
+ roots,
+ ilProvider,
+ devirtualizationManager,
+ modulesBeingInstrumented: nodeFactory.CompilationModuleGroup.CompilationModuleSet,
+ logger)
{
_resilient = resilient;
_parallelism = parallelism;
_generateMapFile = generateMapFile;
SymbolNodeFactory = new ReadyToRunSymbolNodeFactory(nodeFactory);
-
- _inputFilePath = inputFilePath;
-
_corInfoImpls = new ConditionalWeakTable();
+ _inputFiles = inputFiles;
}
public override void Compile(string outputFile)
{
- using (FileStream inputFile = File.OpenRead(_inputFilePath))
- {
- PEReader inputPeReader = new PEReader(inputFile);
+ _dependencyGraph.ComputeMarkedNodes();
+ var nodes = _dependencyGraph.MarkedNodeList;
- _dependencyGraph.ComputeMarkedNodes();
- var nodes = _dependencyGraph.MarkedNodeList;
+ using (PerfEventSource.StartStopEvents.EmittingEvents())
+ {
+ NodeFactory.SetMarkingComplete();
+ ReadyToRunObjectWriter.EmitObject(outputFile, componentModule: null, nodes, NodeFactory, _generateMapFile);
+ CompilationModuleGroup moduleGroup = _nodeFactory.CompilationModuleGroup;
- using (PerfEventSource.StartStopEvents.EmittingEvents())
+ if (moduleGroup.IsCompositeBuildMode)
{
- NodeFactory.SetMarkingComplete();
- ReadyToRunObjectWriter.EmitObject(inputPeReader, outputFile, nodes, NodeFactory, _generateMapFile);
+ // In composite mode with standalone MSIL we rewrite all input MSIL assemblies to the
+ // output folder, adding a format R2R header to them with forwarding information to
+ // the composite executable.
+ string outputDirectory = Path.GetDirectoryName(outputFile);
+ string ownerExecutableName = Path.GetFileName(outputFile);
+ foreach (string inputFile in _inputFiles)
+ {
+ string standaloneMsilOutputFile = Path.Combine(outputDirectory, Path.GetFileName(inputFile));
+ RewriteComponentFile(inputFile: inputFile, outputFile: standaloneMsilOutputFile, ownerExecutableName: ownerExecutableName);
+ }
}
}
}
+ private void RewriteComponentFile(string inputFile, string outputFile, string ownerExecutableName)
+ {
+ EcmaModule inputModule = NodeFactory.TypeSystemContext.GetModuleFromPath(inputFile);
+
+ CopiedCorHeaderNode copiedCorHeader = new CopiedCorHeaderNode(inputModule);
+ DebugDirectoryNode debugDirectory = new DebugDirectoryNode(inputModule);
+ NodeFactory componentFactory = new NodeFactory(
+ _nodeFactory.TypeSystemContext,
+ _nodeFactory.CompilationModuleGroup,
+ _nodeFactory.NameMangler,
+ copiedCorHeader,
+ debugDirectory,
+ win32Resources: new Win32Resources.ResourceData(inputModule),
+ Internal.ReadyToRunConstants.ReadyToRunFlags.READYTORUN_FLAG_Component);
+
+ IComparer> comparer = new SortableDependencyNode.ObjectNodeComparer(new CompilerComparer());
+ DependencyAnalyzerBase componentGraph = new DependencyAnalyzer, NodeFactory>(componentFactory, comparer);
+
+ componentGraph.AddRoot(componentFactory.Header, "Component module R2R header");
+ OwnerCompositeExecutableNode ownerExecutableNode = new OwnerCompositeExecutableNode(_nodeFactory.Target, ownerExecutableName);
+ componentGraph.AddRoot(ownerExecutableNode, "Owner composite executable name");
+ componentGraph.AddRoot(copiedCorHeader, "Copied COR header");
+ componentGraph.AddRoot(debugDirectory, "Debug directory");
+ if (componentFactory.Win32ResourcesNode != null)
+ {
+ componentGraph.AddRoot(componentFactory.Win32ResourcesNode, "Win32 resources");
+ }
+ componentGraph.ComputeMarkedNodes();
+ componentFactory.Header.Add(Internal.Runtime.ReadyToRunSectionType.OwnerCompositeExecutable, ownerExecutableNode, ownerExecutableNode);
+ ReadyToRunObjectWriter.EmitObject(outputFile, componentModule: inputModule, componentGraph.MarkedNodeList, componentFactory, generateMapFile: false);
+ }
+
public override void WriteDependencyLog(string outputFileName)
{
using (FileStream dgmlOutput = new FileStream(outputFileName, FileMode.Create))
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs
index bacab9d70ac3a1..1fc68ea130bbfd 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs
@@ -1,10 +1,11 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.IO;
+using System.Linq;
using ILCompiler.DependencyAnalysis;
using ILCompiler.DependencyAnalysis.ReadyToRun;
using ILCompiler.DependencyAnalysisFramework;
@@ -19,12 +20,12 @@ namespace ILCompiler
{
public sealed class ReadyToRunCodegenCompilationBuilder : CompilationBuilder
{
- private readonly string _inputFilePath;
- private readonly EcmaModule _inputModule;
+ private readonly IEnumerable _inputFiles;
private bool _ibcTuning;
private bool _resilient;
private bool _generateMapFile;
private int _parallelism;
+
private string _jitPath;
// These need to provide reasonable defaults so that the user can optionally skip
@@ -32,11 +33,10 @@ public sealed class ReadyToRunCodegenCompilationBuilder : CompilationBuilder
private KeyValuePair[] _ryujitOptions = Array.Empty>();
private ILProvider _ilProvider = new ReadyToRunILProvider();
- public ReadyToRunCodegenCompilationBuilder(CompilerTypeSystemContext context, CompilationModuleGroup group, string inputFilePath)
+ public ReadyToRunCodegenCompilationBuilder(CompilerTypeSystemContext context, CompilationModuleGroup group, IEnumerable inputFiles)
: base(context, group, new CoreRTNameMangler())
{
- _inputFilePath = inputFilePath;
- _inputModule = context.GetModuleFromPath(_inputFilePath);
+ _inputFiles = inputFiles;
// R2R field layout needs compilation group information
((ReadyToRunCompilerContext)context).SetCompilationGroup(group);
@@ -108,26 +108,17 @@ public ReadyToRunCodegenCompilationBuilder UseParallelism(int parallelism)
return this;
}
-
public override ICompilation ToCompilation()
{
- ModuleTokenResolver moduleTokenResolver = new ModuleTokenResolver(_compilationGroup, _context);
- SignatureContext signatureContext = new SignatureContext(_inputModule, moduleTokenResolver);
- CopiedCorHeaderNode corHeaderNode = new CopiedCorHeaderNode(_inputModule);
- AttributePresenceFilterNode attributePresenceFilterNode = null;
- DebugDirectoryNode debugDirectoryNode = new DebugDirectoryNode(_inputModule);
-
- // Core library attributes are checked FAR more often than other dlls
- // attributes, so produce a highly efficient table for determining if they are
- // present. Other assemblies *MAY* benefit from this feature, but it doesn't show
- // as useful at this time.
- if (_inputModule == _inputModule.Context.SystemModule)
- {
- attributePresenceFilterNode = new AttributePresenceFilterNode(_inputModule);
- }
+ // TODO: only copy COR headers for single-assembly build and for composite build with embedded MSIL
+ IEnumerable inputModules = _compilationGroup.CompilationModuleSet;
+ CopiedCorHeaderNode corHeaderNode = (_compilationGroup.IsCompositeBuildMode ? null : new CopiedCorHeaderNode(inputModules.First()));
+ // TODO: proper support for multiple input files
+ DebugDirectoryNode debugDirectoryNode = new DebugDirectoryNode(inputModules.First());
// Produce a ResourceData where the IBC PROFILE_DATA entry has been filtered out
- ResourceData win32Resources = new ResourceData(_inputModule, (object type, object name, ushort language) =>
+ // TODO: proper support for multiple input files
+ ResourceData win32Resources = new ResourceData(inputModules.First(), (object type, object name, ushort language) =>
{
if (!(type is string) || !(name is string))
return true;
@@ -144,23 +135,20 @@ public override ICompilation ToCompilation()
});
ReadyToRunFlags flags = ReadyToRunFlags.READYTORUN_FLAG_NonSharedPInvokeStubs;
- if (_inputModule.IsPlatformNeutral)
+ if (inputModules.All(module => module.IsPlatformNeutral))
+ {
flags |= ReadyToRunFlags.READYTORUN_FLAG_PlatformNeutralSource;
+ }
flags |= _compilationGroup.GetReadyToRunFlags();
- var header = new HeaderNode(_context.Target, flags);
-
NodeFactory factory = new NodeFactory(
_context,
_compilationGroup,
_nameMangler,
- moduleTokenResolver,
- signatureContext,
corHeaderNode,
debugDirectoryNode,
win32Resources,
- attributePresenceFilterNode,
- header);
+ flags);
IComparer> comparer = new SortableDependencyNode.ObjectNodeComparer(new CompilerComparer());
DependencyAnalyzerBase graph = CreateDependencyGraph(factory, comparer);
@@ -199,8 +187,7 @@ public override ICompilation ToCompilation()
_ilProvider,
_logger,
new DependencyAnalysis.ReadyToRun.DevirtualizationManager(_compilationGroup),
- _inputFilePath,
- new ModuleDesc[] { _inputModule },
+ _inputFiles,
_resilient,
_generateMapFile,
_parallelism);
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCompilationModuleGroupBase.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCompilationModuleGroupBase.cs
index 646bb3fcfefff3..d313f1fa3b6372 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCompilationModuleGroupBase.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCompilationModuleGroupBase.cs
@@ -1,7 +1,8 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using Internal.TypeSystem;
@@ -9,27 +10,31 @@
using Internal.TypeSystem.Interop;
using ILCompiler.DependencyAnalysis.ReadyToRun;
using Debug = System.Diagnostics.Debug;
-using System;
namespace ILCompiler
{
public abstract class ReadyToRunCompilationModuleGroupBase : CompilationModuleGroup
{
- protected readonly HashSet _compilationModuleSet;
+ protected readonly HashSet _compilationModuleSet;
private readonly HashSet _versionBubbleModuleSet;
private Dictionary _typeRefsInCompilationModuleSet;
private readonly bool _compileGenericDependenciesFromVersionBubbleModuleSet;
+ private readonly bool _isCompositeBuildMode;
private readonly ConcurrentDictionary _containsTypeLayoutCache = new ConcurrentDictionary();
private readonly ConcurrentDictionary _versionsWithTypeCache = new ConcurrentDictionary();
private readonly ConcurrentDictionary _versionsWithMethodCache = new ConcurrentDictionary();
public ReadyToRunCompilationModuleGroupBase(
TypeSystemContext context,
- IEnumerable compilationModuleSet,
+ bool isCompositeBuildMode,
+ IEnumerable compilationModuleSet,
IEnumerable versionBubbleModuleSet,
bool compileGenericDependenciesFromVersionBubbleModuleSet)
{
- _compilationModuleSet = new HashSet(compilationModuleSet);
+ _compilationModuleSet = new HashSet(compilationModuleSet);
+ _isCompositeBuildMode = isCompositeBuildMode;
+
+ Debug.Assert(_isCompositeBuildMode || _compilationModuleSet.Count == 1);
_versionBubbleModuleSet = new HashSet(versionBubbleModuleSet);
_versionBubbleModuleSet.UnionWith(_compilationModuleSet);
@@ -213,6 +218,10 @@ public sealed override bool TryGetModuleTokenForExternalType(TypeDesc type, out
return _typeRefsInCompilationModuleSet.TryGetValue(type, out token);
}
+ public sealed override bool IsCompositeBuildMode => _isCompositeBuildMode;
+
+ public sealed override IEnumerable CompilationModuleSet => _compilationModuleSet;
+
private bool ComputeTypeVersionsWithCode(TypeDesc type)
{
if (type.IsCanonicalDefinitionType(CanonicalFormKind.Any))
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCompilerContext.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCompilerContext.cs
index 869dd552f8a4ae..a5871e473ee1e9 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCompilerContext.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCompilerContext.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunHashCode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunHashCode.cs
index 5abc694cfd74ad..dce784b8b42637 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunHashCode.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunHashCode.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunLibraryRootProvider.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunLibraryRootProvider.cs
index 4adcbf615cbac6..1870e823746876 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunLibraryRootProvider.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunLibraryRootProvider.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunMetadataFieldLayoutAlgorithm.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunMetadataFieldLayoutAlgorithm.cs
index b6244393c9d6e8..5079e20cd04560 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunMetadataFieldLayoutAlgorithm.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunMetadataFieldLayoutAlgorithm.cs
@@ -810,7 +810,7 @@ protected override ComputedInstanceFieldLayout ComputeInstanceFieldLayout(Metada
/// This method decides whether the type needs aligned base offset in order to have layout resilient to
/// base class layout changes.
///
- protected override void AlignBaseOffsetIfNecessary(MetadataType type, ref LayoutInt baseOffset)
+ protected override void AlignBaseOffsetIfNecessary(MetadataType type, ref LayoutInt baseOffset, bool requiresAlign8)
{
if (type.IsValueType)
{
@@ -837,7 +837,8 @@ protected override void AlignBaseOffsetIfNecessary(MetadataType type, ref Layout
}
LayoutInt alignment = new LayoutInt(type.Context.Target.PointerSize);
- if (type.RequiresAlign8())
+
+ if (requiresAlign8)
{
alignment = new LayoutInt(8);
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunSingleAssemblyCompilationModuleGroup.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunSingleAssemblyCompilationModuleGroup.cs
index 5e38edec52ac62..f4e85d18aa270c 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunSingleAssemblyCompilationModuleGroup.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunSingleAssemblyCompilationModuleGroup.cs
@@ -1,10 +1,12 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
-using Internal.TypeSystem;
+
using Internal.ReadyToRunConstants;
+using Internal.TypeSystem;
+using Internal.TypeSystem.Ecma;
using Debug = System.Diagnostics.Debug;
@@ -16,11 +18,13 @@ public class ReadyToRunSingleAssemblyCompilationModuleGroup : ReadyToRunCompilat
private bool _profileGuidedCompileRestrictionSet;
public ReadyToRunSingleAssemblyCompilationModuleGroup(
- TypeSystemContext context,
- IEnumerable compilationModuleSet,
+ TypeSystemContext context,
+ bool isCompositeBuildMode,
+ IEnumerable compilationModuleSet,
IEnumerable versionBubbleModuleSet,
bool compileGenericDependenciesFromVersionBubbleModuleSet) :
base(context,
+ isCompositeBuildMode,
compilationModuleSet,
versionBubbleModuleSet,
compileGenericDependenciesFromVersionBubbleModuleSet)
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunTableManager.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunTableManager.cs
index 44d38a26608791..aac7899051ce11 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunTableManager.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunTableManager.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -78,27 +78,19 @@ public class ReadyToRunTableManager : MetadataManager
public ReadyToRunTableManager(CompilerTypeSystemContext typeSystemContext)
: base(typeSystemContext) {}
- public IEnumerable> GetDefinedTypes()
+ public IEnumerable> GetDefinedTypes(EcmaModule module)
{
- foreach (string inputFile in _typeSystemContext.InputFilePaths.Values)
+ foreach (TypeDefinitionHandle typeDefHandle in module.MetadataReader.TypeDefinitions)
{
- EcmaModule module = _typeSystemContext.GetModuleFromPath(inputFile);
- foreach (TypeDefinitionHandle typeDefHandle in module.MetadataReader.TypeDefinitions)
- {
- yield return new TypeInfo(module.MetadataReader, typeDefHandle);
- }
+ yield return new TypeInfo(module.MetadataReader, typeDefHandle);
}
}
- public IEnumerable> GetExportedTypes()
+ public IEnumerable> GetExportedTypes(EcmaModule module)
{
- foreach (string inputFile in _typeSystemContext.InputFilePaths.Values)
+ foreach (ExportedTypeHandle exportedTypeHandle in module.MetadataReader.ExportedTypes)
{
- EcmaModule module = _typeSystemContext.GetModuleFromPath(inputFile);
- foreach (ExportedTypeHandle exportedTypeHandle in module.MetadataReader.ExportedTypes)
- {
- yield return new TypeInfo(module.MetadataReader, exportedTypeHandle);
- }
+ yield return new TypeInfo(module.MetadataReader, exportedTypeHandle);
}
}
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/RuntimeDeterminedTypeHelper.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/RuntimeDeterminedTypeHelper.cs
index a52d7dc818ba86..fdd74ef3b6519d 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/RuntimeDeterminedTypeHelper.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/RuntimeDeterminedTypeHelper.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/SingleMethodCompilationModuleGroup.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/SingleMethodCompilationModuleGroup.cs
index cb1653ca6f1edb..11c0b2ea288d7c 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/SingleMethodCompilationModuleGroup.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/SingleMethodCompilationModuleGroup.cs
@@ -1,10 +1,11 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using Internal.ReadyToRunConstants;
using Internal.TypeSystem;
+using Internal.TypeSystem.Ecma;
namespace ILCompiler
{
@@ -18,11 +19,13 @@ public class SingleMethodCompilationModuleGroup : ReadyToRunCompilationModuleGro
public SingleMethodCompilationModuleGroup(
TypeSystemContext context,
- IEnumerable compilationModuleSet,
+ bool isCompositeBuildMode,
+ IEnumerable compilationModuleSet,
IEnumerable versionBubbleModuleSet,
bool compileGenericDependenciesFromVersionBubbleModuleSet,
MethodDesc method) :
base(context,
+ isCompositeBuildMode,
compilationModuleSet,
versionBubbleModuleSet,
compileGenericDependenciesFromVersionBubbleModuleSet)
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/SystemObjectFieldLayoutAlgorithm.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/SystemObjectFieldLayoutAlgorithm.cs
index 9a57a3170dfd2b..769ed2d09bb9b5 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/SystemObjectFieldLayoutAlgorithm.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/SystemObjectFieldLayoutAlgorithm.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/IBC/IBCProfileData.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/IBC/IBCProfileData.cs
index 7f819a07d5c761..eaf1673f94178e 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/IBC/IBCProfileData.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/IBC/IBCProfileData.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -15,10 +15,10 @@ public IBCProfileData(bool partialNGen, IEnumerable methodDat
{
foreach (MethodProfileData data in methodData)
{
- if (_methodData.ContainsKey(data.Method))
- throw new Exception("Multiple copies of data for the same method");
-
- _methodData.Add(data.Method, data);
+ if (!_methodData.ContainsKey(data.Method))
+ {
+ _methodData.Add(data.Method, data);
+ }
}
_partialNGen = partialNGen;
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/IBC/IBCProfileParser.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/IBC/IBCProfileParser.cs
index 937d732bdf7d19..f4388674941e87 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/IBC/IBCProfileParser.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/IBC/IBCProfileParser.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/IBC/MIbcProfileParser.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/IBC/MIbcProfileParser.cs
index fdb32e54bcb1e0..39b1a4ba10c942 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/IBC/MIbcProfileParser.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/IBC/MIbcProfileParser.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj
index e1bddaaf0e4a4e..65d5ccb5f460a8 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj
@@ -1,4 +1,4 @@
-
+
Library
ILCompiler.ReadyToRun
@@ -99,6 +99,7 @@
+
@@ -130,6 +131,7 @@
+
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs
index 23d43df454bd80..0b07c472f6cbda 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs
@@ -227,12 +227,6 @@ public void CompileMethod(IReadyToRunMethodCodeNode methodCodeNodeNeedingCode)
}
}
- private SignatureContext GetSignatureContext()
- {
- // TODO: this will need changing when compiling multiple input MSIL modules into a single PE executable
- return _compilation.NodeFactory.InputModuleContext;
- }
-
private bool getReadyToRunHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref CORINFO_LOOKUP_KIND pGenericLookupKind, CorInfoHelpFunc id, ref CORINFO_CONST_LOOKUP pLookup)
{
switch (id)
@@ -244,7 +238,7 @@ private bool getReadyToRunHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref
if (type.IsCanonicalSubtype(CanonicalFormKind.Any))
return false;
- pLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.CreateReadyToRunHelper(ReadyToRunHelperId.NewHelper, type, GetSignatureContext()));
+ pLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.CreateReadyToRunHelper(ReadyToRunHelperId.NewHelper, type));
}
break;
case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_NEWARR_1:
@@ -254,7 +248,7 @@ private bool getReadyToRunHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref
if (type.IsCanonicalSubtype(CanonicalFormKind.Any))
return false;
- pLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.CreateReadyToRunHelper(ReadyToRunHelperId.NewArr1, type, GetSignatureContext()));
+ pLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.CreateReadyToRunHelper(ReadyToRunHelperId.NewArr1, type));
}
break;
case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_ISINSTANCEOF:
@@ -267,7 +261,7 @@ private bool getReadyToRunHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref
if (type.IsNullable)
type = type.Instantiation[0];
- pLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.CreateReadyToRunHelper(ReadyToRunHelperId.IsInstanceOf, type, GetSignatureContext()));
+ pLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.CreateReadyToRunHelper(ReadyToRunHelperId.IsInstanceOf, type));
}
break;
case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_CHKCAST:
@@ -280,7 +274,7 @@ private bool getReadyToRunHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref
if (type.IsNullable)
type = type.Instantiation[0];
- pLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.CreateReadyToRunHelper(ReadyToRunHelperId.CastClass, type, GetSignatureContext()));
+ pLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.CreateReadyToRunHelper(ReadyToRunHelperId.CastClass, type));
}
break;
case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_STATIC_BASE:
@@ -289,7 +283,7 @@ private bool getReadyToRunHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref
if (type.IsCanonicalSubtype(CanonicalFormKind.Any))
return false;
- pLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.CreateReadyToRunHelper(ReadyToRunHelperId.CctorTrigger, type, GetSignatureContext()));
+ pLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.CreateReadyToRunHelper(ReadyToRunHelperId.CctorTrigger, type));
}
break;
case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_GENERIC_HANDLE:
@@ -313,8 +307,7 @@ private bool getReadyToRunHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref
pGenericLookupKind.runtimeLookupKind,
helperId,
helperArg,
- methodContext,
- GetSignatureContext());
+ methodContext);
pLookup = CreateConstLookupToSymbol(helper);
}
break;
@@ -337,8 +330,7 @@ private void getReadyToRunDelegateCtorHelper(ref CORINFO_RESOLVED_TOKEN pTargetM
MethodWithToken targetMethod = new MethodWithToken(HandleToObject(pTargetMethod.hMethod), HandleToModuleToken(ref pTargetMethod), constrainedType: null);
pLookup.lookupKind.needsRuntimeLookup = false;
- pLookup.constLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.DelegateCtor(
- delegateTypeDesc, targetMethod, GetSignatureContext()));
+ pLookup.constLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.DelegateCtor(delegateTypeDesc, targetMethod));
}
private ISymbolNode GetHelperFtnUncached(CorInfoHelpFunc ftnNum)
@@ -749,7 +741,7 @@ private InfoAccessType constructStringLiteral(CORINFO_MODULE_STRUCT_* module, md
EcmaMethod method = (EcmaMethod)methodIL.OwningMethod.GetTypicalMethodDefinition();
ISymbolNode stringObject = _compilation.SymbolNodeFactory.StringLiteral(
- new ModuleToken(method.Module, metaTok), GetSignatureContext());
+ new ModuleToken(method.Module, metaTok));
ppValue = (void*)ObjectToHandle(stringObject);
return InfoAccessType.IAT_PPVALUE;
}
@@ -929,6 +921,155 @@ private bool IsGenericTooDeeplyNested(Instantiation instantiation)
return IsGenericTooDeeplyNested(instantiation, 0);
}
+ private void getFieldInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_METHOD_STRUCT_* callerHandle, CORINFO_ACCESS_FLAGS flags, CORINFO_FIELD_INFO* pResult)
+ {
+#if DEBUG
+ // In debug, write some bogus data to the struct to ensure we have filled everything
+ // properly.
+ MemoryHelper.FillMemory((byte*)pResult, 0xcc, Marshal.SizeOf());
+#endif
+
+ Debug.Assert(((int)flags & ((int)CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_GET |
+ (int)CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_SET |
+ (int)CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_ADDRESS |
+ (int)CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_INIT_ARRAY)) != 0);
+
+ var field = HandleToObject(pResolvedToken.hField);
+ MethodDesc callerMethod = HandleToObject(callerHandle);
+
+ if (field.Offset.IsIndeterminate)
+ throw new RequiresRuntimeJitException(field);
+
+ CORINFO_FIELD_ACCESSOR fieldAccessor;
+ CORINFO_FIELD_FLAGS fieldFlags = (CORINFO_FIELD_FLAGS)0;
+ uint fieldOffset = (field.IsStatic && field.HasRva ? 0xBAADF00D : (uint)field.Offset.AsInt);
+
+ if (field.IsStatic)
+ {
+ fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_STATIC;
+
+ if (field.FieldType.IsValueType && field.HasGCStaticBase && !field.HasRva)
+ {
+ // statics of struct types are stored as implicitly boxed in CoreCLR i.e.
+ // we need to modify field access flags appropriately
+ fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_STATIC_IN_HEAP;
+ }
+
+ if (field.HasRva)
+ {
+ fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_UNMANAGED;
+
+ // TODO: Handle the case when the RVA is in the TLS range
+ fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_RVA_ADDRESS;
+
+ // We are not going through a helper. The constructor has to be triggered explicitly.
+ if (!IsClassPreInited(field.OwningType))
+ {
+ fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_INITCLASS;
+ }
+ }
+ else if (field.OwningType.IsCanonicalSubtype(CanonicalFormKind.Any))
+ {
+ // The JIT wants to know how to access a static field on a generic type. We need a runtime lookup.
+ fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_GENERICS_STATIC_HELPER;
+ if (field.IsThreadStatic)
+ {
+ pResult->helper = (field.HasGCStaticBase ?
+ CorInfoHelpFunc.CORINFO_HELP_GETGENERICS_GCTHREADSTATIC_BASE :
+ CorInfoHelpFunc.CORINFO_HELP_GETGENERICS_NONGCTHREADSTATIC_BASE);
+ }
+ else
+ {
+ pResult->helper = (field.HasGCStaticBase ?
+ CorInfoHelpFunc.CORINFO_HELP_GETGENERICS_GCSTATIC_BASE :
+ CorInfoHelpFunc.CORINFO_HELP_GETGENERICS_NONGCSTATIC_BASE);
+ }
+ }
+ else
+ {
+ fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER;
+ pResult->helper = CorInfoHelpFunc.CORINFO_HELP_READYTORUN_STATIC_BASE;
+
+ ReadyToRunHelperId helperId = ReadyToRunHelperId.Invalid;
+ CORINFO_FIELD_ACCESSOR intrinsicAccessor;
+ if (field.IsIntrinsic &&
+ (flags & CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_GET) != 0 &&
+ (intrinsicAccessor = getFieldIntrinsic(field)) != (CORINFO_FIELD_ACCESSOR)(-1))
+ {
+ fieldAccessor = intrinsicAccessor;
+ }
+ else if (field.IsThreadStatic)
+ {
+ if (field.HasGCStaticBase)
+ {
+ helperId = ReadyToRunHelperId.GetThreadStaticBase;
+ }
+ else
+ {
+ helperId = ReadyToRunHelperId.GetThreadNonGcStaticBase;
+ }
+ }
+ else
+ {
+ helperId = field.HasGCStaticBase ?
+ ReadyToRunHelperId.GetGCStaticBase :
+ ReadyToRunHelperId.GetNonGCStaticBase;
+
+ //
+ // Currently, we only do this optimization for regular statics, but it
+ // looks like it may be permissible to do this optimization for
+ // thread statics as well.
+ //
+ if ((flags & CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_ADDRESS) != 0 &&
+ (fieldAccessor != CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_TLS))
+ {
+ fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_SAFESTATIC_BYREF_RETURN;
+ }
+ }
+
+ if (!_compilation.NodeFactory.CompilationModuleGroup.VersionsWithType(field.OwningType) &&
+ fieldAccessor == CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER)
+ {
+ PreventRecursiveFieldInlinesOutsideVersionBubble(field, callerMethod);
+
+ // Static fields outside of the version bubble need to be accessed using the ENCODE_FIELD_ADDRESS
+ // helper in accordance with ZapInfo::getFieldInfo in CoreCLR.
+ pResult->fieldLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.FieldAddress(field));
+
+ pResult->helper = CorInfoHelpFunc.CORINFO_HELP_READYTORUN_STATIC_BASE;
+
+ fieldFlags &= ~CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_STATIC_IN_HEAP; // The dynamic helper takes care of the unboxing
+ fieldOffset = 0;
+ }
+ else
+ if (helperId != ReadyToRunHelperId.Invalid)
+ {
+ pResult->fieldLookup = CreateConstLookupToSymbol(
+ _compilation.SymbolNodeFactory.CreateReadyToRunHelper(helperId, field.OwningType)
+ );
+ }
+ }
+ }
+ else
+ {
+ fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_INSTANCE;
+ }
+
+ if (field.IsInitOnly)
+ fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_FINAL;
+
+ pResult->fieldAccessor = fieldAccessor;
+ pResult->fieldFlags = fieldFlags;
+ pResult->fieldType = getFieldType(pResolvedToken.hField, &pResult->structType, pResolvedToken.hClass);
+ pResult->accessAllowed = CorInfoIsAccessAllowedResult.CORINFO_ACCESS_ALLOWED;
+ pResult->offset = fieldOffset;
+
+ EncodeFieldBaseOffset(field, pResult, callerMethod);
+
+ // TODO: We need to implement access checks for fields and methods. See JitInterface.cpp in mrtjit
+ // and STS::AccessCheck::CanAccess.
+ }
+
private void ceeInfoGetCallInfo(
ref CORINFO_RESOLVED_TOKEN pResolvedToken,
CORINFO_RESOLVED_TOKEN* pConstrainedResolvedToken,
@@ -1308,6 +1449,8 @@ private void ceeInfoGetCallInfo(
pResult->methodFlags = getMethodAttribsInternal(methodToCall);
+ pResult->wrapperDelegateInvoke = false;
+
Get_CORINFO_SIG_INFO(methodToCall, &pResult->sig, useInstantiatingStub);
}
@@ -1422,7 +1565,7 @@ private void classMustBeLoadedBeforeCodeIsRun(CORINFO_CLASS_STRUCT_* cls)
private void classMustBeLoadedBeforeCodeIsRun(TypeDesc type)
{
- ISymbolNode node = _compilation.SymbolNodeFactory.CreateReadyToRunHelper(ReadyToRunHelperId.TypeHandle, type, GetSignatureContext());
+ ISymbolNode node = _compilation.SymbolNodeFactory.CreateReadyToRunHelper(ReadyToRunHelperId.TypeHandle, type);
((MethodWithGCInfo)_methodCodeNode).Fixups.Add(node);
}
@@ -1481,7 +1624,6 @@ private void getCallInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_RESO
pResult->codePointerOrStubLookup.constLookup = CreateConstLookupToSymbol(
_compilation.SymbolNodeFactory.InterfaceDispatchCell(
new MethodWithToken(targetMethod, HandleToModuleToken(ref pResolvedToken, targetMethod), constrainedType: null),
- GetSignatureContext(),
isUnboxingStub: false,
_compilation.NameMangler.GetMangledMethodName(MethodBeingCompiled).ToString()));
}
@@ -1519,8 +1661,7 @@ private void getCallInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_RESO
new MethodWithToken(nonUnboxingMethod, HandleToModuleToken(ref pResolvedToken, nonUnboxingMethod), constrainedType),
isUnboxingStub,
isInstantiatingStub: useInstantiatingStub,
- isPrecodeImportRequired: (flags & CORINFO_CALLINFO_FLAGS.CORINFO_CALLINFO_LDFTN) != 0,
- GetSignatureContext()));
+ isPrecodeImportRequired: (flags & CORINFO_CALLINFO_FLAGS.CORINFO_CALLINFO_LDFTN) != 0));
}
break;
@@ -1536,8 +1677,7 @@ private void getCallInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_RESO
pResult->codePointerOrStubLookup.constLookup = CreateConstLookupToSymbol(
_compilation.NodeFactory.DynamicHelperCell(
new MethodWithToken(targetMethod, HandleToModuleToken(ref pResolvedToken, targetMethod), constrainedType: null),
- useInstantiatingStub,
- GetSignatureContext()));
+ useInstantiatingStub));
Debug.Assert(!pResult->sig.hasTypeArg());
}
@@ -1564,15 +1704,13 @@ private void getCallInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_RESO
{
pResult->instParamLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.CreateReadyToRunHelper(
ReadyToRunHelperId.MethodDictionary,
- new MethodWithToken(targetMethod, HandleToModuleToken(ref pResolvedToken, targetMethod), constrainedType),
- signatureContext: GetSignatureContext()));
+ new MethodWithToken(targetMethod, HandleToModuleToken(ref pResolvedToken, targetMethod), constrainedType)));
}
else
{
pResult->instParamLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.CreateReadyToRunHelper(
ReadyToRunHelperId.TypeDictionary,
- exactType,
- signatureContext: GetSignatureContext()));
+ exactType));
}
}
}
@@ -1794,8 +1932,7 @@ private void embedGenericHandle(ref CORINFO_RESOLVED_TOKEN pResolvedToken, bool
case CorInfoGenericHandleType.CORINFO_HANDLETYPE_CLASS:
symbolNode = _compilation.SymbolNodeFactory.CreateReadyToRunHelper(
ReadyToRunHelperId.TypeHandle,
- HandleToObject(pResolvedToken.hClass),
- GetSignatureContext());
+ HandleToObject(pResolvedToken.hClass));
break;
case CorInfoGenericHandleType.CORINFO_HANDLETYPE_METHOD:
@@ -1810,16 +1947,14 @@ private void embedGenericHandle(ref CORINFO_RESOLVED_TOKEN pResolvedToken, bool
symbolNode = _compilation.SymbolNodeFactory.CreateReadyToRunHelper(
ReadyToRunHelperId.MethodHandle,
- new MethodWithToken(md, HandleToModuleToken(ref pResolvedToken), constrainedType: null),
- GetSignatureContext());
+ new MethodWithToken(md, HandleToModuleToken(ref pResolvedToken), constrainedType: null));
}
break;
case CorInfoGenericHandleType.CORINFO_HANDLETYPE_FIELD:
symbolNode = _compilation.SymbolNodeFactory.CreateReadyToRunHelper(
ReadyToRunHelperId.FieldHandle,
- HandleToObject(pResolvedToken.hField),
- GetSignatureContext());
+ HandleToObject(pResolvedToken.hField));
break;
default:
@@ -1928,7 +2063,7 @@ private void EncodeFieldBaseOffset(FieldDesc field, CORINFO_FIELD_INFO* pResult,
// ENCODE_FIELD_OFFSET
pResult->offset = 0;
pResult->fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_INSTANCE_WITH_BASE;
- pResult->fieldLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.FieldOffset(field, GetSignatureContext()));
+ pResult->fieldLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.FieldOffset(field));
}
}
else if (pMT.IsValueType)
@@ -1948,7 +2083,7 @@ private void EncodeFieldBaseOffset(FieldDesc field, CORINFO_FIELD_INFO* pResult,
// ENCODE_FIELD_OFFSET
pResult->offset = 0;
pResult->fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_INSTANCE_WITH_BASE;
- pResult->fieldLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.FieldOffset(field, GetSignatureContext()));
+ pResult->fieldLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.FieldOffset(field));
}
else
{
@@ -1957,7 +2092,7 @@ private void EncodeFieldBaseOffset(FieldDesc field, CORINFO_FIELD_INFO* pResult,
// ENCODE_FIELD_BASE_OFFSET
pResult->offset -= (uint)pMT.BaseType.InstanceByteCount.AsInt;
pResult->fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_INSTANCE_WITH_BASE;
- pResult->fieldLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.FieldBaseOffset(field.OwningType, GetSignatureContext()));
+ pResult->fieldLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.FieldBaseOffset(field.OwningType));
}
}
@@ -2054,12 +2189,12 @@ private void getAddressOfPInvokeTarget(CORINFO_METHOD_STRUCT_* method, ref CORIN
if (ecmaMethod.IsSuppressGCTransition())
{
- pLookup.addr = (void*)ObjectToHandle(_compilation.SymbolNodeFactory.GetPInvokeTargetNode(methodWithToken, GetSignatureContext()));
+ pLookup.addr = (void*)ObjectToHandle(_compilation.SymbolNodeFactory.GetPInvokeTargetNode(methodWithToken));
pLookup.accessType = InfoAccessType.IAT_PVALUE;
}
else
{
- pLookup.addr = (void*)ObjectToHandle(_compilation.SymbolNodeFactory.GetIndirectPInvokeTargetNode(methodWithToken, GetSignatureContext()));
+ pLookup.addr = (void*)ObjectToHandle(_compilation.SymbolNodeFactory.GetIndirectPInvokeTargetNode(methodWithToken));
pLookup.accessType = InfoAccessType.IAT_PPVALUE;
}
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ObjectWriter/R2RPEBuilder.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ObjectWriter/R2RPEBuilder.cs
index 5815af9deec8cc..944f8b288329bc 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ObjectWriter/R2RPEBuilder.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ObjectWriter/R2RPEBuilder.cs
@@ -96,19 +96,7 @@ public SectionRVADelta(int startRVA, int endRVA, int deltaRVA)
private TargetDetails _target;
///
- /// PE reader representing the input MSIL PE file we're copying to the output composite PE file.
- ///
- private PEReader _peReader;
-
- ///
- /// Custom sections explicitly injected by the caller.
- ///
- private HashSet _customSections;
-
- ///
- /// Complete list of section names includes the sections present in the input MSIL file
- /// (.text, optionally .rsrc and .reloc) and extra questions injected during the R2R PE
- /// creation.
+ /// Complete list of sections to emit into the output R2R executable.
///
private ImmutableArray _sections;
@@ -164,16 +152,17 @@ public SectionRVADelta(int startRVA, int endRVA, int deltaRVA)
/// Constructor initializes the various control structures and combines the section list.
///
/// Target environment specifier
- /// Input MSIL PE file reader
+ /// PE file header builder
/// Callback to retrieve the runtime functions table
public R2RPEBuilder(
TargetDetails target,
- PEReader peReader,
+ PEHeaderBuilder peHeaderBuilder,
+ ISymbolNode r2rHeaderExportSymbol,
+ string outputFileSimpleName,
Func getRuntimeFunctionsTable)
- : base(PEHeaderCopier.Copy(peReader.PEHeaders, target), deterministicIdProvider: null)
+ : base(peHeaderBuilder, deterministicIdProvider: null)
{
_target = target;
- _peReader = peReader;
_getRuntimeFunctionsTable = getRuntimeFunctionsTable;
_sectionRvaDeltas = new List();
@@ -182,10 +171,11 @@ public R2RPEBuilder(
_textSectionIndex = _sectionBuilder.AddSection(TextSectionName, SectionCharacteristics.ContainsCode | SectionCharacteristics.MemExecute | SectionCharacteristics.MemRead, 512);
_dataSectionIndex = _sectionBuilder.AddSection(DataSectionName, SectionCharacteristics.ContainsInitializedData | SectionCharacteristics.MemWrite | SectionCharacteristics.MemRead, 512);
- _customSections = new HashSet();
- foreach (SectionInfo section in _sectionBuilder.GetSections())
+ if (r2rHeaderExportSymbol != null)
{
- _customSections.Add(section.SectionName);
+ _sectionBuilder.AddSection(R2RPEBuilder.ExportDataSectionName, SectionCharacteristics.ContainsInitializedData | SectionCharacteristics.MemRead, 512);
+ _sectionBuilder.AddExportSymbol("RTR_HEADER", 1, r2rHeaderExportSymbol);
+ _sectionBuilder.SetDllNameForExportDirectoryTable(outputFileSimpleName);
}
if (_sectionBuilder.FindSection(R2RPEBuilder.RelocSectionName) == null)
@@ -196,7 +186,7 @@ public R2RPEBuilder(
SectionCharacteristics.ContainsInitializedData |
SectionCharacteristics.MemRead |
SectionCharacteristics.MemDiscardable,
- peReader.PEHeaders.PEHeader.SectionAlignment);
+ PEHeaderConstants.SectionAlignment);
}
ImmutableArray.Builder sectionListBuilder = ImmutableArray.CreateBuilder();
@@ -270,21 +260,18 @@ public int GetSymbolFilePosition(ISymbolNode symbol)
/// Emit built sections into the R2R PE file.
///
/// Output stream for the final R2R PE file
- public void Write(Stream outputStream)
+ /// Timestamp to set in the PE header of the output R2R executable
+ public void Write(Stream outputStream, int timeDateStamp)
{
BlobBuilder outputPeFile = new BlobBuilder();
Serialize(outputPeFile);
- _sectionBuilder.RelocateOutputFile(
- outputPeFile,
- _peReader.PEHeaders.PEHeader.ImageBase,
- outputStream);
+ _sectionBuilder.RelocateOutputFile(outputPeFile, Header.ImageBase, outputStream);
UpdateSectionRVAs(outputStream);
-
ApplyMachineOSOverride(outputStream);
- CopyTimeStampFromInputImage(outputStream);
+ SetPEHeaderTimeStamp(outputStream, timeDateStamp);
_written = true;
}
@@ -403,12 +390,13 @@ private void ApplyMachineOSOverride(Stream outputStream)
}
///
- /// Copy over the timestamp from IL image for determinism.
+ /// Set PE header timestamp in the output R2R image to a given value.
///
/// Output stream representing the R2R PE executable
- private void CopyTimeStampFromInputImage(Stream outputStream)
+ /// Timestamp to set in the R2R PE header
+ private void SetPEHeaderTimeStamp(Stream outputStream, int timeDateStamp)
{
- byte[] patchedTimestamp = BitConverter.GetBytes(_peReader.PEHeaders.CoffHeader.TimeDateStamp);
+ byte[] patchedTimestamp = BitConverter.GetBytes(timeDateStamp);
int seekSize =
DosHeaderSize +
PESignatureSize +
@@ -428,10 +416,13 @@ protected override PEDirectoriesBuilder GetDirectories()
_sectionBuilder.UpdateDirectories(builder);
- RuntimeFunctionsTableNode runtimeFunctionsTable = _getRuntimeFunctionsTable();
- builder.ExceptionTable = new DirectoryEntry(
- relativeVirtualAddress: _sectionBuilder.GetSymbolRVA(runtimeFunctionsTable),
- size: runtimeFunctionsTable.TableSize);
+ if (_getRuntimeFunctionsTable != null)
+ {
+ RuntimeFunctionsTableNode runtimeFunctionsTable = _getRuntimeFunctionsTable();
+ builder.ExceptionTable = new DirectoryEntry(
+ relativeVirtualAddress: _sectionBuilder.GetSymbolRVA(runtimeFunctionsTable),
+ size: runtimeFunctionsTable.TableSize);
+ }
return builder;
}
@@ -554,9 +545,11 @@ protected override BlobBuilder SerializeSection(string name, SectionLocation loc
}
///
- /// Simple helper for copying the various global values in the PE header.
+ /// Simple helper for filling in PE header information by either copying over
+ /// data from a pre-existing input PE header (used for single-assembly R2R files)
+ /// or by explicitly specifying the image characteristics (for composite R2R).
///
- static class PEHeaderCopier
+ static class PEHeaderProvider
{
///
/// Copy PE headers into a PEHeaderBuilder used by PEBuilder.
@@ -564,14 +557,34 @@ static class PEHeaderCopier
/// Headers to copy
/// Target architecture to set in the header
public static PEHeaderBuilder Copy(PEHeaders peHeaders, TargetDetails target)
+ {
+ return Create(
+ peHeaders.CoffHeader.Characteristics,
+ peHeaders.PEHeader.DllCharacteristics,
+ peHeaders.PEHeader.Subsystem,
+ target);
+ }
+
+ ///
+ /// Fill in PE header information into a PEHeaderBuilder used by PEBuilder.
+ ///
+ /// Relocs are not present in the PE executable
+ /// Extra DLL characteristics to apply
+ /// Targeting subsystem
+ /// Target architecture to set in the header
+ public static PEHeaderBuilder Create(Characteristics imageCharacteristics, DllCharacteristics dllCharacteristics, Subsystem subsystem, TargetDetails target)
{
bool is64BitTarget = target.PointerSize == sizeof(long);
- Characteristics imageCharacteristics = peHeaders.CoffHeader.Characteristics;
- if (is64BitTarget)
+ imageCharacteristics &= ~(Characteristics.Bit32Machine | Characteristics.LargeAddressAware);
+ imageCharacteristics |= (is64BitTarget ? Characteristics.LargeAddressAware : Characteristics.Bit32Machine);
+
+ ulong imageBase = PE32HeaderConstants.ImageBase;
+ if (target.IsWindows && is64BitTarget && (imageBase <= uint.MaxValue))
{
- imageCharacteristics &= ~Characteristics.Bit32Machine;
- imageCharacteristics |= Characteristics.LargeAddressAware;
+ // Base addresses below 4 GiB are reserved for WoW on x64 and disallowed on ARM64.
+ // If the input assembly was compiled for anycpu, its base address is 32-bit and we need to fix it.
+ imageBase = (imageCharacteristics & Characteristics.Dll) != 0 ? PE64HeaderConstants.DllImageBase : PE64HeaderConstants.ExeImageBase;
}
int fileAlignment = 0x200;
@@ -589,43 +602,39 @@ public static PEHeaderBuilder Copy(PEHeaders peHeaders, TargetDetails target)
sectionAlignment = fileAlignment;
}
- DllCharacteristics dllCharacteristics = DllCharacteristics.DynamicBase | DllCharacteristics.NxCompatible;
-
- if (!is64BitTarget)
- {
- dllCharacteristics |= DllCharacteristics.NoSeh;
- }
+ dllCharacteristics &= (DllCharacteristics.NxCompatible | DllCharacteristics.TerminalServerAware | DllCharacteristics.AppContainer);
- // Copy over selected DLL characteristics bits from IL image
- dllCharacteristics |= peHeaders.PEHeader.DllCharacteristics &
- (DllCharacteristics.TerminalServerAware | DllCharacteristics.AppContainer);
+ // In Crossgen1, this is under a debug-specific condition 'if (0 == CLRConfig::GetConfigValue(CLRConfig::INTERNAL_NoASLRForNgen))'
+ dllCharacteristics |= DllCharacteristics.DynamicBase;
if (is64BitTarget)
{
dllCharacteristics |= DllCharacteristics.HighEntropyVirtualAddressSpace;
}
+ else
+ {
+ dllCharacteristics |= DllCharacteristics.NoSeh;
+ }
return new PEHeaderBuilder(
machine: target.MachineFromTarget(),
sectionAlignment: sectionAlignment,
fileAlignment: fileAlignment,
- imageBase: peHeaders.PEHeader.ImageBase,
- majorLinkerVersion: 11,
- minorLinkerVersion: 0,
- majorOperatingSystemVersion: 5,
- // Win2k = 5.0 for 32-bit images, Win2003 = 5.2 for 64-bit images
- minorOperatingSystemVersion: is64BitTarget ? (ushort)2 : (ushort)0,
- majorImageVersion: peHeaders.PEHeader.MajorImageVersion,
- minorImageVersion: peHeaders.PEHeader.MinorImageVersion,
- majorSubsystemVersion: peHeaders.PEHeader.MajorSubsystemVersion,
- minorSubsystemVersion: peHeaders.PEHeader.MinorSubsystemVersion,
- subsystem: peHeaders.PEHeader.Subsystem,
+ majorLinkerVersion: PEHeaderConstants.MajorLinkerVersion,
+ minorLinkerVersion: PEHeaderConstants.MinorLinkerVersion,
+ majorOperatingSystemVersion: PEHeaderConstants.MajorOperatingSystemVersion,
+ minorOperatingSystemVersion: PEHeaderConstants.MinorOperatingSystemVersion,
+ majorImageVersion: PEHeaderConstants.MajorImageVersion,
+ minorImageVersion: PEHeaderConstants.MinorImageVersion,
+ majorSubsystemVersion: PEHeaderConstants.MajorSubsystemVersion,
+ minorSubsystemVersion: PEHeaderConstants.MinorSubsystemVersion,
+ subsystem: subsystem,
dllCharacteristics: dllCharacteristics,
imageCharacteristics: imageCharacteristics,
- sizeOfStackReserve: peHeaders.PEHeader.SizeOfStackReserve,
- sizeOfStackCommit: peHeaders.PEHeader.SizeOfStackCommit,
- sizeOfHeapReserve: 0,
- sizeOfHeapCommit: 0);
+ sizeOfStackReserve: (is64BitTarget ? PE64HeaderConstants.SizeOfStackReserve : PE32HeaderConstants.SizeOfStackReserve),
+ sizeOfStackCommit: (is64BitTarget ? PE64HeaderConstants.SizeOfStackCommit : PE32HeaderConstants.SizeOfStackCommit),
+ sizeOfHeapReserve: (is64BitTarget ? PE64HeaderConstants.SizeOfHeapReserve : PE32HeaderConstants.SizeOfHeapReserve),
+ sizeOfHeapCommit: (is64BitTarget ? PE64HeaderConstants.SizeOfHeapCommit : PE32HeaderConstants.SizeOfHeapCommit));
}
}
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ObjectWriter/RelocationHelper.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ObjectWriter/RelocationHelper.cs
index 5bff2d3374f6a5..819888a1a87c75 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ObjectWriter/RelocationHelper.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ObjectWriter/RelocationHelper.cs
@@ -193,7 +193,9 @@ public void ProcessRelocation(RelocType relocationType, int sourceRVA, int targe
case RelocType.IMAGE_REL_BASED_ARM64_PAGEBASE_REL21:
{
relocationLength = 4;
- delta = (targetRVA - sourceRVA) >> 12;
+ int sourcePageRVA = sourceRVA & ~0xfff;
+ // Page delta always fits in 21 bits as long as we use 4-byte RVAs
+ delta = ((targetRVA - sourcePageRVA) >> 12) & 0x1ffff;
break;
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ObjectWriter/SectionBuilder.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ObjectWriter/SectionBuilder.cs
index 4a8bb8dc3a1dba..904bea5ec0397c 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ObjectWriter/SectionBuilder.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ObjectWriter/SectionBuilder.cs
@@ -245,7 +245,10 @@ public class SectionBuilder
DirectoryEntry _relocationDirectoryEntry;
///
- /// Symbol representing the ready-to-run header table.
+ /// Symbol representing the ready-to-run COR (MSIL) header table.
+ /// Only present in single-file R2R executables. Composite R2R
+ /// executables don't have a COR header and locate the ReadyToRun
+ /// header directly using the well-known export symbol RTR_HEADER.
///
ISymbolNode _corHeaderSymbol;
@@ -524,11 +527,6 @@ public IEnumerable GetSections()
}
}
- if (_exportSymbols.Count != 0 && FindSection(R2RPEBuilder.ExportDataSectionName) == null)
- {
- sectionList.Add(new SectionInfo(R2RPEBuilder.ExportDataSectionName, SectionCharacteristics.ContainsInitializedData | SectionCharacteristics.MemRead));
- }
-
return sectionList;
}
diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ObjectWriter/TargetExtensions.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ObjectWriter/TargetExtensions.cs
index 5c3fce29c01b91..d4ba4683609c2e 100644
--- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ObjectWriter/TargetExtensions.cs
+++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ObjectWriter/TargetExtensions.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -22,6 +22,48 @@ public enum MachineOSOverride : ushort
NetBSD = 0x1993,
}
+ ///